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