Merge m-i to m-c
authorPhil Ringnalda <philringnalda@gmail.com>
Sun, 20 Apr 2014 20:04:23 -0700
changeset 197870 9d9d84882a64fb084ca5e563ae9e7f192516feae
parent 197862 28dc0100f9b03b65d68679c528391397b5ffedb8 (current diff)
parent 197869 9dde6cd3739be8ccf00da7febaef98ef93e55507 (diff)
child 197877 5010b38abf18590cb17cf35e0cfaa933579cd748
push id3624
push userasasaki@mozilla.com
push dateMon, 09 Jun 2014 21:49:01 +0000
treeherdermozilla-beta@b1a5da15899a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone31.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-i to m-c
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -2395,17 +2395,17 @@ nsXULPrototypeScript::~nsXULPrototypeScr
 
 nsresult
 nsXULPrototypeScript::Serialize(nsIObjectOutputStream* aStream,
                                 nsXULPrototypeDocument* aProtoDoc,
                                 const nsCOMArray<nsINodeInfo> *aNodeInfos)
 {
     NS_ENSURE_TRUE(aProtoDoc, NS_ERROR_UNEXPECTED);
     AutoSafeJSContext cx;
-    JS::Rooted<JSObject*> global(cx, aProtoDoc->GetCompilationGlobal());
+    JS::Rooted<JSObject*> global(cx, xpc::GetCompilationScope());
     NS_ENSURE_TRUE(global, NS_ERROR_UNEXPECTED);
     JSAutoCompartment ac(cx, global);
 
     NS_ASSERTION(!mSrcLoading || mSrcLoadWaiters != nullptr ||
                  !mScriptObject,
                  "script source still loading when serializing?!");
     if (!mScriptObject)
         return NS_ERROR_FAILURE;
@@ -2417,18 +2417,18 @@ nsXULPrototypeScript::Serialize(nsIObjec
     rv = aStream->Write32(mLangVersion);
     if (NS_FAILED(rv)) return rv;
 
     // Calling fromMarkedLocation() is safe because we trace mScriptObject in
     // TraceScriptObject() and because its value is never changed after it has
     // been set.
     JS::Handle<JSScript*> script =
         JS::Handle<JSScript*>::fromMarkedLocation(mScriptObject.address());
-    MOZ_ASSERT(!strcmp(JS_GetClass(JS::CurrentGlobalOrNull(cx))->name,
-                       "nsXULPrototypeScript compilation scope"));
+    // Note - Inverting the order of these operands is a rooting hazard.
+    MOZ_ASSERT(xpc::GetCompilationScope() == JS::CurrentGlobalOrNull(cx));
     return nsContentUtils::XPConnect()->WriteScript(aStream, cx,
                                                     xpc_UnmarkGrayScript(script));
 }
 
 nsresult
 nsXULPrototypeScript::SerializeOutOfLine(nsIObjectOutputStream* aStream,
                                          nsXULPrototypeDocument* aProtoDoc)
 {
@@ -2485,23 +2485,21 @@ nsXULPrototypeScript::Deserialize(nsIObj
                  !mScriptObject,
                  "prototype script not well-initialized when deserializing?!");
 
     // Read basic prototype data
     aStream->Read32(&mLineNo);
     aStream->Read32(&mLangVersion);
 
     AutoSafeJSContext cx;
-    JS::Rooted<JSObject*> global(cx, aProtoDoc->GetCompilationGlobal());
+    JS::Rooted<JSObject*> global(cx, xpc::GetCompilationScope());
     NS_ENSURE_TRUE(global, NS_ERROR_UNEXPECTED);
     JSAutoCompartment ac(cx, global);
 
     JS::Rooted<JSScript*> newScriptObject(cx);
-    MOZ_ASSERT(!strcmp(JS_GetClass(JS::CurrentGlobalOrNull(cx))->name,
-                       "nsXULPrototypeScript compilation scope"));
     nsresult rv = nsContentUtils::XPConnect()->ReadScript(aStream, cx,
                                                           newScriptObject.address());
     NS_ENSURE_SUCCESS(rv, rv);
     Set(newScriptObject);
     return NS_OK;
 }
 
 
@@ -2624,30 +2622,21 @@ nsresult
 nsXULPrototypeScript::Compile(const char16_t* aText,
                               int32_t aTextLength,
                               nsIURI* aURI,
                               uint32_t aLineNo,
                               nsIDocument* aDocument,
                               nsXULPrototypeDocument* aProtoDoc,
                               nsIOffThreadScriptReceiver *aOffThreadReceiver /* = nullptr */)
 {
-    // We'll compile the script using the prototype document's special
-    // script object as the parent. This ensures that we won't end up
-    // with an uncollectable reference.
-    //
-    // Compiling it using (for example) the first document's global
-    // object would cause JS to keep a reference via the __proto__ or
-    // parent pointer to the first document's global. If that happened,
-    // our script object would reference the first document, and the
-    // first document would indirectly reference the prototype document
-    // because it keeps the prototype cache alive. Circularity!
+    // We'll compile the script in the compilation scope.
     MOZ_ASSERT(aProtoDoc);
-    NS_ENSURE_TRUE(aProtoDoc->GetCompilationGlobal(), NS_ERROR_UNEXPECTED);
+    NS_ENSURE_TRUE(xpc::GetCompilationScope(), NS_ERROR_UNEXPECTED);
     AutoSafeJSContext cx;
-    JSAutoCompartment ac(cx, aProtoDoc->GetCompilationGlobal());
+    JSAutoCompartment ac(cx, xpc::GetCompilationScope());
 
     nsAutoCString urlspec;
     nsContentUtils::GetWrapperSafeScriptFilename(aDocument, aURI, urlspec);
 
     // Ok, compile it to create a prototype script object!
     NS_ENSURE_TRUE(JSVersion(mLangVersion) != JSVERSION_UNKNOWN, NS_OK);
     JS::CompileOptions options(cx);
     options.setIntroductionType("scriptElement")
--- a/content/xul/document/src/nsXULPrototypeDocument.cpp
+++ b/content/xul/document/src/nsXULPrototypeDocument.cpp
@@ -7,17 +7,16 @@
 #include "nsXULPrototypeDocument.h"
 #include "XULDocument.h"
 
 #include "nsAString.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsIPrincipal.h"
 #include "nsJSPrincipals.h"
-#include "nsIScriptGlobalObject.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIServiceManager.h"
 #include "nsIArray.h"
 #include "nsIURI.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "nsString.h"
@@ -33,84 +32,18 @@
 #include "xpcpublic.h"
 #include "mozilla/dom/BindingUtils.h"
 
 using mozilla::dom::DestroyProtoAndIfaceCache;
 using mozilla::AutoPushJSContext;
 using mozilla::AutoSafeJSContext;
 using mozilla::dom::XULDocument;
 
-class nsXULPDGlobalObject : public nsISupports
-{
-public:
-    nsXULPDGlobalObject(nsXULPrototypeDocument* owner);
-
-    // nsISupports interface
-    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-    NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsXULPDGlobalObject)
-
-    JSObject* GetCompilationGlobal();
-    void UnmarkCompilationGlobal()
-    {
-        if (mJSObject) {
-            JS::ExposeObjectToActiveJS(mJSObject);
-        }
-    }
-    void Destroy();
-    nsIPrincipal* GetPrincipal();
-    void ClearGlobalObjectOwner();
-
-protected:
-    virtual ~nsXULPDGlobalObject();
-
-    nsCOMPtr<nsIPrincipal> mCachedPrincipal;
-    nsXULPrototypeDocument* mGlobalObjectOwner; // weak reference
-    JS::Heap<JSObject*> mJSObject;
-    bool mDestroyed; // Probably not necessary, but let's be safe.
-
-    static const JSClass gSharedGlobalClass;
-};
-
-nsIPrincipal* nsXULPrototypeDocument::gSystemPrincipal;
-nsXULPDGlobalObject* nsXULPrototypeDocument::gSystemGlobal;
 uint32_t nsXULPrototypeDocument::gRefCnt;
 
-
-void
-nsXULPDGlobalObject_finalize(JSFreeOp *fop, JSObject *obj)
-{
-    nsXULPDGlobalObject* nativeThis = static_cast<nsXULPDGlobalObject*>(JS_GetPrivate(obj));
-    nativeThis->Destroy();
-
-    // The addref was part of JSObject construction
-    nsContentUtils::DeferredFinalize(nativeThis);
-}
-
-
-bool
-nsXULPDGlobalObject_resolve(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id)
-{
-    bool did_resolve = false;
-
-    return JS_ResolveStandardClass(cx, obj, id, &did_resolve);
-}
-
-
-const JSClass nsXULPDGlobalObject::gSharedGlobalClass = {
-    "nsXULPrototypeScript compilation scope",
-    JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS |
-    JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(0),
-    JS_PropertyStub,  JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
-    JS_EnumerateStub, nsXULPDGlobalObject_resolve,  JS_ConvertStub,
-    nsXULPDGlobalObject_finalize, nullptr, nullptr, nullptr,
-    JS_GlobalObjectTraceHook
-};
-
-
-
 //----------------------------------------------------------------------
 //
 // ctors, dtors, n' stuff
 //
 
 nsXULPrototypeDocument::nsXULPrototypeDocument()
     : mRoot(nullptr),
       mLoaded(false),
@@ -127,41 +60,30 @@ nsXULPrototypeDocument::Init()
     mNodeInfoManager = new nsNodeInfoManager();
     NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_OUT_OF_MEMORY);
 
     return mNodeInfoManager->Init(nullptr);
 }
 
 nsXULPrototypeDocument::~nsXULPrototypeDocument()
 {
-    if (mGlobalObject) {
-        // cleaup cycles etc.
-        mGlobalObject->ClearGlobalObjectOwner();
-    }
-
     if (mRoot)
         mRoot->ReleaseSubtree();
-
-    if (--gRefCnt == 0) {
-        NS_IF_RELEASE(gSystemPrincipal);
-        NS_IF_RELEASE(gSystemGlobal);
-    }
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULPrototypeDocument)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULPrototypeDocument)
     tmp->mPrototypeWaiters.Clear();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULPrototypeDocument)
     if (nsCCUncollectableMarker::InGeneration(cb, tmp->mCCGeneration)) {
         return NS_SUCCESS_INTERRUPTED_TRAVERSE;
     }
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot)
-    NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobalObject)
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNodeInfoManager)
     for (uint32_t i = 0; i < tmp->mPrototypeWaiters.Length(); ++i) {
         NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mPrototypeWaiters[i]");
         cb.NoteXPCOMChild(static_cast<nsINode*>(tmp->mPrototypeWaiters[i].get()));
     }
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULPrototypeDocument)
@@ -186,45 +108,16 @@ NS_NewXULPrototypeDocument(nsXULPrototyp
         *aResult = nullptr;
         return rv;
     }
 
     NS_ADDREF(*aResult);
     return rv;
 }
 
