aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py103
-rw-r--r--components/script/dom/bindings/codegen/Configuration.py4
-rw-r--r--components/script/dom/bindings/conversions.rs21
-rw-r--r--components/script/dom/testbinding.rs24
-rw-r--r--components/script/dom/webidls/TestBinding.webidl3
-rw-r--r--tests/wpt/mozilla/meta/MANIFEST.json6
-rw-r--r--tests/wpt/mozilla/tests/mozilla/variadic-interface.html11
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>