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