-// Helper method that shares a system global among all prototype documents
-// that have the system principal as their security principal.   Called by
-// nsXULPrototypeDocument::Read and nsXULPrototypeDocument::GetCompilationGlobal.
-// This method greatly reduces the number of nsXULPDGlobalObjects and their
-// nsIScriptContexts in apps that load many XUL documents via chrome: URLs.
-
-nsXULPDGlobalObject *
-nsXULPrototypeDocument::NewXULPDGlobalObject()
-{
-    // Now compare DocumentPrincipal() to gSystemPrincipal, in order to create
-    // gSystemGlobal if the two pointers are equal.  Thus, gSystemGlobal
-    // implies gSystemPrincipal.
-    nsXULPDGlobalObject *global;
-    if (DocumentPrincipal() == gSystemPrincipal) {
-        if (!gSystemGlobal) {
-            gSystemGlobal = new nsXULPDGlobalObject(nullptr);
-            if (! gSystemGlobal)
-                return nullptr;
-            NS_ADDREF(gSystemGlobal);
-        }
-        global = gSystemGlobal;
-    } else {
-        global = new nsXULPDGlobalObject(this); // does not refcount
-        if (! global)
-            return nullptr;
-    }
-    return global;
-}
-
 //----------------------------------------------------------------------
 //
 // nsISerializable methods
 //
 
 NS_IMETHODIMP
 nsXULPrototypeDocument::Read(nsIObjectInputStream* aStream)
 {
@@ -260,22 +153,16 @@ nsXULPrototypeDocument::Read(nsIObjectIn
     tmp = aStream->ReadObject(true, getter_AddRefs(supports));
     principal = do_QueryInterface(supports);
     if (NS_FAILED(tmp)) {
       rv = tmp;
     }
     // Better safe than sorry....
     mNodeInfoManager->SetDocumentPrincipal(principal);
 
-
-    // nsIScriptGlobalObject mGlobalObject
-    mGlobalObject = NewXULPDGlobalObject();
-    if (! mGlobalObject)
-        return NS_ERROR_OUT_OF_MEMORY;
-
     mRoot = new nsXULPrototypeElement();
     if (! mRoot)
        return NS_ERROR_OUT_OF_MEMORY;
 
     // nsINodeInfo table
     nsCOMArray<nsINodeInfo> nodeInfos;
 
     tmp = aStream->Read32(&count);
@@ -609,32 +496,20 @@ nsXULPrototypeDocument::DocumentPrincipa
 }
 
 void
 nsXULPrototypeDocument::SetDocumentPrincipal(nsIPrincipal* aPrincipal)
 {
     mNodeInfoManager->SetDocumentPrincipal(aPrincipal);
 }
 
-JSObject*
-nsXULPrototypeDocument::GetCompilationGlobal()
-{
-  if (!mGlobalObject) {
-      mGlobalObject = NewXULPDGlobalObject();
-  }
-  return mGlobalObject->GetCompilationGlobal();
-}
-
 void
 nsXULPrototypeDocument::MarkInCCGeneration(uint32_t aCCGeneration)
 {
     mCCGeneration = aCCGeneration;
-    if (mGlobalObject) {
-        mGlobalObject->UnmarkCompilationGlobal();
-    }
 }
 
 nsNodeInfoManager*
 nsXULPrototypeDocument::GetNodeInfoManager()
 {
     return mNodeInfoManager;
 }
 
@@ -687,123 +562,8 @@ nsXULPrototypeDocument::TraceProtos(JSTr
     return;
   }
 
   mGCNumber = aGCNumber;
   if (mRoot) {
     mRoot->TraceAllScripts(aTrc);
   }
 }
