mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 880538 - Generalize strict-mode reparsing (r=jorendorff)
--HG-- extra : rebase_source : 423ae5c1f922efa523f07ade811e78a1b243c057
This commit is contained in:
parent
bb425fd69b
commit
0331d292e4
@ -205,8 +205,8 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain,
|
||||
canLazilyParse ? &syntaxParser.ref() : NULL, NULL);
|
||||
parser.sct = sct;
|
||||
|
||||
GlobalSharedContext globalsc(cx, scopeChain,
|
||||
options.strictOption, options.extraWarningsOption);
|
||||
Directives directives(options.strictOption);
|
||||
GlobalSharedContext globalsc(cx, scopeChain, directives, options.extraWarningsOption);
|
||||
|
||||
bool savedCallerFun =
|
||||
options.compileAndGo &&
|
||||
@ -240,7 +240,8 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain,
|
||||
// reset when this occurs.
|
||||
Maybe<ParseContext<FullParseHandler> > pc;
|
||||
|
||||
pc.construct(&parser, (GenericParseContext *) NULL, &globalsc, staticLevel, /* bodyid = */ 0);
|
||||
pc.construct(&parser, (GenericParseContext *) NULL, &globalsc, (Directives *) NULL,
|
||||
staticLevel, /* bodyid = */ 0);
|
||||
if (!pc.ref().init())
|
||||
return NULL;
|
||||
|
||||
@ -267,7 +268,8 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain,
|
||||
* wishes to decompile it while it's running.
|
||||
*/
|
||||
JSFunction *fun = evalCaller->functionOrCallerFunction();
|
||||
ObjectBox *funbox = parser.newFunctionBox(fun, pc.addr(), fun->strict());
|
||||
Directives directives(/* strict = */ fun->strict());
|
||||
ObjectBox *funbox = parser.newFunctionBox(fun, pc.addr(), directives);
|
||||
if (!funbox)
|
||||
return NULL;
|
||||
bce.objectList.add(funbox);
|
||||
@ -305,7 +307,7 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain,
|
||||
|
||||
pc.destroy();
|
||||
pc.construct(&parser, (GenericParseContext *) NULL, &globalsc,
|
||||
staticLevel, /* bodyid = */ 0);
|
||||
(Directives *) NULL, staticLevel, /* bodyid = */ 0);
|
||||
if (!pc.ref().init())
|
||||
return NULL;
|
||||
JS_ASSERT(parser.pc == pc.addr());
|
||||
@ -462,16 +464,19 @@ frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileO
|
||||
|
||||
fun->setArgCount(formals.length());
|
||||
|
||||
// If the context is strict, immediately parse the body in strict
|
||||
// mode. Otherwise, we parse it normally. If we see a "use strict"
|
||||
// directive, we backup and reparse it as strict.
|
||||
ParseNode *fn;
|
||||
// Speculatively parse using the default directives implied by the context.
|
||||
// If a directive is encountered (e.g., "use strict") that changes how the
|
||||
// function should have been parsed, we backup and reparse with the new set
|
||||
// of directives.
|
||||
Directives directives(options.strictOption);
|
||||
|
||||
TokenStream::Position start(parser.keepAtoms);
|
||||
parser.tokenStream.tell(&start);
|
||||
bool strict = options.strictOption;
|
||||
bool becameStrict;
|
||||
|
||||
ParseNode *fn;
|
||||
while (true) {
|
||||
fn = parser.standaloneFunctionBody(fun, formals, strict, &becameStrict);
|
||||
Directives newDirectives = directives;
|
||||
fn = parser.standaloneFunctionBody(fun, formals, directives, &newDirectives);
|
||||
if (fn)
|
||||
break;
|
||||
|
||||
@ -481,10 +486,12 @@ frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileO
|
||||
// the parse.
|
||||
parser.clearAbortedSyntaxParse();
|
||||
} else {
|
||||
// If the function became strict, reparse in strict mode.
|
||||
if (strict || !becameStrict || parser.tokenStream.hadError())
|
||||
if (parser.tokenStream.hadError() || directives == newDirectives)
|
||||
return false;
|
||||
strict = true;
|
||||
|
||||
// Assignment must be monotonic to prevent reparsing iloops
|
||||
JS_ASSERT_IF(directives.strict(), newDirectives.strict());
|
||||
directives = newDirectives;
|
||||
}
|
||||
|
||||
parser.tokenStream.seek(start);
|
||||
|
@ -384,7 +384,8 @@ Parser<FullParseHandler>::cloneParseTree(ParseNode *opn)
|
||||
MOZ_ASSUME_UNREACHABLE("module nodes cannot be cloned");
|
||||
}
|
||||
NULLCHECK(pn->pn_funbox =
|
||||
newFunctionBox(opn->pn_funbox->function(), pc, opn->pn_funbox->strict));
|
||||
newFunctionBox(opn->pn_funbox->function(), pc,
|
||||
Directives(/* strict = */ opn->pn_funbox->strict)));
|
||||
NULLCHECK(pn->pn_body = cloneParseTree(opn->pn_body));
|
||||
pn->pn_cookie = opn->pn_cookie;
|
||||
pn->pn_dflags = opn->pn_dflags;
|
||||
|
@ -453,9 +453,10 @@ Parser<ParseHandler>::newObjectBox(JSObject *obj)
|
||||
|
||||
template <typename ParseHandler>
|
||||
FunctionBox::FunctionBox(ExclusiveContext *cx, ObjectBox* traceListHead, JSFunction *fun,
|
||||
ParseContext<ParseHandler> *outerpc, bool strict, bool extraWarnings)
|
||||
ParseContext<ParseHandler> *outerpc, Directives directives,
|
||||
bool extraWarnings)
|
||||
: ObjectBox(fun, traceListHead),
|
||||
SharedContext(cx, strict, extraWarnings),
|
||||
SharedContext(cx, directives, extraWarnings),
|
||||
bindings(),
|
||||
bufStart(0),
|
||||
bufEnd(0),
|
||||
@ -516,8 +517,8 @@ FunctionBox::FunctionBox(ExclusiveContext *cx, ObjectBox* traceListHead, JSFunct
|
||||
|
||||
template <typename ParseHandler>
|
||||
FunctionBox *
|
||||
Parser<ParseHandler>::newFunctionBox(JSFunction *fun,
|
||||
ParseContext<ParseHandler> *outerpc, bool strict)
|
||||
Parser<ParseHandler>::newFunctionBox(JSFunction *fun, ParseContext<ParseHandler> *outerpc,
|
||||
Directives inheritedDirectives)
|
||||
{
|
||||
JS_ASSERT(fun && !IsPoisonedPtr(fun));
|
||||
|
||||
@ -530,7 +531,7 @@ Parser<ParseHandler>::newFunctionBox(JSFunction *fun,
|
||||
*/
|
||||
FunctionBox *funbox =
|
||||
alloc.new_<FunctionBox>(context, traceListHead, fun, outerpc,
|
||||
strict, options().extraWarningsOption);
|
||||
inheritedDirectives, options().extraWarningsOption);
|
||||
if (!funbox) {
|
||||
js_ReportOutOfMemory(context);
|
||||
return NULL;
|
||||
@ -544,7 +545,7 @@ Parser<ParseHandler>::newFunctionBox(JSFunction *fun,
|
||||
ModuleBox::ModuleBox(ExclusiveContext *cx, ObjectBox *traceListHead, Module *module,
|
||||
ParseContext<FullParseHandler> *pc, bool extraWarnings)
|
||||
: ObjectBox(module, traceListHead),
|
||||
SharedContext(cx, true, extraWarnings)
|
||||
SharedContext(cx, Directives(/* strict = */ true), extraWarnings)
|
||||
{
|
||||
}
|
||||
|
||||
@ -602,9 +603,11 @@ Parser<ParseHandler>::parse(JSObject *chain)
|
||||
* an object lock before it finishes generating bytecode into a script
|
||||
* protected from the GC by a root or a stack frame reference.
|
||||
*/
|
||||
GlobalSharedContext globalsc(context, chain,
|
||||
options().strictOption, options().extraWarningsOption);
|
||||
ParseContext<ParseHandler> globalpc(this, NULL, &globalsc, /* staticLevel = */ 0, /* bodyid = */ 0);
|
||||
Directives directives(options().strictOption);
|
||||
GlobalSharedContext globalsc(context, chain, directives, options().extraWarningsOption);
|
||||
ParseContext<ParseHandler> globalpc(this, /* parent = */ NULL, &globalsc,
|
||||
/* newDirectives = */ NULL, /* staticLevel = */ 0,
|
||||
/* bodyid = */ 0);
|
||||
if (!globalpc.init())
|
||||
return null();
|
||||
|
||||
@ -843,11 +846,9 @@ Parser<ParseHandler>::checkStrictBinding(PropertyName *name, Node pn)
|
||||
template <>
|
||||
ParseNode *
|
||||
Parser<FullParseHandler>::standaloneFunctionBody(HandleFunction fun, const AutoNameVector &formals,
|
||||
bool strict, bool *becameStrict)
|
||||
Directives inheritedDirectives,
|
||||
Directives *newDirectives)
|
||||
{
|
||||
if (becameStrict)
|
||||
*becameStrict = false;
|
||||
|
||||
Node fn = handler.newFunctionDefinition();
|
||||
if (!fn)
|
||||
return null();
|
||||
@ -859,12 +860,13 @@ Parser<FullParseHandler>::standaloneFunctionBody(HandleFunction fun, const AutoN
|
||||
argsbody->makeEmpty();
|
||||
fn->pn_body = argsbody;
|
||||
|
||||
FunctionBox *funbox = newFunctionBox(fun, /* outerpc = */ NULL, strict);
|
||||
FunctionBox *funbox = newFunctionBox(fun, /* outerpc = */ NULL, inheritedDirectives);
|
||||
if (!funbox)
|
||||
return null();
|
||||
handler.setFunctionBox(fn, funbox);
|
||||
|
||||
ParseContext<FullParseHandler> funpc(this, pc, funbox, /* staticLevel = */ 0, /* bodyid = */ 0);
|
||||
ParseContext<FullParseHandler> funpc(this, pc, funbox, newDirectives,
|
||||
/* staticLevel = */ 0, /* bodyid = */ 0);
|
||||
if (!funpc.init())
|
||||
return null();
|
||||
|
||||
@ -874,11 +876,8 @@ Parser<FullParseHandler>::standaloneFunctionBody(HandleFunction fun, const AutoN
|
||||
}
|
||||
|
||||
ParseNode *pn = functionBody(Statement, StatementListBody);
|
||||
if (!pn) {
|
||||
if (becameStrict && pc->funBecameStrict)
|
||||
*becameStrict = true;
|
||||
if (!pn)
|
||||
return null();
|
||||
}
|
||||
|
||||
if (!tokenStream.matchToken(TOK_EOF)) {
|
||||
report(ParseError, false, null(), JSMSG_SYNTAX_ERROR);
|
||||
@ -1798,7 +1797,7 @@ Parser<FullParseHandler>::checkFunctionDefinition(HandlePropertyName funName,
|
||||
// so we can skip over them after accounting for their free variables.
|
||||
if (LazyScript *lazyOuter = handler.lazyOuterFunction()) {
|
||||
JSFunction *fun = handler.nextLazyInnerFunction();
|
||||
FunctionBox *funbox = newFunctionBox(fun, pc, /* strict = */ false);
|
||||
FunctionBox *funbox = newFunctionBox(fun, pc, Directives(/* strict = */ false));
|
||||
if (!funbox)
|
||||
return false;
|
||||
handler.setFunctionBox(pn, funbox);
|
||||
@ -1933,27 +1932,29 @@ Parser<ParseHandler>::functionDef(HandlePropertyName funName, const TokenStream:
|
||||
if (!fun)
|
||||
return null();
|
||||
|
||||
// If the outer scope is strict, immediately parse the function in strict
|
||||
// mode. Otherwise, we parse it normally. If we see a "use strict"
|
||||
// directive, we backup and reparse it as strict.
|
||||
bool initiallyStrict = pc->sc->strict;
|
||||
bool becameStrict;
|
||||
if (!functionArgsAndBody(pn, fun, type, kind, initiallyStrict,
|
||||
&becameStrict))
|
||||
{
|
||||
if (initiallyStrict || !becameStrict || tokenStream.hadError())
|
||||
// Speculatively parse using the directives of the parent parsing context.
|
||||
// If a directive is encountered (e.g., "use strict") that changes how the
|
||||
// function should have been parsed, we backup and reparse with the new set
|
||||
// of directives.
|
||||
Directives directives(pc);
|
||||
Directives newDirectives = directives;
|
||||
|
||||
while (true) {
|
||||
if (functionArgsAndBody(pn, fun, type, kind, directives, &newDirectives))
|
||||
break;
|
||||
if (tokenStream.hadError() || directives == newDirectives)
|
||||
return null();
|
||||
|
||||
// Reparse the function in strict mode.
|
||||
// Assignment must be monotonic to prevent reparsing iloops
|
||||
JS_ASSERT_IF(directives.strict(), newDirectives.strict());
|
||||
directives = newDirectives;
|
||||
|
||||
tokenStream.seek(start);
|
||||
if (funName && tokenStream.getToken() == TOK_ERROR)
|
||||
return null();
|
||||
|
||||
// functionArgsAndBody may have already set pn->pn_body before failing.
|
||||
handler.setFunctionBody(pn, null());
|
||||
|
||||
if (!functionArgsAndBody(pn, fun, type, kind, true))
|
||||
return null();
|
||||
}
|
||||
|
||||
return pn;
|
||||
@ -2054,14 +2055,13 @@ template <>
|
||||
bool
|
||||
Parser<FullParseHandler>::functionArgsAndBody(ParseNode *pn, HandleFunction fun,
|
||||
FunctionType type, FunctionSyntaxKind kind,
|
||||
bool strict, bool *becameStrict)
|
||||
Directives inheritedDirectives,
|
||||
Directives *newDirectives)
|
||||
{
|
||||
if (becameStrict)
|
||||
*becameStrict = false;
|
||||
ParseContext<FullParseHandler> *outerpc = pc;
|
||||
|
||||
// Create box for fun->object early to protect against last-ditch GC.
|
||||
FunctionBox *funbox = newFunctionBox(fun, pc, strict);
|
||||
FunctionBox *funbox = newFunctionBox(fun, pc, inheritedDirectives);
|
||||
if (!funbox)
|
||||
return false;
|
||||
|
||||
@ -2077,13 +2077,13 @@ Parser<FullParseHandler>::functionArgsAndBody(ParseNode *pn, HandleFunction fun,
|
||||
tokenStream.tell(&position);
|
||||
parser->tokenStream.seek(position, tokenStream);
|
||||
|
||||
ParseContext<SyntaxParseHandler> funpc(parser, outerpc, funbox,
|
||||
ParseContext<SyntaxParseHandler> funpc(parser, outerpc, funbox, newDirectives,
|
||||
outerpc->staticLevel + 1, outerpc->blockidGen);
|
||||
if (!funpc.init())
|
||||
return false;
|
||||
|
||||
if (!parser->functionArgsAndBodyGeneric(SyntaxParseHandler::NodeGeneric,
|
||||
fun, type, kind, becameStrict))
|
||||
fun, type, kind, newDirectives))
|
||||
{
|
||||
if (parser->hadAbortedSyntaxParse()) {
|
||||
// Try again with a full parse.
|
||||
@ -2111,12 +2111,12 @@ Parser<FullParseHandler>::functionArgsAndBody(ParseNode *pn, HandleFunction fun,
|
||||
} while (false);
|
||||
|
||||
// Continue doing a full parse for this inner function.
|
||||
ParseContext<FullParseHandler> funpc(this, pc, funbox,
|
||||
ParseContext<FullParseHandler> funpc(this, pc, funbox, newDirectives,
|
||||
outerpc->staticLevel + 1, outerpc->blockidGen);
|
||||
if (!funpc.init())
|
||||
return false;
|
||||
|
||||
if (!functionArgsAndBodyGeneric(pn, fun, type, kind, becameStrict))
|
||||
if (!functionArgsAndBodyGeneric(pn, fun, type, kind, newDirectives))
|
||||
return false;
|
||||
|
||||
if (!leaveFunction(pn, outerpc, kind))
|
||||
@ -2138,24 +2138,23 @@ template <>
|
||||
bool
|
||||
Parser<SyntaxParseHandler>::functionArgsAndBody(Node pn, HandleFunction fun,
|
||||
FunctionType type, FunctionSyntaxKind kind,
|
||||
bool strict, bool *becameStrict)
|
||||
Directives inheritedDirectives,
|
||||
Directives *newDirectives)
|
||||
{
|
||||
if (becameStrict)
|
||||
*becameStrict = false;
|
||||
ParseContext<SyntaxParseHandler> *outerpc = pc;
|
||||
|
||||
// Create box for fun->object early to protect against last-ditch GC.
|
||||
FunctionBox *funbox = newFunctionBox(fun, pc, strict);
|
||||
FunctionBox *funbox = newFunctionBox(fun, pc, inheritedDirectives);
|
||||
if (!funbox)
|
||||
return false;
|
||||
|
||||
// Initialize early for possible flags mutation via destructuringExpr.
|
||||
ParseContext<SyntaxParseHandler> funpc(this, pc, funbox,
|
||||
ParseContext<SyntaxParseHandler> funpc(this, pc, funbox, newDirectives,
|
||||
outerpc->staticLevel + 1, outerpc->blockidGen);
|
||||
if (!funpc.init())
|
||||
return false;
|
||||
|
||||
if (!functionArgsAndBodyGeneric(pn, fun, type, kind, becameStrict))
|
||||
if (!functionArgsAndBodyGeneric(pn, fun, type, kind, newDirectives))
|
||||
return false;
|
||||
|
||||
if (!leaveFunction(pn, outerpc, kind))
|
||||
@ -2177,17 +2176,23 @@ Parser<FullParseHandler>::standaloneLazyFunction(HandleFunction fun, unsigned st
|
||||
if (!pn)
|
||||
return null();
|
||||
|
||||
FunctionBox *funbox = newFunctionBox(fun, /* outerpc = */ NULL, strict);
|
||||
Directives directives(/* strict = */ strict);
|
||||
FunctionBox *funbox = newFunctionBox(fun, /* outerpc = */ NULL, directives);
|
||||
if (!funbox)
|
||||
return null();
|
||||
handler.setFunctionBox(pn, funbox);
|
||||
|
||||
ParseContext<FullParseHandler> funpc(this, NULL, funbox, staticLevel, 0);
|
||||
Directives newDirectives = directives;
|
||||
ParseContext<FullParseHandler> funpc(this, /* parent = */ NULL, funbox,
|
||||
&newDirectives, staticLevel, /* bodyid = */ 0);
|
||||
if (!funpc.init())
|
||||
return null();
|
||||
|
||||
if (!functionArgsAndBodyGeneric(pn, fun, Normal, Statement, NULL))
|
||||
if (!functionArgsAndBodyGeneric(pn, fun, Normal, Statement, &newDirectives)) {
|
||||
JS_ASSERT(directives == newDirectives);
|
||||
return null();
|
||||
}
|
||||
|
||||
|
||||
if (fun->isNamedLambda()) {
|
||||
if (AtomDefnPtr p = pc->lexdeps->lookup(fun->name())) {
|
||||
@ -2208,7 +2213,8 @@ Parser<FullParseHandler>::standaloneLazyFunction(HandleFunction fun, unsigned st
|
||||
template <typename ParseHandler>
|
||||
bool
|
||||
Parser<ParseHandler>::functionArgsAndBodyGeneric(Node pn, HandleFunction fun, FunctionType type,
|
||||
FunctionSyntaxKind kind, bool *becameStrict)
|
||||
FunctionSyntaxKind kind,
|
||||
Directives *newDirectives)
|
||||
{
|
||||
// Given a properly initialized parse context, try to parse an actual
|
||||
// function without concern for conversion to strict mode, use of lazy
|
||||
@ -2254,12 +2260,8 @@ Parser<ParseHandler>::functionArgsAndBodyGeneric(Node pn, HandleFunction fun, Fu
|
||||
}
|
||||
|
||||
Node body = functionBody(kind, bodyType);
|
||||
if (!body) {
|
||||
// Notify the caller if this function was discovered to be strict.
|
||||
if (becameStrict && pc->funBecameStrict)
|
||||
*becameStrict = true;
|
||||
if (!body)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!yieldGuard.empty() && !yieldGuard.ref().checkValidBody(body, JSMSG_YIELD_IN_ARROW))
|
||||
return false;
|
||||
@ -2312,7 +2314,8 @@ Parser<FullParseHandler>::moduleDecl()
|
||||
return NULL;
|
||||
pn->pn_modulebox = modulebox;
|
||||
|
||||
ParseContext<FullParseHandler> modulepc(this, pc, modulebox, pc->staticLevel + 1, pc->blockidGen);
|
||||
ParseContext<FullParseHandler> modulepc(this, pc, modulebox, /* newDirectives = */ NULL,
|
||||
pc->staticLevel + 1, pc->blockidGen);
|
||||
if (!modulepc.init())
|
||||
return NULL;
|
||||
MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_MODULE);
|
||||
@ -2441,7 +2444,7 @@ Parser<ParseHandler>::maybeParseDirective(Node pn, bool *cont)
|
||||
if (!pc->sc->strict) {
|
||||
if (pc->sc->isFunctionBox()) {
|
||||
// Request that this function be reparsed as strict.
|
||||
pc->funBecameStrict = true;
|
||||
pc->newDirectives->setStrict();
|
||||
return false;
|
||||
} else {
|
||||
// We don't reparse global scopes, so we keep track of the
|
||||
@ -5984,11 +5987,12 @@ Parser<FullParseHandler>::generatorExpr(ParseNode *kid)
|
||||
return null();
|
||||
|
||||
/* Create box for fun->object early to protect against last-ditch GC. */
|
||||
FunctionBox *genFunbox = newFunctionBox(fun, outerpc, outerpc->sc->strict);
|
||||
Directives directives(/* strict = */ outerpc->sc->strict);
|
||||
FunctionBox *genFunbox = newFunctionBox(fun, outerpc, directives);
|
||||
if (!genFunbox)
|
||||
return null();
|
||||
|
||||
ParseContext<FullParseHandler> genpc(this, outerpc, genFunbox,
|
||||
ParseContext<FullParseHandler> genpc(this, outerpc, genFunbox, /* newDirectives = */ NULL,
|
||||
outerpc->staticLevel + 1, outerpc->blockidGen);
|
||||
if (!genpc.init())
|
||||
return null();
|
||||
|
@ -214,6 +214,13 @@ struct ParseContext : public GenericParseContext
|
||||
// All inner functions in this context. Only filled in when parsing syntax.
|
||||
AutoFunctionVector innerFunctions;
|
||||
|
||||
// In a function context, points to a Directive struct that can be updated
|
||||
// to reflect new directives encountered in the Directive Prologue that
|
||||
// require reparsing the function. In global/module/generator-tail contexts,
|
||||
// we don't need to reparse when encountering a DirectivePrologue so this
|
||||
// pointer may be NULL.
|
||||
Directives *newDirectives;
|
||||
|
||||
// Set when parsing a declaration-like destructuring pattern. This flag
|
||||
// causes PrimaryExpr to create PN_NAME parse nodes for variable references
|
||||
// which are not hooked into any definition's use chain, added to any tree
|
||||
@ -225,12 +232,9 @@ struct ParseContext : public GenericParseContext
|
||||
// they need to be treated differently.
|
||||
bool inDeclDestructuring:1;
|
||||
|
||||
// True if we are in a function, saw a "use strict" directive, and weren't
|
||||
// strict before.
|
||||
bool funBecameStrict:1;
|
||||
|
||||
ParseContext(Parser<ParseHandler> *prs, GenericParseContext *parent,
|
||||
SharedContext *sc, unsigned staticLevel, uint32_t bodyid)
|
||||
SharedContext *sc, Directives *newDirectives,
|
||||
unsigned staticLevel, uint32_t bodyid)
|
||||
: GenericParseContext(parent, sc),
|
||||
bodyid(0), // initialized in init()
|
||||
blockidGen(bodyid), // used to set |bodyid| and subsequently incremented in init()
|
||||
@ -250,8 +254,8 @@ struct ParseContext : public GenericParseContext
|
||||
lexdeps(prs->context),
|
||||
funcStmts(NULL),
|
||||
innerFunctions(prs->context),
|
||||
inDeclDestructuring(false),
|
||||
funBecameStrict(false)
|
||||
newDirectives(newDirectives),
|
||||
inDeclDestructuring(false)
|
||||
{
|
||||
prs->pc = this;
|
||||
}
|
||||
@ -288,6 +292,12 @@ struct ParseContext : public GenericParseContext
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ParseHandler>
|
||||
inline
|
||||
Directives::Directives(ParseContext<ParseHandler> *parent)
|
||||
: strict_(parent->sc->strict)
|
||||
{}
|
||||
|
||||
template <typename ParseHandler>
|
||||
struct BindData;
|
||||
|
||||
@ -369,7 +379,8 @@ class Parser : private AutoGCRooter, public StrictModeGetter
|
||||
*/
|
||||
ObjectBox *newObjectBox(JSObject *obj);
|
||||
ModuleBox *newModuleBox(Module *module, ParseContext<ParseHandler> *pc);
|
||||
FunctionBox *newFunctionBox(JSFunction *fun, ParseContext<ParseHandler> *pc, bool strict);
|
||||
FunctionBox *newFunctionBox(JSFunction *fun, ParseContext<ParseHandler> *pc,
|
||||
Directives directives);
|
||||
|
||||
/*
|
||||
* Create a new function object given parse context (pc) and a name (which
|
||||
@ -402,7 +413,7 @@ class Parser : private AutoGCRooter, public StrictModeGetter
|
||||
|
||||
// Parse a function, given only its body. Used for the Function constructor.
|
||||
Node standaloneFunctionBody(HandleFunction fun, const AutoNameVector &formals,
|
||||
bool strict, bool *becameStrict);
|
||||
Directives inheritedDirectives, Directives *newDirectives);
|
||||
|
||||
// Parse a function, given only its arguments and body. Used for lazily
|
||||
// parsed functions.
|
||||
@ -416,7 +427,7 @@ class Parser : private AutoGCRooter, public StrictModeGetter
|
||||
Node functionBody(FunctionSyntaxKind kind, FunctionBodyType type);
|
||||
|
||||
bool functionArgsAndBodyGeneric(Node pn, HandleFunction fun, FunctionType type,
|
||||
FunctionSyntaxKind kind, bool *becameStrict);
|
||||
FunctionSyntaxKind kind, Directives *newDirectives);
|
||||
|
||||
virtual bool strictMode() { return pc->sc->strict; }
|
||||
|
||||
@ -487,7 +498,7 @@ class Parser : private AutoGCRooter, public StrictModeGetter
|
||||
FunctionType type, FunctionSyntaxKind kind);
|
||||
bool functionArgsAndBody(Node pn, HandleFunction fun,
|
||||
FunctionType type, FunctionSyntaxKind kind,
|
||||
bool strict, bool *becameStrict = NULL);
|
||||
Directives inheritedDirectives, Directives *newDirectives);
|
||||
|
||||
Node unaryOpExpr(ParseNodeKind kind, JSOp op, uint32_t begin);
|
||||
|
||||
|
@ -140,6 +140,30 @@ class FunctionContextFlags
|
||||
|
||||
class GlobalSharedContext;
|
||||
|
||||
// List of directives that may be encountered in a Directive Prologue (ES5 15.1).
|
||||
class Directives
|
||||
{
|
||||
bool strict_;
|
||||
|
||||
public:
|
||||
explicit Directives(bool strict) : strict_(strict) {}
|
||||
template <typename ParseHandler> explicit Directives(ParseContext<ParseHandler> *parent);
|
||||
|
||||
void setStrict() { strict_ = true; }
|
||||
bool strict() const { return strict_; }
|
||||
|
||||
Directives &operator=(Directives rhs) {
|
||||
strict_ = rhs.strict_;
|
||||
return *this;
|
||||
}
|
||||
bool operator==(const Directives &rhs) const {
|
||||
return strict_ == rhs.strict_;
|
||||
}
|
||||
bool operator!=(const Directives &rhs) const {
|
||||
return strict_ != rhs.strict_;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* The struct SharedContext is part of the current parser context (see
|
||||
* ParseContext). It stores information that is reused between the parser and
|
||||
@ -156,10 +180,10 @@ class SharedContext
|
||||
|
||||
// If it's function code, funbox must be non-NULL and scopeChain must be NULL.
|
||||
// If it's global code, funbox must be NULL.
|
||||
SharedContext(ExclusiveContext *cx, bool strict, bool extraWarnings)
|
||||
SharedContext(ExclusiveContext *cx, Directives directives, bool extraWarnings)
|
||||
: context(cx),
|
||||
anyCxFlags(),
|
||||
strict(strict),
|
||||
strict(directives.strict()),
|
||||
extraWarnings(extraWarnings)
|
||||
{}
|
||||
|
||||
@ -192,8 +216,8 @@ class GlobalSharedContext : public SharedContext
|
||||
|
||||
public:
|
||||
GlobalSharedContext(ExclusiveContext *cx, JSObject *scopeChain,
|
||||
bool strict, bool extraWarnings)
|
||||
: SharedContext(cx, strict, extraWarnings),
|
||||
Directives directives, bool extraWarnings)
|
||||
: SharedContext(cx, directives, extraWarnings),
|
||||
scopeChain_(cx, scopeChain)
|
||||
{}
|
||||
|
||||
@ -249,8 +273,8 @@ class FunctionBox : public ObjectBox, public SharedContext
|
||||
|
||||
template <typename ParseHandler>
|
||||
FunctionBox(ExclusiveContext *cx, ObjectBox* traceListHead, JSFunction *fun,
|
||||
ParseContext<ParseHandler> *pc,
|
||||
bool strict, bool extraWarnings);
|
||||
ParseContext<ParseHandler> *pc, Directives directives,
|
||||
bool extraWarnings);
|
||||
|
||||
ObjectBox *toObjectBox() { return this; }
|
||||
JSFunction *function() const { return &object->as<JSFunction>(); }
|
||||
|
Loading…
Reference in New Issue
Block a user