Merge m-i to m-c
authorPhil Ringnalda <philringnalda@gmail.com>
Sun, 20 Apr 2014 20:04:23 -0700
changeset 179780 9d9d84882a64fb084ca5e563ae9e7f192516feae
parent 179779 28dc0100f9b03b65d68679c528391397b5ffedb8 (current diff)
parent 179775 9dde6cd3739be8ccf00da7febaef98ef93e55507 (diff)
child 179787 5010b38abf18590cb17cf35e0cfaa933579cd748
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
milestone31.0a1
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