Bug 899367 - Stop depending on the default compartment object for DOM JSContexts. r=mccr8
authorBobby Holley <bobbyholley@gmail.com>
Wed, 04 Sep 2013 14:06:55 -0700
changeset 145509 14df512b792aeb64e3608f4e4de70151a411f354
parent 145508 6ca662ba7c557d378bd2641dc737c5c031ba9e58
child 145510 8e4bd1c50df4797665d2b056b3117220de3af10b
push id33304
push userbobbyholley@gmail.com
push dateWed, 04 Sep 2013 21:07:07 +0000
treeherdermozilla-inbound@dd6d206a9a8a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8
bugs899367
milestone26.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 899367 - Stop depending on the default compartment object for DOM JSContexts. r=mccr8
dom/base/nsDOMJSUtils.h
dom/base/nsJSUtils.cpp
js/jsd/jsd_xpc.cpp
js/xpconnect/src/XPCJSContextStack.cpp
js/xpconnect/src/nsCxPusher.cpp
--- a/dom/base/nsDOMJSUtils.h
+++ b/dom/base/nsDOMJSUtils.h
@@ -23,16 +23,18 @@ GetScriptContextFromJSContext(JSContext 
     do_QueryInterface(static_cast<nsISupports *>
                                  (::JS_GetContextPrivate(cx)));
 
   // This will return a pointer to something that's about to be
   // released, but that's ok here.
   return scx;
 }
 
+JSObject* GetDefaultScopeFromJSContext(JSContext *cx);
+
 // A factory function for turning a JS::Value argv into an nsIArray
 // but also supports an effecient way of extracting the original argv.
 // Bug 312003 describes why this must be "void *", but argv will be cast to
 // JS::Value* and the args are found at:
 //    ((JS::Value*)aArgv)[0], ..., ((JS::Value*)aArgv)[aArgc - 1]
 // The resulting object will take a copy of the array, and ensure each
 // element is rooted.
 // Optionally, aArgv may be NULL, in which case the array is allocated and
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -9,16 +9,17 @@
  * invoked from the JavaScript code generated from IDL interfaces.
  * The goal of the utility functions is to cut down on the size of
  * the generated code itself.
  */
 
 #include "nsJSUtils.h"
 #include "jsapi.h"
 #include "js/OldDebugAPI.h"
+#include "jsfriendapi.h"
 #include "nsIScriptContext.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIXPConnect.h"
 #include "nsCOMPtr.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsPIDOMWindow.h"
 #include "GeckoProfiler.h"
 #include "nsDOMJSUtils.h" // for GetScriptContextFromJSContext
@@ -135,17 +136,21 @@ nsJSUtils::GetCurrentlyRunningCodeInnerW
 }
 
 void
 nsJSUtils::ReportPendingException(JSContext *aContext)
 {
   if (JS_IsExceptionPending(aContext)) {
     bool saved = JS_SaveFrameChain(aContext);
     {
-      JSAutoCompartment ac(aContext, js::DefaultObjectForContextOrNull(aContext));
+      nsIScriptContext* scx = GetScriptContextFromJSContext(aContext);
+      JS::Rooted<JSObject*> scope(aContext);
+      scope = scx ? scx->GetNativeGlobal()
+                  : js::DefaultObjectForContextOrNull(aContext);
+      JSAutoCompartment ac(aContext, scope);
       JS_ReportPendingException(aContext);
     }
     if (saved) {
       JS_RestoreFrameChain(aContext);
     }
   }
 }
 
@@ -282,8 +287,24 @@ nsJSUtils::EvaluateString(JSContext* aCx
     }
   }
 
   // Wrap the return value into whatever compartment aCx was in.
   if (aRetValue && !JS_WrapValue(aCx, aRetValue))
     return NS_ERROR_OUT_OF_MEMORY;
   return rv;
 }
