Bug 899367 - Have nsGlobalWindow go through nsJSContext to access the outer. r=mccr8
authorBobby Holley <bobbyholley@gmail.com>
Wed, 04 Sep 2013 14:06:55 -0700
changeset 145510 8e4bd1c50df4797665d2b056b3117220de3af10b
parent 145509 14df512b792aeb64e3608f4e4de70151a411f354
child 145511 6a1f5a4594aed54de19f95d093ab090daecdcb9b
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 - Have nsGlobalWindow go through nsJSContext to access the outer. r=mccr8
dom/base/nsGlobalWindow.cpp
dom/base/nsIScriptContext.h
dom/base/nsJSEnvironment.cpp
dom/base/nsJSEnvironment.h
xpcom/base/CycleCollectedJSRuntime.cpp
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -2044,18 +2044,19 @@ nsGlobalWindow::CreateOuterObject(nsGlob
   return SetOuterObject(cx, outer);
 }
 
 nsresult
 nsGlobalWindow::SetOuterObject(JSContext* aCx, JS::Handle<JSObject*> aOuterObject)
 {
   JSAutoCompartment ac(aCx, aOuterObject);
 
-  // Indicate the default compartment object associated with this cx.
-  js::SetDefaultObjectForContext(aCx, aOuterObject);
+  // Inform the nsJSContext, which is the canonical holder of the outer.
+  MOZ_ASSERT(IsOuterWindow());
+  mContext->SetWindowProxy(aOuterObject);
 
   // Set up the prototype for the outer object.
   JS::Rooted<JSObject*> inner(aCx, JS_GetParent(aOuterObject));
   JS::Rooted<JSObject*> proto(aCx);
   if (!JS_GetPrototype(aCx, inner, &proto)) {
     return NS_ERROR_FAILURE;
   }
   JS_SetPrototype(aCx, aOuterObject, proto);
@@ -2441,21 +2442,17 @@ nsGlobalWindow::SetNewDocument(nsIDocume
 
     // Now that both the the inner and outer windows are initialized
     // let the script context do its magic to hook them together.
 #ifdef DEBUG
     JS::Rooted<JSObject*> newInnerJSObject(cx,
         newInnerWindow->FastGetGlobalJSObject());
 #endif
 
-    // Now that we're connecting the outer global to the inner one,
-    // we must have transplanted it. The JS engine tries to maintain
-    // the global object's compartment as its default compartment,
-    // so update that now since it might have changed.
-    js::SetDefaultObjectForContext(cx, mJSObject);
+    MOZ_ASSERT(mContext->GetWindowProxy() == mJSObject);
 #ifdef DEBUG
     JS::Rooted<JSObject*> rootedJSObject(cx, mJSObject);
     JS::Rooted<JSObject*> proto1(cx), proto2(cx);
     JS_GetPrototype(cx, rootedJSObject, &proto1);
     JS_GetPrototype(cx, newInnerJSObject, &proto2);
     NS_ASSERTION(proto1 == proto2,
                  "outer and inner globals should have the same prototype");
 #endif
--- a/dom/base/nsIScriptContext.h
+++ b/dom/base/nsIScriptContext.h
@@ -22,18 +22,18 @@ class nsIArray;
 class nsIVariant;
 class nsIObjectInputStream;
 class nsIObjectOutputStream;
 class nsIScriptObjectPrincipal;
 class nsIDOMWindow;
 class nsIURI;
 
 #define NS_ISCRIPTCONTEXT_IID \
-{ 0x1d931a17, 0x453a, 0x47fb, \
-  { 0x94, 0x66, 0x2d, 0x3e, 0xd1, 0xef, 0x7a, 0xc5 } }
+{ 0x03c0874e, 0xcb49, 0x41c8, \
+  { 0xa3, 0x0b, 0xef, 0x3e, 0xc1, 0x88, 0xb1, 0x1f } }
 
 /* This MUST match JSVERSION_DEFAULT.  This version stuff if we don't
    know what language we have is a little silly... */
 #define SCRIPTVERSION_DEFAULT JSVERSION_DEFAULT
 
 class nsIOffThreadScriptReceiver;
 
 /**
@@ -160,16 +160,23 @@ public:
    * Tell the context we're about to be reinitialize it.
    */
   virtual void WillInitializeContext() = 0;
 
   /**
    * Tell the context we're done reinitializing it.
    */
   virtual void DidInitializeContext() = 0;
+
+  /**
+   * Access the Window Proxy. The setter should only be called by nsGlobalWindow.
+   */
+  virtual void SetWindowProxy(JS::Handle<JSObject*> aWindowProxy) = 0;
+  virtual JSObject* GetWindowProxy() = 0;
+  virtual JSObject* GetWindowProxyPreserveColor() = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContext, NS_ISCRIPTCONTEXT_IID)
 
 #define NS_IOFFTHREADSCRIPTRECEIVER_IID \
 {0x3a980010, 0x878d, 0x46a9,            \
   {0x93, 0xad, 0xbc, 0xfd, 0xd3, 0x8e, 0xa0, 0xc2}}
 
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1147,17 +1147,17 @@ nsJSContext::GetGlobalObject()
   // This'll return a pointer to something we're about to release, but
   // that's ok, the JS object will hold it alive long enough.
   return sgo;
 }
 
 JSObject*
 nsJSContext::GetNativeGlobal()
 {
-    return js::DefaultObjectForContextOrNull(mContext);
+    return GetWindowProxy();
 }
 
 JSContext*
 nsJSContext::GetNativeContext()
 {
   return xpc_UnmarkGrayContext(mContext);
 }
 
