Backed out changeset 4d86e63ff60d, diagnostic patch; back out 3da12edf735e, followup fix; back out bug 631135 completely, unexplained intermittent orange. r=waldo, a=orange
authorMike Shaver <shaver@mozilla.org>
Sat, 19 Feb 2011 20:46:44 -0800
changeset 62876 a633a0030ac6dce8c6e1f1f86a64c736c35166a1
parent 62875 6f544597b3305e781067a771b2f766c72501e6ee
child 62877 4f8d5b10e4ef8046b35275c642ec9c72d5fa4552
push idunknown
push userunknown
push dateunknown
reviewerswaldo, orange
bugs631135
milestone2.0b12pre
backs out4d86e63ff60d40f4c39a1c7d1d880b77d61f9565
Backed out changeset 4d86e63ff60d, diagnostic patch; back out 3da12edf735e, followup fix; back out bug 631135 completely, unexplained intermittent orange. r=waldo, a=orange
caps/tests/mochitest/test_bug246699.html
content/base/src/nsContentUtils.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsJSEnvironment.cpp
dom/base/nsJSUtils.cpp
dom/indexedDB/IDBKeyRange.cpp
dom/src/threads/nsDOMWorker.cpp
js/src/jsapi-tests/Makefile.in
js/src/jsapi-tests/testCrossGlobal.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jscntxtinlines.h
js/src/jscompartment.cpp
js/src/jsinterp.cpp
js/src/jsinterp.h
js/src/jsobj.cpp
js/src/jsobjinlines.h
js/src/jsparse.cpp
js/src/jsregexp.cpp
js/src/jsstr.cpp
js/src/jsxml.cpp
js/src/methodjit/MonoIC.cpp
js/src/shell/js.cpp
js/src/tests/e4x/extensions/cross-global-settings.js
js/src/tests/e4x/extensions/jstests.list
js/src/tests/ecma_5/extensions/cross-global-call.js
js/src/tests/ecma_5/extensions/jstests.list
js/src/xpconnect/src/xpccomponents.cpp
js/src/xpconnect/src/xpcthrower.cpp
js/src/xpconnect/wrappers/AccessCheck.cpp
toolkit/components/ctypes/tests/unit/test_jsctypes.js.in
toolkit/components/perf/PerfMeasurement.cpp
--- a/caps/tests/mochitest/test_bug246699.html
+++ b/caps/tests/mochitest/test_bug246699.html
@@ -8,17 +8,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="text/javascript" src="/MochiKit/packed.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=246699">Mozilla Bug 246699</a>
 <p id="display"></p>
 <div id="content" style="display: none">
-<iframe id="load-frame" src="http://example.com/"></iframe>
+<iframe id="load-frame"></iframe>  
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 /**
  ** Test for Bug 246699
  ** (should produce stack information for caps errors)
  **/
@@ -44,20 +44,18 @@ function tryChromeLoad()
     window.frames[0].location = "chrome://global/content/mozilla.xhtml";
 }
 
 function tryComponentsClasses()
 {
     return Components.classes["@mozilla.org/dummy;1"];
 }
 
