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
91ALWAYS_INLINE static SourceParseMode getAsynFunctionBodyParseMode(SourceParseMode parseMode)
92{
93 if (isAsyncGeneratorWrapperParseMode(parseMode))
94 return SourceParseMode::AsyncGeneratorBodyMode;
95
96 if (parseMode == SourceParseMode::AsyncArrowFunctionMode)
97 return SourceParseMode::AsyncArrowFunctionBodyMode;
98
99 return SourceParseMode::AsyncFunctionBodyMode;
100}
101
102template <typename LexerType>
103void Parser<LexerType>::logError(bool)
104{
105 if (hasError())
106 return;
107 StringPrintStream stream;
108 printUnexpectedTokenText(stream);
109 setErrorMessage(stream.toStringWithLatin1Fallback());
110}
111
112template <typename LexerType> template <typename... Args>
113void Parser<LexerType>::logError(bool shouldPrintToken, Args&&... args)
114{
115 if (hasError())
116 return;
117 StringPrintStream stream;
118 if (shouldPrintToken) {
119 printUnexpectedTokenText(stream);
120 stream.print(". ");
121 }
122 stream.print(std::forward<Args>(args)..., ".");
123 setErrorMessage(stream.toStringWithLatin1Fallback());
124}
125
126template <typename LexerType>
127Parser<LexerType>::Parser(VM* vm, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, SourceParseMode parseMode, SuperBinding superBinding, ConstructorKind defaultConstructorKind, DerivedContextType derivedContextType, bool isEvalContext, EvalContextType evalContextType, DebuggerParseData* debuggerParseData)
128 : m_vm(vm)
129 , m_source(&source)
130 , m_hasStackOverflow(false)
131 , m_allowsIn(true)
132 , m_statementDepth(0)
133 , m_sourceElements(0)
134 , m_parsingBuiltin(builtinMode == JSParserBuiltinMode::Builtin)
135 , m_scriptMode(scriptMode)
136 , m_superBinding(superBinding)
137 , m_defaultConstructorKind(defaultConstructorKind)
138 , m_immediateParentAllowsFunctionDeclarationInStatement(false)
139 , m_debuggerParseData(debuggerParseData)
140{
141 m_lexer = std::make_unique<LexerType>(vm, builtinMode, scriptMode);
142 m_lexer->setCode(source, &m_parserArena);
143 m_token.m_location.line = source.firstLine().oneBasedInt();
144 m_token.m_location.startOffset = source.startOffset();
145 m_token.m_location.endOffset = source.startOffset();
146 m_token.m_location.lineStartOffset = source.startOffset();
147 m_functionCache = vm->addSourceProviderCache(source.provider());
148 m_expressionErrorClassifier = nullptr;
149
150 ScopeRef scope = pushScope();
151 scope->setSourceParseMode(parseMode);
152 scope->setIsEvalContext(isEvalContext);
153 if (isEvalContext)
154 scope->setEvalContextType(evalContextType);
155
156 if (derivedContextType == DerivedContextType::DerivedConstructorContext) {
157 scope->setConstructorKind(ConstructorKind::Extends);
158 scope->setExpectedSuperBinding(SuperBinding::Needed);
159 }
160
161 if (derivedContextType == DerivedContextType::DerivedMethodContext)
162 scope->setExpectedSuperBinding(SuperBinding::Needed);
163
164 if (strictMode == JSParserStrictMode::Strict)
165 scope->setStrictMode();
166
167 if (isModuleParseMode(parseMode))
168 m_moduleScopeData = ModuleScopeData::create();
169
170 if (isProgramOrModuleParseMode(parseMode))
171 scope->setIsGlobalCodeScope();
172
173 next();
174}
175
176class Scope::MaybeParseAsGeneratorForScope : public SetForScope<bool> {
177public:
178 MaybeParseAsGeneratorForScope(ScopeRef& scope, bool shouldParseAsGenerator)
179 : SetForScope<bool>(scope->m_isGenerator, shouldParseAsGenerator) { }
180};
181
182struct DepthManager : private SetForScope<int> {
183public:
184 DepthManager(int* depth)
185 : SetForScope<int>(*depth, *depth)
186 {
187 }
188};
189
190template <typename LexerType>
191Parser<LexerType>::~Parser()
192{
193}
194
195template <typename LexerType>
196String Parser<LexerType>::parseInner(const Identifier& calleeName, SourceParseMode parseMode, ParsingContext parsingContext, Optional<int> functionConstructorParametersEndPosition)
197{
198 String parseError = String();
199
200 ASTBuilder context(const_cast<VM*>(m_vm), m_parserArena, const_cast<SourceCode*>(m_source));
201 ScopeRef scope = currentScope();
202 scope->setIsLexicalScope();
203 SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_parserState.functionParsePhase, FunctionParsePhase::Body);
204
205 bool isArrowFunctionBodyExpression = parseMode == SourceParseMode::AsyncArrowFunctionBodyMode && !match(OPENBRACE);
206 if (m_lexer->isReparsingFunction()) {
207 ParserFunctionInfo<ASTBuilder> functionInfo;
208 if (isGeneratorOrAsyncFunctionBodyParseMode(parseMode))
209 m_parameters = createGeneratorParameters(context, functionInfo.parameterCount);
210 else
211 m_parameters = parseFunctionParameters(context, parseMode, functionInfo);
212
213 if (SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode).contains(parseMode) && !hasError()) {
214 // The only way we could have an error wile reparsing is if we run out of stack space.
215 RELEASE_ASSERT(match(ARROWFUNCTION));
216 next();
217 isArrowFunctionBodyExpression = !match(OPENBRACE);
218 }
219 }
220
221 if (!calleeName.isNull())
222 scope->declareCallee(&calleeName);
223
224 if (m_lexer->isReparsingFunction())
225 m_statementDepth--;
226
227 SourceElements* sourceElements = nullptr;
228 // The only way we can error this early is if we reparse a function and we run out of stack space.
229 if (!hasError()) {
230 if (isAsyncFunctionWrapperParseMode(parseMode))
231 sourceElements = parseAsyncFunctionSourceElements(context, parseMode, isArrowFunctionBodyExpression, CheckForStrictMode);
232 else if (isArrowFunctionBodyExpression)
233 sourceElements = parseArrowFunctionSingleExpressionBodySourceElements(context);
234 else if (isModuleParseMode(parseMode))
235 sourceElements = parseModuleSourceElements(context, parseMode);
236 else if (isGeneratorWrapperParseMode(parseMode))
237 sourceElements = parseGeneratorFunctionSourceElements(context, calleeName, CheckForStrictMode);
238 else if (isAsyncGeneratorWrapperParseMode(parseMode))
239 sourceElements = parseAsyncGeneratorFunctionSourceElements(context, parseMode, isArrowFunctionBodyExpression, CheckForStrictMode);
240 else if (parsingContext == ParsingContext::FunctionConstructor)
241 sourceElements = parseSingleFunction(context, functionConstructorParametersEndPosition);
242 else
243 sourceElements = parseSourceElements(context, CheckForStrictMode);
244 }
245
246 bool validEnding = consume(EOFTOK);
247 if (!sourceElements || !validEnding) {
248 if (hasError())
249 parseError = m_errorMessage;
250 else
251 parseError = "Parser error"_s;
252 }
253
254 IdentifierSet capturedVariables;
255 UniquedStringImplPtrSet sloppyModeHoistedFunctions;
256 scope->getSloppyModeHoistedFunctions(sloppyModeHoistedFunctions);
257 scope->getCapturedVars(capturedVariables);
258
259 VariableEnvironment& varDeclarations = scope->declaredVariables();
260 for (auto& entry : capturedVariables)
261 varDeclarations.markVariableAsCaptured(entry);
262
263 if (isGeneratorWrapperParseMode(parseMode) || isAsyncFunctionOrAsyncGeneratorWrapperParseMode(parseMode)) {
264 if (scope->usedVariablesContains(m_vm->propertyNames->arguments.impl()))
265 context.propagateArgumentsUse();
266 }
267
268 CodeFeatures features = context.features();
269 if (scope->strictMode())
270 features |= StrictModeFeature;
271 if (scope->shadowsArguments())
272 features |= ShadowsArgumentsFeature;
273 if (m_seenTaggedTemplate)
274 features |= NoEvalCacheFeature;
275
276#ifndef NDEBUG
277 if (m_parsingBuiltin && isProgramParseMode(parseMode)) {
278 VariableEnvironment& lexicalVariables = scope->lexicalVariables();
279 const HashSet<UniquedStringImpl*>& closedVariableCandidates = scope->closedVariableCandidates();
280 for (UniquedStringImpl* candidate : closedVariableCandidates) {
281 // FIXME: We allow async to leak because it appearing as a closed variable is a side effect of trying to parse async arrow functions.
282 if (!lexicalVariables.contains(candidate) && !varDeclarations.contains(candidate) && !candidate->isSymbol() && candidate != m_vm->propertyNames->async.impl()) {
283 dataLog("Bad global capture in builtin: '", candidate, "'\n");
284 dataLog(m_source->view());
285 CRASH();
286 }
287 }
288 }
289#endif // NDEBUG
290 didFinishParsing(sourceElements, scope->takeFunctionDeclarations(), varDeclarations, WTFMove(sloppyModeHoistedFunctions), features, context.numConstants());
291
292 return parseError;
293}
294
295template <typename LexerType>
296void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, DeclarationStacks::FunctionStack&& funcStack,
297 VariableEnvironment& varDeclarations, UniquedStringImplPtrSet&& sloppyModeHoistedFunctions, CodeFeatures features, int numConstants)
298{
299 m_sourceElements = sourceElements;
300 m_funcDeclarations = WTFMove(funcStack);
301 m_varDeclarations.swap(varDeclarations);
302 m_features = features;
303 m_sloppyModeHoistedFunctions = WTFMove(sloppyModeHoistedFunctions);
304 m_numConstants = numConstants;
305}
306
307template <typename LexerType>
308bool Parser<LexerType>::isArrowFunctionParameters()
309{
310 if (match(OPENPAREN)) {
311 SavePoint saveArrowFunctionPoint = createSavePoint();
312 next();
313 bool isArrowFunction = false;
314 if (match(CLOSEPAREN)) {
315 next();
316 isArrowFunction = match(ARROWFUNCTION);
317 } else {
318 SyntaxChecker syntaxChecker(const_cast<VM*>(m_vm), m_lexer.get());
319 // We make fake scope, otherwise parseFormalParameters will add variable to current scope that lead to errors
320 AutoPopScopeRef fakeScope(this, pushScope());
321 fakeScope->setSourceParseMode(SourceParseMode::ArrowFunctionMode);
322
323 unsigned parametersCount = 0;
324 bool isArrowFunctionParameterList = true;
325 bool isMethod = false;
326 isArrowFunction = parseFormalParameters(syntaxChecker, syntaxChecker.createFormalParameterList(), isArrowFunctionParameterList, isMethod, parametersCount) && consume(CLOSEPAREN) && match(ARROWFUNCTION);
327 propagateError();
328 popScope(fakeScope, syntaxChecker.NeedsFreeVariableInfo);
329 }
330 restoreSavePoint(saveArrowFunctionPoint);
331 return isArrowFunction;
332 }
333
334 if (matchSpecIdentifier()) {
335 SavePoint saveArrowFunctionPoint = createSavePoint();
336 next();
337 bool isArrowFunction = match(ARROWFUNCTION);
338 restoreSavePoint(saveArrowFunctionPoint);
339 return isArrowFunction;
340 }
341
342 return false;
343}
344
345template <typename LexerType>
346bool Parser<LexerType>::allowAutomaticSemicolon()
347{
348 return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->hasLineTerminatorBeforeToken();
349}
350
351template <typename LexerType>
352template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSourceElements(TreeBuilder& context, SourceElementsMode mode)
353{
354 const unsigned lengthOfUseStrictLiteral = 12; // "use strict".length
355 TreeSourceElements sourceElements = context.createSourceElements();
356 const Identifier* directive = 0;
357 unsigned directiveLiteralLength = 0;
358 auto savePoint = createSavePoint();
359 bool shouldCheckForUseStrict = mode == CheckForStrictMode;
360
361 while (TreeStatement statement = parseStatementListItem(context, directive, &directiveLiteralLength)) {
362 if (shouldCheckForUseStrict) {
363 if (directive) {
364 // "use strict" must be the exact literal without escape sequences or line continuation.
365 if (directiveLiteralLength == lengthOfUseStrictLiteral && m_vm->propertyNames->useStrictIdentifier == *directive) {
366 setStrictMode();
367 shouldCheckForUseStrict = false; // We saw "use strict", there is no need to keep checking for it.
368 if (!isValidStrictMode()) {
369 if (m_parserState.lastFunctionName) {
370 if (m_vm->propertyNames->arguments == *m_parserState.lastFunctionName)
371 semanticFail("Cannot name a function 'arguments' in strict mode");
372 if (m_vm->propertyNames->eval == *m_parserState.lastFunctionName)
373 semanticFail("Cannot name a function 'eval' in strict mode");
374 }
375 if (hasDeclaredVariable(m_vm->propertyNames->arguments))
376 semanticFail("Cannot declare a variable named 'arguments' in strict mode");
377 if (hasDeclaredVariable(m_vm->propertyNames->eval))
378 semanticFail("Cannot declare a variable named 'eval' in strict mode");
379 semanticFailIfTrue(currentScope()->hasNonSimpleParameterList(), "'use strict' directive not allowed inside a function with a non-simple parameter list");
380 semanticFailIfFalse(isValidStrictMode(), "Invalid parameters or function name in strict mode");
381 }
382 // Since strict mode is changed, restoring lexer state by calling next() may cause errors.
383 restoreSavePoint(savePoint);
384 propagateError();
385 continue;
386 }
387
388 // We saw a directive, but it wasn't "use strict". We reset our state to
389 // see if the next statement we parse is also a directive.
390 directive = nullptr;
391 } else {
392 // We saw a statement that wasn't in the form of a directive. The spec says that "use strict"
393 // is only allowed as the first statement, or after a sequence of directives before it, but
394 // not after non-directive statements.
395 shouldCheckForUseStrict = false;
396 }
397 }
398 context.appendStatement(sourceElements, statement);
399 }
400
401 propagateError();
402 return sourceElements;
403}
404
405template <typename LexerType>
406template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseModuleSourceElements(TreeBuilder& context, SourceParseMode parseMode)
407{
408 TreeSourceElements sourceElements = context.createSourceElements();
409 SyntaxChecker syntaxChecker(const_cast<VM*>(m_vm), m_lexer.get());
410
411 while (true) {
412 TreeStatement statement = 0;
413 switch (m_token.m_type) {
414 case EXPORT:
415 statement = parseExportDeclaration(context);
416 if (statement)
417 recordPauseLocation(context.breakpointLocation(statement));
418 break;
419
420 case IMPORT: {
421 SavePoint savePoint = createSavePoint();
422 next();
423 bool isImportDeclaration = !match(OPENPAREN) && !match(DOT);
424 restoreSavePoint(savePoint);
425 if (isImportDeclaration) {
426 statement = parseImportDeclaration(context);
427 if (statement)
428 recordPauseLocation(context.breakpointLocation(statement));
429 break;
430 }
431
432 // This is `import("...")` call or `import.meta` meta property case.
433 FALLTHROUGH;
434 }
435
436 default: {
437 const Identifier* directive = 0;
438 unsigned directiveLiteralLength = 0;
439 if (parseMode == SourceParseMode::ModuleAnalyzeMode) {
440 if (!parseStatementListItem(syntaxChecker, directive, &directiveLiteralLength))
441 goto end;
442 continue;
443 }
444 statement = parseStatementListItem(context, directive, &directiveLiteralLength);
445 break;
446 }
447 }
448
449 if (!statement)
450 goto end;
451 context.appendStatement(sourceElements, statement);
452 }
453
454end:
455 propagateError();
456
457 for (const auto& pair : m_moduleScopeData->exportedBindings()) {
458 const auto& uid = pair.key;
459 if (currentScope()->hasDeclaredVariable(uid)) {
460 currentScope()->declaredVariables().markVariableAsExported(uid);
461 continue;
462 }
463
464 if (currentScope()->hasLexicallyDeclaredVariable(uid)) {
465 currentScope()->lexicalVariables().markVariableAsExported(uid);
466 continue;
467 }
468
469 semanticFail("Exported binding '", uid.get(), "' needs to refer to a top-level declared variable");
470 }
471
472 return sourceElements;
473}
474
475template <typename LexerType>
476template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseGeneratorFunctionSourceElements(TreeBuilder& context, const Identifier& name, SourceElementsMode mode)
477{
478 auto sourceElements = context.createSourceElements();
479
480 unsigned functionKeywordStart = tokenStart();
481 JSTokenLocation startLocation(tokenLocation());
482 JSTextPosition start = tokenStartPosition();
483 unsigned startColumn = tokenColumn();
484 int functionNameStart = m_token.m_location.startOffset;
485 int parametersStart = m_token.m_location.startOffset;
486
487 ParserFunctionInfo<TreeBuilder> info;
488 info.name = &m_vm->propertyNames->nullIdentifier;
489 createGeneratorParameters(context, info.parameterCount);
490 info.startOffset = parametersStart;
491 info.startLine = tokenLine();
492
493 {
494 AutoPopScopeRef generatorBodyScope(this, pushScope());
495 generatorBodyScope->setSourceParseMode(SourceParseMode::GeneratorBodyMode);
496 generatorBodyScope->setConstructorKind(ConstructorKind::None);
497 generatorBodyScope->setExpectedSuperBinding(m_superBinding);
498
499 SyntaxChecker generatorFunctionContext(const_cast<VM*>(m_vm), m_lexer.get());
500 failIfFalse(parseSourceElements(generatorFunctionContext, mode), "Cannot parse the body of a generator");
501 popScope(generatorBodyScope, TreeBuilder::NeedsFreeVariableInfo);
502 }
503 info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, SourceParseMode::GeneratorBodyMode, false);
504
505 info.endLine = tokenLine();
506 info.endOffset = m_token.m_data.offset;
507 info.parametersStartColumn = startColumn;
508
509 auto functionExpr = context.createGeneratorFunctionBody(startLocation, info, name);
510 auto statement = context.createExprStatement(startLocation, functionExpr, start, m_lastTokenEndPosition.line);
511 context.appendStatement(sourceElements, statement);
512
513 return sourceElements;
514}
515
516template <typename LexerType>
517template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseAsyncFunctionSourceElements(TreeBuilder& context, SourceParseMode parseMode, bool isArrowFunctionBodyExpression, SourceElementsMode mode)
518{
519 ASSERT(isAsyncFunctionOrAsyncGeneratorWrapperParseMode(parseMode));
520 auto sourceElements = context.createSourceElements();
521
522 unsigned functionKeywordStart = tokenStart();
523 JSTokenLocation startLocation(tokenLocation());
524 JSTextPosition start = tokenStartPosition();
525 unsigned startColumn = tokenColumn();
526 int functionNameStart = m_token.m_location.startOffset;
527 int parametersStart = m_token.m_location.startOffset;
528
529 ParserFunctionInfo<TreeBuilder> info;
530 info.name = &m_vm->propertyNames->nullIdentifier;
531 createGeneratorParameters(context, info.parameterCount);
532 info.startOffset = parametersStart;
533 info.startLine = tokenLine();
534
535 SourceParseMode innerParseMode = getAsynFunctionBodyParseMode(parseMode);
536
537 {
538 AutoPopScopeRef asyncFunctionBodyScope(this, pushScope());
539 asyncFunctionBodyScope->setSourceParseMode(innerParseMode);
540 SyntaxChecker syntaxChecker(const_cast<VM*>(m_vm), m_lexer.get());
541 if (isArrowFunctionBodyExpression) {
542 if (m_debuggerParseData)
543 failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(context), "Cannot parse the body of async arrow function");
544 else
545 failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(syntaxChecker), "Cannot parse the body of async arrow function");
546 } else {
547 if (m_debuggerParseData)
548 failIfFalse(parseSourceElements(context, mode), "Cannot parse the body of async function");
549 else
550 failIfFalse(parseSourceElements(syntaxChecker, mode), "Cannot parse the body of async function");
551 }
552 popScope(asyncFunctionBodyScope, TreeBuilder::NeedsFreeVariableInfo);
553 }
554 info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, innerParseMode, isArrowFunctionBodyExpression);
555
556 info.endLine = tokenLine();
557 info.endOffset = isArrowFunctionBodyExpression ? tokenLocation().endOffset : m_token.m_data.offset;
558 info.parametersStartColumn = startColumn;
559
560 auto functionExpr = context.createAsyncFunctionBody(startLocation, info, innerParseMode);
561 auto statement = context.createExprStatement(startLocation, functionExpr, start, m_lastTokenEndPosition.line);
562 context.appendStatement(sourceElements, statement);
563
564 return sourceElements;
565}
566
567template <typename LexerType>
568template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseAsyncGeneratorFunctionSourceElements(TreeBuilder& context, SourceParseMode parseMode, bool isArrowFunctionBodyExpression, SourceElementsMode mode)
569{
570 ASSERT_UNUSED(parseMode, isAsyncGeneratorWrapperParseMode(parseMode));
571 auto sourceElements = context.createSourceElements();
572
573 unsigned functionKeywordStart = tokenStart();
574 JSTokenLocation startLocation(tokenLocation());
575 JSTextPosition start = tokenStartPosition();
576 unsigned startColumn = tokenColumn();
577 int functionNameStart = m_token.m_location.startOffset;
578 int parametersStart = m_token.m_location.startOffset;
579
580 ParserFunctionInfo<TreeBuilder> info;
581 info.name = &m_vm->propertyNames->nullIdentifier;
582 createGeneratorParameters(context, info.parameterCount);
583 info.startOffset = parametersStart;
584 info.startLine = tokenLine();
585 SourceParseMode innerParseMode = SourceParseMode::AsyncGeneratorBodyMode;
586 {
587 AutoPopScopeRef asyncFunctionBodyScope(this, pushScope());
588 asyncFunctionBodyScope->setSourceParseMode(innerParseMode);
589 SyntaxChecker syntaxChecker(const_cast<VM*>(m_vm), m_lexer.get());
590 if (isArrowFunctionBodyExpression) {
591 if (m_debuggerParseData)
592 failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(context), "Cannot parse the body of async arrow function");
593 else
594 failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(syntaxChecker), "Cannot parse the body of async arrow function");
595 } else {
596 if (m_debuggerParseData)
597 failIfFalse(parseSourceElements(context, mode), "Cannot parse the body of async function");
598 else
599 failIfFalse(parseSourceElements(syntaxChecker, mode), "Cannot parse the body of async function");
600 }
601 popScope(asyncFunctionBodyScope, TreeBuilder::NeedsFreeVariableInfo);
602 }
603 info.body = context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, tokenColumn(), functionKeywordStart, functionNameStart, parametersStart, strictMode(), ConstructorKind::None, m_superBinding, info.parameterCount, innerParseMode, isArrowFunctionBodyExpression);
604
605 info.endLine = tokenLine();
606 info.endOffset = isArrowFunctionBodyExpression ? tokenLocation().endOffset : m_token.m_data.offset;
607 info.parametersStartColumn = startColumn;
608
609 auto functionExpr = context.createAsyncFunctionBody(startLocation, info, innerParseMode);
610 auto statement = context.createExprStatement(startLocation, functionExpr, start, m_lastTokenEndPosition.line);
611 context.appendStatement(sourceElements, statement);
612
613 return sourceElements;
614}
615
616template <typename LexerType>
617template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseSingleFunction(TreeBuilder& context, Optional<int> functionConstructorParametersEndPosition)
618{
619 TreeSourceElements sourceElements = context.createSourceElements();
620 TreeStatement statement = 0;
621 switch (m_token.m_type) {
622 case FUNCTION:
623 statement = parseFunctionDeclaration(context, ExportType::NotExported, DeclarationDefaultContext::Standard, functionConstructorParametersEndPosition);
624 break;
625 case IDENT:
626 if (*m_token.m_data.ident == m_vm->propertyNames->async && !m_token.m_data.escaped) {
627 next();
628 failIfFalse(match(FUNCTION) && !m_lexer->hasLineTerminatorBeforeToken(), "Cannot parse the async function");
629 statement = parseAsyncFunctionDeclaration(context, ExportType::NotExported, DeclarationDefaultContext::Standard, functionConstructorParametersEndPosition);
630 break;
631 }
632 FALLTHROUGH;
633 default:
634 failDueToUnexpectedToken();
635 break;
636 }
637
638 if (statement) {
639 context.setEndOffset(statement, m_lastTokenEndPosition.offset);
640 context.appendStatement(sourceElements, statement);
641 }
642
643 propagateError();
644 return sourceElements;
645}
646
647
648template <typename LexerType>
649template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatementListItem(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
650{
651 // The grammar is documented here:
652 // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-statements
653 DepthManager statementDepth(&m_statementDepth);
654 m_statementDepth++;
655 TreeStatement result = 0;
656 bool shouldSetEndOffset = true;
657 bool shouldSetPauseLocation = false;
658
659 switch (m_token.m_type) {
660 case CONSTTOKEN:
661 result = parseVariableDeclaration(context, DeclarationType::ConstDeclaration);
662 shouldSetPauseLocation = true;
663 break;
664 case LET: {
665 bool shouldParseVariableDeclaration = true;
666 if (!strictMode()) {
667 SavePoint savePoint = createSavePoint();
668 next();
669 // Intentionally use `isIdentifierOrAnyContextualKeyword(m_token)` and don't use `matchSpecIdentifier()`.
670 // We would like to fall into parseVariableDeclaration path even if "yield" is not treated as an Identifier.
671 // For example, under a generator context, matchSpecIdentifier() for "yield" returns `false`.
672 // But we would like to enter parseVariableDeclaration and raise an error under the context of parseVariableDeclaration
673 // to raise consistent errors between "var", "const" and "let".
674 if (!isIdentifierOrAnyContextualKeyword(m_token) && !match(OPENBRACE) && !match(OPENBRACKET))
675 shouldParseVariableDeclaration = false;
676 restoreSavePoint(savePoint);
677 }
678 if (shouldParseVariableDeclaration)
679 result = parseVariableDeclaration(context, DeclarationType::LetDeclaration);
680 else {
681 bool allowFunctionDeclarationAsStatement = true;
682 result = parseExpressionOrLabelStatement(context, allowFunctionDeclarationAsStatement);
683 }
684 shouldSetPauseLocation = !context.shouldSkipPauseLocation(result);
685 break;
686 }
687 case CLASSTOKEN:
688 result = parseClassDeclaration(context);
689 break;
690 case FUNCTION:
691 result = parseFunctionDeclaration(context);
692 break;
693 case IDENT:
694 if (UNLIKELY(*m_token.m_data.ident == m_vm->propertyNames->async && !m_token.m_data.escaped)) {
695 // Eagerly parse as AsyncFunctionDeclaration. This is the uncommon case,
696 // but could be mistakenly parsed as an AsyncFunctionExpression.
697 SavePoint savePoint = createSavePoint();
698 next();
699 if (UNLIKELY(match(FUNCTION) && !m_lexer->hasLineTerminatorBeforeToken())) {
700 result = parseAsyncFunctionDeclaration(context);
701 break;
702 }
703 restoreSavePoint(savePoint);
704 }
705 FALLTHROUGH;
706 case AWAIT:
707 case YIELD: {
708 // This is a convenient place to notice labeled statements
709 // (even though we also parse them as normal statements)
710 // because we allow the following type of code in sloppy mode:
711 // ``` function foo() { label: function bar() { } } ```
712 bool allowFunctionDeclarationAsStatement = true;
713 result = parseExpressionOrLabelStatement(context, allowFunctionDeclarationAsStatement);
714 shouldSetPauseLocation = !context.shouldSkipPauseLocation(result);
715 break;
716 }
717 default:
718 m_statementDepth--; // parseStatement() increments the depth.
719 result = parseStatement(context, directive, directiveLiteralLength);
720 shouldSetEndOffset = false;
721 break;
722 }
723
724 if (result) {
725 if (shouldSetEndOffset)
726 context.setEndOffset(result, m_lastTokenEndPosition.offset);
727 if (shouldSetPauseLocation)
728 recordPauseLocation(context.breakpointLocation(result));
729 }
730
731 return result;
732}
733
734template <typename LexerType>
735template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVariableDeclaration(TreeBuilder& context, DeclarationType declarationType, ExportType exportType)
736{
737 ASSERT(match(VAR) || match(LET) || match(CONSTTOKEN));
738 JSTokenLocation location(tokenLocation());
739 int start = tokenLine();
740 int end = 0;
741 int scratch;
742 TreeDestructuringPattern scratch1 = 0;
743 TreeExpression scratch2 = 0;
744 JSTextPosition scratch3;
745 bool scratchBool;
746 TreeExpression variableDecls = parseVariableDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3, VarDeclarationContext, declarationType, exportType, scratchBool);
747 propagateError();
748 failIfFalse(autoSemiColon(), "Expected ';' after variable declaration");
749
750 return context.createDeclarationStatement(location, variableDecls, start, end);
751}
752
753template <typename LexerType>
754template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDoWhileStatement(TreeBuilder& context)
755{
756 ASSERT(match(DO));
757 int startLine = tokenLine();
758 next();
759 const Identifier* unused = 0;
760 startLoop();
761 TreeStatement statement = parseStatement(context, unused);
762 endLoop();
763 failIfFalse(statement, "Expected a statement following 'do'");
764 int endLine = tokenLine();
765 JSTokenLocation location(tokenLocation());
766 handleProductionOrFail(WHILE, "while", "end", "do-while loop");
767 handleProductionOrFail(OPENPAREN, "(", "start", "do-while loop condition");
768 semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a do-while loop condition");
769 TreeExpression expr = parseExpression(context);
770 failIfFalse(expr, "Unable to parse do-while loop condition");
771 recordPauseLocation(context.breakpointLocation(expr));
772 handleProductionOrFail(CLOSEPAREN, ")", "end", "do-while loop condition");
773 if (match(SEMICOLON))
774 next(); // Always performs automatic semicolon insertion.
775 return context.createDoWhileStatement(location, statement, expr, startLine, endLine);
776}
777
778template <typename LexerType>
779template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWhileStatement(TreeBuilder& context)
780{
781 ASSERT(match(WHILE));
782 JSTokenLocation location(tokenLocation());
783 int startLine = tokenLine();
784 next();
785
786 handleProductionOrFail(OPENPAREN, "(", "start", "while loop condition");
787 semanticFailIfTrue(match(CLOSEPAREN), "Must provide an expression as a while loop condition");
788 TreeExpression expr = parseExpression(context);
789 failIfFalse(expr, "Unable to parse while loop condition");
790 recordPauseLocation(context.breakpointLocation(expr));
791 int endLine = tokenLine();
792 handleProductionOrFail(CLOSEPAREN, ")", "end", "while loop condition");
793
794 const Identifier* unused = 0;
795 startLoop();
796 TreeStatement statement = parseStatement(context, unused);
797 endLoop();
798 failIfFalse(statement, "Expected a statement as the body of a while loop");
799 return context.createWhileStatement(location, expr, statement, startLine, endLine);
800}
801
802template <typename LexerType>
803template <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)
804{
805 ASSERT(declarationType == DeclarationType::LetDeclaration || declarationType == DeclarationType::VarDeclaration || declarationType == DeclarationType::ConstDeclaration);
806 TreeExpression head = 0;
807 TreeExpression tail = 0;
808 const Identifier* lastIdent;
809 JSToken lastIdentToken;
810 AssignmentContext assignmentContext = assignmentContextFromDeclarationType(declarationType);
811 do {
812 lastIdent = 0;
813 lastPattern = TreeDestructuringPattern(0);
814 JSTokenLocation location(tokenLocation());
815 next();
816 TreeExpression node = 0;
817 declarations++;
818 bool hasInitializer = false;
819 if (matchSpecIdentifier()) {
820 failIfTrue(match(LET) && (declarationType == DeclarationType::LetDeclaration || declarationType == DeclarationType::ConstDeclaration),
821 "Cannot use 'let' as an identifier name for a LexicalDeclaration");
822 semanticFailIfTrue(isDisallowedIdentifierAwait(m_token), "Cannot use 'await' as a ", declarationTypeToVariableKind(declarationType), " ", disallowedIdentifierAwaitReason());
823 JSTextPosition varStart = tokenStartPosition();
824 JSTokenLocation varStartLocation(tokenLocation());
825 identStart = varStart;
826 const Identifier* name = m_token.m_data.ident;
827 lastIdent = name;
828 lastIdentToken = m_token;
829 next();
830 hasInitializer = match(EQUAL);
831 DeclarationResultMask declarationResult = declareVariable(name, declarationType);
832 if (declarationResult != DeclarationResult::Valid) {
833 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a variable named ", name->impl(), " in strict mode");
834 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration) {
835 if (declarationType == DeclarationType::LetDeclaration)
836 internalFailWithMessage(false, "Cannot declare a let variable twice: '", name->impl(), "'");
837 if (declarationType == DeclarationType::ConstDeclaration)
838 internalFailWithMessage(false, "Cannot declare a const variable twice: '", name->impl(), "'");
839 ASSERT(declarationType == DeclarationType::VarDeclaration);
840 internalFailWithMessage(false, "Cannot declare a var variable that shadows a let/const/class variable: '", name->impl(), "'");
841 }
842 }
843 if (exportType == ExportType::Exported) {
844 semanticFailIfFalse(exportName(*name), "Cannot export a duplicate name '", name->impl(), "'");
845 m_moduleScopeData->exportBinding(*name);
846 }
847
848 if (hasInitializer) {
849 JSTextPosition varDivot = tokenStartPosition() + 1;
850 initStart = tokenStartPosition();
851 next(TreeBuilder::DontBuildStrings); // consume '='
852 propagateError();
853 TreeExpression initializer = parseAssignmentExpression(context);
854 initEnd = lastTokenEndPosition();
855 lastInitializer = initializer;
856 failIfFalse(initializer, "Expected expression as the intializer for the variable '", name->impl(), "'");
857
858 node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEndPosition(), assignmentContext);
859 } else {
860 if (declarationListContext == ForLoopContext && declarationType == DeclarationType::ConstDeclaration)
861 forLoopConstDoesNotHaveInitializer = true;
862 failIfTrue(declarationListContext != ForLoopContext && declarationType == DeclarationType::ConstDeclaration, "const declared variable '", name->impl(), "'", " must have an initializer");
863 if (declarationType == DeclarationType::VarDeclaration)
864 node = context.createEmptyVarExpression(varStartLocation, *name);
865 else
866 node = context.createEmptyLetExpression(varStartLocation, *name);
867 }
868 } else {
869 lastIdent = 0;
870 auto pattern = parseDestructuringPattern(context, destructuringKindFromDeclarationType(declarationType), exportType, nullptr, nullptr, assignmentContext);
871 failIfFalse(pattern, "Cannot parse this destructuring pattern");
872 hasInitializer = match(EQUAL);
873 failIfTrue(declarationListContext == VarDeclarationContext && !hasInitializer, "Expected an initializer in destructuring variable declaration");
874 lastPattern = pattern;
875 if (hasInitializer) {
876 next(TreeBuilder::DontBuildStrings); // consume '='
877 TreeExpression rhs = parseAssignmentExpression(context);
878 propagateError();
879 ASSERT(rhs);
880 node = context.createDestructuringAssignment(location, pattern, rhs);
881 lastInitializer = rhs;
882 }
883 }
884
885 if (node) {
886 if (!head)
887 head = node;
888 else if (!tail) {
889 head = context.createCommaExpr(location, head);
890 tail = context.appendToCommaExpr(location, head, head, node);
891 } else
892 tail = context.appendToCommaExpr(location, head, tail, node);
893 }
894 } while (match(COMMA));
895 if (lastIdent)
896 lastPattern = context.createBindingLocation(lastIdentToken.m_location, *lastIdent, lastIdentToken.m_startPosition, lastIdentToken.m_endPosition, assignmentContext);
897
898 return head;
899}
900
901template <typename LexerType>
902bool Parser<LexerType>::declareRestOrNormalParameter(const Identifier& name, const Identifier** duplicateIdentifier)
903{
904 DeclarationResultMask declarationResult = declareParameter(&name);
905 if ((declarationResult & DeclarationResult::InvalidStrictMode) && strictMode()) {
906 semanticFailIfTrue(isEvalOrArguments(&name), "Cannot destructure to a parameter name '", name.impl(), "' in strict mode");
907 if (m_parserState.lastFunctionName && name == *m_parserState.lastFunctionName)
908 semanticFail("Cannot declare a parameter named '", name.impl(), "' as it shadows the name of a strict mode function");
909 semanticFailureDueToKeyword("parameter name");
910 if (!m_lexer->isReparsingFunction() && hasDeclaredParameter(name))
911 semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode as it has already been declared");
912 semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode");
913 }
914 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration) {
915 // It's not always an error to define a duplicate parameter.
916 // It's only an error when there are default parameter values or destructuring parameters.
917 // We note this value now so we can check it later.
918 if (duplicateIdentifier)
919 *duplicateIdentifier = &name;
920 }
921
922 return true;
923}
924
925template <typename LexerType>
926template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::createBindingPattern(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier& name, JSToken token, AssignmentContext bindingContext, const Identifier** duplicateIdentifier)
927{
928 ASSERT(!name.isNull());
929
930 ASSERT(name.impl()->isAtomic() || name.impl()->isSymbol());
931
932 switch (kind) {
933 case DestructuringKind::DestructureToVariables: {
934 DeclarationResultMask declarationResult = declareVariable(&name);
935 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a variable named '", name.impl(), "' in strict mode");
936 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
937 internalFailWithMessage(false, "Cannot declare a var variable that shadows a let/const/class variable: '", name.impl(), "'");
938 break;
939 }
940
941 case DestructuringKind::DestructureToLet:
942 case DestructuringKind::DestructureToConst:
943 case DestructuringKind::DestructureToCatchParameters: {
944 DeclarationResultMask declarationResult = declareVariable(&name, kind == DestructuringKind::DestructureToConst ? DeclarationType::ConstDeclaration : DeclarationType::LetDeclaration);
945 if (declarationResult != DeclarationResult::Valid) {
946 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot destructure to a variable named '", name.impl(), "' in strict mode");
947 failIfTrue(declarationResult & DeclarationResult::InvalidDuplicateDeclaration, "Cannot declare a lexical variable twice: '", name.impl(), "'");
948 }
949 break;
950 }
951
952 case DestructuringKind::DestructureToParameters: {
953 declareRestOrNormalParameter(name, duplicateIdentifier);
954 propagateError();
955 break;
956 }
957
958 case DestructuringKind::DestructureToExpressions: {
959 break;
960 }
961 }
962
963 if (exportType == ExportType::Exported) {
964 semanticFailIfFalse(exportName(name), "Cannot export a duplicate name '", name.impl(), "'");
965 m_moduleScopeData->exportBinding(name);
966 }
967 return context.createBindingLocation(token.m_location, name, token.m_startPosition, token.m_endPosition, bindingContext);
968}
969
970template <typename LexerType>
971template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern Parser<LexerType>::createAssignmentElement(TreeBuilder& context, TreeExpression& assignmentTarget, const JSTextPosition& startPosition, const JSTextPosition& endPosition)
972{
973 return context.createAssignmentElement(assignmentTarget, startPosition, endPosition);
974}
975
976template <typename LexerType>
977template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseArrowFunctionSingleExpressionBodySourceElements(TreeBuilder& context)
978{
979 ASSERT(!match(OPENBRACE));
980
981 JSTokenLocation location(tokenLocation());
982 JSTextPosition start = tokenStartPosition();
983
984 failIfStackOverflow();
985 TreeExpression expr = parseAssignmentExpression(context);
986 failIfFalse(expr, "Cannot parse the arrow function expression");
987
988 context.setEndOffset(expr, m_lastTokenEndPosition.offset);
989
990 JSTextPosition end = tokenEndPosition();
991
992 TreeSourceElements sourceElements = context.createSourceElements();
993 TreeStatement body = context.createReturnStatement(location, expr, start, end);
994 context.setEndOffset(body, m_lastTokenEndPosition.offset);
995 recordPauseLocation(context.breakpointLocation(body));
996 context.appendStatement(sourceElements, body);
997
998 return sourceElements;
999}
1000
1001template <typename LexerType>
1002template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::tryParseDestructuringPatternExpression(TreeBuilder& context, AssignmentContext bindingContext)
1003{
1004 return parseDestructuringPattern(context, DestructuringKind::DestructureToExpressions, ExportType::NotExported, nullptr, nullptr, bindingContext);
1005}
1006
1007template <typename LexerType>
1008template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseBindingOrAssignmentElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
1009{
1010 if (kind == DestructuringKind::DestructureToExpressions)
1011 return parseAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
1012 return parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
1013}
1014
1015template <typename LexerType>
1016template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseObjectRestAssignmentElement(TreeBuilder& context)
1017{
1018 JSTextPosition startPosition = tokenStartPosition();
1019 auto element = parseMemberExpression(context);
1020
1021 if (!element || !context.isAssignmentLocation(element)) {
1022 reclassifyExpressionError(ErrorIndicatesPattern, ErrorIndicatesNothing);
1023 semanticFail("Invalid destructuring assignment target");
1024 }
1025
1026 if (strictMode() && m_parserState.lastIdentifier && context.isResolve(element)) {
1027 bool isEvalOrArguments = m_vm->propertyNames->eval == *m_parserState.lastIdentifier || m_vm->propertyNames->arguments == *m_parserState.lastIdentifier;
1028 if (isEvalOrArguments && strictMode())
1029 reclassifyExpressionError(ErrorIndicatesPattern, ErrorIndicatesNothing);
1030 failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", m_parserState.lastIdentifier->impl(), "' in strict mode");
1031 }
1032
1033 return createAssignmentElement(context, element, startPosition, lastTokenEndPosition());
1034}
1035
1036template <typename LexerType>
1037template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseAssignmentElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
1038{
1039 TreeDestructuringPattern assignmentTarget = 0;
1040
1041 if (match(OPENBRACE) || match(OPENBRACKET)) {
1042 SavePoint savePoint = createSavePoint();
1043 assignmentTarget = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
1044 if (assignmentTarget && !match(DOT) && !match(OPENBRACKET) && !match(OPENPAREN) && !match(BACKQUOTE))
1045 return assignmentTarget;
1046 restoreSavePoint(savePoint);
1047 }
1048
1049 JSTextPosition startPosition = tokenStartPosition();
1050 auto element = parseMemberExpression(context);
1051
1052 semanticFailIfFalse(element && context.isAssignmentLocation(element), "Invalid destructuring assignment target");
1053
1054 if (strictMode() && m_parserState.lastIdentifier && context.isResolve(element)) {
1055 bool isEvalOrArguments = m_vm->propertyNames->eval == *m_parserState.lastIdentifier || m_vm->propertyNames->arguments == *m_parserState.lastIdentifier;
1056 failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", m_parserState.lastIdentifier->impl(), "' in strict mode");
1057 }
1058
1059 return createAssignmentElement(context, element, startPosition, lastTokenEndPosition());
1060}
1061
1062static const char* destructuringKindToVariableKindName(DestructuringKind kind)
1063{
1064 switch (kind) {
1065 case DestructuringKind::DestructureToLet:
1066 case DestructuringKind::DestructureToConst:
1067 return "lexical variable name";
1068 case DestructuringKind::DestructureToVariables:
1069 return "variable name";
1070 case DestructuringKind::DestructureToParameters:
1071 return "parameter name";
1072 case DestructuringKind::DestructureToCatchParameters:
1073 return "catch parameter name";
1074 case DestructuringKind::DestructureToExpressions:
1075 return "expression name";
1076 }
1077 RELEASE_ASSERT_NOT_REACHED();
1078 return "invalid";
1079}
1080
1081template <typename LexerType>
1082template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseObjectRestElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, AssignmentContext bindingContext)
1083{
1084 ASSERT(kind != DestructuringKind::DestructureToExpressions);
1085 failIfStackOverflow();
1086 TreeDestructuringPattern pattern;
1087
1088 if (!matchSpecIdentifier()) {
1089 semanticFailureDueToKeyword(destructuringKindToVariableKindName(kind));
1090 failWithMessage("Expected a binding element");
1091 }
1092 failIfTrue(match(LET) && (kind == DestructuringKind::DestructureToLet || kind == DestructuringKind::DestructureToConst), "Cannot use 'let' as an identifier name for a LexicalDeclaration");
1093 semanticFailIfTrue(isDisallowedIdentifierAwait(m_token), "Cannot use 'await' as a ", destructuringKindToVariableKindName(kind), " ", disallowedIdentifierAwaitReason());
1094 pattern = createBindingPattern(context, kind, exportType, *m_token.m_data.ident, m_token, bindingContext, duplicateIdentifier);
1095 next();
1096 return pattern;
1097}
1098
1099template <typename LexerType>
1100template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseObjectRestBindingOrAssignmentElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, AssignmentContext bindingContext)
1101{
1102 if (kind == DestructuringKind::DestructureToExpressions)
1103 return parseObjectRestAssignmentElement(context);
1104 return parseObjectRestElement(context, kind, exportType, duplicateIdentifier, bindingContext);
1105}
1106
1107template <typename LexerType>
1108template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseDestructuringPattern(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
1109{
1110 failIfStackOverflow();
1111 int nonLHSCount = m_parserState.nonLHSCount;
1112 TreeDestructuringPattern pattern;
1113 switch (m_token.m_type) {
1114 case OPENBRACKET: {
1115 JSTextPosition divotStart = tokenStartPosition();
1116 auto arrayPattern = context.createArrayPattern(m_token.m_location);
1117 next();
1118
1119 if (hasDestructuringPattern)
1120 *hasDestructuringPattern = true;
1121
1122 bool restElementWasFound = false;
1123
1124 do {
1125 while (match(COMMA)) {
1126 context.appendArrayPatternSkipEntry(arrayPattern, m_token.m_location);
1127 next();
1128 }
1129 propagateError();
1130
1131 if (match(CLOSEBRACKET))
1132 break;
1133
1134 if (UNLIKELY(match(DOTDOTDOT))) {
1135 JSTokenLocation location = m_token.m_location;
1136 next();
1137 auto innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
1138 if (kind == DestructuringKind::DestructureToExpressions && !innerPattern)
1139 return 0;
1140 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
1141 context.appendArrayPatternRestEntry(arrayPattern, location, innerPattern);
1142 restElementWasFound = true;
1143 break;
1144 }
1145
1146 JSTokenLocation location = m_token.m_location;
1147 auto innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
1148 if (kind == DestructuringKind::DestructureToExpressions && !innerPattern)
1149 return 0;
1150 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
1151 TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
1152 propagateError();
1153 context.appendArrayPatternEntry(arrayPattern, location, innerPattern, defaultValue);
1154 } while (consume(COMMA));
1155
1156 consumeOrFail(CLOSEBRACKET, restElementWasFound ? "Expected a closing ']' following a rest element destructuring pattern" : "Expected either a closing ']' or a ',' following an element destructuring pattern");
1157 context.finishArrayPattern(arrayPattern, divotStart, divotStart, lastTokenEndPosition());
1158 pattern = arrayPattern;
1159 break;
1160 }
1161 case OPENBRACE: {
1162 auto objectPattern = context.createObjectPattern(m_token.m_location);
1163 next();
1164
1165 if (hasDestructuringPattern)
1166 *hasDestructuringPattern = true;
1167
1168 bool restElementWasFound = false;
1169
1170 do {
1171 bool wasString = false;
1172
1173 if (match(CLOSEBRACE))
1174 break;
1175
1176 if (match(DOTDOTDOT)) {
1177 JSTokenLocation location = m_token.m_location;
1178 next();
1179 auto innerPattern = parseObjectRestBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, bindingContext);
1180 propagateError();
1181 if (!innerPattern)
1182 return 0;
1183 context.appendObjectPatternRestEntry(*m_vm, objectPattern, location, innerPattern);
1184 restElementWasFound = true;
1185 context.setContainsObjectRestElement(objectPattern, restElementWasFound);
1186 break;
1187 }
1188
1189 const Identifier* propertyName = nullptr;
1190 TreeExpression propertyExpression = 0;
1191 TreeDestructuringPattern innerPattern = 0;
1192 JSTokenLocation location = m_token.m_location;
1193 if (matchSpecIdentifier()) {
1194 failIfTrue(match(LET) && (kind == DestructuringKind::DestructureToLet || kind == DestructuringKind::DestructureToConst), "Cannot use 'let' as an identifier name for a LexicalDeclaration");
1195 propertyName = m_token.m_data.ident;
1196 JSToken identifierToken = m_token;
1197 next();
1198 if (consume(COLON))
1199 innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
1200 else {
1201 if (kind == DestructuringKind::DestructureToExpressions) {
1202 bool isEvalOrArguments = m_vm->propertyNames->eval == *propertyName || m_vm->propertyNames->arguments == *propertyName;
1203 if (isEvalOrArguments && strictMode())
1204 reclassifyExpressionError(ErrorIndicatesPattern, ErrorIndicatesNothing);
1205 failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", propertyName->impl(), "' in strict mode");
1206 }
1207 semanticFailIfTrue(isDisallowedIdentifierAwait(identifierToken), "Cannot use 'await' as a ", destructuringKindToVariableKindName(kind), " ", disallowedIdentifierAwaitReason());
1208 innerPattern = createBindingPattern(context, kind, exportType, *propertyName, identifierToken, bindingContext, duplicateIdentifier);
1209 }
1210 } else {
1211 JSTokenType tokenType = m_token.m_type;
1212 switch (m_token.m_type) {
1213 case DOUBLE:
1214 case INTEGER:
1215 propertyName = &m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), m_token.m_data.doubleValue);
1216 break;
1217 case STRING:
1218 propertyName = m_token.m_data.ident;
1219 wasString = true;
1220 break;
1221 case OPENBRACKET:
1222 next();
1223 propertyExpression = parseAssignmentExpression(context);
1224 failIfFalse(propertyExpression, "Cannot parse computed property name");
1225 matchOrFail(CLOSEBRACKET, "Expected ']' to end end a computed property name");
1226 break;
1227 default:
1228 if (m_token.m_type != RESERVED && m_token.m_type != RESERVED_IF_STRICT && !(m_token.m_type & KeywordTokenFlag)) {
1229 if (kind == DestructuringKind::DestructureToExpressions)
1230 return 0;
1231 failWithMessage("Expected a property name");
1232 }
1233 propertyName = m_token.m_data.ident;
1234 break;
1235 }
1236 next();
1237 if (!consume(COLON)) {
1238 if (kind == DestructuringKind::DestructureToExpressions)
1239 return 0;
1240 semanticFailIfTrue(tokenType == RESERVED, "Cannot use abbreviated destructuring syntax for reserved name '", propertyName->impl(), "'");
1241 semanticFailIfTrue(tokenType == RESERVED_IF_STRICT, "Cannot use abbreviated destructuring syntax for reserved name '", propertyName->impl(), "' in strict mode");
1242 semanticFailIfTrue(tokenType & KeywordTokenFlag, "Cannot use abbreviated destructuring syntax for keyword '", propertyName->impl(), "'");
1243
1244 failWithMessage("Expected a ':' prior to a named destructuring property");
1245 }
1246 innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
1247 }
1248 if (kind == DestructuringKind::DestructureToExpressions && !innerPattern)
1249 return 0;
1250 failIfFalse(innerPattern, "Cannot parse this destructuring pattern");
1251 TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
1252 propagateError();
1253 if (propertyExpression) {
1254 context.appendObjectPatternEntry(*m_vm, objectPattern, location, propertyExpression, innerPattern, defaultValue);
1255 context.setContainsComputedProperty(objectPattern, true);
1256 } else {
1257 ASSERT(propertyName);
1258 context.appendObjectPatternEntry(objectPattern, location, wasString, *propertyName, innerPattern, defaultValue);
1259 }
1260 } while (consume(COMMA));
1261
1262 if (kind == DestructuringKind::DestructureToExpressions && !match(CLOSEBRACE))
1263 return 0;
1264 consumeOrFail(CLOSEBRACE, restElementWasFound ? "Expected a closing '}' following a rest element destructuring pattern" : "Expected either a closing '}' or an ',' after a property destructuring pattern");
1265 pattern = objectPattern;
1266 break;
1267 }
1268
1269 default: {
1270 if (!matchSpecIdentifier()) {
1271 if (kind == DestructuringKind::DestructureToExpressions)
1272 return 0;
1273 semanticFailureDueToKeyword(destructuringKindToVariableKindName(kind));
1274 failWithMessage("Expected a parameter pattern or a ')' in parameter list");
1275 }
1276 failIfTrue(match(LET) && (kind == DestructuringKind::DestructureToLet || kind == DestructuringKind::DestructureToConst), "Cannot use 'let' as an identifier name for a LexicalDeclaration");
1277 semanticFailIfTrue(isDisallowedIdentifierAwait(m_token), "Cannot use 'await' as a ", destructuringKindToVariableKindName(kind), " ", disallowedIdentifierAwaitReason());
1278 pattern = createBindingPattern(context, kind, exportType, *m_token.m_data.ident, m_token, bindingContext, duplicateIdentifier);
1279 next();
1280 break;
1281 }
1282 }
1283 m_parserState.nonLHSCount = nonLHSCount;
1284 return pattern;
1285}
1286
1287template <typename LexerType>
1288template <class TreeBuilder> TreeExpression Parser<LexerType>::parseDefaultValueForDestructuringPattern(TreeBuilder& context)
1289{
1290 if (!match(EQUAL))
1291 return 0;
1292
1293 next(TreeBuilder::DontBuildStrings); // consume '='
1294 return parseAssignmentExpression(context);
1295}
1296
1297template <typename LexerType>
1298template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement(TreeBuilder& context)
1299{
1300 ASSERT(match(FOR));
1301 JSTokenLocation location(tokenLocation());
1302 int startLine = tokenLine();
1303 bool isAwaitFor = false;
1304 next();
1305
1306 DepthManager statementDepth(&m_statementDepth);
1307 m_statementDepth++;
1308
1309 if (match(AWAIT)) {
1310 semanticFailIfFalse(currentScope()->isAsyncFunction(), "for-await-of can't be used only in async function or async generator.");
1311 isAwaitFor = true;
1312 next();
1313 }
1314
1315 handleProductionOrFail(OPENPAREN, "(", "start", "for-loop header");
1316 int nonLHSCount = m_parserState.nonLHSCount;
1317 int declarations = 0;
1318 JSTokenLocation declLocation(tokenLocation());
1319 JSTextPosition declsStart;
1320 JSTextPosition declsEnd;
1321 TreeExpression decls = 0;
1322 TreeDestructuringPattern pattern = 0;
1323 bool isVarDeclaraton = match(VAR);
1324 bool isLetDeclaration = match(LET);
1325 bool isConstDeclaration = match(CONSTTOKEN);
1326 bool forLoopConstDoesNotHaveInitializer = false;
1327
1328 VariableEnvironment dummySet;
1329 VariableEnvironment* lexicalVariables = nullptr;
1330 AutoCleanupLexicalScope lexicalScope;
1331
1332 auto gatherLexicalVariablesIfNecessary = [&] {
1333 if (isLetDeclaration || isConstDeclaration) {
1334 ScopeRef scope = lexicalScope.scope();
1335 lexicalVariables = &scope->finalizeLexicalEnvironment();
1336 } else
1337 lexicalVariables = &dummySet;
1338 };
1339
1340 auto popLexicalScopeIfNecessary = [&] {
1341 if (isLetDeclaration || isConstDeclaration)
1342 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1343 };
1344
1345 if (isVarDeclaraton || isLetDeclaration || isConstDeclaration) {
1346 /*
1347 for (var/let/const IDENT in/of expression) statement
1348 for (var/let/const varDeclarationList; expressionOpt; expressionOpt)
1349 */
1350 if (isLetDeclaration || isConstDeclaration) {
1351 ScopeRef newScope = pushScope();
1352 newScope->setIsLexicalScope();
1353 newScope->preventVarDeclarations();
1354 lexicalScope.setIsValid(newScope, this);
1355 }
1356
1357 TreeDestructuringPattern forInTarget = 0;
1358 TreeExpression forInInitializer = 0;
1359 m_allowsIn = false;
1360 JSTextPosition initStart;
1361 JSTextPosition initEnd;
1362 DeclarationType declarationType;
1363 if (isVarDeclaraton)
1364 declarationType = DeclarationType::VarDeclaration;
1365 else if (isLetDeclaration)
1366 declarationType = DeclarationType::LetDeclaration;
1367 else if (isConstDeclaration)
1368 declarationType = DeclarationType::ConstDeclaration;
1369 else
1370 RELEASE_ASSERT_NOT_REACHED();
1371 decls = parseVariableDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd, ForLoopContext, declarationType, ExportType::NotExported, forLoopConstDoesNotHaveInitializer);
1372 m_allowsIn = true;
1373 propagateError();
1374
1375 // Remainder of a standard for loop is handled identically
1376 if (match(SEMICOLON))
1377 goto standardForLoop;
1378
1379 failIfFalse(declarations == 1, "can only declare a single variable in an enumeration");
1380
1381 // Handle for-in with var declaration
1382 JSTextPosition inLocation = tokenStartPosition();
1383 bool isOfEnumeration = false;
1384 if (!match(INTOKEN)) {
1385 failIfFalse(matchContextualKeyword(m_vm->propertyNames->of), "Expected either 'in' or 'of' in enumeration syntax");
1386 isOfEnumeration = true;
1387 next();
1388 } else {
1389 failIfFalse(!isAwaitFor, "Expected 'of' in for-await syntax");
1390 next();
1391 }
1392
1393 bool hasAnyAssignments = !!forInInitializer;
1394 if (hasAnyAssignments) {
1395 if (isOfEnumeration)
1396 internalFailWithMessage(false, "Cannot assign to the loop variable inside a for-of loop header");
1397 if (strictMode() || (isLetDeclaration || isConstDeclaration) || !context.isBindingNode(forInTarget))
1398 internalFailWithMessage(false, "Cannot assign to the loop variable inside a for-in loop header");
1399 }
1400 TreeExpression expr = parseExpression(context);
1401 failIfFalse(expr, "Expected expression to enumerate");
1402 recordPauseLocation(context.breakpointLocation(expr));
1403 JSTextPosition exprEnd = lastTokenEndPosition();
1404
1405 int endLine = tokenLine();
1406
1407 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
1408
1409 const Identifier* unused = 0;
1410 startLoop();
1411 TreeStatement statement = parseStatement(context, unused);
1412 endLoop();
1413 failIfFalse(statement, "Expected statement as body of for-", isOfEnumeration ? "of" : "in", " statement");
1414 gatherLexicalVariablesIfNecessary();
1415 TreeStatement result;
1416 if (isOfEnumeration)
1417 result = context.createForOfLoop(isAwaitFor, location, forInTarget, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
1418 else {
1419 ASSERT(!isAwaitFor);
1420 if (isVarDeclaraton && forInInitializer)
1421 result = context.createForInLoop(location, decls, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
1422 else
1423 result = context.createForInLoop(location, forInTarget, expr, statement, declLocation, declsStart, inLocation, exprEnd, startLine, endLine, *lexicalVariables);
1424 }
1425 popLexicalScopeIfNecessary();
1426 return result;
1427 }
1428
1429 if (!match(SEMICOLON)) {
1430 if (match(OPENBRACE) || match(OPENBRACKET)) {
1431 SavePoint savePoint = createSavePoint();
1432 declsStart = tokenStartPosition();
1433 pattern = tryParseDestructuringPatternExpression(context, AssignmentContext::DeclarationStatement);
1434 declsEnd = lastTokenEndPosition();
1435 if (pattern && (match(INTOKEN) || matchContextualKeyword(m_vm->propertyNames->of)))
1436 goto enumerationLoop;
1437 pattern = TreeDestructuringPattern(0);
1438 restoreSavePoint(savePoint);
1439 }
1440 m_allowsIn = false;
1441 declsStart = tokenStartPosition();
1442 decls = parseExpression(context);
1443 declsEnd = lastTokenEndPosition();
1444 m_allowsIn = true;
1445 failIfFalse(decls, "Cannot parse for loop declarations");
1446 recordPauseLocation(context.breakpointLocation(decls));
1447 }
1448
1449 if (match(SEMICOLON)) {
1450 standardForLoop:
1451 failIfFalse(!isAwaitFor, "Unexpected a ';' in for-await-of header");
1452 // Standard for loop
1453 if (decls)
1454 recordPauseLocation(context.breakpointLocation(decls));
1455 next();
1456 TreeExpression condition = 0;
1457 failIfTrue(forLoopConstDoesNotHaveInitializer && isConstDeclaration, "const variables in for loops must have initializers");
1458
1459 if (!match(SEMICOLON)) {
1460 condition = parseExpression(context);
1461 failIfFalse(condition, "Cannot parse for loop condition expression");
1462 recordPauseLocation(context.breakpointLocation(condition));
1463 }
1464 consumeOrFail(SEMICOLON, "Expected a ';' after the for loop condition expression");
1465
1466 TreeExpression increment = 0;
1467 if (!match(CLOSEPAREN)) {
1468 increment = parseExpression(context);
1469 failIfFalse(increment, "Cannot parse for loop iteration expression");
1470 recordPauseLocation(context.breakpointLocation(increment));
1471 }
1472 int endLine = tokenLine();
1473 handleProductionOrFail(CLOSEPAREN, ")", "end", "for-loop header");
1474 const Identifier* unused = 0;
1475 startLoop();
1476 TreeStatement statement = parseStatement(context, unused);
1477 endLoop();
1478 failIfFalse(statement, "Expected a statement as the body of a for loop");
1479 gatherLexicalVariablesIfNecessary();
1480 TreeStatement result = context.createForLoop(location, decls, condition, increment, statement, startLine, endLine, *lexicalVariables);
1481 popLexicalScopeIfNecessary();
1482 return result;
1483 }
1484
1485 // For-in and For-of loop
1486enumerationLoop:
1487 failIfFalse(nonLHSCount == m_parserState.nonLHSCount, "Expected a reference on the left hand side of an enumeration statement");
1488 bool isOfEnumeration = false;
1489 if (!match(INTOKEN)) {
1490 failIfFalse(matchContextualKeyword(m_vm->propertyNames->of), "Expected either 'in' or 'of' in enumeration syntax");
1491 isOfEnumeration = true;
1492 next();
1493 } else {
1494 failIfFalse(!isAwaitFor, "Expected 'of' in for-await syntax");
1495 next();
1496 }
1497
1498 TreeExpression expr = parseExpression(context);
1499 failIfFalse(expr, "Cannot parse subject for-", isOfEnumeration ? "of" : "in", " statement");
1500 recordPauseLocation(context.breakpointLocation(expr));
1501 JSTextPosition exprEnd = lastTokenEndPosition();
1502 int endLine = tokenLine();
1503
1504 handleProductionOrFail(CLOSEPAREN, ")", "end", (isOfEnumeration ? "for-of header" : "for-in header"));
1505 const Identifier* unused = 0;
1506 startLoop();
1507 TreeStatement statement = parseStatement(context, unused);
1508 endLoop();
1509 failIfFalse(statement, "Expected a statement as the body of a for-", isOfEnumeration ? "of" : "in", "loop");
1510 gatherLexicalVariablesIfNecessary();
1511 TreeStatement result;
1512 if (pattern) {
1513 ASSERT(!decls);
1514 if (isOfEnumeration)
1515 result = context.createForOfLoop(isAwaitFor, location, pattern, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1516 else {
1517 ASSERT(!isAwaitFor);
1518 result = context.createForInLoop(location, pattern, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1519 }
1520
1521 popLexicalScopeIfNecessary();
1522 return result;
1523 }
1524 if (isOfEnumeration)
1525 result = context.createForOfLoop(isAwaitFor, location, decls, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1526 else {
1527 ASSERT(!isAwaitFor);
1528 result = context.createForInLoop(location, decls, expr, statement, declLocation, declsStart, declsEnd, exprEnd, startLine, endLine, *lexicalVariables);
1529 }
1530 popLexicalScopeIfNecessary();
1531 return result;
1532}
1533
1534template <typename LexerType>
1535template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatement(TreeBuilder& context)
1536{
1537 ASSERT(match(BREAK));
1538 JSTokenLocation location(tokenLocation());
1539 JSTextPosition start = tokenStartPosition();
1540 JSTextPosition end = tokenEndPosition();
1541 next();
1542
1543 if (autoSemiColon()) {
1544 semanticFailIfFalse(breakIsValid(), "'break' is only valid inside a switch or loop statement");
1545 return context.createBreakStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
1546 }
1547 failIfFalse(matchSpecIdentifier(), "Expected an identifier as the target for a break statement");
1548 const Identifier* ident = m_token.m_data.ident;
1549 semanticFailIfFalse(getLabel(ident), "Cannot use the undeclared label '", ident->impl(), "'");
1550 end = tokenEndPosition();
1551 next();
1552 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted break statement");
1553 return context.createBreakStatement(location, ident, start, end);
1554}
1555
1556template <typename LexerType>
1557template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueStatement(TreeBuilder& context)
1558{
1559 ASSERT(match(CONTINUE));
1560 JSTokenLocation location(tokenLocation());
1561 JSTextPosition start = tokenStartPosition();
1562 JSTextPosition end = tokenEndPosition();
1563 next();
1564
1565 if (autoSemiColon()) {
1566 semanticFailIfFalse(continueIsValid(), "'continue' is only valid inside a loop statement");
1567 return context.createContinueStatement(location, &m_vm->propertyNames->nullIdentifier, start, end);
1568 }
1569 failIfFalse(matchSpecIdentifier(), "Expected an identifier as the target for a continue statement");
1570 const Identifier* ident = m_token.m_data.ident;
1571 ScopeLabelInfo* label = getLabel(ident);
1572 semanticFailIfFalse(label, "Cannot use the undeclared label '", ident->impl(), "'");
1573 semanticFailIfFalse(label->isLoop, "Cannot continue to the label '", ident->impl(), "' as it is not targeting a loop");
1574 end = tokenEndPosition();
1575 next();
1576 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted continue statement");
1577 return context.createContinueStatement(location, ident, start, end);
1578}
1579
1580template <typename LexerType>
1581template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStatement(TreeBuilder& context)
1582{
1583 ASSERT(match(RETURN));
1584 JSTokenLocation location(tokenLocation());
1585 semanticFailIfFalse(currentScope()->isFunction(), "Return statements are only valid inside functions");
1586 JSTextPosition start = tokenStartPosition();
1587 JSTextPosition end = tokenEndPosition();
1588 next();
1589 // We do the auto semicolon check before attempting to parse expression
1590 // as we need to ensure the a line break after the return correctly terminates
1591 // the statement
1592 if (match(SEMICOLON))
1593 end = tokenEndPosition();
1594
1595 if (autoSemiColon())
1596 return context.createReturnStatement(location, 0, start, end);
1597 TreeExpression expr = parseExpression(context);
1598 failIfFalse(expr, "Cannot parse the return expression");
1599 end = lastTokenEndPosition();
1600 if (match(SEMICOLON))
1601 end = tokenEndPosition();
1602 if (!autoSemiColon())
1603 failWithMessage("Expected a ';' following a return statement");
1604 return context.createReturnStatement(location, expr, start, end);
1605}
1606
1607template <typename LexerType>
1608template <class TreeBuilder> TreeStatement Parser<LexerType>::parseThrowStatement(TreeBuilder& context)
1609{
1610 ASSERT(match(THROW));
1611 JSTokenLocation location(tokenLocation());
1612 JSTextPosition start = tokenStartPosition();
1613 next();
1614 failIfTrue(match(SEMICOLON), "Expected expression after 'throw'");
1615 semanticFailIfTrue(autoSemiColon(), "Cannot have a newline after 'throw'");
1616
1617 TreeExpression expr = parseExpression(context);
1618 failIfFalse(expr, "Cannot parse expression for throw statement");
1619 JSTextPosition end = lastTokenEndPosition();
1620 failIfFalse(autoSemiColon(), "Expected a ';' after a throw statement");
1621
1622 return context.createThrowStatement(location, expr, start, end);
1623}
1624
1625template <typename LexerType>
1626template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement(TreeBuilder& context)
1627{
1628 ASSERT(match(WITH));
1629 JSTokenLocation location(tokenLocation());
1630 semanticFailIfTrue(strictMode(), "'with' statements are not valid in strict mode");
1631 currentScope()->setNeedsFullActivation();
1632 int startLine = tokenLine();
1633 next();
1634
1635 handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'with' statement");
1636 int start = tokenStart();
1637 TreeExpression expr = parseExpression(context);
1638 failIfFalse(expr, "Cannot parse 'with' subject expression");
1639 recordPauseLocation(context.breakpointLocation(expr));
1640 JSTextPosition end = lastTokenEndPosition();
1641 int endLine = tokenLine();
1642 handleProductionOrFail(CLOSEPAREN, ")", "start", "subject of a 'with' statement");
1643 const Identifier* unused = 0;
1644 TreeStatement statement = parseStatement(context, unused);
1645 failIfFalse(statement, "A 'with' statement must have a body");
1646
1647 return context.createWithStatement(location, expr, statement, start, end, startLine, endLine);
1648}
1649
1650template <typename LexerType>
1651template <class TreeBuilder> TreeStatement Parser<LexerType>::parseSwitchStatement(TreeBuilder& context)
1652{
1653 ASSERT(match(SWITCH));
1654 JSTokenLocation location(tokenLocation());
1655 int startLine = tokenLine();
1656 next();
1657 handleProductionOrFail(OPENPAREN, "(", "start", "subject of a 'switch'");
1658 TreeExpression expr = parseExpression(context);
1659 failIfFalse(expr, "Cannot parse switch subject expression");
1660 recordPauseLocation(context.breakpointLocation(expr));
1661 int endLine = tokenLine();
1662
1663 handleProductionOrFail(CLOSEPAREN, ")", "end", "subject of a 'switch'");
1664 handleProductionOrFail(OPENBRACE, "{", "start", "body of a 'switch'");
1665 AutoPopScopeRef lexicalScope(this, pushScope());
1666 lexicalScope->setIsLexicalScope();
1667 lexicalScope->preventVarDeclarations();
1668 startSwitch();
1669 TreeClauseList firstClauses = parseSwitchClauses(context);
1670 propagateError();
1671
1672 TreeClause defaultClause = parseSwitchDefaultClause(context);
1673 propagateError();
1674
1675 TreeClauseList secondClauses = parseSwitchClauses(context);
1676 propagateError();
1677 endSwitch();
1678 handleProductionOrFail(CLOSEBRACE, "}", "end", "body of a 'switch'");
1679
1680 TreeStatement result = context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine, lexicalScope->finalizeLexicalEnvironment(), lexicalScope->takeFunctionDeclarations());
1681 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1682 return result;
1683}
1684
1685template <typename LexerType>
1686template <class TreeBuilder> TreeClauseList Parser<LexerType>::parseSwitchClauses(TreeBuilder& context)
1687{
1688 if (!match(CASE))
1689 return 0;
1690 unsigned startOffset = tokenStart();
1691 next();
1692 TreeExpression condition = parseExpression(context);
1693 failIfFalse(condition, "Cannot parse switch clause");
1694 consumeOrFail(COLON, "Expected a ':' after switch clause expression");
1695 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1696 failIfFalse(statements, "Cannot parse the body of a switch clause");
1697 TreeClause clause = context.createClause(condition, statements);
1698 context.setStartOffset(clause, startOffset);
1699 TreeClauseList clauseList = context.createClauseList(clause);
1700 TreeClauseList tail = clauseList;
1701
1702 while (match(CASE)) {
1703 startOffset = tokenStart();
1704 next();
1705 TreeExpression condition = parseExpression(context);
1706 failIfFalse(condition, "Cannot parse switch case expression");
1707 consumeOrFail(COLON, "Expected a ':' after switch clause expression");
1708 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1709 failIfFalse(statements, "Cannot parse the body of a switch clause");
1710 clause = context.createClause(condition, statements);
1711 context.setStartOffset(clause, startOffset);
1712 tail = context.createClauseList(tail, clause);
1713 }
1714 return clauseList;
1715}
1716
1717template <typename LexerType>
1718template <class TreeBuilder> TreeClause Parser<LexerType>::parseSwitchDefaultClause(TreeBuilder& context)
1719{
1720 if (!match(DEFAULT))
1721 return 0;
1722 unsigned startOffset = tokenStart();
1723 next();
1724 consumeOrFail(COLON, "Expected a ':' after switch default clause");
1725 TreeSourceElements statements = parseSourceElements(context, DontCheckForStrictMode);
1726 failIfFalse(statements, "Cannot parse the body of a switch default clause");
1727 TreeClause result = context.createClause(0, statements);
1728 context.setStartOffset(result, startOffset);
1729 return result;
1730}
1731
1732template <typename LexerType>
1733template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(TreeBuilder& context)
1734{
1735 ASSERT(match(TRY));
1736 JSTokenLocation location(tokenLocation());
1737 TreeStatement tryBlock = 0;
1738 TreeDestructuringPattern catchPattern = 0;
1739 TreeStatement catchBlock = 0;
1740 TreeStatement finallyBlock = 0;
1741 int firstLine = tokenLine();
1742 next();
1743 matchOrFail(OPENBRACE, "Expected a block statement as body of a try statement");
1744
1745 tryBlock = parseBlockStatement(context);
1746 failIfFalse(tryBlock, "Cannot parse the body of try block");
1747 int lastLine = m_lastTokenEndPosition.line;
1748 VariableEnvironment catchEnvironment;
1749 if (match(CATCH)) {
1750 next();
1751
1752 if (match(OPENBRACE)) {
1753 catchBlock = parseBlockStatement(context);
1754 failIfFalse(catchBlock, "Unable to parse 'catch' block");
1755 } else {
1756 handleProductionOrFail(OPENPAREN, "(", "start", "'catch' target");
1757 AutoPopScopeRef catchScope(this, pushScope());
1758 catchScope->setIsLexicalScope();
1759 catchScope->preventVarDeclarations();
1760 const Identifier* ident = nullptr;
1761 if (matchSpecIdentifier()) {
1762 catchScope->setIsSimpleCatchParameterScope();
1763 ident = m_token.m_data.ident;
1764 catchPattern = context.createBindingLocation(m_token.m_location, *ident, m_token.m_startPosition, m_token.m_endPosition, AssignmentContext::DeclarationStatement);
1765 next();
1766 failIfTrueIfStrict(catchScope->declareLexicalVariable(ident, false) & DeclarationResult::InvalidStrictMode, "Cannot declare a catch variable named '", ident->impl(), "' in strict mode");
1767 } else {
1768 catchPattern = parseDestructuringPattern(context, DestructuringKind::DestructureToCatchParameters, ExportType::NotExported);
1769 failIfFalse(catchPattern, "Cannot parse this destructuring pattern");
1770 }
1771 handleProductionOrFail(CLOSEPAREN, ")", "end", "'catch' target");
1772 matchOrFail(OPENBRACE, "Expected exception handler to be a block statement");
1773 catchBlock = parseBlockStatement(context);
1774 failIfFalse(catchBlock, "Unable to parse 'catch' block");
1775 catchEnvironment = catchScope->finalizeLexicalEnvironment();
1776 RELEASE_ASSERT(!ident || (catchEnvironment.size() == 1 && catchEnvironment.contains(ident->impl())));
1777 popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo);
1778 }
1779 }
1780
1781 if (match(FINALLY)) {
1782 next();
1783 matchOrFail(OPENBRACE, "Expected block statement for finally body");
1784 finallyBlock = parseBlockStatement(context);
1785 failIfFalse(finallyBlock, "Cannot parse finally body");
1786 }
1787 failIfFalse(catchBlock || finallyBlock, "Try statements must have at least a catch or finally block");
1788 return context.createTryStatement(location, tryBlock, catchPattern, catchBlock, finallyBlock, firstLine, lastLine, catchEnvironment);
1789}
1790
1791template <typename LexerType>
1792template <class TreeBuilder> TreeStatement Parser<LexerType>::parseDebuggerStatement(TreeBuilder& context)
1793{
1794 ASSERT(match(DEBUGGER));
1795 JSTokenLocation location(tokenLocation());
1796 int startLine = tokenLine();
1797 int endLine = startLine;
1798 next();
1799 if (match(SEMICOLON))
1800 startLine = tokenLine();
1801 failIfFalse(autoSemiColon(), "Debugger keyword must be followed by a ';'");
1802 return context.createDebugger(location, startLine, endLine);
1803}
1804
1805template <typename LexerType>
1806template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBlockStatement(TreeBuilder& context)
1807{
1808 ASSERT(match(OPENBRACE));
1809
1810 // We should treat the first block statement of the function (the body of the function) as the lexical
1811 // scope of the function itself, and not the lexical scope of a 'block' statement within the function.
1812 AutoCleanupLexicalScope lexicalScope;
1813 bool shouldPushLexicalScope = m_statementDepth > 0;
1814 if (shouldPushLexicalScope) {
1815 ScopeRef newScope = pushScope();
1816 newScope->setIsLexicalScope();
1817 newScope->preventVarDeclarations();
1818 lexicalScope.setIsValid(newScope, this);
1819 }
1820 JSTokenLocation location(tokenLocation());
1821 int startOffset = m_token.m_data.offset;
1822 int start = tokenLine();
1823 VariableEnvironment emptyEnvironment;
1824 DeclarationStacks::FunctionStack emptyFunctionStack;
1825 next();
1826 if (match(CLOSEBRACE)) {
1827 int endOffset = m_token.m_data.offset;
1828 next();
1829 TreeStatement result = context.createBlockStatement(location, 0, start, m_lastTokenEndPosition.line, shouldPushLexicalScope ? currentScope()->finalizeLexicalEnvironment() : emptyEnvironment, shouldPushLexicalScope ? currentScope()->takeFunctionDeclarations() : WTFMove(emptyFunctionStack));
1830 context.setStartOffset(result, startOffset);
1831 context.setEndOffset(result, endOffset);
1832 if (shouldPushLexicalScope)
1833 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1834 return result;
1835 }
1836 TreeSourceElements subtree = parseSourceElements(context, DontCheckForStrictMode);
1837 failIfFalse(subtree, "Cannot parse the body of the block statement");
1838 matchOrFail(CLOSEBRACE, "Expected a closing '}' at the end of a block statement");
1839 int endOffset = m_token.m_data.offset;
1840 next();
1841 TreeStatement result = context.createBlockStatement(location, subtree, start, m_lastTokenEndPosition.line, shouldPushLexicalScope ? currentScope()->finalizeLexicalEnvironment() : emptyEnvironment, shouldPushLexicalScope ? currentScope()->takeFunctionDeclarations() : WTFMove(emptyFunctionStack));
1842 context.setStartOffset(result, startOffset);
1843 context.setEndOffset(result, endOffset);
1844 if (shouldPushLexicalScope)
1845 popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
1846
1847 return result;
1848}
1849
1850template <typename LexerType>
1851template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(TreeBuilder& context, const Identifier*& directive, unsigned* directiveLiteralLength)
1852{
1853 DepthManager statementDepth(&m_statementDepth);
1854 m_statementDepth++;
1855 int nonTrivialExpressionCount = 0;
1856 failIfStackOverflow();
1857 TreeStatement result = 0;
1858 bool shouldSetEndOffset = true;
1859 bool shouldSetPauseLocation = false;
1860 bool parentAllowsFunctionDeclarationAsStatement = m_immediateParentAllowsFunctionDeclarationInStatement;
1861 m_immediateParentAllowsFunctionDeclarationInStatement = false;
1862
1863 switch (m_token.m_type) {
1864 case OPENBRACE:
1865 result = parseBlockStatement(context);
1866 shouldSetEndOffset = false;
1867 break;
1868 case VAR:
1869 result = parseVariableDeclaration(context, DeclarationType::VarDeclaration);
1870 shouldSetPauseLocation = true;
1871 break;
1872 case FUNCTION: {
1873 const bool isAsync = false;
1874 result = parseFunctionDeclarationStatement(context, isAsync, parentAllowsFunctionDeclarationAsStatement);
1875 break;
1876 }
1877 case SEMICOLON: {
1878 JSTokenLocation location(tokenLocation());
1879 next();
1880 result = context.createEmptyStatement(location);
1881 shouldSetPauseLocation = true;
1882 break;
1883 }
1884 case IF:
1885 result = parseIfStatement(context);
1886 break;
1887 case DO:
1888 result = parseDoWhileStatement(context);
1889 break;
1890 case WHILE:
1891 result = parseWhileStatement(context);
1892 break;
1893 case FOR:
1894 result = parseForStatement(context);
1895 break;
1896 case CONTINUE:
1897 result = parseContinueStatement(context);
1898 shouldSetPauseLocation = true;
1899 break;
1900 case BREAK:
1901 result = parseBreakStatement(context);
1902 shouldSetPauseLocation = true;
1903 break;
1904 case RETURN:
1905 result = parseReturnStatement(context);
1906 shouldSetPauseLocation = true;
1907 break;
1908 case WITH:
1909 result = parseWithStatement(context);
1910 break;
1911 case SWITCH:
1912 result = parseSwitchStatement(context);
1913 break;
1914 case THROW:
1915 result = parseThrowStatement(context);
1916 shouldSetPauseLocation = true;
1917 break;
1918 case TRY:
1919 result = parseTryStatement(context);
1920 break;
1921 case DEBUGGER:
1922 result = parseDebuggerStatement(context);
1923 shouldSetPauseLocation = true;
1924 break;
1925 case EOFTOK:
1926 case CASE:
1927 case CLOSEBRACE:
1928 case DEFAULT:
1929 // These tokens imply the end of a set of source elements
1930 return 0;
1931 case LET: {
1932 if (!strictMode())
1933 goto identcase;
1934 goto defaultCase;
1935 }
1936 case IDENT:
1937 if (UNLIKELY(*m_token.m_data.ident == m_vm->propertyNames->async && !m_token.m_data.escaped)) {
1938 if (maybeParseAsyncFunctionDeclarationStatement(context, result, parentAllowsFunctionDeclarationAsStatement))
1939 break;
1940 }
1941 FALLTHROUGH;
1942 case AWAIT:
1943 case YIELD: {
1944 identcase:
1945 bool allowFunctionDeclarationAsStatement = false;
1946 result = parseExpressionOrLabelStatement(context, allowFunctionDeclarationAsStatement);
1947 shouldSetPauseLocation = !context.shouldSkipPauseLocation(result);
1948 break;
1949 }
1950 case STRING:
1951 directive = m_token.m_data.ident;
1952 if (directiveLiteralLength)
1953 *directiveLiteralLength = m_token.m_location.endOffset - m_token.m_location.startOffset;
1954 nonTrivialExpressionCount = m_parserState.nonTrivialExpressionCount;
1955 FALLTHROUGH;
1956 default:
1957 defaultCase:
1958 TreeStatement exprStatement = parseExpressionStatement(context);
1959 if (directive && nonTrivialExpressionCount != m_parserState.nonTrivialExpressionCount)
1960 directive = nullptr;
1961 result = exprStatement;
1962 shouldSetPauseLocation = true;
1963 break;
1964 }
1965
1966 if (result) {
1967 if (shouldSetEndOffset)
1968 context.setEndOffset(result, m_lastTokenEndPosition.offset);
1969 if (shouldSetPauseLocation)
1970 recordPauseLocation(context.breakpointLocation(result));
1971 }
1972
1973 return result;
1974}
1975
1976template <typename LexerType>
1977template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclarationStatement(TreeBuilder& context, bool isAsync, bool parentAllowsFunctionDeclarationAsStatement)
1978{
1979 semanticFailIfTrue(strictMode(), "Function declarations are only allowed inside blocks or switch statements in strict mode");
1980 failIfFalse(parentAllowsFunctionDeclarationAsStatement, "Function declarations are only allowed inside block statements or at the top level of a program");
1981 if (!currentScope()->isFunction() && !closestParentOrdinaryFunctionNonLexicalScope()->isEvalContext()) {
1982 // We only implement annex B.3.3 if we're in function mode or eval mode. Otherwise, we fall back
1983 // to hoisting behavior.
1984 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=155813
1985 DepthManager statementDepth(&m_statementDepth);
1986 m_statementDepth = 1;
1987 if (isAsync)
1988 return parseAsyncFunctionDeclaration(context);
1989 return parseFunctionDeclaration(context);
1990 }
1991
1992 // Any function declaration that isn't in a block is a syntax error unless it's
1993 // in an if/else statement. If it's in an if/else statement, we will magically
1994 // treat it as if the if/else statement is inside a block statement.
1995 // to the very top like a "var". For example:
1996 // function a() {
1997 // if (cond) function foo() { }
1998 // }
1999 // will be rewritten as:
2000 // function a() {
2001 // if (cond) { function foo() { } }
2002 // }
2003 AutoPopScopeRef blockScope(this, pushScope());
2004 blockScope->setIsLexicalScope();
2005 blockScope->preventVarDeclarations();
2006 JSTokenLocation location(tokenLocation());
2007 int start = tokenLine();
2008
2009 TreeStatement function = 0;
2010 if (!isAsync)
2011 function = parseFunctionDeclaration(context);
2012 else
2013 function = parseAsyncFunctionDeclaration(context);
2014 propagateError();
2015 failIfFalse(function, "Expected valid function statement after 'function' keyword");
2016 TreeSourceElements sourceElements = context.createSourceElements();
2017 context.appendStatement(sourceElements, function);
2018 TreeStatement result = context.createBlockStatement(location, sourceElements, start, m_lastTokenEndPosition.line, currentScope()->finalizeLexicalEnvironment(), currentScope()->takeFunctionDeclarations());
2019 popScope(blockScope, TreeBuilder::NeedsFreeVariableInfo);
2020 return result;
2021}
2022
2023template <typename LexerType>
2024template <class TreeBuilder> bool Parser<LexerType>::maybeParseAsyncFunctionDeclarationStatement(TreeBuilder& context, TreeStatement& result, bool parentAllowsFunctionDeclarationAsStatement)
2025{
2026 ASSERT(matchContextualKeyword(m_vm->propertyNames->async));
2027 SavePoint savePoint = createSavePoint();
2028 next();
2029 if (match(FUNCTION) && !m_lexer->hasLineTerminatorBeforeToken()) {
2030 const bool isAsync = true;
2031 result = parseFunctionDeclarationStatement(context, isAsync, parentAllowsFunctionDeclarationAsStatement);
2032 return true;
2033 }
2034 restoreSavePoint(savePoint);
2035 return false;
2036}
2037
2038template <typename LexerType>
2039template <class TreeBuilder> bool Parser<LexerType>::parseFormalParameters(TreeBuilder& context, TreeFormalParameterList list, bool isArrowFunction, bool isMethod, unsigned& parameterCount)
2040{
2041#define failIfDuplicateIfViolation() \
2042 if (duplicateParameter) {\
2043 semanticFailIfTrue(hasDefaultParameterValues, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with default parameter values");\
2044 semanticFailIfTrue(hasDestructuringPattern, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with destructuring parameters");\
2045 semanticFailIfTrue(isRestParameter, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with a rest parameter");\
2046 semanticFailIfTrue(isArrowFunction, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in an arrow function");\
2047 semanticFailIfTrue(isMethod, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in a method");\
2048 }
2049
2050 bool hasDefaultParameterValues = false;
2051 bool hasDestructuringPattern = false;
2052 bool isRestParameter = false;
2053 const Identifier* duplicateParameter = nullptr;
2054 unsigned restParameterStart = 0;
2055 do {
2056 TreeDestructuringPattern parameter = 0;
2057 TreeExpression defaultValue = 0;
2058
2059 if (UNLIKELY(match(CLOSEPAREN)))
2060 break;
2061
2062 if (match(DOTDOTDOT)) {
2063 next();
2064 semanticFailIfTrue(!m_parserState.allowAwait && match(AWAIT), "Cannot use 'await' as a parameter name in an async function");
2065 TreeDestructuringPattern destructuringPattern = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported, &duplicateParameter, &hasDestructuringPattern);
2066 propagateError();
2067 parameter = context.createRestParameter(destructuringPattern, restParameterStart);
2068 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.
2069 isRestParameter = true;
2070 } else
2071 parameter = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported, &duplicateParameter, &hasDestructuringPattern);
2072 failIfFalse(parameter, "Cannot parse parameter pattern");
2073 if (!isRestParameter) {
2074 defaultValue = parseDefaultValueForDestructuringPattern(context);
2075 if (defaultValue)
2076 hasDefaultParameterValues = true;
2077 }
2078 propagateError();
2079 failIfDuplicateIfViolation();
2080 if (isRestParameter || defaultValue || hasDestructuringPattern)
2081 currentScope()->setHasNonSimpleParameterList();
2082 context.appendParameter(list, parameter, defaultValue);
2083 if (!isRestParameter) {
2084 restParameterStart++;
2085 if (!hasDefaultParameterValues)
2086 parameterCount++;
2087 }
2088 } while (!isRestParameter && consume(COMMA));
2089
2090 return true;
2091#undef failIfDuplicateIfViolation
2092}
2093
2094template <typename LexerType>
2095template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(
2096 TreeBuilder& context, SyntaxChecker& syntaxChecker, const JSTokenLocation& startLocation, int startColumn, int functionKeywordStart, int functionNameStart, int parametersStart,
2097 ConstructorKind constructorKind, SuperBinding superBinding, FunctionBodyType bodyType, unsigned parameterCount, SourceParseMode parseMode)
2098{
2099 bool isArrowFunctionBodyExpression = bodyType == ArrowFunctionBodyExpression;
2100 if (!isArrowFunctionBodyExpression) {
2101 next();
2102 if (match(CLOSEBRACE)) {
2103 unsigned endColumn = tokenColumn();
2104 SuperBinding functionSuperBinding = adjustSuperBindingForBaseConstructor(constructorKind, superBinding, currentScope());
2105 return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, functionSuperBinding, parameterCount, parseMode, isArrowFunctionBodyExpression);
2106 }
2107 }
2108
2109 DepthManager statementDepth(&m_statementDepth);
2110 m_statementDepth = 0;
2111 if (bodyType == ArrowFunctionBodyExpression) {
2112 if (m_debuggerParseData)
2113 failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(context), "Cannot parse body of this arrow function");
2114 else
2115 failIfFalse(parseArrowFunctionSingleExpressionBodySourceElements(syntaxChecker), "Cannot parse body of this arrow function");
2116 } else {
2117 if (m_debuggerParseData)
2118 failIfFalse(parseSourceElements(context, CheckForStrictMode), bodyType == StandardFunctionBodyBlock ? "Cannot parse body of this function" : "Cannot parse body of this arrow function");
2119 else
2120 failIfFalse(parseSourceElements(syntaxChecker, CheckForStrictMode), bodyType == StandardFunctionBodyBlock ? "Cannot parse body of this function" : "Cannot parse body of this arrow function");
2121 }
2122 unsigned endColumn = tokenColumn();
2123 SuperBinding functionSuperBinding = adjustSuperBindingForBaseConstructor(constructorKind, superBinding, currentScope());
2124 return context.createFunctionMetadata(startLocation, tokenLocation(), startColumn, endColumn, functionKeywordStart, functionNameStart, parametersStart, strictMode(), constructorKind, functionSuperBinding, parameterCount, parseMode, isArrowFunctionBodyExpression);
2125}
2126
2127static const char* stringArticleForFunctionMode(SourceParseMode mode)
2128{
2129 switch (mode) {
2130 case SourceParseMode::GetterMode:
2131 case SourceParseMode::SetterMode:
2132 case SourceParseMode::NormalFunctionMode:
2133 case SourceParseMode::MethodMode:
2134 case SourceParseMode::GeneratorBodyMode:
2135 case SourceParseMode::GeneratorWrapperFunctionMode:
2136 case SourceParseMode::GeneratorWrapperMethodMode:
2137 return "a ";
2138 case SourceParseMode::ArrowFunctionMode:
2139 case SourceParseMode::AsyncFunctionMode:
2140 case SourceParseMode::AsyncFunctionBodyMode:
2141 case SourceParseMode::AsyncMethodMode:
2142 case SourceParseMode::AsyncArrowFunctionBodyMode:
2143 case SourceParseMode::AsyncArrowFunctionMode:
2144 case SourceParseMode::AsyncGeneratorWrapperFunctionMode:
2145 case SourceParseMode::AsyncGeneratorBodyMode:
2146 case SourceParseMode::AsyncGeneratorWrapperMethodMode:
2147 return "an ";
2148 case SourceParseMode::ProgramMode:
2149 case SourceParseMode::ModuleAnalyzeMode:
2150 case SourceParseMode::ModuleEvaluateMode:
2151 RELEASE_ASSERT_NOT_REACHED();
2152 return "";
2153 }
2154 RELEASE_ASSERT_NOT_REACHED();
2155 return nullptr;
2156}
2157
2158static const char* stringForFunctionMode(SourceParseMode mode)
2159{
2160 switch (mode) {
2161 case SourceParseMode::GetterMode:
2162 return "getter";
2163 case SourceParseMode::SetterMode:
2164 return "setter";
2165 case SourceParseMode::NormalFunctionMode:
2166 return "function";
2167 case SourceParseMode::MethodMode:
2168 return "method";
2169 case SourceParseMode::GeneratorBodyMode:
2170 return "generator";
2171 case SourceParseMode::GeneratorWrapperFunctionMode:
2172 case SourceParseMode::GeneratorWrapperMethodMode:
2173 return "generator function";
2174 case SourceParseMode::ArrowFunctionMode:
2175 return "arrow function";
2176 case SourceParseMode::AsyncFunctionMode:
2177 case SourceParseMode::AsyncFunctionBodyMode:
2178 return "async function";
2179 case SourceParseMode::AsyncMethodMode:
2180 return "async method";
2181 case SourceParseMode::AsyncArrowFunctionBodyMode:
2182 case SourceParseMode::AsyncArrowFunctionMode:
2183 return "async arrow function";
2184 case SourceParseMode::AsyncGeneratorWrapperFunctionMode:
2185 case SourceParseMode::AsyncGeneratorBodyMode:
2186 return "async generator function";
2187 case SourceParseMode::AsyncGeneratorWrapperMethodMode:
2188 return "async generator method";
2189 case SourceParseMode::ProgramMode:
2190 case SourceParseMode::ModuleAnalyzeMode:
2191 case SourceParseMode::ModuleEvaluateMode:
2192 RELEASE_ASSERT_NOT_REACHED();
2193 return "";
2194 }
2195 RELEASE_ASSERT_NOT_REACHED();
2196 return nullptr;
2197}
2198
2199template <typename LexerType> template <class TreeBuilder, class FunctionInfoType> typename TreeBuilder::FormalParameterList Parser<LexerType>::parseFunctionParameters(TreeBuilder& context, SourceParseMode mode, FunctionInfoType& functionInfo)
2200{
2201 RELEASE_ASSERT(!(SourceParseModeSet(SourceParseMode::ProgramMode, SourceParseMode::ModuleAnalyzeMode, SourceParseMode::ModuleEvaluateMode).contains(mode)));
2202 TreeFormalParameterList parameterList = context.createFormalParameterList();
2203 SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_parserState.functionParsePhase, FunctionParsePhase::Parameters);
2204
2205 if (UNLIKELY((SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode).contains(mode)))) {
2206 if (!matchSpecIdentifier() && !match(OPENPAREN)) {
2207 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
2208 failWithMessage("Expected an arrow function input parameter");
2209 } else {
2210 if (match(OPENPAREN)) {
2211 next();
2212
2213 if (match(CLOSEPAREN)) {
2214 functionInfo.parameterCount = 0;
2215 } else {
2216 bool isArrowFunction = true;
2217 bool isMethod = false;
2218 failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, isMethod, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
2219 }
2220
2221 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
2222 } else {
2223 functionInfo.parameterCount = 1;
2224 auto parameter = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported);
2225 failIfFalse(parameter, "Cannot parse parameter pattern");
2226 context.appendParameter(parameterList, parameter, 0);
2227 }
2228 }
2229
2230 return parameterList;
2231 }
2232
2233 if (!consume(OPENPAREN)) {
2234 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
2235 failWithMessage("Expected an opening '(' before a ", stringForFunctionMode(mode), "'s parameter list");
2236 }
2237
2238 if (mode == SourceParseMode::GetterMode) {
2239 consumeOrFail(CLOSEPAREN, "getter functions must have no parameters");
2240 functionInfo.parameterCount = 0;
2241 } else if (mode == SourceParseMode::SetterMode) {
2242 failIfTrue(match(CLOSEPAREN), "setter functions must have one parameter");
2243 const Identifier* duplicateParameter = nullptr;
2244 bool hasDestructuringPattern = false;
2245 auto parameter = parseDestructuringPattern(context, DestructuringKind::DestructureToParameters, ExportType::NotExported, &duplicateParameter, &hasDestructuringPattern);
2246 failIfFalse(parameter, "setter functions must have one parameter");
2247 auto defaultValue = parseDefaultValueForDestructuringPattern(context);
2248 propagateError();
2249 if (defaultValue || hasDestructuringPattern) {
2250 semanticFailIfTrue(duplicateParameter, "Duplicate parameter '", duplicateParameter->impl(), "' not allowed in function with non-simple parameter list");
2251 currentScope()->setHasNonSimpleParameterList();
2252 }
2253 context.appendParameter(parameterList, parameter, defaultValue);
2254 functionInfo.parameterCount = defaultValue ? 0 : 1;
2255 failIfTrue(match(COMMA), "setter functions must have one parameter");
2256 consumeOrFail(CLOSEPAREN, "Expected a ')' after a parameter declaration");
2257 } else {
2258 if (match(CLOSEPAREN)) {
2259 functionInfo.parameterCount = 0;
2260 } else {
2261 bool isArrowFunction = false;
2262 bool isMethod = isMethodParseMode(mode);
2263 failIfFalse(parseFormalParameters(context, parameterList, isArrowFunction, isMethod, functionInfo.parameterCount), "Cannot parse parameters for this ", stringForFunctionMode(mode));
2264 }
2265 consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration");
2266 }
2267
2268 return parameterList;
2269}
2270
2271template <typename LexerType>
2272template <class TreeBuilder> typename TreeBuilder::FormalParameterList Parser<LexerType>::createGeneratorParameters(TreeBuilder& context, unsigned& parameterCount)
2273{
2274 auto parameters = context.createFormalParameterList();
2275
2276 JSTokenLocation location(tokenLocation());
2277 JSTextPosition position = tokenStartPosition();
2278
2279 auto addParameter = [&](const Identifier& name) {
2280 declareParameter(&name);
2281 auto binding = context.createBindingLocation(location, name, position, position, AssignmentContext::DeclarationStatement);
2282 context.appendParameter(parameters, binding, 0);
2283 ++parameterCount;
2284 };
2285
2286 // @generator
2287 addParameter(m_vm->propertyNames->generatorPrivateName);
2288 // @generatorState
2289 addParameter(m_vm->propertyNames->generatorStatePrivateName);
2290 // @generatorValue
2291 addParameter(m_vm->propertyNames->generatorValuePrivateName);
2292 // @generatorResumeMode
2293 addParameter(m_vm->propertyNames->generatorResumeModePrivateName);
2294 // @generatorFrame
2295 addParameter(m_vm->propertyNames->generatorFramePrivateName);
2296
2297 return parameters;
2298}
2299
2300template <typename LexerType>
2301template <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)
2302{
2303 RELEASE_ASSERT(isFunctionParseMode(mode));
2304
2305 ScopeRef parentScope = currentScope();
2306
2307 bool isDisallowedAwaitFunctionName = isDisallowedIdentifierAwait(m_token);
2308 const char* isDisallowedAwaitFunctionNameReason = isDisallowedAwaitFunctionName ? disallowedIdentifierAwaitReason() : nullptr;
2309
2310 AutoPopScopeRef functionScope(this, pushScope());
2311 functionScope->setSourceParseMode(mode);
2312 functionScope->setExpectedSuperBinding(expectedSuperBinding);
2313 functionScope->setConstructorKind(constructorKind);
2314 SetForScope<FunctionParsePhase> functionParsePhasePoisoner(m_parserState.functionParsePhase, FunctionParsePhase::Body);
2315 int functionNameStart = m_token.m_location.startOffset;
2316 const Identifier* lastFunctionName = m_parserState.lastFunctionName;
2317 m_parserState.lastFunctionName = nullptr;
2318 int parametersStart = -1;
2319 JSTokenLocation startLocation;
2320 int startColumn = -1;
2321 FunctionBodyType functionBodyType;
2322
2323 auto loadCachedFunction = [&] () -> bool {
2324 if (UNLIKELY(!Options::useSourceProviderCache()))
2325 return false;
2326
2327 if (UNLIKELY(m_debuggerParseData))
2328 return false;
2329
2330 ASSERT(parametersStart != -1);
2331 ASSERT(startColumn != -1);
2332
2333 // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
2334 if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(parametersStart) : 0) {
2335 // If we're in a strict context, the cached function info must say it was strict too.
2336 ASSERT(!strictMode() || cachedInfo->strictMode);
2337 JSTokenLocation endLocation;
2338
2339 ConstructorKind constructorKind = static_cast<ConstructorKind>(cachedInfo->constructorKind);
2340 SuperBinding expectedSuperBinding = static_cast<SuperBinding>(cachedInfo->expectedSuperBinding);
2341
2342 endLocation.line = cachedInfo->lastTokenLine;
2343 endLocation.startOffset = cachedInfo->lastTokenStartOffset;
2344 endLocation.lineStartOffset = cachedInfo->lastTokenLineStartOffset;
2345 ASSERT(endLocation.startOffset >= endLocation.lineStartOffset);
2346
2347 bool endColumnIsOnStartLine = endLocation.line == functionInfo.startLine;
2348 unsigned currentLineStartOffset = m_lexer->currentLineStartOffset();
2349 unsigned bodyEndColumn = endColumnIsOnStartLine ? endLocation.startOffset - currentLineStartOffset : endLocation.startOffset - endLocation.lineStartOffset;
2350
2351 ASSERT(endLocation.startOffset >= endLocation.lineStartOffset);
2352
2353 FunctionBodyType functionBodyType;
2354 if (UNLIKELY(SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode).contains(mode)))
2355 functionBodyType = cachedInfo->isBodyArrowExpression ? ArrowFunctionBodyExpression : ArrowFunctionBodyBlock;
2356 else
2357 functionBodyType = StandardFunctionBodyBlock;
2358
2359 SuperBinding functionSuperBinding = adjustSuperBindingForBaseConstructor(constructorKind, expectedSuperBinding, cachedInfo->needsSuperBinding, cachedInfo->usesEval, cachedInfo->innerArrowFunctionFeatures);
2360
2361 functionInfo.body = context.createFunctionMetadata(
2362 startLocation, endLocation, startColumn, bodyEndColumn,
2363 functionKeywordStart, functionNameStart, parametersStart,
2364 cachedInfo->strictMode, constructorKind, functionSuperBinding,
2365 cachedInfo->parameterCount,
2366 mode, functionBodyType == ArrowFunctionBodyExpression);
2367 functionInfo.endOffset = cachedInfo->endFunctionOffset;
2368 functionInfo.parameterCount = cachedInfo->parameterCount;
2369
2370 functionScope->restoreFromSourceProviderCache(cachedInfo);
2371 popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo);
2372
2373 m_token = cachedInfo->endFunctionToken();
2374
2375 if (endColumnIsOnStartLine)
2376 m_token.m_location.lineStartOffset = currentLineStartOffset;
2377
2378 m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset);
2379 m_lexer->setLineNumber(m_token.m_location.line);
2380
2381 switch (functionBodyType) {
2382 case ArrowFunctionBodyExpression:
2383 next();
2384 context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
2385 break;
2386 case ArrowFunctionBodyBlock:
2387 case StandardFunctionBodyBlock:
2388 context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
2389 next();
2390 break;
2391 }
2392 functionInfo.endLine = m_lastTokenEndPosition.line;
2393 return true;
2394 }
2395
2396 return false;
2397 };
2398
2399 SyntaxChecker syntaxChecker(const_cast<VM*>(m_vm), m_lexer.get());
2400
2401 if (UNLIKELY((SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode).contains(mode)))) {
2402 startLocation = tokenLocation();
2403 functionInfo.startLine = tokenLine();
2404 startColumn = tokenColumn();
2405
2406 parametersStart = m_token.m_location.startOffset;
2407 functionInfo.startOffset = parametersStart;
2408 functionInfo.parametersStartColumn = startColumn;
2409
2410 if (loadCachedFunction())
2411 return true;
2412
2413 {
2414 // Parse formal parameters with [+Yield] parameterization, in order to ban YieldExpressions
2415 // in ArrowFormalParameters, per ES6 #sec-arrow-function-definitions-static-semantics-early-errors.
2416 Scope::MaybeParseAsGeneratorForScope parseAsGenerator(functionScope, parentScope->isGenerator());
2417 SetForScope<bool> overrideAllowAwait(m_parserState.allowAwait, !isAsyncFunctionParseMode(mode));
2418 parseFunctionParameters(syntaxChecker, mode, functionInfo);
2419 propagateError();
2420 }
2421
2422 matchOrFail(ARROWFUNCTION, "Expected a '=>' after arrow function parameter declaration");
2423
2424 if (m_lexer->hasLineTerminatorBeforeToken())
2425 failDueToUnexpectedToken();
2426
2427 ASSERT(constructorKind == ConstructorKind::None);
2428
2429 // Check if arrow body start with {. If it true it mean that arrow function is Fat arrow function
2430 // and we need use common approach to parse function body
2431 next();
2432 functionBodyType = match(OPENBRACE) ? ArrowFunctionBodyBlock : ArrowFunctionBodyExpression;
2433 } else {
2434 // http://ecma-international.org/ecma-262/6.0/#sec-function-definitions
2435 // FunctionExpression :
2436 // function BindingIdentifieropt ( FormalParameters ) { FunctionBody }
2437 //
2438 // FunctionDeclaration[Yield, Default] :
2439 // function BindingIdentifier[?Yield] ( FormalParameters ) { FunctionBody }
2440 // [+Default] function ( FormalParameters ) { FunctionBody }
2441 //
2442 // GeneratorDeclaration[Yield, Default] :
2443 // function * BindingIdentifier[?Yield] ( FormalParameters[Yield] ) { GeneratorBody }
2444 // [+Default] function * ( FormalParameters[Yield] ) { GeneratorBody }
2445 //
2446 // GeneratorExpression :
2447 // function * BindingIdentifier[Yield]opt ( FormalParameters[Yield] ) { GeneratorBody }
2448 //
2449 // The name of FunctionExpression and AsyncFunctionExpression can accept "yield" even in the context of generator.
2450 bool upperScopeIsGenerator = false;
2451 if (!(functionDefinitionType == FunctionDefinitionType::Expression && SourceParseModeSet(SourceParseMode::NormalFunctionMode, SourceParseMode::AsyncFunctionMode).contains(mode)))
2452 upperScopeIsGenerator = upperScope(1)->isGenerator();
2453
2454 if (requirements != FunctionNameRequirements::Unnamed) {
2455 ASSERT_WITH_MESSAGE(!(requirements == FunctionNameRequirements::None && !functionInfo.name), "When specifying FunctionNameRequirements::None, we need to initialize functionInfo.name with the default value in the caller side.");
2456 if (matchSpecIdentifier(upperScopeIsGenerator)) {
2457 functionInfo.name = m_token.m_data.ident;
2458 m_parserState.lastFunctionName = functionInfo.name;
2459 if (UNLIKELY(isDisallowedAwaitFunctionName))
2460 semanticFailIfTrue(functionDefinitionType == FunctionDefinitionType::Declaration || isAsyncFunctionOrAsyncGeneratorWrapperParseMode(mode), "Cannot declare function named 'await' ", isDisallowedAwaitFunctionNameReason);
2461 else if (isAsyncFunctionOrAsyncGeneratorWrapperParseMode(mode) && match(AWAIT) && functionDefinitionType == FunctionDefinitionType::Expression)
2462 semanticFail("Cannot declare ", stringForFunctionMode(mode), " named 'await'");
2463 else if (isGeneratorWrapperParseMode(mode) && match(YIELD) && functionDefinitionType == FunctionDefinitionType::Expression)
2464 semanticFail("Cannot declare generator function named 'yield'");
2465 next();
2466 if (!nameIsInContainingScope)
2467 failIfTrueIfStrict(functionScope->declareCallee(functionInfo.name) & DeclarationResult::InvalidStrictMode, "'", functionInfo.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode");
2468 } else if (requirements == FunctionNameRequirements::Named) {
2469 if (match(OPENPAREN)) {
2470 semanticFailIfTrue(mode == SourceParseMode::NormalFunctionMode, "Function statements must have a name");
2471 semanticFailIfTrue(mode == SourceParseMode::AsyncFunctionMode, "Async function statements must have a name");
2472 }
2473 semanticFailureDueToKeyword(stringForFunctionMode(mode), " name");
2474 failDueToUnexpectedToken();
2475 return false;
2476 }
2477 ASSERT(functionInfo.name);
2478 }
2479
2480 startLocation = tokenLocation();
2481 functionInfo.startLine = tokenLine();
2482 startColumn = tokenColumn();
2483 functionInfo.parametersStartColumn = startColumn;
2484
2485 parametersStart = m_token.m_location.startOffset;
2486 functionInfo.startOffset = parametersStart;
2487
2488 if (loadCachedFunction())
2489 return true;
2490 {
2491 SetForScope<bool> overrideAllowAwait(m_parserState.allowAwait, !isAsyncFunctionParseMode(mode));
2492 parseFunctionParameters(syntaxChecker, mode, functionInfo);
2493 propagateError();
2494 }
2495
2496 matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body");
2497
2498 // If the code is invoked from function constructor, we need to ensure that parameters are only composed by the string offered as parameters.
2499 if (UNLIKELY(functionConstructorParametersEndPosition))
2500 semanticFailIfFalse(lastTokenEndPosition().offset == *functionConstructorParametersEndPosition, "Parameters should match arguments offered as parameters in Function constructor");
2501
2502 // BytecodeGenerator emits code to throw TypeError when a class constructor is "call"ed.
2503 // Set ConstructorKind to None for non-constructor methods of classes.
2504
2505 if (m_defaultConstructorKind != ConstructorKind::None) {
2506 constructorKind = m_defaultConstructorKind;
2507 expectedSuperBinding = m_defaultConstructorKind == ConstructorKind::Extends ? SuperBinding::Needed : SuperBinding::NotNeeded;
2508 }
2509
2510 functionBodyType = StandardFunctionBodyBlock;
2511 }
2512
2513 functionScope->setConstructorKind(constructorKind);
2514 functionScope->setExpectedSuperBinding(expectedSuperBinding);
2515
2516 m_parserState.lastFunctionName = lastFunctionName;
2517 ParserState oldState = internalSaveParserState();
2518
2519 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=156962
2520 // This loop collects the set of capture candidates that aren't
2521 // part of the set of this function's declared parameters. We will
2522 // figure out which parameters are captured for this function when
2523 // we actually generate code for it. For now, we just propagate to
2524 // our parent scopes which variables we might have closed over that
2525 // belong to them. This is necessary for correctness when using
2526 // the source provider cache because we can't close over a variable
2527 // that we don't claim to close over. The source provider cache must
2528 // know this information to properly cache this function.
2529 // This might work itself out nicer if we declared a different
2530 // Scope struct for the parameters (because they are indeed implemented
2531 // as their own scope).
2532 UniquedStringImplPtrSet nonLocalCapturesFromParameterExpressions;
2533 functionScope->forEachUsedVariable([&] (UniquedStringImpl* impl) {
2534 if (!functionScope->hasDeclaredParameter(impl)) {
2535 nonLocalCapturesFromParameterExpressions.add(impl);
2536 if (TreeBuilder::NeedsFreeVariableInfo)
2537 parentScope->addClosedVariableCandidateUnconditionally(impl);
2538 }
2539 });
2540
2541 auto performParsingFunctionBody = [&] {
2542 return parseFunctionBody(context, syntaxChecker, startLocation, startColumn, functionKeywordStart, functionNameStart, parametersStart, constructorKind, expectedSuperBinding, functionBodyType, functionInfo.parameterCount, mode);
2543 };
2544
2545 if (isGeneratorOrAsyncFunctionWrapperParseMode(mode)) {
2546 AutoPopScopeRef generatorBodyScope(this, pushScope());
2547 SourceParseMode innerParseMode = SourceParseMode::GeneratorBodyMode;
2548 if (isAsyncFunctionOrAsyncGeneratorWrapperParseMode(mode))
2549 innerParseMode = getAsynFunctionBodyParseMode(mode);
2550
2551 generatorBodyScope->setSourceParseMode(innerParseMode);
2552 generatorBodyScope->setConstructorKind(ConstructorKind::None);
2553 generatorBodyScope->setExpectedSuperBinding(expectedSuperBinding);
2554
2555 // Disallow 'use strict' directives in the implicit inner function if
2556 // needed.
2557 if (functionScope->hasNonSimpleParameterList())
2558 generatorBodyScope->setHasNonSimpleParameterList();
2559
2560 functionInfo.body = performParsingFunctionBody();
2561
2562 // When a generator has a "use strict" directive, a generator function wrapping it should be strict mode.
2563 if (generatorBodyScope->strictMode())
2564 functionScope->setStrictMode();
2565
2566 popScope(generatorBodyScope, TreeBuilder::NeedsFreeVariableInfo);
2567 } else
2568 functionInfo.body = performParsingFunctionBody();
2569
2570 restoreParserState(oldState);
2571 failIfFalse(functionInfo.body, "Cannot parse the body of this ", stringForFunctionMode(mode));
2572 context.setEndOffset(functionInfo.body, m_lexer->currentOffset());
2573 if (functionScope->strictMode() && requirements != FunctionNameRequirements::Unnamed) {
2574 ASSERT(functionInfo.name);
2575 RELEASE_ASSERT(SourceParseModeSet(SourceParseMode::NormalFunctionMode, SourceParseMode::MethodMode, SourceParseMode::ArrowFunctionMode, SourceParseMode::GeneratorBodyMode, SourceParseMode::GeneratorWrapperFunctionMode).contains(mode) || isAsyncFunctionOrAsyncGeneratorWrapperParseMode(mode));
2576 semanticFailIfTrue(m_vm->propertyNames->arguments == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
2577 semanticFailIfTrue(m_vm->propertyNames->eval == *functionInfo.name, "'", functionInfo.name->impl(), "' is not a valid function name in strict mode");
2578 }
2579
2580 JSTokenLocation location = JSTokenLocation(m_token.m_location);
2581 functionInfo.endOffset = m_token.m_data.offset;
2582
2583 if (functionBodyType == ArrowFunctionBodyExpression) {
2584 location = locationBeforeLastToken();
2585 functionInfo.endOffset = location.endOffset;
2586 } else {
2587 recordFunctionEntryLocation(JSTextPosition(startLocation.line, startLocation.startOffset, startLocation.lineStartOffset));
2588 recordFunctionLeaveLocation(JSTextPosition(location.line, location.startOffset, location.lineStartOffset));
2589 }
2590
2591 // Cache the tokenizer state and the function scope the first time the function is parsed.
2592 // Any future reparsing can then skip the function.
2593 // For arrow function is 8 = x=>x + 4 symbols;
2594 // For ordinary function is 16 = function(){} + 4 symbols
2595 const int minimumSourceLengthToCache = functionBodyType == StandardFunctionBodyBlock ? 16 : 8;
2596 std::unique_ptr<SourceProviderCacheItem> newInfo;
2597 int sourceLength = functionInfo.endOffset - functionInfo.startOffset;
2598 if (TreeBuilder::CanUseFunctionCache && m_functionCache && sourceLength > minimumSourceLengthToCache) {
2599 SourceProviderCacheItemCreationParameters parameters;
2600 parameters.endFunctionOffset = functionInfo.endOffset;
2601 parameters.lastTokenLine = location.line;
2602 parameters.lastTokenStartOffset = location.startOffset;
2603 parameters.lastTokenEndOffset = location.endOffset;
2604 parameters.lastTokenLineStartOffset = location.lineStartOffset;
2605 parameters.parameterCount = functionInfo.parameterCount;
2606 parameters.constructorKind = constructorKind;
2607 parameters.expectedSuperBinding = expectedSuperBinding;
2608 if (functionBodyType == ArrowFunctionBodyExpression) {
2609 parameters.isBodyArrowExpression = true;
2610 parameters.tokenType = m_token.m_type;
2611 }
2612 functionScope->fillParametersForSourceProviderCache(parameters, nonLocalCapturesFromParameterExpressions);
2613 newInfo = SourceProviderCacheItem::create(parameters);
2614 }
2615
2616 bool functionScopeWasStrictMode = functionScope->strictMode();
2617
2618 popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo);
2619
2620 if (functionBodyType != ArrowFunctionBodyExpression) {
2621 matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body");
2622 next();
2623 } else {
2624 // We need to lex the last token again because the last token is lexed under the different context because of the following possibilities.
2625 // 1. which may have different strict mode.
2626 // 2. which may not build strings for tokens.
2627 // But (1) is not possible because we do not recognize the string literal in ArrowFunctionBodyExpression as directive and this is correct in terms of the spec (`value => "use strict"`).
2628 // So we only check TreeBuilder's type here.
2629 ASSERT_UNUSED(functionScopeWasStrictMode, functionScopeWasStrictMode == currentScope()->strictMode());
2630 if (!std::is_same<TreeBuilder, SyntaxChecker>::value)
2631 lexCurrentTokenAgainUnderCurrentContext();
2632 }
2633
2634 if (newInfo)
2635 m_functionCache->add(functionInfo.startOffset, WTFMove(newInfo));
2636
2637 functionInfo.endLine = m_lastTokenEndPosition.line;
2638 return true;
2639}
2640
2641static NO_RETURN_DUE_TO_CRASH FunctionMetadataNode* getMetadata(ParserFunctionInfo<SyntaxChecker>&) { RELEASE_ASSERT_NOT_REACHED(); }
2642static FunctionMetadataNode* getMetadata(ParserFunctionInfo<ASTBuilder>& info) { return info.body; }
2643
2644template <typename LexerType>
2645template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext, Optional<int> functionConstructorParametersEndPosition)
2646{
2647 ASSERT(match(FUNCTION));
2648 JSTokenLocation location(tokenLocation());
2649 unsigned functionKeywordStart = tokenStart();
2650 next();
2651 SourceParseMode parseMode = SourceParseMode::NormalFunctionMode;
2652 if (consume(TIMES))
2653 parseMode = SourceParseMode::GeneratorWrapperFunctionMode;
2654
2655 ParserFunctionInfo<TreeBuilder> functionInfo;
2656 FunctionNameRequirements requirements = FunctionNameRequirements::Named;
2657 if (declarationDefaultContext == DeclarationDefaultContext::ExportDefault) {
2658 // Under the "export default" context, function declaration does not require the function name.
2659 //
2660 // ExportDeclaration:
2661 // ...
2662 // export default HoistableDeclaration[~Yield, +Default]
2663 // ...
2664 //
2665 // HoistableDeclaration[Yield, Default]:
2666 // FunctionDeclaration[?Yield, ?Default]
2667 // GeneratorDeclaration[?Yield, ?Default]
2668 //
2669 // FunctionDeclaration[Yield, Default]:
2670 // ...
2671 // [+Default] function ( FormalParameters[~Yield] ) { FunctionBody[~Yield] }
2672 //
2673 // GeneratorDeclaration[Yield, Default]:
2674 // ...
2675 // [+Default] function * ( FormalParameters[+Yield] ) { GeneratorBody }
2676 //
2677 // In this case, we use "*default*" as this function declaration's name.
2678 requirements = FunctionNameRequirements::None;
2679 functionInfo.name = &m_vm->propertyNames->starDefaultPrivateName;
2680 }
2681
2682 failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration, functionConstructorParametersEndPosition)), "Cannot parse this function");
2683 ASSERT(functionInfo.name);
2684
2685 std::pair<DeclarationResultMask, ScopeRef> functionDeclaration = declareFunction(functionInfo.name);
2686 DeclarationResultMask declarationResult = functionDeclaration.first;
2687 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare a function named '", functionInfo.name->impl(), "' in strict mode");
2688 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
2689 internalFailWithMessage(false, "Cannot declare a function that shadows a let/const/class/function variable '", functionInfo.name->impl(), "' in strict mode");
2690 if (exportType == ExportType::Exported) {
2691 ASSERT_WITH_MESSAGE(declarationDefaultContext != DeclarationDefaultContext::ExportDefault, "Export default case will export the name and binding in the caller.");
2692 semanticFailIfFalse(exportName(*functionInfo.name), "Cannot export a duplicate function name: '", functionInfo.name->impl(), "'");
2693 m_moduleScopeData->exportBinding(*functionInfo.name);
2694 }
2695
2696 TreeStatement result = context.createFuncDeclStatement(location, functionInfo);
2697 if (TreeBuilder::CreatesAST)
2698 functionDeclaration.second->appendFunction(getMetadata(functionInfo));
2699 return result;
2700}
2701
2702template <typename LexerType>
2703template <class TreeBuilder> TreeStatement Parser<LexerType>::parseAsyncFunctionDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext, Optional<int> functionConstructorParametersEndPosition)
2704{
2705 ASSERT(match(FUNCTION));
2706 JSTokenLocation location(tokenLocation());
2707 unsigned functionKeywordStart = tokenStart();
2708 next();
2709 ParserFunctionInfo<TreeBuilder> functionInfo;
2710 SourceParseMode parseMode = SourceParseMode::AsyncFunctionMode;
2711 if (consume(TIMES))
2712 parseMode = SourceParseMode::AsyncGeneratorWrapperFunctionMode;
2713
2714 FunctionNameRequirements requirements = FunctionNameRequirements::Named;
2715 if (declarationDefaultContext == DeclarationDefaultContext::ExportDefault) {
2716 // Under the "export default" context, function declaration does not require the function name.
2717 //
2718 // ExportDeclaration:
2719 // ...
2720 // export default HoistableDeclaration[~Yield, +Default]
2721 // ...
2722 //
2723 // HoistableDeclaration[Yield, Default]:
2724 // FunctionDeclaration[?Yield, ?Default]
2725 // GeneratorDeclaration[?Yield, ?Default]
2726 //
2727 // FunctionDeclaration[Yield, Default]:
2728 // ...
2729 // [+Default] function ( FormalParameters[~Yield] ) { FunctionBody[~Yield] }
2730 //
2731 // GeneratorDeclaration[Yield, Default]:
2732 // ...
2733 // [+Default] function * ( FormalParameters[+Yield] ) { GeneratorBody }
2734 //
2735 // In this case, we use "*default*" as this function declaration's name.
2736 requirements = FunctionNameRequirements::None;
2737 functionInfo.name = &m_vm->propertyNames->starDefaultPrivateName;
2738 }
2739
2740 failIfFalse((parseFunctionInfo(context, requirements, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration, functionConstructorParametersEndPosition)), "Cannot parse this async function");
2741 failIfFalse(functionInfo.name, "Async function statements must have a name");
2742
2743 std::pair<DeclarationResultMask, ScopeRef> functionDeclaration = declareFunction(functionInfo.name);
2744 DeclarationResultMask declarationResult = functionDeclaration.first;
2745 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare an async function named '", functionInfo.name->impl(), "' in strict mode");
2746 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
2747 internalFailWithMessage(false, "Cannot declare an async function that shadows a let/const/class/function variable '", functionInfo.name->impl(), "' in strict mode");
2748 if (exportType == ExportType::Exported) {
2749 semanticFailIfFalse(exportName(*functionInfo.name), "Cannot export a duplicate function name: '", functionInfo.name->impl(), "'");
2750 m_moduleScopeData->exportBinding(*functionInfo.name);
2751 }
2752
2753 TreeStatement result = context.createFuncDeclStatement(location, functionInfo);
2754 if (TreeBuilder::CreatesAST)
2755 functionDeclaration.second->appendFunction(getMetadata(functionInfo));
2756 return result;
2757}
2758
2759template <typename LexerType>
2760template <class TreeBuilder> TreeStatement Parser<LexerType>::parseClassDeclaration(TreeBuilder& context, ExportType exportType, DeclarationDefaultContext declarationDefaultContext)
2761{
2762 ASSERT(match(CLASSTOKEN));
2763 JSTokenLocation location(tokenLocation());
2764 JSTextPosition classStart = tokenStartPosition();
2765 unsigned classStartLine = tokenLine();
2766
2767 ParserClassInfo<TreeBuilder> info;
2768 FunctionNameRequirements requirements = FunctionNameRequirements::Named;
2769 if (declarationDefaultContext == DeclarationDefaultContext::ExportDefault) {
2770 // Under the "export default" context, class declaration does not require the class name.
2771 //
2772 // ExportDeclaration:
2773 // ...
2774 // export default ClassDeclaration[~Yield, +Default]
2775 // ...
2776 //
2777 // ClassDeclaration[Yield, Default]:
2778 // ...
2779 // [+Default] class ClassTail[?Yield]
2780 //
2781 // In this case, we use "*default*" as this class declaration's name.
2782 requirements = FunctionNameRequirements::None;
2783 info.className = &m_vm->propertyNames->starDefaultPrivateName;
2784 }
2785
2786 TreeClassExpression classExpr = parseClass(context, requirements, info);
2787 failIfFalse(classExpr, "Failed to parse class");
2788 ASSERT(info.className);
2789
2790 DeclarationResultMask declarationResult = declareVariable(info.className, DeclarationType::LetDeclaration);
2791 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
2792 internalFailWithMessage(false, "Cannot declare a class twice: '", info.className->impl(), "'");
2793 if (exportType == ExportType::Exported) {
2794 ASSERT_WITH_MESSAGE(declarationDefaultContext != DeclarationDefaultContext::ExportDefault, "Export default case will export the name and binding in the caller.");
2795 semanticFailIfFalse(exportName(*info.className), "Cannot export a duplicate class name: '", info.className->impl(), "'");
2796 m_moduleScopeData->exportBinding(*info.className);
2797 }
2798
2799 JSTextPosition classEnd = lastTokenEndPosition();
2800 unsigned classEndLine = tokenLine();
2801
2802 return context.createClassDeclStatement(location, classExpr, classStart, classEnd, classStartLine, classEndLine);
2803}
2804
2805template <typename LexerType>
2806template <class TreeBuilder> TreeClassExpression Parser<LexerType>::parseClass(TreeBuilder& context, FunctionNameRequirements requirements, ParserClassInfo<TreeBuilder>& info)
2807{
2808 ASSERT(match(CLASSTOKEN));
2809 JSTokenLocation location(tokenLocation());
2810 info.startLine = location.line;
2811 info.startColumn = tokenColumn();
2812 info.startOffset = location.startOffset;
2813 next();
2814
2815 AutoPopScopeRef classScope(this, pushScope());
2816 classScope->setIsLexicalScope();
2817 classScope->preventVarDeclarations();
2818 classScope->setStrictMode();
2819
2820 ASSERT_WITH_MESSAGE(requirements != FunctionNameRequirements::Unnamed, "Currently, there is no caller that uses FunctionNameRequirements::Unnamed for class syntax.");
2821 ASSERT_WITH_MESSAGE(!(requirements == FunctionNameRequirements::None && !info.className), "When specifying FunctionNameRequirements::None, we need to initialize info.className with the default value in the caller side.");
2822 if (match(IDENT)) {
2823 info.className = m_token.m_data.ident;
2824 next();
2825 failIfTrue(classScope->declareLexicalVariable(info.className, true) & DeclarationResult::InvalidStrictMode, "'", info.className->impl(), "' is not a valid class name");
2826 } else if (requirements == FunctionNameRequirements::Named) {
2827 if (match(OPENBRACE))
2828 semanticFail("Class statements must have a name");
2829 semanticFailureDueToKeyword("class name");
2830 failDueToUnexpectedToken();
2831 }
2832 ASSERT(info.className);
2833
2834 TreeExpression parentClass = 0;
2835 if (consume(EXTENDS)) {
2836 parentClass = parseMemberExpression(context);
2837 failIfFalse(parentClass, "Cannot parse the parent class name");
2838 }
2839 const ConstructorKind constructorKind = parentClass ? ConstructorKind::Extends : ConstructorKind::Base;
2840
2841 consumeOrFail(OPENBRACE, "Expected opening '{' at the start of a class body");
2842
2843 TreeExpression constructor = 0;
2844 TreePropertyList classElements = 0;
2845 TreePropertyList classElementsTail = 0;
2846 while (!match(CLOSEBRACE)) {
2847 if (match(SEMICOLON)) {
2848 next();
2849 continue;
2850 }
2851
2852 JSTokenLocation methodLocation(tokenLocation());
2853 unsigned methodStart = tokenStart();
2854
2855 // For backwards compatibility, "static" is a non-reserved keyword in non-strict mode.
2856 ClassElementTag tag = ClassElementTag::Instance;
2857 if (match(RESERVED_IF_STRICT) && *m_token.m_data.ident == m_vm->propertyNames->staticKeyword) {
2858 SavePoint savePoint = createSavePoint();
2859 next();
2860 if (match(OPENPAREN)) {
2861 // Reparse "static()" as a method named "static".
2862 restoreSavePoint(savePoint);
2863 } else
2864 tag = ClassElementTag::Static;
2865 }
2866
2867 // FIXME: Figure out a way to share more code with parseProperty.
2868 const CommonIdentifiers& propertyNames = *m_vm->propertyNames;
2869 const Identifier* ident = &propertyNames.nullIdentifier;
2870 TreeExpression computedPropertyName = 0;
2871 bool isGetter = false;
2872 bool isSetter = false;
2873 SourceParseMode parseMode = SourceParseMode::MethodMode;
2874 if (consume(TIMES))
2875 parseMode = SourceParseMode::GeneratorWrapperMethodMode;
2876
2877parseMethod:
2878 switch (m_token.m_type) {
2879 namedKeyword:
2880 case STRING:
2881 ident = m_token.m_data.ident;
2882 ASSERT(ident);
2883 next();
2884 break;
2885 case IDENT:
2886 if (UNLIKELY(*m_token.m_data.ident == m_vm->propertyNames->async && !m_token.m_data.escaped)) {
2887 if (!isGeneratorMethodParseMode(parseMode) && !isAsyncMethodParseMode(parseMode)) {
2888 ident = m_token.m_data.ident;
2889 next();
2890 if (match(OPENPAREN) || match(COLON) || match(EQUAL) || m_lexer->hasLineTerminatorBeforeToken())
2891 break;
2892 if (UNLIKELY(consume(TIMES)))
2893 parseMode = SourceParseMode::AsyncGeneratorWrapperMethodMode;
2894 else
2895 parseMode = SourceParseMode::AsyncMethodMode;
2896 goto parseMethod;
2897 }
2898 }
2899 FALLTHROUGH;
2900 case AWAIT:
2901 ident = m_token.m_data.ident;
2902 ASSERT(ident);
2903 next();
2904 if (parseMode == SourceParseMode::MethodMode && (matchIdentifierOrKeyword() || match(STRING) || match(DOUBLE) || match(INTEGER) || match(OPENBRACKET))) {
2905 isGetter = *ident == propertyNames.get;
2906 isSetter = *ident == propertyNames.set;
2907 }
2908 break;
2909 case DOUBLE:
2910 case INTEGER:
2911 ident = &m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), m_token.m_data.doubleValue);
2912 ASSERT(ident);
2913 next();
2914 break;
2915 case OPENBRACKET:
2916 next();
2917 computedPropertyName = parseAssignmentExpression(context);
2918 failIfFalse(computedPropertyName, "Cannot parse computed property name");
2919 handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name");
2920 break;
2921 default:
2922 if (m_token.m_type & KeywordTokenFlag)
2923 goto namedKeyword;
2924 failDueToUnexpectedToken();
2925 }
2926
2927 TreeProperty property;
2928 const bool alwaysStrictInsideClass = true;
2929 if (isGetter || isSetter) {
2930 property = parseGetterSetter(context, alwaysStrictInsideClass, isGetter ? PropertyNode::Getter : PropertyNode::Setter,
2931 methodStart, ConstructorKind::None, tag);
2932 failIfFalse(property, "Cannot parse this method");
2933 } else {
2934 ParserFunctionInfo<TreeBuilder> methodInfo;
2935 bool isConstructor = tag == ClassElementTag::Instance && *ident == propertyNames.constructor;
2936 if (isAsyncMethodParseMode(parseMode) || isAsyncGeneratorMethodParseMode(parseMode) || isGeneratorMethodParseMode(parseMode)) {
2937 isConstructor = false;
2938 semanticFailIfTrue(*ident == m_vm->propertyNames->prototype, "Cannot declare ", stringArticleForFunctionMode(parseMode), stringForFunctionMode(parseMode), " named 'prototype'");
2939 semanticFailIfTrue(*ident == m_vm->propertyNames->constructor, "Cannot declare ", stringArticleForFunctionMode(parseMode), stringForFunctionMode(parseMode), " named 'constructor'");
2940 }
2941
2942 methodInfo.name = isConstructor ? info.className : ident;
2943 failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::Unnamed, parseMode, false, isConstructor ? constructorKind : ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, FunctionDefinitionType::Method)), "Cannot parse this method");
2944
2945 TreeExpression method = context.createMethodDefinition(methodLocation, methodInfo);
2946 if (isConstructor) {
2947 semanticFailIfTrue(constructor, "Cannot declare multiple constructors in a single class");
2948 constructor = method;
2949 continue;
2950 }
2951
2952 // FIXME: Syntax error when super() is called
2953 semanticFailIfTrue(tag == ClassElementTag::Static && methodInfo.name && *methodInfo.name == propertyNames.prototype,
2954 "Cannot declare a static method named 'prototype'");
2955
2956 if (computedPropertyName) {
2957 property = context.createProperty(computedPropertyName, method, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed),
2958 PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed, tag);
2959 } else {
2960 property = context.createProperty(methodInfo.name, method, PropertyNode::Constant,
2961 PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed, InferName::Allowed, tag);
2962 }
2963 }
2964
2965 if (classElementsTail)
2966 classElementsTail = context.createPropertyList(methodLocation, property, classElementsTail);
2967 else
2968 classElements = classElementsTail = context.createPropertyList(methodLocation, property);
2969 }
2970
2971 info.endOffset = tokenLocation().endOffset - 1;
2972 consumeOrFail(CLOSEBRACE, "Expected a closing '}' after a class body");
2973
2974 auto classExpression = context.createClassExpr(location, info, classScope->finalizeLexicalEnvironment(), constructor, parentClass, classElements);
2975 popScope(classScope, TreeBuilder::NeedsFreeVariableInfo);
2976 return classExpression;
2977}
2978
2979struct LabelInfo {
2980 LabelInfo(const Identifier* ident, const JSTextPosition& start, const JSTextPosition& end)
2981 : m_ident(ident)
2982 , m_start(start)
2983 , m_end(end)
2984 {
2985 }
2986
2987 const Identifier* m_ident;
2988 JSTextPosition m_start;
2989 JSTextPosition m_end;
2990};
2991
2992template <typename LexerType>
2993template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrLabelStatement(TreeBuilder& context, bool allowFunctionDeclarationAsStatement)
2994{
2995
2996 /* Expression and Label statements are ambiguous at LL(1), so we have a
2997 * special case that looks for a colon as the next character in the input.
2998 */
2999 Vector<LabelInfo> labels;
3000 JSTokenLocation location;
3001 do {
3002 JSTextPosition start = tokenStartPosition();
3003 location = tokenLocation();
3004 if (!nextTokenIsColon()) {
3005 // If we hit this path we're making a expression statement, which
3006 // by definition can't make use of continue/break so we can just
3007 // ignore any labels we might have accumulated.
3008 TreeExpression expression = parseExpression(context);
3009 failIfFalse(expression, "Cannot parse expression statement");
3010 if (!autoSemiColon())
3011 failDueToUnexpectedToken();
3012 return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
3013 }
3014
3015 semanticFailIfTrue(isDisallowedIdentifierAwait(m_token), "Cannot use 'await' as a label ", disallowedIdentifierAwaitReason());
3016 semanticFailIfTrue(isDisallowedIdentifierYield(m_token), "Cannot use 'yield' as a label ", disallowedIdentifierYieldReason());
3017
3018 const Identifier* ident = m_token.m_data.ident;
3019 JSTextPosition end = tokenEndPosition();
3020 next();
3021 consumeOrFail(COLON, "Labels must be followed by a ':'");
3022
3023 // This is O(N^2) over the current list of consecutive labels, but I
3024 // have never seen more than one label in a row in the real world.
3025 for (size_t i = 0; i < labels.size(); i++)
3026 failIfTrue(ident->impl() == labels[i].m_ident->impl(), "Attempted to redeclare the label '", ident->impl(), "'");
3027 failIfTrue(getLabel(ident), "Cannot find scope for the label '", ident->impl(), "'");
3028 labels.append(LabelInfo(ident, start, end));
3029 } while (matchSpecIdentifier());
3030 bool isLoop = false;
3031 switch (m_token.m_type) {
3032 case FOR:
3033 case WHILE:
3034 case DO:
3035 isLoop = true;
3036 break;
3037
3038 default:
3039 break;
3040 }
3041 const Identifier* unused = 0;
3042 ScopeRef labelScope = currentScope();
3043 for (size_t i = 0; i < labels.size(); i++)
3044 pushLabel(labels[i].m_ident, isLoop);
3045 m_immediateParentAllowsFunctionDeclarationInStatement = allowFunctionDeclarationAsStatement;
3046 TreeStatement statement = parseStatement(context, unused);
3047 for (size_t i = 0; i < labels.size(); i++)
3048 popLabel(labelScope);
3049 failIfFalse(statement, "Cannot parse statement");
3050 for (size_t i = 0; i < labels.size(); i++) {
3051 const LabelInfo& info = labels[labels.size() - i - 1];
3052 statement = context.createLabelStatement(location, info.m_ident, statement, info.m_start, info.m_end);
3053 }
3054 return statement;
3055}
3056
3057template <typename LexerType>
3058template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionStatement(TreeBuilder& context)
3059{
3060 switch (m_token.m_type) {
3061 // Consult: http://www.ecma-international.org/ecma-262/6.0/index.html#sec-expression-statement
3062 // The ES6 spec mandates that we should fail from FUNCTION token here. We handle this case
3063 // in parseStatement() which is the only caller of parseExpressionStatement().
3064 // We actually allow FUNCTION in situations where it should not be allowed unless we're in strict mode.
3065 case CLASSTOKEN:
3066 failWithMessage("'class' declaration is not directly within a block statement");
3067 break;
3068 default:
3069 // FIXME: when implementing 'let' we should fail when we see the token sequence "let [".
3070 // https://bugs.webkit.org/show_bug.cgi?id=142944
3071 break;
3072 }
3073 JSTextPosition start = tokenStartPosition();
3074 JSTokenLocation location(tokenLocation());
3075 TreeExpression expression = parseExpression(context);
3076 failIfFalse(expression, "Cannot parse expression statement");
3077 failIfFalse(autoSemiColon(), "Parse error");
3078 return context.createExprStatement(location, expression, start, m_lastTokenEndPosition.line);
3079}
3080
3081template <typename LexerType>
3082template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(TreeBuilder& context)
3083{
3084 ASSERT(match(IF));
3085 JSTokenLocation ifLocation(tokenLocation());
3086 int start = tokenLine();
3087 next();
3088 handleProductionOrFail2(OPENPAREN, "(", "start", "'if' condition");
3089
3090 TreeExpression condition = parseExpression(context);
3091 failIfFalse(condition, "Expected a expression as the condition for an if statement");
3092 recordPauseLocation(context.breakpointLocation(condition));
3093 int end = tokenLine();
3094 handleProductionOrFail2(CLOSEPAREN, ")", "end", "'if' condition");
3095
3096 const Identifier* unused = 0;
3097 m_immediateParentAllowsFunctionDeclarationInStatement = true;
3098 TreeStatement trueBlock = parseStatement(context, unused);
3099 failIfFalse(trueBlock, "Expected a statement as the body of an if block");
3100
3101 if (!match(ELSE))
3102 return context.createIfStatement(ifLocation, condition, trueBlock, 0, start, end);
3103
3104 Vector<TreeExpression> exprStack;
3105 Vector<std::pair<int, int>> posStack;
3106 Vector<JSTokenLocation> tokenLocationStack;
3107 Vector<TreeStatement> statementStack;
3108 bool trailingElse = false;
3109 do {
3110 JSTokenLocation tempLocation = tokenLocation();
3111 next();
3112 if (!match(IF)) {
3113 const Identifier* unused = 0;
3114 m_immediateParentAllowsFunctionDeclarationInStatement = true;
3115 TreeStatement block = parseStatement(context, unused);
3116 failIfFalse(block, "Expected a statement as the body of an else block");
3117 statementStack.append(block);
3118 trailingElse = true;
3119 break;
3120 }
3121 int innerStart = tokenLine();
3122 next();
3123
3124 handleProductionOrFail2(OPENPAREN, "(", "start", "'if' condition");
3125
3126 TreeExpression innerCondition = parseExpression(context);
3127 failIfFalse(innerCondition, "Expected a expression as the condition for an if statement");
3128 recordPauseLocation(context.breakpointLocation(innerCondition));
3129 int innerEnd = tokenLine();
3130 handleProductionOrFail2(CLOSEPAREN, ")", "end", "'if' condition");
3131 const Identifier* unused = 0;
3132 m_immediateParentAllowsFunctionDeclarationInStatement = true;
3133 TreeStatement innerTrueBlock = parseStatement(context, unused);
3134 failIfFalse(innerTrueBlock, "Expected a statement as the body of an if block");
3135 tokenLocationStack.append(tempLocation);
3136 exprStack.append(innerCondition);
3137 posStack.append(std::make_pair(innerStart, innerEnd));
3138 statementStack.append(innerTrueBlock);
3139 } while (match(ELSE));
3140
3141 if (!trailingElse) {
3142 TreeExpression condition = exprStack.last();
3143 exprStack.removeLast();
3144 TreeStatement trueBlock = statementStack.last();
3145 statementStack.removeLast();
3146 std::pair<int, int> pos = posStack.last();
3147 posStack.removeLast();
3148 JSTokenLocation elseLocation = tokenLocationStack.last();
3149 tokenLocationStack.removeLast();
3150 TreeStatement ifStatement = context.createIfStatement(elseLocation, condition, trueBlock, 0, pos.first, pos.second);
3151 context.setEndOffset(ifStatement, context.endOffset(trueBlock));
3152 statementStack.append(ifStatement);
3153 }
3154
3155 while (!exprStack.isEmpty()) {
3156 TreeExpression condition = exprStack.last();
3157 exprStack.removeLast();
3158 TreeStatement falseBlock = statementStack.last();
3159 statementStack.removeLast();
3160 TreeStatement trueBlock = statementStack.last();
3161 statementStack.removeLast();
3162 std::pair<int, int> pos = posStack.last();
3163 posStack.removeLast();
3164 JSTokenLocation elseLocation = tokenLocationStack.last();
3165 tokenLocationStack.removeLast();
3166 TreeStatement ifStatement = context.createIfStatement(elseLocation, condition, trueBlock, falseBlock, pos.first, pos.second);
3167 context.setEndOffset(ifStatement, context.endOffset(falseBlock));
3168 statementStack.append(ifStatement);
3169 }
3170
3171 return context.createIfStatement(ifLocation, condition, trueBlock, statementStack.last(), start, end);
3172}
3173
3174template <typename LexerType>
3175template <class TreeBuilder> typename TreeBuilder::ModuleName Parser<LexerType>::parseModuleName(TreeBuilder& context)
3176{
3177 // ModuleName (ModuleSpecifier in the spec) represents the module name imported by the script.
3178 // http://www.ecma-international.org/ecma-262/6.0/#sec-imports
3179 // http://www.ecma-international.org/ecma-262/6.0/#sec-exports
3180 JSTokenLocation specifierLocation(tokenLocation());
3181 failIfFalse(match(STRING), "Imported modules names must be string literals");
3182 const Identifier* moduleName = m_token.m_data.ident;
3183 next();
3184 return context.createModuleName(specifierLocation, *moduleName);
3185}
3186
3187template <typename LexerType>
3188template <class TreeBuilder> typename TreeBuilder::ImportSpecifier Parser<LexerType>::parseImportClauseItem(TreeBuilder& context, ImportSpecifierType specifierType)
3189{
3190 // Produced node is the item of the ImportClause.
3191 // That is the ImportSpecifier, ImportedDefaultBinding or NameSpaceImport.
3192 // http://www.ecma-international.org/ecma-262/6.0/#sec-imports
3193 JSTokenLocation specifierLocation(tokenLocation());
3194 JSToken localNameToken;
3195 const Identifier* importedName = nullptr;
3196 const Identifier* localName = nullptr;
3197
3198 switch (specifierType) {
3199 case ImportSpecifierType::NamespaceImport: {
3200 // NameSpaceImport :
3201 // * as ImportedBinding
3202 // e.g.
3203 // * as namespace
3204 ASSERT(match(TIMES));
3205 importedName = &m_vm->propertyNames->timesIdentifier;
3206 next();
3207
3208 failIfFalse(matchContextualKeyword(m_vm->propertyNames->as), "Expected 'as' before imported binding name");
3209 next();
3210
3211 failIfFalse(matchSpecIdentifier(), "Expected a variable name for the import declaration");
3212 localNameToken = m_token;
3213 localName = m_token.m_data.ident;
3214 next();
3215 break;
3216 }
3217
3218 case ImportSpecifierType::NamedImport: {
3219 // ImportSpecifier :
3220 // ImportedBinding
3221 // IdentifierName as ImportedBinding
3222 // e.g.
3223 // A
3224 // A as B
3225 ASSERT(matchIdentifierOrKeyword());
3226 localNameToken = m_token;
3227 localName = m_token.m_data.ident;
3228 importedName = localName;
3229 next();
3230
3231 if (matchContextualKeyword(m_vm->propertyNames->as)) {
3232 next();
3233 failIfFalse(matchSpecIdentifier(), "Expected a variable name for the import declaration");
3234 localNameToken = m_token;
3235 localName = m_token.m_data.ident;
3236 next();
3237 }
3238 break;
3239 }
3240
3241 case ImportSpecifierType::DefaultImport: {
3242 // ImportedDefaultBinding :
3243 // ImportedBinding
3244 ASSERT(matchSpecIdentifier());
3245 localNameToken = m_token;
3246 localName = m_token.m_data.ident;
3247 importedName = &m_vm->propertyNames->defaultKeyword;
3248 next();
3249 break;
3250 }
3251 }
3252
3253 semanticFailIfTrue(localNameToken.m_type == AWAIT, "Cannot use 'await' as an imported binding name");
3254 semanticFailIfTrue(localNameToken.m_type & KeywordTokenFlag, "Cannot use keyword as imported binding name");
3255 DeclarationResultMask declarationResult = declareVariable(localName, DeclarationType::ConstDeclaration, (specifierType == ImportSpecifierType::NamespaceImport) ? DeclarationImportType::ImportedNamespace : DeclarationImportType::Imported);
3256 if (declarationResult != DeclarationResult::Valid) {
3257 failIfTrueIfStrict(declarationResult & DeclarationResult::InvalidStrictMode, "Cannot declare an imported binding named ", localName->impl(), " in strict mode");
3258 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
3259 internalFailWithMessage(false, "Cannot declare an imported binding name twice: '", localName->impl(), "'");
3260 }
3261
3262 return context.createImportSpecifier(specifierLocation, *importedName, *localName);
3263}
3264
3265template <typename LexerType>
3266template <class TreeBuilder> TreeStatement Parser<LexerType>::parseImportDeclaration(TreeBuilder& context)
3267{
3268 // http://www.ecma-international.org/ecma-262/6.0/#sec-imports
3269 ASSERT(match(IMPORT));
3270 JSTokenLocation importLocation(tokenLocation());
3271 next();
3272
3273 auto specifierList = context.createImportSpecifierList();
3274
3275 if (match(STRING)) {
3276 // import ModuleSpecifier ;
3277 auto moduleName = parseModuleName(context);
3278 failIfFalse(moduleName, "Cannot parse the module name");
3279 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted import declaration");
3280 return context.createImportDeclaration(importLocation, specifierList, moduleName);
3281 }
3282
3283 bool isFinishedParsingImport = false;
3284 if (matchSpecIdentifier()) {
3285 // ImportedDefaultBinding :
3286 // ImportedBinding
3287 auto specifier = parseImportClauseItem(context, ImportSpecifierType::DefaultImport);
3288 failIfFalse(specifier, "Cannot parse the default import");
3289 context.appendImportSpecifier(specifierList, specifier);
3290 if (match(COMMA))
3291 next();
3292 else
3293 isFinishedParsingImport = true;
3294 }
3295
3296 if (!isFinishedParsingImport) {
3297 if (match(TIMES)) {
3298 // import NameSpaceImport FromClause ;
3299 auto specifier = parseImportClauseItem(context, ImportSpecifierType::NamespaceImport);
3300 failIfFalse(specifier, "Cannot parse the namespace import");
3301 context.appendImportSpecifier(specifierList, specifier);
3302 } else if (match(OPENBRACE)) {
3303 // NamedImports :
3304 // { }
3305 // { ImportsList }
3306 // { ImportsList , }
3307 next();
3308
3309 while (!match(CLOSEBRACE)) {
3310 failIfFalse(matchIdentifierOrKeyword(), "Expected an imported name for the import declaration");
3311 auto specifier = parseImportClauseItem(context, ImportSpecifierType::NamedImport);
3312 failIfFalse(specifier, "Cannot parse the named import");
3313 context.appendImportSpecifier(specifierList, specifier);
3314 if (!consume(COMMA))
3315 break;
3316 }
3317 handleProductionOrFail2(CLOSEBRACE, "}", "end", "import list");
3318 } else
3319 failWithMessage("Expected namespace import or import list");
3320 }
3321
3322 // FromClause :
3323 // from ModuleSpecifier
3324
3325 failIfFalse(matchContextualKeyword(m_vm->propertyNames->from), "Expected 'from' before imported module name");
3326 next();
3327
3328 auto moduleName = parseModuleName(context);
3329 failIfFalse(moduleName, "Cannot parse the module name");
3330 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted import declaration");
3331
3332 return context.createImportDeclaration(importLocation, specifierList, moduleName);
3333}
3334
3335template <typename LexerType>
3336template <class TreeBuilder> typename TreeBuilder::ExportSpecifier Parser<LexerType>::parseExportSpecifier(TreeBuilder& context, Vector<std::pair<const Identifier*, const Identifier*>>& maybeExportedLocalNames, bool& hasKeywordForLocalBindings)
3337{
3338 // ExportSpecifier :
3339 // IdentifierName
3340 // IdentifierName as IdentifierName
3341 // http://www.ecma-international.org/ecma-262/6.0/#sec-exports
3342 ASSERT(matchIdentifierOrKeyword());
3343 JSTokenLocation specifierLocation(tokenLocation());
3344 if (m_token.m_type & KeywordTokenFlag)
3345 hasKeywordForLocalBindings = true;
3346 const Identifier* localName = m_token.m_data.ident;
3347 const Identifier* exportedName = localName;
3348 next();
3349
3350 if (matchContextualKeyword(m_vm->propertyNames->as)) {
3351 next();
3352 failIfFalse(matchIdentifierOrKeyword(), "Expected an exported name for the export declaration");
3353 exportedName = m_token.m_data.ident;
3354 next();
3355 }
3356
3357 semanticFailIfFalse(exportName(*exportedName), "Cannot export a duplicate name '", exportedName->impl(), "'");
3358 maybeExportedLocalNames.append(std::make_pair(localName, exportedName));
3359 return context.createExportSpecifier(specifierLocation, *localName, *exportedName);
3360}
3361
3362template <typename LexerType>
3363template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExportDeclaration(TreeBuilder& context)
3364{
3365 // http://www.ecma-international.org/ecma-262/6.0/#sec-exports
3366 ASSERT(match(EXPORT));
3367 JSTokenLocation exportLocation(tokenLocation());
3368 next();
3369
3370 switch (m_token.m_type) {
3371 case TIMES: {
3372 // export * FromClause ;
3373 next();
3374
3375 failIfFalse(matchContextualKeyword(m_vm->propertyNames->from), "Expected 'from' before exported module name");
3376 next();
3377 auto moduleName = parseModuleName(context);
3378 failIfFalse(moduleName, "Cannot parse the 'from' clause");
3379 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted export declaration");
3380
3381 return context.createExportAllDeclaration(exportLocation, moduleName);
3382 }
3383
3384 case DEFAULT: {
3385 // export default HoistableDeclaration[Default]
3386 // export default ClassDeclaration[Default]
3387 // export default [lookahead not-in {function, class}] AssignmentExpression[In] ;
3388
3389 next();
3390
3391 TreeStatement result = 0;
3392 bool isFunctionOrClassDeclaration = false;
3393 const Identifier* localName = nullptr;
3394
3395 bool startsWithFunction = match(FUNCTION);
3396 if (startsWithFunction || match(CLASSTOKEN)) {
3397 SavePoint savePoint = createSavePoint();
3398 isFunctionOrClassDeclaration = true;
3399 next();
3400
3401 // ES6 Generators
3402 if (startsWithFunction && match(TIMES))
3403 next();
3404 if (match(IDENT))
3405 localName = m_token.m_data.ident;
3406 restoreSavePoint(savePoint);
3407 } else if (matchContextualKeyword(m_vm->propertyNames->async)) {
3408 SavePoint savePoint = createSavePoint();
3409 next();
3410 if (match(FUNCTION) && !m_lexer->hasLineTerminatorBeforeToken()) {
3411 next();
3412 if (match(IDENT))
3413 localName = m_token.m_data.ident;
3414 isFunctionOrClassDeclaration = true;
3415 }
3416 restoreSavePoint(savePoint);
3417 }
3418
3419 if (!localName)
3420 localName = &m_vm->propertyNames->starDefaultPrivateName;
3421
3422 if (isFunctionOrClassDeclaration) {
3423 if (startsWithFunction) {
3424 ASSERT(match(FUNCTION));
3425 DepthManager statementDepth(&m_statementDepth);
3426 m_statementDepth = 1;
3427 result = parseFunctionDeclaration(context, ExportType::NotExported, DeclarationDefaultContext::ExportDefault);
3428 } else if (match(CLASSTOKEN)) {
3429 result = parseClassDeclaration(context, ExportType::NotExported, DeclarationDefaultContext::ExportDefault);
3430 } else {
3431 ASSERT(matchContextualKeyword(m_vm->propertyNames->async));
3432 next();
3433 DepthManager statementDepth(&m_statementDepth);
3434 m_statementDepth = 1;
3435 result = parseAsyncFunctionDeclaration(context, ExportType::NotExported, DeclarationDefaultContext::ExportDefault);
3436 }
3437 } else {
3438 // export default expr;
3439 //
3440 // It should be treated as the same to the following.
3441 //
3442 // const *default* = expr;
3443 // export { *default* as default }
3444 //
3445 // In the above example, *default* is the invisible variable to the users.
3446 // We use the private symbol to represent the name of this variable.
3447 JSTokenLocation location(tokenLocation());
3448 JSTextPosition start = tokenStartPosition();
3449 TreeExpression expression = parseAssignmentExpression(context);
3450 failIfFalse(expression, "Cannot parse expression");
3451
3452 DeclarationResultMask declarationResult = declareVariable(&m_vm->propertyNames->starDefaultPrivateName, DeclarationType::ConstDeclaration);
3453 if (declarationResult & DeclarationResult::InvalidDuplicateDeclaration)
3454 internalFailWithMessage(false, "Only one 'default' export is allowed");
3455
3456 TreeExpression assignment = context.createAssignResolve(location, m_vm->propertyNames->starDefaultPrivateName, expression, start, start, tokenEndPosition(), AssignmentContext::ConstDeclarationStatement);
3457 result = context.createExprStatement(location, assignment, start, tokenEndPosition());
3458 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted export declaration");
3459 }
3460 failIfFalse(result, "Cannot parse the declaration");
3461
3462 semanticFailIfFalse(exportName(m_vm->propertyNames->defaultKeyword), "Only one 'default' export is allowed");
3463 m_moduleScopeData->exportBinding(*localName, m_vm->propertyNames->defaultKeyword);
3464 return context.createExportDefaultDeclaration(exportLocation, result, *localName);
3465 }
3466
3467 case OPENBRACE: {
3468 // export ExportClause FromClause ;
3469 // export ExportClause ;
3470 //
3471 // ExportClause :
3472 // { }
3473 // { ExportsList }
3474 // { ExportsList , }
3475 //
3476 // ExportsList :
3477 // ExportSpecifier
3478 // ExportsList , ExportSpecifier
3479
3480 next();
3481
3482 auto specifierList = context.createExportSpecifierList();
3483 Vector<std::pair<const Identifier*, const Identifier*>> maybeExportedLocalNames;
3484
3485 bool hasKeywordForLocalBindings = false;
3486 while (!match(CLOSEBRACE)) {
3487 failIfFalse(matchIdentifierOrKeyword(), "Expected a variable name for the export declaration");
3488 auto specifier = parseExportSpecifier(context, maybeExportedLocalNames, hasKeywordForLocalBindings);
3489 failIfFalse(specifier, "Cannot parse the named export");
3490 context.appendExportSpecifier(specifierList, specifier);
3491 if (!consume(COMMA))
3492 break;
3493 }
3494 handleProductionOrFail2(CLOSEBRACE, "}", "end", "export list");
3495
3496 typename TreeBuilder::ModuleName moduleName = 0;
3497 if (matchContextualKeyword(m_vm->propertyNames->from)) {
3498 next();
3499 moduleName = parseModuleName(context);
3500 failIfFalse(moduleName, "Cannot parse the 'from' clause");
3501 }
3502 failIfFalse(autoSemiColon(), "Expected a ';' following a targeted export declaration");
3503
3504 if (!moduleName) {
3505 semanticFailIfTrue(hasKeywordForLocalBindings, "Cannot use keyword as exported variable name");
3506 // Since this export declaration does not have module specifier part, it exports the local bindings.
3507 // While the export declaration with module specifier does not have any effect on the current module's scope,
3508 // the export named declaration without module specifier references the local binding names.
3509 // For example,
3510 // export { A, B, C as D } from "mod"
3511 // does not have effect on the current module's scope. But,
3512 // export { A, B, C as D }
3513 // will reference the current module's bindings.
3514 for (const auto& pair : maybeExportedLocalNames) {
3515 const Identifier* localName = pair.first;
3516 const Identifier* exportedName = pair.second;
3517 m_moduleScopeData->exportBinding(*localName, *exportedName);
3518 }
3519 }
3520
3521 return context.createExportNamedDeclaration(exportLocation, specifierList, moduleName);
3522 }
3523
3524 default: {
3525 // export VariableStatement
3526 // export Declaration
3527 TreeStatement result = 0;
3528 switch (m_token.m_type) {
3529 case VAR:
3530 result = parseVariableDeclaration(context, DeclarationType::VarDeclaration, ExportType::Exported);
3531 break;
3532
3533 case CONSTTOKEN:
3534 result = parseVariableDeclaration(context, DeclarationType::ConstDeclaration, ExportType::Exported);
3535 break;
3536
3537 case LET:
3538 result = parseVariableDeclaration(context, DeclarationType::LetDeclaration, ExportType::Exported);
3539 break;
3540
3541 case FUNCTION: {
3542 DepthManager statementDepth(&m_statementDepth);
3543 m_statementDepth = 1;
3544 result = parseFunctionDeclaration(context, ExportType::Exported);
3545 break;
3546 }
3547
3548 case CLASSTOKEN:
3549 result = parseClassDeclaration(context, ExportType::Exported);
3550 break;
3551
3552 case IDENT:
3553 if (*m_token.m_data.ident == m_vm->propertyNames->async && !m_token.m_data.escaped) {
3554 next();
3555 semanticFailIfFalse(match(FUNCTION) && !m_lexer->hasLineTerminatorBeforeToken(), "Expected 'function' keyword following 'async' keyword with no preceding line terminator");
3556 DepthManager statementDepth(&m_statementDepth);
3557 m_statementDepth = 1;
3558 result = parseAsyncFunctionDeclaration(context, ExportType::Exported);
3559 break;
3560 }
3561 FALLTHROUGH;
3562 default:
3563 failWithMessage("Expected either a declaration or a variable statement");
3564 break;
3565 }
3566
3567 failIfFalse(result, "Cannot parse the declaration");
3568 return context.createExportLocalDeclaration(exportLocation, result);
3569 }
3570 }
3571
3572 RELEASE_ASSERT_NOT_REACHED();
3573 return 0;
3574}
3575
3576template <typename LexerType>
3577template <class TreeBuilder> TreeExpression Parser<LexerType>::parseExpression(TreeBuilder& context)
3578{
3579 failIfStackOverflow();
3580 JSTokenLocation location(tokenLocation());
3581 TreeExpression node = parseAssignmentExpression(context);
3582 failIfFalse(node, "Cannot parse expression");
3583 context.setEndOffset(node, m_lastTokenEndPosition.offset);
3584 if (!match(COMMA))
3585 return node;
3586 next();
3587 m_parserState.nonTrivialExpressionCount++;
3588 m_parserState.nonLHSCount++;
3589 TreeExpression right = parseAssignmentExpression(context);
3590 failIfFalse(right, "Cannot parse expression in a comma expression");
3591 context.setEndOffset(right, m_lastTokenEndPosition.offset);
3592 typename TreeBuilder::Comma head = context.createCommaExpr(location, node);
3593 typename TreeBuilder::Comma tail = context.appendToCommaExpr(location, head, head, right);
3594 while (match(COMMA)) {
3595 next(TreeBuilder::DontBuildStrings);
3596 right = parseAssignmentExpression(context);
3597 failIfFalse(right, "Cannot parse expression in a comma expression");
3598 context.setEndOffset(right, m_lastTokenEndPosition.offset);
3599 tail = context.appendToCommaExpr(location, head, tail, right);
3600 }
3601 context.setEndOffset(head, m_lastTokenEndPosition.offset);
3602 return head;
3603}
3604
3605template <typename LexerType>
3606template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpressionOrPropagateErrorClass(TreeBuilder& context)
3607{
3608 ExpressionErrorClassifier classifier(this);
3609 auto assignment = parseAssignmentExpression(context, classifier);
3610 if (!assignment)
3611 classifier.propagateExpressionErrorClass();
3612 return assignment;
3613}
3614
3615template <typename LexerType>
3616template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context)
3617{
3618 ExpressionErrorClassifier classifier(this);
3619 return parseAssignmentExpression(context, classifier);
3620}
3621
3622
3623template <typename LexerType>
3624template <typename TreeBuilder> NEVER_INLINE const char* Parser<LexerType>::metaPropertyName(TreeBuilder& context, TreeExpression expr)
3625{
3626 if (context.isNewTarget(expr))
3627 return "new.target";
3628 if (context.isImportMeta(expr))
3629 return "import.meta";
3630 RELEASE_ASSERT_NOT_REACHED();
3631 return "error";
3632}
3633
3634template <typename LexerType>
3635template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context, ExpressionErrorClassifier& classifier)
3636{
3637 ASSERT(!hasError());
3638
3639 failIfStackOverflow();
3640
3641 if (match(YIELD) && !isYIELDMaskedAsIDENT(currentScope()->isGenerator()))
3642 return parseYieldExpression(context);
3643
3644 JSTextPosition start = tokenStartPosition();
3645 JSTokenLocation location(tokenLocation());
3646 int initialAssignmentCount = m_parserState.assignmentCount;
3647 int initialNonLHSCount = m_parserState.nonLHSCount;
3648 bool maybeAssignmentPattern = match(OPENBRACE) || match(OPENBRACKET);
3649 bool wasOpenParen = match(OPENPAREN);
3650 // Do not use matchSpecIdentifier() here since it is slower than isIdentifierOrKeyword.
3651 // Whether spec identifier is will be validated by isArrowFunctionParameters().
3652 bool wasIdentifierOrKeyword = isIdentifierOrKeyword(m_token);
3653 bool maybeValidArrowFunctionStart = wasOpenParen || wasIdentifierOrKeyword;
3654 SavePoint savePoint = createSavePoint();
3655 size_t usedVariablesSize = 0;
3656
3657 if (wasOpenParen) {
3658 usedVariablesSize = currentScope()->currentUsedVariablesSize();
3659 currentScope()->pushUsedVariableSet();
3660 }
3661
3662 TreeExpression lhs = parseConditionalExpression(context);
3663
3664 if (maybeValidArrowFunctionStart && !match(EOFTOK)) {
3665 bool isArrowFunctionToken = match(ARROWFUNCTION);
3666 if (!lhs || isArrowFunctionToken) {
3667 SavePointWithError errorRestorationSavePoint = createSavePointForError();
3668 restoreSavePoint(savePoint);
3669 bool isAsyncArrow = false;
3670 if (UNLIKELY(classifier.indicatesPossibleAsyncArrowFunction())) {
3671 if (matchContextualKeyword(m_vm->propertyNames->async)) {
3672 next();
3673 isAsyncArrow = !m_lexer->hasLineTerminatorBeforeToken();
3674 }
3675 }
3676 if (isArrowFunctionParameters()) {
3677 if (wasOpenParen)
3678 currentScope()->revertToPreviousUsedVariables(usedVariablesSize);
3679 return parseArrowFunctionExpression(context, isAsyncArrow);
3680 }
3681 if (isArrowFunctionToken)
3682 propagateError();
3683 restoreSavePointWithError(errorRestorationSavePoint);
3684 if (isArrowFunctionToken)
3685 failDueToUnexpectedToken();
3686 }
3687 }
3688
3689 if (!lhs && (!maybeAssignmentPattern || !classifier.indicatesPossiblePattern()))
3690 propagateError();
3691
3692 if (maybeAssignmentPattern && (!lhs || (context.isObjectOrArrayLiteral(lhs) && match(EQUAL)))) {
3693 SavePointWithError expressionErrorLocation = createSavePointForError();
3694 restoreSavePoint(savePoint);
3695 auto pattern = tryParseDestructuringPatternExpression(context, AssignmentContext::AssignmentExpression);
3696 if (classifier.indicatesPossiblePattern() && (!pattern || !match(EQUAL))) {
3697 restoreSavePointWithError(expressionErrorLocation);
3698 return 0;
3699 }
3700 failIfFalse(pattern, "Cannot parse assignment pattern");
3701 consumeOrFail(EQUAL, "Expected '=' following assignment pattern");
3702 auto rhs = parseAssignmentExpression(context);
3703 if (!rhs)
3704 propagateError();
3705 return context.createDestructuringAssignment(location, pattern, rhs);
3706 }
3707
3708 failIfFalse(lhs, "Cannot parse expression");
3709 if (initialNonLHSCount != m_parserState.nonLHSCount) {
3710 if (m_token.m_type >= EQUAL && m_token.m_type <= OREQUAL)
3711 semanticFail("Left hand side of operator '", getToken(), "' must be a reference");
3712
3713 return lhs;
3714 }
3715
3716 int assignmentStack = 0;
3717 Operator op;
3718 bool hadAssignment = false;
3719 while (true) {
3720 switch (m_token.m_type) {
3721 case EQUAL: op = OpEqual; break;
3722 case PLUSEQUAL: op = OpPlusEq; break;
3723 case MINUSEQUAL: op = OpMinusEq; break;
3724 case MULTEQUAL: op = OpMultEq; break;
3725 case DIVEQUAL: op = OpDivEq; break;
3726 case LSHIFTEQUAL: op = OpLShift; break;
3727 case RSHIFTEQUAL: op = OpRShift; break;
3728 case URSHIFTEQUAL: op = OpURShift; break;
3729 case ANDEQUAL: op = OpAndEq; break;
3730 case XOREQUAL: op = OpXOrEq; break;
3731 case OREQUAL: op = OpOrEq; break;
3732 case MODEQUAL: op = OpModEq; break;
3733 case POWEQUAL: op = OpPowEq; break;
3734 default:
3735 goto end;
3736 }
3737 m_parserState.nonTrivialExpressionCount++;
3738 hadAssignment = true;
3739 if (UNLIKELY(context.isMetaProperty(lhs)))
3740 internalFailWithMessage(false, metaPropertyName(context, lhs), " can't be the left hand side of an assignment expression");
3741 context.assignmentStackAppend(assignmentStack, lhs, start, tokenStartPosition(), m_parserState.assignmentCount, op);
3742 start = tokenStartPosition();
3743 m_parserState.assignmentCount++;
3744 next(TreeBuilder::DontBuildStrings);
3745 if (strictMode() && m_parserState.lastIdentifier && context.isResolve(lhs)) {
3746 failIfTrueIfStrict(m_vm->propertyNames->eval == *m_parserState.lastIdentifier, "Cannot modify 'eval' in strict mode");
3747 failIfTrueIfStrict(m_vm->propertyNames->arguments == *m_parserState.lastIdentifier, "Cannot modify 'arguments' in strict mode");
3748 m_parserState.lastIdentifier = 0;
3749 }
3750 lhs = parseAssignmentExpression(context);
3751 failIfFalse(lhs, "Cannot parse the right hand side of an assignment expression");
3752 if (initialNonLHSCount != m_parserState.nonLHSCount) {
3753 if (m_token.m_type >= EQUAL && m_token.m_type <= OREQUAL)
3754 semanticFail("Left hand side of operator '", getToken(), "' must be a reference");
3755 break;
3756 }
3757 }
3758end:
3759 if (hadAssignment)
3760 m_parserState.nonLHSCount++;
3761
3762 if (!TreeBuilder::CreatesAST)
3763 return lhs;
3764
3765 while (assignmentStack)
3766 lhs = context.createAssignment(location, assignmentStack, lhs, initialAssignmentCount, m_parserState.assignmentCount, lastTokenEndPosition());
3767
3768 return lhs;
3769}
3770
3771template <typename LexerType>
3772template <class TreeBuilder> TreeExpression Parser<LexerType>::parseYieldExpression(TreeBuilder& context)
3773{
3774 // YieldExpression[In] :
3775 // yield
3776 // yield [no LineTerminator here] AssignmentExpression[?In, Yield]
3777 // yield [no LineTerminator here] * AssignmentExpression[?In, Yield]
3778
3779 // http://ecma-international.org/ecma-262/6.0/#sec-generator-function-definitions
3780 failIfFalse(currentScope()->isGenerator() && !currentScope()->isArrowFunctionBoundary(), "Cannot use yield expression out of generator");
3781
3782 // http://ecma-international.org/ecma-262/6.0/#sec-generator-function-definitions-static-semantics-early-errors
3783 failIfTrue(m_parserState.functionParsePhase == FunctionParsePhase::Parameters, "Cannot use yield expression within parameters");
3784
3785 JSTokenLocation location(tokenLocation());
3786 JSTextPosition divotStart = tokenStartPosition();
3787 ASSERT(match(YIELD));
3788 SavePoint savePoint = createSavePoint();
3789 next();
3790 if (m_lexer->hasLineTerminatorBeforeToken())
3791 return context.createYield(location);
3792
3793 bool delegate = consume(TIMES);
3794 JSTextPosition argumentStart = tokenStartPosition();
3795 TreeExpression argument = parseAssignmentExpression(context);
3796 if (!argument) {
3797 restoreSavePoint(savePoint);
3798 next();
3799 return context.createYield(location);
3800 }
3801 return context.createYield(location, argument, delegate, divotStart, argumentStart, lastTokenEndPosition());
3802}
3803
3804template <typename LexerType>
3805template <class TreeBuilder> TreeExpression Parser<LexerType>::parseAwaitExpression(TreeBuilder& context)
3806{
3807 ASSERT(match(AWAIT));
3808 ASSERT(currentScope()->isAsyncFunction());
3809 failIfTrue(m_parserState.functionParsePhase == FunctionParsePhase::Parameters, "Cannot use await expression within parameters");
3810 JSTokenLocation location(tokenLocation());
3811 JSTextPosition divotStart = tokenStartPosition();
3812 next();
3813 JSTextPosition argumentStart = tokenStartPosition();
3814 ExpressionErrorClassifier classifier(this);
3815 TreeExpression argument = parseUnaryExpression(context);
3816 failIfFalse(argument, "Failed to parse await expression");
3817 return context.createAwait(location, argument, divotStart, argumentStart, lastTokenEndPosition());
3818}
3819
3820template <typename LexerType>
3821template <class TreeBuilder> TreeExpression Parser<LexerType>::parseConditionalExpression(TreeBuilder& context)
3822{
3823 JSTokenLocation location(tokenLocation());
3824 TreeExpression cond = parseBinaryExpression(context);
3825 failIfFalse(cond, "Cannot parse expression");
3826 if (!match(QUESTION))
3827 return cond;
3828 m_parserState.nonTrivialExpressionCount++;
3829 m_parserState.nonLHSCount++;
3830 next(TreeBuilder::DontBuildStrings);
3831 TreeExpression lhs = parseAssignmentExpression(context);
3832 failIfFalse(lhs, "Cannot parse left hand side of ternary operator");
3833 context.setEndOffset(lhs, m_lastTokenEndPosition.offset);
3834 consumeOrFailWithFlags(COLON, TreeBuilder::DontBuildStrings, "Expected ':' in ternary operator");
3835
3836 TreeExpression rhs = parseAssignmentExpression(context);
3837 failIfFalse(rhs, "Cannot parse right hand side of ternary operator");
3838 context.setEndOffset(rhs, m_lastTokenEndPosition.offset);
3839 return context.createConditionalExpr(location, cond, lhs, rhs);
3840}
3841
3842ALWAYS_INLINE static bool isUnaryOpExcludingUpdateOp(JSTokenType token)
3843{
3844 if (isUpdateOp(token))
3845 return false;
3846 return isUnaryOp(token);
3847}
3848
3849template <typename LexerType>
3850int Parser<LexerType>::isBinaryOperator(JSTokenType token)
3851{
3852 if (m_allowsIn)
3853 return token & (BinaryOpTokenPrecedenceMask << BinaryOpTokenAllowsInPrecedenceAdditionalShift);
3854 return token & BinaryOpTokenPrecedenceMask;
3855}
3856
3857template <typename LexerType>
3858template <class TreeBuilder> TreeExpression Parser<LexerType>::parseBinaryExpression(TreeBuilder& context)
3859{
3860 int operandStackDepth = 0;
3861 int operatorStackDepth = 0;
3862 typename TreeBuilder::BinaryExprContext binaryExprContext(context);
3863 JSTokenLocation location(tokenLocation());
3864 while (true) {
3865 JSTextPosition exprStart = tokenStartPosition();
3866 int initialAssignments = m_parserState.assignmentCount;
3867 JSTokenType leadingTokenTypeForUnaryExpression = m_token.m_type;
3868 TreeExpression current = parseUnaryExpression(context);
3869 failIfFalse(current, "Cannot parse expression");
3870
3871 context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEndPosition(), lastTokenEndPosition(), initialAssignments != m_parserState.assignmentCount);
3872
3873 // 12.6 https://tc39.github.io/ecma262/#sec-exp-operator
3874 // ExponentiationExpresion is described as follows.
3875 //
3876 // ExponentiationExpression[Yield]:
3877 // UnaryExpression[?Yield]
3878 // UpdateExpression[?Yield] ** ExponentiationExpression[?Yield]
3879 //
3880 // As we can see, the left hand side of the ExponentiationExpression is UpdateExpression, not UnaryExpression.
3881 // So placing UnaryExpression not included in UpdateExpression here is a syntax error.
3882 // This is intentional. For example, if UnaryExpression is allowed, we can have the code like `-x**y`.
3883 // But this is confusing: `-(x**y)` OR `(-x)**y`, which interpretation is correct?
3884 // To avoid this problem, ECMA262 makes unparenthesized exponentiation expression as operand of unary operators an early error.
3885 // More rationale: https://mail.mozilla.org/pipermail/es-discuss/2015-September/044232.html
3886 //
3887 // Here, we guarantee that the left hand side of this expression is not unary expression by checking the leading operator of the parseUnaryExpression.
3888 // This check just works. Let's consider the example,
3889 // y <> -x ** z
3890 // ^
3891 // Check this.
3892 // If the binary operator <> has higher precedence than one of "**", this check does not work.
3893 // But it's OK for ** because the operator "**" has the highest operator precedence in the binary operators.
3894 failIfTrue(match(POW) && isUnaryOpExcludingUpdateOp(leadingTokenTypeForUnaryExpression), "Ambiguous unary expression in the left hand side of the exponentiation expression; parentheses must be used to disambiguate the expression");
3895
3896 int precedence = isBinaryOperator(m_token.m_type);
3897 if (!precedence)
3898 break;
3899 m_parserState.nonTrivialExpressionCount++;
3900 m_parserState.nonLHSCount++;
3901 int operatorToken = m_token.m_type;
3902 next(TreeBuilder::DontBuildStrings);
3903
3904 while (operatorStackDepth && context.operatorStackShouldReduce(precedence)) {
3905 ASSERT(operandStackDepth > 1);
3906
3907 typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
3908 typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
3909 context.shrinkOperandStackBy(operandStackDepth, 2);
3910 context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
3911 context.operatorStackPop(operatorStackDepth);
3912 }
3913 context.operatorStackAppend(operatorStackDepth, operatorToken, precedence);
3914 }
3915 while (operatorStackDepth) {
3916 ASSERT(operandStackDepth > 1);
3917
3918 typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
3919 typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
3920 context.shrinkOperandStackBy(operandStackDepth, 2);
3921 context.appendBinaryOperation(location, operandStackDepth, operatorStackDepth, lhs, rhs);
3922 context.operatorStackPop(operatorStackDepth);
3923 }
3924 return context.popOperandStack(operandStackDepth);
3925}
3926
3927template <typename LexerType>
3928template <class TreeBuilder> TreeProperty Parser<LexerType>::parseProperty(TreeBuilder& context, bool complete)
3929{
3930 SourceParseMode parseMode = SourceParseMode::MethodMode;
3931 bool wasIdent = false;
3932
3933 if (consume(TIMES))
3934 parseMode = SourceParseMode::GeneratorWrapperMethodMode;
3935
3936parseProperty:
3937 switch (m_token.m_type) {
3938 case IDENT:
3939 if (UNLIKELY(*m_token.m_data.ident == m_vm->propertyNames->async && !m_token.m_data.escaped)) {
3940 if (parseMode == SourceParseMode::MethodMode) {
3941 SavePoint savePoint = createSavePoint();
3942 next();
3943
3944 if (match(COLON) || match(OPENPAREN) || match(COMMA) || match(CLOSEBRACE)) {
3945 restoreSavePoint(savePoint);
3946 wasIdent = true;
3947 goto namedProperty;
3948 }
3949
3950 failIfTrue(m_lexer->hasLineTerminatorBeforeToken(), "Expected a property name following keyword 'async'");
3951 if (UNLIKELY(consume(TIMES)))
3952 parseMode = SourceParseMode::AsyncGeneratorWrapperMethodMode;
3953 else
3954 parseMode = SourceParseMode::AsyncMethodMode;
3955 goto parseProperty;
3956 }
3957 }
3958 FALLTHROUGH;
3959 case YIELD:
3960 case AWAIT:
3961 wasIdent = true;
3962 FALLTHROUGH;
3963 case STRING: {
3964namedProperty:
3965 const Identifier* ident = m_token.m_data.ident;
3966 unsigned getterOrSetterStartOffset = tokenStart();
3967 JSToken identToken = m_token;
3968
3969 if (complete || (wasIdent && !isGeneratorMethodParseMode(parseMode) && (*ident == m_vm->propertyNames->get || *ident == m_vm->propertyNames->set)))
3970 nextExpectIdentifier(LexerFlagsIgnoreReservedWords);
3971 else
3972 nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
3973
3974 if (!isGeneratorMethodParseMode(parseMode) && !isAsyncMethodParseMode(parseMode) && match(COLON)) {
3975 next();
3976 TreeExpression node = parseAssignmentExpressionOrPropagateErrorClass(context);
3977 failIfFalse(node, "Cannot parse expression for property declaration");
3978 context.setEndOffset(node, m_lexer->currentOffset());
3979 InferName inferName = ident && *ident == m_vm->propertyNames->underscoreProto ? InferName::Disallowed : InferName::Allowed;
3980 return context.createProperty(ident, node, PropertyNode::Constant, PropertyNode::Unknown, complete, SuperBinding::NotNeeded, inferName, ClassElementTag::No);
3981 }
3982
3983 if (match(OPENPAREN)) {
3984 auto method = parsePropertyMethod(context, ident, parseMode);
3985 propagateError();
3986 return context.createProperty(ident, method, PropertyNode::Constant, PropertyNode::KnownDirect, complete, SuperBinding::Needed, InferName::Allowed, ClassElementTag::No);
3987 }
3988 failIfTrue(parseMode != SourceParseMode::MethodMode, "Expected a parenthesis for argument list");
3989
3990 failIfFalse(wasIdent, "Expected an identifier as property name");
3991
3992 if (match(COMMA) || match(CLOSEBRACE)) {
3993 semanticFailureDueToKeywordCheckingToken(identToken, "shorthand property name");
3994 JSTextPosition start = tokenStartPosition();
3995 JSTokenLocation location(tokenLocation());
3996 currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident);
3997 if (currentScope()->isArrowFunction())
3998 currentScope()->setInnerArrowFunctionUsesEval();
3999 TreeExpression node = context.createResolve(location, *ident, start, lastTokenEndPosition());
4000 return context.createProperty(ident, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Shorthand), PropertyNode::KnownDirect, complete, SuperBinding::NotNeeded, InferName::Allowed, ClassElementTag::No);
4001 }
4002
4003 if (match(EQUAL)) // CoverInitializedName is exclusive to BindingPattern and AssignmentPattern
4004 classifyExpressionError(ErrorIndicatesPattern);
4005
4006 PropertyNode::Type type;
4007 if (*ident == m_vm->propertyNames->get)
4008 type = PropertyNode::Getter;
4009 else if (*ident == m_vm->propertyNames->set)
4010 type = PropertyNode::Setter;
4011 else
4012 failWithMessage("Expected a ':' following the property name '", ident->impl(), "'");
4013 return parseGetterSetter(context, complete, type, getterOrSetterStartOffset, ConstructorKind::None, ClassElementTag::No);
4014 }
4015 case DOUBLE:
4016 case INTEGER: {
4017 double propertyName = m_token.m_data.doubleValue;
4018 next();
4019
4020 if (match(OPENPAREN)) {
4021 const Identifier& ident = m_parserArena.identifierArena().makeNumericIdentifier(const_cast<VM*>(m_vm), propertyName);
4022 auto method = parsePropertyMethod(context, &ident, parseMode);
4023 propagateError();
4024 return context.createProperty(&ident, method, PropertyNode::Constant, PropertyNode::Unknown, complete, SuperBinding::Needed, InferName::Allowed, ClassElementTag::No);
4025 }
4026 failIfTrue(parseMode != SourceParseMode::MethodMode, "Expected a parenthesis for argument list");
4027
4028 consumeOrFail(COLON, "Expected ':' after property name");
4029 TreeExpression node = parseAssignmentExpression(context);
4030 failIfFalse(node, "Cannot parse expression for property declaration");
4031 context.setEndOffset(node, m_lexer->currentOffset());
4032 return context.createProperty(const_cast<VM*>(m_vm), m_parserArena, propertyName, node, PropertyNode::Constant, PropertyNode::Unknown, complete, SuperBinding::NotNeeded, ClassElementTag::No);
4033 }
4034 case OPENBRACKET: {
4035 next();
4036 auto propertyName = parseAssignmentExpression(context);
4037 failIfFalse(propertyName, "Cannot parse computed property name");
4038 handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name");
4039
4040 if (match(OPENPAREN)) {
4041 auto method = parsePropertyMethod(context, &m_vm->propertyNames->nullIdentifier, parseMode);
4042 propagateError();
4043 return context.createProperty(propertyName, method, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::KnownDirect, complete, SuperBinding::Needed, ClassElementTag::No);
4044 }
4045 failIfTrue(parseMode != SourceParseMode::MethodMode, "Expected a parenthesis for argument list");
4046
4047 consumeOrFail(COLON, "Expected ':' after property name");
4048 TreeExpression node = parseAssignmentExpression(context);
4049 failIfFalse(node, "Cannot parse expression for property declaration");
4050 context.setEndOffset(node, m_lexer->currentOffset());
4051 return context.createProperty(propertyName, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::Unknown, complete, SuperBinding::NotNeeded, ClassElementTag::No);
4052 }
4053 case DOTDOTDOT: {
4054 auto spreadLocation = m_token.m_location;
4055 auto start = m_token.m_startPosition;
4056 auto divot = m_token.m_endPosition;
4057 next();
4058 TreeExpression elem = parseAssignmentExpressionOrPropagateErrorClass(context);
4059 failIfFalse(elem, "Cannot parse subject of a spread operation");
4060 auto node = context.createObjectSpreadExpression(spreadLocation, elem, start, divot, m_lastTokenEndPosition);
4061 return context.createProperty(node, PropertyNode::Spread, PropertyNode::Unknown, complete, SuperBinding::NotNeeded, ClassElementTag::No);
4062 }
4063 default:
4064 failIfFalse(m_token.m_type & KeywordTokenFlag, "Expected a property name");
4065 wasIdent = true; // Treat keyword token as an identifier
4066 goto namedProperty;
4067 }
4068}
4069
4070template <typename LexerType>
4071template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePropertyMethod(TreeBuilder& context, const Identifier* methodName, SourceParseMode parseMode)
4072{
4073 ASSERT(isMethodParseMode(parseMode));
4074 JSTokenLocation methodLocation(tokenLocation());
4075 unsigned methodStart = tokenStart();
4076 ParserFunctionInfo<TreeBuilder> methodInfo;
4077 methodInfo.name = methodName;
4078 failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::Unnamed, parseMode, false, ConstructorKind::None, SuperBinding::Needed, methodStart, methodInfo, FunctionDefinitionType::Method)), "Cannot parse this method");
4079 return context.createMethodDefinition(methodLocation, methodInfo);
4080}
4081
4082template <typename LexerType>
4083template <class TreeBuilder> TreeProperty Parser<LexerType>::parseGetterSetter(TreeBuilder& context, bool strict, PropertyNode::Type type, unsigned getterOrSetterStartOffset,
4084 ConstructorKind constructorKind, ClassElementTag tag)
4085{
4086 const Identifier* stringPropertyName = 0;
4087 double numericPropertyName = 0;
4088 TreeExpression computedPropertyName = 0;
4089
4090 JSTokenLocation location(tokenLocation());
4091
4092 if (matchSpecIdentifier() || match(STRING) || m_token.m_type & KeywordTokenFlag) {
4093 stringPropertyName = m_token.m_data.ident;
4094 semanticFailIfTrue(tag == ClassElementTag::Static && *stringPropertyName == m_vm->propertyNames->prototype,
4095 "Cannot declare a static method named 'prototype'");
4096 semanticFailIfTrue(tag == ClassElementTag::Instance && *stringPropertyName == m_vm->propertyNames->constructor,
4097 "Cannot declare a getter or setter named 'constructor'");
4098 next();
4099 } else if (match(DOUBLE) || match(INTEGER)) {
4100 numericPropertyName = m_token.m_data.doubleValue;
4101 next();
4102 } else if (match(OPENBRACKET)) {
4103 next();
4104 computedPropertyName = parseAssignmentExpression(context);
4105 failIfFalse(computedPropertyName, "Cannot parse computed property name");
4106 handleProductionOrFail(CLOSEBRACKET, "]", "end", "computed property name");
4107 } else
4108 failDueToUnexpectedToken();
4109
4110 ParserFunctionInfo<TreeBuilder> info;
4111 if (type & PropertyNode::Getter) {
4112 failIfFalse(match(OPENPAREN), "Expected a parameter list for getter definition");
4113 failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::Unnamed, SourceParseMode::GetterMode, false, constructorKind, SuperBinding::Needed, getterOrSetterStartOffset, info, FunctionDefinitionType::Method)), "Cannot parse getter definition");
4114 } else {
4115 failIfFalse(match(OPENPAREN), "Expected a parameter list for setter definition");
4116 failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::Unnamed, SourceParseMode::SetterMode, false, constructorKind, SuperBinding::Needed, getterOrSetterStartOffset, info, FunctionDefinitionType::Method)), "Cannot parse setter definition");
4117 }
4118
4119 if (stringPropertyName)
4120 return context.createGetterOrSetterProperty(location, type, strict, stringPropertyName, info, tag);
4121
4122 if (computedPropertyName)
4123 return context.createGetterOrSetterProperty(location, static_cast<PropertyNode::Type>(type | PropertyNode::Computed), strict, computedPropertyName, info, tag);
4124
4125 return context.createGetterOrSetterProperty(const_cast<VM*>(m_vm), m_parserArena, location, type, strict, numericPropertyName, info, tag);
4126}
4127
4128template <typename LexerType>
4129template <class TreeBuilder> bool Parser<LexerType>::shouldCheckPropertyForUnderscoreProtoDuplicate(TreeBuilder& context, const TreeProperty& property)
4130{
4131 if (!context.getName(property))
4132 return false;
4133
4134 // A Constant property that is not a Computed or Shorthand Constant property.
4135 return context.getType(property) == PropertyNode::Constant;
4136}
4137
4138template <typename LexerType>
4139void Parser<LexerType>::recordPauseLocation(const JSTextPosition& position)
4140{
4141 if (LIKELY(!m_debuggerParseData))
4142 return;
4143
4144 if (position.line < 0)
4145 return;
4146
4147 m_debuggerParseData->pausePositions.appendPause(position);
4148}
4149
4150template <typename LexerType>
4151void Parser<LexerType>::recordFunctionEntryLocation(const JSTextPosition& position)
4152{
4153 if (LIKELY(!m_debuggerParseData))
4154 return;
4155
4156 m_debuggerParseData->pausePositions.appendEntry(position);
4157}
4158
4159template <typename LexerType>
4160void Parser<LexerType>::recordFunctionLeaveLocation(const JSTextPosition& position)
4161{
4162 if (LIKELY(!m_debuggerParseData))
4163 return;
4164
4165 m_debuggerParseData->pausePositions.appendLeave(position);
4166}
4167
4168template <typename LexerType>
4169template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLiteral(TreeBuilder& context)
4170{
4171 SavePoint savePoint = createSavePoint();
4172 consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings, "Expected opening '{' at the start of an object literal");
4173
4174 int oldNonLHSCount = m_parserState.nonLHSCount;
4175
4176 JSTokenLocation location(tokenLocation());
4177 if (match(CLOSEBRACE)) {
4178 next();
4179 return context.createObjectLiteral(location);
4180 }
4181
4182 TreeProperty property = parseProperty(context, false);
4183 failIfFalse(property, "Cannot parse object literal property");
4184
4185 if (context.getType(property) & (PropertyNode::Getter | PropertyNode::Setter)) {
4186 restoreSavePoint(savePoint);
4187 return parseStrictObjectLiteral(context);
4188 }
4189
4190 bool seenUnderscoreProto = false;
4191 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property))
4192 seenUnderscoreProto = *context.getName(property) == m_vm->propertyNames->underscoreProto;
4193
4194 TreePropertyList propertyList = context.createPropertyList(location, property);
4195 TreePropertyList tail = propertyList;
4196 while (match(COMMA)) {
4197 next(TreeBuilder::DontBuildStrings);
4198 if (match(CLOSEBRACE))
4199 break;
4200 JSTokenLocation propertyLocation(tokenLocation());
4201 property = parseProperty(context, false);
4202 failIfFalse(property, "Cannot parse object literal property");
4203 if (context.getType(property) & (PropertyNode::Getter | PropertyNode::Setter)) {
4204 restoreSavePoint(savePoint);
4205 return parseStrictObjectLiteral(context);
4206 }
4207 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property)) {
4208 if (*context.getName(property) == m_vm->propertyNames->underscoreProto) {
4209 semanticFailIfTrue(seenUnderscoreProto, "Attempted to redefine __proto__ property");
4210 seenUnderscoreProto = true;
4211 }
4212 }
4213 tail = context.createPropertyList(propertyLocation, property, tail);
4214 }
4215
4216 location = tokenLocation();
4217 handleProductionOrFail2(CLOSEBRACE, "}", "end", "object literal");
4218
4219 m_parserState.nonLHSCount = oldNonLHSCount;
4220
4221 return context.createObjectLiteral(location, propertyList);
4222}
4223
4224template <typename LexerType>
4225template <class TreeBuilder> TreeExpression Parser<LexerType>::parseStrictObjectLiteral(TreeBuilder& context)
4226{
4227 consumeOrFail(OPENBRACE, "Expected opening '{' at the start of an object literal");
4228
4229 int oldNonLHSCount = m_parserState.nonLHSCount;
4230
4231 JSTokenLocation location(tokenLocation());
4232 if (match(CLOSEBRACE)) {
4233 next();
4234 return context.createObjectLiteral(location);
4235 }
4236
4237 TreeProperty property = parseProperty(context, true);
4238 failIfFalse(property, "Cannot parse object literal property");
4239
4240 bool seenUnderscoreProto = false;
4241 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property))
4242 seenUnderscoreProto = *context.getName(property) == m_vm->propertyNames->underscoreProto;
4243
4244 TreePropertyList propertyList = context.createPropertyList(location, property);
4245 TreePropertyList tail = propertyList;
4246 while (match(COMMA)) {
4247 next();
4248 if (match(CLOSEBRACE))
4249 break;
4250 JSTokenLocation propertyLocation(tokenLocation());
4251 property = parseProperty(context, true);
4252 failIfFalse(property, "Cannot parse object literal property");
4253 if (shouldCheckPropertyForUnderscoreProtoDuplicate(context, property)) {
4254 if (*context.getName(property) == m_vm->propertyNames->underscoreProto) {
4255 semanticFailIfTrue(seenUnderscoreProto, "Attempted to redefine __proto__ property");
4256 seenUnderscoreProto = true;
4257 }
4258 }
4259 tail = context.createPropertyList(propertyLocation, property, tail);
4260 }
4261
4262 location = tokenLocation();
4263 handleProductionOrFail2(CLOSEBRACE, "}", "end", "object literal");
4264
4265 m_parserState.nonLHSCount = oldNonLHSCount;
4266
4267 return context.createObjectLiteral(location, propertyList);
4268}
4269
4270template <typename LexerType>
4271template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrayLiteral(TreeBuilder& context)
4272{
4273 consumeOrFailWithFlags(OPENBRACKET, TreeBuilder::DontBuildStrings, "Expected an opening '[' at the beginning of an array literal");
4274
4275 int oldNonLHSCount = m_parserState.nonLHSCount;
4276
4277 int elisions = 0;
4278 while (match(COMMA)) {
4279 next(TreeBuilder::DontBuildStrings);
4280 elisions++;
4281 }
4282 if (match(CLOSEBRACKET)) {
4283 JSTokenLocation location(tokenLocation());
4284 next(TreeBuilder::DontBuildStrings);
4285 return context.createArray(location, elisions);
4286 }
4287
4288 TreeExpression elem;
4289 if (UNLIKELY(match(DOTDOTDOT))) {
4290 auto spreadLocation = m_token.m_location;
4291 auto start = m_token.m_startPosition;
4292 auto divot = m_token.m_endPosition;
4293 next();
4294 auto spreadExpr = parseAssignmentExpressionOrPropagateErrorClass(context);
4295 failIfFalse(spreadExpr, "Cannot parse subject of a spread operation");
4296 elem = context.createSpreadExpression(spreadLocation, spreadExpr, start, divot, m_lastTokenEndPosition);
4297 } else
4298 elem = parseAssignmentExpressionOrPropagateErrorClass(context);
4299 failIfFalse(elem, "Cannot parse array literal element");
4300 typename TreeBuilder::ElementList elementList = context.createElementList(elisions, elem);
4301 typename TreeBuilder::ElementList tail = elementList;
4302 elisions = 0;
4303 while (match(COMMA)) {
4304 next(TreeBuilder::DontBuildStrings);
4305 elisions = 0;
4306
4307 while (match(COMMA)) {
4308 next();
4309 elisions++;
4310 }
4311
4312 if (match(CLOSEBRACKET)) {
4313 JSTokenLocation location(tokenLocation());
4314 next(TreeBuilder::DontBuildStrings);
4315 return context.createArray(location, elisions, elementList);
4316 }
4317 if (UNLIKELY(match(DOTDOTDOT))) {
4318 auto spreadLocation = m_token.m_location;
4319 auto start = m_token.m_startPosition;
4320 auto divot = m_token.m_endPosition;
4321 next();
4322 TreeExpression elem = parseAssignmentExpressionOrPropagateErrorClass(context);
4323 failIfFalse(elem, "Cannot parse subject of a spread operation");
4324 auto spread = context.createSpreadExpression(spreadLocation, elem, start, divot, m_lastTokenEndPosition);
4325 tail = context.createElementList(tail, elisions, spread);
4326 continue;
4327 }
4328 TreeExpression elem = parseAssignmentExpressionOrPropagateErrorClass(context);
4329 failIfFalse(elem, "Cannot parse array literal element");
4330 tail = context.createElementList(tail, elisions, elem);
4331 }
4332
4333 JSTokenLocation location(tokenLocation());
4334 if (!consume(CLOSEBRACKET)) {
4335 failIfFalse(match(DOTDOTDOT), "Expected either a closing ']' or a ',' following an array element");
4336 semanticFail("The '...' operator should come before a target expression");
4337 }
4338
4339 m_parserState.nonLHSCount = oldNonLHSCount;
4340
4341 return context.createArray(location, elementList);
4342}
4343
4344template <typename LexerType>
4345template <class TreeBuilder> TreeClassExpression Parser<LexerType>::parseClassExpression(TreeBuilder& context)
4346{
4347 ASSERT(match(CLASSTOKEN));
4348 ParserClassInfo<TreeBuilder> info;
4349 info.className = &m_vm->propertyNames->nullIdentifier;
4350 return parseClass(context, FunctionNameRequirements::None, info);
4351}
4352
4353template <typename LexerType>
4354template <class TreeBuilder> TreeExpression Parser<LexerType>::parseFunctionExpression(TreeBuilder& context)
4355{
4356 ASSERT(match(FUNCTION));
4357 JSTokenLocation location(tokenLocation());
4358 unsigned functionKeywordStart = tokenStart();
4359 next();
4360 ParserFunctionInfo<TreeBuilder> functionInfo;
4361 functionInfo.name = &m_vm->propertyNames->nullIdentifier;
4362 SourceParseMode parseMode = SourceParseMode::NormalFunctionMode;
4363 if (consume(TIMES))
4364 parseMode = SourceParseMode::GeneratorWrapperFunctionMode;
4365 failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::None, parseMode, false, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Expression)), "Cannot parse function expression");
4366 return context.createFunctionExpr(location, functionInfo);
4367}
4368
4369template <typename LexerType>
4370template <class TreeBuilder> TreeExpression Parser<LexerType>::parseAsyncFunctionExpression(TreeBuilder& context)
4371{
4372 ASSERT(match(FUNCTION));
4373 JSTokenLocation location(tokenLocation());
4374 unsigned functionKeywordStart = tokenStart();
4375 next();
4376 SourceParseMode parseMode = SourceParseMode::AsyncFunctionMode;
4377
4378 if (consume(TIMES))
4379 parseMode = SourceParseMode::AsyncGeneratorWrapperFunctionMode;
4380
4381 ParserFunctionInfo<TreeBuilder> functionInfo;
4382 functionInfo.name = &m_vm->propertyNames->nullIdentifier;
4383 failIfFalse(parseFunctionInfo(context, FunctionNameRequirements::None, parseMode, false, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Expression), parseMode == SourceParseMode::AsyncFunctionMode ? "Cannot parse async function expression" : "Cannot parse async generator function expression");
4384 return context.createFunctionExpr(location, functionInfo);
4385}
4386
4387template <typename LexerType>
4388template <class TreeBuilder> typename TreeBuilder::TemplateString Parser<LexerType>::parseTemplateString(TreeBuilder& context, bool isTemplateHead, typename LexerType::RawStringsBuildMode rawStringsBuildMode, bool& elementIsTail)
4389{
4390 if (isTemplateHead)
4391 ASSERT(match(BACKQUOTE));
4392 else
4393 matchOrFail(CLOSEBRACE, "Expected a closing '}' following an expression in template literal");
4394
4395 // Re-scan the token to recognize it as Template Element.
4396 m_token.m_type = m_lexer->scanTemplateString(&m_token, rawStringsBuildMode);
4397 matchOrFail(TEMPLATE, "Expected an template element");
4398 const Identifier* cooked = m_token.m_data.cooked;
4399 const Identifier* raw = m_token.m_data.raw;
4400 elementIsTail = m_token.m_data.isTail;
4401 JSTokenLocation location(tokenLocation());
4402 next();
4403 return context.createTemplateString(location, cooked, raw);
4404}
4405
4406template <typename LexerType>
4407template <class TreeBuilder> typename TreeBuilder::TemplateLiteral Parser<LexerType>::parseTemplateLiteral(TreeBuilder& context, typename LexerType::RawStringsBuildMode rawStringsBuildMode)
4408{
4409 ASSERT(match(BACKQUOTE));
4410 JSTokenLocation location(tokenLocation());
4411 bool elementIsTail = false;
4412
4413 auto headTemplateString = parseTemplateString(context, true, rawStringsBuildMode, elementIsTail);
4414 failIfFalse(headTemplateString, "Cannot parse head template element");
4415
4416 typename TreeBuilder::TemplateStringList templateStringList = context.createTemplateStringList(headTemplateString);
4417 typename TreeBuilder::TemplateStringList templateStringTail = templateStringList;
4418
4419 if (elementIsTail)
4420 return context.createTemplateLiteral(location, templateStringList);
4421
4422 failIfTrue(match(CLOSEBRACE), "Template literal expression cannot be empty");
4423 TreeExpression expression = parseExpression(context);
4424 failIfFalse(expression, "Cannot parse expression in template literal");
4425
4426 typename TreeBuilder::TemplateExpressionList templateExpressionList = context.createTemplateExpressionList(expression);
4427 typename TreeBuilder::TemplateExpressionList templateExpressionTail = templateExpressionList;
4428
4429 auto templateString = parseTemplateString(context, false, rawStringsBuildMode, elementIsTail);
4430 failIfFalse(templateString, "Cannot parse template element");
4431 templateStringTail = context.createTemplateStringList(templateStringTail, templateString);
4432
4433 while (!elementIsTail) {
4434 failIfTrue(match(CLOSEBRACE), "Template literal expression cannot be empty");
4435 TreeExpression expression = parseExpression(context);
4436 failIfFalse(expression, "Cannot parse expression in template literal");
4437
4438 templateExpressionTail = context.createTemplateExpressionList(templateExpressionTail, expression);
4439
4440 auto templateString = parseTemplateString(context, false, rawStringsBuildMode, elementIsTail);
4441 failIfFalse(templateString, "Cannot parse template element");
4442 templateStringTail = context.createTemplateStringList(templateStringTail, templateString);
4443 }
4444
4445 return context.createTemplateLiteral(location, templateStringList, templateExpressionList);
4446}
4447
4448template <class LexerType>
4449template <class TreeBuilder> TreeExpression Parser<LexerType>::createResolveAndUseVariable(TreeBuilder& context, const Identifier* ident, bool isEval, const JSTextPosition& start, const JSTokenLocation& location)
4450{
4451 currentScope()->useVariable(ident, isEval);
4452 m_parserState.lastIdentifier = ident;
4453 return context.createResolve(location, *ident, start, lastTokenEndPosition());
4454}
4455
4456template <typename LexerType>
4457template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpression(TreeBuilder& context)
4458{
4459 failIfStackOverflow();
4460 switch (m_token.m_type) {
4461 case FUNCTION:
4462 return parseFunctionExpression(context);
4463 case CLASSTOKEN:
4464 return parseClassExpression(context);
4465 case OPENBRACE:
4466 if (strictMode())
4467 return parseStrictObjectLiteral(context);
4468 return parseObjectLiteral(context);
4469 case OPENBRACKET:
4470 return parseArrayLiteral(context);
4471 case OPENPAREN: {
4472 next();
4473 int oldNonLHSCount = m_parserState.nonLHSCount;
4474 TreeExpression result = parseExpression(context);
4475 m_parserState.nonLHSCount = oldNonLHSCount;
4476 handleProductionOrFail(CLOSEPAREN, ")", "end", "compound expression");
4477 return result;
4478 }
4479 case THISTOKEN: {
4480 JSTokenLocation location(tokenLocation());
4481 next();
4482 if (currentScope()->isArrowFunction())
4483 currentScope()->setInnerArrowFunctionUsesThis();
4484 return context.createThisExpr(location);
4485 }
4486 case AWAIT:
4487 if (m_parserState.functionParsePhase == FunctionParsePhase::Parameters)
4488 failIfFalse(m_parserState.allowAwait, "Cannot use await expression within parameters");
4489 else if (currentFunctionScope()->isAsyncFunctionBoundary())
4490 return parseAwaitExpression(context);
4491
4492 goto identifierExpression;
4493 case IDENT: {
4494 if (UNLIKELY(*m_token.m_data.ident == m_vm->propertyNames->async && !m_token.m_data.escaped)) {
4495 JSTextPosition start = tokenStartPosition();
4496 const Identifier* ident = m_token.m_data.ident;
4497 JSTokenLocation location(tokenLocation());
4498 next();
4499 if (match(FUNCTION) && !m_lexer->hasLineTerminatorBeforeToken())
4500 return parseAsyncFunctionExpression(context);
4501
4502 // Avoid using variable if it is an arrow function parameter
4503 if (UNLIKELY(match(ARROWFUNCTION)))
4504 return 0;
4505
4506 const bool isEval = false;
4507 return createResolveAndUseVariable(context, ident, isEval, start, location);
4508 }
4509 identifierExpression:
4510 JSTextPosition start = tokenStartPosition();
4511 const Identifier* ident = m_token.m_data.ident;
4512 JSTokenLocation location(tokenLocation());
4513 next();
4514
4515 // Avoid using variable if it is an arrow function parameter
4516 if (UNLIKELY(match(ARROWFUNCTION)))
4517 return 0;
4518
4519 return createResolveAndUseVariable(context, ident, *ident == m_vm->propertyNames->eval, start, location);
4520 }
4521 case BIGINT: {
4522 const Identifier* ident = m_token.m_data.bigIntString;
4523 uint8_t radix = m_token.m_data.radix;
4524 JSTokenLocation location(tokenLocation());
4525 next();
4526 return context.createBigInt(location, ident, radix);
4527 }
4528 case STRING: {
4529 const Identifier* ident = m_token.m_data.ident;
4530 JSTokenLocation location(tokenLocation());
4531 next();
4532 return context.createString(location, ident);
4533 }
4534 case DOUBLE: {
4535 double d = m_token.m_data.doubleValue;
4536 JSTokenLocation location(tokenLocation());
4537 next();
4538 return context.createDoubleExpr(location, d);
4539 }
4540 case INTEGER: {
4541 double d = m_token.m_data.doubleValue;
4542 JSTokenLocation location(tokenLocation());
4543 next();
4544 return context.createIntegerExpr(location, d);
4545 }
4546 case NULLTOKEN: {
4547 JSTokenLocation location(tokenLocation());
4548 next();
4549 return context.createNull(location);
4550 }
4551 case TRUETOKEN: {
4552 JSTokenLocation location(tokenLocation());
4553 next();
4554 return context.createBoolean(location, true);
4555 }
4556 case FALSETOKEN: {
4557 JSTokenLocation location(tokenLocation());
4558 next();
4559 return context.createBoolean(location, false);
4560 }
4561 case DIVEQUAL:
4562 case DIVIDE: {
4563 /* regexp */
4564 if (match(DIVEQUAL))
4565 m_token.m_type = m_lexer->scanRegExp(&m_token, '=');
4566 else
4567 m_token.m_type = m_lexer->scanRegExp(&m_token);
4568 matchOrFail(REGEXP, "Invalid regular expression");
4569
4570 const Identifier* pattern = m_token.m_data.pattern;
4571 const Identifier* flags = m_token.m_data.flags;
4572 JSTextPosition start = tokenStartPosition();
4573 JSTokenLocation location(tokenLocation());
4574 next();
4575 TreeExpression re = context.createRegExp(location, *pattern, *flags, start);
4576 if (!re) {
4577 Yarr::ErrorCode errorCode = Yarr::checkSyntax(pattern->string(), flags->string());
4578 regexFail(Yarr::errorMessage(errorCode));
4579 }
4580 return re;
4581 }
4582 case BACKQUOTE:
4583 return parseTemplateLiteral(context, LexerType::RawStringsBuildMode::DontBuildRawStrings);
4584 case YIELD:
4585 if (!strictMode() && !currentScope()->isGenerator())
4586 goto identifierExpression;
4587 failDueToUnexpectedToken();
4588 case LET:
4589 if (!strictMode())
4590 goto identifierExpression;
4591 FALLTHROUGH;
4592 default:
4593 failDueToUnexpectedToken();
4594 }
4595}
4596
4597template <typename LexerType>
4598template <class TreeBuilder> TreeArguments Parser<LexerType>::parseArguments(TreeBuilder& context)
4599{
4600 consumeOrFailWithFlags(OPENPAREN, TreeBuilder::DontBuildStrings, "Expected opening '(' at start of argument list");
4601 JSTokenLocation location(tokenLocation());
4602 if (match(CLOSEPAREN)) {
4603 next(TreeBuilder::DontBuildStrings);
4604 return context.createArguments();
4605 }
4606 auto argumentsStart = m_token.m_startPosition;
4607 auto argumentsDivot = m_token.m_endPosition;
4608
4609 ArgumentType argType = ArgumentType::Normal;
4610 TreeExpression firstArg = parseArgument(context, argType);
4611 failIfFalse(firstArg, "Cannot parse function argument");
4612 semanticFailIfTrue(match(DOTDOTDOT), "The '...' operator should come before the target expression");
4613
4614 bool hasSpread = false;
4615 if (argType == ArgumentType::Spread)
4616 hasSpread = true;
4617 TreeArgumentsList argList = context.createArgumentsList(location, firstArg);
4618 TreeArgumentsList tail = argList;
4619
4620 while (match(COMMA)) {
4621 JSTokenLocation argumentLocation(tokenLocation());
4622 next(TreeBuilder::DontBuildStrings);
4623
4624 if (UNLIKELY(match(CLOSEPAREN)))
4625 break;
4626
4627 TreeExpression arg = parseArgument(context, argType);
4628 propagateError();
4629 semanticFailIfTrue(match(DOTDOTDOT), "The '...' operator should come before the target expression");
4630
4631 if (argType == ArgumentType::Spread)
4632 hasSpread = true;
4633
4634 tail = context.createArgumentsList(argumentLocation, tail, arg);
4635 }
4636
4637 handleProductionOrFail2(CLOSEPAREN, ")", "end", "argument list");
4638 if (hasSpread) {
4639 TreeExpression spreadArray = context.createSpreadExpression(location, context.createArray(location, context.createElementList(argList)), argumentsStart, argumentsDivot, m_lastTokenEndPosition);
4640 return context.createArguments(context.createArgumentsList(location, spreadArray));
4641 }
4642
4643 return context.createArguments(argList);
4644}
4645
4646template <typename LexerType>
4647template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArgument(TreeBuilder& context, ArgumentType& type)
4648{
4649 if (UNLIKELY(match(DOTDOTDOT))) {
4650 JSTokenLocation spreadLocation(tokenLocation());
4651 auto start = m_token.m_startPosition;
4652 auto divot = m_token.m_endPosition;
4653 next();
4654 TreeExpression spreadExpr = parseAssignmentExpression(context);
4655 propagateError();
4656 auto end = m_lastTokenEndPosition;
4657 type = ArgumentType::Spread;
4658 return context.createSpreadExpression(spreadLocation, spreadExpr, start, divot, end);
4659 }
4660
4661 type = ArgumentType::Normal;
4662 return parseAssignmentExpression(context);
4663}
4664
4665template <typename TreeBuilder, typename ParserType, typename = typename std::enable_if<std::is_same<TreeBuilder, ASTBuilder>::value>::type>
4666static inline void recordCallOrApplyDepth(ParserType* parser, VM& vm, Optional<typename ParserType::CallOrApplyDepthScope>& callOrApplyDepthScope, ExpressionNode* expression)
4667{
4668 if (expression->isDotAccessorNode()) {
4669 DotAccessorNode* dot = static_cast<DotAccessorNode*>(expression);
4670 bool isCallOrApply = dot->identifier() == vm.propertyNames->builtinNames().callPublicName() || dot->identifier() == vm.propertyNames->builtinNames().applyPublicName();
4671 if (isCallOrApply)
4672 callOrApplyDepthScope.emplace(parser);
4673 }
4674}
4675
4676template <typename TreeBuilder, typename ParserType, typename = typename std::enable_if<std::is_same<TreeBuilder, SyntaxChecker>::value>::type>
4677static inline void recordCallOrApplyDepth(ParserType*, VM&, Optional<typename ParserType::CallOrApplyDepthScope>&, SyntaxChecker::Expression)
4678{
4679}
4680
4681template <typename LexerType>
4682template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpression(TreeBuilder& context)
4683{
4684 TreeExpression base = 0;
4685 JSTextPosition expressionStart = tokenStartPosition();
4686 int newCount = 0;
4687 JSTokenLocation startLocation = tokenLocation();
4688 JSTokenLocation lastNewTokenLocation;
4689 while (match(NEW)) {
4690 lastNewTokenLocation = tokenLocation();
4691 next();
4692 newCount++;
4693 }
4694 JSTokenLocation location = tokenLocation();
4695
4696 bool baseIsSuper = match(SUPER);
4697 bool previousBaseWasSuper = false;
4698 bool baseIsImport = match(IMPORT);
4699 semanticFailIfTrue((baseIsSuper || baseIsImport) && newCount, "Cannot use new with ", getToken());
4700
4701 bool baseIsNewTarget = false;
4702 if (newCount && match(DOT)) {
4703 next();
4704 if (matchContextualKeyword(m_vm->propertyNames->target)) {
4705 ScopeRef closestOrdinaryFunctionScope = closestParentOrdinaryFunctionNonLexicalScope();
4706 semanticFailIfFalse(currentScope()->isFunction() || closestOrdinaryFunctionScope->evalContextType() == EvalContextType::FunctionEvalContext, "new.target is only valid inside functions");
4707 baseIsNewTarget = true;
4708 if (currentScope()->isArrowFunction()) {
4709 semanticFailIfFalse(!closestOrdinaryFunctionScope->isGlobalCodeScope() || closestOrdinaryFunctionScope->evalContextType() == EvalContextType::FunctionEvalContext, "new.target is not valid inside arrow functions in global code");
4710 currentScope()->setInnerArrowFunctionUsesNewTarget();
4711 }
4712 ASSERT(lastNewTokenLocation.line);
4713 base = context.createNewTargetExpr(lastNewTokenLocation);
4714 newCount--;
4715 next();
4716 } else {
4717 failIfTrue(match(IDENT), "\"new.\" can only followed with target");
4718 failDueToUnexpectedToken();
4719 }
4720 }
4721
4722 bool baseIsAsyncKeyword = false;
4723
4724 if (baseIsSuper) {
4725 ScopeRef closestOrdinaryFunctionScope = closestParentOrdinaryFunctionNonLexicalScope();
4726 semanticFailIfFalse(currentScope()->isFunction() || (closestOrdinaryFunctionScope->isEvalContext() && closestOrdinaryFunctionScope->expectedSuperBinding() == SuperBinding::Needed), "super is not valid in this context");
4727 base = context.createSuperExpr(location);
4728 next();
4729 ScopeRef functionScope = currentFunctionScope();
4730 if (!functionScope->setNeedsSuperBinding()) {
4731 // It unnecessary to check of using super during reparsing one more time. Also it can lead to syntax error
4732 // in case of arrow function because during reparsing we don't know whether we currently parse the arrow function
4733 // inside of the constructor or method.
4734 if (!m_lexer->isReparsingFunction()) {
4735 SuperBinding functionSuperBinding = !functionScope->isArrowFunction() && !closestOrdinaryFunctionScope->isEvalContext()
4736 ? functionScope->expectedSuperBinding()
4737 : closestOrdinaryFunctionScope->expectedSuperBinding();
4738 semanticFailIfTrue(functionSuperBinding == SuperBinding::NotNeeded, "super is not valid in this context");
4739 }
4740 }
4741 } else if (baseIsImport) {
4742 next();
4743 JSTextPosition expressionEnd = lastTokenEndPosition();
4744 if (consume(DOT)) {
4745 if (matchContextualKeyword(m_vm->propertyNames->builtinNames().metaPublicName())) {
4746 semanticFailIfFalse(m_scriptMode == JSParserScriptMode::Module, "import.meta is only valid inside modules");
4747 base = context.createImportMetaExpr(location, createResolveAndUseVariable(context, &m_vm->propertyNames->metaPrivateName, false, expressionStart, location));
4748 next();
4749 } else {
4750 failIfTrue(match(IDENT), "\"import.\" can only followed with meta");
4751 failDueToUnexpectedToken();
4752 }
4753 } else {
4754 consumeOrFail(OPENPAREN, "import call expects exactly one argument");
4755 TreeExpression expr = parseAssignmentExpression(context);
4756 failIfFalse(expr, "Cannot parse expression");
4757 consumeOrFail(CLOSEPAREN, "import call expects exactly one argument");
4758 base = context.createImportExpr(location, expr, expressionStart, expressionEnd, lastTokenEndPosition());
4759 }
4760 } else if (!baseIsNewTarget) {
4761 const bool isAsync = matchContextualKeyword(m_vm->propertyNames->async);
4762
4763 base = parsePrimaryExpression(context);
4764 failIfFalse(base, "Cannot parse base expression");
4765 if (UNLIKELY(isAsync && context.isResolve(base) && !m_lexer->hasLineTerminatorBeforeToken())) {
4766 if (matchSpecIdentifier()) {
4767 // AsyncArrowFunction
4768 forceClassifyExpressionError(ErrorIndicatesAsyncArrowFunction);
4769 failDueToUnexpectedToken();
4770 }
4771 baseIsAsyncKeyword = true;
4772 }
4773 }
4774
4775 failIfFalse(base, "Cannot parse base expression");
4776 while (true) {
4777 location = tokenLocation();
4778 switch (m_token.m_type) {
4779 case OPENBRACKET: {
4780 m_parserState.nonTrivialExpressionCount++;
4781 JSTextPosition expressionEnd = lastTokenEndPosition();
4782 next();
4783 int nonLHSCount = m_parserState.nonLHSCount;
4784 int initialAssignments = m_parserState.assignmentCount;
4785 TreeExpression property = parseExpression(context);
4786 failIfFalse(property, "Cannot parse subscript expression");
4787 base = context.createBracketAccess(startLocation, base, property, initialAssignments != m_parserState.assignmentCount, expressionStart, expressionEnd, tokenEndPosition());
4788
4789 if (UNLIKELY(baseIsSuper && currentScope()->isArrowFunction()))
4790 currentFunctionScope()->setInnerArrowFunctionUsesSuperProperty();
4791
4792 handleProductionOrFail(CLOSEBRACKET, "]", "end", "subscript expression");
4793 m_parserState.nonLHSCount = nonLHSCount;
4794 break;
4795 }
4796 case OPENPAREN: {
4797 m_parserState.nonTrivialExpressionCount++;
4798 int nonLHSCount = m_parserState.nonLHSCount;
4799 if (newCount) {
4800 newCount--;
4801 JSTextPosition expressionEnd = lastTokenEndPosition();
4802 TreeArguments arguments = parseArguments(context);
4803 failIfFalse(arguments, "Cannot parse call arguments");
4804 base = context.createNewExpr(location, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition());
4805 } else {
4806 size_t usedVariablesSize = currentScope()->currentUsedVariablesSize();
4807 JSTextPosition expressionEnd = lastTokenEndPosition();
4808 Optional<CallOrApplyDepthScope> callOrApplyDepthScope;
4809 recordCallOrApplyDepth<TreeBuilder>(this, *m_vm, callOrApplyDepthScope, base);
4810
4811 TreeArguments arguments = parseArguments(context);
4812
4813 if (baseIsAsyncKeyword && (!arguments || match(ARROWFUNCTION))) {
4814 currentScope()->revertToPreviousUsedVariables(usedVariablesSize);
4815 forceClassifyExpressionError(ErrorIndicatesAsyncArrowFunction);
4816 failDueToUnexpectedToken();
4817 }
4818
4819 failIfFalse(arguments, "Cannot parse call arguments");
4820 if (baseIsSuper) {
4821 ScopeRef functionScope = currentFunctionScope();
4822 if (!functionScope->setHasDirectSuper()) {
4823 // It unnecessary to check of using super during reparsing one more time. Also it can lead to syntax error
4824 // in case of arrow function because during reparsing we don't know whether we currently parse the arrow function
4825 // inside of the constructor or method.
4826 if (!m_lexer->isReparsingFunction()) {
4827 ScopeRef closestOrdinaryFunctionScope = closestParentOrdinaryFunctionNonLexicalScope();
4828 ConstructorKind functionConstructorKind = !functionScope->isArrowFunction() && !closestOrdinaryFunctionScope->isEvalContext()
4829 ? functionScope->constructorKind()
4830 : closestOrdinaryFunctionScope->constructorKind();
4831 semanticFailIfTrue(functionConstructorKind == ConstructorKind::None, "super is not valid in this context");
4832 semanticFailIfTrue(functionConstructorKind != ConstructorKind::Extends, "super is not valid in this context");
4833 }
4834 }
4835 if (currentScope()->isArrowFunction())
4836 functionScope->setInnerArrowFunctionUsesSuperCall();
4837 }
4838 base = context.makeFunctionCallNode(startLocation, base, previousBaseWasSuper, arguments, expressionStart,
4839 expressionEnd, lastTokenEndPosition(), callOrApplyDepthScope ? callOrApplyDepthScope->distanceToInnermostChild() : 0);
4840 }
4841 m_parserState.nonLHSCount = nonLHSCount;
4842 break;
4843 }
4844 case DOT: {
4845 m_parserState.nonTrivialExpressionCount++;
4846 JSTextPosition expressionEnd = lastTokenEndPosition();
4847 nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords);
4848 matchOrFail(IDENT, "Expected a property name after '.'");
4849 base = context.createDotAccess(startLocation, base, m_token.m_data.ident, expressionStart, expressionEnd, tokenEndPosition());
4850 if (UNLIKELY(baseIsSuper && currentScope()->isArrowFunction()))
4851 currentFunctionScope()->setInnerArrowFunctionUsesSuperProperty();
4852 next();
4853 break;
4854 }
4855 case BACKQUOTE: {
4856 semanticFailIfTrue(baseIsSuper, "Cannot use super as tag for tagged templates");
4857 JSTextPosition expressionEnd = lastTokenEndPosition();
4858 int nonLHSCount = m_parserState.nonLHSCount;
4859 typename TreeBuilder::TemplateLiteral templateLiteral = parseTemplateLiteral(context, LexerType::RawStringsBuildMode::BuildRawStrings);
4860 failIfFalse(templateLiteral, "Cannot parse template literal");
4861 base = context.createTaggedTemplate(startLocation, base, templateLiteral, expressionStart, expressionEnd, lastTokenEndPosition());
4862 m_parserState.nonLHSCount = nonLHSCount;
4863 m_seenTaggedTemplate = true;
4864 break;
4865 }
4866 default:
4867 goto endMemberExpression;
4868 }
4869 previousBaseWasSuper = baseIsSuper;
4870 baseIsSuper = false;
4871 }
4872endMemberExpression:
4873 semanticFailIfTrue(baseIsSuper, "super is not valid in this context");
4874 while (newCount--)
4875 base = context.createNewExpr(location, base, expressionStart, lastTokenEndPosition());
4876 return base;
4877}
4878
4879template <typename LexerType>
4880template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrowFunctionExpression(TreeBuilder& context, bool isAsync)
4881{
4882 JSTokenLocation location;
4883
4884 unsigned functionKeywordStart = tokenStart();
4885 location = tokenLocation();
4886 ParserFunctionInfo<TreeBuilder> info;
4887 info.name = &m_vm->propertyNames->nullIdentifier;
4888
4889 SourceParseMode parseMode = isAsync ? SourceParseMode::AsyncArrowFunctionMode : SourceParseMode::ArrowFunctionMode;
4890 failIfFalse((parseFunctionInfo(context, FunctionNameRequirements::Unnamed, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, info, FunctionDefinitionType::Expression)), "Cannot parse arrow function expression");
4891
4892 return context.createArrowFunctionExpr(location, info);
4893}
4894
4895static const char* operatorString(bool prefix, unsigned tok)
4896{
4897 switch (tok) {
4898 case MINUSMINUS:
4899 case AUTOMINUSMINUS:
4900 return prefix ? "prefix-decrement" : "decrement";
4901
4902 case PLUSPLUS:
4903 case AUTOPLUSPLUS:
4904 return prefix ? "prefix-increment" : "increment";
4905
4906 case EXCLAMATION:
4907 return "logical-not";
4908
4909 case TILDE:
4910 return "bitwise-not";
4911
4912 case TYPEOF:
4913 return "typeof";
4914
4915 case VOIDTOKEN:
4916 return "void";
4917
4918 case DELETETOKEN:
4919 return "delete";
4920 }
4921 RELEASE_ASSERT_NOT_REACHED();
4922 return "error";
4923}
4924
4925template <typename LexerType>
4926template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpression(TreeBuilder& context)
4927{
4928 typename TreeBuilder::UnaryExprContext unaryExprContext(context);
4929 AllowInOverride allowInOverride(this);
4930 int tokenStackDepth = 0;
4931 bool modifiesExpr = false;
4932 bool requiresLExpr = false;
4933 unsigned lastOperator = 0;
4934
4935 if (UNLIKELY(match(AWAIT) && currentFunctionScope()->isAsyncFunctionBoundary()))
4936 return parseAwaitExpression(context);
4937
4938 JSTokenLocation location(tokenLocation());
4939
4940 while (isUnaryOp(m_token.m_type)) {
4941 if (strictMode()) {
4942 switch (m_token.m_type) {
4943 case PLUSPLUS:
4944 case MINUSMINUS:
4945 case AUTOPLUSPLUS:
4946 case AUTOMINUSMINUS:
4947 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
4948 modifiesExpr = true;
4949 requiresLExpr = true;
4950 break;
4951 default:
4952 semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
4953 break;
4954 }
4955 }
4956 lastOperator = m_token.m_type;
4957 m_parserState.nonLHSCount++;
4958 context.appendUnaryToken(tokenStackDepth, m_token.m_type, tokenStartPosition());
4959 next();
4960 m_parserState.nonTrivialExpressionCount++;
4961 }
4962 JSTextPosition subExprStart = tokenStartPosition();
4963 ASSERT(subExprStart.offset >= subExprStart.lineStartOffset);
4964 TreeExpression expr = parseMemberExpression(context);
4965 if (!expr) {
4966 if (lastOperator)
4967 failWithMessage("Cannot parse subexpression of ", operatorString(true, lastOperator), "operator");
4968 failWithMessage("Cannot parse member expression");
4969 }
4970 if (UNLIKELY(isUpdateOp(static_cast<JSTokenType>(lastOperator)) && context.isMetaProperty(expr)))
4971 internalFailWithMessage(false, metaPropertyName(context, expr), " can't come after a prefix operator");
4972 bool isEvalOrArguments = false;
4973 if (strictMode()) {
4974 if (context.isResolve(expr))
4975 isEvalOrArguments = *m_parserState.lastIdentifier == m_vm->propertyNames->eval || *m_parserState.lastIdentifier == m_vm->propertyNames->arguments;
4976 }
4977 failIfTrueIfStrict(isEvalOrArguments && modifiesExpr, "Cannot modify '", m_parserState.lastIdentifier->impl(), "' in strict mode");
4978 switch (m_token.m_type) {
4979 case PLUSPLUS:
4980 if (UNLIKELY(context.isMetaProperty(expr)))
4981 internalFailWithMessage(false, metaPropertyName(context, expr), " can't come before a postfix operator");
4982 m_parserState.nonTrivialExpressionCount++;
4983 m_parserState.nonLHSCount++;
4984 expr = context.makePostfixNode(location, expr, OpPlusPlus, subExprStart, lastTokenEndPosition(), tokenEndPosition());
4985 m_parserState.assignmentCount++;
4986 failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", m_parserState.lastIdentifier->impl(), "' in strict mode");
4987 semanticFailIfTrue(requiresLExpr, "The ", operatorString(false, lastOperator), " operator requires a reference expression");
4988 lastOperator = PLUSPLUS;
4989 next();
4990 break;
4991 case MINUSMINUS:
4992 if (UNLIKELY(context.isMetaProperty(expr)))
4993 internalFailWithMessage(false, metaPropertyName(context, expr), " can't come before a postfix operator");
4994 m_parserState.nonTrivialExpressionCount++;
4995 m_parserState.nonLHSCount++;
4996 expr = context.makePostfixNode(location, expr, OpMinusMinus, subExprStart, lastTokenEndPosition(), tokenEndPosition());
4997 m_parserState.assignmentCount++;
4998 failIfTrueIfStrict(isEvalOrArguments, "'", m_parserState.lastIdentifier->impl(), "' cannot be modified in strict mode");
4999 semanticFailIfTrue(requiresLExpr, "The ", operatorString(false, lastOperator), " operator requires a reference expression");
5000 lastOperator = PLUSPLUS;
5001 next();
5002 break;
5003 default:
5004 break;
5005 }
5006
5007 JSTextPosition end = lastTokenEndPosition();
5008
5009 if (!TreeBuilder::CreatesAST && (!strictMode()))
5010 return expr;
5011
5012 while (tokenStackDepth) {
5013 switch (context.unaryTokenStackLastType(tokenStackDepth)) {
5014 case EXCLAMATION:
5015 expr = context.createLogicalNot(location, expr);
5016 break;
5017 case TILDE:
5018 expr = context.makeBitwiseNotNode(location, expr);
5019 break;
5020 case MINUS:
5021 expr = context.makeNegateNode(location, expr);
5022 break;
5023 case PLUS:
5024 expr = context.createUnaryPlus(location, expr);
5025 break;
5026 case PLUSPLUS:
5027 case AUTOPLUSPLUS:
5028 expr = context.makePrefixNode(location, expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
5029 m_parserState.assignmentCount++;
5030 break;
5031 case MINUSMINUS:
5032 case AUTOMINUSMINUS:
5033 expr = context.makePrefixNode(location, expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
5034 m_parserState.assignmentCount++;
5035 break;
5036 case TYPEOF:
5037 expr = context.makeTypeOfNode(location, expr);
5038 break;
5039 case VOIDTOKEN:
5040 expr = context.createVoid(location, expr);
5041 break;
5042 case DELETETOKEN:
5043 failIfTrueIfStrict(context.isResolve(expr), "Cannot delete unqualified property '", m_parserState.lastIdentifier->impl(), "' in strict mode");
5044 expr = context.makeDeleteNode(location, expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end);
5045 break;
5046 default:
5047 // If we get here something has gone horribly horribly wrong
5048 CRASH();
5049 }
5050 subExprStart = context.unaryTokenStackLastStart(tokenStackDepth);
5051 context.unaryTokenStackRemoveLast(tokenStackDepth);
5052 }
5053 return expr;
5054}
5055
5056template <typename LexerType> void Parser<LexerType>::printUnexpectedTokenText(WTF::PrintStream& out)
5057{
5058 switch (m_token.m_type) {
5059 case EOFTOK:
5060 out.print("Unexpected end of script");
5061 return;
5062 case UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK:
5063 case UNTERMINATED_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK:
5064 out.print("Incomplete unicode escape in identifier: '", getToken(), "'");
5065 return;
5066 case UNTERMINATED_MULTILINE_COMMENT_ERRORTOK:
5067 out.print("Unterminated multiline comment");
5068 return;
5069 case UNTERMINATED_NUMERIC_LITERAL_ERRORTOK:
5070 out.print("Unterminated numeric literal '", getToken(), "'");
5071 return;
5072 case UNTERMINATED_STRING_LITERAL_ERRORTOK:
5073 out.print("Unterminated string literal '", getToken(), "'");
5074 return;
5075 case INVALID_IDENTIFIER_ESCAPE_ERRORTOK:
5076 out.print("Invalid escape in identifier: '", getToken(), "'");
5077 return;
5078 case UNEXPECTED_ESCAPE_ERRORTOK:
5079 out.print("Unexpected escaped characters in keyword token: '", getToken(), "'");
5080 return;
5081 case INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK:
5082 out.print("Invalid unicode escape in identifier: '", getToken(), "'");
5083 return;
5084 case INVALID_NUMERIC_LITERAL_ERRORTOK:
5085 out.print("Invalid numeric literal: '", getToken(), "'");
5086 return;
5087 case UNTERMINATED_OCTAL_NUMBER_ERRORTOK:
5088 out.print("Invalid use of octal: '", getToken(), "'");
5089 return;
5090 case INVALID_STRING_LITERAL_ERRORTOK:
5091 out.print("Invalid string literal: '", getToken(), "'");
5092 return;
5093 case ERRORTOK:
5094 out.print("Unrecognized token '", getToken(), "'");
5095 return;
5096 case STRING:
5097 out.print("Unexpected string literal ", getToken());
5098 return;
5099 case INTEGER:
5100 case DOUBLE:
5101 out.print("Unexpected number '", getToken(), "'");
5102 return;
5103
5104 case RESERVED_IF_STRICT:
5105 out.print("Unexpected use of reserved word '", getToken(), "' in strict mode");
5106 return;
5107
5108 case RESERVED:
5109 out.print("Unexpected use of reserved word '", getToken(), "'");
5110 return;
5111
5112 case INVALID_PRIVATE_NAME_ERRORTOK:
5113 out.print("Invalid private name '", getToken(), "'");
5114 return;
5115
5116 case AWAIT:
5117 case IDENT:
5118 out.print("Unexpected identifier '", getToken(), "'");
5119 return;
5120
5121 default:
5122 break;
5123 }
5124
5125 if (m_token.m_type & KeywordTokenFlag) {
5126 out.print("Unexpected keyword '", getToken(), "'");
5127 return;
5128 }
5129
5130 out.print("Unexpected token '", getToken(), "'");
5131}
5132
5133// Instantiate the two flavors of Parser we need instead of putting most of this file in Parser.h
5134template class Parser<Lexer<LChar>>;
5135template class Parser<Lexer<UChar>>;
5136
5137} // namespace JSC
5138