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 "DebuggerParseData.h"
28 #include "JSCInlines.h"
31 #include <wtf/SetForScope.h>
32 #include <wtf/StringPrintStream.h>
34 #define updateErrorMessage(shouldPrintToken, ...) do {\
36 logError(shouldPrintToken, __VA_ARGS__); \
39 #define propagateError() do { if (UNLIKELY(hasError())) return 0; } while (0)
40 #define internalFailWithMessage(shouldPrintToken, ...) do { updateErrorMessage(shouldPrintToken, __VA_ARGS__); return 0; } while (0)
41 #define handleErrorToken() do { if (m_token.m_type == EOFTOK || m_token.m_type & ErrorTokenFlag) { failDueToUnexpectedToken(); } } while (0)
42 #define failWithMessage(...) do { { handleErrorToken(); updateErrorMessage(true, __VA_ARGS__); } return 0; } while (0)
43 #define failWithStackOverflow() do { updateErrorMessage(false, "Stack exhausted"); m_hasStackOverflow = true; return 0; } while (0)
44 #define failIfFalse(cond, ...) do { if (!(cond)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
45 #define failIfTrue(cond, ...) do { if (cond) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
46 #define failIfTrueIfStrict(cond, ...) do { if ((cond) && strictMode()) internalFailWithMessage(false, __VA_ARGS__); } while (0)
47 #define failIfFalseIfStrict(cond, ...) do { if ((!(cond)) && strictMode()) internalFailWithMessage(false, __VA_ARGS__); } while (0)
48 #define consumeOrFail(tokenType, ...) do { if (!consume(tokenType)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
49 #define consumeOrFailWithFlags(tokenType, flags, ...) do { if (!consume(tokenType, flags)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
50 #define matchOrFail(tokenType, ...) do { if (!match(tokenType)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
51 #define failIfStackOverflow() do { if (UNLIKELY(!canRecurse())) failWithStackOverflow(); } while (0)
52 #define semanticFail(...) do { internalFailWithMessage(false, __VA_ARGS__); } while (0)
53 #define semanticFailIfTrue(cond, ...) do { if (UNLIKELY(cond)) internalFailWithMessage(false, __VA_ARGS__); } while (0)
54 #define semanticFailIfFalse(cond, ...) do { if (UNLIKELY(!(cond))) internalFailWithMessage(false, __VA_ARGS__); } while (0)
55 #define regexFail(failure) do { setErrorMessage(failure); return 0; } while (0)
56 #define failDueToUnexpectedToken() do {\
61 #define handleProductionOrFail(token, tokenString, operation, production) do {\
62 consumeOrFail(token, "Expected '", tokenString, "' to ", operation, " a ", production);\
65 #define handleProductionOrFail2(token, tokenString, operation, production) do {\
66 consumeOrFail(token, "Expected '", tokenString, "' to ", operation, " an ", production);\
69 #define semanticFailureDueToKeywordCheckingToken(token, ...) do { \
70 if (strictMode() && token.m_type == RESERVED_IF_STRICT) \
71 semanticFail("Cannot use the reserved word '", getToken(token), "' as a ", __VA_ARGS__, " in strict mode"); \
72 if (token.m_type == RESERVED || token.m_type == RESERVED_IF_STRICT) \
73 semanticFail("Cannot use the reserved word '", getToken(token), "' as a ", __VA_ARGS__); \
74 if (token.m_type & KeywordTokenFlag) { \
75 if (!isAnyContextualKeyword(token)) \
76 semanticFail("Cannot use the keyword '", getToken(token), "' as a ", __VA_ARGS__); \
77 if (isDisallowedIdentifierLet(token)) \
78 semanticFail("Cannot use 'let' as a ", __VA_ARGS__, " ", disallowedIdentifierLetReason()); \
79 if (isDisallowedIdentifierAwait(token)) \
80 semanticFail("Cannot use 'await' as a ", __VA_ARGS__, " ", disallowedIdentifierAwaitReason()); \
81 if (isDisallowedIdentifierYield(token)) \
82 semanticFail("Cannot use 'yield' as a ", __VA_ARGS__, " ", disallowedIdentifierYieldReason()); \
86 #define semanticFailureDueToKeyword(...) semanticFailureDueToKeywordCheckingToken(m_token, __VA_ARGS__);
92 template <typename LexerType>
93 void Parser<LexerType>::logError(bool)
97 StringPrintStream stream;
98 printUnexpectedTokenText(stream);
99 setErrorMessage(stream.toStringWithLatin1Fallback());
102 template <typename LexerType> template <typename... Args>
103 void Parser<LexerType>::logError(bool shouldPrintToken, Args&&... args)
107 StringPrintStream stream;
108 if (shouldPrintToken) {
109 printUnexpectedTokenText(stream);
112 stream.print(std::forward<Args>(args)..., ".");
113 setErrorMessage(stream.toStringWithLatin1Fallback());
116 template <typename LexerType>
117 Parser<LexerType>::Parser(VM* vm, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, SourceParseMode parseMode, SuperBinding superBinding, ConstructorKind defaultConstructorKind, DerivedContextType derivedContextType, bool isEvalContext, EvalContextType evalContextType, DebuggerParseData* debuggerParseData)
120 , m_hasStackOverflow(false)
122 , m_syntaxAlreadyValidated(source.provider()->isValid())
123 , m_statementDepth(0)
124 , m_sourceElements(0)
125 , m_parsingBuiltin(builtinMode == JSParserBuiltinMode::Builtin)
126 , m_scriptMode(scriptMode)
127 , m_superBinding(superBinding)
128 , m_defaultConstructorKind(defaultConstructorKind)
129 , m_immediateParentAllowsFunctionDeclarationInStatement(false)
130 , m_debuggerParseData(debuggerParseData)
132 m_lexer = std::make_unique<LexerType>(vm, builtinMode, scriptMode);
133 m_lexer->setCode(source, &m_parserArena);
134 m_token.m_location.line = source.firstLine().oneBasedInt();
135 m_token.m_location.startOffset = source.startOffset();
136 m_token.m_location.endOffset = source.startOffset();
137 m_token.m_location.lineStartOffset = source.startOffset();
138 m_functionCache = vm->addSourceProviderCache(source.provider());
139 m_expressionErrorClassifier = nullptr;
141 ScopeRef scope = pushScope();
142 scope->setSourceParseMode(parseMode);
143 scope->setIsEvalContext(isEvalContext);
145 scope->setEvalContextType(evalContextType);
147 if (derivedContextType == DerivedContextType::DerivedConstructorContext) {
148 scope->setConstructorKind(ConstructorKind::Extends);
149 scope->setExpectedSuperBinding(SuperBinding::Needed);
152 if (derivedContextType == DerivedContextType::DerivedMethodContext)
153 scope->setExpectedSuperBinding(SuperBinding::Needed);
155 if (strictMode == JSParserStrictMode::Strict)
156 scope->setStrictMode();
158 if (isModuleParseMode(parseMode))
159 m_moduleScopeData = ModuleScopeData::create();
161 if (isProgramOrModuleParseMode(parseMode))
162 scope->setIsGlobalCodeScope();
167 class Scope::MaybeParseAsGeneratorForScope : public SetForScope<bool> {
169 MaybeParseAsGeneratorForScope(ScopeRef& scope, bool shouldParseAsGenerator)
170 : SetForScope<bool>(scope->m_isGenerator, shouldParseAsGenerator) { }
173 struct DepthManager : private SetForScope<int> {
175 DepthManager(int* depth)
176 : SetForScope<int>(*depth, *depth)
181 template <typename LexerType>
182 Parser<LexerType>::~Parser()
186 template <typename LexerType>
187 String Parser<LexerType>::parseInner(const Identifier& calleeName, SourceParseMode parseMode)
189 String parseError = String();
191 ASTBuilder context(const_cast<VM*>(m_vm), m_parserArena, const_cast<SourceCode*>(m_source));
192 ScopeRef scope = currentScope();
193 scope->setIsLexicalScope();
194 SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_parserState.functionParsePhase, FunctionParsePhase::Body);
196 bool isArrowFunctionBodyExpression = parseMode == SourceParseMode::AsyncArrowFunctionBodyMode && !match(OPENBRACE);
197 if (m_lexer->isReparsingFunction()) {
198 ParserFunctionInfo<ASTBuilder> functionInfo;
199 if (isGeneratorOrAsyncFunctionBodyParseMode(parseMode))
200 m_parameters = createGeneratorParameters(context, functionInfo.parameterCount);
202 m_parameters = parseFunctionParameters(context, parseMode, functionInfo);
204 if (SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode).contains(parseMode) && !hasError()) {
205 // The only way we could have an error wile reparsing is if we run out of stack space.
206 RELEASE_ASSERT(match(ARROWFUNCTION));
208 isArrowFunctionBodyExpression = !match(OPENBRACE);
212 if (!calleeName.isNull())
213 scope->declareCallee(&calleeName);
215 if (m_lexer->isReparsingFunction())
218 SourceElements* sourceElements = nullptr;
219 // The only way we can error this early is if we reparse a function and we run out of stack space.
221 if (isAsyncFunctionWrapperParseMode(parseMode))
222 sourceElements = parseAsyncFunctionSourceElements(context, parseMode, isArrowFunctionBodyExpression, CheckForStrictMode);
223 else if (isArrowFunctionBodyExpression)
224 sourceElements = parseArrowFunctionSingleExpressionBodySourceElements(context);
225 else if (isModuleParseMode(parseMode))
226 sourceElements = parseModuleSourceElements(context, parseMode);
227 else if (isGeneratorWrapperParseMode(parseMode))
228 sourceElements = parseGeneratorFunctionSourceElements(context, calleeName, CheckForStrictMode);
230 sourceElements = parseSourceElements(context, CheckForStrictMode);
233 bool validEnding = consume(EOFTOK);
234 if (!sourceElements || !validEnding) {
236 parseError = m_errorMessage;
238 parseError = ASCIILiteral("Parser error");
241 IdentifierSet capturedVariables;
242 UniquedStringImplPtrSet sloppyModeHoistedFunctions;
243 scope->getSloppyModeHoistedFunctions(sloppyModeHoistedFunctions);
244 scope->getCapturedVars(capturedVariables);
246 VariableEnvironment& varDeclarations = scope->declaredVariables();
247 for (auto& entry : capturedVariables)
248 varDeclarations.markVariableAsCaptured(entry);
250 if (isGeneratorWrapperParseMode(parseMode) || isAsyncFunctionWrapperParseMode(parseMode)) {
251 if (scope->usedVariablesContains(m_vm->propertyNames->arguments.impl()))
252 context.propagateArgumentsUse();
255 CodeFeatures features = context.features();
256 if (scope->strictMode())
257 features |= StrictModeFeature;
258 if (scope->shadowsArguments())
259 features |= ShadowsArgumentsFeature;
262 if (m_parsingBuiltin && isProgramParseMode(parseMode)) {
263 VariableEnvironment& lexicalVariables = scope->lexicalVariables();
264 const HashSet<UniquedStringImpl*>& closedVariableCandidates = scope->closedVariableCandidates();
265 for (UniquedStringImpl* candidate : closedVariableCandidates) {
266 if (!lexicalVariables.contains(candidate) && !varDeclarations.contains(candidate) && !candidate->isSymbol()) {
267 dataLog("Bad global capture in builtin: '", candidate, "'\n");
268 dataLog(m_source->view());
274 didFinishParsing(sourceElements, scope->takeFunctionDeclarations(), varDeclarations, WTFMove(sloppyModeHoistedFunctions), features, context.numConstants());
279 template <typename LexerType>
280 void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, DeclarationStacks::FunctionStack&& funcStack,
281 VariableEnvironment& varDeclarations, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, CodeFeatures features, int numConstants)
283 m_sourceElements = sourceElements;
284 m_funcDeclarations = WTFMove(funcStack);
285 m_varDeclarations.swap(varDeclarations);
286 m_features = features;
287 m_sloppyModeHoistedFunctions = WTFMove(sloppyModeHoistedFunctions);
288 m_numConstants = numConstants;
291 template <typename LexerType>
292 bool Parser<LexerType>::isArrowFunctionParameters()
294 if (match(OPENPAREN)) {
295 SavePoint saveArrowFunctionPoint = createSavePoint();
297 bool isArrowFunction = false;
298 if (match(CLOSEPAREN)) {
300 isArrowFunction = match(ARROWFUNCTION);
302 SyntaxChecker syntaxChecker(const_cast<VM*>(m_vm), m_lexer.get());
303 // We make fake scope, otherwise parseFormalParameters will add variable to current scope that lead to errors
304 AutoPopScopeRef fakeScope(this, pushScope());
305 fakeScope->setSourceParseMode(SourceParseMode::ArrowFunctionMode);
307 unsigned parametersCount = 0;
308 bool isArrowFunctionParameterList = true;
309 bool isMethod = false;
310 isArrowFunction = parseFormalParameters(syntaxChecker, syntaxChecker.createFormalParameterList(), isArrowFunctionParameterList, isMethod, parametersCount) && consume(CLOSEPAREN) && match(ARROWFUNCTION);
312 popScope(fakeScope, syntaxChecker.NeedsFreeVariableInfo);
314 restoreSavePoint(saveArrowFunctionPoint);
315 return isArrowFunction;
318 if (matchSpecIdentifier()) {
319 SavePoint saveArrowFunctionPoint = createSavePoint();
321 bool isArrowFunction = match(ARROWFUNCTION);
322 restoreSavePoint(saveArrowFunctionPoint);
323 return isArrowFunction;
329 template <typename LexerType>
330 bool Parser<LexerType>::allowAutomaticSemicolon()
332 return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator();
335 template <typename LexerType>
336 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context, SourceElementsMode mode)
338 const unsigned lengthOfUseStrictLiteral = 12; // "use strict".length
339 TreeSourceElements sourceElements = context.createSourceElements();
340 const Identifier* directive = 0;
341 unsigned directiveLiteralLength = 0;
342 auto savePoint = createSavePoint();
343 bool shouldCheckForUseStrict = mode == CheckForStrictMode;
345 while (TreeStatement statement = parseStatementListItem(context, directive, &directiveLiteralLength)) {
346 if (shouldCheckForUseStrict) {
348 // "use strict" must be the exact literal without escape sequences or line continuation.
349 if (directiveLiteralLength == lengthOfUseStrictLiteral && m_vm->propertyNames->useStrictIdentifier == *directive) {
351 shouldCheckForUseStrict = false; // We saw "use strict", there is no need to keep checking for it.
352 if (!isValidStrictMode()) {
353 if (m_parserState.lastFunctionName) {
354 if (m_vm->propertyNames->arguments == *m_parserState.lastFunctionName)
355 semanticFail("Cannot name a function 'arguments' in strict mode");
356 if (m_vm->propertyNames->eval == *m_parserState.lastFunctionName)
357 semanticFail("Cannot name a function 'eval' in strict mode");
359 if (hasDeclaredVariable(m_vm->propertyNames->arguments))
360 semanticFail("Cannot declare a variable named 'arguments' in strict mode");
361 if (hasDeclaredVariable(m_vm->propertyNames->eval))
362 semanticFail("Cannot declare a variable named 'eval' in strict mode");
363 semanticFailIfTrue(currentScope()->hasNonSimpleParameterList(), "'use strict' directive not allowed inside a function with a non-simple parameter list");
364 semanticFailIfFalse(isValidStrictMode(), "Invalid parameters or function name in strict mode");
366 // Since strict mode is changed, restoring lexer state by calling next() may cause errors.
367 restoreSavePoint(savePoint);
372 // We saw a directive, but it wasn't "use strict". We reset our state to
373 // see if the next statement we parse is also a directive.
376 // We saw a statement that wasn't in the form of a directive. The spec says that "use strict"
377 // is only allowed as the first statement, or after a sequence of directives before it, but
378 // not after non-directive statements.
379 shouldCheckForUseStrict = false;
382 context.appendStatement(sourceElements, statement);
386 return sourceElements;
389 template <typename LexerType>
390 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseModuleSourceElements(TreeBuilder& context, SourceParseMode parseMode)
392 TreeSourceElements sourceElements = context.createSourceElements();
393 SyntaxChecker syntaxChecker(const_cast<VM*>(m_vm), m_lexer.get());
396 TreeStatement statement = 0;
397 switch (m_token.m_type) {
399 statement = parseExportDeclaration(context);
401 recordPauseLocation(context.breakpointLocation(statement));
405 SavePoint savePoint = createSavePoint();
407 bool isImportDeclaration = !match(OPENPAREN);
408 restoreSavePoint(savePoint);
409 if (isImportDeclaration) {
410 statement = parseImportDeclaration(context);
412 recordPauseLocation(context.breakpointLocation(statement));
416 // This is `import("...")` call case.
421 const Identifier* directive = 0;
422 unsigned directiveLiteralLength = 0;
423 if (parseMode == SourceParseMode::ModuleAnalyzeMode) {
424 if (!parseStatementListItem(syntaxChecker, directive, &directiveLiteralLength))
428 statement = parseStatementListItem(context, directive, &directiveLiteralLength);
435 context.appendStatement(sourceElements, statement);
441 for (const auto& pair : m_moduleScopeData->exportedBindings()) {
442 const auto& uid = pair.key;
443 if (currentScope()->hasDeclaredVariable(uid)) {
444 currentScope()->declaredVariables().markVariableAsExported(uid);
448 if (currentScope()->hasLexicallyDeclaredVariable(uid)) {
449 currentScope()->lexicalVariables().markVariableAsExported(uid);
453 semanticFail("Exported binding '", uid.get(), "' needs to refer to a top-level declared variable");
456 return sourceElements;
459 template <typename LexerType>
460 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseGeneratorFunctionSourceElements(TreeBuilder& context, const Identifier& name, SourceElementsMode mode)
462 auto sourceElements = context.createSourceElements();
464 unsigned functionKeywordStart = tokenStart();
465 JSTokenLocation startLocation(tokenLocation());
466 JSTextPosition start = tokenStartPosition();
467 unsigned startColumn = tokenColumn();
468 int functionNameStart = m_token.m_location.startOffset;
469 int parametersStart = m_token.m_location.startOffset;
471 ParserFunctionInfo<TreeBuilder> info;
472 info.name = &m_vm->propertyNames->nullIdentifier;
473 createGeneratorParameters(context, info.parameterCount);
474 info.startOffset = parametersStart;
475 info.startLine = tokenLine();
478 AutoPopScopeRef generatorBodyScope(this, pushScope());
479 generatorBodyScope->setSourceParseMode(SourceParseMode::GeneratorBodyMode);
480 generatorBodyScope->setConstructorKind(ConstructorKind::None);
481 generatorBodyScope->setExpectedSuperBinding(m_superBinding);
483 SyntaxChecker generatorFunctionContext(const_cast<VM*>(m_vm), m_lexer.get());
484 failIfFalse(parseSourceElements(generatorFunctionContext, mode), "Cannot parse the body of a generator");
485 popScope(generatorBodyScope, TreeBuilder::NeedsFreeVariableInfo);
487 info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, SourceParseMode::GeneratorBodyMode, false);
489 info.endLine = tokenLine();
490 info.endOffset = m_token.m_data.offset;
491 info.parametersStartColumn = startColumn;
493 auto functionExpr = context.createGeneratorFunctionBody(startLocation, info, name);
494 auto statement = context.createExprStatement(startLocation, functionExpr, start, m_lastTokenEndPosition.line);
495 context.appendStatement(sourceElements, statement);
497 return sourceElements;
500 template <typename LexerType>
501 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseAsyncFunctionSourceElements(TreeBuilder& context, SourceParseMode parseMode, bool isArrowFunctionBodyExpression, SourceElementsMode mode)
503 ASSERT(isAsyncFunctionWrapperParseMode(parseMode));
504 auto sourceElements = context.createSourceElements();
506 unsigned functionKeywordStart = tokenStart();
507 JSTokenLocation startLocation(tokenLocation());
508 JSTextPosition start = tokenStartPosition();
509 unsigned startColumn = tokenColumn();
510 int functionNameStart = m_token.m_location.startOffset;
511 int parametersStart = m_token.m_location.startOffset;
513 ParserFunctionInfo<TreeBuilder> info;
514 info.name = &m_vm->propertyNames->nullIdentifier;
515 createGeneratorParameters(context, info.parameterCount);
516 info.startOffset = parametersStart;
517 info.startLine = tokenLine();
518 SourceParseMode innerParseMode = parseMode == SourceParseMode::AsyncArrowFunctionMode
519 ? SourceParseMode::AsyncArrowFunctionBodyMode
520 : SourceParseMode::AsyncFunctionBodyMode;
522 AutoPopScopeRef asyncFunctionBodyScope(this, pushScope());
523 asyncFunctionBodyScope->setSourceParseMode(innerParseMode);
524 SyntaxChecker syntaxChecker(const_cast<VM*>(m_vm), m_lexer.get());
525 if (isArrowFunctionBodyExpression) {
526 if (m_debuggerParseData)
527 failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(context), "Cannot parse the body of async arrow function");
529 failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(syntaxChecker), "Cannot parse the body of async arrow function");
531 if (m_debuggerParseData)
532 failIfFalse(parseSourceElements(context, mode), "Cannot parse the body of async function");
534 failIfFalse(parseSourceElements(syntaxChecker, mode), "Cannot parse the body of async function");
536 popScope(asyncFunctionBodyScope, TreeBuilder::NeedsFreeVariableInfo);
538 info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, innerParseMode, isArrowFunctionBodyExpression);
540 info.endLine = tokenLine();
541 info.endOffset = isArrowFunctionBodyExpression ? tokenLocation().endOffset : m_token.m_data.offset;
542 info.parametersStartColumn = startColumn;
544 auto functionExpr = context.createAsyncFunctionBody(startLocation, info, innerParseMode);
545 auto statement = context.createExprStatement(startLocation, functionExpr, start, m_lastTokenEndPosition.line);
546 context.appendStatement(sourceElements, statement);
548 return sourceElements;
551 template <typename LexerType>
552 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatementListItem(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
554 // The grammar is documented here:
555 // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-statements
556 DepthManager statementDepth(&m_statementDepth);
558 TreeStatement result = 0;
559 bool shouldSetEndOffset = true;
560 bool shouldSetPauseLocation = false;
562 switch (m_token.m_type) {
564 result = parseVariableDeclaration(context, DeclarationType::ConstDeclaration);
565 shouldSetPauseLocation = true;
568 bool shouldParseVariableDeclaration = true;
570 SavePoint savePoint = createSavePoint();
572 // Intentionally use `isIdentifierOrAnyContextualKeyword(m_token)` and don't use `matchSpecIdentifier()`.
573 // We would like to fall into parseVariableDeclaration path even if "yield" is not treated as an Identifier.
574 // For example, under a generator context, matchSpecIdentifier() for "yield" returns `false`.
575 // But we would like to enter parseVariableDeclaration and raise an error under the context of parseVariableDeclaration
576 // to raise consistent errors between "var", "const" and "let".
577 if (!isIdentifierOrAnyContextualKeyword(m_token) && !match(OPENBRACE) && !match(OPENBRACKET))
578 shouldParseVariableDeclaration = false;
579 restoreSavePoint(savePoint);
581 if (shouldParseVariableDeclaration)
582 result = parseVariableDeclaration(context, DeclarationType::LetDeclaration);
584 bool allowFunctionDeclarationAsStatement = true;
585 result = parseExpressionOrLabelStatement(context, allowFunctionDeclarationAsStatement);
587 shouldSetPauseLocation = !context.shouldSkipPauseLocation(result);
591 result = parseClassDeclaration(context);
594 result = parseFunctionDeclaration(context);
597 // Eagerly parse as AsyncFunctionDeclaration. This is the uncommon case,
598 // but could be mistakenly parsed as an AsyncFunctionExpression.
599 SavePoint savePoint = createSavePoint();
601 if (UNLIKELY(match(FUNCTION) && !m_lexer->prevTerminator())) {
602 result = parseAsyncFunctionDeclaration(context);
605 restoreSavePoint(savePoint);
611 // This is a convenient place to notice labeled statements
612 // (even though we also parse them as normal statements)
613 // because we allow the following type of code in sloppy mode:
614 // ``` function foo() { label: function bar() { } } ```
615 bool allowFunctionDeclarationAsStatement = true;
616 result = parseExpressionOrLabelStatement(context, allowFunctionDeclarationAsStatement);
617 shouldSetPauseLocation = !context.shouldSkipPauseLocation(result);
621 m_statementDepth--; // parseStatement() increments the depth.
622 result = parseStatement(context, directive, directiveLiteralLength);
623 shouldSetEndOffset = false;
628 if (shouldSetEndOffset)
629 context.setEndOffset(result, m_lastTokenEndPosition.offset);
630 if (shouldSetPauseLocation)
631 recordPauseLocation(context.breakpointLocation(result));
637 template <typename LexerType>
638 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVariableDeclaration(TreeBuilder& context, DeclarationType declarationType, ExportType exportType)
640 ASSERT(match(VAR) || match(LET) || match(CONSTTOKEN));
641 JSTokenLocation location(tokenLocation());
642 int start = tokenLine();
645 TreeDestructuringPattern scratch1 = 0;
646 TreeExpression scratch2 = 0;
647 JSTextPosition scratch3;
649 TreeExpression variableDecls = parseVariableDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3, VarDeclarationContext, declarationType, exportType, scratchBool);
651 failIfFalse(autoSemiColon(), "Expected ';' after variable declaration");
653 return context.createDeclarationStatement(location, variableDecls, start, end);
656 template <typename LexerType>
657 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDoWhileStatement(TreeBuilder& context)
660 int startLine = tokenLine();
662 const Identifier* unused = 0;
664 TreeStatement statement = parseStatement(context, unused);
666 failIfFalse(statement, "Expected a statement following 'do'");
667 int endLine = tokenLine();
668 JSTokenLocation location(tokenLocation());
669 handleProductionOrFail(WHILE, "while", "end", "do-while loop");
670 handleProductionOrFail(OPENPAREN, "(", "start", "do-while loop condition");
671 semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a do-while loop condition");
672 TreeExpression expr = parseExpression(context);
673 failIfFalse(expr, "Unable to parse do-while loop condition");
674 recordPauseLocation(context.breakpointLocation(expr));
675 handleProductionOrFail(CLOSEPAREN, ")", "end", "do-while loop condition");
676 if (match(SEMICOLON))
677 next(); // Always performs automatic semicolon insertion.
678 return context.createDoWhileStatement(location, statement, expr, startLine, endLine);
681 template <typename LexerType>
682 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWhileStatement(TreeBuilder& context)
684 ASSERT(match(WHILE));
685 JSTokenLocation location(tokenLocation());
686 int startLine = tokenLine();
689 handleProductionOrFail(OPENPAREN, "(", "start", "while loop condition");
690 semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a while loop condition");
691 TreeExpression expr = parseExpression(context);
692 failIfFalse(expr, "Unable to parse while loop condition");
693 recordPauseLocation(context.breakpointLocation(expr));
694 int endLine = tokenLine();
695 handleProductionOrFail(CLOSEPAREN, ")", "end", "while loop condition");
697 const Identifier* unused = 0;
699 TreeStatement statement = parseStatement(context, unused);
701 failIfFalse(statement, "Expected a statement as the body of a while loop");
702 return context.createWhileStatement(location, expr, statement, startLine, endLine);
705 template <typename LexerType>
706 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)
708 ASSERT(declarationType == DeclarationType::LetDeclaration || declarationType == DeclarationType::VarDeclaration || declarationType == DeclarationType::ConstDeclaration);
709 TreeExpression head = 0;
710 TreeExpression tail = 0;
711 const Identifier* lastIdent;
712 JSToken lastIdentToken;
713 AssignmentContext assignmentContext = assignmentContextFromDeclarationType(declarationType);
716 lastPattern = TreeDestructuringPattern(0);
717 JSTokenLocation location(tokenLocation());
719 TreeExpression node = 0;
721 bool hasInitializer = false;
722 if (matchSpecIdentifier()) {
723 failIfTrue(match(LET) && (declarationType == DeclarationType::LetDeclaration || declarationType == DeclarationType::ConstDeclaration),
724 "Cannot use 'let' as an identifier name for a LexicalDeclaration");
725 semanticFailIfTrue(isDisallowedIdentifierAwait(m_token), "Cannot use 'await' as a ", declarationTypeToVariableKind(declarationType), " ", disallowedIdentifierAwaitReason());
726 JSTextPosition varStart = tokenStartPosition();
727 JSTokenLocation varStartLocation(tokenLocation());
728 identStart = varStart;
729 const Identifier* name = m_token.m_data.ident;
731 lastIdentToken = m_token;
733 hasInitializer = match(EQUAL);
734 DeclarationResultMask declarationResult = declareVariable(name, declarationType);
735 if (declarationResult != DeclarationResult::Valid) {
736 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a variable named ", name->impl(), " in strict mode");
737 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration) {
738 if (declarationType == DeclarationType::LetDeclaration)
739 internalFailWithMessage(false, "Cannot declare a let variable twice: '", name->impl(), "'");
740 if (declarationType == DeclarationType::ConstDeclaration)
741 internalFailWithMessage(false, "Cannot declare a const variable twice: '", name->impl(), "'");
742 ASSERT(declarationType == DeclarationType::VarDeclaration);
743 internalFailWithMessage(false, "Cannot declare a var variable that shadows a let/const/class variable: '", name->impl(), "'");
746 if (exportType == ExportType::Exported) {
747 semanticFailIfFalse(exportName(*name), "Cannot export a duplicate name '", name->impl(), "'");
748 m_moduleScopeData->exportBinding(*name);
751 if (hasInitializer) {
752 JSTextPosition varDivot = tokenStartPosition() + 1;
753 initStart = tokenStartPosition();
754 next(TreeBuilder::DontBuildStrings); // consume '='
756 TreeExpression initializer = parseAssignmentExpression(context);
757 initEnd = lastTokenEndPosition();
758 lastInitializer = initializer;
759 failIfFalse(initializer, "Expected expression as the intializer for the variable '", name->impl(), "'");
761 node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEndPosition(), assignmentContext);
763 if (declarationListContext == ForLoopContext && declarationType == DeclarationType::ConstDeclaration)
764 forLoopConstDoesNotHaveInitializer = true;
765 failIfTrue(declarationListContext != ForLoopContext && declarationType == DeclarationType::ConstDeclaration, "const declared variable '", name->impl(), "'", " must have an initializer");
766 if (declarationType == DeclarationType::VarDeclaration)
767 node = context.createEmptyVarExpression(varStartLocation, *name);
769 node = context.createEmptyLetExpression(varStartLocation, *name);
773 auto pattern = parseDestructuringPattern(context, destructuringKindFromDeclarationType(declarationType), exportType, nullptr, nullptr, assignmentContext);
774 failIfFalse(pattern, "Cannot parse this destructuring pattern");
775 hasInitializer = match(EQUAL);
776 failIfTrue(declarationListContext == VarDeclarationContext && !hasInitializer, "Expected an initializer in destructuring variable declaration");
777 lastPattern = pattern;
778 if (hasInitializer) {
779 next(TreeBuilder::DontBuildStrings); // consume '='
780 TreeExpression rhs = parseAssignmentExpression(context);
783 node = context.createDestructuringAssignment(location, pattern, rhs);
784 lastInitializer = rhs;
792 head = context.createCommaExpr(location, head);
793 tail = context.appendToCommaExpr(location, head, head, node);
795 tail = context.appendToCommaExpr(location, head, tail, node);
797 } while (match(COMMA));
799 lastPattern = context.createBindingLocation(lastIdentToken.m_location, *lastIdent, lastIdentToken.m_startPosition, lastIdentToken.m_endPosition, assignmentContext);
804 template <typename LexerType>
805 bool Parser<LexerType>::declareRestOrNormalParameter(const Identifier& name, const Identifier** duplicateIdentifier)
807 DeclarationResultMask declarationResult = declareParameter(&name);
808 if ((declarationResult & DeclarationResult::InvalidStrictMode) && strictMode()) {
809 semanticFailIfTrue(isEvalOrArguments(&name), "Cannot destructure to a parameter name '", name.impl(), "' in strict mode");
810 if (m_parserState.lastFunctionName && name == *m_parserState.lastFunctionName)
811 semanticFail("Cannot declare a parameter named '", name.impl(), "' as it shadows the name of a strict mode function");
812 semanticFailureDueToKeyword("parameter name");
813 if (!m_lexer->isReparsingFunction() && hasDeclaredParameter(name))
814 semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode as it has already been declared");
815 semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode");
817 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration) {
818 // It's not always an error to define a duplicate parameter.
819 // It's only an error when there are default parameter values or destructuring parameters.
820 // We note this value now so we can check it later.
821 if (duplicateIdentifier)
822 *duplicateIdentifier = &name;
828 template <typename LexerType>
829 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::createBindingPattern(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier& name, JSToken token, AssignmentContext bindingContext, const Identifier** duplicateIdentifier)
831 ASSERT(!name.isNull());
833 ASSERT(name.impl()->isAtomic() || name.impl()->isSymbol());
836 case DestructuringKind::DestructureToVariables: {
837 DeclarationResultMask declarationResult = declareVariable(&name);
838 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a variable named '", name.impl(), "' in strict mode");
839 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
840 internalFailWithMessage(false, "Cannot declare a var variable that shadows a let/const/class variable: '", name.impl(), "'");
844 case DestructuringKind::DestructureToLet:
845 case DestructuringKind::DestructureToConst:
846 case DestructuringKind::DestructureToCatchParameters: {
847 DeclarationResultMask declarationResult = declareVariable(&name, kind == DestructuringKind::DestructureToConst ? DeclarationType::ConstDeclaration : DeclarationType::LetDeclaration);
848 if (declarationResult != DeclarationResult::Valid) {
849 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot destructure to a variable named '", name.impl(), "' in strict mode");
850 failIfTrue(declarationResult & DeclarationResult::InvalidDuplicateDeclaration, "Cannot declare a lexical variable twice: '", name.impl(), "'");
855 case DestructuringKind::DestructureToParameters: {
856 declareRestOrNormalParameter(name, duplicateIdentifier);
861 case DestructuringKind::DestructureToExpressions: {
866 if (exportType == ExportType::Exported) {
867 semanticFailIfFalse(exportName(name), "Cannot export a duplicate name '", name.impl(), "'");
868 m_moduleScopeData->exportBinding(name);
870 return context.createBindingLocation(token.m_location, name, token.m_startPosition, token.m_endPosition, bindingContext);
873 template <typename LexerType>
874 template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern Parser<LexerType>::createAssignmentElement(TreeBuilder& context, TreeExpression& assignmentTarget, const JSTextPosition& startPosition, const JSTextPosition& endPosition)
876 return context.createAssignmentElement(assignmentTarget, startPosition, endPosition);
879 template <typename LexerType>
880 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseArrowFunctionSingleExpressionBodySourceElements(TreeBuilder& context)
882 ASSERT(!match(OPENBRACE));
884 JSTokenLocation location(tokenLocation());
885 JSTextPosition start = tokenStartPosition();
887 failIfStackOverflow();
888 TreeExpression expr = parseAssignmentExpression(context);
889 failIfFalse(expr, "Cannot parse the arrow function expression");
891 context.setEndOffset(expr, m_lastTokenEndPosition.offset);
893 JSTextPosition end = tokenEndPosition();
895 TreeSourceElements sourceElements = context.createSourceElements();
896 TreeStatement body = context.createReturnStatement(location, expr, start, end);
897 context.setEndOffset(body, m_lastTokenEndPosition.offset);
898 recordPauseLocation(context.breakpointLocation(body));
899 context.appendStatement(sourceElements, body);
901 return sourceElements;
904 template <typename LexerType>
905 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::tryParseDestructuringPatternExpression(TreeBuilder& context, AssignmentContext bindingContext)
907 return parseDestructuringPattern(context, DestructuringKind::DestructureToExpressions, ExportType::NotExported, nullptr, nullptr, bindingContext);
910 template <typename LexerType>
911 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseBindingOrAssignmentElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
913 if (kind == DestructuringKind::DestructureToExpressions)
914 return parseAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
915 return parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
918 template <typename LexerType>
919 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseAssignmentElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
921 TreeDestructuringPattern assignmentTarget = 0;
923 if (match(OPENBRACE) || match(OPENBRACKET)) {
924 SavePoint savePoint = createSavePoint();
925 assignmentTarget = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
926 if (assignmentTarget && !match(DOT) && !match(OPENBRACKET) && !match(OPENPAREN) && !match(BACKQUOTE))
927 return assignmentTarget;
928 restoreSavePoint(savePoint);
931 JSTextPosition startPosition = tokenStartPosition();
932 auto element = parseMemberExpression(context);
934 semanticFailIfFalse(element && context.isAssignmentLocation(element), "Invalid destructuring assignment target");
936 if (strictMode() && m_parserState.lastIdentifier && context.isResolve(element)) {
937 bool isEvalOrArguments = m_vm->propertyNames->eval == *m_parserState.lastIdentifier || m_vm->propertyNames->arguments == *m_parserState.lastIdentifier;
938 failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", m_parserState.lastIdentifier->impl(), "' in strict mode");
941 return createAssignmentElement(context, element, startPosition, lastTokenEndPosition());
944 static const char* destructuringKindToVariableKindName(DestructuringKind kind)
947 case DestructuringKind::DestructureToLet:
948 case DestructuringKind::DestructureToConst:
949 return "lexical variable name";
950 case DestructuringKind::DestructureToVariables:
951 return "variable name";
952 case DestructuringKind::DestructureToParameters:
953 return "parameter name";
954 case DestructuringKind::DestructureToCatchParameters:
955 return "catch parameter name";
956 case DestructuringKind::DestructureToExpressions:
957 return "expression name";
959 RELEASE_ASSERT_NOT_REACHED();
963 template <typename LexerType>
964 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseDestructuringPattern(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
966 failIfStackOverflow();
967 int nonLHSCount = m_parserState.nonLHSCount;
968 TreeDestructuringPattern pattern;
969 switch (m_token.m_type) {
971 JSTextPosition divotStart = tokenStartPosition();
972 auto arrayPattern = context.createArrayPattern(m_token.m_location);
975 if (hasDestructuringPattern)
976 *hasDestructuringPattern = true;
978 bool restElementWasFound = false;
981 while (match(COMMA)) {
982 context.appendArrayPatternSkipEntry(arrayPattern, m_token.m_location);
987 if (match(CLOSEBRACKET))
990 if (UNLIKELY(match(DOTDOTDOT))) {
991 JSTokenLocation location = m_token.m_location;
993 auto innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
994 if (kind == DestructuringKind::DestructureToExpressions && !innerPattern)
996 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
997 context.appendArrayPatternRestEntry(arrayPattern, location, innerPattern);
998 restElementWasFound = true;
1002 JSTokenLocation location = m_token.m_location;
1003 auto innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
1004 if (kind == DestructuringKind::DestructureToExpressions && !innerPattern)
1006 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
1007 TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
1009 context.appendArrayPatternEntry(arrayPattern, location, innerPattern, defaultValue);
1010 } while (consume(COMMA));
1012 consumeOrFail(CLOSEBRACKET, restElementWasFound ? "Expected a closing ']' following a rest element destructuring pattern" : "Expected either a closing ']' or a ',' following an element destructuring pattern");
1013 context.finishArrayPattern(arrayPattern, divotStart, divotStart, lastTokenEndPosition());
1014 pattern = arrayPattern;
1018 auto objectPattern = context.createObjectPattern(m_token.m_location);
1021 if (hasDestructuringPattern)
1022 *hasDestructuringPattern = true;
1025 bool wasString = false;
1027 if (match(CLOSEBRACE))
1030 const Identifier* propertyName = nullptr;
1031 TreeExpression propertyExpression = 0;
1032 TreeDestructuringPattern innerPattern = 0;
1033 JSTokenLocation location = m_token.m_location;
1034 if (matchSpecIdentifier()) {
1035 failIfTrue(match(LET) && (kind == DestructuringKind::DestructureToLet || kind == DestructuringKind::DestructureToConst), "Cannot use 'let' as an identifier name for a LexicalDeclaration");
1036 propertyName = m_token.m_data.ident;
1037 JSToken identifierToken = m_token;
1040 innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
1042 if (kind == DestructuringKind::DestructureToExpressions) {
1043 bool isEvalOrArguments = m_vm->propertyNames->eval == *propertyName || m_vm->propertyNames->arguments == *propertyName;
1044 if (isEvalOrArguments && strictMode())
1045 reclassifyExpressionError(ErrorIndicatesPattern, ErrorIndicatesNothing);
1046 failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", propertyName->impl(), "' in strict mode");
1048 semanticFailIfTrue(isDisallowedIdentifierAwait(identifierToken), "Cannot use 'await' as a ", destructuringKindToVariableKindName(kind), " ", disallowedIdentifierAwaitReason());
1049 innerPattern = createBindingPattern(context, kind, exportType, *propertyName, identifierToken, bindingContext, duplicateIdentifier);
1052 JSTokenType tokenType = m_token.m_type;
1053 switch (m_token.m_type) {
1056 propertyName = &m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), m_token.m_data.doubleValue);
1059 propertyName = m_token.m_data.ident;
1064 propertyExpression = parseAssignmentExpression(context);
1065 failIfFalse(propertyExpression, "Cannot parse computed property name");
1066 matchOrFail(CLOSEBRACKET, "Expected ']' to end end a computed property name");
1069 if (m_token.m_type != RESERVED && m_token.m_type != RESERVED_IF_STRICT && !(m_token.m_type & KeywordTokenFlag)) {
1070 if (kind == DestructuringKind::DestructureToExpressions)
1072 failWithMessage("Expected a property name");
1074 propertyName = m_token.m_data.ident;
1078 if (!consume(COLON)) {
1079 if (kind == DestructuringKind::DestructureToExpressions)
1081 semanticFailIfTrue(tokenType == RESERVED, "Cannot use abbreviated destructuring syntax for reserved name '", propertyName->impl(), "'");
1082 semanticFailIfTrue(tokenType == RESERVED_IF_STRICT, "Cannot use abbreviated destructuring syntax for reserved name '", propertyName->impl(), "' in strict mode");
1083 semanticFailIfTrue(tokenType & KeywordTokenFlag, "Cannot use abbreviated destructuring syntax for keyword '", propertyName->impl(), "'");
1085 failWithMessage("Expected a ':' prior to a named destructuring property");
1087 innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
1089 if (kind == DestructuringKind::DestructureToExpressions && !innerPattern)
1091 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
1092 TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
1094 if (propertyExpression)
1095 context.appendObjectPatternEntry(objectPattern, location, propertyExpression, innerPattern, defaultValue);
1097 ASSERT(propertyName);
1098 context.appendObjectPatternEntry(objectPattern, location, wasString, *propertyName, innerPattern, defaultValue);
1100 } while (consume(COMMA));
1102 if (kind == DestructuringKind::DestructureToExpressions && !match(CLOSEBRACE))
1104 consumeOrFail(CLOSEBRACE, "Expected either a closing '}' or an ',' after a property destructuring pattern");
1105 pattern = objectPattern;
1110 if (!matchSpecIdentifier()) {
1111 if (kind == DestructuringKind::DestructureToExpressions)
1113 semanticFailureDueToKeyword(destructuringKindToVariableKindName(kind));
1114 failWithMessage("Expected a parameter pattern or a ')' in parameter list");
1116 failIfTrue(match(LET) && (kind == DestructuringKind::DestructureToLet || kind == DestructuringKind::DestructureToConst), "Cannot use 'let' as an identifier name for a LexicalDeclaration");
1117 semanticFailIfTrue(isDisallowedIdentifierAwait(m_token), "Cannot use 'await' as a ", destructuringKindToVariableKindName(kind), " ", disallowedIdentifierAwaitReason());
1118 pattern = createBindingPattern(context, kind, exportType, *m_token.m_data.ident, m_token, bindingContext, duplicateIdentifier);
1123 m_parserState.nonLHSCount = nonLHSCount;
1127 template <typename LexerType>
1128 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseDefaultValueForDestructuringPattern(TreeBuilder& context)
1133 next(TreeBuilder::DontBuildStrings); // consume '='
1134 return parseAssignmentExpression(context);
1137 template <typename LexerType>
1138 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement(TreeBuilder& context)
1141 JSTokenLocation location(tokenLocation());
1142 int startLine = tokenLine();
1145 DepthManager statementDepth(&m_statementDepth);
1148 handleProductionOrFail(OPENPAREN, "(", "start", "for-loop header");
1149 int nonLHSCount = m_parserState.nonLHSCount;
1150 int declarations = 0;
1151 JSTokenLocation declLocation(tokenLocation());
1152 JSTextPosition declsStart;
1153 JSTextPosition declsEnd;
1154 TreeExpression decls = 0;
1155 TreeDestructuringPattern pattern = 0;
1156 bool isVarDeclaraton = match(VAR);
1157 bool isLetDeclaration = match(LET);
1158 bool isConstDeclaration = match(CONSTTOKEN);
1159 bool forLoopConstDoesNotHaveInitializer = false;
1161 VariableEnvironment dummySet;
1162 VariableEnvironment* lexicalVariables = nullptr;
1163 AutoCleanupLexicalScope lexicalScope;
1165 auto gatherLexicalVariablesIfNecessary = [&] {
1166 if (isLetDeclaration || isConstDeclaration) {
1167 ScopeRef scope = lexicalScope.scope();
1168 lexicalVariables = &scope->finalizeLexicalEnvironment();
1170 lexicalVariables = &dummySet;
1173 auto popLexicalScopeIfNecessary = [&] {
1174 if (isLetDeclaration || isConstDeclaration)
1175 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1178 if (isVarDeclaraton || isLetDeclaration || isConstDeclaration) {
1180 for (var/let/const IDENT in/of expression) statement
1181 for (var/let/const varDeclarationList; expressionOpt; expressionOpt)
1183 if (isLetDeclaration || isConstDeclaration) {
1184 ScopeRef newScope = pushScope();
1185 newScope->setIsLexicalScope();
1186 newScope->preventVarDeclarations();
1187 lexicalScope.setIsValid(newScope, this);
1190 TreeDestructuringPattern forInTarget = 0;
1191 TreeExpression forInInitializer = 0;
1193 JSTextPosition initStart;
1194 JSTextPosition initEnd;
1195 DeclarationType declarationType;
1196 if (isVarDeclaraton)
1197 declarationType = DeclarationType::VarDeclaration;
1198 else if (isLetDeclaration)
1199 declarationType = DeclarationType::LetDeclaration;
1200 else if (isConstDeclaration)
1201 declarationType = DeclarationType::ConstDeclaration;
1203 RELEASE_ASSERT_NOT_REACHED();
1204 decls = parseVariableDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd, ForLoopContext, declarationType, ExportType::NotExported, forLoopConstDoesNotHaveInitializer);
1208 // Remainder of a standard for loop is handled identically
1209 if (match(SEMICOLON))
1210 goto standardForLoop;
1212 failIfFalse(declarations == 1, "can only declare a single variable in an enumeration");
1214 // Handle for-in with var declaration
1215 JSTextPosition inLocation = tokenStartPosition();
1216 bool isOfEnumeration = false;
1217 if (!consume(INTOKEN)) {
1218 failIfFalse(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax");
1219 isOfEnumeration = true;
1222 bool hasAnyAssignments = !!forInInitializer;
1223 if (hasAnyAssignments) {
1224 if (isOfEnumeration)
1225 internalFailWithMessage(false, "Cannot assign to the loop variable inside a for-of loop header");
1226 if (strictMode() || (isLetDeclaration || isConstDeclaration) || !context.isBindingNode(forInTarget))
1227 internalFailWithMessage(false, "Cannot assign to the loop variable inside a for-in loop header");
1229 TreeExpression expr = parseExpression(context);
1230 failIfFalse(expr, "Expected expression to enumerate");
1231 recordPauseLocation(context.breakpointLocation(expr));
1232 JSTextPosition exprEnd = lastTokenEndPosition();
1234 int endLine = tokenLine();
1236 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
1238 const Identifier* unused = 0;
1240 TreeStatement statement = parseStatement(context, unused);
1242 failIfFalse(statement, "Expected statement as body of for-", isOfEnumeration ? "of" : "in", " statement");
1243 gatherLexicalVariablesIfNecessary();
1244 TreeStatement result;
1245 if (isOfEnumeration)
1246 result = context.createForOfLoop(location, forInTarget, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
1248 if (isVarDeclaraton && forInInitializer)
1249 result = context.createForInLoop(location, decls, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
1251 result = context.createForInLoop(location, forInTarget, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
1253 popLexicalScopeIfNecessary();
1257 if (!match(SEMICOLON)) {
1258 if (match(OPENBRACE) || match(OPENBRACKET)) {
1259 SavePoint savePoint = createSavePoint();
1260 declsStart = tokenStartPosition();
1261 pattern = tryParseDestructuringPatternExpression(context, AssignmentContext::DeclarationStatement);
1262 declsEnd = lastTokenEndPosition();
1263 if (pattern && (match(INTOKEN) || (match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of)))
1264 goto enumerationLoop;
1265 pattern = TreeDestructuringPattern(0);
1266 restoreSavePoint(savePoint);
1269 declsStart = tokenStartPosition();
1270 decls = parseExpression(context);
1271 declsEnd = lastTokenEndPosition();
1273 failIfFalse(decls, "Cannot parse for loop declarations");
1274 recordPauseLocation(context.breakpointLocation(decls));
1277 if (match(SEMICOLON)) {
1279 // Standard for loop
1281 recordPauseLocation(context.breakpointLocation(decls));
1283 TreeExpression condition = 0;
1284 failIfTrue(forLoopConstDoesNotHaveInitializer && isConstDeclaration, "const variables in for loops must have initializers");
1286 if (!match(SEMICOLON)) {
1287 condition = parseExpression(context);
1288 failIfFalse(condition, "Cannot parse for loop condition expression");
1289 recordPauseLocation(context.breakpointLocation(condition));
1291 consumeOrFail(SEMICOLON, "Expected a ';' after the for loop condition expression");
1293 TreeExpression increment = 0;
1294 if (!match(CLOSEPAREN)) {
1295 increment = parseExpression(context);
1296 failIfFalse(increment, "Cannot parse for loop iteration expression");
1297 recordPauseLocation(context.breakpointLocation(increment));
1299 int endLine = tokenLine();
1300 handleProductionOrFail(CLOSEPAREN, ")", "end", "for-loop header");
1301 const Identifier* unused = 0;
1303 TreeStatement statement = parseStatement(context, unused);
1305 failIfFalse(statement, "Expected a statement as the body of a for loop");
1306 gatherLexicalVariablesIfNecessary();
1307 TreeStatement result = context.createForLoop(location, decls, condition, increment, statement, startLine, endLine, *lexicalVariables);
1308 popLexicalScopeIfNecessary();
1312 // For-in and For-of loop
1314 failIfFalse(nonLHSCount == m_parserState.nonLHSCount, "Expected a reference on the left hand side of an enumeration statement");
1315 bool isOfEnumeration = false;
1316 if (!consume(INTOKEN)) {
1317 failIfFalse(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax");
1318 isOfEnumeration = true;
1321 TreeExpression expr = parseExpression(context);
1322 failIfFalse(expr, "Cannot parse subject for-", isOfEnumeration ? "of" : "in", " statement");
1323 recordPauseLocation(context.breakpointLocation(expr));
1324 JSTextPosition exprEnd = lastTokenEndPosition();
1325 int endLine = tokenLine();
1327 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
1328 const Identifier* unused = 0;
1330 TreeStatement statement = parseStatement(context, unused);
1332 failIfFalse(statement, "Expected a statement as the body of a for-", isOfEnumeration ? "of" : "in", "loop");
1333 gatherLexicalVariablesIfNecessary();
1334 TreeStatement result;
1337 if (isOfEnumeration)
1338 result = context.createForOfLoop(location, pattern, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1340 result = context.createForInLoop(location, pattern, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1342 popLexicalScopeIfNecessary();
1345 if (isOfEnumeration)
1346 result = context.createForOfLoop(location, decls, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1348 result = context.createForInLoop(location, decls, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1349 popLexicalScopeIfNecessary();
1353 template <typename LexerType>
1354 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatement(TreeBuilder& context)
1356 ASSERT(match(BREAK));
1357 JSTokenLocation location(tokenLocation());
1358 JSTextPosition start = tokenStartPosition();
1359 JSTextPosition end = tokenEndPosition();
1362 if (autoSemiColon()) {
1363 semanticFailIfFalse(breakIsValid(), "'break' is only valid inside a switch or loop statement");
1364 return context.createBreakStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
1366 failIfFalse(matchSpecIdentifier(), "Expected an identifier as the target for a break statement");
1367 const Identifier* ident = m_token.m_data.ident;
1368 semanticFailIfFalse(getLabel(ident), "Cannot use the undeclared label '", ident->impl(), "'");
1369 end = tokenEndPosition();
1371 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted break statement");
1372 return context.createBreakStatement(location, ident, start, end);
1375 template <typename LexerType>
1376 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueStatement(TreeBuilder& context)
1378 ASSERT(match(CONTINUE));
1379 JSTokenLocation location(tokenLocation());
1380 JSTextPosition start = tokenStartPosition();
1381 JSTextPosition end = tokenEndPosition();
1384 if (autoSemiColon()) {
1385 semanticFailIfFalse(continueIsValid(), "'continue' is only valid inside a loop statement");
1386 return context.createContinueStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
1388 failIfFalse(matchSpecIdentifier(), "Expected an identifier as the target for a continue statement");
1389 const Identifier* ident = m_token.m_data.ident;
1390 ScopeLabelInfo* label = getLabel(ident);
1391 semanticFailIfFalse(label, "Cannot use the undeclared label '", ident->impl(), "'");
1392 semanticFailIfFalse(label->isLoop, "Cannot continue to the label '", ident->impl(), "' as it is not targeting a loop");
1393 end = tokenEndPosition();
1395 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted continue statement");
1396 return context.createContinueStatement(location, ident, start, end);
1399 template <typename LexerType>
1400 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStatement(TreeBuilder& context)
1402 ASSERT(match(RETURN));
1403 JSTokenLocation location(tokenLocation());
1404 semanticFailIfFalse(currentScope()->isFunction(), "Return statements are only valid inside functions");
1405 JSTextPosition start = tokenStartPosition();
1406 JSTextPosition end = tokenEndPosition();
1408 // We do the auto semicolon check before attempting to parse expression
1409 // as we need to ensure the a line break after the return correctly terminates
1411 if (match(SEMICOLON))
1412 end = tokenEndPosition();
1414 if (autoSemiColon())
1415 return context.createReturnStatement(location, 0, start, end);
1416 TreeExpression expr = parseExpression(context);
1417 failIfFalse(expr, "Cannot parse the return expression");
1418 end = lastTokenEndPosition();
1419 if (match(SEMICOLON))
1420 end = tokenEndPosition();
1421 if (!autoSemiColon())
1422 failWithMessage("Expected a ';' following a return statement");
1423 return context.createReturnStatement(location, expr, start, end);
1426 template <typename LexerType>
1427 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseThrowStatement(TreeBuilder& context)
1429 ASSERT(match(THROW));
1430 JSTokenLocation location(tokenLocation());
1431 JSTextPosition start = tokenStartPosition();
1433 failIfTrue(match(SEMICOLON), "Expected expression after 'throw'");
1434 semanticFailIfTrue(autoSemiColon(), "Cannot have a newline after 'throw'");
1436 TreeExpression expr = parseExpression(context);
1437 failIfFalse(expr, "Cannot parse expression for throw statement");
1438 JSTextPosition end = lastTokenEndPosition();
1439 failIfFalse(autoSemiColon(), "Expected a ';' after a throw statement");
1441 return context.createThrowStatement(location, expr, start, end);
1444 template <typename LexerType>
1445 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement(TreeBuilder& context)
1447 ASSERT(match(WITH));
1448 JSTokenLocation location(tokenLocation());
1449 semanticFailIfTrue(strictMode(), "'with' statements are not valid in strict mode");
1450 currentScope()->setNeedsFullActivation();
1451 int startLine = tokenLine();
1454 handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'with' statement");
1455 int start = tokenStart();
1456 TreeExpression expr = parseExpression(context);
1457 failIfFalse(expr, "Cannot parse 'with' subject expression");
1458 recordPauseLocation(context.breakpointLocation(expr));
1459 JSTextPosition end = lastTokenEndPosition();
1460 int endLine = tokenLine();
1461 handleProductionOrFail(CLOSEPAREN, ")", "start", "subject of a 'with' statement");
1462 const Identifier* unused = 0;
1463 TreeStatement statement = parseStatement(context, unused);
1464 failIfFalse(statement, "A 'with' statement must have a body");
1466 return context.createWithStatement(location, expr, statement, start, end, startLine, endLine);
1469 template <typename LexerType>
1470 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseSwitchStatement(TreeBuilder& context)
1472 ASSERT(match(SWITCH));
1473 JSTokenLocation location(tokenLocation());
1474 int startLine = tokenLine();
1476 handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'switch'");
1477 TreeExpression expr = parseExpression(context);
1478 failIfFalse(expr, "Cannot parse switch subject expression");
1479 recordPauseLocation(context.breakpointLocation(expr));
1480 int endLine = tokenLine();
1482 handleProductionOrFail(CLOSEPAREN, ")", "end", "subject of a 'switch'");
1483 handleProductionOrFail(OPENBRACE, "{", "start", "body of a 'switch'");
1484 AutoPopScopeRef lexicalScope(this, pushScope());
1485 lexicalScope->setIsLexicalScope();
1486 lexicalScope->preventVarDeclarations();
1488 TreeClauseList firstClauses = parseSwitchClauses(context);
1491 TreeClause defaultClause = parseSwitchDefaultClause(context);
1494 TreeClauseList secondClauses = parseSwitchClauses(context);
1497 handleProductionOrFail(CLOSEBRACE, "}", "end", "body of a 'switch'");
1499 TreeStatement result = context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine, lexicalScope->finalizeLexicalEnvironment(), lexicalScope->takeFunctionDeclarations());
1500 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1504 template <typename LexerType>
1505 template <class TreeBuilder> TreeClauseList Parser<LexerType>::parseSwitchClauses(TreeBuilder& context)
1509 unsigned startOffset = tokenStart();
1511 TreeExpression condition = parseExpression(context);
1512 failIfFalse(condition, "Cannot parse switch clause");
1513 consumeOrFail(COLON, "Expected a ':' after switch clause expression");
1514 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1515 failIfFalse(statements, "Cannot parse the body of a switch clause");
1516 TreeClause clause = context.createClause(condition, statements);
1517 context.setStartOffset(clause, startOffset);
1518 TreeClauseList clauseList = context.createClauseList(clause);
1519 TreeClauseList tail = clauseList;
1521 while (match(CASE)) {
1522 startOffset = tokenStart();
1524 TreeExpression condition = parseExpression(context);
1525 failIfFalse(condition, "Cannot parse switch case expression");
1526 consumeOrFail(COLON, "Expected a ':' after switch clause expression");
1527 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1528 failIfFalse(statements, "Cannot parse the body of a switch clause");
1529 clause = context.createClause(condition, statements);
1530 context.setStartOffset(clause, startOffset);
1531 tail = context.createClauseList(tail, clause);
1536 template <typename LexerType>
1537 template <class TreeBuilder> TreeClause Parser<LexerType>::parseSwitchDefaultClause(TreeBuilder& context)
1539 if (!match(DEFAULT))
1541 unsigned startOffset = tokenStart();
1543 consumeOrFail(COLON, "Expected a ':' after switch default clause");
1544 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1545 failIfFalse(statements, "Cannot parse the body of a switch default clause");
1546 TreeClause result = context.createClause(0, statements);
1547 context.setStartOffset(result, startOffset);
1551 template <typename LexerType>
1552 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(TreeBuilder& context)
1555 JSTokenLocation location(tokenLocation());
1556 TreeStatement tryBlock = 0;
1557 TreeDestructuringPattern catchPattern = 0;
1558 TreeStatement catchBlock = 0;
1559 TreeStatement finallyBlock = 0;
1560 int firstLine = tokenLine();
1562 matchOrFail(OPENBRACE, "Expected a block statement as body of a try statement");
1564 tryBlock = parseBlockStatement(context);
1565 failIfFalse(tryBlock, "Cannot parse the body of try block");
1566 int lastLine = m_lastTokenEndPosition.line;
1567 VariableEnvironment catchEnvironment;
1571 handleProductionOrFail(OPENPAREN, "(", "start", "'catch' target");
1572 AutoPopScopeRef catchScope(this, pushScope());
1573 catchScope->setIsLexicalScope();
1574 catchScope->preventVarDeclarations();
1575 const Identifier* ident = nullptr;
1576 if (matchSpecIdentifier()) {
1577 ident = m_token.m_data.ident;
1578 catchPattern = context.createBindingLocation(m_token.m_location, *ident, m_token.m_startPosition, m_token.m_endPosition, AssignmentContext::DeclarationStatement);
1580 failIfTrueIfStrict(catchScope->declareLexicalVariable(ident, false) & DeclarationResult::InvalidStrictMode, "Cannot declare a catch variable named '", ident->impl(), "' in strict mode");
1582 catchPattern = parseDestructuringPattern(context, DestructuringKind::DestructureToCatchParameters, ExportType::NotExported);
1583 failIfFalse(catchPattern, "Cannot parse this destructuring pattern");
1585 handleProductionOrFail(CLOSEPAREN, ")", "end", "'catch' target");
1586 matchOrFail(OPENBRACE, "Expected exception handler to be a block statement");
1587 catchBlock = parseBlockStatement(context);
1588 failIfFalse(catchBlock, "Unable to parse 'catch' block");
1589 catchEnvironment = catchScope->finalizeLexicalEnvironment();
1590 RELEASE_ASSERT(!ident || (catchEnvironment.size() == 1 && catchEnvironment.contains(ident->impl())));
1591 popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo);
1594 if (match(FINALLY)) {
1596 matchOrFail(OPENBRACE, "Expected block statement for finally body");
1597 finallyBlock = parseBlockStatement(context);
1598 failIfFalse(finallyBlock, "Cannot parse finally body");
1600 failIfFalse(catchBlock || finallyBlock, "Try statements must have at least a catch or finally block");
1601 return context.createTryStatement(location, tryBlock, catchPattern, catchBlock, finallyBlock, firstLine, lastLine, catchEnvironment);
1604 template <typename LexerType>
1605 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDebuggerStatement(TreeBuilder& context)
1607 ASSERT(match(DEBUGGER));
1608 JSTokenLocation location(tokenLocation());
1609 int startLine = tokenLine();
1610 int endLine = startLine;
1612 if (match(SEMICOLON))
1613 startLine = tokenLine();
1614 failIfFalse(autoSemiColon(), "Debugger keyword must be followed by a ';'");
1615 return context.createDebugger(location, startLine, endLine);
1618 template <typename LexerType>
1619 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context)
1621 ASSERT(match(OPENBRACE));
1623 // We should treat the first block statement of the function (the body of the function) as the lexical
1624 // scope of the function itself, and not the lexical scope of a 'block' statement within the function.
1625 AutoCleanupLexicalScope lexicalScope;
1626 bool shouldPushLexicalScope = m_statementDepth > 0;
1627 if (shouldPushLexicalScope) {
1628 ScopeRef newScope = pushScope();
1629 newScope->setIsLexicalScope();
1630 newScope->preventVarDeclarations();
1631 lexicalScope.setIsValid(newScope, this);
1633 JSTokenLocation location(tokenLocation());
1634 int startOffset = m_token.m_data.offset;
1635 int start = tokenLine();
1636 VariableEnvironment emptyEnvironment;
1637 DeclarationStacks::FunctionStack emptyFunctionStack;
1639 if (match(CLOSEBRACE)) {
1640 int endOffset = m_token.m_data.offset;
1642 TreeStatement result = context.createBlockStatement(location, 0, start, m_lastTokenEndPosition.line, shouldPushLexicalScope ? currentScope()->finalizeLexicalEnvironment() : emptyEnvironment, shouldPushLexicalScope ? currentScope()->takeFunctionDeclarations() : WTFMove(emptyFunctionStack));
1643 context.setStartOffset(result, startOffset);
1644 context.setEndOffset(result, endOffset);
1645 if (shouldPushLexicalScope)
1646 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1649 TreeSourceElements subtree = parseSourceElements(context, DontCheckForStrictMode);
1650 failIfFalse(subtree, "Cannot parse the body of the block statement");
1651 matchOrFail(CLOSEBRACE, "Expected a closing '}' at the end of a block statement");
1652 int endOffset = m_token.m_data.offset;
1654 TreeStatement result = context.createBlockStatement(location, subtree, start, m_lastTokenEndPosition.line, shouldPushLexicalScope ? currentScope()->finalizeLexicalEnvironment() : emptyEnvironment, shouldPushLexicalScope ? currentScope()->takeFunctionDeclarations() : WTFMove(emptyFunctionStack));
1655 context.setStartOffset(result, startOffset);
1656 context.setEndOffset(result, endOffset);
1657 if (shouldPushLexicalScope)
1658 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1663 template <typename LexerType>
1664 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
1666 DepthManager statementDepth(&m_statementDepth);
1668 int nonTrivialExpressionCount = 0;
1669 failIfStackOverflow();
1670 TreeStatement result = 0;
1671 bool shouldSetEndOffset = true;
1672 bool shouldSetPauseLocation = false;
1673 bool parentAllowsFunctionDeclarationAsStatement = m_immediateParentAllowsFunctionDeclarationInStatement;
1674 m_immediateParentAllowsFunctionDeclarationInStatement = false;
1676 switch (m_token.m_type) {
1678 result = parseBlockStatement(context);
1679 shouldSetEndOffset = false;
1682 result = parseVariableDeclaration(context, DeclarationType::VarDeclaration);
1683 shouldSetPauseLocation = true;
1686 const bool isAsync = false;
1687 result = parseFunctionDeclarationStatement(context, isAsync, parentAllowsFunctionDeclarationAsStatement);
1691 JSTokenLocation location(tokenLocation());
1693 result = context.createEmptyStatement(location);
1694 shouldSetPauseLocation = true;
1698 result = parseIfStatement(context);
1701 result = parseDoWhileStatement(context);
1704 result = parseWhileStatement(context);
1707 result = parseForStatement(context);
1710 result = parseContinueStatement(context);
1711 shouldSetPauseLocation = true;
1714 result = parseBreakStatement(context);
1715 shouldSetPauseLocation = true;
1718 result = parseReturnStatement(context);
1719 shouldSetPauseLocation = true;
1722 result = parseWithStatement(context);
1725 result = parseSwitchStatement(context);
1728 result = parseThrowStatement(context);
1729 shouldSetPauseLocation = true;
1732 result = parseTryStatement(context);
1735 result = parseDebuggerStatement(context);
1736 shouldSetPauseLocation = true;
1742 // These tokens imply the end of a set of source elements
1750 if (maybeParseAsyncFunctionDeclarationStatement(context, result, parentAllowsFunctionDeclarationAsStatement))
1757 bool allowFunctionDeclarationAsStatement = false;
1758 result = parseExpressionOrLabelStatement(context, allowFunctionDeclarationAsStatement);
1759 shouldSetPauseLocation = !context.shouldSkipPauseLocation(result);
1763 directive = m_token.m_data.ident;
1764 if (directiveLiteralLength)
1765 *directiveLiteralLength = m_token.m_location.endOffset - m_token.m_location.startOffset;
1766 nonTrivialExpressionCount = m_parserState.nonTrivialExpressionCount;
1770 TreeStatement exprStatement = parseExpressionStatement(context);
1771 if (directive && nonTrivialExpressionCount != m_parserState.nonTrivialExpressionCount)
1772 directive = nullptr;
1773 result = exprStatement;
1774 shouldSetPauseLocation = true;
1779 if (shouldSetEndOffset)
1780 context.setEndOffset(result, m_lastTokenEndPosition.offset);
1781 if (shouldSetPauseLocation)
1782 recordPauseLocation(context.breakpointLocation(result));
1788 template <typename LexerType>
1789 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclarationStatement(TreeBuilder& context, bool isAsync, bool parentAllowsFunctionDeclarationAsStatement)
1791 semanticFailIfTrue(strictMode(), "Function declarations are only allowed inside blocks or switch statements in strict mode");
1792 failIfFalse(parentAllowsFunctionDeclarationAsStatement, "Function declarations are only allowed inside block statements or at the top level of a program");
1793 if (!currentScope()->isFunction() && !closestParentOrdinaryFunctionNonLexicalScope()->isEvalContext()) {
1794 // We only implement annex B.3.3 if we're in function mode or eval mode. Otherwise, we fall back
1795 // to hoisting behavior.
1796 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=155813
1797 DepthManager statementDepth(&m_statementDepth);
1798 m_statementDepth = 1;
1800 return parseAsyncFunctionDeclaration(context);
1801 return parseFunctionDeclaration(context);
1804 // Any function declaration that isn't in a block is a syntax error unless it's
1805 // in an if/else statement. If it's in an if/else statement, we will magically
1806 // treat it as if the if/else statement is inside a block statement.
1807 // to the very top like a "var". For example:
1809 // if (cond) function foo() { }
1811 // will be rewritten as:
1813 // if (cond) { function foo() { } }
1815 AutoPopScopeRef blockScope(this, pushScope());
1816 blockScope->setIsLexicalScope();
1817 blockScope->preventVarDeclarations();
1818 JSTokenLocation location(tokenLocation());
1819 int start = tokenLine();
1821 TreeStatement function = 0;
1823 function = parseFunctionDeclaration(context);
1825 function = parseAsyncFunctionDeclaration(context);
1827 failIfFalse(function, "Expected valid function statement after 'function' keyword");
1828 TreeSourceElements sourceElements = context.createSourceElements();
1829 context.appendStatement(sourceElements, function);
1830 TreeStatement result = context.createBlockStatement(location, sourceElements, start, m_lastTokenEndPosition.line, currentScope()->finalizeLexicalEnvironment(), currentScope()->takeFunctionDeclarations());
1831 popScope(blockScope, TreeBuilder::NeedsFreeVariableInfo);
1835 template <typename LexerType>
1836 template <class TreeBuilder> bool Parser<LexerType>::maybeParseAsyncFunctionDeclarationStatement(TreeBuilder& context, TreeStatement& result, bool parentAllowsFunctionDeclarationAsStatement)
1838 ASSERT(match(ASYNC));
1839 SavePoint savePoint = createSavePoint();
1841 if (match(FUNCTION) && !m_lexer->prevTerminator()) {
1842 const bool isAsync = true;
1843 result = parseFunctionDeclarationStatement(context, isAsync, parentAllowsFunctionDeclarationAsStatement);
1846 restoreSavePoint(savePoint);
1850 template <typename LexerType>
1851 template <class TreeBuilder> bool Parser<LexerType>::parseFormalParameters(TreeBuilder& context, TreeFormalParameterList list, bool isArrowFunction, bool isMethod, unsigned& parameterCount)
1853 #define failIfDuplicateIfViolation() \
1854 if (duplicateParameter) {\
1855 semanticFailIfTrue(hasDefaultParameterValues, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with default parameter values");\
1856 semanticFailIfTrue(hasDestructuringPattern, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with destructuring parameters");\
1857 semanticFailIfTrue(isRestParameter, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with a rest parameter");\
1858 semanticFailIfTrue(isArrowFunction, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in an arrow function");\
1859 semanticFailIfTrue(isMethod, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in a method");\
1862 bool hasDefaultParameterValues = false;
1863 bool hasDestructuringPattern = false;
1864 bool isRestParameter = false;
1865 const Identifier* duplicateParameter = nullptr;
1866 unsigned restParameterStart = 0;
1868 TreeDestructuringPattern parameter = 0;
1869 TreeExpression defaultValue = 0;
1871 if (UNLIKELY(match(CLOSEPAREN)))
1874 if (match(DOTDOTDOT)) {
1876 semanticFailIfTrue(!m_parserState.allowAwait && match(AWAIT), "Cannot use 'await' as a parameter name in an async function");
1877 TreeDestructuringPattern destructuringPattern = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported, &duplicateParameter, &hasDestructuringPattern);
1879 parameter = context.createRestParameter(destructuringPattern, restParameterStart);
1880 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.
1881 isRestParameter = true;
1883 parameter = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported, &duplicateParameter, &hasDestructuringPattern);
1884 failIfFalse(parameter, "Cannot parse parameter pattern");
1885 if (!isRestParameter) {
1886 defaultValue = parseDefaultValueForDestructuringPattern(context);
1888 hasDefaultParameterValues = true;
1891 failIfDuplicateIfViolation();
1892 if (isRestParameter || defaultValue || hasDestructuringPattern)
1893 currentScope()->setHasNonSimpleParameterList();
1894 context.appendParameter(list, parameter, defaultValue);
1895 if (!isRestParameter) {
1896 restParameterStart++;
1897 if (!hasDefaultParameterValues)
1900 } while (!isRestParameter && consume(COMMA));
1903 #undef failIfDuplicateIfViolation
1906 template <typename LexerType>
1907 template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(
1908 TreeBuilder& context, SyntaxChecker& syntaxChecker, const JSTokenLocation& startLocation, int startColumn, int functionKeywordStart, int functionNameStart, int parametersStart,
1909 ConstructorKind constructorKind, SuperBinding superBinding, FunctionBodyType bodyType, unsigned parameterCount, SourceParseMode parseMode)
1911 bool isArrowFunctionBodyExpression = bodyType == ArrowFunctionBodyExpression;
1912 if (!isArrowFunctionBodyExpression) {
1914 if (match(CLOSEBRACE)) {
1915 unsigned endColumn = tokenColumn();
1916 SuperBinding functionSuperBinding = adjustSuperBindingForBaseConstructor(constructorKind, superBinding, currentScope());
1917 return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, functionSuperBinding, parameterCount, parseMode, isArrowFunctionBodyExpression);
1921 DepthManager statementDepth(&m_statementDepth);
1922 m_statementDepth = 0;
1923 if (bodyType == ArrowFunctionBodyExpression) {
1924 if (m_debuggerParseData)
1925 failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(context), "Cannot parse body of this arrow function");
1927 failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(syntaxChecker), "Cannot parse body of this arrow function");
1929 if (m_debuggerParseData)
1930 failIfFalse(parseSourceElements(context, CheckForStrictMode), bodyType == StandardFunctionBodyBlock ? "Cannot parse body of this function" : "Cannot parse body of this arrow function");
1932 failIfFalse(parseSourceElements(syntaxChecker, CheckForStrictMode), bodyType == StandardFunctionBodyBlock ? "Cannot parse body of this function" : "Cannot parse body of this arrow function");
1934 unsigned endColumn = tokenColumn();
1935 SuperBinding functionSuperBinding = adjustSuperBindingForBaseConstructor(constructorKind, superBinding, currentScope());
1936 return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, functionSuperBinding, parameterCount, parseMode, isArrowFunctionBodyExpression);
1939 static const char* stringForFunctionMode(SourceParseMode mode)
1942 case SourceParseMode::GetterMode:
1944 case SourceParseMode::SetterMode:
1946 case SourceParseMode::NormalFunctionMode:
1948 case SourceParseMode::MethodMode:
1950 case SourceParseMode::GeneratorBodyMode:
1952 case SourceParseMode::GeneratorWrapperFunctionMode:
1953 case SourceParseMode::GeneratorWrapperMethodMode:
1954 return "generator function";
1955 case SourceParseMode::ArrowFunctionMode:
1956 return "arrow function";
1957 case SourceParseMode::AsyncFunctionMode:
1958 case SourceParseMode::AsyncFunctionBodyMode:
1959 return "async function";
1960 case SourceParseMode::AsyncMethodMode:
1961 return "async method";
1962 case SourceParseMode::AsyncArrowFunctionBodyMode:
1963 case SourceParseMode::AsyncArrowFunctionMode:
1964 return "async arrow function";
1965 case SourceParseMode::ProgramMode:
1966 case SourceParseMode::ModuleAnalyzeMode:
1967 case SourceParseMode::ModuleEvaluateMode:
1968 RELEASE_ASSERT_NOT_REACHED();
1971 RELEASE_ASSERT_NOT_REACHED();
1975 template <typename LexerType> template <class TreeBuilder, class FunctionInfoType> typename TreeBuilder::FormalParameterList Parser<LexerType>::parseFunctionParameters(TreeBuilder& context, SourceParseMode mode, FunctionInfoType& functionInfo)
1977 RELEASE_ASSERT(!(SourceParseModeSet(SourceParseMode::ProgramMode, SourceParseMode::ModuleAnalyzeMode, SourceParseMode::ModuleEvaluateMode).contains(mode)));
1978 TreeFormalParameterList parameterList = context.createFormalParameterList();
1979 SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_parserState.functionParsePhase, FunctionParsePhase::Parameters);
1981 if (UNLIKELY((SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode).contains(mode)))) {
1982 if (!matchSpecIdentifier() && !match(OPENPAREN)) {
1983 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
1984 failWithMessage("Expected an arrow function input parameter");
1986 if (match(OPENPAREN)) {
1989 if (match(CLOSEPAREN)) {
1990 functionInfo.parameterCount = 0;
1992 bool isArrowFunction = true;
1993 bool isMethod = false;
1994 failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, isMethod, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
1997 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
1999 functionInfo.parameterCount = 1;
2000 auto parameter = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported);
2001 failIfFalse(parameter, "Cannot parse parameter pattern");
2002 context.appendParameter(parameterList, parameter, 0);
2006 return parameterList;
2009 if (!consume(OPENPAREN)) {
2010 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
2011 failWithMessage("Expected an opening '(' before a ", stringForFunctionMode(mode), "'s parameter list");
2014 if (mode == SourceParseMode::GetterMode) {
2015 consumeOrFail(CLOSEPAREN, "getter functions must have no parameters");
2016 functionInfo.parameterCount = 0;
2017 } else if (mode == SourceParseMode::SetterMode) {
2018 failIfTrue(match(CLOSEPAREN), "setter functions must have one parameter");
2019 const Identifier* duplicateParameter = nullptr;
2020 bool hasDestructuringPattern = false;
2021 auto parameter = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported, &duplicateParameter, &hasDestructuringPattern);
2022 failIfFalse(parameter, "setter functions must have one parameter");
2023 auto defaultValue = parseDefaultValueForDestructuringPattern(context);
2025 if (defaultValue || hasDestructuringPattern) {
2026 semanticFailIfTrue(duplicateParameter, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with non-simple parameter list");
2027 currentScope()->setHasNonSimpleParameterList();
2029 context.appendParameter(parameterList, parameter, defaultValue);
2030 functionInfo.parameterCount = defaultValue ? 0 : 1;
2031 failIfTrue(match(COMMA), "setter functions must have one parameter");
2032 consumeOrFail(CLOSEPAREN, "Expected a ')' after a parameter declaration");
2034 if (match(CLOSEPAREN)) {
2035 functionInfo.parameterCount = 0;
2037 bool isArrowFunction = false;
2038 bool isMethod = isMethodParseMode(mode);
2039 failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, isMethod, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
2041 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
2044 return parameterList;
2047 template <typename LexerType>
2048 template <class TreeBuilder> typename TreeBuilder::FormalParameterList Parser<LexerType>::createGeneratorParameters(TreeBuilder& context, unsigned& parameterCount)
2050 auto parameters = context.createFormalParameterList();
2052 JSTokenLocation location(tokenLocation());
2053 JSTextPosition position = tokenStartPosition();
2055 auto addParameter = [&](const Identifier& name) {
2056 declareParameter(&name);
2057 auto binding = context.createBindingLocation(location, name, position, position, AssignmentContext::DeclarationStatement);
2058 context.appendParameter(parameters, binding, 0);
2063 addParameter(m_vm->propertyNames->builtinNames().generatorPrivateName());
2065 addParameter(m_vm->propertyNames->builtinNames().generatorStatePrivateName());
2067 addParameter(m_vm->propertyNames->builtinNames().generatorValuePrivateName());
2068 // @generatorResumeMode
2069 addParameter(m_vm->propertyNames->builtinNames().generatorResumeModePrivateName());
2071 addParameter(m_vm->propertyNames->builtinNames().generatorFramePrivateName());
2076 template <typename LexerType>
2077 template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionNameRequirements requirements, SourceParseMode mode, bool nameIsInContainingScope, ConstructorKind constructorKind, SuperBinding expectedSuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>& functionInfo, FunctionDefinitionType functionDefinitionType)
2079 RELEASE_ASSERT(isFunctionParseMode(mode));
2081 ScopeRef parentScope = currentScope();
2083 bool isDisallowedAwaitFunctionName = isDisallowedIdentifierAwait(m_token);
2084 const char* isDisallowedAwaitFunctionNameReason = isDisallowedAwaitFunctionName ? disallowedIdentifierAwaitReason() : nullptr;
2086 AutoPopScopeRef functionScope(this, pushScope());
2087 functionScope->setSourceParseMode(mode);
2088 functionScope->setExpectedSuperBinding(expectedSuperBinding);
2089 functionScope->setConstructorKind(constructorKind);
2090 SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_parserState.functionParsePhase, FunctionParsePhase::Body);
2091 int functionNameStart = m_token.m_location.startOffset;
2092 const Identifier* lastFunctionName = m_parserState.lastFunctionName;
2093 m_parserState.lastFunctionName = nullptr;
2094 int parametersStart = -1;
2095 JSTokenLocation startLocation;
2096 int startColumn = -1;
2097 FunctionBodyType functionBodyType;
2099 auto loadCachedFunction = [&] () -> bool {
2100 if (UNLIKELY(!Options::useSourceProviderCache()))
2103 if (UNLIKELY(m_debuggerParseData))
2106 ASSERT(parametersStart != -1);
2107 ASSERT(startColumn != -1);
2109 // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
2110 if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(parametersStart) : 0) {
2111 // If we're in a strict context, the cached function info must say it was strict too.
2112 ASSERT(!strictMode() || cachedInfo->strictMode);
2113 JSTokenLocation endLocation;
2115 ConstructorKind constructorKind = static_cast<ConstructorKind>(cachedInfo->constructorKind);
2116 SuperBinding expectedSuperBinding = static_cast<SuperBinding>(cachedInfo->expectedSuperBinding);
2118 endLocation.line = cachedInfo->lastTokenLine;
2119 endLocation.startOffset = cachedInfo->lastTokenStartOffset;
2120 endLocation.lineStartOffset = cachedInfo->lastTokenLineStartOffset;
2121 ASSERT(endLocation.startOffset >= endLocation.lineStartOffset);
2123 bool endColumnIsOnStartLine = endLocation.line == functionInfo.startLine;
2124 unsigned currentLineStartOffset = m_lexer->currentLineStartOffset();
2125 unsigned bodyEndColumn = endColumnIsOnStartLine ? endLocation.startOffset - currentLineStartOffset : endLocation.startOffset - endLocation.lineStartOffset;
2127 ASSERT(endLocation.startOffset >= endLocation.lineStartOffset);
2129 FunctionBodyType functionBodyType;
2130 if (UNLIKELY(SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode).contains(mode)))
2131 functionBodyType = cachedInfo->isBodyArrowExpression ? ArrowFunctionBodyExpression : ArrowFunctionBodyBlock;
2133 functionBodyType = StandardFunctionBodyBlock;
2135 SuperBinding functionSuperBinding = adjustSuperBindingForBaseConstructor(constructorKind, expectedSuperBinding, cachedInfo->needsSuperBinding, cachedInfo->usesEval, cachedInfo->innerArrowFunctionFeatures);
2137 functionInfo.body = context.createFunctionMetadata(
2138 startLocation, endLocation, startColumn, bodyEndColumn,
2139 functionKeywordStart, functionNameStart, parametersStart,
2140 cachedInfo->strictMode, constructorKind, functionSuperBinding,
2141 cachedInfo->parameterCount,
2142 mode, functionBodyType == ArrowFunctionBodyExpression);
2143 functionInfo.endOffset = cachedInfo->endFunctionOffset;
2144 functionInfo.parameterCount = cachedInfo->parameterCount;
2146 functionScope->restoreFromSourceProviderCache(cachedInfo);
2147 popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo);
2149 m_token = cachedInfo->endFunctionToken();
2151 if (endColumnIsOnStartLine)
2152 m_token.m_location.lineStartOffset = currentLineStartOffset;
2154 m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset);
2155 m_lexer->setLineNumber(m_token.m_location.line);
2157 switch (functionBodyType) {
2158 case ArrowFunctionBodyExpression:
2160 context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
2162 case ArrowFunctionBodyBlock:
2163 case StandardFunctionBodyBlock:
2164 context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
2168 functionInfo.endLine = m_lastTokenEndPosition.line;
2175 SyntaxChecker syntaxChecker(const_cast<VM*>(m_vm), m_lexer.get());
2177 if (UNLIKELY((SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode).contains(mode)))) {
2178 startLocation = tokenLocation();
2179 functionInfo.startLine = tokenLine();
2180 startColumn = tokenColumn();
2182 parametersStart = m_token.m_location.startOffset;
2183 functionInfo.startOffset = parametersStart;
2184 functionInfo.parametersStartColumn = startColumn;
2186 if (loadCachedFunction())
2190 // Parse formal parameters with [+Yield] parameterization, in order to ban YieldExpressions
2191 // in ArrowFormalParameters, per ES6 #sec-arrow-function-definitions-static-semantics-early-errors.
2192 Scope::MaybeParseAsGeneratorForScope parseAsGenerator(functionScope, parentScope->isGenerator());
2193 SetForScope<bool> overrideAllowAwait(m_parserState.allowAwait, !isAsyncFunctionParseMode(mode));
2194 parseFunctionParameters(syntaxChecker, mode, functionInfo);
2198 matchOrFail(ARROWFUNCTION, "Expected a '=>' after arrow function parameter declaration");
2200 if (m_lexer->prevTerminator())
2201 failDueToUnexpectedToken();
2203 ASSERT(constructorKind == ConstructorKind::None);
2205 // Check if arrow body start with {. If it true it mean that arrow function is Fat arrow function
2206 // and we need use common approach to parse function body
2208 functionBodyType = match(OPENBRACE) ? ArrowFunctionBodyBlock : ArrowFunctionBodyExpression;
2210 // http://ecma-international.org/ecma-262/6.0/#sec-function-definitions
2211 // FunctionExpression :
2212 // function BindingIdentifieropt ( FormalParameters ) { FunctionBody }
2214 // FunctionDeclaration[Yield, Default] :
2215 // function BindingIdentifier[?Yield] ( FormalParameters ) { FunctionBody }
2216 // [+Default] function ( FormalParameters ) { FunctionBody }
2218 // GeneratorDeclaration[Yield, Default] :
2219 // function * BindingIdentifier[?Yield] ( FormalParameters[Yield] ) { GeneratorBody }
2220 // [+Default] function * ( FormalParameters[Yield] ) { GeneratorBody }
2222 // GeneratorExpression :
2223 // function * BindingIdentifier[Yield]opt ( FormalParameters[Yield] ) { GeneratorBody }
2225 // The name of FunctionExpression and AsyncFunctionExpression can accept "yield" even in the context of generator.
2226 bool upperScopeIsGenerator = false;
2227 if (!(functionDefinitionType == FunctionDefinitionType::Expression && SourceParseModeSet(SourceParseMode::NormalFunctionMode, SourceParseMode::AsyncFunctionMode).contains(mode)))
2228 upperScopeIsGenerator = upperScope(1)->isGenerator();
2230 if (requirements != FunctionNameRequirements::Unnamed) {
2231 ASSERT_WITH_MESSAGE(!(requirements == FunctionNameRequirements::None && !functionInfo.name), "When specifying FunctionNameRequirements::None, we need to initialize functionInfo.name with the default value in the caller side.");
2232 if (matchSpecIdentifier(upperScopeIsGenerator)) {
2233 functionInfo.name = m_token.m_data.ident;
2234 m_parserState.lastFunctionName = functionInfo.name;
2235 if (UNLIKELY(isDisallowedAwaitFunctionName))
2236 semanticFailIfTrue(functionDefinitionType == FunctionDefinitionType::Declaration || isAsyncFunctionWrapperParseMode(mode), "Cannot declare function named 'await' ", isDisallowedAwaitFunctionNameReason);
2237 else if (isAsyncFunctionWrapperParseMode(mode) && match(AWAIT) && functionDefinitionType == FunctionDefinitionType::Expression)
2238 semanticFail("Cannot declare async function named 'await'");
2239 else if (isGeneratorWrapperParseMode(mode) && match(YIELD) && functionDefinitionType == FunctionDefinitionType::Expression)
2240 semanticFail("Cannot declare generator function named 'yield'");
2242 if (!nameIsInContainingScope)
2243 failIfTrueIfStrict(functionScope->declareCallee(functionInfo.name) & DeclarationResult::InvalidStrictMode, "'", functionInfo.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode");
2244 } else if (requirements == FunctionNameRequirements::Named) {
2245 if (match(OPENPAREN)) {
2246 semanticFailIfTrue(mode == SourceParseMode::NormalFunctionMode, "Function statements must have a name");
2247 semanticFailIfTrue(mode == SourceParseMode::AsyncFunctionMode, "Async function statements must have a name");
2249 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
2250 failDueToUnexpectedToken();
2253 ASSERT(functionInfo.name);
2256 startLocation = tokenLocation();
2257 functionInfo.startLine = tokenLine();
2258 startColumn = tokenColumn();
2259 functionInfo.parametersStartColumn = startColumn;
2261 parametersStart = m_token.m_location.startOffset;
2262 functionInfo.startOffset = parametersStart;
2264 if (loadCachedFunction())
2267 SetForScope<bool> overrideAllowAwait(m_parserState.allowAwait, !isAsyncFunctionParseMode(mode));
2268 parseFunctionParameters(syntaxChecker, mode, functionInfo);
2272 matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body");
2274 // BytecodeGenerator emits code to throw TypeError when a class constructor is "call"ed.
2275 // Set ConstructorKind to None for non-constructor methods of classes.
2277 if (m_defaultConstructorKind != ConstructorKind::None) {
2278 constructorKind = m_defaultConstructorKind;
2279 expectedSuperBinding = m_defaultConstructorKind == ConstructorKind::Extends ? SuperBinding::Needed : SuperBinding::NotNeeded;
2282 functionBodyType = StandardFunctionBodyBlock;
2285 functionScope->setConstructorKind(constructorKind);
2286 functionScope->setExpectedSuperBinding(expectedSuperBinding);
2288 m_parserState.lastFunctionName = lastFunctionName;
2289 ParserState oldState = internalSaveParserState();
2291 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=156962
2292 // This loop collects the set of capture candidates that aren't
2293 // part of the set of this function's declared parameters. We will
2294 // figure out which parameters are captured for this function when
2295 // we actually generate code for it. For now, we just propagate to
2296 // our parent scopes which variables we might have closed over that
2297 // belong to them. This is necessary for correctness when using
2298 // the source provider cache because we can't close over a variable
2299 // that we don't claim to close over. The source provider cache must
2300 // know this information to properly cache this function.
2301 // This might work itself out nicer if we declared a different
2302 // Scope struct for the parameters (because they are indeed implemented
2303 // as their own scope).
2304 UniquedStringImplPtrSet nonLocalCapturesFromParameterExpressions;
2305 functionScope->forEachUsedVariable([&] (UniquedStringImpl* impl) {
2306 if (!functionScope->hasDeclaredParameter(impl)) {
2307 nonLocalCapturesFromParameterExpressions.add(impl);
2308 if (TreeBuilder::NeedsFreeVariableInfo)
2309 parentScope->addClosedVariableCandidateUnconditionally(impl);
2313 auto performParsingFunctionBody = [&] {
2314 return parseFunctionBody(context, syntaxChecker, startLocation, startColumn, functionKeywordStart, functionNameStart, parametersStart, constructorKind, expectedSuperBinding, functionBodyType, functionInfo.parameterCount, mode);
2317 if (isGeneratorOrAsyncFunctionWrapperParseMode(mode)) {
2318 AutoPopScopeRef generatorBodyScope(this, pushScope());
2319 SourceParseMode innerParseMode = SourceParseMode::GeneratorBodyMode;
2320 if (isAsyncFunctionWrapperParseMode(mode)) {
2321 innerParseMode = mode == SourceParseMode::AsyncArrowFunctionMode
2322 ? SourceParseMode::AsyncArrowFunctionBodyMode
2323 : SourceParseMode::AsyncFunctionBodyMode;
2325 generatorBodyScope->setSourceParseMode(innerParseMode);
2326 generatorBodyScope->setConstructorKind(ConstructorKind::None);
2327 generatorBodyScope->setExpectedSuperBinding(expectedSuperBinding);
2329 // Disallow 'use strict' directives in the implicit inner function if
2331 if (functionScope->hasNonSimpleParameterList())
2332 generatorBodyScope->setHasNonSimpleParameterList();
2334 functionInfo.body = performParsingFunctionBody();
2336 // When a generator has a "use strict" directive, a generator function wrapping it should be strict mode.
2337 if (generatorBodyScope->strictMode())
2338 functionScope->setStrictMode();
2340 popScope(generatorBodyScope, TreeBuilder::NeedsFreeVariableInfo);
2342 functionInfo.body = performParsingFunctionBody();
2344 restoreParserState(oldState);
2345 failIfFalse(functionInfo.body, "Cannot parse the body of this ", stringForFunctionMode(mode));
2346 context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
2347 if (functionScope->strictMode() && requirements != FunctionNameRequirements::Unnamed) {
2348 ASSERT(functionInfo.name);
2349 RELEASE_ASSERT(SourceParseModeSet(SourceParseMode::NormalFunctionMode, SourceParseMode::MethodMode, SourceParseMode::ArrowFunctionMode, SourceParseMode::GeneratorBodyMode, SourceParseMode::GeneratorWrapperFunctionMode).contains(mode) || isAsyncFunctionWrapperParseMode(mode));
2350 semanticFailIfTrue(m_vm->propertyNames->arguments == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
2351 semanticFailIfTrue(m_vm->propertyNames->eval == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
2354 JSTokenLocation location = JSTokenLocation(m_token.m_location);
2355 functionInfo.endOffset = m_token.m_data.offset;
2357 if (functionBodyType == ArrowFunctionBodyExpression) {
2358 location = locationBeforeLastToken();
2359 functionInfo.endOffset = location.endOffset;
2361 recordFunctionEntryLocation(JSTextPosition(startLocation.line, startLocation.startOffset, startLocation.lineStartOffset));
2362 recordFunctionLeaveLocation(JSTextPosition(location.line, location.startOffset, location.lineStartOffset));
2365 // Cache the tokenizer state and the function scope the first time the function is parsed.
2366 // Any future reparsing can then skip the function.
2367 // For arrow function is 8 = x=>x + 4 symbols;
2368 // For ordinary function is 16 = function(){} + 4 symbols
2369 const int minimumSourceLengthToCache = functionBodyType == StandardFunctionBodyBlock ? 16 : 8;
2370 std::unique_ptr<SourceProviderCacheItem> newInfo;
2371 int sourceLength = functionInfo.endOffset - functionInfo.startOffset;
2372 if (TreeBuilder::CanUseFunctionCache && m_functionCache && sourceLength > minimumSourceLengthToCache) {
2373 SourceProviderCacheItemCreationParameters parameters;
2374 parameters.endFunctionOffset = functionInfo.endOffset;
2375 parameters.functionNameStart = functionNameStart;
2376 parameters.lastTokenLine = location.line;
2377 parameters.lastTokenStartOffset = location.startOffset;
2378 parameters.lastTokenEndOffset = location.endOffset;
2379 parameters.lastTokenLineStartOffset = location.lineStartOffset;
2380 parameters.parameterCount = functionInfo.parameterCount;
2381 parameters.constructorKind = constructorKind;
2382 parameters.expectedSuperBinding = expectedSuperBinding;
2383 if (functionBodyType == ArrowFunctionBodyExpression) {
2384 parameters.isBodyArrowExpression = true;
2385 parameters.tokenType = m_token.m_type;
2387 functionScope->fillParametersForSourceProviderCache(parameters, nonLocalCapturesFromParameterExpressions);
2388 newInfo = SourceProviderCacheItem::create(parameters);
2391 popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo);
2393 if (functionBodyType != ArrowFunctionBodyExpression) {
2394 matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body");
2399 m_functionCache->add(functionInfo.startOffset, WTFMove(newInfo));
2401 functionInfo.endLine = m_lastTokenEndPosition.line;
2405 static NO_RETURN_DUE_TO_CRASH FunctionMetadataNode* getMetadata(ParserFunctionInfo<SyntaxChecker>&) { RELEASE_ASSERT_NOT_REACHED(); }
2406 static FunctionMetadataNode* getMetadata(ParserFunctionInfo<ASTBuilder>& info) { return info.body; }
2408 template <typename LexerType>
2409 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext)
2411 ASSERT(match(FUNCTION));
2412 JSTokenLocation location(tokenLocation());
2413 unsigned functionKeywordStart = tokenStart();
2415 SourceParseMode parseMode = SourceParseMode::NormalFunctionMode;
2417 parseMode = SourceParseMode::GeneratorWrapperFunctionMode;
2419 ParserFunctionInfo<TreeBuilder> functionInfo;
2420 FunctionNameRequirements requirements = FunctionNameRequirements::Named;
2421 if (declarationDefaultContext == DeclarationDefaultContext::ExportDefault) {
2422 // Under the "export default" context, function declaration does not require the function name.
2424 // ExportDeclaration:
2426 // export default HoistableDeclaration[~Yield, +Default]
2429 // HoistableDeclaration[Yield, Default]:
2430 // FunctionDeclaration[?Yield, ?Default]
2431 // GeneratorDeclaration[?Yield, ?Default]
2433 // FunctionDeclaration[Yield, Default]:
2435 // [+Default] function ( FormalParameters[~Yield] ) { FunctionBody[~Yield] }
2437 // GeneratorDeclaration[Yield, Default]:
2439 // [+Default] function * ( FormalParameters[+Yield] ) { GeneratorBody }
2441 // In this case, we use "*default*" as this function declaration's name.
2442 requirements = FunctionNameRequirements::None;
2443 functionInfo.name = &m_vm->propertyNames->builtinNames().starDefaultPrivateName();
2446 failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration)), "Cannot parse this function");
2447 ASSERT(functionInfo.name);
2449 std::pair<DeclarationResultMask, ScopeRef> functionDeclaration = declareFunction(functionInfo.name);
2450 DeclarationResultMask declarationResult = functionDeclaration.first;
2451 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a function named '", functionInfo.name->impl(), "' in strict mode");
2452 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
2453 internalFailWithMessage(false, "Cannot declare a function that shadows a let/const/class/function variable '", functionInfo.name->impl(), "' in strict mode");
2454 if (exportType == ExportType::Exported) {
2455 ASSERT_WITH_MESSAGE(declarationDefaultContext != DeclarationDefaultContext::ExportDefault, "Export default case will export the name and binding in the caller.");
2456 semanticFailIfFalse(exportName(*functionInfo.name), "Cannot export a duplicate function name: '", functionInfo.name->impl(), "'");
2457 m_moduleScopeData->exportBinding(*functionInfo.name);
2460 TreeStatement result = context.createFuncDeclStatement(location, functionInfo);
2461 if (TreeBuilder::CreatesAST)
2462 functionDeclaration.second->appendFunction(getMetadata(functionInfo));
2466 template <typename LexerType>
2467 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseAsyncFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext)
2469 ASSERT(match(FUNCTION));
2470 JSTokenLocation location(tokenLocation());
2471 unsigned functionKeywordStart = tokenStart();
2473 ParserFunctionInfo<TreeBuilder> functionInfo;
2474 SourceParseMode parseMode = SourceParseMode::AsyncFunctionMode;
2475 FunctionNameRequirements requirements = FunctionNameRequirements::Named;
2476 if (declarationDefaultContext == DeclarationDefaultContext::ExportDefault) {
2477 // Under the "export default" context, function declaration does not require the function name.
2479 // ExportDeclaration:
2481 // export default HoistableDeclaration[~Yield, +Default]
2484 // HoistableDeclaration[Yield, Default]:
2485 // FunctionDeclaration[?Yield, ?Default]
2486 // GeneratorDeclaration[?Yield, ?Default]
2488 // FunctionDeclaration[Yield, Default]:
2490 // [+Default] function ( FormalParameters[~Yield] ) { FunctionBody[~Yield] }
2492 // GeneratorDeclaration[Yield, Default]:
2494 // [+Default] function * ( FormalParameters[+Yield] ) { GeneratorBody }
2496 // In this case, we use "*default*" as this function declaration's name.
2497 requirements = FunctionNameRequirements::None;
2498 functionInfo.name = &m_vm->propertyNames->builtinNames().starDefaultPrivateName();
2501 failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration)), "Cannot parse this async function");
2502 failIfFalse(functionInfo.name, "Async function statements must have a name");
2504 std::pair<DeclarationResultMask, ScopeRef> functionDeclaration = declareFunction(functionInfo.name);
2505 DeclarationResultMask declarationResult = functionDeclaration.first;
2506 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare an async function named '", functionInfo.name->impl(), "' in strict mode");
2507 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
2508 internalFailWithMessage(false, "Cannot declare an async function that shadows a let/const/class/function variable '", functionInfo.name->impl(), "' in strict mode");
2509 if (exportType == ExportType::Exported) {
2510 semanticFailIfFalse(exportName(*functionInfo.name), "Cannot export a duplicate function name: '", functionInfo.name->impl(), "'");
2511 m_moduleScopeData->exportBinding(*functionInfo.name);
2514 TreeStatement result = context.createFuncDeclStatement(location, functionInfo);
2515 if (TreeBuilder::CreatesAST)
2516 functionDeclaration.second->appendFunction(getMetadata(functionInfo));
2520 template <typename LexerType>
2521 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseClassDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext)
2523 ASSERT(match(CLASSTOKEN));
2524 JSTokenLocation location(tokenLocation());
2525 JSTextPosition classStart = tokenStartPosition();
2526 unsigned classStartLine = tokenLine();
2528 ParserClassInfo<TreeBuilder> info;
2529 FunctionNameRequirements requirements = FunctionNameRequirements::Named;
2530 if (declarationDefaultContext == DeclarationDefaultContext::ExportDefault) {
2531 // Under the "export default" context, class declaration does not require the class name.
2533 // ExportDeclaration:
2535 // export default ClassDeclaration[~Yield, +Default]
2538 // ClassDeclaration[Yield, Default]:
2540 // [+Default] class ClassTail[?Yield]
2542 // In this case, we use "*default*" as this class declaration's name.
2543 requirements = FunctionNameRequirements::None;
2544 info.className = &m_vm->propertyNames->builtinNames().starDefaultPrivateName();
2547 TreeClassExpression classExpr = parseClass(context, requirements, info);
2548 failIfFalse(classExpr, "Failed to parse class");
2549 ASSERT(info.className);
2551 DeclarationResultMask declarationResult = declareVariable(info.className, DeclarationType::LetDeclaration);
2552 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
2553 internalFailWithMessage(false, "Cannot declare a class twice: '", info.className->impl(), "'");
2554 if (exportType == ExportType::Exported) {
2555 ASSERT_WITH_MESSAGE(declarationDefaultContext != DeclarationDefaultContext::ExportDefault, "Export default case will export the name and binding in the caller.");
2556 semanticFailIfFalse(exportName(*info.className), "Cannot export a duplicate class name: '", info.className->impl(), "'");
2557 m_moduleScopeData->exportBinding(*info.className);
2560 JSTextPosition classEnd = lastTokenEndPosition();
2561 unsigned classEndLine = tokenLine();
2563 return context.createClassDeclStatement(location, classExpr, classStart, classEnd, classStartLine, classEndLine);
2566 template <typename LexerType>
2567 template <class TreeBuilder> TreeClassExpression Parser<LexerType>::parseClass(TreeBuilder& context, FunctionNameRequirements requirements, ParserClassInfo<TreeBuilder>& info)
2569 ASSERT(match(CLASSTOKEN));
2570 JSTokenLocation location(tokenLocation());
2571 info.startLine = location.line;
2572 info.startColumn = tokenColumn();
2573 info.startOffset = location.startOffset;
2576 AutoPopScopeRef classScope(this, pushScope());
2577 classScope->setIsLexicalScope();
2578 classScope->preventVarDeclarations();
2579 classScope->setStrictMode();
2581 ASSERT_WITH_MESSAGE(requirements != FunctionNameRequirements::Unnamed, "Currently, there is no caller that uses FunctionNameRequirements::Unnamed for class syntax.");
2582 ASSERT_WITH_MESSAGE(!(requirements == FunctionNameRequirements::None && !info.className), "When specifying FunctionNameRequirements::None, we need to initialize info.className with the default value in the caller side.");
2584 info.className = m_token.m_data.ident;
2586 failIfTrue(classScope->declareLexicalVariable(info.className, true) & DeclarationResult::InvalidStrictMode, "'", info.className->impl(), "' is not a valid class name");
2587 } else if (requirements == FunctionNameRequirements::Named) {
2588 if (match(OPENBRACE))
2589 semanticFail("Class statements must have a name");
2590 semanticFailureDueToKeyword("class name");
2591 failDueToUnexpectedToken();
2593 ASSERT(info.className);
2595 TreeExpression parentClass = 0;
2596 if (consume(EXTENDS)) {
2597 parentClass = parseMemberExpression(context);
2598 failIfFalse(parentClass, "Cannot parse the parent class name");
2600 const ConstructorKind constructorKind = parentClass ? ConstructorKind::Extends : ConstructorKind::Base;
2602 consumeOrFail(OPENBRACE, "Expected opening '{' at the start of a class body");
2604 TreeExpression constructor = 0;
2605 TreePropertyList staticMethods = 0;
2606 TreePropertyList instanceMethods = 0;
2607 TreePropertyList instanceMethodsTail = 0;
2608 TreePropertyList staticMethodsTail = 0;
2609 while (!match(CLOSEBRACE)) {
2610 if (match(SEMICOLON)) {
2615 JSTokenLocation methodLocation(tokenLocation());
2616 unsigned methodStart = tokenStart();
2618 // For backwards compatibility, "static" is a non-reserved keyword in non-strict mode.
2619 bool isStaticMethod = false;
2620 if (match(RESERVED_IF_STRICT) && *m_token.m_data.ident == m_vm->propertyNames->staticKeyword) {
2621 SavePoint savePoint = createSavePoint();
2623 if (match(OPENPAREN)) {
2624 // Reparse "static()" as a method named "static".
2625 restoreSavePoint(savePoint);
2627 isStaticMethod = true;
2630 // FIXME: Figure out a way to share more code with parseProperty.
2631 const CommonIdentifiers& propertyNames = *m_vm->propertyNames;
2632 const Identifier* ident = &propertyNames.nullIdentifier;
2633 TreeExpression computedPropertyName = 0;
2634 bool isGetter = false;
2635 bool isSetter = false;
2636 bool isGenerator = false;
2637 bool isAsync = false;
2638 bool isAsyncMethod = false;
2643 switch (m_token.m_type) {
2646 ident = m_token.m_data.ident;
2651 isAsync = !isGenerator && !isAsyncMethod;
2655 ident = m_token.m_data.ident;
2658 if (!isGenerator && !isAsyncMethod && (matchIdentifierOrKeyword() || match(STRING) || match(DOUBLE) || match(INTEGER) || match(OPENBRACKET))) {
2659 isGetter = *ident == propertyNames.get;
2660 isSetter = *ident == propertyNames.set;
2662 if (UNLIKELY(isAsync && !m_lexer->prevTerminator())) {
2663 isAsyncMethod = true;
2670 ident = &m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), m_token.m_data.doubleValue);
2676 computedPropertyName = parseAssignmentExpression(context);
2677 failIfFalse(computedPropertyName, "Cannot parse computed property name");
2678 handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name");
2681 if (m_token.m_type & KeywordTokenFlag)
2683 failDueToUnexpectedToken();
2686 TreeProperty property;
2687 const bool alwaysStrictInsideClass = true;
2688 if (isGetter || isSetter) {
2689 bool isClassProperty = true;
2690 property = parseGetterSetter(context, alwaysStrictInsideClass, isGetter ? PropertyNode::Getter : PropertyNode::Setter,
2691 methodStart, ConstructorKind::None, isClassProperty, isStaticMethod);
2692 failIfFalse(property, "Cannot parse this method");
2694 ParserFunctionInfo<TreeBuilder> methodInfo;
2695 bool isConstructor = !isStaticMethod && *ident == propertyNames.constructor;
2696 SourceParseMode parseMode = SourceParseMode::MethodMode;
2697 if (isAsyncMethod) {
2698 isConstructor = false;
2699 parseMode = SourceParseMode::AsyncMethodMode;
2700 semanticFailIfTrue(*ident == m_vm->propertyNames->prototype, "Cannot declare an async method named 'prototype'");
2701 semanticFailIfTrue(*ident == m_vm->propertyNames->constructor, "Cannot declare an async method named 'constructor'");
2702 } else if (isGenerator) {
2703 isConstructor = false;
2704 parseMode = SourceParseMode::GeneratorWrapperMethodMode;
2705 semanticFailIfTrue(*ident == m_vm->propertyNames->prototype, "Cannot declare a generator named 'prototype'");
2706 semanticFailIfTrue(*ident == m_vm->propertyNames->constructor, "Cannot declare a generator named 'constructor'");
2708 methodInfo.name = isConstructor ? info.className : ident;
2709 failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::Unnamed, parseMode, false, isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, FunctionDefinitionType::Method)), "Cannot parse this method");
2711 TreeExpression method = context.createMethodDefinition(methodLocation, methodInfo);
2712 if (isConstructor) {
2713 semanticFailIfTrue(constructor, "Cannot declare multiple constructors in a single class");
2714 constructor = method;
2718 // FIXME: Syntax error when super() is called
2719 semanticFailIfTrue(isStaticMethod && methodInfo.name && *methodInfo.name == propertyNames.prototype,
2720 "Cannot declare a static method named 'prototype'");
2722 bool isClassProperty = true;
2723 if (computedPropertyName) {
2724 property = context.createProperty(computedPropertyName, method, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed),
2725 PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed, isClassProperty);
2727 property = context.createProperty(methodInfo.name, method, PropertyNode::Constant,
2728 PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed, InferName::Allowed, isClassProperty);
2732 TreePropertyList& tail = isStaticMethod ? staticMethodsTail : instanceMethodsTail;
2734 tail = context.createPropertyList(methodLocation, property, tail);
2736 tail = context.createPropertyList(methodLocation, property);
2738 staticMethods = tail;
2740 instanceMethods = tail;
2744 info.endOffset = tokenLocation().endOffset - 1;
2745 consumeOrFail(CLOSEBRACE, "Expected a closing '}' after a class body");
2747 auto classExpression = context.createClassExpr(location, info, classScope->finalizeLexicalEnvironment(), constructor, parentClass, instanceMethods, staticMethods);
2748 popScope(classScope, TreeBuilder::NeedsFreeVariableInfo);
2749 return classExpression;
2753 LabelInfo(const Identifier* ident, const JSTextPosition& start, const JSTextPosition& end)
2760 const Identifier* m_ident;
2761 JSTextPosition m_start;
2762 JSTextPosition m_end;
2765 template <typename LexerType>
2766 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrLabelStatement(TreeBuilder& context, bool allowFunctionDeclarationAsStatement)
2769 /* Expression and Label statements are ambiguous at LL(1), so we have a
2770 * special case that looks for a colon as the next character in the input.
2772 Vector<LabelInfo> labels;
2773 JSTokenLocation location;
2775 JSTextPosition start = tokenStartPosition();
2776 location = tokenLocation();
2777 if (!nextTokenIsColon()) {
2778 // If we hit this path we're making a expression statement, which
2779 // by definition can't make use of continue/break so we can just
2780 // ignore any labels we might have accumulated.
2781 TreeExpression expression = parseExpression(context);
2782 failIfFalse(expression, "Cannot parse expression statement");
2783 if (!autoSemiColon())
2784 failDueToUnexpectedToken();
2785 return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
2788 semanticFailIfTrue(isDisallowedIdentifierAwait(m_token), "Cannot use 'await' as a label ", disallowedIdentifierAwaitReason());
2789 semanticFailIfTrue(isDisallowedIdentifierYield(m_token), "Cannot use 'yield' as a label ", disallowedIdentifierYieldReason());
2791 const Identifier* ident = m_token.m_data.ident;
2792 JSTextPosition end = tokenEndPosition();
2794 consumeOrFail(COLON, "Labels must be followed by a ':'");
2795 if (!m_syntaxAlreadyValidated) {
2796 // This is O(N^2) over the current list of consecutive labels, but I
2797 // have never seen more than one label in a row in the real world.
2798 for (size_t i = 0; i < labels.size(); i++)
2799 failIfTrue(ident->impl() == labels[i].m_ident->impl(), "Attempted to redeclare the label '", ident->impl(), "'");
2800 failIfTrue(getLabel(ident), "Cannot find scope for the label '", ident->impl(), "'");
2801 labels.append(LabelInfo(ident, start, end));
2803 } while (matchSpecIdentifier());
2804 bool isLoop = false;
2805 switch (m_token.m_type) {
2815 const Identifier* unused = 0;
2816 ScopeRef labelScope = currentScope();
2817 if (!m_syntaxAlreadyValidated) {
2818 for (size_t i = 0; i < labels.size(); i++)
2819 pushLabel(labels[i].m_ident, isLoop);
2821 m_immediateParentAllowsFunctionDeclarationInStatement = allowFunctionDeclarationAsStatement;
2822 TreeStatement statement = parseStatement(context, unused);
2823 if (!m_syntaxAlreadyValidated) {
2824 for (size_t i = 0; i < labels.size(); i++)
2825 popLabel(labelScope);
2827 failIfFalse(statement, "Cannot parse statement");
2828 for (size_t i = 0; i < labels.size(); i++) {
2829 const LabelInfo& info = labels[labels.size() - i - 1];
2830 statement = context.createLabelStatement(location, info.m_ident, statement, info.m_start, info.m_end);
2835 template <typename LexerType>
2836 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionStatement(TreeBuilder& context)
2838 switch (m_token.m_type) {
2839 // Consult: http://www.ecma-international.org/ecma-262/6.0/index.html#sec-expression-statement
2840 // The ES6 spec mandates that we should fail from FUNCTION token here. We handle this case
2841 // in parseStatement() which is the only caller of parseExpressionStatement().
2842 // We actually allow FUNCTION in situations where it should not be allowed unless we're in strict mode.
2844 failWithMessage("'class' declaration is not directly within a block statement");
2847 // FIXME: when implementing 'let' we should fail when we see the token sequence "let [".
2848 // https://bugs.webkit.org/show_bug.cgi?id=142944
2851 JSTextPosition start = tokenStartPosition();
2852 JSTokenLocation location(tokenLocation());
2853 TreeExpression expression = parseExpression(context);
2854 failIfFalse(expression, "Cannot parse expression statement");
2855 failIfFalse(autoSemiColon(), "Parse error");
2856 return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
2859 template <typename LexerType>
2860 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(TreeBuilder& context)
2863 JSTokenLocation ifLocation(tokenLocation());
2864 int start = tokenLine();
2866 handleProductionOrFail2(OPENPAREN, "(", "start", "'if' condition");
2868 TreeExpression condition = parseExpression(context);
2869 failIfFalse(condition, "Expected a expression as the condition for an if statement");
2870 recordPauseLocation(context.breakpointLocation(condition));
2871 int end = tokenLine();
2872 handleProductionOrFail2(CLOSEPAREN, ")", "end", "'if' condition");
2874 const Identifier* unused = 0;
2875 m_immediateParentAllowsFunctionDeclarationInStatement = true;
2876 TreeStatement trueBlock = parseStatement(context, unused);
2877 failIfFalse(trueBlock, "Expected a statement as the body of an if block");
2880 return context.createIfStatement(ifLocation, condition, trueBlock, 0, start, end);
2882 Vector<TreeExpression> exprStack;
2883 Vector<std::pair<int, int>> posStack;
2884 Vector<JSTokenLocation> tokenLocationStack;
2885 Vector<TreeStatement> statementStack;
2886 bool trailingElse = false;
2888 JSTokenLocation tempLocation = tokenLocation();
2891 const Identifier* unused = 0;
2892 m_immediateParentAllowsFunctionDeclarationInStatement = true;
2893 TreeStatement block = parseStatement(context, unused);
2894 failIfFalse(block, "Expected a statement as the body of an else block");
2895 statementStack.append(block);
2896 trailingElse = true;
2899 int innerStart = tokenLine();
2902 handleProductionOrFail2(OPENPAREN, "(", "start", "'if' condition");
2904 TreeExpression innerCondition = parseExpression(context);
2905 failIfFalse(innerCondition, "Expected a expression as the condition for an if statement");
2906 recordPauseLocation(context.breakpointLocation(innerCondition));
2907 int innerEnd = tokenLine();
2908 handleProductionOrFail2(CLOSEPAREN, ")", "end", "'if' condition");
2909 const Identifier* unused = 0;
2910 m_immediateParentAllowsFunctionDeclarationInStatement = true;
2911 TreeStatement innerTrueBlock = parseStatement(context, unused);
2912 failIfFalse(innerTrueBlock, "Expected a statement as the body of an if block");
2913 tokenLocationStack.append(tempLocation);
2914 exprStack.append(innerCondition);
2915 posStack.append(std::make_pair(innerStart, innerEnd));
2916 statementStack.append(innerTrueBlock);
2917 } while (match(ELSE));
2919 if (!trailingElse) {
2920 TreeExpression condition = exprStack.last();
2921 exprStack.removeLast();
2922 TreeStatement trueBlock = statementStack.last();
2923 statementStack.removeLast();
2924 std::pair<int, int> pos = posStack.last();
2925 posStack.removeLast();
2926 JSTokenLocation elseLocation = tokenLocationStack.last();
2927 tokenLocationStack.removeLast();
2928 TreeStatement ifStatement = context.createIfStatement(elseLocation, condition, trueBlock, 0, pos.first, pos.second);
2929 context.setEndOffset(ifStatement, context.endOffset(trueBlock));
2930 statementStack.append(ifStatement);
2933 while (!exprStack.isEmpty()) {
2934 TreeExpression condition = exprStack.last();
2935 exprStack.removeLast();
2936 TreeStatement falseBlock = statementStack.last();
2937 statementStack.removeLast();
2938 TreeStatement trueBlock = statementStack.last();
2939 statementStack.removeLast();
2940 std::pair<int, int> pos = posStack.last();
2941 posStack.removeLast();
2942 JSTokenLocation elseLocation = tokenLocationStack.last();
2943 tokenLocationStack.removeLast();
2944 TreeStatement ifStatement = context.createIfStatement(elseLocation, condition, trueBlock, falseBlock, pos.first, pos.second);
2945 context.setEndOffset(ifStatement, context.endOffset(falseBlock));
2946 statementStack.append(ifStatement);
2949 return context.createIfStatement(ifLocation, condition, trueBlock, statementStack.last(), start, end);
2952 template <typename LexerType>
2953 template <class TreeBuilder> typename TreeBuilder::ModuleName Parser<LexerType>::parseModuleName(TreeBuilder& context)
2955 // ModuleName (ModuleSpecifier in the spec) represents the module name imported by the script.
2956 // http://www.ecma-international.org/ecma-262/6.0/#sec-imports
2957 // http://www.ecma-international.org/ecma-262/6.0/#sec-exports
2958 JSTokenLocation specifierLocation(tokenLocation());
2959 failIfFalse(match(STRING), "Imported modules names must be string literals");
2960 const Identifier* moduleName = m_token.m_data.ident;
2962 return context.createModuleName(specifierLocation, *moduleName);
2965 template <typename LexerType>
2966 template <class TreeBuilder> typename TreeBuilder::ImportSpecifier Parser<LexerType>::parseImportClauseItem(TreeBuilder& context, ImportSpecifierType specifierType)
2968 // Produced node is the item of the ImportClause.
2969 // That is the ImportSpecifier, ImportedDefaultBinding or NameSpaceImport.
2970 // http://www.ecma-international.org/ecma-262/6.0/#sec-imports
2971 JSTokenLocation specifierLocation(tokenLocation());
2972 JSToken localNameToken;
2973 const Identifier* importedName = nullptr;
2974 const Identifier* localName = nullptr;
2976 switch (specifierType) {
2977 case ImportSpecifierType::NamespaceImport: {
2978 // NameSpaceImport :
2979 // * as ImportedBinding
2982 ASSERT(match(TIMES));
2983 importedName = &m_vm->propertyNames->timesIdentifier;
2986 failIfFalse(matchContextualKeyword(m_vm->propertyNames->as), "Expected 'as' before imported binding name");
2989 failIfFalse(matchSpecIdentifier(), "Expected a variable name for the import declaration");
2990 localNameToken = m_token;
2991 localName = m_token.m_data.ident;
2996 case ImportSpecifierType::NamedImport: {
2997 // ImportSpecifier :
2999 // IdentifierName as ImportedBinding
3003 ASSERT(matchIdentifierOrKeyword());
3004 localNameToken = m_token;
3005 localName = m_token.m_data.ident;
3006 importedName = localName;
3009 if (matchContextualKeyword(m_vm->propertyNames->as)) {
3011 failIfFalse(matchSpecIdentifier(), "Expected a variable name for the import declaration");
3012 localNameToken = m_token;
3013 localName = m_token.m_data.ident;
3019 case ImportSpecifierType::DefaultImport: {
3020 // ImportedDefaultBinding :
3022 ASSERT(matchSpecIdentifier());
3023 localNameToken = m_token;
3024 localName = m_token.m_data.ident;
3025 importedName = &m_vm->propertyNames->defaultKeyword;
3031 semanticFailIfTrue(localNameToken.m_type == AWAIT, "Cannot use 'await' as an imported binding name");
3032 semanticFailIfTrue(localNameToken.m_type & KeywordTokenFlag, "Cannot use keyword as imported binding name");
3033 DeclarationResultMask declarationResult = declareVariable(localName, DeclarationType::ConstDeclaration, (specifierType == ImportSpecifierType::NamespaceImport) ? DeclarationImportType::ImportedNamespace : DeclarationImportType::Imported);
3034 if (declarationResult != DeclarationResult::Valid) {
3035 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare an imported binding named ", localName->impl(), " in strict mode");
3036 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
3037 internalFailWithMessage(false, "Cannot declare an imported binding name twice: '", localName->impl(), "'");
3040 return context.createImportSpecifier(specifierLocation, *importedName, *localName);
3043 template <typename LexerType>
3044 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseImportDeclaration(TreeBuilder& context)
3046 // http://www.ecma-international.org/ecma-262/6.0/#sec-imports
3047 ASSERT(match(IMPORT));
3048 JSTokenLocation importLocation(tokenLocation());
3051 auto specifierList = context.createImportSpecifierList();
3053 if (match(STRING)) {
3054 // import ModuleSpecifier ;
3055 auto moduleName = parseModuleName(context);
3056 failIfFalse(moduleName, "Cannot parse the module name");
3057 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted import declaration");
3058 return context.createImportDeclaration(importLocation, specifierList, moduleName);
3061 bool isFinishedParsingImport = false;
3062 if (matchSpecIdentifier()) {
3063 // ImportedDefaultBinding :
3065 auto specifier = parseImportClauseItem(context, ImportSpecifierType::DefaultImport);
3066 failIfFalse(specifier, "Cannot parse the default import");
3067 context.appendImportSpecifier(specifierList, specifier);
3071 isFinishedParsingImport = true;
3074 if (!isFinishedParsingImport) {
3076 // import NameSpaceImport FromClause ;
3077 auto specifier = parseImportClauseItem(context, ImportSpecifierType::NamespaceImport);
3078 failIfFalse(specifier, "Cannot parse the namespace import");
3079 context.appendImportSpecifier(specifierList, specifier);
3080 } else if (match(OPENBRACE)) {
3084 // { ImportsList , }
3087 while (!match(CLOSEBRACE)) {
3088 failIfFalse(matchIdentifierOrKeyword(), "Expected an imported name for the import declaration");
3089 auto specifier = parseImportClauseItem(context, ImportSpecifierType::NamedImport);
3090 failIfFalse(specifier, "Cannot parse the named import");
3091 context.appendImportSpecifier(specifierList, specifier);
3092 if (!consume(COMMA))
3095 handleProductionOrFail2(CLOSEBRACE, "}", "end", "import list");
3097 failWithMessage("Expected namespace import or import list");
3101 // from ModuleSpecifier
3103 failIfFalse(matchContextualKeyword(m_vm->propertyNames->from), "Expected 'from' before imported module name");
3106 auto moduleName = parseModuleName(context);
3107 failIfFalse(moduleName, "Cannot parse the module name");
3108 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted import declaration");
3110 return context.createImportDeclaration(importLocation, specifierList, moduleName);
3113 template <typename LexerType>
3114 template <class TreeBuilder> typename TreeBuilder::ExportSpecifier Parser<LexerType>::parseExportSpecifier(TreeBuilder& context, Vector<std::pair<const Identifier*, const Identifier*>>& maybeExportedLocalNames, bool& hasKeywordForLocalBindings)
3116 // ExportSpecifier :
3118 // IdentifierName as IdentifierName
3119 // http://www.ecma-international.org/ecma-262/6.0/#sec-exports
3120 ASSERT(matchIdentifierOrKeyword());
3121 JSTokenLocation specifierLocation(tokenLocation());
3122 if (m_token.m_type & KeywordTokenFlag)
3123 hasKeywordForLocalBindings = true;
3124 const Identifier* localName = m_token.m_data.ident;
3125 const Identifier* exportedName = localName;
3128 if (matchContextualKeyword(m_vm->propertyNames->as)) {
3130 failIfFalse(matchIdentifierOrKeyword(), "Expected an exported name for the export declaration");
3131 exportedName = m_token.m_data.ident;
3135 semanticFailIfFalse(exportName(*exportedName), "Cannot export a duplicate name '", exportedName->impl(), "'");
3136 maybeExportedLocalNames.append(std::make_pair(localName, exportedName));
3137 return context.createExportSpecifier(specifierLocation, *localName, *exportedName);
3140 template <typename LexerType>
3141 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExportDeclaration(TreeBuilder& context)
3143 // http://www.ecma-international.org/ecma-262/6.0/#sec-exports
3144 ASSERT(match(EXPORT));
3145 JSTokenLocation exportLocation(tokenLocation());
3148 switch (m_token.m_type) {
3150 // export * FromClause ;
3153 failIfFalse(matchContextualKeyword(m_vm->propertyNames->from), "Expected 'from' before exported module name");
3155 auto moduleName = parseModuleName(context);
3156 failIfFalse(moduleName, "Cannot parse the 'from' clause");
3157 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted export declaration");
3159 return context.createExportAllDeclaration(exportLocation, moduleName);
3163 // export default HoistableDeclaration[Default]
3164 // export default ClassDeclaration[Default]
3165 // export default [lookahead not-in {function, class}] AssignmentExpression[In] ;
3169 TreeStatement result = 0;
3170 bool isFunctionOrClassDeclaration = false;
3171 const Identifier* localName = nullptr;
3173 bool startsWithFunction = match(FUNCTION);
3174 if (startsWithFunction || match(CLASSTOKEN)) {
3175 SavePoint savePoint = createSavePoint();
3176 isFunctionOrClassDeclaration = true;
3180 if (startsWithFunction && match(TIMES))
3183 localName = m_token.m_data.ident;
3184 restoreSavePoint(savePoint);
3185 } else if (match(ASYNC)) {
3186 SavePoint savePoint = createSavePoint();
3188 if (match(FUNCTION) && !m_lexer->prevTerminator()) {
3191 localName = m_token.m_data.ident;
3192 isFunctionOrClassDeclaration = true;