1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  * vim: set ts=8 sts=4 et sw=4 tw=99:
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 #ifndef frontend_Parser_h
8 #define frontend_Parser_h
9 
10 /*
11  * JS parser definitions.
12  */
13 
14 #include "jspubtd.h"
15 
16 #include "frontend/BytecodeCompiler.h"
17 #include "frontend/FullParseHandler.h"
18 #include "frontend/ParseMaps.h"
19 #include "frontend/ParseNode.h"
20 #include "frontend/SharedContext.h"
21 #include "frontend/SyntaxParseHandler.h"
22 
23 namespace js {
24 
25 class ModuleObject;
26 class StaticFunctionBoxScopeObject;
27 
28 namespace frontend {
29 
30 struct StmtInfoPC : public StmtInfoBase
31 {
32     static const unsigned BlockIdLimit = 1 << ParseNode::NumBlockIdBits;
33 
34     StmtInfoPC*     enclosing;
35     StmtInfoPC*     enclosingScope;
36 
37     uint32_t        blockid;        /* for simplified dominance computation */
38     uint32_t        innerBlockScopeDepth; /* maximum depth of nested block scopes, in slots */
39 
40     // Lexical declarations inside switches are tricky because the block id
41     // doesn't convey dominance information. Record what index the current
42     // case's lexical declarations start at so we may generate dead zone
43     // checks for other cases' declarations.
44     //
45     // Only valid if type is StmtType::SWITCH.
46     uint16_t        firstDominatingLexicalInCase;
47 
StmtInfoPCStmtInfoPC48     explicit StmtInfoPC(ExclusiveContext* cx)
49       : StmtInfoBase(cx),
50         blockid(BlockIdLimit),
51         innerBlockScopeDepth(0),
52         firstDominatingLexicalInCase(0)
53     {}
54 };
55 
56 typedef HashSet<JSAtom*, DefaultHasher<JSAtom*>, LifoAllocPolicy<Fallible>> FuncStmtSet;
57 class SharedContext;
58 
59 typedef Vector<Definition*, 16> DeclVector;
60 
61 struct GenericParseContext
62 {
63     // Enclosing function or global context.
64     GenericParseContext* parent;
65 
66     // Context shared between parsing and bytecode generation.
67     SharedContext* sc;
68 
69     // The following flags are set when a particular code feature is detected
70     // in a function.
71 
72     // Function has 'return <expr>;'
73     bool funHasReturnExpr:1;
74 
75     // Function has 'return;'
76     bool funHasReturnVoid:1;
77 
GenericParseContextGenericParseContext78     GenericParseContext(GenericParseContext* parent, SharedContext* sc)
79       : parent(parent),
80         sc(sc),
81         funHasReturnExpr(false),
82         funHasReturnVoid(false)
83     {}
84 };
85 
86 template <typename ParseHandler>
87 bool
88 GenerateBlockId(TokenStream& ts, ParseContext<ParseHandler>* pc, uint32_t& blockid);
89 
90 /*
91  * The struct ParseContext stores information about the current parsing context,
92  * which is part of the parser state (see the field Parser::pc). The current
93  * parsing context is either the global context, or the function currently being
94  * parsed. When the parser encounters a function definition, it creates a new
95  * ParseContext, makes it the new current context, and sets its parent to the
96  * context in which it encountered the definition.
97  */
98 template <typename ParseHandler>
99 struct MOZ_STACK_CLASS ParseContext : public GenericParseContext
100 {
101     typedef typename ParseHandler::Node Node;
102     typedef typename ParseHandler::DefinitionNode DefinitionNode;
103 
104     uint32_t        bodyid;         /* block number of program/function body */
105 
106     StmtInfoStack<StmtInfoPC> stmtStack;
107 
108     Node            maybeFunction;  /* sc->isFunctionBox, the pn where pn->pn_funbox == sc */
109 
110     // If sc->isFunctionBox(), this is used to temporarily link up the
111     // FunctionBox with the JSFunction so the static scope chain may be walked
112     // without a JSScript.
113     mozilla::Maybe<JSFunction::AutoParseUsingFunctionBox> parseUsingFunctionBox;
114 
115     // lastYieldOffset stores the offset of the last yield that was parsed.
116     // NoYieldOffset is its initial value.
117     static const uint32_t NoYieldOffset = UINT32_MAX;
118     uint32_t         lastYieldOffset;
119 
120     // Most functions start off being parsed as non-generators.
121     // Non-generators transition to LegacyGenerator on parsing "yield" in JS 1.7.
122     // An ES6 generator is marked as a "star generator" before its body is parsed.
generatorKindParseContext123     GeneratorKind generatorKind() const {
124         return sc->isFunctionBox() ? sc->asFunctionBox()->generatorKind() : NotGenerator;
125     }
isGeneratorParseContext126     bool isGenerator() const { return generatorKind() != NotGenerator; }
isLegacyGeneratorParseContext127     bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; }
isStarGeneratorParseContext128     bool isStarGenerator() const { return generatorKind() == StarGenerator; }
129 
isArrowFunctionParseContext130     bool isArrowFunction() const {
131         return sc->isFunctionBox() && sc->asFunctionBox()->function()->isArrow();
132     }
isMethodParseContext133     bool isMethod() const {
134         return sc->isFunctionBox() && sc->asFunctionBox()->function()->isMethod();
135     }
136 
137     uint32_t        blockScopeDepth; /* maximum depth of nested block scopes, in slots */
138     Node            blockNode;      /* parse node for a block with let declarations
139                                        (block with its own lexical scope)  */
140 
141   private:
142     AtomDecls<ParseHandler> decls_;     /* function, const, and var declarations */
143     DeclVector      args_;              /* argument definitions */
144     DeclVector      vars_;              /* var/const definitions */
145     DeclVector      bodyLevelLexicals_; /* lexical definitions at body-level */
146 
147     bool checkLocalsOverflow(TokenStream& ts);
148 
149   public:
declsParseContext150     const AtomDecls<ParseHandler>& decls() const {
151         return decls_;
152     }
153 
numArgsParseContext154     uint32_t numArgs() const {
155         MOZ_ASSERT(sc->isFunctionBox());
156         return args_.length();
157     }
158 
159     /*
160      * This function adds a definition to the lexical scope represented by this
161      * ParseContext.
162      *
163      * Pre-conditions:
164      *  + The caller must have already taken care of name collisions:
165      *    - For non-let definitions, this means 'name' isn't in 'decls'.
166      *    - For let definitions, this means 'name' isn't already a name in the
167      *      current block.
168      *  + The given 'pn' is either a placeholder (created by a previous unbound
169      *    use) or an un-bound un-linked name node.
170      *  + The given 'kind' is one of ARG, CONST, VAR, or LET. In particular,
171      *    NAMED_LAMBDA is handled in an ad hoc special case manner (see
172      *    LeaveFunction) that we should consider rewriting.
173      *
174      * Post-conditions:
175      *  + pc->decls().lookupFirst(name) == pn
176      *  + The given name 'pn' has been converted in-place into a
177      *    non-placeholder definition.
178      *  + If this is a function scope (sc->inFunction), 'pn' is bound to a
179      *    particular local/argument slot.
180      *  + PND_CONST is set for Definition::COSNT
181      *  + Pre-existing uses of pre-existing placeholders have been linked to
182      *    'pn' if they are in the scope of 'pn'.
183      *  + Pre-existing placeholders in the scope of 'pn' have been removed.
184      */
185     bool define(TokenStream& ts, HandlePropertyName name, Node pn, Definition::Kind);
186 
187     /*
188      * Let definitions may shadow same-named definitions in enclosing scopes.
189      * To represesent this, 'decls' is not a plain map, but actually:
190      *   decls :: name -> stack of definitions
191      * New bindings are pushed onto the stack, name lookup always refers to the
192      * top of the stack, and leaving a block scope calls popLetDecl for each
193      * name in the block's scope.
194      */
195     void popLetDecl(JSAtom* atom);
196 
197     /* See the sad story in defineArg. */
198     void prepareToAddDuplicateArg(HandlePropertyName name, DefinitionNode prevDecl);
199 
200     /* See the sad story in MakeDefIntoUse. */
201     void updateDecl(TokenStream& ts, JSAtom* atom, Node newDecl);
202 
203     // After a script has been parsed, the parser generates the code's
204     // "bindings". Bindings are a data-structure, ultimately stored in the
205     // compiled JSScript, that serve three purposes:
206     //
207     //  - After parsing, the ParseContext is destroyed and 'decls' along with
208     //    it. Mostly, the emitter just uses the binding information stored in
209     //    the use/def nodes, but the emitter occasionally needs 'bindings' for
210     //    various scope-related queries.
211     //
212     //  - For functions, bindings provide the initial js::Shape to use when
213     //    creating a dynamic scope object (js::CallObject). This shape is used
214     //    during dynamic name lookup.
215     //
216     //  - Sometimes a script's bindings are accessed at runtime to retrieve the
217     //    contents of the lexical scope (e.g., from the debugger).
218     //
219     //  - For global and eval scripts, ES6 15.1.8 specifies that if there are
220     //    name conflicts in the script, *no* bindings from the script are
221     //    instantiated. So, record the vars and lexical bindings to check for
222     //    redeclarations in the prologue.
223     bool generateBindings(ExclusiveContext* cx, TokenStream& ts, LifoAlloc& alloc,
224                           MutableHandle<Bindings> bindings) const;
225 
226   private:
227     ParseContext**  parserPC;     /* this points to the Parser's active pc
228                                        and holds either |this| or one of
229                                        |this|'s descendents */
230 
231     // Value for parserPC to restore at the end. Use 'parent' instead for
232     // information about the parse chain, this may be nullptr if
233     // parent != nullptr.
234     ParseContext<ParseHandler>* oldpc;
235 
236   public:
237     OwnedAtomDefnMapPtr lexdeps;    /* unresolved lexical name dependencies */
238 
239     FuncStmtSet*    funcStmts;     /* Set of (non-top-level) function statements
240                                        that will alias any top-level bindings with
241                                        the same name. */
242 
243     // All inner functions in this context. Only filled in when parsing syntax.
244     Rooted<TraceableVector<JSFunction*>> innerFunctions;
245 
246     // In a function context, points to a Directive struct that can be updated
247     // to reflect new directives encountered in the Directive Prologue that
248     // require reparsing the function. In global/module/generator-tail contexts,
249     // we don't need to reparse when encountering a DirectivePrologue so this
250     // pointer may be nullptr.
251     Directives* newDirectives;
252 
253     // Set when parsing a declaration-like destructuring pattern.  This flag
254     // causes PrimaryExpr to create PN_NAME parse nodes for variable references
255     // which are not hooked into any definition's use chain, added to any tree
256     // context's AtomList, etc. etc.  checkDestructuring will do that work
257     // later.
258     //
259     // The comments atop checkDestructuring explain the distinction between
260     // assignment-like and declaration-like destructuring patterns, and why
261     // they need to be treated differently.
262     bool            inDeclDestructuring:1;
263 
ParseContextParseContext264     ParseContext(Parser<ParseHandler>* prs, GenericParseContext* parent,
265                  Node maybeFunction, SharedContext* sc, Directives* newDirectives)
266       : GenericParseContext(parent, sc),
267         bodyid(0),           // initialized in init()
268         stmtStack(prs->context),
269         maybeFunction(maybeFunction),
270         lastYieldOffset(NoYieldOffset),
271         blockScopeDepth(0),
272         blockNode(ParseHandler::null()),
273         decls_(prs->context, prs->alloc),
274         args_(prs->context),
275         vars_(prs->context),
276         bodyLevelLexicals_(prs->context),
277         parserPC(&prs->pc),
278         oldpc(prs->pc),
279         lexdeps(prs->context),
280         funcStmts(nullptr),
281         innerFunctions(prs->context, TraceableVector<JSFunction*>(prs->context)),
282         newDirectives(newDirectives),
283         inDeclDestructuring(false)
284     {
285         prs->pc = this;
286         if (sc->isFunctionBox())
287             parseUsingFunctionBox.emplace(prs->context, sc->asFunctionBox());
288     }
289 
290     ~ParseContext();
291 
292     bool init(Parser<ParseHandler>& parser);
293 
blockidParseContext294     unsigned blockid() { return stmtStack.innermost() ? stmtStack.innermost()->blockid : bodyid; }
295 
innermostStmtParseContext296     StmtInfoPC* innermostStmt() const { return stmtStack.innermost(); }
innermostScopeStmtParseContext297     StmtInfoPC* innermostScopeStmt() const { return stmtStack.innermostScopeStmt(); }
innermostStaticScopeParseContext298     JSObject* innermostStaticScope() const {
299         if (StmtInfoPC* stmt = innermostScopeStmt())
300             return stmt->staticScope;
301         return sc->staticScope();
302     }
303 
304     // True if we are at the topmost level of a entire script or function body.
305     // For example, while parsing this code we would encounter f1 and f2 at
306     // body level, but we would not encounter f3 or f4 at body level:
307     //
308     //   function f1() { function f2() { } }
309     //   if (cond) { function f3() { if (cond) { function f4() { } } } }
310     //
atBodyLevelParseContext311     bool atBodyLevel() {
312         // 'eval' and non-syntactic scripts are always under an invisible
313         // lexical scope, but since it is not syntactic, it should still be
314         // considered at body level.
315         if (sc->staticScope()->is<StaticEvalObject>()) {
316             bool bl = !innermostStmt()->enclosing;
317             MOZ_ASSERT_IF(bl, innermostStmt()->type == StmtType::BLOCK);
318             MOZ_ASSERT_IF(bl, innermostStmt()->staticScope
319                                              ->template as<StaticBlockObject>()
320                                              .enclosingStaticScope() == sc->staticScope());
321             return bl;
322         }
323         return !innermostStmt();
324     }
325 
atGlobalLevelParseContext326     bool atGlobalLevel() {
327         return atBodyLevel() && sc->isGlobalContext() && !innermostScopeStmt();
328     }
329 
330     // True if we are at the topmost level of a module only.
atModuleLevelParseContext331     bool atModuleLevel() {
332         return atBodyLevel() && sc->isModuleBox();
333     }
334 
335     // True if the current lexical scope is the topmost level of a module.
atModuleScopeParseContext336     bool atModuleScope() {
337         return sc->isModuleBox() && !innermostScopeStmt();
338     }
339 
340     // True if this is the ParseContext for the body of a function created by
341     // the Function constructor.
isFunctionConstructorBodyParseContext342     bool isFunctionConstructorBody() const {
343         return sc->isFunctionBox() && !parent && sc->asFunctionBox()->function()->isLambda();
344     }
345 
useAsmOrInsideUseAsmParseContext346     inline bool useAsmOrInsideUseAsm() const {
347         return sc->isFunctionBox() && sc->asFunctionBox()->useAsmOrInsideUseAsm();
348     }
349 };
350 
351 template <typename ParseHandler>
352 inline
Directives(ParseContext<ParseHandler> * parent)353 Directives::Directives(ParseContext<ParseHandler>* parent)
354   : strict_(parent->sc->strict()),
355     asmJS_(parent->useAsmOrInsideUseAsm())
356 {}
357 
358 template <typename ParseHandler>
359 struct BindData;
360 
361 class CompExprTransplanter;
362 
363 enum VarContext { HoistVars, DontHoistVars };
364 enum PropListType { ObjectLiteral, ClassBody, DerivedClassBody };
365 enum class PropertyType {
366     Normal,
367     Shorthand,
368     Getter,
369     GetterNoExpressionClosure,
370     Setter,
371     SetterNoExpressionClosure,
372     Method,
373     GeneratorMethod,
374     Constructor,
375     DerivedConstructor
376 };
377 
378 // Specify a value for an ES6 grammar parametrization.  We have no enum for
379 // [Return] because its behavior is exactly equivalent to checking whether
380 // we're in a function box -- easier and simpler than passing an extra
381 // parameter everywhere.
382 enum YieldHandling { YieldIsName, YieldIsKeyword };
383 enum InHandling { InAllowed, InProhibited };
384 enum DefaultHandling { NameRequired, AllowDefaultName };
385 enum TripledotHandling { TripledotAllowed, TripledotProhibited };
386 
387 template <typename ParseHandler>
388 class Parser : private JS::AutoGCRooter, public StrictModeGetter
389 {
390     class MOZ_STACK_CLASS AutoPushStmtInfoPC
391     {
392         Parser<ParseHandler>& parser_;
393         StmtInfoPC stmt_;
394 
395       public:
396         AutoPushStmtInfoPC(Parser<ParseHandler>& parser, StmtType type);
397         AutoPushStmtInfoPC(Parser<ParseHandler>& parser, StmtType type,
398                            NestedScopeObject& staticScope);
399         ~AutoPushStmtInfoPC();
400 
401         bool generateBlockId();
402         bool makeInnermostLexicalScope(StaticBlockObject& blockObj);
403 
404         StmtInfoPC& operator*() { return stmt_; }
405         StmtInfoPC* operator->() { return &stmt_; }
406         operator StmtInfoPC*() { return &stmt_; }
407     };
408 
409   public:
410     ExclusiveContext* const context;
411     LifoAlloc& alloc;
412 
413     TokenStream         tokenStream;
414     LifoAlloc::Mark     tempPoolMark;
415 
416     /* list of parsed objects for GC tracing */
417     ObjectBox* traceListHead;
418 
419     /* innermost parse context (stack-allocated) */
420     ParseContext<ParseHandler>* pc;
421 
422     // List of all block scopes.
423     AutoObjectVector blockScopes;
424 
425     /* Compression token for aborting. */
426     SourceCompressionTask* sct;
427 
428     ScriptSource*       ss;
429 
430     /* Root atoms and objects allocated for the parsed tree. */
431     AutoKeepAtoms       keepAtoms;
432 
433     /* Perform constant-folding; must be true when interfacing with the emitter. */
434     const bool          foldConstants:1;
435 
436   private:
437 #if DEBUG
438     /* Our fallible 'checkOptions' member function has been called. */
439     bool checkOptionsCalled:1;
440 #endif
441 
442     /*
443      * Not all language constructs can be handled during syntax parsing. If it
444      * is not known whether the parse succeeds or fails, this bit is set and
445      * the parse will return false.
446      */
447     bool abortedSyntaxParse:1;
448 
449     /* Unexpected end of input, i.e. TOK_EOF not at top-level. */
450     bool isUnexpectedEOF_:1;
451 
452     typedef typename ParseHandler::Node Node;
453     typedef typename ParseHandler::DefinitionNode DefinitionNode;
454 
455   public:
456     /* State specific to the kind of parse being performed. */
457     ParseHandler handler;
458 
prepareNodeForMutation(Node node)459     void prepareNodeForMutation(Node node) { handler.prepareNodeForMutation(node); }
freeTree(Node node)460     void freeTree(Node node) { handler.freeTree(node); }
461 
462   private:
463     bool reportHelper(ParseReportKind kind, bool strict, uint32_t offset,
464                       unsigned errorNumber, va_list args);
465   public:
466     bool report(ParseReportKind kind, bool strict, Node pn, unsigned errorNumber, ...);
467     bool reportNoOffset(ParseReportKind kind, bool strict, unsigned errorNumber, ...);
468     bool reportWithOffset(ParseReportKind kind, bool strict, uint32_t offset, unsigned errorNumber,
469                           ...);
470 
471     Parser(ExclusiveContext* cx, LifoAlloc* alloc, const ReadOnlyCompileOptions& options,
472            const char16_t* chars, size_t length, bool foldConstants,
473            Parser<SyntaxParseHandler>* syntaxParser,
474            LazyScript* lazyOuterFunction);
475     ~Parser();
476 
477     bool checkOptions();
478 
479     // A Parser::Mark is the extension of the LifoAlloc::Mark to the entire
480     // Parser's state. Note: clients must still take care that any ParseContext
481     // that points into released ParseNodes is destroyed.
482     class Mark
483     {
484         friend class Parser;
485         LifoAlloc::Mark mark;
486         ObjectBox* traceListHead;
487     };
mark()488     Mark mark() const {
489         Mark m;
490         m.mark = alloc.mark();
491         m.traceListHead = traceListHead;
492         return m;
493     }
release(Mark m)494     void release(Mark m) {
495         alloc.release(m.mark);
496         traceListHead = m.traceListHead;
497     }
498 
499     friend void js::frontend::MarkParser(JSTracer* trc, JS::AutoGCRooter* parser);
500 
getFilename()501     const char* getFilename() const { return tokenStream.getFilename(); }
versionNumber()502     JSVersion versionNumber() const { return tokenStream.versionNumber(); }
503 
504     /*
505      * Parse a top-level JS script.
506      */
507     Node parse();
508 
509     /*
510      * Allocate a new parsed object or function container from
511      * cx->tempLifoAlloc.
512      */
513     ObjectBox* newObjectBox(JSObject* obj);
514     FunctionBox* newFunctionBox(Node fn, JSFunction* fun, ParseContext<ParseHandler>* outerpc,
515                                 Directives directives, GeneratorKind generatorKind,
516                                 JSObject* enclosingStaticScope);
517 
518     // Use when the funbox is the outermost.
newFunctionBox(Node fn,HandleFunction fun,Directives directives,GeneratorKind generatorKind,HandleObject enclosingStaticScope)519     FunctionBox* newFunctionBox(Node fn, HandleFunction fun, Directives directives,
520                                 GeneratorKind generatorKind, HandleObject enclosingStaticScope)
521     {
522         return newFunctionBox(fn, fun, nullptr, directives, generatorKind,
523                               enclosingStaticScope);
524     }
525 
526     // Use when the funbox should be linked to the outerpc's innermost scope.
newFunctionBox(Node fn,HandleFunction fun,ParseContext<ParseHandler> * outerpc,Directives directives,GeneratorKind generatorKind)527     FunctionBox* newFunctionBox(Node fn, HandleFunction fun, ParseContext<ParseHandler>* outerpc,
528                                 Directives directives, GeneratorKind generatorKind)
529     {
530         RootedObject enclosing(context, outerpc->innermostStaticScope());
531         return newFunctionBox(fn, fun, outerpc, directives, generatorKind, enclosing);
532     }
533 
534     ModuleBox* newModuleBox(Node pn, HandleModuleObject module);
535 
536     /*
537      * Create a new function object given a name (which is optional if this is
538      * a function expression).
539      */
540     JSFunction* newFunction(HandleAtom atom, FunctionSyntaxKind kind, GeneratorKind generatorKind,
541                             HandleObject proto);
542 
generateBlockId(JSObject * staticScope,uint32_t * blockIdOut)543     bool generateBlockId(JSObject* staticScope, uint32_t* blockIdOut) {
544         if (blockScopes.length() == StmtInfoPC::BlockIdLimit) {
545             tokenStream.reportError(JSMSG_NEED_DIET, "program");
546             return false;
547         }
548         MOZ_ASSERT(blockScopes.length() < StmtInfoPC::BlockIdLimit);
549         *blockIdOut = blockScopes.length();
550         return blockScopes.append(staticScope);
551     }
552 
553     void trace(JSTracer* trc);
554 
hadAbortedSyntaxParse()555     bool hadAbortedSyntaxParse() {
556         return abortedSyntaxParse;
557     }
clearAbortedSyntaxParse()558     void clearAbortedSyntaxParse() {
559         abortedSyntaxParse = false;
560     }
561 
isUnexpectedEOF()562     bool isUnexpectedEOF() const { return isUnexpectedEOF_; }
563 
564     bool checkUnescapedName();
565 
566   private:
thisForCtor()567     Parser* thisForCtor() { return this; }
568 
569     JSAtom * stopStringCompression();
570 
571     Node stringLiteral();
572     Node noSubstitutionTemplate();
573     Node templateLiteral(YieldHandling yieldHandling);
574     bool taggedTemplate(YieldHandling yieldHandling, Node nodeList, TokenKind tt);
575     bool appendToCallSiteObj(Node callSiteObj);
576     bool addExprAndGetNextTemplStrToken(YieldHandling yieldHandling, Node nodeList,
577                                         TokenKind* ttp);
578     bool checkStatementsEOF();
579 
580     inline Node newName(PropertyName* name);
581     inline Node newYieldExpression(uint32_t begin, Node expr, bool isYieldStar = false);
582 
583     inline bool abortIfSyntaxParser();
584 
585   public:
586     /* Public entry points for parsing. */
587     Node statement(YieldHandling yieldHandling, bool canHaveDirectives = false);
588 
589     bool maybeParseDirective(Node list, Node pn, bool* cont);
590 
591     // Parse the body of an eval.
592     //
593     // Eval scripts are distinguished from global scripts in that in ES6, per
594     // 18.2.1.1 steps 9 and 10, all eval scripts are executed under a fresh
595     // lexical scope.
596     Node evalBody();
597 
598     // Parse the body of a global script.
599     Node globalBody();
600 
601     // Parse a module.
602     Node standaloneModule(Handle<ModuleObject*> module);
603 
604     // Parse a function, given only its body. Used for the Function and
605     // Generator constructors.
606     Node standaloneFunctionBody(HandleFunction fun, Handle<PropertyNameVector> formals,
607                                 GeneratorKind generatorKind,
608                                 Directives inheritedDirectives, Directives* newDirectives,
609                                 HandleObject enclosingStaticScope);
610 
611     // Parse a function, given only its arguments and body. Used for lazily
612     // parsed functions.
613     Node standaloneLazyFunction(HandleFunction fun, bool strict, GeneratorKind generatorKind);
614 
615     /*
616      * Parse a function body.  Pass StatementListBody if the body is a list of
617      * statements; pass ExpressionBody if the body is a single expression.
618      */
619     enum FunctionBodyType { StatementListBody, ExpressionBody };
620     Node functionBody(InHandling inHandling, YieldHandling yieldHandling, FunctionSyntaxKind kind,
621                       FunctionBodyType type);
622 
623     bool functionArgsAndBodyGeneric(InHandling inHandling, YieldHandling yieldHandling, Node pn,
624                                     HandleFunction fun, FunctionSyntaxKind kind);
625 
626     // Determine whether |yield| is a valid name in the current context, or
627     // whether it's prohibited due to strictness, JS version, or occurrence
628     // inside a star generator.
629     bool checkYieldNameValidity();
yieldExpressionsSupported()630     bool yieldExpressionsSupported() {
631         return versionNumber() >= JSVERSION_1_7 || pc->isGenerator();
632     }
633 
strictMode()634     virtual bool strictMode() { return pc->sc->strict(); }
setLocalStrictMode(bool strict)635     bool setLocalStrictMode(bool strict) {
636         MOZ_ASSERT(tokenStream.debugHasNoLookahead());
637         return pc->sc->setLocalStrictMode(strict);
638     }
639 
options()640     const ReadOnlyCompileOptions& options() const {
641         return tokenStream.options();
642     }
643 
644   private:
645     enum InvokedPrediction { PredictUninvoked = false, PredictInvoked = true };
646     enum ForInitLocation { InForInit, NotInForInit };
647 
648   private:
649     /*
650      * JS parsers, from lowest to highest precedence.
651      *
652      * Each parser must be called during the dynamic scope of a ParseContext
653      * object, pointed to by this->pc.
654      *
655      * Each returns a parse node tree or null on error.
656      *
657      * Parsers whose name has a '1' suffix leave the TokenStream state
658      * pointing to the token one past the end of the parsed fragment.  For a
659      * number of the parsers this is convenient and avoids a lot of
660      * unnecessary ungetting and regetting of tokens.
661      *
662      * Some parsers have two versions:  an always-inlined version (with an 'i'
663      * suffix) and a never-inlined version (with an 'n' suffix).
664      */
665     Node functionStmt(YieldHandling yieldHandling, DefaultHandling defaultHandling);
666     Node functionExpr(InvokedPrediction invoked = PredictUninvoked);
667     Node statements(YieldHandling yieldHandling);
668 
669     Node blockStatement(YieldHandling yieldHandling);
670     Node ifStatement(YieldHandling yieldHandling);
671     Node doWhileStatement(YieldHandling yieldHandling);
672     Node whileStatement(YieldHandling yieldHandling);
673     Node forStatement(YieldHandling yieldHandling);
674     Node switchStatement(YieldHandling yieldHandling);
675     Node continueStatement(YieldHandling yieldHandling);
676     Node breakStatement(YieldHandling yieldHandling);
677     Node returnStatement(YieldHandling yieldHandling);
678     Node withStatement(YieldHandling yieldHandling);
679     Node labeledStatement(YieldHandling yieldHandling);
680     Node throwStatement(YieldHandling yieldHandling);
681     Node tryStatement(YieldHandling yieldHandling);
682     Node debuggerStatement();
683 
684     Node lexicalDeclaration(YieldHandling yieldHandling, bool isConst);
685     Node importDeclaration();
686     Node exportDeclaration();
687     Node expressionStatement(YieldHandling yieldHandling,
688                              InvokedPrediction invoked = PredictUninvoked);
689     Node variables(YieldHandling yieldHandling,
690                    ParseNodeKind kind,
691                    ForInitLocation location,
692                    bool* psimple = nullptr, StaticBlockObject* blockObj = nullptr,
693                    VarContext varContext = HoistVars);
694     Node expr(InHandling inHandling, YieldHandling yieldHandling,
695               TripledotHandling tripledotHandling,
696               InvokedPrediction invoked = PredictUninvoked);
697     Node assignExpr(InHandling inHandling, YieldHandling yieldHandling,
698                     TripledotHandling tripledotHandling,
699                     InvokedPrediction invoked = PredictUninvoked);
700     Node assignExprWithoutYield(YieldHandling yieldHandling, unsigned err);
701     Node yieldExpression(InHandling inHandling);
702     Node condExpr1(InHandling inHandling, YieldHandling yieldHandling,
703                    TripledotHandling tripledotHandling,
704                    InvokedPrediction invoked = PredictUninvoked);
705     Node orExpr1(InHandling inHandling, YieldHandling yieldHandling,
706                  TripledotHandling tripledotHandling,
707                    InvokedPrediction invoked = PredictUninvoked);
708     Node unaryExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling,
709                    InvokedPrediction invoked = PredictUninvoked);
710     Node memberExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling, TokenKind tt,
711                     bool allowCallSyntax, InvokedPrediction invoked = PredictUninvoked);
712     Node primaryExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling, TokenKind tt,
713                      InvokedPrediction invoked = PredictUninvoked);
714     Node exprInParens(InHandling inHandling, YieldHandling yieldHandling,
715                       TripledotHandling tripledotHandling);
716 
717     bool tryNewTarget(Node& newTarget);
718     bool checkAndMarkSuperScope();
719 
720     Node methodDefinition(YieldHandling yieldHandling, PropertyType propType,
721                           HandlePropertyName funName);
722 
723     /*
724      * Additional JS parsers.
725      */
726     bool functionArguments(YieldHandling yieldHandling, FunctionSyntaxKind kind,
727                            Node funcpn, bool* hasRest);
728 
729     Node functionDef(InHandling inHandling, YieldHandling uieldHandling, HandlePropertyName name,
730                      FunctionSyntaxKind kind, GeneratorKind generatorKind,
731                      InvokedPrediction invoked = PredictUninvoked);
732     bool functionArgsAndBody(InHandling inHandling, Node pn, HandleFunction fun,
733                              FunctionSyntaxKind kind, GeneratorKind generatorKind,
734                              Directives inheritedDirectives, Directives* newDirectives);
735 
736     Node unaryOpExpr(YieldHandling yieldHandling, ParseNodeKind kind, JSOp op, uint32_t begin);
737 
738     Node condition(InHandling inHandling, YieldHandling yieldHandling);
739 
740     /* comprehensions */
741     Node legacyComprehensionTail(Node kid, unsigned blockid, GeneratorKind comprehensionKind,
742                                  ParseContext<ParseHandler>* outerpc,
743                                  unsigned innerBlockScopeDepth);
744     Node legacyArrayComprehension(Node array);
745     Node generatorComprehensionLambda(GeneratorKind comprehensionKind, unsigned begin,
746                                       Node innerStmt);
747     Node legacyGeneratorExpr(Node kid);
748     Node comprehensionFor(GeneratorKind comprehensionKind);
749     Node comprehensionIf(GeneratorKind comprehensionKind);
750     Node comprehensionTail(GeneratorKind comprehensionKind);
751     Node comprehension(GeneratorKind comprehensionKind);
752     Node arrayComprehension(uint32_t begin);
753     Node generatorComprehension(uint32_t begin);
754 
755     bool argumentList(YieldHandling yieldHandling, Node listNode, bool* isSpread);
756     Node destructuringExpr(YieldHandling yieldHandling, BindData<ParseHandler>* data,
757                            TokenKind tt);
758     Node destructuringExprWithoutYield(YieldHandling yieldHandling, BindData<ParseHandler>* data,
759                                        TokenKind tt, unsigned msg);
760 
761     Node newBoundImportForCurrentName();
762     bool namedImportsOrNamespaceImport(TokenKind tt, Node importSpecSet);
763     bool addExportName(JSAtom* exportName);
764 
765     enum ClassContext { ClassStatement, ClassExpression };
766     Node classDefinition(YieldHandling yieldHandling, ClassContext classContext, DefaultHandling defaultHandling);
767 
768     Node identifierName(YieldHandling yieldHandling);
769 
770     bool matchLabel(YieldHandling yieldHandling, MutableHandle<PropertyName*> label);
771 
allowsForEachIn()772     bool allowsForEachIn() {
773 #if !JS_HAS_FOR_EACH_IN
774         return false;
775 #else
776         return versionNumber() >= JSVERSION_1_6;
777 #endif
778     }
779 
780     enum AssignmentFlavor {
781         PlainAssignment,
782         CompoundAssignment,
783         KeyedDestructuringAssignment,
784         IncrementAssignment,
785         DecrementAssignment
786     };
787 
788     bool checkAndMarkAsAssignmentLhs(Node pn, AssignmentFlavor flavor);
789     bool matchInOrOf(bool* isForInp, bool* isForOfp);
790 
791     bool checkFunctionArguments();
792 
793     bool defineFunctionThis();
794     Node newThisName();
795 
796     bool makeDefIntoUse(Definition* dn, Node pn, HandleAtom atom);
797     bool checkFunctionDefinition(HandlePropertyName funName, Node* pn, FunctionSyntaxKind kind,
798                                  bool* pbodyProcessed);
799     bool finishFunctionDefinition(Node pn, FunctionBox* funbox, Node body);
800     bool addFreeVariablesFromLazyFunction(JSFunction* fun, ParseContext<ParseHandler>* pc);
801 
802     bool isValidForStatementLHS(Node pn1, JSVersion version, bool forDecl, bool forEach,
803                                 ParseNodeKind headKind);
804     bool checkForHeadConstInitializers(Node pn1);
805 
806     // Use when the current token is TOK_NAME and is known to be 'let'.
807     bool shouldParseLetDeclaration(bool* parseDeclOut);
808 
809     // Use when the lookahead token is TOK_NAME and is known to be 'let'. If a
810     // let declaration should be parsed, the TOK_NAME token of 'let' is
811     // consumed. Otherwise, the current token remains the TOK_NAME token of
812     // 'let'.
813     bool peekShouldParseLetDeclaration(bool* parseDeclOut, TokenStream::Modifier modifier);
814 
815   public:
816     enum FunctionCallBehavior {
817         PermitAssignmentToFunctionCalls,
818         ForbidAssignmentToFunctionCalls
819     };
820 
821     bool isValidSimpleAssignmentTarget(Node node,
822                                        FunctionCallBehavior behavior = ForbidAssignmentToFunctionCalls);
823 
824   private:
825     bool reportIfArgumentsEvalTarget(Node nameNode);
826     bool reportIfNotValidSimpleAssignmentTarget(Node target, AssignmentFlavor flavor);
827 
828     bool checkAndMarkAsIncOperand(Node kid, AssignmentFlavor flavor);
829 
830     bool checkStrictAssignment(Node lhs);
831 
832     bool checkStrictBinding(PropertyName* name, Node pn);
833     bool defineArg(Node funcpn, HandlePropertyName name,
834                    bool disallowDuplicateArgs = false, Node* duplicatedArg = nullptr);
835     Node pushLexicalScope(AutoPushStmtInfoPC& stmt);
836     Node pushLexicalScope(Handle<StaticBlockObject*> blockObj, AutoPushStmtInfoPC& stmt);
837     Node pushLetScope(Handle<StaticBlockObject*> blockObj, AutoPushStmtInfoPC& stmt);
838     bool noteNameUse(HandlePropertyName name, Node pn);
839     Node propertyName(YieldHandling yieldHandling, Node propList,
840                       PropertyType* propType, MutableHandleAtom propAtom);
841     Node computedPropertyName(YieldHandling yieldHandling, Node literal);
842     Node arrayInitializer(YieldHandling yieldHandling);
843     Node newRegExp();
844 
845     Node objectLiteral(YieldHandling yieldHandling);
846 
847     bool checkAndPrepareLexical(bool isConst, const TokenPos& errorPos);
848     Node makeInitializedLexicalBinding(HandlePropertyName name, bool isConst, const TokenPos& pos);
849 
850     Node newBindingNode(PropertyName* name, bool functionScope, VarContext varContext = HoistVars);
851 
852     // Top-level entrypoint into destructuring pattern checking/name-analyzing.
853     bool checkDestructuringPattern(BindData<ParseHandler>* data, Node pattern);
854 
855     // Recursive methods for checking/name-analyzing subcomponents of a
856     // destructuring pattern.  The array/object methods *must* be passed arrays
857     // or objects.  The name method may be passed anything but will report an
858     // error if not passed a name.
859     bool checkDestructuringArray(BindData<ParseHandler>* data, Node arrayPattern);
860     bool checkDestructuringObject(BindData<ParseHandler>* data, Node objectPattern);
861     bool checkDestructuringName(BindData<ParseHandler>* data, Node expr);
862 
863     bool bindInitialized(BindData<ParseHandler>* data, Node pn);
864     bool bindUninitialized(BindData<ParseHandler>* data, Node pn);
865     bool makeSetCall(Node node, unsigned errnum);
866     Node cloneDestructuringDefault(Node opn);
867     Node cloneLeftHandSide(Node opn);
868     Node cloneParseTree(Node opn);
869 
newNumber(const Token & tok)870     Node newNumber(const Token& tok) {
871         return handler.newNumber(tok.number(), tok.decimalPoint(), tok.pos);
872     }
873 
874     static bool
875     bindDestructuringArg(BindData<ParseHandler>* data,
876                          HandlePropertyName name, Parser<ParseHandler>* parser);
877 
878     static bool
879     bindLexical(BindData<ParseHandler>* data,
880                 HandlePropertyName name, Parser<ParseHandler>* parser);
881 
882     static bool
883     bindVar(BindData<ParseHandler>* data,
884             HandlePropertyName name, Parser<ParseHandler>* parser);
885 
null()886     static Node null() { return ParseHandler::null(); }
887 
888     bool reportRedeclaration(Node pn, Definition::Kind redeclKind, HandlePropertyName name);
889     bool reportBadReturn(Node pn, ParseReportKind kind, unsigned errnum, unsigned anonerrnum);
890     DefinitionNode getOrCreateLexicalDependency(ParseContext<ParseHandler>* pc, JSAtom* atom);
891 
892     bool leaveFunction(Node fn, ParseContext<ParseHandler>* outerpc,
893                        FunctionSyntaxKind kind = Expression);
894 
pos()895     TokenPos pos() const { return tokenStream.currentToken().pos; }
896 
897     bool asmJS(Node list);
898 
899     void addTelemetry(JSCompartment::DeprecatedLanguageExtension e);
900 
901     bool warnOnceAboutExprClosure();
902 
903     friend class LegacyCompExprTransplanter;
904     friend struct BindData<ParseHandler>;
905 };
906 
907 } /* namespace frontend */
908 } /* namespace js */
909 
910 /*
911  * Convenience macro to access Parser.tokenStream as a pointer.
912  */
913 #define TS(p) (&(p)->tokenStream)
914 
915 #endif /* frontend_Parser_h */
916