From 7d24cd7752f8b4c030525612fb0fc3496d5fa169 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 14 Feb 2017 13:41:06 +0100 Subject: Pass isMember to getJSToNativeConversionInfo for unions. Also includes a documentation update for isMember. --- components/script/dom/bindings/codegen/CodegenRust.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'components/script/dom/bindings/codegen/CodegenRust.py') diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index b1f188a7b45..bd8232b2a75 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -581,11 +581,9 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, If isDefinitelyObject is True, that means we know the value isObject() and we have no need to recheck that. - if isMember is True, we're being converted from a property of some - JS object, not from an actual method argument, so we can't rely on - our jsval being rooted or outliving us in any way. Any caller - passing true needs to ensure that it is handled correctly in - typeIsSequenceOrHasSequenceMember. + isMember is `False`, "Dictionary", "Union" or "Variadic", and affects + whether this function returns code suitable for an on-stack rooted binding + or suitable for storing in an appropriate larger structure. invalidEnumValueFatal controls whether an invalid enum value conversion attempt will throw (if true) or simply return without doing anything (if @@ -4059,7 +4057,8 @@ def getUnionTypeTemplateVars(type, descriptorProvider): info = getJSToNativeConversionInfo( type, descriptorProvider, failureCode="return Ok(None);", exceptionCode='return Err(());', - isDefinitelyObject=True) + isDefinitelyObject=True, + isMember="Union") template = info.template jsConversion = string.Template(template).substitute({ -- cgit v1.2.3 From 5eaa19bdd4ae221b2db7b547d6dfae0003511735 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 14 Feb 2017 13:59:07 +0100 Subject: Share a little less code between the branches for conversion to any. --- .../script/dom/bindings/codegen/CodegenRust.py | 23 +++++++++++----------- 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'components/script/dom/bindings/codegen/CodegenRust.py') diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index bd8232b2a75..37cab821d92 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -1032,8 +1032,6 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, if type.isAny(): assert not isEnforceRange and not isClamp - declType = "" - default = "" if isMember == "Dictionary": # TODO: Need to properly root dictionaries # https://github.com/servo/servo/issues/6381 @@ -1047,17 +1045,18 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, default = "UndefinedValue()" else: raise TypeError("Can't handle non-null, non-undefined default value here") - else: - declType = CGGeneric("HandleValue") + return handleOptional("${val}", declType, default) - if defaultValue is None: - default = None - elif isinstance(defaultValue, IDLNullValue): - default = "HandleValue::null()" - elif isinstance(defaultValue, IDLUndefinedValue): - default = "HandleValue::undefined()" - else: - raise TypeError("Can't handle non-null, non-undefined default value here") + declType = CGGeneric("HandleValue") + + if defaultValue is None: + default = None + elif isinstance(defaultValue, IDLNullValue): + default = "HandleValue::null()" + elif isinstance(defaultValue, IDLUndefinedValue): + default = "HandleValue::undefined()" + else: + raise TypeError("Can't handle non-null, non-undefined default value here") return handleOptional("${val}", declType, default) -- cgit v1.2.3 From 8ce9ca624367c8e5737b8673548b230b69f4558b Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 14 Feb 2017 14:32:49 +0100 Subject: Use Heap for dictionary and union members. --- .../script/dom/bindings/codegen/CodegenRust.py | 29 ++++++++++++++-------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'components/script/dom/bindings/codegen/CodegenRust.py') diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 37cab821d92..c47cf185bf2 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -1031,21 +1031,22 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, if type.isAny(): assert not isEnforceRange and not isClamp + assert isMember != "Union" if isMember == "Dictionary": # TODO: Need to properly root dictionaries # https://github.com/servo/servo/issues/6381 - declType = CGGeneric("JSVal") + declType = CGGeneric("Heap") if defaultValue is None: default = None elif isinstance(defaultValue, IDLNullValue): - default = "NullValue()" + default = "Heap::new(NullValue())" elif isinstance(defaultValue, IDLUndefinedValue): - default = "UndefinedValue()" + default = "Heap::new(UndefinedValue())" else: raise TypeError("Can't handle non-null, non-undefined default value here") - return handleOptional("${val}", declType, default) + return handleOptional("Heap::new(${val}.get())", declType, default) declType = CGGeneric("HandleValue") @@ -1065,13 +1066,22 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, # TODO: Need to root somehow # https://github.com/servo/servo/issues/6382 - declType = CGGeneric("*mut JSObject") + default = "ptr::null_mut()" templateBody = wrapObjectTemplate("${val}.get().to_object()", - "ptr::null_mut()", + default, isDefinitelyObject, type, failureCode) + if isMember in ("Dictionary", "Union"): + declType = CGGeneric("Heap<*mut JSObject>") + templateBody = "Heap::new(%s)" % templateBody + default = "Heap::new(%s)" % default + else: + # TODO: Need to root somehow + # https://github.com/servo/servo/issues/6382 + declType = CGGeneric("*mut JSObject") + return handleOptional(templateBody, declType, - handleDefaultNull("ptr::null_mut()")) + handleDefaultNull(default)) if type.isDictionary(): # There are no nullable dictionaries @@ -2230,6 +2240,7 @@ def UnionTypes(descriptors, dictionaries, callbacks, typedefs, config): 'dom::types::*', 'js::error::throw_type_error', 'js::jsapi::HandleValue', + 'js::jsapi::Heap', 'js::jsapi::JSContext', 'js::jsapi::JSObject', 'js::jsapi::MutableHandleValue', @@ -4049,7 +4060,7 @@ def getUnionTypeTemplateVars(type, descriptorProvider): typeName = builtinNames[type.tag()] elif type.isObject(): name = type.name - typeName = "*mut JSObject" + typeName = "Heap<*mut JSObject>" else: raise TypeError("Can't handle %s in unions yet" % type) @@ -5993,8 +6004,6 @@ class CGDictionary(CGThing): default = info.default replacements = {"val": "rval.handle()"} conversion = string.Template(templateBody).substitute(replacements) - if memberType.isAny(): - conversion = "%s.get()" % conversion assert (member.defaultValue is None) == (default is None) if not member.optional: -- cgit v1.2.3 From 3613e8f231a06142abb726a28bcd8847e768708c Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 14 Feb 2017 14:42:35 +0100 Subject: Implement JSTraceable for more types. --- components/script/dom/bindings/codegen/CodegenRust.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'components/script/dom/bindings/codegen/CodegenRust.py') diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index c47cf185bf2..444d52d3ae6 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -4103,6 +4103,7 @@ class CGUnionStruct(CGThing): % (self.type, v["name"]) for v in templateVars ] return ("""\ +#[derive(JSTraceable)] pub enum %s { %s } @@ -5881,6 +5882,7 @@ class CGDictionary(CGThing): for m in self.memberInfo] return (string.Template( + "#[derive(JSTraceable)]\n" "pub struct ${selfName} {\n" + "${inheritance}" + "\n".join(memberDecls) + "\n" + -- cgit v1.2.3 From 8c8eb41cdf56feb3b03d3b47cf0a13024a2690d9 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 14 Feb 2017 16:45:32 +0100 Subject: Use from_jsval for dictionaries. --- components/script/dom/bindings/codegen/CodegenRust.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'components/script/dom/bindings/codegen/CodegenRust.py') diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 444d52d3ae6..2d188d41104 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -1090,13 +1090,13 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, typeName = "%s::%s" % (CGDictionary.makeModuleName(type.inner), CGDictionary.makeDictionaryName(type.inner)) declType = CGGeneric(typeName) - template = ("match %s::new(cx, ${val}) {\n" + template = ("match FromJSValConvertible::from_jsval(cx, ${val}, ()) {\n" " Ok(ConversionResult::Success(dictionary)) => dictionary,\n" " Ok(ConversionResult::Failure(error)) => {\n" "%s\n" " }\n" " _ => { %s },\n" - "}" % (typeName, indent(failOrPropagate, 8), exceptionCode)) + "}" % (indent(failOrPropagate, 8), exceptionCode)) return handleOptional(template, declType, handleDefaultNull("%s::empty(cx)" % typeName)) -- cgit v1.2.3 From f7e2f0e641967ba78a0b6b057aec760f9a9ca519 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 14 Feb 2017 16:45:36 +0100 Subject: Use RootedTraceableBox for dictionaries. --- .../script/dom/bindings/codegen/CodegenRust.py | 53 ++++++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) (limited to 'components/script/dom/bindings/codegen/CodegenRust.py') diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 2d188d41104..e4448ff834c 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -19,6 +19,7 @@ from WebIDL import ( IDLBuiltinType, IDLNullValue, IDLNullableType, + IDLObject, IDLType, IDLInterfaceMember, IDLUndefinedValue, @@ -1090,6 +1091,12 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, typeName = "%s::%s" % (CGDictionary.makeModuleName(type.inner), CGDictionary.makeDictionaryName(type.inner)) declType = CGGeneric(typeName) + empty = "%s::empty(cx)" % typeName + + if isMember != "Dictionary" and type_needs_tracing(type): + declType = CGTemplatedType("RootedTraceableBox", declType) + empty = "RootedTraceableBox::new(%s)" % empty + template = ("match FromJSValConvertible::from_jsval(cx, ${val}, ()) {\n" " Ok(ConversionResult::Success(dictionary)) => dictionary,\n" " Ok(ConversionResult::Failure(error)) => {\n" @@ -1098,7 +1105,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, " _ => { %s },\n" "}" % (indent(failOrPropagate, 8), exceptionCode)) - return handleOptional(template, declType, handleDefaultNull("%s::empty(cx)" % typeName)) + return handleOptional(template, declType, handleDefaultNull(empty)) if type.isVoid(): # This one only happens for return values, and its easy: Just @@ -3147,7 +3154,7 @@ class CGCallGenerator(CGThing): args = CGList([CGGeneric(arg) for arg in argsPre], ", ") for (a, name) in arguments: # XXXjdm Perhaps we should pass all nontrivial types by borrowed pointer - if a.type.isDictionary(): + if a.type.isDictionary() and not type_needs_tracing(a.type): name = "&" + name args.append(CGGeneric(name)) @@ -5577,6 +5584,7 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries 'dom::bindings::utils::trace_global', 'dom::bindings::trace::JSTraceable', 'dom::bindings::trace::RootedTraceable', + 'dom::bindings::trace::RootedTraceableBox', 'dom::bindings::callback::CallSetup', 'dom::bindings::callback::CallbackContainer', 'dom::bindings::callback::CallbackInterface', @@ -6163,6 +6171,45 @@ class CGBindingRoot(CGThing): return stripTrailingWhitespace(self.root.define()) +def type_needs_tracing(t): + assert isinstance(t, IDLObject), (t, type(t)) + + if t.isType(): + if isinstance(t, IDLWrapperType): + return type_needs_tracing(t.inner) + + if t.nullable(): + return type_needs_tracing(t.inner) + + if t.isAny(): + return True + + if t.isObject(): + return True + + if t.isSequence(): + return type_needs_tracing(t.inner) + + return False + + if t.isDictionary(): + if t.parent and type_needs_tracing(t.parent): + return True + + if any(type_needs_tracing(member.type) for member in t.members): + return True + + return False + + if t.isInterface(): + return False + + if t.isEnum(): + return False + + assert False, (t, type(t)) + + def argument_type(descriptorProvider, ty, optional=False, defaultValue=None, variadic=False): info = getJSToNativeConversionInfo( ty, descriptorProvider, isArgument=True) @@ -6176,7 +6223,7 @@ def argument_type(descriptorProvider, ty, optional=False, defaultValue=None, var elif optional and not defaultValue: declType = CGWrapper(declType, pre="Option<", post=">") - if ty.isDictionary(): + if ty.isDictionary() and not type_needs_tracing(ty): declType = CGWrapper(declType, pre="&") return declType.define() -- cgit v1.2.3