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