-window.addEventListener("load", function()
-{
-  is(inciteCaps(tryChromeLoad), "denied-stack",
-     "should get stack for content-loading-chrome rejection");
-  is(inciteCaps(tryComponentsClasses), "denied-stack",
-     "should get stack for Components.classes rejection");
-}, false);
+
+is(inciteCaps(tryChromeLoad), "denied-stack",
+   "should get stack for content-loading-chrome rejection");
+is(inciteCaps(tryComponentsClasses), "denied-stack",
+   "should get stack for Components.classes rejection");
 </script>
 </pre>
 </body>
 </html>
 
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -5794,23 +5794,19 @@ CloneSimpleValues(JSContext* cx,
       return NS_ERROR_OUT_OF_MEMORY;
     }
     return SetPropertyOnValueOrObject(cx, OBJECT_TO_JSVAL(newDate), rval, robj,
                                       rid);
   }
 
   // RegExp objects.
   if (js_ObjectIsRegExp(obj)) {
-    JSObject* global = JS_GetGlobalForScopeChain(cx);
-    if (!global) {
-      return NS_ERROR_FAILURE;
-    }
-
     JSObject* proto;
-    if (!js_GetClassPrototype(cx, global, JSProto_RegExp, &proto)) {
+    if (!js_GetClassPrototype(cx, JS_GetScopeChain(cx), JSProto_RegExp,
+                              &proto)) {
       return NS_ERROR_FAILURE;
     }
     JSObject* newRegExp = js_CloneRegExpObject(cx, obj, proto);
     if (!newRegExp) {
       return NS_ERROR_FAILURE;
     }
     return SetPropertyOnValueOrObject(cx, OBJECT_TO_JSVAL(newRegExp), rval,
                                       robj, rid);
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -5798,27 +5798,40 @@ nsGlobalWindow::CallerInnerWindow()
 {
   JSContext *cx = nsContentUtils::GetCurrentJSContext();
   if (!cx) {
     NS_ERROR("Please don't call this method from C++!");
 
     return nsnull;
   }
 
-  JSObject *callerGlobal;
-  if (!::JS_GetGlobalForCallingScript(cx, &callerGlobal) || !callerGlobal)
-      return nsnull;
+  JSObject *scope = nsnull;
+  JSStackFrame *fp = nsnull;
+  JS_FrameIterator(cx, &fp);
+  if (fp) {
+    while (fp->isDummyFrame()) {
+      if (!JS_FrameIterator(cx, &fp))
+        break;
+    }
+
+    if (fp)
+      scope = &fp->scopeChain();
+  }
+
+  if (!scope)
+    scope = JS_GetScopeChain(cx);
 
   JSAutoEnterCompartment ac;
-  if (!ac.enter(cx, callerGlobal))
+  if (!ac.enter(cx, scope))
     return nsnull;
 
   nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
   nsContentUtils::XPConnect()->
-    GetWrappedNativeOfJSObject(cx, callerGlobal, getter_AddRefs(wrapper));
+    GetWrappedNativeOfJSObject(cx, ::JS_GetGlobalForObject(cx, scope),
+                               getter_AddRefs(wrapper));
   if (!wrapper)
     return nsnull;
 
   // The calling window must be holding a reference, so we can just return a
   // raw pointer here and let the QI's addref be balanced by the nsCOMPtr
   // destructor's release.
   nsCOMPtr<nsPIDOMWindow> win = do_QueryWrappedNative(wrapper);
   if (!win)
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -665,35 +665,19 @@ nsJSContext::DOMOperationCallback(JSCont
     // We're waiting on a modal dialog, nothing more to do here.
     return JS_TRUE;
   }
 
   PRTime duration = now - callbackTime;
 
   // Check the amount of time this script has been running, or if the
   // dialog is disabled.
-  JSObject* global;
-  if (!::JS_GetGlobalForCallingScript(cx, &global)) {
-    return JS_FALSE;
-  }
-  if (!global) {
-    global = JS_GetGlobalObject(cx);
-    if (!global) {
-      return NS_ERROR_FAILURE;
-    }
-    OBJ_TO_INNER_OBJECT(cx, global);
-    if (!global) {
-      return NS_ERROR_FAILURE;
-    }
-  }
-
-  NS_ABORT_IF_FALSE(global != NULL, "operation callback without script?");
-
+  JSObject* global = ::JS_GetGlobalForScopeChain(cx);
   PRBool isTrackingChromeCodeTime =
-    xpc::AccessCheck::isChrome(global->getCompartment());
+    global && xpc::AccessCheck::isChrome(global->getCompartment());
   if (duration < (isTrackingChromeCodeTime ?
                   sMaxChromeScriptRunTime : sMaxScriptRunTime)) {
     return JS_TRUE;
   }
 
   if (!nsContentUtils::IsSafeToRunScript()) {
     // If it isn't safe to run script, then it isn't safe to bring up the
     // prompt (since that will cause the event loop to spin). In this case
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -185,23 +185,24 @@ nsJSUtils::GetDynamicScriptContext(JSCon
 }
 
 PRUint64
 nsJSUtils::GetCurrentlyRunningCodeWindowID(JSContext *aContext)
 {
   if (!aContext)
     return 0;
 
-  JSObject *jsGlobal;
-  if (!JS_GetGlobalForCallingScript(aContext, &jsGlobal) || !jsGlobal)
-    return 0;
+  PRUint64 windowID = 0;
 
-  JSAutoEnterCompartment ac;
-  if (!ac.enter(aContext, jsGlobal))
-    return 0;
-  nsIScriptGlobalObject *sg = GetStaticScriptGlobal(aContext, jsGlobal);
-  if (!sg)
-    return 0;
+  JSObject *jsGlobal = JS_GetGlobalForScopeChain(aContext);
+  if (jsGlobal) {
+    nsIScriptGlobalObject *scriptGlobal = GetStaticScriptGlobal(aContext,
+                                                                jsGlobal);
+    if (scriptGlobal) {
+      nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(scriptGlobal);
+      if (win)
+        windowID = win->GetOuterWindow()->WindowID();
+    }
+  }
 
-  nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(sg);
-  return win ? win->GetOuterWindow()->WindowID() : 0;
+  return windowID;
 }
 
--- a/dom/indexedDB/IDBKeyRange.cpp
+++ b/dom/indexedDB/IDBKeyRange.cpp
@@ -109,17 +109,17 @@ ReturnKeyRange(JSContext* aCx,
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(aCx, "Null pointer!");
   NS_ASSERTION(aVp, "Null pointer!");
   NS_ASSERTION(aKeyRange, "Null pointer!");
 
   nsIXPConnect* xpc = nsContentUtils::XPConnect();
   NS_ASSERTION(xpc, "This should never be null!");
 
-  JSObject* global = JS_GetGlobalForScopeChain(aCx);
+  JSObject* global = JS_GetGlobalForObject(aCx, JS_GetScopeChain(aCx));
   NS_ENSURE_TRUE(global, JS_FALSE);
 
   nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
   if (NS_FAILED(xpc->WrapNative(aCx, global, aKeyRange,
                                 NS_GET_IID(nsIIDBKeyRange),
                                 getter_AddRefs(holder)))) {
     JS_ReportError(aCx, "Couldn't wrap IDBKeyRange object.");
     return JS_FALSE;
--- a/dom/src/threads/nsDOMWorker.cpp
+++ b/dom/src/threads/nsDOMWorker.cpp
@@ -629,17 +629,17 @@ nsDOMWorkerFunctions::GetInstanceCommon(
   else {
     instance = do_CreateInstance(contractId.get());
     if (!instance) {
       JS_ReportError(aCx, "Could not create the instance!");
       return JS_FALSE;
     }
   }
 
-  JSObject* global = JS_GetGlobalForScopeChain(aCx);
+  JSObject* global = JS_GetGlobalForObject(aCx, JS_GetScopeChain(aCx));
   if (!global) {
     NS_ASSERTION(JS_IsExceptionPending(aCx), "Need to set an exception!");
     return JS_FALSE;
   }
 
   jsval val;
   nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
   if (NS_FAILED(nsContentUtils::WrapNative(aCx, global, instance, &val,
@@ -2528,17 +2528,18 @@ nsDOMWorker::ReadStructuredClone(JSConte
 
   if (aTag == DOMWORKER_SCTAG_WRAPPEDNATIVE) {
     NS_ASSERTION(!aData, "Huh?");
 
     nsISupports* wrappedNative;
     if (JS_ReadBytes(aReader, &wrappedNative, sizeof(wrappedNative))) {
       NS_ASSERTION(wrappedNative, "Null pointer?!");
 
-      if (JSObject* global = JS_GetGlobalForScopeChain(aCx)) {
+      JSObject* global = JS_GetGlobalForObject(aCx, JS_GetScopeChain(aCx));
+      if (global) {
         jsval val;
         nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
         if (NS_SUCCEEDED(nsContentUtils::WrapNative(aCx, global, wrappedNative,
                                                     &val,
                                                     getter_AddRefs(wrapper)))) {
           return JSVAL_TO_OBJECT(val);
         }
       }
--- a/js/src/jsapi-tests/Makefile.in
+++ b/js/src/jsapi-tests/Makefile.in
@@ -49,17 +49,16 @@ PROGRAM         = jsapi-tests$(BIN_SUFFI
 CPPSRCS = \
   tests.cpp \
   selfTest.cpp \
   testBug604087.cpp \
   testClassGetter.cpp \
   testCloneScript.cpp \
   testConservativeGC.cpp \
   testContexts.cpp \
-  testCrossGlobal.cpp \
   testDebugger.cpp \
   testDeepFreeze.cpp \
   testDefineGetterSetterNonEnumerable.cpp \
   testDefineProperty.cpp \
   testExtendedEq.cpp \
   testFuncCallback.cpp \
   testGCChunkAlloc.cpp \
   testGetPropertyDefault.cpp \
deleted file mode 100644
--- a/js/src/jsapi-tests/testCrossGlobal.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/licenses/publicdomain/
- */
-#include "tests.h"
-
-static const char CODE[] =
-    "function f()                                                   "
-    "{                                                              "
-    "  return new otherGlobal.Array() instanceof otherGlobal.Array; "
-    "}                                                              "
-    "f() && f() && f();                                             ";
-
-BEGIN_TEST(testCrossGlobal_call)
-{
-    JSObject *otherGlobal = JS_NewGlobalObject(cx, basicGlobalClass());
-    CHECK(otherGlobal);
-
-    JSBool res = JS_InitStandardClasses(cx, otherGlobal);
-    CHECK(res);
-
-    res = JS_DefineProperty(cx, global, "otherGlobal", OBJECT_TO_JSVAL(otherGlobal),
-                            JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE);
-    CHECK(res);
-
-    uintN oldopts = JS_GetOptions(cx);
-    uintN newopts = oldopts & ~(JSOPTION_JIT | JSOPTION_METHODJIT | JSOPTION_PROFILING);
-    newopts |= JSOPTION_METHODJIT;
-    JS_SetOptions(cx, newopts);
-
-    jsval rv;
-    EVAL(CODE, &rv);
-
-    CHECK_SAME(rv, JSVAL_TRUE);
-
-    JS_SetOptions(cx, oldopts);
-
-    return true;
-}
-END_TEST(testCrossGlobal_call)
-
-BEGIN_TEST(testCrossGlobal_compileAndGo)
-{
-
-    JSObject *otherGlobal = JS_NewGlobalObject(cx, basicGlobalClass());
-    CHECK(otherGlobal);
-
-    JSBool res = JS_InitStandardClasses(cx, otherGlobal);
-    CHECK(res);
-
-    res = JS_DefineProperty(cx, global, "otherGlobal", OBJECT_TO_JSVAL(otherGlobal),
-                            JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE);
-    CHECK(res);
-
-    res = JS_DefineProperty(cx, otherGlobal, "otherGlobal", OBJECT_TO_JSVAL(otherGlobal),
-                            JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE);
-    CHECK(res);
-
-    uintN oldopts = JS_GetOptions(cx);
-    uintN newopts =
-        oldopts
-        & ~(JSOPTION_COMPILE_N_GO | JSOPTION_JIT | JSOPTION_METHODJIT | JSOPTION_PROFILING);
-    newopts |= JSOPTION_METHODJIT;
-    JS_SetOptions(cx, newopts);
-
-    jsval rv;
-
-    // Compile script
-
-    JSScript *script = JS_CompileScript(cx, global, CODE, strlen(CODE), __FILE__, __LINE__);
-    CHECK(script);
-    JSObject *scriptObj = JS_NewScriptObject(cx, script);
-    CHECK(scriptObj);
-    JS::Anchor<JSObject *> anch(scriptObj);
-
-    // Run script against new other global
-    res = JS_ExecuteScript(cx, otherGlobal, script, &rv);
-    CHECK(res);
-    CHECK_SAME(rv, JSVAL_TRUE);
-
-    // Run script against original global
-    res = JS_ExecuteScript(cx, global, script, &rv);
-    CHECK(res);
-    CHECK_SAME(rv, JSVAL_TRUE);
-
-    JS_SetOptions(cx, oldopts);
-
-    return true;
-}
-END_TEST(testCrossGlobal_compileAndGo)
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1924,44 +1924,34 @@ JS_PUBLIC_API(JSBool)
 JS_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, JSObject **objp)
 {
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     return js_GetClassObject(cx, obj, key, objp);
 }
 
 JS_PUBLIC_API(JSObject *)
+JS_GetScopeChain(JSContext *cx)
+{
+    CHECK_REQUEST(cx);
+    return GetScopeChain(cx);
+}
+
+JS_PUBLIC_API(JSObject *)
 JS_GetGlobalForObject(JSContext *cx, JSObject *obj)
 {
     assertSameCompartment(cx, obj);
     return obj->getGlobal();
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_GetGlobalForScopeChain(JSContext *cx)
 {
     CHECK_REQUEST(cx);
-    return cx->getGlobalFromScopeChain();
-}
-
-JS_PUBLIC_API(JSBool)
-JS_GetGlobalForCallingScript(JSContext *cx, JSObject **objp)
-{
-    JSStackFrame *fp = JS_GetScriptedCaller(cx, NULL);
-    if (!fp) {
-        *objp = NULL;
-        return true;
-    }
-
-    JSObject *scope = JS_GetFrameScopeChain(cx, fp);
-    if (!scope)
-        return false;
-
-    *objp = scope->getGlobal();
-    return true;
+    return GetGlobalForScopeChain(cx);
 }
 
 JS_PUBLIC_API(jsval)
 JS_ComputeThis(JSContext *cx, jsval *vp)
 {
     assertSameCompartment(cx, JSValueArray(vp, 2));
     return BoxThisForVp(cx, Valueify(vp)) ? vp[1] : JSVAL_NULL;
 }
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1094,49 +1094,24 @@ extern JS_PUBLIC_API(JSIdArray *)
 JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj,
                                     JSIdArray *ida);
 
 extern JS_PUBLIC_API(JSBool)
 JS_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
                   JSObject **objp);
 
 extern JS_PUBLIC_API(JSObject *)
+JS_GetScopeChain(JSContext *cx);
+
+extern JS_PUBLIC_API(JSObject *)
 JS_GetGlobalForObject(JSContext *cx, JSObject *obj);
 
-/*
- * Returns the global for the currently executing method or of the object
- * currently being accessed if a property access (get or set) is in progress.
- * If no action is currently in progress, the context's global object is
- * returned. If the context has no global, this method will report an error and
- * return null.
- *
- * To illustrate: suppose a global G with a method defined by a JSNative
- * corresponding to the property G.method. When JS_GetGlobalForScopeChain is
- * invoked during execution of G.method, the object returned will be G. This is
- * so if a script in G calls method, and it is also so if script in a different
- * global G2 calls |G1.method()|, or extracts |G.method| and calls it, and so
- * on. This behavior also applies for property accesses to an |obj.prop| if
- * that property is represented by a |JSPropertyOp| and |JSStrictPropertyOp|
- * pair: the global object will be that corresponding to |obj|.
- */
 extern JS_PUBLIC_API(JSObject *)
 JS_GetGlobalForScopeChain(JSContext *cx);
 
-/*
- * Returns the global of the most recent interpreted code if there is any.
- *
- * NB: This method ignores the current scope chain, any sense of privilege
- *     separation encapsulated in intervening stack frames, and so on.  If you
- *     are attempting to determine the global object to expose it to script,
- *     this is almost certainly not the method you want! You *probably* want
- *     JS_GetGlobalForScopeChain instead.
- */
-extern JS_PUBLIC_API(JSBool)
-JS_GetGlobalForCallingScript(JSContext *cx, JSObject **objp);
-
 #ifdef JS_HAS_CTYPES
 /*
  * Initialize the 'ctypes' object on a global variable 'obj'. The 'ctypes'
  * object will be sealed.
  */
 extern JS_PUBLIC_API(JSBool)
 JS_InitCTypesClass(JSContext *cx, JSObject *global);
 
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -226,18 +226,16 @@ StackSpace::mark(JSTracer *trc)
      */
     Value *end = firstUnused();
     for (StackSegment *seg = currentSegment; seg; seg = seg->getPreviousInMemory()) {
         STATIC_ASSERT(ubound(end) >= 0);
         if (seg->inContext()) {
             /* This may be the only pointer to the initialVarObj. */
             if (seg->hasInitialVarObj())
                 MarkObject(trc, seg->getInitialVarObj(), "varobj");
-            if (seg->hasLastNativeCalleeScope())
-                MarkObject(trc, *seg->lastNativeCalleeScope(), "lastNativeCalleeScope");
 
             /* Mark slots/args trailing off of the last stack frame. */
             JSStackFrame *fp = seg->getCurrentFrame();
             MarkStackRangeConservatively(trc, fp->slots(), end);
 
             /* Mark stack frames and slots/args between stack frames. */
             JSStackFrame *initial = seg->getInitialFrame();
             for (JSStackFrame *f = fp; f != initial; f = f->prev()) {
@@ -1989,22 +1987,16 @@ JSContext::JSContext(JSRuntime *rt)
   : hasVersionOverride(false),
     runtime(rt),
     compartment(NULL),
     regs(NULL),
     busyArrays()
 {}
 
 void
-JSContext::reportInactive()
-{
-    JS_ReportErrorNumber(this, js_GetErrorMessage, NULL, JSMSG_INACTIVE);
-}
-
-void
 JSContext::resetCompartment()
 {
     JSObject *scopeobj;
     if (hasfp()) {
         scopeobj = &fp()->scopeChain();
     } else {
         scopeobj = globalObject;
         if (!scopeobj)
@@ -2087,31 +2079,27 @@ JSContext::popSegmentAndFrame()
     }
     maybeMigrateVersionOverride();
 }
 
 void
 JSContext::saveActiveSegment()
 {
     JS_ASSERT(hasActiveSegment());
-    currentSegment->save(regs, lastNativeCalleeScope, lastNativeCalleeScopePtr);
-    lastNativeCalleeScope = NULL;
-    lastNativeCalleeScopePtr = NULL;
+    currentSegment->save(regs);
     setCurrentRegs(NULL);
     resetCompartment();
 }
 
 void
 JSContext::restoreSegment()
 {
-    js::StackSegment *cs = currentSegment;
-    setCurrentRegs(cs->getSuspendedRegs());
-    lastNativeCalleeScopePtr = cs->lastNativeCalleeScopePtr();
-    lastNativeCalleeScope = cs->lastNativeCalleeScope();
-    cs->restore();
+    js::StackSegment *ccs = currentSegment;
+    setCurrentRegs(ccs->getSuspendedRegs());
+    ccs->restore();
     resetCompartment();
 }
 
 JSGenerator *
 JSContext::generatorFor(JSStackFrame *fp) const
 {
     JS_ASSERT(stack().contains(fp) && fp->isGeneratorFrame());
     JS_ASSERT(!fp->isFloatingGenerator());
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -240,37 +240,32 @@ class StackSegment
     JSFrameRegs         *suspendedRegs;
 
     /* The varobj on entry to initialFrame. */
     JSObject            *initialVarObj;
 
     /* Whether this segment was suspended by JS_SaveFrameChain. */
     bool                saved;
 
-    /* Maintained to implement getGlobalFromScopeChain. */
-    JSObject            *savedLastNativeCalleeScope_;
-    void                *savedLastNativeCalleeScopePtr_;
-
     /* Align at 8 bytes on all platforms. */
 #if JS_BITS_PER_WORD == 32
     void                *padding;
 #endif
 
     /*
      * To make isActive a single null-ness check, this non-null constant is
      * assigned to suspendedRegs when !inContext.
      */
 #define NON_NULL_SUSPENDED_REGS ((JSFrameRegs *)0x1)
 
   public:
     StackSegment()
       : cx(NULL), previousInContext(NULL), previousInMemory(NULL),
         initialFrame(NULL), suspendedRegs(NON_NULL_SUSPENDED_REGS),
-        initialVarObj(NULL), saved(false), savedLastNativeCalleeScope_(NULL),
-         savedLastNativeCalleeScopePtr_(NULL)
+        initialVarObj(NULL), saved(false)
     {
         JS_ASSERT(!inContext());
     }
 
     /* Safe casts guaranteed by the contiguous-stack layout. */
 
     Value *valueRangeBegin() const {
         return (Value *)(this + 1);
@@ -348,19 +343,29 @@ class StackSegment
     void resume() {
         JS_ASSERT(isSuspended());
         suspendedRegs = NULL;
         JS_ASSERT(isActive());
     }
 
     /* When isSuspended, transitioning isSaved <--> !isSaved */
 
-    void save(JSFrameRegs *regs, JSObject *lastNativeCalleeScope, void *lastNativeCalleeScopePtr);
-
-    void restore();
+    void save(JSFrameRegs *regs) {
+        JS_ASSERT(!isSuspended());
+        suspend(regs);
+        saved = true;
+        JS_ASSERT(isSaved());
+    }
+
+    void restore() {
+        JS_ASSERT(isSaved());
+        saved = false;
+        resume();
+        JS_ASSERT(!isSuspended());
+    }
 
     /* Data available when inContext */
 
     JSStackFrame *getInitialFrame() const {
         JS_ASSERT(inContext());
         return initialFrame;
     }
 
@@ -406,31 +411,16 @@ class StackSegment
         return initialVarObj != NULL;
     }
 
     JSObject &getInitialVarObj() const {
         JS_ASSERT(inContext() && initialVarObj);
         return *initialVarObj;
     }
 
-    bool hasLastNativeCalleeScope() const {
-        JS_ASSERT(inContext());
-        return savedLastNativeCalleeScope_ != NULL;
-    }
-
-    JSObject *lastNativeCalleeScope() const {
-        JS_ASSERT(inContext());
-        return savedLastNativeCalleeScope_;
-    }
-
-    void *lastNativeCalleeScopePtr() const {
-        JS_ASSERT(inContext());
-        return savedLastNativeCalleeScopePtr_;
-    }
-
 #ifdef DEBUG
     JS_REQUIRES_STACK bool contains(const JSStackFrame *fp) const;
 #endif
 };
 
 static const size_t VALUES_PER_STACK_SEGMENT = sizeof(StackSegment) / sizeof(Value);
 JS_STATIC_ASSERT(sizeof(StackSegment) % sizeof(Value) == 0);
 
@@ -628,30 +618,27 @@ class StackSpace
     template <class Check>
     inline JSStackFrame *getCallFrame(JSContext *cx, Value *sp, uintN nactual,
                                       JSFunction *fun, JSScript *script,
                                       uint32 *pflags, Check check) const;
 
     inline void popInvokeArgs(const InvokeArgsGuard &args);
     inline void popInvokeFrame(const InvokeFrameGuard &ag);
 
+    inline Value *firstUnused() const;
+
     inline bool isCurrentAndActive(JSContext *cx) const;
     friend class AllFramesIter;
     StackSegment *getCurrentSegment() const { return currentSegment; }
 
 #ifdef XP_WIN
     /* Commit more memory from the reserved stack space. */
     JS_FRIEND_API(bool) bumpCommit(Value *from, ptrdiff_t nvals) const;
 #endif
 
-    /* The first stack location available to push new values and frames. */
-    inline js::Value *firstUnused() const;
-  public:
-    inline void *constFirstUnused() const;
-
   public:
     static const size_t CAPACITY_VALS   = 512 * 1024;
     static const size_t CAPACITY_BYTES  = CAPACITY_VALS * sizeof(Value);
     static const size_t COMMIT_VALS     = 16 * 1024;
     static const size_t COMMIT_BYTES    = COMMIT_VALS * sizeof(Value);
 
     /*
      * SunSpider and v8bench have roughly an average of 9 slots per script.
@@ -1692,42 +1679,16 @@ struct JSContext
         return regs ? regs->fp : NULL;
     }
 
     bool hasfp() {
         JS_ASSERT_IF(regs, regs->fp);
         return !!regs;
     }
 
-    /*
-     * An object created for the global of the currently executing native
-     * method, native getter, or native setter (or null if none is executing),
-     * used for scope chain computation.  The exact identity of this value is
-     * unspecified: function calls and property accesses fill this with
-     * different values, and the trace JIT and method JIT don't update the
-     * value during intra-global-object method calls and property accesses.
-     */
-    JSObject *lastNativeCalleeScope;
-
-    /*
-     * A JavaScript stack location associated with a native call/property
-     * access.
-     */
-    void *lastNativeCalleeScopePtr;
-
-    /*
-     * Computes the global object corresponding to the current scope chain, as
-     * determined by the current callee if one exists, by the object being
-     * accessed if a native property operation is occurring, or by the context
-     * global object if one does not.
-     */
-    inline JSObject *getGlobalFromScopeChain();
-
-    void reportInactive();
-
   public:
     friend class js::StackSpace;
     friend bool js::Interpret(JSContext *, JSStackFrame *, uintN, JSInterpMode);
 
     void resetCompartment();
     void wrapPendingException();
 
     /* For grep-ability, changes to 'regs' should call this function. */
@@ -1802,17 +1763,17 @@ struct JSContext
     }
 
     /* Return the current segment, which may or may not be active. */
     js::StackSegment *getCurrentSegment() const {
         assertSegmentsInSync();
         return currentSegment;
     }
 
-    inline js::RegExpStatics *getRegExpStatics();
+    inline js::RegExpStatics *regExpStatics();
 
     /* Add the given segment to the list as the new active segment. */
     void pushSegmentAndFrame(js::StackSegment *newseg, JSFrameRegs &regs);
 
     /* Remove the active segment and make the next segment active. */
     void popSegmentAndFrame();
 
     /* Mark the top segment as suspended, without pushing a new one. */
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -44,62 +44,52 @@
 #include "jscntxt.h"
 #include "jscompartment.h"
 #include "jsparse.h"
 #include "jsstaticcheck.h"
 #include "jsxml.h"
 #include "jsregexp.h"
 #include "jsgc.h"
 
+namespace js {
+
+static inline JSObject *
+GetGlobalForScopeChain(JSContext *cx)
+{
+    /*
+     * This is essentially GetScopeChain(cx)->getGlobal(), but without
+     * falling off trace.
+     *
+     * This use of cx->fp, possibly on trace, is deliberate:
+     * cx->fp->scopeChain->getGlobal() returns the same object whether we're on
+     * trace or not, since we do not trace calls across global objects.
+     */
+    VOUCH_DOES_NOT_REQUIRE_STACK();
+
+    if (cx->hasfp())
+        return cx->fp()->scopeChain().getGlobal();
+
+    JSObject *scope = cx->globalObject;
+    if (!scope) {
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INACTIVE);
+        return NULL;
+    }
+    OBJ_TO_INNER_OBJECT(cx, scope);
+    return scope;
+}
+
+}
+
 #ifdef JS_METHODJIT
 inline js::mjit::JaegerCompartment *JSContext::jaegerCompartment()
 {
     return compartment->jaegerCompartment;
 }
 #endif
 
-inline JSObject *
-JSContext::getGlobalFromScopeChain()
-{
-    if (regs) {
-        /*
-         * It's fine if the frame is stale on-trace, because we don't trace
-         * calls crossing globals.
-         */
-        VOUCH_DOES_NOT_REQUIRE_STACK();
-
-        /* Consult the frame if it's newer than any last native call. */
-        if (regs->fp > lastNativeCalleeScopePtr)
-            return regs->fp->scopeChain().getGlobal();
-
-        /* Otherwise the callee gives us our global object. */
-        JS_ASSERT(lastNativeCalleeScopePtr <= stack().constFirstUnused());
-        JS_ASSERT(currentSegment < lastNativeCalleeScopePtr);
-        return lastNativeCalleeScope->getGlobal();
-    }
-
-    /* If we have only native calls, consult the last one. */
-    if (lastNativeCalleeScope) {
-        JS_ASSERT(lastNativeCalleeScopePtr <= stack().constFirstUnused());
-        return lastNativeCalleeScope->getGlobal();
-    }
-
-    /*
-     * If no native call has occurred, this is a free-floating request for
-     * a global: return the context globalObject if possible.
-     */
-    JSObject *globalObj = globalObject;
-    if (!globalObj) {
-        reportInactive();
-        return NULL;
-    }
-    OBJ_TO_INNER_OBJECT(this, globalObj);
-    return globalObj;
-}
-
 inline bool
 JSContext::ensureGeneratorStackSpace()
 {
     bool ok = genStack.reserve(genStack.length() + 1);
     if (!ok)
         js_ReportOutOfMemory(this);
     return ok;
 }
@@ -115,47 +105,23 @@ JSContext::computeNextFrame(JSStackFrame
                 return next;
         }
         if (end != ss->getPreviousInContext()->getCurrentFrame())
             next = NULL;
     }
 }
 
 inline js::RegExpStatics *
-JSContext::getRegExpStatics()
+JSContext::regExpStatics()
 {
-    JSObject *global = getGlobalFromScopeChain();
-    if (!global)
-        return NULL;
-    return js::RegExpStatics::extractFrom(global);
+    return js::RegExpStatics::extractFrom(js::GetGlobalForScopeChain(this));
 }
 
 namespace js {
 
-JS_ALWAYS_INLINE void
-StackSegment::save(JSFrameRegs *regs, JSObject *lastNativeCalleeScope,
-                   void *lastNativeCalleeScopePtr)
-{
-    JS_ASSERT(!isSuspended());
-    suspend(regs);
-    saved = true;
-    savedLastNativeCalleeScope_ = lastNativeCalleeScope;
-    savedLastNativeCalleeScopePtr_ = lastNativeCalleeScopePtr;
-    JS_ASSERT(isSaved());
-}
-
-JS_ALWAYS_INLINE void
-StackSegment::restore()
-{
-    JS_ASSERT(isSaved());
-    saved = false;
-    resume();
-    JS_ASSERT(!isSuspended());
-}
-
 JS_REQUIRES_STACK JS_ALWAYS_INLINE JSFrameRegs *
 StackSegment::getCurrentRegs() const
 {
     JS_ASSERT(inContext());
     return isActive() ? cx->regs : getSuspendedRegs();
 }
 
 JS_REQUIRES_STACK JS_ALWAYS_INLINE JSStackFrame *
@@ -182,22 +148,16 @@ StackSpace::firstUnused() const
         }
         return sp;
     }
     JS_ASSERT(invokeArgEnd);
     JS_ASSERT(invokeSegment == currentSegment);
     return invokeArgEnd;
 }
 
-JS_REQUIRES_STACK inline void *
-StackSpace::constFirstUnused() const
-{
-    return firstUnused();
-}
-
 
 /* Inline so we don't need the friend API. */
 JS_ALWAYS_INLINE bool
 StackSpace::isCurrentAndActive(JSContext *cx) const
 {
 #ifdef DEBUG
     JS_ASSERT_IF(cx->getCurrentSegment(),
                  cx->getCurrentSegment()->maybeContext() == cx);
@@ -567,17 +527,17 @@ class AutoNamespaceArray : protected Aut
 class CompartmentChecker
 {
   private:
     JSContext *context;
     JSCompartment *compartment;
 
   public:
     explicit CompartmentChecker(JSContext *cx) : context(cx), compartment(cx->compartment) {
-        check(cx->getGlobalFromScopeChain());
+        check(cx->hasfp() ? JS_GetGlobalForScopeChain(cx) : cx->globalObject);
         VOUCH_DOES_NOT_REQUIRE_STACK();
     }
 
     /*
      * Set a breakpoint here (break js::CompartmentChecker::fail) to debug
      * compartment mismatches.
      */
     static void fail(JSCompartment *c1, JSCompartment *c2) {
@@ -725,53 +685,23 @@ assertSameCompartment(JSContext *cx, T1 
     c.check(t3);
     c.check(t4);
     c.check(t5);
 #endif
 }
 
 #undef START_ASSERT_SAME_COMPARTMENT
 
-namespace detail {
-
-class AutoScopeChainSetter {
-    JSContext * const cx;
-    JSObject * const oldLastNativeCalleeScope;
-    void * const oldLastNativeCalleeScopePtr;
-    JSObject * const scope;
-    JS_DECL_USE_GUARD_OBJECT_NOTIFIER
-
-  public:
-    AutoScopeChainSetter(JSContext *cx, JSObject *scope, void *scopePtr
-                         JS_GUARD_OBJECT_NOTIFIER_PARAM)
-      : cx(cx),
-        oldLastNativeCalleeScope(cx->lastNativeCalleeScope),
-        oldLastNativeCalleeScopePtr(cx->lastNativeCalleeScopePtr),
-        scope(scope)
-    {
-        JS_GUARD_OBJECT_NOTIFIER_INIT;
-        cx->lastNativeCalleeScope = scope;
-        cx->lastNativeCalleeScopePtr = scopePtr;
-    }
-    ~AutoScopeChainSetter() {
-        cx->lastNativeCalleeScope = oldLastNativeCalleeScope;
-        cx->lastNativeCalleeScopePtr = oldLastNativeCalleeScopePtr;
-    }
-};
-
-}
-
 STATIC_PRECONDITION_ASSUME(ubound(vp) >= argc + 2)
 JS_ALWAYS_INLINE bool
 CallJSNative(JSContext *cx, js::Native native, uintN argc, js::Value *vp)
 {
 #ifdef DEBUG
     JSBool alreadyThrowing = cx->isExceptionPending();
 #endif
-    detail::AutoScopeChainSetter scs(cx, &vp[0].toObject(), vp);
     assertSameCompartment(cx, ValueArray(vp, argc + 2));
     JSBool ok = native(cx, argc, vp);
     if (ok) {
         assertSameCompartment(cx, vp[0]);
         JS_ASSERT_IF(!alreadyThrowing, !cx->isExceptionPending());
     }
     return ok;
 }
@@ -812,39 +742,27 @@ CallJSNativeConstructor(JSContext *cx, j
 
     return true;
 }
 
 JS_ALWAYS_INLINE bool
 CallJSPropertyOp(JSContext *cx, js::PropertyOp op, JSObject *obj, jsid id, js::Value *vp)
 {
     assertSameCompartment(cx, obj, id, *vp);
-
-    /*
-     * This property access may occur not in relation to a stack location, so
-     * we can't use |vp| here.  However, since we use the location only in
-     * comparisons, to determine when to refer to the last interpreted frame's
-     * scope chain versus the last native callee's global object, the first
-     * unused location at the end of the stack will suffice.
-     */
-    detail::AutoScopeChainSetter scs(cx, obj, cx->stack().constFirstUnused());
     JSBool ok = op(cx, obj, id, vp);
     if (ok)
         assertSameCompartment(cx, obj, *vp);
     return ok;
 }
 
 JS_ALWAYS_INLINE bool
 CallJSPropertyOpSetter(JSContext *cx, js::StrictPropertyOp op, JSObject *obj, jsid id,
                        JSBool strict, js::Value *vp)
 {
     assertSameCompartment(cx, obj, id, *vp);
-
-    /* See the comment in CallJSPropertyOp for an explanation. */
-    detail::AutoScopeChainSetter scs(cx, obj, cx->stack().constFirstUnused());
     return op(cx, obj, id, strict, vp);
 }
 
 inline bool
 CallSetter(JSContext *cx, JSObject *obj, jsid id, js::StrictPropertyOp op, uintN attrs,
            uintN shortid, JSBool strict, js::Value *vp)
 {
     if (attrs & JSPROP_SETTER)
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -214,22 +214,29 @@ JSCompartment::wrap(JSContext *cx, Value
             return true;
         }
     }
 
     /*
      * Wrappers should really be parented to the wrapped parent of the wrapped
      * object, but in that case a wrapped global object would have a NULL
      * parent without being a proper global object (JSCLASS_IS_GLOBAL). Instead
+,
      * we parent all wrappers to the global object in their home compartment.
      * This loses us some transparency, and is generally very cheesy.
      */
-    JSObject *global = cx->getGlobalFromScopeChain();
-    if (!global)
-        return false;
+    JSObject *global;
+    if (cx->hasfp()) {
+        global = cx->fp()->scopeChain().getGlobal();
+    } else {
+        global = cx->globalObject;
+        OBJ_TO_INNER_OBJECT(cx, global);
+        if (!global)
+            return false;
+    }
 
     /* Unwrap incoming objects. */
     if (vp->isObject()) {
         JSObject *obj = &vp->toObject();
 
         /* If the object is already in this compartment, we are done. */
         if (obj->compartment() == this)
             return true;
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -137,16 +137,43 @@ JSStackFrame::pc(JSContext *cx, JSStackF
     js::mjit::JITScript *jit = script()->getJIT(isConstructing());
     return jit->nativeToPC(next->ncode_);
 #else
     JS_NOT_REACHED("Unknown PC for frame");
     return NULL;
 #endif
 }
 
+JSObject *
+js::GetScopeChain(JSContext *cx)
+{
+    JSStackFrame *fp = js_GetTopStackFrame(cx);
+    if (!fp) {
+        /*
+         * There is no code active on this context. In place of an actual
+         * scope chain, use the context's global object, which is set in
+         * js_InitFunctionAndObjectClasses, and which represents the default
+         * scope chain for the embedding. See also js_FindClassObject.
+         *
+         * For embeddings that use the inner and outer object hooks, the inner
+         * object represents the ultimate global object, with the outer object
+         * acting as a stand-in.
+         */
+        JSObject *obj = cx->globalObject;
+        if (!obj) {
+            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INACTIVE);
+            return NULL;
+        }
+
+        OBJ_TO_INNER_OBJECT(cx, obj);
+        return obj;
+    }
+    return GetScopeChain(cx, fp, ORIGIN_GET_SCOPE_CHAIN_API);
+}
+
 /*
  * This computes the blockChain by iterating through the bytecode
  * of the current script until it reaches the PC. Each time it sees
  * an ENTERBLOCK or LEAVEBLOCK instruction, it records the new
  * blockChain. A faster variant of this function that doesn't
  * require bytecode scanning appears below.
  */
 JSObject *
--- a/js/src/jsinterp.h
+++ b/js/src/jsinterp.h
@@ -798,16 +798,19 @@ namespace js {
 static const size_t VALUES_PER_STACK_FRAME = sizeof(JSStackFrame) / sizeof(Value);
 
 extern JSObject *
 GetBlockChain(JSContext *cx, JSStackFrame *fp);
 
 extern JSObject *
 GetBlockChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen);
 
+extern JSObject *
+GetScopeChain(JSContext *cx);
+
 /*
  * Refresh and return fp->scopeChain.  It may be stale if block scopes are
  * active but not yet reflected by objects in the scope chain.  If a block
  * scope contains a with, eval, XML filtering predicate, or similar such
  * dynamically scoped construct, then compile-time block scope at fp->blocks
  * must reflect at runtime.
  */
 extern JSObject *
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -4237,27 +4237,43 @@ js_SetClassObject(JSContext *cx, JSObjec
     return js_SetReservedSlot(cx, obj, key, ObjectOrNullValue(cobj)) &&
            js_SetReservedSlot(cx, obj, JSProto_LIMIT + key, ObjectOrNullValue(proto));
 }
 
 JSBool
 js_FindClassObject(JSContext *cx, JSObject *start, JSProtoKey protoKey,
                    Value *vp, Class *clasp)
 {
+    JSStackFrame *fp;
     JSObject *obj, *cobj, *pobj;
     jsid id;
     JSProperty *prop;
     const Shape *shape;
 
+    /*
+     * Find the global object. Use cx->fp() directly to avoid falling off
+     * trace; all JIT-elided stack frames have the same global object as
+     * cx->fp().
+     */
+    VOUCH_DOES_NOT_REQUIRE_STACK();
+    if (!start && (fp = cx->maybefp()) != NULL)
+        start = &fp->scopeChain();
+
     if (start) {
-        obj = start->getGlobal();
+        /* Find the topmost object in the scope chain. */
+        do {
+            obj = start;
+            start = obj->getParent();
+        } while (start);
     } else {
-        obj = cx->getGlobalFromScopeChain();
-        if (!obj)
-            return JS_FALSE;
+        obj = cx->globalObject;
+        if (!obj) {
+            vp->setUndefined();
+            return JS_TRUE;
+        }
     }
 
     OBJ_TO_INNER_OBJECT(cx, obj);
     if (!obj)
         return JS_FALSE;
 
     if (protoKey != JSProto_Null) {
         JS_ASSERT(JSProto_Null < protoKey);
@@ -6168,19 +6184,25 @@ js_GetClassPrototype(JSContext *cx, JSOb
                      JSObject **protop, Class *clasp)
 {
     VOUCH_DOES_NOT_REQUIRE_STACK();
     JS_ASSERT(JSProto_Null <= protoKey);
     JS_ASSERT(protoKey < JSProto_LIMIT);
 
     if (protoKey != JSProto_Null) {
         if (!scopeobj) {
-            scopeobj = cx->getGlobalFromScopeChain();
-            if (!scopeobj)
-                return false;
+            if (cx->hasfp())
+                scopeobj = &cx->fp()->scopeChain();
+            if (!scopeobj) {
+                scopeobj = cx->globalObject;
+                if (!scopeobj) {
+                    *protop = NULL;
+                    return true;
+                }
+            }
         }
         scopeobj = scopeobj->getGlobal();
         if (scopeobj->isGlobal()) {
             const Value &v = scopeobj->getReservedSlot(JSProto_LIMIT + protoKey);
             if (v.isObject()) {
                 *protop = &v.toObject();
                 return true;
             }
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -965,19 +965,25 @@ static inline JSObject *
 NewBuiltinClassInstance(JSContext *cx, Class *clasp, gc::FinalizeKind kind)
 {
     VOUCH_DOES_NOT_REQUIRE_STACK();
 
     JSProtoKey protoKey = JSCLASS_CACHED_PROTO_KEY(clasp);
     JS_ASSERT(protoKey != JSProto_Null);
 
     /* NB: inline-expanded and specialized version of js_GetClassPrototype. */
-    JSObject *global = cx->getGlobalFromScopeChain();
-    if (!global)
-        return NULL;
+    JSObject *global;
+    if (!cx->hasfp()) {
+        global = cx->globalObject;
+        OBJ_TO_INNER_OBJECT(cx, global);
+        if (!global)
+            return NULL;
+    } else {
+        global = cx->fp()->scopeChain().getGlobal();
+    }
     JS_ASSERT(global->isGlobal());
 
     const Value &v = global->getReservedSlot(JSProto_LIMIT + protoKey);
     JSObject *proto;
     if (v.isObject()) {
         proto = &v.toObject();
         JS_ASSERT(proto->getParent() == global);
     } else {
--- a/js/src/jsparse.cpp
+++ b/js/src/jsparse.cpp
@@ -8947,20 +8947,17 @@ Parser::primaryExpr(TokenKind tt, JSBool
       case TOK_REGEXP:
       {
         pn = NullaryNode::create(tc);
         if (!pn)
             return NULL;
 
         JSObject *obj;
         if (context->hasfp()) {
-            RegExpStatics *res = context->getRegExpStatics();
-            if (!res)
-                return NULL;
-            obj = RegExp::createObject(context, res,
+            obj = RegExp::createObject(context, context->regExpStatics(),
                                        tokenStream.getTokenbuf().begin(),
                                        tokenStream.getTokenbuf().length(),
                                        tokenStream.currentToken().t_reflags);
         } else {
             obj = RegExp::createObjectNoStatics(context,
                                                 tokenStream.getTokenbuf().begin(),
                                                 tokenStream.getTokenbuf().length(),
                                                 tokenStream.currentToken().t_reflags);
--- a/js/src/jsregexp.cpp
+++ b/js/src/jsregexp.cpp
@@ -145,19 +145,17 @@ js_CloneRegExpObject(JSContext *cx, JSOb
         return NULL;
 
     /* 
      * This clone functionality does not duplicate the JITted code blob, which is necessary for
      * cross-compartment cloning functionality.
      */
     assertSameCompartment(cx, obj, clone);
 
-    RegExpStatics *res = cx->getRegExpStatics();
-    if (!res)
-        return NULL;
+    RegExpStatics *res = cx->regExpStatics();
     RegExp *re = RegExp::extractFrom(obj);
     {
         uint32 origFlags = re->getFlags();
         uint32 staticsFlags = res->getFlags();
         if ((origFlags & staticsFlags) != staticsFlags) {
             /*
              * This regex is lacking flags from the statics, so we must recompile with the new
              * flags instead of increffing.
@@ -398,19 +396,17 @@ regexp_resolve(JSContext *cx, JSObject *
  *  RegExp.leftContext          $`
  *  RegExp.rightContext         $'
  */
 
 #define DEFINE_STATIC_GETTER(name, code)                                        \
     static JSBool                                                               \
     name(JSContext *cx, JSObject *obj, jsid id, jsval *vp)                      \
     {                                                                           \
-        RegExpStatics *res = cx->getRegExpStatics();                            \
-        if (!res)                                                               \
-            return false;                                                       \
+        RegExpStatics *res = cx->regExpStatics();                               \
         code;                                                                   \
     }
 
 DEFINE_STATIC_GETTER(static_input_getter,        return res->createPendingInput(cx, Valueify(vp)))
 DEFINE_STATIC_GETTER(static_multiline_getter,    *vp = BOOLEAN_TO_JSVAL(res->multiline());
                                                  return true)
 DEFINE_STATIC_GETTER(static_lastMatch_getter,    return res->createLastMatch(cx, Valueify(vp)))
 DEFINE_STATIC_GETTER(static_lastParen_getter,    return res->createLastParen(cx, Valueify(vp)))
@@ -426,19 +422,17 @@ DEFINE_STATIC_GETTER(static_paren6_gette
 DEFINE_STATIC_GETTER(static_paren7_getter,       return res->createParen(cx, 7, Valueify(vp)))
 DEFINE_STATIC_GETTER(static_paren8_getter,       return res->createParen(cx, 8, Valueify(vp)))
 DEFINE_STATIC_GETTER(static_paren9_getter,       return res->createParen(cx, 9, Valueify(vp)))
 
 #define DEFINE_STATIC_SETTER(name, code)                                        \
     static JSBool                                                               \
     name(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)       \
     {                                                                           \
-        RegExpStatics *res = cx->getRegExpStatics();                            \
-        if (!res)                                                               \
-            return false;                                                       \
+        RegExpStatics *res = cx->regExpStatics();                               \
         code;                                                                   \
         return true;                                                            \
     }
 
 DEFINE_STATIC_SETTER(static_input_setter,
                      if (!JSVAL_IS_STRING(*vp) && !JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp))
                          return false;
                      res->setPendingInput(JSVAL_TO_STRING(*vp)))
@@ -673,20 +667,17 @@ EscapeNakedForwardSlashes(JSContext *cx,
         return escaped;
     }
     return unescaped;
 }
 
 static bool
 SwapRegExpInternals(JSContext *cx, JSObject *obj, Value *rval, JSString *str, uint32 flags = 0)
 {
-    RegExpStatics *res = cx->getRegExpStatics();
-    if (!res)
-        return false;
-    flags |= res->getFlags();
+    flags |= cx->regExpStatics()->getFlags();
     AlreadyIncRefed<RegExp> re = RegExp::create(cx, str, flags);
     if (!re)
         return false;
     SwapObjectRegExp(cx, obj, re);
     *rval = ObjectValue(*obj);
     return true;
 }
 
@@ -717,19 +708,17 @@ regexp_exec_sub(JSContext *cx, JSObject 
             else if (!ValueToNumber(cx, v, &lastIndex))
                 return JS_FALSE;
             lastIndex = js_DoubleToInteger(lastIndex);
         }
     } else {
         lastIndex = 0;
     }
 
-    RegExpStatics *res = cx->getRegExpStatics();
-    if (!res)
-        return false;
+    RegExpStatics *res = cx->regExpStatics();
 
     JSString *input;
     if (argc) {
         input = js_ValueToString(cx, argv[0]);
         if (!input)
             return false;
         argv[0] = StringValue(input);
     } else {
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -1871,18 +1871,18 @@ str_match(JSContext *cx, uintN argc, Val
         return false;
 
     const RegExpPair *rep = g.normalizeRegExp(false, 1, argc, vp);
     if (!rep)
         return false;
 
     AutoObjectRooter array(cx);
     MatchArgType arg = array.addr();
-    RegExpStatics *res = cx->getRegExpStatics();
-    if (!res || !DoMatch(cx, res, vp, str, *rep, MatchCallback, arg, MATCH_ARGS))
+    RegExpStatics *res = cx->regExpStatics();
+    if (!DoMatch(cx, res, vp, str, *rep, MatchCallback, arg, MATCH_ARGS))
         return false;
 
     /* When not global, DoMatch will leave |RegExp.exec()| in *vp. */
     if (rep->re().global())
         vp->setObjectOrNull(array.object());
     return true;
 }
 
@@ -1901,19 +1901,17 @@ str_search(JSContext *cx, uintN argc, Va
         return true;
     }
     if (cx->isExceptionPending())  /* from tryFlatMatch */
         return false;
     const RegExpPair *rep = g.normalizeRegExp(false, 1, argc, vp);
     if (!rep)
         return false;
 
-    RegExpStatics *res = cx->getRegExpStatics();
-    if (!res)
-        return false;
+    RegExpStatics *res = cx->regExpStatics();
     size_t i = 0;
     if (!rep->re().execute(cx, res, str, &i, true, vp))
         return false;
 
     if (vp->isTrue())
         vp->setInt32(res->matchStart());
     else
         vp->setInt32(-1);
@@ -2354,19 +2352,17 @@ str_replace_regexp(JSContext *cx, uintN 
 {
     const RegExpPair *rep = rdata.g.normalizeRegExp(true, 2, argc, vp);
     if (!rep)
         return false;
 
     rdata.leftIndex = 0;
     rdata.calledBack = false;
 
-    RegExpStatics *res = cx->getRegExpStatics();
-    if (!res)
-        return false;
+    RegExpStatics *res = cx->regExpStatics();
     if (!DoMatch(cx, res, vp, rdata.str, *rep, ReplaceRegExpCallback, &rdata, REPLACE_ARGS))
         return false;
 
     if (!rdata.calledBack) {
         /* Didn't match, so the string is unmodified. */
         vp->setString(rdata.str);
         return true;
     }
@@ -2696,19 +2692,17 @@ str_split(JSContext *cx, uintN argc, Val
         /* Clamp limit between 0 and 1 + string length. */
         limit = js_DoubleToECMAUint32(d);
         if (limit > str->length())
             limit = 1 + str->length();
     }
 
     AutoValueVector splits(cx);
 
-    RegExpStatics *res = cx->getRegExpStatics();
-    if (!res)
-        return false;
+    RegExpStatics *res = cx->regExpStatics();
     jsint i, j;
     uint32 len = i = 0;
     while ((j = find_split(cx, res, str, re, &i, sep)) >= 0) {
         if (limited && len >= limit)
             break;
 
         JSString *sub = js_NewDependentString(cx, str, i, size_t(j - i));
         if (!sub || !splits.append(StringValue(sub)))
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -1672,42 +1672,16 @@ GetXMLSettingFlags(JSContext *cx, uintN 
 
     *flagsp = 0;
     for (size_t n = 0; n < 4; ++n)
         if (flag[n])
             *flagsp |= JS_BIT(n);
     return true;
 }
 
-static JSObject *
-GetXMLScopeChain(JSContext *cx)
-{
-    if (JSStackFrame *fp = js_GetTopStackFrame(cx))
-        return GetScopeChain(cx, fp, ORIGIN_LAME);
-
-    /*
-     * There is no code active on this context. In place of an actual scope
-     * chain, use the context's global object, which is set in
-     * s_InitFunctionAndObjectClasses, and which represents the default scope
-     * chain for the embedding. See also js_FindClassObject.
-     *
-     * For embeddings that use the inner and outer object hooks, the inner
-     * object represents the ultimate global object, with the outer object
-     * acting as a stand-in.
-     */
-    JSObject *obj = cx->globalObject;
-    if (!obj) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INACTIVE);
-        return NULL;
-    }
-
-    OBJ_TO_INNER_OBJECT(cx, obj);
-    return obj;
-}
-
 static JSXML *
 ParseXMLSource(JSContext *cx, JSString *src)
 {
     jsval nsval;
     JSLinearString *uri;
     size_t urilen, srclen, length, offset, dstlen;
     jschar *chars;
     const jschar *srcp, *endp;
@@ -1777,17 +1751,17 @@ ParseXMLSource(JSContext *cx, JSString *
                     --lineno;
             }
         }
     }
 
     {
         Parser parser(cx);
         if (parser.init(chars, length, filename, lineno, cx->findVersion())) {
-            JSObject *scopeChain = GetXMLScopeChain(cx);
+            JSObject *scopeChain = GetScopeChain(cx);
             if (!scopeChain) {
                 cx->free(chars);
                 return NULL;
             }
             JSParseNode *pn = parser.parseXMLText(scopeChain, false);
             uintN flags;
             if (pn && GetXMLSettingFlags(cx, &flags)) {
                 AutoNamespaceArray namespaces(cx);
@@ -7252,17 +7226,17 @@ js_GetFunctionNamespace(JSContext *cx, V
  * is really the only usefully stored value of the default namespace.
  */
 JSBool
 js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp)
 {
     JSObject *ns, *obj, *tmp;
     jsval v;
 
-    JSObject *scopeChain = GetXMLScopeChain(cx);
+    JSObject *scopeChain = GetScopeChain(cx);
 
     obj = NULL;
     for (tmp = scopeChain; tmp; tmp = tmp->getParent()) {
         Class *clasp = tmp->getClass();
         if (clasp == &js_BlockClass || clasp == &js_WithClass)
             continue;
         if (!tmp->getProperty(cx, JS_DEFAULT_XML_NAMESPACE_ID, Valueify(&v)))
             return JS_FALSE;
--- a/js/src/methodjit/MonoIC.cpp
+++ b/js/src/methodjit/MonoIC.cpp
@@ -803,29 +803,19 @@ class CallCompiler : public BaseCompiler
             return false;
 
         if (callingNew)
             vp[1].setMagicWithObjectOrNullPayload(NULL);
 
         if (!CallJSNative(cx, fun->u.n.native, ic.frameSize.getArgc(f), vp))
             THROWV(true);
 
-        /*
-         * Right now, take slow-path for IC misses or multiple stubs. Also take
-         * it if the call crosses, or might cross, globals: in that case
-         * JSContext::getGlobalFromScopeChain requires we note the change of
-         * global.
-         */
-        if (ic.fastGuardedNative ||
-            ic.hasJsFunCheck ||
-            !f.regs.fp->script()->compileAndGo ||
-            obj->getGlobal() != f.regs.fp->scopeChain().getGlobal())
-        {
+        /* Right now, take slow-path for IC misses or multiple stubs. */
+        if (ic.fastGuardedNative || ic.hasJsFunCheck)
             return true;
-        }
 
         /* Native MIC needs to warm up first. */
         if (!ic.hit) {
             ic.hit = true;
             return true;
         }
 
         /* Generate fast-path for calling this native. */
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -4351,50 +4351,16 @@ MJitStats(JSContext *cx, uintN argc, jsv
 
 JSBool
 StringStats(JSContext *cx, uintN argc, jsval *vp)
 {
     JS_SET_RVAL(cx, vp, INT_TO_JSVAL(cx->runtime->stringMemoryUsed));
     return true;
 }
 
-enum CompartmentKind { SAME_COMPARTMENT, NEW_COMPARTMENT };
-
-static JSObject *
-NewGlobalObject(JSContext *cx, CompartmentKind compartment);
-
-JSBool
-NewGlobal(JSContext *cx, uintN argc, jsval *vp)
-{
-    if (argc != 1 || !JSVAL_IS_STRING(JS_ARGV(cx, vp)[0])) {
-        JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "newGlobal");
-        return false;
-    }
-
-    JSString *str = JSVAL_TO_STRING(JS_ARGV(cx, vp)[0]);
-
-    JSBool equalSame = JS_FALSE, equalNew = JS_FALSE;
-    if (!JS_StringEqualsAscii(cx, str, "same-compartment", &equalSame) ||
-        !JS_StringEqualsAscii(cx, str, "new-compartment", &equalNew)) {
-        return false;
-    }
-
-    if (!equalSame && !equalNew) {
-        JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "newGlobal");
-        return false;
-    }
-
-    JSObject *global = NewGlobalObject(cx, equalSame ? SAME_COMPARTMENT : NEW_COMPARTMENT);
-    if (!global)
-        return false;
-
-    JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(global));
-    return true;
-}
-
 static JSFunctionSpec shell_functions[] = {
     JS_FN("version",        Version,        0,0),
     JS_FN("revertVersion",  RevertVersion,  0,0),
     JS_FN("options",        Options,        0,0),
     JS_FN("load",           Load,           1,0),
     JS_FN("evaluate",       Evaluate,       1,0),
     JS_FN("run",            Run,            1,0),
     JS_FN("readline",       ReadLine,       0,0),
@@ -4481,17 +4447,16 @@ static JSFunctionSpec shell_functions[] 
     JS_FN("parent",         Parent,         1,0),
     JS_FN("wrap",           Wrap,           1,0),
     JS_FN("serialize",      Serialize,      1,0),
     JS_FN("deserialize",    Deserialize,    1,0),
 #ifdef JS_METHODJIT
     JS_FN("mjitstats",      MJitStats,      0,0),
 #endif
     JS_FN("stringstats",    StringStats,    0,0),
-    JS_FN("newGlobal",      NewGlobal,      1,0),
     JS_FS_END
 };
 
 static const char shell_help_header[] =
 "Command                  Description\n"
 "=======                  ===========\n";
 
 static const char *const shell_help_messages[] = {
@@ -4507,17 +4472,17 @@ static const char *const shell_help_mess
 "print([exp ...])         Evaluate and print expressions",
 "putstr([exp])            Evaluate and print expression without newline",
 "dateNow()                    Return the current time with sub-ms precision",
 "help([name ...])         Display usage and help messages",
 "quit()                   Quit the shell",
 "assertEq(actual, expected[, msg])\n"
 "  Throw if the first two arguments are not the same (both +0 or both -0,\n"
 "  both NaN, or non-zero and ===)",
-"assertJit()              Throw if the calling function failed to JIT",
+"assertJit()              Throw if the calling function failed to JIT\n",
 "gc()                     Run the garbage collector",
 #ifdef JS_GCMETER
 "gcstats()                Print garbage collector statistics",
 #endif
 "gcparam(name, value)\n"
 "  Wrapper for JS_SetGCParameter. The name must be either 'maxBytes' or\n"
 "  'maxMallocBytes' and the value must be convertable to a positive uint32",
 "countHeap([start[, kind]])\n"
@@ -4552,17 +4517,17 @@ static const char *const shell_help_mess
 "    \"-r\" (disassemble recursively)\n"
 "    \"-l\" (show line numbers)",
 "dissrc([fun])            Disassemble functions with source lines",
 "dumpHeap([fileName[, start[, toFind[, maxDepth[, toIgnore]]]]])\n"
 "  Interface to JS_DumpHeap with output sent to file",
 "dumpObject()             Dump an internal representation of an object",
 "notes([fun])             Show source notes for functions",
 "tracing([true|false|filename]) Turn bytecode execution tracing on/off.\n"
-"                         With filename, send to file.",
+"                         With filename, send to file.\n",
 "stats([string ...])      Dump 'arena', 'atom', 'global' stats",
 #endif
 #ifdef TEST_CVTARGS
 "cvtargs(arg1..., arg12)  Test argument formatter",
 #endif
 "build()                  Show build date and time",
 "clear([obj])             Clear properties of object",
 "intern(str)              Internalize str in the atom table",
@@ -4603,62 +4568,48 @@ static const char *const shell_help_mess
 "snarf(filename)          Read filename into returned string",
 "read(filename)           Synonym for snarf",
 "compile(code)            Compiles a string to bytecode, potentially throwing",
 "parse(code)              Parses a string, potentially throwing",
 "timeout([seconds])\n"
 "  Get/Set the limit in seconds for the execution time for the current context.\n"
 "  A negative value (default) means that the execution time is unlimited.",
 "elapsed()                Execution time elapsed for the current context.",
-"parent(obj)              Returns the parent of obj.",
-"wrap(obj)                Wrap an object into a noop wrapper.",
-"serialize(sd)            Serialize sd using JS_WriteStructuredClone. Returns a TypedArray.",
-"deserialize(a)           Deserialize data generated by serialize.",
+"parent(obj)              Returns the parent of obj.\n",
+"wrap(obj)                Wrap an object into a noop wrapper.\n",
+"serialize(sd)            Serialize sd using JS_WriteStructuredClone. Returns a TypedArray.\n",
+"deserialize(a)           Deserialize data generated by serialize.\n",
 #ifdef JS_METHODJIT
-"mjitstats()              Return stats on mjit memory usage.",
+"mjitstats()              Return stats on mjit memory usage.\n",
 #endif
-"stringstats()            Return stats on string memory usage.",
-"newGlobal(kind)          Return a new global object, in the current\n"
-"                         compartment if kind === 'same-compartment' or in a\n"
-"                         new compartment if kind === 'new-compartment'",
-
-/* Keep these last: see the static assertion below. */
+"stringstats()            Return stats on string memory usage.\n"
 #ifdef MOZ_PROFILING
 "startProfiling()         Start a profiling session.\n"
-"                         Profiler must be running with programatic sampling",
-"stopProfiling()          Stop a running profiling session\n"
+"                         Profiler must be running with programatic sampling\n"
+"stopProfiling()          Stop a running profiling session"
 #endif
 };
 
-#ifdef MOZ_PROFILING
-#define PROFILING_FUNCTION_COUNT 2
-#else
-#define PROFILING_FUNCTION_COUNT 0
-#endif
-
 /* Help messages must match shell functions. */
-JS_STATIC_ASSERT(JS_ARRAY_LENGTH(shell_help_messages) - PROFILING_FUNCTION_COUNT ==
-                 JS_ARRAY_LENGTH(shell_functions) - 1 /* JS_FS_END */);
-
-#undef PROFILING_FUNCTION_COUNT
+JS_STATIC_ASSERT(JS_ARRAY_LENGTH(shell_help_messages) + 1 ==
+                 JS_ARRAY_LENGTH(shell_functions));
 
 #ifdef DEBUG
 static void
 CheckHelpMessages()
 {
     const char *const *m;
     const char *lp;
 
-    /* Messages begin with "function_name(" prefix and don't end with \n. */
+    /* Each message must begin with "function_name(" prefix. */
     for (m = shell_help_messages; m != JS_ARRAY_END(shell_help_messages); ++m) {
         lp = strchr(*m, '(');
         JS_ASSERT(lp);
         JS_ASSERT(memcmp(shell_functions[m - shell_help_messages].name,
                          *m, lp - *m) == 0);
-        JS_ASSERT((*m)[strlen(*m) - 1] != '\n');
     }
 }
 #else
 # define CheckHelpMessages() ((void) 0)
 #endif
 
 static JSBool
 Help(JSContext *cx, uintN argc, jsval *vp)
@@ -5468,82 +5419,74 @@ DestroyContext(JSContext *cx, bool withG
 {
     JSShellContextData *data = GetContextData(cx);
     JS_SetContextPrivate(cx, NULL);
     free(data);
     WITH_SIGNALS_DISABLED(withGC ? JS_DestroyContext(cx) : JS_DestroyContextNoGC(cx));
 }
 
 static JSObject *
-NewGlobalObject(JSContext *cx, CompartmentKind compartment)
+NewGlobalObject(JSContext *cx)
 {
-    JSObject *glob = (compartment == NEW_COMPARTMENT)
-                     ? JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL)
-                     : JS_NewGlobalObject(cx, &global_class);
+    JSObject *glob = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL);
     if (!glob)
         return NULL;
 
-    {
-        JSAutoEnterCompartment ac;
-        if (!ac.enter(cx, glob))
-            return NULL;
-
-#ifndef LAZY_STANDARD_CLASSES
-        if (!JS_InitStandardClasses(cx, glob))
-            return NULL;
+    JSAutoEnterCompartment ac;
+    if (!ac.enter(cx, glob))
+        return NULL;
+
+#ifdef LAZY_STANDARD_CLASSES
+    JS_SetGlobalObject(cx, glob);
+#else
+    if (!JS_InitStandardClasses(cx, glob))
+        return NULL;
 #endif
-
 #ifdef JS_HAS_CTYPES
-        if (!JS_InitCTypesClass(cx, glob))
-            return NULL;
+    if (!JS_InitCTypesClass(cx, glob))
+        return NULL;
 #endif
-        if (!JS::RegisterPerfMeasurement(cx, glob))
-            return NULL;
-        if (!JS_DefineFunctions(cx, glob, shell_functions) ||
-            !JS_DefineProfilingFunctions(cx, glob)) {
-            return NULL;
-        }
-
-        JSObject *it = JS_DefineObject(cx, glob, "it", &its_class, NULL, 0);
-        if (!it)
-            return NULL;
-        if (!JS_DefineProperties(cx, it, its_props))
-            return NULL;
-        if (!JS_DefineFunctions(cx, it, its_methods))
-            return NULL;
-
-        if (!JS_DefineProperty(cx, glob, "custom", JSVAL_VOID, its_getter,
-                               its_setter, 0))
-            return NULL;
-        if (!JS_DefineProperty(cx, glob, "customRdOnly", JSVAL_VOID, its_getter,
-                               its_setter, JSPROP_READONLY))
-            return NULL;
-    }
-
-    if (compartment == NEW_COMPARTMENT && !JS_WrapObject(cx, &glob))
+    if (!JS::RegisterPerfMeasurement(cx, glob))
+        return NULL;
+    if (!JS_DefineFunctions(cx, glob, shell_functions) ||
+        !JS_DefineProfilingFunctions(cx, glob)) {
+        return NULL;
+    }
+
+    JSObject *it = JS_DefineObject(cx, glob, "it", &its_class, NULL, 0);
+    if (!it)
+        return NULL;
+    if (!JS_DefineProperties(cx, it, its_props))
+        return NULL;
+    if (!JS_DefineFunctions(cx, it, its_methods))
+        return NULL;
+
+    if (!JS_DefineProperty(cx, glob, "custom", JSVAL_VOID, its_getter,
+                           its_setter, 0))
+        return NULL;
+    if (!JS_DefineProperty(cx, glob, "customRdOnly", JSVAL_VOID, its_getter,
+                           its_setter, JSPROP_READONLY))
         return NULL;
 
     return glob;
 }
 
 int
 Shell(JSContext *cx, int argc, char **argv, char **envp)
 {
     JSAutoRequest ar(cx);
 
-    JSObject *glob = NewGlobalObject(cx, NEW_COMPARTMENT);
+    JSObject *glob = NewGlobalObject(cx);
     if (!glob)
         return 1;
 
     JSAutoEnterCompartment ac;
     if (!ac.enter(cx, glob))
         return 1;
 
-    JS_SetGlobalObject(cx, glob);
-
     JSObject *envobj = JS_DefineObject(cx, glob, "environment", &env_class, NULL, 0);
     if (!envobj || !JS_SetPrivate(cx, envobj, envp))
         return 1;
 
 #ifdef JSDEBUGGER
     /*
     * XXX A command line option to enable debugging (or not) would be good
     */
@@ -5570,17 +5513,17 @@ Shell(JSContext *cx, int argc, char **ar
     jsdbc = JSDB_InitDebugger(rt, jsdc, 0);
 #endif /* JSDEBUGGER_C_UI */
 #endif /* JSDEBUGGER */
 
 #ifdef JS_THREADSAFE
     class ShellWorkerHooks : public js::workers::WorkerHooks {
     public:
         JSObject *newGlobalObject(JSContext *cx) {
-            return NewGlobalObject(cx, NEW_COMPARTMENT);
+            return NewGlobalObject(cx);
         }
     };
     ShellWorkerHooks hooks;
     if (!JS_AddNamedObjectRoot(cx, &gWorkers, "Workers") ||
         (gWorkerThreadPool = js::workers::init(cx, &hooks, glob, &gWorkers)) == NULL) {
         return 1;
     }
 #endif
deleted file mode 100644
--- a/js/src/tests/e4x/extensions/cross-global-settings.js
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/licenses/publicdomain/
- */
-
-var gTestfile = 'cross-global-settings.js';
-//-----------------------------------------------------------------------------
-var BUGNUMBER = 631135;
-var summary =
-  "Look at the callee's global.XML.* setting values, not the caller's";
-
-print(BUGNUMBER + ": " + summary);
-
-/**************
- * BEGIN TEST *
- **************/
-
-var otherGlobal = newGlobal("same-compartment");
-otherGlobal.XML.prettyPrinting = true;
-otherGlobal.XML.prettyIndent = 2;
-otherGlobal.indent = "  ";
-
-XML.prettyPrinting = true;
-XML.prettyIndent = 16;
-
-var indent = "    " +
-             "    " +
-             "    " +
-             "    ";
-
-var str = otherGlobal.XML("<a><b/><c/></a>").toXMLString();
-
-assertEq(str.indexOf(indent), -1);
-assertEq(str.indexOf(otherGlobal.indent) > 0, true);
-
-/******************************************************************************/
-
-if (typeof reportCompare === "function")
-  reportCompare(true, true);
-
-print("All tests passed!");
--- a/js/src/tests/e4x/extensions/jstests.list
+++ b/js/src/tests/e4x/extensions/jstests.list
@@ -17,9 +17,8 @@ script regress-354151-02.js
 script regress-374025.js
 script regress-374163.js
 script regress-410192.js
 script regress-450871-01.js
 script regress-450871-02.js
 script regress-462734-01.js
 script extensibility.js
 script regress-595207.js
-skip-if(!xulRuntime.shell) script cross-global-settings.js
deleted file mode 100644
--- a/js/src/tests/ecma_5/extensions/cross-global-call.js
+++ /dev/null
@@ -1,70 +0,0 @@
-// Any copyright is dedicated to the Public Domain.
-// http://creativecommons.org/licenses/publicdomain/
-
-//-----------------------------------------------------------------------------
-var BUGNUMBER = 631135;
-var summary =
-  "Objects created by/for natives are created for the caller's scope, not " +
-  "for the native's scope";
-
-print(BUGNUMBER + ": " + summary);
-
-/**************
- * BEGIN TEST *
- **************/
-
-var otherGlobal = newGlobal("same-compartment");
-
-function makeArray()
-{
-  return new otherGlobal.Array();
-}
-
-var a;
-
-a = makeArray();
-assertEq(a instanceof otherGlobal.Array, true);
-assertEq(a instanceof Array, false);
-a = makeArray();
-assertEq(a instanceof otherGlobal.Array, true);
-assertEq(a instanceof Array, false);
-a = makeArray();
-assertEq(a instanceof otherGlobal.Array, true);
-assertEq(a instanceof Array, false);
-
-for (var i = 0; i < 3; i++)
-{
-  a = new otherGlobal.Array();
-  assertEq(a instanceof otherGlobal.Array, true);
-  assertEq(a instanceof Array, false);
-}
-
-
-var res = otherGlobal.Array.prototype.slice.call([1, 2, 3], 0, 1);
-assertEq(res instanceof otherGlobal.Array, true);
-assertEq(res instanceof Array, false);
-
-var obj = { p: 1 };
-var desc = otherGlobal.Object.getOwnPropertyDescriptor(obj, "p");
-assertEq(desc instanceof otherGlobal.Object, true);
-assertEq(desc instanceof Object, false);
-
-try
-{
-  otherGlobal.Function.prototype.call.call(null);
-  var err = "no error";
-}
-catch (e)
-{
-  err = e;
-}
-assertEq(err instanceof otherGlobal.TypeError, true,
-         "bad error: " + err);
-assertEq(err instanceof TypeError, false, "bad error: " + err);
-
-/******************************************************************************/
-
-if (typeof reportCompare === "function")
-  reportCompare(true, true);
-
-print("All tests passed!");
--- a/js/src/tests/ecma_5/extensions/jstests.list
+++ b/js/src/tests/ecma_5/extensions/jstests.list
@@ -4,17 +4,16 @@ script 15.4.4.11.js
 script Boolean-toSource.js
 script Number-toSource.js
 script Object-keys-and-object-ids.js
 script String-toSource.js
 script bug352085.js
 script bug472534.js
 script bug496985.js
 script bug566661.js
-skip-if(!xulRuntime.shell) script cross-global-call.js # needs newGlobal()
 script eval-native-callback-is-indirect.js
 script extension-methods-reject-null-undefined-this.js
 skip-if(!xulRuntime.shell) script function-definition-with.js # needs evaluate()
 script iterator-in-catch.js
 fails script nested-delete-name-in-evalcode.js # bug 604301, at a minimum
 script proxy-strict.js
 script regress-bug567606.js
 script regress-bug607284.js
--- a/js/src/xpconnect/src/xpccomponents.cpp
+++ b/js/src/xpconnect/src/xpccomponents.cpp
@@ -3625,20 +3625,21 @@ xpc_EvalInSandbox(JSContext *cx, JSObjec
         !jsPrincipals) {
         return NS_ERROR_FAILURE;
     }
 
     JSObject *callingScope;
     {
         JSAutoRequest req(cx);
 
-        callingScope = JS_GetGlobalForScopeChain(cx);
+        callingScope = JS_GetScopeChain(cx);
         if (!callingScope) {
             return NS_ERROR_FAILURE;
         }
+        callingScope = JS_GetGlobalForObject(cx, callingScope);
     }
 
     nsRefPtr<ContextHolder> sandcx = new ContextHolder(cx, sandbox);
     if(!sandcx || !sandcx->GetJSContext()) {
         JS_ReportError(cx, "Can't prepare context for evalInSandbox");
         JSPRINCIPALS_DROP(cx, jsPrincipals);
         return NS_ERROR_OUT_OF_MEMORY;
     }
--- a/js/src/xpconnect/src/xpcthrower.cpp
+++ b/js/src/xpconnect/src/xpcthrower.cpp
@@ -312,19 +312,20 @@ XPCThrower::ThrowExceptionObject(JSConte
         {
             if (!JS_WrapValue(cx, &thrown))
                 return JS_FALSE;
             JS_SetPendingException(cx, thrown);
             success = JS_TRUE;
         }
         else if((xpc = nsXPConnect::GetXPConnect()))
         {
-            JSObject* glob = JS_GetGlobalForScopeChain(cx);
+            JSObject* glob = JS_GetScopeChain(cx);
             if(!glob)
                 return JS_FALSE;
+            glob = JS_GetGlobalForObject(cx, glob);
 
             nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
             nsresult rv = xpc->WrapNative(cx, glob, e,
                                           NS_GET_IID(nsIException),
                                           getter_AddRefs(holder));
             if(NS_SUCCEEDED(rv) && holder)
             {
                 JSObject* obj;
--- a/js/src/xpconnect/wrappers/AccessCheck.cpp
+++ b/js/src/xpconnect/wrappers/AccessCheck.cpp
@@ -229,38 +229,47 @@ GetPrincipal(JSObject *obj)
 
     nsIXPConnect *xpc = nsXPConnect::GetRuntimeInstance()->GetXPConnect();
     return xpc->GetPrincipal(obj, PR_TRUE);
 }
 
 bool
 AccessCheck::documentDomainMakesSameOrigin(JSContext *cx, JSObject *obj)
 {
-    JSObject *scope;
-    if (!JS_GetGlobalForCallingScript(cx, &scope))
-        return false;
-    if (!scope) {
-        scope = JS_GetGlobalForScopeChain(cx);
-        if (!scope)
-            return false;
+    JSObject *scope = nsnull;
+    JSStackFrame *fp = nsnull;
+    JS_FrameIterator(cx, &fp);
+    if (fp) {
+        while (fp->isDummyFrame()) {
+            if (!JS_FrameIterator(cx, &fp))
+                break;
+        }
+
+        if (fp)
+            scope = &fp->scopeChain();
     }
 
+    if (!scope)
+        scope = JS_GetScopeChain(cx);
+
     nsIPrincipal *subject;
+    nsIPrincipal *object;
+
     {
         JSAutoEnterCompartment ac;
 
         if (!ac.enter(cx, scope))
             return false;
 
-        subject = GetPrincipal(scope);
+        subject = GetPrincipal(JS_GetGlobalForObject(cx, scope));
     }
+
     if (!subject)
         return false;
 
-    nsIPrincipal *object;
     {
         JSAutoEnterCompartment ac;
 
         if (!ac.enter(cx, obj))
             return false;
 
         object = GetPrincipal(JS_GetGlobalForObject(cx, obj));
     }
--- a/toolkit/components/ctypes/tests/unit/test_jsctypes.js.in
+++ b/toolkit/components/ctypes/tests/unit/test_jsctypes.js.in
@@ -33,25 +33,20 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-var ctypesGlobal = this;
 try {
   // We might be running without privileges, in which case it's up to the
   // harness to give us the 'ctypes' object.
   Components.utils.import("resource://gre/modules/ctypes.jsm");
-
-  // Hack: Determine the global object with which errors thrown by ctypes
-  //       methods will be associated for more precise testing purposes.
-  ctypesGlobal = ctypes.CType.constructor("return this")();
 } catch(e) {
 }
 
 CTYPES_TEST_LIB = ctypes.libraryName("jsctypes-test");
 CTYPES_UNICODE_LIB = ctypes.libraryName("jsctyp\u00E8s-t\u00EB\u00DFt");
 
 function getParent(obj, fun)
 {
@@ -217,37 +212,37 @@ function run_test()
   run_function_tests(library);
   run_closure_tests(library);
   run_variadic_tests(library);
   run_static_data_tests(library);
 
   // test library.close
   let test_void_t = library.declare("test_void_t_cdecl", ctypes.default_abi, ctypes.void_t);
   library.close();
-  do_check_throws(function() { test_void_t(); }, ctypesGlobal.Error);
+  do_check_throws(function() { test_void_t(); }, Error);
   do_check_throws(function() {
     library.declare("test_void_t_cdecl", ctypes.default_abi, ctypes.void_t);
-  }, ctypesGlobal.Error);
+  }, Error);
 
   // test that library functions throw when bound to other objects
   library = ctypes.open(libfile.path);
   let obj = {};
   obj.declare = library.declare;
-  do_check_throws(function () { run_void_tests(obj); }, ctypesGlobal.Error);
+  do_check_throws(function () { run_void_tests(obj); }, Error);
   obj.close = library.close;
-  do_check_throws(function () { obj.close(); }, ctypesGlobal.Error);
+  do_check_throws(function () { obj.close(); }, Error);
 
   // test that functions work as properties of other objects
   let getter = library.declare("get_int8_t_cdecl", ctypes.default_abi, ctypes.int8_t);
   do_check_eq(getter(), 109);
   obj.t = getter;
   do_check_eq(obj.t(), 109);
 
   // bug 521937
-  do_check_throws(function () { let nolib = ctypes.open("notfoundlibrary.dll"); nolib.close(); }, ctypesGlobal.Error);
+  do_check_throws(function () { let nolib = ctypes.open("notfoundlibrary.dll"); nolib.close(); }, Error);
 
   // bug 522360
   do_check_eq(run_load_system_library(), true);
 
   // Test loading a library with a unicode name (bug 589413). Note that nsIFile
   // implementations are not available in some harnesses; if not, the harness
   // should take care of the copy for us.
   let unicodefile = do_get_file(CTYPES_UNICODE_LIB, true);
@@ -259,32 +254,32 @@ function run_test()
   library.close();
   if (copy)
     unicodefile.remove(false);
 }
 
 function run_abstract_class_tests()
 {
   // Test that ctypes.CType is an abstract constructor that throws.
-  do_check_throws(function() { ctypes.CType(); }, ctypesGlobal.Error);
-  do_check_throws(function() { new ctypes.CType() }, ctypesGlobal.Error);
+  do_check_throws(function() { ctypes.CType(); }, Error);
+  do_check_throws(function() { new ctypes.CType() }, Error);
 
   // Test that classes and prototypes are set up correctly.
   do_check_class(ctypes.CType, "Function");
   do_check_class(ctypes.CType.prototype, "CType");
 
   checkParentIsCTypes(ctypes.CType);
   getParent(ctypes, function(p) {
     do_check_true(Object.getPrototypeOf(ctypes.CType) === p.Function.prototype);
     do_check_true(ctypes.CType instanceof p.Function);
   });
 
   do_check_true(ctypes.CType.hasOwnProperty("prototype"));
-  do_check_throws(function() { ctypes.CType.prototype(); }, ctypesGlobal.Error);
-  do_check_throws(function() { new ctypes.CType.prototype() }, ctypesGlobal.Error);
+  do_check_throws(function() { ctypes.CType.prototype(); }, Error);
+  do_check_throws(function() { new ctypes.CType.prototype() }, Error);
   checkParentIsCTypes(ctypes.CType.prototype);
   getParent(ctypes, function(p) {
     do_check_true(Object.getPrototypeOf(ctypes.CType.prototype) === p.Function.prototype);
     do_check_true(ctypes.CType.prototype instanceof p.Function);
   });
   do_check_true(ctypes.CType.prototype.hasOwnProperty("constructor"));
   do_check_true(ctypes.CType.prototype.constructor === ctypes.CType);
 
@@ -292,26 +287,26 @@ function run_abstract_class_tests()
   do_check_true(ctypes.CType.prototype.hasOwnProperty("name"));
   do_check_true(ctypes.CType.prototype.hasOwnProperty("size"));
   do_check_true(ctypes.CType.prototype.hasOwnProperty("ptr"));
   do_check_true(ctypes.CType.prototype.hasOwnProperty("array"));
   do_check_true(ctypes.CType.prototype.hasOwnProperty("toString"));
   do_check_true(ctypes.CType.prototype.hasOwnProperty("toSource"));
 
   // Check that the shared properties and functions on ctypes.CType.prototype throw.
-  do_check_throws(function() { ctypes.CType.prototype.name; }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.CType.prototype.size; }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.CType.prototype.ptr; }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.CType.prototype.array(); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.CType.prototype.toString(); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.CType.prototype.toSource(); }, ctypesGlobal.Error);
+  do_check_throws(function() { ctypes.CType.prototype.name; }, Error);
+  do_check_throws(function() { ctypes.CType.prototype.size; }, Error);
+  do_check_throws(function() { ctypes.CType.prototype.ptr; }, Error);
+  do_check_throws(function() { ctypes.CType.prototype.array(); }, Error);
+  do_check_throws(function() { ctypes.CType.prototype.toString(); }, Error);
+  do_check_throws(function() { ctypes.CType.prototype.toSource(); }, Error);
 
   // Test that ctypes.CData is an abstract constructor that throws.
-  do_check_throws(function() { ctypes.CData(); }, ctypesGlobal.Error);
-  do_check_throws(function() { new ctypes.CData() }, ctypesGlobal.Error);
+  do_check_throws(function() { ctypes.CData(); }, Error);
+  do_check_throws(function() { new ctypes.CData() }, Error);
 
   // Test that classes and prototypes are set up correctly.
   do_check_class(ctypes.CData, "Function");
   do_check_class(ctypes.CData.prototype, "CData");
 
   checkParentIsCTypes(ctypes.CData);
   do_check_true(ctypes.CData.__proto__ === ctypes.CType.prototype);
   do_check_true(ctypes.CData instanceof ctypes.CType);
@@ -327,26 +322,26 @@ function run_abstract_class_tests()
   // Check that ctypes.CData.prototype has the correct properties and functions.
   do_check_true(ctypes.CData.prototype.hasOwnProperty("value"));
   do_check_true(ctypes.CData.prototype.hasOwnProperty("address"));
   do_check_true(ctypes.CData.prototype.hasOwnProperty("readString"));
   do_check_true(ctypes.CData.prototype.hasOwnProperty("toString"));
   do_check_true(ctypes.CData.prototype.hasOwnProperty("toSource"));
 
   // Check that the shared properties and functions on ctypes.CData.prototype throw.
-  do_check_throws(function() { ctypes.CData.prototype.value; }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.CData.prototype.value = null; }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.CData.prototype.address(); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.CData.prototype.readString(); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.CData.prototype.toString(); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.CData.prototype.toSource(); }, ctypesGlobal.Error);
+  do_check_throws(function() { ctypes.CData.prototype.value; }, Error);
+  do_check_throws(function() { ctypes.CData.prototype.value = null; }, Error);
+  do_check_throws(function() { ctypes.CData.prototype.address(); }, Error);
+  do_check_throws(function() { ctypes.CData.prototype.readString(); }, Error);
+  do_check_throws(function() { ctypes.CData.prototype.toString(); }, Error);
+  do_check_throws(function() { ctypes.CData.prototype.toSource(); }, Error);
 }
 
 function run_Int64_tests() {
-  do_check_throws(function() { ctypes.Int64(); }, ctypesGlobal.Error);
+  do_check_throws(function() { ctypes.Int64(); }, Error);
 
   // Test that classes and prototypes are set up correctly.
   do_check_class(ctypes.Int64, "Function");
   do_check_class(ctypes.Int64.prototype, "Int64");
 
   checkParentIsCTypes(ctypes.Int64);
   getParent(ctypes, function(p) {
     do_check_true(Object.getPrototypeOf(ctypes.Int64) === p.Function.prototype);
@@ -363,36 +358,36 @@ function run_Int64_tests() {
   do_check_true(ctypes.Int64.hasOwnProperty("compare"));
   do_check_true(ctypes.Int64.hasOwnProperty("lo"));
   do_check_true(ctypes.Int64.hasOwnProperty("hi"));
   do_check_true(ctypes.Int64.hasOwnProperty("join"));
   do_check_true(ctypes.Int64.prototype.hasOwnProperty("toString"));
   do_check_true(ctypes.Int64.prototype.hasOwnProperty("toSource"));
 
   // Check that the shared functions on ctypes.Int64.prototype throw.
-  do_check_throws(function() { ctypes.Int64.prototype.toString(); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.Int64.prototype.toSource(); }, ctypesGlobal.Error);
+  do_check_throws(function() { ctypes.Int64.prototype.toString(); }, Error);
+  do_check_throws(function() { ctypes.Int64.prototype.toSource(); }, Error);
 
   let i = ctypes.Int64(0);
   checkParentIsCTypes(i);
   do_check_true(i.__proto__ === ctypes.Int64.prototype);
   do_check_true(i instanceof ctypes.Int64);
 
   // Test Int64.toString([radix]).
   do_check_eq(i.toString(), "0");
   for (let radix = 2; radix <= 36; ++radix)
     do_check_eq(i.toString(radix), "0");
-  do_check_throws(function() { i.toString(0); }, ctypesGlobal.Error);
-  do_check_throws(function() { i.toString(1); }, ctypesGlobal.Error);
-  do_check_throws(function() { i.toString(37); }, ctypesGlobal.Error);
-  do_check_throws(function() { i.toString(10, 2); }, ctypesGlobal.Error);
+  do_check_throws(function() { i.toString(0); }, Error);
+  do_check_throws(function() { i.toString(1); }, Error);
+  do_check_throws(function() { i.toString(37); }, Error);
+  do_check_throws(function() { i.toString(10, 2); }, Error);
 
   // Test Int64.toSource().
   do_check_eq(i.toSource(), "ctypes.Int64(\"0\")");
-  do_check_throws(function() { i.toSource(10); }, ctypesGlobal.Error);
+  do_check_throws(function() { i.toSource(10); }, Error);
 
   i = ctypes.Int64("0x28590a1c921def71");
   do_check_eq(i.toString(), i.toString(10));
   do_check_eq(i.toString(10), "2907366152271163249");
   do_check_eq(i.toString(16), "28590a1c921def71");
   do_check_eq(i.toString(2), "10100001011001000010100001110010010010000111011110111101110001");
   do_check_eq(i.toSource(), "ctypes.Int64(\"" + i.toString(10) + "\")");
 
@@ -480,52 +475,52 @@ function run_Int64_tests() {
   let vals = [-0x8000000000001000, 0x8000000000000000,
               "-0x8000000000000001", "0x8000000000000000",
               ctypes.UInt64("0x8000000000000000"),
               Infinity, -Infinity, NaN, 0.1,
               5.68e21, null, undefined, "", {}, [], new Number(16),
               {toString: function () { return 7; }},
               {valueOf: function () { return 7; }}];
   for (let i = 0; i < vals.length; i++)
-    do_check_throws(function () { ctypes.Int64(vals[i]); }, ctypesGlobal.TypeError);
+    do_check_throws(function () { ctypes.Int64(vals[i]); }, TypeError);
 
   // Test ctypes.Int64.compare.
   do_check_eq(ctypes.Int64.compare(ctypes.Int64(5), ctypes.Int64(5)), 0);
   do_check_eq(ctypes.Int64.compare(ctypes.Int64(5), ctypes.Int64(4)), 1);
   do_check_eq(ctypes.Int64.compare(ctypes.Int64(4), ctypes.Int64(5)), -1);
   do_check_eq(ctypes.Int64.compare(ctypes.Int64(-5), ctypes.Int64(-5)), 0);
   do_check_eq(ctypes.Int64.compare(ctypes.Int64(-5), ctypes.Int64(-4)), -1);
   do_check_eq(ctypes.Int64.compare(ctypes.Int64(-4), ctypes.Int64(-5)), 1);
-  do_check_throws(function() { ctypes.Int64.compare(ctypes.Int64(4), ctypes.UInt64(4)); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.Int64.compare(4, 5); }, ctypesGlobal.Error);
+  do_check_throws(function() { ctypes.Int64.compare(ctypes.Int64(4), ctypes.UInt64(4)); }, Error);
+  do_check_throws(function() { ctypes.Int64.compare(4, 5); }, Error);
 
   // Test ctypes.Int64.{lo,hi}.
   do_check_eq(ctypes.Int64.lo(ctypes.Int64(0x28590a1c921de000)), 0x921de000);
   do_check_eq(ctypes.Int64.hi(ctypes.Int64(0x28590a1c921de000)), 0x28590a1c);
   do_check_eq(ctypes.Int64.lo(ctypes.Int64(-0x28590a1c921de000)), 0x6de22000);
   do_check_eq(ctypes.Int64.hi(ctypes.Int64(-0x28590a1c921de000)), -0x28590a1d);
-  do_check_throws(function() { ctypes.Int64.lo(ctypes.UInt64(0)); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.Int64.hi(ctypes.UInt64(0)); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.Int64.lo(0); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.Int64.hi(0); }, ctypesGlobal.Error);
+  do_check_throws(function() { ctypes.Int64.lo(ctypes.UInt64(0)); }, Error);
+  do_check_throws(function() { ctypes.Int64.hi(ctypes.UInt64(0)); }, Error);
+  do_check_throws(function() { ctypes.Int64.lo(0); }, Error);
+  do_check_throws(function() { ctypes.Int64.hi(0); }, Error);
 
   // Test ctypes.Int64.join.
   do_check_eq(ctypes.Int64.join(0, 0).toString(), "0");
   do_check_eq(ctypes.Int64.join(0x28590a1c, 0x921de000).toString(16), "28590a1c921de000");
   do_check_eq(ctypes.Int64.join(-0x28590a1d, 0x6de22000).toString(16), "-28590a1c921de000");
   do_check_eq(ctypes.Int64.join(0x7fffffff, 0xffffffff).toString(16), "7fffffffffffffff");
   do_check_eq(ctypes.Int64.join(-0x80000000, 0x00000000).toString(16), "-8000000000000000");
-  do_check_throws(function() { ctypes.Int64.join(-0x80000001, 0); }, ctypesGlobal.TypeError);
-  do_check_throws(function() { ctypes.Int64.join(0x80000000, 0); }, ctypesGlobal.TypeError);
-  do_check_throws(function() { ctypes.Int64.join(0, -0x1); }, ctypesGlobal.TypeError);
-  do_check_throws(function() { ctypes.Int64.join(0, 0x800000000); }, ctypesGlobal.TypeError);
+  do_check_throws(function() { ctypes.Int64.join(-0x80000001, 0); }, TypeError);
+  do_check_throws(function() { ctypes.Int64.join(0x80000000, 0); }, TypeError);
+  do_check_throws(function() { ctypes.Int64.join(0, -0x1); }, TypeError);
+  do_check_throws(function() { ctypes.Int64.join(0, 0x800000000); }, TypeError);
 }
 
 function run_UInt64_tests() {
-  do_check_throws(function() { ctypes.UInt64(); }, ctypesGlobal.Error);
+  do_check_throws(function() { ctypes.UInt64(); }, Error);
 
   // Test that classes and prototypes are set up correctly.
   do_check_class(ctypes.UInt64, "Function");
   do_check_class(ctypes.UInt64.prototype, "UInt64");
 
   checkParentIsCTypes(ctypes.UInt64);
   getParent(ctypes, function(p) {
     do_check_true(Object.getPrototypeOf(ctypes.UInt64) === p.Function.prototype);
@@ -544,36 +539,36 @@ function run_UInt64_tests() {
   do_check_true(ctypes.UInt64.hasOwnProperty("compare"));
   do_check_true(ctypes.UInt64.hasOwnProperty("lo"));
   do_check_true(ctypes.UInt64.hasOwnProperty("hi"));
   do_check_true(ctypes.UInt64.hasOwnProperty("join"));
   do_check_true(ctypes.UInt64.prototype.hasOwnProperty("toString"));
   do_check_true(ctypes.UInt64.prototype.hasOwnProperty("toSource"));
 
   // Check that the shared functions on ctypes.UInt64.prototype throw.
-  do_check_throws(function() { ctypes.UInt64.prototype.toString(); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.UInt64.prototype.toSource(); }, ctypesGlobal.Error);
+  do_check_throws(function() { ctypes.UInt64.prototype.toString(); }, Error);
+  do_check_throws(function() { ctypes.UInt64.prototype.toSource(); }, Error);
 
   let i = ctypes.UInt64(0);
   checkParentIsCTypes(i);
   do_check_true(i.__proto__ === ctypes.UInt64.prototype);
   do_check_true(i instanceof ctypes.UInt64);
 
   // Test UInt64.toString([radix]).
   do_check_eq(i.toString(), "0");
   for (let radix = 2; radix <= 36; ++radix)
     do_check_eq(i.toString(radix), "0");
-  do_check_throws(function() { i.toString(0); }, ctypesGlobal.Error);
-  do_check_throws(function() { i.toString(1); }, ctypesGlobal.Error);
-  do_check_throws(function() { i.toString(37); }, ctypesGlobal.Error);
-  do_check_throws(function() { i.toString(10, 2); }, ctypesGlobal.Error);
+  do_check_throws(function() { i.toString(0); }, Error);
+  do_check_throws(function() { i.toString(1); }, Error);
+  do_check_throws(function() { i.toString(37); }, Error);
+  do_check_throws(function() { i.toString(10, 2); }, Error);
 
   // Test UInt64.toSource().
   do_check_eq(i.toSource(), "ctypes.UInt64(\"0\")");
-  do_check_throws(function() { i.toSource(10); }, ctypesGlobal.Error);
+  do_check_throws(function() { i.toSource(10); }, Error);
 
   i = ctypes.UInt64("0x28590a1c921def71");
   do_check_eq(i.toString(), i.toString(10));
   do_check_eq(i.toString(10), "2907366152271163249");
   do_check_eq(i.toString(16), "28590a1c921def71");
   do_check_eq(i.toString(2), "10100001011001000010100001110010010010000111011110111101110001");
   do_check_eq(i.toSource(), "ctypes.UInt64(\"" + i.toString(10) + "\")");
 
@@ -640,45 +635,45 @@ function run_UInt64_tests() {
   do_check_eq(i.toString(2), "111111111111111111111111111111111111111111111111111111111111111");
 
   let vals = [-1, 0x10000000000000000, "-1", "-0x1", "0x10000000000000000",
               ctypes.Int64("-1"), Infinity, -Infinity, NaN, 0.1,
               5.68e21, null, undefined, "", {}, [], new Number(16),
               {toString: function () { return 7; }},
               {valueOf: function () { return 7; }}];
   for (let i = 0; i < vals.length; i++)
-    do_check_throws(function () { ctypes.UInt64(vals[i]); }, ctypesGlobal.TypeError);
+    do_check_throws(function () { ctypes.UInt64(vals[i]); }, TypeError);
 
   // Test ctypes.UInt64.compare.
   do_check_eq(ctypes.UInt64.compare(ctypes.UInt64(5), ctypes.UInt64(5)), 0);
   do_check_eq(ctypes.UInt64.compare(ctypes.UInt64(5), ctypes.UInt64(4)), 1);
   do_check_eq(ctypes.UInt64.compare(ctypes.UInt64(4), ctypes.UInt64(5)), -1);
-  do_check_throws(function() { ctypes.UInt64.compare(ctypes.UInt64(4), ctypes.Int64(4)); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.UInt64.compare(4, 5); }, ctypesGlobal.Error);
+  do_check_throws(function() { ctypes.UInt64.compare(ctypes.UInt64(4), ctypes.Int64(4)); }, Error);
+  do_check_throws(function() { ctypes.UInt64.compare(4, 5); }, Error);
 
   // Test ctypes.UInt64.{lo,hi}.
   do_check_eq(ctypes.UInt64.lo(ctypes.UInt64(0x28590a1c921de000)), 0x921de000);
   do_check_eq(ctypes.UInt64.hi(ctypes.UInt64(0x28590a1c921de000)), 0x28590a1c);
   do_check_eq(ctypes.UInt64.lo(ctypes.UInt64(0xa8590a1c921de000)), 0x921de000);
   do_check_eq(ctypes.UInt64.hi(ctypes.UInt64(0xa8590a1c921de000)), 0xa8590a1c);
-  do_check_throws(function() { ctypes.UInt64.lo(ctypes.Int64(0)); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.UInt64.hi(ctypes.Int64(0)); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.UInt64.lo(0); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.UInt64.hi(0); }, ctypesGlobal.Error);
+  do_check_throws(function() { ctypes.UInt64.lo(ctypes.Int64(0)); }, Error);
+  do_check_throws(function() { ctypes.UInt64.hi(ctypes.Int64(0)); }, Error);
+  do_check_throws(function() { ctypes.UInt64.lo(0); }, Error);
+  do_check_throws(function() { ctypes.UInt64.hi(0); }, Error);
 
   // Test ctypes.UInt64.join.
   do_check_eq(ctypes.UInt64.join(0, 0).toString(), "0");
   do_check_eq(ctypes.UInt64.join(0x28590a1c, 0x921de000).toString(16), "28590a1c921de000");
   do_check_eq(ctypes.UInt64.join(0xa8590a1c, 0x921de000).toString(16), "a8590a1c921de000");
   do_check_eq(ctypes.UInt64.join(0xffffffff, 0xffffffff).toString(16), "ffffffffffffffff");
   do_check_eq(ctypes.UInt64.join(0, 0).toString(16), "0");
-  do_check_throws(function() { ctypes.UInt64.join(-0x1, 0); }, ctypesGlobal.TypeError);
-  do_check_throws(function() { ctypes.UInt64.join(0x100000000, 0); }, ctypesGlobal.TypeError);
-  do_check_throws(function() { ctypes.UInt64.join(0, -0x1); }, ctypesGlobal.TypeError);
-  do_check_throws(function() { ctypes.UInt64.join(0, 0x1000000000); }, ctypesGlobal.TypeError);
+  do_check_throws(function() { ctypes.UInt64.join(-0x1, 0); }, TypeError);
+  do_check_throws(function() { ctypes.UInt64.join(0x100000000, 0); }, TypeError);
+  do_check_throws(function() { ctypes.UInt64.join(0, -0x1); }, TypeError);
+  do_check_throws(function() { ctypes.UInt64.join(0, 0x1000000000); }, TypeError);
 }
 
 function run_basic_abi_tests(library, t, name, toprimitive,
                              get_test, set_tests, sum_tests, sum_many_tests) {
   // Test the function call ABI for calls involving the type.
   function declare_fn_cdecl(fn_t, prefix) {
     return library.declare(prefix + name + "_cdecl", fn_t);
   }
@@ -797,22 +792,22 @@ function run_basic_class_tests(t)
   do_check_true(t instanceof ctypes.CType);
 
   checkParentIsCTypes(t.prototype);
   do_check_true(t.prototype.__proto__ === ctypes.CData.prototype);
   do_check_true(t.prototype instanceof ctypes.CData);
   do_check_true(t.prototype.constructor === t);
 
   // Check that the shared properties and functions on 't.prototype' throw.
-  do_check_throws(function() { t.prototype.value; }, ctypesGlobal.Error);
-  do_check_throws(function() { t.prototype.value = null; }, ctypesGlobal.Error);
-  do_check_throws(function() { t.prototype.address(); }, ctypesGlobal.Error);
-  do_check_throws(function() { t.prototype.readString(); }, ctypesGlobal.Error);
-  do_check_throws(function() { t.prototype.toString(); }, ctypesGlobal.Error);
-  do_check_throws(function() { t.prototype.toSource(); }, ctypesGlobal.Error);
+  do_check_throws(function() { t.prototype.value; }, Error);
+  do_check_throws(function() { t.prototype.value = null; }, Error);
+  do_check_throws(function() { t.prototype.address(); }, Error);
+  do_check_throws(function() { t.prototype.readString(); }, Error);
+  do_check_throws(function() { t.prototype.toString(); }, Error);
+  do_check_throws(function() { t.prototype.toSource(); }, Error);
 
   // Test that an instance 'd' of 't' is a CData.
   let d = t();
   do_check_class(d, "CData");
   checkParentIsCTypes(d);
   do_check_true(d.__proto__ === t.prototype);
   do_check_true(d instanceof t);
   do_check_true(d.constructor === t);
@@ -847,17 +842,17 @@ function run_bool_tests(library) {
 
   // don't convert anything else
   let vals = [-1, 2, Infinity, -Infinity, NaN, 0.1,
               ctypes.Int64(0), ctypes.UInt64(0),
               null, undefined, "", "0", {}, [], new Number(16),
               {toString: function () { return 7; }},
               {valueOf: function () { return 7; }}];
   for (let i = 0; i < vals.length; i++)
-    do_check_throws(function () { d.value = vals[i]; }, ctypesGlobal.TypeError);
+    do_check_throws(function () { d.value = vals[i]; }, TypeError);
 
   do_check_true(d.address().constructor === t.ptr);
   do_check_eq(d.address().contents, d.value);
   do_check_eq(d.toSource(), "ctypes." + name + "(" + d.value + ")");
   do_check_eq(d.toSource(), d.toString());
 
   // Test the function call ABI for calls involving the type,
   // and check the alignment of the type against what C says.
@@ -927,17 +922,17 @@ function run_integer_tests(library, t, n
   do_check_eq(d.value, 1);
 
   // don't convert anything else
   let vals = [limits[0] - 1, limits[1] + 1, Infinity, -Infinity, NaN, 0.1,
               null, undefined, "", "0", {}, [], new Number(16),
               {toString: function () { return 7; }},
               {valueOf: function () { return 7; }}];
   for (let i = 0; i < vals.length; i++)
-    do_check_throws(function () { d.value = vals[i]; }, ctypesGlobal.TypeError);
+    do_check_throws(function () { d.value = vals[i]; }, TypeError);
 
   do_check_true(d.address().constructor === t.ptr);
   do_check_eq(d.address().contents, d.value);
   do_check_eq(d.toSource(), "ctypes." + name + "(" + d.value + ")");
   do_check_eq(d.toSource(), d.toString());
 
   // Test the function call ABI for calls involving the type,
   // and check the alignment of the type against what C says.
@@ -976,36 +971,36 @@ function run_float_tests(library, t, nam
   do_check_eq(d.value, 5.25);
   d = t(10);
   do_check_eq(d.value, 10);
   d.value = -10;
   do_check_eq(d.value, -10);
   d = new t(20);
   do_check_eq(d.value, 20);
 
-  do_check_throws(function() { d.value = ctypes.Int64(5); }, ctypesGlobal.TypeError);
-  do_check_throws(function() { d.value = ctypes.Int64(-5); }, ctypesGlobal.TypeError);
-  do_check_throws(function() { d.value = ctypes.UInt64(5); }, ctypesGlobal.TypeError);
+  do_check_throws(function() { d.value = ctypes.Int64(5); }, TypeError);
+  do_check_throws(function() { d.value = ctypes.Int64(-5); }, TypeError);
+  do_check_throws(function() { d.value = ctypes.UInt64(5); }, TypeError);
 
   if (size == 4) {
     d.value = 0x7fffff;
     do_check_eq(d.value, 0x7fffff);
 
     // allow values that can't be represented precisely as a float
     d.value = 0xffffffff;
     let delta = 1 - d.value/0xffffffff;
     do_check_true(delta != 0);
     do_check_true(delta > -0.01 && delta < 0.01);
     d.value = 1 + 1/0x80000000;
     do_check_eq(d.value, 1);
   } else {
     d.value = 0xfffffffffffff000;
     do_check_eq(d.value, 0xfffffffffffff000);
 
-    do_check_throws(function() { d.value = ctypes.Int64("0x7fffffffffffffff"); }, ctypesGlobal.TypeError);
+    do_check_throws(function() { d.value = ctypes.Int64("0x7fffffffffffffff"); }, TypeError);
   }
 
   d.value = Infinity;
   do_check_eq(d.value, Infinity);
   d.value = -Infinity;
   do_check_eq(d.value, -Infinity);
   d.value = NaN;
   do_check_true(isNaN(d.value));
@@ -1014,17 +1009,17 @@ function run_float_tests(library, t, nam
   d.value = -0;
   do_check_eq(1/d.value, 1/-0);
 
   // don't convert anything else
   let vals = [true, false, null, undefined, "", "0", {}, [], new Number(16),
               {toString: function () { return 7; }},
               {valueOf: function () { return 7; }}];
   for (let i = 0; i < vals.length; i++)
-    do_check_throws(function () { d.value = vals[i]; }, ctypesGlobal.TypeError);
+    do_check_throws(function () { d.value = vals[i]; }, TypeError);
 
   // Check that values roundtrip through toSource() correctly.
   function test_roundtrip(t, val)
   {
     let f1 = t(val);
     eval("let f2 = " + f1.toSource());
     do_check_eq(f1.value, f2.value);
   }
@@ -1114,17 +1109,17 @@ function run_wrapped_integer_tests(libra
   do_check_eq(d.value, 1);
 
   // don't convert anything else
   let vals = [limits[2], limits[3], Infinity, -Infinity, NaN, 0.1,
               null, undefined, "", "0", {}, [], new Number(16),
               {toString: function () { return 7; }},
               {valueOf: function () { return 7; }}];
   for (let i = 0; i < vals.length; i++)
-    do_check_throws(function () { d.value = vals[i]; }, ctypesGlobal.TypeError);
+    do_check_throws(function () { d.value = vals[i]; }, TypeError);
 
   do_check_true(d.address().constructor === t.ptr);
   do_check_eq(d.address().contents.toString(), d.value.toString());
   do_check_eq(d.toSource(), "ctypes." + name + "(" + wname + "(\"" + d.value + "\"))");
   do_check_eq(d.toSource(), d.toString());
 
   // Test the function call ABI for calls involving the type,
   // and check the alignment of the type against what C says.
@@ -1160,17 +1155,17 @@ function run_char_tests(library, t, name
   d.value = 5;
   do_check_eq(d.value, 5);
   d = t(10);
   do_check_eq(d.value, 10);
   if (signed) {
     d.value = -10;
     do_check_eq(d.value, -10);
   } else {
-    do_check_throws(function() { d.value = -10; }, ctypesGlobal.TypeError);
+    do_check_throws(function() { d.value = -10; }, TypeError);
   }
   d = new t(20);
   do_check_eq(d.value, 20);
 
   function toprimitive(a) { return a; }
 
   d.value = ctypes.Int64(5);
   do_check_eq(d.value, 5);
@@ -1189,41 +1184,41 @@ function run_char_tests(library, t, name
   do_check_eq(d.value, 0);
   d.value = -0;
   do_check_eq(1/d.value, 1/0);
   d.value = false;
   do_check_eq(d.value, 0);
   d.value = true;
   do_check_eq(d.value, 1);
 
-  do_check_throws(function() { d.value = "5"; }, ctypesGlobal.TypeError);
+  do_check_throws(function() { d.value = "5"; }, TypeError);
 
   // don't convert anything else
   let vals = [limits[0] - 1, limits[1] + 1, Infinity, -Infinity, NaN, 0.1,
               null, undefined, "", "aa", {}, [], new Number(16),
               {toString: function () { return 7; }},
               {valueOf: function () { return 7; }}];
   for (let i = 0; i < vals.length; i++)
-    do_check_throws(function () { d.value = vals[i]; }, ctypesGlobal.TypeError);
+    do_check_throws(function () { d.value = vals[i]; }, TypeError);
 
   do_check_true(d.address().constructor === t.ptr);
   do_check_eq(d.address().contents, 1);
   do_check_eq(d.toSource(), "ctypes." + name + "(" + d.value + ")");
   do_check_eq(d.toSource(), d.toString());
 
   // Test string autoconversion (and lack thereof).
   let literal = "autoconverted";
   let s = t.array()(literal);
   do_check_eq(s.readString(), literal);
   do_check_eq(s.constructor.length, literal.length + 1);
   s = t.array(50)(literal);
   do_check_eq(s.readString(), literal);
-  do_check_throws(function() { t.array(3)(literal); }, ctypesGlobal.Error);
+  do_check_throws(function() { t.array(3)(literal); }, Error);
 
-  do_check_throws(function() { t.ptr(literal); }, ctypesGlobal.TypeError);
+  do_check_throws(function() { t.ptr(literal); }, TypeError);
   let p = t.ptr(s);
   do_check_eq(p.readString(), literal);
 
   // Test the function call ABI for calls involving the type,
   // and check the alignment of the type against what C says.
   run_basic_abi_tests(library, t, name, toprimitive,
     109,
     [ 0, limits[0], limits[1] ],
@@ -1255,23 +1250,23 @@ function run_jschar_tests(library, t, na
   let d = t();
   do_check_eq(d.value.length, 1);
   do_check_eq(toprimitive(d.value), 0);
   d.value = 5;
   do_check_eq(d.value.length, 1);
   do_check_eq(toprimitive(d.value), 5);
   d = t(10);
   do_check_eq(toprimitive(d.value), 10);
-  do_check_throws(function() { d.value = -10; }, ctypesGlobal.TypeError);
+  do_check_throws(function() { d.value = -10; }, TypeError);
   d = new t(20);
   do_check_eq(toprimitive(d.value), 20);
 
   d.value = ctypes.Int64(5);
   do_check_eq(d.value.charCodeAt(0), 5);
-  do_check_throws(function() { d.value = ctypes.Int64(-10); }, ctypesGlobal.TypeError);
+  do_check_throws(function() { d.value = ctypes.Int64(-10); }, TypeError);
   d.value = ctypes.UInt64(5);
   do_check_eq(d.value.charCodeAt(0), 5);
 
   d.value = limits[0];
   do_check_eq(toprimitive(d.value), limits[0]);
   d.value = limits[1];
   do_check_eq(toprimitive(d.value), limits[1]);
   d.value = 0;
@@ -1289,33 +1284,33 @@ function run_jschar_tests(library, t, na
   do_check_eq(d.value, "a");
 
   // don't convert anything else
   let vals = [limits[0] - 1, limits[1] + 1, Infinity, -Infinity, NaN, 0.1,
               null, undefined, "", "aa", {}, [], new Number(16),
               {toString: function () { return 7; }},
               {valueOf: function () { return 7; }}];
   for (let i = 0; i < vals.length; i++)
-    do_check_throws(function () { d.value = vals[i]; }, ctypesGlobal.TypeError);
+    do_check_throws(function () { d.value = vals[i]; }, TypeError);
 
   do_check_true(d.address().constructor === t.ptr);
   do_check_eq(d.address().contents, "a");
   do_check_eq(d.toSource(), "ctypes." + name + "(\"" + d.value + "\")");
   do_check_eq(d.toSource(), d.toString());
 
   // Test string autoconversion (and lack thereof).
   let literal = "autoconverted";
   let s = t.array()(literal);
   do_check_eq(s.readString(), literal);
   do_check_eq(s.constructor.length, literal.length + 1);
   s = t.array(50)(literal);
   do_check_eq(s.readString(), literal);
-  do_check_throws(function() { t.array(3)(literal); }, ctypesGlobal.Error);
+  do_check_throws(function() { t.array(3)(literal); }, Error);
 
-  do_check_throws(function() { t.ptr(literal); }, ctypesGlobal.TypeError);
+  do_check_throws(function() { t.ptr(literal); }, TypeError);
   let p = t.ptr(s);
   do_check_eq(p.readString(), literal);
 
   // Test the function call ABI for calls involving the type,
   // and check the alignment of the type against what C says.
   run_basic_abi_tests(library, t, name, toprimitive,
     109,
     [ 0, limits[0], limits[1] ],
@@ -1351,19 +1346,19 @@ function run_type_ctor_class_tests(c, t,
   // Check that 'c.prototype' has the correct properties and functions.
   for each (let p in props)
     do_check_true(c.prototype.hasOwnProperty(p));
   for each (let f in fns)
     do_check_true(c.prototype.hasOwnProperty(f));
 
   // Check that the shared properties and functions on 'c.prototype' throw.
   for each (let p in props)
-    do_check_throws(function() { c.prototype[p]; }, ctypesGlobal.Error);
+    do_check_throws(function() { c.prototype[p]; }, Error);
   for each (let f in fns)
-    do_check_throws(function() { c.prototype[f](); }, ctypesGlobal.Error);
+    do_check_throws(function() { c.prototype[f](); }, Error);
 
   // Test that classes and prototypes are set up correctly on a constructed
   // type 't'.
   do_check_class(t, "CType");
   do_check_class(t.prototype, "CData");
 
   checkParentIsCTypes(t);
   do_check_true(t.__proto__ === c.prototype);
@@ -1386,31 +1381,31 @@ function run_type_ctor_class_tests(c, t,
   for each (let p in instanceProps)
     do_check_true(t.prototype.__proto__.hasOwnProperty(p));
   for each (let f in instanceFns)
     do_check_true(t.prototype.__proto__.hasOwnProperty(f));
 
   // Check that the shared properties and functions on 't.prototype.__proto__'
   // (and thus also 't.prototype') throw.
   for each (let p in instanceProps) {
-    do_check_throws(function() { t.prototype.__proto__[p]; }, ctypesGlobal.Error);
-    do_check_throws(function() { t.prototype[p]; }, ctypesGlobal.Error);
+    do_check_throws(function() { t.prototype.__proto__[p]; }, Error);
+    do_check_throws(function() { t.prototype[p]; }, Error);
   }
   for each (let f in instanceFns) {
-    do_check_throws(function() { t.prototype.__proto__[f]() }, ctypesGlobal.Error);
-    do_check_throws(function() { t.prototype[f]() }, ctypesGlobal.Error);
+    do_check_throws(function() { t.prototype.__proto__[f]() }, Error);
+    do_check_throws(function() { t.prototype[f]() }, Error);
   }
 
   // Check that 't.prototype' has the correct special properties.
   for each (let p in specialProps)
     do_check_true(t.prototype.hasOwnProperty(p));
 
   // Check that the shared special properties on 't.prototype' throw.
   for each (let p in specialProps)
-    do_check_throws(function() { t.prototype[p]; }, ctypesGlobal.Error);
+    do_check_throws(function() { t.prototype[p]; }, Error);
 
   // Test that an instance 'd' of 't' is a CData.
   if (t.__proto__ != ctypes.FunctionType.prototype) {
     let d = t();
     do_check_class(d, "CData");
     checkParentIsCTypes(d);
     do_check_true(d.__proto__ === t.prototype);
     do_check_true(d instanceof t);
@@ -1419,96 +1414,96 @@ function run_type_ctor_class_tests(c, t,
 }
 
 function run_StructType_tests() {
   run_type_ctor_class_tests(ctypes.StructType,
     ctypes.StructType("s", [{"a": ctypes.int32_t}, {"b": ctypes.int64_t}]),
     ctypes.StructType("t", [{"c": ctypes.int32_t}, {"d": ctypes.int64_t}]),
     [ "fields" ], [ "define" ], [], [ "addressOfField" ], [ "a", "b" ]);
 
-  do_check_throws(function() { ctypes.StructType(); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.StructType("a", [], 5); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.StructType(null, []); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.StructType("a", null); }, ctypesGlobal.Error);
+  do_check_throws(function() { ctypes.StructType(); }, Error);
+  do_check_throws(function() { ctypes.StructType("a", [], 5); }, Error);
+  do_check_throws(function() { ctypes.StructType(null, []); }, Error);
+  do_check_throws(function() { ctypes.StructType("a", null); }, Error);
 
   // Check that malformed descriptors are an error.
   do_check_throws(function() {
     ctypes.StructType("a", [{"x":ctypes.int32_t}, {"x":ctypes.int8_t}]);
-  }, ctypesGlobal.Error);
+  }, Error);
   do_check_throws(function() {
     ctypes.StructType("a", [5]);
-  }, ctypesGlobal.Error);
+  }, Error);
   do_check_throws(function() {
     ctypes.StructType("a", [{}]);
-  }, ctypesGlobal.Error);
+  }, Error);
   do_check_throws(function() {
     ctypes.StructType("a", [{5:ctypes.int32_t}]);
-  }, ctypesGlobal.Error);
+  }, Error);
   do_check_throws(function() {
     ctypes.StructType("a", [{"5":ctypes.int32_t}]);
-  }, ctypesGlobal.Error);
+  }, Error);
   do_check_throws(function() {
     ctypes.StructType("a", [{"x":5}]);
-  }, ctypesGlobal.Error);
+  }, Error);
   do_check_throws(function() {
     ctypes.StructType("a", [{"x":ctypes.int32_t()}]);
-  }, ctypesGlobal.Error);
+  }, Error);
 
   // Check that opaque structs work.
   let opaque_t = ctypes.StructType("a");
   do_check_eq(opaque_t.name, "a");
   do_check_eq(opaque_t.toString(), "type a");
   do_check_eq(opaque_t.toSource(), 'ctypes.StructType("a")');
   do_check_true(opaque_t.prototype === undefined);
   do_check_true(opaque_t.fields === undefined);
   do_check_true(opaque_t.size === undefined);
-  do_check_throws(function() { opaque_t(); }, ctypesGlobal.Error);
+  do_check_throws(function() { opaque_t(); }, Error);
   let opaqueptr_t = opaque_t.ptr;
   do_check_true(opaqueptr_t.targetType === opaque_t);
   do_check_eq(opaqueptr_t.name, "a*");
   do_check_eq(opaqueptr_t.toString(), "type a*");
   do_check_eq(opaqueptr_t.toSource(), 'ctypes.StructType("a").ptr');
 
   // Check that type checking works with opaque structs.
   let opaqueptr = opaqueptr_t();
   opaqueptr.value = opaqueptr_t(1);
   do_check_eq(ptrValue(opaqueptr), 1);
   do_check_throws(function() {
     opaqueptr.value = ctypes.StructType("a").ptr();
-  }, ctypesGlobal.TypeError);
+  }, TypeError);
 
   // Check that 'define' works.
-  do_check_throws(function() { opaque_t.define(); }, ctypesGlobal.Error);
-  do_check_throws(function() { opaque_t.define([], 0); }, ctypesGlobal.Error);
-  do_check_throws(function() { opaque_t.define([{}]); }, ctypesGlobal.Error);
-  do_check_throws(function() { opaque_t.define([{ a: 0 }]); }, ctypesGlobal.Error);
+  do_check_throws(function() { opaque_t.define(); }, Error);
+  do_check_throws(function() { opaque_t.define([], 0); }, Error);
+  do_check_throws(function() { opaque_t.define([{}]); }, Error);
+  do_check_throws(function() { opaque_t.define([{ a: 0 }]); }, Error);
   do_check_throws(function() {
     opaque_t.define([{ a: ctypes.int32_t, b: ctypes.int64_t }]);
-  }, ctypesGlobal.Error);
+  }, Error);
   do_check_throws(function() {
     opaque_t.define([{ a: ctypes.int32_t }, { b: 0 }]);
-  }, ctypesGlobal.Error);
+  }, Error);
   do_check_false(opaque_t.hasOwnProperty("prototype"));
 
   // Check that circular references work with opaque structs...
   // but not crazy ones.
-  do_check_throws(function() { opaque_t.define([{ b: opaque_t }]); }, ctypesGlobal.Error);
+  do_check_throws(function() { opaque_t.define([{ b: opaque_t }]); }, Error);
   let circular_t = ctypes.StructType("circular", [{ a: opaqueptr_t }]);
   opaque_t.define([{ b: circular_t }]);
   let opaque = opaque_t();
   let circular = circular_t(opaque.address());
   opaque.b = circular;
   do_check_eq(circular.a.toSource(), opaque.address().toSource());
   do_check_eq(opaque.b.toSource(), circular.toSource());
 
   // Check that attempting to redefine a struct fails and if attempted, the
   // original definition is preserved.
   do_check_throws(function() {
     opaque_t.define([{ c: ctypes.int32_t.array(8) }]);
-  }, ctypesGlobal.Error);
+  }, Error);
   do_check_eq(opaque_t.size, circular_t.size);
   do_check_true(opaque_t.prototype.hasOwnProperty("b"));
   do_check_false(opaque_t.prototype.hasOwnProperty("c"));
 
   // StructType size, alignment, and offset calculations have already been
   // checked for each basic type. We do not need to check them again.
   let name = "g_t";
   let g_t = ctypes.StructType(name, [{ a: ctypes.int32_t }, { b: ctypes.double }]);
@@ -1527,88 +1522,88 @@ function run_StructType_tests() {
   let fields = [{ a: ctypes.int32_t }, { b: ctypes.int8_t }, { c: g_t }, { d: ctypes.int8_t }];
   let t_t = new ctypes.StructType("t_t", fields);
   do_check_eq(t_t.fields.length, 4);
   do_check_true(t_t.fields[0].a === ctypes.int32_t);
   do_check_true(t_t.fields[1].b === ctypes.int8_t);
   do_check_true(t_t.fields[2].c === g_t);
   do_check_true(t_t.fields[3].d === ctypes.int8_t);
 /* disabled temporarily per bug 598225.
-  do_check_throws(function() { t_t.fields.z = 0; }, ctypesGlobal.Error);
-  do_check_throws(function() { t_t.fields[4] = 0; }, ctypesGlobal.Error);
-  do_check_throws(function() { t_t.fields[4].a = 0; }, ctypesGlobal.Error);
-  do_check_throws(function() { t_t.fields[4].e = 0; }, ctypesGlobal.Error);
+  do_check_throws(function() { t_t.fields.z = 0; }, Error);
+  do_check_throws(function() { t_t.fields[4] = 0; }, Error);
+  do_check_throws(function() { t_t.fields[4].a = 0; }, Error);
+  do_check_throws(function() { t_t.fields[4].e = 0; }, Error);
 */
 
   // Check that struct size bounds work, and that large, but not illegal, sizes
   // are OK.
   if (ctypes.size_t.size == 4) {
     // Test 1: overflow struct size + field padding + field size.
     let large_t = ctypes.StructType("large_t",
         [{"a": ctypes.int8_t.array(0xffffffff)}]);
     do_check_eq(large_t.size, 0xffffffff);
     do_check_throws(function() {
       ctypes.StructType("large_t", [{"a": large_t}, {"b": ctypes.int8_t}]);
-    }, ctypesGlobal.Error);
+    }, Error);
 
     // Test 2: overflow struct size + struct tail padding.
     // To do this, we use a struct with maximum size and alignment 2.
     large_t = ctypes.StructType("large_t",
       [{"a": ctypes.int16_t.array(0xfffffffe / 2)}]);
     do_check_eq(large_t.size, 0xfffffffe);
     do_check_throws(function() {
       ctypes.StructType("large_t", [{"a": large_t}, {"b": ctypes.int8_t}]);
-    }, ctypesGlobal.Error);
+    }, Error);
 
   } else {
     // Test 1: overflow struct size when converting from size_t to jsdouble.
     let large_t = ctypes.StructType("large_t",
         [{"a": ctypes.int8_t.array(0xfffffffffffff800)}]);
     do_check_eq(large_t.size, 0xfffffffffffff800);
     do_check_throws(function() {
       ctypes.StructType("large_t", [{"a": large_t}, {"b": ctypes.int8_t}]);
-    }, ctypesGlobal.Error);
+    }, Error);
     let small_t = ctypes.int8_t.array(0x400);
     do_check_throws(function() {
       ctypes.StructType("large_t", [{"a": large_t}, {"b": small_t}]);
-    }, ctypesGlobal.Error);
+    }, Error);
 
     large_t = ctypes.StructType("large_t",
       [{"a": ctypes.int8_t.array(0x1fffffffffffff)}]);
     do_check_eq(large_t.size, 0x1fffffffffffff);
     do_check_throws(function() {
       ctypes.StructType("large_t", [{"a": large_t.array(2)}, {"b": ctypes.int8_t}]);
-    }, ctypesGlobal.Error);
+    }, Error);
 
     // Test 2: overflow struct size + field padding + field size.
     large_t = ctypes.int8_t.array(0xfffffffffffff800);
     small_t = ctypes.int8_t.array(0x800);
     do_check_throws(function() {
       ctypes.StructType("large_t", [{"a": large_t}, {"b": small_t}]);
-    }, ctypesGlobal.Error);
+    }, Error);
 
     // Test 3: overflow struct size + struct tail padding.
     // To do this, we use a struct with maximum size and alignment 2.
     large_t = ctypes.StructType("large_t",
       [{"a": ctypes.int16_t.array(0xfffffffffffff000 / 2)}]);
     do_check_eq(large_t.size, 0xfffffffffffff000);
     small_t = ctypes.int8_t.array(0xfff);
     do_check_throws(function() {
       ctypes.StructType("large_t", [{"a": large_t}, {"b": small_t}]);
-    }, ctypesGlobal.Error);
+    }, Error);
   }
 
   let g = g_t();
   do_check_eq(g.a, 0);
   do_check_eq(g.b, 0);
   g = new g_t(1, 2);
   do_check_eq(g.a, 1);
   do_check_eq(g.b, 2);
-  do_check_throws(function() { g_t(1); }, ctypesGlobal.Error);
-  do_check_throws(function() { g_t(1, 2, 3); }, ctypesGlobal.Error);
+  do_check_throws(function() { g_t(1); }, Error);
+  do_check_throws(function() { g_t(1, 2, 3); }, Error);
 
   for (let field in g)
     do_check_true(field == "a" || field == "b");
 
   let g_a = g.address();
   do_check_true(g_a.constructor === g_t.ptr);
   do_check_eq(g_a.contents.a, g.a);
 
@@ -1623,59 +1618,59 @@ function run_StructType_tests() {
   do_check_eq(g2.a, 1);
   g2.a = 7;
   do_check_eq(g2.a, 7);
   do_check_eq(s.b.a, 7);
 
   g_a = s.addressOfField("b");
   do_check_true(g_a.constructor === g_t.ptr);
   do_check_eq(g_a.contents.a, s.b.a);
-  do_check_throws(function() { s.addressOfField(); }, ctypesGlobal.Error);
-  do_check_throws(function() { s.addressOfField("d"); }, ctypesGlobal.Error);
-  do_check_throws(function() { s.addressOfField("a", 2); }, ctypesGlobal.Error);
+  do_check_throws(function() { s.addressOfField(); }, Error);
+  do_check_throws(function() { s.addressOfField("d"); }, Error);
+  do_check_throws(function() { s.addressOfField("a", 2); }, Error);
 
   do_check_eq(s.toSource(), "s_t(4, {\"a\": 7, \"b\": 2}, 10)");
   do_check_eq(s.toSource(), s.toString());
   eval("let s2 = " + s.toSource());
   do_check_true(s2.constructor === s_t);
   do_check_eq(s.b.b, s2.b.b);
 
   // Test that structs can be set from an object using 'value'.
-  do_check_throws(function() { s.value; }, ctypesGlobal.Error);
+  do_check_throws(function() { s.value; }, Error);
   let s_init = { "a": 2, "b": { "a": 9, "b": 5 }, "c": 13 };
   s.value = s_init;
   do_check_eq(s.b.a, 9);
   do_check_eq(s.c, 13);
-  do_check_throws(function() { s.value = 5; }, ctypesGlobal.Error);
-  do_check_throws(function() { s.value = ctypes.int32_t(); }, ctypesGlobal.Error);
-  do_check_throws(function() { s.value = {}; }, ctypesGlobal.Error);
-  do_check_throws(function() { s.value = { "a": 2 }; }, ctypesGlobal.Error);
-  do_check_throws(function() { s.value = { "a": 2, "b": 5, "c": 10 }; }, ctypesGlobal.Error);
+  do_check_throws(function() { s.value = 5; }, Error);
+  do_check_throws(function() { s.value = ctypes.int32_t(); }, Error);
+  do_check_throws(function() { s.value = {}; }, Error);
+  do_check_throws(function() { s.value = { "a": 2 }; }, Error);
+  do_check_throws(function() { s.value = { "a": 2, "b": 5, "c": 10 }; }, Error);
   do_check_throws(function() {
     s.value = { "5": 2, "b": { "a": 9, "b": 5 }, "c": 13 };
-  }, ctypesGlobal.Error);
+  }, Error);
   do_check_throws(function() {
     s.value = { "a": 2, "b": { "a": 9, "b": 5 }, "c": 13, "d": 17 };
-  }, ctypesGlobal.Error);
+  }, Error);
   do_check_throws(function() {
     s.value = { "a": 2, "b": { "a": 9, "b": 5, "e": 9 }, "c": 13 };
-  }, ctypesGlobal.Error);
+  }, Error);
 
   // Test that structs can be constructed similarly through ExplicitConvert,
   // and that the single-field case is disambiguated correctly.
   s = s_t(s_init);
   do_check_eq(s.b.a, 9);
   do_check_eq(s.c, 13);
   let v_t = ctypes.StructType("v_t", [{ "x": ctypes.int32_t }]);
   let v = v_t({ "x": 5 });
   do_check_eq(v.x, 5);
   v = v_t(8);
   do_check_eq(v.x, 8);
   let w_t = ctypes.StructType("w_t", [{ "y": v_t }]);
-  do_check_throws(function() { w_t(9); }, ctypesGlobal.Error);
+  do_check_throws(function() { w_t(9); }, Error);
   let w = w_t({ "x": 3 });
   do_check_eq(w.y.x, 3);
   w = w_t({ "y": { "x": 19 } });
   do_check_eq(w.y.x, 19);
   let u_t = ctypes.StructType("u_t", [{ "z": ctypes.ArrayType(ctypes.int32_t, 3) }]);
   let u = u_t([1, 2, 3]);
   do_check_eq(u.z[1], 2);
   u = u_t({ "z": [4, 5, 6] });
@@ -1685,40 +1680,40 @@ function run_StructType_tests() {
   let z_t = ctypes.StructType("z_t", []);
   do_check_eq(z_t.size, 1);
   do_check_eq(z_t.fields.length, 0);
 
   // Check that structs containing arrays of undefined or zero length
   // are illegal, but arrays of defined length work.
   do_check_throws(function() {
     ctypes.StructType("z_t", [{ a: ctypes.int32_t.array() }]);
-  }, ctypesGlobal.Error);
+  }, Error);
   do_check_throws(function() {
     ctypes.StructType("z_t", [{ a: ctypes.int32_t.array(0) }]);
-  }, ctypesGlobal.Error);
+  }, Error);
   z_t = ctypes.StructType("z_t", [{ a: ctypes.int32_t.array(6) }]);
   do_check_eq(z_t.size, ctypes.int32_t.size * 6);
   let z = z_t([1, 2, 3, 4, 5, 6]);
   do_check_eq(z.a[3], 4);
 }
 
 function ptrValue(p) {
   return ctypes.cast(p, ctypes.uintptr_t).value.toString();
 }
 
 function run_PointerType_tests() {
   run_type_ctor_class_tests(ctypes.PointerType,
     ctypes.PointerType(ctypes.int32_t), ctypes.PointerType(ctypes.int64_t),
     [ "targetType" ], [], [ "contents" ], [ "isNull" ], []);
 
-  do_check_throws(function() { ctypes.PointerType(); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.PointerType(ctypes.int32_t, 5); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.PointerType(null); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.PointerType(ctypes.int32_t()); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.PointerType("void"); }, ctypesGlobal.Error);
+  do_check_throws(function() { ctypes.PointerType(); }, Error);
+  do_check_throws(function() { ctypes.PointerType(ctypes.int32_t, 5); }, Error);
+  do_check_throws(function() { ctypes.PointerType(null); }, Error);
+  do_check_throws(function() { ctypes.PointerType(ctypes.int32_t()); }, Error);
+  do_check_throws(function() { ctypes.PointerType("void"); }, Error);
 
   let name = "g_t";
   let g_t = ctypes.StructType(name, [{ a: ctypes.int32_t }, { b: ctypes.double }]);
   let g = g_t(1, 2);
 
   let p_t = ctypes.PointerType(g_t);
   do_check_eq(p_t.name, name + "*");
   do_check_eq(p_t.size, ctypes.uintptr_t.size);
@@ -1729,44 +1724,44 @@ function run_PointerType_tests() {
   do_check_eq(p_t.toSource(),
     "ctypes.StructType(\"g_t\", [{ \"a\": ctypes.int32_t }, { \"b\": ctypes.double }]).ptr");
   do_check_true(p_t.ptr === ctypes.PointerType(p_t));
   do_check_eq(p_t.array().name, name + "*[]");
   do_check_eq(p_t.array(5).name, name + "*[5]");
 
   // Test ExplicitConvert.
   let p = p_t();
-  do_check_throws(function() { p.value; }, ctypesGlobal.Error);
+  do_check_throws(function() { p.value; }, Error);
   do_check_eq(ptrValue(p), 0);
-  do_check_throws(function() { p.contents; }, ctypesGlobal.Error);
-  do_check_throws(function() { p.contents = g; }, ctypesGlobal.Error);
+  do_check_throws(function() { p.contents; }, Error);
+  do_check_throws(function() { p.contents = g; }, Error);
   p = p_t(5);
   do_check_eq(ptrValue(p), 5);
   p = p_t(ctypes.UInt64(10));
   do_check_eq(ptrValue(p), 10);
 
   // Test ImplicitConvert.
   p.value = null;
   do_check_eq(ptrValue(p), 0);
-  do_check_throws(function() { p.value = 5; }, ctypesGlobal.Error);
+  do_check_throws(function() { p.value = 5; }, Error);
 
   // Test opaque pointers.
   let f_t = ctypes.StructType("FILE").ptr;
   do_check_eq(f_t.name, "FILE*");
   do_check_eq(f_t.toSource(), 'ctypes.StructType("FILE").ptr');
   let f = new f_t();
-  do_check_throws(function() { f.contents; }, ctypesGlobal.Error);
-  do_check_throws(function() { f.contents = 0; }, ctypesGlobal.Error);
+  do_check_throws(function() { f.contents; }, Error);
+  do_check_throws(function() { f.contents = 0; }, Error);
   let f = f_t(5);
-  do_check_throws(function() { f.contents = 0; }, ctypesGlobal.Error);
+  do_check_throws(function() { f.contents = 0; }, Error);
   do_check_eq(f.toSource(), 'FILE.ptr(ctypes.UInt64("0x5"))');
 
-  do_check_throws(function() { f_t(p); }, ctypesGlobal.Error);
-  do_check_throws(function() { f.value = p; }, ctypesGlobal.Error);
-  do_check_throws(function() { p.value = f; }, ctypesGlobal.Error);
+  do_check_throws(function() { f_t(p); }, Error);
+  do_check_throws(function() { f.value = p; }, Error);
+  do_check_throws(function() { p.value = f; }, Error);
 
   // Test void pointers.
   let v_t = ctypes.PointerType(ctypes.void_t);
   do_check_true(v_t === ctypes.voidptr_t);
   let v = v_t(p);
   do_check_eq(ptrValue(v), ptrValue(p));
 
   // Test 'contents'.
@@ -1781,49 +1776,49 @@ function run_PointerType_tests() {
   do_check_true(n.isNull() === true);
   n = p.address();
   do_check_true(n.isNull() === false);
 
   // Check that pointers to arrays of undefined or zero length are legal,
   // but that the former cannot be dereferenced.
   let z_t = ctypes.int32_t.array().ptr;
   do_check_eq(ptrValue(z_t()), 0);
-  do_check_throws(function() { z_t().contents }, ctypesGlobal.Error);
+  do_check_throws(function() { z_t().contents }, Error);
   z_t = ctypes.int32_t.array(0).ptr;
   do_check_eq(ptrValue(z_t()), 0);
   let z = ctypes.int32_t.array(0)().address();
   do_check_eq(z.contents.length, 0);
 }
 
 function run_FunctionType_tests() {
   run_type_ctor_class_tests(ctypes.FunctionType,
     ctypes.FunctionType(ctypes.default_abi, ctypes.void_t),
     ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [ ctypes.int32_t ]),
     [ "abi", "returnType", "argTypes", "isVariadic" ],
     undefined, undefined, undefined, undefined);
 
-  do_check_throws(function() { ctypes.FunctionType(); }, ctypesGlobal.Error);
+  do_check_throws(function() { ctypes.FunctionType(); }, Error);
   do_check_throws(function() {
     ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [ ctypes.void_t ]);
-  }, ctypesGlobal.Error);
+  }, Error);
   do_check_throws(function() {
     ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, [ ctypes.void_t ], 5);
-  }, ctypesGlobal.Error);
+  }, Error);
   do_check_throws(function() {
     ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, ctypes.void_t);
-  }, ctypesGlobal.Error);
+  }, Error);
   do_check_throws(function() {
     ctypes.FunctionType(ctypes.default_abi, ctypes.void_t, null);
-  }, ctypesGlobal.Error);
+  }, Error);
   do_check_throws(function() {
     ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t());
-  }, ctypesGlobal.Error);
+  }, Error);
   do_check_throws(function() {
     ctypes.FunctionType(ctypes.void_t, ctypes.void_t);
-  }, ctypesGlobal.Error);
+  }, Error);
 
   let g_t = ctypes.StructType("g_t", [{ a: ctypes.int32_t }, { b: ctypes.double }]);
   let g = g_t(1, 2);
 
   let f_t = ctypes.FunctionType(ctypes.default_abi, g_t);
   let name = "g_t()()";
   do_check_eq(f_t.name, name);
   do_check_eq(f_t.size, undefined);