+
+//
+// nsDOMJSUtils.h
+//
+
+JSObject* GetDefaultScopeFromJSContext(JSContext *cx)
+{
+  // DOM JSContexts don't store their default compartment object on
+  // the cx, so in those cases we need to fetch it via the scx
+  // instead.
+  nsIScriptContext *scx = GetScriptContextFromJSContext(cx);
+  if (scx) {
+    return scx->GetNativeGlobal();
+  }
+  return js::DefaultObjectForContextOrNull(cx);
+}
--- a/js/jsd/jsd_xpc.cpp
+++ b/js/jsd/jsd_xpc.cpp
@@ -25,16 +25,17 @@
 #include "jsdebug.h"
 #include "nsReadableUtils.h"
 #include "nsCRT.h"
 #include "nsCycleCollectionParticipant.h"
 #include "mozilla/Attributes.h"
 
 /* XXX DOM dependency */
 #include "nsIScriptContext.h"
+#include "nsDOMJSUtils.h"
 #include "SandboxPrivate.h"
 #include "nsJSPrincipals.h"
 #include "nsContentUtils.h"
 #include "nsCxPusher.h"
 
 using mozilla::AutoSafeJSContext;
 using mozilla::AutoPushJSContext;
 
@@ -1691,17 +1692,17 @@ jsdContext::GetTag(uint32_t *_rval)
     *_rval = mTag;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 jsdContext::GetGlobalObject (jsdIValue **_rval)
 {
     ASSERT_VALID_EPHEMERAL;
-    JSObject *glob = js::DefaultObjectForContextOrNull(mJSCx);
+    JSObject *glob = GetDefaultScopeFromJSContext(mJSCx);
     JSDValue *jsdv = JSD_NewValue (mJSDCx, OBJECT_TO_JSVAL(glob));
     if (!jsdv)
         return NS_ERROR_FAILURE;
     *_rval = jsdValue::FromPtr (mJSDCx, jsdv);
     if (!*_rval)
         return NS_ERROR_FAILURE;
     return NS_OK;
 }
--- a/js/xpconnect/src/XPCJSContextStack.cpp
+++ b/js/xpconnect/src/XPCJSContextStack.cpp
@@ -65,20 +65,24 @@ XPCJSContextStack::Push(JSContext *cx)
 
     XPCJSContextInfo &e = mStack[mStack.Length() - 1];
     if (e.cx) {
         // The cx we're pushing is also stack-top. In general we still need to
         // call JS_SaveFrameChain here. But if that would put us in a
         // compartment that's same-origin with the current one, we can skip it.
         nsIScriptSecurityManager* ssm = XPCWrapper::GetSecurityManager();
         if ((e.cx == cx) && ssm) {
-            RootedObject defaultGlobal(cx, js::DefaultObjectForContextOrNull(cx));
+            // DOM JSContexts don't store their default compartment object on
+            // the cx, so in those cases we need to fetch it via the scx
+            // instead.
+            RootedObject defaultScope(cx, GetDefaultScopeFromJSContext(cx));
+
             nsIPrincipal *currentPrincipal =
               GetCompartmentPrincipal(js::GetContextCompartment(cx));
-            nsIPrincipal *defaultPrincipal = GetObjectPrincipal(defaultGlobal);
+            nsIPrincipal *defaultPrincipal = GetObjectPrincipal(defaultScope);
             bool equal = false;
             currentPrincipal->Equals(defaultPrincipal, &equal);
             if (equal) {
                 mStack.AppendElement(cx);
                 return true;
             }
         }
 
--- a/js/xpconnect/src/nsCxPusher.cpp
+++ b/js/xpconnect/src/nsCxPusher.cpp
@@ -124,18 +124,22 @@ AutoCxPusher::AutoCxPusher(JSContext* cx
 
   // Enter a request and a compartment for the duration that the cx is on the
   // stack if non-null.
   //
   // NB: We call UnmarkGrayContext so that this can obsolete the need for the
   // old XPCAutoRequest as well.
   if (cx) {
     mAutoRequest.construct(cx);
-    if (js::DefaultObjectForContextOrNull(cx))
-      mAutoCompartment.construct(cx, js::DefaultObjectForContextOrNull(cx));
+
+    // DOM JSContexts don't store their default compartment object on the cx.
+    JSObject *compartmentObject = mScx ? mScx->GetNativeGlobal()
+                                       : js::DefaultObjectForContextOrNull(cx);
+    if (compartmentObject)
+      mAutoCompartment.construct(cx, compartmentObject);
     xpc_UnmarkGrayContext(cx);
   }
 }
 
 NS_EXPORT
 AutoCxPusher::~AutoCxPusher()
 {
   // GC when we pop a script entry point. This is a useful heuristic that helps