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/. */
7 #ifndef frontend_FullParseHandler_h
8 #define frontend_FullParseHandler_h
10 #include "mozilla/Maybe.h" // mozilla::Maybe
11 #include "mozilla/Result.h" // mozilla::Result, mozilla::UnusedZero
12 #include "mozilla/Try.h" // MOZ_TRY*
14 #include <cstddef> // std::nullptr_t
19 #include "frontend/CompilationStencil.h" // CompilationState
20 #include "frontend/FunctionSyntaxKind.h" // FunctionSyntaxKind
21 #include "frontend/NameAnalysisTypes.h" // PrivateNameKind
22 #include "frontend/ParseNode.h"
23 #include "frontend/Parser-macros.h" // MOZ_TRY_VAR_OR_RETURN
24 #include "frontend/ParserAtom.h" // TaggedParserAtomIndex
25 #include "frontend/SharedContext.h"
26 #include "frontend/Stencil.h"
29 struct mozilla::detail::UnusedZero
<js::frontend::ParseNode
*> {
30 static const bool value
= true;
33 #define DEFINE_UNUSED_ZERO(typeName) \
35 struct mozilla::detail::UnusedZero<js::frontend::typeName*> { \
36 static const bool value = true; \
38 FOR_EACH_PARSENODE_SUBCLASS(DEFINE_UNUSED_ZERO
)
39 #undef DEFINE_UNUSED_ZERO
44 class TokenStreamAnyChars
;
46 // Parse handler used when generating a full parse tree for all code which the
48 class FullParseHandler
{
49 ParseNodeAllocator allocator
;
51 ParseNode
* allocParseNode(size_t size
) {
52 return static_cast<ParseNode
*>(allocator
.allocNode(size
));
55 // If this is a full parse to construct the bytecode for a function that
56 // was previously lazily parsed, we still don't want to full parse the
57 // inner functions. These members are used for this functionality:
59 // - reuseGCThings if ture it means that the following fields are valid.
60 // - gcThingsData holds an incomplete stencil-like copy of inner functions as
62 // - scriptData and scriptExtra_ hold information necessary to locate inner
63 // functions to skip over each.
64 // - lazyInnerFunctionIndex is used as we skip over inner functions
65 // (see skipLazyInnerFunction),
66 // - lazyClosedOverBindingIndex is used to synchronize binding computation
67 // with the scope traversal.
68 // (see propagateFreeNamesAndMarkClosedOverBindings),
69 const CompilationSyntaxParseCache
& previousParseCache_
;
71 size_t lazyInnerFunctionIndex
;
72 size_t lazyClosedOverBindingIndex
;
76 /* new_ methods for creating parse nodes. These report OOM on context. */
77 JS_DECLARE_NEW_METHODS(new_
, allocParseNode
, inline)
80 using NodeError
= ParseNodeError
;
82 using Node
= ParseNode
*;
83 using NodeResult
= ParseNodeResult
;
84 using NodeErrorResult
= mozilla::GenericErrorResult
<NodeError
>;
86 #define DECLARE_TYPE(typeName) \
87 using typeName##Type = typeName*; \
88 using typeName##Result = mozilla::Result<typeName*, NodeError>;
89 FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE
)
92 template <class T
, typename
... Args
>
93 inline mozilla::Result
<T
*, NodeError
> newResult(Args
&&... args
) {
94 auto* node
= new_
<T
>(std::forward
<Args
>(args
)...);
96 return mozilla::Result
<T
*, NodeError
>(NodeError());
101 using NullNode
= std::nullptr_t
;
103 bool isPropertyOrPrivateMemberAccess(Node node
) {
104 return node
->isKind(ParseNodeKind::DotExpr
) ||
105 node
->isKind(ParseNodeKind::ElemExpr
) ||
106 node
->isKind(ParseNodeKind::PrivateMemberExpr
) ||
107 node
->isKind(ParseNodeKind::ArgumentsLength
);
110 bool isOptionalPropertyOrPrivateMemberAccess(Node node
) {
111 return node
->isKind(ParseNodeKind::OptionalDotExpr
) ||
112 node
->isKind(ParseNodeKind::OptionalElemExpr
) ||
113 node
->isKind(ParseNodeKind::PrivateMemberExpr
);
116 bool isFunctionCall(Node node
) {
117 // Note: super() is a special form, *not* a function call.
118 return node
->isKind(ParseNodeKind::CallExpr
);
121 static bool isUnparenthesizedDestructuringPattern(Node node
) {
122 return !node
->isInParens() && (node
->isKind(ParseNodeKind::ObjectExpr
) ||
123 node
->isKind(ParseNodeKind::ArrayExpr
));
126 static bool isParenthesizedDestructuringPattern(Node node
) {
127 // Technically this isn't a destructuring pattern at all -- the grammar
128 // doesn't treat it as such. But we need to know when this happens to
129 // consider it a SyntaxError rather than an invalid-left-hand-side
131 return node
->isInParens() && (node
->isKind(ParseNodeKind::ObjectExpr
) ||
132 node
->isKind(ParseNodeKind::ArrayExpr
));
135 FullParseHandler(FrontendContext
* fc
, CompilationState
& compilationState
)
136 : allocator(fc
, compilationState
.parserAllocScope
.alloc()),
137 previousParseCache_(compilationState
.previousParseCache
),
138 lazyInnerFunctionIndex(0),
139 lazyClosedOverBindingIndex(0),
140 reuseGCThings(compilationState
.input
.isDelazifying()) {}
142 static NullNode
null() { return NullNode(); }
143 static constexpr NodeErrorResult
errorResult() {
144 return NodeErrorResult(NodeError());
147 #define DECLARE_AS(typeName) \
148 static typeName##Type as##typeName(Node node) { \
149 return &node->as<typeName>(); \
151 FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS
)
154 NameNodeResult
newName(TaggedParserAtomIndex name
, const TokenPos
& pos
) {
155 return newResult
<NameNode
>(ParseNodeKind::Name
, name
, pos
);
158 UnaryNodeResult
newComputedName(Node expr
, uint32_t begin
, uint32_t end
) {
159 TokenPos
pos(begin
, end
);
160 return newResult
<UnaryNode
>(ParseNodeKind::ComputedName
, pos
, expr
);
163 UnaryNodeResult
newSyntheticComputedName(Node expr
, uint32_t begin
,
165 TokenPos
pos(begin
, end
);
168 newResult
<UnaryNode
>(ParseNodeKind::ComputedName
, pos
, expr
));
169 node
->setSyntheticComputedName();
173 NameNodeResult
newObjectLiteralPropertyName(TaggedParserAtomIndex atom
,
174 const TokenPos
& pos
) {
175 return newResult
<NameNode
>(ParseNodeKind::ObjectPropertyName
, atom
, pos
);
178 NameNodeResult
newPrivateName(TaggedParserAtomIndex atom
,
179 const TokenPos
& pos
) {
180 return newResult
<NameNode
>(ParseNodeKind::PrivateName
, atom
, pos
);
183 NumericLiteralResult
newNumber(double value
, DecimalPoint decimalPoint
,
184 const TokenPos
& pos
) {
185 return newResult
<NumericLiteral
>(value
, decimalPoint
, pos
);
188 BigIntLiteralResult
newBigInt(BigIntIndex index
, bool isZero
,
189 const TokenPos
& pos
) {
190 return newResult
<BigIntLiteral
>(index
, isZero
, pos
);
193 BooleanLiteralResult
newBooleanLiteral(bool cond
, const TokenPos
& pos
) {
194 return newResult
<BooleanLiteral
>(cond
, pos
);
197 NameNodeResult
newStringLiteral(TaggedParserAtomIndex atom
,
198 const TokenPos
& pos
) {
199 return newResult
<NameNode
>(ParseNodeKind::StringExpr
, atom
, pos
);
202 NameNodeResult
newTemplateStringLiteral(TaggedParserAtomIndex atom
,
203 const TokenPos
& pos
) {
204 return newResult
<NameNode
>(ParseNodeKind::TemplateStringExpr
, atom
, pos
);
207 CallSiteNodeResult
newCallSiteObject(uint32_t begin
) {
208 CallSiteNode
* callSiteObj
;
209 MOZ_TRY_VAR(callSiteObj
, newResult
<CallSiteNode
>(begin
));
212 MOZ_TRY_VAR(rawNodes
, newArrayLiteral(callSiteObj
->pn_pos
.begin
));
214 addArrayElement(callSiteObj
, rawNodes
);
219 void addToCallSiteObject(CallSiteNodeType callSiteObj
, Node rawNode
,
221 MOZ_ASSERT(callSiteObj
->isKind(ParseNodeKind::CallSiteObj
));
222 MOZ_ASSERT(rawNode
->isKind(ParseNodeKind::TemplateStringExpr
));
223 MOZ_ASSERT(cookedNode
->isKind(ParseNodeKind::TemplateStringExpr
) ||
224 cookedNode
->isKind(ParseNodeKind::RawUndefinedExpr
));
226 addArrayElement(callSiteObj
, cookedNode
);
227 addArrayElement(callSiteObj
->rawNodes(), rawNode
);
230 * We don't know when the last noSubstTemplate will come in, and we
231 * don't want to deal with this outside this method
233 setEndPosition(callSiteObj
, callSiteObj
->rawNodes());
236 ThisLiteralResult
newThisLiteral(const TokenPos
& pos
, Node thisName
) {
237 return newResult
<ThisLiteral
>(pos
, thisName
);
240 NullLiteralResult
newNullLiteral(const TokenPos
& pos
) {
241 return newResult
<NullLiteral
>(pos
);
244 RawUndefinedLiteralResult
newRawUndefinedLiteral(const TokenPos
& pos
) {
245 return newResult
<RawUndefinedLiteral
>(pos
);
248 RegExpLiteralResult
newRegExp(RegExpIndex index
, const TokenPos
& pos
) {
249 return newResult
<RegExpLiteral
>(index
, pos
);
252 ConditionalExpressionResult
newConditional(Node cond
, Node thenExpr
,
254 return newResult
<ConditionalExpression
>(cond
, thenExpr
, elseExpr
);
257 UnaryNodeResult
newDelete(uint32_t begin
, Node expr
) {
258 if (expr
->isKind(ParseNodeKind::Name
)) {
259 return newUnary(ParseNodeKind::DeleteNameExpr
, begin
, expr
);
262 if (expr
->isKind(ParseNodeKind::DotExpr
)) {
263 return newUnary(ParseNodeKind::DeletePropExpr
, begin
, expr
);
266 if (expr
->isKind(ParseNodeKind::ElemExpr
)) {
267 return newUnary(ParseNodeKind::DeleteElemExpr
, begin
, expr
);
270 if (expr
->isKind(ParseNodeKind::OptionalChain
)) {
271 Node kid
= expr
->as
<UnaryNode
>().kid();
272 // Handle property deletion explicitly. OptionalCall is handled
274 if (kid
->isKind(ParseNodeKind::DotExpr
) ||
275 kid
->isKind(ParseNodeKind::OptionalDotExpr
) ||
276 kid
->isKind(ParseNodeKind::ElemExpr
) ||
277 kid
->isKind(ParseNodeKind::OptionalElemExpr
)) {
278 return newUnary(ParseNodeKind::DeleteOptionalChainExpr
, begin
, kid
);
282 return newUnary(ParseNodeKind::DeleteExpr
, begin
, expr
);
285 UnaryNodeResult
newTypeof(uint32_t begin
, Node kid
) {
286 ParseNodeKind pnk
= kid
->isKind(ParseNodeKind::Name
)
287 ? ParseNodeKind::TypeOfNameExpr
288 : ParseNodeKind::TypeOfExpr
;
289 return newUnary(pnk
, begin
, kid
);
292 UnaryNodeResult
newUnary(ParseNodeKind kind
, uint32_t begin
, Node kid
) {
293 TokenPos
pos(begin
, kid
->pn_pos
.end
);
294 return newResult
<UnaryNode
>(kind
, pos
, kid
);
297 UnaryNodeResult
newUpdate(ParseNodeKind kind
, uint32_t begin
, Node kid
) {
298 TokenPos
pos(begin
, kid
->pn_pos
.end
);
299 return newResult
<UnaryNode
>(kind
, pos
, kid
);
302 UnaryNodeResult
newSpread(uint32_t begin
, Node kid
) {
303 TokenPos
pos(begin
, kid
->pn_pos
.end
);
304 return newResult
<UnaryNode
>(ParseNodeKind::Spread
, pos
, kid
);
308 BinaryNodeResult
newBinary(ParseNodeKind kind
, Node left
, Node right
) {
309 TokenPos
pos(left
->pn_pos
.begin
, right
->pn_pos
.end
);
310 return newResult
<BinaryNode
>(kind
, pos
, left
, right
);
314 NodeResult
appendOrCreateList(ParseNodeKind kind
, Node left
, Node right
,
316 return ParseNode::appendOrCreateList(kind
, left
, right
, this, pc
);
321 ListNodeResult
newArrayLiteral(uint32_t begin
) {
322 return newResult
<ListNode
>(ParseNodeKind::ArrayExpr
,
323 TokenPos(begin
, begin
+ 1));
326 [[nodiscard
]] bool addElision(ListNodeType literal
, const TokenPos
& pos
) {
327 MOZ_ASSERT(literal
->isKind(ParseNodeKind::ArrayExpr
));
329 NullaryNode
* elision
;
330 MOZ_TRY_VAR_OR_RETURN(
331 elision
, newResult
<NullaryNode
>(ParseNodeKind::Elision
, pos
), false);
332 addList(/* list = */ literal
, /* kid = */ elision
);
333 literal
->setHasNonConstInitializer();
337 [[nodiscard
]] bool addSpreadElement(ListNodeType literal
, uint32_t begin
,
340 literal
->isKind(ParseNodeKind::ArrayExpr
) ||
341 IF_RECORD_TUPLE(literal
->isKind(ParseNodeKind::TupleExpr
), false));
343 UnaryNodeType spread
;
344 MOZ_TRY_VAR_OR_RETURN(spread
, newSpread(begin
, inner
), false);
345 addList(/* list = */ literal
, /* kid = */ spread
);
346 literal
->setHasNonConstInitializer();
350 void addArrayElement(ListNodeType literal
, Node element
) {
352 literal
->isKind(ParseNodeKind::ArrayExpr
) ||
353 literal
->isKind(ParseNodeKind::CallSiteObj
) ||
354 IF_RECORD_TUPLE(literal
->isKind(ParseNodeKind::TupleExpr
), false));
355 if (!element
->isConstant()) {
356 literal
->setHasNonConstInitializer();
358 addList(/* list = */ literal
, /* kid = */ element
);
361 CallNodeResult
newCall(Node callee
, ListNodeType args
, JSOp callOp
) {
362 return newResult
<CallNode
>(ParseNodeKind::CallExpr
, callOp
, callee
, args
);
365 CallNodeResult
newOptionalCall(Node callee
, ListNodeType args
, JSOp callOp
) {
366 return newResult
<CallNode
>(ParseNodeKind::OptionalCallExpr
, callOp
, callee
,
370 ListNodeResult
newArguments(const TokenPos
& pos
) {
371 return newResult
<ListNode
>(ParseNodeKind::Arguments
, pos
);
374 CallNodeResult
newSuperCall(Node callee
, ListNodeType args
, bool isSpread
) {
375 return newResult
<CallNode
>(
376 ParseNodeKind::SuperCallExpr
,
377 isSpread
? JSOp::SpreadSuperCall
: JSOp::SuperCall
, callee
, args
);
380 CallNodeResult
newTaggedTemplate(Node tag
, ListNodeType args
, JSOp callOp
) {
381 return newResult
<CallNode
>(ParseNodeKind::TaggedTemplateExpr
, callOp
, tag
,
385 ListNodeResult
newObjectLiteral(uint32_t begin
) {
386 return newResult
<ListNode
>(ParseNodeKind::ObjectExpr
,
387 TokenPos(begin
, begin
+ 1));
390 #ifdef ENABLE_RECORD_TUPLE
391 ListNodeResult
newRecordLiteral(uint32_t begin
) {
392 return newResult
<ListNode
>(ParseNodeKind::RecordExpr
,
393 TokenPos(begin
, begin
+ 1));
396 ListNodeResult
newTupleLiteral(uint32_t begin
) {
397 return newResult
<ListNode
>(ParseNodeKind::TupleExpr
,
398 TokenPos(begin
, begin
+ 1));
402 ClassNodeResult
newClass(Node name
, Node heritage
,
403 LexicalScopeNodeType memberBlock
,
404 #ifdef ENABLE_DECORATORS
405 ListNodeType decorators
,
406 FunctionNodeType addInitializerFunction
,
408 const TokenPos
& pos
) {
409 return newResult
<ClassNode
>(name
, heritage
, memberBlock
,
410 #ifdef ENABLE_DECORATORS
411 decorators
, addInitializerFunction
,
415 ListNodeResult
newClassMemberList(uint32_t begin
) {
416 return newResult
<ListNode
>(ParseNodeKind::ClassMemberList
,
417 TokenPos(begin
, begin
+ 1));
419 ClassNamesResult
newClassNames(Node outer
, Node inner
, const TokenPos
& pos
) {
420 return newResult
<ClassNames
>(outer
, inner
, pos
);
422 NewTargetNodeResult
newNewTarget(NullaryNodeType newHolder
,
423 NullaryNodeType targetHolder
,
424 NameNodeType newTargetName
) {
425 return newResult
<NewTargetNode
>(newHolder
, targetHolder
, newTargetName
);
427 NullaryNodeResult
newPosHolder(const TokenPos
& pos
) {
428 return newResult
<NullaryNode
>(ParseNodeKind::PosHolder
, pos
);
430 UnaryNodeResult
newSuperBase(Node thisName
, const TokenPos
& pos
) {
431 return newResult
<UnaryNode
>(ParseNodeKind::SuperBase
, pos
, thisName
);
433 [[nodiscard
]] bool addPrototypeMutation(ListNodeType literal
, uint32_t begin
,
435 MOZ_ASSERT(literal
->isKind(ParseNodeKind::ObjectExpr
));
437 // Object literals with mutated [[Prototype]] are non-constant so that
438 // singleton objects will have Object.prototype as their [[Prototype]].
439 literal
->setHasNonConstInitializer();
442 MOZ_TRY_VAR_OR_RETURN(
443 mutation
, newUnary(ParseNodeKind::MutateProto
, begin
, expr
), false);
444 addList(/* list = */ literal
, /* kid = */ mutation
);
448 BinaryNodeResult
newPropertyDefinition(Node key
, Node val
) {
449 MOZ_ASSERT(isUsableAsObjectPropertyName(key
));
450 checkAndSetIsDirectRHSAnonFunction(val
);
451 return newResult
<PropertyDefinition
>(key
, val
, AccessorType::None
);
454 void addPropertyDefinition(ListNodeType literal
, BinaryNodeType propdef
) {
456 literal
->isKind(ParseNodeKind::ObjectExpr
) ||
457 IF_RECORD_TUPLE(literal
->isKind(ParseNodeKind::RecordExpr
), false));
458 MOZ_ASSERT(propdef
->isKind(ParseNodeKind::PropertyDefinition
));
460 if (!propdef
->right()->isConstant()) {
461 literal
->setHasNonConstInitializer();
464 addList(/* list = */ literal
, /* kid = */ propdef
);
467 [[nodiscard
]] bool addPropertyDefinition(ListNodeType literal
, Node key
,
470 MOZ_TRY_VAR_OR_RETURN(propdef
, newPropertyDefinition(key
, val
), false);
471 addPropertyDefinition(literal
, propdef
);
475 [[nodiscard
]] bool addShorthand(ListNodeType literal
, NameNodeType name
,
478 literal
->isKind(ParseNodeKind::ObjectExpr
) ||
479 IF_RECORD_TUPLE(literal
->isKind(ParseNodeKind::RecordExpr
), false));
480 MOZ_ASSERT(name
->isKind(ParseNodeKind::ObjectPropertyName
));
481 MOZ_ASSERT(expr
->isKind(ParseNodeKind::Name
));
482 MOZ_ASSERT(name
->atom() == expr
->atom());
484 literal
->setHasNonConstInitializer();
486 MOZ_TRY_VAR_OR_RETURN(
487 propdef
, newBinary(ParseNodeKind::Shorthand
, name
, expr
), false);
488 addList(/* list = */ literal
, /* kid = */ propdef
);
492 [[nodiscard
]] bool addSpreadProperty(ListNodeType literal
, uint32_t begin
,
495 literal
->isKind(ParseNodeKind::ObjectExpr
) ||
496 IF_RECORD_TUPLE(literal
->isKind(ParseNodeKind::RecordExpr
), false));
498 literal
->setHasNonConstInitializer();
500 MOZ_TRY_VAR_OR_RETURN(spread
, newSpread(begin
, inner
), false);
501 addList(/* list = */ literal
, /* kid = */ spread
);
505 [[nodiscard
]] bool addObjectMethodDefinition(ListNodeType literal
, Node key
,
506 FunctionNodeType funNode
,
507 AccessorType atype
) {
508 literal
->setHasNonConstInitializer();
510 checkAndSetIsDirectRHSAnonFunction(funNode
);
513 MOZ_TRY_VAR_OR_RETURN(
514 propdef
, newObjectMethodOrPropertyDefinition(key
, funNode
, atype
),
516 addList(/* list = */ literal
, /* kid = */ propdef
);
520 [[nodiscard
]] ClassMethodResult
newDefaultClassConstructor(
521 Node key
, FunctionNodeType funNode
) {
522 MOZ_ASSERT(isUsableAsObjectPropertyName(key
));
524 checkAndSetIsDirectRHSAnonFunction(funNode
);
526 return newResult
<ClassMethod
>(
527 ParseNodeKind::DefaultConstructor
, key
, funNode
, AccessorType::None
,
528 /* isStatic = */ false, /* initializeIfPrivate = */ nullptr
529 #ifdef ENABLE_DECORATORS
531 /* decorators = */ nullptr
536 [[nodiscard
]] ClassMethodResult
newClassMethodDefinition(
537 Node key
, FunctionNodeType funNode
, AccessorType atype
, bool isStatic
,
538 mozilla::Maybe
<FunctionNodeType
> initializerIfPrivate
539 #ifdef ENABLE_DECORATORS
541 ListNodeType decorators
544 MOZ_ASSERT(isUsableAsObjectPropertyName(key
));
546 checkAndSetIsDirectRHSAnonFunction(funNode
);
548 if (initializerIfPrivate
.isSome()) {
549 return newResult
<ClassMethod
>(ParseNodeKind::ClassMethod
, key
, funNode
,
551 initializerIfPrivate
.value()
552 #ifdef ENABLE_DECORATORS
558 return newResult
<ClassMethod
>(ParseNodeKind::ClassMethod
, key
, funNode
,
560 /* initializeIfPrivate = */ nullptr
561 #ifdef ENABLE_DECORATORS
568 [[nodiscard
]] ClassFieldResult
newClassFieldDefinition(
569 Node name
, FunctionNodeType initializer
, bool isStatic
570 #ifdef ENABLE_DECORATORS
572 ListNodeType decorators
, ClassMethodType accessorGetterNode
,
573 ClassMethodType accessorSetterNode
576 MOZ_ASSERT(isUsableAsObjectPropertyName(name
));
578 return newResult
<ClassField
>(name
, initializer
, isStatic
579 #if ENABLE_DECORATORS
581 decorators
, accessorGetterNode
,
587 [[nodiscard
]] StaticClassBlockResult
newStaticClassBlock(
588 FunctionNodeType block
) {
589 return newResult
<StaticClassBlock
>(block
);
592 [[nodiscard
]] bool addClassMemberDefinition(ListNodeType memberList
,
594 MOZ_ASSERT(memberList
->isKind(ParseNodeKind::ClassMemberList
));
595 // Constructors can be surrounded by LexicalScopes.
596 MOZ_ASSERT(member
->isKind(ParseNodeKind::DefaultConstructor
) ||
597 member
->isKind(ParseNodeKind::ClassMethod
) ||
598 member
->isKind(ParseNodeKind::ClassField
) ||
599 member
->isKind(ParseNodeKind::StaticClassBlock
) ||
600 (member
->isKind(ParseNodeKind::LexicalScope
) &&
601 member
->as
<LexicalScopeNode
>().scopeBody()->is
<ClassMethod
>()));
603 addList(/* list = */ memberList
, /* kid = */ member
);
607 UnaryNodeResult
newInitialYieldExpression(uint32_t begin
, Node gen
) {
608 TokenPos
pos(begin
, begin
+ 1);
609 return newResult
<UnaryNode
>(ParseNodeKind::InitialYield
, pos
, gen
);
612 UnaryNodeResult
newYieldExpression(uint32_t begin
, Node value
) {
613 TokenPos
pos(begin
, value
? value
->pn_pos
.end
: begin
+ 1);
614 return newResult
<UnaryNode
>(ParseNodeKind::YieldExpr
, pos
, value
);
617 UnaryNodeResult
newYieldStarExpression(uint32_t begin
, Node value
) {
618 TokenPos
pos(begin
, value
->pn_pos
.end
);
619 return newResult
<UnaryNode
>(ParseNodeKind::YieldStarExpr
, pos
, value
);
622 UnaryNodeResult
newAwaitExpression(uint32_t begin
, Node value
) {
623 TokenPos
pos(begin
, value
? value
->pn_pos
.end
: begin
+ 1);
624 return newResult
<UnaryNode
>(ParseNodeKind::AwaitExpr
, pos
, value
);
627 UnaryNodeResult
newOptionalChain(uint32_t begin
, Node value
) {
628 TokenPos
pos(begin
, value
->pn_pos
.end
);
629 return newResult
<UnaryNode
>(ParseNodeKind::OptionalChain
, pos
, value
);
634 ListNodeResult
newStatementList(const TokenPos
& pos
) {
635 return newResult
<ListNode
>(ParseNodeKind::StatementList
, pos
);
638 [[nodiscard
]] bool isFunctionStmt(Node stmt
) {
639 while (stmt
->isKind(ParseNodeKind::LabelStmt
)) {
640 stmt
= stmt
->as
<LabeledStatement
>().statement();
642 return stmt
->is
<FunctionNode
>();
645 void addStatementToList(ListNodeType list
, Node stmt
) {
646 MOZ_ASSERT(list
->isKind(ParseNodeKind::StatementList
));
648 addList(/* list = */ list
, /* kid = */ stmt
);
650 if (isFunctionStmt(stmt
)) {
651 // Notify the emitter that the block contains body-level function
652 // definitions that should be processed before the rest of nodes.
653 list
->setHasTopLevelFunctionDeclarations();
657 void setListEndPosition(ListNodeType list
, const TokenPos
& pos
) {
658 MOZ_ASSERT(list
->isKind(ParseNodeKind::StatementList
));
659 list
->pn_pos
.end
= pos
.end
;
662 void addCaseStatementToList(ListNodeType list
, CaseClauseType caseClause
) {
663 MOZ_ASSERT(list
->isKind(ParseNodeKind::StatementList
));
665 addList(/* list = */ list
, /* kid = */ caseClause
);
667 if (caseClause
->statementList()->hasTopLevelFunctionDeclarations()) {
668 list
->setHasTopLevelFunctionDeclarations();
672 [[nodiscard
]] bool prependInitialYield(ListNodeType stmtList
, Node genName
) {
673 MOZ_ASSERT(stmtList
->isKind(ParseNodeKind::StatementList
));
675 TokenPos
yieldPos(stmtList
->pn_pos
.begin
, stmtList
->pn_pos
.begin
+ 1);
676 NullaryNode
* makeGen
;
677 MOZ_TRY_VAR_OR_RETURN(
678 makeGen
, newResult
<NullaryNode
>(ParseNodeKind::Generator
, yieldPos
),
682 MOZ_TRY_VAR_OR_RETURN(
684 newAssignment(ParseNodeKind::AssignExpr
, /* lhs = */ genName
,
685 /* rhs = */ makeGen
),
688 UnaryNode
* initialYield
;
689 MOZ_TRY_VAR_OR_RETURN(initialYield
,
690 newInitialYieldExpression(yieldPos
.begin
, genInit
),
693 stmtList
->prepend(initialYield
);
697 BinaryNodeResult
newSetThis(Node thisName
, Node value
) {
698 return newBinary(ParseNodeKind::SetThis
, thisName
, value
);
701 NullaryNodeResult
newEmptyStatement(const TokenPos
& pos
) {
702 return newResult
<NullaryNode
>(ParseNodeKind::EmptyStmt
, pos
);
705 BinaryNodeResult
newImportAttribute(Node keyNode
, Node valueNode
) {
706 return newBinary(ParseNodeKind::ImportAttribute
, keyNode
, valueNode
);
709 BinaryNodeResult
newModuleRequest(Node moduleSpec
, Node importAttributeList
,
710 const TokenPos
& pos
) {
711 return newResult
<BinaryNode
>(ParseNodeKind::ImportModuleRequest
, pos
,
712 moduleSpec
, importAttributeList
);
715 BinaryNodeResult
newImportDeclaration(Node importSpecSet
, Node moduleRequest
,
716 const TokenPos
& pos
) {
717 return newResult
<BinaryNode
>(ParseNodeKind::ImportDecl
, pos
, importSpecSet
,
721 BinaryNodeResult
newImportSpec(Node importNameNode
, Node bindingName
) {
722 return newBinary(ParseNodeKind::ImportSpec
, importNameNode
, bindingName
);
725 UnaryNodeResult
newImportNamespaceSpec(uint32_t begin
, Node bindingName
) {
726 return newUnary(ParseNodeKind::ImportNamespaceSpec
, begin
, bindingName
);
729 UnaryNodeResult
newExportDeclaration(Node kid
, const TokenPos
& pos
) {
730 return newResult
<UnaryNode
>(ParseNodeKind::ExportStmt
, pos
, kid
);
733 BinaryNodeResult
newExportFromDeclaration(uint32_t begin
, Node exportSpecSet
,
734 Node moduleRequest
) {
736 MOZ_TRY_VAR(decl
, newResult
<BinaryNode
>(ParseNodeKind::ExportFromStmt
,
737 exportSpecSet
, moduleRequest
));
738 decl
->pn_pos
.begin
= begin
;
742 BinaryNodeResult
newExportDefaultDeclaration(Node kid
, Node maybeBinding
,
743 const TokenPos
& pos
) {
745 MOZ_ASSERT(maybeBinding
->isKind(ParseNodeKind::Name
));
746 MOZ_ASSERT(!maybeBinding
->isInParens());
748 checkAndSetIsDirectRHSAnonFunction(kid
);
751 return newResult
<BinaryNode
>(ParseNodeKind::ExportDefaultStmt
, pos
, kid
,
755 BinaryNodeResult
newExportSpec(Node bindingName
, Node exportName
) {
756 return newBinary(ParseNodeKind::ExportSpec
, bindingName
, exportName
);
759 UnaryNodeResult
newExportNamespaceSpec(uint32_t begin
, Node exportName
) {
760 return newUnary(ParseNodeKind::ExportNamespaceSpec
, begin
, exportName
);
763 NullaryNodeResult
newExportBatchSpec(const TokenPos
& pos
) {
764 return newResult
<NullaryNode
>(ParseNodeKind::ExportBatchSpecStmt
, pos
);
767 BinaryNodeResult
newImportMeta(NullaryNodeType importHolder
,
768 NullaryNodeType metaHolder
) {
769 return newResult
<BinaryNode
>(ParseNodeKind::ImportMetaExpr
, importHolder
,
773 BinaryNodeResult
newCallImport(NullaryNodeType importHolder
, Node singleArg
) {
774 return newResult
<BinaryNode
>(ParseNodeKind::CallImportExpr
, importHolder
,
778 BinaryNodeResult
newCallImportSpec(Node specifierArg
, Node optionalArg
) {
779 return newResult
<BinaryNode
>(ParseNodeKind::CallImportSpec
, specifierArg
,
783 UnaryNodeResult
newExprStatement(Node expr
, uint32_t end
) {
784 MOZ_ASSERT(expr
->pn_pos
.end
<= end
);
785 return newResult
<UnaryNode
>(ParseNodeKind::ExpressionStmt
,
786 TokenPos(expr
->pn_pos
.begin
, end
), expr
);
789 TernaryNodeResult
newIfStatement(uint32_t begin
, Node cond
, Node thenBranch
,
792 MOZ_TRY_VAR(node
, newResult
<TernaryNode
>(ParseNodeKind::IfStmt
, cond
,
793 thenBranch
, elseBranch
));
794 node
->pn_pos
.begin
= begin
;
798 BinaryNodeResult
newDoWhileStatement(Node body
, Node cond
,
799 const TokenPos
& pos
) {
800 return newResult
<BinaryNode
>(ParseNodeKind::DoWhileStmt
, pos
, body
, cond
);
803 BinaryNodeResult
newWhileStatement(uint32_t begin
, Node cond
, Node body
) {
804 TokenPos
pos(begin
, body
->pn_pos
.end
);
805 return newResult
<BinaryNode
>(ParseNodeKind::WhileStmt
, pos
, cond
, body
);
808 ForNodeResult
newForStatement(uint32_t begin
, TernaryNodeType forHead
,
809 Node body
, unsigned iflags
) {
810 return newResult
<ForNode
>(TokenPos(begin
, body
->pn_pos
.end
), forHead
, body
,
814 TernaryNodeResult
newForHead(Node init
, Node test
, Node update
,
815 const TokenPos
& pos
) {
816 return newResult
<TernaryNode
>(ParseNodeKind::ForHead
, init
, test
, update
,
820 TernaryNodeResult
newForInOrOfHead(ParseNodeKind kind
, Node target
,
821 Node iteratedExpr
, const TokenPos
& pos
) {
822 MOZ_ASSERT(kind
== ParseNodeKind::ForIn
|| kind
== ParseNodeKind::ForOf
);
823 return newResult
<TernaryNode
>(kind
, target
, nullptr, iteratedExpr
, pos
);
826 SwitchStatementResult
newSwitchStatement(
827 uint32_t begin
, Node discriminant
,
828 LexicalScopeNodeType lexicalForCaseList
, bool hasDefault
) {
829 return newResult
<SwitchStatement
>(begin
, discriminant
, lexicalForCaseList
,
833 CaseClauseResult
newCaseOrDefault(uint32_t begin
, Node expr
, Node body
) {
834 return newResult
<CaseClause
>(expr
, body
, begin
);
837 ContinueStatementResult
newContinueStatement(TaggedParserAtomIndex label
,
838 const TokenPos
& pos
) {
839 return newResult
<ContinueStatement
>(label
, pos
);
842 BreakStatementResult
newBreakStatement(TaggedParserAtomIndex label
,
843 const TokenPos
& pos
) {
844 return newResult
<BreakStatement
>(label
, pos
);
847 UnaryNodeResult
newReturnStatement(Node expr
, const TokenPos
& pos
) {
848 MOZ_ASSERT_IF(expr
, pos
.encloses(expr
->pn_pos
));
849 return newResult
<UnaryNode
>(ParseNodeKind::ReturnStmt
, pos
, expr
);
852 UnaryNodeResult
newExpressionBody(Node expr
) {
853 return newResult
<UnaryNode
>(ParseNodeKind::ReturnStmt
, expr
->pn_pos
, expr
);
856 BinaryNodeResult
newWithStatement(uint32_t begin
, Node expr
, Node body
) {
857 return newResult
<BinaryNode
>(ParseNodeKind::WithStmt
,
858 TokenPos(begin
, body
->pn_pos
.end
), expr
, body
);
861 LabeledStatementResult
newLabeledStatement(TaggedParserAtomIndex label
,
862 Node stmt
, uint32_t begin
) {
863 return newResult
<LabeledStatement
>(label
, stmt
, begin
);
866 UnaryNodeResult
newThrowStatement(Node expr
, const TokenPos
& pos
) {
867 MOZ_ASSERT(pos
.encloses(expr
->pn_pos
));
868 return newResult
<UnaryNode
>(ParseNodeKind::ThrowStmt
, pos
, expr
);
871 TernaryNodeResult
newTryStatement(uint32_t begin
, Node body
,
872 LexicalScopeNodeType catchScope
,
874 return newResult
<TryNode
>(begin
, body
, catchScope
, finallyBlock
);
877 DebuggerStatementResult
newDebuggerStatement(const TokenPos
& pos
) {
878 return newResult
<DebuggerStatement
>(pos
);
881 NameNodeResult
newPropertyName(TaggedParserAtomIndex name
,
882 const TokenPos
& pos
) {
883 return newResult
<NameNode
>(ParseNodeKind::PropertyNameExpr
, name
, pos
);
886 PropertyAccessResult
newPropertyAccess(Node expr
, NameNodeType key
) {
887 return newResult
<PropertyAccess
>(expr
, key
, expr
->pn_pos
.begin
,
891 ArgumentsLengthResult
newArgumentsLength(Node expr
, NameNodeType key
) {
892 return newResult
<ArgumentsLength
>(expr
, key
, expr
->pn_pos
.begin
,
896 PropertyByValueResult
newPropertyByValue(Node lhs
, Node index
, uint32_t end
) {
897 return newResult
<PropertyByValue
>(lhs
, index
, lhs
->pn_pos
.begin
, end
);
900 OptionalPropertyAccessResult
newOptionalPropertyAccess(Node expr
,
902 return newResult
<OptionalPropertyAccess
>(expr
, key
, expr
->pn_pos
.begin
,
906 OptionalPropertyByValueResult
newOptionalPropertyByValue(Node lhs
, Node index
,
908 return newResult
<OptionalPropertyByValue
>(lhs
, index
, lhs
->pn_pos
.begin
,
912 PrivateMemberAccessResult
newPrivateMemberAccess(Node lhs
,
913 NameNodeType privateName
,
915 return newResult
<PrivateMemberAccess
>(lhs
, privateName
, lhs
->pn_pos
.begin
,
919 OptionalPrivateMemberAccessResult
newOptionalPrivateMemberAccess(
920 Node lhs
, NameNodeType privateName
, uint32_t end
) {
921 return newResult
<OptionalPrivateMemberAccess
>(lhs
, privateName
,
922 lhs
->pn_pos
.begin
, end
);
925 bool setupCatchScope(LexicalScopeNodeType lexicalScope
, Node catchName
,
927 BinaryNode
* catchClause
;
929 MOZ_TRY_VAR_OR_RETURN(
931 newResult
<BinaryNode
>(ParseNodeKind::Catch
, catchName
, catchBody
),
934 MOZ_TRY_VAR_OR_RETURN(
936 newResult
<BinaryNode
>(ParseNodeKind::Catch
, catchBody
->pn_pos
,
937 catchName
, catchBody
),
940 lexicalScope
->setScopeBody(catchClause
);
944 [[nodiscard
]] inline bool setLastFunctionFormalParameterDefault(
945 FunctionNodeType funNode
, Node defaultValue
);
947 void checkAndSetIsDirectRHSAnonFunction(Node pn
) {
948 if (IsAnonymousFunctionDefinition(pn
)) {
949 pn
->setDirectRHSAnonFunction(true);
953 ParamsBodyNodeResult
newParamsBody(const TokenPos
& pos
) {
954 return newResult
<ParamsBodyNode
>(pos
);
957 FunctionNodeResult
newFunction(FunctionSyntaxKind syntaxKind
,
958 const TokenPos
& pos
) {
959 return newResult
<FunctionNode
>(syntaxKind
, pos
);
962 BinaryNodeResult
newObjectMethodOrPropertyDefinition(Node key
, Node value
,
963 AccessorType atype
) {
964 MOZ_ASSERT(isUsableAsObjectPropertyName(key
));
966 return newResult
<PropertyDefinition
>(key
, value
, atype
);
969 void setFunctionFormalParametersAndBody(FunctionNodeType funNode
,
970 ParamsBodyNodeType paramsBody
) {
971 funNode
->setBody(paramsBody
);
973 void setFunctionBox(FunctionNodeType funNode
, FunctionBox
* funbox
) {
974 funNode
->setFunbox(funbox
);
975 funbox
->functionNode
= funNode
;
977 void addFunctionFormalParameter(FunctionNodeType funNode
, Node argpn
) {
978 addList(/* list = */ funNode
->body(), /* kid = */ argpn
);
980 void setFunctionBody(FunctionNodeType funNode
, LexicalScopeNodeType body
) {
981 addList(/* list = */ funNode
->body(), /* kid = */ body
);
984 ModuleNodeResult
newModule(const TokenPos
& pos
) {
985 return newResult
<ModuleNode
>(pos
);
988 LexicalScopeNodeResult
newLexicalScope(LexicalScope::ParserData
* bindings
,
990 ScopeKind kind
= ScopeKind::Lexical
) {
991 return newResult
<LexicalScopeNode
>(bindings
, body
, kind
);
994 ClassBodyScopeNodeResult
newClassBodyScope(
995 ClassBodyScope::ParserData
* bindings
, ListNodeType body
) {
996 return newResult
<ClassBodyScopeNode
>(bindings
, body
);
999 CallNodeResult
newNewExpression(uint32_t begin
, Node ctor
, ListNodeType args
,
1001 return newResult
<CallNode
>(ParseNodeKind::NewExpr
,
1002 isSpread
? JSOp::SpreadNew
: JSOp::New
,
1003 TokenPos(begin
, args
->pn_pos
.end
), ctor
, args
);
1006 AssignmentNodeResult
newAssignment(ParseNodeKind kind
, Node lhs
, Node rhs
) {
1007 if ((kind
== ParseNodeKind::AssignExpr
||
1008 kind
== ParseNodeKind::CoalesceAssignExpr
||
1009 kind
== ParseNodeKind::OrAssignExpr
||
1010 kind
== ParseNodeKind::AndAssignExpr
) &&
1011 lhs
->isKind(ParseNodeKind::Name
) && !lhs
->isInParens()) {
1012 checkAndSetIsDirectRHSAnonFunction(rhs
);
1015 return newResult
<AssignmentNode
>(kind
, lhs
, rhs
);
1018 BinaryNodeResult
newInitExpr(Node lhs
, Node rhs
) {
1019 TokenPos
pos(lhs
->pn_pos
.begin
, rhs
->pn_pos
.end
);
1020 return newResult
<BinaryNode
>(ParseNodeKind::InitExpr
, pos
, lhs
, rhs
);
1023 bool isUnparenthesizedAssignment(Node node
) {
1024 if ((node
->isKind(ParseNodeKind::AssignExpr
)) && !node
->isInParens()) {
1031 bool isUnparenthesizedUnaryExpression(Node node
) {
1032 if (!node
->isInParens()) {
1033 ParseNodeKind kind
= node
->getKind();
1034 return kind
== ParseNodeKind::VoidExpr
||
1035 kind
== ParseNodeKind::NotExpr
||
1036 kind
== ParseNodeKind::BitNotExpr
||
1037 kind
== ParseNodeKind::PosExpr
|| kind
== ParseNodeKind::NegExpr
||
1038 kind
== ParseNodeKind::AwaitExpr
|| IsTypeofKind(kind
) ||
1044 bool isReturnStatement(Node node
) {
1045 return node
->isKind(ParseNodeKind::ReturnStmt
);
1048 bool isStatementPermittedAfterReturnStatement(Node node
) {
1049 ParseNodeKind kind
= node
->getKind();
1050 return kind
== ParseNodeKind::Function
|| kind
== ParseNodeKind::VarStmt
||
1051 kind
== ParseNodeKind::BreakStmt
||
1052 kind
== ParseNodeKind::ThrowStmt
|| kind
== ParseNodeKind::EmptyStmt
;
1055 bool isSuperBase(Node node
) { return node
->isKind(ParseNodeKind::SuperBase
); }
1057 bool isUsableAsObjectPropertyName(Node node
) {
1058 return node
->isKind(ParseNodeKind::NumberExpr
) ||
1059 node
->isKind(ParseNodeKind::BigIntExpr
) ||
1060 node
->isKind(ParseNodeKind::ObjectPropertyName
) ||
1061 node
->isKind(ParseNodeKind::StringExpr
) ||
1062 node
->isKind(ParseNodeKind::ComputedName
) ||
1063 node
->isKind(ParseNodeKind::PrivateName
);
1066 AssignmentNodeResult
finishInitializerAssignment(NameNodeType nameNode
,
1068 MOZ_ASSERT(nameNode
->isKind(ParseNodeKind::Name
));
1069 MOZ_ASSERT(!nameNode
->isInParens());
1071 checkAndSetIsDirectRHSAnonFunction(init
);
1073 return newAssignment(ParseNodeKind::AssignExpr
, nameNode
, init
);
1076 void setBeginPosition(Node pn
, Node oth
) {
1077 setBeginPosition(pn
, oth
->pn_pos
.begin
);
1079 void setBeginPosition(Node pn
, uint32_t begin
) {
1080 pn
->pn_pos
.begin
= begin
;
1081 MOZ_ASSERT(pn
->pn_pos
.begin
<= pn
->pn_pos
.end
);
1084 void setEndPosition(Node pn
, Node oth
) {
1085 setEndPosition(pn
, oth
->pn_pos
.end
);
1087 void setEndPosition(Node pn
, uint32_t end
) {
1088 pn
->pn_pos
.end
= end
;
1089 MOZ_ASSERT(pn
->pn_pos
.begin
<= pn
->pn_pos
.end
);
1092 uint32_t getFunctionNameOffset(Node func
, TokenStreamAnyChars
& ts
) {
1093 return func
->pn_pos
.begin
;
1096 ListNodeResult
newList(ParseNodeKind kind
, const TokenPos
& pos
) {
1097 auto list
= newResult
<ListNode
>(kind
, pos
);
1098 MOZ_ASSERT_IF(list
.isOk(), !list
.unwrap()->is
<DeclarationListNode
>());
1099 MOZ_ASSERT_IF(list
.isOk(), !list
.unwrap()->is
<ParamsBodyNode
>());
1103 ListNodeResult
newList(ParseNodeKind kind
, Node kid
) {
1104 auto list
= newResult
<ListNode
>(kind
, kid
);
1105 MOZ_ASSERT_IF(list
.isOk(), !list
.unwrap()->is
<DeclarationListNode
>());
1106 MOZ_ASSERT_IF(list
.isOk(), !list
.unwrap()->is
<ParamsBodyNode
>());
1110 DeclarationListNodeResult
newDeclarationList(ParseNodeKind kind
,
1111 const TokenPos
& pos
) {
1112 return newResult
<DeclarationListNode
>(kind
, pos
);
1115 ListNodeResult
newCommaExpressionList(Node kid
) {
1116 return newResult
<ListNode
>(ParseNodeKind::CommaExpr
, kid
);
1119 void addList(ListNodeType list
, Node kid
) { list
->append(kid
); }
1121 void setListHasNonConstInitializer(ListNodeType literal
) {
1122 literal
->setHasNonConstInitializer();
1125 // NOTE: This is infallible.
1126 template <typename NodeType
>
1127 [[nodiscard
]] NodeType
parenthesize(NodeType node
) {
1128 node
->setInParens(true);
1132 // NOTE: This is infallible.
1133 template <typename NodeType
>
1134 [[nodiscard
]] NodeType
setLikelyIIFE(NodeType node
) {
1135 return parenthesize(node
);
1138 bool isName(Node node
) { return node
->isKind(ParseNodeKind::Name
); }
1140 bool isArgumentsName(Node node
) {
1141 return node
->isKind(ParseNodeKind::Name
) &&
1142 node
->as
<NameNode
>().atom() ==
1143 TaggedParserAtomIndex::WellKnown::arguments();
1146 bool isLengthName(Node node
) {
1147 return node
->isKind(ParseNodeKind::PropertyNameExpr
) &&
1148 node
->as
<NameNode
>().atom() ==
1149 TaggedParserAtomIndex::WellKnown::length();
1152 bool isEvalName(Node node
) {
1153 return node
->isKind(ParseNodeKind::Name
) &&
1154 node
->as
<NameNode
>().atom() ==
1155 TaggedParserAtomIndex::WellKnown::eval();
1158 bool isAsyncKeyword(Node node
) {
1159 return node
->isKind(ParseNodeKind::Name
) &&
1160 node
->pn_pos
.begin
+ strlen("async") == node
->pn_pos
.end
&&
1161 node
->as
<NameNode
>().atom() ==
1162 TaggedParserAtomIndex::WellKnown::async();
1165 bool isArgumentsLength(Node node
) {
1166 return node
->isKind(ParseNodeKind::ArgumentsLength
);
1169 bool isPrivateName(Node node
) {
1170 return node
->isKind(ParseNodeKind::PrivateName
);
1173 bool isPrivateMemberAccess(Node node
) {
1174 if (node
->isKind(ParseNodeKind::OptionalChain
)) {
1175 return isPrivateMemberAccess(node
->as
<UnaryNode
>().kid());
1177 return node
->is
<PrivateMemberAccessBase
>();
1180 TaggedParserAtomIndex
maybeDottedProperty(Node pn
) {
1181 return pn
->is
<PropertyAccessBase
>() ? pn
->as
<PropertyAccessBase
>().name()
1182 : TaggedParserAtomIndex::null();
1184 TaggedParserAtomIndex
isStringExprStatement(Node pn
, TokenPos
* pos
) {
1185 if (pn
->is
<UnaryNode
>()) {
1186 UnaryNode
* unary
= &pn
->as
<UnaryNode
>();
1187 if (auto atom
= unary
->isStringExprStatement()) {
1188 *pos
= unary
->kid()->pn_pos
;
1192 return TaggedParserAtomIndex::null();
1195 bool reuseLazyInnerFunctions() { return reuseGCThings
; }
1196 bool reuseClosedOverBindings() { return reuseGCThings
; }
1197 bool reuseRegexpSyntaxParse() { return reuseGCThings
; }
1198 void nextLazyInnerFunction() { lazyInnerFunctionIndex
++; }
1199 TaggedParserAtomIndex
nextLazyClosedOverBinding() {
1200 // Trailing nullptrs were elided in PerHandlerParser::finishFunction().
1201 auto closedOverBindings
= previousParseCache_
.closedOverBindings();
1202 if (lazyClosedOverBindingIndex
>= closedOverBindings
.Length()) {
1203 return TaggedParserAtomIndex::null();
1206 return closedOverBindings
[lazyClosedOverBindingIndex
++];
1208 const ScriptStencil
& cachedScriptData() const {
1209 // lazyInnerFunctionIndex is incremented with nextLazyInnferFunction before
1210 // reading the content, thus we need -1 to access the element that we just
1212 return previousParseCache_
.scriptData(lazyInnerFunctionIndex
- 1);
1214 const ScriptStencilExtra
& cachedScriptExtra() const {
1215 // lazyInnerFunctionIndex is incremented with nextLazyInnferFunction before
1216 // reading the content, thus we need -1 to access the element that we just
1218 return previousParseCache_
.scriptExtra(lazyInnerFunctionIndex
- 1);
1221 void setPrivateNameKind(Node node
, PrivateNameKind kind
) {
1222 MOZ_ASSERT(node
->is
<NameNode
>());
1223 node
->as
<NameNode
>().setPrivateNameKind(kind
);
1227 inline bool FullParseHandler::setLastFunctionFormalParameterDefault(
1228 FunctionNodeType funNode
, Node defaultValue
) {
1229 ParamsBodyNode
* body
= funNode
->body();
1230 ParseNode
* arg
= body
->last();
1232 MOZ_TRY_VAR_OR_RETURN(
1233 pn
, newAssignment(ParseNodeKind::AssignExpr
, arg
, defaultValue
), false);
1235 body
->replaceLast(pn
);
1239 } // namespace frontend
1242 #endif /* frontend_FullParseHandler_h */