Bug 1037564 Part 2: Replace AutoPushJSContexts et al. in nsXBLPrototypeHandler. r=bholley
authorBob Owen <bobowencode@gmail.com>
Fri, 18 Jul 2014 12:52:32 +0100
changeset 217173 27ca85defc8d96775a6f974c9b635b1ecb4e4cfe
parent 217172 0ce58071a3321a3338f903bbbd0c6d18330c9203
child 217174 4e6f6f7d7753b3480203ae1c343795afabee1a47
push id515
push userraliiev@mozilla.com
push dateMon, 06 Oct 2014 12:51:51 +0000
treeherdermozilla-release@267c7a481bef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs1037564
milestone33.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 1037564 Part 2: Replace AutoPushJSContexts et al. in nsXBLPrototypeHandler. r=bholley
dom/base/ScriptSettings.h
dom/xbl/nsXBLPrototypeHandler.cpp
dom/xbl/nsXBLPrototypeHandler.h
js/xpconnect/src/nsCxPusher.cpp
js/xpconnect/src/nsCxPusher.h
--- a/dom/base/ScriptSettings.h
+++ b/dom/base/ScriptSettings.h
@@ -163,20 +163,21 @@ public:
   bool Init(nsGlobalWindow* aWindow);
   bool Init(nsGlobalWindow* aWindow, JSContext* aCx);
 
   bool InitWithLegacyErrorReporting(nsPIDOMWindow* aWindow);
   bool InitWithLegacyErrorReporting(nsGlobalWindow* aWindow);
 
   JSContext* cx() const {
     MOZ_ASSERT(mCx, "Must call Init before using an AutoJSAPI");
+    MOZ_ASSERT_IF(NS_IsMainThread(), CxPusherIsStackTop());
     return mCx;
   }
 
-  bool CxPusherIsStackTop() { return mCxPusher.ref().IsStackTop(); }
+  bool CxPusherIsStackTop() const { return mCxPusher.ref().IsStackTop(); }
 
 protected:
   // Protected constructor, allowing subclasses to specify a particular cx to
   // be used. This constructor initialises the AutoJSAPI, so Init must NOT be
   // called on subclasses that use this.
   // If aGlobalObject, its associated JS global or aCx are null this will cause
   // an assertion, as will setting aIsMainThread incorrectly.
   AutoJSAPI(nsIGlobalObject* aGlobalObject, bool aIsMainThread, JSContext* aCx);
--- a/dom/xbl/nsXBLPrototypeHandler.cpp
+++ b/dom/xbl/nsXBLPrototypeHandler.cpp
@@ -5,22 +5,22 @@
 
 #include "mozilla/ArrayUtils.h"
 
 #include "nsCOMPtr.h"
 #include "nsXBLPrototypeHandler.h"
 #include "nsXBLPrototypeBinding.h"
 #include "nsContentUtils.h"
 #include "nsCxPusher.h"
+#include "nsGlobalWindow.h"
 #include "nsIContent.h"
 #include "nsIAtom.h"
 #include "nsIDOMKeyEvent.h"
 #include "nsIDOMMouseEvent.h"
 #include "nsNameSpaceManager.h"
-#include "nsIScriptContext.h"
 #include "nsIDocument.h"
 #include "nsIController.h"
 #include "nsIControllers.h"
 #include "nsIDOMXULElement.h"
 #include "nsIURI.h"
 #include "nsIDOMHTMLTextAreaElement.h"
 #include "nsIDOMHTMLInputElement.h"
 #include "nsFocusManager.h"
@@ -41,16 +41,18 @@
 #include "nsCRT.h"
 #include "nsXBLEventHandler.h"
 #include "nsXBLSerialize.h"
 #include "nsJSUtils.h"
 #include "mozilla/BasicEvents.h"
 #include "mozilla/JSEventHandler.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/EventHandlerBinding.h"
+#include "mozilla/dom/ScriptSettings.h"
+#include "xpcpublic.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 uint32_t nsXBLPrototypeHandler::gRefCnt = 0;
 
 int32_t nsXBLPrototypeHandler::kMenuAccessKey = -1;
 
@@ -254,38 +256,35 @@ nsXBLPrototypeHandler::ExecuteHandler(Ev
     }
 
     boundGlobal = do_QueryInterface(boundDocument->GetScopeObject());
   }
 
   if (!boundGlobal)
     return NS_OK;
 
