auto merge of #2244 : Ms2ger/servo/optional-rewrite, r=jdm

This moves all handling of `isOptional` (except `type.isCallback()`, which I believe @jdm is rewriting in #2204) into one place.
This commit is contained in:
bors-servo 2014-04-28 10:46:46 -04:00
commit 32bceb3ae7
3 changed files with 44 additions and 57 deletions

View file

@ -92,19 +92,18 @@ class CastableObjectUnwrapper():
codeOnFailure is the code to run if unwrapping fails. codeOnFailure is the code to run if unwrapping fails.
""" """
def __init__(self, descriptor, source, codeOnFailure, isOptional=False): def __init__(self, descriptor, source, codeOnFailure):
self.substitution = { "type" : descriptor.nativeType, self.substitution = { "type" : descriptor.nativeType,
"depth": descriptor.interface.inheritanceDepth(), "depth": descriptor.interface.inheritanceDepth(),
"prototype": "PrototypeList::id::" + descriptor.name, "prototype": "PrototypeList::id::" + descriptor.name,
"protoID" : "PrototypeList::id::" + descriptor.name + " as uint", "protoID" : "PrototypeList::id::" + descriptor.name + " as uint",
"source" : source, "source" : source,
"codeOnFailure" : CGIndenter(CGGeneric(codeOnFailure), 4).define(), "codeOnFailure" : CGIndenter(CGGeneric(codeOnFailure), 4).define()}
"unwrapped_val" : "Some(val)" if isOptional else "val"}
def __str__(self): def __str__(self):
return string.Template( return string.Template(
"""match unwrap_jsmanaged(${source}, ${prototype}, ${depth}) { """match unwrap_jsmanaged(${source}, ${prototype}, ${depth}) {
Ok(val) => ${unwrapped_val}, Ok(val) => val,
Err(()) => { Err(()) => {
${codeOnFailure} ${codeOnFailure}
} }
@ -121,10 +120,9 @@ class FailureFatalCastableObjectUnwrapper(CastableObjectUnwrapper):
""" """
As CastableObjectUnwrapper, but defaulting to throwing if unwrapping fails As CastableObjectUnwrapper, but defaulting to throwing if unwrapping fails
""" """
def __init__(self, descriptor, source, isOptional): def __init__(self, descriptor, source):
CastableObjectUnwrapper.__init__(self, descriptor, source, CastableObjectUnwrapper.__init__(self, descriptor, source,
"return 0; //XXXjdm return Throw(cx, rv);", "return 0; //XXXjdm return Throw(cx, rv);")
isOptional)
class CGThing(): class CGThing():
""" """
@ -494,6 +492,16 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
if exceptionCode is None: if exceptionCode is None:
exceptionCode = "return 0;" exceptionCode = "return 0;"
def handleOptional(template, declType, isOptional):
if isOptional:
template = "Some(%s)" % template
declType = CGWrapper(declType, pre="Option<", post=">")
initialValue = "None"
else:
initialValue = None
return (template, declType, isOptional, initialValue)
# Unfortunately, .capitalize() on a string will lowercase things inside the # Unfortunately, .capitalize() on a string will lowercase things inside the
# string, which we do not want. # string, which we do not want.
def firstCap(string): def firstCap(string):
@ -587,7 +595,7 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
templateBody = handleDefaultNull(templateBody.define(), templateBody = handleDefaultNull(templateBody.define(),
"None") "None")
return (templateBody, declType, isOptional, "None" if isOptional else None) return handleOptional(templateBody, declType, isOptional)
if type.isGeckoInterface(): if type.isGeckoInterface():
assert not isEnforceRange and not isClamp assert not isEnforceRange and not isClamp
@ -602,34 +610,32 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
template = wrapObjectTemplate(conversion, isDefinitelyObject, type, template = wrapObjectTemplate(conversion, isDefinitelyObject, type,
failureCode) failureCode)
return (template, declType, isOptional, None) return handleOptional(template, declType, isOptional)
templateBody = "" templateBody = ""
if descriptor.interface.isConsequential(): if descriptor.interface.isConsequential():
raise TypeError("Consequential interface %s being used as an " raise TypeError("Consequential interface %s being used as an "
"argument" % descriptor.interface.identifier.name) "argument" % descriptor.interface.identifier.name)
if failureCode is not None: if failureCode is not None:
templateBody = str(CastableObjectUnwrapper( templateBody = str(CastableObjectUnwrapper(
descriptor, descriptor,
"(${val}).to_object()", "(${val}).to_object()",
failureCode, failureCode))
isOptional or type.nullable()))
else: else:
templateBody = str(FailureFatalCastableObjectUnwrapper( templateBody = str(FailureFatalCastableObjectUnwrapper(
descriptor, descriptor,
"(${val}).to_object()", "(${val}).to_object()"))
isOptional or type.nullable()))
declType = CGGeneric(descriptor.nativeType)
if type.nullable():
templateBody = "Some(%s)" % templateBody
declType = CGWrapper(declType, pre="Option<", post=">")
templateBody = wrapObjectTemplate(templateBody, isDefinitelyObject, templateBody = wrapObjectTemplate(templateBody, isDefinitelyObject,
type, failureCode) type, failureCode)
declType = CGGeneric(descriptor.nativeType) return handleOptional(templateBody, declType, isOptional)
if type.nullable() or isOptional:
declType = CGWrapper(declType, pre="Option<", post=">")
return (templateBody, declType, isOptional, "None" if isOptional else None)
if type.isSpiderMonkeyInterface(): if type.isSpiderMonkeyInterface():
raise TypeError("Can't handle SpiderMonkey interface arguments yet") raise TypeError("Can't handle SpiderMonkey interface arguments yet")
@ -648,16 +654,12 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
else: else:
nullBehavior = treatAs[treatNullAs] nullBehavior = treatAs[treatNullAs]
def getConversionCode(isOptional=False): def getConversionCode():
strval = "strval"
if isOptional:
strval = "Some(%s)" % strval
conversionCode = ( conversionCode = (
"match FromJSValConvertible::from_jsval(cx, ${val}, %s) {\n" "match FromJSValConvertible::from_jsval(cx, ${val}, %s) {\n"
" Ok(strval) => %s,\n" " Ok(strval) => strval,\n"
" Err(_) => { %s },\n" " Err(_) => { %s },\n"
"}" % (nullBehavior, strval, exceptionCode)) "}" % (nullBehavior, exceptionCode))
if defaultValue is None: if defaultValue is None:
return conversionCode return conversionCode
@ -680,15 +682,10 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
return handleDefault(conversionCode, default) return handleDefault(conversionCode, default)
declType = "DOMString" declType = "DOMString"
initialValue = None
if type.nullable(): if type.nullable():
declType = "Option<%s>" % declType declType = "Option<%s>" % declType
if isOptional: return handleOptional(getConversionCode(), CGGeneric(declType), isOptional)
declType = "Option<%s>" % declType
initialValue = "None"
return (getConversionCode(isOptional), CGGeneric(declType), False, initialValue)
if type.isEnum(): if type.isEnum():
assert not isEnforceRange and not isClamp assert not isEnforceRange and not isClamp
@ -721,7 +718,7 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
(enum, (enum,
getEnumValueName(defaultValue.value)))) getEnumValueName(defaultValue.value))))
return (template, CGGeneric(enum), isOptional, None) return handleOptional(template, CGGeneric(enum), isOptional)
if type.isCallback(): if type.isCallback():
assert not isEnforceRange and not isClamp assert not isEnforceRange and not isClamp
@ -747,13 +744,8 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
assert not isEnforceRange and not isClamp assert not isEnforceRange and not isClamp
declType = CGGeneric("JSVal") declType = CGGeneric("JSVal")
value = CGGeneric("${val}") templateBody = handleDefaultNull("${val}", "NullValue()")
if isOptional: return handleOptional(templateBody, declType, isOptional)
declType = CGWrapper(declType, pre="Option<", post=">")
value = CGWrapper(value, pre="Some(", post=")")
templateBody = handleDefaultNull(value.define(), "NullValue()")
return (templateBody, declType, isOptional, "None" if isOptional else None)
if type.isObject(): if type.isObject():
raise TypeError("Can't handle object arguments yet") raise TypeError("Can't handle object arguments yet")
@ -784,7 +776,7 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
" Err(_) => return 0,\n" " Err(_) => return 0,\n"
"}" % (typeName, val)) "}" % (typeName, val))
return (template, declType, False, None) return handleOptional(template, declType, isOptional)
if type.isVoid(): if type.isVoid():
assert not isOptional assert not isOptional
@ -800,21 +792,16 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
if failureCode is None: if failureCode is None:
failureCode = 'return 0' failureCode = 'return 0'
value = "v"
declType = CGGeneric(builtinNames[type.tag()]) declType = CGGeneric(builtinNames[type.tag()])
if type.nullable(): if type.nullable():
declType = CGWrapper(declType, pre="Option<", post=">") declType = CGWrapper(declType, pre="Option<", post=">")
if isOptional:
value = "Some(%s)" % value
declType = CGWrapper(declType, pre="Option<", post=">")
#XXXjdm support conversionBehavior here #XXXjdm support conversionBehavior here
template = ( template = (
"match FromJSValConvertible::from_jsval(cx, ${val}, ()) {\n" "match FromJSValConvertible::from_jsval(cx, ${val}, ()) {\n"
" Ok(v) => %s,\n" " Ok(v) => v,\n"
" Err(_) => { %s }\n" " Err(_) => { %s }\n"
"}" % (value, exceptionCode)) "}" % exceptionCode)
if defaultValue is not None: if defaultValue is not None:
if isinstance(defaultValue, IDLNullValue): if isinstance(defaultValue, IDLNullValue):
@ -835,7 +822,7 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
CGGeneric(template), CGGeneric(template),
CGGeneric(defaultStr)).define() CGGeneric(defaultStr)).define()
return (template, declType, isOptional, "None" if isOptional else None) return handleOptional(template, declType, isOptional)
def instantiateJSToNativeConversionTemplate(templateTuple, replacements, def instantiateJSToNativeConversionTemplate(templateTuple, replacements,
argcAndIndex=None): argcAndIndex=None):

