2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 * Copyright (C) 2003, 2006-2010, 2013, 2016 Apple Inc. All rights reserved.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
26 #include "ASTBuilder.h"
27 #include "CodeBlock.h"
29 #include "JSCJSValueInlines.h"
31 #include "JSCInlines.h"
32 #include "SetForScope.h"
33 #include "SourceProvider.h"
36 #include <wtf/HashFunctions.h>
37 #include <wtf/StringPrintStream.h>
38 #include <wtf/WTFThreadData.h>
41 #define updateErrorMessage(shouldPrintToken, ...) do {\
43 logError(shouldPrintToken, __VA_ARGS__); \
46 #define propagateError() do { if (hasError()) return 0; } while (0)
47 #define internalFailWithMessage(shouldPrintToken, ...) do { updateErrorMessage(shouldPrintToken, __VA_ARGS__); return 0; } while (0)
48 #define handleErrorToken() do { if (m_token.m_type == EOFTOK || m_token.m_type & ErrorTokenFlag) { failDueToUnexpectedToken(); } } while (0)
49 #define failWithMessage(...) do { { handleErrorToken(); updateErrorMessage(true, __VA_ARGS__); } return 0; } while (0)
50 #define failWithStackOverflow() do { updateErrorMessage(false, "Stack exhausted"); m_hasStackOverflow = true; return 0; } while (0)
51 #define failIfFalse(cond, ...) do { if (!(cond)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
52 #define failIfTrue(cond, ...) do { if (cond) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
53 #define failIfTrueIfStrict(cond, ...) do { if ((cond) && strictMode()) internalFailWithMessage(false, __VA_ARGS__); } while (0)
54 #define failIfFalseIfStrict(cond, ...) do { if ((!(cond)) && strictMode()) internalFailWithMessage(false, __VA_ARGS__); } while (0)
55 #define consumeOrFail(tokenType, ...) do { if (!consume(tokenType)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
56 #define consumeOrFailWithFlags(tokenType, flags, ...) do { if (!consume(tokenType, flags)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
57 #define matchOrFail(tokenType, ...) do { if (!match(tokenType)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
58 #define failIfStackOverflow() do { if (UNLIKELY(!canRecurse())) failWithStackOverflow(); } while (0)
59 #define semanticFail(...) do { internalFailWithMessage(false, __VA_ARGS__); } while (0)
60 #define semanticFailIfTrue(cond, ...) do { if (cond) internalFailWithMessage(false, __VA_ARGS__); } while (0)
61 #define semanticFailIfFalse(cond, ...) do { if (!(cond)) internalFailWithMessage(false, __VA_ARGS__); } while (0)
62 #define regexFail(failure) do { setErrorMessage(failure); return 0; } while (0)
63 #define failDueToUnexpectedToken() do {\
68 #define handleProductionOrFail(token, tokenString, operation, production) do {\
69 consumeOrFail(token, "Expected '", tokenString, "' to ", operation, " a ", production);\
72 #define handleProductionOrFail2(token, tokenString, operation, production) do {\
73 consumeOrFail(token, "Expected '", tokenString, "' to ", operation, " an ", production);\
76 #define semanticFailureDueToKeyword(...) do { \
77 if (strictMode() && m_token.m_type == RESERVED_IF_STRICT) \
78 semanticFail("Cannot use the reserved word '", getToken(), "' as a ", __VA_ARGS__, " in strict mode"); \
79 if (m_token.m_type == RESERVED || m_token.m_type == RESERVED_IF_STRICT) \
80 semanticFail("Cannot use the reserved word '", getToken(), "' as a ", __VA_ARGS__); \
81 if (m_token.m_type & KeywordTokenFlag) \
82 semanticFail("Cannot use the keyword '", getToken(), "' as a ", __VA_ARGS__); \
89 template <typename LexerType>
90 void Parser<LexerType>::logError(bool)
94 StringPrintStream stream;
95 printUnexpectedTokenText(stream);
96 setErrorMessage(stream.toStringWithLatin1Fallback());
99 template <typename LexerType> template <typename A>
100 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1)
104 StringPrintStream stream;
105 if (shouldPrintToken) {
106 printUnexpectedTokenText(stream);
109 stream.print(value1, ".");
110 setErrorMessage(stream.toStringWithLatin1Fallback());
113 template <typename LexerType> template <typename A, typename B>
114 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2)
118 StringPrintStream stream;
119 if (shouldPrintToken) {
120 printUnexpectedTokenText(stream);
123 stream.print(value1, value2, ".");
124 setErrorMessage(stream.toStringWithLatin1Fallback());
127 template <typename LexerType> template <typename A, typename B, typename C>
128 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3)
132 StringPrintStream stream;
133 if (shouldPrintToken) {
134 printUnexpectedTokenText(stream);
137 stream.print(value1, value2, value3, ".");
138 setErrorMessage(stream.toStringWithLatin1Fallback());
141 template <typename LexerType> template <typename A, typename B, typename C, typename D>
142 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4)
146 StringPrintStream stream;
147 if (shouldPrintToken) {
148 printUnexpectedTokenText(stream);
151 stream.print(value1, value2, value3, value4, ".");
152 setErrorMessage(stream.toStringWithLatin1Fallback());
155 template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E>
156 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4, const E& value5)
160 StringPrintStream stream;
161 if (shouldPrintToken) {
162 printUnexpectedTokenText(stream);
165 stream.print(value1, value2, value3, value4, value5, ".");
166 setErrorMessage(stream.toStringWithLatin1Fallback());
169 template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E, typename F>
170 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4, const E& value5, const F& value6)
174 StringPrintStream stream;
175 if (shouldPrintToken) {
176 printUnexpectedTokenText(stream);
179 stream.print(value1, value2, value3, value4, value5, value6, ".");
180 setErrorMessage(stream.toStringWithLatin1Fallback());
183 template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E, typename F, typename G>
184 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4, const E& value5, const F& value6, const G& value7)
188 StringPrintStream stream;
189 if (shouldPrintToken) {
190 printUnexpectedTokenText(stream);
193 stream.print(value1, value2, value3, value4, value5, value6, value7, ".");
194 setErrorMessage(stream.toStringWithLatin1Fallback());
197 template <typename LexerType>
198 Parser<LexerType>::Parser(VM* vm, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, SourceParseMode parseMode, SuperBinding superBinding, ConstructorKind defaultConstructorKind, DerivedContextType derivedContextType, bool isEvalContext, EvalContextType evalContextType)
201 , m_hasStackOverflow(false)
203 , m_syntaxAlreadyValidated(source.provider()->isValid())
204 , m_statementDepth(0)
205 , m_sourceElements(0)
206 , m_parsingBuiltin(builtinMode == JSParserBuiltinMode::Builtin)
207 , m_superBinding(superBinding)
208 , m_defaultConstructorKind(defaultConstructorKind)
209 , m_immediateParentAllowsFunctionDeclarationInStatement(false)
211 m_lexer = std::make_unique<LexerType>(vm, builtinMode);
212 m_lexer->setCode(source, &m_parserArena);
213 m_token.m_location.line = source.firstLine();
214 m_token.m_location.startOffset = source.startOffset();
215 m_token.m_location.endOffset = source.startOffset();
216 m_token.m_location.lineStartOffset = source.startOffset();
217 m_functionCache = vm->addSourceProviderCache(source.provider());
218 m_expressionErrorClassifier = nullptr;
220 ScopeRef scope = pushScope();
221 scope->setSourceParseMode(parseMode);
222 scope->setIsEvalContext(isEvalContext);
224 scope->setEvalContextType(evalContextType);
226 if (derivedContextType == DerivedContextType::DerivedConstructorContext) {
227 scope->setConstructorKind(ConstructorKind::Derived);
228 scope->setExpectedSuperBinding(SuperBinding::Needed);
231 if (derivedContextType == DerivedContextType::DerivedMethodContext)
232 scope->setExpectedSuperBinding(SuperBinding::Needed);
234 if (strictMode == JSParserStrictMode::Strict)
235 scope->setStrictMode();
237 if (parseMode == SourceParseMode::ModuleAnalyzeMode || parseMode == SourceParseMode::ModuleEvaluateMode)
238 m_moduleScopeData = ModuleScopeData::create();
243 template <typename LexerType>
244 Parser<LexerType>::~Parser()
248 template <typename LexerType>
249 String Parser<LexerType>::parseInner(const Identifier& calleeName, SourceParseMode parseMode)
251 String parseError = String();
253 ASTBuilder context(const_cast<VM*>(m_vm), m_parserArena, const_cast<SourceCode*>(m_source));
254 ScopeRef scope = currentScope();
255 scope->setIsLexicalScope();
256 SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_parserState.functionParsePhase, FunctionParsePhase::Body);
258 bool isArrowFunctionBodyExpression = false;
259 if (m_lexer->isReparsingFunction()) {
260 ParserFunctionInfo<ASTBuilder> functionInfo;
261 if (parseMode == SourceParseMode::GeneratorBodyMode)
262 m_parameters = createGeneratorParameters(context);
264 m_parameters = parseFunctionParameters(context, parseMode, functionInfo);
266 if (parseMode == SourceParseMode::ArrowFunctionMode && !hasError()) {
267 // The only way we could have an error wile reparsing is if we run out of stack space.
268 RELEASE_ASSERT(match(ARROWFUNCTION));
270 isArrowFunctionBodyExpression = !match(OPENBRACE);
274 if (!calleeName.isNull())
275 scope->declareCallee(&calleeName);
277 if (m_lexer->isReparsingFunction())
280 SourceElements* sourceElements = nullptr;
281 // The only way we can error this early is if we reparse a function and we run out of stack space.
283 if (isArrowFunctionBodyExpression)
284 sourceElements = parseArrowFunctionSingleExpressionBodySourceElements(context);
285 else if (isModuleParseMode(parseMode))
286 sourceElements = parseModuleSourceElements(context, parseMode);
288 if (parseMode == SourceParseMode::GeneratorWrapperFunctionMode)
289 sourceElements = parseGeneratorFunctionSourceElements(context, CheckForStrictMode);
291 sourceElements = parseSourceElements(context, CheckForStrictMode);
295 bool validEnding = consume(EOFTOK);
296 if (!sourceElements || !validEnding) {
298 parseError = m_errorMessage;
300 parseError = ASCIILiteral("Parser error");
303 IdentifierSet capturedVariables;
304 UniquedStringImplPtrSet sloppyModeHoistedFunctions;
305 scope->getSloppyModeHoistedFunctions(sloppyModeHoistedFunctions);
306 scope->getCapturedVars(capturedVariables);
308 VariableEnvironment& varDeclarations = scope->declaredVariables();
309 for (auto& entry : capturedVariables)
310 varDeclarations.markVariableAsCaptured(entry);
312 if (parseMode == SourceParseMode::GeneratorWrapperFunctionMode) {
313 if (scope->usedVariablesContains(m_vm->propertyNames->arguments.impl()))
314 context.propagateArgumentsUse();
317 CodeFeatures features = context.features();
318 if (scope->strictMode())
319 features |= StrictModeFeature;
320 if (scope->shadowsArguments())
321 features |= ShadowsArgumentsFeature;
324 if (m_parsingBuiltin && isProgramParseMode(parseMode)) {
325 VariableEnvironment& lexicalVariables = scope->lexicalVariables();
326 const HashSet<UniquedStringImpl*>& closedVariableCandidates = scope->closedVariableCandidates();
327 for (UniquedStringImpl* candidate : closedVariableCandidates) {
328 if (!lexicalVariables.contains(candidate) && !varDeclarations.contains(candidate) && !candidate->isSymbol()) {
329 dataLog("Bad global capture in builtin: '", candidate, "'\n");
330 dataLog(m_source->view());
336 didFinishParsing(sourceElements, scope->takeFunctionDeclarations(), varDeclarations, WTFMove(sloppyModeHoistedFunctions), features, context.numConstants());
341 template <typename LexerType>
342 void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, DeclarationStacks::FunctionStack&& funcStack,
343 VariableEnvironment& varDeclarations, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, CodeFeatures features, int numConstants)
345 m_sourceElements = sourceElements;
346 m_funcDeclarations = WTFMove(funcStack);
347 m_varDeclarations.swap(varDeclarations);
348 m_features = features;
349 m_sloppyModeHoistedFunctions = WTFMove(sloppyModeHoistedFunctions);
350 m_numConstants = numConstants;
353 template <typename LexerType>
354 bool Parser<LexerType>::isArrowFunctionParameters()
356 bool isOpenParen = match(OPENPAREN);
357 bool isIdent = match(IDENT);
359 if (!isOpenParen && !isIdent)
362 bool isArrowFunction = false;
363 SavePoint saveArrowFunctionPoint = createSavePoint();
367 isArrowFunction = match(ARROWFUNCTION);
369 RELEASE_ASSERT(isOpenParen);
371 if (match(CLOSEPAREN)) {
373 isArrowFunction = match(ARROWFUNCTION);
375 SyntaxChecker syntaxChecker(const_cast<VM*>(m_vm), m_lexer.get());
376 // We make fake scope, otherwise parseFormalParameters will add variable to current scope that lead to errors
377 AutoPopScopeRef fakeScope(this, pushScope());
378 fakeScope->setSourceParseMode(SourceParseMode::ArrowFunctionMode);
380 unsigned parametersCount = 0;
381 isArrowFunction = parseFormalParameters(syntaxChecker, syntaxChecker.createFormalParameterList(), parametersCount) && consume(CLOSEPAREN) && match(ARROWFUNCTION);
383 popScope(fakeScope, syntaxChecker.NeedsFreeVariableInfo);
387 restoreSavePoint(saveArrowFunctionPoint);
389 return isArrowFunction;
392 template <typename LexerType>
393 bool Parser<LexerType>::allowAutomaticSemicolon()
395 return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator();
398 template <typename LexerType>
399 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context, SourceElementsMode mode)
401 const unsigned lengthOfUseStrictLiteral = 12; // "use strict".length
402 TreeSourceElements sourceElements = context.createSourceElements();
403 const Identifier* directive = 0;
404 unsigned directiveLiteralLength = 0;
405 auto savePoint = createSavePoint();
406 bool shouldCheckForUseStrict = mode == CheckForStrictMode;
408 while (TreeStatement statement = parseStatementListItem(context, directive, &directiveLiteralLength)) {
409 if (shouldCheckForUseStrict) {
411 // "use strict" must be the exact literal without escape sequences or line continuation.
412 if (directiveLiteralLength == lengthOfUseStrictLiteral && m_vm->propertyNames->useStrictIdentifier == *directive) {
414 shouldCheckForUseStrict = false; // We saw "use strict", there is no need to keep checking for it.
415 if (!isValidStrictMode()) {
416 if (m_parserState.lastFunctionName) {
417 if (m_vm->propertyNames->arguments == *m_parserState.lastFunctionName)
418 semanticFail("Cannot name a function 'arguments' in strict mode");
419 if (m_vm->propertyNames->eval == *m_parserState.lastFunctionName)
420 semanticFail("Cannot name a function 'eval' in strict mode");
422 if (hasDeclaredVariable(m_vm->propertyNames->arguments))
423 semanticFail("Cannot declare a variable named 'arguments' in strict mode");
424 if (hasDeclaredVariable(m_vm->propertyNames->eval))
425 semanticFail("Cannot declare a variable named 'eval' in strict mode");
426 semanticFailIfTrue(currentScope()->hasNonSimpleParameterList(), "'use strict' directive not allowed inside a function with a non-simple parameter list");
427 semanticFailIfFalse(isValidStrictMode(), "Invalid parameters or function name in strict mode");
429 // Since strict mode is changed, restoring lexer state by calling next() may cause errors.
430 restoreSavePoint(savePoint);
435 // We saw a directive, but it wasn't "use strict". We reset our state to
436 // see if the next statement we parse is also a directive.
439 // We saw a statement that wasn't in the form of a directive. The spec says that "use strict"
440 // is only allowed as the first statement, or after a sequence of directives before it, but
441 // not after non-directive statements.
442 shouldCheckForUseStrict = false;
445 context.appendStatement(sourceElements, statement);
449 return sourceElements;
452 template <typename LexerType>
453 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseModuleSourceElements(TreeBuilder& context, SourceParseMode parseMode)
455 TreeSourceElements sourceElements = context.createSourceElements();
456 SyntaxChecker syntaxChecker(const_cast<VM*>(m_vm), m_lexer.get());
459 TreeStatement statement = 0;
461 statement = parseImportDeclaration(context);
462 else if (match(EXPORT))
463 statement = parseExportDeclaration(context);
465 const Identifier* directive = 0;
466 unsigned directiveLiteralLength = 0;
467 if (parseMode == SourceParseMode::ModuleAnalyzeMode) {
468 if (!parseStatementListItem(syntaxChecker, directive, &directiveLiteralLength))
472 statement = parseStatementListItem(context, directive, &directiveLiteralLength);
477 context.appendStatement(sourceElements, statement);
482 for (const auto& pair : m_moduleScopeData->exportedBindings()) {
483 const auto& uid = pair.key;
484 if (currentScope()->hasDeclaredVariable(uid)) {
485 currentScope()->declaredVariables().markVariableAsExported(uid);
489 if (currentScope()->hasLexicallyDeclaredVariable(uid)) {
490 currentScope()->lexicalVariables().markVariableAsExported(uid);
494 semanticFail("Exported binding '", uid.get(), "' needs to refer to a top-level declared variable");
497 return sourceElements;
500 template <typename LexerType>
501 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseGeneratorFunctionSourceElements(TreeBuilder& context, SourceElementsMode mode)
503 auto sourceElements = context.createSourceElements();
505 unsigned functionKeywordStart = tokenStart();
506 JSTokenLocation startLocation(tokenLocation());
507 JSTextPosition start = tokenStartPosition();
508 unsigned startColumn = tokenColumn();
509 int functionNameStart = m_token.m_location.startOffset;
510 int parametersStart = m_token.m_location.startOffset;
512 ParserFunctionInfo<TreeBuilder> info;
513 info.name = &m_vm->propertyNames->nullIdentifier;
514 createGeneratorParameters(context);
515 info.startOffset = parametersStart;
516 info.startLine = tokenLine();
517 info.parameterCount = 4; // generator, state, value, resume mode
520 AutoPopScopeRef generatorBodyScope(this, pushScope());
521 generatorBodyScope->setSourceParseMode(SourceParseMode::GeneratorBodyMode);
522 generatorBodyScope->setConstructorKind(ConstructorKind::None);
523 generatorBodyScope->setExpectedSuperBinding(m_superBinding);
525 SyntaxChecker generatorFunctionContext(const_cast<VM*>(m_vm), m_lexer.get());
526 failIfFalse(parseSourceElements(generatorFunctionContext, mode), "Cannot parse the body of a generator");
527 popScope(generatorBodyScope, TreeBuilder::NeedsFreeVariableInfo);
529 info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, SourceParseMode::GeneratorBodyMode, false);
531 info.endLine = tokenLine();
532 info.endOffset = m_token.m_data.offset;
533 info.parametersStartColumn = startColumn;
535 auto functionExpr = context.createFunctionExpr(startLocation, info);
536 auto statement = context.createExprStatement(startLocation, functionExpr, start, m_lastTokenEndPosition.line);
537 context.appendStatement(sourceElements, statement);
539 return sourceElements;
542 template <typename LexerType>
543 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatementListItem(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
545 // The grammar is documented here:
546 // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-statements
547 DepthManager statementDepth(&m_statementDepth);
549 TreeStatement result = 0;
550 bool shouldSetEndOffset = true;
551 switch (m_token.m_type) {
553 result = parseVariableDeclaration(context, DeclarationType::ConstDeclaration);
556 bool shouldParseVariableDeclaration = true;
558 SavePoint savePoint = createSavePoint();
560 // Intentionally use `match(IDENT) || match(LET) || match(YIELD)` and don't use `matchSpecIdentifier()`.
561 // We would like to fall into parseVariableDeclaration path even if "yield" is not treated as an Identifier.
562 // For example, under a generator context, matchSpecIdentifier() for "yield" returns `false`.
563 // But we would like to enter parseVariableDeclaration and raise an error under the context of parseVariableDeclaration
564 // to raise consistent errors between "var", "const" and "let".
565 if (!(match(IDENT) || match(LET) || match(YIELD)) && !match(OPENBRACE) && !match(OPENBRACKET))
566 shouldParseVariableDeclaration = false;
567 restoreSavePoint(savePoint);
569 if (shouldParseVariableDeclaration)
570 result = parseVariableDeclaration(context, DeclarationType::LetDeclaration);
572 bool allowFunctionDeclarationAsStatement = true;
573 result = parseExpressionOrLabelStatement(context, allowFunctionDeclarationAsStatement);
579 result = parseClassDeclaration(context);
582 result = parseFunctionDeclaration(context);
586 // This is a convenient place to notice labeled statements
587 // (even though we also parse them as normal statements)
588 // because we allow the following type of code in sloppy mode:
589 // ``` function foo() { label: function bar() { } } ```
590 bool allowFunctionDeclarationAsStatement = true;
591 result = parseExpressionOrLabelStatement(context, allowFunctionDeclarationAsStatement);
595 m_statementDepth--; // parseStatement() increments the depth.
596 result = parseStatement(context, directive, directiveLiteralLength);
597 shouldSetEndOffset = false;
601 if (result && shouldSetEndOffset)
602 context.setEndOffset(result, m_lastTokenEndPosition.offset);
607 template <typename LexerType>
608 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVariableDeclaration(TreeBuilder& context, DeclarationType declarationType, ExportType exportType)
610 ASSERT(match(VAR) || match(LET) || match(CONSTTOKEN));
611 JSTokenLocation location(tokenLocation());
612 int start = tokenLine();
615 TreeDestructuringPattern scratch1 = 0;
616 TreeExpression scratch2 = 0;
617 JSTextPosition scratch3;
619 TreeExpression variableDecls = parseVariableDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3, VarDeclarationContext, declarationType, exportType, scratchBool);
621 failIfFalse(autoSemiColon(), "Expected ';' after variable declaration");
623 return context.createDeclarationStatement(location, variableDecls, start, end);
626 template <typename LexerType>
627 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDoWhileStatement(TreeBuilder& context)
630 int startLine = tokenLine();
632 const Identifier* unused = 0;
634 TreeStatement statement = parseStatement(context, unused);
636 failIfFalse(statement, "Expected a statement following 'do'");
637 int endLine = tokenLine();
638 JSTokenLocation location(tokenLocation());
639 handleProductionOrFail(WHILE, "while", "end", "do-while loop");
640 handleProductionOrFail(OPENPAREN, "(", "start", "do-while loop condition");
641 semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a do-while loop condition");
642 TreeExpression expr = parseExpression(context);
643 failIfFalse(expr, "Unable to parse do-while loop condition");
644 handleProductionOrFail(CLOSEPAREN, ")", "end", "do-while loop condition");
645 if (match(SEMICOLON))
646 next(); // Always performs automatic semicolon insertion.
647 return context.createDoWhileStatement(location, statement, expr, startLine, endLine);
650 template <typename LexerType>
651 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWhileStatement(TreeBuilder& context)
653 ASSERT(match(WHILE));
654 JSTokenLocation location(tokenLocation());
655 int startLine = tokenLine();
658 handleProductionOrFail(OPENPAREN, "(", "start", "while loop condition");
659 semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a while loop condition");
660 TreeExpression expr = parseExpression(context);
661 failIfFalse(expr, "Unable to parse while loop condition");
662 int endLine = tokenLine();
663 handleProductionOrFail(CLOSEPAREN, ")", "end", "while loop condition");
665 const Identifier* unused = 0;
667 TreeStatement statement = parseStatement(context, unused);
669 failIfFalse(statement, "Expected a statement as the body of a while loop");
670 return context.createWhileStatement(location, expr, statement, startLine, endLine);
673 template <typename LexerType>
674 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVariableDeclarationList(TreeBuilder& context, int& declarations, TreeDestructuringPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext declarationListContext, DeclarationType declarationType, ExportType exportType, bool& forLoopConstDoesNotHaveInitializer)
676 ASSERT(declarationType == DeclarationType::LetDeclaration || declarationType == DeclarationType::VarDeclaration || declarationType == DeclarationType::ConstDeclaration);
677 TreeExpression head = 0;
678 TreeExpression tail = 0;
679 const Identifier* lastIdent;
680 JSToken lastIdentToken;
681 AssignmentContext assignmentContext = assignmentContextFromDeclarationType(declarationType);
684 lastPattern = TreeDestructuringPattern(0);
685 JSTokenLocation location(tokenLocation());
687 TreeExpression node = 0;
689 bool hasInitializer = false;
690 if (matchSpecIdentifier()) {
691 failIfTrue(match(LET) && (declarationType == DeclarationType::LetDeclaration || declarationType == DeclarationType::ConstDeclaration),
692 "Can't use 'let' as an identifier name for a LexicalDeclaration");
693 JSTextPosition varStart = tokenStartPosition();
694 JSTokenLocation varStartLocation(tokenLocation());
695 identStart = varStart;
696 const Identifier* name = m_token.m_data.ident;
698 lastIdentToken = m_token;
700 hasInitializer = match(EQUAL);
701 DeclarationResultMask declarationResult = declareVariable(name, declarationType);
702 if (declarationResult != DeclarationResult::Valid) {
703 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a variable named ", name->impl(), " in strict mode");
704 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration) {
705 if (declarationType == DeclarationType::LetDeclaration)
706 internalFailWithMessage(false, "Cannot declare a let variable twice: '", name->impl(), "'");
707 if (declarationType == DeclarationType::ConstDeclaration)
708 internalFailWithMessage(false, "Cannot declare a const variable twice: '", name->impl(), "'");
709 ASSERT(declarationType == DeclarationType::VarDeclaration);
710 internalFailWithMessage(false, "Cannot declare a var variable that shadows a let/const/class variable: '", name->impl(), "'");
713 if (exportType == ExportType::Exported) {
714 semanticFailIfFalse(exportName(*name), "Cannot export a duplicate name '", name->impl(), "'");
715 m_moduleScopeData->exportBinding(*name);
718 if (hasInitializer) {
719 JSTextPosition varDivot = tokenStartPosition() + 1;
720 initStart = tokenStartPosition();
721 next(TreeBuilder::DontBuildStrings); // consume '='
723 TreeExpression initializer = parseAssignmentExpression(context);
724 initEnd = lastTokenEndPosition();
725 lastInitializer = initializer;
726 failIfFalse(initializer, "Expected expression as the intializer for the variable '", name->impl(), "'");
728 node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEndPosition(), assignmentContext);
730 if (declarationListContext == ForLoopContext && declarationType == DeclarationType::ConstDeclaration)
731 forLoopConstDoesNotHaveInitializer = true;
732 failIfTrue(declarationListContext != ForLoopContext && declarationType == DeclarationType::ConstDeclaration, "const declared variable '", name->impl(), "'", " must have an initializer");
733 if (declarationType == DeclarationType::VarDeclaration)
734 node = context.createEmptyVarExpression(varStartLocation, *name);
736 node = context.createEmptyLetExpression(varStartLocation, *name);
740 auto pattern = parseDestructuringPattern(context, destructuringKindFromDeclarationType(declarationType), exportType, nullptr, nullptr, assignmentContext);
741 failIfFalse(pattern, "Cannot parse this destructuring pattern");
742 hasInitializer = match(EQUAL);
743 failIfTrue(declarationListContext == VarDeclarationContext && !hasInitializer, "Expected an initializer in destructuring variable declaration");
744 lastPattern = pattern;
745 if (hasInitializer) {
746 next(TreeBuilder::DontBuildStrings); // consume '='
747 TreeExpression rhs = parseAssignmentExpression(context);
750 node = context.createDestructuringAssignment(location, pattern, rhs);
751 lastInitializer = rhs;
759 head = context.createCommaExpr(location, head);
760 tail = context.appendToCommaExpr(location, head, head, node);
762 tail = context.appendToCommaExpr(location, head, tail, node);
764 } while (match(COMMA));
766 lastPattern = context.createBindingLocation(lastIdentToken.m_location, *lastIdent, lastIdentToken.m_startPosition, lastIdentToken.m_endPosition, assignmentContext);
771 template <typename LexerType>
772 bool Parser<LexerType>::declareRestOrNormalParameter(const Identifier& name, const Identifier** duplicateIdentifier)
774 DeclarationResultMask declarationResult = declareParameter(&name);
775 if ((declarationResult & DeclarationResult::InvalidStrictMode) && strictMode()) {
776 semanticFailIfTrue(isEvalOrArguments(&name), "Cannot destructure to a parameter name '", name.impl(), "' in strict mode");
777 if (m_parserState.lastFunctionName && name == *m_parserState.lastFunctionName)
778 semanticFail("Cannot declare a parameter named '", name.impl(), "' as it shadows the name of a strict mode function");
779 semanticFailureDueToKeyword("parameter name");
780 if (hasDeclaredParameter(name))
781 semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode as it has already been declared");
782 semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode");
784 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration) {
785 // It's not always an error to define a duplicate parameter.
786 // It's only an error when there are default parameter values or destructuring parameters.
787 // We note this value now so we can check it later.
788 if (duplicateIdentifier)
789 *duplicateIdentifier = &name;
795 template <typename LexerType>
796 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::createBindingPattern(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier& name, JSToken token, AssignmentContext bindingContext, const Identifier** duplicateIdentifier)
798 ASSERT(!name.isNull());
800 ASSERT(name.impl()->isAtomic() || name.impl()->isSymbol());
803 case DestructuringKind::DestructureToVariables: {
804 DeclarationResultMask declarationResult = declareVariable(&name);
805 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a variable named '", name.impl(), "' in strict mode");
806 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
807 internalFailWithMessage(false, "Cannot declare a var variable that shadows a let/const/class variable: '", name.impl(), "'");
811 case DestructuringKind::DestructureToLet:
812 case DestructuringKind::DestructureToConst:
813 case DestructuringKind::DestructureToCatchParameters: {
814 DeclarationResultMask declarationResult = declareVariable(&name, kind == DestructuringKind::DestructureToConst ? DeclarationType::ConstDeclaration : DeclarationType::LetDeclaration);
815 if (declarationResult != DeclarationResult::Valid) {
816 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot destructure to a variable named '", name.impl(), "' in strict mode");
817 failIfTrue(declarationResult & DeclarationResult::InvalidDuplicateDeclaration, "Cannot declare a lexical variable twice: '", name.impl(), "'");
822 case DestructuringKind::DestructureToParameters: {
823 declareRestOrNormalParameter(name, duplicateIdentifier);
828 case DestructuringKind::DestructureToExpressions: {
833 if (exportType == ExportType::Exported) {
834 semanticFailIfFalse(exportName(name), "Cannot export a duplicate name '", name.impl(), "'");
835 m_moduleScopeData->exportBinding(name);
837 return context.createBindingLocation(token.m_location, name, token.m_startPosition, token.m_endPosition, bindingContext);
840 template <typename LexerType>
841 template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern Parser<LexerType>::createAssignmentElement(TreeBuilder& context, TreeExpression& assignmentTarget, const JSTextPosition& startPosition, const JSTextPosition& endPosition)
843 return context.createAssignmentElement(assignmentTarget, startPosition, endPosition);
846 template <typename LexerType>
847 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseArrowFunctionSingleExpressionBodySourceElements(TreeBuilder& context)
849 ASSERT(!match(OPENBRACE));
851 JSTokenLocation location(tokenLocation());
852 JSTextPosition start = tokenStartPosition();
854 failIfStackOverflow();
855 TreeExpression expr = parseAssignmentExpression(context);
856 failIfFalse(expr, "Cannot parse the arrow function expression");
858 context.setEndOffset(expr, m_lastTokenEndPosition.offset);
860 JSTextPosition end = tokenEndPosition();
862 TreeSourceElements sourceElements = context.createSourceElements();
863 TreeStatement body = context.createReturnStatement(location, expr, start, end);
864 context.setEndOffset(body, m_lastTokenEndPosition.offset);
865 context.appendStatement(sourceElements, body);
867 return sourceElements;
870 template <typename LexerType>
871 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::tryParseDestructuringPatternExpression(TreeBuilder& context, AssignmentContext bindingContext)
873 return parseDestructuringPattern(context, DestructuringKind::DestructureToExpressions, ExportType::NotExported, nullptr, nullptr, bindingContext);
876 template <typename LexerType>
877 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseBindingOrAssignmentElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
879 if (kind == DestructuringKind::DestructureToExpressions)
880 return parseAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
881 return parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
884 template <typename LexerType>
885 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseAssignmentElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
887 TreeDestructuringPattern assignmentTarget = 0;
889 if (match(OPENBRACE) || match(OPENBRACKET)) {
890 SavePoint savePoint = createSavePoint();
891 assignmentTarget = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
892 if (assignmentTarget && !match(DOT) && !match(OPENBRACKET) && !match(OPENPAREN) && !match(TEMPLATE))
893 return assignmentTarget;
894 restoreSavePoint(savePoint);
897 JSTextPosition startPosition = tokenStartPosition();
898 auto element = parseMemberExpression(context);
900 semanticFailIfFalse(element && context.isAssignmentLocation(element), "Invalid destructuring assignment target");
902 if (strictMode() && m_parserState.lastIdentifier && context.isResolve(element)) {
903 bool isEvalOrArguments = m_vm->propertyNames->eval == *m_parserState.lastIdentifier || m_vm->propertyNames->arguments == *m_parserState.lastIdentifier;
904 failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", m_parserState.lastIdentifier->impl(), "' in strict mode");
907 return createAssignmentElement(context, element, startPosition, lastTokenEndPosition());
910 static const char* destructuringKindToVariableKindName(DestructuringKind kind)
913 case DestructuringKind::DestructureToLet:
914 case DestructuringKind::DestructureToConst:
915 return "lexical variable name";
916 case DestructuringKind::DestructureToVariables:
917 return "variable name";
918 case DestructuringKind::DestructureToParameters:
919 return "parameter name";
920 case DestructuringKind::DestructureToCatchParameters:
921 return "catch parameter name";
922 case DestructuringKind::DestructureToExpressions:
923 return "expression name";
925 RELEASE_ASSERT_NOT_REACHED();
929 template <typename LexerType>
930 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseDestructuringPattern(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
932 failIfStackOverflow();
933 int nonLHSCount = m_parserState.nonLHSCount;
934 TreeDestructuringPattern pattern;
935 switch (m_token.m_type) {
937 JSTextPosition divotStart = tokenStartPosition();
938 auto arrayPattern = context.createArrayPattern(m_token.m_location);
941 if (hasDestructuringPattern)
942 *hasDestructuringPattern = true;
944 bool restElementWasFound = false;
947 while (match(COMMA)) {
948 context.appendArrayPatternSkipEntry(arrayPattern, m_token.m_location);
953 if (match(CLOSEBRACKET))
956 if (UNLIKELY(match(DOTDOTDOT))) {
957 JSTokenLocation location = m_token.m_location;
959 auto innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
960 if (kind == DestructuringKind::DestructureToExpressions && !innerPattern)
962 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
964 failIfTrue(kind != DestructuringKind::DestructureToExpressions && !context.isBindingNode(innerPattern), "Expected identifier for a rest element destructuring pattern");
966 context.appendArrayPatternRestEntry(arrayPattern, location, innerPattern);
967 restElementWasFound = true;
971 JSTokenLocation location = m_token.m_location;
972 auto innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
973 if (kind == DestructuringKind::DestructureToExpressions && !innerPattern)
975 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
976 TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
978 context.appendArrayPatternEntry(arrayPattern, location, innerPattern, defaultValue);
979 } while (consume(COMMA));
981 consumeOrFail(CLOSEBRACKET, restElementWasFound ? "Expected a closing ']' following a rest element destructuring pattern" : "Expected either a closing ']' or a ',' following an element destructuring pattern");
982 context.finishArrayPattern(arrayPattern, divotStart, divotStart, lastTokenEndPosition());
983 pattern = arrayPattern;
987 auto objectPattern = context.createObjectPattern(m_token.m_location);
990 if (hasDestructuringPattern)
991 *hasDestructuringPattern = true;
994 bool wasString = false;
996 if (match(CLOSEBRACE))
999 const Identifier* propertyName = nullptr;
1000 TreeExpression propertyExpression = 0;
1001 TreeDestructuringPattern innerPattern = 0;
1002 JSTokenLocation location = m_token.m_location;
1003 if (matchSpecIdentifier()) {
1004 failIfTrue(match(LET) && (kind == DestructuringKind::DestructureToLet || kind == DestructuringKind::DestructureToConst), "Can't use 'let' as an identifier name for a LexicalDeclaration");
1005 propertyName = m_token.m_data.ident;
1006 JSToken identifierToken = m_token;
1009 innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
1011 if (kind == DestructuringKind::DestructureToExpressions) {
1012 bool isEvalOrArguments = m_vm->propertyNames->eval == *propertyName || m_vm->propertyNames->arguments == *propertyName;
1013 if (isEvalOrArguments && strictMode())
1014 reclassifyExpressionError(ErrorIndicatesPattern, ErrorIndicatesNothing);
1015 failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", propertyName->impl(), "' in strict mode");
1017 innerPattern = createBindingPattern(context, kind, exportType, *propertyName, identifierToken, bindingContext, duplicateIdentifier);
1020 JSTokenType tokenType = m_token.m_type;
1021 switch (m_token.m_type) {
1024 propertyName = &m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), m_token.m_data.doubleValue);
1027 propertyName = m_token.m_data.ident;
1032 propertyExpression = parseAssignmentExpression(context);
1033 failIfFalse(propertyExpression, "Cannot parse computed property name");
1034 matchOrFail(CLOSEBRACKET, "Expected ']' to end end a computed property name");
1037 if (m_token.m_type != RESERVED && m_token.m_type != RESERVED_IF_STRICT && !(m_token.m_type & KeywordTokenFlag)) {
1038 if (kind == DestructuringKind::DestructureToExpressions)
1040 failWithMessage("Expected a property name");
1042 propertyName = m_token.m_data.ident;
1046 if (!consume(COLON)) {
1047 if (kind == DestructuringKind::DestructureToExpressions)
1049 semanticFailIfTrue(tokenType == RESERVED, "Cannot use abbreviated destructuring syntax for reserved name '", propertyName->impl(), "'");
1050 semanticFailIfTrue(tokenType == RESERVED_IF_STRICT, "Cannot use abbreviated destructuring syntax for reserved name '", propertyName->impl(), "' in strict mode");
1051 semanticFailIfTrue(tokenType & KeywordTokenFlag, "Cannot use abbreviated destructuring syntax for keyword '", propertyName->impl(), "'");
1053 failWithMessage("Expected a ':' prior to a named destructuring property");
1055 innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
1057 if (kind == DestructuringKind::DestructureToExpressions && !innerPattern)
1059 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
1060 TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
1062 if (propertyExpression)
1063 context.appendObjectPatternEntry(objectPattern, location, propertyExpression, innerPattern, defaultValue);
1065 ASSERT(propertyName);
1066 context.appendObjectPatternEntry(objectPattern, location, wasString, *propertyName, innerPattern, defaultValue);
1068 } while (consume(COMMA));
1070 if (kind == DestructuringKind::DestructureToExpressions && !match(CLOSEBRACE))
1072 consumeOrFail(CLOSEBRACE, "Expected either a closing '}' or an ',' after a property destructuring pattern");
1073 pattern = objectPattern;
1078 if (!matchSpecIdentifier()) {
1079 if (kind == DestructuringKind::DestructureToExpressions)
1081 semanticFailureDueToKeyword(destructuringKindToVariableKindName(kind));
1082 failWithMessage("Expected a parameter pattern or a ')' in parameter list");
1084 failIfTrue(match(LET) && (kind == DestructuringKind::DestructureToLet || kind == DestructuringKind::DestructureToConst), "Can't use 'let' as an identifier name for a LexicalDeclaration");
1085 pattern = createBindingPattern(context, kind, exportType, *m_token.m_data.ident, m_token, bindingContext, duplicateIdentifier);
1090 m_parserState.nonLHSCount = nonLHSCount;
1094 template <typename LexerType>
1095 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseDefaultValueForDestructuringPattern(TreeBuilder& context)
1100 next(TreeBuilder::DontBuildStrings); // consume '='
1101 return parseAssignmentExpression(context);
1104 template <typename LexerType>
1105 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement(TreeBuilder& context)
1108 JSTokenLocation location(tokenLocation());
1109 int startLine = tokenLine();
1111 handleProductionOrFail(OPENPAREN, "(", "start", "for-loop header");
1112 int nonLHSCount = m_parserState.nonLHSCount;
1113 int declarations = 0;
1114 JSTextPosition declsStart;
1115 JSTextPosition declsEnd;
1116 TreeExpression decls = 0;
1117 TreeDestructuringPattern pattern = 0;
1118 bool isVarDeclaraton = match(VAR);
1119 bool isLetDeclaration = match(LET);
1120 bool isConstDeclaration = match(CONSTTOKEN);
1121 bool forLoopConstDoesNotHaveInitializer = false;
1123 VariableEnvironment dummySet;
1124 VariableEnvironment* lexicalVariables = nullptr;
1125 AutoCleanupLexicalScope lexicalScope;
1127 auto gatherLexicalVariablesIfNecessary = [&] {
1128 if (isLetDeclaration || isConstDeclaration) {
1129 ScopeRef scope = lexicalScope.scope();
1130 lexicalVariables = &scope->finalizeLexicalEnvironment();
1132 lexicalVariables = &dummySet;
1135 auto popLexicalScopeIfNecessary = [&] {
1136 if (isLetDeclaration || isConstDeclaration)
1137 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1140 if (isVarDeclaraton || isLetDeclaration || isConstDeclaration) {
1142 for (var/let/const IDENT in/of expression) statement
1143 for (var/let/const varDeclarationList; expressionOpt; expressionOpt)
1145 if (isLetDeclaration || isConstDeclaration) {
1146 ScopeRef newScope = pushScope();
1147 newScope->setIsLexicalScope();
1148 newScope->preventVarDeclarations();
1149 lexicalScope.setIsValid(newScope, this);
1152 TreeDestructuringPattern forInTarget = 0;
1153 TreeExpression forInInitializer = 0;
1155 JSTextPosition initStart;
1156 JSTextPosition initEnd;
1157 DeclarationType declarationType;
1158 if (isVarDeclaraton)
1159 declarationType = DeclarationType::VarDeclaration;
1160 else if (isLetDeclaration)
1161 declarationType = DeclarationType::LetDeclaration;
1162 else if (isConstDeclaration)
1163 declarationType = DeclarationType::ConstDeclaration;
1165 RELEASE_ASSERT_NOT_REACHED();
1166 decls = parseVariableDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd, ForLoopContext, declarationType, ExportType::NotExported, forLoopConstDoesNotHaveInitializer);
1170 // Remainder of a standard for loop is handled identically
1171 if (match(SEMICOLON))
1172 goto standardForLoop;
1174 failIfFalse(declarations == 1, "can only declare a single variable in an enumeration");
1176 // Handle for-in with var declaration
1177 JSTextPosition inLocation = tokenStartPosition();
1178 bool isOfEnumeration = false;
1179 if (!consume(INTOKEN)) {
1180 failIfFalse(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax");
1181 isOfEnumeration = true;
1184 bool hasAnyAssignments = !!forInInitializer;
1185 if (hasAnyAssignments) {
1186 if (isOfEnumeration)
1187 internalFailWithMessage(false, "Cannot assign to the loop variable inside a for-of loop header");
1188 if (strictMode() || (isLetDeclaration || isConstDeclaration) || !context.isBindingNode(forInTarget))
1189 internalFailWithMessage(false, "Cannot assign to the loop variable inside a for-in loop header");
1191 TreeExpression expr = parseExpression(context);
1192 failIfFalse(expr, "Expected expression to enumerate");
1193 JSTextPosition exprEnd = lastTokenEndPosition();
1195 int endLine = tokenLine();
1197 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
1199 const Identifier* unused = 0;
1201 TreeStatement statement = parseStatement(context, unused);
1203 failIfFalse(statement, "Expected statement as body of for-", isOfEnumeration ? "of" : "in", " statement");
1204 gatherLexicalVariablesIfNecessary();
1205 TreeStatement result;
1206 if (isOfEnumeration)
1207 result = context.createForOfLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
1209 result = context.createForInLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
1210 popLexicalScopeIfNecessary();
1214 if (!match(SEMICOLON)) {
1215 if (match(OPENBRACE) || match(OPENBRACKET)) {
1216 SavePoint savePoint = createSavePoint();
1217 declsStart = tokenStartPosition();
1218 pattern = tryParseDestructuringPatternExpression(context, AssignmentContext::DeclarationStatement);
1219 declsEnd = lastTokenEndPosition();
1220 if (pattern && (match(INTOKEN) || (match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of)))
1221 goto enumerationLoop;
1222 pattern = TreeDestructuringPattern(0);
1223 restoreSavePoint(savePoint);
1226 declsStart = tokenStartPosition();
1227 decls = parseExpression(context);
1228 declsEnd = lastTokenEndPosition();
1230 failIfFalse(decls, "Cannot parse for loop declarations");
1233 if (match(SEMICOLON)) {
1235 // Standard for loop
1237 TreeExpression condition = 0;
1238 failIfTrue(forLoopConstDoesNotHaveInitializer && isConstDeclaration, "const variables in for loops must have initializers");
1240 if (!match(SEMICOLON)) {
1241 condition = parseExpression(context);
1242 failIfFalse(condition, "Cannot parse for loop condition expression");
1244 consumeOrFail(SEMICOLON, "Expected a ';' after the for loop condition expression");
1246 TreeExpression increment = 0;
1247 if (!match(CLOSEPAREN)) {
1248 increment = parseExpression(context);
1249 failIfFalse(increment, "Cannot parse for loop iteration expression");
1251 int endLine = tokenLine();
1252 handleProductionOrFail(CLOSEPAREN, ")", "end", "for-loop header");
1253 const Identifier* unused = 0;
1255 TreeStatement statement = parseStatement(context, unused);
1257 failIfFalse(statement, "Expected a statement as the body of a for loop");
1258 gatherLexicalVariablesIfNecessary();
1259 TreeStatement result = context.createForLoop(location, decls, condition, increment, statement, startLine, endLine, *lexicalVariables);
1260 popLexicalScopeIfNecessary();
1264 // For-in and For-of loop
1266 failIfFalse(nonLHSCount == m_parserState.nonLHSCount, "Expected a reference on the left hand side of an enumeration statement");
1267 bool isOfEnumeration = false;
1268 if (!consume(INTOKEN)) {
1269 failIfFalse(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax");
1270 isOfEnumeration = true;
1273 TreeExpression expr = parseExpression(context);
1274 failIfFalse(expr, "Cannot parse subject for-", isOfEnumeration ? "of" : "in", " statement");
1275 JSTextPosition exprEnd = lastTokenEndPosition();
1276 int endLine = tokenLine();
1278 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
1279 const Identifier* unused = 0;
1281 TreeStatement statement = parseStatement(context, unused);
1283 failIfFalse(statement, "Expected a statement as the body of a for-", isOfEnumeration ? "of" : "in", "loop");
1284 gatherLexicalVariablesIfNecessary();
1285 TreeStatement result;
1288 if (isOfEnumeration)
1289 result = context.createForOfLoop(location, pattern, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1291 result = context.createForInLoop(location, pattern, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1293 popLexicalScopeIfNecessary();
1296 if (isOfEnumeration)
1297 result = context.createForOfLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1299 result = context.createForInLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1300 popLexicalScopeIfNecessary();
1304 template <typename LexerType>
1305 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatement(TreeBuilder& context)
1307 ASSERT(match(BREAK));
1308 JSTokenLocation location(tokenLocation());
1309 JSTextPosition start = tokenStartPosition();
1310 JSTextPosition end = tokenEndPosition();
1313 if (autoSemiColon()) {
1314 semanticFailIfFalse(breakIsValid(), "'break' is only valid inside a switch or loop statement");
1315 return context.createBreakStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
1317 failIfFalse(matchSpecIdentifier(), "Expected an identifier as the target for a break statement");
1318 const Identifier* ident = m_token.m_data.ident;
1319 semanticFailIfFalse(getLabel(ident), "Cannot use the undeclared label '", ident->impl(), "'");
1320 end = tokenEndPosition();
1322 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted break statement");
1323 return context.createBreakStatement(location, ident, start, end);
1326 template <typename LexerType>
1327 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueStatement(TreeBuilder& context)
1329 ASSERT(match(CONTINUE));
1330 JSTokenLocation location(tokenLocation());
1331 JSTextPosition start = tokenStartPosition();
1332 JSTextPosition end = tokenEndPosition();
1335 if (autoSemiColon()) {
1336 semanticFailIfFalse(continueIsValid(), "'continue' is only valid inside a loop statement");
1337 return context.createContinueStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
1339 failIfFalse(matchSpecIdentifier(), "Expected an identifier as the target for a continue statement");
1340 const Identifier* ident = m_token.m_data.ident;
1341 ScopeLabelInfo* label = getLabel(ident);
1342 semanticFailIfFalse(label, "Cannot use the undeclared label '", ident->impl(), "'");
1343 semanticFailIfFalse(label->isLoop, "Cannot continue to the label '", ident->impl(), "' as it is not targeting a loop");
1344 end = tokenEndPosition();
1346 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted continue statement");
1347 return context.createContinueStatement(location, ident, start, end);
1350 template <typename LexerType>
1351 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStatement(TreeBuilder& context)
1353 ASSERT(match(RETURN));
1354 JSTokenLocation location(tokenLocation());
1355 semanticFailIfFalse(currentScope()->isFunction(), "Return statements are only valid inside functions");
1356 JSTextPosition start = tokenStartPosition();
1357 JSTextPosition end = tokenEndPosition();
1359 // We do the auto semicolon check before attempting to parse expression
1360 // as we need to ensure the a line break after the return correctly terminates
1362 if (match(SEMICOLON))
1363 end = tokenEndPosition();
1365 if (autoSemiColon())
1366 return context.createReturnStatement(location, 0, start, end);
1367 TreeExpression expr = parseExpression(context);
1368 failIfFalse(expr, "Cannot parse the return expression");
1369 end = lastTokenEndPosition();
1370 if (match(SEMICOLON))
1371 end = tokenEndPosition();
1372 if (!autoSemiColon())
1373 failWithMessage("Expected a ';' following a return statement");
1374 return context.createReturnStatement(location, expr, start, end);
1377 template <typename LexerType>
1378 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseThrowStatement(TreeBuilder& context)
1380 ASSERT(match(THROW));
1381 JSTokenLocation location(tokenLocation());
1382 JSTextPosition start = tokenStartPosition();
1384 failIfTrue(match(SEMICOLON), "Expected expression after 'throw'");
1385 semanticFailIfTrue(autoSemiColon(), "Cannot have a newline after 'throw'");
1387 TreeExpression expr = parseExpression(context);
1388 failIfFalse(expr, "Cannot parse expression for throw statement");
1389 JSTextPosition end = lastTokenEndPosition();
1390 failIfFalse(autoSemiColon(), "Expected a ';' after a throw statement");
1392 return context.createThrowStatement(location, expr, start, end);
1395 template <typename LexerType>
1396 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement(TreeBuilder& context)
1398 ASSERT(match(WITH));
1399 JSTokenLocation location(tokenLocation());
1400 semanticFailIfTrue(strictMode(), "'with' statements are not valid in strict mode");
1401 currentScope()->setNeedsFullActivation();
1402 int startLine = tokenLine();
1405 handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'with' statement");
1406 int start = tokenStart();
1407 TreeExpression expr = parseExpression(context);
1408 failIfFalse(expr, "Cannot parse 'with' subject expression");
1409 JSTextPosition end = lastTokenEndPosition();
1410 int endLine = tokenLine();
1411 handleProductionOrFail(CLOSEPAREN, ")", "start", "subject of a 'with' statement");
1412 const Identifier* unused = 0;
1413 TreeStatement statement = parseStatement(context, unused);
1414 failIfFalse(statement, "A 'with' statement must have a body");
1416 return context.createWithStatement(location, expr, statement, start, end, startLine, endLine);
1419 template <typename LexerType>
1420 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseSwitchStatement(TreeBuilder& context)
1422 ASSERT(match(SWITCH));
1423 JSTokenLocation location(tokenLocation());
1424 int startLine = tokenLine();
1426 handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'switch'");
1427 TreeExpression expr = parseExpression(context);
1428 failIfFalse(expr, "Cannot parse switch subject expression");
1429 int endLine = tokenLine();
1431 handleProductionOrFail(CLOSEPAREN, ")", "end", "subject of a 'switch'");
1432 handleProductionOrFail(OPENBRACE, "{", "start", "body of a 'switch'");
1433 AutoPopScopeRef lexicalScope(this, pushScope());
1434 lexicalScope->setIsLexicalScope();
1435 lexicalScope->preventVarDeclarations();
1437 TreeClauseList firstClauses = parseSwitchClauses(context);
1440 TreeClause defaultClause = parseSwitchDefaultClause(context);
1443 TreeClauseList secondClauses = parseSwitchClauses(context);
1446 handleProductionOrFail(CLOSEBRACE, "}", "end", "body of a 'switch'");
1448 TreeStatement result = context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine, lexicalScope->finalizeLexicalEnvironment(), lexicalScope->takeFunctionDeclarations());
1449 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1453 template <typename LexerType>
1454 template <class TreeBuilder> TreeClauseList Parser<LexerType>::parseSwitchClauses(TreeBuilder& context)
1458 unsigned startOffset = tokenStart();
1460 TreeExpression condition = parseExpression(context);
1461 failIfFalse(condition, "Cannot parse switch clause");
1462 consumeOrFail(COLON, "Expected a ':' after switch clause expression");
1463 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1464 failIfFalse(statements, "Cannot parse the body of a switch clause");
1465 TreeClause clause = context.createClause(condition, statements);
1466 context.setStartOffset(clause, startOffset);
1467 TreeClauseList clauseList = context.createClauseList(clause);
1468 TreeClauseList tail = clauseList;
1470 while (match(CASE)) {
1471 startOffset = tokenStart();
1473 TreeExpression condition = parseExpression(context);
1474 failIfFalse(condition, "Cannot parse switch case expression");
1475 consumeOrFail(COLON, "Expected a ':' after switch clause expression");
1476 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1477 failIfFalse(statements, "Cannot parse the body of a switch clause");
1478 clause = context.createClause(condition, statements);
1479 context.setStartOffset(clause, startOffset);
1480 tail = context.createClauseList(tail, clause);
1485 template <typename LexerType>
1486 template <class TreeBuilder> TreeClause Parser<LexerType>::parseSwitchDefaultClause(TreeBuilder& context)
1488 if (!match(DEFAULT))
1490 unsigned startOffset = tokenStart();
1492 consumeOrFail(COLON, "Expected a ':' after switch default clause");
1493 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1494 failIfFalse(statements, "Cannot parse the body of a switch default clause");
1495 TreeClause result = context.createClause(0, statements);
1496 context.setStartOffset(result, startOffset);
1500 template <typename LexerType>
1501 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(TreeBuilder& context)
1504 JSTokenLocation location(tokenLocation());
1505 TreeStatement tryBlock = 0;
1506 TreeDestructuringPattern catchPattern = 0;
1507 TreeStatement catchBlock = 0;
1508 TreeStatement finallyBlock = 0;
1509 int firstLine = tokenLine();
1511 matchOrFail(OPENBRACE, "Expected a block statement as body of a try statement");
1513 tryBlock = parseBlockStatement(context);
1514 failIfFalse(tryBlock, "Cannot parse the body of try block");
1515 int lastLine = m_lastTokenEndPosition.line;
1516 VariableEnvironment catchEnvironment;
1520 handleProductionOrFail(OPENPAREN, "(", "start", "'catch' target");
1521 AutoPopScopeRef catchScope(this, pushScope());
1522 catchScope->setIsLexicalScope();
1523 catchScope->preventVarDeclarations();
1524 const Identifier* ident = nullptr;
1525 if (matchSpecIdentifier()) {
1526 ident = m_token.m_data.ident;
1527 catchPattern = context.createBindingLocation(m_token.m_location, *ident, m_token.m_startPosition, m_token.m_endPosition, AssignmentContext::DeclarationStatement);
1529 failIfTrueIfStrict(catchScope->declareLexicalVariable(ident, false) & DeclarationResult::InvalidStrictMode, "Cannot declare a catch variable named '", ident->impl(), "' in strict mode");
1531 catchPattern = parseDestructuringPattern(context, DestructuringKind::DestructureToCatchParameters, ExportType::NotExported);
1532 failIfFalse(catchPattern, "Cannot parse this destructuring pattern");
1534 handleProductionOrFail(CLOSEPAREN, ")", "end", "'catch' target");
1535 matchOrFail(OPENBRACE, "Expected exception handler to be a block statement");
1536 catchBlock = parseBlockStatement(context);
1537 failIfFalse(catchBlock, "Unable to parse 'catch' block");
1538 catchEnvironment = catchScope->finalizeLexicalEnvironment();
1539 RELEASE_ASSERT(!ident || (catchEnvironment.size() == 1 && catchEnvironment.contains(ident->impl())));
1540 popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo);
1543 if (match(FINALLY)) {
1545 matchOrFail(OPENBRACE, "Expected block statement for finally body");
1546 finallyBlock = parseBlockStatement(context);
1547 failIfFalse(finallyBlock, "Cannot parse finally body");
1549 failIfFalse(catchBlock || finallyBlock, "Try statements must have at least a catch or finally block");
1550 return context.createTryStatement(location, tryBlock, catchPattern, catchBlock, finallyBlock, firstLine, lastLine, catchEnvironment);
1553 template <typename LexerType>
1554 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDebuggerStatement(TreeBuilder& context)
1556 ASSERT(match(DEBUGGER));
1557 JSTokenLocation location(tokenLocation());
1558 int startLine = tokenLine();
1559 int endLine = startLine;
1561 if (match(SEMICOLON))
1562 startLine = tokenLine();
1563 failIfFalse(autoSemiColon(), "Debugger keyword must be followed by a ';'");
1564 return context.createDebugger(location, startLine, endLine);
1567 template <typename LexerType>
1568 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context)
1570 ASSERT(match(OPENBRACE));
1572 // We should treat the first block statement of the function (the body of the function) as the lexical
1573 // scope of the function itself, and not the lexical scope of a 'block' statement within the function.
1574 AutoCleanupLexicalScope lexicalScope;
1575 bool shouldPushLexicalScope = m_statementDepth > 0;
1576 if (shouldPushLexicalScope) {
1577 ScopeRef newScope = pushScope();
1578 newScope->setIsLexicalScope();
1579 newScope->preventVarDeclarations();
1580 lexicalScope.setIsValid(newScope, this);
1582 JSTokenLocation location(tokenLocation());
1583 int startOffset = m_token.m_data.offset;
1584 int start = tokenLine();
1585 VariableEnvironment emptyEnvironment;
1586 DeclarationStacks::FunctionStack emptyFunctionStack;
1588 if (match(CLOSEBRACE)) {
1589 int endOffset = m_token.m_data.offset;
1591 TreeStatement result = context.createBlockStatement(location, 0, start, m_lastTokenEndPosition.line, shouldPushLexicalScope ? currentScope()->finalizeLexicalEnvironment() : emptyEnvironment, shouldPushLexicalScope ? currentScope()->takeFunctionDeclarations() : WTFMove(emptyFunctionStack));
1592 context.setStartOffset(result, startOffset);
1593 context.setEndOffset(result, endOffset);
1594 if (shouldPushLexicalScope)
1595 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1598 TreeSourceElements subtree = parseSourceElements(context, DontCheckForStrictMode);
1599 failIfFalse(subtree, "Cannot parse the body of the block statement");
1600 matchOrFail(CLOSEBRACE, "Expected a closing '}' at the end of a block statement");
1601 int endOffset = m_token.m_data.offset;
1603 TreeStatement result = context.createBlockStatement(location, subtree, start, m_lastTokenEndPosition.line, shouldPushLexicalScope ? currentScope()->finalizeLexicalEnvironment() : emptyEnvironment, shouldPushLexicalScope ? currentScope()->takeFunctionDeclarations() : WTFMove(emptyFunctionStack));
1604 context.setStartOffset(result, startOffset);
1605 context.setEndOffset(result, endOffset);
1606 if (shouldPushLexicalScope)
1607 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1612 template <typename LexerType>
1613 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
1615 DepthManager statementDepth(&m_statementDepth);
1617 int nonTrivialExpressionCount = 0;
1618 failIfStackOverflow();
1619 TreeStatement result = 0;
1620 bool shouldSetEndOffset = true;
1621 bool parentAllowsFunctionDeclarationAsStatement = m_immediateParentAllowsFunctionDeclarationInStatement;
1622 m_immediateParentAllowsFunctionDeclarationInStatement = false;
1624 switch (m_token.m_type) {
1626 result = parseBlockStatement(context);
1627 shouldSetEndOffset = false;
1630 result = parseVariableDeclaration(context, DeclarationType::VarDeclaration);
1633 if (!strictMode()) {
1634 failIfFalse(parentAllowsFunctionDeclarationAsStatement, "Function declarations are only allowed inside block statements or at the top level of a program");
1635 if (currentScope()->isFunction()) {
1636 // Any function declaration that isn't in a block is a syntax error unless it's
1637 // in an if/else statement. If it's in an if/else statement, we will magically
1638 // treat it as if the if/else statement is inside a block statement.
1639 // to the very top like a "var". For example:
1641 // if (cond) function foo() { }
1643 // will be rewritten as:
1645 // if (cond) { function foo() { } }
1647 AutoPopScopeRef blockScope(this, pushScope());
1648 blockScope->setIsLexicalScope();
1649 blockScope->preventVarDeclarations();
1650 JSTokenLocation location(tokenLocation());
1651 int start = tokenLine();
1653 TreeStatement function = parseFunctionDeclaration(context);
1655 failIfFalse(function, "Expected valid function statement after 'function' keyword");
1656 TreeSourceElements sourceElements = context.createSourceElements();
1657 context.appendStatement(sourceElements, function);
1658 result = context.createBlockStatement(location, sourceElements, start, m_lastTokenEndPosition.line, currentScope()->finalizeLexicalEnvironment(), currentScope()->takeFunctionDeclarations());
1659 popScope(blockScope, TreeBuilder::NeedsFreeVariableInfo);
1661 // We only implement annex B.3.3 if we're in function mode. Otherwise, we fall back
1662 // to hoisting behavior.
1663 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=155813
1664 DepthManager statementDepth(&m_statementDepth);
1665 m_statementDepth = 1;
1666 result = parseFunctionDeclaration(context);
1669 failWithMessage("Function declarations are only allowed inside blocks or switch statements in strict mode");
1673 JSTokenLocation location(tokenLocation());
1675 result = context.createEmptyStatement(location);
1679 result = parseIfStatement(context);
1682 result = parseDoWhileStatement(context);
1685 result = parseWhileStatement(context);
1688 result = parseForStatement(context);
1691 result = parseContinueStatement(context);
1694 result = parseBreakStatement(context);
1697 result = parseReturnStatement(context);
1700 result = parseWithStatement(context);
1703 result = parseSwitchStatement(context);
1706 result = parseThrowStatement(context);
1709 result = parseTryStatement(context);
1712 result = parseDebuggerStatement(context);
1718 // These tokens imply the end of a set of source elements
1722 bool allowFunctionDeclarationAsStatement = false;
1723 result = parseExpressionOrLabelStatement(context, allowFunctionDeclarationAsStatement);
1727 directive = m_token.m_data.ident;
1728 if (directiveLiteralLength)
1729 *directiveLiteralLength = m_token.m_location.endOffset - m_token.m_location.startOffset;
1730 nonTrivialExpressionCount = m_parserState.nonTrivialExpressionCount;
1733 TreeStatement exprStatement = parseExpressionStatement(context);
1734 if (directive && nonTrivialExpressionCount != m_parserState.nonTrivialExpressionCount)
1735 directive = nullptr;
1736 result = exprStatement;
1740 if (result && shouldSetEndOffset)
1741 context.setEndOffset(result, m_lastTokenEndPosition.offset);
1745 template <typename LexerType>
1746 template <class TreeBuilder> bool Parser<LexerType>::parseFormalParameters(TreeBuilder& context, TreeFormalParameterList list, unsigned& parameterCount)
1748 #define failIfDuplicateIfViolation() \
1749 if (duplicateParameter) {\
1750 semanticFailIfTrue(defaultValue, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with default parameter values");\
1751 semanticFailIfTrue(hasDestructuringPattern, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with destructuring parameters");\
1752 semanticFailIfTrue(isRestParameter, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with a rest parameter");\
1755 bool hasDestructuringPattern = false;
1756 bool isRestParameter = false;
1757 const Identifier* duplicateParameter = nullptr;
1759 TreeDestructuringPattern parameter = 0;
1760 TreeExpression defaultValue = 0;
1762 if (UNLIKELY(match(CLOSEPAREN)))
1765 if (match(DOTDOTDOT)) {
1767 failIfFalse(matchSpecIdentifier(), "Rest parameter '...' should be followed by a variable identifier");
1768 declareRestOrNormalParameter(*m_token.m_data.ident, &duplicateParameter);
1770 JSTextPosition identifierStart = tokenStartPosition();
1771 JSTextPosition identifierEnd = tokenEndPosition();
1772 parameter = context.createRestParameter(*m_token.m_data.ident, parameterCount, identifierStart, identifierEnd);
1774 failIfTrue(match(COMMA), "Rest parameter should be the last parameter in a function declaration"); // Let's have a good error message for this common case.
1775 isRestParameter = true;
1777 parameter = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported, &duplicateParameter, &hasDestructuringPattern);
1778 failIfFalse(parameter, "Cannot parse parameter pattern");
1779 if (!isRestParameter)
1780 defaultValue = parseDefaultValueForDestructuringPattern(context);
1782 failIfDuplicateIfViolation();
1783 if (isRestParameter || defaultValue || hasDestructuringPattern)
1784 currentScope()->setHasNonSimpleParameterList();
1785 context.appendParameter(list, parameter, defaultValue);
1786 if (!isRestParameter)
1788 } while (!isRestParameter && consume(COMMA));
1791 #undef failIfDuplicateIfViolation
1794 template <typename LexerType>
1795 template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(
1796 TreeBuilder& context, SyntaxChecker& syntaxChecker, const JSTokenLocation& startLocation, int startColumn, int functionKeywordStart, int functionNameStart, int parametersStart,
1797 ConstructorKind constructorKind, SuperBinding superBinding, FunctionBodyType bodyType, unsigned parameterCount, SourceParseMode parseMode)
1799 bool isArrowFunctionBodyExpression = bodyType == ArrowFunctionBodyExpression;
1800 if (!isArrowFunctionBodyExpression) {
1802 if (match(CLOSEBRACE)) {
1803 unsigned endColumn = tokenColumn();
1804 return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, superBinding, parameterCount, parseMode, isArrowFunctionBodyExpression);
1808 DepthManager statementDepth(&m_statementDepth);
1809 m_statementDepth = 0;
1810 if (bodyType == ArrowFunctionBodyExpression)
1811 failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(syntaxChecker), "Cannot parse body of this arrow function");
1813 failIfFalse(parseSourceElements(syntaxChecker, CheckForStrictMode), bodyType == StandardFunctionBodyBlock ? "Cannot parse body of this function" : "Cannot parse body of this arrow function");
1814 unsigned endColumn = tokenColumn();
1815 return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, superBinding, parameterCount, parseMode, isArrowFunctionBodyExpression);
1818 static const char* stringForFunctionMode(SourceParseMode mode)
1821 case SourceParseMode::GetterMode:
1823 case SourceParseMode::SetterMode:
1825 case SourceParseMode::NormalFunctionMode:
1827 case SourceParseMode::MethodMode:
1829 case SourceParseMode::GeneratorBodyMode:
1831 case SourceParseMode::GeneratorWrapperFunctionMode:
1832 return "generator function";
1833 case SourceParseMode::ArrowFunctionMode:
1834 return "arrow function";
1835 case SourceParseMode::ProgramMode:
1836 case SourceParseMode::ModuleAnalyzeMode:
1837 case SourceParseMode::ModuleEvaluateMode:
1838 RELEASE_ASSERT_NOT_REACHED();
1841 RELEASE_ASSERT_NOT_REACHED();
1845 template <typename LexerType> template <class TreeBuilder, class FunctionInfoType> typename TreeBuilder::FormalParameterList Parser<LexerType>::parseFunctionParameters(TreeBuilder& context, SourceParseMode mode, FunctionInfoType& functionInfo)
1847 RELEASE_ASSERT(mode != SourceParseMode::ProgramMode && mode != SourceParseMode::ModuleAnalyzeMode && mode != SourceParseMode::ModuleEvaluateMode);
1848 TreeFormalParameterList parameterList = context.createFormalParameterList();
1849 SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_parserState.functionParsePhase, FunctionParsePhase::Parameters);
1851 if (mode == SourceParseMode::ArrowFunctionMode) {
1852 if (!match(IDENT) && !match(OPENPAREN)) {
1853 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
1854 failWithMessage("Expected an arrow function input parameter");
1856 if (match(OPENPAREN)) {
1859 if (match(CLOSEPAREN))
1860 functionInfo.parameterCount = 0;
1862 failIfFalse(parseFormalParameters(context, parameterList, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
1864 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
1866 functionInfo.parameterCount = 1;
1867 auto parameter = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported);
1868 failIfFalse(parameter, "Cannot parse parameter pattern");
1869 context.appendParameter(parameterList, parameter, 0);
1873 return parameterList;
1876 if (!consume(OPENPAREN)) {
1877 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
1878 failWithMessage("Expected an opening '(' before a ", stringForFunctionMode(mode), "'s parameter list");
1881 if (mode == SourceParseMode::GetterMode) {
1882 consumeOrFail(CLOSEPAREN, "getter functions must have no parameters");
1883 functionInfo.parameterCount = 0;
1884 } else if (mode == SourceParseMode::SetterMode) {
1885 failIfTrue(match(CLOSEPAREN), "setter functions must have one parameter");
1886 const Identifier* duplicateParameter = nullptr;
1887 auto parameter = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported, &duplicateParameter);
1888 failIfFalse(parameter, "setter functions must have one parameter");
1889 auto defaultValue = parseDefaultValueForDestructuringPattern(context);
1891 semanticFailIfTrue(duplicateParameter && defaultValue, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with default parameter values");
1892 context.appendParameter(parameterList, parameter, defaultValue);
1893 functionInfo.parameterCount = 1;
1894 failIfTrue(match(COMMA), "setter functions must have one parameter");
1895 consumeOrFail(CLOSEPAREN, "Expected a ')' after a parameter declaration");
1897 if (match(CLOSEPAREN))
1898 functionInfo.parameterCount = 0;
1900 failIfFalse(parseFormalParameters(context, parameterList, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
1901 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
1904 return parameterList;
1907 template <typename LexerType>
1908 template <class TreeBuilder> typename TreeBuilder::FormalParameterList Parser<LexerType>::createGeneratorParameters(TreeBuilder& context)
1910 auto parameters = context.createFormalParameterList();
1912 JSTokenLocation location(tokenLocation());
1913 JSTextPosition position = tokenStartPosition();
1916 declareParameter(&m_vm->propertyNames->builtinNames().generatorPrivateName());
1917 auto generator = context.createBindingLocation(location, m_vm->propertyNames->builtinNames().generatorPrivateName(), position, position, AssignmentContext::DeclarationStatement);
1918 context.appendParameter(parameters, generator, 0);
1921 declareParameter(&m_vm->propertyNames->builtinNames().generatorStatePrivateName());
1922 auto generatorState = context.createBindingLocation(location, m_vm->propertyNames->builtinNames().generatorStatePrivateName(), position, position, AssignmentContext::DeclarationStatement);
1923 context.appendParameter(parameters, generatorState, 0);
1926 declareParameter(&m_vm->propertyNames->builtinNames().generatorValuePrivateName());
1927 auto generatorValue = context.createBindingLocation(location, m_vm->propertyNames->builtinNames().generatorValuePrivateName(), position, position, AssignmentContext::DeclarationStatement);
1928 context.appendParameter(parameters, generatorValue, 0);
1930 // @generatorResumeMode
1931 declareParameter(&m_vm->propertyNames->builtinNames().generatorResumeModePrivateName());
1932 auto generatorResumeMode = context.createBindingLocation(location, m_vm->propertyNames->builtinNames().generatorResumeModePrivateName(), position, position, AssignmentContext::DeclarationStatement);
1933 context.appendParameter(parameters, generatorResumeMode, 0);
1938 template <typename LexerType>
1939 template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionRequirements requirements, SourceParseMode mode, bool nameIsInContainingScope, ConstructorKind constructorKind, SuperBinding expectedSuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>& functionInfo, FunctionDefinitionType functionDefinitionType)
1941 RELEASE_ASSERT(isFunctionParseMode(mode));
1943 bool upperScopeIsGenerator = currentScope()->isGenerator();
1944 AutoPopScopeRef functionScope(this, pushScope());
1945 functionScope->setSourceParseMode(mode);
1946 functionScope->setExpectedSuperBinding(expectedSuperBinding);
1947 functionScope->setConstructorKind(constructorKind);
1948 SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_parserState.functionParsePhase, FunctionParsePhase::Body);
1949 int functionNameStart = m_token.m_location.startOffset;
1950 const Identifier* lastFunctionName = m_parserState.lastFunctionName;
1951 m_parserState.lastFunctionName = nullptr;
1952 int parametersStart = -1;
1953 JSTokenLocation startLocation;
1954 int startColumn = -1;
1955 FunctionBodyType functionBodyType;
1957 auto loadCachedFunction = [&] () -> bool {
1958 ASSERT(parametersStart != -1);
1959 ASSERT(startColumn != -1);
1961 // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
1962 if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(parametersStart) : 0) {
1963 // If we're in a strict context, the cached function info must say it was strict too.
1964 ASSERT(!strictMode() || cachedInfo->strictMode);
1965 JSTokenLocation endLocation;
1967 ConstructorKind constructorKind = static_cast<ConstructorKind>(cachedInfo->constructorKind);
1968 SuperBinding expectedSuperBinding = static_cast<SuperBinding>(cachedInfo->expectedSuperBinding);
1970 endLocation.line = cachedInfo->lastTokenLine;
1971 endLocation.startOffset = cachedInfo->lastTokenStartOffset;
1972 endLocation.lineStartOffset = cachedInfo->lastTokenLineStartOffset;
1973 ASSERT(endLocation.startOffset >= endLocation.lineStartOffset);
1975 bool endColumnIsOnStartLine = endLocation.line == functionInfo.startLine;
1976 unsigned currentLineStartOffset = m_lexer->currentLineStartOffset();
1977 unsigned bodyEndColumn = endColumnIsOnStartLine ? endLocation.startOffset - currentLineStartOffset : endLocation.startOffset - endLocation.lineStartOffset;
1979 ASSERT(endLocation.startOffset >= endLocation.lineStartOffset);
1981 FunctionBodyType functionBodyType;
1982 if (mode == SourceParseMode::ArrowFunctionMode)
1983 functionBodyType = cachedInfo->isBodyArrowExpression ? ArrowFunctionBodyExpression : ArrowFunctionBodyBlock;
1985 functionBodyType = StandardFunctionBodyBlock;
1987 functionInfo.body = context.createFunctionMetadata(
1988 startLocation, endLocation, startColumn, bodyEndColumn,
1989 functionKeywordStart, functionNameStart, parametersStart,
1990 cachedInfo->strictMode, constructorKind, expectedSuperBinding, cachedInfo->parameterCount, mode, functionBodyType == ArrowFunctionBodyExpression);
1991 functionInfo.endOffset = cachedInfo->endFunctionOffset;
1992 functionInfo.parameterCount = cachedInfo->parameterCount;
1994 functionScope->restoreFromSourceProviderCache(cachedInfo);
1995 popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo);
1997 m_token = cachedInfo->endFunctionToken();
1999 if (endColumnIsOnStartLine)
2000 m_token.m_location.lineStartOffset = currentLineStartOffset;
2002 m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset);
2003 m_lexer->setLineNumber(m_token.m_location.line);
2005 switch (functionBodyType) {
2006 case ArrowFunctionBodyExpression:
2008 context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
2010 case ArrowFunctionBodyBlock:
2011 case StandardFunctionBodyBlock:
2012 context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
2016 functionInfo.endLine = m_lastTokenEndPosition.line;
2023 SyntaxChecker syntaxChecker(const_cast<VM*>(m_vm), m_lexer.get());
2025 if (mode == SourceParseMode::ArrowFunctionMode) {
2026 startLocation = tokenLocation();
2027 functionInfo.startLine = tokenLine();
2028 startColumn = tokenColumn();
2030 parametersStart = m_token.m_location.startOffset;
2031 functionInfo.startOffset = parametersStart;
2032 functionInfo.parametersStartColumn = startColumn;
2034 if (loadCachedFunction())
2036 parseFunctionParameters(syntaxChecker, mode, functionInfo);
2039 matchOrFail(ARROWFUNCTION, "Expected a '=>' after arrow function parameter declaration");
2041 if (m_lexer->prevTerminator())
2042 failDueToUnexpectedToken();
2044 ASSERT(constructorKind == ConstructorKind::None);
2046 // Check if arrow body start with {. If it true it mean that arrow function is Fat arrow function
2047 // and we need use common approach to parse function body
2049 functionBodyType = match(OPENBRACE) ? ArrowFunctionBodyBlock : ArrowFunctionBodyExpression;
2051 // http://ecma-international.org/ecma-262/6.0/#sec-function-definitions
2052 // FunctionExpression :
2053 // function BindingIdentifieropt ( FormalParameters ) { FunctionBody }
2055 // FunctionDeclaration[Yield, Default] :
2056 // function BindingIdentifier[?Yield] ( FormalParameters ) { FunctionBody }
2057 // [+Default] function ( FormalParameters ) { FunctionBody }
2059 // GeneratorDeclaration[Yield, Default] :
2060 // function * BindingIdentifier[?Yield] ( FormalParameters[Yield] ) { GeneratorBody }
2061 // [+Default] function * ( FormalParameters[Yield] ) { GeneratorBody }
2063 // GeneratorExpression :
2064 // function * BindingIdentifier[Yield]opt ( FormalParameters[Yield] ) { GeneratorBody }
2066 // The name of FunctionExpression can accept "yield" even in the context of generator.
2067 if (functionDefinitionType == FunctionDefinitionType::Expression && mode == SourceParseMode::NormalFunctionMode)
2068 upperScopeIsGenerator = false;
2070 if (matchSpecIdentifier(upperScopeIsGenerator)) {
2071 functionInfo.name = m_token.m_data.ident;
2072 m_parserState.lastFunctionName = functionInfo.name;
2074 if (!nameIsInContainingScope)
2075 failIfTrueIfStrict(functionScope->declareCallee(functionInfo.name) & DeclarationResult::InvalidStrictMode, "'", functionInfo.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode");
2076 } else if (requirements == FunctionNeedsName) {
2077 if (match(OPENPAREN) && mode == SourceParseMode::NormalFunctionMode)
2078 semanticFail("Function statements must have a name");
2079 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
2080 failDueToUnexpectedToken();
2084 startLocation = tokenLocation();
2085 functionInfo.startLine = tokenLine();
2086 startColumn = tokenColumn();
2087 functionInfo.parametersStartColumn = startColumn;
2089 parametersStart = m_token.m_location.startOffset;
2090 functionInfo.startOffset = parametersStart;
2092 if (loadCachedFunction())
2094 parseFunctionParameters(syntaxChecker, mode, functionInfo);
2097 matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body");
2099 // BytecodeGenerator emits code to throw TypeError when a class constructor is "call"ed.
2100 // Set ConstructorKind to None for non-constructor methods of classes.
2102 if (m_defaultConstructorKind != ConstructorKind::None) {
2103 constructorKind = m_defaultConstructorKind;
2104 expectedSuperBinding = m_defaultConstructorKind == ConstructorKind::Derived ? SuperBinding::Needed : SuperBinding::NotNeeded;
2107 functionBodyType = StandardFunctionBodyBlock;
2110 functionScope->setConstructorKind(constructorKind);
2111 functionScope->setExpectedSuperBinding(expectedSuperBinding);
2113 m_parserState.lastFunctionName = lastFunctionName;
2114 ParserState oldState = internalSaveParserState();
2116 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=156962
2117 // This loop collects the set of capture candidates that aren't
2118 // part of the set of this function's declared parameters. We will
2119 // figure out which parameters are captured for this function when
2120 // we actually generate code for it. For now, we just propagate to
2121 // our parent scopes which variables we might have closed over that
2122 // belong to them. This is necessary for correctness when using
2123 // the source provider cache because we can't close over a variable
2124 // that we don't claim to close over. The source provider cache must
2125 // know this information to properly cache this function.
2126 // This might work itself out nicer if we declared a different
2127 // Scope struct for the parameters (because they are indeed implemented
2128 // as their own scope).
2129 UniquedStringImplPtrSet nonLocalCapturesFromParameterExpressions;
2130 functionScope->forEachUsedVariable([&] (UniquedStringImpl* impl) {
2131 if (!functionScope->hasDeclaredParameter(impl))
2132 nonLocalCapturesFromParameterExpressions.add(impl);
2135 auto performParsingFunctionBody = [&] {
2136 return parseFunctionBody(context, syntaxChecker, startLocation, startColumn, functionKeywordStart, functionNameStart, parametersStart, constructorKind, expectedSuperBinding, functionBodyType, functionInfo.parameterCount, mode);
2139 if (mode == SourceParseMode::GeneratorWrapperFunctionMode) {
2140 AutoPopScopeRef generatorBodyScope(this, pushScope());
2141 generatorBodyScope->setSourceParseMode(SourceParseMode::GeneratorBodyMode);
2142 generatorBodyScope->setConstructorKind(ConstructorKind::None);
2143 generatorBodyScope->setExpectedSuperBinding(expectedSuperBinding);
2145 functionInfo.body = performParsingFunctionBody();
2147 // When a generator has a "use strict" directive, a generator function wrapping it should be strict mode.
2148 if (generatorBodyScope->strictMode())
2149 functionScope->setStrictMode();
2151 popScope(generatorBodyScope, TreeBuilder::NeedsFreeVariableInfo);
2153 functionInfo.body = performParsingFunctionBody();
2155 restoreParserState(oldState);
2156 failIfFalse(functionInfo.body, "Cannot parse the body of this ", stringForFunctionMode(mode));
2157 context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
2158 if (functionScope->strictMode() && functionInfo.name) {
2159 RELEASE_ASSERT(mode == SourceParseMode::NormalFunctionMode || mode == SourceParseMode::MethodMode || mode == SourceParseMode::ArrowFunctionMode || mode == SourceParseMode::GeneratorBodyMode || mode == SourceParseMode::GeneratorWrapperFunctionMode);
2160 semanticFailIfTrue(m_vm->propertyNames->arguments == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
2161 semanticFailIfTrue(m_vm->propertyNames->eval == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
2164 JSTokenLocation location = JSTokenLocation(m_token.m_location);
2165 functionInfo.endOffset = m_token.m_data.offset;
2167 if (functionBodyType == ArrowFunctionBodyExpression) {
2168 location = locationBeforeLastToken();
2169 functionInfo.endOffset = location.endOffset;
2172 // Cache the tokenizer state and the function scope the first time the function is parsed.
2173 // Any future reparsing can then skip the function.
2174 // For arrow function is 8 = x=>x + 4 symbols;
2175 // For ordinary function is 16 = function(){} + 4 symbols
2176 const int minimumFunctionLengthToCache = functionBodyType == StandardFunctionBodyBlock ? 16 : 8;
2177 std::unique_ptr<SourceProviderCacheItem> newInfo;
2178 int functionLength = functionInfo.endOffset - functionInfo.startOffset;
2179 if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) {
2180 SourceProviderCacheItemCreationParameters parameters;
2181 parameters.endFunctionOffset = functionInfo.endOffset;
2182 parameters.functionNameStart = functionNameStart;
2183 parameters.lastTokenLine = location.line;
2184 parameters.lastTokenStartOffset = location.startOffset;
2185 parameters.lastTokenEndOffset = location.endOffset;
2186 parameters.lastTokenLineStartOffset = location.lineStartOffset;
2187 parameters.parameterCount = functionInfo.parameterCount;
2188 parameters.constructorKind = constructorKind;
2189 parameters.expectedSuperBinding = expectedSuperBinding;
2190 if (functionBodyType == ArrowFunctionBodyExpression) {
2191 parameters.isBodyArrowExpression = true;
2192 parameters.tokenType = m_token.m_type;
2194 functionScope->fillParametersForSourceProviderCache(parameters, nonLocalCapturesFromParameterExpressions);
2195 newInfo = SourceProviderCacheItem::create(parameters);
2198 popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo);
2200 if (functionBodyType != ArrowFunctionBodyExpression) {
2201 matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body");
2206 m_functionCache->add(functionInfo.startOffset, WTFMove(newInfo));
2208 functionInfo.endLine = m_lastTokenEndPosition.line;
2212 static NO_RETURN_DUE_TO_CRASH FunctionMetadataNode* getMetadata(ParserFunctionInfo<SyntaxChecker>&) { RELEASE_ASSERT_NOT_REACHED(); }
2213 static FunctionMetadataNode* getMetadata(ParserFunctionInfo<ASTBuilder>& info) { return info.body; }
2215 template <typename LexerType>
2216 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context, ExportType exportType)
2218 ASSERT(match(FUNCTION));
2219 JSTokenLocation location(tokenLocation());
2220 unsigned functionKeywordStart = tokenStart();
2222 ParserFunctionInfo<TreeBuilder> functionInfo;
2223 SourceParseMode parseMode = SourceParseMode::NormalFunctionMode;
2225 parseMode = SourceParseMode::GeneratorWrapperFunctionMode;
2226 failIfFalse((parseFunctionInfo(context, FunctionNeedsName, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration)), "Cannot parse this function");
2227 failIfFalse(functionInfo.name, "Function statements must have a name");
2229 std::pair<DeclarationResultMask, ScopeRef> functionDeclaration = declareFunction(functionInfo.name);
2230 DeclarationResultMask declarationResult = functionDeclaration.first;
2231 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a function named '", functionInfo.name->impl(), "' in strict mode");
2232 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
2233 internalFailWithMessage(false, "Cannot declare a function that shadows a let/const/class/function variable '", functionInfo.name->impl(), "' in strict mode");
2234 if (exportType == ExportType::Exported) {
2235 semanticFailIfFalse(exportName(*functionInfo.name), "Cannot export a duplicate function name: '", functionInfo.name->impl(), "'");
2236 m_moduleScopeData->exportBinding(*functionInfo.name);
2239 TreeStatement result = context.createFuncDeclStatement(location, functionInfo);
2240 if (TreeBuilder::CreatesAST)
2241 functionDeclaration.second->appendFunction(getMetadata(functionInfo));
2245 template <typename LexerType>
2246 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseClassDeclaration(TreeBuilder& context, ExportType exportType)
2248 ASSERT(match(CLASSTOKEN));
2249 JSTokenLocation location(tokenLocation());
2250 JSTextPosition classStart = tokenStartPosition();
2251 unsigned classStartLine = tokenLine();
2253 ParserClassInfo<TreeBuilder> info;
2254 TreeClassExpression classExpr = parseClass(context, FunctionNeedsName, info);
2255 failIfFalse(classExpr, "Failed to parse class");
2257 DeclarationResultMask declarationResult = declareVariable(info.className, DeclarationType::LetDeclaration);
2258 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
2259 internalFailWithMessage(false, "Cannot declare a class twice: '", info.className->impl(), "'");
2260 if (exportType == ExportType::Exported) {
2261 semanticFailIfFalse(exportName(*info.className), "Cannot export a duplicate class name: '", info.className->impl(), "'");
2262 m_moduleScopeData->exportBinding(*info.className);
2265 JSTextPosition classEnd = lastTokenEndPosition();
2266 unsigned classEndLine = tokenLine();
2268 return context.createClassDeclStatement(location, classExpr, classStart, classEnd, classStartLine, classEndLine);
2271 template <typename LexerType>
2272 template <class TreeBuilder> TreeClassExpression Parser<LexerType>::parseClass(TreeBuilder& context, FunctionRequirements requirements, ParserClassInfo<TreeBuilder>& info)
2274 ASSERT(match(CLASSTOKEN));
2275 JSTokenLocation location(tokenLocation());
2276 info.startLine = location.line;
2277 info.startColumn = tokenColumn();
2278 info.startOffset = location.startOffset;
2281 AutoPopScopeRef classScope(this, pushScope());
2282 classScope->setIsLexicalScope();
2283 classScope->preventVarDeclarations();
2284 classScope->setStrictMode();
2286 const Identifier* className = nullptr;
2288 className = m_token.m_data.ident;
2290 failIfTrue(classScope->declareLexicalVariable(className, true) & DeclarationResult::InvalidStrictMode, "'", className->impl(), "' is not a valid class name");
2291 } else if (requirements == FunctionNeedsName) {
2292 if (match(OPENBRACE))
2293 semanticFail("Class statements must have a name");
2294 semanticFailureDueToKeyword("class name");
2295 failDueToUnexpectedToken();
2297 className = &m_vm->propertyNames->nullIdentifier;
2299 info.className = className;
2301 TreeExpression parentClass = 0;
2302 if (consume(EXTENDS)) {
2303 parentClass = parseMemberExpression(context);
2304 failIfFalse(parentClass, "Cannot parse the parent class name");
2306 const ConstructorKind constructorKind = parentClass ? ConstructorKind::Derived : ConstructorKind::Base;
2308 consumeOrFail(OPENBRACE, "Expected opening '{' at the start of a class body");
2310 TreeExpression constructor = 0;
2311 TreePropertyList staticMethods = 0;
2312 TreePropertyList instanceMethods = 0;
2313 TreePropertyList instanceMethodsTail = 0;
2314 TreePropertyList staticMethodsTail = 0;
2315 while (!match(CLOSEBRACE)) {
2316 if (match(SEMICOLON)) {
2321 JSTokenLocation methodLocation(tokenLocation());
2322 unsigned methodStart = tokenStart();
2324 // For backwards compatibility, "static" is a non-reserved keyword in non-strict mode.
2325 bool isStaticMethod = false;
2326 if (match(RESERVED_IF_STRICT) && *m_token.m_data.ident == m_vm->propertyNames->staticKeyword) {
2327 SavePoint savePoint = createSavePoint();
2329 if (match(OPENPAREN)) {
2330 // Reparse "static()" as a method named "static".
2331 restoreSavePoint(savePoint);
2333 isStaticMethod = true;
2336 // FIXME: Figure out a way to share more code with parseProperty.
2337 const CommonIdentifiers& propertyNames = *m_vm->propertyNames;
2338 const Identifier* ident = &propertyNames.nullIdentifier;
2339 TreeExpression computedPropertyName = 0;
2340 bool isGetter = false;
2341 bool isSetter = false;
2342 bool isGenerator = false;
2345 switch (m_token.m_type) {
2348 ident = m_token.m_data.ident;
2353 ident = m_token.m_data.ident;
2356 if (!isGenerator && (matchIdentifierOrKeyword() || match(STRING) || match(DOUBLE) || match(INTEGER) || match(OPENBRACKET))) {
2357 isGetter = *ident == propertyNames.get;
2358 isSetter = *ident == propertyNames.set;
2363 ident = &m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), m_token.m_data.doubleValue);
2369 computedPropertyName = parseAssignmentExpression(context);
2370 failIfFalse(computedPropertyName, "Cannot parse computed property name");
2371 handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name");
2374 if (m_token.m_type & KeywordTokenFlag)
2376 failDueToUnexpectedToken();
2379 TreeProperty property;
2380 const bool alwaysStrictInsideClass = true;
2381 if (isGetter || isSetter) {
2382 bool isClassProperty = true;
2383 property = parseGetterSetter(context, alwaysStrictInsideClass, isGetter ? PropertyNode::Getter : PropertyNode::Setter, methodStart,
2384 ConstructorKind::None, isClassProperty);
2385 failIfFalse(property, "Cannot parse this method");
2387 ParserFunctionInfo<TreeBuilder> methodInfo;
2388 bool isConstructor = !isStaticMethod && *ident == propertyNames.constructor;
2389 SourceParseMode parseMode = SourceParseMode::MethodMode;
2391 isConstructor = false;
2392 parseMode = SourceParseMode::GeneratorWrapperFunctionMode;
2393 semanticFailIfTrue(*ident == m_vm->propertyNames->prototype, "Cannot declare a generator named 'prototype'");
2394 semanticFailIfTrue(*ident == m_vm->propertyNames->constructor, "Cannot declare a generator named 'constructor'");
2396 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, parseMode, false, isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, FunctionDefinitionType::Method)), "Cannot parse this method");
2397 methodInfo.name = isConstructor ? className : ident;
2399 TreeExpression method = context.createMethodDefinition(methodLocation, methodInfo);
2400 if (isConstructor) {
2401 semanticFailIfTrue(constructor, "Cannot declare multiple constructors in a single class");
2402 constructor = method;
2406 // FIXME: Syntax error when super() is called
2407 semanticFailIfTrue(isStaticMethod && methodInfo.name && *methodInfo.name == propertyNames.prototype,
2408 "Cannot declare a static method named 'prototype'");
2410 bool isClassProperty = true;
2411 if (computedPropertyName) {
2412 property = context.createProperty(computedPropertyName, method, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed),
2413 PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed, isClassProperty);
2415 property = context.createProperty(methodInfo.name, method, PropertyNode::Constant, PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed, isClassProperty);
2418 TreePropertyList& tail = isStaticMethod ? staticMethodsTail : instanceMethodsTail;
2420 tail = context.createPropertyList(methodLocation, property, tail);
2422 tail = context.createPropertyList(methodLocation, property);
2424 staticMethods = tail;
2426 instanceMethods = tail;
2430 info.endOffset = tokenLocation().endOffset - 1;
2431 consumeOrFail(CLOSEBRACE, "Expected a closing '}' after a class body");
2433 auto classExpression = context.createClassExpr(location, info, classScope->finalizeLexicalEnvironment(), constructor, parentClass, instanceMethods, staticMethods);
2434 popScope(classScope, TreeBuilder::NeedsFreeVariableInfo);
2435 return classExpression;
2439 LabelInfo(const Identifier* ident, const JSTextPosition& start, const JSTextPosition& end)
2446 const Identifier* m_ident;
2447 JSTextPosition m_start;
2448 JSTextPosition m_end;
2451 template <typename LexerType>
2452 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrLabelStatement(TreeBuilder& context, bool allowFunctionDeclarationAsStatement)
2455 /* Expression and Label statements are ambiguous at LL(1), so we have a
2456 * special case that looks for a colon as the next character in the input.
2458 Vector<LabelInfo> labels;
2459 JSTokenLocation location;
2461 JSTextPosition start = tokenStartPosition();
2462 location = tokenLocation();
2463 if (!nextTokenIsColon()) {
2464 // If we hit this path we're making a expression statement, which
2465 // by definition can't make use of continue/break so we can just
2466 // ignore any labels we might have accumulated.
2467 TreeExpression expression = parseExpression(context);
2468 failIfFalse(expression, "Cannot parse expression statement");
2469 if (!autoSemiColon())
2470 failDueToUnexpectedToken();
2471 return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
2473 const Identifier* ident = m_token.m_data.ident;
2474 JSTextPosition end = tokenEndPosition();
2476 consumeOrFail(COLON, "Labels must be followed by a ':'");
2477 if (!m_syntaxAlreadyValidated) {
2478 // This is O(N^2) over the current list of consecutive labels, but I
2479 // have never seen more than one label in a row in the real world.
2480 for (size_t i = 0; i < labels.size(); i++)
2481 failIfTrue(ident->impl() == labels[i].m_ident->impl(), "Attempted to redeclare the label '", ident->impl(), "'");
2482 failIfTrue(getLabel(ident), "Cannot find scope for the label '", ident->impl(), "'");
2483 labels.append(LabelInfo(ident, start, end));
2485 } while (matchSpecIdentifier());
2486 bool isLoop = false;
2487 switch (m_token.m_type) {
2497 const Identifier* unused = 0;
2498 ScopeRef labelScope = currentScope();
2499 if (!m_syntaxAlreadyValidated) {
2500 for (size_t i = 0; i < labels.size(); i++)
2501 pushLabel(labels[i].m_ident, isLoop);
2503 m_immediateParentAllowsFunctionDeclarationInStatement = allowFunctionDeclarationAsStatement;
2504 TreeStatement statement = parseStatement(context, unused);
2505 if (!m_syntaxAlreadyValidated) {
2506 for (size_t i = 0; i < labels.size(); i++)
2507 popLabel(labelScope);
2509 failIfFalse(statement, "Cannot parse statement");
2510 for (size_t i = 0; i < labels.size(); i++) {
2511 const LabelInfo& info = labels[labels.size() - i - 1];
2512 statement = context.createLabelStatement(location, info.m_ident, statement, info.m_start, info.m_end);
2517 template <typename LexerType>
2518 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionStatement(TreeBuilder& context)
2520 switch (m_token.m_type) {
2521 // Consult: http://www.ecma-international.org/ecma-262/6.0/index.html#sec-expression-statement
2522 // The ES6 spec mandates that we should fail from FUNCTION token here. We handle this case
2523 // in parseStatement() which is the only caller of parseExpressionStatement().
2524 // We actually allow FUNCTION in situations where it should not be allowed unless we're in strict mode.
2526 failWithMessage("'class' declaration is not directly within a block statement");
2529 // FIXME: when implementing 'let' we should fail when we see the token sequence "let [".
2530 // https://bugs.webkit.org/show_bug.cgi?id=142944
2533 JSTextPosition start = tokenStartPosition();
2534 JSTokenLocation location(tokenLocation());
2535 TreeExpression expression = parseExpression(context);
2536 failIfFalse(expression, "Cannot parse expression statement");
2537 failIfFalse(autoSemiColon(), "Parse error");
2538 return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
2541 template <typename LexerType>
2542 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(TreeBuilder& context)
2545 JSTokenLocation ifLocation(tokenLocation());
2546 int start = tokenLine();
2548 handleProductionOrFail2(OPENPAREN, "(", "start", "'if' condition");
2550 TreeExpression condition = parseExpression(context);
2551 failIfFalse(condition, "Expected a expression as the condition for an if statement");
2552 int end = tokenLine();
2553 handleProductionOrFail2(CLOSEPAREN, ")", "end", "'if' condition");
2555 const Identifier* unused = 0;
2556 m_immediateParentAllowsFunctionDeclarationInStatement = true;
2557 TreeStatement trueBlock = parseStatement(context, unused);
2558 failIfFalse(trueBlock, "Expected a statement as the body of an if block");
2561 return context.createIfStatement(ifLocation, condition, trueBlock, 0, start, end);
2563 Vector<TreeExpression> exprStack;
2564 Vector<std::pair<int, int>> posStack;
2565 Vector<JSTokenLocation> tokenLocationStack;
2566 Vector<TreeStatement> statementStack;
2567 bool trailingElse = false;
2569 JSTokenLocation tempLocation = tokenLocation();
2572 const Identifier* unused = 0;
2573 m_immediateParentAllowsFunctionDeclarationInStatement = true;
2574 TreeStatement block = parseStatement(context, unused);
2575 failIfFalse(block, "Expected a statement as the body of an else block");
2576 statementStack.append(block);
2577 trailingElse = true;
2580 int innerStart = tokenLine();
2583 handleProductionOrFail2(OPENPAREN, "(", "start", "'if' condition");
2585 TreeExpression innerCondition = parseExpression(context);
2586 failIfFalse(innerCondition, "Expected a expression as the condition for an if statement");
2587 int innerEnd = tokenLine();
2588 handleProductionOrFail2(CLOSEPAREN, ")", "end", "'if' condition");
2589 const Identifier* unused = 0;
2590 m_immediateParentAllowsFunctionDeclarationInStatement = true;
2591 TreeStatement innerTrueBlock = parseStatement(context, unused);
2592 failIfFalse(innerTrueBlock, "Expected a statement as the body of an if block");
2593 tokenLocationStack.append(tempLocation);
2594 exprStack.append(innerCondition);
2595 posStack.append(std::make_pair(innerStart, innerEnd));
2596 statementStack.append(innerTrueBlock);
2597 } while (match(ELSE));
2599 if (!trailingElse) {
2600 TreeExpression condition = exprStack.last();
2601 exprStack.removeLast();
2602 TreeStatement trueBlock = statementStack.last();
2603 statementStack.removeLast();
2604 std::pair<int, int> pos = posStack.last();
2605 posStack.removeLast();
2606 JSTokenLocation elseLocation = tokenLocationStack.last();
2607 tokenLocationStack.removeLast();
2608 TreeStatement ifStatement = context.createIfStatement(elseLocation, condition, trueBlock, 0, pos.first, pos.second);
2609 context.setEndOffset(ifStatement, context.endOffset(trueBlock));
2610 statementStack.append(ifStatement);
2613 while (!exprStack.isEmpty()) {
2614 TreeExpression condition = exprStack.last();
2615 exprStack.removeLast();
2616 TreeStatement falseBlock = statementStack.last();
2617 statementStack.removeLast();
2618 TreeStatement trueBlock = statementStack.last();
2619 statementStack.removeLast();
2620 std::pair<int, int> pos = posStack.last();
2621 posStack.removeLast();
2622 JSTokenLocation elseLocation = tokenLocationStack.last();
2623 tokenLocationStack.removeLast();
2624 TreeStatement ifStatement = context.createIfStatement(elseLocation, condition, trueBlock, falseBlock, pos.first, pos.second);
2625 context.setEndOffset(ifStatement, context.endOffset(falseBlock));
2626 statementStack.append(ifStatement);
2629 return context.createIfStatement(ifLocation, condition, trueBlock, statementStack.last(), start, end);
2632 template <typename LexerType>
2633 template <class TreeBuilder> typename TreeBuilder::ModuleName Parser<LexerType>::parseModuleName(TreeBuilder& context)
2635 // ModuleName (ModuleSpecifier in the spec) represents the module name imported by the script.
2636 // http://www.ecma-international.org/ecma-262/6.0/#sec-imports
2637 // http://www.ecma-international.org/ecma-262/6.0/#sec-exports
2638 JSTokenLocation specifierLocation(tokenLocation());
2639 failIfFalse(match(STRING), "Imported modules names must be string literals");
2640 const Identifier* moduleName = m_token.m_data.ident;
2642 return context.createModuleName(specifierLocation, *moduleName);
2645 template <typename LexerType>
2646 template <class TreeBuilder> typename TreeBuilder::ImportSpecifier Parser<LexerType>::parseImportClauseItem(TreeBuilder& context, ImportSpecifierType specifierType)
2648 // Produced node is the item of the ImportClause.
2649 // That is the ImportSpecifier, ImportedDefaultBinding or NameSpaceImport.
2650 // http://www.ecma-international.org/ecma-262/6.0/#sec-imports
2651 JSTokenLocation specifierLocation(tokenLocation());
2652 JSToken localNameToken;
2653 const Identifier* importedName = nullptr;
2654 const Identifier* localName = nullptr;
2656 switch (specifierType) {
2657 case ImportSpecifierType::NamespaceImport: {
2658 // NameSpaceImport :
2659 // * as ImportedBinding
2662 ASSERT(match(TIMES));
2663 importedName = &m_vm->propertyNames->timesIdentifier;
2666 failIfFalse(matchContextualKeyword(m_vm->propertyNames->as), "Expected 'as' before imported binding name");
2669 matchOrFail(IDENT, "Expected a variable name for the import declaration");
2670 localNameToken = m_token;
2671 localName = m_token.m_data.ident;
2676 case ImportSpecifierType::NamedImport: {
2677 // ImportSpecifier :
2679 // IdentifierName as ImportedBinding
2683 ASSERT(matchIdentifierOrKeyword());
2684 localNameToken = m_token;
2685 localName = m_token.m_data.ident;
2686 importedName = localName;
2689 if (matchContextualKeyword(m_vm->propertyNames->as)) {
2691 matchOrFail(IDENT, "Expected a variable name for the import declaration");
2692 localNameToken = m_token;
2693 localName = m_token.m_data.ident;
2699 case ImportSpecifierType::DefaultImport: {
2700 // ImportedDefaultBinding :
2702 ASSERT(match(IDENT));
2703 localNameToken = m_token;
2704 localName = m_token.m_data.ident;
2705 importedName = &m_vm->propertyNames->defaultKeyword;
2711 semanticFailIfTrue(localNameToken.m_type & KeywordTokenFlag, "Cannot use keyword as imported binding name");
2712 DeclarationResultMask declarationResult = declareVariable(localName, DeclarationType::ConstDeclaration, (specifierType == ImportSpecifierType::NamespaceImport) ? DeclarationImportType::ImportedNamespace : DeclarationImportType::Imported);
2713 if (declarationResult != DeclarationResult::Valid) {
2714 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare an imported binding named ", localName->impl(), " in strict mode");
2715 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
2716 internalFailWithMessage(false, "Cannot declare an imported binding name twice: '", localName->impl(), "'");
2719 return context.createImportSpecifier(specifierLocation, *importedName, *localName);
2722 template <typename LexerType>
2723 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseImportDeclaration(TreeBuilder& context)
2725 // http://www.ecma-international.org/ecma-262/6.0/#sec-imports
2726 ASSERT(match(IMPORT));
2727 JSTokenLocation importLocation(tokenLocation());
2730 auto specifierList = context.createImportSpecifierList();
2732 if (match(STRING)) {
2733 // import ModuleSpecifier ;
2734 auto moduleName = parseModuleName(context);
2735 failIfFalse(moduleName, "Cannot parse the module name");
2736 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted import declaration");
2737 return context.createImportDeclaration(importLocation, specifierList, moduleName);
2740 bool isFinishedParsingImport = false;
2742 // ImportedDefaultBinding :
2744 auto specifier = parseImportClauseItem(context, ImportSpecifierType::DefaultImport);
2745 failIfFalse(specifier, "Cannot parse the default import");
2746 context.appendImportSpecifier(specifierList, specifier);
2750 isFinishedParsingImport = true;
2753 if (!isFinishedParsingImport) {
2755 // import NameSpaceImport FromClause ;
2756 auto specifier = parseImportClauseItem(context, ImportSpecifierType::NamespaceImport);
2757 failIfFalse(specifier, "Cannot parse the namespace import");
2758 context.appendImportSpecifier(specifierList, specifier);
2759 } else if (match(OPENBRACE)) {
2763 // { ImportsList , }
2766 while (!match(CLOSEBRACE)) {
2767 failIfFalse(matchIdentifierOrKeyword(), "Expected an imported name for the import declaration");
2768 auto specifier = parseImportClauseItem(context, ImportSpecifierType::NamedImport);
2769 failIfFalse(specifier, "Cannot parse the named import");
2770 context.appendImportSpecifier(specifierList, specifier);
2771 if (!consume(COMMA))
2774 handleProductionOrFail2(CLOSEBRACE, "}", "end", "import list");
2776 failWithMessage("Expected namespace import or import list");
2780 // from ModuleSpecifier
2782 failIfFalse(matchContextualKeyword(m_vm->propertyNames->from), "Expected 'from' before imported module name");
2785 auto moduleName = parseModuleName(context);
2786 failIfFalse(moduleName, "Cannot parse the module name");
2787 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted import declaration");
2789 return context.createImportDeclaration(importLocation, specifierList, moduleName);
2792 template <typename LexerType>
2793 template <class TreeBuilder> typename TreeBuilder::ExportSpecifier Parser<LexerType>::parseExportSpecifier(TreeBuilder& context, Vector<std::pair<const Identifier*, const Identifier*>>& maybeExportedLocalNames, bool& hasKeywordForLocalBindings)
2795 // ExportSpecifier :
2797 // IdentifierName as IdentifierName
2798 // http://www.ecma-international.org/ecma-262/6.0/#sec-exports
2799 ASSERT(matchIdentifierOrKeyword());
2800 JSTokenLocation specifierLocation(tokenLocation());
2801 if (m_token.m_type & KeywordTokenFlag)
2802 hasKeywordForLocalBindings = true;
2803 const Identifier* localName = m_token.m_data.ident;
2804 const Identifier* exportedName = localName;
2807 if (matchContextualKeyword(m_vm->propertyNames->as)) {
2809 failIfFalse(matchIdentifierOrKeyword(), "Expected an exported name for the export declaration");
2810 exportedName = m_token.m_data.ident;
2814 semanticFailIfFalse(exportName(*exportedName), "Cannot export a duplicate name '", exportedName->impl(), "'");
2815 maybeExportedLocalNames.append(std::make_pair(localName, exportedName));
2816 return context.createExportSpecifier(specifierLocation, *localName, *exportedName);
2819 template <typename LexerType>
2820 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExportDeclaration(TreeBuilder& context)
2822 // http://www.ecma-international.org/ecma-262/6.0/#sec-exports
2823 ASSERT(match(EXPORT));
2824 JSTokenLocation exportLocation(tokenLocation());
2827 switch (m_token.m_type) {
2829 // export * FromClause ;
2832 failIfFalse(matchContextualKeyword(m_vm->propertyNames->from), "Expected 'from' before exported module name");
2834 auto moduleName = parseModuleName(context);
2835 failIfFalse(moduleName, "Cannot parse the 'from' clause");
2836 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted export declaration");
2838 return context.createExportAllDeclaration(exportLocation, moduleName);
2842 // export default HoistableDeclaration[Default]
2843 // export default ClassDeclaration[Default]
2844 // export default [lookahead not-in {function, class}] AssignmentExpression[In] ;
2848 TreeStatement result = 0;
2849 bool isFunctionOrClassDeclaration = false;
2850 const Identifier* localName = nullptr;
2851 SavePoint savePoint = createSavePoint();
2853 bool startsWithFunction = match(FUNCTION);
2854 if (startsWithFunction || match(CLASSTOKEN)) {
2855 isFunctionOrClassDeclaration = true;
2859 if (startsWithFunction && match(TIMES))
2862 localName = m_token.m_data.ident;
2863 restoreSavePoint(savePoint);
2867 if (match(FUNCTION)) {
2868 DepthManager statementDepth(&m_statementDepth);
2869 m_statementDepth = 1;
2870 result = parseFunctionDeclaration(context);
2872 ASSERT(match(CLASSTOKEN));
2873 result = parseClassDeclaration(context);
2876 // export default expr;
2878 // It should be treated as the same to the following.
2880 // const *default* = expr;
2881 // export { *default* as default }
2883 // In the above example, *default* is the invisible variable to the users.
2884 // We use the private symbol to represent the name of this variable.
2885 JSTokenLocation location(tokenLocation());
2886 JSTextPosition start = tokenStartPosition();
2887 TreeExpression expression = parseAssignmentExpression(context);
2888 failIfFalse(expression, "Cannot parse expression");
2890 DeclarationResultMask declarationResult = declareVariable(&m_vm->propertyNames->builtinNames().starDefaultPrivateName(), DeclarationType::ConstDeclaration);
2891 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
2892 internalFailWithMessage(false, "Only one 'default' export is allowed");
2894 TreeExpression assignment = context.createAssignResolve(location, m_vm->propertyNames->builtinNames().starDefaultPrivateName(), expression, start, start, tokenEndPosition(), AssignmentContext::ConstDeclarationStatement);
2895 result = context.createExprStatement(location, assignment, start, tokenEndPosition());
2896 if (!isFunctionOrClassDeclaration)
2897 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted export declaration");
2898 localName = &m_vm->propertyNames->builtinNames().starDefaultPrivateName();
2900 failIfFalse(result, "Cannot parse the declaration");
2902 semanticFailIfFalse(exportName(m_vm->propertyNames->defaultKeyword), "Only one 'default' export is allowed");
2903 m_moduleScopeData->exportBinding(*localName, m_vm->propertyNames->defaultKeyword);
2904 return context.createExportDefaultDeclaration(exportLocation, result, *localName);
2908 // export ExportClause FromClause ;
2909 // export ExportClause ;
2914 // { ExportsList , }
2918 // ExportsList , ExportSpecifier
2922 auto specifierList = context.createExportSpecifierList();
2923 Vector<std::pair<const Identifier*, const Identifier*>> maybeExportedLocalNames;
2925 bool hasKeywordForLocalBindings = false;
2926 while (!match(CLOSEBRACE)) {
2927 failIfFalse(matchIdentifierOrKeyword(), "Expected a variable name for the export declaration");
2928 auto specifier = parseExportSpecifier(context, maybeExportedLocalNames, hasKeywordForLocalBindings);
2929 failIfFalse(specifier, "Cannot parse the named export");
2930 context.appendExportSpecifier(specifierList, specifier);
2931 if (!consume(COMMA))
2934 handleProductionOrFail2(CLOSEBRACE, "}", "end", "export list");
2936 typename TreeBuilder::ModuleName moduleName = 0;
2937 if (matchContextualKeyword(m_vm->propertyNames->from)) {
2939 moduleName = parseModuleName(context);
2940 failIfFalse(moduleName, "Cannot parse the 'from' clause");
2942 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted export declaration");
2945 semanticFailIfTrue(hasKeywordForLocalBindings, "Cannot use keyword as exported variable name");
2946 // Since this export declaration does not have module specifier part, it exports the local bindings.
2947 // While the export declaration with module specifier does not have any effect on the current module's scope,
2948 // the export named declaration without module specifier references the the local binding names.
2950 // export { A, B, C as D } from "mod"
2951 // does not have effect on the current module's scope. But,
2952 // export { A, B, C as D }
2953 // will reference the current module's bindings.
2954 for (const auto& pair : maybeExportedLocalNames) {
2955 const Identifier* localName = pair.first;
2956 const Identifier* exportedName = pair.second;
2957 m_moduleScopeData->exportBinding(*localName, *exportedName);
2961 return context.createExportNamedDeclaration(exportLocation, specifierList, moduleName);
2965 // export VariableStatement
2966 // export Declaration
2967 TreeStatement result = 0;
2968 switch (m_token.m_type) {
2970 result = parseVariableDeclaration(context, DeclarationType::VarDeclaration, ExportType::Exported);
2974 result = parseVariableDeclaration(context, DeclarationType::ConstDeclaration, ExportType::Exported);
2978 result = parseVariableDeclaration(context, DeclarationType::LetDeclaration, ExportType::Exported);
2982 DepthManager statementDepth(&m_statementDepth);
2983 m_statementDepth = 1;
2984 result = parseFunctionDeclaration(context, ExportType::Exported);
2989 result = parseClassDeclaration(context, ExportType::Exported);
2993 failWithMessage("Expected either a declaration or a variable statement");
2996 failIfFalse(result, "Cannot parse the declaration");
2997 return context.createExportLocalDeclaration(exportLocation, result);
3001 RELEASE_ASSERT_NOT_REACHED();
3005 template <typename LexerType>
3006 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseExpression(TreeBuilder& context)
3008 failIfStackOverflow();
3009 JSTokenLocation location(tokenLocation());
3010 TreeExpression node = parseAssignmentExpression(context);
3011 failIfFalse(node, "Cannot parse expression");
3012 context.setEndOffset(node, m_lastTokenEndPosition.offset);
3016 m_parserState.nonTrivialExpressionCount++;
3017 m_parserState.nonLHSCount++;
3018 TreeExpression right = parseAssignmentExpression(context);
3019 failIfFalse(right, "Cannot parse expression in a comma expression");
3020 context.setEndOffset(right, m_lastTokenEndPosition.offset);
3021 typename TreeBuilder::Comma head = context.createCommaExpr(location, node);
3022 typename TreeBuilder::Comma tail = context.appendToCommaExpr(location, head, head, right);
3023 while (match(COMMA)) {
3024 next(TreeBuilder::DontBuildStrings);
3025 right = parseAssignmentExpression(context);
3026 failIfFalse(right, "Cannot parse expression in a comma expression");
3027 context.setEndOffset(right, m_lastTokenEndPosition.offset);
3028 tail = context.appendToCommaExpr(location, head, tail, right);
3030 context.setEndOffset(head, m_lastTokenEndPosition.offset);
3034 template <typename LexerType>
3035 template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpressionOrPropagateErrorClass(TreeBuilder& context)
3037 ExpressionErrorClassifier classifier(this);
3038 auto assignment = parseAssignmentExpression(context, classifier);
3040 classifier.propagateExpressionErrorClass();
3044 template <typename LexerType>
3045 template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context)
3047 ExpressionErrorClassifier classifier(this);
3048 return parseAssignmentExpression(context, classifier);
3051 template <typename LexerType>
3052 template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context, ExpressionErrorClassifier& classifier)
3054 ASSERT(!hasError());
3056 failIfStackOverflow();
3057 JSTextPosition start = tokenStartPosition();
3058 JSTokenLocation location(tokenLocation());
3059 int initialAssignmentCount = m_parserState.assignmentCount;
3060 int initialNonLHSCount = m_parserState.nonLHSCount;
3061 bool maybeAssignmentPattern = match(OPENBRACE) || match(OPENBRACKET);
3062 bool wasOpenParen = match(OPENPAREN);
3063 bool isValidArrowFunctionStart = match(OPENPAREN) || match(IDENT);
3064 SavePoint savePoint = createSavePoint();
3065 size_t usedVariablesSize = 0;
3067 usedVariablesSize = currentScope()->currentUsedVariablesSize();
3068 currentScope()->pushUsedVariableSet();
3071 if (match(YIELD) && !isYIELDMaskedAsIDENT(currentScope()->isGenerator()))
3072 return parseYieldExpression(context);
3074 TreeExpression lhs = parseConditionalExpression(context);
3076 if (isValidArrowFunctionStart && !match(EOFTOK)) {
3077 bool isArrowFunctionToken = match(ARROWFUNCTION);
3078 if (!lhs || isArrowFunctionToken) {
3079 SavePointWithError errorRestorationSavePoint = createSavePointForError();
3080 restoreSavePoint(savePoint);
3081 if (isArrowFunctionParameters()) {
3083 currentScope()->revertToPreviousUsedVariables(usedVariablesSize);
3084 return parseArrowFunctionExpression(context);
3086 restoreSavePointWithError(errorRestorationSavePoint);
3087 if (isArrowFunctionToken)
3088 failDueToUnexpectedToken();
3092 if (!lhs && (!maybeAssignmentPattern || !classifier.indicatesPossiblePattern()))
3095 if (maybeAssignmentPattern && (!lhs || (context.isObjectOrArrayLiteral(lhs) && match(EQUAL)))) {
3096 SavePointWithError expressionErrorLocation = createSavePointForError();
3097 restoreSavePoint(savePoint);
3098 auto pattern = tryParseDestructuringPatternExpression(context, AssignmentContext::AssignmentExpression);
3099 if (classifier.indicatesPossiblePattern() && (!pattern || !match(EQUAL))) {
3100 restoreSavePointWithError(expressionErrorLocation);
3103 failIfFalse(pattern, "Cannot parse assignment pattern");
3104 consumeOrFail(EQUAL, "Expected '=' following assignment pattern");
3105 auto rhs = parseAssignmentExpression(context);
3108 return context.createDestructuringAssignment(location, pattern, rhs);
3111 failIfFalse(lhs, "Cannot parse expression");
3112 if (initialNonLHSCount != m_parserState.nonLHSCount) {
3113 if (m_token.m_type >= EQUAL && m_token.m_type <= OREQUAL)
3114 semanticFail("Left hand side of operator '", getToken(), "' must be a reference");
3119 int assignmentStack = 0;
3121 bool hadAssignment = false;
3123 switch (m_token.m_type) {
3124 case EQUAL: op = OpEqual; break;
3125 case PLUSEQUAL: op = OpPlusEq; break;
3126 case MINUSEQUAL: op = OpMinusEq; break;
3127 case MULTEQUAL: op = OpMultEq; break;
3128 case DIVEQUAL: op = OpDivEq; break;
3129 case LSHIFTEQUAL: op = OpLShift; break;
3130 case RSHIFTEQUAL: op = OpRShift; break;
3131 case URSHIFTEQUAL: op = OpURShift; break;
3132 case ANDEQUAL: op = OpAndEq; break;
3133 case XOREQUAL: op = OpXOrEq; break;
3134 case OREQUAL: op = OpOrEq; break;
3135 case MODEQUAL: op = OpModEq; break;
3136 case POWEQUAL: op = OpPowEq; break;
3140 m_parserState.nonTrivialExpressionCount++;
3141 hadAssignment = true;
3142 if (UNLIKELY(context.isNewTarget(lhs)))
3143 internalFailWithMessage(false, "new.target can't be the left hand side of an assignment expression");
3144 context.assignmentStackAppend(assignmentStack, lhs, start, tokenStartPosition(), m_parserState.assignmentCount, op);
3145 start = tokenStartPosition();
3146 m_parserState.assignmentCount++;
3147 next(TreeBuilder::DontBuildStrings);
3148 if (strictMode() && m_parserState.lastIdentifier && context.isResolve(lhs)) {
3149 failIfTrueIfStrict(m_vm->propertyNames->eval == *m_parserState.lastIdentifier, "Cannot modify 'eval' in strict mode");
3150 failIfTrueIfStrict(m_vm->propertyNames->arguments == *m_parserState.lastIdentifier, "Cannot modify 'arguments' in strict mode");
3151 m_parserState.lastIdentifier = 0;
3153 lhs = parseAssignmentExpression(context);
3154 failIfFalse(lhs, "Cannot parse the right hand side of an assignment expression");
3155 if (initialNonLHSCount != m_parserState.nonLHSCount) {
3156 if (m_token.m_type >= EQUAL && m_token.m_type <= OREQUAL)
3157 semanticFail("Left hand side of operator '", getToken(), "' must be a reference");
3163 m_parserState.nonLHSCount++;
3165 if (!TreeBuilder::CreatesAST)
3168 while (assignmentStack)
3169 lhs = context.createAssignment(location, assignmentStack, lhs, initialAssignmentCount, m_parserState.assignmentCount, lastTokenEndPosition());
3174 template <typename LexerType>
3175 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseYieldExpression(TreeBuilder& context)
3177 // YieldExpression[In] :
3179 // yield [no LineTerminator here] AssignmentExpression[?In, Yield]
3180 // yield [no LineTerminator here] * AssignmentExpression[?In, Yield]
3182 // http://ecma-international.org/ecma-262/6.0/#sec-generator-function-definitions
3183 failIfFalse(currentScope()->isGenerator(), "Cannot use yield expression out of generator");
3185 // http://ecma-international.org/ecma-262/6.0/#sec-generator-function-definitions-static-semantics-early-errors
3186 failIfTrue(m_parserState.functionParsePhase == FunctionParsePhase::Parameters, "Cannot use yield expression within parameters");
3188 JSTokenLocation location(tokenLocation());
3189 JSTextPosition divotStart = tokenStartPosition();
3190 ASSERT(match(YIELD));
3191 SavePoint savePoint = createSavePoint();
3193 if (m_lexer->prevTerminator())
3194 return context.createYield(location);
3196 bool delegate = consume(TIMES);
3197 JSTextPosition argumentStart = tokenStartPosition();
3198 TreeExpression argument = parseAssignmentExpression(context);
3200 restoreSavePoint(savePoint);
3202 return context.createYield(location);
3204 return context.createYield(location, argument, delegate, divotStart, argumentStart, lastTokenEndPosition());
3207 template <typename LexerType>
3208 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseConditionalExpression(TreeBuilder& context)
3210 JSTokenLocation location(tokenLocation());
3211 TreeExpression cond = parseBinaryExpression(context);
3212 failIfFalse(cond, "Cannot parse expression");
3213 if (!match(QUESTION))
3215 m_parserState.nonTrivialExpressionCount++;
3216 m_parserState.nonLHSCount++;
3217 next(TreeBuilder::DontBuildStrings);
3218 TreeExpression lhs = parseAssignmentExpression(context);
3219 failIfFalse(lhs, "Cannot parse left hand side of ternary operator");
3220 context.setEndOffset(lhs, m_lastTokenEndPosition.offset);
3221 consumeOrFailWithFlags(COLON, TreeBuilder::DontBuildStrings, "Expected ':' in ternary operator");
3223 TreeExpression rhs = parseAssignmentExpression(context);
3224 failIfFalse(rhs, "Cannot parse right hand side of ternary operator");
3225 context.setEndOffset(rhs, m_lastTokenEndPosition.offset);
3226 return context.createConditionalExpr(location, cond, lhs, rhs);
3229 ALWAYS_INLINE static bool isUnaryOpExcludingUpdateOp(JSTokenType token)
3231 if (isUpdateOp(token))
3233 return isUnaryOp(token);
3236 template <typename LexerType>
3237 int Parser<LexerType>::isBinaryOperator(JSTokenType token)
3240 return token & (BinaryOpTokenPrecedenceMask << BinaryOpTokenAllowsInPrecedenceAdditionalShift);
3241 return token & BinaryOpTokenPrecedenceMask;
3244 template <typename LexerType>
3245 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseBinaryExpression(TreeBuilder& context)
3247 int operandStackDepth = 0;
3248 int operatorStackDepth = 0;
3249 typename TreeBuilder::BinaryExprContext binaryExprContext(context);
3250 JSTokenLocation location(tokenLocation());
3252 JSTextPosition exprStart = tokenStartPosition();
3253 int initialAssignments = m_parserState.assignmentCount;
3254 JSTokenType leadingTokenTypeForUnaryExpression = m_token.m_type;
3255 TreeExpression current = parseUnaryExpression(context);
3256 failIfFalse(current, "Cannot parse expression");
3258 context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEndPosition(), lastTokenEndPosition(), initialAssignments != m_parserState.assignmentCount);
3260 // 12.6 https://tc39.github.io/ecma262/#sec-exp-operator
3261 // ExponentiationExpresion is described as follows.
3263 // ExponentiationExpression[Yield]:
3264 // UnaryExpression[?Yield]
3265 // UpdateExpression[?Yield] ** ExponentiationExpression[?Yield]
3267 // As we can see, the left hand side of the ExponentiationExpression is UpdateExpression, not UnaryExpression.
3268 // So placing UnaryExpression not included in UpdateExpression here is a syntax error.
3269 // This is intentional. For example, if UnaryExpression is allowed, we can have the code like `-x**y`.
3270 // But this is confusing: `-(x**y)` OR `(-x)**y`, which interpretation is correct?
3271 // To avoid this problem, ECMA262 makes unparenthesized exponentiation expression as operand of unary operators an early error.
3272 // More rationale: https://mail.mozilla.org/pipermail/es-discuss/2015-September/044232.html
3274 // Here, we guarantee that the left hand side of this expression is not unary expression by checking the leading operator of the parseUnaryExpression.
3275 // This check just works. Let's consider the example,
3279 // If the binary operator <> has higher precedence than one of "**", this check does not work.
3280 // But it's OK for ** because the operator "**" has the highest operator precedence in the binary operators.
3281 failIfTrue(match(POW) && isUnaryOpExcludingUpdateOp(leadingTokenTypeForUnaryExpression), "Amiguous unary expression in the left hand side of the exponentiation expression; parenthesis must be used to disambiguate the expression");
3283 int precedence = isBinaryOperator(m_token.m_type);
3286 m_parserState.nonTrivialExpressionCount++;
3287 m_parserState.nonLHSCount++;
3288 int operatorToken = m_token.m_type;
3289 next(TreeBuilder::DontBuildStrings);
3291 while (operatorStackDepth && context.operatorStackShouldReduce(precedence)) {
3292 ASSERT(operandStackDepth > 1);
3294 typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
3295 typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
3296 context.shrinkOperandStackBy(operandStackDepth, 2);
3297 context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
3298 context.operatorStackPop(operatorStackDepth);
3300 context.operatorStackAppend(operatorStackDepth, operatorToken, precedence);
3302 while (operatorStackDepth) {
3303 ASSERT(operandStackDepth > 1);
3305 typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
3306 typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
3307 context.shrinkOperandStackBy(operandStackDepth, 2);
3308 context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
3309 context.operatorStackPop(operatorStackDepth);
3311 return context.popOperandStack(operandStackDepth);
3314 template <typename LexerType>
3315 template <class TreeBuilder> TreeProperty Parser<LexerType>::parseProperty(TreeBuilder& context, bool complete)
3317 bool wasIdent = false;
3318 bool isGenerator = false;
3319 bool isClassProperty = false;
3322 switch (m_token.m_type) {
3328 const Identifier* ident = m_token.m_data.ident;
3329 unsigned getterOrSetterStartOffset = tokenStart();
3330 if (complete || (wasIdent && !isGenerator && (*ident == m_vm->propertyNames->get || *ident == m_vm->propertyNames->set)))
3331 nextExpectIdentifier(LexerFlagsIgnoreReservedWords);
3333 nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
3335 if (!isGenerator && match(COLON)) {
3337 TreeExpression node = parseAssignmentExpressionOrPropagateErrorClass(context);
3338 failIfFalse(node, "Cannot parse expression for property declaration");
3339 context.setEndOffset(node, m_lexer->currentOffset());
3340 return context.createProperty(ident, node, PropertyNode::Constant, PropertyNode::Unknown, complete, SuperBinding::NotNeeded, isClassProperty);
3343 if (match(OPENPAREN)) {
3344 auto method = parsePropertyMethod(context, ident, isGenerator);
3346 return context.createProperty(ident, method, PropertyNode::Constant, PropertyNode::KnownDirect, complete, SuperBinding::Needed, isClassProperty);
3348 failIfTrue(isGenerator, "Expected a parenthesis for argument list");
3350 failIfFalse(wasIdent, "Expected an identifier as property name");
3352 if (match(COMMA) || match(CLOSEBRACE)) {
3353 JSTextPosition start = tokenStartPosition();
3354 JSTokenLocation location(tokenLocation());
3355 currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident);
3356 if (currentScope()->isArrowFunction())
3357 currentScope()->setInnerArrowFunctionUsesEval();
3358 TreeExpression node = context.createResolve(location, *ident, start, lastTokenEndPosition());
3359 return context.createProperty(ident, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Shorthand), PropertyNode::KnownDirect, complete, SuperBinding::NotNeeded, isClassProperty);
3362 if (match(EQUAL)) // CoverInitializedName is exclusive to BindingPattern and AssignmentPattern
3363 classifyExpressionError(ErrorIndicatesPattern);
3365 PropertyNode::Type type;
3366 if (*ident == m_vm->propertyNames->get)
3367 type = PropertyNode::Getter;
3368 else if (*ident == m_vm->propertyNames->set)
3369 type = PropertyNode::Setter;
3371 failWithMessage("Expected a ':' following the property name '", ident->impl(), "'");
3372 return parseGetterSetter(context, complete, type, getterOrSetterStartOffset, ConstructorKind::None, isClassProperty);
3376 double propertyName = m_token.m_data.doubleValue;
3379 if (match(OPENPAREN)) {
3380 const Identifier& ident = m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), propertyName);
3381 auto method = parsePropertyMethod(context, &ident, isGenerator);
3383 return context.createProperty(&ident, method, PropertyNode::Constant, PropertyNode::Unknown, complete, SuperBinding::Needed, isClassProperty);
3385 failIfTrue(isGenerator, "Expected a parenthesis for argument list");
3387 consumeOrFail(COLON, "Expected ':' after property name");
3388 TreeExpression node = parseAssignmentExpression(context);
3389 failIfFalse(node, "Cannot parse expression for property declaration");
3390 context.setEndOffset(node, m_lexer->currentOffset());
3391 return context.createProperty(const_cast<VM*>(m_vm), m_parserArena, propertyName, node, PropertyNode::Constant, PropertyNode::Unknown, complete, SuperBinding::NotNeeded, isClassProperty);
3395 auto propertyName = parseAssignmentExpression(context);
3396 failIfFalse(propertyName, "Cannot parse computed property name");
3397 handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name");
3399 if (match(OPENPAREN)) {
3400 auto method = parsePropertyMethod(context, &m_vm->propertyNames->nullIdentifier, isGenerator);
3402 return context.createProperty(propertyName, method, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::KnownDirect, complete, SuperBinding::Needed, isClassProperty);
3404 failIfTrue(isGenerator, "Expected a parenthesis for argument list");
3406 consumeOrFail(COLON, "Expected ':' after property name");
3407 TreeExpression node = parseAssignmentExpression(context);
3408 failIfFalse(node, "Cannot parse expression for property declaration");
3409 context.setEndOffset(node, m_lexer->currentOffset());
3410 return context.createProperty(propertyName, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::Unknown, complete, SuperBinding::NotNeeded, isClassProperty);
3413 failIfFalse(m_token.m_type & KeywordTokenFlag, "Expected a property name");
3418 template <typename LexerType>
3419 template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePropertyMethod(TreeBuilder& context, const Identifier* methodName, bool isGenerator)
3421 JSTokenLocation methodLocation(tokenLocation());
3422 unsigned methodStart = tokenStart();
3423 ParserFunctionInfo<TreeBuilder> methodInfo;
3424 SourceParseMode parseMode = isGenerator ? SourceParseMode::GeneratorWrapperFunctionMode : SourceParseMode::MethodMode;
3425 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, parseMode, false, ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, FunctionDefinitionType::Method)), "Cannot parse this method");
3426 methodInfo.name = methodName;
3427 return context.createMethodDefinition(methodLocation, methodInfo);
3430 template <typename LexerType>
3431 template <class TreeBuilder> TreeProperty Parser<LexerType>::parseGetterSetter(TreeBuilder& context, bool strict, PropertyNode::Type type, unsigned getterOrSetterStartOffset,
3432 ConstructorKind constructorKind, bool isClassProperty)
3434 const Identifier* stringPropertyName = 0;
3435 double numericPropertyName = 0;
3436 TreeExpression computedPropertyName = 0;
3438 JSTokenLocation location(tokenLocation());
3440 if (matchSpecIdentifier() || match(STRING) || m_token.m_type & KeywordTokenFlag) {
3441 stringPropertyName = m_token.m_data.ident;
3442 semanticFailIfTrue(isClassProperty && *stringPropertyName == m_vm->propertyNames->prototype,
3443 "Cannot declare a static method named 'prototype'");
3444 semanticFailIfTrue(isClassProperty && *stringPropertyName == m_vm->propertyNames->constructor,
3445 "Cannot declare a getter or setter named 'constructor'");
3447 } else if (match(DOUBLE) || match(INTEGER)) {
3448 numericPropertyName = m_token.m_data.doubleValue;
3450 } else if (match(OPENBRACKET)) {
3452 computedPropertyName = parseAssignmentExpression(context);
3453 failIfFalse(computedPropertyName, "Cannot parse computed property name");
3454 handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name");
3456 failDueToUnexpectedToken();
3458 ParserFunctionInfo<TreeBuilder> info;
3459 if (type & PropertyNode::Getter) {
3460 failIfFalse(match(OPENPAREN), "Expected a parameter list for getter definition");
3461 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::GetterMode, false, constructorKind, SuperBinding::Needed, getterOrSetterStartOffset, info, FunctionDefinitionType::Method)), "Cannot parse getter definition");
3463 failIfFalse(match(OPENPAREN), "Expected a parameter list for setter definition");
3464 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SourceParseMode::SetterMode, false, constructorKind, SuperBinding::Needed, getterOrSetterStartOffset, info, FunctionDefinitionType::Method)), "Cannot parse setter definition");
3467 if (stringPropertyName)
3468 return context.createGetterOrSetterProperty(location, type, strict, stringPropertyName, info, isClassProperty);
3470 if (computedPropertyName)
3471 return context.createGetterOrSetterProperty(location, static_cast<PropertyNode::Type>(type | PropertyNode::Computed), strict, computedPropertyName, info, isClassProperty);
3473 return context.createGetterOrSetterProperty(const_cast<VM*>(m_vm), m_parserArena, location, type, strict, numericPropertyName, info, isClassProperty);
3476 template <typename LexerType>
3477 template <class TreeBuilder> bool Parser<LexerType>::shouldCheckPropertyForUnderscoreProtoDuplicate(TreeBuilder& context, const TreeProperty& property)
3479 if (m_syntaxAlreadyValidated)
3482 if (!context.getName(property))
3485 // A Constant property that is not a Computed or Shorthand Constant property.
3486 return context.getType(property) == PropertyNode::Constant;
3489 template <typename LexerType>
3490 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLiteral(TreeBuilder& context)
3492 SavePoint savePoint = createSavePoint();
3493 consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings, "Expected opening '{' at the start of an object literal");
3495 int oldNonLHSCount = m_parserState.nonLHSCount;
3497 JSTokenLocation location(tokenLocation());
3498 if (match(CLOSEBRACE)) {
3500 return context.createObjectLiteral(location);
3503 TreeProperty property = parseProperty(context, false);
3504 failIfFalse(property, "Cannot parse object literal property");
3506 if (!m_syntaxAlreadyValidated && context.getType(property) & (PropertyNode::Getter | PropertyNode::Setter)) {
3507 restoreSavePoint(savePoint);
3508 return parseStrictObjectLiteral(context);
3511 bool seenUnderscoreProto = false;
3512 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property))
3513 seenUnderscoreProto = *context.getName(property) == m_vm->propertyNames->underscoreProto;
3515 TreePropertyList propertyList = context.createPropertyList(location, property);
3516 TreePropertyList tail = propertyList;
3517 while (match(COMMA)) {
3518 next(TreeBuilder::DontBuildStrings);
3519 if (match(CLOSEBRACE))
3521 JSTokenLocation propertyLocation(tokenLocation());
3522 property = parseProperty(context, false);
3523 failIfFalse(property, "Cannot parse object literal property");
3524 if (!m_syntaxAlreadyValidated && context.getType(property) & (PropertyNode::Getter | PropertyNode::Setter)) {
3525 restoreSavePoint(savePoint);
3526 return parseStrictObjectLiteral(context);
3528 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property)) {
3529 if (*context.getName(property) == m_vm->propertyNames->underscoreProto) {
3530 semanticFailIfTrue(seenUnderscoreProto, "Attempted to redefine __proto__ property");
3531 seenUnderscoreProto = true;
3534 tail = context.createPropertyList(propertyLocation, property, tail);
3537 location = tokenLocation();
3538 handleProductionOrFail2(CLOSEBRACE, "}", "end", "object literal");
3540 m_parserState.nonLHSCount = oldNonLHSCount;
3542 return context.createObjectLiteral(location, propertyList);
3545 template <typename LexerType>
3546 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseStrictObjectLiteral(TreeBuilder& context)
3548 consumeOrFail(OPENBRACE, "Expected opening '{' at the start of an object literal");
3550 int oldNonLHSCount = m_parserState.nonLHSCount;
3552 JSTokenLocation location(tokenLocation());
3553 if (match(CLOSEBRACE)) {
3555 return context.createObjectLiteral(location);
3558 TreeProperty property = parseProperty(context, true);
3559 failIfFalse(property, "Cannot parse object literal property");
3561 bool seenUnderscoreProto = false;
3562 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property))
3563 seenUnderscoreProto = *context.getName(property) == m_vm->propertyNames->underscoreProto;
3565 TreePropertyList propertyList = context.createPropertyList(location, property);
3566 TreePropertyList tail = propertyList;
3567 while (match(COMMA)) {
3569 if (match(CLOSEBRACE))
3571 JSTokenLocation propertyLocation(tokenLocation());
3572 property = parseProperty(context, true);
3573 failIfFalse(property, "Cannot parse object literal property");
3574 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property)) {
3575 if (*context.getName(property) == m_vm->propertyNames->underscoreProto) {
3576 semanticFailIfTrue(seenUnderscoreProto, "Attempted to redefine __proto__ property");
3577 seenUnderscoreProto = true;
3580 tail = context.createPropertyList(propertyLocation, property, tail);
3583 location = tokenLocation();
3584 handleProductionOrFail2(CLOSEBRACE, "}", "end", "object literal");
3586 m_parserState.nonLHSCount = oldNonLHSCount;
3588 return context.createObjectLiteral(location, propertyList);
3591 template <typename LexerType>
3592 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrayLiteral(TreeBuilder& context)
3594 consumeOrFailWithFlags(OPENBRACKET, TreeBuilder::DontBuildStrings, "Expected an opening '[' at the beginning of an array literal");
3596 int oldNonLHSCount = m_parserState.nonLHSCount;
3599 while (match(COMMA)) {
3600 next(TreeBuilder::DontBuildStrings);
3603 if (match(CLOSEBRACKET)) {
3604 JSTokenLocation location(tokenLocation());
3605 next(TreeBuilder::DontBuildStrings);
3606 return context.createArray(location, elisions);
3609 TreeExpression elem;
3610 if (UNLIKELY(match(DOTDOTDOT))) {
3611 auto spreadLocation = m_token.m_location;
3612 auto start = m_token.m_startPosition;
3613 auto divot = m_token.m_endPosition;
3615 auto spreadExpr = parseAssignmentExpressionOrPropagateErrorClass(context);
3616 failIfFalse(spreadExpr, "Cannot parse subject of a spread operation");
3617 elem = context.createSpreadExpression(spreadLocation, spreadExpr, start, divot, m_lastTokenEndPosition);
3619 elem = parseAssignmentExpressionOrPropagateErrorClass(context);
3620 failIfFalse(elem, "Cannot parse array literal element");
3621 typename TreeBuilder::ElementList elementList = context.createElementList(elisions, elem);
3622 typename TreeBuilder::ElementList tail = elementList;
3624 while (match(COMMA)) {
3625 next(TreeBuilder::DontBuildStrings);
3628 while (match(COMMA)) {
3633 if (match(CLOSEBRACKET)) {
3634 JSTokenLocation location(tokenLocation());
3635 next(TreeBuilder::DontBuildStrings);
3636 return context.createArray(location, elisions, elementList);
3638 if (UNLIKELY(match(DOTDOTDOT))) {
3639 auto spreadLocation = m_token.m_location;
3640 auto start = m_token.m_startPosition;
3641 auto divot = m_token.m_endPosition;
3643 TreeExpression elem = parseAssignmentExpressionOrPropagateErrorClass(context);
3644 failIfFalse(elem, "Cannot parse subject of a spread operation");
3645 auto spread = context.createSpreadExpression(spreadLocation, elem, start, divot, m_lastTokenEndPosition);
3646 tail = context.createElementList(tail, elisions, spread);
3649 TreeExpression elem = parseAssignmentExpressionOrPropagateErrorClass(context);
3650 failIfFalse(elem, "Cannot parse array literal element");
3651 tail = context.createElementList(tail, elisions, elem);
3654 JSTokenLocation location(tokenLocation());
3655 if (!consume(CLOSEBRACKET)) {
3656 failIfFalse(match(DOTDOTDOT), "Expected either a closing ']' or a ',' following an array element");
3657 semanticFail("The '...' operator should come before a target expression");
3660 m_parserState.nonLHSCount = oldNonLHSCount;
3662 return context.createArray(location, elementList);
3665 template <typename LexerType>
3666 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseFunctionExpression(TreeBuilder& context)
3668 ASSERT(match(FUNCTION));
3669 JSTokenLocation location(tokenLocation());
3670 unsigned functionKeywordStart = tokenStart();
3672 ParserFunctionInfo<TreeBuilder> functionInfo;
3673 functionInfo.name = &m_vm->propertyNames->nullIdentifier;
3674 SourceParseMode parseMode = SourceParseMode::NormalFunctionMode;
3676 parseMode = SourceParseMode::GeneratorWrapperFunctionMode;
3677 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, parseMode, false, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Expression)), "Cannot parse function expression");
3678 return context.createFunctionExpr(location, functionInfo);
3681 template <typename LexerType>
3682 template <class TreeBuilder> typename TreeBuilder::TemplateString Parser<LexerType>::parseTemplateString(TreeBuilder& context, bool isTemplateHead, typename LexerType::RawStringsBuildMode rawStringsBuildMode, bool& elementIsTail)
3684 if (!isTemplateHead) {
3685 matchOrFail(CLOSEBRACE, "Expected a closing '}' following an expression in template literal");
3686 // Re-scan the token to recognize it as Template Element.
3687 m_token.m_type = m_lexer->scanTrailingTemplateString(&m_token, rawStringsBuildMode);
3689 matchOrFail(TEMPLATE, "Expected an template element");
3690 const Identifier* cooked = m_token.m_data.cooked;
3691 const Identifier* raw = m_token.m_data.raw;
3692 elementIsTail = m_token.m_data.isTail;
3693 JSTokenLocation location(tokenLocation());
3695 return context.createTemplateString(location, *cooked, *raw);
3698 template <typename LexerType>
3699 template <class TreeBuilder> typename TreeBuilder::TemplateLiteral Parser<LexerType>::parseTemplateLiteral(TreeBuilder& context, typename LexerType::RawStringsBuildMode rawStringsBuildMode)
3701 JSTokenLocation location(tokenLocation());
3702 bool elementIsTail = false;
3704 auto headTemplateString = parseTemplateString(context, true, rawStringsBuildMode, elementIsTail);
3705 failIfFalse(headTemplateString, "Cannot parse head template element");
3707 typename TreeBuilder::TemplateStringList templateStringList = context.createTemplateStringList(headTemplateString);
3708 typename TreeBuilder::TemplateStringList templateStringTail = templateStringList;
3711 return context.createTemplateLiteral(location, templateStringList);
3713 failIfTrue(match(CLOSEBRACE), "Template literal expression cannot be empty");
3714 TreeExpression expression = parseExpression(context);
3715 failIfFalse(expression, "Cannot parse expression in template literal");
3717 typename TreeBuilder::TemplateExpressionList templateExpressionList = context.createTemplateExpressionList(expression);
3718 typename TreeBuilder::TemplateExpressionList templateExpressionTail = templateExpressionList;
3720 auto templateString = parseTemplateString(context, false, rawStringsBuildMode, elementIsTail);
3721 failIfFalse(templateString, "Cannot parse template element");
3722 templateStringTail = context.createTemplateStringList(tem