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