-
-//----------------------------------------------------------------------
-//
-// nsXULPDGlobalObject
-//
-
-nsXULPDGlobalObject::nsXULPDGlobalObject(nsXULPrototypeDocument* owner)
-  : mGlobalObjectOwner(owner)
-  , mJSObject(nullptr)
-  , mDestroyed(false)
-{
-}
-
-
-nsXULPDGlobalObject::~nsXULPDGlobalObject()
-{
-  MOZ_ASSERT(!mJSObject);
-}
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULPDGlobalObject)
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsXULPDGlobalObject)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJSObject)
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULPDGlobalObject)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULPDGlobalObject)
-  tmp->Destroy();
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULPDGlobalObject)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULPDGlobalObject)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULPDGlobalObject)
-
-JSObject *
-nsXULPDGlobalObject::GetCompilationGlobal()
-{
-  if (mJSObject) {
-    // We've been initialized before. This is what we get.
-    JS::ExposeObjectToActiveJS(mJSObject);
-    return mJSObject;
-  }
-
-  if (mDestroyed) {
-    return nullptr;
-  }
-
-  AutoSafeJSContext cx;
-  JS::CompartmentOptions options;
-  options.setZone(JS::SystemZone)
-         .setInvisibleToDebugger(true);
-  mJSObject = JS_NewGlobalObject(cx, &gSharedGlobalClass,
-                                 nsJSPrincipals::get(GetPrincipal()),
-                                 JS::DontFireOnNewGlobalHook, options);
-  NS_ENSURE_TRUE(mJSObject, nullptr);
-
-  mozilla::HoldJSObjects(this);
-
-  // Add an owning reference from JS back to us. This'll be
-  // released when the JSObject is finalized.
-  JS_SetPrivate(mJSObject, this);
-  NS_ADDREF(this);
-
-  // Set the location information for the new global, so that tools like
-  // about:memory may use that information
-  nsIURI *ownerURI = mGlobalObjectOwner->GetURI();
-  xpc::SetLocationForGlobal(mJSObject, ownerURI);
-
-  return mJSObject;
-}
-
-void
-nsXULPDGlobalObject::ClearGlobalObjectOwner()
-{
-  NS_ASSERTION(!mCachedPrincipal, "This shouldn't ever be set until now!");
-
-  // Cache mGlobalObjectOwner's principal if possible.
-  if (this != nsXULPrototypeDocument::gSystemGlobal)
-    mCachedPrincipal = mGlobalObjectOwner->DocumentPrincipal();
-
-  mGlobalObjectOwner = nullptr;
-}
-
-void
-nsXULPDGlobalObject::Destroy()
-{
-  mDestroyed = true;
-  if (!mJSObject) {
-    return;
-  }
-  mJSObject = nullptr;
-  mozilla::DropJSObjects(this);
-}
-
-nsIPrincipal*
-nsXULPDGlobalObject::GetPrincipal()
-{
-    if (!mGlobalObjectOwner) {
-        // See nsXULPrototypeDocument::NewXULPDGlobalObject, the comment
-        // about gSystemGlobal implying gSystemPrincipal.
-        if (this == nsXULPrototypeDocument::gSystemGlobal) {
-            return nsXULPrototypeDocument::gSystemPrincipal;
-        }
-        // Return the cached principal if it exists.
-        return mCachedPrincipal;
-    }
-
-    return mGlobalObjectOwner->DocumentPrincipal();
-}
--- a/content/xul/document/src/nsXULPrototypeDocument.h
+++ b/content/xul/document/src/nsXULPrototypeDocument.h
@@ -16,17 +16,16 @@
 #include "nsCycleCollectionParticipant.h"
 
 class nsIAtom;
 class nsIPrincipal;
 class nsIURI;
 class nsNodeInfoManager;
 class nsXULPrototypeElement;
 class nsXULPrototypePI;
-class nsXULPDGlobalObject;
 
 namespace mozilla {
 namespace dom {
 class XULDocument;
 } // namespace dom
 } // namespace mozilla
 
 /**
@@ -107,49 +106,39 @@ public:
      * prototype document that the prototype has finished loading.
      * The notification is performed by calling
      * nsIXULDocument::OnPrototypeLoadDone on the registered documents.
      */
     nsresult NotifyLoadDone();
 
     nsNodeInfoManager *GetNodeInfoManager();
 
-    JSObject* GetCompilationGlobal();
-
     void MarkInCCGeneration(uint32_t aCCGeneration);
 
     NS_DECL_CYCLE_COLLECTION_CLASS(nsXULPrototypeDocument)
 
     void TraceProtos(JSTracer* aTrc, uint32_t aGCNumber);
 
 protected:
     nsCOMPtr<nsIURI> mURI;
     nsRefPtr<nsXULPrototypeElement> mRoot;
     nsTArray<nsRefPtr<nsXULPrototypePI> > mProcessingInstructions;
     nsCOMArray<nsIURI> mStyleSheetReferences;
 
-    nsRefPtr<nsXULPDGlobalObject> mGlobalObject;
-
     bool mLoaded;
     nsTArray< nsRefPtr<mozilla::dom::XULDocument> > mPrototypeWaiters;
 
     nsRefPtr<nsNodeInfoManager> mNodeInfoManager;
 
     uint32_t mCCGeneration;
     uint32_t mGCNumber;
 
     nsXULPrototypeDocument();
     virtual ~nsXULPrototypeDocument();
     nsresult Init();
 
     friend NS_IMETHODIMP
     NS_NewXULPrototypeDocument(nsXULPrototypeDocument** aResult);
 
-    nsXULPDGlobalObject *NewXULPDGlobalObject();
-
-    static nsIPrincipal* gSystemPrincipal;
-    static nsXULPDGlobalObject* gSystemGlobal;
     static uint32_t gRefCnt;
-
-    friend class nsXULPDGlobalObject;
 };
 
 #endif // nsXULPrototypeDocument_h__
