Bug 849567 - Automatically handle raw and already_AddRefed return values in Paris bindings and remove resultNotAddRefed, use templatized class to hold strong or weak pointer depending on the return type. r=bz.
authorPeter Van der Beken <peterv@propagandism.org>
Thu, 28 Aug 2014 00:43:56 +0200
changeset 204617 c848479c0127ad6139b246ff920749ee645ef8a7
parent 204616 2ce96b8dd847757bfa26ebecdab88ab2c4982097
child 204618 65a8e5b6c2ee7c52c69cc08b2955f4a707d83512
push id27463
push userryanvm@gmail.com
push dateThu, 11 Sep 2014 00:30:54 +0000
treeherdermozilla-central@bc7deafdac4b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs849567
milestone35.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 849567 - Automatically handle raw and already_AddRefed return values in Paris bindings and remove resultNotAddRefed, use templatized class to hold strong or weak pointer depending on the return type. r=bz.
dom/bindings/BindingUtils.h
dom/bindings/Codegen.py
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -2973,12 +2973,31 @@ WrappedJSToDictionary(nsISupports* aObje
     return false;
   }
 
   JSAutoCompartment ac(cx, obj);
   JS::Rooted<JS::Value> v(cx, OBJECT_TO_JSVAL(obj));
   return aDictionary.Init(cx, v);
 }
 
