зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1191177 - Kill staticLevel. (r=efaust)
This commit is contained in:
Родитель
0d661e6913
Коммит
7ed7ff522b
|
@ -9815,7 +9815,7 @@ ParseFunction(ModuleCompiler& m, ParseNode** fnOut)
|
|||
|
||||
Directives newDirectives = directives;
|
||||
AsmJSParseContext funpc(&m.parser(), outerpc, fn, funbox, &newDirectives,
|
||||
outerpc->staticLevel + 1, /* blockScopeDepth = */ 0);
|
||||
/* blockScopeDepth = */ 0);
|
||||
if (!funpc.init(m.parser()))
|
||||
return false;
|
||||
|
||||
|
|
|
@ -260,11 +260,9 @@ EvalKernel(JSContext* cx, const CallArgs& args, EvalType evalType, AbstractFrame
|
|||
// Per ES5, indirect eval runs in the global scope. (eval is specified this
|
||||
// way so that the compiler can make assumptions about what bindings may or
|
||||
// may not exist in the current frame if it doesn't see 'eval'.)
|
||||
unsigned staticLevel;
|
||||
RootedValue thisv(cx);
|
||||
if (evalType == DIRECT_EVAL) {
|
||||
MOZ_ASSERT_IF(caller.isInterpreterFrame(), !caller.asInterpreterFrame()->runningInJit());
|
||||
staticLevel = caller.script()->staticLevel() + 1;
|
||||
|
||||
// Direct calls to eval are supposed to see the caller's |this|. If we
|
||||
// haven't wrapped that yet, do so now, before we make a copy of it for
|
||||
|
@ -274,7 +272,6 @@ EvalKernel(JSContext* cx, const CallArgs& args, EvalType evalType, AbstractFrame
|
|||
thisv = caller.thisValue();
|
||||
} else {
|
||||
MOZ_ASSERT(args.callee().global() == *scopeobj);
|
||||
staticLevel = 0;
|
||||
|
||||
// Use the global as 'this', modulo outerization.
|
||||
JSObject* thisobj = GetThisObject(cx, scopeobj);
|
||||
|
@ -340,7 +337,7 @@ EvalKernel(JSContext* cx, const CallArgs& args, EvalType evalType, AbstractFrame
|
|||
SourceBufferHolder srcBuf(chars, linearStr->length(), ownership);
|
||||
JSScript* compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(),
|
||||
scopeobj, staticScope, callerScript,
|
||||
options, srcBuf, linearStr, staticLevel);
|
||||
options, srcBuf, linearStr);
|
||||
if (!compiled)
|
||||
return false;
|
||||
|
||||
|
@ -372,8 +369,6 @@ js::DirectEvalStringFromIon(JSContext* cx,
|
|||
|
||||
// ES5 15.1.2.1 steps 2-8.
|
||||
|
||||
unsigned staticLevel = callerScript->staticLevel() + 1;
|
||||
|
||||
RootedLinearString linearStr(cx, str->ensureLinear(cx));
|
||||
if (!linearStr)
|
||||
return false;
|
||||
|
@ -424,7 +419,7 @@ js::DirectEvalStringFromIon(JSContext* cx,
|
|||
SourceBufferHolder srcBuf(chars, linearStr->length(), ownership);
|
||||
JSScript* compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(),
|
||||
scopeobj, staticScope, callerScript,
|
||||
options, srcBuf, linearStr, staticLevel);
|
||||
options, srcBuf, linearStr);
|
||||
if (!compiled)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -114,39 +114,6 @@ from its prototype:
|
|||
scope this script runs. The result refers to the global directly, not
|
||||
via a wrapper or a `WindowProxy` ("outer window", in Firefox).
|
||||
|
||||
`staticLevel`
|
||||
: The number of function bodies enclosing this script's code.
|
||||
|
||||
Global code is at level zero; bodies of functions defined at the top
|
||||
level in global code are at level one; bodies of functions nested within
|
||||
those are at level two; and so on.
|
||||
|
||||
A script for code passed to direct `eval` is at a static level one
|
||||
greater than that of the script containing the call to `eval`, because
|
||||
direct eval code runs within the caller's scope. However, a script for
|
||||
code passed to an indirect `eval` call is at static level zero, since it
|
||||
is evaluated in the global scope.
|
||||
|
||||
Note that a generator's expressions are considered to be part of the
|
||||
body of a synthetic function, produced by the compiler.
|
||||
|
||||
Scripts' static level be useful in deciding where to set breakpoints.
|
||||
For example, a breakpoint set on line 3 in this code:
|
||||
|
||||
```language-js
|
||||
function f() {
|
||||
x = function g() { // line 2
|
||||
// line 3; no code here
|
||||
...;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
should be set in `g`'s script, not in `f`'s, even though neither script
|
||||
contains code at that line. In such a case, the most deeply nested
|
||||
script—the one with the highest static level—should receive the
|
||||
breakpoint.
|
||||
|
||||
`strictMode`
|
||||
: This is `true` if this script's code is ECMAScript strict mode code, and
|
||||
`false` otherwise.
|
||||
|
|
|
@ -56,8 +56,7 @@ class MOZ_STACK_CLASS BytecodeCompiler
|
|||
void maybeSetSourceCompressor(SourceCompressionTask* sourceCompressor);
|
||||
void setSourceArgumentsNotIncluded();
|
||||
|
||||
JSScript* compileScript(HandleObject scopeChain, HandleScript evalCaller,
|
||||
unsigned staticLevel);
|
||||
JSScript* compileScript(HandleObject scopeChain, HandleScript evalCaller);
|
||||
bool compileFunctionBody(MutableHandleFunction fun, const AutoNameVector& formals,
|
||||
GeneratorKind generatorKind);
|
||||
|
||||
|
@ -68,16 +67,14 @@ class MOZ_STACK_CLASS BytecodeCompiler
|
|||
bool canLazilyParse();
|
||||
bool createParser();
|
||||
bool createSourceAndParser();
|
||||
bool createScript(bool savedCallerFun = false, unsigned staticLevel = 0);
|
||||
bool createScript(bool savedCallerFun = false);
|
||||
bool createEmitter(SharedContext* sharedContext, HandleScript evalCaller = nullptr,
|
||||
bool insideNonGlobalEval = false);
|
||||
bool isInsideNonGlobalEval();
|
||||
bool createParseContext(Maybe<ParseContext<FullParseHandler>>& parseContext,
|
||||
SharedContext& globalsc, unsigned staticLevel = 0,
|
||||
uint32_t blockScopeDepth = 0);
|
||||
SharedContext& globalsc, uint32_t blockScopeDepth = 0);
|
||||
bool saveCallerFun(HandleScript evalCaller, ParseContext<FullParseHandler>& parseContext);
|
||||
bool handleStatementParseFailure(HandleObject scopeChain, HandleScript evalCaller,
|
||||
unsigned staticLevel,
|
||||
Maybe<ParseContext<FullParseHandler>>& parseContext,
|
||||
SharedContext& globalsc);
|
||||
bool handleParseFailure(const Directives& newDirectives);
|
||||
|
@ -255,12 +252,10 @@ BytecodeCompiler::createSourceAndParser()
|
|||
}
|
||||
|
||||
bool
|
||||
BytecodeCompiler::createScript(bool savedCallerFun, unsigned staticLevel)
|
||||
BytecodeCompiler::createScript(bool savedCallerFun)
|
||||
{
|
||||
script = JSScript::Create(cx, enclosingStaticScope, savedCallerFun,
|
||||
options, staticLevel,
|
||||
sourceObject, /* sourceStart = */ 0,
|
||||
sourceBuffer.length());
|
||||
script = JSScript::Create(cx, enclosingStaticScope, savedCallerFun, options,
|
||||
sourceObject, /* sourceStart = */ 0, sourceBuffer.length());
|
||||
|
||||
return script != nullptr;
|
||||
}
|
||||
|
@ -285,11 +280,10 @@ bool BytecodeCompiler::isInsideNonGlobalEval()
|
|||
|
||||
bool
|
||||
BytecodeCompiler::createParseContext(Maybe<ParseContext<FullParseHandler>>& parseContext,
|
||||
SharedContext& globalsc, unsigned staticLevel,
|
||||
uint32_t blockScopeDepth)
|
||||
SharedContext& globalsc, uint32_t blockScopeDepth)
|
||||
{
|
||||
parseContext.emplace(parser.ptr(), (GenericParseContext*) nullptr, (ParseNode*) nullptr,
|
||||
&globalsc, (Directives*) nullptr, staticLevel, blockScopeDepth);
|
||||
&globalsc, (Directives*) nullptr, blockScopeDepth);
|
||||
return parseContext->init(*parser);
|
||||
}
|
||||
|
||||
|
@ -318,7 +312,6 @@ BytecodeCompiler::saveCallerFun(HandleScript evalCaller,
|
|||
|
||||
bool
|
||||
BytecodeCompiler::handleStatementParseFailure(HandleObject scopeChain, HandleScript evalCaller,
|
||||
unsigned staticLevel,
|
||||
Maybe<ParseContext<FullParseHandler>>& parseContext,
|
||||
SharedContext& globalsc)
|
||||
{
|
||||
|
@ -340,7 +333,7 @@ BytecodeCompiler::handleStatementParseFailure(HandleObject scopeChain, HandleScr
|
|||
return false;
|
||||
|
||||
parseContext.reset();
|
||||
if (!createParseContext(parseContext, globalsc, staticLevel, script->bindings.numBlockScoped()))
|
||||
if (!createParseContext(parseContext, globalsc, script->bindings.numBlockScoped()))
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(parser->pc == parseContext.ptr());
|
||||
|
@ -563,14 +556,13 @@ BytecodeCompiler::maybeCompleteCompressSource()
|
|||
}
|
||||
|
||||
JSScript*
|
||||
BytecodeCompiler::compileScript(HandleObject scopeChain, HandleScript evalCaller,
|
||||
unsigned staticLevel)
|
||||
BytecodeCompiler::compileScript(HandleObject scopeChain, HandleScript evalCaller)
|
||||
{
|
||||
if (!createSourceAndParser())
|
||||
return nullptr;
|
||||
|
||||
bool savedCallerFun = evalCaller && evalCaller->functionOrCallerFunction();
|
||||
if (!createScript(savedCallerFun, staticLevel))
|
||||
if (!createScript(savedCallerFun))
|
||||
return nullptr;
|
||||
|
||||
GlobalSharedContext globalsc(cx, enclosingStaticScope, directives, options.extraWarningsOption);
|
||||
|
@ -581,7 +573,7 @@ BytecodeCompiler::compileScript(HandleObject scopeChain, HandleScript evalCaller
|
|||
// statements in the script. Use Maybe<> so that the parse context can be
|
||||
// reset when this occurs.
|
||||
Maybe<ParseContext<FullParseHandler>> pc;
|
||||
if (!createParseContext(pc, globalsc, staticLevel))
|
||||
if (!createParseContext(pc, globalsc))
|
||||
return nullptr;
|
||||
|
||||
if (savedCallerFun && !saveCallerFun(evalCaller, pc.ref()))
|
||||
|
@ -599,7 +591,7 @@ BytecodeCompiler::compileScript(HandleObject scopeChain, HandleScript evalCaller
|
|||
|
||||
ParseNode* pn = parser->statement(YieldIsName, canHaveDirectives);
|
||||
if (!pn) {
|
||||
if (!handleStatementParseFailure(scopeChain, evalCaller, staticLevel, pc, globalsc))
|
||||
if (!handleStatementParseFailure(scopeChain, evalCaller, pc, globalsc))
|
||||
return nullptr;
|
||||
|
||||
pn = parser->statement(YieldIsName);
|
||||
|
@ -747,7 +739,6 @@ frontend::CompileScript(ExclusiveContext* cx, LifoAlloc* alloc, HandleObject sco
|
|||
const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf,
|
||||
JSString* source_ /* = nullptr */,
|
||||
unsigned staticLevel /* = 0 */,
|
||||
SourceCompressionTask* extraSct /* = nullptr */)
|
||||
{
|
||||
MOZ_ASSERT(srcBuf.get());
|
||||
|
@ -759,13 +750,11 @@ frontend::CompileScript(ExclusiveContext* cx, LifoAlloc* alloc, HandleObject sco
|
|||
MOZ_ASSERT_IF(evalCaller, options.isRunOnce);
|
||||
MOZ_ASSERT_IF(evalCaller, options.forEval);
|
||||
MOZ_ASSERT_IF(evalCaller && evalCaller->strict(), options.strictOption);
|
||||
MOZ_ASSERT_IF(staticLevel != 0, evalCaller);
|
||||
MOZ_ASSERT_IF(staticLevel != 0, !options.sourceIsLazy);
|
||||
|
||||
BytecodeCompiler compiler(cx, alloc, options, srcBuf, enclosingStaticScope,
|
||||
TraceLogger_ParserCompileScript);
|
||||
compiler.maybeSetSourceCompressor(extraSct);
|
||||
return compiler.compileScript(scopeChain, evalCaller, staticLevel);
|
||||
return compiler.compileScript(scopeChain, evalCaller);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -787,12 +776,9 @@ frontend::CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const cha
|
|||
if (!parser.checkOptions())
|
||||
return false;
|
||||
|
||||
uint32_t staticLevel = lazy->staticLevel(cx);
|
||||
|
||||
Rooted<JSFunction*> fun(cx, lazy->functionNonDelazifying());
|
||||
MOZ_ASSERT(!lazy->isLegacyGenerator());
|
||||
ParseNode* pn = parser.standaloneLazyFunction(fun, staticLevel, lazy->strict(),
|
||||
lazy->generatorKind());
|
||||
ParseNode* pn = parser.standaloneLazyFunction(fun, lazy->strict(), lazy->generatorKind());
|
||||
if (!pn)
|
||||
return false;
|
||||
|
||||
|
@ -803,8 +789,7 @@ frontend::CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const cha
|
|||
RootedScriptSource sourceObject(cx, lazy->sourceObject());
|
||||
MOZ_ASSERT(sourceObject);
|
||||
|
||||
Rooted<JSScript*> script(cx, JSScript::Create(cx, enclosingScope, false,
|
||||
options, staticLevel,
|
||||
Rooted<JSScript*> script(cx, JSScript::Create(cx, enclosingScope, false, options,
|
||||
sourceObject, lazy->begin(), lazy->end()));
|
||||
if (!script)
|
||||
return false;
|
||||
|
|
|
@ -27,7 +27,7 @@ CompileScript(ExclusiveContext* cx, LifoAlloc* alloc,
|
|||
HandleObject scopeChain, Handle<ScopeObject*> enclosingStaticScope,
|
||||
HandleScript evalCaller, const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf, JSString* source_ = nullptr,
|
||||
unsigned staticLevel = 0, SourceCompressionTask* extraSct = nullptr);
|
||||
SourceCompressionTask* extraSct = nullptr);
|
||||
|
||||
bool
|
||||
CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const char16_t* chars, size_t length);
|
||||
|
|
|
@ -5759,7 +5759,6 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
|
|||
Rooted<JSObject*> enclosingScope(cx, innermostStaticScope());
|
||||
Rooted<JSObject*> sourceObject(cx, script->sourceObject());
|
||||
Rooted<JSScript*> script(cx, JSScript::Create(cx, enclosingScope, false, options,
|
||||
parent->staticLevel() + 1,
|
||||
sourceObject,
|
||||
funbox->bufStart, funbox->bufEnd));
|
||||
if (!script)
|
||||
|
|
|
@ -735,7 +735,7 @@ Parser<ParseHandler>::parse()
|
|||
options().extraWarningsOption);
|
||||
ParseContext<ParseHandler> globalpc(this, /* parent = */ nullptr, ParseHandler::null(),
|
||||
&globalsc, /* newDirectives = */ nullptr,
|
||||
/* staticLevel = */ 0, /* blockScopeDepth = */ 0);
|
||||
/* blockScopeDepth = */ 0);
|
||||
if (!globalpc.init(*this))
|
||||
return null();
|
||||
|
||||
|
@ -824,7 +824,7 @@ Parser<FullParseHandler>::standaloneFunctionBody(HandleFunction fun, const AutoN
|
|||
handler.setFunctionBox(fn, funbox);
|
||||
|
||||
ParseContext<FullParseHandler> funpc(this, pc, fn, funbox, newDirectives,
|
||||
/* staticLevel = */ 0, /* blockScopeDepth = */ 0);
|
||||
/* blockScopeDepth = */ 0);
|
||||
if (!funpc.init(*this))
|
||||
return null();
|
||||
|
||||
|
@ -2445,7 +2445,7 @@ Parser<FullParseHandler>::functionArgsAndBody(InHandling inHandling, ParseNode*
|
|||
return false;
|
||||
|
||||
ParseContext<SyntaxParseHandler> funpc(parser, outerpc, SyntaxParseHandler::null(),
|
||||
funbox, newDirectives, outerpc->staticLevel + 1,
|
||||
funbox, newDirectives,
|
||||
/* blockScopeDepth = */ 0);
|
||||
if (!funpc.init(*parser))
|
||||
return false;
|
||||
|
@ -2483,8 +2483,7 @@ Parser<FullParseHandler>::functionArgsAndBody(InHandling inHandling, ParseNode*
|
|||
blockScopes.resize(oldBlockScopesLength);
|
||||
|
||||
// Continue doing a full parse for this inner function.
|
||||
ParseContext<FullParseHandler> funpc(this, pc, pn, funbox,
|
||||
newDirectives, outerpc->staticLevel + 1,
|
||||
ParseContext<FullParseHandler> funpc(this, pc, pn, funbox, newDirectives,
|
||||
/* blockScopeDepth = */ 0);
|
||||
if (!funpc.init(*this))
|
||||
return false;
|
||||
|
@ -2523,8 +2522,7 @@ Parser<SyntaxParseHandler>::functionArgsAndBody(InHandling inHandling, Node pn,
|
|||
return false;
|
||||
|
||||
// Initialize early for possible flags mutation via destructuringExpr.
|
||||
ParseContext<SyntaxParseHandler> funpc(this, pc, handler.null(), funbox,
|
||||
newDirectives, outerpc->staticLevel + 1,
|
||||
ParseContext<SyntaxParseHandler> funpc(this, pc, handler.null(), funbox, newDirectives,
|
||||
/* blockScopeDepth = */ 0);
|
||||
if (!funpc.init(*this))
|
||||
return false;
|
||||
|
@ -2563,8 +2561,8 @@ Parser<ParseHandler>::appendToCallSiteObj(Node callSiteObj)
|
|||
|
||||
template <>
|
||||
ParseNode*
|
||||
Parser<FullParseHandler>::standaloneLazyFunction(HandleFunction fun, unsigned staticLevel,
|
||||
bool strict, GeneratorKind generatorKind)
|
||||
Parser<FullParseHandler>::standaloneLazyFunction(HandleFunction fun, bool strict,
|
||||
GeneratorKind generatorKind)
|
||||
{
|
||||
MOZ_ASSERT(checkOptionsCalled);
|
||||
|
||||
|
@ -2589,7 +2587,7 @@ Parser<FullParseHandler>::standaloneLazyFunction(HandleFunction fun, unsigned st
|
|||
|
||||
Directives newDirectives = directives;
|
||||
ParseContext<FullParseHandler> funpc(this, /* parent = */ nullptr, pn, funbox,
|
||||
&newDirectives, staticLevel, /* blockScopeDepth = */ 0);
|
||||
&newDirectives, /* blockScopeDepth = */ 0);
|
||||
if (!funpc.init(*this))
|
||||
return null();
|
||||
|
||||
|
@ -7537,7 +7535,6 @@ Parser<ParseHandler>::generatorComprehensionLambda(GeneratorKind comprehensionKi
|
|||
|
||||
ParseContext<ParseHandler> genpc(this, outerpc, genfn, genFunbox,
|
||||
/* newDirectives = */ nullptr,
|
||||
outerpc->staticLevel + 1,
|
||||
/* blockScopeDepth = */ 0);
|
||||
if (!genpc.init(*this))
|
||||
return null();
|
||||
|
|
|
@ -106,8 +106,6 @@ struct MOZ_STACK_CLASS ParseContext : public GenericParseContext
|
|||
|
||||
Node maybeFunction; /* sc->isFunctionBox, the pn where pn->pn_funbox == sc */
|
||||
|
||||
const unsigned staticLevel; /* static compilation unit nesting level */
|
||||
|
||||
// lastYieldOffset stores the offset of the last yield that was parsed.
|
||||
// NoYieldOffset is its initial value.
|
||||
static const uint32_t NoYieldOffset = UINT32_MAX;
|
||||
|
@ -251,12 +249,11 @@ struct MOZ_STACK_CLASS ParseContext : public GenericParseContext
|
|||
|
||||
ParseContext(Parser<ParseHandler>* prs, GenericParseContext* parent,
|
||||
Node maybeFunction, SharedContext* sc, Directives* newDirectives,
|
||||
unsigned staticLevel, uint32_t blockScopeDepth)
|
||||
uint32_t blockScopeDepth)
|
||||
: GenericParseContext(parent, sc),
|
||||
bodyid(0), // initialized in init()
|
||||
stmtStack(prs->context),
|
||||
maybeFunction(maybeFunction),
|
||||
staticLevel(staticLevel),
|
||||
lastYieldOffset(NoYieldOffset),
|
||||
blockScopeDepth(blockScopeDepth),
|
||||
blockNode(ParseHandler::null()),
|
||||
|
@ -302,7 +299,7 @@ struct MOZ_STACK_CLASS ParseContext : public GenericParseContext
|
|||
// True if this is the ParseContext for the body of a function created by
|
||||
// the Function constructor.
|
||||
bool isFunctionConstructorBody() const {
|
||||
return sc->isFunctionBox() && staticLevel == 0;
|
||||
return sc->isFunctionBox() && !parent && sc->asFunctionBox()->function()->isLambda();
|
||||
}
|
||||
|
||||
inline bool useAsmOrInsideUseAsm() const {
|
||||
|
@ -554,8 +551,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
|
|||
|
||||
// Parse a function, given only its arguments and body. Used for lazily
|
||||
// parsed functions.
|
||||
Node standaloneLazyFunction(HandleFunction fun, unsigned staticLevel, bool strict,
|
||||
GeneratorKind generatorKind);
|
||||
Node standaloneLazyFunction(HandleFunction fun, bool strict, GeneratorKind generatorKind);
|
||||
|
||||
/*
|
||||
* Parse a function body. Pass StatementListBody if the body is a list of
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
// Debugger.Script.prototype.staticLevel returns the script's static level.
|
||||
load(libdir + 'asserts.js');
|
||||
|
||||
var g = newGlobal();
|
||||
var dbg = Debugger();
|
||||
var gw = dbg.addDebuggee(g);
|
||||
|
||||
function test(expr, level) {
|
||||
var log;
|
||||
dbg.onDebuggerStatement = function (frame) {
|
||||
log += 'd';
|
||||
assertEq(frame.script.staticLevel, level);
|
||||
};
|
||||
|
||||
print("Testing: " + expr);
|
||||
|
||||
log = '';
|
||||
// The shell's 'evaluate' runs its argument as global code.
|
||||
g.evaluate(expr);
|
||||
assertEq(log, 'd');
|
||||
}
|
||||
|
||||
|
||||
test("debugger;", 0);
|
||||
test("(function () { debugger; })()", 1);
|
||||
test("(function () { (function () { debugger; })(); })()", 2);
|
||||
test("(function () { (function () { (function () { debugger; })(); })(); })()", 3);
|
||||
|
||||
test("eval('debugger;');", 1);
|
||||
test("eval('eval(\\\'debugger;\\\');');", 2);
|
||||
test("evil = eval; eval('evil(\\\'debugger;\\\');');", 0); // I don't think it's evil at all!
|
||||
test("(function () { eval('debugger;'); })();", 2);
|
||||
test("evil = eval; (function () { evil('debugger;'); })();", 0);
|
||||
|
||||
// Generators' expressions are within a synthesized function's body.
|
||||
test("((function () { debugger; })() for (x in [1])).next();", 2);
|
||||
test("(x for (x in ((function () { debugger; })(), [1]))).next();", 2);
|
||||
|
||||
// The staticLevel accessor can't be assigned to.
|
||||
g.eval('function f() {}');
|
||||
var fw = gw.makeDebuggeeValue(g.f);
|
||||
assertThrowsInstanceOf(function () { "use strict"; fw.script.staticLevel = 10; },
|
||||
TypeError);
|
|
@ -5,7 +5,6 @@ var fscript = null;
|
|||
dbg.onNewScript = function(script) {
|
||||
dbg.onNewScript = undefined;
|
||||
fscript = script.getChildScripts()[0];
|
||||
assertEq(fscript.staticLevel, 1);
|
||||
}
|
||||
|
||||
g.eval("function f(x) { arguments[0] = 3; return x }");
|
||||
|
|
|
@ -86,6 +86,13 @@ BaselineFrame::trace(JSTracer* trc, JitFrameIterator& frameIterator)
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineFrame::isDirectEvalFrame() const
|
||||
{
|
||||
return isEvalFrame() &&
|
||||
script()->enclosingStaticScope()->as<StaticEvalObject>().isDirect();
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineFrame::copyRawFrameSlots(AutoValueVector* vec) const
|
||||
{
|
||||
|
|
|
@ -408,9 +408,7 @@ class BaselineFrame
|
|||
bool isNonStrictEvalFrame() const {
|
||||
return isEvalFrame() && !script()->strict();
|
||||
}
|
||||
bool isDirectEvalFrame() const {
|
||||
return isEvalFrame() && script()->staticLevel() > 0;
|
||||
}
|
||||
bool isDirectEvalFrame() const;
|
||||
bool isNonStrictDirectEvalFrame() const {
|
||||
return isNonStrictEvalFrame() && isDirectEvalFrame();
|
||||
}
|
||||
|
|
|
@ -4451,7 +4451,7 @@ Evaluate(JSContext* cx, HandleObject scope, Handle<ScopeObject*> staticScope,
|
|||
RootedScript script(cx, frontend::CompileScript(cx, &cx->tempLifoAlloc(),
|
||||
scope, staticScope,
|
||||
/* evalCaller = */ nullptr, options,
|
||||
srcBuf, /* source = */ nullptr, 0, &sct));
|
||||
srcBuf, /* source = */ nullptr, &sct));
|
||||
if (!script)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -772,7 +772,6 @@ CreateFunctionPrototype(JSContext* cx, JSProtoKey key)
|
|||
/* enclosingScope = */ nullptr,
|
||||
/* savedCallerFun = */ false,
|
||||
options,
|
||||
/* staticLevel = */ 0,
|
||||
sourceObject,
|
||||
0,
|
||||
ss->length()));
|
||||
|
|
|
@ -599,7 +599,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
|
|||
HasNonSyntacticScope,
|
||||
};
|
||||
|
||||
uint32_t length, lineno, column, nslots, staticLevel;
|
||||
uint32_t length, lineno, column, nslots;
|
||||
uint32_t natoms, nsrcnotes, i;
|
||||
uint32_t nconsts, nobjects, nregexps, ntrynotes, nblockscopes, nyieldoffsets;
|
||||
uint32_t prologueLength, version;
|
||||
|
@ -672,7 +672,6 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
|
|||
lineno = script->lineno();
|
||||
column = script->column();
|
||||
nslots = script->nslots();
|
||||
staticLevel = script->staticLevel();
|
||||
natoms = script->natoms();
|
||||
|
||||
nsrcnotes = script->numNotes();
|
||||
|
@ -766,7 +765,6 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
|
|||
JSVersion version_ = JSVersion(version);
|
||||
MOZ_ASSERT((version_ & VersionFlags::MASK) == unsigned(version_));
|
||||
|
||||
// staticLevel is set below.
|
||||
CompileOptions options(cx);
|
||||
options.setVersion(version_)
|
||||
.setNoScriptRval(!!(scriptBits & (1 << NoScriptRval)))
|
||||
|
@ -808,7 +806,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
|
|||
}
|
||||
|
||||
script = JSScript::Create(cx, enclosingScope, !!(scriptBits & (1 << SavedCallerFun)),
|
||||
options, /* staticLevel = */ 0, sourceObject, 0, 0);
|
||||
options, sourceObject, 0, 0);
|
||||
if (!script)
|
||||
return false;
|
||||
|
||||
|
@ -886,8 +884,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
|
|||
|
||||
if (!xdr->codeUint32(&lineno) ||
|
||||
!xdr->codeUint32(&column) ||
|
||||
!xdr->codeUint32(&nslots) ||
|
||||
!xdr->codeUint32(&staticLevel))
|
||||
!xdr->codeUint32(&nslots))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -896,7 +893,6 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
|
|||
script->lineno_ = lineno;
|
||||
script->column_ = column;
|
||||
script->nslots_ = nslots;
|
||||
script->staticLevel_ = staticLevel;
|
||||
}
|
||||
|
||||
jsbytecode* code = script->code();
|
||||
|
@ -2438,8 +2434,8 @@ JSScript::initCompartment(ExclusiveContext* cx)
|
|||
|
||||
/* static */ JSScript*
|
||||
JSScript::Create(ExclusiveContext* cx, HandleObject enclosingScope, bool savedCallerFun,
|
||||
const ReadOnlyCompileOptions& options, unsigned staticLevel,
|
||||
HandleObject sourceObject, uint32_t bufStart, uint32_t bufEnd)
|
||||
const ReadOnlyCompileOptions& options, HandleObject sourceObject,
|
||||
uint32_t bufStart, uint32_t bufEnd)
|
||||
{
|
||||
MOZ_ASSERT(bufStart <= bufEnd);
|
||||
|
||||
|
@ -2467,19 +2463,6 @@ JSScript::Create(ExclusiveContext* cx, HandleObject enclosingScope, bool savedCa
|
|||
script->version = options.version;
|
||||
MOZ_ASSERT(script->getVersion() == options.version); // assert that no overflow occurred
|
||||
|
||||
// This is an unsigned-to-uint16_t conversion, test for too-high values.
|
||||
// In practice, recursion in Parser and/or BytecodeEmitter will blow the
|
||||
// stack if we nest functions more than a few hundred deep, so this will
|
||||
// never trigger. Oh well.
|
||||
if (staticLevel > UINT16_MAX) {
|
||||
if (cx->isJSContext()) {
|
||||
JS_ReportErrorNumber(cx->asJSContext(),
|
||||
GetErrorMessage, nullptr, JSMSG_TOO_DEEP, js_function_str);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
script->staticLevel_ = uint16_t(staticLevel);
|
||||
|
||||
script->setSourceObject(sourceObject);
|
||||
script->sourceStart_ = bufStart;
|
||||
script->sourceEnd_ = bufEnd;
|
||||
|
@ -3328,8 +3311,7 @@ CreateEmptyScriptForClone(JSContext* cx, HandleObject enclosingScope, HandleScri
|
|||
.setVersion(src->getVersion());
|
||||
|
||||
return JSScript::Create(cx, enclosingScope, src->savedCallerFun(),
|
||||
options, src->staticLevel(),
|
||||
sourceObject, src->sourceStart(), src->sourceEnd());
|
||||
options, sourceObject, src->sourceStart(), src->sourceEnd());
|
||||
}
|
||||
|
||||
JSScript*
|
||||
|
@ -4060,16 +4042,6 @@ LazyScript::hasUncompiledEnclosingScript() const
|
|||
return !fun.hasScript() || fun.hasUncompiledScript() || !fun.nonLazyScript()->code();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
LazyScript::staticLevel(JSContext* cx) const
|
||||
{
|
||||
for (StaticScopeIter<NoGC> ssi(enclosingScope()); !ssi.done(); ssi++) {
|
||||
if (ssi.type() == StaticScopeIter<NoGC>::Function)
|
||||
return ssi.funScript()->staticLevel() + 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
JSScript::updateBaselineOrIonRaw(JSContext* maybecx)
|
||||
{
|
||||
|
|
|
@ -1016,8 +1016,6 @@ class JSScript : public js::gc::TenuredCell
|
|||
uint16_t nTypeSets_; /* number of type sets used in this script for
|
||||
dynamic type monitoring */
|
||||
|
||||
uint16_t staticLevel_;/* static level for display maintenance */
|
||||
|
||||
// Bit fields.
|
||||
|
||||
public:
|
||||
|
@ -1161,7 +1159,7 @@ class JSScript : public js::gc::TenuredCell
|
|||
public:
|
||||
static JSScript* Create(js::ExclusiveContext* cx,
|
||||
js::HandleObject enclosingScope, bool savedCallerFun,
|
||||
const JS::ReadOnlyCompileOptions& options, unsigned staticLevel,
|
||||
const JS::ReadOnlyCompileOptions& options,
|
||||
js::HandleObject sourceObject, uint32_t sourceStart,
|
||||
uint32_t sourceEnd);
|
||||
|
||||
|
@ -1271,10 +1269,6 @@ class JSScript : public js::gc::TenuredCell
|
|||
return nslots_;
|
||||
}
|
||||
|
||||
size_t staticLevel() const {
|
||||
return staticLevel_;
|
||||
}
|
||||
|
||||
size_t nTypeSets() const {
|
||||
return nTypeSets_;
|
||||
}
|
||||
|
@ -1767,7 +1761,7 @@ class JSScript : public js::gc::TenuredCell
|
|||
return arr->vector[index];
|
||||
}
|
||||
|
||||
// The following 3 functions find the static scope just before the
|
||||
// The following 4 functions find the static scope just before the
|
||||
// execution of the instruction pointed to by pc.
|
||||
|
||||
js::NestedScopeObject* getStaticBlockScope(jsbytecode* pc);
|
||||
|
@ -1780,6 +1774,8 @@ class JSScript : public js::gc::TenuredCell
|
|||
// if the innermost static scope falls without the extent of the script.
|
||||
JSObject* innermostStaticScope(jsbytecode* pc);
|
||||
|
||||
JSObject* innermostStaticScope() { return innermostStaticScope(main()); }
|
||||
|
||||
/*
|
||||
* The isEmpty method tells whether this script has code that computes any
|
||||
* result (not return value, result AKA normal completion value) other than
|
||||
|
@ -2276,7 +2272,6 @@ class LazyScript : public gc::TenuredCell
|
|||
}
|
||||
|
||||
bool hasUncompiledEnclosingScript() const;
|
||||
uint32_t staticLevel(JSContext* cx) const;
|
||||
|
||||
friend class GCMarker;
|
||||
void traceChildren(JSTracer* trc);
|
||||
|
|
|
@ -3869,8 +3869,11 @@ class MOZ_STACK_CLASS Debugger::ScriptQuery
|
|||
if (p) {
|
||||
/* Is our newly found script deeper than the last one we found? */
|
||||
JSScript* incumbent = p->value();
|
||||
if (script->staticLevel() > incumbent->staticLevel())
|
||||
if (StaticScopeChainLength(script->innermostStaticScope()) >
|
||||
StaticScopeChainLength(incumbent->innermostStaticScope()))
|
||||
{
|
||||
p->value() = script;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* This is the first matching script we've encountered for this
|
||||
|
@ -4701,14 +4704,6 @@ DebuggerScript_getSourceLength(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
DebuggerScript_getStaticLevel(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
THIS_DEBUGSCRIPT_SCRIPT(cx, argc, vp, "(get staticLevel)", args, obj, script);
|
||||
args.rval().setNumber(uint32_t(script->staticLevel()));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
DebuggerScript_getGlobal(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
@ -5492,7 +5487,6 @@ static const JSPropertySpec DebuggerScript_properties[] = {
|
|||
JS_PSG("source", DebuggerScript_getSource, 0),
|
||||
JS_PSG("sourceStart", DebuggerScript_getSourceStart, 0),
|
||||
JS_PSG("sourceLength", DebuggerScript_getSourceLength, 0),
|
||||
JS_PSG("staticLevel", DebuggerScript_getStaticLevel, 0),
|
||||
JS_PSG("global", DebuggerScript_getGlobal, 0),
|
||||
JS_PS_END
|
||||
};
|
||||
|
@ -6405,8 +6399,7 @@ EvaluateInEnv(JSContext* cx, Handle<Env*> env, HandleValue thisv, AbstractFrameP
|
|||
SourceBufferHolder srcBuf(chars.start().get(), chars.length(), SourceBufferHolder::NoOwnership);
|
||||
RootedScript script(cx, frontend::CompileScript(cx, &cx->tempLifoAlloc(), env, staticScope,
|
||||
callerScript, options, srcBuf,
|
||||
/* source = */ nullptr,
|
||||
/* staticLevel = */ frame ? 1 : 0));
|
||||
/* source = */ nullptr));
|
||||
if (!script)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -2570,6 +2570,15 @@ js::HasNonSyntacticStaticScopeChain(JSObject* staticScope)
|
|||
return false;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
js::StaticScopeChainLength(JSObject* staticScope)
|
||||
{
|
||||
uint32_t length = 0;
|
||||
for (StaticScopeIter<NoGC> ssi(staticScope); !ssi.done(); ssi++)
|
||||
length++;
|
||||
return length;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
void
|
||||
|
|
|
@ -1234,6 +1234,7 @@ CreateScopeObjectsForScopeChain(JSContext* cx, AutoObjectVector& scopeChain,
|
|||
MutableHandleObject dynamicScopeObj);
|
||||
|
||||
bool HasNonSyntacticStaticScopeChain(JSObject* staticScope);
|
||||
uint32_t StaticScopeChainLength(JSObject* staticScope);
|
||||
|
||||
#ifdef DEBUG
|
||||
void DumpStaticScopeChain(JSScript* script);
|
||||
|
|
|
@ -107,6 +107,13 @@ InterpreterFrame::initExecuteFrame(JSContext* cx, HandleScript script, AbstractF
|
|||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
InterpreterFrame::isDirectEvalFrame() const
|
||||
{
|
||||
return isEvalFrame() &&
|
||||
script()->enclosingStaticScope()->as<StaticEvalObject>().isDirect();
|
||||
}
|
||||
|
||||
bool
|
||||
InterpreterFrame::copyRawFrameSlots(AutoValueVector* vec)
|
||||
{
|
||||
|
|
|
@ -508,9 +508,7 @@ class InterpreterFrame
|
|||
return isEvalFrame() && !script()->strict();
|
||||
}
|
||||
|
||||
bool isDirectEvalFrame() const {
|
||||
return isEvalFrame() && script()->staticLevel() > 0;
|
||||
}
|
||||
bool isDirectEvalFrame() const;
|
||||
|
||||
bool isNonStrictDirectEvalFrame() const {
|
||||
return isNonStrictEvalFrame() && isDirectEvalFrame();
|
||||
|
|
Загрузка…
Ссылка в новой задаче