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 id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswaldo, orange
bugs631135
milestone2.0b12pre
backs out4d86e63ff60d40f4c39a1c7d1d880b77d61f9565
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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;
 }
 
 }