+
+template<class T, class S>
+inline nsRefPtr<T>
+StrongOrRawPtr(already_AddRefed<S>&& aPtr)
+{
+  return aPtr.template downcast<T>();
+}
+
+template<class T>
+inline T*
+StrongOrRawPtr(T* aPtr)
+{
+  return aPtr;
+}
+
+template<class T, template<typename> class SmartPtr, class S>
+inline void
+StrongOrRawPtr(SmartPtr<S>&& aPtr) MOZ_DELETE;
+
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_BindingUtils_h__ */
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -5919,146 +5919,151 @@ def dictionaryMatchesLambda(dictionary, 
 
 
 # Whenever this is modified, please update CGNativeMember.getRetvalInfo as
 # needed to keep the types compatible.
 def getRetvalDeclarationForType(returnType, descriptorProvider,
                                 resultAlreadyAddRefed,
                                 isMember=False):
     """
-    Returns a tuple containing four things:
+    Returns a tuple containing five things:
 
     1) A CGThing for the type of the return value, or None if there is no need
        for a return value.
 
     2) A value indicating the kind of ourparam to pass the value as.  Valid
        options are None to not pass as an out param at all, "ref" (to pass a
        reference as an out param), and "ptr" (to pass a pointer as an out
        param).
 
     3) A CGThing for a tracer for the return value, or None if no tracing is
        needed.
 
     4) An argument string to pass to the retval declaration
        constructor or None if there are no arguments.
+
+    5) The name of a function that needs to be called with the return value
+       before using it, or None if no function needs to be called.
     """
     if returnType is None or returnType.isVoid():
         # Nothing to declare
-        return None, None, None, None
+        return None, None, None, None, None
     if returnType.isPrimitive() and returnType.tag() in builtinNames:
         result = CGGeneric(builtinNames[returnType.tag()])
         if returnType.nullable():
             result = CGTemplatedType("Nullable", result)
-        return result, None, None, None
+        return result, None, None, None, None
     if returnType.isDOMString() or returnType.isScalarValueString():
         if isMember:
-            return CGGeneric("nsString"), "ref", None, None
-        return CGGeneric("DOMString"), "ref", None, None
+            return CGGeneric("nsString"), "ref", None, None, None
+        return CGGeneric("DOMString"), "ref", None, None, None
     if returnType.isByteString():
-        return CGGeneric("nsCString"), "ref", None, None
+        return CGGeneric("nsCString"), "ref", None, None, None
     if returnType.isEnum():
         result = CGGeneric(returnType.unroll().inner.identifier.name)
         if returnType.nullable():
             result = CGTemplatedType("Nullable", result)
-        return result, None, None, None
+        return result, None, None, None, None
     if returnType.isGeckoInterface():
         result = CGGeneric(descriptorProvider.getDescriptor(
             returnType.unroll().inner.identifier.name).nativeType)
+        conversion = None
         if descriptorProvider.getDescriptor(
                 returnType.unroll().inner.identifier.name).nativeOwnership == 'owned':
             result = CGTemplatedType("nsAutoPtr", result)
-        elif resultAlreadyAddRefed:
+        elif isMember:
             result = CGTemplatedType("nsRefPtr", result)
         else:
-            result = CGWrapper(result, post="*")
-        return result, None, None, None
+            conversion = CGGeneric("StrongOrRawPtr<%s>" % result.define())
+            result = CGGeneric("auto")
+        return result, None, None, None, conversion
     if returnType.isCallback():
         name = returnType.unroll().identifier.name
-        return CGGeneric("nsRefPtr<%s>" % name), None, None, None
+        return CGGeneric("nsRefPtr<%s>" % name), None, None, None, None
     if returnType.isAny():
         if isMember:
-            return CGGeneric("JS::Value"), None, None, None
-        return CGGeneric("JS::Rooted<JS::Value>"), "ptr", None, "cx"
+            return CGGeneric("JS::Value"), None, None, None, None
+        return CGGeneric("JS::Rooted<JS::Value>"), "ptr", None, "cx", None
     if returnType.isObject() or returnType.isSpiderMonkeyInterface():
         if isMember:
-            return CGGeneric("JSObject*"), None, None, None
-        return CGGeneric("JS::Rooted<JSObject*>"), "ptr", None, "cx"
+            return CGGeneric("JSObject*"), None, None, None, None
+        return CGGeneric("JS::Rooted<JSObject*>"), "ptr", None, "cx", None
     if returnType.isSequence():
         nullable = returnType.nullable()
         if nullable:
             returnType = returnType.inner
         # If our result is already addrefed, use the right type in the
         # sequence argument here.
-        result, _, _, _ = getRetvalDeclarationForType(returnType.inner,
-                                                      descriptorProvider,
-                                                      resultAlreadyAddRefed,
-                                                      isMember="Sequence")
+        result, _, _, _, _ = getRetvalDeclarationForType(returnType.inner,
+                                                         descriptorProvider,
+                                                         resultAlreadyAddRefed,
+                                                         isMember="Sequence")
         # While we have our inner type, set up our rooter, if needed
         if not isMember and typeNeedsRooting(returnType):
             rooter = CGGeneric("SequenceRooter<%s > resultRooter(cx, &result);\n" %
                                result.define())
         else:
             rooter = None
         result = CGTemplatedType("nsTArray", result)
         if nullable:
             result = CGTemplatedType("Nullable", result)
-        return result, "ref", rooter, None
+        return result, "ref", rooter, None, None
     if returnType.isMozMap():
         nullable = returnType.nullable()
         if nullable:
             returnType = returnType.inner
         # If our result is already addrefed, use the right type in the
         # MozMap argument here.
-        result, _, _, _ = getRetvalDeclarationForType(returnType.inner,
-                                                      descriptorProvider,
-                                                      resultAlreadyAddRefed,
-                                                      isMember="MozMap")
+        result, _, _, _, _ = getRetvalDeclarationForType(returnType.inner,
+                                                         descriptorProvider,
+                                                         resultAlreadyAddRefed,
+                                                         isMember="MozMap")
         # While we have our inner type, set up our rooter, if needed
         if not isMember and typeNeedsRooting(returnType):
             rooter = CGGeneric("MozMapRooter<%s> resultRooter(cx, &result);\n" %
                                result.define())
         else:
             rooter = None
         result = CGTemplatedType("MozMap", result)
         if nullable:
             result = CGTemplatedType("Nullable", result)
-        return result, "ref", rooter, None
+        return result, "ref", rooter, None, None
     if returnType.isDictionary():
         nullable = returnType.nullable()
         dictName = CGDictionary.makeDictionaryName(returnType.unroll().inner)
         result = CGGeneric(dictName)
         if not isMember and typeNeedsRooting(returnType):
             if nullable:
                 result = CGTemplatedType("NullableRootedDictionary", result)
             else:
                 result = CGTemplatedType("RootedDictionary", result)
             resultArgs = "cx"
         else:
             if nullable:
                 result = CGTemplatedType("Nullable", result)
             resultArgs = None
-        return result, "ref", None, resultArgs
+        return result, "ref", None, resultArgs, None
     if returnType.isUnion():
         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():
                 result = CGTemplatedType("Nullable", result)
             resultArgs = None
-        return result, "ref", None, resultArgs
+        return result, "ref", None, resultArgs, None
     if returnType.isDate():
         result = CGGeneric("Date")
         if returnType.nullable():
             result = CGTemplatedType("Nullable", result)
-        return result, None, None, None
+        return result, None, None, None, None
     raise TypeError("Don't know how to declare return value for %s" %
                     returnType)
 
 
 def isResultAlreadyAddRefed(extendedAttributes):
     return 'resultNotAddRefed' not in extendedAttributes
 
 
@@ -6099,17 +6104,17 @@ class CGCallGenerator(CGThing):
                  static, object="self", argsPost=[], resultVar=None):
         CGThing.__init__(self)
 
         assert errorReport is None or isinstance(errorReport, CGThing)
 
         isFallible = errorReport is not None
 
         resultAlreadyAddRefed = isResultAlreadyAddRefed(extendedAttributes)
