Bug 880917 - Generalize JS_NewGlobalObject API to take CompartmentOptions. r=luke

This will be useful for versioning, as well as JIT options and all the other
stuff that eventually needs to move out of the JSContext.
This commit is contained in:
Bobby Holley 2013-06-13 10:09:25 -07:00
parent f0bb406fe1
commit 3b2745a4be
21 changed files with 81 additions and 45 deletions

View File

@ -1117,9 +1117,11 @@ nsFrameScriptExecutor::InitTabChildGlobalInternal(nsISupports* aScope,
JS_SetContextPrivate(cx, aScope); JS_SetContextPrivate(cx, aScope);
JS::CompartmentOptions options;
options.setZone(JS::SystemZone);
nsresult rv = nsresult rv =
xpc->InitClassesWithNewWrappedGlobal(cx, aScope, mPrincipal, xpc->InitClassesWithNewWrappedGlobal(cx, aScope, mPrincipal,
flags, JS::SystemZone, getter_AddRefs(mGlobal)); flags, options, getter_AddRefs(mGlobal));
NS_ENSURE_SUCCESS(rv, false); NS_ENSURE_SUCCESS(rv, false);

View File

@ -284,9 +284,11 @@ nsXBLDocGlobalObject::EnsureScriptEnvironment()
// why - see bug 339647) // why - see bug 339647)
JS_SetErrorReporter(cx, XBL_ProtoErrorReporter); JS_SetErrorReporter(cx, XBL_ProtoErrorReporter);
JS::CompartmentOptions options;
options.setZone(JS::SystemZone);
mJSObject = JS_NewGlobalObject(cx, &gSharedGlobalClass, mJSObject = JS_NewGlobalObject(cx, &gSharedGlobalClass,
nsJSPrincipals::get(GetPrincipal()), nsJSPrincipals::get(GetPrincipal()),
JS::SystemZone); options);
if (!mJSObject) if (!mJSObject)
return NS_OK; return NS_OK;

View File

@ -762,9 +762,11 @@ nsXULPDGlobalObject::EnsureScriptEnvironment()
// will re-fetch the global and set it up in our language globals array. // will re-fetch the global and set it up in our language globals array.
{ {
AutoPushJSContext cx(ctxNew->GetNativeContext()); AutoPushJSContext cx(ctxNew->GetNativeContext());
JS::CompartmentOptions options;
options.setZone(JS::SystemZone);
JS::Rooted<JSObject*> newGlob(cx, JS::Rooted<JSObject*> newGlob(cx,
JS_NewGlobalObject(cx, &gSharedGlobalClass, JS_NewGlobalObject(cx, &gSharedGlobalClass,
nsJSPrincipals::get(GetPrincipal()), JS::SystemZone)); nsJSPrincipals::get(GetPrincipal()), options));
if (!newGlob) if (!newGlob)
return NS_OK; return NS_OK;

View File

@ -2120,10 +2120,10 @@ CreateNativeGlobalForInner(JSContext* aCx,
if (aNewInner->GetOuterWindow()) { if (aNewInner->GetOuterWindow()) {
top = aNewInner->GetTop(); top = aNewInner->GetTop();
} }
JS::ZoneSpecifier zoneSpec = JS::FreshZone; JS::CompartmentOptions options;
if (top) { if (top) {
if (top->GetGlobalJSObject()) { if (top->GetGlobalJSObject()) {
zoneSpec = JS::SameZoneAs(top->GetGlobalJSObject()); options.zoneSpec = JS::SameZoneAs(top->GetGlobalJSObject());
} }
} }
@ -2139,7 +2139,7 @@ CreateNativeGlobalForInner(JSContext* aCx,
nsRefPtr<nsIXPConnectJSObjectHolder> jsholder; nsRefPtr<nsIXPConnectJSObjectHolder> jsholder;
nsresult rv = xpc->InitClassesWithNewWrappedGlobal( nsresult rv = xpc->InitClassesWithNewWrappedGlobal(
aCx, ToSupports(aNewInner), aCx, ToSupports(aNewInner),
aPrincipal, flags, zoneSpec, getter_AddRefs(jsholder)); aPrincipal, flags, options, getter_AddRefs(jsholder));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
MOZ_ASSERT(jsholder); MOZ_ASSERT(jsholder);

View File

@ -783,11 +783,13 @@ XPCShellEnvironment::Init()
return false; return false;
} }
JS::CompartmentOptions options;
options.setZone(JS::SystemZone);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = xpc->InitClassesWithNewWrappedGlobal(cx, rv = xpc->InitClassesWithNewWrappedGlobal(cx,
static_cast<nsIGlobalObject *>(backstagePass), static_cast<nsIGlobalObject *>(backstagePass),
principal, 0, principal, 0,
JS::SystemZone, options,
getter_AddRefs(holder)); getter_AddRefs(holder));
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
NS_ERROR("InitClassesWithNewWrappedGlobal failed!"); NS_ERROR("InitClassesWithNewWrappedGlobal failed!");

View File

@ -941,7 +941,8 @@ JSRuntime::init(uint32_t maxbytes)
if (!atomsZone) if (!atomsZone)
return false; return false;
ScopedJSDeletePtr<JSCompartment> atomsCompartment(new_<JSCompartment>(atomsZone.get())); JS::CompartmentOptions options;
ScopedJSDeletePtr<JSCompartment> atomsCompartment(new_<JSCompartment>(atomsZone.get(), options));
if (!atomsCompartment || !atomsCompartment->init(NULL)) if (!atomsCompartment || !atomsCompartment->init(NULL))
return false; return false;
@ -3427,7 +3428,8 @@ class AutoHoldZone
}; };
JS_PUBLIC_API(JSObject *) JS_PUBLIC_API(JSObject *)
JS_NewGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals, JS::ZoneSpecifier zoneSpec) JS_NewGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals,
const JS::CompartmentOptions &options)
{ {
AssertHeapIsIdle(cx); AssertHeapIsIdle(cx);
CHECK_REQUEST(cx); CHECK_REQUEST(cx);
@ -3436,18 +3438,18 @@ JS_NewGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals, JS::
JSRuntime *rt = cx->runtime(); JSRuntime *rt = cx->runtime();
Zone *zone; Zone *zone;
if (zoneSpec == JS::SystemZone) if (options.zoneSpec == JS::SystemZone)
zone = rt->systemZone; zone = rt->systemZone;
else if (zoneSpec == JS::FreshZone) else if (options.zoneSpec == JS::FreshZone)
zone = NULL; zone = NULL;
else else
zone = ((JSObject *)zoneSpec)->zone(); zone = ((JSObject *)options.zoneSpec)->zone();
JSCompartment *compartment = NewCompartment(cx, zone, principals); JSCompartment *compartment = NewCompartment(cx, zone, principals, options);
if (!compartment) if (!compartment)
return NULL; return NULL;
if (zoneSpec == JS::SystemZone) { if (options.zoneSpec == JS::SystemZone) {
rt->systemZone = compartment->zone(); rt->systemZone = compartment->zone();
rt->systemZone->isSystem = true; rt->systemZone->isSystem = true;
} }

View File

@ -3144,11 +3144,20 @@ SameZoneAs(JSObject *obj)
return ZoneSpecifier(obj); return ZoneSpecifier(obj);
} }
struct JS_PUBLIC_API(CompartmentOptions) {
ZoneSpecifier zoneSpec;
explicit CompartmentOptions() : zoneSpec(JS::FreshZone)
{}
CompartmentOptions &setZone(ZoneSpecifier spec) { zoneSpec = spec; return *this; }
};
} /* namespace JS */ } /* namespace JS */
extern JS_PUBLIC_API(JSObject *) extern JS_PUBLIC_API(JSObject *)
JS_NewGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals, JS_NewGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals,
JS::ZoneSpecifier zoneSpec = JS::FreshZone); const JS::CompartmentOptions &options = JS::CompartmentOptions());
extern JS_PUBLIC_API(JSObject *) extern JS_PUBLIC_API(JSObject *)
JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent); JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent);

