зеркало из https://github.com/mozilla/gecko-dev.git
Bug 897322 - Allow callers to manually fire OnNewGlobalObject when bootstrapping is complete. r=luke
This commit is contained in:
Родитель
fa44cda1c7
Коммит
6f87931f0a
|
@ -256,6 +256,7 @@ nsXBLDocGlobalObject::EnsureScriptEnvironment()
|
|||
.setInvisibleToDebugger(true);
|
||||
mJSObject = JS_NewGlobalObject(cx, &gSharedGlobalClass,
|
||||
nsJSPrincipals::get(GetPrincipal()),
|
||||
JS::DontFireOnNewGlobalHook,
|
||||
options);
|
||||
if (!mJSObject)
|
||||
return NS_OK;
|
||||
|
|
|
@ -767,7 +767,8 @@ nsXULPDGlobalObject::EnsureScriptEnvironment()
|
|||
.setInvisibleToDebugger(true);
|
||||
JS::Rooted<JSObject*> newGlob(cx,
|
||||
JS_NewGlobalObject(cx, &gSharedGlobalClass,
|
||||
nsJSPrincipals::get(GetPrincipal()), options));
|
||||
nsJSPrincipals::get(GetPrincipal()), JS::DontFireOnNewGlobalHook,
|
||||
options));
|
||||
if (!newGlob)
|
||||
return NS_OK;
|
||||
|
||||
|
|
|
@ -535,7 +535,8 @@ class ThreadLocalJSRuntime
|
|||
|
||||
JSAutoRequest ar(mContext);
|
||||
|
||||
mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, NULL);
|
||||
mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, NULL,
|
||||
JS::FireOnNewGlobalHook);
|
||||
NS_ENSURE_TRUE(mGlobal, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
js::SetDefaultObjectForContext(mContext, mGlobal);
|
||||
|
|
|
@ -955,7 +955,7 @@ CreateDedicatedWorkerGlobalScope(JSContext* aCx)
|
|||
options.setVersion(JSVERSION_LATEST);
|
||||
JS::Rooted<JSObject*> global(aCx,
|
||||
JS_NewGlobalObject(aCx, DedicatedWorkerGlobalScope::Class(),
|
||||
GetWorkerPrincipal(), options));
|
||||
GetWorkerPrincipal(), JS::DontFireOnNewGlobalHook, options));
|
||||
if (!global) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1033,6 +1033,8 @@ CreateDedicatedWorkerGlobalScope(JSContext* aCx)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
JS_FireOnNewGlobalObject(aCx, global);
|
||||
|
||||
return global;
|
||||
}
|
||||
|
||||
|
|
|
@ -3350,7 +3350,7 @@ CreateJSDGlobal(JSContext *aCx, JSClass *aClasp)
|
|||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
JSPrincipals *jsPrin = nsJSPrincipals::get(nullPrin);
|
||||
JSObject *global = JS_NewGlobalObject(aCx, aClasp, jsPrin);
|
||||
JS::RootedObject global(aCx, JS_NewGlobalObject(aCx, aClasp, jsPrin, JS::DontFireOnNewGlobalHook));
|
||||
NS_ENSURE_TRUE(global, nullptr);
|
||||
|
||||
// We have created a new global let's attach a private to it
|
||||
|
@ -3359,6 +3359,8 @@ CreateJSDGlobal(JSContext *aCx, JSClass *aClasp)
|
|||
new SandboxPrivate(nullPrin, global);
|
||||
JS_SetPrivate(global, sbp.forget().get());
|
||||
|
||||
JS_FireOnNewGlobalObject(aCx, global);
|
||||
|
||||
return global;
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,8 @@ main (int argc, const char **argv)
|
|||
/* Create the global object. */
|
||||
JS::CompartmentOptions options;
|
||||
options.setVersion(JSVERSION_LATEST);
|
||||
RootedObject global(cx, checkPtr(JS_NewGlobalObject(cx, &global_class, NULL, options)));
|
||||
RootedObject global(cx, checkPtr(JS_NewGlobalObject(cx, &global_class, NULL,
|
||||
JS::FireOnNewGlobalHook, options)));
|
||||
js::SetDefaultObjectForContext(cx, global);
|
||||
|
||||
JSAutoCompartment ac(cx, global);
|
||||
|
|
|
@ -67,9 +67,9 @@ BEGIN_TEST(testBug604087)
|
|||
{
|
||||
JS::RootedObject outerObj(cx, js::Wrapper::New(cx, global, global->getProto(), global,
|
||||
&OuterWrapper::singleton));
|
||||
JS::RootedObject compartment2(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
|
||||
JS::RootedObject compartment3(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
|
||||
JS::RootedObject compartment4(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
|
||||
JS::RootedObject compartment2(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL, JS::FireOnNewGlobalHook));
|
||||
JS::RootedObject compartment3(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL, JS::FireOnNewGlobalHook));
|
||||
JS::RootedObject compartment4(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL, JS::FireOnNewGlobalHook));
|
||||
|
||||
JS::RootedObject c2wrapper(cx, wrap(cx, outerObj, compartment2));
|
||||
CHECK(c2wrapper);
|
||||
|
|
|
@ -44,7 +44,7 @@ CustomMethod(JSContext *cx, unsigned argc, Value *vp)
|
|||
BEGIN_TEST(test_CallNonGenericMethodOnProxy)
|
||||
{
|
||||
// Create the first global object and compartment
|
||||
JS::RootedObject globalA(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
|
||||
JS::RootedObject globalA(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL, JS::FireOnNewGlobalHook));
|
||||
CHECK(globalA);
|
||||
|
||||
JS::RootedObject customA(cx, JS_NewObject(cx, &CustomClass, NULL, NULL));
|
||||
|
@ -60,7 +60,7 @@ BEGIN_TEST(test_CallNonGenericMethodOnProxy)
|
|||
|
||||
// Now create the second global object and compartment...
|
||||
{
|
||||
JS::RootedObject globalB(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
|
||||
JS::RootedObject globalB(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL, JS::FireOnNewGlobalHook));
|
||||
CHECK(globalB);
|
||||
|
||||
// ...and enter it.
|
||||
|
|
|
@ -43,7 +43,7 @@ BEGIN_TEST(testChromeBuffer)
|
|||
{
|
||||
JS_SetTrustedPrincipals(rt, &system_principals);
|
||||
|
||||
trusted_glob = JS_NewGlobalObject(cx, &global_class, &system_principals);
|
||||
trusted_glob = JS_NewGlobalObject(cx, &global_class, &system_principals, JS::FireOnNewGlobalHook);
|
||||
CHECK(trusted_glob);
|
||||
|
||||
if (!JS_AddNamedObjectRoot(cx, &trusted_glob, "trusted-global"))
|
||||
|
|
|
@ -149,7 +149,7 @@ END_TEST(testDebugger_throwHook)
|
|||
BEGIN_TEST(testDebugger_debuggerObjectVsDebugMode)
|
||||
{
|
||||
CHECK(JS_DefineDebuggerObject(cx, global));
|
||||
JS::RootedObject debuggee(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
|
||||
JS::RootedObject debuggee(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL, JS::FireOnNewGlobalHook));
|
||||
CHECK(debuggee);
|
||||
|
||||
{
|
||||
|
@ -189,7 +189,7 @@ BEGIN_TEST(testDebugger_newScriptHook)
|
|||
{
|
||||
// Test that top-level indirect eval fires the newScript hook.
|
||||
CHECK(JS_DefineDebuggerObject(cx, global));
|
||||
JS::RootedObject g(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
|
||||
JS::RootedObject g(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL, JS::FireOnNewGlobalHook));
|
||||
CHECK(g);
|
||||
{
|
||||
JSAutoCompartment ae(cx, g);
|
||||
|
|
|
@ -61,7 +61,7 @@ eval(const char *asciiChars, JSPrincipals *principals, JSPrincipals *originPrinc
|
|||
chars[i] = asciiChars[i];
|
||||
chars[len] = 0;
|
||||
|
||||
JS::RootedObject global(cx, JS_NewGlobalObject(cx, getGlobalClass(), principals));
|
||||
JS::RootedObject global(cx, JS_NewGlobalObject(cx, getGlobalClass(), principals, JS::FireOnNewGlobalHook));
|
||||
CHECK(global);
|
||||
JSAutoCompartment ac(cx, global);
|
||||
CHECK(JS_InitStandardClasses(cx, global));
|
||||
|
|
|
@ -56,7 +56,7 @@ JSObject * JSAPITest::createGlobal(JSPrincipals *principals)
|
|||
/* Create the global object. */
|
||||
JS::CompartmentOptions options;
|
||||
options.setVersion(JSVERSION_LATEST);
|
||||
global = JS_NewGlobalObject(cx, getGlobalClass(), principals, options);
|
||||
global = JS_NewGlobalObject(cx, getGlobalClass(), principals, JS::FireOnNewGlobalHook, options);
|
||||
if (!global)
|
||||
return NULL;
|
||||
JS_AddNamedObjectRoot(cx, &global, "test-global");
|
||||
|
|
|
@ -2907,6 +2907,7 @@ class AutoHoldZone
|
|||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_NewGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals,
|
||||
JS::OnNewGlobalHookOption hookOption,
|
||||
const JS::CompartmentOptions &options)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
|
@ -2944,16 +2945,23 @@ JS_NewGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals,
|
|||
if (!global)
|
||||
return NULL;
|
||||
|
||||
// This hook is infallible, because we can't really throw at this point.
|
||||
// The global object is already created and in the heap, which is
|
||||
// externally observable since the finalize hook will be called when the
|
||||
// global is GCed. This will eat OOM and slow script, but if that happens
|
||||
// we'll likely run up into them again soon in a fallible context.
|
||||
Debugger::onNewGlobalObject(cx, global);
|
||||
if (hookOption == JS::FireOnNewGlobalHook)
|
||||
JS_FireOnNewGlobalObject(cx, global);
|
||||
|
||||
return global;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_FireOnNewGlobalObject(JSContext *cx, JS::HandleObject global)
|
||||
{
|
||||
// This hook is infallible, because we don't really want arbitrary script
|
||||
// to be able to throw errors during delicate global creation routines.
|
||||
// This infallibility will eat OOM and slow script, but if that happens
|
||||
// we'll likely run up into them again soon in a fallible context.
|
||||
Rooted<js::GlobalObject*> globalObject(cx, &global->as<GlobalObject>());
|
||||
Debugger::onNewGlobalObject(cx, globalObject);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_NewObject(JSContext *cx, JSClass *jsclasp, JSObject *protoArg, JSObject *parentArg)
|
||||
{
|
||||
|
|
|
@ -3247,12 +3247,41 @@ struct JS_PUBLIC_API(CompartmentOptions) {
|
|||
}
|
||||
};
|
||||
|
||||
// During global creation, we fire notifications to callbacks registered
|
||||
// via the Debugger API. These callbacks are arbitrary script, and can touch
|
||||
// the global in arbitrary ways. When that happens, the global should not be
|
||||
// in a half-baked state. But this creates a problem for consumers that need
|
||||
// to set slots on the global to put it in a consistent state.
|
||||
//
|
||||
// This API provides a way for consumers to set slots atomically (immediately
|
||||
// after the global is created), before any debugger hooks are fired. It's
|
||||
// unfortunately on the clunky side, but that's the way the cookie crumbles.
|
||||
//
|
||||
// If callers have no additional state on the global to set up, they may pass
|
||||
// |FireOnNewGlobalHook| to JS_NewGlobalObject, which causes that function to
|
||||
// fire the hook as its final act before returning. Otherwise, callers should
|
||||
// pass |DontFireOnNewGlobalHook|, which means that they are responsible for
|
||||
// invoking JS_FireOnNewGlobalObject upon successfully creating the global. If
|
||||
// an error occurs and the operation aborts, callers should skip firing the
|
||||
// hook. But otherwise, callers must take care to fire the hook exactly once
|
||||
// before compiling any script in the global's scope (we have assertions in
|
||||
// place to enforce this). This lets us be sure that debugger clients never miss
|
||||
// breakpoints.
|
||||
enum OnNewGlobalHookOption {
|
||||
FireOnNewGlobalHook,
|
||||
DontFireOnNewGlobalHook
|
||||
};
|
||||
|
||||
} /* namespace JS */
|
||||
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_NewGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals,
|
||||
JS::OnNewGlobalHookOption hookOption,
|
||||
const JS::CompartmentOptions &options = JS::CompartmentOptions());
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_FireOnNewGlobalObject(JSContext *cx, JS::HandleObject global);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent);
|
||||
|
||||
|
|
|
@ -204,7 +204,8 @@ js::StartOffThreadParseScript(JSContext *cx, const CompileOptions &options,
|
|||
JS::CompartmentOptions compartmentOptions(cx->compartment()->options());
|
||||
compartmentOptions.setZone(JS::FreshZone);
|
||||
|
||||
JSObject *global = JS_NewGlobalObject(cx, &workerGlobalClass, NULL, compartmentOptions);
|
||||
JSObject *global = JS_NewGlobalObject(cx, &workerGlobalClass, NULL,
|
||||
JS::FireOnNewGlobalHook, compartmentOptions);
|
||||
if (!global)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -2507,7 +2507,8 @@ static JSClass sandbox_class = {
|
|||
static JSObject *
|
||||
NewSandbox(JSContext *cx, bool lazy)
|
||||
{
|
||||
RootedObject obj(cx, JS_NewGlobalObject(cx, &sandbox_class, NULL));
|
||||
RootedObject obj(cx, JS_NewGlobalObject(cx, &sandbox_class, NULL,
|
||||
JS::DontFireOnNewGlobalHook));
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
|
@ -2521,6 +2522,8 @@ NewSandbox(JSContext *cx, bool lazy)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
JS_FireOnNewGlobalObject(cx, obj);
|
||||
|
||||
if (!cx->compartment()->wrap(cx, obj.address()))
|
||||
return NULL;
|
||||
return obj;
|
||||
|
@ -4884,7 +4887,8 @@ DestroyContext(JSContext *cx, bool withGC)
|
|||
static JSObject *
|
||||
NewGlobalObject(JSContext *cx, JS::CompartmentOptions &options)
|
||||
{
|
||||
RootedObject glob(cx, JS_NewGlobalObject(cx, &global_class, NULL, options));
|
||||
RootedObject glob(cx, JS_NewGlobalObject(cx, &global_class, NULL,
|
||||
JS::DontFireOnNewGlobalHook, options));
|
||||
if (!glob)
|
||||
return NULL;
|
||||
|
||||
|
@ -4953,6 +4957,8 @@ NewGlobalObject(JSContext *cx, JS::CompartmentOptions &options)
|
|||
InitDOMObject(domProto);
|
||||
}
|
||||
|
||||
JS_FireOnNewGlobalObject(cx, glob);
|
||||
|
||||
return glob;
|
||||
}
|
||||
|
||||
|
|
|
@ -688,7 +688,8 @@ JSRuntime::initSelfHosting(JSContext *cx)
|
|||
{
|
||||
JS_ASSERT(!selfHostingGlobal_);
|
||||
RootedObject savedGlobal(cx, js::DefaultObjectForContextOrNull(cx));
|
||||
if (!(selfHostingGlobal_ = JS_NewGlobalObject(cx, &self_hosting_global_class, NULL)))
|
||||
if (!(selfHostingGlobal_ = JS_NewGlobalObject(cx, &self_hosting_global_class,
|
||||
NULL, JS::DontFireOnNewGlobalHook)))
|
||||
return false;
|
||||
JSAutoCompartment ac(cx, selfHostingGlobal_);
|
||||
js::SetDefaultObjectForContext(cx, selfHostingGlobal_);
|
||||
|
@ -704,6 +705,8 @@ JSRuntime::initSelfHosting(JSContext *cx)
|
|||
if (!JS_DefineFunctions(cx, shg, intrinsic_functions))
|
||||
return false;
|
||||
|
||||
JS_FireOnNewGlobalObject(cx, shg);
|
||||
|
||||
/*
|
||||
* In self-hosting mode, scripts emit JSOP_CALLINTRINSIC instead of
|
||||
* JSOP_NAME or JSOP_GNAME to access unbound variables. JSOP_CALLINTRINSIC
|
||||
|
|
|
@ -3368,6 +3368,8 @@ xpc_CreateSandboxObject(JSContext *cx, jsval *vp, nsISupports *prinOrSop, Sandbo
|
|||
// about:memory may use that information
|
||||
xpc::SetLocationForGlobal(sandbox, options.sandboxName);
|
||||
|
||||
JS_FireOnNewGlobalObject(cx, sandbox);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -177,6 +177,8 @@ XPCJSContextStack::GetSafeJSContext()
|
|||
if (NS_FAILED(xpc->InitClasses(mSafeJSContext, glob)))
|
||||
MOZ_CRASH();
|
||||
|
||||
JS_FireOnNewGlobalObject(mSafeJSContext, glob);
|
||||
|
||||
// Save it off so we can destroy it later.
|
||||
mOwnSafeJSContext = mSafeJSContext;
|
||||
|
||||
|
|
|
@ -407,8 +407,12 @@ XPCWrappedNative::WrapNewGlobal(xpcObjectHelper &nativeHelper,
|
|||
// Call the common creation finish routine. This does all of the bookkeeping
|
||||
// like inserting the wrapper into the wrapper map and setting up the wrapper
|
||||
// cache.
|
||||
return FinishCreate(scope, iface, nativeHelper.GetWrapperCache(),
|
||||
wrapper, wrappedGlobal);
|
||||
nsresult rv = FinishCreate(scope, iface, nativeHelper.GetWrapperCache(),
|
||||
wrapper, wrappedGlobal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JS_FireOnNewGlobalObject(cx, global);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -469,7 +469,8 @@ CreateGlobalObject(JSContext *cx, JSClass *clasp, nsIPrincipal *principal,
|
|||
MOZ_ASSERT(principal);
|
||||
|
||||
RootedObject global(cx,
|
||||
JS_NewGlobalObject(cx, clasp, nsJSPrincipals::get(principal), aOptions));
|
||||
JS_NewGlobalObject(cx, clasp, nsJSPrincipals::get(principal),
|
||||
JS::DontFireOnNewGlobalHook, aOptions));
|
||||
if (!global)
|
||||
return nullptr;
|
||||
JSAutoCompartment ac(cx, global);
|
||||
|
|
|
@ -540,7 +540,8 @@ private:
|
|||
JS::CompartmentOptions options;
|
||||
options.setZone(JS::SystemZone)
|
||||
.setVersion(JSVERSION_LATEST);
|
||||
mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, nullptr, options);
|
||||
mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, nullptr,
|
||||
JS::DontFireOnNewGlobalHook, options);
|
||||
NS_ENSURE_TRUE(mGlobal, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
JSAutoCompartment ac(mContext, mGlobal);
|
||||
|
@ -552,6 +553,9 @@ private:
|
|||
if (!JS_DefineFunctions(mContext, mGlobal, PACGlobalFunctions))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
JS::Rooted<JSObject*> rootedGlobal(mContext, mGlobal);
|
||||
JS_FireOnNewGlobalObject(mContext, rootedGlobal);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -522,7 +522,7 @@ int main(int argc, char** argv)
|
|||
};
|
||||
JSObject *glob = nullptr;
|
||||
if (use_js)
|
||||
glob = JS_NewGlobalObject(cx, &global_class, nullptr);
|
||||
glob = JS_NewGlobalObject(cx, &global_class, nullptr, JS::FireOnNewGlobalHook);
|
||||
if (!glob)
|
||||
use_js = false;
|
||||
mozilla::Maybe<JSAutoCompartment> ac;
|
||||
|
|
|
@ -63,7 +63,7 @@ SaveProfileTask::Run() {
|
|||
JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
|
||||
};
|
||||
JSObject *obj = JS_NewGlobalObject(cx, &c, NULL);
|
||||
JSObject *obj = JS_NewGlobalObject(cx, &c, NULL, JS::FireOnNewGlobalHook);
|
||||
|
||||
std::ofstream stream;
|
||||
stream.open(tmpPath.get());
|
||||
|
|
Загрузка…
Ссылка в новой задаче