View file

@ -127,9 +127,9 @@ impl TestBinding {
pub fn PassOptionalFloat(&self, _: Option<f32>) {} pub fn PassOptionalFloat(&self, _: Option<f32>) {}
pub fn PassOptionalDouble(&self, _: Option<f64>) {} pub fn PassOptionalDouble(&self, _: Option<f64>) {}
pub fn PassOptionalString(&self, _: Option<DOMString>) {} pub fn PassOptionalString(&self, _: Option<DOMString>) {}
// pub fn PassOptionalEnum(&self, _: Option<TestEnum>) {} pub fn PassOptionalEnum(&self, _: Option<TestEnum>) {}
pub fn PassOptionalInterface(&self, _: Option<JS<Blob>>) {} pub fn PassOptionalInterface(&self, _: Option<JS<Blob>>) {}
// pub fn PassOptionalUnion(&self, _: Option<HTMLElementOrLong>) {} pub fn PassOptionalUnion(&self, _: Option<HTMLElementOrLong>) {}
pub fn PassOptionalAny(&self, _: *JSContext, _: Option<JSVal>) {} pub fn PassOptionalAny(&self, _: *JSContext, _: Option<JSVal>) {}
pub fn PassOptionalNullableBoolean(&self, _: Option<Option<bool>>) {} pub fn PassOptionalNullableBoolean(&self, _: Option<Option<bool>>) {}
@ -145,8 +145,8 @@ impl TestBinding {
pub fn PassOptionalNullableDouble(&self, _: Option<Option<f64>>) {} pub fn PassOptionalNullableDouble(&self, _: Option<Option<f64>>) {}
pub fn PassOptionalNullableString(&self, _: Option<Option<DOMString>>) {} pub fn PassOptionalNullableString(&self, _: Option<Option<DOMString>>) {}
// pub fn PassOptionalNullableEnum(&self, _: Option<Option<TestEnum>>) {} // pub fn PassOptionalNullableEnum(&self, _: Option<Option<TestEnum>>) {}
// pub fn PassOptionalNullableInterface(&self, _: Option<Option<JS<Blob>>>) {} pub fn PassOptionalNullableInterface(&self, _: Option<Option<JS<Blob>>>) {}
// pub fn PassOptionalNullableUnion(&self, _: Option<Option<HTMLElementOrLong>>) {} pub fn PassOptionalNullableUnion(&self, _: Option<Option<HTMLElementOrLong>>) {}
pub fn PassOptionalBooleanWithDefault(&self, _: bool) {} pub fn PassOptionalBooleanWithDefault(&self, _: bool) {}
pub fn PassOptionalByteWithDefault(&self, _: i8) {} pub fn PassOptionalByteWithDefault(&self, _: i8) {}

View file

@ -132,9 +132,9 @@ interface TestBinding {
void passOptionalFloat(optional float arg); void passOptionalFloat(optional float arg);
void passOptionalDouble(optional double arg); void passOptionalDouble(optional double arg);
void passOptionalString(optional DOMString arg); void passOptionalString(optional DOMString arg);
// void passOptionalEnum(optional TestEnum arg); void passOptionalEnum(optional TestEnum arg);
void passOptionalInterface(optional Blob arg); void passOptionalInterface(optional Blob arg);
// void passOptionalUnion(optional (HTMLElement or long) arg); void passOptionalUnion(optional (HTMLElement or long) arg);
void passOptionalAny(optional any arg); void passOptionalAny(optional any arg);
void passOptionalNullableBoolean(optional boolean? arg); void passOptionalNullableBoolean(optional boolean? arg);
@ -150,8 +150,8 @@ interface TestBinding {
void passOptionalNullableDouble(optional double? arg); void passOptionalNullableDouble(optional double? arg);
void passOptionalNullableString(optional DOMString? arg); void passOptionalNullableString(optional DOMString? arg);
// void passOptionalNullableEnum(optional TestEnum? arg); // void passOptionalNullableEnum(optional TestEnum? arg);
// void passOptionalNullableInterface(optional Blob? arg); void passOptionalNullableInterface(optional Blob? arg);
// void passOptionalNullableUnion(optional (HTMLElement or long)? arg); void passOptionalNullableUnion(optional (HTMLElement or long)? arg);
void passOptionalBooleanWithDefault(optional boolean arg = false); void passOptionalBooleanWithDefault(optional boolean arg = false);
void passOptionalByteWithDefault(optional byte arg = 0); void passOptionalByteWithDefault(optional byte arg = 0);