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