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