View File

@ -30,8 +30,9 @@ using namespace js::gc;
using mozilla::DebugOnly; using mozilla::DebugOnly;
JSCompartment::JSCompartment(Zone *zone) JSCompartment::JSCompartment(Zone *zone, const JS::CompartmentOptions &options = JS::CompartmentOptions())
: zone_(zone), : zone_(zone),
options_(options),
rt(zone->rt), rt(zone->rt),
principals(NULL), principals(NULL),
isSystem(false), isSystem(false),

View File

@ -123,6 +123,7 @@ class DebugScopes;
struct JSCompartment struct JSCompartment
{ {
JS::Zone *zone_; JS::Zone *zone_;
JS::CompartmentOptions options_;
JSRuntime *rt; JSRuntime *rt;
JSPrincipals *principals; JSPrincipals *principals;
@ -144,6 +145,8 @@ struct JSCompartment
JS::Zone *zone() { return zone_; } JS::Zone *zone() { return zone_; }
const JS::Zone *zone() const { return zone_; } const JS::Zone *zone() const { return zone_; }
JS::CompartmentOptions &options() { return options_; }
const JS::CompartmentOptions &options() const { return options_; }
/* /*
* Nb: global_ might be NULL, if (a) it's the atoms compartment, or (b) the * Nb: global_ might be NULL, if (a) it's the atoms compartment, or (b) the
@ -259,7 +262,7 @@ struct JSCompartment
unsigned debugModeBits; // see debugMode() below unsigned debugModeBits; // see debugMode() below
public: public:
JSCompartment(JS::Zone *zone); JSCompartment(JS::Zone *zone, const JS::CompartmentOptions &options);
~JSCompartment(); ~JSCompartment();
bool init(JSContext *cx); bool init(JSContext *cx);

View File

@ -4699,7 +4699,8 @@ AutoPrepareForTracing::AutoPrepareForTracing(JSRuntime *rt)
} }
JSCompartment * JSCompartment *
js::NewCompartment(JSContext *cx, Zone *zone, JSPrincipals *principals) js::NewCompartment(JSContext *cx, Zone *zone, JSPrincipals *principals,
const JS::CompartmentOptions &options)
{ {
JSRuntime *rt = cx->runtime(); JSRuntime *rt = cx->runtime();
JS_AbortIfWrongThread(rt); JS_AbortIfWrongThread(rt);
@ -4721,7 +4722,7 @@ js::NewCompartment(JSContext *cx, Zone *zone, JSPrincipals *principals)
zone->isSystem = principals && principals == trusted; zone->isSystem = principals && principals == trusted;
} }
ScopedJSDeletePtr<JSCompartment> compartment(cx->new_<JSCompartment>(zone)); ScopedJSDeletePtr<JSCompartment> compartment(cx->new_<JSCompartment>(zone, options));
if (!compartment || !compartment->init(cx)) if (!compartment || !compartment->init(cx))
return NULL; return NULL;

View File

@ -1201,7 +1201,8 @@ js_FinalizeStringRT(JSRuntime *rt, JSString *str);
namespace js { namespace js {
JSCompartment * JSCompartment *
NewCompartment(JSContext *cx, JS::Zone *zone, JSPrincipals *principals); NewCompartment(JSContext *cx, JS::Zone *zone, JSPrincipals *principals,
const JS::CompartmentOptions &options);
namespace gc { namespace gc {

View File

@ -4799,8 +4799,9 @@ DestroyContext(JSContext *cx, bool withGC)
static JSObject * static JSObject *
NewGlobalObject(JSContext *cx, JSObject *sameZoneAs) NewGlobalObject(JSContext *cx, JSObject *sameZoneAs)
{ {
JS::ZoneSpecifier spec = sameZoneAs ? JS::SameZoneAs(sameZoneAs) : JS::FreshZone; JS::CompartmentOptions options;
RootedObject glob(cx, JS_NewGlobalObject(cx, &global_class, NULL, spec)); options.setZone(sameZoneAs ? JS::SameZoneAs(sameZoneAs) : JS::FreshZone);
RootedObject glob(cx, JS_NewGlobalObject(cx, &global_class, NULL, options));
if (!glob) if (!glob)
return NULL; return NULL;

View File

@ -44,7 +44,7 @@ class nsWrapperCache;
[ref] native nsCCTraversalCallbackRef(nsCycleCollectionTraversalCallback); [ref] native nsCCTraversalCallbackRef(nsCycleCollectionTraversalCallback);
[ptr] native nsAXPCNativeCallContextPtr(nsAXPCNativeCallContext); [ptr] native nsAXPCNativeCallContextPtr(nsAXPCNativeCallContext);
[ptr] native nsWrapperCachePtr(nsWrapperCache); [ptr] native nsWrapperCachePtr(nsWrapperCache);
native ZoneSpecifier(uintptr_t); [ref] native JSCompartmentOptions(JS::CompartmentOptions);
[ref] native JSCallArgsRef(const JS::CallArgs); [ref] native JSCallArgsRef(const JS::CallArgs);
native JSHandleId(JS::HandleId); native JSHandleId(JS::HandleId);
@ -291,7 +291,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports
{ 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } } { 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
%} %}
[uuid(2950bc62-ba03-4465-9685-a0eec9e188c2)] [uuid(bd61342d-8a88-4f23-8d2d-1782fff02d26)]
interface nsIXPConnect : nsISupports interface nsIXPConnect : nsISupports
{ {
%{ C++ %{ C++
@ -318,14 +318,15 @@ interface nsIXPConnect : nsISupports
* compartment. Can be null if not on the main thread. * compartment. Can be null if not on the main thread.
* @param aFlags one of the flags below specifying what options this * @param aFlags one of the flags below specifying what options this
* global object wants. * global object wants.
* @param aOptions JSAPI-specific options for the new compartment.
*/ */
nsIXPConnectJSObjectHolder nsIXPConnectJSObjectHolder
initClassesWithNewWrappedGlobal( initClassesWithNewWrappedGlobal(
in JSContextPtr aJSContext, in JSContextPtr aJSContext,
in nsISupports aCOMObj, in nsISupports aCOMObj,
in nsIPrincipal aPrincipal, in nsIPrincipal aPrincipal,
in uint32_t aFlags, in uint32_t aFlags,
in ZoneSpecifier aZoneSpec); in JSCompartmentOptions aOptions);
const uint32_t INIT_JS_STANDARD_CLASSES = 1 << 0; const uint32_t INIT_JS_STANDARD_CLASSES = 1 << 0;
// Free bit here! // Free bit here!

View File

@ -726,11 +726,13 @@ mozJSComponentLoader::PrepareObjectForLocation(JSCLContextHelper& aCx,
rv = NS_NewBackstagePass(getter_AddRefs(backstagePass)); rv = NS_NewBackstagePass(getter_AddRefs(backstagePass));
NS_ENSURE_SUCCESS(rv, nullptr); NS_ENSURE_SUCCESS(rv, nullptr);
JS::CompartmentOptions options;
options.setZone(JS::SystemZone);
rv = xpc->InitClassesWithNewWrappedGlobal(aCx, rv = xpc->InitClassesWithNewWrappedGlobal(aCx,
static_cast<nsIGlobalObject *>(backstagePass), static_cast<nsIGlobalObject *>(backstagePass),
mSystemPrincipal, mSystemPrincipal,
0, 0,
JS::SystemZone, options,
getter_AddRefs(holder)); getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, nullptr); NS_ENSURE_SUCCESS(rv, nullptr);

View File

@ -1634,12 +1634,14 @@ main(int argc, char **argv, char **envp)
return 1; return 1;
} }
JS::CompartmentOptions options;
options.setZone(JS::SystemZone);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder; nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = xpc->InitClassesWithNewWrappedGlobal(cx, rv = xpc->InitClassesWithNewWrappedGlobal(cx,
static_cast<nsIGlobalObject *>(backstagePass), static_cast<nsIGlobalObject *>(backstagePass),
systemprincipal, systemprincipal,
0, 0,
JS::SystemZone, options,
getter_AddRefs(holder)); getter_AddRefs(holder));
if (NS_FAILED(rv)) if (NS_FAILED(rv))
return 1; return 1;

View File

@ -3279,10 +3279,12 @@ xpc_CreateSandboxObject(JSContext *cx, jsval *vp, nsISupports *prinOrSop, Sandbo
MOZ_ASSERT(principal); MOZ_ASSERT(principal);
} }
JS::ZoneSpecifier zoneSpec = options.sameZoneAs JS::CompartmentOptions compartmentOptions;
compartmentOptions.setZone(options.sameZoneAs
? JS::SameZoneAs(js::UncheckedUnwrap(options.sameZoneAs)) ? JS::SameZoneAs(js::UncheckedUnwrap(options.sameZoneAs))
: JS::SystemZone; : JS::SystemZone);
RootedObject sandbox(cx, xpc::CreateGlobalObject(cx, &SandboxClass, principal, zoneSpec)); RootedObject sandbox(cx, xpc::CreateGlobalObject(cx, &SandboxClass,
principal, compartmentOptions));
if (!sandbox) if (!sandbox)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;

