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