1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
10 * This is a recursive-descent parser for the JavaScript language specified by
11 * "The ECMAScript Language Specification" (Standard ECMA-262). It uses
12 * lexical and semantic feedback to disambiguate non-LL(1) structures. It
13 * generates trees of nodes induced by the recursive parsing (not precise
14 * syntax trees, see Parser.h). After tree construction, it rewrites trees to
15 * fold constants and evaluate compile-time expressions.
17 * This parser attempts no error recovery.
20 #include "frontend/Parser.h"
22 #include "mozilla/ArrayUtils.h"
23 #include "mozilla/Assertions.h"
24 #include "mozilla/Casting.h"
25 #include "mozilla/Range.h"
26 #include "mozilla/Sprintf.h"
27 #include "mozilla/Try.h" // MOZ_TRY*
28 #include "mozilla/Utf8.h"
29 #include "mozilla/Variant.h"
33 #include <type_traits>
38 #include "frontend/FoldConstants.h"
39 #include "frontend/FunctionSyntaxKind.h" // FunctionSyntaxKind
40 #include "frontend/ModuleSharedContext.h"
41 #include "frontend/ParseNode.h"
42 #include "frontend/ParseNodeVerify.h"
43 #include "frontend/Parser-macros.h" // MOZ_TRY_VAR_OR_RETURN
44 #include "frontend/ParserAtom.h" // TaggedParserAtomIndex, ParserAtomsTable, ParserAtom
45 #include "frontend/ScriptIndex.h" // ScriptIndex
46 #include "frontend/TokenStream.h" // IsKeyword, ReservedWordTokenKind, ReservedWordToCharZ, DeprecatedContent, *TokenStream*, CharBuffer, TokenKindToDesc
47 #include "irregexp/RegExpAPI.h"
48 #include "js/ColumnNumber.h" // JS::LimitedColumnNumberOneOrigin, JS::ColumnNumberOneOrigin
49 #include "js/ErrorReport.h" // JSErrorBase
50 #include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
51 #include "js/HashTable.h"
52 #include "js/RegExpFlags.h" // JS::RegExpFlags
53 #include "js/Stack.h" // JS::NativeStackLimit
54 #include "util/StringBuffer.h" // StringBuffer
55 #include "vm/BytecodeUtil.h"
56 #include "vm/FunctionFlags.h" // js::FunctionFlags
57 #include "vm/GeneratorAndAsyncKind.h" // js::GeneratorKind, js::FunctionAsyncKind
58 #include "vm/JSContext.h"
59 #include "vm/JSScript.h"
60 #include "vm/ModuleBuilder.h" // js::ModuleBuilder
61 #include "vm/Scope.h" // GetScopeDataTrailingNames
62 #include "wasm/AsmJS.h"
64 #include "frontend/ParseContext-inl.h"
65 #include "frontend/SharedContext-inl.h"
69 using mozilla::AssertedCast
;
70 using mozilla::AsVariant
;
72 using mozilla::Nothing
;
73 using mozilla::PointerRangeSize
;
75 using mozilla::Utf8Unit
;
77 using JS::ReadOnlyCompileOptions
;
78 using JS::RegExpFlags
;
80 namespace js::frontend
{
82 using DeclaredNamePtr
= ParseContext::Scope::DeclaredNamePtr
;
83 using AddDeclaredNamePtr
= ParseContext::Scope::AddDeclaredNamePtr
;
84 using BindingIter
= ParseContext::Scope::BindingIter
;
85 using UsedNamePtr
= UsedNameTracker::UsedNameMap::Ptr
;
87 using ParserBindingNameVector
= Vector
<ParserBindingName
, 6>;
89 static inline void PropagateTransitiveParseFlags(const FunctionBox
* inner
,
90 SharedContext
* outer
) {
91 if (inner
->bindingsAccessedDynamically()) {
92 outer
->setBindingsAccessedDynamically();
94 if (inner
->hasDirectEval()) {
95 outer
->setHasDirectEval();
99 static bool StatementKindIsBraced(StatementKind kind
) {
100 return kind
== StatementKind::Block
|| kind
== StatementKind::Switch
||
101 kind
== StatementKind::Try
|| kind
== StatementKind::Catch
||
102 kind
== StatementKind::Finally
;
105 template <class ParseHandler
, typename Unit
>
106 inline typename GeneralParser
<ParseHandler
, Unit
>::FinalParser
*
107 GeneralParser
<ParseHandler
, Unit
>::asFinalParser() {
109 std::is_base_of_v
<GeneralParser
<ParseHandler
, Unit
>, FinalParser
>,
110 "inheritance relationship required by the static_cast<> below");
112 return static_cast<FinalParser
*>(this);
115 template <class ParseHandler
, typename Unit
>
116 inline const typename GeneralParser
<ParseHandler
, Unit
>::FinalParser
*
117 GeneralParser
<ParseHandler
, Unit
>::asFinalParser() const {
119 std::is_base_of_v
<GeneralParser
<ParseHandler
, Unit
>, FinalParser
>,
120 "inheritance relationship required by the static_cast<> below");
122 return static_cast<const FinalParser
*>(this);
125 template <class ParseHandler
, typename Unit
>
126 template <typename ConditionT
, typename ErrorReportT
>
127 bool GeneralParser
<ParseHandler
, Unit
>::mustMatchTokenInternal(
128 ConditionT condition
, ErrorReportT errorReport
) {
129 MOZ_ASSERT(condition(TokenKind::Div
) == false);
130 MOZ_ASSERT(condition(TokenKind::DivAssign
) == false);
131 MOZ_ASSERT(condition(TokenKind::RegExp
) == false);
134 if (!tokenStream
.getToken(&actual
, TokenStream::SlashIsInvalid
)) {
137 if (!condition(actual
)) {
144 ParserSharedBase::ParserSharedBase(FrontendContext
* fc
,
145 CompilationState
& compilationState
,
148 alloc_(compilationState
.parserAllocScope
.alloc()),
149 compilationState_(compilationState
),
151 usedNames_(compilationState
.usedNames
) {
152 fc_
->nameCollectionPool().addActiveCompilation();
155 ParserSharedBase::~ParserSharedBase() {
156 fc_
->nameCollectionPool().removeActiveCompilation();
159 #if defined(DEBUG) || defined(JS_JITSPEW)
160 void ParserSharedBase::dumpAtom(TaggedParserAtomIndex index
) const {
161 parserAtoms().dump(index
);
165 ParserBase::ParserBase(FrontendContext
* fc
,
166 const ReadOnlyCompileOptions
& options
,
167 bool foldConstants
, CompilationState
& compilationState
)
168 : ParserSharedBase(fc
, compilationState
, ParserSharedBase::Kind::Parser
),
169 anyChars(fc
, options
, this),
171 foldConstants_(foldConstants
),
173 checkOptionsCalled_(false),
175 isUnexpectedEOF_(false),
176 awaitHandling_(AwaitIsName
),
177 inParametersOfAsyncFunction_(false) {
180 bool ParserBase::checkOptions() {
182 checkOptionsCalled_
= true;
185 return anyChars
.checkOptions();
188 ParserBase::~ParserBase() { MOZ_ASSERT(checkOptionsCalled_
); }
190 JSAtom
* ParserBase::liftParserAtomToJSAtom(TaggedParserAtomIndex index
) {
191 JSContext
* cx
= fc_
->maybeCurrentJSContext();
193 return parserAtoms().toJSAtom(cx
, fc_
, index
,
194 compilationState_
.input
.atomCache
);
197 template <class ParseHandler
>
198 PerHandlerParser
<ParseHandler
>::PerHandlerParser(
199 FrontendContext
* fc
, const ReadOnlyCompileOptions
& options
,
200 bool foldConstants
, CompilationState
& compilationState
,
201 void* internalSyntaxParser
)
202 : ParserBase(fc
, options
, foldConstants
, compilationState
),
203 handler_(fc
, compilationState
),
204 internalSyntaxParser_(internalSyntaxParser
) {
205 MOZ_ASSERT(compilationState
.isInitialStencil() ==
206 compilationState
.input
.isInitialStencil());
209 template <class ParseHandler
, typename Unit
>
210 GeneralParser
<ParseHandler
, Unit
>::GeneralParser(
211 FrontendContext
* fc
, const ReadOnlyCompileOptions
& options
,
212 const Unit
* units
, size_t length
, bool foldConstants
,
213 CompilationState
& compilationState
, SyntaxParser
* syntaxParser
)
214 : Base(fc
, options
, foldConstants
, compilationState
, syntaxParser
),
215 tokenStream(fc
, &compilationState
.parserAtoms
, options
, units
, length
) {}
217 template <typename Unit
>
218 void Parser
<SyntaxParseHandler
, Unit
>::setAwaitHandling(
219 AwaitHandling awaitHandling
) {
220 this->awaitHandling_
= awaitHandling
;
223 template <typename Unit
>
224 void Parser
<FullParseHandler
, Unit
>::setAwaitHandling(
225 AwaitHandling awaitHandling
) {
226 this->awaitHandling_
= awaitHandling
;
227 if (SyntaxParser
* syntaxParser
= getSyntaxParser()) {
228 syntaxParser
->setAwaitHandling(awaitHandling
);
232 template <class ParseHandler
, typename Unit
>
233 inline void GeneralParser
<ParseHandler
, Unit
>::setAwaitHandling(
234 AwaitHandling awaitHandling
) {
235 asFinalParser()->setAwaitHandling(awaitHandling
);
238 template <typename Unit
>
239 void Parser
<SyntaxParseHandler
, Unit
>::setInParametersOfAsyncFunction(
241 this->inParametersOfAsyncFunction_
= inParameters
;
244 template <typename Unit
>
245 void Parser
<FullParseHandler
, Unit
>::setInParametersOfAsyncFunction(
247 this->inParametersOfAsyncFunction_
= inParameters
;
248 if (SyntaxParser
* syntaxParser
= getSyntaxParser()) {
249 syntaxParser
->setInParametersOfAsyncFunction(inParameters
);
253 template <class ParseHandler
, typename Unit
>
254 inline void GeneralParser
<ParseHandler
, Unit
>::setInParametersOfAsyncFunction(
256 asFinalParser()->setInParametersOfAsyncFunction(inParameters
);
259 template <class ParseHandler
>
260 FunctionBox
* PerHandlerParser
<ParseHandler
>::newFunctionBox(
261 FunctionNodeType funNode
, TaggedParserAtomIndex explicitName
,
262 FunctionFlags flags
, uint32_t toStringStart
, Directives inheritedDirectives
,
263 GeneratorKind generatorKind
, FunctionAsyncKind asyncKind
) {
266 ScriptIndex index
= ScriptIndex(compilationState_
.scriptData
.length());
267 if (uint32_t(index
) >= TaggedScriptThingIndex::IndexLimit
) {
268 ReportAllocationOverflow(fc_
);
271 if (!compilationState_
.appendScriptStencilAndData(fc_
)) {
275 bool isInitialStencil
= compilationState_
.isInitialStencil();
277 // This source extent will be further filled in during the remainder of parse.
279 extent
.toStringStart
= toStringStart
;
281 FunctionBox
* funbox
= alloc_
.new_
<FunctionBox
>(
282 fc_
, extent
, compilationState_
, inheritedDirectives
, generatorKind
,
283 asyncKind
, isInitialStencil
, explicitName
, flags
, index
);
285 ReportOutOfMemory(fc_
);
289 handler_
.setFunctionBox(funNode
, funbox
);
294 template <class ParseHandler
>
295 FunctionBox
* PerHandlerParser
<ParseHandler
>::newFunctionBox(
296 FunctionNodeType funNode
, const ScriptStencil
& cachedScriptData
,
297 const ScriptStencilExtra
& cachedScriptExtra
) {
300 ScriptIndex index
= ScriptIndex(compilationState_
.scriptData
.length());
301 if (uint32_t(index
) >= TaggedScriptThingIndex::IndexLimit
) {
302 ReportAllocationOverflow(fc_
);
305 if (!compilationState_
.appendScriptStencilAndData(fc_
)) {
309 FunctionBox
* funbox
= alloc_
.new_
<FunctionBox
>(
310 fc_
, cachedScriptExtra
.extent
, compilationState_
,
311 Directives(/* strict = */ false), cachedScriptExtra
.generatorKind(),
312 cachedScriptExtra
.asyncKind(), compilationState_
.isInitialStencil(),
313 cachedScriptData
.functionAtom
, cachedScriptData
.functionFlags
, index
);
315 ReportOutOfMemory(fc_
);
319 handler_
.setFunctionBox(funNode
, funbox
);
320 funbox
->initFromScriptStencilExtra(cachedScriptExtra
);
325 bool ParserBase::setSourceMapInfo() {
326 // If support for source pragmas have been fully disabled, we can skip
327 // processing of all of these values.
328 if (!options().sourcePragmas()) {
332 // Not all clients initialize ss. Can't update info to an object that isn't
338 if (anyChars
.hasDisplayURL()) {
339 if (!ss
->setDisplayURL(fc_
, anyChars
.displayURL())) {
344 if (anyChars
.hasSourceMapURL()) {
345 MOZ_ASSERT(!ss
->hasSourceMapURL());
346 if (!ss
->setSourceMapURL(fc_
, anyChars
.sourceMapURL())) {
352 * Source map URLs passed as a compile option (usually via a HTTP source map
353 * header) override any source map urls passed as comment pragmas.
355 if (options().sourceMapURL()) {
356 // Warn about the replacement, but use the new one.
357 if (ss
->hasSourceMapURL()) {
358 if (!warningNoOffset(JSMSG_ALREADY_HAS_PRAGMA
, ss
->filename(),
359 "//# sourceMappingURL")) {
364 if (!ss
->setSourceMapURL(fc_
, options().sourceMapURL())) {
373 * Parse a top-level JS script.
375 template <class ParseHandler
, typename Unit
>
376 typename
ParseHandler::ListNodeResult
377 GeneralParser
<ParseHandler
, Unit
>::parse() {
378 MOZ_ASSERT(checkOptionsCalled_
);
380 SourceExtent extent
= SourceExtent::makeGlobalExtent(
381 /* len = */ 0, options().lineno
,
382 JS::LimitedColumnNumberOneOrigin::fromUnlimited(
383 JS::ColumnNumberOneOrigin(options().column
)));
384 Directives
directives(options().forceStrictMode());
385 GlobalSharedContext
globalsc(this->fc_
, ScopeKind::Global
, options(),
387 SourceParseContext
globalpc(this, &globalsc
, /* newDirectives = */ nullptr);
388 if (!globalpc
.init()) {
389 return errorResult();
392 ParseContext::VarScope
varScope(this);
393 if (!varScope
.init(pc_
)) {
394 return errorResult();
397 ListNodeType stmtList
;
398 MOZ_TRY_VAR(stmtList
, statementList(YieldIsName
));
401 if (!tokenStream
.getToken(&tt
, TokenStream::SlashIsRegExp
)) {
402 return errorResult();
404 if (tt
!= TokenKind::Eof
) {
405 error(JSMSG_GARBAGE_AFTER_INPUT
, "script", TokenKindToDesc(tt
));
406 return errorResult();
409 if (!CheckParseTree(this->fc_
, alloc_
, stmtList
)) {
410 return errorResult();
413 if (foldConstants_
) {
414 Node node
= stmtList
;
415 // Don't constant-fold inside "use asm" code, as this could create a parse
416 // tree that doesn't type-check as asm.js.
417 if (!pc_
->useAsmOrInsideUseAsm()) {
418 if (!FoldConstants(this->fc_
, this->parserAtoms(), &node
, &handler_
)) {
419 return errorResult();
422 stmtList
= handler_
.asListNode(node
);
429 * Strict mode forbids introducing new definitions for 'eval', 'arguments',
430 * 'let', 'static', 'yield', or for any strict mode reserved word.
432 bool ParserBase::isValidStrictBinding(TaggedParserAtomIndex name
) {
433 TokenKind tt
= ReservedWordTokenKind(name
);
434 if (tt
== TokenKind::Limit
) {
435 return name
!= TaggedParserAtomIndex::WellKnown::eval() &&
436 name
!= TaggedParserAtomIndex::WellKnown::arguments();
438 return tt
!= TokenKind::Let
&& tt
!= TokenKind::Static
&&
439 tt
!= TokenKind::Yield
&& !TokenKindIsStrictReservedWord(tt
);
443 * Returns true if all parameter names are valid strict mode binding names and
444 * no duplicate parameter names are present.
446 bool ParserBase::hasValidSimpleStrictParameterNames() {
447 MOZ_ASSERT(pc_
->isFunctionBox() &&
448 pc_
->functionBox()->hasSimpleParameterList());
450 if (pc_
->functionBox()->hasDuplicateParameters
) {
454 for (auto name
: pc_
->positionalFormalParameterNames()) {
456 if (!isValidStrictBinding(name
)) {
463 template <class ParseHandler
, typename Unit
>
464 void GeneralParser
<ParseHandler
, Unit
>::reportMissingClosing(
465 unsigned errorNumber
, unsigned noteNumber
, uint32_t openedPos
) {
466 auto notes
= MakeUnique
<JSErrorNotes
>();
468 ReportOutOfMemory(this->fc_
);
473 JS::LimitedColumnNumberOneOrigin column
;
474 tokenStream
.computeLineAndColumn(openedPos
, &line
, &column
);
476 const size_t MaxWidth
= sizeof("4294967295");
477 char columnNumber
[MaxWidth
];
478 SprintfLiteral(columnNumber
, "%" PRIu32
, column
.oneOriginValue());
479 char lineNumber
[MaxWidth
];
480 SprintfLiteral(lineNumber
, "%" PRIu32
, line
);
482 if (!notes
->addNoteASCII(this->fc_
, getFilename().c_str(), 0, line
,
483 JS::ColumnNumberOneOrigin(column
), GetErrorMessage
,
484 nullptr, noteNumber
, lineNumber
, columnNumber
)) {
488 errorWithNotes(std::move(notes
), errorNumber
);
491 template <class ParseHandler
, typename Unit
>
492 void GeneralParser
<ParseHandler
, Unit
>::reportRedeclarationHelper(
493 TaggedParserAtomIndex
& name
, DeclarationKind
& prevKind
, TokenPos
& pos
,
494 uint32_t& prevPos
, const unsigned& errorNumber
,
495 const unsigned& noteErrorNumber
) {
496 UniqueChars bytes
= this->parserAtoms().toPrintableString(name
);
498 ReportOutOfMemory(this->fc_
);
502 if (prevPos
== DeclaredNameInfo::npos
) {
503 errorAt(pos
.begin
, errorNumber
, DeclarationKindString(prevKind
),
508 auto notes
= MakeUnique
<JSErrorNotes
>();
510 ReportOutOfMemory(this->fc_
);
515 JS::LimitedColumnNumberOneOrigin column
;
516 tokenStream
.computeLineAndColumn(prevPos
, &line
, &column
);
518 const size_t MaxWidth
= sizeof("4294967295");
519 char columnNumber
[MaxWidth
];
520 SprintfLiteral(columnNumber
, "%" PRIu32
, column
.oneOriginValue());
521 char lineNumber
[MaxWidth
];
522 SprintfLiteral(lineNumber
, "%" PRIu32
, line
);
524 if (!notes
->addNoteASCII(this->fc_
, getFilename().c_str(), 0, line
,
525 JS::ColumnNumberOneOrigin(column
), GetErrorMessage
,
526 nullptr, noteErrorNumber
, lineNumber
,
531 errorWithNotesAt(std::move(notes
), pos
.begin
, errorNumber
,
532 DeclarationKindString(prevKind
), bytes
.get());
535 template <class ParseHandler
, typename Unit
>
536 void GeneralParser
<ParseHandler
, Unit
>::reportRedeclaration(
537 TaggedParserAtomIndex name
, DeclarationKind prevKind
, TokenPos pos
,
539 reportRedeclarationHelper(name
, prevKind
, pos
, prevPos
, JSMSG_REDECLARED_VAR
,
540 JSMSG_PREV_DECLARATION
);
543 template <class ParseHandler
, typename Unit
>
544 void GeneralParser
<ParseHandler
, Unit
>::reportMismatchedPlacement(
545 TaggedParserAtomIndex name
, DeclarationKind prevKind
, TokenPos pos
,
547 reportRedeclarationHelper(name
, prevKind
, pos
, prevPos
,
548 JSMSG_MISMATCHED_PLACEMENT
, JSMSG_PREV_DECLARATION
);
551 // notePositionalFormalParameter is called for both the arguments of a regular
552 // function definition and the arguments specified by the Function
555 // The 'disallowDuplicateParams' bool indicates whether the use of another
556 // feature (destructuring or default arguments) disables duplicate arguments.
557 // (ECMA-262 requires us to support duplicate parameter names, but, for newer
558 // features, we consider the code to have "opted in" to higher standards and
559 // forbid duplicates.)
560 template <class ParseHandler
, typename Unit
>
561 bool GeneralParser
<ParseHandler
, Unit
>::notePositionalFormalParameter(
562 FunctionNodeType funNode
, TaggedParserAtomIndex name
, uint32_t beginPos
,
563 bool disallowDuplicateParams
, bool* duplicatedParam
) {
564 if (AddDeclaredNamePtr p
=
565 pc_
->functionScope().lookupDeclaredNameForAdd(name
)) {
566 if (disallowDuplicateParams
) {
567 error(JSMSG_BAD_DUP_ARGS
);
571 // Strict-mode disallows duplicate args. We may not know whether we are
572 // in strict mode or not (since the function body hasn't been parsed).
573 // In such cases, report will queue up the potential error and return
575 if (pc_
->sc()->strict()) {
576 UniqueChars bytes
= this->parserAtoms().toPrintableString(name
);
578 ReportOutOfMemory(this->fc_
);
581 if (!strictModeError(JSMSG_DUPLICATE_FORMAL
, bytes
.get())) {
586 *duplicatedParam
= true;
588 DeclarationKind kind
= DeclarationKind::PositionalFormalParameter
;
589 if (!pc_
->functionScope().addDeclaredName(pc_
, p
, name
, kind
, beginPos
)) {
594 if (!pc_
->positionalFormalParameterNames().append(
595 TrivialTaggedParserAtomIndex::from(name
))) {
596 ReportOutOfMemory(this->fc_
);
600 NameNodeType paramNode
;
601 MOZ_TRY_VAR_OR_RETURN(paramNode
, newName(name
), false);
603 handler_
.addFunctionFormalParameter(funNode
, paramNode
);
607 template <class ParseHandler
>
608 bool PerHandlerParser
<ParseHandler
>::noteDestructuredPositionalFormalParameter(
609 FunctionNodeType funNode
, Node destruct
) {
610 // Append an empty name to the positional formals vector to keep track of
611 // argument slots when making FunctionScope::ParserData.
612 if (!pc_
->positionalFormalParameterNames().append(
613 TrivialTaggedParserAtomIndex::null())) {
614 ReportOutOfMemory(fc_
);
618 handler_
.addFunctionFormalParameter(funNode
, destruct
);
622 template <class ParseHandler
, typename Unit
>
623 bool GeneralParser
<ParseHandler
, Unit
>::noteDeclaredName(
624 TaggedParserAtomIndex name
, DeclarationKind kind
, TokenPos pos
,
625 ClosedOver isClosedOver
) {
626 // The asm.js validator does all its own symbol-table management so, as an
627 // optimization, avoid doing any work here.
628 if (pc_
->useAsmOrInsideUseAsm()) {
633 case DeclarationKind::Var
:
634 case DeclarationKind::BodyLevelFunction
: {
635 Maybe
<DeclarationKind
> redeclaredKind
;
637 if (!pc_
->tryDeclareVar(name
, this, kind
, pos
.begin
, &redeclaredKind
,
642 if (redeclaredKind
) {
643 reportRedeclaration(name
, *redeclaredKind
, pos
, prevPos
);
650 case DeclarationKind::ModuleBodyLevelFunction
: {
651 MOZ_ASSERT(pc_
->atModuleLevel());
653 AddDeclaredNamePtr p
= pc_
->varScope().lookupDeclaredNameForAdd(name
);
655 reportRedeclaration(name
, p
->value()->kind(), pos
, p
->value()->pos());
659 if (!pc_
->varScope().addDeclaredName(pc_
, p
, name
, kind
, pos
.begin
,
664 // Body-level functions in modules are always closed over.
665 pc_
->varScope().lookupDeclaredName(name
)->value()->setClosedOver();
670 case DeclarationKind::FormalParameter
: {
671 // It is an early error if any non-positional formal parameter name
672 // (e.g., destructuring formal parameter) is duplicated.
674 AddDeclaredNamePtr p
=
675 pc_
->functionScope().lookupDeclaredNameForAdd(name
);
677 error(JSMSG_BAD_DUP_ARGS
);
681 if (!pc_
->functionScope().addDeclaredName(pc_
, p
, name
, kind
, pos
.begin
,
689 case DeclarationKind::LexicalFunction
:
690 case DeclarationKind::PrivateName
:
691 case DeclarationKind::Synthetic
:
692 case DeclarationKind::PrivateMethod
: {
693 ParseContext::Scope
* scope
= pc_
->innermostScope();
694 AddDeclaredNamePtr p
= scope
->lookupDeclaredNameForAdd(name
);
696 reportRedeclaration(name
, p
->value()->kind(), pos
, p
->value()->pos());
700 if (!scope
->addDeclaredName(pc_
, p
, name
, kind
, pos
.begin
,
708 case DeclarationKind::SloppyLexicalFunction
: {
709 // Functions in block have complex allowances in sloppy mode for being
710 // labelled that other lexical declarations do not have. Those checks
711 // are done in functionStmt.
713 ParseContext::Scope
* scope
= pc_
->innermostScope();
714 if (AddDeclaredNamePtr p
= scope
->lookupDeclaredNameForAdd(name
)) {
715 // It is usually an early error if there is another declaration
716 // with the same name in the same scope.
718 // Sloppy lexical functions may redeclare other sloppy lexical
719 // functions for web compatibility reasons.
720 if (p
->value()->kind() != DeclarationKind::SloppyLexicalFunction
) {
721 reportRedeclaration(name
, p
->value()->kind(), pos
, p
->value()->pos());
725 if (!scope
->addDeclaredName(pc_
, p
, name
, kind
, pos
.begin
,
734 case DeclarationKind::Let
:
735 case DeclarationKind::Const
:
736 case DeclarationKind::Class
:
737 // The BoundNames of LexicalDeclaration and ForDeclaration must not
738 // contain 'let'. (CatchParameter is the only lexical binding form
739 // without this restriction.)
740 if (name
== TaggedParserAtomIndex::WellKnown::let()) {
741 errorAt(pos
.begin
, JSMSG_LEXICAL_DECL_DEFINES_LET
);
745 // For body-level lexically declared names in a function, it is an
746 // early error if there is a formal parameter of the same name. This
747 // needs a special check if there is an extra var scope due to
748 // parameter expressions.
749 if (pc_
->isFunctionExtraBodyVarScopeInnermost()) {
750 DeclaredNamePtr p
= pc_
->functionScope().lookupDeclaredName(name
);
751 if (p
&& DeclarationKindIsParameter(p
->value()->kind())) {
752 reportRedeclaration(name
, p
->value()->kind(), pos
, p
->value()->pos());
759 case DeclarationKind::Import
:
760 // Module code is always strict, so 'let' is always a keyword and never a
762 MOZ_ASSERT(name
!= TaggedParserAtomIndex::WellKnown::let());
765 case DeclarationKind::SimpleCatchParameter
:
766 case DeclarationKind::CatchParameter
: {
767 ParseContext::Scope
* scope
= pc_
->innermostScope();
769 // It is an early error if there is another declaration with the same
770 // name in the same scope.
771 AddDeclaredNamePtr p
= scope
->lookupDeclaredNameForAdd(name
);
773 reportRedeclaration(name
, p
->value()->kind(), pos
, p
->value()->pos());
777 if (!scope
->addDeclaredName(pc_
, p
, name
, kind
, pos
.begin
,
785 case DeclarationKind::CoverArrowParameter
:
786 // CoverArrowParameter is only used as a placeholder declaration kind.
789 case DeclarationKind::PositionalFormalParameter
:
791 "Positional formal parameter names should use "
792 "notePositionalFormalParameter");
795 case DeclarationKind::VarForAnnexBLexicalFunction
:
797 "Synthesized Annex B vars should go through "
798 "addPossibleAnnexBFunctionBox, and "
799 "propagateAndMarkAnnexBFunctionBoxes");
806 template <class ParseHandler
, typename Unit
>
807 bool GeneralParser
<ParseHandler
, Unit
>::noteDeclaredPrivateName(
808 Node nameNode
, TaggedParserAtomIndex name
, PropertyType propType
,
809 FieldPlacement placement
, TokenPos pos
) {
810 ParseContext::Scope
* scope
= pc_
->innermostScope();
811 AddDeclaredNamePtr p
= scope
->lookupDeclaredNameForAdd(name
);
813 DeclarationKind declKind
= DeclarationKind::PrivateName
;
814 ClosedOver closedOver
= ClosedOver::No
;
815 PrivateNameKind kind
;
817 case PropertyType::Field
:
818 kind
= PrivateNameKind::Field
;
820 case PropertyType::FieldWithAccessor
:
821 // In this case, we create a new private field for the underlying storage,
822 // and use the current name for the getter and setter.
823 kind
= PrivateNameKind::GetterSetter
;
825 case PropertyType::Method
:
826 case PropertyType::GeneratorMethod
:
827 case PropertyType::AsyncMethod
:
828 case PropertyType::AsyncGeneratorMethod
:
829 if (placement
== FieldPlacement::Instance
) {
830 // Optimized private method. Non-optimized paths still get
831 // DeclarationKind::Synthetic.
832 declKind
= DeclarationKind::PrivateMethod
;
835 // Methods must be marked closed-over so that
836 // EmitterScope::lookupPrivate() works even if the method is used, but not
837 // within any method (from a computed property name, or debugger frame)
838 closedOver
= ClosedOver::Yes
;
839 kind
= PrivateNameKind::Method
;
841 case PropertyType::Getter
:
842 kind
= PrivateNameKind::Getter
;
844 case PropertyType::Setter
:
845 kind
= PrivateNameKind::Setter
;
848 kind
= PrivateNameKind::None
;
852 PrivateNameKind prevKind
= p
->value()->privateNameKind();
853 if ((prevKind
== PrivateNameKind::Getter
&&
854 kind
== PrivateNameKind::Setter
) ||
855 (prevKind
== PrivateNameKind::Setter
&&
856 kind
== PrivateNameKind::Getter
)) {
857 // Private methods demands that
860 // static set #x(_) {}
864 // Report a SyntaxError.
865 if (placement
== p
->value()->placement()) {
866 p
->value()->setPrivateNameKind(PrivateNameKind::GetterSetter
);
867 handler_
.setPrivateNameKind(nameNode
, PrivateNameKind::GetterSetter
);
872 reportMismatchedPlacement(name
, p
->value()->kind(), pos
, p
->value()->pos());
876 if (!scope
->addDeclaredName(pc_
, p
, name
, declKind
, pos
.begin
, closedOver
)) {
880 DeclaredNamePtr declared
= scope
->lookupDeclaredName(name
);
881 declared
->value()->setPrivateNameKind(kind
);
882 declared
->value()->setFieldPlacement(placement
);
883 handler_
.setPrivateNameKind(nameNode
, kind
);
888 bool ParserBase::noteUsedNameInternal(TaggedParserAtomIndex name
,
889 NameVisibility visibility
,
890 mozilla::Maybe
<TokenPos
> tokenPosition
) {
891 // The asm.js validator does all its own symbol-table management so, as an
892 // optimization, avoid doing any work here.
893 if (pc_
->useAsmOrInsideUseAsm()) {
897 // Global bindings are properties and not actual bindings; we don't need
898 // to know if they are closed over. So no need to track used name at the
899 // global scope. It is not incorrect to track them, this is an
903 // (a) Track private name references, as the used names tracker is used to
904 // provide early errors for undeclared private name references
905 // (b) If the script has extra bindings, track all references to detect
906 // references to extra bindings
907 ParseContext::Scope
* scope
= pc_
->innermostScope();
908 if (pc_
->sc()->isGlobalContext() && scope
== &pc_
->varScope() &&
909 visibility
== NameVisibility::Public
&&
910 !this->compilationState_
.input
.hasExtraBindings()) {
914 return usedNames_
.noteUse(fc_
, name
, visibility
, pc_
->scriptId(), scope
->id(),
918 template <class ParseHandler
>
919 bool PerHandlerParser
<ParseHandler
>::
920 propagateFreeNamesAndMarkClosedOverBindings(ParseContext::Scope
& scope
) {
921 // Now that we have all the declared names in the scope, check which
922 // functions should exhibit Annex B semantics.
923 if (!scope
.propagateAndMarkAnnexBFunctionBoxes(pc_
, this)) {
927 if (handler_
.reuseClosedOverBindings()) {
928 MOZ_ASSERT(pc_
->isOutermostOfCurrentCompile());
930 // Closed over bindings for all scopes are stored in a contiguous array, in
931 // the same order as the order in which scopes are visited, and seprated by
932 // TaggedParserAtomIndex::null().
933 uint32_t slotCount
= scope
.declaredCount();
934 while (auto parserAtom
= handler_
.nextLazyClosedOverBinding()) {
935 scope
.lookupDeclaredName(parserAtom
)->value()->setClosedOver();
936 MOZ_ASSERT(slotCount
> 0);
940 if (pc_
->isGeneratorOrAsync()) {
941 scope
.setOwnStackSlotCount(slotCount
);
946 constexpr bool isSyntaxParser
=
947 std::is_same_v
<ParseHandler
, SyntaxParseHandler
>;
948 uint32_t scriptId
= pc_
->scriptId();
949 uint32_t scopeId
= scope
.id();
951 uint32_t slotCount
= 0;
952 for (BindingIter bi
= scope
.bindings(pc_
); bi
; bi
++) {
953 bool closedOver
= false;
954 if (UsedNamePtr p
= usedNames_
.lookup(bi
.name())) {
955 p
->value().noteBoundInScope(scriptId
, scopeId
, &closedOver
);
959 if constexpr (isSyntaxParser
) {
960 if (!pc_
->closedOverBindingsForLazy().append(
961 TrivialTaggedParserAtomIndex::from(bi
.name()))) {
962 ReportOutOfMemory(fc_
);
969 if constexpr (!isSyntaxParser
) {
975 if constexpr (!isSyntaxParser
) {
976 if (pc_
->isGeneratorOrAsync()) {
977 scope
.setOwnStackSlotCount(slotCount
);
981 // Append a nullptr to denote end-of-scope.
982 if constexpr (isSyntaxParser
) {
983 if (!pc_
->closedOverBindingsForLazy().append(
984 TrivialTaggedParserAtomIndex::null())) {
985 ReportOutOfMemory(fc_
);
993 template <typename Unit
>
994 bool Parser
<FullParseHandler
, Unit
>::checkStatementsEOF() {
995 // This is designed to be paired with parsing a statement list at the top
998 // The statementList() call breaks on TokenKind::RightCurly, so make sure
999 // we've reached EOF here.
1001 if (!tokenStream
.peekToken(&tt
, TokenStream::SlashIsRegExp
)) {
1004 if (tt
!= TokenKind::Eof
) {
1005 error(JSMSG_UNEXPECTED_TOKEN
, "expression", TokenKindToDesc(tt
));
1011 template <typename ScopeT
>
1012 typename
ScopeT::ParserData
* NewEmptyBindingData(FrontendContext
* fc
,
1014 uint32_t numBindings
) {
1015 using Data
= typename
ScopeT::ParserData
;
1016 size_t allocSize
= SizeOfScopeData
<Data
>(numBindings
);
1017 auto* bindings
= alloc
.newWithSize
<Data
>(allocSize
, numBindings
);
1019 ReportOutOfMemory(fc
);
1024 GlobalScope::ParserData
* NewEmptyGlobalScopeData(FrontendContext
* fc
,
1026 uint32_t numBindings
) {
1027 return NewEmptyBindingData
<GlobalScope
>(fc
, alloc
, numBindings
);
1030 LexicalScope::ParserData
* NewEmptyLexicalScopeData(FrontendContext
* fc
,
1032 uint32_t numBindings
) {
1033 return NewEmptyBindingData
<LexicalScope
>(fc
, alloc
, numBindings
);
1036 FunctionScope::ParserData
* NewEmptyFunctionScopeData(FrontendContext
* fc
,
1038 uint32_t numBindings
) {
1039 return NewEmptyBindingData
<FunctionScope
>(fc
, alloc
, numBindings
);
1044 template <class SlotInfo
>
1045 static MOZ_ALWAYS_INLINE ParserBindingName
* InitializeIndexedBindings(
1046 SlotInfo
& slotInfo
, ParserBindingName
* start
, ParserBindingName
* cursor
) {
1050 template <class SlotInfo
, typename UnsignedInteger
, typename
... Step
>
1051 static MOZ_ALWAYS_INLINE ParserBindingName
* InitializeIndexedBindings(
1052 SlotInfo
& slotInfo
, ParserBindingName
* start
, ParserBindingName
* cursor
,
1053 UnsignedInteger
SlotInfo::*field
, const ParserBindingNameVector
& bindings
,
1056 AssertedCast
<UnsignedInteger
>(PointerRangeSize(start
, cursor
));
1058 ParserBindingName
* newCursor
=
1059 std::uninitialized_copy(bindings
.begin(), bindings
.end(), cursor
);
1061 return InitializeIndexedBindings(slotInfo
, start
, newCursor
,
1062 std::forward
<Step
>(step
)...);
1065 } // namespace detail
1067 // Initialize the trailing name bindings of |data|, then set |data->length| to
1068 // the count of bindings added (which must equal |count|).
1070 // First, |firstBindings| are added to the trailing names. Then any
1071 // "steps" present are performed first to last. Each step is 1) a pointer to a
1072 // member of |data| to be set to the current number of bindings added, and 2) a
1073 // vector of |ParserBindingName|s to then copy into |data->trailingNames|.
1074 // (Thus each |data| member field indicates where the corresponding vector's
1076 template <class Data
, typename
... Step
>
1077 static MOZ_ALWAYS_INLINE
void InitializeBindingData(
1078 Data
* data
, uint32_t count
, const ParserBindingNameVector
& firstBindings
,
1080 MOZ_ASSERT(data
->length
== 0, "data shouldn't be filled yet");
1082 ParserBindingName
* start
= GetScopeDataTrailingNamesPointer(data
);
1083 ParserBindingName
* cursor
= std::uninitialized_copy(
1084 firstBindings
.begin(), firstBindings
.end(), start
);
1087 ParserBindingName
* end
=
1089 detail::InitializeIndexedBindings(data
->slotInfo
, start
, cursor
,
1090 std::forward
<Step
>(step
)...);
1092 MOZ_ASSERT(PointerRangeSize(start
, end
) == count
);
1093 data
->length
= count
;
1096 static Maybe
<GlobalScope::ParserData
*> NewGlobalScopeData(
1097 FrontendContext
* fc
, ParseContext::Scope
& scope
, LifoAlloc
& alloc
,
1099 ParserBindingNameVector
vars(fc
);
1100 ParserBindingNameVector
lets(fc
);
1101 ParserBindingNameVector
consts(fc
);
1103 bool allBindingsClosedOver
= pc
->sc()->allBindingsClosedOver();
1104 for (BindingIter bi
= scope
.bindings(pc
); bi
; bi
++) {
1105 bool closedOver
= allBindingsClosedOver
|| bi
.closedOver();
1107 switch (bi
.kind()) {
1108 case BindingKind::Var
: {
1109 bool isTopLevelFunction
=
1110 bi
.declarationKind() == DeclarationKind::BodyLevelFunction
;
1112 ParserBindingName
binding(bi
.name(), closedOver
, isTopLevelFunction
);
1113 if (!vars
.append(binding
)) {
1118 case BindingKind::Let
: {
1119 ParserBindingName
binding(bi
.name(), closedOver
);
1120 if (!lets
.append(binding
)) {
1125 case BindingKind::Const
: {
1126 ParserBindingName
binding(bi
.name(), closedOver
);
1127 if (!consts
.append(binding
)) {
1133 MOZ_CRASH("Bad global scope BindingKind");
1137 GlobalScope::ParserData
* bindings
= nullptr;
1138 uint32_t numBindings
= vars
.length() + lets
.length() + consts
.length();
1140 if (numBindings
> 0) {
1141 bindings
= NewEmptyBindingData
<GlobalScope
>(fc
, alloc
, numBindings
);
1146 // The ordering here is important. See comments in GlobalScope.
1147 InitializeBindingData(bindings
, numBindings
, vars
,
1148 &ParserGlobalScopeSlotInfo::letStart
, lets
,
1149 &ParserGlobalScopeSlotInfo::constStart
, consts
);
1152 return Some(bindings
);
1155 Maybe
<GlobalScope::ParserData
*> ParserBase::newGlobalScopeData(
1156 ParseContext::Scope
& scope
) {
1157 return NewGlobalScopeData(fc_
, scope
, stencilAlloc(), pc_
);
1160 static Maybe
<ModuleScope::ParserData
*> NewModuleScopeData(
1161 FrontendContext
* fc
, ParseContext::Scope
& scope
, LifoAlloc
& alloc
,
1163 ParserBindingNameVector
imports(fc
);
1164 ParserBindingNameVector
vars(fc
);
1165 ParserBindingNameVector
lets(fc
);
1166 ParserBindingNameVector
consts(fc
);
1168 bool allBindingsClosedOver
=
1169 pc
->sc()->allBindingsClosedOver() || scope
.tooBigToOptimize();
1171 for (BindingIter bi
= scope
.bindings(pc
); bi
; bi
++) {
1172 // Imports are indirect bindings and must not be given known slots.
1173 ParserBindingName
binding(bi
.name(),
1174 (allBindingsClosedOver
|| bi
.closedOver()) &&
1175 bi
.kind() != BindingKind::Import
);
1176 switch (bi
.kind()) {
1177 case BindingKind::Import
:
1178 if (!imports
.append(binding
)) {
1182 case BindingKind::Var
:
1183 if (!vars
.append(binding
)) {
1187 case BindingKind::Let
:
1188 if (!lets
.append(binding
)) {
1192 case BindingKind::Const
:
1193 if (!consts
.append(binding
)) {
1198 MOZ_CRASH("Bad module scope BindingKind");
1202 ModuleScope::ParserData
* bindings
= nullptr;
1203 uint32_t numBindings
=
1204 imports
.length() + vars
.length() + lets
.length() + consts
.length();
1206 if (numBindings
> 0) {
1207 bindings
= NewEmptyBindingData
<ModuleScope
>(fc
, alloc
, numBindings
);
1212 // The ordering here is important. See comments in ModuleScope.
1213 InitializeBindingData(bindings
, numBindings
, imports
,
1214 &ParserModuleScopeSlotInfo::varStart
, vars
,
1215 &ParserModuleScopeSlotInfo::letStart
, lets
,
1216 &ParserModuleScopeSlotInfo::constStart
, consts
);
1219 return Some(bindings
);
1222 Maybe
<ModuleScope::ParserData
*> ParserBase::newModuleScopeData(
1223 ParseContext::Scope
& scope
) {
1224 return NewModuleScopeData(fc_
, scope
, stencilAlloc(), pc_
);
1227 static Maybe
<EvalScope::ParserData
*> NewEvalScopeData(
1228 FrontendContext
* fc
, ParseContext::Scope
& scope
, LifoAlloc
& alloc
,
1230 ParserBindingNameVector
vars(fc
);
1232 // Treat all bindings as closed over in non-strict eval.
1233 bool allBindingsClosedOver
=
1234 !pc
->sc()->strict() || pc
->sc()->allBindingsClosedOver();
1235 for (BindingIter bi
= scope
.bindings(pc
); bi
; bi
++) {
1236 // Eval scopes only contain 'var' bindings.
1237 MOZ_ASSERT(bi
.kind() == BindingKind::Var
);
1238 bool isTopLevelFunction
=
1239 bi
.declarationKind() == DeclarationKind::BodyLevelFunction
;
1240 bool closedOver
= allBindingsClosedOver
|| bi
.closedOver();
1242 ParserBindingName
binding(bi
.name(), closedOver
, isTopLevelFunction
);
1243 if (!vars
.append(binding
)) {
1248 EvalScope::ParserData
* bindings
= nullptr;
1249 uint32_t numBindings
= vars
.length();
1251 if (numBindings
> 0) {
1252 bindings
= NewEmptyBindingData
<EvalScope
>(fc
, alloc
, numBindings
);
1257 InitializeBindingData(bindings
, numBindings
, vars
);
1260 return Some(bindings
);
1263 Maybe
<EvalScope::ParserData
*> ParserBase::newEvalScopeData(
1264 ParseContext::Scope
& scope
) {
1265 return NewEvalScopeData(fc_
, scope
, stencilAlloc(), pc_
);
1268 static Maybe
<FunctionScope::ParserData
*> NewFunctionScopeData(
1269 FrontendContext
* fc
, ParseContext::Scope
& scope
, bool hasParameterExprs
,
1270 LifoAlloc
& alloc
, ParseContext
* pc
) {
1271 ParserBindingNameVector
positionalFormals(fc
);
1272 ParserBindingNameVector
formals(fc
);
1273 ParserBindingNameVector
vars(fc
);
1275 bool allBindingsClosedOver
=
1276 pc
->sc()->allBindingsClosedOver() || scope
.tooBigToOptimize();
1277 bool argumentBindingsClosedOver
=
1278 allBindingsClosedOver
|| pc
->isGeneratorOrAsync();
1279 bool hasDuplicateParams
= pc
->functionBox()->hasDuplicateParameters
;
1281 // Positional parameter names must be added in order of appearance as they are
1282 // referenced using argument slots.
1283 for (size_t i
= 0; i
< pc
->positionalFormalParameterNames().length(); i
++) {
1284 TaggedParserAtomIndex name
= pc
->positionalFormalParameterNames()[i
];
1286 ParserBindingName bindName
;
1288 DeclaredNamePtr p
= scope
.lookupDeclaredName(name
);
1290 // Do not consider any positional formal parameters closed over if
1291 // there are parameter defaults. It is the binding in the defaults
1292 // scope that is closed over instead.
1294 argumentBindingsClosedOver
|| (p
&& p
->value()->closedOver());
1296 // If the parameter name has duplicates, only the final parameter
1297 // name should be on the environment, as otherwise the environment
1298 // object would have multiple, same-named properties.
1299 if (hasDuplicateParams
) {
1300 for (size_t j
= pc
->positionalFormalParameterNames().length() - 1;
1302 if (TaggedParserAtomIndex(pc
->positionalFormalParameterNames()[j
]) ==
1310 bindName
= ParserBindingName(name
, closedOver
);
1313 if (!positionalFormals
.append(bindName
)) {
1318 for (BindingIter bi
= scope
.bindings(pc
); bi
; bi
++) {
1319 ParserBindingName
binding(bi
.name(),
1320 allBindingsClosedOver
|| bi
.closedOver());
1321 switch (bi
.kind()) {
1322 case BindingKind::FormalParameter
:
1323 // Positional parameter names are already handled above.
1324 if (bi
.declarationKind() == DeclarationKind::FormalParameter
) {
1325 if (!formals
.append(binding
)) {
1330 case BindingKind::Var
:
1331 // The only vars in the function scope when there are parameter
1332 // exprs, which induces a separate var environment, should be the
1333 // special bindings.
1334 MOZ_ASSERT_IF(hasParameterExprs
,
1335 FunctionScope::isSpecialName(bi
.name()));
1336 if (!vars
.append(binding
)) {
1340 case BindingKind::Let
:
1341 case BindingKind::Const
:
1344 MOZ_CRASH("bad function scope BindingKind");
1349 FunctionScope::ParserData
* bindings
= nullptr;
1350 uint32_t numBindings
=
1351 positionalFormals
.length() + formals
.length() + vars
.length();
1353 if (numBindings
> 0) {
1354 bindings
= NewEmptyBindingData
<FunctionScope
>(fc
, alloc
, numBindings
);
1359 // The ordering here is important. See comments in FunctionScope.
1360 InitializeBindingData(
1361 bindings
, numBindings
, positionalFormals
,
1362 &ParserFunctionScopeSlotInfo::nonPositionalFormalStart
, formals
,
1363 &ParserFunctionScopeSlotInfo::varStart
, vars
);
1366 return Some(bindings
);
1369 // Compute if `NewFunctionScopeData` would return any binding list with any
1370 // entry marked as closed-over. This is done without the need to allocate the
1371 // binding list. If true, an EnvironmentObject will be needed at runtime.
1372 bool FunctionScopeHasClosedOverBindings(ParseContext
* pc
) {
1373 bool allBindingsClosedOver
= pc
->sc()->allBindingsClosedOver() ||
1374 pc
->functionScope().tooBigToOptimize();
1376 for (BindingIter bi
= pc
->functionScope().bindings(pc
); bi
; bi
++) {
1377 switch (bi
.kind()) {
1378 case BindingKind::FormalParameter
:
1379 case BindingKind::Var
:
1380 if (allBindingsClosedOver
|| bi
.closedOver()) {
1393 Maybe
<FunctionScope::ParserData
*> ParserBase::newFunctionScopeData(
1394 ParseContext::Scope
& scope
, bool hasParameterExprs
) {
1395 return NewFunctionScopeData(fc_
, scope
, hasParameterExprs
, stencilAlloc(),
1399 VarScope::ParserData
* NewEmptyVarScopeData(FrontendContext
* fc
,
1401 uint32_t numBindings
) {
1402 return NewEmptyBindingData
<VarScope
>(fc
, alloc
, numBindings
);
1405 static Maybe
<VarScope::ParserData
*> NewVarScopeData(FrontendContext
* fc
,
1406 ParseContext::Scope
& scope
,
1409 ParserBindingNameVector
vars(fc
);
1411 bool allBindingsClosedOver
=
1412 pc
->sc()->allBindingsClosedOver() || scope
.tooBigToOptimize();
1414 for (BindingIter bi
= scope
.bindings(pc
); bi
; bi
++) {
1415 if (bi
.kind() == BindingKind::Var
) {
1416 ParserBindingName
binding(bi
.name(),
1417 allBindingsClosedOver
|| bi
.closedOver());
1418 if (!vars
.append(binding
)) {
1423 bi
.kind() == BindingKind::Let
|| bi
.kind() == BindingKind::Const
,
1424 "bad var scope BindingKind");
1428 VarScope::ParserData
* bindings
= nullptr;
1429 uint32_t numBindings
= vars
.length();
1431 if (numBindings
> 0) {
1432 bindings
= NewEmptyBindingData
<VarScope
>(fc
, alloc
, numBindings
);
1437 InitializeBindingData(bindings
, numBindings
, vars
);
1440 return Some(bindings
);
1443 // Compute if `NewVarScopeData` would return any binding list. This is done
1444 // without allocate the binding list.
1445 static bool VarScopeHasBindings(ParseContext
* pc
) {
1446 for (BindingIter bi
= pc
->varScope().bindings(pc
); bi
; bi
++) {
1447 if (bi
.kind() == BindingKind::Var
) {
1455 Maybe
<VarScope::ParserData
*> ParserBase::newVarScopeData(
1456 ParseContext::Scope
& scope
) {
1457 return NewVarScopeData(fc_
, scope
, stencilAlloc(), pc_
);
1460 static Maybe
<LexicalScope::ParserData
*> NewLexicalScopeData(
1461 FrontendContext
* fc
, ParseContext::Scope
& scope
, LifoAlloc
& alloc
,
1463 ParserBindingNameVector
lets(fc
);
1464 ParserBindingNameVector
consts(fc
);
1466 bool allBindingsClosedOver
=
1467 pc
->sc()->allBindingsClosedOver() || scope
.tooBigToOptimize();
1469 for (BindingIter bi
= scope
.bindings(pc
); bi
; bi
++) {
1470 ParserBindingName
binding(bi
.name(),
1471 allBindingsClosedOver
|| bi
.closedOver());
1472 switch (bi
.kind()) {
1473 case BindingKind::Let
:
1474 if (!lets
.append(binding
)) {
1478 case BindingKind::Const
:
1479 if (!consts
.append(binding
)) {
1483 case BindingKind::Var
:
1484 case BindingKind::FormalParameter
:
1487 MOZ_CRASH("Bad lexical scope BindingKind");
1492 LexicalScope::ParserData
* bindings
= nullptr;
1493 uint32_t numBindings
= lets
.length() + consts
.length();
1495 if (numBindings
> 0) {
1496 bindings
= NewEmptyBindingData
<LexicalScope
>(fc
, alloc
, numBindings
);
1501 // The ordering here is important. See comments in LexicalScope.
1502 InitializeBindingData(bindings
, numBindings
, lets
,
1503 &ParserLexicalScopeSlotInfo::constStart
, consts
);
1506 return Some(bindings
);
1509 // Compute if `NewLexicalScopeData` would return any binding list with any entry
1510 // marked as closed-over. This is done without the need to allocate the binding
1511 // list. If true, an EnvironmentObject will be needed at runtime.
1512 bool LexicalScopeHasClosedOverBindings(ParseContext
* pc
,
1513 ParseContext::Scope
& scope
) {
1514 bool allBindingsClosedOver
=
1515 pc
->sc()->allBindingsClosedOver() || scope
.tooBigToOptimize();
1517 for (BindingIter bi
= scope
.bindings(pc
); bi
; bi
++) {
1518 switch (bi
.kind()) {
1519 case BindingKind::Let
:
1520 case BindingKind::Const
:
1521 if (allBindingsClosedOver
|| bi
.closedOver()) {
1534 Maybe
<LexicalScope::ParserData
*> ParserBase::newLexicalScopeData(
1535 ParseContext::Scope
& scope
) {
1536 return NewLexicalScopeData(fc_
, scope
, stencilAlloc(), pc_
);
1539 static Maybe
<ClassBodyScope::ParserData
*> NewClassBodyScopeData(
1540 FrontendContext
* fc
, ParseContext::Scope
& scope
, LifoAlloc
& alloc
,
1542 ParserBindingNameVector
privateBrand(fc
);
1543 ParserBindingNameVector
synthetics(fc
);
1544 ParserBindingNameVector
privateMethods(fc
);
1546 bool allBindingsClosedOver
=
1547 pc
->sc()->allBindingsClosedOver() || scope
.tooBigToOptimize();
1549 for (BindingIter bi
= scope
.bindings(pc
); bi
; bi
++) {
1550 ParserBindingName
binding(bi
.name(),
1551 allBindingsClosedOver
|| bi
.closedOver());
1552 switch (bi
.kind()) {
1553 case BindingKind::Synthetic
:
1555 TaggedParserAtomIndex::WellKnown::dot_privateBrand_()) {
1556 MOZ_ASSERT(privateBrand
.empty());
1557 if (!privateBrand
.append(binding
)) {
1561 if (!synthetics
.append(binding
)) {
1567 case BindingKind::PrivateMethod
:
1568 if (!privateMethods
.append(binding
)) {
1574 MOZ_CRASH("bad class body scope BindingKind");
1579 // We should have zero or one private brands.
1580 MOZ_ASSERT(privateBrand
.length() == 0 || privateBrand
.length() == 1);
1582 ClassBodyScope::ParserData
* bindings
= nullptr;
1583 uint32_t numBindings
=
1584 privateBrand
.length() + synthetics
.length() + privateMethods
.length();
1586 if (numBindings
> 0) {
1587 bindings
= NewEmptyBindingData
<ClassBodyScope
>(fc
, alloc
, numBindings
);
1591 // To simplify initialization of the bindings, we concatenate the
1592 // synthetics+privateBrand vector such that the private brand is always the
1593 // first element, as ordering is important. See comments in ClassBodyScope.
1594 ParserBindingNameVector
brandAndSynthetics(fc
);
1595 if (!brandAndSynthetics
.appendAll(privateBrand
)) {
1598 if (!brandAndSynthetics
.appendAll(synthetics
)) {
1602 // The ordering here is important. See comments in ClassBodyScope.
1603 InitializeBindingData(bindings
, numBindings
, brandAndSynthetics
,
1604 &ParserClassBodyScopeSlotInfo::privateMethodStart
,
1608 // `EmitterScope::lookupPrivate()` requires `.privateBrand` to be stored in a
1609 // predictable slot: the first slot available in the environment object,
1610 // `ClassBodyLexicalEnvironmentObject::privateBrandSlot()`. We assume that
1611 // if `.privateBrand` is first in the scope, it will be stored there.
1612 MOZ_ASSERT_IF(!privateBrand
.empty(),
1613 GetScopeDataTrailingNames(bindings
)[0].name() ==
1614 TaggedParserAtomIndex::WellKnown::dot_privateBrand_());
1616 return Some(bindings
);
1619 Maybe
<ClassBodyScope::ParserData
*> ParserBase::newClassBodyScopeData(
1620 ParseContext::Scope
& scope
) {
1621 return NewClassBodyScopeData(fc_
, scope
, stencilAlloc(), pc_
);
1625 SyntaxParseHandler::LexicalScopeNodeResult
1626 PerHandlerParser
<SyntaxParseHandler
>::finishLexicalScope(
1627 ParseContext::Scope
& scope
, Node body
, ScopeKind kind
) {
1628 if (!propagateFreeNamesAndMarkClosedOverBindings(scope
)) {
1629 return errorResult();
1632 return handler_
.newLexicalScope(body
);
1636 FullParseHandler::LexicalScopeNodeResult
1637 PerHandlerParser
<FullParseHandler
>::finishLexicalScope(
1638 ParseContext::Scope
& scope
, ParseNode
* body
, ScopeKind kind
) {
1639 if (!propagateFreeNamesAndMarkClosedOverBindings(scope
)) {
1640 return errorResult();
1643 Maybe
<LexicalScope::ParserData
*> bindings
= newLexicalScopeData(scope
);
1645 return errorResult();
1648 return handler_
.newLexicalScope(*bindings
, body
, kind
);
1652 SyntaxParseHandler::ClassBodyScopeNodeResult
1653 PerHandlerParser
<SyntaxParseHandler
>::finishClassBodyScope(
1654 ParseContext::Scope
& scope
, ListNodeType body
) {
1655 if (!propagateFreeNamesAndMarkClosedOverBindings(scope
)) {
1656 return errorResult();
1659 return handler_
.newClassBodyScope(body
);
1663 FullParseHandler::ClassBodyScopeNodeResult
1664 PerHandlerParser
<FullParseHandler
>::finishClassBodyScope(
1665 ParseContext::Scope
& scope
, ListNode
* body
) {
1666 if (!propagateFreeNamesAndMarkClosedOverBindings(scope
)) {
1667 return errorResult();
1670 Maybe
<ClassBodyScope::ParserData
*> bindings
= newClassBodyScopeData(scope
);
1672 return errorResult();
1675 return handler_
.newClassBodyScope(*bindings
, body
);
1678 template <class ParseHandler
>
1679 bool PerHandlerParser
<ParseHandler
>::checkForUndefinedPrivateFields(
1680 EvalSharedContext
* evalSc
) {
1681 if (!this->compilationState_
.isInitialStencil()) {
1682 // We're delazifying -- so we already checked private names during first
1687 Vector
<UnboundPrivateName
, 8> unboundPrivateNames(fc_
);
1688 if (!usedNames_
.getUnboundPrivateNames(unboundPrivateNames
)) {
1692 // No unbound names, let's get out of here!
1693 if (unboundPrivateNames
.empty()) {
1697 // It is an early error if there's private name references unbound,
1698 // unless it's an eval, in which case we need to check the scope
1701 // The unbound private names are sorted, so just grab the first one.
1702 UnboundPrivateName minimum
= unboundPrivateNames
[0];
1703 UniqueChars str
= this->parserAtoms().toPrintableString(minimum
.atom
);
1705 ReportOutOfMemory(this->fc_
);
1709 errorAt(minimum
.position
.begin
, JSMSG_MISSING_PRIVATE_DECL
, str
.get());
1713 // It's important that the unbound private names are sorted, as we
1714 // want our errors to always be issued to the first textually.
1715 for (UnboundPrivateName unboundName
: unboundPrivateNames
) {
1716 // If the enclosingScope is non-syntactic, then we are in a
1717 // Debugger.Frame.prototype.eval call. In order to find the declared private
1718 // names, we must use the effective scope that was determined when creating
1719 // the scopeContext.
1720 if (!this->compilationState_
.scopeContext
1721 .effectiveScopePrivateFieldCacheHas(unboundName
.atom
)) {
1722 UniqueChars str
= this->parserAtoms().toPrintableString(unboundName
.atom
);
1724 ReportOutOfMemory(this->fc_
);
1727 errorAt(unboundName
.position
.begin
, JSMSG_MISSING_PRIVATE_DECL
,
1736 template <typename Unit
>
1737 FullParseHandler::LexicalScopeNodeResult
1738 Parser
<FullParseHandler
, Unit
>::evalBody(EvalSharedContext
* evalsc
) {
1739 SourceParseContext
evalpc(this, evalsc
, /* newDirectives = */ nullptr);
1740 if (!evalpc
.init()) {
1741 return errorResult();
1744 ParseContext::VarScope
varScope(this);
1745 if (!varScope
.init(pc_
)) {
1746 return errorResult();
1749 LexicalScopeNode
* body
;
1751 // All evals have an implicit non-extensible lexical scope.
1752 ParseContext::Scope
lexicalScope(this);
1753 if (!lexicalScope
.init(pc_
)) {
1754 return errorResult();
1758 MOZ_TRY_VAR(list
, statementList(YieldIsName
));
1760 if (!checkStatementsEOF()) {
1761 return errorResult();
1764 // Private names not lexically defined must trigger a syntax error.
1765 if (!checkForUndefinedPrivateFields(evalsc
)) {
1766 return errorResult();
1769 MOZ_TRY_VAR(body
, finishLexicalScope(lexicalScope
, list
));
1773 if (evalpc
.superScopeNeedsHomeObject() &&
1774 !this->compilationState_
.input
.enclosingScope
.isNull()) {
1775 // If superScopeNeedsHomeObject_ is set and we are an entry-point
1776 // ParseContext, then we must be emitting an eval script, and the
1777 // outer function must already be marked as needing a home object
1778 // since it contains an eval.
1780 this->compilationState_
.scopeContext
.hasFunctionNeedsHomeObjectOnChain
,
1781 "Eval must have found an enclosing function box scope that "
1782 "allows super.property");
1786 if (!CheckParseTree(this->fc_
, alloc_
, body
)) {
1787 return errorResult();
1790 ParseNode
* node
= body
;
1791 // Don't constant-fold inside "use asm" code, as this could create a parse
1792 // tree that doesn't type-check as asm.js.
1793 if (!pc_
->useAsmOrInsideUseAsm()) {
1794 if (!FoldConstants(this->fc_
, this->parserAtoms(), &node
, &handler_
)) {
1795 return errorResult();
1798 body
= handler_
.asLexicalScopeNode(node
);
1800 if (!this->setSourceMapInfo()) {
1801 return errorResult();
1804 if (pc_
->sc()->strict()) {
1805 if (!propagateFreeNamesAndMarkClosedOverBindings(varScope
)) {
1806 return errorResult();
1809 // For non-strict eval scripts, since all bindings are automatically
1810 // considered closed over, we don't need to call propagateFreeNames-
1811 // AndMarkClosedOverBindings. However, Annex B.3.3 functions still need to
1813 if (!varScope
.propagateAndMarkAnnexBFunctionBoxes(pc_
, this)) {
1814 return errorResult();
1818 Maybe
<EvalScope::ParserData
*> bindings
= newEvalScopeData(pc_
->varScope());
1820 return errorResult();
1822 evalsc
->bindings
= *bindings
;
1827 template <typename Unit
>
1828 FullParseHandler::ListNodeResult Parser
<FullParseHandler
, Unit
>::globalBody(
1829 GlobalSharedContext
* globalsc
) {
1830 SourceParseContext
globalpc(this, globalsc
, /* newDirectives = */ nullptr);
1831 if (!globalpc
.init()) {
1832 return errorResult();
1835 ParseContext::VarScope
varScope(this);
1836 if (!varScope
.init(pc_
)) {
1837 return errorResult();
1841 MOZ_TRY_VAR(body
, statementList(YieldIsName
));
1843 if (!checkStatementsEOF()) {
1844 return errorResult();
1847 if (!CheckParseTree(this->fc_
, alloc_
, body
)) {
1848 return errorResult();
1851 if (!checkForUndefinedPrivateFields()) {
1852 return errorResult();
1855 ParseNode
* node
= body
;
1856 // Don't constant-fold inside "use asm" code, as this could create a parse
1857 // tree that doesn't type-check as asm.js.
1858 if (!pc_
->useAsmOrInsideUseAsm()) {
1859 if (!FoldConstants(this->fc_
, this->parserAtoms(), &node
, &handler_
)) {
1860 return errorResult();
1863 body
= &node
->as
<ListNode
>();
1865 if (!this->setSourceMapInfo()) {
1866 return errorResult();
1869 // For global scripts, whether bindings are closed over or not doesn't
1870 // matter, so no need to call propagateFreeNamesAndMarkClosedOver-
1871 // Bindings. However, Annex B.3.3 functions still need to be marked.
1872 if (!varScope
.propagateAndMarkAnnexBFunctionBoxes(pc_
, this)) {
1873 return errorResult();
1876 Maybe
<GlobalScope::ParserData
*> bindings
=
1877 newGlobalScopeData(pc_
->varScope());
1879 return errorResult();
1881 globalsc
->bindings
= *bindings
;
1886 template <typename Unit
>
1887 FullParseHandler::ModuleNodeResult Parser
<FullParseHandler
, Unit
>::moduleBody(
1888 ModuleSharedContext
* modulesc
) {
1889 MOZ_ASSERT(checkOptionsCalled_
);
1891 this->compilationState_
.moduleMetadata
=
1892 fc_
->getAllocator()->template new_
<StencilModuleMetadata
>();
1893 if (!this->compilationState_
.moduleMetadata
) {
1894 return errorResult();
1897 SourceParseContext
modulepc(this, modulesc
, nullptr);
1898 if (!modulepc
.init()) {
1899 return errorResult();
1902 ParseContext::VarScope
varScope(this);
1903 if (!varScope
.init(pc_
)) {
1904 return errorResult();
1907 ModuleNodeType moduleNode
;
1908 MOZ_TRY_VAR(moduleNode
, handler_
.newModule(pos()));
1910 AutoAwaitIsKeyword
<FullParseHandler
, Unit
> awaitIsKeyword(
1911 this, AwaitIsModuleKeyword
);
1913 MOZ_TRY_VAR(stmtList
, statementList(YieldIsName
));
1915 MOZ_ASSERT(stmtList
->isKind(ParseNodeKind::StatementList
));
1916 moduleNode
->setBody(&stmtList
->template as
<ListNode
>());
1918 if (pc_
->isAsync()) {
1919 if (!noteUsedName(TaggedParserAtomIndex::WellKnown::dot_generator_())) {
1920 return errorResult();
1923 if (!pc_
->declareTopLevelDotGeneratorName()) {
1924 return errorResult();
1929 if (!tokenStream
.getToken(&tt
, TokenStream::SlashIsRegExp
)) {
1930 return errorResult();
1932 if (tt
!= TokenKind::Eof
) {
1933 error(JSMSG_GARBAGE_AFTER_INPUT
, "module", TokenKindToDesc(tt
));
1934 return errorResult();
1937 // Set the module to async if an await keyword was found at the top level.
1938 if (pc_
->isAsync()) {
1939 pc_
->sc()->asModuleContext()->builder
.noteAsync(
1940 *this->compilationState_
.moduleMetadata
);
1943 // Generate the Import/Export tables and store in CompilationState.
1944 if (!modulesc
->builder
.buildTables(*this->compilationState_
.moduleMetadata
)) {
1945 return errorResult();
1948 // Check exported local bindings exist and mark them as closed over.
1949 StencilModuleMetadata
& moduleMetadata
=
1950 *this->compilationState_
.moduleMetadata
;
1951 for (auto entry
: moduleMetadata
.localExportEntries
) {
1952 DeclaredNamePtr p
= modulepc
.varScope().lookupDeclaredName(entry
.localName
);
1954 UniqueChars str
= this->parserAtoms().toPrintableString(entry
.localName
);
1956 ReportOutOfMemory(this->fc_
);
1957 return errorResult();
1960 errorNoOffset(JSMSG_MISSING_EXPORT
, str
.get());
1961 return errorResult();
1964 p
->value()->setClosedOver();
1967 // Reserve an environment slot for a "*namespace*" psuedo-binding and mark as
1968 // closed-over. We do not know until module linking if this will be used.
1969 if (!noteDeclaredName(
1970 TaggedParserAtomIndex::WellKnown::star_namespace_star_(),
1971 DeclarationKind::Const
, pos())) {
1972 return errorResult();
1975 .lookupDeclaredName(
1976 TaggedParserAtomIndex::WellKnown::star_namespace_star_())
1980 if (options().deoptimizeModuleGlobalVars
) {
1981 for (BindingIter bi
= modulepc
.varScope().bindings(pc_
); bi
; bi
++) {
1986 if (!CheckParseTree(this->fc_
, alloc_
, stmtList
)) {
1987 return errorResult();
1990 ParseNode
* node
= stmtList
;
1991 // Don't constant-fold inside "use asm" code, as this could create a parse
1992 // tree that doesn't type-check as asm.js.
1993 if (!pc_
->useAsmOrInsideUseAsm()) {
1994 if (!FoldConstants(this->fc_
, this->parserAtoms(), &node
, &handler_
)) {
1995 return errorResult();
1998 stmtList
= &node
->as
<ListNode
>();
2000 if (!this->setSourceMapInfo()) {
2001 return errorResult();
2004 // Private names not lexically defined must trigger a syntax error.
2005 if (!checkForUndefinedPrivateFields()) {
2006 return errorResult();
2009 if (!propagateFreeNamesAndMarkClosedOverBindings(modulepc
.varScope())) {
2010 return errorResult();
2013 Maybe
<ModuleScope::ParserData
*> bindings
=
2014 newModuleScopeData(modulepc
.varScope());
2016 return errorResult();
2019 modulesc
->bindings
= *bindings
;
2023 template <typename Unit
>
2024 SyntaxParseHandler::ModuleNodeResult
2025 Parser
<SyntaxParseHandler
, Unit
>::moduleBody(ModuleSharedContext
* modulesc
) {
2026 MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
2027 return errorResult();
2030 template <class ParseHandler
>
2031 typename
ParseHandler::NameNodeResult
2032 PerHandlerParser
<ParseHandler
>::newInternalDotName(TaggedParserAtomIndex name
) {
2033 NameNodeType nameNode
;
2034 MOZ_TRY_VAR(nameNode
, newName(name
));
2035 if (!noteUsedName(name
)) {
2036 return errorResult();
2041 template <class ParseHandler
>
2042 typename
ParseHandler::NameNodeResult
2043 PerHandlerParser
<ParseHandler
>::newThisName() {
2044 return newInternalDotName(TaggedParserAtomIndex::WellKnown::dot_this_());
2047 template <class ParseHandler
>
2048 typename
ParseHandler::NameNodeResult
2049 PerHandlerParser
<ParseHandler
>::newNewTargetName() {
2050 return newInternalDotName(TaggedParserAtomIndex::WellKnown::dot_newTarget_());
2053 template <class ParseHandler
>
2054 typename
ParseHandler::NameNodeResult
2055 PerHandlerParser
<ParseHandler
>::newDotGeneratorName() {
2056 return newInternalDotName(TaggedParserAtomIndex::WellKnown::dot_generator_());
2059 template <class ParseHandler
>
2060 bool PerHandlerParser
<ParseHandler
>::finishFunctionScopes(
2061 bool isStandaloneFunction
) {
2062 FunctionBox
* funbox
= pc_
->functionBox();
2064 if (funbox
->hasParameterExprs
) {
2065 if (!propagateFreeNamesAndMarkClosedOverBindings(pc_
->functionScope())) {
2069 // Functions with parameter expressions utilize the FunctionScope for vars
2070 // generated by sloppy-direct-evals, as well as arguments (which are
2071 // lexicals bindings). If the function body has var bindings (or has a
2072 // sloppy-direct-eval that might), then an extra VarScope must be created
2074 if (VarScopeHasBindings(pc_
) ||
2075 funbox
->needsExtraBodyVarEnvironmentRegardlessOfBindings()) {
2076 funbox
->setFunctionHasExtraBodyVarScope();
2080 // See: JSFunction::needsCallObject()
2081 if (FunctionScopeHasClosedOverBindings(pc_
) ||
2082 funbox
->needsCallObjectRegardlessOfBindings()) {
2083 funbox
->setNeedsFunctionEnvironmentObjects();
2086 if (funbox
->isNamedLambda() && !isStandaloneFunction
) {
2087 if (!propagateFreeNamesAndMarkClosedOverBindings(pc_
->namedLambdaScope())) {
2091 // See: JSFunction::needsNamedLambdaEnvironment()
2092 if (LexicalScopeHasClosedOverBindings(pc_
, pc_
->namedLambdaScope())) {
2093 funbox
->setNeedsFunctionEnvironmentObjects();
2101 bool PerHandlerParser
<FullParseHandler
>::finishFunction(
2102 bool isStandaloneFunction
/* = false */) {
2103 if (!finishFunctionScopes(isStandaloneFunction
)) {
2107 FunctionBox
* funbox
= pc_
->functionBox();
2108 ScriptStencil
& script
= funbox
->functionStencil();
2110 if (funbox
->isInterpreted()) {
2111 // BCE will need to generate bytecode for this.
2112 funbox
->emitBytecode
= true;
2113 this->compilationState_
.nonLazyFunctionCount
++;
2116 bool hasParameterExprs
= funbox
->hasParameterExprs
;
2118 if (hasParameterExprs
) {
2119 Maybe
<VarScope::ParserData
*> bindings
= newVarScopeData(pc_
->varScope());
2123 funbox
->setExtraVarScopeBindings(*bindings
);
2125 MOZ_ASSERT(bool(*bindings
) == VarScopeHasBindings(pc_
));
2126 MOZ_ASSERT_IF(!funbox
->needsExtraBodyVarEnvironmentRegardlessOfBindings(),
2127 bool(*bindings
) == funbox
->functionHasExtraBodyVarScope());
2131 Maybe
<FunctionScope::ParserData
*> bindings
=
2132 newFunctionScopeData(pc_
->functionScope(), hasParameterExprs
);
2136 funbox
->setFunctionScopeBindings(*bindings
);
2139 if (funbox
->isNamedLambda() && !isStandaloneFunction
) {
2140 Maybe
<LexicalScope::ParserData
*> bindings
=
2141 newLexicalScopeData(pc_
->namedLambdaScope());
2145 funbox
->setNamedLambdaBindings(*bindings
);
2148 funbox
->finishScriptFlags();
2149 funbox
->copyFunctionFields(script
);
2151 if (this->compilationState_
.isInitialStencil()) {
2152 ScriptStencilExtra
& scriptExtra
= funbox
->functionExtraStencil();
2153 funbox
->copyFunctionExtraFields(scriptExtra
);
2154 funbox
->copyScriptExtraFields(scriptExtra
);
2161 bool PerHandlerParser
<SyntaxParseHandler
>::finishFunction(
2162 bool isStandaloneFunction
/* = false */) {
2163 // The BaseScript for a lazily parsed function needs to know its set of
2164 // free variables and inner functions so that when it is fully parsed, we
2165 // can skip over any already syntax parsed inner functions and still
2166 // retain correct scope information.
2168 if (!finishFunctionScopes(isStandaloneFunction
)) {
2172 FunctionBox
* funbox
= pc_
->functionBox();
2173 ScriptStencil
& script
= funbox
->functionStencil();
2175 funbox
->finishScriptFlags();
2176 funbox
->copyFunctionFields(script
);
2178 ScriptStencilExtra
& scriptExtra
= funbox
->functionExtraStencil();
2179 funbox
->copyFunctionExtraFields(scriptExtra
);
2180 funbox
->copyScriptExtraFields(scriptExtra
);
2182 // Elide nullptr sentinels from end of binding list. These are inserted for
2183 // each scope regardless of if any bindings are actually closed over.
2185 AtomVector
& closedOver
= pc_
->closedOverBindingsForLazy();
2186 while (!closedOver
.empty() && !closedOver
.back()) {
2187 closedOver
.popBack();
2191 // Check if we will overflow the `ngcthings` field later.
2192 mozilla::CheckedUint32 ngcthings
=
2193 mozilla::CheckedUint32(pc_
->innerFunctionIndexesForLazy
.length()) +
2194 mozilla::CheckedUint32(pc_
->closedOverBindingsForLazy().length());
2195 if (!ngcthings
.isValid()) {
2196 ReportAllocationOverflow(fc_
);
2200 // If there are no script-things, we can return early without allocating.
2201 if (ngcthings
.value() == 0) {
2202 MOZ_ASSERT(!script
.hasGCThings());
2206 TaggedScriptThingIndex
* cursor
= nullptr;
2207 if (!this->compilationState_
.allocateGCThingsUninitialized(
2208 fc_
, funbox
->index(), ngcthings
.value(), &cursor
)) {
2212 // Copy inner-function and closed-over-binding info for the stencil. The order
2213 // is important here. We emit functions first, followed by the bindings info.
2214 // The bindings list uses nullptr as delimiter to separates the bindings per
2217 // See: FullParseHandler::nextLazyInnerFunction(),
2218 // FullParseHandler::nextLazyClosedOverBinding()
2219 for (const ScriptIndex
& index
: pc_
->innerFunctionIndexesForLazy
) {
2220 void* raw
= &(*cursor
++);
2221 new (raw
) TaggedScriptThingIndex(index
);
2223 for (auto binding
: pc_
->closedOverBindingsForLazy()) {
2224 void* raw
= &(*cursor
++);
2226 this->parserAtoms().markUsedByStencil(binding
, ParserAtom::Atomize::Yes
);
2227 new (raw
) TaggedScriptThingIndex(binding
);
2229 new (raw
) TaggedScriptThingIndex();
2236 static YieldHandling
GetYieldHandling(GeneratorKind generatorKind
) {
2237 if (generatorKind
== GeneratorKind::NotGenerator
) {
2240 return YieldIsKeyword
;
2243 static AwaitHandling
GetAwaitHandling(FunctionAsyncKind asyncKind
) {
2244 if (asyncKind
== FunctionAsyncKind::SyncFunction
) {
2247 return AwaitIsKeyword
;
2250 static FunctionFlags
InitialFunctionFlags(FunctionSyntaxKind kind
,
2251 GeneratorKind generatorKind
,
2252 FunctionAsyncKind asyncKind
,
2253 bool isSelfHosting
) {
2254 FunctionFlags flags
= {};
2257 case FunctionSyntaxKind::Expression
:
2258 flags
= (generatorKind
== GeneratorKind::NotGenerator
&&
2259 asyncKind
== FunctionAsyncKind::SyncFunction
2260 ? FunctionFlags::INTERPRETED_LAMBDA
2261 : FunctionFlags::INTERPRETED_LAMBDA_GENERATOR_OR_ASYNC
);
2263 case FunctionSyntaxKind::Arrow
:
2264 flags
= FunctionFlags::INTERPRETED_LAMBDA_ARROW
;
2266 case FunctionSyntaxKind::Method
:
2267 case FunctionSyntaxKind::FieldInitializer
:
2268 case FunctionSyntaxKind::StaticClassBlock
:
2269 flags
= FunctionFlags::INTERPRETED_METHOD
;
2271 case FunctionSyntaxKind::ClassConstructor
:
2272 case FunctionSyntaxKind::DerivedClassConstructor
:
2273 flags
= FunctionFlags::INTERPRETED_CLASS_CTOR
;
2275 case FunctionSyntaxKind::Getter
:
2276 flags
= FunctionFlags::INTERPRETED_GETTER
;
2278 case FunctionSyntaxKind::Setter
:
2279 flags
= FunctionFlags::INTERPRETED_SETTER
;
2282 MOZ_ASSERT(kind
== FunctionSyntaxKind::Statement
);
2283 flags
= (generatorKind
== GeneratorKind::NotGenerator
&&
2284 asyncKind
== FunctionAsyncKind::SyncFunction
2285 ? FunctionFlags::INTERPRETED_NORMAL
2286 : FunctionFlags::INTERPRETED_GENERATOR_OR_ASYNC
);
2289 if (isSelfHosting
) {
2290 flags
.setIsSelfHostedBuiltin();
2296 template <typename Unit
>
2297 FullParseHandler::FunctionNodeResult
2298 Parser
<FullParseHandler
, Unit
>::standaloneFunction(
2299 const Maybe
<uint32_t>& parameterListEnd
, FunctionSyntaxKind syntaxKind
,
2300 GeneratorKind generatorKind
, FunctionAsyncKind asyncKind
,
2301 Directives inheritedDirectives
, Directives
* newDirectives
) {
2302 MOZ_ASSERT(checkOptionsCalled_
);
2305 if (!tokenStream
.getToken(&tt
, TokenStream::SlashIsRegExp
)) {
2306 return errorResult();
2308 if (asyncKind
== FunctionAsyncKind::AsyncFunction
) {
2309 MOZ_ASSERT(tt
== TokenKind::Async
);
2310 if (!tokenStream
.getToken(&tt
, TokenStream::SlashIsRegExp
)) {
2311 return errorResult();
2314 MOZ_ASSERT(tt
== TokenKind::Function
);
2316 if (!tokenStream
.getToken(&tt
)) {
2317 return errorResult();
2319 if (generatorKind
== GeneratorKind::Generator
) {
2320 MOZ_ASSERT(tt
== TokenKind::Mul
);
2321 if (!tokenStream
.getToken(&tt
)) {
2322 return errorResult();
2326 // Skip function name, if present.
2327 TaggedParserAtomIndex explicitName
;
2328 if (TokenKindIsPossibleIdentifierName(tt
)) {
2329 explicitName
= anyChars
.currentName();
2331 anyChars
.ungetToken();
2334 FunctionNodeType funNode
;
2335 MOZ_TRY_VAR(funNode
, handler_
.newFunction(syntaxKind
, pos()));
2337 ParamsBodyNodeType argsbody
;
2338 MOZ_TRY_VAR(argsbody
, handler_
.newParamsBody(pos()));
2339 funNode
->setBody(argsbody
);
2341 bool isSelfHosting
= options().selfHostingMode
;
2342 FunctionFlags flags
=
2343 InitialFunctionFlags(syntaxKind
, generatorKind
, asyncKind
, isSelfHosting
);
2344 FunctionBox
* funbox
=
2345 newFunctionBox(funNode
, explicitName
, flags
, /* toStringStart = */ 0,
2346 inheritedDirectives
, generatorKind
, asyncKind
);
2348 return errorResult();
2351 // Function is not syntactically part of another script.
2352 MOZ_ASSERT(funbox
->index() == CompilationStencil::TopLevelIndex
);
2354 funbox
->initStandalone(this->compilationState_
.scopeContext
, syntaxKind
);
2356 SourceParseContext
funpc(this, funbox
, newDirectives
);
2357 if (!funpc
.init()) {
2358 return errorResult();
2361 YieldHandling yieldHandling
= GetYieldHandling(generatorKind
);
2362 AwaitHandling awaitHandling
= GetAwaitHandling(asyncKind
);
2363 AutoAwaitIsKeyword
<FullParseHandler
, Unit
> awaitIsKeyword(this,
2365 if (!functionFormalParametersAndBody(InAllowed
, yieldHandling
, &funNode
,
2366 syntaxKind
, parameterListEnd
,
2367 /* isStandaloneFunction = */ true)) {
2368 return errorResult();
2371 if (!tokenStream
.getToken(&tt
, TokenStream::SlashIsRegExp
)) {
2372 return errorResult();
2374 if (tt
!= TokenKind::Eof
) {
2375 error(JSMSG_GARBAGE_AFTER_INPUT
, "function body", TokenKindToDesc(tt
));
2376 return errorResult();
2379 if (!CheckParseTree(this->fc_
, alloc_
, funNode
)) {
2380 return errorResult();
2383 ParseNode
* node
= funNode
;
2384 // Don't constant-fold inside "use asm" code, as this could create a parse
2385 // tree that doesn't type-check as asm.js.
2386 if (!pc_
->useAsmOrInsideUseAsm()) {
2387 if (!FoldConstants(this->fc_
, this->parserAtoms(), &node
, &handler_
)) {
2388 return errorResult();
2391 funNode
= &node
->as
<FunctionNode
>();
2393 if (!checkForUndefinedPrivateFields(nullptr)) {
2394 return errorResult();
2397 if (!this->setSourceMapInfo()) {
2398 return errorResult();
2404 template <class ParseHandler
, typename Unit
>
2405 typename
ParseHandler::LexicalScopeNodeResult
2406 GeneralParser
<ParseHandler
, Unit
>::functionBody(InHandling inHandling
,
2407 YieldHandling yieldHandling
,
2408 FunctionSyntaxKind kind
,
2409 FunctionBodyType type
) {
2410 MOZ_ASSERT(pc_
->isFunctionBox());
2413 uint32_t startYieldOffset
= pc_
->lastYieldOffset
;
2417 if (type
== StatementListBody
) {
2418 bool inheritedStrict
= pc_
->sc()->strict();
2419 MOZ_TRY_VAR(body
, statementList(yieldHandling
));
2421 // When we transitioned from non-strict to strict mode, we need to
2422 // validate that all parameter names are valid strict mode names.
2423 if (!inheritedStrict
&& pc_
->sc()->strict()) {
2424 MOZ_ASSERT(pc_
->sc()->hasExplicitUseStrict(),
2425 "strict mode should only change when a 'use strict' directive "
2427 if (!hasValidSimpleStrictParameterNames()) {
2428 // Request that this function be reparsed as strict to report
2429 // the invalid parameter name at the correct source location.
2430 pc_
->newDirectives
->setStrict();
2431 return errorResult();
2435 MOZ_ASSERT(type
== ExpressionBody
);
2437 // Async functions are implemented as generators, and generators are
2438 // assumed to be statement lists, to prepend initial `yield`.
2439 ListNodeType stmtList
= null();
2440 if (pc_
->isAsync()) {
2441 MOZ_TRY_VAR(stmtList
, handler_
.newStatementList(pos()));
2446 assignExpr(inHandling
, yieldHandling
, TripledotProhibited
));
2448 MOZ_TRY_VAR(body
, handler_
.newExpressionBody(kid
));
2450 if (pc_
->isAsync()) {
2451 handler_
.addStatementToList(stmtList
, body
);
2456 MOZ_ASSERT_IF(!pc_
->isGenerator() && !pc_
->isAsync(),
2457 pc_
->lastYieldOffset
== startYieldOffset
);
2458 MOZ_ASSERT_IF(pc_
->isGenerator(), kind
!= FunctionSyntaxKind::Arrow
);
2459 MOZ_ASSERT_IF(pc_
->isGenerator(), type
== StatementListBody
);
2461 if (pc_
->needsDotGeneratorName()) {
2462 MOZ_ASSERT_IF(!pc_
->isAsync(), type
== StatementListBody
);
2463 if (!pc_
->declareDotGeneratorName()) {
2464 return errorResult();
2466 if (pc_
->isGenerator()) {
2467 NameNodeType generator
;
2468 MOZ_TRY_VAR(generator
, newDotGeneratorName());
2469 if (!handler_
.prependInitialYield(handler_
.asListNode(body
), generator
)) {
2470 return errorResult();
2475 // Declare the 'arguments', 'this', and 'new.target' bindings if necessary
2476 // before finishing up the scope so these special bindings get marked as
2477 // closed over if necessary. Arrow functions don't have these bindings.
2478 if (kind
!= FunctionSyntaxKind::Arrow
) {
2479 bool canSkipLazyClosedOverBindings
= handler_
.reuseClosedOverBindings();
2480 if (!pc_
->declareFunctionArgumentsObject(usedNames_
,
2481 canSkipLazyClosedOverBindings
)) {
2482 return errorResult();
2484 if (!pc_
->declareFunctionThis(usedNames_
, canSkipLazyClosedOverBindings
)) {
2485 return errorResult();
2487 if (!pc_
->declareNewTarget(usedNames_
, canSkipLazyClosedOverBindings
)) {
2488 return errorResult();
2492 return finishLexicalScope(pc_
->varScope(), body
, ScopeKind::FunctionLexical
);
2495 template <class ParseHandler
, typename Unit
>
2496 bool GeneralParser
<ParseHandler
, Unit
>::matchOrInsertSemicolon(
2497 Modifier modifier
/* = TokenStream::SlashIsRegExp */) {
2498 TokenKind tt
= TokenKind::Eof
;
2499 if (!tokenStream
.peekTokenSameLine(&tt
, modifier
)) {
2502 if (tt
!= TokenKind::Eof
&& tt
!= TokenKind::Eol
&& tt
!= TokenKind::Semi
&&
2503 tt
!= TokenKind::RightCurly
) {
2505 * When current token is `await` and it's outside of async function,
2506 * it's possibly intended to be an await expression.
2511 * tried to insert semicolon here
2513 * Detect this situation and throw an understandable error. Otherwise
2514 * we'd throw a confusing "unexpected token: (unexpected token)" error.
2516 if (!pc_
->isAsync() && anyChars
.currentToken().type
== TokenKind::Await
) {
2517 error(JSMSG_AWAIT_OUTSIDE_ASYNC_OR_MODULE
);
2520 if (!yieldExpressionsSupported() &&
2521 anyChars
.currentToken().type
== TokenKind::Yield
) {
2522 error(JSMSG_YIELD_OUTSIDE_GENERATOR
);
2526 /* Advance the scanner for proper error location reporting. */
2527 tokenStream
.consumeKnownToken(tt
, modifier
);
2528 error(JSMSG_UNEXPECTED_TOKEN_NO_EXPECT
, TokenKindToDesc(tt
));
2532 return tokenStream
.matchToken(&matched
, TokenKind::Semi
, modifier
);
2535 bool ParserBase::leaveInnerFunction(ParseContext
* outerpc
) {
2536 MOZ_ASSERT(pc_
!= outerpc
);
2538 MOZ_ASSERT_IF(outerpc
->isFunctionBox(),
2539 outerpc
->functionBox()->index() < pc_
->functionBox()->index());
2541 // If the current function allows super.property but cannot have a home
2542 // object, i.e., it is an arrow function, we need to propagate the flag to
2543 // the outer ParseContext.
2544 if (pc_
->superScopeNeedsHomeObject()) {
2545 if (!pc_
->isArrowFunction()) {
2546 MOZ_ASSERT(pc_
->functionBox()->needsHomeObject());
2548 outerpc
->setSuperScopeNeedsHomeObject();
2552 // Lazy functions inner to another lazy function need to be remembered by
2553 // the inner function so that if the outer function is eventually parsed
2554 // we do not need any further parsing or processing of the inner function.
2556 // Append the inner function index here unconditionally; the vector is only
2557 // used if the Parser using outerpc is a syntax parsing. See
2558 // GeneralParser<SyntaxParseHandler>::finishFunction.
2559 if (!outerpc
->innerFunctionIndexesForLazy
.append(
2560 pc_
->functionBox()->index())) {
2564 PropagateTransitiveParseFlags(pc_
->functionBox(), outerpc
->sc());
2569 TaggedParserAtomIndex
ParserBase::prefixAccessorName(
2570 PropertyType propType
, TaggedParserAtomIndex propAtom
) {
2571 StringBuffer
prefixed(fc_
);
2572 if (propType
== PropertyType::Setter
) {
2573 if (!prefixed
.append("set ")) {
2574 return TaggedParserAtomIndex::null();
2577 if (!prefixed
.append("get ")) {
2578 return TaggedParserAtomIndex::null();
2581 if (!prefixed
.append(this->parserAtoms(), propAtom
)) {
2582 return TaggedParserAtomIndex::null();
2584 return prefixed
.finishParserAtom(this->parserAtoms(), fc_
);
2587 template <class ParseHandler
, typename Unit
>
2588 void GeneralParser
<ParseHandler
, Unit
>::setFunctionStartAtPosition(
2589 FunctionBox
* funbox
, TokenPos pos
) const {
2591 JS::LimitedColumnNumberOneOrigin startColumn
;
2592 tokenStream
.computeLineAndColumn(pos
.begin
, &startLine
, &startColumn
);
2594 // NOTE: `Debugger::CallData::findScripts` relies on sourceStart and
2595 // lineno/column referring to the same location.
2596 funbox
->setStart(pos
.begin
, startLine
, startColumn
);
2599 template <class ParseHandler
, typename Unit
>
2600 void GeneralParser
<ParseHandler
, Unit
>::setFunctionStartAtCurrentToken(
2601 FunctionBox
* funbox
) const {
2602 setFunctionStartAtPosition(funbox
, anyChars
.currentToken().pos
);
2605 template <class ParseHandler
, typename Unit
>
2606 bool GeneralParser
<ParseHandler
, Unit
>::functionArguments(
2607 YieldHandling yieldHandling
, FunctionSyntaxKind kind
,
2608 FunctionNodeType funNode
) {
2609 FunctionBox
* funbox
= pc_
->functionBox();
2611 // Modifier for the following tokens.
2612 // TokenStream::SlashIsDiv for the following cases:
2625 // TokenStream::SlashIsRegExp for the following case:
2628 Modifier firstTokenModifier
=
2629 kind
!= FunctionSyntaxKind::Arrow
|| funbox
->isAsync()
2630 ? TokenStream::SlashIsDiv
2631 : TokenStream::SlashIsRegExp
;
2633 if (!tokenStream
.getToken(&tt
, firstTokenModifier
)) {
2637 if (kind
== FunctionSyntaxKind::Arrow
&& TokenKindIsPossibleIdentifier(tt
)) {
2638 // Record the start of function source (for FunctionToString).
2639 setFunctionStartAtCurrentToken(funbox
);
2641 ParamsBodyNodeType argsbody
;
2642 MOZ_TRY_VAR_OR_RETURN(argsbody
, handler_
.newParamsBody(pos()), false);
2643 handler_
.setFunctionFormalParametersAndBody(funNode
, argsbody
);
2645 TaggedParserAtomIndex name
= bindingIdentifier(yieldHandling
);
2650 constexpr bool disallowDuplicateParams
= true;
2651 bool duplicatedParam
= false;
2652 if (!notePositionalFormalParameter(funNode
, name
, pos().begin
,
2653 disallowDuplicateParams
,
2654 &duplicatedParam
)) {
2657 MOZ_ASSERT(!duplicatedParam
);
2658 MOZ_ASSERT(pc_
->positionalFormalParameterNames().length() == 1);
2660 funbox
->setLength(1);
2661 funbox
->setArgCount(1);
2665 if (tt
!= TokenKind::LeftParen
) {
2666 error(kind
== FunctionSyntaxKind::Arrow
? JSMSG_BAD_ARROW_ARGS
2667 : JSMSG_PAREN_BEFORE_FORMAL
);
2671 // Record the start of function source (for FunctionToString).
2672 setFunctionStartAtCurrentToken(funbox
);
2674 ParamsBodyNodeType argsbody
;
2675 MOZ_TRY_VAR_OR_RETURN(argsbody
, handler_
.newParamsBody(pos()), false);
2676 handler_
.setFunctionFormalParametersAndBody(funNode
, argsbody
);
2679 if (!tokenStream
.matchToken(&matched
, TokenKind::RightParen
,
2680 TokenStream::SlashIsRegExp
)) {
2684 bool hasRest
= false;
2685 bool hasDefault
= false;
2686 bool duplicatedParam
= false;
2687 bool disallowDuplicateParams
=
2688 kind
== FunctionSyntaxKind::Arrow
||
2689 kind
== FunctionSyntaxKind::Method
||
2690 kind
== FunctionSyntaxKind::FieldInitializer
||
2691 kind
== FunctionSyntaxKind::ClassConstructor
;
2692 AtomVector
& positionalFormals
= pc_
->positionalFormalParameterNames();
2694 if (kind
== FunctionSyntaxKind::Getter
) {
2695 error(JSMSG_ACCESSOR_WRONG_ARGS
, "getter", "no", "s");
2701 error(JSMSG_PARAMETER_AFTER_REST
);
2706 if (!tokenStream
.getToken(&tt
, TokenStream::SlashIsRegExp
)) {
2710 if (tt
== TokenKind::TripleDot
) {
2711 if (kind
== FunctionSyntaxKind::Setter
) {
2712 error(JSMSG_ACCESSOR_WRONG_ARGS
, "setter", "one", "");
2716 disallowDuplicateParams
= true;
2717 if (duplicatedParam
) {
2718 // Has duplicated args before the rest parameter.
2719 error(JSMSG_BAD_DUP_ARGS
);
2724 funbox
->setHasRest();
2726 if (!tokenStream
.getToken(&tt
)) {
2730 if (!TokenKindIsPossibleIdentifier(tt
) &&
2731 tt
!= TokenKind::LeftBracket
&& tt
!= TokenKind::LeftCurly
) {
2732 error(JSMSG_NO_REST_NAME
);
2738 case TokenKind::LeftBracket
:
2739 case TokenKind::LeftCurly
: {
2740 disallowDuplicateParams
= true;
2741 if (duplicatedParam
) {
2742 // Has duplicated args before the destructuring parameter.
2743 error(JSMSG_BAD_DUP_ARGS
);
2747 funbox
->hasDestructuringArgs
= true;
2750 MOZ_TRY_VAR_OR_RETURN(
2752 destructuringDeclarationWithoutYieldOrAwait(
2753 DeclarationKind::FormalParameter
, yieldHandling
, tt
),
2756 if (!noteDestructuredPositionalFormalParameter(funNode
, destruct
)) {
2764 if (!TokenKindIsPossibleIdentifier(tt
)) {
2765 error(JSMSG_MISSING_FORMAL
);
2769 TaggedParserAtomIndex name
= bindingIdentifier(yieldHandling
);
2774 if (!notePositionalFormalParameter(funNode
, name
, pos().begin
,
2775 disallowDuplicateParams
,
2776 &duplicatedParam
)) {
2779 if (duplicatedParam
) {
2780 funbox
->hasDuplicateParameters
= true;
2787 if (positionalFormals
.length() >= ARGNO_LIMIT
) {
2788 error(JSMSG_TOO_MANY_FUN_ARGS
);
2793 if (!tokenStream
.matchToken(&matched
, TokenKind::Assign
,
2794 TokenStream::SlashIsRegExp
)) {
2799 error(JSMSG_REST_WITH_DEFAULT
);
2802 disallowDuplicateParams
= true;
2803 if (duplicatedParam
) {
2804 error(JSMSG_BAD_DUP_ARGS
);
2811 // The Function.length property is the number of formals
2812 // before the first default argument.
2813 funbox
->setLength(positionalFormals
.length() - 1);
2815 funbox
->hasParameterExprs
= true;
2818 MOZ_TRY_VAR_OR_RETURN(
2819 def_expr
, assignExprWithoutYieldOrAwait(yieldHandling
), false);
2820 if (!handler_
.setLastFunctionFormalParameterDefault(funNode
,
2826 // Setter syntax uniquely requires exactly one argument.
2827 if (kind
== FunctionSyntaxKind::Setter
) {
2831 if (!tokenStream
.matchToken(&matched
, TokenKind::Comma
,
2832 TokenStream::SlashIsRegExp
)) {
2840 if (!tokenStream
.peekToken(&tt
, TokenStream::SlashIsRegExp
)) {
2843 if (tt
== TokenKind::RightParen
) {
2850 if (!tokenStream
.getToken(&tt
, TokenStream::SlashIsRegExp
)) {
2853 if (tt
!= TokenKind::RightParen
) {
2854 if (kind
== FunctionSyntaxKind::Setter
) {
2855 error(JSMSG_ACCESSOR_WRONG_ARGS
, "setter", "one", "");
2859 error(JSMSG_PAREN_AFTER_FORMAL
);
2864 funbox
->setLength(positionalFormals
.length() - hasRest
);
2867 funbox
->setArgCount(positionalFormals
.length());
2868 } else if (kind
== FunctionSyntaxKind::Setter
) {
2869 error(JSMSG_ACCESSOR_WRONG_ARGS
, "setter", "one", "");
2876 template <typename Unit
>
2877 bool Parser
<FullParseHandler
, Unit
>::skipLazyInnerFunction(
2878 FunctionNode
* funNode
, uint32_t toStringStart
, bool tryAnnexB
) {
2879 // When a lazily-parsed function is called, we only fully parse (and emit)
2880 // that function, not any of its nested children. The initial syntax-only
2881 // parse recorded the free variables of nested functions and their extents,
2882 // so we can skip over them after accounting for their free variables.
2884 MOZ_ASSERT(pc_
->isOutermostOfCurrentCompile());
2885 handler_
.nextLazyInnerFunction();
2886 const ScriptStencil
& cachedData
= handler_
.cachedScriptData();
2887 const ScriptStencilExtra
& cachedExtra
= handler_
.cachedScriptExtra();
2888 MOZ_ASSERT(toStringStart
== cachedExtra
.extent
.toStringStart
);
2890 FunctionBox
* funbox
= newFunctionBox(funNode
, cachedData
, cachedExtra
);
2895 ScriptStencil
& script
= funbox
->functionStencil();
2896 funbox
->copyFunctionFields(script
);
2898 // If the inner lazy function is class constructor, connect it to the class
2899 // statement/expression we are parsing.
2900 if (funbox
->isClassConstructor()) {
2902 pc_
->template findInnermostStatement
<ParseContext::ClassStatement
>();
2903 MOZ_ASSERT(!classStmt
->constructorBox
);
2904 classStmt
->constructorBox
= funbox
;
2907 MOZ_ASSERT_IF(pc_
->isFunctionBox(),
2908 pc_
->functionBox()->index() < funbox
->index());
2910 PropagateTransitiveParseFlags(funbox
, pc_
->sc());
2912 if (!tokenStream
.advance(funbox
->extent().sourceEnd
)) {
2916 // Append possible Annex B function box only upon successfully parsing.
2918 !pc_
->innermostScope()->addPossibleAnnexBFunctionBox(pc_
, funbox
)) {
2925 template <typename Unit
>
2926 bool Parser
<SyntaxParseHandler
, Unit
>::skipLazyInnerFunction(
2927 FunctionNodeType funNode
, uint32_t toStringStart
, bool tryAnnexB
) {
2928 MOZ_CRASH("Cannot skip lazy inner functions when syntax parsing");
2931 template <class ParseHandler
, typename Unit
>
2932 bool GeneralParser
<ParseHandler
, Unit
>::skipLazyInnerFunction(
2933 FunctionNodeType funNode
, uint32_t toStringStart
, bool tryAnnexB
) {
2934 return asFinalParser()->skipLazyInnerFunction(funNode
, toStringStart
,
2938 template <class ParseHandler
, typename Unit
>
2939 bool GeneralParser
<ParseHandler
, Unit
>::addExprAndGetNextTemplStrToken(
2940 YieldHandling yieldHandling
, ListNodeType nodeList
, TokenKind
* ttp
) {
2942 MOZ_TRY_VAR_OR_RETURN(pn
, expr(InAllowed
, yieldHandling
, TripledotProhibited
),
2944 handler_
.addList(nodeList
, pn
);
2947 if (!tokenStream
.getToken(&tt
, TokenStream::SlashIsRegExp
)) {
2950 if (tt
!= TokenKind::RightCurly
) {
2951 error(JSMSG_TEMPLSTR_UNTERM_EXPR
);
2955 return tokenStream
.getTemplateToken(ttp
);
2958 template <class ParseHandler
, typename Unit
>
2959 bool GeneralParser
<ParseHandler
, Unit
>::taggedTemplate(
2960 YieldHandling yieldHandling
, ListNodeType tagArgsList
, TokenKind tt
) {
2961 CallSiteNodeType callSiteObjNode
;
2962 MOZ_TRY_VAR_OR_RETURN(callSiteObjNode
,
2963 handler_
.newCallSiteObject(pos().begin
), false);
2964 handler_
.addList(tagArgsList
, callSiteObjNode
);
2966 pc_
->sc()->setHasCallSiteObj();
2969 if (!appendToCallSiteObj(callSiteObjNode
)) {
2972 if (tt
!= TokenKind::TemplateHead
) {
2976 if (!addExprAndGetNextTemplStrToken(yieldHandling
, tagArgsList
, &tt
)) {
2980 handler_
.setEndPosition(tagArgsList
, callSiteObjNode
);
2984 template <class ParseHandler
, typename Unit
>
2985 typename
ParseHandler::ListNodeResult
2986 GeneralParser
<ParseHandler
, Unit
>::templateLiteral(
2987 YieldHandling yieldHandling
) {
2988 NameNodeType literal
;
2989 MOZ_TRY_VAR(literal
, noSubstitutionUntaggedTemplate());
2991 ListNodeType nodeList
;
2992 MOZ_TRY_VAR(nodeList
,
2993 handler_
.newList(ParseNodeKind::TemplateStringListExpr
, literal
));
2997 if (!addExprAndGetNextTemplStrToken(yieldHandling
, nodeList
, &tt
)) {
2998 return errorResult();
3001 MOZ_TRY_VAR(literal
, noSubstitutionUntaggedTemplate());
3003 handler_
.addList(nodeList
, literal
);
3004 } while (tt
== TokenKind::TemplateHead
);
3008 template <class ParseHandler
, typename Unit
>
3009 typename
ParseHandler::FunctionNodeResult
3010 GeneralParser
<ParseHandler
, Unit
>::functionDefinition(
3011 FunctionNodeType funNode
, uint32_t toStringStart
, InHandling inHandling
,
3012 YieldHandling yieldHandling
, TaggedParserAtomIndex funName
,
3013 FunctionSyntaxKind kind
, GeneratorKind generatorKind
,
3014 FunctionAsyncKind asyncKind
, bool tryAnnexB
/* = false */) {
3015 MOZ_ASSERT_IF(kind
== FunctionSyntaxKind::Statement
, funName
);
3017 // If we see any inner function, note it on our current context. The bytecode
3018 // emitter may eliminate the function later, but we use a conservative
3019 // definition for consistency between lazy and full parsing.
3020 pc_
->sc()->setHasInnerFunctions();
3022 // When fully parsing a lazy script, we do not fully reparse its inner
3023 // functions, which are also lazy. Instead, their free variables and source
3024 // extents are recorded and may be skipped.
3025 if (handler_
.reuseLazyInnerFunctions()) {
3026 if (!skipLazyInnerFunction(funNode
, toStringStart
, tryAnnexB
)) {
3027 return errorResult();
3033 bool isSelfHosting
= options().selfHostingMode
;
3034 FunctionFlags flags
=
3035 InitialFunctionFlags(kind
, generatorKind
, asyncKind
, isSelfHosting
);
3037 // Self-hosted functions with special function names require extended slots
3038 // for various purposes.
3039 bool forceExtended
=
3040 isSelfHosting
&& funName
&&
3041 this->parserAtoms().isExtendedUnclonedSelfHostedFunctionName(funName
);
3042 if (forceExtended
) {
3043 flags
.setIsExtended();
3046 // Speculatively parse using the directives of the parent parsing context.
3047 // If a directive is encountered (e.g., "use strict") that changes how the
3048 // function should have been parsed, we backup and reparse with the new set
3050 Directives
directives(pc_
);
3051 Directives newDirectives
= directives
;
3053 Position
start(tokenStream
);
3054 auto startObj
= this->compilationState_
.getPosition();
3056 // Parse the inner function. The following is a loop as we may attempt to
3057 // reparse a function due to failed syntax parsing and encountering new
3058 // "use foo" directives.
3060 if (trySyntaxParseInnerFunction(&funNode
, funName
, flags
, toStringStart
,
3061 inHandling
, yieldHandling
, kind
,
3062 generatorKind
, asyncKind
, tryAnnexB
,
3063 directives
, &newDirectives
)) {
3068 if (anyChars
.hadError() || directives
== newDirectives
) {
3069 return errorResult();
3072 // Assignment must be monotonic to prevent infinitely attempting to
3074 MOZ_ASSERT_IF(directives
.strict(), newDirectives
.strict());
3075 MOZ_ASSERT_IF(directives
.asmJS(), newDirectives
.asmJS());
3076 directives
= newDirectives
;
3078 // Rewind to retry parsing with new directives applied.
3079 tokenStream
.rewind(start
);
3080 this->compilationState_
.rewind(startObj
);
3082 // functionFormalParametersAndBody may have already set body before failing.
3083 handler_
.setFunctionFormalParametersAndBody(funNode
, null());
3089 template <typename Unit
>
3090 bool Parser
<FullParseHandler
, Unit
>::advancePastSyntaxParsedFunction(
3091 SyntaxParser
* syntaxParser
) {
3092 MOZ_ASSERT(getSyntaxParser() == syntaxParser
);
3094 // Advance this parser over tokens processed by the syntax parser.
3095 Position
currentSyntaxPosition(syntaxParser
->tokenStream
);
3096 if (!tokenStream
.fastForward(currentSyntaxPosition
, syntaxParser
->anyChars
)) {
3100 anyChars
.adoptState(syntaxParser
->anyChars
);
3101 tokenStream
.adoptState(syntaxParser
->tokenStream
);
3105 template <typename Unit
>
3106 bool Parser
<FullParseHandler
, Unit
>::trySyntaxParseInnerFunction(
3107 FunctionNode
** funNode
, TaggedParserAtomIndex explicitName
,
3108 FunctionFlags flags
, uint32_t toStringStart
, InHandling inHandling
,
3109 YieldHandling yieldHandling
, FunctionSyntaxKind kind
,
3110 GeneratorKind generatorKind
, FunctionAsyncKind asyncKind
, bool tryAnnexB
,
3111 Directives inheritedDirectives
, Directives
* newDirectives
) {
3112 // Try a syntax parse for this inner function.
3114 // If we're assuming this function is an IIFE, always perform a full
3115 // parse to avoid the overhead of a lazy syntax-only parse. Although
3116 // the prediction may be incorrect, IIFEs are common enough that it
3117 // pays off for lots of code.
3118 if ((*funNode
)->isLikelyIIFE() &&
3119 generatorKind
== GeneratorKind::NotGenerator
&&
3120 asyncKind
== FunctionAsyncKind::SyncFunction
) {
3124 SyntaxParser
* syntaxParser
= getSyntaxParser();
3125 if (!syntaxParser
) {
3129 UsedNameTracker::RewindToken token
= usedNames_
.getRewindToken();
3130 auto statePosition
= this->compilationState_
.getPosition();
3132 // Move the syntax parser to the current position in the stream. In the
3133 // common case this seeks forward, but it'll also seek backward *at least*
3134 // when arrow functions appear inside arrow function argument defaults
3135 // (because we rewind to reparse arrow functions once we're certain they're
3136 // arrow functions):
3138 // var x = (y = z => 2) => q;
3139 // // ^ we first seek to here to syntax-parse this function
3140 // // ^ then we seek back to here to syntax-parse the outer function
3141 Position
currentPosition(tokenStream
);
3142 if (!syntaxParser
->tokenStream
.seekTo(currentPosition
, anyChars
)) {
3146 // Make a FunctionBox before we enter the syntax parser, because |pn|
3147 // still expects a FunctionBox to be attached to it during BCE, and
3148 // the syntax parser cannot attach one to it.
3149 FunctionBox
* funbox
=
3150 newFunctionBox(*funNode
, explicitName
, flags
, toStringStart
,
3151 inheritedDirectives
, generatorKind
, asyncKind
);
3155 funbox
->initWithEnclosingParseContext(pc_
, kind
);
3157 auto syntaxNodeResult
= syntaxParser
->innerFunctionForFunctionBox(
3158 SyntaxParseHandler::Node::NodeGeneric
, pc_
, funbox
, inHandling
,
3159 yieldHandling
, kind
, newDirectives
);
3160 if (syntaxNodeResult
.isErr()) {
3161 if (syntaxParser
->hadAbortedSyntaxParse()) {
3162 // Try again with a full parse. UsedNameTracker needs to be
3163 // rewound to just before we tried the syntax parse for
3165 syntaxParser
->clearAbortedSyntaxParse();
3166 usedNames_
.rewind(token
);
3167 this->compilationState_
.rewind(statePosition
);
3168 MOZ_ASSERT(!fc_
->hadErrors());
3174 if (!advancePastSyntaxParsedFunction(syntaxParser
)) {
3178 // Update the end position of the parse node.
3179 (*funNode
)->pn_pos
.end
= anyChars
.currentToken().pos
.end
;
3181 // Append possible Annex B function box only upon successfully parsing.
3183 if (!pc_
->innermostScope()->addPossibleAnnexBFunctionBox(pc_
, funbox
)) {
3191 // We failed to do a syntax parse above, so do the full parse.
3192 FunctionNodeType innerFunc
;
3193 MOZ_TRY_VAR_OR_RETURN(
3195 innerFunction(*funNode
, pc_
, explicitName
, flags
, toStringStart
,
3196 inHandling
, yieldHandling
, kind
, generatorKind
, asyncKind
,
3197 tryAnnexB
, inheritedDirectives
, newDirectives
),
3200 *funNode
= innerFunc
;
3204 template <typename Unit
>
3205 bool Parser
<SyntaxParseHandler
, Unit
>::trySyntaxParseInnerFunction(
3206 FunctionNodeType
* funNode
, TaggedParserAtomIndex explicitName
,
3207 FunctionFlags flags
, uint32_t toStringStart
, InHandling inHandling
,
3208 YieldHandling yieldHandling
, FunctionSyntaxKind kind
,
3209 GeneratorKind generatorKind
, FunctionAsyncKind asyncKind
, bool tryAnnexB
,
3210 Directives inheritedDirectives
, Directives
* newDirectives
) {
3211 // This is already a syntax parser, so just parse the inner function.
3212 FunctionNodeType innerFunc
;
3213 MOZ_TRY_VAR_OR_RETURN(
3215 innerFunction(*funNode
, pc_
, explicitName
, flags
, toStringStart
,
3216 inHandling
, yieldHandling
, kind
, generatorKind
, asyncKind
,
3217 tryAnnexB
, inheritedDirectives
, newDirectives
),
3220 *funNode
= innerFunc
;
3224 template <class ParseHandler
, typename Unit
>
3225 inline bool GeneralParser
<ParseHandler
, Unit
>::trySyntaxParseInnerFunction(
3226 FunctionNodeType
* funNode
, TaggedParserAtomIndex explicitName
,
3227 FunctionFlags flags
, uint32_t toStringStart
, InHandling inHandling
,
3228 YieldHandling yieldHandling
, FunctionSyntaxKind kind
,
3229 GeneratorKind generatorKind
, FunctionAsyncKind asyncKind
, bool tryAnnexB
,
3230 Directives inheritedDirectives
, Directives
* newDirectives
) {
3231 return asFinalParser()->trySyntaxParseInnerFunction(
3232 funNode
, explicitName
, flags
, toStringStart
, inHandling
, yieldHandling
,
3233 kind
, generatorKind
, asyncKind
, tryAnnexB
, inheritedDirectives
,
3237 template <class ParseHandler
, typename Unit
>
3238 typename
ParseHandler::FunctionNodeResult
3239 GeneralParser
<ParseHandler
, Unit
>::innerFunctionForFunctionBox(
3240 FunctionNodeType funNode
, ParseContext
* outerpc
, FunctionBox
* funbox
,
3241 InHandling inHandling
, YieldHandling yieldHandling
, FunctionSyntaxKind kind
,
3242 Directives
* newDirectives
) {
3243 // Note that it is possible for outerpc != this->pc_, as we may be
3244 // attempting to syntax parse an inner function from an outer full
3245 // parser. In that case, outerpc is a SourceParseContext from the full parser
3246 // instead of the current top of the stack of the syntax parser.
3248 // Push a new ParseContext.
3249 SourceParseContext
funpc(this, funbox
, newDirectives
);
3250 if (!funpc
.init()) {
3251 return errorResult();
3254 if (!functionFormalParametersAndBody(inHandling
, yieldHandling
, &funNode
,
3256 return errorResult();
3259 if (!leaveInnerFunction(outerpc
)) {
3260 return errorResult();
3266 template <class ParseHandler
, typename Unit
>
3267 typename
ParseHandler::FunctionNodeResult
3268 GeneralParser
<ParseHandler
, Unit
>::innerFunction(
3269 FunctionNodeType funNode
, ParseContext
* outerpc
,
3270 TaggedParserAtomIndex explicitName
, FunctionFlags flags
,
3271 uint32_t toStringStart
, InHandling inHandling
, YieldHandling yieldHandling
,
3272 FunctionSyntaxKind kind
, GeneratorKind generatorKind
,
3273 FunctionAsyncKind asyncKind
, bool tryAnnexB
, Directives inheritedDirectives
,
3274 Directives
* newDirectives
) {
3275 // Note that it is possible for outerpc != this->pc_, as we may be
3276 // attempting to syntax parse an inner function from an outer full
3277 // parser. In that case, outerpc is a SourceParseContext from the full parser
3278 // instead of the current top of the stack of the syntax parser.
3280 FunctionBox
* funbox
=
3281 newFunctionBox(funNode
, explicitName
, flags
, toStringStart
,
3282 inheritedDirectives
, generatorKind
, asyncKind
);
3284 return errorResult();
3286 funbox
->initWithEnclosingParseContext(outerpc
, kind
);
3288 FunctionNodeType innerFunc
;
3289 MOZ_TRY_VAR(innerFunc
,
3290 innerFunctionForFunctionBox(funNode
, outerpc
, funbox
, inHandling
,
3291 yieldHandling
, kind
, newDirectives
));
3293 // Append possible Annex B function box only upon successfully parsing.
3295 if (!pc_
->innermostScope()->addPossibleAnnexBFunctionBox(pc_
, funbox
)) {
3296 return errorResult();
3303 template <class ParseHandler
, typename Unit
>
3304 bool GeneralParser
<ParseHandler
, Unit
>::appendToCallSiteObj(
3305 CallSiteNodeType callSiteObj
) {
3307 MOZ_TRY_VAR_OR_RETURN(cookedNode
, noSubstitutionTaggedTemplate(), false);
3309 auto atom
= tokenStream
.getRawTemplateStringAtom();
3313 NameNodeType rawNode
;
3314 MOZ_TRY_VAR_OR_RETURN(rawNode
, handler_
.newTemplateStringLiteral(atom
, pos()),
3317 handler_
.addToCallSiteObject(callSiteObj
, rawNode
, cookedNode
);
3321 template <typename Unit
>
3322 FullParseHandler::FunctionNodeResult
3323 Parser
<FullParseHandler
, Unit
>::standaloneLazyFunction(
3324 CompilationInput
& input
, uint32_t toStringStart
, bool strict
,
3325 GeneratorKind generatorKind
, FunctionAsyncKind asyncKind
) {
3326 MOZ_ASSERT(checkOptionsCalled_
);
3328 FunctionSyntaxKind syntaxKind
= input
.functionSyntaxKind();
3329 FunctionNodeType funNode
;
3330 MOZ_TRY_VAR(funNode
, handler_
.newFunction(syntaxKind
, pos()));
3332 TaggedParserAtomIndex displayAtom
=
3333 this->getCompilationState().previousParseCache
.displayAtom();
3335 Directives
directives(strict
);
3336 FunctionBox
* funbox
=
3337 newFunctionBox(funNode
, displayAtom
, input
.functionFlags(), toStringStart
,
3338 directives
, generatorKind
, asyncKind
);
3340 return errorResult();
3342 const ScriptStencilExtra
& funExtra
=
3343 this->getCompilationState().previousParseCache
.funExtra();
3344 funbox
->initFromLazyFunction(
3345 funExtra
, this->getCompilationState().scopeContext
, syntaxKind
);
3346 if (funbox
->useMemberInitializers()) {
3347 funbox
->setMemberInitializers(funExtra
.memberInitializers());
3350 Directives newDirectives
= directives
;
3351 SourceParseContext
funpc(this, funbox
, &newDirectives
);
3352 if (!funpc
.init()) {
3353 return errorResult();
3356 // Our tokenStream has no current token, so funNode's position is garbage.
3357 // Substitute the position of the first token in our source. If the
3358 // function is a not-async arrow, use TokenStream::SlashIsRegExp to keep
3359 // verifyConsistentModifier from complaining (we will use
3360 // TokenStream::SlashIsRegExp in functionArguments).
3361 Modifier modifier
= (input
.functionFlags().isArrow() &&
3362 asyncKind
== FunctionAsyncKind::SyncFunction
)
3363 ? TokenStream::SlashIsRegExp
3364 : TokenStream::SlashIsDiv
;
3365 if (!tokenStream
.peekTokenPos(&funNode
->pn_pos
, modifier
)) {
3366 return errorResult();
3369 YieldHandling yieldHandling
= GetYieldHandling(generatorKind
);
3371 if (funbox
->isSyntheticFunction()) {
3372 // Currently default class constructors are the only synthetic function that
3373 // supports delazification.
3374 MOZ_ASSERT(funbox
->isClassConstructor());
3375 MOZ_ASSERT(funbox
->extent().toStringStart
== funbox
->extent().sourceStart
);
3377 HasHeritage hasHeritage
= funbox
->isDerivedClassConstructor()
3380 TokenPos
synthesizedBodyPos(funbox
->extent().toStringStart
,
3381 funbox
->extent().toStringEnd
);
3383 // Reset pos() to the `class` keyword for predictable results.
3384 tokenStream
.consumeKnownToken(TokenKind::Class
);
3386 if (!this->synthesizeConstructorBody(synthesizedBodyPos
, hasHeritage
,
3388 return errorResult();
3391 if (!functionFormalParametersAndBody(InAllowed
, yieldHandling
, &funNode
,
3393 MOZ_ASSERT(directives
== newDirectives
);
3394 return errorResult();
3398 if (!CheckParseTree(this->fc_
, alloc_
, funNode
)) {
3399 return errorResult();
3402 ParseNode
* node
= funNode
;
3403 // Don't constant-fold inside "use asm" code, as this could create a parse
3404 // tree that doesn't type-check as asm.js.
3405 if (!pc_
->useAsmOrInsideUseAsm()) {
3406 if (!FoldConstants(this->fc_
, this->parserAtoms(), &node
, &handler_
)) {
3407 return errorResult();
3410 funNode
= &node
->as
<FunctionNode
>();
3415 void ParserBase::setFunctionEndFromCurrentToken(FunctionBox
* funbox
) const {
3416 if (compilationState_
.isInitialStencil()) {
3417 MOZ_ASSERT(anyChars
.currentToken().type
!= TokenKind::Eof
);
3418 MOZ_ASSERT(anyChars
.currentToken().type
< TokenKind::Limit
);
3419 funbox
->setEnd(anyChars
.currentToken().pos
.end
);
3421 // If we're delazifying an arrow function with expression body and
3422 // the expression is also a function, we arrive here immediately after
3423 // skipping the function by Parser::skipLazyInnerFunction.
3430 // In that case, the current token's type field is either Limit or
3432 // We shouldn't read the value if it's poisoned.
3433 // See TokenStreamSpecific<Unit, AnyCharsAccess>::advance and
3434 // mfbt/MemoryChecking.h for more details.
3436 // Also, in delazification, the FunctionBox should already have the
3437 // correct extent, and we shouldn't overwrite it here.
3438 // See ScriptStencil variant of PerHandlerParser::newFunctionBox.
3439 #if !defined(MOZ_ASAN) && !defined(MOZ_MSAN) && !defined(MOZ_VALGRIND)
3440 MOZ_ASSERT(anyChars
.currentToken().type
!= TokenKind::Eof
);
3442 MOZ_ASSERT(funbox
->extent().sourceEnd
== anyChars
.currentToken().pos
.end
);
3446 template <class ParseHandler
, typename Unit
>
3447 bool GeneralParser
<ParseHandler
, Unit
>::functionFormalParametersAndBody(
3448 InHandling inHandling
, YieldHandling yieldHandling
,
3449 FunctionNodeType
* funNode
, FunctionSyntaxKind kind
,
3450 const Maybe
<uint32_t>& parameterListEnd
/* = Nothing() */,
3451 bool isStandaloneFunction
/* = false */) {
3452 // Given a properly initialized parse context, try to parse an actual
3453 // function without concern for conversion to strict mode, use of lazy
3454 // parsing and such.
3456 FunctionBox
* funbox
= pc_
->functionBox();
3458 if (kind
== FunctionSyntaxKind::ClassConstructor
||
3459 kind
== FunctionSyntaxKind::DerivedClassConstructor
) {
3460 if (!noteUsedName(TaggedParserAtomIndex::WellKnown::dot_initializers_())) {
3465 // See below for an explanation why arrow function parameters and arrow
3466 // function bodies are parsed with different yield/await settings.
3468 AwaitHandling awaitHandling
=
3469 kind
== FunctionSyntaxKind::StaticClassBlock
? AwaitIsDisallowed
3470 : (funbox
->isAsync() ||
3471 (kind
== FunctionSyntaxKind::Arrow
&& awaitIsKeyword()))
3474 AutoAwaitIsKeyword
<ParseHandler
, Unit
> awaitIsKeyword(this, awaitHandling
);
3475 AutoInParametersOfAsyncFunction
<ParseHandler
, Unit
> inParameters(
3476 this, funbox
->isAsync());
3477 if (!functionArguments(yieldHandling
, kind
, *funNode
)) {
3482 Maybe
<ParseContext::VarScope
> varScope
;
3483 if (funbox
->hasParameterExprs
) {
3484 varScope
.emplace(this);
3485 if (!varScope
->init(pc_
)) {
3489 pc_
->functionScope().useAsVarScope(pc_
);
3492 if (kind
== FunctionSyntaxKind::Arrow
) {
3494 if (!tokenStream
.peekTokenSameLine(&tt
)) {
3498 if (tt
== TokenKind::Eol
) {
3499 error(JSMSG_UNEXPECTED_TOKEN
,
3500 "'=>' on the same line after an argument list",
3501 TokenKindToDesc(tt
));
3504 if (tt
!= TokenKind::Arrow
) {
3505 error(JSMSG_BAD_ARROW_ARGS
);
3508 tokenStream
.consumeKnownToken(TokenKind::Arrow
);
3511 // When parsing something for new Function() we have to make sure to
3512 // only treat a certain part of the source as a parameter list.
3513 if (parameterListEnd
.isSome() && parameterListEnd
.value() != pos().begin
) {
3514 error(JSMSG_UNEXPECTED_PARAMLIST_END
);
3518 // Parse the function body.
3519 FunctionBodyType bodyType
= StatementListBody
;
3521 if (!tokenStream
.getToken(&tt
, TokenStream::SlashIsRegExp
)) {
3524 uint32_t openedPos
= 0;
3525 if (tt
!= TokenKind::LeftCurly
) {
3526 if (kind
!= FunctionSyntaxKind::Arrow
) {
3527 error(JSMSG_CURLY_BEFORE_BODY
);
3531 anyChars
.ungetToken();
3532 bodyType
= ExpressionBody
;
3533 funbox
->setHasExprBody();
3535 openedPos
= pos().begin
;
3538 // Arrow function parameters inherit yieldHandling from the enclosing
3539 // context, but the arrow body doesn't. E.g. in |(a = yield) => yield|,
3540 // |yield| in the parameters is either a name or keyword, depending on
3541 // whether the arrow function is enclosed in a generator function or not.
3542 // Whereas the |yield| in the function body is always parsed as a name.
3543 // The same goes when parsing |await| in arrow functions.
3544 YieldHandling bodyYieldHandling
= GetYieldHandling(pc_
->generatorKind());
3545 AwaitHandling bodyAwaitHandling
= GetAwaitHandling(pc_
->asyncKind());
3546 bool inheritedStrict
= pc_
->sc()->strict();
3547 LexicalScopeNodeType body
;
3549 AutoAwaitIsKeyword
<ParseHandler
, Unit
> awaitIsKeyword(this,
3551 AutoInParametersOfAsyncFunction
<ParseHandler
, Unit
> inParameters(this,
3553 MOZ_TRY_VAR_OR_RETURN(
3554 body
, functionBody(inHandling
, bodyYieldHandling
, kind
, bodyType
),
3558 // Revalidate the function name when we transitioned to strict mode.
3559 if ((kind
== FunctionSyntaxKind::Statement
||
3560 kind
== FunctionSyntaxKind::Expression
) &&
3561 funbox
->explicitName() && !inheritedStrict
&& pc_
->sc()->strict()) {
3562 MOZ_ASSERT(pc_
->sc()->hasExplicitUseStrict(),
3563 "strict mode should only change when a 'use strict' directive "
3566 auto propertyName
= funbox
->explicitName();
3567 YieldHandling nameYieldHandling
;
3568 if (kind
== FunctionSyntaxKind::Expression
) {
3569 // Named lambda has binding inside it.
3570 nameYieldHandling
= bodyYieldHandling
;
3572 // Otherwise YieldHandling cannot be checked at this point
3573 // because of different context.
3574 // It should already be checked before this point.
3575 nameYieldHandling
= YieldIsName
;
3578 // We already use the correct await-handling at this point, therefore
3579 // we don't need call AutoAwaitIsKeyword here.
3581 uint32_t nameOffset
= handler_
.getFunctionNameOffset(*funNode
, anyChars
);
3582 if (!checkBindingIdentifier(propertyName
, nameOffset
, nameYieldHandling
)) {
3587 if (bodyType
== StatementListBody
) {
3588 // Cannot use mustMatchToken here because of internal compiler error on
3589 // gcc 6.4.0, with linux 64 SM hazard build.
3591 if (!tokenStream
.getToken(&actual
, TokenStream::SlashIsRegExp
)) {
3594 if (actual
!= TokenKind::RightCurly
) {
3595 reportMissingClosing(JSMSG_CURLY_AFTER_BODY
, JSMSG_CURLY_OPENED
,
3600 setFunctionEndFromCurrentToken(funbox
);
3602 MOZ_ASSERT(kind
== FunctionSyntaxKind::Arrow
);
3604 if (anyChars
.hadError()) {
3608 setFunctionEndFromCurrentToken(funbox
);
3610 if (kind
== FunctionSyntaxKind::Statement
) {
3611 if (!matchOrInsertSemicolon()) {
3617 if (IsMethodDefinitionKind(kind
) && pc_
->superScopeNeedsHomeObject()) {
3618 funbox
->setNeedsHomeObject();
3621 if (!finishFunction(isStandaloneFunction
)) {
3625 handler_
.setEndPosition(body
, pos().begin
);
3626 handler_
.setEndPosition(*funNode
, pos().end
);
3627 handler_
.setFunctionBody(*funNode
, body
);
3632 template <class ParseHandler
, typename Unit
>
3633 typename
ParseHandler::FunctionNodeResult
3634 GeneralParser
<ParseHandler
, Unit
>::functionStmt(uint32_t toStringStart
,
3635 YieldHandling yieldHandling
,
3636 DefaultHandling defaultHandling
,
3637 FunctionAsyncKind asyncKind
) {
3638 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Function
));
3640 // In sloppy mode, Annex B.3.2 allows labelled function declarations.
3641 // Otherwise it's a parse error.
3642 ParseContext::Statement
* declaredInStmt
= pc_
->innermostStatement();
3643 if (declaredInStmt
&& declaredInStmt
->kind() == StatementKind::Label
) {
3644 MOZ_ASSERT(!pc_
->sc()->strict(),
3645 "labeled functions shouldn't be parsed in strict mode");
3647 // Find the innermost non-label statement. Report an error if it's
3648 // unbraced: functions can't appear in it. Otherwise the statement
3649 // (or its absence) determines the scope the function's bound in.
3650 while (declaredInStmt
&& declaredInStmt
->kind() == StatementKind::Label
) {
3651 declaredInStmt
= declaredInStmt
->enclosing();
3654 if (declaredInStmt
&& !StatementKindIsBraced(declaredInStmt
->kind())) {
3655 error(JSMSG_SLOPPY_FUNCTION_LABEL
);
3656 return errorResult();
3661 if (!tokenStream
.getToken(&tt
)) {
3662 return errorResult();
3665 GeneratorKind generatorKind
= GeneratorKind::NotGenerator
;
3666 if (tt
== TokenKind::Mul
) {
3667 generatorKind
= GeneratorKind::Generator
;
3668 if (!tokenStream
.getToken(&tt
)) {
3669 return errorResult();
3673 TaggedParserAtomIndex name
;
3674 if (TokenKindIsPossibleIdentifier(tt
)) {
3675 name
= bindingIdentifier(yieldHandling
);
3677 return errorResult();
3679 } else if (defaultHandling
== AllowDefaultName
) {
3680 name
= TaggedParserAtomIndex::WellKnown::default_();
3681 anyChars
.ungetToken();
3683 /* Unnamed function expressions are forbidden in statement context. */
3684 error(JSMSG_UNNAMED_FUNCTION_STMT
);
3685 return errorResult();
3688 // Note the declared name and check for early errors.
3689 DeclarationKind kind
;
3690 if (declaredInStmt
) {
3691 MOZ_ASSERT(declaredInStmt
->kind() != StatementKind::Label
);
3692 MOZ_ASSERT(StatementKindIsBraced(declaredInStmt
->kind()));
3695 (!pc_
->sc()->strict() && generatorKind
== GeneratorKind::NotGenerator
&&
3696 asyncKind
== FunctionAsyncKind::SyncFunction
)
3697 ? DeclarationKind::SloppyLexicalFunction
3698 : DeclarationKind::LexicalFunction
;
3700 kind
= pc_
->atModuleLevel() ? DeclarationKind::ModuleBodyLevelFunction
3701 : DeclarationKind::BodyLevelFunction
;
3704 if (!noteDeclaredName(name
, kind
, pos())) {
3705 return errorResult();
3708 FunctionSyntaxKind syntaxKind
= FunctionSyntaxKind::Statement
;
3709 FunctionNodeType funNode
;
3710 MOZ_TRY_VAR(funNode
, handler_
.newFunction(syntaxKind
, pos()));
3712 // Under sloppy mode, try Annex B.3.3 semantics. If making an additional
3713 // 'var' binding of the same name does not throw an early error, do so.
3714 // This 'var' binding would be assigned the function object when its
3715 // declaration is reached, not at the start of the block.
3717 // This semantics is implemented upon Scope exit in
3718 // Scope::propagateAndMarkAnnexBFunctionBoxes.
3719 bool tryAnnexB
= kind
== DeclarationKind::SloppyLexicalFunction
;
3721 YieldHandling newYieldHandling
= GetYieldHandling(generatorKind
);
3722 return functionDefinition(funNode
, toStringStart
, InAllowed
, newYieldHandling
,
3723 name
, syntaxKind
, generatorKind
, asyncKind
,
3727 template <class ParseHandler
, typename Unit
>
3728 typename
ParseHandler::FunctionNodeResult
3729 GeneralParser
<ParseHandler
, Unit
>::functionExpr(uint32_t toStringStart
,
3730 InvokedPrediction invoked
,
3731 FunctionAsyncKind asyncKind
) {
3732 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Function
));
3734 AutoAwaitIsKeyword
<ParseHandler
, Unit
> awaitIsKeyword(
3735 this, GetAwaitHandling(asyncKind
));
3736 GeneratorKind generatorKind
= GeneratorKind::NotGenerator
;
3738 if (!tokenStream
.getToken(&tt
)) {
3739 return errorResult();
3742 if (tt
== TokenKind::Mul
) {
3743 generatorKind
= GeneratorKind::Generator
;
3744 if (!tokenStream
.getToken(&tt
)) {
3745 return errorResult();
3749 YieldHandling yieldHandling
= GetYieldHandling(generatorKind
);
3751 TaggedParserAtomIndex name
;
3752 if (TokenKindIsPossibleIdentifier(tt
)) {
3753 name
= bindingIdentifier(yieldHandling
);
3755 return errorResult();
3758 anyChars
.ungetToken();
3761 FunctionSyntaxKind syntaxKind
= FunctionSyntaxKind::Expression
;
3762 FunctionNodeType funNode
;
3763 MOZ_TRY_VAR(funNode
, handler_
.newFunction(syntaxKind
, pos()));
3766 funNode
= handler_
.setLikelyIIFE(funNode
);
3769 return functionDefinition(funNode
, toStringStart
, InAllowed
, yieldHandling
,
3770 name
, syntaxKind
, generatorKind
, asyncKind
);
3774 * Return true if this node, known to be an unparenthesized string literal
3775 * that never contain escape sequences, could be the string of a directive in a
3776 * Directive Prologue. Directive strings never contain escape sequences or line
3779 static inline bool IsUseStrictDirective(const TokenPos
& pos
,
3780 TaggedParserAtomIndex atom
) {
3781 // the length of "use strict", including quotation.
3782 static constexpr size_t useStrictLength
= 12;
3783 return atom
== TaggedParserAtomIndex::WellKnown::use_strict_() &&
3784 pos
.begin
+ useStrictLength
== pos
.end
;
3786 static inline bool IsUseAsmDirective(const TokenPos
& pos
,
3787 TaggedParserAtomIndex atom
) {
3788 // the length of "use asm", including quotation.
3789 static constexpr size_t useAsmLength
= 9;
3790 return atom
== TaggedParserAtomIndex::WellKnown::use_asm_() &&
3791 pos
.begin
+ useAsmLength
== pos
.end
;
3794 template <typename Unit
>
3795 bool Parser
<SyntaxParseHandler
, Unit
>::asmJS(ListNodeType list
) {
3796 // While asm.js could technically be validated and compiled during syntax
3797 // parsing, we have no guarantee that some later JS wouldn't abort the
3798 // syntax parse and cause us to re-parse (and re-compile) the asm.js module.
3799 // For simplicity, unconditionally abort the syntax parse when "use asm" is
3800 // encountered so that asm.js is always validated/compiled exactly once
3801 // during a full parse.
3802 MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
3806 template <typename Unit
>
3807 bool Parser
<FullParseHandler
, Unit
>::asmJS(ListNodeType list
) {
3808 // Disable syntax parsing in anything nested inside the asm.js module.
3809 disableSyntaxParser();
3811 // We should be encountering the "use asm" directive for the first time; if
3812 // the directive is already, we must have failed asm.js validation and we're
3813 // reparsing. In that case, don't try to validate again. A non-null
3814 // newDirectives means we're not in a normal function.
3815 if (!pc_
->newDirectives
|| pc_
->newDirectives
->asmJS()) {
3819 // If there is no ScriptSource, then we are doing a non-compiling parse and
3820 // so we shouldn't (and can't, without a ScriptSource) compile.
3821 if (ss
== nullptr) {
3825 pc_
->functionBox()->useAsm
= true;
3827 // Attempt to validate and compile this asm.js module. On success, the
3828 // tokenStream has been advanced to the closing }. On failure, the
3829 // tokenStream is in an indeterminate state and we must reparse the
3830 // function from the beginning. Reparsing is triggered by marking that a
3831 // new directive has been encountered and returning 'false'.
3833 if (!CompileAsmJS(this->fc_
, this->parserAtoms(), *this, list
, &validated
)) {
3837 pc_
->newDirectives
->setAsmJS();
3844 template <class ParseHandler
, typename Unit
>
3845 inline bool GeneralParser
<ParseHandler
, Unit
>::asmJS(ListNodeType list
) {
3846 return asFinalParser()->asmJS(list
);
3850 * Recognize Directive Prologue members and directives. Assuming |pn| is a
3851 * candidate for membership in a directive prologue, recognize directives and
3852 * set |pc_|'s flags accordingly. If |pn| is indeed part of a prologue, set its
3855 * Note that the following is a strict mode function:
3858 * "blah" // inserted semi colon
3864 * That is, even though "use\x20loose" can never be a directive, now or in the
3865 * future (because of the hex escape), the Directive Prologue extends through it
3866 * to the "use strict" statement, which is indeed a directive.
3868 template <class ParseHandler
, typename Unit
>
3869 bool GeneralParser
<ParseHandler
, Unit
>::maybeParseDirective(
3870 ListNodeType list
, Node possibleDirective
, bool* cont
) {
3871 TokenPos directivePos
;
3872 TaggedParserAtomIndex directive
=
3873 handler_
.isStringExprStatement(possibleDirective
, &directivePos
);
3875 *cont
= !!directive
;
3880 if (IsUseStrictDirective(directivePos
, directive
)) {
3881 // Functions with non-simple parameter lists (destructuring,
3882 // default or rest parameters) must not contain a "use strict"
3884 if (pc_
->isFunctionBox()) {
3885 FunctionBox
* funbox
= pc_
->functionBox();
3886 if (!funbox
->hasSimpleParameterList()) {
3887 const char* parameterKind
= funbox
->hasDestructuringArgs
3889 : funbox
->hasParameterExprs
? "default"
3891 errorAt(directivePos
.begin
, JSMSG_STRICT_NON_SIMPLE_PARAMS
,
3897 // We're going to be in strict mode. Note that this scope explicitly
3898 // had "use strict";
3899 pc_
->sc()->setExplicitUseStrict();
3900 if (!pc_
->sc()->strict()) {
3901 // Some strict mode violations can appear before a Use Strict Directive
3902 // is applied. (See the |DeprecatedContent| enum initializers.) These
3903 // violations can manifest in two ways.
3905 // First, the violation can appear *before* the Use Strict Directive.
3906 // Numeric literals (and therefore octal literals) can only precede a
3907 // Use Strict Directive if this function's parameter list is not simple,
3908 // but we reported an error for non-simple parameter lists above, so
3909 // octal literals present no issue. But octal escapes and \8 and \9 can
3910 // appear in the directive prologue before a Use Strict Directive:
3914 // "hell\157 world"; // octal escape
3915 // "\8"; "\9"; // NonOctalDecimalEscape
3916 // "use strict"; // retroactively makes all the above errors
3919 // Second, the violation can appear *after* the Use Strict Directive but
3920 // *before* the directive is recognized as terminated. This only
3921 // happens when a directive is terminated by ASI, and the next token
3922 // contains a violation:
3926 // "use strict" // ASI
3931 // "use strict" // ASI
3932 // "hell\157 world";
3936 // "use strict" // ASI
3940 // We note such violations when tokenizing. Then, if a violation has
3941 // been observed at the time a "use strict" is applied, we report the
3943 switch (anyChars
.sawDeprecatedContent()) {
3944 case DeprecatedContent::None
:
3946 case DeprecatedContent::OctalLiteral
:
3947 error(JSMSG_DEPRECATED_OCTAL_LITERAL
);
3949 case DeprecatedContent::OctalEscape
:
3950 error(JSMSG_DEPRECATED_OCTAL_ESCAPE
);
3952 case DeprecatedContent::EightOrNineEscape
:
3953 error(JSMSG_DEPRECATED_EIGHT_OR_NINE_ESCAPE
);
3957 pc_
->sc()->setStrictScript();
3959 } else if (IsUseAsmDirective(directivePos
, directive
)) {
3960 if (pc_
->isFunctionBox()) {
3963 return warningAt(directivePos
.begin
, JSMSG_USE_ASM_DIRECTIVE_FAIL
);
3968 template <class ParseHandler
, typename Unit
>
3969 typename
ParseHandler::ListNodeResult
3970 GeneralParser
<ParseHandler
, Unit
>::statementList(YieldHandling yieldHandling
) {
3971 AutoCheckRecursionLimit
recursion(this->fc_
);
3972 if (!recursion
.check(this->fc_
)) {
3973 return errorResult();
3976 ListNodeType stmtList
;
3977 MOZ_TRY_VAR(stmtList
, handler_
.newStatementList(pos()));
3979 bool canHaveDirectives
= pc_
->atBodyLevel();
3980 if (canHaveDirectives
) {
3981 // Clear flags for deprecated content that might have been seen in an
3982 // enclosing context.
3983 anyChars
.clearSawDeprecatedContent();
3986 bool canHaveHashbangComment
= pc_
->atTopLevel();
3987 if (canHaveHashbangComment
) {
3988 tokenStream
.consumeOptionalHashbangComment();
3991 bool afterReturn
= false;
3992 bool warnedAboutStatementsAfterReturn
= false;
3993 uint32_t statementBegin
= 0;
3995 TokenKind tt
= TokenKind::Eof
;
3996 if (!tokenStream
.peekToken(&tt
, TokenStream::SlashIsRegExp
)) {
3997 if (anyChars
.isEOF()) {
3998 isUnexpectedEOF_
= true;
4000 return errorResult();
4002 if (tt
== TokenKind::Eof
|| tt
== TokenKind::RightCurly
) {
4004 if (!tokenStream
.peekTokenPos(&pos
, TokenStream::SlashIsRegExp
)) {
4005 return errorResult();
4007 handler_
.setListEndPosition(stmtList
, pos
);
4011 if (!tokenStream
.peekOffset(&statementBegin
,
4012 TokenStream::SlashIsRegExp
)) {
4013 return errorResult();
4016 auto nextResult
= statementListItem(yieldHandling
, canHaveDirectives
);
4017 if (nextResult
.isErr()) {
4018 if (anyChars
.isEOF()) {
4019 isUnexpectedEOF_
= true;
4021 return errorResult();
4023 Node next
= nextResult
.unwrap();
4024 if (!warnedAboutStatementsAfterReturn
) {
4026 if (!handler_
.isStatementPermittedAfterReturnStatement(next
)) {
4027 if (!warningAt(statementBegin
, JSMSG_STMT_AFTER_RETURN
)) {
4028 return errorResult();
4031 warnedAboutStatementsAfterReturn
= true;
4033 } else if (handler_
.isReturnStatement(next
)) {
4038 if (canHaveDirectives
) {
4039 if (!maybeParseDirective(stmtList
, next
, &canHaveDirectives
)) {
4040 return errorResult();
4044 handler_
.addStatementToList(stmtList
, next
);
4050 template <class ParseHandler
, typename Unit
>
4051 typename
ParseHandler::NodeResult GeneralParser
<ParseHandler
, Unit
>::condition(
4052 InHandling inHandling
, YieldHandling yieldHandling
) {
4053 if (!mustMatchToken(TokenKind::LeftParen
, JSMSG_PAREN_BEFORE_COND
)) {
4054 return errorResult();
4058 MOZ_TRY_VAR(pn
, exprInParens(inHandling
, yieldHandling
, TripledotProhibited
));
4060 if (!mustMatchToken(TokenKind::RightParen
, JSMSG_PAREN_AFTER_COND
)) {
4061 return errorResult();
4067 template <class ParseHandler
, typename Unit
>
4068 bool GeneralParser
<ParseHandler
, Unit
>::matchLabel(
4069 YieldHandling yieldHandling
, TaggedParserAtomIndex
* labelOut
) {
4070 MOZ_ASSERT(labelOut
!= nullptr);
4071 TokenKind tt
= TokenKind::Eof
;
4072 if (!tokenStream
.peekTokenSameLine(&tt
, TokenStream::SlashIsRegExp
)) {
4076 if (TokenKindIsPossibleIdentifier(tt
)) {
4077 tokenStream
.consumeKnownToken(tt
, TokenStream::SlashIsRegExp
);
4079 *labelOut
= labelIdentifier(yieldHandling
);
4084 *labelOut
= TaggedParserAtomIndex::null();
4089 template <class ParseHandler
, typename Unit
>
4090 GeneralParser
<ParseHandler
, Unit
>::PossibleError::PossibleError(
4091 GeneralParser
<ParseHandler
, Unit
>& parser
)
4092 : parser_(parser
) {}
4094 template <class ParseHandler
, typename Unit
>
4095 typename GeneralParser
<ParseHandler
, Unit
>::PossibleError::Error
&
4096 GeneralParser
<ParseHandler
, Unit
>::PossibleError::error(ErrorKind kind
) {
4097 if (kind
== ErrorKind::Expression
) {
4100 if (kind
== ErrorKind::Destructuring
) {
4101 return destructuringError_
;
4103 MOZ_ASSERT(kind
== ErrorKind::DestructuringWarning
);
4104 return destructuringWarning_
;
4107 template <class ParseHandler
, typename Unit
>
4108 void GeneralParser
<ParseHandler
, Unit
>::PossibleError::setResolved(
4110 error(kind
).state_
= ErrorState::None
;
4113 template <class ParseHandler
, typename Unit
>
4114 bool GeneralParser
<ParseHandler
, Unit
>::PossibleError::hasError(
4116 return error(kind
).state_
== ErrorState::Pending
;
4119 template <class ParseHandler
, typename Unit
>
4120 bool GeneralParser
<ParseHandler
,
4121 Unit
>::PossibleError::hasPendingDestructuringError() {
4122 return hasError(ErrorKind::Destructuring
);
4125 template <class ParseHandler
, typename Unit
>
4126 void GeneralParser
<ParseHandler
, Unit
>::PossibleError::setPending(
4127 ErrorKind kind
, const TokenPos
& pos
, unsigned errorNumber
) {
4128 // Don't overwrite a previously recorded error.
4129 if (hasError(kind
)) {
4133 // If we report an error later, we'll do it from the position where we set
4134 // the state to pending.
4135 Error
& err
= error(kind
);
4136 err
.offset_
= pos
.begin
;
4137 err
.errorNumber_
= errorNumber
;
4138 err
.state_
= ErrorState::Pending
;
4141 template <class ParseHandler
, typename Unit
>
4142 void GeneralParser
<ParseHandler
, Unit
>::PossibleError::
4143 setPendingDestructuringErrorAt(const TokenPos
& pos
, unsigned errorNumber
) {
4144 setPending(ErrorKind::Destructuring
, pos
, errorNumber
);
4147 template <class ParseHandler
, typename Unit
>
4148 void GeneralParser
<ParseHandler
, Unit
>::PossibleError::
4149 setPendingDestructuringWarningAt(const TokenPos
& pos
,
4150 unsigned errorNumber
) {
4151 setPending(ErrorKind::DestructuringWarning
, pos
, errorNumber
);
4154 template <class ParseHandler
, typename Unit
>
4155 void GeneralParser
<ParseHandler
, Unit
>::PossibleError::
4156 setPendingExpressionErrorAt(const TokenPos
& pos
, unsigned errorNumber
) {
4157 setPending(ErrorKind::Expression
, pos
, errorNumber
);
4160 template <class ParseHandler
, typename Unit
>
4161 bool GeneralParser
<ParseHandler
, Unit
>::PossibleError::checkForError(
4163 if (!hasError(kind
)) {
4167 Error
& err
= error(kind
);
4168 parser_
.errorAt(err
.offset_
, err
.errorNumber_
);
4172 template <class ParseHandler
, typename Unit
>
4173 bool GeneralParser
<ParseHandler
,
4174 Unit
>::PossibleError::checkForDestructuringErrorOrWarning() {
4175 // Clear pending expression error, because we're definitely not in an
4176 // expression context.
4177 setResolved(ErrorKind::Expression
);
4179 // Report any pending destructuring error.
4180 return checkForError(ErrorKind::Destructuring
);
4183 template <class ParseHandler
, typename Unit
>
4184 bool GeneralParser
<ParseHandler
,
4185 Unit
>::PossibleError::checkForExpressionError() {
4186 // Clear pending destructuring error, because we're definitely not
4187 // in a destructuring context.
4188 setResolved(ErrorKind::Destructuring
);
4189 setResolved(ErrorKind::DestructuringWarning
);
4191 // Report any pending expression error.
4192 return checkForError(ErrorKind::Expression
);
4195 template <class ParseHandler
, typename Unit
>
4196 void GeneralParser
<ParseHandler
, Unit
>::PossibleError::transferErrorTo(
4197 ErrorKind kind
, PossibleError
* other
) {
4198 if (hasError(kind
) && !other
->hasError(kind
)) {
4199 Error
& err
= error(kind
);
4200 Error
& otherErr
= other
->error(kind
);
4201 otherErr
.offset_
= err
.offset_
;
4202 otherErr
.errorNumber_
= err
.errorNumber_
;
4203 otherErr
.state_
= err
.state_
;
4207 template <class ParseHandler
, typename Unit
>
4208 void GeneralParser
<ParseHandler
, Unit
>::PossibleError::transferErrorsTo(
4209 PossibleError
* other
) {
4211 MOZ_ASSERT(this != other
);
4212 MOZ_ASSERT(&parser_
== &other
->parser_
,
4213 "Can't transfer fields to an instance which belongs to a "
4214 "different parser");
4216 transferErrorTo(ErrorKind::Destructuring
, other
);
4217 transferErrorTo(ErrorKind::Expression
, other
);
4220 template <class ParseHandler
, typename Unit
>
4221 typename
ParseHandler::BinaryNodeResult
4222 GeneralParser
<ParseHandler
, Unit
>::bindingInitializer(
4223 Node lhs
, DeclarationKind kind
, YieldHandling yieldHandling
) {
4224 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Assign
));
4226 if (kind
== DeclarationKind::FormalParameter
) {
4227 pc_
->functionBox()->hasParameterExprs
= true;
4231 MOZ_TRY_VAR(rhs
, assignExpr(InAllowed
, yieldHandling
, TripledotProhibited
));
4233 BinaryNodeType assign
;
4235 handler_
.newAssignment(ParseNodeKind::AssignExpr
, lhs
, rhs
));
4240 template <class ParseHandler
, typename Unit
>
4241 typename
ParseHandler::NameNodeResult
4242 GeneralParser
<ParseHandler
, Unit
>::bindingIdentifier(
4243 DeclarationKind kind
, YieldHandling yieldHandling
) {
4244 TaggedParserAtomIndex name
= bindingIdentifier(yieldHandling
);
4246 return errorResult();
4249 NameNodeType binding
;
4250 MOZ_TRY_VAR(binding
, newName(name
));
4251 if (!noteDeclaredName(name
, kind
, pos())) {
4252 return errorResult();
4258 template <class ParseHandler
, typename Unit
>
4259 typename
ParseHandler::NodeResult
4260 GeneralParser
<ParseHandler
, Unit
>::bindingIdentifierOrPattern(
4261 DeclarationKind kind
, YieldHandling yieldHandling
, TokenKind tt
) {
4262 if (tt
== TokenKind::LeftBracket
) {
4263 return arrayBindingPattern(kind
, yieldHandling
);
4266 if (tt
== TokenKind::LeftCurly
) {
4267 return objectBindingPattern(kind
, yieldHandling
);
4270 if (!TokenKindIsPossibleIdentifierName(tt
)) {
4271 error(JSMSG_NO_VARIABLE_NAME
);
4272 return errorResult();
4275 return bindingIdentifier(kind
, yieldHandling
);
4278 template <class ParseHandler
, typename Unit
>
4279 typename
ParseHandler::ListNodeResult
4280 GeneralParser
<ParseHandler
, Unit
>::objectBindingPattern(
4281 DeclarationKind kind
, YieldHandling yieldHandling
) {
4282 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::LeftCurly
));
4284 AutoCheckRecursionLimit
recursion(this->fc_
);
4285 if (!recursion
.check(this->fc_
)) {
4286 return errorResult();
4289 uint32_t begin
= pos().begin
;
4290 ListNodeType literal
;
4291 MOZ_TRY_VAR(literal
, handler_
.newObjectLiteral(begin
));
4293 Maybe
<DeclarationKind
> declKind
= Some(kind
);
4294 TaggedParserAtomIndex propAtom
;
4297 if (!tokenStream
.peekToken(&tt
)) {
4298 return errorResult();
4300 if (tt
== TokenKind::RightCurly
) {
4304 if (tt
== TokenKind::TripleDot
) {
4305 tokenStream
.consumeKnownToken(TokenKind::TripleDot
);
4306 uint32_t begin
= pos().begin
;
4309 if (!tokenStream
.getToken(&tt
)) {
4310 return errorResult();
4313 if (!TokenKindIsPossibleIdentifierName(tt
)) {
4314 error(JSMSG_NO_VARIABLE_NAME
);
4315 return errorResult();
4319 MOZ_TRY_VAR(inner
, bindingIdentifier(kind
, yieldHandling
));
4321 if (!handler_
.addSpreadProperty(literal
, begin
, inner
)) {
4322 return errorResult();
4325 TokenPos namePos
= anyChars
.nextToken().pos
;
4327 PropertyType propType
;
4329 MOZ_TRY_VAR(propName
, propertyOrMethodName(
4330 yieldHandling
, PropertyNameInPattern
, declKind
,
4331 literal
, &propType
, &propAtom
));
4333 if (propType
== PropertyType::Normal
) {
4334 // Handle e.g., |var {p: x} = o| and |var {p: x=0} = o|.
4336 if (!tokenStream
.getToken(&tt
, TokenStream::SlashIsRegExp
)) {
4337 return errorResult();
4341 MOZ_TRY_VAR(binding
,
4342 bindingIdentifierOrPattern(kind
, yieldHandling
, tt
));
4344 bool hasInitializer
;
4345 if (!tokenStream
.matchToken(&hasInitializer
, TokenKind::Assign
,
4346 TokenStream::SlashIsRegExp
)) {
4347 return errorResult();
4351 if (hasInitializer
) {
4352 MOZ_TRY_VAR(bindingExpr
,
4353 bindingInitializer(binding
, kind
, yieldHandling
));
4355 bindingExpr
= binding
;
4358 if (!handler_
.addPropertyDefinition(literal
, propName
, bindingExpr
)) {
4359 return errorResult();
4361 } else if (propType
== PropertyType::Shorthand
) {
4362 // Handle e.g., |var {x, y} = o| as destructuring shorthand
4363 // for |var {x: x, y: y} = o|.
4364 MOZ_ASSERT(TokenKindIsPossibleIdentifierName(tt
));
4366 NameNodeType binding
;
4367 MOZ_TRY_VAR(binding
, bindingIdentifier(kind
, yieldHandling
));
4369 if (!handler_
.addShorthand(literal
, handler_
.asNameNode(propName
),
4371 return errorResult();
4373 } else if (propType
== PropertyType::CoverInitializedName
) {
4374 // Handle e.g., |var {x=1, y=2} = o| as destructuring
4375 // shorthand with default values.
4376 MOZ_ASSERT(TokenKindIsPossibleIdentifierName(tt
));
4378 NameNodeType binding
;
4379 MOZ_TRY_VAR(binding
, bindingIdentifier(kind
, yieldHandling
));
4381 tokenStream
.consumeKnownToken(TokenKind::Assign
);
4383 BinaryNodeType bindingExpr
;
4384 MOZ_TRY_VAR(bindingExpr
,
4385 bindingInitializer(binding
, kind
, yieldHandling
));
4387 if (!handler_
.addPropertyDefinition(literal
, propName
, bindingExpr
)) {
4388 return errorResult();
4391 errorAt(namePos
.begin
, JSMSG_NO_VARIABLE_NAME
);
4392 return errorResult();
4397 if (!tokenStream
.matchToken(&matched
, TokenKind::Comma
,
4398 TokenStream::SlashIsInvalid
)) {
4399 return errorResult();
4404 if (tt
== TokenKind::TripleDot
) {
4405 error(JSMSG_REST_WITH_COMMA
);
4406 return errorResult();
4410 if (!mustMatchToken(TokenKind::RightCurly
, [this, begin
](TokenKind actual
) {
4411 this->reportMissingClosing(JSMSG_CURLY_AFTER_LIST
, JSMSG_CURLY_OPENED
,
4414 return errorResult();
4417 handler_
.setEndPosition(literal
, pos().end
);
4421 template <class ParseHandler
, typename Unit
>
4422 typename
ParseHandler::ListNodeResult
4423 GeneralParser
<ParseHandler
, Unit
>::arrayBindingPattern(
4424 DeclarationKind kind
, YieldHandling yieldHandling
) {
4425 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::LeftBracket
));
4427 AutoCheckRecursionLimit
recursion(this->fc_
);
4428 if (!recursion
.check(this->fc_
)) {
4429 return errorResult();
4432 uint32_t begin
= pos().begin
;
4433 ListNodeType literal
;
4434 MOZ_TRY_VAR(literal
, handler_
.newArrayLiteral(begin
));
4438 if (index
>= NativeObject::MAX_DENSE_ELEMENTS_COUNT
) {
4439 error(JSMSG_ARRAY_INIT_TOO_BIG
);
4440 return errorResult();
4444 if (!tokenStream
.getToken(&tt
)) {
4445 return errorResult();
4448 if (tt
== TokenKind::RightBracket
) {
4449 anyChars
.ungetToken();
4453 if (tt
== TokenKind::Comma
) {
4454 if (!handler_
.addElision(literal
, pos())) {
4455 return errorResult();
4457 } else if (tt
== TokenKind::TripleDot
) {
4458 uint32_t begin
= pos().begin
;
4461 if (!tokenStream
.getToken(&tt
)) {
4462 return errorResult();
4466 MOZ_TRY_VAR(inner
, bindingIdentifierOrPattern(kind
, yieldHandling
, tt
));
4468 if (!handler_
.addSpreadElement(literal
, begin
, inner
)) {
4469 return errorResult();
4473 MOZ_TRY_VAR(binding
, bindingIdentifierOrPattern(kind
, yieldHandling
, tt
));
4475 bool hasInitializer
;
4476 if (!tokenStream
.matchToken(&hasInitializer
, TokenKind::Assign
,
4477 TokenStream::SlashIsRegExp
)) {
4478 return errorResult();
4482 if (hasInitializer
) {
4483 MOZ_TRY_VAR(element
, bindingInitializer(binding
, kind
, yieldHandling
));
4488 handler_
.addArrayElement(literal
, element
);
4491 if (tt
!= TokenKind::Comma
) {
4492 // If we didn't already match TokenKind::Comma in above case.
4494 if (!tokenStream
.matchToken(&matched
, TokenKind::Comma
,
4495 TokenStream::SlashIsRegExp
)) {
4496 return errorResult();
4502 if (tt
== TokenKind::TripleDot
) {
4503 error(JSMSG_REST_WITH_COMMA
);
4504 return errorResult();
4509 if (!mustMatchToken(TokenKind::RightBracket
, [this, begin
](TokenKind actual
) {
4510 this->reportMissingClosing(JSMSG_BRACKET_AFTER_LIST
,
4511 JSMSG_BRACKET_OPENED
, begin
);
4513 return errorResult();
4516 handler_
.setEndPosition(literal
, pos().end
);
4520 template <class ParseHandler
, typename Unit
>
4521 typename
ParseHandler::NodeResult
4522 GeneralParser
<ParseHandler
, Unit
>::destructuringDeclaration(
4523 DeclarationKind kind
, YieldHandling yieldHandling
, TokenKind tt
) {
4524 MOZ_ASSERT(anyChars
.isCurrentTokenType(tt
));
4525 MOZ_ASSERT(tt
== TokenKind::LeftBracket
|| tt
== TokenKind::LeftCurly
);
4527 if (tt
== TokenKind::LeftBracket
) {
4528 return arrayBindingPattern(kind
, yieldHandling
);
4530 return objectBindingPattern(kind
, yieldHandling
);
4533 template <class ParseHandler
, typename Unit
>
4534 typename
ParseHandler::NodeResult
4535 GeneralParser
<ParseHandler
, Unit
>::destructuringDeclarationWithoutYieldOrAwait(
4536 DeclarationKind kind
, YieldHandling yieldHandling
, TokenKind tt
) {
4537 uint32_t startYieldOffset
= pc_
->lastYieldOffset
;
4538 uint32_t startAwaitOffset
= pc_
->lastAwaitOffset
;
4541 MOZ_TRY_VAR(res
, destructuringDeclaration(kind
, yieldHandling
, tt
));
4543 if (pc_
->lastYieldOffset
!= startYieldOffset
) {
4544 errorAt(pc_
->lastYieldOffset
, JSMSG_YIELD_IN_PARAMETER
);
4545 return errorResult();
4547 if (pc_
->lastAwaitOffset
!= startAwaitOffset
) {
4548 errorAt(pc_
->lastAwaitOffset
, JSMSG_AWAIT_IN_PARAMETER
);
4549 return errorResult();
4554 template <class ParseHandler
, typename Unit
>
4555 typename
ParseHandler::LexicalScopeNodeResult
4556 GeneralParser
<ParseHandler
, Unit
>::blockStatement(YieldHandling yieldHandling
,
4557 unsigned errorNumber
) {
4558 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::LeftCurly
));
4559 uint32_t openedPos
= pos().begin
;
4561 ParseContext::Statement
stmt(pc_
, StatementKind::Block
);
4562 ParseContext::Scope
scope(this);
4563 if (!scope
.init(pc_
)) {
4564 return errorResult();
4568 MOZ_TRY_VAR(list
, statementList(yieldHandling
));
4570 if (!mustMatchToken(TokenKind::RightCurly
, [this, errorNumber
,
4571 openedPos
](TokenKind actual
) {
4572 this->reportMissingClosing(errorNumber
, JSMSG_CURLY_OPENED
, openedPos
);
4574 return errorResult();
4577 return finishLexicalScope(scope
, list
);
4580 template <class ParseHandler
, typename Unit
>
4581 typename
ParseHandler::NodeResult
4582 GeneralParser
<ParseHandler
, Unit
>::expressionAfterForInOrOf(
4583 ParseNodeKind forHeadKind
, YieldHandling yieldHandling
) {
4584 MOZ_ASSERT(forHeadKind
== ParseNodeKind::ForIn
||
4585 forHeadKind
== ParseNodeKind::ForOf
);
4586 if (forHeadKind
== ParseNodeKind::ForOf
) {
4587 return assignExpr(InAllowed
, yieldHandling
, TripledotProhibited
);
4590 return expr(InAllowed
, yieldHandling
, TripledotProhibited
);
4593 template <class ParseHandler
, typename Unit
>
4594 typename
ParseHandler::NodeResult
4595 GeneralParser
<ParseHandler
, Unit
>::declarationPattern(
4596 DeclarationKind declKind
, TokenKind tt
, bool initialDeclaration
,
4597 YieldHandling yieldHandling
, ParseNodeKind
* forHeadKind
,
4598 Node
* forInOrOfExpression
) {
4599 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::LeftBracket
) ||
4600 anyChars
.isCurrentTokenType(TokenKind::LeftCurly
));
4603 MOZ_TRY_VAR(pattern
, destructuringDeclaration(declKind
, yieldHandling
, tt
));
4605 if (initialDeclaration
&& forHeadKind
) {
4606 bool isForIn
, isForOf
;
4607 if (!matchInOrOf(&isForIn
, &isForOf
)) {
4608 return errorResult();
4612 *forHeadKind
= ParseNodeKind::ForIn
;
4613 } else if (isForOf
) {
4614 *forHeadKind
= ParseNodeKind::ForOf
;
4616 *forHeadKind
= ParseNodeKind::ForHead
;
4619 if (*forHeadKind
!= ParseNodeKind::ForHead
) {
4620 MOZ_TRY_VAR(*forInOrOfExpression
,
4621 expressionAfterForInOrOf(*forHeadKind
, yieldHandling
));
4627 if (!mustMatchToken(TokenKind::Assign
, JSMSG_BAD_DESTRUCT_DECL
)) {
4628 return errorResult();
4632 MOZ_TRY_VAR(init
, assignExpr(forHeadKind
? InProhibited
: InAllowed
,
4633 yieldHandling
, TripledotProhibited
));
4635 return handler_
.newAssignment(ParseNodeKind::AssignExpr
, pattern
, init
);
4638 template <class ParseHandler
, typename Unit
>
4639 typename
ParseHandler::AssignmentNodeResult
4640 GeneralParser
<ParseHandler
, Unit
>::initializerInNameDeclaration(
4641 NameNodeType binding
, DeclarationKind declKind
, bool initialDeclaration
,
4642 YieldHandling yieldHandling
, ParseNodeKind
* forHeadKind
,
4643 Node
* forInOrOfExpression
) {
4644 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Assign
));
4646 uint32_t initializerOffset
;
4647 if (!tokenStream
.peekOffset(&initializerOffset
, TokenStream::SlashIsRegExp
)) {
4648 return errorResult();
4652 MOZ_TRY_VAR(initializer
, assignExpr(forHeadKind
? InProhibited
: InAllowed
,
4653 yieldHandling
, TripledotProhibited
));
4655 if (forHeadKind
&& initialDeclaration
) {
4656 bool isForIn
, isForOf
;
4657 if (!matchInOrOf(&isForIn
, &isForOf
)) {
4658 return errorResult();
4661 // An initialized declaration can't appear in a for-of:
4663 // for (var/let/const x = ... of ...); // BAD
4665 errorAt(initializerOffset
, JSMSG_OF_AFTER_FOR_LOOP_DECL
);
4666 return errorResult();
4670 // Lexical declarations in for-in loops can't be initialized:
4672 // for (let/const x = ... in ...); // BAD
4673 if (DeclarationKindIsLexical(declKind
)) {
4674 errorAt(initializerOffset
, JSMSG_IN_AFTER_LEXICAL_FOR_DECL
);
4675 return errorResult();
4678 // This leaves only initialized for-in |var| declarations. ES6
4679 // forbids these; later ES un-forbids in non-strict mode code.
4680 *forHeadKind
= ParseNodeKind::ForIn
;
4681 if (!strictModeErrorAt(initializerOffset
,
4682 JSMSG_INVALID_FOR_IN_DECL_WITH_INIT
)) {
4683 return errorResult();
4687 *forInOrOfExpression
,
4688 expressionAfterForInOrOf(ParseNodeKind::ForIn
, yieldHandling
));
4690 *forHeadKind
= ParseNodeKind::ForHead
;
4694 return handler_
.finishInitializerAssignment(binding
, initializer
);
4697 template <class ParseHandler
, typename Unit
>
4698 typename
ParseHandler::NodeResult
4699 GeneralParser
<ParseHandler
, Unit
>::declarationName(DeclarationKind declKind
,
4701 bool initialDeclaration
,
4702 YieldHandling yieldHandling
,
4703 ParseNodeKind
* forHeadKind
,
4704 Node
* forInOrOfExpression
) {
4705 // Anything other than possible identifier is an error.
4706 if (!TokenKindIsPossibleIdentifier(tt
)) {
4707 error(JSMSG_NO_VARIABLE_NAME
);
4708 return errorResult();
4711 TaggedParserAtomIndex name
= bindingIdentifier(yieldHandling
);
4713 return errorResult();
4716 NameNodeType binding
;
4717 MOZ_TRY_VAR(binding
, newName(name
));
4719 TokenPos namePos
= pos();
4721 // The '=' context after a variable name in a declaration is an opportunity
4722 // for ASI, and thus for the next token to start an ExpressionStatement:
4724 // var foo // VariableDeclaration
4725 // /bar/g; // ExpressionStatement
4727 // Therefore get the token here with SlashIsRegExp.
4729 if (!tokenStream
.matchToken(&matched
, TokenKind::Assign
,
4730 TokenStream::SlashIsRegExp
)) {
4731 return errorResult();
4736 MOZ_TRY_VAR(declaration
,
4737 initializerInNameDeclaration(binding
, declKind
,
4738 initialDeclaration
, yieldHandling
,
4739 forHeadKind
, forInOrOfExpression
));
4741 declaration
= binding
;
4743 if (initialDeclaration
&& forHeadKind
) {
4744 bool isForIn
, isForOf
;
4745 if (!matchInOrOf(&isForIn
, &isForOf
)) {
4746 return errorResult();
4750 *forHeadKind
= ParseNodeKind::ForIn
;
4751 } else if (isForOf
) {
4752 *forHeadKind
= ParseNodeKind::ForOf
;
4754 *forHeadKind
= ParseNodeKind::ForHead
;
4758 if (forHeadKind
&& *forHeadKind
!= ParseNodeKind::ForHead
) {
4759 MOZ_TRY_VAR(*forInOrOfExpression
,
4760 expressionAfterForInOrOf(*forHeadKind
, yieldHandling
));
4762 // Normal const declarations, and const declarations in for(;;)
4763 // heads, must be initialized.
4764 if (declKind
== DeclarationKind::Const
) {
4765 errorAt(namePos
.begin
, JSMSG_BAD_CONST_DECL
);
4766 return errorResult();
4771 // Note the declared name after knowing whether or not we are in a for-of
4772 // loop, due to special early error semantics in Annex B.3.5.
4773 if (!noteDeclaredName(name
, declKind
, namePos
)) {
4774 return errorResult();
4780 template <class ParseHandler
, typename Unit
>
4781 typename
ParseHandler::DeclarationListNodeResult
4782 GeneralParser
<ParseHandler
, Unit
>::declarationList(
4783 YieldHandling yieldHandling
, ParseNodeKind kind
,
4784 ParseNodeKind
* forHeadKind
/* = nullptr */,
4785 Node
* forInOrOfExpression
/* = nullptr */) {
4786 MOZ_ASSERT(kind
== ParseNodeKind::VarStmt
|| kind
== ParseNodeKind::LetDecl
||
4787 kind
== ParseNodeKind::ConstDecl
);
4789 DeclarationKind declKind
;
4791 case ParseNodeKind::VarStmt
:
4792 declKind
= DeclarationKind::Var
;
4794 case ParseNodeKind::ConstDecl
:
4795 declKind
= DeclarationKind::Const
;
4797 case ParseNodeKind::LetDecl
:
4798 declKind
= DeclarationKind::Let
;
4801 MOZ_CRASH("Unknown declaration kind");
4804 DeclarationListNodeType decl
;
4805 MOZ_TRY_VAR(decl
, handler_
.newDeclarationList(kind
, pos()));
4807 bool moreDeclarations
;
4808 bool initialDeclaration
= true;
4810 MOZ_ASSERT_IF(!initialDeclaration
&& forHeadKind
,
4811 *forHeadKind
== ParseNodeKind::ForHead
);
4814 if (!tokenStream
.getToken(&tt
)) {
4815 return errorResult();
4819 if (tt
== TokenKind::LeftBracket
|| tt
== TokenKind::LeftCurly
) {
4820 MOZ_TRY_VAR(binding
, declarationPattern(declKind
, tt
, initialDeclaration
,
4821 yieldHandling
, forHeadKind
,
4822 forInOrOfExpression
));
4824 MOZ_TRY_VAR(binding
, declarationName(declKind
, tt
, initialDeclaration
,
4825 yieldHandling
, forHeadKind
,
4826 forInOrOfExpression
));
4829 handler_
.addList(decl
, binding
);
4831 // If we have a for-in/of loop, the above call matches the entirety
4832 // of the loop head (up to the closing parenthesis).
4833 if (forHeadKind
&& *forHeadKind
!= ParseNodeKind::ForHead
) {
4837 initialDeclaration
= false;
4839 if (!tokenStream
.matchToken(&moreDeclarations
, TokenKind::Comma
,
4840 TokenStream::SlashIsRegExp
)) {
4841 return errorResult();
4843 } while (moreDeclarations
);
4848 template <class ParseHandler
, typename Unit
>
4849 typename
ParseHandler::DeclarationListNodeResult
4850 GeneralParser
<ParseHandler
, Unit
>::lexicalDeclaration(
4851 YieldHandling yieldHandling
, DeclarationKind kind
) {
4852 MOZ_ASSERT(kind
== DeclarationKind::Const
|| kind
== DeclarationKind::Let
);
4854 if (options().selfHostingMode
) {
4855 error(JSMSG_SELFHOSTED_LEXICAL
);
4856 return errorResult();
4860 * Parse body-level lets without a new block object. ES6 specs
4861 * that an execution environment's initial lexical environment
4862 * is the VariableEnvironment, i.e., body-level lets are in
4863 * the same environment record as vars.
4865 * However, they cannot be parsed exactly as vars, as ES6
4866 * requires that uninitialized lets throw ReferenceError on use.
4868 * See 8.1.1.1.6 and the note in 13.2.1.
4870 DeclarationListNodeType decl
;
4872 declarationList(yieldHandling
, kind
== DeclarationKind::Const
4873 ? ParseNodeKind::ConstDecl
4874 : ParseNodeKind::LetDecl
));
4875 if (!matchOrInsertSemicolon()) {
4876 return errorResult();
4882 template <class ParseHandler
, typename Unit
>
4883 typename
ParseHandler::NameNodeResult
4884 GeneralParser
<ParseHandler
, Unit
>::moduleExportName() {
4885 MOZ_ASSERT(anyChars
.currentToken().type
== TokenKind::String
);
4886 TaggedParserAtomIndex name
= anyChars
.currentToken().atom();
4887 if (!this->parserAtoms().isModuleExportName(name
)) {
4888 error(JSMSG_UNPAIRED_SURROGATE_EXPORT
);
4889 return errorResult();
4891 return handler_
.newStringLiteral(name
, pos());
4894 template <class ParseHandler
, typename Unit
>
4895 bool GeneralParser
<ParseHandler
, Unit
>::assertClause(
4896 ListNodeType assertionsSet
) {
4897 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Assert
));
4899 if (!options().importAssertions()) {
4900 error(JSMSG_IMPORT_ASSERTIONS_NOT_SUPPORTED
);
4904 if (!abortIfSyntaxParser()) {
4908 if (!mustMatchToken(TokenKind::LeftCurly
, JSMSG_CURLY_AFTER_ASSERT
)) {
4912 // Handle the form |... assert {}|
4914 if (!tokenStream
.getToken(&token
)) {
4917 if (token
== TokenKind::RightCurly
) {
4921 js::HashSet
<TaggedParserAtomIndex
, TaggedParserAtomIndexHasher
,
4922 js::SystemAllocPolicy
>
4926 TaggedParserAtomIndex keyName
;
4927 if (TokenKindIsPossibleIdentifierName(token
)) {
4928 keyName
= anyChars
.currentName();
4929 } else if (token
== TokenKind::String
) {
4930 keyName
= anyChars
.currentToken().atom();
4932 error(JSMSG_ASSERT_KEY_EXPECTED
);
4936 auto p
= usedAssertionKeys
.lookupForAdd(keyName
);
4938 UniqueChars str
= this->parserAtoms().toPrintableString(keyName
);
4940 ReportOutOfMemory(this->fc_
);
4943 error(JSMSG_DUPLICATE_ASSERT_KEY
, str
.get());
4946 if (!usedAssertionKeys
.add(p
, keyName
)) {
4947 ReportOutOfMemory(this->fc_
);
4951 NameNodeType keyNode
;
4952 MOZ_TRY_VAR_OR_RETURN(keyNode
, newName(keyName
), false);
4954 if (!mustMatchToken(TokenKind::Colon
, JSMSG_COLON_AFTER_ASSERT_KEY
)) {
4957 if (!mustMatchToken(TokenKind::String
, JSMSG_ASSERT_STRING_LITERAL
)) {
4961 NameNodeType valueNode
;
4962 MOZ_TRY_VAR_OR_RETURN(valueNode
, stringLiteral(), false);
4964 BinaryNodeType importAssertionNode
;
4965 MOZ_TRY_VAR_OR_RETURN(importAssertionNode
,
4966 handler_
.newImportAssertion(keyNode
, valueNode
),
4969 handler_
.addList(assertionsSet
, importAssertionNode
);
4971 if (!tokenStream
.getToken(&token
)) {
4974 if (token
== TokenKind::Comma
) {
4975 if (!tokenStream
.getToken(&token
)) {
4979 if (token
== TokenKind::RightCurly
) {
4987 template <class ParseHandler
, typename Unit
>
4988 bool GeneralParser
<ParseHandler
, Unit
>::namedImports(
4989 ListNodeType importSpecSet
) {
4990 if (!abortIfSyntaxParser()) {
4995 // Handle the forms |import {} from 'a'| and
4996 // |import { ..., } from 'a'| (where ... is non empty), by
4997 // escaping the loop early if the next token is }.
4999 if (!tokenStream
.getToken(&tt
)) {
5003 if (tt
== TokenKind::RightCurly
) {
5007 TaggedParserAtomIndex importName
;
5008 NameNodeType importNameNode
= null();
5009 if (TokenKindIsPossibleIdentifierName(tt
)) {
5010 importName
= anyChars
.currentName();
5011 MOZ_TRY_VAR_OR_RETURN(importNameNode
, newName(importName
), false);
5012 } else if (tt
== TokenKind::String
) {
5013 MOZ_TRY_VAR_OR_RETURN(importNameNode
, moduleExportName(), false);
5015 error(JSMSG_NO_IMPORT_NAME
);
5020 if (!tokenStream
.matchToken(&matched
, TokenKind::As
)) {
5026 if (!tokenStream
.getToken(&afterAs
)) {
5030 if (!TokenKindIsPossibleIdentifierName(afterAs
)) {
5031 error(JSMSG_NO_BINDING_NAME
);
5035 // String export names can't refer to local bindings.
5036 if (tt
== TokenKind::String
) {
5037 error(JSMSG_AS_AFTER_STRING
);
5041 // Keywords cannot be bound to themselves, so an import name
5042 // that is a keyword is a syntax error if it is not followed
5043 // by the keyword 'as'.
5044 // See the ImportSpecifier production in ES6 section 15.2.2.
5045 MOZ_ASSERT(importName
);
5046 if (IsKeyword(importName
)) {
5047 error(JSMSG_AS_AFTER_RESERVED_WORD
, ReservedWordToCharZ(importName
));
5052 TaggedParserAtomIndex bindingAtom
= importedBinding();
5057 NameNodeType bindingName
;
5058 MOZ_TRY_VAR_OR_RETURN(bindingName
, newName(bindingAtom
), false);
5059 if (!noteDeclaredName(bindingAtom
, DeclarationKind::Import
, pos())) {
5063 BinaryNodeType importSpec
;
5064 MOZ_TRY_VAR_OR_RETURN(
5065 importSpec
, handler_
.newImportSpec(importNameNode
, bindingName
), false);
5067 handler_
.addList(importSpecSet
, importSpec
);
5070 if (!tokenStream
.getToken(&next
)) {
5074 if (next
== TokenKind::RightCurly
) {
5078 if (next
!= TokenKind::Comma
) {
5079 error(JSMSG_RC_AFTER_IMPORT_SPEC_LIST
);
5087 template <class ParseHandler
, typename Unit
>
5088 bool GeneralParser
<ParseHandler
, Unit
>::namespaceImport(
5089 ListNodeType importSpecSet
) {
5090 if (!abortIfSyntaxParser()) {
5094 if (!mustMatchToken(TokenKind::As
, JSMSG_AS_AFTER_IMPORT_STAR
)) {
5097 uint32_t begin
= pos().begin
;
5099 if (!mustMatchToken(TokenKindIsPossibleIdentifierName
,
5100 JSMSG_NO_BINDING_NAME
)) {
5104 // Namespace imports are not indirect bindings but lexical
5105 // definitions that hold a module namespace object. They are treated
5106 // as const variables which are initialized during the
5107 // ModuleInstantiate step.
5108 TaggedParserAtomIndex bindingName
= importedBinding();
5112 NameNodeType bindingNameNode
;
5113 MOZ_TRY_VAR_OR_RETURN(bindingNameNode
, newName(bindingName
), false);
5114 if (!noteDeclaredName(bindingName
, DeclarationKind::Const
, pos())) {
5118 // The namespace import name is currently required to live on the
5120 pc_
->varScope().lookupDeclaredName(bindingName
)->value()->setClosedOver();
5122 UnaryNodeType importSpec
;
5123 MOZ_TRY_VAR_OR_RETURN(importSpec
,
5124 handler_
.newImportNamespaceSpec(begin
, bindingNameNode
),
5127 handler_
.addList(importSpecSet
, importSpec
);
5132 template <class ParseHandler
, typename Unit
>
5133 typename
ParseHandler::BinaryNodeResult
5134 GeneralParser
<ParseHandler
, Unit
>::importDeclaration() {
5135 if (!abortIfSyntaxParser()) {
5136 return errorResult();
5139 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Import
));
5141 if (!pc_
->atModuleLevel()) {
5142 error(JSMSG_IMPORT_DECL_AT_TOP_LEVEL
);
5143 return errorResult();
5146 uint32_t begin
= pos().begin
;
5148 if (!tokenStream
.getToken(&tt
)) {
5149 return errorResult();
5152 ListNodeType importSpecSet
;
5153 MOZ_TRY_VAR(importSpecSet
,
5154 handler_
.newList(ParseNodeKind::ImportSpecList
, pos()));
5156 if (tt
== TokenKind::String
) {
5157 // Handle the form |import 'a'| by leaving the list empty. This is
5158 // equivalent to |import {} from 'a'|.
5159 handler_
.setEndPosition(importSpecSet
, pos().begin
);
5161 if (tt
== TokenKind::LeftCurly
) {
5162 if (!namedImports(importSpecSet
)) {
5163 return errorResult();
5165 } else if (tt
== TokenKind::Mul
) {
5166 if (!namespaceImport(importSpecSet
)) {
5167 return errorResult();
5169 } else if (TokenKindIsPossibleIdentifierName(tt
)) {
5170 // Handle the form |import a from 'b'|, by adding a single import
5171 // specifier to the list, with 'default' as the import name and
5172 // 'a' as the binding name. This is equivalent to
5173 // |import { default as a } from 'b'|.
5174 NameNodeType importName
;
5175 MOZ_TRY_VAR(importName
,
5176 newName(TaggedParserAtomIndex::WellKnown::default_()));
5178 TaggedParserAtomIndex bindingAtom
= importedBinding();
5180 return errorResult();
5183 NameNodeType bindingName
;
5184 MOZ_TRY_VAR(bindingName
, newName(bindingAtom
));
5186 if (!noteDeclaredName(bindingAtom
, DeclarationKind::Import
, pos())) {
5187 return errorResult();
5190 BinaryNodeType importSpec
;
5191 MOZ_TRY_VAR(importSpec
, handler_
.newImportSpec(importName
, bindingName
));
5193 handler_
.addList(importSpecSet
, importSpec
);
5195 if (!tokenStream
.peekToken(&tt
)) {
5196 return errorResult();
5199 if (tt
== TokenKind::Comma
) {
5200 tokenStream
.consumeKnownToken(tt
);
5201 if (!tokenStream
.getToken(&tt
)) {
5202 return errorResult();
5205 if (tt
== TokenKind::LeftCurly
) {
5206 if (!namedImports(importSpecSet
)) {
5207 return errorResult();
5209 } else if (tt
== TokenKind::Mul
) {
5210 if (!namespaceImport(importSpecSet
)) {
5211 return errorResult();
5214 error(JSMSG_NAMED_IMPORTS_OR_NAMESPACE_IMPORT
);
5215 return errorResult();
5219 error(JSMSG_DECLARATION_AFTER_IMPORT
);
5220 return errorResult();
5223 if (!mustMatchToken(TokenKind::From
, JSMSG_FROM_AFTER_IMPORT_CLAUSE
)) {
5224 return errorResult();
5227 if (!mustMatchToken(TokenKind::String
, JSMSG_MODULE_SPEC_AFTER_FROM
)) {
5228 return errorResult();
5232 NameNodeType moduleSpec
;
5233 MOZ_TRY_VAR(moduleSpec
, stringLiteral());
5235 if (!tokenStream
.peekTokenSameLine(&tt
, TokenStream::SlashIsRegExp
)) {
5236 return errorResult();
5239 ListNodeType importAssertionList
;
5240 MOZ_TRY_VAR(importAssertionList
,
5241 handler_
.newList(ParseNodeKind::ImportAssertionList
, pos()));
5243 if (tt
== TokenKind::Assert
) {
5244 tokenStream
.consumeKnownToken(TokenKind::Assert
,
5245 TokenStream::SlashIsRegExp
);
5247 if (!assertClause(importAssertionList
)) {
5248 return errorResult();
5252 if (!matchOrInsertSemicolon(TokenStream::SlashIsRegExp
)) {
5253 return errorResult();
5256 BinaryNodeType moduleRequest
;
5257 MOZ_TRY_VAR(moduleRequest
,
5258 handler_
.newModuleRequest(moduleSpec
, importAssertionList
,
5259 TokenPos(begin
, pos().end
)));
5261 BinaryNodeType node
;
5262 MOZ_TRY_VAR(node
, handler_
.newImportDeclaration(importSpecSet
, moduleRequest
,
5263 TokenPos(begin
, pos().end
)));
5264 if (!processImport(node
)) {
5265 return errorResult();
5271 template <class ParseHandler
, typename Unit
>
5272 inline typename
ParseHandler::NodeResult
5273 GeneralParser
<ParseHandler
, Unit
>::importDeclarationOrImportExpr(
5274 YieldHandling yieldHandling
) {
5275 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Import
));
5278 if (!tokenStream
.peekToken(&tt
)) {
5279 return errorResult();
5282 if (tt
== TokenKind::Dot
|| tt
== TokenKind::LeftParen
) {
5283 return expressionStatement(yieldHandling
);
5286 return importDeclaration();
5289 template <typename Unit
>
5290 bool Parser
<FullParseHandler
, Unit
>::checkExportedName(
5291 TaggedParserAtomIndex exportName
) {
5292 if (!pc_
->sc()->asModuleContext()->builder
.hasExportedName(exportName
)) {
5296 UniqueChars str
= this->parserAtoms().toPrintableString(exportName
);
5298 ReportOutOfMemory(this->fc_
);
5302 error(JSMSG_DUPLICATE_EXPORT_NAME
, str
.get());
5306 template <typename Unit
>
5307 inline bool Parser
<SyntaxParseHandler
, Unit
>::checkExportedName(
5308 TaggedParserAtomIndex exportName
) {
5309 MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5313 template <class ParseHandler
, typename Unit
>
5314 inline bool GeneralParser
<ParseHandler
, Unit
>::checkExportedName(
5315 TaggedParserAtomIndex exportName
) {
5316 return asFinalParser()->checkExportedName(exportName
);
5319 template <typename Unit
>
5320 bool Parser
<FullParseHandler
, Unit
>::checkExportedNamesForArrayBinding(
5322 MOZ_ASSERT(array
->isKind(ParseNodeKind::ArrayExpr
));
5324 for (ParseNode
* node
: array
->contents()) {
5325 if (node
->isKind(ParseNodeKind::Elision
)) {
5330 if (node
->isKind(ParseNodeKind::Spread
)) {
5331 binding
= node
->as
<UnaryNode
>().kid();
5332 } else if (node
->isKind(ParseNodeKind::AssignExpr
)) {
5333 binding
= node
->as
<AssignmentNode
>().left();
5338 if (!checkExportedNamesForDeclaration(binding
)) {
5346 template <typename Unit
>
5347 inline bool Parser
<SyntaxParseHandler
, Unit
>::checkExportedNamesForArrayBinding(
5348 ListNodeType array
) {
5349 MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5353 template <class ParseHandler
, typename Unit
>
5355 GeneralParser
<ParseHandler
, Unit
>::checkExportedNamesForArrayBinding(
5356 ListNodeType array
) {
5357 return asFinalParser()->checkExportedNamesForArrayBinding(array
);
5360 template <typename Unit
>
5361 bool Parser
<FullParseHandler
, Unit
>::checkExportedNamesForObjectBinding(
5363 MOZ_ASSERT(obj
->isKind(ParseNodeKind::ObjectExpr
));
5365 for (ParseNode
* node
: obj
->contents()) {
5366 MOZ_ASSERT(node
->isKind(ParseNodeKind::MutateProto
) ||
5367 node
->isKind(ParseNodeKind::PropertyDefinition
) ||
5368 node
->isKind(ParseNodeKind::Shorthand
) ||
5369 node
->isKind(ParseNodeKind::Spread
));
5372 if (node
->isKind(ParseNodeKind::Spread
)) {
5373 target
= node
->as
<UnaryNode
>().kid();
5375 if (node
->isKind(ParseNodeKind::MutateProto
)) {
5376 target
= node
->as
<UnaryNode
>().kid();
5378 target
= node
->as
<BinaryNode
>().right();
5381 if (target
->isKind(ParseNodeKind::AssignExpr
)) {
5382 target
= target
->as
<AssignmentNode
>().left();
5386 if (!checkExportedNamesForDeclaration(target
)) {
5394 template <typename Unit
>
5395 inline bool Parser
<SyntaxParseHandler
,
5396 Unit
>::checkExportedNamesForObjectBinding(ListNodeType obj
) {
5397 MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5401 template <class ParseHandler
, typename Unit
>
5403 GeneralParser
<ParseHandler
, Unit
>::checkExportedNamesForObjectBinding(
5405 return asFinalParser()->checkExportedNamesForObjectBinding(obj
);
5408 template <typename Unit
>
5409 bool Parser
<FullParseHandler
, Unit
>::checkExportedNamesForDeclaration(
5411 if (node
->isKind(ParseNodeKind::Name
)) {
5412 if (!checkExportedName(node
->as
<NameNode
>().atom())) {
5415 } else if (node
->isKind(ParseNodeKind::ArrayExpr
)) {
5416 if (!checkExportedNamesForArrayBinding(&node
->as
<ListNode
>())) {
5420 MOZ_ASSERT(node
->isKind(ParseNodeKind::ObjectExpr
));
5421 if (!checkExportedNamesForObjectBinding(&node
->as
<ListNode
>())) {
5429 template <typename Unit
>
5430 inline bool Parser
<SyntaxParseHandler
, Unit
>::checkExportedNamesForDeclaration(
5432 MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5436 template <class ParseHandler
, typename Unit
>
5437 inline bool GeneralParser
<ParseHandler
, Unit
>::checkExportedNamesForDeclaration(
5439 return asFinalParser()->checkExportedNamesForDeclaration(node
);
5442 template <typename Unit
>
5443 bool Parser
<FullParseHandler
, Unit
>::checkExportedNamesForDeclarationList(
5444 DeclarationListNodeType node
) {
5445 for (ParseNode
* binding
: node
->contents()) {
5446 if (binding
->isKind(ParseNodeKind::AssignExpr
)) {
5447 binding
= binding
->as
<AssignmentNode
>().left();
5449 MOZ_ASSERT(binding
->isKind(ParseNodeKind::Name
));
5452 if (!checkExportedNamesForDeclaration(binding
)) {
5460 template <typename Unit
>
5462 Parser
<SyntaxParseHandler
, Unit
>::checkExportedNamesForDeclarationList(
5463 DeclarationListNodeType node
) {
5464 MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5468 template <class ParseHandler
, typename Unit
>
5470 GeneralParser
<ParseHandler
, Unit
>::checkExportedNamesForDeclarationList(
5471 DeclarationListNodeType node
) {
5472 return asFinalParser()->checkExportedNamesForDeclarationList(node
);
5475 template <typename Unit
>
5476 inline bool Parser
<FullParseHandler
, Unit
>::checkExportedNameForClause(
5477 NameNode
* nameNode
) {
5478 return checkExportedName(nameNode
->atom());
5481 template <typename Unit
>
5482 inline bool Parser
<SyntaxParseHandler
, Unit
>::checkExportedNameForClause(
5483 NameNodeType nameNode
) {
5484 MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5488 template <class ParseHandler
, typename Unit
>
5489 inline bool GeneralParser
<ParseHandler
, Unit
>::checkExportedNameForClause(
5490 NameNodeType nameNode
) {
5491 return asFinalParser()->checkExportedNameForClause(nameNode
);
5494 template <typename Unit
>
5495 bool Parser
<FullParseHandler
, Unit
>::checkExportedNameForFunction(
5496 FunctionNode
* funNode
) {
5497 return checkExportedName(funNode
->funbox()->explicitName());
5500 template <typename Unit
>
5501 inline bool Parser
<SyntaxParseHandler
, Unit
>::checkExportedNameForFunction(
5502 FunctionNodeType funNode
) {
5503 MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5507 template <class ParseHandler
, typename Unit
>
5508 inline bool GeneralParser
<ParseHandler
, Unit
>::checkExportedNameForFunction(
5509 FunctionNodeType funNode
) {
5510 return asFinalParser()->checkExportedNameForFunction(funNode
);
5513 template <typename Unit
>
5514 bool Parser
<FullParseHandler
, Unit
>::checkExportedNameForClass(
5515 ClassNode
* classNode
) {
5516 MOZ_ASSERT(classNode
->names());
5517 return checkExportedName(classNode
->names()->innerBinding()->atom());
5520 template <typename Unit
>
5521 inline bool Parser
<SyntaxParseHandler
, Unit
>::checkExportedNameForClass(
5522 ClassNodeType classNode
) {
5523 MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5527 template <class ParseHandler
, typename Unit
>
5528 inline bool GeneralParser
<ParseHandler
, Unit
>::checkExportedNameForClass(
5529 ClassNodeType classNode
) {
5530 return asFinalParser()->checkExportedNameForClass(classNode
);
5534 inline bool PerHandlerParser
<FullParseHandler
>::processExport(ParseNode
* node
) {
5535 return pc_
->sc()->asModuleContext()->builder
.processExport(node
);
5539 inline bool PerHandlerParser
<SyntaxParseHandler
>::processExport(Node node
) {
5540 MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5545 inline bool PerHandlerParser
<FullParseHandler
>::processExportFrom(
5546 BinaryNodeType node
) {
5547 return pc_
->sc()->asModuleContext()->builder
.processExportFrom(node
);
5551 inline bool PerHandlerParser
<SyntaxParseHandler
>::processExportFrom(
5552 BinaryNodeType node
) {
5553 MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5558 inline bool PerHandlerParser
<FullParseHandler
>::processImport(
5559 BinaryNodeType node
) {
5560 return pc_
->sc()->asModuleContext()->builder
.processImport(node
);
5564 inline bool PerHandlerParser
<SyntaxParseHandler
>::processImport(
5565 BinaryNodeType node
) {
5566 MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5570 template <class ParseHandler
, typename Unit
>
5571 typename
ParseHandler::BinaryNodeResult
5572 GeneralParser
<ParseHandler
, Unit
>::exportFrom(uint32_t begin
, Node specList
) {
5573 if (!abortIfSyntaxParser()) {
5574 return errorResult();
5577 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::From
));
5579 if (!mustMatchToken(TokenKind::String
, JSMSG_MODULE_SPEC_AFTER_FROM
)) {
5580 return errorResult();
5583 NameNodeType moduleSpec
;
5584 MOZ_TRY_VAR(moduleSpec
, stringLiteral());
5587 if (!tokenStream
.peekTokenSameLine(&tt
, TokenStream::SlashIsRegExp
)) {
5588 return errorResult();
5590 uint32_t moduleSpecPos
= pos().begin
;
5592 ListNodeType importAssertionList
;
5593 MOZ_TRY_VAR(importAssertionList
,
5594 handler_
.newList(ParseNodeKind::ImportAssertionList
, pos()));
5595 if (tt
== TokenKind::Assert
) {
5596 tokenStream
.consumeKnownToken(TokenKind::Assert
,
5597 TokenStream::SlashIsRegExp
);
5599 if (!assertClause(importAssertionList
)) {
5600 return errorResult();
5604 if (!matchOrInsertSemicolon(TokenStream::SlashIsRegExp
)) {
5605 return errorResult();
5608 BinaryNodeType moduleRequest
;
5609 MOZ_TRY_VAR(moduleRequest
,
5610 handler_
.newModuleRequest(moduleSpec
, importAssertionList
,
5611 TokenPos(moduleSpecPos
, pos().end
)));
5613 BinaryNodeType node
;
5615 node
, handler_
.newExportFromDeclaration(begin
, specList
, moduleRequest
));
5617 if (!processExportFrom(node
)) {
5618 return errorResult();
5624 template <class ParseHandler
, typename Unit
>
5625 typename
ParseHandler::BinaryNodeResult
5626 GeneralParser
<ParseHandler
, Unit
>::exportBatch(uint32_t begin
) {
5627 if (!abortIfSyntaxParser()) {
5628 return errorResult();
5631 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Mul
));
5632 uint32_t beginExportSpec
= pos().begin
;
5635 MOZ_TRY_VAR(kid
, handler_
.newList(ParseNodeKind::ExportSpecList
, pos()));
5638 if (!tokenStream
.matchToken(&foundAs
, TokenKind::As
)) {
5639 return errorResult();
5644 if (!tokenStream
.getToken(&tt
)) {
5645 return errorResult();
5648 NameNodeType exportName
= null();
5649 if (TokenKindIsPossibleIdentifierName(tt
)) {
5650 MOZ_TRY_VAR(exportName
, newName(anyChars
.currentName()));
5651 } else if (tt
== TokenKind::String
) {
5652 MOZ_TRY_VAR(exportName
, moduleExportName());
5654 error(JSMSG_NO_EXPORT_NAME
);
5655 return errorResult();
5658 if (!checkExportedNameForClause(exportName
)) {
5659 return errorResult();
5662 UnaryNodeType exportSpec
;
5663 MOZ_TRY_VAR(exportSpec
,
5664 handler_
.newExportNamespaceSpec(beginExportSpec
, exportName
));
5666 handler_
.addList(kid
, exportSpec
);
5668 // Handle the form |export *| by adding a special export batch
5669 // specifier to the list.
5670 NullaryNodeType exportSpec
;
5671 MOZ_TRY_VAR(exportSpec
, handler_
.newExportBatchSpec(pos()));
5673 handler_
.addList(kid
, exportSpec
);
5676 if (!mustMatchToken(TokenKind::From
, JSMSG_FROM_AFTER_EXPORT_STAR
)) {
5677 return errorResult();
5680 return exportFrom(begin
, kid
);
5683 template <typename Unit
>
5684 bool Parser
<FullParseHandler
, Unit
>::checkLocalExportNames(ListNode
* node
) {
5685 // ES 2017 draft 15.2.3.1.
5686 for (ParseNode
* next
: node
->contents()) {
5687 ParseNode
* name
= next
->as
<BinaryNode
>().left();
5689 if (name
->isKind(ParseNodeKind::StringExpr
)) {
5690 errorAt(name
->pn_pos
.begin
, JSMSG_BAD_LOCAL_STRING_EXPORT
);
5694 MOZ_ASSERT(name
->isKind(ParseNodeKind::Name
));
5696 TaggedParserAtomIndex ident
= name
->as
<NameNode
>().atom();
5697 if (!checkLocalExportName(ident
, name
->pn_pos
.begin
)) {
5705 template <typename Unit
>
5706 bool Parser
<SyntaxParseHandler
, Unit
>::checkLocalExportNames(
5707 ListNodeType node
) {
5708 MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5712 template <class ParseHandler
, typename Unit
>
5713 inline bool GeneralParser
<ParseHandler
, Unit
>::checkLocalExportNames(
5714 ListNodeType node
) {
5715 return asFinalParser()->checkLocalExportNames(node
);
5718 template <class ParseHandler
, typename Unit
>
5719 typename
ParseHandler::NodeResult
5720 GeneralParser
<ParseHandler
, Unit
>::exportClause(uint32_t begin
) {
5721 if (!abortIfSyntaxParser()) {
5722 return errorResult();
5725 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::LeftCurly
));
5728 MOZ_TRY_VAR(kid
, handler_
.newList(ParseNodeKind::ExportSpecList
, pos()));
5732 // Handle the forms |export {}| and |export { ..., }| (where ... is non
5733 // empty), by escaping the loop early if the next token is }.
5734 if (!tokenStream
.getToken(&tt
)) {
5735 return errorResult();
5738 if (tt
== TokenKind::RightCurly
) {
5742 NameNodeType bindingName
= null();
5743 if (TokenKindIsPossibleIdentifierName(tt
)) {
5744 MOZ_TRY_VAR(bindingName
, newName(anyChars
.currentName()));
5745 } else if (tt
== TokenKind::String
) {
5746 MOZ_TRY_VAR(bindingName
, moduleExportName());
5748 error(JSMSG_NO_BINDING_NAME
);
5749 return errorResult();
5753 if (!tokenStream
.matchToken(&foundAs
, TokenKind::As
)) {
5754 return errorResult();
5757 NameNodeType exportName
= null();
5760 if (!tokenStream
.getToken(&tt
)) {
5761 return errorResult();
5764 if (TokenKindIsPossibleIdentifierName(tt
)) {
5765 MOZ_TRY_VAR(exportName
, newName(anyChars
.currentName()));
5766 } else if (tt
== TokenKind::String
) {
5767 MOZ_TRY_VAR(exportName
, moduleExportName());
5769 error(JSMSG_NO_EXPORT_NAME
);
5770 return errorResult();
5773 if (tt
!= TokenKind::String
) {
5774 MOZ_TRY_VAR(exportName
, newName(anyChars
.currentName()));
5776 MOZ_TRY_VAR(exportName
, moduleExportName());
5780 if (!checkExportedNameForClause(exportName
)) {
5781 return errorResult();
5784 BinaryNodeType exportSpec
;
5785 MOZ_TRY_VAR(exportSpec
, handler_
.newExportSpec(bindingName
, exportName
));
5787 handler_
.addList(kid
, exportSpec
);
5790 if (!tokenStream
.getToken(&next
)) {
5791 return errorResult();
5794 if (next
== TokenKind::RightCurly
) {
5798 if (next
!= TokenKind::Comma
) {
5799 error(JSMSG_RC_AFTER_EXPORT_SPEC_LIST
);
5800 return errorResult();
5804 // Careful! If |from| follows, even on a new line, it must start a
5808 // from "foo"; // a single ExportDeclaration
5810 // But if it doesn't, we might have an ASI opportunity in SlashIsRegExp
5813 // export { x } // ExportDeclaration, terminated by ASI
5814 // fro\u006D // ExpressionStatement, the name "from"
5816 // In that case let matchOrInsertSemicolon sort out ASI or any necessary
5819 if (!tokenStream
.matchToken(&matched
, TokenKind::From
,
5820 TokenStream::SlashIsRegExp
)) {
5821 return errorResult();
5825 return exportFrom(begin
, kid
);
5828 if (!matchOrInsertSemicolon()) {
5829 return errorResult();
5832 if (!checkLocalExportNames(kid
)) {
5833 return errorResult();
5838 handler_
.newExportDeclaration(kid
, TokenPos(begin
, pos().end
)));
5840 if (!processExport(node
)) {
5841 return errorResult();
5847 template <class ParseHandler
, typename Unit
>
5848 typename
ParseHandler::UnaryNodeResult
5849 GeneralParser
<ParseHandler
, Unit
>::exportVariableStatement(uint32_t begin
) {
5850 if (!abortIfSyntaxParser()) {
5851 return errorResult();
5854 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Var
));
5856 DeclarationListNodeType kid
;
5857 MOZ_TRY_VAR(kid
, declarationList(YieldIsName
, ParseNodeKind::VarStmt
));
5858 if (!matchOrInsertSemicolon()) {
5859 return errorResult();
5861 if (!checkExportedNamesForDeclarationList(kid
)) {
5862 return errorResult();
5867 handler_
.newExportDeclaration(kid
, TokenPos(begin
, pos().end
)));
5869 if (!processExport(node
)) {
5870 return errorResult();
5876 template <class ParseHandler
, typename Unit
>
5877 typename
ParseHandler::UnaryNodeResult
5878 GeneralParser
<ParseHandler
, Unit
>::exportFunctionDeclaration(
5879 uint32_t begin
, uint32_t toStringStart
,
5880 FunctionAsyncKind asyncKind
/* = SyncFunction */) {
5881 if (!abortIfSyntaxParser()) {
5882 return errorResult();
5885 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Function
));
5889 kid
, functionStmt(toStringStart
, YieldIsName
, NameRequired
, asyncKind
));
5891 if (!checkExportedNameForFunction(handler_
.asFunctionNode(kid
))) {
5892 return errorResult();
5897 handler_
.newExportDeclaration(kid
, TokenPos(begin
, pos().end
)));
5899 if (!processExport(node
)) {
5900 return errorResult();
5906 template <class ParseHandler
, typename Unit
>
5907 typename
ParseHandler::UnaryNodeResult
5908 GeneralParser
<ParseHandler
, Unit
>::exportClassDeclaration(uint32_t begin
) {
5909 if (!abortIfSyntaxParser()) {
5910 return errorResult();
5913 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Class
));
5916 MOZ_TRY_VAR(kid
, classDefinition(YieldIsName
, ClassStatement
, NameRequired
));
5918 if (!checkExportedNameForClass(kid
)) {
5919 return errorResult();
5924 handler_
.newExportDeclaration(kid
, TokenPos(begin
, pos().end
)));
5926 if (!processExport(node
)) {
5927 return errorResult();
5933 template <class ParseHandler
, typename Unit
>
5934 typename
ParseHandler::UnaryNodeResult
5935 GeneralParser
<ParseHandler
, Unit
>::exportLexicalDeclaration(
5936 uint32_t begin
, DeclarationKind kind
) {
5937 if (!abortIfSyntaxParser()) {
5938 return errorResult();
5941 MOZ_ASSERT(kind
== DeclarationKind::Const
|| kind
== DeclarationKind::Let
);
5942 MOZ_ASSERT_IF(kind
== DeclarationKind::Const
,
5943 anyChars
.isCurrentTokenType(TokenKind::Const
));
5944 MOZ_ASSERT_IF(kind
== DeclarationKind::Let
,
5945 anyChars
.isCurrentTokenType(TokenKind::Let
));
5947 DeclarationListNodeType kid
;
5948 MOZ_TRY_VAR(kid
, lexicalDeclaration(YieldIsName
, kind
));
5949 if (!checkExportedNamesForDeclarationList(kid
)) {
5950 return errorResult();
5955 handler_
.newExportDeclaration(kid
, TokenPos(begin
, pos().end
)));
5957 if (!processExport(node
)) {
5958 return errorResult();
5964 template <class ParseHandler
, typename Unit
>
5965 typename
ParseHandler::BinaryNodeResult
5966 GeneralParser
<ParseHandler
, Unit
>::exportDefaultFunctionDeclaration(
5967 uint32_t begin
, uint32_t toStringStart
,
5968 FunctionAsyncKind asyncKind
/* = SyncFunction */) {
5969 if (!abortIfSyntaxParser()) {
5970 return errorResult();
5973 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Function
));
5976 MOZ_TRY_VAR(kid
, functionStmt(toStringStart
, YieldIsName
, AllowDefaultName
,
5979 BinaryNodeType node
;
5980 MOZ_TRY_VAR(node
, handler_
.newExportDefaultDeclaration(
5981 kid
, null(), TokenPos(begin
, pos().end
)));
5983 if (!processExport(node
)) {
5984 return errorResult();
5990 template <class ParseHandler
, typename Unit
>
5991 typename
ParseHandler::BinaryNodeResult
5992 GeneralParser
<ParseHandler
, Unit
>::exportDefaultClassDeclaration(
5994 if (!abortIfSyntaxParser()) {
5995 return errorResult();
5998 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Class
));
6002 classDefinition(YieldIsName
, ClassStatement
, AllowDefaultName
));
6004 BinaryNodeType node
;
6005 MOZ_TRY_VAR(node
, handler_
.newExportDefaultDeclaration(
6006 kid
, null(), TokenPos(begin
, pos().end
)));
6008 if (!processExport(node
)) {
6009 return errorResult();
6015 template <class ParseHandler
, typename Unit
>
6016 typename
ParseHandler::BinaryNodeResult
6017 GeneralParser
<ParseHandler
, Unit
>::exportDefaultAssignExpr(uint32_t begin
) {
6018 if (!abortIfSyntaxParser()) {
6019 return errorResult();
6022 TaggedParserAtomIndex name
= TaggedParserAtomIndex::WellKnown::default_();
6023 NameNodeType nameNode
;
6024 MOZ_TRY_VAR(nameNode
, newName(name
));
6025 if (!noteDeclaredName(name
, DeclarationKind::Const
, pos())) {
6026 return errorResult();
6030 MOZ_TRY_VAR(kid
, assignExpr(InAllowed
, YieldIsName
, TripledotProhibited
));
6032 if (!matchOrInsertSemicolon()) {
6033 return errorResult();
6036 BinaryNodeType node
;
6037 MOZ_TRY_VAR(node
, handler_
.newExportDefaultDeclaration(
6038 kid
, nameNode
, TokenPos(begin
, pos().end
)));
6040 if (!processExport(node
)) {
6041 return errorResult();
6047 template <class ParseHandler
, typename Unit
>
6048 typename
ParseHandler::BinaryNodeResult
6049 GeneralParser
<ParseHandler
, Unit
>::exportDefault(uint32_t begin
) {
6050 if (!abortIfSyntaxParser()) {
6051 return errorResult();
6054 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Default
));
6057 if (!tokenStream
.getToken(&tt
, TokenStream::SlashIsRegExp
)) {
6058 return errorResult();
6061 if (!checkExportedName(TaggedParserAtomIndex::WellKnown::default_())) {
6062 return errorResult();
6066 case TokenKind::Function
:
6067 return exportDefaultFunctionDeclaration(begin
, pos().begin
);
6069 case TokenKind::Async
: {
6070 TokenKind nextSameLine
= TokenKind::Eof
;
6071 if (!tokenStream
.peekTokenSameLine(&nextSameLine
)) {
6072 return errorResult();
6075 if (nextSameLine
== TokenKind::Function
) {
6076 uint32_t toStringStart
= pos().begin
;
6077 tokenStream
.consumeKnownToken(TokenKind::Function
);
6078 return exportDefaultFunctionDeclaration(
6079 begin
, toStringStart
, FunctionAsyncKind::AsyncFunction
);
6082 anyChars
.ungetToken();
6083 return exportDefaultAssignExpr(begin
);
6086 case TokenKind::Class
:
6087 return exportDefaultClassDeclaration(begin
);
6090 anyChars
.ungetToken();
6091 return exportDefaultAssignExpr(begin
);
6095 template <class ParseHandler
, typename Unit
>
6096 typename
ParseHandler::NodeResult
6097 GeneralParser
<ParseHandler
, Unit
>::exportDeclaration() {
6098 if (!abortIfSyntaxParser()) {
6099 return errorResult();
6102 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Export
));
6104 if (!pc_
->atModuleLevel()) {
6105 error(JSMSG_EXPORT_DECL_AT_TOP_LEVEL
);
6106 return errorResult();
6109 uint32_t begin
= pos().begin
;
6112 if (!tokenStream
.getToken(&tt
)) {
6113 return errorResult();
6116 case TokenKind::Mul
:
6117 return exportBatch(begin
);
6119 case TokenKind::LeftCurly
:
6120 return exportClause(begin
);
6122 case TokenKind::Var
:
6123 return exportVariableStatement(begin
);
6125 case TokenKind::Function
:
6126 return exportFunctionDeclaration(begin
, pos().begin
);
6128 case TokenKind::Async
: {
6129 TokenKind nextSameLine
= TokenKind::Eof
;
6130 if (!tokenStream
.peekTokenSameLine(&nextSameLine
)) {
6131 return errorResult();
6134 if (nextSameLine
== TokenKind::Function
) {
6135 uint32_t toStringStart
= pos().begin
;
6136 tokenStream
.consumeKnownToken(TokenKind::Function
);
6137 return exportFunctionDeclaration(begin
, toStringStart
,
6138 FunctionAsyncKind::AsyncFunction
);
6141 error(JSMSG_DECLARATION_AFTER_EXPORT
);
6142 return errorResult();
6145 case TokenKind::Class
:
6146 return exportClassDeclaration(begin
);
6148 case TokenKind::Const
:
6149 return exportLexicalDeclaration(begin
, DeclarationKind::Const
);
6151 case TokenKind::Let
:
6152 return exportLexicalDeclaration(begin
, DeclarationKind::Let
);
6154 case TokenKind::Default
:
6155 return exportDefault(begin
);
6158 error(JSMSG_DECLARATION_AFTER_EXPORT
);
6159 return errorResult();
6163 template <class ParseHandler
, typename Unit
>
6164 typename
ParseHandler::UnaryNodeResult
6165 GeneralParser
<ParseHandler
, Unit
>::expressionStatement(
6166 YieldHandling yieldHandling
, InvokedPrediction invoked
) {
6167 anyChars
.ungetToken();
6169 MOZ_TRY_VAR(pnexpr
, expr(InAllowed
, yieldHandling
, TripledotProhibited
,
6170 /* possibleError = */ nullptr, invoked
));
6171 if (!matchOrInsertSemicolon()) {
6172 return errorResult();
6174 return handler_
.newExprStatement(pnexpr
, pos().end
);
6177 template <class ParseHandler
, typename Unit
>
6178 typename
ParseHandler::NodeResult
6179 GeneralParser
<ParseHandler
, Unit
>::consequentOrAlternative(
6180 YieldHandling yieldHandling
) {
6182 if (!tokenStream
.peekToken(&next
, TokenStream::SlashIsRegExp
)) {
6183 return errorResult();
6186 // Annex B.3.4 says that unbraced FunctionDeclarations under if/else in
6187 // non-strict code act as if they were braced: |if (x) function f() {}|
6188 // parses as |if (x) { function f() {} }|.
6190 // Careful! FunctionDeclaration doesn't include generators or async
6192 if (next
== TokenKind::Function
) {
6193 tokenStream
.consumeKnownToken(next
, TokenStream::SlashIsRegExp
);
6195 // Parser::statement would handle this, but as this function handles
6196 // every other error case, it seems best to handle this.
6197 if (pc_
->sc()->strict()) {
6198 error(JSMSG_FORBIDDEN_AS_STATEMENT
, "function declarations");
6199 return errorResult();
6202 TokenKind maybeStar
;
6203 if (!tokenStream
.peekToken(&maybeStar
)) {
6204 return errorResult();
6207 if (maybeStar
== TokenKind::Mul
) {
6208 error(JSMSG_FORBIDDEN_AS_STATEMENT
, "generator declarations");
6209 return errorResult();
6212 ParseContext::Statement
stmt(pc_
, StatementKind::Block
);
6213 ParseContext::Scope
scope(this);
6214 if (!scope
.init(pc_
)) {
6215 return errorResult();
6218 TokenPos funcPos
= pos();
6220 MOZ_TRY_VAR(fun
, functionStmt(pos().begin
, yieldHandling
, NameRequired
));
6223 MOZ_TRY_VAR(block
, handler_
.newStatementList(funcPos
));
6225 handler_
.addStatementToList(block
, fun
);
6226 return finishLexicalScope(scope
, block
);
6229 return statement(yieldHandling
);
6232 template <class ParseHandler
, typename Unit
>
6233 typename
ParseHandler::TernaryNodeResult
6234 GeneralParser
<ParseHandler
, Unit
>::ifStatement(YieldHandling yieldHandling
) {
6235 Vector
<Node
, 4> condList(fc_
), thenList(fc_
);
6236 Vector
<uint32_t, 4> posList(fc_
);
6239 ParseContext::Statement
stmt(pc_
, StatementKind::If
);
6242 uint32_t begin
= pos().begin
;
6244 /* An IF node has three kids: condition, then, and optional else. */
6246 MOZ_TRY_VAR(cond
, condition(InAllowed
, yieldHandling
));
6249 if (!tokenStream
.peekToken(&tt
, TokenStream::SlashIsRegExp
)) {
6250 return errorResult();
6254 MOZ_TRY_VAR(thenBranch
, consequentOrAlternative(yieldHandling
));
6256 if (!condList
.append(cond
) || !thenList
.append(thenBranch
) ||
6257 !posList
.append(begin
)) {
6258 return errorResult();
6262 if (!tokenStream
.matchToken(&matched
, TokenKind::Else
,
6263 TokenStream::SlashIsRegExp
)) {
6264 return errorResult();
6267 if (!tokenStream
.matchToken(&matched
, TokenKind::If
,
6268 TokenStream::SlashIsRegExp
)) {
6269 return errorResult();
6274 MOZ_TRY_VAR(elseBranch
, consequentOrAlternative(yieldHandling
));
6276 elseBranch
= null();
6281 TernaryNodeType ifNode
;
6282 for (int i
= condList
.length() - 1; i
>= 0; i
--) {
6283 MOZ_TRY_VAR(ifNode
, handler_
.newIfStatement(posList
[i
], condList
[i
],
6284 thenList
[i
], elseBranch
));
6285 elseBranch
= ifNode
;
6291 template <class ParseHandler
, typename Unit
>
6292 typename
ParseHandler::BinaryNodeResult
6293 GeneralParser
<ParseHandler
, Unit
>::doWhileStatement(
6294 YieldHandling yieldHandling
) {
6295 uint32_t begin
= pos().begin
;
6296 ParseContext::Statement
stmt(pc_
, StatementKind::DoLoop
);
6298 MOZ_TRY_VAR(body
, statement(yieldHandling
));
6299 if (!mustMatchToken(TokenKind::While
, JSMSG_WHILE_AFTER_DO
)) {
6300 return errorResult();
6303 MOZ_TRY_VAR(cond
, condition(InAllowed
, yieldHandling
));
6305 // The semicolon after do-while is even more optional than most
6306 // semicolons in JS. Web compat required this by 2004:
6307 // http://bugzilla.mozilla.org/show_bug.cgi?id=238945
6308 // ES3 and ES5 disagreed, but ES6 conforms to Web reality:
6309 // https://bugs.ecmascript.org/show_bug.cgi?id=157
6310 // To parse |do {} while (true) false| correctly, use SlashIsRegExp.
6312 if (!tokenStream
.matchToken(&ignored
, TokenKind::Semi
,
6313 TokenStream::SlashIsRegExp
)) {
6314 return errorResult();
6316 return handler_
.newDoWhileStatement(body
, cond
, TokenPos(begin
, pos().end
));
6319 template <class ParseHandler
, typename Unit
>
6320 typename
ParseHandler::BinaryNodeResult
6321 GeneralParser
<ParseHandler
, Unit
>::whileStatement(YieldHandling yieldHandling
) {
6322 uint32_t begin
= pos().begin
;
6323 ParseContext::Statement
stmt(pc_
, StatementKind::WhileLoop
);
6325 MOZ_TRY_VAR(cond
, condition(InAllowed
, yieldHandling
));
6327 MOZ_TRY_VAR(body
, statement(yieldHandling
));
6328 return handler_
.newWhileStatement(begin
, cond
, body
);
6331 template <class ParseHandler
, typename Unit
>
6332 bool GeneralParser
<ParseHandler
, Unit
>::matchInOrOf(bool* isForInp
,
6335 if (!tokenStream
.getToken(&tt
, TokenStream::SlashIsRegExp
)) {
6339 *isForInp
= tt
== TokenKind::In
;
6340 *isForOfp
= tt
== TokenKind::Of
;
6341 if (!*isForInp
&& !*isForOfp
) {
6342 anyChars
.ungetToken();
6345 MOZ_ASSERT_IF(*isForInp
|| *isForOfp
, *isForInp
!= *isForOfp
);
6349 template <class ParseHandler
, typename Unit
>
6350 bool GeneralParser
<ParseHandler
, Unit
>::forHeadStart(
6351 YieldHandling yieldHandling
, IteratorKind iterKind
,
6352 ParseNodeKind
* forHeadKind
, Node
* forInitialPart
,
6353 Maybe
<ParseContext::Scope
>& forLoopLexicalScope
,
6354 Node
* forInOrOfExpression
) {
6355 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::LeftParen
));
6358 if (!tokenStream
.peekToken(&tt
, TokenStream::SlashIsRegExp
)) {
6362 // Super-duper easy case: |for (;| is a C-style for-loop with no init
6364 if (tt
== TokenKind::Semi
) {
6365 *forInitialPart
= null();
6366 *forHeadKind
= ParseNodeKind::ForHead
;
6370 // Parsing after |for (var| is also relatively simple (from this method's
6371 // point of view). No block-related work complicates matters, so delegate
6372 // to Parser::declaration.
6373 if (tt
== TokenKind::Var
) {
6374 tokenStream
.consumeKnownToken(tt
, TokenStream::SlashIsRegExp
);
6376 // Pass null for block object because |var| declarations don't use one.
6377 MOZ_TRY_VAR_OR_RETURN(*forInitialPart
,
6378 declarationList(yieldHandling
, ParseNodeKind::VarStmt
,
6379 forHeadKind
, forInOrOfExpression
),
6384 // Otherwise we have a lexical declaration or an expression.
6386 // For-in loop backwards compatibility requires that |let| starting a
6387 // for-loop that's not a (new to ES6) for-of loop, in non-strict mode code,
6388 // parse as an identifier. (|let| in for-of is always a declaration.)
6390 // For-of loops can't start with the token sequence "async of", because that
6391 // leads to a shift-reduce conflict when parsing |for (async of => {};;)| or
6392 // |for (async of [])|.
6393 bool parsingLexicalDeclaration
= false;
6394 bool letIsIdentifier
= false;
6395 bool startsWithForOf
= false;
6396 if (tt
== TokenKind::Const
) {
6397 parsingLexicalDeclaration
= true;
6398 tokenStream
.consumeKnownToken(tt
, TokenStream::SlashIsRegExp
);
6399 } else if (tt
== TokenKind::Let
) {
6400 // We could have a {For,Lexical}Declaration, or we could have a
6401 // LeftHandSideExpression with lookahead restrictions so it's not
6402 // ambiguous with the former. Check for a continuation of the former
6403 // to decide which we have.
6404 tokenStream
.consumeKnownToken(TokenKind::Let
, TokenStream::SlashIsRegExp
);
6407 if (!tokenStream
.peekToken(&next
)) {
6411 parsingLexicalDeclaration
= nextTokenContinuesLetDeclaration(next
);
6412 if (!parsingLexicalDeclaration
) {
6413 anyChars
.ungetToken();
6414 letIsIdentifier
= true;
6416 } else if (tt
== TokenKind::Async
&& iterKind
== IteratorKind::Sync
) {
6417 tokenStream
.consumeKnownToken(TokenKind::Async
, TokenStream::SlashIsRegExp
);
6420 if (!tokenStream
.peekToken(&next
)) {
6424 if (next
== TokenKind::Of
) {
6425 startsWithForOf
= true;
6427 anyChars
.ungetToken();
6430 if (parsingLexicalDeclaration
) {
6431 if (options().selfHostingMode
) {
6432 error(JSMSG_SELFHOSTED_LEXICAL
);
6436 forLoopLexicalScope
.emplace(this);
6437 if (!forLoopLexicalScope
->init(pc_
)) {
6441 // Push a temporary ForLoopLexicalHead Statement that allows for
6442 // lexical declarations, as they are usually allowed only in braced
6444 ParseContext::Statement
forHeadStmt(pc_
, StatementKind::ForLoopLexicalHead
);
6446 MOZ_TRY_VAR_OR_RETURN(
6448 declarationList(yieldHandling
,
6449 tt
== TokenKind::Const
? ParseNodeKind::ConstDecl
6450 : ParseNodeKind::LetDecl
,
6451 forHeadKind
, forInOrOfExpression
),
6456 uint32_t exprOffset
;
6457 if (!tokenStream
.peekOffset(&exprOffset
, TokenStream::SlashIsRegExp
)) {
6461 // Finally, handle for-loops that start with expressions. Pass
6462 // |InProhibited| so that |in| isn't parsed in a RelationalExpression as a
6463 // binary operator. |in| makes it a for-in loop, *not* an |in| expression.
6464 PossibleError
possibleError(*this);
6465 MOZ_TRY_VAR_OR_RETURN(
6467 expr(InProhibited
, yieldHandling
, TripledotProhibited
, &possibleError
),
6470 bool isForIn
, isForOf
;
6471 if (!matchInOrOf(&isForIn
, &isForOf
)) {
6475 // If we don't encounter 'in'/'of', we have a for(;;) loop. We've handled
6476 // the init expression; the caller handles the rest.
6477 if (!isForIn
&& !isForOf
) {
6478 if (!possibleError
.checkForExpressionError()) {
6482 *forHeadKind
= ParseNodeKind::ForHead
;
6486 MOZ_ASSERT(isForIn
!= isForOf
);
6488 // In a for-of loop, 'let' that starts the loop head is a |let| keyword,
6489 // per the [lookahead ≠let] restriction on the LeftHandSideExpression
6490 // variant of such loops. Expressions that start with |let| can't be used
6494 // for (let.prop of [1]) // BAD
6498 if (isForOf
&& letIsIdentifier
) {
6499 errorAt(exprOffset
, JSMSG_BAD_STARTING_FOROF_LHS
, "let");
6503 // In a for-of loop, the LeftHandSideExpression isn't allowed to be an
6504 // identifier named "async" per the [lookahead ≠async of] restriction.
6505 if (isForOf
&& startsWithForOf
) {
6506 errorAt(exprOffset
, JSMSG_BAD_STARTING_FOROF_LHS
, "async of");
6510 *forHeadKind
= isForIn
? ParseNodeKind::ForIn
: ParseNodeKind::ForOf
;
6512 // Verify the left-hand side expression doesn't have a forbidden form.
6513 if (handler_
.isUnparenthesizedDestructuringPattern(*forInitialPart
)) {
6514 if (!possibleError
.checkForDestructuringErrorOrWarning()) {
6517 } else if (handler_
.isName(*forInitialPart
)) {
6518 if (const char* chars
= nameIsArgumentsOrEval(*forInitialPart
)) {
6519 // |chars| is "arguments" or "eval" here.
6520 if (!strictModeErrorAt(exprOffset
, JSMSG_BAD_STRICT_ASSIGN
, chars
)) {
6524 } else if (handler_
.isPropertyOrPrivateMemberAccess(*forInitialPart
)) {
6525 // Permitted: no additional testing/fixup needed.
6526 } else if (handler_
.isFunctionCall(*forInitialPart
)) {
6527 if (!strictModeErrorAt(exprOffset
, JSMSG_BAD_FOR_LEFTSIDE
)) {
6531 errorAt(exprOffset
, JSMSG_BAD_FOR_LEFTSIDE
);
6535 if (!possibleError
.checkForExpressionError()) {
6539 // Finally, parse the iterated expression, making the for-loop's closing
6540 // ')' the next token.
6541 MOZ_TRY_VAR_OR_RETURN(*forInOrOfExpression
,
6542 expressionAfterForInOrOf(*forHeadKind
, yieldHandling
),
6547 template <class ParseHandler
, typename Unit
>
6548 typename
ParseHandler::NodeResult
6549 GeneralParser
<ParseHandler
, Unit
>::forStatement(YieldHandling yieldHandling
) {
6550 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::For
));
6552 uint32_t begin
= pos().begin
;
6554 ParseContext::Statement
stmt(pc_
, StatementKind::ForLoop
);
6556 IteratorKind iterKind
= IteratorKind::Sync
;
6557 unsigned iflags
= 0;
6559 if (pc_
->isAsync() || pc_
->sc()->isModuleContext()) {
6561 if (!tokenStream
.matchToken(&matched
, TokenKind::Await
)) {
6562 return errorResult();
6565 // If we come across a top level await here, mark the module as async.
6566 if (matched
&& pc_
->sc()->isModuleContext() && !pc_
->isAsync()) {
6567 if (!options().topLevelAwait
) {
6568 error(JSMSG_TOP_LEVEL_AWAIT_NOT_SUPPORTED
);
6569 return errorResult();
6571 pc_
->sc()->asModuleContext()->setIsAsync();
6572 MOZ_ASSERT(pc_
->isAsync());
6576 iflags
|= JSITER_FORAWAITOF
;
6577 iterKind
= IteratorKind::Async
;
6581 if (!mustMatchToken(TokenKind::LeftParen
, [this](TokenKind actual
) {
6582 this->error((actual
== TokenKind::Await
&& !this->pc_
->isAsync())
6583 ? JSMSG_FOR_AWAIT_OUTSIDE_ASYNC
6584 : JSMSG_PAREN_AFTER_FOR
);
6586 return errorResult();
6589 // ParseNodeKind::ForHead, ParseNodeKind::ForIn, or
6590 // ParseNodeKind::ForOf depending on the loop type.
6591 ParseNodeKind headKind
;
6593 // |x| in either |for (x; ...; ...)| or |for (x in/of ...)|.
6596 // The next two variables are used to implement `for (let/const ...)`.
6598 // We generate an implicit block, wrapping the whole loop, to store loop
6599 // variables declared this way. Note that if the loop uses `for (var...)`
6600 // instead, those variables go on some existing enclosing scope, so no
6601 // implicit block scope is created.
6603 // Both variables remain null/none if the loop is any other form.
6605 // The static block scope for the implicit block scope.
6606 Maybe
<ParseContext::Scope
> forLoopLexicalScope
;
6608 // The expression being iterated over, for for-in/of loops only. Unused
6609 // for for(;;) loops.
6612 // Parse the entirety of the loop-head for a for-in/of loop (so the next
6613 // token is the closing ')'):
6615 // for (... in/of ...) ...
6618 // ...OR, parse up to the first ';' in a C-style for-loop:
6620 // for (...; ...; ...) ...
6623 // In either case the subsequent token can be consistently accessed using
6624 // TokenStream::SlashIsDiv semantics.
6625 if (!forHeadStart(yieldHandling
, iterKind
, &headKind
, &startNode
,
6626 forLoopLexicalScope
, &iteratedExpr
)) {
6627 return errorResult();
6630 MOZ_ASSERT(headKind
== ParseNodeKind::ForIn
||
6631 headKind
== ParseNodeKind::ForOf
||
6632 headKind
== ParseNodeKind::ForHead
);
6634 if (iterKind
== IteratorKind::Async
&& headKind
!= ParseNodeKind::ForOf
) {
6635 errorAt(begin
, JSMSG_FOR_AWAIT_NOT_OF
);
6636 return errorResult();
6639 TernaryNodeType forHead
;
6640 if (headKind
== ParseNodeKind::ForHead
) {
6641 Node init
= startNode
;
6643 // Look for an operand: |for (;| means we might have already examined
6644 // this semicolon with that modifier.
6645 if (!mustMatchToken(TokenKind::Semi
, JSMSG_SEMI_AFTER_FOR_INIT
)) {
6646 return errorResult();
6650 if (!tokenStream
.peekToken(&tt
, TokenStream::SlashIsRegExp
)) {
6651 return errorResult();
6655 if (tt
== TokenKind::Semi
) {
6658 MOZ_TRY_VAR(test
, expr(InAllowed
, yieldHandling
, TripledotProhibited
));
6661 if (!mustMatchToken(TokenKind::Semi
, JSMSG_SEMI_AFTER_FOR_COND
)) {
6662 return errorResult();
6665 if (!tokenStream
.peekToken(&tt
, TokenStream::SlashIsRegExp
)) {
6666 return errorResult();
6670 if (tt
== TokenKind::RightParen
) {
6673 MOZ_TRY_VAR(update
, expr(InAllowed
, yieldHandling
, TripledotProhibited
));
6676 if (!mustMatchToken(TokenKind::RightParen
, JSMSG_PAREN_AFTER_FOR_CTRL
)) {
6677 return errorResult();
6680 TokenPos
headPos(begin
, pos().end
);
6681 MOZ_TRY_VAR(forHead
, handler_
.newForHead(init
, test
, update
, headPos
));
6683 MOZ_ASSERT(headKind
== ParseNodeKind::ForIn
||
6684 headKind
== ParseNodeKind::ForOf
);
6686 // |target| is the LeftHandSideExpression or declaration to which the
6687 // per-iteration value (an arbitrary value exposed by the iteration
6688 // protocol, or a string naming a property) is assigned.
6689 Node target
= startNode
;
6691 // Parse the rest of the for-in/of head.
6692 if (headKind
== ParseNodeKind::ForIn
) {
6693 stmt
.refineForKind(StatementKind::ForInLoop
);
6695 stmt
.refineForKind(StatementKind::ForOfLoop
);
6698 // Parser::declaration consumed everything up to the closing ')'. That
6699 // token follows an {Assignment,}Expression and so must be interpreted
6700 // as an operand to be consistent with normal expression tokenizing.
6701 if (!mustMatchToken(TokenKind::RightParen
, JSMSG_PAREN_AFTER_FOR_CTRL
)) {
6702 return errorResult();
6705 TokenPos
headPos(begin
, pos().end
);
6706 MOZ_TRY_VAR(forHead
, handler_
.newForInOrOfHead(headKind
, target
,
6707 iteratedExpr
, headPos
));
6711 MOZ_TRY_VAR(body
, statement(yieldHandling
));
6713 ForNodeType forLoop
;
6714 MOZ_TRY_VAR(forLoop
, handler_
.newForStatement(begin
, forHead
, body
, iflags
));
6716 if (forLoopLexicalScope
) {
6717 return finishLexicalScope(*forLoopLexicalScope
, forLoop
);
6723 template <class ParseHandler
, typename Unit
>
6724 typename
ParseHandler::SwitchStatementResult
6725 GeneralParser
<ParseHandler
, Unit
>::switchStatement(
6726 YieldHandling yieldHandling
) {
6727 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Switch
));
6728 uint32_t begin
= pos().begin
;
6730 if (!mustMatchToken(TokenKind::LeftParen
, JSMSG_PAREN_BEFORE_SWITCH
)) {
6731 return errorResult();
6735 MOZ_TRY_VAR(discriminant
,
6736 exprInParens(InAllowed
, yieldHandling
, TripledotProhibited
));
6738 if (!mustMatchToken(TokenKind::RightParen
, JSMSG_PAREN_AFTER_SWITCH
)) {
6739 return errorResult();
6741 if (!mustMatchToken(TokenKind::LeftCurly
, JSMSG_CURLY_BEFORE_SWITCH
)) {
6742 return errorResult();
6745 ParseContext::Statement
stmt(pc_
, StatementKind::Switch
);
6746 ParseContext::Scope
scope(this);
6747 if (!scope
.init(pc_
)) {
6748 return errorResult();
6751 ListNodeType caseList
;
6752 MOZ_TRY_VAR(caseList
, handler_
.newStatementList(pos()));
6754 bool seenDefault
= false;
6757 if (!tokenStream
.getToken(&tt
, TokenStream::SlashIsRegExp
)) {
6758 return errorResult();
6760 if (tt
== TokenKind::RightCurly
) {
6763 uint32_t caseBegin
= pos().begin
;
6767 case TokenKind::Default
:
6769 error(JSMSG_TOO_MANY_DEFAULTS
);
6770 return errorResult();
6773 caseExpr
= null(); // The default case has pn_left == nullptr.
6776 case TokenKind::Case
:
6777 MOZ_TRY_VAR(caseExpr
,
6778 expr(InAllowed
, yieldHandling
, TripledotProhibited
));
6782 error(JSMSG_BAD_SWITCH
);
6783 return errorResult();
6786 if (!mustMatchToken(TokenKind::Colon
, JSMSG_COLON_AFTER_CASE
)) {
6787 return errorResult();
6791 MOZ_TRY_VAR(body
, handler_
.newStatementList(pos()));
6793 bool afterReturn
= false;
6794 bool warnedAboutStatementsAfterReturn
= false;
6795 uint32_t statementBegin
= 0;
6797 if (!tokenStream
.peekToken(&tt
, TokenStream::SlashIsRegExp
)) {
6798 return errorResult();
6800 if (tt
== TokenKind::RightCurly
|| tt
== TokenKind::Case
||
6801 tt
== TokenKind::Default
) {
6805 if (!tokenStream
.peekOffset(&statementBegin
,
6806 TokenStream::SlashIsRegExp
)) {
6807 return errorResult();
6811 MOZ_TRY_VAR(stmt
, statementListItem(yieldHandling
));
6812 if (!warnedAboutStatementsAfterReturn
) {
6814 if (!handler_
.isStatementPermittedAfterReturnStatement(stmt
)) {
6815 if (!warningAt(statementBegin
, JSMSG_STMT_AFTER_RETURN
)) {
6816 return errorResult();
6819 warnedAboutStatementsAfterReturn
= true;
6821 } else if (handler_
.isReturnStatement(stmt
)) {
6825 handler_
.addStatementToList(body
, stmt
);
6828 CaseClauseType caseClause
;
6829 MOZ_TRY_VAR(caseClause
,
6830 handler_
.newCaseOrDefault(caseBegin
, caseExpr
, body
));
6831 handler_
.addCaseStatementToList(caseList
, caseClause
);
6834 LexicalScopeNodeType lexicalForCaseList
;
6835 MOZ_TRY_VAR(lexicalForCaseList
, finishLexicalScope(scope
, caseList
));
6837 handler_
.setEndPosition(lexicalForCaseList
, pos().end
);
6839 return handler_
.newSwitchStatement(begin
, discriminant
, lexicalForCaseList
,
6843 template <class ParseHandler
, typename Unit
>
6844 typename
ParseHandler::ContinueStatementResult
6845 GeneralParser
<ParseHandler
, Unit
>::continueStatement(
6846 YieldHandling yieldHandling
) {
6847 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Continue
));
6848 uint32_t begin
= pos().begin
;
6850 TaggedParserAtomIndex label
;
6851 if (!matchLabel(yieldHandling
, &label
)) {
6852 return errorResult();
6855 auto validity
= pc_
->checkContinueStatement(label
);
6856 if (validity
.isErr()) {
6857 switch (validity
.unwrapErr()) {
6858 case ParseContext::ContinueStatementError::NotInALoop
:
6859 errorAt(begin
, JSMSG_BAD_CONTINUE
);
6861 case ParseContext::ContinueStatementError::LabelNotFound
:
6862 error(JSMSG_LABEL_NOT_FOUND
);
6865 return errorResult();
6868 if (!matchOrInsertSemicolon()) {
6869 return errorResult();
6872 return handler_
.newContinueStatement(label
, TokenPos(begin
, pos().end
));
6875 template <class ParseHandler
, typename Unit
>
6876 typename
ParseHandler::BreakStatementResult
6877 GeneralParser
<ParseHandler
, Unit
>::breakStatement(YieldHandling yieldHandling
) {
6878 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Break
));
6879 uint32_t begin
= pos().begin
;
6881 TaggedParserAtomIndex label
;
6882 if (!matchLabel(yieldHandling
, &label
)) {
6883 return errorResult();
6886 auto validity
= pc_
->checkBreakStatement(label
);
6887 if (validity
.isErr()) {
6888 switch (validity
.unwrapErr()) {
6889 case ParseContext::BreakStatementError::ToughBreak
:
6890 errorAt(begin
, JSMSG_TOUGH_BREAK
);
6891 return errorResult();
6892 case ParseContext::BreakStatementError::LabelNotFound
:
6893 error(JSMSG_LABEL_NOT_FOUND
);
6894 return errorResult();
6898 if (!matchOrInsertSemicolon()) {
6899 return errorResult();
6902 return handler_
.newBreakStatement(label
, TokenPos(begin
, pos().end
));
6905 template <class ParseHandler
, typename Unit
>
6906 typename
ParseHandler::UnaryNodeResult
6907 GeneralParser
<ParseHandler
, Unit
>::returnStatement(
6908 YieldHandling yieldHandling
) {
6909 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Return
));
6910 uint32_t begin
= pos().begin
;
6912 MOZ_ASSERT(pc_
->isFunctionBox());
6914 // Parse an optional operand.
6916 // This is ugly, but we don't want to require a semicolon.
6918 TokenKind tt
= TokenKind::Eof
;
6919 if (!tokenStream
.peekTokenSameLine(&tt
, TokenStream::SlashIsRegExp
)) {
6920 return errorResult();
6923 case TokenKind::Eol
:
6924 case TokenKind::Eof
:
6925 case TokenKind::Semi
:
6926 case TokenKind::RightCurly
:
6930 MOZ_TRY_VAR(exprNode
,
6931 expr(InAllowed
, yieldHandling
, TripledotProhibited
));
6935 if (!matchOrInsertSemicolon()) {
6936 return errorResult();
6939 return handler_
.newReturnStatement(exprNode
, TokenPos(begin
, pos().end
));
6942 template <class ParseHandler
, typename Unit
>
6943 typename
ParseHandler::UnaryNodeResult
6944 GeneralParser
<ParseHandler
, Unit
>::yieldExpression(InHandling inHandling
) {
6945 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Yield
));
6946 uint32_t begin
= pos().begin
;
6948 MOZ_ASSERT(pc_
->isGenerator());
6949 MOZ_ASSERT(pc_
->isFunctionBox());
6951 pc_
->lastYieldOffset
= begin
;
6954 ParseNodeKind kind
= ParseNodeKind::YieldExpr
;
6955 TokenKind tt
= TokenKind::Eof
;
6956 if (!tokenStream
.peekTokenSameLine(&tt
, TokenStream::SlashIsRegExp
)) {
6957 return errorResult();
6960 // TokenKind::Eol is special; it implements the [no LineTerminator here]
6961 // quirk in the grammar.
6962 case TokenKind::Eol
:
6963 // The rest of these make up the complete set of tokens that can
6964 // appear after any of the places where AssignmentExpression is used
6965 // throughout the grammar. Conveniently, none of them can also be the
6966 // start an expression.
6967 case TokenKind::Eof
:
6968 case TokenKind::Semi
:
6969 case TokenKind::RightCurly
:
6970 case TokenKind::RightBracket
:
6971 case TokenKind::RightParen
:
6972 case TokenKind::Colon
:
6973 case TokenKind::Comma
:
6974 case TokenKind::In
: // Annex B.3.6 `for (x = yield in y) ;`
6978 case TokenKind::Mul
:
6979 kind
= ParseNodeKind::YieldStarExpr
;
6980 tokenStream
.consumeKnownToken(TokenKind::Mul
, TokenStream::SlashIsRegExp
);
6983 MOZ_TRY_VAR(exprNode
,
6984 assignExpr(inHandling
, YieldIsKeyword
, TripledotProhibited
));
6986 if (kind
== ParseNodeKind::YieldStarExpr
) {
6987 return handler_
.newYieldStarExpression(begin
, exprNode
);
6989 return handler_
.newYieldExpression(begin
, exprNode
);
6992 template <class ParseHandler
, typename Unit
>
6993 typename
ParseHandler::BinaryNodeResult
6994 GeneralParser
<ParseHandler
, Unit
>::withStatement(YieldHandling yieldHandling
) {
6995 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::With
));
6996 uint32_t begin
= pos().begin
;
6998 if (pc_
->sc()->strict()) {
6999 if (!strictModeError(JSMSG_STRICT_CODE_WITH
)) {
7000 return errorResult();
7004 if (!mustMatchToken(TokenKind::LeftParen
, JSMSG_PAREN_BEFORE_WITH
)) {
7005 return errorResult();
7009 MOZ_TRY_VAR(objectExpr
,
7010 exprInParens(InAllowed
, yieldHandling
, TripledotProhibited
));
7012 if (!mustMatchToken(TokenKind::RightParen
, JSMSG_PAREN_AFTER_WITH
)) {
7013 return errorResult();
7018 ParseContext::Statement
stmt(pc_
, StatementKind::With
);
7019 MOZ_TRY_VAR(innerBlock
, statement(yieldHandling
));
7022 pc_
->sc()->setBindingsAccessedDynamically();
7024 return handler_
.newWithStatement(begin
, objectExpr
, innerBlock
);
7027 template <class ParseHandler
, typename Unit
>
7028 typename
ParseHandler::NodeResult
7029 GeneralParser
<ParseHandler
, Unit
>::labeledItem(YieldHandling yieldHandling
) {
7031 if (!tokenStream
.getToken(&tt
, TokenStream::SlashIsRegExp
)) {
7032 return errorResult();
7035 if (tt
== TokenKind::Function
) {
7037 if (!tokenStream
.peekToken(&next
)) {
7038 return errorResult();
7041 // GeneratorDeclaration is only matched by HoistableDeclaration in
7042 // StatementListItem, so generators can't be inside labels.
7043 if (next
== TokenKind::Mul
) {
7044 error(JSMSG_GENERATOR_LABEL
);
7045 return errorResult();
7048 // Per 13.13.1 it's a syntax error if LabelledItem: FunctionDeclaration
7049 // is ever matched. Per Annex B.3.2 that modifies this text, this
7050 // applies only to strict mode code.
7051 if (pc_
->sc()->strict()) {
7052 error(JSMSG_FUNCTION_LABEL
);
7053 return errorResult();
7056 return functionStmt(pos().begin
, yieldHandling
, NameRequired
);
7059 anyChars
.ungetToken();
7060 return statement(yieldHandling
);
7063 template <class ParseHandler
, typename Unit
>
7064 typename
ParseHandler::LabeledStatementResult
7065 GeneralParser
<ParseHandler
, Unit
>::labeledStatement(
7066 YieldHandling yieldHandling
) {
7067 TaggedParserAtomIndex label
= labelIdentifier(yieldHandling
);
7069 return errorResult();
7072 auto hasSameLabel
= [&label
](ParseContext::LabelStatement
* stmt
) {
7073 return stmt
->label() == label
;
7076 uint32_t begin
= pos().begin
;
7078 if (pc_
->template findInnermostStatement
<ParseContext::LabelStatement
>(
7080 errorAt(begin
, JSMSG_DUPLICATE_LABEL
);
7081 return errorResult();
7084 tokenStream
.consumeKnownToken(TokenKind::Colon
);
7086 /* Push a label struct and parse the statement. */
7087 ParseContext::LabelStatement
stmt(pc_
, label
);
7089 MOZ_TRY_VAR(pn
, labeledItem(yieldHandling
));
7091 return handler_
.newLabeledStatement(label
, pn
, begin
);
7094 template <class ParseHandler
, typename Unit
>
7095 typename
ParseHandler::UnaryNodeResult
7096 GeneralParser
<ParseHandler
, Unit
>::throwStatement(YieldHandling yieldHandling
) {
7097 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Throw
));
7098 uint32_t begin
= pos().begin
;
7100 /* ECMA-262 Edition 3 says 'throw [no LineTerminator here] Expr'. */
7101 TokenKind tt
= TokenKind::Eof
;
7102 if (!tokenStream
.peekTokenSameLine(&tt
, TokenStream::SlashIsRegExp
)) {
7103 return errorResult();
7105 if (tt
== TokenKind::Eof
|| tt
== TokenKind::Semi
||
7106 tt
== TokenKind::RightCurly
) {
7107 error(JSMSG_MISSING_EXPR_AFTER_THROW
);
7108 return errorResult();
7110 if (tt
== TokenKind::Eol
) {
7111 error(JSMSG_LINE_BREAK_AFTER_THROW
);
7112 return errorResult();
7116 MOZ_TRY_VAR(throwExpr
, expr(InAllowed
, yieldHandling
, TripledotProhibited
));
7118 if (!matchOrInsertSemicolon()) {
7119 return errorResult();
7122 return handler_
.newThrowStatement(throwExpr
, TokenPos(begin
, pos().end
));
7125 template <class ParseHandler
, typename Unit
>
7126 typename
ParseHandler::TernaryNodeResult
7127 GeneralParser
<ParseHandler
, Unit
>::tryStatement(YieldHandling yieldHandling
) {
7128 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Try
));
7129 uint32_t begin
= pos().begin
;
7132 * try nodes are ternary.
7133 * kid1 is the try statement
7134 * kid2 is the catch node list or null
7135 * kid3 is the finally statement
7137 * catch nodes are binary.
7138 * left is the catch-name/pattern or null
7139 * right is the catch block
7141 * catch lvalue nodes are either:
7142 * a single identifier
7143 * TokenKind::RightBracket for a destructuring left-hand side
7144 * TokenKind::RightCurly for a destructuring left-hand side
7146 * finally nodes are TokenKind::LeftCurly statement lists.
7151 if (!mustMatchToken(TokenKind::LeftCurly
, JSMSG_CURLY_BEFORE_TRY
)) {
7152 return errorResult();
7155 uint32_t openedPos
= pos().begin
;
7157 ParseContext::Statement
stmt(pc_
, StatementKind::Try
);
7158 ParseContext::Scope
scope(this);
7159 if (!scope
.init(pc_
)) {
7160 return errorResult();
7163 MOZ_TRY_VAR(innerBlock
, statementList(yieldHandling
));
7165 MOZ_TRY_VAR(innerBlock
, finishLexicalScope(scope
, innerBlock
));
7167 if (!mustMatchToken(
7168 TokenKind::RightCurly
, [this, openedPos
](TokenKind actual
) {
7169 this->reportMissingClosing(JSMSG_CURLY_AFTER_TRY
,
7170 JSMSG_CURLY_OPENED
, openedPos
);
7172 return errorResult();
7176 LexicalScopeNodeType catchScope
= null();
7178 if (!tokenStream
.getToken(&tt
)) {
7179 return errorResult();
7181 if (tt
== TokenKind::Catch
) {
7183 * Create a lexical scope node around the whole catch clause,
7184 * including the head.
7186 ParseContext::Statement
stmt(pc_
, StatementKind::Catch
);
7187 ParseContext::Scope
scope(this);
7188 if (!scope
.init(pc_
)) {
7189 return errorResult();
7193 * Legal catch forms are:
7196 * where lhs is a name or a destructuring left-hand side.
7198 bool omittedBinding
;
7199 if (!tokenStream
.matchToken(&omittedBinding
, TokenKind::LeftCurly
)) {
7200 return errorResult();
7204 if (omittedBinding
) {
7207 if (!mustMatchToken(TokenKind::LeftParen
, JSMSG_PAREN_BEFORE_CATCH
)) {
7208 return errorResult();
7211 if (!tokenStream
.getToken(&tt
)) {
7212 return errorResult();
7215 case TokenKind::LeftBracket
:
7216 case TokenKind::LeftCurly
:
7217 MOZ_TRY_VAR(catchName
,
7218 destructuringDeclaration(DeclarationKind::CatchParameter
,
7219 yieldHandling
, tt
));
7223 if (!TokenKindIsPossibleIdentifierName(tt
)) {
7224 error(JSMSG_CATCH_IDENTIFIER
);
7225 return errorResult();
7228 MOZ_TRY_VAR(catchName
,
7229 bindingIdentifier(DeclarationKind::SimpleCatchParameter
,
7235 if (!mustMatchToken(TokenKind::RightParen
, JSMSG_PAREN_AFTER_CATCH
)) {
7236 return errorResult();
7239 if (!mustMatchToken(TokenKind::LeftCurly
, JSMSG_CURLY_BEFORE_CATCH
)) {
7240 return errorResult();
7244 LexicalScopeNodeType catchBody
;
7245 MOZ_TRY_VAR(catchBody
, catchBlockStatement(yieldHandling
, scope
));
7247 MOZ_TRY_VAR(catchScope
, finishLexicalScope(scope
, catchBody
));
7249 if (!handler_
.setupCatchScope(catchScope
, catchName
, catchBody
)) {
7250 return errorResult();
7252 handler_
.setEndPosition(catchScope
, pos().end
);
7254 if (!tokenStream
.getToken(&tt
, TokenStream::SlashIsRegExp
)) {
7255 return errorResult();
7259 Node finallyBlock
= null();
7261 if (tt
== TokenKind::Finally
) {
7262 if (!mustMatchToken(TokenKind::LeftCurly
, JSMSG_CURLY_BEFORE_FINALLY
)) {
7263 return errorResult();
7266 uint32_t openedPos
= pos().begin
;
7268 ParseContext::Statement
stmt(pc_
, StatementKind::Finally
);
7269 ParseContext::Scope
scope(this);
7270 if (!scope
.init(pc_
)) {
7271 return errorResult();
7274 MOZ_TRY_VAR(finallyBlock
, statementList(yieldHandling
));
7276 MOZ_TRY_VAR(finallyBlock
, finishLexicalScope(scope
, finallyBlock
));
7278 if (!mustMatchToken(
7279 TokenKind::RightCurly
, [this, openedPos
](TokenKind actual
) {
7280 this->reportMissingClosing(JSMSG_CURLY_AFTER_FINALLY
,
7281 JSMSG_CURLY_OPENED
, openedPos
);
7283 return errorResult();
7286 anyChars
.ungetToken();
7288 if (!catchScope
&& !finallyBlock
) {
7289 error(JSMSG_CATCH_OR_FINALLY
);
7290 return errorResult();
7293 return handler_
.newTryStatement(begin
, innerBlock
, catchScope
, finallyBlock
);
7296 template <class ParseHandler
, typename Unit
>
7297 typename
ParseHandler::LexicalScopeNodeResult
7298 GeneralParser
<ParseHandler
, Unit
>::catchBlockStatement(
7299 YieldHandling yieldHandling
, ParseContext::Scope
& catchParamScope
) {
7300 uint32_t openedPos
= pos().begin
;
7302 ParseContext::Statement
stmt(pc_
, StatementKind::Block
);
7304 // ES 13.15.7 CatchClauseEvaluation
7306 // Step 8 means that the body of a catch block always has an additional
7308 ParseContext::Scope
scope(this);
7309 if (!scope
.init(pc_
)) {
7310 return errorResult();
7313 // The catch parameter names cannot be redeclared inside the catch
7314 // block, so declare the name in the inner scope.
7315 if (!scope
.addCatchParameters(pc_
, catchParamScope
)) {
7316 return errorResult();
7320 MOZ_TRY_VAR(list
, statementList(yieldHandling
));
7322 if (!mustMatchToken(
7323 TokenKind::RightCurly
, [this, openedPos
](TokenKind actual
) {
7324 this->reportMissingClosing(JSMSG_CURLY_AFTER_CATCH
,
7325 JSMSG_CURLY_OPENED
, openedPos
);
7327 return errorResult();
7330 // The catch parameter names are not bound in the body scope, so remove
7331 // them before generating bindings.
7332 scope
.removeCatchParameters(pc_
, catchParamScope
);
7333 return finishLexicalScope(scope
, list
);
7336 template <class ParseHandler
, typename Unit
>
7337 typename
ParseHandler::DebuggerStatementResult
7338 GeneralParser
<ParseHandler
, Unit
>::debuggerStatement() {
7340 p
.begin
= pos().begin
;
7341 if (!matchOrInsertSemicolon()) {
7342 return errorResult();
7346 return handler_
.newDebuggerStatement(p
);
7349 static AccessorType
ToAccessorType(PropertyType propType
) {
7351 case PropertyType::Getter
:
7352 return AccessorType::Getter
;
7353 case PropertyType::Setter
:
7354 return AccessorType::Setter
;
7355 case PropertyType::Normal
:
7356 case PropertyType::Method
:
7357 case PropertyType::GeneratorMethod
:
7358 case PropertyType::AsyncMethod
:
7359 case PropertyType::AsyncGeneratorMethod
:
7360 case PropertyType::Constructor
:
7361 case PropertyType::DerivedConstructor
:
7362 return AccessorType::None
;
7364 MOZ_CRASH("unexpected property type");
7368 #ifdef ENABLE_DECORATORS
7369 template <class ParseHandler
, typename Unit
>
7370 typename
ParseHandler::ListNodeResult
7371 GeneralParser
<ParseHandler
, Unit
>::decoratorList(YieldHandling yieldHandling
) {
7372 ListNodeType decorators
;
7373 MOZ_TRY_VAR(decorators
,
7374 handler_
.newList(ParseNodeKind::DecoratorList
, pos()));
7376 // Build a decorator list element. At each entry point to this loop we have
7377 // already consumed the |@| token
7380 if (!tokenStream
.getToken(&tt
, TokenStream::SlashIsInvalid
)) {
7381 return errorResult();
7385 MOZ_TRY_VAR(decorator
, decoratorExpr(yieldHandling
, tt
));
7387 handler_
.addList(decorators
, decorator
);
7389 if (!tokenStream
.getToken(&tt
)) {
7390 return errorResult();
7392 if (tt
!= TokenKind::At
) {
7393 anyChars
.ungetToken();
7401 template <class ParseHandler
, typename Unit
>
7402 bool GeneralParser
<ParseHandler
, Unit
>::classMember(
7403 YieldHandling yieldHandling
, const ParseContext::ClassStatement
& classStmt
,
7404 TaggedParserAtomIndex className
, uint32_t classStartOffset
,
7405 HasHeritage hasHeritage
, ClassInitializedMembers
& classInitializedMembers
,
7406 ListNodeType
& classMembers
, bool* done
) {
7410 if (!tokenStream
.getToken(&tt
, TokenStream::SlashIsInvalid
)) {
7413 if (tt
== TokenKind::RightCurly
) {
7418 if (tt
== TokenKind::Semi
) {
7422 #ifdef ENABLE_DECORATORS
7423 ListNodeType decorators
= null();
7424 if (tt
== TokenKind::At
) {
7425 MOZ_TRY_VAR_OR_RETURN(decorators
, decoratorList(yieldHandling
), false);
7427 if (!tokenStream
.getToken(&tt
, TokenStream::SlashIsInvalid
)) {
7433 bool isStatic
= false;
7434 if (tt
== TokenKind::Static
) {
7435 if (!tokenStream
.peekToken(&tt
)) {
7439 if (tt
== TokenKind::LeftCurly
) {
7440 /* Parsing static class block: static { ... } */
7441 FunctionNodeType staticBlockBody
;
7442 MOZ_TRY_VAR_OR_RETURN(staticBlockBody
,
7443 staticClassBlock(classInitializedMembers
), false);
7445 StaticClassBlockType classBlock
;
7446 MOZ_TRY_VAR_OR_RETURN(
7447 classBlock
, handler_
.newStaticClassBlock(staticBlockBody
), false);
7449 return handler_
.addClassMemberDefinition(classMembers
, classBlock
);
7452 if (tt
!= TokenKind::LeftParen
&& tt
!= TokenKind::Assign
&&
7453 tt
!= TokenKind::Semi
&& tt
!= TokenKind::RightCurly
) {
7456 anyChars
.ungetToken();
7459 anyChars
.ungetToken();
7462 uint32_t propNameOffset
;
7463 if (!tokenStream
.peekOffset(&propNameOffset
, TokenStream::SlashIsInvalid
)) {
7467 TaggedParserAtomIndex propAtom
;
7468 PropertyType propType
;
7470 MOZ_TRY_VAR_OR_RETURN(
7472 propertyOrMethodName(yieldHandling
, PropertyNameInClass
,
7473 /* maybeDecl = */ Nothing(), classMembers
, &propType
,
7477 if (propType
== PropertyType::Field
||
7478 propType
== PropertyType::FieldWithAccessor
) {
7480 if (propAtom
== TaggedParserAtomIndex::WellKnown::prototype()) {
7481 errorAt(propNameOffset
, JSMSG_BAD_METHOD_DEF
);
7486 if (propAtom
== TaggedParserAtomIndex::WellKnown::constructor()) {
7487 errorAt(propNameOffset
, JSMSG_BAD_METHOD_DEF
);
7491 if (handler_
.isPrivateName(propName
)) {
7492 if (propAtom
== TaggedParserAtomIndex::WellKnown::hash_constructor_()) {
7493 errorAt(propNameOffset
, JSMSG_BAD_METHOD_DEF
);
7497 auto privateName
= propAtom
;
7498 if (!noteDeclaredPrivateName(
7499 propName
, privateName
, propType
,
7500 isStatic
? FieldPlacement::Static
: FieldPlacement::Instance
,
7506 #ifdef ENABLE_DECORATORS
7507 ClassMethodType accessorGetterNode
= null();
7508 ClassMethodType accessorSetterNode
= null();
7509 if (propType
== PropertyType::FieldWithAccessor
) {
7510 // Decorators Proposal
7511 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-runtime-semantics-classfielddefinitionevaluation
7513 // FieldDefinition : accessor ClassElementName Initializeropt
7515 // Step 1. Let name be the result of evaluating ClassElementName.
7517 // Step 3. Let privateStateDesc be the string-concatenation of name
7518 // and " accessor storage".
7519 StringBuffer
privateStateDesc(fc_
);
7520 if (!privateStateDesc
.append(this->parserAtoms(), propAtom
)) {
7523 if (!privateStateDesc
.append(" accessor storage")) {
7526 // Step 4. Let privateStateName be a new Private Name whose
7527 // [[Description]] value is privateStateDesc.
7528 TokenPos
propNamePos(propNameOffset
, pos().end
);
7529 auto privateStateName
=
7530 privateStateDesc
.finishParserAtom(this->parserAtoms(), fc_
);
7531 if (!noteDeclaredPrivateName(
7532 propName
, privateStateName
, propType
,
7533 isStatic
? FieldPlacement::Static
: FieldPlacement::Instance
,
7538 // Step 5. Let getter be MakeAutoAccessorGetter(homeObject, name,
7539 // privateStateName).
7540 MOZ_TRY_VAR_OR_RETURN(
7542 synthesizeAccessor(propName
, propNamePos
, propAtom
, privateStateName
,
7543 isStatic
, FunctionSyntaxKind::Getter
,
7544 classInitializedMembers
),
7547 // If the accessor is not decorated or is a non-static private field,
7548 // add it to the class here. Otherwise, we'll handle this when the
7549 // decorators are called. We don't need to keep a reference to the node
7550 // after this except for non-static private accessors. Please see the
7551 // comment in the definition of ClassField for details.
7552 bool addAccessorImmediately
=
7553 !decorators
|| (!isStatic
&& handler_
.isPrivateName(propName
));
7554 if (addAccessorImmediately
) {
7555 if (!handler_
.addClassMemberDefinition(classMembers
,
7556 accessorGetterNode
)) {
7559 if (!handler_
.isPrivateName(propName
)) {
7560 accessorGetterNode
= null();
7564 // Step 6. Let setter be MakeAutoAccessorSetter(homeObject, name,
7565 // privateStateName).
7566 MOZ_TRY_VAR_OR_RETURN(
7568 synthesizeAccessor(propName
, propNamePos
, propAtom
, privateStateName
,
7569 isStatic
, FunctionSyntaxKind::Setter
,
7570 classInitializedMembers
),
7573 if (addAccessorImmediately
) {
7574 if (!handler_
.addClassMemberDefinition(classMembers
,
7575 accessorSetterNode
)) {
7578 if (!handler_
.isPrivateName(propName
)) {
7579 accessorSetterNode
= null();
7583 // Step 10. Return ClassElementDefinition Record { [[Key]]: name,
7584 // [[Kind]]: accessor, [[Get]]: getter, [[Set]]: setter,
7585 // [[BackingStorageKey]]: privateStateName, [[Initializers]]:
7586 // initializers, [[Decorators]]: empty }.
7587 MOZ_TRY_VAR_OR_RETURN(
7588 propName
, handler_
.newPrivateName(privateStateName
, pos()), false);
7589 propAtom
= privateStateName
;
7590 // We maintain `decorators` here to perform this step at the same time:
7591 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-static-semantics-classelementevaluation
7592 // 4. Set fieldDefinition.[[Decorators]] to decorators.
7596 classInitializedMembers
.staticFields
++;
7598 classInitializedMembers
.instanceFields
++;
7601 TokenPos
propNamePos(propNameOffset
, pos().end
);
7602 FunctionNodeType initializer
;
7603 MOZ_TRY_VAR_OR_RETURN(
7605 fieldInitializerOpt(propNamePos
, propName
, propAtom
,
7606 classInitializedMembers
, isStatic
, hasHeritage
),
7609 if (!matchOrInsertSemicolon(TokenStream::SlashIsInvalid
)) {
7613 ClassFieldType field
;
7614 MOZ_TRY_VAR_OR_RETURN(field
,
7615 handler_
.newClassFieldDefinition(
7616 propName
, initializer
, isStatic
7617 #ifdef ENABLE_DECORATORS
7619 decorators
, accessorGetterNode
, accessorSetterNode
7624 return handler_
.addClassMemberDefinition(classMembers
, field
);
7627 if (propType
!= PropertyType::Getter
&& propType
!= PropertyType::Setter
&&
7628 propType
!= PropertyType::Method
&&
7629 propType
!= PropertyType::GeneratorMethod
&&
7630 propType
!= PropertyType::AsyncMethod
&&
7631 propType
!= PropertyType::AsyncGeneratorMethod
) {
7632 errorAt(propNameOffset
, JSMSG_BAD_METHOD_DEF
);
7636 bool isConstructor
=
7637 !isStatic
&& propAtom
== TaggedParserAtomIndex::WellKnown::constructor();
7638 if (isConstructor
) {
7639 if (propType
!= PropertyType::Method
) {
7640 errorAt(propNameOffset
, JSMSG_BAD_METHOD_DEF
);
7643 if (classStmt
.constructorBox
) {
7644 errorAt(propNameOffset
, JSMSG_DUPLICATE_PROPERTY
, "constructor");
7647 propType
= hasHeritage
== HasHeritage::Yes
7648 ? PropertyType::DerivedConstructor
7649 : PropertyType::Constructor
;
7650 } else if (isStatic
&&
7651 propAtom
== TaggedParserAtomIndex::WellKnown::prototype()) {
7652 errorAt(propNameOffset
, JSMSG_BAD_METHOD_DEF
);
7656 TaggedParserAtomIndex funName
;
7658 case PropertyType::Getter
:
7659 case PropertyType::Setter
: {
7660 bool hasStaticName
=
7661 !anyChars
.isCurrentTokenType(TokenKind::RightBracket
) && propAtom
;
7662 if (hasStaticName
) {
7663 funName
= prefixAccessorName(propType
, propAtom
);
7670 case PropertyType::Constructor
:
7671 case PropertyType::DerivedConstructor
:
7672 funName
= className
;
7675 if (!anyChars
.isCurrentTokenType(TokenKind::RightBracket
)) {
7680 // When |super()| is invoked, we search for the nearest scope containing
7681 // |.initializers| to initialize the class fields. This set-up precludes
7682 // declaring |.initializers| in the class scope, because in some syntactic
7683 // contexts |super()| can appear nested in a class, while actually belonging
7684 // to an outer class definition.
7687 // class Outer extends Base {
7693 // // The super() call in the computed property name mustn't access
7694 // // Inner's |.initializers| array, but instead Outer's.
7699 Maybe
<ParseContext::Scope
> dotInitializersScope
;
7700 if (isConstructor
&& !options().selfHostingMode
) {
7701 dotInitializersScope
.emplace(this);
7702 if (!dotInitializersScope
->init(pc_
)) {
7706 if (!noteDeclaredName(TaggedParserAtomIndex::WellKnown::dot_initializers_(),
7707 DeclarationKind::Let
, pos())) {
7712 // Calling toString on constructors need to return the source text for
7713 // the entire class. The end offset is unknown at this point in
7714 // parsing and will be amended when class parsing finishes below.
7715 FunctionNodeType funNode
;
7716 MOZ_TRY_VAR_OR_RETURN(
7718 methodDefinition(isConstructor
? classStartOffset
: propNameOffset
,
7722 AccessorType atype
= ToAccessorType(propType
);
7724 Maybe
<FunctionNodeType
> initializerIfPrivate
= Nothing();
7725 if (handler_
.isPrivateName(propName
)) {
7726 if (propAtom
== TaggedParserAtomIndex::WellKnown::hash_constructor_()) {
7727 // #constructor is an invalid private name.
7728 errorAt(propNameOffset
, JSMSG_BAD_METHOD_DEF
);
7732 TaggedParserAtomIndex privateName
= propAtom
;
7733 if (!noteDeclaredPrivateName(
7734 propName
, privateName
, propType
,
7735 isStatic
? FieldPlacement::Static
: FieldPlacement::Instance
,
7740 // Private non-static methods are stored in the class body environment.
7741 // Private non-static accessors are stamped onto every instance using
7742 // initializers. Private static methods are stamped onto the constructor
7743 // during class evaluation; see BytecodeEmitter::emitPropertyList.
7745 if (atype
== AccessorType::Getter
|| atype
== AccessorType::Setter
) {
7746 classInitializedMembers
.privateAccessors
++;
7747 TokenPos
propNamePos(propNameOffset
, pos().end
);
7748 FunctionNodeType initializerNode
;
7749 MOZ_TRY_VAR_OR_RETURN(
7751 synthesizePrivateMethodInitializer(propAtom
, atype
, propNamePos
),
7753 initializerIfPrivate
= Some(initializerNode
);
7755 MOZ_ASSERT(atype
== AccessorType::None
);
7756 classInitializedMembers
.privateMethods
++;
7762 MOZ_TRY_VAR_OR_RETURN(
7764 handler_
.newClassMethodDefinition(propName
, funNode
, atype
, isStatic
,
7765 initializerIfPrivate
7766 #ifdef ENABLE_DECORATORS
7773 if (dotInitializersScope
.isSome()) {
7774 MOZ_TRY_VAR_OR_RETURN(
7775 method
, finishLexicalScope(*dotInitializersScope
, method
), false);
7776 dotInitializersScope
.reset();
7779 return handler_
.addClassMemberDefinition(classMembers
, method
);
7782 template <class ParseHandler
, typename Unit
>
7783 bool GeneralParser
<ParseHandler
, Unit
>::finishClassConstructor(
7784 const ParseContext::ClassStatement
& classStmt
,
7785 TaggedParserAtomIndex className
, HasHeritage hasHeritage
,
7786 uint32_t classStartOffset
, uint32_t classEndOffset
,
7787 const ClassInitializedMembers
& classInitializedMembers
,
7788 ListNodeType
& classMembers
) {
7789 if (classStmt
.constructorBox
== nullptr) {
7790 MOZ_ASSERT(!options().selfHostingMode
);
7791 // Unconditionally create the scope here, because it's always the
7793 ParseContext::Scope
dotInitializersScope(this);
7794 if (!dotInitializersScope
.init(pc_
)) {
7798 if (!noteDeclaredName(TaggedParserAtomIndex::WellKnown::dot_initializers_(),
7799 DeclarationKind::Let
, pos())) {
7803 // synthesizeConstructor assigns to classStmt.constructorBox
7804 TokenPos
synthesizedBodyPos(classStartOffset
, classEndOffset
);
7805 FunctionNodeType synthesizedCtor
;
7806 MOZ_TRY_VAR_OR_RETURN(
7808 synthesizeConstructor(className
, synthesizedBodyPos
, hasHeritage
),
7811 // Note: the *function* has the name of the class, but the *property*
7812 // containing the function has the name "constructor"
7813 Node constructorNameNode
;
7814 MOZ_TRY_VAR_OR_RETURN(
7815 constructorNameNode
,
7816 handler_
.newObjectLiteralPropertyName(
7817 TaggedParserAtomIndex::WellKnown::constructor(), pos()),
7819 ClassMethodType method
;
7820 MOZ_TRY_VAR_OR_RETURN(method
,
7821 handler_
.newDefaultClassConstructor(
7822 constructorNameNode
, synthesizedCtor
),
7824 LexicalScopeNodeType scope
;
7825 MOZ_TRY_VAR_OR_RETURN(
7826 scope
, finishLexicalScope(dotInitializersScope
, method
), false);
7827 if (!handler_
.addClassMemberDefinition(classMembers
, scope
)) {
7832 MOZ_ASSERT(classStmt
.constructorBox
);
7833 FunctionBox
* ctorbox
= classStmt
.constructorBox
;
7835 // Amend the toStringEnd offset for the constructor now that we've
7836 // finished parsing the class.
7837 ctorbox
->setCtorToStringEnd(classEndOffset
);
7839 size_t numMemberInitializers
= classInitializedMembers
.privateAccessors
+
7840 classInitializedMembers
.instanceFields
;
7841 bool hasPrivateBrand
= classInitializedMembers
.hasPrivateBrand();
7842 if (hasPrivateBrand
|| numMemberInitializers
> 0) {
7843 // Now that we have full set of initializers, update the constructor.
7844 MemberInitializers
initializers(hasPrivateBrand
, numMemberInitializers
);
7845 ctorbox
->setMemberInitializers(initializers
);
7847 // Field initialization need access to `this`.
7848 ctorbox
->setCtorFunctionHasThisBinding();
7854 template <class ParseHandler
, typename Unit
>
7855 typename
ParseHandler::ClassNodeResult
7856 GeneralParser
<ParseHandler
, Unit
>::classDefinition(
7857 YieldHandling yieldHandling
, ClassContext classContext
,
7858 DefaultHandling defaultHandling
) {
7859 #ifdef ENABLE_DECORATORS
7860 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::At
) ||
7861 anyChars
.isCurrentTokenType(TokenKind::Class
));
7863 ListNodeType decorators
= null();
7864 if (anyChars
.isCurrentTokenType(TokenKind::At
)) {
7865 MOZ_TRY_VAR(decorators
, decoratorList(yieldHandling
));
7867 if (!tokenStream
.getToken(&next
)) {
7868 return errorResult();
7870 if (next
!= TokenKind::Class
) {
7871 error(JSMSG_CLASS_EXPECTED
);
7872 return errorResult();
7876 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Class
));
7879 uint32_t classStartOffset
= pos().begin
;
7880 bool savedStrictness
= setLocalStrictMode(true);
7882 // Classes are quite broken in self-hosted code.
7883 if (options().selfHostingMode
) {
7884 error(JSMSG_SELFHOSTED_CLASS
);
7885 return errorResult();
7889 if (!tokenStream
.getToken(&tt
)) {
7890 return errorResult();
7893 TaggedParserAtomIndex className
;
7894 if (TokenKindIsPossibleIdentifier(tt
)) {
7895 className
= bindingIdentifier(yieldHandling
);
7897 return errorResult();
7899 } else if (classContext
== ClassStatement
) {
7900 if (defaultHandling
== AllowDefaultName
) {
7901 className
= TaggedParserAtomIndex::WellKnown::default_();
7902 anyChars
.ungetToken();
7904 // Class statements must have a bound name
7905 error(JSMSG_UNNAMED_CLASS_STMT
);
7906 return errorResult();
7909 // Make sure to put it back, whatever it was
7910 anyChars
.ungetToken();
7913 // Because the binding definitions keep track of their blockId, we need to
7914 // create at least the inner binding later. Keep track of the name's
7915 // position in order to provide it for the nodes created later.
7916 TokenPos namePos
= pos();
7918 bool isInClass
= pc_
->sc()->inClass();
7920 // Push a ParseContext::ClassStatement to keep track of the constructor
7922 ParseContext::ClassStatement
classStmt(pc_
);
7924 NameNodeType innerName
;
7925 Node nameNode
= null();
7926 Node classHeritage
= null();
7927 LexicalScopeNodeType classBlock
= null();
7928 ClassBodyScopeNodeType classBodyBlock
= null();
7929 uint32_t classEndOffset
;
7931 // A named class creates a new lexical scope with a const binding of the
7932 // class name for the "inner name".
7933 ParseContext::Statement
innerScopeStmt(pc_
, StatementKind::Block
);
7934 ParseContext::Scope
innerScope(this);
7935 if (!innerScope
.init(pc_
)) {
7936 return errorResult();
7939 bool hasHeritageBool
;
7940 if (!tokenStream
.matchToken(&hasHeritageBool
, TokenKind::Extends
)) {
7941 return errorResult();
7943 HasHeritage hasHeritage
=
7944 hasHeritageBool
? HasHeritage::Yes
: HasHeritage::No
;
7945 if (hasHeritage
== HasHeritage::Yes
) {
7946 if (!tokenStream
.getToken(&tt
)) {
7947 return errorResult();
7949 MOZ_TRY_VAR(classHeritage
,
7950 optionalExpr(yieldHandling
, TripledotProhibited
, tt
));
7953 if (!mustMatchToken(TokenKind::LeftCurly
, JSMSG_CURLY_BEFORE_CLASS
)) {
7954 return errorResult();
7958 ParseContext::Statement
bodyScopeStmt(pc_
, StatementKind::Block
);
7959 ParseContext::Scope
bodyScope(this);
7960 if (!bodyScope
.init(pc_
)) {
7961 return errorResult();
7964 ListNodeType classMembers
;
7965 MOZ_TRY_VAR(classMembers
, handler_
.newClassMemberList(pos().begin
));
7967 ClassInitializedMembers classInitializedMembers
{};
7970 if (!classMember(yieldHandling
, classStmt
, className
, classStartOffset
,
7971 hasHeritage
, classInitializedMembers
, classMembers
,
7973 return errorResult();
7980 if (classInitializedMembers
.privateMethods
+
7981 classInitializedMembers
.privateAccessors
>
7983 // We declare `.privateBrand` as ClosedOver because the constructor
7984 // always uses it, even a default constructor. We could equivalently
7985 // `noteUsedName` when parsing the constructor, except that at that
7986 // time, we don't necessarily know if the class has a private brand.
7987 if (!noteDeclaredName(
7988 TaggedParserAtomIndex::WellKnown::dot_privateBrand_(),
7989 DeclarationKind::Synthetic
, namePos
, ClosedOver::Yes
)) {
7990 return errorResult();
7994 if (classInitializedMembers
.instanceFieldKeys
> 0) {
7995 if (!noteDeclaredName(
7996 TaggedParserAtomIndex::WellKnown::dot_fieldKeys_(),
7997 DeclarationKind::Synthetic
, namePos
)) {
7998 return errorResult();
8002 if (classInitializedMembers
.staticFields
> 0) {
8003 if (!noteDeclaredName(
8004 TaggedParserAtomIndex::WellKnown::dot_staticInitializers_(),
8005 DeclarationKind::Synthetic
, namePos
)) {
8006 return errorResult();
8010 if (classInitializedMembers
.staticFieldKeys
> 0) {
8011 if (!noteDeclaredName(
8012 TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_(),
8013 DeclarationKind::Synthetic
, namePos
)) {
8014 return errorResult();
8018 classEndOffset
= pos().end
;
8019 if (!finishClassConstructor(classStmt
, className
, hasHeritage
,
8020 classStartOffset
, classEndOffset
,
8021 classInitializedMembers
, classMembers
)) {
8022 return errorResult();
8025 MOZ_TRY_VAR(classBodyBlock
,
8026 finishClassBodyScope(bodyScope
, classMembers
));
8028 // Pop the class body scope
8032 // The inner name is immutable.
8033 if (!noteDeclaredName(className
, DeclarationKind::Const
, namePos
)) {
8034 return errorResult();
8037 MOZ_TRY_VAR(innerName
, newName(className
, namePos
));
8040 MOZ_TRY_VAR(classBlock
, finishLexicalScope(innerScope
, classBodyBlock
));
8042 // Pop the inner scope.
8046 NameNodeType outerName
= null();
8047 if (classContext
== ClassStatement
) {
8048 // The outer name is mutable.
8049 if (!noteDeclaredName(className
, DeclarationKind::Class
, namePos
)) {
8050 return errorResult();
8053 MOZ_TRY_VAR(outerName
, newName(className
, namePos
));
8056 MOZ_TRY_VAR(nameNode
,
8057 handler_
.newClassNames(outerName
, innerName
, namePos
));
8059 MOZ_ALWAYS_TRUE(setLocalStrictMode(savedStrictness
));
8060 // We're leaving a class definition that was not itself nested within a class
8062 mozilla::Maybe
<UnboundPrivateName
> maybeUnboundName
;
8063 if (!usedNames_
.hasUnboundPrivateNames(fc_
, maybeUnboundName
)) {
8064 return errorResult();
8066 if (maybeUnboundName
) {
8068 this->parserAtoms().toPrintableString(maybeUnboundName
->atom
);
8070 ReportOutOfMemory(this->fc_
);
8071 return errorResult();
8074 errorAt(maybeUnboundName
->position
.begin
, JSMSG_MISSING_PRIVATE_DECL
,
8076 return errorResult();
8080 return handler_
.newClass(nameNode
, classHeritage
, classBlock
,
8081 #ifdef ENABLE_DECORATORS
8084 TokenPos(classStartOffset
, classEndOffset
));
8087 template <class ParseHandler
, typename Unit
>
8088 typename
ParseHandler::FunctionNodeResult
8089 GeneralParser
<ParseHandler
, Unit
>::synthesizeConstructor(
8090 TaggedParserAtomIndex className
, TokenPos synthesizedBodyPos
,
8091 HasHeritage hasHeritage
) {
8092 FunctionSyntaxKind functionSyntaxKind
=
8093 hasHeritage
== HasHeritage::Yes
8094 ? FunctionSyntaxKind::DerivedClassConstructor
8095 : FunctionSyntaxKind::ClassConstructor
;
8097 bool isSelfHosting
= options().selfHostingMode
;
8098 FunctionFlags flags
=
8099 InitialFunctionFlags(functionSyntaxKind
, GeneratorKind::NotGenerator
,
8100 FunctionAsyncKind::SyncFunction
, isSelfHosting
);
8102 // Create the top-level field initializer node.
8103 FunctionNodeType funNode
;
8104 MOZ_TRY_VAR(funNode
,
8105 handler_
.newFunction(functionSyntaxKind
, synthesizedBodyPos
));
8107 // If we see any inner function, note it on our current context. The bytecode
8108 // emitter may eliminate the function later, but we use a conservative
8109 // definition for consistency between lazy and full parsing.
8110 pc_
->sc()->setHasInnerFunctions();
8112 // When fully parsing a lazy script, we do not fully reparse its inner
8113 // functions, which are also lazy. Instead, their free variables and source
8114 // extents are recorded and may be skipped.
8115 if (handler_
.reuseLazyInnerFunctions()) {
8116 if (!skipLazyInnerFunction(funNode
, synthesizedBodyPos
.begin
,
8117 /* tryAnnexB = */ false)) {
8118 return errorResult();
8124 // Create the FunctionBox and link it to the function object.
8125 Directives
directives(true);
8126 FunctionBox
* funbox
= newFunctionBox(
8127 funNode
, className
, flags
, synthesizedBodyPos
.begin
, directives
,
8128 GeneratorKind::NotGenerator
, FunctionAsyncKind::SyncFunction
);
8130 return errorResult();
8132 funbox
->initWithEnclosingParseContext(pc_
, functionSyntaxKind
);
8133 setFunctionEndFromCurrentToken(funbox
);
8135 // Mark this function as being synthesized by the parser. This means special
8136 // handling in delazification will be used since we don't have typical
8138 funbox
->setSyntheticFunction();
8140 // Push a SourceParseContext on to the stack.
8141 ParseContext
* outerpc
= pc_
;
8142 SourceParseContext
funpc(this, funbox
, /* newDirectives = */ nullptr);
8143 if (!funpc
.init()) {
8144 return errorResult();
8147 if (!synthesizeConstructorBody(synthesizedBodyPos
, hasHeritage
, funNode
,
8149 return errorResult();
8152 if (!leaveInnerFunction(outerpc
)) {
8153 return errorResult();
8159 template <class ParseHandler
, typename Unit
>
8160 bool GeneralParser
<ParseHandler
, Unit
>::synthesizeConstructorBody(
8161 TokenPos synthesizedBodyPos
, HasHeritage hasHeritage
,
8162 FunctionNodeType funNode
, FunctionBox
* funbox
) {
8163 MOZ_ASSERT(funbox
->isClassConstructor());
8165 // Create a ParamsBodyNode for the parameters + body (there are no
8167 ParamsBodyNodeType argsbody
;
8168 MOZ_TRY_VAR_OR_RETURN(argsbody
, handler_
.newParamsBody(synthesizedBodyPos
),
8170 handler_
.setFunctionFormalParametersAndBody(funNode
, argsbody
);
8171 setFunctionStartAtPosition(funbox
, synthesizedBodyPos
);
8173 if (hasHeritage
== HasHeritage::Yes
) {
8174 // Synthesize the equivalent to `function f(...args)`
8175 funbox
->setHasRest();
8176 if (!notePositionalFormalParameter(
8177 funNode
, TaggedParserAtomIndex::WellKnown::dot_args_(),
8178 synthesizedBodyPos
.begin
,
8179 /* disallowDuplicateParams = */ false,
8180 /* duplicatedParam = */ nullptr)) {
8183 funbox
->setArgCount(1);
8185 funbox
->setArgCount(0);
8188 pc_
->functionScope().useAsVarScope(pc_
);
8190 ListNodeType stmtList
;
8191 MOZ_TRY_VAR_OR_RETURN(stmtList
, handler_
.newStatementList(synthesizedBodyPos
),
8194 if (!noteUsedName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
8198 if (!noteUsedName(TaggedParserAtomIndex::WellKnown::dot_initializers_())) {
8202 if (hasHeritage
== HasHeritage::Yes
) {
8203 // |super()| implicitly reads |new.target|.
8204 if (!noteUsedName(TaggedParserAtomIndex::WellKnown::dot_newTarget_())) {
8208 NameNodeType thisName
;
8209 MOZ_TRY_VAR_OR_RETURN(thisName
, newThisName(), false);
8211 UnaryNodeType superBase
;
8212 MOZ_TRY_VAR_OR_RETURN(
8213 superBase
, handler_
.newSuperBase(thisName
, synthesizedBodyPos
), false);
8215 ListNodeType arguments
;
8216 MOZ_TRY_VAR_OR_RETURN(arguments
, handler_
.newArguments(synthesizedBodyPos
),
8219 NameNodeType argsNameNode
;
8220 MOZ_TRY_VAR_OR_RETURN(argsNameNode
,
8221 newName(TaggedParserAtomIndex::WellKnown::dot_args_(),
8222 synthesizedBodyPos
),
8224 if (!noteUsedName(TaggedParserAtomIndex::WellKnown::dot_args_())) {
8228 UnaryNodeType spreadArgs
;
8229 MOZ_TRY_VAR_OR_RETURN(
8230 spreadArgs
, handler_
.newSpread(synthesizedBodyPos
.begin
, argsNameNode
),
8232 handler_
.addList(arguments
, spreadArgs
);
8234 CallNodeType superCall
;
8235 MOZ_TRY_VAR_OR_RETURN(
8237 handler_
.newSuperCall(superBase
, arguments
, /* isSpread = */ true),
8240 BinaryNodeType setThis
;
8241 MOZ_TRY_VAR_OR_RETURN(setThis
, handler_
.newSetThis(thisName
, superCall
),
8244 UnaryNodeType exprStatement
;
8245 MOZ_TRY_VAR_OR_RETURN(
8247 handler_
.newExprStatement(setThis
, synthesizedBodyPos
.end
), false);
8249 handler_
.addStatementToList(stmtList
, exprStatement
);
8252 bool canSkipLazyClosedOverBindings
= handler_
.reuseClosedOverBindings();
8253 if (!pc_
->declareFunctionThis(usedNames_
, canSkipLazyClosedOverBindings
)) {
8256 if (!pc_
->declareNewTarget(usedNames_
, canSkipLazyClosedOverBindings
)) {
8260 LexicalScopeNodeType initializerBody
;
8261 MOZ_TRY_VAR_OR_RETURN(
8263 finishLexicalScope(pc_
->varScope(), stmtList
, ScopeKind::FunctionLexical
),
8265 handler_
.setBeginPosition(initializerBody
, stmtList
);
8266 handler_
.setEndPosition(initializerBody
, stmtList
);
8268 handler_
.setFunctionBody(funNode
, initializerBody
);
8270 return finishFunction();
8273 template <class ParseHandler
, typename Unit
>
8274 typename
ParseHandler::FunctionNodeResult
8275 GeneralParser
<ParseHandler
, Unit
>::privateMethodInitializer(
8276 TokenPos propNamePos
, TaggedParserAtomIndex propAtom
,
8277 TaggedParserAtomIndex storedMethodAtom
) {
8278 if (!abortIfSyntaxParser()) {
8279 return errorResult();
8282 // Synthesize an initializer function that the constructor can use to stamp a
8283 // private method onto an instance object.
8284 FunctionSyntaxKind syntaxKind
= FunctionSyntaxKind::FieldInitializer
;
8285 FunctionAsyncKind asyncKind
= FunctionAsyncKind::SyncFunction
;
8286 GeneratorKind generatorKind
= GeneratorKind::NotGenerator
;
8287 bool isSelfHosting
= options().selfHostingMode
;
8288 FunctionFlags flags
=
8289 InitialFunctionFlags(syntaxKind
, generatorKind
, asyncKind
, isSelfHosting
);
8291 FunctionNodeType funNode
;
8292 MOZ_TRY_VAR(funNode
, handler_
.newFunction(syntaxKind
, propNamePos
));
8294 Directives
directives(true);
8295 FunctionBox
* funbox
=
8296 newFunctionBox(funNode
, TaggedParserAtomIndex::null(), flags
,
8297 propNamePos
.begin
, directives
, generatorKind
, asyncKind
);
8299 return errorResult();
8301 funbox
->initWithEnclosingParseContext(pc_
, syntaxKind
);
8303 // Push a SourceParseContext on to the stack.
8304 ParseContext
* outerpc
= pc_
;
8305 SourceParseContext
funpc(this, funbox
, /* newDirectives = */ nullptr);
8306 if (!funpc
.init()) {
8307 return errorResult();
8309 pc_
->functionScope().useAsVarScope(pc_
);
8311 // Add empty parameter list.
8312 ParamsBodyNodeType argsbody
;
8313 MOZ_TRY_VAR(argsbody
, handler_
.newParamsBody(propNamePos
));
8314 handler_
.setFunctionFormalParametersAndBody(funNode
, argsbody
);
8315 setFunctionStartAtCurrentToken(funbox
);
8316 funbox
->setArgCount(0);
8318 // Note both the stored private method body and it's private name as being
8319 // used in the initializer. They will be emitted into the method body in the
8321 if (!noteUsedName(storedMethodAtom
)) {
8322 return errorResult();
8324 MOZ_TRY(privateNameReference(propAtom
));
8326 // Unlike field initializers, private method initializers are not created with
8327 // a body of synthesized AST nodes. Instead, the body is left empty and the
8328 // initializer is synthesized at the bytecode level.
8329 // See BytecodeEmitter::emitPrivateMethodInitializer.
8330 ListNodeType stmtList
;
8331 MOZ_TRY_VAR(stmtList
, handler_
.newStatementList(propNamePos
));
8333 bool canSkipLazyClosedOverBindings
= handler_
.reuseClosedOverBindings();
8334 if (!pc_
->declareFunctionThis(usedNames_
, canSkipLazyClosedOverBindings
)) {
8335 return errorResult();
8337 if (!pc_
->declareNewTarget(usedNames_
, canSkipLazyClosedOverBindings
)) {
8338 return errorResult();
8341 LexicalScopeNodeType initializerBody
;
8342 MOZ_TRY_VAR(initializerBody
, finishLexicalScope(pc_
->varScope(), stmtList
,
8343 ScopeKind::FunctionLexical
));
8344 handler_
.setBeginPosition(initializerBody
, stmtList
);
8345 handler_
.setEndPosition(initializerBody
, stmtList
);
8346 handler_
.setFunctionBody(funNode
, initializerBody
);
8348 // Set field-initializer lambda boundary to start at property name and end
8349 // after method body.
8350 setFunctionStartAtPosition(funbox
, propNamePos
);
8351 setFunctionEndFromCurrentToken(funbox
);
8353 if (!finishFunction()) {
8354 return errorResult();
8357 if (!leaveInnerFunction(outerpc
)) {
8358 return errorResult();
8364 template <class ParseHandler
, typename Unit
>
8365 typename
ParseHandler::FunctionNodeResult
8366 GeneralParser
<ParseHandler
, Unit
>::staticClassBlock(
8367 ClassInitializedMembers
& classInitializedMembers
) {
8368 // Both for getting-this-done, and because this will invariably be executed,
8369 // syntax parsing should be aborted.
8370 if (!abortIfSyntaxParser()) {
8371 return errorResult();
8374 FunctionSyntaxKind syntaxKind
= FunctionSyntaxKind::StaticClassBlock
;
8375 FunctionAsyncKind asyncKind
= FunctionAsyncKind::SyncFunction
;
8376 GeneratorKind generatorKind
= GeneratorKind::NotGenerator
;
8377 bool isSelfHosting
= options().selfHostingMode
;
8378 FunctionFlags flags
=
8379 InitialFunctionFlags(syntaxKind
, generatorKind
, asyncKind
, isSelfHosting
);
8381 AutoAwaitIsKeyword
awaitIsKeyword(this, AwaitHandling::AwaitIsDisallowed
);
8383 // Create the function node for the static class body.
8384 FunctionNodeType funNode
;
8385 MOZ_TRY_VAR(funNode
, handler_
.newFunction(syntaxKind
, pos()));
8387 // Create the FunctionBox and link it to the function object.
8388 Directives
directives(true);
8389 FunctionBox
* funbox
=
8390 newFunctionBox(funNode
, TaggedParserAtomIndex::null(), flags
, pos().begin
,
8391 directives
, generatorKind
, asyncKind
);
8393 return errorResult();
8395 funbox
->initWithEnclosingParseContext(pc_
, syntaxKind
);
8396 MOZ_ASSERT(funbox
->isSyntheticFunction());
8397 MOZ_ASSERT(!funbox
->allowSuperCall());
8398 MOZ_ASSERT(!funbox
->allowArguments());
8399 MOZ_ASSERT(!funbox
->allowReturn());
8401 // Set start at `static` token.
8402 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Static
));
8403 setFunctionStartAtCurrentToken(funbox
);
8405 // Push a SourceParseContext on to the stack.
8406 ParseContext
* outerpc
= pc_
;
8407 SourceParseContext
funpc(this, funbox
, /* newDirectives = */ nullptr);
8408 if (!funpc
.init()) {
8409 return errorResult();
8412 pc_
->functionScope().useAsVarScope(pc_
);
8414 uint32_t start
= pos().begin
;
8416 tokenStream
.consumeKnownToken(TokenKind::LeftCurly
);
8418 // Static class blocks are code-generated as if they were static field
8419 // initializers, so we bump the staticFields count here, which ensures
8420 // .staticInitializers is noted as used.
8421 classInitializedMembers
.staticFields
++;
8423 LexicalScopeNodeType body
;
8425 functionBody(InHandling::InAllowed
, YieldHandling::YieldIsKeyword
,
8426 syntaxKind
, FunctionBodyType::StatementListBody
));
8428 if (anyChars
.isEOF()) {
8429 error(JSMSG_UNTERMINATED_STATIC_CLASS_BLOCK
);
8430 return errorResult();
8433 tokenStream
.consumeKnownToken(TokenKind::RightCurly
,
8434 TokenStream::Modifier::SlashIsRegExp
);
8436 TokenPos
wholeBodyPos(start
, pos().end
);
8438 handler_
.setEndPosition(funNode
, wholeBodyPos
.end
);
8439 setFunctionEndFromCurrentToken(funbox
);
8441 // Create a ParamsBodyNode for the parameters + body (there are no
8443 ParamsBodyNodeType argsbody
;
8444 MOZ_TRY_VAR(argsbody
, handler_
.newParamsBody(wholeBodyPos
));
8446 handler_
.setFunctionFormalParametersAndBody(funNode
, argsbody
);
8447 funbox
->setArgCount(0);
8449 if (pc_
->superScopeNeedsHomeObject()) {
8450 funbox
->setNeedsHomeObject();
8453 handler_
.setEndPosition(body
, pos().begin
);
8454 handler_
.setEndPosition(funNode
, pos().end
);
8455 handler_
.setFunctionBody(funNode
, body
);
8457 if (!finishFunction()) {
8458 return errorResult();
8461 if (!leaveInnerFunction(outerpc
)) {
8462 return errorResult();
8468 template <class ParseHandler
, typename Unit
>
8469 typename
ParseHandler::FunctionNodeResult
8470 GeneralParser
<ParseHandler
, Unit
>::fieldInitializerOpt(
8471 TokenPos propNamePos
, Node propName
, TaggedParserAtomIndex propAtom
,
8472 ClassInitializedMembers
& classInitializedMembers
, bool isStatic
,
8473 HasHeritage hasHeritage
) {
8474 if (!abortIfSyntaxParser()) {
8475 return errorResult();
8478 bool hasInitializer
= false;
8479 if (!tokenStream
.matchToken(&hasInitializer
, TokenKind::Assign
,
8480 TokenStream::SlashIsDiv
)) {
8481 return errorResult();
8484 FunctionSyntaxKind syntaxKind
= FunctionSyntaxKind::FieldInitializer
;
8485 FunctionAsyncKind asyncKind
= FunctionAsyncKind::SyncFunction
;
8486 GeneratorKind generatorKind
= GeneratorKind::NotGenerator
;
8487 bool isSelfHosting
= options().selfHostingMode
;
8488 FunctionFlags flags
=
8489 InitialFunctionFlags(syntaxKind
, generatorKind
, asyncKind
, isSelfHosting
);
8491 // Create the top-level field initializer node.
8492 FunctionNodeType funNode
;
8493 MOZ_TRY_VAR(funNode
, handler_
.newFunction(syntaxKind
, propNamePos
));
8495 // Create the FunctionBox and link it to the function object.
8496 Directives
directives(true);
8497 FunctionBox
* funbox
=
8498 newFunctionBox(funNode
, TaggedParserAtomIndex::null(), flags
,
8499 propNamePos
.begin
, directives
, generatorKind
, asyncKind
);
8501 return errorResult();
8503 funbox
->initWithEnclosingParseContext(pc_
, syntaxKind
);
8504 MOZ_ASSERT(funbox
->isSyntheticFunction());
8506 // We can't use setFunctionStartAtCurrentToken because that uses pos().begin,
8507 // which is incorrect for fields without initializers (pos() points to the
8508 // field identifier)
8509 setFunctionStartAtPosition(funbox
, propNamePos
);
8511 // Push a SourceParseContext on to the stack.
8512 ParseContext
* outerpc
= pc_
;
8513 SourceParseContext
funpc(this, funbox
, /* newDirectives = */ nullptr);
8514 if (!funpc
.init()) {
8515 return errorResult();
8518 pc_
->functionScope().useAsVarScope(pc_
);
8520 Node initializerExpr
;
8521 if (hasInitializer
) {
8522 // Parse the expression for the field initializer.
8524 AutoAwaitIsKeyword
awaitHandling(this, AwaitIsName
);
8525 MOZ_TRY_VAR(initializerExpr
,
8526 assignExpr(InAllowed
, YieldIsName
, TripledotProhibited
));
8529 handler_
.checkAndSetIsDirectRHSAnonFunction(initializerExpr
);
8531 MOZ_TRY_VAR(initializerExpr
, handler_
.newRawUndefinedLiteral(propNamePos
));
8534 TokenPos
wholeInitializerPos(propNamePos
.begin
, pos().end
);
8536 // Update the end position of the parse node.
8537 handler_
.setEndPosition(funNode
, wholeInitializerPos
.end
);
8538 setFunctionEndFromCurrentToken(funbox
);
8540 // Create a ParamsBodyNode for the parameters + body (there are no
8542 ParamsBodyNodeType argsbody
;
8543 MOZ_TRY_VAR(argsbody
, handler_
.newParamsBody(wholeInitializerPos
));
8544 handler_
.setFunctionFormalParametersAndBody(funNode
, argsbody
);
8545 funbox
->setArgCount(0);
8547 NameNodeType thisName
;
8548 MOZ_TRY_VAR(thisName
, newThisName());
8550 // Build `this.field` expression.
8551 ThisLiteralType propAssignThis
;
8552 MOZ_TRY_VAR(propAssignThis
,
8553 handler_
.newThisLiteral(wholeInitializerPos
, thisName
));
8555 Node propAssignFieldAccess
;
8556 uint32_t indexValue
;
8558 // See BytecodeEmitter::emitCreateFieldKeys for an explanation of what
8559 // .fieldKeys means and its purpose.
8560 NameNodeType fieldKeysName
;
8565 TaggedParserAtomIndex::WellKnown::dot_staticFieldKeys_()));
8567 MOZ_TRY_VAR(fieldKeysName
,
8569 TaggedParserAtomIndex::WellKnown::dot_fieldKeys_()));
8571 if (!fieldKeysName
) {
8572 return errorResult();
8575 double fieldKeyIndex
;
8577 fieldKeyIndex
= classInitializedMembers
.staticFieldKeys
++;
8579 fieldKeyIndex
= classInitializedMembers
.instanceFieldKeys
++;
8581 Node fieldKeyIndexNode
;
8582 MOZ_TRY_VAR(fieldKeyIndexNode
,
8583 handler_
.newNumber(fieldKeyIndex
, DecimalPoint::NoDecimal
,
8584 wholeInitializerPos
));
8587 MOZ_TRY_VAR(fieldKeyValue
,
8588 handler_
.newPropertyByValue(fieldKeysName
, fieldKeyIndexNode
,
8589 wholeInitializerPos
.end
));
8591 MOZ_TRY_VAR(propAssignFieldAccess
,
8592 handler_
.newPropertyByValue(propAssignThis
, fieldKeyValue
,
8593 wholeInitializerPos
.end
));
8594 } else if (handler_
.isPrivateName(propName
)) {
8595 // It would be nice if we could tweak this here such that only if
8596 // HasHeritage::Yes we end up emitting CheckPrivateField, but otherwise we
8597 // emit InitElem -- this is an optimization to minimize HasOwn checks
8598 // in InitElem for classes without heritage.
8600 // Further tweaking would be to ultimately only do CheckPrivateField for the
8601 // -first- field in a derived class, which would suffice to match the
8604 NameNodeType privateNameNode
;
8605 MOZ_TRY_VAR(privateNameNode
, privateNameReference(propAtom
));
8607 MOZ_TRY_VAR(propAssignFieldAccess
,
8608 handler_
.newPrivateMemberAccess(propAssignThis
, privateNameNode
,
8609 wholeInitializerPos
.end
));
8610 } else if (this->parserAtoms().isIndex(propAtom
, &indexValue
)) {
8611 MOZ_TRY_VAR(propAssignFieldAccess
,
8612 handler_
.newPropertyByValue(propAssignThis
, propName
,
8613 wholeInitializerPos
.end
));
8615 NameNodeType propAssignName
;
8616 MOZ_TRY_VAR(propAssignName
,
8617 handler_
.newPropertyName(propAtom
, wholeInitializerPos
));
8619 MOZ_TRY_VAR(propAssignFieldAccess
,
8620 handler_
.newPropertyAccess(propAssignThis
, propAssignName
));
8623 // Synthesize an property init.
8624 BinaryNodeType initializerPropInit
;
8625 MOZ_TRY_VAR(initializerPropInit
,
8626 handler_
.newInitExpr(propAssignFieldAccess
, initializerExpr
));
8628 UnaryNodeType exprStatement
;
8629 MOZ_TRY_VAR(exprStatement
, handler_
.newExprStatement(
8630 initializerPropInit
, wholeInitializerPos
.end
));
8632 ListNodeType statementList
;
8633 MOZ_TRY_VAR(statementList
, handler_
.newStatementList(wholeInitializerPos
));
8634 handler_
.addStatementToList(statementList
, exprStatement
);
8636 bool canSkipLazyClosedOverBindings
= handler_
.reuseClosedOverBindings();
8637 if (!pc_
->declareFunctionThis(usedNames_
, canSkipLazyClosedOverBindings
)) {
8638 return errorResult();
8640 if (!pc_
->declareNewTarget(usedNames_
, canSkipLazyClosedOverBindings
)) {
8641 return errorResult();
8644 // Set the function's body to the field assignment.
8645 LexicalScopeNodeType initializerBody
;
8646 MOZ_TRY_VAR(initializerBody
,
8647 finishLexicalScope(pc_
->varScope(), statementList
,
8648 ScopeKind::FunctionLexical
));
8650 handler_
.setFunctionBody(funNode
, initializerBody
);
8652 if (pc_
->superScopeNeedsHomeObject()) {
8653 funbox
->setNeedsHomeObject();
8656 if (!finishFunction()) {
8657 return errorResult();
8660 if (!leaveInnerFunction(outerpc
)) {
8661 return errorResult();
8667 template <class ParseHandler
, typename Unit
>
8668 typename
ParseHandler::FunctionNodeResult
8669 GeneralParser
<ParseHandler
, Unit
>::synthesizePrivateMethodInitializer(
8670 TaggedParserAtomIndex propAtom
, AccessorType accessorType
,
8671 TokenPos propNamePos
) {
8672 if (!abortIfSyntaxParser()) {
8673 return errorResult();
8676 // Synthesize a name for the lexical variable that will store the
8678 StringBuffer
storedMethodName(fc_
);
8679 if (!storedMethodName
.append(this->parserAtoms(), propAtom
)) {
8680 return errorResult();
8682 if (!storedMethodName
.append(
8683 accessorType
== AccessorType::Getter
? ".getter" : ".setter")) {
8684 return errorResult();
8686 auto storedMethodProp
=
8687 storedMethodName
.finishParserAtom(this->parserAtoms(), fc_
);
8688 if (!storedMethodProp
) {
8689 return errorResult();
8691 if (!noteDeclaredName(storedMethodProp
, DeclarationKind::Synthetic
, pos())) {
8692 return errorResult();
8695 return privateMethodInitializer(propNamePos
, propAtom
, storedMethodProp
);
8698 #ifdef ENABLE_DECORATORS
8700 template <class ParseHandler
, typename Unit
>
8701 typename
ParseHandler::ClassMethodResult
8702 GeneralParser
<ParseHandler
, Unit
>::synthesizeAccessor(
8703 Node propName
, TokenPos propNamePos
, TaggedParserAtomIndex propAtom
,
8704 TaggedParserAtomIndex privateStateNameAtom
, bool isStatic
,
8705 FunctionSyntaxKind syntaxKind
,
8706 ClassInitializedMembers
& classInitializedMembers
) {
8707 // Decorators Proposal
8708 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-makeautoaccessorgetter
8709 // The abstract operation MakeAutoAccessorGetter takes arguments homeObject
8710 // (an Object), name (a property key or Private Name), and privateStateName (a
8711 // Private Name) and returns a function object.
8713 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-makeautoaccessorsetter
8714 // The abstract operation MakeAutoAccessorSetter takes arguments homeObject
8715 // (an Object), name (a property key or Private Name), and privateStateName (a
8716 // Private Name) and returns a function object.
8717 if (!abortIfSyntaxParser()) {
8718 return errorResult();
8721 AccessorType accessorType
= syntaxKind
== FunctionSyntaxKind::Getter
8722 ? AccessorType::Getter
8723 : AccessorType::Setter
;
8725 mozilla::Maybe
<FunctionNodeType
> initializerIfPrivate
= Nothing();
8726 if (!isStatic
&& handler_
.isPrivateName(propName
)) {
8727 classInitializedMembers
.privateAccessors
++;
8728 FunctionNodeType initializerNode
;
8729 MOZ_TRY_VAR(initializerNode
, synthesizePrivateMethodInitializer(
8730 propAtom
, accessorType
, propNamePos
));
8731 initializerIfPrivate
= Some(initializerNode
);
8732 handler_
.setPrivateNameKind(propName
, PrivateNameKind::GetterSetter
);
8735 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-makeautoaccessorgetter
8736 // 2. Let getter be CreateBuiltinFunction(getterClosure, 0, "get", « »).
8738 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-makeautoaccessorsetter
8739 // 2. Let setter be CreateBuiltinFunction(setterClosure, 1, "set", « »).
8740 StringBuffer
storedMethodName(fc_
);
8741 if (!storedMethodName
.append(accessorType
== AccessorType::Getter
? "get"
8743 return errorResult();
8745 TaggedParserAtomIndex funNameAtom
=
8746 storedMethodName
.finishParserAtom(this->parserAtoms(), fc_
);
8748 FunctionNodeType funNode
;
8749 MOZ_TRY_VAR(funNode
,
8750 synthesizeAccessorBody(funNameAtom
, propNamePos
,
8751 privateStateNameAtom
, syntaxKind
));
8753 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-makeautoaccessorgetter
8754 // 3. Perform MakeMethod(getter, homeObject).
8755 // 4. Return getter.
8757 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-makeautoaccessorsetter
8758 // 3. Perform MakeMethod(setter, homeObject).
8759 // 4. Return setter.
8760 return handler_
.newClassMethodDefinition(
8761 propName
, funNode
, accessorType
, isStatic
, initializerIfPrivate
, null());
8764 template <class ParseHandler
, typename Unit
>
8765 typename
ParseHandler::FunctionNodeResult
8766 GeneralParser
<ParseHandler
, Unit
>::synthesizeAccessorBody(
8767 TaggedParserAtomIndex funNameAtom
, TokenPos propNamePos
,
8768 TaggedParserAtomIndex propNameAtom
, FunctionSyntaxKind syntaxKind
) {
8769 if (!abortIfSyntaxParser()) {
8770 return errorResult();
8773 FunctionAsyncKind asyncKind
= FunctionAsyncKind::SyncFunction
;
8774 GeneratorKind generatorKind
= GeneratorKind::NotGenerator
;
8775 bool isSelfHosting
= options().selfHostingMode
;
8776 FunctionFlags flags
=
8777 InitialFunctionFlags(syntaxKind
, generatorKind
, asyncKind
, isSelfHosting
);
8779 // Create the top-level function node.
8780 FunctionNodeType funNode
;
8781 MOZ_TRY_VAR(funNode
, handler_
.newFunction(syntaxKind
, propNamePos
));
8783 // Create the FunctionBox and link it to the function object.
8784 Directives
directives(true);
8785 FunctionBox
* funbox
=
8786 newFunctionBox(funNode
, funNameAtom
, flags
, propNamePos
.begin
, directives
,
8787 generatorKind
, asyncKind
);
8789 return errorResult();
8791 funbox
->initWithEnclosingParseContext(pc_
, syntaxKind
);
8792 funbox
->setSyntheticFunction();
8794 // Push a SourceParseContext on to the stack.
8795 ParseContext
* outerpc
= pc_
;
8796 SourceParseContext
funpc(this, funbox
, /* newDirectives = */ nullptr);
8797 if (!funpc
.init()) {
8798 return errorResult();
8801 pc_
->functionScope().useAsVarScope(pc_
);
8803 // The function we synthesize is located at the field with the
8805 setFunctionStartAtCurrentToken(funbox
);
8806 setFunctionEndFromCurrentToken(funbox
);
8808 // Create a ListNode for the parameters + body
8809 ParamsBodyNodeType paramsbody
;
8810 MOZ_TRY_VAR(paramsbody
, handler_
.newParamsBody(propNamePos
));
8811 handler_
.setFunctionFormalParametersAndBody(funNode
, paramsbody
);
8813 if (syntaxKind
== FunctionSyntaxKind::Getter
) {
8814 funbox
->setArgCount(0);
8816 funbox
->setArgCount(1);
8819 // Build `this` expression to access the privateStateName for use in the
8820 // operations to create the getter and setter below.
8821 NameNodeType thisName
;
8822 MOZ_TRY_VAR(thisName
, newThisName());
8824 ThisLiteralType propThis
;
8825 MOZ_TRY_VAR(propThis
, handler_
.newThisLiteral(propNamePos
, thisName
));
8827 NameNodeType privateNameNode
;
8828 MOZ_TRY_VAR(privateNameNode
, privateNameReference(propNameAtom
));
8830 Node propFieldAccess
;
8831 MOZ_TRY_VAR(propFieldAccess
, handler_
.newPrivateMemberAccess(
8832 propThis
, privateNameNode
, propNamePos
.end
));
8835 if (syntaxKind
== FunctionSyntaxKind::Getter
) {
8836 // Decorators Proposal
8837 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-makeautoaccessorgetter
8838 // 1. Let getterClosure be a new Abstract Closure with no parameters that
8839 // captures privateStateName and performs the following steps when called:
8840 // 1.a. Let o be the this value.
8841 // 1.b. Return ? PrivateGet(privateStateName, o).
8842 MOZ_TRY_VAR(accessorBody
,
8843 handler_
.newReturnStatement(propFieldAccess
, propNamePos
));
8845 // Decorators Proposal
8846 // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-makeautoaccessorsetter
8847 // The abstract operation MakeAutoAccessorSetter takes arguments homeObject
8848 // (an Object), name (a property key or Private Name), and privateStateName
8849 // (a Private Name) and returns a function object.
8850 // 1. Let setterClosure be a new Abstract Closure with parameters (value)
8851 // that captures privateStateName and performs the following steps when
8853 // 1.a. Let o be the this value.
8854 notePositionalFormalParameter(funNode
,
8855 TaggedParserAtomIndex::WellKnown::value(),
8856 /* pos = */ 0, false,
8857 /* duplicatedParam = */ nullptr);
8859 Node initializerExpr
;
8860 MOZ_TRY_VAR(initializerExpr
,
8861 handler_
.newName(TaggedParserAtomIndex::WellKnown::value(),
8864 // 1.b. Perform ? PrivateSet(privateStateName, o, value).
8866 MOZ_TRY_VAR(assignment
,
8867 handler_
.newAssignment(ParseNodeKind::AssignExpr
,
8868 propFieldAccess
, initializerExpr
));
8870 MOZ_TRY_VAR(accessorBody
,
8871 handler_
.newExprStatement(assignment
, propNamePos
.end
));
8873 // 1.c. Return undefined.
8876 ListNodeType statementList
;
8877 MOZ_TRY_VAR(statementList
, handler_
.newStatementList(propNamePos
));
8878 handler_
.addStatementToList(statementList
, accessorBody
);
8880 bool canSkipLazyClosedOverBindings
= handler_
.reuseClosedOverBindings();
8881 if (!pc_
->declareFunctionThis(usedNames_
, canSkipLazyClosedOverBindings
)) {
8882 return errorResult();
8884 if (!pc_
->declareNewTarget(usedNames_
, canSkipLazyClosedOverBindings
)) {
8885 return errorResult();
8888 LexicalScopeNodeType initializerBody
;
8889 MOZ_TRY_VAR(initializerBody
,
8890 finishLexicalScope(pc_
->varScope(), statementList
,
8891 ScopeKind::FunctionLexical
));
8893 handler_
.setFunctionBody(funNode
, initializerBody
);
8895 if (pc_
->superScopeNeedsHomeObject()) {
8896 funbox
->setNeedsHomeObject();
8899 if (!finishFunction()) {
8900 return errorResult();
8903 if (!leaveInnerFunction(outerpc
)) {
8904 return errorResult();
8912 bool ParserBase::nextTokenContinuesLetDeclaration(TokenKind next
) {
8913 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Let
));
8914 MOZ_ASSERT(anyChars
.nextToken().type
== next
);
8916 TokenStreamShared::verifyConsistentModifier(TokenStreamShared::SlashIsDiv
,
8917 anyChars
.nextToken());
8919 // Destructuring continues a let declaration.
8920 if (next
== TokenKind::LeftBracket
|| next
== TokenKind::LeftCurly
) {
8924 // A "let" edge case deserves special comment. Consider this:
8926 // let // not an ASI opportunity
8929 // Static semantics in §13.3.1.1 turn a LexicalDeclaration that binds
8930 // "let" into an early error. Does this retroactively permit ASI so
8931 // that we should parse this as two ExpressionStatements? No. ASI
8932 // resolves during parsing. Static semantics only apply to the full
8933 // parse tree with ASI applied. No backsies!
8935 // Otherwise a let declaration must have a name.
8936 return TokenKindIsPossibleIdentifier(next
);
8939 template <class ParseHandler
, typename Unit
>
8940 typename
ParseHandler::DeclarationListNodeResult
8941 GeneralParser
<ParseHandler
, Unit
>::variableStatement(
8942 YieldHandling yieldHandling
) {
8943 DeclarationListNodeType vars
;
8944 MOZ_TRY_VAR(vars
, declarationList(yieldHandling
, ParseNodeKind::VarStmt
));
8945 if (!matchOrInsertSemicolon()) {
8946 return errorResult();
8951 template <class ParseHandler
, typename Unit
>
8952 typename
ParseHandler::NodeResult GeneralParser
<ParseHandler
, Unit
>::statement(
8953 YieldHandling yieldHandling
) {
8954 MOZ_ASSERT(checkOptionsCalled_
);
8956 AutoCheckRecursionLimit
recursion(this->fc_
);
8957 if (!recursion
.check(this->fc_
)) {
8958 return errorResult();
8962 if (!tokenStream
.getToken(&tt
, TokenStream::SlashIsRegExp
)) {
8963 return errorResult();
8967 // BlockStatement[?Yield, ?Return]
8968 case TokenKind::LeftCurly
:
8969 return blockStatement(yieldHandling
);
8971 // VariableStatement[?Yield]
8972 case TokenKind::Var
:
8973 return variableStatement(yieldHandling
);
8976 case TokenKind::Semi
:
8977 return handler_
.newEmptyStatement(pos());
8979 // ExpressionStatement[?Yield].
8981 case TokenKind::Yield
: {
8982 // Don't use a ternary operator here due to obscure linker issues
8983 // around using static consts in the arms of a ternary.
8985 if (yieldExpressionsSupported()) {
8986 modifier
= TokenStream::SlashIsRegExp
;
8988 modifier
= TokenStream::SlashIsDiv
;
8992 if (!tokenStream
.peekToken(&next
, modifier
)) {
8993 return errorResult();
8996 if (next
== TokenKind::Colon
) {
8997 return labeledStatement(yieldHandling
);
9000 return expressionStatement(yieldHandling
);
9004 // If we encounter an await in a module, and the module is not marked
9005 // as async, mark the module as async.
9006 if (tt
== TokenKind::Await
&& !pc_
->isAsync()) {
9007 if (pc_
->atModuleTopLevel()) {
9008 if (!options().topLevelAwait
) {
9009 error(JSMSG_TOP_LEVEL_AWAIT_NOT_SUPPORTED
);
9010 return errorResult();
9012 pc_
->sc()->asModuleContext()->setIsAsync();
9013 MOZ_ASSERT(pc_
->isAsync());
9017 // Avoid getting next token with SlashIsDiv.
9018 if (tt
== TokenKind::Await
&& pc_
->isAsync()) {
9019 return expressionStatement(yieldHandling
);
9022 if (!TokenKindIsPossibleIdentifier(tt
)) {
9023 return expressionStatement(yieldHandling
);
9027 if (!tokenStream
.peekToken(&next
)) {
9028 return errorResult();
9031 // |let| here can only be an Identifier, not a declaration. Give nicer
9032 // errors for declaration-looking typos.
9033 if (tt
== TokenKind::Let
) {
9034 bool forbiddenLetDeclaration
= false;
9036 if (next
== TokenKind::LeftBracket
) {
9037 // Enforce ExpressionStatement's 'let [' lookahead restriction.
9038 forbiddenLetDeclaration
= true;
9039 } else if (next
== TokenKind::LeftCurly
||
9040 TokenKindIsPossibleIdentifier(next
)) {
9041 // 'let {' and 'let foo' aren't completely forbidden, if ASI
9042 // causes 'let' to be the entire Statement. But if they're
9043 // same-line, we can aggressively give a better error message.
9045 // Note that this ignores 'yield' as TokenKind::Yield: we'll handle it
9046 // correctly but with a worse error message.
9047 TokenKind nextSameLine
;
9048 if (!tokenStream
.peekTokenSameLine(&nextSameLine
)) {
9049 return errorResult();
9052 MOZ_ASSERT(TokenKindIsPossibleIdentifier(nextSameLine
) ||
9053 nextSameLine
== TokenKind::LeftCurly
||
9054 nextSameLine
== TokenKind::Eol
);
9056 forbiddenLetDeclaration
= nextSameLine
!= TokenKind::Eol
;
9059 if (forbiddenLetDeclaration
) {
9060 error(JSMSG_FORBIDDEN_AS_STATEMENT
, "lexical declarations");
9061 return errorResult();
9063 } else if (tt
== TokenKind::Async
) {
9064 // Peek only on the same line: ExpressionStatement's lookahead
9065 // restriction is phrased as
9067 // [lookahead ∉ { '{',
9069 // async [no LineTerminator here] function,
9073 // meaning that code like this is valid:
9076 // async // ASI opportunity
9077 // function clownshoes() {}
9078 TokenKind maybeFunction
;
9079 if (!tokenStream
.peekTokenSameLine(&maybeFunction
)) {
9080 return errorResult();
9083 if (maybeFunction
== TokenKind::Function
) {
9084 error(JSMSG_FORBIDDEN_AS_STATEMENT
, "async function declarations");
9085 return errorResult();
9088 // Otherwise this |async| begins an ExpressionStatement or is a
9092 // NOTE: It's unfortunately allowed to have a label named 'let' in
9093 // non-strict code. 💯
9094 if (next
== TokenKind::Colon
) {
9095 return labeledStatement(yieldHandling
);
9098 return expressionStatement(yieldHandling
);
9101 case TokenKind::New
:
9102 return expressionStatement(yieldHandling
, PredictInvoked
);
9104 // IfStatement[?Yield, ?Return]
9106 return ifStatement(yieldHandling
);
9108 // BreakableStatement[?Yield, ?Return]
9110 // BreakableStatement[Yield, Return]:
9111 // IterationStatement[?Yield, ?Return]
9112 // SwitchStatement[?Yield, ?Return]
9114 return doWhileStatement(yieldHandling
);
9116 case TokenKind::While
:
9117 return whileStatement(yieldHandling
);
9119 case TokenKind::For
:
9120 return forStatement(yieldHandling
);
9122 case TokenKind::Switch
:
9123 return switchStatement(yieldHandling
);
9125 // ContinueStatement[?Yield]
9126 case TokenKind::Continue
:
9127 return continueStatement(yieldHandling
);
9129 // BreakStatement[?Yield]
9130 case TokenKind::Break
:
9131 return breakStatement(yieldHandling
);
9133 // [+Return] ReturnStatement[?Yield]
9134 case TokenKind::Return
:
9135 // The Return parameter is only used here, and the effect is easily
9136 // detected this way, so don't bother passing around an extra parameter
9138 if (!pc_
->allowReturn()) {
9139 error(JSMSG_BAD_RETURN_OR_YIELD
, "return");
9140 return errorResult();
9142 return returnStatement(yieldHandling
);
9144 // WithStatement[?Yield, ?Return]
9145 case TokenKind::With
:
9146 return withStatement(yieldHandling
);
9148 // LabelledStatement[?Yield, ?Return]
9149 // This is really handled by default and TokenKind::Yield cases above.
9151 // ThrowStatement[?Yield]
9152 case TokenKind::Throw
:
9153 return throwStatement(yieldHandling
);
9155 // TryStatement[?Yield, ?Return]
9156 case TokenKind::Try
:
9157 return tryStatement(yieldHandling
);
9159 // DebuggerStatement
9160 case TokenKind::Debugger
:
9161 return debuggerStatement();
9163 // |function| is forbidden by lookahead restriction (unless as child
9164 // statement of |if| or |else|, but Parser::consequentOrAlternative
9166 case TokenKind::Function
:
9167 error(JSMSG_FORBIDDEN_AS_STATEMENT
, "function declarations");
9168 return errorResult();
9170 // |class| is also forbidden by lookahead restriction.
9171 case TokenKind::Class
:
9172 error(JSMSG_FORBIDDEN_AS_STATEMENT
, "classes");
9173 return errorResult();
9175 // ImportDeclaration (only inside modules)
9176 case TokenKind::Import
:
9177 return importDeclarationOrImportExpr(yieldHandling
);
9179 // ExportDeclaration (only inside modules)
9180 case TokenKind::Export
:
9181 return exportDeclaration();
9183 // Miscellaneous error cases arguably better caught here than elsewhere.
9185 case TokenKind::Catch
:
9186 error(JSMSG_CATCH_WITHOUT_TRY
);
9187 return errorResult();
9189 case TokenKind::Finally
:
9190 error(JSMSG_FINALLY_WITHOUT_TRY
);
9191 return errorResult();
9193 // NOTE: default case handled in the ExpressionStatement section.
9197 template <class ParseHandler
, typename Unit
>
9198 typename
ParseHandler::NodeResult
9199 GeneralParser
<ParseHandler
, Unit
>::statementListItem(
9200 YieldHandling yieldHandling
, bool canHaveDirectives
/* = false */) {
9201 MOZ_ASSERT(checkOptionsCalled_
);
9203 AutoCheckRecursionLimit
recursion(this->fc_
);
9204 if (!recursion
.check(this->fc_
)) {
9205 return errorResult();
9209 if (!tokenStream
.getToken(&tt
, TokenStream::SlashIsRegExp
)) {
9210 return errorResult();
9214 // BlockStatement[?Yield, ?Return]
9215 case TokenKind::LeftCurly
:
9216 return blockStatement(yieldHandling
);
9218 // VariableStatement[?Yield]
9219 case TokenKind::Var
:
9220 return variableStatement(yieldHandling
);
9223 case TokenKind::Semi
:
9224 return handler_
.newEmptyStatement(pos());
9226 // ExpressionStatement[?Yield].
9228 // These should probably be handled by a single ExpressionStatement
9229 // function in a default, not split up this way.
9230 case TokenKind::String
:
9231 if (!canHaveDirectives
&&
9232 anyChars
.currentToken().atom() ==
9233 TaggedParserAtomIndex::WellKnown::use_asm_()) {
9234 if (!warning(JSMSG_USE_ASM_DIRECTIVE_FAIL
)) {
9235 return errorResult();
9238 return expressionStatement(yieldHandling
);
9240 case TokenKind::Yield
: {
9241 // Don't use a ternary operator here due to obscure linker issues
9242 // around using static consts in the arms of a ternary.
9244 if (yieldExpressionsSupported()) {
9245 modifier
= TokenStream::SlashIsRegExp
;
9247 modifier
= TokenStream::SlashIsDiv
;
9251 if (!tokenStream
.peekToken(&next
, modifier
)) {
9252 return errorResult();
9255 if (next
== TokenKind::Colon
) {
9256 return labeledStatement(yieldHandling
);
9259 return expressionStatement(yieldHandling
);
9263 // If we encounter an await in a module, and the module is not marked
9264 // as async, mark the module as async.
9265 if (tt
== TokenKind::Await
&& !pc_
->isAsync()) {
9266 if (pc_
->atModuleTopLevel()) {
9267 if (!options().topLevelAwait
) {
9268 error(JSMSG_TOP_LEVEL_AWAIT_NOT_SUPPORTED
);
9269 return errorResult();
9271 pc_
->sc()->asModuleContext()->setIsAsync();
9272 MOZ_ASSERT(pc_
->isAsync());
9276 // Avoid getting next token with SlashIsDiv.
9277 if (tt
== TokenKind::Await
&& pc_
->isAsync()) {
9278 return expressionStatement(yieldHandling
);
9281 if (!TokenKindIsPossibleIdentifier(tt
)) {
9282 return expressionStatement(yieldHandling
);
9286 if (!tokenStream
.peekToken(&next
)) {
9287 return errorResult();
9290 if (tt
== TokenKind::Let
&& nextTokenContinuesLetDeclaration(next
)) {
9291 return lexicalDeclaration(yieldHandling
, DeclarationKind::Let
);
9294 if (tt
== TokenKind::Async
) {
9295 TokenKind nextSameLine
= TokenKind::Eof
;
9296 if (!tokenStream
.peekTokenSameLine(&nextSameLine
)) {
9297 return errorResult();
9299 if (nextSameLine
== TokenKind::Function
) {
9300 uint32_t toStringStart
= pos().begin
;
9301 tokenStream
.consumeKnownToken(TokenKind::Function
);
9302 return functionStmt(toStringStart
, yieldHandling
, NameRequired
,
9303 FunctionAsyncKind::AsyncFunction
);
9307 if (next
== TokenKind::Colon
) {
9308 return labeledStatement(yieldHandling
);
9311 return expressionStatement(yieldHandling
);
9314 case TokenKind::New
:
9315 return expressionStatement(yieldHandling
, PredictInvoked
);
9317 // IfStatement[?Yield, ?Return]
9319 return ifStatement(yieldHandling
);
9321 // BreakableStatement[?Yield, ?Return]
9323 // BreakableStatement[Yield, Return]:
9324 // IterationStatement[?Yield, ?Return]
9325 // SwitchStatement[?Yield, ?Return]
9327 return doWhileStatement(yieldHandling
);
9329 case TokenKind::While
:
9330 return whileStatement(yieldHandling
);
9332 case TokenKind::For
:
9333 return forStatement(yieldHandling
);
9335 case TokenKind::Switch
:
9336 return switchStatement(yieldHandling
);
9338 // ContinueStatement[?Yield]
9339 case TokenKind::Continue
:
9340 return continueStatement(yieldHandling
);
9342 // BreakStatement[?Yield]
9343 case TokenKind::Break
:
9344 return breakStatement(yieldHandling
);
9346 // [+Return] ReturnStatement[?Yield]
9347 case TokenKind::Return
:
9348 // The Return parameter is only used here, and the effect is easily
9349 // detected this way, so don't bother passing around an extra parameter
9351 if (!pc_
->allowReturn()) {
9352 error(JSMSG_BAD_RETURN_OR_YIELD
, "return");
9353 return errorResult();
9355 return returnStatement(yieldHandling
);
9357 // WithStatement[?Yield, ?Return]
9358 case TokenKind::With
:
9359 return withStatement(yieldHandling
);
9361 // LabelledStatement[?Yield, ?Return]
9362 // This is really handled by default and TokenKind::Yield cases above.
9364 // ThrowStatement[?Yield]
9365 case TokenKind::Throw
:
9366 return throwStatement(yieldHandling
);
9368 // TryStatement[?Yield, ?Return]
9369 case TokenKind::Try
:
9370 return tryStatement(yieldHandling
);
9372 // DebuggerStatement
9373 case TokenKind::Debugger
:
9374 return debuggerStatement();
9376 // Declaration[Yield]:
9378 // HoistableDeclaration[?Yield, ~Default]
9379 case TokenKind::Function
:
9380 return functionStmt(pos().begin
, yieldHandling
, NameRequired
);
9382 // DecoratorList[?Yield, ?Await] opt ClassDeclaration[?Yield, ~Default]
9383 #ifdef ENABLE_DECORATORS
9385 return classDefinition(yieldHandling
, ClassStatement
, NameRequired
);
9388 case TokenKind::Class
:
9389 return classDefinition(yieldHandling
, ClassStatement
, NameRequired
);
9391 // LexicalDeclaration[In, ?Yield]
9392 // LetOrConst BindingList[?In, ?Yield]
9393 case TokenKind::Const
:
9394 // [In] is the default behavior, because for-loops specially parse
9395 // their heads to handle |in| in this situation.
9396 return lexicalDeclaration(yieldHandling
, DeclarationKind::Const
);
9398 // ImportDeclaration (only inside modules)
9399 case TokenKind::Import
:
9400 return importDeclarationOrImportExpr(yieldHandling
);
9402 // ExportDeclaration (only inside modules)
9403 case TokenKind::Export
:
9404 return exportDeclaration();
9406 // Miscellaneous error cases arguably better caught here than elsewhere.
9408 case TokenKind::Catch
:
9409 error(JSMSG_CATCH_WITHOUT_TRY
);
9410 return errorResult();
9412 case TokenKind::Finally
:
9413 error(JSMSG_FINALLY_WITHOUT_TRY
);
9414 return errorResult();
9416 // NOTE: default case handled in the ExpressionStatement section.
9420 template <class ParseHandler
, typename Unit
>
9421 typename
ParseHandler::NodeResult GeneralParser
<ParseHandler
, Unit
>::expr(
9422 InHandling inHandling
, YieldHandling yieldHandling
,
9423 TripledotHandling tripledotHandling
,
9424 PossibleError
* possibleError
/* = nullptr */,
9425 InvokedPrediction invoked
/* = PredictUninvoked */) {
9427 MOZ_TRY_VAR(pn
, assignExpr(inHandling
, yieldHandling
, tripledotHandling
,
9428 possibleError
, invoked
));
9431 if (!tokenStream
.matchToken(&matched
, TokenKind::Comma
,
9432 TokenStream::SlashIsRegExp
)) {
9433 return errorResult();
9440 MOZ_TRY_VAR(seq
, handler_
.newCommaExpressionList(pn
));
9442 // Trailing comma before the closing parenthesis is valid in an arrow
9443 // function parameters list: `(a, b, ) => body`. Check if we are
9444 // directly under CoverParenthesizedExpressionAndArrowParameterList,
9445 // and the next two tokens are closing parenthesis and arrow. If all
9446 // are present allow the trailing comma.
9447 if (tripledotHandling
== TripledotAllowed
) {
9449 if (!tokenStream
.peekToken(&tt
, TokenStream::SlashIsRegExp
)) {
9450 return errorResult();
9453 if (tt
== TokenKind::RightParen
) {
9454 tokenStream
.consumeKnownToken(TokenKind::RightParen
,
9455 TokenStream::SlashIsRegExp
);
9457 if (!tokenStream
.peekToken(&tt
)) {
9458 return errorResult();
9460 if (tt
!= TokenKind::Arrow
) {
9461 error(JSMSG_UNEXPECTED_TOKEN
, "expression",
9462 TokenKindToDesc(TokenKind::RightParen
));
9463 return errorResult();
9466 anyChars
.ungetToken(); // put back right paren
9471 // Additional calls to assignExpr should not reuse the possibleError
9472 // which had been passed into the function. Otherwise we would lose
9473 // information needed to determine whether or not we're dealing with
9474 // a non-recoverable situation.
9475 PossibleError
possibleErrorInner(*this);
9476 MOZ_TRY_VAR(pn
, assignExpr(inHandling
, yieldHandling
, tripledotHandling
,
9477 &possibleErrorInner
));
9479 if (!possibleError
) {
9480 // Report any pending expression error.
9481 if (!possibleErrorInner
.checkForExpressionError()) {
9482 return errorResult();
9485 possibleErrorInner
.transferErrorsTo(possibleError
);
9488 handler_
.addList(seq
, pn
);
9490 if (!tokenStream
.matchToken(&matched
, TokenKind::Comma
,
9491 TokenStream::SlashIsRegExp
)) {
9492 return errorResult();
9501 static ParseNodeKind
BinaryOpTokenKindToParseNodeKind(TokenKind tok
) {
9502 MOZ_ASSERT(TokenKindIsBinaryOp(tok
));
9503 return ParseNodeKind(size_t(ParseNodeKind::BinOpFirst
) +
9504 (size_t(tok
) - size_t(TokenKind::BinOpFirst
)));
9507 // This list must be kept in the same order in several places:
9508 // - The binary operators in ParseNode.h ,
9509 // - the binary operators in TokenKind.h
9510 // - the JSOp code list in BytecodeEmitter.cpp
9511 static const int PrecedenceTable
[] = {
9512 1, /* ParseNodeKind::Coalesce */
9513 2, /* ParseNodeKind::Or */
9514 3, /* ParseNodeKind::And */
9515 4, /* ParseNodeKind::BitOr */
9516 5, /* ParseNodeKind::BitXor */
9517 6, /* ParseNodeKind::BitAnd */
9518 7, /* ParseNodeKind::StrictEq */
9519 7, /* ParseNodeKind::Eq */
9520 7, /* ParseNodeKind::StrictNe */
9521 7, /* ParseNodeKind::Ne */
9522 8, /* ParseNodeKind::Lt */
9523 8, /* ParseNodeKind::Le */
9524 8, /* ParseNodeKind::Gt */
9525 8, /* ParseNodeKind::Ge */
9526 8, /* ParseNodeKind::InstanceOf */
9527 8, /* ParseNodeKind::In */
9528 8, /* ParseNodeKind::PrivateIn */
9529 9, /* ParseNodeKind::Lsh */
9530 9, /* ParseNodeKind::Rsh */
9531 9, /* ParseNodeKind::Ursh */
9532 10, /* ParseNodeKind::Add */
9533 10, /* ParseNodeKind::Sub */
9534 11, /* ParseNodeKind::Star */
9535 11, /* ParseNodeKind::Div */
9536 11, /* ParseNodeKind::Mod */
9537 12 /* ParseNodeKind::Pow */
9540 static const int PRECEDENCE_CLASSES
= 12;
9542 static int Precedence(ParseNodeKind pnk
) {
9543 // Everything binds tighter than ParseNodeKind::Limit, because we want
9544 // to reduce all nodes to a single node when we reach a token that is not
9545 // another binary operator.
9546 if (pnk
== ParseNodeKind::Limit
) {
9550 MOZ_ASSERT(pnk
>= ParseNodeKind::BinOpFirst
);
9551 MOZ_ASSERT(pnk
<= ParseNodeKind::BinOpLast
);
9552 return PrecedenceTable
[size_t(pnk
) - size_t(ParseNodeKind::BinOpFirst
)];
9555 enum class EnforcedParentheses
: uint8_t { CoalesceExpr
, AndOrExpr
, None
};
9557 template <class ParseHandler
, typename Unit
>
9558 MOZ_ALWAYS_INLINE typename
ParseHandler::NodeResult
9559 GeneralParser
<ParseHandler
, Unit
>::orExpr(InHandling inHandling
,
9560 YieldHandling yieldHandling
,
9561 TripledotHandling tripledotHandling
,
9562 PossibleError
* possibleError
,
9563 InvokedPrediction invoked
) {
9564 // Shift-reduce parser for the binary operator part of the JS expression
9567 // Conceptually there's just one stack, a stack of pairs (lhs, op).
9568 // It's implemented using two separate arrays, though.
9569 Node nodeStack
[PRECEDENCE_CLASSES
];
9570 ParseNodeKind kindStack
[PRECEDENCE_CLASSES
];
9573 EnforcedParentheses unparenthesizedExpression
= EnforcedParentheses::None
;
9576 pn
, unaryExpr(yieldHandling
, tripledotHandling
, possibleError
, invoked
,
9577 PrivateNameHandling::PrivateNameAllowed
));
9579 // If a binary operator follows, consume it and compute the
9580 // corresponding operator.
9582 if (!tokenStream
.getToken(&tok
)) {
9583 return errorResult();
9586 // Ensure that if we have a private name lhs we are legally constructing a
9587 // `#x in obj` expessions:
9588 if (handler_
.isPrivateName(pn
)) {
9589 if (tok
!= TokenKind::In
|| inHandling
!= InAllowed
) {
9590 error(JSMSG_ILLEGAL_PRIVATE_NAME
);
9591 return errorResult();
9596 if (tok
== TokenKind::In
? inHandling
== InAllowed
9597 : TokenKindIsBinaryOp(tok
)) {
9598 // We're definitely not in a destructuring context, so report any
9599 // pending expression error now.
9600 if (possibleError
&& !possibleError
->checkForExpressionError()) {
9601 return errorResult();
9604 bool isErgonomicBrandCheck
= false;
9606 // Report an error for unary expressions on the LHS of **.
9607 case TokenKind::Pow
:
9608 if (handler_
.isUnparenthesizedUnaryExpression(pn
)) {
9609 error(JSMSG_BAD_POW_LEFTSIDE
);
9610 return errorResult();
9615 case TokenKind::And
:
9616 // In the case that the `??` is on the left hand side of the
9617 // expression: Disallow Mixing of ?? and other logical operators (||
9618 // and &&) unless one expression is parenthesized
9619 if (unparenthesizedExpression
== EnforcedParentheses::CoalesceExpr
) {
9620 error(JSMSG_BAD_COALESCE_MIXING
);
9621 return errorResult();
9623 // If we have not detected a mixing error at this point, record that
9624 // we have an unparenthesized expression, in case we have one later.
9625 unparenthesizedExpression
= EnforcedParentheses::AndOrExpr
;
9628 case TokenKind::Coalesce
:
9629 if (unparenthesizedExpression
== EnforcedParentheses::AndOrExpr
) {
9630 error(JSMSG_BAD_COALESCE_MIXING
);
9631 return errorResult();
9633 // If we have not detected a mixing error at this point, record that
9634 // we have an unparenthesized expression, in case we have one later.
9635 unparenthesizedExpression
= EnforcedParentheses::CoalesceExpr
;
9639 // if the LHS is a private name, and the operator is In,
9640 // ensure we're construcing an ergonomic brand check of
9641 // '#x in y', rather than having a higher precedence operator
9642 // like + cause a different reduction, such as
9644 if (handler_
.isPrivateName(pn
)) {
9645 if (depth
> 0 && Precedence(kindStack
[depth
- 1]) >=
9646 Precedence(ParseNodeKind::InExpr
)) {
9647 error(JSMSG_INVALID_PRIVATE_NAME_PRECEDENCE
);
9648 return errorResult();
9651 isErgonomicBrandCheck
= true;
9656 // do nothing in other cases
9660 if (isErgonomicBrandCheck
) {
9661 pnk
= ParseNodeKind::PrivateInExpr
;
9663 pnk
= BinaryOpTokenKindToParseNodeKind(tok
);
9667 tok
= TokenKind::Eof
;
9668 pnk
= ParseNodeKind::Limit
;
9671 // From this point on, destructuring defaults are definitely an error.
9672 possibleError
= nullptr;
9674 // If pnk has precedence less than or equal to another operator on the
9675 // stack, reduce. This combines nodes on the stack until we form the
9676 // actual lhs of pnk.
9678 // The >= in this condition works because it is appendOrCreateList's
9679 // job to decide if the operator in question is left- or
9680 // right-associative, and build the corresponding tree.
9681 while (depth
> 0 && Precedence(kindStack
[depth
- 1]) >= Precedence(pnk
)) {
9683 ParseNodeKind combiningPnk
= kindStack
[depth
];
9684 MOZ_TRY_VAR(pn
, handler_
.appendOrCreateList(combiningPnk
,
9685 nodeStack
[depth
], pn
, pc_
));
9688 if (pnk
== ParseNodeKind::Limit
) {
9692 nodeStack
[depth
] = pn
;
9693 kindStack
[depth
] = pnk
;
9695 MOZ_ASSERT(depth
<= PRECEDENCE_CLASSES
);
9698 anyChars
.ungetToken();
9700 // Had the next token been a Div, we would have consumed it. So there's no
9701 // ambiguity if we later (after ASI) re-get this token with SlashIsRegExp.
9702 anyChars
.allowGettingNextTokenWithSlashIsRegExp();
9704 MOZ_ASSERT(depth
== 0);
9708 template <class ParseHandler
, typename Unit
>
9709 MOZ_ALWAYS_INLINE typename
ParseHandler::NodeResult
9710 GeneralParser
<ParseHandler
, Unit
>::condExpr(InHandling inHandling
,
9711 YieldHandling yieldHandling
,
9712 TripledotHandling tripledotHandling
,
9713 PossibleError
* possibleError
,
9714 InvokedPrediction invoked
) {
9716 MOZ_TRY_VAR(condition
, orExpr(inHandling
, yieldHandling
, tripledotHandling
,
9717 possibleError
, invoked
));
9720 if (!tokenStream
.matchToken(&matched
, TokenKind::Hook
,
9721 TokenStream::SlashIsInvalid
)) {
9722 return errorResult();
9729 MOZ_TRY_VAR(thenExpr
,
9730 assignExpr(InAllowed
, yieldHandling
, TripledotProhibited
));
9732 if (!mustMatchToken(TokenKind::Colon
, JSMSG_COLON_IN_COND
)) {
9733 return errorResult();
9737 MOZ_TRY_VAR(elseExpr
,
9738 assignExpr(inHandling
, yieldHandling
, TripledotProhibited
));
9740 return handler_
.newConditional(condition
, thenExpr
, elseExpr
);
9743 template <class ParseHandler
, typename Unit
>
9744 typename
ParseHandler::NodeResult GeneralParser
<ParseHandler
, Unit
>::assignExpr(
9745 InHandling inHandling
, YieldHandling yieldHandling
,
9746 TripledotHandling tripledotHandling
,
9747 PossibleError
* possibleError
/* = nullptr */,
9748 InvokedPrediction invoked
/* = PredictUninvoked */) {
9749 AutoCheckRecursionLimit
recursion(this->fc_
);
9750 if (!recursion
.check(this->fc_
)) {
9751 return errorResult();
9754 // It's very common at this point to have a "detectably simple" expression,
9755 // i.e. a name/number/string token followed by one of the following tokens
9756 // that obviously isn't part of an expression: , ; : ) ] }
9758 // (In Parsemark this happens 81.4% of the time; in code with large
9759 // numeric arrays, such as some Kraken benchmarks, it happens more often.)
9761 // In such cases, we can avoid the full expression parsing route through
9762 // assignExpr(), condExpr(), orExpr(), unaryExpr(), memberExpr(), and
9765 TokenKind firstToken
;
9766 if (!tokenStream
.getToken(&firstToken
, TokenStream::SlashIsRegExp
)) {
9767 return errorResult();
9770 TokenPos exprPos
= pos();
9774 // This only handles identifiers that *never* have special meaning anywhere
9775 // in the language. Contextual keywords, reserved words in strict mode,
9776 // and other hard cases are handled outside this fast path.
9777 if (firstToken
== TokenKind::Name
) {
9778 if (!tokenStream
.nextTokenEndsExpr(&endsExpr
)) {
9779 return errorResult();
9782 TaggedParserAtomIndex name
= identifierReference(yieldHandling
);
9784 return errorResult();
9787 return identifierReference(name
);
9791 if (firstToken
== TokenKind::Number
) {
9792 if (!tokenStream
.nextTokenEndsExpr(&endsExpr
)) {
9793 return errorResult();
9796 return newNumber(anyChars
.currentToken());
9800 if (firstToken
== TokenKind::String
) {
9801 if (!tokenStream
.nextTokenEndsExpr(&endsExpr
)) {
9802 return errorResult();
9805 return stringLiteral();
9809 if (firstToken
== TokenKind::Yield
&& yieldExpressionsSupported()) {
9810 return yieldExpression(inHandling
);
9813 bool maybeAsyncArrow
= false;
9814 if (firstToken
== TokenKind::Async
) {
9815 TokenKind nextSameLine
= TokenKind::Eof
;
9816 if (!tokenStream
.peekTokenSameLine(&nextSameLine
)) {
9817 return errorResult();
9820 if (TokenKindIsPossibleIdentifier(nextSameLine
)) {
9821 maybeAsyncArrow
= true;
9825 anyChars
.ungetToken();
9827 // Save the tokenizer state in case we find an arrow function and have to
9829 Position
start(tokenStream
);
9830 auto ghostToken
= this->compilationState_
.getPosition();
9832 PossibleError
possibleErrorInner(*this);
9834 TokenKind tokenAfterLHS
;
9836 if (maybeAsyncArrow
) {
9837 tokenStream
.consumeKnownToken(TokenKind::Async
, TokenStream::SlashIsRegExp
);
9839 TokenKind tokenAfterAsync
;
9840 if (!tokenStream
.getToken(&tokenAfterAsync
)) {
9841 return errorResult();
9843 MOZ_ASSERT(TokenKindIsPossibleIdentifier(tokenAfterAsync
));
9845 // Check yield validity here.
9846 TaggedParserAtomIndex name
= bindingIdentifier(yieldHandling
);
9848 return errorResult();
9851 if (!tokenStream
.peekToken(&tokenAfterLHS
, TokenStream::SlashIsRegExp
)) {
9852 return errorResult();
9855 isArrow
= tokenAfterLHS
== TokenKind::Arrow
;
9857 // |async [no LineTerminator] of| without being followed by => is only
9858 // possible in for-await-of loops, e.g. |for await (async of [])|. Pretend
9859 // the |async| token was parsed an identifier reference and then proceed
9860 // with the rest of this function.
9862 anyChars
.ungetToken(); // unget the binding identifier
9864 // The next token is guaranteed to never be a Div (, because it's an
9865 // identifier), so it's okay to re-get the token with SlashIsRegExp.
9866 anyChars
.allowGettingNextTokenWithSlashIsRegExp();
9868 TaggedParserAtomIndex asyncName
= identifierReference(yieldHandling
);
9870 return errorResult();
9873 MOZ_TRY_VAR(lhs
, identifierReference(asyncName
));
9876 MOZ_TRY_VAR(lhs
, condExpr(inHandling
, yieldHandling
, tripledotHandling
,
9877 &possibleErrorInner
, invoked
));
9879 // Use SlashIsRegExp here because the ConditionalExpression parsed above
9880 // could be the entirety of this AssignmentExpression, and then ASI
9881 // permits this token to be a regular expression.
9882 if (!tokenStream
.peekToken(&tokenAfterLHS
, TokenStream::SlashIsRegExp
)) {
9883 return errorResult();
9886 isArrow
= tokenAfterLHS
== TokenKind::Arrow
;
9890 // Rewind to reparse as an arrow function.
9892 // Note: We do not call CompilationState::rewind here because parsing
9893 // during delazification will see the same rewind and need the same sequence
9894 // of inner functions to skip over.
9895 // Instead, we mark inner functions as "ghost".
9897 // See GHOST_FUNCTION in FunctionFlags.h for more details.
9898 tokenStream
.rewind(start
);
9899 this->compilationState_
.markGhost(ghostToken
);
9902 if (!tokenStream
.getToken(&next
, TokenStream::SlashIsRegExp
)) {
9903 return errorResult();
9905 TokenPos startPos
= pos();
9906 uint32_t toStringStart
= startPos
.begin
;
9907 anyChars
.ungetToken();
9909 FunctionAsyncKind asyncKind
= FunctionAsyncKind::SyncFunction
;
9911 if (next
== TokenKind::Async
) {
9912 tokenStream
.consumeKnownToken(next
, TokenStream::SlashIsRegExp
);
9914 TokenKind nextSameLine
= TokenKind::Eof
;
9915 if (!tokenStream
.peekTokenSameLine(&nextSameLine
)) {
9916 return errorResult();
9919 // The AsyncArrowFunction production are
9920 // async [no LineTerminator here] AsyncArrowBindingIdentifier ...
9921 // async [no LineTerminator here] ArrowFormalParameters ...
9922 if (TokenKindIsPossibleIdentifier(nextSameLine
) ||
9923 nextSameLine
== TokenKind::LeftParen
) {
9924 asyncKind
= FunctionAsyncKind::AsyncFunction
;
9926 anyChars
.ungetToken();
9930 FunctionSyntaxKind syntaxKind
= FunctionSyntaxKind::Arrow
;
9931 FunctionNodeType funNode
;
9932 MOZ_TRY_VAR(funNode
, handler_
.newFunction(syntaxKind
, startPos
));
9934 return functionDefinition(funNode
, toStringStart
, inHandling
, yieldHandling
,
9935 TaggedParserAtomIndex::null(), syntaxKind
,
9936 GeneratorKind::NotGenerator
, asyncKind
);
9940 tokenStream
.getToken(&tokenAfterLHS
, TokenStream::SlashIsRegExp
));
9943 switch (tokenAfterLHS
) {
9944 case TokenKind::Assign
:
9945 kind
= ParseNodeKind::AssignExpr
;
9947 case TokenKind::AddAssign
:
9948 kind
= ParseNodeKind::AddAssignExpr
;
9950 case TokenKind::SubAssign
:
9951 kind
= ParseNodeKind::SubAssignExpr
;
9953 case TokenKind::CoalesceAssign
:
9954 kind
= ParseNodeKind::CoalesceAssignExpr
;
9956 case TokenKind::OrAssign
:
9957 kind
= ParseNodeKind::OrAssignExpr
;
9959 case TokenKind::AndAssign
:
9960 kind
= ParseNodeKind::AndAssignExpr
;
9962 case TokenKind::BitOrAssign
:
9963 kind
= ParseNodeKind::BitOrAssignExpr
;
9965 case TokenKind::BitXorAssign
:
9966 kind
= ParseNodeKind::BitXorAssignExpr
;
9968 case TokenKind::BitAndAssign
:
9969 kind
= ParseNodeKind::BitAndAssignExpr
;
9971 case TokenKind::LshAssign
:
9972 kind
= ParseNodeKind::LshAssignExpr
;
9974 case TokenKind::RshAssign
:
9975 kind
= ParseNodeKind::RshAssignExpr
;
9977 case TokenKind::UrshAssign
:
9978 kind
= ParseNodeKind::UrshAssignExpr
;
9980 case TokenKind::MulAssign
:
9981 kind
= ParseNodeKind::MulAssignExpr
;
9983 case TokenKind::DivAssign
:
9984 kind
= ParseNodeKind::DivAssignExpr
;
9986 case TokenKind::ModAssign
:
9987 kind
= ParseNodeKind::ModAssignExpr
;
9989 case TokenKind::PowAssign
:
9990 kind
= ParseNodeKind::PowAssignExpr
;
9994 MOZ_ASSERT(!anyChars
.isCurrentTokenAssignment());
9995 if (!possibleError
) {
9996 if (!possibleErrorInner
.checkForExpressionError()) {
9997 return errorResult();
10000 possibleErrorInner
.transferErrorsTo(possibleError
);
10003 anyChars
.ungetToken();
10007 // Verify the left-hand side expression doesn't have a forbidden form.
10008 if (handler_
.isUnparenthesizedDestructuringPattern(lhs
)) {
10009 if (kind
!= ParseNodeKind::AssignExpr
) {
10010 error(JSMSG_BAD_DESTRUCT_ASS
);
10011 return errorResult();
10014 if (!possibleErrorInner
.checkForDestructuringErrorOrWarning()) {
10015 return errorResult();
10017 } else if (handler_
.isName(lhs
)) {
10018 if (const char* chars
= nameIsArgumentsOrEval(lhs
)) {
10019 // |chars| is "arguments" or "eval" here.
10020 if (!strictModeErrorAt(exprPos
.begin
, JSMSG_BAD_STRICT_ASSIGN
, chars
)) {
10021 return errorResult();
10024 } else if (handler_
.isPropertyOrPrivateMemberAccess(lhs
)) {
10025 // Permitted: no additional testing/fixup needed.
10026 } else if (handler_
.isFunctionCall(lhs
)) {
10027 // We don't have to worry about backward compatibility issues with the new
10028 // compound assignment operators, so we always throw here. Also that way we
10029 // don't have to worry if |f() &&= expr| should always throw an error or
10030 // only if |f()| returns true.
10031 if (kind
== ParseNodeKind::CoalesceAssignExpr
||
10032 kind
== ParseNodeKind::OrAssignExpr
||
10033 kind
== ParseNodeKind::AndAssignExpr
) {
10034 errorAt(exprPos
.begin
, JSMSG_BAD_LEFTSIDE_OF_ASS
);
10035 return errorResult();
10038 if (!strictModeErrorAt(exprPos
.begin
, JSMSG_BAD_LEFTSIDE_OF_ASS
)) {
10039 return errorResult();
10042 if (possibleError
) {
10043 possibleError
->setPendingDestructuringErrorAt(exprPos
,
10044 JSMSG_BAD_DESTRUCT_TARGET
);
10047 errorAt(exprPos
.begin
, JSMSG_BAD_LEFTSIDE_OF_ASS
);
10048 return errorResult();
10051 if (!possibleErrorInner
.checkForExpressionError()) {
10052 return errorResult();
10056 MOZ_TRY_VAR(rhs
, assignExpr(inHandling
, yieldHandling
, TripledotProhibited
));
10058 return handler_
.newAssignment(kind
, lhs
, rhs
);
10061 template <class ParseHandler
>
10062 const char* PerHandlerParser
<ParseHandler
>::nameIsArgumentsOrEval(Node node
) {
10063 MOZ_ASSERT(handler_
.isName(node
),
10064 "must only call this function on known names");
10066 if (handler_
.isEvalName(node
)) {
10069 if (handler_
.isArgumentsName(node
)) {
10070 return "arguments";
10075 template <class ParseHandler
, typename Unit
>
10076 bool GeneralParser
<ParseHandler
, Unit
>::checkIncDecOperand(
10077 Node operand
, uint32_t operandOffset
) {
10078 if (handler_
.isName(operand
)) {
10079 if (const char* chars
= nameIsArgumentsOrEval(operand
)) {
10080 if (!strictModeErrorAt(operandOffset
, JSMSG_BAD_STRICT_ASSIGN
, chars
)) {
10084 } else if (handler_
.isPropertyOrPrivateMemberAccess(operand
)) {
10085 // Permitted: no additional testing/fixup needed.
10086 } else if (handler_
.isFunctionCall(operand
)) {
10087 // Assignment to function calls is forbidden in ES6. We're still
10088 // somewhat concerned about sites using this in dead code, so forbid it
10089 // only in strict mode code.
10090 if (!strictModeErrorAt(operandOffset
, JSMSG_BAD_INCOP_OPERAND
)) {
10094 errorAt(operandOffset
, JSMSG_BAD_INCOP_OPERAND
);
10100 template <class ParseHandler
, typename Unit
>
10101 typename
ParseHandler::UnaryNodeResult
10102 GeneralParser
<ParseHandler
, Unit
>::unaryOpExpr(YieldHandling yieldHandling
,
10103 ParseNodeKind kind
,
10106 MOZ_TRY_VAR(kid
, unaryExpr(yieldHandling
, TripledotProhibited
));
10107 return handler_
.newUnary(kind
, begin
, kid
);
10110 template <class ParseHandler
, typename Unit
>
10111 typename
ParseHandler::NodeResult
10112 GeneralParser
<ParseHandler
, Unit
>::optionalExpr(
10113 YieldHandling yieldHandling
, TripledotHandling tripledotHandling
,
10114 TokenKind tt
, PossibleError
* possibleError
/* = nullptr */,
10115 InvokedPrediction invoked
/* = PredictUninvoked */) {
10116 AutoCheckRecursionLimit
recursion(this->fc_
);
10117 if (!recursion
.check(this->fc_
)) {
10118 return errorResult();
10121 uint32_t begin
= pos().begin
;
10125 memberExpr(yieldHandling
, tripledotHandling
, tt
,
10126 /* allowCallSyntax = */ true, possibleError
, invoked
));
10128 if (!tokenStream
.peekToken(&tt
, TokenStream::SlashIsDiv
)) {
10129 return errorResult();
10132 if (tt
!= TokenKind::OptionalChain
) {
10137 if (!tokenStream
.getToken(&tt
)) {
10138 return errorResult();
10141 if (tt
== TokenKind::Eof
) {
10142 anyChars
.ungetToken();
10147 if (tt
== TokenKind::OptionalChain
) {
10148 if (!tokenStream
.getToken(&tt
)) {
10149 return errorResult();
10151 if (TokenKindIsPossibleIdentifierName(tt
)) {
10152 MOZ_TRY_VAR(nextMember
,
10153 memberPropertyAccess(lhs
, OptionalKind::Optional
));
10154 } else if (tt
== TokenKind::PrivateName
) {
10155 MOZ_TRY_VAR(nextMember
,
10156 memberPrivateAccess(lhs
, OptionalKind::Optional
));
10157 } else if (tt
== TokenKind::LeftBracket
) {
10158 MOZ_TRY_VAR(nextMember
, memberElemAccess(lhs
, yieldHandling
,
10159 OptionalKind::Optional
));
10160 } else if (tt
== TokenKind::LeftParen
) {
10161 MOZ_TRY_VAR(nextMember
,
10162 memberCall(tt
, lhs
, yieldHandling
, possibleError
,
10163 OptionalKind::Optional
));
10165 error(JSMSG_NAME_AFTER_DOT
);
10166 return errorResult();
10168 } else if (tt
== TokenKind::Dot
) {
10169 if (!tokenStream
.getToken(&tt
)) {
10170 return errorResult();
10172 if (TokenKindIsPossibleIdentifierName(tt
)) {
10173 MOZ_TRY_VAR(nextMember
, memberPropertyAccess(lhs
));
10174 } else if (tt
== TokenKind::PrivateName
) {
10175 MOZ_TRY_VAR(nextMember
, memberPrivateAccess(lhs
));
10177 error(JSMSG_NAME_AFTER_DOT
);
10178 return errorResult();
10180 } else if (tt
== TokenKind::LeftBracket
) {
10181 MOZ_TRY_VAR(nextMember
, memberElemAccess(lhs
, yieldHandling
));
10182 } else if (tt
== TokenKind::LeftParen
) {
10183 MOZ_TRY_VAR(nextMember
,
10184 memberCall(tt
, lhs
, yieldHandling
, possibleError
));
10185 } else if (tt
== TokenKind::TemplateHead
||
10186 tt
== TokenKind::NoSubsTemplate
) {
10187 error(JSMSG_BAD_OPTIONAL_TEMPLATE
);
10188 return errorResult();
10190 anyChars
.ungetToken();
10194 MOZ_ASSERT(nextMember
);
10198 return handler_
.newOptionalChain(begin
, lhs
);
10201 template <class ParseHandler
, typename Unit
>
10202 typename
ParseHandler::NodeResult GeneralParser
<ParseHandler
, Unit
>::unaryExpr(
10203 YieldHandling yieldHandling
, TripledotHandling tripledotHandling
,
10204 PossibleError
* possibleError
/* = nullptr */,
10205 InvokedPrediction invoked
/* = PredictUninvoked */,
10206 PrivateNameHandling privateNameHandling
/* = PrivateNameProhibited */) {
10207 AutoCheckRecursionLimit
recursion(this->fc_
);
10208 if (!recursion
.check(this->fc_
)) {
10209 return errorResult();
10213 if (!tokenStream
.getToken(&tt
, TokenStream::SlashIsRegExp
)) {
10214 return errorResult();
10216 uint32_t begin
= pos().begin
;
10218 case TokenKind::Void
:
10219 return unaryOpExpr(yieldHandling
, ParseNodeKind::VoidExpr
, begin
);
10220 case TokenKind::Not
:
10221 return unaryOpExpr(yieldHandling
, ParseNodeKind::NotExpr
, begin
);
10222 case TokenKind::BitNot
:
10223 return unaryOpExpr(yieldHandling
, ParseNodeKind::BitNotExpr
, begin
);
10224 case TokenKind::Add
:
10225 return unaryOpExpr(yieldHandling
, ParseNodeKind::PosExpr
, begin
);
10226 case TokenKind::Sub
:
10227 return unaryOpExpr(yieldHandling
, ParseNodeKind::NegExpr
, begin
);
10229 case TokenKind::TypeOf
: {
10230 // The |typeof| operator is specially parsed to distinguish its
10231 // application to a name, from its application to a non-name
10234 // // Looks up the name, doesn't find it and so evaluates to
10236 // assertEq(typeof nonExistentName, "undefined");
10238 // // Evaluates expression, triggering a runtime ReferenceError for
10239 // // the undefined name.
10240 // typeof (1, nonExistentName);
10242 MOZ_TRY_VAR(kid
, unaryExpr(yieldHandling
, TripledotProhibited
));
10244 return handler_
.newTypeof(begin
, kid
);
10247 case TokenKind::Inc
:
10248 case TokenKind::Dec
: {
10250 if (!tokenStream
.getToken(&tt2
, TokenStream::SlashIsRegExp
)) {
10251 return errorResult();
10254 uint32_t operandOffset
= pos().begin
;
10256 MOZ_TRY_VAR(operand
,
10257 optionalExpr(yieldHandling
, TripledotProhibited
, tt2
));
10258 if (!checkIncDecOperand(operand
, operandOffset
)) {
10259 return errorResult();
10261 ParseNodeKind pnk
= (tt
== TokenKind::Inc
)
10262 ? ParseNodeKind::PreIncrementExpr
10263 : ParseNodeKind::PreDecrementExpr
;
10264 return handler_
.newUpdate(pnk
, begin
, operand
);
10266 case TokenKind::PrivateName
: {
10267 if (privateNameHandling
== PrivateNameHandling::PrivateNameAllowed
) {
10268 TaggedParserAtomIndex field
= anyChars
.currentName();
10269 return privateNameReference(field
);
10271 error(JSMSG_INVALID_PRIVATE_NAME_IN_UNARY_EXPR
);
10272 return errorResult();
10275 case TokenKind::Delete
: {
10276 uint32_t exprOffset
;
10277 if (!tokenStream
.peekOffset(&exprOffset
, TokenStream::SlashIsRegExp
)) {
10278 return errorResult();
10282 MOZ_TRY_VAR(expr
, unaryExpr(yieldHandling
, TripledotProhibited
));
10284 // Per spec, deleting most unary expressions is valid -- it simply
10285 // returns true -- except for two cases:
10286 // 1. `var x; ...; delete x` is a syntax error in strict mode.
10287 // 2. Private fields cannot be deleted.
10288 if (handler_
.isName(expr
)) {
10289 if (!strictModeErrorAt(exprOffset
, JSMSG_DEPRECATED_DELETE_OPERAND
)) {
10290 return errorResult();
10293 pc_
->sc()->setBindingsAccessedDynamically();
10296 if (handler_
.isPrivateMemberAccess(expr
)) {
10297 errorAt(exprOffset
, JSMSG_PRIVATE_DELETE
);
10298 return errorResult();
10301 return handler_
.newDelete(begin
, expr
);
10303 case TokenKind::Await
: {
10304 // If we encounter an await in a module, mark it as async.
10305 if (!pc_
->isAsync() && pc_
->sc()->isModule()) {
10306 if (!options().topLevelAwait
) {
10307 error(JSMSG_TOP_LEVEL_AWAIT_NOT_SUPPORTED
);
10308 return errorResult();
10310 pc_
->sc()->asModuleContext()->setIsAsync();
10311 MOZ_ASSERT(pc_
->isAsync());
10314 if (pc_
->isAsync()) {
10315 if (inParametersOfAsyncFunction()) {
10316 error(JSMSG_AWAIT_IN_PARAMETER
);
10317 return errorResult();
10320 MOZ_TRY_VAR(kid
, unaryExpr(yieldHandling
, tripledotHandling
,
10321 possibleError
, invoked
));
10322 pc_
->lastAwaitOffset
= begin
;
10323 return handler_
.newAwaitExpression(begin
, kid
);
10331 MOZ_TRY_VAR(expr
, optionalExpr(yieldHandling
, tripledotHandling
, tt
,
10332 possibleError
, invoked
));
10334 /* Don't look across a newline boundary for a postfix incop. */
10335 if (!tokenStream
.peekTokenSameLine(&tt
)) {
10336 return errorResult();
10339 if (tt
!= TokenKind::Inc
&& tt
!= TokenKind::Dec
) {
10343 tokenStream
.consumeKnownToken(tt
);
10344 if (!checkIncDecOperand(expr
, begin
)) {
10345 return errorResult();
10348 ParseNodeKind pnk
= (tt
== TokenKind::Inc
)
10349 ? ParseNodeKind::PostIncrementExpr
10350 : ParseNodeKind::PostDecrementExpr
;
10351 return handler_
.newUpdate(pnk
, begin
, expr
);
10356 template <class ParseHandler
, typename Unit
>
10357 typename
ParseHandler::NodeResult
10358 GeneralParser
<ParseHandler
, Unit
>::assignExprWithoutYieldOrAwait(
10359 YieldHandling yieldHandling
) {
10360 uint32_t startYieldOffset
= pc_
->lastYieldOffset
;
10361 uint32_t startAwaitOffset
= pc_
->lastAwaitOffset
;
10364 MOZ_TRY_VAR(res
, assignExpr(InAllowed
, yieldHandling
, TripledotProhibited
));
10366 if (pc_
->lastYieldOffset
!= startYieldOffset
) {
10367 errorAt(pc_
->lastYieldOffset
, JSMSG_YIELD_IN_PARAMETER
);
10368 return errorResult();
10370 if (pc_
->lastAwaitOffset
!= startAwaitOffset
) {
10371 errorAt(pc_
->lastAwaitOffset
, JSMSG_AWAIT_IN_PARAMETER
);
10372 return errorResult();
10377 template <class ParseHandler
, typename Unit
>
10378 typename
ParseHandler::ListNodeResult
10379 GeneralParser
<ParseHandler
, Unit
>::argumentList(
10380 YieldHandling yieldHandling
, bool* isSpread
,
10381 PossibleError
* possibleError
/* = nullptr */) {
10382 ListNodeType argsList
;
10383 MOZ_TRY_VAR(argsList
, handler_
.newArguments(pos()));
10386 if (!tokenStream
.matchToken(&matched
, TokenKind::RightParen
,
10387 TokenStream::SlashIsRegExp
)) {
10388 return errorResult();
10391 handler_
.setEndPosition(argsList
, pos().end
);
10396 bool spread
= false;
10397 uint32_t begin
= 0;
10398 if (!tokenStream
.matchToken(&matched
, TokenKind::TripleDot
,
10399 TokenStream::SlashIsRegExp
)) {
10400 return errorResult();
10404 begin
= pos().begin
;
10409 MOZ_TRY_VAR(argNode
, assignExpr(InAllowed
, yieldHandling
,
10410 TripledotProhibited
, possibleError
));
10412 MOZ_TRY_VAR(argNode
, handler_
.newSpread(begin
, argNode
));
10415 handler_
.addList(argsList
, argNode
);
10418 if (!tokenStream
.matchToken(&matched
, TokenKind::Comma
,
10419 TokenStream::SlashIsRegExp
)) {
10420 return errorResult();
10427 if (!tokenStream
.peekToken(&tt
, TokenStream::SlashIsRegExp
)) {
10428 return errorResult();
10430 if (tt
== TokenKind::RightParen
) {
10435 if (!mustMatchToken(TokenKind::RightParen
, JSMSG_PAREN_AFTER_ARGS
)) {
10436 return errorResult();
10439 handler_
.setEndPosition(argsList
, pos().end
);
10443 bool ParserBase::checkAndMarkSuperScope() {
10444 if (!pc_
->sc()->allowSuperProperty()) {
10448 pc_
->setSuperScopeNeedsHomeObject();
10452 template <class ParseHandler
, typename Unit
>
10453 bool GeneralParser
<ParseHandler
, Unit
>::computeErrorMetadata(
10454 ErrorMetadata
* err
, const ErrorReportMixin::ErrorOffset
& offset
) const {
10455 if (offset
.is
<ErrorReportMixin::Current
>()) {
10456 return tokenStream
.computeErrorMetadata(err
, AsVariant(pos().begin
));
10458 return tokenStream
.computeErrorMetadata(err
, offset
);
10461 template <class ParseHandler
, typename Unit
>
10462 typename
ParseHandler::NodeResult GeneralParser
<ParseHandler
, Unit
>::memberExpr(
10463 YieldHandling yieldHandling
, TripledotHandling tripledotHandling
,
10464 TokenKind tt
, bool allowCallSyntax
, PossibleError
* possibleError
,
10465 InvokedPrediction invoked
) {
10466 MOZ_ASSERT(anyChars
.isCurrentTokenType(tt
));
10470 AutoCheckRecursionLimit
recursion(this->fc_
);
10471 if (!recursion
.check(this->fc_
)) {
10472 return errorResult();
10475 /* Check for new expression first. */
10476 if (tt
== TokenKind::New
) {
10477 uint32_t newBegin
= pos().begin
;
10478 // Make sure this wasn't a |new.target| in disguise.
10479 NewTargetNodeType newTarget
;
10480 if (!tryNewTarget(&newTarget
)) {
10481 return errorResult();
10486 // Gotten by tryNewTarget
10487 tt
= anyChars
.currentToken().type
;
10489 MOZ_TRY_VAR(ctorExpr
,
10490 memberExpr(yieldHandling
, TripledotProhibited
, tt
,
10491 /* allowCallSyntax = */ false,
10492 /* possibleError = */ nullptr, PredictInvoked
));
10494 // If we have encountered an optional chain, in the form of `new
10495 // ClassName?.()` then we need to throw, as this is disallowed by the
10497 bool optionalToken
;
10498 if (!tokenStream
.matchToken(&optionalToken
, TokenKind::OptionalChain
)) {
10499 return errorResult();
10501 if (optionalToken
) {
10502 errorAt(newBegin
, JSMSG_BAD_NEW_OPTIONAL
);
10503 return errorResult();
10507 if (!tokenStream
.matchToken(&matched
, TokenKind::LeftParen
)) {
10508 return errorResult();
10511 bool isSpread
= false;
10514 MOZ_TRY_VAR(args
, argumentList(yieldHandling
, &isSpread
));
10516 MOZ_TRY_VAR(args
, handler_
.newArguments(pos()));
10520 return errorResult();
10524 lhs
, handler_
.newNewExpression(newBegin
, ctorExpr
, args
, isSpread
));
10526 } else if (tt
== TokenKind::Super
) {
10527 NameNodeType thisName
;
10528 MOZ_TRY_VAR(thisName
, newThisName());
10529 MOZ_TRY_VAR(lhs
, handler_
.newSuperBase(thisName
, pos()));
10530 } else if (tt
== TokenKind::Import
) {
10531 MOZ_TRY_VAR(lhs
, importExpr(yieldHandling
, allowCallSyntax
));
10533 MOZ_TRY_VAR(lhs
, primaryExpr(yieldHandling
, tripledotHandling
, tt
,
10534 possibleError
, invoked
));
10537 MOZ_ASSERT_IF(handler_
.isSuperBase(lhs
),
10538 anyChars
.isCurrentTokenType(TokenKind::Super
));
10541 if (!tokenStream
.getToken(&tt
)) {
10542 return errorResult();
10544 if (tt
== TokenKind::Eof
) {
10545 anyChars
.ungetToken();
10550 if (tt
== TokenKind::Dot
) {
10551 if (!tokenStream
.getToken(&tt
)) {
10552 return errorResult();
10555 if (TokenKindIsPossibleIdentifierName(tt
)) {
10556 MOZ_TRY_VAR(nextMember
, memberPropertyAccess(lhs
));
10557 } else if (tt
== TokenKind::PrivateName
) {
10558 MOZ_TRY_VAR(nextMember
, memberPrivateAccess(lhs
));
10560 error(JSMSG_NAME_AFTER_DOT
);
10561 return errorResult();
10563 } else if (tt
== TokenKind::LeftBracket
) {
10564 MOZ_TRY_VAR(nextMember
, memberElemAccess(lhs
, yieldHandling
));
10565 } else if ((allowCallSyntax
&& tt
== TokenKind::LeftParen
) ||
10566 tt
== TokenKind::TemplateHead
||
10567 tt
== TokenKind::NoSubsTemplate
) {
10568 if (handler_
.isSuperBase(lhs
)) {
10569 if (!pc_
->sc()->allowSuperCall()) {
10570 error(JSMSG_BAD_SUPERCALL
);
10571 return errorResult();
10574 if (tt
!= TokenKind::LeftParen
) {
10575 error(JSMSG_BAD_SUPER
);
10576 return errorResult();
10579 MOZ_TRY_VAR(nextMember
, memberSuperCall(lhs
, yieldHandling
));
10582 TaggedParserAtomIndex::WellKnown::dot_initializers_())) {
10583 return errorResult();
10586 MOZ_TRY_VAR(nextMember
,
10587 memberCall(tt
, lhs
, yieldHandling
, possibleError
));
10590 anyChars
.ungetToken();
10591 if (handler_
.isSuperBase(lhs
)) {
10600 if (handler_
.isSuperBase(lhs
)) {
10601 error(JSMSG_BAD_SUPER
);
10602 return errorResult();
10608 template <class ParseHandler
, typename Unit
>
10609 typename
ParseHandler::NodeResult
10610 GeneralParser
<ParseHandler
, Unit
>::decoratorExpr(YieldHandling yieldHandling
,
10612 MOZ_ASSERT(anyChars
.isCurrentTokenType(tt
));
10614 AutoCheckRecursionLimit
recursion(this->fc_
);
10615 if (!recursion
.check(this->fc_
)) {
10616 return errorResult();
10619 if (tt
== TokenKind::LeftParen
) {
10620 // DecoratorParenthesizedExpression
10622 MOZ_TRY_VAR(expr
, exprInParens(InAllowed
, yieldHandling
, TripledotAllowed
,
10623 /* possibleError*/ nullptr));
10624 if (!mustMatchToken(TokenKind::RightParen
, JSMSG_PAREN_AFTER_DECORATOR
)) {
10625 return errorResult();
10628 return handler_
.parenthesize(expr
);
10631 if (!TokenKindIsPossibleIdentifier(tt
)) {
10632 error(JSMSG_DECORATOR_NAME_EXPECTED
);
10633 return errorResult();
10636 TaggedParserAtomIndex name
= identifierReference(yieldHandling
);
10638 return errorResult();
10642 MOZ_TRY_VAR(lhs
, identifierReference(name
));
10645 if (!tokenStream
.getToken(&tt
)) {
10646 return errorResult();
10648 if (tt
== TokenKind::Eof
) {
10649 anyChars
.ungetToken();
10654 if (tt
== TokenKind::Dot
) {
10655 if (!tokenStream
.getToken(&tt
)) {
10656 return errorResult();
10659 if (TokenKindIsPossibleIdentifierName(tt
)) {
10660 MOZ_TRY_VAR(nextMember
, memberPropertyAccess(lhs
));
10661 } else if (tt
== TokenKind::PrivateName
) {
10662 MOZ_TRY_VAR(nextMember
, memberPrivateAccess(lhs
));
10664 error(JSMSG_NAME_AFTER_DOT
);
10665 return errorResult();
10667 } else if (tt
== TokenKind::LeftParen
) {
10668 MOZ_TRY_VAR(nextMember
, memberCall(tt
, lhs
, yieldHandling
,
10669 /* possibleError */ nullptr));
10671 // This is a `DecoratorCallExpression` and it's defined at the top level
10672 // of `Decorator`, no other `DecoratorMemberExpression` is allowed to
10673 // follow after the arguments.
10676 anyChars
.ungetToken();
10686 template <class ParseHandler
>
10687 inline typename
ParseHandler::NameNodeResult
10688 PerHandlerParser
<ParseHandler
>::newName(TaggedParserAtomIndex name
) {
10689 return newName(name
, pos());
10692 template <class ParseHandler
>
10693 inline typename
ParseHandler::NameNodeResult
10694 PerHandlerParser
<ParseHandler
>::newName(TaggedParserAtomIndex name
,
10696 return handler_
.newName(name
, pos
);
10699 template <class ParseHandler
>
10700 inline typename
ParseHandler::NameNodeResult
10701 PerHandlerParser
<ParseHandler
>::newPrivateName(TaggedParserAtomIndex name
) {
10702 return handler_
.newPrivateName(name
, pos());
10705 template <class ParseHandler
, typename Unit
>
10706 typename
ParseHandler::NodeResult
10707 GeneralParser
<ParseHandler
, Unit
>::memberPropertyAccess(
10708 Node lhs
, OptionalKind optionalKind
/* = OptionalKind::NonOptional */) {
10709 MOZ_ASSERT(TokenKindIsPossibleIdentifierName(anyChars
.currentToken().type
) ||
10710 anyChars
.currentToken().type
== TokenKind::PrivateName
);
10711 TaggedParserAtomIndex field
= anyChars
.currentName();
10712 if (handler_
.isSuperBase(lhs
) && !checkAndMarkSuperScope()) {
10713 error(JSMSG_BAD_SUPERPROP
, "property");
10714 return errorResult();
10718 MOZ_TRY_VAR(name
, handler_
.newPropertyName(field
, pos()));
10720 if (optionalKind
== OptionalKind::Optional
) {
10721 MOZ_ASSERT(!handler_
.isSuperBase(lhs
));
10722 return handler_
.newOptionalPropertyAccess(lhs
, name
);
10724 return handler_
.newPropertyAccess(lhs
, name
);
10727 template <class ParseHandler
, typename Unit
>
10728 typename
ParseHandler::NodeResult
10729 GeneralParser
<ParseHandler
, Unit
>::memberPrivateAccess(
10730 Node lhs
, OptionalKind optionalKind
/* = OptionalKind::NonOptional */) {
10731 MOZ_ASSERT(anyChars
.currentToken().type
== TokenKind::PrivateName
);
10733 TaggedParserAtomIndex field
= anyChars
.currentName();
10734 // Cannot access private fields on super.
10735 if (handler_
.isSuperBase(lhs
)) {
10736 error(JSMSG_BAD_SUPERPRIVATE
);
10737 return errorResult();
10740 NameNodeType privateName
;
10741 MOZ_TRY_VAR(privateName
, privateNameReference(field
));
10743 if (optionalKind
== OptionalKind::Optional
) {
10744 MOZ_ASSERT(!handler_
.isSuperBase(lhs
));
10745 return handler_
.newOptionalPrivateMemberAccess(lhs
, privateName
, pos().end
);
10747 return handler_
.newPrivateMemberAccess(lhs
, privateName
, pos().end
);
10750 template <class ParseHandler
, typename Unit
>
10751 typename
ParseHandler::NodeResult
10752 GeneralParser
<ParseHandler
, Unit
>::memberElemAccess(
10753 Node lhs
, YieldHandling yieldHandling
,
10754 OptionalKind optionalKind
/* = OptionalKind::NonOptional */) {
10755 MOZ_ASSERT(anyChars
.currentToken().type
== TokenKind::LeftBracket
);
10757 MOZ_TRY_VAR(propExpr
, expr(InAllowed
, yieldHandling
, TripledotProhibited
));
10759 if (!mustMatchToken(TokenKind::RightBracket
, JSMSG_BRACKET_IN_INDEX
)) {
10760 return errorResult();
10763 if (handler_
.isSuperBase(lhs
) && !checkAndMarkSuperScope()) {
10764 error(JSMSG_BAD_SUPERPROP
, "member");
10765 return errorResult();
10767 if (optionalKind
== OptionalKind::Optional
) {
10768 MOZ_ASSERT(!handler_
.isSuperBase(lhs
));
10769 return handler_
.newOptionalPropertyByValue(lhs
, propExpr
, pos().end
);
10771 return handler_
.newPropertyByValue(lhs
, propExpr
, pos().end
);
10774 template <class ParseHandler
, typename Unit
>
10775 typename
ParseHandler::NodeResult
10776 GeneralParser
<ParseHandler
, Unit
>::memberSuperCall(
10777 Node lhs
, YieldHandling yieldHandling
) {
10778 MOZ_ASSERT(anyChars
.currentToken().type
== TokenKind::LeftParen
);
10779 // Despite the fact that it's impossible to have |super()| in a
10780 // generator, we still inherit the yieldHandling of the
10781 // memberExpression, per spec. Curious.
10782 bool isSpread
= false;
10784 MOZ_TRY_VAR(args
, argumentList(yieldHandling
, &isSpread
));
10786 CallNodeType superCall
;
10787 MOZ_TRY_VAR(superCall
, handler_
.newSuperCall(lhs
, args
, isSpread
));
10789 // |super()| implicitly reads |new.target|.
10790 if (!noteUsedName(TaggedParserAtomIndex::WellKnown::dot_newTarget_())) {
10791 return errorResult();
10794 NameNodeType thisName
;
10795 MOZ_TRY_VAR(thisName
, newThisName());
10797 return handler_
.newSetThis(thisName
, superCall
);
10800 template <class ParseHandler
, typename Unit
>
10801 typename
ParseHandler::NodeResult GeneralParser
<ParseHandler
, Unit
>::memberCall(
10802 TokenKind tt
, Node lhs
, YieldHandling yieldHandling
,
10803 PossibleError
* possibleError
/* = nullptr */,
10804 OptionalKind optionalKind
/* = OptionalKind::NonOptional */) {
10805 if (options().selfHostingMode
&&
10806 (handler_
.isPropertyOrPrivateMemberAccess(lhs
) ||
10807 handler_
.isOptionalPropertyOrPrivateMemberAccess(lhs
))) {
10808 error(JSMSG_SELFHOSTED_METHOD_CALL
);
10809 return errorResult();
10812 MOZ_ASSERT(tt
== TokenKind::LeftParen
|| tt
== TokenKind::TemplateHead
||
10813 tt
== TokenKind::NoSubsTemplate
,
10814 "Unexpected token kind for member call");
10816 JSOp op
= JSOp::Call
;
10817 bool maybeAsyncArrow
= false;
10818 if (tt
== TokenKind::LeftParen
&& optionalKind
== OptionalKind::NonOptional
) {
10819 if (handler_
.isAsyncKeyword(lhs
)) {
10820 // |async (| can be the start of an async arrow
10821 // function, so we need to defer reporting possible
10822 // errors from destructuring syntax. To give better
10823 // error messages, we only allow the AsyncArrowHead
10824 // part of the CoverCallExpressionAndAsyncArrowHead
10825 // syntax when the initial name is "async".
10826 maybeAsyncArrow
= true;
10827 } else if (handler_
.isEvalName(lhs
)) {
10828 // Select the right Eval op and flag pc_ as having a
10830 op
= pc_
->sc()->strict() ? JSOp::StrictEval
: JSOp::Eval
;
10831 pc_
->sc()->setBindingsAccessedDynamically();
10832 pc_
->sc()->setHasDirectEval();
10834 // In non-strict mode code, direct calls to eval can
10835 // add variables to the call object.
10836 if (pc_
->isFunctionBox() && !pc_
->sc()->strict()) {
10837 pc_
->functionBox()->setFunHasExtensibleScope();
10840 // If we're in a method, mark the method as requiring
10841 // support for 'super', since direct eval code can use
10842 // it. (If we're not in a method, that's fine, so
10843 // ignore the return value.)
10844 checkAndMarkSuperScope();
10848 if (tt
== TokenKind::LeftParen
) {
10849 bool isSpread
= false;
10850 PossibleError
* asyncPossibleError
=
10851 maybeAsyncArrow
? possibleError
: nullptr;
10854 argumentList(yieldHandling
, &isSpread
, asyncPossibleError
));
10856 if (op
== JSOp::Eval
) {
10857 op
= JSOp::SpreadEval
;
10858 } else if (op
== JSOp::StrictEval
) {
10859 op
= JSOp::StrictSpreadEval
;
10861 op
= JSOp::SpreadCall
;
10865 if (optionalKind
== OptionalKind::Optional
) {
10866 return handler_
.newOptionalCall(lhs
, args
, op
);
10868 return handler_
.newCall(lhs
, args
, op
);
10872 MOZ_TRY_VAR(args
, handler_
.newArguments(pos()));
10874 if (!taggedTemplate(yieldHandling
, args
, tt
)) {
10875 return errorResult();
10878 if (optionalKind
== OptionalKind::Optional
) {
10879 error(JSMSG_BAD_OPTIONAL_TEMPLATE
);
10880 return errorResult();
10883 return handler_
.newTaggedTemplate(lhs
, args
, op
);
10886 template <class ParseHandler
, typename Unit
>
10887 bool GeneralParser
<ParseHandler
, Unit
>::checkLabelOrIdentifierReference(
10888 TaggedParserAtomIndex ident
, uint32_t offset
, YieldHandling yieldHandling
,
10889 TokenKind hint
/* = TokenKind::Limit */) {
10891 if (hint
== TokenKind::Limit
) {
10892 tt
= ReservedWordTokenKind(ident
);
10894 // All non-reserved word kinds are folded into TokenKind::Limit in
10895 // ReservedWordTokenKind and the following code.
10896 if (hint
== TokenKind::Name
|| hint
== TokenKind::PrivateName
) {
10897 hint
= TokenKind::Limit
;
10899 MOZ_ASSERT(hint
== ReservedWordTokenKind(ident
),
10900 "hint doesn't match actual token kind");
10904 if (!pc_
->sc()->allowArguments() &&
10905 ident
== TaggedParserAtomIndex::WellKnown::arguments()) {
10906 error(JSMSG_BAD_ARGUMENTS
);
10910 if (tt
== TokenKind::Limit
) {
10911 // Either TokenKind::Name or TokenKind::PrivateName
10914 if (TokenKindIsContextualKeyword(tt
)) {
10915 if (tt
== TokenKind::Yield
) {
10916 if (yieldHandling
== YieldIsKeyword
) {
10917 errorAt(offset
, JSMSG_RESERVED_ID
, "yield");
10920 if (pc_
->sc()->strict()) {
10921 if (!strictModeErrorAt(offset
, JSMSG_RESERVED_ID
, "yield")) {
10927 if (tt
== TokenKind::Await
) {
10928 if (awaitIsKeyword() || awaitIsDisallowed()) {
10929 errorAt(offset
, JSMSG_RESERVED_ID
, "await");
10934 if (pc_
->sc()->strict()) {
10935 if (tt
== TokenKind::Let
) {
10936 if (!strictModeErrorAt(offset
, JSMSG_RESERVED_ID
, "let")) {
10941 if (tt
== TokenKind::Static
) {
10942 if (!strictModeErrorAt(offset
, JSMSG_RESERVED_ID
, "static")) {
10950 if (TokenKindIsStrictReservedWord(tt
)) {
10951 if (pc_
->sc()->strict()) {
10952 if (!strictModeErrorAt(offset
, JSMSG_RESERVED_ID
,
10953 ReservedWordToCharZ(tt
))) {
10959 if (TokenKindIsKeyword(tt
) || TokenKindIsReservedWordLiteral(tt
)) {
10960 errorAt(offset
, JSMSG_INVALID_ID
, ReservedWordToCharZ(tt
));
10963 if (TokenKindIsFutureReservedWord(tt
)) {
10964 errorAt(offset
, JSMSG_RESERVED_ID
, ReservedWordToCharZ(tt
));
10967 MOZ_ASSERT_UNREACHABLE("Unexpected reserved word kind.");
10971 template <class ParseHandler
, typename Unit
>
10972 bool GeneralParser
<ParseHandler
, Unit
>::checkBindingIdentifier(
10973 TaggedParserAtomIndex ident
, uint32_t offset
, YieldHandling yieldHandling
,
10974 TokenKind hint
/* = TokenKind::Limit */) {
10975 if (pc_
->sc()->strict()) {
10976 if (ident
== TaggedParserAtomIndex::WellKnown::arguments()) {
10977 if (!strictModeErrorAt(offset
, JSMSG_BAD_STRICT_ASSIGN
, "arguments")) {
10983 if (ident
== TaggedParserAtomIndex::WellKnown::eval()) {
10984 if (!strictModeErrorAt(offset
, JSMSG_BAD_STRICT_ASSIGN
, "eval")) {
10991 return checkLabelOrIdentifierReference(ident
, offset
, yieldHandling
, hint
);
10994 template <class ParseHandler
, typename Unit
>
10995 TaggedParserAtomIndex
10996 GeneralParser
<ParseHandler
, Unit
>::labelOrIdentifierReference(
10997 YieldHandling yieldHandling
) {
10998 // ES 2017 draft 12.1.1.
10999 // StringValue of IdentifierName normalizes any Unicode escape sequences
11000 // in IdentifierName hence such escapes cannot be used to write an
11001 // Identifier whose code point sequence is the same as a ReservedWord.
11003 // Use const ParserName* instead of TokenKind to reflect the normalization.
11005 // Unless the name contains escapes, we can reuse the current TokenKind
11006 // to determine if the name is a restricted identifier.
11007 TokenKind hint
= !anyChars
.currentNameHasEscapes(this->parserAtoms())
11008 ? anyChars
.currentToken().type
11009 : TokenKind::Limit
;
11010 TaggedParserAtomIndex ident
= anyChars
.currentName();
11011 if (!checkLabelOrIdentifierReference(ident
, pos().begin
, yieldHandling
,
11013 return TaggedParserAtomIndex::null();
11018 template <class ParseHandler
, typename Unit
>
11019 TaggedParserAtomIndex GeneralParser
<ParseHandler
, Unit
>::bindingIdentifier(
11020 YieldHandling yieldHandling
) {
11021 TokenKind hint
= !anyChars
.currentNameHasEscapes(this->parserAtoms())
11022 ? anyChars
.currentToken().type
11023 : TokenKind::Limit
;
11024 TaggedParserAtomIndex ident
= anyChars
.currentName();
11025 if (!checkBindingIdentifier(ident
, pos().begin
, yieldHandling
, hint
)) {
11026 return TaggedParserAtomIndex::null();
11031 template <class ParseHandler
>
11032 typename
ParseHandler::NameNodeResult
11033 PerHandlerParser
<ParseHandler
>::identifierReference(
11034 TaggedParserAtomIndex name
) {
11036 MOZ_TRY_VAR(id
, newName(name
));
11038 if (!noteUsedName(name
)) {
11039 return errorResult();
11045 template <class ParseHandler
>
11046 typename
ParseHandler::NameNodeResult
11047 PerHandlerParser
<ParseHandler
>::privateNameReference(
11048 TaggedParserAtomIndex name
) {
11050 MOZ_TRY_VAR(id
, newPrivateName(name
));
11052 if (!noteUsedName(name
, NameVisibility::Private
, Some(pos()))) {
11053 return errorResult();
11059 template <class ParseHandler
>
11060 typename
ParseHandler::NameNodeResult
11061 PerHandlerParser
<ParseHandler
>::stringLiteral() {
11062 return handler_
.newStringLiteral(anyChars
.currentToken().atom(), pos());
11065 template <class ParseHandler
>
11066 typename
ParseHandler::NodeResult
11067 PerHandlerParser
<ParseHandler
>::noSubstitutionTaggedTemplate() {
11068 if (anyChars
.hasInvalidTemplateEscape()) {
11069 anyChars
.clearInvalidTemplateEscape();
11070 return handler_
.newRawUndefinedLiteral(pos());
11073 return handler_
.newTemplateStringLiteral(anyChars
.currentToken().atom(),
11077 template <class ParseHandler
, typename Unit
>
11078 typename
ParseHandler::NameNodeResult
11079 GeneralParser
<ParseHandler
, Unit
>::noSubstitutionUntaggedTemplate() {
11080 if (!tokenStream
.checkForInvalidTemplateEscapeError()) {
11081 return errorResult();
11084 return handler_
.newTemplateStringLiteral(anyChars
.currentToken().atom(),
11088 template <typename Unit
>
11089 FullParseHandler::RegExpLiteralResult
11090 Parser
<FullParseHandler
, Unit
>::newRegExp() {
11091 MOZ_ASSERT(!options().selfHostingMode
);
11093 // Create the regexp and check its syntax.
11094 const auto& chars
= tokenStream
.getCharBuffer();
11095 mozilla::Range
<const char16_t
> range(chars
.begin(), chars
.length());
11096 RegExpFlags flags
= anyChars
.currentToken().regExpFlags();
11098 uint32_t offset
= anyChars
.currentToken().pos
.begin
;
11100 JS::LimitedColumnNumberOneOrigin column
;
11101 tokenStream
.computeLineAndColumn(offset
, &line
, &column
);
11103 if (!handler_
.reuseRegexpSyntaxParse()) {
11104 // Verify that the Regexp will syntax parse when the time comes to
11105 // instantiate it. If we have already done a syntax parse, we can
11107 if (!irregexp::CheckPatternSyntax(
11108 this->alloc_
, this->fc_
->stackLimit(), anyChars
, range
, flags
,
11109 Some(line
), Some(JS::ColumnNumberOneOrigin(column
)))) {
11110 return errorResult();
11115 this->parserAtoms().internChar16(fc_
, chars
.begin(), chars
.length());
11117 return errorResult();
11119 // RegExp patterm must be atomized.
11120 this->parserAtoms().markUsedByStencil(atom
, ParserAtom::Atomize::Yes
);
11122 RegExpIndex
index(this->compilationState_
.regExpData
.length());
11123 if (uint32_t(index
) >= TaggedScriptThingIndex::IndexLimit
) {
11124 ReportAllocationOverflow(fc_
);
11125 return errorResult();
11127 if (!this->compilationState_
.regExpData
.emplaceBack(atom
, flags
)) {
11128 js::ReportOutOfMemory(this->fc_
);
11129 return errorResult();
11132 return handler_
.newRegExp(index
, pos());
11135 template <typename Unit
>
11136 SyntaxParseHandler::RegExpLiteralResult
11137 Parser
<SyntaxParseHandler
, Unit
>::newRegExp() {
11138 MOZ_ASSERT(!options().selfHostingMode
);
11140 // Only check the regexp's syntax, but don't create a regexp object.
11141 const auto& chars
= tokenStream
.getCharBuffer();
11142 RegExpFlags flags
= anyChars
.currentToken().regExpFlags();
11144 uint32_t offset
= anyChars
.currentToken().pos
.begin
;
11146 JS::LimitedColumnNumberOneOrigin column
;
11147 tokenStream
.computeLineAndColumn(offset
, &line
, &column
);
11149 mozilla::Range
<const char16_t
> source(chars
.begin(), chars
.length());
11150 if (!irregexp::CheckPatternSyntax(this->alloc_
, this->fc_
->stackLimit(),
11151 anyChars
, source
, flags
, Some(line
),
11152 Some(JS::ColumnNumberOneOrigin(column
)))) {
11153 return errorResult();
11156 return handler_
.newRegExp(SyntaxParseHandler::Node::NodeGeneric
, pos());
11159 template <class ParseHandler
, typename Unit
>
11160 typename
ParseHandler::RegExpLiteralResult
11161 GeneralParser
<ParseHandler
, Unit
>::newRegExp() {
11162 return asFinalParser()->newRegExp();
11165 template <typename Unit
>
11166 FullParseHandler::BigIntLiteralResult
11167 Parser
<FullParseHandler
, Unit
>::newBigInt() {
11168 // The token's charBuffer contains the DecimalIntegerLiteral or
11169 // NonDecimalIntegerLiteral production, and as such does not include the
11170 // BigIntLiteralSuffix (the trailing "n"). Note that NonDecimalIntegerLiteral
11171 // productions start with 0[bBoOxX], indicating binary/octal/hex.
11172 const auto& chars
= tokenStream
.getCharBuffer();
11173 if (chars
.length() > UINT32_MAX
) {
11174 ReportAllocationOverflow(fc_
);
11175 return errorResult();
11178 BigIntIndex
index(this->compilationState_
.bigIntData
.length());
11179 if (uint32_t(index
) >= TaggedScriptThingIndex::IndexLimit
) {
11180 ReportAllocationOverflow(fc_
);
11181 return errorResult();
11183 if (!this->compilationState_
.bigIntData
.emplaceBack()) {
11184 js::ReportOutOfMemory(this->fc_
);
11185 return errorResult();
11188 if (!this->compilationState_
.bigIntData
[index
].init(
11189 this->fc_
, this->stencilAlloc(), chars
)) {
11190 return errorResult();
11193 bool isZero
= this->compilationState_
.bigIntData
[index
].isZero();
11195 // Should the operations below fail, the buffer held by data will
11196 // be cleaned up by the CompilationState destructor.
11197 return handler_
.newBigInt(index
, isZero
, pos());
11200 template <typename Unit
>
11201 SyntaxParseHandler::BigIntLiteralResult
11202 Parser
<SyntaxParseHandler
, Unit
>::newBigInt() {
11203 // The tokenizer has already checked the syntax of the bigint.
11205 return handler_
.newBigInt();
11208 template <class ParseHandler
, typename Unit
>
11209 typename
ParseHandler::BigIntLiteralResult
11210 GeneralParser
<ParseHandler
, Unit
>::newBigInt() {
11211 return asFinalParser()->newBigInt();
11214 // |exprPossibleError| is the PossibleError state within |expr|,
11215 // |possibleError| is the surrounding PossibleError state.
11216 template <class ParseHandler
, typename Unit
>
11217 bool GeneralParser
<ParseHandler
, Unit
>::checkDestructuringAssignmentTarget(
11218 Node expr
, TokenPos exprPos
, PossibleError
* exprPossibleError
,
11219 PossibleError
* possibleError
, TargetBehavior behavior
) {
11220 // Report any pending expression error if we're definitely not in a
11221 // destructuring context or the possible destructuring target is a
11222 // property accessor.
11223 if (!possibleError
|| handler_
.isPropertyOrPrivateMemberAccess(expr
)) {
11224 return exprPossibleError
->checkForExpressionError();
11227 // |expr| may end up as a destructuring assignment target, so we need to
11228 // validate it's either a name or can be parsed as a nested destructuring
11229 // pattern. Property accessors are also valid assignment targets, but
11230 // those are already handled above.
11232 exprPossibleError
->transferErrorsTo(possibleError
);
11234 // Return early if a pending destructuring error is already present.
11235 if (possibleError
->hasPendingDestructuringError()) {
11239 if (handler_
.isName(expr
)) {
11240 checkDestructuringAssignmentName(handler_
.asNameNode(expr
), exprPos
,
11245 if (handler_
.isUnparenthesizedDestructuringPattern(expr
)) {
11246 if (behavior
== TargetBehavior::ForbidAssignmentPattern
) {
11247 possibleError
->setPendingDestructuringErrorAt(exprPos
,
11248 JSMSG_BAD_DESTRUCT_TARGET
);
11253 // Parentheses are forbidden around destructuring *patterns* (but allowed
11254 // around names). Use our nicer error message for parenthesized, nested
11255 // patterns if nested destructuring patterns are allowed.
11256 if (handler_
.isParenthesizedDestructuringPattern(expr
) &&
11257 behavior
!= TargetBehavior::ForbidAssignmentPattern
) {
11258 possibleError
->setPendingDestructuringErrorAt(exprPos
,
11259 JSMSG_BAD_DESTRUCT_PARENS
);
11261 possibleError
->setPendingDestructuringErrorAt(exprPos
,
11262 JSMSG_BAD_DESTRUCT_TARGET
);
11268 template <class ParseHandler
, typename Unit
>
11269 void GeneralParser
<ParseHandler
, Unit
>::checkDestructuringAssignmentName(
11270 NameNodeType name
, TokenPos namePos
, PossibleError
* possibleError
) {
11272 // GCC 8.0.1 crashes if this is a one-liner.
11273 bool isName
= handler_
.isName(name
);
11274 MOZ_ASSERT(isName
);
11277 // Return early if a pending destructuring error is already present.
11278 if (possibleError
->hasPendingDestructuringError()) {
11282 if (pc_
->sc()->strict()) {
11283 if (handler_
.isArgumentsName(name
)) {
11284 if (pc_
->sc()->strict()) {
11285 possibleError
->setPendingDestructuringErrorAt(
11286 namePos
, JSMSG_BAD_STRICT_ASSIGN_ARGUMENTS
);
11288 possibleError
->setPendingDestructuringWarningAt(
11289 namePos
, JSMSG_BAD_STRICT_ASSIGN_ARGUMENTS
);
11294 if (handler_
.isEvalName(name
)) {
11295 if (pc_
->sc()->strict()) {
11296 possibleError
->setPendingDestructuringErrorAt(
11297 namePos
, JSMSG_BAD_STRICT_ASSIGN_EVAL
);
11299 possibleError
->setPendingDestructuringWarningAt(
11300 namePos
, JSMSG_BAD_STRICT_ASSIGN_EVAL
);
11307 template <class ParseHandler
, typename Unit
>
11308 bool GeneralParser
<ParseHandler
, Unit
>::checkDestructuringAssignmentElement(
11309 Node expr
, TokenPos exprPos
, PossibleError
* exprPossibleError
,
11310 PossibleError
* possibleError
) {
11311 // ES2018 draft rev 0719f44aab93215ed9a626b2f45bd34f36916834
11312 // 12.15.5 Destructuring Assignment
11314 // AssignmentElement[Yield, Await]:
11315 // DestructuringAssignmentTarget[?Yield, ?Await]
11316 // DestructuringAssignmentTarget[?Yield, ?Await] Initializer[+In,
11320 // If |expr| is an assignment element with an initializer expression, its
11321 // destructuring assignment target was already validated in assignExpr().
11322 // Otherwise we need to check that |expr| is a valid destructuring target.
11323 if (handler_
.isUnparenthesizedAssignment(expr
)) {
11324 // Report any pending expression error if we're definitely not in a
11325 // destructuring context.
11326 if (!possibleError
) {
11327 return exprPossibleError
->checkForExpressionError();
11330 exprPossibleError
->transferErrorsTo(possibleError
);
11333 return checkDestructuringAssignmentTarget(expr
, exprPos
, exprPossibleError
,
11337 template <class ParseHandler
, typename Unit
>
11338 typename
ParseHandler::ListNodeResult
11339 GeneralParser
<ParseHandler
, Unit
>::arrayInitializer(
11340 YieldHandling yieldHandling
, PossibleError
* possibleError
) {
11341 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::LeftBracket
));
11343 uint32_t begin
= pos().begin
;
11344 ListNodeType literal
;
11345 MOZ_TRY_VAR(literal
, handler_
.newArrayLiteral(begin
));
11348 if (!tokenStream
.getToken(&tt
, TokenStream::SlashIsRegExp
)) {
11349 return errorResult();
11352 if (tt
== TokenKind::RightBracket
) {
11354 * Mark empty arrays as non-constant, since we cannot easily
11355 * determine their type.
11357 handler_
.setListHasNonConstInitializer(literal
);
11359 anyChars
.ungetToken();
11361 for (uint32_t index
= 0;; index
++) {
11362 if (index
>= NativeObject::MAX_DENSE_ELEMENTS_COUNT
) {
11363 error(JSMSG_ARRAY_INIT_TOO_BIG
);
11364 return errorResult();
11368 if (!tokenStream
.peekToken(&tt
, TokenStream::SlashIsRegExp
)) {
11369 return errorResult();
11371 if (tt
== TokenKind::RightBracket
) {
11375 if (tt
== TokenKind::Comma
) {
11376 tokenStream
.consumeKnownToken(TokenKind::Comma
,
11377 TokenStream::SlashIsRegExp
);
11378 if (!handler_
.addElision(literal
, pos())) {
11379 return errorResult();
11384 if (tt
== TokenKind::TripleDot
) {
11385 tokenStream
.consumeKnownToken(TokenKind::TripleDot
,
11386 TokenStream::SlashIsRegExp
);
11387 uint32_t begin
= pos().begin
;
11390 if (!tokenStream
.peekTokenPos(&innerPos
, TokenStream::SlashIsRegExp
)) {
11391 return errorResult();
11394 PossibleError
possibleErrorInner(*this);
11397 assignExpr(InAllowed
, yieldHandling
, TripledotProhibited
,
11398 &possibleErrorInner
));
11399 if (!checkDestructuringAssignmentTarget(
11400 inner
, innerPos
, &possibleErrorInner
, possibleError
)) {
11401 return errorResult();
11404 if (!handler_
.addSpreadElement(literal
, begin
, inner
)) {
11405 return errorResult();
11408 TokenPos elementPos
;
11409 if (!tokenStream
.peekTokenPos(&elementPos
,
11410 TokenStream::SlashIsRegExp
)) {
11411 return errorResult();
11414 PossibleError
possibleErrorInner(*this);
11416 MOZ_TRY_VAR(element
,
11417 assignExpr(InAllowed
, yieldHandling
, TripledotProhibited
,
11418 &possibleErrorInner
));
11419 if (!checkDestructuringAssignmentElement(
11420 element
, elementPos
, &possibleErrorInner
, possibleError
)) {
11421 return errorResult();
11423 handler_
.addArrayElement(literal
, element
);
11427 if (!tokenStream
.matchToken(&matched
, TokenKind::Comma
,
11428 TokenStream::SlashIsRegExp
)) {
11429 return errorResult();
11435 if (tt
== TokenKind::TripleDot
&& possibleError
) {
11436 possibleError
->setPendingDestructuringErrorAt(pos(),
11437 JSMSG_REST_WITH_COMMA
);
11441 if (!mustMatchToken(
11442 TokenKind::RightBracket
, [this, begin
](TokenKind actual
) {
11443 this->reportMissingClosing(JSMSG_BRACKET_AFTER_LIST
,
11444 JSMSG_BRACKET_OPENED
, begin
);
11446 return errorResult();
11450 handler_
.setEndPosition(literal
, pos().end
);
11454 template <class ParseHandler
, typename Unit
>
11455 typename
ParseHandler::NodeResult
11456 GeneralParser
<ParseHandler
, Unit
>::propertyName(
11457 YieldHandling yieldHandling
, PropertyNameContext propertyNameContext
,
11458 const Maybe
<DeclarationKind
>& maybeDecl
, ListNodeType propList
,
11459 TaggedParserAtomIndex
* propAtomOut
) {
11460 // PropertyName[Yield, Await]:
11461 // LiteralPropertyName
11462 // ComputedPropertyName[?Yield, ?Await]
11464 // LiteralPropertyName:
11468 TokenKind ltok
= anyChars
.currentToken().type
;
11470 *propAtomOut
= TaggedParserAtomIndex::null();
11472 case TokenKind::Number
: {
11473 auto numAtom
= NumberToParserAtom(fc_
, this->parserAtoms(),
11474 anyChars
.currentToken().number());
11476 return errorResult();
11478 *propAtomOut
= numAtom
;
11479 return newNumber(anyChars
.currentToken());
11482 case TokenKind::BigInt
: {
11484 MOZ_TRY_VAR(biNode
, newBigInt());
11485 return handler_
.newSyntheticComputedName(biNode
, pos().begin
, pos().end
);
11487 case TokenKind::String
: {
11488 auto str
= anyChars
.currentToken().atom();
11489 *propAtomOut
= str
;
11491 if (this->parserAtoms().isIndex(str
, &index
)) {
11492 return handler_
.newNumber(index
, NoDecimal
, pos());
11494 return stringLiteral();
11497 case TokenKind::LeftBracket
:
11498 return computedPropertyName(yieldHandling
, maybeDecl
, propertyNameContext
,
11501 case TokenKind::PrivateName
: {
11502 if (propertyNameContext
!= PropertyNameContext::PropertyNameInClass
) {
11503 error(JSMSG_ILLEGAL_PRIVATE_FIELD
);
11504 return errorResult();
11507 TaggedParserAtomIndex propName
= anyChars
.currentName();
11508 *propAtomOut
= propName
;
11509 return privateNameReference(propName
);
11513 if (!TokenKindIsPossibleIdentifierName(ltok
)) {
11514 error(JSMSG_UNEXPECTED_TOKEN
, "property name", TokenKindToDesc(ltok
));
11515 return errorResult();
11518 TaggedParserAtomIndex name
= anyChars
.currentName();
11519 *propAtomOut
= name
;
11520 return handler_
.newObjectLiteralPropertyName(name
, pos());
11525 // True if `kind` can be the first token of a PropertyName.
11526 static bool TokenKindCanStartPropertyName(TokenKind tt
) {
11527 return TokenKindIsPossibleIdentifierName(tt
) || tt
== TokenKind::String
||
11528 tt
== TokenKind::Number
|| tt
== TokenKind::LeftBracket
||
11529 tt
== TokenKind::Mul
|| tt
== TokenKind::BigInt
||
11530 tt
== TokenKind::PrivateName
;
11533 template <class ParseHandler
, typename Unit
>
11534 typename
ParseHandler::NodeResult
11535 GeneralParser
<ParseHandler
, Unit
>::propertyOrMethodName(
11536 YieldHandling yieldHandling
, PropertyNameContext propertyNameContext
,
11537 const Maybe
<DeclarationKind
>& maybeDecl
, ListNodeType propList
,
11538 PropertyType
* propType
, TaggedParserAtomIndex
* propAtomOut
) {
11539 // We're parsing an object literal, class, or destructuring pattern;
11540 // propertyNameContext tells which one. This method parses any of the
11541 // following, storing the corresponding PropertyType in `*propType` to tell
11542 // the caller what we parsed:
11544 // async [no LineTerminator here] PropertyName
11545 // ==> PropertyType::AsyncMethod
11546 // async [no LineTerminator here] * PropertyName
11547 // ==> PropertyType::AsyncGeneratorMethod
11548 // * PropertyName ==> PropertyType::GeneratorMethod
11549 // get PropertyName ==> PropertyType::Getter
11550 // set PropertyName ==> PropertyType::Setter
11551 // accessor PropertyName ==> PropertyType::FieldWithAccessor
11552 // PropertyName : ==> PropertyType::Normal
11553 // PropertyName ==> see below
11555 // In the last case, where there's not a `:` token to consume, we peek at
11556 // (but don't consume) the next token to decide how to set `*propType`.
11558 // `,` or `}` ==> PropertyType::Shorthand
11559 // `(` ==> PropertyType::Method
11560 // `=`, not in a class ==> PropertyType::CoverInitializedName
11561 // '=', in a class ==> PropertyType::Field
11562 // any token, in a class ==> PropertyType::Field (ASI)
11564 // The caller must check `*propType` and throw if whatever we parsed isn't
11565 // allowed here (for example, a getter in a destructuring pattern).
11567 // This method does *not* match `static` (allowed in classes) or `...`
11568 // (allowed in object literals and patterns). The caller must take care of
11569 // those before calling this method.
11572 if (!tokenStream
.getToken(<ok
, TokenStream::SlashIsInvalid
)) {
11573 return errorResult();
11576 MOZ_ASSERT(ltok
!= TokenKind::RightCurly
,
11577 "caller should have handled TokenKind::RightCurly");
11579 // Accept `async` and/or `*`, indicating an async or generator method;
11580 // or `get` or `set` or `accessor`, indicating an accessor.
11581 bool isGenerator
= false;
11582 bool isAsync
= false;
11583 bool isGetter
= false;
11584 bool isSetter
= false;
11585 #ifdef ENABLE_DECORATORS
11586 bool hasAccessor
= false;
11589 if (ltok
== TokenKind::Async
) {
11590 // `async` is also a PropertyName by itself (it's a conditional keyword),
11591 // so peek at the next token to see if we're really looking at a method.
11592 TokenKind tt
= TokenKind::Eof
;
11593 if (!tokenStream
.peekTokenSameLine(&tt
)) {
11594 return errorResult();
11596 if (TokenKindCanStartPropertyName(tt
)) {
11598 tokenStream
.consumeKnownToken(tt
);
11603 if (ltok
== TokenKind::Mul
) {
11604 isGenerator
= true;
11605 if (!tokenStream
.getToken(<ok
)) {
11606 return errorResult();
11610 if (!isAsync
&& !isGenerator
&&
11611 (ltok
== TokenKind::Get
|| ltok
== TokenKind::Set
)) {
11612 // We have parsed |get| or |set|. Look for an accessor property
11615 if (!tokenStream
.peekToken(&tt
)) {
11616 return errorResult();
11618 if (TokenKindCanStartPropertyName(tt
)) {
11619 tokenStream
.consumeKnownToken(tt
);
11620 isGetter
= (ltok
== TokenKind::Get
);
11621 isSetter
= (ltok
== TokenKind::Set
);
11625 #ifdef ENABLE_DECORATORS
11626 if (!isGenerator
&& !isAsync
&& propertyNameContext
== PropertyNameInClass
&&
11627 ltok
== TokenKind::Accessor
) {
11628 MOZ_ASSERT(!isGetter
&& !isSetter
);
11630 if (!tokenStream
.peekTokenSameLine(&tt
)) {
11631 return errorResult();
11634 // The target rule is `accessor [no LineTerminator here]
11635 // ClassElementName[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt`
11636 if (TokenKindCanStartPropertyName(tt
)) {
11637 tokenStream
.consumeKnownToken(tt
);
11638 hasAccessor
= true;
11644 MOZ_TRY_VAR(propName
, propertyName(yieldHandling
, propertyNameContext
,
11645 maybeDecl
, propList
, propAtomOut
));
11647 // Grab the next token following the property/method name.
11648 // (If this isn't a colon, we're going to either put it back or throw.)
11650 if (!tokenStream
.getToken(&tt
)) {
11651 return errorResult();
11654 if (tt
== TokenKind::Colon
) {
11655 if (isGenerator
|| isAsync
|| isGetter
|| isSetter
11656 #ifdef ENABLE_DECORATORS
11660 error(JSMSG_BAD_PROP_ID
);
11661 return errorResult();
11663 *propType
= PropertyType::Normal
;
11667 if (propertyNameContext
!= PropertyNameInClass
&&
11668 TokenKindIsPossibleIdentifierName(ltok
) &&
11669 (tt
== TokenKind::Comma
|| tt
== TokenKind::RightCurly
||
11670 tt
== TokenKind::Assign
)) {
11671 #ifdef ENABLE_DECORATORS
11672 MOZ_ASSERT(!hasAccessor
);
11674 if (isGenerator
|| isAsync
|| isGetter
|| isSetter
) {
11675 error(JSMSG_BAD_PROP_ID
);
11676 return errorResult();
11679 anyChars
.ungetToken();
11680 *propType
= tt
== TokenKind::Assign
? PropertyType::CoverInitializedName
11681 : PropertyType::Shorthand
;
11685 if (tt
== TokenKind::LeftParen
) {
11686 anyChars
.ungetToken();
11688 #ifdef ENABLE_RECORD_TUPLE
11689 if (propertyNameContext
== PropertyNameInRecord
) {
11690 // Record & Tuple proposal, section 7.1.1:
11691 // RecordPropertyDefinition doesn't cover methods
11692 error(JSMSG_BAD_PROP_ID
);
11693 return errorResult();
11697 #ifdef ENABLE_DECORATORS
11699 error(JSMSG_BAD_PROP_ID
);
11700 return errorResult();
11704 if (isGenerator
&& isAsync
) {
11705 *propType
= PropertyType::AsyncGeneratorMethod
;
11706 } else if (isGenerator
) {
11707 *propType
= PropertyType::GeneratorMethod
;
11708 } else if (isAsync
) {
11709 *propType
= PropertyType::AsyncMethod
;
11710 } else if (isGetter
) {
11711 *propType
= PropertyType::Getter
;
11712 } else if (isSetter
) {
11713 *propType
= PropertyType::Setter
;
11715 *propType
= PropertyType::Method
;
11720 if (propertyNameContext
== PropertyNameInClass
) {
11721 if (isGenerator
|| isAsync
|| isGetter
|| isSetter
) {
11722 error(JSMSG_BAD_PROP_ID
);
11723 return errorResult();
11725 anyChars
.ungetToken();
11726 #ifdef ENABLE_DECORATORS
11727 if (!hasAccessor
) {
11728 *propType
= PropertyType::Field
;
11730 *propType
= PropertyType::FieldWithAccessor
;
11733 *propType
= PropertyType::Field
;
11738 error(JSMSG_COLON_AFTER_ID
);
11739 return errorResult();
11742 template <class ParseHandler
, typename Unit
>
11743 typename
ParseHandler::UnaryNodeResult
11744 GeneralParser
<ParseHandler
, Unit
>::computedPropertyName(
11745 YieldHandling yieldHandling
, const Maybe
<DeclarationKind
>& maybeDecl
,
11746 PropertyNameContext propertyNameContext
, ListNodeType literal
) {
11747 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::LeftBracket
));
11749 uint32_t begin
= pos().begin
;
11752 if (*maybeDecl
== DeclarationKind::FormalParameter
) {
11753 pc_
->functionBox()->hasParameterExprs
= true;
11755 } else if (propertyNameContext
==
11756 PropertyNameContext::PropertyNameInLiteral
) {
11757 handler_
.setListHasNonConstInitializer(literal
);
11761 MOZ_TRY_VAR(assignNode
,
11762 assignExpr(InAllowed
, yieldHandling
, TripledotProhibited
));
11764 if (!mustMatchToken(TokenKind::RightBracket
, JSMSG_COMP_PROP_UNTERM_EXPR
)) {
11765 return errorResult();
11767 return handler_
.newComputedName(assignNode
, begin
, pos().end
);
11770 template <class ParseHandler
, typename Unit
>
11771 typename
ParseHandler::ListNodeResult
11772 GeneralParser
<ParseHandler
, Unit
>::objectLiteral(YieldHandling yieldHandling
,
11773 PossibleError
* possibleError
) {
11774 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::LeftCurly
));
11776 uint32_t openedPos
= pos().begin
;
11778 ListNodeType literal
;
11779 MOZ_TRY_VAR(literal
, handler_
.newObjectLiteral(pos().begin
));
11781 bool seenPrototypeMutation
= false;
11782 bool seenCoverInitializedName
= false;
11783 Maybe
<DeclarationKind
> declKind
= Nothing();
11784 TaggedParserAtomIndex propAtom
;
11787 if (!tokenStream
.peekToken(&tt
)) {
11788 return errorResult();
11790 if (tt
== TokenKind::RightCurly
) {
11794 if (tt
== TokenKind::TripleDot
) {
11795 tokenStream
.consumeKnownToken(TokenKind::TripleDot
);
11796 uint32_t begin
= pos().begin
;
11799 if (!tokenStream
.peekTokenPos(&innerPos
, TokenStream::SlashIsRegExp
)) {
11800 return errorResult();
11803 PossibleError
possibleErrorInner(*this);
11805 MOZ_TRY_VAR(inner
, assignExpr(InAllowed
, yieldHandling
,
11806 TripledotProhibited
, &possibleErrorInner
));
11807 if (!checkDestructuringAssignmentTarget(
11808 inner
, innerPos
, &possibleErrorInner
, possibleError
,
11809 TargetBehavior::ForbidAssignmentPattern
)) {
11810 return errorResult();
11812 if (!handler_
.addSpreadProperty(literal
, begin
, inner
)) {
11813 return errorResult();
11816 TokenPos namePos
= anyChars
.nextToken().pos
;
11818 PropertyType propType
;
11820 MOZ_TRY_VAR(propName
, propertyOrMethodName(
11821 yieldHandling
, PropertyNameInLiteral
, declKind
,
11822 literal
, &propType
, &propAtom
));
11824 if (propType
== PropertyType::Normal
) {
11826 if (!tokenStream
.peekTokenPos(&exprPos
, TokenStream::SlashIsRegExp
)) {
11827 return errorResult();
11830 PossibleError
possibleErrorInner(*this);
11832 MOZ_TRY_VAR(propExpr
,
11833 assignExpr(InAllowed
, yieldHandling
, TripledotProhibited
,
11834 &possibleErrorInner
));
11836 if (!checkDestructuringAssignmentElement(
11837 propExpr
, exprPos
, &possibleErrorInner
, possibleError
)) {
11838 return errorResult();
11841 if (propAtom
== TaggedParserAtomIndex::WellKnown::proto_()) {
11842 if (seenPrototypeMutation
) {
11843 // Directly report the error when we're definitely not
11844 // in a destructuring context.
11845 if (!possibleError
) {
11846 errorAt(namePos
.begin
, JSMSG_DUPLICATE_PROTO_PROPERTY
);
11847 return errorResult();
11850 // Otherwise delay error reporting until we've
11851 // determined whether or not we're destructuring.
11852 possibleError
->setPendingExpressionErrorAt(
11853 namePos
, JSMSG_DUPLICATE_PROTO_PROPERTY
);
11855 seenPrototypeMutation
= true;
11857 // This occurs *only* if we observe PropertyType::Normal!
11858 // Only |__proto__: v| mutates [[Prototype]]. Getters,
11859 // setters, method/generator definitions, computed
11860 // property name versions of all of these, and shorthands
11862 if (!handler_
.addPrototypeMutation(literal
, namePos
.begin
,
11864 return errorResult();
11867 BinaryNodeType propDef
;
11868 MOZ_TRY_VAR(propDef
,
11869 handler_
.newPropertyDefinition(propName
, propExpr
));
11871 handler_
.addPropertyDefinition(literal
, propDef
);
11873 } else if (propType
== PropertyType::Shorthand
) {
11875 * Support, e.g., |({x, y} = o)| as destructuring shorthand
11876 * for |({x: x, y: y} = o)|, and |var o = {x, y}| as
11877 * initializer shorthand for |var o = {x: x, y: y}|.
11879 TaggedParserAtomIndex name
= identifierReference(yieldHandling
);
11881 return errorResult();
11884 NameNodeType nameExpr
;
11885 MOZ_TRY_VAR(nameExpr
, identifierReference(name
));
11887 if (possibleError
) {
11888 checkDestructuringAssignmentName(nameExpr
, namePos
, possibleError
);
11891 if (!handler_
.addShorthand(literal
, handler_
.asNameNode(propName
),
11893 return errorResult();
11895 } else if (propType
== PropertyType::CoverInitializedName
) {
11897 * Support, e.g., |({x=1, y=2} = o)| as destructuring
11898 * shorthand with default values, as per ES6 12.14.5
11900 TaggedParserAtomIndex name
= identifierReference(yieldHandling
);
11902 return errorResult();
11906 MOZ_TRY_VAR(lhs
, identifierReference(name
));
11908 tokenStream
.consumeKnownToken(TokenKind::Assign
);
11910 if (!seenCoverInitializedName
) {
11911 // "shorthand default" or "CoverInitializedName" syntax is
11912 // only valid in the case of destructuring.
11913 seenCoverInitializedName
= true;
11915 if (!possibleError
) {
11916 // Destructuring defaults are definitely not allowed
11917 // in this object literal, because of something the
11918 // caller knows about the preceding code. For example,
11919 // maybe the preceding token is an operator:
11921 error(JSMSG_COLON_AFTER_ID
);
11922 return errorResult();
11925 // Here we set a pending error so that later in the parse,
11926 // once we've determined whether or not we're
11927 // destructuring, the error can be reported or ignored
11929 possibleError
->setPendingExpressionErrorAt(pos(),
11930 JSMSG_COLON_AFTER_ID
);
11933 if (const char* chars
= nameIsArgumentsOrEval(lhs
)) {
11934 // |chars| is "arguments" or "eval" here.
11935 if (!strictModeErrorAt(namePos
.begin
, JSMSG_BAD_STRICT_ASSIGN
,
11937 return errorResult();
11943 assignExpr(InAllowed
, yieldHandling
, TripledotProhibited
));
11945 BinaryNodeType propExpr
;
11946 MOZ_TRY_VAR(propExpr
, handler_
.newAssignment(ParseNodeKind::AssignExpr
,
11949 if (!handler_
.addPropertyDefinition(literal
, propName
, propExpr
)) {
11950 return errorResult();
11953 TaggedParserAtomIndex funName
;
11954 bool hasStaticName
=
11955 !anyChars
.isCurrentTokenType(TokenKind::RightBracket
) && propAtom
;
11956 if (hasStaticName
) {
11957 funName
= propAtom
;
11959 if (propType
== PropertyType::Getter
||
11960 propType
== PropertyType::Setter
) {
11961 funName
= prefixAccessorName(propType
, propAtom
);
11963 return errorResult();
11968 FunctionNodeType funNode
;
11969 MOZ_TRY_VAR(funNode
,
11970 methodDefinition(namePos
.begin
, propType
, funName
));
11972 AccessorType atype
= ToAccessorType(propType
);
11973 if (!handler_
.addObjectMethodDefinition(literal
, propName
, funNode
,
11975 return errorResult();
11978 if (possibleError
) {
11979 possibleError
->setPendingDestructuringErrorAt(
11980 namePos
, JSMSG_BAD_DESTRUCT_TARGET
);
11986 if (!tokenStream
.matchToken(&matched
, TokenKind::Comma
,
11987 TokenStream::SlashIsInvalid
)) {
11988 return errorResult();
11993 if (tt
== TokenKind::TripleDot
&& possibleError
) {
11994 possibleError
->setPendingDestructuringErrorAt(pos(),
11995 JSMSG_REST_WITH_COMMA
);
11999 if (!mustMatchToken(
12000 TokenKind::RightCurly
, [this, openedPos
](TokenKind actual
) {
12001 this->reportMissingClosing(JSMSG_CURLY_AFTER_LIST
,
12002 JSMSG_CURLY_OPENED
, openedPos
);
12004 return errorResult();
12007 handler_
.setEndPosition(literal
, pos().end
);
12011 #ifdef ENABLE_RECORD_TUPLE
12012 template <class ParseHandler
, typename Unit
>
12013 typename
ParseHandler::ListNodeResult
12014 GeneralParser
<ParseHandler
, Unit
>::recordLiteral(YieldHandling yieldHandling
) {
12015 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::HashCurly
));
12017 uint32_t openedPos
= pos().begin
;
12019 ListNodeType literal
;
12020 MOZ_TRY_VAR(literal
, handler_
.newRecordLiteral(pos().begin
));
12022 TaggedParserAtomIndex propAtom
;
12025 if (!tokenStream
.peekToken(&tt
)) {
12026 return errorResult();
12028 if (tt
== TokenKind::RightCurly
) {
12032 if (tt
== TokenKind::TripleDot
) {
12033 tokenStream
.consumeKnownToken(TokenKind::TripleDot
);
12034 uint32_t begin
= pos().begin
;
12037 if (!tokenStream
.peekTokenPos(&innerPos
, TokenStream::SlashIsRegExp
)) {
12038 return errorResult();
12043 assignExpr(InAllowed
, yieldHandling
, TripledotProhibited
));
12045 if (!handler_
.addSpreadProperty(literal
, begin
, inner
)) {
12046 return errorResult();
12049 TokenPos namePos
= anyChars
.nextToken().pos
;
12051 PropertyType propType
;
12053 MOZ_TRY_VAR(propName
,
12054 propertyOrMethodName(yieldHandling
, PropertyNameInRecord
,
12055 /* maybeDecl */ Nothing(), literal
,
12056 &propType
, &propAtom
));
12058 if (propType
== PropertyType::Normal
) {
12060 if (!tokenStream
.peekTokenPos(&exprPos
, TokenStream::SlashIsRegExp
)) {
12061 return errorResult();
12065 MOZ_TRY_VAR(propExpr
,
12066 assignExpr(InAllowed
, yieldHandling
, TripledotProhibited
));
12068 if (propAtom
== TaggedParserAtomIndex::WellKnown::proto_()) {
12069 errorAt(namePos
.begin
, JSMSG_RECORD_NO_PROTO
);
12070 return errorResult();
12073 BinaryNodeType propDef
;
12074 MOZ_TRY_VAR(propDef
,
12075 handler_
.newPropertyDefinition(propName
, propExpr
));
12077 handler_
.addPropertyDefinition(literal
, propDef
);
12078 } else if (propType
== PropertyType::Shorthand
) {
12080 * Support |var o = #{x, y}| as initializer shorthand for
12081 * |var o = #{x: x, y: y}|.
12083 TaggedParserAtomIndex name
= identifierReference(yieldHandling
);
12085 return errorResult();
12088 NameNodeType nameExpr
;
12089 MOZ_TRY_VAR(nameExpr
, identifierReference(name
));
12091 if (!handler_
.addShorthand(literal
, handler_
.asNameNode(propName
),
12093 return errorResult();
12096 error(JSMSG_BAD_PROP_ID
);
12097 return errorResult();
12102 if (!tokenStream
.matchToken(&matched
, TokenKind::Comma
,
12103 TokenStream::SlashIsInvalid
)) {
12104 return errorResult();
12111 if (!mustMatchToken(
12112 TokenKind::RightCurly
, [this, openedPos
](TokenKind actual
) {
12113 this->reportMissingClosing(JSMSG_CURLY_AFTER_LIST
,
12114 JSMSG_CURLY_OPENED
, openedPos
);
12116 return errorResult();
12119 handler_
.setEndPosition(literal
, pos().end
);
12123 template <class ParseHandler
, typename Unit
>
12124 typename
ParseHandler::ListNodeResult
12125 GeneralParser
<ParseHandler
, Unit
>::tupleLiteral(YieldHandling yieldHandling
) {
12126 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::HashBracket
));
12128 uint32_t begin
= pos().begin
;
12129 ListNodeType literal
;
12130 MOZ_TRY_VAR(literal
, handler_
.newTupleLiteral(begin
));
12132 for (uint32_t index
= 0;; index
++) {
12133 if (index
>= NativeObject::MAX_DENSE_ELEMENTS_COUNT
) {
12134 error(JSMSG_ARRAY_INIT_TOO_BIG
);
12135 return errorResult();
12139 if (!tokenStream
.peekToken(&tt
, TokenStream::SlashIsRegExp
)) {
12140 return errorResult();
12142 if (tt
== TokenKind::RightBracket
) {
12146 if (tt
== TokenKind::TripleDot
) {
12147 tokenStream
.consumeKnownToken(TokenKind::TripleDot
,
12148 TokenStream::SlashIsRegExp
);
12149 uint32_t begin
= pos().begin
;
12152 if (!tokenStream
.peekTokenPos(&innerPos
, TokenStream::SlashIsRegExp
)) {
12153 return errorResult();
12158 assignExpr(InAllowed
, yieldHandling
, TripledotProhibited
));
12160 if (!handler_
.addSpreadElement(literal
, begin
, inner
)) {
12161 return errorResult();
12164 TokenPos elementPos
;
12165 if (!tokenStream
.peekTokenPos(&elementPos
, TokenStream::SlashIsRegExp
)) {
12166 return errorResult();
12170 MOZ_TRY_VAR(element
,
12171 assignExpr(InAllowed
, yieldHandling
, TripledotProhibited
));
12172 handler_
.addArrayElement(literal
, element
);
12176 if (!tokenStream
.matchToken(&matched
, TokenKind::Comma
,
12177 TokenStream::SlashIsRegExp
)) {
12178 return errorResult();
12185 if (!mustMatchToken(TokenKind::RightBracket
, [this, begin
](TokenKind actual
) {
12186 this->reportMissingClosing(JSMSG_BRACKET_AFTER_LIST
,
12187 JSMSG_BRACKET_OPENED
, begin
);
12189 return errorResult();
12192 handler_
.setEndPosition(literal
, pos().end
);
12197 template <class ParseHandler
, typename Unit
>
12198 typename
ParseHandler::FunctionNodeResult
12199 GeneralParser
<ParseHandler
, Unit
>::methodDefinition(
12200 uint32_t toStringStart
, PropertyType propType
,
12201 TaggedParserAtomIndex funName
) {
12202 FunctionSyntaxKind syntaxKind
;
12203 switch (propType
) {
12204 case PropertyType::Getter
:
12205 syntaxKind
= FunctionSyntaxKind::Getter
;
12208 case PropertyType::Setter
:
12209 syntaxKind
= FunctionSyntaxKind::Setter
;
12212 case PropertyType::Method
:
12213 case PropertyType::GeneratorMethod
:
12214 case PropertyType::AsyncMethod
:
12215 case PropertyType::AsyncGeneratorMethod
:
12216 syntaxKind
= FunctionSyntaxKind::Method
;
12219 case PropertyType::Constructor
:
12220 syntaxKind
= FunctionSyntaxKind::ClassConstructor
;
12223 case PropertyType::DerivedConstructor
:
12224 syntaxKind
= FunctionSyntaxKind::DerivedClassConstructor
;
12228 MOZ_CRASH("unexpected property type");
12231 GeneratorKind generatorKind
= (propType
== PropertyType::GeneratorMethod
||
12232 propType
== PropertyType::AsyncGeneratorMethod
)
12233 ? GeneratorKind::Generator
12234 : GeneratorKind::NotGenerator
;
12236 FunctionAsyncKind asyncKind
= (propType
== PropertyType::AsyncMethod
||
12237 propType
== PropertyType::AsyncGeneratorMethod
)
12238 ? FunctionAsyncKind::AsyncFunction
12239 : FunctionAsyncKind::SyncFunction
;
12241 YieldHandling yieldHandling
= GetYieldHandling(generatorKind
);
12243 FunctionNodeType funNode
;
12244 MOZ_TRY_VAR(funNode
, handler_
.newFunction(syntaxKind
, pos()));
12246 return functionDefinition(funNode
, toStringStart
, InAllowed
, yieldHandling
,
12247 funName
, syntaxKind
, generatorKind
, asyncKind
);
12250 template <class ParseHandler
, typename Unit
>
12251 bool GeneralParser
<ParseHandler
, Unit
>::tryNewTarget(
12252 NewTargetNodeType
* newTarget
) {
12253 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::New
));
12255 *newTarget
= null();
12257 NullaryNodeType newHolder
;
12258 MOZ_TRY_VAR_OR_RETURN(newHolder
, handler_
.newPosHolder(pos()), false);
12260 uint32_t begin
= pos().begin
;
12262 // |new| expects to look for an operand, so we will honor that.
12264 if (!tokenStream
.getToken(&next
, TokenStream::SlashIsRegExp
)) {
12268 // Don't unget the token, since lookahead cannot handle someone calling
12269 // getToken() with a different modifier. Callers should inspect
12271 if (next
!= TokenKind::Dot
) {
12275 if (!tokenStream
.getToken(&next
)) {
12278 if (next
!= TokenKind::Target
) {
12279 error(JSMSG_UNEXPECTED_TOKEN
, "target", TokenKindToDesc(next
));
12283 if (!pc_
->sc()->allowNewTarget()) {
12284 errorAt(begin
, JSMSG_BAD_NEWTARGET
);
12288 NullaryNodeType targetHolder
;
12289 MOZ_TRY_VAR_OR_RETURN(targetHolder
, handler_
.newPosHolder(pos()), false);
12291 NameNodeType newTargetName
;
12292 MOZ_TRY_VAR_OR_RETURN(newTargetName
, newNewTargetName(), false);
12294 MOZ_TRY_VAR_OR_RETURN(
12295 *newTarget
, handler_
.newNewTarget(newHolder
, targetHolder
, newTargetName
),
12301 template <class ParseHandler
, typename Unit
>
12302 typename
ParseHandler::BinaryNodeResult
12303 GeneralParser
<ParseHandler
, Unit
>::importExpr(YieldHandling yieldHandling
,
12304 bool allowCallSyntax
) {
12305 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::Import
));
12307 NullaryNodeType importHolder
;
12308 MOZ_TRY_VAR(importHolder
, handler_
.newPosHolder(pos()));
12311 if (!tokenStream
.getToken(&next
)) {
12312 return errorResult();
12315 if (next
== TokenKind::Dot
) {
12316 if (!tokenStream
.getToken(&next
)) {
12317 return errorResult();
12319 if (next
!= TokenKind::Meta
) {
12320 error(JSMSG_UNEXPECTED_TOKEN
, "meta", TokenKindToDesc(next
));
12321 return errorResult();
12324 if (parseGoal() != ParseGoal::Module
) {
12325 errorAt(pos().begin
, JSMSG_IMPORT_META_OUTSIDE_MODULE
);
12326 return errorResult();
12329 NullaryNodeType metaHolder
;
12330 MOZ_TRY_VAR(metaHolder
, handler_
.newPosHolder(pos()));
12332 return handler_
.newImportMeta(importHolder
, metaHolder
);
12335 if (next
== TokenKind::LeftParen
&& allowCallSyntax
) {
12337 MOZ_TRY_VAR(arg
, assignExpr(InAllowed
, yieldHandling
, TripledotProhibited
));
12339 if (!tokenStream
.peekToken(&next
, TokenStream::SlashIsRegExp
)) {
12340 return errorResult();
12344 if (options().importAssertions()) {
12345 if (next
== TokenKind::Comma
) {
12346 tokenStream
.consumeKnownToken(TokenKind::Comma
,
12347 TokenStream::SlashIsRegExp
);
12349 if (!tokenStream
.peekToken(&next
, TokenStream::SlashIsRegExp
)) {
12350 return errorResult();
12353 if (next
!= TokenKind::RightParen
) {
12354 MOZ_TRY_VAR(optionalArg
, assignExpr(InAllowed
, yieldHandling
,
12355 TripledotProhibited
));
12357 if (!tokenStream
.peekToken(&next
, TokenStream::SlashIsRegExp
)) {
12358 return errorResult();
12361 if (next
== TokenKind::Comma
) {
12362 tokenStream
.consumeKnownToken(TokenKind::Comma
,
12363 TokenStream::SlashIsRegExp
);
12366 MOZ_TRY_VAR(optionalArg
,
12367 handler_
.newPosHolder(TokenPos(pos().end
, pos().end
)));
12370 MOZ_TRY_VAR(optionalArg
,
12371 handler_
.newPosHolder(TokenPos(pos().end
, pos().end
)));
12374 MOZ_TRY_VAR(optionalArg
,
12375 handler_
.newPosHolder(TokenPos(pos().end
, pos().end
)));
12378 if (!mustMatchToken(TokenKind::RightParen
, JSMSG_PAREN_AFTER_ARGS
)) {
12379 return errorResult();
12383 MOZ_TRY_VAR(spec
, handler_
.newCallImportSpec(arg
, optionalArg
));
12385 return handler_
.newCallImport(importHolder
, spec
);
12388 error(JSMSG_UNEXPECTED_TOKEN_NO_EXPECT
, TokenKindToDesc(next
));
12389 return errorResult();
12392 template <class ParseHandler
, typename Unit
>
12393 typename
ParseHandler::NodeResult
12394 GeneralParser
<ParseHandler
, Unit
>::primaryExpr(
12395 YieldHandling yieldHandling
, TripledotHandling tripledotHandling
,
12396 TokenKind tt
, PossibleError
* possibleError
, InvokedPrediction invoked
) {
12397 MOZ_ASSERT(anyChars
.isCurrentTokenType(tt
));
12398 AutoCheckRecursionLimit
recursion(this->fc_
);
12399 if (!recursion
.check(this->fc_
)) {
12400 return errorResult();
12404 case TokenKind::Function
:
12405 return functionExpr(pos().begin
, invoked
,
12406 FunctionAsyncKind::SyncFunction
);
12408 case TokenKind::Class
:
12409 return classDefinition(yieldHandling
, ClassExpression
, NameRequired
);
12411 case TokenKind::LeftBracket
:
12412 return arrayInitializer(yieldHandling
, possibleError
);
12414 case TokenKind::LeftCurly
:
12415 return objectLiteral(yieldHandling
, possibleError
);
12417 #ifdef ENABLE_RECORD_TUPLE
12418 case TokenKind::HashCurly
:
12419 return recordLiteral(yieldHandling
);
12421 case TokenKind::HashBracket
:
12422 return tupleLiteral(yieldHandling
);
12425 #ifdef ENABLE_DECORATORS
12426 case TokenKind::At
:
12427 return classDefinition(yieldHandling
, ClassExpression
, NameRequired
);
12430 case TokenKind::LeftParen
: {
12432 if (!tokenStream
.peekToken(&next
, TokenStream::SlashIsRegExp
)) {
12433 return errorResult();
12436 if (next
== TokenKind::RightParen
) {
12437 // Not valid expression syntax, but this is valid in an arrow function
12438 // with no params: `() => body`.
12439 tokenStream
.consumeKnownToken(TokenKind::RightParen
,
12440 TokenStream::SlashIsRegExp
);
12442 if (!tokenStream
.peekToken(&next
)) {
12443 return errorResult();
12445 if (next
!= TokenKind::Arrow
) {
12446 error(JSMSG_UNEXPECTED_TOKEN
, "expression",
12447 TokenKindToDesc(TokenKind::RightParen
));
12448 return errorResult();
12451 // Now just return something that will allow parsing to continue.
12452 // It doesn't matter what; when we reach the =>, we will rewind and
12453 // reparse the whole arrow function. See Parser::assignExpr.
12454 return handler_
.newNullLiteral(pos());
12457 // Pass |possibleError| to support destructuring in arrow parameters.
12459 MOZ_TRY_VAR(expr
, exprInParens(InAllowed
, yieldHandling
, TripledotAllowed
,
12461 if (!mustMatchToken(TokenKind::RightParen
, JSMSG_PAREN_IN_PAREN
)) {
12462 return errorResult();
12464 return handler_
.parenthesize(expr
);
12467 case TokenKind::TemplateHead
:
12468 return templateLiteral(yieldHandling
);
12470 case TokenKind::NoSubsTemplate
:
12471 return noSubstitutionUntaggedTemplate();
12473 case TokenKind::String
:
12474 return stringLiteral();
12477 if (!TokenKindIsPossibleIdentifier(tt
)) {
12478 error(JSMSG_UNEXPECTED_TOKEN
, "expression", TokenKindToDesc(tt
));
12479 return errorResult();
12482 if (tt
== TokenKind::Async
) {
12483 TokenKind nextSameLine
= TokenKind::Eof
;
12484 if (!tokenStream
.peekTokenSameLine(&nextSameLine
)) {
12485 return errorResult();
12488 if (nextSameLine
== TokenKind::Function
) {
12489 uint32_t toStringStart
= pos().begin
;
12490 tokenStream
.consumeKnownToken(TokenKind::Function
);
12491 return functionExpr(toStringStart
, PredictUninvoked
,
12492 FunctionAsyncKind::AsyncFunction
);
12496 TaggedParserAtomIndex name
= identifierReference(yieldHandling
);
12498 return errorResult();
12501 return identifierReference(name
);
12504 case TokenKind::RegExp
:
12505 return newRegExp();
12507 case TokenKind::Number
:
12508 return newNumber(anyChars
.currentToken());
12510 case TokenKind::BigInt
:
12511 return newBigInt();
12513 case TokenKind::True
:
12514 return handler_
.newBooleanLiteral(true, pos());
12515 case TokenKind::False
:
12516 return handler_
.newBooleanLiteral(false, pos());
12517 case TokenKind::This
: {
12518 NameNodeType thisName
= null();
12519 if (pc_
->sc()->hasFunctionThisBinding()) {
12520 MOZ_TRY_VAR(thisName
, newThisName());
12522 return handler_
.newThisLiteral(pos(), thisName
);
12524 case TokenKind::Null
:
12525 return handler_
.newNullLiteral(pos());
12527 case TokenKind::TripleDot
: {
12528 // This isn't valid expression syntax, but it's valid in an arrow
12529 // function as a trailing rest param: `(a, b, ...rest) => body`. Check
12530 // if it's directly under
12531 // CoverParenthesizedExpressionAndArrowParameterList, and check for a
12532 // name, closing parenthesis, and arrow, and allow it only if all are
12534 if (tripledotHandling
!= TripledotAllowed
) {
12535 error(JSMSG_UNEXPECTED_TOKEN
, "expression", TokenKindToDesc(tt
));
12536 return errorResult();
12540 if (!tokenStream
.getToken(&next
)) {
12541 return errorResult();
12544 if (next
== TokenKind::LeftBracket
|| next
== TokenKind::LeftCurly
) {
12545 // Validate, but don't store the pattern right now. The whole arrow
12546 // function is reparsed in functionFormalParametersAndBody().
12547 MOZ_TRY(destructuringDeclaration(DeclarationKind::CoverArrowParameter
,
12548 yieldHandling
, next
));
12550 // This doesn't check that the provided name is allowed, e.g. if
12551 // the enclosing code is strict mode code, any of "let", "yield",
12552 // or "arguments" should be prohibited. Argument-parsing code
12554 if (!TokenKindIsPossibleIdentifier(next
)) {
12555 error(JSMSG_UNEXPECTED_TOKEN
, "rest argument name",
12556 TokenKindToDesc(next
));
12557 return errorResult();
12561 if (!tokenStream
.getToken(&next
)) {
12562 return errorResult();
12564 if (next
!= TokenKind::RightParen
) {
12565 error(JSMSG_UNEXPECTED_TOKEN
, "closing parenthesis",
12566 TokenKindToDesc(next
));
12567 return errorResult();
12570 if (!tokenStream
.peekToken(&next
)) {
12571 return errorResult();
12573 if (next
!= TokenKind::Arrow
) {
12574 // Advance the scanner for proper error location reporting.
12575 tokenStream
.consumeKnownToken(next
);
12576 error(JSMSG_UNEXPECTED_TOKEN
, "'=>' after argument list",
12577 TokenKindToDesc(next
));
12578 return errorResult();
12581 anyChars
.ungetToken(); // put back right paren
12583 // Return an arbitrary expression node. See case TokenKind::RightParen
12585 return handler_
.newNullLiteral(pos());
12590 template <class ParseHandler
, typename Unit
>
12591 typename
ParseHandler::NodeResult
12592 GeneralParser
<ParseHandler
, Unit
>::exprInParens(
12593 InHandling inHandling
, YieldHandling yieldHandling
,
12594 TripledotHandling tripledotHandling
,
12595 PossibleError
* possibleError
/* = nullptr */) {
12596 MOZ_ASSERT(anyChars
.isCurrentTokenType(TokenKind::LeftParen
));
12597 return expr(inHandling
, yieldHandling
, tripledotHandling
, possibleError
,
12601 template class PerHandlerParser
<FullParseHandler
>;
12602 template class PerHandlerParser
<SyntaxParseHandler
>;
12603 template class GeneralParser
<FullParseHandler
, Utf8Unit
>;
12604 template class GeneralParser
<SyntaxParseHandler
, Utf8Unit
>;
12605 template class GeneralParser
<FullParseHandler
, char16_t
>;
12606 template class GeneralParser
<SyntaxParseHandler
, char16_t
>;
12607 template class Parser
<FullParseHandler
, Utf8Unit
>;
12608 template class Parser
<SyntaxParseHandler
, Utf8Unit
>;
12609 template class Parser
<FullParseHandler
, char16_t
>;
12610 template class Parser
<SyntaxParseHandler
, char16_t
>;
12612 } // namespace js::frontend