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