tor-browser

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

ReflectParse.cpp (127625B)


      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 /* JS reflection package. */
      8 
      9 #include "mozilla/DebugOnly.h"
     10 
     11 #include <utility>
     12 
     13 #include "jspubtd.h"
     14 
     15 #include "builtin/Array.h"
     16 #include "frontend/CompilationStencil.h"
     17 #include "frontend/FrontendContext.h"  // AutoReportFrontendContext
     18 #include "frontend/ModuleSharedContext.h"
     19 #include "frontend/ParseNode.h"
     20 #include "frontend/Parser.h"
     21 #include "js/ColumnNumber.h"          // JS::LimitedColumnNumberOneOrigin
     22 #include "js/friend/ErrorMessages.h"  // js::GetErrorMessage, JSMSG_*
     23 #include "js/friend/StackLimits.h"    // js::AutoCheckRecursionLimit
     24 #include "js/PropertyAndElement.h"    // JS_DefineFunction
     25 #include "js/StableStringChars.h"
     26 #include "vm/FunctionFlags.h"  // js::FunctionFlags
     27 #include "vm/Interpreter.h"
     28 #include "vm/JSAtomUtils.h"  // Atomize, AtomizeUTF8Chars
     29 #include "vm/JSObject.h"
     30 #include "vm/ModuleBuilder.h"  // js::ModuleBuilder
     31 #include "vm/PlainObject.h"    // js::PlainObject
     32 #include "vm/RegExpObject.h"
     33 
     34 #include "vm/JSContext-inl.h"
     35 #include "vm/JSObject-inl.h"
     36 #include "vm/ObjectOperations-inl.h"
     37 
     38 using namespace js;
     39 using namespace js::frontend;
     40 
     41 using JS::AutoStableStringChars;
     42 using JS::CompileOptions;
     43 using JS::RootedValueArray;
     44 using mozilla::DebugOnly;
     45 
     46 enum ASTType {
     47  AST_ERROR = -1,
     48 #define ASTDEF(ast, str) ast,
     49 #include "jsast.tbl"
     50 #undef ASTDEF
     51  AST_LIMIT
     52 };
     53 
     54 enum AssignmentOperator {
     55  AOP_ERR = -1,
     56 
     57  /* assign */
     58  AOP_ASSIGN = 0,
     59  /* operator-assign */
     60  AOP_PLUS,
     61  AOP_MINUS,
     62  AOP_STAR,
     63  AOP_DIV,
     64  AOP_MOD,
     65  AOP_POW,
     66  /* shift-assign */
     67  AOP_LSH,
     68  AOP_RSH,
     69  AOP_URSH,
     70  /* binary */
     71  AOP_BITOR,
     72  AOP_BITXOR,
     73  AOP_BITAND,
     74  /* short-circuit */
     75  AOP_COALESCE,
     76  AOP_OR,
     77  AOP_AND,
     78 
     79  AOP_LIMIT
     80 };
     81 
     82 enum BinaryOperator {
     83  BINOP_ERR = -1,
     84 
     85  /* eq */
     86  BINOP_EQ = 0,
     87  BINOP_NE,
     88  BINOP_STRICTEQ,
     89  BINOP_STRICTNE,
     90  /* rel */
     91  BINOP_LT,
     92  BINOP_LE,
     93  BINOP_GT,
     94  BINOP_GE,
     95  /* shift */
     96  BINOP_LSH,
     97  BINOP_RSH,
     98  BINOP_URSH,
     99  /* arithmetic */
    100  BINOP_ADD,
    101  BINOP_SUB,
    102  BINOP_STAR,
    103  BINOP_DIV,
    104  BINOP_MOD,
    105  BINOP_POW,
    106  /* binary */
    107  BINOP_BITOR,
    108  BINOP_BITXOR,
    109  BINOP_BITAND,
    110  /* misc */
    111  BINOP_IN,
    112  BINOP_INSTANCEOF,
    113  BINOP_COALESCE,
    114 
    115  BINOP_LIMIT
    116 };
    117 
    118 enum UnaryOperator {
    119  UNOP_ERR = -1,
    120 
    121  UNOP_DELETE = 0,
    122  UNOP_NEG,
    123  UNOP_POS,
    124  UNOP_NOT,
    125  UNOP_BITNOT,
    126  UNOP_TYPEOF,
    127  UNOP_VOID,
    128  UNOP_AWAIT,
    129 
    130  UNOP_LIMIT
    131 };
    132 
    133 enum VarDeclKind {
    134  VARDECL_ERR = -1,
    135  VARDECL_VAR = 0,
    136  VARDECL_CONST,
    137  VARDECL_LET,
    138 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
    139  VARDECL_USING,
    140  VARDECL_AWAIT_USING,
    141 #endif
    142  VARDECL_LIMIT
    143 };
    144 
    145 enum PropKind {
    146  PROP_ERR = -1,
    147  PROP_INIT = 0,
    148  PROP_GETTER,
    149  PROP_SETTER,
    150  PROP_MUTATEPROTO,
    151  PROP_LIMIT
    152 };
    153 
    154 static const char* const aopNames[] = {
    155    "=",     /* AOP_ASSIGN */
    156    "+=",    /* AOP_PLUS */
    157    "-=",    /* AOP_MINUS */
    158    "*=",    /* AOP_STAR */
    159    "/=",    /* AOP_DIV */
    160    "%=",    /* AOP_MOD */
    161    "**=",   /* AOP_POW */
    162    "<<=",   /* AOP_LSH */
    163    ">>=",   /* AOP_RSH */
    164    ">>>=",  /* AOP_URSH */
    165    "|=",    /* AOP_BITOR */
    166    "^=",    /* AOP_BITXOR */
    167    "&=",    /* AOP_BITAND */
    168    "\?\?=", /* AOP_COALESCE */
    169    "||=",   /* AOP_OR */
    170    "&&=",   /* AOP_AND */
    171 };
    172 
    173 static const char* const binopNames[] = {
    174    "==",         /* BINOP_EQ */
    175    "!=",         /* BINOP_NE */
    176    "===",        /* BINOP_STRICTEQ */
    177    "!==",        /* BINOP_STRICTNE */
    178    "<",          /* BINOP_LT */
    179    "<=",         /* BINOP_LE */
    180    ">",          /* BINOP_GT */
    181    ">=",         /* BINOP_GE */
    182    "<<",         /* BINOP_LSH */
    183    ">>",         /* BINOP_RSH */
    184    ">>>",        /* BINOP_URSH */
    185    "+",          /* BINOP_PLUS */
    186    "-",          /* BINOP_MINUS */
    187    "*",          /* BINOP_STAR */
    188    "/",          /* BINOP_DIV */
    189    "%",          /* BINOP_MOD */
    190    "**",         /* BINOP_POW */
    191    "|",          /* BINOP_BITOR */
    192    "^",          /* BINOP_BITXOR */
    193    "&",          /* BINOP_BITAND */
    194    "in",         /* BINOP_IN */
    195    "instanceof", /* BINOP_INSTANCEOF */
    196    "??",         /* BINOP_COALESCE */
    197 };
    198 
    199 static const char* const unopNames[] = {
    200    "delete", /* UNOP_DELETE */
    201    "-",      /* UNOP_NEG */
    202    "+",      /* UNOP_POS */
    203    "!",      /* UNOP_NOT */
    204    "~",      /* UNOP_BITNOT */
    205    "typeof", /* UNOP_TYPEOF */
    206    "void",   /* UNOP_VOID */
    207    "await",  /* UNOP_AWAIT */
    208 };
    209 
    210 static const char* const nodeTypeNames[] = {
    211 #define ASTDEF(ast, str) str,
    212 #include "jsast.tbl"
    213 #undef ASTDEF
    214    nullptr};
    215 
    216 enum YieldKind { Delegating, NotDelegating };
    217 
    218 using NodeVector = RootedValueVector;
    219 
    220 /*
    221 * ParseNode is a somewhat intricate data structure, and its invariants have
    222 * evolved, making it more likely that there could be a disconnect between the
    223 * parser and the AST serializer. We use these macros to check invariants on a
    224 * parse node and raise a dynamic error on failure.
    225 */
    226 #define LOCAL_ASSERT(expr)                                    \
    227  JS_BEGIN_MACRO                                              \
    228    MOZ_ASSERT(expr);                                         \
    229    if (!(expr)) {                                            \
    230      JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, \
    231                                JSMSG_BAD_PARSE_NODE);        \
    232      return false;                                           \
    233    }                                                         \
    234  JS_END_MACRO
    235 
    236 #define LOCAL_NOT_REACHED(expr)                             \
    237  JS_BEGIN_MACRO                                            \
    238    MOZ_ASSERT(false);                                      \
    239    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, \
    240                              JSMSG_BAD_PARSE_NODE);        \
    241    return false;                                           \
    242  JS_END_MACRO
    243 
    244 namespace {
    245 
    246 /* Set 'result' to obj[id] if any such property exists, else defaultValue. */
    247 static bool GetPropertyDefault(JSContext* cx, HandleObject obj, HandleId id,
    248                               HandleValue defaultValue,
    249                               MutableHandleValue result) {
    250  bool found;
    251  if (!HasProperty(cx, obj, id, &found)) {
    252    return false;
    253  }
    254  if (!found) {
    255    result.set(defaultValue);
    256    return true;
    257  }
    258  return GetProperty(cx, obj, obj, id, result);
    259 }
    260 
    261 enum class GeneratorStyle { None, ES6 };
    262 
    263 /*
    264 * Builder class that constructs JavaScript AST node objects.
    265 */
    266 class NodeBuilder {
    267  using CallbackArray = RootedValueArray<AST_LIMIT>;
    268 
    269  JSContext* cx;
    270  FrontendContext* fc;
    271  frontend::Parser<frontend::FullParseHandler, char16_t>* parser;
    272  bool saveLoc;       /* save source location information?     */
    273  char const* src;    /* UTF-8 encoded source filename or null */
    274  RootedValue srcval; /* source filename JS value or null      */
    275 
    276 public:
    277  NodeBuilder(JSContext* c, FrontendContext* f, bool l, char const* s)
    278      : cx(c), fc(f), parser(nullptr), saveLoc(l), src(s), srcval(c) {}
    279 
    280  [[nodiscard]] bool init() {
    281    if (src) {
    282      if (!atomValueUtf8(src, &srcval)) {
    283        return false;
    284      }
    285    } else {
    286      srcval.setNull();
    287    }
    288 
    289    return true;
    290  }
    291 
    292  void setParser(frontend::Parser<frontend::FullParseHandler, char16_t>* p) {
    293    parser = p;
    294  }
    295 
    296 private:
    297  [[nodiscard]] bool atomValue(const char* s, MutableHandleValue dst) {
    298    MOZ_ASSERT(JS::StringIsASCII(s));
    299 
    300    /*
    301     * Bug 575416: instead of Atomize, lookup constant atoms in tbl file
    302     */
    303    Rooted<JSAtom*> atom(cx, Atomize(cx, s, strlen(s)));
    304    if (!atom) {
    305      return false;
    306    }
    307 
    308    dst.setString(atom);
    309    return true;
    310  }
    311 
    312  [[nodiscard]] bool atomValueUtf8(const char* s, MutableHandleValue dst) {
    313    Rooted<JSAtom*> atom(cx, AtomizeUTF8Chars(cx, s, strlen(s)));
    314    if (!atom) {
    315      return false;
    316    }
    317 
    318    dst.setString(atom);
    319    return true;
    320  }
    321 
    322  [[nodiscard]] bool newObject(MutableHandleObject dst) {
    323    Rooted<PlainObject*> nobj(cx, NewPlainObject(cx));
    324    if (!nobj) {
    325      return false;
    326    }
    327 
    328    dst.set(nobj);
    329    return true;
    330  }
    331 
    332  [[nodiscard]] bool newArray(NodeVector& elts, MutableHandleValue dst);
    333 
    334  [[nodiscard]] bool createNode(ASTType type, TokenPos* pos,
    335                                MutableHandleObject dst);
    336 
    337  [[nodiscard]] bool newNodeHelper(HandleObject obj, MutableHandleValue dst) {
    338    // The end of the implementation of newNode().
    339    MOZ_ASSERT(obj);
    340    dst.setObject(*obj);
    341    return true;
    342  }
    343 
    344  template <typename... Arguments>
    345  [[nodiscard]] bool newNodeHelper(HandleObject obj, const char* name,
    346                                   HandleValue value, Arguments&&... rest) {
    347    // Recursive loop to define properties. Note that the newNodeHelper()
    348    // call below passes two fewer arguments than we received, as we omit
    349    // `name` and `value`. This eventually bottoms out in a call to the
    350    // non-template newNodeHelper() above.
    351    return defineProperty(obj, name, value) &&
    352           newNodeHelper(obj, std::forward<Arguments>(rest)...);
    353  }
    354 
    355  // Create a node object with "type" and "loc" properties, as well as zero
    356  // or more properties passed in as arguments. The signature is really more
    357  // like:
    358  //
    359  //     bool newNode(ASTType type, TokenPos* pos,
    360  //                  {const char *name0, HandleValue value0,}...
    361  //                  MutableHandleValue dst);
    362  template <typename... Arguments>
    363  [[nodiscard]] bool newNode(ASTType type, TokenPos* pos, Arguments&&... args) {
    364    RootedObject node(cx);
    365    return createNode(type, pos, &node) &&
    366           newNodeHelper(node, std::forward<Arguments>(args)...);
    367  }
    368 
    369  [[nodiscard]] bool listNode(ASTType type, const char* propName,
    370                              NodeVector& elts, TokenPos* pos,
    371                              MutableHandleValue dst) {
    372    RootedValue array(cx);
    373    if (!newArray(elts, &array)) {
    374      return false;
    375    }
    376 
    377    return newNode(type, pos, propName, array, dst);
    378  }
    379 
    380  [[nodiscard]] bool defineProperty(HandleObject obj, const char* name,
    381                                    HandleValue val) {
    382    MOZ_ASSERT_IF(val.isMagic(), val.whyMagic() == JS_SERIALIZE_NO_NODE);
    383 
    384    /*
    385     * Bug 575416: instead of Atomize, lookup constant atoms in tbl file
    386     */
    387    Rooted<JSAtom*> atom(cx, Atomize(cx, name, strlen(name)));
    388    if (!atom) {
    389      return false;
    390    }
    391 
    392    // Represent "no node" as null and ensure users are not exposed to magic
    393    // values.
    394    RootedValue optVal(cx,
    395                       val.isMagic(JS_SERIALIZE_NO_NODE) ? NullValue() : val);
    396    return DefineDataProperty(cx, obj, atom->asPropertyName(), optVal);
    397  }
    398 
    399  [[nodiscard]] bool newNodeLoc(TokenPos* pos, MutableHandleValue dst);
    400 
    401  [[nodiscard]] bool setNodeLoc(HandleObject node, TokenPos* pos);
    402 
    403 public:
    404  /*
    405   * All of the public builder methods take as their last two
    406   * arguments a nullable token position and a non-nullable, rooted
    407   * outparam.
    408   *
    409   * Any Value arguments representing optional subnodes may be a
    410   * JS_SERIALIZE_NO_NODE magic value.
    411   */
    412 
    413  /*
    414   * misc nodes
    415   */
    416 
    417  [[nodiscard]] bool program(NodeVector& elts, TokenPos* pos,
    418                             MutableHandleValue dst);
    419 
    420  [[nodiscard]] bool literal(HandleValue val, TokenPos* pos,
    421                             MutableHandleValue dst);
    422 
    423  [[nodiscard]] bool identifier(HandleValue name, TokenPos* pos,
    424                                MutableHandleValue dst);
    425 
    426  [[nodiscard]] bool function(ASTType type, TokenPos* pos, HandleValue id,
    427                              NodeVector& args, NodeVector& defaults,
    428                              HandleValue body, HandleValue rest,
    429                              GeneratorStyle generatorStyle, bool isAsync,
    430                              bool isExpression, MutableHandleValue dst);
    431 
    432  [[nodiscard]] bool variableDeclarator(HandleValue id, HandleValue init,
    433                                        TokenPos* pos, MutableHandleValue dst);
    434 
    435  [[nodiscard]] bool switchCase(HandleValue expr, NodeVector& elts,
    436                                TokenPos* pos, MutableHandleValue dst);
    437 
    438  [[nodiscard]] bool catchClause(HandleValue var, HandleValue body,
    439                                 TokenPos* pos, MutableHandleValue dst);
    440 
    441  [[nodiscard]] bool prototypeMutation(HandleValue val, TokenPos* pos,
    442                                       MutableHandleValue dst);
    443  [[nodiscard]] bool propertyInitializer(HandleValue key, HandleValue val,
    444                                         PropKind kind, bool isShorthand,
    445                                         bool isMethod, TokenPos* pos,
    446                                         MutableHandleValue dst);
    447 
    448  /*
    449   * statements
    450   */
    451 
    452  [[nodiscard]] bool blockStatement(NodeVector& elts, TokenPos* pos,
    453                                    MutableHandleValue dst);
    454 
    455  [[nodiscard]] bool expressionStatement(HandleValue expr, TokenPos* pos,
    456                                         MutableHandleValue dst);
    457 
    458  [[nodiscard]] bool emptyStatement(TokenPos* pos, MutableHandleValue dst);
    459 
    460  [[nodiscard]] bool ifStatement(HandleValue test, HandleValue cons,
    461                                 HandleValue alt, TokenPos* pos,
    462                                 MutableHandleValue dst);
    463 
    464  [[nodiscard]] bool breakStatement(HandleValue label, TokenPos* pos,
    465                                    MutableHandleValue dst);
    466 
    467  [[nodiscard]] bool continueStatement(HandleValue label, TokenPos* pos,
    468                                       MutableHandleValue dst);
    469 
    470  [[nodiscard]] bool labeledStatement(HandleValue label, HandleValue stmt,
    471                                      TokenPos* pos, MutableHandleValue dst);
    472 
    473  [[nodiscard]] bool throwStatement(HandleValue arg, TokenPos* pos,
    474                                    MutableHandleValue dst);
    475 
    476  [[nodiscard]] bool returnStatement(HandleValue arg, TokenPos* pos,
    477                                     MutableHandleValue dst);
    478 
    479  [[nodiscard]] bool forStatement(HandleValue init, HandleValue test,
    480                                  HandleValue update, HandleValue stmt,
    481                                  TokenPos* pos, MutableHandleValue dst);
    482 
    483  [[nodiscard]] bool forInStatement(HandleValue var, HandleValue expr,
    484                                    HandleValue stmt, TokenPos* pos,
    485                                    MutableHandleValue dst);
    486 
    487  [[nodiscard]] bool forOfStatement(HandleValue var, HandleValue expr,
    488                                    HandleValue stmt, TokenPos* pos,
    489                                    MutableHandleValue dst);
    490 
    491  [[nodiscard]] bool withStatement(HandleValue expr, HandleValue stmt,
    492                                   TokenPos* pos, MutableHandleValue dst);
    493 
    494  [[nodiscard]] bool whileStatement(HandleValue test, HandleValue stmt,
    495                                    TokenPos* pos, MutableHandleValue dst);
    496 
    497  [[nodiscard]] bool doWhileStatement(HandleValue stmt, HandleValue test,
    498                                      TokenPos* pos, MutableHandleValue dst);
    499 
    500  [[nodiscard]] bool switchStatement(HandleValue disc, NodeVector& elts,
    501                                     bool lexical, TokenPos* pos,
    502                                     MutableHandleValue dst);
    503 
    504  [[nodiscard]] bool tryStatement(HandleValue body, HandleValue handler,
    505                                  HandleValue finally, TokenPos* pos,
    506                                  MutableHandleValue dst);
    507 
    508  [[nodiscard]] bool debuggerStatement(TokenPos* pos, MutableHandleValue dst);
    509 
    510  [[nodiscard]] bool moduleRequest(HandleValue moduleSpec,
    511                                   NodeVector& attributes, TokenPos* pos,
    512                                   MutableHandleValue dst);
    513 
    514  [[nodiscard]] bool importAttribute(HandleValue key, HandleValue value,
    515                                     TokenPos* pos, MutableHandleValue dst);
    516 
    517  [[nodiscard]] bool importDeclaration(NodeVector& elts, HandleValue moduleSpec,
    518                                       TokenPos* pos, MutableHandleValue dst);
    519 
    520  [[nodiscard]] bool importSpecifier(HandleValue importName,
    521                                     HandleValue bindingName, TokenPos* pos,
    522                                     MutableHandleValue dst);
    523 
    524  [[nodiscard]] bool importNamespaceSpecifier(HandleValue bindingName,
    525                                              TokenPos* pos,
    526                                              MutableHandleValue dst);
    527 
    528  [[nodiscard]] bool exportDeclaration(HandleValue decl, NodeVector& elts,
    529                                       HandleValue moduleSpec,
    530                                       HandleValue isDefault, TokenPos* pos,
    531                                       MutableHandleValue dst);
    532 
    533  [[nodiscard]] bool exportSpecifier(HandleValue bindingName,
    534                                     HandleValue exportName, TokenPos* pos,
    535                                     MutableHandleValue dst);
    536 
    537  [[nodiscard]] bool exportNamespaceSpecifier(HandleValue exportName,
    538                                              TokenPos* pos,
    539                                              MutableHandleValue dst);
    540 
    541  [[nodiscard]] bool exportBatchSpecifier(TokenPos* pos,
    542                                          MutableHandleValue dst);
    543 
    544  [[nodiscard]] bool classDefinition(bool expr, HandleValue name,
    545                                     HandleValue heritage, HandleValue block,
    546 #ifdef ENABLE_DECORATORS
    547                                     HandleValue decorators,
    548 #endif
    549                                     TokenPos* pos, MutableHandleValue dst);
    550  [[nodiscard]] bool classMembers(NodeVector& members, MutableHandleValue dst);
    551  [[nodiscard]] bool classMethod(HandleValue name, HandleValue body,
    552 #ifdef ENABLE_DECORATORS
    553                                 HandleValue decorators,
    554 #endif
    555                                 PropKind kind, bool isStatic, TokenPos* pos,
    556                                 MutableHandleValue dst);
    557  [[nodiscard]] bool classField(HandleValue name, HandleValue initializer,
    558 #ifdef ENABLE_DECORATORS
    559                                HandleValue decorators,
    560 #endif
    561                                TokenPos* pos, MutableHandleValue dst);
    562  [[nodiscard]] bool staticClassBlock(HandleValue body, TokenPos* pos,
    563                                      MutableHandleValue dst);
    564 
    565  /*
    566   * expressions
    567   */
    568 
    569  [[nodiscard]] bool binaryExpression(BinaryOperator op, HandleValue left,
    570                                      HandleValue right, TokenPos* pos,
    571                                      MutableHandleValue dst);
    572 
    573  [[nodiscard]] bool unaryExpression(UnaryOperator op, HandleValue expr,
    574                                     TokenPos* pos, MutableHandleValue dst);
    575 
    576  [[nodiscard]] bool assignmentExpression(AssignmentOperator op,
    577                                          HandleValue lhs, HandleValue rhs,
    578                                          TokenPos* pos,
    579                                          MutableHandleValue dst);
    580 
    581  [[nodiscard]] bool updateExpression(HandleValue expr, bool incr, bool prefix,
    582                                      TokenPos* pos, MutableHandleValue dst);
    583 
    584  [[nodiscard]] bool logicalExpression(ParseNodeKind pnk, HandleValue left,
    585                                       HandleValue right, TokenPos* pos,
    586                                       MutableHandleValue dst);
    587 
    588  [[nodiscard]] bool conditionalExpression(HandleValue test, HandleValue cons,
    589                                           HandleValue alt, TokenPos* pos,
    590                                           MutableHandleValue dst);
    591 
    592  [[nodiscard]] bool sequenceExpression(NodeVector& elts, TokenPos* pos,
    593                                        MutableHandleValue dst);
    594 
    595  [[nodiscard]] bool newExpression(HandleValue callee, NodeVector& args,
    596                                   TokenPos* pos, MutableHandleValue dst);
    597 
    598  [[nodiscard]] bool callExpression(HandleValue callee, NodeVector& args,
    599                                    TokenPos* pos, MutableHandleValue dst,
    600                                    bool isOptional = false);
    601 
    602  [[nodiscard]] bool memberExpression(bool computed, HandleValue expr,
    603                                      HandleValue member, TokenPos* pos,
    604                                      MutableHandleValue dst,
    605                                      bool isOptional = false);
    606 
    607  [[nodiscard]] bool arrayExpression(NodeVector& elts, TokenPos* pos,
    608                                     MutableHandleValue dst);
    609 
    610  [[nodiscard]] bool templateLiteral(NodeVector& elts, TokenPos* pos,
    611                                     MutableHandleValue dst);
    612 
    613  [[nodiscard]] bool taggedTemplate(HandleValue callee, NodeVector& args,
    614                                    TokenPos* pos, MutableHandleValue dst);
    615 
    616  [[nodiscard]] bool callSiteObj(NodeVector& raw, NodeVector& cooked,
    617                                 TokenPos* pos, MutableHandleValue dst);
    618 
    619  [[nodiscard]] bool spreadExpression(HandleValue expr, TokenPos* pos,
    620                                      MutableHandleValue dst);
    621 
    622  [[nodiscard]] bool optionalExpression(HandleValue expr, TokenPos* pos,
    623                                        MutableHandleValue dst);
    624 
    625  [[nodiscard]] bool deleteOptionalExpression(HandleValue expr, TokenPos* pos,
    626                                              MutableHandleValue dst);
    627 
    628  [[nodiscard]] bool computedName(HandleValue name, TokenPos* pos,
    629                                  MutableHandleValue dst);
    630 
    631  [[nodiscard]] bool objectExpression(NodeVector& elts, TokenPos* pos,
    632                                      MutableHandleValue dst);
    633 
    634  [[nodiscard]] bool thisExpression(TokenPos* pos, MutableHandleValue dst);
    635 
    636  [[nodiscard]] bool yieldExpression(HandleValue arg, YieldKind kind,
    637                                     TokenPos* pos, MutableHandleValue dst);
    638 
    639  [[nodiscard]] bool metaProperty(HandleValue meta, HandleValue property,
    640                                  TokenPos* pos, MutableHandleValue dst);
    641 
    642  [[nodiscard]] bool callImportExpression(HandleValue ident, NodeVector& args,
    643                                          TokenPos* pos,
    644                                          MutableHandleValue dst);
    645 
    646  [[nodiscard]] bool super(TokenPos* pos, MutableHandleValue dst);
    647 
    648  /*
    649   * declarations
    650   */
    651 
    652  [[nodiscard]] bool variableDeclaration(NodeVector& elts, VarDeclKind kind,
    653                                         TokenPos* pos, MutableHandleValue dst);
    654 
    655  /*
    656   * patterns
    657   */
    658 
    659  [[nodiscard]] bool arrayPattern(NodeVector& elts, TokenPos* pos,
    660                                  MutableHandleValue dst);
    661 
    662  [[nodiscard]] bool objectPattern(NodeVector& elts, TokenPos* pos,
    663                                   MutableHandleValue dst);
    664 
    665  [[nodiscard]] bool propertyPattern(HandleValue key, HandleValue patt,
    666                                     bool isShorthand, TokenPos* pos,
    667                                     MutableHandleValue dst);
    668 };
    669 
    670 } /* anonymous namespace */
    671 
    672 bool NodeBuilder::createNode(ASTType type, TokenPos* pos,
    673                             MutableHandleObject dst) {
    674  MOZ_ASSERT(type > AST_ERROR && type < AST_LIMIT);
    675 
    676  RootedValue tv(cx);
    677  Rooted<PlainObject*> node(cx, NewPlainObject(cx));
    678  if (!node || !setNodeLoc(node, pos) || !atomValue(nodeTypeNames[type], &tv) ||
    679      !defineProperty(node, "type", tv)) {
    680    return false;
    681  }
    682 
    683  dst.set(node);
    684  return true;
    685 }
    686 
    687 bool NodeBuilder::newArray(NodeVector& elts, MutableHandleValue dst) {
    688  const size_t len = elts.length();
    689  if (len > UINT32_MAX) {
    690    ReportAllocationOverflow(fc);
    691    return false;
    692  }
    693  RootedObject array(cx, NewDenseFullyAllocatedArray(cx, uint32_t(len)));
    694  if (!array) {
    695    return false;
    696  }
    697 
    698  for (size_t i = 0; i < len; i++) {
    699    RootedValue val(cx, elts[i]);
    700 
    701    MOZ_ASSERT_IF(val.isMagic(), val.whyMagic() == JS_SERIALIZE_NO_NODE);
    702 
    703    /* Represent "no node" as an array hole by not adding the value. */
    704    if (val.isMagic(JS_SERIALIZE_NO_NODE)) {
    705      continue;
    706    }
    707 
    708    if (!DefineDataElement(cx, array, i, val)) {
    709      return false;
    710    }
    711  }
    712 
    713  dst.setObject(*array);
    714  return true;
    715 }
    716 
    717 bool NodeBuilder::newNodeLoc(TokenPos* pos, MutableHandleValue dst) {
    718  if (!pos) {
    719    dst.setNull();
    720    return true;
    721  }
    722 
    723  RootedObject loc(cx);
    724  RootedObject to(cx);
    725  RootedValue val(cx);
    726 
    727  if (!newObject(&loc)) {
    728    return false;
    729  }
    730 
    731  dst.setObject(*loc);
    732 
    733  uint32_t startLineNum, endLineNum;
    734  JS::LimitedColumnNumberOneOrigin startColumnIndex, endColumnIndex;
    735  parser->tokenStream.computeLineAndColumn(pos->begin, &startLineNum,
    736                                           &startColumnIndex);
    737  parser->tokenStream.computeLineAndColumn(pos->end, &endLineNum,
    738                                           &endColumnIndex);
    739 
    740  if (!newObject(&to)) {
    741    return false;
    742  }
    743  val.setObject(*to);
    744  if (!defineProperty(loc, "start", val)) {
    745    return false;
    746  }
    747  val.setNumber(startLineNum);
    748  if (!defineProperty(to, "line", val)) {
    749    return false;
    750  }
    751  val.setNumber(startColumnIndex.oneOriginValue());
    752  if (!defineProperty(to, "column", val)) {
    753    return false;
    754  }
    755 
    756  if (!newObject(&to)) {
    757    return false;
    758  }
    759  val.setObject(*to);
    760  if (!defineProperty(loc, "end", val)) {
    761    return false;
    762  }
    763  val.setNumber(endLineNum);
    764  if (!defineProperty(to, "line", val)) {
    765    return false;
    766  }
    767  val.setNumber(endColumnIndex.oneOriginValue());
    768  if (!defineProperty(to, "column", val)) {
    769    return false;
    770  }
    771 
    772  if (!defineProperty(loc, "source", srcval)) {
    773    return false;
    774  }
    775 
    776  return true;
    777 }
    778 
    779 bool NodeBuilder::setNodeLoc(HandleObject node, TokenPos* pos) {
    780  if (!saveLoc) {
    781    return true;
    782  }
    783 
    784  RootedValue loc(cx);
    785  return newNodeLoc(pos, &loc) && defineProperty(node, "loc", loc);
    786 }
    787 
    788 bool NodeBuilder::program(NodeVector& elts, TokenPos* pos,
    789                          MutableHandleValue dst) {
    790  return listNode(AST_PROGRAM, "body", elts, pos, dst);
    791 }
    792 
    793 bool NodeBuilder::blockStatement(NodeVector& elts, TokenPos* pos,
    794                                 MutableHandleValue dst) {
    795  return listNode(AST_BLOCK_STMT, "body", elts, pos, dst);
    796 }
    797 
    798 bool NodeBuilder::expressionStatement(HandleValue expr, TokenPos* pos,
    799                                      MutableHandleValue dst) {
    800  return newNode(AST_EXPR_STMT, pos, "expression", expr, dst);
    801 }
    802 
    803 bool NodeBuilder::emptyStatement(TokenPos* pos, MutableHandleValue dst) {
    804  return newNode(AST_EMPTY_STMT, pos, dst);
    805 }
    806 
    807 bool NodeBuilder::ifStatement(HandleValue test, HandleValue cons,
    808                              HandleValue alt, TokenPos* pos,
    809                              MutableHandleValue dst) {
    810  return newNode(AST_IF_STMT, pos, "test", test, "consequent", cons,
    811                 "alternate", alt, dst);
    812 }
    813 
    814 bool NodeBuilder::breakStatement(HandleValue label, TokenPos* pos,
    815                                 MutableHandleValue dst) {
    816  return newNode(AST_BREAK_STMT, pos, "label", label, dst);
    817 }
    818 
    819 bool NodeBuilder::continueStatement(HandleValue label, TokenPos* pos,
    820                                    MutableHandleValue dst) {
    821  return newNode(AST_CONTINUE_STMT, pos, "label", label, dst);
    822 }
    823 
    824 bool NodeBuilder::labeledStatement(HandleValue label, HandleValue stmt,
    825                                   TokenPos* pos, MutableHandleValue dst) {
    826  return newNode(AST_LAB_STMT, pos, "label", label, "body", stmt, dst);
    827 }
    828 
    829 bool NodeBuilder::throwStatement(HandleValue arg, TokenPos* pos,
    830                                 MutableHandleValue dst) {
    831  return newNode(AST_THROW_STMT, pos, "argument", arg, dst);
    832 }
    833 
    834 bool NodeBuilder::returnStatement(HandleValue arg, TokenPos* pos,
    835                                  MutableHandleValue dst) {
    836  return newNode(AST_RETURN_STMT, pos, "argument", arg, dst);
    837 }
    838 
    839 bool NodeBuilder::forStatement(HandleValue init, HandleValue test,
    840                               HandleValue update, HandleValue stmt,
    841                               TokenPos* pos, MutableHandleValue dst) {
    842  return newNode(AST_FOR_STMT, pos, "init", init, "test", test, "update",
    843                 update, "body", stmt, dst);
    844 }
    845 
    846 bool NodeBuilder::forInStatement(HandleValue var, HandleValue expr,
    847                                 HandleValue stmt, TokenPos* pos,
    848                                 MutableHandleValue dst) {
    849  return newNode(AST_FOR_IN_STMT, pos, "left", var, "right", expr, "body", stmt,
    850                 dst);
    851 }
    852 
    853 bool NodeBuilder::forOfStatement(HandleValue var, HandleValue expr,
    854                                 HandleValue stmt, TokenPos* pos,
    855                                 MutableHandleValue dst) {
    856  return newNode(AST_FOR_OF_STMT, pos, "left", var, "right", expr, "body", stmt,
    857                 dst);
    858 }
    859 
    860 bool NodeBuilder::withStatement(HandleValue expr, HandleValue stmt,
    861                                TokenPos* pos, MutableHandleValue dst) {
    862  return newNode(AST_WITH_STMT, pos, "object", expr, "body", stmt, dst);
    863 }
    864 
    865 bool NodeBuilder::whileStatement(HandleValue test, HandleValue stmt,
    866                                 TokenPos* pos, MutableHandleValue dst) {
    867  return newNode(AST_WHILE_STMT, pos, "test", test, "body", stmt, dst);
    868 }
    869 
    870 bool NodeBuilder::doWhileStatement(HandleValue stmt, HandleValue test,
    871                                   TokenPos* pos, MutableHandleValue dst) {
    872  return newNode(AST_DO_STMT, pos, "body", stmt, "test", test, dst);
    873 }
    874 
    875 bool NodeBuilder::switchStatement(HandleValue disc, NodeVector& elts,
    876                                  bool lexical, TokenPos* pos,
    877                                  MutableHandleValue dst) {
    878  RootedValue array(cx);
    879  if (!newArray(elts, &array)) {
    880    return false;
    881  }
    882 
    883  RootedValue lexicalVal(cx, BooleanValue(lexical));
    884  return newNode(AST_SWITCH_STMT, pos, "discriminant", disc, "cases", array,
    885                 "lexical", lexicalVal, dst);
    886 }
    887 
    888 bool NodeBuilder::tryStatement(HandleValue body, HandleValue handler,
    889                               HandleValue finally, TokenPos* pos,
    890                               MutableHandleValue dst) {
    891  return newNode(AST_TRY_STMT, pos, "block", body, "handler", handler,
    892                 "finalizer", finally, dst);
    893 }
    894 
    895 bool NodeBuilder::debuggerStatement(TokenPos* pos, MutableHandleValue dst) {
    896  return newNode(AST_DEBUGGER_STMT, pos, dst);
    897 }
    898 
    899 bool NodeBuilder::binaryExpression(BinaryOperator op, HandleValue left,
    900                                   HandleValue right, TokenPos* pos,
    901                                   MutableHandleValue dst) {
    902  MOZ_ASSERT(op > BINOP_ERR && op < BINOP_LIMIT);
    903 
    904  RootedValue opName(cx);
    905  if (!atomValue(binopNames[op], &opName)) {
    906    return false;
    907  }
    908 
    909  return newNode(AST_BINARY_EXPR, pos, "operator", opName, "left", left,
    910                 "right", right, dst);
    911 }
    912 
    913 bool NodeBuilder::unaryExpression(UnaryOperator unop, HandleValue expr,
    914                                  TokenPos* pos, MutableHandleValue dst) {
    915  MOZ_ASSERT(unop > UNOP_ERR && unop < UNOP_LIMIT);
    916 
    917  RootedValue opName(cx);
    918  if (!atomValue(unopNames[unop], &opName)) {
    919    return false;
    920  }
    921 
    922  RootedValue trueVal(cx, BooleanValue(true));
    923  return newNode(AST_UNARY_EXPR, pos, "operator", opName, "argument", expr,
    924                 "prefix", trueVal, dst);
    925 }
    926 
    927 bool NodeBuilder::assignmentExpression(AssignmentOperator aop, HandleValue lhs,
    928                                       HandleValue rhs, TokenPos* pos,
    929                                       MutableHandleValue dst) {
    930  MOZ_ASSERT(aop > AOP_ERR && aop < AOP_LIMIT);
    931 
    932  RootedValue opName(cx);
    933  if (!atomValue(aopNames[aop], &opName)) {
    934    return false;
    935  }
    936 
    937  return newNode(AST_ASSIGN_EXPR, pos, "operator", opName, "left", lhs, "right",
    938                 rhs, dst);
    939 }
    940 
    941 bool NodeBuilder::updateExpression(HandleValue expr, bool incr, bool prefix,
    942                                   TokenPos* pos, MutableHandleValue dst) {
    943  RootedValue opName(cx);
    944  if (!atomValue(incr ? "++" : "--", &opName)) {
    945    return false;
    946  }
    947 
    948  RootedValue prefixVal(cx, BooleanValue(prefix));
    949 
    950  return newNode(AST_UPDATE_EXPR, pos, "operator", opName, "argument", expr,
    951                 "prefix", prefixVal, dst);
    952 }
    953 
    954 bool NodeBuilder::logicalExpression(ParseNodeKind pnk, HandleValue left,
    955                                    HandleValue right, TokenPos* pos,
    956                                    MutableHandleValue dst) {
    957  RootedValue opName(cx);
    958  switch (pnk) {
    959    case ParseNodeKind::OrExpr:
    960      if (!atomValue("||", &opName)) {
    961        return false;
    962      }
    963      break;
    964    case ParseNodeKind::CoalesceExpr:
    965      if (!atomValue("??", &opName)) {
    966        return false;
    967      }
    968      break;
    969    case ParseNodeKind::AndExpr:
    970      if (!atomValue("&&", &opName)) {
    971        return false;
    972      }
    973      break;
    974    default:
    975      MOZ_CRASH("Unexpected ParseNodeKind: Must be `Or`, `And`, or `Coalesce`");
    976  }
    977 
    978  return newNode(AST_LOGICAL_EXPR, pos, "operator", opName, "left", left,
    979                 "right", right, dst);
    980 }
    981 
    982 bool NodeBuilder::conditionalExpression(HandleValue test, HandleValue cons,
    983                                        HandleValue alt, TokenPos* pos,
    984                                        MutableHandleValue dst) {
    985  return newNode(AST_COND_EXPR, pos, "test", test, "consequent", cons,
    986                 "alternate", alt, dst);
    987 }
    988 
    989 bool NodeBuilder::sequenceExpression(NodeVector& elts, TokenPos* pos,
    990                                     MutableHandleValue dst) {
    991  return listNode(AST_LIST_EXPR, "expressions", elts, pos, dst);
    992 }
    993 
    994 bool NodeBuilder::callExpression(HandleValue callee, NodeVector& args,
    995                                 TokenPos* pos, MutableHandleValue dst,
    996                                 bool isOptional) {
    997  RootedValue array(cx);
    998  if (!newArray(args, &array)) {
    999    return false;
   1000  }
   1001 
   1002  return newNode(isOptional ? AST_OPT_CALL_EXPR : AST_CALL_EXPR, pos, "callee",
   1003                 callee, "arguments", array, dst);
   1004 }
   1005 
   1006 bool NodeBuilder::newExpression(HandleValue callee, NodeVector& args,
   1007                                TokenPos* pos, MutableHandleValue dst) {
   1008  RootedValue array(cx);
   1009  if (!newArray(args, &array)) {
   1010    return false;
   1011  }
   1012 
   1013  return newNode(AST_NEW_EXPR, pos, "callee", callee, "arguments", array, dst);
   1014 }
   1015 
   1016 bool NodeBuilder::memberExpression(bool computed, HandleValue expr,
   1017                                   HandleValue member, TokenPos* pos,
   1018                                   MutableHandleValue dst,
   1019                                   bool isOptional /* = false */) {
   1020  RootedValue computedVal(cx, BooleanValue(computed));
   1021 
   1022  return newNode(isOptional ? AST_OPT_MEMBER_EXPR : AST_MEMBER_EXPR, pos,
   1023                 "object", expr, "property", member, "computed", computedVal,
   1024                 dst);
   1025 }
   1026 
   1027 bool NodeBuilder::arrayExpression(NodeVector& elts, TokenPos* pos,
   1028                                  MutableHandleValue dst) {
   1029  return listNode(AST_ARRAY_EXPR, "elements", elts, pos, dst);
   1030 }
   1031 
   1032 bool NodeBuilder::callSiteObj(NodeVector& raw, NodeVector& cooked,
   1033                              TokenPos* pos, MutableHandleValue dst) {
   1034  RootedValue rawVal(cx);
   1035  if (!newArray(raw, &rawVal)) {
   1036    return false;
   1037  }
   1038 
   1039  RootedValue cookedVal(cx);
   1040  if (!newArray(cooked, &cookedVal)) {
   1041    return false;
   1042  }
   1043 
   1044  return newNode(AST_CALL_SITE_OBJ, pos, "raw", rawVal, "cooked", cookedVal,
   1045                 dst);
   1046 }
   1047 
   1048 bool NodeBuilder::taggedTemplate(HandleValue callee, NodeVector& args,
   1049                                 TokenPos* pos, MutableHandleValue dst) {
   1050  RootedValue array(cx);
   1051  if (!newArray(args, &array)) {
   1052    return false;
   1053  }
   1054 
   1055  return newNode(AST_TAGGED_TEMPLATE, pos, "callee", callee, "arguments", array,
   1056                 dst);
   1057 }
   1058 
   1059 bool NodeBuilder::templateLiteral(NodeVector& elts, TokenPos* pos,
   1060                                  MutableHandleValue dst) {
   1061  return listNode(AST_TEMPLATE_LITERAL, "elements", elts, pos, dst);
   1062 }
   1063 
   1064 bool NodeBuilder::computedName(HandleValue name, TokenPos* pos,
   1065                               MutableHandleValue dst) {
   1066  return newNode(AST_COMPUTED_NAME, pos, "name", name, dst);
   1067 }
   1068 
   1069 bool NodeBuilder::spreadExpression(HandleValue expr, TokenPos* pos,
   1070                                   MutableHandleValue dst) {
   1071  return newNode(AST_SPREAD_EXPR, pos, "expression", expr, dst);
   1072 }
   1073 
   1074 bool NodeBuilder::optionalExpression(HandleValue expr, TokenPos* pos,
   1075                                     MutableHandleValue dst) {
   1076  return newNode(AST_OPTIONAL_EXPR, pos, "expression", expr, dst);
   1077 }
   1078 
   1079 bool NodeBuilder::deleteOptionalExpression(HandleValue expr, TokenPos* pos,
   1080                                           MutableHandleValue dst) {
   1081  return newNode(AST_DELETE_OPTIONAL_EXPR, pos, "expression", expr, dst);
   1082 }
   1083 
   1084 bool NodeBuilder::propertyPattern(HandleValue key, HandleValue patt,
   1085                                  bool isShorthand, TokenPos* pos,
   1086                                  MutableHandleValue dst) {
   1087  RootedValue kindName(cx);
   1088  if (!atomValue("init", &kindName)) {
   1089    return false;
   1090  }
   1091 
   1092  RootedValue isShorthandVal(cx, BooleanValue(isShorthand));
   1093 
   1094  return newNode(AST_PROP_PATT, pos, "key", key, "value", patt, "kind",
   1095                 kindName, "shorthand", isShorthandVal, dst);
   1096 }
   1097 
   1098 bool NodeBuilder::prototypeMutation(HandleValue val, TokenPos* pos,
   1099                                    MutableHandleValue dst) {
   1100  return newNode(AST_PROTOTYPEMUTATION, pos, "value", val, dst);
   1101 }
   1102 
   1103 bool NodeBuilder::propertyInitializer(HandleValue key, HandleValue val,
   1104                                      PropKind kind, bool isShorthand,
   1105                                      bool isMethod, TokenPos* pos,
   1106                                      MutableHandleValue dst) {
   1107  RootedValue kindName(cx);
   1108  if (!atomValue(kind == PROP_INIT     ? "init"
   1109                 : kind == PROP_GETTER ? "get"
   1110                                       : "set",
   1111                 &kindName)) {
   1112    return false;
   1113  }
   1114 
   1115  RootedValue isShorthandVal(cx, BooleanValue(isShorthand));
   1116  RootedValue isMethodVal(cx, BooleanValue(isMethod));
   1117 
   1118  return newNode(AST_PROPERTY, pos, "key", key, "value", val, "kind", kindName,
   1119                 "method", isMethodVal, "shorthand", isShorthandVal, dst);
   1120 }
   1121 
   1122 bool NodeBuilder::objectExpression(NodeVector& elts, TokenPos* pos,
   1123                                   MutableHandleValue dst) {
   1124  return listNode(AST_OBJECT_EXPR, "properties", elts, pos, dst);
   1125 }
   1126 
   1127 bool NodeBuilder::thisExpression(TokenPos* pos, MutableHandleValue dst) {
   1128  return newNode(AST_THIS_EXPR, pos, dst);
   1129 }
   1130 
   1131 bool NodeBuilder::yieldExpression(HandleValue arg, YieldKind kind,
   1132                                  TokenPos* pos, MutableHandleValue dst) {
   1133  RootedValue delegateVal(cx);
   1134  switch (kind) {
   1135    case Delegating:
   1136      delegateVal = BooleanValue(true);
   1137      break;
   1138    case NotDelegating:
   1139      delegateVal = BooleanValue(false);
   1140      break;
   1141  }
   1142  return newNode(AST_YIELD_EXPR, pos, "argument", arg, "delegate", delegateVal,
   1143                 dst);
   1144 }
   1145 
   1146 bool NodeBuilder::moduleRequest(HandleValue moduleSpec, NodeVector& attributes,
   1147                                TokenPos* pos, MutableHandleValue dst) {
   1148  RootedValue array(cx);
   1149  if (!newArray(attributes, &array)) {
   1150    return false;
   1151  }
   1152 
   1153  return newNode(AST_MODULE_REQUEST, pos, "source", moduleSpec, "attributes",
   1154                 array, dst);
   1155 }
   1156 
   1157 bool NodeBuilder::importAttribute(HandleValue key, HandleValue value,
   1158                                  TokenPos* pos, MutableHandleValue dst) {
   1159  return newNode(AST_IMPORT_ATTRIBUTE, pos, "key", key, "value", value, dst);
   1160 }
   1161 
   1162 bool NodeBuilder::importDeclaration(NodeVector& elts, HandleValue moduleRequest,
   1163                                    TokenPos* pos, MutableHandleValue dst) {
   1164  RootedValue array(cx);
   1165  if (!newArray(elts, &array)) {
   1166    return false;
   1167  }
   1168 
   1169  return newNode(AST_IMPORT_DECL, pos, "specifiers", array, "moduleRequest",
   1170                 moduleRequest, dst);
   1171 }
   1172 
   1173 bool NodeBuilder::importSpecifier(HandleValue importName,
   1174                                  HandleValue bindingName, TokenPos* pos,
   1175                                  MutableHandleValue dst) {
   1176  return newNode(AST_IMPORT_SPEC, pos, "id", importName, "name", bindingName,
   1177                 dst);
   1178 }
   1179 
   1180 bool NodeBuilder::importNamespaceSpecifier(HandleValue bindingName,
   1181                                           TokenPos* pos,
   1182                                           MutableHandleValue dst) {
   1183  return newNode(AST_IMPORT_NAMESPACE_SPEC, pos, "name", bindingName, dst);
   1184 }
   1185 
   1186 bool NodeBuilder::exportDeclaration(HandleValue decl, NodeVector& elts,
   1187                                    HandleValue moduleRequest,
   1188                                    HandleValue isDefault, TokenPos* pos,
   1189                                    MutableHandleValue dst) {
   1190  RootedValue array(cx, NullValue());
   1191  if (decl.isNull() && !newArray(elts, &array)) {
   1192    return false;
   1193  }
   1194 
   1195  return newNode(AST_EXPORT_DECL, pos, "declaration", decl, "specifiers", array,
   1196                 "moduleRequest", moduleRequest, "isDefault", isDefault, dst);
   1197 }
   1198 
   1199 bool NodeBuilder::exportSpecifier(HandleValue bindingName,
   1200                                  HandleValue exportName, TokenPos* pos,
   1201                                  MutableHandleValue dst) {
   1202  return newNode(AST_EXPORT_SPEC, pos, "id", bindingName, "name", exportName,
   1203                 dst);
   1204 }
   1205 
   1206 bool NodeBuilder::exportNamespaceSpecifier(HandleValue exportName,
   1207                                           TokenPos* pos,
   1208                                           MutableHandleValue dst) {
   1209  return newNode(AST_EXPORT_NAMESPACE_SPEC, pos, "name", exportName, dst);
   1210 }
   1211 
   1212 bool NodeBuilder::exportBatchSpecifier(TokenPos* pos, MutableHandleValue dst) {
   1213  return newNode(AST_EXPORT_BATCH_SPEC, pos, dst);
   1214 }
   1215 
   1216 bool NodeBuilder::variableDeclaration(NodeVector& elts, VarDeclKind kind,
   1217                                      TokenPos* pos, MutableHandleValue dst) {
   1218  MOZ_ASSERT(kind > VARDECL_ERR && kind < VARDECL_LIMIT);
   1219 
   1220  RootedValue array(cx), kindName(cx);
   1221  const char* s;
   1222  switch (kind) {
   1223    case VARDECL_CONST:
   1224      s = "const";
   1225      break;
   1226    case VARDECL_LET:
   1227      s = "let";
   1228      break;
   1229 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   1230    case VARDECL_USING:
   1231      s = "using";
   1232      break;
   1233    case VARDECL_AWAIT_USING:
   1234      s = "await using";
   1235      break;
   1236 #endif
   1237    default:
   1238      s = "var";
   1239  }
   1240  if (!newArray(elts, &array) || !atomValue(s, &kindName)) {
   1241    return false;
   1242  }
   1243 
   1244  return newNode(AST_VAR_DECL, pos, "kind", kindName, "declarations", array,
   1245                 dst);
   1246 }
   1247 
   1248 bool NodeBuilder::variableDeclarator(HandleValue id, HandleValue init,
   1249                                     TokenPos* pos, MutableHandleValue dst) {
   1250  return newNode(AST_VAR_DTOR, pos, "id", id, "init", init, dst);
   1251 }
   1252 
   1253 bool NodeBuilder::switchCase(HandleValue expr, NodeVector& elts, TokenPos* pos,
   1254                             MutableHandleValue dst) {
   1255  RootedValue array(cx);
   1256  if (!newArray(elts, &array)) {
   1257    return false;
   1258  }
   1259 
   1260  return newNode(AST_CASE, pos, "test", expr, "consequent", array, dst);
   1261 }
   1262 
   1263 bool NodeBuilder::catchClause(HandleValue var, HandleValue body, TokenPos* pos,
   1264                              MutableHandleValue dst) {
   1265  return newNode(AST_CATCH, pos, "param", var, "body", body, dst);
   1266 }
   1267 
   1268 bool NodeBuilder::literal(HandleValue val, TokenPos* pos,
   1269                          MutableHandleValue dst) {
   1270  return newNode(AST_LITERAL, pos, "value", val, dst);
   1271 }
   1272 
   1273 bool NodeBuilder::identifier(HandleValue name, TokenPos* pos,
   1274                             MutableHandleValue dst) {
   1275  return newNode(AST_IDENTIFIER, pos, "name", name, dst);
   1276 }
   1277 
   1278 bool NodeBuilder::objectPattern(NodeVector& elts, TokenPos* pos,
   1279                                MutableHandleValue dst) {
   1280  return listNode(AST_OBJECT_PATT, "properties", elts, pos, dst);
   1281 }
   1282 
   1283 bool NodeBuilder::arrayPattern(NodeVector& elts, TokenPos* pos,
   1284                               MutableHandleValue dst) {
   1285  return listNode(AST_ARRAY_PATT, "elements", elts, pos, dst);
   1286 }
   1287 
   1288 bool NodeBuilder::function(ASTType type, TokenPos* pos, HandleValue id,
   1289                           NodeVector& args, NodeVector& defaults,
   1290                           HandleValue body, HandleValue rest,
   1291                           GeneratorStyle generatorStyle, bool isAsync,
   1292                           bool isExpression, MutableHandleValue dst) {
   1293  RootedValue array(cx), defarray(cx);
   1294  if (!newArray(args, &array)) {
   1295    return false;
   1296  }
   1297  if (!newArray(defaults, &defarray)) {
   1298    return false;
   1299  }
   1300 
   1301  bool isGenerator = generatorStyle != GeneratorStyle::None;
   1302  RootedValue isGeneratorVal(cx, BooleanValue(isGenerator));
   1303  RootedValue isAsyncVal(cx, BooleanValue(isAsync));
   1304  RootedValue isExpressionVal(cx, BooleanValue(isExpression));
   1305 
   1306  if (isGenerator) {
   1307    MOZ_ASSERT(generatorStyle == GeneratorStyle::ES6);
   1308    JSAtom* styleStr = Atomize(cx, "es6", 3);
   1309    if (!styleStr) {
   1310      return false;
   1311    }
   1312    RootedValue styleVal(cx, StringValue(styleStr));
   1313    return newNode(type, pos, "id", id, "params", array, "defaults", defarray,
   1314                   "body", body, "rest", rest, "generator", isGeneratorVal,
   1315                   "async", isAsyncVal, "style", styleVal, "expression",
   1316                   isExpressionVal, dst);
   1317  }
   1318 
   1319  return newNode(type, pos, "id", id, "params", array, "defaults", defarray,
   1320                 "body", body, "rest", rest, "generator", isGeneratorVal,
   1321                 "async", isAsyncVal, "expression", isExpressionVal, dst);
   1322 }
   1323 
   1324 bool NodeBuilder::classMethod(HandleValue name, HandleValue body,
   1325 #ifdef ENABLE_DECORATORS
   1326                              HandleValue decorators,
   1327 #endif
   1328                              PropKind kind, bool isStatic, TokenPos* pos,
   1329                              MutableHandleValue dst) {
   1330  RootedValue kindName(cx);
   1331  if (!atomValue(kind == PROP_INIT     ? "method"
   1332                 : kind == PROP_GETTER ? "get"
   1333                                       : "set",
   1334                 &kindName)) {
   1335    return false;
   1336  }
   1337 
   1338  RootedValue isStaticVal(cx, BooleanValue(isStatic));
   1339  return newNode(AST_CLASS_METHOD, pos, "name", name, "body", body, "kind",
   1340                 kindName, "static", isStaticVal,
   1341 #ifdef ENABLE_DECORATORS
   1342                 "decorators", decorators,
   1343 #endif
   1344                 dst);
   1345 }
   1346 
   1347 bool NodeBuilder::classField(HandleValue name, HandleValue initializer,
   1348 #ifdef ENABLE_DECORATORS
   1349                             HandleValue decorators,
   1350 #endif
   1351                             TokenPos* pos, MutableHandleValue dst) {
   1352  return newNode(AST_CLASS_FIELD, pos, "name", name, "init", initializer,
   1353 #ifdef ENABLE_DECORATORS
   1354                 "decorators", decorators,
   1355 #endif
   1356                 dst);
   1357 }
   1358 
   1359 bool NodeBuilder::staticClassBlock(HandleValue body, TokenPos* pos,
   1360                                   MutableHandleValue dst) {
   1361  return newNode(AST_STATIC_CLASS_BLOCK, pos, "body", body, dst);
   1362 }
   1363 
   1364 bool NodeBuilder::classMembers(NodeVector& members, MutableHandleValue dst) {
   1365  return newArray(members, dst);
   1366 }
   1367 
   1368 bool NodeBuilder::classDefinition(bool expr, HandleValue name,
   1369                                  HandleValue heritage, HandleValue block,
   1370 #ifdef ENABLE_DECORATORS
   1371                                  HandleValue decorators,
   1372 #endif
   1373                                  TokenPos* pos, MutableHandleValue dst) {
   1374  ASTType type = expr ? AST_CLASS_EXPR : AST_CLASS_STMT;
   1375  return newNode(type, pos, "id", name, "superClass", heritage, "body", block,
   1376 #ifdef ENABLE_DECORATORS
   1377                 "decorators", decorators,
   1378 #endif
   1379                 dst);
   1380 }
   1381 
   1382 bool NodeBuilder::metaProperty(HandleValue meta, HandleValue property,
   1383                               TokenPos* pos, MutableHandleValue dst) {
   1384  return newNode(AST_METAPROPERTY, pos, "meta", meta, "property", property,
   1385                 dst);
   1386 }
   1387 
   1388 bool NodeBuilder::callImportExpression(HandleValue ident, NodeVector& args,
   1389                                       TokenPos* pos, MutableHandleValue dst) {
   1390  RootedValue array(cx);
   1391  if (!newArray(args, &array)) {
   1392    return false;
   1393  }
   1394 
   1395  return newNode(AST_CALL_IMPORT, pos, "ident", ident, "arguments", array, dst);
   1396 }
   1397 
   1398 bool NodeBuilder::super(TokenPos* pos, MutableHandleValue dst) {
   1399  return newNode(AST_SUPER, pos, dst);
   1400 }
   1401 
   1402 namespace {
   1403 
   1404 /*
   1405 * Serialization of parse nodes to JavaScript objects.
   1406 *
   1407 * All serialization methods take a non-nullable ParseNode pointer.
   1408 */
   1409 class ASTSerializer {
   1410  JSContext* cx;
   1411  FrontendContext* fc;
   1412  Parser<FullParseHandler, char16_t>* parser;
   1413  NodeBuilder builder;
   1414  DebugOnly<uint32_t> lineno;
   1415 
   1416  Value unrootedAtomContents(JSAtom* atom) {
   1417    return StringValue(atom ? atom : cx->names().empty_);
   1418  }
   1419 
   1420  BinaryOperator binop(ParseNodeKind kind);
   1421  UnaryOperator unop(ParseNodeKind kind);
   1422  AssignmentOperator aop(ParseNodeKind kind);
   1423 
   1424  bool statements(ListNode* stmtList, NodeVector& elts);
   1425  bool expressions(ListNode* exprList, NodeVector& elts);
   1426  bool leftAssociate(ListNode* node, MutableHandleValue dst);
   1427  bool rightAssociate(ListNode* node, MutableHandleValue dst);
   1428  bool functionArgs(ParamsBodyNode* pn, NodeVector& args, NodeVector& defaults,
   1429                    MutableHandleValue rest);
   1430 
   1431  bool sourceElement(ParseNode* pn, MutableHandleValue dst);
   1432 
   1433  bool declaration(ParseNode* pn, MutableHandleValue dst);
   1434  bool variableDeclaration(ListNode* declList, bool lexical,
   1435                           MutableHandleValue dst);
   1436  bool variableDeclarator(ParseNode* pn, MutableHandleValue dst);
   1437  bool importDeclaration(BinaryNode* importNode, MutableHandleValue dst);
   1438  bool importSpecifier(BinaryNode* importSpec, MutableHandleValue dst);
   1439  bool importNamespaceSpecifier(UnaryNode* importSpec, MutableHandleValue dst);
   1440  bool exportDeclaration(ParseNode* exportNode, MutableHandleValue dst);
   1441  bool exportSpecifier(BinaryNode* exportSpec, MutableHandleValue dst);
   1442  bool exportNamespaceSpecifier(UnaryNode* exportSpec, MutableHandleValue dst);
   1443  bool classDefinition(ClassNode* pn, bool expr, MutableHandleValue dst);
   1444  bool importAttributes(ListNode* attributeList, NodeVector& attributes);
   1445 
   1446  bool optStatement(ParseNode* pn, MutableHandleValue dst) {
   1447    if (!pn) {
   1448      dst.setMagic(JS_SERIALIZE_NO_NODE);
   1449      return true;
   1450    }
   1451    return statement(pn, dst);
   1452  }
   1453 
   1454  bool forInit(ParseNode* pn, MutableHandleValue dst);
   1455  bool forIn(ForNode* loop, ParseNode* iterExpr, HandleValue var,
   1456             HandleValue stmt, MutableHandleValue dst);
   1457  bool forOf(ForNode* loop, ParseNode* iterExpr, HandleValue var,
   1458             HandleValue stmt, MutableHandleValue dst);
   1459  bool statement(ParseNode* pn, MutableHandleValue dst);
   1460  bool blockStatement(ListNode* node, MutableHandleValue dst);
   1461  bool switchStatement(SwitchStatement* switchStmt, MutableHandleValue dst);
   1462  bool switchCase(CaseClause* caseClause, MutableHandleValue dst);
   1463  bool tryStatement(TryNode* tryNode, MutableHandleValue dst);
   1464  bool catchClause(BinaryNode* catchClause, MutableHandleValue dst);
   1465 
   1466  bool optExpression(ParseNode* pn, MutableHandleValue dst) {
   1467    if (!pn) {
   1468      dst.setMagic(JS_SERIALIZE_NO_NODE);
   1469      return true;
   1470    }
   1471    return expression(pn, dst);
   1472  }
   1473 
   1474  bool expression(ParseNode* pn, MutableHandleValue dst);
   1475 
   1476  bool propertyName(ParseNode* key, MutableHandleValue dst);
   1477  bool property(ParseNode* pn, MutableHandleValue dst);
   1478 
   1479  bool classMethod(ClassMethod* classMethod, MutableHandleValue dst);
   1480  bool classField(ClassField* classField, MutableHandleValue dst);
   1481  bool staticClassBlock(StaticClassBlock* staticClassBlock,
   1482                        MutableHandleValue dst);
   1483 
   1484  bool optIdentifier(Handle<JSAtom*> atom, TokenPos* pos,
   1485                     MutableHandleValue dst) {
   1486    if (!atom) {
   1487      dst.setMagic(JS_SERIALIZE_NO_NODE);
   1488      return true;
   1489    }
   1490    return identifier(atom, pos, dst);
   1491  }
   1492 
   1493  bool identifier(Handle<JSAtom*> atom, TokenPos* pos, MutableHandleValue dst);
   1494  bool identifier(NameNode* id, MutableHandleValue dst);
   1495  bool identifierOrLiteral(ParseNode* id, MutableHandleValue dst);
   1496  bool literal(ParseNode* pn, MutableHandleValue dst);
   1497 
   1498  bool optPattern(ParseNode* pn, MutableHandleValue dst) {
   1499    if (!pn) {
   1500      dst.setMagic(JS_SERIALIZE_NO_NODE);
   1501      return true;
   1502    }
   1503    return pattern(pn, dst);
   1504  }
   1505 
   1506  bool pattern(ParseNode* pn, MutableHandleValue dst);
   1507  bool arrayPattern(ListNode* array, MutableHandleValue dst);
   1508  bool objectPattern(ListNode* obj, MutableHandleValue dst);
   1509 
   1510  bool function(FunctionNode* funNode, ASTType type, MutableHandleValue dst);
   1511  bool functionArgsAndBody(ParamsBodyNode* pn, NodeVector& args,
   1512                           NodeVector& defaults, bool isAsync,
   1513                           bool isExpression, MutableHandleValue body,
   1514                           MutableHandleValue rest);
   1515  bool functionBody(ParseNode* pn, TokenPos* pos, MutableHandleValue dst);
   1516 
   1517 public:
   1518  ASTSerializer(JSContext* c, FrontendContext* f, bool l, char const* src,
   1519                uint32_t ln)
   1520      : cx(c),
   1521        fc(f),
   1522        parser(nullptr),
   1523        builder(c, f, l, src)
   1524 #ifdef DEBUG
   1525        ,
   1526        lineno(ln)
   1527 #endif
   1528  {
   1529  }
   1530 
   1531  bool init() { return builder.init(); }
   1532 
   1533  void setParser(frontend::Parser<frontend::FullParseHandler, char16_t>* p) {
   1534    parser = p;
   1535    builder.setParser(p);
   1536  }
   1537 
   1538  bool program(ListNode* node, MutableHandleValue dst);
   1539 };
   1540 
   1541 } /* anonymous namespace */
   1542 
   1543 AssignmentOperator ASTSerializer::aop(ParseNodeKind kind) {
   1544  switch (kind) {
   1545    case ParseNodeKind::AssignExpr:
   1546      return AOP_ASSIGN;
   1547    case ParseNodeKind::AddAssignExpr:
   1548      return AOP_PLUS;
   1549    case ParseNodeKind::SubAssignExpr:
   1550      return AOP_MINUS;
   1551    case ParseNodeKind::MulAssignExpr:
   1552      return AOP_STAR;
   1553    case ParseNodeKind::DivAssignExpr:
   1554      return AOP_DIV;
   1555    case ParseNodeKind::ModAssignExpr:
   1556      return AOP_MOD;
   1557    case ParseNodeKind::PowAssignExpr:
   1558      return AOP_POW;
   1559    case ParseNodeKind::LshAssignExpr:
   1560      return AOP_LSH;
   1561    case ParseNodeKind::RshAssignExpr:
   1562      return AOP_RSH;
   1563    case ParseNodeKind::UrshAssignExpr:
   1564      return AOP_URSH;
   1565    case ParseNodeKind::BitOrAssignExpr:
   1566      return AOP_BITOR;
   1567    case ParseNodeKind::BitXorAssignExpr:
   1568      return AOP_BITXOR;
   1569    case ParseNodeKind::BitAndAssignExpr:
   1570      return AOP_BITAND;
   1571    case ParseNodeKind::CoalesceAssignExpr:
   1572      return AOP_COALESCE;
   1573    case ParseNodeKind::OrAssignExpr:
   1574      return AOP_OR;
   1575    case ParseNodeKind::AndAssignExpr:
   1576      return AOP_AND;
   1577    default:
   1578      return AOP_ERR;
   1579  }
   1580 }
   1581 
   1582 UnaryOperator ASTSerializer::unop(ParseNodeKind kind) {
   1583  if (IsDeleteKind(kind)) {
   1584    return UNOP_DELETE;
   1585  }
   1586 
   1587  if (IsTypeofKind(kind)) {
   1588    return UNOP_TYPEOF;
   1589  }
   1590 
   1591  switch (kind) {
   1592    case ParseNodeKind::AwaitExpr:
   1593      return UNOP_AWAIT;
   1594    case ParseNodeKind::NegExpr:
   1595      return UNOP_NEG;
   1596    case ParseNodeKind::PosExpr:
   1597      return UNOP_POS;
   1598    case ParseNodeKind::NotExpr:
   1599      return UNOP_NOT;
   1600    case ParseNodeKind::BitNotExpr:
   1601      return UNOP_BITNOT;
   1602    case ParseNodeKind::VoidExpr:
   1603      return UNOP_VOID;
   1604    default:
   1605      return UNOP_ERR;
   1606  }
   1607 }
   1608 
   1609 BinaryOperator ASTSerializer::binop(ParseNodeKind kind) {
   1610  switch (kind) {
   1611    case ParseNodeKind::LshExpr:
   1612      return BINOP_LSH;
   1613    case ParseNodeKind::RshExpr:
   1614      return BINOP_RSH;
   1615    case ParseNodeKind::UrshExpr:
   1616      return BINOP_URSH;
   1617    case ParseNodeKind::LtExpr:
   1618      return BINOP_LT;
   1619    case ParseNodeKind::LeExpr:
   1620      return BINOP_LE;
   1621    case ParseNodeKind::GtExpr:
   1622      return BINOP_GT;
   1623    case ParseNodeKind::GeExpr:
   1624      return BINOP_GE;
   1625    case ParseNodeKind::EqExpr:
   1626      return BINOP_EQ;
   1627    case ParseNodeKind::NeExpr:
   1628      return BINOP_NE;
   1629    case ParseNodeKind::StrictEqExpr:
   1630      return BINOP_STRICTEQ;
   1631    case ParseNodeKind::StrictNeExpr:
   1632      return BINOP_STRICTNE;
   1633    case ParseNodeKind::AddExpr:
   1634      return BINOP_ADD;
   1635    case ParseNodeKind::SubExpr:
   1636      return BINOP_SUB;
   1637    case ParseNodeKind::MulExpr:
   1638      return BINOP_STAR;
   1639    case ParseNodeKind::DivExpr:
   1640      return BINOP_DIV;
   1641    case ParseNodeKind::ModExpr:
   1642      return BINOP_MOD;
   1643    case ParseNodeKind::PowExpr:
   1644      return BINOP_POW;
   1645    case ParseNodeKind::BitOrExpr:
   1646      return BINOP_BITOR;
   1647    case ParseNodeKind::BitXorExpr:
   1648      return BINOP_BITXOR;
   1649    case ParseNodeKind::BitAndExpr:
   1650      return BINOP_BITAND;
   1651    case ParseNodeKind::InExpr:
   1652    case ParseNodeKind::PrivateInExpr:
   1653      return BINOP_IN;
   1654    case ParseNodeKind::InstanceOfExpr:
   1655      return BINOP_INSTANCEOF;
   1656    case ParseNodeKind::CoalesceExpr:
   1657      return BINOP_COALESCE;
   1658    default:
   1659      return BINOP_ERR;
   1660  }
   1661 }
   1662 
   1663 bool ASTSerializer::statements(ListNode* stmtList, NodeVector& elts) {
   1664  MOZ_ASSERT(stmtList->isKind(ParseNodeKind::StatementList));
   1665 
   1666  if (!elts.reserve(stmtList->count())) {
   1667    return false;
   1668  }
   1669 
   1670  for (ParseNode* stmt : stmtList->contents()) {
   1671    MOZ_ASSERT(stmtList->pn_pos.encloses(stmt->pn_pos));
   1672 
   1673    RootedValue elt(cx);
   1674    if (!sourceElement(stmt, &elt)) {
   1675      return false;
   1676    }
   1677    elts.infallibleAppend(elt);
   1678  }
   1679 
   1680  return true;
   1681 }
   1682 
   1683 bool ASTSerializer::expressions(ListNode* exprList, NodeVector& elts) {
   1684  if (!elts.reserve(exprList->count())) {
   1685    return false;
   1686  }
   1687 
   1688  for (ParseNode* expr : exprList->contents()) {
   1689    MOZ_ASSERT(exprList->pn_pos.encloses(expr->pn_pos));
   1690 
   1691    RootedValue elt(cx);
   1692    if (!expression(expr, &elt)) {
   1693      return false;
   1694    }
   1695    elts.infallibleAppend(elt);
   1696  }
   1697 
   1698  return true;
   1699 }
   1700 
   1701 bool ASTSerializer::blockStatement(ListNode* node, MutableHandleValue dst) {
   1702  MOZ_ASSERT(node->isKind(ParseNodeKind::StatementList));
   1703 
   1704  NodeVector stmts(cx);
   1705  return statements(node, stmts) &&
   1706         builder.blockStatement(stmts, &node->pn_pos, dst);
   1707 }
   1708 
   1709 bool ASTSerializer::program(ListNode* node, MutableHandleValue dst) {
   1710 #ifdef DEBUG
   1711  {
   1712    const TokenStreamAnyChars& anyChars = parser->anyChars;
   1713    auto lineToken = anyChars.lineToken(node->pn_pos.begin);
   1714    MOZ_ASSERT(anyChars.lineNumber(lineToken) == lineno);
   1715  }
   1716 #endif
   1717 
   1718  NodeVector stmts(cx);
   1719  return statements(node, stmts) && builder.program(stmts, &node->pn_pos, dst);
   1720 }
   1721 
   1722 bool ASTSerializer::sourceElement(ParseNode* pn, MutableHandleValue dst) {
   1723  /* SpiderMonkey allows declarations even in pure statement contexts. */
   1724  return statement(pn, dst);
   1725 }
   1726 
   1727 bool ASTSerializer::declaration(ParseNode* pn, MutableHandleValue dst) {
   1728  MOZ_ASSERT(pn->isKind(ParseNodeKind::Function) ||
   1729             pn->isKind(ParseNodeKind::VarStmt) ||
   1730             pn->isKind(ParseNodeKind::LetDecl) ||
   1731 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   1732             pn->isKind(ParseNodeKind::UsingDecl) ||
   1733             pn->isKind(ParseNodeKind::AwaitUsingDecl) ||
   1734 #endif
   1735             pn->isKind(ParseNodeKind::ConstDecl));
   1736 
   1737  switch (pn->getKind()) {
   1738    case ParseNodeKind::Function:
   1739      return function(&pn->as<FunctionNode>(), AST_FUNC_DECL, dst);
   1740 
   1741    case ParseNodeKind::VarStmt:
   1742      return variableDeclaration(&pn->as<ListNode>(), false, dst);
   1743 
   1744    default:
   1745      MOZ_ASSERT(pn->isKind(ParseNodeKind::LetDecl) ||
   1746 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   1747                 pn->isKind(ParseNodeKind::UsingDecl) ||
   1748                 pn->isKind(ParseNodeKind::AwaitUsingDecl) ||
   1749 #endif
   1750                 pn->isKind(ParseNodeKind::ConstDecl));
   1751      return variableDeclaration(&pn->as<ListNode>(), true, dst);
   1752  }
   1753 }
   1754 
   1755 bool ASTSerializer::variableDeclaration(ListNode* declList, bool lexical,
   1756                                        MutableHandleValue dst) {
   1757  MOZ_ASSERT_IF(lexical, declList->isKind(ParseNodeKind::LetDecl) ||
   1758 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   1759                             declList->isKind(ParseNodeKind::UsingDecl) ||
   1760                             declList->isKind(ParseNodeKind::AwaitUsingDecl) ||
   1761 #endif
   1762                             declList->isKind(ParseNodeKind::ConstDecl));
   1763  MOZ_ASSERT_IF(!lexical, declList->isKind(ParseNodeKind::VarStmt));
   1764 
   1765  VarDeclKind kind = VARDECL_ERR;
   1766  // Treat both the toplevel const binding (secretly var-like) and the lexical
   1767  // const the same way
   1768  if (lexical) {
   1769    if (declList->isKind(ParseNodeKind::LetDecl)) {
   1770      kind = VARDECL_LET;
   1771    }
   1772 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   1773    else if (declList->isKind(ParseNodeKind::UsingDecl)) {
   1774      kind = VARDECL_USING;
   1775    } else if (declList->isKind(ParseNodeKind::AwaitUsingDecl)) {
   1776      kind = VARDECL_AWAIT_USING;
   1777    }
   1778 #endif
   1779    else {
   1780      kind = VARDECL_CONST;
   1781    }
   1782  } else {
   1783    kind =
   1784        declList->isKind(ParseNodeKind::VarStmt) ? VARDECL_VAR : VARDECL_CONST;
   1785  }
   1786 
   1787  NodeVector dtors(cx);
   1788  if (!dtors.reserve(declList->count())) {
   1789    return false;
   1790  }
   1791  for (ParseNode* decl : declList->contents()) {
   1792    RootedValue child(cx);
   1793    if (!variableDeclarator(decl, &child)) {
   1794      return false;
   1795    }
   1796    dtors.infallibleAppend(child);
   1797  }
   1798  return builder.variableDeclaration(dtors, kind, &declList->pn_pos, dst);
   1799 }
   1800 
   1801 bool ASTSerializer::variableDeclarator(ParseNode* pn, MutableHandleValue dst) {
   1802  ParseNode* patternNode;
   1803  ParseNode* initNode;
   1804 
   1805  if (pn->isKind(ParseNodeKind::Name)) {
   1806    patternNode = pn;
   1807    initNode = nullptr;
   1808  } else if (pn->isKind(ParseNodeKind::AssignExpr)) {
   1809    AssignmentNode* assignNode = &pn->as<AssignmentNode>();
   1810    patternNode = assignNode->left();
   1811    initNode = assignNode->right();
   1812    MOZ_ASSERT(pn->pn_pos.encloses(patternNode->pn_pos));
   1813    MOZ_ASSERT(pn->pn_pos.encloses(initNode->pn_pos));
   1814  } else {
   1815    /* This happens for a destructuring declarator in a for-in/of loop. */
   1816    patternNode = pn;
   1817    initNode = nullptr;
   1818  }
   1819 
   1820  RootedValue patternVal(cx), init(cx);
   1821  return pattern(patternNode, &patternVal) && optExpression(initNode, &init) &&
   1822         builder.variableDeclarator(patternVal, init, &pn->pn_pos, dst);
   1823 }
   1824 
   1825 bool ASTSerializer::importDeclaration(BinaryNode* importNode,
   1826                                      MutableHandleValue dst) {
   1827  MOZ_ASSERT(importNode->isKind(ParseNodeKind::ImportDecl));
   1828 
   1829  ListNode* specList = &importNode->left()->as<ListNode>();
   1830  MOZ_ASSERT(specList->isKind(ParseNodeKind::ImportSpecList));
   1831 
   1832  auto* moduleRequest = &importNode->right()->as<BinaryNode>();
   1833  MOZ_ASSERT(moduleRequest->isKind(ParseNodeKind::ImportModuleRequest));
   1834 
   1835  ParseNode* moduleSpecNode = moduleRequest->left();
   1836  MOZ_ASSERT(moduleSpecNode->isKind(ParseNodeKind::StringExpr));
   1837 
   1838  auto* attributeList = &moduleRequest->right()->as<ListNode>();
   1839  MOZ_ASSERT(attributeList->isKind(ParseNodeKind::ImportAttributeList));
   1840 
   1841  NodeVector elts(cx);
   1842  if (!elts.reserve(specList->count())) {
   1843    return false;
   1844  }
   1845 
   1846  for (ParseNode* item : specList->contents()) {
   1847    RootedValue elt(cx);
   1848    if (item->is<UnaryNode>()) {
   1849      auto* spec = &item->as<UnaryNode>();
   1850      if (!importNamespaceSpecifier(spec, &elt)) {
   1851        return false;
   1852      }
   1853    } else {
   1854      auto* spec = &item->as<BinaryNode>();
   1855      if (!importSpecifier(spec, &elt)) {
   1856        return false;
   1857      }
   1858    }
   1859    elts.infallibleAppend(elt);
   1860  }
   1861 
   1862  RootedValue moduleSpec(cx);
   1863  if (!literal(moduleSpecNode, &moduleSpec)) {
   1864    return false;
   1865  }
   1866 
   1867  NodeVector attributes(cx);
   1868  if (!importAttributes(attributeList, attributes)) {
   1869    return false;
   1870  }
   1871 
   1872  RootedValue moduleRequestValue(cx);
   1873  if (!builder.moduleRequest(moduleSpec, attributes, &importNode->pn_pos,
   1874                             &moduleRequestValue)) {
   1875    return false;
   1876  }
   1877 
   1878  return builder.importDeclaration(elts, moduleRequestValue,
   1879                                   &importNode->pn_pos, dst);
   1880 }
   1881 
   1882 bool ASTSerializer::importSpecifier(BinaryNode* importSpec,
   1883                                    MutableHandleValue dst) {
   1884  MOZ_ASSERT(importSpec->isKind(ParseNodeKind::ImportSpec));
   1885  NameNode* importNameNode = &importSpec->left()->as<NameNode>();
   1886  NameNode* bindingNameNode = &importSpec->right()->as<NameNode>();
   1887 
   1888  RootedValue importName(cx);
   1889  RootedValue bindingName(cx);
   1890  return identifierOrLiteral(importNameNode, &importName) &&
   1891         identifier(bindingNameNode, &bindingName) &&
   1892         builder.importSpecifier(importName, bindingName, &importSpec->pn_pos,
   1893                                 dst);
   1894 }
   1895 
   1896 bool ASTSerializer::importNamespaceSpecifier(UnaryNode* importSpec,
   1897                                             MutableHandleValue dst) {
   1898  MOZ_ASSERT(importSpec->isKind(ParseNodeKind::ImportNamespaceSpec));
   1899  NameNode* bindingNameNode = &importSpec->kid()->as<NameNode>();
   1900 
   1901  RootedValue bindingName(cx);
   1902  return identifier(bindingNameNode, &bindingName) &&
   1903         builder.importNamespaceSpecifier(bindingName, &importSpec->pn_pos,
   1904                                          dst);
   1905 }
   1906 
   1907 bool ASTSerializer::exportDeclaration(ParseNode* exportNode,
   1908                                      MutableHandleValue dst) {
   1909  MOZ_ASSERT(exportNode->isKind(ParseNodeKind::ExportStmt) ||
   1910             exportNode->isKind(ParseNodeKind::ExportFromStmt) ||
   1911             exportNode->isKind(ParseNodeKind::ExportDefaultStmt));
   1912  MOZ_ASSERT_IF(exportNode->isKind(ParseNodeKind::ExportStmt),
   1913                exportNode->is<UnaryNode>());
   1914  MOZ_ASSERT_IF(exportNode->isKind(ParseNodeKind::ExportFromStmt),
   1915                exportNode->as<BinaryNode>().right()->isKind(
   1916                    ParseNodeKind::ImportModuleRequest));
   1917 
   1918  RootedValue decl(cx, NullValue());
   1919  NodeVector elts(cx);
   1920 
   1921  ParseNode* kid = exportNode->isKind(ParseNodeKind::ExportStmt)
   1922                       ? exportNode->as<UnaryNode>().kid()
   1923                       : exportNode->as<BinaryNode>().left();
   1924  switch (ParseNodeKind kind = kid->getKind()) {
   1925    case ParseNodeKind::ExportSpecList: {
   1926      ListNode* specList = &kid->as<ListNode>();
   1927      if (!elts.reserve(specList->count())) {
   1928        return false;
   1929      }
   1930 
   1931      for (ParseNode* spec : specList->contents()) {
   1932        RootedValue elt(cx);
   1933        if (spec->isKind(ParseNodeKind::ExportSpec)) {
   1934          if (!exportSpecifier(&spec->as<BinaryNode>(), &elt)) {
   1935            return false;
   1936          }
   1937        } else if (spec->isKind(ParseNodeKind::ExportNamespaceSpec)) {
   1938          if (!exportNamespaceSpecifier(&spec->as<UnaryNode>(), &elt)) {
   1939            return false;
   1940          }
   1941        } else {
   1942          MOZ_ASSERT(spec->isKind(ParseNodeKind::ExportBatchSpecStmt));
   1943          if (!builder.exportBatchSpecifier(&exportNode->pn_pos, &elt)) {
   1944            return false;
   1945          }
   1946        }
   1947        elts.infallibleAppend(elt);
   1948      }
   1949      break;
   1950    }
   1951 
   1952    case ParseNodeKind::Function:
   1953      if (!function(&kid->as<FunctionNode>(), AST_FUNC_DECL, &decl)) {
   1954        return false;
   1955      }
   1956      break;
   1957 
   1958    case ParseNodeKind::ClassDecl:
   1959      if (!classDefinition(&kid->as<ClassNode>(), false, &decl)) {
   1960        return false;
   1961      }
   1962      break;
   1963 
   1964    case ParseNodeKind::VarStmt:
   1965    case ParseNodeKind::ConstDecl:
   1966    case ParseNodeKind::LetDecl:
   1967      if (!variableDeclaration(&kid->as<ListNode>(),
   1968                               kind != ParseNodeKind::VarStmt, &decl)) {
   1969        return false;
   1970      }
   1971      break;
   1972 
   1973    default:
   1974      if (!expression(kid, &decl)) {
   1975        return false;
   1976      }
   1977      break;
   1978  }
   1979 
   1980  RootedValue moduleSpec(cx, NullValue());
   1981  RootedValue moduleRequestValue(cx, NullValue());
   1982  if (exportNode->isKind(ParseNodeKind::ExportFromStmt)) {
   1983    ParseNode* moduleRequest = exportNode->as<BinaryNode>().right();
   1984    if (!literal(moduleRequest->as<BinaryNode>().left(), &moduleSpec)) {
   1985      return false;
   1986    }
   1987 
   1988    auto* attributeList =
   1989        &moduleRequest->as<BinaryNode>().right()->as<ListNode>();
   1990    MOZ_ASSERT(attributeList->isKind(ParseNodeKind::ImportAttributeList));
   1991 
   1992    NodeVector attributes(cx);
   1993    if (!importAttributes(attributeList, attributes)) {
   1994      return false;
   1995    }
   1996 
   1997    if (!builder.moduleRequest(moduleSpec, attributes, &exportNode->pn_pos,
   1998                               &moduleRequestValue)) {
   1999      return false;
   2000    }
   2001  }
   2002 
   2003  RootedValue isDefault(cx, BooleanValue(false));
   2004  if (exportNode->isKind(ParseNodeKind::ExportDefaultStmt)) {
   2005    isDefault.setBoolean(true);
   2006  }
   2007 
   2008  return builder.exportDeclaration(decl, elts, moduleRequestValue, isDefault,
   2009                                   &exportNode->pn_pos, dst);
   2010 }
   2011 
   2012 bool ASTSerializer::exportSpecifier(BinaryNode* exportSpec,
   2013                                    MutableHandleValue dst) {
   2014  MOZ_ASSERT(exportSpec->isKind(ParseNodeKind::ExportSpec));
   2015  NameNode* bindingNameNode = &exportSpec->left()->as<NameNode>();
   2016  NameNode* exportNameNode = &exportSpec->right()->as<NameNode>();
   2017 
   2018  RootedValue bindingName(cx);
   2019  RootedValue exportName(cx);
   2020  return identifierOrLiteral(bindingNameNode, &bindingName) &&
   2021         identifierOrLiteral(exportNameNode, &exportName) &&
   2022         builder.exportSpecifier(bindingName, exportName, &exportSpec->pn_pos,
   2023                                 dst);
   2024 }
   2025 
   2026 bool ASTSerializer::exportNamespaceSpecifier(UnaryNode* exportSpec,
   2027                                             MutableHandleValue dst) {
   2028  MOZ_ASSERT(exportSpec->isKind(ParseNodeKind::ExportNamespaceSpec));
   2029  NameNode* exportNameNode = &exportSpec->kid()->as<NameNode>();
   2030 
   2031  RootedValue exportName(cx);
   2032  return identifierOrLiteral(exportNameNode, &exportName) &&
   2033         builder.exportNamespaceSpecifier(exportName, &exportSpec->pn_pos, dst);
   2034 }
   2035 
   2036 bool ASTSerializer::importAttributes(ListNode* attributeList,
   2037                                     NodeVector& attributes) {
   2038  for (ParseNode* attributeItem : attributeList->contents()) {
   2039    BinaryNode* attributeNode = &attributeItem->as<BinaryNode>();
   2040    MOZ_ASSERT(attributeNode->isKind(ParseNodeKind::ImportAttribute));
   2041 
   2042    NameNode* keyNameNode = &attributeNode->left()->as<NameNode>();
   2043    NameNode* valueNameNode = &attributeNode->right()->as<NameNode>();
   2044 
   2045    RootedValue key(cx);
   2046    if (!identifierOrLiteral(keyNameNode, &key)) {
   2047      return false;
   2048    }
   2049 
   2050    RootedValue value(cx);
   2051    if (!literal(valueNameNode, &value)) {
   2052      return false;
   2053    }
   2054 
   2055    RootedValue attribute(cx);
   2056    if (!builder.importAttribute(key, value, &attributeNode->pn_pos,
   2057                                 &attribute)) {
   2058      return false;
   2059    }
   2060 
   2061    if (!attributes.append(attribute)) {
   2062      return false;
   2063    }
   2064  }
   2065 
   2066  return true;
   2067 }
   2068 
   2069 bool ASTSerializer::switchCase(CaseClause* caseClause, MutableHandleValue dst) {
   2070  MOZ_ASSERT_IF(
   2071      caseClause->caseExpression(),
   2072      caseClause->pn_pos.encloses(caseClause->caseExpression()->pn_pos));
   2073  MOZ_ASSERT(caseClause->pn_pos.encloses(caseClause->statementList()->pn_pos));
   2074 
   2075  NodeVector stmts(cx);
   2076  RootedValue expr(cx);
   2077  return optExpression(caseClause->caseExpression(), &expr) &&
   2078         statements(caseClause->statementList(), stmts) &&
   2079         builder.switchCase(expr, stmts, &caseClause->pn_pos, dst);
   2080 }
   2081 
   2082 bool ASTSerializer::switchStatement(SwitchStatement* switchStmt,
   2083                                    MutableHandleValue dst) {
   2084  MOZ_ASSERT(switchStmt->pn_pos.encloses(switchStmt->discriminant().pn_pos));
   2085  MOZ_ASSERT(
   2086      switchStmt->pn_pos.encloses(switchStmt->lexicalForCaseList().pn_pos));
   2087 
   2088  RootedValue disc(cx);
   2089  if (!expression(&switchStmt->discriminant(), &disc)) {
   2090    return false;
   2091  }
   2092 
   2093  ListNode* caseList =
   2094      &switchStmt->lexicalForCaseList().scopeBody()->as<ListNode>();
   2095 
   2096  NodeVector cases(cx);
   2097  if (!cases.reserve(caseList->count())) {
   2098    return false;
   2099  }
   2100 
   2101  for (ParseNode* item : caseList->contents()) {
   2102    CaseClause* caseClause = &item->as<CaseClause>();
   2103    RootedValue child(cx);
   2104    if (!switchCase(caseClause, &child)) {
   2105      return false;
   2106    }
   2107    cases.infallibleAppend(child);
   2108  }
   2109 
   2110  // `lexical` field is always true.
   2111  return builder.switchStatement(disc, cases, true, &switchStmt->pn_pos, dst);
   2112 }
   2113 
   2114 bool ASTSerializer::catchClause(BinaryNode* catchClause,
   2115                                MutableHandleValue dst) {
   2116  MOZ_ASSERT(catchClause->isKind(ParseNodeKind::Catch));
   2117 
   2118  ParseNode* varNode = catchClause->left();
   2119  MOZ_ASSERT_IF(varNode, catchClause->pn_pos.encloses(varNode->pn_pos));
   2120 
   2121  ParseNode* bodyNode = catchClause->right();
   2122  MOZ_ASSERT(catchClause->pn_pos.encloses(bodyNode->pn_pos));
   2123 
   2124  RootedValue var(cx), body(cx);
   2125  if (!optPattern(varNode, &var)) {
   2126    return false;
   2127  }
   2128 
   2129  return statement(bodyNode, &body) &&
   2130         builder.catchClause(var, body, &catchClause->pn_pos, dst);
   2131 }
   2132 
   2133 bool ASTSerializer::tryStatement(TryNode* tryNode, MutableHandleValue dst) {
   2134  ParseNode* bodyNode = tryNode->body();
   2135  MOZ_ASSERT(tryNode->pn_pos.encloses(bodyNode->pn_pos));
   2136 
   2137  LexicalScopeNode* catchNode = tryNode->catchScope();
   2138  MOZ_ASSERT_IF(catchNode, tryNode->pn_pos.encloses(catchNode->pn_pos));
   2139 
   2140  ParseNode* finallyNode = tryNode->finallyBlock();
   2141  MOZ_ASSERT_IF(finallyNode, tryNode->pn_pos.encloses(finallyNode->pn_pos));
   2142 
   2143  RootedValue body(cx);
   2144  if (!statement(bodyNode, &body)) {
   2145    return false;
   2146  }
   2147 
   2148  RootedValue handler(cx, NullValue());
   2149  if (catchNode) {
   2150    LexicalScopeNode* catchScope = &catchNode->as<LexicalScopeNode>();
   2151    if (!catchClause(&catchScope->scopeBody()->as<BinaryNode>(), &handler)) {
   2152      return false;
   2153    }
   2154  }
   2155 
   2156  RootedValue finally(cx);
   2157  return optStatement(finallyNode, &finally) &&
   2158         builder.tryStatement(body, handler, finally, &tryNode->pn_pos, dst);
   2159 }
   2160 
   2161 bool ASTSerializer::forInit(ParseNode* pn, MutableHandleValue dst) {
   2162  if (!pn) {
   2163    dst.setMagic(JS_SERIALIZE_NO_NODE);
   2164    return true;
   2165  }
   2166 
   2167  bool lexical = pn->isKind(ParseNodeKind::LetDecl) ||
   2168                 pn->isKind(ParseNodeKind::ConstDecl)
   2169 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   2170                 || pn->isKind(ParseNodeKind::UsingDecl) ||
   2171                 pn->isKind(ParseNodeKind::AwaitUsingDecl)
   2172 #endif
   2173      ;
   2174  return (lexical || pn->isKind(ParseNodeKind::VarStmt))
   2175             ? variableDeclaration(&pn->as<ListNode>(), lexical, dst)
   2176             : expression(pn, dst);
   2177 }
   2178 
   2179 bool ASTSerializer::forOf(ForNode* loop, ParseNode* iterExpr, HandleValue var,
   2180                          HandleValue stmt, MutableHandleValue dst) {
   2181  RootedValue expr(cx);
   2182 
   2183  return expression(iterExpr, &expr) &&
   2184         builder.forOfStatement(var, expr, stmt, &loop->pn_pos, dst);
   2185 }
   2186 
   2187 bool ASTSerializer::forIn(ForNode* loop, ParseNode* iterExpr, HandleValue var,
   2188                          HandleValue stmt, MutableHandleValue dst) {
   2189  RootedValue expr(cx);
   2190 
   2191  return expression(iterExpr, &expr) &&
   2192         builder.forInStatement(var, expr, stmt, &loop->pn_pos, dst);
   2193 }
   2194 
   2195 bool ASTSerializer::classDefinition(ClassNode* pn, bool expr,
   2196                                    MutableHandleValue dst) {
   2197  RootedValue className(cx, MagicValue(JS_SERIALIZE_NO_NODE));
   2198  RootedValue heritage(cx);
   2199  RootedValue classBody(cx);
   2200 #ifdef ENABLE_DECORATORS
   2201  NodeVector classDecorators(cx);
   2202  RootedValue classDecoratorsArray(cx);
   2203  TokenPos decoratorPos;
   2204  bool decoratorsParsed = true;
   2205  if (pn->decorators()) {
   2206    decoratorPos.begin = pn->decorators()->head()->pn_pos.begin;
   2207    decoratorPos.end = pn->decorators()->last()->pn_pos.end;
   2208    decoratorsParsed =
   2209        expressions(pn->decorators(), classDecorators) &&
   2210        builder.sequenceExpression(classDecorators, &decoratorPos,
   2211                                   &classDecoratorsArray);
   2212  } else {
   2213    classDecoratorsArray.setMagic(JS_SERIALIZE_NO_NODE);
   2214  }
   2215 #endif
   2216 
   2217  if (ClassNames* names = pn->names()) {
   2218    if (!identifier(names->innerBinding(), &className)) {
   2219      return false;
   2220    }
   2221  }
   2222 
   2223  return optExpression(pn->heritage(), &heritage) &&
   2224         statement(pn->memberList(), &classBody) &&
   2225 #ifdef ENABLE_DECORATORS
   2226         decoratorsParsed &&
   2227 #endif
   2228         builder.classDefinition(expr, className, heritage, classBody,
   2229 #ifdef ENABLE_DECORATORS
   2230                                 classDecoratorsArray,
   2231 #endif
   2232                                 &pn->pn_pos, dst);
   2233 }
   2234 
   2235 bool ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) {
   2236  AutoCheckRecursionLimit recursion(cx);
   2237  if (!recursion.check(cx)) {
   2238    return false;
   2239  }
   2240 
   2241  switch (pn->getKind()) {
   2242    case ParseNodeKind::Function:
   2243    case ParseNodeKind::VarStmt:
   2244      return declaration(pn, dst);
   2245 
   2246    case ParseNodeKind::LetDecl:
   2247    case ParseNodeKind::ConstDecl:
   2248 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   2249    case ParseNodeKind::UsingDecl:
   2250    case ParseNodeKind::AwaitUsingDecl:
   2251 #endif
   2252      return declaration(pn, dst);
   2253 
   2254    case ParseNodeKind::ImportDecl:
   2255      return importDeclaration(&pn->as<BinaryNode>(), dst);
   2256 
   2257    case ParseNodeKind::ExportStmt:
   2258    case ParseNodeKind::ExportDefaultStmt:
   2259    case ParseNodeKind::ExportFromStmt:
   2260      return exportDeclaration(pn, dst);
   2261 
   2262    case ParseNodeKind::EmptyStmt:
   2263      return builder.emptyStatement(&pn->pn_pos, dst);
   2264 
   2265    case ParseNodeKind::ExpressionStmt: {
   2266      RootedValue expr(cx);
   2267      return expression(pn->as<UnaryNode>().kid(), &expr) &&
   2268             builder.expressionStatement(expr, &pn->pn_pos, dst);
   2269    }
   2270 
   2271    case ParseNodeKind::LexicalScope:
   2272      pn = pn->as<LexicalScopeNode>().scopeBody();
   2273      if (!pn->isKind(ParseNodeKind::StatementList)) {
   2274        return statement(pn, dst);
   2275      }
   2276      [[fallthrough]];
   2277 
   2278    case ParseNodeKind::StatementList:
   2279      return blockStatement(&pn->as<ListNode>(), dst);
   2280 
   2281    case ParseNodeKind::IfStmt: {
   2282      TernaryNode* ifNode = &pn->as<TernaryNode>();
   2283 
   2284      ParseNode* testNode = ifNode->kid1();
   2285      MOZ_ASSERT(ifNode->pn_pos.encloses(testNode->pn_pos));
   2286 
   2287      ParseNode* consNode = ifNode->kid2();
   2288      MOZ_ASSERT(ifNode->pn_pos.encloses(consNode->pn_pos));
   2289 
   2290      ParseNode* altNode = ifNode->kid3();
   2291      MOZ_ASSERT_IF(altNode, ifNode->pn_pos.encloses(altNode->pn_pos));
   2292 
   2293      RootedValue test(cx), cons(cx), alt(cx);
   2294 
   2295      return expression(testNode, &test) && statement(consNode, &cons) &&
   2296             optStatement(altNode, &alt) &&
   2297             builder.ifStatement(test, cons, alt, &ifNode->pn_pos, dst);
   2298    }
   2299 
   2300    case ParseNodeKind::SwitchStmt:
   2301      return switchStatement(&pn->as<SwitchStatement>(), dst);
   2302 
   2303    case ParseNodeKind::TryStmt:
   2304      return tryStatement(&pn->as<TryNode>(), dst);
   2305 
   2306    case ParseNodeKind::WithStmt:
   2307    case ParseNodeKind::WhileStmt: {
   2308      BinaryNode* node = &pn->as<BinaryNode>();
   2309 
   2310      ParseNode* exprNode = node->left();
   2311      MOZ_ASSERT(node->pn_pos.encloses(exprNode->pn_pos));
   2312 
   2313      ParseNode* stmtNode = node->right();
   2314      MOZ_ASSERT(node->pn_pos.encloses(stmtNode->pn_pos));
   2315 
   2316      RootedValue expr(cx), stmt(cx);
   2317 
   2318      return expression(exprNode, &expr) && statement(stmtNode, &stmt) &&
   2319             (node->isKind(ParseNodeKind::WithStmt)
   2320                  ? builder.withStatement(expr, stmt, &node->pn_pos, dst)
   2321                  : builder.whileStatement(expr, stmt, &node->pn_pos, dst));
   2322    }
   2323 
   2324    case ParseNodeKind::DoWhileStmt: {
   2325      BinaryNode* node = &pn->as<BinaryNode>();
   2326 
   2327      ParseNode* stmtNode = node->left();
   2328      MOZ_ASSERT(node->pn_pos.encloses(stmtNode->pn_pos));
   2329 
   2330      ParseNode* testNode = node->right();
   2331      MOZ_ASSERT(node->pn_pos.encloses(testNode->pn_pos));
   2332 
   2333      RootedValue stmt(cx), test(cx);
   2334 
   2335      return statement(stmtNode, &stmt) && expression(testNode, &test) &&
   2336             builder.doWhileStatement(stmt, test, &node->pn_pos, dst);
   2337    }
   2338 
   2339    case ParseNodeKind::ForStmt: {
   2340      ForNode* forNode = &pn->as<ForNode>();
   2341 
   2342      TernaryNode* head = forNode->head();
   2343      MOZ_ASSERT(forNode->pn_pos.encloses(head->pn_pos));
   2344 
   2345      ParseNode* stmtNode = forNode->right();
   2346      MOZ_ASSERT(forNode->pn_pos.encloses(stmtNode->pn_pos));
   2347 
   2348      ParseNode* initNode = head->kid1();
   2349      MOZ_ASSERT_IF(initNode, head->pn_pos.encloses(initNode->pn_pos));
   2350 
   2351      ParseNode* maybeTest = head->kid2();
   2352      MOZ_ASSERT_IF(maybeTest, head->pn_pos.encloses(maybeTest->pn_pos));
   2353 
   2354      ParseNode* updateOrIter = head->kid3();
   2355      MOZ_ASSERT_IF(updateOrIter, head->pn_pos.encloses(updateOrIter->pn_pos));
   2356 
   2357      RootedValue stmt(cx);
   2358      if (!statement(stmtNode, &stmt)) {
   2359        return false;
   2360      }
   2361 
   2362      if (head->isKind(ParseNodeKind::ForIn) ||
   2363          head->isKind(ParseNodeKind::ForOf)) {
   2364        RootedValue var(cx);
   2365        if (initNode->is<LexicalScopeNode>()) {
   2366          LexicalScopeNode* scopeNode = &initNode->as<LexicalScopeNode>();
   2367          if (!variableDeclaration(&scopeNode->scopeBody()->as<ListNode>(),
   2368                                   true, &var)) {
   2369            return false;
   2370          }
   2371        } else if (!initNode->isKind(ParseNodeKind::VarStmt) &&
   2372                   !initNode->isKind(ParseNodeKind::LetDecl) &&
   2373 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   2374                   !initNode->isKind(ParseNodeKind::UsingDecl) &&
   2375                   !initNode->isKind(ParseNodeKind::AwaitUsingDecl) &&
   2376 #endif
   2377                   !initNode->isKind(ParseNodeKind::ConstDecl)) {
   2378          if (!pattern(initNode, &var)) {
   2379            return false;
   2380          }
   2381        } else {
   2382          if (!variableDeclaration(
   2383                  &initNode->as<ListNode>(),
   2384                  initNode->isKind(ParseNodeKind::LetDecl) ||
   2385 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   2386                      initNode->isKind(ParseNodeKind::UsingDecl) ||
   2387                      initNode->isKind(ParseNodeKind::AwaitUsingDecl) ||
   2388 #endif
   2389                      initNode->isKind(ParseNodeKind::ConstDecl),
   2390                  &var)) {
   2391            return false;
   2392          }
   2393        }
   2394        if (head->isKind(ParseNodeKind::ForIn)) {
   2395          return forIn(forNode, updateOrIter, var, stmt, dst);
   2396        }
   2397        return forOf(forNode, updateOrIter, var, stmt, dst);
   2398      }
   2399 
   2400      RootedValue init(cx), test(cx), update(cx);
   2401 
   2402      return forInit(initNode, &init) && optExpression(maybeTest, &test) &&
   2403             optExpression(updateOrIter, &update) &&
   2404             builder.forStatement(init, test, update, stmt, &forNode->pn_pos,
   2405                                  dst);
   2406    }
   2407 
   2408    case ParseNodeKind::BreakStmt:
   2409    case ParseNodeKind::ContinueStmt: {
   2410      LoopControlStatement* node = &pn->as<LoopControlStatement>();
   2411      RootedValue label(cx);
   2412      Rooted<JSAtom*> pnAtom(cx);
   2413      if (node->label()) {
   2414        pnAtom.set(parser->liftParserAtomToJSAtom(node->label()));
   2415        if (!pnAtom) {
   2416          return false;
   2417        }
   2418      }
   2419      return optIdentifier(pnAtom, nullptr, &label) &&
   2420             (node->isKind(ParseNodeKind::BreakStmt)
   2421                  ? builder.breakStatement(label, &node->pn_pos, dst)
   2422                  : builder.continueStatement(label, &node->pn_pos, dst));
   2423    }
   2424 
   2425    case ParseNodeKind::LabelStmt: {
   2426      LabeledStatement* labelNode = &pn->as<LabeledStatement>();
   2427      ParseNode* stmtNode = labelNode->statement();
   2428      MOZ_ASSERT(labelNode->pn_pos.encloses(stmtNode->pn_pos));
   2429 
   2430      RootedValue label(cx), stmt(cx);
   2431      Rooted<JSAtom*> pnAtom(
   2432          cx, parser->liftParserAtomToJSAtom(labelNode->label()));
   2433      if (!pnAtom.get()) {
   2434        return false;
   2435      }
   2436      return identifier(pnAtom, nullptr, &label) &&
   2437             statement(stmtNode, &stmt) &&
   2438             builder.labeledStatement(label, stmt, &labelNode->pn_pos, dst);
   2439    }
   2440 
   2441    case ParseNodeKind::ThrowStmt: {
   2442      UnaryNode* throwNode = &pn->as<UnaryNode>();
   2443      ParseNode* operand = throwNode->kid();
   2444      MOZ_ASSERT(throwNode->pn_pos.encloses(operand->pn_pos));
   2445 
   2446      RootedValue arg(cx);
   2447 
   2448      return expression(operand, &arg) &&
   2449             builder.throwStatement(arg, &throwNode->pn_pos, dst);
   2450    }
   2451 
   2452    case ParseNodeKind::ReturnStmt: {
   2453      UnaryNode* returnNode = &pn->as<UnaryNode>();
   2454      ParseNode* operand = returnNode->kid();
   2455      MOZ_ASSERT_IF(operand, returnNode->pn_pos.encloses(operand->pn_pos));
   2456 
   2457      RootedValue arg(cx);
   2458 
   2459      return optExpression(operand, &arg) &&
   2460             builder.returnStatement(arg, &returnNode->pn_pos, dst);
   2461    }
   2462 
   2463    case ParseNodeKind::DebuggerStmt:
   2464      return builder.debuggerStatement(&pn->pn_pos, dst);
   2465 
   2466    case ParseNodeKind::ClassDecl:
   2467      return classDefinition(&pn->as<ClassNode>(), false, dst);
   2468 
   2469    case ParseNodeKind::ClassMemberList: {
   2470      ListNode* memberList = &pn->as<ListNode>();
   2471      NodeVector members(cx);
   2472      if (!members.reserve(memberList->count())) {
   2473        return false;
   2474      }
   2475 
   2476      for (ParseNode* item : memberList->contents()) {
   2477        if (item->is<LexicalScopeNode>()) {
   2478          item = item->as<LexicalScopeNode>().scopeBody();
   2479        }
   2480        if (item->is<ClassField>()) {
   2481          ClassField* field = &item->as<ClassField>();
   2482          MOZ_ASSERT(memberList->pn_pos.encloses(field->pn_pos));
   2483 
   2484          RootedValue prop(cx);
   2485          if (!classField(field, &prop)) {
   2486            return false;
   2487          }
   2488          members.infallibleAppend(prop);
   2489        } else if (item->is<StaticClassBlock>()) {
   2490          // StaticClassBlock* block = &item->as<StaticClassBlock>();
   2491          StaticClassBlock* scb = &item->as<StaticClassBlock>();
   2492          MOZ_ASSERT(memberList->pn_pos.encloses(scb->pn_pos));
   2493          RootedValue prop(cx);
   2494          if (!staticClassBlock(scb, &prop)) {
   2495            return false;
   2496          }
   2497          members.infallibleAppend(prop);
   2498        } else if (!item->isKind(ParseNodeKind::DefaultConstructor)) {
   2499          ClassMethod* method = &item->as<ClassMethod>();
   2500          MOZ_ASSERT(memberList->pn_pos.encloses(method->pn_pos));
   2501 
   2502          RootedValue prop(cx);
   2503          if (!classMethod(method, &prop)) {
   2504            return false;
   2505          }
   2506          members.infallibleAppend(prop);
   2507        }
   2508      }
   2509 
   2510      return builder.classMembers(members, dst);
   2511    }
   2512 
   2513    default:
   2514      LOCAL_NOT_REACHED("unexpected statement type");
   2515  }
   2516 }
   2517 
   2518 bool ASTSerializer::classMethod(ClassMethod* classMethod,
   2519                                MutableHandleValue dst) {
   2520  PropKind kind;
   2521  switch (classMethod->accessorType()) {
   2522    case AccessorType::None:
   2523      kind = PROP_INIT;
   2524      break;
   2525 
   2526    case AccessorType::Getter:
   2527      kind = PROP_GETTER;
   2528      break;
   2529 
   2530    case AccessorType::Setter:
   2531      kind = PROP_SETTER;
   2532      break;
   2533 
   2534    default:
   2535      LOCAL_NOT_REACHED("unexpected object-literal property");
   2536  }
   2537 #ifdef ENABLE_DECORATORS
   2538  NodeVector methodDecorators(cx);
   2539  RootedValue methodDecoratorsArray(cx);
   2540  TokenPos decoratorPos;
   2541  bool decoratorsParsed = true;
   2542  if (classMethod->decorators()) {
   2543    decoratorPos.begin = classMethod->decorators()->head()->pn_pos.begin;
   2544    decoratorPos.end = classMethod->decorators()->last()->pn_pos.end;
   2545    decoratorsParsed =
   2546        expressions(classMethod->decorators(), methodDecorators) &&
   2547        builder.sequenceExpression(methodDecorators, &decoratorPos,
   2548                                   &methodDecoratorsArray);
   2549  } else {
   2550    methodDecoratorsArray.setMagic(JS_SERIALIZE_NO_NODE);
   2551  }
   2552 #endif
   2553 
   2554  RootedValue key(cx), val(cx);
   2555  bool isStatic = classMethod->isStatic();
   2556  return propertyName(&classMethod->name(), &key) &&
   2557         expression(&classMethod->method(), &val) &&
   2558 #ifdef ENABLE_DECORATORS
   2559         decoratorsParsed &&
   2560 #endif
   2561         builder.classMethod(key, val,
   2562 #ifdef ENABLE_DECORATORS
   2563                             methodDecoratorsArray,
   2564 #endif
   2565                             kind, isStatic, &classMethod->pn_pos, dst);
   2566 }
   2567 
   2568 bool ASTSerializer::classField(ClassField* classField, MutableHandleValue dst) {
   2569  RootedValue key(cx), val(cx);
   2570  // Dig through the lambda and get to the actual expression
   2571  ParseNode* value = classField->initializer()
   2572                         ->body()
   2573                         ->body()
   2574                         ->scopeBody()
   2575                         ->as<ListNode>()
   2576                         .head()
   2577                         ->as<UnaryNode>()
   2578                         .kid()
   2579                         ->as<BinaryNode>()
   2580                         .right();
   2581 #ifdef ENABLE_DECORATORS
   2582  NodeVector fieldDecorators(cx);
   2583  RootedValue fieldDecoratorsArray(cx);
   2584  TokenPos decoratorPos;
   2585  bool decoratorsParsed = true;
   2586  if (classField->decorators()) {
   2587    decoratorPos.begin = classField->decorators()->head()->pn_pos.begin;
   2588    decoratorPos.end = classField->decorators()->last()->pn_pos.end;
   2589    decoratorsParsed =
   2590        expressions(classField->decorators(), fieldDecorators) &&
   2591        builder.sequenceExpression(fieldDecorators, &decoratorPos,
   2592                                   &fieldDecoratorsArray);
   2593  } else {
   2594    fieldDecoratorsArray.setMagic(JS_SERIALIZE_NO_NODE);
   2595  }
   2596 #endif
   2597  // RawUndefinedExpr is the node we use for "there is no initializer". If one
   2598  // writes, literally, `x = undefined;`, it will not be a RawUndefinedExpr
   2599  // node, but rather a variable reference.
   2600  // Behavior for "there is no initializer" should be { ..., "init": null }
   2601  if (value->getKind() != ParseNodeKind::RawUndefinedExpr) {
   2602    if (!expression(value, &val)) {
   2603      return false;
   2604    }
   2605  } else {
   2606    val.setNull();
   2607  }
   2608  return propertyName(&classField->name(), &key) &&
   2609 #ifdef ENABLE_DECORATORS
   2610         decoratorsParsed &&
   2611 #endif
   2612         builder.classField(key, val,
   2613 #ifdef ENABLE_DECORATORS
   2614                            fieldDecoratorsArray,
   2615 #endif
   2616                            &classField->pn_pos, dst);
   2617 }
   2618 
   2619 bool ASTSerializer::staticClassBlock(StaticClassBlock* staticClassBlock,
   2620                                     MutableHandleValue dst) {
   2621  FunctionNode* fun = staticClassBlock->function();
   2622 
   2623  NodeVector args(cx);
   2624  NodeVector defaults(cx);
   2625 
   2626  RootedValue body(cx), rest(cx);
   2627  rest.setNull();
   2628  return functionArgsAndBody(fun->body(), args, defaults, false, false, &body,
   2629                             &rest) &&
   2630         builder.staticClassBlock(body, &staticClassBlock->pn_pos, dst);
   2631 }
   2632 
   2633 bool ASTSerializer::leftAssociate(ListNode* node, MutableHandleValue dst) {
   2634  MOZ_ASSERT(!node->empty());
   2635 
   2636  ParseNodeKind pnk = node->getKind();
   2637  bool lor = pnk == ParseNodeKind::OrExpr;
   2638  bool coalesce = pnk == ParseNodeKind::CoalesceExpr;
   2639  bool logop = lor || coalesce || pnk == ParseNodeKind::AndExpr;
   2640 
   2641  ParseNode* head = node->head();
   2642  RootedValue left(cx);
   2643  if (!expression(head, &left)) {
   2644    return false;
   2645  }
   2646  for (ParseNode* next : node->contentsFrom(head->pn_next)) {
   2647    RootedValue right(cx);
   2648    if (!expression(next, &right)) {
   2649      return false;
   2650    }
   2651 
   2652    TokenPos subpos(node->pn_pos.begin, next->pn_pos.end);
   2653 
   2654    if (logop) {
   2655      if (!builder.logicalExpression(pnk, left, right, &subpos, &left)) {
   2656        return false;
   2657      }
   2658    } else {
   2659      BinaryOperator op = binop(node->getKind());
   2660      LOCAL_ASSERT(op > BINOP_ERR && op < BINOP_LIMIT);
   2661 
   2662      if (!builder.binaryExpression(op, left, right, &subpos, &left)) {
   2663        return false;
   2664      }
   2665    }
   2666  }
   2667 
   2668  dst.set(left);
   2669  return true;
   2670 }
   2671 
   2672 bool ASTSerializer::rightAssociate(ListNode* node, MutableHandleValue dst) {
   2673  MOZ_ASSERT(!node->empty());
   2674 
   2675  // First, we need to reverse the list, so that we can traverse it in the right
   2676  // order. It's OK to destructively reverse the list, because there are no
   2677  // other consumers.
   2678 
   2679  ParseNode* head = node->head();
   2680  ParseNode* prev = nullptr;
   2681  ParseNode* current = head;
   2682  ParseNode* next;
   2683  while (current != nullptr) {
   2684    next = current->pn_next;
   2685    current->pn_next = prev;
   2686    prev = current;
   2687    current = next;
   2688  }
   2689 
   2690  head = prev;
   2691 
   2692  RootedValue right(cx);
   2693  if (!expression(head, &right)) {
   2694    return false;
   2695  }
   2696  for (ParseNode* next = head->pn_next; next; next = next->pn_next) {
   2697    RootedValue left(cx);
   2698    if (!expression(next, &left)) {
   2699      return false;
   2700    }
   2701 
   2702    TokenPos subpos(node->pn_pos.begin, next->pn_pos.end);
   2703 
   2704    BinaryOperator op = binop(node->getKind());
   2705    LOCAL_ASSERT(op > BINOP_ERR && op < BINOP_LIMIT);
   2706 
   2707    if (!builder.binaryExpression(op, left, right, &subpos, &right)) {
   2708      return false;
   2709    }
   2710  }
   2711 
   2712  dst.set(right);
   2713  return true;
   2714 }
   2715 
   2716 bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
   2717  AutoCheckRecursionLimit recursion(cx);
   2718  if (!recursion.check(cx)) {
   2719    return false;
   2720  }
   2721 
   2722  switch (pn->getKind()) {
   2723    case ParseNodeKind::Function: {
   2724      FunctionNode* funNode = &pn->as<FunctionNode>();
   2725      ASTType type =
   2726          funNode->funbox()->isArrow() ? AST_ARROW_EXPR : AST_FUNC_EXPR;
   2727      return function(funNode, type, dst);
   2728    }
   2729 
   2730    case ParseNodeKind::CommaExpr: {
   2731      NodeVector exprs(cx);
   2732      return expressions(&pn->as<ListNode>(), exprs) &&
   2733             builder.sequenceExpression(exprs, &pn->pn_pos, dst);
   2734    }
   2735 
   2736    case ParseNodeKind::ConditionalExpr: {
   2737      ConditionalExpression* condNode = &pn->as<ConditionalExpression>();
   2738      ParseNode* testNode = condNode->kid1();
   2739      ParseNode* consNode = condNode->kid2();
   2740      ParseNode* altNode = condNode->kid3();
   2741      MOZ_ASSERT(condNode->pn_pos.encloses(testNode->pn_pos));
   2742      MOZ_ASSERT(condNode->pn_pos.encloses(consNode->pn_pos));
   2743      MOZ_ASSERT(condNode->pn_pos.encloses(altNode->pn_pos));
   2744 
   2745      RootedValue test(cx), cons(cx), alt(cx);
   2746 
   2747      return expression(testNode, &test) && expression(consNode, &cons) &&
   2748             expression(altNode, &alt) &&
   2749             builder.conditionalExpression(test, cons, alt, &condNode->pn_pos,
   2750                                           dst);
   2751    }
   2752 
   2753    case ParseNodeKind::CoalesceExpr:
   2754    case ParseNodeKind::OrExpr:
   2755    case ParseNodeKind::AndExpr:
   2756      return leftAssociate(&pn->as<ListNode>(), dst);
   2757 
   2758    case ParseNodeKind::PreIncrementExpr:
   2759    case ParseNodeKind::PreDecrementExpr: {
   2760      UnaryNode* incDec = &pn->as<UnaryNode>();
   2761      ParseNode* operand = incDec->kid();
   2762      MOZ_ASSERT(incDec->pn_pos.encloses(operand->pn_pos));
   2763 
   2764      bool inc = incDec->isKind(ParseNodeKind::PreIncrementExpr);
   2765      RootedValue expr(cx);
   2766      return expression(operand, &expr) &&
   2767             builder.updateExpression(expr, inc, true, &incDec->pn_pos, dst);
   2768    }
   2769 
   2770    case ParseNodeKind::PostIncrementExpr:
   2771    case ParseNodeKind::PostDecrementExpr: {
   2772      UnaryNode* incDec = &pn->as<UnaryNode>();
   2773      ParseNode* operand = incDec->kid();
   2774      MOZ_ASSERT(incDec->pn_pos.encloses(operand->pn_pos));
   2775 
   2776      bool inc = incDec->isKind(ParseNodeKind::PostIncrementExpr);
   2777      RootedValue expr(cx);
   2778      return expression(operand, &expr) &&
   2779             builder.updateExpression(expr, inc, false, &incDec->pn_pos, dst);
   2780    }
   2781 
   2782    case ParseNodeKind::AssignExpr:
   2783    case ParseNodeKind::AddAssignExpr:
   2784    case ParseNodeKind::SubAssignExpr:
   2785    case ParseNodeKind::CoalesceAssignExpr:
   2786    case ParseNodeKind::OrAssignExpr:
   2787    case ParseNodeKind::AndAssignExpr:
   2788    case ParseNodeKind::BitOrAssignExpr:
   2789    case ParseNodeKind::BitXorAssignExpr:
   2790    case ParseNodeKind::BitAndAssignExpr:
   2791    case ParseNodeKind::LshAssignExpr:
   2792    case ParseNodeKind::RshAssignExpr:
   2793    case ParseNodeKind::UrshAssignExpr:
   2794    case ParseNodeKind::MulAssignExpr:
   2795    case ParseNodeKind::DivAssignExpr:
   2796    case ParseNodeKind::ModAssignExpr:
   2797    case ParseNodeKind::PowAssignExpr: {
   2798      AssignmentNode* assignNode = &pn->as<AssignmentNode>();
   2799      ParseNode* lhsNode = assignNode->left();
   2800      ParseNode* rhsNode = assignNode->right();
   2801      MOZ_ASSERT(assignNode->pn_pos.encloses(lhsNode->pn_pos));
   2802      MOZ_ASSERT(assignNode->pn_pos.encloses(rhsNode->pn_pos));
   2803 
   2804      AssignmentOperator op = aop(assignNode->getKind());
   2805      LOCAL_ASSERT(op > AOP_ERR && op < AOP_LIMIT);
   2806 
   2807      RootedValue lhs(cx), rhs(cx);
   2808      return pattern(lhsNode, &lhs) && expression(rhsNode, &rhs) &&
   2809             builder.assignmentExpression(op, lhs, rhs, &assignNode->pn_pos,
   2810                                          dst);
   2811    }
   2812 
   2813    case ParseNodeKind::AddExpr:
   2814    case ParseNodeKind::SubExpr:
   2815    case ParseNodeKind::StrictEqExpr:
   2816    case ParseNodeKind::EqExpr:
   2817    case ParseNodeKind::StrictNeExpr:
   2818    case ParseNodeKind::NeExpr:
   2819    case ParseNodeKind::LtExpr:
   2820    case ParseNodeKind::LeExpr:
   2821    case ParseNodeKind::GtExpr:
   2822    case ParseNodeKind::GeExpr:
   2823    case ParseNodeKind::LshExpr:
   2824    case ParseNodeKind::RshExpr:
   2825    case ParseNodeKind::UrshExpr:
   2826    case ParseNodeKind::MulExpr:
   2827    case ParseNodeKind::DivExpr:
   2828    case ParseNodeKind::ModExpr:
   2829    case ParseNodeKind::BitOrExpr:
   2830    case ParseNodeKind::BitXorExpr:
   2831    case ParseNodeKind::BitAndExpr:
   2832    case ParseNodeKind::InExpr:
   2833    case ParseNodeKind::PrivateInExpr:
   2834    case ParseNodeKind::InstanceOfExpr:
   2835      return leftAssociate(&pn->as<ListNode>(), dst);
   2836 
   2837    case ParseNodeKind::PowExpr:
   2838      return rightAssociate(&pn->as<ListNode>(), dst);
   2839 
   2840    case ParseNodeKind::DeleteNameExpr:
   2841    case ParseNodeKind::DeletePropExpr:
   2842    case ParseNodeKind::DeleteElemExpr:
   2843    case ParseNodeKind::DeleteExpr:
   2844    case ParseNodeKind::TypeOfNameExpr:
   2845    case ParseNodeKind::TypeOfExpr:
   2846    case ParseNodeKind::VoidExpr:
   2847    case ParseNodeKind::NotExpr:
   2848    case ParseNodeKind::BitNotExpr:
   2849    case ParseNodeKind::PosExpr:
   2850    case ParseNodeKind::AwaitExpr:
   2851    case ParseNodeKind::NegExpr: {
   2852      UnaryNode* unaryNode = &pn->as<UnaryNode>();
   2853      ParseNode* operand = unaryNode->kid();
   2854      MOZ_ASSERT(unaryNode->pn_pos.encloses(operand->pn_pos));
   2855 
   2856      UnaryOperator op = unop(unaryNode->getKind());
   2857      LOCAL_ASSERT(op > UNOP_ERR && op < UNOP_LIMIT);
   2858 
   2859      RootedValue expr(cx);
   2860      return expression(operand, &expr) &&
   2861             builder.unaryExpression(op, expr, &unaryNode->pn_pos, dst);
   2862    }
   2863 
   2864    case ParseNodeKind::DeleteOptionalChainExpr: {
   2865      RootedValue expr(cx);
   2866      return expression(pn->as<UnaryNode>().kid(), &expr) &&
   2867             builder.deleteOptionalExpression(expr, &pn->pn_pos, dst);
   2868    }
   2869 
   2870    case ParseNodeKind::OptionalChain: {
   2871      RootedValue expr(cx);
   2872      return expression(pn->as<UnaryNode>().kid(), &expr) &&
   2873             builder.optionalExpression(expr, &pn->pn_pos, dst);
   2874    }
   2875 
   2876    case ParseNodeKind::NewExpr:
   2877    case ParseNodeKind::TaggedTemplateExpr:
   2878    case ParseNodeKind::CallExpr:
   2879    case ParseNodeKind::OptionalCallExpr:
   2880    case ParseNodeKind::SuperCallExpr: {
   2881      BinaryNode* node = &pn->as<BinaryNode>();
   2882      ParseNode* calleeNode = node->left();
   2883      ListNode* argsList = &node->right()->as<ListNode>();
   2884      MOZ_ASSERT(node->pn_pos.encloses(calleeNode->pn_pos));
   2885 
   2886      RootedValue callee(cx);
   2887      if (node->isKind(ParseNodeKind::SuperCallExpr)) {
   2888        MOZ_ASSERT(calleeNode->isKind(ParseNodeKind::SuperBase));
   2889        if (!builder.super(&calleeNode->pn_pos, &callee)) {
   2890          return false;
   2891        }
   2892      } else {
   2893        if (!expression(calleeNode, &callee)) {
   2894          return false;
   2895        }
   2896      }
   2897 
   2898      NodeVector args(cx);
   2899      if (!args.reserve(argsList->count())) {
   2900        return false;
   2901      }
   2902 
   2903      for (ParseNode* argNode : argsList->contents()) {
   2904        MOZ_ASSERT(node->pn_pos.encloses(argNode->pn_pos));
   2905 
   2906        RootedValue arg(cx);
   2907        if (!expression(argNode, &arg)) {
   2908          return false;
   2909        }
   2910        args.infallibleAppend(arg);
   2911      }
   2912 
   2913      if (node->getKind() == ParseNodeKind::TaggedTemplateExpr) {
   2914        return builder.taggedTemplate(callee, args, &node->pn_pos, dst);
   2915      }
   2916 
   2917      bool isOptional = node->isKind(ParseNodeKind::OptionalCallExpr);
   2918 
   2919      // SUPERCALL is Call(super, args)
   2920      return node->isKind(ParseNodeKind::NewExpr)
   2921                 ? builder.newExpression(callee, args, &node->pn_pos, dst)
   2922                 : builder.callExpression(callee, args, &node->pn_pos, dst,
   2923                                          isOptional);
   2924    }
   2925 
   2926    case ParseNodeKind::DotExpr:
   2927    case ParseNodeKind::OptionalDotExpr:
   2928    case ParseNodeKind::ArgumentsLength: {
   2929      PropertyAccessBase* prop = &pn->as<PropertyAccessBase>();
   2930      MOZ_ASSERT(prop->pn_pos.encloses(prop->expression().pn_pos));
   2931 
   2932      bool isSuper =
   2933          prop->is<PropertyAccess>() && prop->as<PropertyAccess>().isSuper();
   2934 
   2935      RootedValue expr(cx);
   2936      RootedValue propname(cx);
   2937      Rooted<JSAtom*> pnAtom(
   2938          cx, parser->liftParserAtomToJSAtom(prop->key().atom()));
   2939      if (!pnAtom.get()) {
   2940        return false;
   2941      }
   2942 
   2943      if (isSuper) {
   2944        if (!builder.super(&prop->expression().pn_pos, &expr)) {
   2945          return false;
   2946        }
   2947      } else {
   2948        if (!expression(&prop->expression(), &expr)) {
   2949          return false;
   2950        }
   2951      }
   2952 
   2953      bool isOptional = prop->isKind(ParseNodeKind::OptionalDotExpr);
   2954 
   2955      return identifier(pnAtom, nullptr, &propname) &&
   2956             builder.memberExpression(false, expr, propname, &prop->pn_pos, dst,
   2957                                      isOptional);
   2958    }
   2959 
   2960    case ParseNodeKind::ElemExpr:
   2961    case ParseNodeKind::OptionalElemExpr: {
   2962      PropertyByValueBase* elem = &pn->as<PropertyByValueBase>();
   2963      MOZ_ASSERT(elem->pn_pos.encloses(elem->expression().pn_pos));
   2964      MOZ_ASSERT(elem->pn_pos.encloses(elem->key().pn_pos));
   2965 
   2966      bool isSuper =
   2967          elem->is<PropertyByValue>() && elem->as<PropertyByValue>().isSuper();
   2968 
   2969      RootedValue expr(cx), key(cx);
   2970 
   2971      if (isSuper) {
   2972        if (!builder.super(&elem->expression().pn_pos, &expr)) {
   2973          return false;
   2974        }
   2975      } else {
   2976        if (!expression(&elem->expression(), &expr)) {
   2977          return false;
   2978        }
   2979      }
   2980 
   2981      bool isOptional = elem->isKind(ParseNodeKind::OptionalElemExpr);
   2982 
   2983      return expression(&elem->key(), &key) &&
   2984             builder.memberExpression(true, expr, key, &elem->pn_pos, dst,
   2985                                      isOptional);
   2986    }
   2987 
   2988    case ParseNodeKind::PrivateMemberExpr:
   2989    case ParseNodeKind::OptionalPrivateMemberExpr: {
   2990      PrivateMemberAccessBase* privateExpr = &pn->as<PrivateMemberAccessBase>();
   2991      MOZ_ASSERT(
   2992          privateExpr->pn_pos.encloses(privateExpr->expression().pn_pos));
   2993      MOZ_ASSERT(
   2994          privateExpr->pn_pos.encloses(privateExpr->privateName().pn_pos));
   2995 
   2996      RootedValue expr(cx), key(cx);
   2997 
   2998      if (!expression(&privateExpr->expression(), &expr)) {
   2999        return false;
   3000      }
   3001 
   3002      bool isOptional =
   3003          privateExpr->isKind(ParseNodeKind::OptionalPrivateMemberExpr);
   3004 
   3005      return expression(&privateExpr->privateName(), &key) &&
   3006             builder.memberExpression(true, expr, key, &privateExpr->pn_pos,
   3007                                      dst, isOptional);
   3008    }
   3009 
   3010    case ParseNodeKind::CallSiteObj: {
   3011      CallSiteNode* callSiteObj = &pn->as<CallSiteNode>();
   3012      ListNode* rawNodes = callSiteObj->rawNodes();
   3013      NodeVector raw(cx);
   3014      if (!raw.reserve(rawNodes->count())) {
   3015        return false;
   3016      }
   3017      for (ParseNode* item : rawNodes->contents()) {
   3018        NameNode* rawItem = &item->as<NameNode>();
   3019        MOZ_ASSERT(callSiteObj->pn_pos.encloses(rawItem->pn_pos));
   3020 
   3021        JSAtom* exprAtom = parser->liftParserAtomToJSAtom(rawItem->atom());
   3022        if (!exprAtom) {
   3023          return false;
   3024        }
   3025        RootedValue expr(cx, StringValue(exprAtom));
   3026        raw.infallibleAppend(expr);
   3027      }
   3028 
   3029      NodeVector cooked(cx);
   3030      if (!cooked.reserve(callSiteObj->count() - 1)) {
   3031        return false;
   3032      }
   3033 
   3034      for (ParseNode* cookedItem :
   3035           callSiteObj->contentsFrom(rawNodes->pn_next)) {
   3036        MOZ_ASSERT(callSiteObj->pn_pos.encloses(cookedItem->pn_pos));
   3037 
   3038        RootedValue expr(cx);
   3039        if (cookedItem->isKind(ParseNodeKind::RawUndefinedExpr)) {
   3040          expr.setUndefined();
   3041        } else {
   3042          MOZ_ASSERT(cookedItem->isKind(ParseNodeKind::TemplateStringExpr));
   3043          JSAtom* exprAtom =
   3044              parser->liftParserAtomToJSAtom(cookedItem->as<NameNode>().atom());
   3045          if (!exprAtom) {
   3046            return false;
   3047          }
   3048          expr.setString(exprAtom);
   3049        }
   3050        cooked.infallibleAppend(expr);
   3051      }
   3052 
   3053      return builder.callSiteObj(raw, cooked, &callSiteObj->pn_pos, dst);
   3054    }
   3055 
   3056    case ParseNodeKind::ArrayExpr: {
   3057      ListNode* array = &pn->as<ListNode>();
   3058      NodeVector elts(cx);
   3059      if (!elts.reserve(array->count())) {
   3060        return false;
   3061      }
   3062 
   3063      for (ParseNode* item : array->contents()) {
   3064        MOZ_ASSERT(array->pn_pos.encloses(item->pn_pos));
   3065 
   3066        if (item->isKind(ParseNodeKind::Elision)) {
   3067          elts.infallibleAppend(NullValue());
   3068        } else {
   3069          RootedValue expr(cx);
   3070          if (!expression(item, &expr)) {
   3071            return false;
   3072          }
   3073          elts.infallibleAppend(expr);
   3074        }
   3075      }
   3076 
   3077      return builder.arrayExpression(elts, &array->pn_pos, dst);
   3078    }
   3079 
   3080    case ParseNodeKind::Spread: {
   3081      RootedValue expr(cx);
   3082      return expression(pn->as<UnaryNode>().kid(), &expr) &&
   3083             builder.spreadExpression(expr, &pn->pn_pos, dst);
   3084    }
   3085 
   3086    case ParseNodeKind::ComputedName: {
   3087      if (pn->as<UnaryNode>().isSyntheticComputedName()) {
   3088        return literal(pn->as<UnaryNode>().kid(), dst);
   3089      }
   3090      RootedValue name(cx);
   3091      return expression(pn->as<UnaryNode>().kid(), &name) &&
   3092             builder.computedName(name, &pn->pn_pos, dst);
   3093    }
   3094 
   3095    case ParseNodeKind::ObjectExpr: {
   3096      ListNode* obj = &pn->as<ListNode>();
   3097      NodeVector elts(cx);
   3098      if (!elts.reserve(obj->count())) {
   3099        return false;
   3100      }
   3101 
   3102      for (ParseNode* item : obj->contents()) {
   3103        MOZ_ASSERT(obj->pn_pos.encloses(item->pn_pos));
   3104 
   3105        RootedValue prop(cx);
   3106        if (!property(item, &prop)) {
   3107          return false;
   3108        }
   3109        elts.infallibleAppend(prop);
   3110      }
   3111 
   3112      return builder.objectExpression(elts, &obj->pn_pos, dst);
   3113    }
   3114 
   3115    case ParseNodeKind::PrivateName:
   3116    case ParseNodeKind::Name:
   3117      return identifier(&pn->as<NameNode>(), dst);
   3118 
   3119    case ParseNodeKind::ThisExpr:
   3120      return builder.thisExpression(&pn->pn_pos, dst);
   3121 
   3122    case ParseNodeKind::TemplateStringListExpr: {
   3123      ListNode* list = &pn->as<ListNode>();
   3124      NodeVector elts(cx);
   3125      if (!elts.reserve(list->count())) {
   3126        return false;
   3127      }
   3128 
   3129      for (ParseNode* item : list->contents()) {
   3130        MOZ_ASSERT(list->pn_pos.encloses(item->pn_pos));
   3131 
   3132        RootedValue expr(cx);
   3133        if (!expression(item, &expr)) {
   3134          return false;
   3135        }
   3136        elts.infallibleAppend(expr);
   3137      }
   3138 
   3139      return builder.templateLiteral(elts, &list->pn_pos, dst);
   3140    }
   3141 
   3142    case ParseNodeKind::TemplateStringExpr:
   3143    case ParseNodeKind::StringExpr:
   3144    case ParseNodeKind::RegExpExpr:
   3145    case ParseNodeKind::NumberExpr:
   3146    case ParseNodeKind::BigIntExpr:
   3147    case ParseNodeKind::TrueExpr:
   3148    case ParseNodeKind::FalseExpr:
   3149    case ParseNodeKind::NullExpr:
   3150    case ParseNodeKind::RawUndefinedExpr:
   3151      return literal(pn, dst);
   3152 
   3153    case ParseNodeKind::YieldStarExpr: {
   3154      UnaryNode* yieldNode = &pn->as<UnaryNode>();
   3155      ParseNode* operand = yieldNode->kid();
   3156      MOZ_ASSERT(yieldNode->pn_pos.encloses(operand->pn_pos));
   3157 
   3158      RootedValue arg(cx);
   3159      return expression(operand, &arg) &&
   3160             builder.yieldExpression(arg, Delegating, &yieldNode->pn_pos, dst);
   3161    }
   3162 
   3163    case ParseNodeKind::YieldExpr: {
   3164      UnaryNode* yieldNode = &pn->as<UnaryNode>();
   3165      ParseNode* operand = yieldNode->kid();
   3166      MOZ_ASSERT_IF(operand, yieldNode->pn_pos.encloses(operand->pn_pos));
   3167 
   3168      RootedValue arg(cx);
   3169      return optExpression(operand, &arg) &&
   3170             builder.yieldExpression(arg, NotDelegating, &yieldNode->pn_pos,
   3171                                     dst);
   3172    }
   3173 
   3174    case ParseNodeKind::ClassDecl:
   3175      return classDefinition(&pn->as<ClassNode>(), true, dst);
   3176 
   3177    case ParseNodeKind::NewTargetExpr: {
   3178      auto* node = &pn->as<NewTargetNode>();
   3179      ParseNode* firstNode = node->newHolder();
   3180      MOZ_ASSERT(firstNode->isKind(ParseNodeKind::PosHolder));
   3181      MOZ_ASSERT(node->pn_pos.encloses(firstNode->pn_pos));
   3182 
   3183      ParseNode* secondNode = node->targetHolder();
   3184      MOZ_ASSERT(secondNode->isKind(ParseNodeKind::PosHolder));
   3185      MOZ_ASSERT(node->pn_pos.encloses(secondNode->pn_pos));
   3186 
   3187      RootedValue firstIdent(cx);
   3188      RootedValue secondIdent(cx);
   3189 
   3190      Rooted<JSAtom*> firstStr(cx, cx->names().new_);
   3191      Rooted<JSAtom*> secondStr(cx, cx->names().target);
   3192 
   3193      return identifier(firstStr, &firstNode->pn_pos, &firstIdent) &&
   3194             identifier(secondStr, &secondNode->pn_pos, &secondIdent) &&
   3195             builder.metaProperty(firstIdent, secondIdent, &node->pn_pos, dst);
   3196    }
   3197 
   3198    case ParseNodeKind::ImportMetaExpr: {
   3199      BinaryNode* node = &pn->as<BinaryNode>();
   3200      ParseNode* firstNode = node->left();
   3201      MOZ_ASSERT(firstNode->isKind(ParseNodeKind::PosHolder));
   3202      MOZ_ASSERT(node->pn_pos.encloses(firstNode->pn_pos));
   3203 
   3204      ParseNode* secondNode = node->right();
   3205      MOZ_ASSERT(secondNode->isKind(ParseNodeKind::PosHolder));
   3206      MOZ_ASSERT(node->pn_pos.encloses(secondNode->pn_pos));
   3207 
   3208      RootedValue firstIdent(cx);
   3209      RootedValue secondIdent(cx);
   3210 
   3211      Rooted<JSAtom*> firstStr(cx, cx->names().import);
   3212      Rooted<JSAtom*> secondStr(cx, cx->names().meta);
   3213 
   3214      return identifier(firstStr, &firstNode->pn_pos, &firstIdent) &&
   3215             identifier(secondStr, &secondNode->pn_pos, &secondIdent) &&
   3216             builder.metaProperty(firstIdent, secondIdent, &node->pn_pos, dst);
   3217    }
   3218 
   3219    case ParseNodeKind::CallImportExpr: {
   3220      BinaryNode* node = &pn->as<BinaryNode>();
   3221      ParseNode* identNode = node->left();
   3222      MOZ_ASSERT(identNode->isKind(ParseNodeKind::PosHolder));
   3223      MOZ_ASSERT(identNode->pn_pos.encloses(identNode->pn_pos));
   3224 
   3225      ParseNode* specNode = node->right();
   3226      MOZ_ASSERT(specNode->is<BinaryNode>());
   3227      MOZ_ASSERT(specNode->isKind(ParseNodeKind::CallImportSpec));
   3228 
   3229      ParseNode* argNode = specNode->as<BinaryNode>().left();
   3230      MOZ_ASSERT(node->pn_pos.encloses(argNode->pn_pos));
   3231 
   3232      ParseNode* optionsArgNode = specNode->as<BinaryNode>().right();
   3233      MOZ_ASSERT(node->pn_pos.encloses(optionsArgNode->pn_pos));
   3234 
   3235      RootedValue ident(cx);
   3236      Handle<PropertyName*> name = cx->names().import;
   3237      if (!identifier(name, &identNode->pn_pos, &ident)) {
   3238        return false;
   3239      }
   3240 
   3241      NodeVector args(cx);
   3242 
   3243      RootedValue arg(cx);
   3244      if (!expression(argNode, &arg)) {
   3245        return false;
   3246      }
   3247      if (!args.append(arg)) {
   3248        return false;
   3249      }
   3250 
   3251      if (!optionsArgNode->isKind(ParseNodeKind::PosHolder)) {
   3252        RootedValue optionsArg(cx);
   3253        if (!expression(optionsArgNode, &optionsArg)) {
   3254          return false;
   3255        }
   3256        if (!args.append(optionsArg)) {
   3257          return false;
   3258        }
   3259      }
   3260 
   3261      return builder.callImportExpression(ident, args, &pn->pn_pos, dst);
   3262    }
   3263 
   3264    case ParseNodeKind::SetThis: {
   3265      // SETTHIS is used to assign the result of a super() call to |this|.
   3266      // It's not part of the original AST, so just forward to the call.
   3267      BinaryNode* node = &pn->as<BinaryNode>();
   3268      MOZ_ASSERT(node->left()->isKind(ParseNodeKind::Name));
   3269      return expression(node->right(), dst);
   3270    }
   3271 
   3272    default:
   3273      LOCAL_NOT_REACHED("unexpected expression type");
   3274  }
   3275 }
   3276 
   3277 bool ASTSerializer::propertyName(ParseNode* key, MutableHandleValue dst) {
   3278  if (key->isKind(ParseNodeKind::ComputedName)) {
   3279    return expression(key, dst);
   3280  }
   3281  if (key->isKind(ParseNodeKind::ObjectPropertyName) ||
   3282      key->isKind(ParseNodeKind::PrivateName)) {
   3283    return identifier(&key->as<NameNode>(), dst);
   3284  }
   3285 
   3286  LOCAL_ASSERT(key->isKind(ParseNodeKind::StringExpr) ||
   3287               key->isKind(ParseNodeKind::NumberExpr) ||
   3288               key->isKind(ParseNodeKind::BigIntExpr));
   3289 
   3290  return literal(key, dst);
   3291 }
   3292 
   3293 bool ASTSerializer::property(ParseNode* pn, MutableHandleValue dst) {
   3294  if (pn->isKind(ParseNodeKind::MutateProto)) {
   3295    RootedValue val(cx);
   3296    return expression(pn->as<UnaryNode>().kid(), &val) &&
   3297           builder.prototypeMutation(val, &pn->pn_pos, dst);
   3298  }
   3299  if (pn->isKind(ParseNodeKind::Spread)) {
   3300    return expression(pn, dst);
   3301  }
   3302 
   3303  PropKind kind;
   3304  if (pn->is<PropertyDefinition>()) {
   3305    switch (pn->as<PropertyDefinition>().accessorType()) {
   3306      case AccessorType::None:
   3307        kind = PROP_INIT;
   3308        break;
   3309 
   3310      case AccessorType::Getter:
   3311        kind = PROP_GETTER;
   3312        break;
   3313 
   3314      case AccessorType::Setter:
   3315        kind = PROP_SETTER;
   3316        break;
   3317 
   3318      default:
   3319        LOCAL_NOT_REACHED("unexpected object-literal property");
   3320    }
   3321  } else {
   3322    MOZ_ASSERT(pn->isKind(ParseNodeKind::Shorthand));
   3323    kind = PROP_INIT;
   3324  }
   3325 
   3326  BinaryNode* node = &pn->as<BinaryNode>();
   3327  ParseNode* keyNode = node->left();
   3328  ParseNode* valNode = node->right();
   3329 
   3330  bool isShorthand = node->isKind(ParseNodeKind::Shorthand);
   3331  bool isMethod =
   3332      valNode->is<FunctionNode>() &&
   3333      valNode->as<FunctionNode>().funbox()->kind() == FunctionFlags::Method;
   3334  RootedValue key(cx), val(cx);
   3335  return propertyName(keyNode, &key) && expression(valNode, &val) &&
   3336         builder.propertyInitializer(key, val, kind, isShorthand, isMethod,
   3337                                     &node->pn_pos, dst);
   3338 }
   3339 
   3340 bool ASTSerializer::literal(ParseNode* pn, MutableHandleValue dst) {
   3341  RootedValue val(cx);
   3342  switch (pn->getKind()) {
   3343    case ParseNodeKind::TemplateStringExpr:
   3344    case ParseNodeKind::StringExpr: {
   3345      JSAtom* exprAtom =
   3346          parser->liftParserAtomToJSAtom(pn->as<NameNode>().atom());
   3347      if (!exprAtom) {
   3348        return false;
   3349      }
   3350      val.setString(exprAtom);
   3351      break;
   3352    }
   3353 
   3354    case ParseNodeKind::RegExpExpr: {
   3355      RegExpObject* re = pn->as<RegExpLiteral>().create(
   3356          cx, fc, parser->parserAtoms(),
   3357          parser->getCompilationState().input.atomCache,
   3358          parser->getCompilationState());
   3359      if (!re) {
   3360        return false;
   3361      }
   3362 
   3363      val.setObject(*re);
   3364      break;
   3365    }
   3366 
   3367    case ParseNodeKind::NumberExpr:
   3368      val.setNumber(pn->as<NumericLiteral>().value());
   3369      break;
   3370 
   3371    case ParseNodeKind::BigIntExpr: {
   3372      auto index = pn->as<BigIntLiteral>().index();
   3373      BigInt* x = parser->compilationState_.bigIntData[index].createBigInt(cx);
   3374      if (!x) {
   3375        return false;
   3376      }
   3377      cx->check(x);
   3378      val.setBigInt(x);
   3379      break;
   3380    }
   3381 
   3382    case ParseNodeKind::NullExpr:
   3383      val.setNull();
   3384      break;
   3385 
   3386    case ParseNodeKind::RawUndefinedExpr:
   3387      val.setUndefined();
   3388      break;
   3389 
   3390    case ParseNodeKind::TrueExpr:
   3391      val.setBoolean(true);
   3392      break;
   3393 
   3394    case ParseNodeKind::FalseExpr:
   3395      val.setBoolean(false);
   3396      break;
   3397 
   3398    default:
   3399      LOCAL_NOT_REACHED("unexpected literal type");
   3400  }
   3401 
   3402  return builder.literal(val, &pn->pn_pos, dst);
   3403 }
   3404 
   3405 bool ASTSerializer::arrayPattern(ListNode* array, MutableHandleValue dst) {
   3406  MOZ_ASSERT(array->isKind(ParseNodeKind::ArrayExpr));
   3407 
   3408  NodeVector elts(cx);
   3409  if (!elts.reserve(array->count())) {
   3410    return false;
   3411  }
   3412 
   3413  for (ParseNode* item : array->contents()) {
   3414    if (item->isKind(ParseNodeKind::Elision)) {
   3415      elts.infallibleAppend(NullValue());
   3416    } else if (item->isKind(ParseNodeKind::Spread)) {
   3417      RootedValue target(cx);
   3418      RootedValue spread(cx);
   3419      if (!pattern(item->as<UnaryNode>().kid(), &target)) {
   3420        return false;
   3421      }
   3422      if (!builder.spreadExpression(target, &item->pn_pos, &spread))
   3423        return false;
   3424      elts.infallibleAppend(spread);
   3425    } else {
   3426      RootedValue patt(cx);
   3427      if (!pattern(item, &patt)) {
   3428        return false;
   3429      }
   3430      elts.infallibleAppend(patt);
   3431    }
   3432  }
   3433 
   3434  return builder.arrayPattern(elts, &array->pn_pos, dst);
   3435 }
   3436 
   3437 bool ASTSerializer::objectPattern(ListNode* obj, MutableHandleValue dst) {
   3438  MOZ_ASSERT(obj->isKind(ParseNodeKind::ObjectExpr));
   3439 
   3440  NodeVector elts(cx);
   3441  if (!elts.reserve(obj->count())) {
   3442    return false;
   3443  }
   3444 
   3445  for (ParseNode* propdef : obj->contents()) {
   3446    if (propdef->isKind(ParseNodeKind::Spread)) {
   3447      RootedValue target(cx);
   3448      RootedValue spread(cx);
   3449      if (!pattern(propdef->as<UnaryNode>().kid(), &target)) {
   3450        return false;
   3451      }
   3452      if (!builder.spreadExpression(target, &propdef->pn_pos, &spread))
   3453        return false;
   3454      elts.infallibleAppend(spread);
   3455      continue;
   3456    }
   3457    // Patterns can't have getters/setters.
   3458    LOCAL_ASSERT(!propdef->is<PropertyDefinition>() ||
   3459                 propdef->as<PropertyDefinition>().accessorType() ==
   3460                     AccessorType::None);
   3461 
   3462    RootedValue key(cx);
   3463    ParseNode* target;
   3464    if (propdef->isKind(ParseNodeKind::MutateProto)) {
   3465      RootedValue pname(cx, StringValue(cx->names().proto_));
   3466      if (!builder.literal(pname, &propdef->pn_pos, &key)) {
   3467        return false;
   3468      }
   3469      target = propdef->as<UnaryNode>().kid();
   3470    } else {
   3471      BinaryNode* prop = &propdef->as<BinaryNode>();
   3472      if (!propertyName(prop->left(), &key)) {
   3473        return false;
   3474      }
   3475      target = prop->right();
   3476    }
   3477 
   3478    RootedValue patt(cx), prop(cx);
   3479    if (!pattern(target, &patt) ||
   3480        !builder.propertyPattern(key, patt,
   3481                                 propdef->isKind(ParseNodeKind::Shorthand),
   3482                                 &propdef->pn_pos, &prop)) {
   3483      return false;
   3484    }
   3485 
   3486    elts.infallibleAppend(prop);
   3487  }
   3488 
   3489  return builder.objectPattern(elts, &obj->pn_pos, dst);
   3490 }
   3491 
   3492 bool ASTSerializer::pattern(ParseNode* pn, MutableHandleValue dst) {
   3493  AutoCheckRecursionLimit recursion(cx);
   3494  if (!recursion.check(cx)) {
   3495    return false;
   3496  }
   3497 
   3498  switch (pn->getKind()) {
   3499    case ParseNodeKind::ObjectExpr:
   3500      return objectPattern(&pn->as<ListNode>(), dst);
   3501 
   3502    case ParseNodeKind::ArrayExpr:
   3503      return arrayPattern(&pn->as<ListNode>(), dst);
   3504 
   3505    default:
   3506      return expression(pn, dst);
   3507  }
   3508 }
   3509 
   3510 bool ASTSerializer::identifier(Handle<JSAtom*> atom, TokenPos* pos,
   3511                               MutableHandleValue dst) {
   3512  RootedValue atomContentsVal(cx, unrootedAtomContents(atom));
   3513  return builder.identifier(atomContentsVal, pos, dst);
   3514 }
   3515 
   3516 bool ASTSerializer::identifier(NameNode* id, MutableHandleValue dst) {
   3517  LOCAL_ASSERT(id->atom());
   3518 
   3519  Rooted<JSAtom*> pnAtom(cx, parser->liftParserAtomToJSAtom(id->atom()));
   3520  if (!pnAtom.get()) {
   3521    return false;
   3522  }
   3523  return identifier(pnAtom, &id->pn_pos, dst);
   3524 }
   3525 
   3526 bool ASTSerializer::identifierOrLiteral(ParseNode* id, MutableHandleValue dst) {
   3527  if (id->getKind() == ParseNodeKind::Name) {
   3528    return identifier(&id->as<NameNode>(), dst);
   3529  }
   3530  return literal(id, dst);
   3531 }
   3532 
   3533 bool ASTSerializer::function(FunctionNode* funNode, ASTType type,
   3534                             MutableHandleValue dst) {
   3535  FunctionBox* funbox = funNode->funbox();
   3536 
   3537  GeneratorStyle generatorStyle =
   3538      funbox->isGenerator() ? GeneratorStyle::ES6 : GeneratorStyle::None;
   3539 
   3540  bool isAsync = funbox->isAsync();
   3541  bool isExpression = funbox->hasExprBody();
   3542 
   3543  RootedValue id(cx);
   3544  Rooted<JSAtom*> funcAtom(cx);
   3545  if (funbox->explicitName()) {
   3546    funcAtom.set(parser->liftParserAtomToJSAtom(funbox->explicitName()));
   3547    if (!funcAtom) {
   3548      return false;
   3549    }
   3550  }
   3551  if (!optIdentifier(funcAtom, nullptr, &id)) {
   3552    return false;
   3553  }
   3554 
   3555  NodeVector args(cx);
   3556  NodeVector defaults(cx);
   3557 
   3558  RootedValue body(cx), rest(cx);
   3559  if (funbox->hasRest()) {
   3560    rest.setUndefined();
   3561  } else {
   3562    rest.setNull();
   3563  }
   3564  return functionArgsAndBody(funNode->body(), args, defaults, isAsync,
   3565                             isExpression, &body, &rest) &&
   3566         builder.function(type, &funNode->pn_pos, id, args, defaults, body,
   3567                          rest, generatorStyle, isAsync, isExpression, dst);
   3568 }
   3569 
   3570 bool ASTSerializer::functionArgsAndBody(ParamsBodyNode* pn, NodeVector& args,
   3571                                        NodeVector& defaults, bool isAsync,
   3572                                        bool isExpression,
   3573                                        MutableHandleValue body,
   3574                                        MutableHandleValue rest) {
   3575  // Serialize the arguments.
   3576  if (!functionArgs(pn, args, defaults, rest)) {
   3577    return false;
   3578  }
   3579 
   3580  // Skip the enclosing lexical scope.
   3581  ParseNode* bodyNode = pn->body()->scopeBody();
   3582 
   3583  // Serialize the body.
   3584  switch (bodyNode->getKind()) {
   3585    // Arrow function with expression body.
   3586    case ParseNodeKind::ReturnStmt:
   3587      MOZ_ASSERT(isExpression);
   3588      return expression(bodyNode->as<UnaryNode>().kid(), body);
   3589 
   3590    // Function with statement body.
   3591    case ParseNodeKind::StatementList: {
   3592      ParseNode* firstNode = bodyNode->as<ListNode>().head();
   3593 
   3594      // Skip over initial yield in generator.
   3595      if (firstNode && firstNode->isKind(ParseNodeKind::InitialYield)) {
   3596        firstNode = firstNode->pn_next;
   3597      }
   3598 
   3599      // Async arrow with expression body is converted into STATEMENTLIST
   3600      // to insert initial yield.
   3601      if (isAsync && isExpression) {
   3602        MOZ_ASSERT(firstNode->getKind() == ParseNodeKind::ReturnStmt);
   3603        return expression(firstNode->as<UnaryNode>().kid(), body);
   3604      }
   3605 
   3606      return functionBody(firstNode, &bodyNode->pn_pos, body);
   3607    }
   3608 
   3609    default:
   3610      LOCAL_NOT_REACHED("unexpected function contents");
   3611  }
   3612 }
   3613 
   3614 bool ASTSerializer::functionArgs(ParamsBodyNode* pn, NodeVector& args,
   3615                                 NodeVector& defaults,
   3616                                 MutableHandleValue rest) {
   3617  RootedValue node(cx);
   3618  bool defaultsNull = true;
   3619  MOZ_ASSERT(defaults.empty(),
   3620             "must be initially empty for it to be proper to clear this "
   3621             "when there are no defaults");
   3622 
   3623  MOZ_ASSERT(rest.isNullOrUndefined(),
   3624             "rest is set to |undefined| when a rest argument is present, "
   3625             "otherwise rest is set to |null|");
   3626 
   3627  for (ParseNode* arg : pn->parameters()) {
   3628    ParseNode* pat;
   3629    ParseNode* defNode;
   3630    if (arg->isKind(ParseNodeKind::Name) ||
   3631        arg->isKind(ParseNodeKind::ArrayExpr) ||
   3632        arg->isKind(ParseNodeKind::ObjectExpr)) {
   3633      pat = arg;
   3634      defNode = nullptr;
   3635    } else {
   3636      MOZ_ASSERT(arg->isKind(ParseNodeKind::AssignExpr));
   3637      AssignmentNode* assignNode = &arg->as<AssignmentNode>();
   3638      pat = assignNode->left();
   3639      defNode = assignNode->right();
   3640    }
   3641 
   3642    // Process the name or pattern.
   3643    MOZ_ASSERT(pat->isKind(ParseNodeKind::Name) ||
   3644               pat->isKind(ParseNodeKind::ArrayExpr) ||
   3645               pat->isKind(ParseNodeKind::ObjectExpr));
   3646    if (!pattern(pat, &node)) {
   3647      return false;
   3648    }
   3649    if (rest.isUndefined() && arg->pn_next == *std::end(pn->parameters())) {
   3650      rest.setObject(node.toObject());
   3651    } else {
   3652      if (!args.append(node)) {
   3653        return false;
   3654      }
   3655    }
   3656 
   3657    // Process its default (or lack thereof).
   3658    if (defNode) {
   3659      defaultsNull = false;
   3660      RootedValue def(cx);
   3661      if (!expression(defNode, &def) || !defaults.append(def)) {
   3662        return false;
   3663      }
   3664    } else {
   3665      if (!defaults.append(NullValue())) {
   3666        return false;
   3667      }
   3668    }
   3669  }
   3670  MOZ_ASSERT(!rest.isUndefined(),
   3671             "if a rest argument was present (signified by "
   3672             "|rest.isUndefined()| initially), the rest node was properly "
   3673             "recorded");
   3674 
   3675  if (defaultsNull) {
   3676    defaults.clear();
   3677  }
   3678 
   3679  return true;
   3680 }
   3681 
   3682 bool ASTSerializer::functionBody(ParseNode* pn, TokenPos* pos,
   3683                                 MutableHandleValue dst) {
   3684  NodeVector elts(cx);
   3685 
   3686  // We aren't sure how many elements there are up front, so we'll check each
   3687  // append.
   3688  for (ParseNode* next = pn; next; next = next->pn_next) {
   3689    RootedValue child(cx);
   3690    if (!sourceElement(next, &child) || !elts.append(child)) {
   3691      return false;
   3692    }
   3693  }
   3694 
   3695  return builder.blockStatement(elts, pos, dst);
   3696 }
   3697 
   3698 static bool reflect_parse(JSContext* cx, uint32_t argc, Value* vp) {
   3699  CallArgs args = CallArgsFromVp(argc, vp);
   3700 
   3701  if (!args.requireAtLeast(cx, "Reflect.parse", 1)) {
   3702    return false;
   3703  }
   3704 
   3705  RootedString src(cx, ToString<CanGC>(cx, args[0]));
   3706  if (!src) {
   3707    return false;
   3708  }
   3709 
   3710  UniqueChars filename;
   3711  uint32_t lineno = 1;
   3712  bool loc = true;
   3713  ParseGoal target = ParseGoal::Script;
   3714 
   3715  RootedValue arg(cx, args.get(1));
   3716 
   3717  if (!arg.isNullOrUndefined()) {
   3718    if (!arg.isObject()) {
   3719      ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_SEARCH_STACK, arg,
   3720                       nullptr, "not an object");
   3721      return false;
   3722    }
   3723 
   3724    RootedObject config(cx, &arg.toObject());
   3725 
   3726    RootedValue prop(cx);
   3727 
   3728    /* config.loc */
   3729    RootedId locId(cx, NameToId(cx->names().loc));
   3730    RootedValue trueVal(cx, BooleanValue(true));
   3731    if (!GetPropertyDefault(cx, config, locId, trueVal, &prop)) {
   3732      return false;
   3733    }
   3734 
   3735    loc = ToBoolean(prop);
   3736 
   3737    if (loc) {
   3738      /* config.source */
   3739      RootedId sourceId(cx, NameToId(cx->names().source));
   3740      RootedValue nullVal(cx, NullValue());
   3741      if (!GetPropertyDefault(cx, config, sourceId, nullVal, &prop)) {
   3742        return false;
   3743      }
   3744 
   3745      if (!prop.isNullOrUndefined()) {
   3746        RootedString str(cx, ToString<CanGC>(cx, prop));
   3747        if (!str) {
   3748          return false;
   3749        }
   3750 
   3751        filename = StringToNewUTF8CharsZ(cx, *str);
   3752        if (!filename) {
   3753          return false;
   3754        }
   3755      }
   3756 
   3757      /* config.line */
   3758      RootedId lineId(cx, NameToId(cx->names().line));
   3759      RootedValue oneValue(cx, Int32Value(1));
   3760      if (!GetPropertyDefault(cx, config, lineId, oneValue, &prop) ||
   3761          !ToUint32(cx, prop, &lineno)) {
   3762        return false;
   3763      }
   3764    }
   3765 
   3766    /* config.target */
   3767    RootedId targetId(cx, NameToId(cx->names().target));
   3768    RootedValue scriptVal(cx, StringValue(cx->names().script));
   3769    if (!GetPropertyDefault(cx, config, targetId, scriptVal, &prop)) {
   3770      return false;
   3771    }
   3772 
   3773    if (!prop.isString()) {
   3774      ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_SEARCH_STACK, prop,
   3775                       nullptr, "not 'script' or 'module'");
   3776      return false;
   3777    }
   3778 
   3779    RootedString stringProp(cx, prop.toString());
   3780    bool isScript = false;
   3781    bool isModule = false;
   3782    if (!EqualStrings(cx, stringProp, cx->names().script, &isScript)) {
   3783      return false;
   3784    }
   3785 
   3786    if (!EqualStrings(cx, stringProp, cx->names().module, &isModule)) {
   3787      return false;
   3788    }
   3789 
   3790    if (isScript) {
   3791      target = ParseGoal::Script;
   3792    } else if (isModule) {
   3793      target = ParseGoal::Module;
   3794    } else {
   3795      JS_ReportErrorASCII(cx,
   3796                          "Bad target value, expected 'script' or 'module'");
   3797      return false;
   3798    }
   3799  }
   3800 
   3801  AutoReportFrontendContext fc(cx);
   3802  ASTSerializer serialize(cx, &fc, loc, filename.get(), lineno);
   3803  if (!serialize.init()) {
   3804    return false;
   3805  }
   3806 
   3807  JSLinearString* linear = src->ensureLinear(cx);
   3808  if (!linear) {
   3809    return false;
   3810  }
   3811 
   3812  AutoStableStringChars linearChars(cx);
   3813  if (!linearChars.initTwoByte(cx, linear)) {
   3814    return false;
   3815  }
   3816 
   3817  CompileOptions options(cx);
   3818  options.setFileAndLine(filename.get(), lineno);
   3819  options.setForceFullParse();
   3820  options.allowHTMLComments = target == ParseGoal::Script;
   3821  mozilla::Range<const char16_t> chars = linearChars.twoByteRange();
   3822 
   3823  Rooted<CompilationInput> input(cx, CompilationInput(options));
   3824  if (target == ParseGoal::Script) {
   3825    if (!input.get().initForGlobal(&fc)) {
   3826      return false;
   3827    }
   3828  } else {
   3829    if (!input.get().initForModule(&fc)) {
   3830      return false;
   3831    }
   3832  }
   3833 
   3834  LifoAllocScope allocScope(&cx->tempLifoAlloc());
   3835  frontend::NoScopeBindingCache scopeCache;
   3836  frontend::CompilationState compilationState(&fc, allocScope, input.get());
   3837  if (!compilationState.init(&fc, &scopeCache)) {
   3838    return false;
   3839  }
   3840 
   3841  Parser<FullParseHandler, char16_t> parser(&fc, options, chars.begin().get(),
   3842                                            chars.length(), compilationState,
   3843                                            /* syntaxParser = */ nullptr);
   3844  if (!parser.checkOptions()) {
   3845    return false;
   3846  }
   3847 
   3848  serialize.setParser(&parser);
   3849 
   3850  ParseNode* pn;
   3851  if (target == ParseGoal::Script) {
   3852    pn = parser.parse().unwrapOr(nullptr);
   3853    if (!pn) {
   3854      return false;
   3855    }
   3856  } else {
   3857    ModuleBuilder builder(&fc, &parser);
   3858 
   3859    uint32_t len = chars.length();
   3860    SourceExtent extent = SourceExtent::makeGlobalExtent(
   3861        len, options.lineno,
   3862        JS::LimitedColumnNumberOneOrigin::fromUnlimited(
   3863            JS::ColumnNumberOneOrigin(options.column)));
   3864    ModuleSharedContext modulesc(&fc, options, builder, extent);
   3865    pn = parser.moduleBody(&modulesc).unwrapOr(nullptr);
   3866    if (!pn) {
   3867      return false;
   3868    }
   3869 
   3870    pn = pn->as<ModuleNode>().body();
   3871  }
   3872 
   3873  RootedValue val(cx);
   3874  if (!serialize.program(&pn->as<ListNode>(), &val)) {
   3875    args.rval().setNull();
   3876    return false;
   3877  }
   3878 
   3879  args.rval().set(val);
   3880  return true;
   3881 }
   3882 
   3883 JS_PUBLIC_API bool JS_InitReflectParse(JSContext* cx, HandleObject global) {
   3884  RootedValue reflectVal(cx);
   3885  if (!GetProperty(cx, global, global, cx->names().Reflect, &reflectVal)) {
   3886    return false;
   3887  }
   3888  if (!reflectVal.isObject()) {
   3889    JS_ReportErrorASCII(
   3890        cx, "JS_InitReflectParse must be called during global initialization");
   3891    return false;
   3892  }
   3893 
   3894  RootedObject reflectObj(cx, &reflectVal.toObject());
   3895  return JS_DefineFunction(cx, reflectObj, "parse", reflect_parse, 1, 0);
   3896 }