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/. */
6 
7 /*
8  * JS parser.
9  *
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.
16  *
17  * This parser attempts no error recovery.
18  */
19 
20 #include "frontend/Parser.h"
21 
22 #include "mozilla/ArrayUtils.h"
23 #include "mozilla/Casting.h"
24 #include "mozilla/Range.h"
25 #include "mozilla/Sprintf.h"
26 #include "mozilla/Utf8.h"
27 #include "mozilla/Variant.h"
28 
29 #include <memory>
30 #include <new>
31 #include <type_traits>
32 
33 #include "jsnum.h"
34 #include "jstypes.h"
35 
36 #include "frontend/BytecodeCompiler.h"
37 #include "frontend/FoldConstants.h"
38 #include "frontend/FunctionSyntaxKind.h"  // FunctionSyntaxKind
39 #include "frontend/ModuleSharedContext.h"
40 #include "frontend/ParseNode.h"
41 #include "frontend/ParseNodeVerify.h"
42 #include "frontend/ParserAtom.h"  // TaggedParserAtomIndex, ParserAtomsTable, ParserAtom
43 #include "frontend/ScriptIndex.h"  // ScriptIndex
44 #include "frontend/TokenStream.h"
45 #include "irregexp/RegExpAPI.h"
46 #include "js/friend/ErrorMessages.h"  // js::GetErrorMessage, JSMSG_*
47 #include "js/HashTable.h"
48 #include "js/RegExpFlags.h"     // JS::RegExpFlags
49 #include "util/StringBuffer.h"  // StringBuffer
50 #include "vm/BytecodeUtil.h"
51 #include "vm/FunctionFlags.h"          // js::FunctionFlags
52 #include "vm/GeneratorAndAsyncKind.h"  // js::GeneratorKind, js::FunctionAsyncKind
53 #include "vm/JSContext.h"
54 #include "vm/JSScript.h"
55 #include "vm/ModuleBuilder.h"  // js::ModuleBuilder
56 #include "vm/Scope.h"          // GetScopeDataTrailingNames
57 #include "vm/WellKnownAtom.h"  // js_*_str
58 #include "wasm/AsmJS.h"
59 
60 #include "frontend/ParseContext-inl.h"
61 #include "frontend/SharedContext-inl.h"
62 
63 using namespace js;
64 
65 using mozilla::AssertedCast;
66 using mozilla::AsVariant;
67 using mozilla::Maybe;
68 using mozilla::Nothing;
69 using mozilla::PointerRangeSize;
70 using mozilla::Some;
71 using mozilla::Utf8Unit;
72 
73 using JS::ReadOnlyCompileOptions;
74 using JS::RegExpFlags;
75 
76 namespace js::frontend {
77 
78 using DeclaredNamePtr = ParseContext::Scope::DeclaredNamePtr;
79 using AddDeclaredNamePtr = ParseContext::Scope::AddDeclaredNamePtr;
80 using BindingIter = ParseContext::Scope::BindingIter;
81 using UsedNamePtr = UsedNameTracker::UsedNameMap::Ptr;
82 
83 using ParserBindingNameVector = Vector<ParserBindingName, 6>;
84 
85 template <class T, class U>
PropagateTransitiveParseFlags(const T * inner,U * outer)86 static inline void PropagateTransitiveParseFlags(const T* inner, U* outer) {
87   if (inner->bindingsAccessedDynamically()) {
88     outer->setBindingsAccessedDynamically();
89   }
90   if (inner->hasDirectEval()) {
91     outer->setHasDirectEval();
92   }
93 }
94 
StatementKindIsBraced(StatementKind kind)95 static bool StatementKindIsBraced(StatementKind kind) {
96   return kind == StatementKind::Block || kind == StatementKind::Switch ||
97          kind == StatementKind::Try || kind == StatementKind::Catch ||
98          kind == StatementKind::Finally;
99 }
100 
101 template <class ParseHandler, typename Unit>
102 inline typename GeneralParser<ParseHandler, Unit>::FinalParser*
asFinalParser()103 GeneralParser<ParseHandler, Unit>::asFinalParser() {
104   static_assert(
105       std::is_base_of_v<GeneralParser<ParseHandler, Unit>, FinalParser>,
106       "inheritance relationship required by the static_cast<> below");
107 
108   return static_cast<FinalParser*>(this);
109 }
110 
111 template <class ParseHandler, typename Unit>
112 inline const typename GeneralParser<ParseHandler, Unit>::FinalParser*
asFinalParser() const113 GeneralParser<ParseHandler, Unit>::asFinalParser() const {
114   static_assert(
115       std::is_base_of_v<GeneralParser<ParseHandler, Unit>, FinalParser>,
116       "inheritance relationship required by the static_cast<> below");
117 
118   return static_cast<const FinalParser*>(this);
119 }
120 
121 template <class ParseHandler, typename Unit>
122 template <typename ConditionT, typename ErrorReportT>
mustMatchTokenInternal(ConditionT condition,ErrorReportT errorReport)123 bool GeneralParser<ParseHandler, Unit>::mustMatchTokenInternal(
124     ConditionT condition, ErrorReportT errorReport) {
125   MOZ_ASSERT(condition(TokenKind::Div) == false);
126   MOZ_ASSERT(condition(TokenKind::DivAssign) == false);
127   MOZ_ASSERT(condition(TokenKind::RegExp) == false);
128 
129   TokenKind actual;
130   if (!tokenStream.getToken(&actual, TokenStream::SlashIsInvalid)) {
131     return false;
132   }
133   if (!condition(actual)) {
134     errorReport(actual);
135     return false;
136   }
137   return true;
138 }
139 
ParserSharedBase(JSContext * cx,CompilationState & compilationState,Kind kind)140 ParserSharedBase::ParserSharedBase(JSContext* cx,
141                                    CompilationState& compilationState,
142                                    Kind kind)
143     : cx_(cx),
144       alloc_(compilationState.parserAllocScope.alloc()),
145       compilationState_(compilationState),
146       pc_(nullptr),
147       usedNames_(compilationState.usedNames) {
148   cx->frontendCollectionPool().addActiveCompilation();
149 }
150 
~ParserSharedBase()151 ParserSharedBase::~ParserSharedBase() {
152   cx_->frontendCollectionPool().removeActiveCompilation();
153 }
154 
155 #if defined(DEBUG) || defined(JS_JITSPEW)
dumpAtom(TaggedParserAtomIndex index) const156 void ParserSharedBase::dumpAtom(TaggedParserAtomIndex index) const {
157   parserAtoms().dump(index);
158 }
159 #endif
160 
ParserBase(JSContext * cx,const ReadOnlyCompileOptions & options,bool foldConstants,CompilationState & compilationState)161 ParserBase::ParserBase(JSContext* cx, const ReadOnlyCompileOptions& options,
162                        bool foldConstants, CompilationState& compilationState)
163     : ParserSharedBase(cx, compilationState, ParserSharedBase::Kind::Parser),
164       anyChars(cx, options, this),
165       ss(nullptr),
166       foldConstants_(foldConstants),
167 #ifdef DEBUG
168       checkOptionsCalled_(false),
169 #endif
170       isUnexpectedEOF_(false),
171       awaitHandling_(AwaitIsName),
172       inParametersOfAsyncFunction_(false) {
173 }
174 
checkOptions()175 bool ParserBase::checkOptions() {
176 #ifdef DEBUG
177   checkOptionsCalled_ = true;
178 #endif
179 
180   return anyChars.checkOptions();
181 }
182 
~ParserBase()183 ParserBase::~ParserBase() { MOZ_ASSERT(checkOptionsCalled_); }
184 
185 template <class ParseHandler>
PerHandlerParser(JSContext * cx,const ReadOnlyCompileOptions & options,bool foldConstants,CompilationState & compilationState,void * internalSyntaxParser)186 PerHandlerParser<ParseHandler>::PerHandlerParser(
187     JSContext* cx, const ReadOnlyCompileOptions& options, bool foldConstants,
188     CompilationState& compilationState, void* internalSyntaxParser)
189     : ParserBase(cx, options, foldConstants, compilationState),
190       handler_(cx, compilationState),
191       internalSyntaxParser_(internalSyntaxParser) {
192   MOZ_ASSERT(compilationState.isInitialStencil() ==
193              compilationState.input.isInitialStencil());
194 }
195 
196 template <class ParseHandler, typename Unit>
GeneralParser(JSContext * cx,const ReadOnlyCompileOptions & options,const Unit * units,size_t length,bool foldConstants,CompilationState & compilationState,SyntaxParser * syntaxParser)197 GeneralParser<ParseHandler, Unit>::GeneralParser(
198     JSContext* cx, const ReadOnlyCompileOptions& options, const Unit* units,
199     size_t length, bool foldConstants, CompilationState& compilationState,
200     SyntaxParser* syntaxParser)
201     : Base(cx, options, foldConstants, compilationState, syntaxParser),
202       tokenStream(cx, &compilationState.parserAtoms, options, units, length) {}
203 
204 template <typename Unit>
setAwaitHandling(AwaitHandling awaitHandling)205 void Parser<SyntaxParseHandler, Unit>::setAwaitHandling(
206     AwaitHandling awaitHandling) {
207   this->awaitHandling_ = awaitHandling;
208 }
209 
210 template <typename Unit>
setAwaitHandling(AwaitHandling awaitHandling)211 void Parser<FullParseHandler, Unit>::setAwaitHandling(
212     AwaitHandling awaitHandling) {
213   this->awaitHandling_ = awaitHandling;
214   if (SyntaxParser* syntaxParser = getSyntaxParser()) {
215     syntaxParser->setAwaitHandling(awaitHandling);
216   }
217 }
218 
219 template <class ParseHandler, typename Unit>
setAwaitHandling(AwaitHandling awaitHandling)220 inline void GeneralParser<ParseHandler, Unit>::setAwaitHandling(
221     AwaitHandling awaitHandling) {
222   asFinalParser()->setAwaitHandling(awaitHandling);
223 }
224 
225 template <typename Unit>
setInParametersOfAsyncFunction(bool inParameters)226 void Parser<SyntaxParseHandler, Unit>::setInParametersOfAsyncFunction(
227     bool inParameters) {
228   this->inParametersOfAsyncFunction_ = inParameters;
229 }
230 
231 template <typename Unit>
setInParametersOfAsyncFunction(bool inParameters)232 void Parser<FullParseHandler, Unit>::setInParametersOfAsyncFunction(
233     bool inParameters) {
234   this->inParametersOfAsyncFunction_ = inParameters;
235   if (SyntaxParser* syntaxParser = getSyntaxParser()) {
236     syntaxParser->setInParametersOfAsyncFunction(inParameters);
237   }
238 }
239 
240 template <class ParseHandler, typename Unit>
setInParametersOfAsyncFunction(bool inParameters)241 inline void GeneralParser<ParseHandler, Unit>::setInParametersOfAsyncFunction(
242     bool inParameters) {
243   asFinalParser()->setInParametersOfAsyncFunction(inParameters);
244 }
245 
246 template <class ParseHandler>
newFunctionBox(FunctionNodeType funNode,TaggedParserAtomIndex explicitName,FunctionFlags flags,uint32_t toStringStart,Directives inheritedDirectives,GeneratorKind generatorKind,FunctionAsyncKind asyncKind)247 FunctionBox* PerHandlerParser<ParseHandler>::newFunctionBox(
248     FunctionNodeType funNode, TaggedParserAtomIndex explicitName,
249     FunctionFlags flags, uint32_t toStringStart, Directives inheritedDirectives,
250     GeneratorKind generatorKind, FunctionAsyncKind asyncKind) {
251   MOZ_ASSERT(funNode);
252 
253   ScriptIndex index = ScriptIndex(compilationState_.scriptData.length());
254   if (uint32_t(index) >= TaggedScriptThingIndex::IndexLimit) {
255     ReportAllocationOverflow(cx_);
256     return nullptr;
257   }
258   if (!compilationState_.appendScriptStencilAndData(cx_)) {
259     return nullptr;
260   }
261 
262   bool isInitialStencil = compilationState_.isInitialStencil();
263 
264   // This source extent will be further filled in during the remainder of parse.
265   SourceExtent extent;
266   extent.toStringStart = toStringStart;
267 
268   /*
269    * We use JSContext.tempLifoAlloc to allocate parsed objects and place them
270    * on a list in this Parser to ensure GC safety. Thus the tempLifoAlloc
271    * arenas containing the entries must be alive until we are done with
272    * scanning, parsing and code generation for the whole script or top-level
273    * function.
274    */
275   FunctionBox* funbox = alloc_.new_<FunctionBox>(
276       cx_, extent, compilationState_, inheritedDirectives, generatorKind,
277       asyncKind, isInitialStencil, explicitName, flags, index);
278   if (!funbox) {
279     ReportOutOfMemory(cx_);
280     return nullptr;
281   }
282 
283   handler_.setFunctionBox(funNode, funbox);
284 
285   return funbox;
286 }
287 
288 template <class ParseHandler>
newFunctionBox(FunctionNodeType funNode,const ScriptStencil & cachedScriptData,const ScriptStencilExtra & cachedScriptExtra)289 FunctionBox* PerHandlerParser<ParseHandler>::newFunctionBox(
290     FunctionNodeType funNode, const ScriptStencil& cachedScriptData,
291     const ScriptStencilExtra& cachedScriptExtra) {
292   MOZ_ASSERT(funNode);
293 
294   ScriptIndex index = ScriptIndex(compilationState_.scriptData.length());
295   if (uint32_t(index) >= TaggedScriptThingIndex::IndexLimit) {
296     ReportAllocationOverflow(cx_);
297     return nullptr;
298   }
299   if (!compilationState_.appendScriptStencilAndData(cx_)) {
300     return nullptr;
301   }
302 
303   /*
304    * We use JSContext.tempLifoAlloc to allocate parsed objects and place them
305    * on a list in this Parser to ensure GC safety. Thus the tempLifoAlloc
306    * arenas containing the entries must be alive until we are done with
307    * scanning, parsing and code generation for the whole script or top-level
308    * function.
309    */
310   FunctionBox* funbox = alloc_.new_<FunctionBox>(
311       cx_, cachedScriptExtra.extent, compilationState_,
312       Directives(/* strict = */ false), cachedScriptExtra.generatorKind(),
313       cachedScriptExtra.asyncKind(), compilationState_.isInitialStencil(),
314       cachedScriptData.functionAtom, cachedScriptData.functionFlags, index);
315   if (!funbox) {
316     ReportOutOfMemory(cx_);
317     return nullptr;
318   }
319 
320   handler_.setFunctionBox(funNode, funbox);
321   funbox->initFromScriptStencilExtra(cachedScriptExtra);
322 
323   return funbox;
324 }
325 
setSourceMapInfo()326 bool ParserBase::setSourceMapInfo() {
327   // If support for source pragmas have been fully disabled, we can skip
328   // processing of all of these values.
329   if (!options().sourcePragmas()) {
330     return true;
331   }
332 
333   // Not all clients initialize ss. Can't update info to an object that isn't
334   // there.
335   if (!ss) {
336     return true;
337   }
338 
339   if (anyChars.hasDisplayURL()) {
340     if (!ss->setDisplayURL(cx_, anyChars.displayURL())) {
341       return false;
342     }
343   }
344 
345   if (anyChars.hasSourceMapURL()) {
346     MOZ_ASSERT(!ss->hasSourceMapURL());
347     if (!ss->setSourceMapURL(cx_, anyChars.sourceMapURL())) {
348       return false;
349     }
350   }
351 
352   /*
353    * Source map URLs passed as a compile option (usually via a HTTP source map
354    * header) override any source map urls passed as comment pragmas.
355    */
356   if (options().sourceMapURL()) {
357     // Warn about the replacement, but use the new one.
358     if (ss->hasSourceMapURL()) {
359       if (!warningNoOffset(JSMSG_ALREADY_HAS_PRAGMA, ss->filename(),
360                            "//# sourceMappingURL")) {
361         return false;
362       }
363     }
364 
365     if (!ss->setSourceMapURL(cx_, options().sourceMapURL())) {
366       return false;
367     }
368   }
369 
370   return true;
371 }
372 
373 /*
374  * Parse a top-level JS script.
375  */
376 template <class ParseHandler, typename Unit>
parse()377 typename ParseHandler::ListNodeType GeneralParser<ParseHandler, Unit>::parse() {
378   MOZ_ASSERT(checkOptionsCalled_);
379 
380   SourceExtent extent = SourceExtent::makeGlobalExtent(
381       /* len = */ 0, options().lineno, options().column);
382   Directives directives(options().forceStrictMode());
383   GlobalSharedContext globalsc(cx_, ScopeKind::Global, options(), directives,
384                                extent);
385   SourceParseContext globalpc(this, &globalsc, /* newDirectives = */ nullptr);
386   if (!globalpc.init()) {
387     return null();
388   }
389 
390   ParseContext::VarScope varScope(this);
391   if (!varScope.init(pc_)) {
392     return null();
393   }
394 
395   ListNodeType stmtList = statementList(YieldIsName);
396   if (!stmtList) {
397     return null();
398   }
399 
400   TokenKind tt;
401   if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) {
402     return null();
403   }
404   if (tt != TokenKind::Eof) {
405     error(JSMSG_GARBAGE_AFTER_INPUT, "script", TokenKindToDesc(tt));
406     return null();
407   }
408 
409   if (!CheckParseTree(cx_, alloc_, stmtList)) {
410     return null();
411   }
412 
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(cx_, this->parserAtoms(), &node, &handler_)) {
419         return null();
420       }
421     }
422     stmtList = handler_.asList(node);
423   }
424 
425   return stmtList;
426 }
427 
428 /*
429  * Strict mode forbids introducing new definitions for 'eval', 'arguments',
430  * 'let', 'static', 'yield', or for any strict mode reserved word.
431  */
isValidStrictBinding(TaggedParserAtomIndex name)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();
437   }
438   return tt != TokenKind::Let && tt != TokenKind::Static &&
439          tt != TokenKind::Yield && !TokenKindIsStrictReservedWord(tt);
440 }
441 
442 /*
443  * Returns true if all parameter names are valid strict mode binding names and
444  * no duplicate parameter names are present.
445  */
hasValidSimpleStrictParameterNames()446 bool ParserBase::hasValidSimpleStrictParameterNames() {
447   MOZ_ASSERT(pc_->isFunctionBox() &&
448              pc_->functionBox()->hasSimpleParameterList());
449 
450   if (pc_->functionBox()->hasDuplicateParameters) {
451     return false;
452   }
453 
454   for (auto name : pc_->positionalFormalParameterNames()) {
455     MOZ_ASSERT(name);
456     if (!isValidStrictBinding(name)) {
457       return false;
458     }
459   }
460   return true;
461 }
462 
463 template <class ParseHandler, typename Unit>
reportMissingClosing(unsigned errorNumber,unsigned noteNumber,uint32_t openedPos)464 void GeneralParser<ParseHandler, Unit>::reportMissingClosing(
465     unsigned errorNumber, unsigned noteNumber, uint32_t openedPos) {
466   auto notes = MakeUnique<JSErrorNotes>();
467   if (!notes) {
468     ReportOutOfMemory(pc_->sc()->cx_);
469     return;
470   }
471 
472   uint32_t line, column;
473   tokenStream.computeLineAndColumn(openedPos, &line, &column);
474 
475   const size_t MaxWidth = sizeof("4294967295");
476   char columnNumber[MaxWidth];
477   SprintfLiteral(columnNumber, "%" PRIu32, column);
478   char lineNumber[MaxWidth];
479   SprintfLiteral(lineNumber, "%" PRIu32, line);
480 
481   if (!notes->addNoteASCII(pc_->sc()->cx_, getFilename(), 0, line, column,
482                            GetErrorMessage, nullptr, noteNumber, lineNumber,
483                            columnNumber)) {
484     return;
485   }
486 
487   errorWithNotes(std::move(notes), errorNumber);
488 }
489 
490 template <class ParseHandler, typename Unit>
reportRedeclaration(TaggedParserAtomIndex name,DeclarationKind prevKind,TokenPos pos,uint32_t prevPos)491 void GeneralParser<ParseHandler, Unit>::reportRedeclaration(
492     TaggedParserAtomIndex name, DeclarationKind prevKind, TokenPos pos,
493     uint32_t prevPos) {
494   UniqueChars bytes = this->parserAtoms().toPrintableString(cx_, name);
495   if (!bytes) {
496     return;
497   }
498 
499   if (prevPos == DeclaredNameInfo::npos) {
500     errorAt(pos.begin, JSMSG_REDECLARED_VAR, DeclarationKindString(prevKind),
501             bytes.get());
502     return;
503   }
504 
505   auto notes = MakeUnique<JSErrorNotes>();
506   if (!notes) {
507     ReportOutOfMemory(pc_->sc()->cx_);
508     return;
509   }
510 
511   uint32_t line, column;
512   tokenStream.computeLineAndColumn(prevPos, &line, &column);
513 
514   const size_t MaxWidth = sizeof("4294967295");
515   char columnNumber[MaxWidth];
516   SprintfLiteral(columnNumber, "%" PRIu32, column);
517   char lineNumber[MaxWidth];
518   SprintfLiteral(lineNumber, "%" PRIu32, line);
519 
520   if (!notes->addNoteASCII(pc_->sc()->cx_, getFilename(), 0, line, column,
521                            GetErrorMessage, nullptr, JSMSG_REDECLARED_PREV,
522                            lineNumber, columnNumber)) {
523     return;
524   }
525 
526   errorWithNotesAt(std::move(notes), pos.begin, JSMSG_REDECLARED_VAR,
527                    DeclarationKindString(prevKind), bytes.get());
528 }
529 
530 // notePositionalFormalParameter is called for both the arguments of a regular
531 // function definition and the arguments specified by the Function
532 // constructor.
533 //
534 // The 'disallowDuplicateParams' bool indicates whether the use of another
535 // feature (destructuring or default arguments) disables duplicate arguments.
536 // (ECMA-262 requires us to support duplicate parameter names, but, for newer
537 // features, we consider the code to have "opted in" to higher standards and
538 // forbid duplicates.)
539 template <class ParseHandler, typename Unit>
notePositionalFormalParameter(FunctionNodeType funNode,TaggedParserAtomIndex name,uint32_t beginPos,bool disallowDuplicateParams,bool * duplicatedParam)540 bool GeneralParser<ParseHandler, Unit>::notePositionalFormalParameter(
541     FunctionNodeType funNode, TaggedParserAtomIndex name, uint32_t beginPos,
542     bool disallowDuplicateParams, bool* duplicatedParam) {
543   if (AddDeclaredNamePtr p =
544           pc_->functionScope().lookupDeclaredNameForAdd(name)) {
545     if (disallowDuplicateParams) {
546       error(JSMSG_BAD_DUP_ARGS);
547       return false;
548     }
549 
550     // Strict-mode disallows duplicate args. We may not know whether we are
551     // in strict mode or not (since the function body hasn't been parsed).
552     // In such cases, report will queue up the potential error and return
553     // 'true'.
554     if (pc_->sc()->strict()) {
555       UniqueChars bytes = this->parserAtoms().toPrintableString(cx_, name);
556       if (!bytes) {
557         return false;
558       }
559       if (!strictModeError(JSMSG_DUPLICATE_FORMAL, bytes.get())) {
560         return false;
561       }
562     }
563 
564     *duplicatedParam = true;
565   } else {
566     DeclarationKind kind = DeclarationKind::PositionalFormalParameter;
567     if (!pc_->functionScope().addDeclaredName(pc_, p, name, kind, beginPos)) {
568       return false;
569     }
570   }
571 
572   if (!pc_->positionalFormalParameterNames().append(
573           TrivialTaggedParserAtomIndex::from(name))) {
574     ReportOutOfMemory(cx_);
575     return false;
576   }
577 
578   NameNodeType paramNode = newName(name);
579   if (!paramNode) {
580     return false;
581   }
582 
583   handler_.addFunctionFormalParameter(funNode, paramNode);
584   return true;
585 }
586 
587 template <class ParseHandler>
noteDestructuredPositionalFormalParameter(FunctionNodeType funNode,Node destruct)588 bool PerHandlerParser<ParseHandler>::noteDestructuredPositionalFormalParameter(
589     FunctionNodeType funNode, Node destruct) {
590   // Append an empty name to the positional formals vector to keep track of
591   // argument slots when making FunctionScope::ParserData.
592   if (!pc_->positionalFormalParameterNames().append(
593           TrivialTaggedParserAtomIndex::null())) {
594     ReportOutOfMemory(cx_);
595     return false;
596   }
597 
598   handler_.addFunctionFormalParameter(funNode, destruct);
599   return true;
600 }
601 
602 template <class ParseHandler, typename Unit>
noteDeclaredName(TaggedParserAtomIndex name,DeclarationKind kind,TokenPos pos,ClosedOver isClosedOver)603 bool GeneralParser<ParseHandler, Unit>::noteDeclaredName(
604     TaggedParserAtomIndex name, DeclarationKind kind, TokenPos pos,
605     ClosedOver isClosedOver) {
606   // The asm.js validator does all its own symbol-table management so, as an
607   // optimization, avoid doing any work here.
608   if (pc_->useAsmOrInsideUseAsm()) {
609     return true;
610   }
611 
612   switch (kind) {
613     case DeclarationKind::Var:
614     case DeclarationKind::BodyLevelFunction: {
615       Maybe<DeclarationKind> redeclaredKind;
616       uint32_t prevPos;
617       if (!pc_->tryDeclareVar(name, this, kind, pos.begin, &redeclaredKind,
618                               &prevPos)) {
619         return false;
620       }
621 
622       if (redeclaredKind) {
623         reportRedeclaration(name, *redeclaredKind, pos, prevPos);
624         return false;
625       }
626 
627       break;
628     }
629 
630     case DeclarationKind::ModuleBodyLevelFunction: {
631       MOZ_ASSERT(pc_->atModuleLevel());
632 
633       AddDeclaredNamePtr p = pc_->varScope().lookupDeclaredNameForAdd(name);
634       if (p) {
635         reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos());
636         return false;
637       }
638 
639       if (!pc_->varScope().addDeclaredName(pc_, p, name, kind, pos.begin,
640                                            isClosedOver)) {
641         return false;
642       }
643 
644       // Body-level functions in modules are always closed over.
645       pc_->varScope().lookupDeclaredName(name)->value()->setClosedOver();
646 
647       break;
648     }
649 
650     case DeclarationKind::FormalParameter: {
651       // It is an early error if any non-positional formal parameter name
652       // (e.g., destructuring formal parameter) is duplicated.
653 
654       AddDeclaredNamePtr p =
655           pc_->functionScope().lookupDeclaredNameForAdd(name);
656       if (p) {
657         error(JSMSG_BAD_DUP_ARGS);
658         return false;
659       }
660 
661       if (!pc_->functionScope().addDeclaredName(pc_, p, name, kind, pos.begin,
662                                                 isClosedOver)) {
663         return false;
664       }
665 
666       break;
667     }
668 
669     case DeclarationKind::LexicalFunction:
670     case DeclarationKind::PrivateName:
671     case DeclarationKind::Synthetic:
672     case DeclarationKind::PrivateMethod: {
673       ParseContext::Scope* scope = pc_->innermostScope();
674       AddDeclaredNamePtr p = scope->lookupDeclaredNameForAdd(name);
675       if (p) {
676         reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos());
677         return false;
678       }
679 
680       if (!scope->addDeclaredName(pc_, p, name, kind, pos.begin,
681                                   isClosedOver)) {
682         return false;
683       }
684 
685       break;
686     }
687 
688     case DeclarationKind::SloppyLexicalFunction: {
689       // Functions in block have complex allowances in sloppy mode for being
690       // labelled that other lexical declarations do not have. Those checks
691       // are more complex than calling checkLexicalDeclarationDirectlyWithin-
692       // Block and are done in checkFunctionDefinition.
693 
694       ParseContext::Scope* scope = pc_->innermostScope();
695       if (AddDeclaredNamePtr p = scope->lookupDeclaredNameForAdd(name)) {
696         // It is usually an early error if there is another declaration
697         // with the same name in the same scope.
698         //
699         // Sloppy lexical functions may redeclare other sloppy lexical
700         // functions for web compatibility reasons.
701         if (p->value()->kind() != DeclarationKind::SloppyLexicalFunction) {
702           reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos());
703           return false;
704         }
705       } else {
706         if (!scope->addDeclaredName(pc_, p, name, kind, pos.begin,
707                                     isClosedOver)) {
708           return false;
709         }
710       }
711 
712       break;
713     }
714 
715     case DeclarationKind::Let:
716     case DeclarationKind::Const:
717     case DeclarationKind::Class:
718       // The BoundNames of LexicalDeclaration and ForDeclaration must not
719       // contain 'let'. (CatchParameter is the only lexical binding form
720       // without this restriction.)
721       if (name == TaggedParserAtomIndex::WellKnown::let()) {
722         errorAt(pos.begin, JSMSG_LEXICAL_DECL_DEFINES_LET);
723         return false;
724       }
725 
726       // For body-level lexically declared names in a function, it is an
727       // early error if there is a formal parameter of the same name. This
728       // needs a special check if there is an extra var scope due to
729       // parameter expressions.
730       if (pc_->isFunctionExtraBodyVarScopeInnermost()) {
731         DeclaredNamePtr p = pc_->functionScope().lookupDeclaredName(name);
732         if (p && DeclarationKindIsParameter(p->value()->kind())) {
733           reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos());
734           return false;
735         }
736       }
737 
738       [[fallthrough]];
739 
740     case DeclarationKind::Import:
741       // Module code is always strict, so 'let' is always a keyword and never a
742       // name.
743       MOZ_ASSERT(name != TaggedParserAtomIndex::WellKnown::let());
744       [[fallthrough]];
745 
746     case DeclarationKind::SimpleCatchParameter:
747     case DeclarationKind::CatchParameter: {
748       ParseContext::Scope* scope = pc_->innermostScope();
749 
750       // It is an early error if there is another declaration with the same
751       // name in the same scope.
752       AddDeclaredNamePtr p = scope->lookupDeclaredNameForAdd(name);
753       if (p) {
754         reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos());
755         return false;
756       }
757 
758       if (!scope->addDeclaredName(pc_, p, name, kind, pos.begin,
759                                   isClosedOver)) {
760         return false;
761       }
762 
763       break;
764     }
765 
766     case DeclarationKind::CoverArrowParameter:
767       // CoverArrowParameter is only used as a placeholder declaration kind.
768       break;
769 
770     case DeclarationKind::PositionalFormalParameter:
771       MOZ_CRASH(
772           "Positional formal parameter names should use "
773           "notePositionalFormalParameter");
774       break;
775 
776     case DeclarationKind::VarForAnnexBLexicalFunction:
777       MOZ_CRASH(
778           "Synthesized Annex B vars should go through "
779           "tryDeclareVarForAnnexBLexicalFunction");
780       break;
781   }
782 
783   return true;
784 }
785 
786 template <class ParseHandler, typename Unit>
noteDeclaredPrivateName(Node nameNode,TaggedParserAtomIndex name,PropertyType propType,FieldPlacement placement,TokenPos pos)787 bool GeneralParser<ParseHandler, Unit>::noteDeclaredPrivateName(
788     Node nameNode, TaggedParserAtomIndex name, PropertyType propType,
789     FieldPlacement placement, TokenPos pos) {
790   ParseContext::Scope* scope = pc_->innermostScope();
791   AddDeclaredNamePtr p = scope->lookupDeclaredNameForAdd(name);
792 
793   DeclarationKind declKind = DeclarationKind::PrivateName;
794   ClosedOver closedOver = ClosedOver::No;
795   PrivateNameKind kind;
796   switch (propType) {
797     case PropertyType::Field:
798       kind = PrivateNameKind::Field;
799       break;
800     case PropertyType::Method:
801     case PropertyType::GeneratorMethod:
802     case PropertyType::AsyncMethod:
803     case PropertyType::AsyncGeneratorMethod:
804       if (placement == FieldPlacement::Instance) {
805         // Optimized private method. Non-optimized paths still get
806         // DeclarationKind::Synthetic.
807         declKind = DeclarationKind::PrivateMethod;
808       }
809 
810       // Methods must be marked closed-over so that
811       // EmitterScope::lookupPrivate() works even if the method is used, but not
812       // within any method (from a computed property name, or debugger frame)
813       closedOver = ClosedOver::Yes;
814       kind = PrivateNameKind::Method;
815       break;
816     case PropertyType::Getter:
817       kind = PrivateNameKind::Getter;
818       break;
819     case PropertyType::Setter:
820       kind = PrivateNameKind::Setter;
821       break;
822     default:
823       kind = PrivateNameKind::None;
824   }
825 
826   if (p) {
827     PrivateNameKind prevKind = p->value()->privateNameKind();
828     if ((prevKind == PrivateNameKind::Getter &&
829          kind == PrivateNameKind::Setter) ||
830         (prevKind == PrivateNameKind::Setter &&
831          kind == PrivateNameKind::Getter)) {
832       // Private methods demands that
833       //
834       // class A {
835       //   static set #x(_) {}
836       //   get #x() { }
837       // }
838       //
839       // Report a SyntaxError.
840       if (placement == p->value()->placement()) {
841         p->value()->setPrivateNameKind(PrivateNameKind::GetterSetter);
842         handler_.setPrivateNameKind(nameNode, PrivateNameKind::GetterSetter);
843         return true;
844       }
845     }
846 
847     reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos());
848     return false;
849   }
850 
851   if (!scope->addDeclaredName(pc_, p, name, declKind, pos.begin, closedOver)) {
852     return false;
853   }
854 
855   DeclaredNamePtr declared = scope->lookupDeclaredName(name);
856   declared->value()->setPrivateNameKind(kind);
857   declared->value()->setFieldPlacement(placement);
858   handler_.setPrivateNameKind(nameNode, kind);
859 
860   return true;
861 }
862 
noteUsedNameInternal(TaggedParserAtomIndex name,NameVisibility visibility,mozilla::Maybe<TokenPos> tokenPosition)863 bool ParserBase::noteUsedNameInternal(TaggedParserAtomIndex name,
864                                       NameVisibility visibility,
865                                       mozilla::Maybe<TokenPos> tokenPosition) {
866   // The asm.js validator does all its own symbol-table management so, as an
867   // optimization, avoid doing any work here.
868   if (pc_->useAsmOrInsideUseAsm()) {
869     return true;
870   }
871 
872   // Global bindings are properties and not actual bindings; we don't need
873   // to know if they are closed over. So no need to track used name at the
874   // global scope. It is not incorrect to track them, this is an
875   // optimization.
876   //
877   // As an exception however, we continue to track private name references,
878   // as the used names tracker is used to provide early errors for undeclared
879   // private name references
880   ParseContext::Scope* scope = pc_->innermostScope();
881   if (pc_->sc()->isGlobalContext() && scope == &pc_->varScope() &&
882       visibility == NameVisibility::Public) {
883     return true;
884   }
885 
886   return usedNames_.noteUse(cx_, name, visibility, pc_->scriptId(), scope->id(),
887                             tokenPosition);
888 }
889 
890 template <class ParseHandler>
891 bool PerHandlerParser<ParseHandler>::
propagateFreeNamesAndMarkClosedOverBindings(ParseContext::Scope & scope)892     propagateFreeNamesAndMarkClosedOverBindings(ParseContext::Scope& scope) {
893   // Now that we have all the declared names in the scope, check which
894   // functions should exhibit Annex B semantics.
895   if (!scope.propagateAndMarkAnnexBFunctionBoxes(pc_, this)) {
896     return false;
897   }
898 
899   if (handler_.reuseClosedOverBindings()) {
900     MOZ_ASSERT(pc_->isOutermostOfCurrentCompile());
901 
902     // Closed over bindings for all scopes are stored in a contiguous array, in
903     // the same order as the order in which scopes are visited, and seprated by
904     // TaggedParserAtomIndex::null().
905     uint32_t slotCount = scope.declaredCount();
906     while (auto parserAtom = handler_.nextLazyClosedOverBinding()) {
907       scope.lookupDeclaredName(parserAtom)->value()->setClosedOver();
908       MOZ_ASSERT(slotCount > 0);
909       slotCount--;
910     }
911 
912     if (pc_->isGeneratorOrAsync()) {
913       scope.setOwnStackSlotCount(slotCount);
914     }
915     return true;
916   }
917 
918   constexpr bool isSyntaxParser =
919       std::is_same_v<ParseHandler, SyntaxParseHandler>;
920   uint32_t scriptId = pc_->scriptId();
921   uint32_t scopeId = scope.id();
922 
923   uint32_t slotCount = 0;
924   for (BindingIter bi = scope.bindings(pc_); bi; bi++) {
925     bool closedOver = false;
926     if (UsedNamePtr p = usedNames_.lookup(bi.name())) {
927       p->value().noteBoundInScope(scriptId, scopeId, &closedOver);
928       if (closedOver) {
929         bi.setClosedOver();
930 
931         if constexpr (isSyntaxParser) {
932           if (!pc_->closedOverBindingsForLazy().append(
933                   TrivialTaggedParserAtomIndex::from(bi.name()))) {
934             ReportOutOfMemory(cx_);
935             return false;
936           }
937         }
938       }
939     }
940 
941     if constexpr (!isSyntaxParser) {
942       if (!closedOver) {
943         slotCount++;
944       }
945     }
946   }
947   if constexpr (!isSyntaxParser) {
948     if (pc_->isGeneratorOrAsync()) {
949       scope.setOwnStackSlotCount(slotCount);
950     }
951   }
952 
953   // Append a nullptr to denote end-of-scope.
954   if constexpr (isSyntaxParser) {
955     if (!pc_->closedOverBindingsForLazy().append(
956             TrivialTaggedParserAtomIndex::null())) {
957       ReportOutOfMemory(cx_);
958       return false;
959     }
960   }
961 
962   return true;
963 }
964 
965 template <typename Unit>
checkStatementsEOF()966 bool Parser<FullParseHandler, Unit>::checkStatementsEOF() {
967   // This is designed to be paired with parsing a statement list at the top
968   // level.
969   //
970   // The statementList() call breaks on TokenKind::RightCurly, so make sure
971   // we've reached EOF here.
972   TokenKind tt;
973   if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) {
974     return false;
975   }
976   if (tt != TokenKind::Eof) {
977     error(JSMSG_UNEXPECTED_TOKEN, "expression", TokenKindToDesc(tt));
978     return false;
979   }
980   return true;
981 }
982 
983 template <typename ScopeT>
NewEmptyBindingData(JSContext * cx,LifoAlloc & alloc,uint32_t numBindings)984 typename ScopeT::ParserData* NewEmptyBindingData(JSContext* cx,
985                                                  LifoAlloc& alloc,
986                                                  uint32_t numBindings) {
987   using Data = typename ScopeT::ParserData;
988   size_t allocSize = SizeOfScopeData<Data>(numBindings);
989   auto* bindings = alloc.newWithSize<Data>(allocSize, numBindings);
990   if (!bindings) {
991     ReportOutOfMemory(cx);
992   }
993   return bindings;
994 }
995 
NewEmptyGlobalScopeData(JSContext * cx,LifoAlloc & alloc,uint32_t numBindings)996 GlobalScope::ParserData* NewEmptyGlobalScopeData(JSContext* cx,
997                                                  LifoAlloc& alloc,
998                                                  uint32_t numBindings) {
999   return NewEmptyBindingData<GlobalScope>(cx, alloc, numBindings);
1000 }
1001 
NewEmptyLexicalScopeData(JSContext * cx,LifoAlloc & alloc,uint32_t numBindings)1002 LexicalScope::ParserData* NewEmptyLexicalScopeData(JSContext* cx,
1003                                                    LifoAlloc& alloc,
1004                                                    uint32_t numBindings) {
1005   return NewEmptyBindingData<LexicalScope>(cx, alloc, numBindings);
1006 }
1007 
NewEmptyFunctionScopeData(JSContext * cx,LifoAlloc & alloc,uint32_t numBindings)1008 FunctionScope::ParserData* NewEmptyFunctionScopeData(JSContext* cx,
1009                                                      LifoAlloc& alloc,
1010                                                      uint32_t numBindings) {
1011   return NewEmptyBindingData<FunctionScope>(cx, alloc, numBindings);
1012 }
1013 
1014 namespace detail {
1015 
1016 template <class SlotInfo>
InitializeIndexedBindings(SlotInfo & slotInfo,ParserBindingName * start,ParserBindingName * cursor)1017 static MOZ_ALWAYS_INLINE ParserBindingName* InitializeIndexedBindings(
1018     SlotInfo& slotInfo, ParserBindingName* start, ParserBindingName* cursor) {
1019   return cursor;
1020 }
1021 
1022 template <class SlotInfo, typename UnsignedInteger, typename... Step>
InitializeIndexedBindings(SlotInfo & slotInfo,ParserBindingName * start,ParserBindingName * cursor,UnsignedInteger SlotInfo::* field,const ParserBindingNameVector & bindings,Step &&...step)1023 static MOZ_ALWAYS_INLINE ParserBindingName* InitializeIndexedBindings(
1024     SlotInfo& slotInfo, ParserBindingName* start, ParserBindingName* cursor,
1025     UnsignedInteger SlotInfo::*field, const ParserBindingNameVector& bindings,
1026     Step&&... step) {
1027   slotInfo.*field =
1028       AssertedCast<UnsignedInteger>(PointerRangeSize(start, cursor));
1029 
1030   ParserBindingName* newCursor =
1031       std::uninitialized_copy(bindings.begin(), bindings.end(), cursor);
1032 
1033   return InitializeIndexedBindings(slotInfo, start, newCursor,
1034                                    std::forward<Step>(step)...);
1035 }
1036 
1037 }  // namespace detail
1038 
1039 // Initialize the trailing name bindings of |data|, then set |data->length| to
1040 // the count of bindings added (which must equal |count|).
1041 //
1042 // First, |firstBindings| are added to the trailing names.  Then any
1043 // "steps" present are performed first to last.  Each step is 1) a pointer to a
1044 // member of |data| to be set to the current number of bindings added, and 2) a
1045 // vector of |ParserBindingName|s to then copy into |data->trailingNames|.
1046 // (Thus each |data| member field indicates where the corresponding vector's
1047 //  names start.)
1048 template <class Data, typename... Step>
InitializeBindingData(Data * data,uint32_t count,const ParserBindingNameVector & firstBindings,Step &&...step)1049 static MOZ_ALWAYS_INLINE void InitializeBindingData(
1050     Data* data, uint32_t count, const ParserBindingNameVector& firstBindings,
1051     Step&&... step) {
1052   MOZ_ASSERT(data->length == 0, "data shouldn't be filled yet");
1053 
1054   ParserBindingName* start = GetScopeDataTrailingNamesPointer(data);
1055   ParserBindingName* cursor = std::uninitialized_copy(
1056       firstBindings.begin(), firstBindings.end(), start);
1057 
1058 #ifdef DEBUG
1059   ParserBindingName* end =
1060 #endif
1061       detail::InitializeIndexedBindings(data->slotInfo, start, cursor,
1062                                         std::forward<Step>(step)...);
1063 
1064   MOZ_ASSERT(PointerRangeSize(start, end) == count);
1065   data->length = count;
1066 }
1067 
NewGlobalScopeData(JSContext * cx,ParseContext::Scope & scope,LifoAlloc & alloc,ParseContext * pc)1068 Maybe<GlobalScope::ParserData*> NewGlobalScopeData(JSContext* cx,
1069                                                    ParseContext::Scope& scope,
1070                                                    LifoAlloc& alloc,
1071                                                    ParseContext* pc) {
1072   ParserBindingNameVector vars(cx);
1073   ParserBindingNameVector lets(cx);
1074   ParserBindingNameVector consts(cx);
1075 
1076   bool allBindingsClosedOver = pc->sc()->allBindingsClosedOver();
1077   for (BindingIter bi = scope.bindings(pc); bi; bi++) {
1078     bool closedOver = allBindingsClosedOver || bi.closedOver();
1079 
1080     switch (bi.kind()) {
1081       case BindingKind::Var: {
1082         bool isTopLevelFunction =
1083             bi.declarationKind() == DeclarationKind::BodyLevelFunction;
1084 
1085         ParserBindingName binding(bi.name(), closedOver, isTopLevelFunction);
1086         if (!vars.append(binding)) {
1087           return Nothing();
1088         }
1089         break;
1090       }
1091       case BindingKind::Let: {
1092         ParserBindingName binding(bi.name(), closedOver);
1093         if (!lets.append(binding)) {
1094           return Nothing();
1095         }
1096         break;
1097       }
1098       case BindingKind::Const: {
1099         ParserBindingName binding(bi.name(), closedOver);
1100         if (!consts.append(binding)) {
1101           return Nothing();
1102         }
1103         break;
1104       }
1105       default:
1106         MOZ_CRASH("Bad global scope BindingKind");
1107     }
1108   }
1109 
1110   GlobalScope::ParserData* bindings = nullptr;
1111   uint32_t numBindings = vars.length() + lets.length() + consts.length();
1112 
1113   if (numBindings > 0) {
1114     bindings = NewEmptyBindingData<GlobalScope>(cx, alloc, numBindings);
1115     if (!bindings) {
1116       return Nothing();
1117     }
1118 
1119     // The ordering here is important. See comments in GlobalScope.
1120     InitializeBindingData(bindings, numBindings, vars,
1121                           &ParserGlobalScopeSlotInfo::letStart, lets,
1122                           &ParserGlobalScopeSlotInfo::constStart, consts);
1123   }
1124 
1125   return Some(bindings);
1126 }
1127 
newGlobalScopeData(ParseContext::Scope & scope)1128 Maybe<GlobalScope::ParserData*> ParserBase::newGlobalScopeData(
1129     ParseContext::Scope& scope) {
1130   return NewGlobalScopeData(cx_, scope, stencilAlloc(), pc_);
1131 }
1132 
NewModuleScopeData(JSContext * cx,ParseContext::Scope & scope,LifoAlloc & alloc,ParseContext * pc)1133 Maybe<ModuleScope::ParserData*> NewModuleScopeData(JSContext* cx,
1134                                                    ParseContext::Scope& scope,
1135                                                    LifoAlloc& alloc,
1136                                                    ParseContext* pc) {
1137   ParserBindingNameVector imports(cx);
1138   ParserBindingNameVector vars(cx);
1139   ParserBindingNameVector lets(cx);
1140   ParserBindingNameVector consts(cx);
1141 
1142   bool allBindingsClosedOver =
1143       pc->sc()->allBindingsClosedOver() || scope.tooBigToOptimize();
1144 
1145   for (BindingIter bi = scope.bindings(pc); bi; bi++) {
1146     // Imports are indirect bindings and must not be given known slots.
1147     ParserBindingName binding(bi.name(),
1148                               (allBindingsClosedOver || bi.closedOver()) &&
1149                                   bi.kind() != BindingKind::Import);
1150     switch (bi.kind()) {
1151       case BindingKind::Import:
1152         if (!imports.append(binding)) {
1153           return Nothing();
1154         }
1155         break;
1156       case BindingKind::Var:
1157         if (!vars.append(binding)) {
1158           return Nothing();
1159         }
1160         break;
1161       case BindingKind::Let:
1162         if (!lets.append(binding)) {
1163           return Nothing();
1164         }
1165         break;
1166       case BindingKind::Const:
1167         if (!consts.append(binding)) {
1168           return Nothing();
1169         }
1170         break;
1171       default:
1172         MOZ_CRASH("Bad module scope BindingKind");
1173     }
1174   }
1175 
1176   ModuleScope::ParserData* bindings = nullptr;
1177   uint32_t numBindings =
1178       imports.length() + vars.length() + lets.length() + consts.length();
1179 
1180   if (numBindings > 0) {
1181     bindings = NewEmptyBindingData<ModuleScope>(cx, alloc, numBindings);
1182     if (!bindings) {
1183       return Nothing();
1184     }
1185 
1186     // The ordering here is important. See comments in ModuleScope.
1187     InitializeBindingData(bindings, numBindings, imports,
1188                           &ParserModuleScopeSlotInfo::varStart, vars,
1189                           &ParserModuleScopeSlotInfo::letStart, lets,
1190                           &ParserModuleScopeSlotInfo::constStart, consts);
1191   }
1192 
1193   return Some(bindings);
1194 }
1195 
newModuleScopeData(ParseContext::Scope & scope)1196 Maybe<ModuleScope::ParserData*> ParserBase::newModuleScopeData(
1197     ParseContext::Scope& scope) {
1198   return NewModuleScopeData(cx_, scope, stencilAlloc(), pc_);
1199 }
1200 
NewEvalScopeData(JSContext * cx,ParseContext::Scope & scope,LifoAlloc & alloc,ParseContext * pc)1201 Maybe<EvalScope::ParserData*> NewEvalScopeData(JSContext* cx,
1202                                                ParseContext::Scope& scope,
1203                                                LifoAlloc& alloc,
1204                                                ParseContext* pc) {
1205   ParserBindingNameVector vars(cx);
1206 
1207   // Treat all bindings as closed over in non-strict eval.
1208   bool allBindingsClosedOver =
1209       !pc->sc()->strict() || pc->sc()->allBindingsClosedOver();
1210   for (BindingIter bi = scope.bindings(pc); bi; bi++) {
1211     // Eval scopes only contain 'var' bindings.
1212     MOZ_ASSERT(bi.kind() == BindingKind::Var);
1213     bool isTopLevelFunction =
1214         bi.declarationKind() == DeclarationKind::BodyLevelFunction;
1215     bool closedOver = allBindingsClosedOver || bi.closedOver();
1216 
1217     ParserBindingName binding(bi.name(), closedOver, isTopLevelFunction);
1218     if (!vars.append(binding)) {
1219       return Nothing();
1220     }
1221   }
1222 
1223   EvalScope::ParserData* bindings = nullptr;
1224   uint32_t numBindings = vars.length();
1225 
1226   if (numBindings > 0) {
1227     bindings = NewEmptyBindingData<EvalScope>(cx, alloc, numBindings);
1228     if (!bindings) {
1229       return Nothing();
1230     }
1231 
1232     InitializeBindingData(bindings, numBindings, vars);
1233   }
1234 
1235   return Some(bindings);
1236 }
1237 
newEvalScopeData(ParseContext::Scope & scope)1238 Maybe<EvalScope::ParserData*> ParserBase::newEvalScopeData(
1239     ParseContext::Scope& scope) {
1240   return NewEvalScopeData(cx_, scope, stencilAlloc(), pc_);
1241 }
1242 
NewFunctionScopeData(JSContext * cx,ParseContext::Scope & scope,bool hasParameterExprs,LifoAlloc & alloc,ParseContext * pc)1243 Maybe<FunctionScope::ParserData*> NewFunctionScopeData(
1244     JSContext* cx, ParseContext::Scope& scope, bool hasParameterExprs,
1245     LifoAlloc& alloc, ParseContext* pc) {
1246   ParserBindingNameVector positionalFormals(cx);
1247   ParserBindingNameVector formals(cx);
1248   ParserBindingNameVector vars(cx);
1249 
1250   bool allBindingsClosedOver =
1251       pc->sc()->allBindingsClosedOver() || scope.tooBigToOptimize();
1252   bool argumentBindingsClosedOver =
1253       allBindingsClosedOver || pc->isGeneratorOrAsync();
1254   bool hasDuplicateParams = pc->functionBox()->hasDuplicateParameters;
1255 
1256   // Positional parameter names must be added in order of appearance as they are
1257   // referenced using argument slots.
1258   for (size_t i = 0; i < pc->positionalFormalParameterNames().length(); i++) {
1259     TaggedParserAtomIndex name = pc->positionalFormalParameterNames()[i];
1260 
1261     ParserBindingName bindName;
1262     if (name) {
1263       DeclaredNamePtr p = scope.lookupDeclaredName(name);
1264 
1265       // Do not consider any positional formal parameters closed over if
1266       // there are parameter defaults. It is the binding in the defaults
1267       // scope that is closed over instead.
1268       bool closedOver =
1269           argumentBindingsClosedOver || (p && p->value()->closedOver());
1270 
1271       // If the parameter name has duplicates, only the final parameter
1272       // name should be on the environment, as otherwise the environment
1273       // object would have multiple, same-named properties.
1274       if (hasDuplicateParams) {
1275         for (size_t j = pc->positionalFormalParameterNames().length() - 1;
1276              j > i; j--) {
1277           if (TaggedParserAtomIndex(pc->positionalFormalParameterNames()[j]) ==
1278               name) {
1279             closedOver = false;
1280             break;
1281           }
1282         }
1283       }
1284 
1285       bindName = ParserBindingName(name, closedOver);
1286     }
1287 
1288     if (!positionalFormals.append(bindName)) {
1289       return Nothing();
1290     }
1291   }
1292 
1293   for (BindingIter bi = scope.bindings(pc); bi; bi++) {
1294     ParserBindingName binding(bi.name(),
1295                               allBindingsClosedOver || bi.closedOver());
1296     switch (bi.kind()) {
1297       case BindingKind::FormalParameter:
1298         // Positional parameter names are already handled above.
1299         if (bi.declarationKind() == DeclarationKind::FormalParameter) {
1300           if (!formals.append(binding)) {
1301             return Nothing();
1302           }
1303         }
1304         break;
1305       case BindingKind::Var:
1306         // The only vars in the function scope when there are parameter
1307         // exprs, which induces a separate var environment, should be the
1308         // special bindings.
1309         MOZ_ASSERT_IF(hasParameterExprs,
1310                       FunctionScope::isSpecialName(cx, bi.name()));
1311         if (!vars.append(binding)) {
1312           return Nothing();
1313         }
1314         break;
1315       case BindingKind::Let:
1316       case BindingKind::Const:
1317         break;
1318       default:
1319         MOZ_CRASH("bad function scope BindingKind");
1320         break;
1321     }
1322   }
1323 
1324   FunctionScope::ParserData* bindings = nullptr;
1325   uint32_t numBindings =
1326       positionalFormals.length() + formals.length() + vars.length();
1327 
1328   if (numBindings > 0) {
1329     bindings = NewEmptyBindingData<FunctionScope>(cx, alloc, numBindings);
1330     if (!bindings) {
1331       return Nothing();
1332     }
1333 
1334     // The ordering here is important. See comments in FunctionScope.
1335     InitializeBindingData(
1336         bindings, numBindings, positionalFormals,
1337         &ParserFunctionScopeSlotInfo::nonPositionalFormalStart, formals,
1338         &ParserFunctionScopeSlotInfo::varStart, vars);
1339   }
1340 
1341   return Some(bindings);
1342 }
1343 
1344 // Compute if `NewFunctionScopeData` would return any binding list with any
1345 // entry marked as closed-over. This is done without the need to allocate the
1346 // binding list. If true, an EnvironmentObject will be needed at runtime.
FunctionScopeHasClosedOverBindings(ParseContext * pc)1347 bool FunctionScopeHasClosedOverBindings(ParseContext* pc) {
1348   bool allBindingsClosedOver = pc->sc()->allBindingsClosedOver() ||
1349                                pc->functionScope().tooBigToOptimize();
1350 
1351   for (BindingIter bi = pc->functionScope().bindings(pc); bi; bi++) {
1352     switch (bi.kind()) {
1353       case BindingKind::FormalParameter:
1354       case BindingKind::Var:
1355         if (allBindingsClosedOver || bi.closedOver()) {
1356           return true;
1357         }
1358         break;
1359 
1360       default:
1361         break;
1362     }
1363   }
1364 
1365   return false;
1366 }
1367 
newFunctionScopeData(ParseContext::Scope & scope,bool hasParameterExprs)1368 Maybe<FunctionScope::ParserData*> ParserBase::newFunctionScopeData(
1369     ParseContext::Scope& scope, bool hasParameterExprs) {
1370   return NewFunctionScopeData(cx_, scope, hasParameterExprs, stencilAlloc(),
1371                               pc_);
1372 }
1373 
NewEmptyVarScopeData(JSContext * cx,LifoAlloc & alloc,uint32_t numBindings)1374 VarScope::ParserData* NewEmptyVarScopeData(JSContext* cx, LifoAlloc& alloc,
1375                                            uint32_t numBindings) {
1376   return NewEmptyBindingData<VarScope>(cx, alloc, numBindings);
1377 }
1378 
NewVarScopeData(JSContext * cx,ParseContext::Scope & scope,LifoAlloc & alloc,ParseContext * pc)1379 Maybe<VarScope::ParserData*> NewVarScopeData(JSContext* cx,
1380                                              ParseContext::Scope& scope,
1381                                              LifoAlloc& alloc,
1382                                              ParseContext* pc) {
1383   ParserBindingNameVector vars(cx);
1384 
1385   bool allBindingsClosedOver =
1386       pc->sc()->allBindingsClosedOver() || scope.tooBigToOptimize();
1387 
1388   for (BindingIter bi = scope.bindings(pc); bi; bi++) {
1389     if (bi.kind() == BindingKind::Var) {
1390       ParserBindingName binding(bi.name(),
1391                                 allBindingsClosedOver || bi.closedOver());
1392       if (!vars.append(binding)) {
1393         return Nothing();
1394       }
1395     } else {
1396       MOZ_ASSERT(
1397           bi.kind() == BindingKind::Let || bi.kind() == BindingKind::Const,
1398           "bad var scope BindingKind");
1399     }
1400   }
1401 
1402   VarScope::ParserData* bindings = nullptr;
1403   uint32_t numBindings = vars.length();
1404 
1405   if (numBindings > 0) {
1406     bindings = NewEmptyBindingData<VarScope>(cx, alloc, numBindings);
1407     if (!bindings) {
1408       return Nothing();
1409     }
1410 
1411     InitializeBindingData(bindings, numBindings, vars);
1412   }
1413 
1414   return Some(bindings);
1415 }
1416 
1417 // Compute if `NewVarScopeData` would return any binding list. This is done
1418 // without allocate the binding list.
VarScopeHasBindings(ParseContext * pc)1419 static bool VarScopeHasBindings(ParseContext* pc) {
1420   for (BindingIter bi = pc->varScope().bindings(pc); bi; bi++) {
1421     if (bi.kind() == BindingKind::Var) {
1422       return true;
1423     }
1424   }
1425 
1426   return false;
1427 }
1428 
newVarScopeData(ParseContext::Scope & scope)1429 Maybe<VarScope::ParserData*> ParserBase::newVarScopeData(
1430     ParseContext::Scope& scope) {
1431   return NewVarScopeData(cx_, scope, stencilAlloc(), pc_);
1432 }
1433 
NewLexicalScopeData(JSContext * cx,ParseContext::Scope & scope,LifoAlloc & alloc,ParseContext * pc)1434 Maybe<LexicalScope::ParserData*> NewLexicalScopeData(JSContext* cx,
1435                                                      ParseContext::Scope& scope,
1436                                                      LifoAlloc& alloc,
1437                                                      ParseContext* pc) {
1438   ParserBindingNameVector lets(cx);
1439   ParserBindingNameVector consts(cx);
1440 
1441   bool allBindingsClosedOver =
1442       pc->sc()->allBindingsClosedOver() || scope.tooBigToOptimize();
1443 
1444   for (BindingIter bi = scope.bindings(pc); bi; bi++) {
1445     ParserBindingName binding(bi.name(),
1446                               allBindingsClosedOver || bi.closedOver());
1447     switch (bi.kind()) {
1448       case BindingKind::Let:
1449         if (!lets.append(binding)) {
1450           return Nothing();
1451         }
1452         break;
1453       case BindingKind::Const:
1454         if (!consts.append(binding)) {
1455           return Nothing();
1456         }
1457         break;
1458       case BindingKind::Var:
1459       case BindingKind::FormalParameter:
1460         break;
1461       default:
1462         MOZ_CRASH("Bad lexical scope BindingKind");
1463         break;
1464     }
1465   }
1466 
1467   LexicalScope::ParserData* bindings = nullptr;
1468   uint32_t numBindings = lets.length() + consts.length();
1469 
1470   if (numBindings > 0) {
1471     bindings = NewEmptyBindingData<LexicalScope>(cx, alloc, numBindings);
1472     if (!bindings) {
1473       return Nothing();
1474     }
1475 
1476     // The ordering here is important. See comments in LexicalScope.
1477     InitializeBindingData(bindings, numBindings, lets,
1478                           &ParserLexicalScopeSlotInfo::constStart, consts);
1479   }
1480 
1481   return Some(bindings);
1482 }
1483 
1484 // Compute if `NewLexicalScopeData` would return any binding list with any entry
1485 // marked as closed-over. This is done without the need to allocate the binding
1486 // list. If true, an EnvironmentObject will be needed at runtime.
LexicalScopeHasClosedOverBindings(ParseContext * pc,ParseContext::Scope & scope)1487 bool LexicalScopeHasClosedOverBindings(ParseContext* pc,
1488                                        ParseContext::Scope& scope) {
1489   bool allBindingsClosedOver =
1490       pc->sc()->allBindingsClosedOver() || scope.tooBigToOptimize();
1491 
1492   for (BindingIter bi = scope.bindings(pc); bi; bi++) {
1493     switch (bi.kind()) {
1494       case BindingKind::Let:
1495       case BindingKind::Const:
1496         if (allBindingsClosedOver || bi.closedOver()) {
1497           return true;
1498         }
1499         break;
1500 
1501       default:
1502         break;
1503     }
1504   }
1505 
1506   return false;
1507 }
1508 
newLexicalScopeData(ParseContext::Scope & scope)1509 Maybe<LexicalScope::ParserData*> ParserBase::newLexicalScopeData(
1510     ParseContext::Scope& scope) {
1511   return NewLexicalScopeData(cx_, scope, stencilAlloc(), pc_);
1512 }
1513 
NewClassBodyScopeData(JSContext * cx,ParseContext::Scope & scope,LifoAlloc & alloc,ParseContext * pc)1514 Maybe<ClassBodyScope::ParserData*> NewClassBodyScopeData(
1515     JSContext* cx, ParseContext::Scope& scope, LifoAlloc& alloc,
1516     ParseContext* pc) {
1517   ParserBindingNameVector privateBrand(cx);
1518   ParserBindingNameVector synthetics(cx);
1519   ParserBindingNameVector privateMethods(cx);
1520 
1521   bool allBindingsClosedOver =
1522       pc->sc()->allBindingsClosedOver() || scope.tooBigToOptimize();
1523 
1524   for (BindingIter bi = scope.bindings(pc); bi; bi++) {
1525     ParserBindingName binding(bi.name(),
1526                               allBindingsClosedOver || bi.closedOver());
1527     switch (bi.kind()) {
1528       case BindingKind::Synthetic:
1529         if (bi.name() == TaggedParserAtomIndex::WellKnown::dotPrivateBrand()) {
1530           MOZ_ASSERT(privateBrand.empty());
1531           if (!privateBrand.append(binding)) {
1532             return Nothing();
1533           }
1534         } else {
1535           if (!synthetics.append(binding)) {
1536             return Nothing();
1537           }
1538         }
1539         break;
1540 
1541       case BindingKind::PrivateMethod:
1542         if (!privateMethods.append(binding)) {
1543           return Nothing();
1544         }
1545         break;
1546 
1547       default:
1548         MOZ_CRASH("bad class body scope BindingKind");
1549         break;
1550     }
1551   }
1552 
1553   // We should have zero or one private brands.
1554   MOZ_ASSERT(privateBrand.length() == 0 || privateBrand.length() == 1);
1555 
1556   ClassBodyScope::ParserData* bindings = nullptr;
1557   uint32_t numBindings =
1558       privateBrand.length() + synthetics.length() + privateMethods.length();
1559 
1560   if (numBindings > 0) {
1561     bindings = NewEmptyBindingData<ClassBodyScope>(cx, alloc, numBindings);
1562     if (!bindings) {
1563       return Nothing();
1564     }
1565     // To simplify initialization of the bindings, we concatenate the
1566     // synthetics+privateBrand vector such that the private brand is always the
1567     // first element, as ordering is important. See comments in ClassBodyScope.
1568     ParserBindingNameVector brandAndSynthetics(cx);
1569     if (!brandAndSynthetics.appendAll(privateBrand)) {
1570       return Nothing();
1571     }
1572     if (!brandAndSynthetics.appendAll(synthetics)) {
1573       return Nothing();
1574     }
1575 
1576     // The ordering here is important. See comments in ClassBodyScope.
1577     InitializeBindingData(bindings, numBindings, brandAndSynthetics,
1578                           &ParserClassBodyScopeSlotInfo::privateMethodStart,
1579                           privateMethods);
1580   }
1581 
1582   // `EmitterScope::lookupPrivate()` requires `.privateBrand` to be stored in a
1583   // predictable slot: the first slot available in the environment object,
1584   // `ClassBodyLexicalEnvironmentObject::privateBrandSlot()`. We assume that
1585   // if `.privateBrand` is first in the scope, it will be stored there.
1586   MOZ_ASSERT_IF(!privateBrand.empty(),
1587                 GetScopeDataTrailingNames(bindings)[0].name() ==
1588                     TaggedParserAtomIndex::WellKnown::dotPrivateBrand());
1589 
1590   return Some(bindings);
1591 }
1592 
newClassBodyScopeData(ParseContext::Scope & scope)1593 Maybe<ClassBodyScope::ParserData*> ParserBase::newClassBodyScopeData(
1594     ParseContext::Scope& scope) {
1595   return NewClassBodyScopeData(cx_, scope, stencilAlloc(), pc_);
1596 }
1597 
1598 template <>
1599 SyntaxParseHandler::LexicalScopeNodeType
finishLexicalScope(ParseContext::Scope & scope,Node body,ScopeKind kind)1600 PerHandlerParser<SyntaxParseHandler>::finishLexicalScope(
1601     ParseContext::Scope& scope, Node body, ScopeKind kind) {
1602   if (!propagateFreeNamesAndMarkClosedOverBindings(scope)) {
1603     return null();
1604   }
1605 
1606   return handler_.newLexicalScope(body);
1607 }
1608 
1609 template <>
finishLexicalScope(ParseContext::Scope & scope,ParseNode * body,ScopeKind kind)1610 LexicalScopeNode* PerHandlerParser<FullParseHandler>::finishLexicalScope(
1611     ParseContext::Scope& scope, ParseNode* body, ScopeKind kind) {
1612   if (!propagateFreeNamesAndMarkClosedOverBindings(scope)) {
1613     return nullptr;
1614   }
1615 
1616   Maybe<LexicalScope::ParserData*> bindings = newLexicalScopeData(scope);
1617   if (!bindings) {
1618     return nullptr;
1619   }
1620 
1621   return handler_.newLexicalScope(*bindings, body, kind);
1622 }
1623 
1624 template <>
1625 SyntaxParseHandler::ClassBodyScopeNodeType
finishClassBodyScope(ParseContext::Scope & scope,ListNodeType body)1626 PerHandlerParser<SyntaxParseHandler>::finishClassBodyScope(
1627     ParseContext::Scope& scope, ListNodeType body) {
1628   if (!propagateFreeNamesAndMarkClosedOverBindings(scope)) {
1629     return null();
1630   }
1631 
1632   return handler_.newClassBodyScope(body);
1633 }
1634 
1635 template <>
finishClassBodyScope(ParseContext::Scope & scope,ListNode * body)1636 ClassBodyScopeNode* PerHandlerParser<FullParseHandler>::finishClassBodyScope(
1637     ParseContext::Scope& scope, ListNode* body) {
1638   if (!propagateFreeNamesAndMarkClosedOverBindings(scope)) {
1639     return nullptr;
1640   }
1641 
1642   Maybe<ClassBodyScope::ParserData*> bindings = newClassBodyScopeData(scope);
1643   if (!bindings) {
1644     return nullptr;
1645   }
1646 
1647   return handler_.newClassBodyScope(*bindings, body);
1648 }
1649 
1650 template <class ParseHandler>
checkForUndefinedPrivateFields(EvalSharedContext * evalSc)1651 bool PerHandlerParser<ParseHandler>::checkForUndefinedPrivateFields(
1652     EvalSharedContext* evalSc) {
1653   if (!this->compilationState_.isInitialStencil()) {
1654     // We're delazifying -- so we already checked private names during first
1655     // parse.
1656     return true;
1657   }
1658 
1659   Vector<UnboundPrivateName, 8> unboundPrivateNames(cx_);
1660   if (!usedNames_.getUnboundPrivateNames(unboundPrivateNames)) {
1661     return false;
1662   }
1663 
1664   // No unbound names, let's get out of here!
1665   if (unboundPrivateNames.empty()) {
1666     return true;
1667   }
1668 
1669   // It is an early error if there's private name references unbound,
1670   // unless it's an eval, in which case we need to check the scope
1671   // chain.
1672   if (!evalSc) {
1673     // The unbound private names are sorted, so just grab the first one.
1674     UnboundPrivateName minimum = unboundPrivateNames[0];
1675     UniqueChars str = this->parserAtoms().toPrintableString(cx_, minimum.atom);
1676     if (!str) {
1677       return false;
1678     }
1679 
1680     errorAt(minimum.position.begin, JSMSG_MISSING_PRIVATE_DECL, str.get());
1681     return false;
1682   }
1683 
1684   // It's important that the unbound private names are sorted, as we
1685   // want our errors to always be issued to the first textually.
1686   for (UnboundPrivateName unboundName : unboundPrivateNames) {
1687     // If the enclosingScope is non-syntactic, then we are in a
1688     // Debugger.Frame.prototype.eval call. In order to find the declared private
1689     // names, we must use the effective scope that was determined when creating
1690     // the scopeContext.
1691     if (!this->compilationState_.scopeContext
1692              .effectiveScopePrivateFieldCacheHas(unboundName.atom)) {
1693       UniqueChars str =
1694           this->parserAtoms().toPrintableString(cx_, unboundName.atom);
1695       if (!str) {
1696         return false;
1697       }
1698       errorAt(unboundName.position.begin, JSMSG_MISSING_PRIVATE_DECL,
1699               str.get());
1700       return false;
1701     }
1702   }
1703 
1704   return true;
1705 }
1706 
1707 template <typename Unit>
evalBody(EvalSharedContext * evalsc)1708 LexicalScopeNode* Parser<FullParseHandler, Unit>::evalBody(
1709     EvalSharedContext* evalsc) {
1710   SourceParseContext evalpc(this, evalsc, /* newDirectives = */ nullptr);
1711   if (!evalpc.init()) {
1712     return nullptr;
1713   }
1714 
1715   ParseContext::VarScope varScope(this);
1716   if (!varScope.init(pc_)) {
1717     return nullptr;
1718   }
1719 
1720   LexicalScopeNode* body;
1721   {
1722     // All evals have an implicit non-extensible lexical scope.
1723     ParseContext::Scope lexicalScope(this);
1724     if (!lexicalScope.init(pc_)) {
1725       return nullptr;
1726     }
1727 
1728     ListNode* list = statementList(YieldIsName);
1729     if (!list) {
1730       return nullptr;
1731     }
1732 
1733     if (!checkStatementsEOF()) {
1734       return nullptr;
1735     }
1736 
1737     // Private names not lexically defined must trigger a syntax error.
1738     if (!checkForUndefinedPrivateFields(evalsc)) {
1739       return nullptr;
1740     }
1741 
1742     body = finishLexicalScope(lexicalScope, list);
1743     if (!body) {
1744       return nullptr;
1745     }
1746   }
1747 
1748 #ifdef DEBUG
1749   if (evalpc.superScopeNeedsHomeObject() &&
1750       !this->compilationState_.input.enclosingScope.isNull()) {
1751     // If superScopeNeedsHomeObject_ is set and we are an entry-point
1752     // ParseContext, then we must be emitting an eval script, and the
1753     // outer function must already be marked as needing a home object
1754     // since it contains an eval.
1755     MOZ_ASSERT(
1756         this->compilationState_.scopeContext.hasFunctionNeedsHomeObjectOnChain,
1757         "Eval must have found an enclosing function box scope that "
1758         "allows super.property");
1759   }
1760 #endif
1761 
1762   if (!CheckParseTree(cx_, alloc_, body)) {
1763     return null();
1764   }
1765 
1766   ParseNode* node = body;
1767   // Don't constant-fold inside "use asm" code, as this could create a parse
1768   // tree that doesn't type-check as asm.js.
1769   if (!pc_->useAsmOrInsideUseAsm()) {
1770     if (!FoldConstants(cx_, this->parserAtoms(), &node, &handler_)) {
1771       return null();
1772     }
1773   }
1774   body = handler_.asLexicalScope(node);
1775 
1776   if (!this->setSourceMapInfo()) {
1777     return nullptr;
1778   }
1779 
1780   if (pc_->sc()->strict()) {
1781     if (!propagateFreeNamesAndMarkClosedOverBindings(varScope)) {
1782       return nullptr;
1783     }
1784   } else {
1785     // For non-strict eval scripts, since all bindings are automatically
1786     // considered closed over, we don't need to call propagateFreeNames-
1787     // AndMarkClosedOverBindings. However, Annex B.3.3 functions still need to
1788     // be marked.
1789     if (!varScope.propagateAndMarkAnnexBFunctionBoxes(pc_, this)) {
1790       return nullptr;
1791     }
1792   }
1793 
1794   Maybe<EvalScope::ParserData*> bindings = newEvalScopeData(pc_->varScope());
1795   if (!bindings) {
1796     return nullptr;
1797   }
1798   evalsc->bindings = *bindings;
1799 
1800   return body;
1801 }
1802 
1803 template <typename Unit>
globalBody(GlobalSharedContext * globalsc)1804 ListNode* Parser<FullParseHandler, Unit>::globalBody(
1805     GlobalSharedContext* globalsc) {
1806   SourceParseContext globalpc(this, globalsc, /* newDirectives = */ nullptr);
1807   if (!globalpc.init()) {
1808     return nullptr;
1809   }
1810 
1811   ParseContext::VarScope varScope(this);
1812   if (!varScope.init(pc_)) {
1813     return nullptr;
1814   }
1815 
1816   ListNode* body = statementList(YieldIsName);
1817   if (!body) {
1818     return nullptr;
1819   }
1820 
1821   if (!checkStatementsEOF()) {
1822     return nullptr;
1823   }
1824 
1825   if (!CheckParseTree(cx_, alloc_, body)) {
1826     return null();
1827   }
1828 
1829   if (!checkForUndefinedPrivateFields()) {
1830     return null();
1831   }
1832 
1833   ParseNode* node = body;
1834   // Don't constant-fold inside "use asm" code, as this could create a parse
1835   // tree that doesn't type-check as asm.js.
1836   if (!pc_->useAsmOrInsideUseAsm()) {
1837     if (!FoldConstants(cx_, this->parserAtoms(), &node, &handler_)) {
1838       return null();
1839     }
1840   }
1841   body = &node->as<ListNode>();
1842 
1843   if (!this->setSourceMapInfo()) {
1844     return nullptr;
1845   }
1846 
1847   // For global scripts, whether bindings are closed over or not doesn't
1848   // matter, so no need to call propagateFreeNamesAndMarkClosedOver-
1849   // Bindings. However, Annex B.3.3 functions still need to be marked.
1850   if (!varScope.propagateAndMarkAnnexBFunctionBoxes(pc_, this)) {
1851     return nullptr;
1852   }
1853 
1854   Maybe<GlobalScope::ParserData*> bindings =
1855       newGlobalScopeData(pc_->varScope());
1856   if (!bindings) {
1857     return nullptr;
1858   }
1859   globalsc->bindings = *bindings;
1860 
1861   return body;
1862 }
1863 
1864 template <typename Unit>
moduleBody(ModuleSharedContext * modulesc)1865 ModuleNode* Parser<FullParseHandler, Unit>::moduleBody(
1866     ModuleSharedContext* modulesc) {
1867   MOZ_ASSERT(checkOptionsCalled_);
1868 
1869   this->compilationState_.moduleMetadata =
1870       cx_->template new_<StencilModuleMetadata>();
1871   if (!this->compilationState_.moduleMetadata) {
1872     return null();
1873   }
1874 
1875   SourceParseContext modulepc(this, modulesc, nullptr);
1876   if (!modulepc.init()) {
1877     return null();
1878   }
1879 
1880   ParseContext::VarScope varScope(this);
1881   if (!varScope.init(pc_)) {
1882     return null();
1883   }
1884 
1885   ModuleNodeType moduleNode = handler_.newModule(pos());
1886   if (!moduleNode) {
1887     return null();
1888   }
1889 
1890   AutoAwaitIsKeyword<FullParseHandler, Unit> awaitIsKeyword(
1891       this, AwaitIsModuleKeyword);
1892   ListNode* stmtList = statementList(YieldIsName);
1893   if (!stmtList) {
1894     return null();
1895   }
1896 
1897   MOZ_ASSERT(stmtList->isKind(ParseNodeKind::StatementList));
1898   moduleNode->setBody(&stmtList->as<ListNode>());
1899 
1900   if (pc_->isAsync()) {
1901     if (!noteUsedName(TaggedParserAtomIndex::WellKnown::dotGenerator())) {
1902       return null();
1903     }
1904 
1905     if (!pc_->declareTopLevelDotGeneratorName()) {
1906       return null();
1907     }
1908   }
1909 
1910   TokenKind tt;
1911   if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) {
1912     return null();
1913   }
1914   if (tt != TokenKind::Eof) {
1915     error(JSMSG_GARBAGE_AFTER_INPUT, "module", TokenKindToDesc(tt));
1916     return null();
1917   }
1918 
1919   // Set the module to async if an await keyword was found at the top level.
1920   if (pc_->isAsync()) {
1921     pc_->sc()->asModuleContext()->builder.noteAsync(
1922         *this->compilationState_.moduleMetadata);
1923   }
1924 
1925   // Generate the Import/Export tables and store in CompilationState.
1926   if (!modulesc->builder.buildTables(*this->compilationState_.moduleMetadata)) {
1927     return null();
1928   }
1929 
1930   // Check exported local bindings exist and mark them as closed over.
1931   StencilModuleMetadata& moduleMetadata =
1932       *this->compilationState_.moduleMetadata;
1933   for (auto entry : moduleMetadata.localExportEntries) {
1934     DeclaredNamePtr p = modulepc.varScope().lookupDeclaredName(entry.localName);
1935     if (!p) {
1936       UniqueChars str =
1937           this->parserAtoms().toPrintableString(cx_, entry.localName);
1938       if (!str) {
1939         return null();
1940       }
1941 
1942       errorNoOffset(JSMSG_MISSING_EXPORT, str.get());
1943       return null();
1944     }
1945 
1946     p->value()->setClosedOver();
1947   }
1948 
1949   // Reserve an environment slot for a "*namespace*" psuedo-binding and mark as
1950   // closed-over. We do not know until module linking if this will be used.
1951   if (!noteDeclaredName(TaggedParserAtomIndex::WellKnown::starNamespaceStar(),
1952                         DeclarationKind::Const, pos())) {
1953     return nullptr;
1954   }
1955   modulepc.varScope()
1956       .lookupDeclaredName(TaggedParserAtomIndex::WellKnown::starNamespaceStar())
1957       ->value()
1958       ->setClosedOver();
1959 
1960   if (!CheckParseTree(cx_, alloc_, stmtList)) {
1961     return null();
1962   }
1963 
1964   ParseNode* node = stmtList;
1965   // Don't constant-fold inside "use asm" code, as this could create a parse
1966   // tree that doesn't type-check as asm.js.
1967   if (!pc_->useAsmOrInsideUseAsm()) {
1968     if (!FoldConstants(cx_, this->parserAtoms(), &node, &handler_)) {
1969       return null();
1970     }
1971   }
1972   stmtList = &node->as<ListNode>();
1973 
1974   if (!this->setSourceMapInfo()) {
1975     return null();
1976   }
1977 
1978   // Private names not lexically defined must trigger a syntax error.
1979   if (!checkForUndefinedPrivateFields()) {
1980     return null();
1981   }
1982 
1983   if (!propagateFreeNamesAndMarkClosedOverBindings(modulepc.varScope())) {
1984     return null();
1985   }
1986 
1987   Maybe<ModuleScope::ParserData*> bindings =
1988       newModuleScopeData(modulepc.varScope());
1989   if (!bindings) {
1990     return nullptr;
1991   }
1992 
1993   modulesc->bindings = *bindings;
1994   return moduleNode;
1995 }
1996 
1997 template <typename Unit>
moduleBody(ModuleSharedContext * modulesc)1998 SyntaxParseHandler::ModuleNodeType Parser<SyntaxParseHandler, Unit>::moduleBody(
1999     ModuleSharedContext* modulesc) {
2000   MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
2001   return SyntaxParseHandler::NodeFailure;
2002 }
2003 
2004 template <class ParseHandler>
2005 typename ParseHandler::NameNodeType
newInternalDotName(TaggedParserAtomIndex name)2006 PerHandlerParser<ParseHandler>::newInternalDotName(TaggedParserAtomIndex name) {
2007   NameNodeType nameNode = newName(name);
2008   if (!nameNode) {
2009     return null();
2010   }
2011   if (!noteUsedName(name)) {
2012     return null();
2013   }
2014   return nameNode;
2015 }
2016 
2017 template <class ParseHandler>
2018 typename ParseHandler::NameNodeType
newThisName()2019 PerHandlerParser<ParseHandler>::newThisName() {
2020   return newInternalDotName(TaggedParserAtomIndex::WellKnown::dotThis());
2021 }
2022 
2023 template <class ParseHandler>
2024 typename ParseHandler::NameNodeType
newDotGeneratorName()2025 PerHandlerParser<ParseHandler>::newDotGeneratorName() {
2026   return newInternalDotName(TaggedParserAtomIndex::WellKnown::dotGenerator());
2027 }
2028 
2029 template <class ParseHandler>
finishFunctionScopes(bool isStandaloneFunction)2030 bool PerHandlerParser<ParseHandler>::finishFunctionScopes(
2031     bool isStandaloneFunction) {
2032   FunctionBox* funbox = pc_->functionBox();
2033 
2034   if (funbox->hasParameterExprs) {
2035     if (!propagateFreeNamesAndMarkClosedOverBindings(pc_->functionScope())) {
2036       return false;
2037     }
2038 
2039     // Functions with parameter expressions utilize the FunctionScope for vars
2040     // generated by sloppy-direct-evals, as well as arguments (which are
2041     // lexicals bindings). If the function body has var bindings (or has a
2042     // sloppy-direct-eval that might), then an extra VarScope must be created
2043     // for them.
2044     if (VarScopeHasBindings(pc_) ||
2045         funbox->needsExtraBodyVarEnvironmentRegardlessOfBindings()) {
2046       funbox->setFunctionHasExtraBodyVarScope();
2047     }
2048   }
2049 
2050   // See: JSFunction::needsCallObject()
2051   if (FunctionScopeHasClosedOverBindings(pc_) ||
2052       funbox->needsCallObjectRegardlessOfBindings()) {
2053     funbox->setNeedsFunctionEnvironmentObjects();
2054   }
2055 
2056   if (funbox->isNamedLambda() && !isStandaloneFunction) {
2057     if (!propagateFreeNamesAndMarkClosedOverBindings(pc_->namedLambdaScope())) {
2058       return false;
2059     }
2060 
2061     // See: JSFunction::needsNamedLambdaEnvironment()
2062     if (LexicalScopeHasClosedOverBindings(pc_, pc_->namedLambdaScope())) {
2063       funbox->setNeedsFunctionEnvironmentObjects();
2064     }
2065   }
2066 
2067   return true;
2068 }
2069 
2070 template <>
finishFunction(bool isStandaloneFunction)2071 bool PerHandlerParser<FullParseHandler>::finishFunction(
2072     bool isStandaloneFunction /* = false */) {
2073   if (!finishFunctionScopes(isStandaloneFunction)) {
2074     return false;
2075   }
2076 
2077   FunctionBox* funbox = pc_->functionBox();
2078   ScriptStencil& script = funbox->functionStencil();
2079 
2080   if (funbox->isInterpreted()) {
2081     // BCE will need to generate bytecode for this.
2082     funbox->emitBytecode = true;
2083     this->compilationState_.nonLazyFunctionCount++;
2084   }
2085 
2086   bool hasParameterExprs = funbox->hasParameterExprs;
2087 
2088   if (hasParameterExprs) {
2089     Maybe<VarScope::ParserData*> bindings = newVarScopeData(pc_->varScope());
2090     if (!bindings) {
2091       return false;
2092     }
2093     funbox->setExtraVarScopeBindings(*bindings);
2094 
2095     MOZ_ASSERT(bool(*bindings) == VarScopeHasBindings(pc_));
2096     MOZ_ASSERT_IF(!funbox->needsExtraBodyVarEnvironmentRegardlessOfBindings(),
2097                   bool(*bindings) == funbox->functionHasExtraBodyVarScope());
2098   }
2099 
2100   {
2101     Maybe<FunctionScope::ParserData*> bindings =
2102         newFunctionScopeData(pc_->functionScope(), hasParameterExprs);
2103     if (!bindings) {
2104       return false;
2105     }
2106     funbox->setFunctionScopeBindings(*bindings);
2107   }
2108 
2109   if (funbox->isNamedLambda() && !isStandaloneFunction) {
2110     Maybe<LexicalScope::ParserData*> bindings =
2111         newLexicalScopeData(pc_->namedLambdaScope());
2112     if (!bindings) {
2113       return false;
2114     }
2115     funbox->setNamedLambdaBindings(*bindings);
2116   }
2117 
2118   funbox->finishScriptFlags();
2119   funbox->copyFunctionFields(script);
2120 
2121   if (this->compilationState_.isInitialStencil()) {
2122     ScriptStencilExtra& scriptExtra = funbox->functionExtraStencil();
2123     funbox->copyFunctionExtraFields(scriptExtra);
2124     funbox->copyScriptExtraFields(scriptExtra);
2125   }
2126 
2127   return true;
2128 }
2129 
2130 template <>
finishFunction(bool isStandaloneFunction)2131 bool PerHandlerParser<SyntaxParseHandler>::finishFunction(
2132     bool isStandaloneFunction /* = false */) {
2133   // The BaseScript for a lazily parsed function needs to know its set of
2134   // free variables and inner functions so that when it is fully parsed, we
2135   // can skip over any already syntax parsed inner functions and still
2136   // retain correct scope information.
2137 
2138   if (!finishFunctionScopes(isStandaloneFunction)) {
2139     return false;
2140   }
2141 
2142   FunctionBox* funbox = pc_->functionBox();
2143   ScriptStencil& script = funbox->functionStencil();
2144 
2145   funbox->finishScriptFlags();
2146   funbox->copyFunctionFields(script);
2147 
2148   ScriptStencilExtra& scriptExtra = funbox->functionExtraStencil();
2149   funbox->copyFunctionExtraFields(scriptExtra);
2150   funbox->copyScriptExtraFields(scriptExtra);
2151 
2152   // Elide nullptr sentinels from end of binding list. These are inserted for
2153   // each scope regardless of if any bindings are actually closed over.
2154   {
2155     AtomVector& closedOver = pc_->closedOverBindingsForLazy();
2156     while (!closedOver.empty() && !closedOver.back()) {
2157       closedOver.popBack();
2158     }
2159   }
2160 
2161   // Check if we will overflow the `ngcthings` field later.
2162   mozilla::CheckedUint32 ngcthings =
2163       mozilla::CheckedUint32(pc_->innerFunctionIndexesForLazy.length()) +
2164       mozilla::CheckedUint32(pc_->closedOverBindingsForLazy().length());
2165   if (!ngcthings.isValid()) {
2166     ReportAllocationOverflow(cx_);
2167     return false;
2168   }
2169 
2170   // If there are no script-things, we can return early without allocating.
2171   if (ngcthings.value() == 0) {
2172     MOZ_ASSERT(!script.hasGCThings());
2173     return true;
2174   }
2175 
2176   TaggedScriptThingIndex* cursor = nullptr;
2177   if (!this->compilationState_.allocateGCThingsUninitialized(
2178           cx_, funbox->index(), ngcthings.value(), &cursor)) {
2179     return false;
2180   }
2181 
2182   // Copy inner-function and closed-over-binding info for the stencil. The order
2183   // is important here. We emit functions first, followed by the bindings info.
2184   // The bindings list uses nullptr as delimiter to separates the bindings per
2185   // scope.
2186   //
2187   // See: FullParseHandler::nextLazyInnerFunction(),
2188   //      FullParseHandler::nextLazyClosedOverBinding()
2189   for (const ScriptIndex& index : pc_->innerFunctionIndexesForLazy) {
2190     void* raw = &(*cursor++);
2191     new (raw) TaggedScriptThingIndex(index);
2192   }
2193   for (auto binding : pc_->closedOverBindingsForLazy()) {
2194     void* raw = &(*cursor++);
2195     if (binding) {
2196       this->parserAtoms().markUsedByStencil(binding, ParserAtom::Atomize::Yes);
2197       new (raw) TaggedScriptThingIndex(binding);
2198     } else {
2199       new (raw) TaggedScriptThingIndex();
2200     }
2201   }
2202 
2203   return true;
2204 }
2205 
GetYieldHandling(GeneratorKind generatorKind)2206 static YieldHandling GetYieldHandling(GeneratorKind generatorKind) {
2207   if (generatorKind == GeneratorKind::NotGenerator) {
2208     return YieldIsName;
2209   }
2210   return YieldIsKeyword;
2211 }
2212 
GetAwaitHandling(FunctionAsyncKind asyncKind)2213 static AwaitHandling GetAwaitHandling(FunctionAsyncKind asyncKind) {
2214   if (asyncKind == FunctionAsyncKind::SyncFunction) {
2215     return AwaitIsName;
2216   }
2217   return AwaitIsKeyword;
2218 }
2219 
InitialFunctionFlags(FunctionSyntaxKind kind,GeneratorKind generatorKind,FunctionAsyncKind asyncKind,bool isSelfHosting,bool forceExtended)2220 FunctionFlags InitialFunctionFlags(FunctionSyntaxKind kind,
2221                                    GeneratorKind generatorKind,
2222                                    FunctionAsyncKind asyncKind,
2223                                    bool isSelfHosting, bool forceExtended) {
2224   FunctionFlags flags = {};
2225   gc::AllocKind allocKind = gc::AllocKind::FUNCTION;
2226 
2227   // Only normal function statements/expressions may force extended mode. Other
2228   // types of functions use extended slots for their own purposes.
2229   MOZ_ASSERT_IF(forceExtended, kind == FunctionSyntaxKind::Statement ||
2230                                    kind == FunctionSyntaxKind::Expression);
2231 
2232   switch (kind) {
2233     case FunctionSyntaxKind::Expression:
2234       flags = (generatorKind == GeneratorKind::NotGenerator &&
2235                        asyncKind == FunctionAsyncKind::SyncFunction
2236                    ? FunctionFlags::INTERPRETED_LAMBDA
2237                    : FunctionFlags::INTERPRETED_LAMBDA_GENERATOR_OR_ASYNC);
2238       break;
2239     case FunctionSyntaxKind::Arrow:
2240       flags = FunctionFlags::INTERPRETED_LAMBDA_ARROW;
2241       allocKind = gc::AllocKind::FUNCTION_EXTENDED;
2242       break;
2243     case FunctionSyntaxKind::Method:
2244     case FunctionSyntaxKind::FieldInitializer:
2245     case FunctionSyntaxKind::StaticClassBlock:
2246       flags = FunctionFlags::INTERPRETED_METHOD;
2247       allocKind = gc::AllocKind::FUNCTION_EXTENDED;
2248       break;
2249     case FunctionSyntaxKind::ClassConstructor:
2250     case FunctionSyntaxKind::DerivedClassConstructor:
2251       flags = FunctionFlags::INTERPRETED_CLASS_CTOR;
2252       allocKind = gc::AllocKind::FUNCTION_EXTENDED;
2253       break;
2254     case FunctionSyntaxKind::Getter:
2255       flags = FunctionFlags::INTERPRETED_GETTER;
2256       allocKind = gc::AllocKind::FUNCTION_EXTENDED;
2257       break;
2258     case FunctionSyntaxKind::Setter:
2259       flags = FunctionFlags::INTERPRETED_SETTER;
2260       allocKind = gc::AllocKind::FUNCTION_EXTENDED;
2261       break;
2262     default:
2263       MOZ_ASSERT(kind == FunctionSyntaxKind::Statement);
2264       flags = (generatorKind == GeneratorKind::NotGenerator &&
2265                        asyncKind == FunctionAsyncKind::SyncFunction
2266                    ? FunctionFlags::INTERPRETED_NORMAL
2267                    : FunctionFlags::INTERPRETED_GENERATOR_OR_ASYNC);
2268   }
2269 
2270   if (isSelfHosting) {
2271     flags.setIsSelfHostedBuiltin();
2272   }
2273 
2274   if ((allocKind == gc::AllocKind::FUNCTION_EXTENDED) || forceExtended) {
2275     flags.setIsExtended();
2276   }
2277 
2278   return flags;
2279 }
2280 
2281 template <typename Unit>
standaloneFunction(const Maybe<uint32_t> & parameterListEnd,FunctionSyntaxKind syntaxKind,GeneratorKind generatorKind,FunctionAsyncKind asyncKind,Directives inheritedDirectives,Directives * newDirectives)2282 FunctionNode* Parser<FullParseHandler, Unit>::standaloneFunction(
2283     const Maybe<uint32_t>& parameterListEnd, FunctionSyntaxKind syntaxKind,
2284     GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
2285     Directives inheritedDirectives, Directives* newDirectives) {
2286   MOZ_ASSERT(checkOptionsCalled_);
2287   // Skip prelude.
2288   TokenKind tt;
2289   if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) {
2290     return null();
2291   }
2292   if (asyncKind == FunctionAsyncKind::AsyncFunction) {
2293     MOZ_ASSERT(tt == TokenKind::Async);
2294     if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) {
2295       return null();
2296     }
2297   }
2298   MOZ_ASSERT(tt == TokenKind::Function);
2299 
2300   if (!tokenStream.getToken(&tt)) {
2301     return null();
2302   }
2303   if (generatorKind == GeneratorKind::Generator) {
2304     MOZ_ASSERT(tt == TokenKind::Mul);
2305     if (!tokenStream.getToken(&tt)) {
2306       return null();
2307     }
2308   }
2309 
2310   // Skip function name, if present.
2311   TaggedParserAtomIndex explicitName;
2312   if (TokenKindIsPossibleIdentifierName(tt)) {
2313     explicitName = anyChars.currentName();
2314   } else {
2315     anyChars.ungetToken();
2316   }
2317 
2318   FunctionNodeType funNode = handler_.newFunction(syntaxKind, pos());
2319   if (!funNode) {
2320     return null();
2321   }
2322 
2323   ListNodeType argsbody = handler_.newList(ParseNodeKind::ParamsBody, pos());
2324   if (!argsbody) {
2325     return null();
2326   }
2327   funNode->setBody(argsbody);
2328 
2329   bool isSelfHosting = options().selfHostingMode;
2330   FunctionFlags flags =
2331       InitialFunctionFlags(syntaxKind, generatorKind, asyncKind, isSelfHosting);
2332   FunctionBox* funbox =
2333       newFunctionBox(funNode, explicitName, flags, /* toStringStart = */ 0,
2334                      inheritedDirectives, generatorKind, asyncKind);
2335   if (!funbox) {
2336     return null();
2337   }
2338 
2339   // Function is not syntactically part of another script.
2340   MOZ_ASSERT(funbox->index() == CompilationStencil::TopLevelIndex);
2341 
2342   funbox->initStandalone(this->compilationState_.scopeContext, flags,
2343                          syntaxKind);
2344 
2345   SourceParseContext funpc(this, funbox, newDirectives);
2346   if (!funpc.init()) {
2347     return null();
2348   }
2349 
2350   YieldHandling yieldHandling = GetYieldHandling(generatorKind);
2351   AwaitHandling awaitHandling = GetAwaitHandling(asyncKind);
2352   AutoAwaitIsKeyword<FullParseHandler, Unit> awaitIsKeyword(this,
2353                                                             awaitHandling);
2354   if (!functionFormalParametersAndBody(InAllowed, yieldHandling, &funNode,
2355                                        syntaxKind, parameterListEnd,
2356                                        /* isStandaloneFunction = */ true)) {
2357     return null();
2358   }
2359 
2360   if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) {
2361     return null();
2362   }
2363   if (tt != TokenKind::Eof) {
2364     error(JSMSG_GARBAGE_AFTER_INPUT, "function body", TokenKindToDesc(tt));
2365     return null();
2366   }
2367 
2368   if (!CheckParseTree(cx_, alloc_, funNode)) {
2369     return null();
2370   }
2371 
2372   ParseNode* node = funNode;
2373   // Don't constant-fold inside "use asm" code, as this could create a parse
2374   // tree that doesn't type-check as asm.js.
2375   if (!pc_->useAsmOrInsideUseAsm()) {
2376     if (!FoldConstants(cx_, this->parserAtoms(), &node, &handler_)) {
2377       return null();
2378     }
2379   }
2380   funNode = &node->as<FunctionNode>();
2381 
2382   if (!checkForUndefinedPrivateFields(nullptr)) {
2383     return null();
2384   }
2385 
2386   if (!this->setSourceMapInfo()) {
2387     return null();
2388   }
2389 
2390   return funNode;
2391 }
2392 
2393 template <class ParseHandler, typename Unit>
2394 typename ParseHandler::LexicalScopeNodeType
functionBody(InHandling inHandling,YieldHandling yieldHandling,FunctionSyntaxKind kind,FunctionBodyType type)2395 GeneralParser<ParseHandler, Unit>::functionBody(InHandling inHandling,
2396                                                 YieldHandling yieldHandling,
2397                                                 FunctionSyntaxKind kind,
2398                                                 FunctionBodyType type) {
2399   MOZ_ASSERT(pc_->isFunctionBox());
2400 
2401 #ifdef DEBUG
2402   uint32_t startYieldOffset = pc_->lastYieldOffset;
2403 #endif
2404 
2405   Node body;
2406   if (type == StatementListBody) {
2407     bool inheritedStrict = pc_->sc()->strict();
2408     body = statementList(yieldHandling);
2409     if (!body) {
2410       return null();
2411     }
2412 
2413     // When we transitioned from non-strict to strict mode, we need to
2414     // validate that all parameter names are valid strict mode names.
2415     if (!inheritedStrict && pc_->sc()->strict()) {
2416       MOZ_ASSERT(pc_->sc()->hasExplicitUseStrict(),
2417                  "strict mode should only change when a 'use strict' directive "
2418                  "is present");
2419       if (!hasValidSimpleStrictParameterNames()) {
2420         // Request that this function be reparsed as strict to report
2421         // the invalid parameter name at the correct source location.
2422         pc_->newDirectives->setStrict();
2423         return null();
2424       }
2425     }
2426   } else {
2427     MOZ_ASSERT(type == ExpressionBody);
2428 
2429     // Async functions are implemented as generators, and generators are
2430     // assumed to be statement lists, to prepend initial `yield`.
2431     ListNodeType stmtList = null();
2432     if (pc_->isAsync()) {
2433       stmtList = handler_.newStatementList(pos());
2434       if (!stmtList) {
2435         return null();
2436       }
2437     }
2438 
2439     Node kid = assignExpr(inHandling, yieldHandling, TripledotProhibited);
2440     if (!kid) {
2441       return null();
2442     }
2443 
2444     body = handler_.newExpressionBody(kid);
2445     if (!body) {
2446       return null();
2447     }
2448 
2449     if (pc_->isAsync()) {
2450       handler_.addStatementToList(stmtList, body);
2451       body = stmtList;
2452     }
2453   }
2454 
2455   MOZ_ASSERT_IF(!pc_->isGenerator() && !pc_->isAsync(),
2456                 pc_->lastYieldOffset == startYieldOffset);
2457   MOZ_ASSERT_IF(pc_->isGenerator(), kind != FunctionSyntaxKind::Arrow);
2458   MOZ_ASSERT_IF(pc_->isGenerator(), type == StatementListBody);
2459 
2460   if (pc_->needsDotGeneratorName()) {
2461     MOZ_ASSERT_IF(!pc_->isAsync(), type == StatementListBody);
2462     if (!pc_->declareDotGeneratorName()) {
2463       return null();
2464     }
2465     if (pc_->isGenerator()) {
2466       NameNodeType generator = newDotGeneratorName();
2467       if (!generator) {
2468         return null();
2469       }
2470       if (!handler_.prependInitialYield(handler_.asList(body), generator)) {
2471         return null();
2472       }
2473     }
2474   }
2475 
2476   // Declare the 'arguments' and 'this' bindings if necessary before
2477   // finishing up the scope so these special bindings get marked as closed
2478   // over if necessary. Arrow functions don't have these bindings.
2479   if (kind != FunctionSyntaxKind::Arrow) {
2480     bool canSkipLazyClosedOverBindings = handler_.reuseClosedOverBindings();
2481     if (!pc_->declareFunctionArgumentsObject(usedNames_,
2482                                              canSkipLazyClosedOverBindings)) {
2483       return null();
2484     }
2485     if (!pc_->declareFunctionThis(usedNames_, canSkipLazyClosedOverBindings)) {
2486       return null();
2487     }
2488   }
2489 
2490   return finishLexicalScope(pc_->varScope(), body, ScopeKind::FunctionLexical);
2491 }
2492 
2493 template <class ParseHandler, typename Unit>
matchOrInsertSemicolon(Modifier modifier)2494 bool GeneralParser<ParseHandler, Unit>::matchOrInsertSemicolon(
2495     Modifier modifier /* = TokenStream::SlashIsRegExp */) {
2496   TokenKind tt = TokenKind::Eof;
2497   if (!tokenStream.peekTokenSameLine(&tt, modifier)) {
2498     return false;
2499   }
2500   if (tt != TokenKind::Eof && tt != TokenKind::Eol && tt != TokenKind::Semi &&
2501       tt != TokenKind::RightCurly) {
2502     /*
2503      * When current token is `await` and it's outside of async function,
2504      * it's possibly intended to be an await expression.
2505      *
2506      *   await f();
2507      *        ^
2508      *        |
2509      *        tried to insert semicolon here
2510      *
2511      * Detect this situation and throw an understandable error.  Otherwise
2512      * we'd throw a confusing "unexpected token: (unexpected token)" error.
2513      */
2514     if (!pc_->isAsync() && anyChars.currentToken().type == TokenKind::Await) {
2515       error(JSMSG_AWAIT_OUTSIDE_ASYNC_OR_MODULE);
2516       return false;
2517     }
2518     if (!yieldExpressionsSupported() &&
2519         anyChars.currentToken().type == TokenKind::Yield) {
2520       error(JSMSG_YIELD_OUTSIDE_GENERATOR);
2521       return false;
2522     }
2523 
2524     /* Advance the scanner for proper error location reporting. */
2525     tokenStream.consumeKnownToken(tt, modifier);
2526     error(JSMSG_UNEXPECTED_TOKEN_NO_EXPECT, TokenKindToDesc(tt));
2527     return false;
2528   }
2529   bool matched;
2530   return tokenStream.matchToken(&matched, TokenKind::Semi, modifier);
2531 }
2532 
leaveInnerFunction(ParseContext * outerpc)2533 bool ParserBase::leaveInnerFunction(ParseContext* outerpc) {
2534   MOZ_ASSERT(pc_ != outerpc);
2535 
2536   MOZ_ASSERT_IF(outerpc->isFunctionBox(),
2537                 outerpc->functionBox()->index() < pc_->functionBox()->index());
2538 
2539   // If the current function allows super.property but cannot have a home
2540   // object, i.e., it is an arrow function, we need to propagate the flag to
2541   // the outer ParseContext.
2542   if (pc_->superScopeNeedsHomeObject()) {
2543     if (!pc_->isArrowFunction()) {
2544       MOZ_ASSERT(pc_->functionBox()->needsHomeObject());
2545     } else {
2546       outerpc->setSuperScopeNeedsHomeObject();
2547     }
2548   }
2549 
2550   // Lazy functions inner to another lazy function need to be remembered by
2551   // the inner function so that if the outer function is eventually parsed
2552   // we do not need any further parsing or processing of the inner function.
2553   //
2554   // Append the inner function index here unconditionally; the vector is only
2555   // used if the Parser using outerpc is a syntax parsing. See
2556   // GeneralParser<SyntaxParseHandler>::finishFunction.
2557   if (!outerpc->innerFunctionIndexesForLazy.append(
2558           pc_->functionBox()->index())) {
2559     return false;
2560   }
2561 
2562   PropagateTransitiveParseFlags(pc_->functionBox(), outerpc->sc());
2563 
2564   return true;
2565 }
2566 
prefixAccessorName(PropertyType propType,TaggedParserAtomIndex propAtom)2567 TaggedParserAtomIndex ParserBase::prefixAccessorName(
2568     PropertyType propType, TaggedParserAtomIndex propAtom) {
2569   StringBuffer prefixed(cx_);
2570   if (propType == PropertyType::Setter) {
2571     if (!prefixed.append("set ", 4)) {
2572       return TaggedParserAtomIndex::null();
2573     }
2574   } else {
2575     if (!prefixed.append("get ", 4)) {
2576       return TaggedParserAtomIndex::null();
2577     }
2578   }
2579   if (!prefixed.append(this->parserAtoms(), propAtom)) {
2580     return TaggedParserAtomIndex::null();
2581   }
2582   return prefixed.finishParserAtom(this->parserAtoms());
2583 }
2584 
2585 template <class ParseHandler, typename Unit>
setFunctionStartAtPosition(FunctionBox * funbox,TokenPos pos) const2586 void GeneralParser<ParseHandler, Unit>::setFunctionStartAtPosition(
2587     FunctionBox* funbox, TokenPos pos) const {
2588   uint32_t startLine, startColumn;
2589   tokenStream.computeLineAndColumn(pos.begin, &startLine, &startColumn);
2590 
2591   // NOTE: `Debugger::CallData::findScripts` relies on sourceStart and
2592   //       lineno/column referring to the same location.
2593   funbox->setStart(pos.begin, startLine, startColumn);
2594 }
2595 
2596 template <class ParseHandler, typename Unit>
setFunctionStartAtCurrentToken(FunctionBox * funbox) const2597 void GeneralParser<ParseHandler, Unit>::setFunctionStartAtCurrentToken(
2598     FunctionBox* funbox) const {
2599   setFunctionStartAtPosition(funbox, anyChars.currentToken().pos);
2600 }
2601 
2602 template <class ParseHandler, typename Unit>
functionArguments(YieldHandling yieldHandling,FunctionSyntaxKind kind,FunctionNodeType funNode)2603 bool GeneralParser<ParseHandler, Unit>::functionArguments(
2604     YieldHandling yieldHandling, FunctionSyntaxKind kind,
2605     FunctionNodeType funNode) {
2606   FunctionBox* funbox = pc_->functionBox();
2607 
2608   bool parenFreeArrow = false;
2609   // Modifier for the following tokens.
2610   // TokenStream::SlashIsDiv for the following cases:
2611   //   async a => 1
2612   //         ^
2613   //
2614   //   (a) => 1
2615   //   ^
2616   //
2617   //   async (a) => 1
2618   //         ^
2619   //
2620   //   function f(a) {}
2621   //             ^
2622   //
2623   // TokenStream::SlashIsRegExp for the following case:
2624   //   a => 1
2625   //   ^
2626   Modifier firstTokenModifier = TokenStream::SlashIsDiv;
2627 
2628   // Modifier for the the first token in each argument.
2629   // can be changed to TokenStream::SlashIsDiv for the following case:
2630   //   async a => 1
2631   //         ^
2632   Modifier argModifier = TokenStream::SlashIsRegExp;
2633   if (kind == FunctionSyntaxKind::Arrow) {
2634     TokenKind tt;
2635     // In async function, the first token after `async` is already gotten
2636     // with TokenStream::SlashIsDiv.
2637     // In sync function, the first token is already gotten with
2638     // TokenStream::SlashIsRegExp.
2639     firstTokenModifier = funbox->isAsync() ? TokenStream::SlashIsDiv
2640                                            : TokenStream::SlashIsRegExp;
2641     if (!tokenStream.peekToken(&tt, firstTokenModifier)) {
2642       return false;
2643     }
2644     if (TokenKindIsPossibleIdentifier(tt)) {
2645       parenFreeArrow = true;
2646       argModifier = firstTokenModifier;
2647     }
2648   }
2649 
2650   TokenPos firstTokenPos;
2651   if (!parenFreeArrow) {
2652     TokenKind tt;
2653     if (!tokenStream.getToken(&tt, firstTokenModifier)) {
2654       return false;
2655     }
2656     if (tt != TokenKind::LeftParen) {
2657       error(kind == FunctionSyntaxKind::Arrow ? JSMSG_BAD_ARROW_ARGS
2658                                               : JSMSG_PAREN_BEFORE_FORMAL);
2659       return false;
2660     }
2661 
2662     firstTokenPos = pos();
2663 
2664     // Record the start of function source (for FunctionToString). If we
2665     // are parenFreeArrow, we will set this below, after consuming the NAME.
2666     setFunctionStartAtCurrentToken(funbox);
2667   } else {
2668     // When delazifying, we may not have a current token and pos() is
2669     // garbage. In that case, substitute the first token's position.
2670     if (!tokenStream.peekTokenPos(&firstTokenPos, firstTokenModifier)) {
2671       return false;
2672     }
2673   }
2674 
2675   ListNodeType argsbody =
2676       handler_.newList(ParseNodeKind::ParamsBody, firstTokenPos);
2677   if (!argsbody) {
2678     return false;
2679   }
2680   handler_.setFunctionFormalParametersAndBody(funNode, argsbody);
2681 
2682   bool hasArguments = false;
2683   if (parenFreeArrow) {
2684     hasArguments = true;
2685   } else {
2686     bool matched;
2687     if (!tokenStream.matchToken(&matched, TokenKind::RightParen,
2688                                 TokenStream::SlashIsRegExp)) {
2689       return false;
2690     }
2691     if (!matched) {
2692       hasArguments = true;
2693     }
2694   }
2695   if (hasArguments) {
2696     bool hasRest = false;
2697     bool hasDefault = false;
2698     bool duplicatedParam = false;
2699     bool disallowDuplicateParams =
2700         kind == FunctionSyntaxKind::Arrow ||
2701         kind == FunctionSyntaxKind::Method ||
2702         kind == FunctionSyntaxKind::FieldInitializer ||
2703         kind == FunctionSyntaxKind::ClassConstructor;
2704     AtomVector& positionalFormals = pc_->positionalFormalParameterNames();
2705 
2706     if (kind == FunctionSyntaxKind::Getter) {
2707       error(JSMSG_ACCESSOR_WRONG_ARGS, "getter", "no", "s");
2708       return false;
2709     }
2710 
2711     while (true) {
2712       if (hasRest) {
2713         error(JSMSG_PARAMETER_AFTER_REST);
2714         return false;
2715       }
2716 
2717       TokenKind tt;
2718       if (!tokenStream.getToken(&tt, argModifier)) {
2719         return false;
2720       }
2721       argModifier = TokenStream::SlashIsRegExp;
2722       MOZ_ASSERT_IF(parenFreeArrow, TokenKindIsPossibleIdentifier(tt));
2723 
2724       if (tt == TokenKind::TripleDot) {
2725         if (kind == FunctionSyntaxKind::Setter) {
2726           error(JSMSG_ACCESSOR_WRONG_ARGS, "setter", "one", "");
2727           return false;
2728         }
2729 
2730         disallowDuplicateParams = true;
2731         if (duplicatedParam) {
2732           // Has duplicated args before the rest parameter.
2733           error(JSMSG_BAD_DUP_ARGS);
2734           return false;
2735         }
2736 
2737         hasRest = true;
2738         funbox->setHasRest();
2739 
2740         if (!tokenStream.getToken(&tt)) {
2741           return false;
2742         }
2743 
2744         if (!TokenKindIsPossibleIdentifier(tt) &&
2745             tt != TokenKind::LeftBracket && tt != TokenKind::LeftCurly) {
2746           error(JSMSG_NO_REST_NAME);
2747           return false;
2748         }
2749       }
2750 
2751       switch (tt) {
2752         case TokenKind::LeftBracket:
2753         case TokenKind::LeftCurly: {
2754           disallowDuplicateParams = true;
2755           if (duplicatedParam) {
2756             // Has duplicated args before the destructuring parameter.
2757             error(JSMSG_BAD_DUP_ARGS);
2758             return false;
2759           }
2760 
2761           funbox->hasDestructuringArgs = true;
2762 
2763           Node destruct = destructuringDeclarationWithoutYieldOrAwait(
2764               DeclarationKind::FormalParameter, yieldHandling, tt);
2765           if (!destruct) {
2766             return false;
2767           }
2768 
2769           if (!noteDestructuredPositionalFormalParameter(funNode, destruct)) {
2770             return false;
2771           }
2772 
2773           break;
2774         }
2775 
2776         default: {
2777           if (!TokenKindIsPossibleIdentifier(tt)) {
2778             error(JSMSG_MISSING_FORMAL);
2779             return false;
2780           }
2781 
2782           if (parenFreeArrow) {
2783             setFunctionStartAtCurrentToken(funbox);
2784           }
2785 
2786           TaggedParserAtomIndex name = bindingIdentifier(yieldHandling);
2787           if (!name) {
2788             return false;
2789           }
2790 
2791           if (!notePositionalFormalParameter(funNode, name, pos().begin,
2792                                              disallowDuplicateParams,
2793                                              &duplicatedParam)) {
2794             return false;
2795           }
2796           if (duplicatedParam) {
2797             funbox->hasDuplicateParameters = true;
2798           }
2799 
2800           break;
2801         }
2802       }
2803 
2804       if (positionalFormals.length() >= ARGNO_LIMIT) {
2805         error(JSMSG_TOO_MANY_FUN_ARGS);
2806         return false;
2807       }
2808 
2809       // The next step is to detect arguments with default expressions,
2810       // e.g. |function parseInt(str, radix = 10) {}|.  But if we have a
2811       // parentheses-free arrow function, |a => ...|, the '=' necessary
2812       // for a default expression would really be an assignment operator:
2813       // that is, |a = b => 42;| would parse as |a = (b => 42);|.  So we
2814       // should stop parsing arguments here.
2815       if (parenFreeArrow) {
2816         break;
2817       }
2818 
2819       bool matched;
2820       if (!tokenStream.matchToken(&matched, TokenKind::Assign,
2821                                   TokenStream::SlashIsRegExp)) {
2822         return false;
2823       }
2824       if (matched) {
2825         // A default argument without parentheses would look like:
2826         // a = expr => body, but both operators are right-associative, so
2827         // that would have been parsed as a = (expr => body) instead.
2828         // Therefore it's impossible to get here with parenFreeArrow.
2829         MOZ_ASSERT(!parenFreeArrow);
2830 
2831         if (hasRest) {
2832           error(JSMSG_REST_WITH_DEFAULT);
2833           return false;
2834         }
2835         disallowDuplicateParams = true;
2836         if (duplicatedParam) {
2837           error(JSMSG_BAD_DUP_ARGS);
2838           return false;
2839         }
2840 
2841         if (!hasDefault) {
2842           hasDefault = true;
2843 
2844           // The Function.length property is the number of formals
2845           // before the first default argument.
2846           funbox->setLength(positionalFormals.length() - 1);
2847         }
2848         funbox->hasParameterExprs = true;
2849 
2850         Node def_expr = assignExprWithoutYieldOrAwait(yieldHandling);
2851         if (!def_expr) {
2852           return false;
2853         }
2854         if (!handler_.setLastFunctionFormalParameterDefault(funNode,
2855                                                             def_expr)) {
2856           return false;
2857         }
2858       }
2859 
2860       // Setter syntax uniquely requires exactly one argument.
2861       if (kind == FunctionSyntaxKind::Setter) {
2862         break;
2863       }
2864 
2865       if (!tokenStream.matchToken(&matched, TokenKind::Comma,
2866                                   TokenStream::SlashIsRegExp)) {
2867         return false;
2868       }
2869       if (!matched) {
2870         break;
2871       }
2872 
2873       if (!hasRest) {
2874         if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) {
2875           return false;
2876         }
2877         if (tt == TokenKind::RightParen) {
2878           break;
2879         }
2880       }
2881     }
2882 
2883     if (!parenFreeArrow) {
2884       TokenKind tt;
2885       if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) {
2886         return false;
2887       }
2888       if (tt != TokenKind::RightParen) {
2889         if (kind == FunctionSyntaxKind::Setter) {
2890           error(JSMSG_ACCESSOR_WRONG_ARGS, "setter", "one", "");
2891           return false;
2892         }
2893 
2894         error(JSMSG_PAREN_AFTER_FORMAL);
2895         return false;
2896       }
2897     }
2898 
2899     if (!hasDefault) {
2900       funbox->setLength(positionalFormals.length() - hasRest);
2901     }
2902 
2903     funbox->setArgCount(positionalFormals.length());
2904   } else if (kind == FunctionSyntaxKind::Setter) {
2905     error(JSMSG_ACCESSOR_WRONG_ARGS, "setter", "one", "");
2906     return false;
2907   }
2908 
2909   return true;
2910 }
2911 
2912 template <typename Unit>
skipLazyInnerFunction(FunctionNode * funNode,uint32_t toStringStart,bool tryAnnexB)2913 bool Parser<FullParseHandler, Unit>::skipLazyInnerFunction(
2914     FunctionNode* funNode, uint32_t toStringStart, bool tryAnnexB) {
2915   // When a lazily-parsed function is called, we only fully parse (and emit)
2916   // that function, not any of its nested children. The initial syntax-only
2917   // parse recorded the free variables of nested functions and their extents,
2918   // so we can skip over them after accounting for their free variables.
2919 
2920   MOZ_ASSERT(pc_->isOutermostOfCurrentCompile());
2921   handler_.nextLazyInnerFunction();
2922   const ScriptStencil& cachedData = handler_.cachedScriptData();
2923   const ScriptStencilExtra& cachedExtra = handler_.cachedScriptExtra();
2924   MOZ_ASSERT(toStringStart == cachedExtra.extent.toStringStart);
2925 
2926   FunctionBox* funbox = newFunctionBox(funNode, cachedData, cachedExtra);
2927   if (!funbox) {
2928     return false;
2929   }
2930 
2931   ScriptStencil& script = funbox->functionStencil();
2932   funbox->copyFunctionFields(script);
2933 
2934   // If the inner lazy function is class constructor, connect it to the class
2935   // statement/expression we are parsing.
2936   if (funbox->isClassConstructor()) {
2937     auto classStmt =
2938         pc_->template findInnermostStatement<ParseContext::ClassStatement>();
2939     MOZ_ASSERT(!classStmt->constructorBox);
2940     classStmt->constructorBox = funbox;
2941   }
2942 
2943   MOZ_ASSERT_IF(pc_->isFunctionBox(),
2944                 pc_->functionBox()->index() < funbox->index());
2945 
2946   PropagateTransitiveParseFlags(funbox, pc_->sc());
2947 
2948   if (!tokenStream.advance(funbox->extent().sourceEnd)) {
2949     return false;
2950   }
2951 
2952   // Append possible Annex B function box only upon successfully parsing.
2953   if (tryAnnexB &&
2954       !pc_->innermostScope()->addPossibleAnnexBFunctionBox(pc_, funbox)) {
2955     return false;
2956   }
2957 
2958   return true;
2959 }
2960 
2961 template <typename Unit>
skipLazyInnerFunction(FunctionNodeType funNode,uint32_t toStringStart,bool tryAnnexB)2962 bool Parser<SyntaxParseHandler, Unit>::skipLazyInnerFunction(
2963     FunctionNodeType funNode, uint32_t toStringStart, bool tryAnnexB) {
2964   MOZ_CRASH("Cannot skip lazy inner functions when syntax parsing");
2965 }
2966 
2967 template <class ParseHandler, typename Unit>
skipLazyInnerFunction(FunctionNodeType funNode,uint32_t toStringStart,bool tryAnnexB)2968 bool GeneralParser<ParseHandler, Unit>::skipLazyInnerFunction(
2969     FunctionNodeType funNode, uint32_t toStringStart, bool tryAnnexB) {
2970   return asFinalParser()->skipLazyInnerFunction(funNode, toStringStart,
2971                                                 tryAnnexB);
2972 }
2973 
2974 template <class ParseHandler, typename Unit>
addExprAndGetNextTemplStrToken(YieldHandling yieldHandling,ListNodeType nodeList,TokenKind * ttp)2975 bool GeneralParser<ParseHandler, Unit>::addExprAndGetNextTemplStrToken(
2976     YieldHandling yieldHandling, ListNodeType nodeList, TokenKind* ttp) {
2977   Node pn = expr(InAllowed, yieldHandling, TripledotProhibited);
2978   if (!pn) {
2979     return false;
2980   }
2981   handler_.addList(nodeList, pn);
2982 
2983   TokenKind tt;
2984   if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) {
2985     return false;
2986   }
2987   if (tt != TokenKind::RightCurly) {
2988     error(JSMSG_TEMPLSTR_UNTERM_EXPR);
2989     return false;
2990   }
2991 
2992   return tokenStream.getTemplateToken(ttp);
2993 }
2994 
2995 template <class ParseHandler, typename Unit>
taggedTemplate(YieldHandling yieldHandling,ListNodeType tagArgsList,TokenKind tt)2996 bool GeneralParser<ParseHandler, Unit>::taggedTemplate(
2997     YieldHandling yieldHandling, ListNodeType tagArgsList, TokenKind tt) {
2998   CallSiteNodeType callSiteObjNode = handler_.newCallSiteObject(pos().begin);
2999   if (!callSiteObjNode) {
3000     return false;
3001   }
3002   handler_.addList(tagArgsList, callSiteObjNode);
3003 
3004   pc_->sc()->setHasCallSiteObj();
3005 
3006   while (true) {
3007     if (!appendToCallSiteObj(callSiteObjNode)) {
3008       return false;
3009     }
3010     if (tt != TokenKind::TemplateHead) {
3011       break;
3012     }
3013 
3014     if (!addExprAndGetNextTemplStrToken(yieldHandling, tagArgsList, &tt)) {
3015       return false;
3016     }
3017   }
3018   handler_.setEndPosition(tagArgsList, callSiteObjNode);
3019   return true;
3020 }
3021 
3022 template <class ParseHandler, typename Unit>
3023 typename ParseHandler::ListNodeType
templateLiteral(YieldHandling yieldHandling)3024 GeneralParser<ParseHandler, Unit>::templateLiteral(
3025     YieldHandling yieldHandling) {
3026   NameNodeType literal = noSubstitutionUntaggedTemplate();
3027   if (!literal) {
3028     return null();
3029   }
3030 
3031   ListNodeType nodeList =
3032       handler_.newList(ParseNodeKind::TemplateStringListExpr, literal);
3033   if (!nodeList) {
3034     return null();
3035   }
3036 
3037   TokenKind tt;
3038   do {
3039     if (!addExprAndGetNextTemplStrToken(yieldHandling, nodeList, &tt)) {
3040       return null();
3041     }
3042 
3043     literal = noSubstitutionUntaggedTemplate();
3044     if (!literal) {
3045       return null();
3046     }
3047 
3048     handler_.addList(nodeList, literal);
3049   } while (tt == TokenKind::TemplateHead);
3050   return nodeList;
3051 }
3052 
3053 template <class ParseHandler, typename Unit>
3054 typename ParseHandler::FunctionNodeType
functionDefinition(FunctionNodeType funNode,uint32_t toStringStart,InHandling inHandling,YieldHandling yieldHandling,TaggedParserAtomIndex funName,FunctionSyntaxKind kind,GeneratorKind generatorKind,FunctionAsyncKind asyncKind,bool tryAnnexB)3055 GeneralParser<ParseHandler, Unit>::functionDefinition(
3056     FunctionNodeType funNode, uint32_t toStringStart, InHandling inHandling,
3057     YieldHandling yieldHandling, TaggedParserAtomIndex funName,
3058     FunctionSyntaxKind kind, GeneratorKind generatorKind,
3059     FunctionAsyncKind asyncKind, bool tryAnnexB /* = false */) {
3060   MOZ_ASSERT_IF(kind == FunctionSyntaxKind::Statement, funName);
3061 
3062   // If we see any inner function, note it on our current context. The bytecode
3063   // emitter may eliminate the function later, but we use a conservative
3064   // definition for consistency between lazy and full parsing.
3065   pc_->sc()->setHasInnerFunctions();
3066 
3067   // When fully parsing a lazy script, we do not fully reparse its inner
3068   // functions, which are also lazy. Instead, their free variables and source
3069   // extents are recorded and may be skipped.
3070   if (handler_.reuseLazyInnerFunctions()) {
3071     if (!skipLazyInnerFunction(funNode, toStringStart, tryAnnexB)) {
3072       return null();
3073     }
3074 
3075     return funNode;
3076   }
3077 
3078   // Self-hosted functions with special function names require extended slots
3079   // for various purposes.
3080   bool isSelfHosting = options().selfHostingMode;
3081   bool forceExtended =
3082       isSelfHosting && funName &&
3083       this->parserAtoms().isExtendedUnclonedSelfHostedFunctionName(funName);
3084 
3085   FunctionFlags flags = InitialFunctionFlags(kind, generatorKind, asyncKind,
3086                                              isSelfHosting, forceExtended);
3087 
3088   // Speculatively parse using the directives of the parent parsing context.
3089   // If a directive is encountered (e.g., "use strict") that changes how the
3090   // function should have been parsed, we backup and reparse with the new set
3091   // of directives.
3092   Directives directives(pc_);
3093   Directives newDirectives = directives;
3094 
3095   Position start(tokenStream);
3096   auto startObj = this->compilationState_.getPosition();
3097 
3098   // Parse the inner function. The following is a loop as we may attempt to
3099   // reparse a function due to failed syntax parsing and encountering new
3100   // "use foo" directives.
3101   while (true) {
3102     if (trySyntaxParseInnerFunction(&funNode, funName, flags, toStringStart,
3103                                     inHandling, yieldHandling, kind,
3104                                     generatorKind, asyncKind, tryAnnexB,
3105                                     directives, &newDirectives)) {
3106       break;
3107     }
3108 
3109     // Return on error.
3110     if (anyChars.hadError() || directives == newDirectives) {
3111       return null();
3112     }
3113 
3114     // Assignment must be monotonic to prevent infinitely attempting to
3115     // reparse.
3116     MOZ_ASSERT_IF(directives.strict(), newDirectives.strict());
3117     MOZ_ASSERT_IF(directives.asmJS(), newDirectives.asmJS());
3118     directives = newDirectives;
3119 
3120     // Rewind to retry parsing with new directives applied.
3121     tokenStream.rewind(start);
3122     this->compilationState_.rewind(startObj);
3123 
3124     // functionFormalParametersAndBody may have already set body before
3125     // failing.
3126     handler_.setFunctionFormalParametersAndBody(funNode, null());
3127   }
3128 
3129   return funNode;
3130 }
3131 
3132 template <typename Unit>
advancePastSyntaxParsedFunction(SyntaxParser * syntaxParser)3133 bool Parser<FullParseHandler, Unit>::advancePastSyntaxParsedFunction(
3134     SyntaxParser* syntaxParser) {
3135   MOZ_ASSERT(getSyntaxParser() == syntaxParser);
3136 
3137   // Advance this parser over tokens processed by the syntax parser.
3138   Position currentSyntaxPosition(syntaxParser->tokenStream);
3139   if (!tokenStream.fastForward(currentSyntaxPosition, syntaxParser->anyChars)) {
3140     return false;
3141   }
3142 
3143   anyChars.adoptState(syntaxParser->anyChars);
3144   tokenStream.adoptState(syntaxParser->tokenStream);
3145   return true;
3146 }
3147 
3148 template <typename Unit>
trySyntaxParseInnerFunction(FunctionNode ** funNode,TaggedParserAtomIndex explicitName,FunctionFlags flags,uint32_t toStringStart,InHandling inHandling,YieldHandling yieldHandling,FunctionSyntaxKind kind,GeneratorKind generatorKind,FunctionAsyncKind asyncKind,bool tryAnnexB,Directives inheritedDirectives,Directives * newDirectives)3149 bool Parser<FullParseHandler, Unit>::trySyntaxParseInnerFunction(
3150     FunctionNode** funNode, TaggedParserAtomIndex explicitName,
3151     FunctionFlags flags, uint32_t toStringStart, InHandling inHandling,
3152     YieldHandling yieldHandling, FunctionSyntaxKind kind,
3153     GeneratorKind generatorKind, FunctionAsyncKind asyncKind, bool tryAnnexB,
3154     Directives inheritedDirectives, Directives* newDirectives) {
3155   // Try a syntax parse for this inner function.
3156   do {
3157     // If we're assuming this function is an IIFE, always perform a full
3158     // parse to avoid the overhead of a lazy syntax-only parse. Although
3159     // the prediction may be incorrect, IIFEs are common enough that it
3160     // pays off for lots of code.
3161     if ((*funNode)->isLikelyIIFE() &&
3162         generatorKind == GeneratorKind::NotGenerator &&
3163         asyncKind == FunctionAsyncKind::SyncFunction) {
3164       break;
3165     }
3166 
3167     SyntaxParser* syntaxParser = getSyntaxParser();
3168     if (!syntaxParser) {
3169       break;
3170     }
3171 
3172     UsedNameTracker::RewindToken token = usedNames_.getRewindToken();
3173     auto statePosition = this->compilationState_.getPosition();
3174 
3175     // Move the syntax parser to the current position in the stream.  In the
3176     // common case this seeks forward, but it'll also seek backward *at least*
3177     // when arrow functions appear inside arrow function argument defaults
3178     // (because we rewind to reparse arrow functions once we're certain they're
3179     // arrow functions):
3180     //
3181     //   var x = (y = z => 2) => q;
3182     //   //           ^ we first seek to here to syntax-parse this function
3183     //   //      ^ then we seek back to here to syntax-parse the outer function
3184     Position currentPosition(tokenStream);
3185     if (!syntaxParser->tokenStream.seekTo(currentPosition, anyChars)) {
3186       return false;
3187     }
3188 
3189     // Make a FunctionBox before we enter the syntax parser, because |pn|
3190     // still expects a FunctionBox to be attached to it during BCE, and
3191     // the syntax parser cannot attach one to it.
3192     FunctionBox* funbox =
3193         newFunctionBox(*funNode, explicitName, flags, toStringStart,
3194                        inheritedDirectives, generatorKind, asyncKind);
3195     if (!funbox) {
3196       return false;
3197     }
3198     funbox->initWithEnclosingParseContext(pc_, flags, kind);
3199 
3200     SyntaxParseHandler::Node syntaxNode =
3201         syntaxParser->innerFunctionForFunctionBox(
3202             SyntaxParseHandler::NodeGeneric, pc_, funbox, inHandling,
3203             yieldHandling, kind, newDirectives);
3204     if (!syntaxNode) {
3205       if (syntaxParser->hadAbortedSyntaxParse()) {
3206         // Try again with a full parse. UsedNameTracker needs to be
3207         // rewound to just before we tried the syntax parse for
3208         // correctness.
3209         syntaxParser->clearAbortedSyntaxParse();
3210         usedNames_.rewind(token);
3211         this->compilationState_.rewind(statePosition);
3212         MOZ_ASSERT_IF(!syntaxParser->cx_->isHelperThreadContext(),
3213                       !syntaxParser->cx_->isExceptionPending());
3214         break;
3215       }
3216       return false;
3217     }
3218 
3219     if (!advancePastSyntaxParsedFunction(syntaxParser)) {
3220       return false;
3221     }
3222 
3223     // Update the end position of the parse node.
3224     (*funNode)->pn_pos.end = anyChars.currentToken().pos.end;
3225 
3226     // Append possible Annex B function box only upon successfully parsing.
3227     if (tryAnnexB) {
3228       if (!pc_->innermostScope()->addPossibleAnnexBFunctionBox(pc_, funbox)) {
3229         return false;
3230       }
3231     }
3232 
3233     return true;
3234   } while (false);
3235 
3236   // We failed to do a syntax parse above, so do the full parse.
3237   FunctionNodeType innerFunc =
3238       innerFunction(*funNode, pc_, explicitName, flags, toStringStart,
3239                     inHandling, yieldHandling, kind, generatorKind, asyncKind,
3240                     tryAnnexB, inheritedDirectives, newDirectives);
3241   if (!innerFunc) {
3242     return false;
3243   }
3244 
3245   *funNode = innerFunc;
3246   return true;
3247 }
3248 
3249 template <typename Unit>
trySyntaxParseInnerFunction(FunctionNodeType * funNode,TaggedParserAtomIndex explicitName,FunctionFlags flags,uint32_t toStringStart,InHandling inHandling,YieldHandling yieldHandling,FunctionSyntaxKind kind,GeneratorKind generatorKind,FunctionAsyncKind asyncKind,bool tryAnnexB,Directives inheritedDirectives,Directives * newDirectives)3250 bool Parser<SyntaxParseHandler, Unit>::trySyntaxParseInnerFunction(
3251     FunctionNodeType* funNode, TaggedParserAtomIndex explicitName,
3252     FunctionFlags flags, uint32_t toStringStart, InHandling inHandling,
3253     YieldHandling yieldHandling, FunctionSyntaxKind kind,
3254     GeneratorKind generatorKind, FunctionAsyncKind asyncKind, bool tryAnnexB,
3255     Directives inheritedDirectives, Directives* newDirectives) {
3256   // This is already a syntax parser, so just parse the inner function.
3257   FunctionNodeType innerFunc =
3258       innerFunction(*funNode, pc_, explicitName, flags, toStringStart,
3259                     inHandling, yieldHandling, kind, generatorKind, asyncKind,
3260                     tryAnnexB, inheritedDirectives, newDirectives);
3261 
3262   if (!innerFunc) {
3263     return false;
3264   }
3265 
3266   *funNode = innerFunc;
3267   return true;
3268 }
3269 
3270 template <class ParseHandler, typename Unit>
trySyntaxParseInnerFunction(FunctionNodeType * funNode,TaggedParserAtomIndex explicitName,FunctionFlags flags,uint32_t toStringStart,InHandling inHandling,YieldHandling yieldHandling,FunctionSyntaxKind kind,GeneratorKind generatorKind,FunctionAsyncKind asyncKind,bool tryAnnexB,Directives inheritedDirectives,Directives * newDirectives)3271 inline bool GeneralParser<ParseHandler, Unit>::trySyntaxParseInnerFunction(
3272     FunctionNodeType* funNode, TaggedParserAtomIndex explicitName,
3273     FunctionFlags flags, uint32_t toStringStart, InHandling inHandling,
3274     YieldHandling yieldHandling, FunctionSyntaxKind kind,
3275     GeneratorKind generatorKind, FunctionAsyncKind asyncKind, bool tryAnnexB,
3276     Directives inheritedDirectives, Directives* newDirectives) {
3277   return asFinalParser()->trySyntaxParseInnerFunction(
3278       funNode, explicitName, flags, toStringStart, inHandling, yieldHandling,
3279       kind, generatorKind, asyncKind, tryAnnexB, inheritedDirectives,
3280       newDirectives);
3281 }
3282 
3283 template <class ParseHandler, typename Unit>
3284 typename ParseHandler::FunctionNodeType
innerFunctionForFunctionBox(FunctionNodeType funNode,ParseContext * outerpc,FunctionBox * funbox,InHandling inHandling,YieldHandling yieldHandling,FunctionSyntaxKind kind,Directives * newDirectives)3285 GeneralParser<ParseHandler, Unit>::innerFunctionForFunctionBox(
3286     FunctionNodeType funNode, ParseContext* outerpc, FunctionBox* funbox,
3287     InHandling inHandling, YieldHandling yieldHandling, FunctionSyntaxKind kind,
3288     Directives* newDirectives) {
3289   // Note that it is possible for outerpc != this->pc_, as we may be
3290   // attempting to syntax parse an inner function from an outer full
3291   // parser. In that case, outerpc is a SourceParseContext from the full parser
3292   // instead of the current top of the stack of the syntax parser.
3293 
3294   // Push a new ParseContext.
3295   SourceParseContext funpc(this, funbox, newDirectives);
3296   if (!funpc.init()) {
3297     return null();
3298   }
3299 
3300   if (!functionFormalParametersAndBody(inHandling, yieldHandling, &funNode,
3301                                        kind)) {
3302     return null();
3303   }
3304 
3305   if (!leaveInnerFunction(outerpc)) {
3306     return null();
3307   }
3308 
3309   return funNode;
3310 }
3311 
3312 template <class ParseHandler, typename Unit>
3313 typename ParseHandler::FunctionNodeType
innerFunction(FunctionNodeType funNode,ParseContext * outerpc,TaggedParserAtomIndex explicitName,FunctionFlags flags,uint32_t toStringStart,InHandling inHandling,YieldHandling yieldHandling,FunctionSyntaxKind kind,GeneratorKind generatorKind,FunctionAsyncKind asyncKind,bool tryAnnexB,Directives inheritedDirectives,Directives * newDirectives)3314 GeneralParser<ParseHandler, Unit>::innerFunction(
3315     FunctionNodeType funNode, ParseContext* outerpc,
3316     TaggedParserAtomIndex explicitName, FunctionFlags flags,
3317     uint32_t toStringStart, InHandling inHandling, YieldHandling yieldHandling,
3318     FunctionSyntaxKind kind, GeneratorKind generatorKind,
3319     FunctionAsyncKind asyncKind, bool tryAnnexB, Directives inheritedDirectives,
3320     Directives* newDirectives) {
3321   // Note that it is possible for outerpc != this->pc_, as we may be
3322   // attempting to syntax parse an inner function from an outer full
3323   // parser. In that case, outerpc is a SourceParseContext from the full parser
3324   // instead of the current top of the stack of the syntax parser.
3325 
3326   FunctionBox* funbox =
3327       newFunctionBox(funNode, explicitName, flags, toStringStart,
3328                      inheritedDirectives, generatorKind, asyncKind);
3329   if (!funbox) {
3330     return null();
3331   }
3332   funbox->initWithEnclosingParseContext(outerpc, flags, kind);
3333 
3334   FunctionNodeType innerFunc = innerFunctionForFunctionBox(
3335       funNode, outerpc, funbox, inHandling, yieldHandling, kind, newDirectives);
3336   if (!innerFunc) {
3337     return null();
3338   }
3339 
3340   // Append possible Annex B function box only upon successfully parsing.
3341   if (tryAnnexB) {
3342     if (!pc_->innermostScope()->addPossibleAnnexBFunctionBox(pc_, funbox)) {
3343       return null();
3344     }
3345   }
3346 
3347   return innerFunc;
3348 }
3349 
3350 template <class ParseHandler, typename Unit>
appendToCallSiteObj(CallSiteNodeType callSiteObj)3351 bool GeneralParser<ParseHandler, Unit>::appendToCallSiteObj(
3352     CallSiteNodeType callSiteObj) {
3353   Node cookedNode = noSubstitutionTaggedTemplate();
3354   if (!cookedNode) {
3355     return false;
3356   }
3357 
3358   auto atom = tokenStream.getRawTemplateStringAtom();
3359   if (!atom) {
3360     return false;
3361   }
3362   NameNodeType rawNode = handler_.newTemplateStringLiteral(atom, pos());
3363   if (!rawNode) {
3364     return false;
3365   }
3366 
3367   handler_.addToCallSiteObject(callSiteObj, rawNode, cookedNode);
3368   return true;
3369 }
3370 
3371 template <typename Unit>
standaloneLazyFunction(CompilationInput & input,uint32_t toStringStart,bool strict,GeneratorKind generatorKind,FunctionAsyncKind asyncKind)3372 FunctionNode* Parser<FullParseHandler, Unit>::standaloneLazyFunction(
3373     CompilationInput& input, uint32_t toStringStart, bool strict,
3374     GeneratorKind generatorKind, FunctionAsyncKind asyncKind) {
3375   MOZ_ASSERT(checkOptionsCalled_);
3376 
3377   FunctionSyntaxKind syntaxKind = input.functionSyntaxKind();
3378   FunctionNodeType funNode = handler_.newFunction(syntaxKind, pos());
3379   if (!funNode) {
3380     return null();
3381   }
3382 
3383   TaggedParserAtomIndex displayAtom =
3384       this->getCompilationState().previousParseCache.displayAtom();
3385 
3386   Directives directives(strict);
3387   FunctionBox* funbox =
3388       newFunctionBox(funNode, displayAtom, input.functionFlags(), toStringStart,
3389                      directives, generatorKind, asyncKind);
3390   if (!funbox) {
3391     return null();
3392   }
3393   const ScriptStencilExtra& funExtra =
3394       this->getCompilationState().previousParseCache.funExtra();
3395   funbox->initFromLazyFunction(funExtra,
3396                                this->getCompilationState().scopeContext,
3397                                input.functionFlags(), syntaxKind);
3398   if (funbox->useMemberInitializers()) {
3399     funbox->setMemberInitializers(funExtra.memberInitializers());
3400   }
3401 
3402   Directives newDirectives = directives;
3403   SourceParseContext funpc(this, funbox, &newDirectives);
3404   if (!funpc.init()) {
3405     return null();
3406   }
3407 
3408   // Our tokenStream has no current token, so funNode's position is garbage.
3409   // Substitute the position of the first token in our source.  If the
3410   // function is a not-async arrow, use TokenStream::SlashIsRegExp to keep
3411   // verifyConsistentModifier from complaining (we will use
3412   // TokenStream::SlashIsRegExp in functionArguments).
3413   Modifier modifier = (input.functionFlags().isArrow() &&
3414                        asyncKind == FunctionAsyncKind::SyncFunction)
3415                           ? TokenStream::SlashIsRegExp
3416                           : TokenStream::SlashIsDiv;
3417   if (!tokenStream.peekTokenPos(&funNode->pn_pos, modifier)) {
3418     return null();
3419   }
3420 
3421   YieldHandling yieldHandling = GetYieldHandling(generatorKind);
3422 
3423   if (funbox->isSyntheticFunction()) {
3424     // Currently default class constructors are the only synthetic function that
3425     // supports delazification.
3426     MOZ_ASSERT(funbox->isClassConstructor());
3427     MOZ_ASSERT(funbox->extent().toStringStart == funbox->extent().sourceStart);
3428 
3429     HasHeritage hasHeritage = funbox->isDerivedClassConstructor()
3430                                   ? HasHeritage::Yes
3431                                   : HasHeritage::No;
3432     TokenPos synthesizedBodyPos(funbox->extent().toStringStart,
3433                                 funbox->extent().toStringEnd);
3434 
3435     // Reset pos() to the `class` keyword for predictable results.
3436     tokenStream.consumeKnownToken(TokenKind::Class);
3437 
3438     if (!this->synthesizeConstructorBody(synthesizedBodyPos, hasHeritage,
3439                                          funNode, funbox)) {
3440       return null();
3441     }
3442   } else {
3443     if (!functionFormalParametersAndBody(InAllowed, yieldHandling, &funNode,
3444                                          syntaxKind)) {
3445       MOZ_ASSERT(directives == newDirectives);
3446       return null();
3447     }
3448   }
3449 
3450   if (!CheckParseTree(cx_, alloc_, funNode)) {
3451     return null();
3452   }
3453 
3454   ParseNode* node = funNode;
3455   // Don't constant-fold inside "use asm" code, as this could create a parse
3456   // tree that doesn't type-check as asm.js.
3457   if (!pc_->useAsmOrInsideUseAsm()) {
3458     if (!FoldConstants(cx_, this->parserAtoms(), &node, &handler_)) {
3459       return null();
3460     }
3461   }
3462   funNode = &node->as<FunctionNode>();
3463 
3464   return funNode;
3465 }
3466 
setFunctionEndFromCurrentToken(FunctionBox * funbox) const3467 void ParserBase::setFunctionEndFromCurrentToken(FunctionBox* funbox) const {
3468   if (compilationState_.isInitialStencil()) {
3469     MOZ_ASSERT(anyChars.currentToken().type != TokenKind::Eof);
3470     MOZ_ASSERT(anyChars.currentToken().type < TokenKind::Limit);
3471     funbox->setEnd(anyChars.currentToken().pos.end);
3472   } else {
3473     // If we're delazifying an arrow function with expression body and
3474     // the expression is also a function, we arrive here immediately after
3475     // skipping the function by Parser::skipLazyInnerFunction.
3476     //
3477     //   a => b => c
3478     //              ^
3479     //              |
3480     //              we're here
3481     //
3482     // In that case, the current token's type field is either Limit or
3483     // poisoned.
3484     // We shouldn't read the value if it's poisoned.
3485     // See TokenStreamSpecific<Unit, AnyCharsAccess>::advance and
3486     // mfbt/MemoryChecking.h for more details.
3487     //
3488     // Also, in delazification, the FunctionBox should already have the
3489     // correct extent, and we shouldn't overwrite it here.
3490     // See ScriptStencil variant of PerHandlerParser::newFunctionBox.
3491 #if !defined(MOZ_ASAN) && !defined(MOZ_MSAN) && !defined(MOZ_VALGRIND)
3492     MOZ_ASSERT(anyChars.currentToken().type != TokenKind::Eof);
3493 #endif
3494     MOZ_ASSERT(funbox->extent().sourceEnd == anyChars.currentToken().pos.end);
3495   }
3496 }
3497 
3498 template <class ParseHandler, typename Unit>
functionFormalParametersAndBody(InHandling inHandling,YieldHandling yieldHandling,FunctionNodeType * funNode,FunctionSyntaxKind kind,const Maybe<uint32_t> & parameterListEnd,bool isStandaloneFunction)3499 bool GeneralParser<ParseHandler, Unit>::functionFormalParametersAndBody(
3500     InHandling inHandling, YieldHandling yieldHandling,
3501     FunctionNodeType* funNode, FunctionSyntaxKind kind,
3502     const Maybe<uint32_t>& parameterListEnd /* = Nothing() */,
3503     bool isStandaloneFunction /* = false */) {
3504   // Given a properly initialized parse context, try to parse an actual
3505   // function without concern for conversion to strict mode, use of lazy
3506   // parsing and such.
3507 
3508   FunctionBox* funbox = pc_->functionBox();
3509 
3510   if (kind == FunctionSyntaxKind::ClassConstructor ||
3511       kind == FunctionSyntaxKind::DerivedClassConstructor) {
3512     if (!noteUsedName(TaggedParserAtomIndex::WellKnown::dotInitializers())) {
3513       return false;
3514     }
3515   }
3516 
3517   // See below for an explanation why arrow function parameters and arrow
3518   // function bodies are parsed with different yield/await settings.
3519   {
3520     AwaitHandling awaitHandling =
3521         kind == FunctionSyntaxKind::StaticClassBlock ? AwaitIsDisallowed
3522         : (funbox->isAsync() ||
3523            (kind == FunctionSyntaxKind::Arrow && awaitIsKeyword()))
3524             ? AwaitIsKeyword
3525             : AwaitIsName;
3526     AutoAwaitIsKeyword<ParseHandler, Unit> awaitIsKeyword(this, awaitHandling);
3527     AutoInParametersOfAsyncFunction<ParseHandler, Unit> inParameters(
3528         this, funbox->isAsync());
3529     if (!functionArguments(yieldHandling, kind, *funNode)) {
3530       return false;
3531     }
3532   }
3533 
3534   Maybe<ParseContext::VarScope> varScope;
3535   if (funbox->hasParameterExprs) {
3536     varScope.emplace(this);
3537     if (!varScope->init(pc_)) {
3538       return false;
3539     }
3540   } else {
3541     pc_->functionScope().useAsVarScope(pc_);
3542   }
3543 
3544   if (kind == FunctionSyntaxKind::Arrow) {
3545     TokenKind tt;
3546     if (!tokenStream.peekTokenSameLine(&tt)) {
3547       return false;
3548     }
3549 
3550     if (tt == TokenKind::Eol) {
3551       error(JSMSG_UNEXPECTED_TOKEN,
3552             "'=>' on the same line after an argument list",
3553             TokenKindToDesc(tt));
3554       return false;
3555     }
3556     if (tt != TokenKind::Arrow) {
3557       error(JSMSG_BAD_ARROW_ARGS);
3558       return false;
3559     }
3560     tokenStream.consumeKnownToken(TokenKind::Arrow);
3561   }
3562 
3563   // When parsing something for new Function() we have to make sure to
3564   // only treat a certain part of the source as a parameter list.
3565   if (parameterListEnd.isSome() && parameterListEnd.value() != pos().begin) {
3566     error(JSMSG_UNEXPECTED_PARAMLIST_END);
3567     return false;
3568   }
3569 
3570   // Parse the function body.
3571   FunctionBodyType bodyType = StatementListBody;
3572   TokenKind tt;
3573   if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) {
3574     return false;
3575   }
3576   uint32_t openedPos = 0;
3577   if (tt != TokenKind::LeftCurly) {
3578     if (kind != FunctionSyntaxKind::Arrow) {
3579       error(JSMSG_CURLY_BEFORE_BODY);
3580       return false;
3581     }
3582 
3583     anyChars.ungetToken();
3584     bodyType = ExpressionBody;
3585     funbox->setHasExprBody();
3586   } else {
3587     openedPos = pos().begin;
3588   }
3589 
3590   // Arrow function parameters inherit yieldHandling from the enclosing
3591   // context, but the arrow body doesn't. E.g. in |(a = yield) => yield|,
3592   // |yield| in the parameters is either a name or keyword, depending on
3593   // whether the arrow function is enclosed in a generator function or not.
3594   // Whereas the |yield| in the function body is always parsed as a name.
3595   // The same goes when parsing |await| in arrow functions.
3596   YieldHandling bodyYieldHandling = GetYieldHandling(pc_->generatorKind());
3597   AwaitHandling bodyAwaitHandling = GetAwaitHandling(pc_->asyncKind());
3598   bool inheritedStrict = pc_->sc()->strict();
3599   LexicalScopeNodeType body;
3600   {
3601     AutoAwaitIsKeyword<ParseHandler, Unit> awaitIsKeyword(this,
3602                                                           bodyAwaitHandling);
3603     AutoInParametersOfAsyncFunction<ParseHandler, Unit> inParameters(this,
3604                                                                      false);
3605     body = functionBody(inHandling, bodyYieldHandling, kind, bodyType);
3606     if (!body) {
3607       return false;
3608     }
3609   }
3610 
3611   // Revalidate the function name when we transitioned to strict mode.
3612   if ((kind == FunctionSyntaxKind::Statement ||
3613        kind == FunctionSyntaxKind::Expression) &&
3614       funbox->explicitName() && !inheritedStrict && pc_->sc()->strict()) {
3615     MOZ_ASSERT(pc_->sc()->hasExplicitUseStrict(),
3616                "strict mode should only change when a 'use strict' directive "
3617                "is present");
3618 
3619     auto propertyName = funbox->explicitName();
3620     YieldHandling nameYieldHandling;
3621     if (kind == FunctionSyntaxKind::Expression) {
3622       // Named lambda has binding inside it.
3623       nameYieldHandling = bodyYieldHandling;
3624     } else {
3625       // Otherwise YieldHandling cannot be checked at this point
3626       // because of different context.
3627       // It should already be checked before this point.
3628       nameYieldHandling = YieldIsName;
3629     }
3630 
3631     // We already use the correct await-handling at this point, therefore
3632     // we don't need call AutoAwaitIsKeyword here.
3633 
3634     uint32_t nameOffset = handler_.getFunctionNameOffset(*funNode, anyChars);
3635     if (!checkBindingIdentifier(propertyName, nameOffset, nameYieldHandling)) {
3636       return false;
3637     }
3638   }
3639 
3640   if (bodyType == StatementListBody) {
3641     // Cannot use mustMatchToken here because of internal compiler error on
3642     // gcc 6.4.0, with linux 64 SM hazard build.
3643     TokenKind actual;
3644     if (!tokenStream.getToken(&actual, TokenStream::SlashIsRegExp)) {
3645       return false;
3646     }
3647     if (actual != TokenKind::RightCurly) {
3648       reportMissingClosing(JSMSG_CURLY_AFTER_BODY, JSMSG_CURLY_OPENED,
3649                            openedPos);
3650       return false;
3651     }
3652 
3653     setFunctionEndFromCurrentToken(funbox);
3654   } else {
3655     MOZ_ASSERT(kind == FunctionSyntaxKind::Arrow);
3656 
3657     if (anyChars.hadError()) {
3658       return false;
3659     }
3660 
3661     setFunctionEndFromCurrentToken(funbox);
3662 
3663     if (kind == FunctionSyntaxKind::Statement) {
3664       if (!matchOrInsertSemicolon()) {
3665         return false;
3666       }
3667     }
3668   }
3669 
3670   if (IsMethodDefinitionKind(kind) && pc_->superScopeNeedsHomeObject()) {
3671     funbox->setNeedsHomeObject();
3672   }
3673 
3674   if (!finishFunction(isStandaloneFunction)) {
3675     return false;
3676   }
3677 
3678   handler_.setEndPosition(body, pos().begin);
3679   handler_.setEndPosition(*funNode, pos().end);
3680   handler_.setFunctionBody(*funNode, body);
3681 
3682   return true;
3683 }
3684 
3685 template <class ParseHandler, typename Unit>
3686 typename ParseHandler::FunctionNodeType
functionStmt(uint32_t toStringStart,YieldHandling yieldHandling,DefaultHandling defaultHandling,FunctionAsyncKind asyncKind)3687 GeneralParser<ParseHandler, Unit>::functionStmt(uint32_t toStringStart,
3688                                                 YieldHandling yieldHandling,
3689                                                 DefaultHandling defaultHandling,
3690                                                 FunctionAsyncKind asyncKind) {
3691   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Function));
3692 
3693   // In sloppy mode, Annex B.3.2 allows labelled function declarations.
3694   // Otherwise it's a parse error.
3695   ParseContext::Statement* declaredInStmt = pc_->innermostStatement();
3696   if (declaredInStmt && declaredInStmt->kind() == StatementKind::Label) {
3697     MOZ_ASSERT(!pc_->sc()->strict(),
3698                "labeled functions shouldn't be parsed in strict mode");
3699 
3700     // Find the innermost non-label statement.  Report an error if it's
3701     // unbraced: functions can't appear in it.  Otherwise the statement
3702     // (or its absence) determines the scope the function's bound in.
3703     while (declaredInStmt && declaredInStmt->kind() == StatementKind::Label) {
3704       declaredInStmt = declaredInStmt->enclosing();
3705     }
3706 
3707     if (declaredInStmt && !StatementKindIsBraced(declaredInStmt->kind())) {
3708       error(JSMSG_SLOPPY_FUNCTION_LABEL);
3709       return null();
3710     }
3711   }
3712 
3713   TokenKind tt;
3714   if (!tokenStream.getToken(&tt)) {
3715     return null();
3716   }
3717 
3718   GeneratorKind generatorKind = GeneratorKind::NotGenerator;
3719   if (tt == TokenKind::Mul) {
3720     generatorKind = GeneratorKind::Generator;
3721     if (!tokenStream.getToken(&tt)) {
3722       return null();
3723     }
3724   }
3725 
3726   TaggedParserAtomIndex name;
3727   if (TokenKindIsPossibleIdentifier(tt)) {
3728     name = bindingIdentifier(yieldHandling);
3729     if (!name) {
3730       return null();
3731     }
3732   } else if (defaultHandling == AllowDefaultName) {
3733     name = TaggedParserAtomIndex::WellKnown::default_();
3734     anyChars.ungetToken();
3735   } else {
3736     /* Unnamed function expressions are forbidden in statement context. */
3737     error(JSMSG_UNNAMED_FUNCTION_STMT);
3738     return null();
3739   }
3740 
3741   // Note the declared name and check for early errors.
3742   DeclarationKind kind;
3743   if (declaredInStmt) {
3744     MOZ_ASSERT(declaredInStmt->kind() != StatementKind::Label);
3745     MOZ_ASSERT(StatementKindIsBraced(declaredInStmt->kind()));
3746 
3747     kind =
3748         (!pc_->sc()->strict() && generatorKind == GeneratorKind::NotGenerator &&
3749          asyncKind == FunctionAsyncKind::SyncFunction)
3750             ? DeclarationKind::SloppyLexicalFunction
3751             : DeclarationKind::LexicalFunction;
3752   } else {
3753     kind = pc_->atModuleLevel() ? DeclarationKind::ModuleBodyLevelFunction
3754                                 : DeclarationKind::BodyLevelFunction;
3755   }
3756 
3757   if (!noteDeclaredName(name, kind, pos())) {
3758     return null();
3759   }
3760 
3761   FunctionSyntaxKind syntaxKind = FunctionSyntaxKind::Statement;
3762   FunctionNodeType funNode = handler_.newFunction(syntaxKind, pos());
3763   if (!funNode) {
3764     return null();
3765   }
3766 
3767   // Under sloppy mode, try Annex B.3.3 semantics. If making an additional
3768   // 'var' binding of the same name does not throw an early error, do so.
3769   // This 'var' binding would be assigned the function object when its
3770   // declaration is reached, not at the start of the block.
3771   //
3772   // This semantics is implemented upon Scope exit in
3773   // Scope::propagateAndMarkAnnexBFunctionBoxes.
3774   bool tryAnnexB = kind == DeclarationKind::SloppyLexicalFunction;
3775 
3776   YieldHandling newYieldHandling = GetYieldHandling(generatorKind);
3777   return functionDefinition(funNode, toStringStart, InAllowed, newYieldHandling,
3778                             name, syntaxKind, generatorKind, asyncKind,
3779                             tryAnnexB);
3780 }
3781 
3782 template <class ParseHandler, typename Unit>
3783 typename ParseHandler::FunctionNodeType
functionExpr(uint32_t toStringStart,InvokedPrediction invoked,FunctionAsyncKind asyncKind)3784 GeneralParser<ParseHandler, Unit>::functionExpr(uint32_t toStringStart,
3785                                                 InvokedPrediction invoked,
3786                                                 FunctionAsyncKind asyncKind) {
3787   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Function));
3788 
3789   AutoAwaitIsKeyword<ParseHandler, Unit> awaitIsKeyword(
3790       this, GetAwaitHandling(asyncKind));
3791   GeneratorKind generatorKind = GeneratorKind::NotGenerator;
3792   TokenKind tt;
3793   if (!tokenStream.getToken(&tt)) {
3794     return null();
3795   }
3796 
3797   if (tt == TokenKind::Mul) {
3798     generatorKind = GeneratorKind::Generator;
3799     if (!tokenStream.getToken(&tt)) {
3800       return null();
3801     }
3802   }
3803 
3804   YieldHandling yieldHandling = GetYieldHandling(generatorKind);
3805 
3806   TaggedParserAtomIndex name;
3807   if (TokenKindIsPossibleIdentifier(tt)) {
3808     name = bindingIdentifier(yieldHandling);
3809     if (!name) {
3810       return null();
3811     }
3812   } else {
3813     anyChars.ungetToken();
3814   }
3815 
3816   FunctionSyntaxKind syntaxKind = FunctionSyntaxKind::Expression;
3817   FunctionNodeType funNode = handler_.newFunction(syntaxKind, pos());
3818   if (!funNode) {
3819     return null();
3820   }
3821 
3822   if (invoked) {
3823     funNode = handler_.setLikelyIIFE(funNode);
3824   }
3825 
3826   return functionDefinition(funNode, toStringStart, InAllowed, yieldHandling,
3827                             name, syntaxKind, generatorKind, asyncKind);
3828 }
3829 
3830 /*
3831  * Return true if this node, known to be an unparenthesized string literal
3832  * that never contain escape sequences, could be the string of a directive in a
3833  * Directive Prologue. Directive strings never contain escape sequences or line
3834  * continuations.
3835  */
IsUseStrictDirective(const TokenPos & pos,TaggedParserAtomIndex atom)3836 static inline bool IsUseStrictDirective(const TokenPos& pos,
3837                                         TaggedParserAtomIndex atom) {
3838   // the length of "use strict", including quotation.
3839   static constexpr size_t useStrictLength = 12;
3840   return atom == TaggedParserAtomIndex::WellKnown::useStrict() &&
3841          pos.begin + useStrictLength == pos.end;
3842 }
IsUseAsmDirective(const TokenPos & pos,TaggedParserAtomIndex atom)3843 static inline bool IsUseAsmDirective(const TokenPos& pos,
3844                                      TaggedParserAtomIndex atom) {
3845   // the length of "use asm", including quotation.
3846   static constexpr size_t useAsmLength = 9;
3847   return atom == TaggedParserAtomIndex::WellKnown::useAsm() &&
3848          pos.begin + useAsmLength == pos.end;
3849 }
3850 
3851 template <typename Unit>
asmJS(ListNodeType list)3852 bool Parser<SyntaxParseHandler, Unit>::asmJS(ListNodeType list) {
3853   // While asm.js could technically be validated and compiled during syntax
3854   // parsing, we have no guarantee that some later JS wouldn't abort the
3855   // syntax parse and cause us to re-parse (and re-compile) the asm.js module.
3856   // For simplicity, unconditionally abort the syntax parse when "use asm" is
3857   // encountered so that asm.js is always validated/compiled exactly once
3858   // during a full parse.
3859   MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
3860   return false;
3861 }
3862 
3863 template <typename Unit>
asmJS(ListNodeType list)3864 bool Parser<FullParseHandler, Unit>::asmJS(ListNodeType list) {
3865   // Disable syntax parsing in anything nested inside the asm.js module.
3866   disableSyntaxParser();
3867 
3868   // We should be encountering the "use asm" directive for the first time; if
3869   // the directive is already, we must have failed asm.js validation and we're
3870   // reparsing. In that case, don't try to validate again. A non-null
3871   // newDirectives means we're not in a normal function.
3872   if (!pc_->newDirectives || pc_->newDirectives->asmJS()) {
3873     return true;
3874   }
3875 
3876   // If there is no ScriptSource, then we are doing a non-compiling parse and
3877   // so we shouldn't (and can't, without a ScriptSource) compile.
3878   if (ss == nullptr) {
3879     return true;
3880   }
3881 
3882   pc_->functionBox()->useAsm = true;
3883 
3884   // Attempt to validate and compile this asm.js module. On success, the
3885   // tokenStream has been advanced to the closing }. On failure, the
3886   // tokenStream is in an indeterminate state and we must reparse the
3887   // function from the beginning. Reparsing is triggered by marking that a
3888   // new directive has been encountered and returning 'false'.
3889   bool validated;
3890   if (!CompileAsmJS(cx_, this->parserAtoms(), *this, list, &validated)) {
3891     return false;
3892   }
3893   if (!validated) {
3894     pc_->newDirectives->setAsmJS();
3895     return false;
3896   }
3897 
3898   return true;
3899 }
3900 
3901 template <class ParseHandler, typename Unit>
asmJS(ListNodeType list)3902 inline bool GeneralParser<ParseHandler, Unit>::asmJS(ListNodeType list) {
3903   return asFinalParser()->asmJS(list);
3904 }
3905 
3906 /*
3907  * Recognize Directive Prologue members and directives. Assuming |pn| is a
3908  * candidate for membership in a directive prologue, recognize directives and
3909  * set |pc_|'s flags accordingly. If |pn| is indeed part of a prologue, set its
3910  * |prologue| flag.
3911  *
3912  * Note that the following is a strict mode function:
3913  *
3914  * function foo() {
3915  *   "blah" // inserted semi colon
3916  *        "blurgh"
3917  *   "use\x20loose"
3918  *   "use strict"
3919  * }
3920  *
3921  * That is, even though "use\x20loose" can never be a directive, now or in the
3922  * future (because of the hex escape), the Directive Prologue extends through it
3923  * to the "use strict" statement, which is indeed a directive.
3924  */
3925 template <class ParseHandler, typename Unit>
maybeParseDirective(ListNodeType list,Node possibleDirective,bool * cont)3926 bool GeneralParser<ParseHandler, Unit>::maybeParseDirective(
3927     ListNodeType list, Node possibleDirective, bool* cont) {
3928   TokenPos directivePos;
3929   TaggedParserAtomIndex directive =
3930       handler_.isStringExprStatement(possibleDirective, &directivePos);
3931 
3932   *cont = !!directive;
3933   if (!*cont) {
3934     return true;
3935   }
3936 
3937   if (IsUseStrictDirective(directivePos, directive)) {
3938     // Functions with non-simple parameter lists (destructuring,
3939     // default or rest parameters) must not contain a "use strict"
3940     // directive.
3941     if (pc_->isFunctionBox()) {
3942       FunctionBox* funbox = pc_->functionBox();
3943       if (!funbox->hasSimpleParameterList()) {
3944         const char* parameterKind = funbox->hasDestructuringArgs
3945                                         ? "destructuring"
3946                                     : funbox->hasParameterExprs ? "default"
3947                                                                 : "rest";
3948         errorAt(directivePos.begin, JSMSG_STRICT_NON_SIMPLE_PARAMS,
3949                 parameterKind);
3950         return false;
3951       }
3952     }
3953 
3954     // We're going to be in strict mode. Note that this scope explicitly
3955     // had "use strict";
3956     pc_->sc()->setExplicitUseStrict();
3957     if (!pc_->sc()->strict()) {
3958       // Some strict mode violations can appear before a Use Strict Directive
3959       // is applied.  (See the |DeprecatedContent| enum initializers.)  These
3960       // violations can manifest in two ways.
3961       //
3962       // First, the violation can appear *before* the Use Strict Directive.
3963       // Numeric literals (and therefore octal literals) can only precede a
3964       // Use Strict Directive if this function's parameter list is not simple,
3965       // but we reported an error for non-simple parameter lists above, so
3966       // octal literals present no issue.  But octal escapes and \8 and \9 can
3967       // appear in the directive prologue before a Use Strict Directive:
3968       //
3969       //   function f()
3970       //   {
3971       //     "hell\157 world";  // octal escape
3972       //     "\8"; "\9";        // NonOctalDecimalEscape
3973       //     "use strict";      // retroactively makes all the above errors
3974       //   }
3975       //
3976       // Second, the violation can appear *after* the Use Strict Directive but
3977       // *before* the directive is recognized as terminated.  This only
3978       // happens when a directive is terminated by ASI, and the next token
3979       // contains a violation:
3980       //
3981       //   function a()
3982       //   {
3983       //     "use strict"  // ASI
3984       //     0755;
3985       //   }
3986       //   function b()
3987       //   {
3988       //     "use strict"  // ASI
3989       //     "hell\157 world";
3990       //   }
3991       //   function c()
3992       //   {
3993       //     "use strict"  // ASI
3994       //     "\8";
3995       //   }
3996       //
3997       // We note such violations when tokenizing.  Then, if a violation has
3998       // been observed at the time a "use strict" is applied, we report the
3999       // error.
4000       switch (anyChars.sawDeprecatedContent()) {
4001         case DeprecatedContent::None:
4002           break;
4003         case DeprecatedContent::OctalLiteral:
4004           error(JSMSG_DEPRECATED_OCTAL_LITERAL);
4005           return false;
4006         case DeprecatedContent::OctalEscape:
4007           error(JSMSG_DEPRECATED_OCTAL_ESCAPE);
4008           return false;
4009         case DeprecatedContent::EightOrNineEscape:
4010           error(JSMSG_DEPRECATED_EIGHT_OR_NINE_ESCAPE);
4011           return false;
4012       }
4013 
4014       pc_->sc()->setStrictScript();
4015     }
4016   } else if (IsUseAsmDirective(directivePos, directive)) {
4017     if (pc_->isFunctionBox()) {
4018       return asmJS(list);
4019     }
4020     return warningAt(directivePos.begin, JSMSG_USE_ASM_DIRECTIVE_FAIL);
4021   }
4022   return true;
4023 }
4024 
4025 template <class ParseHandler, typename Unit>
4026 typename ParseHandler::ListNodeType
statementList(YieldHandling yieldHandling)4027 GeneralParser<ParseHandler, Unit>::statementList(YieldHandling yieldHandling) {
4028   AutoCheckRecursionLimit recursion(cx_);
4029   if (!recursion.check(cx_)) {
4030     return null();
4031   }
4032 
4033   ListNodeType stmtList = handler_.newStatementList(pos());
4034   if (!stmtList) {
4035     return null();
4036   }
4037 
4038   bool canHaveDirectives = pc_->atBodyLevel();
4039   if (canHaveDirectives) {
4040     // Clear flags for deprecated content that might have been seen in an
4041     // enclosing context.
4042     anyChars.clearSawDeprecatedContent();
4043   }
4044 
4045   bool canHaveHashbangComment = pc_->atTopLevel();
4046   if (canHaveHashbangComment) {
4047     tokenStream.consumeOptionalHashbangComment();
4048   }
4049 
4050   bool afterReturn = false;
4051   bool warnedAboutStatementsAfterReturn = false;
4052   uint32_t statementBegin = 0;
4053   for (;;) {
4054     TokenKind tt = TokenKind::Eof;
4055     if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) {
4056       if (anyChars.isEOF()) {
4057         isUnexpectedEOF_ = true;
4058       }
4059       return null();
4060     }
4061     if (tt == TokenKind::Eof || tt == TokenKind::RightCurly) {
4062       TokenPos pos;
4063       if (!tokenStream.peekTokenPos(&pos, TokenStream::SlashIsRegExp)) {
4064         return null();
4065       }
4066       handler_.setListEndPosition(stmtList, pos);
4067       break;
4068     }
4069     if (afterReturn) {
4070       if (!tokenStream.peekOffset(&statementBegin,
4071                                   TokenStream::SlashIsRegExp)) {
4072         return null();
4073       }
4074     }
4075     Node next = statementListItem(yieldHandling, canHaveDirectives);
4076     if (!next) {
4077       if (anyChars.isEOF()) {
4078         isUnexpectedEOF_ = true;
4079       }
4080       return null();
4081     }
4082     if (!warnedAboutStatementsAfterReturn) {
4083       if (afterReturn) {
4084         if (!handler_.isStatementPermittedAfterReturnStatement(next)) {
4085           if (!warningAt(statementBegin, JSMSG_STMT_AFTER_RETURN)) {
4086             return null();
4087           }
4088 
4089           warnedAboutStatementsAfterReturn = true;
4090         }
4091       } else if (handler_.isReturnStatement(next)) {
4092         afterReturn = true;
4093       }
4094     }
4095 
4096     if (canHaveDirectives) {
4097       if (!maybeParseDirective(stmtList, next, &canHaveDirectives)) {
4098         return null();
4099       }
4100     }
4101 
4102     handler_.addStatementToList(stmtList, next);
4103   }
4104 
4105   return stmtList;
4106 }
4107 
4108 template <class ParseHandler, typename Unit>
condition(InHandling inHandling,YieldHandling yieldHandling)4109 typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::condition(
4110     InHandling inHandling, YieldHandling yieldHandling) {
4111   if (!mustMatchToken(TokenKind::LeftParen, JSMSG_PAREN_BEFORE_COND)) {
4112     return null();
4113   }
4114 
4115   Node pn = exprInParens(inHandling, yieldHandling, TripledotProhibited);
4116   if (!pn) {
4117     return null();
4118   }
4119 
4120   if (!mustMatchToken(TokenKind::RightParen, JSMSG_PAREN_AFTER_COND)) {
4121     return null();
4122   }
4123 
4124   return pn;
4125 }
4126 
4127 template <class ParseHandler, typename Unit>
matchLabel(YieldHandling yieldHandling,TaggedParserAtomIndex * labelOut)4128 bool GeneralParser<ParseHandler, Unit>::matchLabel(
4129     YieldHandling yieldHandling, TaggedParserAtomIndex* labelOut) {
4130   MOZ_ASSERT(labelOut != nullptr);
4131   TokenKind tt = TokenKind::Eof;
4132   if (!tokenStream.peekTokenSameLine(&tt, TokenStream::SlashIsRegExp)) {
4133     return false;
4134   }
4135 
4136   if (TokenKindIsPossibleIdentifier(tt)) {
4137     tokenStream.consumeKnownToken(tt, TokenStream::SlashIsRegExp);
4138 
4139     *labelOut = labelIdentifier(yieldHandling);
4140     if (!*labelOut) {
4141       return false;
4142     }
4143   } else {
4144     *labelOut = TaggedParserAtomIndex::null();
4145   }
4146   return true;
4147 }
4148 
4149 template <class ParseHandler, typename Unit>
PossibleError(GeneralParser<ParseHandler,Unit> & parser)4150 GeneralParser<ParseHandler, Unit>::PossibleError::PossibleError(
4151     GeneralParser<ParseHandler, Unit>& parser)
4152     : parser_(parser) {}
4153 
4154 template <class ParseHandler, typename Unit>
4155 typename GeneralParser<ParseHandler, Unit>::PossibleError::Error&
error(ErrorKind kind)4156 GeneralParser<ParseHandler, Unit>::PossibleError::error(ErrorKind kind) {
4157   if (kind == ErrorKind::Expression) {
4158     return exprError_;
4159   }
4160   if (kind == ErrorKind::Destructuring) {
4161     return destructuringError_;
4162   }
4163   MOZ_ASSERT(kind == ErrorKind::DestructuringWarning);
4164   return destructuringWarning_;
4165 }
4166 
4167 template <class ParseHandler, typename Unit>
setResolved(ErrorKind kind)4168 void GeneralParser<ParseHandler, Unit>::PossibleError::setResolved(
4169     ErrorKind kind) {
4170   error(kind).state_ = ErrorState::None;
4171 }
4172 
4173 template <class ParseHandler, typename Unit>
hasError(ErrorKind kind)4174 bool GeneralParser<ParseHandler, Unit>::PossibleError::hasError(
4175     ErrorKind kind) {
4176   return error(kind).state_ == ErrorState::Pending;
4177 }
4178 
4179 template <class ParseHandler, typename Unit>
4180 bool GeneralParser<ParseHandler,
hasPendingDestructuringError()4181                    Unit>::PossibleError::hasPendingDestructuringError() {
4182   return hasError(ErrorKind::Destructuring);
4183 }
4184 
4185 template <class ParseHandler, typename Unit>
setPending(ErrorKind kind,const TokenPos & pos,unsigned errorNumber)4186 void GeneralParser<ParseHandler, Unit>::PossibleError::setPending(
4187     ErrorKind kind, const TokenPos& pos, unsigned errorNumber) {
4188   // Don't overwrite a previously recorded error.
4189   if (hasError(kind)) {
4190     return;
4191   }
4192 
4193   // If we report an error later, we'll do it from the position where we set
4194   // the state to pending.
4195   Error& err = error(kind);
4196   err.offset_ = pos.begin;
4197   err.errorNumber_ = errorNumber;
4198   err.state_ = ErrorState::Pending;
4199 }
4200 
4201 template <class ParseHandler, typename Unit>
4202 void GeneralParser<ParseHandler, Unit>::PossibleError::
setPendingDestructuringErrorAt(const TokenPos & pos,unsigned errorNumber)4203     setPendingDestructuringErrorAt(const TokenPos& pos, unsigned errorNumber) {
4204   setPending(ErrorKind::Destructuring, pos, errorNumber);
4205 }
4206 
4207 template <class ParseHandler, typename Unit>
4208 void GeneralParser<ParseHandler, Unit>::PossibleError::
setPendingDestructuringWarningAt(const TokenPos & pos,unsigned errorNumber)4209     setPendingDestructuringWarningAt(const TokenPos& pos,
4210                                      unsigned errorNumber) {
4211   setPending(ErrorKind::DestructuringWarning, pos, errorNumber);
4212 }
4213 
4214 template <class ParseHandler, typename Unit>
4215 void GeneralParser<ParseHandler, Unit>::PossibleError::
setPendingExpressionErrorAt(const TokenPos & pos,unsigned errorNumber)4216     setPendingExpressionErrorAt(const TokenPos& pos, unsigned errorNumber) {
4217   setPending(ErrorKind::Expression, pos, errorNumber);
4218 }
4219 
4220 template <class ParseHandler, typename Unit>
checkForError(ErrorKind kind)4221 bool GeneralParser<ParseHandler, Unit>::PossibleError::checkForError(
4222     ErrorKind kind) {
4223   if (!hasError(kind)) {
4224     return true;
4225   }
4226 
4227   Error& err = error(kind);
4228   parser_.errorAt(err.offset_, err.errorNumber_);
4229   return false;
4230 }
4231 
4232 template <class ParseHandler, typename Unit>
4233 bool GeneralParser<ParseHandler,
checkForDestructuringErrorOrWarning()4234                    Unit>::PossibleError::checkForDestructuringErrorOrWarning() {
4235   // Clear pending expression error, because we're definitely not in an
4236   // expression context.
4237   setResolved(ErrorKind::Expression);
4238 
4239   // Report any pending destructuring error.
4240   return checkForError(ErrorKind::Destructuring);
4241 }
4242 
4243 template <class ParseHandler, typename Unit>
4244 bool GeneralParser<ParseHandler,
checkForExpressionError()4245                    Unit>::PossibleError::checkForExpressionError() {
4246   // Clear pending destructuring error, because we're definitely not
4247   // in a destructuring context.
4248   setResolved(ErrorKind::Destructuring);
4249   setResolved(ErrorKind::DestructuringWarning);
4250 
4251   // Report any pending expression error.
4252   return checkForError(ErrorKind::Expression);
4253 }
4254 
4255 template <class ParseHandler, typename Unit>
transferErrorTo(ErrorKind kind,PossibleError * other)4256 void GeneralParser<ParseHandler, Unit>::PossibleError::transferErrorTo(
4257     ErrorKind kind, PossibleError* other) {
4258   if (hasError(kind) && !other->hasError(kind)) {
4259     Error& err = error(kind);
4260     Error& otherErr = other->error(kind);
4261     otherErr.offset_ = err.offset_;
4262     otherErr.errorNumber_ = err.errorNumber_;
4263     otherErr.state_ = err.state_;
4264   }
4265 }
4266 
4267 template <class ParseHandler, typename Unit>
transferErrorsTo(PossibleError * other)4268 void GeneralParser<ParseHandler, Unit>::PossibleError::transferErrorsTo(
4269     PossibleError* other) {
4270   MOZ_ASSERT(other);
4271   MOZ_ASSERT(this != other);
4272   MOZ_ASSERT(&parser_ == &other->parser_,
4273              "Can't transfer fields to an instance which belongs to a "
4274              "different parser");
4275 
4276   transferErrorTo(ErrorKind::Destructuring, other);
4277   transferErrorTo(ErrorKind::Expression, other);
4278 }
4279 
4280 template <class ParseHandler, typename Unit>
4281 typename ParseHandler::BinaryNodeType
bindingInitializer(Node lhs,DeclarationKind kind,YieldHandling yieldHandling)4282 GeneralParser<ParseHandler, Unit>::bindingInitializer(
4283     Node lhs, DeclarationKind kind, YieldHandling yieldHandling) {
4284   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Assign));
4285 
4286   if (kind == DeclarationKind::FormalParameter) {
4287     pc_->functionBox()->hasParameterExprs = true;
4288   }
4289 
4290   Node rhs = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
4291   if (!rhs) {
4292     return null();
4293   }
4294 
4295   BinaryNodeType assign =
4296       handler_.newAssignment(ParseNodeKind::AssignExpr, lhs, rhs);
4297   if (!assign) {
4298     return null();
4299   }
4300 
4301   return assign;
4302 }
4303 
4304 template <class ParseHandler, typename Unit>
4305 typename ParseHandler::NameNodeType
bindingIdentifier(DeclarationKind kind,YieldHandling yieldHandling)4306 GeneralParser<ParseHandler, Unit>::bindingIdentifier(
4307     DeclarationKind kind, YieldHandling yieldHandling) {
4308   TaggedParserAtomIndex name = bindingIdentifier(yieldHandling);
4309   if (!name) {
4310     return null();
4311   }
4312 
4313   NameNodeType binding = newName(name);
4314   if (!binding || !noteDeclaredName(name, kind, pos())) {
4315     return null();
4316   }
4317 
4318   return binding;
4319 }
4320 
4321 template <class ParseHandler, typename Unit>
4322 typename ParseHandler::Node
bindingIdentifierOrPattern(DeclarationKind kind,YieldHandling yieldHandling,TokenKind tt)4323 GeneralParser<ParseHandler, Unit>::bindingIdentifierOrPattern(
4324     DeclarationKind kind, YieldHandling yieldHandling, TokenKind tt) {
4325   if (tt == TokenKind::LeftBracket) {
4326     return arrayBindingPattern(kind, yieldHandling);
4327   }
4328 
4329   if (tt == TokenKind::LeftCurly) {
4330     return objectBindingPattern(kind, yieldHandling);
4331   }
4332 
4333   if (!TokenKindIsPossibleIdentifierName(tt)) {
4334     error(JSMSG_NO_VARIABLE_NAME);
4335     return null();
4336   }
4337 
4338   return bindingIdentifier(kind, yieldHandling);
4339 }
4340 
4341 template <class ParseHandler, typename Unit>
4342 typename ParseHandler::ListNodeType
objectBindingPattern(DeclarationKind kind,YieldHandling yieldHandling)4343 GeneralParser<ParseHandler, Unit>::objectBindingPattern(
4344     DeclarationKind kind, YieldHandling yieldHandling) {
4345   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftCurly));
4346 
4347   AutoCheckRecursionLimit recursion(cx_);
4348   if (!recursion.check(cx_)) {
4349     return null();
4350   }
4351 
4352   uint32_t begin = pos().begin;
4353   ListNodeType literal = handler_.newObjectLiteral(begin);
4354   if (!literal) {
4355     return null();
4356   }
4357 
4358   Maybe<DeclarationKind> declKind = Some(kind);
4359   TaggedParserAtomIndex propAtom;
4360   for (;;) {
4361     TokenKind tt;
4362     if (!tokenStream.peekToken(&tt)) {
4363       return null();
4364     }
4365     if (tt == TokenKind::RightCurly) {
4366       break;
4367     }
4368 
4369     if (tt == TokenKind::TripleDot) {
4370       tokenStream.consumeKnownToken(TokenKind::TripleDot);
4371       uint32_t begin = pos().begin;
4372 
4373       TokenKind tt;
4374       if (!tokenStream.getToken(&tt)) {
4375         return null();
4376       }
4377 
4378       if (!TokenKindIsPossibleIdentifierName(tt)) {
4379         error(JSMSG_NO_VARIABLE_NAME);
4380         return null();
4381       }
4382 
4383       NameNodeType inner = bindingIdentifier(kind, yieldHandling);
4384       if (!inner) {
4385         return null();
4386       }
4387 
4388       if (!handler_.addSpreadProperty(literal, begin, inner)) {
4389         return null();
4390       }
4391     } else {
4392       TokenPos namePos = anyChars.nextToken().pos;
4393 
4394       PropertyType propType;
4395       Node propName =
4396           propertyOrMethodName(yieldHandling, PropertyNameInPattern, declKind,
4397                                literal, &propType, &propAtom);
4398       if (!propName) {
4399         return null();
4400       }
4401 
4402       if (propType == PropertyType::Normal) {
4403         // Handle e.g., |var {p: x} = o| and |var {p: x=0} = o|.
4404 
4405         if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) {
4406           return null();
4407         }
4408 
4409         Node binding = bindingIdentifierOrPattern(kind, yieldHandling, tt);
4410         if (!binding) {
4411           return null();
4412         }
4413 
4414         bool hasInitializer;
4415         if (!tokenStream.matchToken(&hasInitializer, TokenKind::Assign,
4416                                     TokenStream::SlashIsRegExp)) {
4417           return null();
4418         }
4419 
4420         Node bindingExpr =
4421             hasInitializer ? bindingInitializer(binding, kind, yieldHandling)
4422                            : binding;
4423         if (!bindingExpr) {
4424           return null();
4425         }
4426 
4427         if (!handler_.addPropertyDefinition(literal, propName, bindingExpr)) {
4428           return null();
4429         }
4430       } else if (propType == PropertyType::Shorthand) {
4431         // Handle e.g., |var {x, y} = o| as destructuring shorthand
4432         // for |var {x: x, y: y} = o|.
4433         MOZ_ASSERT(TokenKindIsPossibleIdentifierName(tt));
4434 
4435         NameNodeType binding = bindingIdentifier(kind, yieldHandling);
4436         if (!binding) {
4437           return null();
4438         }
4439 
4440         if (!handler_.addShorthand(literal, handler_.asName(propName),
4441                                    binding)) {
4442           return null();
4443         }
4444       } else if (propType == PropertyType::CoverInitializedName) {
4445         // Handle e.g., |var {x=1, y=2} = o| as destructuring
4446         // shorthand with default values.
4447         MOZ_ASSERT(TokenKindIsPossibleIdentifierName(tt));
4448 
4449         NameNodeType binding = bindingIdentifier(kind, yieldHandling);
4450         if (!binding) {
4451           return null();
4452         }
4453 
4454         tokenStream.consumeKnownToken(TokenKind::Assign);
4455 
4456         BinaryNodeType bindingExpr =
4457             bindingInitializer(binding, kind, yieldHandling);
4458         if (!bindingExpr) {
4459           return null();
4460         }
4461 
4462         if (!handler_.addPropertyDefinition(literal, propName, bindingExpr)) {
4463           return null();
4464         }
4465       } else {
4466         errorAt(namePos.begin, JSMSG_NO_VARIABLE_NAME);
4467         return null();
4468       }
4469     }
4470 
4471     bool matched;
4472     if (!tokenStream.matchToken(&matched, TokenKind::Comma,
4473                                 TokenStream::SlashIsInvalid)) {
4474       return null();
4475     }
4476     if (!matched) {
4477       break;
4478     }
4479     if (tt == TokenKind::TripleDot) {
4480       error(JSMSG_REST_WITH_COMMA);
4481       return null();
4482     }
4483   }
4484 
4485   if (!mustMatchToken(TokenKind::RightCurly, [this, begin](TokenKind actual) {
4486         this->reportMissingClosing(JSMSG_CURLY_AFTER_LIST, JSMSG_CURLY_OPENED,
4487                                    begin);
4488       })) {
4489     return null();
4490   }
4491 
4492   handler_.setEndPosition(literal, pos().end);
4493   return literal;
4494 }
4495 
4496 template <class ParseHandler, typename Unit>
4497 typename ParseHandler::ListNodeType
arrayBindingPattern(DeclarationKind kind,YieldHandling yieldHandling)4498 GeneralParser<ParseHandler, Unit>::arrayBindingPattern(
4499     DeclarationKind kind, YieldHandling yieldHandling) {
4500   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftBracket));
4501 
4502   AutoCheckRecursionLimit recursion(cx_);
4503   if (!recursion.check(cx_)) {
4504     return null();
4505   }
4506 
4507   uint32_t begin = pos().begin;
4508   ListNodeType literal = handler_.newArrayLiteral(begin);
4509   if (!literal) {
4510     return null();
4511   }
4512 
4513   uint32_t index = 0;
4514   for (;; index++) {
4515     if (index >= NativeObject::MAX_DENSE_ELEMENTS_COUNT) {
4516       error(JSMSG_ARRAY_INIT_TOO_BIG);
4517       return null();
4518     }
4519 
4520     TokenKind tt;
4521     if (!tokenStream.getToken(&tt)) {
4522       return null();
4523     }
4524 
4525     if (tt == TokenKind::RightBracket) {
4526       anyChars.ungetToken();
4527       break;
4528     }
4529 
4530     if (tt == TokenKind::Comma) {
4531       if (!handler_.addElision(literal, pos())) {
4532         return null();
4533       }
4534     } else if (tt == TokenKind::TripleDot) {
4535       uint32_t begin = pos().begin;
4536 
4537       TokenKind tt;
4538       if (!tokenStream.getToken(&tt)) {
4539         return null();
4540       }
4541 
4542       Node inner = bindingIdentifierOrPattern(kind, yieldHandling, tt);
4543       if (!inner) {
4544         return null();
4545       }
4546 
4547       if (!handler_.addSpreadElement(literal, begin, inner)) {
4548         return null();
4549       }
4550     } else {
4551       Node binding = bindingIdentifierOrPattern(kind, yieldHandling, tt);
4552       if (!binding) {
4553         return null();
4554       }
4555 
4556       bool hasInitializer;
4557       if (!tokenStream.matchToken(&hasInitializer, TokenKind::Assign,
4558                                   TokenStream::SlashIsRegExp)) {
4559         return null();
4560       }
4561 
4562       Node element = hasInitializer
4563                          ? bindingInitializer(binding, kind, yieldHandling)
4564                          : binding;
4565       if (!element) {
4566         return null();
4567       }
4568 
4569       handler_.addArrayElement(literal, element);
4570     }
4571 
4572     if (tt != TokenKind::Comma) {
4573       // If we didn't already match TokenKind::Comma in above case.
4574       bool matched;
4575       if (!tokenStream.matchToken(&matched, TokenKind::Comma,
4576                                   TokenStream::SlashIsRegExp)) {
4577         return null();
4578       }
4579       if (!matched) {
4580         break;
4581       }
4582 
4583       if (tt == TokenKind::TripleDot) {
4584         error(JSMSG_REST_WITH_COMMA);
4585         return null();
4586       }
4587     }
4588   }
4589 
4590   if (!mustMatchToken(TokenKind::RightBracket, [this, begin](TokenKind actual) {
4591         this->reportMissingClosing(JSMSG_BRACKET_AFTER_LIST,
4592                                    JSMSG_BRACKET_OPENED, begin);
4593       })) {
4594     return null();
4595   }
4596 
4597   handler_.setEndPosition(literal, pos().end);
4598   return literal;
4599 }
4600 
4601 template <class ParseHandler, typename Unit>
4602 typename ParseHandler::Node
destructuringDeclaration(DeclarationKind kind,YieldHandling yieldHandling,TokenKind tt)4603 GeneralParser<ParseHandler, Unit>::destructuringDeclaration(
4604     DeclarationKind kind, YieldHandling yieldHandling, TokenKind tt) {
4605   MOZ_ASSERT(anyChars.isCurrentTokenType(tt));
4606   MOZ_ASSERT(tt == TokenKind::LeftBracket || tt == TokenKind::LeftCurly);
4607 
4608   return tt == TokenKind::LeftBracket
4609              ? arrayBindingPattern(kind, yieldHandling)
4610              : objectBindingPattern(kind, yieldHandling);
4611 }
4612 
4613 template <class ParseHandler, typename Unit>
4614 typename ParseHandler::Node
destructuringDeclarationWithoutYieldOrAwait(DeclarationKind kind,YieldHandling yieldHandling,TokenKind tt)4615 GeneralParser<ParseHandler, Unit>::destructuringDeclarationWithoutYieldOrAwait(
4616     DeclarationKind kind, YieldHandling yieldHandling, TokenKind tt) {
4617   uint32_t startYieldOffset = pc_->lastYieldOffset;
4618   uint32_t startAwaitOffset = pc_->lastAwaitOffset;
4619   Node res = destructuringDeclaration(kind, yieldHandling, tt);
4620   if (res) {
4621     if (pc_->lastYieldOffset != startYieldOffset) {
4622       errorAt(pc_->lastYieldOffset, JSMSG_YIELD_IN_PARAMETER);
4623       return null();
4624     }
4625     if (pc_->lastAwaitOffset != startAwaitOffset) {
4626       errorAt(pc_->lastAwaitOffset, JSMSG_AWAIT_IN_PARAMETER);
4627       return null();
4628     }
4629   }
4630   return res;
4631 }
4632 
4633 template <class ParseHandler, typename Unit>
4634 typename ParseHandler::LexicalScopeNodeType
blockStatement(YieldHandling yieldHandling,unsigned errorNumber)4635 GeneralParser<ParseHandler, Unit>::blockStatement(YieldHandling yieldHandling,
4636                                                   unsigned errorNumber) {
4637   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftCurly));
4638   uint32_t openedPos = pos().begin;
4639 
4640   ParseContext::Statement stmt(pc_, StatementKind::Block);
4641   ParseContext::Scope scope(this);
4642   if (!scope.init(pc_)) {
4643     return null();
4644   }
4645 
4646   ListNodeType list = statementList(yieldHandling);
4647   if (!list) {
4648     return null();
4649   }
4650 
4651   if (!mustMatchToken(TokenKind::RightCurly, [this, errorNumber,
4652                                               openedPos](TokenKind actual) {
4653         this->reportMissingClosing(errorNumber, JSMSG_CURLY_OPENED, openedPos);
4654       })) {
4655     return null();
4656   }
4657 
4658   return finishLexicalScope(scope, list);
4659 }
4660 
4661 template <class ParseHandler, typename Unit>
4662 typename ParseHandler::Node
expressionAfterForInOrOf(ParseNodeKind forHeadKind,YieldHandling yieldHandling)4663 GeneralParser<ParseHandler, Unit>::expressionAfterForInOrOf(
4664     ParseNodeKind forHeadKind, YieldHandling yieldHandling) {
4665   MOZ_ASSERT(forHeadKind == ParseNodeKind::ForIn ||
4666              forHeadKind == ParseNodeKind::ForOf);
4667   Node pn = forHeadKind == ParseNodeKind::ForOf
4668                 ? assignExpr(InAllowed, yieldHandling, TripledotProhibited)
4669                 : expr(InAllowed, yieldHandling, TripledotProhibited);
4670   return pn;
4671 }
4672 
4673 template <class ParseHandler, typename Unit>
4674 typename ParseHandler::Node
declarationPattern(DeclarationKind declKind,TokenKind tt,bool initialDeclaration,YieldHandling yieldHandling,ParseNodeKind * forHeadKind,Node * forInOrOfExpression)4675 GeneralParser<ParseHandler, Unit>::declarationPattern(
4676     DeclarationKind declKind, TokenKind tt, bool initialDeclaration,
4677     YieldHandling yieldHandling, ParseNodeKind* forHeadKind,
4678     Node* forInOrOfExpression) {
4679   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftBracket) ||
4680              anyChars.isCurrentTokenType(TokenKind::LeftCurly));
4681 
4682   Node pattern = destructuringDeclaration(declKind, yieldHandling, tt);
4683   if (!pattern) {
4684     return null();
4685   }
4686 
4687   if (initialDeclaration && forHeadKind) {
4688     bool isForIn, isForOf;
4689     if (!matchInOrOf(&isForIn, &isForOf)) {
4690       return null();
4691     }
4692 
4693     if (isForIn) {
4694       *forHeadKind = ParseNodeKind::ForIn;
4695     } else if (isForOf) {
4696       *forHeadKind = ParseNodeKind::ForOf;
4697     } else {
4698       *forHeadKind = ParseNodeKind::ForHead;
4699     }
4700 
4701     if (*forHeadKind != ParseNodeKind::ForHead) {
4702       *forInOrOfExpression =
4703           expressionAfterForInOrOf(*forHeadKind, yieldHandling);
4704       if (!*forInOrOfExpression) {
4705         return null();
4706       }
4707 
4708       return pattern;
4709     }
4710   }
4711 
4712   if (!mustMatchToken(TokenKind::Assign, JSMSG_BAD_DESTRUCT_DECL)) {
4713     return null();
4714   }
4715 
4716   Node init = assignExpr(forHeadKind ? InProhibited : InAllowed, yieldHandling,
4717                          TripledotProhibited);
4718   if (!init) {
4719     return null();
4720   }
4721 
4722   return handler_.newAssignment(ParseNodeKind::AssignExpr, pattern, init);
4723 }
4724 
4725 template <class ParseHandler, typename Unit>
4726 typename ParseHandler::AssignmentNodeType
initializerInNameDeclaration(NameNodeType binding,DeclarationKind declKind,bool initialDeclaration,YieldHandling yieldHandling,ParseNodeKind * forHeadKind,Node * forInOrOfExpression)4727 GeneralParser<ParseHandler, Unit>::initializerInNameDeclaration(
4728     NameNodeType binding, DeclarationKind declKind, bool initialDeclaration,
4729     YieldHandling yieldHandling, ParseNodeKind* forHeadKind,
4730     Node* forInOrOfExpression) {
4731   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Assign));
4732 
4733   uint32_t initializerOffset;
4734   if (!tokenStream.peekOffset(&initializerOffset, TokenStream::SlashIsRegExp)) {
4735     return null();
4736   }
4737 
4738   Node initializer = assignExpr(forHeadKind ? InProhibited : InAllowed,
4739                                 yieldHandling, TripledotProhibited);
4740   if (!initializer) {
4741     return null();
4742   }
4743 
4744   if (forHeadKind && initialDeclaration) {
4745     bool isForIn, isForOf;
4746     if (!matchInOrOf(&isForIn, &isForOf)) {
4747       return null();
4748     }
4749 
4750     // An initialized declaration can't appear in a for-of:
4751     //
4752     //   for (var/let/const x = ... of ...); // BAD
4753     if (isForOf) {
4754       errorAt(initializerOffset, JSMSG_OF_AFTER_FOR_LOOP_DECL);
4755       return null();
4756     }
4757 
4758     if (isForIn) {
4759       // Lexical declarations in for-in loops can't be initialized:
4760       //
4761       //   for (let/const x = ... in ...); // BAD
4762       if (DeclarationKindIsLexical(declKind)) {
4763         errorAt(initializerOffset, JSMSG_IN_AFTER_LEXICAL_FOR_DECL);
4764         return null();
4765       }
4766 
4767       // This leaves only initialized for-in |var| declarations.  ES6
4768       // forbids these; later ES un-forbids in non-strict mode code.
4769       *forHeadKind = ParseNodeKind::ForIn;
4770       if (!strictModeErrorAt(initializerOffset,
4771                              JSMSG_INVALID_FOR_IN_DECL_WITH_INIT)) {
4772         return null();
4773       }
4774 
4775       *forInOrOfExpression =
4776           expressionAfterForInOrOf(ParseNodeKind::ForIn, yieldHandling);
4777       if (!*forInOrOfExpression) {
4778         return null();
4779       }
4780     } else {
4781       *forHeadKind = ParseNodeKind::ForHead;
4782     }
4783   }
4784 
4785   return handler_.finishInitializerAssignment(binding, initializer);
4786 }
4787 
4788 template <class ParseHandler, typename Unit>
declarationName(DeclarationKind declKind,TokenKind tt,bool initialDeclaration,YieldHandling yieldHandling,ParseNodeKind * forHeadKind,Node * forInOrOfExpression)4789 typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::declarationName(
4790     DeclarationKind declKind, TokenKind tt, bool initialDeclaration,
4791     YieldHandling yieldHandling, ParseNodeKind* forHeadKind,
4792     Node* forInOrOfExpression) {
4793   // Anything other than possible identifier is an error.
4794   if (!TokenKindIsPossibleIdentifier(tt)) {
4795     error(JSMSG_NO_VARIABLE_NAME);
4796     return null();
4797   }
4798 
4799   TaggedParserAtomIndex name = bindingIdentifier(yieldHandling);
4800   if (!name) {
4801     return null();
4802   }
4803 
4804   NameNodeType binding = newName(name);
4805   if (!binding) {
4806     return null();
4807   }
4808 
4809   TokenPos namePos = pos();
4810 
4811   // The '=' context after a variable name in a declaration is an opportunity
4812   // for ASI, and thus for the next token to start an ExpressionStatement:
4813   //
4814   //  var foo   // VariableDeclaration
4815   //  /bar/g;   // ExpressionStatement
4816   //
4817   // Therefore get the token here with SlashIsRegExp.
4818   bool matched;
4819   if (!tokenStream.matchToken(&matched, TokenKind::Assign,
4820                               TokenStream::SlashIsRegExp)) {
4821     return null();
4822   }
4823 
4824   Node declaration;
4825   if (matched) {
4826     declaration = initializerInNameDeclaration(
4827         binding, declKind, initialDeclaration, yieldHandling, forHeadKind,
4828         forInOrOfExpression);
4829     if (!declaration) {
4830       return null();
4831     }
4832   } else {
4833     declaration = binding;
4834 
4835     if (initialDeclaration && forHeadKind) {
4836       bool isForIn, isForOf;
4837       if (!matchInOrOf(&isForIn, &isForOf)) {
4838         return null();
4839       }
4840 
4841       if (isForIn) {
4842         *forHeadKind = ParseNodeKind::ForIn;
4843       } else if (isForOf) {
4844         *forHeadKind = ParseNodeKind::ForOf;
4845       } else {
4846         *forHeadKind = ParseNodeKind::ForHead;
4847       }
4848     }
4849 
4850     if (forHeadKind && *forHeadKind != ParseNodeKind::ForHead) {
4851       *forInOrOfExpression =
4852           expressionAfterForInOrOf(*forHeadKind, yieldHandling);
4853       if (!*forInOrOfExpression) {
4854         return null();
4855       }
4856     } else {
4857       // Normal const declarations, and const declarations in for(;;)
4858       // heads, must be initialized.
4859       if (declKind == DeclarationKind::Const) {
4860         errorAt(namePos.begin, JSMSG_BAD_CONST_DECL);
4861         return null();
4862       }
4863     }
4864   }
4865 
4866   // Note the declared name after knowing whether or not we are in a for-of
4867   // loop, due to special early error semantics in Annex B.3.5.
4868   if (!noteDeclaredName(name, declKind, namePos)) {
4869     return null();
4870   }
4871 
4872   return declaration;
4873 }
4874 
4875 template <class ParseHandler, typename Unit>
4876 typename ParseHandler::ListNodeType
declarationList(YieldHandling yieldHandling,ParseNodeKind kind,ParseNodeKind * forHeadKind,Node * forInOrOfExpression)4877 GeneralParser<ParseHandler, Unit>::declarationList(
4878     YieldHandling yieldHandling, ParseNodeKind kind,
4879     ParseNodeKind* forHeadKind /* = nullptr */,
4880     Node* forInOrOfExpression /* = nullptr */) {
4881   MOZ_ASSERT(kind == ParseNodeKind::VarStmt || kind == ParseNodeKind::LetDecl ||
4882              kind == ParseNodeKind::ConstDecl);
4883 
4884   DeclarationKind declKind;
4885   switch (kind) {
4886     case ParseNodeKind::VarStmt:
4887       declKind = DeclarationKind::Var;
4888       break;
4889     case ParseNodeKind::ConstDecl:
4890       declKind = DeclarationKind::Const;
4891       break;
4892     case ParseNodeKind::LetDecl:
4893       declKind = DeclarationKind::Let;
4894       break;
4895     default:
4896       MOZ_CRASH("Unknown declaration kind");
4897   }
4898 
4899   ListNodeType decl = handler_.newDeclarationList(kind, pos());
4900   if (!decl) {
4901     return null();
4902   }
4903 
4904   bool moreDeclarations;
4905   bool initialDeclaration = true;
4906   do {
4907     MOZ_ASSERT_IF(!initialDeclaration && forHeadKind,
4908                   *forHeadKind == ParseNodeKind::ForHead);
4909 
4910     TokenKind tt;
4911     if (!tokenStream.getToken(&tt)) {
4912       return null();
4913     }
4914 
4915     Node binding =
4916         (tt == TokenKind::LeftBracket || tt == TokenKind::LeftCurly)
4917             ? declarationPattern(declKind, tt, initialDeclaration,
4918                                  yieldHandling, forHeadKind,
4919                                  forInOrOfExpression)
4920             : declarationName(declKind, tt, initialDeclaration, yieldHandling,
4921                               forHeadKind, forInOrOfExpression);
4922     if (!binding) {
4923       return null();
4924     }
4925 
4926     handler_.addList(decl, binding);
4927 
4928     // If we have a for-in/of loop, the above call matches the entirety
4929     // of the loop head (up to the closing parenthesis).
4930     if (forHeadKind && *forHeadKind != ParseNodeKind::ForHead) {
4931       break;
4932     }
4933 
4934     initialDeclaration = false;
4935 
4936     if (!tokenStream.matchToken(&moreDeclarations, TokenKind::Comma,
4937                                 TokenStream::SlashIsRegExp)) {
4938       return null();
4939     }
4940   } while (moreDeclarations);
4941 
4942   return decl;
4943 }
4944 
4945 template <class ParseHandler, typename Unit>
4946 typename ParseHandler::ListNodeType
lexicalDeclaration(YieldHandling yieldHandling,DeclarationKind kind)4947 GeneralParser<ParseHandler, Unit>::lexicalDeclaration(
4948     YieldHandling yieldHandling, DeclarationKind kind) {
4949   MOZ_ASSERT(kind == DeclarationKind::Const || kind == DeclarationKind::Let);
4950 
4951   /*
4952    * Parse body-level lets without a new block object. ES6 specs
4953    * that an execution environment's initial lexical environment
4954    * is the VariableEnvironment, i.e., body-level lets are in
4955    * the same environment record as vars.
4956    *
4957    * However, they cannot be parsed exactly as vars, as ES6
4958    * requires that uninitialized lets throw ReferenceError on use.
4959    *
4960    * See 8.1.1.1.6 and the note in 13.2.1.
4961    */
4962   ListNodeType decl = declarationList(
4963       yieldHandling, kind == DeclarationKind::Const ? ParseNodeKind::ConstDecl
4964                                                     : ParseNodeKind::LetDecl);
4965   if (!decl || !matchOrInsertSemicolon()) {
4966     return null();
4967   }
4968 
4969   return decl;
4970 }
4971 
4972 template <class ParseHandler, typename Unit>
4973 typename ParseHandler::NameNodeType
moduleExportName()4974 GeneralParser<ParseHandler, Unit>::moduleExportName() {
4975   MOZ_ASSERT(anyChars.currentToken().type == TokenKind::String);
4976   TaggedParserAtomIndex name = anyChars.currentToken().atom();
4977   if (!this->parserAtoms().isModuleExportName(name)) {
4978     error(JSMSG_UNPAIRED_SURROGATE_EXPORT);
4979     return null();
4980   }
4981   return handler_.newStringLiteral(name, pos());
4982 }
4983 
4984 template <class ParseHandler, typename Unit>
assertClause(ListNodeType assertionsSet)4985 bool GeneralParser<ParseHandler, Unit>::assertClause(
4986     ListNodeType assertionsSet) {
4987   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Assert));
4988 
4989   if (!options().importAssertions) {
4990     error(JSMSG_IMPORT_ASSERTIONS_NOT_SUPPORTED);
4991     return false;
4992   }
4993 
4994   if (!abortIfSyntaxParser()) {
4995     return false;
4996   }
4997 
4998   if (!mustMatchToken(TokenKind::LeftCurly, JSMSG_CURLY_AFTER_ASSERT)) {
4999     return false;
5000   }
5001 
5002   // Handle the form |... assert {}|
5003   TokenKind token;
5004   if (!tokenStream.getToken(&token)) {
5005     return false;
5006   }
5007   if (token == TokenKind::RightCurly) {
5008     return true;
5009   }
5010 
5011   js::HashSet<TaggedParserAtomIndex, TaggedParserAtomIndexHasher,
5012               js::SystemAllocPolicy>
5013       usedAssertionKeys;
5014 
5015   for (;;) {
5016     TaggedParserAtomIndex keyName;
5017     if (TokenKindIsPossibleIdentifierName(token)) {
5018       keyName = anyChars.currentName();
5019     } else if (token == TokenKind::String) {
5020       keyName = anyChars.currentToken().atom();
5021     } else {
5022       error(JSMSG_ASSERT_KEY_EXPECTED);
5023       return false;
5024     }
5025 
5026     auto p = usedAssertionKeys.lookupForAdd(keyName);
5027     if (p) {
5028       UniqueChars str = this->parserAtoms().toPrintableString(cx_, keyName);
5029       if (!str) {
5030         return false;
5031       }
5032       error(JSMSG_DUPLICATE_ASSERT_KEY, str.get());
5033       return false;
5034     }
5035     if (!usedAssertionKeys.add(p, keyName)) {
5036       ReportOutOfMemory(cx_);
5037       return false;
5038     }
5039 
5040     NameNodeType keyNode = newName(keyName);
5041     if (!keyNode) {
5042       return false;
5043     }
5044 
5045     if (!mustMatchToken(TokenKind::Colon, JSMSG_COLON_AFTER_ASSERT_KEY)) {
5046       return false;
5047     }
5048     if (!mustMatchToken(TokenKind::String, JSMSG_ASSERT_STRING_LITERAL)) {
5049       return false;
5050     }
5051 
5052     NameNodeType valueNode = stringLiteral();
5053     if (!valueNode) {
5054       return false;
5055     }
5056 
5057     BinaryNodeType importAssertionNode =
5058         handler_.newImportAssertion(keyNode, valueNode);
5059     if (!importAssertionNode) {
5060       return false;
5061     }
5062 
5063     handler_.addList(assertionsSet, importAssertionNode);
5064 
5065     if (!tokenStream.getToken(&token)) {
5066       return false;
5067     }
5068     if (token == TokenKind::Comma) {
5069       if (!tokenStream.getToken(&token)) {
5070         return false;
5071       }
5072     }
5073     if (token == TokenKind::RightCurly) {
5074       break;
5075     }
5076   }
5077 
5078   return true;
5079 }
5080 
5081 template <class ParseHandler, typename Unit>
namedImports(ListNodeType importSpecSet)5082 bool GeneralParser<ParseHandler, Unit>::namedImports(
5083     ListNodeType importSpecSet) {
5084   if (!abortIfSyntaxParser()) {
5085     return false;
5086   }
5087 
5088   while (true) {
5089     // Handle the forms |import {} from 'a'| and
5090     // |import { ..., } from 'a'| (where ... is non empty), by
5091     // escaping the loop early if the next token is }.
5092     TokenKind tt;
5093     if (!tokenStream.getToken(&tt)) {
5094       return false;
5095     }
5096 
5097     if (tt == TokenKind::RightCurly) {
5098       break;
5099     }
5100 
5101     TaggedParserAtomIndex importName;
5102     NameNodeType importNameNode = null();
5103     if (TokenKindIsPossibleIdentifierName(tt)) {
5104       importName = anyChars.currentName();
5105       importNameNode = newName(importName);
5106     } else if (tt == TokenKind::String) {
5107       importNameNode = moduleExportName();
5108     } else {
5109       error(JSMSG_NO_IMPORT_NAME);
5110     }
5111     if (!importNameNode) {
5112       return false;
5113     }
5114 
5115     bool matched;
5116     if (!tokenStream.matchToken(&matched, TokenKind::As)) {
5117       return false;
5118     }
5119 
5120     if (matched) {
5121       TokenKind afterAs;
5122       if (!tokenStream.getToken(&afterAs)) {
5123         return false;
5124       }
5125 
5126       if (!TokenKindIsPossibleIdentifierName(afterAs)) {
5127         error(JSMSG_NO_BINDING_NAME);
5128         return false;
5129       }
5130     } else {
5131       // String export names can't refer to local bindings.
5132       if (tt == TokenKind::String) {
5133         error(JSMSG_AS_AFTER_STRING);
5134         return false;
5135       }
5136 
5137       // Keywords cannot be bound to themselves, so an import name
5138       // that is a keyword is a syntax error if it is not followed
5139       // by the keyword 'as'.
5140       // See the ImportSpecifier production in ES6 section 15.2.2.
5141       MOZ_ASSERT(importName);
5142       if (IsKeyword(importName)) {
5143         error(JSMSG_AS_AFTER_RESERVED_WORD, ReservedWordToCharZ(importName));
5144         return false;
5145       }
5146     }
5147 
5148     TaggedParserAtomIndex bindingAtom = importedBinding();
5149     if (!bindingAtom) {
5150       return false;
5151     }
5152 
5153     NameNodeType bindingName = newName(bindingAtom);
5154     if (!bindingName) {
5155       return false;
5156     }
5157     if (!noteDeclaredName(bindingAtom, DeclarationKind::Import, pos())) {
5158       return false;
5159     }
5160 
5161     BinaryNodeType importSpec =
5162         handler_.newImportSpec(importNameNode, bindingName);
5163     if (!importSpec) {
5164       return false;
5165     }
5166 
5167     handler_.addList(importSpecSet, importSpec);
5168 
5169     TokenKind next;
5170     if (!tokenStream.getToken(&next)) {
5171       return false;
5172     }
5173 
5174     if (next == TokenKind::RightCurly) {
5175       break;
5176     }
5177 
5178     if (next != TokenKind::Comma) {
5179       error(JSMSG_RC_AFTER_IMPORT_SPEC_LIST);
5180       return false;
5181     }
5182   }
5183 
5184   return true;
5185 }
5186 
5187 template <class ParseHandler, typename Unit>
namespaceImport(ListNodeType importSpecSet)5188 bool GeneralParser<ParseHandler, Unit>::namespaceImport(
5189     ListNodeType importSpecSet) {
5190   if (!abortIfSyntaxParser()) {
5191     return false;
5192   }
5193 
5194   if (!mustMatchToken(TokenKind::As, JSMSG_AS_AFTER_IMPORT_STAR)) {
5195     return false;
5196   }
5197   uint32_t begin = pos().begin;
5198 
5199   if (!mustMatchToken(TokenKindIsPossibleIdentifierName,
5200                       JSMSG_NO_BINDING_NAME)) {
5201     return false;
5202   }
5203 
5204   // Namespace imports are not indirect bindings but lexical
5205   // definitions that hold a module namespace object. They are treated
5206   // as const variables which are initialized during the
5207   // ModuleInstantiate step.
5208   TaggedParserAtomIndex bindingName = importedBinding();
5209   if (!bindingName) {
5210     return false;
5211   }
5212   NameNodeType bindingNameNode = newName(bindingName);
5213   if (!bindingNameNode) {
5214     return false;
5215   }
5216   if (!noteDeclaredName(bindingName, DeclarationKind::Const, pos())) {
5217     return false;
5218   }
5219 
5220   // The namespace import name is currently required to live on the
5221   // environment.
5222   pc_->varScope().lookupDeclaredName(bindingName)->value()->setClosedOver();
5223 
5224   UnaryNodeType importSpec =
5225       handler_.newImportNamespaceSpec(begin, bindingNameNode);
5226   if (!importSpec) {
5227     return false;
5228   }
5229 
5230   handler_.addList(importSpecSet, importSpec);
5231 
5232   return true;
5233 }
5234 
5235 template <class ParseHandler, typename Unit>
5236 typename ParseHandler::BinaryNodeType
importDeclaration()5237 GeneralParser<ParseHandler, Unit>::importDeclaration() {
5238   if (!abortIfSyntaxParser()) {
5239     return null();
5240   }
5241 
5242   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Import));
5243 
5244   if (!pc_->atModuleLevel()) {
5245     error(JSMSG_IMPORT_DECL_AT_TOP_LEVEL);
5246     return null();
5247   }
5248 
5249   uint32_t begin = pos().begin;
5250   TokenKind tt;
5251   if (!tokenStream.getToken(&tt)) {
5252     return null();
5253   }
5254 
5255   ListNodeType importSpecSet =
5256       handler_.newList(ParseNodeKind::ImportSpecList, pos());
5257   if (!importSpecSet) {
5258     return null();
5259   }
5260 
5261   if (tt == TokenKind::String) {
5262     // Handle the form |import 'a'| by leaving the list empty. This is
5263     // equivalent to |import {} from 'a'|.
5264     handler_.setEndPosition(importSpecSet, pos().begin);
5265   } else {
5266     if (tt == TokenKind::LeftCurly) {
5267       if (!namedImports(importSpecSet)) {
5268         return null();
5269       }
5270     } else if (tt == TokenKind::Mul) {
5271       if (!namespaceImport(importSpecSet)) {
5272         return null();
5273       }
5274     } else if (TokenKindIsPossibleIdentifierName(tt)) {
5275       // Handle the form |import a from 'b'|, by adding a single import
5276       // specifier to the list, with 'default' as the import name and
5277       // 'a' as the binding name. This is equivalent to
5278       // |import { default as a } from 'b'|.
5279       NameNodeType importName =
5280           newName(TaggedParserAtomIndex::WellKnown::default_());
5281       if (!importName) {
5282         return null();
5283       }
5284 
5285       TaggedParserAtomIndex bindingAtom = importedBinding();
5286       if (!bindingAtom) {
5287         return null();
5288       }
5289 
5290       NameNodeType bindingName = newName(bindingAtom);
5291       if (!bindingName) {
5292         return null();
5293       }
5294 
5295       if (!noteDeclaredName(bindingAtom, DeclarationKind::Import, pos())) {
5296         return null();
5297       }
5298 
5299       BinaryNodeType importSpec =
5300           handler_.newImportSpec(importName, bindingName);
5301       if (!importSpec) {
5302         return null();
5303       }
5304 
5305       handler_.addList(importSpecSet, importSpec);
5306 
5307       if (!tokenStream.peekToken(&tt)) {
5308         return null();
5309       }
5310 
5311       if (tt == TokenKind::Comma) {
5312         tokenStream.consumeKnownToken(tt);
5313         if (!tokenStream.getToken(&tt)) {
5314           return null();
5315         }
5316 
5317         if (tt == TokenKind::LeftCurly) {
5318           if (!namedImports(importSpecSet)) {
5319             return null();
5320           }
5321         } else if (tt == TokenKind::Mul) {
5322           if (!namespaceImport(importSpecSet)) {
5323             return null();
5324           }
5325         } else {
5326           error(JSMSG_NAMED_IMPORTS_OR_NAMESPACE_IMPORT);
5327           return null();
5328         }
5329       }
5330     } else {
5331       error(JSMSG_DECLARATION_AFTER_IMPORT);
5332       return null();
5333     }
5334 
5335     if (!mustMatchToken(TokenKind::From, JSMSG_FROM_AFTER_IMPORT_CLAUSE)) {
5336       return null();
5337     }
5338 
5339     if (!mustMatchToken(TokenKind::String, JSMSG_MODULE_SPEC_AFTER_FROM)) {
5340       return null();
5341     }
5342   }
5343 
5344   NameNodeType moduleSpec = stringLiteral();
5345   if (!moduleSpec) {
5346     return null();
5347   }
5348 
5349   if (!tokenStream.peekTokenSameLine(&tt, TokenStream::SlashIsRegExp)) {
5350     return null();
5351   }
5352 
5353   ListNodeType importAssertionList =
5354       handler_.newList(ParseNodeKind::ImportAssertionList, pos());
5355   if (!importAssertionList) {
5356     return null();
5357   }
5358 
5359   if (tt == TokenKind::Assert) {
5360     tokenStream.consumeKnownToken(TokenKind::Assert,
5361                                   TokenStream::SlashIsRegExp);
5362 
5363     if (!assertClause(importAssertionList)) {
5364       return null();
5365     }
5366   }
5367 
5368   if (!matchOrInsertSemicolon(TokenStream::SlashIsRegExp)) {
5369     return null();
5370   }
5371 
5372   BinaryNodeType moduleRequest = handler_.newModuleRequest(
5373       moduleSpec, importAssertionList, TokenPos(begin, pos().end));
5374   if (!moduleRequest) {
5375     return null();
5376   }
5377 
5378   BinaryNodeType node = handler_.newImportDeclaration(
5379       importSpecSet, moduleRequest, TokenPos(begin, pos().end));
5380   if (!node || !processImport(node)) {
5381     return null();
5382   }
5383 
5384   return node;
5385 }
5386 
5387 template <class ParseHandler, typename Unit>
5388 inline typename ParseHandler::Node
importDeclarationOrImportExpr(YieldHandling yieldHandling)5389 GeneralParser<ParseHandler, Unit>::importDeclarationOrImportExpr(
5390     YieldHandling yieldHandling) {
5391   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Import));
5392 
5393   TokenKind tt;
5394   if (!tokenStream.peekToken(&tt)) {
5395     return null();
5396   }
5397 
5398   if (tt == TokenKind::Dot || tt == TokenKind::LeftParen) {
5399     return expressionStatement(yieldHandling);
5400   }
5401 
5402   return importDeclaration();
5403 }
5404 
5405 template <typename Unit>
checkExportedName(TaggedParserAtomIndex exportName)5406 bool Parser<FullParseHandler, Unit>::checkExportedName(
5407     TaggedParserAtomIndex exportName) {
5408   if (!pc_->sc()->asModuleContext()->builder.hasExportedName(exportName)) {
5409     return true;
5410   }
5411 
5412   UniqueChars str = this->parserAtoms().toPrintableString(cx_, exportName);
5413   if (!str) {
5414     return false;
5415   }
5416 
5417   error(JSMSG_DUPLICATE_EXPORT_NAME, str.get());
5418   return false;
5419 }
5420 
5421 template <typename Unit>
checkExportedName(TaggedParserAtomIndex exportName)5422 inline bool Parser<SyntaxParseHandler, Unit>::checkExportedName(
5423     TaggedParserAtomIndex exportName) {
5424   MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5425   return false;
5426 }
5427 
5428 template <class ParseHandler, typename Unit>
checkExportedName(TaggedParserAtomIndex exportName)5429 inline bool GeneralParser<ParseHandler, Unit>::checkExportedName(
5430     TaggedParserAtomIndex exportName) {
5431   return asFinalParser()->checkExportedName(exportName);
5432 }
5433 
5434 template <typename Unit>
checkExportedNamesForArrayBinding(ListNode * array)5435 bool Parser<FullParseHandler, Unit>::checkExportedNamesForArrayBinding(
5436     ListNode* array) {
5437   MOZ_ASSERT(array->isKind(ParseNodeKind::ArrayExpr));
5438 
5439   for (ParseNode* node : array->contents()) {
5440     if (node->isKind(ParseNodeKind::Elision)) {
5441       continue;
5442     }
5443 
5444     ParseNode* binding;
5445     if (node->isKind(ParseNodeKind::Spread)) {
5446       binding = node->as<UnaryNode>().kid();
5447     } else if (node->isKind(ParseNodeKind::AssignExpr)) {
5448       binding = node->as<AssignmentNode>().left();
5449     } else {
5450       binding = node;
5451     }
5452 
5453     if (!checkExportedNamesForDeclaration(binding)) {
5454       return false;
5455     }
5456   }
5457 
5458   return true;
5459 }
5460 
5461 template <typename Unit>
checkExportedNamesForArrayBinding(ListNodeType array)5462 inline bool Parser<SyntaxParseHandler, Unit>::checkExportedNamesForArrayBinding(
5463     ListNodeType array) {
5464   MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5465   return false;
5466 }
5467 
5468 template <class ParseHandler, typename Unit>
5469 inline bool
checkExportedNamesForArrayBinding(ListNodeType array)5470 GeneralParser<ParseHandler, Unit>::checkExportedNamesForArrayBinding(
5471     ListNodeType array) {
5472   return asFinalParser()->checkExportedNamesForArrayBinding(array);
5473 }
5474 
5475 template <typename Unit>
checkExportedNamesForObjectBinding(ListNode * obj)5476 bool Parser<FullParseHandler, Unit>::checkExportedNamesForObjectBinding(
5477     ListNode* obj) {
5478   MOZ_ASSERT(obj->isKind(ParseNodeKind::ObjectExpr));
5479 
5480   for (ParseNode* node : obj->contents()) {
5481     MOZ_ASSERT(node->isKind(ParseNodeKind::MutateProto) ||
5482                node->isKind(ParseNodeKind::PropertyDefinition) ||
5483                node->isKind(ParseNodeKind::Shorthand) ||
5484                node->isKind(ParseNodeKind::Spread));
5485 
5486     ParseNode* target;
5487     if (node->isKind(ParseNodeKind::Spread)) {
5488       target = node->as<UnaryNode>().kid();
5489     } else {
5490       if (node->isKind(ParseNodeKind::MutateProto)) {
5491         target = node->as<UnaryNode>().kid();
5492       } else {
5493         target = node->as<BinaryNode>().right();
5494       }
5495 
5496       if (target->isKind(ParseNodeKind::AssignExpr)) {
5497         target = target->as<AssignmentNode>().left();
5498       }
5499     }
5500 
5501     if (!checkExportedNamesForDeclaration(target)) {
5502       return false;
5503     }
5504   }
5505 
5506   return true;
5507 }
5508 
5509 template <typename Unit>
5510 inline bool Parser<SyntaxParseHandler,
checkExportedNamesForObjectBinding(ListNodeType obj)5511                    Unit>::checkExportedNamesForObjectBinding(ListNodeType obj) {
5512   MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5513   return false;
5514 }
5515 
5516 template <class ParseHandler, typename Unit>
5517 inline bool
checkExportedNamesForObjectBinding(ListNodeType obj)5518 GeneralParser<ParseHandler, Unit>::checkExportedNamesForObjectBinding(
5519     ListNodeType obj) {
5520   return asFinalParser()->checkExportedNamesForObjectBinding(obj);
5521 }
5522 
5523 template <typename Unit>
checkExportedNamesForDeclaration(ParseNode * node)5524 bool Parser<FullParseHandler, Unit>::checkExportedNamesForDeclaration(
5525     ParseNode* node) {
5526   if (node->isKind(ParseNodeKind::Name)) {
5527     if (!checkExportedName(node->as<NameNode>().atom())) {
5528       return false;
5529     }
5530   } else if (node->isKind(ParseNodeKind::ArrayExpr)) {
5531     if (!checkExportedNamesForArrayBinding(&node->as<ListNode>())) {
5532       return false;
5533     }
5534   } else {
5535     MOZ_ASSERT(node->isKind(ParseNodeKind::ObjectExpr));
5536     if (!checkExportedNamesForObjectBinding(&node->as<ListNode>())) {
5537       return false;
5538     }
5539   }
5540 
5541   return true;
5542 }
5543 
5544 template <typename Unit>
checkExportedNamesForDeclaration(Node node)5545 inline bool Parser<SyntaxParseHandler, Unit>::checkExportedNamesForDeclaration(
5546     Node node) {
5547   MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5548   return false;
5549 }
5550 
5551 template <class ParseHandler, typename Unit>
checkExportedNamesForDeclaration(Node node)5552 inline bool GeneralParser<ParseHandler, Unit>::checkExportedNamesForDeclaration(
5553     Node node) {
5554   return asFinalParser()->checkExportedNamesForDeclaration(node);
5555 }
5556 
5557 template <typename Unit>
checkExportedNamesForDeclarationList(ListNode * node)5558 bool Parser<FullParseHandler, Unit>::checkExportedNamesForDeclarationList(
5559     ListNode* node) {
5560   for (ParseNode* binding : node->contents()) {
5561     if (binding->isKind(ParseNodeKind::AssignExpr)) {
5562       binding = binding->as<AssignmentNode>().left();
5563     } else {
5564       MOZ_ASSERT(binding->isKind(ParseNodeKind::Name));
5565     }
5566 
5567     if (!checkExportedNamesForDeclaration(binding)) {
5568       return false;
5569     }
5570   }
5571 
5572   return true;
5573 }
5574 
5575 template <typename Unit>
5576 inline bool
checkExportedNamesForDeclarationList(ListNodeType node)5577 Parser<SyntaxParseHandler, Unit>::checkExportedNamesForDeclarationList(
5578     ListNodeType node) {
5579   MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5580   return false;
5581 }
5582 
5583 template <class ParseHandler, typename Unit>
5584 inline bool
checkExportedNamesForDeclarationList(ListNodeType node)5585 GeneralParser<ParseHandler, Unit>::checkExportedNamesForDeclarationList(
5586     ListNodeType node) {
5587   return asFinalParser()->checkExportedNamesForDeclarationList(node);
5588 }
5589 
5590 template <typename Unit>
checkExportedNameForClause(NameNode * nameNode)5591 inline bool Parser<FullParseHandler, Unit>::checkExportedNameForClause(
5592     NameNode* nameNode) {
5593   return checkExportedName(nameNode->atom());
5594 }
5595 
5596 template <typename Unit>
checkExportedNameForClause(NameNodeType nameNode)5597 inline bool Parser<SyntaxParseHandler, Unit>::checkExportedNameForClause(
5598     NameNodeType nameNode) {
5599   MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5600   return false;
5601 }
5602 
5603 template <class ParseHandler, typename Unit>
checkExportedNameForClause(NameNodeType nameNode)5604 inline bool GeneralParser<ParseHandler, Unit>::checkExportedNameForClause(
5605     NameNodeType nameNode) {
5606   return asFinalParser()->checkExportedNameForClause(nameNode);
5607 }
5608 
5609 template <typename Unit>
checkExportedNameForFunction(FunctionNode * funNode)5610 bool Parser<FullParseHandler, Unit>::checkExportedNameForFunction(
5611     FunctionNode* funNode) {
5612   return checkExportedName(funNode->funbox()->explicitName());
5613 }
5614 
5615 template <typename Unit>
checkExportedNameForFunction(FunctionNodeType funNode)5616 inline bool Parser<SyntaxParseHandler, Unit>::checkExportedNameForFunction(
5617     FunctionNodeType funNode) {
5618   MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5619   return false;
5620 }
5621 
5622 template <class ParseHandler, typename Unit>
checkExportedNameForFunction(FunctionNodeType funNode)5623 inline bool GeneralParser<ParseHandler, Unit>::checkExportedNameForFunction(
5624     FunctionNodeType funNode) {
5625   return asFinalParser()->checkExportedNameForFunction(funNode);
5626 }
5627 
5628 template <typename Unit>
checkExportedNameForClass(ClassNode * classNode)5629 bool Parser<FullParseHandler, Unit>::checkExportedNameForClass(
5630     ClassNode* classNode) {
5631   MOZ_ASSERT(classNode->names());
5632   return checkExportedName(classNode->names()->innerBinding()->atom());
5633 }
5634 
5635 template <typename Unit>
checkExportedNameForClass(ClassNodeType classNode)5636 inline bool Parser<SyntaxParseHandler, Unit>::checkExportedNameForClass(
5637     ClassNodeType classNode) {
5638   MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5639   return false;
5640 }
5641 
5642 template <class ParseHandler, typename Unit>
checkExportedNameForClass(ClassNodeType classNode)5643 inline bool GeneralParser<ParseHandler, Unit>::checkExportedNameForClass(
5644     ClassNodeType classNode) {
5645   return asFinalParser()->checkExportedNameForClass(classNode);
5646 }
5647 
5648 template <>
processExport(ParseNode * node)5649 inline bool PerHandlerParser<FullParseHandler>::processExport(ParseNode* node) {
5650   return pc_->sc()->asModuleContext()->builder.processExport(node);
5651 }
5652 
5653 template <>
processExport(Node node)5654 inline bool PerHandlerParser<SyntaxParseHandler>::processExport(Node node) {
5655   MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5656   return false;
5657 }
5658 
5659 template <>
processExportFrom(BinaryNodeType node)5660 inline bool PerHandlerParser<FullParseHandler>::processExportFrom(
5661     BinaryNodeType node) {
5662   return pc_->sc()->asModuleContext()->builder.processExportFrom(node);
5663 }
5664 
5665 template <>
processExportFrom(BinaryNodeType node)5666 inline bool PerHandlerParser<SyntaxParseHandler>::processExportFrom(
5667     BinaryNodeType node) {
5668   MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5669   return false;
5670 }
5671 
5672 template <>
processImport(BinaryNodeType node)5673 inline bool PerHandlerParser<FullParseHandler>::processImport(
5674     BinaryNodeType node) {
5675   return pc_->sc()->asModuleContext()->builder.processImport(node);
5676 }
5677 
5678 template <>
processImport(BinaryNodeType node)5679 inline bool PerHandlerParser<SyntaxParseHandler>::processImport(
5680     BinaryNodeType node) {
5681   MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5682   return false;
5683 }
5684 
5685 template <class ParseHandler, typename Unit>
5686 typename ParseHandler::BinaryNodeType
exportFrom(uint32_t begin,Node specList)5687 GeneralParser<ParseHandler, Unit>::exportFrom(uint32_t begin, Node specList) {
5688   if (!abortIfSyntaxParser()) {
5689     return null();
5690   }
5691 
5692   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::From));
5693 
5694   if (!mustMatchToken(TokenKind::String, JSMSG_MODULE_SPEC_AFTER_FROM)) {
5695     return null();
5696   }
5697 
5698   NameNodeType moduleSpec = stringLiteral();
5699   if (!moduleSpec) {
5700     return null();
5701   }
5702 
5703   TokenKind tt;
5704   if (!tokenStream.peekTokenSameLine(&tt, TokenStream::SlashIsRegExp)) {
5705     return null();
5706   }
5707   uint32_t moduleSpecPos = pos().begin;
5708 
5709   ListNodeType importAssertionList =
5710       handler_.newList(ParseNodeKind::ImportAssertionList, pos());
5711   if (tt == TokenKind::Assert) {
5712     tokenStream.consumeKnownToken(TokenKind::Assert,
5713                                   TokenStream::SlashIsRegExp);
5714 
5715     if (!assertClause(importAssertionList)) {
5716       return null();
5717     }
5718   }
5719 
5720   if (!matchOrInsertSemicolon(TokenStream::SlashIsRegExp)) {
5721     return null();
5722   }
5723 
5724   BinaryNodeType moduleRequest = handler_.newModuleRequest(
5725       moduleSpec, importAssertionList, TokenPos(moduleSpecPos, pos().end));
5726 
5727   BinaryNodeType node =
5728       handler_.newExportFromDeclaration(begin, specList, moduleRequest);
5729   if (!node) {
5730     return null();
5731   }
5732 
5733   if (!processExportFrom(node)) {
5734     return null();
5735   }
5736 
5737   return node;
5738 }
5739 
5740 template <class ParseHandler, typename Unit>
5741 typename ParseHandler::BinaryNodeType
exportBatch(uint32_t begin)5742 GeneralParser<ParseHandler, Unit>::exportBatch(uint32_t begin) {
5743   if (!abortIfSyntaxParser()) {
5744     return null();
5745   }
5746 
5747   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Mul));
5748   uint32_t beginExportSpec = pos().begin;
5749 
5750   ListNodeType kid = handler_.newList(ParseNodeKind::ExportSpecList, pos());
5751   if (!kid) {
5752     return null();
5753   }
5754 
5755   bool foundAs;
5756   if (!tokenStream.matchToken(&foundAs, TokenKind::As)) {
5757     return null();
5758   }
5759 
5760   if (foundAs) {
5761     TokenKind tt;
5762     if (!tokenStream.getToken(&tt)) {
5763       return null();
5764     }
5765 
5766     NameNodeType exportName = null();
5767     if (TokenKindIsPossibleIdentifierName(tt)) {
5768       exportName = newName(anyChars.currentName());
5769     } else if (tt == TokenKind::String) {
5770       exportName = moduleExportName();
5771     } else {
5772       error(JSMSG_NO_EXPORT_NAME);
5773     }
5774     if (!exportName) {
5775       return null();
5776     }
5777 
5778     if (!checkExportedNameForClause(exportName)) {
5779       return null();
5780     }
5781 
5782     UnaryNodeType exportSpec =
5783         handler_.newExportNamespaceSpec(beginExportSpec, exportName);
5784     if (!exportSpec) {
5785       return null();
5786     }
5787 
5788     handler_.addList(kid, exportSpec);
5789   } else {
5790     // Handle the form |export *| by adding a special export batch
5791     // specifier to the list.
5792     NullaryNodeType exportSpec = handler_.newExportBatchSpec(pos());
5793     if (!exportSpec) {
5794       return null();
5795     }
5796 
5797     handler_.addList(kid, exportSpec);
5798   }
5799 
5800   if (!mustMatchToken(TokenKind::From, JSMSG_FROM_AFTER_EXPORT_STAR)) {
5801     return null();
5802   }
5803 
5804   return exportFrom(begin, kid);
5805 }
5806 
5807 template <typename Unit>
checkLocalExportNames(ListNode * node)5808 bool Parser<FullParseHandler, Unit>::checkLocalExportNames(ListNode* node) {
5809   // ES 2017 draft 15.2.3.1.
5810   for (ParseNode* next : node->contents()) {
5811     ParseNode* name = next->as<BinaryNode>().left();
5812 
5813     if (name->isKind(ParseNodeKind::StringExpr)) {
5814       errorAt(name->pn_pos.begin, JSMSG_BAD_LOCAL_STRING_EXPORT);
5815       return false;
5816     }
5817 
5818     MOZ_ASSERT(name->isKind(ParseNodeKind::Name));
5819 
5820     TaggedParserAtomIndex ident = name->as<NameNode>().atom();
5821     if (!checkLocalExportName(ident, name->pn_pos.begin)) {
5822       return false;
5823     }
5824   }
5825 
5826   return true;
5827 }
5828 
5829 template <typename Unit>
checkLocalExportNames(ListNodeType node)5830 bool Parser<SyntaxParseHandler, Unit>::checkLocalExportNames(
5831     ListNodeType node) {
5832   MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
5833   return false;
5834 }
5835 
5836 template <class ParseHandler, typename Unit>
checkLocalExportNames(ListNodeType node)5837 inline bool GeneralParser<ParseHandler, Unit>::checkLocalExportNames(
5838     ListNodeType node) {
5839   return asFinalParser()->checkLocalExportNames(node);
5840 }
5841 
5842 template <class ParseHandler, typename Unit>
exportClause(uint32_t begin)5843 typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::exportClause(
5844     uint32_t begin) {
5845   if (!abortIfSyntaxParser()) {
5846     return null();
5847   }
5848 
5849   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftCurly));
5850 
5851   ListNodeType kid = handler_.newList(ParseNodeKind::ExportSpecList, pos());
5852   if (!kid) {
5853     return null();
5854   }
5855 
5856   TokenKind tt;
5857   while (true) {
5858     // Handle the forms |export {}| and |export { ..., }| (where ... is non
5859     // empty), by escaping the loop early if the next token is }.
5860     if (!tokenStream.getToken(&tt)) {
5861       return null();
5862     }
5863 
5864     if (tt == TokenKind::RightCurly) {
5865       break;
5866     }
5867 
5868     NameNodeType bindingName = null();
5869     if (TokenKindIsPossibleIdentifierName(tt)) {
5870       bindingName = newName(anyChars.currentName());
5871     } else if (tt == TokenKind::String) {
5872       bindingName = moduleExportName();
5873     } else {
5874       error(JSMSG_NO_BINDING_NAME);
5875     }
5876     if (!bindingName) {
5877       return null();
5878     }
5879 
5880     bool foundAs;
5881     if (!tokenStream.matchToken(&foundAs, TokenKind::As)) {
5882       return null();
5883     }
5884 
5885     NameNodeType exportName = null();
5886     if (foundAs) {
5887       TokenKind tt;
5888       if (!tokenStream.getToken(&tt)) {
5889         return null();
5890       }
5891 
5892       if (TokenKindIsPossibleIdentifierName(tt)) {
5893         exportName = newName(anyChars.currentName());
5894       } else if (tt == TokenKind::String) {
5895         exportName = moduleExportName();
5896       } else {
5897         error(JSMSG_NO_EXPORT_NAME);
5898       }
5899     } else {
5900       if (tt != TokenKind::String) {
5901         exportName = newName(anyChars.currentName());
5902       } else {
5903         exportName = moduleExportName();
5904       }
5905     }
5906     if (!exportName) {
5907       return null();
5908     }
5909 
5910     if (!checkExportedNameForClause(exportName)) {
5911       return null();
5912     }
5913 
5914     BinaryNodeType exportSpec = handler_.newExportSpec(bindingName, exportName);
5915     if (!exportSpec) {
5916       return null();
5917     }
5918 
5919     handler_.addList(kid, exportSpec);
5920 
5921     TokenKind next;
5922     if (!tokenStream.getToken(&next)) {
5923       return null();
5924     }
5925 
5926     if (next == TokenKind::RightCurly) {
5927       break;
5928     }
5929 
5930     if (next != TokenKind::Comma) {
5931       error(JSMSG_RC_AFTER_EXPORT_SPEC_LIST);
5932       return null();
5933     }
5934   }
5935 
5936   // Careful!  If |from| follows, even on a new line, it must start a
5937   // FromClause:
5938   //
5939   //   export { x }
5940   //   from "foo"; // a single ExportDeclaration
5941   //
5942   // But if it doesn't, we might have an ASI opportunity in SlashIsRegExp
5943   // context:
5944   //
5945   //   export { x }   // ExportDeclaration, terminated by ASI
5946   //   fro\u006D      // ExpressionStatement, the name "from"
5947   //
5948   // In that case let matchOrInsertSemicolon sort out ASI or any necessary
5949   // error.
5950   bool matched;
5951   if (!tokenStream.matchToken(&matched, TokenKind::From,
5952                               TokenStream::SlashIsRegExp)) {
5953     return null();
5954   }
5955 
5956   if (matched) {
5957     return exportFrom(begin, kid);
5958   }
5959 
5960   if (!matchOrInsertSemicolon()) {
5961     return null();
5962   }
5963 
5964   if (!checkLocalExportNames(kid)) {
5965     return null();
5966   }
5967 
5968   UnaryNodeType node =
5969       handler_.newExportDeclaration(kid, TokenPos(begin, pos().end));
5970   if (!node) {
5971     return null();
5972   }
5973 
5974   if (!processExport(node)) {
5975     return null();
5976   }
5977 
5978   return node;
5979 }
5980 
5981 template <class ParseHandler, typename Unit>
5982 typename ParseHandler::UnaryNodeType
exportVariableStatement(uint32_t begin)5983 GeneralParser<ParseHandler, Unit>::exportVariableStatement(uint32_t begin) {
5984   if (!abortIfSyntaxParser()) {
5985     return null();
5986   }
5987 
5988   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Var));
5989 
5990   ListNodeType kid = declarationList(YieldIsName, ParseNodeKind::VarStmt);
5991   if (!kid) {
5992     return null();
5993   }
5994   if (!matchOrInsertSemicolon()) {
5995     return null();
5996   }
5997   if (!checkExportedNamesForDeclarationList(kid)) {
5998     return null();
5999   }
6000 
6001   UnaryNodeType node =
6002       handler_.newExportDeclaration(kid, TokenPos(begin, pos().end));
6003   if (!node) {
6004     return null();
6005   }
6006 
6007   if (!processExport(node)) {
6008     return null();
6009   }
6010 
6011   return node;
6012 }
6013 
6014 template <class ParseHandler, typename Unit>
6015 typename ParseHandler::UnaryNodeType
exportFunctionDeclaration(uint32_t begin,uint32_t toStringStart,FunctionAsyncKind asyncKind)6016 GeneralParser<ParseHandler, Unit>::exportFunctionDeclaration(
6017     uint32_t begin, uint32_t toStringStart,
6018     FunctionAsyncKind asyncKind /* = SyncFunction */) {
6019   if (!abortIfSyntaxParser()) {
6020     return null();
6021   }
6022 
6023   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Function));
6024 
6025   Node kid = functionStmt(toStringStart, YieldIsName, NameRequired, asyncKind);
6026   if (!kid) {
6027     return null();
6028   }
6029 
6030   if (!checkExportedNameForFunction(handler_.asFunction(kid))) {
6031     return null();
6032   }
6033 
6034   UnaryNodeType node =
6035       handler_.newExportDeclaration(kid, TokenPos(begin, pos().end));
6036   if (!node) {
6037     return null();
6038   }
6039 
6040   if (!processExport(node)) {
6041     return null();
6042   }
6043 
6044   return node;
6045 }
6046 
6047 template <class ParseHandler, typename Unit>
6048 typename ParseHandler::UnaryNodeType
exportClassDeclaration(uint32_t begin)6049 GeneralParser<ParseHandler, Unit>::exportClassDeclaration(uint32_t begin) {
6050   if (!abortIfSyntaxParser()) {
6051     return null();
6052   }
6053 
6054   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Class));
6055 
6056   ClassNodeType kid =
6057       classDefinition(YieldIsName, ClassStatement, NameRequired);
6058   if (!kid) {
6059     return null();
6060   }
6061 
6062   if (!checkExportedNameForClass(kid)) {
6063     return null();
6064   }
6065 
6066   UnaryNodeType node =
6067       handler_.newExportDeclaration(kid, TokenPos(begin, pos().end));
6068   if (!node) {
6069     return null();
6070   }
6071 
6072   if (!processExport(node)) {
6073     return null();
6074   }
6075 
6076   return node;
6077 }
6078 
6079 template <class ParseHandler, typename Unit>
6080 typename ParseHandler::UnaryNodeType
exportLexicalDeclaration(uint32_t begin,DeclarationKind kind)6081 GeneralParser<ParseHandler, Unit>::exportLexicalDeclaration(
6082     uint32_t begin, DeclarationKind kind) {
6083   if (!abortIfSyntaxParser()) {
6084     return null();
6085   }
6086 
6087   MOZ_ASSERT(kind == DeclarationKind::Const || kind == DeclarationKind::Let);
6088   MOZ_ASSERT_IF(kind == DeclarationKind::Const,
6089                 anyChars.isCurrentTokenType(TokenKind::Const));
6090   MOZ_ASSERT_IF(kind == DeclarationKind::Let,
6091                 anyChars.isCurrentTokenType(TokenKind::Let));
6092 
6093   ListNodeType kid = lexicalDeclaration(YieldIsName, kind);
6094   if (!kid) {
6095     return null();
6096   }
6097   if (!checkExportedNamesForDeclarationList(kid)) {
6098     return null();
6099   }
6100 
6101   UnaryNodeType node =
6102       handler_.newExportDeclaration(kid, TokenPos(begin, pos().end));
6103   if (!node) {
6104     return null();
6105   }
6106 
6107   if (!processExport(node)) {
6108     return null();
6109   }
6110 
6111   return node;
6112 }
6113 
6114 template <class ParseHandler, typename Unit>
6115 typename ParseHandler::BinaryNodeType
exportDefaultFunctionDeclaration(uint32_t begin,uint32_t toStringStart,FunctionAsyncKind asyncKind)6116 GeneralParser<ParseHandler, Unit>::exportDefaultFunctionDeclaration(
6117     uint32_t begin, uint32_t toStringStart,
6118     FunctionAsyncKind asyncKind /* = SyncFunction */) {
6119   if (!abortIfSyntaxParser()) {
6120     return null();
6121   }
6122 
6123   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Function));
6124 
6125   Node kid =
6126       functionStmt(toStringStart, YieldIsName, AllowDefaultName, asyncKind);
6127   if (!kid) {
6128     return null();
6129   }
6130 
6131   BinaryNodeType node = handler_.newExportDefaultDeclaration(
6132       kid, null(), TokenPos(begin, pos().end));
6133   if (!node) {
6134     return null();
6135   }
6136 
6137   if (!processExport(node)) {
6138     return null();
6139   }
6140 
6141   return node;
6142 }
6143 
6144 template <class ParseHandler, typename Unit>
6145 typename ParseHandler::BinaryNodeType
exportDefaultClassDeclaration(uint32_t begin)6146 GeneralParser<ParseHandler, Unit>::exportDefaultClassDeclaration(
6147     uint32_t begin) {
6148   if (!abortIfSyntaxParser()) {
6149     return null();
6150   }
6151 
6152   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Class));
6153 
6154   ClassNodeType kid =
6155       classDefinition(YieldIsName, ClassStatement, AllowDefaultName);
6156   if (!kid) {
6157     return null();
6158   }
6159 
6160   BinaryNodeType node = handler_.newExportDefaultDeclaration(
6161       kid, null(), TokenPos(begin, pos().end));
6162   if (!node) {
6163     return null();
6164   }
6165 
6166   if (!processExport(node)) {
6167     return null();
6168   }
6169 
6170   return node;
6171 }
6172 
6173 template <class ParseHandler, typename Unit>
6174 typename ParseHandler::BinaryNodeType
exportDefaultAssignExpr(uint32_t begin)6175 GeneralParser<ParseHandler, Unit>::exportDefaultAssignExpr(uint32_t begin) {
6176   if (!abortIfSyntaxParser()) {
6177     return null();
6178   }
6179 
6180   TaggedParserAtomIndex name = TaggedParserAtomIndex::WellKnown::default_();
6181   NameNodeType nameNode = newName(name);
6182   if (!nameNode) {
6183     return null();
6184   }
6185   if (!noteDeclaredName(name, DeclarationKind::Const, pos())) {
6186     return null();
6187   }
6188 
6189   Node kid = assignExpr(InAllowed, YieldIsName, TripledotProhibited);
6190   if (!kid) {
6191     return null();
6192   }
6193 
6194   if (!matchOrInsertSemicolon()) {
6195     return null();
6196   }
6197 
6198   BinaryNodeType node = handler_.newExportDefaultDeclaration(
6199       kid, nameNode, TokenPos(begin, pos().end));
6200   if (!node) {
6201     return null();
6202   }
6203 
6204   if (!processExport(node)) {
6205     return null();
6206   }
6207 
6208   return node;
6209 }
6210 
6211 template <class ParseHandler, typename Unit>
6212 typename ParseHandler::BinaryNodeType
exportDefault(uint32_t begin)6213 GeneralParser<ParseHandler, Unit>::exportDefault(uint32_t begin) {
6214   if (!abortIfSyntaxParser()) {
6215     return null();
6216   }
6217 
6218   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Default));
6219 
6220   TokenKind tt;
6221   if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) {
6222     return null();
6223   }
6224 
6225   if (!checkExportedName(TaggedParserAtomIndex::WellKnown::default_())) {
6226     return null();
6227   }
6228 
6229   switch (tt) {
6230     case TokenKind::Function:
6231       return exportDefaultFunctionDeclaration(begin, pos().begin);
6232 
6233     case TokenKind::Async: {
6234       TokenKind nextSameLine = TokenKind::Eof;
6235       if (!tokenStream.peekTokenSameLine(&nextSameLine)) {
6236         return null();
6237       }
6238 
6239       if (nextSameLine == TokenKind::Function) {
6240         uint32_t toStringStart = pos().begin;
6241         tokenStream.consumeKnownToken(TokenKind::Function);
6242         return exportDefaultFunctionDeclaration(
6243             begin, toStringStart, FunctionAsyncKind::AsyncFunction);
6244       }
6245 
6246       anyChars.ungetToken();
6247       return exportDefaultAssignExpr(begin);
6248     }
6249 
6250     case TokenKind::Class:
6251       return exportDefaultClassDeclaration(begin);
6252 
6253     default:
6254       anyChars.ungetToken();
6255       return exportDefaultAssignExpr(begin);
6256   }
6257 }
6258 
6259 template <class ParseHandler, typename Unit>
6260 typename ParseHandler::Node
exportDeclaration()6261 GeneralParser<ParseHandler, Unit>::exportDeclaration() {
6262   if (!abortIfSyntaxParser()) {
6263     return null();
6264   }
6265 
6266   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Export));
6267 
6268   if (!pc_->atModuleLevel()) {
6269     error(JSMSG_EXPORT_DECL_AT_TOP_LEVEL);
6270     return null();
6271   }
6272 
6273   uint32_t begin = pos().begin;
6274 
6275   TokenKind tt;
6276   if (!tokenStream.getToken(&tt)) {
6277     return null();
6278   }
6279   switch (tt) {
6280     case TokenKind::Mul:
6281       return exportBatch(begin);
6282 
6283     case TokenKind::LeftCurly:
6284       return exportClause(begin);
6285 
6286     case TokenKind::Var:
6287       return exportVariableStatement(begin);
6288 
6289     case TokenKind::Function:
6290       return exportFunctionDeclaration(begin, pos().begin);
6291 
6292     case TokenKind::Async: {
6293       TokenKind nextSameLine = TokenKind::Eof;
6294       if (!tokenStream.peekTokenSameLine(&nextSameLine)) {
6295         return null();
6296       }
6297 
6298       if (nextSameLine == TokenKind::Function) {
6299         uint32_t toStringStart = pos().begin;
6300         tokenStream.consumeKnownToken(TokenKind::Function);
6301         return exportFunctionDeclaration(begin, toStringStart,
6302                                          FunctionAsyncKind::AsyncFunction);
6303       }
6304 
6305       error(JSMSG_DECLARATION_AFTER_EXPORT);
6306       return null();
6307     }
6308 
6309     case TokenKind::Class:
6310       return exportClassDeclaration(begin);
6311 
6312     case TokenKind::Const:
6313       return exportLexicalDeclaration(begin, DeclarationKind::Const);
6314 
6315     case TokenKind::Let:
6316       return exportLexicalDeclaration(begin, DeclarationKind::Let);
6317 
6318     case TokenKind::Default:
6319       return exportDefault(begin);
6320 
6321     default:
6322       error(JSMSG_DECLARATION_AFTER_EXPORT);
6323       return null();
6324   }
6325 }
6326 
6327 template <class ParseHandler, typename Unit>
6328 typename ParseHandler::UnaryNodeType
expressionStatement(YieldHandling yieldHandling,InvokedPrediction invoked)6329 GeneralParser<ParseHandler, Unit>::expressionStatement(
6330     YieldHandling yieldHandling, InvokedPrediction invoked) {
6331   anyChars.ungetToken();
6332   Node pnexpr = expr(InAllowed, yieldHandling, TripledotProhibited,
6333                      /* possibleError = */ nullptr, invoked);
6334   if (!pnexpr) {
6335     return null();
6336   }
6337   if (!matchOrInsertSemicolon()) {
6338     return null();
6339   }
6340   return handler_.newExprStatement(pnexpr, pos().end);
6341 }
6342 
6343 template <class ParseHandler, typename Unit>
6344 typename ParseHandler::Node
consequentOrAlternative(YieldHandling yieldHandling)6345 GeneralParser<ParseHandler, Unit>::consequentOrAlternative(
6346     YieldHandling yieldHandling) {
6347   TokenKind next;
6348   if (!tokenStream.peekToken(&next, TokenStream::SlashIsRegExp)) {
6349     return null();
6350   }
6351 
6352   // Annex B.3.4 says that unbraced FunctionDeclarations under if/else in
6353   // non-strict code act as if they were braced: |if (x) function f() {}|
6354   // parses as |if (x) { function f() {} }|.
6355   //
6356   // Careful!  FunctionDeclaration doesn't include generators or async
6357   // functions.
6358   if (next == TokenKind::Function) {
6359     tokenStream.consumeKnownToken(next, TokenStream::SlashIsRegExp);
6360 
6361     // Parser::statement would handle this, but as this function handles
6362     // every other error case, it seems best to handle this.
6363     if (pc_->sc()->strict()) {
6364       error(JSMSG_FORBIDDEN_AS_STATEMENT, "function declarations");
6365       return null();
6366     }
6367 
6368     TokenKind maybeStar;
6369     if (!tokenStream.peekToken(&maybeStar)) {
6370       return null();
6371     }
6372 
6373     if (maybeStar == TokenKind::Mul) {
6374       error(JSMSG_FORBIDDEN_AS_STATEMENT, "generator declarations");
6375       return null();
6376     }
6377 
6378     ParseContext::Statement stmt(pc_, StatementKind::Block);
6379     ParseContext::Scope scope(this);
6380     if (!scope.init(pc_)) {
6381       return null();
6382     }
6383 
6384     TokenPos funcPos = pos();
6385     Node fun = functionStmt(pos().begin, yieldHandling, NameRequired);
6386     if (!fun) {
6387       return null();
6388     }
6389 
6390     ListNodeType block = handler_.newStatementList(funcPos);
6391     if (!block) {
6392       return null();
6393     }
6394 
6395     handler_.addStatementToList(block, fun);
6396     return finishLexicalScope(scope, block);
6397   }
6398 
6399   return statement(yieldHandling);
6400 }
6401 
6402 template <class ParseHandler, typename Unit>
6403 typename ParseHandler::TernaryNodeType
ifStatement(YieldHandling yieldHandling)6404 GeneralParser<ParseHandler, Unit>::ifStatement(YieldHandling yieldHandling) {
6405   Vector<Node, 4> condList(cx_), thenList(cx_);
6406   Vector<uint32_t, 4> posList(cx_);
6407   Node elseBranch;
6408 
6409   ParseContext::Statement stmt(pc_, StatementKind::If);
6410 
6411   while (true) {
6412     uint32_t begin = pos().begin;
6413 
6414     /* An IF node has three kids: condition, then, and optional else. */
6415     Node cond = condition(InAllowed, yieldHandling);
6416     if (!cond) {
6417       return null();
6418     }
6419 
6420     TokenKind tt;
6421     if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) {
6422       return null();
6423     }
6424 
6425     Node thenBranch = consequentOrAlternative(yieldHandling);
6426     if (!thenBranch) {
6427       return null();
6428     }
6429 
6430     if (!condList.append(cond) || !thenList.append(thenBranch) ||
6431         !posList.append(begin)) {
6432       return null();
6433     }
6434 
6435     bool matched;
6436     if (!tokenStream.matchToken(&matched, TokenKind::Else,
6437                                 TokenStream::SlashIsRegExp)) {
6438       return null();
6439     }
6440     if (matched) {
6441       if (!tokenStream.matchToken(&matched, TokenKind::If,
6442                                   TokenStream::SlashIsRegExp)) {
6443         return null();
6444       }
6445       if (matched) {
6446         continue;
6447       }
6448       elseBranch = consequentOrAlternative(yieldHandling);
6449       if (!elseBranch) {
6450         return null();
6451       }
6452     } else {
6453       elseBranch = null();
6454     }
6455     break;
6456   }
6457 
6458   TernaryNodeType ifNode;
6459   for (int i = condList.length() - 1; i >= 0; i--) {
6460     ifNode = handler_.newIfStatement(posList[i], condList[i], thenList[i],
6461                                      elseBranch);
6462     if (!ifNode) {
6463       return null();
6464     }
6465     elseBranch = ifNode;
6466   }
6467 
6468   return ifNode;
6469 }
6470 
6471 template <class ParseHandler, typename Unit>
6472 typename ParseHandler::BinaryNodeType
doWhileStatement(YieldHandling yieldHandling)6473 GeneralParser<ParseHandler, Unit>::doWhileStatement(
6474     YieldHandling yieldHandling) {
6475   uint32_t begin = pos().begin;
6476   ParseContext::Statement stmt(pc_, StatementKind::DoLoop);
6477   Node body = statement(yieldHandling);
6478   if (!body) {
6479     return null();
6480   }
6481   if (!mustMatchToken(TokenKind::While, JSMSG_WHILE_AFTER_DO)) {
6482     return null();
6483   }
6484   Node cond = condition(InAllowed, yieldHandling);
6485   if (!cond) {
6486     return null();
6487   }
6488 
6489   // The semicolon after do-while is even more optional than most
6490   // semicolons in JS.  Web compat required this by 2004:
6491   //   http://bugzilla.mozilla.org/show_bug.cgi?id=238945
6492   // ES3 and ES5 disagreed, but ES6 conforms to Web reality:
6493   //   https://bugs.ecmascript.org/show_bug.cgi?id=157
6494   // To parse |do {} while (true) false| correctly, use SlashIsRegExp.
6495   bool ignored;
6496   if (!tokenStream.matchToken(&ignored, TokenKind::Semi,
6497                               TokenStream::SlashIsRegExp)) {
6498     return null();
6499   }
6500   return handler_.newDoWhileStatement(body, cond, TokenPos(begin, pos().end));
6501 }
6502 
6503 template <class ParseHandler, typename Unit>
6504 typename ParseHandler::BinaryNodeType
whileStatement(YieldHandling yieldHandling)6505 GeneralParser<ParseHandler, Unit>::whileStatement(YieldHandling yieldHandling) {
6506   uint32_t begin = pos().begin;
6507   ParseContext::Statement stmt(pc_, StatementKind::WhileLoop);
6508   Node cond = condition(InAllowed, yieldHandling);
6509   if (!cond) {
6510     return null();
6511   }
6512   Node body = statement(yieldHandling);
6513   if (!body) {
6514     return null();
6515   }
6516   return handler_.newWhileStatement(begin, cond, body);
6517 }
6518 
6519 template <class ParseHandler, typename Unit>
matchInOrOf(bool * isForInp,bool * isForOfp)6520 bool GeneralParser<ParseHandler, Unit>::matchInOrOf(bool* isForInp,
6521                                                     bool* isForOfp) {
6522   TokenKind tt;
6523   if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) {
6524     return false;
6525   }
6526 
6527   *isForInp = tt == TokenKind::In;
6528   *isForOfp = tt == TokenKind::Of;
6529   if (!*isForInp && !*isForOfp) {
6530     anyChars.ungetToken();
6531   }
6532 
6533   MOZ_ASSERT_IF(*isForInp || *isForOfp, *isForInp != *isForOfp);
6534   return true;
6535 }
6536 
6537 template <class ParseHandler, typename Unit>
forHeadStart(YieldHandling yieldHandling,IteratorKind iterKind,ParseNodeKind * forHeadKind,Node * forInitialPart,Maybe<ParseContext::Scope> & forLoopLexicalScope,Node * forInOrOfExpression)6538 bool GeneralParser<ParseHandler, Unit>::forHeadStart(
6539     YieldHandling yieldHandling, IteratorKind iterKind,
6540     ParseNodeKind* forHeadKind, Node* forInitialPart,
6541     Maybe<ParseContext::Scope>& forLoopLexicalScope,
6542     Node* forInOrOfExpression) {
6543   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftParen));
6544 
6545   TokenKind tt;
6546   if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) {
6547     return false;
6548   }
6549 
6550   // Super-duper easy case: |for (;| is a C-style for-loop with no init
6551   // component.
6552   if (tt == TokenKind::Semi) {
6553     *forInitialPart = null();
6554     *forHeadKind = ParseNodeKind::ForHead;
6555     return true;
6556   }
6557 
6558   // Parsing after |for (var| is also relatively simple (from this method's
6559   // point of view).  No block-related work complicates matters, so delegate
6560   // to Parser::declaration.
6561   if (tt == TokenKind::Var) {
6562     tokenStream.consumeKnownToken(tt, TokenStream::SlashIsRegExp);
6563 
6564     // Pass null for block object because |var| declarations don't use one.
6565     *forInitialPart = declarationList(yieldHandling, ParseNodeKind::VarStmt,
6566                                       forHeadKind, forInOrOfExpression);
6567     return *forInitialPart != null();
6568   }
6569 
6570   // Otherwise we have a lexical declaration or an expression.
6571 
6572   // For-in loop backwards compatibility requires that |let| starting a
6573   // for-loop that's not a (new to ES6) for-of loop, in non-strict mode code,
6574   // parse as an identifier.  (|let| in for-of is always a declaration.)
6575   //
6576   // For-of loops can't start with the token sequence "async of", because that
6577   // leads to a shift-reduce conflict when parsing |for (async of => {};;)| or
6578   // |for (async of [])|.
6579   bool parsingLexicalDeclaration = false;
6580   bool letIsIdentifier = false;
6581   bool startsWithForOf = false;
6582   if (tt == TokenKind::Const) {
6583     parsingLexicalDeclaration = true;
6584     tokenStream.consumeKnownToken(tt, TokenStream::SlashIsRegExp);
6585   } else if (tt == TokenKind::Let) {
6586     // We could have a {For,Lexical}Declaration, or we could have a
6587     // LeftHandSideExpression with lookahead restrictions so it's not
6588     // ambiguous with the former.  Check for a continuation of the former
6589     // to decide which we have.
6590     tokenStream.consumeKnownToken(TokenKind::Let, TokenStream::SlashIsRegExp);
6591 
6592     TokenKind next;
6593     if (!tokenStream.peekToken(&next)) {
6594       return false;
6595     }
6596 
6597     parsingLexicalDeclaration = nextTokenContinuesLetDeclaration(next);
6598     if (!parsingLexicalDeclaration) {
6599       anyChars.ungetToken();
6600       letIsIdentifier = true;
6601     }
6602   } else if (tt == TokenKind::Async && iterKind == IteratorKind::Sync) {
6603     tokenStream.consumeKnownToken(TokenKind::Async, TokenStream::SlashIsRegExp);
6604 
6605     TokenKind next;
6606     if (!tokenStream.peekToken(&next)) {
6607       return false;
6608     }
6609 
6610     if (next == TokenKind::Of) {
6611       startsWithForOf = true;
6612     }
6613     anyChars.ungetToken();
6614   }
6615 
6616   if (parsingLexicalDeclaration) {
6617     forLoopLexicalScope.emplace(this);
6618     if (!forLoopLexicalScope->init(pc_)) {
6619       return false;
6620     }
6621 
6622     // Push a temporary ForLoopLexicalHead Statement that allows for
6623     // lexical declarations, as they are usually allowed only in braced
6624     // statements.
6625     ParseContext::Statement forHeadStmt(pc_, StatementKind::ForLoopLexicalHead);
6626 
6627     *forInitialPart =
6628         declarationList(yieldHandling,
6629                         tt == TokenKind::Const ? ParseNodeKind::ConstDecl
6630                                                : ParseNodeKind::LetDecl,
6631                         forHeadKind, forInOrOfExpression);
6632     return *forInitialPart != null();
6633   }
6634 
6635   uint32_t exprOffset;
6636   if (!tokenStream.peekOffset(&exprOffset, TokenStream::SlashIsRegExp)) {
6637     return false;
6638   }
6639 
6640   // Finally, handle for-loops that start with expressions.  Pass
6641   // |InProhibited| so that |in| isn't parsed in a RelationalExpression as a
6642   // binary operator.  |in| makes it a for-in loop, *not* an |in| expression.
6643   PossibleError possibleError(*this);
6644   *forInitialPart =
6645       expr(InProhibited, yieldHandling, TripledotProhibited, &possibleError);
6646   if (!*forInitialPart) {
6647     return false;
6648   }
6649 
6650   bool isForIn, isForOf;
6651   if (!matchInOrOf(&isForIn, &isForOf)) {
6652     return false;
6653   }
6654 
6655   // If we don't encounter 'in'/'of', we have a for(;;) loop.  We've handled
6656   // the init expression; the caller handles the rest.
6657   if (!isForIn && !isForOf) {
6658     if (!possibleError.checkForExpressionError()) {
6659       return false;
6660     }
6661 
6662     *forHeadKind = ParseNodeKind::ForHead;
6663     return true;
6664   }
6665 
6666   MOZ_ASSERT(isForIn != isForOf);
6667 
6668   // In a for-of loop, 'let' that starts the loop head is a |let| keyword,
6669   // per the [lookahead ≠ let] restriction on the LeftHandSideExpression
6670   // variant of such loops.  Expressions that start with |let| can't be used
6671   // here.
6672   //
6673   //   var let = {};
6674   //   for (let.prop of [1]) // BAD
6675   //     break;
6676   //
6677   // See ES6 13.7.
6678   if (isForOf && letIsIdentifier) {
6679     errorAt(exprOffset, JSMSG_BAD_STARTING_FOROF_LHS, "let");
6680     return false;
6681   }
6682 
6683   // In a for-of loop, the LeftHandSideExpression isn't allowed to be an
6684   // identifier named "async" per the [lookahead ≠ async of] restriction.
6685   if (isForOf && startsWithForOf) {
6686     errorAt(exprOffset, JSMSG_BAD_STARTING_FOROF_LHS, "async of");
6687     return false;
6688   }
6689 
6690   *forHeadKind = isForIn ? ParseNodeKind::ForIn : ParseNodeKind::ForOf;
6691 
6692   // Verify the left-hand side expression doesn't have a forbidden form.
6693   if (handler_.isUnparenthesizedDestructuringPattern(*forInitialPart)) {
6694     if (!possibleError.checkForDestructuringErrorOrWarning()) {
6695       return false;
6696     }
6697   } else if (handler_.isName(*forInitialPart)) {
6698     if (const char* chars = nameIsArgumentsOrEval(*forInitialPart)) {
6699       // |chars| is "arguments" or "eval" here.
6700       if (!strictModeErrorAt(exprOffset, JSMSG_BAD_STRICT_ASSIGN, chars)) {
6701         return false;
6702       }
6703     }
6704   } else if (handler_.isPropertyOrPrivateMemberAccess(*forInitialPart)) {
6705     // Permitted: no additional testing/fixup needed.
6706   } else if (handler_.isFunctionCall(*forInitialPart)) {
6707     if (!strictModeErrorAt(exprOffset, JSMSG_BAD_FOR_LEFTSIDE)) {
6708       return false;
6709     }
6710   } else {
6711     errorAt(exprOffset, JSMSG_BAD_FOR_LEFTSIDE);
6712     return false;
6713   }
6714 
6715   if (!possibleError.checkForExpressionError()) {
6716     return false;
6717   }
6718 
6719   // Finally, parse the iterated expression, making the for-loop's closing
6720   // ')' the next token.
6721   *forInOrOfExpression = expressionAfterForInOrOf(*forHeadKind, yieldHandling);
6722   return *forInOrOfExpression != null();
6723 }
6724 
6725 template <class ParseHandler, typename Unit>
forStatement(YieldHandling yieldHandling)6726 typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::forStatement(
6727     YieldHandling yieldHandling) {
6728   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::For));
6729 
6730   uint32_t begin = pos().begin;
6731 
6732   ParseContext::Statement stmt(pc_, StatementKind::ForLoop);
6733 
6734   IteratorKind iterKind = IteratorKind::Sync;
6735   unsigned iflags = 0;
6736 
6737   if (pc_->isAsync() || pc_->sc()->isModuleContext()) {
6738     bool matched;
6739     if (!tokenStream.matchToken(&matched, TokenKind::Await)) {
6740       return null();
6741     }
6742 
6743     // If we come across a top level await here, mark the module as async.
6744     if (matched && pc_->sc()->isModuleContext() && !pc_->isAsync()) {
6745       pc_->sc()->asModuleContext()->setIsAsync();
6746       MOZ_ASSERT(pc_->isAsync());
6747     }
6748 
6749     if (matched) {
6750       iflags |= JSITER_FORAWAITOF;
6751       iterKind = IteratorKind::Async;
6752     }
6753   }
6754 
6755   if (!mustMatchToken(TokenKind::LeftParen, [this](TokenKind actual) {
6756         this->error((actual == TokenKind::Await && !this->pc_->isAsync())
6757                         ? JSMSG_FOR_AWAIT_OUTSIDE_ASYNC
6758                         : JSMSG_PAREN_AFTER_FOR);
6759       })) {
6760     return null();
6761   }
6762 
6763   // ParseNodeKind::ForHead, ParseNodeKind::ForIn, or
6764   // ParseNodeKind::ForOf depending on the loop type.
6765   ParseNodeKind headKind;
6766 
6767   // |x| in either |for (x; ...; ...)| or |for (x in/of ...)|.
6768   Node startNode;
6769 
6770   // The next two variables are used to implement `for (let/const ...)`.
6771   //
6772   // We generate an implicit block, wrapping the whole loop, to store loop
6773   // variables declared this way. Note that if the loop uses `for (var...)`
6774   // instead, those variables go on some existing enclosing scope, so no
6775   // implicit block scope is created.
6776   //
6777   // Both variables remain null/none if the loop is any other form.
6778 
6779   // The static block scope for the implicit block scope.
6780   Maybe<ParseContext::Scope> forLoopLexicalScope;
6781 
6782   // The expression being iterated over, for for-in/of loops only.  Unused
6783   // for for(;;) loops.
6784   Node iteratedExpr;
6785 
6786   // Parse the entirety of the loop-head for a for-in/of loop (so the next
6787   // token is the closing ')'):
6788   //
6789   //   for (... in/of ...) ...
6790   //                     ^next token
6791   //
6792   // ...OR, parse up to the first ';' in a C-style for-loop:
6793   //
6794   //   for (...; ...; ...) ...
6795   //           ^next token
6796   //
6797   // In either case the subsequent token can be consistently accessed using
6798   // TokenStream::SlashIsDiv semantics.
6799   if (!forHeadStart(yieldHandling, iterKind, &headKind, &startNode,
6800                     forLoopLexicalScope, &iteratedExpr)) {
6801     return null();
6802   }
6803 
6804   MOZ_ASSERT(headKind == ParseNodeKind::ForIn ||
6805              headKind == ParseNodeKind::ForOf ||
6806              headKind == ParseNodeKind::ForHead);
6807 
6808   if (iterKind == IteratorKind::Async && headKind != ParseNodeKind::ForOf) {
6809     errorAt(begin, JSMSG_FOR_AWAIT_NOT_OF);
6810     return null();
6811   }
6812 
6813   TernaryNodeType forHead;
6814   if (headKind == ParseNodeKind::ForHead) {
6815     Node init = startNode;
6816 
6817     // Look for an operand: |for (;| means we might have already examined
6818     // this semicolon with that modifier.
6819     if (!mustMatchToken(TokenKind::Semi, JSMSG_SEMI_AFTER_FOR_INIT)) {
6820       return null();
6821     }
6822 
6823     TokenKind tt;
6824     if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) {
6825       return null();
6826     }
6827 
6828     Node test;
6829     if (tt == TokenKind::Semi) {
6830       test = null();
6831     } else {
6832       test = expr(InAllowed, yieldHandling, TripledotProhibited);
6833       if (!test) {
6834         return null();
6835       }
6836     }
6837 
6838     if (!mustMatchToken(TokenKind::Semi, JSMSG_SEMI_AFTER_FOR_COND)) {
6839       return null();
6840     }
6841 
6842     if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) {
6843       return null();
6844     }
6845 
6846     Node update;
6847     if (tt == TokenKind::RightParen) {
6848       update = null();
6849     } else {
6850       update = expr(InAllowed, yieldHandling, TripledotProhibited);
6851       if (!update) {
6852         return null();
6853       }
6854     }
6855 
6856     if (!mustMatchToken(TokenKind::RightParen, JSMSG_PAREN_AFTER_FOR_CTRL)) {
6857       return null();
6858     }
6859 
6860     TokenPos headPos(begin, pos().end);
6861     forHead = handler_.newForHead(init, test, update, headPos);
6862     if (!forHead) {
6863       return null();
6864     }
6865   } else {
6866     MOZ_ASSERT(headKind == ParseNodeKind::ForIn ||
6867                headKind == ParseNodeKind::ForOf);
6868 
6869     // |target| is the LeftHandSideExpression or declaration to which the
6870     // per-iteration value (an arbitrary value exposed by the iteration
6871     // protocol, or a string naming a property) is assigned.
6872     Node target = startNode;
6873 
6874     // Parse the rest of the for-in/of head.
6875     if (headKind == ParseNodeKind::ForIn) {
6876       stmt.refineForKind(StatementKind::ForInLoop);
6877     } else {
6878       stmt.refineForKind(StatementKind::ForOfLoop);
6879     }
6880 
6881     // Parser::declaration consumed everything up to the closing ')'.  That
6882     // token follows an {Assignment,}Expression and so must be interpreted
6883     // as an operand to be consistent with normal expression tokenizing.
6884     if (!mustMatchToken(TokenKind::RightParen, JSMSG_PAREN_AFTER_FOR_CTRL)) {
6885       return null();
6886     }
6887 
6888     TokenPos headPos(begin, pos().end);
6889     forHead =
6890         handler_.newForInOrOfHead(headKind, target, iteratedExpr, headPos);
6891     if (!forHead) {
6892       return null();
6893     }
6894   }
6895 
6896   Node body = statement(yieldHandling);
6897   if (!body) {
6898     return null();
6899   }
6900 
6901   ForNodeType forLoop = handler_.newForStatement(begin, forHead, body, iflags);
6902   if (!forLoop) {
6903     return null();
6904   }
6905 
6906   if (forLoopLexicalScope) {
6907     return finishLexicalScope(*forLoopLexicalScope, forLoop);
6908   }
6909 
6910   return forLoop;
6911 }
6912 
6913 template <class ParseHandler, typename Unit>
6914 typename ParseHandler::SwitchStatementType
switchStatement(YieldHandling yieldHandling)6915 GeneralParser<ParseHandler, Unit>::switchStatement(
6916     YieldHandling yieldHandling) {
6917   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Switch));
6918   uint32_t begin = pos().begin;
6919 
6920   if (!mustMatchToken(TokenKind::LeftParen, JSMSG_PAREN_BEFORE_SWITCH)) {
6921     return null();
6922   }
6923 
6924   Node discriminant =
6925       exprInParens(InAllowed, yieldHandling, TripledotProhibited);
6926   if (!discriminant) {
6927     return null();
6928   }
6929 
6930   if (!mustMatchToken(TokenKind::RightParen, JSMSG_PAREN_AFTER_SWITCH)) {
6931     return null();
6932   }
6933   if (!mustMatchToken(TokenKind::LeftCurly, JSMSG_CURLY_BEFORE_SWITCH)) {
6934     return null();
6935   }
6936 
6937   ParseContext::Statement stmt(pc_, StatementKind::Switch);
6938   ParseContext::Scope scope(this);
6939   if (!scope.init(pc_)) {
6940     return null();
6941   }
6942 
6943   ListNodeType caseList = handler_.newStatementList(pos());
6944   if (!caseList) {
6945     return null();
6946   }
6947 
6948   bool seenDefault = false;
6949   TokenKind tt;
6950   while (true) {
6951     if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) {
6952       return null();
6953     }
6954     if (tt == TokenKind::RightCurly) {
6955       break;
6956     }
6957     uint32_t caseBegin = pos().begin;
6958 
6959     Node caseExpr;
6960     switch (tt) {
6961       case TokenKind::Default:
6962         if (seenDefault) {
6963           error(JSMSG_TOO_MANY_DEFAULTS);
6964           return null();
6965         }
6966         seenDefault = true;
6967         caseExpr = null();  // The default case has pn_left == nullptr.
6968         break;
6969 
6970       case TokenKind::Case:
6971         caseExpr = expr(InAllowed, yieldHandling, TripledotProhibited);
6972         if (!caseExpr) {
6973           return null();
6974         }
6975         break;
6976 
6977       default:
6978         error(JSMSG_BAD_SWITCH);
6979         return null();
6980     }
6981 
6982     if (!mustMatchToken(TokenKind::Colon, JSMSG_COLON_AFTER_CASE)) {
6983       return null();
6984     }
6985 
6986     ListNodeType body = handler_.newStatementList(pos());
6987     if (!body) {
6988       return null();
6989     }
6990 
6991     bool afterReturn = false;
6992     bool warnedAboutStatementsAfterReturn = false;
6993     uint32_t statementBegin = 0;
6994     while (true) {
6995       if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) {
6996         return null();
6997       }
6998       if (tt == TokenKind::RightCurly || tt == TokenKind::Case ||
6999           tt == TokenKind::Default) {
7000         break;
7001       }
7002       if (afterReturn) {
7003         if (!tokenStream.peekOffset(&statementBegin,
7004                                     TokenStream::SlashIsRegExp)) {
7005           return null();
7006         }
7007       }
7008       Node stmt = statementListItem(yieldHandling);
7009       if (!stmt) {
7010         return null();
7011       }
7012       if (!warnedAboutStatementsAfterReturn) {
7013         if (afterReturn) {
7014           if (!handler_.isStatementPermittedAfterReturnStatement(stmt)) {
7015             if (!warningAt(statementBegin, JSMSG_STMT_AFTER_RETURN)) {
7016               return null();
7017             }
7018 
7019             warnedAboutStatementsAfterReturn = true;
7020           }
7021         } else if (handler_.isReturnStatement(stmt)) {
7022           afterReturn = true;
7023         }
7024       }
7025       handler_.addStatementToList(body, stmt);
7026     }
7027 
7028     CaseClauseType caseClause =
7029         handler_.newCaseOrDefault(caseBegin, caseExpr, body);
7030     if (!caseClause) {
7031       return null();
7032     }
7033     handler_.addCaseStatementToList(caseList, caseClause);
7034   }
7035 
7036   LexicalScopeNodeType lexicalForCaseList = finishLexicalScope(scope, caseList);
7037   if (!lexicalForCaseList) {
7038     return null();
7039   }
7040 
7041   handler_.setEndPosition(lexicalForCaseList, pos().end);
7042 
7043   return handler_.newSwitchStatement(begin, discriminant, lexicalForCaseList,
7044                                      seenDefault);
7045 }
7046 
7047 template <class ParseHandler, typename Unit>
7048 typename ParseHandler::ContinueStatementType
continueStatement(YieldHandling yieldHandling)7049 GeneralParser<ParseHandler, Unit>::continueStatement(
7050     YieldHandling yieldHandling) {
7051   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Continue));
7052   uint32_t begin = pos().begin;
7053 
7054   TaggedParserAtomIndex label;
7055   if (!matchLabel(yieldHandling, &label)) {
7056     return null();
7057   }
7058 
7059   auto validity = pc_->checkContinueStatement(label);
7060   if (validity.isErr()) {
7061     switch (validity.unwrapErr()) {
7062       case ParseContext::ContinueStatementError::NotInALoop:
7063         errorAt(begin, JSMSG_BAD_CONTINUE);
7064         break;
7065       case ParseContext::ContinueStatementError::LabelNotFound:
7066         error(JSMSG_LABEL_NOT_FOUND);
7067         break;
7068     }
7069     return null();
7070   }
7071 
7072   if (!matchOrInsertSemicolon()) {
7073     return null();
7074   }
7075 
7076   return handler_.newContinueStatement(label, TokenPos(begin, pos().end));
7077 }
7078 
7079 template <class ParseHandler, typename Unit>
7080 typename ParseHandler::BreakStatementType
breakStatement(YieldHandling yieldHandling)7081 GeneralParser<ParseHandler, Unit>::breakStatement(YieldHandling yieldHandling) {
7082   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Break));
7083   uint32_t begin = pos().begin;
7084 
7085   TaggedParserAtomIndex label;
7086   if (!matchLabel(yieldHandling, &label)) {
7087     return null();
7088   }
7089 
7090   auto validity = pc_->checkBreakStatement(label);
7091   if (validity.isErr()) {
7092     switch (validity.unwrapErr()) {
7093       case ParseContext::BreakStatementError::ToughBreak:
7094         errorAt(begin, JSMSG_TOUGH_BREAK);
7095         return null();
7096       case ParseContext::BreakStatementError::LabelNotFound:
7097         error(JSMSG_LABEL_NOT_FOUND);
7098         return null();
7099     }
7100   }
7101 
7102   if (!matchOrInsertSemicolon()) {
7103     return null();
7104   }
7105 
7106   return handler_.newBreakStatement(label, TokenPos(begin, pos().end));
7107 }
7108 
7109 template <class ParseHandler, typename Unit>
7110 typename ParseHandler::UnaryNodeType
returnStatement(YieldHandling yieldHandling)7111 GeneralParser<ParseHandler, Unit>::returnStatement(
7112     YieldHandling yieldHandling) {
7113   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Return));
7114   uint32_t begin = pos().begin;
7115 
7116   MOZ_ASSERT(pc_->isFunctionBox());
7117 
7118   // Parse an optional operand.
7119   //
7120   // This is ugly, but we don't want to require a semicolon.
7121   Node exprNode;
7122   TokenKind tt = TokenKind::Eof;
7123   if (!tokenStream.peekTokenSameLine(&tt, TokenStream::SlashIsRegExp)) {
7124     return null();
7125   }
7126   switch (tt) {
7127     case TokenKind::Eol:
7128     case TokenKind::Eof:
7129     case TokenKind::Semi:
7130     case TokenKind::RightCurly:
7131       exprNode = null();
7132       break;
7133     default: {
7134       exprNode = expr(InAllowed, yieldHandling, TripledotProhibited);
7135       if (!exprNode) {
7136         return null();
7137       }
7138     }
7139   }
7140 
7141   if (!matchOrInsertSemicolon()) {
7142     return null();
7143   }
7144 
7145   return handler_.newReturnStatement(exprNode, TokenPos(begin, pos().end));
7146 }
7147 
7148 template <class ParseHandler, typename Unit>
7149 typename ParseHandler::UnaryNodeType
yieldExpression(InHandling inHandling)7150 GeneralParser<ParseHandler, Unit>::yieldExpression(InHandling inHandling) {
7151   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Yield));
7152   uint32_t begin = pos().begin;
7153 
7154   MOZ_ASSERT(pc_->isGenerator());
7155   MOZ_ASSERT(pc_->isFunctionBox());
7156 
7157   pc_->lastYieldOffset = begin;
7158 
7159   Node exprNode;
7160   ParseNodeKind kind = ParseNodeKind::YieldExpr;
7161   TokenKind tt = TokenKind::Eof;
7162   if (!tokenStream.peekTokenSameLine(&tt, TokenStream::SlashIsRegExp)) {
7163     return null();
7164   }
7165   switch (tt) {
7166     // TokenKind::Eol is special; it implements the [no LineTerminator here]
7167     // quirk in the grammar.
7168     case TokenKind::Eol:
7169     // The rest of these make up the complete set of tokens that can
7170     // appear after any of the places where AssignmentExpression is used
7171     // throughout the grammar.  Conveniently, none of them can also be the
7172     // start an expression.
7173     case TokenKind::Eof:
7174     case TokenKind::Semi:
7175     case TokenKind::RightCurly:
7176     case TokenKind::RightBracket:
7177     case TokenKind::RightParen:
7178     case TokenKind::Colon:
7179     case TokenKind::Comma:
7180     case TokenKind::In:  // Annex B.3.6 `for (x = yield in y) ;`
7181       // No value.
7182       exprNode = null();
7183       break;
7184     case TokenKind::Mul:
7185       kind = ParseNodeKind::YieldStarExpr;
7186       tokenStream.consumeKnownToken(TokenKind::Mul, TokenStream::SlashIsRegExp);
7187       [[fallthrough]];
7188     default:
7189       exprNode = assignExpr(inHandling, YieldIsKeyword, TripledotProhibited);
7190       if (!exprNode) {
7191         return null();
7192       }
7193   }
7194   if (kind == ParseNodeKind::YieldStarExpr) {
7195     return handler_.newYieldStarExpression(begin, exprNode);
7196   }
7197   return handler_.newYieldExpression(begin, exprNode);
7198 }
7199 
7200 template <class ParseHandler, typename Unit>
7201 typename ParseHandler::BinaryNodeType
withStatement(YieldHandling yieldHandling)7202 GeneralParser<ParseHandler, Unit>::withStatement(YieldHandling yieldHandling) {
7203   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::With));
7204   uint32_t begin = pos().begin;
7205 
7206   if (pc_->sc()->strict()) {
7207     if (!strictModeError(JSMSG_STRICT_CODE_WITH)) {
7208       return null();
7209     }
7210   }
7211 
7212   if (!mustMatchToken(TokenKind::LeftParen, JSMSG_PAREN_BEFORE_WITH)) {
7213     return null();
7214   }
7215 
7216   Node objectExpr = exprInParens(InAllowed, yieldHandling, TripledotProhibited);
7217   if (!objectExpr) {
7218     return null();
7219   }
7220 
7221   if (!mustMatchToken(TokenKind::RightParen, JSMSG_PAREN_AFTER_WITH)) {
7222     return null();
7223   }
7224 
7225   Node innerBlock;
7226   {
7227     ParseContext::Statement stmt(pc_, StatementKind::With);
7228     innerBlock = statement(yieldHandling);
7229     if (!innerBlock) {
7230       return null();
7231     }
7232   }
7233 
7234   pc_->sc()->setBindingsAccessedDynamically();
7235 
7236   return handler_.newWithStatement(begin, objectExpr, innerBlock);
7237 }
7238 
7239 template <class ParseHandler, typename Unit>
labeledItem(YieldHandling yieldHandling)7240 typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::labeledItem(
7241     YieldHandling yieldHandling) {
7242   TokenKind tt;
7243   if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) {
7244     return null();
7245   }
7246 
7247   if (tt == TokenKind::Function) {
7248     TokenKind next;
7249     if (!tokenStream.peekToken(&next)) {
7250       return null();
7251     }
7252 
7253     // GeneratorDeclaration is only matched by HoistableDeclaration in
7254     // StatementListItem, so generators can't be inside labels.
7255     if (next == TokenKind::Mul) {
7256       error(JSMSG_GENERATOR_LABEL);
7257       return null();
7258     }
7259 
7260     // Per 13.13.1 it's a syntax error if LabelledItem: FunctionDeclaration
7261     // is ever matched.  Per Annex B.3.2 that modifies this text, this
7262     // applies only to strict mode code.
7263     if (pc_->sc()->strict()) {
7264       error(JSMSG_FUNCTION_LABEL);
7265       return null();
7266     }
7267 
7268     return functionStmt(pos().begin, yieldHandling, NameRequired);
7269   }
7270 
7271   anyChars.ungetToken();
7272   return statement(yieldHandling);
7273 }
7274 
7275 template <class ParseHandler, typename Unit>
7276 typename ParseHandler::LabeledStatementType
labeledStatement(YieldHandling yieldHandling)7277 GeneralParser<ParseHandler, Unit>::labeledStatement(
7278     YieldHandling yieldHandling) {
7279   TaggedParserAtomIndex label = labelIdentifier(yieldHandling);
7280   if (!label) {
7281     return null();
7282   }
7283 
7284   auto hasSameLabel = [&label](ParseContext::LabelStatement* stmt) {
7285     return stmt->label() == label;
7286   };
7287 
7288   uint32_t begin = pos().begin;
7289 
7290   if (pc_->template findInnermostStatement<ParseContext::LabelStatement>(
7291           hasSameLabel)) {
7292     errorAt(begin, JSMSG_DUPLICATE_LABEL);
7293     return null();
7294   }
7295 
7296   tokenStream.consumeKnownToken(TokenKind::Colon);
7297 
7298   /* Push a label struct and parse the statement. */
7299   ParseContext::LabelStatement stmt(pc_, label);
7300   Node pn = labeledItem(yieldHandling);
7301   if (!pn) {
7302     return null();
7303   }
7304 
7305   return handler_.newLabeledStatement(label, pn, begin);
7306 }
7307 
7308 template <class ParseHandler, typename Unit>
7309 typename ParseHandler::UnaryNodeType
throwStatement(YieldHandling yieldHandling)7310 GeneralParser<ParseHandler, Unit>::throwStatement(YieldHandling yieldHandling) {
7311   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Throw));
7312   uint32_t begin = pos().begin;
7313 
7314   /* ECMA-262 Edition 3 says 'throw [no LineTerminator here] Expr'. */
7315   TokenKind tt = TokenKind::Eof;
7316   if (!tokenStream.peekTokenSameLine(&tt, TokenStream::SlashIsRegExp)) {
7317     return null();
7318   }
7319   if (tt == TokenKind::Eof || tt == TokenKind::Semi ||
7320       tt == TokenKind::RightCurly) {
7321     error(JSMSG_MISSING_EXPR_AFTER_THROW);
7322     return null();
7323   }
7324   if (tt == TokenKind::Eol) {
7325     error(JSMSG_LINE_BREAK_AFTER_THROW);
7326     return null();
7327   }
7328 
7329   Node throwExpr = expr(InAllowed, yieldHandling, TripledotProhibited);
7330   if (!throwExpr) {
7331     return null();
7332   }
7333 
7334   if (!matchOrInsertSemicolon()) {
7335     return null();
7336   }
7337 
7338   return handler_.newThrowStatement(throwExpr, TokenPos(begin, pos().end));
7339 }
7340 
7341 template <class ParseHandler, typename Unit>
7342 typename ParseHandler::TernaryNodeType
tryStatement(YieldHandling yieldHandling)7343 GeneralParser<ParseHandler, Unit>::tryStatement(YieldHandling yieldHandling) {
7344   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Try));
7345   uint32_t begin = pos().begin;
7346 
7347   /*
7348    * try nodes are ternary.
7349    * kid1 is the try statement
7350    * kid2 is the catch node list or null
7351    * kid3 is the finally statement
7352    *
7353    * catch nodes are binary.
7354    * left is the catch-name/pattern or null
7355    * right is the catch block
7356    *
7357    * catch lvalue nodes are either:
7358    *   a single identifier
7359    *   TokenKind::RightBracket for a destructuring left-hand side
7360    *   TokenKind::RightCurly for a destructuring left-hand side
7361    *
7362    * finally nodes are TokenKind::LeftCurly statement lists.
7363    */
7364 
7365   Node innerBlock;
7366   {
7367     if (!mustMatchToken(TokenKind::LeftCurly, JSMSG_CURLY_BEFORE_TRY)) {
7368       return null();
7369     }
7370 
7371     uint32_t openedPos = pos().begin;
7372 
7373     ParseContext::Statement stmt(pc_, StatementKind::Try);
7374     ParseContext::Scope scope(this);
7375     if (!scope.init(pc_)) {
7376       return null();
7377     }
7378 
7379     innerBlock = statementList(yieldHandling);
7380     if (!innerBlock) {
7381       return null();
7382     }
7383 
7384     innerBlock = finishLexicalScope(scope, innerBlock);
7385     if (!innerBlock) {
7386       return null();
7387     }
7388 
7389     if (!mustMatchToken(
7390             TokenKind::RightCurly, [this, openedPos](TokenKind actual) {
7391               this->reportMissingClosing(JSMSG_CURLY_AFTER_TRY,
7392                                          JSMSG_CURLY_OPENED, openedPos);
7393             })) {
7394       return null();
7395     }
7396   }
7397 
7398   LexicalScopeNodeType catchScope = null();
7399   TokenKind tt;
7400   if (!tokenStream.getToken(&tt)) {
7401     return null();
7402   }
7403   if (tt == TokenKind::Catch) {
7404     /*
7405      * Create a lexical scope node around the whole catch clause,
7406      * including the head.
7407      */
7408     ParseContext::Statement stmt(pc_, StatementKind::Catch);
7409     ParseContext::Scope scope(this);
7410     if (!scope.init(pc_)) {
7411       return null();
7412     }
7413 
7414     /*
7415      * Legal catch forms are:
7416      *   catch (lhs) {
7417      *   catch {
7418      * where lhs is a name or a destructuring left-hand side.
7419      */
7420     bool omittedBinding;
7421     if (!tokenStream.matchToken(&omittedBinding, TokenKind::LeftCurly)) {
7422       return null();
7423     }
7424 
7425     Node catchName;
7426     if (omittedBinding) {
7427       catchName = null();
7428     } else {
7429       if (!mustMatchToken(TokenKind::LeftParen, JSMSG_PAREN_BEFORE_CATCH)) {
7430         return null();
7431       }
7432 
7433       if (!tokenStream.getToken(&tt)) {
7434         return null();
7435       }
7436       switch (tt) {
7437         case TokenKind::LeftBracket:
7438         case TokenKind::LeftCurly:
7439           catchName = destructuringDeclaration(DeclarationKind::CatchParameter,
7440                                                yieldHandling, tt);
7441           if (!catchName) {
7442             return null();
7443           }
7444           break;
7445 
7446         default: {
7447           if (!TokenKindIsPossibleIdentifierName(tt)) {
7448             error(JSMSG_CATCH_IDENTIFIER);
7449             return null();
7450           }
7451 
7452           catchName = bindingIdentifier(DeclarationKind::SimpleCatchParameter,
7453                                         yieldHandling);
7454           if (!catchName) {
7455             return null();
7456           }
7457           break;
7458         }
7459       }
7460 
7461       if (!mustMatchToken(TokenKind::RightParen, JSMSG_PAREN_AFTER_CATCH)) {
7462         return null();
7463       }
7464 
7465       if (!mustMatchToken(TokenKind::LeftCurly, JSMSG_CURLY_BEFORE_CATCH)) {
7466         return null();
7467       }
7468     }
7469 
7470     LexicalScopeNodeType catchBody = catchBlockStatement(yieldHandling, scope);
7471     if (!catchBody) {
7472       return null();
7473     }
7474 
7475     catchScope = finishLexicalScope(scope, catchBody);
7476     if (!catchScope) {
7477       return null();
7478     }
7479 
7480     if (!handler_.setupCatchScope(catchScope, catchName, catchBody)) {
7481       return null();
7482     }
7483     handler_.setEndPosition(catchScope, pos().end);
7484 
7485     if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) {
7486       return null();
7487     }
7488   }
7489 
7490   Node finallyBlock = null();
7491 
7492   if (tt == TokenKind::Finally) {
7493     if (!mustMatchToken(TokenKind::LeftCurly, JSMSG_CURLY_BEFORE_FINALLY)) {
7494       return null();
7495     }
7496 
7497     uint32_t openedPos = pos().begin;
7498 
7499     ParseContext::Statement stmt(pc_, StatementKind::Finally);
7500     ParseContext::Scope scope(this);
7501     if (!scope.init(pc_)) {
7502       return null();
7503     }
7504 
7505     finallyBlock = statementList(yieldHandling);
7506     if (!finallyBlock) {
7507       return null();
7508     }
7509 
7510     finallyBlock = finishLexicalScope(scope, finallyBlock);
7511     if (!finallyBlock) {
7512       return null();
7513     }
7514 
7515     if (!mustMatchToken(
7516             TokenKind::RightCurly, [this, openedPos](TokenKind actual) {
7517               this->reportMissingClosing(JSMSG_CURLY_AFTER_FINALLY,
7518                                          JSMSG_CURLY_OPENED, openedPos);
7519             })) {
7520       return null();
7521     }
7522   } else {
7523     anyChars.ungetToken();
7524   }
7525   if (!catchScope && !finallyBlock) {
7526     error(JSMSG_CATCH_OR_FINALLY);
7527     return null();
7528   }
7529 
7530   return handler_.newTryStatement(begin, innerBlock, catchScope, finallyBlock);
7531 }
7532 
7533 template <class ParseHandler, typename Unit>
7534 typename ParseHandler::LexicalScopeNodeType
catchBlockStatement(YieldHandling yieldHandling,ParseContext::Scope & catchParamScope)7535 GeneralParser<ParseHandler, Unit>::catchBlockStatement(
7536     YieldHandling yieldHandling, ParseContext::Scope& catchParamScope) {
7537   uint32_t openedPos = pos().begin;
7538 
7539   ParseContext::Statement stmt(pc_, StatementKind::Block);
7540 
7541   // ES 13.15.7 CatchClauseEvaluation
7542   //
7543   // Step 8 means that the body of a catch block always has an additional
7544   // lexical scope.
7545   ParseContext::Scope scope(this);
7546   if (!scope.init(pc_)) {
7547     return null();
7548   }
7549 
7550   // The catch parameter names cannot be redeclared inside the catch
7551   // block, so declare the name in the inner scope.
7552   if (!scope.addCatchParameters(pc_, catchParamScope)) {
7553     return null();
7554   }
7555 
7556   ListNodeType list = statementList(yieldHandling);
7557   if (!list) {
7558     return null();
7559   }
7560 
7561   if (!mustMatchToken(
7562           TokenKind::RightCurly, [this, openedPos](TokenKind actual) {
7563             this->reportMissingClosing(JSMSG_CURLY_AFTER_CATCH,
7564                                        JSMSG_CURLY_OPENED, openedPos);
7565           })) {
7566     return null();
7567   }
7568 
7569   // The catch parameter names are not bound in the body scope, so remove
7570   // them before generating bindings.
7571   scope.removeCatchParameters(pc_, catchParamScope);
7572   return finishLexicalScope(scope, list);
7573 }
7574 
7575 template <class ParseHandler, typename Unit>
7576 typename ParseHandler::DebuggerStatementType
debuggerStatement()7577 GeneralParser<ParseHandler, Unit>::debuggerStatement() {
7578   TokenPos p;
7579   p.begin = pos().begin;
7580   if (!matchOrInsertSemicolon()) {
7581     return null();
7582   }
7583   p.end = pos().end;
7584 
7585   return handler_.newDebuggerStatement(p);
7586 }
7587 
ToAccessorType(PropertyType propType)7588 static AccessorType ToAccessorType(PropertyType propType) {
7589   switch (propType) {
7590     case PropertyType::Getter:
7591       return AccessorType::Getter;
7592     case PropertyType::Setter:
7593       return AccessorType::Setter;
7594     case PropertyType::Normal:
7595     case PropertyType::Method:
7596     case PropertyType::GeneratorMethod:
7597     case PropertyType::AsyncMethod:
7598     case PropertyType::AsyncGeneratorMethod:
7599     case PropertyType::Constructor:
7600     case PropertyType::DerivedConstructor:
7601       return AccessorType::None;
7602     default:
7603       MOZ_CRASH("unexpected property type");
7604   }
7605 }
7606 
7607 template <class ParseHandler, typename Unit>
classMember(YieldHandling yieldHandling,const ParseContext::ClassStatement & classStmt,TaggedParserAtomIndex className,uint32_t classStartOffset,HasHeritage hasHeritage,ClassInitializedMembers & classInitializedMembers,ListNodeType & classMembers,bool * done)7608 bool GeneralParser<ParseHandler, Unit>::classMember(
7609     YieldHandling yieldHandling, const ParseContext::ClassStatement& classStmt,
7610     TaggedParserAtomIndex className, uint32_t classStartOffset,
7611     HasHeritage hasHeritage, ClassInitializedMembers& classInitializedMembers,
7612     ListNodeType& classMembers, bool* done) {
7613   *done = false;
7614 
7615   TokenKind tt;
7616   if (!tokenStream.getToken(&tt, TokenStream::SlashIsInvalid)) {
7617     return false;
7618   }
7619   if (tt == TokenKind::RightCurly) {
7620     *done = true;
7621     return true;
7622   }
7623 
7624   if (tt == TokenKind::Semi) {
7625     return true;
7626   }
7627 
7628   bool isStatic = false;
7629   if (tt == TokenKind::Static) {
7630     if (!tokenStream.peekToken(&tt)) {
7631       return false;
7632     }
7633 
7634     if (tt == TokenKind::LeftCurly) {
7635       /* Parsing static class block: static { ... } */
7636       FunctionNodeType staticBlockBody =
7637           staticClassBlock(classInitializedMembers);
7638       if (!staticBlockBody) {
7639         return false;
7640       }
7641 
7642       StaticClassBlockType classBlock =
7643           handler_.newStaticClassBlock(staticBlockBody);
7644       if (!classBlock) {
7645         return false;
7646       }
7647 
7648       return handler_.addClassMemberDefinition(classMembers, classBlock);
7649     }
7650 
7651     if (tt != TokenKind::LeftParen && tt != TokenKind::Assign &&
7652         tt != TokenKind::Semi && tt != TokenKind::RightCurly) {
7653       isStatic = true;
7654     } else {
7655       anyChars.ungetToken();
7656     }
7657   } else {
7658     anyChars.ungetToken();
7659   }
7660 
7661   uint32_t propNameOffset;
7662   if (!tokenStream.peekOffset(&propNameOffset, TokenStream::SlashIsInvalid)) {
7663     return false;
7664   }
7665 
7666   TaggedParserAtomIndex propAtom;
7667   PropertyType propType;
7668   Node propName = propertyOrMethodName(yieldHandling, PropertyNameInClass,
7669                                        /* maybeDecl = */ Nothing(),
7670                                        classMembers, &propType, &propAtom);
7671   if (!propName) {
7672     return false;
7673   }
7674 
7675   if (propType == PropertyType::Field) {
7676     if (isStatic) {
7677       if (propAtom == TaggedParserAtomIndex::WellKnown::prototype()) {
7678         errorAt(propNameOffset, JSMSG_BAD_METHOD_DEF);
7679         return false;
7680       }
7681     }
7682 
7683     if (propAtom == TaggedParserAtomIndex::WellKnown::constructor()) {
7684       errorAt(propNameOffset, JSMSG_BAD_METHOD_DEF);
7685       return false;
7686     }
7687 
7688     if (handler_.isPrivateName(propName)) {
7689       if (propAtom == TaggedParserAtomIndex::WellKnown::hashConstructor()) {
7690         errorAt(propNameOffset, JSMSG_BAD_METHOD_DEF);
7691         return false;
7692       }
7693 
7694       auto privateName = propAtom;
7695       if (!noteDeclaredPrivateName(
7696               propName, privateName, propType,
7697               isStatic ? FieldPlacement::Static : FieldPlacement::Instance,
7698               pos())) {
7699         return false;
7700       }
7701     }
7702 
7703     if (isStatic) {
7704       classInitializedMembers.staticFields++;
7705     } else {
7706       classInitializedMembers.instanceFields++;
7707     }
7708 
7709     TokenPos propNamePos(propNameOffset, pos().end);
7710     FunctionNodeType initializer =
7711         fieldInitializerOpt(propNamePos, propName, propAtom,
7712                             classInitializedMembers, isStatic, hasHeritage);
7713     if (!initializer) {
7714       return false;
7715     }
7716 
7717     if (!matchOrInsertSemicolon(TokenStream::SlashIsInvalid)) {
7718       return false;
7719     }
7720 
7721     ClassFieldType field =
7722         handler_.newClassFieldDefinition(propName, initializer, isStatic);
7723     if (!field) {
7724       return false;
7725     }
7726 
7727     return handler_.addClassMemberDefinition(classMembers, field);
7728   }
7729 
7730   if (propType != PropertyType::Getter && propType != PropertyType::Setter &&
7731       propType != PropertyType::Method &&
7732       propType != PropertyType::GeneratorMethod &&
7733       propType != PropertyType::AsyncMethod &&
7734       propType != PropertyType::AsyncGeneratorMethod) {
7735     errorAt(propNameOffset, JSMSG_BAD_METHOD_DEF);
7736     return false;
7737   }
7738 
7739   bool isConstructor =
7740       !isStatic && propAtom == TaggedParserAtomIndex::WellKnown::constructor();
7741   if (isConstructor) {
7742     if (propType != PropertyType::Method) {
7743       errorAt(propNameOffset, JSMSG_BAD_METHOD_DEF);
7744       return false;
7745     }
7746     if (classStmt.constructorBox) {
7747       errorAt(propNameOffset, JSMSG_DUPLICATE_PROPERTY, "constructor");
7748       return false;
7749     }
7750     propType = hasHeritage == HasHeritage::Yes
7751                    ? PropertyType::DerivedConstructor
7752                    : PropertyType::Constructor;
7753   } else if (isStatic &&
7754              propAtom == TaggedParserAtomIndex::WellKnown::prototype()) {
7755     errorAt(propNameOffset, JSMSG_BAD_METHOD_DEF);
7756     return false;
7757   }
7758 
7759   TaggedParserAtomIndex funName;
7760   switch (propType) {
7761     case PropertyType::Getter:
7762     case PropertyType::Setter: {
7763       bool hasStaticName =
7764           !anyChars.isCurrentTokenType(TokenKind::RightBracket) && propAtom;
7765       if (hasStaticName) {
7766         funName = prefixAccessorName(propType, propAtom);
7767         if (!funName) {
7768           return false;
7769         }
7770       }
7771       break;
7772     }
7773     case PropertyType::Constructor:
7774     case PropertyType::DerivedConstructor:
7775       funName = className;
7776       break;
7777     default:
7778       if (!anyChars.isCurrentTokenType(TokenKind::RightBracket)) {
7779         funName = propAtom;
7780       }
7781   }
7782 
7783   // When |super()| is invoked, we search for the nearest scope containing
7784   // |.initializers| to initialize the class fields. This set-up precludes
7785   // declaring |.initializers| in the class scope, because in some syntactic
7786   // contexts |super()| can appear nested in a class, while actually belonging
7787   // to an outer class definition.
7788   //
7789   // Example:
7790   // class Outer extends Base {
7791   //   field = 1;
7792   //   constructor() {
7793   //     class Inner {
7794   //       field = 2;
7795   //
7796   //       // The super() call in the computed property name mustn't access
7797   //       // Inner's |.initializers| array, but instead Outer's.
7798   //       [super()]() {}
7799   //     }
7800   //   }
7801   // }
7802   Maybe<ParseContext::Scope> dotInitializersScope;
7803   if (isConstructor && !options().selfHostingMode) {
7804     dotInitializersScope.emplace(this);
7805     if (!dotInitializersScope->init(pc_)) {
7806       return false;
7807     }
7808 
7809     if (!noteDeclaredName(TaggedParserAtomIndex::WellKnown::dotInitializers(),
7810                           DeclarationKind::Let, pos())) {
7811       return false;
7812     }
7813   }
7814 
7815   // Calling toString on constructors need to return the source text for
7816   // the entire class. The end offset is unknown at this point in
7817   // parsing and will be amended when class parsing finishes below.
7818   FunctionNodeType funNode = methodDefinition(
7819       isConstructor ? classStartOffset : propNameOffset, propType, funName);
7820   if (!funNode) {
7821     return false;
7822   }
7823 
7824   AccessorType atype = ToAccessorType(propType);
7825 
7826   Maybe<FunctionNodeType> initializerIfPrivate = Nothing();
7827   if (handler_.isPrivateName(propName)) {
7828     if (propAtom == TaggedParserAtomIndex::WellKnown::hashConstructor()) {
7829       // #constructor is an invalid private name.
7830       errorAt(propNameOffset, JSMSG_BAD_METHOD_DEF);
7831       return false;
7832     }
7833 
7834     TaggedParserAtomIndex privateName = propAtom;
7835     if (!noteDeclaredPrivateName(
7836             propName, privateName, propType,
7837             isStatic ? FieldPlacement::Static : FieldPlacement::Instance,
7838             pos())) {
7839       return false;
7840     }
7841 
7842     // Private non-static methods are stored in the class body environment.
7843     // Private non-static accessors are stamped onto every instance using
7844     // initializers. Private static methods are stamped onto the constructor
7845     // during class evaluation; see BytecodeEmitter::emitPropertyList.
7846     if (!isStatic) {
7847       if (atype == AccessorType::Getter || atype == AccessorType::Setter) {
7848         classInitializedMembers.privateAccessors++;
7849 
7850         // Synthesize a name for the lexical variable that will store the
7851         // accessor body.
7852         StringBuffer storedMethodName(cx_);
7853         if (!storedMethodName.append(this->parserAtoms(), propAtom)) {
7854           return false;
7855         }
7856         if (!storedMethodName.append(
7857                 atype == AccessorType::Getter ? ".getter" : ".setter")) {
7858           return false;
7859         }
7860         auto storedMethodProp =
7861             storedMethodName.finishParserAtom(this->parserAtoms());
7862         if (!storedMethodProp) {
7863           return false;
7864         }
7865         if (!noteDeclaredName(storedMethodProp, DeclarationKind::Synthetic,
7866                               pos())) {
7867           return false;
7868         }
7869 
7870         TokenPos propNamePos(propNameOffset, pos().end);
7871         auto initializerNode =
7872             privateMethodInitializer(propNamePos, propAtom, storedMethodProp);
7873         if (!initializerNode) {
7874           return false;
7875         }
7876         initializerIfPrivate = Some(initializerNode);
7877       } else {
7878         MOZ_ASSERT(atype == AccessorType::None);
7879         classInitializedMembers.privateMethods++;
7880       }
7881     }
7882   }
7883 
7884   Node method = handler_.newClassMethodDefinition(
7885       propName, funNode, atype, isStatic, initializerIfPrivate);
7886   if (!method) {
7887     return false;
7888   }
7889 
7890   if (dotInitializersScope.isSome()) {
7891     method = finishLexicalScope(*dotInitializersScope, method);
7892     if (!method) {
7893       return false;
7894     }
7895     dotInitializersScope.reset();
7896   }
7897 
7898   return handler_.addClassMemberDefinition(classMembers, method);
7899 }
7900 
7901 template <class ParseHandler, typename Unit>
finishClassConstructor(const ParseContext::ClassStatement & classStmt,TaggedParserAtomIndex className,HasHeritage hasHeritage,uint32_t classStartOffset,uint32_t classEndOffset,const ClassInitializedMembers & classInitializedMembers,ListNodeType & classMembers)7902 bool GeneralParser<ParseHandler, Unit>::finishClassConstructor(
7903     const ParseContext::ClassStatement& classStmt,
7904     TaggedParserAtomIndex className, HasHeritage hasHeritage,
7905     uint32_t classStartOffset, uint32_t classEndOffset,
7906     const ClassInitializedMembers& classInitializedMembers,
7907     ListNodeType& classMembers) {
7908   if (classStmt.constructorBox == nullptr) {
7909     MOZ_ASSERT(!options().selfHostingMode);
7910     // Unconditionally create the scope here, because it's always the
7911     // constructor.
7912     ParseContext::Scope dotInitializersScope(this);
7913     if (!dotInitializersScope.init(pc_)) {
7914       return false;
7915     }
7916 
7917     if (!noteDeclaredName(TaggedParserAtomIndex::WellKnown::dotInitializers(),
7918                           DeclarationKind::Let, pos())) {
7919       return false;
7920     }
7921 
7922     // synthesizeConstructor assigns to classStmt.constructorBox
7923     TokenPos synthesizedBodyPos(classStartOffset, classEndOffset);
7924     FunctionNodeType synthesizedCtor =
7925         synthesizeConstructor(className, synthesizedBodyPos, hasHeritage);
7926     if (!synthesizedCtor) {
7927       return false;
7928     }
7929 
7930     // Note: the *function* has the name of the class, but the *property*
7931     // containing the function has the name "constructor"
7932     Node constructorNameNode = handler_.newObjectLiteralPropertyName(
7933         TaggedParserAtomIndex::WellKnown::constructor(), pos());
7934     if (!constructorNameNode) {
7935       return false;
7936     }
7937     ClassMethodType method = handler_.newDefaultClassConstructor(
7938         constructorNameNode, synthesizedCtor);
7939     if (!method) {
7940       return false;
7941     }
7942     LexicalScopeNodeType scope =
7943         finishLexicalScope(dotInitializersScope, method);
7944     if (!scope) {
7945       return false;
7946     }
7947     if (!handler_.addClassMemberDefinition(classMembers, scope)) {
7948       return false;
7949     }
7950   }
7951 
7952   MOZ_ASSERT(classStmt.constructorBox);
7953   FunctionBox* ctorbox = classStmt.constructorBox;
7954 
7955   // Amend the toStringEnd offset for the constructor now that we've
7956   // finished parsing the class.
7957   ctorbox->setCtorToStringEnd(classEndOffset);
7958 
7959   size_t numMemberInitializers = classInitializedMembers.privateAccessors +
7960                                  classInitializedMembers.instanceFields;
7961   bool hasPrivateBrand = classInitializedMembers.hasPrivateBrand();
7962   if (hasPrivateBrand || numMemberInitializers > 0) {
7963     // Now that we have full set of initializers, update the constructor.
7964     MemberInitializers initializers(hasPrivateBrand, numMemberInitializers);
7965     ctorbox->setMemberInitializers(initializers);
7966 
7967     // Field initialization need access to `this`.
7968     ctorbox->setCtorFunctionHasThisBinding();
7969   }
7970 
7971   return true;
7972 }
7973 
7974 template <class ParseHandler, typename Unit>
7975 typename ParseHandler::ClassNodeType
classDefinition(YieldHandling yieldHandling,ClassContext classContext,DefaultHandling defaultHandling)7976 GeneralParser<ParseHandler, Unit>::classDefinition(
7977     YieldHandling yieldHandling, ClassContext classContext,
7978     DefaultHandling defaultHandling) {
7979   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Class));
7980 
7981   uint32_t classStartOffset = pos().begin;
7982   bool savedStrictness = setLocalStrictMode(true);
7983 
7984   TokenKind tt;
7985   if (!tokenStream.getToken(&tt)) {
7986     return null();
7987   }
7988 
7989   TaggedParserAtomIndex className;
7990   if (TokenKindIsPossibleIdentifier(tt)) {
7991     className = bindingIdentifier(yieldHandling);
7992     if (!className) {
7993       return null();
7994     }
7995   } else if (classContext == ClassStatement) {
7996     if (defaultHandling == AllowDefaultName) {
7997       className = TaggedParserAtomIndex::WellKnown::default_();
7998       anyChars.ungetToken();
7999     } else {
8000       // Class statements must have a bound name
8001       error(JSMSG_UNNAMED_CLASS_STMT);
8002       return null();
8003     }
8004   } else {
8005     // Make sure to put it back, whatever it was
8006     anyChars.ungetToken();
8007   }
8008 
8009   // Because the binding definitions keep track of their blockId, we need to
8010   // create at least the inner binding later. Keep track of the name's
8011   // position in order to provide it for the nodes created later.
8012   TokenPos namePos = pos();
8013 
8014   bool isInClass = pc_->sc()->inClass();
8015 
8016   // Push a ParseContext::ClassStatement to keep track of the constructor
8017   // funbox.
8018   ParseContext::ClassStatement classStmt(pc_);
8019 
8020   NameNodeType innerName;
8021   Node nameNode = null();
8022   Node classHeritage = null();
8023   LexicalScopeNodeType classBlock = null();
8024   ClassBodyScopeNodeType classBodyBlock = null();
8025   uint32_t classEndOffset;
8026   {
8027     // A named class creates a new lexical scope with a const binding of the
8028     // class name for the "inner name".
8029     ParseContext::Statement innerScopeStmt(pc_, StatementKind::Block);
8030     ParseContext::Scope innerScope(this);
8031     if (!innerScope.init(pc_)) {
8032       return null();
8033     }
8034 
8035     bool hasHeritageBool;
8036     if (!tokenStream.matchToken(&hasHeritageBool, TokenKind::Extends)) {
8037       return null();
8038     }
8039     HasHeritage hasHeritage =
8040         hasHeritageBool ? HasHeritage::Yes : HasHeritage::No;
8041     if (hasHeritage == HasHeritage::Yes) {
8042       if (!tokenStream.getToken(&tt)) {
8043         return null();
8044       }
8045       classHeritage = optionalExpr(yieldHandling, TripledotProhibited, tt);
8046       if (!classHeritage) {
8047         return null();
8048       }
8049     }
8050 
8051     if (!mustMatchToken(TokenKind::LeftCurly, JSMSG_CURLY_BEFORE_CLASS)) {
8052       return null();
8053     }
8054 
8055     {
8056       ParseContext::Statement bodyScopeStmt(pc_, StatementKind::Block);
8057       ParseContext::Scope bodyScope(this);
8058       if (!bodyScope.init(pc_)) {
8059         return null();
8060       }
8061 
8062       ListNodeType classMembers = handler_.newClassMemberList(pos().begin);
8063       if (!classMembers) {
8064         return null();
8065       }
8066 
8067       ClassInitializedMembers classInitializedMembers{};
8068       for (;;) {
8069         bool done;
8070         if (!classMember(yieldHandling, classStmt, className, classStartOffset,
8071                          hasHeritage, classInitializedMembers, classMembers,
8072                          &done)) {
8073           return null();
8074         }
8075         if (done) {
8076           break;
8077         }
8078       }
8079 
8080       if (classInitializedMembers.privateMethods +
8081               classInitializedMembers.privateAccessors >
8082           0) {
8083         // We declare `.privateBrand` as ClosedOver because the constructor
8084         // always uses it, even a default constructor. We could equivalently
8085         // `noteNameUsed` when parsing the constructor, except that at that
8086         // time, we don't necessarily know if the class has a private brand.
8087         if (!noteDeclaredName(
8088                 TaggedParserAtomIndex::WellKnown::dotPrivateBrand(),
8089                 DeclarationKind::Synthetic, namePos, ClosedOver::Yes)) {
8090           return null();
8091         }
8092       }
8093 
8094       if (classInitializedMembers.instanceFieldKeys > 0) {
8095         if (!noteDeclaredName(TaggedParserAtomIndex::WellKnown::dotFieldKeys(),
8096                               DeclarationKind::Synthetic, namePos)) {
8097           return null();
8098         }
8099       }
8100 
8101       if (classInitializedMembers.staticFields > 0) {
8102         if (!noteDeclaredName(
8103                 TaggedParserAtomIndex::WellKnown::dotStaticInitializers(),
8104                 DeclarationKind::Synthetic, namePos)) {
8105           return null();
8106         }
8107       }
8108 
8109       if (classInitializedMembers.staticFieldKeys > 0) {
8110         if (!noteDeclaredName(
8111                 TaggedParserAtomIndex::WellKnown::dotStaticFieldKeys(),
8112                 DeclarationKind::Synthetic, namePos)) {
8113           return null();
8114         }
8115       }
8116 
8117       classEndOffset = pos().end;
8118       if (!finishClassConstructor(classStmt, className, hasHeritage,
8119                                   classStartOffset, classEndOffset,
8120                                   classInitializedMembers, classMembers)) {
8121         return null();
8122       }
8123 
8124       classBodyBlock = finishClassBodyScope(bodyScope, classMembers);
8125       if (!classBodyBlock) {
8126         return null();
8127       }
8128 
8129       // Pop the class body scope
8130     }
8131 
8132     if (className) {
8133       // The inner name is immutable.
8134       if (!noteDeclaredName(className, DeclarationKind::Const, namePos)) {
8135         return null();
8136       }
8137 
8138       innerName = newName(className, namePos);
8139       if (!innerName) {
8140         return null();
8141       }
8142     }
8143 
8144     classBlock = finishLexicalScope(innerScope, classBodyBlock);
8145     if (!classBlock) {
8146       return null();
8147     }
8148 
8149     // Pop the inner scope.
8150   }
8151 
8152   if (className) {
8153     NameNodeType outerName = null();
8154     if (classContext == ClassStatement) {
8155       // The outer name is mutable.
8156       if (!noteDeclaredName(className, DeclarationKind::Class, namePos)) {
8157         return null();
8158       }
8159 
8160       outerName = newName(className, namePos);
8161       if (!outerName) {
8162         return null();
8163       }
8164     }
8165 
8166     nameNode = handler_.newClassNames(outerName, innerName, namePos);
8167     if (!nameNode) {
8168       return null();
8169     }
8170   }
8171   MOZ_ALWAYS_TRUE(setLocalStrictMode(savedStrictness));
8172   // We're leaving a class definition that was not itself nested within a class
8173   if (!isInClass) {
8174     mozilla::Maybe<UnboundPrivateName> maybeUnboundName;
8175     if (!usedNames_.hasUnboundPrivateNames(cx_, maybeUnboundName)) {
8176       return null();
8177     }
8178     if (maybeUnboundName) {
8179       UniqueChars str =
8180           this->parserAtoms().toPrintableString(cx_, maybeUnboundName->atom);
8181       if (!str) {
8182         return null();
8183       }
8184 
8185       errorAt(maybeUnboundName->position.begin, JSMSG_MISSING_PRIVATE_DECL,
8186               str.get());
8187       return null();
8188     }
8189   }
8190 
8191   return handler_.newClass(nameNode, classHeritage, classBlock,
8192                            TokenPos(classStartOffset, classEndOffset));
8193 }
8194 
8195 template <class ParseHandler, typename Unit>
8196 typename ParseHandler::FunctionNodeType
synthesizeConstructor(TaggedParserAtomIndex className,TokenPos synthesizedBodyPos,HasHeritage hasHeritage)8197 GeneralParser<ParseHandler, Unit>::synthesizeConstructor(
8198     TaggedParserAtomIndex className, TokenPos synthesizedBodyPos,
8199     HasHeritage hasHeritage) {
8200   FunctionSyntaxKind functionSyntaxKind =
8201       hasHeritage == HasHeritage::Yes
8202           ? FunctionSyntaxKind::DerivedClassConstructor
8203           : FunctionSyntaxKind::ClassConstructor;
8204 
8205   bool isSelfHosting = options().selfHostingMode;
8206   FunctionFlags flags =
8207       InitialFunctionFlags(functionSyntaxKind, GeneratorKind::NotGenerator,
8208                            FunctionAsyncKind::SyncFunction, isSelfHosting);
8209 
8210   // Create the top-level field initializer node.
8211   FunctionNodeType funNode =
8212       handler_.newFunction(functionSyntaxKind, synthesizedBodyPos);
8213   if (!funNode) {
8214     return null();
8215   }
8216 
8217   // If we see any inner function, note it on our current context. The bytecode
8218   // emitter may eliminate the function later, but we use a conservative
8219   // definition for consistency between lazy and full parsing.
8220   pc_->sc()->setHasInnerFunctions();
8221 
8222   // When fully parsing a lazy script, we do not fully reparse its inner
8223   // functions, which are also lazy. Instead, their free variables and source
8224   // extents are recorded and may be skipped.
8225   if (handler_.reuseLazyInnerFunctions()) {
8226     if (!skipLazyInnerFunction(funNode, synthesizedBodyPos.begin,
8227                                /* tryAnnexB = */ false)) {
8228       return null();
8229     }
8230 
8231     return funNode;
8232   }
8233 
8234   // Create the FunctionBox and link it to the function object.
8235   Directives directives(true);
8236   FunctionBox* funbox = newFunctionBox(
8237       funNode, className, flags, synthesizedBodyPos.begin, directives,
8238       GeneratorKind::NotGenerator, FunctionAsyncKind::SyncFunction);
8239   if (!funbox) {
8240     return null();
8241   }
8242   funbox->initWithEnclosingParseContext(pc_, flags, functionSyntaxKind);
8243   setFunctionEndFromCurrentToken(funbox);
8244 
8245   // Mark this function as being synthesized by the parser. This means special
8246   // handling in delazification will be used since we don't have typical
8247   // function syntax.
8248   funbox->setSyntheticFunction();
8249 
8250   // Push a SourceParseContext on to the stack.
8251   ParseContext* outerpc = pc_;
8252   SourceParseContext funpc(this, funbox, /* newDirectives = */ nullptr);
8253   if (!funpc.init()) {
8254     return null();
8255   }
8256 
8257   if (!synthesizeConstructorBody(synthesizedBodyPos, hasHeritage, funNode,
8258                                  funbox)) {
8259     return null();
8260   }
8261 
8262   if (!leaveInnerFunction(outerpc)) {
8263     return null();
8264   }
8265 
8266   return funNode;
8267 }
8268 
8269 template <class ParseHandler, typename Unit>
8270 typename ParseHandler::FunctionNodeType
synthesizeConstructorBody(TokenPos synthesizedBodyPos,HasHeritage hasHeritage,FunctionNodeType funNode,FunctionBox * funbox)8271 GeneralParser<ParseHandler, Unit>::synthesizeConstructorBody(
8272     TokenPos synthesizedBodyPos, HasHeritage hasHeritage,
8273     FunctionNodeType funNode, FunctionBox* funbox) {
8274   MOZ_ASSERT(funbox->isClassConstructor());
8275 
8276   // Create a ListNode for the parameters + body (there are no parameters).
8277   ListNodeType argsbody =
8278       handler_.newList(ParseNodeKind::ParamsBody, synthesizedBodyPos);
8279   if (!argsbody) {
8280     return null();
8281   }
8282   handler_.setFunctionFormalParametersAndBody(funNode, argsbody);
8283   setFunctionStartAtPosition(funbox, synthesizedBodyPos);
8284 
8285   if (hasHeritage == HasHeritage::Yes) {
8286     // Synthesize the equivalent to `function f(...args)`
8287     funbox->setHasRest();
8288     if (!notePositionalFormalParameter(
8289             funNode, TaggedParserAtomIndex::WellKnown::dotArgs(),
8290             synthesizedBodyPos.begin,
8291             /* disallowDuplicateParams = */ false,
8292             /* duplicatedParam = */ nullptr)) {
8293       return null();
8294     }
8295     funbox->setArgCount(1);
8296   } else {
8297     funbox->setArgCount(0);
8298   }
8299 
8300   pc_->functionScope().useAsVarScope(pc_);
8301 
8302   auto stmtList = handler_.newStatementList(synthesizedBodyPos);
8303   if (!stmtList) {
8304     return null();
8305   }
8306 
8307   if (!noteUsedName(TaggedParserAtomIndex::WellKnown::dotThis())) {
8308     return null();
8309   }
8310 
8311   if (!noteUsedName(TaggedParserAtomIndex::WellKnown::dotInitializers())) {
8312     return null();
8313   }
8314 
8315   bool canSkipLazyClosedOverBindings = handler_.reuseClosedOverBindings();
8316   if (!pc_->declareFunctionThis(usedNames_, canSkipLazyClosedOverBindings)) {
8317     return null();
8318   }
8319 
8320   if (hasHeritage == HasHeritage::Yes) {
8321     NameNodeType thisName = newThisName();
8322     if (!thisName) {
8323       return null();
8324     }
8325 
8326     UnaryNodeType superBase =
8327         handler_.newSuperBase(thisName, synthesizedBodyPos);
8328     if (!superBase) {
8329       return null();
8330     }
8331 
8332     ListNodeType arguments = handler_.newArguments(synthesizedBodyPos);
8333     if (!arguments) {
8334       return null();
8335     }
8336 
8337     NameNodeType argsNameNode = newName(
8338         TaggedParserAtomIndex::WellKnown::dotArgs(), synthesizedBodyPos);
8339     if (!argsNameNode) {
8340       return null();
8341     }
8342     if (!noteUsedName(TaggedParserAtomIndex::WellKnown::dotArgs())) {
8343       return null();
8344     }
8345 
8346     UnaryNodeType spreadArgs =
8347         handler_.newSpread(synthesizedBodyPos.begin, argsNameNode);
8348     if (!spreadArgs) {
8349       return null();
8350     }
8351     handler_.addList(arguments, spreadArgs);
8352 
8353     CallNodeType superCall =
8354         handler_.newSuperCall(superBase, arguments, /* isSpread = */ true);
8355     if (!superCall) {
8356       return null();
8357     }
8358 
8359     BinaryNodeType setThis = handler_.newSetThis(thisName, superCall);
8360     if (!setThis) {
8361       return null();
8362     }
8363 
8364     UnaryNodeType exprStatement =
8365         handler_.newExprStatement(setThis, synthesizedBodyPos.end);
8366     if (!exprStatement) {
8367       return null();
8368     }
8369 
8370     handler_.addStatementToList(stmtList, exprStatement);
8371   }
8372 
8373   auto initializerBody =
8374       finishLexicalScope(pc_->varScope(), stmtList, ScopeKind::FunctionLexical);
8375   if (!initializerBody) {
8376     return null();
8377   }
8378   handler_.setBeginPosition(initializerBody, stmtList);
8379   handler_.setEndPosition(initializerBody, stmtList);
8380 
8381   handler_.setFunctionBody(funNode, initializerBody);
8382 
8383   if (!finishFunction()) {
8384     return null();
8385   }
8386 
8387   return funNode;
8388 }
8389 
8390 template <class ParseHandler, typename Unit>
8391 typename ParseHandler::FunctionNodeType
privateMethodInitializer(TokenPos propNamePos,TaggedParserAtomIndex propAtom,TaggedParserAtomIndex storedMethodAtom)8392 GeneralParser<ParseHandler, Unit>::privateMethodInitializer(
8393     TokenPos propNamePos, TaggedParserAtomIndex propAtom,
8394     TaggedParserAtomIndex storedMethodAtom) {
8395   if (!abortIfSyntaxParser()) {
8396     return null();
8397   }
8398 
8399   // Synthesize an initializer function that the constructor can use to stamp a
8400   // private method onto an instance object.
8401   FunctionSyntaxKind syntaxKind = FunctionSyntaxKind::FieldInitializer;
8402   FunctionAsyncKind asyncKind = FunctionAsyncKind::SyncFunction;
8403   GeneratorKind generatorKind = GeneratorKind::NotGenerator;
8404   bool isSelfHosting = options().selfHostingMode;
8405   FunctionFlags flags =
8406       InitialFunctionFlags(syntaxKind, generatorKind, asyncKind, isSelfHosting);
8407 
8408   FunctionNodeType funNode = handler_.newFunction(syntaxKind, propNamePos);
8409   if (!funNode) {
8410     return null();
8411   }
8412 
8413   Directives directives(true);
8414   FunctionBox* funbox =
8415       newFunctionBox(funNode, TaggedParserAtomIndex::null(), flags,
8416                      propNamePos.begin, directives, generatorKind, asyncKind);
8417   if (!funbox) {
8418     return null();
8419   }
8420   funbox->initWithEnclosingParseContext(pc_, flags, syntaxKind);
8421 
8422   // Push a SourceParseContext on to the stack.
8423   ParseContext* outerpc = pc_;
8424   SourceParseContext funpc(this, funbox, /* newDirectives = */ nullptr);
8425   if (!funpc.init()) {
8426     return null();
8427   }
8428   pc_->functionScope().useAsVarScope(pc_);
8429 
8430   // Add empty parameter list.
8431   ListNodeType argsbody =
8432       handler_.newList(ParseNodeKind::ParamsBody, propNamePos);
8433   if (!argsbody) {
8434     return null();
8435   }
8436   handler_.setFunctionFormalParametersAndBody(funNode, argsbody);
8437   setFunctionStartAtCurrentToken(funbox);
8438   funbox->setArgCount(0);
8439 
8440   // Note both the stored private method body and it's private name as being
8441   // used in the initializer. They will be emitted into the method body in the
8442   // BCE.
8443   if (!noteUsedName(storedMethodAtom)) {
8444     return null();
8445   }
8446   NameNodeType privateNameNode = privateNameReference(propAtom);
8447   if (!privateNameNode) {
8448     return null();
8449   }
8450 
8451   bool canSkipLazyClosedOverBindings = handler_.reuseClosedOverBindings();
8452   if (!pc_->declareFunctionThis(usedNames_, canSkipLazyClosedOverBindings)) {
8453     return null();
8454   }
8455 
8456   // Unlike field initializers, private method initializers are not created with
8457   // a body of synthesized AST nodes. Instead, the body is left empty and the
8458   // initializer is synthesized at the bytecode level.
8459   // See BytecodeEmitter::emitPrivateMethodInitializer.
8460   ListNodeType stmtList = handler_.newStatementList(propNamePos);
8461   if (!stmtList) {
8462     return null();
8463   }
8464   LexicalScopeNodeType initializerBody =
8465       finishLexicalScope(pc_->varScope(), stmtList, ScopeKind::FunctionLexical);
8466   if (!initializerBody) {
8467     return null();
8468   }
8469   handler_.setBeginPosition(initializerBody, stmtList);
8470   handler_.setEndPosition(initializerBody, stmtList);
8471   handler_.setFunctionBody(funNode, initializerBody);
8472 
8473   // Set field-initializer lambda boundary to start at property name and end
8474   // after method body.
8475   setFunctionStartAtPosition(funbox, propNamePos);
8476   setFunctionEndFromCurrentToken(funbox);
8477 
8478   if (!finishFunction()) {
8479     return null();
8480   }
8481 
8482   if (!leaveInnerFunction(outerpc)) {
8483     return null();
8484   }
8485 
8486   return funNode;
8487 }
8488 
8489 template <class ParseHandler, typename Unit>
8490 typename ParseHandler::FunctionNodeType
staticClassBlock(ClassInitializedMembers & classInitializedMembers)8491 GeneralParser<ParseHandler, Unit>::staticClassBlock(
8492     ClassInitializedMembers& classInitializedMembers) {
8493   // Both for getting-this-done, and because this will invariably be executed,
8494   // syntax parsing should be aborted.
8495   if (!abortIfSyntaxParser()) {
8496     return null();
8497   }
8498 
8499   FunctionSyntaxKind syntaxKind = FunctionSyntaxKind::StaticClassBlock;
8500   FunctionAsyncKind asyncKind = FunctionAsyncKind::SyncFunction;
8501   GeneratorKind generatorKind = GeneratorKind::NotGenerator;
8502   bool isSelfHosting = options().selfHostingMode;
8503   FunctionFlags flags =
8504       InitialFunctionFlags(syntaxKind, generatorKind, asyncKind, isSelfHosting);
8505 
8506   AutoAwaitIsKeyword awaitIsKeyword(this, AwaitHandling::AwaitIsDisallowed);
8507 
8508   // Create the function node for the static class body.
8509   FunctionNodeType funNode = handler_.newFunction(syntaxKind, pos());
8510   if (!funNode) {
8511     return null();
8512   }
8513 
8514   // Create the FunctionBox and link it to the function object.
8515   Directives directives(true);
8516   FunctionBox* funbox =
8517       newFunctionBox(funNode, TaggedParserAtomIndex::null(), flags, pos().begin,
8518                      directives, generatorKind, asyncKind);
8519   if (!funbox) {
8520     return null();
8521   }
8522   funbox->initWithEnclosingParseContext(pc_, flags, syntaxKind);
8523   MOZ_ASSERT(funbox->isSyntheticFunction());
8524   MOZ_ASSERT(!funbox->allowSuperCall());
8525   MOZ_ASSERT(!funbox->allowArguments());
8526   MOZ_ASSERT(!funbox->allowReturn());
8527 
8528   // Set start at `static` token.
8529   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Static));
8530   setFunctionStartAtCurrentToken(funbox);
8531 
8532   // Push a SourceParseContext on to the stack.
8533   ParseContext* outerpc = pc_;
8534   SourceParseContext funpc(this, funbox, /* newDirectives = */ nullptr);
8535   if (!funpc.init()) {
8536     return null();
8537   }
8538 
8539   pc_->functionScope().useAsVarScope(pc_);
8540 
8541   uint32_t start = pos().begin;
8542 
8543   tokenStream.consumeKnownToken(TokenKind::LeftCurly);
8544 
8545   // Static class blocks are code-generated as if they were static field
8546   // initializers, so we bump the staticFields count here, which ensures
8547   // .staticInitializers is noted as used.
8548   classInitializedMembers.staticFields++;
8549 
8550   LexicalScopeNodeType body =
8551       functionBody(InHandling::InAllowed, YieldHandling::YieldIsKeyword,
8552                    syntaxKind, FunctionBodyType::StatementListBody);
8553   if (!body) {
8554     return null();
8555   }
8556 
8557   if (anyChars.isEOF()) {
8558     error(JSMSG_UNTERMINATED_STATIC_CLASS_BLOCK);
8559     return null();
8560   }
8561 
8562   tokenStream.consumeKnownToken(TokenKind::RightCurly,
8563                                 TokenStream::Modifier::SlashIsRegExp);
8564 
8565   TokenPos wholeBodyPos(start, pos().end);
8566 
8567   handler_.setEndPosition(funNode, wholeBodyPos.end);
8568   setFunctionEndFromCurrentToken(funbox);
8569 
8570   // Create a ListNode for the parameters + body (there are no parameters).
8571   ListNodeType argsbody =
8572       handler_.newList(ParseNodeKind::ParamsBody, wholeBodyPos);
8573   if (!argsbody) {
8574     return null();
8575   }
8576 
8577   handler_.setFunctionFormalParametersAndBody(funNode, argsbody);
8578   funbox->setArgCount(0);
8579 
8580   if (pc_->superScopeNeedsHomeObject()) {
8581     funbox->setNeedsHomeObject();
8582   }
8583 
8584   handler_.setEndPosition(body, pos().begin);
8585   handler_.setEndPosition(funNode, pos().end);
8586   handler_.setFunctionBody(funNode, body);
8587 
8588   if (!finishFunction()) {
8589     return null();
8590   }
8591 
8592   if (!leaveInnerFunction(outerpc)) {
8593     return null();
8594   }
8595 
8596   return funNode;
8597 }
8598 
8599 template <class ParseHandler, typename Unit>
8600 typename ParseHandler::FunctionNodeType
fieldInitializerOpt(TokenPos propNamePos,Node propName,TaggedParserAtomIndex propAtom,ClassInitializedMembers & classInitializedMembers,bool isStatic,HasHeritage hasHeritage)8601 GeneralParser<ParseHandler, Unit>::fieldInitializerOpt(
8602     TokenPos propNamePos, Node propName, TaggedParserAtomIndex propAtom,
8603     ClassInitializedMembers& classInitializedMembers, bool isStatic,
8604     HasHeritage hasHeritage) {
8605   if (!abortIfSyntaxParser()) {
8606     return null();
8607   }
8608 
8609   bool hasInitializer = false;
8610   if (!tokenStream.matchToken(&hasInitializer, TokenKind::Assign,
8611                               TokenStream::SlashIsDiv)) {
8612     return null();
8613   }
8614 
8615   FunctionSyntaxKind syntaxKind = FunctionSyntaxKind::FieldInitializer;
8616   FunctionAsyncKind asyncKind = FunctionAsyncKind::SyncFunction;
8617   GeneratorKind generatorKind = GeneratorKind::NotGenerator;
8618   bool isSelfHosting = options().selfHostingMode;
8619   FunctionFlags flags =
8620       InitialFunctionFlags(syntaxKind, generatorKind, asyncKind, isSelfHosting);
8621 
8622   // Create the top-level field initializer node.
8623   FunctionNodeType funNode = handler_.newFunction(syntaxKind, propNamePos);
8624   if (!funNode) {
8625     return null();
8626   }
8627 
8628   // Create the FunctionBox and link it to the function object.
8629   Directives directives(true);
8630   FunctionBox* funbox =
8631       newFunctionBox(funNode, TaggedParserAtomIndex::null(), flags,
8632                      propNamePos.begin, directives, generatorKind, asyncKind);
8633   if (!funbox) {
8634     return null();
8635   }
8636   funbox->initWithEnclosingParseContext(pc_, flags, syntaxKind);
8637   MOZ_ASSERT(funbox->isSyntheticFunction());
8638 
8639   // We can't use setFunctionStartAtCurrentToken because that uses pos().begin,
8640   // which is incorrect for fields without initializers (pos() points to the
8641   // field identifier)
8642   setFunctionStartAtPosition(funbox, propNamePos);
8643 
8644   // Push a SourceParseContext on to the stack.
8645   ParseContext* outerpc = pc_;
8646   SourceParseContext funpc(this, funbox, /* newDirectives = */ nullptr);
8647   if (!funpc.init()) {
8648     return null();
8649   }
8650 
8651   pc_->functionScope().useAsVarScope(pc_);
8652 
8653   Node initializerExpr;
8654   if (hasInitializer) {
8655     // Parse the expression for the field initializer.
8656     {
8657       AutoAwaitIsKeyword awaitHandling(this, AwaitIsName);
8658       initializerExpr = assignExpr(InAllowed, YieldIsName, TripledotProhibited);
8659       if (!initializerExpr) {
8660         return null();
8661       }
8662     }
8663 
8664     handler_.checkAndSetIsDirectRHSAnonFunction(initializerExpr);
8665   } else {
8666     initializerExpr = handler_.newRawUndefinedLiteral(propNamePos);
8667     if (!initializerExpr) {
8668       return null();
8669     }
8670   }
8671 
8672   TokenPos wholeInitializerPos(propNamePos.begin, pos().end);
8673 
8674   // Update the end position of the parse node.
8675   handler_.setEndPosition(funNode, wholeInitializerPos.end);
8676   setFunctionEndFromCurrentToken(funbox);
8677 
8678   // Create a ListNode for the parameters + body (there are no parameters).
8679   ListNodeType argsbody =
8680       handler_.newList(ParseNodeKind::ParamsBody, wholeInitializerPos);
8681   if (!argsbody) {
8682     return null();
8683   }
8684   handler_.setFunctionFormalParametersAndBody(funNode, argsbody);
8685   funbox->setArgCount(0);
8686 
8687   NameNodeType thisName = newThisName();
8688   if (!thisName) {
8689     return null();
8690   }
8691 
8692   // Build `this.field` expression.
8693   ThisLiteralType propAssignThis =
8694       handler_.newThisLiteral(wholeInitializerPos, thisName);
8695   if (!propAssignThis) {
8696     return null();
8697   }
8698 
8699   Node propAssignFieldAccess;
8700   uint32_t indexValue;
8701   if (!propAtom) {
8702     // See BytecodeEmitter::emitCreateFieldKeys for an explanation of what
8703     // .fieldKeys means and its purpose.
8704     NameNodeType fieldKeysName;
8705     if (isStatic) {
8706       fieldKeysName = newInternalDotName(
8707           TaggedParserAtomIndex::WellKnown::dotStaticFieldKeys());
8708     } else {
8709       fieldKeysName =
8710           newInternalDotName(TaggedParserAtomIndex::WellKnown::dotFieldKeys());
8711     }
8712     if (!fieldKeysName) {
8713       return null();
8714     }
8715 
8716     double fieldKeyIndex;
8717     if (isStatic) {
8718       fieldKeyIndex = classInitializedMembers.staticFieldKeys++;
8719     } else {
8720       fieldKeyIndex = classInitializedMembers.instanceFieldKeys++;
8721     }
8722     Node fieldKeyIndexNode = handler_.newNumber(
8723         fieldKeyIndex, DecimalPoint::NoDecimal, wholeInitializerPos);
8724     if (!fieldKeyIndexNode) {
8725       return null();
8726     }
8727 
8728     Node fieldKeyValue = handler_.newPropertyByValue(
8729         fieldKeysName, fieldKeyIndexNode, wholeInitializerPos.end);
8730     if (!fieldKeyValue) {
8731       return null();
8732     }
8733 
8734     propAssignFieldAccess = handler_.newPropertyByValue(
8735         propAssignThis, fieldKeyValue, wholeInitializerPos.end);
8736     if (!propAssignFieldAccess) {
8737       return null();
8738     }
8739   } else if (handler_.isPrivateName(propName)) {
8740     // It would be nice if we could tweak this here such that only if
8741     // HasHeritage::Yes we end up emitting CheckPrivateField, but otherwise we
8742     // emit InitElem -- this is an optimization to minimize HasOwn checks
8743     // in InitElem for classes without heritage.
8744     //
8745     // Further tweaking would be to ultimately only do CheckPrivateField for the
8746     // -first- field in a derived class, which would suffice to match the
8747     // semantic check.
8748 
8749     NameNodeType privateNameNode = privateNameReference(propAtom);
8750     if (!privateNameNode) {
8751       return null();
8752     }
8753 
8754     propAssignFieldAccess = handler_.newPrivateMemberAccess(
8755         propAssignThis, privateNameNode, wholeInitializerPos.end);
8756     if (!propAssignFieldAccess) {
8757       return null();
8758     }
8759   } else if (this->parserAtoms().isIndex(propAtom, &indexValue)) {
8760     propAssignFieldAccess = handler_.newPropertyByValue(
8761         propAssignThis, propName, wholeInitializerPos.end);
8762     if (!propAssignFieldAccess) {
8763       return null();
8764     }
8765   } else {
8766     NameNodeType propAssignName =
8767         handler_.newPropertyName(propAtom, wholeInitializerPos);
8768     if (!propAssignName) {
8769       return null();
8770     }
8771 
8772     propAssignFieldAccess =
8773         handler_.newPropertyAccess(propAssignThis, propAssignName);
8774     if (!propAssignFieldAccess) {
8775       return null();
8776     }
8777   }
8778 
8779   // Synthesize an property init.
8780   AssignmentNodeType initializerPropInit = handler_.newAssignment(
8781       ParseNodeKind::InitExpr, propAssignFieldAccess, initializerExpr);
8782   if (!initializerPropInit) {
8783     return null();
8784   }
8785 
8786   bool canSkipLazyClosedOverBindings = handler_.reuseClosedOverBindings();
8787   if (!pc_->declareFunctionThis(usedNames_, canSkipLazyClosedOverBindings)) {
8788     return null();
8789   }
8790 
8791   UnaryNodeType exprStatement =
8792       handler_.newExprStatement(initializerPropInit, wholeInitializerPos.end);
8793   if (!exprStatement) {
8794     return null();
8795   }
8796 
8797   ListNodeType statementList = handler_.newStatementList(wholeInitializerPos);
8798   if (!statementList) {
8799     return null();
8800   }
8801   handler_.addStatementToList(statementList, exprStatement);
8802 
8803   // Set the function's body to the field assignment.
8804   LexicalScopeNodeType initializerBody = finishLexicalScope(
8805       pc_->varScope(), statementList, ScopeKind::FunctionLexical);
8806   if (!initializerBody) {
8807     return null();
8808   }
8809 
8810   handler_.setFunctionBody(funNode, initializerBody);
8811 
8812   if (pc_->superScopeNeedsHomeObject()) {
8813     funbox->setNeedsHomeObject();
8814   }
8815 
8816   if (!finishFunction()) {
8817     return null();
8818   }
8819 
8820   if (!leaveInnerFunction(outerpc)) {
8821     return null();
8822   }
8823 
8824   return funNode;
8825 }
8826 
nextTokenContinuesLetDeclaration(TokenKind next)8827 bool ParserBase::nextTokenContinuesLetDeclaration(TokenKind next) {
8828   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Let));
8829   MOZ_ASSERT(anyChars.nextToken().type == next);
8830 
8831   TokenStreamShared::verifyConsistentModifier(TokenStreamShared::SlashIsDiv,
8832                                               anyChars.nextToken());
8833 
8834   // Destructuring continues a let declaration.
8835   if (next == TokenKind::LeftBracket || next == TokenKind::LeftCurly) {
8836     return true;
8837   }
8838 
8839   // A "let" edge case deserves special comment.  Consider this:
8840   //
8841   //   let     // not an ASI opportunity
8842   //   let;
8843   //
8844   // Static semantics in §13.3.1.1 turn a LexicalDeclaration that binds
8845   // "let" into an early error.  Does this retroactively permit ASI so
8846   // that we should parse this as two ExpressionStatements?   No.  ASI
8847   // resolves during parsing.  Static semantics only apply to the full
8848   // parse tree with ASI applied.  No backsies!
8849 
8850   // Otherwise a let declaration must have a name.
8851   return TokenKindIsPossibleIdentifier(next);
8852 }
8853 
8854 template <class ParseHandler, typename Unit>
8855 typename ParseHandler::ListNodeType
variableStatement(YieldHandling yieldHandling)8856 GeneralParser<ParseHandler, Unit>::variableStatement(
8857     YieldHandling yieldHandling) {
8858   ListNodeType vars = declarationList(yieldHandling, ParseNodeKind::VarStmt);
8859   if (!vars) {
8860     return null();
8861   }
8862   if (!matchOrInsertSemicolon()) {
8863     return null();
8864   }
8865   return vars;
8866 }
8867 
8868 template <class ParseHandler, typename Unit>
statement(YieldHandling yieldHandling)8869 typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::statement(
8870     YieldHandling yieldHandling) {
8871   MOZ_ASSERT(checkOptionsCalled_);
8872 
8873   AutoCheckRecursionLimit recursion(cx_);
8874   if (!recursion.check(cx_)) {
8875     return null();
8876   }
8877 
8878   TokenKind tt;
8879   if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) {
8880     return null();
8881   }
8882 
8883   switch (tt) {
8884     // BlockStatement[?Yield, ?Return]
8885     case TokenKind::LeftCurly:
8886       return blockStatement(yieldHandling);
8887 
8888     // VariableStatement[?Yield]
8889     case TokenKind::Var:
8890       return variableStatement(yieldHandling);
8891 
8892     // EmptyStatement
8893     case TokenKind::Semi:
8894       return handler_.newEmptyStatement(pos());
8895 
8896       // ExpressionStatement[?Yield].
8897 
8898     case TokenKind::Yield: {
8899       // Don't use a ternary operator here due to obscure linker issues
8900       // around using static consts in the arms of a ternary.
8901       Modifier modifier;
8902       if (yieldExpressionsSupported()) {
8903         modifier = TokenStream::SlashIsRegExp;
8904       } else {
8905         modifier = TokenStream::SlashIsDiv;
8906       }
8907 
8908       TokenKind next;
8909       if (!tokenStream.peekToken(&next, modifier)) {
8910         return null();
8911       }
8912 
8913       if (next == TokenKind::Colon) {
8914         return labeledStatement(yieldHandling);
8915       }
8916 
8917       return expressionStatement(yieldHandling);
8918     }
8919 
8920     default: {
8921       // If we encounter an await in a module, and the module is not marked
8922       // as async, mark the module as async.
8923       if (tt == TokenKind::Await && !pc_->isAsync()) {
8924         if (pc_->atModuleTopLevel()) {
8925           pc_->sc()->asModuleContext()->setIsAsync();
8926           MOZ_ASSERT(pc_->isAsync());
8927         }
8928       }
8929 
8930       // Avoid getting next token with SlashIsDiv.
8931       if (tt == TokenKind::Await && pc_->isAsync()) {
8932         return expressionStatement(yieldHandling);
8933       }
8934 
8935       if (!TokenKindIsPossibleIdentifier(tt)) {
8936         return expressionStatement(yieldHandling);
8937       }
8938 
8939       TokenKind next;
8940       if (!tokenStream.peekToken(&next)) {
8941         return null();
8942       }
8943 
8944       // |let| here can only be an Identifier, not a declaration.  Give nicer
8945       // errors for declaration-looking typos.
8946       if (tt == TokenKind::Let) {
8947         bool forbiddenLetDeclaration = false;
8948 
8949         if (next == TokenKind::LeftBracket) {
8950           // Enforce ExpressionStatement's 'let [' lookahead restriction.
8951           forbiddenLetDeclaration = true;
8952         } else if (next == TokenKind::LeftCurly ||
8953                    TokenKindIsPossibleIdentifier(next)) {
8954           // 'let {' and 'let foo' aren't completely forbidden, if ASI
8955           // causes 'let' to be the entire Statement.  But if they're
8956           // same-line, we can aggressively give a better error message.
8957           //
8958           // Note that this ignores 'yield' as TokenKind::Yield: we'll handle it
8959           // correctly but with a worse error message.
8960           TokenKind nextSameLine;
8961           if (!tokenStream.peekTokenSameLine(&nextSameLine)) {
8962             return null();
8963           }
8964 
8965           MOZ_ASSERT(TokenKindIsPossibleIdentifier(nextSameLine) ||
8966                      nextSameLine == TokenKind::LeftCurly ||
8967                      nextSameLine == TokenKind::Eol);
8968 
8969           forbiddenLetDeclaration = nextSameLine != TokenKind::Eol;
8970         }
8971 
8972         if (forbiddenLetDeclaration) {
8973           error(JSMSG_FORBIDDEN_AS_STATEMENT, "lexical declarations");
8974           return null();
8975         }
8976       } else if (tt == TokenKind::Async) {
8977         // Peek only on the same line: ExpressionStatement's lookahead
8978         // restriction is phrased as
8979         //
8980         //   [lookahead ∉ { '{',
8981         //                  function,
8982         //                  async [no LineTerminator here] function,
8983         //                  class,
8984         //                  let '[' }]
8985         //
8986         // meaning that code like this is valid:
8987         //
8988         //   if (true)
8989         //     async       // ASI opportunity
8990         //   function clownshoes() {}
8991         TokenKind maybeFunction;
8992         if (!tokenStream.peekTokenSameLine(&maybeFunction)) {
8993           return null();
8994         }
8995 
8996         if (maybeFunction == TokenKind::Function) {
8997           error(JSMSG_FORBIDDEN_AS_STATEMENT, "async function declarations");
8998           return null();
8999         }
9000 
9001         // Otherwise this |async| begins an ExpressionStatement or is a
9002         // label name.
9003       }
9004 
9005       // NOTE: It's unfortunately allowed to have a label named 'let' in
9006       //       non-strict code.  ��
9007       if (next == TokenKind::Colon) {
9008         return labeledStatement(yieldHandling);
9009       }
9010 
9011       return expressionStatement(yieldHandling);
9012     }
9013 
9014     case TokenKind::New:
9015       return expressionStatement(yieldHandling, PredictInvoked);
9016 
9017     // IfStatement[?Yield, ?Return]
9018     case TokenKind::If:
9019       return ifStatement(yieldHandling);
9020 
9021     // BreakableStatement[?Yield, ?Return]
9022     //
9023     // BreakableStatement[Yield, Return]:
9024     //   IterationStatement[?Yield, ?Return]
9025     //   SwitchStatement[?Yield, ?Return]
9026     case TokenKind::Do:
9027       return doWhileStatement(yieldHandling);
9028 
9029     case TokenKind::While:
9030       return whileStatement(yieldHandling);
9031 
9032     case TokenKind::For:
9033       return forStatement(yieldHandling);
9034 
9035     case TokenKind::Switch:
9036       return switchStatement(yieldHandling);
9037 
9038     // ContinueStatement[?Yield]
9039     case TokenKind::Continue:
9040       return continueStatement(yieldHandling);
9041 
9042     // BreakStatement[?Yield]
9043     case TokenKind::Break:
9044       return breakStatement(yieldHandling);
9045 
9046     // [+Return] ReturnStatement[?Yield]
9047     case TokenKind::Return:
9048       // The Return parameter is only used here, and the effect is easily
9049       // detected this way, so don't bother passing around an extra parameter
9050       // everywhere.
9051       if (!pc_->allowReturn()) {
9052         error(JSMSG_BAD_RETURN_OR_YIELD, js_return_str);
9053         return null();
9054       }
9055       return returnStatement(yieldHandling);
9056 
9057     // WithStatement[?Yield, ?Return]
9058     case TokenKind::With:
9059       return withStatement(yieldHandling);
9060 
9061     // LabelledStatement[?Yield, ?Return]
9062     // This is really handled by default and TokenKind::Yield cases above.
9063 
9064     // ThrowStatement[?Yield]
9065     case TokenKind::Throw:
9066       return throwStatement(yieldHandling);
9067 
9068     // TryStatement[?Yield, ?Return]
9069     case TokenKind::Try:
9070       return tryStatement(yieldHandling);
9071 
9072     // DebuggerStatement
9073     case TokenKind::Debugger:
9074       return debuggerStatement();
9075 
9076     // |function| is forbidden by lookahead restriction (unless as child
9077     // statement of |if| or |else|, but Parser::consequentOrAlternative
9078     // handles that).
9079     case TokenKind::Function:
9080       error(JSMSG_FORBIDDEN_AS_STATEMENT, "function declarations");
9081       return null();
9082 
9083     // |class| is also forbidden by lookahead restriction.
9084     case TokenKind::Class:
9085       error(JSMSG_FORBIDDEN_AS_STATEMENT, "classes");
9086       return null();
9087 
9088     // ImportDeclaration (only inside modules)
9089     case TokenKind::Import:
9090       return importDeclarationOrImportExpr(yieldHandling);
9091 
9092     // ExportDeclaration (only inside modules)
9093     case TokenKind::Export:
9094       return exportDeclaration();
9095 
9096       // Miscellaneous error cases arguably better caught here than elsewhere.
9097 
9098     case TokenKind::Catch:
9099       error(JSMSG_CATCH_WITHOUT_TRY);
9100       return null();
9101 
9102     case TokenKind::Finally:
9103       error(JSMSG_FINALLY_WITHOUT_TRY);
9104       return null();
9105 
9106       // NOTE: default case handled in the ExpressionStatement section.
9107   }
9108 }
9109 
9110 template <class ParseHandler, typename Unit>
9111 typename ParseHandler::Node
statementListItem(YieldHandling yieldHandling,bool canHaveDirectives)9112 GeneralParser<ParseHandler, Unit>::statementListItem(
9113     YieldHandling yieldHandling, bool canHaveDirectives /* = false */) {
9114   MOZ_ASSERT(checkOptionsCalled_);
9115 
9116   AutoCheckRecursionLimit recursion(cx_);
9117   if (!recursion.check(cx_)) {
9118     return null();
9119   }
9120 
9121   TokenKind tt;
9122   if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) {
9123     return null();
9124   }
9125 
9126   switch (tt) {
9127     // BlockStatement[?Yield, ?Return]
9128     case TokenKind::LeftCurly:
9129       return blockStatement(yieldHandling);
9130 
9131     // VariableStatement[?Yield]
9132     case TokenKind::Var:
9133       return variableStatement(yieldHandling);
9134 
9135     // EmptyStatement
9136     case TokenKind::Semi:
9137       return handler_.newEmptyStatement(pos());
9138 
9139     // ExpressionStatement[?Yield].
9140     //
9141     // These should probably be handled by a single ExpressionStatement
9142     // function in a default, not split up this way.
9143     case TokenKind::String:
9144       if (!canHaveDirectives &&
9145           anyChars.currentToken().atom() ==
9146               TaggedParserAtomIndex::WellKnown::useAsm()) {
9147         if (!warning(JSMSG_USE_ASM_DIRECTIVE_FAIL)) {
9148           return null();
9149         }
9150       }
9151       return expressionStatement(yieldHandling);
9152 
9153     case TokenKind::Yield: {
9154       // Don't use a ternary operator here due to obscure linker issues
9155       // around using static consts in the arms of a ternary.
9156       Modifier modifier;
9157       if (yieldExpressionsSupported()) {
9158         modifier = TokenStream::SlashIsRegExp;
9159       } else {
9160         modifier = TokenStream::SlashIsDiv;
9161       }
9162 
9163       TokenKind next;
9164       if (!tokenStream.peekToken(&next, modifier)) {
9165         return null();
9166       }
9167 
9168       if (next == TokenKind::Colon) {
9169         return labeledStatement(yieldHandling);
9170       }
9171 
9172       return expressionStatement(yieldHandling);
9173     }
9174 
9175     default: {
9176       // If we encounter an await in a module, and the module is not marked
9177       // as async, mark the module as async.
9178       if (tt == TokenKind::Await && !pc_->isAsync()) {
9179         if (pc_->atModuleTopLevel()) {
9180           pc_->sc()->asModuleContext()->setIsAsync();
9181           MOZ_ASSERT(pc_->isAsync());
9182         }
9183       }
9184 
9185       // Avoid getting next token with SlashIsDiv.
9186       if (tt == TokenKind::Await && pc_->isAsync()) {
9187         return expressionStatement(yieldHandling);
9188       }
9189 
9190       if (!TokenKindIsPossibleIdentifier(tt)) {
9191         return expressionStatement(yieldHandling);
9192       }
9193 
9194       TokenKind next;
9195       if (!tokenStream.peekToken(&next)) {
9196         return null();
9197       }
9198 
9199       if (tt == TokenKind::Let && nextTokenContinuesLetDeclaration(next)) {
9200         return lexicalDeclaration(yieldHandling, DeclarationKind::Let);
9201       }
9202 
9203       if (tt == TokenKind::Async) {
9204         TokenKind nextSameLine = TokenKind::Eof;
9205         if (!tokenStream.peekTokenSameLine(&nextSameLine)) {
9206           return null();
9207         }
9208         if (nextSameLine == TokenKind::Function) {
9209           uint32_t toStringStart = pos().begin;
9210           tokenStream.consumeKnownToken(TokenKind::Function);
9211           return functionStmt(toStringStart, yieldHandling, NameRequired,
9212                               FunctionAsyncKind::AsyncFunction);
9213         }
9214       }
9215 
9216       if (next == TokenKind::Colon) {
9217         return labeledStatement(yieldHandling);
9218       }
9219 
9220       return expressionStatement(yieldHandling);
9221     }
9222 
9223     case TokenKind::New:
9224       return expressionStatement(yieldHandling, PredictInvoked);
9225 
9226     // IfStatement[?Yield, ?Return]
9227     case TokenKind::If:
9228       return ifStatement(yieldHandling);
9229 
9230     // BreakableStatement[?Yield, ?Return]
9231     //
9232     // BreakableStatement[Yield, Return]:
9233     //   IterationStatement[?Yield, ?Return]
9234     //   SwitchStatement[?Yield, ?Return]
9235     case TokenKind::Do:
9236       return doWhileStatement(yieldHandling);
9237 
9238     case TokenKind::While:
9239       return whileStatement(yieldHandling);
9240 
9241     case TokenKind::For:
9242       return forStatement(yieldHandling);
9243 
9244     case TokenKind::Switch:
9245       return switchStatement(yieldHandling);
9246 
9247     // ContinueStatement[?Yield]
9248     case TokenKind::Continue:
9249       return continueStatement(yieldHandling);
9250 
9251     // BreakStatement[?Yield]
9252     case TokenKind::Break:
9253       return breakStatement(yieldHandling);
9254 
9255     // [+Return] ReturnStatement[?Yield]
9256     case TokenKind::Return:
9257       // The Return parameter is only used here, and the effect is easily
9258       // detected this way, so don't bother passing around an extra parameter
9259       // everywhere.
9260       if (!pc_->allowReturn()) {
9261         error(JSMSG_BAD_RETURN_OR_YIELD, js_return_str);
9262         return null();
9263       }
9264       return returnStatement(yieldHandling);
9265 
9266     // WithStatement[?Yield, ?Return]
9267     case TokenKind::With:
9268       return withStatement(yieldHandling);
9269 
9270     // LabelledStatement[?Yield, ?Return]
9271     // This is really handled by default and TokenKind::Yield cases above.
9272 
9273     // ThrowStatement[?Yield]
9274     case TokenKind::Throw:
9275       return throwStatement(yieldHandling);
9276 
9277     // TryStatement[?Yield, ?Return]
9278     case TokenKind::Try:
9279       return tryStatement(yieldHandling);
9280 
9281     // DebuggerStatement
9282     case TokenKind::Debugger:
9283       return debuggerStatement();
9284 
9285     // Declaration[Yield]:
9286 
9287     //   HoistableDeclaration[?Yield, ~Default]
9288     case TokenKind::Function:
9289       return functionStmt(pos().begin, yieldHandling, NameRequired);
9290 
9291     //   ClassDeclaration[?Yield, ~Default]
9292     case TokenKind::Class:
9293       return classDefinition(yieldHandling, ClassStatement, NameRequired);
9294 
9295     //   LexicalDeclaration[In, ?Yield]
9296     //     LetOrConst BindingList[?In, ?Yield]
9297     case TokenKind::Const:
9298       // [In] is the default behavior, because for-loops specially parse
9299       // their heads to handle |in| in this situation.
9300       return lexicalDeclaration(yieldHandling, DeclarationKind::Const);
9301 
9302     // ImportDeclaration (only inside modules)
9303     case TokenKind::Import:
9304       return importDeclarationOrImportExpr(yieldHandling);
9305 
9306     // ExportDeclaration (only inside modules)
9307     case TokenKind::Export:
9308       return exportDeclaration();
9309 
9310       // Miscellaneous error cases arguably better caught here than elsewhere.
9311 
9312     case TokenKind::Catch:
9313       error(JSMSG_CATCH_WITHOUT_TRY);
9314       return null();
9315 
9316     case TokenKind::Finally:
9317       error(JSMSG_FINALLY_WITHOUT_TRY);
9318       return null();
9319 
9320       // NOTE: default case handled in the ExpressionStatement section.
9321   }
9322 }
9323 
9324 template <class ParseHandler, typename Unit>
expr(InHandling inHandling,YieldHandling yieldHandling,TripledotHandling tripledotHandling,PossibleError * possibleError,InvokedPrediction invoked)9325 typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::expr(
9326     InHandling inHandling, YieldHandling yieldHandling,
9327     TripledotHandling tripledotHandling,
9328     PossibleError* possibleError /* = nullptr */,
9329     InvokedPrediction invoked /* = PredictUninvoked */) {
9330   Node pn = assignExpr(inHandling, yieldHandling, tripledotHandling,
9331                        possibleError, invoked);
9332   if (!pn) {
9333     return null();
9334   }
9335 
9336   bool matched;
9337   if (!tokenStream.matchToken(&matched, TokenKind::Comma,
9338                               TokenStream::SlashIsRegExp)) {
9339     return null();
9340   }
9341   if (!matched) {
9342     return pn;
9343   }
9344 
9345   ListNodeType seq = handler_.newCommaExpressionList(pn);
9346   if (!seq) {
9347     return null();
9348   }
9349   while (true) {
9350     // Trailing comma before the closing parenthesis is valid in an arrow
9351     // function parameters list: `(a, b, ) => body`. Check if we are
9352     // directly under CoverParenthesizedExpressionAndArrowParameterList,
9353     // and the next two tokens are closing parenthesis and arrow. If all
9354     // are present allow the trailing comma.
9355     if (tripledotHandling == TripledotAllowed) {
9356       TokenKind tt;
9357       if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) {
9358         return null();
9359       }
9360 
9361       if (tt == TokenKind::RightParen) {
9362         tokenStream.consumeKnownToken(TokenKind::RightParen,
9363                                       TokenStream::SlashIsRegExp);
9364 
9365         if (!tokenStream.peekToken(&tt)) {
9366           return null();
9367         }
9368         if (tt != TokenKind::Arrow) {
9369           error(JSMSG_UNEXPECTED_TOKEN, "expression",
9370                 TokenKindToDesc(TokenKind::RightParen));
9371           return null();
9372         }
9373 
9374         anyChars.ungetToken();  // put back right paren
9375         break;
9376       }
9377     }
9378 
9379     // Additional calls to assignExpr should not reuse the possibleError
9380     // which had been passed into the function. Otherwise we would lose
9381     // information needed to determine whether or not we're dealing with
9382     // a non-recoverable situation.
9383     PossibleError possibleErrorInner(*this);
9384     pn = assignExpr(inHandling, yieldHandling, tripledotHandling,
9385                     &possibleErrorInner);
9386     if (!pn) {
9387       return null();
9388     }
9389 
9390     if (!possibleError) {
9391       // Report any pending expression error.
9392       if (!possibleErrorInner.checkForExpressionError()) {
9393         return null();
9394       }
9395     } else {
9396       possibleErrorInner.transferErrorsTo(possibleError);
9397     }
9398 
9399     handler_.addList(seq, pn);
9400 
9401     if (!tokenStream.matchToken(&matched, TokenKind::Comma,
9402                                 TokenStream::SlashIsRegExp)) {
9403       return null();
9404     }
9405     if (!matched) {
9406       break;
9407     }
9408   }
9409   return seq;
9410 }
9411 
BinaryOpTokenKindToParseNodeKind(TokenKind tok)9412 static ParseNodeKind BinaryOpTokenKindToParseNodeKind(TokenKind tok) {
9413   MOZ_ASSERT(TokenKindIsBinaryOp(tok));
9414   return ParseNodeKind(size_t(ParseNodeKind::BinOpFirst) +
9415                        (size_t(tok) - size_t(TokenKind::BinOpFirst)));
9416 }
9417 
9418 // This list must be kept in the same order in several places:
9419 //   - The binary operators in ParseNode.h ,
9420 //   - the binary operators in TokenKind.h
9421 //   - the JSOp code list in BytecodeEmitter.cpp
9422 static const int PrecedenceTable[] = {
9423     1,  /* ParseNodeKind::Coalesce */
9424     2,  /* ParseNodeKind::Or */
9425     3,  /* ParseNodeKind::And */
9426     4,  /* ParseNodeKind::BitOr */
9427     5,  /* ParseNodeKind::BitXor */
9428     6,  /* ParseNodeKind::BitAnd */
9429     7,  /* ParseNodeKind::StrictEq */
9430     7,  /* ParseNodeKind::Eq */
9431     7,  /* ParseNodeKind::StrictNe */
9432     7,  /* ParseNodeKind::Ne */
9433     8,  /* ParseNodeKind::Lt */
9434     8,  /* ParseNodeKind::Le */
9435     8,  /* ParseNodeKind::Gt */
9436     8,  /* ParseNodeKind::Ge */
9437     8,  /* ParseNodeKind::InstanceOf */
9438     8,  /* ParseNodeKind::In */
9439     8,  /* ParseNodeKind::PrivateIn */
9440     9,  /* ParseNodeKind::Lsh */
9441     9,  /* ParseNodeKind::Rsh */
9442     9,  /* ParseNodeKind::Ursh */
9443     10, /* ParseNodeKind::Add */
9444     10, /* ParseNodeKind::Sub */
9445     11, /* ParseNodeKind::Star */
9446     11, /* ParseNodeKind::Div */
9447     11, /* ParseNodeKind::Mod */
9448     12  /* ParseNodeKind::Pow */
9449 };
9450 
9451 static const int PRECEDENCE_CLASSES = 12;
9452 
Precedence(ParseNodeKind pnk)9453 static int Precedence(ParseNodeKind pnk) {
9454   // Everything binds tighter than ParseNodeKind::Limit, because we want
9455   // to reduce all nodes to a single node when we reach a token that is not
9456   // another binary operator.
9457   if (pnk == ParseNodeKind::Limit) {
9458     return 0;
9459   }
9460 
9461   MOZ_ASSERT(pnk >= ParseNodeKind::BinOpFirst);
9462   MOZ_ASSERT(pnk <= ParseNodeKind::BinOpLast);
9463   return PrecedenceTable[size_t(pnk) - size_t(ParseNodeKind::BinOpFirst)];
9464 }
9465 
9466 enum class EnforcedParentheses : uint8_t { CoalesceExpr, AndOrExpr, None };
9467 
9468 template <class ParseHandler, typename Unit>
9469 MOZ_ALWAYS_INLINE typename ParseHandler::Node
orExpr(InHandling inHandling,YieldHandling yieldHandling,TripledotHandling tripledotHandling,PossibleError * possibleError,InvokedPrediction invoked)9470 GeneralParser<ParseHandler, Unit>::orExpr(InHandling inHandling,
9471                                           YieldHandling yieldHandling,
9472                                           TripledotHandling tripledotHandling,
9473                                           PossibleError* possibleError,
9474                                           InvokedPrediction invoked) {
9475   // Shift-reduce parser for the binary operator part of the JS expression
9476   // syntax.
9477 
9478   // Conceptually there's just one stack, a stack of pairs (lhs, op).
9479   // It's implemented using two separate arrays, though.
9480   Node nodeStack[PRECEDENCE_CLASSES];
9481   ParseNodeKind kindStack[PRECEDENCE_CLASSES];
9482   int depth = 0;
9483   Node pn;
9484   EnforcedParentheses unparenthesizedExpression = EnforcedParentheses::None;
9485   for (;;) {
9486     pn = unaryExpr(yieldHandling, tripledotHandling, possibleError, invoked,
9487                    PrivateNameHandling::PrivateNameAllowed);
9488     if (!pn) {
9489       return null();
9490     }
9491 
9492     // If a binary operator follows, consume it and compute the
9493     // corresponding operator.
9494     TokenKind tok;
9495     if (!tokenStream.getToken(&tok)) {
9496       return null();
9497     }
9498 
9499     // Ensure that if we have a private name lhs we are legally constructing a
9500     // `#x in obj` expessions:
9501     if (handler_.isPrivateName(pn)) {
9502       if (tok != TokenKind::In || inHandling != InAllowed) {
9503         error(JSMSG_ILLEGAL_PRIVATE_NAME);
9504         return null();
9505       }
9506     }
9507 
9508     ParseNodeKind pnk;
9509     if (tok == TokenKind::In ? inHandling == InAllowed
9510                              : TokenKindIsBinaryOp(tok)) {
9511       // We're definitely not in a destructuring context, so report any
9512       // pending expression error now.
9513       if (possibleError && !possibleError->checkForExpressionError()) {
9514         return null();
9515       }
9516 
9517       bool isErgonomicBrandCheck = false;
9518       switch (tok) {
9519         // Report an error for unary expressions on the LHS of **.
9520         case TokenKind::Pow:
9521           if (handler_.isUnparenthesizedUnaryExpression(pn)) {
9522             error(JSMSG_BAD_POW_LEFTSIDE);
9523             return null();
9524           }
9525           break;
9526 
9527         case TokenKind::Or:
9528         case TokenKind::And:
9529           // In the case that the `??` is on the left hand side of the
9530           // expression: Disallow Mixing of ?? and other logical operators (||
9531           // and &&) unless one expression is parenthesized
9532           if (unparenthesizedExpression == EnforcedParentheses::CoalesceExpr) {
9533             error(JSMSG_BAD_COALESCE_MIXING);
9534             return null();
9535           }
9536           // If we have not detected a mixing error at this point, record that
9537           // we have an unparenthesized expression, in case we have one later.
9538           unparenthesizedExpression = EnforcedParentheses::AndOrExpr;
9539           break;
9540 
9541         case TokenKind::Coalesce:
9542           if (unparenthesizedExpression == EnforcedParentheses::AndOrExpr) {
9543             error(JSMSG_BAD_COALESCE_MIXING);
9544             return null();
9545           }
9546           // If we have not detected a mixing error at this point, record that
9547           // we have an unparenthesized expression, in case we have one later.
9548           unparenthesizedExpression = EnforcedParentheses::CoalesceExpr;
9549           break;
9550 
9551         case TokenKind::In:
9552           // if the LHS is a private name, and the operator is In,
9553           // ensure we're construcing an ergonomic brand check of
9554           // '#x in y', rather than having a higher precedence operator
9555           // like + cause a different reduction, such as
9556           // 1 + #x in y.
9557           if (handler_.isPrivateName(pn)) {
9558             if (depth > 0 && Precedence(kindStack[depth - 1]) >=
9559                                  Precedence(ParseNodeKind::InExpr)) {
9560               error(JSMSG_INVALID_PRIVATE_NAME_PRECEDENCE);
9561               return null();
9562             }
9563 
9564             isErgonomicBrandCheck = true;
9565           }
9566           break;
9567 
9568         default:
9569           // do nothing in other cases
9570           break;
9571       }
9572 
9573       if (isErgonomicBrandCheck) {
9574         pnk = ParseNodeKind::PrivateInExpr;
9575       } else {
9576         pnk = BinaryOpTokenKindToParseNodeKind(tok);
9577       }
9578 
9579     } else {
9580       tok = TokenKind::Eof;
9581       pnk = ParseNodeKind::Limit;
9582     }
9583 
9584     // From this point on, destructuring defaults are definitely an error.
9585     possibleError = nullptr;
9586 
9587     // If pnk has precedence less than or equal to another operator on the
9588     // stack, reduce. This combines nodes on the stack until we form the
9589     // actual lhs of pnk.
9590     //
9591     // The >= in this condition works because it is appendOrCreateList's
9592     // job to decide if the operator in question is left- or
9593     // right-associative, and build the corresponding tree.
9594     while (depth > 0 && Precedence(kindStack[depth - 1]) >= Precedence(pnk)) {
9595       depth--;
9596       ParseNodeKind combiningPnk = kindStack[depth];
9597       pn = handler_.appendOrCreateList(combiningPnk, nodeStack[depth], pn, pc_);
9598 
9599       if (!pn) {
9600         return null();
9601       }
9602     }
9603 
9604     if (pnk == ParseNodeKind::Limit) {
9605       break;
9606     }
9607 
9608     nodeStack[depth] = pn;
9609     kindStack[depth] = pnk;
9610     depth++;
9611     MOZ_ASSERT(depth <= PRECEDENCE_CLASSES);
9612   }
9613 
9614   anyChars.ungetToken();
9615 
9616   // Had the next token been a Div, we would have consumed it. So there's no
9617   // ambiguity if we later (after ASI) re-get this token with SlashIsRegExp.
9618   anyChars.allowGettingNextTokenWithSlashIsRegExp();
9619 
9620   MOZ_ASSERT(depth == 0);
9621   return pn;
9622 }
9623 
9624 template <class ParseHandler, typename Unit>
9625 MOZ_ALWAYS_INLINE typename ParseHandler::Node
condExpr(InHandling inHandling,YieldHandling yieldHandling,TripledotHandling tripledotHandling,PossibleError * possibleError,InvokedPrediction invoked)9626 GeneralParser<ParseHandler, Unit>::condExpr(InHandling inHandling,
9627                                             YieldHandling yieldHandling,
9628                                             TripledotHandling tripledotHandling,
9629                                             PossibleError* possibleError,
9630                                             InvokedPrediction invoked) {
9631   Node condition = orExpr(inHandling, yieldHandling, tripledotHandling,
9632                           possibleError, invoked);
9633   if (!condition) {
9634     return null();
9635   }
9636 
9637   bool matched;
9638   if (!tokenStream.matchToken(&matched, TokenKind::Hook,
9639                               TokenStream::SlashIsInvalid)) {
9640     return null();
9641   }
9642   if (!matched) {
9643     return condition;
9644   }
9645 
9646   Node thenExpr = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
9647   if (!thenExpr) {
9648     return null();
9649   }
9650 
9651   if (!mustMatchToken(TokenKind::Colon, JSMSG_COLON_IN_COND)) {
9652     return null();
9653   }
9654 
9655   Node elseExpr = assignExpr(inHandling, yieldHandling, TripledotProhibited);
9656   if (!elseExpr) {
9657     return null();
9658   }
9659 
9660   return handler_.newConditional(condition, thenExpr, elseExpr);
9661 }
9662 
9663 template <class ParseHandler, typename Unit>
assignExpr(InHandling inHandling,YieldHandling yieldHandling,TripledotHandling tripledotHandling,PossibleError * possibleError,InvokedPrediction invoked)9664 typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::assignExpr(
9665     InHandling inHandling, YieldHandling yieldHandling,
9666     TripledotHandling tripledotHandling,
9667     PossibleError* possibleError /* = nullptr */,
9668     InvokedPrediction invoked /* = PredictUninvoked */) {
9669   AutoCheckRecursionLimit recursion(cx_);
9670   if (!recursion.check(cx_)) {
9671     return null();
9672   }
9673 
9674   // It's very common at this point to have a "detectably simple" expression,
9675   // i.e. a name/number/string token followed by one of the following tokens
9676   // that obviously isn't part of an expression: , ; : ) ] }
9677   //
9678   // (In Parsemark this happens 81.4% of the time;  in code with large
9679   // numeric arrays, such as some Kraken benchmarks, it happens more often.)
9680   //
9681   // In such cases, we can avoid the full expression parsing route through
9682   // assignExpr(), condExpr(), orExpr(), unaryExpr(), memberExpr(), and
9683   // primaryExpr().
9684 
9685   TokenKind firstToken;
9686   if (!tokenStream.getToken(&firstToken, TokenStream::SlashIsRegExp)) {
9687     return null();
9688   }
9689 
9690   TokenPos exprPos = pos();
9691 
9692   bool endsExpr;
9693 
9694   // This only handles identifiers that *never* have special meaning anywhere
9695   // in the language.  Contextual keywords, reserved words in strict mode,
9696   // and other hard cases are handled outside this fast path.
9697   if (firstToken == TokenKind::Name) {
9698     if (!tokenStream.nextTokenEndsExpr(&endsExpr)) {
9699       return null();
9700     }
9701     if (endsExpr) {
9702       TaggedParserAtomIndex name = identifierReference(yieldHandling);
9703       if (!name) {
9704         return null();
9705       }
9706 
9707       return identifierReference(name);
9708     }
9709   }
9710 
9711   if (firstToken == TokenKind::Number) {
9712     if (!tokenStream.nextTokenEndsExpr(&endsExpr)) {
9713       return null();
9714     }
9715     if (endsExpr) {
9716       return newNumber(anyChars.currentToken());
9717     }
9718   }
9719 
9720   if (firstToken == TokenKind::String) {
9721     if (!tokenStream.nextTokenEndsExpr(&endsExpr)) {
9722       return null();
9723     }
9724     if (endsExpr) {
9725       return stringLiteral();
9726     }
9727   }
9728 
9729   if (firstToken == TokenKind::Yield && yieldExpressionsSupported()) {
9730     return yieldExpression(inHandling);
9731   }
9732 
9733   bool maybeAsyncArrow = false;
9734   if (firstToken == TokenKind::Async) {
9735     TokenKind nextSameLine = TokenKind::Eof;
9736     if (!tokenStream.peekTokenSameLine(&nextSameLine)) {
9737       return null();
9738     }
9739 
9740     if (TokenKindIsPossibleIdentifier(nextSameLine)) {
9741       maybeAsyncArrow = true;
9742     }
9743   }
9744 
9745   anyChars.ungetToken();
9746 
9747   // Save the tokenizer state in case we find an arrow function and have to
9748   // rewind.
9749   Position start(tokenStream);
9750   auto ghostToken = this->compilationState_.getPosition();
9751 
9752   PossibleError possibleErrorInner(*this);
9753   Node lhs;
9754   TokenKind tokenAfterLHS;
9755   bool isArrow;
9756   if (maybeAsyncArrow) {
9757     tokenStream.consumeKnownToken(TokenKind::Async, TokenStream::SlashIsRegExp);
9758 
9759     TokenKind tokenAfterAsync;
9760     if (!tokenStream.getToken(&tokenAfterAsync)) {
9761       return null();
9762     }
9763     MOZ_ASSERT(TokenKindIsPossibleIdentifier(tokenAfterAsync));
9764 
9765     // Check yield validity here.
9766     TaggedParserAtomIndex name = bindingIdentifier(yieldHandling);
9767     if (!name) {
9768       return null();
9769     }
9770 
9771     if (!tokenStream.peekToken(&tokenAfterLHS, TokenStream::SlashIsRegExp)) {
9772       return null();
9773     }
9774 
9775     isArrow = tokenAfterLHS == TokenKind::Arrow;
9776 
9777     // |async [no LineTerminator] of| without being followed by => is only
9778     // possible in for-await-of loops, e.g. |for await (async of [])|. Pretend
9779     // the |async| token was parsed an identifier reference and then proceed
9780     // with the rest of this function.
9781     if (!isArrow) {
9782       anyChars.ungetToken();  // unget the binding identifier
9783 
9784       // The next token is guaranteed to never be a Div (, because it's an
9785       // identifier), so it's okay to re-get the token with SlashIsRegExp.
9786       anyChars.allowGettingNextTokenWithSlashIsRegExp();
9787 
9788       TaggedParserAtomIndex asyncName = identifierReference(yieldHandling);
9789       if (!asyncName) {
9790         return null();
9791       }
9792 
9793       lhs = identifierReference(asyncName);
9794       if (!lhs) {
9795         return null();
9796       }
9797     }
9798   } else {
9799     lhs = condExpr(inHandling, yieldHandling, tripledotHandling,
9800                    &possibleErrorInner, invoked);
9801     if (!lhs) {
9802       return null();
9803     }
9804 
9805     // Use SlashIsRegExp here because the ConditionalExpression parsed above
9806     // could be the entirety of this AssignmentExpression, and then ASI
9807     // permits this token to be a regular expression.
9808     if (!tokenStream.peekToken(&tokenAfterLHS, TokenStream::SlashIsRegExp)) {
9809       return null();
9810     }
9811 
9812     isArrow = tokenAfterLHS == TokenKind::Arrow;
9813   }
9814 
9815   if (isArrow) {
9816     // Rewind to reparse as an arrow function.
9817     //
9818     // Note: We do not call CompilationState::rewind here because parsing
9819     // during delazification will see the same rewind and need the same sequence
9820     // of inner functions to skip over.
9821     // Instead, we mark inner functions as "ghost".
9822     //
9823     // See GHOST_FUNCTION in FunctionFlags.h for more details.
9824     tokenStream.rewind(start);
9825     this->compilationState_.markGhost(ghostToken);
9826 
9827     TokenKind next;
9828     if (!tokenStream.getToken(&next, TokenStream::SlashIsRegExp)) {
9829       return null();
9830     }
9831     TokenPos startPos = pos();
9832     uint32_t toStringStart = startPos.begin;
9833     anyChars.ungetToken();
9834 
9835     FunctionAsyncKind asyncKind = FunctionAsyncKind::SyncFunction;
9836 
9837     if (next == TokenKind::Async) {
9838       tokenStream.consumeKnownToken(next, TokenStream::SlashIsRegExp);
9839 
9840       TokenKind nextSameLine = TokenKind::Eof;
9841       if (!tokenStream.peekTokenSameLine(&nextSameLine)) {
9842         return null();
9843       }
9844 
9845       // The AsyncArrowFunction production are
9846       //   async [no LineTerminator here] AsyncArrowBindingIdentifier ...
9847       //   async [no LineTerminator here] ArrowFormalParameters ...
9848       if (TokenKindIsPossibleIdentifier(nextSameLine) ||
9849           nextSameLine == TokenKind::LeftParen) {
9850         asyncKind = FunctionAsyncKind::AsyncFunction;
9851       } else {
9852         anyChars.ungetToken();
9853       }
9854     }
9855 
9856     FunctionSyntaxKind syntaxKind = FunctionSyntaxKind::Arrow;
9857     FunctionNodeType funNode = handler_.newFunction(syntaxKind, startPos);
9858     if (!funNode) {
9859       return null();
9860     }
9861 
9862     return functionDefinition(funNode, toStringStart, inHandling, yieldHandling,
9863                               TaggedParserAtomIndex::null(), syntaxKind,
9864                               GeneratorKind::NotGenerator, asyncKind);
9865   }
9866 
9867   MOZ_ALWAYS_TRUE(
9868       tokenStream.getToken(&tokenAfterLHS, TokenStream::SlashIsRegExp));
9869 
9870   ParseNodeKind kind;
9871   switch (tokenAfterLHS) {
9872     case TokenKind::Assign:
9873       kind = ParseNodeKind::AssignExpr;
9874       break;
9875     case TokenKind::AddAssign:
9876       kind = ParseNodeKind::AddAssignExpr;
9877       break;
9878     case TokenKind::SubAssign:
9879       kind = ParseNodeKind::SubAssignExpr;
9880       break;
9881     case TokenKind::CoalesceAssign:
9882       kind = ParseNodeKind::CoalesceAssignExpr;
9883       break;
9884     case TokenKind::OrAssign:
9885       kind = ParseNodeKind::OrAssignExpr;
9886       break;
9887     case TokenKind::AndAssign:
9888       kind = ParseNodeKind::AndAssignExpr;
9889       break;
9890     case TokenKind::BitOrAssign:
9891       kind = ParseNodeKind::BitOrAssignExpr;
9892       break;
9893     case TokenKind::BitXorAssign:
9894       kind = ParseNodeKind::BitXorAssignExpr;
9895       break;
9896     case TokenKind::BitAndAssign:
9897       kind = ParseNodeKind::BitAndAssignExpr;
9898       break;
9899     case TokenKind::LshAssign:
9900       kind = ParseNodeKind::LshAssignExpr;
9901       break;
9902     case TokenKind::RshAssign:
9903       kind = ParseNodeKind::RshAssignExpr;
9904       break;
9905     case TokenKind::UrshAssign:
9906       kind = ParseNodeKind::UrshAssignExpr;
9907       break;
9908     case TokenKind::MulAssign:
9909       kind = ParseNodeKind::MulAssignExpr;
9910       break;
9911     case TokenKind::DivAssign:
9912       kind = ParseNodeKind::DivAssignExpr;
9913       break;
9914     case TokenKind::ModAssign:
9915       kind = ParseNodeKind::ModAssignExpr;
9916       break;
9917     case TokenKind::PowAssign:
9918       kind = ParseNodeKind::PowAssignExpr;
9919       break;
9920 
9921     default:
9922       MOZ_ASSERT(!anyChars.isCurrentTokenAssignment());
9923       if (!possibleError) {
9924         if (!possibleErrorInner.checkForExpressionError()) {
9925           return null();
9926         }
9927       } else {
9928         possibleErrorInner.transferErrorsTo(possibleError);
9929       }
9930 
9931       anyChars.ungetToken();
9932       return lhs;
9933   }
9934 
9935   // Verify the left-hand side expression doesn't have a forbidden form.
9936   if (handler_.isUnparenthesizedDestructuringPattern(lhs)) {
9937     if (kind != ParseNodeKind::AssignExpr) {
9938       error(JSMSG_BAD_DESTRUCT_ASS);
9939       return null();
9940     }
9941 
9942     if (!possibleErrorInner.checkForDestructuringErrorOrWarning()) {
9943       return null();
9944     }
9945   } else if (handler_.isName(lhs)) {
9946     if (const char* chars = nameIsArgumentsOrEval(lhs)) {
9947       // |chars| is "arguments" or "eval" here.
9948       if (!strictModeErrorAt(exprPos.begin, JSMSG_BAD_STRICT_ASSIGN, chars)) {
9949         return null();
9950       }
9951     }
9952   } else if (handler_.isPropertyOrPrivateMemberAccess(lhs)) {
9953     // Permitted: no additional testing/fixup needed.
9954   } else if (handler_.isFunctionCall(lhs)) {
9955     // We don't have to worry about backward compatibility issues with the new
9956     // compound assignment operators, so we always throw here. Also that way we
9957     // don't have to worry if |f() &&= expr| should always throw an error or
9958     // only if |f()| returns true.
9959     if (kind == ParseNodeKind::CoalesceAssignExpr ||
9960         kind == ParseNodeKind::OrAssignExpr ||
9961         kind == ParseNodeKind::AndAssignExpr) {
9962       errorAt(exprPos.begin, JSMSG_BAD_LEFTSIDE_OF_ASS);
9963       return null();
9964     }
9965 
9966     if (!strictModeErrorAt(exprPos.begin, JSMSG_BAD_LEFTSIDE_OF_ASS)) {
9967       return null();
9968     }
9969 
9970     if (possibleError) {
9971       possibleError->setPendingDestructuringErrorAt(exprPos,
9972                                                     JSMSG_BAD_DESTRUCT_TARGET);
9973     }
9974   } else {
9975     errorAt(exprPos.begin, JSMSG_BAD_LEFTSIDE_OF_ASS);
9976     return null();
9977   }
9978 
9979   if (!possibleErrorInner.checkForExpressionError()) {
9980     return null();
9981   }
9982 
9983   Node rhs = assignExpr(inHandling, yieldHandling, TripledotProhibited);
9984   if (!rhs) {
9985     return null();
9986   }
9987 
9988   return handler_.newAssignment(kind, lhs, rhs);
9989 }
9990 
9991 template <class ParseHandler>
nameIsArgumentsOrEval(Node node)9992 const char* PerHandlerParser<ParseHandler>::nameIsArgumentsOrEval(Node node) {
9993   MOZ_ASSERT(handler_.isName(node),
9994              "must only call this function on known names");
9995 
9996   if (handler_.isEvalName(node)) {
9997     return js_eval_str;
9998   }
9999   if (handler_.isArgumentsName(node)) {
10000     return js_arguments_str;
10001   }
10002   return nullptr;
10003 }
10004 
10005 template <class ParseHandler, typename Unit>
checkIncDecOperand(Node operand,uint32_t operandOffset)10006 bool GeneralParser<ParseHandler, Unit>::checkIncDecOperand(
10007     Node operand, uint32_t operandOffset) {
10008   if (handler_.isName(operand)) {
10009     if (const char* chars = nameIsArgumentsOrEval(operand)) {
10010       if (!strictModeErrorAt(operandOffset, JSMSG_BAD_STRICT_ASSIGN, chars)) {
10011         return false;
10012       }
10013     }
10014   } else if (handler_.isPropertyOrPrivateMemberAccess(operand)) {
10015     // Permitted: no additional testing/fixup needed.
10016   } else if (handler_.isFunctionCall(operand)) {
10017     // Assignment to function calls is forbidden in ES6.  We're still
10018     // somewhat concerned about sites using this in dead code, so forbid it
10019     // only in strict mode code.
10020     if (!strictModeErrorAt(operandOffset, JSMSG_BAD_INCOP_OPERAND)) {
10021       return false;
10022     }
10023   } else {
10024     errorAt(operandOffset, JSMSG_BAD_INCOP_OPERAND);
10025     return false;
10026   }
10027   return true;
10028 }
10029 
10030 template <class ParseHandler, typename Unit>
10031 typename ParseHandler::UnaryNodeType
unaryOpExpr(YieldHandling yieldHandling,ParseNodeKind kind,uint32_t begin)10032 GeneralParser<ParseHandler, Unit>::unaryOpExpr(YieldHandling yieldHandling,
10033                                                ParseNodeKind kind,
10034                                                uint32_t begin) {
10035   Node kid = unaryExpr(yieldHandling, TripledotProhibited);
10036   if (!kid) {
10037     return null();
10038   }
10039   return handler_.newUnary(kind, begin, kid);
10040 }
10041 
10042 template <class ParseHandler, typename Unit>
optionalExpr(YieldHandling yieldHandling,TripledotHandling tripledotHandling,TokenKind tt,PossibleError * possibleError,InvokedPrediction invoked)10043 typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::optionalExpr(
10044     YieldHandling yieldHandling, TripledotHandling tripledotHandling,
10045     TokenKind tt, PossibleError* possibleError /* = nullptr */,
10046     InvokedPrediction invoked /* = PredictUninvoked */) {
10047   AutoCheckRecursionLimit recursion(cx_);
10048   if (!recursion.check(cx_)) {
10049     return null();
10050   }
10051 
10052   uint32_t begin = pos().begin;
10053 
10054   Node lhs = memberExpr(yieldHandling, tripledotHandling, tt,
10055                         /* allowCallSyntax = */ true, possibleError, invoked);
10056   if (!lhs) {
10057     return null();
10058   }
10059 
10060   if (!tokenStream.peekToken(&tt, TokenStream::SlashIsDiv)) {
10061     return null();
10062   }
10063 
10064   if (tt != TokenKind::OptionalChain) {
10065     return lhs;
10066   }
10067 
10068   while (true) {
10069     if (!tokenStream.getToken(&tt)) {
10070       return null();
10071     }
10072 
10073     if (tt == TokenKind::Eof) {
10074       anyChars.ungetToken();
10075       break;
10076     }
10077 
10078     Node nextMember;
10079     if (tt == TokenKind::OptionalChain) {
10080       if (!tokenStream.getToken(&tt)) {
10081         return null();
10082       }
10083       if (TokenKindIsPossibleIdentifierName(tt)) {
10084         nextMember = memberPropertyAccess(lhs, OptionalKind::Optional);
10085         if (!nextMember) {
10086           return null();
10087         }
10088       } else if (tt == TokenKind::PrivateName) {
10089         nextMember = memberPrivateAccess(lhs, OptionalKind::Optional);
10090         if (!nextMember) {
10091           return null();
10092         }
10093       } else if (tt == TokenKind::LeftBracket) {
10094         nextMember =
10095             memberElemAccess(lhs, yieldHandling, OptionalKind::Optional);
10096         if (!nextMember) {
10097           return null();
10098         }
10099       } else if (tt == TokenKind::LeftParen) {
10100         nextMember = memberCall(tt, lhs, yieldHandling, possibleError,
10101                                 OptionalKind::Optional);
10102         if (!nextMember) {
10103           return null();
10104         }
10105       } else {
10106         error(JSMSG_NAME_AFTER_DOT);
10107         return null();
10108       }
10109     } else if (tt == TokenKind::Dot) {
10110       if (!tokenStream.getToken(&tt)) {
10111         return null();
10112       }
10113       if (TokenKindIsPossibleIdentifierName(tt)) {
10114         nextMember = memberPropertyAccess(lhs);
10115         if (!nextMember) {
10116           return null();
10117         }
10118       } else if (tt == TokenKind::PrivateName) {
10119         nextMember = memberPrivateAccess(lhs);
10120         if (!nextMember) {
10121           return null();
10122         }
10123       } else {
10124         error(JSMSG_NAME_AFTER_DOT);
10125         return null();
10126       }
10127     } else if (tt == TokenKind::LeftBracket) {
10128       nextMember = memberElemAccess(lhs, yieldHandling);
10129       if (!nextMember) {
10130         return null();
10131       }
10132     } else if (tt == TokenKind::LeftParen) {
10133       nextMember = memberCall(tt, lhs, yieldHandling, possibleError);
10134       if (!nextMember) {
10135         return null();
10136       }
10137     } else if (tt == TokenKind::TemplateHead ||
10138                tt == TokenKind::NoSubsTemplate) {
10139       error(JSMSG_BAD_OPTIONAL_TEMPLATE);
10140       return null();
10141     } else {
10142       anyChars.ungetToken();
10143       break;
10144     }
10145 
10146     MOZ_ASSERT(nextMember);
10147     lhs = nextMember;
10148   }
10149 
10150   return handler_.newOptionalChain(begin, lhs);
10151 }
10152 
10153 template <class ParseHandler, typename Unit>
unaryExpr(YieldHandling yieldHandling,TripledotHandling tripledotHandling,PossibleError * possibleError,InvokedPrediction invoked,PrivateNameHandling privateNameHandling)10154 typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::unaryExpr(
10155     YieldHandling yieldHandling, TripledotHandling tripledotHandling,
10156     PossibleError* possibleError /* = nullptr */,
10157     InvokedPrediction invoked /* = PredictUninvoked */,
10158     PrivateNameHandling privateNameHandling /* = PrivateNameProhibited */) {
10159   AutoCheckRecursionLimit recursion(cx_);
10160   if (!recursion.check(cx_)) {
10161     return null();
10162   }
10163 
10164   TokenKind tt;
10165   if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) {
10166     return null();
10167   }
10168   uint32_t begin = pos().begin;
10169   switch (tt) {
10170     case TokenKind::Void:
10171       return unaryOpExpr(yieldHandling, ParseNodeKind::VoidExpr, begin);
10172     case TokenKind::Not:
10173       return unaryOpExpr(yieldHandling, ParseNodeKind::NotExpr, begin);
10174     case TokenKind::BitNot:
10175       return unaryOpExpr(yieldHandling, ParseNodeKind::BitNotExpr, begin);
10176     case TokenKind::Add:
10177       return unaryOpExpr(yieldHandling, ParseNodeKind::PosExpr, begin);
10178     case TokenKind::Sub:
10179       return unaryOpExpr(yieldHandling, ParseNodeKind::NegExpr, begin);
10180 
10181     case TokenKind::TypeOf: {
10182       // The |typeof| operator is specially parsed to distinguish its
10183       // application to a name, from its application to a non-name
10184       // expression:
10185       //
10186       //   // Looks up the name, doesn't find it and so evaluates to
10187       //   // "undefined".
10188       //   assertEq(typeof nonExistentName, "undefined");
10189       //
10190       //   // Evaluates expression, triggering a runtime ReferenceError for
10191       //   // the undefined name.
10192       //   typeof (1, nonExistentName);
10193       Node kid = unaryExpr(yieldHandling, TripledotProhibited);
10194       if (!kid) {
10195         return null();
10196       }
10197 
10198       return handler_.newTypeof(begin, kid);
10199     }
10200 
10201     case TokenKind::Inc:
10202     case TokenKind::Dec: {
10203       TokenKind tt2;
10204       if (!tokenStream.getToken(&tt2, TokenStream::SlashIsRegExp)) {
10205         return null();
10206       }
10207 
10208       uint32_t operandOffset = pos().begin;
10209       Node operand = optionalExpr(yieldHandling, TripledotProhibited, tt2);
10210       if (!operand || !checkIncDecOperand(operand, operandOffset)) {
10211         return null();
10212       }
10213       ParseNodeKind pnk = (tt == TokenKind::Inc)
10214                               ? ParseNodeKind::PreIncrementExpr
10215                               : ParseNodeKind::PreDecrementExpr;
10216       return handler_.newUpdate(pnk, begin, operand);
10217     }
10218     case TokenKind::PrivateName: {
10219       if (privateNameHandling == PrivateNameHandling::PrivateNameAllowed) {
10220         TaggedParserAtomIndex field = anyChars.currentName();
10221         return privateNameReference(field);
10222       }
10223       error(JSMSG_INVALID_PRIVATE_NAME_IN_UNARY_EXPR);
10224       return null();
10225     }
10226 
10227     case TokenKind::Delete: {
10228       uint32_t exprOffset;
10229       if (!tokenStream.peekOffset(&exprOffset, TokenStream::SlashIsRegExp)) {
10230         return null();
10231       }
10232 
10233       Node expr = unaryExpr(yieldHandling, TripledotProhibited);
10234       if (!expr) {
10235         return null();
10236       }
10237 
10238       // Per spec, deleting most unary expressions is valid -- it simply
10239       // returns true -- except for two cases:
10240       // 1. `var x; ...; delete x` is a syntax error in strict mode.
10241       // 2. Private fields cannot be deleted.
10242       if (handler_.isName(expr)) {
10243         if (!strictModeErrorAt(exprOffset, JSMSG_DEPRECATED_DELETE_OPERAND)) {
10244           return null();
10245         }
10246 
10247         pc_->sc()->setBindingsAccessedDynamically();
10248       }
10249 
10250       if (handler_.isPrivateMemberAccess(expr)) {
10251         errorAt(exprOffset, JSMSG_PRIVATE_DELETE);
10252         return null();
10253       }
10254 
10255       return handler_.newDelete(begin, expr);
10256     }
10257     case TokenKind::Await: {
10258       // If we encounter an await in a module, mark it as async.
10259       if (!pc_->isAsync() && pc_->sc()->isModule()) {
10260         pc_->sc()->asModuleContext()->setIsAsync();
10261         MOZ_ASSERT(pc_->isAsync());
10262       }
10263 
10264       if (pc_->isAsync()) {
10265         if (inParametersOfAsyncFunction()) {
10266           error(JSMSG_AWAIT_IN_PARAMETER);
10267           return null();
10268         }
10269         Node kid =
10270             unaryExpr(yieldHandling, tripledotHandling, possibleError, invoked);
10271         if (!kid) {
10272           return null();
10273         }
10274         pc_->lastAwaitOffset = begin;
10275         return handler_.newAwaitExpression(begin, kid);
10276       }
10277     }
10278 
10279       [[fallthrough]];
10280 
10281     default: {
10282       Node expr = optionalExpr(yieldHandling, tripledotHandling, tt,
10283                                possibleError, invoked);
10284       if (!expr) {
10285         return null();
10286       }
10287 
10288       /* Don't look across a newline boundary for a postfix incop. */
10289       if (!tokenStream.peekTokenSameLine(&tt)) {
10290         return null();
10291       }
10292 
10293       if (tt != TokenKind::Inc && tt != TokenKind::Dec) {
10294         return expr;
10295       }
10296 
10297       tokenStream.consumeKnownToken(tt);
10298       if (!checkIncDecOperand(expr, begin)) {
10299         return null();
10300       }
10301 
10302       ParseNodeKind pnk = (tt == TokenKind::Inc)
10303                               ? ParseNodeKind::PostIncrementExpr
10304                               : ParseNodeKind::PostDecrementExpr;
10305       return handler_.newUpdate(pnk, begin, expr);
10306     }
10307   }
10308 }
10309 
10310 template <class ParseHandler, typename Unit>
10311 typename ParseHandler::Node
assignExprWithoutYieldOrAwait(YieldHandling yieldHandling)10312 GeneralParser<ParseHandler, Unit>::assignExprWithoutYieldOrAwait(
10313     YieldHandling yieldHandling) {
10314   uint32_t startYieldOffset = pc_->lastYieldOffset;
10315   uint32_t startAwaitOffset = pc_->lastAwaitOffset;
10316   Node res = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
10317   if (res) {
10318     if (pc_->lastYieldOffset != startYieldOffset) {
10319       errorAt(pc_->lastYieldOffset, JSMSG_YIELD_IN_PARAMETER);
10320       return null();
10321     }
10322     if (pc_->lastAwaitOffset != startAwaitOffset) {
10323       errorAt(pc_->lastAwaitOffset, JSMSG_AWAIT_IN_PARAMETER);
10324       return null();
10325     }
10326   }
10327   return res;
10328 }
10329 
10330 template <class ParseHandler, typename Unit>
10331 typename ParseHandler::ListNodeType
argumentList(YieldHandling yieldHandling,bool * isSpread,PossibleError * possibleError)10332 GeneralParser<ParseHandler, Unit>::argumentList(
10333     YieldHandling yieldHandling, bool* isSpread,
10334     PossibleError* possibleError /* = nullptr */) {
10335   ListNodeType argsList = handler_.newArguments(pos());
10336   if (!argsList) {
10337     return null();
10338   }
10339 
10340   bool matched;
10341   if (!tokenStream.matchToken(&matched, TokenKind::RightParen,
10342                               TokenStream::SlashIsRegExp)) {
10343     return null();
10344   }
10345   if (matched) {
10346     handler_.setEndPosition(argsList, pos().end);
10347     return argsList;
10348   }
10349 
10350   while (true) {
10351     bool spread = false;
10352     uint32_t begin = 0;
10353     if (!tokenStream.matchToken(&matched, TokenKind::TripleDot,
10354                                 TokenStream::SlashIsRegExp)) {
10355       return null();
10356     }
10357     if (matched) {
10358       spread = true;
10359       begin = pos().begin;
10360       *isSpread = true;
10361     }
10362 
10363     Node argNode = assignExpr(InAllowed, yieldHandling, TripledotProhibited,
10364                               possibleError);
10365     if (!argNode) {
10366       return null();
10367     }
10368     if (spread) {
10369       argNode = handler_.newSpread(begin, argNode);
10370       if (!argNode) {
10371         return null();
10372       }
10373     }
10374 
10375     handler_.addList(argsList, argNode);
10376 
10377     bool matched;
10378     if (!tokenStream.matchToken(&matched, TokenKind::Comma,
10379                                 TokenStream::SlashIsRegExp)) {
10380       return null();
10381     }
10382     if (!matched) {
10383       break;
10384     }
10385 
10386     TokenKind tt;
10387     if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) {
10388       return null();
10389     }
10390     if (tt == TokenKind::RightParen) {
10391       break;
10392     }
10393   }
10394 
10395   if (!mustMatchToken(TokenKind::RightParen, JSMSG_PAREN_AFTER_ARGS)) {
10396     return null();
10397   }
10398 
10399   handler_.setEndPosition(argsList, pos().end);
10400   return argsList;
10401 }
10402 
checkAndMarkSuperScope()10403 bool ParserBase::checkAndMarkSuperScope() {
10404   if (!pc_->sc()->allowSuperProperty()) {
10405     return false;
10406   }
10407 
10408   pc_->setSuperScopeNeedsHomeObject();
10409   return true;
10410 }
10411 
10412 template <class ParseHandler, typename Unit>
computeErrorMetadata(ErrorMetadata * err,const ErrorReportMixin::ErrorOffset & offset)10413 bool GeneralParser<ParseHandler, Unit>::computeErrorMetadata(
10414     ErrorMetadata* err, const ErrorReportMixin::ErrorOffset& offset) {
10415   if (offset.is<ErrorReportMixin::Current>()) {
10416     return tokenStream.computeErrorMetadata(err, AsVariant(pos().begin));
10417   }
10418   return tokenStream.computeErrorMetadata(err, offset);
10419 }
10420 
10421 template <class ParseHandler, typename Unit>
memberExpr(YieldHandling yieldHandling,TripledotHandling tripledotHandling,TokenKind tt,bool allowCallSyntax,PossibleError * possibleError,InvokedPrediction invoked)10422 typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::memberExpr(
10423     YieldHandling yieldHandling, TripledotHandling tripledotHandling,
10424     TokenKind tt, bool allowCallSyntax, PossibleError* possibleError,
10425     InvokedPrediction invoked) {
10426   MOZ_ASSERT(anyChars.isCurrentTokenType(tt));
10427 
10428   Node lhs;
10429 
10430   AutoCheckRecursionLimit recursion(cx_);
10431   if (!recursion.check(cx_)) {
10432     return null();
10433   }
10434 
10435   /* Check for new expression first. */
10436   if (tt == TokenKind::New) {
10437     uint32_t newBegin = pos().begin;
10438     // Make sure this wasn't a |new.target| in disguise.
10439     BinaryNodeType newTarget;
10440     if (!tryNewTarget(&newTarget)) {
10441       return null();
10442     }
10443     if (newTarget) {
10444       lhs = newTarget;
10445     } else {
10446       // Gotten by tryNewTarget
10447       tt = anyChars.currentToken().type;
10448       Node ctorExpr = memberExpr(yieldHandling, TripledotProhibited, tt,
10449                                  /* allowCallSyntax = */ false,
10450                                  /* possibleError = */ nullptr, PredictInvoked);
10451       if (!ctorExpr) {
10452         return null();
10453       }
10454 
10455       // If we have encountered an optional chain, in the form of `new
10456       // ClassName?.()` then we need to throw, as this is disallowed by the
10457       // spec.
10458       bool optionalToken;
10459       if (!tokenStream.matchToken(&optionalToken, TokenKind::OptionalChain)) {
10460         return null();
10461       }
10462       if (optionalToken) {
10463         errorAt(newBegin, JSMSG_BAD_NEW_OPTIONAL);
10464         return null();
10465       }
10466 
10467       bool matched;
10468       if (!tokenStream.matchToken(&matched, TokenKind::LeftParen)) {
10469         return null();
10470       }
10471 
10472       bool isSpread = false;
10473       Node args;
10474       if (matched) {
10475         args = argumentList(yieldHandling, &isSpread);
10476       } else {
10477         args = handler_.newArguments(pos());
10478       }
10479 
10480       if (!args) {
10481         return null();
10482       }
10483 
10484       lhs = handler_.newNewExpression(newBegin, ctorExpr, args, isSpread);
10485       if (!lhs) {
10486         return null();
10487       }
10488     }
10489   } else if (tt == TokenKind::Super) {
10490     NameNodeType thisName = newThisName();
10491     if (!thisName) {
10492       return null();
10493     }
10494     lhs = handler_.newSuperBase(thisName, pos());
10495     if (!lhs) {
10496       return null();
10497     }
10498   } else if (tt == TokenKind::Import) {
10499     lhs = importExpr(yieldHandling, allowCallSyntax);
10500     if (!lhs) {
10501       return null();
10502     }
10503   } else {
10504     lhs = primaryExpr(yieldHandling, tripledotHandling, tt, possibleError,
10505                       invoked);
10506     if (!lhs) {
10507       return null();
10508     }
10509   }
10510 
10511   MOZ_ASSERT_IF(handler_.isSuperBase(lhs),
10512                 anyChars.isCurrentTokenType(TokenKind::Super));
10513 
10514   while (true) {
10515     if (!tokenStream.getToken(&tt)) {
10516       return null();
10517     }
10518     if (tt == TokenKind::Eof) {
10519       anyChars.ungetToken();
10520       break;
10521     }
10522 
10523     Node nextMember;
10524     if (tt == TokenKind::Dot) {
10525       if (!tokenStream.getToken(&tt)) {
10526         return null();
10527       }
10528 
10529       if (TokenKindIsPossibleIdentifierName(tt)) {
10530         nextMember = memberPropertyAccess(lhs);
10531         if (!nextMember) {
10532           return null();
10533         }
10534       } else if (tt == TokenKind::PrivateName) {
10535         nextMember = memberPrivateAccess(lhs);
10536         if (!nextMember) {
10537           return null();
10538         }
10539       } else {
10540         error(JSMSG_NAME_AFTER_DOT);
10541         return null();
10542       }
10543     } else if (tt == TokenKind::LeftBracket) {
10544       nextMember = memberElemAccess(lhs, yieldHandling);
10545       if (!nextMember) {
10546         return null();
10547       }
10548     } else if ((allowCallSyntax && tt == TokenKind::LeftParen) ||
10549                tt == TokenKind::TemplateHead ||
10550                tt == TokenKind::NoSubsTemplate) {
10551       if (handler_.isSuperBase(lhs)) {
10552         if (!pc_->sc()->allowSuperCall()) {
10553           error(JSMSG_BAD_SUPERCALL);
10554           return null();
10555         }
10556 
10557         if (tt != TokenKind::LeftParen) {
10558           error(JSMSG_BAD_SUPER);
10559           return null();
10560         }
10561 
10562         nextMember = memberSuperCall(lhs, yieldHandling);
10563         if (!nextMember) {
10564           return null();
10565         }
10566 
10567         if (!noteUsedName(
10568                 TaggedParserAtomIndex::WellKnown::dotInitializers())) {
10569           return null();
10570         }
10571       } else {
10572         nextMember = memberCall(tt, lhs, yieldHandling, possibleError);
10573         if (!nextMember) {
10574           return null();
10575         }
10576       }
10577     } else {
10578       anyChars.ungetToken();
10579       if (handler_.isSuperBase(lhs)) {
10580         break;
10581       }
10582       return lhs;
10583     }
10584 
10585     lhs = nextMember;
10586   }
10587 
10588   if (handler_.isSuperBase(lhs)) {
10589     error(JSMSG_BAD_SUPER);
10590     return null();
10591   }
10592 
10593   return lhs;
10594 }
10595 
10596 template <class ParseHandler>
10597 inline typename ParseHandler::NameNodeType
newName(TaggedParserAtomIndex name)10598 PerHandlerParser<ParseHandler>::newName(TaggedParserAtomIndex name) {
10599   return newName(name, pos());
10600 }
10601 
10602 template <class ParseHandler>
10603 inline typename ParseHandler::NameNodeType
newName(TaggedParserAtomIndex name,TokenPos pos)10604 PerHandlerParser<ParseHandler>::newName(TaggedParserAtomIndex name,
10605                                         TokenPos pos) {
10606   return handler_.newName(name, pos);
10607 }
10608 
10609 template <class ParseHandler>
10610 inline typename ParseHandler::NameNodeType
newPrivateName(TaggedParserAtomIndex name)10611 PerHandlerParser<ParseHandler>::newPrivateName(TaggedParserAtomIndex name) {
10612   return handler_.newPrivateName(name, pos());
10613 }
10614 
10615 template <class ParseHandler, typename Unit>
10616 typename ParseHandler::Node
memberPropertyAccess(Node lhs,OptionalKind optionalKind)10617 GeneralParser<ParseHandler, Unit>::memberPropertyAccess(
10618     Node lhs, OptionalKind optionalKind /* = OptionalKind::NonOptional */) {
10619   MOZ_ASSERT(TokenKindIsPossibleIdentifierName(anyChars.currentToken().type) ||
10620              anyChars.currentToken().type == TokenKind::PrivateName);
10621   TaggedParserAtomIndex field = anyChars.currentName();
10622   if (handler_.isSuperBase(lhs) && !checkAndMarkSuperScope()) {
10623     error(JSMSG_BAD_SUPERPROP, "property");
10624     return null();
10625   }
10626 
10627   NameNodeType name = handler_.newPropertyName(field, pos());
10628   if (!name) {
10629     return null();
10630   }
10631 
10632   if (optionalKind == OptionalKind::Optional) {
10633     MOZ_ASSERT(!handler_.isSuperBase(lhs));
10634     return handler_.newOptionalPropertyAccess(lhs, name);
10635   }
10636   return handler_.newPropertyAccess(lhs, name);
10637 }
10638 
10639 template <class ParseHandler, typename Unit>
10640 typename ParseHandler::Node
memberPrivateAccess(Node lhs,OptionalKind optionalKind)10641 GeneralParser<ParseHandler, Unit>::memberPrivateAccess(
10642     Node lhs, OptionalKind optionalKind /* = OptionalKind::NonOptional */) {
10643   MOZ_ASSERT(anyChars.currentToken().type == TokenKind::PrivateName);
10644 
10645   TaggedParserAtomIndex field = anyChars.currentName();
10646   // Cannot access private fields on super.
10647   if (handler_.isSuperBase(lhs)) {
10648     error(JSMSG_BAD_SUPERPRIVATE);
10649     return null();
10650   }
10651 
10652   NameNodeType privateName = privateNameReference(field);
10653   if (!privateName) {
10654     return null();
10655   }
10656 
10657   if (optionalKind == OptionalKind::Optional) {
10658     MOZ_ASSERT(!handler_.isSuperBase(lhs));
10659     return handler_.newOptionalPrivateMemberAccess(lhs, privateName, pos().end);
10660   }
10661   return handler_.newPrivateMemberAccess(lhs, privateName, pos().end);
10662 }
10663 
10664 template <class ParseHandler, typename Unit>
memberElemAccess(Node lhs,YieldHandling yieldHandling,OptionalKind optionalKind)10665 typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::memberElemAccess(
10666     Node lhs, YieldHandling yieldHandling,
10667     OptionalKind optionalKind /* = OptionalKind::NonOptional */) {
10668   MOZ_ASSERT(anyChars.currentToken().type == TokenKind::LeftBracket);
10669   Node propExpr = expr(InAllowed, yieldHandling, TripledotProhibited);
10670   if (!propExpr) {
10671     return null();
10672   }
10673 
10674   if (!mustMatchToken(TokenKind::RightBracket, JSMSG_BRACKET_IN_INDEX)) {
10675     return null();
10676   }
10677 
10678   if (handler_.isSuperBase(lhs) && !checkAndMarkSuperScope()) {
10679     error(JSMSG_BAD_SUPERPROP, "member");
10680     return null();
10681   }
10682   if (optionalKind == OptionalKind::Optional) {
10683     MOZ_ASSERT(!handler_.isSuperBase(lhs));
10684     return handler_.newOptionalPropertyByValue(lhs, propExpr, pos().end);
10685   }
10686   return handler_.newPropertyByValue(lhs, propExpr, pos().end);
10687 }
10688 
10689 template <class ParseHandler, typename Unit>
memberSuperCall(Node lhs,YieldHandling yieldHandling)10690 typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::memberSuperCall(
10691     Node lhs, YieldHandling yieldHandling) {
10692   MOZ_ASSERT(anyChars.currentToken().type == TokenKind::LeftParen);
10693   // Despite the fact that it's impossible to have |super()| in a
10694   // generator, we still inherit the yieldHandling of the
10695   // memberExpression, per spec. Curious.
10696   bool isSpread = false;
10697   Node args = argumentList(yieldHandling, &isSpread);
10698   if (!args) {
10699     return null();
10700   }
10701 
10702   CallNodeType superCall = handler_.newSuperCall(lhs, args, isSpread);
10703   if (!superCall) {
10704     return null();
10705   }
10706 
10707   NameNodeType thisName = newThisName();
10708   if (!thisName) {
10709     return null();
10710   }
10711 
10712   return handler_.newSetThis(thisName, superCall);
10713 }
10714 
10715 template <class ParseHandler, typename Unit>
memberCall(TokenKind tt,Node lhs,YieldHandling yieldHandling,PossibleError * possibleError,OptionalKind optionalKind)10716 typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::memberCall(
10717     TokenKind tt, Node lhs, YieldHandling yieldHandling,
10718     PossibleError* possibleError /* = nullptr */,
10719     OptionalKind optionalKind /* = OptionalKind::NonOptional */) {
10720   if (options().selfHostingMode &&
10721       (handler_.isPropertyOrPrivateMemberAccess(lhs) ||
10722        handler_.isOptionalPropertyOrPrivateMemberAccess(lhs))) {
10723     error(JSMSG_SELFHOSTED_METHOD_CALL);
10724     return null();
10725   }
10726 
10727   MOZ_ASSERT(tt == TokenKind::LeftParen || tt == TokenKind::TemplateHead ||
10728                  tt == TokenKind::NoSubsTemplate,
10729              "Unexpected token kind for member call");
10730 
10731   JSOp op = JSOp::Call;
10732   bool maybeAsyncArrow = false;
10733   if (auto prop = handler_.maybeDottedProperty(lhs)) {
10734     // Use the JSOp::Fun{Apply,Call} optimizations given the right
10735     // syntax.
10736     if (prop == TaggedParserAtomIndex::WellKnown::apply()) {
10737       op = JSOp::FunApply;
10738     } else if (prop == TaggedParserAtomIndex::WellKnown::call()) {
10739       op = JSOp::FunCall;
10740     }
10741   } else if (tt == TokenKind::LeftParen &&
10742              optionalKind == OptionalKind::NonOptional) {
10743     if (handler_.isAsyncKeyword(lhs)) {
10744       // |async (| can be the start of an async arrow
10745       // function, so we need to defer reporting possible
10746       // errors from destructuring syntax. To give better
10747       // error messages, we only allow the AsyncArrowHead
10748       // part of the CoverCallExpressionAndAsyncArrowHead
10749       // syntax when the initial name is "async".
10750       maybeAsyncArrow = true;
10751     } else if (handler_.isEvalName(lhs)) {
10752       // Select the right Eval op and flag pc_ as having a
10753       // direct eval.
10754       op = pc_->sc()->strict() ? JSOp::StrictEval : JSOp::Eval;
10755       pc_->sc()->setBindingsAccessedDynamically();
10756       pc_->sc()->setHasDirectEval();
10757 
10758       // In non-strict mode code, direct calls to eval can
10759       // add variables to the call object.
10760       if (pc_->isFunctionBox() && !pc_->sc()->strict()) {
10761         pc_->functionBox()->setFunHasExtensibleScope();
10762       }
10763 
10764       // If we're in a method, mark the method as requiring
10765       // support for 'super', since direct eval code can use
10766       // it. (If we're not in a method, that's fine, so
10767       // ignore the return value.)
10768       checkAndMarkSuperScope();
10769     }
10770   }
10771 
10772   if (tt == TokenKind::LeftParen) {
10773     bool isSpread = false;
10774     PossibleError* asyncPossibleError =
10775         maybeAsyncArrow ? possibleError : nullptr;
10776     Node args = argumentList(yieldHandling, &isSpread, asyncPossibleError);
10777     if (!args) {
10778       return null();
10779     }
10780     if (isSpread) {
10781       if (op == JSOp::Eval) {
10782         op = JSOp::SpreadEval;
10783       } else if (op == JSOp::StrictEval) {
10784         op = JSOp::StrictSpreadEval;
10785       } else {
10786         op = JSOp::SpreadCall;
10787       }
10788     }
10789 
10790     if (optionalKind == OptionalKind::Optional) {
10791       return handler_.newOptionalCall(lhs, args, op);
10792     }
10793     return handler_.newCall(lhs, args, op);
10794   }
10795 
10796   ListNodeType args = handler_.newArguments(pos());
10797   if (!args) {
10798     return null();
10799   }
10800 
10801   if (!taggedTemplate(yieldHandling, args, tt)) {
10802     return null();
10803   }
10804 
10805   if (optionalKind == OptionalKind::Optional) {
10806     error(JSMSG_BAD_OPTIONAL_TEMPLATE);
10807     return null();
10808   }
10809 
10810   return handler_.newTaggedTemplate(lhs, args, op);
10811 }
10812 
10813 template <class ParseHandler, typename Unit>
checkLabelOrIdentifierReference(TaggedParserAtomIndex ident,uint32_t offset,YieldHandling yieldHandling,TokenKind hint)10814 bool GeneralParser<ParseHandler, Unit>::checkLabelOrIdentifierReference(
10815     TaggedParserAtomIndex ident, uint32_t offset, YieldHandling yieldHandling,
10816     TokenKind hint /* = TokenKind::Limit */) {
10817   TokenKind tt;
10818   if (hint == TokenKind::Limit) {
10819     tt = ReservedWordTokenKind(ident);
10820   } else {
10821     // All non-reserved word kinds are folded into TokenKind::Limit in
10822     // ReservedWordTokenKind and the following code.
10823     if (hint == TokenKind::Name || hint == TokenKind::PrivateName) {
10824       hint = TokenKind::Limit;
10825     }
10826     MOZ_ASSERT(hint == ReservedWordTokenKind(ident),
10827                "hint doesn't match actual token kind");
10828     tt = hint;
10829   }
10830 
10831   if (!pc_->sc()->allowArguments() &&
10832       ident == TaggedParserAtomIndex::WellKnown::arguments()) {
10833     error(JSMSG_BAD_ARGUMENTS);
10834     return false;
10835   }
10836 
10837   if (tt == TokenKind::Limit) {
10838     // Either TokenKind::Name or TokenKind::PrivateName
10839     return true;
10840   }
10841   if (TokenKindIsContextualKeyword(tt)) {
10842     if (tt == TokenKind::Yield) {
10843       if (yieldHandling == YieldIsKeyword) {
10844         errorAt(offset, JSMSG_RESERVED_ID, "yield");
10845         return false;
10846       }
10847       if (pc_->sc()->strict()) {
10848         if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "yield")) {
10849           return false;
10850         }
10851       }
10852       return true;
10853     }
10854     if (tt == TokenKind::Await) {
10855       if (awaitIsKeyword() || awaitIsDisallowed()) {
10856         errorAt(offset, JSMSG_RESERVED_ID, "await");
10857         return false;
10858       }
10859       return true;
10860     }
10861     if (pc_->sc()->strict()) {
10862       if (tt == TokenKind::Let) {
10863         if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "let")) {
10864           return false;
10865         }
10866         return true;
10867       }
10868       if (tt == TokenKind::Static) {
10869         if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "static")) {
10870           return false;
10871         }
10872         return true;
10873       }
10874     }
10875     return true;
10876   }
10877   if (TokenKindIsStrictReservedWord(tt)) {
10878     if (pc_->sc()->strict()) {
10879       if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID,
10880                              ReservedWordToCharZ(tt))) {
10881         return false;
10882       }
10883     }
10884     return true;
10885   }
10886   if (TokenKindIsKeyword(tt) || TokenKindIsReservedWordLiteral(tt)) {
10887     errorAt(offset, JSMSG_INVALID_ID, ReservedWordToCharZ(tt));
10888     return false;
10889   }
10890   if (TokenKindIsFutureReservedWord(tt)) {
10891     errorAt(offset, JSMSG_RESERVED_ID, ReservedWordToCharZ(tt));
10892     return false;
10893   }
10894   MOZ_ASSERT_UNREACHABLE("Unexpected reserved word kind.");
10895   return false;
10896 }
10897 
10898 template <class ParseHandler, typename Unit>
checkBindingIdentifier(TaggedParserAtomIndex ident,uint32_t offset,YieldHandling yieldHandling,TokenKind hint)10899 bool GeneralParser<ParseHandler, Unit>::checkBindingIdentifier(
10900     TaggedParserAtomIndex ident, uint32_t offset, YieldHandling yieldHandling,
10901     TokenKind hint /* = TokenKind::Limit */) {
10902   if (pc_->sc()->strict()) {
10903     if (ident == TaggedParserAtomIndex::WellKnown::arguments()) {
10904       if (!strictModeErrorAt(offset, JSMSG_BAD_STRICT_ASSIGN, "arguments")) {
10905         return false;
10906       }
10907       return true;
10908     }
10909 
10910     if (ident == TaggedParserAtomIndex::WellKnown::eval()) {
10911       if (!strictModeErrorAt(offset, JSMSG_BAD_STRICT_ASSIGN, "eval")) {
10912         return false;
10913       }
10914       return true;
10915     }
10916   }
10917 
10918   return checkLabelOrIdentifierReference(ident, offset, yieldHandling, hint);
10919 }
10920 
10921 template <class ParseHandler, typename Unit>
10922 TaggedParserAtomIndex
labelOrIdentifierReference(YieldHandling yieldHandling)10923 GeneralParser<ParseHandler, Unit>::labelOrIdentifierReference(
10924     YieldHandling yieldHandling) {
10925   // ES 2017 draft 12.1.1.
10926   //   StringValue of IdentifierName normalizes any Unicode escape sequences
10927   //   in IdentifierName hence such escapes cannot be used to write an
10928   //   Identifier whose code point sequence is the same as a ReservedWord.
10929   //
10930   // Use const ParserName* instead of TokenKind to reflect the normalization.
10931 
10932   // Unless the name contains escapes, we can reuse the current TokenKind
10933   // to determine if the name is a restricted identifier.
10934   TokenKind hint = !anyChars.currentNameHasEscapes(this->parserAtoms())
10935                        ? anyChars.currentToken().type
10936                        : TokenKind::Limit;
10937   TaggedParserAtomIndex ident = anyChars.currentName();
10938   if (!checkLabelOrIdentifierReference(ident, pos().begin, yieldHandling,
10939                                        hint)) {
10940     return TaggedParserAtomIndex::null();
10941   }
10942   return ident;
10943 }
10944 
10945 template <class ParseHandler, typename Unit>
bindingIdentifier(YieldHandling yieldHandling)10946 TaggedParserAtomIndex GeneralParser<ParseHandler, Unit>::bindingIdentifier(
10947     YieldHandling yieldHandling) {
10948   TokenKind hint = !anyChars.currentNameHasEscapes(this->parserAtoms())
10949                        ? anyChars.currentToken().type
10950                        : TokenKind::Limit;
10951   TaggedParserAtomIndex ident = anyChars.currentName();
10952   if (!checkBindingIdentifier(ident, pos().begin, yieldHandling, hint)) {
10953     return TaggedParserAtomIndex::null();
10954   }
10955   return ident;
10956 }
10957 
10958 template <class ParseHandler>
10959 typename ParseHandler::NameNodeType
identifierReference(TaggedParserAtomIndex name)10960 PerHandlerParser<ParseHandler>::identifierReference(
10961     TaggedParserAtomIndex name) {
10962   NameNodeType id = newName(name);
10963   if (!id) {
10964     return null();
10965   }
10966 
10967   if (!noteUsedName(name)) {
10968     return null();
10969   }
10970 
10971   return id;
10972 }
10973 
10974 template <class ParseHandler>
10975 typename ParseHandler::NameNodeType
privateNameReference(TaggedParserAtomIndex name)10976 PerHandlerParser<ParseHandler>::privateNameReference(
10977     TaggedParserAtomIndex name) {
10978   NameNodeType id = newPrivateName(name);
10979   if (!id) {
10980     return null();
10981   }
10982 
10983   if (!noteUsedName(name, NameVisibility::Private, Some(pos()))) {
10984     return null();
10985   }
10986 
10987   return id;
10988 }
10989 
10990 template <class ParseHandler>
10991 typename ParseHandler::NameNodeType
stringLiteral()10992 PerHandlerParser<ParseHandler>::stringLiteral() {
10993   return handler_.newStringLiteral(anyChars.currentToken().atom(), pos());
10994 }
10995 
10996 template <class ParseHandler>
10997 typename ParseHandler::Node
noSubstitutionTaggedTemplate()10998 PerHandlerParser<ParseHandler>::noSubstitutionTaggedTemplate() {
10999   if (anyChars.hasInvalidTemplateEscape()) {
11000     anyChars.clearInvalidTemplateEscape();
11001     return handler_.newRawUndefinedLiteral(pos());
11002   }
11003 
11004   return handler_.newTemplateStringLiteral(anyChars.currentToken().atom(),
11005                                            pos());
11006 }
11007 
11008 template <class ParseHandler, typename Unit>
11009 typename ParseHandler::NameNodeType
noSubstitutionUntaggedTemplate()11010 GeneralParser<ParseHandler, Unit>::noSubstitutionUntaggedTemplate() {
11011   if (!tokenStream.checkForInvalidTemplateEscapeError()) {
11012     return null();
11013   }
11014 
11015   return handler_.newTemplateStringLiteral(anyChars.currentToken().atom(),
11016                                            pos());
11017 }
11018 
11019 template <typename Unit>
newRegExp()11020 RegExpLiteral* Parser<FullParseHandler, Unit>::newRegExp() {
11021   MOZ_ASSERT(!options().selfHostingMode);
11022 
11023   // Create the regexp and check its syntax.
11024   const auto& chars = tokenStream.getCharBuffer();
11025   mozilla::Range<const char16_t> range(chars.begin(), chars.length());
11026   RegExpFlags flags = anyChars.currentToken().regExpFlags();
11027 
11028   uint32_t offset = anyChars.currentToken().pos.begin;
11029   uint32_t line, column;
11030   tokenStream.computeLineAndColumn(offset, &line, &column);
11031 
11032   if (!handler_.reuseRegexpSyntaxParse()) {
11033     // Verify that the Regexp will syntax parse when the time comes to
11034     // instantiate it. If we have already done a syntax parse, we can
11035     // skip this.
11036     LifoAllocScope parserAllocScope(&cx_->tempLifoAlloc());
11037     if (!irregexp::CheckPatternSyntax(cx_, anyChars, range, flags, Some(line),
11038                                       Some(column))) {
11039       return nullptr;
11040     }
11041   }
11042 
11043   auto atom =
11044       this->parserAtoms().internChar16(cx_, chars.begin(), chars.length());
11045   if (!atom) {
11046     return nullptr;
11047   }
11048   // RegExp patterm must be atomized.
11049   this->parserAtoms().markUsedByStencil(atom, ParserAtom::Atomize::Yes);
11050 
11051   RegExpIndex index(this->compilationState_.regExpData.length());
11052   if (uint32_t(index) >= TaggedScriptThingIndex::IndexLimit) {
11053     ReportAllocationOverflow(cx_);
11054     return nullptr;
11055   }
11056   if (!this->compilationState_.regExpData.emplaceBack(atom, flags)) {
11057     js::ReportOutOfMemory(cx_);
11058     return nullptr;
11059   }
11060 
11061   return handler_.newRegExp(index, pos());
11062 }
11063 
11064 template <typename Unit>
11065 SyntaxParseHandler::RegExpLiteralType
newRegExp()11066 Parser<SyntaxParseHandler, Unit>::newRegExp() {
11067   MOZ_ASSERT(!options().selfHostingMode);
11068 
11069   // Only check the regexp's syntax, but don't create a regexp object.
11070   const auto& chars = tokenStream.getCharBuffer();
11071   RegExpFlags flags = anyChars.currentToken().regExpFlags();
11072 
11073   uint32_t offset = anyChars.currentToken().pos.begin;
11074   uint32_t line, column;
11075   tokenStream.computeLineAndColumn(offset, &line, &column);
11076 
11077   mozilla::Range<const char16_t> source(chars.begin(), chars.length());
11078   {
11079     LifoAllocScope regExpAllocScope(&alloc_);
11080     if (!irregexp::CheckPatternSyntax(cx_, anyChars, source, flags, Some(line),
11081                                       Some(column))) {
11082       return null();
11083     }
11084   }
11085 
11086   return handler_.newRegExp(SyntaxParseHandler::NodeGeneric, pos());
11087 }
11088 
11089 template <class ParseHandler, typename Unit>
11090 typename ParseHandler::RegExpLiteralType
newRegExp()11091 GeneralParser<ParseHandler, Unit>::newRegExp() {
11092   return asFinalParser()->newRegExp();
11093 }
11094 
11095 template <typename Unit>
newBigInt()11096 BigIntLiteral* Parser<FullParseHandler, Unit>::newBigInt() {
11097   // The token's charBuffer contains the DecimalIntegerLiteral or
11098   // NonDecimalIntegerLiteral production, and as such does not include the
11099   // BigIntLiteralSuffix (the trailing "n").  Note that NonDecimalIntegerLiteral
11100   // productions start with 0[bBoOxX], indicating binary/octal/hex.
11101   const auto& chars = tokenStream.getCharBuffer();
11102   if (chars.length() > UINT32_MAX) {
11103     ReportAllocationOverflow(cx_);
11104     return null();
11105   }
11106 
11107   BigIntIndex index(this->compilationState_.bigIntData.length());
11108   if (uint32_t(index) >= TaggedScriptThingIndex::IndexLimit) {
11109     ReportAllocationOverflow(cx_);
11110     return null();
11111   }
11112   if (!this->compilationState_.bigIntData.emplaceBack()) {
11113     js::ReportOutOfMemory(cx_);
11114     return null();
11115   }
11116 
11117   if (!this->compilationState_.bigIntData[index].init(
11118           this->cx_, this->stencilAlloc(), chars)) {
11119     return null();
11120   }
11121 
11122   bool isZero = this->compilationState_.bigIntData[index].isZero();
11123 
11124   // Should the operations below fail, the buffer held by data will
11125   // be cleaned up by the CompilationState destructor.
11126   return handler_.newBigInt(index, isZero, pos());
11127 }
11128 
11129 template <typename Unit>
11130 SyntaxParseHandler::BigIntLiteralType
newBigInt()11131 Parser<SyntaxParseHandler, Unit>::newBigInt() {
11132   // The tokenizer has already checked the syntax of the bigint.
11133 
11134   return handler_.newBigInt();
11135 }
11136 
11137 template <class ParseHandler, typename Unit>
11138 typename ParseHandler::BigIntLiteralType
newBigInt()11139 GeneralParser<ParseHandler, Unit>::newBigInt() {
11140   return asFinalParser()->newBigInt();
11141 }
11142 
11143 // |exprPossibleError| is the PossibleError state within |expr|,
11144 // |possibleError| is the surrounding PossibleError state.
11145 template <class ParseHandler, typename Unit>
checkDestructuringAssignmentTarget(Node expr,TokenPos exprPos,PossibleError * exprPossibleError,PossibleError * possibleError,TargetBehavior behavior)11146 bool GeneralParser<ParseHandler, Unit>::checkDestructuringAssignmentTarget(
11147     Node expr, TokenPos exprPos, PossibleError* exprPossibleError,
11148     PossibleError* possibleError, TargetBehavior behavior) {
11149   // Report any pending expression error if we're definitely not in a
11150   // destructuring context or the possible destructuring target is a
11151   // property accessor.
11152   if (!possibleError || handler_.isPropertyOrPrivateMemberAccess(expr)) {
11153     return exprPossibleError->checkForExpressionError();
11154   }
11155 
11156   // |expr| may end up as a destructuring assignment target, so we need to
11157   // validate it's either a name or can be parsed as a nested destructuring
11158   // pattern. Property accessors are also valid assignment targets, but
11159   // those are already handled above.
11160 
11161   exprPossibleError->transferErrorsTo(possibleError);
11162 
11163   // Return early if a pending destructuring error is already present.
11164   if (possibleError->hasPendingDestructuringError()) {
11165     return true;
11166   }
11167 
11168   if (handler_.isName(expr)) {
11169     checkDestructuringAssignmentName(handler_.asName(expr), exprPos,
11170                                      possibleError);
11171     return true;
11172   }
11173 
11174   if (handler_.isUnparenthesizedDestructuringPattern(expr)) {
11175     if (behavior == TargetBehavior::ForbidAssignmentPattern) {
11176       possibleError->setPendingDestructuringErrorAt(exprPos,
11177                                                     JSMSG_BAD_DESTRUCT_TARGET);
11178     }
11179     return true;
11180   }
11181 
11182   // Parentheses are forbidden around destructuring *patterns* (but allowed
11183   // around names). Use our nicer error message for parenthesized, nested
11184   // patterns if nested destructuring patterns are allowed.
11185   if (handler_.isParenthesizedDestructuringPattern(expr) &&
11186       behavior != TargetBehavior::ForbidAssignmentPattern) {
11187     possibleError->setPendingDestructuringErrorAt(exprPos,
11188                                                   JSMSG_BAD_DESTRUCT_PARENS);
11189   } else {
11190     possibleError->setPendingDestructuringErrorAt(exprPos,
11191                                                   JSMSG_BAD_DESTRUCT_TARGET);
11192   }
11193 
11194   return true;
11195 }
11196 
11197 template <class ParseHandler, typename Unit>
checkDestructuringAssignmentName(NameNodeType name,TokenPos namePos,PossibleError * possibleError)11198 void GeneralParser<ParseHandler, Unit>::checkDestructuringAssignmentName(
11199     NameNodeType name, TokenPos namePos, PossibleError* possibleError) {
11200 #ifdef DEBUG
11201   // GCC 8.0.1 crashes if this is a one-liner.
11202   bool isName = handler_.isName(name);
11203   MOZ_ASSERT(isName);
11204 #endif
11205 
11206   // Return early if a pending destructuring error is already present.
11207   if (possibleError->hasPendingDestructuringError()) {
11208     return;
11209   }
11210 
11211   if (pc_->sc()->strict()) {
11212     if (handler_.isArgumentsName(name)) {
11213       if (pc_->sc()->strict()) {
11214         possibleError->setPendingDestructuringErrorAt(
11215             namePos, JSMSG_BAD_STRICT_ASSIGN_ARGUMENTS);
11216       } else {
11217         possibleError->setPendingDestructuringWarningAt(
11218             namePos, JSMSG_BAD_STRICT_ASSIGN_ARGUMENTS);
11219       }
11220       return;
11221     }
11222 
11223     if (handler_.isEvalName(name)) {
11224       if (pc_->sc()->strict()) {
11225         possibleError->setPendingDestructuringErrorAt(
11226             namePos, JSMSG_BAD_STRICT_ASSIGN_EVAL);
11227       } else {
11228         possibleError->setPendingDestructuringWarningAt(
11229             namePos, JSMSG_BAD_STRICT_ASSIGN_EVAL);
11230       }
11231       return;
11232     }
11233   }
11234 }
11235 
11236 template <class ParseHandler, typename Unit>
checkDestructuringAssignmentElement(Node expr,TokenPos exprPos,PossibleError * exprPossibleError,PossibleError * possibleError)11237 bool GeneralParser<ParseHandler, Unit>::checkDestructuringAssignmentElement(
11238     Node expr, TokenPos exprPos, PossibleError* exprPossibleError,
11239     PossibleError* possibleError) {
11240   // ES2018 draft rev 0719f44aab93215ed9a626b2f45bd34f36916834
11241   // 12.15.5 Destructuring Assignment
11242   //
11243   // AssignmentElement[Yield, Await]:
11244   //   DestructuringAssignmentTarget[?Yield, ?Await]
11245   //   DestructuringAssignmentTarget[?Yield, ?Await] Initializer[+In,
11246   //                                                             ?Yield,
11247   //                                                             ?Await]
11248 
11249   // If |expr| is an assignment element with an initializer expression, its
11250   // destructuring assignment target was already validated in assignExpr().
11251   // Otherwise we need to check that |expr| is a valid destructuring target.
11252   if (handler_.isUnparenthesizedAssignment(expr)) {
11253     // Report any pending expression error if we're definitely not in a
11254     // destructuring context.
11255     if (!possibleError) {
11256       return exprPossibleError->checkForExpressionError();
11257     }
11258 
11259     exprPossibleError->transferErrorsTo(possibleError);
11260     return true;
11261   }
11262   return checkDestructuringAssignmentTarget(expr, exprPos, exprPossibleError,
11263                                             possibleError);
11264 }
11265 
11266 template <class ParseHandler, typename Unit>
11267 typename ParseHandler::ListNodeType
arrayInitializer(YieldHandling yieldHandling,PossibleError * possibleError)11268 GeneralParser<ParseHandler, Unit>::arrayInitializer(
11269     YieldHandling yieldHandling, PossibleError* possibleError) {
11270   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftBracket));
11271 
11272   uint32_t begin = pos().begin;
11273   ListNodeType literal = handler_.newArrayLiteral(begin);
11274   if (!literal) {
11275     return null();
11276   }
11277 
11278   TokenKind tt;
11279   if (!tokenStream.getToken(&tt, TokenStream::SlashIsRegExp)) {
11280     return null();
11281   }
11282 
11283   if (tt == TokenKind::RightBracket) {
11284     /*
11285      * Mark empty arrays as non-constant, since we cannot easily
11286      * determine their type.
11287      */
11288     handler_.setListHasNonConstInitializer(literal);
11289   } else {
11290     anyChars.ungetToken();
11291 
11292     for (uint32_t index = 0;; index++) {
11293       if (index >= NativeObject::MAX_DENSE_ELEMENTS_COUNT) {
11294         error(JSMSG_ARRAY_INIT_TOO_BIG);
11295         return null();
11296       }
11297 
11298       TokenKind tt;
11299       if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) {
11300         return null();
11301       }
11302       if (tt == TokenKind::RightBracket) {
11303         break;
11304       }
11305 
11306       if (tt == TokenKind::Comma) {
11307         tokenStream.consumeKnownToken(TokenKind::Comma,
11308                                       TokenStream::SlashIsRegExp);
11309         if (!handler_.addElision(literal, pos())) {
11310           return null();
11311         }
11312         continue;
11313       }
11314 
11315       if (tt == TokenKind::TripleDot) {
11316         tokenStream.consumeKnownToken(TokenKind::TripleDot,
11317                                       TokenStream::SlashIsRegExp);
11318         uint32_t begin = pos().begin;
11319 
11320         TokenPos innerPos;
11321         if (!tokenStream.peekTokenPos(&innerPos, TokenStream::SlashIsRegExp)) {
11322           return null();
11323         }
11324 
11325         PossibleError possibleErrorInner(*this);
11326         Node inner = assignExpr(InAllowed, yieldHandling, TripledotProhibited,
11327                                 &possibleErrorInner);
11328         if (!inner) {
11329           return null();
11330         }
11331         if (!checkDestructuringAssignmentTarget(
11332                 inner, innerPos, &possibleErrorInner, possibleError)) {
11333           return null();
11334         }
11335 
11336         if (!handler_.addSpreadElement(literal, begin, inner)) {
11337           return null();
11338         }
11339       } else {
11340         TokenPos elementPos;
11341         if (!tokenStream.peekTokenPos(&elementPos,
11342                                       TokenStream::SlashIsRegExp)) {
11343           return null();
11344         }
11345 
11346         PossibleError possibleErrorInner(*this);
11347         Node element = assignExpr(InAllowed, yieldHandling, TripledotProhibited,
11348                                   &possibleErrorInner);
11349         if (!element) {
11350           return null();
11351         }
11352         if (!checkDestructuringAssignmentElement(
11353                 element, elementPos, &possibleErrorInner, possibleError)) {
11354           return null();
11355         }
11356         handler_.addArrayElement(literal, element);
11357       }
11358 
11359       bool matched;
11360       if (!tokenStream.matchToken(&matched, TokenKind::Comma,
11361                                   TokenStream::SlashIsRegExp)) {
11362         return null();
11363       }
11364       if (!matched) {
11365         break;
11366       }
11367 
11368       if (tt == TokenKind::TripleDot && possibleError) {
11369         possibleError->setPendingDestructuringErrorAt(pos(),
11370                                                       JSMSG_REST_WITH_COMMA);
11371       }
11372     }
11373 
11374     if (!mustMatchToken(
11375             TokenKind::RightBracket, [this, begin](TokenKind actual) {
11376               this->reportMissingClosing(JSMSG_BRACKET_AFTER_LIST,
11377                                          JSMSG_BRACKET_OPENED, begin);
11378             })) {
11379       return null();
11380     }
11381   }
11382 
11383   handler_.setEndPosition(literal, pos().end);
11384   return literal;
11385 }
11386 
11387 template <class ParseHandler, typename Unit>
propertyName(YieldHandling yieldHandling,PropertyNameContext propertyNameContext,const Maybe<DeclarationKind> & maybeDecl,ListNodeType propList,TaggedParserAtomIndex * propAtomOut)11388 typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::propertyName(
11389     YieldHandling yieldHandling, PropertyNameContext propertyNameContext,
11390     const Maybe<DeclarationKind>& maybeDecl, ListNodeType propList,
11391     TaggedParserAtomIndex* propAtomOut) {
11392   // PropertyName[Yield, Await]:
11393   //   LiteralPropertyName
11394   //   ComputedPropertyName[?Yield, ?Await]
11395   //
11396   // LiteralPropertyName:
11397   //   IdentifierName
11398   //   StringLiteral
11399   //   NumericLiteral
11400   TokenKind ltok = anyChars.currentToken().type;
11401 
11402   *propAtomOut = TaggedParserAtomIndex::null();
11403   switch (ltok) {
11404     case TokenKind::Number: {
11405       auto numAtom = NumberToParserAtom(cx_, this->parserAtoms(),
11406                                         anyChars.currentToken().number());
11407       if (!numAtom) {
11408         return null();
11409       }
11410       *propAtomOut = numAtom;
11411       return newNumber(anyChars.currentToken());
11412     }
11413 
11414     case TokenKind::BigInt: {
11415       Node biNode = newBigInt();
11416       if (!biNode) {
11417         return null();
11418       }
11419       return handler_.newSyntheticComputedName(biNode, pos().begin, pos().end);
11420     }
11421     case TokenKind::String: {
11422       auto str = anyChars.currentToken().atom();
11423       *propAtomOut = str;
11424       uint32_t index;
11425       if (this->parserAtoms().isIndex(str, &index)) {
11426         return handler_.newNumber(index, NoDecimal, pos());
11427       }
11428       return stringLiteral();
11429     }
11430 
11431     case TokenKind::LeftBracket:
11432       return computedPropertyName(yieldHandling, maybeDecl, propertyNameContext,
11433                                   propList);
11434 
11435     case TokenKind::PrivateName: {
11436       if (propertyNameContext != PropertyNameContext::PropertyNameInClass) {
11437         error(JSMSG_ILLEGAL_PRIVATE_FIELD);
11438         return null();
11439       }
11440 
11441       TaggedParserAtomIndex propName = anyChars.currentName();
11442       *propAtomOut = propName;
11443       return privateNameReference(propName);
11444     }
11445 
11446     default: {
11447       if (!TokenKindIsPossibleIdentifierName(ltok)) {
11448         error(JSMSG_UNEXPECTED_TOKEN, "property name", TokenKindToDesc(ltok));
11449         return null();
11450       }
11451 
11452       TaggedParserAtomIndex name = anyChars.currentName();
11453       *propAtomOut = name;
11454       return handler_.newObjectLiteralPropertyName(name, pos());
11455     }
11456   }
11457 }
11458 
11459 // True if `kind` can be the first token of a PropertyName.
TokenKindCanStartPropertyName(TokenKind tt)11460 static bool TokenKindCanStartPropertyName(TokenKind tt) {
11461   return TokenKindIsPossibleIdentifierName(tt) || tt == TokenKind::String ||
11462          tt == TokenKind::Number || tt == TokenKind::LeftBracket ||
11463          tt == TokenKind::Mul || tt == TokenKind::BigInt ||
11464          tt == TokenKind::PrivateName;
11465 }
11466 
11467 template <class ParseHandler, typename Unit>
11468 typename ParseHandler::Node
propertyOrMethodName(YieldHandling yieldHandling,PropertyNameContext propertyNameContext,const Maybe<DeclarationKind> & maybeDecl,ListNodeType propList,PropertyType * propType,TaggedParserAtomIndex * propAtomOut)11469 GeneralParser<ParseHandler, Unit>::propertyOrMethodName(
11470     YieldHandling yieldHandling, PropertyNameContext propertyNameContext,
11471     const Maybe<DeclarationKind>& maybeDecl, ListNodeType propList,
11472     PropertyType* propType, TaggedParserAtomIndex* propAtomOut) {
11473   // We're parsing an object literal, class, or destructuring pattern;
11474   // propertyNameContext tells which one. This method parses any of the
11475   // following, storing the corresponding PropertyType in `*propType` to tell
11476   // the caller what we parsed:
11477   //
11478   //     async [no LineTerminator here] PropertyName
11479   //                            ==> PropertyType::AsyncMethod
11480   //     async [no LineTerminator here] * PropertyName
11481   //                            ==> PropertyType::AsyncGeneratorMethod
11482   //     * PropertyName         ==> PropertyType::GeneratorMethod
11483   //     get PropertyName       ==> PropertyType::Getter
11484   //     set PropertyName       ==> PropertyType::Setter
11485   //     PropertyName :         ==> PropertyType::Normal
11486   //     PropertyName           ==> see below
11487   //
11488   // In the last case, where there's not a `:` token to consume, we peek at
11489   // (but don't consume) the next token to decide how to set `*propType`.
11490   //
11491   //     `,` or `}`             ==> PropertyType::Shorthand
11492   //     `(`                    ==> PropertyType::Method
11493   //     `=`, not in a class    ==> PropertyType::CoverInitializedName
11494   //     '=', in a class        ==> PropertyType::Field
11495   //     any token, in a class  ==> PropertyType::Field (ASI)
11496   //
11497   // The caller must check `*propType` and throw if whatever we parsed isn't
11498   // allowed here (for example, a getter in a destructuring pattern).
11499   //
11500   // This method does *not* match `static` (allowed in classes) or `...`
11501   // (allowed in object literals and patterns). The caller must take care of
11502   // those before calling this method.
11503 
11504   TokenKind ltok;
11505   if (!tokenStream.getToken(&ltok, TokenStream::SlashIsInvalid)) {
11506     return null();
11507   }
11508 
11509   MOZ_ASSERT(ltok != TokenKind::RightCurly,
11510              "caller should have handled TokenKind::RightCurly");
11511 
11512   // Accept `async` and/or `*`, indicating an async or generator method;
11513   // or `get` or `set`, indicating an accessor.
11514   bool isGenerator = false;
11515   bool isAsync = false;
11516   bool isGetter = false;
11517   bool isSetter = false;
11518 
11519   if (ltok == TokenKind::Async) {
11520     // `async` is also a PropertyName by itself (it's a conditional keyword),
11521     // so peek at the next token to see if we're really looking at a method.
11522     TokenKind tt = TokenKind::Eof;
11523     if (!tokenStream.peekTokenSameLine(&tt)) {
11524       return null();
11525     }
11526     if (TokenKindCanStartPropertyName(tt)) {
11527       isAsync = true;
11528       tokenStream.consumeKnownToken(tt);
11529       ltok = tt;
11530     }
11531   }
11532 
11533   if (ltok == TokenKind::Mul) {
11534     isGenerator = true;
11535     if (!tokenStream.getToken(&ltok)) {
11536       return null();
11537     }
11538   }
11539 
11540   if (!isAsync && !isGenerator &&
11541       (ltok == TokenKind::Get || ltok == TokenKind::Set)) {
11542     // We have parsed |get| or |set|. Look for an accessor property
11543     // name next.
11544     TokenKind tt;
11545     if (!tokenStream.peekToken(&tt)) {
11546       return null();
11547     }
11548     if (TokenKindCanStartPropertyName(tt)) {
11549       tokenStream.consumeKnownToken(tt);
11550       isGetter = (ltok == TokenKind::Get);
11551       isSetter = (ltok == TokenKind::Set);
11552     }
11553   }
11554 
11555   Node propName = propertyName(yieldHandling, propertyNameContext, maybeDecl,
11556                                propList, propAtomOut);
11557   if (!propName) {
11558     return null();
11559   }
11560 
11561   // Grab the next token following the property/method name.
11562   // (If this isn't a colon, we're going to either put it back or throw.)
11563   TokenKind tt;
11564   if (!tokenStream.getToken(&tt)) {
11565     return null();
11566   }
11567 
11568   if (tt == TokenKind::Colon) {
11569     if (isGenerator || isAsync || isGetter || isSetter) {
11570       error(JSMSG_BAD_PROP_ID);
11571       return null();
11572     }
11573     *propType = PropertyType::Normal;
11574     return propName;
11575   }
11576 
11577   if (propertyNameContext != PropertyNameInClass &&
11578       TokenKindIsPossibleIdentifierName(ltok) &&
11579       (tt == TokenKind::Comma || tt == TokenKind::RightCurly ||
11580        tt == TokenKind::Assign)) {
11581     if (isGenerator || isAsync || isGetter || isSetter) {
11582       error(JSMSG_BAD_PROP_ID);
11583       return null();
11584     }
11585 
11586     anyChars.ungetToken();
11587     *propType = tt == TokenKind::Assign ? PropertyType::CoverInitializedName
11588                                         : PropertyType::Shorthand;
11589     return propName;
11590   }
11591 
11592   if (tt == TokenKind::LeftParen) {
11593     anyChars.ungetToken();
11594 
11595 #ifdef ENABLE_RECORD_TUPLE
11596     if (propertyNameContext == PropertyNameInRecord) {
11597       // Record & Tuple proposal, section 7.1.1:
11598       // RecordPropertyDefinition doesn't cover methods
11599       error(JSMSG_BAD_PROP_ID);
11600       return null();
11601     }
11602 #endif
11603 
11604     if (isGenerator && isAsync) {
11605       *propType = PropertyType::AsyncGeneratorMethod;
11606     } else if (isGenerator) {
11607       *propType = PropertyType::GeneratorMethod;
11608     } else if (isAsync) {
11609       *propType = PropertyType::AsyncMethod;
11610     } else if (isGetter) {
11611       *propType = PropertyType::Getter;
11612     } else if (isSetter) {
11613       *propType = PropertyType::Setter;
11614     } else {
11615       *propType = PropertyType::Method;
11616     }
11617     return propName;
11618   }
11619 
11620   if (propertyNameContext == PropertyNameInClass) {
11621     if (isGenerator || isAsync || isGetter || isSetter) {
11622       error(JSMSG_BAD_PROP_ID);
11623       return null();
11624     }
11625     anyChars.ungetToken();
11626     *propType = PropertyType::Field;
11627     return propName;
11628   }
11629 
11630   error(JSMSG_COLON_AFTER_ID);
11631   return null();
11632 }
11633 
11634 template <class ParseHandler, typename Unit>
11635 typename ParseHandler::UnaryNodeType
computedPropertyName(YieldHandling yieldHandling,const Maybe<DeclarationKind> & maybeDecl,PropertyNameContext propertyNameContext,ListNodeType literal)11636 GeneralParser<ParseHandler, Unit>::computedPropertyName(
11637     YieldHandling yieldHandling, const Maybe<DeclarationKind>& maybeDecl,
11638     PropertyNameContext propertyNameContext, ListNodeType literal) {
11639   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftBracket));
11640 
11641   uint32_t begin = pos().begin;
11642 
11643   if (maybeDecl) {
11644     if (*maybeDecl == DeclarationKind::FormalParameter) {
11645       pc_->functionBox()->hasParameterExprs = true;
11646     }
11647   } else if (propertyNameContext ==
11648              PropertyNameContext::PropertyNameInLiteral) {
11649     handler_.setListHasNonConstInitializer(literal);
11650   }
11651 
11652   Node assignNode = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
11653   if (!assignNode) {
11654     return null();
11655   }
11656 
11657   if (!mustMatchToken(TokenKind::RightBracket, JSMSG_COMP_PROP_UNTERM_EXPR)) {
11658     return null();
11659   }
11660   return handler_.newComputedName(assignNode, begin, pos().end);
11661 }
11662 
11663 template <class ParseHandler, typename Unit>
11664 typename ParseHandler::ListNodeType
objectLiteral(YieldHandling yieldHandling,PossibleError * possibleError)11665 GeneralParser<ParseHandler, Unit>::objectLiteral(YieldHandling yieldHandling,
11666                                                  PossibleError* possibleError) {
11667   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftCurly));
11668 
11669   uint32_t openedPos = pos().begin;
11670 
11671   ListNodeType literal = handler_.newObjectLiteral(pos().begin);
11672   if (!literal) {
11673     return null();
11674   }
11675 
11676   bool seenPrototypeMutation = false;
11677   bool seenCoverInitializedName = false;
11678   Maybe<DeclarationKind> declKind = Nothing();
11679   TaggedParserAtomIndex propAtom;
11680   for (;;) {
11681     TokenKind tt;
11682     if (!tokenStream.peekToken(&tt)) {
11683       return null();
11684     }
11685     if (tt == TokenKind::RightCurly) {
11686       break;
11687     }
11688 
11689     if (tt == TokenKind::TripleDot) {
11690       tokenStream.consumeKnownToken(TokenKind::TripleDot);
11691       uint32_t begin = pos().begin;
11692 
11693       TokenPos innerPos;
11694       if (!tokenStream.peekTokenPos(&innerPos, TokenStream::SlashIsRegExp)) {
11695         return null();
11696       }
11697 
11698       PossibleError possibleErrorInner(*this);
11699       Node inner = assignExpr(InAllowed, yieldHandling, TripledotProhibited,
11700                               &possibleErrorInner);
11701       if (!inner) {
11702         return null();
11703       }
11704       if (!checkDestructuringAssignmentTarget(
11705               inner, innerPos, &possibleErrorInner, possibleError,
11706               TargetBehavior::ForbidAssignmentPattern)) {
11707         return null();
11708       }
11709       if (!handler_.addSpreadProperty(literal, begin, inner)) {
11710         return null();
11711       }
11712     } else {
11713       TokenPos namePos = anyChars.nextToken().pos;
11714 
11715       PropertyType propType;
11716       Node propName =
11717           propertyOrMethodName(yieldHandling, PropertyNameInLiteral, declKind,
11718                                literal, &propType, &propAtom);
11719       if (!propName) {
11720         return null();
11721       }
11722 
11723       if (propType == PropertyType::Normal) {
11724         TokenPos exprPos;
11725         if (!tokenStream.peekTokenPos(&exprPos, TokenStream::SlashIsRegExp)) {
11726           return null();
11727         }
11728 
11729         PossibleError possibleErrorInner(*this);
11730         Node propExpr = assignExpr(InAllowed, yieldHandling,
11731                                    TripledotProhibited, &possibleErrorInner);
11732         if (!propExpr) {
11733           return null();
11734         }
11735 
11736         if (!checkDestructuringAssignmentElement(
11737                 propExpr, exprPos, &possibleErrorInner, possibleError)) {
11738           return null();
11739         }
11740 
11741         if (propAtom == TaggedParserAtomIndex::WellKnown::proto()) {
11742           if (seenPrototypeMutation) {
11743             // Directly report the error when we're definitely not
11744             // in a destructuring context.
11745             if (!possibleError) {
11746               errorAt(namePos.begin, JSMSG_DUPLICATE_PROTO_PROPERTY);
11747               return null();
11748             }
11749 
11750             // Otherwise delay error reporting until we've
11751             // determined whether or not we're destructuring.
11752             possibleError->setPendingExpressionErrorAt(
11753                 namePos, JSMSG_DUPLICATE_PROTO_PROPERTY);
11754           }
11755           seenPrototypeMutation = true;
11756 
11757           // This occurs *only* if we observe PropertyType::Normal!
11758           // Only |__proto__: v| mutates [[Prototype]]. Getters,
11759           // setters, method/generator definitions, computed
11760           // property name versions of all of these, and shorthands
11761           // do not.
11762           if (!handler_.addPrototypeMutation(literal, namePos.begin,
11763                                              propExpr)) {
11764             return null();
11765           }
11766         } else {
11767           BinaryNodeType propDef =
11768               handler_.newPropertyDefinition(propName, propExpr);
11769           if (!propDef) {
11770             return null();
11771           }
11772 
11773           handler_.addPropertyDefinition(literal, propDef);
11774         }
11775       } else if (propType == PropertyType::Shorthand) {
11776         /*
11777          * Support, e.g., |({x, y} = o)| as destructuring shorthand
11778          * for |({x: x, y: y} = o)|, and |var o = {x, y}| as
11779          * initializer shorthand for |var o = {x: x, y: y}|.
11780          */
11781         TaggedParserAtomIndex name = identifierReference(yieldHandling);
11782         if (!name) {
11783           return null();
11784         }
11785 
11786         NameNodeType nameExpr = identifierReference(name);
11787         if (!nameExpr) {
11788           return null();
11789         }
11790 
11791         if (possibleError) {
11792           checkDestructuringAssignmentName(nameExpr, namePos, possibleError);
11793         }
11794 
11795         if (!handler_.addShorthand(literal, handler_.asName(propName),
11796                                    nameExpr)) {
11797           return null();
11798         }
11799       } else if (propType == PropertyType::CoverInitializedName) {
11800         /*
11801          * Support, e.g., |({x=1, y=2} = o)| as destructuring
11802          * shorthand with default values, as per ES6 12.14.5
11803          */
11804         TaggedParserAtomIndex name = identifierReference(yieldHandling);
11805         if (!name) {
11806           return null();
11807         }
11808 
11809         Node lhs = identifierReference(name);
11810         if (!lhs) {
11811           return null();
11812         }
11813 
11814         tokenStream.consumeKnownToken(TokenKind::Assign);
11815 
11816         if (!seenCoverInitializedName) {
11817           // "shorthand default" or "CoverInitializedName" syntax is
11818           // only valid in the case of destructuring.
11819           seenCoverInitializedName = true;
11820 
11821           if (!possibleError) {
11822             // Destructuring defaults are definitely not allowed
11823             // in this object literal, because of something the
11824             // caller knows about the preceding code. For example,
11825             // maybe the preceding token is an operator:
11826             // |x + {y=z}|.
11827             error(JSMSG_COLON_AFTER_ID);
11828             return null();
11829           }
11830 
11831           // Here we set a pending error so that later in the parse,
11832           // once we've determined whether or not we're
11833           // destructuring, the error can be reported or ignored
11834           // appropriately.
11835           possibleError->setPendingExpressionErrorAt(pos(),
11836                                                      JSMSG_COLON_AFTER_ID);
11837         }
11838 
11839         if (const char* chars = nameIsArgumentsOrEval(lhs)) {
11840           // |chars| is "arguments" or "eval" here.
11841           if (!strictModeErrorAt(namePos.begin, JSMSG_BAD_STRICT_ASSIGN,
11842                                  chars)) {
11843             return null();
11844           }
11845         }
11846 
11847         Node rhs = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
11848         if (!rhs) {
11849           return null();
11850         }
11851 
11852         BinaryNodeType propExpr =
11853             handler_.newAssignment(ParseNodeKind::AssignExpr, lhs, rhs);
11854         if (!propExpr) {
11855           return null();
11856         }
11857 
11858         if (!handler_.addPropertyDefinition(literal, propName, propExpr)) {
11859           return null();
11860         }
11861       } else {
11862         TaggedParserAtomIndex funName;
11863         bool hasStaticName =
11864             !anyChars.isCurrentTokenType(TokenKind::RightBracket) && propAtom;
11865         if (hasStaticName) {
11866           funName = propAtom;
11867 
11868           if (propType == PropertyType::Getter ||
11869               propType == PropertyType::Setter) {
11870             funName = prefixAccessorName(propType, propAtom);
11871             if (!funName) {
11872               return null();
11873             }
11874           }
11875         }
11876 
11877         FunctionNodeType funNode =
11878             methodDefinition(namePos.begin, propType, funName);
11879         if (!funNode) {
11880           return null();
11881         }
11882 
11883         AccessorType atype = ToAccessorType(propType);
11884         if (!handler_.addObjectMethodDefinition(literal, propName, funNode,
11885                                                 atype)) {
11886           return null();
11887         }
11888 
11889         if (possibleError) {
11890           possibleError->setPendingDestructuringErrorAt(
11891               namePos, JSMSG_BAD_DESTRUCT_TARGET);
11892         }
11893       }
11894     }
11895 
11896     bool matched;
11897     if (!tokenStream.matchToken(&matched, TokenKind::Comma,
11898                                 TokenStream::SlashIsInvalid)) {
11899       return null();
11900     }
11901     if (!matched) {
11902       break;
11903     }
11904     if (tt == TokenKind::TripleDot && possibleError) {
11905       possibleError->setPendingDestructuringErrorAt(pos(),
11906                                                     JSMSG_REST_WITH_COMMA);
11907     }
11908   }
11909 
11910   if (!mustMatchToken(
11911           TokenKind::RightCurly, [this, openedPos](TokenKind actual) {
11912             this->reportMissingClosing(JSMSG_CURLY_AFTER_LIST,
11913                                        JSMSG_CURLY_OPENED, openedPos);
11914           })) {
11915     return null();
11916   }
11917 
11918   handler_.setEndPosition(literal, pos().end);
11919   return literal;
11920 }
11921 
11922 #ifdef ENABLE_RECORD_TUPLE
11923 template <class ParseHandler, typename Unit>
11924 typename ParseHandler::ListNodeType
recordLiteral(YieldHandling yieldHandling)11925 GeneralParser<ParseHandler, Unit>::recordLiteral(YieldHandling yieldHandling) {
11926   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::HashCurly));
11927 
11928   uint32_t openedPos = pos().begin;
11929 
11930   ListNodeType literal = handler_.newRecordLiteral(pos().begin);
11931   if (!literal) {
11932     return null();
11933   }
11934 
11935   TaggedParserAtomIndex propAtom;
11936   for (;;) {
11937     TokenKind tt;
11938     if (!tokenStream.peekToken(&tt)) {
11939       return null();
11940     }
11941     if (tt == TokenKind::RightCurly) {
11942       break;
11943     }
11944 
11945     if (tt == TokenKind::TripleDot) {
11946       tokenStream.consumeKnownToken(TokenKind::TripleDot);
11947       uint32_t begin = pos().begin;
11948 
11949       TokenPos innerPos;
11950       if (!tokenStream.peekTokenPos(&innerPos, TokenStream::SlashIsRegExp)) {
11951         return null();
11952       }
11953 
11954       Node inner = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
11955       if (!inner) {
11956         return null();
11957       }
11958 
11959       if (!handler_.addSpreadProperty(literal, begin, inner)) {
11960         return null();
11961       }
11962     } else {
11963       TokenPos namePos = anyChars.nextToken().pos;
11964 
11965       PropertyType propType;
11966       Node propName = propertyOrMethodName(yieldHandling, PropertyNameInRecord,
11967                                            /* maybeDecl */ Nothing(), literal,
11968                                            &propType, &propAtom);
11969       if (!propName) {
11970         return null();
11971       }
11972 
11973       if (propType == PropertyType::Normal) {
11974         TokenPos exprPos;
11975         if (!tokenStream.peekTokenPos(&exprPos, TokenStream::SlashIsRegExp)) {
11976           return null();
11977         }
11978 
11979         Node propExpr =
11980             assignExpr(InAllowed, yieldHandling, TripledotProhibited);
11981         if (!propExpr) {
11982           return null();
11983         }
11984 
11985         if (propAtom == TaggedParserAtomIndex::WellKnown::proto()) {
11986           errorAt(namePos.begin, JSMSG_RECORD_NO_PROTO);
11987           return null();
11988         }
11989 
11990         BinaryNodeType propDef =
11991             handler_.newPropertyDefinition(propName, propExpr);
11992         if (!propDef) {
11993           return null();
11994         }
11995 
11996         handler_.addPropertyDefinition(literal, propDef);
11997       } else if (propType == PropertyType::Shorthand) {
11998         /*
11999          * Support |var o = #{x, y}| as initializer shorthand for
12000          * |var o = #{x: x, y: y}|.
12001          */
12002         TaggedParserAtomIndex name = identifierReference(yieldHandling);
12003         if (!name) {
12004           return null();
12005         }
12006 
12007         NameNodeType nameExpr = identifierReference(name);
12008         if (!nameExpr) {
12009           return null();
12010         }
12011 
12012         if (!handler_.addShorthand(literal, handler_.asName(propName),
12013                                    nameExpr)) {
12014           return null();
12015         }
12016       } else {
12017         error(JSMSG_BAD_PROP_ID);
12018         return null();
12019       }
12020     }
12021 
12022     bool matched;
12023     if (!tokenStream.matchToken(&matched, TokenKind::Comma,
12024                                 TokenStream::SlashIsInvalid)) {
12025       return null();
12026     }
12027     if (!matched) {
12028       break;
12029     }
12030   }
12031 
12032   if (!mustMatchToken(
12033           TokenKind::RightCurly, [this, openedPos](TokenKind actual) {
12034             this->reportMissingClosing(JSMSG_CURLY_AFTER_LIST,
12035                                        JSMSG_CURLY_OPENED, openedPos);
12036           })) {
12037     return null();
12038   }
12039 
12040   handler_.setEndPosition(literal, pos().end);
12041   return literal;
12042 }
12043 
12044 template <class ParseHandler, typename Unit>
12045 typename ParseHandler::ListNodeType
tupleLiteral(YieldHandling yieldHandling)12046 GeneralParser<ParseHandler, Unit>::tupleLiteral(YieldHandling yieldHandling) {
12047   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::HashBracket));
12048 
12049   uint32_t begin = pos().begin;
12050   ListNodeType literal = handler_.newTupleLiteral(begin);
12051   if (!literal) {
12052     return null();
12053   }
12054 
12055   for (uint32_t index = 0;; index++) {
12056     if (index >= NativeObject::MAX_DENSE_ELEMENTS_COUNT) {
12057       error(JSMSG_ARRAY_INIT_TOO_BIG);
12058       return null();
12059     }
12060 
12061     TokenKind tt;
12062     if (!tokenStream.peekToken(&tt, TokenStream::SlashIsRegExp)) {
12063       return null();
12064     }
12065     if (tt == TokenKind::RightBracket) {
12066       break;
12067     }
12068 
12069     if (tt == TokenKind::TripleDot) {
12070       tokenStream.consumeKnownToken(TokenKind::TripleDot,
12071                                     TokenStream::SlashIsRegExp);
12072       uint32_t begin = pos().begin;
12073 
12074       TokenPos innerPos;
12075       if (!tokenStream.peekTokenPos(&innerPos, TokenStream::SlashIsRegExp)) {
12076         return null();
12077       }
12078 
12079       Node inner = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
12080       if (!inner) {
12081         return null();
12082       }
12083 
12084       if (!handler_.addSpreadElement(literal, begin, inner)) {
12085         return null();
12086       }
12087     } else {
12088       TokenPos elementPos;
12089       if (!tokenStream.peekTokenPos(&elementPos, TokenStream::SlashIsRegExp)) {
12090         return null();
12091       }
12092 
12093       Node element = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
12094       if (!element) {
12095         return null();
12096       }
12097       handler_.addArrayElement(literal, element);
12098     }
12099 
12100     bool matched;
12101     if (!tokenStream.matchToken(&matched, TokenKind::Comma,
12102                                 TokenStream::SlashIsRegExp)) {
12103       return null();
12104     }
12105     if (!matched) {
12106       break;
12107     }
12108   }
12109 
12110   if (!mustMatchToken(TokenKind::RightBracket, [this, begin](TokenKind actual) {
12111         this->reportMissingClosing(JSMSG_BRACKET_AFTER_LIST,
12112                                    JSMSG_BRACKET_OPENED, begin);
12113       })) {
12114     return null();
12115   }
12116 
12117   handler_.setEndPosition(literal, pos().end);
12118   return literal;
12119 }
12120 #endif
12121 
12122 template <class ParseHandler, typename Unit>
12123 typename ParseHandler::FunctionNodeType
methodDefinition(uint32_t toStringStart,PropertyType propType,TaggedParserAtomIndex funName)12124 GeneralParser<ParseHandler, Unit>::methodDefinition(
12125     uint32_t toStringStart, PropertyType propType,
12126     TaggedParserAtomIndex funName) {
12127   FunctionSyntaxKind syntaxKind;
12128   switch (propType) {
12129     case PropertyType::Getter:
12130       syntaxKind = FunctionSyntaxKind::Getter;
12131       break;
12132 
12133     case PropertyType::Setter:
12134       syntaxKind = FunctionSyntaxKind::Setter;
12135       break;
12136 
12137     case PropertyType::Method:
12138     case PropertyType::GeneratorMethod:
12139     case PropertyType::AsyncMethod:
12140     case PropertyType::AsyncGeneratorMethod:
12141       syntaxKind = FunctionSyntaxKind::Method;
12142       break;
12143 
12144     case PropertyType::Constructor:
12145       syntaxKind = FunctionSyntaxKind::ClassConstructor;
12146       break;
12147 
12148     case PropertyType::DerivedConstructor:
12149       syntaxKind = FunctionSyntaxKind::DerivedClassConstructor;
12150       break;
12151 
12152     default:
12153       MOZ_CRASH("unexpected property type");
12154   }
12155 
12156   GeneratorKind generatorKind = (propType == PropertyType::GeneratorMethod ||
12157                                  propType == PropertyType::AsyncGeneratorMethod)
12158                                     ? GeneratorKind::Generator
12159                                     : GeneratorKind::NotGenerator;
12160 
12161   FunctionAsyncKind asyncKind = (propType == PropertyType::AsyncMethod ||
12162                                  propType == PropertyType::AsyncGeneratorMethod)
12163                                     ? FunctionAsyncKind::AsyncFunction
12164                                     : FunctionAsyncKind::SyncFunction;
12165 
12166   YieldHandling yieldHandling = GetYieldHandling(generatorKind);
12167 
12168   FunctionNodeType funNode = handler_.newFunction(syntaxKind, pos());
12169   if (!funNode) {
12170     return null();
12171   }
12172 
12173   return functionDefinition(funNode, toStringStart, InAllowed, yieldHandling,
12174                             funName, syntaxKind, generatorKind, asyncKind);
12175 }
12176 
12177 template <class ParseHandler, typename Unit>
tryNewTarget(BinaryNodeType * newTarget)12178 bool GeneralParser<ParseHandler, Unit>::tryNewTarget(
12179     BinaryNodeType* newTarget) {
12180   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::New));
12181 
12182   *newTarget = null();
12183 
12184   NullaryNodeType newHolder = handler_.newPosHolder(pos());
12185   if (!newHolder) {
12186     return false;
12187   }
12188 
12189   uint32_t begin = pos().begin;
12190 
12191   // |new| expects to look for an operand, so we will honor that.
12192   TokenKind next;
12193   if (!tokenStream.getToken(&next, TokenStream::SlashIsRegExp)) {
12194     return false;
12195   }
12196 
12197   // Don't unget the token, since lookahead cannot handle someone calling
12198   // getToken() with a different modifier. Callers should inspect
12199   // currentToken().
12200   if (next != TokenKind::Dot) {
12201     return true;
12202   }
12203 
12204   if (!tokenStream.getToken(&next)) {
12205     return false;
12206   }
12207   if (next != TokenKind::Target) {
12208     error(JSMSG_UNEXPECTED_TOKEN, "target", TokenKindToDesc(next));
12209     return false;
12210   }
12211 
12212   if (!pc_->sc()->allowNewTarget()) {
12213     errorAt(begin, JSMSG_BAD_NEWTARGET);
12214     return false;
12215   }
12216 
12217   NullaryNodeType targetHolder = handler_.newPosHolder(pos());
12218   if (!targetHolder) {
12219     return false;
12220   }
12221 
12222   *newTarget = handler_.newNewTarget(newHolder, targetHolder);
12223   return !!*newTarget;
12224 }
12225 
12226 template <class ParseHandler, typename Unit>
12227 typename ParseHandler::BinaryNodeType
importExpr(YieldHandling yieldHandling,bool allowCallSyntax)12228 GeneralParser<ParseHandler, Unit>::importExpr(YieldHandling yieldHandling,
12229                                               bool allowCallSyntax) {
12230   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Import));
12231 
12232   NullaryNodeType importHolder = handler_.newPosHolder(pos());
12233   if (!importHolder) {
12234     return null();
12235   }
12236 
12237   TokenKind next;
12238   if (!tokenStream.getToken(&next)) {
12239     return null();
12240   }
12241 
12242   if (next == TokenKind::Dot) {
12243     if (!tokenStream.getToken(&next)) {
12244       return null();
12245     }
12246     if (next != TokenKind::Meta) {
12247       error(JSMSG_UNEXPECTED_TOKEN, "meta", TokenKindToDesc(next));
12248       return null();
12249     }
12250 
12251     if (parseGoal() != ParseGoal::Module) {
12252       errorAt(pos().begin, JSMSG_IMPORT_META_OUTSIDE_MODULE);
12253       return null();
12254     }
12255 
12256     NullaryNodeType metaHolder = handler_.newPosHolder(pos());
12257     if (!metaHolder) {
12258       return null();
12259     }
12260 
12261     return handler_.newImportMeta(importHolder, metaHolder);
12262   } else if (next == TokenKind::LeftParen && allowCallSyntax) {
12263     Node arg = assignExpr(InAllowed, yieldHandling, TripledotProhibited);
12264     if (!arg) {
12265       return null();
12266     }
12267 
12268     if (!tokenStream.peekToken(&next, TokenStream::SlashIsRegExp)) {
12269       return null();
12270     }
12271 
12272     Node optionalArg;
12273     if (options().importAssertions) {
12274       if (next == TokenKind::Comma) {
12275         tokenStream.consumeKnownToken(TokenKind::Comma,
12276                                       TokenStream::SlashIsRegExp);
12277 
12278         if (!tokenStream.peekToken(&next, TokenStream::SlashIsRegExp)) {
12279           return null();
12280         }
12281 
12282         if (next != TokenKind::RightParen) {
12283           optionalArg =
12284               assignExpr(InAllowed, yieldHandling, TripledotProhibited);
12285           if (!optionalArg) {
12286             return null();
12287           }
12288 
12289           if (!tokenStream.peekToken(&next, TokenStream::SlashIsRegExp)) {
12290             return null();
12291           }
12292 
12293           if (next == TokenKind::Comma) {
12294             tokenStream.consumeKnownToken(TokenKind::Comma,
12295                                           TokenStream::SlashIsRegExp);
12296           }
12297         } else {
12298           optionalArg = handler_.newPosHolder(TokenPos(pos().end, pos().end));
12299           if (!optionalArg) {
12300             return null();
12301           }
12302         }
12303       } else {
12304         optionalArg = handler_.newPosHolder(TokenPos(pos().end, pos().end));
12305         if (!optionalArg) {
12306           return null();
12307         }
12308       }
12309     } else {
12310       optionalArg = handler_.newPosHolder(TokenPos(pos().end, pos().end));
12311       if (!optionalArg) {
12312         return null();
12313       }
12314     }
12315 
12316     if (!mustMatchToken(TokenKind::RightParen, JSMSG_PAREN_AFTER_ARGS)) {
12317       return null();
12318     }
12319 
12320     Node spec = handler_.newCallImportSpec(arg, optionalArg);
12321     if (!spec) {
12322       return null();
12323     }
12324 
12325     return handler_.newCallImport(importHolder, spec);
12326   } else {
12327     error(JSMSG_UNEXPECTED_TOKEN_NO_EXPECT, TokenKindToDesc(next));
12328     return null();
12329   }
12330 }
12331 
12332 template <class ParseHandler, typename Unit>
primaryExpr(YieldHandling yieldHandling,TripledotHandling tripledotHandling,TokenKind tt,PossibleError * possibleError,InvokedPrediction invoked)12333 typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::primaryExpr(
12334     YieldHandling yieldHandling, TripledotHandling tripledotHandling,
12335     TokenKind tt, PossibleError* possibleError, InvokedPrediction invoked) {
12336   MOZ_ASSERT(anyChars.isCurrentTokenType(tt));
12337   AutoCheckRecursionLimit recursion(cx_);
12338   if (!recursion.check(cx_)) {
12339     return null();
12340   }
12341 
12342   switch (tt) {
12343     case TokenKind::Function:
12344       return functionExpr(pos().begin, invoked,
12345                           FunctionAsyncKind::SyncFunction);
12346 
12347     case TokenKind::Class:
12348       return classDefinition(yieldHandling, ClassExpression, NameRequired);
12349 
12350     case TokenKind::LeftBracket:
12351       return arrayInitializer(yieldHandling, possibleError);
12352 
12353     case TokenKind::LeftCurly:
12354       return objectLiteral(yieldHandling, possibleError);
12355 
12356 #ifdef ENABLE_RECORD_TUPLE
12357     case TokenKind::HashCurly:
12358       return recordLiteral(yieldHandling);
12359 
12360     case TokenKind::HashBracket:
12361       return tupleLiteral(yieldHandling);
12362 #endif
12363 
12364     case TokenKind::LeftParen: {
12365       TokenKind next;
12366       if (!tokenStream.peekToken(&next, TokenStream::SlashIsRegExp)) {
12367         return null();
12368       }
12369 
12370       if (next == TokenKind::RightParen) {
12371         // Not valid expression syntax, but this is valid in an arrow function
12372         // with no params: `() => body`.
12373         tokenStream.consumeKnownToken(TokenKind::RightParen,
12374                                       TokenStream::SlashIsRegExp);
12375 
12376         if (!tokenStream.peekToken(&next)) {
12377           return null();
12378         }
12379         if (next != TokenKind::Arrow) {
12380           error(JSMSG_UNEXPECTED_TOKEN, "expression",
12381                 TokenKindToDesc(TokenKind::RightParen));
12382           return null();
12383         }
12384 
12385         // Now just return something that will allow parsing to continue.
12386         // It doesn't matter what; when we reach the =>, we will rewind and
12387         // reparse the whole arrow function. See Parser::assignExpr.
12388         return handler_.newNullLiteral(pos());
12389       }
12390 
12391       // Pass |possibleError| to support destructuring in arrow parameters.
12392       Node expr = exprInParens(InAllowed, yieldHandling, TripledotAllowed,
12393                                possibleError);
12394       if (!expr) {
12395         return null();
12396       }
12397       if (!mustMatchToken(TokenKind::RightParen, JSMSG_PAREN_IN_PAREN)) {
12398         return null();
12399       }
12400       return handler_.parenthesize(expr);
12401     }
12402 
12403     case TokenKind::TemplateHead:
12404       return templateLiteral(yieldHandling);
12405 
12406     case TokenKind::NoSubsTemplate:
12407       return noSubstitutionUntaggedTemplate();
12408 
12409     case TokenKind::String:
12410       return stringLiteral();
12411 
12412     default: {
12413       if (!TokenKindIsPossibleIdentifier(tt)) {
12414         error(JSMSG_UNEXPECTED_TOKEN, "expression", TokenKindToDesc(tt));
12415         return null();
12416       }
12417 
12418       if (tt == TokenKind::Async) {
12419         TokenKind nextSameLine = TokenKind::Eof;
12420         if (!tokenStream.peekTokenSameLine(&nextSameLine)) {
12421           return null();
12422         }
12423 
12424         if (nextSameLine == TokenKind::Function) {
12425           uint32_t toStringStart = pos().begin;
12426           tokenStream.consumeKnownToken(TokenKind::Function);
12427           return functionExpr(toStringStart, PredictUninvoked,
12428                               FunctionAsyncKind::AsyncFunction);
12429         }
12430       }
12431 
12432       TaggedParserAtomIndex name = identifierReference(yieldHandling);
12433       if (!name) {
12434         return null();
12435       }
12436 
12437       return identifierReference(name);
12438     }
12439 
12440     case TokenKind::RegExp:
12441       return newRegExp();
12442 
12443     case TokenKind::Number:
12444       return newNumber(anyChars.currentToken());
12445 
12446     case TokenKind::BigInt:
12447       return newBigInt();
12448 
12449     case TokenKind::True:
12450       return handler_.newBooleanLiteral(true, pos());
12451     case TokenKind::False:
12452       return handler_.newBooleanLiteral(false, pos());
12453     case TokenKind::This: {
12454       NameNodeType thisName = null();
12455       if (pc_->sc()->hasFunctionThisBinding()) {
12456         thisName = newThisName();
12457         if (!thisName) {
12458           return null();
12459         }
12460       }
12461       return handler_.newThisLiteral(pos(), thisName);
12462     }
12463     case TokenKind::Null:
12464       return handler_.newNullLiteral(pos());
12465 
12466     case TokenKind::TripleDot: {
12467       // This isn't valid expression syntax, but it's valid in an arrow
12468       // function as a trailing rest param: `(a, b, ...rest) => body`.  Check
12469       // if it's directly under
12470       // CoverParenthesizedExpressionAndArrowParameterList, and check for a
12471       // name, closing parenthesis, and arrow, and allow it only if all are
12472       // present.
12473       if (tripledotHandling != TripledotAllowed) {
12474         error(JSMSG_UNEXPECTED_TOKEN, "expression", TokenKindToDesc(tt));
12475         return null();
12476       }
12477 
12478       TokenKind next;
12479       if (!tokenStream.getToken(&next)) {
12480         return null();
12481       }
12482 
12483       if (next == TokenKind::LeftBracket || next == TokenKind::LeftCurly) {
12484         // Validate, but don't store the pattern right now. The whole arrow
12485         // function is reparsed in functionFormalParametersAndBody().
12486         if (!destructuringDeclaration(DeclarationKind::CoverArrowParameter,
12487                                       yieldHandling, next)) {
12488           return null();
12489         }
12490       } else {
12491         // This doesn't check that the provided name is allowed, e.g. if
12492         // the enclosing code is strict mode code, any of "let", "yield",
12493         // or "arguments" should be prohibited.  Argument-parsing code
12494         // handles that.
12495         if (!TokenKindIsPossibleIdentifier(next)) {
12496           error(JSMSG_UNEXPECTED_TOKEN, "rest argument name",
12497                 TokenKindToDesc(next));
12498           return null();
12499         }
12500       }
12501 
12502       if (!tokenStream.getToken(&next)) {
12503         return null();
12504       }
12505       if (next != TokenKind::RightParen) {
12506         error(JSMSG_UNEXPECTED_TOKEN, "closing parenthesis",
12507               TokenKindToDesc(next));
12508         return null();
12509       }
12510 
12511       if (!tokenStream.peekToken(&next)) {
12512         return null();
12513       }
12514       if (next != TokenKind::Arrow) {
12515         // Advance the scanner for proper error location reporting.
12516         tokenStream.consumeKnownToken(next);
12517         error(JSMSG_UNEXPECTED_TOKEN, "'=>' after argument list",
12518               TokenKindToDesc(next));
12519         return null();
12520       }
12521 
12522       anyChars.ungetToken();  // put back right paren
12523 
12524       // Return an arbitrary expression node. See case TokenKind::RightParen
12525       // above.
12526       return handler_.newNullLiteral(pos());
12527     }
12528   }
12529 }
12530 
12531 template <class ParseHandler, typename Unit>
exprInParens(InHandling inHandling,YieldHandling yieldHandling,TripledotHandling tripledotHandling,PossibleError * possibleError)12532 typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::exprInParens(
12533     InHandling inHandling, YieldHandling yieldHandling,
12534     TripledotHandling tripledotHandling,
12535     PossibleError* possibleError /* = nullptr */) {
12536   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::LeftParen));
12537   return expr(inHandling, yieldHandling, tripledotHandling, possibleError,
12538               PredictInvoked);
12539 }
12540 
12541 template class PerHandlerParser<FullParseHandler>;
12542 template class PerHandlerParser<SyntaxParseHandler>;
12543 template class GeneralParser<FullParseHandler, Utf8Unit>;
12544 template class GeneralParser<SyntaxParseHandler, Utf8Unit>;
12545 template class GeneralParser<FullParseHandler, char16_t>;
12546 template class GeneralParser<SyntaxParseHandler, char16_t>;
12547 template class Parser<FullParseHandler, Utf8Unit>;
12548 template class Parser<SyntaxParseHandler, Utf8Unit>;
12549 template class Parser<FullParseHandler, char16_t>;
12550 template class Parser<SyntaxParseHandler, char16_t>;
12551 
12552 }  // namespace js::frontend
12553