--- a/dom/tests/mochitest/beacon/test_beaconContentPolicy.html
+++ b/dom/tests/mochitest/beacon/test_beaconContentPolicy.html
@@ -25,84 +25,73 @@ const Ci = SpecialPowers.Ci;
 // not enabled by default yet.
 SimpleTest.waitForExplicitFinish();
 
 var policy = setupPolicy();
 
 SpecialPowers.pushPrefEnv({'set': [["beacon.enabled", true]]}, beginTest);
 
 function setupPolicy() {
-  info("creating the policy");
   var policyID = SpecialPowers.wrap(SpecialPowers.Components).ID("{b80e19d0-878f-d41b-2654-194714a4115c}");
   var policyName = "@mozilla.org/testpolicy;1";
   var policy = {
     // nsISupports implementation
     QueryInterface: function(iid) {
-      info("QueryInterface called " + iid);
       iid = SpecialPowers.wrap(iid);
       if (iid.equals(Ci.nsISupports) ||
         iid.equals(Ci.nsIFactory) ||
         iid.equals(Ci.nsIContentPolicy))
         return this;
-      info("unknown interface!");
       throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE;
     },
     
     // nsIFactory implementation
     createInstance: function(outer, iid) {
-      info("createInstance called " + iid);
       return this.QueryInterface(iid);
     },
 
     // nsIContentPolicy implementation
     shouldLoad: function(contentType, contentLocation, requestOrigin, context, mimeTypeGuess, extra) {
-      info("shouldLoad");
-      info("url: " + SpecialPowers.wrap(contentLocation).spec);
       // Remember last content type seen for the test url
 
       if (SpecialPowers.wrap(contentLocation).spec == beaconUrl) {
         is(contentType,  Ci.nsIContentPolicy.TYPE_BEACON, "Beacon content type should match expected.  is: " + contentType + " should be: " + Ci.nsIContentPolicy.TYPE_BEACON);
         teardownPolicy();
         SimpleTest.finish();
       }
 
       return Ci.nsIContentPolicy.ACCEPT;
     },
 
     shouldProcess: function(contentType, contentLocation, requestOrigin, context, mimeTypeGuess, extra) {
-      info("shouldProcess");
-      info("url: " + SpecialPowers.wrap(contentLocation).spec);
       return Ci.nsIContentPolicy.ACCEPT;
     }
   }
   policy = SpecialPowers.wrapCallbackObject(policy);
 
   // Register content policy
-  info("registering the policy");
   var componentManager = SpecialPowers.wrap(SpecialPowers.Components).manager.QueryInterface(Ci.nsIComponentRegistrar);
   componentManager.registerFactory(policyID, "Test content policy", policyName, policy);
 
   var categoryManager = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
   categoryManager.addCategoryEntry("content-policy", policyName, policyName, false, true);
 
-  info("returning the policy");
   return { 'policy': policy, 'policyID': policyID, 'policyName': policyName };
 }
 
 function teardownPolicy() {
   setTimeout(function() {
     // policy will not be removed from the category correctly
     var componentManager = SpecialPowers.wrap(SpecialPowers.Components).manager.QueryInterface(Ci.nsIComponentRegistrar);
     componentManager.unregisterFactory(policy.policyID, policy.policy);
     var categoryManager = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
     categoryManager.deleteCategoryEntry("content-policy", policy.policyName, false);
   }, 0);
 }
 
 function beginTest() {
-  info("sending the beacon");
   navigator.sendBeacon(beaconUrl, "bacon would have been a better name than beacon");
 }
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/xbl/nsXBLDocumentInfo.cpp
+++ b/dom/xbl/nsXBLDocumentInfo.cpp
@@ -6,17 +6,16 @@
 
 #include "mozilla/DebugOnly.h"
 
 #include "nsXBLDocumentInfo.h"
 #include "nsHashtable.h"
 #include "nsIDocument.h"
 #include "nsXBLPrototypeBinding.h"
 #include "nsIScriptObjectPrincipal.h"
-#include "nsIScriptGlobalObject.h"
 #include "nsIScriptContext.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMScriptObjectFactory.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "nsIURI.h"
 #include "nsIConsoleService.h"
 #include "nsIScriptError.h"
@@ -36,196 +35,16 @@
 #include "mozilla/dom/URL.h"
 
 using namespace mozilla;
 using namespace mozilla::scache;
 using namespace mozilla::dom;
 
 static const char kXBLCachePrefix[] = "xblcache";
 
