Bug 1265770. Don't try to get a prototype for the interface object for an interface that's [NoInterfaceObject], since it's just unnecessary work that can't even be done at all in some cases (e.g. when the parent interface is also [NoInterfaceObject]). r=peterv
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 20 Apr 2016 18:04:56 -0400
changeset 332057 4b03e85de2207b0eb5af7dde859ed10f83f050cc
parent 332056 77721ee6f814ad33eb61cbcb9a0ae14f10c44432
child 332058 408ac64b72edd03b0b9f480d06787d03f90f07a0
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs1265770
milestone48.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 1265770. Don't try to get a prototype for the interface object for an interface that's [NoInterfaceObject], since it's just unnecessary work that can't even be done at all in some cases (e.g. when the parent interface is also [NoInterfaceObject]). r=peterv
dom/bindings/BindingUtils.cpp
dom/bindings/BindingUtils.h
dom/bindings/Codegen.py
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -877,16 +877,19 @@ CreateInterfaceObjects(JSContext* cx, JS
              "Must have name precisely when we have an interface object");
   MOZ_ASSERT(!constructorClass || !constructor);
   MOZ_ASSERT(!protoClass == !protoCache,
              "If, and only if, there is an interface prototype object we need "
              "to cache it");
   MOZ_ASSERT(!(constructorClass || constructor) == !constructorCache,
              "If, and only if, there is an interface object we need to cache "
              "it");
+  MOZ_ASSERT(constructorProto || (!constructorClass && !constructor),
+             "Must have a constructor proto if we plan to create a constructor "
+             "object");
 
   JS::Rooted<JSObject*> proto(cx);
   if (protoClass) {
     proto =
       CreateInterfacePrototypeObject(cx, global, protoProto, protoClass,
                                      properties, chromeOnlyProperties,
                                      unscopableNames);
     if (!proto) {
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -563,17 +563,19 @@ struct NamedConstructor
 
 /*
  * Create a DOM interface object (if constructorClass is non-null) and/or a
  * DOM interface prototype object (if protoClass is non-null).
  *
  * global is used as the parent of the interface object and the interface
  *        prototype object
  * protoProto is the prototype to use for the interface prototype object.
- * interfaceProto is the prototype to use for the interface object.
+ * interfaceProto is the prototype to use for the interface object.  This can be
+ *                null if both constructorClass and constructor are null (as in,
+ *                if we're not creating an interface object at all).
  * protoClass is the JSClass to use for the interface prototype object.
  *            This is null if we should not create an interface prototype
  *            object.
  * protoCache a pointer to a JSObject pointer where we should cache the
  *            interface prototype object. This must be null if protoClass is and
  *            vice versa.
  * constructorClass is the JSClass to use for the interface object.
  *                  This is null if we should not create an interface object or
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -2855,21 +2855,25 @@ class CGCreateInterfaceObjectsMethod(CGA
             protoClass = "nullptr"
             protoCache = "nullptr"
             parentProto = "nullptr"
             getParentProto = None
 
         if needInterfaceObject:
             interfaceClass = "&sInterfaceObjectClass.mBase"
             interfaceCache = "&aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::%s)" % self.descriptor.name
+            getConstructorProto = CGGeneric(getConstructorProto)
+            constructorProto = "constructorProto"
         else:
             # We don't have slots to store the named constructors.
             assert len(self.descriptor.interface.namedConstructors) == 0
             interfaceClass = "nullptr"
             interfaceCache = "nullptr"
+            getConstructorProto = None
+            constructorProto = "nullptr"
 
         isGlobal = self.descriptor.isGlobal() is not None
         if not isGlobal and self.properties.hasNonChromeOnly():
             properties = "sNativeProperties.Upcast()"
         else:
             properties = "nullptr"
         if not isGlobal and self.properties.hasChromeOnly():
             chromeProperties = "nsContentUtils::ThreadsafeIsCallerChrome() ? sChromeOnlyNativeProperties.Upcast() : nullptr"
@@ -2877,26 +2881,27 @@ class CGCreateInterfaceObjectsMethod(CGA
             chromeProperties = "nullptr"
 
         call = fill(
             """
             JS::Heap<JSObject*>* protoCache = ${protoCache};
             JS::Heap<JSObject*>* interfaceCache = ${interfaceCache};
             dom::CreateInterfaceObjects(aCx, aGlobal, ${parentProto},
                                         ${protoClass}, protoCache,
-                                        constructorProto, ${interfaceClass}, ${constructHookHolder}, ${constructArgs}, ${namedConstructors},
+                                        ${constructorProto}, ${interfaceClass}, ${constructHookHolder}, ${constructArgs}, ${namedConstructors},
                                         interfaceCache,
                                         ${properties},
                                         ${chromeProperties},
                                         ${name}, aDefineOnGlobal,
                                         ${unscopableNames});
             """,
             protoClass=protoClass,
             parentProto=parentProto,
             protoCache=protoCache,
+            constructorProto=constructorProto,
             interfaceClass=interfaceClass,
             constructHookHolder=constructHookHolder,
             constructArgs=constructArgs,
             namedConstructors=namedConstructors,
             interfaceCache=interfaceCache,
             properties=properties,
             chromeProperties=chromeProperties,
             name='"' + self.descriptor.interface.identifier.name + '"' if needInterfaceObject else "nullptr",
@@ -3063,17 +3068,17 @@ class CGCreateInterfaceObjectsMethod(CGA
                 }
                 """,
                 protoCache=protoCache,
                 failureCode=failureCode))
         else:
             makeProtoPrototypeImmutable = None
 
         return CGList(
-            [getParentProto, CGGeneric(getConstructorProto), initIds,
+            [getParentProto, getConstructorProto, initIds,
              prefCache, CGGeneric(call), defineAliases, unforgeableHolderSetup,
              speciesSetup, makeProtoPrototypeImmutable],
             "\n").define()
 
 
 class CGGetPerInterfaceObject(CGAbstractMethod):
     """
     A method for getting a per-interface object (a prototype object or interface