Backed out 33 changesets (bug 896126, bug 887334, bug 889911, bug 889714, bug 895774) for xpcshell failures on a CLOSED TREE.
authorRyan VanderMeulen <ryanvm@gmail.com>
Sat, 27 Jul 2013 10:29:36 -0400
changeset 148112 b3d0c2498b4219e9b2761bb95a1e96c27cbefe34
parent 148111 5f9484e134f9539e4618d30153900e7940d8367f
child 148113 3a82519f0b44c1d7f0b5e4880a3055bab642aac0
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs896126, 887334, 889911, 889714, 895774
milestone24.0a2
backs out5f9484e134f9539e4618d30153900e7940d8367f
8318754cde46aa4fe2ca7a721aa90f05ff7e5534
3c2b8b15cdaaf1aa48bb9660624b564717e8fba2
fc50bc25f83c1a907b10b08165666e93925356d0
ddf47eba68c0475e52be91eb6326b9ecd79a2fbf
b78327115beabba80b40bb7fc0354f10d0ccef32
5db330103fbe1013d65d21a5843828b83e37cf93
6844870765b114d44bef1e330ac03e99ac9c2e27
ff3db04a7caa15a4170955f8c66ee2832fa4606e
af1c512d29787e5bfaaf624ad7e82aaaf7b147cc
35b6d437eb110a9d6f3d7d851adbd8e62f31fcab
28ea664f13330c25a5fc16b9cd5b525583fa579f
be520c3f0c897b43452d3334d3f10b853301119e
508522bee36719b268482ae8379d3dfc7a942a9f
0d59888536b54999cd4d9a6284a2c08c39873af2
101e407d040a669532f57eab945df6bbdb95bdf3
cd2f2d2299eef5157a5dcae14f3bd3879f439e1c
f7fb970c89065b86e360e714d7c947e917d5c1c9
fd8bd2219d4908c4bf7559ae83f4c39cdf219ef3
40c3e35e19861603a31655cf7b26f5c8eecd2020
b2bb42cc8f020bd6cb008f826ff9a7e2b1bc223a
e22cc8bdcbcf8b37d1c45dccfe7c61e9f04b91a1
588385ea4fee6e397ea5024450b38cbcec8a11d1
9150b4f39c107c34e35b7dbe0737819f6add3a27
43e8b15601b8c303e779d152bcbd1ff51841a3cc
3242b9e0f6b07d362787661b1154140d09e2e995
7b45f302e40e47cedd70422d80a3d994cae715c6
53e221a057cc113fe99d295a29963a79be485bef
193e8efe1350b9b5b36adb7370fa3b30a66d280e
b78af29d5ac5e7d3c08bfb9ecf4c0b3313b37de9
b156c252aac0c9f39564700dd33d2c9b118df898
a6b7104a9a82d7d9ad7a88a4302c8384645b92c5
d1e156bb38059cc3291713c4badfd7ebe3c9e26a
Backed out 33 changesets (bug 896126, bug 887334, bug 889911, bug 889714, bug 895774) for xpcshell failures on a CLOSED TREE. Backed out changeset 5f9484e134f9 (bug 896126) Backed out changeset 8318754cde46 (bug 887334) Backed out changeset 3c2b8b15cdaa (bug 887334) Backed out changeset fc50bc25f83c (bug 887334) Backed out changeset ddf47eba68c0 (bug 887334) Backed out changeset b78327115bea (bug 887334) Backed out changeset 5db330103fbe (bug 887334) Backed out changeset 6844870765b1 (bug 887334) Backed out changeset ff3db04a7caa (bug 887334) Backed out changeset af1c512d2978 (bug 887334) Backed out changeset 35b6d437eb11 (bug 887334) Backed out changeset 28ea664f1333 (bug 887334) Backed out changeset be520c3f0c89 (bug 887334) Backed out changeset 508522bee367 (bug 887334) Backed out changeset 0d59888536b5 (bug 887334) Backed out changeset 101e407d040a (bug 887334) Backed out changeset cd2f2d2299ee (bug 887334) Backed out changeset f7fb970c8906 (bug 887334) Backed out changeset fd8bd2219d49 (bug 887334) Backed out changeset 40c3e35e1986 (bug 889714) Backed out changeset b2bb42cc8f02 (bug 889714) Backed out changeset e22cc8bdcbcf (bug 889714) Backed out changeset 588385ea4fee (bug 889714) Backed out changeset 9150b4f39c10 (bug 889714) Backed out changeset 43e8b15601b8 (bug 889714) Backed out changeset 3242b9e0f6b0 (bug 889714) Backed out changeset 7b45f302e40e (bug 889714) Backed out changeset 53e221a057cc (bug 889714) Backed out changeset 193e8efe1350 (bug 889911) Backed out changeset b78af29d5ac5 (bug 889911) Backed out changeset b156c252aac0 (bug 889911) Backed out changeset a6b7104a9a82 (bug 889911) Backed out changeset d1e156bb3805 (bug 895774)
content/xbl/src/nsXBLProtoImplMethod.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsJSEnvironment.cpp
dom/base/nsJSUtils.cpp
dom/indexedDB/IDBObjectStore.cpp
dom/workers/WorkerPrivate.cpp
ipc/testshell/TestShellChild.cpp
ipc/testshell/TestShellParent.cpp
ipc/testshell/XPCShellEnvironment.cpp
ipc/testshell/XPCShellEnvironment.h
js/src/ion/Ion.cpp
js/src/jit-test/tests/basic/testBug895774.js
js/src/jit-test/tests/parser/bug-896126.js
js/src/jsapi-tests/tests.cpp
js/src/jsapi-tests/tests.h
js/src/jsapi.cpp
js/src/jsatom.cpp
js/src/jscntxt.cpp
js/src/jscntxtinlines.h
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/jscompartmentinlines.h
js/src/jsdbgapi.cpp
js/src/jsfriendapi.cpp
js/src/jsfriendapi.h
js/src/shell/js.cpp
js/src/vm/Debugger.cpp
js/src/vm/SelfHosting.cpp
js/src/vm/Stack.cpp
js/src/vm/Stack.h
js/src/vm/String.cpp
js/xpconnect/idl/nsIScriptError.idl
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/loader/mozJSSubScriptLoader.cpp
js/xpconnect/shell/xpcshell.cpp
js/xpconnect/src/XPCJSContextStack.cpp
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/XPCQuickStubs.cpp
js/xpconnect/src/nsCxPusher.cpp
js/xpconnect/src/nsCxPusher.h
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/src/xpcpublic.h
netwerk/base/src/ProxyAutoConfig.cpp
toolkit/components/contentprefs/tests/unit_cps2/AsyncRunner.jsm
toolkit/components/social/test/xpcshell/head.js
toolkit/devtools/server/tests/unit/test_sourcemaps-04.js
toolkit/devtools/server/tests/unit/test_sourcemaps-05.js
toolkit/mozapps/installer/precompile_cache.js
--- a/content/xbl/src/nsXBLProtoImplMethod.cpp
+++ b/content/xbl/src/nsXBLProtoImplMethod.cpp
@@ -342,17 +342,20 @@ nsXBLProtoImplAnonymousMethod::Execute(n
                                 0 /* argc */, nullptr /* argv */, retval.address());
   }
 
   if (!ok) {
     // If a constructor or destructor threw an exception, it doesn't stop
     // anything else.  We just report it.  Note that we need to set aside the
     // frame chain here, since the constructor invocation is not related to
     // whatever is on the stack right now, really.
-    nsJSUtils::ReportPendingException(cx);
+    JSBool saved = JS_SaveFrameChain(cx);
+    JS_ReportPendingException(cx);
+    if (saved)
+        JS_RestoreFrameChain(cx);
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 nsresult
 nsXBLProtoImplAnonymousMethod::Write(nsIScriptContext* aContext,
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -2067,19 +2067,18 @@ nsGlobalWindow::CreateOuterObject(nsGlob
   js::SetProxyExtra(outer, 0, js::PrivateValue(ToSupports(this)));
 
   return SetOuterObject(cx, outer);
 }
 
 nsresult
 nsGlobalWindow::SetOuterObject(JSContext* aCx, JS::Handle<JSObject*> aOuterObject)
 {
-  JSAutoCompartment ac(aCx, aOuterObject);
-
-  // Indicate the default compartment object associated with this cx.
+  // Force our context's global object to be the outer.
+  // NB: JS_SetGlobalObject sets aCx->compartment.
   JS_SetGlobalObject(aCx, aOuterObject);
 
   // Set up the prototype for the outer object.
   JSObject* inner = JS_GetParent(aOuterObject);
   JS::Rooted<JSObject*> proto(aCx);
   if (!JS_GetPrototype(aCx, inner, proto.address())) {
     return NS_ERROR_FAILURE;
   }
@@ -10850,25 +10849,23 @@ nsGlobalWindow::BuildURIfromBase(const c
   if (aCXused)
     *aCXused = cx;
   return NS_NewURI(aBuiltURI, nsDependentCString(aURL), charset.get(), baseURI);
 }
 
 nsresult
 nsGlobalWindow::SecurityCheckURL(const char *aURL)
 {
-  JSContext       *cxUsed;
+  JSContext       *cx;
   bool             freePass;
   nsCOMPtr<nsIURI> uri;
 
-  if (NS_FAILED(BuildURIfromBase(aURL, getter_AddRefs(uri), &freePass, &cxUsed)))
+  if (NS_FAILED(BuildURIfromBase(aURL, getter_AddRefs(uri), &freePass, &cx)))
     return NS_ERROR_FAILURE;
 
-  AutoPushJSContext cx(cxUsed);
-
   if (!freePass && NS_FAILED(nsContentUtils::GetSecurityManager()->
         CheckLoadURIFromScript(cx, uri)))
     return NS_ERROR_FAILURE;
 
   return NS_OK;
 }
 
 void
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1328,17 +1328,16 @@ nsJSContext::CompileScript(const PRUnich
   PROFILER_LABEL_PRINTF("JS", "Compile Script", "%s", aURL ? aURL : "");
   NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
 
   NS_ENSURE_ARG_POINTER(aPrincipal);
 
   AutoPushJSContext cx(mContext);
   JSAutoRequest ar(cx);
   JS::Rooted<JSObject*> scopeObject(mContext, GetNativeGlobal());
-  JSAutoCompartment ac(cx, scopeObject);
   xpc_UnmarkGrayObject(scopeObject);
 
   bool ok = false;
 
   nsresult rv = sSecurityManager->CanExecuteScripts(cx, aPrincipal, &ok);
   if (NS_FAILED(rv)) {
     return NS_ERROR_FAILURE;
   }
@@ -2340,20 +2339,17 @@ bool
 nsJSContext::IsContextInitialized()
 {
   return mIsInitialized;
 }
 
 void
 nsJSContext::ScriptEvaluated(bool aTerminated)
 {
-  if (GetNativeGlobal()) {
-    JSAutoCompartment ac(mContext, GetNativeGlobal());
-    JS_MaybeGC(mContext);
-  }
+  JS_MaybeGC(mContext);
 
   if (aTerminated) {
     mOperationCallbackTime = 0;
     mModalStateTime = 0;
     mActive = true;
   }
 }
 
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -138,20 +138,17 @@ nsJSUtils::GetCurrentlyRunningCodeInnerW
   return innerWindowID;
 }
 
 void
 nsJSUtils::ReportPendingException(JSContext *aContext)
 {
   if (JS_IsExceptionPending(aContext)) {
     bool saved = JS_SaveFrameChain(aContext);
-    {
-      JSAutoCompartment ac(aContext, js::GetDefaultGlobalForContext(aContext));
-      JS_ReportPendingException(aContext);
-    }
+    JS_ReportPendingException(aContext);
     if (saved) {
       JS_RestoreFrameChain(aContext);
     }
   }
 }
 
 nsresult
 nsJSUtils::CompileFunction(JSContext* aCx,
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -555,21 +555,16 @@ class ThreadLocalJSRuntime
     return entry;
   }
 
   JSContext *Context() const
   {
     return mContext;
   }
 
-  JSObject *Global() const
-  {
-    return mGlobal;
-  }
-
   ~ThreadLocalJSRuntime()
   {
     MOZ_COUNT_DTOR(ThreadLocalJSRuntime);
 
     if (mContext) {
       JS_DestroyContext(mContext);
     }
 
@@ -4033,17 +4028,16 @@ CreateIndexHelper::InsertDataFromObjectS
     tlsEntry = ThreadLocalJSRuntime::Create();
     NS_ENSURE_TRUE(tlsEntry, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
     PR_SetThreadPrivate(sTLSIndex, tlsEntry);
   }
 
   JSContext* cx = tlsEntry->Context();
   JSAutoRequest ar(cx);
-  JSAutoCompartment ac(cx, tlsEntry->Global());
 
   do {
     StructuredCloneReadInfo cloneReadInfo;
     rv = IDBObjectStore::GetStructuredCloneReadInfoFromStatement(stmt, 1, 2,
       mDatabase, cloneReadInfo);
     NS_ENSURE_SUCCESS(rv, rv);
 
     JSAutoStructuredCloneBuffer& buffer = cloneReadInfo.mCloneBuffer;
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -1687,23 +1687,16 @@ WorkerRunnable::Run()
   JSAutoRequest ar(cx);
 
   Maybe<JSAutoCompartment> ac;
   if (targetCompartmentObject) {
     ac.construct(cx, targetCompartmentObject);
   }
 
   bool result = WorkerRun(cx, mWorkerPrivate);
-  // In the case of CompileScriptRunnnable, WorkerRun above can cause us to
-  // lazily create a global, in which case we need to be in its compartment
-  // when calling PostRun() below. Maybe<> this time...
-  if (mTarget == WorkerThread && ac.empty() &&
-      js::GetDefaultGlobalForContext(cx)) {
-    ac.construct(cx, js::GetDefaultGlobalForContext(cx));
-  }
   PostRun(cx, mWorkerPrivate, result);
   return result ? NS_OK : NS_ERROR_FAILURE;
 }
 
 void
 WorkerRunnable::PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
                         bool aRunResult)
 {
@@ -2837,17 +2830,16 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
     runnable = new GarbageCollectRunnable(this, true, false);
     idleGCEventTarget = new WorkerRunnableEventTarget(runnable);
 
     idleGCEvent = runnable;
   }
 
   EnableMemoryReporter();
 
-  Maybe<JSAutoCompartment> maybeAC;
   for (;;) {
     Status currentStatus;
     bool scheduleIdleGC;
 
     WorkerRunnable* event;
     {
       MutexAutoLock lock(mMutex);
 
@@ -2856,27 +2848,16 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
       }
 
       bool eventIsNotIdleGCEvent;
       currentStatus = mStatus;
 
       {
         MutexAutoUnlock unlock(mMutex);
 
-        // Workers lazily create a global object in CompileScriptRunnable. In
-        // the old world, creating the global would implicitly set it as the
-        // default compartment object on mJSContext, meaning that subsequent
-        // runnables would be able to operate in that compartment without
-        // explicitly entering it. That no longer works, so we mimic the
-        // "operate in the compartment of the worker global once it exists"
-        // behavior here. This could probably be improved with some refactoring.
-        if (maybeAC.empty() && js::GetDefaultGlobalForContext(aCx)) {
-          maybeAC.construct(aCx, js::GetDefaultGlobalForContext(aCx));
-        }
-
         if (!normalGCTimerRunning &&
             event != idleGCEvent &&
             currentStatus <= Terminating) {
           // Must always cancel before changing the timer's target.
           if (NS_FAILED(gcTimer->Cancel())) {
             NS_WARNING("Failed to cancel GC timer!");
           }
 
--- a/ipc/testshell/TestShellChild.cpp
+++ b/ipc/testshell/TestShellChild.cpp
@@ -55,18 +55,19 @@ TestShellChild::RecvPTestShellCommandCon
   }
 
   return PTestShellCommandChild::Send__delete__(aActor, response);
 }
 
 PContextWrapperChild*
 TestShellChild::AllocPContextWrapper()
 {
-  if (mXPCShell) {
-    return new ContextWrapperChild(nsContentUtils::GetSafeJSContext());
+  JSContext* cx;
+  if (mXPCShell && (cx = mXPCShell->GetContext())) {
+    return new ContextWrapperChild(cx);
   }
   return NULL;
 }
 
 bool
 TestShellChild::DeallocPContextWrapper(PContextWrapperChild* actor)
 {
   delete actor;
--- a/ipc/testshell/TestShellParent.cpp
+++ b/ipc/testshell/TestShellParent.cpp
@@ -86,19 +86,21 @@ TestShellCommandParent::SetCallback(JSCo
 }
 
 JSBool
 TestShellCommandParent::RunCallback(const nsString& aResponse)
 {
   NS_ENSURE_TRUE(*mCallback.ToJSValPtr() != JSVAL_NULL && mCx, JS_FALSE);
 
   JSAutoRequest ar(mCx);
-  NS_ENSURE_TRUE(mCallback.ToJSObject(), JS_FALSE);
-  JSAutoCompartment ac(mCx, mCallback.ToJSObject());
-  JS::Rooted<JSObject*> global(mCx, JS_GetGlobalForScopeChain(mCx));
+
+  JS::Rooted<JSObject*> global(mCx, JS_GetGlobalForObject(mCx, mCallback.ToJSObject()));
+  NS_ENSURE_TRUE(global, JS_FALSE);
+
+  JSAutoCompartment ac(mCx, global);
 
   JSString* str = JS_NewUCStringCopyN(mCx, aResponse.get(), aResponse.Length());
   NS_ENSURE_TRUE(str, JS_FALSE);
 
   JS::Rooted<JS::Value> strVal(mCx, JS::StringValue(str));
 
   JS::Rooted<JS::Value> rval(mCx);
   JSBool ok = JS_CallFunctionValue(mCx, global, mCallback, 1, strVal.address(),
--- a/ipc/testshell/XPCShellEnvironment.cpp
+++ b/ipc/testshell/XPCShellEnvironment.cpp
@@ -1,10 +1,9 @@
-/* vim: set ts=8 sts=4 et sw=4 tw=80:
- * This Source Code Form is subject to the terms of the Mozilla Public
+/* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <stdlib.h>
 #include <errno.h>
 #ifdef HAVE_IO_H
 #include <io.h>     /* for isatty() */
 #endif
@@ -41,21 +40,22 @@
 #include "nsThreadUtils.h"
 #include "nsXULAppAPI.h"
 
 #include "BackstagePass.h"
 
 #include "TestShellChild.h"
 #include "TestShellParent.h"
 
+#define EXITCODE_RUNTIME_ERROR 3
+#define EXITCODE_FILE_NOT_FOUND 4
+
 using mozilla::ipc::XPCShellEnvironment;
 using mozilla::ipc::TestShellChild;
 using mozilla::ipc::TestShellParent;
-using mozilla::AutoSafeJSContext;
-using namespace JS;
 
 namespace {
 
 static const char kDefaultRuntimeScriptFilename[] = "xpcshell.js";
 
 class XPCShellDirProvider : public nsIDirectoryServiceProvider
 {
 public:
@@ -68,27 +68,133 @@ public:
     bool SetGREDir(const char *dir);
     void ClearGREDir() { mGREDir = nullptr; }
 
 private:
     nsCOMPtr<nsIFile> mGREDir;
 };
 
 inline XPCShellEnvironment*
-Environment(JSObject* global)
+Environment(JSContext* cx)
+{
+    XPCShellEnvironment* env = 
+        static_cast<XPCShellEnvironment*>(JS_GetContextPrivate(cx));
+    NS_ASSERTION(env, "Should never be null!");
+    return env;
+}
+
+static void
+ScriptErrorReporter(JSContext *cx,
+                    const char *message,
+                    JSErrorReport *report)
 {
-    AutoSafeJSContext cx;
-    JSAutoCompartment ac(cx, global);
-    Rooted<Value> v(cx);
-    if (!JS_GetProperty(cx, global, "__XPCShellEnvironment", v.address()) ||
-        !v.get().isDouble())
-    {
-        return nullptr;
+    int i, j, k, n;
+    char *prefix = NULL, *tmp;
+    const char *ctmp;
+    nsCOMPtr<nsIXPConnect> xpc;
+
+    // Don't report an exception from inner JS frames as the callers may intend
+    // to handle it.
+    if (JS_DescribeScriptedCaller(cx, nullptr, nullptr)) {
+        return;
+    }
+
+    // In some cases cx->fp is null here so use XPConnect to tell us about inner
+    // frames.
+    if ((xpc = do_GetService(nsIXPConnect::GetCID()))) {
+        nsAXPCNativeCallContext *cc = nullptr;
+        xpc->GetCurrentNativeCallContext(&cc);
+        if (cc) {
+            nsAXPCNativeCallContext *prev = cc;
+            while (NS_SUCCEEDED(prev->GetPreviousCallContext(&prev)) && prev) {
+                uint16_t lang;
+                if (NS_SUCCEEDED(prev->GetLanguage(&lang)) &&
+                    lang == nsAXPCNativeCallContext::LANG_JS) {
+                    return;
+                }
+            }
+        }
+    }
+
+    if (!report) {
+        fprintf(stderr, "%s\n", message);
+        return;
+    }
+
+    /* Conditionally ignore reported warnings. */
+    if (JSREPORT_IS_WARNING(report->flags) &&
+        !Environment(cx)->ShouldReportWarnings()) {
+        return;
+    }
+
+    if (report->filename)
+        prefix = JS_smprintf("%s:", report->filename);
+    if (report->lineno) {
+        tmp = prefix;
+        prefix = JS_smprintf("%s%u: ", tmp ? tmp : "", report->lineno);
+        JS_free(cx, tmp);
     }
-    return static_cast<XPCShellEnvironment*>(v.get().toPrivate());
+    if (JSREPORT_IS_WARNING(report->flags)) {
+        tmp = prefix;
+        prefix = JS_smprintf("%s%swarning: ",
+                             tmp ? tmp : "",
+                             JSREPORT_IS_STRICT(report->flags) ? "strict " : "");
+        JS_free(cx, tmp);
+    }
+
+    /* embedded newlines -- argh! */
+    while ((ctmp = strchr(message, '\n')) != 0) {
+        ctmp++;
+        if (prefix) fputs(prefix, stderr);
+        fwrite(message, 1, ctmp - message, stderr);
+        message = ctmp;
+    }
+    /* If there were no filename or lineno, the prefix might be empty */
+    if (prefix)
+        fputs(prefix, stderr);
+    fputs(message, stderr);
+
+    if (!report->linebuf) {
+        fputc('\n', stderr);
+        goto out;
+    }
+
+    fprintf(stderr, ":\n%s%s\n%s", prefix, report->linebuf, prefix);
+    n = report->tokenptr - report->linebuf;
+    for (i = j = 0; i < n; i++) {
+        if (report->linebuf[i] == '\t') {
+            for (k = (j + 8) & ~7; j < k; j++) {
+                fputc('.', stderr);
+            }
+            continue;
+        }
+        fputc('.', stderr);
+        j++;
+    }
+    fputs("^\n", stderr);
+ out:
+    if (!JSREPORT_IS_WARNING(report->flags)) {
+        Environment(cx)->SetExitCode(EXITCODE_RUNTIME_ERROR);
+    }
+    JS_free(cx, prefix);
+}
+
+JSContextCallback gOldContextCallback = NULL;
+
+static JSBool
+ContextCallback(JSContext *cx,
+                unsigned contextOp)
+{
+    if (gOldContextCallback && !gOldContextCallback(cx, contextOp))
+        return JS_FALSE;
+
+    if (contextOp == JSCONTEXT_NEW) {
+        JS_SetErrorReporter(cx, ScriptErrorReporter);
+    }
+    return JS_TRUE;
 }
 
 static JSBool
 Print(JSContext *cx,
       unsigned argc,
       JS::Value *vp)
 {
     unsigned i, n;
@@ -172,24 +278,25 @@ Load(JSContext *cx,
         FILE *file = fopen(filename.ptr(), "r");
         if (!file) {
             JS_ReportError(cx, "cannot open file '%s' for reading", filename.ptr());
             return JS_FALSE;
         }
         JS::CompileOptions options(cx);
         options.setUTF8(true)
                .setFileAndLine(filename.ptr(), 1)
-               .setPrincipals(Environment(JS_GetGlobalForScopeChain(cx))->GetPrincipal());
+               .setPrincipals(Environment(cx)->GetPrincipal());
         JS::RootedObject rootedObj(cx, obj);
         JSScript *script = JS::Compile(cx, rootedObj, options, file);
         fclose(file);
         if (!script)
             return JS_FALSE;
 
-        if (!JS_ExecuteScript(cx, obj, script, result.address())) {
+        if (!Environment(cx)->ShouldCompileOnly() &&
+            !JS_ExecuteScript(cx, obj, script, result.address())) {
             return JS_FALSE;
         }
     }
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
@@ -212,17 +319,21 @@ BuildDate(JSContext *cx, unsigned argc, 
     return JS_TRUE;
 }
 
 static JSBool
 Quit(JSContext *cx,
      unsigned argc,
      JS::Value *vp)
 {
-    XPCShellEnvironment* env = Environment(JS_GetGlobalForScopeChain(cx));
+    int exitCode = 0;
+    JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "/ i", &exitCode);
+
+    XPCShellEnvironment* env = Environment(cx);
+    env->SetExitCode(exitCode);
     env->SetIsQuitting();
 
     return JS_FALSE;
 }
 
 static JSBool
 DumpXPC(JSContext *cx,
         unsigned argc,
@@ -387,26 +498,26 @@ typedef enum JSShellErrNum
 #define MSG_DEF(name, number, count, exception, format) \
     name = number,
 #include "jsshell.msg"
 #undef MSG_DEF
     JSShellErr_Limit
 #undef MSGDEF
 } JSShellErrNum;
 
-} /* anonymous namespace */
-
-void
-XPCShellEnvironment::ProcessFile(JSContext *cx,
-                                 JS::Handle<JSObject*> obj,
-                                 const char *filename,
-                                 FILE *file,
-                                 JSBool forceTTY)
+static void
+ProcessFile(JSContext *cx,
+            JS::Handle<JSObject*> obj,
+            const char *filename,
+            FILE *file,
+            JSBool forceTTY)
 {
-    XPCShellEnvironment* env = this;
+    XPCShellEnvironment* env = Environment(cx);
+    nsCxPusher pusher;
+    pusher.Push(env->GetContext());
 
     JSScript *script;
     JS::Rooted<JS::Value> result(cx);
     int lineno, startline;
     JSBool ok, hitEOF;
     char *bufp, buffer[4096];
     JSString *str;
 
@@ -438,17 +549,17 @@ XPCShellEnvironment::ProcessFile(JSConte
         JSAutoRequest ar(cx);
         JSAutoCompartment ac(cx, obj);
 
         JS::CompileOptions options(cx);
         options.setUTF8(true)
                .setFileAndLine(filename, 1)
                .setPrincipals(env->GetPrincipal());
         JSScript* script = JS::Compile(cx, obj, options, file);
-        if (script)
+        if (script && !env->ShouldCompileOnly())
             (void)JS_ExecuteScript(cx, obj, script, result.address());
 
         return;
     }
 
     /* It's an interactive filehandle; drop into read-eval-print loop. */
     lineno = 1;
     hitEOF = JS_FALSE;
@@ -478,37 +589,41 @@ XPCShellEnvironment::ProcessFile(JSConte
         /* Clear any pending exception from previous failed compiles.  */
         JS_ClearPendingException(cx);
         script =
             JS_CompileScriptForPrincipals(cx, obj, env->GetPrincipal(), buffer,
                                           strlen(buffer), "typein", startline);
         if (script) {
             JSErrorReporter older;
 
-            ok = JS_ExecuteScript(cx, obj, script, result.address());
-            if (ok && result != JSVAL_VOID) {
-                /* Suppress error reports from JS_ValueToString(). */
-                older = JS_SetErrorReporter(cx, NULL);
-                str = JS_ValueToString(cx, result);
-                JSAutoByteString bytes;
-                if (str)
-                    bytes.encodeLatin1(cx, str);
-                JS_SetErrorReporter(cx, older);
+            if (!env->ShouldCompileOnly()) {
+                ok = JS_ExecuteScript(cx, obj, script, result.address());
+                if (ok && result != JSVAL_VOID) {
+                    /* Suppress error reports from JS_ValueToString(). */
+                    older = JS_SetErrorReporter(cx, NULL);
+                    str = JS_ValueToString(cx, result);
+                    JSAutoByteString bytes;
+                    if (str)
+                        bytes.encodeLatin1(cx, str);
+                    JS_SetErrorReporter(cx, older);
 
-                if (!!bytes)
-                    fprintf(stdout, "%s\n", bytes.ptr());
-                else
-                    ok = JS_FALSE;
+                    if (!!bytes)
+                        fprintf(stdout, "%s\n", bytes.ptr());
+                    else
+                        ok = JS_FALSE;
+                }
             }
         }
     } while (!hitEOF && !env->IsQuitting());
 
     fprintf(stdout, "\n");
 }
 
+} /* anonymous namespace */
+
 NS_IMETHODIMP_(nsrefcnt)
 XPCShellDirProvider::AddRef()
 {
     return 2;
 }
 
 NS_IMETHODIMP_(nsrefcnt)
 XPCShellDirProvider::Release()
@@ -547,34 +662,51 @@ XPCShellEnvironment::CreateEnvironment()
     if (env && !env->Init()) {
         delete env;
         env = nullptr;
     }
     return env;
 }
 
 XPCShellEnvironment::XPCShellEnvironment()
-:   mQuitting(JS_FALSE)
+:   mCx(NULL),
+    mJSPrincipals(NULL),
+    mExitCode(0),
+    mQuitting(JS_FALSE),
+    mReportWarnings(JS_TRUE),
+    mCompileOnly(JS_FALSE)
 {
 }
 
 XPCShellEnvironment::~XPCShellEnvironment()
 {
+    if (mCx) {
+        JS_BeginRequest(mCx);
 
-    AutoSafeJSContext cx;
-    JSObject* global = GetGlobalObject();
-    if (global) {
-        {
-            JSAutoCompartment ac(cx, global);
-            JS_SetAllNonReservedSlotsToUndefined(cx, global);
+        JSObject* global = GetGlobalObject();
+        if (global) {
+            JS_SetAllNonReservedSlotsToUndefined(mCx, global);
         }
         mGlobalHolder.Release();
 
-        JSRuntime *rt = JS_GetRuntime(cx);
+        JSRuntime *rt = JS_GetRuntime(mCx);
         JS_GC(rt);
+
+        if (mJSPrincipals) {
+            JS_DropPrincipals(rt, mJSPrincipals);
+        }
+
+        JS_EndRequest(mCx);
+        JS_DestroyContext(mCx);
+
+        if (gOldContextCallback) {
+            NS_ASSERTION(rt, "Should never be null!");
+            JS_SetContextCallback(rt, gOldContextCallback);
+            gOldContextCallback = NULL;
+        }
     }
 }
 
 bool
 XPCShellEnvironment::Init()
 {
     nsresult rv;
 
@@ -597,17 +729,28 @@ XPCShellEnvironment::Init()
         return false;
     }
 
     if (!mGlobalHolder.Hold(rt)) {
         NS_ERROR("Can't protect global object!");
         return false;
     }
 
-    AutoSafeJSContext cx;
+    gOldContextCallback = JS_SetContextCallback(rt, ContextCallback);
+
+    JSContext *cx = JS_NewContext(rt, 8192);
+    if (!cx) {
+        NS_ERROR("JS_NewContext failed!");
+
+        JS_SetContextCallback(rt, gOldContextCallback);
+        gOldContextCallback = NULL;
+
+        return false;
+    }
+    mCx = cx;
 
     JS_SetContextPrivate(cx, this);
 
     nsCOMPtr<nsIXPConnect> xpc =
       do_GetService(nsIXPConnect::GetCID());
     if (!xpc) {
         NS_ERROR("failed to get nsXPConnect service!");
         return false;
@@ -615,21 +758,28 @@ XPCShellEnvironment::Init()
 
     nsCOMPtr<nsIPrincipal> principal;
     nsCOMPtr<nsIScriptSecurityManager> securityManager =
         do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
     if (NS_SUCCEEDED(rv) && securityManager) {
         rv = securityManager->GetSystemPrincipal(getter_AddRefs(principal));
         if (NS_FAILED(rv)) {
             fprintf(stderr, "+++ Failed to obtain SystemPrincipal from ScriptSecurityManager service.\n");
+        } else {
+            // fetch the JS principals and stick in a global
+            mJSPrincipals = nsJSPrincipals::get(principal);
+            JS_HoldPrincipals(mJSPrincipals);
         }
     } else {
         fprintf(stderr, "+++ Failed to get ScriptSecurityManager service, running without principals");
     }
 
+    nsCxPusher pusher;
+    pusher.Push(mCx);
+
     nsRefPtr<BackstagePass> backstagePass;
     rv = NS_NewBackstagePass(getter_AddRefs(backstagePass));
     if (NS_FAILED(rv)) {
         NS_ERROR("Failed to create backstage pass!");
         return false;
     }
 
     JS::CompartmentOptions options;
@@ -646,29 +796,28 @@ XPCShellEnvironment::Init()
         return false;
     }
 
     JS::Rooted<JSObject*> globalObj(cx, holder->GetJSObject());
     if (!globalObj) {
         NS_ERROR("Failed to get global JSObject!");
         return false;
     }
-    JSAutoCompartment ac(cx, globalObj);
 
     backstagePass->SetGlobalObject(globalObj);
 
-    if (!JS_DefineProperty(cx, globalObj, "__XPCShellEnvironment",
-                           PRIVATE_TO_JSVAL(this), JS_PropertyStub,
-                           JS_StrictPropertyStub,
-                           JSPROP_READONLY | JSPROP_PERMANENT) ||
-        !JS_DefineFunctions(cx, globalObj, gGlobalFunctions) ||
-        !JS_DefineProfilingFunctions(cx, globalObj))
     {
-        NS_ERROR("JS_DefineFunctions failed!");
-        return false;
+        JSAutoRequest ar(cx);
+        JSAutoCompartment ac(cx, globalObj);
+
+        if (!JS_DefineFunctions(cx, globalObj, gGlobalFunctions) ||
+	    !JS_DefineProfilingFunctions(cx, globalObj)) {
+            NS_ERROR("JS_DefineFunctions failed!");
+            return false;
+        }
     }
 
     mGlobalHolder = globalObj;
 
     FILE* runtimeScriptFile = fopen(kDefaultRuntimeScriptFilename, "r");
     if (runtimeScriptFile) {
         fprintf(stdout, "[loading '%s'...]\n", kDefaultRuntimeScriptFilename);
         ProcessFile(cx, globalObj, kDefaultRuntimeScriptFilename,
@@ -678,41 +827,50 @@ XPCShellEnvironment::Init()
 
     return true;
 }
 
 bool
 XPCShellEnvironment::EvaluateString(const nsString& aString,
                                     nsString* aResult)
 {
-  AutoSafeJSContext cx;
-  JS::Rooted<JSObject*> global(cx, GetGlobalObject());
-  JSAutoCompartment ac(cx, global);
+  XPCShellEnvironment* env = Environment(mCx);
+  nsCxPusher pusher;
+  pusher.Push(env->GetContext());
+
+  JSAutoRequest ar(mCx);
+
+  JS_ClearPendingException(mCx);
+
+  JS::Rooted<JSObject*> global(mCx, GetGlobalObject());
+  JSAutoCompartment ac(mCx, global);
 
   JSScript* script =
-      JS_CompileUCScriptForPrincipals(cx, global, GetPrincipal(),
+      JS_CompileUCScriptForPrincipals(mCx, global, GetPrincipal(),
                                       aString.get(), aString.Length(),
                                       "typein", 0);
   if (!script) {
      return false;
   }
 
-  if (aResult) {
-      aResult->Truncate();
-  }
+  if (!ShouldCompileOnly()) {
+      if (aResult) {
+          aResult->Truncate();
+      }
 
-  JS::Rooted<JS::Value> result(cx);
-  JSBool ok = JS_ExecuteScript(cx, global, script, result.address());
-  if (ok && result != JSVAL_VOID) {
-      JSErrorReporter old = JS_SetErrorReporter(cx, NULL);
-      JSString* str = JS_ValueToString(cx, result);
-      nsDependentJSString depStr;
-      if (str)
-          depStr.init(cx, str);
-      JS_SetErrorReporter(cx, old);
+      JS::Rooted<JS::Value> result(mCx);
+      JSBool ok = JS_ExecuteScript(mCx, global, script, result.address());
+      if (ok && result != JSVAL_VOID) {
+          JSErrorReporter old = JS_SetErrorReporter(mCx, NULL);
+          JSString* str = JS_ValueToString(mCx, result);
+          nsDependentJSString depStr;
+          if (str)
+              depStr.init(mCx, str);
+          JS_SetErrorReporter(mCx, old);
 
-      if (!depStr.IsEmpty() && aResult) {
-          aResult->Assign(depStr);
+          if (!depStr.IsEmpty() && aResult) {
+              aResult->Assign(depStr);
+          }
       }
   }
 
   return true;
 }
--- a/ipc/testshell/XPCShellEnvironment.h
+++ b/ipc/testshell/XPCShellEnvironment.h
@@ -9,58 +9,84 @@
 
 #include <string>
 #include <stdio.h>
 
 #include "nsAutoJSValHolder.h"
 #include "nsCOMPtr.h"
 #include "nsDebug.h"
 #include "nsStringGlue.h"
-#include "nsJSPrincipals.h"
-#include "nsContentUtils.h"
 
 struct JSContext;
 class JSObject;
 struct JSPrincipals;
 
 namespace mozilla {
 namespace ipc {
 
 class XPCShellEnvironment
 {
 public:
     static XPCShellEnvironment* CreateEnvironment();
     ~XPCShellEnvironment();
 
-    void ProcessFile(JSContext *cx, JS::Handle<JSObject*> obj,
-                     const char *filename, FILE *file, JSBool forceTTY);
     bool EvaluateString(const nsString& aString,
                         nsString* aResult = nullptr);
 
     JSPrincipals* GetPrincipal() {
-        return nsJSPrincipals::get(nsContentUtils::GetSystemPrincipal());
+        return mJSPrincipals;
     }
 
     JSObject* GetGlobalObject() {
         return mGlobalHolder.ToJSObject();
     }
 
+    JSContext* GetContext() {
+        return mCx;
+    }
+
+    void SetExitCode(int aExitCode) {
+        mExitCode = aExitCode;
+    }
+    int ExitCode() {
+        return mExitCode;
+    }
+
     void SetIsQuitting() {
         mQuitting = JS_TRUE;
     }
     JSBool IsQuitting() {
         return mQuitting;
     }
 
+    void SetShouldReportWarnings(JSBool aReportWarnings) {
+        mReportWarnings = aReportWarnings;
+    }
+    JSBool ShouldReportWarnings() {
+        return mReportWarnings;
+    }
+
+    void SetShouldCompoleOnly(JSBool aCompileOnly) {
+        mCompileOnly = aCompileOnly;
+    }
+    JSBool ShouldCompileOnly() {
+        return mCompileOnly;
+    }
+
 protected:
     XPCShellEnvironment();
     bool Init();
 
 private:
+    JSContext* mCx;
     nsAutoJSValHolder mGlobalHolder;
+    JSPrincipals* mJSPrincipals;
 
+    int mExitCode;
     JSBool mQuitting;
+    JSBool mReportWarnings;
+    JSBool mCompileOnly;
 };
 
 } /* namespace ipc */
 } /* namespace mozilla */
 
 #endif /* _IPC_TESTSHELL_XPCSHELLENVIRONMENT_H_ */
--- a/js/src/ion/Ion.cpp
+++ b/js/src/ion/Ion.cpp
@@ -187,17 +187,17 @@ IonRuntime::~IonRuntime()
 {
     js_delete(functionWrappers_);
     freeOsrTempData();
 }
 
 bool
 IonRuntime::initialize(JSContext *cx)
 {
-    AutoCompartment ac(cx, cx->runtime()->atomsCompartment);
+    AutoEnterAtomsCompartment ac(cx);
 
     IonContext ictx(cx, NULL);
     AutoFlushCache afc("IonRuntime::initialize");
 
     execAlloc_ = cx->runtime()->getExecAlloc(cx);
     if (!execAlloc_)
         return false;
 
@@ -267,17 +267,17 @@ IonRuntime::initialize(JSContext *cx)
 }
 
 IonCode *
 IonRuntime::debugTrapHandler(JSContext *cx)
 {
     if (!debugTrapHandler_) {
         // IonRuntime code stubs are shared across compartments and have to
         // be allocated in the atoms compartment.
-        AutoCompartment ac(cx, cx->runtime()->atomsCompartment);
+        AutoEnterAtomsCompartment ac(cx);
         debugTrapHandler_ = generateDebugTrapHandler(cx);
     }
     return debugTrapHandler_;
 }
 
 uint8_t *
 IonRuntime::allocateOsrTempData(size_t size)
 {
deleted file mode 100644
--- a/js/src/jit-test/tests/basic/testBug895774.js
+++ /dev/null
@@ -1,14 +0,0 @@
-var g1 = newGlobal();
-var g2 = newGlobal();
-g1.eval("function f1() { debugger; evaluate('debugger', {newContext:true}) }");
-g2.eval("function f2() { f1(); assertEq(Number(this), 42) }");
-g2.f1 = g1.f1;
-
-var dbg = new Debugger(g1,g2);
-dbg.onDebuggerStatement = function(frame) {
-    var target = frame.older;
-    dbg.onDebuggerStatement = function(frame) {
-        assertEq(Number(target.this.unsafeDereference()), 42);
-    }
-}
-g2.f2.call(42);
deleted file mode 100644
--- a/js/src/jit-test/tests/parser/bug-896126.js
+++ /dev/null
@@ -1,11 +0,0 @@
-// |jit-test| error: SyntaxError
-({
-    r: function() {
-        function f() {
-            w[0xe56241c6 >> 3]
-        }
-    },
-    s: function() {
-        "use asm"
-        return (1 for
-
--- a/js/src/jsapi-tests/tests.cpp
+++ b/js/src/jsapi-tests/tests.cpp
@@ -18,18 +18,18 @@ bool JSAPITest::init()
         return false;
     cx = createContext();
     if (!cx)
         return false;
     JS_BeginRequest(cx);
     JS::RootedObject global(cx, createGlobal());
     if (!global)
         return false;
-    JS_EnterCompartment(cx, global);
-    return true;
+    oldCompartment = JS_EnterCompartment(cx, global);
+    return oldCompartment != NULL;
 }
 
 bool JSAPITest::exec(const char *bytes, const char *filename, int lineno)
 {
     JS::RootedValue v(cx);
     JS::HandleObject global = JS::HandleObject::fromMarkedLocation(&this->global);
     return JS_EvaluateScript(cx, global, bytes, strlen(bytes), filename, lineno, v.address()) ||
         fail(bytes, filename, lineno);
--- a/js/src/jsapi-tests/tests.h
+++ b/js/src/jsapi-tests/tests.h
@@ -76,17 +76,16 @@ class JSAPITest
 
     virtual void uninit() {
         if (oldCompartment) {
             JS_LeaveCompartment(cx, oldCompartment);
             oldCompartment = NULL;
         }
         if (cx) {
             JS_RemoveObjectRoot(cx, &global);
-            JS_LeaveCompartment(cx, NULL);
             JS_EndRequest(cx);
             JS_DestroyContext(cx);
             cx = NULL;
         }
         if (rt) {
             destroyRuntime();
             rt = NULL;
         }
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1232,24 +1232,22 @@ JS_PUBLIC_API(JSContext *)
 JS_NewContext(JSRuntime *rt, size_t stackChunkSize)
 {
     return NewContext(rt, stackChunkSize);
 }
 
 JS_PUBLIC_API(void)
 JS_DestroyContext(JSContext *cx)
 {
-    JS_ASSERT(!cx->compartment());
     DestroyContext(cx, DCM_FORCE_GC);
 }
 
 JS_PUBLIC_API(void)
 JS_DestroyContextNoGC(JSContext *cx)
 {
-    JS_ASSERT(!cx->compartment());
     DestroyContext(cx, DCM_NO_GC);
 }
 
 JS_PUBLIC_API(void *)
 JS_GetContextPrivate(JSContext *cx)
 {
     return cx->data;
 }
@@ -2077,18 +2075,16 @@ JS_GetGlobalForCompartmentOrNull(JSConte
     return c->maybeGlobal();
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_GetGlobalForScopeChain(JSContext *cx)
 {
     AssertHeapIsIdleOrIterating(cx);
     CHECK_REQUEST(cx);
-    if (!cx->compartment())
-        return NULL;
     return cx->global();
 }
 
 JS_PUBLIC_API(jsval)
 JS_ComputeThis(JSContext *cx, jsval *vp)
 {
     AssertHeapIsIdle(cx);
     assertSameCompartment(cx, JSValueArray(vp, 2));
@@ -3266,22 +3262,20 @@ JS_NewGlobalObject(JSContext *cx, JSClas
 
     if (options.zoneSpec == JS::SystemZone) {
         rt->systemZone = compartment->zone();
         rt->systemZone->isSystem = true;
     }
 
     AutoHoldZone hold(compartment->zone());
 
-    Rooted<GlobalObject *> global(cx);
-    {
-        AutoCompartment ac(cx, compartment);
-        global = GlobalObject::create(cx, Valueify(clasp));
-    }
-
+    JSCompartment *saved = cx->compartment();
+    cx->setCompartment(compartment);
+    Rooted<GlobalObject *> global(cx, GlobalObject::create(cx, Valueify(clasp)));
+    cx->setCompartment(saved);
     if (!global)
         return NULL;
 
     if (!Debugger::onNewGlobalObject(cx, global))
         return NULL;
 
     return global;
 }
--- a/js/src/jsatom.cpp
+++ b/js/src/jsatom.cpp
@@ -252,17 +252,17 @@ AtomizeAndTakeOwnership(JSContext *cx, j
     SkipRoot skipHash(cx, &p); /* Prevent the hash from being poisoned. */
     if (p) {
         JSAtom *atom = p->asPtr();
         p->setTagged(bool(ib));
         js_free(tbchars);
         return atom;
     }
 
-    AutoCompartment ac(cx, cx->runtime()->atomsCompartment);
+    AutoEnterAtomsCompartment ac(cx);
 
     JSFlatString *flat = js_NewString<CanGC>(cx, tbchars, length);
     if (!flat) {
         js_free(tbchars);
         return NULL;
     }
 
     JSAtom *atom = flat->morphAtomizedStringIntoAtom();
@@ -296,17 +296,17 @@ AtomizeAndCopyChars(JSContext *cx, const
     AtomSet::AddPtr p = atoms.lookupForAdd(AtomHasher::Lookup(tbchars, length));
     SkipRoot skipHash(cx, &p); /* Prevent the hash from being poisoned. */
     if (p) {
         JSAtom *atom = p->asPtr();
         p->setTagged(bool(ib));
         return atom;
     }
 
-    AutoCompartment ac(cx, cx->runtime()->atomsCompartment);
+    AutoEnterAtomsCompartment ac(cx);
 
     JSFlatString *flat = js_NewStringCopyN<allowGC>(cx, tbchars, length);
     if (!flat)
         return NULL;
 
     JSAtom *atom = flat->morphAtomizedStringIntoAtom();
 
     if (!atoms.relookupOrAdd(p, AtomHasher::Lookup(tbchars, length),
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -1261,17 +1261,17 @@ JSRuntime::getDefaultLocale()
  * the caller must subsequently take an error path. If wrapping fails, it will
  * set a new (uncatchable) exception to be used in place of the original.
  */
 void
 JSContext::wrapPendingException()
 {
     RootedValue value(this, getPendingException());
     clearPendingException();
-    if (!IsAtomsCompartment(compartment()) && compartment()->wrap(this, &value))
+    if (compartment()->wrap(this, &value))
         setPendingException(value);
 }
 
 
 void
 JSContext::enterGenerator(JSGenerator *gen)
 {
     JS_ASSERT(!gen->prevGenerator);
@@ -1298,19 +1298,24 @@ bool
 JSContext::saveFrameChain()
 {
     if (!savedFrameChains_.append(SavedFrameChain(compartment(), enterCompartmentDepth_)))
         return false;
 
     if (Activation *act = mainThread().activation())
         act->saveFrameChain();
 
-    setCompartment(NULL);
+    if (defaultCompartmentObject_)
+        setCompartment(defaultCompartmentObject_->compartment());
+    else
+        setCompartment(NULL);
     enterCompartmentDepth_ = 0;
 
+    if (isExceptionPending())
+        wrapPendingException();
     return true;
 }
 
 void
 JSContext::restoreFrameChain()
 {
     SavedFrameChain sfc = savedFrameChains_.popCopy();
     setCompartment(sfc.compartment);
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -462,58 +462,76 @@ JSContext::propertyTree()
 {
     return compartment()->propertyTree;
 }
 
 inline void
 JSContext::setDefaultCompartmentObject(JSObject *obj)
 {
     defaultCompartmentObject_ = obj;
+
+    if (!hasEnteredCompartment()) {
+        /*
+         * If JSAPI callers want to JS_SetGlobalObject while code is running,
+         * they must have entered a compartment (otherwise there will be no
+         * final leaveCompartment call to set the context's compartment back to
+         * defaultCompartmentObject->compartment()).
+         */
+        JS_ASSERT(!currentlyRunning());
+        setCompartment(obj ? obj->compartment() : NULL);
+        if (throwing)
+            wrapPendingException();
+    }
 }
 
 inline void
 JSContext::setDefaultCompartmentObjectIfUnset(JSObject *obj)
 {
     if (!defaultCompartmentObject_)
         setDefaultCompartmentObject(obj);
 }
 
 inline void
 JSContext::enterCompartment(JSCompartment *c)
 {
     enterCompartmentDepth_++;
+    setCompartment(c);
     c->enter();
-    setCompartment(c);
     if (throwing)
         wrapPendingException();
 }
 
 inline void
 JSContext::leaveCompartment(JSCompartment *oldCompartment)
 {
     JS_ASSERT(hasEnteredCompartment());
     enterCompartmentDepth_--;
 
-    // Only call leave() after we've setCompartment()-ed away from the current
-    // compartment.
-    JSCompartment *startingCompartment = compartment();
-    setCompartment(oldCompartment);
-    startingCompartment->leave();
+    compartment()->leave();
 
-    if (throwing && oldCompartment)
+    /*
+     * Before we entered the current compartment, 'compartment' was
+     * 'oldCompartment', so we might want to simply set it back. However, we
+     * currently have this terrible scheme whereby defaultCompartmentObject_ can
+     * be updated while enterCompartmentDepth_ > 0. In this case, oldCompartment
+     * != defaultCompartmentObject_->compartment and we must ignore
+     * oldCompartment.
+     */
+    if (hasEnteredCompartment() || !defaultCompartmentObject_)
+        setCompartment(oldCompartment);
+    else
+        setCompartment(defaultCompartmentObject_->compartment());
+
+    if (throwing)
         wrapPendingException();
 }
 
 inline void
 JSContext::setCompartment(JSCompartment *comp)
 {
-    // Both the current and the new compartment should be properly marked as
-    // entered at this point.
-    JS_ASSERT_IF(compartment_, compartment_->hasBeenEntered());
-    JS_ASSERT_IF(comp, comp->hasBeenEntered());
     compartment_ = comp;
     zone_ = comp ? comp->zone() : NULL;
     allocator_ = zone_ ? &zone_->allocator : NULL;
 }
 
 inline JSScript *
 JSContext::currentScript(jsbytecode **ppc,
                          MaybeAllowCrossCompartment allowCrossCompartment) const
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -186,17 +186,16 @@ JSCompartment::putWrapper(const CrossCom
     JS_ASSERT_IF(wrapped.kind != CrossCompartmentKey::StringWrapper, wrapper.isObject());
     return crossCompartmentWrappers.put(wrapped, wrapper);
 }
 
 bool
 JSCompartment::wrap(JSContext *cx, MutableHandleValue vp, HandleObject existingArg)
 {
     JS_ASSERT(cx->compartment() == this);
-    JS_ASSERT(this != rt->atomsCompartment);
     JS_ASSERT_IF(existingArg, existingArg->compartment() == cx->compartment());
     JS_ASSERT_IF(existingArg, vp.isObject());
     JS_ASSERT_IF(existingArg, IsDeadProxyObject(existingArg));
 
     unsigned flags = 0;
 
     JS_CHECK_CHROME_RECURSION(cx, return false);
 
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -134,17 +134,16 @@ struct JSCompartment
     friend struct JSContext;
     js::ReadBarriered<js::GlobalObject> global_;
 
     unsigned                     enterCompartmentDepth;
 
   public:
     void enter() { enterCompartmentDepth++; }
     void leave() { enterCompartmentDepth--; }
-    bool hasBeenEntered() { return !!enterCompartmentDepth; }
 
     JS::Zone *zone() { return zone_; }
     const JS::Zone *zone() const { return zone_; }
     JS::CompartmentOptions &options() { return options_; }
     const JS::CompartmentOptions &options() const { return options_; }
 
     /*
      * Nb: global_ might be NULL, if (a) it's the atoms compartment, or (b) the
@@ -451,17 +450,16 @@ class AssertCompartmentUnchanged
 
 class AutoCompartment
 {
     JSContext * const cx_;
     JSCompartment * const origin_;
 
   public:
     inline AutoCompartment(JSContext *cx, JSObject *target);
-    inline AutoCompartment(JSContext *cx, JSCompartment *target);
     inline ~AutoCompartment();
 
     JSContext *context() const { return cx_; }
     JSCompartment *origin() const { return origin_; }
 
   private:
     AutoCompartment(const AutoCompartment &) MOZ_DELETE;
     AutoCompartment & operator=(const AutoCompartment &) MOZ_DELETE;
--- a/js/src/jscompartmentinlines.h
+++ b/js/src/jscompartmentinlines.h
@@ -28,21 +28,44 @@ JSCompartment::maybeGlobal() const
 
 js::AutoCompartment::AutoCompartment(JSContext *cx, JSObject *target)
   : cx_(cx),
     origin_(cx->compartment())
 {
     cx_->enterCompartment(target->compartment());
 }
 
-js::AutoCompartment::AutoCompartment(JSContext *cx, JSCompartment *target)
-  : cx_(cx),
-    origin_(cx_->compartment())
-{
-    cx_->enterCompartment(target);
-}
-
 js::AutoCompartment::~AutoCompartment()
 {
     cx_->leaveCompartment(origin_);
 }
 
+namespace js {
+
+/*
+ * Entering the atoms comaprtment is not possible with the AutoCompartment
+ * since the atoms compartment does not have a global.
+ *
+ * Note: since most of the VM assumes that cx->global is non-null, only a
+ * restricted set of (atom creating/destroying) operations may be used from
+ * inside the atoms compartment.
+ */
+class AutoEnterAtomsCompartment
+{
+    JSContext *cx;
+    JSCompartment *oldCompartment;
+  public:
+    AutoEnterAtomsCompartment(JSContext *cx)
+      : cx(cx),
+        oldCompartment(cx->compartment())
+    {
+        cx->setCompartment(cx->runtime()->atomsCompartment);
+    }
+
+    ~AutoEnterAtomsCompartment()
+    {
+        cx->setCompartment(oldCompartment);
+    }
+};
+
+} /* namespace js */
+
 #endif /* jscompartmentinlines_h */
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -1058,17 +1058,17 @@ FormatFrame(JSContext *cx, const NonBuil
         JSAbstractFramePtr frame(Jsvalify(iter.abstractFramePtr()));
         callObj = frame.callObject(cx);
         if (callObj)
             callProps.fetch(callObj);
     }
 
     RootedValue thisVal(cx);
     AutoPropertyDescArray thisProps(cx);
-    if (iter.computeThis(cx)) {
+    if (iter.computeThis()) {
         thisVal = iter.thisv();
         if (showThisProps && !thisVal.isPrimitive())
             thisProps.fetch(&thisVal.toObject());
     }
 
     // print the frame number and function name
     if (funname) {
         JSAutoByteString funbytes;
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -296,16 +296,38 @@ JS_DefineFunctionsWithHelp(JSContext *cx
             if (!DefineHelpProperty(cx, fun, "help", fs->help))
                 return false;
         }
     }
 
     return true;
 }
 
+AutoSwitchCompartment::AutoSwitchCompartment(JSContext *cx, JSCompartment *newCompartment
+                                             MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
+  : cx(cx), oldCompartment(cx->compartment())
+{
+    MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+    cx->setCompartment(newCompartment);
+}
+
+AutoSwitchCompartment::AutoSwitchCompartment(JSContext *cx, HandleObject target
+                                             MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
+  : cx(cx), oldCompartment(cx->compartment())
+{
+    MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+    cx->setCompartment(target->compartment());
+}
+
+AutoSwitchCompartment::~AutoSwitchCompartment()
+{
+    /* The old compartment may have been destroyed, so we can't use cx->setCompartment. */
+    cx->setCompartment(oldCompartment);
+}
+
 JS_FRIEND_API(JS::Zone *)
 js::GetCompartmentZone(JSCompartment *comp)
 {
     return comp->zone();
 }
 
 JS_FRIEND_API(bool)
 js::IsSystemCompartment(JSCompartment *comp)
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -218,16 +218,29 @@ typedef bool
 
  /*
   * Dump the complete object graph of heap-allocated things.
   * fp is the file for the dump output.
   */
 extern JS_FRIEND_API(void)
 DumpHeapComplete(JSRuntime *rt, FILE *fp);
 
+class JS_FRIEND_API(AutoSwitchCompartment) {
+  private:
+    JSContext *cx;
+    JSCompartment *oldCompartment;
+  public:
+    AutoSwitchCompartment(JSContext *cx, JSCompartment *newCompartment
+                          MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
+    AutoSwitchCompartment(JSContext *cx, JS::HandleObject target
+                          MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
+    ~AutoSwitchCompartment();
+    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
 #ifdef OLD_GETTER_SETTER_METHODS
 JS_FRIEND_API(JSBool) obj_defineGetter(JSContext *cx, unsigned argc, js::Value *vp);
 JS_FRIEND_API(JSBool) obj_defineSetter(JSContext *cx, unsigned argc, js::Value *vp);
 #endif
 
 extern JS_FRIEND_API(bool)
 IsSystemCompartment(JSCompartment *comp);
 
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -825,46 +825,43 @@ LoadScriptRelativeToScript(JSContext *cx
 }
 
 class AutoNewContext
 {
   private:
     JSContext *oldcx;
     JSContext *newcx;
     Maybe<JSAutoRequest> newRequest;
-    Maybe<AutoCompartment> newCompartment;
 
     AutoNewContext(const AutoNewContext &) MOZ_DELETE;
 
   public:
     AutoNewContext() : oldcx(NULL), newcx(NULL) {}
 
     bool enter(JSContext *cx) {
         JS_ASSERT(!JS_IsExceptionPending(cx));
         oldcx = cx;
         newcx = NewContext(JS_GetRuntime(cx));
         if (!newcx)
             return false;
         JS_SetOptions(newcx, JS_GetOptions(newcx) | JSOPTION_DONT_REPORT_UNCAUGHT);
         JS_SetGlobalObject(newcx, JS_GetGlobalForScopeChain(cx));
 
         newRequest.construct(newcx);
-        newCompartment.construct(newcx, JS_GetGlobalForScopeChain(cx));
         return true;
     }
 
     JSContext *get() { return newcx; }
 
     ~AutoNewContext() {
         if (newcx) {
             RootedValue exc(oldcx);
             bool throwing = JS_IsExceptionPending(newcx);
             if (throwing)
                 JS_GetPendingException(newcx, exc.address());
-            newCompartment.destroy();
             newRequest.destroy();
             if (throwing)
                 JS_SetPendingException(oldcx, exc);
             DestroyContext(newcx, false);
         }
     }
 };
 
@@ -2612,36 +2609,36 @@ EvalInFrame(JSContext *cx, unsigned argc
     ScriptFrameIter fi(cx);
     for (uint32_t i = 0; i < upCount; ++i, ++fi) {
         ScriptFrameIter next(fi);
         ++next;
         if (next.done())
             break;
     }
 
-    AutoSaveFrameChain sfc(cx);
-    mozilla::Maybe<AutoCompartment> ac;
-    if (saveCurrent) {
-        if (!sfc.save())
-            return false;
-        ac.construct(cx, GetDefaultGlobalForContext(cx));
-    }
+    bool saved = false;
+    if (saveCurrent)
+        saved = JS_SaveFrameChain(cx);
 
     size_t length;
     const jschar *chars = JS_GetStringCharsAndLength(cx, str, &length);
     if (!chars)
         return false;
 
     JSAbstractFramePtr frame(Jsvalify(fi.abstractFramePtr()));
     RootedScript fpscript(cx, frame.script());
     bool ok = !!frame.evaluateUCInStackFrame(cx, chars, length,
                                              fpscript->filename(),
                                              JS_PCToLineNumber(cx, fpscript,
                                                                fi.pc()),
                                              MutableHandleValue::fromMarkedLocation(vp));
+
+    if (saved)
+        JS_RestoreFrameChain(cx);
+
     return ok;
 }
 
 static JSBool
 ShapeOf(JSContext *cx, unsigned argc, JS::Value *vp)
 {
     JS::Value v;
     if (argc < 1 || !((v = JS_ARGV(cx, vp)[0]).isObject())) {
@@ -5128,17 +5125,16 @@ Shell(JSContext *cx, OptionParser *op, c
     if (op->getBoolOption("fuzzing-safe"))
         fuzzingSafe = true;
 
     RootedObject glob(cx);
     glob = NewGlobalObject(cx, NULL);
     if (!glob)
         return 1;
 
-    JSAutoCompartment ac(cx, glob);
     JS_SetGlobalObject(cx, glob);
 
     JSObject *envobj = JS_DefineObject(cx, glob, "environment", &env_class, NULL, 0);
     if (!envobj)
         return 1;
     JS_SetPrivate(envobj, envp);
 
     int result = ProcessArgs(cx, glob, op);
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -3811,17 +3811,17 @@ DebuggerFrame_getConstructing(JSContext 
 
 static JSBool
 DebuggerFrame_getThis(JSContext *cx, unsigned argc, Value *vp)
 {
     THIS_FRAME(cx, argc, vp, "get this", args, thisobj, iter);
     RootedValue thisv(cx);
     {
         AutoCompartment ac(cx, iter.scopeChain());
-        if (!iter.computeThis(cx))
+        if (!iter.computeThis())
             return false;
         thisv = iter.thisv();
     }
     if (!Debugger::fromChildJSObject(thisobj)->wrapDebuggeeValue(cx, &thisv))
         return false;
     args.rval().set(thisv);
     return true;
 }
@@ -4184,17 +4184,17 @@ DebuggerGenericEval(JSContext *cx, const
         ac.construct(cx, iter->scopeChain());
     else
         ac.construct(cx, scope);
 
     RootedValue thisv(cx);
     Rooted<Env *> env(cx);
     if (iter) {
         /* ExecuteInEnv requires 'fp' to have a computed 'this" value. */
-        if (!iter->computeThis(cx))
+        if (!iter->computeThis())
             return false;
         thisv = iter->thisv();
         env = GetDebugScopeForFrame(cx, iter->abstractFramePtr());
         if (!env)
             return false;
     } else {
         thisv = ObjectValue(*scope);
         env = scope;
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -645,18 +645,18 @@ const JSFunctionSpec intrinsic_functions
 
 bool
 JSRuntime::initSelfHosting(JSContext *cx)
 {
     JS_ASSERT(!selfHostingGlobal_);
     RootedObject savedGlobal(cx, js::GetDefaultGlobalForContext(cx));
     if (!(selfHostingGlobal_ = JS_NewGlobalObject(cx, &self_hosting_global_class, NULL)))
         return false;
-    JSAutoCompartment ac(cx, selfHostingGlobal_);
     JS_SetGlobalObject(cx, selfHostingGlobal_);
+    JSAutoCompartment ac(cx, cx->global());
     Rooted<GlobalObject*> shg(cx, &selfHostingGlobal_->as<GlobalObject>());
     /*
      * During initialization of standard classes for the self-hosting global,
      * all self-hosted functions are ignored. Thus, we don't create cyclic
      * dependencies in the order of initialization.
      */
     if (!GlobalObject::initStandardClasses(cx, shg))
         return false;
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -1123,22 +1123,22 @@ ScriptFrameIter::argsObj() const
       case SCRIPTED:
         return interpFrame()->argsObj();
     }
     JS_NOT_REACHED("Unexpected state");
     return interpFrame()->argsObj();
 }
 
 bool
-ScriptFrameIter::computeThis(JSContext *cx) const
+ScriptFrameIter::computeThis() const
 {
     JS_ASSERT(!done());
     if (!isIon()) {
-        assertSameCompartment(cx, scopeChain());
-        return ComputeThis(cx, abstractFramePtr());
+        JS_ASSERT(data_.cx_);
+        return ComputeThis(data_.cx_, abstractFramePtr());
     }
     return true;
 }
 
 Value
 ScriptFrameIter::thisv() const
 {
     switch (data_.state_) {
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -1512,17 +1512,17 @@ class ScriptFrameIter
 
     JSObject   *scopeChain() const;
     CallObject &callObj() const;
 
     bool        hasArgsObj() const;
     ArgumentsObject &argsObj() const;
 
     // Ensure that thisv is correct, see ComputeThis.
-    bool        computeThis(JSContext *cx) const;
+    bool        computeThis() const;
     Value       thisv() const;
 
     Value       returnValue() const;
     void        setReturnValue(const Value &v);
 
     JSFunction *maybeCallee() const {
         return isFunctionFrame() ? callee() : NULL;
     }
--- a/js/src/vm/String.cpp
+++ b/js/src/vm/String.cpp
@@ -495,17 +495,17 @@ JSFlatString::isIndexSlow(uint32_t *inde
 
 #define R TO_SMALL_CHAR
 const StaticStrings::SmallChar StaticStrings::toSmallChar[] = { R7(0) };
 #undef R
 
 bool
 StaticStrings::init(JSContext *cx)
 {
-    AutoCompartment ac(cx, cx->runtime()->atomsCompartment);
+    AutoEnterAtomsCompartment ac(cx);
 
     for (uint32_t i = 0; i < UNIT_STATIC_LIMIT; i++) {
         jschar buffer[] = { jschar(i), '\0' };
         JSFlatString *s = js_NewStringCopyN<CanGC>(cx, buffer, 1);
         if (!s)
             return false;
         unitStaticTable[i] = s->morphAtomizedStringIntoAtom();
     }
--- a/js/xpconnect/idl/nsIScriptError.idl
+++ b/js/xpconnect/idl/nsIScriptError.idl
@@ -40,17 +40,17 @@ interface nsIScriptError : nsIConsoleMes
     readonly attribute uint32_t lineNumber;
     readonly attribute uint32_t columnNumber;
     readonly attribute uint32_t flags;
 
     /**
      * Categories I know about -
      * XUL javascript
      * content javascript (both of these from nsDocShell, currently)
-     * system javascript (errors in JS components and other system JS)
+     * component javascript (errors in JS components)
      */
     readonly attribute string category;
 
     /* Get the window id this was initialized with.  Zero will be
        returned if init() was used instead of initWithWindowID(). */
     readonly attribute unsigned long long outerWindowID;
 
     /* Get the inner window id this was initialized with.  Zero will be
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -118,16 +118,71 @@ static PRLogModuleInfo *gJSCLLog;
 #define ERROR_SCOPE_OBJ "%s - Second argument must be an object."
 #define ERROR_NOT_PRESENT "%s - EXPORTED_SYMBOLS is not present."
 #define ERROR_NOT_AN_ARRAY "%s - EXPORTED_SYMBOLS is not an array."
 #define ERROR_GETTING_ARRAY_LENGTH "%s - Error getting array length of EXPORTED_SYMBOLS."
 #define ERROR_ARRAY_ELEMENT "%s - EXPORTED_SYMBOLS[%d] is not a string."
 #define ERROR_GETTING_SYMBOL "%s - Could not get symbol '%s'."
 #define ERROR_SETTING_SYMBOL "%s - Could not set symbol '%s' on target object."
 
+void
+mozJSLoaderErrorReporter(JSContext *cx, const char *message, JSErrorReport *rep)
+{
+    nsresult rv;
+
+    /* Use the console service to register the error. */
+    nsCOMPtr<nsIConsoleService> consoleService =
+        do_GetService(NS_CONSOLESERVICE_CONTRACTID);
+
+    /*
+     * Make an nsIScriptError, populate it with information from this
+     * error, then log it with the console service.  The UI can then
+     * poll the service to update the Error console.
+     */
+    nsCOMPtr<nsIScriptError> errorObject =
+        do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
+
+    if (consoleService && errorObject) {
+        uint32_t column = rep->uctokenptr - rep->uclinebuf;
+
+        const PRUnichar* ucmessage =
+            static_cast<const PRUnichar*>(rep->ucmessage);
+        const PRUnichar* uclinebuf =
+            static_cast<const PRUnichar*>(rep->uclinebuf);
+
+        rv = errorObject->Init(
+              ucmessage ? nsDependentString(ucmessage) : EmptyString(),
+              NS_ConvertASCIItoUTF16(rep->filename),
+              uclinebuf ? nsDependentString(uclinebuf) : EmptyString(),
+              rep->lineno, column, rep->flags,
+              "component javascript");
+        if (NS_SUCCEEDED(rv)) {
+            rv = consoleService->LogMessage(errorObject);
+            if (NS_SUCCEEDED(rv)) {
+                // We're done!  Skip return to fall thru to stderr
+                // printout, for the benefit of those invoking the
+                // browser with -console
+                // return;
+            }
+        }
+    }
+
+    /*
+     * If any of the above fails for some reason, fall back to
+     * printing to stderr.
+     */
+#ifdef DEBUG
+    fprintf(stderr, "JS Component Loader: %s %s:%d\n"
+            "                     %s\n",
+            JSREPORT_IS_WARNING(rep->flags) ? "WARNING" : "ERROR",
+            rep->filename, rep->lineno,
+            message ? message : "<no message>");
+#endif
+}
+
 static JSBool
 Dump(JSContext *cx, unsigned argc, jsval *vp)
 {
     JSString *str;
     if (!argc)
         return true;
 
     str = JS_ValueToString(cx, JS_ARGV(cx, vp)[0]);
@@ -510,17 +565,17 @@ mozJSComponentLoader::LoadModule(FileLoc
         return NULL;
     }
 
     JSObject* file_jsobj = file_holder->GetJSObject();
     if (!file_jsobj) {
         return NULL;
     }
 
-    JSCLAutoErrorReporterSetter aers(cx, xpc::SystemErrorReporter);
+    JSCLAutoErrorReporterSetter aers(cx, mozJSLoaderErrorReporter);
 
     RootedValue NSGetFactory_val(cx);
     if (!JS_GetProperty(cx, entry->obj, "NSGetFactory", NSGetFactory_val.address()) ||
         JSVAL_IS_VOID(NSGetFactory_val)) {
         return NULL;
     }
 
     if (JS_TypeOfValue(cx, NSGetFactory_val) != JSTYPE_FUNCTION) {
@@ -761,17 +816,17 @@ mozJSComponentLoader::ObjectForLocation(
                                         char **aLocation,
                                         bool aPropagateExceptions,
                                         JS::MutableHandleValue aException)
 {
     JSCLContextHelper cx(mContext);
 
     JS_AbortIfWrongThread(JS_GetRuntime(cx));
 
-    JSCLAutoErrorReporterSetter aers(cx, xpc::SystemErrorReporter);
+    JSCLAutoErrorReporterSetter aers(cx, mozJSLoaderErrorReporter);
 
     bool realFile = false;
     RootedObject obj(cx, PrepareObjectForLocation(cx, aComponentFile, aURI,
                                                   mReuseLoaderGlobal, &realFile));
     NS_ENSURE_TRUE(obj, NS_ERROR_FAILURE);
 
     JSAutoCompartment ac(cx, obj);
 
@@ -1070,17 +1125,16 @@ mozJSComponentLoader::UnloadModules()
     mInitialized = false;
 
     if (mLoaderGlobal) {
         MOZ_ASSERT(mReuseLoaderGlobal, "How did this happen?");
 
         JSAutoRequest ar(mContext);
         RootedObject global(mContext, mLoaderGlobal->GetJSObject());
         if (global) {
-            JSAutoCompartment ac(mContext, global);
             JS_SetAllNonReservedSlotsToUndefined(mContext, global);
         } else {
             NS_WARNING("Going to leak!");
         }
 
         mLoaderGlobal = nullptr;
     }
 
--- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -45,16 +45,20 @@ using namespace JS;
 #define LOAD_ERROR_NOCONTENT "ContentLength not available (not a local URL?)"
 #define LOAD_ERROR_BADCHARSET "Error converting to specified charset"
 #define LOAD_ERROR_BADREAD   "File Read Error."
 #define LOAD_ERROR_READUNDERFLOW "File Read Error (underflow.)"
 #define LOAD_ERROR_NOPRINCIPALS "Failed to get principals."
 #define LOAD_ERROR_NOSPEC "Failed to get URI spec.  This is bad."
 #define LOAD_ERROR_CONTENTTOOBIG "ContentLength is too large"
 
+// We just use the same reporter as the component loader
+extern void
+mozJSLoaderErrorReporter(JSContext *cx, const char *message, JSErrorReport *rep);
+
 mozJSSubScriptLoader::mozJSSubScriptLoader() : mSystemPrincipal(nullptr)
 {
     // Force construction of the JS component loader.  We may need it later.
     nsCOMPtr<xpcIJSModuleLoader> componentLoader =
         do_GetService(MOZJSCOMPONENTLOADER_CONTRACTID);
 }
 
 mozJSSubScriptLoader::~mozJSSubScriptLoader()
@@ -114,17 +118,17 @@ mozJSSubScriptLoader::ReadScript(nsIURI 
 
     nsCString buf;
     rv = NS_ReadInputStreamToString(instream, buf, len);
     if (NS_FAILED(rv))
         return rv;
 
     /* set our own error reporter so we can report any bad things as catchable
      * exceptions, including the source/line number */
-    er = JS_SetErrorReporter(cx, xpc::SystemErrorReporter);
+    er = JS_SetErrorReporter(cx, mozJSLoaderErrorReporter);
 
     JS::CompileOptions options(cx);
     options.setPrincipals(nsJSPrincipals::get(principal))
            .setFileAndLine(uriStr, 1);
     if (!charset.IsVoid()) {
         nsString script;
         rv = nsScriptLoader::ConvertToUTF16(nullptr, reinterpret_cast<const uint8_t*>(buf.get()), len,
                                             charset, nullptr, script);
--- a/js/xpconnect/shell/xpcshell.cpp
+++ b/js/xpconnect/shell/xpcshell.cpp
@@ -134,17 +134,16 @@ static const char kXPConnectServiceContr
 #define EXITCODE_RUNTIME_ERROR 3
 #define EXITCODE_FILE_NOT_FOUND 4
 
 FILE *gOutFile = NULL;
 FILE *gErrFile = NULL;
 FILE *gInFile = NULL;
 
 int gExitCode = 0;
-bool gIgnoreReportedErrors = false;
 JSBool gQuitting = false;
 static JSBool reportWarnings = true;
 static JSBool compileOnly = false;
 
 JSPrincipals *gJSPrincipals = nullptr;
 nsAutoString *gWorkingDirectory = nullptr;
 
 static JSBool
@@ -262,16 +261,107 @@ GetLine(JSContext *cx, char *bufp, FILE 
         fflush(gOutFile);
         if ((!fgets(line, sizeof line, file) && errno != EINTR) || feof(file))
             return false;
         strcpy(bufp, line);
     }
     return true;
 }
 
+static void
+my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
+{
+    int i, j, k, n;
+    char *prefix = NULL, *tmp;
+    const char *ctmp;
+    nsCOMPtr<nsIXPConnect> xpc;
+
+    // Don't report an exception from inner JS frames as the callers may intend
+    // to handle it.
+    if (JS_DescribeScriptedCaller(cx, nullptr, nullptr)) {
+        return;
+    }
+
+    // In some cases cx->fp is null here so use XPConnect to tell us about inner
+    // frames.
+    if ((xpc = do_GetService(nsIXPConnect::GetCID()))) {
+        nsAXPCNativeCallContext *cc = nullptr;
+        xpc->GetCurrentNativeCallContext(&cc);
+        if (cc) {
+            nsAXPCNativeCallContext *prev = cc;
+            while (NS_SUCCEEDED(prev->GetPreviousCallContext(&prev)) && prev) {
+                uint16_t lang;
+                if (NS_SUCCEEDED(prev->GetLanguage(&lang)) &&
+                    lang == nsAXPCNativeCallContext::LANG_JS) {
+                    return;
+                }
+            }
+        }
+    }
+
+    if (!report) {
+        fprintf(gErrFile, "%s\n", message);
+        return;
+    }
+
+    /* Conditionally ignore reported warnings. */
+    if (JSREPORT_IS_WARNING(report->flags) && !reportWarnings)
+        return;
+
+    if (report->filename)
+        prefix = JS_smprintf("%s:", report->filename);
+    if (report->lineno) {
+        tmp = prefix;
+        prefix = JS_smprintf("%s%u: ", tmp ? tmp : "", report->lineno);
+        JS_free(cx, tmp);
+    }
+    if (JSREPORT_IS_WARNING(report->flags)) {
+        tmp = prefix;
+        prefix = JS_smprintf("%s%swarning: ",
+                             tmp ? tmp : "",
+                             JSREPORT_IS_STRICT(report->flags) ? "strict " : "");
+        JS_free(cx, tmp);
+    }
+
+    /* embedded newlines -- argh! */
+    while ((ctmp = strchr(message, '\n')) != 0) {
+        ctmp++;
+        if (prefix) fputs(prefix, gErrFile);
+        fwrite(message, 1, ctmp - message, gErrFile);
+        message = ctmp;
+    }
+    /* If there were no filename or lineno, the prefix might be empty */
+    if (prefix)
+        fputs(prefix, gErrFile);
+    fputs(message, gErrFile);
+
+    if (!report->linebuf) {
+        fputc('\n', gErrFile);
+        goto out;
+    }
+
+    fprintf(gErrFile, ":\n%s%s\n%s", prefix, report->linebuf, prefix);
+    n = report->tokenptr - report->linebuf;
+    for (i = j = 0; i < n; i++) {
+        if (report->linebuf[i] == '\t') {
+            for (k = (j + 8) & ~7; j < k; j++) {
+                fputc('.', gErrFile);
+            }
+            continue;
+        }
+        fputc('.', gErrFile);
+        j++;
+    }
+    fputs("^\n", gErrFile);
+ out:
+    if (!JSREPORT_IS_WARNING(report->flags))
+        gExitCode = EXITCODE_RUNTIME_ERROR;
+    JS_free(cx, prefix);
+}
+
 static JSBool
 ReadLine(JSContext *cx, unsigned argc, jsval *vp)
 {
     // While 4096 might be quite arbitrary, this is something to be fixed in
     // bug 105707. It is also the same limit as in ProcessFile.
     char buf[4096];
     JSString *str;
 
@@ -423,31 +513,16 @@ Quit(JSContext *cx, unsigned argc, jsval
     gExitCode = 0;
     JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp),"/ i", &gExitCode);
 
     gQuitting = true;
 //    exit(0);
     return false;
 }
 
-// Provide script a way to disable the xpcshell error reporter, preventing
-// reported errors from being logged to the console and also from affecting the
-// exit code returned by the xpcshell binary.
-static JSBool
-IgnoreReportedErrors(JSContext *cx, unsigned argc, jsval *vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    if (argc != 1 || !args[0].isBoolean()) {
-        JS_ReportError(cx, "Bad arguments");
-        return false;
-    }
-    gIgnoreReportedErrors = args[0].toBoolean();
-    return true;
-}
-
 static JSBool
 DumpXPC(JSContext *cx, unsigned argc, jsval *vp)
 {
     int32_t depth = 2;
 
     if (argc > 0) {
         if (!JS_ValueToInt32(cx, JS_ARGV(cx, vp)[0], &depth))
             return false;
@@ -825,17 +900,16 @@ File(JSContext *cx, unsigned argc, jsval
   return true;
 }
 
 static const JSFunctionSpec glob_functions[] = {
     JS_FS("print",           Print,          0,0),
     JS_FS("readline",        ReadLine,       1,0),
     JS_FS("load",            Load,           1,0),
     JS_FS("quit",            Quit,           0,0),
-    JS_FS("ignoreReportedErrors", IgnoreReportedErrors, 1,0),
     JS_FS("version",         Version,        1,0),
     JS_FS("build",           BuildDate,      0,0),
     JS_FS("dumpXPC",         DumpXPC,        1,0),
     JS_FS("dump",            Dump,           1,0),
     JS_FS("gc",              GC,             0,0),
 #ifdef JS_GC_ZEAL
     JS_FS("gczeal",          GCZeal,         1,0),
 #endif
@@ -1313,17 +1387,16 @@ ProcessArgs(JSContext *cx, JS::Handle<JS
         }
         default:
             return usage();
         }
     }
 
     if (filename || isInteractive)
         Process(cx, obj, filename, forceTTY);
-
     return gExitCode;
 }
 
 /***************************************************************************/
 
 // #define TEST_InitClassesWithNewWrappedGlobal
 
 #ifdef TEST_InitClassesWithNewWrappedGlobal
@@ -1398,37 +1471,24 @@ nsXPCFunctionThisTranslator::TranslateTh
     return NS_OK;
 }
 
 #endif
 
 // ContextCallback calls are chained
 static JSContextCallback gOldJSContextCallback;
 
-void
-XPCShellErrorReporter(JSContext *cx, const char *message, JSErrorReport *rep)
-{
-    if (gIgnoreReportedErrors)
-        return;
-
-    if (!JSREPORT_IS_WARNING(rep->flags))
-        gExitCode = EXITCODE_RUNTIME_ERROR;
-
-    // Delegate to the system error reporter for heavy lifting.
-    xpc::SystemErrorReporterExternal(cx, message, rep);
-}
-
 static JSBool
 ContextCallback(JSContext *cx, unsigned contextOp)
 {
     if (gOldJSContextCallback && !gOldJSContextCallback(cx, contextOp))
         return false;
 
     if (contextOp == JSCONTEXT_NEW) {
-        JS_SetErrorReporter(cx, XPCShellErrorReporter);
+        JS_SetErrorReporter(cx, my_ErrorReporter);
     }
     return true;
 }
 
 static bool
 GetCurrentWorkingDirectory(nsAString& workingDirectory)
 {
 #if !defined(XP_WIN) && !defined(XP_UNIX)
--- a/js/xpconnect/src/XPCJSContextStack.cpp
+++ b/js/xpconnect/src/XPCJSContextStack.cpp
@@ -124,16 +124,21 @@ SafeFinalize(JSFreeOp *fop, JSObject* ob
 static JSClass global_class = {
     "global_for_XPCJSContextStack_SafeJSContext",
     XPCONNECT_GLOBAL_FLAGS,
     JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
     JS_EnumerateStub, SafeGlobalResolve, JS_ConvertStub, SafeFinalize,
     NULL, NULL, NULL, NULL, TraceXPCGlobal
 };
 
+// We just use the same reporter as the component loader
+// XXX #include angels cry.
+extern void
+mozJSLoaderErrorReporter(JSContext *cx, const char *message, JSErrorReport *rep);
+
 JSContext*
 XPCJSContextStack::GetSafeJSContext()
 {
     if (mSafeJSContext)
         return mSafeJSContext;
 
     // Start by getting the principal holder and principal for this
     // context.  If we can't manage that, don't bother with the rest.
@@ -148,17 +153,17 @@ XPCJSContextStack::GetSafeJSContext()
         MOZ_CRASH();
 
     mSafeJSContext = JS_NewContext(rt, 8192);
     if (!mSafeJSContext)
         MOZ_CRASH();
     JSAutoRequest req(mSafeJSContext);
 
     JS::RootedObject glob(mSafeJSContext);
-    JS_SetErrorReporter(mSafeJSContext, xpc::SystemErrorReporter);
+    JS_SetErrorReporter(mSafeJSContext, mozJSLoaderErrorReporter);
 
     JS::CompartmentOptions options;
     options.setZone(JS::SystemZone);
     glob = xpc::CreateGlobalObject(mSafeJSContext, &global_class, principal, options);
     if (!glob)
         MOZ_CRASH();
 
     // Make sure the context is associated with a proper compartment
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -2831,21 +2831,20 @@ XPCJSRuntime::OnJSContextNew(JSContext *
     // rest of the cx setup.
     JSAutoRequest ar(cx);
 
     // if it is our first context then we need to generate our string ids
     if (JSID_IS_VOID(mStrIDs[0])) {
         RootedString str(cx);
         for (unsigned i = 0; i < IDX_TOTAL_COUNT; i++) {
             str = JS_InternString(cx, mStrings[i]);
-            if (!str) {
+            if (!str || !JS_ValueToId(cx, STRING_TO_JSVAL(str), &mStrIDs[i])) {
                 mStrIDs[0] = JSID_VOID;
                 return false;
             }
-            mStrIDs[i] = INTERNED_STRING_TO_JSID(cx, str);
             mStrJSVals[i] = STRING_TO_JSVAL(str);
         }
 
         if (!mozilla::dom::DefineStaticJSVals(cx) ||
             !InternStaticDictionaryJSVals(cx)) {
             return false;
         }
     }
--- a/js/xpconnect/src/XPCQuickStubs.cpp
+++ b/js/xpconnect/src/XPCQuickStubs.cpp
@@ -213,23 +213,23 @@ ThrowCallFailed(JSContext *cx, nsresult 
     /* Only one of memberId or memberName should be given. */
     MOZ_ASSERT(JSID_IS_VOID(memberId) != !memberName);
 
     // From XPCThrower::ThrowBadResult.
     char* sz;
     const char* format;
     const char* name;
 
-    // If the cx already has a pending exception, just throw that.
-    //
-    // We used to check here to make sure the exception matched rv (whatever
-    // that means). But this meant that we'd be calling into JSAPI below with
-    // a pending exception, which isn't really kosher. The first exception thrown
-    // should generally take precedence anyway.
-    if (JS_IsExceptionPending(cx))
+    /*
+     *  If there is a pending exception when the native call returns and
+     *  it has the same error result as returned by the native call, then
+     *  the native call may be passing through an error from a previous JS
+     *  call. So we'll just throw that exception into our JS.
+     */
+    if (XPCThrower::CheckForPendingException(rv, cx))
         return false;
 
     // else...
 
     if (!nsXPCException::NameAndFormatForNSResult(NS_ERROR_XPC_NATIVE_RETURNED_FAILURE, nullptr, &format) ||
         !format) {
         format = "";
     }
--- a/js/xpconnect/src/nsCxPusher.cpp
+++ b/js/xpconnect/src/nsCxPusher.cpp
@@ -120,39 +120,34 @@ AutoCxPusher::AutoCxPusher(JSContext* cx
     // is running at the moment in the context.
     mScriptIsRunning = true;
   }
 
   if (!stack->Push(cx)) {
     MOZ_CRASH();
   }
 
+  // Enter a request for the duration that the cx is on the stack if non-null.
+  // NB: We call UnmarkGrayContext so that this can obsolete the need for the
+  // old XPCAutoRequest as well.
+  if (cx) {
+    mAutoRequest.construct(cx);
+    xpc_UnmarkGrayContext(cx);
+  }
+
 #ifdef DEBUG
   mPushedContext = cx;
   mCompartmentDepthOnEntry = cx ? js::GetEnterCompartmentDepth(cx) : 0;
 #endif
-
-  // Enter a request and a compartment for the duration that the cx is on the
-  // stack if non-null.
-  //
-  // NB: We call UnmarkGrayContext so that this can obsolete the need for the
-  // old XPCAutoRequest as well.
-  if (cx) {
-    mAutoRequest.construct(cx);
-    if (js::GetDefaultGlobalForContext(cx))
-      mAutoCompartment.construct(cx, js::GetDefaultGlobalForContext(cx));
-    xpc_UnmarkGrayContext(cx);
-  }
 }
 
 NS_EXPORT
 AutoCxPusher::~AutoCxPusher()
 {
-  // Leave the compartment and request before popping.
-  mAutoCompartment.destroyIfConstructed();
+  // Leave the request before popping.
   mAutoRequest.destroyIfConstructed();
 
   // When we push a context, we may save the frame chain and pretend like we
   // haven't entered any compartment. This gets restored on Pop(), but we can
   // run into trouble if a Push/Pop are interleaved with a
   // JSAutoEnterCompartment. Make sure the compartment depth right before we
   // pop is the same as it was right after we pushed.
   MOZ_ASSERT_IF(mPushedContext, mCompartmentDepthOnEntry ==
--- a/js/xpconnect/src/nsCxPusher.h
+++ b/js/xpconnect/src/nsCxPusher.h
@@ -28,17 +28,16 @@ public:
   AutoCxPusher(JSContext *aCx, bool aAllowNull = false);
   // XPCShell uses an nsCxPusher, which contains an AutoCxPusher.
   NS_EXPORT ~AutoCxPusher();
 
   nsIScriptContext* GetScriptContext() { return mScx; }
 
 private:
   mozilla::Maybe<JSAutoRequest> mAutoRequest;
-  mozilla::Maybe<JSAutoCompartment> mAutoCompartment;
   nsCOMPtr<nsIScriptContext> mScx;
   bool mScriptIsRunning;
 #ifdef DEBUG
   JSContext* mPushedContext;
   unsigned mCompartmentDepthOnEntry;
 #endif
 };
 
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -216,80 +216,18 @@ JSBool
 nsXPConnect::IsISupportsDescendant(nsIInterfaceInfo* info)
 {
     bool found = false;
     if (info)
         info->HasAncestor(&NS_GET_IID(nsISupports), &found);
     return found;
 }
 
-void
-xpc::SystemErrorReporter(JSContext *cx, const char *message, JSErrorReport *rep)
-{
-    // It would be nice to assert !JS_DescribeScriptedCaller here, to be sure
-    // that there isn't any script running that could catch the exception. But
-    // the JS engine invokes the error reporter directly if someone reports an
-    // ErrorReport that it doesn't know how to turn into an exception. Arguably
-    // it should just learn how to throw everything. But either way, if the
-    // exception is ending here, it's not going to get propagated to a caller,
-    // so it's up to us to make it known.
-
-    nsresult rv;
-
-    /* Use the console service to register the error. */
-    nsCOMPtr<nsIConsoleService> consoleService =
-        do_GetService(NS_CONSOLESERVICE_CONTRACTID);
-
-    /*
-     * Make an nsIScriptError, populate it with information from this
-     * error, then log it with the console service.
-     */
-    nsCOMPtr<nsIScriptError> errorObject =
-        do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
-
-    if (consoleService && errorObject) {
-        uint32_t column = rep->uctokenptr - rep->uclinebuf;
-
-        const PRUnichar* ucmessage =
-            static_cast<const PRUnichar*>(rep->ucmessage);
-        const PRUnichar* uclinebuf =
-            static_cast<const PRUnichar*>(rep->uclinebuf);
-
-        rv = errorObject->Init(
-              ucmessage ? nsDependentString(ucmessage) : EmptyString(),
-              NS_ConvertASCIItoUTF16(rep->filename),
-              uclinebuf ? nsDependentString(uclinebuf) : EmptyString(),
-              rep->lineno, column, rep->flags,
-              "system javascript");
-        if (NS_SUCCEEDED(rv))
-            consoleService->LogMessage(errorObject);
-    }
-
-    /* Log to stderr in debug builds. */
-#ifdef DEBUG
-    fprintf(stderr, "System JS : %s %s:%d\n"
-            "                     %s\n",
-            JSREPORT_IS_WARNING(rep->flags) ? "WARNING" : "ERROR",
-            rep->filename, rep->lineno,
-            message ? message : "<no message>");
-#endif
-
-}
-
-NS_EXPORT_(void)
-xpc::SystemErrorReporterExternal(JSContext *cx, const char *message,
-                                 JSErrorReport *rep)
-{
-    return SystemErrorReporter(cx, message, rep);
-}
-
-
 /***************************************************************************/
 
-
 nsresult
 nsXPConnect::GetInfoForIID(const nsIID * aIID, nsIInterfaceInfo** info)
 {
   return XPTInterfaceInfoManager::GetSingleton()->GetInfoForIID(aIID, info);
 }
 
 nsresult
 nsXPConnect::GetInfoForName(const char * name, nsIInterfaceInfo** info)
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -417,30 +417,16 @@ JSObject *
 GetJunkScope();
 
 /**
  * Returns the native global of the junk scope. See comment of GetJunkScope
  * about the conditions of using it.
  */
 nsIGlobalObject *
 GetJunkScopeGlobal();
-
-// Error reporter used when there is no associated DOM window on to which to
-// report errors and warnings.
-void
-SystemErrorReporter(JSContext *cx, const char *message, JSErrorReport *rep);
-
-// We have a separate version that's exported with external linkage for use by
-// xpcshell, since external linkage on windows changes the signature to make it
-// incompatible with the JSErrorReporter type, causing JS_SetErrorReporter calls
-// to fail to compile.
-NS_EXPORT_(void)
-SystemErrorReporterExternal(JSContext *cx, const char *message,
-                            JSErrorReport *rep);
-
 } // namespace xpc
 
 namespace mozilla {
 namespace dom {
 
 extern int HandlerFamily;
 inline void* ProxyFamily() { return &HandlerFamily; }
 
--- a/netwerk/base/src/ProxyAutoConfig.cpp
+++ b/netwerk/base/src/ProxyAutoConfig.cpp
@@ -537,17 +537,16 @@ private:
     JSAutoRequest ar(mContext);
 
     JS::CompartmentOptions options;
     options.setZone(JS::SystemZone)
            .setVersion(JSVERSION_LATEST);
     mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, nullptr, options);
     NS_ENSURE_TRUE(mGlobal, NS_ERROR_OUT_OF_MEMORY);
 
-    JSAutoCompartment ac(mContext, mGlobal);
     JS_SetGlobalObject(mContext, mGlobal);
     JS_InitStandardClasses(mContext, mGlobal);
 
     JS_SetErrorReporter(mContext, PACErrorReporter);
 
     if (!JS_DefineFunctions(mContext, mGlobal, PACGlobalFunctions))
       return NS_ERROR_FAILURE;
 
@@ -589,17 +588,16 @@ ProxyAutoConfig::SetupJS()
   if (mPACScript.IsEmpty())
     return NS_ERROR_FAILURE;
 
   mJSRuntime = JSRuntimeWrapper::Create();
   if (!mJSRuntime)
     return NS_ERROR_FAILURE;
 
   JSAutoRequest ar(mJSRuntime->Context());
-  JSAutoCompartment ac(mJSRuntime->Context(), mJSRuntime->Global());
 
   sRunning = this;
   JSScript *script = JS_CompileScript(mJSRuntime->Context(),
                                       mJSRuntime->Global(),
                                       mPACScript.get(), mPACScript.Length(),
                                       mPACURI.get(), 1);
   if (!script ||
       !JS_ExecuteScript(mJSRuntime->Context(), mJSRuntime->Global(), script, nullptr)) {
@@ -631,17 +629,16 @@ ProxyAutoConfig::GetProxyForURI(const ns
   if (mJSNeedsSetup)
     SetupJS();
 
   if (!mJSRuntime || !mJSRuntime->IsOK())
     return NS_ERROR_NOT_AVAILABLE;
 
   JSContext *cx = mJSRuntime->Context();
   JSAutoRequest ar(cx);
-  JSAutoCompartment ac(cx, mJSRuntime->Global());
 
   // the sRunning flag keeps a new PAC file from being installed
   // while the event loop is spinning on a DNS function. Don't early return.
   sRunning = this;
   mRunningHost = aTestHost;
 
   nsresult rv = NS_ERROR_FAILURE;
   JS::RootedString uriString(cx, JS_NewStringCopyZ(cx, aTestURI.get()));
@@ -671,17 +668,16 @@ ProxyAutoConfig::GetProxyForURI(const ns
 }
 
 void
 ProxyAutoConfig::GC()
 {
   if (!mJSRuntime || !mJSRuntime->IsOK())
     return;
 
-  JSAutoCompartment ac(mJSRuntime->Context(), mJSRuntime->Global());
   JS_MaybeGC(mJSRuntime->Context());
 }
 
 ProxyAutoConfig::~ProxyAutoConfig()
 {
   MOZ_COUNT_DTOR(ProxyAutoConfig);
   NS_ASSERTION(!mJSRuntime,
                "~ProxyAutoConfig leaking JS runtime that "
--- a/toolkit/components/contentprefs/tests/unit_cps2/AsyncRunner.jsm
+++ b/toolkit/components/contentprefs/tests/unit_cps2/AsyncRunner.jsm
@@ -58,15 +58,12 @@ AsyncRunner.prototype = {
   destroy: function AR_destroy() {
     Cc["@mozilla.org/consoleservice;1"].
       getService(Ci.nsIConsoleService).
       unregisterListener(this);
     this.destroy = function AR_alreadyDestroyed() {};
   },
 
   observe: function AR_consoleServiceListener(msg) {
-    if (msg instanceof Ci.nsIScriptError &&
-        !(msg.flags & Ci.nsIScriptError.warningFlag))
-    {
+    if (msg instanceof Ci.nsIScriptError)
       this._callbacks.consoleError(msg);
-    }
   },
 };
--- a/toolkit/components/social/test/xpcshell/head.js
+++ b/toolkit/components/social/test/xpcshell/head.js
@@ -146,21 +146,18 @@ AsyncRunner.prototype = {
   destroy: function destroy() {
     Cc["@mozilla.org/consoleservice;1"].
       getService(Ci.nsIConsoleService).
       unregisterListener(this);
     this.destroy = function alreadyDestroyed() {};
   },
 
   observe: function observe(msg) {
-    if (msg instanceof Ci.nsIScriptError &&
-        !(msg.flags & Ci.nsIScriptError.warningFlag))
-    {
+    if (msg instanceof Ci.nsIScriptError)
       this._callbacks.consoleError(msg);
-    }
   },
 };
 
 
 function promiseAddVisits(aPlaceInfo)
 {
   let deferred = Promise.defer();
   let places = [];
--- a/toolkit/devtools/server/tests/unit/test_sourcemaps-04.js
+++ b/toolkit/devtools/server/tests/unit/test_sourcemaps-04.js
@@ -6,25 +6,16 @@
  */
 
 var gDebuggee;
 var gClient;
 var gThreadClient;
 
 Components.utils.import('resource:///modules/devtools/SourceMap.jsm');
 
-// Deep in the complicated labyrinth of code that this test invokes, beneath
-// debugger callbacks, sandboxes and nested event loops, lies an exception.
-// This exception lay sleeping since the dawn of time, held captive in a
-// delicate balance of custom xpcshell error reporters and garbage data about
-// the XPCCallContext stack. But bholley dug too greedily, and too deep, and
-// awoke shadow and flame in the darkness of nsExternalHelperAppService.cpp.
-// We must now trust in deep magic to ensure that it does not awaken again.
-ignoreReportedErrors(true);
-
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-source-map");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
     attachTestTabAndResume(gClient, "test-source-map", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
--- a/toolkit/devtools/server/tests/unit/test_sourcemaps-05.js
+++ b/toolkit/devtools/server/tests/unit/test_sourcemaps-05.js
@@ -6,25 +6,16 @@
  */
 
 var gDebuggee;
 var gClient;
 var gThreadClient;
 
 Components.utils.import('resource:///modules/devtools/SourceMap.jsm');
 
-// Deep in the complicated labyrinth of code that this test invokes, beneath
-// debugger callbacks, sandboxes and nested event loops, lies an exception.
-// This exception lay sleeping since the dawn of time, held captive in a
-// delicate balance of custom xpcshell error reporters and garbage data about
-// the XPCCallContext stack. But bholley dug too greedily, and too deep, and
-// awoke shadow and flame in the darkness of nsExternalHelperAppService.cpp.
-// We must now trust in deep magic to ensure that it does not awaken again.
-ignoreReportedErrors(true);
-
 function run_test()
 {
   initTestDebuggerServer();
   gDebuggee = addTestGlobal("test-source-map");
   gClient = new DebuggerClient(DebuggerServer.connectPipe());
   gClient.connect(function() {
     attachTestTabAndResume(gClient, "test-source-map", function(aResponse, aTabClient, aThreadClient) {
       gThreadClient = aThreadClient;
--- a/toolkit/mozapps/installer/precompile_cache.js
+++ b/toolkit/mozapps/installer/precompile_cache.js
@@ -61,32 +61,22 @@ function get_modules_under(uri) {
            .concat(dir_entries(file.file, "modules", ".jsm"));
   } else {
     throw "Expected a nsIJARURI or nsIFileURL";
   }
 }
 
 function load_modules_under(spec, uri) {
   var entries = get_modules_under(uri);
-  // The precompilation of JS here sometimes reports errors, which we don't
-  // really care about. But if the errors are ever reported to xpcshell's
-  // error reporter, it will cause it to return an error code, which will break
-  // automation. Currently they won't be, because the component loader spins up
-  // its JSContext before xpcshell has time to set its context callback (which
-  // overrides the error reporter on all newly-created JSContexts). But as we
-  // move towards a singled-cxed browser, we'll run into this. So let's be
-  // forward-thinking and deal with it now.
-  ignoreReportedErrors(true);
   for each (let entry in entries) {
     try {
       dump(spec + entry + "\n");
       Cu.import(spec + entry, null);
     } catch(e) {}
   }
-  ignoreReportedErrors(false);
 }
 
 function resolveResource(spec) {
   var uri = Services.io.newURI(spec, null, null);
   return Services.io.newURI(rph.resolveURI(uri), null, null);
 }
 
 function precompile_startupcache(uri) {