diff options
-rw-r--r-- | components/script/dom/bindings/codegen/CodegenRust.py | 103 | ||||
-rw-r--r-- | components/script/dom/bindings/codegen/Configuration.py | 4 | ||||
-rw-r--r-- | components/script/dom/bindings/conversions.rs | 21 | ||||
-rw-r--r-- | components/script/dom/testbinding.rs | 24 | ||||
-rw-r--r-- | components/script/dom/webidls/TestBinding.webidl | 3 | ||||
-rw-r--r-- | tests/wpt/mozilla/meta/MANIFEST.json | 6 | ||||
-rw-r--r-- | tests/wpt/mozilla/tests/mozilla/variadic-interface.html | 11 |
7 files changed, 107 insertions, 65 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 74929661033..5ac6c455e39 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -102,29 +102,26 @@ numericTags = [ ] -class CastableObjectUnwrapper(): +def unwrapCastableObject(descriptor, source, codeOnFailure, conversionFunction): """ - A class for unwrapping an object named by the "source" argument - based on the passed-in descriptor. Stringifies to a Rust expression of + A function for unwrapping an object named by the "source" argument + based on the passed-in descriptor. Returns the string of the Rust expression of the appropriate type. codeOnFailure is the code to run if unwrapping fails. """ - def __init__(self, descriptor, source, codeOnFailure, handletype): - self.substitution = { - "source": source, - "codeOnFailure": CGIndenter(CGGeneric(codeOnFailure), 8).define(), - "handletype": handletype, - } - - def __str__(self): - return string.Template("""\ -match root_from_handle${handletype}(${source}) { + args = { + "failureCode": CGIndenter(CGGeneric(codeOnFailure), 8).define(), + "function": conversionFunction, + "source": source, + } + return """\ +match %(function)s(%(source)s) { Ok(val) => val, Err(()) => { -${codeOnFailure} +%(failureCode)s } -}""").substitute(self.substitution) +}""" % args # We'll want to insert the indent at the beginnings of lines, but we @@ -757,12 +754,13 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, return handleOptional(template, declType, handleDefaultNull("None")) - if isMember: - descriptorType = descriptor.memberType + conversionFunction = "root_from_handlevalue" + descriptorType = descriptor.returnType + if isMember == "Variadic": + conversionFunction = "native_from_handlevalue" + descriptorType = descriptor.nativeType elif isArgument: descriptorType = descriptor.argumentType - else: - descriptorType = descriptor.nativeType templateBody = "" if descriptor.interface.isConsequential(): @@ -782,8 +780,8 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, else: unwrapFailureCode = failureCode - templateBody = str( - CastableObjectUnwrapper(descriptor, "${val}", unwrapFailureCode, "value")) + templateBody = unwrapCastableObject( + descriptor, "${val}", unwrapFailureCode, conversionFunction) declType = CGGeneric(descriptorType) if type.nullable(): @@ -1187,31 +1185,26 @@ class CGArgumentConverter(CGThing): variadicConversion = { "val": string.Template("${args}.get(variadicArg)").substitute(replacer), } - innerConverter = instantiateJSToNativeConversionTemplate( - template, variadicConversion, declType, "slot") - - seqType = CGTemplatedType("Vec", declType) - - variadicConversion = string.Template( - "let mut vector: ${seqType} = Vec::with_capacity((${argc} - ${index}) as usize);\n" - "for variadicArg in ${index}..${argc} {\n" - "${inner}\n" - " vector.push(slot);\n" - "}\n" - "vector" - ).substitute({ - "index": index, - "argc": argc, - "seqType": seqType.define(), - "inner": CGIndenter(innerConverter, 4).define(), - }) + innerConverter = [instantiateJSToNativeConversionTemplate( + template, variadicConversion, declType, "slot")] - variadicConversion = CGIfElseWrapper(condition, - CGGeneric(variadicConversion), - CGGeneric("Vec::new()")).define() + arg = "arg%d" % index + vec = "Vec::with_capacity((%(argc)s - %(index)s) as usize)" % {'argc': argc, 'index': index} - self.converter = instantiateJSToNativeConversionTemplate( - variadicConversion, replacementVariables, seqType, "arg%d" % index) + if argument.type.isGeckoInterface(): + code = "let mut %s = RootedVec::new();\n*%s = %s;\n" % (arg, arg, vec) + innerConverter.append(CGGeneric("%s.push(JS::from_ref(&*slot));" % arg)) + else: + code = "let mut %s = %s;\n" % (arg, vec) + innerConverter.append(CGGeneric("%s.push(slot);" % arg)) + inner = CGIndenter(CGList(innerConverter, "\n"), 4).define() + + code += """\ +for variadicArg in %(index)s..%(argc)s { +%(inner)s +}""" % {'argc': argc, 'index': index, 'inner': inner} + + self.converter = CGGeneric(code) def define(self): return self.converter.define() @@ -1693,7 +1686,7 @@ class CGImports(CGWrapper): class CGIfWrapper(CGWrapper): - def __init__(self, child, condition): + def __init__(self, condition, child): pre = CGWrapper(CGGeneric(condition), pre="if ", post=" {\n", reindent=True) CGWrapper.__init__(self, CGIndenter(child), pre=pre.define(), @@ -1923,7 +1916,7 @@ class CGList(CGThing): class CGIfElseWrapper(CGList): def __init__(self, condition, ifTrue, ifFalse): - kids = [CGIfWrapper(ifTrue, condition), + kids = [CGIfWrapper(condition, ifTrue), CGWrapper(CGIndenter(ifFalse), pre=" else {\n", post="\n}")] CGList.__init__(self, kids) @@ -3476,7 +3469,7 @@ def getUnionTypeTemplateVars(type, descriptorProvider): if type.isGeckoInterface(): name = type.inner.identifier.name - typeName = descriptorProvider.getDescriptor(name).nativeType + typeName = descriptorProvider.getDescriptor(name).returnType elif type.isEnum(): name = type.inner.identifier.name typeName = name @@ -3629,7 +3622,7 @@ class CGUnionConversionStruct(CGThing): if hasObjectTypes: assert interfaceObject templateBody = CGList([interfaceObject], "\n") - conversions.append(CGIfWrapper(templateBody, "value.get().is_object()")) + conversions.append(CGIfWrapper("value.get().is_object()", templateBody)) otherMemberTypes = [ t for t in memberTypes if t.isPrimitive() or t.isString() or t.isEnum() @@ -4082,7 +4075,7 @@ class CGProxySpecialOperation(CGPerSignatureCall): return "" wrap = CGGeneric(wrapForType(**self.templateValues)) - wrap = CGIfWrapper(wrap, "found") + wrap = CGIfWrapper("found", wrap) return "\n" + wrap.define() @@ -5216,7 +5209,7 @@ class CGBindingRoot(CGThing): 'dom::bindings::callback::wrap_call_this_object', 'dom::bindings::conversions::{ConversionBehavior, DOM_OBJECT_SLOT, IDLInterface}', 'dom::bindings::conversions::{FromJSValConvertible, StringificationBehavior}', - 'dom::bindings::conversions::{ToJSValConvertible, jsid_to_str}', + 'dom::bindings::conversions::{ToJSValConvertible, jsid_to_str, native_from_handlevalue}', 'dom::bindings::conversions::{private_from_object, root_from_object}', 'dom::bindings::conversions::{root_from_handleobject, root_from_handlevalue}', 'dom::bindings::codegen::{PrototypeList, RegisterBindings, UnionTypes}', @@ -5231,6 +5224,7 @@ class CGBindingRoot(CGThing): 'dom::bindings::num::Finite', 'dom::bindings::str::ByteString', 'dom::bindings::str::USVString', + 'dom::bindings::trace::RootedVec', 'mem::heap_size_of_raw_self_and_children', 'libc', 'util::str::DOMString', @@ -5262,7 +5256,10 @@ def argument_type(descriptorProvider, ty, optional=False, defaultValue=None, var declType = info.declType if variadic: - declType = CGWrapper(declType, pre="Vec<", post=">") + if ty.isGeckoInterface(): + declType = CGWrapper(declType, pre="&[", post="]") + else: + declType = CGWrapper(declType, pre="Vec<", post=">") elif optional and not defaultValue: declType = CGWrapper(declType, pre="Option<", post=">") @@ -5636,8 +5633,8 @@ class CallbackMember(CGNativeMember): ).substitute({"arg": arg.identifier.name}) elif arg.optional and not arg.defaultValue: conversion = ( - CGIfWrapper(CGGeneric(conversion), - "%s.is_some()" % arg.identifier.name).define() + + CGIfWrapper("%s.is_some()" % arg.identifier.name, + CGGeneric(conversion)).define() + " else if argc == %d {\n" " // This is our current trailing argument; reduce argc\n" " argc -= 1;\n" diff --git a/components/script/dom/bindings/codegen/Configuration.py b/components/script/dom/bindings/codegen/Configuration.py index 4275d8da24c..715719aae60 100644 --- a/components/script/dom/bindings/codegen/Configuration.py +++ b/components/script/dom/bindings/codegen/Configuration.py @@ -157,14 +157,12 @@ class Descriptor(DescriptorProvider): ty = "%sBinding::%s" % (ifaceName, ifaceName) self.returnType = "Rc<%s>" % ty self.argumentType = "???" - self.memberType = "???" self.nativeType = ty else: self.needsRooting = True self.returnType = "Root<%s>" % ifaceName self.argumentType = "&%s" % ifaceName - self.memberType = "Root<%s>" % ifaceName - self.nativeType = "Root<%s>" % ifaceName + self.nativeType = "*const %s" % ifaceName self.concreteType = ifaceName self.register = desc.get('register', True) diff --git a/components/script/dom/bindings/conversions.rs b/components/script/dom/bindings/conversions.rs index d43642ee7e2..45279e7a966 100644 --- a/components/script/dom/bindings/conversions.rs +++ b/components/script/dom/bindings/conversions.rs @@ -728,6 +728,14 @@ pub unsafe fn private_from_proto_check<F>(mut obj: *mut JSObject, proto_check: F } } +fn native_from_object<T>(obj: *mut JSObject) -> Result<*const T, ()> + where T: Reflectable + IDLInterface +{ + unsafe { + private_from_proto_check(obj, T::derives).map(|ptr| ptr as *const T) + } +} + /// Get a `Root<T>` for the given DOM object, unwrapping any wrapper /// around it first, and checking if the object is of the correct type. /// @@ -737,11 +745,14 @@ pub unsafe fn private_from_proto_check<F>(mut obj: *mut JSObject, proto_check: F pub fn root_from_object<T>(obj: *mut JSObject) -> Result<Root<T>, ()> where T: Reflectable + IDLInterface { - unsafe { - private_from_proto_check(obj, T::derives).map(|ptr| { - Root::from_ref(&*(ptr as *const T)) - }) - } + native_from_object(obj).map(|ptr| unsafe { Root::from_ref(&*ptr) }) +} + +/// Get a `*const T` for a DOM object accessible from a `HandleValue`. +pub fn native_from_handlevalue<T>(v: HandleValue) -> Result<*const T, ()> + where T: Reflectable + IDLInterface +{ + native_from_object(v.get().to_object()) } /// Get a `Root<T>` for a DOM object accessible from a `HandleValue`. diff --git a/components/script/dom/testbinding.rs b/components/script/dom/testbinding.rs index e88bb70a191..df098b98aa5 100644 --- a/components/script/dom/testbinding.rs +++ b/components/script/dom/testbinding.rs @@ -6,13 +6,14 @@ use dom::bindings::codegen::Bindings::EventListenerBinding::EventListener; use dom::bindings::codegen::Bindings::FunctionBinding::Function; -use dom::bindings::codegen::Bindings::TestBindingBinding::{TestBindingMethods, TestEnum}; +use dom::bindings::codegen::Bindings::TestBindingBinding::{self, TestBindingMethods, TestEnum}; use dom::bindings::codegen::UnionTypes::{BlobOrString, EventOrString}; use dom::bindings::codegen::UnionTypes::{EventOrUSVString, HTMLElementOrLong}; +use dom::bindings::error::Fallible; use dom::bindings::global::{GlobalRef, global_root_from_reflector}; use dom::bindings::js::Root; use dom::bindings::num::Finite; -use dom::bindings::reflector::Reflector; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::bindings::str::{ByteString, USVString}; use dom::blob::Blob; use js::jsapi::{HandleValue, JSContext, JSObject}; @@ -27,6 +28,23 @@ pub struct TestBinding { reflector_: Reflector, } +impl TestBinding { + fn new_inherited() -> TestBinding { + TestBinding { + reflector_: Reflector::new(), + } + } + + pub fn new(global: GlobalRef) -> Root<TestBinding> { + reflect_dom_object(box TestBinding::new_inherited(), + global, TestBindingBinding::Wrap) + } + + pub fn Constructor(global: GlobalRef) -> Fallible<Root<TestBinding>> { + Ok(TestBinding::new(global)) + } +} + impl TestBindingMethods for TestBinding { fn BooleanAttribute(&self) -> bool { false } fn SetBooleanAttribute(&self, _: bool) {} @@ -360,7 +378,7 @@ impl TestBindingMethods for TestBinding { fn PassVariadicUsvstring(&self, _: Vec<USVString>) {} fn PassVariadicByteString(&self, _: Vec<ByteString>) {} fn PassVariadicEnum(&self, _: Vec<TestEnum>) {} - // fn PassVariadicInterface(self, _: Vec<&Blob>) {} + fn PassVariadicInterface(&self, _: &[&Blob]) {} fn PassVariadicUnion(&self, _: Vec<HTMLElementOrLong>) {} fn PassVariadicUnion2(&self, _: Vec<EventOrString>) {} fn PassVariadicUnion3(&self, _: Vec<BlobOrString>) {} diff --git a/components/script/dom/webidls/TestBinding.webidl b/components/script/dom/webidls/TestBinding.webidl index f845be7dc15..803944b75fa 100644 --- a/components/script/dom/webidls/TestBinding.webidl +++ b/components/script/dom/webidls/TestBinding.webidl @@ -68,6 +68,7 @@ dictionary TestDictionaryDefaults { object? nullableObjectValue = null; }; +[Constructor] interface TestBinding { attribute boolean booleanAttribute; attribute byte byteAttribute; @@ -340,7 +341,7 @@ interface TestBinding { void passVariadicUsvstring(USVString... args); void passVariadicByteString(ByteString... args); void passVariadicEnum(TestEnum... args); - // void passVariadicInterface(Blob... args); + void passVariadicInterface(Blob... args); void passVariadicUnion((HTMLElement or long)... args); void passVariadicUnion2((Event or DOMString)... args); void passVariadicUnion3((Blob or DOMString)... args); diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index 81eab3bdd73..117bdbf5407 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -5041,6 +5041,12 @@ "url": "/_mozilla/mozilla/union.html" } ], + "mozilla/variadic-interface.html": [ + { + "path": "mozilla/variadic-interface.html", + "url": "/_mozilla/mozilla/variadic-interface.html" + } + ], "mozilla/webgl_context_creation_error.html": [ { "path": "mozilla/webgl_context_creation_error.html", diff --git a/tests/wpt/mozilla/tests/mozilla/variadic-interface.html b/tests/wpt/mozilla/tests/mozilla/variadic-interface.html new file mode 100644 index 00000000000..bf928f8fe09 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/variadic-interface.html @@ -0,0 +1,11 @@ +<!doctype html> +<meta charset=utf-8> +<title></title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script> +test(function() { + var t = new TestBinding; + t.passVariadicInterface(new Blob, new Blob); +}, "Variadic interface arguments work."); +</script> |