Bug 1148593 - Pass JSContext to CallbackObject constructor. r=bz
authorTom Tromey <tromey@mozilla.com>
Fri, 24 Jul 2015 07:00:00 -0400
changeset 254787 e741b5a17b192176055856daad38ab4a424eaf36
parent 254786 7845b333c6198ea8db3599f84fb49f37fa0348f1
child 254788 01675d5848735f8c8fe41715c1ac0bac279dc0b1
push id16720
push userryanvm@gmail.com
push dateMon, 27 Jul 2015 19:45:38 +0000
treeherderb2g-inbound@13354b414396 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1148593
milestone42.0a1
Bug 1148593 - Pass JSContext to CallbackObject constructor. r=bz
dom/base/nsGlobalWindow.cpp
dom/bindings/CallbackFunction.h
dom/bindings/CallbackInterface.h
dom/bindings/CallbackObject.h
dom/bindings/Codegen.py
dom/events/DOMEventTargetHelper.cpp
dom/events/EventListenerManager.cpp
dom/promise/Promise.cpp
dom/xbl/nsXBLPrototypeHandler.cpp
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -5548,17 +5548,17 @@ nsGlobalWindow::RequestAnimationFrame(JS
 {
   FORWARD_TO_INNER(RequestAnimationFrame, (aCallback, cx, aHandle), NS_ERROR_UNEXPECTED);
   if (!aCallback.isObject() || !JS::IsCallable(&aCallback.toObject())) {
     return NS_ERROR_INVALID_ARG;
   }
 
   JS::Rooted<JSObject*> callbackObj(cx, &aCallback.toObject());
   nsRefPtr<FrameRequestCallback> callback =
-    new FrameRequestCallback(callbackObj, GetIncumbentGlobal());
+    new FrameRequestCallback(cx, callbackObj, GetIncumbentGlobal());
 
   ErrorResult rv;
   *aHandle = RequestAnimationFrame(*callback, rv);
 
   return rv.StealNSResult();
 }
 
 void
--- a/dom/bindings/CallbackFunction.h
+++ b/dom/bindings/CallbackFunction.h
@@ -20,19 +20,20 @@
 #include "mozilla/dom/CallbackObject.h"
 
 namespace mozilla {
 namespace dom {
 
 class CallbackFunction : public CallbackObject
 {
 public:
-  explicit CallbackFunction(JS::Handle<JSObject*> aCallable,
+  // See CallbackObject for an explanation of the arguments.
+  explicit CallbackFunction(JSContext* aCx, JS::Handle<JSObject*> aCallable,
                             nsIGlobalObject* aIncumbentGlobal)
-    : CallbackObject(aCallable, aIncumbentGlobal)
+    : CallbackObject(aCx, aCallable, aIncumbentGlobal)
   {
   }
 
   JS::Handle<JSObject*> Callable() const
   {
     return Callback();
   }
 
--- a/dom/bindings/CallbackInterface.h
+++ b/dom/bindings/CallbackInterface.h
@@ -19,19 +19,20 @@
 #include "mozilla/dom/CallbackObject.h"
 
 namespace mozilla {
 namespace dom {
 
 class CallbackInterface : public CallbackObject
 {
 public:
-  explicit CallbackInterface(JS::Handle<JSObject*> aCallback,
+  // See CallbackObject for an explanation of the arguments.
+  explicit CallbackInterface(JSContext* aCx, JS::Handle<JSObject*> aCallback,
                              nsIGlobalObject *aIncumbentGlobal)
-    : CallbackObject(aCallback, aIncumbentGlobal)
+    : CallbackObject(aCx, aCallback, aIncumbentGlobal)
   {
   }
 
 protected:
   bool GetCallableProperty(JSContext* cx, JS::Handle<jsid> aPropId,
                            JS::MutableHandle<JS::Value> aCallable);
 
 };
--- a/dom/bindings/CallbackObject.h
+++ b/dom/bindings/CallbackObject.h
@@ -44,18 +44,22 @@ public:
   NS_DECLARE_STATIC_IID_ACCESSOR(DOM_CALLBACKOBJECT_IID)
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CallbackObject)
 
   // The caller may pass a global object which will act as an override for the
   // incumbent script settings object when the callback is invoked (overriding
   // the entry point computed from aCallback). If no override is required, the
-  // caller should pass null.
-  explicit CallbackObject(JS::Handle<JSObject*> aCallback, nsIGlobalObject *aIncumbentGlobal)
+  // caller should pass null.  |aCx| is used to capture the current
+  // stack, which is later used as an async parent when the callback
+  // is invoked.  aCx can be nullptr, in which case no stack is
+  // captured.
+  explicit CallbackObject(JSContext* aCx, JS::Handle<JSObject*> aCallback,
+                          nsIGlobalObject *aIncumbentGlobal)
   {
     Init(aCallback, aIncumbentGlobal);
   }
 
   JS::Handle<JSObject*> Callback() const
   {
     JS::ExposeObjectToActiveJS(mCallback);
     return CallbackPreserveColor();
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -3971,17 +3971,17 @@ class FailureFatalCastableObjectUnwrappe
             isCallbackReturnValue)
 
 
 class CGCallbackTempRoot(CGGeneric):
     def __init__(self, name):
         define = dedent("""
             { // Scope for tempRoot
               JS::Rooted<JSObject*> tempRoot(cx, &${val}.toObject());
-              ${declName} = new %s(tempRoot, mozilla::dom::GetIncumbentGlobal());
+              ${declName} = new %s(cx, tempRoot, mozilla::dom::GetIncumbentGlobal());
             }
             """) % name
         CGGeneric.__init__(self, define=define)
 
 
 class JSToNativeConversionInfo():
     """
     An object representing information about a JS-to-native conversion.
@@ -13903,17 +13903,17 @@ class CGJSImplClass(CGBindingImplClass):
             decorators = ""
             # We need a protected virtual destructor our subclasses can use
             destructor = ClassDestructor(virtual=True, visibility="protected")
         else:
             decorators = "final"
             destructor = ClassDestructor(virtual=False, visibility="private")
 
         baseConstructors = [
-            ("mImpl(new %s(aJSImplObject, /* aIncumbentGlobal = */ nullptr))" %
+            ("mImpl(new %s(nullptr, aJSImplObject, /* aIncumbentGlobal = */ nullptr))" %
              jsImplName(descriptor.name)),
             "mParent(aParent)"]
         parentInterface = descriptor.interface.parent
         while parentInterface:
             if parentInterface.isJSImplemented():
                 baseConstructors.insert(
                     0, "%s(aJSImplObject, aParent)" % parentClass)
                 break
@@ -14048,23 +14048,24 @@ class CGCallback(CGClass):
         if (not self.idlObject.isInterface() and
             not self.idlObject._treatNonObjectAsNull):
             body = "MOZ_ASSERT(JS::IsCallable(mCallback));\n"
         else:
             # Not much we can assert about it, other than not being null, and
             # CallbackObject does that already.
             body = ""
         return [ClassConstructor(
-            [Argument("JS::Handle<JSObject*>", "aCallback"),
+            [Argument("JSContext*", "aCx"),
+             Argument("JS::Handle<JSObject*>", "aCallback"),
              Argument("nsIGlobalObject*", "aIncumbentGlobal")],
             bodyInHeader=True,
             visibility="public",
             explicit=True,
             baseConstructors=[
-                "%s(aCallback, aIncumbentGlobal)" % self.baseName,
+                "%s(aCx, aCallback, aIncumbentGlobal)" % self.baseName,
             ],
             body=body)]
 
     def getMethodImpls(self, method):
         assert method.needThisHandling
         args = list(method.args)
         # Strip out the JSContext*/JSObject* args
         # that got added.
--- a/dom/events/DOMEventTargetHelper.cpp
+++ b/dom/events/DOMEventTargetHelper.cpp
@@ -282,17 +282,17 @@ DOMEventTargetHelper::DispatchTrustedEve
 nsresult
 DOMEventTargetHelper::SetEventHandler(nsIAtom* aType,
                                       JSContext* aCx,
                                       const JS::Value& aValue)
 {
   nsRefPtr<EventHandlerNonNull> handler;
   JS::Rooted<JSObject*> callable(aCx);
   if (aValue.isObject() && JS::IsCallable(callable = &aValue.toObject())) {
-    handler = new EventHandlerNonNull(callable, dom::GetIncumbentGlobal());
+    handler = new EventHandlerNonNull(aCx, callable, dom::GetIncumbentGlobal());
   }
   SetEventHandler(aType, EmptyString(), handler);
   return NS_OK;
 }
 
 void
 DOMEventTargetHelper::GetEventHandler(nsIAtom* aType,
                                       JSContext* aCx,
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -948,25 +948,25 @@ EventListenerManager::CompileEventHandle
   result = nsJSUtils::CompileFunction(jsapi, scopeChain, options,
                                       nsAtomCString(typeAtom),
                                       argCount, argNames, *body, handler.address());
   NS_ENSURE_SUCCESS(result, result);
   NS_ENSURE_TRUE(handler, NS_ERROR_FAILURE);
 
   if (jsEventHandler->EventName() == nsGkAtoms::onerror && win) {
     nsRefPtr<OnErrorEventHandlerNonNull> handlerCallback =
-      new OnErrorEventHandlerNonNull(handler, /* aIncumbentGlobal = */ nullptr);
+      new OnErrorEventHandlerNonNull(nullptr, handler, /* aIncumbentGlobal = */ nullptr);
     jsEventHandler->SetHandler(handlerCallback);
   } else if (jsEventHandler->EventName() == nsGkAtoms::onbeforeunload && win) {
     nsRefPtr<OnBeforeUnloadEventHandlerNonNull> handlerCallback =
-      new OnBeforeUnloadEventHandlerNonNull(handler, /* aIncumbentGlobal = */ nullptr);
+      new OnBeforeUnloadEventHandlerNonNull(nullptr, handler, /* aIncumbentGlobal = */ nullptr);
     jsEventHandler->SetHandler(handlerCallback);
   } else {
     nsRefPtr<EventHandlerNonNull> handlerCallback =
-      new EventHandlerNonNull(handler, /* aIncumbentGlobal = */ nullptr);
+      new EventHandlerNonNull(nullptr, handler, /* aIncumbentGlobal = */ nullptr);
     jsEventHandler->SetHandler(handlerCallback);
   }
 
   return result;
 }
 
 nsresult
 EventListenerManager::HandleEventSubType(Listener* aListener,
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -1307,17 +1307,17 @@ Promise::ResolveInternal(JSContext* aCx,
         nsRefPtr<PromiseCallback> rejectCb = new RejectPromiseCallback(this, glob);
         nsRefPtr<FastThenableResolverTask> task =
           new FastThenableResolverTask(resolveCb, rejectCb, nextPromise);
         DispatchToMicroTask(task);
         return;
       }
 
       nsRefPtr<PromiseInit> thenCallback =
-        new PromiseInit(thenObj, mozilla::dom::GetIncumbentGlobal());
+        new PromiseInit(nullptr, thenObj, mozilla::dom::GetIncumbentGlobal());
       nsRefPtr<ThenableResolverTask> task =
         new ThenableResolverTask(this, valueObj, thenCallback);
       DispatchToMicroTask(task);
       return;
     }
   }
 
   MaybeSettle(aValue, Resolved);
--- a/dom/xbl/nsXBLPrototypeHandler.cpp
+++ b/dom/xbl/nsXBLPrototypeHandler.cpp
@@ -311,17 +311,17 @@ nsXBLPrototypeHandler::ExecuteHandler(Ev
   NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
 
   // Next, clone the generic handler with our desired scope chain.
   JS::Rooted<JSObject*> bound(cx, JS::CloneFunctionObject(cx, genericHandler,
                                                           scopeChain));
   NS_ENSURE_TRUE(bound, NS_ERROR_FAILURE);
 
   nsRefPtr<EventHandlerNonNull> handlerCallback =
-    new EventHandlerNonNull(bound, /* aIncumbentGlobal = */ nullptr);
+    new EventHandlerNonNull(nullptr, bound, /* aIncumbentGlobal = */ nullptr);
 
   TypedEventHandler typedHandler(handlerCallback);
 
   // Execute it.
   nsCOMPtr<JSEventHandler> jsEventHandler;
   rv = NS_NewJSEventHandler(scriptTarget, onEventAtom,
                             typedHandler,
                             getter_AddRefs(jsEventHandler));