-class nsXBLDocGlobalObject : public nsISupports
-{
-public:
-  nsXBLDocGlobalObject(nsXBLDocumentInfo *aGlobalObjectOwner);
-
-  // nsISupports interface
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsXBLDocGlobalObject)
-
-  JSObject *GetCompilationGlobal();
-  void UnmarkCompilationGlobal();
-  void Destroy();
-  nsIPrincipal* GetPrincipal();
-
-  void ClearGlobalObjectOwner();
-
-  static const JSClass gSharedGlobalClass;
-
-protected:
-  virtual ~nsXBLDocGlobalObject();
-
-  JS::Heap<JSObject*> mJSObject;
-  nsXBLDocumentInfo* mGlobalObjectOwner; // weak reference
-  bool mDestroyed; // Probably not necessary, but let's be safe.
-};
-
-static void
-nsXBLDocGlobalObject_finalize(JSFreeOp *fop, JSObject *obj)
-{
-  nsISupports *nativeThis = (nsISupports*)JS_GetPrivate(obj);
-  nsXBLDocGlobalObject* dgo = static_cast<nsXBLDocGlobalObject*>(nativeThis);
-
-  if (dgo)
-    dgo->Destroy();
-
-  // The addref was part of JSObject construction. Note that this effectively
-  // just calls release later on.
-  nsContentUtils::DeferredFinalize(nativeThis);
-}
-
-static bool
-nsXBLDocGlobalObject_resolve(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id)
-{
-  bool did_resolve = false;
-  return JS_ResolveStandardClass(cx, obj, id, &did_resolve);
-}
-
-
-const JSClass nsXBLDocGlobalObject::gSharedGlobalClass = {
-    "nsXBLPrototypeScript compilation scope",
-    JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS |
-    JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(0),
-    JS_PropertyStub,  JS_DeletePropertyStub,
-    JS_PropertyStub, JS_StrictPropertyStub,
-    JS_EnumerateStub, nsXBLDocGlobalObject_resolve,
-    JS_ConvertStub, nsXBLDocGlobalObject_finalize,
-    nullptr, nullptr, nullptr, JS_GlobalObjectTraceHook
-};
-
-//----------------------------------------------------------------------
-//
-// nsXBLDocGlobalObject
-//
-
-nsXBLDocGlobalObject::nsXBLDocGlobalObject(nsXBLDocumentInfo *aGlobalObjectOwner)
-    : mJSObject(nullptr)
-    , mGlobalObjectOwner(aGlobalObjectOwner) // weak reference
-    , mDestroyed(false)
-
-{
-}
-
-
-nsXBLDocGlobalObject::~nsXBLDocGlobalObject()
-{
-  MOZ_ASSERT(!mJSObject);
-}
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLDocGlobalObject)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXBLDocGlobalObject)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsXBLDocGlobalObject)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mJSObject)
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXBLDocGlobalObject)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXBLDocGlobalObject)
-  tmp->Destroy();
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXBLDocGlobalObject)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXBLDocGlobalObject)
-
-void
-nsXBLDocGlobalObject::ClearGlobalObjectOwner()
-{
-  mGlobalObjectOwner = nullptr;
-}
-
-void
-nsXBLDocGlobalObject::UnmarkCompilationGlobal()
-{
-  if (mJSObject) {
-    JS::ExposeObjectToActiveJS(mJSObject);
-  }
-}
-
-JSObject *
-nsXBLDocGlobalObject::GetCompilationGlobal()
-{
-  // The prototype document has its own special secret script object
-  // that can be used to compile scripts and event handlers.
-  if (mJSObject || mDestroyed) {
-    // We've been initialized before - what we have is what you get.
-    return mJSObject;
-  }
-
-  AutoSafeJSContext cx;
-  JS::CompartmentOptions options;
-  options.setZone(JS::SystemZone)
-         .setInvisibleToDebugger(true);
-  mJSObject = JS_NewGlobalObject(cx, &gSharedGlobalClass,
-                                 nsJSPrincipals::get(GetPrincipal()),
-                                 JS::DontFireOnNewGlobalHook,
-                                 options);
-  if (!mJSObject)
-      return nullptr;
-
-  mozilla::HoldJSObjects(this);
-
-  // Set the location information for the new global, so that tools like
-  // about:memory may use that information
-  nsIURI *ownerURI = mGlobalObjectOwner->DocumentURI();
-  xpc::SetLocationForGlobal(mJSObject, ownerURI);
-
-  // Add an owning reference from JS back to us. This'll be
-  // released when the JSObject is finalized.
-  ::JS_SetPrivate(mJSObject, this);
-  NS_ADDREF(this);
-  return mJSObject;
-}
-
-void
-nsXBLDocGlobalObject::Destroy()
-{
-  // Maintain indempotence.
-  mDestroyed = true;
-  if (!mJSObject)
-    return;
-  mJSObject = nullptr;
-  mozilla::DropJSObjects(this);
-}
-
-
-nsIPrincipal*
-nsXBLDocGlobalObject::GetPrincipal()
-{
-  if (!mGlobalObjectOwner) {
-    // XXXbz this should really save the principal when
-    // ClearGlobalObjectOwner() happens.
-    return nullptr;
-  }
-
-  nsRefPtr<nsXBLDocumentInfo> docInfo =
-    static_cast<nsXBLDocumentInfo*>(mGlobalObjectOwner);
-
-  nsCOMPtr<nsIDocument> document = docInfo->GetDocument();
-  if (!document)
-    return nullptr;
-
-  return document->NodePrincipal();
-}
-
 /* Implementation file */
 
 static PLDHashOperator
 TraverseProtos(const nsACString &aKey, nsXBLPrototypeBinding *aProto, void* aClosure)
 {
   nsCycleCollectionTraversalCallback *cb =
     static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
   aProto->Traverse(*cb);
@@ -255,29 +74,27 @@ TraceProtos(const nsACString &aKey, nsXB
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLDocumentInfo)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXBLDocumentInfo)
   if (tmp->mBindingTable) {
     tmp->mBindingTable->EnumerateRead(UnlinkProtoJSObjects, nullptr);
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobalObject)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXBLDocumentInfo)
   if (tmp->mDocument &&
       nsCCUncollectableMarker::InGeneration(cb, tmp->mDocument->GetMarkedCCGeneration())) {
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
   }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
   if (tmp->mBindingTable) {
     tmp->mBindingTable->EnumerateRead(TraverseProtos, &cb);
   }
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobalObject)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsXBLDocumentInfo)
   if (tmp->mBindingTable) {
     ProtoTracer closure = { aCallbacks, aClosure };
     tmp->mBindingTable->EnumerateRead(TraceProtos, &closure);
   }
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
@@ -300,19 +117,16 @@ nsXBLDocumentInfo::MarkInCCGeneration(ui
 {
   if (mDocument) {
     mDocument->MarkUncollectableForCCGeneration(aGeneration);
   }
   // Unmark any JS we hold
   if (mBindingTable) {
     mBindingTable->EnumerateRead(UnmarkProtos, nullptr);
   }
-  if (mGlobalObject) {
-    mGlobalObject->UnmarkCompilationGlobal();
-  }
 }
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXBLDocumentInfo)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXBLDocumentInfo)
@@ -353,20 +167,16 @@ nsXBLDocumentInfo::nsXBLDocumentInfo(nsI
     nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
     nsresult rv = ssm->PolicyAllowsScript(uri, &allow);
     mScriptAccess = NS_SUCCEEDED(rv) && allow;
   }
 }
 
 nsXBLDocumentInfo::~nsXBLDocumentInfo()
 {
-  /* destructor code */
-  if (mGlobalObject) {
-    mGlobalObject->ClearGlobalObjectOwner(); // just in case
-  }
   mozilla::DropJSObjects(this);
 }
 
 nsXBLPrototypeBinding*
 nsXBLDocumentInfo::GetPrototypeBinding(const nsACString& aRef)
 {
   if (!mBindingTable)
     return nullptr;
@@ -541,32 +351,17 @@ FlushScopedSkinSheets(const nsACString &
 void
 nsXBLDocumentInfo::FlushSkinStylesheets()
 {
   if (mBindingTable) {
     mBindingTable->EnumerateRead(FlushScopedSkinSheets, nullptr);
   }
 }
 
-JSObject*
-nsXBLDocumentInfo::GetCompilationGlobal()
-{
-  EnsureGlobalObject();
-  return mGlobalObject->GetCompilationGlobal();
-}
-
-void
-nsXBLDocumentInfo::EnsureGlobalObject()
-{
-  if (!mGlobalObject) {
-    mGlobalObject = new nsXBLDocGlobalObject(this);
-  }
-}
-
 #ifdef DEBUG
 void
 AssertInCompilationScope()
 {
   AutoJSContext cx;
-  MOZ_ASSERT(JS_GetClass(JS::CurrentGlobalOrNull(cx)) ==
-             &nsXBLDocGlobalObject::gSharedGlobalClass);
+  // Note - Inverting the order of these operands is a rooting hazard.
+  MOZ_ASSERT(xpc::GetCompilationScope() == JS::CurrentGlobalOrNull(cx));
 }
 #endif
--- a/dom/xbl/nsXBLDocumentInfo.h
+++ b/dom/xbl/nsXBLDocumentInfo.h
@@ -40,36 +40,31 @@ public:
   nsresult WritePrototypeBindings();
 
   void SetFirstPrototypeBinding(nsXBLPrototypeBinding* aBinding);
 
   void FlushSkinStylesheets();
 
   bool IsChrome() { return mIsChrome; }
 
-  JSObject* GetCompilationGlobal();
-
   void MarkInCCGeneration(uint32_t aGeneration);
 
   static nsresult ReadPrototypeBindings(nsIURI* aURI, nsXBLDocumentInfo** aDocInfo);
 
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsXBLDocumentInfo)
 
 private:
-  void EnsureGlobalObject();
   nsCOMPtr<nsIDocument> mDocument;
   bool mScriptAccess;
   bool mIsChrome;
   // the binding table owns each nsXBLPrototypeBinding
   nsAutoPtr<nsClassHashtable<nsCStringHashKey, nsXBLPrototypeBinding>> mBindingTable;
 
   // non-owning pointer to the first binding in the table
   nsXBLPrototypeBinding* mFirstBinding;
-
-  nsRefPtr<nsXBLDocGlobalObject> mGlobalObject;
 };
 
 #ifdef DEBUG
 void AssertInCompilationScope();
 #else
 inline void AssertInCompilationScope() {}
 #endif
 