@@ -1840,39 +1835,39 @@ function run_FunctionType_tests() {
   do_check_eq(fp_t.name, name);
   do_check_eq(fp_t.size, ctypes.uintptr_t.size);
 
   do_check_eq(fp_t.toString(), "type " + name);
   do_check_eq(fp_t.toSource(),
     "ctypes.FunctionType(ctypes.default_abi, g_t).ptr");
 
   // Check that constructing a FunctionType CData directly throws.
-  do_check_throws(function() { f_t(); }, ctypesGlobal.Error);
+  do_check_throws(function() { f_t(); }, Error);
 
   // Test ExplicitConvert.
   let f = fp_t();
-  do_check_throws(function() { f.value; }, ctypesGlobal.Error);
+  do_check_throws(function() { f.value; }, Error);
   do_check_eq(ptrValue(f), 0);
   f = fp_t(5);
   do_check_eq(ptrValue(f), 5);
   f = fp_t(ctypes.UInt64(10));
   do_check_eq(ptrValue(f), 10);
 
   // Test ImplicitConvert.
   f.value = null;
   do_check_eq(ptrValue(f), 0);
-  do_check_throws(function() { f.value = 5; }, ctypesGlobal.Error);
+  do_check_throws(function() { f.value = 5; }, Error);
   do_check_eq(f.toSource(),
     'ctypes.FunctionType(ctypes.default_abi, g_t).ptr(ctypes.UInt64("0x0"))');
 
   // Test ImplicitConvert from a function pointer of different type.
   let f2_t = ctypes.FunctionType(ctypes.default_abi, g_t, [ ctypes.int32_t ]);
   let f2 = f2_t.ptr();
-  do_check_throws(function() { f.value = f2; }, ctypesGlobal.Error);
-  do_check_throws(function() { f2.value = f; }, ctypesGlobal.Error);
+  do_check_throws(function() { f.value = f2; }, Error);
+  do_check_throws(function() { f2.value = f; }, Error);
 
   // Test that converting to a voidptr_t works.
   let v = ctypes.voidptr_t(f2);
   do_check_eq(v.toSource(), 'ctypes.voidptr_t(ctypes.UInt64("0x0"))');
 
   // Test some more complex names.
   do_check_eq(fp_t.array().name, "g_t(*[])()");
   do_check_eq(fp_t.array().ptr.name, "g_t(*(*)[])()");
@@ -1893,18 +1888,18 @@ function run_FunctionType_tests() {
 #endif
 
   let f4_t = ctypes.FunctionType(ctypes.default_abi,
     ctypes.char.ptr.array().ptr, [ ctypes.int32_t, fp_t ]);
   do_check_true(f4_t.argTypes.length == 2);
   do_check_true(f4_t.argTypes[0] === ctypes.int32_t);
   do_check_true(f4_t.argTypes[1] === fp_t);
 /* disabled temporarily per bug 598225.
-  do_check_throws(function() { f4_t.argTypes.z = 0; }, ctypesGlobal.Error);
-  do_check_throws(function() { f4_t.argTypes[0] = 0; }, ctypesGlobal.Error);
+  do_check_throws(function() { f4_t.argTypes.z = 0; }, Error);
+  do_check_throws(function() { f4_t.argTypes[0] = 0; }, Error);
 */
 
   let t4_t = f4_t.ptr.ptr.array(8).array();
   do_check_eq(t4_t.name, "char*(*(**[][8])(int32_t, g_t(*)()))[]");
 
   // Not available in a Worker
   if ("@mozilla.org/systemprincipal;1" in Components.classes) {
     var sp = Components.classes["@mozilla.org/systemprincipal;1"].
@@ -1922,47 +1917,47 @@ function run_FunctionType_tests() {
   }
 }
 
 function run_ArrayType_tests() {
   run_type_ctor_class_tests(ctypes.ArrayType,
     ctypes.ArrayType(ctypes.int32_t, 10), ctypes.ArrayType(ctypes.int64_t),
     [ "elementType", "length" ], [], [ "length" ], [ "addressOfElement" ]);
 
-  do_check_throws(function() { ctypes.ArrayType(); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.ArrayType(null); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.ArrayType(ctypes.int32_t, 1, 5); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.ArrayType(ctypes.int32_t, -1); }, ctypesGlobal.Error);
+  do_check_throws(function() { ctypes.ArrayType(); }, Error);
+  do_check_throws(function() { ctypes.ArrayType(null); }, Error);
+  do_check_throws(function() { ctypes.ArrayType(ctypes.int32_t, 1, 5); }, Error);
+  do_check_throws(function() { ctypes.ArrayType(ctypes.int32_t, -1); }, Error);
 
   let name = "g_t";
   let g_t = ctypes.StructType(name, [{ a: ctypes.int32_t }, { b: ctypes.double }]);
   let g = g_t(1, 2);
 
   let a_t = ctypes.ArrayType(g_t, 10);
   do_check_eq(a_t.name, name + "[10]");
   do_check_eq(a_t.length, 10);
   do_check_eq(a_t.size, g_t.size * 10);
   do_check_true(a_t.elementType === g_t);
 
   do_check_eq(a_t.toString(), "type " + name + "[10]");
   do_check_eq(a_t.toSource(),
     "ctypes.StructType(\"g_t\", [{ \"a\": ctypes.int32_t }, { \"b\": ctypes.double }]).array(10)");
   do_check_eq(a_t.array().name, name + "[][10]");
   do_check_eq(a_t.array(5).name, name + "[5][10]");
-  do_check_throws(function() { ctypes.int32_t.array().array(); }, ctypesGlobal.Error);
+  do_check_throws(function() { ctypes.int32_t.array().array(); }, Error);
 
   let a = new a_t();
   do_check_eq(a[0].a, 0);
   do_check_eq(a[0].b, 0);
   a[0] = g;
   do_check_eq(a[0].a, 1);
   do_check_eq(a[0].b, 2);
-  do_check_throws(function() { a[-1]; }, ctypesGlobal.Error);
+  do_check_throws(function() { a[-1]; }, Error);
   do_check_eq(a[9].a, 0);
-  do_check_throws(function() { a[10]; }, ctypesGlobal.Error);
+  do_check_throws(function() { a[10]; }, Error);
 
   do_check_eq(a[ctypes.Int64(0)].a, 1);
   do_check_eq(a[ctypes.UInt64(0)].b, 2);
 
   let a_p = a.addressOfElement(0);
   do_check_true(a_p.constructor.targetType === g_t);
   do_check_true(a_p.constructor === g_t.ptr);
   do_check_eq(a_p.contents.a, a[0].a);
@@ -1973,48 +1968,48 @@ function run_ArrayType_tests() {
   let a2_t = ctypes.ArrayType(g_t);
   do_check_eq(a2_t.name, "g_t[]");
   do_check_eq(a2_t.length, undefined);
   do_check_eq(a2_t.size, undefined);
   let a2 = new a2_t(5);
   do_check_eq(a2.constructor.length, 5);
   do_check_eq(a2.length, 5);
   do_check_eq(a2.constructor.size, g_t.size * 5);
-  do_check_throws(function() { new a2_t(); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.ArrayType(ctypes.ArrayType(g_t)); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.ArrayType(ctypes.ArrayType(g_t), 5); }, ctypesGlobal.Error);
+  do_check_throws(function() { new a2_t(); }, Error);
+  do_check_throws(function() { ctypes.ArrayType(ctypes.ArrayType(g_t)); }, Error);
+  do_check_throws(function() { ctypes.ArrayType(ctypes.ArrayType(g_t), 5); }, Error);
 
   let b_t = ctypes.int8_t.array(ctypes.UInt64(0xffff));
   do_check_eq(b_t.length, 0xffff);
   b_t = ctypes.int8_t.array(ctypes.Int64(0xffff));
   do_check_eq(b_t.length, 0xffff);
 
   // Check that array size bounds work, and that large, but not illegal, sizes
   // are OK.
   if (ctypes.size_t.size == 4) {
     do_check_throws(function() {
       ctypes.ArrayType(ctypes.int8_t, 0x100000000);
-    }, ctypesGlobal.Error);
+    }, Error);
     do_check_throws(function() {
       ctypes.ArrayType(ctypes.int16_t, 0x80000000);
-    }, ctypesGlobal.Error);
+    }, Error);
 
     let large_t = ctypes.int8_t.array(0x80000000);
-    do_check_throws(function() { large_t.array(2); }, ctypesGlobal.Error);
+    do_check_throws(function() { large_t.array(2); }, Error);
 
   } else {
     do_check_throws(function() {
       ctypes.ArrayType(ctypes.int8_t, ctypes.UInt64("0xffffffffffffffff"));
-    }, ctypesGlobal.Error);
+    }, Error);
     do_check_throws(function() {
       ctypes.ArrayType(ctypes.int16_t, ctypes.UInt64("0x8000000000000000"));
-    }, ctypesGlobal.Error);
+    }, Error);
 
     let large_t = ctypes.int8_t.array(0x8000000000000000);