-        result, resultOutParam, resultRooter, resultArgs = \
+        result, resultOutParam, resultRooter, resultArgs, resultConversion = \
             getRetvalDeclarationForType(
                 returnType, descriptorProvider, resultAlreadyAddRefed)
 
         args = CGList([CGGeneric(arg) for arg in argsPre], ", ")
         for a, name in arguments:
             arg = CGGeneric(name)
 
             # Now constify the things that need it
@@ -6164,34 +6169,39 @@ class CGCallGenerator(CGThing):
         args.extend(CGGeneric(arg) for arg in argsPost)
 
         # Build up our actual call
         self.cgRoot = CGList([])
 
         call = CGGeneric(nativeMethodName)
         if not static:
             call = CGWrapper(call, pre="%s->" % object)
-        call = CGList([call, CGWrapper(args, pre="(", post=");\n")])
+        call = CGList([call, CGWrapper(args, pre="(", post=")")])
+        if resultConversion is not None:
+            call = CGList([resultConversion, CGWrapper(call, pre="(", post=")")])
         if resultVar is None and result is not None:
             needResultDecl = True
             resultVar = "result"
 
         if needResultDecl:
             if resultRooter is not None:
                 self.cgRoot.prepend(resultRooter)
             if resultArgs is not None:
-                resultArgs = "(%s)" % resultArgs
-            else:
-                resultArgs = ""
-            result = CGWrapper(result, post=(" %s%s;\n" % (resultVar, resultArgs)))
-            self.cgRoot.prepend(result)
-            if not resultOutParam:
-                call = CGWrapper(call, pre=resultVar + " = ")
-
-        call = CGWrapper(call)
+                resultArgsStr = "(%s)" % resultArgs
+            else:
+                resultArgsStr = ""
+            result = CGWrapper(result, post=(" %s%s" % (resultVar, resultArgsStr)))
+            if resultOutParam is None and resultArgs is None:
+                call = CGList([result, CGWrapper(call, pre="(", post=")")])
+            else:
+                self.cgRoot.prepend(CGWrapper(result, post=";\n"))
+                if resultOutParam is None:
+                    call = CGWrapper(call, pre=resultVar + " = ")
+
+        call = CGWrapper(call, post=";\n")
         self.cgRoot.append(call)
 
         if isFallible:
             self.cgRoot.prepend(CGGeneric("ErrorResult rv;\n"))
             self.cgRoot.append(CGGeneric("rv.WouldReportJSException();\n"))
             self.cgRoot.append(CGGeneric("if (rv.Failed()) {\n"))
             self.cgRoot.append(CGIndenter(errorReport))
             self.cgRoot.append(CGGeneric("}\n"))
@@ -7707,19 +7717,19 @@ class CGSpecializedGetter(CGAbstractStat
                 CGGetterCall(self.attr.type, nativeName,
                              self.descriptor, self.attr).define())
 
     @staticmethod
     def makeNativeName(descriptor, attr):
         name = attr.identifier.name
         nativeName = MakeNativeName(descriptor.binaryNameFor(name))
         # resultOutParam does not depend on whether resultAlreadyAddRefed is set
-        _, resultOutParam, _, _ = getRetvalDeclarationForType(attr.type,
-                                                              descriptor,
-                                                              False)
+        _, resultOutParam, _, _, _ = getRetvalDeclarationForType(attr.type,
+                                                                 descriptor,
+                                                                 False)
         infallible = ('infallible' in
                       descriptor.getExtendedAttributes(attr, getter=True))
         if resultOutParam or attr.type.nullable() or not infallible:
             nativeName = "Get" + nativeName
         return nativeName
 
 
 class CGStaticGetter(CGAbstractStaticBindingMethod):