Bug 949264 - Part 2: Support union members in generated events. r=smaug, a=1.3+
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 12 Dec 2013 16:11:55 -0500
changeset 174992 bdd7de70155cba3f240bbcc2c600b141dad606b7
parent 174991 5ee1b0c4fc4242a5f3d08a285732d50e80a310ec
child 174993 a224f09028eaf6e770b35c16e8fa09066961bae0
push id3224
push userlsblakk@mozilla.com
push dateTue, 04 Feb 2014 01:06:49 +0000
treeherdermozilla-beta@60c04d0987f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, 1
bugs949264
milestone28.0a2
Bug 949264 - Part 2: Support union members in generated events. r=smaug, a=1.3+
dom/bindings/Codegen.py
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -3292,17 +3292,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),
@@ -4724,17 +4724,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():
@@ -6906,17 +6906,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")],
@@ -6965,16 +6965,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()
@@ -11487,16 +11521,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)
 
@@ -11636,16 +11672,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=(
@@ -11697,16 +11738,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():