summaryrefslogtreecommitdiffstats
path: root/js/src/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/frontend')
-rw-r--r--js/src/frontend/BytecodeCompiler.cpp12
-rw-r--r--js/src/frontend/BytecodeCompiler.h2
-rw-r--r--js/src/frontend/BytecodeEmitter.cpp3
-rw-r--r--js/src/frontend/Parser.cpp167
-rw-r--r--js/src/frontend/Parser.h28
-rw-r--r--js/src/frontend/SharedContext.h5
-rw-r--r--js/src/frontend/TokenStream.cpp6
-rw-r--r--js/src/frontend/TokenStream.h7
8 files changed, 154 insertions, 76 deletions
diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp
index 76afe80b1..b5be5f5ac 100644
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -77,7 +77,7 @@ class MOZ_STACK_CLASS BytecodeCompiler
bool canLazilyParse();
bool createParser();
bool createSourceAndParser(Maybe<uint32_t> parameterListEnd = Nothing());
- bool createScript();
+ bool createScript(uint32_t preludeStart = 0);
bool emplaceEmitter(Maybe<BytecodeEmitter>& emitter, SharedContext* sharedContext);
bool handleParseFailure(const Directives& newDirectives);
bool deoptimizeArgumentsInEnclosingScripts(JSContext* cx, HandleObject environment);
@@ -242,10 +242,11 @@ BytecodeCompiler::createSourceAndParser(Maybe<uint32_t> parameterListEnd /* = No
}
bool
-BytecodeCompiler::createScript()
+BytecodeCompiler::createScript(uint32_t preludeStart /* = 0 */)
{
script = JSScript::Create(cx, options,
- sourceObject, /* sourceStart = */ 0, sourceBuffer.length());
+ sourceObject, /* sourceStart = */ 0, sourceBuffer.length(),
+ preludeStart);
return script != nullptr;
}
@@ -456,7 +457,7 @@ BytecodeCompiler::compileStandaloneFunction(MutableHandleFunction fun,
if (fn->pn_funbox->function()->isInterpreted()) {
MOZ_ASSERT(fun == fn->pn_funbox->function());
- if (!createScript())
+ if (!createScript(fn->pn_funbox->preludeStart))
return false;
Maybe<BytecodeEmitter> emitter;
@@ -650,7 +651,8 @@ frontend::CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const cha
MOZ_ASSERT(sourceObject);
Rooted<JSScript*> script(cx, JSScript::Create(cx, options, sourceObject,
- lazy->begin(), lazy->end()));
+ lazy->begin(), lazy->end(),
+ lazy->preludeStart()));
if (!script)
return false;
diff --git a/js/src/frontend/BytecodeCompiler.h b/js/src/frontend/BytecodeCompiler.h
index 72e967639..0bc1ab2ab 100644
--- a/js/src/frontend/BytecodeCompiler.h
+++ b/js/src/frontend/BytecodeCompiler.h
@@ -109,6 +109,8 @@ IsIdentifier(JSLinearString* str);
* As above, but taking chars + length.
*/
bool
+IsIdentifier(const char* chars, size_t length);
+bool
IsIdentifier(const char16_t* chars, size_t length);
/* True if str is a keyword. Defined in TokenStream.cpp. */
diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
index 4eb7bf880..c5e62ae34 100644
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -7834,7 +7834,8 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
Rooted<JSObject*> sourceObject(cx, script->sourceObject());
Rooted<JSScript*> script(cx, JSScript::Create(cx, options, sourceObject,
- funbox->bufStart, funbox->bufEnd));
+ funbox->bufStart, funbox->bufEnd,
+ funbox->preludeStart));
if (!script)
return false;
diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
index 209265a58..1ba725a82 100644
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -441,7 +441,8 @@ UsedNameTracker::rewind(RewindToken token)
}
FunctionBox::FunctionBox(ExclusiveContext* cx, LifoAlloc& alloc, ObjectBox* traceListHead,
- JSFunction* fun, Directives directives, bool extraWarnings,
+ JSFunction* fun, uint32_t preludeStart,
+ Directives directives, bool extraWarnings,
GeneratorKind generatorKind, FunctionAsyncKind asyncKind)
: ObjectBox(fun, traceListHead),
SharedContext(cx, Kind::ObjectBox, directives, extraWarnings),
@@ -454,6 +455,7 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, LifoAlloc& alloc, ObjectBox* trac
bufEnd(0),
startLine(1),
startColumn(0),
+ preludeStart(preludeStart),
length(0),
generatorKindBits_(GeneratorKindAsBits(generatorKind)),
asyncKindBits_(AsyncKindAsBits(asyncKind)),
@@ -738,7 +740,8 @@ Parser<ParseHandler>::newObjectBox(JSObject* obj)
template <typename ParseHandler>
FunctionBox*
-Parser<ParseHandler>::newFunctionBox(Node fn, JSFunction* fun, Directives inheritedDirectives,
+Parser<ParseHandler>::newFunctionBox(Node fn, JSFunction* fun, uint32_t preludeStart,
+ Directives inheritedDirectives,
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
bool tryAnnexB)
{
@@ -753,8 +756,9 @@ Parser<ParseHandler>::newFunctionBox(Node fn, JSFunction* fun, Directives inheri
* function.
*/
FunctionBox* funbox =
- alloc.new_<FunctionBox>(context, alloc, traceListHead, fun, inheritedDirectives,
- options().extraWarningsOption, generatorKind, asyncKind);
+ alloc.new_<FunctionBox>(context, alloc, traceListHead, fun, preludeStart,
+ inheritedDirectives, options().extraWarningsOption,
+ generatorKind, asyncKind);
if (!funbox) {
ReportOutOfMemory(context);
return nullptr;
@@ -2214,6 +2218,7 @@ Parser<SyntaxParseHandler>::finishFunction()
LazyScript* lazy = LazyScript::Create(context, fun, pc->closedOverBindingsForLazy(),
pc->innerFunctionsForLazy, versionNumber(),
funbox->bufStart, funbox->bufEnd,
+ funbox->preludeStart,
funbox->startLine, funbox->startColumn);
if (!lazy)
return false;
@@ -2267,6 +2272,33 @@ Parser<FullParseHandler>::standaloneFunction(HandleFunction fun,
{
MOZ_ASSERT(checkOptionsCalled);
+ // Skip prelude.
+ TokenKind tt;
+ if (!tokenStream.getToken(&tt))
+ return null();
+ if (asyncKind == AsyncFunction) {
+ MOZ_ASSERT(tt == TOK_ASYNC);
+ if (!tokenStream.getToken(&tt))
+ return null();
+ }
+ MOZ_ASSERT(tt == TOK_FUNCTION);
+
+ if (!tokenStream.getToken(&tt))
+ return null();
+ if (generatorKind == StarGenerator && asyncKind == SyncFunction) {
+ MOZ_ASSERT(tt == TOK_MUL);
+ if (!tokenStream.getToken(&tt))
+ return null();
+ }
+
+ // Skip function name, if present.
+ if (tt == TOK_NAME || tt == TOK_YIELD) {
+ MOZ_ASSERT(tokenStream.currentName() == fun->explicitName());
+ } else {
+ MOZ_ASSERT(fun->explicitName() == nullptr);
+ tokenStream.ungetToken();
+ }
+
Node fn = handler.newFunctionDefinition();
if (!fn)
return null();
@@ -2276,8 +2308,8 @@ Parser<FullParseHandler>::standaloneFunction(HandleFunction fun,
return null();
fn->pn_body = argsbody;
- FunctionBox* funbox = newFunctionBox(fn, fun, inheritedDirectives, generatorKind,
- asyncKind, /* tryAnnexB = */ false);
+ FunctionBox* funbox = newFunctionBox(fn, fun, /* preludeStart = */ 0, inheritedDirectives,
+ generatorKind, asyncKind, /* tryAnnexB = */ false);
if (!funbox)
return null();
funbox->initStandaloneFunction(enclosingScope);
@@ -2295,7 +2327,6 @@ Parser<FullParseHandler>::standaloneFunction(HandleFunction fun,
return null();
}
- TokenKind tt;
if (!tokenStream.getToken(&tt, TokenStream::Operand))
return null();
if (tt != TOK_EOF) {
@@ -2991,8 +3022,8 @@ Parser<ParseHandler>::checkFunctionDefinition(HandleAtom funAtom, Node pn, Funct
template <>
bool
-Parser<FullParseHandler>::skipLazyInnerFunction(ParseNode* pn, FunctionSyntaxKind kind,
- bool tryAnnexB)
+Parser<FullParseHandler>::skipLazyInnerFunction(ParseNode* pn, uint32_t preludeStart,
+ FunctionSyntaxKind kind, bool tryAnnexB)
{
// When a lazily-parsed function is called, we only fully parse (and emit)
// that function, not any of its nested children. The initial syntax-only
@@ -3001,7 +3032,7 @@ Parser<FullParseHandler>::skipLazyInnerFunction(ParseNode* pn, FunctionSyntaxKin
RootedFunction fun(context, handler.nextLazyInnerFunction());
MOZ_ASSERT(!fun->isLegacyGenerator());
- FunctionBox* funbox = newFunctionBox(pn, fun, Directives(/* strict = */ false),
+ FunctionBox* funbox = newFunctionBox(pn, fun, preludeStart, Directives(/* strict = */ false),
fun->generatorKind(), fun->asyncKind(), tryAnnexB);
if (!funbox)
return false;
@@ -3031,8 +3062,8 @@ Parser<FullParseHandler>::skipLazyInnerFunction(ParseNode* pn, FunctionSyntaxKin
template <>
bool
-Parser<SyntaxParseHandler>::skipLazyInnerFunction(Node pn, FunctionSyntaxKind kind,
- bool tryAnnexB)
+Parser<SyntaxParseHandler>::skipLazyInnerFunction(Node pn, uint32_t preludeStart,
+ FunctionSyntaxKind kind, bool tryAnnexB)
{
MOZ_CRASH("Cannot skip lazy inner functions when syntax parsing");
}
@@ -3108,7 +3139,8 @@ Parser<ParseHandler>::templateLiteral(YieldHandling yieldHandling)
template <typename ParseHandler>
typename ParseHandler::Node
-Parser<ParseHandler>::functionDefinition(InHandling inHandling, YieldHandling yieldHandling,
+Parser<ParseHandler>::functionDefinition(uint32_t preludeStart, InHandling inHandling,
+ YieldHandling yieldHandling,
HandleAtom funName, FunctionSyntaxKind kind,
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
InvokedPrediction invoked)
@@ -3132,7 +3164,7 @@ Parser<ParseHandler>::functionDefinition(InHandling inHandling, YieldHandling yi
// functions, which are also lazy. Instead, their free variables and
// source extents are recorded and may be skipped.
if (handler.canSkipLazyInnerFunctions()) {
- if (!skipLazyInnerFunction(pn, kind, tryAnnexB))
+ if (!skipLazyInnerFunction(pn, preludeStart, kind, tryAnnexB))
return null();
return pn;
}
@@ -3165,8 +3197,9 @@ Parser<ParseHandler>::functionDefinition(InHandling inHandling, YieldHandling yi
// reparse a function due to failed syntax parsing and encountering new
// "use foo" directives.
while (true) {
- if (trySyntaxParseInnerFunction(pn, fun, inHandling, yieldHandling, kind, generatorKind,
- asyncKind, tryAnnexB, directives, &newDirectives))
+ if (trySyntaxParseInnerFunction(pn, fun, preludeStart, inHandling, yieldHandling, kind,
+ generatorKind, asyncKind, tryAnnexB, directives,
+ &newDirectives))
{
break;
}
@@ -3193,6 +3226,7 @@ Parser<ParseHandler>::functionDefinition(InHandling inHandling, YieldHandling yi
template <>
bool
Parser<FullParseHandler>::trySyntaxParseInnerFunction(ParseNode* pn, HandleFunction fun,
+ uint32_t preludeStart,
InHandling inHandling,
YieldHandling yieldHandling,
FunctionSyntaxKind kind,
@@ -3226,14 +3260,15 @@ Parser<FullParseHandler>::trySyntaxParseInnerFunction(ParseNode* pn, HandleFunct
// Make a FunctionBox before we enter the syntax parser, because |pn|
// still expects a FunctionBox to be attached to it during BCE, and
// the syntax parser cannot attach one to it.
- FunctionBox* funbox = newFunctionBox(pn, fun, inheritedDirectives, generatorKind,
- asyncKind, tryAnnexB);
+ FunctionBox* funbox = newFunctionBox(pn, fun, preludeStart, inheritedDirectives,
+ generatorKind, asyncKind, tryAnnexB);
if (!funbox)
return false;
funbox->initWithEnclosingParseContext(pc, kind);
- if (!parser->innerFunction(SyntaxParseHandler::NodeGeneric, pc, funbox, inHandling,
- yieldHandling, kind, inheritedDirectives, newDirectives))
+ if (!parser->innerFunction(SyntaxParseHandler::NodeGeneric, pc, funbox, preludeStart,
+ inHandling, yieldHandling, kind,
+ inheritedDirectives, newDirectives))
{
if (parser->hadAbortedSyntaxParse()) {
// Try again with a full parse. UsedNameTracker needs to be
@@ -3259,13 +3294,14 @@ Parser<FullParseHandler>::trySyntaxParseInnerFunction(ParseNode* pn, HandleFunct
} while (false);
// We failed to do a syntax parse above, so do the full parse.
- return innerFunction(pn, pc, fun, inHandling, yieldHandling, kind, generatorKind, asyncKind,
- tryAnnexB, inheritedDirectives, newDirectives);
+ return innerFunction(pn, pc, fun, preludeStart, inHandling, yieldHandling, kind,
+ generatorKind, asyncKind, tryAnnexB, inheritedDirectives, newDirectives);
}
template <>
bool
Parser<SyntaxParseHandler>::trySyntaxParseInnerFunction(Node pn, HandleFunction fun,
+ uint32_t preludeStart,
InHandling inHandling,
YieldHandling yieldHandling,
FunctionSyntaxKind kind,
@@ -3276,13 +3312,14 @@ Parser<SyntaxParseHandler>::trySyntaxParseInnerFunction(Node pn, HandleFunction
Directives* newDirectives)
{
// This is already a syntax parser, so just parse the inner function.
- return innerFunction(pn, pc, fun, inHandling, yieldHandling, kind, generatorKind, asyncKind,
- tryAnnexB, inheritedDirectives, newDirectives);
+ return innerFunction(pn, pc, fun, preludeStart, inHandling, yieldHandling, kind,
+ generatorKind, asyncKind, tryAnnexB, inheritedDirectives, newDirectives);
}
template <typename ParseHandler>
bool
Parser<ParseHandler>::innerFunction(Node pn, ParseContext* outerpc, FunctionBox* funbox,
+ uint32_t preludeStart,
InHandling inHandling, YieldHandling yieldHandling,
FunctionSyntaxKind kind, Directives inheritedDirectives,
Directives* newDirectives)
@@ -3306,6 +3343,7 @@ Parser<ParseHandler>::innerFunction(Node pn, ParseContext* outerpc, FunctionBox*
template <typename ParseHandler>
bool
Parser<ParseHandler>::innerFunction(Node pn, ParseContext* outerpc, HandleFunction fun,
+ uint32_t preludeStart,
InHandling inHandling, YieldHandling yieldHandling,
FunctionSyntaxKind kind,
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
@@ -3317,14 +3355,14 @@ Parser<ParseHandler>::innerFunction(Node pn, ParseContext* outerpc, HandleFuncti
// parser. In that case, outerpc is a ParseContext from the full parser
// instead of the current top of the stack of the syntax parser.
- FunctionBox* funbox = newFunctionBox(pn, fun, inheritedDirectives, generatorKind,
- asyncKind, tryAnnexB);
+ FunctionBox* funbox = newFunctionBox(pn, fun, preludeStart, inheritedDirectives,
+ generatorKind, asyncKind, tryAnnexB);
if (!funbox)
return false;
funbox->initWithEnclosingParseContext(outerpc, kind);
- return innerFunction(pn, outerpc, funbox, inHandling, yieldHandling, kind, inheritedDirectives,
- newDirectives);
+ return innerFunction(pn, outerpc, funbox, preludeStart, inHandling, yieldHandling, kind,
+ inheritedDirectives, newDirectives);
}
template <typename ParseHandler>
@@ -3359,8 +3397,8 @@ Parser<FullParseHandler>::standaloneLazyFunction(HandleFunction fun, bool strict
return null();
Directives directives(strict);
- FunctionBox* funbox = newFunctionBox(pn, fun, directives, generatorKind, asyncKind,
- /* tryAnnexB = */ false);
+ FunctionBox* funbox = newFunctionBox(pn, fun, /* preludeStart = */ 0, directives,
+ generatorKind, asyncKind, /* tryAnnexB = */ false);
if (!funbox)
return null();
funbox->initFromLazyFunction();
@@ -3529,8 +3567,8 @@ Parser<ParseHandler>::functionFormalParametersAndBody(InHandling inHandling,
template <typename ParseHandler>
typename ParseHandler::Node
-Parser<ParseHandler>::functionStmt(YieldHandling yieldHandling, DefaultHandling defaultHandling,
- FunctionAsyncKind asyncKind)
+Parser<ParseHandler>::functionStmt(uint32_t preludeStart, YieldHandling yieldHandling,
+ DefaultHandling defaultHandling, FunctionAsyncKind asyncKind)
{
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION));
@@ -3579,8 +3617,8 @@ Parser<ParseHandler>::functionStmt(YieldHandling yieldHandling, DefaultHandling
}
YieldHandling newYieldHandling = GetYieldHandling(generatorKind, asyncKind);
- Node fun = functionDefinition(InAllowed, newYieldHandling, name, Statement, generatorKind,
- asyncKind, PredictUninvoked);
+ Node fun = functionDefinition(preludeStart, InAllowed, newYieldHandling, name, Statement,
+ generatorKind, asyncKind, PredictUninvoked);
if (!fun)
return null();
@@ -3597,7 +3635,8 @@ Parser<ParseHandler>::functionStmt(YieldHandling yieldHandling, DefaultHandling
template <typename ParseHandler>
typename ParseHandler::Node
-Parser<ParseHandler>::functionExpr(InvokedPrediction invoked, FunctionAsyncKind asyncKind)
+Parser<ParseHandler>::functionExpr(uint32_t preludeStart, InvokedPrediction invoked,
+ FunctionAsyncKind asyncKind)
{
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION));
@@ -3628,8 +3667,8 @@ Parser<ParseHandler>::functionExpr(InvokedPrediction invoked, FunctionAsyncKind
tokenStream.ungetToken();
}
- return functionDefinition(InAllowed, yieldHandling, name, Expression, generatorKind,
- asyncKind, invoked);
+ return functionDefinition(preludeStart, InAllowed, yieldHandling, name, Expression,
+ generatorKind, asyncKind, invoked);
}
/*
@@ -5074,7 +5113,7 @@ Parser<FullParseHandler>::exportDeclaration()
}
case TOK_FUNCTION:
- kid = functionStmt(YieldIsKeyword, NameRequired);
+ kid = functionStmt(pos().begin, YieldIsKeyword, NameRequired);
if (!kid)
return null();
@@ -5114,7 +5153,7 @@ Parser<FullParseHandler>::exportDeclaration()
ParseNode* nameNode = nullptr;
switch (tt) {
case TOK_FUNCTION:
- kid = functionStmt(YieldIsKeyword, AllowDefaultName);
+ kid = functionStmt(pos().begin, YieldIsKeyword, AllowDefaultName);
if (!kid)
return null();
break;
@@ -5131,7 +5170,7 @@ Parser<FullParseHandler>::exportDeclaration()
if (nextSameLine == TOK_FUNCTION) {
tokenStream.consumeKnownToken(nextSameLine);
- kid = functionStmt(YieldIsName, AllowDefaultName, AsyncFunction);
+ kid = functionStmt(pos().begin, YieldIsName, AllowDefaultName, AsyncFunction);
if (!kid)
return null();
break;
@@ -5232,7 +5271,7 @@ Parser<ParseHandler>::consequentOrAlternative(YieldHandling yieldHandling)
// will report the strict mode error.
if (!pc->sc()->strict()) {
tokenStream.consumeKnownToken(next, TokenStream::Operand);
- return functionStmt(yieldHandling, NameRequired);
+ return functionStmt(pos().begin, yieldHandling, NameRequired);
}
}
@@ -6182,7 +6221,7 @@ Parser<ParseHandler>::labeledItem(YieldHandling yieldHandling)
return null();
}
- return functionStmt(yieldHandling, NameRequired);
+ return functionStmt(pos().begin, yieldHandling, NameRequired);
}
tokenStream.ungetToken();
@@ -6649,6 +6688,10 @@ Parser<ParseHandler>::classDefinition(YieldHandling yieldHandling,
tokenStream.ungetToken();
}
+ uint32_t nameOffset;
+ if (!tokenStream.peekOffset(&nameOffset))
+ return null();
+
PropertyType propType;
Node propName = propertyName(yieldHandling, classMethods, &propType, &propAtom);
if (!propName)
@@ -6701,7 +6744,7 @@ Parser<ParseHandler>::classDefinition(YieldHandling yieldHandling,
if (!tokenStream.isCurrentTokenType(TOK_RB))
funName = propAtom;
}
- Node fn = methodDefinition(propType, funName);
+ Node fn = methodDefinition(nameOffset, propType, funName);
if (!fn)
return null();
@@ -7094,8 +7137,9 @@ Parser<ParseHandler>::statementListItem(YieldHandling yieldHandling,
if (!tokenStream.peekTokenSameLine(&nextSameLine))
return null();
if (nextSameLine == TOK_FUNCTION) {
+ uint32_t preludeStart = pos().begin;
tokenStream.consumeKnownToken(TOK_FUNCTION);
- return functionStmt(yieldHandling, NameRequired, AsyncFunction);
+ return functionStmt(preludeStart, yieldHandling, NameRequired, AsyncFunction);
}
}
@@ -7174,7 +7218,7 @@ Parser<ParseHandler>::statementListItem(YieldHandling yieldHandling,
// HoistableDeclaration[?Yield, ~Default]
case TOK_FUNCTION:
- return functionStmt(yieldHandling, NameRequired);
+ return functionStmt(pos().begin, yieldHandling, NameRequired);
// ClassDeclaration[?Yield, ~Default]
case TOK_CLASS:
@@ -7677,8 +7721,10 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
tokenStream.seek(start);
- if (!tokenStream.peekToken(&next, TokenStream::Operand))
+ if (!tokenStream.getToken(&next, TokenStream::Operand))
return null();
+ uint32_t preludeStart = pos().begin;
+ tokenStream.ungetToken();
GeneratorKind generatorKind = NotGenerator;
FunctionAsyncKind asyncKind = SyncFunction;
@@ -7702,7 +7748,7 @@ Parser<ParseHandler>::assignExpr(InHandling inHandling, YieldHandling yieldHandl
}
}
- Node arrowFunc = functionDefinition(inHandling, yieldHandling, nullptr,
+ Node arrowFunc = functionDefinition(preludeStart, inHandling, yieldHandling, nullptr,
Arrow, generatorKind, asyncKind);
if (!arrowFunc)
return null();
@@ -8054,8 +8100,8 @@ Parser<ParseHandler>::generatorComprehensionLambda(unsigned begin)
// Create box for fun->object early to root it.
Directives directives(/* strict = */ outerpc->sc()->strict());
- FunctionBox* genFunbox = newFunctionBox(genfn, fun, directives, StarGenerator, SyncFunction,
- /* tryAnnexB = */ false);
+ FunctionBox* genFunbox = newFunctionBox(genfn, fun, /* preludeStart = */ 0, directives,
+ StarGenerator, SyncFunction, /* tryAnnexB = */ false);
if (!genFunbox)
return null();
genFunbox->isGenexpLambda = true;
@@ -8087,12 +8133,14 @@ Parser<ParseHandler>::generatorComprehensionLambda(unsigned begin)
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN);
+ uint32_t end = pos().end;
handler.setBeginPosition(comp, begin);
- handler.setEndPosition(comp, pos().end);
+ handler.setEndPosition(comp, end);
+ genFunbox->bufEnd = end;
handler.addStatementToList(body, comp);
- handler.setEndPosition(body, pos().end);
+ handler.setEndPosition(body, end);
handler.setBeginPosition(genfn, begin);
- handler.setEndPosition(genfn, pos().end);
+ handler.setEndPosition(genfn, end);
Node generator = newDotGeneratorName();
if (!generator)
@@ -9158,6 +9206,8 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError*
if (tt == TOK_RC)
break;
+ TokenPos namePos = pos();
+
tokenStream.ungetToken();
PropertyType propType;
@@ -9309,7 +9359,7 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError*
}
}
- Node fn = methodDefinition(propType, funName);
+ Node fn = methodDefinition(namePos.begin, propType, funName);
if (!fn)
return null();
@@ -9336,13 +9386,15 @@ Parser<ParseHandler>::objectLiteral(YieldHandling yieldHandling, PossibleError*
template <typename ParseHandler>
typename ParseHandler::Node
-Parser<ParseHandler>::methodDefinition(PropertyType propType, HandleAtom funName)
+Parser<ParseHandler>::methodDefinition(uint32_t preludeStart, PropertyType propType,
+ HandleAtom funName)
{
FunctionSyntaxKind kind = FunctionSyntaxKindFromPropertyType(propType);
GeneratorKind generatorKind = GeneratorKindFromPropertyType(propType);
FunctionAsyncKind asyncKind = AsyncKindFromPropertyType(propType);
YieldHandling yieldHandling = GetYieldHandling(generatorKind, asyncKind);
- return functionDefinition(InAllowed, yieldHandling, funName, kind, generatorKind, asyncKind);
+ return functionDefinition(preludeStart, InAllowed, yieldHandling, funName, kind,
+ generatorKind, asyncKind);
}
template <typename ParseHandler>
@@ -9404,7 +9456,7 @@ Parser<ParseHandler>::primaryExpr(YieldHandling yieldHandling, TripledotHandling
switch (tt) {
case TOK_FUNCTION:
- return functionExpr(invoked);
+ return functionExpr(pos().begin, invoked);
case TOK_CLASS:
return classDefinition(yieldHandling, ClassExpression, NameRequired);
@@ -9471,8 +9523,9 @@ Parser<ParseHandler>::primaryExpr(YieldHandling yieldHandling, TripledotHandling
return null();
if (nextSameLine == TOK_FUNCTION) {
+ uint32_t preludeStart = pos().begin;
tokenStream.consumeKnownToken(TOK_FUNCTION);
- return functionExpr(PredictUninvoked, AsyncFunction);
+ return functionExpr(preludeStart, PredictUninvoked, AsyncFunction);
}
}
diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h
index 12642fad8..090931f5b 100644
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -954,7 +954,8 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
* cx->tempLifoAlloc.
*/
ObjectBox* newObjectBox(JSObject* obj);
- FunctionBox* newFunctionBox(Node fn, JSFunction* fun, Directives directives,
+ FunctionBox* newFunctionBox(Node fn, JSFunction* fun, uint32_t preludeStart,
+ Directives directives,
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
bool tryAnnexB);
@@ -1034,8 +1035,9 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
// Parse an inner function given an enclosing ParseContext and a
// FunctionBox for the inner function.
- bool innerFunction(Node pn, ParseContext* outerpc, FunctionBox* funbox, InHandling inHandling,
- YieldHandling yieldHandling, FunctionSyntaxKind kind,
+ bool innerFunction(Node pn, ParseContext* outerpc, FunctionBox* funbox, uint32_t preludeStart,
+ InHandling inHandling, YieldHandling yieldHandling,
+ FunctionSyntaxKind kind,
Directives inheritedDirectives, Directives* newDirectives);
// Parse a function's formal parameters and its body assuming its function
@@ -1088,9 +1090,10 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
* Some parsers have two versions: an always-inlined version (with an 'i'
* suffix) and a never-inlined version (with an 'n' suffix).
*/
- Node functionStmt(YieldHandling yieldHandling, DefaultHandling defaultHandling,
+ Node functionStmt(uint32_t preludeStart,
+ YieldHandling yieldHandling, DefaultHandling defaultHandling,
FunctionAsyncKind asyncKind = SyncFunction);
- Node functionExpr(InvokedPrediction invoked = PredictUninvoked,
+ Node functionExpr(uint32_t preludeStart, InvokedPrediction invoked = PredictUninvoked,
FunctionAsyncKind asyncKind = SyncFunction);
Node statementList(YieldHandling yieldHandling);
@@ -1222,7 +1225,7 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
bool tryNewTarget(Node& newTarget);
bool checkAndMarkSuperScope();
- Node methodDefinition(PropertyType propType, HandleAtom funName);
+ Node methodDefinition(uint32_t preludeStart, PropertyType propType, HandleAtom funName);
/*
* Additional JS parsers.
@@ -1230,7 +1233,8 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
bool functionArguments(YieldHandling yieldHandling, FunctionSyntaxKind kind,
Node funcpn);
- Node functionDefinition(InHandling inHandling, YieldHandling yieldHandling, HandleAtom name,
+ Node functionDefinition(uint32_t preludeStart,
+ InHandling inHandling, YieldHandling yieldHandling, HandleAtom name,
FunctionSyntaxKind kind,
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
InvokedPrediction invoked = PredictUninvoked);
@@ -1321,14 +1325,16 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
bool checkFunctionDefinition(HandleAtom funAtom, Node pn, FunctionSyntaxKind kind,
GeneratorKind generatorKind, bool* tryAnnexB);
- bool skipLazyInnerFunction(Node pn, FunctionSyntaxKind kind, bool tryAnnexB);
- bool innerFunction(Node pn, ParseContext* outerpc, HandleFunction fun,
+ bool skipLazyInnerFunction(Node pn, uint32_t preludeStart, FunctionSyntaxKind kind,
+ bool tryAnnexB);
+ bool innerFunction(Node pn, ParseContext* outerpc, HandleFunction fun, uint32_t preludeStart,
InHandling inHandling, YieldHandling yieldHandling,
FunctionSyntaxKind kind,
GeneratorKind generatorKind, FunctionAsyncKind asyncKind, bool tryAnnexB,
Directives inheritedDirectives, Directives* newDirectives);
- bool trySyntaxParseInnerFunction(Node pn, HandleFunction fun, InHandling inHandling,
- YieldHandling yieldHandling, FunctionSyntaxKind kind,
+ bool trySyntaxParseInnerFunction(Node pn, HandleFunction fun, uint32_t preludeStart,
+ InHandling inHandling, YieldHandling yieldHandling,
+ FunctionSyntaxKind kind,
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
bool tryAnnexB,
Directives inheritedDirectives, Directives* newDirectives);
diff --git a/js/src/frontend/SharedContext.h b/js/src/frontend/SharedContext.h
index a6ac542f6..b20417d5d 100644
--- a/js/src/frontend/SharedContext.h
+++ b/js/src/frontend/SharedContext.h
@@ -450,6 +450,7 @@ class FunctionBox : public ObjectBox, public SharedContext
uint32_t bufEnd;
uint32_t startLine;
uint32_t startColumn;
+ uint32_t preludeStart;
uint16_t length;
uint8_t generatorKindBits_; /* The GeneratorKind of this function. */
@@ -476,8 +477,8 @@ class FunctionBox : public ObjectBox, public SharedContext
FunctionContextFlags funCxFlags;
FunctionBox(ExclusiveContext* cx, LifoAlloc& alloc, ObjectBox* traceListHead, JSFunction* fun,
- Directives directives, bool extraWarnings, GeneratorKind generatorKind,
- FunctionAsyncKind asyncKind);
+ uint32_t preludeStart, Directives directives, bool extraWarnings,
+ GeneratorKind generatorKind, FunctionAsyncKind asyncKind);
MutableHandle<LexicalScope::Data*> namedLambdaBindings() {
MOZ_ASSERT(context->compartment()->runtimeFromAnyThread()->keepAtoms());
diff --git a/js/src/frontend/TokenStream.cpp b/js/src/frontend/TokenStream.cpp
index 179a7c244..b040d2998 100644
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -172,6 +172,12 @@ frontend::IsIdentifier(JSLinearString* str)
}
bool
+frontend::IsIdentifier(const char* chars, size_t length)
+{
+ return ::IsIdentifier(chars, length);
+}
+
+bool
frontend::IsIdentifier(const char16_t* chars, size_t length)
{
return ::IsIdentifier(chars, length);
diff --git a/js/src/frontend/TokenStream.h b/js/src/frontend/TokenStream.h
index 5d6b4b795..77eea3d81 100644
--- a/js/src/frontend/TokenStream.h
+++ b/js/src/frontend/TokenStream.h
@@ -570,6 +570,13 @@ class MOZ_STACK_CLASS TokenStream
return true;
}
+ MOZ_MUST_USE bool peekOffset(uint32_t* offset, Modifier modifier = None) {
+ TokenPos pos;
+ if (!peekTokenPos(&pos, modifier))
+ return false;
+ *offset = pos.begin;
+ return true;
+ }
// This is like peekToken(), with one exception: if there is an EOL
// between the end of the current token and the start of the next token, it
// return true and store TOK_EOL in |*ttp|. In that case, no token with