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