mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 17:55:50 +00:00
Bug 1398601 - Support target objects in js::ExecuteInJSMEnvironment r=jorendorff
This allows js::ExecuteInJSMEnvironment to take a target object argument as used by the subscript loader. This adds WithEnvironments with a corresponding lexical on top of the ordinary NonSyntacticVariablesObject environment chain. MozReview-Commit-ID: JhHEfV92Zpv --HG-- extra : rebase_source : d1ef9564d30a25fd9e1cf1ca7e95bf40c780dcdf
This commit is contained in:
parent
39e87f69a6
commit
0260bcbae4
@ -445,19 +445,14 @@ js::IsAnyBuiltinEval(JSFunction* fun)
|
||||
}
|
||||
|
||||
static bool
|
||||
ExecuteInNonSyntacticGlobalInternal(JSContext* cx, HandleObject global, HandleScript scriptArg,
|
||||
HandleObject varEnv, HandleObject lexEnv)
|
||||
ExecuteInExtensibleLexicalEnvironment(JSContext* cx, HandleScript scriptArg, HandleObject env)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, global, varEnv, lexEnv);
|
||||
MOZ_ASSERT(global->is<GlobalObject>());
|
||||
MOZ_ASSERT(varEnv->is<NonSyntacticVariablesObject>());
|
||||
MOZ_ASSERT(IsExtensibleLexicalEnvironment(lexEnv));
|
||||
MOZ_ASSERT(lexEnv->enclosingEnvironment() == varEnv);
|
||||
assertSameCompartment(cx, env);
|
||||
MOZ_ASSERT(IsExtensibleLexicalEnvironment(env));
|
||||
MOZ_RELEASE_ASSERT(scriptArg->hasNonSyntacticScope());
|
||||
|
||||
RootedScript script(cx, scriptArg);
|
||||
Rooted<GlobalObject*> globalRoot(cx, &global->as<GlobalObject>());
|
||||
if (script->compartment() != cx->compartment()) {
|
||||
script = CloneGlobalScript(cx, ScopeKind::NonSyntactic, script);
|
||||
if (!script)
|
||||
@ -467,7 +462,7 @@ ExecuteInNonSyntacticGlobalInternal(JSContext* cx, HandleObject global, HandleSc
|
||||
}
|
||||
|
||||
RootedValue rval(cx);
|
||||
return ExecuteKernel(cx, script, *lexEnv, UndefinedValue(),
|
||||
return ExecuteKernel(cx, script, *env, UndefinedValue(),
|
||||
NullFramePtr() /* evalInFrame */, rval.address());
|
||||
}
|
||||
|
||||
@ -485,7 +480,7 @@ js::ExecuteInGlobalAndReturnScope(JSContext* cx, HandleObject global, HandleScri
|
||||
if (!lexEnv)
|
||||
return false;
|
||||
|
||||
if (!ExecuteInNonSyntacticGlobalInternal(cx, global, scriptArg, varEnv, lexEnv))
|
||||
if (!ExecuteInExtensibleLexicalEnvironment(cx, scriptArg, lexEnv))
|
||||
return false;
|
||||
|
||||
envArg.set(lexEnv);
|
||||
@ -509,14 +504,51 @@ js::NewJSMEnvironment(JSContext* cx)
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
js::ExecuteInJSMEnvironment(JSContext* cx, HandleScript scriptArg, HandleObject varEnv)
|
||||
{
|
||||
AutoObjectVector emptyChain(cx);
|
||||
return ExecuteInJSMEnvironment(cx, scriptArg, varEnv, emptyChain);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
js::ExecuteInJSMEnvironment(JSContext* cx, HandleScript scriptArg, HandleObject varEnv,
|
||||
AutoObjectVector& targetObj)
|
||||
{
|
||||
assertSameCompartment(cx, varEnv);
|
||||
MOZ_ASSERT(cx->compartment()->getNonSyntacticLexicalEnvironment(varEnv));
|
||||
MOZ_DIAGNOSTIC_ASSERT(scriptArg->noScriptRval());
|
||||
|
||||
RootedObject global(cx, &varEnv->global());
|
||||
RootedObject lexEnv(cx, JS_ExtensibleLexicalEnvironment(varEnv));
|
||||
RootedObject env(cx, JS_ExtensibleLexicalEnvironment(varEnv));
|
||||
|
||||
return ExecuteInNonSyntacticGlobalInternal(cx, global, scriptArg, varEnv, lexEnv);
|
||||
// If the Gecko subscript loader specifies target objects, we need to add
|
||||
// them to the environment. These are added after the NSVO environment.
|
||||
if (!targetObj.empty()) {
|
||||
// The environment chain will be as follows:
|
||||
// GlobalObject / BackstagePass
|
||||
// LexicalEnvironmentObject[this=global]
|
||||
// NonSyntacticVariablesObject (the JSMEnvironment)
|
||||
// LexicalEnvironmentObject[this=nsvo]
|
||||
// WithEnvironmentObject[target=targetObj]
|
||||
// LexicalEnvironmentObject[this=targetObj] (*)
|
||||
//
|
||||
// (*) This environment intentionally intercepts JSOP_GLOBALTHIS, but
|
||||
// not JSOP_FUNCTIONTHIS (which instead will fallback to the NSVO). I
|
||||
// don't make the rules, I just record them.
|
||||
|
||||
// Wrap the target objects in WithEnvironments.
|
||||
if (!js::CreateObjectsForEnvironmentChain(cx, targetObj, env, &env))
|
||||
return false;
|
||||
|
||||
// See CreateNonSyntacticEnvironmentChain
|
||||
if (!JSObject::setQualifiedVarObj(cx, env))
|
||||
return false;
|
||||
|
||||
// Create an extensible LexicalEnvironmentObject for target object
|
||||
env = cx->compartment()->getOrCreateNonSyntacticLexicalEnvironment(cx, env);
|
||||
if (!env)
|
||||
return false;
|
||||
}
|
||||
|
||||
return ExecuteInExtensibleLexicalEnvironment(cx, scriptArg, env);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSObject*)
|
||||
@ -536,3 +568,11 @@ js::GetJSMEnvironmentOfScriptedCaller(JSContext* cx)
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
js::IsJSMEnvironment(JSObject* obj)
|
||||
{
|
||||
// NOTE: This also returns true if the NonSyntacticVariablesObject was
|
||||
// created for reasons other than the JSM loader.
|
||||
return obj->is<NonSyntacticVariablesObject>();
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ BEGIN_TEST(testExecuteInJSMEnvironment_Basic)
|
||||
|
||||
JS::CompileOptions options(cx);
|
||||
options.setFileAndLine(__FILE__, __LINE__);
|
||||
options.setNoScriptRval(true);
|
||||
|
||||
JS::RootedScript script(cx);
|
||||
CHECK(JS::CompileForNonSyntacticScope(cx, options, src, sizeof(src)-1, &script));
|
||||
@ -82,6 +83,7 @@ BEGIN_TEST(testExecuteInJSMEnvironment_Callback)
|
||||
|
||||
JS::CompileOptions options(cx);
|
||||
options.setFileAndLine(__FILE__, __LINE__);
|
||||
options.setNoScriptRval(true);
|
||||
|
||||
JS::RootedScript script(cx);
|
||||
CHECK(JS::CompileForNonSyntacticScope(cx, options, src, sizeof(src)-1, &script));
|
||||
|
@ -2888,16 +2888,69 @@ extern JS_FRIEND_API(bool)
|
||||
ExecuteInGlobalAndReturnScope(JSContext* cx, JS::HandleObject obj, JS::HandleScript script,
|
||||
JS::MutableHandleObject scope);
|
||||
|
||||
// These functions are only for JSM component loader, please don't use this for anything else!
|
||||
// These functions are provided for the JSM component loader in Gecko.
|
||||
//
|
||||
// A 'JSMEnvironment' refers to an environment chain constructed for JSM loading
|
||||
// in a shared global. Internally it is a NonSyntacticVariablesObject with a
|
||||
// corresponding extensible LexicalEnvironmentObject that is accessible by
|
||||
// JS_ExtensibleLexicalEnvironment. The |this| value of that lexical environment
|
||||
// is the NSVO itself.
|
||||
//
|
||||
// Normal global environment (ES6): JSM "global" environment:
|
||||
//
|
||||
// * - extensible lexical environment
|
||||
// | (code runs in this environment;
|
||||
// | `let/const` bindings go here)
|
||||
// |
|
||||
// * - JSMEnvironment (=== `this`)
|
||||
// | (`var` bindings go here)
|
||||
// |
|
||||
// * - extensible lexical environment * - extensible lexical environment
|
||||
// | (code runs in this environment; | (empty)
|
||||
// | `let/const` bindings go here) |
|
||||
// | |
|
||||
// * - actual global (=== `this`) * - shared JSM global
|
||||
// (var bindings go here; and (Object, Math, etc. live here)
|
||||
// Object, Math, etc. live here)
|
||||
|
||||
// Allocate a new environment in current compartment that is compatible with JSM
|
||||
// shared loading.
|
||||
extern JS_FRIEND_API(JSObject*)
|
||||
NewJSMEnvironment(JSContext* cx);
|
||||
|
||||
// Execute the given script (copied into compartment if necessary) in the given
|
||||
// JSMEnvironment. The script must have been compiled for hasNonSyntacticScope.
|
||||
// The |jsmEnv| must have been previously allocated by NewJSMEnvironment.
|
||||
//
|
||||
// NOTE: The associated extensible lexical environment is reused.
|
||||
extern JS_FRIEND_API(bool)
|
||||
ExecuteInJSMEnvironment(JSContext* cx, JS::HandleScript script, JS::HandleObject nsvo);
|
||||
ExecuteInJSMEnvironment(JSContext* cx, JS::HandleScript script, JS::HandleObject jsmEnv);
|
||||
|
||||
// Additionally, target objects may be specified as required by the Gecko
|
||||
// subscript loader. These are wrapped in non-syntactic WithEnvironments and
|
||||
// temporarily placed on environment chain.
|
||||
//
|
||||
// See also: JS::CloneAndExecuteScript(...)
|
||||
extern JS_FRIEND_API(bool)
|
||||
ExecuteInJSMEnvironment(JSContext* cx, JS::HandleScript script, JS::HandleObject jsmEnv,
|
||||
JS::AutoObjectVector& targetObj);
|
||||
|
||||
// Used by native methods to determine the JSMEnvironment of caller if possible
|
||||
// by looking at stack frames. Returns nullptr if top frame isn't a scripted
|
||||
// caller in a JSM.
|
||||
//
|
||||
// NOTE: This may find NonSyntacticVariablesObject generated by other embedding
|
||||
// such as a Gecko FrameScript. Caller can check the compartment if needed.
|
||||
extern JS_FRIEND_API(JSObject*)
|
||||
GetJSMEnvironmentOfScriptedCaller(JSContext* cx);
|
||||
|
||||
// Determine if obj is a JSMEnvironment
|
||||
//
|
||||
// NOTE: This may return true for an NonSyntacticVariablesObject generated by
|
||||
// other embedding such as a Gecko FrameScript. Caller can check compartment.
|
||||
extern JS_FRIEND_API(bool)
|
||||
IsJSMEnvironment(JSObject* obj);
|
||||
|
||||
|
||||
#if defined(XP_WIN) && defined(_WIN64)
|
||||
// Parameters use void* types to avoid #including windows.h. The return value of
|
||||
|
Loading…
Reference in New Issue
Block a user