-  nsIScriptContext *boundContext = boundGlobal->GetScriptContext();
-  if (!boundContext)
-    return NS_OK;
-
   nsISupports *scriptTarget;
 
   if (winRoot) {
     scriptTarget = boundGlobal;
   } else {
     scriptTarget = aTarget;
   }
 
-  // We're about to create a new JSEventHandler, which means that we're
-  // responsible for pushing the context of the event target. See the similar
-  // comment in nsEventManagerListener.cpp.
-  nsCxPusher pusher;
-  NS_ENSURE_STATE(pusher.Push(aTarget));
-
-  AutoPushJSContext cx(boundContext->GetNativeContext());
+  // We're about to create a new JSEventHandler, which means that we need to
+  // Initiatize an AutoJSAPI with aTarget's bound global to make sure any errors
+  // are reported to the correct place.
+  AutoJSAPI jsapi;
+  if (NS_WARN_IF(!jsapi.InitWithLegacyErrorReporting(boundGlobal))) {
+    return NS_OK;
+  }
+  JSContext* cx = jsapi.cx();
   JS::Rooted<JSObject*> handler(cx);
 
-  rv = EnsureEventHandler(boundGlobal, boundContext, onEventAtom, &handler);
+  rv = EnsureEventHandler(jsapi, onEventAtom, &handler);
   NS_ENSURE_SUCCESS(rv, rv);
 
   JSAddonId* addonId = MapURIToAddonID(mPrototypeBinding->DocURI());
 
   JS::Rooted<JSObject*> globalObject(cx, boundGlobal->GetGlobalJSObject());
   JS::Rooted<JSObject*> scopeObject(cx, xpc::GetScopeForXBLExecution(cx, globalObject, addonId));
   NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY);
 
@@ -333,42 +332,40 @@ nsXBLPrototypeHandler::ExecuteHandler(Ev
 
   // Handle the event.
   jsEventHandler->HandleEvent(aEvent);
   jsEventHandler->Disconnect();
   return NS_OK;
 }
 
 nsresult
-nsXBLPrototypeHandler::EnsureEventHandler(nsIScriptGlobalObject* aGlobal,
-                                          nsIScriptContext *aBoundContext,
-                                          nsIAtom *aName,
+nsXBLPrototypeHandler::EnsureEventHandler(AutoJSAPI& jsapi, nsIAtom* aName,
                                           JS::MutableHandle<JSObject*> aHandler)
 {
-  AutoPushJSContext cx(aBoundContext->GetNativeContext());
+  JSContext* cx = jsapi.cx();
 
   // Check to see if we've already compiled this
-  nsCOMPtr<nsPIDOMWindow> pWindow = do_QueryInterface(aGlobal);
+  JS::Rooted<JSObject*> globalObject(cx, JS::CurrentGlobalOrNull(cx));
+  nsCOMPtr<nsPIDOMWindow> pWindow = xpc::WindowOrNull(globalObject);
   if (pWindow) {
     JS::Rooted<JSObject*> cachedHandler(cx, pWindow->GetCachedXBLPrototypeHandler(this));
     if (cachedHandler) {
       JS::ExposeObjectToActiveJS(cachedHandler);
       aHandler.set(cachedHandler);
       NS_ENSURE_TRUE(aHandler, NS_ERROR_FAILURE);
       return NS_OK;
     }
   }
 
   // Ensure that we have something to compile
   nsDependentString handlerText(mHandlerText);
   NS_ENSURE_TRUE(!handlerText.IsEmpty(), NS_ERROR_FAILURE);
 
   JSAddonId* addonId = MapURIToAddonID(mPrototypeBinding->DocURI());
 
-  JS::Rooted<JSObject*> globalObject(cx, aGlobal->GetGlobalJSObject());
   JS::Rooted<JSObject*> scopeObject(cx, xpc::GetScopeForXBLExecution(cx, globalObject, addonId));
   NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY);
 
   nsAutoCString bindingURI;
   mPrototypeBinding->DocURI()->GetSpec(bindingURI);
 
   uint32_t argCount;
   const char **argNames;
--- a/dom/xbl/nsXBLPrototypeHandler.h
+++ b/dom/xbl/nsXBLPrototypeHandler.h
@@ -8,31 +8,31 @@
 
 #include "nsIAtom.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsIController.h"
 #include "nsAutoPtr.h"
 #include "nsXBLEventHandler.h"
 #include "nsIWeakReference.h"
-#include "nsIScriptGlobalObject.h"
 #include "nsCycleCollectionParticipant.h"
 #include "js/TypeDecls.h"
 
 class nsIDOMEvent;
 class nsIContent;
 class nsIDOMUIEvent;
 class nsIDOMKeyEvent;
 class nsIDOMMouseEvent;
 class nsIObjectInputStream;
 class nsIObjectOutputStream;
 class nsXBLPrototypeBinding;
 
 namespace mozilla {
 namespace dom {
+class AutoJSAPI;
 class EventTarget;
 }
 }
 
 #define NS_HANDLER_TYPE_XBL_JS              (1 << 0)
 #define NS_HANDLER_TYPE_XBL_COMMAND         (1 << 1)
 #define NS_HANDLER_TYPE_XUL                 (1 << 2)
 #define NS_HANDLER_HAS_ALLOW_UNTRUSTED_ATTR (1 << 4)
@@ -161,18 +161,17 @@ protected:
                           const char16_t* aAllowUntrusted=nullptr);
 
   void ReportKeyConflict(const char16_t* aKey, const char16_t* aModifiers, nsIContent* aElement, const char *aMessageName);
   void GetEventType(nsAString& type);
   bool ModifiersMatchMask(nsIDOMUIEvent* aEvent,
                             bool aIgnoreShiftKey = false);
   nsresult DispatchXBLCommand(mozilla::dom::EventTarget* aTarget, nsIDOMEvent* aEvent);
   nsresult DispatchXULKeyCommand(nsIDOMEvent* aEvent);
