aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/script/dom/bindings/codegen/CodegenRust.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/script/dom/bindings/codegen/CodegenRust.py')
-rw-r--r--src/components/script/dom/bindings/codegen/CodegenRust.py736
1 files changed, 231 insertions, 505 deletions
diff --git a/src/components/script/dom/bindings/codegen/CodegenRust.py b/src/components/script/dom/bindings/codegen/CodegenRust.py
index 833ebaf1d63..2162d445c24 100644
--- a/src/components/script/dom/bindings/codegen/CodegenRust.py
+++ b/src/components/script/dom/bindings/codegen/CodegenRust.py
@@ -141,11 +141,9 @@ class CGThing():
"""
def __init__(self):
pass # Nothing for now
- def declare(self):
- """Produce code for a header file."""
- assert(False) # Override me!
+
def define(self):
- """Produce code for a cpp file."""
+ """Produce code for a Rust file."""
assert(False) # Override me!
class CGMethodCall(CGThing):
@@ -599,215 +597,28 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
if isMember:
raise TypeError("Can't handle unions as members, we have a "
"holderType")
- nullable = type.nullable();
- if nullable:
- type = type.inner
-
- assert(defaultValue is None or
- (isinstance(defaultValue, IDLNullValue) and nullable))
-
- unionArgumentObj = "${holderName}"
- #if isOptional or nullable:
- # unionArgumentObj += ".get_mut_ref()"
-
- memberTypes = type.flatMemberTypes
- names = []
- interfaceMemberTypes = filter(lambda t: t.isNonCallbackInterface(), memberTypes)
- if len(interfaceMemberTypes) > 0:
- interfaceObject = []
- for memberType in interfaceMemberTypes:
- if type.isGeckoInterface():
- name = memberType.inner.identifier.name
- else:
- name = memberType.name
- interfaceObject.append(CGGeneric("{res = %s.TrySetTo%s(cx, ${val}, ${valPtr}); res.is_err() || !res.unwrap()}" % (unionArgumentObj, name)))
- names.append(name)
- interfaceObject = CGWrapper(CGList(interfaceObject, " ||\n"), pre="done = ", post=";\n", reindent=True)
- else:
- interfaceObject = None
-
- arrayObjectMemberTypes = filter(lambda t: t.isArray() or t.isSequence(), memberTypes)
- if len(arrayObjectMemberTypes) > 0:
- assert len(arrayObjectMemberTypes) == 1
- memberType = arrayObjectMemberTypes[0]
- name = memberType.name
- arrayObject = CGGeneric("done = {res = %s.TrySetTo%s(cx, ${val}, ${valPtr}); res.is_err() || !res.unwrap()};" % (unionArgumentObj, name))
- # XXX Now we're supposed to check for an array or a platform object
- # that supports indexed properties... skip that last for now. It's a
- # bit of a pain.
- arrayObject = CGWrapper(CGIndenter(arrayObject),
- pre="if (IsArrayLike(cx, &argObj)) {\n",
- post="}")
- names.append(name)
- else:
- arrayObject = None
-
- dateObjectMemberTypes = filter(lambda t: t.isDate(), memberTypes)
- if len(dateObjectMemberTypes) > 0:
- assert len(dateObjectMemberTypes) == 1
- memberType = dateObjectMemberTypes[0]
- name = memberType.name
- dateObject = CGGeneric("%s.SetTo%s(cx, ${val}, ${valPtr});\n"
- "done = true;" % (unionArgumentObj, name))
- dateObject = CGWrapper(CGIndenter(dateObject),
- pre="if (JS_ObjectIsDate(cx, &argObj)) {\n",
- post="\n}")
- names.append(name)
- else:
- dateObject = None
-
- callbackMemberTypes = filter(lambda t: t.isCallback() or t.isCallbackInterface(), memberTypes)
- if len(callbackMemberTypes) > 0:
- assert len(callbackMemberTypes) == 1
- memberType = callbackMemberTypes[0]
- name = memberType.name
- callbackObject = CGGeneric("done = {res = %s.TrySetTo%s(cx, ${val}, ${valPtr}); res.is_err() || !res.unwrap()};" % (unionArgumentObj, name))
- names.append(name)
- else:
- callbackObject = None
-
- dictionaryMemberTypes = filter(lambda t: t.isDictionary(), memberTypes)
- if len(dictionaryMemberTypes) > 0:
- raise TypeError("No support for unwrapping dictionaries as member "
- "of a union")
- else:
- dictionaryObject = None
-
- if callbackObject or dictionaryObject:
- nonPlatformObject = CGList([callbackObject, dictionaryObject], "\n")
- nonPlatformObject = CGWrapper(CGIndenter(nonPlatformObject),
- pre="if (!IsPlatformObject(cx, &argObj)) {\n",
- post="\n}")
- else:
- nonPlatformObject = None
-
- objectMemberTypes = filter(lambda t: t.isObject(), memberTypes)
- if len(objectMemberTypes) > 0:
- object = CGGeneric("%s.SetToObject(&argObj);\n"
- "done = true;" % unionArgumentObj)
- else:
- object = None
-
- hasObjectTypes = interfaceObject or arrayObject or dateObject or nonPlatformObject or object
- if hasObjectTypes:
- # If we try more specific object types first then we need to check
- # whether that succeeded before converting to object.
- if object and (interfaceObject or arrayObject or dateObject or nonPlatformObject):
- object = CGWrapper(CGIndenter(object), pre="if (!done) {\n",
- post=("\n}"))
-
- if arrayObject or dateObject or nonPlatformObject:
- # An object can be both an array object and not a platform
- # object, but we shouldn't have both in the union's members
- # because they are not distinguishable.
- assert not (arrayObject and nonPlatformObject)
- templateBody = CGList([arrayObject, dateObject, nonPlatformObject], " else ")
- else:
- templateBody = None
- if interfaceObject:
- if templateBody:
- templateBody = CGList([templateBody, object], "\n")
- templateBody = CGWrapper(CGIndenter(templateBody),
- pre="if (!done) {\n", post=("\n}"))
- templateBody = CGList([interfaceObject, templateBody], "\n")
- else:
- templateBody = CGList([templateBody, object], "\n")
-
- if any([arrayObject, dateObject, nonPlatformObject, object]):
- templateBody.prepend(CGGeneric("JSObject& argObj = ${val}.toObject();"))
- templateBody = CGWrapper(CGIndenter(templateBody),
- pre="if (${val}).is_object() {\n",
- post="\n}")
- else:
- templateBody = CGGeneric()
-
- otherMemberTypes = filter(lambda t: t.isString() or t.isEnum(),
- memberTypes)
- otherMemberTypes.extend(t for t in memberTypes if t.isPrimitive())
- if len(otherMemberTypes) > 0:
- assert len(otherMemberTypes) == 1
- memberType = otherMemberTypes[0]
- if memberType.isEnum():
- name = memberType.inner.identifier.name
- else:
- name = memberType.name
- other = CGGeneric("done = {res = %s.TrySetTo%s(cx, ${val}, ${valPtr}); res.is_err() || !res.unwrap()};" % (unionArgumentObj, name))
- names.append(name)
- if hasObjectTypes:
- other = CGWrapper(CGIndenter(other), "{\n", post="\n}")
- if object:
- join = " else "
- else:
- other = CGWrapper(other, pre="if (!done) ")
- join = "\n"
- templateBody = CGList([templateBody, other], join)
- else:
- other = None
-
- templateBody = CGWrapper(templateBody, pre="let mut done = false;\n"
- "let mut res = Ok(true);\n")
- throw = CGGeneric("if res.is_err() {\n"
- " return 0;\n"
- "}\n"
- "if !done {\n"
- " return throw_not_in_union(cx, \"%s\");\n"
- "}" % ", ".join(names))
- templateBody = CGWrapper(CGIndenter(CGList([templateBody, throw], "\n")), pre="{\n", post="\n}")
-
- typeName = type.name
- argumentTypeName = typeName + "Argument"
- if nullable:
- typeName = "Option<" + typeName + " >"
- nonConstDecl = "${declName}"
-
- def handleNull(templateBody, setToNullVar, extraConditionForNull=""):
- null = CGGeneric("if %s((${val}).is_null_or_undefined()) {\n"
- " %s = None;\n"
- "}" % (extraConditionForNull, setToNullVar))
- templateBody = CGWrapper(CGIndenter(templateBody), pre="{\n", post="\n}")
- return CGList([null, templateBody], " else ")
+ declType = CGGeneric(type.name)
+ value = CGGeneric("value")
+ if type.nullable():
+ declType = CGWrapper(declType, pre="Option<", post=" >")
+ value = CGWrapper(value, pre="Some(", post=")")
- if type.hasNullableType:
- templateBody = handleNull(templateBody, unionArgumentObj)
+ templateBody = CGGeneric("match %s::from_value(cx, ${val}) {\n"
+ " Err(()) => { %s },\n"
+ " Ok(value) => ${declName} = %s,\n"
+ "}" % (type.name, exceptionCode, value.define()))
- declType = CGGeneric(typeName)
- holderType = CGGeneric(argumentTypeName)
- if isOptional:
- mutableDecl = nonConstDecl + ".Value()"
- declType = CGWrapper(declType, pre="const Optional<", post=" >")
- holderType = CGWrapper(holderType, pre="Option<", post=" >")
- constructDecl = CGGeneric(nonConstDecl + ".Construct();")
- if nullable:
- constructHolder = CGGeneric("${holderName} = Some(%s.SetValue());" % mutableDecl)
- else:
- constructHolder = CGGeneric("${holderName} = Some(${declName}.Value());")
- else:
- mutableDecl = nonConstDecl
- constructDecl = None
- holderInit = "${declName}"
- if nullable:
- holderInit += ".get_mut_ref()"
- else:
- holderInit = "&mut " + holderInit
- constructHolder = CGWrapper(holderType, pre="let mut ${holderName} = ", post="::new(" + holderInit + ");")
- if nullable:
- constructHolder = CGWrapper(constructHolder, pre="${declName} = Some(uninit());\n")
- holderType = None
+ if type.nullable():
+ templateBody = CGIfElseWrapper(
+ "(${val}).is_null_or_undefined()",
+ CGGeneric("${declName} = None;"),
+ templateBody)
- templateBody = CGList([constructHolder, templateBody], "\n")
- if nullable:
- if defaultValue:
- assert(isinstance(defaultValue, IDLNullValue))
- valueMissing = "!(${haveValue}) || "
- else:
- valueMissing = ""
- templateBody = handleNull(templateBody, mutableDecl,
- extraConditionForNull=valueMissing)
- templateBody = CGWrapper(CGIndenter(CGList([constructDecl, templateBody], "\n")),
- pre="{\n", post="\n}")
+ templateBody = handleDefaultNull(templateBody.define(),
+ "${declName} = None")
- return templateBody.define(), declType, holderType, False, "uninit()" if not nullable else None
+ return (templateBody, declType, None, isOptional, "None" if isOptional else None)
if type.isGeckoInterface():
assert not isEnforceRange and not isClamp
@@ -1084,8 +895,8 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
template = (
"match FromJSValConvertible::from_jsval(cx, ${val}, ()) {\n"
" Ok(v) => ${declName} = %s,\n"
- " Err(_) => %s\n"
- "}" % (successVal, failureCode))
+ " Err(_) => { %s }\n"
+ "}" % (successVal, exceptionCode))
if type.nullable():
declType = CGGeneric("Option<" + typeName + ">")
@@ -1762,9 +1573,7 @@ class CGNativePropertyHooks(CGThing):
def __init__(self, descriptor):
CGThing.__init__(self)
self.descriptor = descriptor
- def declare(self):
- #return "extern const NativePropertyHooks NativeHooks;\n"
- return ""
+
def define(self):
if self.descriptor.concrete and self.descriptor.proxy:
resolveOwnProperty = "ResolveOwnProperty"
@@ -1787,20 +1596,14 @@ class CGIndenter(CGThing):
A class that takes another CGThing and generates code that indents that
CGThing by some number of spaces. The default indent is two spaces.
"""
- def __init__(self, child, indentLevel=2, declareOnly=False):
+ def __init__(self, child, indentLevel=2):
CGThing.__init__(self)
self.child = child
self.indent = " " * indentLevel
- self.declareOnly = declareOnly
- def declare(self):
- decl = self.child.declare()
- if decl is not "":
- return re.sub(lineStartDetector, self.indent, decl)
- else:
- return ""
+
def define(self):
defn = self.child.define()
- if defn is not "" and not self.declareOnly:
+ if defn is not "":
return re.sub(lineStartDetector, self.indent, defn)
else:
return defn
@@ -1809,38 +1612,21 @@ class CGWrapper(CGThing):
"""
Generic CGThing that wraps other CGThings with pre and post text.
"""
- def __init__(self, child, pre="", post="", declarePre=None,
- declarePost=None, definePre=None, definePost=None,
- declareOnly=False, defineOnly=False, reindent=False):
+ def __init__(self, child, pre="", post="", reindent=False):
CGThing.__init__(self)
self.child = child
- self.declarePre = declarePre or pre
- self.declarePost = declarePost or post
- self.definePre = definePre or pre
- self.definePost = definePost or post
- self.declareOnly = declareOnly
- self.defineOnly = defineOnly
+ self.pre = pre
+ self.post = post
self.reindent = reindent
- def declare(self):
- if self.defineOnly:
- return ''
- decl = self.child.declare()
- if self.reindent:
- # We don't use lineStartDetector because we don't want to
- # insert whitespace at the beginning of our _first_ line.
- decl = stripTrailingWhitespace(
- decl.replace("\n", "\n" + (" " * len(self.declarePre))))
- return self.declarePre + decl + self.declarePost
+
def define(self):
- if self.declareOnly:
- return ''
defn = self.child.define()
if self.reindent:
# We don't use lineStartDetector because we don't want to
# insert whitespace at the beginning of our _first_ line.
defn = stripTrailingWhitespace(
- defn.replace("\n", "\n" + (" " * len(self.definePre))))
- return self.definePre + defn + self.definePost
+ defn.replace("\n", "\n" + (" " * len(self.pre))))
+ return self.pre + defn + self.post
class CGImports(CGWrapper):
"""
@@ -1868,7 +1654,7 @@ class CGImports(CGWrapper):
statements.extend('use %s;' % i for i in sorted(imports))
CGWrapper.__init__(self, child,
- declarePre='\n'.join(statements) + '\n\n')
+ pre='\n'.join(statements) + '\n\n')
@staticmethod
def getDeclarationFilename(decl):
@@ -1885,23 +1671,20 @@ class CGIfWrapper(CGWrapper):
post="\n}")
class CGNamespace(CGWrapper):
- def __init__(self, namespace, child, declareOnly=False, public=False):
+ def __init__(self, namespace, child, public=False):
pre = "%smod %s {\n" % ("pub " if public else "", namespace)
post = "} // mod %s\n" % namespace
- CGWrapper.__init__(self, child, pre=pre, post=post,
- declareOnly=declareOnly)
+ CGWrapper.__init__(self, child, pre=pre, post=post)
+
@staticmethod
- def build(namespaces, child, declareOnly=False, public=False):
+ def build(namespaces, child, public=False):
"""
Static helper method to build multiple wrapped namespaces.
"""
if not namespaces:
- return CGWrapper(child, declareOnly=declareOnly)
- inner = CGNamespace.build(namespaces[1:], child, declareOnly=declareOnly, public=public)
- return CGNamespace(namespaces[0], inner, declareOnly=declareOnly, public=public)
-
- def declare(self):
- return ""
+ return child
+ inner = CGNamespace.build(namespaces[1:], child, public=public)
+ return CGNamespace(namespaces[0], inner, public=public)
def DOMClass(descriptor):
protoList = ['PrototypeList::id::' + proto for proto in descriptor.prototypeChain]
@@ -1924,9 +1707,7 @@ class CGDOMJSClass(CGThing):
def __init__(self, descriptor):
CGThing.__init__(self)
self.descriptor = descriptor
- def declare(self):
- #return "extern DOMJSClass Class;\n"
- return ""
+
def define(self):
traceHook = "Some(%s)" % TRACE_HOOK_NAME
if self.descriptor.createGlobal:
@@ -1978,9 +1759,7 @@ class CGPrototypeJSClass(CGThing):
def __init__(self, descriptor):
CGThing.__init__(self)
self.descriptor = descriptor
- def declare(self):
- # We're purely for internal consumption
- return ""
+
def define(self):
return """
static PrototypeClassName__: [u8, ..%s] = %s;
@@ -2016,9 +1795,7 @@ class CGInterfaceObjectJSClass(CGThing):
def __init__(self, descriptor):
CGThing.__init__(self)
self.descriptor = descriptor
- def declare(self):
- # We're purely for internal consumption
- return ""
+
def define(self):
if True:
return ""
@@ -2059,23 +1836,28 @@ class CGList(CGThing):
self.children.insert(0, child)
def join(self, generator):
return self.joiner.join(filter(lambda s: len(s) > 0, (child for child in generator)))
- def declare(self):
- return self.join(child.declare() for child in self.children if child is not None)
+
def define(self):
return self.join(child.define() for child in self.children if child is not None)
+
+class CGIfElseWrapper(CGList):
+ def __init__(self, condition, ifTrue, ifFalse):
+ kids = [ CGIfWrapper(ifTrue, condition),
+ CGWrapper(CGIndenter(ifFalse), pre=" else {\n", post="\n}") ]
+ CGList.__init__(self, kids)
+
+
class CGGeneric(CGThing):
"""
A class that spits out a fixed string into the codegen. Can spit out a
separate string for the declaration too.
"""
- def __init__(self, define="", declare=""):
- self.declareText = declare
- self.defineText = define
- def declare(self):
- return self.declareText
+ def __init__(self, text):
+ self.text = text
+
def define(self):
- return self.defineText
+ return self.text
def getTypes(descriptor):
"""
@@ -2224,7 +2006,6 @@ class CGAbstractMethod(CGThing):
self.name = name
self.returnType = returnType
self.args = args
- self.inline = inline
self.alwaysInline = alwaysInline
self.extern = extern
self.templateArgs = templateArgs
@@ -2258,17 +2039,10 @@ class CGAbstractMethod(CGThing):
return "\n unsafe {" if self.unsafe else ""
def _unsafe_close(self):
return "\n }\n" if self.unsafe else ""
- def declare(self):
- if self.inline:
- return self._define()
- #return "%sfn %s%s(%s)%s;\n" % (self._decorators(), self.name, self._template(),
- # self._argstring(), self._returnType())
- return ""
- def _define(self, fromDeclare=False):
+ def define(self, fromDeclare=False):
return self.definition_prologue(fromDeclare) + "\n" + self.definition_body() + self.definition_epilogue()
- def define(self):
- return "" if self.inline else self._define()
+
def definition_prologue(self, fromDeclare):
return "%sfn %s%s(%s)%s {%s" % (self._decorators(), self.name, self._template(),
self._argstring(fromDeclare), self._returnType(), self._unsafe_open())
@@ -2359,9 +2133,6 @@ class CGAbstractExternMethod(CGAbstractMethod):
def __init__(self, descriptor, name, returnType, args):
CGAbstractMethod.__init__(self, descriptor, name, returnType, args,
inline=False, extern=True)
- def declare(self):
- # We only have implementation
- return ""
class PropertyArrays():
def __init__(self, descriptor):
@@ -2559,10 +2330,6 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
args = [Argument('&mut JSPageInfo', 'js_info')]
CGAbstractMethod.__init__(self, descriptor, 'DefineDOMInterface', 'bool', args, pub=True)
- def declare(self):
- #return CGAbstractMethod.declare(self)
- return ""
-
def define(self):
return CGAbstractMethod.define(self)
@@ -3124,9 +2891,6 @@ class CGMemberJITInfo(CGThing):
self.member = member
self.descriptor = descriptor
- def declare(self):
- return ""
-
def defineJitInfo(self, infoName, opName, infallible):
protoID = "PrototypeList::id::%s as u32" % self.descriptor.name
depth = self.descriptor.interface.inheritanceDepth()
@@ -3200,9 +2964,6 @@ class CGEnum(CGThing):
CGThing.__init__(self)
self.enum = enum
- def declare(self):
- return ""
-
def define(self):
return """
#[repr(uint)]
@@ -3320,176 +3081,178 @@ def getUnionTypeTemplateVars(type, descriptorProvider):
name = type.name
typeName = "/*" + type.name + "*/"
- tryNextCode = """{
- return Ok(true);
-}"""
(template, declType, holderType,
dealWithOptional, initialValue) = getJSToNativeConversionTemplate(
- type, descriptorProvider, failureCode=tryNextCode,
- isDefinitelyObject=True, isOptional=type.nullable(), preSuccess="e" + name + "(", postSuccess=")")
+ type, descriptorProvider, failureCode="return Ok(None);",
+ exceptionCode='return Err(());',
+ isDefinitelyObject=True, isOptional=False)
structType = declType.define()
externalType = getUnionAccessorSignatureType(type, descriptorProvider).define()
- if type.isObject():
- setter = CGGeneric("pub fn SetToObject(obj: *JSObject) {\n"
- " mUnion = Some(eObject(obj));\n"
- "}")
- else:
- jsConversion = string.Template(template).substitute(
- {
- "val": "value",
- "valPtr": "pvalue",
- "declName": "*self.mUnion",
- "holderName": "m" + name + "Holder"
- }
- )
- jsConversion = CGWrapper(CGGeneric(jsConversion),
- post="\n"
- "return Ok(false);")
- setter = CGWrapper(CGIndenter(jsConversion),
- pre="pub fn TrySetTo" + name + "(&mut self, cx: *JSContext, value: JSVal, pvalue: *JSVal) -> Result<bool,()> {\n",
- post="\n"
- "}")
+ assert not type.isObject()
+ jsConversion = string.Template(template).substitute({
+ "val": "value",
+ "valPtr": None,
+ "declName": "retval",
+ "holderName": None,
+ })
+ jsConversion = CGWrapper(CGGeneric(jsConversion),
+ pre="let retval;\n",
+ post="\nOk(Some(retval))")
return {
- "name": name,
- "typeName": typeName,
- "structType": structType,
- "externalType": externalType,
- "optRef": 'ref ' if externalType[0] == '&' else '',
- "setter": CGIndenter(setter).define(),
- "holderType": holderType.define() if holderType else None
- }
-
-def mapTemplate(template, templateVarArray):
- return map(lambda v: string.Template(template).substitute(v),
- templateVarArray)
+ "name": name,
+ "typeName": typeName,
+ "jsConversion": jsConversion,
+ }
class CGUnionStruct(CGThing):
def __init__(self, type, descriptorProvider):
+ assert not type.nullable()
+ assert not type.hasNullableType
+
CGThing.__init__(self)
- self.type = type.unroll()
+ self.type = type
self.descriptorProvider = descriptorProvider
- def declare(self):
+ def define(self):
templateVars = map(lambda t: getUnionTypeTemplateVars(t, self.descriptorProvider),
self.type.flatMemberTypes)
+ enumValues = [
+ " e%s(%s)," % (v["name"], v["typeName"]) for v in templateVars
+ ]
+ return ("pub enum %s {\n"
+ "%s\n"
+ "}\n") % (self.type, "\n".join(enumValues))
- callDestructors = []
- enumValues = []
- methods = []
- if self.type.hasNullableType:
- callDestructors.append(" case eNull:\n"
- " break;")
- enumValues.append("eNull")
- methods.append(""" pub fn IsNull(&self) -> bool {
- match *self {
- eNull => true,
- _ => false
- }
- }""")
-
- destructorTemplate = """ fn Destroy${name}(&mut self) {
- assert!(Is${name}(), "Wrong type!");
- *self.mUnion = None;
- }"""
- destructors = mapTemplate(destructorTemplate, templateVars)
- callDestructors.extend(mapTemplate(" case e${name}:\n"
- " Destroy${name}();\n"
- " break;", templateVars))
- enumValues.extend(mapTemplate("e${name}(${typeName})", templateVars))
- methodTemplate = """ pub fn Is${name}(&self) -> bool {
- match *self {
- e${name}(_) => true,
- _ => false
- }
- }
- pub fn GetAs${name}<'a>(&'a self) -> ${externalType} {
- assert!(self.Is${name}());
- match *self {
- e${name}(${optRef}inner) => inner,
- _ => unreachable!()
- }
- }"""
- methods.extend(mapTemplate(methodTemplate, templateVars))
- values = mapTemplate("UnionMember<${structType} > m${name};", templateVars)
- return string.Template("""
-pub enum ${structName} {
- ${enumValues}
-}
-
-impl ${structName} {
-${methods}
-}
-""").substitute(
- {
- "structName": self.type.__str__(),
- "callDestructors": "\n".join(callDestructors),
- "destructors": "\n".join(destructors),
- "methods": "\n\n".join(methods),
- "enumValues": ",\n ".join(enumValues),
- "values": "\n ".join(values),
- })
-
- def define(self):
- return """
-"""
class CGUnionConversionStruct(CGThing):
def __init__(self, type, descriptorProvider):
+ assert not type.nullable()
+ assert not type.hasNullableType
+
CGThing.__init__(self)
- self.type = type.unroll()
+ self.type = type
self.descriptorProvider = descriptorProvider
- def declare(self):
- setters = []
+ def from_value_method(self):
+ memberTypes = self.type.flatMemberTypes
+ names = []
+ conversions = []
- if self.type.hasNullableType:
- setters.append(""" pub fn SetNull(&mut self) -> bool
- {
- mUnion = Some(eNull);
- return true;
- }""")
+ interfaceMemberTypes = filter(lambda t: t.isNonCallbackInterface(), memberTypes)
+ if len(interfaceMemberTypes) > 0:
+ def get_name(memberType):
+ if self.type.isGeckoInterface():
+ return memberType.inner.identifier.name
+
+ return memberType.name
+
+ def get_match(name):
+ return (
+ "match %s::TryConvertTo%s(cx, value) {\n"
+ " Err(_) => return Err(()),\n"
+ " Ok(Some(value)) => return Ok(e%s(value)),\n"
+ " Ok(None) => (),\n"
+ "}\n") % (self.type, name, name)
+
+ typeNames = [get_name(memberType) for memberType in interfaceMemberTypes]
+ interfaceObject = CGList(CGGeneric(get_match(typeName)) for typeName in typeNames)
+ names.extend(typeNames)
+ else:
+ interfaceObject = None
- templateVars = map(lambda t: getUnionTypeTemplateVars(t, self.descriptorProvider),
- self.type.flatMemberTypes)
- structName = self.type.__str__()
-
- setters.extend(mapTemplate("${setter}", templateVars))
- private = "\n".join(mapTemplate(""" fn SetAs${name}() -> &${structType}
- {
- mUnion.mType = mUnion.e${name};
- return mUnion.mValue.m${name}.SetValue();
- }""", templateVars))
- private += "\n\n"
- holders = filter(lambda v: v["holderType"] is not None, templateVars)
- if len(holders) > 0:
- private += "\n".join(mapTemplate(" ${holderType} m${name}Holder;", holders))
- private += "\n\n"
- private += " " + structName + "& mUnion;"
- return string.Template("""
-pub struct ${structName}Argument<'a> {
- mUnion: &'a mut ${innerType}
-}
+ arrayObjectMemberTypes = filter(lambda t: t.isArray() or t.isSequence(), memberTypes)
+ if len(arrayObjectMemberTypes) > 0:
+ assert len(arrayObjectMemberTypes) == 1
+ raise TypeError("Can't handle arrays or sequences in unions.")
+ else:
+ arrayObject = None
-impl<'a> ${structName}Argument<'a> {
- pub fn new(union: &'a mut ${innerType}) -> ${structName}Argument<'a> {
- ${structName}Argument {
- mUnion: union
- }
- }
+ dateObjectMemberTypes = filter(lambda t: t.isDate(), memberTypes)
+ if len(dateObjectMemberTypes) > 0:
+ assert len(dateObjectMemberTypes) == 1
+ raise TypeError("Can't handle dates in unions.")
+ else:
+ dateObject = None
-${setters}
-}
-""").substitute({"structName": structName,
- "innerType": ("Option<%s>" % structName) if self.type.nullable() else structName,
- "setters": "\n\n".join(setters),
- })
+ callbackMemberTypes = filter(lambda t: t.isCallback() or t.isCallbackInterface(), memberTypes)
+ if len(callbackMemberTypes) > 0:
+ assert len(callbackMemberTypes) == 1
+ raise TypeError("Can't handle callbacks in unions.")
+ else:
+ callbackObject = None
+
+ dictionaryMemberTypes = filter(lambda t: t.isDictionary(), memberTypes)
+ if len(dictionaryMemberTypes) > 0:
+ raise TypeError("No support for unwrapping dictionaries as member "
+ "of a union")
+ else:
+ dictionaryObject = None
+
+ if callbackObject or dictionaryObject:
+ assert False, "Not currently supported"
+ else:
+ nonPlatformObject = None
+
+ objectMemberTypes = filter(lambda t: t.isObject(), memberTypes)
+ if len(objectMemberTypes) > 0:
+ raise TypeError("Can't handle objects in unions.")
+ else:
+ object = None
+
+ hasObjectTypes = interfaceObject or arrayObject or dateObject or nonPlatformObject or object
+ if hasObjectTypes:
+ assert interfaceObject
+ templateBody = CGList([interfaceObject], "\n")
+ conversions.append(CGIfWrapper(templateBody, "value.is_object()"))
+
+ otherMemberTypes = [
+ t for t in memberTypes if t.isPrimitive() or t.isString() or t.isEnum()
+ ]
+ if len(otherMemberTypes) > 0:
+ assert len(otherMemberTypes) == 1
+ memberType = otherMemberTypes[0]
+ if memberType.isEnum():
+ name = memberType.inner.identifier.name
+ else:
+ name = memberType.name
+ match = (
+ "match %s::TryConvertTo%s(cx, value) {\n"
+ " Err(_) => return Err(()),\n"
+ " Ok(Some(value)) => return Ok(e%s(value)),\n"
+ " Ok(None) => (),\n"
+ "}\n") % (self.type, name, name)
+ conversions.append(CGGeneric(match))
+ names.append(name)
+
+ conversions.append(CGGeneric(
+ "throw_not_in_union(cx, \"%s\");\n"
+ "Err(())" % ", ".join(names)))
+ return CGWrapper(
+ CGIndenter(CGList(conversions, "\n\n")),
+ pre="pub fn from_value(cx: *JSContext, value: JSVal) -> Result<%s, ()> {\n" % self.type,
+ post="\n}")
+
+ def try_method(self, t):
+ templateVars = getUnionTypeTemplateVars(t, self.descriptorProvider)
+ returnType = "Result<Option<%s>, ()>" % templateVars["typeName"]
+ jsConversion = templateVars["jsConversion"]
+
+ return CGWrapper(
+ CGIndenter(jsConversion, 4),
+ pre="pub fn TryConvertTo%s(cx: *JSContext, value: JSVal) -> %s {\n" % (t.name, returnType),
+ post="\n}")
def define(self):
+ methods = [self.from_value_method()]
+ methods.extend(self.try_method(t) for t in self.type.flatMemberTypes)
return """
-"""
+impl %s {
+%s
+}""" % (self.type, CGIndenter(CGList(methods, "\n\n")).define())
+
class ClassItem:
""" Use with CGClass """
@@ -3872,7 +3635,7 @@ class CGClass(CGThing):
in self.templateSpecialization])
return className
- def declare(self):
+ def define(self):
result = ''
if self.templateArgs:
templateArgs = [a.declare() for a in self.templateArgs]
@@ -3948,8 +3711,6 @@ class CGClass(CGThing):
result += "}"
return result
- def define(self):
- return ''
class CGXrayHelper(CGAbstractExternMethod):
def __init__(self, descriptor, name, args, properties):
@@ -4103,8 +3864,7 @@ class CGProxyUnwrap(CGAbstractMethod):
def __init__(self, descriptor):
args = [Argument('*JSObject', 'obj')]
CGAbstractMethod.__init__(self, descriptor, "UnwrapProxy", '*' + descriptor.concreteType, args, alwaysInline=True)
- def declare(self):
- return ""
+
def definition_body(self):
return """ /*if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
obj = js::UnwrapObject(obj);
@@ -4493,9 +4253,7 @@ class CGDOMJSProxyHandlerDOMClass(CGThing):
def __init__(self, descriptor):
CGThing.__init__(self)
self.descriptor = descriptor
- def declare(self):
- #return "extern const DOMClass Class;\n"
- return ""
+
def define(self):
return """
static Class: DOMClass = """ + DOMClass(self.descriptor) + """;
@@ -4555,7 +4313,7 @@ class CGDescriptor(CGThing):
cgThings.append(CGPrototypeJSClass(descriptor))
properties = PropertyArrays(descriptor)
- cgThings.append(CGGeneric(define=str(properties)))
+ cgThings.append(CGGeneric(str(properties)))
cgThings.append(CGCreateInterfaceObjectsMethod(descriptor, properties))
# Set up our Xray callbacks as needed.
@@ -4605,8 +4363,6 @@ class CGDescriptor(CGThing):
# post='\n')
self.cgRoot = cgThings
- def declare(self):
- return self.cgRoot.declare()
def define(self):
return self.cgRoot.define()
@@ -4650,8 +4406,6 @@ class CGNamespacedEnum(CGThing):
# Save the result.
self.node = curr
- def declare(self):
- return self.node.declare()
def define(self):
return self.node.define()
@@ -4674,9 +4428,12 @@ class CGDictionary(CGThing):
defaultValue=member.defaultValue))
for member in dictionary.members ]
- def declare(self):
+ def define(self):
if not self.generatable:
return ""
+ return self.struct() + "\n" + self.impl()
+
+ def struct(self):
d = self.dictionary
if d.parent:
inheritance = " parent: %s::%s,\n" % (self.makeModuleName(d.parent),
@@ -4697,9 +4454,7 @@ class CGDictionary(CGThing):
"}").substitute( { "selfName": self.makeClassName(d),
"inheritance": inheritance }))
- def define(self):
- if not self.generatable:
- return ""
+ def impl(self):
d = self.dictionary
if d.parent:
initParent = ("// Per spec, we init the parent's members first\n"
@@ -4928,8 +4683,8 @@ class CGBindingRoot(CGThing):
CGList([CGGeneric(" use dom::bindings::utils::EnumEntry;"),
CGEnum(e)]), public=True)
def makeEnumTypedef(e):
- return CGGeneric(declare=("pub type %s = self::%sValues::valuelist;\n" %
- (e.identifier.name, e.identifier.name)))
+ return CGGeneric("pub type %s = self::%sValues::valuelist;\n" %
+ (e.identifier.name, e.identifier.name))
cgthings = [ fun(e) for e in config.getEnums(webIDLFile)
for fun in [makeEnum, makeEnumTypedef] ]
@@ -5028,10 +4783,8 @@ class CGBindingRoot(CGThing):
'dom::bindings::conversions::{Default, Empty}',
'dom::bindings::codegen::*',
'dom::bindings::codegen::UnionTypes::*',
- 'dom::bindings::codegen::UnionConversions::*',
'dom::bindings::error::{FailureUnknown, Fallible, Error, ErrorResult}',
'dom::bindings::error::{throw_method_failed_with_details}',
- 'dom::bindings::error::{throw_not_in_union}',
'script_task::JSPageInfo',
'dom::bindings::proxyhandler',
'dom::bindings::proxyhandler::{_obj_toString, defineProperty}',
@@ -5045,7 +4798,6 @@ class CGBindingRoot(CGThing):
'std::vec',
'std::str',
'std::num',
- 'std::unstable::intrinsics::uninit',
'std::unstable::raw::Box',
])
@@ -5054,8 +4806,7 @@ class CGBindingRoot(CGThing):
# Store the final result.
self.root = curr
- def declare(self):
- return stripTrailingWhitespace(self.root.declare())
+
def define(self):
return stripTrailingWhitespace(self.root.define())
@@ -5971,7 +5722,7 @@ class GlobalGenRoots():
return "dom::%s" % descriptor.name.lower()
descriptors = [d.name for d in config.getDescriptors(register=True, hasInterfaceObject=True)]
- curr = CGList([CGGeneric(declare="pub use dom::%s::%s;\n" % (name.lower(), name)) for name in descriptors])
+ curr = CGList([CGGeneric("pub use dom::%s::%s;\n" % (name.lower(), name)) for name in descriptors])
curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
return curr
@@ -5979,7 +5730,7 @@ class GlobalGenRoots():
def BindingDeclarations(config):
descriptors = [d.name for d in config.getDescriptors(register=True)]
- curr = CGList([CGGeneric(declare="pub mod %sBinding;\n" % name) for name in descriptors])
+ curr = CGList([CGGeneric("pub mod %sBinding;\n" % name) for name in descriptors])
curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
return curr
@@ -5987,19 +5738,19 @@ class GlobalGenRoots():
def InheritTypes(config):
descriptors = config.getDescriptors(register=True, hasInterfaceObject=True)
- allprotos = [CGGeneric(declare="#[allow(unused_imports)];\n"),
- CGGeneric(declare="use dom::types::*;\n"),
- CGGeneric(declare="use dom::bindings::js::JS;\n"),
- CGGeneric(declare="use dom::bindings::trace::Traceable;\n"),
- CGGeneric(declare="use extra::serialize::{Encodable, Encoder};\n"),
- CGGeneric(declare="use js::jsapi::JSTracer;\n\n")]
+ allprotos = [CGGeneric("#[allow(unused_imports)];\n"),
+ CGGeneric("use dom::types::*;\n"),
+ CGGeneric("use dom::bindings::js::JS;\n"),
+ CGGeneric("use dom::bindings::trace::Traceable;\n"),
+ CGGeneric("use extra::serialize::{Encodable, Encoder};\n"),
+ CGGeneric("use js::jsapi::JSTracer;\n\n")]
for descriptor in descriptors:
name = descriptor.name
- protos = [CGGeneric(declare='pub trait %s {}\n' % (name + 'Base'))]
+ protos = [CGGeneric('pub trait %s {}\n' % (name + 'Base'))]
for proto in descriptor.prototypeChain:
- protos += [CGGeneric(declare='impl %s for %s {}\n' % (proto + 'Base',
+ protos += [CGGeneric('impl %s for %s {}\n' % (proto + 'Base',
descriptor.concreteType))]
- derived = [CGGeneric(declare='pub trait %s { fn %s(&self) -> bool; }\n' %
+ derived = [CGGeneric('pub trait %s { fn %s(&self) -> bool; }\n' %
(name + 'Derived', 'is_' + name.lower()))]
for protoName in descriptor.prototypeChain[1:-1]:
protoDescriptor = config.getDescriptor(protoName)
@@ -6012,10 +5763,10 @@ class GlobalGenRoots():
'selfName': name + 'Derived',
'baseName': protoDescriptor.concreteType,
'parentName': protoDescriptor.prototypeChain[-2].lower()})
- derived += [CGGeneric(declare=delegate)]
- derived += [CGGeneric(declare='\n')]
+ derived += [CGGeneric(delegate)]
+ derived += [CGGeneric('\n')]
- cast = [CGGeneric(declare=string.Template('''pub trait ${castTraitName} {
+ cast = [CGGeneric(string.Template('''pub trait ${castTraitName} {
fn from<T: ${fromBound}>(derived: &JS<T>) -> JS<Self> {
unsafe { derived.clone().transmute() }
}
@@ -6029,9 +5780,9 @@ class GlobalGenRoots():
'castTraitName': name + 'Cast',
'fromBound': name + 'Base',
'toBound': name + 'Derived'})),
- CGGeneric(declare="impl %s for %s {}\n\n" % (name + 'Cast', name))]
+ CGGeneric("impl %s for %s {}\n\n" % (name + 'Cast', name))]
- trace = [CGGeneric(declare=string.Template('''impl Traceable for ${name} {
+ trace = [CGGeneric(string.Template('''impl Traceable for ${name} {
fn trace(&self, tracer: *mut JSTracer) {
unsafe {
self.encode(&mut *tracer);
@@ -6086,7 +5837,7 @@ class GlobalGenRoots():
#stack[len(elements)].append(clazz)
- curr = CGList([stack[0], curr], "\n")
+ curr = CGList([stack[0], curr, UnionConversions(config.getDescriptors())], "\n")
#curr = CGHeaders([], [], includes, [], curr)
@@ -6094,37 +5845,12 @@ class GlobalGenRoots():
#curr = CGIncludeGuard('UnionTypes', curr)
curr = CGImports(curr, [
- 'dom::bindings::js::JS',
- 'dom::types::*',
- ])
-
- # Add the auto-generated comment.
- curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
-
- # Done.
- return curr
-
- @staticmethod
- def UnionConversions(config):
-
- unions = UnionConversions(config.getDescriptors())
- curr = unions
-
- # Wrap all of that in our namespaces.
- #curr = CGNamespace.build(['mozilla', 'dom'], unions)
-
- curr = CGWrapper(curr, post='\n')
-
- #curr = CGHeaders([], [], ["nsDebug.h", "mozilla/dom/UnionTypes.h", "nsDOMQS.h"], [], curr)
-
- # Add include guards.
- #curr = CGIncludeGuard('UnionConversions', curr)
-
- curr = CGImports(curr, [
'dom::bindings::utils::unwrap_jsmanaged',
- 'dom::bindings::codegen::UnionTypes::*',
'dom::bindings::codegen::PrototypeList',
'dom::bindings::conversions::{FromJSValConvertible, ToJSValConvertible}',
+ 'dom::bindings::error::throw_not_in_union',
+ 'dom::bindings::js::JS',
+ 'dom::types::*',
'js::{crust, JS_ARGV, JS_CALLEE, JS_THIS_OBJECT}',
'js::{JSCLASS_GLOBAL_SLOT_COUNT, JSCLASS_IS_DOMJSCLASS}',
'js::{JSCLASS_IS_GLOBAL, JSCLASS_RESERVED_SLOTS_SHIFT}',