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 (!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 semanticFailureDueToKeyword(...) do { \
73 if (strictMode() && m_token.m_type == RESERVED_IF_STRICT) \
74 semanticFail("Cannot use the reserved word '", getToken(), "' as a ", __VA_ARGS__, " in strict mode"); \
75 if (m_token.m_type == RESERVED || m_token.m_type == RESERVED_IF_STRICT) \
76 semanticFail("Cannot use the reserved word '", getToken(), "' as a ", __VA_ARGS__); \
77 if (m_token.m_type & KeywordTokenFlag) \
78 semanticFail("Cannot use the keyword '", getToken(), "' as a ", __VA_ARGS__); \
85 template <typename LexerType>
86 void Parser<LexerType>::logError(bool)
90 StringPrintStream stream;
91 printUnexpectedTokenText(stream);
92 setErrorMessage(stream.toString());
95 template <typename LexerType> template <typename A>
96 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1)
100 StringPrintStream stream;
101 if (shouldPrintToken) {
102 printUnexpectedTokenText(stream);
105 stream.print(value1, ".");
106 setErrorMessage(stream.toString());
109 template <typename LexerType> template <typename A, typename B>
110 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2)
114 StringPrintStream stream;
115 if (shouldPrintToken) {
116 printUnexpectedTokenText(stream);
119 stream.print(value1, value2, ".");
120 setErrorMessage(stream.toString());
123 template <typename LexerType> template <typename A, typename B, typename C>
124 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3)
128 StringPrintStream stream;
129 if (shouldPrintToken) {
130 printUnexpectedTokenText(stream);
133 stream.print(value1, value2, value3, ".");
134 setErrorMessage(stream.toString());
137 template <typename LexerType> template <typename A, typename B, typename C, typename D>
138 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4)
142 StringPrintStream stream;
143 if (shouldPrintToken) {
144 printUnexpectedTokenText(stream);
147 stream.print(value1, value2, value3, value4, ".");
148 setErrorMessage(stream.toString());
151 template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E>
152 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4, const E& value5)
156 StringPrintStream stream;
157 if (shouldPrintToken) {
158 printUnexpectedTokenText(stream);
161 stream.print(value1, value2, value3, value4, value5, ".");
162 setErrorMessage(stream.toString());
165 template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E, typename F>
166 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4, const E& value5, const F& value6)
170 StringPrintStream stream;
171 if (shouldPrintToken) {
172 printUnexpectedTokenText(stream);
175 stream.print(value1, value2, value3, value4, value5, value6, ".");
176 setErrorMessage(stream.toString());
179 template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E, typename F, typename G>
180 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)
184 StringPrintStream stream;
185 if (shouldPrintToken) {
186 printUnexpectedTokenText(stream);
189 stream.print(value1, value2, value3, value4, value5, value6, value7, ".");
190 setErrorMessage(stream.toString());
193 template <typename LexerType>
194 Parser<LexerType>::Parser(VM* vm, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, SourceParseMode parseMode, SuperBinding superBinding, ConstructorKind defaultConstructorKind, ThisTDZMode thisTDZMode, DerivedContextType derivedContextType, bool isEvalContext, EvalContextType evalContextType)
197 , m_hasStackOverflow(false)
199 , m_syntaxAlreadyValidated(source.provider()->isValid())
200 , m_statementDepth(0)
201 , m_sourceElements(0)
202 , m_parsingBuiltin(builtinMode == JSParserBuiltinMode::Builtin)
203 , m_superBinding(superBinding)
204 , m_defaultConstructorKind(defaultConstructorKind)
205 , m_thisTDZMode(thisTDZMode)
206 , m_immediateParentAllowsFunctionDeclarationInStatement(false)
208 m_lexer = std::make_unique<LexerType>(vm, builtinMode);
209 m_lexer->setCode(source, &m_parserArena);
210 m_token.m_location.line = source.firstLine();
211 m_token.m_location.startOffset = source.startOffset();
212 m_token.m_location.endOffset = source.startOffset();
213 m_token.m_location.lineStartOffset = source.startOffset();
214 m_functionCache = vm->addSourceProviderCache(source.provider());
215 m_expressionErrorClassifier = nullptr;
217 ScopeRef scope = pushScope();
218 scope->setSourceParseMode(parseMode);
219 scope->setIsEvalContext(isEvalContext);
221 scope->setEvalContextType(evalContextType);
223 if (derivedContextType == DerivedContextType::DerivedConstructorContext) {
224 scope->setConstructorKind(ConstructorKind::Derived);
225 scope->setExpectedSuperBinding(SuperBinding::Needed);
228 if (derivedContextType == DerivedContextType::DerivedMethodContext)
229 scope->setExpectedSuperBinding(SuperBinding::Needed);
231 if (strictMode == JSParserStrictMode::Strict)
232 scope->setStrictMode();
237 template <typename LexerType>
238 Parser<LexerType>::~Parser()
242 template <typename LexerType>
243 String Parser<LexerType>::parseInner(const Identifier& calleeName, SourceParseMode parseMode)
245 String parseError = String();
247 ASTBuilder context(const_cast<VM*>(m_vm), m_parserArena, const_cast<SourceCode*>(m_source));
248 ScopeRef scope = currentScope();
249 scope->setIsLexicalScope();
250 SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_parserState.functionParsePhase, FunctionParsePhase::Body);
252 bool isArrowFunctionBodyExpression = false;
253 if (m_lexer->isReparsingFunction()) {
254 ParserFunctionInfo<ASTBuilder> functionInfo;
255 if (parseMode == SourceParseMode::GeneratorBodyMode)
256 functionInfo.parameters = createGeneratorParameters(context);
258 parseFunctionParameters(context, parseMode, functionInfo);
259 m_parameters = functionInfo.parameters;
261 if (parseMode == SourceParseMode::ArrowFunctionMode && !hasError()) {
262 // The only way we could have an error wile reparsing is if we run out of stack space.
263 RELEASE_ASSERT(match(ARROWFUNCTION));
265 isArrowFunctionBodyExpression = !match(OPENBRACE);
269 if (!calleeName.isNull())
270 scope->declareCallee(&calleeName);
272 if (m_lexer->isReparsingFunction())
275 SourceElements* sourceElements = nullptr;
276 // The only way we can error this early is if we reparse a function and we run out of stack space.
278 if (isArrowFunctionBodyExpression)
279 sourceElements = parseArrowFunctionSingleExpressionBodySourceElements(context);
280 else if (isModuleParseMode(parseMode))
281 sourceElements = parseModuleSourceElements(context, parseMode);
283 if (parseMode == SourceParseMode::GeneratorWrapperFunctionMode)
284 sourceElements = parseGeneratorFunctionSourceElements(context, CheckForStrictMode);
286 sourceElements = parseSourceElements(context, CheckForStrictMode);
290 bool validEnding = consume(EOFTOK);
291 if (!sourceElements || !validEnding) {
293 parseError = m_errorMessage;
295 parseError = ASCIILiteral("Parser error");
298 IdentifierSet capturedVariables;
299 UniquedStringImplPtrSet sloppyModeHoistedFunctions;
300 scope->getSloppyModeHoistedFunctions(sloppyModeHoistedFunctions);
301 scope->getCapturedVars(capturedVariables);
303 VariableEnvironment& varDeclarations = scope->declaredVariables();
304 for (auto& entry : capturedVariables)
305 varDeclarations.markVariableAsCaptured(entry);
307 if (parseMode == SourceParseMode::GeneratorWrapperFunctionMode) {
308 if (scope->usedVariablesContains(m_vm->propertyNames->arguments.impl()))
309 context.propagateArgumentsUse();
312 CodeFeatures features = context.features();
313 if (scope->strictMode())
314 features |= StrictModeFeature;
315 if (scope->shadowsArguments())
316 features |= ShadowsArgumentsFeature;
319 if (m_parsingBuiltin && isProgramParseMode(parseMode)) {
320 VariableEnvironment& lexicalVariables = scope->lexicalVariables();
321 const IdentifierSet& closedVariableCandidates = scope->closedVariableCandidates();
322 const BuiltinNames& builtinNames = m_vm->propertyNames->builtinNames();
323 for (const RefPtr<UniquedStringImpl>& candidate : closedVariableCandidates) {
324 if (!lexicalVariables.contains(candidate) && !varDeclarations.contains(candidate) && !builtinNames.isPrivateName(*candidate.get())) {
325 dataLog("Bad global capture in builtin: '", candidate, "'\n");
326 dataLog(m_source->view());
332 didFinishParsing(sourceElements, scope->takeFunctionDeclarations(), varDeclarations, WTFMove(sloppyModeHoistedFunctions), features, context.numConstants());
337 template <typename LexerType>
338 void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, DeclarationStacks::FunctionStack&& funcStack,
339 VariableEnvironment& varDeclarations, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, CodeFeatures features, int numConstants)
341 m_sourceElements = sourceElements;
342 m_funcDeclarations = WTFMove(funcStack);
343 m_varDeclarations.swap(varDeclarations);
344 m_features = features;
345 m_sloppyModeHoistedFunctions = WTFMove(sloppyModeHoistedFunctions);
346 m_numConstants = numConstants;
349 template <typename LexerType>
350 bool Parser<LexerType>::isArrowFunctionParameters()
352 bool isOpenParen = match(OPENPAREN);
353 bool isIdent = match(IDENT);
355 if (!isOpenParen && !isIdent)
358 bool isArrowFunction = false;
359 SavePoint saveArrowFunctionPoint = createSavePoint();
363 isArrowFunction = match(ARROWFUNCTION);
365 RELEASE_ASSERT(isOpenParen);
367 if (match(CLOSEPAREN)) {
369 isArrowFunction = match(ARROWFUNCTION);
371 SyntaxChecker syntaxChecker(const_cast<VM*>(m_vm), m_lexer.get());
372 // We make fake scope, otherwise parseFormalParameters will add variable to current scope that lead to errors
373 AutoPopScopeRef fakeScope(this, pushScope());
374 fakeScope->setSourceParseMode(SourceParseMode::ArrowFunctionMode);
376 unsigned parametersCount = 0;
377 isArrowFunction = parseFormalParameters(syntaxChecker, syntaxChecker.createFormalParameterList(), parametersCount) && consume(CLOSEPAREN) && match(ARROWFUNCTION);
379 popScope(fakeScope, syntaxChecker.NeedsFreeVariableInfo);
383 restoreSavePoint(saveArrowFunctionPoint);
385 return isArrowFunction;
388 template <typename LexerType>
389 bool Parser<LexerType>::allowAutomaticSemicolon()
391 return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator();
394 template <typename LexerType>
395 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context, SourceElementsMode mode)
397 const unsigned lengthOfUseStrictLiteral = 12; // "use strict".length
398 TreeSourceElements sourceElements = context.createSourceElements();
399 bool seenNonDirective = false;
400 const Identifier* directive = 0;
401 unsigned directiveLiteralLength = 0;
402 auto savePoint = createSavePoint();
403 bool hasSetStrict = false;
405 while (TreeStatement statement = parseStatementListItem(context, directive, &directiveLiteralLength)) {
406 if (mode == CheckForStrictMode && !seenNonDirective) {
408 // "use strict" must be the exact literal without escape sequences or line continuation.
409 if (!hasSetStrict && directiveLiteralLength == lengthOfUseStrictLiteral && m_vm->propertyNames->useStrictIdentifier == *directive) {
412 if (!isValidStrictMode()) {
413 if (m_parserState.lastFunctionName) {
414 if (m_vm->propertyNames->arguments == *m_parserState.lastFunctionName)
415 semanticFail("Cannot name a function 'arguments' in strict mode");
416 if (m_vm->propertyNames->eval == *m_parserState.lastFunctionName)
417 semanticFail("Cannot name a function 'eval' in strict mode");
419 if (hasDeclaredVariable(m_vm->propertyNames->arguments))
420 semanticFail("Cannot declare a variable named 'arguments' in strict mode");
421 if (hasDeclaredVariable(m_vm->propertyNames->eval))
422 semanticFail("Cannot declare a variable named 'eval' in strict mode");
423 semanticFailIfFalse(isValidStrictMode(), "Invalid parameters or function name in strict mode");
425 restoreSavePoint(savePoint);
430 seenNonDirective = true;
432 context.appendStatement(sourceElements, statement);
436 return sourceElements;
439 template <typename LexerType>
440 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseModuleSourceElements(TreeBuilder& context, SourceParseMode parseMode)
442 TreeSourceElements sourceElements = context.createSourceElements();
443 SyntaxChecker syntaxChecker(const_cast<VM*>(m_vm), m_lexer.get());
446 TreeStatement statement = 0;
448 statement = parseImportDeclaration(context);
449 else if (match(EXPORT))
450 statement = parseExportDeclaration(context);
452 const Identifier* directive = 0;
453 unsigned directiveLiteralLength = 0;
454 if (parseMode == SourceParseMode::ModuleAnalyzeMode) {
455 if (!parseStatementListItem(syntaxChecker, directive, &directiveLiteralLength))
459 statement = parseStatementListItem(context, directive, &directiveLiteralLength);
464 context.appendStatement(sourceElements, statement);
469 for (const auto& uid : currentScope()->moduleScopeData().exportedBindings()) {
470 if (currentScope()->hasDeclaredVariable(uid)) {
471 currentScope()->declaredVariables().markVariableAsExported(uid);
475 if (currentScope()->hasLexicallyDeclaredVariable(uid)) {
476 currentScope()->lexicalVariables().markVariableAsExported(uid);
480 semanticFail("Exported binding '", uid.get(), "' needs to refer to a top-level declared variable");
483 return sourceElements;
486 template <typename LexerType>
487 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseGeneratorFunctionSourceElements(TreeBuilder& context, SourceElementsMode mode)
489 auto sourceElements = context.createSourceElements();
491 unsigned functionKeywordStart = tokenStart();
492 JSTokenLocation startLocation(tokenLocation());
493 JSTextPosition start = tokenStartPosition();
494 unsigned startColumn = tokenColumn();
495 int functionNameStart = m_token.m_location.startOffset;
496 int parametersStart = m_token.m_location.startOffset;
498 ParserFunctionInfo<TreeBuilder> info;
499 info.name = &m_vm->propertyNames->nullIdentifier;
500 info.parameters = createGeneratorParameters(context);
501 info.startOffset = parametersStart;
502 info.startLine = tokenLine();
503 info.parameterCount = 4; // generator, state, value, resume mode
506 AutoPopScopeRef generatorBodyScope(this, pushScope());
507 generatorBodyScope->setSourceParseMode(SourceParseMode::GeneratorBodyMode);
508 SyntaxChecker generatorFunctionContext(const_cast<VM*>(m_vm), m_lexer.get());
509 failIfFalse(parseSourceElements(generatorFunctionContext, mode), "Cannot parse the body of a generator");
510 popScope(generatorBodyScope, TreeBuilder::NeedsFreeVariableInfo);
512 info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, SourceParseMode::GeneratorBodyMode, false);
514 info.endLine = tokenLine();
515 info.endOffset = m_token.m_data.offset;
516 info.bodyStartColumn = startColumn;
518 auto functionExpr = context.createFunctionExpr(startLocation, info);
519 auto statement = context.createExprStatement(startLocation, functionExpr, start, m_lastTokenEndPosition.line);
520 context.appendStatement(sourceElements, statement);
522 return sourceElements;
525 template <typename LexerType>
526 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatementListItem(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
528 // The grammar is documented here:
529 // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-statements
530 DepthManager statementDepth(&m_statementDepth);
532 TreeStatement result = 0;
533 bool shouldSetEndOffset = true;
534 switch (m_token.m_type) {
536 result = parseVariableDeclaration(context, DeclarationType::ConstDeclaration);
539 bool shouldParseVariableDeclaration = true;
541 SavePoint savePoint = createSavePoint();
543 // Intentionally use `match(IDENT) || match(LET) || match(YIELD)` and don't use `matchSpecIdentifier()`.
544 // We would like to fall into parseVariableDeclaration path even if "yield" is not treated as an Identifier.
545 // For example, under a generator context, matchSpecIdentifier() for "yield" returns `false`.
546 // But we would like to enter parseVariableDeclaration and raise an error under the context of parseVariableDeclaration
547 // to raise consistent errors between "var", "const" and "let".
548 if (!(match(IDENT) || match(LET) || match(YIELD)) && !match(OPENBRACE) && !match(OPENBRACKET))
549 shouldParseVariableDeclaration = false;
550 restoreSavePoint(savePoint);
552 if (shouldParseVariableDeclaration)
553 result = parseVariableDeclaration(context, DeclarationType::LetDeclaration);
555 bool allowFunctionDeclarationAsStatement = true;
556 result = parseExpressionOrLabelStatement(context, allowFunctionDeclarationAsStatement);
562 result = parseClassDeclaration(context);
565 result = parseFunctionDeclaration(context);
569 // This is a convenient place to notice labeled statements
570 // (even though we also parse them as normal statements)
571 // because we allow the following type of code in sloppy mode:
572 // ``` function foo() { label: function bar() { } } ```
573 bool allowFunctionDeclarationAsStatement = true;
574 result = parseExpressionOrLabelStatement(context, allowFunctionDeclarationAsStatement);
578 m_statementDepth--; // parseStatement() increments the depth.
579 result = parseStatement(context, directive, directiveLiteralLength);
580 shouldSetEndOffset = false;
584 if (result && shouldSetEndOffset)
585 context.setEndOffset(result, m_lastTokenEndPosition.offset);
590 template <typename LexerType>
591 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVariableDeclaration(TreeBuilder& context, DeclarationType declarationType, ExportType exportType)
593 ASSERT(match(VAR) || match(LET) || match(CONSTTOKEN));
594 JSTokenLocation location(tokenLocation());
595 int start = tokenLine();
598 TreeDestructuringPattern scratch1 = 0;
599 TreeExpression scratch2 = 0;
600 JSTextPosition scratch3;
602 TreeExpression variableDecls = parseVariableDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3, VarDeclarationContext, declarationType, exportType, scratchBool);
604 failIfFalse(autoSemiColon(), "Expected ';' after variable declaration");
606 return context.createDeclarationStatement(location, variableDecls, start, end);
609 template <typename LexerType>
610 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDoWhileStatement(TreeBuilder& context)
613 int startLine = tokenLine();
615 const Identifier* unused = 0;
617 TreeStatement statement = parseStatement(context, unused);
619 failIfFalse(statement, "Expected a statement following 'do'");
620 int endLine = tokenLine();
621 JSTokenLocation location(tokenLocation());
622 handleProductionOrFail(WHILE, "while", "end", "do-while loop");
623 handleProductionOrFail(OPENPAREN, "(", "start", "do-while loop condition");
624 semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a do-while loop condition");
625 TreeExpression expr = parseExpression(context);
626 failIfFalse(expr, "Unable to parse do-while loop condition");
627 handleProductionOrFail(CLOSEPAREN, ")", "end", "do-while loop condition");
628 if (match(SEMICOLON))
629 next(); // Always performs automatic semicolon insertion.
630 return context.createDoWhileStatement(location, statement, expr, startLine, endLine);
633 template <typename LexerType>
634 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWhileStatement(TreeBuilder& context)
636 ASSERT(match(WHILE));
637 JSTokenLocation location(tokenLocation());
638 int startLine = tokenLine();
641 handleProductionOrFail(OPENPAREN, "(", "start", "while loop condition");
642 semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a while loop condition");
643 TreeExpression expr = parseExpression(context);
644 failIfFalse(expr, "Unable to parse while loop condition");
645 int endLine = tokenLine();
646 handleProductionOrFail(CLOSEPAREN, ")", "end", "while loop condition");
648 const Identifier* unused = 0;
650 TreeStatement statement = parseStatement(context, unused);
652 failIfFalse(statement, "Expected a statement as the body of a while loop");
653 return context.createWhileStatement(location, expr, statement, startLine, endLine);
656 template <typename LexerType>
657 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)
659 ASSERT(declarationType == DeclarationType::LetDeclaration || declarationType == DeclarationType::VarDeclaration || declarationType == DeclarationType::ConstDeclaration);
660 TreeExpression head = 0;
661 TreeExpression tail = 0;
662 const Identifier* lastIdent;
663 JSToken lastIdentToken;
664 AssignmentContext assignmentContext = assignmentContextFromDeclarationType(declarationType);
667 lastPattern = TreeDestructuringPattern(0);
668 JSTokenLocation location(tokenLocation());
670 TreeExpression node = 0;
672 bool hasInitializer = false;
673 if (matchSpecIdentifier()) {
674 failIfTrue(match(LET) && (declarationType == DeclarationType::LetDeclaration || declarationType == DeclarationType::ConstDeclaration),
675 "Can't use 'let' as an identifier name for a LexicalDeclaration");
676 JSTextPosition varStart = tokenStartPosition();
677 JSTokenLocation varStartLocation(tokenLocation());
678 identStart = varStart;
679 const Identifier* name = m_token.m_data.ident;
681 lastIdentToken = m_token;
683 hasInitializer = match(EQUAL);
684 DeclarationResultMask declarationResult = declareVariable(name, declarationType);
685 if (declarationResult != DeclarationResult::Valid) {
686 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a variable named ", name->impl(), " in strict mode");
687 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration) {
688 if (declarationType == DeclarationType::LetDeclaration)
689 internalFailWithMessage(false, "Cannot declare a let variable twice: '", name->impl(), "'");
690 if (declarationType == DeclarationType::ConstDeclaration)
691 internalFailWithMessage(false, "Cannot declare a const variable twice: '", name->impl(), "'");
692 ASSERT(declarationType == DeclarationType::VarDeclaration);
693 internalFailWithMessage(false, "Cannot declare a var variable that shadows a let/const/class variable: '", name->impl(), "'");
696 if (exportType == ExportType::Exported) {
697 semanticFailIfFalse(exportName(*name), "Cannot export a duplicate name '", name->impl(), "'");
698 currentScope()->moduleScopeData().exportBinding(*name);
701 if (hasInitializer) {
702 JSTextPosition varDivot = tokenStartPosition() + 1;
703 initStart = tokenStartPosition();
704 next(TreeBuilder::DontBuildStrings); // consume '='
706 TreeExpression initializer = parseAssignmentExpression(context);
707 initEnd = lastTokenEndPosition();
708 lastInitializer = initializer;
709 failIfFalse(initializer, "Expected expression as the intializer for the variable '", name->impl(), "'");
711 node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEndPosition(), assignmentContext);
713 if (declarationListContext == ForLoopContext && declarationType == DeclarationType::ConstDeclaration)
714 forLoopConstDoesNotHaveInitializer = true;
715 failIfTrue(declarationListContext != ForLoopContext && declarationType == DeclarationType::ConstDeclaration, "const declared variable '", name->impl(), "'", " must have an initializer");
716 if (declarationType == DeclarationType::VarDeclaration)
717 node = context.createEmptyVarExpression(varStartLocation, *name);
719 node = context.createEmptyLetExpression(varStartLocation, *name);
723 auto pattern = parseDestructuringPattern(context, destructuringKindFromDeclarationType(declarationType), exportType, nullptr, nullptr, assignmentContext);
724 failIfFalse(pattern, "Cannot parse this destructuring pattern");
725 hasInitializer = match(EQUAL);
726 failIfTrue(declarationListContext == VarDeclarationContext && !hasInitializer, "Expected an initializer in destructuring variable declaration");
727 lastPattern = pattern;
728 if (hasInitializer) {
729 next(TreeBuilder::DontBuildStrings); // consume '='
730 TreeExpression rhs = parseAssignmentExpression(context);
731 node = context.createDestructuringAssignment(location, pattern, rhs);
732 lastInitializer = rhs;
740 head = context.createCommaExpr(location, head);
741 tail = context.appendToCommaExpr(location, head, head, node);
743 tail = context.appendToCommaExpr(location, head, tail, node);
745 } while (match(COMMA));
747 lastPattern = context.createBindingLocation(lastIdentToken.m_location, *lastIdent, lastIdentToken.m_startPosition, lastIdentToken.m_endPosition, assignmentContext);
752 template <typename LexerType>
753 bool Parser<LexerType>::declareRestOrNormalParameter(const Identifier& name, const Identifier** duplicateIdentifier)
755 DeclarationResultMask declarationResult = declareParameter(&name);
756 if ((declarationResult & DeclarationResult::InvalidStrictMode) && strictMode()) {
757 semanticFailIfTrue(isEvalOrArguments(&name), "Cannot destructure to a parameter name '", name.impl(), "' in strict mode");
758 if (m_parserState.lastFunctionName && name == *m_parserState.lastFunctionName)
759 semanticFail("Cannot declare a parameter named '", name.impl(), "' as it shadows the name of a strict mode function");
760 semanticFailureDueToKeyword("parameter name");
761 if (hasDeclaredParameter(name))
762 semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode as it has already been declared");
763 semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode");
765 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration) {
766 // It's not always an error to define a duplicate parameter.
767 // It's only an error when there are default parameter values or destructuring parameters.
768 // We note this value now so we can check it later.
769 if (duplicateIdentifier)
770 *duplicateIdentifier = &name;
776 template <typename LexerType>
777 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::createBindingPattern(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier& name, JSToken token, AssignmentContext bindingContext, const Identifier** duplicateIdentifier)
779 ASSERT(!name.isNull());
781 ASSERT(name.impl()->isAtomic() || name.impl()->isSymbol());
784 case DestructuringKind::DestructureToVariables: {
785 DeclarationResultMask declarationResult = declareVariable(&name);
786 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a variable named '", name.impl(), "' in strict mode");
787 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
788 internalFailWithMessage(false, "Cannot declare a var variable that shadows a let/const/class variable: '", name.impl(), "'");
792 case DestructuringKind::DestructureToLet:
793 case DestructuringKind::DestructureToConst:
794 case DestructuringKind::DestructureToCatchParameters: {
795 DeclarationResultMask declarationResult = declareVariable(&name, kind == DestructuringKind::DestructureToConst ? DeclarationType::ConstDeclaration : DeclarationType::LetDeclaration);
796 if (declarationResult != DeclarationResult::Valid) {
797 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot destructure to a variable named '", name.impl(), "' in strict mode");
798 failIfTrue(declarationResult & DeclarationResult::InvalidDuplicateDeclaration, "Cannot declare a lexical variable twice: '", name.impl(), "'");
803 case DestructuringKind::DestructureToParameters: {
804 declareRestOrNormalParameter(name, duplicateIdentifier);
809 case DestructuringKind::DestructureToExpressions: {
814 if (exportType == ExportType::Exported) {
815 semanticFailIfFalse(exportName(name), "Cannot export a duplicate name '", name.impl(), "'");
816 currentScope()->moduleScopeData().exportBinding(name);
818 return context.createBindingLocation(token.m_location, name, token.m_startPosition, token.m_endPosition, bindingContext);
821 template <typename LexerType>
822 template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern Parser<LexerType>::createAssignmentElement(TreeBuilder& context, TreeExpression& assignmentTarget, const JSTextPosition& startPosition, const JSTextPosition& endPosition)
824 return context.createAssignmentElement(assignmentTarget, startPosition, endPosition);
827 template <typename LexerType>
828 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseArrowFunctionSingleExpressionBodySourceElements(TreeBuilder& context)
830 ASSERT(!match(OPENBRACE));
832 JSTokenLocation location(tokenLocation());
833 JSTextPosition start = tokenStartPosition();
835 failIfStackOverflow();
836 TreeExpression expr = parseAssignmentExpression(context);
837 failIfFalse(expr, "Cannot parse the arrow function expression");
839 context.setEndOffset(expr, m_lastTokenEndPosition.offset);
841 JSTextPosition end = tokenEndPosition();
843 TreeSourceElements sourceElements = context.createSourceElements();
844 TreeStatement body = context.createReturnStatement(location, expr, start, end);
845 context.setEndOffset(body, m_lastTokenEndPosition.offset);
846 context.appendStatement(sourceElements, body);
848 return sourceElements;
851 template <typename LexerType>
852 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::tryParseDestructuringPatternExpression(TreeBuilder& context, AssignmentContext bindingContext)
854 return parseDestructuringPattern(context, DestructuringKind::DestructureToExpressions, ExportType::NotExported, nullptr, nullptr, bindingContext);
857 template <typename LexerType>
858 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseBindingOrAssignmentElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
860 if (kind == DestructuringKind::DestructureToExpressions)
861 return parseAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
862 return parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
865 template <typename LexerType>
866 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseAssignmentElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
868 TreeDestructuringPattern assignmentTarget = 0;
870 if (match(OPENBRACE) || match(OPENBRACKET)) {
871 SavePoint savePoint = createSavePoint();
872 assignmentTarget = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
873 if (assignmentTarget && !match(DOT) && !match(OPENBRACKET) && !match(OPENPAREN) && !match(TEMPLATE))
874 return assignmentTarget;
875 restoreSavePoint(savePoint);
878 JSTextPosition startPosition = tokenStartPosition();
879 auto element = parseMemberExpression(context);
881 semanticFailIfFalse(element && context.isAssignmentLocation(element), "Invalid destructuring assignment target");
883 if (strictMode() && m_parserState.lastIdentifier && context.isResolve(element)) {
884 bool isEvalOrArguments = m_vm->propertyNames->eval == *m_parserState.lastIdentifier || m_vm->propertyNames->arguments == *m_parserState.lastIdentifier;
885 failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", m_parserState.lastIdentifier->impl(), "' in strict mode");
888 return createAssignmentElement(context, element, startPosition, lastTokenEndPosition());
891 static const char* destructuringKindToVariableKindName(DestructuringKind kind)
894 case DestructuringKind::DestructureToLet:
895 case DestructuringKind::DestructureToConst:
896 return "lexical variable name";
897 case DestructuringKind::DestructureToVariables:
898 return "variable name";
899 case DestructuringKind::DestructureToParameters:
900 return "parameter name";
901 case DestructuringKind::DestructureToCatchParameters:
902 return "catch parameter name";
903 case DestructuringKind::DestructureToExpressions:
904 return "expression name";
906 RELEASE_ASSERT_NOT_REACHED();
910 template <typename LexerType>
911 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseDestructuringPattern(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
913 failIfStackOverflow();
914 int nonLHSCount = m_parserState.nonLHSCount;
915 TreeDestructuringPattern pattern;
916 switch (m_token.m_type) {
918 JSTextPosition divotStart = tokenStartPosition();
919 auto arrayPattern = context.createArrayPattern(m_token.m_location);
922 if (hasDestructuringPattern)
923 *hasDestructuringPattern = true;
925 bool restElementWasFound = false;
928 while (match(COMMA)) {
929 context.appendArrayPatternSkipEntry(arrayPattern, m_token.m_location);
934 if (match(CLOSEBRACKET))
937 if (UNLIKELY(match(DOTDOTDOT))) {
938 JSTokenLocation location = m_token.m_location;
940 auto innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
941 if (kind == DestructuringKind::DestructureToExpressions && !innerPattern)
943 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
945 failIfTrue(kind != DestructuringKind::DestructureToExpressions && !context.isBindingNode(innerPattern), "Expected identifier for a rest element destructuring pattern");
947 context.appendArrayPatternRestEntry(arrayPattern, location, innerPattern);
948 restElementWasFound = true;
952 JSTokenLocation location = m_token.m_location;
953 auto innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
954 if (kind == DestructuringKind::DestructureToExpressions && !innerPattern)
956 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
957 TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
958 context.appendArrayPatternEntry(arrayPattern, location, innerPattern, defaultValue);
959 } while (consume(COMMA));
961 consumeOrFail(CLOSEBRACKET, restElementWasFound ? "Expected a closing ']' following a rest element destructuring pattern" : "Expected either a closing ']' or a ',' following an element destructuring pattern");
962 context.finishArrayPattern(arrayPattern, divotStart, divotStart, lastTokenEndPosition());
963 pattern = arrayPattern;
967 auto objectPattern = context.createObjectPattern(m_token.m_location);
970 if (hasDestructuringPattern)
971 *hasDestructuringPattern = true;
974 bool wasString = false;
976 if (match(CLOSEBRACE))
979 const Identifier* propertyName = nullptr;
980 TreeExpression propertyExpression = 0;
981 TreeDestructuringPattern innerPattern = 0;
982 JSTokenLocation location = m_token.m_location;
983 if (matchSpecIdentifier()) {
984 failIfTrue(match(LET) && (kind == DestructuringKind::DestructureToLet || kind == DestructuringKind::DestructureToConst), "Can't use 'let' as an identifier name for a LexicalDeclaration");
985 propertyName = m_token.m_data.ident;
986 JSToken identifierToken = m_token;
989 innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
991 if (kind == DestructuringKind::DestructureToExpressions) {
992 bool isEvalOrArguments = m_vm->propertyNames->eval == *propertyName || m_vm->propertyNames->arguments == *propertyName;
993 if (isEvalOrArguments && strictMode())
994 reclassifyExpressionError(ErrorIndicatesPattern, ErrorIndicatesNothing);
995 failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", propertyName->impl(), "' in strict mode");
997 innerPattern = createBindingPattern(context, kind, exportType, *propertyName, identifierToken, bindingContext, duplicateIdentifier);
1000 JSTokenType tokenType = m_token.m_type;
1001 switch (m_token.m_type) {
1004 propertyName = &m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), m_token.m_data.doubleValue);
1007 propertyName = m_token.m_data.ident;
1012 propertyExpression = parseAssignmentExpression(context);
1013 failIfFalse(propertyExpression, "Cannot parse computed property name");
1014 matchOrFail(CLOSEBRACKET, "Expected ']' to end end a computed property name");
1017 if (m_token.m_type != RESERVED && m_token.m_type != RESERVED_IF_STRICT && !(m_token.m_type & KeywordTokenFlag)) {
1018 if (kind == DestructuringKind::DestructureToExpressions)
1020 failWithMessage("Expected a property name");
1022 propertyName = m_token.m_data.ident;
1026 if (!consume(COLON)) {
1027 if (kind == DestructuringKind::DestructureToExpressions)
1029 semanticFailIfTrue(tokenType == RESERVED, "Cannot use abbreviated destructuring syntax for reserved name '", propertyName->impl(), "'");
1030 semanticFailIfTrue(tokenType == RESERVED_IF_STRICT, "Cannot use abbreviated destructuring syntax for reserved name '", propertyName->impl(), "' in strict mode");
1031 semanticFailIfTrue(tokenType & KeywordTokenFlag, "Cannot use abbreviated destructuring syntax for keyword '", propertyName->impl(), "'");
1033 failWithMessage("Expected a ':' prior to a named destructuring property");
1035 innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
1037 if (kind == DestructuringKind::DestructureToExpressions && !innerPattern)
1039 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
1040 TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
1041 if (propertyExpression)
1042 context.appendObjectPatternEntry(objectPattern, location, propertyExpression, innerPattern, defaultValue);
1044 ASSERT(propertyName);
1045 context.appendObjectPatternEntry(objectPattern, location, wasString, *propertyName, innerPattern, defaultValue);
1047 } while (consume(COMMA));
1049 if (kind == DestructuringKind::DestructureToExpressions && !match(CLOSEBRACE))
1051 consumeOrFail(CLOSEBRACE, "Expected either a closing '}' or an ',' after a property destructuring pattern");
1052 pattern = objectPattern;
1057 if (!matchSpecIdentifier()) {
1058 if (kind == DestructuringKind::DestructureToExpressions)
1060 semanticFailureDueToKeyword(destructuringKindToVariableKindName(kind));
1061 failWithMessage("Expected a parameter pattern or a ')' in parameter list");
1063 failIfTrue(match(LET) && (kind == DestructuringKind::DestructureToLet || kind == DestructuringKind::DestructureToConst), "Can't use 'let' as an identifier name for a LexicalDeclaration");
1064 pattern = createBindingPattern(context, kind, exportType, *m_token.m_data.ident, m_token, bindingContext, duplicateIdentifier);
1069 m_parserState.nonLHSCount = nonLHSCount;
1073 template <typename LexerType>
1074 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseDefaultValueForDestructuringPattern(TreeBuilder& context)
1079 next(TreeBuilder::DontBuildStrings); // consume '='
1080 return parseAssignmentExpression(context);
1083 template <typename LexerType>
1084 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement(TreeBuilder& context)
1087 JSTokenLocation location(tokenLocation());
1088 int startLine = tokenLine();
1090 handleProductionOrFail(OPENPAREN, "(", "start", "for-loop header");
1091 int nonLHSCount = m_parserState.nonLHSCount;
1092 int declarations = 0;
1093 JSTextPosition declsStart;
1094 JSTextPosition declsEnd;
1095 TreeExpression decls = 0;
1096 TreeDestructuringPattern pattern = 0;
1097 bool isVarDeclaraton = match(VAR);
1098 bool isLetDeclaration = match(LET);
1099 bool isConstDeclaration = match(CONSTTOKEN);
1100 bool forLoopConstDoesNotHaveInitializer = false;
1102 VariableEnvironment dummySet;
1103 VariableEnvironment* lexicalVariables = nullptr;
1104 AutoCleanupLexicalScope lexicalScope;
1106 auto gatherLexicalVariablesIfNecessary = [&] {
1107 if (isLetDeclaration || isConstDeclaration) {
1108 ScopeRef scope = lexicalScope.scope();
1109 lexicalVariables = &scope->finalizeLexicalEnvironment();
1111 lexicalVariables = &dummySet;
1114 auto popLexicalScopeIfNecessary = [&] {
1115 if (isLetDeclaration || isConstDeclaration)
1116 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1119 if (isVarDeclaraton || isLetDeclaration || isConstDeclaration) {
1121 for (var/let/const IDENT in/of expression) statement
1122 for (var/let/const varDeclarationList; expressionOpt; expressionOpt)
1124 if (isLetDeclaration || isConstDeclaration) {
1125 ScopeRef newScope = pushScope();
1126 newScope->setIsLexicalScope();
1127 newScope->preventVarDeclarations();
1128 lexicalScope.setIsValid(newScope, this);
1131 TreeDestructuringPattern forInTarget = 0;
1132 TreeExpression forInInitializer = 0;
1134 JSTextPosition initStart;
1135 JSTextPosition initEnd;
1136 DeclarationType declarationType;
1137 if (isVarDeclaraton)
1138 declarationType = DeclarationType::VarDeclaration;
1139 else if (isLetDeclaration)
1140 declarationType = DeclarationType::LetDeclaration;
1141 else if (isConstDeclaration)
1142 declarationType = DeclarationType::ConstDeclaration;
1144 RELEASE_ASSERT_NOT_REACHED();
1145 decls = parseVariableDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd, ForLoopContext, declarationType, ExportType::NotExported, forLoopConstDoesNotHaveInitializer);
1149 // Remainder of a standard for loop is handled identically
1150 if (match(SEMICOLON))
1151 goto standardForLoop;
1153 failIfFalse(declarations == 1, "can only declare a single variable in an enumeration");
1155 // Handle for-in with var declaration
1156 JSTextPosition inLocation = tokenStartPosition();
1157 bool isOfEnumeration = false;
1158 if (!consume(INTOKEN)) {
1159 failIfFalse(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax");
1160 isOfEnumeration = true;
1163 bool hasAnyAssignments = !!forInInitializer;
1164 if (hasAnyAssignments) {
1165 if (isOfEnumeration)
1166 internalFailWithMessage(false, "Cannot assign to the loop variable inside a for-of loop header");
1167 internalFailWithMessage(false, "Cannot assign to the loop variable inside a for-in loop header");
1169 TreeExpression expr = parseExpression(context);
1170 failIfFalse(expr, "Expected expression to enumerate");
1171 JSTextPosition exprEnd = lastTokenEndPosition();
1173 int endLine = tokenLine();
1175 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
1177 const Identifier* unused = 0;
1179 TreeStatement statement = parseStatement(context, unused);
1181 failIfFalse(statement, "Expected statement as body of for-", isOfEnumeration ? "of" : "in", " statement");
1182 gatherLexicalVariablesIfNecessary();
1183 TreeStatement result;
1184 if (isOfEnumeration)
1185 result = context.createForOfLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
1187 result = context.createForInLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
1188 popLexicalScopeIfNecessary();
1192 if (!match(SEMICOLON)) {
1193 if (match(OPENBRACE) || match(OPENBRACKET)) {
1194 SavePoint savePoint = createSavePoint();
1195 declsStart = tokenStartPosition();
1196 pattern = tryParseDestructuringPatternExpression(context, AssignmentContext::DeclarationStatement);
1197 declsEnd = lastTokenEndPosition();
1198 if (pattern && (match(INTOKEN) || (match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of)))
1199 goto enumerationLoop;
1200 pattern = TreeDestructuringPattern(0);
1201 restoreSavePoint(savePoint);
1204 declsStart = tokenStartPosition();
1205 decls = parseExpression(context);
1206 declsEnd = lastTokenEndPosition();
1208 failIfFalse(decls, "Cannot parse for loop declarations");
1211 if (match(SEMICOLON)) {
1213 // Standard for loop
1215 TreeExpression condition = 0;
1216 failIfTrue(forLoopConstDoesNotHaveInitializer && isConstDeclaration, "const variables in for loops must have initializers");
1218 if (!match(SEMICOLON)) {
1219 condition = parseExpression(context);
1220 failIfFalse(condition, "Cannot parse for loop condition expression");
1222 consumeOrFail(SEMICOLON, "Expected a ';' after the for loop condition expression");
1224 TreeExpression increment = 0;
1225 if (!match(CLOSEPAREN)) {
1226 increment = parseExpression(context);
1227 failIfFalse(increment, "Cannot parse for loop iteration expression");
1229 int endLine = tokenLine();
1230 handleProductionOrFail(CLOSEPAREN, ")", "end", "for-loop header");
1231 const Identifier* unused = 0;
1233 TreeStatement statement = parseStatement(context, unused);
1235 failIfFalse(statement, "Expected a statement as the body of a for loop");
1236 gatherLexicalVariablesIfNecessary();
1237 TreeStatement result = context.createForLoop(location, decls, condition, increment, statement, startLine, endLine, *lexicalVariables);
1238 popLexicalScopeIfNecessary();
1242 // For-in and For-of loop
1244 failIfFalse(nonLHSCount == m_parserState.nonLHSCount, "Expected a reference on the left hand side of an enumeration statement");
1245 bool isOfEnumeration = false;
1246 if (!consume(INTOKEN)) {
1247 failIfFalse(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax");
1248 isOfEnumeration = true;
1251 TreeExpression expr = parseExpression(context);
1252 failIfFalse(expr, "Cannot parse subject for-", isOfEnumeration ? "of" : "in", " statement");
1253 JSTextPosition exprEnd = lastTokenEndPosition();
1254 int endLine = tokenLine();
1256 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
1257 const Identifier* unused = 0;
1259 TreeStatement statement = parseStatement(context, unused);
1261 failIfFalse(statement, "Expected a statement as the body of a for-", isOfEnumeration ? "of" : "in", "loop");
1262 gatherLexicalVariablesIfNecessary();
1263 TreeStatement result;
1266 if (isOfEnumeration)
1267 result = context.createForOfLoop(location, pattern, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1269 result = context.createForInLoop(location, pattern, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1271 popLexicalScopeIfNecessary();
1274 if (isOfEnumeration)
1275 result = context.createForOfLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1277 result = context.createForInLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1278 popLexicalScopeIfNecessary();
1282 template <typename LexerType>
1283 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatement(TreeBuilder& context)
1285 ASSERT(match(BREAK));
1286 JSTokenLocation location(tokenLocation());
1287 JSTextPosition start = tokenStartPosition();
1288 JSTextPosition end = tokenEndPosition();
1291 if (autoSemiColon()) {
1292 semanticFailIfFalse(breakIsValid(), "'break' is only valid inside a switch or loop statement");
1293 return context.createBreakStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
1295 failIfFalse(matchSpecIdentifier(), "Expected an identifier as the target for a break statement");
1296 const Identifier* ident = m_token.m_data.ident;
1297 semanticFailIfFalse(getLabel(ident), "Cannot use the undeclared label '", ident->impl(), "'");
1298 end = tokenEndPosition();
1300 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted break statement");
1301 return context.createBreakStatement(location, ident, start, end);
1304 template <typename LexerType>
1305 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueStatement(TreeBuilder& context)
1307 ASSERT(match(CONTINUE));
1308 JSTokenLocation location(tokenLocation());
1309 JSTextPosition start = tokenStartPosition();
1310 JSTextPosition end = tokenEndPosition();
1313 if (autoSemiColon()) {
1314 semanticFailIfFalse(continueIsValid(), "'continue' is only valid inside a loop statement");
1315 return context.createContinueStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
1317 failIfFalse(matchSpecIdentifier(), "Expected an identifier as the target for a continue statement");
1318 const Identifier* ident = m_token.m_data.ident;
1319 ScopeLabelInfo* label = getLabel(ident);
1320 semanticFailIfFalse(label, "Cannot use the undeclared label '", ident->impl(), "'");
1321 semanticFailIfFalse(label->isLoop, "Cannot continue to the label '", ident->impl(), "' as it is not targeting a loop");
1322 end = tokenEndPosition();
1324 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted continue statement");
1325 return context.createContinueStatement(location, ident, start, end);
1328 template <typename LexerType>
1329 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStatement(TreeBuilder& context)
1331 ASSERT(match(RETURN));
1332 JSTokenLocation location(tokenLocation());
1333 semanticFailIfFalse(currentScope()->isFunction(), "Return statements are only valid inside functions");
1334 JSTextPosition start = tokenStartPosition();
1335 JSTextPosition end = tokenEndPosition();
1337 // We do the auto semicolon check before attempting to parse expression
1338 // as we need to ensure the a line break after the return correctly terminates
1340 if (match(SEMICOLON))
1341 end = tokenEndPosition();
1343 if (autoSemiColon())
1344 return context.createReturnStatement(location, 0, start, end);
1345 TreeExpression expr = parseExpression(context);
1346 failIfFalse(expr, "Cannot parse the return expression");
1347 end = lastTokenEndPosition();
1348 if (match(SEMICOLON))
1349 end = tokenEndPosition();
1350 if (!autoSemiColon())
1351 failWithMessage("Expected a ';' following a return statement");
1352 return context.createReturnStatement(location, expr, start, end);
1355 template <typename LexerType>
1356 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseThrowStatement(TreeBuilder& context)
1358 ASSERT(match(THROW));
1359 JSTokenLocation location(tokenLocation());
1360 JSTextPosition start = tokenStartPosition();
1362 failIfTrue(match(SEMICOLON), "Expected expression after 'throw'");
1363 semanticFailIfTrue(autoSemiColon(), "Cannot have a newline after 'throw'");
1365 TreeExpression expr = parseExpression(context);
1366 failIfFalse(expr, "Cannot parse expression for throw statement");
1367 JSTextPosition end = lastTokenEndPosition();
1368 failIfFalse(autoSemiColon(), "Expected a ';' after a throw statement");
1370 return context.createThrowStatement(location, expr, start, end);
1373 template <typename LexerType>
1374 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement(TreeBuilder& context)
1376 ASSERT(match(WITH));
1377 JSTokenLocation location(tokenLocation());
1378 semanticFailIfTrue(strictMode(), "'with' statements are not valid in strict mode");
1379 currentScope()->setNeedsFullActivation();
1380 int startLine = tokenLine();
1383 handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'with' statement");
1384 int start = tokenStart();
1385 TreeExpression expr = parseExpression(context);
1386 failIfFalse(expr, "Cannot parse 'with' subject expression");
1387 JSTextPosition end = lastTokenEndPosition();
1388 int endLine = tokenLine();
1389 handleProductionOrFail(CLOSEPAREN, ")", "start", "subject of a 'with' statement");
1390 const Identifier* unused = 0;
1391 TreeStatement statement = parseStatement(context, unused);
1392 failIfFalse(statement, "A 'with' statement must have a body");
1394 return context.createWithStatement(location, expr, statement, start, end, startLine, endLine);
1397 template <typename LexerType>
1398 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseSwitchStatement(TreeBuilder& context)
1400 ASSERT(match(SWITCH));
1401 JSTokenLocation location(tokenLocation());
1402 int startLine = tokenLine();
1404 handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'switch'");
1405 TreeExpression expr = parseExpression(context);
1406 failIfFalse(expr, "Cannot parse switch subject expression");
1407 int endLine = tokenLine();
1409 handleProductionOrFail(CLOSEPAREN, ")", "end", "subject of a 'switch'");
1410 handleProductionOrFail(OPENBRACE, "{", "start", "body of a 'switch'");
1411 AutoPopScopeRef lexicalScope(this, pushScope());
1412 lexicalScope->setIsLexicalScope();
1413 lexicalScope->preventVarDeclarations();
1415 TreeClauseList firstClauses = parseSwitchClauses(context);
1418 TreeClause defaultClause = parseSwitchDefaultClause(context);
1421 TreeClauseList secondClauses = parseSwitchClauses(context);
1424 handleProductionOrFail(CLOSEBRACE, "}", "end", "body of a 'switch'");
1426 TreeStatement result = context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine, lexicalScope->finalizeLexicalEnvironment(), lexicalScope->takeFunctionDeclarations());
1427 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1431 template <typename LexerType>
1432 template <class TreeBuilder> TreeClauseList Parser<LexerType>::parseSwitchClauses(TreeBuilder& context)
1436 unsigned startOffset = tokenStart();
1438 TreeExpression condition = parseExpression(context);
1439 failIfFalse(condition, "Cannot parse switch clause");
1440 consumeOrFail(COLON, "Expected a ':' after switch clause expression");
1441 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1442 failIfFalse(statements, "Cannot parse the body of a switch clause");
1443 TreeClause clause = context.createClause(condition, statements);
1444 context.setStartOffset(clause, startOffset);
1445 TreeClauseList clauseList = context.createClauseList(clause);
1446 TreeClauseList tail = clauseList;
1448 while (match(CASE)) {
1449 startOffset = tokenStart();
1451 TreeExpression condition = parseExpression(context);
1452 failIfFalse(condition, "Cannot parse switch case expression");
1453 consumeOrFail(COLON, "Expected a ':' after switch clause expression");
1454 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1455 failIfFalse(statements, "Cannot parse the body of a switch clause");
1456 clause = context.createClause(condition, statements);
1457 context.setStartOffset(clause, startOffset);
1458 tail = context.createClauseList(tail, clause);
1463 template <typename LexerType>
1464 template <class TreeBuilder> TreeClause Parser<LexerType>::parseSwitchDefaultClause(TreeBuilder& context)
1466 if (!match(DEFAULT))
1468 unsigned startOffset = tokenStart();
1470 consumeOrFail(COLON, "Expected a ':' after switch default clause");
1471 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1472 failIfFalse(statements, "Cannot parse the body of a switch default clause");
1473 TreeClause result = context.createClause(0, statements);
1474 context.setStartOffset(result, startOffset);
1478 template <typename LexerType>
1479 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(TreeBuilder& context)
1482 JSTokenLocation location(tokenLocation());
1483 TreeStatement tryBlock = 0;
1484 TreeDestructuringPattern catchPattern = 0;
1485 TreeStatement catchBlock = 0;
1486 TreeStatement finallyBlock = 0;
1487 int firstLine = tokenLine();
1489 matchOrFail(OPENBRACE, "Expected a block statement as body of a try statement");
1491 tryBlock = parseBlockStatement(context);
1492 failIfFalse(tryBlock, "Cannot parse the body of try block");
1493 int lastLine = m_lastTokenEndPosition.line;
1494 VariableEnvironment catchEnvironment;
1498 handleProductionOrFail(OPENPAREN, "(", "start", "'catch' target");
1499 AutoPopScopeRef catchScope(this, pushScope());
1500 catchScope->setIsLexicalScope();
1501 catchScope->preventVarDeclarations();
1502 const Identifier* ident = nullptr;
1503 if (matchSpecIdentifier()) {
1504 ident = m_token.m_data.ident;
1505 catchPattern = context.createBindingLocation(m_token.m_location, *ident, m_token.m_startPosition, m_token.m_endPosition, AssignmentContext::DeclarationStatement);
1507 failIfTrueIfStrict(catchScope->declareLexicalVariable(ident, false) & DeclarationResult::InvalidStrictMode, "Cannot declare a catch variable named '", ident->impl(), "' in strict mode");
1509 catchPattern = parseDestructuringPattern(context, DestructuringKind::DestructureToCatchParameters, ExportType::NotExported);
1510 failIfFalse(catchPattern, "Cannot parse this destructuring pattern");
1512 handleProductionOrFail(CLOSEPAREN, ")", "end", "'catch' target");
1513 matchOrFail(OPENBRACE, "Expected exception handler to be a block statement");
1514 catchBlock = parseBlockStatement(context);
1515 failIfFalse(catchBlock, "Unable to parse 'catch' block");
1516 catchEnvironment = catchScope->finalizeLexicalEnvironment();
1517 RELEASE_ASSERT(!ident || (catchEnvironment.size() == 1 && catchEnvironment.contains(ident->impl())));
1518 popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo);
1521 if (match(FINALLY)) {
1523 matchOrFail(OPENBRACE, "Expected block statement for finally body");
1524 finallyBlock = parseBlockStatement(context);
1525 failIfFalse(finallyBlock, "Cannot parse finally body");
1527 failIfFalse(catchBlock || finallyBlock, "Try statements must have at least a catch or finally block");
1528 return context.createTryStatement(location, tryBlock, catchPattern, catchBlock, finallyBlock, firstLine, lastLine, catchEnvironment);
1531 template <typename LexerType>
1532 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDebuggerStatement(TreeBuilder& context)
1534 ASSERT(match(DEBUGGER));
1535 JSTokenLocation location(tokenLocation());
1536 int startLine = tokenLine();
1537 int endLine = startLine;
1539 if (match(SEMICOLON))
1540 startLine = tokenLine();
1541 failIfFalse(autoSemiColon(), "Debugger keyword must be followed by a ';'");
1542 return context.createDebugger(location, startLine, endLine);
1545 template <typename LexerType>
1546 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context)
1548 ASSERT(match(OPENBRACE));
1550 // We should treat the first block statement of the function (the body of the function) as the lexical
1551 // scope of the function itself, and not the lexical scope of a 'block' statement within the function.
1552 AutoCleanupLexicalScope lexicalScope;
1553 bool shouldPushLexicalScope = m_statementDepth > 0;
1554 if (shouldPushLexicalScope) {
1555 ScopeRef newScope = pushScope();
1556 newScope->setIsLexicalScope();
1557 newScope->preventVarDeclarations();
1558 lexicalScope.setIsValid(newScope, this);
1560 JSTokenLocation location(tokenLocation());
1561 int startOffset = m_token.m_data.offset;
1562 int start = tokenLine();
1563 VariableEnvironment emptyEnvironment;
1564 DeclarationStacks::FunctionStack emptyFunctionStack;
1566 if (match(CLOSEBRACE)) {
1567 int endOffset = m_token.m_data.offset;
1569 TreeStatement result = context.createBlockStatement(location, 0, start, m_lastTokenEndPosition.line, shouldPushLexicalScope ? currentScope()->finalizeLexicalEnvironment() : emptyEnvironment, shouldPushLexicalScope ? currentScope()->takeFunctionDeclarations() : WTFMove(emptyFunctionStack));
1570 context.setStartOffset(result, startOffset);
1571 context.setEndOffset(result, endOffset);
1572 if (shouldPushLexicalScope)
1573 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1576 TreeSourceElements subtree = parseSourceElements(context, DontCheckForStrictMode);
1577 failIfFalse(subtree, "Cannot parse the body of the block statement");
1578 matchOrFail(CLOSEBRACE, "Expected a closing '}' at the end of a block statement");
1579 int endOffset = m_token.m_data.offset;
1581 TreeStatement result = context.createBlockStatement(location, subtree, start, m_lastTokenEndPosition.line, shouldPushLexicalScope ? currentScope()->finalizeLexicalEnvironment() : emptyEnvironment, shouldPushLexicalScope ? currentScope()->takeFunctionDeclarations() : WTFMove(emptyFunctionStack));
1582 context.setStartOffset(result, startOffset);
1583 context.setEndOffset(result, endOffset);
1584 if (shouldPushLexicalScope)
1585 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1590 template <typename LexerType>
1591 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
1593 DepthManager statementDepth(&m_statementDepth);
1596 int nonTrivialExpressionCount = 0;
1597 failIfStackOverflow();
1598 TreeStatement result = 0;
1599 bool shouldSetEndOffset = true;
1600 bool parentAllowsFunctionDeclarationAsStatement = m_immediateParentAllowsFunctionDeclarationInStatement;
1601 m_immediateParentAllowsFunctionDeclarationInStatement = false;
1603 switch (m_token.m_type) {
1605 result = parseBlockStatement(context);
1606 shouldSetEndOffset = false;
1609 result = parseVariableDeclaration(context, DeclarationType::VarDeclaration);
1612 if (!strictMode()) {
1613 failIfFalse(parentAllowsFunctionDeclarationAsStatement, "Function declarations are only allowed inside block statements or at the top level of a program");
1614 if (currentScope()->isFunction()) {
1615 // Any function declaration that isn't in a block is a syntax error unless it's
1616 // in an if/else statement. If it's in an if/else statement, we will magically
1617 // treat it as if the if/else statement is inside a block statement.
1618 // to the very top like a "var". For example:
1620 // if (cond) function foo() { }
1622 // will be rewritten as:
1624 // if (cond) { function foo() { } }
1626 AutoPopScopeRef blockScope(this, pushScope());
1627 blockScope->setIsLexicalScope();
1628 blockScope->preventVarDeclarations();
1629 JSTokenLocation location(tokenLocation());
1630 int start = tokenLine();
1632 TreeStatement function = parseFunctionDeclaration(context);
1634 failIfFalse(function, "Expected valid function statement after 'function' keyword");
1635 TreeSourceElements sourceElements = context.createSourceElements();
1636 context.appendStatement(sourceElements, function);
1637 result = context.createBlockStatement(location, sourceElements, start, m_lastTokenEndPosition.line, currentScope()->finalizeLexicalEnvironment(), currentScope()->takeFunctionDeclarations());
1638 popScope(blockScope, TreeBuilder::NeedsFreeVariableInfo);
1640 // We only implement annex B.3.3 if we're in function mode. Otherwise, we fall back
1641 // to hoisting behavior.
1642 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=155813
1643 DepthManager statementDepth(&m_statementDepth);
1644 m_statementDepth = 1;
1645 result = parseFunctionDeclaration(context);
1648 failWithMessage("Function declarations are only allowed inside blocks or switch statements in strict mode");
1652 JSTokenLocation location(tokenLocation());
1654 result = context.createEmptyStatement(location);
1658 result = parseIfStatement(context);
1661 result = parseDoWhileStatement(context);
1664 result = parseWhileStatement(context);
1667 result = parseForStatement(context);
1670 result = parseContinueStatement(context);
1673 result = parseBreakStatement(context);
1676 result = parseReturnStatement(context);
1679 result = parseWithStatement(context);
1682 result = parseSwitchStatement(context);
1685 result = parseThrowStatement(context);
1688 result = parseTryStatement(context);
1691 result = parseDebuggerStatement(context);
1697 // These tokens imply the end of a set of source elements
1701 bool allowFunctionDeclarationAsStatement = false;
1702 result = parseExpressionOrLabelStatement(context, allowFunctionDeclarationAsStatement);
1706 directive = m_token.m_data.ident;
1707 if (directiveLiteralLength)
1708 *directiveLiteralLength = m_token.m_location.endOffset - m_token.m_location.startOffset;
1709 nonTrivialExpressionCount = m_parserState.nonTrivialExpressionCount;
1712 TreeStatement exprStatement = parseExpressionStatement(context);
1713 if (directive && nonTrivialExpressionCount != m_parserState.nonTrivialExpressionCount)
1715 result = exprStatement;
1719 if (result && shouldSetEndOffset)
1720 context.setEndOffset(result, m_lastTokenEndPosition.offset);
1724 template <typename LexerType>
1725 template <class TreeBuilder> bool Parser<LexerType>::parseFormalParameters(TreeBuilder& context, TreeFormalParameterList list, unsigned& parameterCount)
1727 #define failIfDuplicateIfViolation() \
1728 if (duplicateParameter) {\
1729 semanticFailIfTrue(defaultValue, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with default parameter values");\
1730 semanticFailIfTrue(hasDestructuringPattern, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with destructuring parameters");\
1731 semanticFailIfTrue(isRestParameter, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with a rest parameter");\
1734 bool hasDestructuringPattern = false;
1735 bool isRestParameter = false;
1736 const Identifier* duplicateParameter = nullptr;
1738 TreeDestructuringPattern parameter = 0;
1739 TreeExpression defaultValue = 0;
1741 if (match(DOTDOTDOT)) {
1743 failIfFalse(matchSpecIdentifier(), "Rest parameter '...' should be followed by a variable identifier");
1744 declareRestOrNormalParameter(*m_token.m_data.ident, &duplicateParameter);
1746 JSTextPosition identifierStart = tokenStartPosition();
1747 JSTextPosition identifierEnd = tokenEndPosition();
1748 parameter = context.createRestParameter(*m_token.m_data.ident, parameterCount, identifierStart, identifierEnd);
1750 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.
1751 isRestParameter = true;
1753 parameter = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported, &duplicateParameter, &hasDestructuringPattern);
1754 failIfFalse(parameter, "Cannot parse parameter pattern");
1755 if (!isRestParameter)
1756 defaultValue = parseDefaultValueForDestructuringPattern(context);
1758 failIfDuplicateIfViolation();
1759 context.appendParameter(list, parameter, defaultValue);
1760 if (!isRestParameter)
1762 } while (!isRestParameter && consume(COMMA));
1765 #undef failIfDuplicateIfViolation
1768 template <typename LexerType>
1769 template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(
1770 TreeBuilder& context, const JSTokenLocation& startLocation, int startColumn, int functionKeywordStart, int functionNameStart, int parametersStart,
1771 ConstructorKind constructorKind, SuperBinding superBinding, FunctionBodyType bodyType, unsigned parameterCount, SourceParseMode parseMode)
1773 bool isArrowFunctionBodyExpression = bodyType == ArrowFunctionBodyExpression;
1774 if (!isArrowFunctionBodyExpression) {
1776 if (match(CLOSEBRACE)) {
1777 unsigned endColumn = tokenColumn();
1778 return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, superBinding, parameterCount, parseMode, isArrowFunctionBodyExpression);
1782 DepthManager statementDepth(&m_statementDepth);
1783 m_statementDepth = 0;
1784 SyntaxChecker syntaxChecker(const_cast<VM*>(m_vm), m_lexer.get());
1785 if (bodyType == ArrowFunctionBodyExpression)
1786 failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(syntaxChecker), "Cannot parse body of this arrow function");
1788 failIfFalse(parseSourceElements(syntaxChecker, CheckForStrictMode), bodyType == StandardFunctionBodyBlock ? "Cannot parse body of this function" : "Cannot parse body of this arrow function");
1789 unsigned endColumn = tokenColumn();
1790 return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, superBinding, parameterCount, parseMode, isArrowFunctionBodyExpression);
1793 static const char* stringForFunctionMode(SourceParseMode mode)
1796 case SourceParseMode::GetterMode:
1798 case SourceParseMode::SetterMode:
1800 case SourceParseMode::NormalFunctionMode:
1802 case SourceParseMode::MethodMode:
1804 case SourceParseMode::GeneratorBodyMode:
1806 case SourceParseMode::GeneratorWrapperFunctionMode:
1807 return "generator function";
1808 case SourceParseMode::ArrowFunctionMode:
1809 return "arrow function";
1810 case SourceParseMode::ProgramMode:
1811 case SourceParseMode::ModuleAnalyzeMode:
1812 case SourceParseMode::ModuleEvaluateMode:
1813 RELEASE_ASSERT_NOT_REACHED();
1816 RELEASE_ASSERT_NOT_REACHED();
1820 template <typename LexerType> template <class TreeBuilder> int Parser<LexerType>::parseFunctionParameters(TreeBuilder& context, SourceParseMode mode, ParserFunctionInfo<TreeBuilder>& functionInfo)
1822 RELEASE_ASSERT(mode != SourceParseMode::ProgramMode && mode != SourceParseMode::ModuleAnalyzeMode && mode != SourceParseMode::ModuleEvaluateMode);
1823 int parametersStart = m_token.m_location.startOffset;
1824 TreeFormalParameterList parameterList = context.createFormalParameterList();
1825 functionInfo.parameters = parameterList;
1826 functionInfo.startOffset = parametersStart;
1827 SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_parserState.functionParsePhase, FunctionParsePhase::Parameters);
1829 if (mode == SourceParseMode::ArrowFunctionMode) {
1830 if (!match(IDENT) && !match(OPENPAREN)) {
1831 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
1832 failWithMessage("Expected an arrow function input parameter");
1834 if (match(OPENPAREN)) {
1837 if (match(CLOSEPAREN))
1838 functionInfo.parameterCount = 0;
1840 failIfFalse(parseFormalParameters(context, parameterList, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
1842 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
1844 functionInfo.parameterCount = 1;
1845 auto parameter = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported);
1846 failIfFalse(parameter, "Cannot parse parameter pattern");
1847 context.appendParameter(parameterList, parameter, 0);
1851 return parametersStart;
1854 if (!consume(OPENPAREN)) {
1855 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
1856 failWithMessage("Expected an opening '(' before a ", stringForFunctionMode(mode), "'s parameter list");
1859 if (mode == SourceParseMode::GetterMode) {
1860 consumeOrFail(CLOSEPAREN, "getter functions must have no parameters");
1861 functionInfo.parameterCount = 0;
1862 } else if (mode == SourceParseMode::SetterMode) {
1863 failIfTrue(match(CLOSEPAREN), "setter functions must have one parameter");
1864 const Identifier* duplicateParameter = nullptr;
1865 auto parameter = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported, &duplicateParameter);
1866 failIfFalse(parameter, "setter functions must have one parameter");
1867 auto defaultValue = parseDefaultValueForDestructuringPattern(context);
1869 semanticFailIfTrue(duplicateParameter && defaultValue, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with default parameter values");
1870 context.appendParameter(parameterList, parameter, defaultValue);
1871 functionInfo.parameterCount = 1;
1872 failIfTrue(match(COMMA), "setter functions must have one parameter");
1873 consumeOrFail(CLOSEPAREN, "Expected a ')' after a parameter declaration");
1875 if (match(CLOSEPAREN))
1876 functionInfo.parameterCount = 0;
1878 failIfFalse(parseFormalParameters(context, parameterList, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
1879 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
1882 return parametersStart;
1885 template <typename LexerType>
1886 template <class TreeBuilder> typename TreeBuilder::FormalParameterList Parser<LexerType>::createGeneratorParameters(TreeBuilder& context)
1888 auto parameters = context.createFormalParameterList();
1890 JSTokenLocation location(tokenLocation());
1891 JSTextPosition position = tokenStartPosition();
1894 declareParameter(&m_vm->propertyNames->generatorPrivateName);
1895 auto generator = context.createBindingLocation(location, m_vm->propertyNames->generatorPrivateName, position, position, AssignmentContext::DeclarationStatement);
1896 context.appendParameter(parameters, generator, 0);
1899 declareParameter(&m_vm->propertyNames->generatorStatePrivateName);
1900 auto generatorState = context.createBindingLocation(location, m_vm->propertyNames->generatorStatePrivateName, position, position, AssignmentContext::DeclarationStatement);
1901 context.appendParameter(parameters, generatorState, 0);
1904 declareParameter(&m_vm->propertyNames->generatorValuePrivateName);
1905 auto generatorValue = context.createBindingLocation(location, m_vm->propertyNames->generatorValuePrivateName, position, position, AssignmentContext::DeclarationStatement);
1906 context.appendParameter(parameters, generatorValue, 0);
1908 // @generatorResumeMode
1909 declareParameter(&m_vm->propertyNames->generatorResumeModePrivateName);
1910 auto generatorResumeMode = context.createBindingLocation(location, m_vm->propertyNames->generatorResumeModePrivateName, position, position, AssignmentContext::DeclarationStatement);
1911 context.appendParameter(parameters, generatorResumeMode, 0);
1916 template <typename LexerType>
1917 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)
1919 RELEASE_ASSERT(isFunctionParseMode(mode));
1921 bool upperScopeIsGenerator = currentScope()->isGenerator();
1922 AutoPopScopeRef functionScope(this, pushScope());
1923 functionScope->setSourceParseMode(mode);
1924 SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_parserState.functionParsePhase, FunctionParsePhase::Body);
1925 int functionNameStart = m_token.m_location.startOffset;
1926 const Identifier* lastFunctionName = m_parserState.lastFunctionName;
1927 m_parserState.lastFunctionName = nullptr;
1928 int parametersStart;
1929 JSTokenLocation startLocation;
1931 FunctionBodyType functionBodyType;
1933 if (mode == SourceParseMode::ArrowFunctionMode) {
1934 startLocation = tokenLocation();
1935 functionInfo.startLine = tokenLine();
1936 startColumn = tokenColumn();
1938 parametersStart = parseFunctionParameters(context, mode, functionInfo);
1941 matchOrFail(ARROWFUNCTION, "Expected a '=>' after arrow function parameter declaration");
1943 if (m_lexer->prevTerminator())
1944 failDueToUnexpectedToken();
1946 ASSERT(constructorKind == ConstructorKind::None);
1948 // Check if arrow body start with {. If it true it mean that arrow function is Fat arrow function
1949 // and we need use common approach to parse function body
1951 functionBodyType = match(OPENBRACE) ? ArrowFunctionBodyBlock : ArrowFunctionBodyExpression;
1953 // http://ecma-international.org/ecma-262/6.0/#sec-function-definitions
1954 // FunctionExpression :
1955 // function BindingIdentifieropt ( FormalParameters ) { FunctionBody }
1957 // FunctionDeclaration[Yield, Default] :
1958 // function BindingIdentifier[?Yield] ( FormalParameters ) { FunctionBody }
1959 // [+Default] function ( FormalParameters ) { FunctionBody }
1961 // GeneratorDeclaration[Yield, Default] :
1962 // function * BindingIdentifier[?Yield] ( FormalParameters[Yield] ) { GeneratorBody }
1963 // [+Default] function * ( FormalParameters[Yield] ) { GeneratorBody }
1965 // GeneratorExpression :
1966 // function * BindingIdentifier[Yield]opt ( FormalParameters[Yield] ) { GeneratorBody }
1968 // The name of FunctionExpression can accept "yield" even in the context of generator.
1969 if (functionDefinitionType == FunctionDefinitionType::Expression && mode == SourceParseMode::NormalFunctionMode)
1970 upperScopeIsGenerator = false;
1972 if (matchSpecIdentifier(upperScopeIsGenerator)) {
1973 functionInfo.name = m_token.m_data.ident;
1974 m_parserState.lastFunctionName = functionInfo.name;
1976 if (!nameIsInContainingScope)
1977 failIfTrueIfStrict(functionScope->declareCallee(functionInfo.name) & DeclarationResult::InvalidStrictMode, "'", functionInfo.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode");
1978 } else if (requirements == FunctionNeedsName) {
1979 if (match(OPENPAREN) && mode == SourceParseMode::NormalFunctionMode)
1980 semanticFail("Function statements must have a name");
1981 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
1982 failDueToUnexpectedToken();
1986 startLocation = tokenLocation();
1987 functionInfo.startLine = tokenLine();
1988 startColumn = tokenColumn();
1990 parametersStart = parseFunctionParameters(context, mode, functionInfo);
1993 matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body");
1995 // BytecodeGenerator emits code to throw TypeError when a class constructor is "call"ed.
1996 // Set ConstructorKind to None for non-constructor methods of classes.
1998 if (m_defaultConstructorKind != ConstructorKind::None) {
1999 constructorKind = m_defaultConstructorKind;
2000 expectedSuperBinding = m_defaultConstructorKind == ConstructorKind::Derived ? SuperBinding::Needed : SuperBinding::NotNeeded;
2003 functionBodyType = StandardFunctionBodyBlock;
2006 functionScope->setConstructorKind(constructorKind);
2007 functionScope->setExpectedSuperBinding(expectedSuperBinding);
2009 functionInfo.bodyStartColumn = startColumn;
2011 // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
2012 if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(functionInfo.startOffset) : 0) {
2013 // If we're in a strict context, the cached function info must say it was strict too.
2014 ASSERT(!strictMode() || cachedInfo->strictMode);
2015 JSTokenLocation endLocation;
2017 endLocation.line = cachedInfo->lastTockenLine;
2018 endLocation.startOffset = cachedInfo->lastTockenStartOffset;
2019 endLocation.lineStartOffset = cachedInfo->lastTockenLineStartOffset;
2021 bool endColumnIsOnStartLine = (endLocation.line == functionInfo.startLine);
2022 ASSERT(endLocation.startOffset >= endLocation.lineStartOffset);
2023 unsigned bodyEndColumn = endColumnIsOnStartLine ?
2024 endLocation.startOffset - m_token.m_data.lineStartOffset :
2025 endLocation.startOffset - endLocation.lineStartOffset;
2026 unsigned currentLineStartOffset = m_token.m_location.lineStartOffset;
2028 functionInfo.body = context.createFunctionMetadata(
2029 startLocation, endLocation, functionInfo.bodyStartColumn, bodyEndColumn,
2030 functionKeywordStart, functionNameStart, parametersStart,
2031 cachedInfo->strictMode, constructorKind, expectedSuperBinding, cachedInfo->parameterCount, mode, functionBodyType == ArrowFunctionBodyExpression);
2033 functionScope->restoreFromSourceProviderCache(cachedInfo);
2034 popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo);
2036 m_token = cachedInfo->endFunctionToken();
2038 if (endColumnIsOnStartLine)
2039 m_token.m_location.lineStartOffset = currentLineStartOffset;
2041 m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset);
2042 m_lexer->setLineNumber(m_token.m_location.line);
2043 functionInfo.endOffset = cachedInfo->endFunctionOffset;
2045 if (mode == SourceParseMode::ArrowFunctionMode)
2046 functionBodyType = cachedInfo->isBodyArrowExpression ? ArrowFunctionBodyExpression : ArrowFunctionBodyBlock;
2048 functionBodyType = StandardFunctionBodyBlock;
2050 switch (functionBodyType) {
2051 case ArrowFunctionBodyExpression:
2053 context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
2055 case ArrowFunctionBodyBlock:
2056 case StandardFunctionBodyBlock:
2057 context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
2061 functionInfo.endLine = m_lastTokenEndPosition.line;
2065 m_parserState.lastFunctionName = lastFunctionName;
2066 ParserState oldState = internalSaveParserState();
2068 auto performParsingFunctionBody = [&] {
2069 return parseFunctionBody(context, startLocation, startColumn, functionKeywordStart, functionNameStart, parametersStart, constructorKind, expectedSuperBinding, functionBodyType, functionInfo.parameterCount, mode);
2072 if (mode == SourceParseMode::GeneratorWrapperFunctionMode) {
2073 AutoPopScopeRef generatorBodyScope(this, pushScope());
2074 generatorBodyScope->setSourceParseMode(SourceParseMode::GeneratorBodyMode);
2075 functionInfo.body = performParsingFunctionBody();
2077 // When a generator has a "use strict" directive, a generator function wrapping it should be strict mode.
2078 if (generatorBodyScope->strictMode())
2079 functionScope->setStrictMode();
2081 semanticFailIfTrue(generatorBodyScope->hasDirectSuper(), "Cannot call super() outside of a class constructor");
2082 if (generatorBodyScope->needsSuperBinding())
2083 semanticFailIfTrue(expectedSuperBinding == SuperBinding::NotNeeded, "super can only be used in a method of a derived class");
2085 popScope(generatorBodyScope, TreeBuilder::NeedsFreeVariableInfo);
2087 functionInfo.body = performParsingFunctionBody();
2089 restoreParserState(oldState);
2090 failIfFalse(functionInfo.body, "Cannot parse the body of this ", stringForFunctionMode(mode));
2091 context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
2092 if (functionScope->strictMode() && functionInfo.name) {
2093 RELEASE_ASSERT(mode == SourceParseMode::NormalFunctionMode || mode == SourceParseMode::MethodMode || mode == SourceParseMode::ArrowFunctionMode || mode == SourceParseMode::GeneratorBodyMode || mode == SourceParseMode::GeneratorWrapperFunctionMode);
2094 semanticFailIfTrue(m_vm->propertyNames->arguments == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
2095 semanticFailIfTrue(m_vm->propertyNames->eval == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
2097 // It unncecessary to check of using super during reparsing one more time. Also it can lead to syntax error
2098 // in case of arrow function becuase during reparsing we don't know that parse arrow function
2099 // inside of the constructor or method
2100 if (!m_lexer->isReparsingFunction()) {
2101 if (functionScope->hasDirectSuper()) {
2102 ScopeRef scopeRef = closestParentOrdinaryFunctionNonLexicalScope();
2103 ConstructorKind functionConstructorKind = functionBodyType == StandardFunctionBodyBlock && !scopeRef->isEvalContext()
2105 : scopeRef->constructorKind();
2106 semanticFailIfTrue(functionConstructorKind == ConstructorKind::None, "Cannot call super() outside of a class constructor");
2107 semanticFailIfTrue(functionConstructorKind != ConstructorKind::Derived, "Cannot call super() in a base class constructor");
2109 if (functionScope->needsSuperBinding()) {
2110 ScopeRef scopeRef = closestParentOrdinaryFunctionNonLexicalScope();
2111 SuperBinding functionSuperBinding = functionBodyType == StandardFunctionBodyBlock && !scopeRef->isEvalContext()
2112 ? expectedSuperBinding
2113 : scopeRef->expectedSuperBinding();
2114 semanticFailIfTrue(functionSuperBinding == SuperBinding::NotNeeded, "super can only be used in a method of a derived class");
2118 JSTokenLocation location = JSTokenLocation(m_token.m_location);
2119 functionInfo.endOffset = m_token.m_data.offset;
2121 if (functionBodyType == ArrowFunctionBodyExpression) {
2122 location = locationBeforeLastToken();
2123 functionInfo.endOffset = location.endOffset;
2126 // Cache the tokenizer state and the function scope the first time the function is parsed.
2127 // Any future reparsing can then skip the function.
2128 // For arrow function is 8 = x=>x + 4 symbols;
2129 // For ordinary function is 16 = function(){} + 4 symbols
2130 const int minimumFunctionLengthToCache = functionBodyType == StandardFunctionBodyBlock ? 16 : 8;
2131 std::unique_ptr<SourceProviderCacheItem> newInfo;
2132 int functionLength = functionInfo.endOffset - functionInfo.startOffset;
2133 if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) {
2134 SourceProviderCacheItemCreationParameters parameters;
2135 parameters.endFunctionOffset = functionInfo.endOffset;
2136 parameters.functionNameStart = functionNameStart;
2137 parameters.lastTockenLine = location.line;
2138 parameters.lastTockenStartOffset = location.startOffset;
2139 parameters.lastTockenEndOffset = location.endOffset;
2140 parameters.lastTockenLineStartOffset = location.lineStartOffset;
2141 parameters.parameterCount = functionInfo.parameterCount;
2142 if (functionBodyType == ArrowFunctionBodyExpression) {
2143 parameters.isBodyArrowExpression = true;
2144 parameters.tokenType = m_token.m_type;
2146 functionScope->fillParametersForSourceProviderCache(parameters);
2147 newInfo = SourceProviderCacheItem::create(parameters);
2150 popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo);
2152 if (functionBodyType != ArrowFunctionBodyExpression) {
2153 matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body");
2158 m_functionCache->add(functionInfo.startOffset, WTFMove(newInfo));
2160 functionInfo.endLine = m_lastTokenEndPosition.line;
2164 static NO_RETURN_DUE_TO_CRASH FunctionMetadataNode* getMetadata(ParserFunctionInfo<SyntaxChecker>&) { RELEASE_ASSERT_NOT_REACHED(); }
2165 static FunctionMetadataNode* getMetadata(ParserFunctionInfo<ASTBuilder>& info) { return info.body; }
2167 template <typename LexerType>
2168 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context, ExportType exportType)
2170 ASSERT(match(FUNCTION));
2171 JSTokenLocation location(tokenLocation());
2172 unsigned functionKeywordStart = tokenStart();
2174 ParserFunctionInfo<TreeBuilder> functionInfo;
2175 SourceParseMode parseMode = SourceParseMode::NormalFunctionMode;
2176 #if ENABLE(ES6_GENERATORS)
2178 parseMode = SourceParseMode::GeneratorWrapperFunctionMode;
2180 failIfFalse((parseFunctionInfo(context, FunctionNeedsName, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration)), "Cannot parse this function");
2181 failIfFalse(functionInfo.name, "Function statements must have a name");
2183 std::pair<DeclarationResultMask, ScopeRef> functionDeclaration = declareFunction(functionInfo.name);
2184 DeclarationResultMask declarationResult = functionDeclaration.first;
2185 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a function named '", functionInfo.name->impl(), "' in strict mode");
2186 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
2187 internalFailWithMessage(false, "Cannot declare a function that shadows a let/const/class/function variable '", functionInfo.name->impl(), "' in strict mode");
2188 if (exportType == ExportType::Exported) {
2189 semanticFailIfFalse(exportName(*functionInfo.name), "Cannot export a duplicate function name: '", functionInfo.name->impl(), "'");
2190 currentScope()->moduleScopeData().exportBinding(*functionInfo.name);
2193 TreeStatement result = context.createFuncDeclStatement(location, functionInfo);
2194 if (TreeBuilder::CreatesAST)
2195 functionDeclaration.second->appendFunction(getMetadata(functionInfo));
2199 template <typename LexerType>
2200 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseClassDeclaration(TreeBuilder& context, ExportType exportType)
2202 ASSERT(match(CLASSTOKEN));
2203 JSTokenLocation location(tokenLocation());
2204 JSTextPosition classStart = tokenStartPosition();
2205 unsigned classStartLine = tokenLine();
2207 ParserClassInfo<TreeBuilder> info;
2208 TreeClassExpression classExpr = parseClass(context, FunctionNeedsName, info);
2209 failIfFalse(classExpr, "Failed to parse class");
2211 DeclarationResultMask declarationResult = declareVariable(info.className, DeclarationType::LetDeclaration);
2212 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
2213 internalFailWithMessage(false, "Cannot declare a class twice: '", info.className->impl(), "'");
2214 if (exportType == ExportType::Exported) {
2215 semanticFailIfFalse(exportName(*info.className), "Cannot export a duplicate class name: '", info.className->impl(), "'");
2216 currentScope()->moduleScopeData().exportBinding(*info.className);
2219 JSTextPosition classEnd = lastTokenEndPosition();
2220 unsigned classEndLine = tokenLine();
2222 return context.createClassDeclStatement(location, classExpr, classStart, classEnd, classStartLine, classEndLine);
2225 template <typename LexerType>
2226 template <class TreeBuilder> TreeClassExpression Parser<LexerType>::parseClass(TreeBuilder& context, FunctionRequirements requirements, ParserClassInfo<TreeBuilder>& info)
2228 ASSERT(match(CLASSTOKEN));
2229 JSTokenLocation location(tokenLocation());
2230 info.startLine = location.line;
2231 info.startColumn = tokenColumn();
2232 info.startOffset = location.startOffset;
2235 AutoPopScopeRef classScope(this, pushScope());
2236 classScope->setIsLexicalScope();
2237 classScope->preventVarDeclarations();
2238 classScope->setStrictMode();
2240 const Identifier* className = nullptr;
2242 className = m_token.m_data.ident;
2244 failIfTrue(classScope->declareLexicalVariable(className, true) & DeclarationResult::InvalidStrictMode, "'", className->impl(), "' is not a valid class name");
2245 } else if (requirements == FunctionNeedsName) {
2246 if (match(OPENBRACE))
2247 semanticFail("Class statements must have a name");
2248 semanticFailureDueToKeyword("class name");
2249 failDueToUnexpectedToken();
2251 className = &m_vm->propertyNames->nullIdentifier;
2253 info.className = className;
2255 TreeExpression parentClass = 0;
2256 if (consume(EXTENDS)) {
2257 parentClass = parseMemberExpression(context);
2258 failIfFalse(parentClass, "Cannot parse the parent class name");
2260 const ConstructorKind constructorKind = parentClass ? ConstructorKind::Derived : ConstructorKind::Base;
2262 consumeOrFail(OPENBRACE, "Expected opening '{' at the start of a class body");
2264 TreeExpression constructor = 0;
2265 TreePropertyList staticMethods = 0;
2266 TreePropertyList instanceMethods = 0;
2267 TreePropertyList instanceMethodsTail = 0;
2268 TreePropertyList staticMethodsTail = 0;
2269 while (!match(CLOSEBRACE)) {
2270 if (match(SEMICOLON)) {
2275 JSTokenLocation methodLocation(tokenLocation());
2276 unsigned methodStart = tokenStart();
2278 // For backwards compatibility, "static" is a non-reserved keyword in non-strict mode.
2279 bool isStaticMethod = false;
2280 if (match(RESERVED_IF_STRICT) && *m_token.m_data.ident == m_vm->propertyNames->staticKeyword) {
2281 SavePoint savePoint = createSavePoint();
2283 if (match(OPENPAREN)) {
2284 // Reparse "static()" as a method named "static".
2285 restoreSavePoint(savePoint);
2287 isStaticMethod = true;
2290 // FIXME: Figure out a way to share more code with parseProperty.
2291 const CommonIdentifiers& propertyNames = *m_vm->propertyNames;
2292 const Identifier* ident = &propertyNames.nullIdentifier;
2293 TreeExpression computedPropertyName = 0;
2294 bool isGetter = false;
2295 bool isSetter = false;
2296 bool isGenerator = false;
2297 #if ENABLE(ES6_GENERATORS)
2301 switch (m_token.m_type) {
2304 ident = m_token.m_data.ident;
2309 ident = m_token.m_data.ident;
2312 if (!isGenerator && (matchIdentifierOrKeyword() || match(STRING) || match(DOUBLE) || match(INTEGER) || match(OPENBRACKET))) {
2313 isGetter = *ident == propertyNames.get;
2314 isSetter = *ident == propertyNames.set;
2319 ident = &m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), m_token.m_data.doubleValue);
2325 computedPropertyName = parseAssignmentExpression(context);
2326 failIfFalse(computedPropertyName, "Cannot parse computed property name");
2327 handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name");
2330 if (m_token.m_type & KeywordTokenFlag)
2332 failDueToUnexpectedToken();
2335 TreeProperty property;
2336 const bool alwaysStrictInsideClass = true;
2337 if (isGetter || isSetter) {
2338 property = parseGetterSetter(context, alwaysStrictInsideClass, isGetter ? PropertyNode::Getter : PropertyNode::Setter, methodStart,
2339 ConstructorKind::None, SuperBinding::Needed);
2340 failIfFalse(property, "Cannot parse this method");
2342 ParserFunctionInfo<TreeBuilder> methodInfo;
2343 bool isConstructor = !isStaticMethod && *ident == propertyNames.constructor;
2344 SourceParseMode parseMode = SourceParseMode::MethodMode;
2346 isConstructor = false;
2347 parseMode = SourceParseMode::GeneratorWrapperFunctionMode;
2348 semanticFailIfTrue(*ident == m_vm->propertyNames->prototype, "Cannot declare a generator named 'prototype'");
2349 semanticFailIfTrue(*ident == m_vm->propertyNames->constructor, "Cannot declare a generator named 'constructor'");
2351 failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, parseMode, false, isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, FunctionDefinitionType::Method)), "Cannot parse this method");
2352 methodInfo.name = isConstructor ? className : ident;
2354 TreeExpression method = context.createMethodDefinition(methodLocation, methodInfo);
2355 if (isConstructor) {
2356 semanticFailIfTrue(constructor, "Cannot declare multiple constructors in a single class");
2357 constructor = method;
2361 // FIXME: Syntax error when super() is called
2362 semanticFailIfTrue(isStaticMethod && methodInfo.name && *methodInfo.name == propertyNames.prototype,
2363 "Cannot declare a static method named 'prototype'");
2364 if (computedPropertyName) {
2365 property = context.createProperty(computedPropertyName, method, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed),
2366 PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed);
2368 property = context.createProperty(methodInfo.name, method, PropertyNode::Constant, PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed);
2371 TreePropertyList& tail = isStaticMethod ? staticMethodsTail : instanceMethodsTail;
2373 tail = context.createPropertyList(methodLocation, property, tail);
2375 tail = context.createPropertyList(methodLocation, property);
2377 staticMethods = tail;
2379 instanceMethods = tail;
2383 info.endOffset = tokenLocation().endOffset - 1;
2384 consumeOrFail(CLOSEBRACE, "Expected a closing '}' after a class body");
2386 auto classExpression = context.createClassExpr(location, info, classScope->finalizeLexicalEnvironment(), constructor, parentClass, instanceMethods, staticMethods);
2387 popScope(classScope, TreeBuilder::NeedsFreeVariableInfo);
2388 return classExpression;
2392 LabelInfo(const Identifier* ident, const JSTextPosition& start, const JSTextPosition& end)
2399 const Identifier* m_ident;
2400 JSTextPosition m_start;
2401 JSTextPosition m_end;
2404 template <typename LexerType>
2405 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrLabelStatement(TreeBuilder& context, bool allowFunctionDeclarationAsStatement)
2408 /* Expression and Label statements are ambiguous at LL(1), so we have a
2409 * special case that looks for a colon as the next character in the input.
2411 Vector<LabelInfo> labels;
2412 JSTokenLocation location;
2414 JSTextPosition start = tokenStartPosition();
2415 location = tokenLocation();
2416 if (!nextTokenIsColon()) {
2417 // If we hit this path we're making a expression statement, which
2418 // by definition can't make use of continue/break so we can just
2419 // ignore any labels we might have accumulated.
2420 TreeExpression expression = parseExpression(context);
2421 failIfFalse(expression, "Cannot parse expression statement");
2422 if (!autoSemiColon())
2423 failDueToUnexpectedToken();
2424 return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
2426 const Identifier* ident = m_token.m_data.ident;
2427 JSTextPosition end = tokenEndPosition();
2429 consumeOrFail(COLON, "Labels must be followed by a ':'");
2430 if (!m_syntaxAlreadyValidated) {
2431 // This is O(N^2) over the current list of consecutive labels, but I
2432 // have never seen more than one label in a row in the real world.
2433 for (size_t i = 0; i < labels.size(); i++)
2434 failIfTrue(ident->impl() == labels[i].m_ident->impl(), "Attempted to redeclare the label '", ident->impl(), "'");
2435 failIfTrue(getLabel(ident), "Cannot find scope for the label '", ident->impl(), "'");
2436 labels.append(LabelInfo(ident, start, end));
2438 } while (matchSpecIdentifier());
2439 bool isLoop = false;
2440 switch (m_token.m_type) {
2450 const Identifier* unused = 0;
2451 ScopeRef labelScope = currentScope();
2452 if (!m_syntaxAlreadyValidated) {
2453 for (size_t i = 0; i < labels.size(); i++)
2454 pushLabel(labels[i].m_ident, isLoop);
2456 m_immediateParentAllowsFunctionDeclarationInStatement = allowFunctionDeclarationAsStatement;
2457 TreeStatement statement = parseStatement(context, unused);
2458 if (!m_syntaxAlreadyValidated) {
2459 for (size_t i = 0; i < labels.size(); i++)
2460 popLabel(labelScope);
2462 failIfFalse(statement, "Cannot parse statement");
2463 for (size_t i = 0; i < labels.size(); i++) {
2464 const LabelInfo& info = labels[labels.size() - i - 1];
2465 statement = context.createLabelStatement(location, info.m_ident, statement, info.m_start, info.m_end);
2470 template <typename LexerType>
2471 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionStatement(TreeBuilder& context)
2473 switch (m_token.m_type) {
2474 // Consult: http://www.ecma-international.org/ecma-262/6.0/index.html#sec-expression-statement
2475 // The ES6 spec mandates that we should fail from FUNCTION token here. We handle this case
2476 // in parseStatement() which is the only caller of parseExpressionStatement().
2477 // We actually allow FUNCTION in situations where it should not be allowed unless we're in strict mode.
2479 failWithMessage("'class' declaration is not directly within a block statement");
2482 // FIXME: when implementing 'let' we should fail when we see the token sequence "let [".
2483 // https://bugs.webkit.org/show_bug.cgi?id=142944
2486 JSTextPosition start = tokenStartPosition();
2487 JSTokenLocation location(tokenLocation());
2488 TreeExpression expression = parseExpression(context);
2489 failIfFalse(expression, "Cannot parse expression statement");
2490 failIfFalse(autoSemiColon(), "Parse error");
2491 return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
2494 template <typename LexerType>
2495 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(TreeBuilder& context)
2498 JSTokenLocation ifLocation(tokenLocation());
2499 int start = tokenLine();
2501 handleProductionOrFail(OPENPAREN, "(", "start", "'if' condition");
2503 TreeExpression condition = parseExpression(context);
2504 failIfFalse(condition, "Expected a expression as the condition for an if statement");
2505 int end = tokenLine();
2506 handleProductionOrFail(CLOSEPAREN, ")", "end", "'if' condition");
2508 const Identifier* unused = 0;
2509 m_immediateParentAllowsFunctionDeclarationInStatement = true;
2510 TreeStatement trueBlock = parseStatement(context, unused);
2511 failIfFalse(trueBlock, "Expected a statement as the body of an if block");
2514 return context.createIfStatement(ifLocation, condition, trueBlock, 0, start, end);
2516 Vector<TreeExpression> exprStack;
2517 Vector<std::pair<int, int>> posStack;
2518 Vector<JSTokenLocation> tokenLocationStack;
2519 Vector<TreeStatement> statementStack;
2520 bool trailingElse = false;
2522 JSTokenLocation tempLocation = tokenLocation();
2525 const Identifier* unused = 0;
2526 m_immediateParentAllowsFunctionDeclarationInStatement = true;
2527 TreeStatement block = parseStatement(context, unused);
2528 failIfFalse(block, "Expected a statement as the body of an else block");
2529 statementStack.append(block);
2530 trailingElse = true;
2533 int innerStart = tokenLine();
2536 handleProductionOrFail(OPENPAREN, "(", "start", "'if' condition");
2538 TreeExpression innerCondition = parseExpression(context);
2539 failIfFalse(innerCondition, "Expected a expression as the condition for an if statement");
2540 int innerEnd = tokenLine();
2541 handleProductionOrFail(CLOSEPAREN, ")", "end", "'if' condition");
2542 const Identifier* unused = 0;
2543 m_immediateParentAllowsFunctionDeclarationInStatement = true;
2544 TreeStatement innerTrueBlock = parseStatement(context, unused);
2545 failIfFalse(innerTrueBlock, "Expected a statement as the body of an if block");
2546 tokenLocationStack.append(tempLocation);
2547 exprStack.append(innerCondition);
2548 posStack.append(std::make_pair(innerStart, innerEnd));
2549 statementStack.append(innerTrueBlock);
2550 } while (match(ELSE));
2552 if (!trailingElse) {
2553 TreeExpression condition = exprStack.last();
2554 exprStack.removeLast();
2555 TreeStatement trueBlock = statementStack.last();
2556 statementStack.removeLast();
2557 std::pair<int, int> pos = posStack.last();
2558 posStack.removeLast();
2559 JSTokenLocation elseLocation = tokenLocationStack.last();
2560 tokenLocationStack.removeLast();
2561 TreeStatement ifStatement = context.createIfStatement(elseLocation, condition, trueBlock, 0, pos.first, pos.second);
2562 context.setEndOffset(ifStatement, context.endOffset(trueBlock));
2563 statementStack.append(ifStatement);
2566 while (!exprStack.isEmpty()) {
2567 TreeExpression condition = exprStack.last();
2568 exprStack.removeLast();
2569 TreeStatement falseBlock = statementStack.last();
2570 statementStack.removeLast();
2571 TreeStatement trueBlock = statementStack.last();
2572 statementStack.removeLast();
2573 std::pair<int, int> pos = posStack.last();
2574 posStack.removeLast();
2575 JSTokenLocation elseLocation = tokenLocationStack.last();
2576 tokenLocationStack.removeLast();
2577 TreeStatement ifStatement = context.createIfStatement(elseLocation, condition, trueBlock, falseBlock, pos.first, pos.second);
2578 context.setEndOffset(ifStatement, context.endOffset(falseBlock));
2579 statementStack.append(ifStatement);
2582 return context.createIfStatement(ifLocation, condition, trueBlock, statementStack.last(), start, end);
2585 template <typename LexerType>
2586 template <class TreeBuilder> typename TreeBuilder::ModuleName Parser<LexerType>::parseModuleName(TreeBuilder& context)
2588 // ModuleName (ModuleSpecifier in the spec) represents the module name imported by the script.
2589 // http://www.ecma-international.org/ecma-262/6.0/#sec-imports
2590 // http://www.ecma-international.org/ecma-262/6.0/#sec-exports
2591 JSTokenLocation specifierLocation(tokenLocation());
2592 failIfFalse(match(STRING), "Imported modules names must be string literals");
2593 const Identifier* moduleName = m_token.m_data.ident;
2595 return context.createModuleName(specifierLocation, *moduleName);
2598 template <typename LexerType>
2599 template <class TreeBuilder> typename TreeBuilder::ImportSpecifier Parser<LexerType>::parseImportClauseItem(TreeBuilder& context, ImportSpecifierType specifierType)
2601 // Produced node is the item of the ImportClause.
2602 // That is the ImportSpecifier, ImportedDefaultBinding or NameSpaceImport.
2603 // http://www.ecma-international.org/ecma-262/6.0/#sec-imports
2604 JSTokenLocation specifierLocation(tokenLocation());
2605 JSToken localNameToken;
2606 const Identifier* importedName = nullptr;
2607 const Identifier* localName = nullptr;
2609 switch (specifierType) {
2610 case ImportSpecifierType::NamespaceImport: {
2611 // NameSpaceImport :
2612 // * as ImportedBinding
2615 ASSERT(match(TIMES));
2616 importedName = &m_vm->propertyNames->timesIdentifier;
2619 failIfFalse(matchContextualKeyword(m_vm->propertyNames->as), "Expected 'as' before imported binding name");
2622 matchOrFail(IDENT, "Expected a variable name for the import declaration");
2623 localNameToken = m_token;
2624 localName = m_token.m_data.ident;
2629 case ImportSpecifierType::NamedImport: {
2630 // ImportSpecifier :
2632 // IdentifierName as ImportedBinding
2636 ASSERT(matchIdentifierOrKeyword());
2637 localNameToken = m_token;
2638 localName = m_token.m_data.ident;
2639 importedName = localName;
2642 if (matchContextualKeyword(m_vm->propertyNames->as)) {
2644 matchOrFail(IDENT, "Expected a variable name for the import declaration");
2645 localNameToken = m_token;
2646 localName = m_token.m_data.ident;
2652 case ImportSpecifierType::DefaultImport: {
2653 // ImportedDefaultBinding :
2655 ASSERT(match(IDENT));
2656 localNameToken = m_token;
2657 localName = m_token.m_data.ident;
2658 importedName = &m_vm->propertyNames->defaultKeyword;
2664 semanticFailIfTrue(localNameToken.m_type & KeywordTokenFlag, "Cannot use keyword as imported binding name");
2665 DeclarationResultMask declarationResult = declareVariable(localName, DeclarationType::ConstDeclaration, (specifierType == ImportSpecifierType::NamespaceImport) ? DeclarationImportType::ImportedNamespace : DeclarationImportType::Imported);
2666 if (declarationResult != DeclarationResult::Valid) {
2667 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare an imported binding named ", localName->impl(), " in strict mode");
2668 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
2669 internalFailWithMessage(false, "Cannot declare an imported binding name twice: '", localName->impl(), "'");
2672 return context.createImportSpecifier(specifierLocation, *importedName, *localName);
2675 template <typename LexerType>
2676 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseImportDeclaration(TreeBuilder& context)
2678 // http://www.ecma-international.org/ecma-262/6.0/#sec-imports
2679 ASSERT(match(IMPORT));
2680 JSTokenLocation importLocation(tokenLocation());
2683 auto specifierList = context.createImportSpecifierList();
2685 if (match(STRING)) {
2686 // import ModuleSpecifier ;
2687 auto moduleName = parseModuleName(context);
2688 failIfFalse(moduleName, "Cannot parse the module name");
2689 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted import declaration");
2690 return context.createImportDeclaration(importLocation, specifierList, moduleName);
2693 bool isFinishedParsingImport = false;
2695 // ImportedDefaultBinding :
2697 auto specifier = parseImportClauseItem(context, ImportSpecifierType::DefaultImport);
2698 failIfFalse(specifier, "Cannot parse the default import");
2699 context.appendImportSpecifier(specifierList, specifier);
2703 isFinishedParsingImport = true;
2706 if (!isFinishedParsingImport) {
2708 // import NameSpaceImport FromClause ;
2709 auto specifier = parseImportClauseItem(context, ImportSpecifierType::NamespaceImport);
2710 failIfFalse(specifier, "Cannot parse the namespace import");
2711 context.appendImportSpecifier(specifierList, specifier);
2712 } else if (match(OPENBRACE)) {
2716 // { ImportsList , }
2719 while (!match(CLOSEBRACE)) {
2720 failIfFalse(matchIdentifierOrKeyword(), "Expected an imported name for the import declaration");
2721 auto specifier = parseImportClauseItem(context, ImportSpecifierType::NamedImport);
2722 failIfFalse(specifier, "Cannot parse the named import");
2723 context.appendImportSpecifier(specifierList, specifier);
2724 if (!consume(COMMA))
2727 handleProductionOrFail(CLOSEBRACE, "}", "end", "import list");
2729 failWithMessage("Expected namespace import or import list");
2733 // from ModuleSpecifier
2735 failIfFalse(matchContextualKeyword(m_vm->propertyNames->from), "Expected 'from' before imported module name");
2738 auto moduleName = parseModuleName(context);
2739 failIfFalse(moduleName, "Cannot parse the module name");
2740 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted import declaration");
2742 return context.createImportDeclaration(importLocation, specifierList, moduleName);
2745 template <typename LexerType>
2746 template <class TreeBuilder> typename TreeBuilder::ExportSpecifier Parser<LexerType>::parseExportSpecifier(TreeBuilder& context, Vector<const Identifier*>& maybeLocalNames, bool& hasKeywordForLocalBindings)
2748 // ExportSpecifier :
2750 // IdentifierName as IdentifierName
2751 // http://www.ecma-international.org/ecma-262/6.0/#sec-exports
2752 ASSERT(matchIdentifierOrKeyword());
2753 JSTokenLocation specifierLocation(tokenLocation());
2754 if (m_token.m_type & KeywordTokenFlag)
2755 hasKeywordForLocalBindings = true;
2756 const Identifier* localName = m_token.m_data.ident;
2757 const Identifier* exportedName = localName;
2760 if (matchContextualKeyword(m_vm->propertyNames->as)) {
2762 failIfFalse(matchIdentifierOrKeyword(), "Expected an exported name for the export declaration");
2763 exportedName = m_token.m_data.ident;
2767 semanticFailIfFalse(exportName(*exportedName), "Cannot export a duplicate name '", exportedName->impl(), "'");
2768 maybeLocalNames.append(localName);
2769 return context.createExportSpecifier(specifierLocation, *localName, *exportedName);
2772 template <typename LexerType>
2773 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExportDeclaration(TreeBuilder& context)
2775 // http://www.ecma-international.org/ecma-262/6.0/#sec-exports
2776 ASSERT(match(EXPORT));
2777 JSTokenLocation exportLocation(tokenLocation());
2780 switch (m_token.m_type) {
2782 // export * FromClause ;
2785 failIfFalse(matchContextualKeyword(m_vm->propertyNames->from), "Expected 'from' before exported module name");
2787 auto moduleName = parseModuleName(context);
2788 failIfFalse(moduleName, "Cannot parse the 'from' clause");
2789 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted export declaration");
2791 return context.createExportAllDeclaration(exportLocation, moduleName);
2795 // export default HoistableDeclaration[Default]
2796 // export default ClassDeclaration[Default]
2797 // export default [lookahead not-in {function, class}] AssignmentExpression[In] ;
2801 TreeStatement result = 0;
2802 bool isFunctionOrClassDeclaration = false;
2803 const Identifier* localName = nullptr;
2804 SavePoint savePoint = createSavePoint();
2806 bool startsWithFunction = match(FUNCTION);
2807 if (startsWithFunction || match(CLASSTOKEN)) {
2808 isFunctionOrClassDeclaration = true;
2811 #if ENABLE(ES6_GENERATORS)
2813 if (startsWithFunction && match(TIMES))
2817 localName = m_token.m_data.ident;
2818 restoreSavePoint(savePoint);
2822 if (match(FUNCTION)) {
2823 DepthManager statementDepth(&m_statementDepth);
2824 m_statementDepth = 1;
2825 result = parseFunctionDeclaration(context);
2827 ASSERT(match(CLASSTOKEN));
2828 result = parseClassDeclaration(context);
2831 // export default expr;
2833 // It should be treated as the same to the following.
2835 // const *default* = expr;
2836 // export { *default* as default }
2838 // In the above example, *default* is the invisible variable to the users.
2839 // We use the private symbol to represent the name of this variable.
2840 JSTokenLocation location(tokenLocation());
2841 JSTextPosition start = tokenStartPosition();
2842 TreeExpression expression = parseAssignmentExpression(context);
2843 failIfFalse(expression, "Cannot parse expression");
2845 DeclarationResultMask declarationResult = declareVariable(&m_vm->propertyNames->starDefaultPrivateName, DeclarationType::ConstDeclaration);
2846 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
2847 internalFailWithMessage(false, "Only one 'default' export is allowed");
2849 TreeExpression assignment = context.createAssignResolve(location, m_vm->propertyNames->starDefaultPrivateName, expression, start, start, tokenEndPosition(), AssignmentContext::ConstDeclarationStatement);
2850 result = context.createExprStatement(location, assignment, start, tokenEndPosition());
2851 if (!isFunctionOrClassDeclaration)
2852 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted export declaration");
2853 localName = &m_vm->propertyNames->starDefaultPrivateName;
2855 failIfFalse(result, "Cannot parse the declaration");
2857 semanticFailIfFalse(exportName(m_vm->propertyNames->defaultKeyword), "Only one 'default' export is allowed");
2858 currentScope()->moduleScopeData().exportBinding(*localName);
2859 return context.createExportDefaultDeclaration(exportLocation, result, *localName);
2863 // export ExportClause FromClause ;
2864 // export ExportClause ;
2869 // { ExportsList , }
2873 // ExportsList , ExportSpecifier
2877 auto specifierList = context.createExportSpecifierList();
2878 Vector<const Identifier*> maybeLocalNames;
2880 bool hasKeywordForLocalBindings = false;
2881 while (!match(CLOSEBRACE)) {
2882 failIfFalse(matchIdentifierOrKeyword(), "Expected a variable name for the export declaration");
2883 auto specifier = parseExportSpecifier(context, maybeLocalNames, hasKeywordForLocalBindings);
2884 failIfFalse(specifier, "Cannot parse the named export");
2885 context.appendExportSpecifier(specifierList, specifier);
2886 if (!consume(COMMA))
2889 handleProductionOrFail(CLOSEBRACE, "}", "end", "export list");
2891 typename TreeBuilder::ModuleName moduleName = 0;
2892 if (matchContextualKeyword(m_vm->propertyNames->from)) {
2894 moduleName = parseModuleName(context);
2895 failIfFalse(moduleName, "Cannot parse the 'from' clause");
2897 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted export declaration");
2900 semanticFailIfTrue(hasKeywordForLocalBindings, "Cannot use keyword as exported variable name");
2901 // Since this export declaration does not have module specifier part, it exports the local bindings.
2902 // While the export declaration with module specifier does not have any effect on the current module's scope,
2903 // the export named declaration without module specifier references the the local binding names.
2905 // export { A, B, C as D } from "mod"
2906 // does not have effect on the current module's scope. But,
2907 // export { A, B, C as D }
2908 // will reference the current module's bindings.
2909 for (const Identifier* localName : maybeLocalNames)
2910 currentScope()->moduleScopeData().exportBinding(*localName);
2913 return context.createExportNamedDeclaration(exportLocation, specifierList, moduleName);
2917 // export VariableStatement
2918 // export Declaration
2919 TreeStatement result = 0;
2920 switch (m_token.m_type) {
2922 result = parseVariableDeclaration(context, DeclarationType::VarDeclaration, ExportType::Exported);
2926 result = parseVariableDeclaration(context, DeclarationType::ConstDeclaration, ExportType::Exported);
2930 result = parseVariableDeclaration(context, DeclarationType::LetDeclaration, ExportType::Exported);
2934 DepthManager statementDepth(&m_statementDepth);
2935 m_statementDepth = 1;
2936 result = parseFunctionDeclaration(context, ExportType::Exported);
2941 result = parseClassDeclaration(context, ExportType::Exported);
2945 failWithMessage("Expected either a declaration or a variable statement");
2948 failIfFalse(result, "Cannot parse the declaration");
2949 return context.createExportLocalDeclaration(exportLocation, result);
2953 RELEASE_ASSERT_NOT_REACHED();
2957 template <typename LexerType>
2958 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseExpression(TreeBuilder& context)
2960 failIfStackOverflow();
2961 JSTokenLocation location(tokenLocation());
2962 TreeExpression node = parseAssignmentExpression(context);
2963 failIfFalse(node, "Cannot parse expression");
2964 context.setEndOffset(node, m_lastTokenEndPosition.offset);
2968 m_parserState.nonTrivialExpressionCount++;
2969 m_parserState.nonLHSCount++;
2970 TreeExpression right = parseAssignmentExpression(context);
2971 failIfFalse(right, "Cannot parse expression in a comma expression");
2972 context.setEndOffset(right, m_lastTokenEndPosition.offset);
2973 typename TreeBuilder::Comma head = context.createCommaExpr(location, node);
2974 typename TreeBuilder::Comma tail = context.appendToCommaExpr(location, head, head, right);
2975 while (match(COMMA)) {
2976 next(TreeBuilder::DontBuildStrings);
2977 right = parseAssignmentExpression(context);
2978 failIfFalse(right, "Cannot parse expression in a comma expression");
2979 context.setEndOffset(right, m_lastTokenEndPosition.offset);
2980 tail = context.appendToCommaExpr(location, head, tail, right);
2982 context.setEndOffset(head, m_lastTokenEndPosition.offset);
2986 template <typename LexerType>
2987 template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpressionOrPropagateErrorClass(TreeBuilder& context)
2989 ExpressionErrorClassifier classifier(this);
2990 auto assignment = parseAssignmentExpression(context, classifier);
2992 classifier.propagateExpressionErrorClass();
2996 template <typename LexerType>
2997 template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context)
2999 ExpressionErrorClassifier classifier(this);
3000 return parseAssignmentExpression(context, classifier);
3003 template <typename LexerType>
3004 template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context, ExpressionErrorClassifier& classifier)
3006 ASSERT(!hasError());
3008 failIfStackOverflow();
3009 JSTextPosition start = tokenStartPosition();
3010 JSTokenLocation location(tokenLocation());
3011 int initialAssignmentCount = m_parserState.assignmentCount;
3012 int initialNonLHSCount = m_parserState.nonLHSCount;
3013 bool maybeAssignmentPattern = match(OPENBRACE) || match(OPENBRACKET);
3014 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
3015 bool wasOpenParen = match(OPENPAREN);
3016 bool isValidArrowFunctionStart = match(OPENPAREN) || match(IDENT);
3017 SavePoint savePoint = createSavePoint();
3018 size_t usedVariablesSize;
3020 usedVariablesSize = currentScope()->currentUsedVariablesSize();
3021 currentScope()->pushUsedVariableSet();
3025 #if ENABLE(ES6_GENERATORS)
3026 if (match(YIELD) && !isYIELDMaskedAsIDENT(currentScope()->isGenerator()))
3027 return parseYieldExpression(context);
3030 TreeExpression lhs = parseConditionalExpression(context);
3032 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
3033 if (isValidArrowFunctionStart && !match(EOFTOK)) {
3034 bool isArrowFunctionToken = match(ARROWFUNCTION);
3035 if (!lhs || isArrowFunctionToken) {
3036 SavePoint errorRestorationSavePoint = createSavePointForError();
3037 String oldErrorMessage = m_errorMessage;
3038 String oldLexerErrorMessage = m_lexer->getErrorMessage();
3039 bool hasLexerError = m_lexer->sawError();
3040 restoreSavePoint(savePoint);
3041 if (isArrowFunctionParameters()) {
3043 currentScope()->revertToPreviousUsedVariables(usedVariablesSize);
3044 return parseArrowFunctionExpression(context);
3046 restoreSavePointWithError(errorRestorationSavePoint, oldErrorMessage);
3047 m_lexer->setErrorMessage(oldLexerErrorMessage);
3048 m_lexer->setSawError(hasLexerError);
3049 if (isArrowFunctionToken)
3050 failDueToUnexpectedToken();
3056 if (!lhs && (!maybeAssignmentPattern || !classifier.indicatesPossiblePattern()))
3059 if (maybeAssignmentPattern && (!lhs || (context.isObjectOrArrayLiteral(lhs) && match(EQUAL)))) {
3060 String expressionError = m_errorMessage;
3061 String oldLexerErrorMessage = m_lexer->getErrorMessage();
3062 bool hasLexerError = m_lexer->sawError();
3063 SavePoint expressionErrorLocation = createSavePointForError();
3064 restoreSavePoint(savePoint);
3065 auto pattern = tryParseDestructuringPatternExpression(context, AssignmentContext::AssignmentExpression);
3066 if (classifier.indicatesPossiblePattern() && (!pattern || !match(EQUAL))) {
3067 restoreSavePointWithError(expressionErrorLocation, expressionError);
3068 m_lexer->setErrorMessage(oldLexerErrorMessage);
3069 m_lexer->setSawError(hasLexerError);
3072 failIfFalse(pattern, "Cannot parse assignment pattern");
3073 consumeOrFail(EQUAL, "Expected '=' following assignment pattern");
3074 auto rhs = parseAssignmentExpression(context);
3077 return context.createDestructuringAssignment(location, pattern, rhs);
3080 failIfFalse(lhs, "Cannot parse expression");
3081 if (initialNonLHSCount != m_parserState.nonLHSCount) {
3082 if (m_token.m_type >= EQUAL && m_token.m_type <= OREQUAL)
3083 semanticFail("Left hand side of operator '", getToken(), "' must be a reference");
3088 int assignmentStack = 0;
3090 bool hadAssignment = false;
3092 switch (m_token.m_type) {
3093 case EQUAL: op = OpEqual; break;
3094 case PLUSEQUAL: op = OpPlusEq; break;
3095 case MINUSEQUAL: op = OpMinusEq; break;
3096 case MULTEQUAL: op = OpMultEq; break;
3097 case DIVEQUAL: op = OpDivEq; break;
3098 case LSHIFTEQUAL: op = OpLShift; break;
3099 case RSHIFTEQUAL: op = OpRShift; break;
3100 case URSHIFTEQUAL: op = OpURShift; break;
3101 case ANDEQUAL: op = OpAndEq; break;
3102 case XOREQUAL: op = OpXOrEq; break;
3103 case OREQUAL: op = OpOrEq; break;
3104 case MODEQUAL: op = OpModEq; break;
3108 m_parserState.nonTrivialExpressionCount++;
3109 hadAssignment = true;
3110 if (UNLIKELY(context.isNewTarget(lhs)))
3111 internalFailWithMessage(false, "new.target can't be the left hand side of an assignment expression");
3112 context.assignmentStackAppend(assignmentStack, lhs, start, tokenStartPosition(), m_parserState.assignmentCount, op);
3113 start = tokenStartPosition();
3114 m_parserState.assignmentCount++;
3115 next(TreeBuilder::DontBuildStrings);
3116 if (strictMode() && m_parserState.lastIdentifier && context.isResolve(lhs)) {
3117 failIfTrueIfStrict(m_vm->propertyNames->eval == *m_parserState.lastIdentifier, "Cannot modify 'eval' in strict mode");
3118 failIfTrueIfStrict(m_vm->propertyNames->arguments == *m_parserState.lastIdentifier, "Cannot modify 'arguments' in strict mode");
3119 m_parserState.lastIdentifier = 0;
3121 lhs = parseAssignmentExpression(context);
3122 failIfFalse(lhs, "Cannot parse the right hand side of an assignment expression");
3123 if (initialNonLHSCount != m_parserState.nonLHSCount) {
3124 if (m_token.m_type >= EQUAL && m_token.m_type <= OREQUAL)
3125 semanticFail("Left hand side of operator '", getToken(), "' must be a reference");
3131 m_parserState.nonLHSCount++;
3133 if (!TreeBuilder::CreatesAST)
3136 while (assignmentStack)
3137 lhs = context.createAssignment(location, assignmentStack, lhs, initialAssignmentCount, m_parserState.assignmentCount, lastTokenEndPosition());
3142 template <typename LexerType>
3143 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseYieldExpression(TreeBuilder& context)
3145 // YieldExpression[In] :
3147 // yield [no LineTerminator here] AssignmentExpression[?In, Yield]
3148 // yield [no LineTerminator here] * AssignmentExpression[?In, Yield]
3150 // http://ecma-international.org/ecma-262/6.0/#sec-generator-function-definitions
3151 failIfFalse(currentScope()->isGenerator(), "Cannot use yield expression out of generator");
3153 // http://ecma-international.org/ecma-262/6.0/#sec-generator-function-definitions-static-semantics-early-errors
3154 failIfTrue(m_parserState.functionParsePhase == FunctionParsePhase::Parameters, "Cannot use yield expression within parameters");
3156 JSTokenLocation location(tokenLocation());
3157 JSTextPosition divotStart = tokenStartPosition();
3158 ASSERT(match(YIELD));
3159 SavePoint savePoint = createSavePoint();
3161 if (m_lexer->prevTerminator())
3162 return context.createYield(location);
3164 bool delegate = consume(TIMES);
3165 JSTextPosition argumentStart = tokenStartPosition();
3166 TreeExpression argument = parseAssignmentExpression(context);
3168 restoreSavePoint(savePoint);
3170 return context.createYield(location);
3172 return context.createYield(location, argument, delegate, divotStart, argumentStart, lastTokenEndPosition());
3175 template <typename LexerType>
3176 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseConditionalExpression(TreeBuilder& context)
3178 JSTokenLocation location(tokenLocation());
3179 TreeExpression cond = parseBinaryExpression(context);
3180 failIfFalse(cond, "Cannot parse expression");
3181 if (!match(QUESTION))
3183 m_parserState.nonTrivialExpressionCount++;
3184 m_parserState.nonLHSCount++;
3185 next(TreeBuilder::DontBuildStrings);
3186 TreeExpression lhs = parseAssignmentExpression(context);
3187 failIfFalse(lhs, "Cannot parse left hand side of ternary operator");
3188 context.setEndOffset(lhs, m_lastTokenEndPosition.offset);
3189 consumeOrFailWithFlags(COLON, TreeBuilder::DontBuildStrings, "Expected ':' in ternary operator");
3191 TreeExpression rhs = parseAssignmentExpression(context);
3192 failIfFalse(rhs, "Cannot parse right hand side of ternary operator");
3193 context.setEndOffset(rhs, m_lastTokenEndPosition.offset);
3194 return context.createConditionalExpr(location, cond, lhs, rhs);
3197 ALWAYS_INLINE static bool isUnaryOp(JSTokenType token)
3199 return token & UnaryOpTokenFlag;
3202 template <typename LexerType>
3203 int Parser<LexerType>::isBinaryOperator(JSTokenType token)
3206 return token & (BinaryOpTokenPrecedenceMask << BinaryOpTokenAllowsInPrecedenceAdditionalShift);
3207 return token & BinaryOpTokenPrecedenceMask;
3210 template <typename LexerType>
3211 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseBinaryExpression(TreeBuilder& context)
3213 int operandStackDepth = 0;
3214 int operatorStackDepth = 0;
3215 typename TreeBuilder::BinaryExprContext binaryExprContext(context);
3216 JSTokenLocation location(tokenLocation());
3218 JSTextPosition exprStart = tokenStartPosition();
3219 int initialAssignments = m_parserState.assignmentCount;
3220 TreeExpression current = parseUnaryExpression(context);
3221 failIfFalse(current, "Cannot parse expression");
3223 context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEndPosition(), lastTokenEndPosition(), initialAssignments != m_parserState.assignmentCount);