@@ -2594,16 +2594,34 @@ void
 nsJSContext::ReportPendingException()
 {
   if (mIsInitialized) {
     nsJSUtils::ReportPendingException(mContext);
   }
 }
 
 void
+nsJSContext::SetWindowProxy(JS::Handle<JSObject*> aWindowProxy)
+{
+  js::SetDefaultObjectForContext(mContext, aWindowProxy);
+}
+
+JSObject*
+nsJSContext::GetWindowProxy()
+{
+  return xpc_UnmarkGrayObject(GetWindowProxyPreserveColor());
+}
+
+JSObject*
+nsJSContext::GetWindowProxyPreserveColor()
+{
+  return js::DefaultObjectForContextOrNull(mContext);
+}
+
+void
 nsJSContext::LikelyShortLivingObjectCreated()
 {
   ++sLikelyShortLivingObjectsNeedingGC;
 }
 
 void
 mozilla::dom::StartupJSEnvironment()
 {
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -76,16 +76,20 @@ public:
   virtual bool GetProcessingScriptTag() MOZ_OVERRIDE;
   virtual void SetProcessingScriptTag(bool aResult) MOZ_OVERRIDE;
 
   virtual nsresult InitClasses(JS::Handle<JSObject*> aGlobalObj) MOZ_OVERRIDE;
 
   virtual void WillInitializeContext() MOZ_OVERRIDE;
   virtual void DidInitializeContext() MOZ_OVERRIDE;
 
+  virtual void SetWindowProxy(JS::Handle<JSObject*> aWindowProxy) MOZ_OVERRIDE;
+  virtual JSObject* GetWindowProxy() MOZ_OVERRIDE;
+  virtual JSObject* GetWindowProxyPreserveColor() MOZ_OVERRIDE;
+
   static void LoadStart();
   static void LoadEnd();
 
   enum IsCompartment {
     CompartmentGC,
     NonCompartmentGC
   };
 
--- a/xpcom/base/CycleCollectedJSRuntime.cpp
+++ b/xpcom/base/CycleCollectedJSRuntime.cpp
@@ -927,17 +927,17 @@ CycleCollectedJSRuntime::UsefulToMergeZo
   JSContext* iter = nullptr;
   JSContext* cx;
   JSAutoRequest ar(nsContentUtils::GetSafeJSContext());
   while ((cx = JS_ContextIterator(mJSRuntime, &iter))) {
     // Skip anything without an nsIScriptContext, as well as any scx whose
     // NativeGlobal() is not an outer window (this happens with XUL Prototype
     // compilation scopes, for example, which we're not interested in).
     nsIScriptContext* scx = GetScriptContextFromJSContext(cx);
-    JS::RootedObject global(cx, scx ? scx->GetNativeGlobal() : nullptr);
+    JS::RootedObject global(cx, scx ? scx->GetWindowProxyPreserveColor() : nullptr);
     if (!global || !js::GetObjectParent(global)) {
       continue;
     }
     // Grab the inner from the outer.
     global = JS_ObjectToInnerObject(cx, global);
     MOZ_ASSERT(!js::GetObjectParent(global));
     if (JS::GCThingIsMarkedGray(global) &&
         !js::IsSystemCompartment(js::GetObjectCompartment(global))) {