diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 2a04db77cc9..84d80124df9 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -700,10 +700,13 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, raise TypeError("Can't handle array arguments yet") if type.isSequence(): - # Use the same type that for return values - declType = getRetvalDeclarationForType(type, descriptorProvider) + innerInfo = getJSToNativeConversionInfo(type.unroll(), descriptorProvider) + declType = CGWrapper(innerInfo.declType, pre="Vec<", post=">") config = getConversionConfigForType(type, isEnforceRange, isClamp, treatNullAs) + if type.nullable(): + declType = CGWrapper(declType, pre="Option<", post=" >") + templateBody = ("match FromJSValConvertible::from_jsval(cx, ${val}, %s) {\n" " Ok(value) => value,\n" " Err(()) => { %s },\n" @@ -1221,7 +1224,7 @@ def getConversionConfigForType(type, isEnforceRange, isClamp, treatNullAs): return "StringificationBehavior::Default" else: return treatAs[treatNullAs] - if type.isInteger(): + if type.isPrimitive() and type.isInteger(): if isEnforceRange: return "ConversionBehavior::EnforceRange" elif isClamp: @@ -3571,8 +3574,8 @@ def getUnionTypeTemplateVars(type, descriptorProvider): # for getJSToNativeConversionInfo. # Also, for dictionaries we would need to handle conversion of # null/undefined to the dictionary correctly. - if type.isDictionary() or type.isSequence(): - raise TypeError("Can't handle dictionaries or sequences in unions") + if type.isDictionary(): + raise TypeError("Can't handle dictionaries in unions") if type.isGeckoInterface(): name = type.inner.identifier.name @@ -3580,7 +3583,11 @@ def getUnionTypeTemplateVars(type, descriptorProvider): elif type.isEnum(): name = type.inner.identifier.name typeName = name - elif type.isArray() or type.isSequence(): + elif type.isSequence(): + name = type.name + inner = getUnionTypeTemplateVars(type.unroll(), descriptorProvider) + typeName = "Vec<" + inner["typeName"] + ">" + elif type.isArray(): name = str(type) # XXXjdm dunno about typeName here typeName = "/*" + type.name + "*/" @@ -3664,22 +3671,22 @@ class CGUnionConversionStruct(CGThing): names = [] conversions = [] + def get_name(memberType): + if self.type.isGeckoInterface(): + return memberType.inner.identifier.name + + return memberType.name + + def get_match(name): + return ( + "match %s::TryConvertTo%s(cx, value) {\n" + " Err(_) => return Err(()),\n" + " Ok(Some(value)) => return Ok(%s::e%s(value)),\n" + " Ok(None) => (),\n" + "}\n") % (self.type, name, self.type, name) + interfaceMemberTypes = filter(lambda t: t.isNonCallbackInterface(), memberTypes) if len(interfaceMemberTypes) > 0: - def get_name(memberType): - if self.type.isGeckoInterface(): - return memberType.inner.identifier.name - - return memberType.name - - def get_match(name): - return ( - "match %s::TryConvertTo%s(cx, value) {\n" - " Err(_) => return Err(()),\n" - " Ok(Some(value)) => return Ok(%s::e%s(value)),\n" - " Ok(None) => (),\n" - "}\n") % (self.type, name, self.type, name) - typeNames = [get_name(memberType) for memberType in interfaceMemberTypes] interfaceObject = CGList(CGGeneric(get_match(typeName)) for typeName in typeNames) names.extend(typeNames) @@ -3689,7 +3696,9 @@ class CGUnionConversionStruct(CGThing): arrayObjectMemberTypes = filter(lambda t: t.isArray() or t.isSequence(), memberTypes) if len(arrayObjectMemberTypes) > 0: assert len(arrayObjectMemberTypes) == 1 - raise TypeError("Can't handle arrays or sequences in unions.") + typeName = arrayObjectMemberTypes[0].name + arrayObject = CGGeneric(get_match(typeName)) + names.append(typeName) else: arrayObject = None @@ -3727,8 +3736,12 @@ class CGUnionConversionStruct(CGThing): hasObjectTypes = interfaceObject or arrayObject or dateObject or nonPlatformObject or object if hasObjectTypes: - assert interfaceObject - templateBody = CGList([interfaceObject], "\n") + assert interfaceObject or arrayObject + templateBody = CGList([], "\n") + if interfaceObject: + templateBody.append(interfaceObject) + if arrayObject: + templateBody.append(arrayObject) conversions.append(CGIfWrapper("value.get().is_object()", templateBody)) otherMemberTypes = [ diff --git a/components/script/dom/bindings/conversions.rs b/components/script/dom/bindings/conversions.rs index 1509276db31..0ddee79814b 100644 --- a/components/script/dom/bindings/conversions.rs +++ b/components/script/dom/bindings/conversions.rs @@ -94,6 +94,17 @@ impl> FromJSValConvertible for Finite } } +impl FromJSValConvertible for Root { + type Config = (); + + unsafe fn from_jsval(_cx: *mut JSContext, + value: HandleValue, + _config: Self::Config) + -> Result, ()> { + root_from_handlevalue(value) + } +} + /// Convert the given `jsid` to a `DOMString`. Fails if the `jsid` is not a /// string, or if the string does not contain valid UTF-16. pub fn jsid_to_str(cx: *mut JSContext, id: HandleId) -> DOMString { diff --git a/components/script/dom/testbinding.rs b/components/script/dom/testbinding.rs index 687d68a5eb9..31fa20f0409 100644 --- a/components/script/dom/testbinding.rs +++ b/components/script/dom/testbinding.rs @@ -7,8 +7,10 @@ use dom::bindings::codegen::Bindings::EventListenerBinding::EventListener; use dom::bindings::codegen::Bindings::FunctionBinding::Function; use dom::bindings::codegen::Bindings::TestBindingBinding::{self, TestBindingMethods, TestEnum}; +use dom::bindings::codegen::UnionTypes::{BlobOrBlobSequence}; use dom::bindings::codegen::UnionTypes::{BlobOrString, EventOrString}; use dom::bindings::codegen::UnionTypes::{EventOrUSVString, HTMLElementOrLong}; +use dom::bindings::codegen::UnionTypes::{StringOrLongSequence, StringOrStringSequence}; use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; @@ -188,7 +190,13 @@ impl TestBindingMethods for TestBinding { fn ReceiveObject(&self, _: *mut JSContext) -> *mut JSObject { panic!() } fn ReceiveUnion(&self) -> HTMLElementOrLong { HTMLElementOrLong::eLong(0) } fn ReceiveUnion2(&self) -> EventOrString { EventOrString::eString(DOMString::new()) } + fn ReceiveUnion3(&self) -> StringOrLongSequence { StringOrLongSequence::eLongSequence(vec![]) } + fn ReceiveUnion4(&self) -> StringOrStringSequence { StringOrStringSequence::eStringSequence(vec![]) } + fn ReceiveUnion5(&self) -> BlobOrBlobSequence { BlobOrBlobSequence::eBlobSequence(vec![]) } fn ReceiveSequence(&self) -> Vec { vec![1] } + fn ReceiveInterfaceSequence(&self) -> Vec> { + vec![Blob::new(self.global().r(), Vec::new(), "")] + } fn ReceiveNullableBoolean(&self) -> Option { Some(false) } fn ReceiveNullableByte(&self) -> Option { Some(0) } @@ -217,6 +225,9 @@ impl TestBindingMethods for TestBinding { fn ReceiveNullableUnion2(&self) -> Option { Some(EventOrString::eString(DOMString::new())) } + fn ReceiveNullableUnion3(&self) -> Option { + Some(StringOrLongSequence::eString(DOMString::new())) + } fn ReceiveNullableSequence(&self) -> Option> { Some(vec![1]) } fn PassBoolean(&self, _: bool) {} @@ -240,12 +251,14 @@ impl TestBindingMethods for TestBinding { fn PassUnion(&self, _: HTMLElementOrLong) {} fn PassUnion2(&self, _: EventOrString) {} fn PassUnion3(&self, _: BlobOrString) {} + fn PassUnion4(&self, _: StringOrStringSequence) {} fn PassAny(&self, _: *mut JSContext, _: HandleValue) {} fn PassObject(&self, _: *mut JSContext, _: *mut JSObject) {} fn PassCallbackFunction(&self, _: Rc) {} fn PassCallbackInterface(&self, _: Rc) {} fn PassSequence(&self, _: Vec) {} fn PassStringSequence(&self, _: Vec) {} + fn PassInterfaceSequence(&self, _: Vec>) {} fn PassNullableBoolean(&self, _: Option) {} fn PassNullableByte(&self, _: Option) {} diff --git a/components/script/dom/webidls/TestBinding.webidl b/components/script/dom/webidls/TestBinding.webidl index 7934182621e..65ab4cf886c 100644 --- a/components/script/dom/webidls/TestBinding.webidl +++ b/components/script/dom/webidls/TestBinding.webidl @@ -149,7 +149,11 @@ interface TestBinding { object receiveObject(); (HTMLElement or long) receiveUnion(); (Event or DOMString) receiveUnion2(); + (DOMString or sequence) receiveUnion3(); + (DOMString or sequence) receiveUnion4(); + (Blob or sequence) receiveUnion5(); sequence receiveSequence(); + sequence receiveInterfaceSequence(); byte? receiveNullableByte(); boolean? receiveNullableBoolean(); @@ -172,6 +176,7 @@ interface TestBinding { object? receiveNullableObject(); (HTMLElement or long)? receiveNullableUnion(); (Event or DOMString)? receiveNullableUnion2(); + (DOMString or sequence)? receiveNullableUnion3(); sequence? receiveNullableSequence(); void passBoolean(boolean arg); @@ -195,12 +200,14 @@ interface TestBinding { void passUnion((HTMLElement or long) arg); void passUnion2((Event or DOMString) data); void passUnion3((Blob or DOMString) data); + void passUnion4((DOMString or sequence) seq); void passAny(any arg); void passObject(object arg); void passCallbackFunction(Function fun); void passCallbackInterface(EventListener listener); void passSequence(sequence seq); void passStringSequence(sequence seq); + void passInterfaceSequence(sequence seq); void passNullableBoolean(boolean? arg); void passNullableByte(byte? arg);