-    do_check_throws(function() { large_t.array(2); }, ctypesGlobal.Error);
+    do_check_throws(function() { large_t.array(2); }, Error);
   }
 
   // Test that arrays ImplicitConvert to pointers.
   let b = ctypes.int32_t.array(10)();
   let p = ctypes.int32_t.ptr();
   p.value = b;
   do_check_eq(ptrValue(b.addressOfElement(0)), ptrValue(p));
   p = ctypes.voidptr_t();
@@ -2029,37 +2024,37 @@ function run_ArrayType_tests() {
   do_check_eq(c.toSource(), c.toString());
   eval("let c2 = " + c.toSource());
   do_check_eq(c2.constructor.name, "int32_t[6]");
   do_check_eq(c2.length, 6);
   do_check_eq(c2[3], c[3]);
 
   c.value = c;
   do_check_eq(c[3], 4);
-  do_check_throws(function() { c.value; }, ctypesGlobal.Error);
-  do_check_throws(function() { c.value = [1, 2, 3, 4, 5]; }, ctypesGlobal.Error);
-  do_check_throws(function() { c.value = [1, 2, 3, 4, 5, 6, 7]; }, ctypesGlobal.Error);
-  do_check_throws(function() { c.value = [1, 2, 7.4, 4, 5, 6]; }, ctypesGlobal.Error);
-  do_check_throws(function() { c.value = []; }, ctypesGlobal.Error);
+  do_check_throws(function() { c.value; }, Error);
+  do_check_throws(function() { c.value = [1, 2, 3, 4, 5]; }, Error);
+  do_check_throws(function() { c.value = [1, 2, 3, 4, 5, 6, 7]; }, Error);
+  do_check_throws(function() { c.value = [1, 2, 7.4, 4, 5, 6]; }, Error);
+  do_check_throws(function() { c.value = []; }, Error);
 }
 
 function run_cast_tests() {
   // Test casting between basic types.
   let i = ctypes.int32_t();
   let j = ctypes.cast(i, ctypes.int16_t);
   do_check_eq(ptrValue(i.address()), ptrValue(j.address()));
   do_check_eq(i.value, j.value);
   let k = ctypes.cast(i, ctypes.uint32_t);
   do_check_eq(ptrValue(i.address()), ptrValue(k.address()));
   do_check_eq(i.value, k.value);
 
   // Test casting to a type of undefined or larger size.
-  do_check_throws(function() { ctypes.cast(i, ctypes.void_t); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.cast(i, ctypes.int32_t.array()); }, ctypesGlobal.Error);
-  do_check_throws(function() { ctypes.cast(i, ctypes.int64_t); }, ctypesGlobal.Error);
+  do_check_throws(function() { ctypes.cast(i, ctypes.void_t); }, Error);
+  do_check_throws(function() { ctypes.cast(i, ctypes.int32_t.array()); }, Error);
+  do_check_throws(function() { ctypes.cast(i, ctypes.int64_t); }, Error);
 
   // Test casting between special types.
   let g_t = ctypes.StructType("g_t", [{ a: ctypes.int32_t }, { b: ctypes.double }]);
   let a_t = ctypes.ArrayType(g_t, 4);
   let p_t = ctypes.PointerType(g_t);
   let f_t = ctypes.FunctionType(ctypes.default_abi, ctypes.void_t).ptr;
 
   let a = a_t();
@@ -2087,40 +2082,40 @@ function run_cast_tests() {
 
 function run_void_tests(library) {
   let test_void_t = library.declare("test_void_t_cdecl", ctypes.default_abi, ctypes.void_t);
   do_check_eq(test_void_t(), undefined);
 
   // Test that library.declare throws with void function args.
   do_check_throws(function() {
     library.declare("test_void_t_cdecl", ctypes.default_abi, ctypes.void_t, ctypes.void_t);
-  }, ctypesGlobal.Error);
+  }, Error);
 
 #ifdef WIN32
 #ifndef HAVE_64BIT_OS
   test_void_t = library.declare("test_void_t_stdcall", ctypes.stdcall_abi, ctypes.void_t);
   do_check_eq(test_void_t(), undefined);
 
   // Check that WINAPI symbol lookup for a regular stdcall function fails.
   do_check_throws(function() {
     let test_winapi_t = library.declare("test_void_t_stdcall", ctypes.winapi_abi, ctypes.void_t);
-  }, ctypesGlobal.Error);
+  }, Error);
 #endif
 #endif
 }
 
 function run_string_tests(library) {
   let test_ansi_len = library.declare("test_ansi_len", ctypes.default_abi, ctypes.int32_t, ctypes.char.ptr);
   do_check_eq(test_ansi_len(""), 0);
   do_check_eq(test_ansi_len("hello world"), 11);
 
   // don't convert anything else to a string
   let vals = [true, 0, 1/3, undefined, {}, {toString: function () { return "bad"; }}, []];
   for (let i = 0; i < vals.length; i++)
-    do_check_throws(function() { test_ansi_len(vals[i]); }, ctypesGlobal.TypeError);
+    do_check_throws(function() { test_ansi_len(vals[i]); }, TypeError);
 
   let test_wide_len = library.declare("test_wide_len", ctypes.default_abi, ctypes.int32_t, ctypes.jschar.ptr);
   do_check_eq(test_wide_len("hello world"), 11);
 
   let test_ansi_ret = library.declare("test_ansi_ret", ctypes.default_abi, ctypes.char.ptr);
   do_check_eq(test_ansi_ret().readString(), "success");
 
   let test_wide_ret = library.declare("test_wide_ret", ctypes.default_abi, ctypes.jschar.ptr);
@@ -2235,26 +2230,26 @@ function run_function_tests(library)
 
   // Test that library.declare() returns data of type FunctionType.ptr, and that
   // it is immutable.
   do_check_true(test_ansi_len.constructor.targetType.__proto__ ===
     ctypes.FunctionType.prototype);
   do_check_eq(test_ansi_len.constructor.toSource(),
     "ctypes.FunctionType(ctypes.default_abi, ctypes.int32_t, [ctypes.char.ptr]).ptr");
 /* disabled temporarily per bug 598225.
-  do_check_throws(function() { test_ansi_len.value = null; }, ctypesGlobal.Error);
+  do_check_throws(function() { test_ansi_len.value = null; }, Error);
   do_check_eq(ptrValue(test_ansi_len), ptrValue(ptr));
 */
 
   // Test that the library.declare(name, functionType) form works.
   let test_ansi_len_2 = library.declare("test_ansi_len", fn_t);
   do_check_true(test_ansi_len_2.constructor === fn_t);
   do_check_eq(ptrValue(test_ansi_len), ptrValue(test_ansi_len_2));
 /* disabled temporarily per bug 598225.
-  do_check_throws(function() { test_ansi_len_2.value = null; }, ctypesGlobal.Error);
+  do_check_throws(function() { test_ansi_len_2.value = null; }, Error);
   do_check_eq(ptrValue(test_ansi_len_2), ptrValue(ptr));
 */
 }
 
 function run_closure_tests(library)
 {
   run_single_closure_tests(library, ctypes.default_abi, "cdecl");
 #ifdef WIN32
@@ -2262,17 +2257,17 @@ function run_closure_tests(library)
   run_single_closure_tests(library, ctypes.stdcall_abi, "stdcall");
 
   // Check that attempting to construct a ctypes.winapi_abi closure throws.
   function closure_fn()
   {
     return 1;
   }
   let fn_t = ctypes.FunctionType(ctypes.winapi_abi, ctypes.int32_t, []).ptr;
-  do_check_throws(function() { fn_t(closure_fn) }, ctypesGlobal.Error);
+  do_check_throws(function() { fn_t(closure_fn) }, Error);
 #endif
 #endif
 }
 
 function run_single_closure_tests(library, abi, suffix)
 {
   let b = 23;
 
@@ -2317,39 +2312,39 @@ function run_variadic_tests(library) {
                      ctypes.int32_t(1),
                      ctypes.int32_t(2),
                      ctypes.int32_t(3)),
               6);
 
   do_check_throws(function() {
     ctypes.FunctionType(ctypes.default_abi, ctypes.bool,
                         [ctypes.bool, "...", ctypes.bool]);
-  }, ctypesGlobal.Error);
+  }, Error);
 
   do_check_throws(function() {
     ctypes.FunctionType(ctypes.default_abi, ctypes.bool, ["..."]);
-  }, ctypesGlobal.Error);
+  }, Error);
 
 #ifdef WIN32
 #ifndef HAVE_64BIT_OS
   do_check_throws(function() {
       ctypes.FunctionType(ctypes.stdcall_abi, ctypes.bool,
                           [ctypes.bool, "..."]);
-  }, ctypesGlobal.Error);
+  }, Error);
   do_check_throws(function() {
       ctypes.FunctionType(ctypes.winapi_abi, ctypes.bool,
                           [ctypes.bool, "..."]);
-  }, ctypesGlobal.Error);
+  }, Error);
 #endif
 #endif
 
   do_check_throws(function() {
     // No variadic closure callbacks allowed.
     sum_va_type(function(){});
-  }, ctypesGlobal.Error);
+  }, Error);
 
   let count_true_va = library.declare("test_sum_va_cdecl", ctypes.default_abi, ctypes.uint8_t,
                                       ctypes.uint8_t, "...");
   do_check_eq(count_true_va(8,
                             ctypes.bool(false),
                             ctypes.bool(false),
                             ctypes.bool(false),
                             ctypes.bool(true),
@@ -2385,17 +2380,17 @@ function run_variadic_tests(library) {
   do_check_eq(result[2], 16);
   
   do_check_true(!!(sum_va_type().value = sum_va_type()));
   let sum_notva_type = ctypes.FunctionType(sum_va_type.targetType.abi,
                                            sum_va_type.targetType.returnType,
                                            [ctypes.uint8_t]).ptr;
   do_check_throws(function() {
     sum_va_type().value = sum_notva_type();
-  }, ctypesGlobal.Error);
+  }, Error);
 }
 
 function run_static_data_tests(library)
 {
   const rect_t = new ctypes.StructType("RECT",
                        [{ top   : ctypes.int32_t },
                         { left  : ctypes.int32_t },
                         { bottom: ctypes.int32_t },
--- a/toolkit/components/perf/PerfMeasurement.cpp
+++ b/toolkit/components/perf/PerfMeasurement.cpp
@@ -107,17 +107,21 @@ NS_IMETHODIMP
 Module::Call(nsIXPConnectWrappedNative* wrapper,
              JSContext* cx,
              JSObject* obj,
              PRUint32 argc,
              jsval* argv,
              jsval* vp,
              PRBool* _retval)
 {
-  JSObject* global = JS_GetGlobalForScopeChain(cx);
+  JSObject* scope = JS_GetScopeChain(cx);
+  if (!scope)
+    return NS_ERROR_NOT_AVAILABLE;
+
+  JSObject* global = JS_GetGlobalForObject(cx, scope);
   if (!global)
     return NS_ERROR_NOT_AVAILABLE;
 
   *_retval = InitAndSealPerfMeasurementClass(cx, global);
   return NS_OK;
 }
 
 }