Bug 949264 part 2. Support union members in generated events. r=smaug
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 12 Dec 2013 16:11:55 -0500
changeset 160269 ebd95b488dc10086c1bb45588136097dd8c23bdf
parent 160268 fe7c562b3cc71a05f444430139c726bd408c7734
child 160270 1d09a0b29c109ba5b56227432125cab1b64f7aa4
push id25827
push userkwierso@gmail.com
push dateFri, 13 Dec 2013 03:13:04 +0000
treeherdermozilla-central@1bc33fa19b24 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs949264
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 949264 part 2. Support union members in generated events. r=smaug
dom/bindings/Codegen.py
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -3272,17 +3272,17 @@ for (uint32_t i = 0; i < length; ++i) {
                           '  ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "%s", "%s");\n'
                           "%s\n"
                           "}" % (exceptionCodeIndented.define(),
                                  firstCap(sourceDescription),
                                  ", ".join(names),
                                  exceptionCodeIndented.define()))
         templateBody = CGWrapper(CGIndenter(CGList([templateBody, throw], "\n")), pre="{\n", post="\n}")
 
-        typeName = ("Owning" if isMember else "") + type.name
+        typeName = CGUnionStruct.unionTypeDecl(type, isMember)
         argumentTypeName = typeName + "Argument"
         if nullable:
             typeName = "Nullable<" + typeName + " >"
 
         def handleNull(templateBody, setToNullVar, extraConditionForNull=""):
             nullTest = "%s${val}.isNullOrUndefined()" % extraConditionForNull
             return CGIfElseWrapper(nullTest,
                                    CGGeneric("%s.SetNull();" % setToNullVar),
@@ -4697,17 +4697,17 @@ def getRetvalDeclarationForType(returnTy
                 result = CGTemplatedType("RootedDictionary", result)
             resultArgs = "cx"
         else:
             if nullable:
                 result = CGTemplatedType("Nullable", result)
             resultArgs = None
         return result, True, None, resultArgs
     if returnType.isUnion():
-        result = CGGeneric("Owning" + returnType.unroll().name)
+        result = CGGeneric(CGUnionStruct.unionTypeName(returnType.unroll(), True))
         if not isMember and typeNeedsRooting(returnType):
             if returnType.nullable():
                 result = CGTemplatedType("NullableRootedUnion", result)
             else:
                 result = CGTemplatedType("RootedUnion", result)
             resultArgs = "cx"
         else:
             if returnType.nullable():
@@ -6886,17 +6886,17 @@ class CGUnionStruct(CGThing):
         methods.append(ClassMethod("ToJSVal", "bool", [
                                    Argument("JSContext*", "cx"),
                                    Argument("JS::Handle<JSObject*>", "scopeObj"),
                                    Argument("JS::MutableHandle<JS::Value>", "rval")
         ], body=CGSwitch("mType", toJSValCases,
                          default=CGGeneric("return false;")).define(), const=True))
 
         constructors = [ctor]
-        selfName = ("Owning" if self.ownsMembers else "") + str(self.type)
+        selfName = CGUnionStruct.unionTypeName(self.type, self.ownsMembers)
         if self.ownsMembers:
             if len(traceCases):
                 traceBody = CGSwitch("mType", traceCases,
                                      default=CGGeneric("")).define()
             else:
                 traceBody = ""
             methods.append(ClassMethod("TraceUnion", "void",
                                        [Argument("JSTracer*", "trc")],
@@ -6945,16 +6945,38 @@ class CGUnionStruct(CGThing):
                 "typedArraysAreStructs": True
                 })
         return CGGeneric(wrapCode)
 
     @staticmethod
     def isUnionCopyConstructible(type):
         return all(isTypeCopyConstructible(t) for t in type.flatMemberTypes)
 
+    @staticmethod
+    def unionTypeName(type, ownsMembers):
+        """
+        Returns a string name for this known union type.
+        """
+        assert type.isUnion() and not type.nullable()
+        return ("Owning" if ownsMembers else "") + type.name
+
+    @staticmethod
+    def unionTypeDecl(type, ownsMembers):
+        """
+        Returns a string for declaring this possibly-nullable union type.
+        """
+        assert type.isUnion()
+        nullable = type.nullable()
+        if nullable:
+            type = type.inner
+        decl = CGGeneric(CGUnionStruct.unionTypeName(type, ownsMembers))
+        if nullable:
+            decl = CGTemplatedType("Nullable", decl)
+        return decl.define()
+
 class CGUnionConversionStruct(CGThing):
     def __init__(self, type, descriptorProvider):
         CGThing.__init__(self)
         self.type = type.unroll()
         self.descriptorProvider = descriptorProvider
 
     def declare(self):
 
@@ -9849,16 +9871,24 @@ class CGNativeMember(ClassMethod):
         if type.isDictionary():
             if isMember:
                 # Only the first member of the tuple matters here, but return
                 # bogus values for the others in case someone decides to use
                 # them.
                 return CGDictionary.makeDictionaryName(type.inner), None, None
             # In this case we convert directly into our outparam to start with
             return "void", "", ""
+        if type.isUnion():
+            if isMember:
+                # Only the first member of the tuple matters here, but return
+                # bogus values for the others in case someone decides to use
+                # them.
+                return CGUnionStruct.unionTypeDecl(type, True), None, None
+            # In this case we convert directly into our outparam to start with
+            return "void", "", ""
 
         raise TypeError("Don't know how to declare return value for %s" %
                         type)
 
     def getArgs(self, returnType, argList):
         args = [self.getArg(arg) for arg in argList]
         # Now the outparams
         if returnType.isDOMString():
@@ -9878,16 +9908,20 @@ class CGNativeMember(ClassMethod):
         elif returnType.isDictionary():
             nullable = returnType.nullable()
             if nullable:
                 returnType = returnType.inner
             dictType = CGGeneric(CGDictionary.makeDictionaryName(returnType.inner))
             if nullable:
                 dictType = CGTemplatedType("Nullable", dictType)
             args.append(Argument("%s&" % dictType.define(), "retval"))
+        elif returnType.isUnion():
+            args.append(Argument("%s&" %
+                                 CGUnionStruct.unionTypeDecl(returnType, True),
+                                 "retval"))
         # And the ErrorResult
         if not 'infallible' in self.extendedAttrs:
             # Use aRv so it won't conflict with local vars named "rv"
             args.append(Argument("ErrorResult&", "aRv"))
         # The legacycaller thisval
         if self.member.isMethod() and self.member.isLegacycaller():
             # If it has an identifier, we can't deal with it yet
             assert self.member.isIdentifierLess()
@@ -11458,16 +11492,18 @@ class CGEventGetter(CGNativeMember):
             ret += "  JS::ExposeObjectToActiveJS(%s);\n" % memberName
             ret += "}\n"
             ret += "return " + memberName + ";"
             return ret;
         if type.isAny():
             ret =  "JS::ExposeValueToActiveJS("+ memberName + ");\n"
             ret += "return " + memberName + ";"
             return ret;
+        if type.isUnion():
+            return "retval = " + memberName + ";"
         raise TypeError("Event code generator does not support this type!")
 
     def declare(self, cgClass):
         if getattr(self.member, "originatingInterface",
                    cgClass.descriptor.interface) != cgClass.descriptor.interface:
             return ""
         return CGNativeMember.declare(self, cgClass)
 
@@ -11607,16 +11643,21 @@ class CGEventClass(CGBindingImplClass):
                         nativeType.pop(0)
                         if nativeType[0] == "dom":
                             nativeType.pop(0)
                     nativeType = CGWrapper(CGGeneric("::".join(nativeType)), pre="nsRefPtr<", post=">").define()
                 elif m.type.isAny():
                     nativeType = "JS::Heap<JS::Value>"
                 elif m.type.isObject() or m.type.isSpiderMonkeyInterface():
                     nativeType = "JS::Heap<JSObject*>"
+                elif m.type.isUnion():
+                    nativeType = CGUnionStruct.unionTypeDecl(m.type, True)
+                else:
+                    raise TypeError("Don't know how to declare member of type %s" %
+                                    m.type)
                 members.append(ClassMember(CGDictionary.makeMemberName(m.identifier.name),
                                nativeType,
                                visibility="private",
                                body="body"))
 
         parent = self.descriptor.interface.parent
         self.parentType = self.descriptor.getDescriptor(parent.identifier.name).nativeType.split('::')[-1]
         baseDeclarations=(
@@ -11668,16 +11709,19 @@ class CGEventClass(CGBindingImplClass):
         retVal = ""
         for m in self.descriptor.interface.members:
             if m.isAttr():
                 name = CGDictionary.makeMemberName(m.identifier.name)
                 if m.type.isAny():
                     retVal += "  NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(" + name + ")\n"
                 elif m.type.isObject() or m.type.isSpiderMonkeyInterface():
                     retVal += "  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(" + name + ")\n"
+                elif typeNeedsRooting(m.type):
+                    raise TypeError("Need to implement tracing for event "
+                                    "member of type %s" % m.type)
         return retVal
 
     def define(self):
         dropJS = ""
         for m in self.descriptor.interface.members:
             if m.isAttr():
                 member = CGDictionary.makeMemberName(m.identifier.name);
                 if m.type.isAny():