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"
29 #include "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 (cond) internalFailWithMessage(false, __VA_ARGS__); } while (0)
54 #define semanticFailIfFalse(cond, ...) do { if (!(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 semanticFailureDueToKeyword(...) do { \
70 if (strictMode() && m_token.m_type == RESERVED_IF_STRICT) \
71 semanticFail("Cannot use the reserved word '", getToken(), "' as a ", __VA_ARGS__, " in strict mode"); \
72 if (m_token.m_type == RESERVED || m_token.m_type == RESERVED_IF_STRICT) \
73 semanticFail("Cannot use the reserved word '", getToken(), "' as a ", __VA_ARGS__); \
74 if (m_token.m_type & KeywordTokenFlag) \
75 semanticFail("Cannot use the keyword '", getToken(), "' as a ", __VA_ARGS__); \
76 if (isDisallowedIdentifierAwait(m_token)) \
77 semanticFail("Can't use 'await' as a ", __VA_ARGS__, " ", disallowedIdentifierAwaitReason()); \
84 template <typename LexerType>
85 void Parser<LexerType>::logError(bool)
89 StringPrintStream stream;
90 printUnexpectedTokenText(stream);
91 setErrorMessage(stream.toStringWithLatin1Fallback());
94 template <typename LexerType> template <typename A>
95 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1)
99 StringPrintStream stream;
100 if (shouldPrintToken) {
101 printUnexpectedTokenText(stream);
104 stream.print(value1, ".");
105 setErrorMessage(stream.toStringWithLatin1Fallback());
108 template <typename LexerType> template <typename A, typename B>
109 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2)
113 StringPrintStream stream;
114 if (shouldPrintToken) {
115 printUnexpectedTokenText(stream);
118 stream.print(value1, value2, ".");
119 setErrorMessage(stream.toStringWithLatin1Fallback());
122 template <typename LexerType> template <typename A, typename B, typename C>
123 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3)
127 StringPrintStream stream;
128 if (shouldPrintToken) {
129 printUnexpectedTokenText(stream);
132 stream.print(value1, value2, value3, ".");
133 setErrorMessage(stream.toStringWithLatin1Fallback());
136 template <typename LexerType> template <typename A, typename B, typename C, typename D>
137 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4)
141 StringPrintStream stream;
142 if (shouldPrintToken) {
143 printUnexpectedTokenText(stream);
146 stream.print(value1, value2, value3, value4, ".");
147 setErrorMessage(stream.toStringWithLatin1Fallback());
150 template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E>
151 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4, const E& value5)
155 StringPrintStream stream;
156 if (shouldPrintToken) {
157 printUnexpectedTokenText(stream);
160 stream.print(value1, value2, value3, value4, value5, ".");
161 setErrorMessage(stream.toStringWithLatin1Fallback());
164 template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E, typename F>
165 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4, const E& value5, const F& value6)
169 StringPrintStream stream;
170 if (shouldPrintToken) {
171 printUnexpectedTokenText(stream);
174 stream.print(value1, value2, value3, value4, value5, value6, ".");
175 setErrorMessage(stream.toStringWithLatin1Fallback());
178 template <typename LexerType> template <typename A, typename B, typename C, typename D, typename E, typename F, typename G>
179 void Parser<LexerType>::logError(bool shouldPrintToken, const A& value1, const B& value2, const C& value3, const D& value4, const E& value5, const F& value6, const G& value7)
183 StringPrintStream stream;
184 if (shouldPrintToken) {
185 printUnexpectedTokenText(stream);
188 stream.print(value1, value2, value3, value4, value5, value6, value7, ".");
189 setErrorMessage(stream.toStringWithLatin1Fallback());
192 template <typename LexerType>
193 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)
196 , m_hasStackOverflow(false)
198 , m_syntaxAlreadyValidated(source.provider()->isValid())
199 , m_statementDepth(0)
200 , m_sourceElements(0)
201 , m_parsingBuiltin(builtinMode == JSParserBuiltinMode::Builtin)
202 , m_scriptMode(scriptMode)
203 , m_superBinding(superBinding)
204 , m_defaultConstructorKind(defaultConstructorKind)
205 , m_immediateParentAllowsFunctionDeclarationInStatement(false)
206 , m_debuggerParseData(debuggerParseData)
208 m_lexer = std::make_unique<LexerType>(vm, builtinMode, scriptMode);
209 m_lexer->setCode(source, &m_parserArena);
210 m_token.m_location.line = source.firstLine();
211 m_token.m_location.startOffset = source.startOffset();
212 m_token.m_location.endOffset = source.startOffset();
213 m_token.m_location.lineStartOffset = source.startOffset();
214 m_functionCache = vm->addSourceProviderCache(source.provider());
215 m_expressionErrorClassifier = nullptr;
217 ScopeRef scope = pushScope();
218 scope->setSourceParseMode(parseMode);
219 scope->setIsEvalContext(isEvalContext);
221 scope->setEvalContextType(evalContextType);
223 if (derivedContextType == DerivedContextType::DerivedConstructorContext) {
224 scope->setConstructorKind(ConstructorKind::Extends);
225 scope->setExpectedSuperBinding(SuperBinding::Needed);
228 if (derivedContextType == DerivedContextType::DerivedMethodContext)
229 scope->setExpectedSuperBinding(SuperBinding::Needed);
231 if (strictMode == JSParserStrictMode::Strict)
232 scope->setStrictMode();
234 if (parseMode == SourceParseMode::ModuleAnalyzeMode || parseMode == SourceParseMode::ModuleEvaluateMode)
235 m_moduleScopeData = ModuleScopeData::create();
240 class Scope::MaybeParseAsGeneratorForScope : public SetForScope<bool> {
242 MaybeParseAsGeneratorForScope(ScopeRef& scope, bool shouldParseAsGenerator)
243 : SetForScope<bool>(scope->m_isGenerator, shouldParseAsGenerator) { }
246 template <typename LexerType>
247 Parser<LexerType>::~Parser()
251 template <typename LexerType>
252 String Parser<LexerType>::parseInner(const Identifier& calleeName, SourceParseMode parseMode)
254 String parseError = String();
256 ASTBuilder context(const_cast<VM*>(m_vm), m_parserArena, const_cast<SourceCode*>(m_source));
257 ScopeRef scope = currentScope();
258 scope->setIsLexicalScope();
259 SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_parserState.functionParsePhase, FunctionParsePhase::Body);
261 bool isArrowFunctionBodyExpression = parseMode == SourceParseMode::AsyncArrowFunctionBodyMode && !match(OPENBRACE);
262 if (m_lexer->isReparsingFunction()) {
263 ParserFunctionInfo<ASTBuilder> functionInfo;
264 if (SourceParseModeSet(SourceParseMode::GeneratorBodyMode).contains(parseMode) || isAsyncFunctionBodyParseMode(parseMode))
265 m_parameters = createGeneratorParameters(context, functionInfo.parameterCount);
267 m_parameters = parseFunctionParameters(context, parseMode, functionInfo);
269 if (SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode).contains(parseMode) && !hasError()) {
270 // The only way we could have an error wile reparsing is if we run out of stack space.
271 RELEASE_ASSERT(match(ARROWFUNCTION));
273 isArrowFunctionBodyExpression = !match(OPENBRACE);
277 if (!calleeName.isNull())
278 scope->declareCallee(&calleeName);
280 if (m_lexer->isReparsingFunction())
283 SourceElements* sourceElements = nullptr;
284 // The only way we can error this early is if we reparse a function and we run out of stack space.
286 if (isAsyncFunctionWrapperParseMode(parseMode))
287 sourceElements = parseAsyncFunctionSourceElements(context, parseMode, isArrowFunctionBodyExpression, CheckForStrictMode);
288 else if (isArrowFunctionBodyExpression)
289 sourceElements = parseArrowFunctionSingleExpressionBodySourceElements(context);
290 else if (isModuleParseMode(parseMode))
291 sourceElements = parseModuleSourceElements(context, parseMode);
292 else if (parseMode == SourceParseMode::GeneratorWrapperFunctionMode)
293 sourceElements = parseGeneratorFunctionSourceElements(context, CheckForStrictMode);
295 sourceElements = parseSourceElements(context, CheckForStrictMode);
298 bool validEnding = consume(EOFTOK);
299 if (!sourceElements || !validEnding) {
301 parseError = m_errorMessage;
303 parseError = ASCIILiteral("Parser error");
306 IdentifierSet capturedVariables;
307 UniquedStringImplPtrSet sloppyModeHoistedFunctions;
308 scope->getSloppyModeHoistedFunctions(sloppyModeHoistedFunctions);
309 scope->getCapturedVars(capturedVariables);
311 VariableEnvironment& varDeclarations = scope->declaredVariables();
312 for (auto& entry : capturedVariables)
313 varDeclarations.markVariableAsCaptured(entry);
315 if (SourceParseModeSet(SourceParseMode::GeneratorWrapperFunctionMode).contains(parseMode) || isAsyncFunctionWrapperParseMode(parseMode)) {
316 if (scope->usedVariablesContains(m_vm->propertyNames->arguments.impl()))
317 context.propagateArgumentsUse();
320 CodeFeatures features = context.features();
321 if (scope->strictMode())
322 features |= StrictModeFeature;
323 if (scope->shadowsArguments())
324 features |= ShadowsArgumentsFeature;
327 if (m_parsingBuiltin && isProgramParseMode(parseMode)) {
328 VariableEnvironment& lexicalVariables = scope->lexicalVariables();
329 const HashSet<UniquedStringImpl*>& closedVariableCandidates = scope->closedVariableCandidates();
330 for (UniquedStringImpl* candidate : closedVariableCandidates) {
331 if (!lexicalVariables.contains(candidate) && !varDeclarations.contains(candidate) && !candidate->isSymbol()) {
332 dataLog("Bad global capture in builtin: '", candidate, "'\n");
333 dataLog(m_source->view());
339 didFinishParsing(sourceElements, scope->takeFunctionDeclarations(), varDeclarations, WTFMove(sloppyModeHoistedFunctions), features, context.numConstants());
344 template <typename LexerType>
345 void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, DeclarationStacks::FunctionStack&& funcStack,
346 VariableEnvironment& varDeclarations, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, CodeFeatures features, int numConstants)
348 m_sourceElements = sourceElements;
349 m_funcDeclarations = WTFMove(funcStack);
350 m_varDeclarations.swap(varDeclarations);
351 m_features = features;
352 m_sloppyModeHoistedFunctions = WTFMove(sloppyModeHoistedFunctions);
353 m_numConstants = numConstants;
356 template <typename LexerType>
357 bool Parser<LexerType>::isArrowFunctionParameters()
359 if (match(OPENPAREN)) {
360 SavePoint saveArrowFunctionPoint = createSavePoint();
362 bool isArrowFunction = false;
363 if (match(CLOSEPAREN)) {
365 isArrowFunction = match(ARROWFUNCTION);
367 SyntaxChecker syntaxChecker(const_cast<VM*>(m_vm), m_lexer.get());
368 // We make fake scope, otherwise parseFormalParameters will add variable to current scope that lead to errors
369 AutoPopScopeRef fakeScope(this, pushScope());
370 fakeScope->setSourceParseMode(SourceParseMode::ArrowFunctionMode);
372 unsigned parametersCount = 0;
373 unsigned functionLength = 0;
374 bool isArrowFunctionParameterList = true;
375 isArrowFunction = parseFormalParameters(syntaxChecker, syntaxChecker.createFormalParameterList(), isArrowFunctionParameterList, parametersCount, functionLength) && consume(CLOSEPAREN) && match(ARROWFUNCTION);
377 popScope(fakeScope, syntaxChecker.NeedsFreeVariableInfo);
379 restoreSavePoint(saveArrowFunctionPoint);
380 return isArrowFunction;
383 if (matchSpecIdentifier()) {
384 SavePoint saveArrowFunctionPoint = createSavePoint();
386 bool isArrowFunction = match(ARROWFUNCTION);
387 restoreSavePoint(saveArrowFunctionPoint);
388 return isArrowFunction;
394 template <typename LexerType>
395 bool Parser<LexerType>::allowAutomaticSemicolon()
397 return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator();
400 template <typename LexerType>
401 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context, SourceElementsMode mode)
403 const unsigned lengthOfUseStrictLiteral = 12; // "use strict".length
404 TreeSourceElements sourceElements = context.createSourceElements();
405 const Identifier* directive = 0;
406 unsigned directiveLiteralLength = 0;
407 auto savePoint = createSavePoint();
408 bool shouldCheckForUseStrict = mode == CheckForStrictMode;
410 while (TreeStatement statement = parseStatementListItem(context, directive, &directiveLiteralLength)) {
411 if (shouldCheckForUseStrict) {
413 // "use strict" must be the exact literal without escape sequences or line continuation.
414 if (directiveLiteralLength == lengthOfUseStrictLiteral && m_vm->propertyNames->useStrictIdentifier == *directive) {
416 shouldCheckForUseStrict = false; // We saw "use strict", there is no need to keep checking for it.
417 if (!isValidStrictMode()) {
418 if (m_parserState.lastFunctionName) {
419 if (m_vm->propertyNames->arguments == *m_parserState.lastFunctionName)
420 semanticFail("Cannot name a function 'arguments' in strict mode");
421 if (m_vm->propertyNames->eval == *m_parserState.lastFunctionName)
422 semanticFail("Cannot name a function 'eval' in strict mode");
424 if (hasDeclaredVariable(m_vm->propertyNames->arguments))
425 semanticFail("Cannot declare a variable named 'arguments' in strict mode");
426 if (hasDeclaredVariable(m_vm->propertyNames->eval))
427 semanticFail("Cannot declare a variable named 'eval' in strict mode");
428 semanticFailIfTrue(currentScope()->hasNonSimpleParameterList(), "'use strict' directive not allowed inside a function with a non-simple parameter list");
429 semanticFailIfFalse(isValidStrictMode(), "Invalid parameters or function name in strict mode");
431 // Since strict mode is changed, restoring lexer state by calling next() may cause errors.
432 restoreSavePoint(savePoint);
437 // We saw a directive, but it wasn't "use strict". We reset our state to
438 // see if the next statement we parse is also a directive.
441 // We saw a statement that wasn't in the form of a directive. The spec says that "use strict"
442 // is only allowed as the first statement, or after a sequence of directives before it, but
443 // not after non-directive statements.
444 shouldCheckForUseStrict = false;
447 context.appendStatement(sourceElements, statement);
451 return sourceElements;
454 template <typename LexerType>
455 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseModuleSourceElements(TreeBuilder& context, SourceParseMode parseMode)
457 TreeSourceElements sourceElements = context.createSourceElements();
458 SyntaxChecker syntaxChecker(const_cast<VM*>(m_vm), m_lexer.get());
461 TreeStatement statement = 0;
463 statement = parseImportDeclaration(context);
465 recordPauseLocation(context.breakpointLocation(statement));
466 } else if (match(EXPORT)) {
467 statement = parseExportDeclaration(context);
469 recordPauseLocation(context.breakpointLocation(statement));
471 const Identifier* directive = 0;
472 unsigned directiveLiteralLength = 0;
473 if (parseMode == SourceParseMode::ModuleAnalyzeMode) {
474 if (!parseStatementListItem(syntaxChecker, directive, &directiveLiteralLength))
478 statement = parseStatementListItem(context, directive, &directiveLiteralLength);
483 context.appendStatement(sourceElements, statement);
488 for (const auto& pair : m_moduleScopeData->exportedBindings()) {
489 const auto& uid = pair.key;
490 if (currentScope()->hasDeclaredVariable(uid)) {
491 currentScope()->declaredVariables().markVariableAsExported(uid);
495 if (currentScope()->hasLexicallyDeclaredVariable(uid)) {
496 currentScope()->lexicalVariables().markVariableAsExported(uid);
500 semanticFail("Exported binding '", uid.get(), "' needs to refer to a top-level declared variable");
503 return sourceElements;
506 template <typename LexerType>
507 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseGeneratorFunctionSourceElements(TreeBuilder& context, SourceElementsMode mode)
509 auto sourceElements = context.createSourceElements();
511 unsigned functionKeywordStart = tokenStart();
512 JSTokenLocation startLocation(tokenLocation());
513 JSTextPosition start = tokenStartPosition();
514 unsigned startColumn = tokenColumn();
515 int functionNameStart = m_token.m_location.startOffset;
516 int parametersStart = m_token.m_location.startOffset;
518 ParserFunctionInfo<TreeBuilder> info;
519 info.name = &m_vm->propertyNames->nullIdentifier;
520 createGeneratorParameters(context, info.parameterCount);
521 info.startOffset = parametersStart;
522 info.startLine = tokenLine();
525 AutoPopScopeRef generatorBodyScope(this, pushScope());
526 generatorBodyScope->setSourceParseMode(SourceParseMode::GeneratorBodyMode);
527 generatorBodyScope->setConstructorKind(ConstructorKind::None);
528 generatorBodyScope->setExpectedSuperBinding(m_superBinding);
530 SyntaxChecker generatorFunctionContext(const_cast<VM*>(m_vm), m_lexer.get());
531 failIfFalse(parseSourceElements(generatorFunctionContext, mode), "Cannot parse the body of a generator");
532 popScope(generatorBodyScope, TreeBuilder::NeedsFreeVariableInfo);
534 info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, info.functionLength, SourceParseMode::GeneratorBodyMode, false);
536 info.endLine = tokenLine();
537 info.endOffset = m_token.m_data.offset;
538 info.parametersStartColumn = startColumn;
540 auto functionExpr = context.createFunctionExpr(startLocation, info);
541 auto statement = context.createExprStatement(startLocation, functionExpr, start, m_lastTokenEndPosition.line);
542 context.appendStatement(sourceElements, statement);
544 return sourceElements;
547 template <typename LexerType>
548 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseAsyncFunctionSourceElements(TreeBuilder& context, SourceParseMode parseMode, bool isArrowFunctionBodyExpression, SourceElementsMode mode)
550 ASSERT(isAsyncFunctionWrapperParseMode(parseMode));
551 auto sourceElements = context.createSourceElements();
553 unsigned functionKeywordStart = tokenStart();
554 JSTokenLocation startLocation(tokenLocation());
555 JSTextPosition start = tokenStartPosition();
556 unsigned startColumn = tokenColumn();
557 int functionNameStart = m_token.m_location.startOffset;
558 int parametersStart = m_token.m_location.startOffset;
560 ParserFunctionInfo<TreeBuilder> info;
561 info.name = &m_vm->propertyNames->nullIdentifier;
562 createGeneratorParameters(context, info.parameterCount);
563 info.startOffset = parametersStart;
564 info.startLine = tokenLine();
565 SourceParseMode innerParseMode = parseMode == SourceParseMode::AsyncArrowFunctionMode
566 ? SourceParseMode::AsyncArrowFunctionBodyMode
567 : SourceParseMode::AsyncFunctionBodyMode;
569 AutoPopScopeRef asyncFunctionBodyScope(this, pushScope());
570 asyncFunctionBodyScope->setSourceParseMode(innerParseMode);
571 SyntaxChecker asyncFunctionContext(const_cast<VM*>(m_vm), m_lexer.get());
572 if (isArrowFunctionBodyExpression)
573 failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(asyncFunctionContext), "Cannot parse the body of async arrow function");
575 failIfFalse(parseSourceElements(asyncFunctionContext, mode), "Cannot parse the body of async function");
576 popScope(asyncFunctionBodyScope, TreeBuilder::NeedsFreeVariableInfo);
578 info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, info.functionLength, innerParseMode, isArrowFunctionBodyExpression);
580 info.endLine = tokenLine();
581 info.endOffset = isArrowFunctionBodyExpression ? tokenLocation().endOffset : m_token.m_data.offset;
582 info.parametersStartColumn = startColumn;
584 auto functionExpr = context.createAsyncFunctionBody(startLocation, info, innerParseMode);
585 auto statement = context.createExprStatement(startLocation, functionExpr, start, m_lastTokenEndPosition.line);
586 context.appendStatement(sourceElements, statement);
588 return sourceElements;
591 template <typename LexerType>
592 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatementListItem(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
594 // The grammar is documented here:
595 // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-statements
596 DepthManager statementDepth(&m_statementDepth);
598 TreeStatement result = 0;
599 bool shouldSetEndOffset = true;
600 bool shouldSetPauseLocation = false;
602 switch (m_token.m_type) {
604 result = parseVariableDeclaration(context, DeclarationType::ConstDeclaration);
605 shouldSetPauseLocation = true;
608 bool shouldParseVariableDeclaration = true;
610 SavePoint savePoint = createSavePoint();
612 // Intentionally use `match(IDENT) || match(LET) || match(YIELD)` and don't use `matchSpecIdentifier()`.
613 // We would like to fall into parseVariableDeclaration path even if "yield" is not treated as an Identifier.
614 // For example, under a generator context, matchSpecIdentifier() for "yield" returns `false`.
615 // But we would like to enter parseVariableDeclaration and raise an error under the context of parseVariableDeclaration
616 // to raise consistent errors between "var", "const" and "let".
617 if (!(match(IDENT) || match(LET) || match(YIELD) || match(AWAIT)) && !match(OPENBRACE) && !match(OPENBRACKET))
618 shouldParseVariableDeclaration = false;
619 restoreSavePoint(savePoint);
621 if (shouldParseVariableDeclaration)
622 result = parseVariableDeclaration(context, DeclarationType::LetDeclaration);
624 bool allowFunctionDeclarationAsStatement = true;
625 result = parseExpressionOrLabelStatement(context, allowFunctionDeclarationAsStatement);
627 shouldSetPauseLocation = !context.shouldSkipPauseLocation(result);
631 result = parseClassDeclaration(context);
634 result = parseFunctionDeclaration(context);
637 #if ENABLE(ES2017_ASYNCFUNCTION_SYNTAX)
638 if (UNLIKELY(*m_token.m_data.ident == m_vm->propertyNames->async)) {
639 // Eagerly parse as AsyncFunctionDeclaration. This is the uncommon case,
640 // but could be mistakenly parsed as an AsyncFunctionExpression.
641 SavePoint savePoint = createSavePoint();
643 if (UNLIKELY(match(FUNCTION) && !m_lexer->prevTerminator())) {
644 result = parseAsyncFunctionDeclaration(context);
647 restoreSavePoint(savePoint);
653 // This is a convenient place to notice labeled statements
654 // (even though we also parse them as normal statements)
655 // because we allow the following type of code in sloppy mode:
656 // ``` function foo() { label: function bar() { } } ```
657 bool allowFunctionDeclarationAsStatement = true;
658 result = parseExpressionOrLabelStatement(context, allowFunctionDeclarationAsStatement);
659 shouldSetPauseLocation = !context.shouldSkipPauseLocation(result);
663 m_statementDepth--; // parseStatement() increments the depth.
664 result = parseStatement(context, directive, directiveLiteralLength);
665 shouldSetEndOffset = false;
670 if (shouldSetEndOffset)
671 context.setEndOffset(result, m_lastTokenEndPosition.offset);
672 if (shouldSetPauseLocation)
673 recordPauseLocation(context.breakpointLocation(result));
679 template <typename LexerType>
680 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVariableDeclaration(TreeBuilder& context, DeclarationType declarationType, ExportType exportType)
682 ASSERT(match(VAR) || match(LET) || match(CONSTTOKEN));
683 JSTokenLocation location(tokenLocation());
684 int start = tokenLine();
687 TreeDestructuringPattern scratch1 = 0;
688 TreeExpression scratch2 = 0;
689 JSTextPosition scratch3;
691 TreeExpression variableDecls = parseVariableDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3, VarDeclarationContext, declarationType, exportType, scratchBool);
693 failIfFalse(autoSemiColon(), "Expected ';' after variable declaration");
695 return context.createDeclarationStatement(location, variableDecls, start, end);
698 template <typename LexerType>
699 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDoWhileStatement(TreeBuilder& context)
702 int startLine = tokenLine();
704 const Identifier* unused = 0;
706 TreeStatement statement = parseStatement(context, unused);
708 failIfFalse(statement, "Expected a statement following 'do'");
709 int endLine = tokenLine();
710 JSTokenLocation location(tokenLocation());
711 handleProductionOrFail(WHILE, "while", "end", "do-while loop");
712 handleProductionOrFail(OPENPAREN, "(", "start", "do-while loop condition");
713 semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a do-while loop condition");
714 TreeExpression expr = parseExpression(context);
715 failIfFalse(expr, "Unable to parse do-while loop condition");
716 recordPauseLocation(context.breakpointLocation(expr));
717 handleProductionOrFail(CLOSEPAREN, ")", "end", "do-while loop condition");
718 if (match(SEMICOLON))
719 next(); // Always performs automatic semicolon insertion.
720 return context.createDoWhileStatement(location, statement, expr, startLine, endLine);
723 template <typename LexerType>
724 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWhileStatement(TreeBuilder& context)
726 ASSERT(match(WHILE));
727 JSTokenLocation location(tokenLocation());
728 int startLine = tokenLine();
731 handleProductionOrFail(OPENPAREN, "(", "start", "while loop condition");
732 semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a while loop condition");
733 TreeExpression expr = parseExpression(context);
734 failIfFalse(expr, "Unable to parse while loop condition");
735 recordPauseLocation(context.breakpointLocation(expr));
736 int endLine = tokenLine();
737 handleProductionOrFail(CLOSEPAREN, ")", "end", "while loop condition");
739 const Identifier* unused = 0;
741 TreeStatement statement = parseStatement(context, unused);
743 failIfFalse(statement, "Expected a statement as the body of a while loop");
744 return context.createWhileStatement(location, expr, statement, startLine, endLine);
747 template <typename LexerType>
748 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)
750 ASSERT(declarationType == DeclarationType::LetDeclaration || declarationType == DeclarationType::VarDeclaration || declarationType == DeclarationType::ConstDeclaration);
751 TreeExpression head = 0;
752 TreeExpression tail = 0;
753 const Identifier* lastIdent;
754 JSToken lastIdentToken;
755 AssignmentContext assignmentContext = assignmentContextFromDeclarationType(declarationType);
758 lastPattern = TreeDestructuringPattern(0);
759 JSTokenLocation location(tokenLocation());
761 TreeExpression node = 0;
763 bool hasInitializer = false;
764 if (matchSpecIdentifier()) {
765 failIfTrue(match(LET) && (declarationType == DeclarationType::LetDeclaration || declarationType == DeclarationType::ConstDeclaration),
766 "Can't use 'let' as an identifier name for a LexicalDeclaration");
767 semanticFailIfTrue(isDisallowedIdentifierAwait(m_token), "Can't use 'await' as a ", declarationTypeToVariableKind(declarationType), " ", disallowedIdentifierAwaitReason());
768 JSTextPosition varStart = tokenStartPosition();
769 JSTokenLocation varStartLocation(tokenLocation());
770 identStart = varStart;
771 const Identifier* name = m_token.m_data.ident;
773 lastIdentToken = m_token;
775 hasInitializer = match(EQUAL);
776 DeclarationResultMask declarationResult = declareVariable(name, declarationType);
777 if (declarationResult != DeclarationResult::Valid) {
778 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a variable named ", name->impl(), " in strict mode");
779 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration) {
780 if (declarationType == DeclarationType::LetDeclaration)
781 internalFailWithMessage(false, "Cannot declare a let variable twice: '", name->impl(), "'");
782 if (declarationType == DeclarationType::ConstDeclaration)
783 internalFailWithMessage(false, "Cannot declare a const variable twice: '", name->impl(), "'");
784 ASSERT(declarationType == DeclarationType::VarDeclaration);
785 internalFailWithMessage(false, "Cannot declare a var variable that shadows a let/const/class variable: '", name->impl(), "'");
788 if (exportType == ExportType::Exported) {
789 semanticFailIfFalse(exportName(*name), "Cannot export a duplicate name '", name->impl(), "'");
790 m_moduleScopeData->exportBinding(*name);
793 if (hasInitializer) {
794 JSTextPosition varDivot = tokenStartPosition() + 1;
795 initStart = tokenStartPosition();
796 next(TreeBuilder::DontBuildStrings); // consume '='
798 TreeExpression initializer = parseAssignmentExpression(context);
799 initEnd = lastTokenEndPosition();
800 lastInitializer = initializer;
801 failIfFalse(initializer, "Expected expression as the intializer for the variable '", name->impl(), "'");
803 node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEndPosition(), assignmentContext);
805 if (declarationListContext == ForLoopContext && declarationType == DeclarationType::ConstDeclaration)
806 forLoopConstDoesNotHaveInitializer = true;
807 failIfTrue(declarationListContext != ForLoopContext && declarationType == DeclarationType::ConstDeclaration, "const declared variable '", name->impl(), "'", " must have an initializer");
808 if (declarationType == DeclarationType::VarDeclaration)
809 node = context.createEmptyVarExpression(varStartLocation, *name);
811 node = context.createEmptyLetExpression(varStartLocation, *name);
815 auto pattern = parseDestructuringPattern(context, destructuringKindFromDeclarationType(declarationType), exportType, nullptr, nullptr, assignmentContext);
816 failIfFalse(pattern, "Cannot parse this destructuring pattern");
817 hasInitializer = match(EQUAL);
818 failIfTrue(declarationListContext == VarDeclarationContext && !hasInitializer, "Expected an initializer in destructuring variable declaration");
819 lastPattern = pattern;
820 if (hasInitializer) {
821 next(TreeBuilder::DontBuildStrings); // consume '='
822 TreeExpression rhs = parseAssignmentExpression(context);
825 node = context.createDestructuringAssignment(location, pattern, rhs);
826 lastInitializer = rhs;
834 head = context.createCommaExpr(location, head);
835 tail = context.appendToCommaExpr(location, head, head, node);
837 tail = context.appendToCommaExpr(location, head, tail, node);
839 } while (match(COMMA));
841 lastPattern = context.createBindingLocation(lastIdentToken.m_location, *lastIdent, lastIdentToken.m_startPosition, lastIdentToken.m_endPosition, assignmentContext);
846 template <typename LexerType>
847 bool Parser<LexerType>::declareRestOrNormalParameter(const Identifier& name, const Identifier** duplicateIdentifier)
849 DeclarationResultMask declarationResult = declareParameter(&name);
850 if ((declarationResult & DeclarationResult::InvalidStrictMode) && strictMode()) {
851 semanticFailIfTrue(isEvalOrArguments(&name), "Cannot destructure to a parameter name '", name.impl(), "' in strict mode");
852 if (m_parserState.lastFunctionName && name == *m_parserState.lastFunctionName)
853 semanticFail("Cannot declare a parameter named '", name.impl(), "' as it shadows the name of a strict mode function");
854 semanticFailureDueToKeyword("parameter name");
855 if (hasDeclaredParameter(name))
856 semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode as it has already been declared");
857 semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode");
859 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration) {
860 // It's not always an error to define a duplicate parameter.
861 // It's only an error when there are default parameter values or destructuring parameters.
862 // We note this value now so we can check it later.
863 if (duplicateIdentifier)
864 *duplicateIdentifier = &name;
870 template <typename LexerType>
871 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::createBindingPattern(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier& name, JSToken token, AssignmentContext bindingContext, const Identifier** duplicateIdentifier)
873 ASSERT(!name.isNull());
875 ASSERT(name.impl()->isAtomic() || name.impl()->isSymbol());
878 case DestructuringKind::DestructureToVariables: {
879 DeclarationResultMask declarationResult = declareVariable(&name);
880 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a variable named '", name.impl(), "' in strict mode");
881 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
882 internalFailWithMessage(false, "Cannot declare a var variable that shadows a let/const/class variable: '", name.impl(), "'");
886 case DestructuringKind::DestructureToLet:
887 case DestructuringKind::DestructureToConst:
888 case DestructuringKind::DestructureToCatchParameters: {
889 DeclarationResultMask declarationResult = declareVariable(&name, kind == DestructuringKind::DestructureToConst ? DeclarationType::ConstDeclaration : DeclarationType::LetDeclaration);
890 if (declarationResult != DeclarationResult::Valid) {
891 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot destructure to a variable named '", name.impl(), "' in strict mode");
892 failIfTrue(declarationResult & DeclarationResult::InvalidDuplicateDeclaration, "Cannot declare a lexical variable twice: '", name.impl(), "'");
897 case DestructuringKind::DestructureToParameters: {
898 declareRestOrNormalParameter(name, duplicateIdentifier);
903 case DestructuringKind::DestructureToExpressions: {
908 if (exportType == ExportType::Exported) {
909 semanticFailIfFalse(exportName(name), "Cannot export a duplicate name '", name.impl(), "'");
910 m_moduleScopeData->exportBinding(name);
912 return context.createBindingLocation(token.m_location, name, token.m_startPosition, token.m_endPosition, bindingContext);
915 template <typename LexerType>
916 template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern Parser<LexerType>::createAssignmentElement(TreeBuilder& context, TreeExpression& assignmentTarget, const JSTextPosition& startPosition, const JSTextPosition& endPosition)
918 return context.createAssignmentElement(assignmentTarget, startPosition, endPosition);
921 template <typename LexerType>
922 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseArrowFunctionSingleExpressionBodySourceElements(TreeBuilder& context)
924 ASSERT(!match(OPENBRACE));
926 JSTokenLocation location(tokenLocation());
927 JSTextPosition start = tokenStartPosition();
929 failIfStackOverflow();
930 TreeExpression expr = parseAssignmentExpression(context);
931 failIfFalse(expr, "Cannot parse the arrow function expression");
933 context.setEndOffset(expr, m_lastTokenEndPosition.offset);
935 JSTextPosition end = tokenEndPosition();
937 TreeSourceElements sourceElements = context.createSourceElements();
938 TreeStatement body = context.createReturnStatement(location, expr, start, end);
939 context.setEndOffset(body, m_lastTokenEndPosition.offset);
940 recordPauseLocation(context.breakpointLocation(body));
941 context.appendStatement(sourceElements, body);
943 return sourceElements;
946 template <typename LexerType>
947 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::tryParseDestructuringPatternExpression(TreeBuilder& context, AssignmentContext bindingContext)
949 return parseDestructuringPattern(context, DestructuringKind::DestructureToExpressions, ExportType::NotExported, nullptr, nullptr, bindingContext);
952 template <typename LexerType>
953 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseBindingOrAssignmentElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
955 if (kind == DestructuringKind::DestructureToExpressions)
956 return parseAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
957 return parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
960 template <typename LexerType>
961 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseAssignmentElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
963 TreeDestructuringPattern assignmentTarget = 0;
965 if (match(OPENBRACE) || match(OPENBRACKET)) {
966 SavePoint savePoint = createSavePoint();
967 assignmentTarget = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
968 if (assignmentTarget && !match(DOT) && !match(OPENBRACKET) && !match(OPENPAREN) && !match(TEMPLATE))
969 return assignmentTarget;
970 restoreSavePoint(savePoint);
973 JSTextPosition startPosition = tokenStartPosition();
974 auto element = parseMemberExpression(context);
976 semanticFailIfFalse(element && context.isAssignmentLocation(element), "Invalid destructuring assignment target");
978 if (strictMode() && m_parserState.lastIdentifier && context.isResolve(element)) {
979 bool isEvalOrArguments = m_vm->propertyNames->eval == *m_parserState.lastIdentifier || m_vm->propertyNames->arguments == *m_parserState.lastIdentifier;
980 failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", m_parserState.lastIdentifier->impl(), "' in strict mode");
983 return createAssignmentElement(context, element, startPosition, lastTokenEndPosition());
986 static const char* destructuringKindToVariableKindName(DestructuringKind kind)
989 case DestructuringKind::DestructureToLet:
990 case DestructuringKind::DestructureToConst:
991 return "lexical variable name";
992 case DestructuringKind::DestructureToVariables:
993 return "variable name";
994 case DestructuringKind::DestructureToParameters:
995 return "parameter name";
996 case DestructuringKind::DestructureToCatchParameters:
997 return "catch parameter name";
998 case DestructuringKind::DestructureToExpressions:
999 return "expression name";
1001 RELEASE_ASSERT_NOT_REACHED();
1005 template <typename LexerType>
1006 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseDestructuringPattern(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
1008 failIfStackOverflow();
1009 int nonLHSCount = m_parserState.nonLHSCount;
1010 TreeDestructuringPattern pattern;
1011 switch (m_token.m_type) {
1013 JSTextPosition divotStart = tokenStartPosition();
1014 auto arrayPattern = context.createArrayPattern(m_token.m_location);
1017 if (hasDestructuringPattern)
1018 *hasDestructuringPattern = true;
1020 bool restElementWasFound = false;
1023 while (match(COMMA)) {
1024 context.appendArrayPatternSkipEntry(arrayPattern, m_token.m_location);
1029 if (match(CLOSEBRACKET))
1032 if (UNLIKELY(match(DOTDOTDOT))) {
1033 JSTokenLocation location = m_token.m_location;
1035 auto innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
1036 if (kind == DestructuringKind::DestructureToExpressions && !innerPattern)
1038 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
1039 context.appendArrayPatternRestEntry(arrayPattern, location, innerPattern);
1040 restElementWasFound = true;
1044 JSTokenLocation location = m_token.m_location;
1045 auto innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
1046 if (kind == DestructuringKind::DestructureToExpressions && !innerPattern)
1048 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
1049 TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
1051 context.appendArrayPatternEntry(arrayPattern, location, innerPattern, defaultValue);
1052 } while (consume(COMMA));
1054 consumeOrFail(CLOSEBRACKET, restElementWasFound ? "Expected a closing ']' following a rest element destructuring pattern" : "Expected either a closing ']' or a ',' following an element destructuring pattern");
1055 context.finishArrayPattern(arrayPattern, divotStart, divotStart, lastTokenEndPosition());
1056 pattern = arrayPattern;
1060 auto objectPattern = context.createObjectPattern(m_token.m_location);
1063 if (hasDestructuringPattern)
1064 *hasDestructuringPattern = true;
1067 bool wasString = false;
1069 if (match(CLOSEBRACE))
1072 const Identifier* propertyName = nullptr;
1073 TreeExpression propertyExpression = 0;
1074 TreeDestructuringPattern innerPattern = 0;
1075 JSTokenLocation location = m_token.m_location;
1076 if (matchSpecIdentifier()) {
1077 failIfTrue(match(LET) && (kind == DestructuringKind::DestructureToLet || kind == DestructuringKind::DestructureToConst), "Can't use 'let' as an identifier name for a LexicalDeclaration");
1078 propertyName = m_token.m_data.ident;
1079 JSToken identifierToken = m_token;
1082 innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
1084 if (kind == DestructuringKind::DestructureToExpressions) {
1085 bool isEvalOrArguments = m_vm->propertyNames->eval == *propertyName || m_vm->propertyNames->arguments == *propertyName;
1086 if (isEvalOrArguments && strictMode())
1087 reclassifyExpressionError(ErrorIndicatesPattern, ErrorIndicatesNothing);
1088 failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", propertyName->impl(), "' in strict mode");
1090 semanticFailIfTrue(isDisallowedIdentifierAwait(identifierToken), "Can't use 'await' as a ", destructuringKindToVariableKindName(kind), " ", disallowedIdentifierAwaitReason());
1091 innerPattern = createBindingPattern(context, kind, exportType, *propertyName, identifierToken, bindingContext, duplicateIdentifier);
1094 JSTokenType tokenType = m_token.m_type;
1095 switch (m_token.m_type) {
1098 propertyName = &m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), m_token.m_data.doubleValue);
1101 propertyName = m_token.m_data.ident;
1106 propertyExpression = parseAssignmentExpression(context);
1107 failIfFalse(propertyExpression, "Cannot parse computed property name");
1108 matchOrFail(CLOSEBRACKET, "Expected ']' to end end a computed property name");
1111 if (m_token.m_type != RESERVED && m_token.m_type != RESERVED_IF_STRICT && !(m_token.m_type & KeywordTokenFlag)) {
1112 if (kind == DestructuringKind::DestructureToExpressions)
1114 failWithMessage("Expected a property name");
1116 propertyName = m_token.m_data.ident;
1120 if (!consume(COLON)) {
1121 if (kind == DestructuringKind::DestructureToExpressions)
1123 semanticFailIfTrue(tokenType == RESERVED, "Cannot use abbreviated destructuring syntax for reserved name '", propertyName->impl(), "'");
1124 semanticFailIfTrue(tokenType == RESERVED_IF_STRICT, "Cannot use abbreviated destructuring syntax for reserved name '", propertyName->impl(), "' in strict mode");
1125 semanticFailIfTrue(tokenType & KeywordTokenFlag, "Cannot use abbreviated destructuring syntax for keyword '", propertyName->impl(), "'");
1127 failWithMessage("Expected a ':' prior to a named destructuring property");
1129 innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
1131 if (kind == DestructuringKind::DestructureToExpressions && !innerPattern)
1133 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
1134 TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
1136 if (propertyExpression)
1137 context.appendObjectPatternEntry(objectPattern, location, propertyExpression, innerPattern, defaultValue);
1139 ASSERT(propertyName);
1140 context.appendObjectPatternEntry(objectPattern, location, wasString, *propertyName, innerPattern, defaultValue);
1142 } while (consume(COMMA));
1144 if (kind == DestructuringKind::DestructureToExpressions && !match(CLOSEBRACE))
1146 consumeOrFail(CLOSEBRACE, "Expected either a closing '}' or an ',' after a property destructuring pattern");
1147 pattern = objectPattern;
1152 if (!matchSpecIdentifier()) {
1153 if (kind == DestructuringKind::DestructureToExpressions)
1155 semanticFailureDueToKeyword(destructuringKindToVariableKindName(kind));
1156 failWithMessage("Expected a parameter pattern or a ')' in parameter list");
1158 failIfTrue(match(LET) && (kind == DestructuringKind::DestructureToLet || kind == DestructuringKind::DestructureToConst), "Can't use 'let' as an identifier name for a LexicalDeclaration");
1159 semanticFailIfTrue(isDisallowedIdentifierAwait(m_token), "Can't use 'await' as a ", destructuringKindToVariableKindName(kind), " ", disallowedIdentifierAwaitReason());
1160 pattern = createBindingPattern(context, kind, exportType, *m_token.m_data.ident, m_token, bindingContext, duplicateIdentifier);
1165 m_parserState.nonLHSCount = nonLHSCount;
1169 template <typename LexerType>
1170 template <class TreeBuilder> TreeExpression Parser<LexerType>::parseDefaultValueForDestructuringPattern(TreeBuilder& context)
1175 next(TreeBuilder::DontBuildStrings); // consume '='
1176 return parseAssignmentExpression(context);
1179 template <typename LexerType>
1180 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement(TreeBuilder& context)
1183 JSTokenLocation location(tokenLocation());
1184 int startLine = tokenLine();
1186 handleProductionOrFail(OPENPAREN, "(", "start", "for-loop header");
1187 int nonLHSCount = m_parserState.nonLHSCount;
1188 int declarations = 0;
1189 JSTokenLocation declLocation(tokenLocation());
1190 JSTextPosition declsStart;
1191 JSTextPosition declsEnd;
1192 TreeExpression decls = 0;
1193 TreeDestructuringPattern pattern = 0;
1194 bool isVarDeclaraton = match(VAR);
1195 bool isLetDeclaration = match(LET);
1196 bool isConstDeclaration = match(CONSTTOKEN);
1197 bool forLoopConstDoesNotHaveInitializer = false;
1199 VariableEnvironment dummySet;
1200 VariableEnvironment* lexicalVariables = nullptr;
1201 AutoCleanupLexicalScope lexicalScope;
1203 auto gatherLexicalVariablesIfNecessary = [&] {
1204 if (isLetDeclaration || isConstDeclaration) {
1205 ScopeRef scope = lexicalScope.scope();
1206 lexicalVariables = &scope->finalizeLexicalEnvironment();
1208 lexicalVariables = &dummySet;
1211 auto popLexicalScopeIfNecessary = [&] {
1212 if (isLetDeclaration || isConstDeclaration)
1213 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1216 if (isVarDeclaraton || isLetDeclaration || isConstDeclaration) {
1218 for (var/let/const IDENT in/of expression) statement
1219 for (var/let/const varDeclarationList; expressionOpt; expressionOpt)
1221 if (isLetDeclaration || isConstDeclaration) {
1222 ScopeRef newScope = pushScope();
1223 newScope->setIsLexicalScope();
1224 newScope->preventVarDeclarations();
1225 lexicalScope.setIsValid(newScope, this);
1228 TreeDestructuringPattern forInTarget = 0;
1229 TreeExpression forInInitializer = 0;
1231 JSTextPosition initStart;
1232 JSTextPosition initEnd;
1233 DeclarationType declarationType;
1234 if (isVarDeclaraton)
1235 declarationType = DeclarationType::VarDeclaration;
1236 else if (isLetDeclaration)
1237 declarationType = DeclarationType::LetDeclaration;
1238 else if (isConstDeclaration)
1239 declarationType = DeclarationType::ConstDeclaration;
1241 RELEASE_ASSERT_NOT_REACHED();
1242 decls = parseVariableDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd, ForLoopContext, declarationType, ExportType::NotExported, forLoopConstDoesNotHaveInitializer);
1246 // Remainder of a standard for loop is handled identically
1247 if (match(SEMICOLON))
1248 goto standardForLoop;
1250 failIfFalse(declarations == 1, "can only declare a single variable in an enumeration");
1252 // Handle for-in with var declaration
1253 JSTextPosition inLocation = tokenStartPosition();
1254 bool isOfEnumeration = false;
1255 if (!consume(INTOKEN)) {
1256 failIfFalse(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax");
1257 isOfEnumeration = true;
1260 bool hasAnyAssignments = !!forInInitializer;
1261 if (hasAnyAssignments) {
1262 if (isOfEnumeration)
1263 internalFailWithMessage(false, "Cannot assign to the loop variable inside a for-of loop header");
1264 if (strictMode() || (isLetDeclaration || isConstDeclaration) || !context.isBindingNode(forInTarget))
1265 internalFailWithMessage(false, "Cannot assign to the loop variable inside a for-in loop header");
1267 TreeExpression expr = parseExpression(context);
1268 failIfFalse(expr, "Expected expression to enumerate");
1269 recordPauseLocation(context.breakpointLocation(expr));
1270 JSTextPosition exprEnd = lastTokenEndPosition();
1272 int endLine = tokenLine();
1274 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
1276 const Identifier* unused = 0;
1278 TreeStatement statement = parseStatement(context, unused);
1280 failIfFalse(statement, "Expected statement as body of for-", isOfEnumeration ? "of" : "in", " statement");
1281 gatherLexicalVariablesIfNecessary();
1282 TreeStatement result;
1283 if (isOfEnumeration)
1284 result = context.createForOfLoop(location, forInTarget, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
1286 if (isVarDeclaraton && forInInitializer)
1287 result = context.createForInLoop(location, decls, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
1289 result = context.createForInLoop(location, forInTarget, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
1291 popLexicalScopeIfNecessary();
1295 if (!match(SEMICOLON)) {
1296 if (match(OPENBRACE) || match(OPENBRACKET)) {
1297 SavePoint savePoint = createSavePoint();
1298 declsStart = tokenStartPosition();
1299 pattern = tryParseDestructuringPatternExpression(context, AssignmentContext::DeclarationStatement);
1300 declsEnd = lastTokenEndPosition();
1301 if (pattern && (match(INTOKEN) || (match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of)))
1302 goto enumerationLoop;
1303 pattern = TreeDestructuringPattern(0);
1304 restoreSavePoint(savePoint);
1307 declsStart = tokenStartPosition();
1308 decls = parseExpression(context);
1309 declsEnd = lastTokenEndPosition();
1311 failIfFalse(decls, "Cannot parse for loop declarations");
1312 recordPauseLocation(context.breakpointLocation(decls));
1315 if (match(SEMICOLON)) {
1317 // Standard for loop
1319 recordPauseLocation(context.breakpointLocation(decls));
1321 TreeExpression condition = 0;
1322 failIfTrue(forLoopConstDoesNotHaveInitializer && isConstDeclaration, "const variables in for loops must have initializers");
1324 if (!match(SEMICOLON)) {
1325 condition = parseExpression(context);
1326 failIfFalse(condition, "Cannot parse for loop condition expression");
1327 recordPauseLocation(context.breakpointLocation(condition));
1329 consumeOrFail(SEMICOLON, "Expected a ';' after the for loop condition expression");
1331 TreeExpression increment = 0;
1332 if (!match(CLOSEPAREN)) {
1333 increment = parseExpression(context);
1334 failIfFalse(increment, "Cannot parse for loop iteration expression");
1335 recordPauseLocation(context.breakpointLocation(increment));
1337 int endLine = tokenLine();
1338 handleProductionOrFail(CLOSEPAREN, ")", "end", "for-loop header");
1339 const Identifier* unused = 0;
1341 TreeStatement statement = parseStatement(context, unused);
1343 failIfFalse(statement, "Expected a statement as the body of a for loop");
1344 gatherLexicalVariablesIfNecessary();
1345 TreeStatement result = context.createForLoop(location, decls, condition, increment, statement, startLine, endLine, *lexicalVariables);
1346 popLexicalScopeIfNecessary();
1350 // For-in and For-of loop
1352 failIfFalse(nonLHSCount == m_parserState.nonLHSCount, "Expected a reference on the left hand side of an enumeration statement");
1353 bool isOfEnumeration = false;
1354 if (!consume(INTOKEN)) {
1355 failIfFalse(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax");
1356 isOfEnumeration = true;
1359 TreeExpression expr = parseExpression(context);
1360 failIfFalse(expr, "Cannot parse subject for-", isOfEnumeration ? "of" : "in", " statement");
1361 recordPauseLocation(context.breakpointLocation(expr));
1362 JSTextPosition exprEnd = lastTokenEndPosition();
1363 int endLine = tokenLine();
1365 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
1366 const Identifier* unused = 0;
1368 TreeStatement statement = parseStatement(context, unused);
1370 failIfFalse(statement, "Expected a statement as the body of a for-", isOfEnumeration ? "of" : "in", "loop");
1371 gatherLexicalVariablesIfNecessary();
1372 TreeStatement result;
1375 if (isOfEnumeration)
1376 result = context.createForOfLoop(location, pattern, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1378 result = context.createForInLoop(location, pattern, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1380 popLexicalScopeIfNecessary();
1383 if (isOfEnumeration)
1384 result = context.createForOfLoop(location, decls, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1386 result = context.createForInLoop(location, decls, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1387 popLexicalScopeIfNecessary();
1391 template <typename LexerType>
1392 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatement(TreeBuilder& context)
1394 ASSERT(match(BREAK));
1395 JSTokenLocation location(tokenLocation());
1396 JSTextPosition start = tokenStartPosition();
1397 JSTextPosition end = tokenEndPosition();
1400 if (autoSemiColon()) {
1401 semanticFailIfFalse(breakIsValid(), "'break' is only valid inside a switch or loop statement");
1402 return context.createBreakStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
1404 failIfFalse(matchSpecIdentifier(), "Expected an identifier as the target for a break statement");
1405 const Identifier* ident = m_token.m_data.ident;
1406 semanticFailIfFalse(getLabel(ident), "Cannot use the undeclared label '", ident->impl(), "'");
1407 end = tokenEndPosition();
1409 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted break statement");
1410 return context.createBreakStatement(location, ident, start, end);
1413 template <typename LexerType>
1414 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueStatement(TreeBuilder& context)
1416 ASSERT(match(CONTINUE));
1417 JSTokenLocation location(tokenLocation());
1418 JSTextPosition start = tokenStartPosition();
1419 JSTextPosition end = tokenEndPosition();
1422 if (autoSemiColon()) {
1423 semanticFailIfFalse(continueIsValid(), "'continue' is only valid inside a loop statement");
1424 return context.createContinueStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
1426 failIfFalse(matchSpecIdentifier(), "Expected an identifier as the target for a continue statement");
1427 const Identifier* ident = m_token.m_data.ident;
1428 ScopeLabelInfo* label = getLabel(ident);
1429 semanticFailIfFalse(label, "Cannot use the undeclared label '", ident->impl(), "'");
1430 semanticFailIfFalse(label->isLoop, "Cannot continue to the label '", ident->impl(), "' as it is not targeting a loop");
1431 end = tokenEndPosition();
1433 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted continue statement");
1434 return context.createContinueStatement(location, ident, start, end);
1437 template <typename LexerType>
1438 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStatement(TreeBuilder& context)
1440 ASSERT(match(RETURN));
1441 JSTokenLocation location(tokenLocation());
1442 semanticFailIfFalse(currentScope()->isFunction(), "Return statements are only valid inside functions");
1443 JSTextPosition start = tokenStartPosition();
1444 JSTextPosition end = tokenEndPosition();
1446 // We do the auto semicolon check before attempting to parse expression
1447 // as we need to ensure the a line break after the return correctly terminates
1449 if (match(SEMICOLON))
1450 end = tokenEndPosition();
1452 if (autoSemiColon())
1453 return context.createReturnStatement(location, 0, start, end);
1454 TreeExpression expr = parseExpression(context);
1455 failIfFalse(expr, "Cannot parse the return expression");
1456 end = lastTokenEndPosition();
1457 if (match(SEMICOLON))
1458 end = tokenEndPosition();
1459 if (!autoSemiColon())
1460 failWithMessage("Expected a ';' following a return statement");
1461 return context.createReturnStatement(location, expr, start, end);
1464 template <typename LexerType>
1465 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseThrowStatement(TreeBuilder& context)
1467 ASSERT(match(THROW));
1468 JSTokenLocation location(tokenLocation());
1469 JSTextPosition start = tokenStartPosition();
1471 failIfTrue(match(SEMICOLON), "Expected expression after 'throw'");
1472 semanticFailIfTrue(autoSemiColon(), "Cannot have a newline after 'throw'");
1474 TreeExpression expr = parseExpression(context);
1475 failIfFalse(expr, "Cannot parse expression for throw statement");
1476 JSTextPosition end = lastTokenEndPosition();
1477 failIfFalse(autoSemiColon(), "Expected a ';' after a throw statement");
1479 return context.createThrowStatement(location, expr, start, end);
1482 template <typename LexerType>
1483 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement(TreeBuilder& context)
1485 ASSERT(match(WITH));
1486 JSTokenLocation location(tokenLocation());
1487 semanticFailIfTrue(strictMode(), "'with' statements are not valid in strict mode");
1488 currentScope()->setNeedsFullActivation();
1489 int startLine = tokenLine();
1492 handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'with' statement");
1493 int start = tokenStart();
1494 TreeExpression expr = parseExpression(context);
1495 failIfFalse(expr, "Cannot parse 'with' subject expression");
1496 recordPauseLocation(context.breakpointLocation(expr));
1497 JSTextPosition end = lastTokenEndPosition();
1498 int endLine = tokenLine();
1499 handleProductionOrFail(CLOSEPAREN, ")", "start", "subject of a 'with' statement");
1500 const Identifier* unused = 0;
1501 TreeStatement statement = parseStatement(context, unused);
1502 failIfFalse(statement, "A 'with' statement must have a body");
1504 return context.createWithStatement(location, expr, statement, start, end, startLine, endLine);
1507 template <typename LexerType>
1508 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseSwitchStatement(TreeBuilder& context)
1510 ASSERT(match(SWITCH));
1511 JSTokenLocation location(tokenLocation());
1512 int startLine = tokenLine();
1514 handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'switch'");
1515 TreeExpression expr = parseExpression(context);
1516 failIfFalse(expr, "Cannot parse switch subject expression");
1517 recordPauseLocation(context.breakpointLocation(expr));
1518 int endLine = tokenLine();
1520 handleProductionOrFail(CLOSEPAREN, ")", "end", "subject of a 'switch'");
1521 handleProductionOrFail(OPENBRACE, "{", "start", "body of a 'switch'");
1522 AutoPopScopeRef lexicalScope(this, pushScope());
1523 lexicalScope->setIsLexicalScope();
1524 lexicalScope->preventVarDeclarations();
1526 TreeClauseList firstClauses = parseSwitchClauses(context);
1529 TreeClause defaultClause = parseSwitchDefaultClause(context);
1532 TreeClauseList secondClauses = parseSwitchClauses(context);
1535 handleProductionOrFail(CLOSEBRACE, "}", "end", "body of a 'switch'");
1537 TreeStatement result = context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine, lexicalScope->finalizeLexicalEnvironment(), lexicalScope->takeFunctionDeclarations());
1538 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1542 template <typename LexerType>
1543 template <class TreeBuilder> TreeClauseList Parser<LexerType>::parseSwitchClauses(TreeBuilder& context)
1547 unsigned startOffset = tokenStart();
1549 TreeExpression condition = parseExpression(context);
1550 failIfFalse(condition, "Cannot parse switch clause");
1551 consumeOrFail(COLON, "Expected a ':' after switch clause expression");
1552 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1553 failIfFalse(statements, "Cannot parse the body of a switch clause");
1554 TreeClause clause = context.createClause(condition, statements);
1555 context.setStartOffset(clause, startOffset);
1556 TreeClauseList clauseList = context.createClauseList(clause);
1557 TreeClauseList tail = clauseList;
1559 while (match(CASE)) {
1560 startOffset = tokenStart();
1562 TreeExpression condition = parseExpression(context);
1563 failIfFalse(condition, "Cannot parse switch case expression");
1564 consumeOrFail(COLON, "Expected a ':' after switch clause expression");
1565 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1566 failIfFalse(statements, "Cannot parse the body of a switch clause");
1567 clause = context.createClause(condition, statements);
1568 context.setStartOffset(clause, startOffset);
1569 tail = context.createClauseList(tail, clause);
1574 template <typename LexerType>
1575 template <class TreeBuilder> TreeClause Parser<LexerType>::parseSwitchDefaultClause(TreeBuilder& context)
1577 if (!match(DEFAULT))
1579 unsigned startOffset = tokenStart();
1581 consumeOrFail(COLON, "Expected a ':' after switch default clause");
1582 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1583 failIfFalse(statements, "Cannot parse the body of a switch default clause");
1584 TreeClause result = context.createClause(0, statements);
1585 context.setStartOffset(result, startOffset);
1589 template <typename LexerType>
1590 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(TreeBuilder& context)
1593 JSTokenLocation location(tokenLocation());
1594 TreeStatement tryBlock = 0;
1595 TreeDestructuringPattern catchPattern = 0;
1596 TreeStatement catchBlock = 0;
1597 TreeStatement finallyBlock = 0;
1598 int firstLine = tokenLine();
1600 matchOrFail(OPENBRACE, "Expected a block statement as body of a try statement");
1602 tryBlock = parseBlockStatement(context);
1603 failIfFalse(tryBlock, "Cannot parse the body of try block");
1604 int lastLine = m_lastTokenEndPosition.line;
1605 VariableEnvironment catchEnvironment;
1609 handleProductionOrFail(OPENPAREN, "(", "start", "'catch' target");
1610 AutoPopScopeRef catchScope(this, pushScope());
1611 catchScope->setIsLexicalScope();
1612 catchScope->preventVarDeclarations();
1613 const Identifier* ident = nullptr;
1614 if (matchSpecIdentifier()) {
1615 ident = m_token.m_data.ident;
1616 catchPattern = context.createBindingLocation(m_token.m_location, *ident, m_token.m_startPosition, m_token.m_endPosition, AssignmentContext::DeclarationStatement);
1618 failIfTrueIfStrict(catchScope->declareLexicalVariable(ident, false) & DeclarationResult::InvalidStrictMode, "Cannot declare a catch variable named '", ident->impl(), "' in strict mode");
1620 catchPattern = parseDestructuringPattern(context, DestructuringKind::DestructureToCatchParameters, ExportType::NotExported);
1621 failIfFalse(catchPattern, "Cannot parse this destructuring pattern");
1623 handleProductionOrFail(CLOSEPAREN, ")", "end", "'catch' target");
1624 matchOrFail(OPENBRACE, "Expected exception handler to be a block statement");
1625 catchBlock = parseBlockStatement(context);
1626 failIfFalse(catchBlock, "Unable to parse 'catch' block");
1627 catchEnvironment = catchScope->finalizeLexicalEnvironment();
1628 RELEASE_ASSERT(!ident || (catchEnvironment.size() == 1 && catchEnvironment.contains(ident->impl())));
1629 popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo);
1632 if (match(FINALLY)) {
1634 matchOrFail(OPENBRACE, "Expected block statement for finally body");
1635 finallyBlock = parseBlockStatement(context);
1636 failIfFalse(finallyBlock, "Cannot parse finally body");
1638 failIfFalse(catchBlock || finallyBlock, "Try statements must have at least a catch or finally block");
1639 return context.createTryStatement(location, tryBlock, catchPattern, catchBlock, finallyBlock, firstLine, lastLine, catchEnvironment);
1642 template <typename LexerType>
1643 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDebuggerStatement(TreeBuilder& context)
1645 ASSERT(match(DEBUGGER));
1646 JSTokenLocation location(tokenLocation());
1647 int startLine = tokenLine();
1648 int endLine = startLine;
1650 if (match(SEMICOLON))
1651 startLine = tokenLine();
1652 failIfFalse(autoSemiColon(), "Debugger keyword must be followed by a ';'");
1653 return context.createDebugger(location, startLine, endLine);
1656 template <typename LexerType>
1657 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context)
1659 ASSERT(match(OPENBRACE));
1661 // We should treat the first block statement of the function (the body of the function) as the lexical
1662 // scope of the function itself, and not the lexical scope of a 'block' statement within the function.
1663 AutoCleanupLexicalScope lexicalScope;
1664 bool shouldPushLexicalScope = m_statementDepth > 0;
1665 if (shouldPushLexicalScope) {
1666 ScopeRef newScope = pushScope();
1667 newScope->setIsLexicalScope();
1668 newScope->preventVarDeclarations();
1669 lexicalScope.setIsValid(newScope, this);
1671 JSTokenLocation location(tokenLocation());
1672 int startOffset = m_token.m_data.offset;
1673 int start = tokenLine();
1674 VariableEnvironment emptyEnvironment;
1675 DeclarationStacks::FunctionStack emptyFunctionStack;
1677 if (match(CLOSEBRACE)) {
1678 int endOffset = m_token.m_data.offset;
1680 TreeStatement result = context.createBlockStatement(location, 0, start, m_lastTokenEndPosition.line, shouldPushLexicalScope ? currentScope()->finalizeLexicalEnvironment() : emptyEnvironment, shouldPushLexicalScope ? currentScope()->takeFunctionDeclarations() : WTFMove(emptyFunctionStack));
1681 context.setStartOffset(result, startOffset);
1682 context.setEndOffset(result, endOffset);
1683 if (shouldPushLexicalScope)
1684 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1687 TreeSourceElements subtree = parseSourceElements(context, DontCheckForStrictMode);
1688 failIfFalse(subtree, "Cannot parse the body of the block statement");
1689 matchOrFail(CLOSEBRACE, "Expected a closing '}' at the end of a block statement");
1690 int endOffset = m_token.m_data.offset;
1692 TreeStatement result = context.createBlockStatement(location, subtree, start, m_lastTokenEndPosition.line, shouldPushLexicalScope ? currentScope()->finalizeLexicalEnvironment() : emptyEnvironment, shouldPushLexicalScope ? currentScope()->takeFunctionDeclarations() : WTFMove(emptyFunctionStack));
1693 context.setStartOffset(result, startOffset);
1694 context.setEndOffset(result, endOffset);
1695 if (shouldPushLexicalScope)
1696 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1701 template <typename LexerType>
1702 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
1704 DepthManager statementDepth(&m_statementDepth);
1706 int nonTrivialExpressionCount = 0;
1707 failIfStackOverflow();
1708 TreeStatement result = 0;
1709 bool shouldSetEndOffset = true;
1710 bool shouldSetPauseLocation = false;
1711 bool parentAllowsFunctionDeclarationAsStatement = m_immediateParentAllowsFunctionDeclarationInStatement;
1712 m_immediateParentAllowsFunctionDeclarationInStatement = false;
1714 switch (m_token.m_type) {
1716 result = parseBlockStatement(context);
1717 shouldSetEndOffset = false;
1720 result = parseVariableDeclaration(context, DeclarationType::VarDeclaration);
1721 shouldSetPauseLocation = true;
1724 const bool isAsync = false;
1725 result = parseFunctionDeclarationStatement(context, isAsync, parentAllowsFunctionDeclarationAsStatement);
1729 JSTokenLocation location(tokenLocation());
1731 result = context.createEmptyStatement(location);
1732 shouldSetPauseLocation = true;
1736 result = parseIfStatement(context);
1739 result = parseDoWhileStatement(context);
1742 result = parseWhileStatement(context);
1745 result = parseForStatement(context);
1748 result = parseContinueStatement(context);
1749 shouldSetPauseLocation = true;
1752 result = parseBreakStatement(context);
1753 shouldSetPauseLocation = true;
1756 result = parseReturnStatement(context);
1757 shouldSetPauseLocation = true;
1760 result = parseWithStatement(context);
1763 result = parseSwitchStatement(context);
1766 result = parseThrowStatement(context);
1767 shouldSetPauseLocation = true;
1770 result = parseTryStatement(context);
1773 result = parseDebuggerStatement(context);
1774 shouldSetPauseLocation = true;
1780 // These tokens imply the end of a set of source elements
1783 #if ENABLE(ES2017_ASYNCFUNCTION_SYNTAX)
1784 if (UNLIKELY(*m_token.m_data.ident == m_vm->propertyNames->async && maybeParseAsyncFunctionDeclarationStatement(context, result, parentAllowsFunctionDeclarationAsStatement)))
1790 bool allowFunctionDeclarationAsStatement = false;
1791 result = parseExpressionOrLabelStatement(context, allowFunctionDeclarationAsStatement);
1792 shouldSetPauseLocation = !context.shouldSkipPauseLocation(result);
1796 directive = m_token.m_data.ident;
1797 if (directiveLiteralLength)
1798 *directiveLiteralLength = m_token.m_location.endOffset - m_token.m_location.startOffset;
1799 nonTrivialExpressionCount = m_parserState.nonTrivialExpressionCount;
1802 TreeStatement exprStatement = parseExpressionStatement(context);
1803 if (directive && nonTrivialExpressionCount != m_parserState.nonTrivialExpressionCount)
1804 directive = nullptr;
1805 result = exprStatement;
1806 shouldSetPauseLocation = true;
1811 if (shouldSetEndOffset)
1812 context.setEndOffset(result, m_lastTokenEndPosition.offset);
1813 if (shouldSetPauseLocation)
1814 recordPauseLocation(context.breakpointLocation(result));
1820 template <typename LexerType>
1821 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclarationStatement(TreeBuilder& context, bool isAsync, bool parentAllowsFunctionDeclarationAsStatement)
1823 semanticFailIfTrue(strictMode(), "Function declarations are only allowed inside blocks or switch statements in strict mode");
1824 failIfFalse(parentAllowsFunctionDeclarationAsStatement, "Function declarations are only allowed inside block statements or at the top level of a program");
1825 if (!currentScope()->isFunction()) {
1826 // We only implement annex B.3.3 if we're in function mode. Otherwise, we fall back
1827 // to hoisting behavior.
1828 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=155813
1829 DepthManager statementDepth(&m_statementDepth);
1830 m_statementDepth = 1;
1832 return parseAsyncFunctionDeclaration(context);
1833 return parseFunctionDeclaration(context);
1836 // Any function declaration that isn't in a block is a syntax error unless it's
1837 // in an if/else statement. If it's in an if/else statement, we will magically
1838 // treat it as if the if/else statement is inside a block statement.
1839 // to the very top like a "var". For example:
1841 // if (cond) function foo() { }
1843 // will be rewritten as:
1845 // if (cond) { function foo() { } }
1847 AutoPopScopeRef blockScope(this, pushScope());
1848 blockScope->setIsLexicalScope();
1849 blockScope->preventVarDeclarations();
1850 JSTokenLocation location(tokenLocation());
1851 int start = tokenLine();
1853 TreeStatement function = 0;
1855 function = parseFunctionDeclaration(context);
1857 function = parseAsyncFunctionDeclaration(context);
1859 failIfFalse(function, "Expected valid function statement after 'function' keyword");
1860 TreeSourceElements sourceElements = context.createSourceElements();
1861 context.appendStatement(sourceElements, function);
1862 TreeStatement result = context.createBlockStatement(location, sourceElements, start, m_lastTokenEndPosition.line, currentScope()->finalizeLexicalEnvironment(), currentScope()->takeFunctionDeclarations());
1863 popScope(blockScope, TreeBuilder::NeedsFreeVariableInfo);
1867 template <typename LexerType>
1868 template <class TreeBuilder> bool Parser<LexerType>::maybeParseAsyncFunctionDeclarationStatement(TreeBuilder& context, TreeStatement& result, bool parentAllowsFunctionDeclarationAsStatement)
1870 ASSERT(*m_token.m_data.ident == m_vm->propertyNames->async);
1871 SavePoint savePoint = createSavePoint();
1873 if (match(FUNCTION) && !m_lexer->prevTerminator()) {
1874 const bool isAsync = true;
1875 result = parseFunctionDeclarationStatement(context, isAsync, parentAllowsFunctionDeclarationAsStatement);
1878 restoreSavePoint(savePoint);
1882 template <typename LexerType>
1883 template <class TreeBuilder> bool Parser<LexerType>::parseFormalParameters(TreeBuilder& context, TreeFormalParameterList list, bool isArrowFunction, unsigned& parameterCount, unsigned& functionLength)
1885 #define failIfDuplicateIfViolation() \
1886 if (duplicateParameter) {\
1887 semanticFailIfTrue(hasDefaultParameterValues, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with default parameter values");\
1888 semanticFailIfTrue(hasDestructuringPattern, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with destructuring parameters");\
1889 semanticFailIfTrue(isRestParameter, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with a rest parameter");\
1890 semanticFailIfTrue(isArrowFunction, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in an arrow function");\
1893 bool hasDefaultParameterValues = false;
1894 bool hasDestructuringPattern = false;
1895 bool isRestParameter = false;
1896 const Identifier* duplicateParameter = nullptr;
1898 TreeDestructuringPattern parameter = 0;
1899 TreeExpression defaultValue = 0;
1901 if (UNLIKELY(match(CLOSEPAREN)))
1904 if (match(DOTDOTDOT)) {
1906 semanticFailIfTrue(!m_parserState.allowAwait && match(AWAIT), "Can't use 'await' as a parameter name in an async function");
1907 TreeDestructuringPattern destructuringPattern = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported, &duplicateParameter, &hasDestructuringPattern);
1909 parameter = context.createRestParameter(destructuringPattern, parameterCount);
1910 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.
1911 isRestParameter = true;
1913 parameter = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported, &duplicateParameter, &hasDestructuringPattern);
1914 failIfFalse(parameter, "Cannot parse parameter pattern");
1915 if (!isRestParameter) {
1916 defaultValue = parseDefaultValueForDestructuringPattern(context);
1918 hasDefaultParameterValues = true;
1921 failIfDuplicateIfViolation();
1922 if (isRestParameter || defaultValue || hasDestructuringPattern)
1923 currentScope()->setHasNonSimpleParameterList();
1924 context.appendParameter(list, parameter, defaultValue);
1925 if (!isRestParameter) {
1927 if (!hasDefaultParameterValues)
1930 } while (!isRestParameter && consume(COMMA));
1933 #undef failIfDuplicateIfViolation
1936 template <typename LexerType>
1937 template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(
1938 TreeBuilder& context, SyntaxChecker& syntaxChecker, const JSTokenLocation& startLocation, int startColumn, int functionKeywordStart, int functionNameStart, int parametersStart,
1939 ConstructorKind constructorKind, SuperBinding superBinding, FunctionBodyType bodyType, unsigned parameterCount, unsigned functionLength, SourceParseMode parseMode)
1941 bool isArrowFunctionBodyExpression = bodyType == ArrowFunctionBodyExpression;
1942 if (!isArrowFunctionBodyExpression) {
1944 if (match(CLOSEBRACE)) {
1945 unsigned endColumn = tokenColumn();
1946 return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, superBinding, parameterCount, functionLength, parseMode, isArrowFunctionBodyExpression);
1950 DepthManager statementDepth(&m_statementDepth);
1951 m_statementDepth = 0;
1952 if (bodyType == ArrowFunctionBodyExpression) {
1953 if (m_debuggerParseData)
1954 failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(context), "Cannot parse body of this arrow function");
1956 failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(syntaxChecker), "Cannot parse body of this arrow function");
1958 if (m_debuggerParseData)
1959 failIfFalse(parseSourceElements(context, CheckForStrictMode), bodyType == StandardFunctionBodyBlock ? "Cannot parse body of this function" : "Cannot parse body of this arrow function");
1961 failIfFalse(parseSourceElements(syntaxChecker, CheckForStrictMode), bodyType == StandardFunctionBodyBlock ? "Cannot parse body of this function" : "Cannot parse body of this arrow function");
1963 unsigned endColumn = tokenColumn();
1964 return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, superBinding, parameterCount, functionLength, parseMode, isArrowFunctionBodyExpression);
1967 static const char* stringForFunctionMode(SourceParseMode mode)
1970 case SourceParseMode::GetterMode:
1972 case SourceParseMode::SetterMode:
1974 case SourceParseMode::NormalFunctionMode:
1976 case SourceParseMode::MethodMode:
1978 case SourceParseMode::GeneratorBodyMode:
1980 case SourceParseMode::GeneratorWrapperFunctionMode:
1981 return "generator function";
1982 case SourceParseMode::ArrowFunctionMode:
1983 return "arrow function";
1984 case SourceParseMode::AsyncFunctionMode:
1985 case SourceParseMode::AsyncFunctionBodyMode:
1986 return "async function";
1987 case SourceParseMode::AsyncMethodMode:
1988 return "async method";
1989 case SourceParseMode::AsyncArrowFunctionBodyMode:
1990 case SourceParseMode::AsyncArrowFunctionMode:
1991 return "async arrow function";
1992 case SourceParseMode::ProgramMode:
1993 case SourceParseMode::ModuleAnalyzeMode:
1994 case SourceParseMode::ModuleEvaluateMode:
1995 RELEASE_ASSERT_NOT_REACHED();
1998 RELEASE_ASSERT_NOT_REACHED();
2002 template <typename LexerType> template <class TreeBuilder, class FunctionInfoType> typename TreeBuilder::FormalParameterList Parser<LexerType>::parseFunctionParameters(TreeBuilder& context, SourceParseMode mode, FunctionInfoType& functionInfo)
2004 RELEASE_ASSERT(!(SourceParseModeSet(SourceParseMode::ProgramMode, SourceParseMode::ModuleAnalyzeMode, SourceParseMode::ModuleEvaluateMode).contains(mode)));
2005 TreeFormalParameterList parameterList = context.createFormalParameterList();
2006 SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_parserState.functionParsePhase, FunctionParsePhase::Parameters);
2008 if (UNLIKELY((SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode).contains(mode)))) {
2009 if (!matchSpecIdentifier() && !match(OPENPAREN)) {
2010 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
2011 failWithMessage("Expected an arrow function input parameter");
2013 if (match(OPENPAREN)) {
2016 if (match(CLOSEPAREN)) {
2017 functionInfo.parameterCount = 0;
2018 functionInfo.functionLength = 0;
2020 bool isArrowFunction = true;
2021 failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, functionInfo.parameterCount, functionInfo.functionLength), "Cannot parse parameters for this ", stringForFunctionMode(mode));
2024 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
2026 functionInfo.parameterCount = 1;
2027 functionInfo.functionLength = 1;
2028 auto parameter = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported);
2029 failIfFalse(parameter, "Cannot parse parameter pattern");
2030 context.appendParameter(parameterList, parameter, 0);
2034 return parameterList;
2037 if (!consume(OPENPAREN)) {
2038 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
2039 failWithMessage("Expected an opening '(' before a ", stringForFunctionMode(mode), "'s parameter list");
2042 if (mode == SourceParseMode::GetterMode) {
2043 consumeOrFail(CLOSEPAREN, "getter functions must have no parameters");
2044 functionInfo.parameterCount = 0;
2045 functionInfo.functionLength = 0;
2046 } else if (mode == SourceParseMode::SetterMode) {
2047 failIfTrue(match(CLOSEPAREN), "setter functions must have one parameter");
2048 const Identifier* duplicateParameter = nullptr;
2049 bool hasDestructuringPattern = false;
2050 auto parameter = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported, &duplicateParameter, &hasDestructuringPattern);
2051 failIfFalse(parameter, "setter functions must have one parameter");
2052 auto defaultValue = parseDefaultValueForDestructuringPattern(context);
2054 if (defaultValue || hasDestructuringPattern) {
2055 semanticFailIfTrue(duplicateParameter, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with non-simple parameter list");
2056 currentScope()->setHasNonSimpleParameterList();
2058 context.appendParameter(parameterList, parameter, defaultValue);
2059 functionInfo.parameterCount = 1;
2060 functionInfo.functionLength = defaultValue ? 0 : 1;
2061 failIfTrue(match(COMMA), "setter functions must have one parameter");
2062 consumeOrFail(CLOSEPAREN, "Expected a ')' after a parameter declaration");
2064 if (match(CLOSEPAREN)) {
2065 functionInfo.parameterCount = 0;
2066 functionInfo.functionLength = 0;
2068 bool isArrowFunction = false;
2069 failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, functionInfo.parameterCount, functionInfo.functionLength), "Cannot parse parameters for this ", stringForFunctionMode(mode));
2071 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
2074 return parameterList;
2077 template <typename LexerType>
2078 template <class TreeBuilder> typename TreeBuilder::FormalParameterList Parser<LexerType>::createGeneratorParameters(TreeBuilder& context, unsigned& parameterCount)
2080 auto parameters = context.createFormalParameterList();
2082 JSTokenLocation location(tokenLocation());
2083 JSTextPosition position = tokenStartPosition();
2085 auto addParameter = [&](const Identifier& name) {
2086 declareParameter(&name);
2087 auto binding = context.createBindingLocation(location, name, position, position, AssignmentContext::DeclarationStatement);
2088 context.appendParameter(parameters, binding, 0);
2093 addParameter(m_vm->propertyNames->builtinNames().generatorPrivateName());
2095 addParameter(m_vm->propertyNames->builtinNames().generatorStatePrivateName());
2097 addParameter(m_vm->propertyNames->builtinNames().generatorValuePrivateName());
2098 // @generatorResumeMode
2099 addParameter(m_vm->propertyNames->builtinNames().generatorResumeModePrivateName());
2101 addParameter(m_vm->propertyNames->builtinNames().generatorFramePrivateName());
2106 template <typename LexerType>
2107 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)
2109 RELEASE_ASSERT(isFunctionParseMode(mode));
2111 ScopeRef parentScope = currentScope();
2113 bool isDisallowedAwaitFunctionName = isDisallowedIdentifierAwait(m_token);
2114 const char* isDisallowedAwaitFunctionNameReason = isDisallowedAwaitFunctionName ? disallowedIdentifierAwaitReason() : nullptr;
2116 AutoPopScopeRef functionScope(this, pushScope());
2117 functionScope->setSourceParseMode(mode);
2118 functionScope->setExpectedSuperBinding(expectedSuperBinding);
2119 functionScope->setConstructorKind(constructorKind);
2120 SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_parserState.functionParsePhase, FunctionParsePhase::Body);
2121 int functionNameStart = m_token.m_location.startOffset;
2122 const Identifier* lastFunctionName = m_parserState.lastFunctionName;
2123 m_parserState.lastFunctionName = nullptr;
2124 int parametersStart = -1;
2125 JSTokenLocation startLocation;
2126 int startColumn = -1;
2127 FunctionBodyType functionBodyType;
2129 auto loadCachedFunction = [&] () -> bool {
2130 if (UNLIKELY(!Options::useSourceProviderCache()))
2133 if (UNLIKELY(m_debuggerParseData))
2136 ASSERT(parametersStart != -1);
2137 ASSERT(startColumn != -1);
2139 // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
2140 if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(parametersStart) : 0) {
2141 // If we're in a strict context, the cached function info must say it was strict too.
2142 ASSERT(!strictMode() || cachedInfo->strictMode);
2143 JSTokenLocation endLocation;
2145 ConstructorKind constructorKind = static_cast<ConstructorKind>(cachedInfo->constructorKind);
2146 SuperBinding expectedSuperBinding = static_cast<SuperBinding>(cachedInfo->expectedSuperBinding);
2148 endLocation.line = cachedInfo->lastTokenLine;
2149 endLocation.startOffset = cachedInfo->lastTokenStartOffset;
2150 endLocation.lineStartOffset = cachedInfo->lastTokenLineStartOffset;
2151 ASSERT(endLocation.startOffset >= endLocation.lineStartOffset);
2153 bool endColumnIsOnStartLine = endLocation.line == functionInfo.startLine;
2154 unsigned currentLineStartOffset = m_lexer->currentLineStartOffset();
2155 unsigned bodyEndColumn = endColumnIsOnStartLine ? endLocation.startOffset - currentLineStartOffset : endLocation.startOffset - endLocation.lineStartOffset;
2157 ASSERT(endLocation.startOffset >= endLocation.lineStartOffset);
2159 FunctionBodyType functionBodyType;
2160 if (UNLIKELY(SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode).contains(mode)))
2161 functionBodyType = cachedInfo->isBodyArrowExpression ? ArrowFunctionBodyExpression : ArrowFunctionBodyBlock;
2163 functionBodyType = StandardFunctionBodyBlock;
2165 functionInfo.body = context.createFunctionMetadata(
2166 startLocation, endLocation, startColumn, bodyEndColumn,
2167 functionKeywordStart, functionNameStart, parametersStart,
2168 cachedInfo->strictMode, constructorKind, expectedSuperBinding,
2169 cachedInfo->parameterCount, cachedInfo->functionLength,
2170 mode, functionBodyType == ArrowFunctionBodyExpression);
2171 functionInfo.endOffset = cachedInfo->endFunctionOffset;
2172 functionInfo.parameterCount = cachedInfo->parameterCount;
2173 functionInfo.functionLength = cachedInfo->functionLength;
2175 functionScope->restoreFromSourceProviderCache(cachedInfo);
2176 popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo);
2178 m_token = cachedInfo->endFunctionToken();
2180 if (endColumnIsOnStartLine)
2181 m_token.m_location.lineStartOffset = currentLineStartOffset;
2183 m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset);
2184 m_lexer->setLineNumber(m_token.m_location.line);
2186 switch (functionBodyType) {
2187 case ArrowFunctionBodyExpression:
2189 context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
2191 case ArrowFunctionBodyBlock:
2192 case StandardFunctionBodyBlock:
2193 context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
2197 functionInfo.endLine = m_lastTokenEndPosition.line;
2204 SyntaxChecker syntaxChecker(const_cast<VM*>(m_vm), m_lexer.get());
2206 if (UNLIKELY((SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode).contains(mode)))) {
2207 startLocation = tokenLocation();
2208 functionInfo.startLine = tokenLine();
2209 startColumn = tokenColumn();
2211 parametersStart = m_token.m_location.startOffset;
2212 functionInfo.startOffset = parametersStart;
2213 functionInfo.parametersStartColumn = startColumn;
2215 if (loadCachedFunction())
2219 // Parse formal parameters with [+Yield] parameterization, in order to ban YieldExpressions
2220 // in ArrowFormalParameters, per ES6 #sec-arrow-function-definitions-static-semantics-early-errors.
2221 Scope::MaybeParseAsGeneratorForScope parseAsGenerator(functionScope, parentScope->isGenerator());
2222 SetForScope<bool> overrideAllowAwait(m_parserState.allowAwait, !isAsyncFunctionParseMode(mode));
2223 parseFunctionParameters(syntaxChecker, mode, functionInfo);
2227 matchOrFail(ARROWFUNCTION, "Expected a '=>' after arrow function parameter declaration");
2229 if (m_lexer->prevTerminator())
2230 failDueToUnexpectedToken();
2232 ASSERT(constructorKind == ConstructorKind::None);
2234 // Check if arrow body start with {. If it true it mean that arrow function is Fat arrow function
2235 // and we need use common approach to parse function body
2237 functionBodyType = match(OPENBRACE) ? ArrowFunctionBodyBlock : ArrowFunctionBodyExpression;
2239 // http://ecma-international.org/ecma-262/6.0/#sec-function-definitions
2240 // FunctionExpression :
2241 // function BindingIdentifieropt ( FormalParameters ) { FunctionBody }
2243 // FunctionDeclaration[Yield, Default] :
2244 // function BindingIdentifier[?Yield] ( FormalParameters ) { FunctionBody }
2245 // [+Default] function ( FormalParameters ) { FunctionBody }
2247 // GeneratorDeclaration[Yield, Default] :
2248 // function * BindingIdentifier[?Yield] ( FormalParameters[Yield] ) { GeneratorBody }
2249 // [+Default] function * ( FormalParameters[Yield] ) { GeneratorBody }
2251 // GeneratorExpression :
2252 // function * BindingIdentifier[Yield]opt ( FormalParameters[Yield] ) { GeneratorBody }
2254 // The name of FunctionExpression and AsyncFunctionExpression can accept "yield" even in the context of generator.
2255 bool upperScopeIsGenerator = false;
2256 if (!(functionDefinitionType == FunctionDefinitionType::Expression && SourceParseModeSet(SourceParseMode::NormalFunctionMode, SourceParseMode::AsyncFunctionMode).contains(mode)))
2257 upperScopeIsGenerator = upperScope(1)->isGenerator();
2259 if (requirements != FunctionNameRequirements::Unnamed) {
2260 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.");
2261 if (matchSpecIdentifier(upperScopeIsGenerator)) {
2262 functionInfo.name = m_token.m_data.ident;
2263 m_parserState.lastFunctionName = functionInfo.name;
2264 if (UNLIKELY(isDisallowedAwaitFunctionName))
2265 semanticFailIfTrue(functionDefinitionType == FunctionDefinitionType::Declaration || isAsyncFunctionWrapperParseMode(mode), "Cannot declare function named 'await' ", isDisallowedAwaitFunctionNameReason);
2266 else if (isAsyncFunctionWrapperParseMode(mode) && match(AWAIT) && functionDefinitionType == FunctionDefinitionType::Expression)
2267 semanticFail("Cannot declare async function named 'await'");
2269 if (!nameIsInContainingScope)
2270 failIfTrueIfStrict(functionScope->declareCallee(functionInfo.name) & DeclarationResult::InvalidStrictMode, "'", functionInfo.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode");
2271 } else if (requirements == FunctionNameRequirements::Named) {
2272 if (match(OPENPAREN)) {
2273 semanticFailIfTrue(mode == SourceParseMode::NormalFunctionMode, "Function statements must have a name");
2274 semanticFailIfTrue(mode == SourceParseMode::AsyncFunctionMode, "Async function statements must have a name");
2276 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
2277 failDueToUnexpectedToken();
2280 ASSERT(functionInfo.name);
2283 startLocation = tokenLocation();
2284 functionInfo.startLine = tokenLine();
2285 startColumn = tokenColumn();
2286 functionInfo.parametersStartColumn = startColumn;
2288 parametersStart = m_token.m_location.startOffset;
2289 functionInfo.startOffset = parametersStart;
2291 if (loadCachedFunction())
2294 SetForScope<bool> overrideAllowAwait(m_parserState.allowAwait, !isAsyncFunctionParseMode(mode));
2295 parseFunctionParameters(syntaxChecker, mode, functionInfo);
2299 matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body");
2301 // BytecodeGenerator emits code to throw TypeError when a class constructor is "call"ed.
2302 // Set ConstructorKind to None for non-constructor methods of classes.
2304 if (m_defaultConstructorKind != ConstructorKind::None) {
2305 constructorKind = m_defaultConstructorKind;
2306 expectedSuperBinding = m_defaultConstructorKind == ConstructorKind::Extends ? SuperBinding::Needed : SuperBinding::NotNeeded;
2309 functionBodyType = StandardFunctionBodyBlock;
2312 functionScope->setConstructorKind(constructorKind);
2313 functionScope->setExpectedSuperBinding(expectedSuperBinding);
2315 m_parserState.lastFunctionName = lastFunctionName;
2316 ParserState oldState = internalSaveParserState();
2318 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=156962
2319 // This loop collects the set of capture candidates that aren't
2320 // part of the set of this function's declared parameters. We will
2321 // figure out which parameters are captured for this function when
2322 // we actually generate code for it. For now, we just propagate to
2323 // our parent scopes which variables we might have closed over that
2324 // belong to them. This is necessary for correctness when using
2325 // the source provider cache because we can't close over a variable
2326 // that we don't claim to close over. The source provider cache must
2327 // know this information to properly cache this function.
2328 // This might work itself out nicer if we declared a different
2329 // Scope struct for the parameters (because they are indeed implemented
2330 // as their own scope).
2331 UniquedStringImplPtrSet nonLocalCapturesFromParameterExpressions;
2332 functionScope->forEachUsedVariable([&] (UniquedStringImpl* impl) {
2333 if (!functionScope->hasDeclaredParameter(impl)) {
2334 nonLocalCapturesFromParameterExpressions.add(impl);
2335 if (TreeBuilder::NeedsFreeVariableInfo)
2336 parentScope->addClosedVariableCandidateUnconditionally(impl);
2340 auto performParsingFunctionBody = [&] {
2341 return parseFunctionBody(context, syntaxChecker, startLocation, startColumn, functionKeywordStart, functionNameStart, parametersStart, constructorKind, expectedSuperBinding, functionBodyType, functionInfo.parameterCount, functionInfo.functionLength, mode);
2344 if (mode == SourceParseMode::GeneratorWrapperFunctionMode || isAsyncFunctionWrapperParseMode(mode)) {
2345 AutoPopScopeRef generatorBodyScope(this, pushScope());
2346 SourceParseMode innerParseMode = SourceParseMode::GeneratorBodyMode;
2347 if (isAsyncFunctionWrapperParseMode(mode)) {
2348 innerParseMode = mode == SourceParseMode::AsyncArrowFunctionMode
2349 ? SourceParseMode::AsyncArrowFunctionBodyMode
2350 : SourceParseMode::AsyncFunctionBodyMode;
2352 generatorBodyScope->setSourceParseMode(innerParseMode);
2353 generatorBodyScope->setConstructorKind(ConstructorKind::None);
2354 generatorBodyScope->setExpectedSuperBinding(expectedSuperBinding);
2356 // Disallow 'use strict' directives in the implicit inner function if
2358 if (functionScope->hasNonSimpleParameterList())
2359 generatorBodyScope->setHasNonSimpleParameterList();
2361 functionInfo.body = performParsingFunctionBody();
2363 // When a generator has a "use strict" directive, a generator function wrapping it should be strict mode.
2364 if (generatorBodyScope->strictMode())
2365 functionScope->setStrictMode();
2367 popScope(generatorBodyScope, TreeBuilder::NeedsFreeVariableInfo);
2369 functionInfo.body = performParsingFunctionBody();
2371 restoreParserState(oldState);
2372 failIfFalse(functionInfo.body, "Cannot parse the body of this ", stringForFunctionMode(mode));
2373 context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
2374 if (functionScope->strictMode() && requirements != FunctionNameRequirements::Unnamed) {
2375 ASSERT(functionInfo.name);
2376 RELEASE_ASSERT(SourceParseModeSet(SourceParseMode::NormalFunctionMode, SourceParseMode::MethodMode, SourceParseMode::ArrowFunctionMode, SourceParseMode::GeneratorBodyMode, SourceParseMode::GeneratorWrapperFunctionMode).contains(mode) || isAsyncFunctionWrapperParseMode(mode));
2377 semanticFailIfTrue(m_vm->propertyNames->arguments == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
2378 semanticFailIfTrue(m_vm->propertyNames->eval == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
2381 JSTokenLocation location = JSTokenLocation(m_token.m_location);
2382 functionInfo.endOffset = m_token.m_data.offset;
2384 if (functionBodyType == ArrowFunctionBodyExpression) {
2385 location = locationBeforeLastToken();
2386 functionInfo.endOffset = location.endOffset;
2388 recordFunctionEntryLocation(JSTextPosition(startLocation.line, startLocation.startOffset, startLocation.lineStartOffset));
2389 recordFunctionLeaveLocation(JSTextPosition(location.line, location.startOffset, location.lineStartOffset));
2392 // Cache the tokenizer state and the function scope the first time the function is parsed.
2393 // Any future reparsing can then skip the function.
2394 // For arrow function is 8 = x=>x + 4 symbols;
2395 // For ordinary function is 16 = function(){} + 4 symbols
2396 const int minimumFunctionLengthToCache = functionBodyType == StandardFunctionBodyBlock ? 16 : 8;
2397 std::unique_ptr<SourceProviderCacheItem> newInfo;
2398 int functionLength = functionInfo.endOffset - functionInfo.startOffset;
2399 if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) {
2400 SourceProviderCacheItemCreationParameters parameters;
2401 parameters.endFunctionOffset = functionInfo.endOffset;
2402 parameters.functionNameStart = functionNameStart;
2403 parameters.lastTokenLine = location.line;
2404 parameters.lastTokenStartOffset = location.startOffset;
2405 parameters.lastTokenEndOffset = location.endOffset;
2406 parameters.lastTokenLineStartOffset = location.lineStartOffset;
2407 parameters.parameterCount = functionInfo.parameterCount;
2408 parameters.functionLength = functionInfo.functionLength;
2409 parameters.constructorKind = constructorKind;
2410 parameters.expectedSuperBinding = expectedSuperBinding;
2411 if (functionBodyType == ArrowFunctionBodyExpression) {
2412 parameters.isBodyArrowExpression = true;
2413 parameters.tokenType = m_token.m_type;
2415 functionScope->fillParametersForSourceProviderCache(parameters, nonLocalCapturesFromParameterExpressions);
2416 newInfo = SourceProviderCacheItem::create(parameters);
2419 popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo);
2421 if (functionBodyType != ArrowFunctionBodyExpression) {
2422 matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body");
2427 m_functionCache->add(functionInfo.startOffset, WTFMove(newInfo));
2429 functionInfo.endLine = m_lastTokenEndPosition.line;
2433 static NO_RETURN_DUE_TO_CRASH FunctionMetadataNode* getMetadata(ParserFunctionInfo<SyntaxChecker>&) { RELEASE_ASSERT_NOT_REACHED(); }
2434 static FunctionMetadataNode* getMetadata(ParserFunctionInfo<ASTBuilder>& info) { return info.body; }
2436 template <typename LexerType>
2437 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext)
2439 ASSERT(match(FUNCTION));
2440 JSTokenLocation location(tokenLocation());
2441 unsigned functionKeywordStart = tokenStart();
2443 SourceParseMode parseMode = SourceParseMode::NormalFunctionMode;
2445 parseMode = SourceParseMode::GeneratorWrapperFunctionMode;
2447 ParserFunctionInfo<TreeBuilder> functionInfo;
2448 FunctionNameRequirements requirements = FunctionNameRequirements::Named;
2449 if (declarationDefaultContext == DeclarationDefaultContext::ExportDefault) {
2450 // Under the "export default" context, function declaration does not require the function name.
2452 // ExportDeclaration:
2454 // export default HoistableDeclaration[~Yield, +Default]
2457 // HoistableDeclaration[Yield, Default]:
2458 // FunctionDeclaration[?Yield, ?Default]
2459 // GeneratorDeclaration[?Yield, ?Default]
2461 // FunctionDeclaration[Yield, Default]:
2463 // [+Default] function ( FormalParameters[~Yield] ) { FunctionBody[~Yield] }
2465 // GeneratorDeclaration[Yield, Default]:
2467 // [+Default] function * ( FormalParameters[+Yield] ) { GeneratorBody }
2469 // In this case, we use "*default*" as this function declaration's name.
2470 requirements = FunctionNameRequirements::None;
2471 functionInfo.name = &m_vm->propertyNames->builtinNames().starDefaultPrivateName();
2474 failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration)), "Cannot parse this function");
2475 ASSERT(functionInfo.name);
2477 std::pair<DeclarationResultMask, ScopeRef> functionDeclaration = declareFunction(functionInfo.name);
2478 DeclarationResultMask declarationResult = functionDeclaration.first;
2479 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a function named '", functionInfo.name->impl(), "' in strict mode");
2480 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
2481 internalFailWithMessage(false, "Cannot declare a function that shadows a let/const/class/function variable '", functionInfo.name->impl(), "' in strict mode");
2482 if (exportType == ExportType::Exported) {
2483 ASSERT_WITH_MESSAGE(declarationDefaultContext != DeclarationDefaultContext::ExportDefault, "Export default case will export the name and binding in the caller.");
2484 semanticFailIfFalse(exportName(*functionInfo.name), "Cannot export a duplicate function name: '", functionInfo.name->impl(), "'");
2485 m_moduleScopeData->exportBinding(*functionInfo.name);
2488 TreeStatement result = context.createFuncDeclStatement(location, functionInfo);
2489 if (TreeBuilder::CreatesAST)
2490 functionDeclaration.second->appendFunction(getMetadata(functionInfo));
2494 template <typename LexerType>
2495 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseAsyncFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext)
2497 ASSERT(match(FUNCTION));
2498 JSTokenLocation location(tokenLocation());
2499 unsigned functionKeywordStart = tokenStart();
2501 ParserFunctionInfo<TreeBuilder> functionInfo;
2502 SourceParseMode parseMode = SourceParseMode::AsyncFunctionMode;
2503 FunctionNameRequirements requirements = FunctionNameRequirements::Named;
2504 if (declarationDefaultContext == DeclarationDefaultContext::ExportDefault) {
2505 // Under the "export default" context, function declaration does not require the function name.
2507 // ExportDeclaration:
2509 // export default HoistableDeclaration[~Yield, +Default]
2512 // HoistableDeclaration[Yield, Default]:
2513 // FunctionDeclaration[?Yield, ?Default]
2514 // GeneratorDeclaration[?Yield, ?Default]
2516 // FunctionDeclaration[Yield, Default]:
2518 // [+Default] function ( FormalParameters[~Yield] ) { FunctionBody[~Yield] }
2520 // GeneratorDeclaration[Yield, Default]:
2522 // [+Default] function * ( FormalParameters[+Yield] ) { GeneratorBody }
2524 // In this case, we use "*default*" as this function declaration's name.
2525 requirements = FunctionNameRequirements::None;
2526 functionInfo.name = &m_vm->propertyNames->builtinNames().starDefaultPrivateName();
2529 failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration)), "Cannot parse this async function");
2530 failIfFalse(functionInfo.name, "Async function statements must have a name");
2532 std::pair<DeclarationResultMask, ScopeRef> functionDeclaration = declareFunction(functionInfo.name);
2533 DeclarationResultMask declarationResult = functionDeclaration.first;
2534 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare an async function named '", functionInfo.name->impl(), "' in strict mode");
2535 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
2536 internalFailWithMessage(false, "Cannot declare an async function that shadows a let/const/class/function variable '", functionInfo.name->impl(), "' in strict mode");
2537 if (exportType == ExportType::Exported) {
2538 semanticFailIfFalse(exportName(*functionInfo.name), "Cannot export a duplicate function name: '", functionInfo.name->impl(), "'");
2539 m_moduleScopeData->exportBinding(*functionInfo.name);
2542 TreeStatement result = context.createFuncDeclStatement(location, functionInfo);
2543 if (TreeBuilder::CreatesAST)
2544 functionDeclaration.second->appendFunction(getMetadata(functionInfo));
2548 template <typename LexerType>
2549 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseClassDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext)
2551 ASSERT(match(CLASSTOKEN));
2552 JSTokenLocation location(tokenLocation());
2553 JSTextPosition classStart = tokenStartPosition();
2554 unsigned classStartLine = tokenLine();
2556 ParserClassInfo<TreeBuilder> info;
2557 FunctionNameRequirements requirements = FunctionNameRequirements::Named;
2558 if (declarationDefaultContext == DeclarationDefaultContext::ExportDefault) {
2559 // Under the "export default" context, class declaration does not require the class name.
2561 // ExportDeclaration:
2563 // export default ClassDeclaration[~Yield, +Default]
2566 // ClassDeclaration[Yield, Default]:
2568 // [+Default] class ClassTail[?Yield]
2570 // In this case, we use "*default*" as this class declaration's name.
2571 requirements = FunctionNameRequirements::None;
2572 info.className = &m_vm->propertyNames->builtinNames().starDefaultPrivateName();
2575 TreeClassExpression classExpr = parseClass(context, requirements, info);
2576 failIfFalse(classExpr, "Failed to parse class");
2577 ASSERT(info.className);
2579 DeclarationResultMask declarationResult = declareVariable(info.className, DeclarationType::LetDeclaration);
2580 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
2581 internalFailWithMessage(false, "Cannot declare a class twice: '", info.className->impl(), "'");
2582 if (exportType == ExportType::Exported) {
2583 ASSERT_WITH_MESSAGE(declarationDefaultContext != DeclarationDefaultContext::ExportDefault, "Export default case will export the name and binding in the caller.");
2584 semanticFailIfFalse(exportName(*info.className), "Cannot export a duplicate class name: '", info.className->impl(), "'");
2585 m_moduleScopeData->exportBinding(*info.className);
2588 JSTextPosition classEnd = lastTokenEndPosition();
2589 unsigned classEndLine = tokenLine();
2591 return context.createClassDeclStatement(location, classExpr, classStart, classEnd, classStartLine, classEndLine);
2594 template <typename LexerType>
2595 template <class TreeBuilder> TreeClassExpression Parser<LexerType>::parseClass(TreeBuilder& context, FunctionNameRequirements requirements, ParserClassInfo<TreeBuilder>& info)
2597 ASSERT(match(CLASSTOKEN));
2598 JSTokenLocation location(tokenLocation());
2599 info.startLine = location.line;
2600 info.startColumn = tokenColumn();
2601 info.startOffset = location.startOffset;
2604 AutoPopScopeRef classScope(this, pushScope());
2605 classScope->setIsLexicalScope();
2606 classScope->preventVarDeclarations();
2607 classScope->setStrictMode();
2609 ASSERT_WITH_MESSAGE(requirements != FunctionNameRequirements::Unnamed, "Currently, there is no caller that uses FunctionNameRequirements::Unnamed for class syntax.");
2610 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.");
2612 info.className = m_token.m_data.ident;
2614 failIfTrue(classScope->declareLexicalVariable(info.className, true) & DeclarationResult::InvalidStrictMode, "'", info.className->impl(), "' is not a valid class name");
2615 } else if (requirements == FunctionNameRequirements::Named) {
2616 if (match(OPENBRACE))
2617 semanticFail("Class statements must have a name");
2618 semanticFailureDueToKeyword("class name");
2619 failDueToUnexpectedToken();
2621 ASSERT(info.className);
2623 TreeExpression parentClass = 0;
2624 if (consume(EXTENDS)) {
2625 parentClass = parseMemberExpression(context);
2626 failIfFalse(parentClass, "Cannot parse the parent class name");
2628 const ConstructorKind constructorKind = parentClass ? ConstructorKind::Extends : ConstructorKind::Base;
2630 consumeOrFail(OPENBRACE, "Expected opening '{' at the start of a class body");
2632 TreeExpression constructor = 0;
2633 TreePropertyList staticMethods = 0;
2634 TreePropertyList instanceMethods = 0;
2635 TreePropertyList instanceMethodsTail = 0;
2636 TreePropertyList staticMethodsTail = 0;
2637 while (!match(CLOSEBRACE)) {
2638 if (match(SEMICOLON)) {
2643 JSTokenLocation methodLocation(tokenLocation());
2644 unsigned methodStart = tokenStart();
2646 // For backwards compatibility, "static" is a non-reserved keyword in non-strict mode.
2647 bool isStaticMethod = false;
2648 if (match(RESERVED_IF_STRICT) && *m_token.m_data.ident == m_vm->propertyNames->staticKeyword) {
2649 SavePoint savePoint = createSavePoint();
2651 if (match(OPENPAREN)) {
2652 // Reparse "static()" as a method named "static".
2653 restoreSavePoint(savePoint);
2655 isStaticMethod = true;
2658 // FIXME: Figure out a way to share more code with parseProperty.
2659 const CommonIdentifiers& propertyNames = *m_vm->propertyNames;
2660 const Identifier* ident = &propertyNames.nullIdentifier;
2661 TreeExpression computedPropertyName = 0;
2662 bool isGetter = false;
2663 bool isSetter = false;
2664 bool isGenerator = false;
2665 bool isAsyncMethod = false;
2669 UNUSED_LABEL(parseMethod);
2671 switch (m_token.m_type) {
2674 ident = m_token.m_data.ident;
2680 ident = m_token.m_data.ident;
2683 if (!isGenerator && !isAsyncMethod && (matchIdentifierOrKeyword() || match(STRING) || match(DOUBLE) || match(INTEGER) || match(OPENBRACKET))) {
2684 isGetter = *ident == propertyNames.get;
2685 isSetter = *ident == propertyNames.set;
2687 #if ENABLE(ES2017_ASYNCFUNCTION_SYNTAX)
2688 if (UNLIKELY(*ident == propertyNames.async && !m_lexer->prevTerminator() && !isAsyncMethod)) {
2689 isAsyncMethod = true;
2697 ident = &m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), m_token.m_data.doubleValue);
2703 computedPropertyName = parseAssignmentExpression(context);
2704 failIfFalse(computedPropertyName, "Cannot parse computed property name");
2705 handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name");
2708 if (m_token.m_type & KeywordTokenFlag)
2710 failDueToUnexpectedToken();
2713 TreeProperty property;
2714 const bool alwaysStrictInsideClass = true;
2715 if (isGetter || isSetter) {
2716 bool isClassProperty = true;
2717 property = parseGetterSetter(context, alwaysStrictInsideClass, isGetter ? PropertyNode::Getter : PropertyNode::Setter, methodStart,
2718 ConstructorKind::None, isClassProperty);
2719 failIfFalse(property, "Cannot parse this method");
2721 ParserFunctionInfo<TreeBuilder> methodInfo;
2722 bool isConstructor = !isStaticMethod && *ident == propertyNames.constructor;
2723 SourceParseMode parseMode = SourceParseMode::MethodMode;
2724 if (isAsyncMethod) {
2725 isConstructor = false;
2726 parseMode = SourceParseMode::AsyncMethodMode;
2727 semanticFailIfTrue(*ident == m_vm->propertyNames->prototype, "Cannot declare an async method named 'prototype'");
2728 semanticFailIfTrue(*ident == m_vm->propertyNames->constructor, "Cannot declare an async method named 'constructor'");
2729 } else if (isGenerator) {
2730 isConstructor = false;
2731 parseMode = SourceParseMode::GeneratorWrapperFunctionMode;
2732 semanticFailIfTrue(*ident == m_vm->propertyNames->prototype, "Cannot declare a generator named 'prototype'");
2733 semanticFailIfTrue(*ident == m_vm->propertyNames->constructor, "Cannot declare a generator named 'constructor'");
2735 methodInfo.name = isConstructor ? info.className : ident;
2736 failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::Unnamed, parseMode, false, isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, FunctionDefinitionType::Method)), "Cannot parse this method");
2738 TreeExpression method = context.createMethodDefinition(methodLocation, methodInfo);
2739 if (isConstructor) {
2740 semanticFailIfTrue(constructor, "Cannot declare multiple constructors in a single class");
2741 constructor = method;
2745 // FIXME: Syntax error when super() is called
2746 semanticFailIfTrue(isStaticMethod && methodInfo.name && *methodInfo.name == propertyNames.prototype,
2747 "Cannot declare a static method named 'prototype'");
2749 bool isClassProperty = true;
2750 if (computedPropertyName) {
2751 property = context.createProperty(computedPropertyName, method, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed),
2752 PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed, isClassProperty);
2754 property = context.createProperty(methodInfo.name, method, PropertyNode::Constant, PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed, isClassProperty);
2757 TreePropertyList& tail = isStaticMethod ? staticMethodsTail : instanceMethodsTail;
2759 tail = context.createPropertyList(methodLocation, property, tail);
2761 tail = context.createPropertyList(methodLocation, property);
2763 staticMethods = tail;
2765 instanceMethods = tail;
2769 info.endOffset = tokenLocation().endOffset - 1;
2770 consumeOrFail(CLOSEBRACE, "Expected a closing '}' after a class body");
2772 auto classExpression = context.createClassExpr(location, info, classScope->finalizeLexicalEnvironment(), constructor, parentClass, instanceMethods, staticMethods);
2773 popScope(classScope, TreeBuilder::NeedsFreeVariableInfo);
2774 return classExpression;
2778 LabelInfo(const Identifier* ident, const JSTextPosition& start, const JSTextPosition& end)
2785 const Identifier* m_ident;
2786 JSTextPosition m_start;
2787 JSTextPosition m_end;
2790 template <typename LexerType>
2791 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrLabelStatement(TreeBuilder& context, bool allowFunctionDeclarationAsStatement)
2794 /* Expression and Label statements are ambiguous at LL(1), so we have a
2795 * special case that looks for a colon as the next character in the input.
2797 Vector<LabelInfo> labels;
2798 JSTokenLocation location;
2800 JSTextPosition start = tokenStartPosition();
2801 location = tokenLocation();
2802 if (!nextTokenIsColon()) {
2803 // If we hit this path we're making a expression statement, which
2804 // by definition can't make use of continue/break so we can just
2805 // ignore any labels we might have accumulated.
2806 TreeExpression expression = parseExpression(context);
2807 failIfFalse(expression, "Cannot parse expression statement");
2808 if (!autoSemiColon())
2809 failDueToUnexpectedToken();
2810 return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
2813 if (UNLIKELY(match(AWAIT)))
2814 semanticFailIfTrue(isDisallowedIdentifierAwait(m_token), "Can't use 'await' as a label ", disallowedIdentifierAwaitReason());
2816 const Identifier* ident = m_token.m_data.ident;
2817 JSTextPosition end = tokenEndPosition();
2819 consumeOrFail(COLON, "Labels must be followed by a ':'");
2820 if (!m_syntaxAlreadyValidated) {
2821 // This is O(N^2) over the current list of consecutive labels, but I
2822 // have never seen more than one label in a row in the real world.
2823 for (size_t i = 0; i < labels.size(); i++)
2824 failIfTrue(ident->impl() == labels[i].m_ident->impl(), "Attempted to redeclare the label '", ident->impl(), "'");
2825 failIfTrue(getLabel(ident), "Cannot find scope for the label '", ident->impl(), "'");
2826 labels.append(LabelInfo(ident, start, end));
2828 } while (matchSpecIdentifier());
2829 bool isLoop = false;
2830 switch (m_token.m_type) {
2840 const Identifier* unused = 0;
2841 ScopeRef labelScope = currentScope();
2842 if (!m_syntaxAlreadyValidated) {
2843 for (size_t i = 0; i < labels.size(); i++)
2844 pushLabel(labels[i].m_ident, isLoop);
2846 m_immediateParentAllowsFunctionDeclarationInStatement = allowFunctionDeclarationAsStatement;
2847 TreeStatement statement = parseStatement(context, unused);
2848 if (!m_syntaxAlreadyValidated) {
2849 for (size_t i = 0; i < labels.size(); i++)
2850 popLabel(labelScope);
2852 failIfFalse(statement, "Cannot parse statement");
2853 for (size_t i = 0; i < labels.size(); i++) {
2854 const LabelInfo& info = labels[labels.size() - i - 1];
2855 statement = context.createLabelStatement(location, info.m_ident, statement, info.m_start, info.m_end);
2860 template <typename LexerType>
2861 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionStatement(TreeBuilder& context)
2863 switch (m_token.m_type) {
2864 // Consult: http://www.ecma-international.org/ecma-262/6.0/index.html#sec-expression-statement
2865 // The ES6 spec mandates that we should fail from FUNCTION token here. We handle this case
2866 // in parseStatement() which is the only caller of parseExpressionStatement().
2867 // We actually allow FUNCTION in situations where it should not be allowed unless we're in strict mode.
2869 failWithMessage("'class' declaration is not directly within a block statement");
2872 // FIXME: when implementing 'let' we should fail when we see the token sequence "let [".
2873 // https://bugs.webkit.org/show_bug.cgi?id=142944
2876 JSTextPosition start = tokenStartPosition();
2877 JSTokenLocation location(tokenLocation());
2878 TreeExpression expression = parseExpression(context);
2879 failIfFalse(expression, "Cannot parse expression statement");
2880 failIfFalse(autoSemiColon(), "Parse error");
2881 return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
2884 template <typename LexerType>
2885 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(TreeBuilder& context)
2888 JSTokenLocation ifLocation(tokenLocation());
2889 int start = tokenLine();
2891 handleProductionOrFail2(OPENPAREN, "(", "start", "'if' condition");
2893 TreeExpression condition = parseExpression(context);
2894 failIfFalse(condition, "Expected a expression as the condition for an if statement");
2895 recordPauseLocation(context.breakpointLocation(condition));
2896 int end = tokenLine();
2897 handleProductionOrFail2(CLOSEPAREN, ")", "end", "'if' condition");
2899 const Identifier* unused = 0;
2900 m_immediateParentAllowsFunctionDeclarationInStatement = true;
2901 TreeStatement trueBlock = parseStatement(context, unused);
2902 failIfFalse(trueBlock, "Expected a statement as the body of an if block");
2905 return context.createIfStatement(ifLocation, condition, trueBlock, 0, start, end);
2907 Vector<TreeExpression> exprStack;
2908 Vector<std::pair<int, int>> posStack;
2909 Vector<JSTokenLocation> tokenLocationStack;
2910 Vector<TreeStatement> statementStack;
2911 bool trailingElse = false;
2913 JSTokenLocation tempLocation = tokenLocation();
2916 const Identifier* unused = 0;
2917 m_immediateParentAllowsFunctionDeclarationInStatement = true;
2918 TreeStatement block = parseStatement(context, unused);
2919 failIfFalse(block, "Expected a statement as the body of an else block");
2920 statementStack.append(block);
2921 trailingElse = true;
2924 int innerStart = tokenLine();
2927 handleProductionOrFail2(OPENPAREN, "(", "start", "'if' condition");
2929 TreeExpression innerCondition = parseExpression(context);
2930 failIfFalse(innerCondition, "Expected a expression as the condition for an if statement");
2931 recordPauseLocation(context.breakpointLocation(innerCondition));
2932 int innerEnd = tokenLine();
2933 handleProductionOrFail2(CLOSEPAREN, ")", "end", "'if' condition");
2934 const Identifier* unused = 0;
2935 m_immediateParentAllowsFunctionDeclarationInStatement = true;
2936 TreeStatement innerTrueBlock = parseStatement(context, unused);
2937 failIfFalse(innerTrueBlock, "Expected a statement as the body of an if block");
2938 tokenLocationStack.append(tempLocation);
2939 exprStack.append(innerCondition);
2940 posStack.append(std::make_pair(innerStart, innerEnd));
2941 statementStack.append(innerTrueBlock);
2942 } while (match(ELSE));
2944 if (!trailingElse) {
2945 TreeExpression condition = exprStack.last();
2946 exprStack.removeLast();
2947 TreeStatement trueBlock = statementStack.last();
2948 statementStack.removeLast();
2949 std::pair<int, int> pos = posStack.last();
2950 posStack.removeLast();
2951 JSTokenLocation elseLocation = tokenLocationStack.last();
2952 tokenLocationStack.removeLast();
2953 TreeStatement ifStatement = context.createIfStatement(elseLocation, condition, trueBlock, 0, pos.first, pos.second);
2954 context.setEndOffset(ifStatement, context.endOffset(trueBlock));
2955 statementStack.append(ifStatement);
2958 while (!exprStack.isEmpty()) {
2959 TreeExpression condition = exprStack.last();
2960 exprStack.removeLast();
2961 TreeStatement falseBlock = statementStack.last();
2962 statementStack.removeLast();
2963 TreeStatement trueBlock = statementStack.last();
2964 statementStack.removeLast();
2965 std::pair<int, int> pos = posStack.last();
2966 posStack.removeLast();
2967 JSTokenLocation elseLocation = tokenLocationStack.last();
2968 tokenLocationStack.removeLast();
2969 TreeStatement ifStatement = context.createIfStatement(elseLocation, condition, trueBlock, falseBlock, pos.first, pos.second);
2970 context.setEndOffset(ifStatement, context.endOffset(falseBlock));
2971 statementStack.append(ifStatement);
2974 return context.createIfStatement(ifLocation, condition, trueBlock, statementStack.last(), start, end);
2977 template <typename LexerType>
2978 template <class TreeBuilder> typename TreeBuilder::ModuleName Parser<LexerType>::parseModuleName(TreeBuilder& context)
2980 // ModuleName (ModuleSpecifier in the spec) represents the module name imported by the script.
2981 // http://www.ecma-international.org/ecma-262/6.0/#sec-imports
2982 // http://www.ecma-international.org/ecma-262/6.0/#sec-exports
2983 JSTokenLocation specifierLocation(tokenLocation());
2984 failIfFalse(match(STRING), "Imported modules names must be string literals");
2985 const Identifier* moduleName = m_token.m_data.ident;
2987 return context.createModuleName(specifierLocation, *moduleName);
2990 template <typename LexerType>
2991 template <class TreeBuilder> typename TreeBuilder::ImportSpecifier Parser<LexerType>::parseImportClauseItem(TreeBuilder& context, ImportSpecifierType specifierType)
2993 // Produced node is the item of the ImportClause.
2994 // That is the ImportSpecifier, ImportedDefaultBinding or NameSpaceImport.
2995 // http://www.ecma-international.org/ecma-262/6.0/#sec-imports
2996 JSTokenLocation specifierLocation(tokenLocation());
2997 JSToken localNameToken;
2998 const Identifier* importedName = nullptr;
2999 const Identifier* localName = nullptr;
3001 switch (specifierType) {
3002 case ImportSpecifierType::NamespaceImport: {
3003 // NameSpaceImport :
3004 // * as ImportedBinding
3007 ASSERT(match(TIMES));
3008 importedName = &m_vm->propertyNames->timesIdentifier;
3011 failIfFalse(matchContextualKeyword(m_vm->propertyNames->as), "Expected 'as' before imported binding name");
3014 failIfFalse(matchSpecIdentifier(), "Expected a variable name for the import declaration");
3015 localNameToken = m_token;
3016 localName = m_token.m_data.ident;
3021 case ImportSpecifierType::NamedImport: {
3022 // ImportSpecifier :
3024 // IdentifierName as ImportedBinding
3028 ASSERT(matchIdentifierOrKeyword());
3029 localNameToken = m_token;
3030 localName = m_token.m_data.ident;
3031 importedName = localName;
3034 if (matchContextualKeyword(m_vm->propertyNames->as)) {
3036 failIfFalse(matchSpecIdentifier(), "Expected a variable name for the import declaration");
3037 localNameToken = m_token;
3038 localName = m_token.m_data.ident;
3044 case ImportSpecifierType::DefaultImport: {
3045 // ImportedDefaultBinding :
3047 ASSERT(matchSpecIdentifier());
3048 localNameToken = m_token;
3049 localName = m_token.m_data.ident;
3050 importedName = &m_vm->propertyNames->defaultKeyword;
3056 semanticFailIfTrue(localNameToken.m_type == AWAIT, "Cannot use 'await' as an imported binding name");
3057 semanticFailIfTrue(localNameToken.m_type & KeywordTokenFlag, "Cannot use keyword as imported binding name");
3058 DeclarationResultMask declarationResult = declareVariable(localName, DeclarationType::ConstDeclaration, (specifierType == ImportSpecifierType::NamespaceImport) ? DeclarationImportType::ImportedNamespace : DeclarationImportType::Imported);
3059 if (declarationResult != DeclarationResult::Valid) {
3060 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare an imported binding named ", localName->impl(), " in strict mode");
3061 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
3062 internalFailWithMessage(false, "Cannot declare an imported binding name twice: '", localName->impl(), "'");
3065 return context.createImportSpecifier(specifierLocation, *importedName, *localName);
3068 template <typename LexerType>
3069 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseImportDeclaration(TreeBuilder& context)
3071 // http://www.ecma-international.org/ecma-262/6.0/#sec-imports
3072 ASSERT(match(IMPORT));
3073 JSTokenLocation importLocation(tokenLocation());
3076 auto specifierList = context.createImportSpecifierList();
3078 if (match(STRING)) {
3079 // import ModuleSpecifier ;
3080 auto moduleName = parseModuleName(context);
3081 failIfFalse(moduleName, "Cannot parse the module name");
3082 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted import declaration");
3083 return context.createImportDeclaration(importLocation, specifierList, moduleName);
3086 bool isFinishedParsingImport = false;
3087 if (matchSpecIdentifier()) {
3088 // ImportedDefaultBinding :
3090 auto specifier = parseImportClauseItem(context, ImportSpecifierType::DefaultImport);
3091 failIfFalse(specifier, "Cannot parse the default import");
3092 context.appendImportSpecifier(specifierList, specifier);
3096 isFinishedParsingImport = true;
3099 if (!isFinishedParsingImport) {
3101 // import NameSpaceImport FromClause ;
3102 auto specifier = parseImportClauseItem(context, ImportSpecifierType::NamespaceImport);
3103 failIfFalse(specifier, "Cannot parse the namespace import");
3104 context.appendImportSpecifier(specifierList, specifier);
3105 } else if (match(OPENBRACE)) {
3109 // { ImportsList , }
3112 while (!match(CLOSEBRACE)) {
3113 failIfFalse(matchIdentifierOrKeyword(), "Expected an imported name for the import declaration");
3114 auto specifier = parseImportClauseItem(context, ImportSpecifierType::NamedImport);
3115 failIfFalse(specifier, "Cannot parse the named import");
3116 context.appendImportSpecifier(specifierList, specifier);
3117 if (!consume(COMMA))
3120 handleProductionOrFail2(CLOSEBRACE, "}", "end", "import list");
3122 failWithMessage("Expected namespace import or import list");
3126 // from ModuleSpecifier
3128 failIfFalse(matchContextualKeyword(m_vm->propertyNames->from), "Expected 'from' before imported module name");
3131 auto moduleName = parseModuleName(context);
3132 failIfFalse(moduleName, "Cannot parse the module name");
3133 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted import declaration");
3135 return context.createImportDeclaration(importLocation, specifierList, moduleName);
3138 template <typename LexerType>
3139 template <class TreeBuilder> typename TreeBuilder::ExportSpecifier Parser<LexerType>::parseExportSpecifier(TreeBuilder& context, Vector<std::pair<const Identifier*, const Identifier*>>& maybeExportedLocalNames, bool& hasKeywordForLocalBindings)
3141 // ExportSpecifier :
3143 // IdentifierName as IdentifierName
3144 // http://www.ecma-international.org/ecma-262/6.0/#sec-exports
3145 ASSERT(matchIdentifierOrKeyword());
3146 JSTokenLocation specifierLocation(tokenLocation());
3147 if (m_token.m_type & KeywordTokenFlag)
3148 hasKeywordForLocalBindings = true;
3149 const Identifier* localName = m_token.m_data.ident;
3150 const Identifier* exportedName = localName;
3153 if (matchContextualKeyword(m_vm->propertyNames->as)) {
3155 failIfFalse(matchIdentifierOrKeyword(), "Expected an exported name for the export declaration");
3156 exportedName = m_token.m_data.ident;
3160 semanticFailIfFalse(exportName(*exportedName), "Cannot export a duplicate name '", exportedName->impl(), "'");
3161 maybeExportedLocalNames.append(std::make_pair(localName, exportedName));
3162 return context.createExportSpecifier(specifierLocation, *localName, *exportedName);
3165 template <typename LexerType>
3166 template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExportDeclaration(TreeBuilder& context)
3168 // http://www.ecma-international.org/ecma-262/6.0/#sec-exports
3169 ASSERT(match(EXPORT));
3170 JSTokenLocation exportLocation(tokenLocation());
3173 switch (m_token.m_type) {
3175 // export * FromClause ;
3178 failIfFalse(matchContextualKeyword(m_vm->propertyNames->from), "Expected 'from' before exported module name");
3180 auto moduleName = parseModuleName(context);
3181 failIfFalse(moduleName, "Cannot parse the 'from' clause");
3182 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted export declaration");
3184 return context.createExportAllDeclaration(exportLocation, moduleName);
3188 // export default HoistableDeclaration[Default]
3189 // export default ClassDeclaration[Default]
3190 // export default [lookahead not-in {function, class}] AssignmentExpression[In] ;
3194 TreeStatement result = 0;
3195 bool isFunctionOrClassDeclaration = false;