-  nsresult EnsureEventHandler(nsIScriptGlobalObject* aGlobal,
-                              nsIScriptContext *aBoundContext, nsIAtom *aName,
+  nsresult EnsureEventHandler(mozilla::dom::AutoJSAPI& jsapi, nsIAtom* aName,
                               JS::MutableHandle<JSObject*> aHandler);
   static int32_t KeyToMask(int32_t key);
   static int32_t AccelKeyMask();
 
   static int32_t kMenuAccessKey;
   static void InitAccessKeys();
 
   static const int32_t cShift;
--- a/js/xpconnect/src/nsCxPusher.cpp
+++ b/js/xpconnect/src/nsCxPusher.cpp
@@ -156,17 +156,17 @@ AutoCxPusher::~AutoCxPusher()
                                 js::GetEnterCompartmentDepth(mPushedContext));
   DebugOnly<JSContext*> stackTop;
   MOZ_ASSERT(mPushedContext == nsXPConnect::XPConnect()->GetCurrentJSContext());
   XPCJSRuntime::Get()->GetJSContextStack()->Pop();
   mScx = nullptr;
 }
 
 bool
-AutoCxPusher::IsStackTop()
+AutoCxPusher::IsStackTop() const
 {
   uint32_t currentDepth = XPCJSRuntime::Get()->GetJSContextStack()->Count();
   MOZ_ASSERT(currentDepth >= mStackDepthAfterPush);
   return currentDepth == mStackDepthAfterPush;
 }
 
 AutoJSContext::AutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
   : mCx(nullptr)
--- a/js/xpconnect/src/nsCxPusher.h
+++ b/js/xpconnect/src/nsCxPusher.h
@@ -31,17 +31,17 @@ public:
   AutoCxPusher(JSContext *aCx, bool aAllowNull = false);
   // XPCShell uses an nsCxPusher, which contains an AutoCxPusher.
   ~AutoCxPusher();
 
   nsIScriptContext* GetScriptContext() { return mScx; }
 
   // Returns true if this AutoCxPusher performed the push that is currently at
   // the top of the cx stack.
-  bool IsStackTop();
+  bool IsStackTop() const;
 
 private:
   mozilla::Maybe<JSAutoRequest> mAutoRequest;
   mozilla::Maybe<JSAutoCompartment> mAutoCompartment;
   nsCOMPtr<nsIScriptContext> mScx;
   uint32_t mStackDepthAfterPush;
 #ifdef DEBUG
   JSContext* mPushedContext;