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 /* JS parser. */
8
9 #ifndef frontend_Parser_h
10 #define frontend_Parser_h
11
12 /*
13 * [SMDOC] JS Parser
14 *
15 * JS parsers capable of generating ASTs from source text.
16 *
17 * A parser embeds token stream information, then gets and matches tokens to
18 * generate a syntax tree that, if desired, BytecodeEmitter will use to compile
19 * bytecode.
20 *
21 * Like token streams (see the comment near the top of TokenStream.h), parser
22 * classes are heavily templatized -- along the token stream's character-type
23 * axis, and also along a full-parse/syntax-parse axis. Certain limitations of
24 * C++ (primarily the inability to partially specialize function templates),
25 * plus the desire to minimize compiled code size in duplicate function
26 * template instantiations wherever possible, mean that Parser exhibits much of
27 * the same unholy template/inheritance complexity as token streams.
28 *
29 * == ParserSharedBase ==
30 *
31 * ParserSharedBase is the base class for both regular JS and BinAST parsing.
32 * This class contains common fields and methods between both parsers. There is
33 * currently no BinAST parser here so this can potentially be merged into the
34 * ParserBase type below.
35 *
36 * == ParserBase → ParserSharedBase, ErrorReportMixin ==
37 *
38 * ParserBase is the base class for regular JS parser, shared by all regular JS
39 * parsers of all character types and parse-handling behavior. It stores
40 * everything character- and handler-agnostic.
41 *
42 * ParserBase's most important field is the parser's token stream's
43 * |TokenStreamAnyChars| component, for all tokenizing aspects that are
44 * character-type-agnostic. The character-type-sensitive components residing
45 * in |TokenStreamSpecific| (see the comment near the top of TokenStream.h)
46 * live elsewhere in this hierarchy. These separate locations are the reason
47 * for the |AnyCharsAccess| template parameter to |TokenStreamChars| and
48 * |TokenStreamSpecific|.
49 *
50 * == PerHandlerParser<ParseHandler> → ParserBase ==
51 *
52 * Certain parsing behavior varies between full parsing and syntax-only parsing
53 * but does not vary across source-text character types. For example, the work
54 * to "create an arguments object for a function" obviously varies between
55 * syntax and full parsing but (because no source characters are examined) does
56 * not vary by source text character type. Such functionality is implemented
57 * through functions in PerHandlerParser.
58 *
59 * Functionality only used by syntax parsing or full parsing doesn't live here:
60 * it should be implemented in the appropriate Parser<ParseHandler> (described
61 * further below).
62 *
63 * == GeneralParser<ParseHandler, Unit> → PerHandlerParser<ParseHandler> ==
64 *
65 * Most parsing behavior varies across the character-type axis (and possibly
66 * along the full/syntax axis). For example:
67 *
68 * * Parsing ECMAScript's Expression production, implemented by
69 * GeneralParser::expr, varies in this manner: different types are used to
70 * represent nodes in full and syntax parsing (ParseNode* versus an enum),
71 * and reading the tokens comprising the expression requires inspecting
72 * individual characters (necessarily dependent upon character type).
73 * * Reporting an error or warning does not depend on the full/syntax parsing
74 * distinction. But error reports and warnings include a line of context
75 * (or a slice of one), for pointing out where a mistake was made.
76 * Computing such line of context requires inspecting the source text to
77 * make that line/slice of context, which requires knowing the source text
78 * character type.
79 *
80 * Such functionality, implemented using identical function code across these
81 * axes, should live in GeneralParser.
82 *
83 * GeneralParser's most important field is the parser's token stream's
84 * |TokenStreamSpecific| component, for all aspects of tokenizing that (contra
85 * |TokenStreamAnyChars| in ParserBase above) are character-type-sensitive. As
86 * noted above, this field's existence separate from that in ParserBase
87 * motivates the |AnyCharsAccess| template parameters on various token stream
88 * classes.
89 *
90 * Everything in PerHandlerParser *could* be folded into GeneralParser (below)
91 * if desired. We don't fold in this manner because all such functions would
92 * be instantiated once per Unit -- but if exactly equivalent code would be
93 * generated (because PerHandlerParser functions have no awareness of Unit),
94 * it's risky to *depend* upon the compiler coalescing the instantiations into
95 * one in the final binary. PerHandlerParser guarantees no duplication.
96 *
97 * == Parser<ParseHandler, Unit> final → GeneralParser<ParseHandler, Unit> ==
98 *
99 * The final (pun intended) axis of complexity lies in Parser.
100 *
101 * Some functionality depends on character type, yet also is defined in
102 * significantly different form in full and syntax parsing. For example,
103 * attempting to parse the source text of a module will do so in full parsing
104 * but immediately fail in syntax parsing -- so the former is a mess'o'code
105 * while the latter is effectively |return null();|. Such functionality is
106 * defined in Parser<SyntaxParseHandler or FullParseHandler, Unit> as
107 * appropriate.
108 *
109 * There's a crucial distinction between GeneralParser and Parser, that
110 * explains why both must exist (despite taking exactly the same template
111 * parameters, and despite GeneralParser and Parser existing in a one-to-one
112 * relationship). GeneralParser is one unspecialized template class:
113 *
114 * template<class ParseHandler, typename Unit>
115 * class GeneralParser : ...
116 * {
117 * ...parsing functions...
118 * };
119 *
120 * but Parser is one undefined template class with two separate
121 * specializations:
122 *
123 * // Declare, but do not define.
124 * template<class ParseHandler, typename Unit> class Parser;
125 *
126 * // Define a syntax-parsing specialization.
127 * template<typename Unit>
128 * class Parser<SyntaxParseHandler, Unit> final
129 * : public GeneralParser<SyntaxParseHandler, Unit>
130 * {
131 * ...parsing functions...
132 * };
133 *
134 * // Define a full-parsing specialization.
135 * template<typename Unit>
136 * class Parser<SyntaxParseHandler, Unit> final
137 * : public GeneralParser<SyntaxParseHandler, Unit>
138 * {
139 * ...parsing functions...
140 * };
141 *
142 * This odd distinction is necessary because C++ unfortunately doesn't allow
143 * partial function specialization:
144 *
145 * // BAD: You can only specialize a template function if you specify *every*
146 * // template parameter, i.e. ParseHandler *and* Unit.
147 * template<typename Unit>
148 * void
149 * GeneralParser<SyntaxParseHandler, Unit>::foo() {}
150 *
151 * But if you specialize Parser *as a class*, then this is allowed:
152 *
153 * template<typename Unit>
154 * void
155 * Parser<SyntaxParseHandler, Unit>::foo() {}
156 *
157 * template<typename Unit>
158 * void
159 * Parser<FullParseHandler, Unit>::foo() {}
160 *
161 * because the only template parameter on the function is Unit -- and so all
162 * template parameters *are* varying, not a strict subset of them.
163 *
164 * So -- any parsing functionality that is differently defined for different
165 * ParseHandlers, *but* is defined textually identically for different Unit
166 * (even if different code ends up generated for them by the compiler), should
167 * reside in Parser.
168 */
169
170 #include "mozilla/Array.h"
171 #include "mozilla/Maybe.h"
172
173 #include <type_traits>
174 #include <utility>
175
176 #include "jspubtd.h"
177
178 #include "ds/Nestable.h"
179 #include "frontend/BytecodeCompiler.h"
180 #include "frontend/CompilationStencil.h" // CompilationState
181 #include "frontend/ErrorReporter.h"
182 #include "frontend/FullParseHandler.h"
183 #include "frontend/FunctionSyntaxKind.h" // FunctionSyntaxKind
184 #include "frontend/IteratorKind.h"
185 #include "frontend/NameAnalysisTypes.h"
186 #include "frontend/NameCollections.h"
187 #include "frontend/ParseContext.h"
188 #include "frontend/ParserAtom.h" // ParserAtomsTable, TaggedParserAtomIndex
189 #include "frontend/SharedContext.h"
190 #include "frontend/SyntaxParseHandler.h"
191 #include "frontend/TokenStream.h"
192 #include "js/friend/ErrorMessages.h" // JSErrNum, JSMSG_*
193 #include "js/Vector.h"
194 #include "vm/ErrorReporting.h"
195 #include "vm/GeneratorAndAsyncKind.h" // js::GeneratorKind, js::FunctionAsyncKind
196
197 namespace js {
198
199 class ModuleObject;
200
201 namespace frontend {
202
203 template <class ParseHandler, typename Unit>
204 class GeneralParser;
205
206 class SourceParseContext : public ParseContext {
207 public:
208 template <typename ParseHandler, typename Unit>
SourceParseContext(GeneralParser<ParseHandler,Unit> * prs,SharedContext * sc,Directives * newDirectives)209 SourceParseContext(GeneralParser<ParseHandler, Unit>* prs, SharedContext* sc,
210 Directives* newDirectives)
211 : ParseContext(prs->cx_, prs->pc_, sc, prs->tokenStream,
212 prs->compilationState_, newDirectives,
213 std::is_same_v<ParseHandler, FullParseHandler>) {}
214 };
215
216 enum VarContext { HoistVars, DontHoistVars };
217 enum PropListType { ObjectLiteral, ClassBody, DerivedClassBody };
218 enum class PropertyType {
219 Normal,
220 Shorthand,
221 CoverInitializedName,
222 Getter,
223 Setter,
224 Method,
225 GeneratorMethod,
226 AsyncMethod,
227 AsyncGeneratorMethod,
228 Constructor,
229 DerivedConstructor,
230 Field,
231 };
232
233 enum AwaitHandling : uint8_t {
234 AwaitIsName,
235 AwaitIsKeyword,
236 AwaitIsModuleKeyword
237 };
238
239 template <class ParseHandler, typename Unit>
240 class AutoAwaitIsKeyword;
241
242 template <class ParseHandler, typename Unit>
243 class AutoInParametersOfAsyncFunction;
244
245 class MOZ_STACK_CLASS ParserSharedBase {
246 public:
247 enum class Kind { Parser };
248
249 ParserSharedBase(JSContext* cx, CompilationState& compilationState,
250 Kind kind);
251 ~ParserSharedBase();
252
253 public:
254 JSContext* const cx_;
255
256 LifoAlloc& alloc_;
257
258 CompilationState& compilationState_;
259
260 // innermost parse context (stack-allocated)
261 ParseContext* pc_;
262
263 // For tracking used names in this parsing session.
264 UsedNameTracker& usedNames_;
265
266 public:
getCompilationState()267 CompilationState& getCompilationState() { return compilationState_; }
268
parserAtoms()269 ParserAtomsTable& parserAtoms() { return compilationState_.parserAtoms; }
parserAtoms()270 const ParserAtomsTable& parserAtoms() const {
271 return compilationState_.parserAtoms;
272 }
273
stencilAlloc()274 LifoAlloc& stencilAlloc() { return compilationState_.alloc; }
275
liftParserAtomToJSAtom(TaggedParserAtomIndex index)276 JSAtom* liftParserAtomToJSAtom(TaggedParserAtomIndex index) {
277 return parserAtoms().toJSAtom(cx_, index,
278 compilationState_.input.atomCache);
279 }
280
281 #if defined(DEBUG) || defined(JS_JITSPEW)
282 void dumpAtom(TaggedParserAtomIndex index) const;
283 #endif
284 };
285
286 class MOZ_STACK_CLASS ParserBase : public ParserSharedBase,
287 public ErrorReportMixin {
288 using Base = ErrorReportMixin;
289
290 public:
291 TokenStreamAnyChars anyChars;
292
293 ScriptSource* ss;
294
295 // Perform constant-folding; must be true when interfacing with the emitter.
296 const bool foldConstants_ : 1;
297
298 protected:
299 #if DEBUG
300 /* Our fallible 'checkOptions' member function has been called. */
301 bool checkOptionsCalled_ : 1;
302 #endif
303
304 /* Unexpected end of input, i.e. Eof not at top-level. */
305 bool isUnexpectedEOF_ : 1;
306
307 /* AwaitHandling */ uint8_t awaitHandling_ : 2;
308
309 bool inParametersOfAsyncFunction_ : 1;
310
311 public:
awaitIsKeyword()312 bool awaitIsKeyword() const { return awaitHandling_ != AwaitIsName; }
313
inParametersOfAsyncFunction()314 bool inParametersOfAsyncFunction() const {
315 return inParametersOfAsyncFunction_;
316 }
317
parseGoal()318 ParseGoal parseGoal() const {
319 return pc_->sc()->hasModuleGoal() ? ParseGoal::Module : ParseGoal::Script;
320 }
321
322 template <class, typename>
323 friend class AutoAwaitIsKeyword;
324 template <class, typename>
325 friend class AutoInParametersOfAsyncFunction;
326
327 ParserBase(JSContext* cx, const JS::ReadOnlyCompileOptions& options,
328 bool foldConstants, CompilationState& compilationState);
329 ~ParserBase();
330
331 bool checkOptions();
332
getFilename()333 const char* getFilename() const { return anyChars.getFilename(); }
pos()334 TokenPos pos() const { return anyChars.currentToken().pos; }
335
336 // Determine whether |yield| is a valid name in the current context.
yieldExpressionsSupported()337 bool yieldExpressionsSupported() const { return pc_->isGenerator(); }
338
setLocalStrictMode(bool strict)339 bool setLocalStrictMode(bool strict) {
340 MOZ_ASSERT(anyChars.debugHasNoLookahead());
341 return pc_->sc()->setLocalStrictMode(strict);
342 }
343
344 public:
345 // Implement ErrorReportMixin.
346
getContext()347 JSContext* getContext() const override { return cx_; }
348
strictMode()349 bool strictMode() const override { return pc_->sc()->strict(); }
350
options()351 const JS::ReadOnlyCompileOptions& options() const override {
352 return anyChars.options();
353 }
354
355 using Base::error;
356 using Base::errorAt;
357 using Base::errorNoOffset;
358 using Base::errorWithNotes;
359 using Base::errorWithNotesAt;
360 using Base::errorWithNotesNoOffset;
361 using Base::strictModeError;
362 using Base::strictModeErrorAt;
363 using Base::strictModeErrorNoOffset;
364 using Base::strictModeErrorWithNotes;
365 using Base::strictModeErrorWithNotesAt;
366 using Base::strictModeErrorWithNotesNoOffset;
367 using Base::warning;
368 using Base::warningAt;
369 using Base::warningNoOffset;
370
371 public:
isUnexpectedEOF()372 bool isUnexpectedEOF() const { return isUnexpectedEOF_; }
373
374 bool isValidStrictBinding(TaggedParserAtomIndex name);
375
376 bool hasValidSimpleStrictParameterNames();
377
378 // A Parser::Mark is the extension of the LifoAlloc::Mark to the entire
379 // Parser's state. Note: clients must still take care that any ParseContext
380 // that points into released ParseNodes is destroyed.
381 class Mark {
382 friend class ParserBase;
383 LifoAlloc::Mark mark;
384 CompilationState::CompilationStatePosition pos;
385 };
mark()386 Mark mark() const {
387 Mark m;
388 m.mark = alloc_.mark();
389 m.pos = compilationState_.getPosition();
390 return m;
391 }
release(Mark m)392 void release(Mark m) {
393 alloc_.release(m.mark);
394 compilationState_.rewind(m.pos);
395 }
396
397 public:
398 mozilla::Maybe<GlobalScope::ParserData*> newGlobalScopeData(
399 ParseContext::Scope& scope);
400 mozilla::Maybe<ModuleScope::ParserData*> newModuleScopeData(
401 ParseContext::Scope& scope);
402 mozilla::Maybe<EvalScope::ParserData*> newEvalScopeData(
403 ParseContext::Scope& scope);
404 mozilla::Maybe<FunctionScope::ParserData*> newFunctionScopeData(
405 ParseContext::Scope& scope, bool hasParameterExprs);
406 mozilla::Maybe<VarScope::ParserData*> newVarScopeData(
407 ParseContext::Scope& scope);
408 mozilla::Maybe<LexicalScope::ParserData*> newLexicalScopeData(
409 ParseContext::Scope& scope);
410 mozilla::Maybe<ClassBodyScope::ParserData*> newClassBodyScopeData(
411 ParseContext::Scope& scope);
412
413 protected:
414 enum InvokedPrediction { PredictUninvoked = false, PredictInvoked = true };
415 enum ForInitLocation { InForInit, NotInForInit };
416
417 // While on a |let| Name token, examine |next| (which must already be
418 // gotten). Indicate whether |next|, the next token already gotten with
419 // modifier TokenStream::SlashIsDiv, continues a LexicalDeclaration.
420 bool nextTokenContinuesLetDeclaration(TokenKind next);
421
422 bool noteUsedNameInternal(TaggedParserAtomIndex name,
423 NameVisibility visibility,
424 mozilla::Maybe<TokenPos> tokenPosition);
425
426 bool checkAndMarkSuperScope();
427
428 bool leaveInnerFunction(ParseContext* outerpc);
429
430 TaggedParserAtomIndex prefixAccessorName(PropertyType propType,
431 TaggedParserAtomIndex propAtom);
432
433 [[nodiscard]] bool setSourceMapInfo();
434
435 void setFunctionEndFromCurrentToken(FunctionBox* funbox) const;
436 };
437
438 template <class ParseHandler>
439 class MOZ_STACK_CLASS PerHandlerParser : public ParserBase {
440 using Base = ParserBase;
441
442 private:
443 using Node = typename ParseHandler::Node;
444
445 #define DECLARE_TYPE(typeName, longTypeName, asMethodName) \
446 using longTypeName = typename ParseHandler::longTypeName;
447 FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
448 #undef DECLARE_TYPE
449
450 protected:
451 /* State specific to the kind of parse being performed. */
452 ParseHandler handler_;
453
454 // When ParseHandler is FullParseHandler:
455 //
456 // If non-null, this field holds the syntax parser used to attempt lazy
457 // parsing of inner functions. If null, then lazy parsing is disabled.
458 //
459 // When ParseHandler is SyntaxParseHandler:
460 //
461 // If non-null, this field must be a sentinel value signaling that the
462 // syntax parse was aborted. If null, then lazy parsing was aborted due
463 // to encountering unsupported language constructs.
464 //
465 // |internalSyntaxParser_| is really a |Parser<SyntaxParseHandler, Unit>*|
466 // where |Unit| varies per |Parser<ParseHandler, Unit>|. But this
467 // template class doesn't know |Unit|, so we store a |void*| here and make
468 // |GeneralParser<ParseHandler, Unit>::getSyntaxParser| impose the real type.
469 void* internalSyntaxParser_;
470
471 private:
472 // NOTE: The argument ordering here is deliberately different from the
473 // public constructor so that typos calling the public constructor
474 // are less likely to select this overload.
475 PerHandlerParser(JSContext* cx, const JS::ReadOnlyCompileOptions& options,
476 bool foldConstants, CompilationState& compilationState,
477 void* internalSyntaxParser);
478
479 protected:
480 template <typename Unit>
PerHandlerParser(JSContext * cx,const JS::ReadOnlyCompileOptions & options,bool foldConstants,CompilationState & compilationState,GeneralParser<SyntaxParseHandler,Unit> * syntaxParser)481 PerHandlerParser(JSContext* cx, const JS::ReadOnlyCompileOptions& options,
482 bool foldConstants, CompilationState& compilationState,
483 GeneralParser<SyntaxParseHandler, Unit>* syntaxParser)
484 : PerHandlerParser(cx, options, foldConstants, compilationState,
485 static_cast<void*>(syntaxParser)) {}
486
null()487 static typename ParseHandler::NullNode null() { return ParseHandler::null(); }
488
489 NameNodeType stringLiteral();
490
491 const char* nameIsArgumentsOrEval(Node node);
492
493 bool noteDestructuredPositionalFormalParameter(FunctionNodeType funNode,
494 Node destruct);
495
496 bool noteUsedName(
497 TaggedParserAtomIndex name,
498 NameVisibility visibility = NameVisibility::Public,
499 mozilla::Maybe<TokenPos> tokenPosition = mozilla::Nothing()) {
500 // If the we are delazifying, the BaseScript already has all the closed-over
501 // info for bindings and there's no need to track used names.
502 if (handler_.canSkipLazyClosedOverBindings()) {
503 return true;
504 }
505
506 return ParserBase::noteUsedNameInternal(name, visibility, tokenPosition);
507 }
508
509 // Required on Scope exit.
510 bool propagateFreeNamesAndMarkClosedOverBindings(ParseContext::Scope& scope);
511
512 bool checkForUndefinedPrivateFields(EvalSharedContext* evalSc = nullptr);
513
514 bool finishFunctionScopes(bool isStandaloneFunction);
515 LexicalScopeNodeType finishLexicalScope(ParseContext::Scope& scope, Node body,
516 ScopeKind kind = ScopeKind::Lexical);
517 ClassBodyScopeNodeType finishClassBodyScope(ParseContext::Scope& scope,
518 ListNodeType body);
519 bool finishFunction(bool isStandaloneFunction = false);
520
521 inline NameNodeType newName(TaggedParserAtomIndex name);
522 inline NameNodeType newName(TaggedParserAtomIndex name, TokenPos pos);
523
524 inline NameNodeType newPrivateName(TaggedParserAtomIndex name);
525
526 NameNodeType newInternalDotName(TaggedParserAtomIndex name);
527 NameNodeType newThisName();
528 NameNodeType newDotGeneratorName();
529
530 NameNodeType identifierReference(TaggedParserAtomIndex name);
531 NameNodeType privateNameReference(TaggedParserAtomIndex name);
532
533 Node noSubstitutionTaggedTemplate();
534
535 inline bool processExport(Node node);
536 inline bool processExportFrom(BinaryNodeType node);
537 inline bool processImport(BinaryNodeType node);
538
539 // If ParseHandler is SyntaxParseHandler:
540 // Do nothing.
541 // If ParseHandler is FullParseHandler:
542 // Disable syntax parsing of all future inner functions during this
543 // full-parse.
544 inline void disableSyntaxParser();
545
546 // If ParseHandler is SyntaxParseHandler:
547 // Flag the current syntax parse as aborted due to unsupported language
548 // constructs and return false. Aborting the current syntax parse does
549 // not disable attempts to syntax-parse future inner functions.
550 // If ParseHandler is FullParseHandler:
551 // Disable syntax parsing of all future inner functions and return true.
552 inline bool abortIfSyntaxParser();
553
554 // If ParseHandler is SyntaxParseHandler:
555 // Return whether the last syntax parse was aborted due to unsupported
556 // language constructs.
557 // If ParseHandler is FullParseHandler:
558 // Return false.
559 inline bool hadAbortedSyntaxParse();
560
561 // If ParseHandler is SyntaxParseHandler:
562 // Clear whether the last syntax parse was aborted.
563 // If ParseHandler is FullParseHandler:
564 // Do nothing.
565 inline void clearAbortedSyntaxParse();
566
567 public:
newPropertyName(TaggedParserAtomIndex key,const TokenPos & pos)568 NameNodeType newPropertyName(TaggedParserAtomIndex key, const TokenPos& pos) {
569 return handler_.newPropertyName(key, pos);
570 }
571
newPropertyAccess(Node expr,NameNodeType key)572 PropertyAccessType newPropertyAccess(Node expr, NameNodeType key) {
573 return handler_.newPropertyAccess(expr, key);
574 }
575
576 FunctionBox* newFunctionBox(FunctionNodeType funNode,
577 TaggedParserAtomIndex explicitName,
578 FunctionFlags flags, uint32_t toStringStart,
579 Directives directives,
580 GeneratorKind generatorKind,
581 FunctionAsyncKind asyncKind);
582
583 public:
584 // ErrorReportMixin.
585
586 using Base::error;
587 using Base::errorAt;
588 using Base::errorNoOffset;
589 using Base::errorWithNotes;
590 using Base::errorWithNotesAt;
591 using Base::errorWithNotesNoOffset;
592 using Base::strictModeError;
593 using Base::strictModeErrorAt;
594 using Base::strictModeErrorNoOffset;
595 using Base::strictModeErrorWithNotes;
596 using Base::strictModeErrorWithNotesAt;
597 using Base::strictModeErrorWithNotesNoOffset;
598 using Base::warning;
599 using Base::warningAt;
600 using Base::warningNoOffset;
601 };
602
603 #define ABORTED_SYNTAX_PARSE_SENTINEL reinterpret_cast<void*>(0x1)
604
605 template <>
disableSyntaxParser()606 inline void PerHandlerParser<SyntaxParseHandler>::disableSyntaxParser() {}
607
608 template <>
abortIfSyntaxParser()609 inline bool PerHandlerParser<SyntaxParseHandler>::abortIfSyntaxParser() {
610 internalSyntaxParser_ = ABORTED_SYNTAX_PARSE_SENTINEL;
611 return false;
612 }
613
614 template <>
hadAbortedSyntaxParse()615 inline bool PerHandlerParser<SyntaxParseHandler>::hadAbortedSyntaxParse() {
616 return internalSyntaxParser_ == ABORTED_SYNTAX_PARSE_SENTINEL;
617 }
618
619 template <>
clearAbortedSyntaxParse()620 inline void PerHandlerParser<SyntaxParseHandler>::clearAbortedSyntaxParse() {
621 internalSyntaxParser_ = nullptr;
622 }
623
624 #undef ABORTED_SYNTAX_PARSE_SENTINEL
625
626 // Disable syntax parsing of all future inner functions during this
627 // full-parse.
628 template <>
disableSyntaxParser()629 inline void PerHandlerParser<FullParseHandler>::disableSyntaxParser() {
630 internalSyntaxParser_ = nullptr;
631 }
632
633 template <>
abortIfSyntaxParser()634 inline bool PerHandlerParser<FullParseHandler>::abortIfSyntaxParser() {
635 disableSyntaxParser();
636 return true;
637 }
638
639 template <>
hadAbortedSyntaxParse()640 inline bool PerHandlerParser<FullParseHandler>::hadAbortedSyntaxParse() {
641 return false;
642 }
643
644 template <>
clearAbortedSyntaxParse()645 inline void PerHandlerParser<FullParseHandler>::clearAbortedSyntaxParse() {}
646
647 template <class Parser>
648 class ParserAnyCharsAccess {
649 public:
650 using TokenStreamSpecific = typename Parser::TokenStream;
651 using GeneralTokenStreamChars =
652 typename TokenStreamSpecific::GeneralCharsBase;
653
654 static inline TokenStreamAnyChars& anyChars(GeneralTokenStreamChars* ts);
655 static inline const TokenStreamAnyChars& anyChars(
656 const GeneralTokenStreamChars* ts);
657 };
658
659 // Specify a value for an ES6 grammar parametrization. We have no enum for
660 // [Return] because its behavior is almost exactly equivalent to checking
661 // whether we're in a function box -- easier and simpler than passing an extra
662 // parameter everywhere.
663 enum YieldHandling { YieldIsName, YieldIsKeyword };
664 enum InHandling { InAllowed, InProhibited };
665 enum DefaultHandling { NameRequired, AllowDefaultName };
666 enum TripledotHandling { TripledotAllowed, TripledotProhibited };
667
668 // For Ergonomic brand checks.
669 enum PrivateNameHandling { PrivateNameProhibited, PrivateNameAllowed };
670
671 template <class ParseHandler, typename Unit>
672 class Parser;
673
674 template <class ParseHandler, typename Unit>
675 class MOZ_STACK_CLASS GeneralParser : public PerHandlerParser<ParseHandler> {
676 public:
677 using TokenStream =
678 TokenStreamSpecific<Unit, ParserAnyCharsAccess<GeneralParser>>;
679
680 private:
681 using Base = PerHandlerParser<ParseHandler>;
682 using FinalParser = Parser<ParseHandler, Unit>;
683 using Node = typename ParseHandler::Node;
684
685 #define DECLARE_TYPE(typeName, longTypeName, asMethodName) \
686 using longTypeName = typename ParseHandler::longTypeName;
687 FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
688 #undef DECLARE_TYPE
689
690 using typename Base::InvokedPrediction;
691 using SyntaxParser = Parser<SyntaxParseHandler, Unit>;
692
693 protected:
694 using Modifier = TokenStreamShared::Modifier;
695 using Position = typename TokenStream::Position;
696
697 using Base::PredictInvoked;
698 using Base::PredictUninvoked;
699
700 using Base::alloc_;
701 using Base::awaitIsKeyword;
702 using Base::inParametersOfAsyncFunction;
703 using Base::parseGoal;
704 #if DEBUG
705 using Base::checkOptionsCalled_;
706 #endif
707 using Base::checkForUndefinedPrivateFields;
708 using Base::finishClassBodyScope;
709 using Base::finishFunctionScopes;
710 using Base::finishLexicalScope;
711 using Base::foldConstants_;
712 using Base::getFilename;
713 using Base::hasValidSimpleStrictParameterNames;
714 using Base::isUnexpectedEOF_;
715 using Base::nameIsArgumentsOrEval;
716 using Base::newDotGeneratorName;
717 using Base::newFunctionBox;
718 using Base::newName;
719 using Base::null;
720 using Base::options;
721 using Base::pos;
722 using Base::propagateFreeNamesAndMarkClosedOverBindings;
723 using Base::setLocalStrictMode;
724 using Base::stringLiteral;
725 using Base::yieldExpressionsSupported;
726
727 using Base::abortIfSyntaxParser;
728 using Base::clearAbortedSyntaxParse;
729 using Base::disableSyntaxParser;
730 using Base::hadAbortedSyntaxParse;
731
732 public:
733 // Implement ErrorReportMixin.
734
735 [[nodiscard]] bool computeErrorMetadata(
736 ErrorMetadata* err, const ErrorReportMixin::ErrorOffset& offset) override;
737
738 using Base::error;
739 using Base::errorAt;
740 using Base::errorNoOffset;
741 using Base::errorWithNotes;
742 using Base::errorWithNotesAt;
743 using Base::errorWithNotesNoOffset;
744 using Base::strictModeError;
745 using Base::strictModeErrorAt;
746 using Base::strictModeErrorNoOffset;
747 using Base::strictModeErrorWithNotes;
748 using Base::strictModeErrorWithNotesAt;
749 using Base::strictModeErrorWithNotesNoOffset;
750 using Base::warning;
751 using Base::warningAt;
752 using Base::warningNoOffset;
753
754 public:
755 using Base::anyChars;
756 using Base::cx_;
757 using Base::handler_;
758 using Base::noteUsedName;
759 using Base::pc_;
760 using Base::usedNames_;
761
762 private:
763 using Base::checkAndMarkSuperScope;
764 using Base::finishFunction;
765 using Base::identifierReference;
766 using Base::leaveInnerFunction;
767 using Base::newInternalDotName;
768 using Base::newThisName;
769 using Base::nextTokenContinuesLetDeclaration;
770 using Base::noSubstitutionTaggedTemplate;
771 using Base::noteDestructuredPositionalFormalParameter;
772 using Base::prefixAccessorName;
773 using Base::privateNameReference;
774 using Base::processExport;
775 using Base::processExportFrom;
776 using Base::processImport;
777 using Base::setFunctionEndFromCurrentToken;
778
779 private:
780 inline FinalParser* asFinalParser();
781 inline const FinalParser* asFinalParser() const;
782
783 /*
784 * A class for temporarily stashing errors while parsing continues.
785 *
786 * The ability to stash an error is useful for handling situations where we
787 * aren't able to verify that an error has occurred until later in the parse.
788 * For instance | ({x=1}) | is always parsed as an object literal with
789 * a SyntaxError, however, in the case where it is followed by '=>' we rewind
790 * and reparse it as a valid arrow function. Here a PossibleError would be
791 * set to 'pending' when the initial SyntaxError was encountered then
792 * 'resolved' just before rewinding the parser.
793 *
794 * There are currently two kinds of PossibleErrors: Expression and
795 * Destructuring errors. Expression errors are used to mark a possible
796 * syntax error when a grammar production is used in an expression context.
797 * For example in |{x = 1}|, we mark the CoverInitializedName |x = 1| as a
798 * possible expression error, because CoverInitializedName productions
799 * are disallowed when an actual ObjectLiteral is expected.
800 * Destructuring errors are used to record possible syntax errors in
801 * destructuring contexts. For example in |[...rest, ] = []|, we initially
802 * mark the trailing comma after the spread expression as a possible
803 * destructuring error, because the ArrayAssignmentPattern grammar
804 * production doesn't allow a trailing comma after the rest element.
805 *
806 * When using PossibleError one should set a pending error at the location
807 * where an error occurs. From that point, the error may be resolved
808 * (invalidated) or left until the PossibleError is checked.
809 *
810 * Ex:
811 * PossibleError possibleError(*this);
812 * possibleError.setPendingExpressionErrorAt(pos, JSMSG_BAD_PROP_ID);
813 * // A JSMSG_BAD_PROP_ID ParseError is reported, returns false.
814 * if (!possibleError.checkForExpressionError()) {
815 * return false; // we reach this point with a pending exception
816 * }
817 *
818 * PossibleError possibleError(*this);
819 * possibleError.setPendingExpressionErrorAt(pos, JSMSG_BAD_PROP_ID);
820 * // Returns true, no error is reported.
821 * if (!possibleError.checkForDestructuringError()) {
822 * return false; // not reached, no pending exception
823 * }
824 *
825 * PossibleError possibleError(*this);
826 * // Returns true, no error is reported.
827 * if (!possibleError.checkForExpressionError()) {
828 * return false; // not reached, no pending exception
829 * }
830 */
831 class MOZ_STACK_CLASS PossibleError {
832 private:
833 enum class ErrorKind { Expression, Destructuring, DestructuringWarning };
834
835 enum class ErrorState { None, Pending };
836
837 struct Error {
838 ErrorState state_ = ErrorState::None;
839
840 // Error reporting fields.
841 uint32_t offset_;
842 unsigned errorNumber_;
843 };
844
845 GeneralParser<ParseHandler, Unit>& parser_;
846 Error exprError_;
847 Error destructuringError_;
848 Error destructuringWarning_;
849
850 // Returns the error report.
851 Error& error(ErrorKind kind);
852
853 // Return true if an error is pending without reporting.
854 bool hasError(ErrorKind kind);
855
856 // Resolve any pending error.
857 void setResolved(ErrorKind kind);
858
859 // Set a pending error. Only a single error may be set per instance and
860 // error kind.
861 void setPending(ErrorKind kind, const TokenPos& pos, unsigned errorNumber);
862
863 // If there is a pending error, report it and return false, otherwise
864 // return true.
865 [[nodiscard]] bool checkForError(ErrorKind kind);
866
867 // Transfer an existing error to another instance.
868 void transferErrorTo(ErrorKind kind, PossibleError* other);
869
870 public:
871 explicit PossibleError(GeneralParser<ParseHandler, Unit>& parser);
872
873 // Return true if a pending destructuring error is present.
874 bool hasPendingDestructuringError();
875
876 // Set a pending destructuring error. Only a single error may be set
877 // per instance, i.e. subsequent calls to this method are ignored and
878 // won't overwrite the existing pending error.
879 void setPendingDestructuringErrorAt(const TokenPos& pos,
880 unsigned errorNumber);
881
882 // Set a pending destructuring warning. Only a single warning may be
883 // set per instance, i.e. subsequent calls to this method are ignored
884 // and won't overwrite the existing pending warning.
885 void setPendingDestructuringWarningAt(const TokenPos& pos,
886 unsigned errorNumber);
887
888 // Set a pending expression error. Only a single error may be set per
889 // instance, i.e. subsequent calls to this method are ignored and won't
890 // overwrite the existing pending error.
891 void setPendingExpressionErrorAt(const TokenPos& pos, unsigned errorNumber);
892
893 // If there is a pending destructuring error or warning, report it and
894 // return false, otherwise return true. Clears any pending expression
895 // error.
896 [[nodiscard]] bool checkForDestructuringErrorOrWarning();
897
898 // If there is a pending expression error, report it and return false,
899 // otherwise return true. Clears any pending destructuring error or
900 // warning.
901 [[nodiscard]] bool checkForExpressionError();
902
903 // Pass pending errors between possible error instances. This is useful
904 // for extending the lifetime of a pending error beyond the scope of
905 // the PossibleError where it was initially set (keeping in mind that
906 // PossibleError is a MOZ_STACK_CLASS).
907 void transferErrorsTo(PossibleError* other);
908 };
909
910 protected:
getSyntaxParser()911 SyntaxParser* getSyntaxParser() const {
912 return reinterpret_cast<SyntaxParser*>(Base::internalSyntaxParser_);
913 }
914
915 public:
916 TokenStream tokenStream;
917
918 public:
919 GeneralParser(JSContext* cx, const JS::ReadOnlyCompileOptions& options,
920 const Unit* units, size_t length, bool foldConstants,
921 CompilationState& compilationState, SyntaxParser* syntaxParser);
922
923 inline void setAwaitHandling(AwaitHandling awaitHandling);
924 inline void setInParametersOfAsyncFunction(bool inParameters);
925
926 /*
927 * Parse a top-level JS script.
928 */
929 ListNodeType parse();
930
931 private:
932 /*
933 * Gets the next token and checks if it matches to the given `condition`.
934 * If it matches, returns true.
935 * If it doesn't match, calls `errorReport` to report the error, and
936 * returns false.
937 * If other error happens, it returns false but `errorReport` may not be
938 * called and other error will be thrown in that case.
939 *
940 * In any case, the already gotten token is not ungotten.
941 *
942 * The signature of `condition` is [...](TokenKind actual) -> bool, and
943 * the signature of `errorReport` is [...](TokenKind actual).
944 */
945 template <typename ConditionT, typename ErrorReportT>
946 [[nodiscard]] bool mustMatchTokenInternal(ConditionT condition,
947 ErrorReportT errorReport);
948
949 public:
950 /*
951 * The following mustMatchToken variants follow the behavior and parameter
952 * types of mustMatchTokenInternal above.
953 *
954 * If modifier is omitted, `SlashIsDiv` is used.
955 * If TokenKind is passed instead of `condition`, it checks if the next
956 * token is the passed token.
957 * If error number is passed instead of `errorReport`, it reports an
958 * error with the passed errorNumber.
959 */
mustMatchToken(TokenKind expected,JSErrNum errorNumber)960 [[nodiscard]] bool mustMatchToken(TokenKind expected, JSErrNum errorNumber) {
961 return mustMatchTokenInternal(
962 [expected](TokenKind actual) { return actual == expected; },
963 [this, errorNumber](TokenKind) { this->error(errorNumber); });
964 }
965
966 template <typename ConditionT>
mustMatchToken(ConditionT condition,JSErrNum errorNumber)967 [[nodiscard]] bool mustMatchToken(ConditionT condition,
968 JSErrNum errorNumber) {
969 return mustMatchTokenInternal(condition, [this, errorNumber](TokenKind) {
970 this->error(errorNumber);
971 });
972 }
973
974 template <typename ErrorReportT>
mustMatchToken(TokenKind expected,ErrorReportT errorReport)975 [[nodiscard]] bool mustMatchToken(TokenKind expected,
976 ErrorReportT errorReport) {
977 return mustMatchTokenInternal(
978 [expected](TokenKind actual) { return actual == expected; },
979 errorReport);
980 }
981
982 private:
983 NameNodeType noSubstitutionUntaggedTemplate();
984 ListNodeType templateLiteral(YieldHandling yieldHandling);
985 bool taggedTemplate(YieldHandling yieldHandling, ListNodeType tagArgsList,
986 TokenKind tt);
987 bool appendToCallSiteObj(CallSiteNodeType callSiteObj);
988 bool addExprAndGetNextTemplStrToken(YieldHandling yieldHandling,
989 ListNodeType nodeList, TokenKind* ttp);
990
991 inline bool trySyntaxParseInnerFunction(
992 FunctionNodeType* funNode, TaggedParserAtomIndex explicitName,
993 FunctionFlags flags, uint32_t toStringStart, InHandling inHandling,
994 YieldHandling yieldHandling, FunctionSyntaxKind kind,
995 GeneratorKind generatorKind, FunctionAsyncKind asyncKind, bool tryAnnexB,
996 Directives inheritedDirectives, Directives* newDirectives);
997
998 inline bool skipLazyInnerFunction(FunctionNodeType funNode,
999 uint32_t toStringStart, bool tryAnnexB);
1000
1001 void setFunctionStartAtPosition(FunctionBox* funbox, TokenPos pos) const;
1002 void setFunctionStartAtCurrentToken(FunctionBox* funbox) const;
1003
1004 public:
1005 /* Public entry points for parsing. */
1006 Node statementListItem(YieldHandling yieldHandling,
1007 bool canHaveDirectives = false);
1008
1009 // Parse an inner function given an enclosing ParseContext and a
1010 // FunctionBox for the inner function.
1011 [[nodiscard]] FunctionNodeType innerFunctionForFunctionBox(
1012 FunctionNodeType funNode, ParseContext* outerpc, FunctionBox* funbox,
1013 InHandling inHandling, YieldHandling yieldHandling,
1014 FunctionSyntaxKind kind, Directives* newDirectives);
1015
1016 // Parse a function's formal parameters and its body assuming its function
1017 // ParseContext is already on the stack.
1018 bool functionFormalParametersAndBody(
1019 InHandling inHandling, YieldHandling yieldHandling,
1020 FunctionNodeType* funNode, FunctionSyntaxKind kind,
1021 const mozilla::Maybe<uint32_t>& parameterListEnd = mozilla::Nothing(),
1022 bool isStandaloneFunction = false);
1023
1024 private:
1025 /*
1026 * JS parsers, from lowest to highest precedence.
1027 *
1028 * Each parser must be called during the dynamic scope of a ParseContext
1029 * object, pointed to by this->pc_.
1030 *
1031 * Each returns a parse node tree or null on error.
1032 */
1033 FunctionNodeType functionStmt(
1034 uint32_t toStringStart, YieldHandling yieldHandling,
1035 DefaultHandling defaultHandling,
1036 FunctionAsyncKind asyncKind = FunctionAsyncKind::SyncFunction);
1037 FunctionNodeType functionExpr(uint32_t toStringStart,
1038 InvokedPrediction invoked,
1039 FunctionAsyncKind asyncKind);
1040
1041 Node statement(YieldHandling yieldHandling);
1042 bool maybeParseDirective(ListNodeType list, Node pn, bool* cont);
1043
1044 LexicalScopeNodeType blockStatement(
1045 YieldHandling yieldHandling,
1046 unsigned errorNumber = JSMSG_CURLY_IN_COMPOUND);
1047 BinaryNodeType doWhileStatement(YieldHandling yieldHandling);
1048 BinaryNodeType whileStatement(YieldHandling yieldHandling);
1049
1050 Node forStatement(YieldHandling yieldHandling);
1051 bool forHeadStart(YieldHandling yieldHandling, IteratorKind iterKind,
1052 ParseNodeKind* forHeadKind, Node* forInitialPart,
1053 mozilla::Maybe<ParseContext::Scope>& forLetImpliedScope,
1054 Node* forInOrOfExpression);
1055 Node expressionAfterForInOrOf(ParseNodeKind forHeadKind,
1056 YieldHandling yieldHandling);
1057
1058 SwitchStatementType switchStatement(YieldHandling yieldHandling);
1059 ContinueStatementType continueStatement(YieldHandling yieldHandling);
1060 BreakStatementType breakStatement(YieldHandling yieldHandling);
1061 UnaryNodeType returnStatement(YieldHandling yieldHandling);
1062 BinaryNodeType withStatement(YieldHandling yieldHandling);
1063 UnaryNodeType throwStatement(YieldHandling yieldHandling);
1064 TernaryNodeType tryStatement(YieldHandling yieldHandling);
1065 LexicalScopeNodeType catchBlockStatement(
1066 YieldHandling yieldHandling, ParseContext::Scope& catchParamScope);
1067 DebuggerStatementType debuggerStatement();
1068
1069 ListNodeType variableStatement(YieldHandling yieldHandling);
1070
1071 LabeledStatementType labeledStatement(YieldHandling yieldHandling);
1072 Node labeledItem(YieldHandling yieldHandling);
1073
1074 TernaryNodeType ifStatement(YieldHandling yieldHandling);
1075 Node consequentOrAlternative(YieldHandling yieldHandling);
1076
1077 ListNodeType lexicalDeclaration(YieldHandling yieldHandling,
1078 DeclarationKind kind);
1079
1080 NameNodeType moduleExportName();
1081
1082 BinaryNodeType importDeclaration();
1083 Node importDeclarationOrImportExpr(YieldHandling yieldHandling);
1084 bool namedImports(ListNodeType importSpecSet);
1085 bool namespaceImport(ListNodeType importSpecSet);
1086
importedBinding()1087 TaggedParserAtomIndex importedBinding() {
1088 return bindingIdentifier(YieldIsName);
1089 }
1090
1091 BinaryNodeType exportFrom(uint32_t begin, Node specList);
1092 BinaryNodeType exportBatch(uint32_t begin);
1093 inline bool checkLocalExportNames(ListNodeType node);
1094 Node exportClause(uint32_t begin);
1095 UnaryNodeType exportFunctionDeclaration(
1096 uint32_t begin, uint32_t toStringStart,
1097 FunctionAsyncKind asyncKind = FunctionAsyncKind::SyncFunction);
1098 UnaryNodeType exportVariableStatement(uint32_t begin);
1099 UnaryNodeType exportClassDeclaration(uint32_t begin);
1100 UnaryNodeType exportLexicalDeclaration(uint32_t begin, DeclarationKind kind);
1101 BinaryNodeType exportDefaultFunctionDeclaration(
1102 uint32_t begin, uint32_t toStringStart,
1103 FunctionAsyncKind asyncKind = FunctionAsyncKind::SyncFunction);
1104 BinaryNodeType exportDefaultClassDeclaration(uint32_t begin);
1105 BinaryNodeType exportDefaultAssignExpr(uint32_t begin);
1106 BinaryNodeType exportDefault(uint32_t begin);
1107 Node exportDeclaration();
1108
1109 UnaryNodeType expressionStatement(
1110 YieldHandling yieldHandling,
1111 InvokedPrediction invoked = PredictUninvoked);
1112
1113 // Declaration parsing. The main entrypoint is Parser::declarationList,
1114 // with sub-functionality split out into the remaining methods.
1115
1116 // |blockScope| may be non-null only when |kind| corresponds to a lexical
1117 // declaration (that is, PNK_LET or PNK_CONST).
1118 //
1119 // The for* parameters, for normal declarations, should be null/ignored.
1120 // They should be non-null only when Parser::forHeadStart parses a
1121 // declaration at the start of a for-loop head.
1122 //
1123 // In this case, on success |*forHeadKind| is PNK_FORHEAD, PNK_FORIN, or
1124 // PNK_FOROF, corresponding to the three for-loop kinds. The precise value
1125 // indicates what was parsed.
1126 //
1127 // If parsing recognized a for(;;) loop, the next token is the ';' within
1128 // the loop-head that separates the init/test parts.
1129 //
1130 // Otherwise, for for-in/of loops, the next token is the ')' ending the
1131 // loop-head. Additionally, the expression that the loop iterates over was
1132 // parsed into |*forInOrOfExpression|.
1133 ListNodeType declarationList(YieldHandling yieldHandling, ParseNodeKind kind,
1134 ParseNodeKind* forHeadKind = nullptr,
1135 Node* forInOrOfExpression = nullptr);
1136
1137 // The items in a declaration list are either patterns or names, with or
1138 // without initializers. These two methods parse a single pattern/name and
1139 // any associated initializer -- and if parsing an |initialDeclaration|
1140 // will, if parsing in a for-loop head (as specified by |forHeadKind| being
1141 // non-null), consume additional tokens up to the closing ')' in a
1142 // for-in/of loop head, returning the iterated expression in
1143 // |*forInOrOfExpression|. (An "initial declaration" is the first
1144 // declaration in a declaration list: |a| but not |b| in |var a, b|, |{c}|
1145 // but not |d| in |let {c} = 3, d|.)
1146 Node declarationPattern(DeclarationKind declKind, TokenKind tt,
1147 bool initialDeclaration, YieldHandling yieldHandling,
1148 ParseNodeKind* forHeadKind,
1149 Node* forInOrOfExpression);
1150 Node declarationName(DeclarationKind declKind, TokenKind tt,
1151 bool initialDeclaration, YieldHandling yieldHandling,
1152 ParseNodeKind* forHeadKind, Node* forInOrOfExpression);
1153
1154 // Having parsed a name (not found in a destructuring pattern) declared by
1155 // a declaration, with the current token being the '=' separating the name
1156 // from its initializer, parse and bind that initializer -- and possibly
1157 // consume trailing in/of and subsequent expression, if so directed by
1158 // |forHeadKind|.
1159 AssignmentNodeType initializerInNameDeclaration(NameNodeType binding,
1160 DeclarationKind declKind,
1161 bool initialDeclaration,
1162 YieldHandling yieldHandling,
1163 ParseNodeKind* forHeadKind,
1164 Node* forInOrOfExpression);
1165
1166 Node expr(InHandling inHandling, YieldHandling yieldHandling,
1167 TripledotHandling tripledotHandling,
1168 PossibleError* possibleError = nullptr,
1169 InvokedPrediction invoked = PredictUninvoked);
1170 Node assignExpr(InHandling inHandling, YieldHandling yieldHandling,
1171 TripledotHandling tripledotHandling,
1172 PossibleError* possibleError = nullptr,
1173 InvokedPrediction invoked = PredictUninvoked);
1174 Node assignExprWithoutYieldOrAwait(YieldHandling yieldHandling);
1175 UnaryNodeType yieldExpression(InHandling inHandling);
1176 Node condExpr(InHandling inHandling, YieldHandling yieldHandling,
1177 TripledotHandling tripledotHandling,
1178 PossibleError* possibleError, InvokedPrediction invoked);
1179 Node orExpr(InHandling inHandling, YieldHandling yieldHandling,
1180 TripledotHandling tripledotHandling, PossibleError* possibleError,
1181 InvokedPrediction invoked);
1182 Node unaryExpr(YieldHandling yieldHandling,
1183 TripledotHandling tripledotHandling,
1184 PossibleError* possibleError = nullptr,
1185 InvokedPrediction invoked = PredictUninvoked,
1186 PrivateNameHandling privateNameHandling =
1187 PrivateNameHandling::PrivateNameProhibited);
1188 Node optionalExpr(YieldHandling yieldHandling,
1189 TripledotHandling tripledotHandling, TokenKind tt,
1190 PossibleError* possibleError = nullptr,
1191 InvokedPrediction invoked = PredictUninvoked);
1192 Node memberExpr(YieldHandling yieldHandling,
1193 TripledotHandling tripledotHandling, TokenKind tt,
1194 bool allowCallSyntax, PossibleError* possibleError,
1195 InvokedPrediction invoked);
1196 Node primaryExpr(YieldHandling yieldHandling,
1197 TripledotHandling tripledotHandling, TokenKind tt,
1198 PossibleError* possibleError, InvokedPrediction invoked);
1199 Node exprInParens(InHandling inHandling, YieldHandling yieldHandling,
1200 TripledotHandling tripledotHandling,
1201 PossibleError* possibleError = nullptr);
1202
1203 bool tryNewTarget(BinaryNodeType* newTarget);
1204
1205 BinaryNodeType importExpr(YieldHandling yieldHandling, bool allowCallSyntax);
1206
1207 FunctionNodeType methodDefinition(uint32_t toStringStart,
1208 PropertyType propType,
1209 TaggedParserAtomIndex funName);
1210
1211 /*
1212 * Additional JS parsers.
1213 */
1214 bool functionArguments(YieldHandling yieldHandling, FunctionSyntaxKind kind,
1215 FunctionNodeType funNode);
1216
1217 FunctionNodeType functionDefinition(
1218 FunctionNodeType funNode, uint32_t toStringStart, InHandling inHandling,
1219 YieldHandling yieldHandling, TaggedParserAtomIndex name,
1220 FunctionSyntaxKind kind, GeneratorKind generatorKind,
1221 FunctionAsyncKind asyncKind, bool tryAnnexB = false);
1222
1223 // Parse a function body. Pass StatementListBody if the body is a list of
1224 // statements; pass ExpressionBody if the body is a single expression.
1225 //
1226 // Don't include opening LeftCurly token when invoking.
1227 enum FunctionBodyType { StatementListBody, ExpressionBody };
1228 LexicalScopeNodeType functionBody(InHandling inHandling,
1229 YieldHandling yieldHandling,
1230 FunctionSyntaxKind kind,
1231 FunctionBodyType type);
1232
1233 UnaryNodeType unaryOpExpr(YieldHandling yieldHandling, ParseNodeKind kind,
1234 uint32_t begin);
1235
1236 Node condition(InHandling inHandling, YieldHandling yieldHandling);
1237
1238 ListNodeType argumentList(YieldHandling yieldHandling, bool* isSpread,
1239 PossibleError* possibleError = nullptr);
1240 Node destructuringDeclaration(DeclarationKind kind,
1241 YieldHandling yieldHandling, TokenKind tt);
1242 Node destructuringDeclarationWithoutYieldOrAwait(DeclarationKind kind,
1243 YieldHandling yieldHandling,
1244 TokenKind tt);
1245
1246 inline bool checkExportedName(TaggedParserAtomIndex exportName);
1247 inline bool checkExportedNamesForArrayBinding(ListNodeType array);
1248 inline bool checkExportedNamesForObjectBinding(ListNodeType obj);
1249 inline bool checkExportedNamesForDeclaration(Node node);
1250 inline bool checkExportedNamesForDeclarationList(ListNodeType node);
1251 inline bool checkExportedNameForFunction(FunctionNodeType funNode);
1252 inline bool checkExportedNameForClass(ClassNodeType classNode);
1253 inline bool checkExportedNameForClause(NameNodeType nameNode);
1254
1255 enum ClassContext { ClassStatement, ClassExpression };
1256 ClassNodeType classDefinition(YieldHandling yieldHandling,
1257 ClassContext classContext,
1258 DefaultHandling defaultHandling);
1259 struct ClassInitializedMembers {
1260 // The number of instance class fields.
1261 size_t instanceFields = 0;
1262
1263 // The number of instance class fields with computed property names.
1264 size_t instanceFieldKeys = 0;
1265
1266 // The number of static class fields.
1267 size_t staticFields = 0;
1268
1269 // The number of static blocks
1270 size_t staticBlocks = 0;
1271
1272 // The number of static class fields with computed property names.
1273 size_t staticFieldKeys = 0;
1274
1275 // The number of instance class private methods.
1276 size_t privateMethods = 0;
1277
1278 // The number of instance class private accessors.
1279 size_t privateAccessors = 0;
1280
hasPrivateBrandClassInitializedMembers1281 bool hasPrivateBrand() const {
1282 return privateMethods > 0 || privateAccessors > 0;
1283 }
1284 };
1285 [[nodiscard]] bool classMember(
1286 YieldHandling yieldHandling,
1287 const ParseContext::ClassStatement& classStmt,
1288 TaggedParserAtomIndex className, uint32_t classStartOffset,
1289 HasHeritage hasHeritage, ClassInitializedMembers& classInitializedMembers,
1290 ListNodeType& classMembers, bool* done);
1291 [[nodiscard]] bool finishClassConstructor(
1292 const ParseContext::ClassStatement& classStmt,
1293 TaggedParserAtomIndex className, HasHeritage hasHeritage,
1294 uint32_t classStartOffset, uint32_t classEndOffset,
1295 const ClassInitializedMembers& classInitializedMembers,
1296 ListNodeType& classMembers);
1297
1298 FunctionNodeType privateMethodInitializer(
1299 TokenPos propNamePos, TaggedParserAtomIndex propAtom,
1300 TaggedParserAtomIndex storedMethodAtom);
1301 FunctionNodeType fieldInitializerOpt(
1302 TokenPos propNamePos, Node name, TaggedParserAtomIndex atom,
1303 ClassInitializedMembers& classInitializedMembers, bool isStatic,
1304 HasHeritage hasHeritage);
1305
1306 FunctionNodeType staticClassBlock(
1307 ClassInitializedMembers& classInitializedMembers);
1308
1309 FunctionNodeType synthesizeConstructor(TaggedParserAtomIndex className,
1310 TokenPos synthesizedBodyPos,
1311 HasHeritage hasHeritage);
1312
1313 protected:
1314 FunctionNodeType synthesizeConstructorBody(TokenPos synthesizedBodyPos,
1315 HasHeritage hasHeritage,
1316 FunctionNodeType funNode,
1317 FunctionBox* funbox);
1318
1319 private:
1320 bool checkBindingIdentifier(TaggedParserAtomIndex ident, uint32_t offset,
1321 YieldHandling yieldHandling,
1322 TokenKind hint = TokenKind::Limit);
1323
1324 TaggedParserAtomIndex labelOrIdentifierReference(YieldHandling yieldHandling);
1325
labelIdentifier(YieldHandling yieldHandling)1326 TaggedParserAtomIndex labelIdentifier(YieldHandling yieldHandling) {
1327 return labelOrIdentifierReference(yieldHandling);
1328 }
1329
identifierReference(YieldHandling yieldHandling)1330 TaggedParserAtomIndex identifierReference(YieldHandling yieldHandling) {
1331 return labelOrIdentifierReference(yieldHandling);
1332 }
1333
1334 bool matchLabel(YieldHandling yieldHandling, TaggedParserAtomIndex* labelOut);
1335
1336 // Indicate if the next token (tokenized with SlashIsRegExp) is |in| or |of|.
1337 // If so, consume it.
1338 bool matchInOrOf(bool* isForInp, bool* isForOfp);
1339
1340 private:
1341 bool checkIncDecOperand(Node operand, uint32_t operandOffset);
1342 bool checkStrictAssignment(Node lhs);
1343
1344 void reportMissingClosing(unsigned errorNumber, unsigned noteNumber,
1345 uint32_t openedPos);
1346
1347 void reportRedeclaration(TaggedParserAtomIndex name, DeclarationKind prevKind,
1348 TokenPos pos, uint32_t prevPos);
1349 bool notePositionalFormalParameter(FunctionNodeType funNode,
1350 TaggedParserAtomIndex name,
1351 uint32_t beginPos,
1352 bool disallowDuplicateParams,
1353 bool* duplicatedParam);
1354
1355 enum PropertyNameContext {
1356 PropertyNameInLiteral,
1357 PropertyNameInPattern,
1358 PropertyNameInClass
1359 };
1360 Node propertyName(YieldHandling yieldHandling,
1361 PropertyNameContext propertyNameContext,
1362 const mozilla::Maybe<DeclarationKind>& maybeDecl,
1363 ListNodeType propList, TaggedParserAtomIndex* propAtomOut);
1364 Node propertyOrMethodName(YieldHandling yieldHandling,
1365 PropertyNameContext propertyNameContext,
1366 const mozilla::Maybe<DeclarationKind>& maybeDecl,
1367 ListNodeType propList, PropertyType* propType,
1368 TaggedParserAtomIndex* propAtomOut);
1369 UnaryNodeType computedPropertyName(
1370 YieldHandling yieldHandling,
1371 const mozilla::Maybe<DeclarationKind>& maybeDecl,
1372 PropertyNameContext propertyNameContext, ListNodeType literal);
1373 ListNodeType arrayInitializer(YieldHandling yieldHandling,
1374 PossibleError* possibleError);
1375 inline RegExpLiteralType newRegExp();
1376
1377 ListNodeType objectLiteral(YieldHandling yieldHandling,
1378 PossibleError* possibleError);
1379
1380 BinaryNodeType bindingInitializer(Node lhs, DeclarationKind kind,
1381 YieldHandling yieldHandling);
1382 NameNodeType bindingIdentifier(DeclarationKind kind,
1383 YieldHandling yieldHandling);
1384 Node bindingIdentifierOrPattern(DeclarationKind kind,
1385 YieldHandling yieldHandling, TokenKind tt);
1386 ListNodeType objectBindingPattern(DeclarationKind kind,
1387 YieldHandling yieldHandling);
1388 ListNodeType arrayBindingPattern(DeclarationKind kind,
1389 YieldHandling yieldHandling);
1390
1391 enum class TargetBehavior {
1392 PermitAssignmentPattern,
1393 ForbidAssignmentPattern
1394 };
1395 bool checkDestructuringAssignmentTarget(
1396 Node expr, TokenPos exprPos, PossibleError* exprPossibleError,
1397 PossibleError* possibleError,
1398 TargetBehavior behavior = TargetBehavior::PermitAssignmentPattern);
1399 void checkDestructuringAssignmentName(NameNodeType name, TokenPos namePos,
1400 PossibleError* possibleError);
1401 bool checkDestructuringAssignmentElement(Node expr, TokenPos exprPos,
1402 PossibleError* exprPossibleError,
1403 PossibleError* possibleError);
1404
newNumber(const Token & tok)1405 NumericLiteralType newNumber(const Token& tok) {
1406 return handler_.newNumber(tok.number(), tok.decimalPoint(), tok.pos);
1407 }
1408
1409 inline BigIntLiteralType newBigInt();
1410
1411 enum class OptionalKind {
1412 NonOptional = 0,
1413 Optional,
1414 };
1415 Node memberPropertyAccess(
1416 Node lhs, OptionalKind optionalKind = OptionalKind::NonOptional);
1417 Node memberPrivateAccess(
1418 Node lhs, OptionalKind optionalKind = OptionalKind::NonOptional);
1419 Node memberElemAccess(Node lhs, YieldHandling yieldHandling,
1420 OptionalKind optionalKind = OptionalKind::NonOptional);
1421 Node memberSuperCall(Node lhs, YieldHandling yieldHandling);
1422 Node memberCall(TokenKind tt, Node lhs, YieldHandling yieldHandling,
1423 PossibleError* possibleError,
1424 OptionalKind optionalKind = OptionalKind::NonOptional);
1425
1426 protected:
1427 // Match the current token against the BindingIdentifier production with
1428 // the given Yield parameter. If there is no match, report a syntax
1429 // error.
1430 TaggedParserAtomIndex bindingIdentifier(YieldHandling yieldHandling);
1431
1432 bool checkLabelOrIdentifierReference(TaggedParserAtomIndex ident,
1433 uint32_t offset,
1434 YieldHandling yieldHandling,
1435 TokenKind hint = TokenKind::Limit);
1436
1437 ListNodeType statementList(YieldHandling yieldHandling);
1438
1439 [[nodiscard]] FunctionNodeType innerFunction(
1440 FunctionNodeType funNode, ParseContext* outerpc,
1441 TaggedParserAtomIndex explicitName, FunctionFlags flags,
1442 uint32_t toStringStart, InHandling inHandling,
1443 YieldHandling yieldHandling, FunctionSyntaxKind kind,
1444 GeneratorKind generatorKind, FunctionAsyncKind asyncKind, bool tryAnnexB,
1445 Directives inheritedDirectives, Directives* newDirectives);
1446
1447 // Implements Automatic Semicolon Insertion.
1448 //
1449 // Use this to match `;` in contexts where ASI is allowed. Call this after
1450 // ruling out all other possibilities except `;`, by peeking ahead if
1451 // necessary.
1452 //
1453 // Unlike most optional Modifiers, this method's `modifier` argument defaults
1454 // to SlashIsRegExp, since that's by far the most common case: usually an
1455 // optional semicolon is at the end of a statement or declaration, and the
1456 // next token could be a RegExp literal beginning a new ExpressionStatement.
1457 bool matchOrInsertSemicolon(Modifier modifier = TokenStream::SlashIsRegExp);
1458
1459 bool noteDeclaredName(TaggedParserAtomIndex name, DeclarationKind kind,
1460 TokenPos pos, ClosedOver isClosedOver = ClosedOver::No);
1461
1462 bool noteDeclaredPrivateName(Node nameNode, TaggedParserAtomIndex name,
1463 PropertyType propType, FieldPlacement placement,
1464 TokenPos pos);
1465
1466 private:
1467 inline bool asmJS(ListNodeType list);
1468 };
1469
1470 template <typename Unit>
1471 class MOZ_STACK_CLASS Parser<SyntaxParseHandler, Unit> final
1472 : public GeneralParser<SyntaxParseHandler, Unit> {
1473 using Base = GeneralParser<SyntaxParseHandler, Unit>;
1474 using Node = SyntaxParseHandler::Node;
1475
1476 #define DECLARE_TYPE(typeName, longTypeName, asMethodName) \
1477 using longTypeName = SyntaxParseHandler::longTypeName;
1478 FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
1479 #undef DECLARE_TYPE
1480
1481 using SyntaxParser = Parser<SyntaxParseHandler, Unit>;
1482
1483 // Numerous Base::* functions have bodies like
1484 //
1485 // return asFinalParser()->func(...);
1486 //
1487 // and must be able to call functions here. Add a friendship relationship
1488 // so functions here can be hidden when appropriate.
1489 friend class GeneralParser<SyntaxParseHandler, Unit>;
1490
1491 public:
1492 using Base::Base;
1493
1494 // Inherited types, listed here to have non-dependent names.
1495 using typename Base::Modifier;
1496 using typename Base::Position;
1497 using typename Base::TokenStream;
1498
1499 // Inherited functions, listed here to have non-dependent names.
1500
1501 public:
1502 using Base::anyChars;
1503 using Base::clearAbortedSyntaxParse;
1504 using Base::cx_;
1505 using Base::hadAbortedSyntaxParse;
1506 using Base::innerFunctionForFunctionBox;
1507 using Base::tokenStream;
1508
1509 public:
1510 // ErrorReportMixin.
1511
1512 using Base::error;
1513 using Base::errorAt;
1514 using Base::errorNoOffset;
1515 using Base::errorWithNotes;
1516 using Base::errorWithNotesAt;
1517 using Base::errorWithNotesNoOffset;
1518 using Base::strictModeError;
1519 using Base::strictModeErrorAt;
1520 using Base::strictModeErrorNoOffset;
1521 using Base::strictModeErrorWithNotes;
1522 using Base::strictModeErrorWithNotesAt;
1523 using Base::strictModeErrorWithNotesNoOffset;
1524 using Base::warning;
1525 using Base::warningAt;
1526 using Base::warningNoOffset;
1527
1528 private:
1529 using Base::alloc_;
1530 #if DEBUG
1531 using Base::checkOptionsCalled_;
1532 #endif
1533 using Base::checkForUndefinedPrivateFields;
1534 using Base::finishFunctionScopes;
1535 using Base::functionFormalParametersAndBody;
1536 using Base::handler_;
1537 using Base::innerFunction;
1538 using Base::matchOrInsertSemicolon;
1539 using Base::mustMatchToken;
1540 using Base::newFunctionBox;
1541 using Base::newLexicalScopeData;
1542 using Base::newModuleScopeData;
1543 using Base::newName;
1544 using Base::noteDeclaredName;
1545 using Base::null;
1546 using Base::options;
1547 using Base::pc_;
1548 using Base::pos;
1549 using Base::propagateFreeNamesAndMarkClosedOverBindings;
1550 using Base::ss;
1551 using Base::statementList;
1552 using Base::stringLiteral;
1553 using Base::usedNames_;
1554
1555 private:
1556 using Base::abortIfSyntaxParser;
1557 using Base::disableSyntaxParser;
1558
1559 public:
1560 // Functions with multiple overloads of different visibility. We can't
1561 // |using| the whole thing into existence because of the visibility
1562 // distinction, so we instead must manually delegate the required overload.
1563
bindingIdentifier(YieldHandling yieldHandling)1564 TaggedParserAtomIndex bindingIdentifier(YieldHandling yieldHandling) {
1565 return Base::bindingIdentifier(yieldHandling);
1566 }
1567
1568 // Functions present in both Parser<ParseHandler, Unit> specializations.
1569
1570 inline void setAwaitHandling(AwaitHandling awaitHandling);
1571 inline void setInParametersOfAsyncFunction(bool inParameters);
1572
1573 RegExpLiteralType newRegExp();
1574 BigIntLiteralType newBigInt();
1575
1576 // Parse a module.
1577 ModuleNodeType moduleBody(ModuleSharedContext* modulesc);
1578
1579 inline bool checkLocalExportNames(ListNodeType node);
1580 inline bool checkExportedName(TaggedParserAtomIndex exportName);
1581 inline bool checkExportedNamesForArrayBinding(ListNodeType array);
1582 inline bool checkExportedNamesForObjectBinding(ListNodeType obj);
1583 inline bool checkExportedNamesForDeclaration(Node node);
1584 inline bool checkExportedNamesForDeclarationList(ListNodeType node);
1585 inline bool checkExportedNameForFunction(FunctionNodeType funNode);
1586 inline bool checkExportedNameForClass(ClassNodeType classNode);
1587 inline bool checkExportedNameForClause(NameNodeType nameNode);
1588
1589 bool trySyntaxParseInnerFunction(
1590 FunctionNodeType* funNode, TaggedParserAtomIndex explicitName,
1591 FunctionFlags flags, uint32_t toStringStart, InHandling inHandling,
1592 YieldHandling yieldHandling, FunctionSyntaxKind kind,
1593 GeneratorKind generatorKind, FunctionAsyncKind asyncKind, bool tryAnnexB,
1594 Directives inheritedDirectives, Directives* newDirectives);
1595
1596 bool skipLazyInnerFunction(FunctionNodeType funNode, uint32_t toStringStart,
1597 bool tryAnnexB);
1598
1599 bool asmJS(ListNodeType list);
1600
1601 // Functions present only in Parser<SyntaxParseHandler, Unit>.
1602 };
1603
1604 template <typename Unit>
1605 class MOZ_STACK_CLASS Parser<FullParseHandler, Unit> final
1606 : public GeneralParser<FullParseHandler, Unit> {
1607 using Base = GeneralParser<FullParseHandler, Unit>;
1608 using Node = FullParseHandler::Node;
1609
1610 #define DECLARE_TYPE(typeName, longTypeName, asMethodName) \
1611 using longTypeName = FullParseHandler::longTypeName;
1612 FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
1613 #undef DECLARE_TYPE
1614
1615 using SyntaxParser = Parser<SyntaxParseHandler, Unit>;
1616
1617 // Numerous Base::* functions have bodies like
1618 //
1619 // return asFinalParser()->func(...);
1620 //
1621 // and must be able to call functions here. Add a friendship relationship
1622 // so functions here can be hidden when appropriate.
1623 friend class GeneralParser<FullParseHandler, Unit>;
1624
1625 public:
1626 using Base::Base;
1627
1628 // Inherited types, listed here to have non-dependent names.
1629 using typename Base::Modifier;
1630 using typename Base::Position;
1631 using typename Base::TokenStream;
1632
1633 // Inherited functions, listed here to have non-dependent names.
1634
1635 public:
1636 using Base::anyChars;
1637 using Base::clearAbortedSyntaxParse;
1638 using Base::functionFormalParametersAndBody;
1639 using Base::hadAbortedSyntaxParse;
1640 using Base::handler_;
1641 using Base::newFunctionBox;
1642 using Base::options;
1643 using Base::pc_;
1644 using Base::pos;
1645 using Base::ss;
1646 using Base::tokenStream;
1647
1648 public:
1649 // ErrorReportMixin.
1650
1651 using Base::error;
1652 using Base::errorAt;
1653 using Base::errorNoOffset;
1654 using Base::errorWithNotes;
1655 using Base::errorWithNotesAt;
1656 using Base::errorWithNotesNoOffset;
1657 using Base::strictModeError;
1658 using Base::strictModeErrorAt;
1659 using Base::strictModeErrorNoOffset;
1660 using Base::strictModeErrorWithNotes;
1661 using Base::strictModeErrorWithNotesAt;
1662 using Base::strictModeErrorWithNotesNoOffset;
1663 using Base::warning;
1664 using Base::warningAt;
1665 using Base::warningNoOffset;
1666
1667 private:
1668 using Base::alloc_;
1669 using Base::checkLabelOrIdentifierReference;
1670 #if DEBUG
1671 using Base::checkOptionsCalled_;
1672 #endif
1673 using Base::checkForUndefinedPrivateFields;
1674 using Base::cx_;
1675 using Base::finishClassBodyScope;
1676 using Base::finishFunctionScopes;
1677 using Base::finishLexicalScope;
1678 using Base::innerFunction;
1679 using Base::innerFunctionForFunctionBox;
1680 using Base::matchOrInsertSemicolon;
1681 using Base::mustMatchToken;
1682 using Base::newEvalScopeData;
1683 using Base::newFunctionScopeData;
1684 using Base::newGlobalScopeData;
1685 using Base::newLexicalScopeData;
1686 using Base::newModuleScopeData;
1687 using Base::newName;
1688 using Base::newVarScopeData;
1689 using Base::noteDeclaredName;
1690 using Base::noteUsedName;
1691 using Base::null;
1692 using Base::propagateFreeNamesAndMarkClosedOverBindings;
1693 using Base::statementList;
1694 using Base::stringLiteral;
1695 using Base::usedNames_;
1696
1697 using Base::abortIfSyntaxParser;
1698 using Base::disableSyntaxParser;
1699 using Base::getSyntaxParser;
1700
1701 public:
1702 // Functions with multiple overloads of different visibility. We can't
1703 // |using| the whole thing into existence because of the visibility
1704 // distinction, so we instead must manually delegate the required overload.
1705
bindingIdentifier(YieldHandling yieldHandling)1706 TaggedParserAtomIndex bindingIdentifier(YieldHandling yieldHandling) {
1707 return Base::bindingIdentifier(yieldHandling);
1708 }
1709
1710 // Functions present in both Parser<ParseHandler, Unit> specializations.
1711
1712 friend class AutoAwaitIsKeyword<SyntaxParseHandler, Unit>;
1713 inline void setAwaitHandling(AwaitHandling awaitHandling);
1714
1715 friend class AutoInParametersOfAsyncFunction<SyntaxParseHandler, Unit>;
1716 inline void setInParametersOfAsyncFunction(bool inParameters);
1717
1718 RegExpLiteralType newRegExp();
1719 BigIntLiteralType newBigInt();
1720
1721 // Parse a module.
1722 ModuleNodeType moduleBody(ModuleSharedContext* modulesc);
1723
1724 bool checkLocalExportNames(ListNodeType node);
1725 bool checkExportedName(TaggedParserAtomIndex exportName);
1726 bool checkExportedNamesForArrayBinding(ListNodeType array);
1727 bool checkExportedNamesForObjectBinding(ListNodeType obj);
1728 bool checkExportedNamesForDeclaration(Node node);
1729 bool checkExportedNamesForDeclarationList(ListNodeType node);
1730 bool checkExportedNameForFunction(FunctionNodeType funNode);
1731 bool checkExportedNameForClass(ClassNodeType classNode);
1732 inline bool checkExportedNameForClause(NameNodeType nameNode);
1733
1734 bool trySyntaxParseInnerFunction(
1735 FunctionNodeType* funNode, TaggedParserAtomIndex explicitName,
1736 FunctionFlags flags, uint32_t toStringStart, InHandling inHandling,
1737 YieldHandling yieldHandling, FunctionSyntaxKind kind,
1738 GeneratorKind generatorKind, FunctionAsyncKind asyncKind, bool tryAnnexB,
1739 Directives inheritedDirectives, Directives* newDirectives);
1740
1741 [[nodiscard]] bool advancePastSyntaxParsedFunction(
1742 SyntaxParser* syntaxParser);
1743
1744 bool skipLazyInnerFunction(FunctionNodeType funNode, uint32_t toStringStart,
1745 bool tryAnnexB);
1746
1747 // Functions present only in Parser<FullParseHandler, Unit>.
1748
1749 // Parse the body of an eval.
1750 //
1751 // Eval scripts are distinguished from global scripts in that in ES6, per
1752 // 18.2.1.1 steps 9 and 10, all eval scripts are executed under a fresh
1753 // lexical scope.
1754 LexicalScopeNodeType evalBody(EvalSharedContext* evalsc);
1755
1756 // Parse a function, given only its arguments and body. Used for lazily
1757 // parsed functions.
1758 FunctionNodeType standaloneLazyFunction(HandleFunction fun,
1759 uint32_t toStringStart, bool strict,
1760 GeneratorKind generatorKind,
1761 FunctionAsyncKind asyncKind);
1762
1763 // Parse a function, used for the Function, GeneratorFunction, and
1764 // AsyncFunction constructors.
1765 FunctionNodeType standaloneFunction(
1766 const mozilla::Maybe<uint32_t>& parameterListEnd,
1767 FunctionSyntaxKind syntaxKind, GeneratorKind generatorKind,
1768 FunctionAsyncKind asyncKind, Directives inheritedDirectives,
1769 Directives* newDirectives);
1770
1771 bool checkStatementsEOF();
1772
1773 // Parse the body of a global script.
1774 ListNodeType globalBody(GlobalSharedContext* globalsc);
1775
checkLocalExportName(TaggedParserAtomIndex ident,uint32_t offset)1776 bool checkLocalExportName(TaggedParserAtomIndex ident, uint32_t offset) {
1777 return checkLabelOrIdentifierReference(ident, offset, YieldIsName);
1778 }
1779
1780 bool asmJS(ListNodeType list);
1781 };
1782
1783 template <class Parser>
1784 /* static */ inline const TokenStreamAnyChars&
anyChars(const GeneralTokenStreamChars * ts)1785 ParserAnyCharsAccess<Parser>::anyChars(const GeneralTokenStreamChars* ts) {
1786 // The structure we're walking through looks like this:
1787 //
1788 // struct ParserBase
1789 // {
1790 // ...;
1791 // TokenStreamAnyChars anyChars;
1792 // ...;
1793 // };
1794 // struct Parser : <class that ultimately inherits from ParserBase>
1795 // {
1796 // ...;
1797 // TokenStreamSpecific tokenStream;
1798 // ...;
1799 // };
1800 //
1801 // We're passed a GeneralTokenStreamChars* (this being a base class of
1802 // Parser::tokenStream). We cast that pointer to a TokenStreamSpecific*,
1803 // then translate that to the enclosing Parser*, then return the |anyChars|
1804 // member within.
1805
1806 static_assert(std::is_base_of_v<GeneralTokenStreamChars, TokenStreamSpecific>,
1807 "the static_cast<> below assumes a base-class relationship");
1808 const auto* tss = static_cast<const TokenStreamSpecific*>(ts);
1809
1810 auto tssAddr = reinterpret_cast<uintptr_t>(tss);
1811
1812 using ActualTokenStreamType = decltype(std::declval<Parser>().tokenStream);
1813 static_assert(std::is_same_v<ActualTokenStreamType, TokenStreamSpecific>,
1814 "Parser::tokenStream must have type TokenStreamSpecific");
1815
1816 uintptr_t parserAddr = tssAddr - offsetof(Parser, tokenStream);
1817
1818 return reinterpret_cast<const Parser*>(parserAddr)->anyChars;
1819 }
1820
1821 template <class Parser>
anyChars(GeneralTokenStreamChars * ts)1822 /* static */ inline TokenStreamAnyChars& ParserAnyCharsAccess<Parser>::anyChars(
1823 GeneralTokenStreamChars* ts) {
1824 const TokenStreamAnyChars& anyCharsConst =
1825 anyChars(const_cast<const GeneralTokenStreamChars*>(ts));
1826
1827 return const_cast<TokenStreamAnyChars&>(anyCharsConst);
1828 }
1829
1830 template <class ParseHandler, typename Unit>
1831 class MOZ_STACK_CLASS AutoAwaitIsKeyword {
1832 using GeneralParser = frontend::GeneralParser<ParseHandler, Unit>;
1833
1834 private:
1835 GeneralParser* parser_;
1836 AwaitHandling oldAwaitHandling_;
1837
1838 public:
AutoAwaitIsKeyword(GeneralParser * parser,AwaitHandling awaitHandling)1839 AutoAwaitIsKeyword(GeneralParser* parser, AwaitHandling awaitHandling) {
1840 parser_ = parser;
1841 oldAwaitHandling_ = static_cast<AwaitHandling>(parser_->awaitHandling_);
1842
1843 // 'await' is always a keyword in module contexts, so we don't modify
1844 // the state when the original handling is AwaitIsModuleKeyword.
1845 if (oldAwaitHandling_ != AwaitIsModuleKeyword) {
1846 parser_->setAwaitHandling(awaitHandling);
1847 }
1848 }
1849
~AutoAwaitIsKeyword()1850 ~AutoAwaitIsKeyword() { parser_->setAwaitHandling(oldAwaitHandling_); }
1851 };
1852
1853 template <class ParseHandler, typename Unit>
1854 class MOZ_STACK_CLASS AutoInParametersOfAsyncFunction {
1855 using GeneralParser = frontend::GeneralParser<ParseHandler, Unit>;
1856
1857 private:
1858 GeneralParser* parser_;
1859 bool oldInParametersOfAsyncFunction_;
1860
1861 public:
AutoInParametersOfAsyncFunction(GeneralParser * parser,bool inParameters)1862 AutoInParametersOfAsyncFunction(GeneralParser* parser, bool inParameters) {
1863 parser_ = parser;
1864 oldInParametersOfAsyncFunction_ = parser_->inParametersOfAsyncFunction_;
1865 parser_->setInParametersOfAsyncFunction(inParameters);
1866 }
1867
~AutoInParametersOfAsyncFunction()1868 ~AutoInParametersOfAsyncFunction() {
1869 parser_->setInParametersOfAsyncFunction(oldInParametersOfAsyncFunction_);
1870 }
1871 };
1872
1873 GlobalScope::ParserData* NewEmptyGlobalScopeData(JSContext* cx,
1874 LifoAlloc& alloc,
1875 uint32_t numBindings);
1876
1877 VarScope::ParserData* NewEmptyVarScopeData(JSContext* cx, LifoAlloc& alloc,
1878 uint32_t numBindings);
1879
1880 LexicalScope::ParserData* NewEmptyLexicalScopeData(JSContext* cx,
1881 LifoAlloc& alloc,
1882 uint32_t numBindings);
1883
1884 FunctionScope::ParserData* NewEmptyFunctionScopeData(JSContext* cx,
1885 LifoAlloc& alloc,
1886 uint32_t numBindings);
1887
1888 mozilla::Maybe<GlobalScope::ParserData*> NewGlobalScopeData(
1889 JSContext* context, ParseContext::Scope& scope, LifoAlloc& alloc,
1890 ParseContext* pc);
1891
1892 mozilla::Maybe<EvalScope::ParserData*> NewEvalScopeData(
1893 JSContext* context, ParseContext::Scope& scope, LifoAlloc& alloc,
1894 ParseContext* pc);
1895
1896 mozilla::Maybe<FunctionScope::ParserData*> NewFunctionScopeData(
1897 JSContext* context, ParseContext::Scope& scope, bool hasParameterExprs,
1898 LifoAlloc& alloc, ParseContext* pc);
1899
1900 mozilla::Maybe<VarScope::ParserData*> NewVarScopeData(
1901 JSContext* context, ParseContext::Scope& scope, LifoAlloc& alloc,
1902 ParseContext* pc);
1903
1904 mozilla::Maybe<LexicalScope::ParserData*> NewLexicalScopeData(
1905 JSContext* context, ParseContext::Scope& scope, LifoAlloc& alloc,
1906 ParseContext* pc);
1907
1908 bool FunctionScopeHasClosedOverBindings(ParseContext* pc);
1909 bool LexicalScopeHasClosedOverBindings(ParseContext* pc,
1910 ParseContext::Scope& scope);
1911
1912 } /* namespace frontend */
1913 } /* namespace js */
1914
1915 #endif /* frontend_Parser_h */
1916