Merge m-i to m-c

This commit is contained in:
Phil Ringnalda 2014-04-20 20:04:23 -07:00
commit 245f6f4821
19 changed files with 71 additions and 539 deletions

View File

@ -2400,7 +2400,7 @@ nsXULPrototypeScript::Serialize(nsIObjectOutputStream* aStream,
{
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);
@ -2422,8 +2422,8 @@ nsXULPrototypeScript::Serialize(nsIObjectOutputStream* aStream,
// 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));
}
@ -2490,13 +2490,11 @@ nsXULPrototypeScript::Deserialize(nsIObjectInputStream* aStream,
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);
@ -2629,20 +2627,11 @@ nsXULPrototypeScript::Compile(const char16_t* aText,
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);

View File

@ -12,7 +12,6 @@
#include "nsIObjectOutputStream.h"
#include "nsIPrincipal.h"
#include "nsJSPrincipals.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsIScriptSecurityManager.h"
#include "nsIServiceManager.h"
@ -38,74 +37,8 @@ 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
@ -132,18 +65,8 @@ nsXULPrototypeDocument::Init()
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)
@ -156,7 +79,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULPrototypeDocument)
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]");
@ -191,35 +113,6 @@ NS_NewXULPrototypeDocument(nsXULPrototypeDocument** 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
@ -265,12 +158,6 @@ nsXULPrototypeDocument::Read(nsIObjectInputStream* aStream)
// 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;
@ -614,22 +501,10 @@ 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*
@ -692,118 +567,3 @@ nsXULPrototypeDocument::TraceProtos(JSTracer* aTrc, uint32_t aGCNumber)
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();
}

View File

@ -21,7 +21,6 @@ class nsIURI;
class nsNodeInfoManager;
class nsXULPrototypeElement;
class nsXULPrototypePI;
class nsXULPDGlobalObject;
namespace mozilla {
namespace dom {
@ -112,8 +111,6 @@ public:
nsNodeInfoManager *GetNodeInfoManager();
JSObject* GetCompilationGlobal();
void MarkInCCGeneration(uint32_t aCCGeneration);
NS_DECL_CYCLE_COLLECTION_CLASS(nsXULPrototypeDocument)
@ -126,8 +123,6 @@ protected:
nsTArray<nsRefPtr<nsXULPrototypePI> > mProcessingInstructions;
nsCOMArray<nsIURI> mStyleSheetReferences;
nsRefPtr<nsXULPDGlobalObject> mGlobalObject;
bool mLoaded;
nsTArray< nsRefPtr<mozilla::dom::XULDocument> > mPrototypeWaiters;
@ -143,13 +138,7 @@ protected:
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__

View File

@ -30,32 +30,26 @@ 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) {
@ -68,22 +62,18 @@ function setupPolicy() {
},
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 };
}
@ -98,7 +88,6 @@ function teardownPolicy() {
}
function beginTest() {
info("sending the beacon");
navigator.sendBeacon(beaconUrl, "bacon would have been a better name than beacon");
}

View File

@ -11,7 +11,6 @@
#include "nsIDocument.h"
#include "nsXBLPrototypeBinding.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptContext.h"
#include "nsIDOMDocument.h"
#include "nsIDOMScriptObjectFactory.h"
@ -41,186 +40,6 @@ 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
@ -260,7 +79,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXBLDocumentInfo)
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 &&
@ -272,7 +90,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXBLDocumentInfo)
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)
@ -305,9 +122,6 @@ nsXBLDocumentInfo::MarkInCCGeneration(uint32_t aGeneration)
if (mBindingTable) {
mBindingTable->EnumerateRead(UnmarkProtos, nullptr);
}
if (mGlobalObject) {
mGlobalObject->UnmarkCompilationGlobal();
}
}
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXBLDocumentInfo)
@ -358,10 +172,6 @@ nsXBLDocumentInfo::nsXBLDocumentInfo(nsIDocument* aDocument)
nsXBLDocumentInfo::~nsXBLDocumentInfo()
{
/* destructor code */
if (mGlobalObject) {
mGlobalObject->ClearGlobalObjectOwner(); // just in case
}
mozilla::DropJSObjects(this);
}
@ -546,27 +356,12 @@ nsXBLDocumentInfo::FlushSkinStylesheets()
}
}
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

View File

@ -45,8 +45,6 @@ public:
bool IsChrome() { return mIsChrome; }
JSObject* GetCompilationGlobal();
void MarkInCCGeneration(uint32_t aGeneration);
static nsresult ReadPrototypeBindings(nsIURI* aURI, nsXBLDocumentInfo** aDocInfo);
@ -54,7 +52,6 @@ public:
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsXBLDocumentInfo)
private:
void EnsureGlobalObject();
nsCOMPtr<nsIDocument> mDocument;
bool mScriptAccess;
bool mIsChrome;
@ -63,8 +60,6 @@ private:
// non-owning pointer to the first binding in the table
nsXBLPrototypeBinding* mFirstBinding;
nsRefPtr<nsXBLDocGlobalObject> mGlobalObject;
};
#ifdef DEBUG

View File

@ -201,7 +201,7 @@ nsXBLProtoImpl::CompilePrototypeMembers(nsXBLPrototypeBinding* aBinding)
// 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);

View File

@ -919,7 +919,7 @@ nsXBLPrototypeBinding::Read(nsIObjectInputStream* aStream,
}
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);
@ -1072,7 +1072,7 @@ nsXBLPrototypeBinding::Write(nsIObjectOutputStream* aStream)
// 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);

View File

