Backed out 33 changesets (bug 896126, bug 887334, bug 889911, bug 889714, bug 895774) for breaking xpcshell tests on a CLOSED TREE.
authorWes Kocher <wkocher@mozilla.com>
Thu, 25 Jul 2013 15:32:19 -0700
changeset 143701 659b0d61fbc6545e7e400710d241f147028b600e
parent 143700 84b828b63115943534ce64dc5cb9de20d284984b
child 143702 fedcc7eb515b0c5f18bc237b2a0bbcecec69ce23
push id4035
push userkwierso@gmail.com
push dateThu, 25 Jul 2013 22:33:02 +0000
treeherdermozilla-aurora@659b0d61fbc6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs896126, 887334, 889911, 889714, 895774
milestone24.0a2
backs out84b828b63115943534ce64dc5cb9de20d284984b
90dd4a81f0e524a8f376265e42564e6026560a5f
ce42d46f8703462607e652a1c6658fffa9e16bb8
0162540d3ba380ad9c650fa721e5c54f52370c71
94717e9e5e8a6533f9711d1129445cbc3fad1438
45c8301b2800eb795d89267035dfa229f219a46b
409df5742b7ad32edbcbddb8fa3df5bd4a853f2c
aa0205a0b60ac4824bfeb5964115cd80afda3722
a48028124452f647efb6209ae5a226a0b4fbd943
762a8d22146071e2abb2de46db83cb9013b367a5
2c36942312c84139579644d36ef5f8fc4fa2086a
1e48252b5a1d42934c5cee9135f8437a8abf1f4b
30b19452ea7afe0cda3203e3b05d97b867bac7e6
e0f3ed4738d3ae7fc61783a874f565b58fc614e0
2aa3a1f91a7db6c439c2d11abfacc5be829df2a3
e9d11a42124671d71ccc0a624b7e0825487e2768
c7e4cd12068a2047c6bb734437c35ab0f385f7ce
89e3b08492de178f8adfad6f8a25acb6436df0c2
a3f028f1f05ee96dc6ec025c260c056326cfff15
eaf22159cd3e44c1f279a3c0f3951e2a281bafab
142c7afd4ec5d193bb62da5679f46db99b78c4c1
0645c69167ba3298d741dac359dd0309b7756e6b
6462b9338a4925d77cadd80fc5e44c1ccf466139
c9387ac33f08e22e83c212216d19598956fd50c4
efe2d89832cf9e71548e01928490ea3893aedc3a
a83ae579e3df2989661c3964c7315ee51219de53
8d6c8265c2e63980d4e5c8baf38eb83657fa01c2
95cdfa09a620688d4fef05adc8c9f0bc2e4a424f
9b908f05db0bb74bcf90e4ae29bf6fad58e200b5
c7b60796eee3ca214177e218a97ea75876fcfb2c
037f34ec7b8bf423599f27b37374b09d71403148
33ef1b0a043fd82f2ad2ac6a9405a94e5abe10f7
05efd6fc03e34538f840edfcbe9eca0efbe2ee2b
Backed out 33 changesets (bug 896126, bug 887334, bug 889911, bug 889714, bug 895774) for breaking xpcshell tests on a CLOSED TREE. Backed out changeset 84b828b63115 (bug 896126) Backed out changeset 90dd4a81f0e5 (bug 887334) Backed out changeset ce42d46f8703 (bug 887334) Backed out changeset 0162540d3ba3 (bug 887334) Backed out changeset 94717e9e5e8a (bug 887334) Backed out changeset 45c8301b2800 (bug 887334) Backed out changeset 409df5742b7a (bug 887334) Backed out changeset aa0205a0b60a (bug 887334) Backed out changeset a48028124452 (bug 887334) Backed out changeset 762a8d221460 (bug 887334) Backed out changeset 2c36942312c8 (bug 887334) Backed out changeset 1e48252b5a1d (bug 887334) Backed out changeset 30b19452ea7a (bug 887334) Backed out changeset e0f3ed4738d3 (bug 887334) Backed out changeset 2aa3a1f91a7d (bug 887334) Backed out changeset e9d11a421246 (bug 887334) Backed out changeset c7e4cd12068a (bug 887334) Backed out changeset 89e3b08492de (bug 887334) Backed out changeset a3f028f1f05e (bug 887334) Backed out changeset eaf22159cd3e (bug 889714) Backed out changeset 142c7afd4ec5 (bug 889714) Backed out changeset 0645c69167ba (bug 889714) Backed out changeset 6462b9338a49 (bug 889714) Backed out changeset c9387ac33f08 (bug 889714) Backed out changeset efe2d89832cf (bug 889714) Backed out changeset a83ae579e3df (bug 889714) Backed out changeset 8d6c8265c2e6 (bug 889714) Backed out changeset 95cdfa09a620 (bug 889714) Backed out changeset 9b908f05db0b (bug 889911) Backed out changeset c7b60796eee3 (bug 889911) Backed out changeset 037f34ec7b8b (bug 889911) Backed out changeset 33ef1b0a043f (bug 889911) Backed out changeset 05efd6fc03e3 (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,20 +55,20 @@ TestShellChild::RecvPTestShellCommandCon
   }
 
   return PTestShellCommandChild::Send__delete__(aActor, response);
 }
 
 PContextWrapperChild*
 TestShellChild::AllocPContextWrapper()
 {
-  // This function was removed shortly after the merge, and was never called to
-  // begin with. Let's just MOZ_CRASH on 24 rather than fixing the merge
-  // conflict.
-  MOZ_CRASH();
+  JSContext* cx;
+  if (mXPCShell && (cx = mXPCShell->GetContext())) {
+    return new ContextWrapperChild(cx);
+  }
   return NULL;
 }
 
 bool
 TestShellChild::DeallocPContextWrapper(PContextWrapperChild* actor)
 {
   delete actor;
   return true;
--- 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) {