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 #ifndef frontend_FullParseHandler_h
8 #define frontend_FullParseHandler_h
9 
10 #include "mozilla/Attributes.h"
11 #include "mozilla/PodOperations.h"
12 
13 #include <cstddef>  // std::nullptr_t
14 #include <string.h>
15 
16 #include "frontend/FunctionSyntaxKind.h"  // FunctionSyntaxKind
17 #include "frontend/ParseNode.h"
18 #include "frontend/SharedContext.h"
19 #include "frontend/Stencil.h"
20 #include "vm/JSContext.h"
21 
22 namespace js {
23 
24 class RegExpObject;
25 
26 namespace frontend {
27 
28 class TokenStreamAnyChars;
29 
30 enum class SourceKind {
31   // We are parsing from a text source (Parser.h)
32   Text,
33   // We are parsing from a binary source (BinASTParser.h)
34   Binary,
35 };
36 
37 // Parse handler used when generating a full parse tree for all code which the
38 // parser encounters.
39 class FullParseHandler {
40   ParseNodeAllocator allocator;
41 
allocParseNode(size_t size)42   ParseNode* allocParseNode(size_t size) {
43     return static_cast<ParseNode*>(allocator.allocNode(size));
44   }
45 
46   /*
47    * If this is a full parse to construct the bytecode for a function that
48    * was previously lazily parsed, we still don't want to full parse the
49    * inner functions. These members are used for this functionality:
50    *
51    * - lazyOuterFunction_ holds the lazyScript for this current parse
52    * - lazyInnerFunctionIndex is used as we skip over inner functions
53    *   (see skipLazyInnerFunction),
54    */
55   const Rooted<BaseScript*> lazyOuterFunction_;
56   size_t lazyInnerFunctionIndex;
57 
58   size_t lazyClosedOverBindingIndex;
59 
60   const SourceKind sourceKind_;
61 
62  public:
63   /* new_ methods for creating parse nodes. These report OOM on context. */
64   JS_DECLARE_NEW_METHODS(new_, allocParseNode, inline)
65 
66   // FIXME: Use ListNode instead of ListNodeType as an alias (bug 1489008).
67   using Node = ParseNode*;
68 
69 #define DECLARE_TYPE(typeName, longTypeName, asMethodName) \
70   using longTypeName = typeName*;
71   FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
72 #undef DECLARE_TYPE
73 
74   using NullNode = std::nullptr_t;
75 
isPropertyAccess(Node node)76   bool isPropertyAccess(Node node) {
77     return node->isKind(ParseNodeKind::DotExpr) ||
78            node->isKind(ParseNodeKind::ElemExpr);
79   }
80 
isOptionalPropertyAccess(Node node)81   bool isOptionalPropertyAccess(Node node) {
82     return node->isKind(ParseNodeKind::OptionalDotExpr) ||
83            node->isKind(ParseNodeKind::OptionalElemExpr);
84   }
85 
isFunctionCall(Node node)86   bool isFunctionCall(Node node) {
87     // Note: super() is a special form, *not* a function call.
88     return node->isKind(ParseNodeKind::CallExpr);
89   }
90 
isUnparenthesizedDestructuringPattern(Node node)91   static bool isUnparenthesizedDestructuringPattern(Node node) {
92     return !node->isInParens() && (node->isKind(ParseNodeKind::ObjectExpr) ||
93                                    node->isKind(ParseNodeKind::ArrayExpr));
94   }
95 
isParenthesizedDestructuringPattern(Node node)96   static bool isParenthesizedDestructuringPattern(Node node) {
97     // Technically this isn't a destructuring pattern at all -- the grammar
98     // doesn't treat it as such.  But we need to know when this happens to
99     // consider it a SyntaxError rather than an invalid-left-hand-side
100     // ReferenceError.
101     return node->isInParens() && (node->isKind(ParseNodeKind::ObjectExpr) ||
102                                   node->isKind(ParseNodeKind::ArrayExpr));
103   }
104 
105   FullParseHandler(JSContext* cx, LifoAlloc& alloc,
106                    BaseScript* lazyOuterFunction,
107                    SourceKind kind = SourceKind::Text)
allocator(cx,alloc)108       : allocator(cx, alloc),
109         lazyOuterFunction_(cx, lazyOuterFunction),
110         lazyInnerFunctionIndex(0),
111         lazyClosedOverBindingIndex(0),
112         sourceKind_(kind) {
113     // The BaseScript::gcthings() array contains the inner function list
114     // followed by the closed-over bindings data. Advance the index for
115     // closed-over bindings to the end of the inner functions. The
116     // nextLazyInnerFunction / nextLazyClosedOverBinding accessors confirm we
117     // have the expected types. See also: BaseScript::CreateLazy.
118     if (lazyOuterFunction) {
119       for (JS::GCCellPtr gcThing : lazyOuterFunction->gcthings()) {
120         if (gcThing.is<JSObject>()) {
121           lazyClosedOverBindingIndex++;
122         } else {
123           break;
124         }
125       }
126     }
127   }
128 
null()129   static NullNode null() { return NullNode(); }
130 
131 #define DECLARE_AS(typeName, longTypeName, asMethodName) \
132   static longTypeName asMethodName(Node node) { return &node->as<typeName>(); }
FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)133   FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
134 #undef DECLARE_AS
135 
136   // The FullParseHandler may be used to create nodes for text sources
137   // (from Parser.h) or for binary sources (from BinASTParser.h). In the latter
138   // case, some common assumptions on offsets are incorrect, e.g. in `a + b`,
139   // `a`, `b` and `+` may be stored in any order. We use `sourceKind()`
140   // to determine whether we need to check these assumptions.
141   SourceKind sourceKind() const { return sourceKind_; }
142 
newName(PropertyName * name,const TokenPos & pos,JSContext * cx)143   NameNodeType newName(PropertyName* name, const TokenPos& pos, JSContext* cx) {
144     return new_<NameNode>(ParseNodeKind::Name, name, pos);
145   }
146 
newComputedName(Node expr,uint32_t begin,uint32_t end)147   UnaryNodeType newComputedName(Node expr, uint32_t begin, uint32_t end) {
148     TokenPos pos(begin, end);
149     return new_<UnaryNode>(ParseNodeKind::ComputedName, pos, expr);
150   }
151 
newObjectLiteralPropertyName(JSAtom * atom,const TokenPos & pos)152   NameNodeType newObjectLiteralPropertyName(JSAtom* atom, const TokenPos& pos) {
153     return new_<NameNode>(ParseNodeKind::ObjectPropertyName, atom, pos);
154   }
155 
newNumber(double value,DecimalPoint decimalPoint,const TokenPos & pos)156   NumericLiteralType newNumber(double value, DecimalPoint decimalPoint,
157                                const TokenPos& pos) {
158     return new_<NumericLiteral>(value, decimalPoint, pos);
159   }
160 
newBigInt(BigIntIndex index,CompilationInfo & compilationInfo,const TokenPos & pos)161   BigIntLiteralType newBigInt(BigIntIndex index,
162                               CompilationInfo& compilationInfo,
163                               const TokenPos& pos) {
164     return new_<BigIntLiteral>(index, compilationInfo, pos);
165   }
166 
newBooleanLiteral(bool cond,const TokenPos & pos)167   BooleanLiteralType newBooleanLiteral(bool cond, const TokenPos& pos) {
168     return new_<BooleanLiteral>(cond, pos);
169   }
170 
newStringLiteral(JSAtom * atom,const TokenPos & pos)171   NameNodeType newStringLiteral(JSAtom* atom, const TokenPos& pos) {
172     return new_<NameNode>(ParseNodeKind::StringExpr, atom, pos);
173   }
174 
newTemplateStringLiteral(JSAtom * atom,const TokenPos & pos)175   NameNodeType newTemplateStringLiteral(JSAtom* atom, const TokenPos& pos) {
176     return new_<NameNode>(ParseNodeKind::TemplateStringExpr, atom, pos);
177   }
178 
newCallSiteObject(uint32_t begin)179   CallSiteNodeType newCallSiteObject(uint32_t begin) {
180     CallSiteNode* callSiteObj = new_<CallSiteNode>(begin);
181     if (!callSiteObj) {
182       return null();
183     }
184 
185     ListNode* rawNodes = newArrayLiteral(callSiteObj->pn_pos.begin);
186     if (!rawNodes) {
187       return null();
188     }
189 
190     addArrayElement(callSiteObj, rawNodes);
191 
192     return callSiteObj;
193   }
194 
addToCallSiteObject(CallSiteNodeType callSiteObj,Node rawNode,Node cookedNode)195   void addToCallSiteObject(CallSiteNodeType callSiteObj, Node rawNode,
196                            Node cookedNode) {
197     MOZ_ASSERT(callSiteObj->isKind(ParseNodeKind::CallSiteObj));
198     MOZ_ASSERT(rawNode->isKind(ParseNodeKind::TemplateStringExpr));
199     MOZ_ASSERT(cookedNode->isKind(ParseNodeKind::TemplateStringExpr) ||
200                cookedNode->isKind(ParseNodeKind::RawUndefinedExpr));
201 
202     addArrayElement(callSiteObj, cookedNode);
203     addArrayElement(callSiteObj->rawNodes(), rawNode);
204 
205     /*
206      * We don't know when the last noSubstTemplate will come in, and we
207      * don't want to deal with this outside this method
208      */
209     setEndPosition(callSiteObj, callSiteObj->rawNodes());
210   }
211 
newThisLiteral(const TokenPos & pos,Node thisName)212   ThisLiteralType newThisLiteral(const TokenPos& pos, Node thisName) {
213     return new_<ThisLiteral>(pos, thisName);
214   }
215 
newNullLiteral(const TokenPos & pos)216   NullLiteralType newNullLiteral(const TokenPos& pos) {
217     return new_<NullLiteral>(pos);
218   }
219 
newRawUndefinedLiteral(const TokenPos & pos)220   RawUndefinedLiteralType newRawUndefinedLiteral(const TokenPos& pos) {
221     return new_<RawUndefinedLiteral>(pos);
222   }
223 
newRegExp(RegExpIndex index,const TokenPos & pos)224   RegExpLiteralType newRegExp(RegExpIndex index, const TokenPos& pos) {
225     return new_<RegExpLiteral>(index, pos);
226   }
227 
newConditional(Node cond,Node thenExpr,Node elseExpr)228   ConditionalExpressionType newConditional(Node cond, Node thenExpr,
229                                            Node elseExpr) {
230     return new_<ConditionalExpression>(cond, thenExpr, elseExpr);
231   }
232 
newDelete(uint32_t begin,Node expr)233   UnaryNodeType newDelete(uint32_t begin, Node expr) {
234     if (expr->isKind(ParseNodeKind::Name)) {
235       return newUnary(ParseNodeKind::DeleteNameExpr, begin, expr);
236     }
237 
238     if (expr->isKind(ParseNodeKind::DotExpr)) {
239       return newUnary(ParseNodeKind::DeletePropExpr, begin, expr);
240     }
241 
242     if (expr->isKind(ParseNodeKind::ElemExpr)) {
243       return newUnary(ParseNodeKind::DeleteElemExpr, begin, expr);
244     }
245 
246     if (expr->isKind(ParseNodeKind::OptionalChain)) {
247       Node kid = expr->as<UnaryNode>().kid();
248       // Handle property deletion explicitly. OptionalCall is handled
249       // via DeleteExpr.
250       if (kid->isKind(ParseNodeKind::DotExpr) ||
251           kid->isKind(ParseNodeKind::OptionalDotExpr) ||
252           kid->isKind(ParseNodeKind::ElemExpr) ||
253           kid->isKind(ParseNodeKind::OptionalElemExpr)) {
254         return newUnary(ParseNodeKind::DeleteOptionalChainExpr, begin, kid);
255       }
256     }
257 
258     return newUnary(ParseNodeKind::DeleteExpr, begin, expr);
259   }
260 
newTypeof(uint32_t begin,Node kid)261   UnaryNodeType newTypeof(uint32_t begin, Node kid) {
262     ParseNodeKind pnk = kid->isKind(ParseNodeKind::Name)
263                             ? ParseNodeKind::TypeOfNameExpr
264                             : ParseNodeKind::TypeOfExpr;
265     return newUnary(pnk, begin, kid);
266   }
267 
newUnary(ParseNodeKind kind,uint32_t begin,Node kid)268   UnaryNodeType newUnary(ParseNodeKind kind, uint32_t begin, Node kid) {
269     TokenPos pos(begin, kid->pn_pos.end);
270     return new_<UnaryNode>(kind, pos, kid);
271   }
272 
newUpdate(ParseNodeKind kind,uint32_t begin,Node kid)273   UnaryNodeType newUpdate(ParseNodeKind kind, uint32_t begin, Node kid) {
274     TokenPos pos(begin, kid->pn_pos.end);
275     return new_<UnaryNode>(kind, pos, kid);
276   }
277 
newSpread(uint32_t begin,Node kid)278   UnaryNodeType newSpread(uint32_t begin, Node kid) {
279     TokenPos pos(begin, kid->pn_pos.end);
280     return new_<UnaryNode>(ParseNodeKind::Spread, pos, kid);
281   }
282 
283  private:
newBinary(ParseNodeKind kind,Node left,Node right)284   BinaryNodeType newBinary(ParseNodeKind kind, Node left, Node right) {
285     TokenPos pos(left->pn_pos.begin, right->pn_pos.end);
286     return new_<BinaryNode>(kind, pos, left, right);
287   }
288 
289  public:
appendOrCreateList(ParseNodeKind kind,Node left,Node right,ParseContext * pc)290   Node appendOrCreateList(ParseNodeKind kind, Node left, Node right,
291                           ParseContext* pc) {
292     return ParseNode::appendOrCreateList(kind, left, right, this, pc);
293   }
294 
295   // Expressions
296 
newArrayLiteral(uint32_t begin)297   ListNodeType newArrayLiteral(uint32_t begin) {
298     return new_<ListNode>(ParseNodeKind::ArrayExpr, TokenPos(begin, begin + 1));
299   }
300 
addElision(ListNodeType literal,const TokenPos & pos)301   MOZ_MUST_USE bool addElision(ListNodeType literal, const TokenPos& pos) {
302     MOZ_ASSERT(literal->isKind(ParseNodeKind::ArrayExpr));
303 
304     NullaryNode* elision = new_<NullaryNode>(ParseNodeKind::Elision, pos);
305     if (!elision) {
306       return false;
307     }
308     addList(/* list = */ literal, /* kid = */ elision);
309     literal->setHasArrayHoleOrSpread();
310     literal->setHasNonConstInitializer();
311     return true;
312   }
313 
addSpreadElement(ListNodeType literal,uint32_t begin,Node inner)314   MOZ_MUST_USE bool addSpreadElement(ListNodeType literal, uint32_t begin,
315                                      Node inner) {
316     MOZ_ASSERT(literal->isKind(ParseNodeKind::ArrayExpr));
317 
318     UnaryNodeType spread = newSpread(begin, inner);
319     if (!spread) {
320       return false;
321     }
322     addList(/* list = */ literal, /* kid = */ spread);
323     literal->setHasArrayHoleOrSpread();
324     literal->setHasNonConstInitializer();
325     return true;
326   }
327 
addArrayElement(ListNodeType literal,Node element)328   void addArrayElement(ListNodeType literal, Node element) {
329     if (!element->isConstant()) {
330       literal->setHasNonConstInitializer();
331     }
332     addList(/* list = */ literal, /* kid = */ element);
333   }
334 
newCall(Node callee,Node args,JSOp callOp)335   CallNodeType newCall(Node callee, Node args, JSOp callOp) {
336     return new_<CallNode>(ParseNodeKind::CallExpr, callOp, callee, args);
337   }
338 
newOptionalCall(Node callee,Node args,JSOp callOp)339   OptionalCallNodeType newOptionalCall(Node callee, Node args, JSOp callOp) {
340     return new_<CallNode>(ParseNodeKind::OptionalCallExpr, callOp, callee,
341                           args);
342   }
343 
newArguments(const TokenPos & pos)344   ListNodeType newArguments(const TokenPos& pos) {
345     return new_<ListNode>(ParseNodeKind::Arguments, pos);
346   }
347 
newSuperCall(Node callee,Node args,bool isSpread)348   CallNodeType newSuperCall(Node callee, Node args, bool isSpread) {
349     return new_<CallNode>(ParseNodeKind::SuperCallExpr,
350                           isSpread ? JSOp::SpreadSuperCall : JSOp::SuperCall,
351                           callee, args);
352   }
353 
newTaggedTemplate(Node tag,Node args,JSOp callOp)354   CallNodeType newTaggedTemplate(Node tag, Node args, JSOp callOp) {
355     return new_<CallNode>(ParseNodeKind::TaggedTemplateExpr, callOp, tag, args);
356   }
357 
newObjectLiteral(uint32_t begin)358   ListNodeType newObjectLiteral(uint32_t begin) {
359     return new_<ListNode>(ParseNodeKind::ObjectExpr,
360                           TokenPos(begin, begin + 1));
361   }
362 
newClass(Node name,Node heritage,LexicalScopeNodeType memberBlock,const TokenPos & pos)363   ClassNodeType newClass(Node name, Node heritage,
364                          LexicalScopeNodeType memberBlock,
365                          const TokenPos& pos) {
366     return new_<ClassNode>(name, heritage, memberBlock, pos);
367   }
newClassMemberList(uint32_t begin)368   ListNodeType newClassMemberList(uint32_t begin) {
369     return new_<ListNode>(ParseNodeKind::ClassMemberList,
370                           TokenPos(begin, begin + 1));
371   }
newClassNames(Node outer,Node inner,const TokenPos & pos)372   ClassNamesType newClassNames(Node outer, Node inner, const TokenPos& pos) {
373     return new_<ClassNames>(outer, inner, pos);
374   }
newNewTarget(NullaryNodeType newHolder,NullaryNodeType targetHolder)375   BinaryNodeType newNewTarget(NullaryNodeType newHolder,
376                               NullaryNodeType targetHolder) {
377     return new_<BinaryNode>(ParseNodeKind::NewTargetExpr, newHolder,
378                             targetHolder);
379   }
newPosHolder(const TokenPos & pos)380   NullaryNodeType newPosHolder(const TokenPos& pos) {
381     return new_<NullaryNode>(ParseNodeKind::PosHolder, pos);
382   }
newSuperBase(Node thisName,const TokenPos & pos)383   UnaryNodeType newSuperBase(Node thisName, const TokenPos& pos) {
384     return new_<UnaryNode>(ParseNodeKind::SuperBase, pos, thisName);
385   }
addPrototypeMutation(ListNodeType literal,uint32_t begin,Node expr)386   MOZ_MUST_USE bool addPrototypeMutation(ListNodeType literal, uint32_t begin,
387                                          Node expr) {
388     MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr));
389 
390     // Object literals with mutated [[Prototype]] are non-constant so that
391     // singleton objects will have Object.prototype as their [[Prototype]].
392     literal->setHasNonConstInitializer();
393 
394     UnaryNode* mutation = newUnary(ParseNodeKind::MutateProto, begin, expr);
395     if (!mutation) {
396       return false;
397     }
398     addList(/* list = */ literal, /* kid = */ mutation);
399     return true;
400   }
401 
newPropertyDefinition(Node key,Node val)402   BinaryNodeType newPropertyDefinition(Node key, Node val) {
403     MOZ_ASSERT(isUsableAsObjectPropertyName(key));
404     checkAndSetIsDirectRHSAnonFunction(val);
405     return new_<PropertyDefinition>(key, val, AccessorType::None);
406   }
407 
addPropertyDefinition(ListNodeType literal,BinaryNodeType propdef)408   void addPropertyDefinition(ListNodeType literal, BinaryNodeType propdef) {
409     MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr));
410     MOZ_ASSERT(propdef->isKind(ParseNodeKind::PropertyDefinition));
411 
412     if (!propdef->right()->isConstant()) {
413       literal->setHasNonConstInitializer();
414     }
415 
416     addList(/* list = */ literal, /* kid = */ propdef);
417   }
418 
addPropertyDefinition(ListNodeType literal,Node key,Node val)419   MOZ_MUST_USE bool addPropertyDefinition(ListNodeType literal, Node key,
420                                           Node val) {
421     BinaryNode* propdef = newPropertyDefinition(key, val);
422     if (!propdef) {
423       return false;
424     }
425     addPropertyDefinition(literal, propdef);
426     return true;
427   }
428 
addShorthand(ListNodeType literal,NameNodeType name,NameNodeType expr)429   MOZ_MUST_USE bool addShorthand(ListNodeType literal, NameNodeType name,
430                                  NameNodeType expr) {
431     MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr));
432     MOZ_ASSERT(name->isKind(ParseNodeKind::ObjectPropertyName));
433     MOZ_ASSERT(expr->isKind(ParseNodeKind::Name));
434     MOZ_ASSERT(name->atom() == expr->atom());
435 
436     literal->setHasNonConstInitializer();
437     BinaryNode* propdef = newBinary(ParseNodeKind::Shorthand, name, expr);
438     if (!propdef) {
439       return false;
440     }
441     addList(/* list = */ literal, /* kid = */ propdef);
442     return true;
443   }
444 
addSpreadProperty(ListNodeType literal,uint32_t begin,Node inner)445   MOZ_MUST_USE bool addSpreadProperty(ListNodeType literal, uint32_t begin,
446                                       Node inner) {
447     MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr));
448 
449     literal->setHasNonConstInitializer();
450     ParseNode* spread = newSpread(begin, inner);
451     if (!spread) {
452       return false;
453     }
454     addList(/* list = */ literal, /* kid = */ spread);
455     return true;
456   }
457 
addObjectMethodDefinition(ListNodeType literal,Node key,FunctionNodeType funNode,AccessorType atype)458   MOZ_MUST_USE bool addObjectMethodDefinition(ListNodeType literal, Node key,
459                                               FunctionNodeType funNode,
460                                               AccessorType atype) {
461     literal->setHasNonConstInitializer();
462 
463     checkAndSetIsDirectRHSAnonFunction(funNode);
464 
465     ParseNode* propdef =
466         newObjectMethodOrPropertyDefinition(key, funNode, atype);
467     if (!propdef) {
468       return false;
469     }
470 
471     addList(/* list = */ literal, /* kid = */ propdef);
472     return true;
473   }
474 
newClassMethodDefinition(Node key,FunctionNodeType funNode,AccessorType atype,bool isStatic)475   MOZ_MUST_USE ClassMethod* newClassMethodDefinition(Node key,
476                                                      FunctionNodeType funNode,
477                                                      AccessorType atype,
478                                                      bool isStatic) {
479     MOZ_ASSERT(isUsableAsObjectPropertyName(key));
480 
481     checkAndSetIsDirectRHSAnonFunction(funNode);
482 
483     return new_<ClassMethod>(key, funNode, atype, isStatic);
484   }
485 
newClassFieldDefinition(Node name,FunctionNodeType initializer,bool isStatic)486   MOZ_MUST_USE ClassField* newClassFieldDefinition(Node name,
487                                                    FunctionNodeType initializer,
488                                                    bool isStatic) {
489     MOZ_ASSERT(isUsableAsObjectPropertyName(name));
490 
491     return new_<ClassField>(name, initializer, isStatic);
492   }
493 
addClassMemberDefinition(ListNodeType memberList,Node member)494   MOZ_MUST_USE bool addClassMemberDefinition(ListNodeType memberList,
495                                              Node member) {
496     MOZ_ASSERT(memberList->isKind(ParseNodeKind::ClassMemberList));
497     // Constructors can be surrounded by LexicalScopes.
498     MOZ_ASSERT(member->isKind(ParseNodeKind::ClassMethod) ||
499                member->isKind(ParseNodeKind::ClassField) ||
500                (member->isKind(ParseNodeKind::LexicalScope) &&
501                 member->as<LexicalScopeNode>().scopeBody()->isKind(
502                     ParseNodeKind::ClassMethod)));
503 
504     addList(/* list = */ memberList, /* kid = */ member);
505     return true;
506   }
507 
newInitialYieldExpression(uint32_t begin,Node gen)508   UnaryNodeType newInitialYieldExpression(uint32_t begin, Node gen) {
509     TokenPos pos(begin, begin + 1);
510     return new_<UnaryNode>(ParseNodeKind::InitialYield, pos, gen);
511   }
512 
newYieldExpression(uint32_t begin,Node value)513   UnaryNodeType newYieldExpression(uint32_t begin, Node value) {
514     TokenPos pos(begin, value ? value->pn_pos.end : begin + 1);
515     return new_<UnaryNode>(ParseNodeKind::YieldExpr, pos, value);
516   }
517 
newYieldStarExpression(uint32_t begin,Node value)518   UnaryNodeType newYieldStarExpression(uint32_t begin, Node value) {
519     TokenPos pos(begin, value->pn_pos.end);
520     return new_<UnaryNode>(ParseNodeKind::YieldStarExpr, pos, value);
521   }
522 
newAwaitExpression(uint32_t begin,Node value)523   UnaryNodeType newAwaitExpression(uint32_t begin, Node value) {
524     TokenPos pos(begin, value ? value->pn_pos.end : begin + 1);
525     return new_<UnaryNode>(ParseNodeKind::AwaitExpr, pos, value);
526   }
527 
newOptionalChain(uint32_t begin,Node value)528   UnaryNodeType newOptionalChain(uint32_t begin, Node value) {
529     TokenPos pos(begin, value->pn_pos.end);
530     return new_<UnaryNode>(ParseNodeKind::OptionalChain, pos, value);
531   }
532 
533   // Statements
534 
newStatementList(const TokenPos & pos)535   ListNodeType newStatementList(const TokenPos& pos) {
536     return new_<ListNode>(ParseNodeKind::StatementList, pos);
537   }
538 
isFunctionStmt(Node stmt)539   MOZ_MUST_USE bool isFunctionStmt(Node stmt) {
540     while (stmt->isKind(ParseNodeKind::LabelStmt)) {
541       stmt = stmt->as<LabeledStatement>().statement();
542     }
543     return stmt->is<FunctionNode>();
544   }
545 
addStatementToList(ListNodeType list,Node stmt)546   void addStatementToList(ListNodeType list, Node stmt) {
547     MOZ_ASSERT(list->isKind(ParseNodeKind::StatementList));
548 
549     addList(/* list = */ list, /* kid = */ stmt);
550 
551     if (isFunctionStmt(stmt)) {
552       // Notify the emitter that the block contains body-level function
553       // definitions that should be processed before the rest of nodes.
554       list->setHasTopLevelFunctionDeclarations();
555     }
556   }
557 
setListEndPosition(ListNodeType list,const TokenPos & pos)558   void setListEndPosition(ListNodeType list, const TokenPos& pos) {
559     MOZ_ASSERT(list->isKind(ParseNodeKind::StatementList));
560     list->pn_pos.end = pos.end;
561   }
562 
addCaseStatementToList(ListNodeType list,CaseClauseType caseClause)563   void addCaseStatementToList(ListNodeType list, CaseClauseType caseClause) {
564     MOZ_ASSERT(list->isKind(ParseNodeKind::StatementList));
565 
566     addList(/* list = */ list, /* kid = */ caseClause);
567 
568     if (caseClause->statementList()->hasTopLevelFunctionDeclarations()) {
569       list->setHasTopLevelFunctionDeclarations();
570     }
571   }
572 
prependInitialYield(ListNodeType stmtList,Node genName)573   MOZ_MUST_USE bool prependInitialYield(ListNodeType stmtList, Node genName) {
574     MOZ_ASSERT(stmtList->isKind(ParseNodeKind::StatementList));
575 
576     TokenPos yieldPos(stmtList->pn_pos.begin, stmtList->pn_pos.begin + 1);
577     NullaryNode* makeGen =
578         new_<NullaryNode>(ParseNodeKind::Generator, yieldPos);
579     if (!makeGen) {
580       return false;
581     }
582 
583     ParseNode* genInit =
584         newAssignment(ParseNodeKind::AssignExpr, /* lhs = */ genName,
585                       /* rhs = */ makeGen);
586     if (!genInit) {
587       return false;
588     }
589 
590     UnaryNode* initialYield =
591         newInitialYieldExpression(yieldPos.begin, genInit);
592     if (!initialYield) {
593       return false;
594     }
595 
596     stmtList->prepend(initialYield);
597     return true;
598   }
599 
newSetThis(Node thisName,Node value)600   BinaryNodeType newSetThis(Node thisName, Node value) {
601     return newBinary(ParseNodeKind::SetThis, thisName, value);
602   }
603 
newEmptyStatement(const TokenPos & pos)604   NullaryNodeType newEmptyStatement(const TokenPos& pos) {
605     return new_<NullaryNode>(ParseNodeKind::EmptyStmt, pos);
606   }
607 
newImportDeclaration(Node importSpecSet,Node moduleSpec,const TokenPos & pos)608   BinaryNodeType newImportDeclaration(Node importSpecSet, Node moduleSpec,
609                                       const TokenPos& pos) {
610     return new_<BinaryNode>(ParseNodeKind::ImportDecl, pos, importSpecSet,
611                             moduleSpec);
612   }
613 
newImportSpec(Node importNameNode,Node bindingName)614   BinaryNodeType newImportSpec(Node importNameNode, Node bindingName) {
615     return newBinary(ParseNodeKind::ImportSpec, importNameNode, bindingName);
616   }
617 
newExportDeclaration(Node kid,const TokenPos & pos)618   UnaryNodeType newExportDeclaration(Node kid, const TokenPos& pos) {
619     return new_<UnaryNode>(ParseNodeKind::ExportStmt, pos, kid);
620   }
621 
newExportFromDeclaration(uint32_t begin,Node exportSpecSet,Node moduleSpec)622   BinaryNodeType newExportFromDeclaration(uint32_t begin, Node exportSpecSet,
623                                           Node moduleSpec) {
624     BinaryNode* decl = new_<BinaryNode>(ParseNodeKind::ExportFromStmt,
625                                         exportSpecSet, moduleSpec);
626     if (!decl) {
627       return nullptr;
628     }
629     decl->pn_pos.begin = begin;
630     return decl;
631   }
632 
newExportDefaultDeclaration(Node kid,Node maybeBinding,const TokenPos & pos)633   BinaryNodeType newExportDefaultDeclaration(Node kid, Node maybeBinding,
634                                              const TokenPos& pos) {
635     if (maybeBinding) {
636       MOZ_ASSERT(maybeBinding->isKind(ParseNodeKind::Name));
637       MOZ_ASSERT(!maybeBinding->isInParens());
638 
639       checkAndSetIsDirectRHSAnonFunction(kid);
640     }
641 
642     return new_<BinaryNode>(ParseNodeKind::ExportDefaultStmt, pos, kid,
643                             maybeBinding);
644   }
645 
newExportSpec(Node bindingName,Node exportName)646   BinaryNodeType newExportSpec(Node bindingName, Node exportName) {
647     return newBinary(ParseNodeKind::ExportSpec, bindingName, exportName);
648   }
649 
newExportBatchSpec(const TokenPos & pos)650   NullaryNodeType newExportBatchSpec(const TokenPos& pos) {
651     return new_<NullaryNode>(ParseNodeKind::ExportBatchSpecStmt, pos);
652   }
653 
newImportMeta(NullaryNodeType importHolder,NullaryNodeType metaHolder)654   BinaryNodeType newImportMeta(NullaryNodeType importHolder,
655                                NullaryNodeType metaHolder) {
656     return new_<BinaryNode>(ParseNodeKind::ImportMetaExpr, importHolder,
657                             metaHolder);
658   }
659 
newCallImport(NullaryNodeType importHolder,Node singleArg)660   BinaryNodeType newCallImport(NullaryNodeType importHolder, Node singleArg) {
661     return new_<BinaryNode>(ParseNodeKind::CallImportExpr, importHolder,
662                             singleArg);
663   }
664 
newExprStatement(Node expr,uint32_t end)665   UnaryNodeType newExprStatement(Node expr, uint32_t end) {
666     MOZ_ASSERT_IF(sourceKind() == SourceKind::Text, expr->pn_pos.end <= end);
667     return new_<UnaryNode>(ParseNodeKind::ExpressionStmt,
668                            TokenPos(expr->pn_pos.begin, end), expr);
669   }
670 
newExprStatement(Node expr)671   UnaryNodeType newExprStatement(Node expr) {
672     return newExprStatement(expr, expr->pn_pos.end);
673   }
674 
newIfStatement(uint32_t begin,Node cond,Node thenBranch,Node elseBranch)675   TernaryNodeType newIfStatement(uint32_t begin, Node cond, Node thenBranch,
676                                  Node elseBranch) {
677     TernaryNode* node =
678         new_<TernaryNode>(ParseNodeKind::IfStmt, cond, thenBranch, elseBranch);
679     if (!node) {
680       return nullptr;
681     }
682     node->pn_pos.begin = begin;
683     return node;
684   }
685 
newDoWhileStatement(Node body,Node cond,const TokenPos & pos)686   BinaryNodeType newDoWhileStatement(Node body, Node cond,
687                                      const TokenPos& pos) {
688     return new_<BinaryNode>(ParseNodeKind::DoWhileStmt, pos, body, cond);
689   }
690 
newWhileStatement(uint32_t begin,Node cond,Node body)691   BinaryNodeType newWhileStatement(uint32_t begin, Node cond, Node body) {
692     TokenPos pos(begin, body->pn_pos.end);
693     return new_<BinaryNode>(ParseNodeKind::WhileStmt, pos, cond, body);
694   }
695 
newForStatement(uint32_t begin,TernaryNodeType forHead,Node body,unsigned iflags)696   ForNodeType newForStatement(uint32_t begin, TernaryNodeType forHead,
697                               Node body, unsigned iflags) {
698     return new_<ForNode>(TokenPos(begin, body->pn_pos.end), forHead, body,
699                          iflags);
700   }
701 
newForHead(Node init,Node test,Node update,const TokenPos & pos)702   TernaryNodeType newForHead(Node init, Node test, Node update,
703                              const TokenPos& pos) {
704     return new_<TernaryNode>(ParseNodeKind::ForHead, init, test, update, pos);
705   }
706 
newForInOrOfHead(ParseNodeKind kind,Node target,Node iteratedExpr,const TokenPos & pos)707   TernaryNodeType newForInOrOfHead(ParseNodeKind kind, Node target,
708                                    Node iteratedExpr, const TokenPos& pos) {
709     MOZ_ASSERT(kind == ParseNodeKind::ForIn || kind == ParseNodeKind::ForOf);
710     return new_<TernaryNode>(kind, target, nullptr, iteratedExpr, pos);
711   }
712 
newSwitchStatement(uint32_t begin,Node discriminant,LexicalScopeNodeType lexicalForCaseList,bool hasDefault)713   SwitchStatementType newSwitchStatement(
714       uint32_t begin, Node discriminant,
715       LexicalScopeNodeType lexicalForCaseList, bool hasDefault) {
716     return new_<SwitchStatement>(begin, discriminant, lexicalForCaseList,
717                                  hasDefault);
718   }
719 
newCaseOrDefault(uint32_t begin,Node expr,Node body)720   CaseClauseType newCaseOrDefault(uint32_t begin, Node expr, Node body) {
721     return new_<CaseClause>(expr, body, begin);
722   }
723 
newContinueStatement(PropertyName * label,const TokenPos & pos)724   ContinueStatementType newContinueStatement(PropertyName* label,
725                                              const TokenPos& pos) {
726     return new_<ContinueStatement>(label, pos);
727   }
728 
newBreakStatement(PropertyName * label,const TokenPos & pos)729   BreakStatementType newBreakStatement(PropertyName* label,
730                                        const TokenPos& pos) {
731     return new_<BreakStatement>(label, pos);
732   }
733 
newReturnStatement(Node expr,const TokenPos & pos)734   UnaryNodeType newReturnStatement(Node expr, const TokenPos& pos) {
735     MOZ_ASSERT_IF(expr && sourceKind() == SourceKind::Text,
736                   pos.encloses(expr->pn_pos));
737     return new_<UnaryNode>(ParseNodeKind::ReturnStmt, pos, expr);
738   }
739 
newExpressionBody(Node expr)740   UnaryNodeType newExpressionBody(Node expr) {
741     return new_<UnaryNode>(ParseNodeKind::ReturnStmt, expr->pn_pos, expr);
742   }
743 
newWithStatement(uint32_t begin,Node expr,Node body)744   BinaryNodeType newWithStatement(uint32_t begin, Node expr, Node body) {
745     return new_<BinaryNode>(ParseNodeKind::WithStmt,
746                             TokenPos(begin, body->pn_pos.end), expr, body);
747   }
748 
newLabeledStatement(PropertyName * label,Node stmt,uint32_t begin)749   LabeledStatementType newLabeledStatement(PropertyName* label, Node stmt,
750                                            uint32_t begin) {
751     return new_<LabeledStatement>(label, stmt, begin);
752   }
753 
newThrowStatement(Node expr,const TokenPos & pos)754   UnaryNodeType newThrowStatement(Node expr, const TokenPos& pos) {
755     MOZ_ASSERT_IF(sourceKind() == SourceKind::Text, pos.encloses(expr->pn_pos));
756     return new_<UnaryNode>(ParseNodeKind::ThrowStmt, pos, expr);
757   }
758 
newTryStatement(uint32_t begin,Node body,LexicalScopeNodeType catchScope,Node finallyBlock)759   TernaryNodeType newTryStatement(uint32_t begin, Node body,
760                                   LexicalScopeNodeType catchScope,
761                                   Node finallyBlock) {
762     return new_<TryNode>(begin, body, catchScope, finallyBlock);
763   }
764 
newDebuggerStatement(const TokenPos & pos)765   DebuggerStatementType newDebuggerStatement(const TokenPos& pos) {
766     return new_<DebuggerStatement>(pos);
767   }
768 
newPropertyName(PropertyName * name,const TokenPos & pos)769   NameNodeType newPropertyName(PropertyName* name, const TokenPos& pos) {
770     return new_<NameNode>(ParseNodeKind::PropertyNameExpr, name, pos);
771   }
772 
newPropertyAccess(Node expr,NameNodeType key)773   PropertyAccessType newPropertyAccess(Node expr, NameNodeType key) {
774     return new_<PropertyAccess>(expr, key, expr->pn_pos.begin, key->pn_pos.end);
775   }
776 
newPropertyByValue(Node lhs,Node index,uint32_t end)777   PropertyByValueType newPropertyByValue(Node lhs, Node index, uint32_t end) {
778     return new_<PropertyByValue>(lhs, index, lhs->pn_pos.begin, end);
779   }
780 
newOptionalPropertyAccess(Node expr,NameNodeType key)781   OptionalPropertyAccessType newOptionalPropertyAccess(Node expr,
782                                                        NameNodeType key) {
783     return new_<OptionalPropertyAccess>(expr, key, expr->pn_pos.begin,
784                                         key->pn_pos.end);
785   }
786 
newOptionalPropertyByValue(Node lhs,Node index,uint32_t end)787   OptionalPropertyByValueType newOptionalPropertyByValue(Node lhs, Node index,
788                                                          uint32_t end) {
789     return new_<OptionalPropertyByValue>(lhs, index, lhs->pn_pos.begin, end);
790   }
791 
setupCatchScope(LexicalScopeNodeType lexicalScope,Node catchName,Node catchBody)792   bool setupCatchScope(LexicalScopeNodeType lexicalScope, Node catchName,
793                        Node catchBody) {
794     BinaryNode* catchClause;
795     if (catchName) {
796       catchClause =
797           new_<BinaryNode>(ParseNodeKind::Catch, catchName, catchBody);
798     } else {
799       catchClause = new_<BinaryNode>(ParseNodeKind::Catch, catchBody->pn_pos,
800                                      catchName, catchBody);
801     }
802     if (!catchClause) {
803       return false;
804     }
805     lexicalScope->setScopeBody(catchClause);
806     return true;
807   }
808 
809   inline MOZ_MUST_USE bool setLastFunctionFormalParameterDefault(
810       FunctionNodeType funNode, Node defaultValue);
811 
checkAndSetIsDirectRHSAnonFunction(Node pn)812   void checkAndSetIsDirectRHSAnonFunction(Node pn) {
813     if (IsAnonymousFunctionDefinition(pn)) {
814       pn->setDirectRHSAnonFunction(true);
815     }
816   }
817 
newFunction(FunctionSyntaxKind syntaxKind,const TokenPos & pos)818   FunctionNodeType newFunction(FunctionSyntaxKind syntaxKind,
819                                const TokenPos& pos) {
820     return new_<FunctionNode>(syntaxKind, pos);
821   }
822 
newObjectMethodOrPropertyDefinition(Node key,Node value,AccessorType atype)823   BinaryNodeType newObjectMethodOrPropertyDefinition(Node key, Node value,
824                                                      AccessorType atype) {
825     MOZ_ASSERT(isUsableAsObjectPropertyName(key));
826 
827     return new_<PropertyDefinition>(key, value, atype);
828   }
829 
newShorthandPropertyDefinition(Node key,Node value)830   BinaryNodeType newShorthandPropertyDefinition(Node key, Node value) {
831     MOZ_ASSERT(isUsableAsObjectPropertyName(key));
832 
833     return newBinary(ParseNodeKind::Shorthand, key, value);
834   }
835 
newParamsBody(const TokenPos & pos)836   ListNodeType newParamsBody(const TokenPos& pos) {
837     return new_<ListNode>(ParseNodeKind::ParamsBody, pos);
838   }
839 
setFunctionFormalParametersAndBody(FunctionNodeType funNode,ListNodeType paramsBody)840   void setFunctionFormalParametersAndBody(FunctionNodeType funNode,
841                                           ListNodeType paramsBody) {
842     MOZ_ASSERT_IF(paramsBody, paramsBody->isKind(ParseNodeKind::ParamsBody));
843     funNode->setBody(paramsBody);
844   }
setFunctionBox(FunctionNodeType funNode,FunctionBox * funbox)845   void setFunctionBox(FunctionNodeType funNode, FunctionBox* funbox) {
846     funNode->setFunbox(funbox);
847     funbox->functionNode = funNode;
848   }
addFunctionFormalParameter(FunctionNodeType funNode,Node argpn)849   void addFunctionFormalParameter(FunctionNodeType funNode, Node argpn) {
850     addList(/* list = */ funNode->body(), /* kid = */ argpn);
851   }
setFunctionBody(FunctionNodeType funNode,LexicalScopeNodeType body)852   void setFunctionBody(FunctionNodeType funNode, LexicalScopeNodeType body) {
853     MOZ_ASSERT(funNode->body()->isKind(ParseNodeKind::ParamsBody));
854     addList(/* list = */ funNode->body(), /* kid = */ body);
855   }
856 
newModule(const TokenPos & pos)857   ModuleNodeType newModule(const TokenPos& pos) {
858     return new_<ModuleNode>(pos);
859   }
860 
861   LexicalScopeNodeType newLexicalScope(LexicalScope::Data* bindings, Node body,
862                                        ScopeKind kind = ScopeKind::Lexical) {
863     return new_<LexicalScopeNode>(bindings, body, kind);
864   }
865 
newNewExpression(uint32_t begin,Node ctor,Node args,bool isSpread)866   CallNodeType newNewExpression(uint32_t begin, Node ctor, Node args,
867                                 bool isSpread) {
868     return new_<CallNode>(ParseNodeKind::NewExpr,
869                           isSpread ? JSOp::SpreadNew : JSOp::New,
870                           TokenPos(begin, args->pn_pos.end), ctor, args);
871   }
872 
newAssignment(ParseNodeKind kind,Node lhs,Node rhs)873   AssignmentNodeType newAssignment(ParseNodeKind kind, Node lhs, Node rhs) {
874     if ((kind == ParseNodeKind::AssignExpr ||
875          kind == ParseNodeKind::InitExpr) &&
876         lhs->isKind(ParseNodeKind::Name) && !lhs->isInParens()) {
877       checkAndSetIsDirectRHSAnonFunction(rhs);
878     }
879 
880     return new_<AssignmentNode>(kind, lhs, rhs);
881   }
882 
isUnparenthesizedAssignment(Node node)883   bool isUnparenthesizedAssignment(Node node) {
884     if ((node->isKind(ParseNodeKind::AssignExpr)) && !node->isInParens()) {
885       return true;
886     }
887 
888     return false;
889   }
890 
isUnparenthesizedUnaryExpression(Node node)891   bool isUnparenthesizedUnaryExpression(Node node) {
892     if (!node->isInParens()) {
893       ParseNodeKind kind = node->getKind();
894       return kind == ParseNodeKind::VoidExpr ||
895              kind == ParseNodeKind::NotExpr ||
896              kind == ParseNodeKind::BitNotExpr ||
897              kind == ParseNodeKind::PosExpr || kind == ParseNodeKind::NegExpr ||
898              IsTypeofKind(kind) || IsDeleteKind(kind);
899     }
900     return false;
901   }
902 
isReturnStatement(Node node)903   bool isReturnStatement(Node node) {
904     return node->isKind(ParseNodeKind::ReturnStmt);
905   }
906 
isStatementPermittedAfterReturnStatement(Node node)907   bool isStatementPermittedAfterReturnStatement(Node node) {
908     ParseNodeKind kind = node->getKind();
909     return kind == ParseNodeKind::Function || kind == ParseNodeKind::VarStmt ||
910            kind == ParseNodeKind::BreakStmt ||
911            kind == ParseNodeKind::ThrowStmt || kind == ParseNodeKind::EmptyStmt;
912   }
913 
isSuperBase(Node node)914   bool isSuperBase(Node node) { return node->isKind(ParseNodeKind::SuperBase); }
915 
isUsableAsObjectPropertyName(Node node)916   bool isUsableAsObjectPropertyName(Node node) {
917     return node->isKind(ParseNodeKind::NumberExpr) ||
918            node->isKind(ParseNodeKind::BigIntExpr) ||
919            node->isKind(ParseNodeKind::ObjectPropertyName) ||
920            node->isKind(ParseNodeKind::StringExpr) ||
921            node->isKind(ParseNodeKind::ComputedName);
922   }
923 
finishInitializerAssignment(NameNodeType nameNode,Node init)924   AssignmentNodeType finishInitializerAssignment(NameNodeType nameNode,
925                                                  Node init) {
926     MOZ_ASSERT(nameNode->isKind(ParseNodeKind::Name));
927     MOZ_ASSERT(!nameNode->isInParens());
928 
929     checkAndSetIsDirectRHSAnonFunction(init);
930 
931     return newAssignment(ParseNodeKind::AssignExpr, nameNode, init);
932   }
933 
setBeginPosition(Node pn,Node oth)934   void setBeginPosition(Node pn, Node oth) {
935     setBeginPosition(pn, oth->pn_pos.begin);
936   }
setBeginPosition(Node pn,uint32_t begin)937   void setBeginPosition(Node pn, uint32_t begin) {
938     pn->pn_pos.begin = begin;
939     MOZ_ASSERT_IF(sourceKind() == SourceKind::Text,
940                   pn->pn_pos.begin <= pn->pn_pos.end);
941   }
942 
setEndPosition(Node pn,Node oth)943   void setEndPosition(Node pn, Node oth) {
944     setEndPosition(pn, oth->pn_pos.end);
945   }
setEndPosition(Node pn,uint32_t end)946   void setEndPosition(Node pn, uint32_t end) {
947     pn->pn_pos.end = end;
948     MOZ_ASSERT_IF(sourceKind() == SourceKind::Text,
949                   pn->pn_pos.begin <= pn->pn_pos.end);
950   }
951 
getFunctionNameOffset(Node func,TokenStreamAnyChars & ts)952   uint32_t getFunctionNameOffset(Node func, TokenStreamAnyChars& ts) {
953     return func->pn_pos.begin;
954   }
955 
isDeclarationKind(ParseNodeKind kind)956   bool isDeclarationKind(ParseNodeKind kind) {
957     return kind == ParseNodeKind::VarStmt || kind == ParseNodeKind::LetDecl ||
958            kind == ParseNodeKind::ConstDecl;
959   }
960 
newList(ParseNodeKind kind,const TokenPos & pos)961   ListNodeType newList(ParseNodeKind kind, const TokenPos& pos) {
962     MOZ_ASSERT(!isDeclarationKind(kind));
963     return new_<ListNode>(kind, pos);
964   }
965 
966  public:
newList(ParseNodeKind kind,Node kid)967   ListNodeType newList(ParseNodeKind kind, Node kid) {
968     MOZ_ASSERT(!isDeclarationKind(kind));
969     return new_<ListNode>(kind, kid);
970   }
971 
newDeclarationList(ParseNodeKind kind,const TokenPos & pos)972   ListNodeType newDeclarationList(ParseNodeKind kind, const TokenPos& pos) {
973     MOZ_ASSERT(isDeclarationKind(kind));
974     return new_<ListNode>(kind, pos);
975   }
976 
isDeclarationList(Node node)977   bool isDeclarationList(Node node) {
978     return isDeclarationKind(node->getKind());
979   }
980 
singleBindingFromDeclaration(ListNodeType decl)981   Node singleBindingFromDeclaration(ListNodeType decl) {
982     MOZ_ASSERT(isDeclarationList(decl));
983     MOZ_ASSERT(decl->count() == 1);
984     return decl->head();
985   }
986 
newCommaExpressionList(Node kid)987   ListNodeType newCommaExpressionList(Node kid) {
988     return new_<ListNode>(ParseNodeKind::CommaExpr, kid);
989   }
990 
addList(ListNodeType list,Node kid)991   void addList(ListNodeType list, Node kid) {
992     if (sourceKind_ == SourceKind::Text) {
993       list->append(kid);
994     } else {
995       list->appendWithoutOrderAssumption(kid);
996     }
997   }
998 
setListHasNonConstInitializer(ListNodeType literal)999   void setListHasNonConstInitializer(ListNodeType literal) {
1000     literal->setHasNonConstInitializer();
1001   }
1002   template <typename NodeType>
parenthesize(NodeType node)1003   MOZ_MUST_USE NodeType parenthesize(NodeType node) {
1004     node->setInParens(true);
1005     return node;
1006   }
1007   template <typename NodeType>
setLikelyIIFE(NodeType node)1008   MOZ_MUST_USE NodeType setLikelyIIFE(NodeType node) {
1009     return parenthesize(node);
1010   }
1011 
isName(Node node)1012   bool isName(Node node) { return node->isKind(ParseNodeKind::Name); }
1013 
isArgumentsName(Node node,JSContext * cx)1014   bool isArgumentsName(Node node, JSContext* cx) {
1015     return node->isKind(ParseNodeKind::Name) &&
1016            node->as<NameNode>().atom() == cx->names().arguments;
1017   }
1018 
isEvalName(Node node,JSContext * cx)1019   bool isEvalName(Node node, JSContext* cx) {
1020     return node->isKind(ParseNodeKind::Name) &&
1021            node->as<NameNode>().atom() == cx->names().eval;
1022   }
1023 
isAsyncKeyword(Node node,JSContext * cx)1024   bool isAsyncKeyword(Node node, JSContext* cx) {
1025     return node->isKind(ParseNodeKind::Name) &&
1026            node->pn_pos.begin + strlen("async") == node->pn_pos.end &&
1027            node->as<NameNode>().atom() == cx->names().async;
1028   }
1029 
maybeDottedProperty(Node pn)1030   PropertyName* maybeDottedProperty(Node pn) {
1031     return pn->is<PropertyAccessBase>() ? &pn->as<PropertyAccessBase>().name()
1032                                         : nullptr;
1033   }
isStringExprStatement(Node pn,TokenPos * pos)1034   JSAtom* isStringExprStatement(Node pn, TokenPos* pos) {
1035     if (pn->is<UnaryNode>()) {
1036       UnaryNode* unary = &pn->as<UnaryNode>();
1037       if (JSAtom* atom = unary->isStringExprStatement()) {
1038         *pos = unary->kid()->pn_pos;
1039         return atom;
1040       }
1041     }
1042     return nullptr;
1043   }
1044 
canSkipLazyInnerFunctions()1045   bool canSkipLazyInnerFunctions() { return !!lazyOuterFunction_; }
canSkipLazyClosedOverBindings()1046   bool canSkipLazyClosedOverBindings() { return !!lazyOuterFunction_; }
canSkipRegexpSyntaxParse()1047   bool canSkipRegexpSyntaxParse() { return !!lazyOuterFunction_; }
nextLazyInnerFunction()1048   JSFunction* nextLazyInnerFunction() {
1049     return &lazyOuterFunction_->gcthings()[lazyInnerFunctionIndex++]
1050                 .as<JSObject>()
1051                 .as<JSFunction>();
1052   }
nextLazyClosedOverBinding()1053   JSAtom* nextLazyClosedOverBinding() {
1054     auto gcthings = lazyOuterFunction_->gcthings();
1055 
1056     // Trailing nullptrs were elided in PerHandlerParser::finishFunction().
1057     if (lazyClosedOverBindingIndex >= gcthings.Length()) {
1058       return nullptr;
1059     }
1060 
1061     // These entries are either JSAtom* or nullptr, so use the 'asCell()'
1062     // accessor which is faster.
1063     gc::Cell* cell = gcthings[lazyClosedOverBindingIndex++].asCell();
1064     MOZ_ASSERT_IF(cell, cell->as<JSString>()->isAtom());
1065     return static_cast<JSAtom*>(cell);
1066   }
1067 };
1068 
setLastFunctionFormalParameterDefault(FunctionNodeType funNode,Node defaultValue)1069 inline bool FullParseHandler::setLastFunctionFormalParameterDefault(
1070     FunctionNodeType funNode, Node defaultValue) {
1071   ListNode* body = funNode->body();
1072   ParseNode* arg = body->last();
1073   ParseNode* pn = newAssignment(ParseNodeKind::AssignExpr, arg, defaultValue);
1074   if (!pn) {
1075     return false;
1076   }
1077 
1078   body->replaceLast(pn);
1079   return true;
1080 }
1081 
1082 }  // namespace frontend
1083 }  // namespace js
1084 
1085 #endif /* frontend_FullParseHandler_h */
1086