Bug 1852740: add tests for the `fetchpriority` attribute in Link headers. r=necko...
[gecko.git] / js / src / frontend / SyntaxParseHandler.h
blob40c1078e4cd79928b8cca7bf8afe5bf5b286444f
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
13 #include <string.h>
15 #include "jstypes.h"
17 #include "frontend/CompilationStencil.h" // CompilationState
18 #include "frontend/FunctionSyntaxKind.h" // FunctionSyntaxKind
19 #include "frontend/NameAnalysisTypes.h" // PrivateNameKind
20 #include "frontend/ParseNode.h"
21 #include "frontend/ParserAtom.h" // TaggedParserAtomIndex
22 #include "frontend/TokenStream.h"
24 namespace js {
26 namespace frontend {
28 // Parse handler used when processing the syntax in a block of code, to generate
29 // the minimal information which is required to detect syntax errors and allow
30 // bytecode to be emitted for outer functions.
32 // When parsing, we start at the top level with a full parse, and when possible
33 // only check the syntax for inner functions, so that they can be lazily parsed
34 // into bytecode when/if they first run. Checking the syntax of a function is
35 // several times faster than doing a full parse/emit, and lazy parsing improves
36 // both performance and memory usage significantly when pages contain large
37 // amounts of code that never executes (which happens often).
38 class SyntaxParseHandler {
39 // Remember the last encountered name or string literal during syntax parses.
40 TaggedParserAtomIndex lastAtom;
41 TokenPos lastStringPos;
43 public:
44 enum Node {
45 NodeFailure = 0,
46 NodeGeneric,
47 NodeGetProp,
48 NodeStringExprStatement,
49 NodeReturn,
50 NodeBreak,
51 NodeThrow,
52 NodeEmptyStatement,
54 NodeVarDeclaration,
55 NodeLexicalDeclaration,
57 // A non-arrow function expression with block body, from bog-standard
58 // ECMAScript.
59 NodeFunctionExpression,
61 NodeFunctionArrow,
62 NodeFunctionStatement,
64 // This is needed for proper assignment-target handling. ES6 formally
65 // requires function calls *not* pass IsValidSimpleAssignmentTarget,
66 // but at last check there were still sites with |f() = 5| and similar
67 // in code not actually executed (or at least not executed enough to be
68 // noticed).
69 NodeFunctionCall,
71 NodeOptionalFunctionCall,
73 // Node representing normal names which don't require any special
74 // casing.
75 NodeName,
77 // Nodes representing the names "arguments" and "eval".
78 NodeArgumentsName,
79 NodeEvalName,
81 // Node representing the "async" name, which may actually be a
82 // contextual keyword.
83 NodePotentialAsyncKeyword,
85 // Node representing private names.
86 NodePrivateName,
88 NodeDottedProperty,
89 NodeOptionalDottedProperty,
90 NodeElement,
91 NodeOptionalElement,
92 // A distinct node for [PrivateName], to make detecting delete this.#x
93 // detectable in syntax parse
94 NodePrivateMemberAccess,
95 NodeOptionalPrivateMemberAccess,
97 // Destructuring target patterns can't be parenthesized: |([a]) = [3];|
98 // must be a syntax error. (We can't use NodeGeneric instead of these
99 // because that would trigger invalid-left-hand-side ReferenceError
100 // semantics when SyntaxError semantics are desired.)
101 NodeParenthesizedArray,
102 NodeParenthesizedObject,
104 // In rare cases a parenthesized |node| doesn't have the same semantics
105 // as |node|. Each such node has a special Node value, and we use a
106 // different Node value to represent the parenthesized form. See also
107 // is{Unp,P}arenthesized*(Node), parenthesize(Node), and the various
108 // functions that deal in NodeUnparenthesized* below.
110 // Valuable for recognizing potential destructuring patterns.
111 NodeUnparenthesizedArray,
112 NodeUnparenthesizedObject,
114 // The directive prologue at the start of a FunctionBody or ScriptBody
115 // is the longest sequence (possibly empty) of string literal
116 // expression statements at the start of a function. Thus we need this
117 // to treat |"use strict";| as a possible Use Strict Directive and
118 // |("use strict");| as a useless statement.
119 NodeUnparenthesizedString,
121 // For destructuring patterns an assignment element with
122 // an initializer expression is not allowed be parenthesized.
123 // i.e. |{x = 1} = obj|
124 NodeUnparenthesizedAssignment,
126 // This node is necessary to determine if the base operand in an
127 // exponentiation operation is an unparenthesized unary expression.
128 // We want to reject |-2 ** 3|, but still need to allow |(-2) ** 3|.
129 NodeUnparenthesizedUnary,
131 // This node is necessary to determine if the LHS of a property access is
132 // super related.
133 NodeSuperBase
136 #define DECLARE_TYPE(typeName, longTypeName, asMethodName) \
137 using longTypeName = Node;
138 FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
139 #undef DECLARE_TYPE
141 using NullNode = Node;
143 bool isNonArrowFunctionExpression(Node node) const {
144 return node == NodeFunctionExpression;
147 bool isPropertyOrPrivateMemberAccess(Node node) {
148 return node == NodeDottedProperty || node == NodeElement ||
149 node == NodePrivateMemberAccess;
152 bool isOptionalPropertyOrPrivateMemberAccess(Node node) {
153 return node == NodeOptionalDottedProperty || node == NodeOptionalElement ||
154 node == NodeOptionalPrivateMemberAccess;
157 bool isFunctionCall(Node node) {
158 // Note: super() is a special form, *not* a function call.
159 return node == NodeFunctionCall;
162 static bool isUnparenthesizedDestructuringPattern(Node node) {
163 return node == NodeUnparenthesizedArray ||
164 node == NodeUnparenthesizedObject;
167 static bool isParenthesizedDestructuringPattern(Node node) {
168 // Technically this isn't a destructuring target at all -- the grammar
169 // doesn't treat it as such. But we need to know when this happens to
170 // consider it a SyntaxError rather than an invalid-left-hand-side
171 // ReferenceError.
172 return node == NodeParenthesizedArray || node == NodeParenthesizedObject;
175 public:
176 SyntaxParseHandler(FrontendContext* fc, CompilationState& compilationState) {
177 MOZ_ASSERT(!compilationState.input.isDelazifying());
180 static NullNode null() { return NodeFailure; }
182 #define DECLARE_AS(typeName, longTypeName, asMethodName) \
183 static longTypeName asMethodName(Node node) { return node; }
184 FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
185 #undef DECLARE_AS
187 NameNodeType newName(TaggedParserAtomIndex name, const TokenPos& pos) {
188 lastAtom = name;
189 if (name == TaggedParserAtomIndex::WellKnown::arguments()) {
190 return NodeArgumentsName;
192 if (pos.begin + strlen("async") == pos.end &&
193 name == TaggedParserAtomIndex::WellKnown::async()) {
194 return NodePotentialAsyncKeyword;
196 if (name == TaggedParserAtomIndex::WellKnown::eval()) {
197 return NodeEvalName;
199 return NodeName;
202 UnaryNodeType newComputedName(Node expr, uint32_t start, uint32_t end) {
203 return NodeGeneric;
206 UnaryNodeType newSyntheticComputedName(Node expr, uint32_t start,
207 uint32_t end) {
208 return NodeGeneric;
211 NameNodeType newObjectLiteralPropertyName(TaggedParserAtomIndex atom,
212 const TokenPos& pos) {
213 return NodeName;
216 NameNodeType newPrivateName(TaggedParserAtomIndex atom, const TokenPos& pos) {
217 return NodePrivateName;
220 NumericLiteralType newNumber(double value, DecimalPoint decimalPoint,
221 const TokenPos& pos) {
222 return NodeGeneric;
225 BigIntLiteralType newBigInt() { return NodeGeneric; }
227 BooleanLiteralType newBooleanLiteral(bool cond, const TokenPos& pos) {
228 return NodeGeneric;
231 NameNodeType newStringLiteral(TaggedParserAtomIndex atom,
232 const TokenPos& pos) {
233 lastAtom = atom;
234 lastStringPos = pos;
235 return NodeUnparenthesizedString;
238 NameNodeType newTemplateStringLiteral(TaggedParserAtomIndex atom,
239 const TokenPos& pos) {
240 return NodeGeneric;
243 CallSiteNodeType newCallSiteObject(uint32_t begin) { return NodeGeneric; }
245 void addToCallSiteObject(CallSiteNodeType callSiteObj, Node rawNode,
246 Node cookedNode) {}
248 ThisLiteralType newThisLiteral(const TokenPos& pos, Node thisName) {
249 return NodeGeneric;
251 NullLiteralType newNullLiteral(const TokenPos& pos) { return NodeGeneric; }
252 RawUndefinedLiteralType newRawUndefinedLiteral(const TokenPos& pos) {
253 return NodeGeneric;
256 RegExpLiteralType newRegExp(Node reobj, const TokenPos& pos) {
257 return NodeGeneric;
260 ConditionalExpressionType newConditional(Node cond, Node thenExpr,
261 Node elseExpr) {
262 return NodeGeneric;
265 UnaryNodeType newDelete(uint32_t begin, Node expr) {
266 return NodeUnparenthesizedUnary;
269 UnaryNodeType newTypeof(uint32_t begin, Node kid) {
270 return NodeUnparenthesizedUnary;
273 UnaryNodeType newUnary(ParseNodeKind kind, uint32_t begin, Node kid) {
274 return NodeUnparenthesizedUnary;
277 UnaryNodeType newUpdate(ParseNodeKind kind, uint32_t begin, Node kid) {
278 return NodeGeneric;
281 UnaryNodeType newSpread(uint32_t begin, Node kid) { return NodeGeneric; }
283 Node appendOrCreateList(ParseNodeKind kind, Node left, Node right,
284 ParseContext* pc) {
285 return NodeGeneric;
288 // Expressions
290 ListNodeType newArrayLiteral(uint32_t begin) {
291 return NodeUnparenthesizedArray;
293 [[nodiscard]] bool addElision(ListNodeType literal, const TokenPos& pos) {
294 return true;
296 [[nodiscard]] bool addSpreadElement(ListNodeType literal, uint32_t begin,
297 Node inner) {
298 return true;
300 void addArrayElement(ListNodeType literal, Node element) {}
302 ListNodeType newArguments(const TokenPos& pos) { return NodeGeneric; }
303 CallNodeType newCall(Node callee, ListNodeType args, JSOp callOp) {
304 return NodeFunctionCall;
307 CallNodeType newOptionalCall(Node callee, ListNodeType args, JSOp callOp) {
308 return NodeOptionalFunctionCall;
311 CallNodeType newSuperCall(Node callee, ListNodeType args, bool isSpread) {
312 return NodeGeneric;
314 CallNodeType newTaggedTemplate(Node tag, ListNodeType args, JSOp callOp) {
315 return NodeGeneric;
318 ListNodeType newObjectLiteral(uint32_t begin) {
319 return NodeUnparenthesizedObject;
322 #ifdef ENABLE_RECORD_TUPLE
323 ListNodeType newRecordLiteral(uint32_t begin) { return NodeGeneric; }
325 ListNodeType newTupleLiteral(uint32_t begin) { return NodeGeneric; }
326 #endif
328 ListNodeType newClassMemberList(uint32_t begin) { return NodeGeneric; }
329 ClassNamesType newClassNames(Node outer, Node inner, const TokenPos& pos) {
330 return NodeGeneric;
332 ClassNodeType newClass(Node name, Node heritage, Node methodBlock,
333 #ifdef ENABLE_DECORATORS
334 ListNodeType decorators,
335 #endif
336 const TokenPos& pos) {
337 return NodeGeneric;
340 LexicalScopeNodeType newLexicalScope(Node body) {
341 return NodeLexicalDeclaration;
344 ClassBodyScopeNodeType newClassBodyScope(Node body) {
345 return NodeLexicalDeclaration;
348 NewTargetNodeType newNewTarget(NullaryNodeType newHolder,
349 NullaryNodeType targetHolder,
350 NameNodeType newTargetName) {
351 return NodeGeneric;
353 NullaryNodeType newPosHolder(const TokenPos& pos) { return NodeGeneric; }
354 UnaryNodeType newSuperBase(Node thisName, const TokenPos& pos) {
355 return NodeSuperBase;
358 [[nodiscard]] bool addPrototypeMutation(ListNodeType literal, uint32_t begin,
359 Node expr) {
360 return true;
362 BinaryNodeType newPropertyDefinition(Node key, Node val) {
363 return NodeGeneric;
365 void addPropertyDefinition(ListNodeType literal, BinaryNodeType propdef) {}
366 [[nodiscard]] bool addPropertyDefinition(ListNodeType literal, Node key,
367 Node expr) {
368 return true;
370 [[nodiscard]] bool addShorthand(ListNodeType literal, NameNodeType name,
371 NameNodeType expr) {
372 return true;
374 [[nodiscard]] bool addSpreadProperty(ListNodeType literal, uint32_t begin,
375 Node inner) {
376 return true;
378 [[nodiscard]] bool addObjectMethodDefinition(ListNodeType literal, Node key,
379 FunctionNodeType funNode,
380 AccessorType atype) {
381 return true;
383 [[nodiscard]] Node newDefaultClassConstructor(Node key,
384 FunctionNodeType funNode) {
385 return NodeGeneric;
387 [[nodiscard]] Node newClassMethodDefinition(
388 Node key, FunctionNodeType funNode, AccessorType atype, bool isStatic,
389 mozilla::Maybe<FunctionNodeType> initializerIfPrivate
390 #ifdef ENABLE_DECORATORS
392 ListNodeType decorators
393 #endif
395 return NodeGeneric;
397 [[nodiscard]] Node newClassFieldDefinition(Node name,
398 FunctionNodeType initializer,
399 bool isStatic
400 #ifdef ENABLE_DECORATORS
402 ListNodeType decorators,
403 ClassMethodType accessorGetterNode,
404 ClassMethodType accessorSetterNode
405 #endif
407 return NodeGeneric;
410 [[nodiscard]] Node newStaticClassBlock(FunctionNodeType block) {
411 return NodeGeneric;
414 [[nodiscard]] bool addClassMemberDefinition(ListNodeType memberList,
415 Node member) {
416 return true;
418 UnaryNodeType newYieldExpression(uint32_t begin, Node value) {
419 return NodeGeneric;
421 UnaryNodeType newYieldStarExpression(uint32_t begin, Node value) {
422 return NodeGeneric;
424 UnaryNodeType newAwaitExpression(uint32_t begin, Node value) {
425 return NodeUnparenthesizedUnary;
427 UnaryNodeType newOptionalChain(uint32_t begin, Node value) {
428 return NodeGeneric;
431 // Statements
433 ListNodeType newStatementList(const TokenPos& pos) { return NodeGeneric; }
434 void addStatementToList(ListNodeType list, Node stmt) {}
435 void setListEndPosition(ListNodeType list, const TokenPos& pos) {}
436 void addCaseStatementToList(ListNodeType list, CaseClauseType caseClause) {}
437 [[nodiscard]] bool prependInitialYield(ListNodeType stmtList, Node genName) {
438 return true;
440 NullaryNodeType newEmptyStatement(const TokenPos& pos) {
441 return NodeEmptyStatement;
444 BinaryNodeType newImportAssertion(Node keyNode, Node valueNode) {
445 return NodeGeneric;
447 BinaryNodeType newModuleRequest(Node moduleSpec, Node importAssertionList,
448 const TokenPos& pos) {
449 return NodeGeneric;
451 BinaryNodeType newImportDeclaration(Node importSpecSet, Node moduleRequest,
452 const TokenPos& pos) {
453 return NodeGeneric;
455 BinaryNodeType newImportSpec(Node importNameNode, Node bindingName) {
456 return NodeGeneric;
458 UnaryNodeType newImportNamespaceSpec(uint32_t begin, Node bindingName) {
459 return NodeGeneric;
461 UnaryNodeType newExportDeclaration(Node kid, const TokenPos& pos) {
462 return NodeGeneric;
464 BinaryNodeType newExportFromDeclaration(uint32_t begin, Node exportSpecSet,
465 Node moduleRequest) {
466 return NodeGeneric;
468 BinaryNodeType newExportDefaultDeclaration(Node kid, Node maybeBinding,
469 const TokenPos& pos) {
470 return NodeGeneric;
472 BinaryNodeType newExportSpec(Node bindingName, Node exportName) {
473 return NodeGeneric;
475 UnaryNodeType newExportNamespaceSpec(uint32_t begin, Node exportName) {
476 return NodeGeneric;
478 NullaryNodeType newExportBatchSpec(const TokenPos& pos) {
479 return NodeGeneric;
481 BinaryNodeType newImportMeta(NullaryNodeType importHolder,
482 NullaryNodeType metaHolder) {
483 return NodeGeneric;
485 BinaryNodeType newCallImport(NullaryNodeType importHolder, Node singleArg) {
486 return NodeGeneric;
488 BinaryNodeType newCallImportSpec(Node specifierArg, Node optionalArg) {
489 return NodeGeneric;
492 BinaryNodeType newSetThis(Node thisName, Node value) { return value; }
494 UnaryNodeType newExprStatement(Node expr, uint32_t end) {
495 return expr == NodeUnparenthesizedString ? NodeStringExprStatement
496 : NodeGeneric;
499 TernaryNodeType newIfStatement(uint32_t begin, Node cond, Node thenBranch,
500 Node elseBranch) {
501 return NodeGeneric;
503 BinaryNodeType newDoWhileStatement(Node body, Node cond,
504 const TokenPos& pos) {
505 return NodeGeneric;
507 BinaryNodeType newWhileStatement(uint32_t begin, Node cond, Node body) {
508 return NodeGeneric;
510 SwitchStatementType newSwitchStatement(
511 uint32_t begin, Node discriminant,
512 LexicalScopeNodeType lexicalForCaseList, bool hasDefault) {
513 return NodeGeneric;
515 CaseClauseType newCaseOrDefault(uint32_t begin, Node expr, Node body) {
516 return NodeGeneric;
518 ContinueStatementType newContinueStatement(TaggedParserAtomIndex label,
519 const TokenPos& pos) {
520 return NodeGeneric;
522 BreakStatementType newBreakStatement(TaggedParserAtomIndex label,
523 const TokenPos& pos) {
524 return NodeBreak;
526 UnaryNodeType newReturnStatement(Node expr, const TokenPos& pos) {
527 return NodeReturn;
529 UnaryNodeType newExpressionBody(Node expr) { return NodeReturn; }
530 BinaryNodeType newWithStatement(uint32_t begin, Node expr, Node body) {
531 return NodeGeneric;
534 LabeledStatementType newLabeledStatement(TaggedParserAtomIndex label,
535 Node stmt, uint32_t begin) {
536 return NodeGeneric;
539 UnaryNodeType newThrowStatement(Node expr, const TokenPos& pos) {
540 return NodeThrow;
542 TernaryNodeType newTryStatement(uint32_t begin, Node body,
543 LexicalScopeNodeType catchScope,
544 Node finallyBlock) {
545 return NodeGeneric;
547 DebuggerStatementType newDebuggerStatement(const TokenPos& pos) {
548 return NodeGeneric;
551 NameNodeType newPropertyName(TaggedParserAtomIndex name,
552 const TokenPos& pos) {
553 lastAtom = name;
554 return NodeGeneric;
557 PropertyAccessType newPropertyAccess(Node expr, NameNodeType key) {
558 return NodeDottedProperty;
561 PropertyAccessType newOptionalPropertyAccess(Node expr, NameNodeType key) {
562 return NodeOptionalDottedProperty;
565 PropertyByValueType newPropertyByValue(Node lhs, Node index, uint32_t end) {
566 MOZ_ASSERT(!isPrivateName(index));
567 return NodeElement;
570 PropertyByValueType newOptionalPropertyByValue(Node lhs, Node index,
571 uint32_t end) {
572 return NodeOptionalElement;
575 PrivateMemberAccessType newPrivateMemberAccess(Node lhs, Node privateName,
576 uint32_t end) {
577 return NodePrivateMemberAccess;
580 PrivateMemberAccessType newOptionalPrivateMemberAccess(Node lhs,
581 Node privateName,
582 uint32_t end) {
583 return NodeOptionalPrivateMemberAccess;
586 [[nodiscard]] bool setupCatchScope(LexicalScopeNodeType lexicalScope,
587 Node catchName, Node catchBody) {
588 return true;
591 [[nodiscard]] bool setLastFunctionFormalParameterDefault(
592 FunctionNodeType funNode, Node defaultValue) {
593 return true;
596 void checkAndSetIsDirectRHSAnonFunction(Node pn) {}
598 ParamsBodyNodeType newParamsBody(const TokenPos& pos) { return NodeGeneric; }
600 FunctionNodeType newFunction(FunctionSyntaxKind syntaxKind,
601 const TokenPos& pos) {
602 switch (syntaxKind) {
603 case FunctionSyntaxKind::Statement:
604 return NodeFunctionStatement;
605 case FunctionSyntaxKind::Arrow:
606 return NodeFunctionArrow;
607 default:
608 // All non-arrow function expressions are initially presumed to have
609 // block body. This will be overridden later *if* the function
610 // expression permissibly has an AssignmentExpression body.
611 return NodeFunctionExpression;
615 void setFunctionFormalParametersAndBody(FunctionNodeType funNode,
616 ParamsBodyNodeType paramsBody) {}
617 void setFunctionBody(FunctionNodeType funNode, LexicalScopeNodeType body) {}
618 void setFunctionBox(FunctionNodeType funNode, FunctionBox* funbox) {}
619 void addFunctionFormalParameter(FunctionNodeType funNode, Node argpn) {}
621 ForNodeType newForStatement(uint32_t begin, TernaryNodeType forHead,
622 Node body, unsigned iflags) {
623 return NodeGeneric;
626 TernaryNodeType newForHead(Node init, Node test, Node update,
627 const TokenPos& pos) {
628 return NodeGeneric;
631 TernaryNodeType newForInOrOfHead(ParseNodeKind kind, Node target,
632 Node iteratedExpr, const TokenPos& pos) {
633 return NodeGeneric;
636 AssignmentNodeType finishInitializerAssignment(NameNodeType nameNode,
637 Node init) {
638 return NodeUnparenthesizedAssignment;
641 void setBeginPosition(Node pn, Node oth) {}
642 void setBeginPosition(Node pn, uint32_t begin) {}
644 void setEndPosition(Node pn, Node oth) {}
645 void setEndPosition(Node pn, uint32_t end) {}
647 uint32_t getFunctionNameOffset(Node func, TokenStreamAnyChars& ts) {
648 // XXX This offset isn't relevant to the offending function name. But
649 // we may not *have* that function name around, because of how lazy
650 // parsing works -- the actual name could be outside
651 // |tokenStream.userbuf|'s observed region. So the current offset
652 // is the best we can do.
653 return ts.currentToken().pos.begin;
656 ListNodeType newList(ParseNodeKind kind, const TokenPos& pos) {
657 MOZ_ASSERT(kind != ParseNodeKind::VarStmt);
658 MOZ_ASSERT(kind != ParseNodeKind::LetDecl);
659 MOZ_ASSERT(kind != ParseNodeKind::ConstDecl);
660 MOZ_ASSERT(kind != ParseNodeKind::ParamsBody);
661 return NodeGeneric;
664 ListNodeType newList(ParseNodeKind kind, Node kid) {
665 return newList(kind, TokenPos());
668 DeclarationListNodeType newDeclarationList(ParseNodeKind kind,
669 const TokenPos& pos) {
670 if (kind == ParseNodeKind::VarStmt) {
671 return NodeVarDeclaration;
673 MOZ_ASSERT(kind == ParseNodeKind::LetDecl ||
674 kind == ParseNodeKind::ConstDecl);
675 return NodeLexicalDeclaration;
678 ListNodeType newCommaExpressionList(Node kid) { return NodeGeneric; }
680 void addList(ListNodeType list, Node kid) {
681 MOZ_ASSERT(list == NodeGeneric || list == NodeUnparenthesizedArray ||
682 list == NodeUnparenthesizedObject ||
683 list == NodeVarDeclaration || list == NodeLexicalDeclaration ||
684 list == NodeFunctionCall);
687 CallNodeType newNewExpression(uint32_t begin, Node ctor, ListNodeType args,
688 bool isSpread) {
689 return NodeGeneric;
692 AssignmentNodeType newAssignment(ParseNodeKind kind, Node lhs, Node rhs) {
693 return kind == ParseNodeKind::AssignExpr ? NodeUnparenthesizedAssignment
694 : NodeGeneric;
697 AssignmentNodeType newInitExpr(Node lhs, Node rhs) { return NodeGeneric; }
699 bool isUnparenthesizedAssignment(Node node) {
700 return node == NodeUnparenthesizedAssignment;
703 bool isUnparenthesizedUnaryExpression(Node node) {
704 return node == NodeUnparenthesizedUnary;
707 bool isReturnStatement(Node node) { return node == NodeReturn; }
709 bool isStatementPermittedAfterReturnStatement(Node pn) {
710 return pn == NodeFunctionStatement || isNonArrowFunctionExpression(pn) ||
711 pn == NodeVarDeclaration || pn == NodeBreak || pn == NodeThrow ||
712 pn == NodeEmptyStatement;
715 bool isSuperBase(Node pn) { return pn == NodeSuperBase; }
717 void setListHasNonConstInitializer(ListNodeType literal) {}
718 [[nodiscard]] Node parenthesize(Node node) {
719 // A number of nodes have different behavior upon parenthesization, but
720 // only in some circumstances. Convert these nodes to special
721 // parenthesized forms.
722 if (node == NodeUnparenthesizedArray) {
723 return NodeParenthesizedArray;
725 if (node == NodeUnparenthesizedObject) {
726 return NodeParenthesizedObject;
729 // Other nodes need not be recognizable after parenthesization; convert
730 // them to a generic node.
731 if (node == NodeUnparenthesizedString ||
732 node == NodeUnparenthesizedAssignment ||
733 node == NodeUnparenthesizedUnary) {
734 return NodeGeneric;
737 // Convert parenthesized |async| to a normal name node.
738 if (node == NodePotentialAsyncKeyword) {
739 return NodeName;
742 // In all other cases, the parenthesized form of |node| is equivalent
743 // to the unparenthesized form: return |node| unchanged.
744 return node;
746 template <typename NodeType>
747 [[nodiscard]] NodeType setLikelyIIFE(NodeType node) {
748 return node; // Remain in syntax-parse mode.
751 bool isName(Node node) {
752 return node == NodeName || node == NodeArgumentsName ||
753 node == NodeEvalName || node == NodePotentialAsyncKeyword;
756 bool isArgumentsName(Node node) { return node == NodeArgumentsName; }
757 bool isEvalName(Node node) { return node == NodeEvalName; }
758 bool isAsyncKeyword(Node node) { return node == NodePotentialAsyncKeyword; }
760 bool isPrivateName(Node node) { return node == NodePrivateName; }
761 bool isPrivateMemberAccess(Node node) {
762 return node == NodePrivateMemberAccess;
765 TaggedParserAtomIndex maybeDottedProperty(Node node) {
766 // Note: |super.apply(...)| is a special form that calls an "apply"
767 // method retrieved from one value, but using a *different* value as
768 // |this|. It's not really eligible for the funapply/funcall
769 // optimizations as they're currently implemented (assuming a single
770 // value is used for both retrieval and |this|).
771 if (node != NodeDottedProperty && node != NodeOptionalDottedProperty) {
772 return TaggedParserAtomIndex::null();
774 return lastAtom;
777 TaggedParserAtomIndex isStringExprStatement(Node pn, TokenPos* pos) {
778 if (pn == NodeStringExprStatement) {
779 *pos = lastStringPos;
780 return lastAtom;
782 return TaggedParserAtomIndex::null();
785 bool reuseLazyInnerFunctions() { return false; }
786 bool reuseClosedOverBindings() { return false; }
787 TaggedParserAtomIndex nextLazyClosedOverBinding() {
788 MOZ_CRASH(
789 "SyntaxParseHandler::canSkipLazyClosedOverBindings must return false");
792 void setPrivateNameKind(Node node, PrivateNameKind kind) {}
795 } // namespace frontend
796 } // namespace js
798 #endif /* frontend_SyntaxParseHandler_h */