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/. */
7 /* JS reflection package. */
11 #include "mozilla/ArrayUtils.h"
12 #include "mozilla/DebugOnly.h"
21 #include "frontend/Parser.h"
22 #include "frontend/TokenStream.h"
23 #include "js/CharacterEncoding.h"
24 #include "vm/RegExpObject.h"
26 #include "jsobjinlines.h"
28 #include "frontend/ParseNode-inl.h"
31 using namespace js::frontend
;
33 using JS::AutoValueArray
;
34 using mozilla::ArrayLength
;
35 using mozilla::DebugOnly
;
37 char const * const js::aopNames
[] = {
46 ">>>=", /* AOP_URSH */
48 "^=", /* AOP_BITXOR */
52 char const * const js::binopNames
[] = {
55 "===", /* BINOP_STRICTEQ */
56 "!==", /* BINOP_STRICTNE */
63 ">>>", /* BINOP_URSH */
65 "-", /* BINOP_MINUS */
69 "|", /* BINOP_BITOR */
70 "^", /* BINOP_BITXOR */
71 "&", /* BINOP_BITAND */
73 "instanceof", /* BINOP_INSTANCEOF */
76 char const * const js::unopNames
[] = {
77 "delete", /* UNOP_DELETE */
81 "~", /* UNOP_BITNOT */
82 "typeof", /* UNOP_TYPEOF */
83 "void" /* UNOP_VOID */
86 char const * const js::nodeTypeNames
[] = {
87 #define ASTDEF(ast, str, method) str,
93 static char const * const callbackNames
[] = {
94 #define ASTDEF(ast, str, method) method,
100 enum YieldKind
{ Delegating
, NotDelegating
};
102 typedef AutoValueVector NodeVector
;
105 * ParseNode is a somewhat intricate data structure, and its invariants have
106 * evolved, making it more likely that there could be a disconnect between the
107 * parser and the AST serializer. We use these macros to check invariants on a
108 * parse node and raise a dynamic error on failure.
110 #define LOCAL_ASSERT(expr) \
114 JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_PARSE_NODE); \
119 #define LOCAL_NOT_REACHED(expr) \
122 JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_PARSE_NODE); \
128 /* Set 'result' to obj[id] if any such property exists, else defaultValue. */
130 GetPropertyDefault(JSContext
* cx
, HandleObject obj
, HandleId id
, HandleValue defaultValue
,
131 MutableHandleValue result
)
134 if (!JSObject::hasProperty(cx
, obj
, id
, &found
))
137 result
.set(defaultValue
);
140 return JSObject::getGeneric(cx
, obj
, obj
, id
, result
);
144 * Builder class that constructs JavaScript AST node objects. See:
146 * https://developer.mozilla.org/en/SpiderMonkey/Parser_API
148 * Bug 569487: generalize builder interface
152 typedef AutoValueArray
<AST_LIMIT
> CallbackArray
;
155 TokenStream
* tokenStream
;
156 bool saveLoc
; /* save source location information? */
157 char const* src
; /* source filename or null */
158 RootedValue srcval
; /* source filename JS value or null */
159 CallbackArray callbacks
; /* user-specified callbacks */
160 RootedValue userv
; /* user-specified builder object or null */
163 NodeBuilder(JSContext
* c
, bool l
, char const* s
)
164 : cx(c
), tokenStream(nullptr), saveLoc(l
), src(s
), srcval(c
), callbacks(cx
),
168 bool init(HandleObject userobj
= js::NullPtr()) {
170 if (!atomValue(src
, &srcval
))
178 for (unsigned i
= 0; i
< AST_LIMIT
; i
++) {
179 callbacks
[i
].setNull();
184 userv
.setObject(*userobj
);
186 RootedValue
nullVal(cx
, NullValue());
187 RootedValue
funv(cx
);
188 for (unsigned i
= 0; i
< AST_LIMIT
; i
++) {
189 const char* name
= callbackNames
[i
];
190 RootedAtom
atom(cx
, Atomize(cx
, name
, strlen(name
)));
193 RootedId
id(cx
, AtomToId(atom
));
194 if (!GetPropertyDefault(cx
, userobj
, id
, nullVal
, &funv
))
197 if (funv
.isNullOrUndefined()) {
198 callbacks
[i
].setNull();
202 if (!funv
.isObject() || !funv
.toObject().is
<JSFunction
>()) {
203 js_ReportValueErrorFlags(cx
, JSREPORT_ERROR
, JSMSG_NOT_FUNCTION
,
204 JSDVG_SEARCH_STACK
, funv
, js::NullPtr(), nullptr, nullptr);
208 callbacks
[i
].set(funv
);
214 void setTokenStream(TokenStream
* ts
) {
219 bool callback(HandleValue fun
, TokenPos
* pos
, MutableHandleValue dst
) {
222 if (!newNodeLoc(pos
, &loc
))
224 AutoValueArray
<1> argv(cx
);
226 return Invoke(cx
, userv
, fun
, argv
.length(), argv
.begin(), dst
);
229 AutoValueArray
<1> argv(cx
);
230 argv
[0].setNull(); /* no zero-length arrays allowed! */
231 return Invoke(cx
, userv
, fun
, 0, argv
.begin(), dst
);
234 bool callback(HandleValue fun
, HandleValue v1
, TokenPos
* pos
, MutableHandleValue dst
) {
237 if (!newNodeLoc(pos
, &loc
))
239 AutoValueArray
<2> argv(cx
);
242 return Invoke(cx
, userv
, fun
, argv
.length(), argv
.begin(), dst
);
245 AutoValueArray
<1> argv(cx
);
247 return Invoke(cx
, userv
, fun
, argv
.length(), argv
.begin(), dst
);
250 bool callback(HandleValue fun
, HandleValue v1
, HandleValue v2
, TokenPos
* pos
,
251 MutableHandleValue dst
) {
254 if (!newNodeLoc(pos
, &loc
))
256 AutoValueArray
<3> argv(cx
);
260 return Invoke(cx
, userv
, fun
, argv
.length(), argv
.begin(), dst
);
263 AutoValueArray
<2> argv(cx
);
266 return Invoke(cx
, userv
, fun
, argv
.length(), argv
.begin(), dst
);
269 bool callback(HandleValue fun
, HandleValue v1
, HandleValue v2
, HandleValue v3
, TokenPos
* pos
,
270 MutableHandleValue dst
) {
273 if (!newNodeLoc(pos
, &loc
))
275 AutoValueArray
<4> argv(cx
);
280 return Invoke(cx
, userv
, fun
, argv
.length(), argv
.begin(), dst
);
283 AutoValueArray
<3> argv(cx
);
287 return Invoke(cx
, userv
, fun
, argv
.length(), argv
.begin(), dst
);
290 bool callback(HandleValue fun
, HandleValue v1
, HandleValue v2
, HandleValue v3
, HandleValue v4
,
291 TokenPos
* pos
, MutableHandleValue dst
) {
294 if (!newNodeLoc(pos
, &loc
))
296 AutoValueArray
<5> argv(cx
);
302 return Invoke(cx
, userv
, fun
, argv
.length(), argv
.begin(), dst
);
305 AutoValueArray
<4> argv(cx
);
310 return Invoke(cx
, userv
, fun
, argv
.length(), argv
.begin(), dst
);
313 bool callback(HandleValue fun
, HandleValue v1
, HandleValue v2
, HandleValue v3
, HandleValue v4
,
314 HandleValue v5
, TokenPos
* pos
, MutableHandleValue dst
) {
317 if (!newNodeLoc(pos
, &loc
))
319 AutoValueArray
<6> argv(cx
);
326 return Invoke(cx
, userv
, fun
, argv
.length(), argv
.begin(), dst
);
329 AutoValueArray
<5> argv(cx
);
335 return Invoke(cx
, userv
, fun
, argv
.length(), argv
.begin(), dst
);
338 // WARNING: Returning a Handle is non-standard, but it works in this case
339 // because both |v| and |UndefinedHandleValue| are definitely rooted on a
340 // previous stack frame (i.e. we're just choosing between two
341 // already-rooted values).
342 HandleValue
opt(HandleValue v
) {
343 MOZ_ASSERT_IF(v
.isMagic(), v
.whyMagic() == JS_SERIALIZE_NO_NODE
);
344 return v
.isMagic(JS_SERIALIZE_NO_NODE
) ? JS::UndefinedHandleValue
: v
;
347 bool atomValue(const char* s
, MutableHandleValue dst
) {
349 * Bug 575416: instead of Atomize, lookup constant atoms in tbl file
351 RootedAtom
atom(cx
, Atomize(cx
, s
, strlen(s
)));
359 bool newObject(MutableHandleObject dst
) {
360 RootedPlainObject
nobj(cx
, NewBuiltinClassInstance
<PlainObject
>(cx
));
368 bool newArray(NodeVector
& elts
, MutableHandleValue dst
);
370 bool newNode(ASTType type
, TokenPos
* pos
, MutableHandleObject dst
);
372 bool newNode(ASTType type
, TokenPos
* pos
, MutableHandleValue dst
) {
373 RootedObject
node(cx
);
374 return newNode(type
, pos
, &node
) &&
375 setResult(node
, dst
);
378 bool newNode(ASTType type
, TokenPos
* pos
,
379 const char* childName
, HandleValue child
,
380 MutableHandleValue dst
) {
381 RootedObject
node(cx
);
382 return newNode(type
, pos
, &node
) &&
383 setProperty(node
, childName
, child
) &&
384 setResult(node
, dst
);
387 bool newNode(ASTType type
, TokenPos
* pos
,
388 const char* childName1
, HandleValue child1
,
389 const char* childName2
, HandleValue child2
,
390 MutableHandleValue dst
) {
391 RootedObject
node(cx
);
392 return newNode(type
, pos
, &node
) &&
393 setProperty(node
, childName1
, child1
) &&
394 setProperty(node
, childName2
, child2
) &&
395 setResult(node
, dst
);
398 bool newNode(ASTType type
, TokenPos
* pos
,
399 const char* childName1
, HandleValue child1
,
400 const char* childName2
, HandleValue child2
,
401 const char* childName3
, HandleValue child3
,
402 MutableHandleValue dst
) {
403 RootedObject
node(cx
);
404 return newNode(type
, pos
, &node
) &&
405 setProperty(node
, childName1
, child1
) &&
406 setProperty(node
, childName2
, child2
) &&
407 setProperty(node
, childName3
, child3
) &&
408 setResult(node
, dst
);
411 bool newNode(ASTType type
, TokenPos
* pos
,
412 const char* childName1
, HandleValue child1
,
413 const char* childName2
, HandleValue child2
,
414 const char* childName3
, HandleValue child3
,
415 const char* childName4
, HandleValue child4
,
416 MutableHandleValue dst
) {
417 RootedObject
node(cx
);
418 return newNode(type
, pos
, &node
) &&
419 setProperty(node
, childName1
, child1
) &&
420 setProperty(node
, childName2
, child2
) &&
421 setProperty(node
, childName3
, child3
) &&
422 setProperty(node
, childName4
, child4
) &&
423 setResult(node
, dst
);
426 bool newNode(ASTType type
, TokenPos
* pos
,
427 const char* childName1
, HandleValue child1
,
428 const char* childName2
, HandleValue child2
,
429 const char* childName3
, HandleValue child3
,
430 const char* childName4
, HandleValue child4
,
431 const char* childName5
, HandleValue child5
,
432 MutableHandleValue dst
) {
433 RootedObject
node(cx
);
434 return newNode(type
, pos
, &node
) &&
435 setProperty(node
, childName1
, child1
) &&
436 setProperty(node
, childName2
, child2
) &&
437 setProperty(node
, childName3
, child3
) &&
438 setProperty(node
, childName4
, child4
) &&
439 setProperty(node
, childName5
, child5
) &&
440 setResult(node
, dst
);
443 bool newNode(ASTType type
, TokenPos
* pos
,
444 const char* childName1
, HandleValue child1
,
445 const char* childName2
, HandleValue child2
,
446 const char* childName3
, HandleValue child3
,
447 const char* childName4
, HandleValue child4
,
448 const char* childName5
, HandleValue child5
,
449 const char* childName6
, HandleValue child6
,
450 MutableHandleValue dst
) {
451 RootedObject
node(cx
);
452 return newNode(type
, pos
, &node
) &&
453 setProperty(node
, childName1
, child1
) &&
454 setProperty(node
, childName2
, child2
) &&
455 setProperty(node
, childName3
, child3
) &&
456 setProperty(node
, childName4
, child4
) &&
457 setProperty(node
, childName5
, child5
) &&
458 setProperty(node
, childName6
, child6
) &&
459 setResult(node
, dst
);
462 bool newNode(ASTType type
, TokenPos
* pos
,
463 const char* childName1
, HandleValue child1
,
464 const char* childName2
, HandleValue child2
,
465 const char* childName3
, HandleValue child3
,
466 const char* childName4
, HandleValue child4
,
467 const char* childName5
, HandleValue child5
,
468 const char* childName6
, HandleValue child6
,
469 const char* childName7
, HandleValue child7
,
470 MutableHandleValue dst
) {
471 RootedObject
node(cx
);
472 return newNode(type
, pos
, &node
) &&
473 setProperty(node
, childName1
, child1
) &&
474 setProperty(node
, childName2
, child2
) &&
475 setProperty(node
, childName3
, child3
) &&
476 setProperty(node
, childName4
, child4
) &&
477 setProperty(node
, childName5
, child5
) &&
478 setProperty(node
, childName6
, child6
) &&
479 setProperty(node
, childName7
, child7
) &&
480 setResult(node
, dst
);
483 bool listNode(ASTType type
, const char* propName
, NodeVector
& elts
, TokenPos
* pos
,
484 MutableHandleValue dst
) {
485 RootedValue
array(cx
);
486 if (!newArray(elts
, &array
))
489 RootedValue
cb(cx
, callbacks
[type
]);
491 return callback(cb
, array
, pos
, dst
);
493 return newNode(type
, pos
, propName
, array
, dst
);
496 bool setProperty(HandleObject obj
, const char* name
, HandleValue val
) {
497 MOZ_ASSERT_IF(val
.isMagic(), val
.whyMagic() == JS_SERIALIZE_NO_NODE
);
500 * Bug 575416: instead of Atomize, lookup constant atoms in tbl file
502 RootedAtom
atom(cx
, Atomize(cx
, name
, strlen(name
)));
506 /* Represent "no node" as null and ensure users are not exposed to magic values. */
507 RootedValue
optVal(cx
, val
.isMagic(JS_SERIALIZE_NO_NODE
) ? NullValue() : val
);
508 return JSObject::defineProperty(cx
, obj
, atom
->asPropertyName(), optVal
);
511 bool newNodeLoc(TokenPos
* pos
, MutableHandleValue dst
);
513 bool setNodeLoc(HandleObject node
, TokenPos
* pos
);
515 bool setResult(HandleObject obj
, MutableHandleValue dst
) {
523 * All of the public builder methods take as their last two
524 * arguments a nullable token position and a non-nullable, rooted
527 * Any Value arguments representing optional subnodes may be a
528 * JS_SERIALIZE_NO_NODE magic value.
535 bool program(NodeVector
& elts
, TokenPos
* pos
, MutableHandleValue dst
);
537 bool literal(HandleValue val
, TokenPos
* pos
, MutableHandleValue dst
);
539 bool identifier(HandleValue name
, TokenPos
* pos
, MutableHandleValue dst
);
541 bool function(ASTType type
, TokenPos
* pos
,
542 HandleValue id
, NodeVector
& args
, NodeVector
& defaults
,
543 HandleValue body
, HandleValue rest
, bool isGenerator
, bool isExpression
,
544 MutableHandleValue dst
);
546 bool variableDeclarator(HandleValue id
, HandleValue init
, TokenPos
* pos
,
547 MutableHandleValue dst
);
549 bool switchCase(HandleValue expr
, NodeVector
& elts
, TokenPos
* pos
, MutableHandleValue dst
);
551 bool catchClause(HandleValue var
, HandleValue guard
, HandleValue body
, TokenPos
* pos
,
552 MutableHandleValue dst
);
554 bool prototypeMutation(HandleValue val
, TokenPos
* pos
, MutableHandleValue dst
);
555 bool propertyInitializer(HandleValue key
, HandleValue val
, PropKind kind
, bool isShorthand
,
556 bool isMethod
, TokenPos
* pos
, MutableHandleValue dst
);
563 bool blockStatement(NodeVector
& elts
, TokenPos
* pos
, MutableHandleValue dst
);
565 bool expressionStatement(HandleValue expr
, TokenPos
* pos
, MutableHandleValue dst
);
567 bool emptyStatement(TokenPos
* pos
, MutableHandleValue dst
);
569 bool ifStatement(HandleValue test
, HandleValue cons
, HandleValue alt
, TokenPos
* pos
,
570 MutableHandleValue dst
);
572 bool breakStatement(HandleValue label
, TokenPos
* pos
, MutableHandleValue dst
);
574 bool continueStatement(HandleValue label
, TokenPos
* pos
, MutableHandleValue dst
);
576 bool labeledStatement(HandleValue label
, HandleValue stmt
, TokenPos
* pos
,
577 MutableHandleValue dst
);
579 bool throwStatement(HandleValue arg
, TokenPos
* pos
, MutableHandleValue dst
);
581 bool returnStatement(HandleValue arg
, TokenPos
* pos
, MutableHandleValue dst
);
583 bool forStatement(HandleValue init
, HandleValue test
, HandleValue update
, HandleValue stmt
,
584 TokenPos
* pos
, MutableHandleValue dst
);
586 bool forInStatement(HandleValue var
, HandleValue expr
, HandleValue stmt
,
587 bool isForEach
, TokenPos
* pos
, MutableHandleValue dst
);
589 bool forOfStatement(HandleValue var
, HandleValue expr
, HandleValue stmt
, TokenPos
* pos
,
590 MutableHandleValue dst
);
592 bool withStatement(HandleValue expr
, HandleValue stmt
, TokenPos
* pos
, MutableHandleValue dst
);
594 bool whileStatement(HandleValue test
, HandleValue stmt
, TokenPos
* pos
, MutableHandleValue dst
);
596 bool doWhileStatement(HandleValue stmt
, HandleValue test
, TokenPos
* pos
,
597 MutableHandleValue dst
);
599 bool switchStatement(HandleValue disc
, NodeVector
& elts
, bool lexical
, TokenPos
* pos
,
600 MutableHandleValue dst
);
602 bool tryStatement(HandleValue body
, NodeVector
& guarded
, HandleValue unguarded
,
603 HandleValue finally
, TokenPos
* pos
, MutableHandleValue dst
);
605 bool debuggerStatement(TokenPos
* pos
, MutableHandleValue dst
);
607 bool letStatement(NodeVector
& head
, HandleValue stmt
, TokenPos
* pos
, MutableHandleValue dst
);
609 bool importDeclaration(NodeVector
& elts
, HandleValue moduleSpec
, TokenPos
* pos
, MutableHandleValue dst
);
611 bool importSpecifier(HandleValue importName
, HandleValue bindingName
, TokenPos
* pos
, MutableHandleValue dst
);
613 bool exportDeclaration(HandleValue decl
, NodeVector
& elts
, HandleValue moduleSpec
, TokenPos
* pos
, MutableHandleValue dst
);
615 bool exportSpecifier(HandleValue bindingName
, HandleValue exportName
, TokenPos
* pos
, MutableHandleValue dst
);
617 bool exportBatchSpecifier(TokenPos
* pos
, MutableHandleValue dst
);
623 bool binaryExpression(BinaryOperator op
, HandleValue left
, HandleValue right
, TokenPos
* pos
,
624 MutableHandleValue dst
);
626 bool unaryExpression(UnaryOperator op
, HandleValue expr
, TokenPos
* pos
, MutableHandleValue dst
);
628 bool assignmentExpression(AssignmentOperator op
, HandleValue lhs
, HandleValue rhs
,
629 TokenPos
* pos
, MutableHandleValue dst
);
631 bool updateExpression(HandleValue expr
, bool incr
, bool prefix
, TokenPos
* pos
,
632 MutableHandleValue dst
);
634 bool logicalExpression(bool lor
, HandleValue left
, HandleValue right
, TokenPos
* pos
,
635 MutableHandleValue dst
);
637 bool conditionalExpression(HandleValue test
, HandleValue cons
, HandleValue alt
, TokenPos
* pos
,
638 MutableHandleValue dst
);
640 bool sequenceExpression(NodeVector
& elts
, TokenPos
* pos
, MutableHandleValue dst
);
642 bool newExpression(HandleValue callee
, NodeVector
& args
, TokenPos
* pos
, MutableHandleValue dst
);
644 bool callExpression(HandleValue callee
, NodeVector
& args
, TokenPos
* pos
,
645 MutableHandleValue dst
);
647 bool memberExpression(bool computed
, HandleValue expr
, HandleValue member
, TokenPos
* pos
,
648 MutableHandleValue dst
);
650 bool arrayExpression(NodeVector
& elts
, TokenPos
* pos
, MutableHandleValue dst
);
652 bool templateLiteral(NodeVector
& elts
, TokenPos
* pos
, MutableHandleValue dst
);
654 bool taggedTemplate(HandleValue callee
, NodeVector
& args
, TokenPos
* pos
,
655 MutableHandleValue dst
);
657 bool callSiteObj(NodeVector
& raw
, NodeVector
& cooked
, TokenPos
* pos
, MutableHandleValue dst
);
659 bool spreadExpression(HandleValue expr
, TokenPos
* pos
, MutableHandleValue dst
);
661 bool computedName(HandleValue name
, TokenPos
* pos
, MutableHandleValue dst
);
663 bool objectExpression(NodeVector
& elts
, TokenPos
* pos
, MutableHandleValue dst
);
665 bool thisExpression(TokenPos
* pos
, MutableHandleValue dst
);
667 bool yieldExpression(HandleValue arg
, YieldKind kind
, TokenPos
* pos
, MutableHandleValue dst
);
669 bool comprehensionBlock(HandleValue patt
, HandleValue src
, bool isForEach
, bool isForOf
, TokenPos
* pos
,
670 MutableHandleValue dst
);
672 bool comprehensionExpression(HandleValue body
, NodeVector
& blocks
, HandleValue filter
,
673 bool isLegacy
, TokenPos
* pos
, MutableHandleValue dst
);
675 bool generatorExpression(HandleValue body
, NodeVector
& blocks
, HandleValue filter
,
676 bool isLegacy
, TokenPos
* pos
, MutableHandleValue dst
);
678 bool letExpression(NodeVector
& head
, HandleValue expr
, TokenPos
* pos
, MutableHandleValue dst
);
684 bool variableDeclaration(NodeVector
& elts
, VarDeclKind kind
, TokenPos
* pos
,
685 MutableHandleValue dst
);
691 bool arrayPattern(NodeVector
& elts
, TokenPos
* pos
, MutableHandleValue dst
);
693 bool objectPattern(NodeVector
& elts
, TokenPos
* pos
, MutableHandleValue dst
);
695 bool propertyPattern(HandleValue key
, HandleValue patt
, bool isShorthand
, TokenPos
* pos
,
696 MutableHandleValue dst
);
699 } /* anonymous namespace */
702 NodeBuilder::newNode(ASTType type
, TokenPos
* pos
, MutableHandleObject dst
)
704 MOZ_ASSERT(type
> AST_ERROR
&& type
< AST_LIMIT
);
707 RootedPlainObject
node(cx
, NewBuiltinClassInstance
<PlainObject
>(cx
));
709 !setNodeLoc(node
, pos
) ||
710 !atomValue(nodeTypeNames
[type
], &tv
) ||
711 !setProperty(node
, "type", tv
)) {
720 NodeBuilder::newArray(NodeVector
& elts
, MutableHandleValue dst
)
722 const size_t len
= elts
.length();
723 if (len
> UINT32_MAX
) {
724 js_ReportAllocationOverflow(cx
);
727 RootedObject
array(cx
, NewDenseFullyAllocatedArray(cx
, uint32_t(len
)));
731 for (size_t i
= 0; i
< len
; i
++) {
732 RootedValue
val(cx
, elts
[i
]);
734 MOZ_ASSERT_IF(val
.isMagic(), val
.whyMagic() == JS_SERIALIZE_NO_NODE
);
736 /* Represent "no node" as an array hole by not adding the value. */
737 if (val
.isMagic(JS_SERIALIZE_NO_NODE
))
740 if (!JSObject::setElement(cx
, array
, array
, i
, &val
, false))
744 dst
.setObject(*array
);
749 NodeBuilder::newNodeLoc(TokenPos
* pos
, MutableHandleValue dst
)
756 RootedObject
loc(cx
);
760 if (!newObject(&loc
))
765 uint32_t startLineNum
, startColumnIndex
;
766 uint32_t endLineNum
, endColumnIndex
;
767 tokenStream
->srcCoords
.lineNumAndColumnIndex(pos
->begin
, &startLineNum
, &startColumnIndex
);
768 tokenStream
->srcCoords
.lineNumAndColumnIndex(pos
->end
, &endLineNum
, &endColumnIndex
);
773 if (!setProperty(loc
, "start", val
))
775 val
.setNumber(startLineNum
);
776 if (!setProperty(to
, "line", val
))
778 val
.setNumber(startColumnIndex
);
779 if (!setProperty(to
, "column", val
))
785 if (!setProperty(loc
, "end", val
))
787 val
.setNumber(endLineNum
);
788 if (!setProperty(to
, "line", val
))
790 val
.setNumber(endColumnIndex
);
791 if (!setProperty(to
, "column", val
))
794 if (!setProperty(loc
, "source", srcval
))
801 NodeBuilder::setNodeLoc(HandleObject node
, TokenPos
* pos
)
804 RootedValue
nullVal(cx
, NullValue());
805 setProperty(node
, "loc", nullVal
);
810 return newNodeLoc(pos
, &loc
) &&
811 setProperty(node
, "loc", loc
);
815 NodeBuilder::program(NodeVector
& elts
, TokenPos
* pos
, MutableHandleValue dst
)
817 return listNode(AST_PROGRAM
, "body", elts
, pos
, dst
);
821 NodeBuilder::blockStatement(NodeVector
& elts
, TokenPos
* pos
, MutableHandleValue dst
)
823 return listNode(AST_BLOCK_STMT
, "body", elts
, pos
, dst
);
827 NodeBuilder::expressionStatement(HandleValue expr
, TokenPos
* pos
, MutableHandleValue dst
)
829 RootedValue
cb(cx
, callbacks
[AST_EXPR_STMT
]);
831 return callback(cb
, expr
, pos
, dst
);
833 return newNode(AST_EXPR_STMT
, pos
, "expression", expr
, dst
);
837 NodeBuilder::emptyStatement(TokenPos
* pos
, MutableHandleValue dst
)
839 RootedValue
cb(cx
, callbacks
[AST_EMPTY_STMT
]);
841 return callback(cb
, pos
, dst
);
843 return newNode(AST_EMPTY_STMT
, pos
, dst
);
847 NodeBuilder::ifStatement(HandleValue test
, HandleValue cons
, HandleValue alt
, TokenPos
* pos
,
848 MutableHandleValue dst
)
850 RootedValue
cb(cx
, callbacks
[AST_IF_STMT
]);
852 return callback(cb
, test
, cons
, opt(alt
), pos
, dst
);
854 return newNode(AST_IF_STMT
, pos
,
862 NodeBuilder::breakStatement(HandleValue label
, TokenPos
* pos
, MutableHandleValue dst
)
864 RootedValue
cb(cx
, callbacks
[AST_BREAK_STMT
]);
866 return callback(cb
, opt(label
), pos
, dst
);
868 return newNode(AST_BREAK_STMT
, pos
, "label", label
, dst
);
872 NodeBuilder::continueStatement(HandleValue label
, TokenPos
* pos
, MutableHandleValue dst
)
874 RootedValue
cb(cx
, callbacks
[AST_CONTINUE_STMT
]);
876 return callback(cb
, opt(label
), pos
, dst
);
878 return newNode(AST_CONTINUE_STMT
, pos
, "label", label
, dst
);
882 NodeBuilder::labeledStatement(HandleValue label
, HandleValue stmt
, TokenPos
* pos
,
883 MutableHandleValue dst
)
885 RootedValue
cb(cx
, callbacks
[AST_LAB_STMT
]);
887 return callback(cb
, label
, stmt
, pos
, dst
);
889 return newNode(AST_LAB_STMT
, pos
,
896 NodeBuilder::throwStatement(HandleValue arg
, TokenPos
* pos
, MutableHandleValue dst
)
898 RootedValue
cb(cx
, callbacks
[AST_THROW_STMT
]);
900 return callback(cb
, arg
, pos
, dst
);
902 return newNode(AST_THROW_STMT
, pos
, "argument", arg
, dst
);
906 NodeBuilder::returnStatement(HandleValue arg
, TokenPos
* pos
, MutableHandleValue dst
)
908 RootedValue
cb(cx
, callbacks
[AST_RETURN_STMT
]);
910 return callback(cb
, opt(arg
), pos
, dst
);
912 return newNode(AST_RETURN_STMT
, pos
, "argument", arg
, dst
);
916 NodeBuilder::forStatement(HandleValue init
, HandleValue test
, HandleValue update
, HandleValue stmt
,
917 TokenPos
* pos
, MutableHandleValue dst
)
919 RootedValue
cb(cx
, callbacks
[AST_FOR_STMT
]);
921 return callback(cb
, opt(init
), opt(test
), opt(update
), stmt
, pos
, dst
);
923 return newNode(AST_FOR_STMT
, pos
,
932 NodeBuilder::forInStatement(HandleValue var
, HandleValue expr
, HandleValue stmt
, bool isForEach
,
933 TokenPos
* pos
, MutableHandleValue dst
)
935 RootedValue
isForEachVal(cx
, BooleanValue(isForEach
));
937 RootedValue
cb(cx
, callbacks
[AST_FOR_IN_STMT
]);
939 return callback(cb
, var
, expr
, stmt
, isForEachVal
, pos
, dst
);
941 return newNode(AST_FOR_IN_STMT
, pos
,
945 "each", isForEachVal
,
950 NodeBuilder::forOfStatement(HandleValue var
, HandleValue expr
, HandleValue stmt
, TokenPos
* pos
,
951 MutableHandleValue dst
)
953 RootedValue
cb(cx
, callbacks
[AST_FOR_OF_STMT
]);
955 return callback(cb
, var
, expr
, stmt
, pos
, dst
);
957 return newNode(AST_FOR_OF_STMT
, pos
,
965 NodeBuilder::withStatement(HandleValue expr
, HandleValue stmt
, TokenPos
* pos
,
966 MutableHandleValue dst
)
968 RootedValue
cb(cx
, callbacks
[AST_WITH_STMT
]);
970 return callback(cb
, expr
, stmt
, pos
, dst
);
972 return newNode(AST_WITH_STMT
, pos
,
979 NodeBuilder::whileStatement(HandleValue test
, HandleValue stmt
, TokenPos
* pos
,
980 MutableHandleValue dst
)
982 RootedValue
cb(cx
, callbacks
[AST_WHILE_STMT
]);
984 return callback(cb
, test
, stmt
, pos
, dst
);
986 return newNode(AST_WHILE_STMT
, pos
,
993 NodeBuilder::doWhileStatement(HandleValue stmt
, HandleValue test
, TokenPos
* pos
,
994 MutableHandleValue dst
)
996 RootedValue
cb(cx
, callbacks
[AST_DO_STMT
]);
998 return callback(cb
, stmt
, test
, pos
, dst
);
1000 return newNode(AST_DO_STMT
, pos
,
1007 NodeBuilder::switchStatement(HandleValue disc
, NodeVector
& elts
, bool lexical
, TokenPos
* pos
,
1008 MutableHandleValue dst
)
1010 RootedValue
array(cx
);
1011 if (!newArray(elts
, &array
))
1014 RootedValue
lexicalVal(cx
, BooleanValue(lexical
));
1016 RootedValue
cb(cx
, callbacks
[AST_SWITCH_STMT
]);
1018 return callback(cb
, disc
, array
, lexicalVal
, pos
, dst
);
1020 return newNode(AST_SWITCH_STMT
, pos
,
1021 "discriminant", disc
,
1023 "lexical", lexicalVal
,
1028 NodeBuilder::tryStatement(HandleValue body
, NodeVector
& guarded
, HandleValue unguarded
,
1029 HandleValue finally
, TokenPos
* pos
, MutableHandleValue dst
)
1031 RootedValue
guardedHandlers(cx
);
1032 if (!newArray(guarded
, &guardedHandlers
))
1035 RootedValue
cb(cx
, callbacks
[AST_TRY_STMT
]);
1037 return callback(cb
, body
, guardedHandlers
, unguarded
, opt(finally
), pos
, dst
);
1039 return newNode(AST_TRY_STMT
, pos
,
1041 "guardedHandlers", guardedHandlers
,
1042 "handler", unguarded
,
1043 "finalizer", finally
,
1048 NodeBuilder::debuggerStatement(TokenPos
* pos
, MutableHandleValue dst
)
1050 RootedValue
cb(cx
, callbacks
[AST_DEBUGGER_STMT
]);
1052 return callback(cb
, pos
, dst
);
1054 return newNode(AST_DEBUGGER_STMT
, pos
, dst
);
1058 NodeBuilder::binaryExpression(BinaryOperator op
, HandleValue left
, HandleValue right
, TokenPos
* pos
,
1059 MutableHandleValue dst
)
1061 MOZ_ASSERT(op
> BINOP_ERR
&& op
< BINOP_LIMIT
);
1063 RootedValue
opName(cx
);
1064 if (!atomValue(binopNames
[op
], &opName
))
1067 RootedValue
cb(cx
, callbacks
[AST_BINARY_EXPR
]);
1069 return callback(cb
, opName
, left
, right
, pos
, dst
);
1071 return newNode(AST_BINARY_EXPR
, pos
,
1079 NodeBuilder::unaryExpression(UnaryOperator unop
, HandleValue expr
, TokenPos
* pos
,
1080 MutableHandleValue dst
)
1082 MOZ_ASSERT(unop
> UNOP_ERR
&& unop
< UNOP_LIMIT
);
1084 RootedValue
opName(cx
);
1085 if (!atomValue(unopNames
[unop
], &opName
))
1088 RootedValue
cb(cx
, callbacks
[AST_UNARY_EXPR
]);
1090 return callback(cb
, opName
, expr
, pos
, dst
);
1092 RootedValue
trueVal(cx
, BooleanValue(true));
1093 return newNode(AST_UNARY_EXPR
, pos
,
1101 NodeBuilder::assignmentExpression(AssignmentOperator aop
, HandleValue lhs
, HandleValue rhs
,
1102 TokenPos
* pos
, MutableHandleValue dst
)
1104 MOZ_ASSERT(aop
> AOP_ERR
&& aop
< AOP_LIMIT
);
1106 RootedValue
opName(cx
);
1107 if (!atomValue(aopNames
[aop
], &opName
))
1110 RootedValue
cb(cx
, callbacks
[AST_ASSIGN_EXPR
]);
1112 return callback(cb
, opName
, lhs
, rhs
, pos
, dst
);
1114 return newNode(AST_ASSIGN_EXPR
, pos
,
1122 NodeBuilder::updateExpression(HandleValue expr
, bool incr
, bool prefix
, TokenPos
* pos
,
1123 MutableHandleValue dst
)
1125 RootedValue
opName(cx
);
1126 if (!atomValue(incr
? "++" : "--", &opName
))
1129 RootedValue
prefixVal(cx
, BooleanValue(prefix
));
1131 RootedValue
cb(cx
, callbacks
[AST_UPDATE_EXPR
]);
1133 return callback(cb
, expr
, opName
, prefixVal
, pos
, dst
);
1135 return newNode(AST_UPDATE_EXPR
, pos
,
1138 "prefix", prefixVal
,
1143 NodeBuilder::logicalExpression(bool lor
, HandleValue left
, HandleValue right
, TokenPos
* pos
,
1144 MutableHandleValue dst
)
1146 RootedValue
opName(cx
);
1147 if (!atomValue(lor
? "||" : "&&", &opName
))
1150 RootedValue
cb(cx
, callbacks
[AST_LOGICAL_EXPR
]);
1152 return callback(cb
, opName
, left
, right
, pos
, dst
);
1154 return newNode(AST_LOGICAL_EXPR
, pos
,
1162 NodeBuilder::conditionalExpression(HandleValue test
, HandleValue cons
, HandleValue alt
,
1163 TokenPos
* pos
, MutableHandleValue dst
)
1165 RootedValue
cb(cx
, callbacks
[AST_COND_EXPR
]);
1167 return callback(cb
, test
, cons
, alt
, pos
, dst
);
1169 return newNode(AST_COND_EXPR
, pos
,
1177 NodeBuilder::sequenceExpression(NodeVector
& elts
, TokenPos
* pos
, MutableHandleValue dst
)
1179 return listNode(AST_LIST_EXPR
, "expressions", elts
, pos
, dst
);
1183 NodeBuilder::callExpression(HandleValue callee
, NodeVector
& args
, TokenPos
* pos
,
1184 MutableHandleValue dst
)
1186 RootedValue
array(cx
);
1187 if (!newArray(args
, &array
))
1190 RootedValue
cb(cx
, callbacks
[AST_CALL_EXPR
]);
1192 return callback(cb
, callee
, array
, pos
, dst
);
1194 return newNode(AST_CALL_EXPR
, pos
,
1201 NodeBuilder::newExpression(HandleValue callee
, NodeVector
& args
, TokenPos
* pos
,
1202 MutableHandleValue dst
)
1204 RootedValue
array(cx
);
1205 if (!newArray(args
, &array
))
1208 RootedValue
cb(cx
, callbacks
[AST_NEW_EXPR
]);
1210 return callback(cb
, callee
, array
, pos
, dst
);
1212 return newNode(AST_NEW_EXPR
, pos
,
1219 NodeBuilder::memberExpression(bool computed
, HandleValue expr
, HandleValue member
, TokenPos
* pos
,
1220 MutableHandleValue dst
)
1222 RootedValue
computedVal(cx
, BooleanValue(computed
));
1224 RootedValue
cb(cx
, callbacks
[AST_MEMBER_EXPR
]);
1226 return callback(cb
, computedVal
, expr
, member
, pos
, dst
);
1228 return newNode(AST_MEMBER_EXPR
, pos
,
1231 "computed", computedVal
,
1236 NodeBuilder::arrayExpression(NodeVector
& elts
, TokenPos
* pos
, MutableHandleValue dst
)
1238 return listNode(AST_ARRAY_EXPR
, "elements", elts
, pos
, dst
);
1242 NodeBuilder::callSiteObj(NodeVector
& raw
, NodeVector
& cooked
, TokenPos
* pos
, MutableHandleValue dst
)
1244 RootedValue
rawVal(cx
);
1245 if (!newArray(raw
, &rawVal
))
1248 RootedValue
cookedVal(cx
);
1249 if (!newArray(cooked
, &cookedVal
))
1252 return newNode(AST_CALL_SITE_OBJ
, pos
,
1254 "cooked", cookedVal
,
1259 NodeBuilder::taggedTemplate(HandleValue callee
, NodeVector
& args
, TokenPos
* pos
,
1260 MutableHandleValue dst
)
1262 RootedValue
array(cx
);
1263 if (!newArray(args
, &array
))
1266 return newNode(AST_TAGGED_TEMPLATE
, pos
,
1273 NodeBuilder::templateLiteral(NodeVector
& elts
, TokenPos
* pos
, MutableHandleValue dst
)
1275 return listNode(AST_TEMPLATE_LITERAL
, "elements", elts
, pos
, dst
);
1279 NodeBuilder::computedName(HandleValue name
, TokenPos
* pos
, MutableHandleValue dst
)
1281 return newNode(AST_COMPUTED_NAME
, pos
,
1287 NodeBuilder::spreadExpression(HandleValue expr
, TokenPos
* pos
, MutableHandleValue dst
)
1289 return newNode(AST_SPREAD_EXPR
, pos
,
1295 NodeBuilder::propertyPattern(HandleValue key
, HandleValue patt
, bool isShorthand
, TokenPos
* pos
,
1296 MutableHandleValue dst
)
1298 RootedValue
kindName(cx
);
1299 if (!atomValue("init", &kindName
))
1302 RootedValue
isShorthandVal(cx
, BooleanValue(isShorthand
));
1304 RootedValue
cb(cx
, callbacks
[AST_PROP_PATT
]);
1306 return callback(cb
, key
, patt
, pos
, dst
);
1308 return newNode(AST_PROP_PATT
, pos
,
1312 "shorthand", isShorthandVal
,
1317 NodeBuilder::prototypeMutation(HandleValue val
, TokenPos
* pos
, MutableHandleValue dst
)
1319 RootedValue
cb(cx
, callbacks
[AST_PROTOTYPEMUTATION
]);
1321 return callback(cb
, val
, pos
, dst
);
1323 return newNode(AST_PROTOTYPEMUTATION
, pos
,
1329 NodeBuilder::propertyInitializer(HandleValue key
, HandleValue val
, PropKind kind
, bool isShorthand
,
1330 bool isMethod
, TokenPos
* pos
, MutableHandleValue dst
)
1332 RootedValue
kindName(cx
);
1333 if (!atomValue(kind
== PROP_INIT
1335 : kind
== PROP_GETTER
1337 : "set", &kindName
)) {
1341 RootedValue
isShorthandVal(cx
, BooleanValue(isShorthand
));
1342 RootedValue
isMethodVal(cx
, BooleanValue(isMethod
));
1344 RootedValue
cb(cx
, callbacks
[AST_PROPERTY
]);
1346 return callback(cb
, kindName
, key
, val
, pos
, dst
);
1348 return newNode(AST_PROPERTY
, pos
,
1352 "method", isMethodVal
,
1353 "shorthand", isShorthandVal
,
1358 NodeBuilder::objectExpression(NodeVector
& elts
, TokenPos
* pos
, MutableHandleValue dst
)
1360 return listNode(AST_OBJECT_EXPR
, "properties", elts
, pos
, dst
);
1364 NodeBuilder::thisExpression(TokenPos
* pos
, MutableHandleValue dst
)
1366 RootedValue
cb(cx
, callbacks
[AST_THIS_EXPR
]);
1368 return callback(cb
, pos
, dst
);
1370 return newNode(AST_THIS_EXPR
, pos
, dst
);
1374 NodeBuilder::yieldExpression(HandleValue arg
, YieldKind kind
, TokenPos
* pos
, MutableHandleValue dst
)
1376 RootedValue
cb(cx
, callbacks
[AST_YIELD_EXPR
]);
1377 RootedValue
delegateVal(cx
);
1381 delegateVal
= BooleanValue(true);
1384 delegateVal
= BooleanValue(false);
1389 return callback(cb
, opt(arg
), delegateVal
, pos
, dst
);
1390 return newNode(AST_YIELD_EXPR
, pos
, "argument", arg
, "delegate", delegateVal
, dst
);
1394 NodeBuilder::comprehensionBlock(HandleValue patt
, HandleValue src
, bool isForEach
, bool isForOf
, TokenPos
* pos
,
1395 MutableHandleValue dst
)
1397 RootedValue
isForEachVal(cx
, BooleanValue(isForEach
));
1398 RootedValue
isForOfVal(cx
, BooleanValue(isForOf
));
1400 RootedValue
cb(cx
, callbacks
[AST_COMP_BLOCK
]);
1402 return callback(cb
, patt
, src
, isForEachVal
, isForOfVal
, pos
, dst
);
1404 return newNode(AST_COMP_BLOCK
, pos
,
1407 "each", isForEachVal
,
1413 NodeBuilder::comprehensionExpression(HandleValue body
, NodeVector
& blocks
, HandleValue filter
,
1414 bool isLegacy
, TokenPos
* pos
, MutableHandleValue dst
)
1416 RootedValue
array(cx
);
1417 if (!newArray(blocks
, &array
))
1420 RootedValue
style(cx
);
1421 if (!atomValue(isLegacy
? "legacy" : "modern", &style
))
1424 RootedValue
cb(cx
, callbacks
[AST_COMP_EXPR
]);
1426 return callback(cb
, body
, array
, opt(filter
), style
, pos
, dst
);
1428 return newNode(AST_COMP_EXPR
, pos
,
1437 NodeBuilder::generatorExpression(HandleValue body
, NodeVector
& blocks
, HandleValue filter
,
1438 bool isLegacy
, TokenPos
* pos
, MutableHandleValue dst
)
1440 RootedValue
array(cx
);
1441 if (!newArray(blocks
, &array
))
1444 RootedValue
style(cx
);
1445 if (!atomValue(isLegacy
? "legacy" : "modern", &style
))
1448 RootedValue
cb(cx
, callbacks
[AST_GENERATOR_EXPR
]);
1450 return callback(cb
, body
, array
, opt(filter
), style
, pos
, dst
);
1452 return newNode(AST_GENERATOR_EXPR
, pos
,
1461 NodeBuilder::letExpression(NodeVector
& head
, HandleValue expr
, TokenPos
* pos
,
1462 MutableHandleValue dst
)
1464 RootedValue
array(cx
);
1465 if (!newArray(head
, &array
))
1468 RootedValue
cb(cx
, callbacks
[AST_LET_EXPR
]);
1470 return callback(cb
, array
, expr
, pos
, dst
);
1472 return newNode(AST_LET_EXPR
, pos
,
1479 NodeBuilder::letStatement(NodeVector
& head
, HandleValue stmt
, TokenPos
* pos
, MutableHandleValue dst
)
1481 RootedValue
array(cx
);
1482 if (!newArray(head
, &array
))
1485 RootedValue
cb(cx
, callbacks
[AST_LET_STMT
]);
1487 return callback(cb
, array
, stmt
, pos
, dst
);
1489 return newNode(AST_LET_STMT
, pos
,
1496 NodeBuilder::importDeclaration(NodeVector
& elts
, HandleValue moduleSpec
, TokenPos
* pos
,
1497 MutableHandleValue dst
)
1499 RootedValue
array(cx
);
1500 if (!newArray(elts
, &array
))
1503 RootedValue
cb(cx
, callbacks
[AST_IMPORT_DECL
]);
1505 return callback(cb
, array
, moduleSpec
, pos
, dst
);
1507 return newNode(AST_IMPORT_DECL
, pos
,
1508 "specifiers", array
,
1509 "source", moduleSpec
,
1514 NodeBuilder::importSpecifier(HandleValue importName
, HandleValue bindingName
, TokenPos
* pos
,
1515 MutableHandleValue dst
)
1517 RootedValue
cb(cx
, callbacks
[AST_IMPORT_SPEC
]);
1519 return callback(cb
, importName
, bindingName
, pos
, dst
);
1521 return newNode(AST_IMPORT_SPEC
, pos
,
1523 "name", bindingName
,
1528 NodeBuilder::exportDeclaration(HandleValue decl
, NodeVector
& elts
, HandleValue moduleSpec
,
1529 TokenPos
* pos
, MutableHandleValue dst
)
1531 RootedValue
array(cx
, NullValue());
1532 if (decl
.isNull() && !newArray(elts
, &array
))
1535 RootedValue
cb(cx
, callbacks
[AST_IMPORT_DECL
]);
1538 return callback(cb
, decl
, array
, moduleSpec
, pos
, dst
);
1540 return newNode(AST_EXPORT_DECL
, pos
,
1541 "declaration", decl
,
1542 "specifiers", array
,
1543 "source", moduleSpec
,
1548 NodeBuilder::exportSpecifier(HandleValue bindingName
, HandleValue exportName
, TokenPos
* pos
,
1549 MutableHandleValue dst
)
1551 RootedValue
cb(cx
, callbacks
[AST_EXPORT_SPEC
]);
1553 return callback(cb
, bindingName
, exportName
, pos
, dst
);
1555 return newNode(AST_EXPORT_SPEC
, pos
,
1562 NodeBuilder::exportBatchSpecifier(TokenPos
* pos
, MutableHandleValue dst
)
1564 RootedValue
cb(cx
, callbacks
[AST_EXPORT_BATCH_SPEC
]);
1566 return callback(cb
, pos
, dst
);
1568 return newNode(AST_EXPORT_BATCH_SPEC
, pos
, dst
);
1572 NodeBuilder::variableDeclaration(NodeVector
& elts
, VarDeclKind kind
, TokenPos
* pos
,
1573 MutableHandleValue dst
)
1575 MOZ_ASSERT(kind
> VARDECL_ERR
&& kind
< VARDECL_LIMIT
);
1577 RootedValue
array(cx
), kindName(cx
);
1578 if (!newArray(elts
, &array
) ||
1579 !atomValue(kind
== VARDECL_CONST
1581 : kind
== VARDECL_LET
1583 : "var", &kindName
)) {
1587 RootedValue
cb(cx
, callbacks
[AST_VAR_DECL
]);
1589 return callback(cb
, kindName
, array
, pos
, dst
);
1591 return newNode(AST_VAR_DECL
, pos
,
1593 "declarations", array
,
1598 NodeBuilder::variableDeclarator(HandleValue id
, HandleValue init
, TokenPos
* pos
,
1599 MutableHandleValue dst
)
1601 RootedValue
cb(cx
, callbacks
[AST_VAR_DTOR
]);
1603 return callback(cb
, id
, opt(init
), pos
, dst
);
1605 return newNode(AST_VAR_DTOR
, pos
, "id", id
, "init", init
, dst
);
1609 NodeBuilder::switchCase(HandleValue expr
, NodeVector
& elts
, TokenPos
* pos
, MutableHandleValue dst
)
1611 RootedValue
array(cx
);
1612 if (!newArray(elts
, &array
))
1615 RootedValue
cb(cx
, callbacks
[AST_CASE
]);
1617 return callback(cb
, opt(expr
), array
, pos
, dst
);
1619 return newNode(AST_CASE
, pos
,
1621 "consequent", array
,
1626 NodeBuilder::catchClause(HandleValue var
, HandleValue guard
, HandleValue body
, TokenPos
* pos
,
1627 MutableHandleValue dst
)
1629 RootedValue
cb(cx
, callbacks
[AST_CATCH
]);
1631 return callback(cb
, var
, opt(guard
), body
, pos
, dst
);
1633 return newNode(AST_CATCH
, pos
,
1641 NodeBuilder::literal(HandleValue val
, TokenPos
* pos
, MutableHandleValue dst
)
1643 RootedValue
cb(cx
, callbacks
[AST_LITERAL
]);
1645 return callback(cb
, val
, pos
, dst
);
1647 return newNode(AST_LITERAL
, pos
, "value", val
, dst
);
1651 NodeBuilder::identifier(HandleValue name
, TokenPos
* pos
, MutableHandleValue dst
)
1653 RootedValue
cb(cx
, callbacks
[AST_IDENTIFIER
]);
1655 return callback(cb
, name
, pos
, dst
);
1657 return newNode(AST_IDENTIFIER
, pos
, "name", name
, dst
);
1661 NodeBuilder::objectPattern(NodeVector
& elts
, TokenPos
* pos
, MutableHandleValue dst
)
1663 return listNode(AST_OBJECT_PATT
, "properties", elts
, pos
, dst
);
1667 NodeBuilder::arrayPattern(NodeVector
& elts
, TokenPos
* pos
, MutableHandleValue dst
)
1669 return listNode(AST_ARRAY_PATT
, "elements", elts
, pos
, dst
);
1673 NodeBuilder::function(ASTType type
, TokenPos
* pos
,
1674 HandleValue id
, NodeVector
& args
, NodeVector
& defaults
,
1675 HandleValue body
, HandleValue rest
,
1676 bool isGenerator
, bool isExpression
,
1677 MutableHandleValue dst
)
1679 RootedValue
array(cx
), defarray(cx
);
1680 if (!newArray(args
, &array
))
1682 if (!newArray(defaults
, &defarray
))
1685 RootedValue
isGeneratorVal(cx
, BooleanValue(isGenerator
));
1686 RootedValue
isExpressionVal(cx
, BooleanValue(isExpression
));
1688 RootedValue
cb(cx
, callbacks
[type
]);
1690 return callback(cb
, opt(id
), array
, body
, isGeneratorVal
, isExpressionVal
, pos
, dst
);
1693 return newNode(type
, pos
,
1696 "defaults", defarray
,
1699 "generator", isGeneratorVal
,
1700 "expression", isExpressionVal
,
1707 * Serialization of parse nodes to JavaScript objects.
1709 * All serialization methods take a non-nullable ParseNode pointer.
1714 Parser
<FullParseHandler
>* parser
;
1715 NodeBuilder builder
;
1716 DebugOnly
<uint32_t> lineno
;
1718 Value
unrootedAtomContents(JSAtom
* atom
) {
1719 return StringValue(atom
? atom
: cx
->names().empty
);
1722 BinaryOperator
binop(ParseNodeKind kind
, JSOp op
);
1723 UnaryOperator
unop(ParseNodeKind kind
, JSOp op
);
1724 AssignmentOperator
aop(JSOp op
);
1726 bool statements(ParseNode
* pn
, NodeVector
& elts
);
1727 bool expressions(ParseNode
* pn
, NodeVector
& elts
);
1728 bool leftAssociate(ParseNode
* pn
, MutableHandleValue dst
);
1729 bool functionArgs(ParseNode
* pn
, ParseNode
* pnargs
, ParseNode
* pndestruct
, ParseNode
* pnbody
,
1730 NodeVector
& args
, NodeVector
& defaults
, MutableHandleValue rest
);
1732 bool sourceElement(ParseNode
* pn
, MutableHandleValue dst
);
1734 bool declaration(ParseNode
* pn
, MutableHandleValue dst
);
1735 bool variableDeclaration(ParseNode
* pn
, bool lexical
, MutableHandleValue dst
);
1736 bool variableDeclarator(ParseNode
* pn
, MutableHandleValue dst
);
1737 bool let(ParseNode
* pn
, bool expr
, MutableHandleValue dst
);
1738 bool importDeclaration(ParseNode
* pn
, MutableHandleValue dst
);
1739 bool importSpecifier(ParseNode
* pn
, MutableHandleValue dst
);
1740 bool exportDeclaration(ParseNode
* pn
, MutableHandleValue dst
);
1741 bool exportSpecifier(ParseNode
* pn
, MutableHandleValue dst
);
1743 bool optStatement(ParseNode
* pn
, MutableHandleValue dst
) {
1745 dst
.setMagic(JS_SERIALIZE_NO_NODE
);
1748 return statement(pn
, dst
);
1751 bool forInit(ParseNode
* pn
, MutableHandleValue dst
);
1752 bool forIn(ParseNode
* loop
, ParseNode
* head
, HandleValue var
, HandleValue stmt
,
1753 MutableHandleValue dst
);
1754 bool forOf(ParseNode
* loop
, ParseNode
* head
, HandleValue var
, HandleValue stmt
,
1755 MutableHandleValue dst
);
1756 bool statement(ParseNode
* pn
, MutableHandleValue dst
);
1757 bool blockStatement(ParseNode
* pn
, MutableHandleValue dst
);
1758 bool switchStatement(ParseNode
* pn
, MutableHandleValue dst
);
1759 bool switchCase(ParseNode
* pn
, MutableHandleValue dst
);
1760 bool tryStatement(ParseNode
* pn
, MutableHandleValue dst
);
1761 bool catchClause(ParseNode
* pn
, bool* isGuarded
, MutableHandleValue dst
);
1763 bool optExpression(ParseNode
* pn
, MutableHandleValue dst
) {
1765 dst
.setMagic(JS_SERIALIZE_NO_NODE
);
1768 return expression(pn
, dst
);
1771 bool expression(ParseNode
* pn
, MutableHandleValue dst
);
1773 bool propertyName(ParseNode
* pn
, MutableHandleValue dst
);
1774 bool property(ParseNode
* pn
, MutableHandleValue dst
);
1776 bool optIdentifier(HandleAtom atom
, TokenPos
* pos
, MutableHandleValue dst
) {
1778 dst
.setMagic(JS_SERIALIZE_NO_NODE
);
1781 return identifier(atom
, pos
, dst
);
1784 bool identifier(HandleAtom atom
, TokenPos
* pos
, MutableHandleValue dst
);
1785 bool identifier(ParseNode
* pn
, MutableHandleValue dst
);
1786 bool literal(ParseNode
* pn
, MutableHandleValue dst
);
1788 bool pattern(ParseNode
* pn
, MutableHandleValue dst
);
1789 bool arrayPattern(ParseNode
* pn
, MutableHandleValue dst
);
1790 bool objectPattern(ParseNode
* pn
, MutableHandleValue dst
);
1792 bool function(ParseNode
* pn
, ASTType type
, MutableHandleValue dst
);
1793 bool functionArgsAndBody(ParseNode
* pn
, NodeVector
& args
, NodeVector
& defaults
,
1794 MutableHandleValue body
, MutableHandleValue rest
);
1795 bool functionBody(ParseNode
* pn
, TokenPos
* pos
, MutableHandleValue dst
);
1797 bool comprehensionBlock(ParseNode
* pn
, MutableHandleValue dst
);
1798 bool comprehension(ParseNode
* pn
, MutableHandleValue dst
);
1799 bool generatorExpression(ParseNode
* pn
, MutableHandleValue dst
);
1802 ASTSerializer(JSContext
* c
, bool l
, char const* src
, uint32_t ln
)
1804 , builder(c
, l
, src
)
1810 bool init(HandleObject userobj
) {
1811 return builder
.init(userobj
);
1814 void setParser(Parser
<FullParseHandler
>* p
) {
1816 builder
.setTokenStream(&p
->tokenStream
);
1819 bool program(ParseNode
* pn
, MutableHandleValue dst
);
1822 } /* anonymous namespace */
1825 ASTSerializer::aop(JSOp op
)
1858 ASTSerializer::unop(ParseNodeKind kind
, JSOp op
)
1860 if (kind
== PNK_DELETE
)
1873 case JSOP_TYPEOFEXPR
:
1883 ASTSerializer::binop(ParseNodeKind kind
, JSOp op
)
1905 return BINOP_STRICTEQ
;
1907 return BINOP_STRICTNE
;
1921 return BINOP_BITXOR
;
1923 return BINOP_BITAND
;
1926 case PNK_INSTANCEOF
:
1927 return BINOP_INSTANCEOF
;
1934 ASTSerializer::statements(ParseNode
* pn
, NodeVector
& elts
)
1936 MOZ_ASSERT(pn
->isKind(PNK_STATEMENTLIST
));
1937 MOZ_ASSERT(pn
->isArity(PN_LIST
));
1939 if (!elts
.reserve(pn
->pn_count
))
1942 for (ParseNode
* next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
1943 MOZ_ASSERT(pn
->pn_pos
.encloses(next
->pn_pos
));
1945 RootedValue
elt(cx
);
1946 if (!sourceElement(next
, &elt
))
1948 elts
.infallibleAppend(elt
);
1955 ASTSerializer::expressions(ParseNode
* pn
, NodeVector
& elts
)
1957 if (!elts
.reserve(pn
->pn_count
))
1960 for (ParseNode
* next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
1961 MOZ_ASSERT(pn
->pn_pos
.encloses(next
->pn_pos
));
1963 RootedValue
elt(cx
);
1964 if (!expression(next
, &elt
))
1966 elts
.infallibleAppend(elt
);
1973 ASTSerializer::blockStatement(ParseNode
* pn
, MutableHandleValue dst
)
1975 MOZ_ASSERT(pn
->isKind(PNK_STATEMENTLIST
));
1977 NodeVector
stmts(cx
);
1978 return statements(pn
, stmts
) &&
1979 builder
.blockStatement(stmts
, &pn
->pn_pos
, dst
);
1983 ASTSerializer::program(ParseNode
* pn
, MutableHandleValue dst
)
1985 MOZ_ASSERT(parser
->tokenStream
.srcCoords
.lineNum(pn
->pn_pos
.begin
) == lineno
);
1987 NodeVector
stmts(cx
);
1988 return statements(pn
, stmts
) &&
1989 builder
.program(stmts
, &pn
->pn_pos
, dst
);
1993 ASTSerializer::sourceElement(ParseNode
* pn
, MutableHandleValue dst
)
1995 /* SpiderMonkey allows declarations even in pure statement contexts. */
1996 return statement(pn
, dst
);
2000 ASTSerializer::declaration(ParseNode
* pn
, MutableHandleValue dst
)
2002 MOZ_ASSERT(pn
->isKind(PNK_FUNCTION
) ||
2003 pn
->isKind(PNK_VAR
) ||
2004 pn
->isKind(PNK_GLOBALCONST
) ||
2005 pn
->isKind(PNK_LET
) ||
2006 pn
->isKind(PNK_CONST
));
2008 switch (pn
->getKind()) {
2010 return function(pn
, AST_FUNC_DECL
, dst
);
2013 case PNK_GLOBALCONST
:
2014 return variableDeclaration(pn
, false, dst
);
2017 MOZ_ASSERT(pn
->isKind(PNK_LET
) || pn
->isKind(PNK_CONST
));
2018 return variableDeclaration(pn
, true, dst
);
2023 ASTSerializer::variableDeclaration(ParseNode
* pn
, bool lexical
, MutableHandleValue dst
)
2025 MOZ_ASSERT_IF(lexical
, pn
->isKind(PNK_LET
) || pn
->isKind(PNK_CONST
));
2026 MOZ_ASSERT_IF(!lexical
, pn
->isKind(PNK_VAR
) || pn
->isKind(PNK_GLOBALCONST
));
2028 VarDeclKind kind
= VARDECL_ERR
;
2029 // Treat both the toplevel const binding (secretly var-like) and the lexical const
2032 kind
= pn
->isKind(PNK_LET
) ? VARDECL_LET
: VARDECL_CONST
;
2034 kind
= pn
->isKind(PNK_VAR
) ? VARDECL_VAR
: VARDECL_CONST
;
2036 NodeVector
dtors(cx
);
2037 if (!dtors
.reserve(pn
->pn_count
))
2039 for (ParseNode
* next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
2040 RootedValue
child(cx
);
2041 if (!variableDeclarator(next
, &child
))
2043 dtors
.infallibleAppend(child
);
2045 return builder
.variableDeclaration(dtors
, kind
, &pn
->pn_pos
, dst
);
2049 ASTSerializer::variableDeclarator(ParseNode
* pn
, MutableHandleValue dst
)
2054 if (pn
->isKind(PNK_NAME
)) {
2056 pnright
= pn
->isUsed() ? nullptr : pn
->pn_expr
;
2057 MOZ_ASSERT_IF(pnright
, pn
->pn_pos
.encloses(pnright
->pn_pos
));
2058 } else if (pn
->isKind(PNK_ASSIGN
)) {
2059 pnleft
= pn
->pn_left
;
2060 pnright
= pn
->pn_right
;
2061 MOZ_ASSERT(pn
->pn_pos
.encloses(pnleft
->pn_pos
));
2062 MOZ_ASSERT(pn
->pn_pos
.encloses(pnright
->pn_pos
));
2064 /* This happens for a destructuring declarator in a for-in/of loop. */
2069 RootedValue
left(cx
), right(cx
);
2070 return pattern(pnleft
, &left
) &&
2071 optExpression(pnright
, &right
) &&
2072 builder
.variableDeclarator(left
, right
, &pn
->pn_pos
, dst
);
2076 ASTSerializer::let(ParseNode
* pn
, bool expr
, MutableHandleValue dst
)
2078 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
2079 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_right
->pn_pos
));
2081 ParseNode
* letHead
= pn
->pn_left
;
2082 LOCAL_ASSERT(letHead
->isArity(PN_LIST
));
2084 ParseNode
* letBody
= pn
->pn_right
;
2085 LOCAL_ASSERT(letBody
->isKind(PNK_LEXICALSCOPE
));
2087 NodeVector
dtors(cx
);
2088 if (!dtors
.reserve(letHead
->pn_count
))
2091 for (ParseNode
* next
= letHead
->pn_head
; next
; next
= next
->pn_next
) {
2092 RootedValue
child(cx
);
2094 if (!variableDeclarator(next
, &child
))
2096 dtors
.infallibleAppend(child
);
2101 ? expression(letBody
->pn_expr
, &v
) &&
2102 builder
.letExpression(dtors
, v
, &pn
->pn_pos
, dst
)
2103 : statement(letBody
->pn_expr
, &v
) &&
2104 builder
.letStatement(dtors
, v
, &pn
->pn_pos
, dst
);
2108 ASTSerializer::importDeclaration(ParseNode
* pn
, MutableHandleValue dst
)
2110 MOZ_ASSERT(pn
->isKind(PNK_IMPORT
));
2111 MOZ_ASSERT(pn
->pn_left
->isKind(PNK_IMPORT_SPEC_LIST
));
2112 MOZ_ASSERT(pn
->pn_right
->isKind(PNK_STRING
));
2114 NodeVector
elts(cx
);
2115 if (!elts
.reserve(pn
->pn_left
->pn_count
))
2118 for (ParseNode
* next
= pn
->pn_left
->pn_head
; next
; next
= next
->pn_next
) {
2119 RootedValue
elt(cx
);
2120 if (!importSpecifier(next
, &elt
))
2122 elts
.infallibleAppend(elt
);
2125 RootedValue
moduleSpec(cx
);
2126 return literal(pn
->pn_right
, &moduleSpec
) &&
2127 builder
.importDeclaration(elts
, moduleSpec
, &pn
->pn_pos
, dst
);
2131 ASTSerializer::importSpecifier(ParseNode
* pn
, MutableHandleValue dst
)
2133 MOZ_ASSERT(pn
->isKind(PNK_IMPORT_SPEC
));
2135 RootedValue
importName(cx
);
2136 RootedValue
bindingName(cx
);
2137 return identifier(pn
->pn_left
, &importName
) &&
2138 identifier(pn
->pn_right
, &bindingName
) &&
2139 builder
.importSpecifier(importName
, bindingName
, &pn
->pn_pos
, dst
);
2143 ASTSerializer::exportDeclaration(ParseNode
* pn
, MutableHandleValue dst
)
2145 MOZ_ASSERT(pn
->isKind(PNK_EXPORT
) || pn
->isKind(PNK_EXPORT_FROM
));
2146 MOZ_ASSERT_IF(pn
->isKind(PNK_EXPORT_FROM
), pn
->pn_right
->isKind(PNK_STRING
));
2148 RootedValue
decl(cx
, NullValue());
2149 NodeVector
elts(cx
);
2151 ParseNode
* kid
= pn
->isKind(PNK_EXPORT
) ? pn
->pn_kid
: pn
->pn_left
;
2152 switch (ParseNodeKind kind
= kid
->getKind()) {
2153 case PNK_EXPORT_SPEC_LIST
:
2154 if (!elts
.reserve(pn
->pn_left
->pn_count
))
2157 for (ParseNode
* next
= pn
->pn_left
->pn_head
; next
; next
= next
->pn_next
) {
2158 RootedValue
elt(cx
);
2159 if (next
->isKind(PNK_EXPORT_SPEC
)) {
2160 if (!exportSpecifier(next
, &elt
))
2163 if (!builder
.exportBatchSpecifier(&pn
->pn_pos
, &elt
))
2166 elts
.infallibleAppend(elt
);
2171 if (!function(kid
, AST_FUNC_DECL
, &decl
))
2177 case PNK_GLOBALCONST
:
2179 if (!variableDeclaration(kid
, kind
== PNK_LET
, &decl
))
2184 LOCAL_NOT_REACHED("unexpected statement type");
2187 RootedValue
moduleSpec(cx
, NullValue());
2188 if (pn
->isKind(PNK_EXPORT_FROM
) && !literal(pn
->pn_right
, &moduleSpec
))
2191 return builder
.exportDeclaration(decl
, elts
, moduleSpec
, &pn
->pn_pos
, dst
);
2195 ASTSerializer::exportSpecifier(ParseNode
* pn
, MutableHandleValue dst
)
2197 MOZ_ASSERT(pn
->isKind(PNK_EXPORT_SPEC
));
2199 RootedValue
bindingName(cx
);
2200 RootedValue
exportName(cx
);
2201 return identifier(pn
->pn_left
, &bindingName
) &&
2202 identifier(pn
->pn_right
, &exportName
) &&
2203 builder
.exportSpecifier(bindingName
, exportName
, &pn
->pn_pos
, dst
);
2207 ASTSerializer::switchCase(ParseNode
* pn
, MutableHandleValue dst
)
2209 MOZ_ASSERT_IF(pn
->pn_left
, pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
2210 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_right
->pn_pos
));
2212 NodeVector
stmts(cx
);
2214 RootedValue
expr(cx
);
2216 return optExpression(pn
->pn_left
, &expr
) &&
2217 statements(pn
->pn_right
, stmts
) &&
2218 builder
.switchCase(expr
, stmts
, &pn
->pn_pos
, dst
);
2222 ASTSerializer::switchStatement(ParseNode
* pn
, MutableHandleValue dst
)
2224 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
2225 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_right
->pn_pos
));
2227 RootedValue
disc(cx
);
2229 if (!expression(pn
->pn_left
, &disc
))
2232 ParseNode
* listNode
;
2235 if (pn
->pn_right
->isKind(PNK_LEXICALSCOPE
)) {
2236 listNode
= pn
->pn_right
->pn_expr
;
2239 listNode
= pn
->pn_right
;
2243 NodeVector
cases(cx
);
2244 if (!cases
.reserve(listNode
->pn_count
))
2247 for (ParseNode
* next
= listNode
->pn_head
; next
; next
= next
->pn_next
) {
2248 RootedValue
child(cx
);
2249 if (!switchCase(next
, &child
))
2251 cases
.infallibleAppend(child
);
2254 return builder
.switchStatement(disc
, cases
, lexical
, &pn
->pn_pos
, dst
);
2258 ASTSerializer::catchClause(ParseNode
* pn
, bool* isGuarded
, MutableHandleValue dst
)
2260 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid1
->pn_pos
));
2261 MOZ_ASSERT_IF(pn
->pn_kid2
, pn
->pn_pos
.encloses(pn
->pn_kid2
->pn_pos
));
2262 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid3
->pn_pos
));
2264 RootedValue
var(cx
), guard(cx
), body(cx
);
2266 if (!pattern(pn
->pn_kid1
, &var
) ||
2267 !optExpression(pn
->pn_kid2
, &guard
)) {
2271 *isGuarded
= !guard
.isMagic(JS_SERIALIZE_NO_NODE
);
2273 return statement(pn
->pn_kid3
, &body
) &&
2274 builder
.catchClause(var
, guard
, body
, &pn
->pn_pos
, dst
);
2278 ASTSerializer::tryStatement(ParseNode
* pn
, MutableHandleValue dst
)
2280 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid1
->pn_pos
));
2281 MOZ_ASSERT_IF(pn
->pn_kid2
, pn
->pn_pos
.encloses(pn
->pn_kid2
->pn_pos
));
2282 MOZ_ASSERT_IF(pn
->pn_kid3
, pn
->pn_pos
.encloses(pn
->pn_kid3
->pn_pos
));
2284 RootedValue
body(cx
);
2285 if (!statement(pn
->pn_kid1
, &body
))
2288 NodeVector
guarded(cx
);
2289 RootedValue
unguarded(cx
, NullValue());
2292 if (!guarded
.reserve(pn
->pn_kid2
->pn_count
))
2295 for (ParseNode
* next
= pn
->pn_kid2
->pn_head
; next
; next
= next
->pn_next
) {
2296 RootedValue
clause(cx
);
2298 if (!catchClause(next
->pn_expr
, &isGuarded
, &clause
))
2301 guarded
.infallibleAppend(clause
);
2307 RootedValue
finally(cx
);
2308 return optStatement(pn
->pn_kid3
, &finally
) &&
2309 builder
.tryStatement(body
, guarded
, unguarded
, finally
, &pn
->pn_pos
, dst
);
2313 ASTSerializer::forInit(ParseNode
* pn
, MutableHandleValue dst
)
2316 dst
.setMagic(JS_SERIALIZE_NO_NODE
);
2320 return (pn
->isKind(PNK_VAR
) || pn
->isKind(PNK_GLOBALCONST
))
2321 ? variableDeclaration(pn
, false, dst
)
2322 : expression(pn
, dst
);
2326 ASTSerializer::forOf(ParseNode
* loop
, ParseNode
* head
, HandleValue var
, HandleValue stmt
,
2327 MutableHandleValue dst
)
2329 RootedValue
expr(cx
);
2331 return expression(head
->pn_kid3
, &expr
) &&
2332 builder
.forOfStatement(var
, expr
, stmt
, &loop
->pn_pos
, dst
);
2336 ASTSerializer::forIn(ParseNode
* loop
, ParseNode
* head
, HandleValue var
, HandleValue stmt
,
2337 MutableHandleValue dst
)
2339 RootedValue
expr(cx
);
2340 bool isForEach
= loop
->pn_iflags
& JSITER_FOREACH
;
2342 return expression(head
->pn_kid3
, &expr
) &&
2343 builder
.forInStatement(var
, expr
, stmt
, isForEach
, &loop
->pn_pos
, dst
);
2347 ASTSerializer::statement(ParseNode
* pn
, MutableHandleValue dst
)
2349 JS_CHECK_RECURSION(cx
, return false);
2350 switch (pn
->getKind()) {
2353 case PNK_GLOBALCONST
:
2354 return declaration(pn
, dst
);
2358 return pn
->isArity(PN_BINARY
)
2359 ? let(pn
, false, dst
)
2360 : declaration(pn
, dst
);
2363 return importDeclaration(pn
, dst
);
2366 case PNK_EXPORT_FROM
:
2367 return exportDeclaration(pn
, dst
);
2370 LOCAL_ASSERT(pn
->isUsed());
2371 return statement(pn
->pn_lexdef
, dst
);
2375 RootedValue
expr(cx
);
2376 return expression(pn
->pn_kid
, &expr
) &&
2377 builder
.expressionStatement(expr
, &pn
->pn_pos
, dst
);
2379 return builder
.emptyStatement(&pn
->pn_pos
, dst
);
2381 case PNK_LEXICALSCOPE
:
2383 if (!pn
->isKind(PNK_STATEMENTLIST
))
2384 return statement(pn
, dst
);
2387 case PNK_STATEMENTLIST
:
2388 return blockStatement(pn
, dst
);
2392 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid1
->pn_pos
));
2393 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid2
->pn_pos
));
2394 MOZ_ASSERT_IF(pn
->pn_kid3
, pn
->pn_pos
.encloses(pn
->pn_kid3
->pn_pos
));
2396 RootedValue
test(cx
), cons(cx
), alt(cx
);
2398 return expression(pn
->pn_kid1
, &test
) &&
2399 statement(pn
->pn_kid2
, &cons
) &&
2400 optStatement(pn
->pn_kid3
, &alt
) &&
2401 builder
.ifStatement(test
, cons
, alt
, &pn
->pn_pos
, dst
);
2405 return switchStatement(pn
, dst
);
2408 return tryStatement(pn
, dst
);
2413 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
2414 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_right
->pn_pos
));
2416 RootedValue
expr(cx
), stmt(cx
);
2418 return expression(pn
->pn_left
, &expr
) &&
2419 statement(pn
->pn_right
, &stmt
) &&
2420 (pn
->isKind(PNK_WITH
)
2421 ? builder
.withStatement(expr
, stmt
, &pn
->pn_pos
, dst
)
2422 : builder
.whileStatement(expr
, stmt
, &pn
->pn_pos
, dst
));
2427 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
2428 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_right
->pn_pos
));
2430 RootedValue
stmt(cx
), test(cx
);
2432 return statement(pn
->pn_left
, &stmt
) &&
2433 expression(pn
->pn_right
, &test
) &&
2434 builder
.doWhileStatement(stmt
, test
, &pn
->pn_pos
, dst
);
2439 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
2440 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_right
->pn_pos
));
2442 ParseNode
* head
= pn
->pn_left
;
2444 MOZ_ASSERT_IF(head
->pn_kid1
, head
->pn_pos
.encloses(head
->pn_kid1
->pn_pos
));
2445 MOZ_ASSERT_IF(head
->pn_kid2
, head
->pn_pos
.encloses(head
->pn_kid2
->pn_pos
));
2446 MOZ_ASSERT_IF(head
->pn_kid3
, head
->pn_pos
.encloses(head
->pn_kid3
->pn_pos
));
2448 RootedValue
stmt(cx
);
2449 if (!statement(pn
->pn_right
, &stmt
))
2452 if (head
->isKind(PNK_FORIN
)) {
2453 RootedValue
var(cx
);
2454 return (!head
->pn_kid1
2455 ? pattern(head
->pn_kid2
, &var
)
2456 : head
->pn_kid1
->isKind(PNK_LEXICALSCOPE
)
2457 ? variableDeclaration(head
->pn_kid1
->pn_expr
, true, &var
)
2458 : variableDeclaration(head
->pn_kid1
, false, &var
)) &&
2459 forIn(pn
, head
, var
, stmt
, dst
);
2462 if (head
->isKind(PNK_FOROF
)) {
2463 RootedValue
var(cx
);
2464 return (!head
->pn_kid1
2465 ? pattern(head
->pn_kid2
, &var
)
2466 : head
->pn_kid1
->isKind(PNK_LEXICALSCOPE
)
2467 ? variableDeclaration(head
->pn_kid1
->pn_expr
, true, &var
)
2468 : variableDeclaration(head
->pn_kid1
, false, &var
)) &&
2469 forOf(pn
, head
, var
, stmt
, dst
);
2472 RootedValue
init(cx
), test(cx
), update(cx
);
2474 return forInit(head
->pn_kid1
, &init
) &&
2475 optExpression(head
->pn_kid2
, &test
) &&
2476 optExpression(head
->pn_kid3
, &update
) &&
2477 builder
.forStatement(init
, test
, update
, stmt
, &pn
->pn_pos
, dst
);
2480 /* Synthesized by the parser when a for-in loop contains a variable initializer. */
2483 LOCAL_ASSERT(pn
->pn_count
== 2);
2485 ParseNode
* prelude
= pn
->pn_head
;
2486 ParseNode
* loop
= prelude
->pn_next
;
2488 LOCAL_ASSERT(prelude
->isKind(PNK_VAR
) && loop
->isKind(PNK_FOR
));
2490 RootedValue
var(cx
);
2491 if (!variableDeclaration(prelude
, false, &var
))
2494 ParseNode
* head
= loop
->pn_left
;
2495 MOZ_ASSERT(head
->isKind(PNK_FORIN
));
2497 RootedValue
stmt(cx
);
2499 return statement(loop
->pn_right
, &stmt
) && forIn(loop
, head
, var
, stmt
, dst
);
2505 RootedValue
label(cx
);
2506 RootedAtom
pnAtom(cx
, pn
->pn_atom
);
2507 return optIdentifier(pnAtom
, nullptr, &label
) &&
2508 (pn
->isKind(PNK_BREAK
)
2509 ? builder
.breakStatement(label
, &pn
->pn_pos
, dst
)
2510 : builder
.continueStatement(label
, &pn
->pn_pos
, dst
));
2515 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_expr
->pn_pos
));
2517 RootedValue
label(cx
), stmt(cx
);
2518 RootedAtom
pnAtom(cx
, pn
->as
<LabeledStatement
>().label());
2519 return identifier(pnAtom
, nullptr, &label
) &&
2520 statement(pn
->pn_expr
, &stmt
) &&
2521 builder
.labeledStatement(label
, stmt
, &pn
->pn_pos
, dst
);
2526 MOZ_ASSERT_IF(pn
->pn_kid
, pn
->pn_pos
.encloses(pn
->pn_kid
->pn_pos
));
2528 RootedValue
arg(cx
);
2530 return optExpression(pn
->pn_kid
, &arg
) &&
2531 builder
.throwStatement(arg
, &pn
->pn_pos
, dst
);
2536 MOZ_ASSERT_IF(pn
->pn_left
, pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
2538 RootedValue
arg(cx
);
2540 return optExpression(pn
->pn_left
, &arg
) &&
2541 builder
.returnStatement(arg
, &pn
->pn_pos
, dst
);
2545 return builder
.debuggerStatement(&pn
->pn_pos
, dst
);
2548 return builder
.emptyStatement(&pn
->pn_pos
, dst
);
2551 LOCAL_NOT_REACHED("unexpected statement type");
2556 ASTSerializer::leftAssociate(ParseNode
* pn
, MutableHandleValue dst
)
2558 MOZ_ASSERT(pn
->isArity(PN_LIST
));
2559 MOZ_ASSERT(pn
->pn_count
>= 1);
2561 ParseNodeKind kind
= pn
->getKind();
2562 bool lor
= kind
== PNK_OR
;
2563 bool logop
= lor
|| (kind
== PNK_AND
);
2565 ParseNode
* head
= pn
->pn_head
;
2566 RootedValue
left(cx
);
2567 if (!expression(head
, &left
))
2569 for (ParseNode
* next
= head
->pn_next
; next
; next
= next
->pn_next
) {
2570 RootedValue
right(cx
);
2571 if (!expression(next
, &right
))
2574 TokenPos
subpos(pn
->pn_pos
.begin
, next
->pn_pos
.end
);
2577 if (!builder
.logicalExpression(lor
, left
, right
, &subpos
, &left
))
2580 BinaryOperator op
= binop(pn
->getKind(), pn
->getOp());
2581 LOCAL_ASSERT(op
> BINOP_ERR
&& op
< BINOP_LIMIT
);
2583 if (!builder
.binaryExpression(op
, left
, right
, &subpos
, &left
))
2593 ASTSerializer::comprehensionBlock(ParseNode
* pn
, MutableHandleValue dst
)
2595 LOCAL_ASSERT(pn
->isArity(PN_BINARY
));
2597 ParseNode
* in
= pn
->pn_left
;
2599 LOCAL_ASSERT(in
&& (in
->isKind(PNK_FORIN
) || in
->isKind(PNK_FOROF
)));
2601 bool isForEach
= in
->isKind(PNK_FORIN
) && (pn
->pn_iflags
& JSITER_FOREACH
);
2602 bool isForOf
= in
->isKind(PNK_FOROF
);
2604 RootedValue
patt(cx
), src(cx
);
2605 return pattern(in
->pn_kid2
, &patt
) &&
2606 expression(in
->pn_kid3
, &src
) &&
2607 builder
.comprehensionBlock(patt
, src
, isForEach
, isForOf
, &in
->pn_pos
, dst
);
2611 ASTSerializer::comprehension(ParseNode
* pn
, MutableHandleValue dst
)
2613 // There are two array comprehension flavors.
2614 // 1. The kind that was in ES4 for a while: [z for (x in y)]
2615 // 2. The kind that was in ES6 for a while: [for (x of y) z]
2616 // They have slightly different parse trees and scoping.
2617 bool isLegacy
= pn
->isKind(PNK_LEXICALSCOPE
);
2618 ParseNode
* next
= isLegacy
? pn
->pn_expr
: pn
;
2619 LOCAL_ASSERT(next
->isKind(PNK_FOR
));
2621 NodeVector
blocks(cx
);
2623 while (next
->isKind(PNK_FOR
)) {
2624 RootedValue
block(cx
);
2625 if (!comprehensionBlock(next
, &block
) || !blocks
.append(block
))
2627 next
= next
->pn_right
;
2630 RootedValue
filter(cx
, MagicValue(JS_SERIALIZE_NO_NODE
));
2632 if (next
->isKind(PNK_IF
)) {
2633 if (!optExpression(next
->pn_kid1
, &filter
))
2635 next
= next
->pn_kid2
;
2636 } else if (next
->isKind(PNK_STATEMENTLIST
) && next
->pn_count
== 0) {
2637 /* FoldConstants optimized away the push. */
2638 NodeVector
empty(cx
);
2639 return builder
.arrayExpression(empty
, &pn
->pn_pos
, dst
);
2642 LOCAL_ASSERT(next
->isKind(PNK_ARRAYPUSH
));
2644 RootedValue
body(cx
);
2646 return expression(next
->pn_kid
, &body
) &&
2647 builder
.comprehensionExpression(body
, blocks
, filter
, isLegacy
, &pn
->pn_pos
, dst
);
2651 ASTSerializer::generatorExpression(ParseNode
* pn
, MutableHandleValue dst
)
2653 // Just as there are two kinds of array comprehension (see
2654 // ASTSerializer::comprehension), there are legacy and modern generator
2656 bool isLegacy
= pn
->isKind(PNK_LEXICALSCOPE
);
2657 ParseNode
* next
= isLegacy
? pn
->pn_expr
: pn
;
2658 LOCAL_ASSERT(next
->isKind(PNK_FOR
));
2660 NodeVector
blocks(cx
);
2662 while (next
->isKind(PNK_FOR
)) {
2663 RootedValue
block(cx
);
2664 if (!comprehensionBlock(next
, &block
) || !blocks
.append(block
))
2666 next
= next
->pn_right
;
2669 RootedValue
filter(cx
, MagicValue(JS_SERIALIZE_NO_NODE
));
2671 if (next
->isKind(PNK_IF
)) {
2672 if (!optExpression(next
->pn_kid1
, &filter
))
2674 next
= next
->pn_kid2
;
2677 LOCAL_ASSERT(next
->isKind(PNK_SEMI
) &&
2678 next
->pn_kid
->isKind(PNK_YIELD
) &&
2679 next
->pn_kid
->pn_left
);
2681 RootedValue
body(cx
);
2683 return expression(next
->pn_kid
->pn_left
, &body
) &&
2684 builder
.generatorExpression(body
, blocks
, filter
, isLegacy
, &pn
->pn_pos
, dst
);
2688 ASTSerializer::expression(ParseNode
* pn
, MutableHandleValue dst
)
2690 JS_CHECK_RECURSION(cx
, return false);
2691 switch (pn
->getKind()) {
2694 ASTType type
= pn
->pn_funbox
->function()->isArrow() ? AST_ARROW_EXPR
: AST_FUNC_EXPR
;
2695 return function(pn
, type
, dst
);
2700 NodeVector
exprs(cx
);
2701 return expressions(pn
, exprs
) &&
2702 builder
.sequenceExpression(exprs
, &pn
->pn_pos
, dst
);
2705 case PNK_CONDITIONAL
:
2707 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid1
->pn_pos
));
2708 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid2
->pn_pos
));
2709 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid3
->pn_pos
));
2711 RootedValue
test(cx
), cons(cx
), alt(cx
);
2713 return expression(pn
->pn_kid1
, &test
) &&
2714 expression(pn
->pn_kid2
, &cons
) &&
2715 expression(pn
->pn_kid3
, &alt
) &&
2716 builder
.conditionalExpression(test
, cons
, alt
, &pn
->pn_pos
, dst
);
2722 if (pn
->isArity(PN_BINARY
)) {
2723 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
2724 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_right
->pn_pos
));
2726 RootedValue
left(cx
), right(cx
);
2727 return expression(pn
->pn_left
, &left
) &&
2728 expression(pn
->pn_right
, &right
) &&
2729 builder
.logicalExpression(pn
->isKind(PNK_OR
), left
, right
, &pn
->pn_pos
, dst
);
2731 return leftAssociate(pn
, dst
);
2734 case PNK_PREINCREMENT
:
2735 case PNK_PREDECREMENT
:
2737 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid
->pn_pos
));
2739 bool inc
= pn
->isKind(PNK_PREINCREMENT
);
2740 RootedValue
expr(cx
);
2741 return expression(pn
->pn_kid
, &expr
) &&
2742 builder
.updateExpression(expr
, inc
, true, &pn
->pn_pos
, dst
);
2745 case PNK_POSTINCREMENT
:
2746 case PNK_POSTDECREMENT
:
2748 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid
->pn_pos
));
2750 bool inc
= pn
->isKind(PNK_POSTINCREMENT
);
2751 RootedValue
expr(cx
);
2752 return expression(pn
->pn_kid
, &expr
) &&
2753 builder
.updateExpression(expr
, inc
, false, &pn
->pn_pos
, dst
);
2759 case PNK_BITORASSIGN
:
2760 case PNK_BITXORASSIGN
:
2761 case PNK_BITANDASSIGN
:
2764 case PNK_URSHASSIGN
:
2769 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
2770 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_right
->pn_pos
));
2772 AssignmentOperator op
= aop(pn
->getOp());
2773 LOCAL_ASSERT(op
> AOP_ERR
&& op
< AOP_LIMIT
);
2775 RootedValue
lhs(cx
), rhs(cx
);
2776 return pattern(pn
->pn_left
, &lhs
) &&
2777 expression(pn
->pn_right
, &rhs
) &&
2778 builder
.assignmentExpression(op
, lhs
, rhs
, &pn
->pn_pos
, dst
);
2801 case PNK_INSTANCEOF
:
2802 if (pn
->isArity(PN_BINARY
)) {
2803 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
2804 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_right
->pn_pos
));
2806 BinaryOperator op
= binop(pn
->getKind(), pn
->getOp());
2807 LOCAL_ASSERT(op
> BINOP_ERR
&& op
< BINOP_LIMIT
);
2809 RootedValue
left(cx
), right(cx
);
2810 return expression(pn
->pn_left
, &left
) &&
2811 expression(pn
->pn_right
, &right
) &&
2812 builder
.binaryExpression(op
, left
, right
, &pn
->pn_pos
, dst
);
2814 return leftAssociate(pn
, dst
);
2823 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid
->pn_pos
));
2825 UnaryOperator op
= unop(pn
->getKind(), pn
->getOp());
2826 LOCAL_ASSERT(op
> UNOP_ERR
&& op
< UNOP_LIMIT
);
2828 RootedValue
expr(cx
);
2829 return expression(pn
->pn_kid
, &expr
) &&
2830 builder
.unaryExpression(op
, expr
, &pn
->pn_pos
, dst
);
2833 #if JS_HAS_GENERATOR_EXPRS
2835 return generatorExpression(pn
->generatorExpr(), dst
);
2839 case PNK_TAGGED_TEMPLATE
:
2842 ParseNode
* next
= pn
->pn_head
;
2843 MOZ_ASSERT(pn
->pn_pos
.encloses(next
->pn_pos
));
2845 RootedValue
callee(cx
);
2846 if (!expression(next
, &callee
))
2849 NodeVector
args(cx
);
2850 if (!args
.reserve(pn
->pn_count
- 1))
2853 for (next
= next
->pn_next
; next
; next
= next
->pn_next
) {
2854 MOZ_ASSERT(pn
->pn_pos
.encloses(next
->pn_pos
));
2856 RootedValue
arg(cx
);
2857 if (!expression(next
, &arg
))
2859 args
.infallibleAppend(arg
);
2862 if (pn
->getKind() == PNK_TAGGED_TEMPLATE
)
2863 return builder
.taggedTemplate(callee
, args
, &pn
->pn_pos
, dst
);
2865 return pn
->isKind(PNK_NEW
)
2866 ? builder
.newExpression(callee
, args
, &pn
->pn_pos
, dst
)
2868 : builder
.callExpression(callee
, args
, &pn
->pn_pos
, dst
);
2873 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_expr
->pn_pos
));
2875 RootedValue
expr(cx
), id(cx
);
2876 RootedAtom
pnAtom(cx
, pn
->pn_atom
);
2877 return expression(pn
->pn_expr
, &expr
) &&
2878 identifier(pnAtom
, nullptr, &id
) &&
2879 builder
.memberExpression(false, expr
, id
, &pn
->pn_pos
, dst
);
2884 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
2885 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_right
->pn_pos
));
2887 RootedValue
left(cx
), right(cx
);
2888 return expression(pn
->pn_left
, &left
) &&
2889 expression(pn
->pn_right
, &right
) &&
2890 builder
.memberExpression(true, left
, right
, &pn
->pn_pos
, dst
);
2893 case PNK_CALLSITEOBJ
:
2896 if (!raw
.reserve(pn
->pn_head
->pn_count
))
2898 for (ParseNode
* next
= pn
->pn_head
->pn_head
; next
; next
= next
->pn_next
) {
2899 MOZ_ASSERT(pn
->pn_pos
.encloses(next
->pn_pos
));
2901 RootedValue
expr(cx
);
2902 expr
.setString(next
->pn_atom
);
2903 raw
.infallibleAppend(expr
);
2906 NodeVector
cooked(cx
);
2907 if (!cooked
.reserve(pn
->pn_count
- 1))
2910 for (ParseNode
* next
= pn
->pn_head
->pn_next
; next
; next
= next
->pn_next
) {
2911 MOZ_ASSERT(pn
->pn_pos
.encloses(next
->pn_pos
));
2913 RootedValue
expr(cx
);
2914 expr
.setString(next
->pn_atom
);
2915 cooked
.infallibleAppend(expr
);
2918 return builder
.callSiteObj(raw
, cooked
, &pn
->pn_pos
, dst
);
2923 NodeVector
elts(cx
);
2924 if (!elts
.reserve(pn
->pn_count
))
2927 for (ParseNode
* next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
2928 MOZ_ASSERT(pn
->pn_pos
.encloses(next
->pn_pos
));
2930 if (next
->isKind(PNK_ELISION
)) {
2931 elts
.infallibleAppend(NullValue());
2933 RootedValue
expr(cx
);
2934 if (!expression(next
, &expr
))
2936 elts
.infallibleAppend(expr
);
2940 return builder
.arrayExpression(elts
, &pn
->pn_pos
, dst
);
2945 RootedValue
expr(cx
);
2946 return expression(pn
->pn_kid
, &expr
) &&
2947 builder
.spreadExpression(expr
, &pn
->pn_pos
, dst
);
2950 case PNK_COMPUTED_NAME
:
2952 RootedValue
name(cx
);
2953 return expression(pn
->pn_kid
, &name
) &&
2954 builder
.computedName(name
, &pn
->pn_pos
, dst
);
2959 NodeVector
elts(cx
);
2960 if (!elts
.reserve(pn
->pn_count
))
2963 for (ParseNode
* next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
2964 MOZ_ASSERT(pn
->pn_pos
.encloses(next
->pn_pos
));
2966 RootedValue
prop(cx
);
2967 if (!property(next
, &prop
))
2969 elts
.infallibleAppend(prop
);
2972 return builder
.objectExpression(elts
, &pn
->pn_pos
, dst
);
2976 return identifier(pn
, dst
);
2979 return builder
.thisExpression(&pn
->pn_pos
, dst
);
2981 case PNK_TEMPLATE_STRING_LIST
:
2983 NodeVector
elts(cx
);
2984 if (!elts
.reserve(pn
->pn_count
))
2987 for (ParseNode
* next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
2988 MOZ_ASSERT(pn
->pn_pos
.encloses(next
->pn_pos
));
2990 RootedValue
expr(cx
);
2991 if (!expression(next
, &expr
))
2993 elts
.infallibleAppend(expr
);
2996 return builder
.templateLiteral(elts
, &pn
->pn_pos
, dst
);
2999 case PNK_TEMPLATE_STRING
:
3006 return literal(pn
, dst
);
3008 case PNK_YIELD_STAR
:
3010 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
3012 RootedValue
arg(cx
);
3013 return expression(pn
->pn_left
, &arg
) &&
3014 builder
.yieldExpression(arg
, Delegating
, &pn
->pn_pos
, dst
);
3019 MOZ_ASSERT_IF(pn
->pn_left
, pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
3021 RootedValue
arg(cx
);
3022 return optExpression(pn
->pn_left
, &arg
) &&
3023 builder
.yieldExpression(arg
, NotDelegating
, &pn
->pn_pos
, dst
);
3027 MOZ_ASSERT(pn
->pn_pos
.encloses(pn
->pn_head
->pn_pos
));
3029 /* NB: it's no longer the case that pn_count could be 2. */
3030 LOCAL_ASSERT(pn
->pn_count
== 1);
3031 return comprehension(pn
->pn_head
, dst
);
3034 return let(pn
, true, dst
);
3037 LOCAL_NOT_REACHED("unexpected expression type");
3042 ASTSerializer::propertyName(ParseNode
* pn
, MutableHandleValue dst
)
3044 if (pn
->isKind(PNK_COMPUTED_NAME
))
3045 return expression(pn
, dst
);
3046 if (pn
->isKind(PNK_NAME
))
3047 return identifier(pn
, dst
);
3049 LOCAL_ASSERT(pn
->isKind(PNK_STRING
) || pn
->isKind(PNK_NUMBER
));
3051 return literal(pn
, dst
);
3055 ASTSerializer::property(ParseNode
* pn
, MutableHandleValue dst
)
3057 if (pn
->isKind(PNK_MUTATEPROTO
)) {
3058 RootedValue
val(cx
);
3059 return expression(pn
->pn_kid
, &val
) &&
3060 builder
.prototypeMutation(val
, &pn
->pn_pos
, dst
);
3064 switch (pn
->getOp()) {
3069 case JSOP_INITPROP_GETTER
:
3073 case JSOP_INITPROP_SETTER
:
3078 LOCAL_NOT_REACHED("unexpected object-literal property");
3081 bool isShorthand
= pn
->isKind(PNK_SHORTHAND
);
3082 bool isMethod
= pn
->pn_right
->isKind(PNK_FUNCTION
) && kind
== PROP_INIT
;
3083 RootedValue
key(cx
), val(cx
);
3084 return propertyName(pn
->pn_left
, &key
) &&
3085 expression(pn
->pn_right
, &val
) &&
3086 builder
.propertyInitializer(key
, val
, kind
, isShorthand
, isMethod
, &pn
->pn_pos
, dst
);
3090 ASTSerializer::literal(ParseNode
* pn
, MutableHandleValue dst
)
3092 RootedValue
val(cx
);
3093 switch (pn
->getKind()) {
3094 case PNK_TEMPLATE_STRING
:
3096 val
.setString(pn
->pn_atom
);
3101 RootedObject
re1(cx
, pn
->as
<RegExpLiteral
>().objbox()->object
);
3102 LOCAL_ASSERT(re1
&& re1
->is
<RegExpObject
>());
3104 RootedObject
re2(cx
, CloneRegExpObject(cx
, re1
));
3108 val
.setObject(*re2
);
3113 val
.setNumber(pn
->pn_dval
);
3121 val
.setBoolean(true);
3125 val
.setBoolean(false);
3129 LOCAL_NOT_REACHED("unexpected literal type");
3132 return builder
.literal(val
, &pn
->pn_pos
, dst
);
3136 ASTSerializer::arrayPattern(ParseNode
* pn
, MutableHandleValue dst
)
3138 MOZ_ASSERT(pn
->isKind(PNK_ARRAY
));
3140 NodeVector
elts(cx
);
3141 if (!elts
.reserve(pn
->pn_count
))
3144 for (ParseNode
* next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
3145 if (next
->isKind(PNK_ELISION
)) {
3146 elts
.infallibleAppend(NullValue());
3147 } else if (next
->isKind(PNK_SPREAD
)) {
3148 RootedValue
target(cx
);
3149 RootedValue
spread(cx
);
3150 if (!pattern(next
->pn_kid
, &target
))
3152 if(!builder
.spreadExpression(target
, &next
->pn_pos
, &spread
))
3154 elts
.infallibleAppend(spread
);
3156 RootedValue
patt(cx
);
3157 if (!pattern(next
, &patt
))
3159 elts
.infallibleAppend(patt
);
3163 return builder
.arrayPattern(elts
, &pn
->pn_pos
, dst
);
3167 ASTSerializer::objectPattern(ParseNode
* pn
, MutableHandleValue dst
)
3169 MOZ_ASSERT(pn
->isKind(PNK_OBJECT
));
3171 NodeVector
elts(cx
);
3172 if (!elts
.reserve(pn
->pn_count
))
3175 for (ParseNode
* propdef
= pn
->pn_head
; propdef
; propdef
= propdef
->pn_next
) {
3176 LOCAL_ASSERT(propdef
->isKind(PNK_MUTATEPROTO
) != propdef
->isOp(JSOP_INITPROP
));
3178 RootedValue
key(cx
);
3180 if (propdef
->isKind(PNK_MUTATEPROTO
)) {
3181 RootedValue
pname(cx
, StringValue(cx
->names().proto
));
3182 if (!builder
.literal(pname
, &propdef
->pn_pos
, &key
))
3184 target
= propdef
->pn_kid
;
3186 if (!propertyName(propdef
->pn_left
, &key
))
3188 target
= propdef
->pn_right
;
3191 RootedValue
patt(cx
), prop(cx
);
3192 if (!pattern(target
, &patt
) ||
3193 !builder
.propertyPattern(key
, patt
, propdef
->isKind(PNK_SHORTHAND
), &propdef
->pn_pos
,
3199 elts
.infallibleAppend(prop
);
3202 return builder
.objectPattern(elts
, &pn
->pn_pos
, dst
);
3206 ASTSerializer::pattern(ParseNode
* pn
, MutableHandleValue dst
)
3208 JS_CHECK_RECURSION(cx
, return false);
3209 switch (pn
->getKind()) {
3211 return objectPattern(pn
, dst
);
3214 return arrayPattern(pn
, dst
);
3217 return expression(pn
, dst
);
3222 ASTSerializer::identifier(HandleAtom atom
, TokenPos
* pos
, MutableHandleValue dst
)
3224 RootedValue
atomContentsVal(cx
, unrootedAtomContents(atom
));
3225 return builder
.identifier(atomContentsVal
, pos
, dst
);
3229 ASTSerializer::identifier(ParseNode
* pn
, MutableHandleValue dst
)
3231 LOCAL_ASSERT(pn
->isArity(PN_NAME
) || pn
->isArity(PN_NULLARY
));
3232 LOCAL_ASSERT(pn
->pn_atom
);
3234 RootedAtom
pnAtom(cx
, pn
->pn_atom
);
3235 return identifier(pnAtom
, &pn
->pn_pos
, dst
);
3239 ASTSerializer::function(ParseNode
* pn
, ASTType type
, MutableHandleValue dst
)
3241 RootedFunction
func(cx
, pn
->pn_funbox
->function());
3243 // FIXME: Provide more information (legacy generator vs star generator).
3244 bool isGenerator
= pn
->pn_funbox
->isGenerator();
3247 #if JS_HAS_EXPR_CLOSURES
3248 func
->isExprClosure();
3254 RootedAtom
funcAtom(cx
, func
->atom());
3255 if (!optIdentifier(funcAtom
, nullptr, &id
))
3258 NodeVector
args(cx
);
3259 NodeVector
defaults(cx
);
3261 RootedValue
body(cx
), rest(cx
);
3262 if (func
->hasRest())
3263 rest
.setUndefined();
3266 return functionArgsAndBody(pn
->pn_body
, args
, defaults
, &body
, &rest
) &&
3267 builder
.function(type
, &pn
->pn_pos
, id
, args
, defaults
, body
,
3268 rest
, isGenerator
, isExpression
, dst
);
3272 ASTSerializer::functionArgsAndBody(ParseNode
* pn
, NodeVector
& args
, NodeVector
& defaults
,
3273 MutableHandleValue body
, MutableHandleValue rest
)
3278 /* Extract the args and body separately. */
3279 if (pn
->isKind(PNK_ARGSBODY
)) {
3281 pnbody
= pn
->last();
3287 ParseNode
* pndestruct
;
3289 /* Extract the destructuring assignments. */
3290 if (pnbody
->isArity(PN_LIST
) && (pnbody
->pn_xflags
& PNX_DESTRUCT
)) {
3291 ParseNode
* head
= pnbody
->pn_head
;
3292 LOCAL_ASSERT(head
&& head
->isKind(PNK_SEMI
));
3294 pndestruct
= head
->pn_kid
;
3295 LOCAL_ASSERT(pndestruct
);
3296 LOCAL_ASSERT(pndestruct
->isKind(PNK_VAR
));
3298 pndestruct
= nullptr;
3301 /* Serialize the arguments and body. */
3302 switch (pnbody
->getKind()) {
3303 case PNK_RETURN
: /* expression closure, no destructured args */
3304 return functionArgs(pn
, pnargs
, nullptr, pnbody
, args
, defaults
, rest
) &&
3305 expression(pnbody
->pn_left
, body
);
3307 case PNK_SEQ
: /* expression closure with destructured args */
3309 ParseNode
* pnstart
= pnbody
->pn_head
->pn_next
;
3310 LOCAL_ASSERT(pnstart
&& pnstart
->isKind(PNK_RETURN
));
3312 return functionArgs(pn
, pnargs
, pndestruct
, pnbody
, args
, defaults
, rest
) &&
3313 expression(pnstart
->pn_left
, body
);
3316 case PNK_STATEMENTLIST
: /* statement closure */
3318 ParseNode
* pnstart
= (pnbody
->pn_xflags
& PNX_DESTRUCT
)
3319 ? pnbody
->pn_head
->pn_next
3322 // Skip over initial yield in generator.
3323 if (pnstart
&& pnstart
->isKind(PNK_YIELD
)) {
3324 MOZ_ASSERT(pnstart
->getOp() == JSOP_INITIALYIELD
);
3325 pnstart
= pnstart
->pn_next
;
3328 return functionArgs(pn
, pnargs
, pndestruct
, pnbody
, args
, defaults
, rest
) &&
3329 functionBody(pnstart
, &pnbody
->pn_pos
, body
);
3333 LOCAL_NOT_REACHED("unexpected function contents");
3338 ASTSerializer::functionArgs(ParseNode
* pn
, ParseNode
* pnargs
, ParseNode
* pndestruct
,
3339 ParseNode
* pnbody
, NodeVector
& args
, NodeVector
& defaults
,
3340 MutableHandleValue rest
)
3343 ParseNode
* arg
= pnargs
? pnargs
->pn_head
: nullptr;
3344 ParseNode
* destruct
= pndestruct
? pndestruct
->pn_head
: nullptr;
3345 RootedValue
node(cx
);
3348 * Arguments are found in potentially two different places: 1) the
3349 * argsbody sequence (which ends with the body node), or 2) a
3350 * destructuring initialization at the beginning of the body. Loop
3351 * |arg| through the argsbody and |destruct| through the initial
3352 * destructuring assignments, stopping only when we've exhausted
3355 while ((arg
&& arg
!= pnbody
) || destruct
) {
3356 if (destruct
&& destruct
->pn_right
->frameSlot() == i
) {
3357 if (!pattern(destruct
->pn_left
, &node
) || !args
.append(node
))
3359 destruct
= destruct
->pn_next
;
3360 } else if (arg
&& arg
!= pnbody
) {
3362 * We don't check that arg->frameSlot() == i since we
3363 * can't call that method if the arg def has been turned
3366 * function(a) { function a() { } }
3368 * There's no other way to ask a non-destructuring arg its
3369 * index in the formals list, so we rely on the ability to
3370 * ask destructuring args their index above.
3372 MOZ_ASSERT(arg
->isKind(PNK_NAME
) || arg
->isKind(PNK_ASSIGN
));
3373 ParseNode
* argName
= arg
->isKind(PNK_NAME
) ? arg
: arg
->pn_left
;
3374 if (!identifier(argName
, &node
))
3376 if (rest
.isUndefined() && arg
->pn_next
== pnbody
)
3377 rest
.setObject(node
.toObject());
3378 else if (!args
.append(node
))
3380 if (arg
->pn_dflags
& PND_DEFAULT
) {
3381 ParseNode
* expr
= arg
->expr();
3382 RootedValue
def(cx
);
3383 if (!expression(expr
, &def
) || !defaults
.append(def
))
3388 LOCAL_NOT_REACHED("missing function argument");
3392 MOZ_ASSERT(!rest
.isUndefined());
3398 ASTSerializer::functionBody(ParseNode
* pn
, TokenPos
* pos
, MutableHandleValue dst
)
3400 NodeVector
elts(cx
);
3402 /* We aren't sure how many elements there are up front, so we'll check each append. */
3403 for (ParseNode
* next
= pn
; next
; next
= next
->pn_next
) {
3404 RootedValue
child(cx
);
3405 if (!sourceElement(next
, &child
) || !elts
.append(child
))
3409 return builder
.blockStatement(elts
, pos
, dst
);
3413 reflect_parse(JSContext
* cx
, uint32_t argc
, jsval
* vp
)
3415 CallArgs args
= CallArgsFromVp(argc
, vp
);
3417 if (args
.length() < 1) {
3418 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, nullptr, JSMSG_MORE_ARGS_NEEDED
,
3419 "Reflect.parse", "0", "s");
3423 RootedString
src(cx
, ToString
<CanGC
>(cx
, args
[0]));
3427 ScopedJSFreePtr
<char> filename
;
3428 uint32_t lineno
= 1;
3431 RootedObject
builder(cx
);
3433 RootedValue
arg(cx
, args
.get(1));
3435 if (!arg
.isNullOrUndefined()) {
3436 if (!arg
.isObject()) {
3437 js_ReportValueErrorFlags(cx
, JSREPORT_ERROR
, JSMSG_UNEXPECTED_TYPE
,
3438 JSDVG_SEARCH_STACK
, arg
, js::NullPtr(),
3439 "not an object", nullptr);
3443 RootedObject
config(cx
, &arg
.toObject());
3445 RootedValue
prop(cx
);
3448 RootedId
locId(cx
, NameToId(cx
->names().loc
));
3449 RootedValue
trueVal(cx
, BooleanValue(true));
3450 if (!GetPropertyDefault(cx
, config
, locId
, trueVal
, &prop
))
3453 loc
= ToBoolean(prop
);
3457 RootedId
sourceId(cx
, NameToId(cx
->names().source
));
3458 RootedValue
nullVal(cx
, NullValue());
3459 if (!GetPropertyDefault(cx
, config
, sourceId
, nullVal
, &prop
))
3462 if (!prop
.isNullOrUndefined()) {
3463 RootedString
str(cx
, ToString
<CanGC
>(cx
, prop
));
3467 filename
= JS_EncodeString(cx
, str
);
3473 RootedId
lineId(cx
, NameToId(cx
->names().line
));
3474 RootedValue
oneValue(cx
, Int32Value(1));
3475 if (!GetPropertyDefault(cx
, config
, lineId
, oneValue
, &prop
) ||
3476 !ToUint32(cx
, prop
, &lineno
)) {
3481 /* config.builder */
3482 RootedId
builderId(cx
, NameToId(cx
->names().builder
));
3483 RootedValue
nullVal(cx
, NullValue());
3484 if (!GetPropertyDefault(cx
, config
, builderId
, nullVal
, &prop
))
3487 if (!prop
.isNullOrUndefined()) {
3488 if (!prop
.isObject()) {
3489 js_ReportValueErrorFlags(cx
, JSREPORT_ERROR
, JSMSG_UNEXPECTED_TYPE
,
3490 JSDVG_SEARCH_STACK
, prop
, js::NullPtr(),
3491 "not an object", nullptr);
3494 builder
= &prop
.toObject();
3498 /* Extract the builder methods first to report errors before parsing. */
3499 ASTSerializer
serialize(cx
, loc
, filename
, lineno
);
3500 if (!serialize
.init(builder
))
3503 JSFlatString
* flat
= src
->ensureFlat(cx
);
3507 AutoStableStringChars
flatChars(cx
);
3508 if (!flatChars
.initTwoByte(cx
, flat
))
3511 CompileOptions
options(cx
);
3512 options
.setFileAndLine(filename
, lineno
);
3513 options
.setCanLazilyParse(false);
3514 mozilla::Range
<const char16_t
> chars
= flatChars
.twoByteRange();
3515 Parser
<FullParseHandler
> parser(cx
, &cx
->tempLifoAlloc(), options
, chars
.start().get(),
3516 chars
.length(), /* foldConstants = */ false, nullptr, nullptr);
3517 if (!parser
.checkOptions())
3520 serialize
.setParser(&parser
);
3522 ParseNode
* pn
= parser
.parse(nullptr);
3526 RootedValue
val(cx
);
3527 if (!serialize
.program(pn
, &val
)) {
3528 args
.rval().setNull();
3532 args
.rval().set(val
);
3536 JS_PUBLIC_API(JSObject
*)
3537 JS_InitReflect(JSContext
* cx
, HandleObject obj
)
3539 static const JSFunctionSpec static_methods
[] = {
3540 JS_FN("parse", reflect_parse
, 1, 0),
3544 RootedObject
proto(cx
, obj
->as
<GlobalObject
>().getOrCreateObjectPrototype(cx
));
3547 RootedPlainObject
Reflect(cx
, NewObjectWithGivenProto
<PlainObject
>(cx
, proto
, obj
,
3552 if (!JS_DefineProperty(cx
, obj
, "Reflect", Reflect
, 0,
3553 JS_STUBGETTER
, JS_STUBSETTER
)) {
3557 if (!JS_DefineFunctions(cx
, Reflect
, static_methods
))