mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
Initialize rooted dictionaries to a stable value before setting fields.
This commit is contained in:
parent
16166d6673
commit
f5eb8445b0
2 changed files with 58 additions and 23 deletions
|
@ -1045,12 +1045,12 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||||
if defaultValue is None:
|
if defaultValue is None:
|
||||||
default = None
|
default = None
|
||||||
elif isinstance(defaultValue, IDLNullValue):
|
elif isinstance(defaultValue, IDLNullValue):
|
||||||
default = "Heap::new(NullValue())"
|
default = "NullValue()"
|
||||||
elif isinstance(defaultValue, IDLUndefinedValue):
|
elif isinstance(defaultValue, IDLUndefinedValue):
|
||||||
default = "Heap::new(UndefinedValue())"
|
default = "UndefinedValue()"
|
||||||
else:
|
else:
|
||||||
raise TypeError("Can't handle non-null, non-undefined default value here")
|
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")
|
declType = CGGeneric("HandleValue")
|
||||||
|
|
||||||
|
@ -1077,8 +1077,6 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||||
|
|
||||||
if isMember in ("Dictionary", "Union"):
|
if isMember in ("Dictionary", "Union"):
|
||||||
declType = CGGeneric("Heap<*mut JSObject>")
|
declType = CGGeneric("Heap<*mut JSObject>")
|
||||||
templateBody = "Heap::new(%s)" % templateBody
|
|
||||||
default = "Heap::new(%s)" % default
|
|
||||||
else:
|
else:
|
||||||
# TODO: Need to root somehow
|
# TODO: Need to root somehow
|
||||||
# https://github.com/servo/servo/issues/6382
|
# 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::Iterable',
|
||||||
'dom::bindings::iterable::IteratorType',
|
'dom::bindings::iterable::IteratorType',
|
||||||
'dom::bindings::js::JS',
|
'dom::bindings::js::JS',
|
||||||
|
'dom::bindings::js::OptionalHeapSetter',
|
||||||
'dom::bindings::js::Root',
|
'dom::bindings::js::Root',
|
||||||
'dom::bindings::js::RootedReference',
|
'dom::bindings::js::RootedReference',
|
||||||
'dom::bindings::namespace::NamespaceObjectClass',
|
'dom::bindings::namespace::NamespaceObjectClass',
|
||||||
|
@ -6064,7 +6063,7 @@ class CGDictionary(CGThing):
|
||||||
def impl(self):
|
def impl(self):
|
||||||
d = self.dictionary
|
d = self.dictionary
|
||||||
if d.parent:
|
if d.parent:
|
||||||
initParent = ("parent: {\n"
|
initParent = ("{\n"
|
||||||
" match try!(%s::%s::new(cx, val)) {\n"
|
" match try!(%s::%s::new(cx, val)) {\n"
|
||||||
" ConversionResult::Success(v) => v,\n"
|
" ConversionResult::Success(v) => v,\n"
|
||||||
" ConversionResult::Failure(error) => {\n"
|
" ConversionResult::Failure(error) => {\n"
|
||||||
|
@ -6072,16 +6071,20 @@ class CGDictionary(CGThing):
|
||||||
" return Err(());\n"
|
" return Err(());\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"},\n" % (self.makeModuleName(d.parent),
|
"}" % (self.makeModuleName(d.parent),
|
||||||
self.makeClassName(d.parent)))
|
self.makeClassName(d.parent)))
|
||||||
else:
|
else:
|
||||||
initParent = ""
|
initParent = ""
|
||||||
|
|
||||||
def memberInit(memberInfo):
|
def memberInit(memberInfo, isInitial):
|
||||||
member, _ = memberInfo
|
member, _ = memberInfo
|
||||||
name = self.makeMemberName(member.identifier.name)
|
name = self.makeMemberName(member.identifier.name)
|
||||||
conversion = self.getMemberConversion(memberInfo, member.type)
|
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):
|
def varInsert(varName, dictionaryName):
|
||||||
insertion = ("rooted!(in(cx) let mut %s_js = UndefinedValue());\n"
|
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()))
|
(name, name, varInsert(name, member.identifier.name).define()))
|
||||||
return CGGeneric("%s\n" % insertion.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])
|
memberInserts = CGList([memberInsert(m) for m in self.memberInfo])
|
||||||
|
|
||||||
actualType = self.makeClassName(d)
|
selfName = self.makeClassName(d)
|
||||||
preInitial = ""
|
|
||||||
postInitial = ""
|
|
||||||
if self.membersNeedTracing():
|
if self.membersNeedTracing():
|
||||||
actualType = "RootedTraceableBox<%s>" % actualType
|
actualType = "RootedTraceableBox<%s>" % selfName
|
||||||
preInitial = "RootedTraceableBox::new("
|
preInitial = "let mut dictionary = RootedTraceableBox::new(%s::default());\n" % selfName
|
||||||
postInitial = ")"
|
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(
|
return string.Template(
|
||||||
"impl ${selfName} {\n"
|
"impl ${selfName} {\n"
|
||||||
|
@ -6131,10 +6139,10 @@ class CGDictionary(CGThing):
|
||||||
" return Err(());\n"
|
" return Err(());\n"
|
||||||
" };\n"
|
" };\n"
|
||||||
" rooted!(in(cx) let object = object);\n"
|
" rooted!(in(cx) let object = object);\n"
|
||||||
" let dictionary = ${preInitial}${selfName} {\n"
|
"${preInitial}"
|
||||||
"${initParent}"
|
"${initParent}"
|
||||||
"${initMembers}"
|
"${initMembers}"
|
||||||
" }${postInitial};\n"
|
"${postInitial}"
|
||||||
" Ok(ConversionResult::Success(dictionary))\n"
|
" Ok(ConversionResult::Success(dictionary))\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
|
@ -6154,13 +6162,13 @@ class CGDictionary(CGThing):
|
||||||
" rval.set(ObjectOrNullValue(obj.get()))\n"
|
" rval.set(ObjectOrNullValue(obj.get()))\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n").substitute({
|
"}\n").substitute({
|
||||||
"selfName": self.makeClassName(d),
|
"selfName": selfName,
|
||||||
"actualType": actualType,
|
"actualType": actualType,
|
||||||
"initParent": CGIndenter(CGGeneric(initParent), indentLevel=12).define(),
|
"initParent": CGIndenter(CGGeneric(initParent), indentLevel=12).define(),
|
||||||
"initMembers": CGIndenter(memberInits, indentLevel=12).define(),
|
"initMembers": CGIndenter(memberInits, indentLevel=12).define(),
|
||||||
"insertMembers": CGIndenter(memberInserts, indentLevel=8).define(),
|
"insertMembers": CGIndenter(memberInserts, indentLevel=8).define(),
|
||||||
"preInitial": CGGeneric(preInitial).define(),
|
"preInitial": CGIndenter(CGGeneric(preInitial), indentLevel=12).define(),
|
||||||
"postInitial": CGGeneric(postInitial).define(),
|
"postInitial": CGIndenter(CGGeneric(postInitial), indentLevel=12).define(),
|
||||||
})
|
})
|
||||||
|
|
||||||
def membersNeedTracing(self):
|
def membersNeedTracing(self):
|
||||||
|
|
|
@ -31,7 +31,8 @@ use dom::bindings::trace::JSTraceable;
|
||||||
use dom::bindings::trace::trace_reflector;
|
use dom::bindings::trace::trace_reflector;
|
||||||
use dom::node::Node;
|
use dom::node::Node;
|
||||||
use heapsize::HeapSizeOf;
|
use heapsize::HeapSizeOf;
|
||||||
use js::jsapi::{JSObject, JSTracer};
|
use js::jsapi::{JSObject, JSTracer, Heap};
|
||||||
|
use js::rust::GCMethods;
|
||||||
use mitochondria::OnceCell;
|
use mitochondria::OnceCell;
|
||||||
use script_layout_interface::TrustedNodeAddress;
|
use script_layout_interface::TrustedNodeAddress;
|
||||||
use script_thread::STACK_ROOTS;
|
use script_thread::STACK_ROOTS;
|
||||||
|
@ -654,3 +655,29 @@ unsafe impl<T: DomObject> JSTraceable for Root<T> {
|
||||||
// Already traced.
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue