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