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