diff options
Diffstat (limited to 'components/script/dom/bindings/codegen/CodegenRust.py')
-rw-r--r-- | components/script/dom/bindings/codegen/CodegenRust.py | 83 |
1 files changed, 58 insertions, 25 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 86ee03d7ddd..39e8bfa275d 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -836,6 +836,8 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, descriptorType = descriptor.nativeType elif isArgument: descriptorType = descriptor.argumentType + elif descriptor.interface.identifier.name == "WindowProxy": + conversionFunction = "windowproxy_from_handlevalue" if failureCode is None: substitutions = { @@ -2409,7 +2411,9 @@ def UnionTypes(descriptors, dictionaries, callbacks, typedefs, config): 'crate::dom::bindings::conversions::ConversionBehavior', 'crate::dom::bindings::conversions::StringificationBehavior', 'crate::dom::bindings::conversions::root_from_handlevalue', + 'crate::dom::bindings::conversions::windowproxy_from_handlevalue', 'std::ptr::NonNull', + 'std::rc::Rc', 'crate::dom::bindings::record::Record', 'crate::dom::bindings::num::Finite', 'crate::dom::bindings::root::DomRoot', @@ -2419,10 +2423,12 @@ def UnionTypes(descriptors, dictionaries, callbacks, typedefs, config): 'crate::dom::bindings::trace::RootedTraceableBox', 'crate::dom::bindings::utils::find_enum_value', 'crate::dom::types::*', + 'crate::dom::windowproxy::WindowProxy', 'crate::script_runtime::JSContext as SafeJSContext', 'js::error::throw_type_error', 'js::rust::HandleValue', 'js::jsapi::Heap', + 'js::jsapi::IsCallable', 'js::jsapi::JSContext', 'js::jsapi::JSObject', 'js::rust::MutableHandleValue', @@ -2438,9 +2444,10 @@ def UnionTypes(descriptors, dictionaries, callbacks, typedefs, config): if not t.isUnion(): continue for memberType in t.flatMemberTypes: - if memberType.isDictionary() or memberType.isEnum(): + if memberType.isDictionary() or memberType.isEnum() or memberType.isCallback(): memberModule = getModuleFromObject(memberType) - memberName = memberType.inner.identifier.name + memberName = (memberType.callback.identifier.name + if memberType.isCallback() else memberType.inner.identifier.name) imports.append("%s::%s" % (memberModule, memberName)) if memberType.isEnum(): imports.append("%s::%sValues" % (memberModule, memberName)) @@ -4380,6 +4387,9 @@ def getUnionTypeTemplateVars(type, descriptorProvider): elif is_typed_array(type): name = type.name typeName = "typedarray::Heap" + name + elif type.isCallback(): + name = type.name + typeName = name else: raise TypeError("Can't handle %s in unions yet" % type) @@ -4418,12 +4428,19 @@ class CGUnionStruct(CGThing): return False def define(self): + def getTypeWrapper(t): + if type_needs_tracing(t): + return "RootedTraceableBox" + if t.isCallback(): + return "Rc" + return "" + templateVars = map(lambda t: (getUnionTypeTemplateVars(t, self.descriptorProvider), - type_needs_tracing(t)), + getTypeWrapper(t)), self.type.flatMemberTypes) enumValues = [ - " %s(%s)," % (v["name"], "RootedTraceableBox<%s>" % v["typeName"] if trace else v["typeName"]) - for (v, trace) in templateVars + " %s(%s)," % (v["name"], "%s<%s>" % (wrapper, v["typeName"]) if wrapper else v["typeName"]) + for (v, wrapper) in templateVars ] enumConversions = [ " %s::%s(ref inner) => inner.to_jsval(cx, rval)," @@ -4506,7 +4523,8 @@ class CGUnionConversionStruct(CGThing): callbackMemberTypes = filter(lambda t: t.isCallback() or t.isCallbackInterface(), memberTypes) if len(callbackMemberTypes) > 0: assert len(callbackMemberTypes) == 1 - raise TypeError("Can't handle callbacks in unions.") + typeName = callbackMemberTypes[0].name + callbackObject = CGGeneric(get_match(typeName)) else: callbackObject = None @@ -4537,7 +4555,7 @@ class CGUnionConversionStruct(CGThing): else: mozMapObject = None - hasObjectTypes = object or interfaceObject or arrayObject or dateObject or mozMapObject + hasObjectTypes = object or interfaceObject or arrayObject or dateObject or callbackObject or mozMapObject if hasObjectTypes: # "object" is not distinguishable from other types assert not object or not (interfaceObject or arrayObject or dateObject or callbackObject or mozMapObject) @@ -4548,6 +4566,8 @@ class CGUnionConversionStruct(CGThing): templateBody.append(interfaceObject) if arrayObject: templateBody.append(arrayObject) + if callbackObject: + templateBody.append(callbackObject) if mozMapObject: templateBody.append(mozMapObject) conversions.append(CGIfWrapper("value.get().is_object()", templateBody)) @@ -4608,6 +4628,8 @@ class CGUnionConversionStruct(CGThing): actualType = templateVars["typeName"] if type_needs_tracing(t): actualType = "RootedTraceableBox<%s>" % actualType + if t.isCallback(): + actualType = "Rc<%s>" % actualType returnType = "Result<Option<%s>, ()>" % actualType jsConversion = templateVars["jsConversion"] @@ -6388,8 +6410,11 @@ class CGDictionary(CGThing): def struct(self): d = self.dictionary if d.parent: - inheritance = " pub parent: %s::%s,\n" % (self.makeModuleName(d.parent), - self.makeClassName(d.parent)) + typeName = "%s::%s" % (self.makeModuleName(d.parent), + self.makeClassName(d.parent)) + if type_needs_tracing(d.parent): + typeName = "RootedTraceableBox<%s>" % typeName + inheritance = " pub parent: %s,\n" % typeName else: inheritance = "" memberDecls = [" pub %s: %s," % @@ -6399,8 +6424,9 @@ class CGDictionary(CGThing): derive = ["JSTraceable"] mustRoot = "" if self.membersNeedTracing(): - mustRoot = "#[must_root]\n" - derive += ["Default"] + mustRoot = "#[unrooted_must_root_lint::must_root]\n" + if not self.hasRequiredFields(self.dictionary): + derive += ["Default"] return (string.Template( "#[derive(${derive})]\n" @@ -6460,16 +6486,14 @@ class CGDictionary(CGThing): selfName = self.makeClassName(d) if self.membersNeedTracing(): actualType = "RootedTraceableBox<%s>" % selfName - preInitial = "let mut dictionary = RootedTraceableBox::new(%s::default());\n" % selfName - initParent = initParent = ("dictionary.parent = %s;\n" % initParent) if initParent else "" - memberInits = CGList([memberInit(m, False) for m in self.memberInfo]) - postInitial = "" + preInitial = "let dictionary = RootedTraceableBox::new(%s {\n" % selfName + postInitial = "});\n" else: actualType = selfName preInitial = "let dictionary = %s {\n" % selfName postInitial = "};\n" - initParent = ("parent: %s,\n" % initParent) if initParent else "" - memberInits = CGList([memberInit(m, True) for m in self.memberInfo]) + initParent = ("parent: %s,\n" % initParent) if initParent else "" + memberInits = CGList([memberInit(m, True) for m in self.memberInfo]) return string.Template( "impl ${selfName} {\n" @@ -6515,15 +6539,12 @@ class CGDictionary(CGThing): "initParent": CGIndenter(CGGeneric(initParent), indentLevel=16).define(), "initMembers": CGIndenter(memberInits, indentLevel=16).define(), "insertMembers": CGIndenter(memberInserts, indentLevel=8).define(), - "preInitial": CGIndenter(CGGeneric(preInitial), indentLevel=16).define(), - "postInitial": CGIndenter(CGGeneric(postInitial), indentLevel=16).define(), + "preInitial": CGIndenter(CGGeneric(preInitial), indentLevel=8).define(), + "postInitial": CGIndenter(CGGeneric(postInitial), indentLevel=8).define(), }) def membersNeedTracing(self): - for member, _ in self.memberInfo: - if type_needs_tracing(member.type): - return True - return False + return type_needs_tracing(self.dictionary) @staticmethod def makeDictionaryName(dictionary): @@ -6923,7 +6944,8 @@ class CGCallback(CGClass): bases=[ClassBase(baseName)], constructors=self.getConstructors(), methods=realMethods, - decorators="#[derive(JSTraceable, PartialEq)]\n#[allow_unrooted_interior]") + decorators="#[derive(JSTraceable, PartialEq)]\n" + "#[unrooted_must_root_lint::allow_unrooted_interior]") def getConstructors(self): return [ClassConstructor( @@ -7386,7 +7408,16 @@ class CGIterableMethodGenerator(CGGeneric): rooted!(in(*cx) let mut call_arg2 = UndefinedValue()); let mut call_args = vec![UndefinedValue(), UndefinedValue(), ObjectValue(*_obj)]; rooted!(in(*cx) let mut ignoredReturnVal = UndefinedValue()); - for i in 0..(*this).get_iterable_length() { + + // This has to be a while loop since get_iterable_length() may change during + // the callback, and we need to avoid iterator invalidation. + // + // It is possible for this to loop infinitely, but that matches the spec + // and other browsers. + // + // https://heycam.github.io/webidl/#es-forEach + let mut i = 0; + while i < (*this).get_iterable_length() { (*this).get_value_at_index(i).to_jsval(*cx, call_arg1.handle_mut()); (*this).get_key_at_index(i).to_jsval(*cx, call_arg2.handle_mut()); call_args[0] = call_arg1.handle().get(); @@ -7396,6 +7427,8 @@ class CGIterableMethodGenerator(CGGeneric): ignoredReturnVal.handle_mut()) { return false; } + + i += 1; } let result = (); |