Source code

Revision control

Other Tools

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