--- a/dom/xbl/nsXBLProtoImpl.cpp
+++ b/dom/xbl/nsXBLProtoImpl.cpp
@@ -196,17 +196,17 @@ nsXBLProtoImpl::InitTargetObjects(nsXBLP
 
 nsresult
 nsXBLProtoImpl::CompilePrototypeMembers(nsXBLPrototypeBinding* aBinding)
 {
   // We want to pre-compile our implementation's members against a "prototype context". Then when we actually 
   // bind the prototype to a real xbl instance, we'll clone the pre-compiled JS into the real instance's 
   // context.
   AutoSafeJSContext cx;
-  JS::Rooted<JSObject*> compilationGlobal(cx, aBinding->XBLDocumentInfo()->GetCompilationGlobal());
+  JS::Rooted<JSObject*> compilationGlobal(cx, xpc::GetCompilationScope());
   NS_ENSURE_TRUE(compilationGlobal, NS_ERROR_UNEXPECTED);
   JSAutoCompartment ac(cx, compilationGlobal);
 
   mPrecompiledMemberHolder = JS_NewObjectWithGivenProto(cx, nullptr, JS::NullPtr(), compilationGlobal);
   if (!mPrecompiledMemberHolder)
     return NS_ERROR_OUT_OF_MEMORY;
 
   // Now that we have a class object installed, we walk our member list and compile each of our
--- a/dom/xbl/nsXBLPrototypeBinding.cpp
+++ b/dom/xbl/nsXBLPrototypeBinding.cpp
@@ -914,17 +914,17 @@ nsXBLPrototypeBinding::Read(nsIObjectInp
 
   for (; interfaceCount > 0; interfaceCount--) {
     nsIID iid;
     aStream->ReadID(&iid);
     mInterfaceTable.Put(iid, mBinding);
   }
 
   AutoSafeJSContext cx;
-  JS::Rooted<JSObject*> compilationGlobal(cx, aDocInfo->GetCompilationGlobal());
+  JS::Rooted<JSObject*> compilationGlobal(cx, xpc::GetCompilationScope());
   NS_ENSURE_TRUE(compilationGlobal, NS_ERROR_UNEXPECTED);
   JSAutoCompartment ac(cx, compilationGlobal);
 
   bool isFirstBinding = aFlags & XBLBinding_Serialize_IsFirstBinding;
   rv = Init(id, aDocInfo, nullptr, isFirstBinding);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // We need to set the prototype binding before reading the nsXBLProtoImpl,
@@ -1067,17 +1067,17 @@ WriteInterfaceID(const nsIID& aKey, nsIC
 nsresult
 nsXBLPrototypeBinding::Write(nsIObjectOutputStream* aStream)
 {
   // This writes out the binding. Note that mCheckedBaseProto,
   // mKeyHandlersRegistered and mKeyHandlers are not serialized as they are
   // computed on demand.
 
   AutoSafeJSContext cx;
-  JS::Rooted<JSObject*> compilationGlobal(cx, mXBLDocInfoWeak->GetCompilationGlobal());
+  JS::Rooted<JSObject*> compilationGlobal(cx, xpc::GetCompilationScope());
   NS_ENSURE_TRUE(compilationGlobal, NS_ERROR_UNEXPECTED);
   JSAutoCompartment ac(cx, compilationGlobal);
 
   uint8_t flags = mInheritStyle ? XBLBinding_Serialize_InheritStyle : 0;
 
   // mAlternateBindingURI is only set on the first binding.
   if (mAlternateBindingURI) {
     flags |= XBLBinding_Serialize_IsFirstBinding;
--- a/js/src/jsapi-tests/testXDR.cpp
+++ b/js/src/jsapi-tests/testXDR.cpp
@@ -41,17 +41,17 @@ FreezeThaw(JSContext *cx, JS::HandleScri
     // freeze
     uint32_t nbytes;
     void *memory = JS_EncodeScript(cx, script, &nbytes);
     if (!memory)
         return nullptr;
 
     // thaw
     JSScript *script2 = JS_DecodeScript(cx, memory, nbytes,
-                                        script->principals(), script->originPrincipals());
+                                        script->originPrincipals());
     js_free(memory);
     return script2;
 }
 
 static JSScript *
 GetScript(JSContext *cx, JS::HandleObject funobj)
 {
     JS::RootedFunction fun(cx, JS_GetObjectFunction(funobj));
@@ -65,17 +65,16 @@ FreezeThaw(JSContext *cx, JS::HandleObje
     uint32_t nbytes;
     void *memory = JS_EncodeInterpretedFunction(cx, funobj, &nbytes);
     if (!memory)
         return nullptr;
 
     // thaw
     JSScript *script = GetScript(cx, funobj);
     JSObject *funobj2 = JS_DecodeInterpretedFunction(cx, memory, nbytes,
-                                                     script->principals(),
                                                      script->originPrincipals());
     js_free(memory);
     return funobj2;
 }
 
 static TestJSPrincipals testPrincipal0(1);
 static TestJSPrincipals testPrincipal1(1);
 
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -6336,30 +6336,30 @@ JS_EncodeInterpretedFunction(JSContext *
     RootedObject funobj(cx, funobjArg);
     if (!encoder.codeFunction(&funobj))
         return nullptr;
     return encoder.forgetData(lengthp);
 }
 
 JS_PUBLIC_API(JSScript *)
 JS_DecodeScript(JSContext *cx, const void *data, uint32_t length,
-                JSPrincipals *principals, JSPrincipals *originPrincipals)
-{
-    XDRDecoder decoder(cx, data, length, principals, originPrincipals);
+                JSPrincipals *originPrincipals)
+{
+    XDRDecoder decoder(cx, data, length, originPrincipals);
     RootedScript script(cx);
     if (!decoder.codeScript(&script))
         return nullptr;
     return script;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_DecodeInterpretedFunction(JSContext *cx, const void *data, uint32_t length,
-                             JSPrincipals *principals, JSPrincipals *originPrincipals)
-{
-    XDRDecoder decoder(cx, data, length, principals, originPrincipals);
+                             JSPrincipals *originPrincipals)
+{
+    XDRDecoder decoder(cx, data, length, originPrincipals);
     RootedObject funobj(cx);
     if (!decoder.codeFunction(&funobj))
         return nullptr;
     return funobj;
 }
 
 JS_PUBLIC_API(bool)
 JS_PreventExtensions(JSContext *cx, JS::HandleObject obj)
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -4757,22 +4757,21 @@ class AutoHideScriptedCaller
 
 extern JS_PUBLIC_API(void *)
 JS_EncodeScript(JSContext *cx, JS::HandleScript script, uint32_t *lengthp);
 
 extern JS_PUBLIC_API(void *)
 JS_EncodeInterpretedFunction(JSContext *cx, JS::HandleObject funobj, uint32_t *lengthp);
 
 extern JS_PUBLIC_API(JSScript *)
-JS_DecodeScript(JSContext *cx, const void *data, uint32_t length,
-                JSPrincipals *principals, JSPrincipals *originPrincipals);
+JS_DecodeScript(JSContext *cx, const void *data, uint32_t length, JSPrincipals *originPrincipals);
 
 extern JS_PUBLIC_API(JSObject *)
 JS_DecodeInterpretedFunction(JSContext *cx, const void *data, uint32_t length,
-                             JSPrincipals *principals, JSPrincipals *originPrincipals);
+                             JSPrincipals *originPrincipals);
 
 namespace JS {
 
 /*
  * This callback represents a request by the JS engine to open for reading the
  * existing cache entry for the given global and char range that may contain a
  * module. If a cache entry exists, the callback shall return 'true' and return
  * the size, base address and an opaque file handle as outparams. If the
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1210,18 +1210,17 @@ Evaluate(JSContext *cx, unsigned argc, j
                     JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr,
                                          JSSMSG_CACHE_SINGLETON_FAILED);
                     return false;
                 }
                 JS::CompartmentOptionsRef(cx).cloneSingletonsOverride().set(true);
             }
 
             if (loadBytecode) {
-                script = JS_DecodeScript(cx, loadBuffer, loadLength, cx->compartment()->principals,
-                                         options.originPrincipals(cx));
+                script = JS_DecodeScript(cx, loadBuffer, loadLength, options.originPrincipals(cx));
             } else {
                 script = JS::Compile(cx, global, options, codeChars, codeLength);
             }
 
             if (!script)
                 return false;
         }
 
--- a/js/src/vm/Xdr.cpp
+++ b/js/src/vm/Xdr.cpp
@@ -117,18 +117,17 @@ XDRState<mode>::codeScript(MutableHandle
 template<XDRMode mode>
 bool
 XDRState<mode>::codeConstValue(MutableHandleValue vp)
 {
     return XDRScriptConst(this, vp);
 }
 
 XDRDecoder::XDRDecoder(JSContext *cx, const void *data, uint32_t length,
-                       JSPrincipals *principals, JSPrincipals *originPrincipals)
+                       JSPrincipals *originPrincipals)
   : XDRState<XDR_DECODE>(cx)
 {
     buf.setData(data, length);
-    this->principals_ = principals;
-    this->originPrincipals_ = NormalizeOriginPrincipals(principals, originPrincipals);
+    this->originPrincipals_ = originPrincipals;
 }
 
 template class js::XDRState<XDR_ENCODE>;
 template class js::XDRState<XDR_DECODE>;
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -90,21 +90,20 @@ class XDRBuffer {
  * XDR serialization state.  All data is encoded in little endian.
  */
 template <XDRMode mode>
 class XDRState {
   public:
     XDRBuffer buf;
 
   protected:
-    JSPrincipals *principals_;
     JSPrincipals *originPrincipals_;
 
     XDRState(JSContext *cx)
-      : buf(cx), principals_(nullptr), originPrincipals_(nullptr) {
+      : buf(cx), originPrincipals_(nullptr) {
     }
 
   public:
     JSContext *cx() const {
         return buf.cx();
     }
 
     JSPrincipals *originPrincipals() const {
@@ -251,15 +250,15 @@ class XDREncoder : public XDRState<XDR_E
         buf.setData(nullptr, 0);
         return data;
     }
 };
 
 class XDRDecoder : public XDRState<XDR_DECODE> {
   public:
     XDRDecoder(JSContext *cx, const void *data, uint32_t length,
-               JSPrincipals *principals, JSPrincipals *originPrincipals);
+               JSPrincipals *originPrincipals);
 
 };
 
 } /* namespace js */
 
 #endif /* vm_Xdr_h */
--- a/js/xpconnect/loader/mozJSLoaderUtils.cpp
+++ b/js/xpconnect/loader/mozJSLoaderUtils.cpp
@@ -23,17 +23,17 @@ ReadCachedScript(StartupCache* cache, ns
 {
     nsAutoArrayPtr<char> buf;
     uint32_t len;
     nsresult rv = cache->GetBuffer(PromiseFlatCString(uri).get(),
                                    getter_Transfers(buf), &len);
     if (NS_FAILED(rv))
         return rv; // don't warn since NOT_AVAILABLE is an ok error
 
-    scriptp.set(JS_DecodeScript(cx, buf, len, nsJSPrincipals::get(systemPrincipal), nullptr));
+    scriptp.set(JS_DecodeScript(cx, buf, len, nullptr));
     if (!scriptp)
         return NS_ERROR_OUT_OF_MEMORY;
     return NS_OK;
 }
 
 nsresult
 ReadCachedFunction(StartupCache* cache, nsACString &uri, JSContext *cx,
                    nsIPrincipal *systemPrincipal, JSFunction **functionp)
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -583,16 +583,24 @@ GetJunkScopeGlobal()
     // GetJunkScope would ideally never fail, currently it is not yet the case
     // unfortunately...(see Bug 874158)
     if (!junkScope)
         return nullptr;
     return GetNativeForGlobal(junkScope);
 }
 
 JSObject *
+GetCompilationScope()
+{
+    XPCJSRuntime *self = nsXPConnect::GetRuntimeInstance();
+    NS_ENSURE_TRUE(self, nullptr);
+    return self->GetCompilationScope();
+}
+
+JSObject *
 GetSafeJSContextGlobal()
 {
     return XPCJSRuntime::Get()->GetJSContextStack()->GetSafeJSContextGlobal();
 }
 
 nsGlobalWindow*
 WindowOrNull(JSObject *aObj)
 {
@@ -3040,16 +3048,17 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* 
    mWrappedJSToReleaseArray(),
    mNativesToReleaseArray(),
    mDoingFinalization(false),
    mVariantRoots(nullptr),
    mWrappedJSRoots(nullptr),
    mObjectHolderRoots(nullptr),
    mWatchdogManager(new WatchdogManager(MOZ_THIS_IN_INITIALIZER_LIST())),
    mJunkScope(MOZ_THIS_IN_INITIALIZER_LIST()->Runtime(), nullptr),
+   mCompilationScope(MOZ_THIS_IN_INITIALIZER_LIST()->Runtime(), nullptr),
    mAsyncSnowWhiteFreer(new AsyncFreeSnowWhite())
 {
     DOM_InitInterfaces();
 
     // these jsids filled in later when we have a JSContext to work with.
     mStrIDs[0] = JSID_VOID;
 
     MOZ_ASSERT(Runtime());
@@ -3471,23 +3480,42 @@ XPCJSRuntime::RemoveContextCallback(xpcC
 }
 
 JSObject *
 XPCJSRuntime::GetJunkScope()
 {
     if (!mJunkScope) {
         AutoSafeJSContext cx;
         SandboxOptions options;
-        options.sandboxName.AssignASCII("XPConnect Junk Compartment");
+        options.sandboxName.AssignLiteral("XPConnect Junk Compartment");
         RootedValue v(cx);
         nsresult rv = CreateSandboxObject(cx, &v, nsContentUtils::GetSystemPrincipal(), options);
         NS_ENSURE_SUCCESS(rv, nullptr);
 
         mJunkScope = js::UncheckedUnwrap(&v.toObject());
     }
     return mJunkScope;
 }
 
+JSObject *
+XPCJSRuntime::GetCompilationScope()
+{
+    if (!mCompilationScope) {
+        AutoSafeJSContext cx;
+        SandboxOptions options;
+        options.sandboxName.AssignLiteral("XPConnect Compilation Compartment");
+        options.invisibleToDebugger = true;
+        RootedValue v(cx);
+        nsresult rv = CreateSandboxObject(cx, &v, /* principal = */ nullptr, options);
+        NS_ENSURE_SUCCESS(rv, nullptr);
+
+        mCompilationScope = js::UncheckedUnwrap(&v.toObject());
+    }
+    return mCompilationScope;
+}
+
+
 void
-XPCJSRuntime::DeleteJunkScope()
+XPCJSRuntime::DeleteSingletonScopes()
 {
     mJunkScope = nullptr;
+    mCompilationScope = nullptr;
 }
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -83,17 +83,17 @@ nsXPConnect::nsXPConnect()
 
     char* reportableEnv = PR_GetEnv("MOZ_REPORT_ALL_JS_EXCEPTIONS");
     if (reportableEnv && *reportableEnv)
         gReportAllJSExceptions = 1;
 }
 
 nsXPConnect::~nsXPConnect()
 {
-    mRuntime->DeleteJunkScope();
+    mRuntime->DeleteSingletonScopes();
     mRuntime->DestroyJSContextStack();
 
     // In order to clean up everything properly, we need to GC twice: once now,
     // to clean anything that can go away on its own (like the Junk Scope, which
     // we unrooted above), and once after forcing a bunch of shutdown in
     // XPConnect, to clean the stuff we forcibly disconnected. The forced
     // shutdown code defaults to leaking in a number of situations, so we can't
     // get by with only the second GC. :-(
@@ -1355,17 +1355,18 @@ nsXPConnect::SetDebugModeWhenPossible(bo
 
 NS_IMETHODIMP
 nsXPConnect::NotifyDidPaint()
 {
     JS::NotifyDidPaint(GetRuntime()->Runtime());
     return NS_OK;
 }
 
-static const uint8_t HAS_PRINCIPALS_FLAG               = 1;
+// Note - We used to have HAS_PRINCIPALS_FLAG = 1 here, so reusing that flag
+// will require bumping the XDR version number.
 static const uint8_t HAS_ORIGIN_PRINCIPALS_FLAG        = 2;
 
 static nsresult
 WriteScriptOrFunction(nsIObjectOutputStream *stream, JSContext *cx,
                       JSScript *scriptArg, HandleObject functionObj)
 {
     // Exactly one of script or functionObj must be given
     MOZ_ASSERT(!scriptArg != !functionObj);
@@ -1377,35 +1378,27 @@ WriteScriptOrFunction(nsIObjectOutputStr
     }
 
     nsIPrincipal *principal =
         nsJSPrincipals::get(JS_GetScriptPrincipals(script));
     nsIPrincipal *originPrincipal =
         nsJSPrincipals::get(JS_GetScriptOriginPrincipals(script));
 
     uint8_t flags = 0;
-    if (principal)
-        flags |= HAS_PRINCIPALS_FLAG;
 
     // Optimize for the common case when originPrincipals == principals. As
     // originPrincipals is set to principals when the former is null we can
     // simply skip the originPrincipals when they are the same as principals.
     if (originPrincipal && originPrincipal != principal)
         flags |= HAS_ORIGIN_PRINCIPALS_FLAG;
 
     nsresult rv = stream->Write8(flags);
     if (NS_FAILED(rv))
         return rv;
 
-    if (flags & HAS_PRINCIPALS_FLAG) {
-        rv = stream->WriteObject(principal, true);
-        if (NS_FAILED(rv))
-            return rv;
-    }
-
     if (flags & HAS_ORIGIN_PRINCIPALS_FLAG) {
         rv = stream->WriteObject(originPrincipal, true);
         if (NS_FAILED(rv))
             return rv;
     }
 
     uint32_t size;
     void* data;
@@ -1434,27 +1427,16 @@ ReadScriptOrFunction(nsIObjectInputStrea
     // Exactly one of script or functionObj must be given
     MOZ_ASSERT(!scriptp != !functionObjp);
 
     uint8_t flags;
     nsresult rv = stream->Read8(&flags);
     if (NS_FAILED(rv))
         return rv;
 
-    nsJSPrincipals* principal = nullptr;
-    nsCOMPtr<nsIPrincipal> readPrincipal;
-    if (flags & HAS_PRINCIPALS_FLAG) {
-        nsCOMPtr<nsISupports> supports;
-        rv = stream->ReadObject(true, getter_AddRefs(supports));
-        if (NS_FAILED(rv))
-            return rv;
-        readPrincipal = do_QueryInterface(supports);
-        principal = nsJSPrincipals::get(readPrincipal);
-    }
-
     nsJSPrincipals* originPrincipal = nullptr;
     nsCOMPtr<nsIPrincipal> readOriginPrincipal;
     if (flags & HAS_ORIGIN_PRINCIPALS_FLAG) {
         nsCOMPtr<nsISupports> supports;
         rv = stream->ReadObject(true, getter_AddRefs(supports));
         if (NS_FAILED(rv))
             return rv;
         readOriginPrincipal = do_QueryInterface(supports);
@@ -1468,24 +1450,24 @@ ReadScriptOrFunction(nsIObjectInputStrea
 
     char* data;
     rv = stream->ReadBytes(size, &data);
     if (NS_FAILED(rv))
         return rv;
 
     {
         if (scriptp) {
-            JSScript *script = JS_DecodeScript(cx, data, size, principal, originPrincipal);
+            JSScript *script = JS_DecodeScript(cx, data, size, originPrincipal);
             if (!script)
                 rv = NS_ERROR_OUT_OF_MEMORY;
             else
                 *scriptp = script;
         } else {
             JSObject *funobj = JS_DecodeInterpretedFunction(cx, data, size,
-                                                            principal, originPrincipal);
+                                                            originPrincipal);
             if (!funobj)
                 rv = NS_ERROR_OUT_OF_MEMORY;
             else
                 *functionObjp = funobj;
         }
     }
 
     nsMemory::Free(data);
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -552,17 +552,18 @@ public:
     static bool InterruptCallback(JSContext *cx);
     static void OutOfMemoryCallback(JSContext *cx);
 
     size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
 
     AutoMarkingPtr**  GetAutoRootsAdr() {return &mAutoRoots;}
 
     JSObject* GetJunkScope();
-    void DeleteJunkScope();
+    JSObject* GetCompilationScope();
+    void DeleteSingletonScopes();
 
     PRTime GetWatchdogTimestamp(WatchdogTimestampCategory aCategory);
     void OnAfterProcessNextEvent() { mSlowScriptCheckpoint = mozilla::TimeStamp(); }
 
 private:
     XPCJSRuntime(); // no implementation
     XPCJSRuntime(nsXPConnect* aXPConnect);
 
@@ -593,16 +594,17 @@ private:
     XPCRootSetElem *mVariantRoots;
     XPCRootSetElem *mWrappedJSRoots;
     XPCRootSetElem *mObjectHolderRoots;
     nsTArray<xpcGCCallback> extraGCCallbacks;
     nsTArray<xpcContextCallback> extraContextCallbacks;
     nsRefPtr<WatchdogManager> mWatchdogManager;
     JS::GCSliceCallback mPrevGCSliceCallback;
     JS::PersistentRootedObject mJunkScope;
+    JS::PersistentRootedObject mCompilationScope;
     nsRefPtr<AsyncFreeSnowWhite> mAsyncSnowWhiteFreer;
 
     mozilla::TimeStamp mSlowScriptCheckpoint;
 
 #define XPCCCX_STRING_CACHE_SIZE 2
 
     mozilla::Maybe<nsString> mScratchStrings[XPCCCX_STRING_CACHE_SIZE];
 
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -431,16 +431,24 @@ GetJunkScope();
 /**
  * Returns the native global of the junk scope. See comment of GetJunkScope
  * about the conditions of using it.
  */
 nsIGlobalObject *
 GetJunkScopeGlobal();
 
 /**
+ * Shared compilation scope for XUL prototype documents and XBL
+ * precompilation. This compartment has a null principal. No code may run, and
+ * it is invisible to the debugger.
+ */
+JSObject *
+GetCompilationScope();
+
+/**
  * If |aObj| is a window, returns the associated nsGlobalWindow.
  * Otherwise, returns null.
  */
 nsGlobalWindow*
 WindowOrNull(JSObject *aObj);
 
 /*
  * Returns the dummy global associated with the SafeJSContext. Callers MUST