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_SyntaxParseHandler_h
8 #define frontend_SyntaxParseHandler_h
10 #include "mozilla/Assertions.h"
11 #include "mozilla/Maybe.h" // mozilla::Maybe
12 #include "mozilla/Result.h" // mozilla::Result, mozilla::UnusedZero
18 #include "frontend/CompilationStencil.h" // CompilationState
19 #include "frontend/FunctionSyntaxKind.h" // FunctionSyntaxKind
20 #include "frontend/NameAnalysisTypes.h" // PrivateNameKind
21 #include "frontend/ParseNode.h"
22 #include "frontend/ParserAtom.h" // TaggedParserAtomIndex
23 #include "frontend/TokenStream.h"
27 enum SyntaxParseHandlerNode
{
31 NodeStringExprStatement
,
38 NodeLexicalDeclaration
,
40 // A non-arrow function expression with block body, from bog-standard
42 NodeFunctionExpression
,
45 NodeFunctionStatement
,
47 // This is needed for proper assignment-target handling. ES6 formally
48 // requires function calls *not* pass IsValidSimpleAssignmentTarget,
49 // but at last check there were still sites with |f() = 5| and similar
50 // in code not actually executed (or at least not executed enough to be
54 NodeOptionalFunctionCall
,
56 // Node representing normal names which don't require any special
60 // Nodes representing the names "arguments" and "eval".
64 // Node representing the "async" name, which may actually be a
65 // contextual keyword.
66 NodePotentialAsyncKeyword
,
68 // Node representing private names.
72 NodeOptionalDottedProperty
,
75 // A distinct node for [PrivateName], to make detecting delete this.#x
76 // detectable in syntax parse
77 NodePrivateMemberAccess
,
78 NodeOptionalPrivateMemberAccess
,
80 // Destructuring target patterns can't be parenthesized: |([a]) = [3];|
81 // must be a syntax error. (We can't use NodeGeneric instead of these
82 // because that would trigger invalid-left-hand-side ReferenceError
83 // semantics when SyntaxError semantics are desired.)
84 NodeParenthesizedArray
,
85 NodeParenthesizedObject
,
87 // In rare cases a parenthesized |node| doesn't have the same semantics
88 // as |node|. Each such node has a special Node value, and we use a
89 // different Node value to represent the parenthesized form. See also
90 // is{Unp,P}arenthesized*(Node), parenthesize(Node), and the various
91 // functions that deal in NodeUnparenthesized* below.
93 // Valuable for recognizing potential destructuring patterns.
94 NodeUnparenthesizedArray
,
95 NodeUnparenthesizedObject
,
97 // The directive prologue at the start of a FunctionBody or ScriptBody
98 // is the longest sequence (possibly empty) of string literal
99 // expression statements at the start of a function. Thus we need this
100 // to treat |"use strict";| as a possible Use Strict Directive and
101 // |("use strict");| as a useless statement.
102 NodeUnparenthesizedString
,
104 // For destructuring patterns an assignment element with
105 // an initializer expression is not allowed be parenthesized.
106 // i.e. |{x = 1} = obj|
107 NodeUnparenthesizedAssignment
,
109 // This node is necessary to determine if the base operand in an
110 // exponentiation operation is an unparenthesized unary expression.
111 // We want to reject |-2 ** 3|, but still need to allow |(-2) ** 3|.
112 NodeUnparenthesizedUnary
,
114 // This node is necessary to determine if the LHS of a property access is
119 } // namespace frontend
123 struct mozilla::detail::UnusedZero
<js::frontend::SyntaxParseHandlerNode
> {
124 static const bool value
= true;
130 // Parse handler used when processing the syntax in a block of code, to generate
131 // the minimal information which is required to detect syntax errors and allow
132 // bytecode to be emitted for outer functions.
134 // When parsing, we start at the top level with a full parse, and when possible
135 // only check the syntax for inner functions, so that they can be lazily parsed
136 // into bytecode when/if they first run. Checking the syntax of a function is
137 // several times faster than doing a full parse/emit, and lazy parsing improves
138 // both performance and memory usage significantly when pages contain large
139 // amounts of code that never executes (which happens often).
140 class SyntaxParseHandler
{
141 // Remember the last encountered name or string literal during syntax parses.
142 TaggedParserAtomIndex lastAtom
;
143 TokenPos lastStringPos
;
148 using Node
= SyntaxParseHandlerNode
;
150 using NodeResult
= mozilla::Result
<Node
, NodeError
>;
151 using NodeErrorResult
= mozilla::GenericErrorResult
<NodeError
>;
153 #define DECLARE_TYPE(typeName) \
154 using typeName##Type = Node; \
155 using typeName##Result = mozilla::Result<Node, NodeError>;
156 FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE
)
159 using NullNode
= Node
;
161 bool isNonArrowFunctionExpression(Node node
) const {
162 return node
== NodeFunctionExpression
;
165 bool isPropertyOrPrivateMemberAccess(Node node
) {
166 return node
== NodeDottedProperty
|| node
== NodeElement
||
167 node
== NodePrivateMemberAccess
;
170 bool isOptionalPropertyOrPrivateMemberAccess(Node node
) {
171 return node
== NodeOptionalDottedProperty
|| node
== NodeOptionalElement
||
172 node
== NodeOptionalPrivateMemberAccess
;
175 bool isFunctionCall(Node node
) {
176 // Note: super() is a special form, *not* a function call.
177 return node
== NodeFunctionCall
;
180 static bool isUnparenthesizedDestructuringPattern(Node node
) {
181 return node
== NodeUnparenthesizedArray
||
182 node
== NodeUnparenthesizedObject
;
185 static bool isParenthesizedDestructuringPattern(Node node
) {
186 // Technically this isn't a destructuring target at all -- the grammar
187 // doesn't treat it as such. But we need to know when this happens to
188 // consider it a SyntaxError rather than an invalid-left-hand-side
190 return node
== NodeParenthesizedArray
|| node
== NodeParenthesizedObject
;
194 SyntaxParseHandler(FrontendContext
* fc
, CompilationState
& compilationState
) {
195 MOZ_ASSERT(!compilationState
.input
.isDelazifying());
198 static NullNode
null() { return NodeFailure
; }
199 static constexpr NodeErrorResult
errorResult() {
200 return NodeErrorResult(NodeError());
203 #define DECLARE_AS(typeName) \
204 static typeName##Type as##typeName(Node node) { return node; }
205 FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS
)
208 NameNodeResult
newName(TaggedParserAtomIndex name
, const TokenPos
& pos
) {
210 if (name
== TaggedParserAtomIndex::WellKnown::arguments()) {
211 return NodeArgumentsName
;
213 if (pos
.begin
+ strlen("async") == pos
.end
&&
214 name
== TaggedParserAtomIndex::WellKnown::async()) {
215 return NodePotentialAsyncKeyword
;
217 if (name
== TaggedParserAtomIndex::WellKnown::eval()) {
223 UnaryNodeResult
newComputedName(Node expr
, uint32_t start
, uint32_t end
) {
227 UnaryNodeResult
newSyntheticComputedName(Node expr
, uint32_t start
,
232 NameNodeResult
newObjectLiteralPropertyName(TaggedParserAtomIndex atom
,
233 const TokenPos
& pos
) {
237 NameNodeResult
newPrivateName(TaggedParserAtomIndex atom
,
238 const TokenPos
& pos
) {
239 return NodePrivateName
;
242 NumericLiteralResult
newNumber(double value
, DecimalPoint decimalPoint
,
243 const TokenPos
& pos
) {
247 BigIntLiteralResult
newBigInt() { return NodeGeneric
; }
249 BooleanLiteralResult
newBooleanLiteral(bool cond
, const TokenPos
& pos
) {
253 NameNodeResult
newStringLiteral(TaggedParserAtomIndex atom
,
254 const TokenPos
& pos
) {
257 return NodeUnparenthesizedString
;
260 NameNodeResult
newTemplateStringLiteral(TaggedParserAtomIndex atom
,
261 const TokenPos
& pos
) {
265 CallSiteNodeResult
newCallSiteObject(uint32_t begin
) { return NodeGeneric
; }
267 void addToCallSiteObject(CallSiteNodeType callSiteObj
, Node rawNode
,
270 ThisLiteralResult
newThisLiteral(const TokenPos
& pos
, Node thisName
) {
273 NullLiteralResult
newNullLiteral(const TokenPos
& pos
) { return NodeGeneric
; }
274 RawUndefinedLiteralResult
newRawUndefinedLiteral(const TokenPos
& pos
) {
278 RegExpLiteralResult
newRegExp(Node reobj
, const TokenPos
& pos
) {
282 ConditionalExpressionResult
newConditional(Node cond
, Node thenExpr
,
287 UnaryNodeResult
newDelete(uint32_t begin
, Node expr
) {
288 return NodeUnparenthesizedUnary
;
291 UnaryNodeResult
newTypeof(uint32_t begin
, Node kid
) {
292 return NodeUnparenthesizedUnary
;
295 UnaryNodeResult
newUnary(ParseNodeKind kind
, uint32_t begin
, Node kid
) {
296 return NodeUnparenthesizedUnary
;
299 UnaryNodeResult
newUpdate(ParseNodeKind kind
, uint32_t begin
, Node kid
) {
303 UnaryNodeResult
newSpread(uint32_t begin
, Node kid
) { return NodeGeneric
; }
305 NodeResult
appendOrCreateList(ParseNodeKind kind
, Node left
, Node right
,
312 ListNodeResult
newArrayLiteral(uint32_t begin
) {
313 return NodeUnparenthesizedArray
;
315 [[nodiscard
]] bool addElision(ListNodeType literal
, const TokenPos
& pos
) {
318 [[nodiscard
]] bool addSpreadElement(ListNodeType literal
, uint32_t begin
,
322 void addArrayElement(ListNodeType literal
, Node element
) {}
324 ListNodeResult
newArguments(const TokenPos
& pos
) { return NodeGeneric
; }
325 CallNodeResult
newCall(Node callee
, ListNodeType args
, JSOp callOp
) {
326 return NodeFunctionCall
;
329 CallNodeResult
newOptionalCall(Node callee
, ListNodeType args
, JSOp callOp
) {
330 return NodeOptionalFunctionCall
;
333 CallNodeResult
newSuperCall(Node callee
, ListNodeType args
, bool isSpread
) {
336 CallNodeResult
newTaggedTemplate(Node tag
, ListNodeType args
, JSOp callOp
) {
340 ListNodeResult
newObjectLiteral(uint32_t begin
) {
341 return NodeUnparenthesizedObject
;
344 #ifdef ENABLE_RECORD_TUPLE
345 ListNodeResult
newRecordLiteral(uint32_t begin
) { return NodeGeneric
; }
347 ListNodeResult
newTupleLiteral(uint32_t begin
) { return NodeGeneric
; }
350 ListNodeResult
newClassMemberList(uint32_t begin
) { return NodeGeneric
; }
351 ClassNamesResult
newClassNames(Node outer
, Node inner
, const TokenPos
& pos
) {
354 ClassNodeResult
newClass(Node name
, Node heritage
, Node methodBlock
,
355 #ifdef ENABLE_DECORATORS
356 ListNodeType decorators
,
358 const TokenPos
& pos
) {
362 LexicalScopeNodeResult
newLexicalScope(Node body
) {
363 return NodeLexicalDeclaration
;
366 ClassBodyScopeNodeResult
newClassBodyScope(Node body
) {
367 return NodeLexicalDeclaration
;
370 NewTargetNodeResult
newNewTarget(NullaryNodeType newHolder
,
371 NullaryNodeType targetHolder
,
372 NameNodeType newTargetName
) {
375 NullaryNodeResult
newPosHolder(const TokenPos
& pos
) { return NodeGeneric
; }
376 UnaryNodeResult
newSuperBase(Node thisName
, const TokenPos
& pos
) {
377 return NodeSuperBase
;
380 [[nodiscard
]] bool addPrototypeMutation(ListNodeType literal
, uint32_t begin
,
384 BinaryNodeResult
newPropertyDefinition(Node key
, Node val
) {
387 void addPropertyDefinition(ListNodeType literal
, BinaryNodeType propdef
) {}
388 [[nodiscard
]] bool addPropertyDefinition(ListNodeType literal
, Node key
,
392 [[nodiscard
]] bool addShorthand(ListNodeType literal
, NameNodeType name
,
396 [[nodiscard
]] bool addSpreadProperty(ListNodeType literal
, uint32_t begin
,
400 [[nodiscard
]] bool addObjectMethodDefinition(ListNodeType literal
, Node key
,
401 FunctionNodeType funNode
,
402 AccessorType atype
) {
405 [[nodiscard
]] NodeResult
newDefaultClassConstructor(
406 Node key
, FunctionNodeType funNode
) {
409 [[nodiscard
]] NodeResult
newClassMethodDefinition(
410 Node key
, FunctionNodeType funNode
, AccessorType atype
, bool isStatic
,
411 mozilla::Maybe
<FunctionNodeType
> initializerIfPrivate
412 #ifdef ENABLE_DECORATORS
414 ListNodeType decorators
419 [[nodiscard
]] NodeResult
newClassFieldDefinition(
420 Node name
, FunctionNodeType initializer
, bool isStatic
421 #ifdef ENABLE_DECORATORS
423 ListNodeType decorators
, ClassMethodType accessorGetterNode
,
424 ClassMethodType accessorSetterNode
430 [[nodiscard
]] NodeResult
newStaticClassBlock(FunctionNodeType block
) {
434 [[nodiscard
]] bool addClassMemberDefinition(ListNodeType memberList
,
438 UnaryNodeResult
newYieldExpression(uint32_t begin
, Node value
) {
441 UnaryNodeResult
newYieldStarExpression(uint32_t begin
, Node value
) {
444 UnaryNodeResult
newAwaitExpression(uint32_t begin
, Node value
) {
445 return NodeUnparenthesizedUnary
;
447 UnaryNodeResult
newOptionalChain(uint32_t begin
, Node value
) {
453 ListNodeResult
newStatementList(const TokenPos
& pos
) { return NodeGeneric
; }
454 void addStatementToList(ListNodeType list
, Node stmt
) {}
455 void setListEndPosition(ListNodeType list
, const TokenPos
& pos
) {}
456 void addCaseStatementToList(ListNodeType list
, CaseClauseType caseClause
) {}
457 [[nodiscard
]] bool prependInitialYield(ListNodeType stmtList
, Node genName
) {
460 NullaryNodeResult
newEmptyStatement(const TokenPos
& pos
) {
461 return NodeEmptyStatement
;
464 BinaryNodeResult
newImportAssertion(Node keyNode
, Node valueNode
) {
467 BinaryNodeResult
newModuleRequest(Node moduleSpec
, Node importAssertionList
,
468 const TokenPos
& pos
) {
471 BinaryNodeResult
newImportDeclaration(Node importSpecSet
, Node moduleRequest
,
472 const TokenPos
& pos
) {
475 BinaryNodeResult
newImportSpec(Node importNameNode
, Node bindingName
) {
478 UnaryNodeResult
newImportNamespaceSpec(uint32_t begin
, Node bindingName
) {
481 UnaryNodeResult
newExportDeclaration(Node kid
, const TokenPos
& pos
) {
484 BinaryNodeResult
newExportFromDeclaration(uint32_t begin
, Node exportSpecSet
,
485 Node moduleRequest
) {
488 BinaryNodeResult
newExportDefaultDeclaration(Node kid
, Node maybeBinding
,
489 const TokenPos
& pos
) {
492 BinaryNodeResult
newExportSpec(Node bindingName
, Node exportName
) {
495 UnaryNodeResult
newExportNamespaceSpec(uint32_t begin
, Node exportName
) {
498 NullaryNodeResult
newExportBatchSpec(const TokenPos
& pos
) {
501 BinaryNodeResult
newImportMeta(NullaryNodeType importHolder
,
502 NullaryNodeType metaHolder
) {
505 BinaryNodeResult
newCallImport(NullaryNodeType importHolder
, Node singleArg
) {
508 BinaryNodeResult
newCallImportSpec(Node specifierArg
, Node optionalArg
) {
512 BinaryNodeResult
newSetThis(Node thisName
, Node value
) { return value
; }
514 UnaryNodeResult
newExprStatement(Node expr
, uint32_t end
) {
515 return expr
== NodeUnparenthesizedString
? NodeStringExprStatement
519 TernaryNodeResult
newIfStatement(uint32_t begin
, Node cond
, Node thenBranch
,
523 BinaryNodeResult
newDoWhileStatement(Node body
, Node cond
,
524 const TokenPos
& pos
) {
527 BinaryNodeResult
newWhileStatement(uint32_t begin
, Node cond
, Node body
) {
530 SwitchStatementResult
newSwitchStatement(
531 uint32_t begin
, Node discriminant
,
532 LexicalScopeNodeType lexicalForCaseList
, bool hasDefault
) {
535 CaseClauseResult
newCaseOrDefault(uint32_t begin
, Node expr
, Node body
) {
538 ContinueStatementResult
newContinueStatement(TaggedParserAtomIndex label
,
539 const TokenPos
& pos
) {
542 BreakStatementResult
newBreakStatement(TaggedParserAtomIndex label
,
543 const TokenPos
& pos
) {
546 UnaryNodeResult
newReturnStatement(Node expr
, const TokenPos
& pos
) {
549 UnaryNodeResult
newExpressionBody(Node expr
) { return NodeReturn
; }
550 BinaryNodeResult
newWithStatement(uint32_t begin
, Node expr
, Node body
) {
554 LabeledStatementResult
newLabeledStatement(TaggedParserAtomIndex label
,
555 Node stmt
, uint32_t begin
) {
559 UnaryNodeResult
newThrowStatement(Node expr
, const TokenPos
& pos
) {
562 TernaryNodeResult
newTryStatement(uint32_t begin
, Node body
,
563 LexicalScopeNodeType catchScope
,
567 DebuggerStatementResult
newDebuggerStatement(const TokenPos
& pos
) {
571 NameNodeResult
newPropertyName(TaggedParserAtomIndex name
,
572 const TokenPos
& pos
) {
577 PropertyAccessResult
newPropertyAccess(Node expr
, NameNodeType key
) {
578 return NodeDottedProperty
;
581 PropertyAccessResult
newOptionalPropertyAccess(Node expr
, NameNodeType key
) {
582 return NodeOptionalDottedProperty
;
585 PropertyByValueResult
newPropertyByValue(Node lhs
, Node index
, uint32_t end
) {
586 MOZ_ASSERT(!isPrivateName(index
));
590 PropertyByValueResult
newOptionalPropertyByValue(Node lhs
, Node index
,
592 return NodeOptionalElement
;
595 PrivateMemberAccessResult
newPrivateMemberAccess(Node lhs
, Node privateName
,
597 return NodePrivateMemberAccess
;
600 PrivateMemberAccessResult
newOptionalPrivateMemberAccess(Node lhs
,
603 return NodeOptionalPrivateMemberAccess
;
606 [[nodiscard
]] bool setupCatchScope(LexicalScopeNodeType lexicalScope
,
607 Node catchName
, Node catchBody
) {
611 [[nodiscard
]] bool setLastFunctionFormalParameterDefault(
612 FunctionNodeType funNode
, Node defaultValue
) {
616 void checkAndSetIsDirectRHSAnonFunction(Node pn
) {}
618 ParamsBodyNodeResult
newParamsBody(const TokenPos
& pos
) {
622 FunctionNodeResult
newFunction(FunctionSyntaxKind syntaxKind
,
623 const TokenPos
& pos
) {
624 switch (syntaxKind
) {
625 case FunctionSyntaxKind::Statement
:
626 return NodeFunctionStatement
;
627 case FunctionSyntaxKind::Arrow
:
628 return NodeFunctionArrow
;
630 // All non-arrow function expressions are initially presumed to have
631 // block body. This will be overridden later *if* the function
632 // expression permissibly has an AssignmentExpression body.
633 return NodeFunctionExpression
;
637 void setFunctionFormalParametersAndBody(FunctionNodeType funNode
,
638 ParamsBodyNodeType paramsBody
) {}
639 void setFunctionBody(FunctionNodeType funNode
, LexicalScopeNodeType body
) {}
640 void setFunctionBox(FunctionNodeType funNode
, FunctionBox
* funbox
) {}
641 void addFunctionFormalParameter(FunctionNodeType funNode
, Node argpn
) {}
643 ForNodeResult
newForStatement(uint32_t begin
, TernaryNodeType forHead
,
644 Node body
, unsigned iflags
) {
648 TernaryNodeResult
newForHead(Node init
, Node test
, Node update
,
649 const TokenPos
& pos
) {
653 TernaryNodeResult
newForInOrOfHead(ParseNodeKind kind
, Node target
,
654 Node iteratedExpr
, const TokenPos
& pos
) {
658 AssignmentNodeResult
finishInitializerAssignment(NameNodeType nameNode
,
660 return NodeUnparenthesizedAssignment
;
663 void setBeginPosition(Node pn
, Node oth
) {}
664 void setBeginPosition(Node pn
, uint32_t begin
) {}
666 void setEndPosition(Node pn
, Node oth
) {}
667 void setEndPosition(Node pn
, uint32_t end
) {}
669 uint32_t getFunctionNameOffset(Node func
, TokenStreamAnyChars
& ts
) {
670 // XXX This offset isn't relevant to the offending function name. But
671 // we may not *have* that function name around, because of how lazy
672 // parsing works -- the actual name could be outside
673 // |tokenStream.userbuf|'s observed region. So the current offset
674 // is the best we can do.
675 return ts
.currentToken().pos
.begin
;
678 ListNodeResult
newList(ParseNodeKind kind
, const TokenPos
& pos
) {
679 MOZ_ASSERT(kind
!= ParseNodeKind::VarStmt
);
680 MOZ_ASSERT(kind
!= ParseNodeKind::LetDecl
);
681 MOZ_ASSERT(kind
!= ParseNodeKind::ConstDecl
);
682 MOZ_ASSERT(kind
!= ParseNodeKind::ParamsBody
);
686 ListNodeResult
newList(ParseNodeKind kind
, Node kid
) {
687 return newList(kind
, TokenPos());
690 DeclarationListNodeResult
newDeclarationList(ParseNodeKind kind
,
691 const TokenPos
& pos
) {
692 if (kind
== ParseNodeKind::VarStmt
) {
693 return NodeVarDeclaration
;
695 MOZ_ASSERT(kind
== ParseNodeKind::LetDecl
||
696 kind
== ParseNodeKind::ConstDecl
);
697 return NodeLexicalDeclaration
;
700 ListNodeResult
newCommaExpressionList(Node kid
) { return NodeGeneric
; }
702 void addList(ListNodeType list
, Node kid
) {
703 MOZ_ASSERT(list
== NodeGeneric
|| list
== NodeUnparenthesizedArray
||
704 list
== NodeUnparenthesizedObject
||
705 list
== NodeVarDeclaration
|| list
== NodeLexicalDeclaration
||
706 list
== NodeFunctionCall
);
709 CallNodeResult
newNewExpression(uint32_t begin
, Node ctor
, ListNodeType args
,
714 AssignmentNodeResult
newAssignment(ParseNodeKind kind
, Node lhs
, Node rhs
) {
715 return kind
== ParseNodeKind::AssignExpr
? NodeUnparenthesizedAssignment
719 AssignmentNodeResult
newInitExpr(Node lhs
, Node rhs
) { return NodeGeneric
; }
721 bool isUnparenthesizedAssignment(Node node
) {
722 return node
== NodeUnparenthesizedAssignment
;
725 bool isUnparenthesizedUnaryExpression(Node node
) {
726 return node
== NodeUnparenthesizedUnary
;
729 bool isReturnStatement(Node node
) { return node
== NodeReturn
; }
731 bool isStatementPermittedAfterReturnStatement(Node pn
) {
732 return pn
== NodeFunctionStatement
|| isNonArrowFunctionExpression(pn
) ||
733 pn
== NodeVarDeclaration
|| pn
== NodeBreak
|| pn
== NodeThrow
||
734 pn
== NodeEmptyStatement
;
737 bool isSuperBase(Node pn
) { return pn
== NodeSuperBase
; }
739 void setListHasNonConstInitializer(ListNodeType literal
) {}
741 // NOTE: This is infallible.
742 [[nodiscard
]] Node
parenthesize(Node node
) {
743 // A number of nodes have different behavior upon parenthesization, but
744 // only in some circumstances. Convert these nodes to special
745 // parenthesized forms.
746 if (node
== NodeUnparenthesizedArray
) {
747 return NodeParenthesizedArray
;
749 if (node
== NodeUnparenthesizedObject
) {
750 return NodeParenthesizedObject
;
753 // Other nodes need not be recognizable after parenthesization; convert
754 // them to a generic node.
755 if (node
== NodeUnparenthesizedString
||
756 node
== NodeUnparenthesizedAssignment
||
757 node
== NodeUnparenthesizedUnary
) {
761 // Convert parenthesized |async| to a normal name node.
762 if (node
== NodePotentialAsyncKeyword
) {
766 // In all other cases, the parenthesized form of |node| is equivalent
767 // to the unparenthesized form: return |node| unchanged.
771 // NOTE: This is infallible.
772 template <typename NodeType
>
773 [[nodiscard
]] NodeType
setLikelyIIFE(NodeType node
) {
774 return node
; // Remain in syntax-parse mode.
777 bool isName(Node node
) {
778 return node
== NodeName
|| node
== NodeArgumentsName
||
779 node
== NodeEvalName
|| node
== NodePotentialAsyncKeyword
;
782 bool isArgumentsName(Node node
) { return node
== NodeArgumentsName
; }
783 bool isEvalName(Node node
) { return node
== NodeEvalName
; }
784 bool isAsyncKeyword(Node node
) { return node
== NodePotentialAsyncKeyword
; }
786 bool isPrivateName(Node node
) { return node
== NodePrivateName
; }
787 bool isPrivateMemberAccess(Node node
) {
788 return node
== NodePrivateMemberAccess
;
791 TaggedParserAtomIndex
maybeDottedProperty(Node node
) {
792 // Note: |super.apply(...)| is a special form that calls an "apply"
793 // method retrieved from one value, but using a *different* value as
794 // |this|. It's not really eligible for the funapply/funcall
795 // optimizations as they're currently implemented (assuming a single
796 // value is used for both retrieval and |this|).
797 if (node
!= NodeDottedProperty
&& node
!= NodeOptionalDottedProperty
) {
798 return TaggedParserAtomIndex::null();
803 TaggedParserAtomIndex
isStringExprStatement(Node pn
, TokenPos
* pos
) {
804 if (pn
== NodeStringExprStatement
) {
805 *pos
= lastStringPos
;
808 return TaggedParserAtomIndex::null();
811 bool reuseLazyInnerFunctions() { return false; }
812 bool reuseClosedOverBindings() { return false; }
813 TaggedParserAtomIndex
nextLazyClosedOverBinding() {
815 "SyntaxParseHandler::canSkipLazyClosedOverBindings must return false");
818 void setPrivateNameKind(Node node
, PrivateNameKind kind
) {}
821 } // namespace frontend
824 #endif /* frontend_SyntaxParseHandler_h */