1/*
2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 * Copyright (C) 2003-2019 Apple Inc. All rights reserved.
5 *
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.
10 *
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.
15 *
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.
20 *
21 */
22
23#include "config.h"
24#include "Parser.h"
25
26#include "ASTBuilder.h"
27#include "BuiltinNames.h"
28#include "DebuggerParseData.h"
29#include "JSCInlines.h"
30#include "VM.h"
31#include <utility>
32#include <wtf/SetForScope.h>
33#include <wtf/StringPrintStream.h>
34
35#define updateErrorMessage(shouldPrintToken, ...) do {\
36 propagateError(); \
37 logError(shouldPrintToken, __VA_ARGS__); \
38} while (0)
39
40#define propagateError() do { if (UNLIKELY(hasError())) return 0; } while (0)
41#define internalFailWithMessage(shouldPrintToken, ...) do { updateErrorMessage(shouldPrintToken, __VA_ARGS__); return 0; } while (0)
42#define handleErrorToken() do { if (m_token.m_type == EOFTOK || m_token.m_type & ErrorTokenFlag) { failDueToUnexpectedToken(); } } while (0)
43#define failWithMessage(...) do { { handleErrorToken(); updateErrorMessage(true, __VA_ARGS__); } return 0; } while (0)
44#define failWithStackOverflow() do { updateErrorMessage(false, "Stack exhausted"); m_hasStackOverflow = true; return 0; } while (0)
45#define failIfFalse(cond, ...) do { if (!(cond)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
46#define failIfTrue(cond, ...) do { if (cond) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
47#define failIfTrueIfStrict(cond, ...) do { if ((cond) && strictMode()) internalFailWithMessage(false, __VA_ARGS__); } while (0)
48#define failIfFalseIfStrict(cond, ...) do { if ((!(cond)) && strictMode()) internalFailWithMessage(false, __VA_ARGS__); } while (0)
49#define consumeOrFail(tokenType, ...) do { if (!consume(tokenType)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
50#define consumeOrFailWithFlags(tokenType, flags, ...) do { if (!consume(tokenType, flags)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
51#define matchOrFail(tokenType, ...) do { if (!match(tokenType)) { handleErrorToken(); internalFailWithMessage(true, __VA_ARGS__); } } while (0)
52#define failIfStackOverflow() do { if (UNLIKELY(!canRecurse())) failWithStackOverflow(); } while (0)
53#define semanticFail(...) do { internalFailWithMessage(false, __VA_ARGS__); } while (0)
54#define semanticFailIfTrue(cond, ...) do { if (UNLIKELY(cond)) internalFailWithMessage(false, __VA_ARGS__); } while (0)
55#define semanticFailIfFalse(cond, ...) do { if (UNLIKELY(!(cond))) internalFailWithMessage(false, __VA_ARGS__); } while (0)
56#define regexFail(failure) do { setErrorMessage(failure); return 0; } while (0)
57#define failDueToUnexpectedToken() do {\
58 logError(true);\
59 return 0;\
60} while (0)
61
62#define handleProductionOrFail(token, tokenString, operation, production) do {\
63 consumeOrFail(token, "Expected '", tokenString, "' to ", operation, " a ", production);\
64} while (0)
65
66#define handleProductionOrFail2(token, tokenString, operation, production) do {\
67 consumeOrFail(token, "Expected '", tokenString, "' to ", operation, " an ", production);\
68} while (0)
69
70#define semanticFailureDueToKeywordCheckingToken(token, ...) do { \
71 if (strictMode() && token.m_type == RESERVED_IF_STRICT) \
72 semanticFail("Cannot use the reserved word '", getToken(token), "' as a ", __VA_ARGS__, " in strict mode"); \
73 if (token.m_type == RESERVED || token.m_type == RESERVED_IF_STRICT) \
74 semanticFail("Cannot use the reserved word '", getToken(token), "' as a ", __VA_ARGS__); \
75 if (token.m_type & KeywordTokenFlag) { \
76 if (!isAnyContextualKeyword(token)) \
77 semanticFail("Cannot use the keyword '", getToken(token), "' as a ", __VA_ARGS__); \
78 if (isDisallowedIdentifierLet(token)) \
79 semanticFail("Cannot use 'let' as a ", __VA_ARGS__, " ", disallowedIdentifierLetReason()); \
80 if (isDisallowedIdentifierAwait(token)) \
81 semanticFail("Cannot use 'await' as a ", __VA_ARGS__, " ", disallowedIdentifierAwaitReason()); \
82 if (isDisallowedIdentifierYield(token)) \
83 semanticFail("Cannot use 'yield' as a ", __VA_ARGS__, " ", disallowedIdentifierYieldReason()); \
84 } \
85} while (0)
86
87#define semanticFailureDueToKeyword(...) semanticFailureDueToKeywordCheckingToken(m_token, __VA_ARGS__);
88
89namespace JSC {
90
91std::atomic<unsigned> globalParseCount { 0 };
92
93ALWAYS_INLINE static SourceParseMode getAsynFunctionBodyParseMode(SourceParseMode parseMode)
94{
95 if (isAsyncGeneratorWrapperParseMode(parseMode))
96 return SourceParseMode::AsyncGeneratorBodyMode;
97
98 if (parseMode == SourceParseMode::AsyncArrowFunctionMode)
99 return SourceParseMode::AsyncArrowFunctionBodyMode;
100
101 return SourceParseMode::AsyncFunctionBodyMode;
102}
103
104template <typename LexerType>
105void Parser<LexerType>::logError(bool)
106{
107 if (hasError())
108 return;
109 StringPrintStream stream;
110 printUnexpectedTokenText(stream);
111 setErrorMessage(stream.toStringWithLatin1Fallback());
112}
113
114template <typename LexerType> template <typename... Args>
115void Parser<LexerType>::logError(bool shouldPrintToken, Args&&... args)
116{
117 if (hasError())
118 return;
119 StringPrintStream stream;
120 if (shouldPrintToken) {
121 printUnexpectedTokenText(stream);
122 stream.print(". ");
123 }
124 stream.print(std::forward<Args>(args)..., ".");
125 setErrorMessage(stream.toStringWithLatin1Fallback());
126}
127
128template <typename LexerType>
129Parser<LexerType>::Parser(VM& vm, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, SourceParseMode parseMode, SuperBinding superBinding, ConstructorKind defaultConstructorKindForTopLevelFunction, DerivedContextType derivedContextType, bool isEvalContext, EvalContextType evalContextType, DebuggerParseData* debuggerParseData)
130 : m_vm(vm)
131 , m_source(&source)
132 , m_hasStackOverflow(false)
133 , m_allowsIn(true)
134 , m_statementDepth(0)
135 , m_sourceElements(0)
136 , m_parsingBuiltin(builtinMode == JSParserBuiltinMode::Builtin)
137 , m_scriptMode(scriptMode)
138 , m_superBinding(superBinding)
139 , m_defaultConstructorKindForTopLevelFunction(defaultConstructorKindForTopLevelFunction)
140 , m_immediateParentAllowsFunctionDeclarationInStatement(false)
141 , m_debuggerParseData(debuggerParseData)
142{
143 m_lexer = makeUnique<LexerType>(vm, builtinMode, scriptMode);
144 m_lexer->setCode(source, &m_parserArena);
145 m_token.m_location.line = source.firstLine().oneBasedInt();
146 m_token.m_location.startOffset = source.startOffset();
147 m_token.m_location.endOffset = source.startOffset();
148 m_token.m_location.lineStartOffset = source.startOffset();
149 m_functionCache = vm.addSourceProviderCache(source.provider());
150 m_expressionErrorClassifier = nullptr;
151
152 ScopeRef scope = pushScope();
153 scope->setSourceParseMode(parseMode);
154 scope->setIsEvalContext(isEvalContext);
155 if (isEvalContext)
156 scope->setEvalContextType(evalContextType);
157
158 if (derivedContextType == DerivedContextType::DerivedConstructorContext) {
159 scope->setConstructorKind(ConstructorKind::Extends);
160 scope->setExpectedSuperBinding(SuperBinding::Needed);
161 }
162
163 if (derivedContextType == DerivedContextType::DerivedMethodContext)
164 scope->setExpectedSuperBinding(SuperBinding::Needed);
165
166 if (strictMode == JSParserStrictMode::Strict)
167 scope->setStrictMode();
168
169 if (isModuleParseMode(parseMode))
170 m_moduleScopeData = ModuleScopeData::create();
171
172 if (isProgramOrModuleParseMode(parseMode))
173 scope->setIsGlobalCodeScope();
174
175 next();
176}
177
178class Scope::MaybeParseAsGeneratorForScope {
179public:
180 MaybeParseAsGeneratorForScope(ScopeRef& scope, bool shouldParseAsGenerator)
181 : m_scope(scope)
182 , m_oldValue(scope->m_isGenerator)
183 {
184 m_scope->m_isGenerator = shouldParseAsGenerator;
185 }
186
187 ~MaybeParseAsGeneratorForScope()
188 {
189 m_scope->m_isGenerator = m_oldValue;
190 }
191
192private:
193 ScopeRef m_scope;
194 bool m_oldValue;
195};
196
197struct DepthManager : private SetForScope<int> {
198public:
199 DepthManager(int* depth)
200 : SetForScope<int>(*depth, *depth)
201 {
202 }
203};
204
205template <typename LexerType>
206Parser<LexerType>::~Parser()
207{
208}
209
210template <typename LexerType>
211String Parser<LexerType>::parseInner(const Identifier& calleeName, SourceParseMode parseMode, ParsingContext parsingContext, Optional<int> functionConstructorParametersEndPosition)
212{
213 String parseError = String();
214
215 ASTBuilder context(const_cast<VM&>(m_vm), m_parserArena, const_cast<SourceCode*>(m_source));
216 ScopeRef scope = currentScope();
217 scope->setIsLexicalScope();
218 SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_parserState.functionParsePhase, FunctionParsePhase::Body);
219
220 bool isArrowFunctionBodyExpression = parseMode == SourceParseMode::AsyncArrowFunctionBodyMode && !match(OPENBRACE);
221 if (m_lexer->isReparsingFunction()) {
222 ParserFunctionInfo<ASTBuilder> functionInfo;
223 if (isGeneratorOrAsyncFunctionBodyParseMode(parseMode))
224 m_parameters = createGeneratorParameters(context, functionInfo.parameterCount);
225 else
226 m_parameters = parseFunctionParameters(context, parseMode, functionInfo);
227
228 if (SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode).contains(parseMode) && !hasError()) {
229 // The only way we could have an error wile reparsing is if we run out of stack space.
230 RELEASE_ASSERT(match(ARROWFUNCTION));
231 next();
232 isArrowFunctionBodyExpression = !match(OPENBRACE);
233 }
234 }
235
236 if (!calleeName.isNull())
237 scope->declareCallee(&calleeName);
238
239 if (m_lexer->isReparsingFunction())
240 m_statementDepth--;
241
242 SourceElements* sourceElements = nullptr;
243 // The only way we can error this early is if we reparse a function and we run out of stack space.
244 if (!hasError()) {
245 if (isAsyncFunctionWrapperParseMode(parseMode))
246 sourceElements = parseAsyncFunctionSourceElements(context, parseMode, isArrowFunctionBodyExpression, CheckForStrictMode);
247 else if (isArrowFunctionBodyExpression)
248 sourceElements = parseArrowFunctionSingleExpressionBodySourceElements(context);
249 else if (isModuleParseMode(parseMode))
250 sourceElements = parseModuleSourceElements(context, parseMode);
251 else if (isGeneratorWrapperParseMode(parseMode))
252 sourceElements = parseGeneratorFunctionSourceElements(context, calleeName, CheckForStrictMode);
253 else if (isAsyncGeneratorWrapperParseMode(parseMode))
254 sourceElements = parseAsyncGeneratorFunctionSourceElements(context, parseMode, isArrowFunctionBodyExpression, CheckForStrictMode);
255 else if (parsingContext == ParsingContext::FunctionConstructor)
256 sourceElements = parseSingleFunction(context, functionConstructorParametersEndPosition);
257 else
258 sourceElements = parseSourceElements(context, CheckForStrictMode);
259 }
260
261 bool validEnding = consume(EOFTOK);
262 if (!sourceElements || !validEnding) {
263 if (hasError())
264 parseError = m_errorMessage;
265 else
266 parseError = "Parser error"_s;
267 }
268
269 IdentifierSet capturedVariables;
270 UniquedStringImplPtrSet sloppyModeHoistedFunctions;
271 scope->getSloppyModeHoistedFunctions(sloppyModeHoistedFunctions);
272 scope->getCapturedVars(capturedVariables);
273
274 VariableEnvironment& varDeclarations = scope->declaredVariables();
275 for (auto& entry : capturedVariables)
276 varDeclarations.markVariableAsCaptured(entry);
277
278 if (isGeneratorWrapperParseMode(parseMode) || isAsyncFunctionOrAsyncGeneratorWrapperParseMode(parseMode)) {
279 if (scope->usedVariablesContains(m_vm.propertyNames->arguments.impl()))
280 context.propagateArgumentsUse();
281 }
282
283 CodeFeatures features = context.features();
284 if (scope->strictMode())
285 features |= StrictModeFeature;
286 if (scope->shadowsArguments())
287 features |= ShadowsArgumentsFeature;
288 if (m_seenTaggedTemplate)
289 features |= NoEvalCacheFeature;
290
291#ifndef NDEBUG
292 if (m_parsingBuiltin && isProgramParseMode(parseMode)) {
293 VariableEnvironment& lexicalVariables = scope->lexicalVariables();
294 const HashSet<UniquedStringImpl*>& closedVariableCandidates = scope->closedVariableCandidates();
295 for (UniquedStringImpl* candidate : closedVariableCandidates) {
296 // FIXME: We allow async to leak because it appearing as a closed variable is a side effect of trying to parse async arrow functions.
297 if (!lexicalVariables.contains(candidate) && !varDeclarations.contains(candidate) && !candidate->isSymbol() && candidate != m_vm.propertyNames->async.impl()) {
298 dataLog("Bad global capture in builtin: '", candidate, "'\n");
299 dataLog(m_source->view());
300 CRASH();
301 }
302 }
303 }
304#endif // NDEBUG
305 didFinishParsing(sourceElements, scope->takeFunctionDeclarations(), varDeclarations, WTFMove(sloppyModeHoistedFunctions), features, context.numConstants());
306
307 return parseError;
308}
309
310template <typename LexerType>
311void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, DeclarationStacks::FunctionStack&& funcStack,
312 VariableEnvironment& varDeclarations, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, CodeFeatures features, int numConstants)
313{
314 m_sourceElements = sourceElements;
315 m_funcDeclarations = WTFMove(funcStack);
316 m_varDeclarations.swap(varDeclarations);
317 m_features = features;
318 m_sloppyModeHoistedFunctions = WTFMove(sloppyModeHoistedFunctions);
319 m_numConstants = numConstants;
320}
321
322template <typename LexerType>
323bool Parser<LexerType>::isArrowFunctionParameters()
324{
325 if (match(OPENPAREN)) {
326 SavePoint saveArrowFunctionPoint = createSavePoint();
327 next();
328 bool isArrowFunction = false;
329 if (match(CLOSEPAREN)) {
330 next();
331 isArrowFunction = match(ARROWFUNCTION);
332 } else {
333 SyntaxChecker syntaxChecker(const_cast<VM&>(m_vm), m_lexer.get());
334 // We make fake scope, otherwise parseFormalParameters will add variable to current scope that lead to errors
335 AutoPopScopeRef fakeScope(this, pushScope());
336 fakeScope->setSourceParseMode(SourceParseMode::ArrowFunctionMode);
337
338 unsigned parametersCount = 0;
339 bool isArrowFunctionParameterList = true;
340 bool isMethod = false;
341 isArrowFunction = parseFormalParameters(syntaxChecker, syntaxChecker.createFormalParameterList(), isArrowFunctionParameterList, isMethod, parametersCount) && consume(CLOSEPAREN) && match(ARROWFUNCTION);
342 propagateError();
343 popScope(fakeScope, syntaxChecker.NeedsFreeVariableInfo);
344 }
345 restoreSavePoint(saveArrowFunctionPoint);
346 return isArrowFunction;
347 }
348
349 if (matchSpecIdentifier()) {
350 semanticFailIfTrue(!m_parserState.allowAwait && match(AWAIT), "Cannot use 'await' as a parameter name in an async function");
351 SavePoint saveArrowFunctionPoint = createSavePoint();
352 next();
353 bool isArrowFunction = match(ARROWFUNCTION);
354 restoreSavePoint(saveArrowFunctionPoint);
355 return isArrowFunction;
356 }
357
358 return false;
359}
360
361template <typename LexerType>
362bool Parser<LexerType>::allowAutomaticSemicolon()
363{
364 return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->hasLineTerminatorBeforeToken();
365}
366
367template <typename LexerType>
368template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context, SourceElementsMode mode)
369{
370 const unsigned lengthOfUseStrictLiteral = 12; // "use strict".length
371 TreeSourceElements sourceElements = context.createSourceElements();
372 const Identifier* directive = 0;
373 unsigned directiveLiteralLength = 0;
374 auto savePoint = createSavePoint();
375 bool shouldCheckForUseStrict = mode == CheckForStrictMode;
376
377 while (TreeStatement statement = parseStatementListItem(context, directive, &directiveLiteralLength)) {
378 if (shouldCheckForUseStrict) {
379 if (directive) {
380 // "use strict" must be the exact literal without escape sequences or line continuation.
381 if (directiveLiteralLength == lengthOfUseStrictLiteral && m_vm.propertyNames->useStrictIdentifier == *directive) {
382 setStrictMode();
383 shouldCheckForUseStrict = false; // We saw "use strict", there is no need to keep checking for it.
384 if (!isValidStrictMode()) {
385 if (m_parserState.lastFunctionName) {
386 if (m_vm.propertyNames->arguments == *m_parserState.lastFunctionName)
387 semanticFail("Cannot name a function 'arguments' in strict mode");
388 if (m_vm.propertyNames->eval == *m_parserState.lastFunctionName)
389 semanticFail("Cannot name a function 'eval' in strict mode");
390 }
391 if (hasDeclaredVariable(m_vm.propertyNames->arguments))
392 semanticFail("Cannot declare a variable named 'arguments' in strict mode");
393 if (hasDeclaredVariable(m_vm.propertyNames->eval))
394 semanticFail("Cannot declare a variable named 'eval' in strict mode");
395 semanticFailIfTrue(currentScope()->hasNonSimpleParameterList(), "'use strict' directive not allowed inside a function with a non-simple parameter list");
396 semanticFailIfFalse(isValidStrictMode(), "Invalid parameters or function name in strict mode");
397 }
398 // Since strict mode is changed, restoring lexer state by calling next() may cause errors.
399 restoreSavePoint(savePoint);
400 propagateError();
401 continue;
402 }
403
404 // We saw a directive, but it wasn't "use strict". We reset our state to
405 // see if the next statement we parse is also a directive.
406 directive = nullptr;
407 } else {
408 // We saw a statement that wasn't in the form of a directive. The spec says that "use strict"
409 // is only allowed as the first statement, or after a sequence of directives before it, but
410 // not after non-directive statements.
411 shouldCheckForUseStrict = false;
412 }
413 }
414 context.appendStatement(sourceElements, statement);
415 }
416
417 propagateError();
418 return sourceElements;
419}
420
421template <typename LexerType>
422template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseModuleSourceElements(TreeBuilder& context, SourceParseMode parseMode)
423{
424 TreeSourceElements sourceElements = context.createSourceElements();
425 SyntaxChecker syntaxChecker(const_cast<VM&>(m_vm), m_lexer.get());
426
427 while (true) {
428 TreeStatement statement = 0;
429 switch (m_token.m_type) {
430 case EXPORT_:
431 statement = parseExportDeclaration(context);
432 if (statement)
433 recordPauseLocation(context.breakpointLocation(statement));
434 break;
435
436 case IMPORT: {
437 SavePoint savePoint = createSavePoint();
438 next();
439 bool isImportDeclaration = !match(OPENPAREN) && !match(DOT);
440 restoreSavePoint(savePoint);
441 if (isImportDeclaration) {
442 statement = parseImportDeclaration(context);
443 if (statement)
444 recordPauseLocation(context.breakpointLocation(statement));
445 break;
446 }
447
448 // This is `import("...")` call or `import.meta` meta property case.
449 FALLTHROUGH;
450 }
451
452 default: {
453 const Identifier* directive = 0;
454 unsigned directiveLiteralLength = 0;
455 if (parseMode == SourceParseMode::ModuleAnalyzeMode) {
456 if (!parseStatementListItem(syntaxChecker, directive, &directiveLiteralLength))
457 goto end;
458 continue;
459 }
460 statement = parseStatementListItem(context, directive, &directiveLiteralLength);
461 break;
462 }
463 }
464
465 if (!statement)
466 goto end;
467 context.appendStatement(sourceElements, statement);
468 }
469
470end:
471 propagateError();
472
473 for (const auto& pair : m_moduleScopeData->exportedBindings()) {
474 const auto& uid = pair.key;
475 if (currentScope()->hasDeclaredVariable(uid)) {
476 currentScope()->declaredVariables().markVariableAsExported(uid);
477 continue;
478 }
479
480 if (currentScope()->hasLexicallyDeclaredVariable(uid)) {
481 currentScope()->lexicalVariables().markVariableAsExported(uid);
482 continue;
483 }
484
485 semanticFail("Exported binding '", uid.get(), "' needs to refer to a top-level declared variable");
486 }
487
488 return sourceElements;
489}
490
491template <typename LexerType>
492template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseGeneratorFunctionSourceElements(TreeBuilder& context, const Identifier& name, SourceElementsMode mode)
493{
494 auto sourceElements = context.createSourceElements();
495
496 unsigned functionKeywordStart = tokenStart();
497 JSTokenLocation startLocation(tokenLocation());
498 JSTextPosition start = tokenStartPosition();
499 unsigned startColumn = tokenColumn();
500 int functionNameStart = m_token.m_location.startOffset;
501 int parametersStart = m_token.m_location.startOffset;
502
503 ParserFunctionInfo<TreeBuilder> info;
504 info.name = &m_vm.propertyNames->nullIdentifier;
505 createGeneratorParameters(context, info.parameterCount);
506 info.startOffset = parametersStart;
507 info.startLine = tokenLine();
508
509 {
510 AutoPopScopeRef generatorBodyScope(this, pushScope());
511 generatorBodyScope->setSourceParseMode(SourceParseMode::GeneratorBodyMode);
512 generatorBodyScope->setConstructorKind(ConstructorKind::None);
513 generatorBodyScope->setExpectedSuperBinding(m_superBinding);
514
515 SyntaxChecker generatorFunctionContext(const_cast<VM&>(m_vm), m_lexer.get());
516 failIfFalse(parseSourceElements(generatorFunctionContext, mode), "Cannot parse the body of a generator");
517 popScope(generatorBodyScope, TreeBuilder::NeedsFreeVariableInfo);
518 }
519 info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, SourceParseMode::GeneratorBodyMode, false);
520
521 info.endLine = tokenLine();
522 info.endOffset = m_token.m_data.offset;
523 info.parametersStartColumn = startColumn;
524
525 auto functionExpr = context.createGeneratorFunctionBody(startLocation, info, name);
526 auto statement = context.createExprStatement(startLocation, functionExpr, start, m_lastTokenEndPosition.line);
527 context.appendStatement(sourceElements, statement);
528
529 return sourceElements;
530}
531
532template <typename LexerType>
533template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseAsyncFunctionSourceElements(TreeBuilder& context, SourceParseMode parseMode, bool isArrowFunctionBodyExpression, SourceElementsMode mode)
534{
535 ASSERT(isAsyncFunctionOrAsyncGeneratorWrapperParseMode(parseMode));
536 auto sourceElements = context.createSourceElements();
537
538 unsigned functionKeywordStart = tokenStart();
539 JSTokenLocation startLocation(tokenLocation());
540 JSTextPosition start = tokenStartPosition();
541 unsigned startColumn = tokenColumn();
542 int functionNameStart = m_token.m_location.startOffset;
543 int parametersStart = m_token.m_location.startOffset;
544
545 ParserFunctionInfo<TreeBuilder> info;
546 info.name = &m_vm.propertyNames->nullIdentifier;
547 createGeneratorParameters(context, info.parameterCount);
548 info.startOffset = parametersStart;
549 info.startLine = tokenLine();
550
551 SourceParseMode innerParseMode = getAsynFunctionBodyParseMode(parseMode);
552
553 {
554 AutoPopScopeRef asyncFunctionBodyScope(this, pushScope());
555 asyncFunctionBodyScope->setSourceParseMode(innerParseMode);
556 SyntaxChecker syntaxChecker(const_cast<VM&>(m_vm), m_lexer.get());
557 if (isArrowFunctionBodyExpression) {
558 if (m_debuggerParseData)
559 failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(context), "Cannot parse the body of async arrow function");
560 else
561 failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(syntaxChecker), "Cannot parse the body of async arrow function");
562 } else {
563 if (m_debuggerParseData)
564 failIfFalse(parseSourceElements(context, mode), "Cannot parse the body of async function");
565 else
566 failIfFalse(parseSourceElements(syntaxChecker, mode), "Cannot parse the body of async function");
567 }
568 popScope(asyncFunctionBodyScope, TreeBuilder::NeedsFreeVariableInfo);
569 }
570 info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, innerParseMode, isArrowFunctionBodyExpression);
571
572 info.endLine = tokenLine();
573 info.endOffset = isArrowFunctionBodyExpression ? tokenLocation().endOffset : m_token.m_data.offset;
574 info.parametersStartColumn = startColumn;
575
576 auto functionExpr = context.createAsyncFunctionBody(startLocation, info, innerParseMode);
577 auto statement = context.createExprStatement(startLocation, functionExpr, start, m_lastTokenEndPosition.line);
578 context.appendStatement(sourceElements, statement);
579
580 return sourceElements;
581}
582
583template <typename LexerType>
584template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseAsyncGeneratorFunctionSourceElements(TreeBuilder& context, SourceParseMode parseMode, bool isArrowFunctionBodyExpression, SourceElementsMode mode)
585{
586 ASSERT_UNUSED(parseMode, isAsyncGeneratorWrapperParseMode(parseMode));
587 auto sourceElements = context.createSourceElements();
588
589 unsigned functionKeywordStart = tokenStart();
590 JSTokenLocation startLocation(tokenLocation());
591 JSTextPosition start = tokenStartPosition();
592 unsigned startColumn = tokenColumn();
593 int functionNameStart = m_token.m_location.startOffset;
594 int parametersStart = m_token.m_location.startOffset;
595
596 ParserFunctionInfo<TreeBuilder> info;
597 info.name = &m_vm.propertyNames->nullIdentifier;
598 createGeneratorParameters(context, info.parameterCount);
599 info.startOffset = parametersStart;
600 info.startLine = tokenLine();
601 SourceParseMode innerParseMode = SourceParseMode::AsyncGeneratorBodyMode;
602 {
603 AutoPopScopeRef asyncFunctionBodyScope(this, pushScope());
604 asyncFunctionBodyScope->setSourceParseMode(innerParseMode);
605 SyntaxChecker syntaxChecker(const_cast<VM&>(m_vm), m_lexer.get());
606 if (isArrowFunctionBodyExpression) {
607 if (m_debuggerParseData)
608 failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(context), "Cannot parse the body of async arrow function");
609 else
610 failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(syntaxChecker), "Cannot parse the body of async arrow function");
611 } else {
612 if (m_debuggerParseData)
613 failIfFalse(parseSourceElements(context, mode), "Cannot parse the body of async function");
614 else
615 failIfFalse(parseSourceElements(syntaxChecker, mode), "Cannot parse the body of async function");
616 }
617 popScope(asyncFunctionBodyScope, TreeBuilder::NeedsFreeVariableInfo);
618 }
619 info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, innerParseMode, isArrowFunctionBodyExpression);
620
621 info.endLine = tokenLine();
622 info.endOffset = isArrowFunctionBodyExpression ? tokenLocation().endOffset : m_token.m_data.offset;
623 info.parametersStartColumn = startColumn;
624
625 auto functionExpr = context.createAsyncFunctionBody(startLocation, info, innerParseMode);
626 auto statement = context.createExprStatement(startLocation, functionExpr, start, m_lastTokenEndPosition.line);
627 context.appendStatement(sourceElements, statement);
628
629 return sourceElements;
630}
631
632template <typename LexerType>
633template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSingleFunction(TreeBuilder& context, Optional<int> functionConstructorParametersEndPosition)
634{
635 TreeSourceElements sourceElements = context.createSourceElements();
636 TreeStatement statement = 0;
637 switch (m_token.m_type) {
638 case FUNCTION:
639 statement = parseFunctionDeclaration(context, ExportType::NotExported, DeclarationDefaultContext::Standard, functionConstructorParametersEndPosition);
640 break;
641 case IDENT:
642 if (*m_token.m_data.ident == m_vm.propertyNames->async && !m_token.m_data.escaped) {
643 next();
644 failIfFalse(match(FUNCTION) && !m_lexer->hasLineTerminatorBeforeToken(), "Cannot parse the async function");
645 statement = parseAsyncFunctionDeclaration(context, ExportType::NotExported, DeclarationDefaultContext::Standard, functionConstructorParametersEndPosition);
646 break;
647 }
648 FALLTHROUGH;
649 default:
650 failDueToUnexpectedToken();
651 break;
652 }
653
654 if (statement) {
655 context.setEndOffset(statement, m_lastTokenEndPosition.offset);
656 context.appendStatement(sourceElements, statement);
657 }
658
659 propagateError();
660 return sourceElements;
661}
662
663
664template <typename LexerType>
665template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatementListItem(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
666{
667 // The grammar is documented here:
668 // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-statements
669 DepthManager statementDepth(&m_statementDepth);
670 m_statementDepth++;
671 failIfStackOverflow();
672 TreeStatement result = 0;
673 bool shouldSetEndOffset = true;
674 bool shouldSetPauseLocation = false;
675
676 switch (m_token.m_type) {
677 case CONSTTOKEN:
678 result = parseVariableDeclaration(context, DeclarationType::ConstDeclaration);
679 shouldSetPauseLocation = true;
680 break;
681 case LET: {
682 bool shouldParseVariableDeclaration = true;
683 if (!strictMode()) {
684 SavePoint savePoint = createSavePoint();
685 next();
686 // Intentionally use `isIdentifierOrAnyContextualKeyword(m_token)` and don't use `matchSpecIdentifier()`.
687 // We would like to fall into parseVariableDeclaration path even if "yield" is not treated as an Identifier.
688 // For example, under a generator context, matchSpecIdentifier() for "yield" returns `false`.
689 // But we would like to enter parseVariableDeclaration and raise an error under the context of parseVariableDeclaration
690 // to raise consistent errors between "var", "const" and "let".
691 if (!isIdentifierOrAnyContextualKeyword(m_token) && !match(OPENBRACE) && !match(OPENBRACKET))
692 shouldParseVariableDeclaration = false;
693 restoreSavePoint(savePoint);
694 }
695 if (shouldParseVariableDeclaration)
696 result = parseVariableDeclaration(context, DeclarationType::LetDeclaration);
697 else {
698 bool allowFunctionDeclarationAsStatement = true;
699 result = parseExpressionOrLabelStatement(context, allowFunctionDeclarationAsStatement);
700 }
701 shouldSetPauseLocation = !context.shouldSkipPauseLocation(result);
702 break;
703 }
704 case CLASSTOKEN:
705 result = parseClassDeclaration(context);
706 break;
707 case FUNCTION:
708 result = parseFunctionDeclaration(context);
709 break;
710 case IDENT:
711 if (UNLIKELY(*m_token.m_data.ident == m_vm.propertyNames->async && !m_token.m_data.escaped)) {
712 // Eagerly parse as AsyncFunctionDeclaration. This is the uncommon case,
713 // but could be mistakenly parsed as an AsyncFunctionExpression.
714 SavePoint savePoint = createSavePoint();
715 next();
716 if (UNLIKELY(match(FUNCTION) && !m_lexer->hasLineTerminatorBeforeToken())) {
717 result = parseAsyncFunctionDeclaration(context);
718 break;
719 }
720 restoreSavePoint(savePoint);
721 }
722 FALLTHROUGH;
723 case AWAIT:
724 case YIELD: {
725 // This is a convenient place to notice labeled statements
726 // (even though we also parse them as normal statements)
727 // because we allow the following type of code in sloppy mode:
728 // ``` function foo() { label: function bar() { } } ```
729 bool allowFunctionDeclarationAsStatement = true;
730 result = parseExpressionOrLabelStatement(context, allowFunctionDeclarationAsStatement);
731 shouldSetPauseLocation = !context.shouldSkipPauseLocation(result);
732 break;
733 }
734 default:
735 m_statementDepth--; // parseStatement() increments the depth.
736 result = parseStatement(context, directive, directiveLiteralLength);
737 shouldSetEndOffset = false;
738 break;
739 }
740
741 if (result) {
742 if (shouldSetEndOffset)
743 context.setEndOffset(result, m_lastTokenEndPosition.offset);
744 if (shouldSetPauseLocation)
745 recordPauseLocation(context.breakpointLocation(result));
746 }
747
748 return result;
749}
750
751template <typename LexerType>
752template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVariableDeclaration(TreeBuilder& context, DeclarationType declarationType, ExportType exportType)
753{
754 ASSERT(match(VAR) || match(LET) || match(CONSTTOKEN));
755 JSTokenLocation location(tokenLocation());
756 int start = tokenLine();
757 int end = 0;
758 int scratch;
759 TreeDestructuringPattern scratch1 = 0;
760 TreeExpression scratch2 = 0;
761 JSTextPosition scratch3;
762 bool scratchBool;
763 TreeExpression variableDecls = parseVariableDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3, VarDeclarationContext, declarationType, exportType, scratchBool);
764 propagateError();
765 failIfFalse(autoSemiColon(), "Expected ';' after variable declaration");
766
767 return context.createDeclarationStatement(location, variableDecls, start, end);
768}
769
770template <typename LexerType>
771template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDoWhileStatement(TreeBuilder& context)
772{
773 ASSERT(match(DO));
774 int startLine = tokenLine();
775 next();
776 const Identifier* unused = 0;
777 startLoop();
778 TreeStatement statement = parseStatement(context, unused);
779 endLoop();
780 failIfFalse(statement, "Expected a statement following 'do'");
781 int endLine = tokenLine();
782 JSTokenLocation location(tokenLocation());
783 handleProductionOrFail(WHILE, "while", "end", "do-while loop");
784 handleProductionOrFail(OPENPAREN, "(", "start", "do-while loop condition");
785 semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a do-while loop condition");
786 TreeExpression expr = parseExpression(context);
787 failIfFalse(expr, "Unable to parse do-while loop condition");
788 recordPauseLocation(context.breakpointLocation(expr));
789 handleProductionOrFail(CLOSEPAREN, ")", "end", "do-while loop condition");
790 if (match(SEMICOLON))
791 next(); // Always performs automatic semicolon insertion.
792 return context.createDoWhileStatement(location, statement, expr, startLine, endLine);
793}
794
795template <typename LexerType>
796template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWhileStatement(TreeBuilder& context)
797{
798 ASSERT(match(WHILE));
799 JSTokenLocation location(tokenLocation());
800 int startLine = tokenLine();
801 next();
802
803 handleProductionOrFail(OPENPAREN, "(", "start", "while loop condition");
804 semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a while loop condition");
805 TreeExpression expr = parseExpression(context);
806 failIfFalse(expr, "Unable to parse while loop condition");
807 recordPauseLocation(context.breakpointLocation(expr));
808 int endLine = tokenLine();
809 handleProductionOrFail(CLOSEPAREN, ")", "end", "while loop condition");
810
811 const Identifier* unused = 0;
812 startLoop();
813 TreeStatement statement = parseStatement(context, unused);
814 endLoop();
815 failIfFalse(statement, "Expected a statement as the body of a while loop");
816 return context.createWhileStatement(location, expr, statement, startLine, endLine);
817}
818
819template <typename LexerType>
820template <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)
821{
822 ASSERT(declarationType == DeclarationType::LetDeclaration || declarationType == DeclarationType::VarDeclaration || declarationType == DeclarationType::ConstDeclaration);
823 TreeExpression head = 0;
824 TreeExpression tail = 0;
825 const Identifier* lastIdent;
826 JSToken lastIdentToken;
827 AssignmentContext assignmentContext = assignmentContextFromDeclarationType(declarationType);
828 do {
829 lastIdent = 0;
830 lastPattern = TreeDestructuringPattern(0);
831 JSTokenLocation location(tokenLocation());
832 next();
833 TreeExpression node = 0;
834 declarations++;
835 bool hasInitializer = false;
836 if (matchSpecIdentifier()) {
837 failIfTrue(match(LET) && (declarationType == DeclarationType::LetDeclaration || declarationType == DeclarationType::ConstDeclaration),
838 "Cannot use 'let' as an identifier name for a LexicalDeclaration");
839 semanticFailIfTrue(isDisallowedIdentifierAwait(m_token), "Cannot use 'await' as a ", declarationTypeToVariableKind(declarationType), " ", disallowedIdentifierAwaitReason());
840 JSTextPosition varStart = tokenStartPosition();
841 JSTokenLocation varStartLocation(tokenLocation());
842 identStart = varStart;
843 const Identifier* name = m_token.m_data.ident;
844 lastIdent = name;
845 lastIdentToken = m_token;
846 next();
847 hasInitializer = match(EQUAL);
848 DeclarationResultMask declarationResult = declareVariable(name, declarationType);
849 if (declarationResult != DeclarationResult::Valid) {
850 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a variable named ", name->impl(), " in strict mode");
851 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration) {
852 if (declarationType == DeclarationType::LetDeclaration)
853 internalFailWithMessage(false, "Cannot declare a let variable twice: '", name->impl(), "'");
854 if (declarationType == DeclarationType::ConstDeclaration)
855 internalFailWithMessage(false, "Cannot declare a const variable twice: '", name->impl(), "'");
856 ASSERT(declarationType == DeclarationType::VarDeclaration);
857 internalFailWithMessage(false, "Cannot declare a var variable that shadows a let/const/class variable: '", name->impl(), "'");
858 }
859 }
860 if (exportType == ExportType::Exported) {
861 semanticFailIfFalse(exportName(*name), "Cannot export a duplicate name '", name->impl(), "'");
862 m_moduleScopeData->exportBinding(*name);
863 }
864
865 if (hasInitializer) {
866 JSTextPosition varDivot = tokenStartPosition() + 1;
867 initStart = tokenStartPosition();
868 next(TreeBuilder::DontBuildStrings); // consume '='
869 propagateError();
870 TreeExpression initializer = parseAssignmentExpression(context);
871 initEnd = lastTokenEndPosition();
872 lastInitializer = initializer;
873 failIfFalse(initializer, "Expected expression as the intializer for the variable '", name->impl(), "'");
874
875 node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEndPosition(), assignmentContext);
876 } else {
877 if (declarationListContext == ForLoopContext && declarationType == DeclarationType::ConstDeclaration)
878 forLoopConstDoesNotHaveInitializer = true;
879 failIfTrue(declarationListContext != ForLoopContext && declarationType == DeclarationType::ConstDeclaration, "const declared variable '", name->impl(), "'", " must have an initializer");
880 if (declarationType == DeclarationType::VarDeclaration)
881 node = context.createEmptyVarExpression(varStartLocation, *name);
882 else
883 node = context.createEmptyLetExpression(varStartLocation, *name);
884 }
885 } else {
886 lastIdent = 0;
887 auto pattern = parseDestructuringPattern(context, destructuringKindFromDeclarationType(declarationType), exportType, nullptr, nullptr, assignmentContext);
888 failIfFalse(pattern, "Cannot parse this destructuring pattern");
889 hasInitializer = match(EQUAL);
890 failIfTrue(declarationListContext == VarDeclarationContext && !hasInitializer, "Expected an initializer in destructuring variable declaration");
891 lastPattern = pattern;
892 if (hasInitializer) {
893 next(TreeBuilder::DontBuildStrings); // consume '='
894 TreeExpression rhs = parseAssignmentExpression(context);
895 propagateError();
896 ASSERT(rhs);
897 node = context.createDestructuringAssignment(location, pattern, rhs);
898 lastInitializer = rhs;
899 }
900 }
901
902 if (node) {
903 if (!head)
904 head = node;
905 else if (!tail) {
906 head = context.createCommaExpr(location, head);
907 tail = context.appendToCommaExpr(location, head, head, node);
908 } else
909 tail = context.appendToCommaExpr(location, head, tail, node);
910 }
911 } while (match(COMMA));
912 if (lastIdent)
913 lastPattern = context.createBindingLocation(lastIdentToken.m_location, *lastIdent, lastIdentToken.m_startPosition, lastIdentToken.m_endPosition, assignmentContext);
914
915 return head;
916}
917
918template <typename LexerType>
919bool Parser<LexerType>::declareRestOrNormalParameter(const Identifier& name, const Identifier** duplicateIdentifier)
920{
921 DeclarationResultMask declarationResult = declareParameter(&name);
922 if ((declarationResult & DeclarationResult::InvalidStrictMode) && strictMode()) {
923 semanticFailIfTrue(isEvalOrArguments(&name), "Cannot destructure to a parameter name '", name.impl(), "' in strict mode");
924 if (m_parserState.lastFunctionName && name == *m_parserState.lastFunctionName)
925 semanticFail("Cannot declare a parameter named '", name.impl(), "' as it shadows the name of a strict mode function");
926 semanticFailureDueToKeyword("parameter name");
927 if (!m_lexer->isReparsingFunction() && hasDeclaredParameter(name))
928 semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode as it has already been declared");
929 semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode");
930 }
931 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration) {
932 // It's not always an error to define a duplicate parameter.
933 // It's only an error when there are default parameter values or destructuring parameters.
934 // We note this value now so we can check it later.
935 if (duplicateIdentifier)
936 *duplicateIdentifier = &name;
937 }
938
939 return true;
940}
941
942template <typename LexerType>
943template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::createBindingPattern(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier& name, JSToken token, AssignmentContext bindingContext, const Identifier** duplicateIdentifier)
944{
945 ASSERT(!name.isNull());
946
947 ASSERT(name.impl()->isAtom() || name.impl()->isSymbol());
948
949 switch (kind) {
950 case DestructuringKind::DestructureToVariables: {
951 DeclarationResultMask declarationResult = declareVariable(&name);
952 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a variable named '", name.impl(), "' in strict mode");
953 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
954 internalFailWithMessage(false, "Cannot declare a var variable that shadows a let/const/class variable: '", name.impl(), "'");
955 break;
956 }
957
958 case DestructuringKind::DestructureToLet:
959 case DestructuringKind::DestructureToConst:
960 case DestructuringKind::DestructureToCatchParameters: {
961 DeclarationResultMask declarationResult = declareVariable(&name, kind == DestructuringKind::DestructureToConst ? DeclarationType::ConstDeclaration : DeclarationType::LetDeclaration);
962 if (declarationResult != DeclarationResult::Valid) {
963 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot destructure to a variable named '", name.impl(), "' in strict mode");
964 failIfTrue(declarationResult & DeclarationResult::InvalidDuplicateDeclaration, "Cannot declare a lexical variable twice: '", name.impl(), "'");
965 }
966 break;
967 }
968
969 case DestructuringKind::DestructureToParameters: {
970 declareRestOrNormalParameter(name, duplicateIdentifier);
971 propagateError();
972 break;
973 }
974
975 case DestructuringKind::DestructureToExpressions: {
976 break;
977 }
978 }
979
980 if (exportType == ExportType::Exported) {
981 semanticFailIfFalse(exportName(name), "Cannot export a duplicate name '", name.impl(), "'");
982 m_moduleScopeData->exportBinding(name);
983 }
984 return context.createBindingLocation(token.m_location, name, token.m_startPosition, token.m_endPosition, bindingContext);
985}
986
987template <typename LexerType>
988template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern Parser<LexerType>::createAssignmentElement(TreeBuilder& context, TreeExpression& assignmentTarget, const JSTextPosition& startPosition, const JSTextPosition& endPosition)
989{
990 return context.createAssignmentElement(assignmentTarget, startPosition, endPosition);
991}
992
993template <typename LexerType>
994template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseArrowFunctionSingleExpressionBodySourceElements(TreeBuilder& context)
995{
996 ASSERT(!match(OPENBRACE));
997
998 JSTokenLocation location(tokenLocation());
999 JSTextPosition start = tokenStartPosition();
1000
1001 failIfStackOverflow();
1002 TreeExpression expr = parseAssignmentExpression(context);
1003 failIfFalse(expr, "Cannot parse the arrow function expression");
1004
1005 context.setEndOffset(expr, m_lastTokenEndPosition.offset);
1006
1007 JSTextPosition end = tokenEndPosition();
1008
1009 TreeSourceElements sourceElements = context.createSourceElements();
1010 TreeStatement body = context.createReturnStatement(location, expr, start, end);
1011 context.setEndOffset(body, m_lastTokenEndPosition.offset);
1012 recordPauseLocation(context.breakpointLocation(body));
1013 context.appendStatement(sourceElements, body);
1014
1015 return sourceElements;
1016}
1017
1018template <typename LexerType>
1019template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::tryParseDestructuringPatternExpression(TreeBuilder& context, AssignmentContext bindingContext)
1020{
1021 return parseDestructuringPattern(context, DestructuringKind::DestructureToExpressions, ExportType::NotExported, nullptr, nullptr, bindingContext);
1022}
1023
1024template <typename LexerType>
1025template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseBindingOrAssignmentElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
1026{
1027 if (kind == DestructuringKind::DestructureToExpressions)
1028 return parseAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
1029 return parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
1030}
1031
1032template <typename LexerType>
1033template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseObjectRestAssignmentElement(TreeBuilder& context)
1034{
1035 JSTextPosition startPosition = tokenStartPosition();
1036 auto element = parseMemberExpression(context);
1037
1038 if (!element || !context.isAssignmentLocation(element)) {
1039 reclassifyExpressionError(ErrorIndicatesPattern, ErrorIndicatesNothing);
1040 semanticFail("Invalid destructuring assignment target");
1041 }
1042
1043 if (strictMode() && m_parserState.lastIdentifier && context.isResolve(element)) {
1044 bool isEvalOrArguments = m_vm.propertyNames->eval == *m_parserState.lastIdentifier || m_vm.propertyNames->arguments == *m_parserState.lastIdentifier;
1045 if (isEvalOrArguments && strictMode())
1046 reclassifyExpressionError(ErrorIndicatesPattern, ErrorIndicatesNothing);
1047 failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", m_parserState.lastIdentifier->impl(), "' in strict mode");
1048 }
1049
1050 return createAssignmentElement(context, element, startPosition, lastTokenEndPosition());
1051}
1052
1053template <typename LexerType>
1054template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseAssignmentElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
1055{
1056 TreeDestructuringPattern assignmentTarget = 0;
1057
1058 if (match(OPENBRACE) || match(OPENBRACKET)) {
1059 SavePoint savePoint = createSavePoint();
1060 assignmentTarget = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
1061 if (assignmentTarget && !match(DOT) && !match(OPENBRACKET) && !match(OPENPAREN) && !match(BACKQUOTE))
1062 return assignmentTarget;
1063 restoreSavePoint(savePoint);
1064 }
1065
1066 JSTextPosition startPosition = tokenStartPosition();
1067 auto element = parseMemberExpression(context);
1068
1069 semanticFailIfFalse(element && context.isAssignmentLocation(element), "Invalid destructuring assignment target");
1070
1071 if (strictMode() && m_parserState.lastIdentifier && context.isResolve(element)) {
1072 bool isEvalOrArguments = m_vm.propertyNames->eval == *m_parserState.lastIdentifier || m_vm.propertyNames->arguments == *m_parserState.lastIdentifier;
1073 failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", m_parserState.lastIdentifier->impl(), "' in strict mode");
1074 }
1075
1076 return createAssignmentElement(context, element, startPosition, lastTokenEndPosition());
1077}
1078
1079static const char* destructuringKindToVariableKindName(DestructuringKind kind)
1080{
1081 switch (kind) {
1082 case DestructuringKind::DestructureToLet:
1083 case DestructuringKind::DestructureToConst:
1084 return "lexical variable name";
1085 case DestructuringKind::DestructureToVariables:
1086 return "variable name";
1087 case DestructuringKind::DestructureToParameters:
1088 return "parameter name";
1089 case DestructuringKind::DestructureToCatchParameters:
1090 return "catch parameter name";
1091 case DestructuringKind::DestructureToExpressions:
1092 return "expression name";
1093 }
1094 RELEASE_ASSERT_NOT_REACHED();
1095 return "invalid";
1096}
1097
1098template <typename LexerType>
1099template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseObjectRestElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, AssignmentContext bindingContext)
1100{
1101 ASSERT(kind != DestructuringKind::DestructureToExpressions);
1102 failIfStackOverflow();
1103 TreeDestructuringPattern pattern;
1104
1105 if (!matchSpecIdentifier()) {
1106 semanticFailureDueToKeyword(destructuringKindToVariableKindName(kind));
1107 failWithMessage("Expected a binding element");
1108 }
1109 failIfTrue(match(LET) && (kind == DestructuringKind::DestructureToLet || kind == DestructuringKind::DestructureToConst), "Cannot use 'let' as an identifier name for a LexicalDeclaration");
1110 semanticFailIfTrue(isDisallowedIdentifierAwait(m_token), "Cannot use 'await' as a ", destructuringKindToVariableKindName(kind), " ", disallowedIdentifierAwaitReason());
1111 pattern = createBindingPattern(context, kind, exportType, *m_token.m_data.ident, m_token, bindingContext, duplicateIdentifier);
1112 next();
1113 return pattern;
1114}
1115
1116template <typename LexerType>
1117template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseObjectRestBindingOrAssignmentElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, AssignmentContext bindingContext)
1118{
1119 if (kind == DestructuringKind::DestructureToExpressions)
1120 return parseObjectRestAssignmentElement(context);
1121 return parseObjectRestElement(context, kind, exportType, duplicateIdentifier, bindingContext);
1122}
1123
1124template <typename LexerType>
1125template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseDestructuringPattern(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
1126{
1127 failIfStackOverflow();
1128 int nonLHSCount = m_parserState.nonLHSCount;
1129 TreeDestructuringPattern pattern;
1130 switch (m_token.m_type) {
1131 case OPENBRACKET: {
1132 JSTextPosition divotStart = tokenStartPosition();
1133 auto arrayPattern = context.createArrayPattern(m_token.m_location);
1134 next();
1135
1136 if (hasDestructuringPattern)
1137 *hasDestructuringPattern = true;
1138
1139 bool restElementWasFound = false;
1140
1141 do {
1142 while (match(COMMA)) {
1143 context.appendArrayPatternSkipEntry(arrayPattern, m_token.m_location);
1144 next();
1145 }
1146 propagateError();
1147
1148 if (match(CLOSEBRACKET))
1149 break;
1150
1151 if (UNLIKELY(match(DOTDOTDOT))) {
1152 JSTokenLocation location = m_token.m_location;
1153 next();
1154 auto innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
1155 if (kind == DestructuringKind::DestructureToExpressions && !innerPattern)
1156 return 0;
1157 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
1158 context.appendArrayPatternRestEntry(arrayPattern, location, innerPattern);
1159 restElementWasFound = true;
1160 break;
1161 }
1162
1163 JSTokenLocation location = m_token.m_location;
1164 auto innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
1165 if (kind == DestructuringKind::DestructureToExpressions && !innerPattern)
1166 return 0;
1167 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
1168 TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
1169 propagateError();
1170 context.appendArrayPatternEntry(arrayPattern, location, innerPattern, defaultValue);
1171 } while (consume(COMMA));
1172
1173 consumeOrFail(CLOSEBRACKET, restElementWasFound ? "Expected a closing ']' following a rest element destructuring pattern" : "Expected either a closing ']' or a ',' following an element destructuring pattern");
1174 context.finishArrayPattern(arrayPattern, divotStart, divotStart, lastTokenEndPosition());
1175 pattern = arrayPattern;
1176 break;
1177 }
1178 case OPENBRACE: {
1179 auto objectPattern = context.createObjectPattern(m_token.m_location);
1180 next();
1181
1182 if (hasDestructuringPattern)
1183 *hasDestructuringPattern = true;
1184
1185 bool restElementWasFound = false;
1186
1187 do {
1188 bool wasString = false;
1189
1190 if (match(CLOSEBRACE))
1191 break;
1192
1193 if (match(DOTDOTDOT)) {
1194 JSTokenLocation location = m_token.m_location;
1195 next();
1196 auto innerPattern = parseObjectRestBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, bindingContext);
1197 propagateError();
1198 if (!innerPattern)
1199 return 0;
1200 context.appendObjectPatternRestEntry(m_vm, objectPattern, location, innerPattern);
1201 restElementWasFound = true;
1202 context.setContainsObjectRestElement(objectPattern, restElementWasFound);
1203 break;
1204 }
1205
1206 const Identifier* propertyName = nullptr;
1207 TreeExpression propertyExpression = 0;
1208 TreeDestructuringPattern innerPattern = 0;
1209 JSTokenLocation location = m_token.m_location;
1210 if (matchSpecIdentifier()) {
1211 failIfTrue(match(LET) && (kind == DestructuringKind::DestructureToLet || kind == DestructuringKind::DestructureToConst), "Cannot use 'let' as an identifier name for a LexicalDeclaration");
1212 propertyName = m_token.m_data.ident;
1213 JSToken identifierToken = m_token;
1214 next();
1215 if (consume(COLON))
1216 innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
1217 else {
1218 if (kind == DestructuringKind::DestructureToExpressions) {
1219 bool isEvalOrArguments = m_vm.propertyNames->eval == *propertyName || m_vm.propertyNames->arguments == *propertyName;
1220 if (isEvalOrArguments && strictMode())
1221 reclassifyExpressionError(ErrorIndicatesPattern, ErrorIndicatesNothing);
1222 failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", propertyName->impl(), "' in strict mode");
1223 }
1224 semanticFailIfTrue(isDisallowedIdentifierAwait(identifierToken), "Cannot use 'await' as a ", destructuringKindToVariableKindName(kind), " ", disallowedIdentifierAwaitReason());
1225 innerPattern = createBindingPattern(context, kind, exportType, *propertyName, identifierToken, bindingContext, duplicateIdentifier);
1226 }
1227 } else {
1228 JSTokenType tokenType = m_token.m_type;
1229 switch (m_token.m_type) {
1230 case DOUBLE:
1231 case INTEGER:
1232 propertyName = &m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM&>(m_vm), m_token.m_data.doubleValue);
1233 break;
1234 case STRING:
1235 propertyName = m_token.m_data.ident;
1236 wasString = true;
1237 break;
1238 case OPENBRACKET:
1239 next();
1240 propertyExpression = parseAssignmentExpression(context);
1241 failIfFalse(propertyExpression, "Cannot parse computed property name");
1242 matchOrFail(CLOSEBRACKET, "Expected ']' to end end a computed property name");
1243 break;
1244 default:
1245 if (m_token.m_type != RESERVED && m_token.m_type != RESERVED_IF_STRICT && !(m_token.m_type & KeywordTokenFlag)) {
1246 if (kind == DestructuringKind::DestructureToExpressions)
1247 return 0;
1248 failWithMessage("Expected a property name");
1249 }
1250 propertyName = m_token.m_data.ident;
1251 break;
1252 }
1253 next();
1254 if (!consume(COLON)) {
1255 if (kind == DestructuringKind::DestructureToExpressions)
1256 return 0;
1257 semanticFailIfTrue(tokenType == RESERVED, "Cannot use abbreviated destructuring syntax for reserved name '", propertyName->impl(), "'");
1258 semanticFailIfTrue(tokenType == RESERVED_IF_STRICT, "Cannot use abbreviated destructuring syntax for reserved name '", propertyName->impl(), "' in strict mode");
1259 semanticFailIfTrue(tokenType & KeywordTokenFlag, "Cannot use abbreviated destructuring syntax for keyword '", propertyName->impl(), "'");
1260
1261 failWithMessage("Expected a ':' prior to a named destructuring property");
1262 }
1263 innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
1264 }
1265 if (kind == DestructuringKind::DestructureToExpressions && !innerPattern)
1266 return 0;
1267 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
1268 TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
1269 propagateError();
1270 if (propertyExpression) {
1271 context.appendObjectPatternEntry(m_vm, objectPattern, location, propertyExpression, innerPattern, defaultValue);
1272 context.setContainsComputedProperty(objectPattern, true);
1273 } else {
1274 ASSERT(propertyName);
1275 context.appendObjectPatternEntry(objectPattern, location, wasString, *propertyName, innerPattern, defaultValue);
1276 }
1277 } while (consume(COMMA));
1278
1279 if (kind == DestructuringKind::DestructureToExpressions && !match(CLOSEBRACE))
1280 return 0;
1281 consumeOrFail(CLOSEBRACE, restElementWasFound ? "Expected a closing '}' following a rest element destructuring pattern" : "Expected either a closing '}' or an ',' after a property destructuring pattern");
1282 pattern = objectPattern;
1283 break;
1284 }
1285
1286 default: {
1287 if (!matchSpecIdentifier()) {
1288 if (kind == DestructuringKind::DestructureToExpressions)
1289 return 0;
1290 semanticFailureDueToKeyword(destructuringKindToVariableKindName(kind));
1291 failWithMessage("Expected a parameter pattern or a ')' in parameter list");
1292 }
1293 failIfTrue(match(LET) && (kind == DestructuringKind::DestructureToLet || kind == DestructuringKind::DestructureToConst), "Cannot use 'let' as an identifier name for a LexicalDeclaration");
1294 semanticFailIfTrue(isDisallowedIdentifierAwait(m_token), "Cannot use 'await' as a ", destructuringKindToVariableKindName(kind), " ", disallowedIdentifierAwaitReason());
1295 pattern = createBindingPattern(context, kind, exportType, *m_token.m_data.ident, m_token, bindingContext, duplicateIdentifier);
1296 next();
1297 break;
1298 }
1299 }
1300 m_parserState.nonLHSCount = nonLHSCount;
1301 return pattern;
1302}
1303
1304template <typename LexerType>
1305template <class TreeBuilder> TreeExpression Parser<LexerType>::parseDefaultValueForDestructuringPattern(TreeBuilder& context)
1306{
1307 if (!match(EQUAL))
1308 return 0;
1309
1310 next(TreeBuilder::DontBuildStrings); // consume '='
1311 return parseAssignmentExpression(context);
1312}
1313
1314template <typename LexerType>
1315template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement(TreeBuilder& context)
1316{
1317 ASSERT(match(FOR));
1318 JSTokenLocation location(tokenLocation());
1319 int startLine = tokenLine();
1320 bool isAwaitFor = false;
1321 next();
1322
1323 DepthManager statementDepth(&m_statementDepth);
1324 m_statementDepth++;
1325
1326 if (match(AWAIT)) {
1327 semanticFailIfFalse(currentScope()->isAsyncFunction(), "for-await-of can only be used in an async function or async generator");
1328 isAwaitFor = true;
1329 next();
1330 }
1331
1332 handleProductionOrFail(OPENPAREN, "(", "start", "for-loop header");
1333 int nonLHSCount = m_parserState.nonLHSCount;
1334 int declarations = 0;
1335 JSTokenLocation declLocation(tokenLocation());
1336 JSTextPosition declsStart;
1337 JSTextPosition declsEnd;
1338 TreeExpression decls = 0;
1339 TreeDestructuringPattern pattern = 0;
1340 bool isVarDeclaraton = match(VAR);
1341 bool isLetDeclaration = match(LET);
1342 bool isConstDeclaration = match(CONSTTOKEN);
1343 bool forLoopConstDoesNotHaveInitializer = false;
1344
1345 VariableEnvironment dummySet;
1346 VariableEnvironment* lexicalVariables = nullptr;
1347 AutoCleanupLexicalScope lexicalScope;
1348
1349 auto gatherLexicalVariablesIfNecessary = [&] {
1350 if (isLetDeclaration || isConstDeclaration) {
1351 ScopeRef scope = lexicalScope.scope();
1352 lexicalVariables = &scope->finalizeLexicalEnvironment();
1353 } else
1354 lexicalVariables = &dummySet;
1355 };
1356
1357 auto popLexicalScopeIfNecessary = [&] {
1358 if (isLetDeclaration || isConstDeclaration)
1359 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1360 };
1361
1362 if (isVarDeclaraton || isLetDeclaration || isConstDeclaration) {
1363 /*
1364 for (var/let/const IDENT in/of expression) statement
1365 for (var/let/const varDeclarationList; expressionOpt; expressionOpt)
1366 */
1367 if (isLetDeclaration || isConstDeclaration) {
1368 ScopeRef newScope = pushScope();
1369 newScope->setIsLexicalScope();
1370 newScope->preventVarDeclarations();
1371 lexicalScope.setIsValid(newScope, this);
1372 }
1373
1374 TreeDestructuringPattern forInTarget = 0;
1375 TreeExpression forInInitializer = 0;
1376 m_allowsIn = false;
1377 JSTextPosition initStart;
1378 JSTextPosition initEnd;
1379 DeclarationType declarationType;
1380 if (isVarDeclaraton)
1381 declarationType = DeclarationType::VarDeclaration;
1382 else if (isLetDeclaration)
1383 declarationType = DeclarationType::LetDeclaration;
1384 else if (isConstDeclaration)
1385 declarationType = DeclarationType::ConstDeclaration;
1386 else
1387 RELEASE_ASSERT_NOT_REACHED();
1388 decls = parseVariableDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd, ForLoopContext, declarationType, ExportType::NotExported, forLoopConstDoesNotHaveInitializer);
1389 m_allowsIn = true;
1390 propagateError();
1391
1392 // Remainder of a standard for loop is handled identically
1393 if (match(SEMICOLON))
1394 goto standardForLoop;
1395
1396 failIfFalse(declarations == 1, "can only declare a single variable in an enumeration");
1397
1398 // Handle for-in with var declaration
1399 JSTextPosition inLocation = tokenStartPosition();
1400 bool isOfEnumeration = false;
1401 if (!match(INTOKEN)) {
1402 failIfFalse(matchContextualKeyword(m_vm.propertyNames->of), "Expected either 'in' or 'of' in enumeration syntax");
1403 isOfEnumeration = true;
1404 next();
1405 } else {
1406 failIfFalse(!isAwaitFor, "Expected 'of' in for-await syntax");
1407 next();
1408 }
1409
1410 bool hasAnyAssignments = !!forInInitializer;
1411 if (hasAnyAssignments) {
1412 if (isOfEnumeration)
1413 internalFailWithMessage(false, "Cannot assign to the loop variable inside a for-of loop header");
1414 if (strictMode() || (isLetDeclaration || isConstDeclaration) || !context.isBindingNode(forInTarget))
1415 internalFailWithMessage(false, "Cannot assign to the loop variable inside a for-in loop header");
1416 }
1417 TreeExpression expr = parseExpression(context);
1418 failIfFalse(expr, "Expected expression to enumerate");
1419 recordPauseLocation(context.breakpointLocation(expr));
1420 JSTextPosition exprEnd = lastTokenEndPosition();
1421
1422 int endLine = tokenLine();
1423
1424 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
1425
1426 const Identifier* unused = 0;
1427 startLoop();
1428 TreeStatement statement = parseStatement(context, unused);
1429 endLoop();
1430 failIfFalse(statement, "Expected statement as body of for-", isOfEnumeration ? "of" : "in", " statement");
1431 gatherLexicalVariablesIfNecessary();
1432 TreeStatement result;
1433 if (isOfEnumeration)
1434 result = context.createForOfLoop(isAwaitFor, location, forInTarget, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
1435 else {
1436 ASSERT(!isAwaitFor);
1437 if (isVarDeclaraton && forInInitializer)
1438 result = context.createForInLoop(location, decls, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
1439 else
1440 result = context.createForInLoop(location, forInTarget, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
1441 }
1442 popLexicalScopeIfNecessary();
1443 return result;
1444 }
1445
1446 if (!match(SEMICOLON)) {
1447 if (match(OPENBRACE) || match(OPENBRACKET)) {
1448 SavePoint savePoint = createSavePoint();
1449 declsStart = tokenStartPosition();
1450 pattern = tryParseDestructuringPatternExpression(context, AssignmentContext::DeclarationStatement);
1451 declsEnd = lastTokenEndPosition();
1452 if (pattern && (match(INTOKEN) || matchContextualKeyword(m_vm.propertyNames->of)))
1453 goto enumerationLoop;
1454 pattern = TreeDestructuringPattern(0);
1455 restoreSavePoint(savePoint);
1456 }
1457 m_allowsIn = false;
1458 declsStart = tokenStartPosition();
1459 decls = parseExpression(context);
1460 declsEnd = lastTokenEndPosition();
1461 m_allowsIn = true;
1462 failIfFalse(decls, "Cannot parse for loop declarations");
1463 recordPauseLocation(context.breakpointLocation(decls));
1464 }
1465
1466 if (match(SEMICOLON)) {
1467 standardForLoop:
1468 failIfFalse(!isAwaitFor, "Unexpected a ';' in for-await-of header");
1469 // Standard for loop
1470 if (decls)
1471 recordPauseLocation(context.breakpointLocation(decls));
1472 next();
1473 TreeExpression condition = 0;
1474 failIfTrue(forLoopConstDoesNotHaveInitializer && isConstDeclaration, "const variables in for loops must have initializers");
1475
1476 if (!match(SEMICOLON)) {
1477 condition = parseExpression(context);
1478 failIfFalse(condition, "Cannot parse for loop condition expression");
1479 recordPauseLocation(context.breakpointLocation(condition));
1480 }
1481 consumeOrFail(SEMICOLON, "Expected a ';' after the for loop condition expression");
1482
1483 TreeExpression increment = 0;
1484 if (!match(CLOSEPAREN)) {
1485 increment = parseExpression(context);
1486 failIfFalse(increment, "Cannot parse for loop iteration expression");
1487 recordPauseLocation(context.breakpointLocation(increment));
1488 }
1489 int endLine = tokenLine();
1490 handleProductionOrFail(CLOSEPAREN, ")", "end", "for-loop header");
1491 const Identifier* unused = 0;
1492 startLoop();
1493 TreeStatement statement = parseStatement(context, unused);
1494 endLoop();
1495 failIfFalse(statement, "Expected a statement as the body of a for loop");
1496 gatherLexicalVariablesIfNecessary();
1497 TreeStatement result = context.createForLoop(location, decls, condition, increment, statement, startLine, endLine, *lexicalVariables);
1498 popLexicalScopeIfNecessary();
1499 return result;
1500 }
1501
1502 // For-in and For-of loop
1503enumerationLoop:
1504 failIfFalse(nonLHSCount == m_parserState.nonLHSCount, "Expected a reference on the left hand side of an enumeration statement");
1505 bool isOfEnumeration = false;
1506 if (!match(INTOKEN)) {
1507 failIfFalse(matchContextualKeyword(m_vm.propertyNames->of), "Expected either 'in' or 'of' in enumeration syntax");
1508 isOfEnumeration = true;
1509 next();
1510 } else {
1511 failIfFalse(!isAwaitFor, "Expected 'of' in for-await syntax");
1512 next();
1513 }
1514
1515 TreeExpression expr = parseExpression(context);
1516 failIfFalse(expr, "Cannot parse subject for-", isOfEnumeration ? "of" : "in", " statement");
1517 recordPauseLocation(context.breakpointLocation(expr));
1518 JSTextPosition exprEnd = lastTokenEndPosition();
1519 int endLine = tokenLine();
1520
1521 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
1522 const Identifier* unused = 0;
1523 startLoop();
1524 TreeStatement statement = parseStatement(context, unused);
1525 endLoop();
1526 failIfFalse(statement, "Expected a statement as the body of a for-", isOfEnumeration ? "of" : "in", "loop");
1527 gatherLexicalVariablesIfNecessary();
1528 TreeStatement result;
1529 if (pattern) {
1530 ASSERT(!decls);
1531 if (isOfEnumeration)
1532 result = context.createForOfLoop(isAwaitFor, location, pattern, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1533 else {
1534 ASSERT(!isAwaitFor);
1535 result = context.createForInLoop(location, pattern, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1536 }
1537
1538 popLexicalScopeIfNecessary();
1539 return result;
1540 }
1541 if (isOfEnumeration)
1542 result = context.createForOfLoop(isAwaitFor, location, decls, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1543 else {
1544 ASSERT(!isAwaitFor);
1545 result = context.createForInLoop(location, decls, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1546 }
1547 popLexicalScopeIfNecessary();
1548 return result;
1549}
1550
1551template <typename LexerType>
1552template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatement(TreeBuilder& context)
1553{
1554 ASSERT(match(BREAK));
1555 JSTokenLocation location(tokenLocation());
1556 JSTextPosition start = tokenStartPosition();
1557 JSTextPosition end = tokenEndPosition();
1558 next();
1559
1560 if (autoSemiColon()) {
1561 semanticFailIfFalse(breakIsValid(), "'break' is only valid inside a switch or loop statement");
1562 return context.createBreakStatement(location, &m_vm.propertyNames->nullIdentifier, start, end);
1563 }
1564 failIfFalse(matchSpecIdentifier(), "Expected an identifier as the target for a break statement");
1565 const Identifier* ident = m_token.m_data.ident;
1566 semanticFailIfFalse(getLabel(ident), "Cannot use the undeclared label '", ident->impl(), "'");
1567 end = tokenEndPosition();
1568 next();
1569 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted break statement");
1570 return context.createBreakStatement(location, ident, start, end);
1571}
1572
1573template <typename LexerType>
1574template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueStatement(TreeBuilder& context)
1575{
1576 ASSERT(match(CONTINUE));
1577 JSTokenLocation location(tokenLocation());
1578 JSTextPosition start = tokenStartPosition();
1579 JSTextPosition end = tokenEndPosition();
1580 next();
1581
1582 if (autoSemiColon()) {
1583 semanticFailIfFalse(continueIsValid(), "'continue' is only valid inside a loop statement");
1584 return context.createContinueStatement(location, &m_vm.propertyNames->nullIdentifier, start, end);
1585 }
1586 failIfFalse(matchSpecIdentifier(), "Expected an identifier as the target for a continue statement");
1587 const Identifier* ident = m_token.m_data.ident;
1588 ScopeLabelInfo* label = getLabel(ident);
1589 semanticFailIfFalse(label, "Cannot use the undeclared label '", ident->impl(), "'");
1590 semanticFailIfFalse(label->isLoop, "Cannot continue to the label '", ident->impl(), "' as it is not targeting a loop");
1591 end = tokenEndPosition();
1592 next();
1593 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted continue statement");
1594 return context.createContinueStatement(location, ident, start, end);
1595}
1596
1597template <typename LexerType>
1598template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStatement(TreeBuilder& context)
1599{
1600 ASSERT(match(RETURN));
1601 JSTokenLocation location(tokenLocation());
1602 semanticFailIfFalse(currentScope()->isFunction(), "Return statements are only valid inside functions");
1603 JSTextPosition start = tokenStartPosition();
1604 JSTextPosition end = tokenEndPosition();
1605 next();
1606 // We do the auto semicolon check before attempting to parse expression
1607 // as we need to ensure the a line break after the return correctly terminates
1608 // the statement
1609 if (match(SEMICOLON))
1610 end = tokenEndPosition();
1611
1612 if (autoSemiColon())
1613 return context.createReturnStatement(location, 0, start, end);
1614 TreeExpression expr = parseExpression(context);
1615 failIfFalse(expr, "Cannot parse the return expression");
1616 end = lastTokenEndPosition();
1617 if (match(SEMICOLON))
1618 end = tokenEndPosition();
1619 if (!autoSemiColon())
1620 failWithMessage("Expected a ';' following a return statement");
1621 return context.createReturnStatement(location, expr, start, end);
1622}
1623
1624template <typename LexerType>
1625template <class TreeBuilder> TreeStatement Parser<LexerType>::parseThrowStatement(TreeBuilder& context)
1626{
1627 ASSERT(match(THROW));
1628 JSTokenLocation location(tokenLocation());
1629 JSTextPosition start = tokenStartPosition();
1630 next();
1631 failIfTrue(match(SEMICOLON), "Expected expression after 'throw'");
1632 semanticFailIfTrue(autoSemiColon(), "Cannot have a newline after 'throw'");
1633
1634 TreeExpression expr = parseExpression(context);
1635 failIfFalse(expr, "Cannot parse expression for throw statement");
1636 JSTextPosition end = lastTokenEndPosition();
1637 failIfFalse(autoSemiColon(), "Expected a ';' after a throw statement");
1638
1639 return context.createThrowStatement(location, expr, start, end);
1640}
1641
1642template <typename LexerType>
1643template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement(TreeBuilder& context)
1644{
1645 ASSERT(match(WITH));
1646 JSTokenLocation location(tokenLocation());
1647 semanticFailIfTrue(strictMode(), "'with' statements are not valid in strict mode");
1648 currentScope()->setNeedsFullActivation();
1649 int startLine = tokenLine();
1650 next();
1651
1652 handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'with' statement");
1653 int start = tokenStart();
1654 TreeExpression expr = parseExpression(context);
1655 failIfFalse(expr, "Cannot parse 'with' subject expression");
1656 recordPauseLocation(context.breakpointLocation(expr));
1657 JSTextPosition end = lastTokenEndPosition();
1658 int endLine = tokenLine();
1659 handleProductionOrFail(CLOSEPAREN, ")", "start", "subject of a 'with' statement");
1660 const Identifier* unused = 0;
1661 TreeStatement statement = parseStatement(context, unused);
1662 failIfFalse(statement, "A 'with' statement must have a body");
1663
1664 return context.createWithStatement(location, expr, statement, start, end, startLine, endLine);
1665}
1666
1667template <typename LexerType>
1668template <class TreeBuilder> TreeStatement Parser<LexerType>::parseSwitchStatement(TreeBuilder& context)
1669{
1670 ASSERT(match(SWITCH));
1671 JSTokenLocation location(tokenLocation());
1672 int startLine = tokenLine();
1673 next();
1674 handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'switch'");
1675 TreeExpression expr = parseExpression(context);
1676 failIfFalse(expr, "Cannot parse switch subject expression");
1677 recordPauseLocation(context.breakpointLocation(expr));
1678 int endLine = tokenLine();
1679
1680 handleProductionOrFail(CLOSEPAREN, ")", "end", "subject of a 'switch'");
1681 handleProductionOrFail(OPENBRACE, "{", "start", "body of a 'switch'");
1682 AutoPopScopeRef lexicalScope(this, pushScope());
1683 lexicalScope->setIsLexicalScope();
1684 lexicalScope->preventVarDeclarations();
1685 startSwitch();
1686 TreeClauseList firstClauses = parseSwitchClauses(context);
1687 propagateError();
1688
1689 TreeClause defaultClause = parseSwitchDefaultClause(context);
1690 propagateError();
1691
1692 TreeClauseList secondClauses = parseSwitchClauses(context);
1693 propagateError();
1694 endSwitch();
1695 handleProductionOrFail(CLOSEBRACE, "}", "end", "body of a 'switch'");
1696
1697 TreeStatement result = context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine, lexicalScope->finalizeLexicalEnvironment(), lexicalScope->takeFunctionDeclarations());
1698 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1699 return result;
1700}
1701
1702template <typename LexerType>
1703template <class TreeBuilder> TreeClauseList Parser<LexerType>::parseSwitchClauses(TreeBuilder& context)
1704{
1705 if (!match(CASE))
1706 return 0;
1707 unsigned startOffset = tokenStart();
1708 next();
1709 TreeExpression condition = parseExpression(context);
1710 failIfFalse(condition, "Cannot parse switch clause");
1711 consumeOrFail(COLON, "Expected a ':' after switch clause expression");
1712 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1713 failIfFalse(statements, "Cannot parse the body of a switch clause");
1714 TreeClause clause = context.createClause(condition, statements);
1715 context.setStartOffset(clause, startOffset);
1716 TreeClauseList clauseList = context.createClauseList(clause);
1717 TreeClauseList tail = clauseList;
1718
1719 while (match(CASE)) {
1720 startOffset = tokenStart();
1721 next();
1722 TreeExpression condition = parseExpression(context);
1723 failIfFalse(condition, "Cannot parse switch case expression");
1724 consumeOrFail(COLON, "Expected a ':' after switch clause expression");
1725 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1726 failIfFalse(statements, "Cannot parse the body of a switch clause");
1727 clause = context.createClause(condition, statements);
1728 context.setStartOffset(clause, startOffset);
1729 tail = context.createClauseList(tail, clause);
1730 }
1731 return clauseList;
1732}
1733
1734template <typename LexerType>
1735template <class TreeBuilder> TreeClause Parser<LexerType>::parseSwitchDefaultClause(TreeBuilder& context)
1736{
1737 if (!match(DEFAULT))
1738 return 0;
1739 unsigned startOffset = tokenStart();
1740 next();
1741 consumeOrFail(COLON, "Expected a ':' after switch default clause");
1742 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1743 failIfFalse(statements, "Cannot parse the body of a switch default clause");
1744 TreeClause result = context.createClause(0, statements);
1745 context.setStartOffset(result, startOffset);
1746 return result;
1747}
1748
1749template <typename LexerType>
1750template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(TreeBuilder& context)
1751{
1752 ASSERT(match(TRY));
1753 JSTokenLocation location(tokenLocation());
1754 TreeStatement tryBlock = 0;
1755 TreeDestructuringPattern catchPattern = 0;
1756 TreeStatement catchBlock = 0;
1757 TreeStatement finallyBlock = 0;
1758 int firstLine = tokenLine();
1759 next();
1760 matchOrFail(OPENBRACE, "Expected a block statement as body of a try statement");
1761
1762 tryBlock = parseBlockStatement(context);
1763 failIfFalse(tryBlock, "Cannot parse the body of try block");
1764 int lastLine = m_lastTokenEndPosition.line;
1765 VariableEnvironment catchEnvironment;
1766 if (match(CATCH)) {
1767 next();
1768
1769 if (match(OPENBRACE)) {
1770 catchBlock = parseBlockStatement(context);
1771 failIfFalse(catchBlock, "Unable to parse 'catch' block");
1772 } else {
1773 handleProductionOrFail(OPENPAREN, "(", "start", "'catch' target");
1774 AutoPopScopeRef catchScope(this, pushScope());
1775 catchScope->setIsLexicalScope();
1776 catchScope->preventVarDeclarations();
1777 const Identifier* ident = nullptr;
1778 if (matchSpecIdentifier()) {
1779 catchScope->setIsSimpleCatchParameterScope();
1780 ident = m_token.m_data.ident;
1781 catchPattern = context.createBindingLocation(m_token.m_location, *ident, m_token.m_startPosition, m_token.m_endPosition, AssignmentContext::DeclarationStatement);
1782 next();
1783 failIfTrueIfStrict(catchScope->declareLexicalVariable(ident, false) & DeclarationResult::InvalidStrictMode, "Cannot declare a catch variable named '", ident->impl(), "' in strict mode");
1784 } else {
1785 catchPattern = parseDestructuringPattern(context, DestructuringKind::DestructureToCatchParameters, ExportType::NotExported);
1786 failIfFalse(catchPattern, "Cannot parse this destructuring pattern");
1787 }
1788 handleProductionOrFail(CLOSEPAREN, ")", "end", "'catch' target");
1789 matchOrFail(OPENBRACE, "Expected exception handler to be a block statement");
1790 catchBlock = parseBlockStatement(context);
1791 failIfFalse(catchBlock, "Unable to parse 'catch' block");
1792 catchEnvironment = catchScope->finalizeLexicalEnvironment();
1793 RELEASE_ASSERT(!ident || (catchEnvironment.size() == 1 && catchEnvironment.contains(ident->impl())));
1794 popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo);
1795 }
1796 }
1797
1798 if (match(FINALLY)) {
1799 next();
1800 matchOrFail(OPENBRACE, "Expected block statement for finally body");
1801 finallyBlock = parseBlockStatement(context);
1802 failIfFalse(finallyBlock, "Cannot parse finally body");
1803 }
1804 failIfFalse(catchBlock || finallyBlock, "Try statements must have at least a catch or finally block");
1805 return context.createTryStatement(location, tryBlock, catchPattern, catchBlock, finallyBlock, firstLine, lastLine, catchEnvironment);
1806}
1807
1808template <typename LexerType>
1809template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDebuggerStatement(TreeBuilder& context)
1810{
1811 ASSERT(match(DEBUGGER));
1812 JSTokenLocation location(tokenLocation());
1813 int startLine = tokenLine();
1814 int endLine = startLine;
1815 next();
1816 if (match(SEMICOLON))
1817 startLine = tokenLine();
1818 failIfFalse(autoSemiColon(), "Debugger keyword must be followed by a ';'");
1819 return context.createDebugger(location, startLine, endLine);
1820}
1821
1822template <typename LexerType>
1823template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context)
1824{
1825 ASSERT(match(OPENBRACE));
1826
1827 // We should treat the first block statement of the function (the body of the function) as the lexical
1828 // scope of the function itself, and not the lexical scope of a 'block' statement within the function.
1829 AutoCleanupLexicalScope lexicalScope;
1830 bool shouldPushLexicalScope = m_statementDepth > 0;
1831 if (shouldPushLexicalScope) {
1832 ScopeRef newScope = pushScope();
1833 newScope->setIsLexicalScope();
1834 newScope->preventVarDeclarations();
1835 lexicalScope.setIsValid(newScope, this);
1836 }
1837 JSTokenLocation location(tokenLocation());
1838 int startOffset = m_token.m_data.offset;
1839 int start = tokenLine();
1840 VariableEnvironment emptyEnvironment;
1841 DeclarationStacks::FunctionStack emptyFunctionStack;
1842 next();
1843 if (match(CLOSEBRACE)) {
1844 int endOffset = m_token.m_data.offset;
1845 next();
1846 TreeStatement result = context.createBlockStatement(location, 0, start, m_lastTokenEndPosition.line, shouldPushLexicalScope ? currentScope()->finalizeLexicalEnvironment() : emptyEnvironment, shouldPushLexicalScope ? currentScope()->takeFunctionDeclarations() : WTFMove(emptyFunctionStack));
1847 context.setStartOffset(result, startOffset);
1848 context.setEndOffset(result, endOffset);
1849 if (shouldPushLexicalScope)
1850 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1851 return result;
1852 }
1853 TreeSourceElements subtree = parseSourceElements(context, DontCheckForStrictMode);
1854 failIfFalse(subtree, "Cannot parse the body of the block statement");
1855 matchOrFail(CLOSEBRACE, "Expected a closing '}' at the end of a block statement");
1856 int endOffset = m_token.m_data.offset;
1857 next();
1858 TreeStatement result = context.createBlockStatement(location, subtree, start, m_lastTokenEndPosition.line, shouldPushLexicalScope ? currentScope()->finalizeLexicalEnvironment() : emptyEnvironment, shouldPushLexicalScope ? currentScope()->takeFunctionDeclarations() : WTFMove(emptyFunctionStack));
1859 context.setStartOffset(result, startOffset);
1860 context.setEndOffset(result, endOffset);
1861 if (shouldPushLexicalScope)
1862 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1863
1864 return result;
1865}
1866
1867template <typename LexerType>
1868template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
1869{
1870 DepthManager statementDepth(&m_statementDepth);
1871 m_statementDepth++;
1872 int nonTrivialExpressionCount = 0;
1873 failIfStackOverflow();
1874 TreeStatement result = 0;
1875 bool shouldSetEndOffset = true;
1876 bool shouldSetPauseLocation = false;
1877 bool parentAllowsFunctionDeclarationAsStatement = m_immediateParentAllowsFunctionDeclarationInStatement;
1878 m_immediateParentAllowsFunctionDeclarationInStatement = false;
1879
1880 switch (m_token.m_type) {
1881 case OPENBRACE:
1882 result = parseBlockStatement(context);
1883 shouldSetEndOffset = false;
1884 break;
1885 case VAR:
1886 result = parseVariableDeclaration(context, DeclarationType::VarDeclaration);
1887 shouldSetPauseLocation = true;
1888 break;
1889 case FUNCTION: {
1890 const bool isAsync = false;
1891 result = parseFunctionDeclarationStatement(context, isAsync, parentAllowsFunctionDeclarationAsStatement);
1892 break;
1893 }
1894 case SEMICOLON: {
1895 JSTokenLocation location(tokenLocation());
1896 next();
1897 result = context.createEmptyStatement(location);
1898 shouldSetPauseLocation = true;
1899 break;
1900 }
1901 case IF:
1902 result = parseIfStatement(context);
1903 break;
1904 case DO:
1905 result = parseDoWhileStatement(context);
1906 break;
1907 case WHILE:
1908 result = parseWhileStatement(context);
1909 break;
1910 case FOR:
1911 result = parseForStatement(context);
1912 break;
1913 case CONTINUE:
1914 result = parseContinueStatement(context);
1915 shouldSetPauseLocation = true;
1916 break;
1917 case BREAK:
1918 result = parseBreakStatement(context);
1919 shouldSetPauseLocation = true;
1920 break;
1921 case RETURN:
1922 result = parseReturnStatement(context);
1923 shouldSetPauseLocation = true;
1924 break;
1925 case WITH:
1926 result = parseWithStatement(context);
1927 break;
1928 case SWITCH:
1929 result = parseSwitchStatement(context);
1930 break;
1931 case THROW:
1932 result = parseThrowStatement(context);
1933 shouldSetPauseLocation = true;
1934 break;
1935 case TRY:
1936 result = parseTryStatement(context);
1937 break;
1938 case DEBUGGER:
1939 result = parseDebuggerStatement(context);
1940 shouldSetPauseLocation = true;
1941 break;
1942 case EOFTOK:
1943 case CASE:
1944 case CLOSEBRACE:
1945 case DEFAULT:
1946 // These tokens imply the end of a set of source elements
1947 return 0;
1948 case LET: {
1949 if (!strictMode())
1950 goto identcase;
1951 goto defaultCase;
1952 }
1953 case IDENT:
1954 if (UNLIKELY(*m_token.m_data.ident == m_vm.propertyNames->async && !m_token.m_data.escaped)) {
1955 if (maybeParseAsyncFunctionDeclarationStatement(context, result, parentAllowsFunctionDeclarationAsStatement))
1956 break;
1957 }
1958 FALLTHROUGH;
1959 case AWAIT:
1960 case YIELD: {
1961 identcase:
1962 bool allowFunctionDeclarationAsStatement = false;
1963 result = parseExpressionOrLabelStatement(context, allowFunctionDeclarationAsStatement);
1964 shouldSetPauseLocation = !context.shouldSkipPauseLocation(result);
1965 break;
1966 }
1967 case STRING:
1968 directive = m_token.m_data.ident;
1969 if (directiveLiteralLength)
1970 *directiveLiteralLength = m_token.m_location.endOffset - m_token.m_location.startOffset;
1971 nonTrivialExpressionCount = m_parserState.nonTrivialExpressionCount;
1972 FALLTHROUGH;
1973 default:
1974 defaultCase:
1975 TreeStatement exprStatement = parseExpressionStatement(context);
1976 if (directive && nonTrivialExpressionCount != m_parserState.nonTrivialExpressionCount)
1977 directive = nullptr;
1978 result = exprStatement;
1979 shouldSetPauseLocation = true;
1980 break;
1981 }
1982
1983 if (result) {
1984 if (shouldSetEndOffset)
1985 context.setEndOffset(result, m_lastTokenEndPosition.offset);
1986 if (shouldSetPauseLocation)
1987 recordPauseLocation(context.breakpointLocation(result));
1988 }
1989
1990 return result;
1991}
1992
1993template <typename LexerType>
1994template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclarationStatement(TreeBuilder& context, bool isAsync, bool parentAllowsFunctionDeclarationAsStatement)
1995{
1996 semanticFailIfTrue(strictMode(), "Function declarations are only allowed inside blocks or switch statements in strict mode");
1997 failIfFalse(parentAllowsFunctionDeclarationAsStatement, "Function declarations are only allowed inside block statements or at the top level of a program");
1998 if (!currentScope()->isFunction() && !closestParentOrdinaryFunctionNonLexicalScope()->isEvalContext()) {
1999 // We only implement annex B.3.3 if we're in function mode or eval mode. Otherwise, we fall back
2000 // to hoisting behavior.
2001 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=155813
2002 DepthManager statementDepth(&m_statementDepth);
2003 m_statementDepth = 1;
2004 if (isAsync)
2005 return parseAsyncFunctionDeclaration(context);
2006 return parseFunctionDeclaration(context);
2007 }
2008
2009 // Any function declaration that isn't in a block is a syntax error unless it's
2010 // in an if/else statement. If it's in an if/else statement, we will magically
2011 // treat it as if the if/else statement is inside a block statement.
2012 // to the very top like a "var". For example:
2013 // function a() {
2014 // if (cond) function foo() { }
2015 // }
2016 // will be rewritten as:
2017 // function a() {
2018 // if (cond) { function foo() { } }
2019 // }
2020 AutoPopScopeRef blockScope(this, pushScope());
2021 blockScope->setIsLexicalScope();
2022 blockScope->preventVarDeclarations();
2023 JSTokenLocation location(tokenLocation());
2024 int start = tokenLine();
2025
2026 TreeStatement function = 0;
2027 if (!isAsync)
2028 function = parseFunctionDeclaration(context);
2029 else
2030 function = parseAsyncFunctionDeclaration(context);
2031 propagateError();
2032 failIfFalse(function, "Expected valid function statement after 'function' keyword");
2033 TreeSourceElements sourceElements = context.createSourceElements();
2034 context.appendStatement(sourceElements, function);
2035 TreeStatement result = context.createBlockStatement(location, sourceElements, start, m_lastTokenEndPosition.line, currentScope()->finalizeLexicalEnvironment(), currentScope()->takeFunctionDeclarations());
2036 popScope(blockScope, TreeBuilder::NeedsFreeVariableInfo);
2037 return result;
2038}
2039
2040template <typename LexerType>
2041template <class TreeBuilder> bool Parser<LexerType>::maybeParseAsyncFunctionDeclarationStatement(TreeBuilder& context, TreeStatement& result, bool parentAllowsFunctionDeclarationAsStatement)
2042{
2043 ASSERT(matchContextualKeyword(m_vm.propertyNames->async));
2044 SavePoint savePoint = createSavePoint();
2045 next();
2046 if (match(FUNCTION) && !m_lexer->hasLineTerminatorBeforeToken()) {
2047 const bool isAsync = true;
2048 result = parseFunctionDeclarationStatement(context, isAsync, parentAllowsFunctionDeclarationAsStatement);
2049 return true;
2050 }
2051 restoreSavePoint(savePoint);
2052 return false;
2053}
2054
2055template <typename LexerType>
2056template <class TreeBuilder> bool Parser<LexerType>::parseFormalParameters(TreeBuilder& context, TreeFormalParameterList list, bool isArrowFunction, bool isMethod, unsigned& parameterCount)
2057{
2058#define failIfDuplicateIfViolation() \
2059 if (duplicateParameter) {\
2060 semanticFailIfTrue(hasDefaultParameterValues, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with default parameter values");\
2061 semanticFailIfTrue(hasDestructuringPattern, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with destructuring parameters");\
2062 semanticFailIfTrue(isRestParameter, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with a rest parameter");\
2063 semanticFailIfTrue(isArrowFunction, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in an arrow function");\
2064 semanticFailIfTrue(isMethod, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in a method");\
2065 }
2066
2067 bool hasDefaultParameterValues = false;
2068 bool hasDestructuringPattern = false;
2069 bool isRestParameter = false;
2070 const Identifier* duplicateParameter = nullptr;
2071 unsigned restParameterStart = 0;
2072 do {
2073 TreeDestructuringPattern parameter = 0;
2074 TreeExpression defaultValue = 0;
2075
2076 if (UNLIKELY(match(CLOSEPAREN)))
2077 break;
2078
2079 if (match(DOTDOTDOT)) {
2080 next();
2081 semanticFailIfTrue(!m_parserState.allowAwait && match(AWAIT), "Cannot use 'await' as a parameter name in an async function");
2082 TreeDestructuringPattern destructuringPattern = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported, &duplicateParameter, &hasDestructuringPattern);
2083 propagateError();
2084 parameter = context.createRestParameter(destructuringPattern, restParameterStart);
2085 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.
2086 isRestParameter = true;
2087 } else
2088 parameter = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported, &duplicateParameter, &hasDestructuringPattern);
2089 failIfFalse(parameter, "Cannot parse parameter pattern");
2090 if (!isRestParameter) {
2091 defaultValue = parseDefaultValueForDestructuringPattern(context);
2092 if (defaultValue)
2093 hasDefaultParameterValues = true;
2094 }
2095 propagateError();
2096 failIfDuplicateIfViolation();
2097 if (isRestParameter || defaultValue || hasDestructuringPattern)
2098 currentScope()->setHasNonSimpleParameterList();
2099 context.appendParameter(list, parameter, defaultValue);
2100 if (!isRestParameter) {
2101 restParameterStart++;
2102 if (!hasDefaultParameterValues)
2103 parameterCount++;
2104 }
2105 } while (!isRestParameter && consume(COMMA));
2106
2107 return true;
2108#undef failIfDuplicateIfViolation
2109}
2110
2111template <typename LexerType>
2112template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(
2113 TreeBuilder& context, SyntaxChecker& syntaxChecker, const JSTokenLocation& startLocation, int startColumn, int functionKeywordStart, int functionNameStart, int parametersStart,
2114 ConstructorKind constructorKind, SuperBinding superBinding, FunctionBodyType bodyType, unsigned parameterCount, SourceParseMode parseMode)
2115{
2116 bool isArrowFunctionBodyExpression = bodyType == ArrowFunctionBodyExpression;
2117 if (!isArrowFunctionBodyExpression) {
2118 next();
2119 if (match(CLOSEBRACE)) {
2120 unsigned endColumn = tokenColumn();
2121 SuperBinding functionSuperBinding = adjustSuperBindingForBaseConstructor(constructorKind, superBinding, currentScope());
2122 return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, functionSuperBinding, parameterCount, parseMode, isArrowFunctionBodyExpression);
2123 }
2124 }
2125
2126 DepthManager statementDepth(&m_statementDepth);
2127 m_statementDepth = 0;
2128 if (bodyType == ArrowFunctionBodyExpression) {
2129 if (m_debuggerParseData)
2130 failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(context), "Cannot parse body of this arrow function");
2131 else
2132 failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(syntaxChecker), "Cannot parse body of this arrow function");
2133 } else {
2134 if (m_debuggerParseData)
2135 failIfFalse(parseSourceElements(context, CheckForStrictMode), bodyType == StandardFunctionBodyBlock ? "Cannot parse body of this function" : "Cannot parse body of this arrow function");
2136 else
2137 failIfFalse(parseSourceElements(syntaxChecker, CheckForStrictMode), bodyType == StandardFunctionBodyBlock ? "Cannot parse body of this function" : "Cannot parse body of this arrow function");
2138 }
2139 unsigned endColumn = tokenColumn();
2140 SuperBinding functionSuperBinding = adjustSuperBindingForBaseConstructor(constructorKind, superBinding, currentScope());
2141 return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, functionSuperBinding, parameterCount, parseMode, isArrowFunctionBodyExpression);
2142}
2143
2144static const char* stringArticleForFunctionMode(SourceParseMode mode)
2145{
2146 switch (mode) {
2147 case SourceParseMode::GetterMode:
2148 case SourceParseMode::SetterMode:
2149 case SourceParseMode::NormalFunctionMode:
2150 case SourceParseMode::MethodMode:
2151 case SourceParseMode::GeneratorBodyMode:
2152 case SourceParseMode::GeneratorWrapperFunctionMode:
2153 case SourceParseMode::GeneratorWrapperMethodMode:
2154 return "a ";
2155 case SourceParseMode::ArrowFunctionMode:
2156 case SourceParseMode::AsyncFunctionMode:
2157 case SourceParseMode::AsyncFunctionBodyMode:
2158 case SourceParseMode::AsyncMethodMode:
2159 case SourceParseMode::AsyncArrowFunctionBodyMode:
2160 case SourceParseMode::AsyncArrowFunctionMode:
2161 case SourceParseMode::AsyncGeneratorWrapperFunctionMode:
2162 case SourceParseMode::AsyncGeneratorBodyMode:
2163 case SourceParseMode::AsyncGeneratorWrapperMethodMode:
2164 return "an ";
2165 case SourceParseMode::ProgramMode:
2166 case SourceParseMode::ModuleAnalyzeMode:
2167 case SourceParseMode::ModuleEvaluateMode:
2168 RELEASE_ASSERT_NOT_REACHED();
2169 return "";
2170 }
2171 RELEASE_ASSERT_NOT_REACHED();
2172 return nullptr;
2173}
2174
2175static const char* stringForFunctionMode(SourceParseMode mode)
2176{
2177 switch (mode) {
2178 case SourceParseMode::GetterMode:
2179 return "getter";
2180 case SourceParseMode::SetterMode:
2181 return "setter";
2182 case SourceParseMode::NormalFunctionMode:
2183 return "function";
2184 case SourceParseMode::MethodMode:
2185 return "method";
2186 case SourceParseMode::GeneratorBodyMode:
2187 return "generator";
2188 case SourceParseMode::GeneratorWrapperFunctionMode:
2189 case SourceParseMode::GeneratorWrapperMethodMode:
2190 return "generator function";
2191 case SourceParseMode::ArrowFunctionMode:
2192 return "arrow function";
2193 case SourceParseMode::AsyncFunctionMode:
2194 case SourceParseMode::AsyncFunctionBodyMode:
2195 return "async function";
2196 case SourceParseMode::AsyncMethodMode:
2197 return "async method";
2198 case SourceParseMode::AsyncArrowFunctionBodyMode:
2199 case SourceParseMode::AsyncArrowFunctionMode:
2200 return "async arrow function";
2201 case SourceParseMode::AsyncGeneratorWrapperFunctionMode:
2202 case SourceParseMode::AsyncGeneratorBodyMode:
2203 return "async generator function";
2204 case SourceParseMode::AsyncGeneratorWrapperMethodMode:
2205 return "async generator method";
2206 case SourceParseMode::ProgramMode:
2207 case SourceParseMode::ModuleAnalyzeMode:
2208 case SourceParseMode::ModuleEvaluateMode:
2209 RELEASE_ASSERT_NOT_REACHED();
2210 return "";
2211 }
2212 RELEASE_ASSERT_NOT_REACHED();
2213 return nullptr;
2214}
2215
2216template <typename LexerType> template <class TreeBuilder, class FunctionInfoType> typename TreeBuilder::FormalParameterList Parser<LexerType>::parseFunctionParameters(TreeBuilder& context, SourceParseMode mode, FunctionInfoType& functionInfo)
2217{
2218 RELEASE_ASSERT(!(SourceParseModeSet(SourceParseMode::ProgramMode, SourceParseMode::ModuleAnalyzeMode, SourceParseMode::ModuleEvaluateMode).contains(mode)));
2219 TreeFormalParameterList parameterList = context.createFormalParameterList();
2220 SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_parserState.functionParsePhase, FunctionParsePhase::Parameters);
2221
2222 if (UNLIKELY((SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode).contains(mode)))) {
2223 if (!matchSpecIdentifier() && !match(OPENPAREN)) {
2224 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
2225 failWithMessage("Expected an arrow function input parameter");
2226 } else {
2227 if (match(OPENPAREN)) {
2228 next();
2229
2230 if (match(CLOSEPAREN)) {
2231 functionInfo.parameterCount = 0;
2232 } else {
2233 bool isArrowFunction = true;
2234 bool isMethod = false;
2235 failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, isMethod, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
2236 }
2237
2238 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
2239 } else {
2240 functionInfo.parameterCount = 1;
2241 auto parameter = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported);
2242 failIfFalse(parameter, "Cannot parse parameter pattern");
2243 context.appendParameter(parameterList, parameter, 0);
2244 }
2245 }
2246
2247 return parameterList;
2248 }
2249
2250 if (!consume(OPENPAREN)) {
2251 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
2252 failWithMessage("Expected an opening '(' before a ", stringForFunctionMode(mode), "'s parameter list");
2253 }
2254
2255 if (mode == SourceParseMode::GetterMode) {
2256 consumeOrFail(CLOSEPAREN, "getter functions must have no parameters");
2257 functionInfo.parameterCount = 0;
2258 } else if (mode == SourceParseMode::SetterMode) {
2259 failIfTrue(match(CLOSEPAREN), "setter functions must have one parameter");
2260 const Identifier* duplicateParameter = nullptr;
2261 bool hasDestructuringPattern = false;
2262 auto parameter = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported, &duplicateParameter, &hasDestructuringPattern);
2263 failIfFalse(parameter, "setter functions must have one parameter");
2264 auto defaultValue = parseDefaultValueForDestructuringPattern(context);
2265 propagateError();
2266 if (defaultValue || hasDestructuringPattern) {
2267 semanticFailIfTrue(duplicateParameter, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with non-simple parameter list");
2268 currentScope()->setHasNonSimpleParameterList();
2269 }
2270 context.appendParameter(parameterList, parameter, defaultValue);
2271 functionInfo.parameterCount = defaultValue ? 0 : 1;
2272 failIfTrue(match(COMMA), "setter functions must have one parameter");
2273 consumeOrFail(CLOSEPAREN, "Expected a ')' after a parameter declaration");
2274 } else {
2275 if (match(CLOSEPAREN)) {
2276 functionInfo.parameterCount = 0;
2277 } else {
2278 bool isArrowFunction = false;
2279 bool isMethod = isMethodParseMode(mode);
2280 failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, isMethod, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
2281 }
2282 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
2283 }
2284
2285 return parameterList;
2286}
2287
2288template <typename LexerType>
2289template <class TreeBuilder> typename TreeBuilder::FormalParameterList Parser<LexerType>::createGeneratorParameters(TreeBuilder& context, unsigned& parameterCount)
2290{
2291 auto parameters = context.createFormalParameterList();
2292
2293 JSTokenLocation location(tokenLocation());
2294 JSTextPosition position = tokenStartPosition();
2295
2296 auto addParameter = [&](const Identifier& name) {
2297 declareParameter(&name);
2298 auto binding = context.createBindingLocation(location, name, position, position, AssignmentContext::DeclarationStatement);
2299 context.appendParameter(parameters, binding, 0);
2300 ++parameterCount;
2301 };
2302
2303 // @generator
2304 addParameter(m_vm.propertyNames->generatorPrivateName);
2305 // @generatorState
2306 addParameter(m_vm.propertyNames->generatorStatePrivateName);
2307 // @generatorValue
2308 addParameter(m_vm.propertyNames->generatorValuePrivateName);
2309 // @generatorResumeMode
2310 addParameter(m_vm.propertyNames->generatorResumeModePrivateName);
2311 // @generatorFrame
2312 addParameter(m_vm.propertyNames->generatorFramePrivateName);
2313
2314 return parameters;
2315}
2316
2317template <typename LexerType>
2318template <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, Optional<int> functionConstructorParametersEndPosition)
2319{
2320 RELEASE_ASSERT(isFunctionParseMode(mode));
2321
2322 ScopeRef parentScope = currentScope();
2323
2324 bool isDisallowedAwaitFunctionName = isDisallowedIdentifierAwait(m_token);
2325 const char* isDisallowedAwaitFunctionNameReason = isDisallowedAwaitFunctionName ? disallowedIdentifierAwaitReason() : nullptr;
2326
2327 AutoPopScopeRef functionScope(this, pushScope());
2328 functionScope->setSourceParseMode(mode);
2329 functionScope->setExpectedSuperBinding(expectedSuperBinding);
2330 functionScope->setConstructorKind(constructorKind);
2331 SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_parserState.functionParsePhase, FunctionParsePhase::Body);
2332 int functionNameStart = m_token.m_location.startOffset;
2333 const Identifier* lastFunctionName = m_parserState.lastFunctionName;
2334 m_parserState.lastFunctionName = nullptr;
2335 int parametersStart = -1;
2336 JSTokenLocation startLocation;
2337 int startColumn = -1;
2338 FunctionBodyType functionBodyType;
2339
2340 auto loadCachedFunction = [&] () -> bool {
2341 if (UNLIKELY(!Options::useSourceProviderCache()))
2342 return false;
2343
2344 if (UNLIKELY(m_debuggerParseData))
2345 return false;
2346
2347 ASSERT(parametersStart != -1);
2348 ASSERT(startColumn != -1);
2349
2350 // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
2351 if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFu