tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SyntaxParseHandler.h (29062B)


      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_SyntaxParseHandler_h
      8 #define frontend_SyntaxParseHandler_h
      9 
     10 #include "mozilla/Assertions.h"
     11 #include "mozilla/Maybe.h"   // mozilla::Maybe
     12 #include "mozilla/Result.h"  // mozilla::Result, mozilla::UnusedZero
     13 
     14 #include <string.h>
     15 
     16 #include "jstypes.h"
     17 
     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"
     24 
     25 namespace js {
     26 namespace frontend {
     27 enum SyntaxParseHandlerNode {
     28  NodeFailure = 0,
     29  NodeGeneric,
     30  NodeGetProp,
     31  NodeStringExprStatement,
     32  NodeReturn,
     33  NodeBreak,
     34  NodeThrow,
     35  NodeEmptyStatement,
     36 
     37  NodeVarDeclaration,
     38  NodeLexicalDeclaration,
     39 
     40  // A non-arrow function expression with block body, from bog-standard
     41  // ECMAScript.
     42  NodeFunctionExpression,
     43 
     44  NodeFunctionArrow,
     45  NodeFunctionStatement,
     46 
     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
     51  // noticed).
     52  NodeFunctionCall,
     53 
     54  NodeOptionalFunctionCall,
     55 
     56  // Node representing normal names which don't require any special
     57  // casing.
     58  NodeName,
     59 
     60  // Nodes representing the names "arguments", "length" and "eval".
     61  NodeArgumentsName,
     62  NodeLengthName,
     63  NodeEvalName,
     64 
     65  // Node representing the "async" name, which may actually be a
     66  // contextual keyword.
     67  NodePotentialAsyncKeyword,
     68 
     69  // Node representing private names.
     70  NodePrivateName,
     71 
     72  NodeDottedProperty,
     73  NodeOptionalDottedProperty,
     74  NodeElement,
     75  NodeOptionalElement,
     76  // A distinct node for [PrivateName], to make detecting delete this.#x
     77  // detectable in syntax parse
     78  NodePrivateMemberAccess,
     79  NodeOptionalPrivateMemberAccess,
     80 
     81  // Node representing the compound Arguments.length expression;
     82  // Used only for property access, not assignment.
     83  NodeArgumentsLength,
     84 
     85  // Destructuring target patterns can't be parenthesized: |([a]) = [3];|
     86  // must be a syntax error.  (We can't use NodeGeneric instead of these
     87  // because that would trigger invalid-left-hand-side ReferenceError
     88  // semantics when SyntaxError semantics are desired.)
     89  NodeParenthesizedArray,
     90  NodeParenthesizedObject,
     91 
     92  // In rare cases a parenthesized |node| doesn't have the same semantics
     93  // as |node|.  Each such node has a special Node value, and we use a
     94  // different Node value to represent the parenthesized form.  See also
     95  // is{Unp,P}arenthesized*(Node), parenthesize(Node), and the various
     96  // functions that deal in NodeUnparenthesized* below.
     97 
     98  // Valuable for recognizing potential destructuring patterns.
     99  NodeUnparenthesizedArray,
    100  NodeUnparenthesizedObject,
    101 
    102  // The directive prologue at the start of a FunctionBody or ScriptBody
    103  // is the longest sequence (possibly empty) of string literal
    104  // expression statements at the start of a function.  Thus we need this
    105  // to treat |"use strict";| as a possible Use Strict Directive and
    106  // |("use strict");| as a useless statement.
    107  NodeUnparenthesizedString,
    108 
    109  // For destructuring patterns an assignment element with
    110  // an initializer expression is not allowed be parenthesized.
    111  // i.e. |{x = 1} = obj|
    112  NodeUnparenthesizedAssignment,
    113 
    114  // This node is necessary to determine if the base operand in an
    115  // exponentiation operation is an unparenthesized unary expression.
    116  // We want to reject |-2 ** 3|, but still need to allow |(-2) ** 3|.
    117  NodeUnparenthesizedUnary,
    118 
    119  // This node is necessary to determine if the LHS of a property access is
    120  // super related.
    121  NodeSuperBase
    122 };
    123 
    124 }  // namespace frontend
    125 }  // namespace js
    126 
    127 template <>
    128 struct mozilla::detail::UnusedZero<js::frontend::SyntaxParseHandlerNode> {
    129  static const bool value = true;
    130 };
    131 
    132 namespace js {
    133 namespace frontend {
    134 
    135 // Parse handler used when processing the syntax in a block of code, to generate
    136 // the minimal information which is required to detect syntax errors and allow
    137 // bytecode to be emitted for outer functions.
    138 //
    139 // When parsing, we start at the top level with a full parse, and when possible
    140 // only check the syntax for inner functions, so that they can be lazily parsed
    141 // into bytecode when/if they first run. Checking the syntax of a function is
    142 // several times faster than doing a full parse/emit, and lazy parsing improves
    143 // both performance and memory usage significantly when pages contain large
    144 // amounts of code that never executes (which happens often).
    145 class SyntaxParseHandler {
    146  // Remember the last encountered name or string literal during syntax parses.
    147  TaggedParserAtomIndex lastAtom;
    148  TokenPos lastStringPos;
    149 
    150 public:
    151  struct NodeError {};
    152 
    153  using Node = SyntaxParseHandlerNode;
    154 
    155  using NodeResult = mozilla::Result<Node, NodeError>;
    156  using NodeErrorResult = mozilla::GenericErrorResult<NodeError>;
    157 
    158 #define DECLARE_TYPE(typeName) \
    159  using typeName##Type = Node; \
    160  using typeName##Result = mozilla::Result<Node, NodeError>;
    161  FOR_EACH_PARSENODE_SUBCLASS(DECLARE_TYPE)
    162 #undef DECLARE_TYPE
    163 
    164  using NullNode = Node;
    165 
    166  bool isNonArrowFunctionExpression(Node node) const {
    167    return node == NodeFunctionExpression;
    168  }
    169 
    170  bool isPropertyOrPrivateMemberAccess(Node node) {
    171    return node == NodeDottedProperty || node == NodeElement ||
    172           node == NodePrivateMemberAccess || node == NodeArgumentsLength;
    173  }
    174 
    175  bool isOptionalPropertyOrPrivateMemberAccess(Node node) {
    176    return node == NodeOptionalDottedProperty || node == NodeOptionalElement ||
    177           node == NodeOptionalPrivateMemberAccess;
    178  }
    179 
    180  bool isFunctionCall(Node node) {
    181    // Note: super() is a special form, *not* a function call.
    182    return node == NodeFunctionCall;
    183  }
    184 
    185  static bool isUnparenthesizedDestructuringPattern(Node node) {
    186    return node == NodeUnparenthesizedArray ||
    187           node == NodeUnparenthesizedObject;
    188  }
    189 
    190  static bool isParenthesizedDestructuringPattern(Node node) {
    191    // Technically this isn't a destructuring target at all -- the grammar
    192    // doesn't treat it as such.  But we need to know when this happens to
    193    // consider it a SyntaxError rather than an invalid-left-hand-side
    194    // ReferenceError.
    195    return node == NodeParenthesizedArray || node == NodeParenthesizedObject;
    196  }
    197 
    198 public:
    199  SyntaxParseHandler(FrontendContext* fc, CompilationState& compilationState) {
    200    MOZ_ASSERT(!compilationState.input.isDelazifying());
    201  }
    202 
    203  static NullNode null() { return NodeFailure; }
    204  static constexpr NodeErrorResult errorResult() {
    205    return NodeErrorResult(NodeError());
    206  }
    207 
    208 #define DECLARE_AS(typeName) \
    209  static typeName##Type as##typeName(Node node) { return node; }
    210  FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
    211 #undef DECLARE_AS
    212 
    213  NameNodeResult newName(TaggedParserAtomIndex name, const TokenPos& pos) {
    214    lastAtom = name;
    215    if (name == TaggedParserAtomIndex::WellKnown::arguments()) {
    216      return NodeArgumentsName;
    217    }
    218    if (pos.begin + strlen("async") == pos.end &&
    219        name == TaggedParserAtomIndex::WellKnown::async()) {
    220      return NodePotentialAsyncKeyword;
    221    }
    222    if (name == TaggedParserAtomIndex::WellKnown::eval()) {
    223      return NodeEvalName;
    224    }
    225    return NodeName;
    226  }
    227 
    228  UnaryNodeResult newComputedName(Node expr, uint32_t start, uint32_t end) {
    229    return NodeGeneric;
    230  }
    231 
    232  UnaryNodeResult newSyntheticComputedName(Node expr, uint32_t start,
    233                                           uint32_t end) {
    234    return NodeGeneric;
    235  }
    236 
    237  NameNodeResult newObjectLiteralPropertyName(TaggedParserAtomIndex atom,
    238                                              const TokenPos& pos) {
    239    return NodeName;
    240  }
    241 
    242  NameNodeResult newPrivateName(TaggedParserAtomIndex atom,
    243                                const TokenPos& pos) {
    244    return NodePrivateName;
    245  }
    246 
    247  NumericLiteralResult newNumber(double value, DecimalPoint decimalPoint,
    248                                 const TokenPos& pos) {
    249    return NodeGeneric;
    250  }
    251 
    252  BigIntLiteralResult newBigInt() { return NodeGeneric; }
    253 
    254  BooleanLiteralResult newBooleanLiteral(bool cond, const TokenPos& pos) {
    255    return NodeGeneric;
    256  }
    257 
    258  NameNodeResult newStringLiteral(TaggedParserAtomIndex atom,
    259                                  const TokenPos& pos) {
    260    lastAtom = atom;
    261    lastStringPos = pos;
    262    return NodeUnparenthesizedString;
    263  }
    264 
    265  NameNodeResult newTemplateStringLiteral(TaggedParserAtomIndex atom,
    266                                          const TokenPos& pos) {
    267    return NodeGeneric;
    268  }
    269 
    270  CallSiteNodeResult newCallSiteObject(uint32_t begin) { return NodeGeneric; }
    271 
    272  void addToCallSiteObject(CallSiteNodeType callSiteObj, Node rawNode,
    273                           Node cookedNode) {}
    274 
    275  ThisLiteralResult newThisLiteral(const TokenPos& pos, Node thisName) {
    276    return NodeGeneric;
    277  }
    278  NullLiteralResult newNullLiteral(const TokenPos& pos) { return NodeGeneric; }
    279  RawUndefinedLiteralResult newRawUndefinedLiteral(const TokenPos& pos) {
    280    return NodeGeneric;
    281  }
    282 
    283  RegExpLiteralResult newRegExp(Node reobj, const TokenPos& pos) {
    284    return NodeGeneric;
    285  }
    286 
    287  ConditionalExpressionResult newConditional(Node cond, Node thenExpr,
    288                                             Node elseExpr) {
    289    return NodeGeneric;
    290  }
    291 
    292  UnaryNodeResult newDelete(uint32_t begin, Node expr) {
    293    return NodeUnparenthesizedUnary;
    294  }
    295 
    296  UnaryNodeResult newTypeof(uint32_t begin, Node kid) {
    297    return NodeUnparenthesizedUnary;
    298  }
    299 
    300  UnaryNodeResult newUnary(ParseNodeKind kind, uint32_t begin, Node kid) {
    301    return NodeUnparenthesizedUnary;
    302  }
    303 
    304  UnaryNodeResult newUpdate(ParseNodeKind kind, uint32_t begin, Node kid) {
    305    return NodeGeneric;
    306  }
    307 
    308  UnaryNodeResult newSpread(uint32_t begin, Node kid) { return NodeGeneric; }
    309 
    310  NodeResult appendOrCreateList(ParseNodeKind kind, Node left, Node right,
    311                                ParseContext* pc) {
    312    return NodeGeneric;
    313  }
    314 
    315  // Expressions
    316 
    317  ListNodeResult newArrayLiteral(uint32_t begin) {
    318    return NodeUnparenthesizedArray;
    319  }
    320  [[nodiscard]] bool addElision(ListNodeType literal, const TokenPos& pos) {
    321    return true;
    322  }
    323  [[nodiscard]] bool addSpreadElement(ListNodeType literal, uint32_t begin,
    324                                      Node inner) {
    325    return true;
    326  }
    327  void addArrayElement(ListNodeType literal, Node element) {}
    328 
    329  ListNodeResult newArguments(const TokenPos& pos) { return NodeGeneric; }
    330  CallNodeResult newCall(Node callee, ListNodeType args, JSOp callOp) {
    331    return NodeFunctionCall;
    332  }
    333 
    334  CallNodeResult newOptionalCall(Node callee, ListNodeType args, JSOp callOp) {
    335    return NodeOptionalFunctionCall;
    336  }
    337 
    338  CallNodeResult newSuperCall(Node callee, ListNodeType args, bool isSpread) {
    339    return NodeGeneric;
    340  }
    341  CallNodeResult newTaggedTemplate(Node tag, ListNodeType args, JSOp callOp) {
    342    return NodeGeneric;
    343  }
    344 
    345  ListNodeResult newObjectLiteral(uint32_t begin) {
    346    return NodeUnparenthesizedObject;
    347  }
    348 
    349  ListNodeResult newClassMemberList(uint32_t begin) { return NodeGeneric; }
    350  ClassNamesResult newClassNames(Node outer, Node inner, const TokenPos& pos) {
    351    return NodeGeneric;
    352  }
    353  ClassNodeResult newClass(Node name, Node heritage, Node methodBlock,
    354 #ifdef ENABLE_DECORATORS
    355                           ListNodeType decorators,
    356                           FunctionNodeType addInitializerFunction,
    357 #endif
    358                           const TokenPos& pos) {
    359    return NodeGeneric;
    360  }
    361 
    362  LexicalScopeNodeResult newLexicalScope(Node body) {
    363    return NodeLexicalDeclaration;
    364  }
    365 
    366  ClassBodyScopeNodeResult newClassBodyScope(Node body) {
    367    return NodeLexicalDeclaration;
    368  }
    369 
    370  NewTargetNodeResult newNewTarget(NullaryNodeType newHolder,
    371                                   NullaryNodeType targetHolder,
    372                                   NameNodeType newTargetName) {
    373    return NodeGeneric;
    374  }
    375  NullaryNodeResult newPosHolder(const TokenPos& pos) { return NodeGeneric; }
    376  UnaryNodeResult newSuperBase(Node thisName, const TokenPos& pos) {
    377    return NodeSuperBase;
    378  }
    379 
    380  [[nodiscard]] bool addPrototypeMutation(ListNodeType literal, uint32_t begin,
    381                                          Node expr) {
    382    return true;
    383  }
    384  BinaryNodeResult newPropertyDefinition(Node key, Node val) {
    385    return NodeGeneric;
    386  }
    387  void addPropertyDefinition(ListNodeType literal, BinaryNodeType propdef) {}
    388  [[nodiscard]] bool addPropertyDefinition(ListNodeType literal, Node key,
    389                                           Node expr) {
    390    return true;
    391  }
    392  [[nodiscard]] bool addShorthand(ListNodeType literal, NameNodeType name,
    393                                  NameNodeType expr) {
    394    return true;
    395  }
    396  [[nodiscard]] bool addSpreadProperty(ListNodeType literal, uint32_t begin,
    397                                       Node inner) {
    398    return true;
    399  }
    400  [[nodiscard]] bool addObjectMethodDefinition(ListNodeType literal, Node key,
    401                                               FunctionNodeType funNode,
    402                                               AccessorType atype) {
    403    return true;
    404  }
    405  [[nodiscard]] NodeResult newDefaultClassConstructor(
    406      Node key, FunctionNodeType funNode) {
    407    return NodeGeneric;
    408  }
    409  [[nodiscard]] NodeResult newClassMethodDefinition(
    410      Node key, FunctionNodeType funNode, AccessorType atype, bool isStatic,
    411      mozilla::Maybe<FunctionNodeType> initializerIfPrivate
    412 #ifdef ENABLE_DECORATORS
    413      ,
    414      ListNodeType decorators
    415 #endif
    416  ) {
    417    return NodeGeneric;
    418  }
    419  [[nodiscard]] NodeResult newClassFieldDefinition(
    420      Node name, FunctionNodeType initializer, bool isStatic
    421 #ifdef ENABLE_DECORATORS
    422      ,
    423      ListNodeType decorators, ClassMethodType accessorGetterNode,
    424      ClassMethodType accessorSetterNode
    425 #endif
    426  ) {
    427    return NodeGeneric;
    428  }
    429 
    430  [[nodiscard]] NodeResult newStaticClassBlock(FunctionNodeType block) {
    431    return NodeGeneric;
    432  }
    433 
    434  [[nodiscard]] bool addClassMemberDefinition(ListNodeType memberList,
    435                                              Node member) {
    436    return true;
    437  }
    438  UnaryNodeResult newYieldExpression(uint32_t begin, Node value) {
    439    return NodeGeneric;
    440  }
    441  UnaryNodeResult newYieldStarExpression(uint32_t begin, Node value) {
    442    return NodeGeneric;
    443  }
    444  UnaryNodeResult newAwaitExpression(uint32_t begin, Node value) {
    445    return NodeUnparenthesizedUnary;
    446  }
    447  UnaryNodeResult newOptionalChain(uint32_t begin, Node value) {
    448    return NodeGeneric;
    449  }
    450 
    451  // Statements
    452 
    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) {
    458    return true;
    459  }
    460  NullaryNodeResult newEmptyStatement(const TokenPos& pos) {
    461    return NodeEmptyStatement;
    462  }
    463 
    464  BinaryNodeResult newImportAttribute(Node keyNode, Node valueNode) {
    465    return NodeGeneric;
    466  }
    467  BinaryNodeResult newModuleRequest(Node moduleSpec, Node importAttributeList,
    468                                    const TokenPos& pos) {
    469    return NodeGeneric;
    470  }
    471  BinaryNodeResult newImportDeclaration(Node importSpecSet, Node moduleRequest,
    472                                        const TokenPos& pos) {
    473    return NodeGeneric;
    474  }
    475  BinaryNodeResult newImportSpec(Node importNameNode, Node bindingName) {
    476    return NodeGeneric;
    477  }
    478  UnaryNodeResult newImportNamespaceSpec(uint32_t begin, Node bindingName) {
    479    return NodeGeneric;
    480  }
    481  UnaryNodeResult newExportDeclaration(Node kid, const TokenPos& pos) {
    482    return NodeGeneric;
    483  }
    484  BinaryNodeResult newExportFromDeclaration(uint32_t begin, Node exportSpecSet,
    485                                            Node moduleRequest) {
    486    return NodeGeneric;
    487  }
    488  BinaryNodeResult newExportDefaultDeclaration(Node kid, Node maybeBinding,
    489                                               const TokenPos& pos) {
    490    return NodeGeneric;
    491  }
    492  BinaryNodeResult newExportSpec(Node bindingName, Node exportName) {
    493    return NodeGeneric;
    494  }
    495  UnaryNodeResult newExportNamespaceSpec(uint32_t begin, Node exportName) {
    496    return NodeGeneric;
    497  }
    498  NullaryNodeResult newExportBatchSpec(const TokenPos& pos) {
    499    return NodeGeneric;
    500  }
    501  BinaryNodeResult newImportMeta(NullaryNodeType importHolder,
    502                                 NullaryNodeType metaHolder) {
    503    return NodeGeneric;
    504  }
    505  BinaryNodeResult newCallImport(NullaryNodeType importHolder, Node singleArg) {
    506    return NodeGeneric;
    507  }
    508  BinaryNodeResult newCallImportSpec(Node specifierArg, Node optionalArg) {
    509    return NodeGeneric;
    510  }
    511 
    512  BinaryNodeResult newSetThis(Node thisName, Node value) { return value; }
    513 
    514  UnaryNodeResult newExprStatement(Node expr, uint32_t end) {
    515    return expr == NodeUnparenthesizedString ? NodeStringExprStatement
    516                                             : NodeGeneric;
    517  }
    518 
    519  TernaryNodeResult newIfStatement(uint32_t begin, Node cond, Node thenBranch,
    520                                   Node elseBranch) {
    521    return NodeGeneric;
    522  }
    523  BinaryNodeResult newDoWhileStatement(Node body, Node cond,
    524                                       const TokenPos& pos) {
    525    return NodeGeneric;
    526  }
    527  BinaryNodeResult newWhileStatement(uint32_t begin, Node cond, Node body) {
    528    return NodeGeneric;
    529  }
    530  SwitchStatementResult newSwitchStatement(
    531      uint32_t begin, Node discriminant,
    532      LexicalScopeNodeType lexicalForCaseList, bool hasDefault) {
    533    return NodeGeneric;
    534  }
    535  CaseClauseResult newCaseOrDefault(uint32_t begin, Node expr, Node body) {
    536    return NodeGeneric;
    537  }
    538  ContinueStatementResult newContinueStatement(TaggedParserAtomIndex label,
    539                                               const TokenPos& pos) {
    540    return NodeGeneric;
    541  }
    542  BreakStatementResult newBreakStatement(TaggedParserAtomIndex label,
    543                                         const TokenPos& pos) {
    544    return NodeBreak;
    545  }
    546  UnaryNodeResult newReturnStatement(Node expr, const TokenPos& pos) {
    547    return NodeReturn;
    548  }
    549  UnaryNodeResult newExpressionBody(Node expr) { return NodeReturn; }
    550  BinaryNodeResult newWithStatement(uint32_t begin, Node expr, Node body) {
    551    return NodeGeneric;
    552  }
    553 
    554  LabeledStatementResult newLabeledStatement(TaggedParserAtomIndex label,
    555                                             Node stmt, uint32_t begin) {
    556    return NodeGeneric;
    557  }
    558 
    559  UnaryNodeResult newThrowStatement(Node expr, const TokenPos& pos) {
    560    return NodeThrow;
    561  }
    562  TernaryNodeResult newTryStatement(uint32_t begin, Node body,
    563                                    LexicalScopeNodeType catchScope,
    564                                    Node finallyBlock) {
    565    return NodeGeneric;
    566  }
    567  DebuggerStatementResult newDebuggerStatement(const TokenPos& pos) {
    568    return NodeGeneric;
    569  }
    570 
    571  NameNodeResult newPropertyName(TaggedParserAtomIndex name,
    572                                 const TokenPos& pos) {
    573    lastAtom = name;
    574    if (name == TaggedParserAtomIndex::WellKnown::length()) {
    575      return NodeLengthName;
    576    }
    577    return NodeGeneric;
    578  }
    579 
    580  PropertyAccessResult newPropertyAccess(Node expr, NameNodeType key) {
    581    return NodeDottedProperty;
    582  }
    583 
    584  PropertyAccessResult newArgumentsLength(Node expr, NameNodeType key) {
    585    return NodeArgumentsLength;
    586  }
    587 
    588  PropertyAccessResult newOptionalPropertyAccess(Node expr, NameNodeType key) {
    589    return NodeOptionalDottedProperty;
    590  }
    591 
    592  PropertyByValueResult newPropertyByValue(Node lhs, Node index, uint32_t end) {
    593    MOZ_ASSERT(!isPrivateName(index));
    594    return NodeElement;
    595  }
    596 
    597  PropertyByValueResult newOptionalPropertyByValue(Node lhs, Node index,
    598                                                   uint32_t end) {
    599    return NodeOptionalElement;
    600  }
    601 
    602  PrivateMemberAccessResult newPrivateMemberAccess(Node lhs, Node privateName,
    603                                                   uint32_t end) {
    604    return NodePrivateMemberAccess;
    605  }
    606 
    607  PrivateMemberAccessResult newOptionalPrivateMemberAccess(Node lhs,
    608                                                           Node privateName,
    609                                                           uint32_t end) {
    610    return NodeOptionalPrivateMemberAccess;
    611  }
    612 
    613  [[nodiscard]] bool setupCatchScope(LexicalScopeNodeType lexicalScope,
    614                                     Node catchName, Node catchBody) {
    615    return true;
    616  }
    617 
    618  [[nodiscard]] bool setLastFunctionFormalParameterDefault(
    619      FunctionNodeType funNode, Node defaultValue) {
    620    return true;
    621  }
    622 
    623  void checkAndSetIsDirectRHSAnonFunction(Node pn) {}
    624 
    625  ParamsBodyNodeResult newParamsBody(const TokenPos& pos) {
    626    return NodeGeneric;
    627  }
    628 
    629  FunctionNodeResult newFunction(FunctionSyntaxKind syntaxKind,
    630                                 const TokenPos& pos) {
    631    switch (syntaxKind) {
    632      case FunctionSyntaxKind::Statement:
    633        return NodeFunctionStatement;
    634      case FunctionSyntaxKind::Arrow:
    635        return NodeFunctionArrow;
    636      default:
    637        // All non-arrow function expressions are initially presumed to have
    638        // block body.  This will be overridden later *if* the function
    639        // expression permissibly has an AssignmentExpression body.
    640        return NodeFunctionExpression;
    641    }
    642  }
    643 
    644  void setFunctionFormalParametersAndBody(FunctionNodeType funNode,
    645                                          ParamsBodyNodeType paramsBody) {}
    646  void setFunctionBody(FunctionNodeType funNode, LexicalScopeNodeType body) {}
    647  void setFunctionBox(FunctionNodeType funNode, FunctionBox* funbox) {}
    648  void addFunctionFormalParameter(FunctionNodeType funNode, Node argpn) {}
    649 
    650  ForNodeResult newForStatement(uint32_t begin, TernaryNodeType forHead,
    651                                Node body, unsigned iflags) {
    652    return NodeGeneric;
    653  }
    654 
    655  TernaryNodeResult newForHead(Node init, Node test, Node update,
    656                               const TokenPos& pos) {
    657    return NodeGeneric;
    658  }
    659 
    660  TernaryNodeResult newForInOrOfHead(ParseNodeKind kind, Node target,
    661                                     Node iteratedExpr, const TokenPos& pos) {
    662    return NodeGeneric;
    663  }
    664 
    665  AssignmentNodeResult finishInitializerAssignment(NameNodeType nameNode,
    666                                                   Node init) {
    667    return NodeUnparenthesizedAssignment;
    668  }
    669 
    670  void setBeginPosition(Node pn, Node oth) {}
    671  void setBeginPosition(Node pn, uint32_t begin) {}
    672 
    673  void setEndPosition(Node pn, Node oth) {}
    674  void setEndPosition(Node pn, uint32_t end) {}
    675 
    676  uint32_t getFunctionNameOffset(Node func, TokenStreamAnyChars& ts) {
    677    // XXX This offset isn't relevant to the offending function name.  But
    678    //     we may not *have* that function name around, because of how lazy
    679    //     parsing works -- the actual name could be outside
    680    //     |tokenStream.userbuf|'s observed region.  So the current offset
    681    //     is the best we can do.
    682    return ts.currentToken().pos.begin;
    683  }
    684 
    685  ListNodeResult newList(ParseNodeKind kind, const TokenPos& pos) {
    686    MOZ_ASSERT(kind != ParseNodeKind::VarStmt);
    687    MOZ_ASSERT(kind != ParseNodeKind::LetDecl);
    688    MOZ_ASSERT(kind != ParseNodeKind::ConstDecl);
    689    MOZ_ASSERT(kind != ParseNodeKind::ParamsBody);
    690 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
    691    MOZ_ASSERT(kind != ParseNodeKind::UsingDecl);
    692    MOZ_ASSERT(kind != ParseNodeKind::AwaitUsingDecl);
    693 #endif
    694    return NodeGeneric;
    695  }
    696 
    697  ListNodeResult newList(ParseNodeKind kind, Node kid) {
    698    return newList(kind, TokenPos());
    699  }
    700 
    701  DeclarationListNodeResult newDeclarationList(ParseNodeKind kind,
    702                                               const TokenPos& pos) {
    703    if (kind == ParseNodeKind::VarStmt) {
    704      return NodeVarDeclaration;
    705    }
    706    MOZ_ASSERT(kind == ParseNodeKind::LetDecl ||
    707               kind == ParseNodeKind::ConstDecl
    708 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
    709               || kind == ParseNodeKind::UsingDecl ||
    710               kind == ParseNodeKind::AwaitUsingDecl
    711 #endif
    712    );
    713    return NodeLexicalDeclaration;
    714  }
    715 
    716  ListNodeResult newCommaExpressionList(Node kid) { return NodeGeneric; }
    717 
    718  void addList(ListNodeType list, Node kid) {
    719    MOZ_ASSERT(list == NodeGeneric || list == NodeUnparenthesizedArray ||
    720               list == NodeUnparenthesizedObject ||
    721               list == NodeVarDeclaration || list == NodeLexicalDeclaration ||
    722               list == NodeFunctionCall);
    723  }
    724 
    725  CallNodeResult newNewExpression(uint32_t begin, Node ctor, ListNodeType args,
    726                                  bool isSpread) {
    727    return NodeGeneric;
    728  }
    729 
    730  AssignmentNodeResult newAssignment(ParseNodeKind kind, Node lhs, Node rhs) {
    731    return kind == ParseNodeKind::AssignExpr ? NodeUnparenthesizedAssignment
    732                                             : NodeGeneric;
    733  }
    734 
    735  AssignmentNodeResult newInitExpr(Node lhs, Node rhs) { return NodeGeneric; }
    736 
    737  bool isUnparenthesizedAssignment(Node node) {
    738    return node == NodeUnparenthesizedAssignment;
    739  }
    740 
    741  bool isUnparenthesizedUnaryExpression(Node node) {
    742    return node == NodeUnparenthesizedUnary;
    743  }
    744 
    745  bool isReturnStatement(Node node) { return node == NodeReturn; }
    746 
    747  bool isStatementPermittedAfterReturnStatement(Node pn) {
    748    return pn == NodeFunctionStatement || isNonArrowFunctionExpression(pn) ||
    749           pn == NodeVarDeclaration || pn == NodeBreak || pn == NodeThrow ||
    750           pn == NodeEmptyStatement;
    751  }
    752 
    753  bool isSuperBase(Node pn) { return pn == NodeSuperBase; }
    754 
    755  void setListHasNonConstInitializer(ListNodeType literal) {}
    756 
    757  // NOTE: This is infallible.
    758  [[nodiscard]] Node parenthesize(Node node) {
    759    // A number of nodes have different behavior upon parenthesization, but
    760    // only in some circumstances.  Convert these nodes to special
    761    // parenthesized forms.
    762    if (node == NodeUnparenthesizedArray) {
    763      return NodeParenthesizedArray;
    764    }
    765    if (node == NodeUnparenthesizedObject) {
    766      return NodeParenthesizedObject;
    767    }
    768 
    769    // Other nodes need not be recognizable after parenthesization; convert
    770    // them to a generic node.
    771    if (node == NodeUnparenthesizedString ||
    772        node == NodeUnparenthesizedAssignment ||
    773        node == NodeUnparenthesizedUnary) {
    774      return NodeGeneric;
    775    }
    776 
    777    // Convert parenthesized |async| to a normal name node.
    778    if (node == NodePotentialAsyncKeyword) {
    779      return NodeName;
    780    }
    781 
    782    // In all other cases, the parenthesized form of |node| is equivalent
    783    // to the unparenthesized form: return |node| unchanged.
    784    return node;
    785  }
    786 
    787  // NOTE: This is infallible.
    788  template <typename NodeType>
    789  [[nodiscard]] NodeType setLikelyIIFE(NodeType node) {
    790    return node;  // Remain in syntax-parse mode.
    791  }
    792 
    793  bool isName(Node node) {
    794    return node == NodeName || node == NodeArgumentsName ||
    795           node == NodeLengthName || node == NodeEvalName ||
    796           node == NodePotentialAsyncKeyword;
    797  }
    798 
    799  bool isArgumentsName(Node node) { return node == NodeArgumentsName; }
    800  bool isLengthName(Node node) { return node == NodeLengthName; }
    801  bool isEvalName(Node node) { return node == NodeEvalName; }
    802  bool isAsyncKeyword(Node node) { return node == NodePotentialAsyncKeyword; }
    803 
    804  bool isArgumentsLength(Node node) { return node == NodeArgumentsLength; }
    805 
    806  bool isPrivateName(Node node) { return node == NodePrivateName; }
    807  bool isPrivateMemberAccess(Node node) {
    808    return node == NodePrivateMemberAccess;
    809  }
    810 
    811  TaggedParserAtomIndex maybeDottedProperty(Node node) {
    812    // Note: |super.apply(...)| is a special form that calls an "apply"
    813    // method retrieved from one value, but using a *different* value as
    814    // |this|.  It's not really eligible for the funapply/funcall
    815    // optimizations as they're currently implemented (assuming a single
    816    // value is used for both retrieval and |this|).
    817    if (node != NodeDottedProperty && node != NodeOptionalDottedProperty &&
    818        node != NodeArgumentsLength) {
    819      return TaggedParserAtomIndex::null();
    820    }
    821    return lastAtom;
    822  }
    823 
    824  TaggedParserAtomIndex isStringExprStatement(Node pn, TokenPos* pos) {
    825    if (pn == NodeStringExprStatement) {
    826      *pos = lastStringPos;
    827      return lastAtom;
    828    }
    829    return TaggedParserAtomIndex::null();
    830  }
    831 
    832  bool reuseLazyInnerFunctions() { return false; }
    833  bool reuseClosedOverBindings() { return false; }
    834  TaggedParserAtomIndex nextLazyClosedOverBinding() {
    835    MOZ_CRASH(
    836        "SyntaxParseHandler::canSkipLazyClosedOverBindings must return false");
    837  }
    838 
    839  void setPrivateNameKind(Node node, PrivateNameKind kind) {}
    840 };
    841 
    842 }  // namespace frontend
    843 }  // namespace js
    844 
    845 #endif /* frontend_SyntaxParseHandler_h */