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