Bug 849567 - Automatically handle raw and already_AddRefed return values in Paris bindings and remove resultNotAddRefed, statically assert that we keep a strong reference to return values of NewObject methods. r=bz.
authorPeter Van der Beken <peterv@propagandism.org>
Thu, 28 Aug 2014 00:43:56 +0200
changeset 204618 65a8e5b6c2ee7c52c69cc08b2955f4a707d83512
parent 204617 c848479c0127ad6139b246ff920749ee645ef8a7
child 204619 9e0d430f66f3d23d8981bb96a7237197c32818c6
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, statically assert that we keep a strong reference to return values of NewObject methods. r=bz.
dom/bindings/Codegen.py
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -6564,23 +6564,27 @@ class CGPerSignatureCall(CGThing):
 
     def getArguments(self):
         return [(a, "arg" + str(i)) for i, a in enumerate(self.arguments)]
 
     def isFallible(self):
         return 'infallible' not in self.extendedAttributes
 
     def wrap_return_value(self):
+        wrapCode = ""
+
         returnsNewObject = memberReturnsNewObject(self.idlNode)
-        if returnsNewObject:
-            # We better be returning addrefed things!
-            assert(isResultAlreadyAddRefed(self.extendedAttributes) or
-                   # NewObject can return raw pointers to owned objects
-                   (self.returnType.isGeckoInterface() and
-                    self.descriptor.getDescriptor(self.returnType.unroll().inner.identifier.name).nativeOwnership == 'owned'))
+        if (returnsNewObject and
+            self.returnType.isGeckoInterface() and
+            not self.descriptor.getDescriptor(self.returnType.unroll().inner.identifier.name).nativeOwnership == 'owned'):
+            wrapCode += dedent(
+                """
+                static_assert(!IsPointer<decltype(result)>::value,
+                              "NewObject implies that we need to keep the object alive with a strong reference.");
+                """)
 
         setSlot = self.idlNode.isAttr() and self.idlNode.slotIndex is not None
         if setSlot:
             # For attributes in slots, we want to do some
             # post-processing once we've wrapped them.
             successCode = "break;\n"
         else:
             successCode = None
@@ -6588,17 +6592,17 @@ class CGPerSignatureCall(CGThing):
         resultTemplateValues = {
             'jsvalRef': 'args.rval()',
             'jsvalHandle': 'args.rval()',
             'returnsNewObject': returnsNewObject,
             'successCode': successCode,
             'obj': "reflector" if setSlot else "obj"
         }
         try:
-            wrapCode = wrapForType(self.returnType, self.descriptor, resultTemplateValues)
+            wrapCode += wrapForType(self.returnType, self.descriptor, resultTemplateValues)
         except MethodNotNewObjectError, err:
             assert not returnsNewObject
             raise TypeError("%s being returned from non-NewObject method or property %s.%s" %
                             (err.typename,
                              self.descriptor.interface.identifier.name,
                              self.idlNode.identifier.name))
         if setSlot:
             # We need to make sure that our initial wrapping is done in the
@@ -12245,17 +12249,17 @@ class CGNativeMember(ClassMethod):
             if self.resultAlreadyAddRefed:
                 if isMember:
                     holder = "nsRefPtr"
                 else:
                     holder = "already_AddRefed"
                 if memberReturnsNewObject(self.member) or isMember:
                     warning = ""
                 else:
-                    warning = "// Mark this as resultNotAddRefed to return raw pointers\n"
+                    warning = "// Return a raw pointer here to avoid refcounting, but make sure it's safe (the object should be kept alive by the callee).\n"
                 result = CGWrapper(result,
                                    pre=("%s%s<" % (warning, holder)),
                                    post=">")
             else:
                 result = CGWrapper(result, post="*")
             # Since we always force an owning type for callback return values,
             # our ${declName} is an OwningNonNull or nsRefPtr.  So we can just
             # .forget() to get our already_AddRefed.
@@ -13490,19 +13494,18 @@ class FakeMember():
 
     def isAttr(self):
         return False
 
     def isMethod(self):
         return False
 
     def getExtendedAttribute(self, name):
-        # Claim to be a [NewObject] so we can avoid the "mark this
-        # resultNotAddRefed" comments CGNativeMember codegen would
-        # otherwise stick in.
+        # Claim to be a [NewObject] so we can avoid the "return a raw pointer"
+        # comments CGNativeMember codegen would otherwise stick in.
         if name == "NewObject":
             return True
         return None
 
 
 class CallbackMember(CGNativeMember):
     def __init__(self, sig, name, descriptorProvider, needThisHandling,
                  rethrowContentException=False, typedArraysAreStructs=False):