aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/codegen/CodegenRust.py
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2018-07-06 11:14:44 -0700
committerManish Goregaokar <manishsmail@gmail.com>2018-07-06 13:10:56 -0700
commitcceaede96a18e67d93c087d6d499f27eda022025 (patch)
treeb996f245a09434a0bd4f69e3e13c2e531885a950 /components/script/dom/bindings/codegen/CodegenRust.py
parentc90737e6c8b9436919706f9490ba6d05492b7121 (diff)
downloadservo-cceaede96a18e67d93c087d6d499f27eda022025.tar.gz
servo-cceaede96a18e67d93c087d6d499f27eda022025.zip
Make (dictionary)::empty() safe
It currently works by constructing from null (which will throw a runtime error if there are non-defaultable members). This changes it so that we no longer need a JSContext to construct this, so it can be safely constructed. In the case of non-defaultable members, this method simply does not exist.
Diffstat (limited to 'components/script/dom/bindings/codegen/CodegenRust.py')
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py56
1 files changed, 48 insertions, 8 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py
index ae76667707e..6015a4b126a 100644
--- a/components/script/dom/bindings/codegen/CodegenRust.py
+++ b/components/script/dom/bindings/codegen/CodegenRust.py
@@ -744,7 +744,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
if defaultValue:
assert isinstance(defaultValue, IDLNullValue)
dictionary, = dictionaries
- default = "%s::%s(%s::%s::empty(cx))" % (
+ default = "%s::%s(%s::%s::empty())" % (
union_native_type(type),
dictionary.name,
CGDictionary.makeModuleName(dictionary.inner),
@@ -1148,7 +1148,7 @@ 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
+ empty = "%s::empty()" % typeName
if type_needs_tracing(type):
declType = CGTemplatedType("RootedTraceableBox", declType)
@@ -6274,12 +6274,7 @@ class CGDictionary(CGThing):
return string.Template(
"impl ${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"
+ "${empty}\n"
" pub unsafe fn new(cx: *mut JSContext, val: HandleValue) \n"
" -> Result<ConversionResult<${actualType}>, ()> {\n"
" let object = if val.get().is_null_or_undefined() {\n"
@@ -6315,6 +6310,7 @@ class CGDictionary(CGThing):
"}\n").substitute({
"selfName": selfName,
"actualType": actualType,
+ "empty": CGIndenter(CGGeneric(self.makeEmpty()), indentLevel=4).define(),
"initParent": CGIndenter(CGGeneric(initParent), indentLevel=12).define(),
"initMembers": CGIndenter(memberInits, indentLevel=12).define(),
"insertMembers": CGIndenter(memberInserts, indentLevel=8).define(),
@@ -6380,6 +6376,50 @@ class CGDictionary(CGThing):
return CGGeneric(conversion)
+ def makeEmpty(self):
+ if self.hasRequiredFields(self.dictionary):
+ return ""
+ parentTemplate = "parent: %s::%s::empty(),\n"
+ fieldTemplate = "%s: %s,\n"
+ functionTemplate = (
+ "pub fn empty() -> Self {\n"
+ " Self {\n"
+ "%s"
+ " }\n"
+ "}"
+ )
+ if self.membersNeedTracing():
+ parentTemplate = "dictionary.parent = %s::%s::empty();\n"
+ fieldTemplate = "dictionary.%s = %s;\n"
+ functionTemplate = (
+ "pub fn empty() -> RootedTraceableBox<Self> {\n"
+ " let mut dictionary = RootedTraceableBox::new(Self::default());\n"
+ "%s"
+ " dictionary\n"
+ "}"
+ )
+ s = ""
+ if self.dictionary.parent:
+ s += parentTemplate % (self.makeModuleName(self.dictionary.parent),
+ self.makeClassName(self.dictionary.parent))
+ for member, info in self.memberInfo:
+ if not member.optional:
+ return ""
+ default = info.default
+ if not default:
+ default = "None"
+ s += fieldTemplate % (self.makeMemberName(member.identifier.name), default)
+ return functionTemplate % CGIndenter(CGGeneric(s), 12).define()
+
+ def hasRequiredFields(self, dictionary):
+ if dictionary.parent:
+ if self.hasRequiredFields(dictionary.parent):
+ return True
+ for member in dictionary.members:
+ if not member.optional:
+ return True
+ return False
+
@staticmethod
def makeMemberName(name):
# Can't use Rust keywords as member names.