@ -46,7 +46,7 @@ FreezeThaw(JSContext *cx, JS::HandleScript script)
// thaw
JSScript *script2 = JS_DecodeScript(cx, memory, nbytes,
script->principals(), script->originPrincipals());
script->originPrincipals());
js_free(memory);
return script2;
}
@ -70,7 +70,6 @@ FreezeThaw(JSContext *cx, JS::HandleObject funobj)
// thaw
JSScript *script = GetScript(cx, funobj);
JSObject *funobj2 = JS_DecodeInterpretedFunction(cx, memory, nbytes,
script->principals(),
script->originPrincipals());
js_free(memory);
return funobj2;

View File

@ -6341,9 +6341,9 @@ JS_EncodeInterpretedFunction(JSContext *cx, HandleObject funobjArg, uint32_t *le
JS_PUBLIC_API(JSScript *)
JS_DecodeScript(JSContext *cx, const void *data, uint32_t length,
JSPrincipals *principals, JSPrincipals *originPrincipals)
JSPrincipals *originPrincipals)
{
XDRDecoder decoder(cx, data, length, principals, originPrincipals);
XDRDecoder decoder(cx, data, length, originPrincipals);
RootedScript script(cx);
if (!decoder.codeScript(&script))
return nullptr;
@ -6352,9 +6352,9 @@ JS_DecodeScript(JSContext *cx, const void *data, uint32_t length,
JS_PUBLIC_API(JSObject *)
JS_DecodeInterpretedFunction(JSContext *cx, const void *data, uint32_t length,
JSPrincipals *principals, JSPrincipals *originPrincipals)
JSPrincipals *originPrincipals)
{
XDRDecoder decoder(cx, data, length, principals, originPrincipals);
XDRDecoder decoder(cx, data, length, originPrincipals);
RootedObject funobj(cx);
if (!decoder.codeFunction(&funobj))
return nullptr;

View File

@ -4762,12 +4762,11 @@ 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 {

View File

@ -1215,8 +1215,7 @@ Evaluate(JSContext *cx, unsigned argc, jsval *vp)
}
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);
}

View File

@ -122,12 +122,11 @@ XDRState<mode>::codeConstValue(MutableHandleValue 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>;

View File

@ -95,11 +95,10 @@ class XDRState {
XDRBuffer buf;
protected:
JSPrincipals *principals_;
JSPrincipals *originPrincipals_;
XDRState(JSContext *cx)
: buf(cx), principals_(nullptr), originPrincipals_(nullptr) {
: buf(cx), originPrincipals_(nullptr) {
}
public:
@ -256,7 +255,7 @@ class XDREncoder : public XDRState<XDR_ENCODE> {
class XDRDecoder : public XDRState<XDR_DECODE> {
public:
XDRDecoder(JSContext *cx, const void *data, uint32_t length,
JSPrincipals *principals, JSPrincipals *originPrincipals);
JSPrincipals *originPrincipals);
};

View File

@ -28,7 +28,7 @@ ReadCachedScript(StartupCache* cache, nsACString &uri, JSContext *cx,
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;

View File

@ -587,6 +587,14 @@ GetJunkScopeGlobal()
return GetNativeForGlobal(junkScope);
}
JSObject *
GetCompilationScope()
{
XPCJSRuntime *self = nsXPConnect::GetRuntimeInstance();
NS_ENSURE_TRUE(self, nullptr);
return self->GetCompilationScope();
}
JSObject *
GetSafeJSContextGlobal()
{
@ -3045,6 +3053,7 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
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();
@ -3476,7 +3485,7 @@ 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);
@ -3486,8 +3495,27 @@ XPCJSRuntime::GetJunkScope()
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;
}

View File

@ -88,7 +88,7 @@ nsXPConnect::nsXPConnect()
nsXPConnect::~nsXPConnect()
{
mRuntime->DeleteJunkScope();
mRuntime->DeleteSingletonScopes();
mRuntime->DestroyJSContextStack();
// In order to clean up everything properly, we need to GC twice: once now,
@ -1360,7 +1360,8 @@ nsXPConnect::NotifyDidPaint()
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
@ -1382,8 +1383,6 @@ WriteScriptOrFunction(nsIObjectOutputStream *stream, JSContext *cx,
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
@ -1395,12 +1394,6 @@ WriteScriptOrFunction(nsIObjectOutputStream *stream, JSContext *cx,
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))
@ -1439,17 +1432,6 @@ ReadScriptOrFunction(nsIObjectInputStream *stream, JSContext *cx,
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) {
@ -1473,14 +1455,14 @@ ReadScriptOrFunction(nsIObjectInputStream *stream, JSContext *cx,
{
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

View File

@ -557,7 +557,8 @@ public:
AutoMarkingPtr** GetAutoRootsAdr() {return &mAutoRoots;}
JSObject* GetJunkScope();
void DeleteJunkScope();
JSObject* GetCompilationScope();
void DeleteSingletonScopes();
PRTime GetWatchdogTimestamp(WatchdogTimestampCategory aCategory);
void OnAfterProcessNextEvent() { mSlowScriptCheckpoint = mozilla::TimeStamp(); }
@ -598,6 +599,7 @@ private:
nsRefPtr<WatchdogManager> mWatchdogManager;
JS::GCSliceCallback mPrevGCSliceCallback;
JS::PersistentRootedObject mJunkScope;
JS::PersistentRootedObject mCompilationScope;
nsRefPtr<AsyncFreeSnowWhite> mAsyncSnowWhiteFreer;
mozilla::TimeStamp mSlowScriptCheckpoint;

View File

@ -435,6 +435,14 @@ GetJunkScope();
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.