зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1193583 - Change the semantics of Debugger.evalInGlobal to be like executing a series of statements at the global level instead of like an indirect eval. (r=jimb)
This is to allow the web console to introduce and persist lexical bindings on the global level. If evalInGlobal were like an indirect eval, then no lexical bindings can escape the lexical environment of the eval.
This commit is contained in:
Родитель
256fcebeb7
Коммит
1194a532eb
|
@ -0,0 +1,13 @@
|
|||
var g = newGlobal();r
|
||||
var dbg = new Debugger;
|
||||
var gw = dbg.addDebuggee(g);
|
||||
|
||||
// executeInGlobal should be able to introduce and persist lexical bindings.
|
||||
assertEq(gw.evalInGlobal(`let x = 42; x;`).return, 42);
|
||||
assertEq(gw.evalInGlobal(`x;`).return, 42);
|
||||
|
||||
// By contrast, Debugger.Frame.eval is like direct eval, and shouldn't be able
|
||||
// to introduce new lexical bindings.
|
||||
dbg.onDebuggerStatement = function (frame) { frame.eval(`let y = 84;`); };
|
||||
g.eval(`debugger;`);
|
||||
assertEq(gw.evalInGlobal(`y;`).return, undefined);
|
|
@ -361,7 +361,7 @@ jit::CanEnterBaselineMethod(JSContext* cx, RunState& state)
|
|||
} else {
|
||||
MOZ_ASSERT(state.isExecute());
|
||||
ExecuteType type = state.asExecute()->type();
|
||||
if (type == EXECUTE_DEBUG || type == EXECUTE_DEBUG_GLOBAL) {
|
||||
if (type == EXECUTE_DEBUG) {
|
||||
JitSpew(JitSpew_BaselineAbort, "debugger frame");
|
||||
return Method_CantCompile;
|
||||
}
|
||||
|
|
|
@ -6344,9 +6344,21 @@ EvaluateInEnv(JSContext* cx, Handle<Env*> env, HandleValue thisv, AbstractFrameP
|
|||
Rooted<ScopeObject*> enclosingStaticScope(cx);
|
||||
if (!env->is<GlobalObject>())
|
||||
enclosingStaticScope = StaticNonSyntacticScopeObjects::create(cx, nullptr);
|
||||
Rooted<StaticEvalObject*> staticScope(cx, StaticEvalObject::create(cx, enclosingStaticScope));
|
||||
if (!staticScope)
|
||||
return false;
|
||||
|
||||
// Do not consider executeInGlobal{WithBindings} as an eval, but instead
|
||||
// as executing a series of statements at the global level. This is to
|
||||
// circumvent the fresh lexical scope that all eval have, so that the
|
||||
// users of executeInGlobal, like the web console, may add new bindings to
|
||||
// the global scope.
|
||||
Rooted<ScopeObject*> staticScope(cx);
|
||||
if (frame) {
|
||||
staticScope = StaticEvalObject::create(cx, enclosingStaticScope);
|
||||
if (!staticScope)
|
||||
return false;
|
||||
} else {
|
||||
staticScope = enclosingStaticScope;
|
||||
}
|
||||
|
||||
CompileOptions options(cx);
|
||||
options.setIsRunOnce(true)
|
||||
.setForEval(true)
|
||||
|
@ -6363,11 +6375,14 @@ EvaluateInEnv(JSContext* cx, Handle<Env*> env, HandleValue thisv, AbstractFrameP
|
|||
if (!script)
|
||||
return false;
|
||||
|
||||
if (script->strict())
|
||||
staticScope->setStrict();
|
||||
// Again, executeInGlobal is not considered eval.
|
||||
if (frame) {
|
||||
if (script->strict())
|
||||
staticScope->as<StaticEvalObject>().setStrict();
|
||||
script->setActiveEval();
|
||||
}
|
||||
|
||||
script->setActiveEval();
|
||||
ExecuteType type = !frame ? EXECUTE_DEBUG_GLOBAL : EXECUTE_DEBUG;
|
||||
ExecuteType type = !frame ? EXECUTE_GLOBAL : EXECUTE_DEBUG;
|
||||
return ExecuteKernel(cx, script, *env, thisv, NullValue(), type, frame, rval.address());
|
||||
}
|
||||
|
||||
|
|
|
@ -253,20 +253,6 @@ InterpreterFrame::epilogue(JSContext* cx)
|
|||
DebugScopes::onPopStrictEvalScope(this);
|
||||
} else if (isDirectEvalFrame()) {
|
||||
MOZ_ASSERT_IF(isDebuggerEvalFrame(), !IsSyntacticScope(scopeChain()));
|
||||
} else {
|
||||
/*
|
||||
* Debugger.Object.prototype.evalInGlobal creates indirect eval
|
||||
* frames scoped to the given global;
|
||||
* Debugger.Object.prototype.evalInGlobalWithBindings creates
|
||||
* indirect eval frames scoped to an object carrying the introduced
|
||||
* bindings.
|
||||
*/
|
||||
if (isDebuggerEvalFrame()) {
|
||||
MOZ_ASSERT(scopeChain()->is<GlobalObject>() ||
|
||||
scopeChain()->enclosingScope()->is<GlobalObject>());
|
||||
} else {
|
||||
MOZ_ASSERT(scopeChain()->is<GlobalObject>());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -283,8 +283,7 @@ enum ExecuteType {
|
|||
EXECUTE_MODULE = 0x4, /* == InterpreterFrame::GLOBAL */
|
||||
EXECUTE_DIRECT_EVAL = 0x8, /* == InterpreterFrame::EVAL */
|
||||
EXECUTE_INDIRECT_EVAL = 0x9, /* == InterpreterFrame::GLOBAL | EVAL */
|
||||
EXECUTE_DEBUG = 0x18, /* == InterpreterFrame::EVAL | DEBUGGER */
|
||||
EXECUTE_DEBUG_GLOBAL = 0x19 /* == InterpreterFrame::EVAL | DEBUGGER | GLOBAL */
|
||||
EXECUTE_DEBUG = 0x18, /* == InterpreterFrame::EVAL | DEBUGGER_EVAL */
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
Загрузка…
Ссылка в новой задаче