diff options
author | Josh Matthews <josh@joshmatthews.net> | 2017-05-26 14:27:05 -0400 |
---|---|---|
committer | Josh Matthews <josh@joshmatthews.net> | 2017-09-25 16:11:48 -0400 |
commit | f5eb8445b05d892b432d769f5e036f786e223fd4 (patch) | |
tree | 323092cd64b7bf493114aa4dbb5582b39ddad2cb /components/script/dom/bindings | |
parent | 16166d66731d7040a91ddbed6ffd05d4fc64c97b (diff) | |
download | servo-f5eb8445b05d892b432d769f5e036f786e223fd4.tar.gz servo-f5eb8445b05d892b432d769f5e036f786e223fd4.zip |
Initialize rooted dictionaries to a stable value before setting fields.
Diffstat (limited to 'components/script/dom/bindings')
-rw-r--r-- | components/script/dom/bindings/codegen/CodegenRust.py | 52 | ||||
-rw-r--r-- | components/script/dom/bindings/js.rs | 29 |
2 files changed, 58 insertions, 23 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index aa58afe1913..05db89f3766 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -1045,12 +1045,12 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, if defaultValue is None: default = None elif isinstance(defaultValue, IDLNullValue): - default = "Heap::new(NullValue())" + default = "NullValue()" elif isinstance(defaultValue, IDLUndefinedValue): - default = "Heap::new(UndefinedValue())" + default = "UndefinedValue()" else: raise TypeError("Can't handle non-null, non-undefined default value here") - return handleOptional("Heap::new(${val}.get())", declType, default) + return handleOptional("${val}.get()", declType, default) declType = CGGeneric("HandleValue") @@ -1077,8 +1077,6 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, 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 @@ -5708,6 +5706,7 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries 'dom::bindings::iterable::Iterable', 'dom::bindings::iterable::IteratorType', 'dom::bindings::js::JS', + 'dom::bindings::js::OptionalHeapSetter', 'dom::bindings::js::Root', 'dom::bindings::js::RootedReference', 'dom::bindings::namespace::NamespaceObjectClass', @@ -6064,7 +6063,7 @@ class CGDictionary(CGThing): def impl(self): d = self.dictionary if d.parent: - initParent = ("parent: {\n" + initParent = ("{\n" " match try!(%s::%s::new(cx, val)) {\n" " ConversionResult::Success(v) => v,\n" " ConversionResult::Failure(error) => {\n" @@ -6072,16 +6071,20 @@ class CGDictionary(CGThing): " return Err(());\n" " }\n" " }\n" - "},\n" % (self.makeModuleName(d.parent), - self.makeClassName(d.parent))) + "}" % (self.makeModuleName(d.parent), + self.makeClassName(d.parent))) else: initParent = "" - def memberInit(memberInfo): + def memberInit(memberInfo, isInitial): member, _ = memberInfo name = self.makeMemberName(member.identifier.name) conversion = self.getMemberConversion(memberInfo, member.type) - return CGGeneric("%s: %s,\n" % (name, conversion.define())) + if isInitial: + return CGGeneric("%s: %s,\n" % (name, conversion.define())) + if member.type.isAny() or member.type.isObject(): + return CGGeneric("dictionary.%s.set(%s);\n" % (name, conversion.define())) + return CGGeneric("dictionary.%s = %s;\n" % (name, conversion.define())) def varInsert(varName, dictionaryName): insertion = ("rooted!(in(cx) let mut %s_js = UndefinedValue());\n" @@ -6101,16 +6104,21 @@ class CGDictionary(CGThing): (name, name, varInsert(name, member.identifier.name).define())) return CGGeneric("%s\n" % insertion.define()) - memberInits = CGList([memberInit(m) for m in self.memberInfo]) memberInserts = CGList([memberInsert(m) for m in self.memberInfo]) - actualType = self.makeClassName(d) - preInitial = "" - postInitial = "" + selfName = self.makeClassName(d) if self.membersNeedTracing(): - actualType = "RootedTraceableBox<%s>" % actualType - preInitial = "RootedTraceableBox::new(" - postInitial = ")" + 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 = "" + 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]) return string.Template( "impl ${selfName} {\n" @@ -6131,10 +6139,10 @@ class CGDictionary(CGThing): " return Err(());\n" " };\n" " rooted!(in(cx) let object = object);\n" - " let dictionary = ${preInitial}${selfName} {\n" + "${preInitial}" "${initParent}" "${initMembers}" - " }${postInitial};\n" + "${postInitial}" " Ok(ConversionResult::Success(dictionary))\n" " }\n" "}\n" @@ -6154,13 +6162,13 @@ class CGDictionary(CGThing): " rval.set(ObjectOrNullValue(obj.get()))\n" " }\n" "}\n").substitute({ - "selfName": self.makeClassName(d), + "selfName": selfName, "actualType": actualType, "initParent": CGIndenter(CGGeneric(initParent), indentLevel=12).define(), "initMembers": CGIndenter(memberInits, indentLevel=12).define(), "insertMembers": CGIndenter(memberInserts, indentLevel=8).define(), - "preInitial": CGGeneric(preInitial).define(), - "postInitial": CGGeneric(postInitial).define(), + "preInitial": CGIndenter(CGGeneric(preInitial), indentLevel=12).define(), + "postInitial": CGIndenter(CGGeneric(postInitial), indentLevel=12).define(), }) def membersNeedTracing(self): diff --git a/components/script/dom/bindings/js.rs b/components/script/dom/bindings/js.rs index 976665e4850..07dc4d74778 100644 --- a/components/script/dom/bindings/js.rs +++ b/components/script/dom/bindings/js.rs @@ -31,7 +31,8 @@ use dom::bindings::trace::JSTraceable; use dom::bindings::trace::trace_reflector; use dom::node::Node; use heapsize::HeapSizeOf; -use js::jsapi::{JSObject, JSTracer}; +use js::jsapi::{JSObject, JSTracer, Heap}; +use js::rust::GCMethods; use mitochondria::OnceCell; use script_layout_interface::TrustedNodeAddress; use script_thread::STACK_ROOTS; @@ -654,3 +655,29 @@ unsafe impl<T: DomObject> JSTraceable for Root<T> { // Already traced. } } + +/// Helper trait for safer manipulations of Option<Heap<T>> values. +pub trait OptionalHeapSetter { + type Value; + /// Update this optional heap value with a new value. + fn set(&mut self, v: Option<Self::Value>); +} + +impl<T: GCMethods + Copy> OptionalHeapSetter for Option<Heap<T>> where Heap<T>: Default { + type Value = T; + fn set(&mut self, v: Option<T>) { + let v = match v { + None => { + *self = None; + return; + } + Some(v) => v, + }; + + if self.is_none() { + *self = Some(Heap::default()); + } + + self.as_ref().unwrap().set(v); + } +} |