aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/codegen/CodegenRust.py
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/bindings/codegen/CodegenRust.py')
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py148
1 files changed, 108 insertions, 40 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py
index 9a98848108b..68ab0a33c18 100644
--- a/components/script/dom/bindings/codegen/CodegenRust.py
+++ b/components/script/dom/bindings/codegen/CodegenRust.py
@@ -723,9 +723,6 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
if type.nullable():
declType = CGWrapper(declType, pre="Option<", post=" >")
- if isMember != "Dictionary" and type_needs_tracing(type):
- declType = CGTemplatedType("RootedTraceableBox", declType)
-
templateBody = ("match FromJSValConvertible::from_jsval(cx, ${val}, ()) {\n"
" Ok(ConversionResult::Success(value)) => value,\n"
" Ok(ConversionResult::Failure(error)) => {\n"
@@ -1048,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")
@@ -1080,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
@@ -1099,9 +1094,8 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
declType = CGGeneric(typeName)
empty = "%s::empty(cx)" % typeName
- if isMember != "Dictionary" and type_needs_tracing(type):
+ if 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"
@@ -1427,6 +1421,8 @@ def getRetvalDeclarationForType(returnType, descriptorProvider):
nullable = returnType.nullable()
dictName = returnType.inner.name if nullable else returnType.name
result = CGGeneric(dictName)
+ if type_needs_tracing(returnType):
+ result = CGWrapper(result, pre="RootedTraceableBox<", post=">")
if nullable:
result = CGWrapper(result, pre="Option<", post=">")
return result
@@ -2262,6 +2258,7 @@ def UnionTypes(descriptors, dictionaries, callbacks, typedefs, config):
'dom::bindings::str::ByteString',
'dom::bindings::str::DOMString',
'dom::bindings::str::USVString',
+ 'dom::bindings::trace::RootedTraceableBox',
'dom::types::*',
'js::error::throw_type_error',
'js::jsapi::HandleValue',
@@ -4014,27 +4011,36 @@ pub enum %s {
pairs = ",\n ".join(['("%s", super::%s::%s)' % (val, ident, getEnumValueName(val)) for val in enum.values()])
- inner = """\
+ inner = string.Template("""\
use dom::bindings::conversions::ToJSValConvertible;
use js::jsapi::{JSContext, MutableHandleValue};
use js::jsval::JSVal;
-pub const pairs: &'static [(&'static str, super::%s)] = &[
- %s,
+pub const pairs: &'static [(&'static str, super::${ident})] = &[
+ ${pairs},
];
-impl super::%s {
+impl super::${ident} {
pub fn as_str(&self) -> &'static str {
pairs[*self as usize].0
}
}
-impl ToJSValConvertible for super::%s {
+impl Default for super::${ident} {
+ fn default() -> super::${ident} {
+ pairs[0].1
+ }
+}
+
+impl ToJSValConvertible for super::${ident} {
unsafe fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
pairs[*self as usize].0.to_jsval(cx, rval);
}
}
- """ % (ident, pairs, ident, ident)
+ """).substitute({
+ 'ident': ident,
+ 'pairs': pairs
+ })
self.cgRoot = CGList([
CGGeneric(decl),
CGNamespace.build([ident + "Values"],
@@ -4132,15 +4138,23 @@ class CGUnionStruct(CGThing):
self.type = type
self.descriptorProvider = descriptorProvider
+ def membersNeedTracing(self):
+ for t in self.type.flatMemberTypes:
+ if type_needs_tracing(t):
+ return True
+ return False
+
def define(self):
- templateVars = map(lambda t: getUnionTypeTemplateVars(t, self.descriptorProvider),
+ templateVars = map(lambda t: (getUnionTypeTemplateVars(t, self.descriptorProvider),
+ type_needs_tracing(t)),
self.type.flatMemberTypes)
enumValues = [
- " %s(%s)," % (v["name"], v["typeName"]) for v in templateVars
+ " %s(%s)," % (v["name"], "RootedTraceableBox<%s>" % v["typeName"] if trace else v["typeName"])
+ for (v, trace) in templateVars
]
enumConversions = [
" %s::%s(ref inner) => inner.to_jsval(cx, rval),"
- % (self.type, v["name"]) for v in templateVars
+ % (self.type, v["name"]) for (v, _) in templateVars
]
return ("""\
#[derive(JSTraceable)]
@@ -4167,6 +4181,12 @@ class CGUnionConversionStruct(CGThing):
self.type = type
self.descriptorProvider = descriptorProvider
+ def membersNeedTracing(self):
+ for t in self.type.flatMemberTypes:
+ if type_needs_tracing(t):
+ return True
+ return False
+
def from_jsval(self):
memberTypes = self.type.flatMemberTypes
names = []
@@ -4310,13 +4330,20 @@ class CGUnionConversionStruct(CGThing):
def try_method(self, t):
templateVars = getUnionTypeTemplateVars(t, self.descriptorProvider)
- returnType = "Result<Option<%s>, ()>" % templateVars["typeName"]
+ actualType = templateVars["typeName"]
+ if type_needs_tracing(t):
+ actualType = "RootedTraceableBox<%s>" % actualType
+ returnType = "Result<Option<%s>, ()>" % actualType
jsConversion = templateVars["jsConversion"]
+ # Any code to convert to Object is unused, since we're already converting
+ # from an Object value.
+ if t.name == 'Object':
+ return CGGeneric('')
+
return CGWrapper(
CGIndenter(jsConversion, 4),
- # TryConvertToObject is unused, but not generating it while generating others is tricky.
- pre="#[allow(dead_code)] unsafe fn TryConvertTo%s(cx: *mut JSContext, value: HandleValue) -> %s {\n"
+ pre="unsafe fn TryConvertTo%s(cx: *mut JSContext, value: HandleValue) -> %s {\n"
% (t.name, returnType),
post="\n}")
@@ -5682,6 +5709,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',
@@ -6018,18 +6046,27 @@ class CGDictionary(CGThing):
(self.makeMemberName(m[0].identifier.name), self.getMemberType(m))
for m in self.memberInfo]
+ derive = ["JSTraceable"]
+ mustRoot = ""
+ if self.membersNeedTracing():
+ mustRoot = "#[must_root]\n"
+ derive += ["Default"]
+
return (string.Template(
- "#[derive(JSTraceable)]\n"
+ "#[derive(${derive})]\n"
+ "${mustRoot}" +
"pub struct ${selfName} {\n" +
"${inheritance}" +
"\n".join(memberDecls) + "\n" +
"}").substitute({"selfName": self.makeClassName(d),
- "inheritance": inheritance}))
+ "inheritance": inheritance,
+ "mustRoot": mustRoot,
+ "derive": ', '.join(derive)}))
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"
@@ -6037,16 +6074,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"
@@ -6066,19 +6107,32 @@ 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])
+ 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 = ""
+ 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"
- " pub unsafe fn empty(cx: *mut JSContext) -> ${selfName} {\n"
+ " pub unsafe fn empty(cx: *mut JSContext) -> ${actualType} {\n"
" match ${selfName}::new(cx, HandleValue::null()) {\n"
" Ok(ConversionResult::Success(v)) => v,\n"
" _ => unreachable!(),\n"
" }\n"
" }\n"
" pub unsafe fn new(cx: *mut JSContext, val: HandleValue) \n"
- " -> Result<ConversionResult<${selfName}>, ()> {\n"
+ " -> Result<ConversionResult<${actualType}>, ()> {\n"
" let object = if val.get().is_null_or_undefined() {\n"
" ptr::null_mut()\n"
" } else if val.get().is_object() {\n"
@@ -6088,17 +6142,18 @@ class CGDictionary(CGThing):
" return Err(());\n"
" };\n"
" rooted!(in(cx) let object = object);\n"
- " Ok(ConversionResult::Success(${selfName} {\n"
+ "${preInitial}"
"${initParent}"
"${initMembers}"
- " }))\n"
+ "${postInitial}"
+ " Ok(ConversionResult::Success(dictionary))\n"
" }\n"
"}\n"
"\n"
- "impl FromJSValConvertible for ${selfName} {\n"
+ "impl FromJSValConvertible for ${actualType} {\n"
" type Config = ();\n"
" unsafe fn from_jsval(cx: *mut JSContext, value: HandleValue, _option: ())\n"
- " -> Result<ConversionResult<${selfName}>, ()> {\n"
+ " -> Result<ConversionResult<${actualType}>, ()> {\n"
" ${selfName}::new(cx, value)\n"
" }\n"
"}\n"
@@ -6110,12 +6165,21 @@ 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": CGIndenter(CGGeneric(preInitial), indentLevel=12).define(),
+ "postInitial": CGIndenter(CGGeneric(postInitial), indentLevel=12).define(),
})
+ def membersNeedTracing(self):
+ for member, _ in self.memberInfo:
+ if type_needs_tracing(member.type):
+ return True
+ return False
+
@staticmethod
def makeDictionaryName(dictionary):
return dictionary.identifier.name
@@ -6638,7 +6702,7 @@ class CallbackMember(CGNativeMember):
replacements["argCount"] = self.argCountStr
replacements["argvDecl"] = string.Template(
"rooted_vec!(let mut argv);\n"
- "argv.extend((0..${argCount}).map(|_| Heap::new(UndefinedValue())));\n"
+ "argv.extend((0..${argCount}).map(|_| Heap::default()));\n"
).substitute(replacements)
else:
# Avoid weird 0-sized arrays
@@ -6713,7 +6777,11 @@ class CallbackMember(CGNativeMember):
conversion = wrapForType(
"argv_root.handle_mut()", result=argval,
- successCode="argv[%s] = Heap::new(argv_root.get());" % jsvalIndex,
+ successCode=("{\n" +
+ "let arg = &mut argv[%s];\n" +
+ "*arg = Heap::default();\n" +
+ "arg.set(argv_root.get());\n" +
+ "}") % jsvalIndex,
pre="rooted!(in(cx) let mut argv_root = UndefinedValue());")
if arg.variadic:
conversion = string.Template(
@@ -6729,7 +6797,7 @@ class CallbackMember(CGNativeMember):
" // This is our current trailing argument; reduce argc\n"
" argc -= 1;\n"
"} else {\n"
- " argv[%d] = Heap::new(UndefinedValue());\n"
+ " argv[%d] = Heap::default();\n"
"}" % (i + 1, i))
return conversion