Bug 889714 - Stash the XPCShellEnvironment instance on the global, rather than the cx. r=mrbkap
authorBobby Holley <bobbyholley@gmail.com>
Wed, 31 Jul 2013 10:59:25 -0700
changeset 148168 fb2a3ba7080d871ced3eaebe88b85b33e469ccdd
parent 148167 f9f93b7689316fdf2d3bc489a78b4e2ad90c9b6a
child 148169 2e0d0144923c7480f0100feb4fbed2dbc1ee99b7
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap
bugs889714
milestone24.0a2
Bug 889714 - Stash the XPCShellEnvironment instance on the global, rather than the cx. r=mrbkap We need to stash it somewhere, because the shell-provided JSNatives need to access it. This solution only works for script running in the scope of the global we create. Butthat's fine here, because we only use it for load() and quit(), which only exist in the scope of that global.
ipc/testshell/XPCShellEnvironment.cpp
--- a/ipc/testshell/XPCShellEnvironment.cpp
+++ b/ipc/testshell/XPCShellEnvironment.cpp
@@ -44,16 +44,18 @@
 #include "BackstagePass.h"
 
 #include "TestShellChild.h"
 #include "TestShellParent.h"
 
 using mozilla::ipc::XPCShellEnvironment;
 using mozilla::ipc::TestShellChild;
 using mozilla::ipc::TestShellParent;
+using mozilla::AutoSafeJSContext;
+using namespace JS;
 
 namespace {
 
 static const char kDefaultRuntimeScriptFilename[] = "xpcshell.js";
 
 class XPCShellDirProvider : public nsIDirectoryServiceProvider
 {
 public:
@@ -66,22 +68,27 @@ public:
     bool SetGREDir(const char *dir);
     void ClearGREDir() { mGREDir = nullptr; }
 
 private:
     nsCOMPtr<nsIFile> mGREDir;
 };
 
 inline XPCShellEnvironment*
-Environment(JSContext* cx)
+Environment(JSObject* global)
 {
-    XPCShellEnvironment* env = 
-        static_cast<XPCShellEnvironment*>(JS_GetContextPrivate(cx));
-    NS_ASSERTION(env, "Should never be null!");
-    return env;
+    AutoSafeJSContext cx;
+    JSAutoCompartment ac(cx, global);
+    Rooted<Value> v(cx);
+    if (!JS_GetProperty(cx, global, "__XPCShellEnvironment", v.address()) ||
+        !v.get().isDouble())
+    {
+        return nullptr;
+    }
+    return static_cast<XPCShellEnvironment*>(v.get().toPrivate());
 }
 
 static void
 ScriptErrorReporter(JSContext *cx,
                     const char *message,
                     JSErrorReport *report)
 {
     int i, j, k, n;
@@ -267,17 +274,17 @@ Load(JSContext *cx,
         FILE *file = fopen(filename.ptr(), "r");
         if (!file) {
             JS_ReportError(cx, "cannot open file '%s' for reading", filename.ptr());
             return JS_FALSE;
         }
         JS::CompileOptions options(cx);
         options.setUTF8(true)
                .setFileAndLine(filename.ptr(), 1)
-               .setPrincipals(Environment(cx)->GetPrincipal());
+               .setPrincipals(Environment(JS_GetGlobalForScopeChain(cx))->GetPrincipal());
         JS::RootedObject rootedObj(cx, obj);
         JSScript *script = JS::Compile(cx, rootedObj, options, file);
         fclose(file);
         if (!script)
             return JS_FALSE;
 
         if (!JS_ExecuteScript(cx, obj, script, result.address())) {
             return JS_FALSE;
@@ -307,17 +314,17 @@ BuildDate(JSContext *cx, unsigned argc, 
     return JS_TRUE;
 }
 
 static JSBool
 Quit(JSContext *cx,
      unsigned argc,
      JS::Value *vp)
 {
-    XPCShellEnvironment* env = Environment(cx);
+    XPCShellEnvironment* env = Environment(JS_GetGlobalForScopeChain(cx));
     env->SetIsQuitting();
 
     return JS_FALSE;
 }
 
 static JSBool
 DumpXPC(JSContext *cx,
         unsigned argc,
@@ -782,18 +789,22 @@ XPCShellEnvironment::Init()
     }
 
     backstagePass->SetGlobalObject(globalObj);
 
     {
         JSAutoRequest ar(cx);
         JSAutoCompartment ac(cx, globalObj);
 
-        if (!JS_DefineFunctions(cx, globalObj, gGlobalFunctions) ||
-	    !JS_DefineProfilingFunctions(cx, globalObj)) {
+        if (!JS_DefineProperty(cx, globalObj, "__XPCShellEnvironment",
+                               PRIVATE_TO_JSVAL(this), JS_PropertyStub,
+                               JS_StrictPropertyStub,
+                               JSPROP_READONLY | JSPROP_PERMANENT) ||
+            !JS_DefineFunctions(cx, globalObj, gGlobalFunctions) ||
+            !JS_DefineProfilingFunctions(cx, globalObj)) {
             NS_ERROR("JS_DefineFunctions failed!");
             return false;
         }
     }
 
     mGlobalHolder = globalObj;
 
     FILE* runtimeScriptFile = fopen(kDefaultRuntimeScriptFilename, "r");