View File

@ -167,7 +167,9 @@ XPCJSContextStack::GetSafeJSContext()
JS_SetErrorReporter(mSafeJSContext, mozJSLoaderErrorReporter); JS_SetErrorReporter(mSafeJSContext, mozJSLoaderErrorReporter);
glob = xpc::CreateGlobalObject(mSafeJSContext, &global_class, principal, JS::SystemZone); JS::CompartmentOptions options;
options.setZone(JS::SystemZone);
glob = xpc::CreateGlobalObject(mSafeJSContext, &global_class, principal, options);
if (glob) { if (glob) {
// Make sure the context is associated with a proper compartment // Make sure the context is associated with a proper compartment

View File

@ -285,7 +285,7 @@ FinishCreate(XPCWrappedNativeScope* Scope,
nsresult nsresult
XPCWrappedNative::WrapNewGlobal(xpcObjectHelper &nativeHelper, XPCWrappedNative::WrapNewGlobal(xpcObjectHelper &nativeHelper,
nsIPrincipal *principal, bool initStandardClasses, nsIPrincipal *principal, bool initStandardClasses,
ZoneSpecifier zoneSpec, JS::CompartmentOptions& aOptions,
XPCWrappedNative **wrappedGlobal) XPCWrappedNative **wrappedGlobal)
{ {
AutoJSContext cx; AutoJSContext cx;
@ -315,7 +315,7 @@ XPCWrappedNative::WrapNewGlobal(xpcObjectHelper &nativeHelper,
MOZ_ASSERT(clasp->flags & JSCLASS_IS_GLOBAL); MOZ_ASSERT(clasp->flags & JSCLASS_IS_GLOBAL);
// Create the global. // Create the global.
RootedObject global(cx, xpc::CreateGlobalObject(cx, clasp, principal, zoneSpec)); RootedObject global(cx, xpc::CreateGlobalObject(cx, clasp, principal, aOptions));
if (!global) if (!global)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
XPCWrappedNativeScope *scope = GetCompartmentPrivate(global)->scope; XPCWrappedNativeScope *scope = GetCompartmentPrivate(global)->scope;

View File

@ -981,7 +981,7 @@ namespace xpc {
JSObject* JSObject*
CreateGlobalObject(JSContext *cx, JSClass *clasp, nsIPrincipal *principal, CreateGlobalObject(JSContext *cx, JSClass *clasp, nsIPrincipal *principal,
JS::ZoneSpecifier zoneSpec) JS::CompartmentOptions& aOptions)
{ {
// Make sure that Type Inference is enabled for everything non-chrome. // Make sure that Type Inference is enabled for everything non-chrome.
// Sandboxes and compilation scopes are exceptions. See bug 744034. // Sandboxes and compilation scopes are exceptions. See bug 744034.
@ -991,7 +991,7 @@ CreateGlobalObject(JSContext *cx, JSClass *clasp, nsIPrincipal *principal,
MOZ_ASSERT(principal); MOZ_ASSERT(principal);
RootedObject global(cx, RootedObject global(cx,
JS_NewGlobalObject(cx, clasp, nsJSPrincipals::get(principal), zoneSpec)); JS_NewGlobalObject(cx, clasp, nsJSPrincipals::get(principal), aOptions));
if (!global) if (!global)
return nullptr; return nullptr;
JSAutoCompartment ac(cx, global); JSAutoCompartment ac(cx, global);
@ -1027,7 +1027,7 @@ nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext,
nsISupports *aCOMObj, nsISupports *aCOMObj,
nsIPrincipal * aPrincipal, nsIPrincipal * aPrincipal,
uint32_t aFlags, uint32_t aFlags,
JS::ZoneSpecifier zoneSpec, JS::CompartmentOptions& aOptions,
nsIXPConnectJSObjectHolder **_retval) nsIXPConnectJSObjectHolder **_retval)
{ {
NS_ASSERTION(aJSContext, "bad param"); NS_ASSERTION(aJSContext, "bad param");
@ -1046,8 +1046,7 @@ nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext,
nsresult rv = nsresult rv =
XPCWrappedNative::WrapNewGlobal(helper, aPrincipal, XPCWrappedNative::WrapNewGlobal(helper, aPrincipal,
aFlags & nsIXPConnect::INIT_JS_STANDARD_CLASSES, aFlags & nsIXPConnect::INIT_JS_STANDARD_CLASSES,
zoneSpec, aOptions, getter_AddRefs(wrappedGlobal));
getter_AddRefs(wrappedGlobal));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// Grab a copy of the global and enter its compartment. // Grab a copy of the global and enter its compartment.

View File

@ -2471,7 +2471,7 @@ public:
static nsresult static nsresult
WrapNewGlobal(xpcObjectHelper &nativeHelper, WrapNewGlobal(xpcObjectHelper &nativeHelper,
nsIPrincipal *principal, bool initStandardClasses, nsIPrincipal *principal, bool initStandardClasses,
JS::ZoneSpecifier zoneSpec, JS::CompartmentOptions& aOptions,
XPCWrappedNative **wrappedGlobal); XPCWrappedNative **wrappedGlobal);
static nsresult static nsresult
@ -3796,7 +3796,7 @@ struct SandboxOptions {
JSObject * JSObject *
CreateGlobalObject(JSContext *cx, JSClass *clasp, nsIPrincipal *principal, CreateGlobalObject(JSContext *cx, JSClass *clasp, nsIPrincipal *principal,
JS::ZoneSpecifier zoneSpec); JS::CompartmentOptions& aOptions);
} }
// Helper for creating a sandbox object to use for evaluating // Helper for creating a sandbox object to use for evaluating

View File

@ -536,7 +536,9 @@ private:
JSAutoRequest ar(mContext); JSAutoRequest ar(mContext);
mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, nullptr, JS::SystemZone); JS::CompartmentOptions options;
options.setZone(JS::SystemZone);
mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, nullptr, options);
NS_ENSURE_TRUE(mGlobal, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_TRUE(mGlobal, NS_ERROR_OUT_OF_MEMORY);
JS_SetGlobalObject(mContext, mGlobal); JS_SetGlobalObject(mContext, mGlobal);