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 JS_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 RootedObject
nobj(cx
, NewBuiltinClassInstance(cx
, &JSObject::class_
));
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 JS_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 propertyInitializer(HandleValue key
, HandleValue val
, PropKind kind
, bool isShorthand
,
555 bool isMethod
, TokenPos
*pos
, MutableHandleValue dst
);
562 bool blockStatement(NodeVector
&elts
, TokenPos
*pos
, MutableHandleValue dst
);
564 bool expressionStatement(HandleValue expr
, TokenPos
*pos
, MutableHandleValue dst
);
566 bool emptyStatement(TokenPos
*pos
, MutableHandleValue dst
);
568 bool ifStatement(HandleValue test
, HandleValue cons
, HandleValue alt
, TokenPos
*pos
,
569 MutableHandleValue dst
);
571 bool breakStatement(HandleValue label
, TokenPos
*pos
, MutableHandleValue dst
);
573 bool continueStatement(HandleValue label
, TokenPos
*pos
, MutableHandleValue dst
);
575 bool labeledStatement(HandleValue label
, HandleValue stmt
, TokenPos
*pos
,
576 MutableHandleValue dst
);
578 bool throwStatement(HandleValue arg
, TokenPos
*pos
, MutableHandleValue dst
);
580 bool returnStatement(HandleValue arg
, TokenPos
*pos
, MutableHandleValue dst
);
582 bool forStatement(HandleValue init
, HandleValue test
, HandleValue update
, HandleValue stmt
,
583 TokenPos
*pos
, MutableHandleValue dst
);
585 bool forInStatement(HandleValue var
, HandleValue expr
, HandleValue stmt
,
586 bool isForEach
, TokenPos
*pos
, MutableHandleValue dst
);
588 bool forOfStatement(HandleValue var
, HandleValue expr
, HandleValue stmt
, TokenPos
*pos
,
589 MutableHandleValue dst
);
591 bool withStatement(HandleValue expr
, HandleValue stmt
, TokenPos
*pos
, MutableHandleValue dst
);
593 bool whileStatement(HandleValue test
, HandleValue stmt
, TokenPos
*pos
, MutableHandleValue dst
);
595 bool doWhileStatement(HandleValue stmt
, HandleValue test
, TokenPos
*pos
,
596 MutableHandleValue dst
);
598 bool switchStatement(HandleValue disc
, NodeVector
&elts
, bool lexical
, TokenPos
*pos
,
599 MutableHandleValue dst
);
601 bool tryStatement(HandleValue body
, NodeVector
&guarded
, HandleValue unguarded
,
602 HandleValue finally
, TokenPos
*pos
, MutableHandleValue dst
);
604 bool debuggerStatement(TokenPos
*pos
, MutableHandleValue dst
);
606 bool letStatement(NodeVector
&head
, HandleValue stmt
, TokenPos
*pos
, MutableHandleValue dst
);
608 bool importDeclaration(NodeVector
&elts
, HandleValue moduleSpec
, TokenPos
*pos
, MutableHandleValue dst
);
610 bool importSpecifier(HandleValue importName
, HandleValue bindingName
, TokenPos
*pos
, MutableHandleValue dst
);
612 bool exportDeclaration(HandleValue decl
, NodeVector
&elts
, HandleValue moduleSpec
, TokenPos
*pos
, MutableHandleValue dst
);
614 bool exportSpecifier(HandleValue bindingName
, HandleValue exportName
, TokenPos
*pos
, MutableHandleValue dst
);
616 bool exportBatchSpecifier(TokenPos
*pos
, MutableHandleValue dst
);
622 bool binaryExpression(BinaryOperator op
, HandleValue left
, HandleValue right
, TokenPos
*pos
,
623 MutableHandleValue dst
);
625 bool unaryExpression(UnaryOperator op
, HandleValue expr
, TokenPos
*pos
, MutableHandleValue dst
);
627 bool assignmentExpression(AssignmentOperator op
, HandleValue lhs
, HandleValue rhs
,
628 TokenPos
*pos
, MutableHandleValue dst
);
630 bool updateExpression(HandleValue expr
, bool incr
, bool prefix
, TokenPos
*pos
,
631 MutableHandleValue dst
);
633 bool logicalExpression(bool lor
, HandleValue left
, HandleValue right
, TokenPos
*pos
,
634 MutableHandleValue dst
);
636 bool conditionalExpression(HandleValue test
, HandleValue cons
, HandleValue alt
, TokenPos
*pos
,
637 MutableHandleValue dst
);
639 bool sequenceExpression(NodeVector
&elts
, TokenPos
*pos
, MutableHandleValue dst
);
641 bool newExpression(HandleValue callee
, NodeVector
&args
, TokenPos
*pos
, MutableHandleValue dst
);
643 bool callExpression(HandleValue callee
, NodeVector
&args
, TokenPos
*pos
,
644 MutableHandleValue dst
);
646 bool memberExpression(bool computed
, HandleValue expr
, HandleValue member
, TokenPos
*pos
,
647 MutableHandleValue dst
);
649 bool arrayExpression(NodeVector
&elts
, TokenPos
*pos
, MutableHandleValue dst
);
651 bool templateLiteral(NodeVector
&elts
, TokenPos
*pos
, MutableHandleValue dst
);
653 bool taggedTemplate(HandleValue callee
, NodeVector
&args
, TokenPos
*pos
,
654 MutableHandleValue dst
);
656 bool callSiteObj(NodeVector
&raw
, NodeVector
&cooked
, TokenPos
*pos
, MutableHandleValue dst
);
658 bool spreadExpression(HandleValue expr
, TokenPos
*pos
, MutableHandleValue dst
);
660 bool computedName(HandleValue name
, TokenPos
*pos
, MutableHandleValue dst
);
662 bool objectExpression(NodeVector
&elts
, TokenPos
*pos
, MutableHandleValue dst
);
664 bool thisExpression(TokenPos
*pos
, MutableHandleValue dst
);
666 bool yieldExpression(HandleValue arg
, YieldKind kind
, TokenPos
*pos
, MutableHandleValue dst
);
668 bool comprehensionBlock(HandleValue patt
, HandleValue src
, bool isForEach
, bool isForOf
, TokenPos
*pos
,
669 MutableHandleValue dst
);
671 bool comprehensionExpression(HandleValue body
, NodeVector
&blocks
, HandleValue filter
,
672 TokenPos
*pos
, MutableHandleValue dst
);
674 bool generatorExpression(HandleValue body
, NodeVector
&blocks
, HandleValue filter
,
675 TokenPos
*pos
, MutableHandleValue dst
);
677 bool letExpression(NodeVector
&head
, HandleValue expr
, TokenPos
*pos
, MutableHandleValue dst
);
683 bool variableDeclaration(NodeVector
&elts
, VarDeclKind kind
, TokenPos
*pos
,
684 MutableHandleValue dst
);
690 bool arrayPattern(NodeVector
&elts
, TokenPos
*pos
, MutableHandleValue dst
);
692 bool objectPattern(NodeVector
&elts
, TokenPos
*pos
, MutableHandleValue dst
);
694 bool propertyPattern(HandleValue key
, HandleValue patt
, bool isShorthand
, TokenPos
*pos
,
695 MutableHandleValue dst
);
698 } /* anonymous namespace */
701 NodeBuilder::newNode(ASTType type
, TokenPos
*pos
, MutableHandleObject dst
)
703 JS_ASSERT(type
> AST_ERROR
&& type
< AST_LIMIT
);
706 RootedObject
node(cx
, NewBuiltinClassInstance(cx
, &JSObject::class_
));
708 !setNodeLoc(node
, pos
) ||
709 !atomValue(nodeTypeNames
[type
], &tv
) ||
710 !setProperty(node
, "type", tv
)) {
719 NodeBuilder::newArray(NodeVector
&elts
, MutableHandleValue dst
)
721 const size_t len
= elts
.length();
722 if (len
> UINT32_MAX
) {
723 js_ReportAllocationOverflow(cx
);
726 RootedObject
array(cx
, NewDenseAllocatedArray(cx
, uint32_t(len
)));
730 for (size_t i
= 0; i
< len
; i
++) {
731 RootedValue
val(cx
, elts
[i
]);
733 JS_ASSERT_IF(val
.isMagic(), val
.whyMagic() == JS_SERIALIZE_NO_NODE
);
735 /* Represent "no node" as an array hole by not adding the value. */
736 if (val
.isMagic(JS_SERIALIZE_NO_NODE
))
739 if (!JSObject::setElement(cx
, array
, array
, i
, &val
, false))
743 dst
.setObject(*array
);
748 NodeBuilder::newNodeLoc(TokenPos
*pos
, MutableHandleValue dst
)
755 RootedObject
loc(cx
);
759 if (!newObject(&loc
))
764 uint32_t startLineNum
, startColumnIndex
;
765 uint32_t endLineNum
, endColumnIndex
;
766 tokenStream
->srcCoords
.lineNumAndColumnIndex(pos
->begin
, &startLineNum
, &startColumnIndex
);
767 tokenStream
->srcCoords
.lineNumAndColumnIndex(pos
->end
, &endLineNum
, &endColumnIndex
);
772 if (!setProperty(loc
, "start", val
))
774 val
.setNumber(startLineNum
);
775 if (!setProperty(to
, "line", val
))
777 val
.setNumber(startColumnIndex
);
778 if (!setProperty(to
, "column", val
))
784 if (!setProperty(loc
, "end", val
))
786 val
.setNumber(endLineNum
);
787 if (!setProperty(to
, "line", val
))
789 val
.setNumber(endColumnIndex
);
790 if (!setProperty(to
, "column", val
))
793 if (!setProperty(loc
, "source", srcval
))
800 NodeBuilder::setNodeLoc(HandleObject node
, TokenPos
*pos
)
803 RootedValue
nullVal(cx
, NullValue());
804 setProperty(node
, "loc", nullVal
);
809 return newNodeLoc(pos
, &loc
) &&
810 setProperty(node
, "loc", loc
);
814 NodeBuilder::program(NodeVector
&elts
, TokenPos
*pos
, MutableHandleValue dst
)
816 return listNode(AST_PROGRAM
, "body", elts
, pos
, dst
);
820 NodeBuilder::blockStatement(NodeVector
&elts
, TokenPos
*pos
, MutableHandleValue dst
)
822 return listNode(AST_BLOCK_STMT
, "body", elts
, pos
, dst
);
826 NodeBuilder::expressionStatement(HandleValue expr
, TokenPos
*pos
, MutableHandleValue dst
)
828 RootedValue
cb(cx
, callbacks
[AST_EXPR_STMT
]);
830 return callback(cb
, expr
, pos
, dst
);
832 return newNode(AST_EXPR_STMT
, pos
, "expression", expr
, dst
);
836 NodeBuilder::emptyStatement(TokenPos
*pos
, MutableHandleValue dst
)
838 RootedValue
cb(cx
, callbacks
[AST_EMPTY_STMT
]);
840 return callback(cb
, pos
, dst
);
842 return newNode(AST_EMPTY_STMT
, pos
, dst
);
846 NodeBuilder::ifStatement(HandleValue test
, HandleValue cons
, HandleValue alt
, TokenPos
*pos
,
847 MutableHandleValue dst
)
849 RootedValue
cb(cx
, callbacks
[AST_IF_STMT
]);
851 return callback(cb
, test
, cons
, opt(alt
), pos
, dst
);
853 return newNode(AST_IF_STMT
, pos
,
861 NodeBuilder::breakStatement(HandleValue label
, TokenPos
*pos
, MutableHandleValue dst
)
863 RootedValue
cb(cx
, callbacks
[AST_BREAK_STMT
]);
865 return callback(cb
, opt(label
), pos
, dst
);
867 return newNode(AST_BREAK_STMT
, pos
, "label", label
, dst
);
871 NodeBuilder::continueStatement(HandleValue label
, TokenPos
*pos
, MutableHandleValue dst
)
873 RootedValue
cb(cx
, callbacks
[AST_CONTINUE_STMT
]);
875 return callback(cb
, opt(label
), pos
, dst
);
877 return newNode(AST_CONTINUE_STMT
, pos
, "label", label
, dst
);
881 NodeBuilder::labeledStatement(HandleValue label
, HandleValue stmt
, TokenPos
*pos
,
882 MutableHandleValue dst
)
884 RootedValue
cb(cx
, callbacks
[AST_LAB_STMT
]);
886 return callback(cb
, label
, stmt
, pos
, dst
);
888 return newNode(AST_LAB_STMT
, pos
,
895 NodeBuilder::throwStatement(HandleValue arg
, TokenPos
*pos
, MutableHandleValue dst
)
897 RootedValue
cb(cx
, callbacks
[AST_THROW_STMT
]);
899 return callback(cb
, arg
, pos
, dst
);
901 return newNode(AST_THROW_STMT
, pos
, "argument", arg
, dst
);
905 NodeBuilder::returnStatement(HandleValue arg
, TokenPos
*pos
, MutableHandleValue dst
)
907 RootedValue
cb(cx
, callbacks
[AST_RETURN_STMT
]);
909 return callback(cb
, opt(arg
), pos
, dst
);
911 return newNode(AST_RETURN_STMT
, pos
, "argument", arg
, dst
);
915 NodeBuilder::forStatement(HandleValue init
, HandleValue test
, HandleValue update
, HandleValue stmt
,
916 TokenPos
*pos
, MutableHandleValue dst
)
918 RootedValue
cb(cx
, callbacks
[AST_FOR_STMT
]);
920 return callback(cb
, opt(init
), opt(test
), opt(update
), stmt
, pos
, dst
);
922 return newNode(AST_FOR_STMT
, pos
,
931 NodeBuilder::forInStatement(HandleValue var
, HandleValue expr
, HandleValue stmt
, bool isForEach
,
932 TokenPos
*pos
, MutableHandleValue dst
)
934 RootedValue
isForEachVal(cx
, BooleanValue(isForEach
));
936 RootedValue
cb(cx
, callbacks
[AST_FOR_IN_STMT
]);
938 return callback(cb
, var
, expr
, stmt
, isForEachVal
, pos
, dst
);
940 return newNode(AST_FOR_IN_STMT
, pos
,
944 "each", isForEachVal
,
949 NodeBuilder::forOfStatement(HandleValue var
, HandleValue expr
, HandleValue stmt
, TokenPos
*pos
,
950 MutableHandleValue dst
)
952 RootedValue
cb(cx
, callbacks
[AST_FOR_OF_STMT
]);
954 return callback(cb
, var
, expr
, stmt
, pos
, dst
);
956 return newNode(AST_FOR_OF_STMT
, pos
,
964 NodeBuilder::withStatement(HandleValue expr
, HandleValue stmt
, TokenPos
*pos
,
965 MutableHandleValue dst
)
967 RootedValue
cb(cx
, callbacks
[AST_WITH_STMT
]);
969 return callback(cb
, expr
, stmt
, pos
, dst
);
971 return newNode(AST_WITH_STMT
, pos
,
978 NodeBuilder::whileStatement(HandleValue test
, HandleValue stmt
, TokenPos
*pos
,
979 MutableHandleValue dst
)
981 RootedValue
cb(cx
, callbacks
[AST_WHILE_STMT
]);
983 return callback(cb
, test
, stmt
, pos
, dst
);
985 return newNode(AST_WHILE_STMT
, pos
,
992 NodeBuilder::doWhileStatement(HandleValue stmt
, HandleValue test
, TokenPos
*pos
,
993 MutableHandleValue dst
)
995 RootedValue
cb(cx
, callbacks
[AST_DO_STMT
]);
997 return callback(cb
, stmt
, test
, pos
, dst
);
999 return newNode(AST_DO_STMT
, pos
,
1006 NodeBuilder::switchStatement(HandleValue disc
, NodeVector
&elts
, bool lexical
, TokenPos
*pos
,
1007 MutableHandleValue dst
)
1009 RootedValue
array(cx
);
1010 if (!newArray(elts
, &array
))
1013 RootedValue
lexicalVal(cx
, BooleanValue(lexical
));
1015 RootedValue
cb(cx
, callbacks
[AST_SWITCH_STMT
]);
1017 return callback(cb
, disc
, array
, lexicalVal
, pos
, dst
);
1019 return newNode(AST_SWITCH_STMT
, pos
,
1020 "discriminant", disc
,
1022 "lexical", lexicalVal
,
1027 NodeBuilder::tryStatement(HandleValue body
, NodeVector
&guarded
, HandleValue unguarded
,
1028 HandleValue finally
, TokenPos
*pos
, MutableHandleValue dst
)
1030 RootedValue
guardedHandlers(cx
);
1031 if (!newArray(guarded
, &guardedHandlers
))
1034 RootedValue
cb(cx
, callbacks
[AST_TRY_STMT
]);
1036 return callback(cb
, body
, guardedHandlers
, unguarded
, opt(finally
), pos
, dst
);
1038 return newNode(AST_TRY_STMT
, pos
,
1040 "guardedHandlers", guardedHandlers
,
1041 "handler", unguarded
,
1042 "finalizer", finally
,
1047 NodeBuilder::debuggerStatement(TokenPos
*pos
, MutableHandleValue dst
)
1049 RootedValue
cb(cx
, callbacks
[AST_DEBUGGER_STMT
]);
1051 return callback(cb
, pos
, dst
);
1053 return newNode(AST_DEBUGGER_STMT
, pos
, dst
);
1057 NodeBuilder::binaryExpression(BinaryOperator op
, HandleValue left
, HandleValue right
, TokenPos
*pos
,
1058 MutableHandleValue dst
)
1060 JS_ASSERT(op
> BINOP_ERR
&& op
< BINOP_LIMIT
);
1062 RootedValue
opName(cx
);
1063 if (!atomValue(binopNames
[op
], &opName
))
1066 RootedValue
cb(cx
, callbacks
[AST_BINARY_EXPR
]);
1068 return callback(cb
, opName
, left
, right
, pos
, dst
);
1070 return newNode(AST_BINARY_EXPR
, pos
,
1078 NodeBuilder::unaryExpression(UnaryOperator unop
, HandleValue expr
, TokenPos
*pos
,
1079 MutableHandleValue dst
)
1081 JS_ASSERT(unop
> UNOP_ERR
&& unop
< UNOP_LIMIT
);
1083 RootedValue
opName(cx
);
1084 if (!atomValue(unopNames
[unop
], &opName
))
1087 RootedValue
cb(cx
, callbacks
[AST_UNARY_EXPR
]);
1089 return callback(cb
, opName
, expr
, pos
, dst
);
1091 RootedValue
trueVal(cx
, BooleanValue(true));
1092 return newNode(AST_UNARY_EXPR
, pos
,
1100 NodeBuilder::assignmentExpression(AssignmentOperator aop
, HandleValue lhs
, HandleValue rhs
,
1101 TokenPos
*pos
, MutableHandleValue dst
)
1103 JS_ASSERT(aop
> AOP_ERR
&& aop
< AOP_LIMIT
);
1105 RootedValue
opName(cx
);
1106 if (!atomValue(aopNames
[aop
], &opName
))
1109 RootedValue
cb(cx
, callbacks
[AST_ASSIGN_EXPR
]);
1111 return callback(cb
, opName
, lhs
, rhs
, pos
, dst
);
1113 return newNode(AST_ASSIGN_EXPR
, pos
,
1121 NodeBuilder::updateExpression(HandleValue expr
, bool incr
, bool prefix
, TokenPos
*pos
,
1122 MutableHandleValue dst
)
1124 RootedValue
opName(cx
);
1125 if (!atomValue(incr
? "++" : "--", &opName
))
1128 RootedValue
prefixVal(cx
, BooleanValue(prefix
));
1130 RootedValue
cb(cx
, callbacks
[AST_UPDATE_EXPR
]);
1132 return callback(cb
, expr
, opName
, prefixVal
, pos
, dst
);
1134 return newNode(AST_UPDATE_EXPR
, pos
,
1137 "prefix", prefixVal
,
1142 NodeBuilder::logicalExpression(bool lor
, HandleValue left
, HandleValue right
, TokenPos
*pos
,
1143 MutableHandleValue dst
)
1145 RootedValue
opName(cx
);
1146 if (!atomValue(lor
? "||" : "&&", &opName
))
1149 RootedValue
cb(cx
, callbacks
[AST_LOGICAL_EXPR
]);
1151 return callback(cb
, opName
, left
, right
, pos
, dst
);
1153 return newNode(AST_LOGICAL_EXPR
, pos
,
1161 NodeBuilder::conditionalExpression(HandleValue test
, HandleValue cons
, HandleValue alt
,
1162 TokenPos
*pos
, MutableHandleValue dst
)
1164 RootedValue
cb(cx
, callbacks
[AST_COND_EXPR
]);
1166 return callback(cb
, test
, cons
, alt
, pos
, dst
);
1168 return newNode(AST_COND_EXPR
, pos
,
1176 NodeBuilder::sequenceExpression(NodeVector
&elts
, TokenPos
*pos
, MutableHandleValue dst
)
1178 return listNode(AST_LIST_EXPR
, "expressions", elts
, pos
, dst
);
1182 NodeBuilder::callExpression(HandleValue callee
, NodeVector
&args
, TokenPos
*pos
,
1183 MutableHandleValue dst
)
1185 RootedValue
array(cx
);
1186 if (!newArray(args
, &array
))
1189 RootedValue
cb(cx
, callbacks
[AST_CALL_EXPR
]);
1191 return callback(cb
, callee
, array
, pos
, dst
);
1193 return newNode(AST_CALL_EXPR
, pos
,
1200 NodeBuilder::newExpression(HandleValue callee
, NodeVector
&args
, TokenPos
*pos
,
1201 MutableHandleValue dst
)
1203 RootedValue
array(cx
);
1204 if (!newArray(args
, &array
))
1207 RootedValue
cb(cx
, callbacks
[AST_NEW_EXPR
]);
1209 return callback(cb
, callee
, array
, pos
, dst
);
1211 return newNode(AST_NEW_EXPR
, pos
,
1218 NodeBuilder::memberExpression(bool computed
, HandleValue expr
, HandleValue member
, TokenPos
*pos
,
1219 MutableHandleValue dst
)
1221 RootedValue
computedVal(cx
, BooleanValue(computed
));
1223 RootedValue
cb(cx
, callbacks
[AST_MEMBER_EXPR
]);
1225 return callback(cb
, computedVal
, expr
, member
, pos
, dst
);
1227 return newNode(AST_MEMBER_EXPR
, pos
,
1230 "computed", computedVal
,
1235 NodeBuilder::arrayExpression(NodeVector
&elts
, TokenPos
*pos
, MutableHandleValue dst
)
1237 return listNode(AST_ARRAY_EXPR
, "elements", elts
, pos
, dst
);
1241 NodeBuilder::callSiteObj(NodeVector
&raw
, NodeVector
&cooked
, TokenPos
*pos
, MutableHandleValue dst
)
1243 RootedValue
rawVal(cx
);
1244 if (!newArray(raw
, &rawVal
))
1247 RootedValue
cookedVal(cx
);
1248 if (!newArray(cooked
, &cookedVal
))
1251 return newNode(AST_CALL_SITE_OBJ
, pos
,
1253 "cooked", cookedVal
,
1258 NodeBuilder::taggedTemplate(HandleValue callee
, NodeVector
&args
, TokenPos
*pos
,
1259 MutableHandleValue dst
)
1261 RootedValue
array(cx
);
1262 if (!newArray(args
, &array
))
1265 return newNode(AST_TAGGED_TEMPLATE
, pos
,
1272 NodeBuilder::templateLiteral(NodeVector
&elts
, TokenPos
*pos
, MutableHandleValue dst
)
1274 return listNode(AST_TEMPLATE_LITERAL
, "elements", elts
, pos
, dst
);
1278 NodeBuilder::computedName(HandleValue name
, TokenPos
*pos
, MutableHandleValue dst
)
1280 return newNode(AST_COMPUTED_NAME
, pos
,
1286 NodeBuilder::spreadExpression(HandleValue expr
, TokenPos
*pos
, MutableHandleValue dst
)
1288 return newNode(AST_SPREAD_EXPR
, pos
,
1294 NodeBuilder::propertyPattern(HandleValue key
, HandleValue patt
, bool isShorthand
, TokenPos
*pos
,
1295 MutableHandleValue dst
)
1297 RootedValue
kindName(cx
);
1298 if (!atomValue("init", &kindName
))
1301 RootedValue
isShorthandVal(cx
, BooleanValue(isShorthand
));
1303 RootedValue
cb(cx
, callbacks
[AST_PROP_PATT
]);
1305 return callback(cb
, key
, patt
, pos
, dst
);
1307 return newNode(AST_PROP_PATT
, pos
,
1311 "shorthand", isShorthandVal
,
1316 NodeBuilder::propertyInitializer(HandleValue key
, HandleValue val
, PropKind kind
, bool isShorthand
,
1317 bool isMethod
, TokenPos
*pos
, MutableHandleValue dst
)
1319 RootedValue
kindName(cx
);
1320 if (!atomValue(kind
== PROP_INIT
1322 : kind
== PROP_GETTER
1324 : "set", &kindName
)) {
1328 RootedValue
isShorthandVal(cx
, BooleanValue(isShorthand
));
1329 RootedValue
isMethodVal(cx
, BooleanValue(isMethod
));
1331 RootedValue
cb(cx
, callbacks
[AST_PROPERTY
]);
1333 return callback(cb
, kindName
, key
, val
, pos
, dst
);
1335 return newNode(AST_PROPERTY
, pos
,
1339 "method", isMethodVal
,
1340 "shorthand", isShorthandVal
,
1345 NodeBuilder::objectExpression(NodeVector
&elts
, TokenPos
*pos
, MutableHandleValue dst
)
1347 return listNode(AST_OBJECT_EXPR
, "properties", elts
, pos
, dst
);
1351 NodeBuilder::thisExpression(TokenPos
*pos
, MutableHandleValue dst
)
1353 RootedValue
cb(cx
, callbacks
[AST_THIS_EXPR
]);
1355 return callback(cb
, pos
, dst
);
1357 return newNode(AST_THIS_EXPR
, pos
, dst
);
1361 NodeBuilder::yieldExpression(HandleValue arg
, YieldKind kind
, TokenPos
*pos
, MutableHandleValue dst
)
1363 RootedValue
cb(cx
, callbacks
[AST_YIELD_EXPR
]);
1364 RootedValue
delegateVal(cx
);
1368 delegateVal
= BooleanValue(true);
1371 delegateVal
= BooleanValue(false);
1376 return callback(cb
, opt(arg
), delegateVal
, pos
, dst
);
1377 return newNode(AST_YIELD_EXPR
, pos
, "argument", arg
, "delegate", delegateVal
, dst
);
1381 NodeBuilder::comprehensionBlock(HandleValue patt
, HandleValue src
, bool isForEach
, bool isForOf
, TokenPos
*pos
,
1382 MutableHandleValue dst
)
1384 RootedValue
isForEachVal(cx
, BooleanValue(isForEach
));
1385 RootedValue
isForOfVal(cx
, BooleanValue(isForOf
));
1387 RootedValue
cb(cx
, callbacks
[AST_COMP_BLOCK
]);
1389 return callback(cb
, patt
, src
, isForEachVal
, isForOfVal
, pos
, dst
);
1391 return newNode(AST_COMP_BLOCK
, pos
,
1394 "each", isForEachVal
,
1400 NodeBuilder::comprehensionExpression(HandleValue body
, NodeVector
&blocks
, HandleValue filter
,
1401 TokenPos
*pos
, MutableHandleValue dst
)
1403 RootedValue
array(cx
);
1404 if (!newArray(blocks
, &array
))
1407 RootedValue
cb(cx
, callbacks
[AST_COMP_EXPR
]);
1409 return callback(cb
, body
, array
, opt(filter
), pos
, dst
);
1411 return newNode(AST_COMP_EXPR
, pos
,
1419 NodeBuilder::generatorExpression(HandleValue body
, NodeVector
&blocks
, HandleValue filter
,
1420 TokenPos
*pos
, MutableHandleValue dst
)
1422 RootedValue
array(cx
);
1423 if (!newArray(blocks
, &array
))
1426 RootedValue
cb(cx
, callbacks
[AST_GENERATOR_EXPR
]);
1428 return callback(cb
, body
, array
, opt(filter
), pos
, dst
);
1430 return newNode(AST_GENERATOR_EXPR
, pos
,
1438 NodeBuilder::letExpression(NodeVector
&head
, HandleValue expr
, TokenPos
*pos
,
1439 MutableHandleValue dst
)
1441 RootedValue
array(cx
);
1442 if (!newArray(head
, &array
))
1445 RootedValue
cb(cx
, callbacks
[AST_LET_EXPR
]);
1447 return callback(cb
, array
, expr
, pos
, dst
);
1449 return newNode(AST_LET_EXPR
, pos
,
1456 NodeBuilder::letStatement(NodeVector
&head
, HandleValue stmt
, TokenPos
*pos
, MutableHandleValue dst
)
1458 RootedValue
array(cx
);
1459 if (!newArray(head
, &array
))
1462 RootedValue
cb(cx
, callbacks
[AST_LET_STMT
]);
1464 return callback(cb
, array
, stmt
, pos
, dst
);
1466 return newNode(AST_LET_STMT
, pos
,
1473 NodeBuilder::importDeclaration(NodeVector
&elts
, HandleValue moduleSpec
, TokenPos
*pos
,
1474 MutableHandleValue dst
)
1476 RootedValue
array(cx
);
1477 if (!newArray(elts
, &array
))
1480 RootedValue
cb(cx
, callbacks
[AST_IMPORT_DECL
]);
1482 return callback(cb
, array
, moduleSpec
, pos
, dst
);
1484 return newNode(AST_IMPORT_DECL
, pos
,
1485 "specifiers", array
,
1486 "source", moduleSpec
,
1491 NodeBuilder::importSpecifier(HandleValue importName
, HandleValue bindingName
, TokenPos
*pos
,
1492 MutableHandleValue dst
)
1494 RootedValue
cb(cx
, callbacks
[AST_IMPORT_SPEC
]);
1496 return callback(cb
, importName
, bindingName
, pos
, dst
);
1498 return newNode(AST_IMPORT_SPEC
, pos
,
1500 "name", bindingName
,
1505 NodeBuilder::exportDeclaration(HandleValue decl
, NodeVector
&elts
, HandleValue moduleSpec
,
1506 TokenPos
*pos
, MutableHandleValue dst
)
1508 RootedValue
array(cx
, NullValue());
1509 if (decl
.isNull() && !newArray(elts
, &array
))
1512 RootedValue
cb(cx
, callbacks
[AST_IMPORT_DECL
]);
1515 return callback(cb
, decl
, array
, moduleSpec
, pos
, dst
);
1517 return newNode(AST_EXPORT_DECL
, pos
,
1518 "declaration", decl
,
1519 "specifiers", array
,
1520 "source", moduleSpec
,
1525 NodeBuilder::exportSpecifier(HandleValue bindingName
, HandleValue exportName
, TokenPos
*pos
,
1526 MutableHandleValue dst
)
1528 RootedValue
cb(cx
, callbacks
[AST_EXPORT_SPEC
]);
1530 return callback(cb
, bindingName
, exportName
, pos
, dst
);
1532 return newNode(AST_EXPORT_SPEC
, pos
,
1539 NodeBuilder::exportBatchSpecifier(TokenPos
*pos
, MutableHandleValue dst
)
1541 RootedValue
cb(cx
, callbacks
[AST_EXPORT_BATCH_SPEC
]);
1543 return callback(cb
, pos
, dst
);
1545 return newNode(AST_EXPORT_BATCH_SPEC
, pos
, dst
);
1549 NodeBuilder::variableDeclaration(NodeVector
&elts
, VarDeclKind kind
, TokenPos
*pos
,
1550 MutableHandleValue dst
)
1552 JS_ASSERT(kind
> VARDECL_ERR
&& kind
< VARDECL_LIMIT
);
1554 RootedValue
array(cx
), kindName(cx
);
1555 if (!newArray(elts
, &array
) ||
1556 !atomValue(kind
== VARDECL_CONST
1558 : kind
== VARDECL_LET
1560 : "var", &kindName
)) {
1564 RootedValue
cb(cx
, callbacks
[AST_VAR_DECL
]);
1566 return callback(cb
, kindName
, array
, pos
, dst
);
1568 return newNode(AST_VAR_DECL
, pos
,
1570 "declarations", array
,
1575 NodeBuilder::variableDeclarator(HandleValue id
, HandleValue init
, TokenPos
*pos
,
1576 MutableHandleValue dst
)
1578 RootedValue
cb(cx
, callbacks
[AST_VAR_DTOR
]);
1580 return callback(cb
, id
, opt(init
), pos
, dst
);
1582 return newNode(AST_VAR_DTOR
, pos
, "id", id
, "init", init
, dst
);
1586 NodeBuilder::switchCase(HandleValue expr
, NodeVector
&elts
, TokenPos
*pos
, MutableHandleValue dst
)
1588 RootedValue
array(cx
);
1589 if (!newArray(elts
, &array
))
1592 RootedValue
cb(cx
, callbacks
[AST_CASE
]);
1594 return callback(cb
, opt(expr
), array
, pos
, dst
);
1596 return newNode(AST_CASE
, pos
,
1598 "consequent", array
,
1603 NodeBuilder::catchClause(HandleValue var
, HandleValue guard
, HandleValue body
, TokenPos
*pos
,
1604 MutableHandleValue dst
)
1606 RootedValue
cb(cx
, callbacks
[AST_CATCH
]);
1608 return callback(cb
, var
, opt(guard
), body
, pos
, dst
);
1610 return newNode(AST_CATCH
, pos
,
1618 NodeBuilder::literal(HandleValue val
, TokenPos
*pos
, MutableHandleValue dst
)
1620 RootedValue
cb(cx
, callbacks
[AST_LITERAL
]);
1622 return callback(cb
, val
, pos
, dst
);
1624 return newNode(AST_LITERAL
, pos
, "value", val
, dst
);
1628 NodeBuilder::identifier(HandleValue name
, TokenPos
*pos
, MutableHandleValue dst
)
1630 RootedValue
cb(cx
, callbacks
[AST_IDENTIFIER
]);
1632 return callback(cb
, name
, pos
, dst
);
1634 return newNode(AST_IDENTIFIER
, pos
, "name", name
, dst
);
1638 NodeBuilder::objectPattern(NodeVector
&elts
, TokenPos
*pos
, MutableHandleValue dst
)
1640 return listNode(AST_OBJECT_PATT
, "properties", elts
, pos
, dst
);
1644 NodeBuilder::arrayPattern(NodeVector
&elts
, TokenPos
*pos
, MutableHandleValue dst
)
1646 return listNode(AST_ARRAY_PATT
, "elements", elts
, pos
, dst
);
1650 NodeBuilder::function(ASTType type
, TokenPos
*pos
,
1651 HandleValue id
, NodeVector
&args
, NodeVector
&defaults
,
1652 HandleValue body
, HandleValue rest
,
1653 bool isGenerator
, bool isExpression
,
1654 MutableHandleValue dst
)
1656 RootedValue
array(cx
), defarray(cx
);
1657 if (!newArray(args
, &array
))
1659 if (!newArray(defaults
, &defarray
))
1662 RootedValue
isGeneratorVal(cx
, BooleanValue(isGenerator
));
1663 RootedValue
isExpressionVal(cx
, BooleanValue(isExpression
));
1665 RootedValue
cb(cx
, callbacks
[type
]);
1667 return callback(cb
, opt(id
), array
, body
, isGeneratorVal
, isExpressionVal
, pos
, dst
);
1670 return newNode(type
, pos
,
1673 "defaults", defarray
,
1676 "generator", isGeneratorVal
,
1677 "expression", isExpressionVal
,
1684 * Serialization of parse nodes to JavaScript objects.
1686 * All serialization methods take a non-nullable ParseNode pointer.
1691 Parser
<FullParseHandler
> *parser
;
1692 NodeBuilder builder
;
1693 DebugOnly
<uint32_t> lineno
;
1695 Value
unrootedAtomContents(JSAtom
*atom
) {
1696 return StringValue(atom
? atom
: cx
->names().empty
);
1699 BinaryOperator
binop(ParseNodeKind kind
, JSOp op
);
1700 UnaryOperator
unop(ParseNodeKind kind
, JSOp op
);
1701 AssignmentOperator
aop(JSOp op
);
1703 bool statements(ParseNode
*pn
, NodeVector
&elts
);
1704 bool expressions(ParseNode
*pn
, NodeVector
&elts
);
1705 bool leftAssociate(ParseNode
*pn
, MutableHandleValue dst
);
1706 bool functionArgs(ParseNode
*pn
, ParseNode
*pnargs
, ParseNode
*pndestruct
, ParseNode
*pnbody
,
1707 NodeVector
&args
, NodeVector
&defaults
, MutableHandleValue rest
);
1709 bool sourceElement(ParseNode
*pn
, MutableHandleValue dst
);
1711 bool declaration(ParseNode
*pn
, MutableHandleValue dst
);
1712 bool variableDeclaration(ParseNode
*pn
, bool let
, MutableHandleValue dst
);
1713 bool variableDeclarator(ParseNode
*pn
, VarDeclKind
*pkind
, MutableHandleValue dst
);
1714 bool let(ParseNode
*pn
, bool expr
, MutableHandleValue dst
);
1715 bool importDeclaration(ParseNode
*pn
, MutableHandleValue dst
);
1716 bool importSpecifier(ParseNode
*pn
, MutableHandleValue dst
);
1717 bool exportDeclaration(ParseNode
*pn
, MutableHandleValue dst
);
1718 bool exportSpecifier(ParseNode
*pn
, MutableHandleValue dst
);
1720 bool optStatement(ParseNode
*pn
, MutableHandleValue dst
) {
1722 dst
.setMagic(JS_SERIALIZE_NO_NODE
);
1725 return statement(pn
, dst
);
1728 bool forInit(ParseNode
*pn
, MutableHandleValue dst
);
1729 bool forIn(ParseNode
*loop
, ParseNode
*head
, HandleValue var
, HandleValue stmt
,
1730 MutableHandleValue dst
);
1731 bool forOf(ParseNode
*loop
, ParseNode
*head
, HandleValue var
, HandleValue stmt
,
1732 MutableHandleValue dst
);
1733 bool statement(ParseNode
*pn
, MutableHandleValue dst
);
1734 bool blockStatement(ParseNode
*pn
, MutableHandleValue dst
);
1735 bool switchStatement(ParseNode
*pn
, MutableHandleValue dst
);
1736 bool switchCase(ParseNode
*pn
, MutableHandleValue dst
);
1737 bool tryStatement(ParseNode
*pn
, MutableHandleValue dst
);
1738 bool catchClause(ParseNode
*pn
, bool *isGuarded
, MutableHandleValue dst
);
1740 bool optExpression(ParseNode
*pn
, MutableHandleValue dst
) {
1742 dst
.setMagic(JS_SERIALIZE_NO_NODE
);
1745 return expression(pn
, dst
);
1748 bool expression(ParseNode
*pn
, MutableHandleValue dst
);
1750 bool propertyName(ParseNode
*pn
, MutableHandleValue dst
);
1751 bool property(ParseNode
*pn
, MutableHandleValue dst
);
1753 bool optIdentifier(HandleAtom atom
, TokenPos
*pos
, MutableHandleValue dst
) {
1755 dst
.setMagic(JS_SERIALIZE_NO_NODE
);
1758 return identifier(atom
, pos
, dst
);
1761 bool identifier(HandleAtom atom
, TokenPos
*pos
, MutableHandleValue dst
);
1762 bool identifier(ParseNode
*pn
, MutableHandleValue dst
);
1763 bool literal(ParseNode
*pn
, MutableHandleValue dst
);
1765 bool pattern(ParseNode
*pn
, VarDeclKind
*pkind
, MutableHandleValue dst
);
1766 bool arrayPattern(ParseNode
*pn
, VarDeclKind
*pkind
, MutableHandleValue dst
);
1767 bool objectPattern(ParseNode
*pn
, VarDeclKind
*pkind
, MutableHandleValue dst
);
1769 bool function(ParseNode
*pn
, ASTType type
, MutableHandleValue dst
);
1770 bool functionArgsAndBody(ParseNode
*pn
, NodeVector
&args
, NodeVector
&defaults
,
1771 MutableHandleValue body
, MutableHandleValue rest
);
1772 bool functionBody(ParseNode
*pn
, TokenPos
*pos
, MutableHandleValue dst
);
1774 bool comprehensionBlock(ParseNode
*pn
, MutableHandleValue dst
);
1775 bool comprehension(ParseNode
*pn
, MutableHandleValue dst
);
1776 bool generatorExpression(ParseNode
*pn
, MutableHandleValue dst
);
1779 ASTSerializer(JSContext
*c
, bool l
, char const *src
, uint32_t ln
)
1781 , builder(c
, l
, src
)
1787 bool init(HandleObject userobj
) {
1788 return builder
.init(userobj
);
1791 void setParser(Parser
<FullParseHandler
> *p
) {
1793 builder
.setTokenStream(&p
->tokenStream
);
1796 bool program(ParseNode
*pn
, MutableHandleValue dst
);
1799 } /* anonymous namespace */
1802 ASTSerializer::aop(JSOp op
)
1835 ASTSerializer::unop(ParseNodeKind kind
, JSOp op
)
1837 if (kind
== PNK_DELETE
)
1850 case JSOP_TYPEOFEXPR
:
1860 ASTSerializer::binop(ParseNodeKind kind
, JSOp op
)
1882 return BINOP_STRICTEQ
;
1884 return BINOP_STRICTNE
;
1898 return BINOP_BITXOR
;
1900 return BINOP_BITAND
;
1903 case PNK_INSTANCEOF
:
1904 return BINOP_INSTANCEOF
;
1911 ASTSerializer::statements(ParseNode
*pn
, NodeVector
&elts
)
1913 JS_ASSERT(pn
->isKind(PNK_STATEMENTLIST
));
1914 JS_ASSERT(pn
->isArity(PN_LIST
));
1916 if (!elts
.reserve(pn
->pn_count
))
1919 for (ParseNode
*next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
1920 JS_ASSERT(pn
->pn_pos
.encloses(next
->pn_pos
));
1922 RootedValue
elt(cx
);
1923 if (!sourceElement(next
, &elt
))
1925 elts
.infallibleAppend(elt
);
1932 ASTSerializer::expressions(ParseNode
*pn
, NodeVector
&elts
)
1934 if (!elts
.reserve(pn
->pn_count
))
1937 for (ParseNode
*next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
1938 JS_ASSERT(pn
->pn_pos
.encloses(next
->pn_pos
));
1940 RootedValue
elt(cx
);
1941 if (!expression(next
, &elt
))
1943 elts
.infallibleAppend(elt
);
1950 ASTSerializer::blockStatement(ParseNode
*pn
, MutableHandleValue dst
)
1952 JS_ASSERT(pn
->isKind(PNK_STATEMENTLIST
));
1954 NodeVector
stmts(cx
);
1955 return statements(pn
, stmts
) &&
1956 builder
.blockStatement(stmts
, &pn
->pn_pos
, dst
);
1960 ASTSerializer::program(ParseNode
*pn
, MutableHandleValue dst
)
1962 JS_ASSERT(parser
->tokenStream
.srcCoords
.lineNum(pn
->pn_pos
.begin
) == lineno
);
1964 NodeVector
stmts(cx
);
1965 return statements(pn
, stmts
) &&
1966 builder
.program(stmts
, &pn
->pn_pos
, dst
);
1970 ASTSerializer::sourceElement(ParseNode
*pn
, MutableHandleValue dst
)
1972 /* SpiderMonkey allows declarations even in pure statement contexts. */
1973 return statement(pn
, dst
);
1977 ASTSerializer::declaration(ParseNode
*pn
, MutableHandleValue dst
)
1979 JS_ASSERT(pn
->isKind(PNK_FUNCTION
) ||
1980 pn
->isKind(PNK_VAR
) ||
1981 pn
->isKind(PNK_LET
) ||
1982 pn
->isKind(PNK_CONST
));
1984 switch (pn
->getKind()) {
1986 return function(pn
, AST_FUNC_DECL
, dst
);
1990 return variableDeclaration(pn
, false, dst
);
1993 JS_ASSERT(pn
->isKind(PNK_LET
));
1994 return variableDeclaration(pn
, true, dst
);
1999 ASTSerializer::variableDeclaration(ParseNode
*pn
, bool let
, MutableHandleValue dst
)
2001 JS_ASSERT(let
? pn
->isKind(PNK_LET
) : (pn
->isKind(PNK_VAR
) || pn
->isKind(PNK_CONST
)));
2003 /* Later updated to VARDECL_CONST if we find a PND_CONST declarator. */
2004 VarDeclKind kind
= let
? VARDECL_LET
: VARDECL_VAR
;
2006 NodeVector
dtors(cx
);
2007 if (!dtors
.reserve(pn
->pn_count
))
2009 for (ParseNode
*next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
2010 RootedValue
child(cx
);
2011 if (!variableDeclarator(next
, &kind
, &child
))
2013 dtors
.infallibleAppend(child
);
2015 return builder
.variableDeclaration(dtors
, kind
, &pn
->pn_pos
, dst
);
2019 ASTSerializer::variableDeclarator(ParseNode
*pn
, VarDeclKind
*pkind
, MutableHandleValue dst
)
2024 if (pn
->isKind(PNK_NAME
)) {
2026 pnright
= pn
->isUsed() ? nullptr : pn
->pn_expr
;
2027 JS_ASSERT_IF(pnright
, pn
->pn_pos
.encloses(pnright
->pn_pos
));
2028 } else if (pn
->isKind(PNK_ASSIGN
)) {
2029 pnleft
= pn
->pn_left
;
2030 pnright
= pn
->pn_right
;
2031 JS_ASSERT(pn
->pn_pos
.encloses(pnleft
->pn_pos
));
2032 JS_ASSERT(pn
->pn_pos
.encloses(pnright
->pn_pos
));
2034 /* This happens for a destructuring declarator in a for-in/of loop. */
2039 RootedValue
left(cx
), right(cx
);
2040 return pattern(pnleft
, pkind
, &left
) &&
2041 optExpression(pnright
, &right
) &&
2042 builder
.variableDeclarator(left
, right
, &pn
->pn_pos
, dst
);
2046 ASTSerializer::let(ParseNode
*pn
, bool expr
, MutableHandleValue dst
)
2048 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
2049 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_right
->pn_pos
));
2051 ParseNode
*letHead
= pn
->pn_left
;
2052 LOCAL_ASSERT(letHead
->isArity(PN_LIST
));
2054 ParseNode
*letBody
= pn
->pn_right
;
2055 LOCAL_ASSERT(letBody
->isKind(PNK_LEXICALSCOPE
));
2057 NodeVector
dtors(cx
);
2058 if (!dtors
.reserve(letHead
->pn_count
))
2061 VarDeclKind kind
= VARDECL_LET_HEAD
;
2063 for (ParseNode
*next
= letHead
->pn_head
; next
; next
= next
->pn_next
) {
2064 RootedValue
child(cx
);
2066 * Unlike in |variableDeclaration|, this does not update |kind|; since let-heads do
2067 * not contain const declarations, declarators should never have PND_CONST set.
2069 if (!variableDeclarator(next
, &kind
, &child
))
2071 dtors
.infallibleAppend(child
);
2076 ? expression(letBody
->pn_expr
, &v
) &&
2077 builder
.letExpression(dtors
, v
, &pn
->pn_pos
, dst
)
2078 : statement(letBody
->pn_expr
, &v
) &&
2079 builder
.letStatement(dtors
, v
, &pn
->pn_pos
, dst
);
2083 ASTSerializer::importDeclaration(ParseNode
*pn
, MutableHandleValue dst
)
2085 JS_ASSERT(pn
->isKind(PNK_IMPORT
));
2086 JS_ASSERT(pn
->pn_left
->isKind(PNK_IMPORT_SPEC_LIST
));
2087 JS_ASSERT(pn
->pn_right
->isKind(PNK_STRING
));
2089 NodeVector
elts(cx
);
2090 if (!elts
.reserve(pn
->pn_count
))
2093 for (ParseNode
*next
= pn
->pn_left
->pn_head
; next
; next
= next
->pn_next
) {
2094 RootedValue
elt(cx
);
2095 if (!importSpecifier(next
, &elt
))
2097 elts
.infallibleAppend(elt
);
2100 RootedValue
moduleSpec(cx
);
2101 return literal(pn
->pn_right
, &moduleSpec
) &&
2102 builder
.importDeclaration(elts
, moduleSpec
, &pn
->pn_pos
, dst
);
2106 ASTSerializer::importSpecifier(ParseNode
*pn
, MutableHandleValue dst
)
2108 JS_ASSERT(pn
->isKind(PNK_IMPORT_SPEC
));
2110 RootedValue
importName(cx
);
2111 RootedValue
bindingName(cx
);
2112 return identifier(pn
->pn_left
, &importName
) &&
2113 identifier(pn
->pn_right
, &bindingName
) &&
2114 builder
.importSpecifier(importName
, bindingName
, &pn
->pn_pos
, dst
);
2118 ASTSerializer::exportDeclaration(ParseNode
*pn
, MutableHandleValue dst
)
2120 JS_ASSERT(pn
->isKind(PNK_EXPORT
) || pn
->isKind(PNK_EXPORT_FROM
));
2121 JS_ASSERT_IF(pn
->isKind(PNK_EXPORT_FROM
), pn
->pn_right
->isKind(PNK_STRING
));
2123 RootedValue
decl(cx
, NullValue());
2124 NodeVector
elts(cx
);
2126 ParseNode
*kid
= pn
->isKind(PNK_EXPORT
) ? pn
->pn_kid
: pn
->pn_left
;
2127 switch (ParseNodeKind kind
= kid
->getKind()) {
2128 case PNK_EXPORT_SPEC_LIST
:
2129 if (!elts
.reserve(pn
->pn_count
))
2132 for (ParseNode
*next
= pn
->pn_left
->pn_head
; next
; next
= next
->pn_next
) {
2133 RootedValue
elt(cx
);
2134 if (next
->isKind(PNK_EXPORT_SPEC
)) {
2135 if (!exportSpecifier(next
, &elt
))
2138 if (!builder
.exportBatchSpecifier(&pn
->pn_pos
, &elt
))
2141 elts
.infallibleAppend(elt
);
2146 if (!function(kid
, AST_FUNC_DECL
, &decl
))
2153 if (!variableDeclaration(kid
, kind
== PNK_LET
, &decl
))
2158 LOCAL_NOT_REACHED("unexpected statement type");
2161 RootedValue
moduleSpec(cx
, NullValue());
2162 if (pn
->isKind(PNK_EXPORT_FROM
) && !literal(pn
->pn_right
, &moduleSpec
))
2165 return builder
.exportDeclaration(decl
, elts
, moduleSpec
, &pn
->pn_pos
, dst
);
2169 ASTSerializer::exportSpecifier(ParseNode
*pn
, MutableHandleValue dst
)
2171 JS_ASSERT(pn
->isKind(PNK_EXPORT_SPEC
));
2173 RootedValue
bindingName(cx
);
2174 RootedValue
exportName(cx
);
2175 return identifier(pn
->pn_left
, &bindingName
) &&
2176 identifier(pn
->pn_right
, &exportName
) &&
2177 builder
.exportSpecifier(bindingName
, exportName
, &pn
->pn_pos
, dst
);
2181 ASTSerializer::switchCase(ParseNode
*pn
, MutableHandleValue dst
)
2183 JS_ASSERT_IF(pn
->pn_left
, pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
2184 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_right
->pn_pos
));
2186 NodeVector
stmts(cx
);
2188 RootedValue
expr(cx
);
2190 return optExpression(pn
->pn_left
, &expr
) &&
2191 statements(pn
->pn_right
, stmts
) &&
2192 builder
.switchCase(expr
, stmts
, &pn
->pn_pos
, dst
);
2196 ASTSerializer::switchStatement(ParseNode
*pn
, MutableHandleValue dst
)
2198 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
2199 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_right
->pn_pos
));
2201 RootedValue
disc(cx
);
2203 if (!expression(pn
->pn_left
, &disc
))
2206 ParseNode
*listNode
;
2209 if (pn
->pn_right
->isKind(PNK_LEXICALSCOPE
)) {
2210 listNode
= pn
->pn_right
->pn_expr
;
2213 listNode
= pn
->pn_right
;
2217 NodeVector
cases(cx
);
2218 if (!cases
.reserve(listNode
->pn_count
))
2221 for (ParseNode
*next
= listNode
->pn_head
; next
; next
= next
->pn_next
) {
2222 RootedValue
child(cx
);
2223 if (!switchCase(next
, &child
))
2225 cases
.infallibleAppend(child
);
2228 return builder
.switchStatement(disc
, cases
, lexical
, &pn
->pn_pos
, dst
);
2232 ASTSerializer::catchClause(ParseNode
*pn
, bool *isGuarded
, MutableHandleValue dst
)
2234 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid1
->pn_pos
));
2235 JS_ASSERT_IF(pn
->pn_kid2
, pn
->pn_pos
.encloses(pn
->pn_kid2
->pn_pos
));
2236 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid3
->pn_pos
));
2238 RootedValue
var(cx
), guard(cx
), body(cx
);
2240 if (!pattern(pn
->pn_kid1
, nullptr, &var
) ||
2241 !optExpression(pn
->pn_kid2
, &guard
)) {
2245 *isGuarded
= !guard
.isMagic(JS_SERIALIZE_NO_NODE
);
2247 return statement(pn
->pn_kid3
, &body
) &&
2248 builder
.catchClause(var
, guard
, body
, &pn
->pn_pos
, dst
);
2252 ASTSerializer::tryStatement(ParseNode
*pn
, MutableHandleValue dst
)
2254 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid1
->pn_pos
));
2255 JS_ASSERT_IF(pn
->pn_kid2
, pn
->pn_pos
.encloses(pn
->pn_kid2
->pn_pos
));
2256 JS_ASSERT_IF(pn
->pn_kid3
, pn
->pn_pos
.encloses(pn
->pn_kid3
->pn_pos
));
2258 RootedValue
body(cx
);
2259 if (!statement(pn
->pn_kid1
, &body
))
2262 NodeVector
guarded(cx
);
2263 RootedValue
unguarded(cx
, NullValue());
2266 if (!guarded
.reserve(pn
->pn_kid2
->pn_count
))
2269 for (ParseNode
*next
= pn
->pn_kid2
->pn_head
; next
; next
= next
->pn_next
) {
2270 RootedValue
clause(cx
);
2272 if (!catchClause(next
->pn_expr
, &isGuarded
, &clause
))
2275 guarded
.infallibleAppend(clause
);
2281 RootedValue
finally(cx
);
2282 return optStatement(pn
->pn_kid3
, &finally
) &&
2283 builder
.tryStatement(body
, guarded
, unguarded
, finally
, &pn
->pn_pos
, dst
);
2287 ASTSerializer::forInit(ParseNode
*pn
, MutableHandleValue dst
)
2290 dst
.setMagic(JS_SERIALIZE_NO_NODE
);
2294 return (pn
->isKind(PNK_VAR
) || pn
->isKind(PNK_CONST
))
2295 ? variableDeclaration(pn
, false, dst
)
2296 : expression(pn
, dst
);
2300 ASTSerializer::forOf(ParseNode
*loop
, ParseNode
*head
, HandleValue var
, HandleValue stmt
,
2301 MutableHandleValue dst
)
2303 RootedValue
expr(cx
);
2305 return expression(head
->pn_kid3
, &expr
) &&
2306 builder
.forOfStatement(var
, expr
, stmt
, &loop
->pn_pos
, dst
);
2310 ASTSerializer::forIn(ParseNode
*loop
, ParseNode
*head
, HandleValue var
, HandleValue stmt
,
2311 MutableHandleValue dst
)
2313 RootedValue
expr(cx
);
2314 bool isForEach
= loop
->pn_iflags
& JSITER_FOREACH
;
2316 return expression(head
->pn_kid3
, &expr
) &&
2317 builder
.forInStatement(var
, expr
, stmt
, isForEach
, &loop
->pn_pos
, dst
);
2321 ASTSerializer::statement(ParseNode
*pn
, MutableHandleValue dst
)
2323 JS_CHECK_RECURSION(cx
, return false);
2324 switch (pn
->getKind()) {
2328 return declaration(pn
, dst
);
2331 return pn
->isArity(PN_BINARY
)
2332 ? let(pn
, false, dst
)
2333 : declaration(pn
, dst
);
2336 return importDeclaration(pn
, dst
);
2339 case PNK_EXPORT_FROM
:
2340 return exportDeclaration(pn
, dst
);
2343 LOCAL_ASSERT(pn
->isUsed());
2344 return statement(pn
->pn_lexdef
, dst
);
2348 RootedValue
expr(cx
);
2349 return expression(pn
->pn_kid
, &expr
) &&
2350 builder
.expressionStatement(expr
, &pn
->pn_pos
, dst
);
2352 return builder
.emptyStatement(&pn
->pn_pos
, dst
);
2354 case PNK_LEXICALSCOPE
:
2356 if (!pn
->isKind(PNK_STATEMENTLIST
))
2357 return statement(pn
, dst
);
2360 case PNK_STATEMENTLIST
:
2361 return blockStatement(pn
, dst
);
2365 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid1
->pn_pos
));
2366 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid2
->pn_pos
));
2367 JS_ASSERT_IF(pn
->pn_kid3
, pn
->pn_pos
.encloses(pn
->pn_kid3
->pn_pos
));
2369 RootedValue
test(cx
), cons(cx
), alt(cx
);
2371 return expression(pn
->pn_kid1
, &test
) &&
2372 statement(pn
->pn_kid2
, &cons
) &&
2373 optStatement(pn
->pn_kid3
, &alt
) &&
2374 builder
.ifStatement(test
, cons
, alt
, &pn
->pn_pos
, dst
);
2378 return switchStatement(pn
, dst
);
2381 return tryStatement(pn
, dst
);
2386 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
2387 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_right
->pn_pos
));
2389 RootedValue
expr(cx
), stmt(cx
);
2391 return expression(pn
->pn_left
, &expr
) &&
2392 statement(pn
->pn_right
, &stmt
) &&
2393 (pn
->isKind(PNK_WITH
)
2394 ? builder
.withStatement(expr
, stmt
, &pn
->pn_pos
, dst
)
2395 : builder
.whileStatement(expr
, stmt
, &pn
->pn_pos
, dst
));
2400 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
2401 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_right
->pn_pos
));
2403 RootedValue
stmt(cx
), test(cx
);
2405 return statement(pn
->pn_left
, &stmt
) &&
2406 expression(pn
->pn_right
, &test
) &&
2407 builder
.doWhileStatement(stmt
, test
, &pn
->pn_pos
, dst
);
2412 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
2413 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_right
->pn_pos
));
2415 ParseNode
*head
= pn
->pn_left
;
2417 JS_ASSERT_IF(head
->pn_kid1
, head
->pn_pos
.encloses(head
->pn_kid1
->pn_pos
));
2418 JS_ASSERT_IF(head
->pn_kid2
, head
->pn_pos
.encloses(head
->pn_kid2
->pn_pos
));
2419 JS_ASSERT_IF(head
->pn_kid3
, head
->pn_pos
.encloses(head
->pn_kid3
->pn_pos
));
2421 RootedValue
stmt(cx
);
2422 if (!statement(pn
->pn_right
, &stmt
))
2425 if (head
->isKind(PNK_FORIN
)) {
2426 RootedValue
var(cx
);
2427 return (!head
->pn_kid1
2428 ? pattern(head
->pn_kid2
, nullptr, &var
)
2429 : head
->pn_kid1
->isKind(PNK_LEXICALSCOPE
)
2430 ? variableDeclaration(head
->pn_kid1
->pn_expr
, true, &var
)
2431 : variableDeclaration(head
->pn_kid1
, false, &var
)) &&
2432 forIn(pn
, head
, var
, stmt
, dst
);
2435 if (head
->isKind(PNK_FOROF
)) {
2436 RootedValue
var(cx
);
2437 return (!head
->pn_kid1
2438 ? pattern(head
->pn_kid2
, nullptr, &var
)
2439 : head
->pn_kid1
->isKind(PNK_LEXICALSCOPE
)
2440 ? variableDeclaration(head
->pn_kid1
->pn_expr
, true, &var
)
2441 : variableDeclaration(head
->pn_kid1
, false, &var
)) &&
2442 forOf(pn
, head
, var
, stmt
, dst
);
2445 RootedValue
init(cx
), test(cx
), update(cx
);
2447 return forInit(head
->pn_kid1
, &init
) &&
2448 optExpression(head
->pn_kid2
, &test
) &&
2449 optExpression(head
->pn_kid3
, &update
) &&
2450 builder
.forStatement(init
, test
, update
, stmt
, &pn
->pn_pos
, dst
);
2453 /* Synthesized by the parser when a for-in loop contains a variable initializer. */
2456 LOCAL_ASSERT(pn
->pn_count
== 2);
2458 ParseNode
*prelude
= pn
->pn_head
;
2459 ParseNode
*loop
= prelude
->pn_next
;
2461 LOCAL_ASSERT(prelude
->isKind(PNK_VAR
) && loop
->isKind(PNK_FOR
));
2463 RootedValue
var(cx
);
2464 if (!variableDeclaration(prelude
, false, &var
))
2467 ParseNode
*head
= loop
->pn_left
;
2468 JS_ASSERT(head
->isKind(PNK_FORIN
));
2470 RootedValue
stmt(cx
);
2472 return statement(loop
->pn_right
, &stmt
) && forIn(loop
, head
, var
, stmt
, dst
);
2478 RootedValue
label(cx
);
2479 RootedAtom
pnAtom(cx
, pn
->pn_atom
);
2480 return optIdentifier(pnAtom
, nullptr, &label
) &&
2481 (pn
->isKind(PNK_BREAK
)
2482 ? builder
.breakStatement(label
, &pn
->pn_pos
, dst
)
2483 : builder
.continueStatement(label
, &pn
->pn_pos
, dst
));
2488 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_expr
->pn_pos
));
2490 RootedValue
label(cx
), stmt(cx
);
2491 RootedAtom
pnAtom(cx
, pn
->as
<LabeledStatement
>().label());
2492 return identifier(pnAtom
, nullptr, &label
) &&
2493 statement(pn
->pn_expr
, &stmt
) &&
2494 builder
.labeledStatement(label
, stmt
, &pn
->pn_pos
, dst
);
2500 JS_ASSERT_IF(pn
->pn_kid
, pn
->pn_pos
.encloses(pn
->pn_kid
->pn_pos
));
2502 RootedValue
arg(cx
);
2504 return optExpression(pn
->pn_kid
, &arg
) &&
2505 (pn
->isKind(PNK_THROW
)
2506 ? builder
.throwStatement(arg
, &pn
->pn_pos
, dst
)
2507 : builder
.returnStatement(arg
, &pn
->pn_pos
, dst
));
2511 return builder
.debuggerStatement(&pn
->pn_pos
, dst
);
2514 return builder
.emptyStatement(&pn
->pn_pos
, dst
);
2517 LOCAL_NOT_REACHED("unexpected statement type");
2522 ASTSerializer::leftAssociate(ParseNode
*pn
, MutableHandleValue dst
)
2524 JS_ASSERT(pn
->isArity(PN_LIST
));
2525 JS_ASSERT(pn
->pn_count
>= 1);
2527 ParseNodeKind kind
= pn
->getKind();
2528 bool lor
= kind
== PNK_OR
;
2529 bool logop
= lor
|| (kind
== PNK_AND
);
2531 ParseNode
*head
= pn
->pn_head
;
2532 RootedValue
left(cx
);
2533 if (!expression(head
, &left
))
2535 for (ParseNode
*next
= head
->pn_next
; next
; next
= next
->pn_next
) {
2536 RootedValue
right(cx
);
2537 if (!expression(next
, &right
))
2540 TokenPos
subpos(pn
->pn_pos
.begin
, next
->pn_pos
.end
);
2543 if (!builder
.logicalExpression(lor
, left
, right
, &subpos
, &left
))
2546 BinaryOperator op
= binop(pn
->getKind(), pn
->getOp());
2547 LOCAL_ASSERT(op
> BINOP_ERR
&& op
< BINOP_LIMIT
);
2549 if (!builder
.binaryExpression(op
, left
, right
, &subpos
, &left
))
2559 ASTSerializer::comprehensionBlock(ParseNode
*pn
, MutableHandleValue dst
)
2561 LOCAL_ASSERT(pn
->isArity(PN_BINARY
));
2563 ParseNode
*in
= pn
->pn_left
;
2565 LOCAL_ASSERT(in
&& (in
->isKind(PNK_FORIN
) || in
->isKind(PNK_FOROF
)));
2567 bool isForEach
= pn
->pn_iflags
& JSITER_FOREACH
;
2568 bool isForOf
= in
->isKind(PNK_FOROF
);
2570 RootedValue
patt(cx
), src(cx
);
2571 return pattern(in
->pn_kid2
, nullptr, &patt
) &&
2572 expression(in
->pn_kid3
, &src
) &&
2573 builder
.comprehensionBlock(patt
, src
, isForEach
, isForOf
, &in
->pn_pos
, dst
);
2577 ASTSerializer::comprehension(ParseNode
*pn
, MutableHandleValue dst
)
2579 LOCAL_ASSERT(pn
->isKind(PNK_FOR
));
2581 NodeVector
blocks(cx
);
2583 ParseNode
*next
= pn
;
2584 while (next
->isKind(PNK_FOR
)) {
2585 RootedValue
block(cx
);
2586 if (!comprehensionBlock(next
, &block
) || !blocks
.append(block
))
2588 next
= next
->pn_right
;
2591 RootedValue
filter(cx
, MagicValue(JS_SERIALIZE_NO_NODE
));
2593 if (next
->isKind(PNK_IF
)) {
2594 if (!optExpression(next
->pn_kid1
, &filter
))
2596 next
= next
->pn_kid2
;
2597 } else if (next
->isKind(PNK_STATEMENTLIST
) && next
->pn_count
== 0) {
2598 /* FoldConstants optimized away the push. */
2599 NodeVector
empty(cx
);
2600 return builder
.arrayExpression(empty
, &pn
->pn_pos
, dst
);
2603 LOCAL_ASSERT(next
->isKind(PNK_ARRAYPUSH
));
2605 RootedValue
body(cx
);
2607 return expression(next
->pn_kid
, &body
) &&
2608 builder
.comprehensionExpression(body
, blocks
, filter
, &pn
->pn_pos
, dst
);
2612 ASTSerializer::generatorExpression(ParseNode
*pn
, MutableHandleValue dst
)
2614 LOCAL_ASSERT(pn
->isKind(PNK_FOR
));
2616 NodeVector
blocks(cx
);
2618 ParseNode
*next
= pn
;
2619 while (next
->isKind(PNK_FOR
)) {
2620 RootedValue
block(cx
);
2621 if (!comprehensionBlock(next
, &block
) || !blocks
.append(block
))
2623 next
= next
->pn_right
;
2626 RootedValue
filter(cx
, MagicValue(JS_SERIALIZE_NO_NODE
));
2628 if (next
->isKind(PNK_IF
)) {
2629 if (!optExpression(next
->pn_kid1
, &filter
))
2631 next
= next
->pn_kid2
;
2634 LOCAL_ASSERT(next
->isKind(PNK_SEMI
) &&
2635 next
->pn_kid
->isKind(PNK_YIELD
) &&
2636 next
->pn_kid
->pn_kid
);
2638 RootedValue
body(cx
);
2640 return expression(next
->pn_kid
->pn_kid
, &body
) &&
2641 builder
.generatorExpression(body
, blocks
, filter
, &pn
->pn_pos
, dst
);
2645 ASTSerializer::expression(ParseNode
*pn
, MutableHandleValue dst
)
2647 JS_CHECK_RECURSION(cx
, return false);
2648 switch (pn
->getKind()) {
2651 ASTType type
= pn
->pn_funbox
->function()->isArrow() ? AST_ARROW_EXPR
: AST_FUNC_EXPR
;
2652 return function(pn
, type
, dst
);
2657 NodeVector
exprs(cx
);
2658 return expressions(pn
, exprs
) &&
2659 builder
.sequenceExpression(exprs
, &pn
->pn_pos
, dst
);
2662 case PNK_CONDITIONAL
:
2664 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid1
->pn_pos
));
2665 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid2
->pn_pos
));
2666 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid3
->pn_pos
));
2668 RootedValue
test(cx
), cons(cx
), alt(cx
);
2670 return expression(pn
->pn_kid1
, &test
) &&
2671 expression(pn
->pn_kid2
, &cons
) &&
2672 expression(pn
->pn_kid3
, &alt
) &&
2673 builder
.conditionalExpression(test
, cons
, alt
, &pn
->pn_pos
, dst
);
2679 if (pn
->isArity(PN_BINARY
)) {
2680 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
2681 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_right
->pn_pos
));
2683 RootedValue
left(cx
), right(cx
);
2684 return expression(pn
->pn_left
, &left
) &&
2685 expression(pn
->pn_right
, &right
) &&
2686 builder
.logicalExpression(pn
->isKind(PNK_OR
), left
, right
, &pn
->pn_pos
, dst
);
2688 return leftAssociate(pn
, dst
);
2691 case PNK_PREINCREMENT
:
2692 case PNK_PREDECREMENT
:
2694 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid
->pn_pos
));
2696 bool inc
= pn
->isKind(PNK_PREINCREMENT
);
2697 RootedValue
expr(cx
);
2698 return expression(pn
->pn_kid
, &expr
) &&
2699 builder
.updateExpression(expr
, inc
, true, &pn
->pn_pos
, dst
);
2702 case PNK_POSTINCREMENT
:
2703 case PNK_POSTDECREMENT
:
2705 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid
->pn_pos
));
2707 bool inc
= pn
->isKind(PNK_POSTINCREMENT
);
2708 RootedValue
expr(cx
);
2709 return expression(pn
->pn_kid
, &expr
) &&
2710 builder
.updateExpression(expr
, inc
, false, &pn
->pn_pos
, dst
);
2716 case PNK_BITORASSIGN
:
2717 case PNK_BITXORASSIGN
:
2718 case PNK_BITANDASSIGN
:
2721 case PNK_URSHASSIGN
:
2726 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
2727 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_right
->pn_pos
));
2729 AssignmentOperator op
= aop(pn
->getOp());
2730 LOCAL_ASSERT(op
> AOP_ERR
&& op
< AOP_LIMIT
);
2732 RootedValue
lhs(cx
), rhs(cx
);
2733 return pattern(pn
->pn_left
, nullptr, &lhs
) &&
2734 expression(pn
->pn_right
, &rhs
) &&
2735 builder
.assignmentExpression(op
, lhs
, rhs
, &pn
->pn_pos
, dst
);
2758 case PNK_INSTANCEOF
:
2759 if (pn
->isArity(PN_BINARY
)) {
2760 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
2761 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_right
->pn_pos
));
2763 BinaryOperator op
= binop(pn
->getKind(), pn
->getOp());
2764 LOCAL_ASSERT(op
> BINOP_ERR
&& op
< BINOP_LIMIT
);
2766 RootedValue
left(cx
), right(cx
);
2767 return expression(pn
->pn_left
, &left
) &&
2768 expression(pn
->pn_right
, &right
) &&
2769 builder
.binaryExpression(op
, left
, right
, &pn
->pn_pos
, dst
);
2771 return leftAssociate(pn
, dst
);
2780 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid
->pn_pos
));
2782 UnaryOperator op
= unop(pn
->getKind(), pn
->getOp());
2783 LOCAL_ASSERT(op
> UNOP_ERR
&& op
< UNOP_LIMIT
);
2785 RootedValue
expr(cx
);
2786 return expression(pn
->pn_kid
, &expr
) &&
2787 builder
.unaryExpression(op
, expr
, &pn
->pn_pos
, dst
);
2790 #if JS_HAS_GENERATOR_EXPRS
2792 return generatorExpression(pn
->generatorExpr(), dst
);
2796 case PNK_TAGGED_TEMPLATE
:
2799 ParseNode
*next
= pn
->pn_head
;
2800 JS_ASSERT(pn
->pn_pos
.encloses(next
->pn_pos
));
2802 RootedValue
callee(cx
);
2803 if (!expression(next
, &callee
))
2806 NodeVector
args(cx
);
2807 if (!args
.reserve(pn
->pn_count
- 1))
2810 for (next
= next
->pn_next
; next
; next
= next
->pn_next
) {
2811 JS_ASSERT(pn
->pn_pos
.encloses(next
->pn_pos
));
2813 RootedValue
arg(cx
);
2814 if (!expression(next
, &arg
))
2816 args
.infallibleAppend(arg
);
2819 if (pn
->getKind() == PNK_TAGGED_TEMPLATE
)
2820 return builder
.taggedTemplate(callee
, args
, &pn
->pn_pos
, dst
);
2822 return pn
->isKind(PNK_NEW
)
2823 ? builder
.newExpression(callee
, args
, &pn
->pn_pos
, dst
)
2825 : builder
.callExpression(callee
, args
, &pn
->pn_pos
, dst
);
2830 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_expr
->pn_pos
));
2832 RootedValue
expr(cx
), id(cx
);
2833 RootedAtom
pnAtom(cx
, pn
->pn_atom
);
2834 return expression(pn
->pn_expr
, &expr
) &&
2835 identifier(pnAtom
, nullptr, &id
) &&
2836 builder
.memberExpression(false, expr
, id
, &pn
->pn_pos
, dst
);
2841 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_left
->pn_pos
));
2842 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_right
->pn_pos
));
2844 RootedValue
left(cx
), right(cx
);
2845 return expression(pn
->pn_left
, &left
) &&
2846 expression(pn
->pn_right
, &right
) &&
2847 builder
.memberExpression(true, left
, right
, &pn
->pn_pos
, dst
);
2850 case PNK_CALLSITEOBJ
:
2853 if (!raw
.reserve(pn
->pn_head
->pn_count
))
2855 for (ParseNode
*next
= pn
->pn_head
->pn_head
; next
; next
= next
->pn_next
) {
2856 JS_ASSERT(pn
->pn_pos
.encloses(next
->pn_pos
));
2858 RootedValue
expr(cx
);
2859 expr
.setString(next
->pn_atom
);
2860 raw
.infallibleAppend(expr
);
2863 NodeVector
cooked(cx
);
2864 if (!cooked
.reserve(pn
->pn_count
- 1))
2867 for (ParseNode
*next
= pn
->pn_head
->pn_next
; next
; next
= next
->pn_next
) {
2868 JS_ASSERT(pn
->pn_pos
.encloses(next
->pn_pos
));
2870 RootedValue
expr(cx
);
2871 expr
.setString(next
->pn_atom
);
2872 cooked
.infallibleAppend(expr
);
2875 return builder
.callSiteObj(raw
, cooked
, &pn
->pn_pos
, dst
);
2880 NodeVector
elts(cx
);
2881 if (!elts
.reserve(pn
->pn_count
))
2884 for (ParseNode
*next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
2885 JS_ASSERT(pn
->pn_pos
.encloses(next
->pn_pos
));
2887 if (next
->isKind(PNK_ELISION
)) {
2888 elts
.infallibleAppend(NullValue());
2890 RootedValue
expr(cx
);
2891 if (!expression(next
, &expr
))
2893 elts
.infallibleAppend(expr
);
2897 return builder
.arrayExpression(elts
, &pn
->pn_pos
, dst
);
2902 RootedValue
expr(cx
);
2903 return expression(pn
->pn_kid
, &expr
) &&
2904 builder
.spreadExpression(expr
, &pn
->pn_pos
, dst
);
2907 case PNK_COMPUTED_NAME
:
2909 RootedValue
name(cx
);
2910 return expression(pn
->pn_kid
, &name
) &&
2911 builder
.computedName(name
, &pn
->pn_pos
, dst
);
2916 NodeVector
elts(cx
);
2917 if (!elts
.reserve(pn
->pn_count
))
2920 for (ParseNode
*next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
2921 JS_ASSERT(pn
->pn_pos
.encloses(next
->pn_pos
));
2923 RootedValue
prop(cx
);
2924 if (!property(next
, &prop
))
2926 elts
.infallibleAppend(prop
);
2929 return builder
.objectExpression(elts
, &pn
->pn_pos
, dst
);
2933 return identifier(pn
, dst
);
2936 return builder
.thisExpression(&pn
->pn_pos
, dst
);
2938 case PNK_TEMPLATE_STRING_LIST
:
2940 NodeVector
elts(cx
);
2941 if (!elts
.reserve(pn
->pn_count
))
2944 for (ParseNode
*next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
2945 JS_ASSERT(pn
->pn_pos
.encloses(next
->pn_pos
));
2947 RootedValue
expr(cx
);
2948 if (!expression(next
, &expr
))
2950 elts
.infallibleAppend(expr
);
2953 return builder
.templateLiteral(elts
, &pn
->pn_pos
, dst
);
2956 case PNK_TEMPLATE_STRING
:
2963 return literal(pn
, dst
);
2965 case PNK_YIELD_STAR
:
2967 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_kid
->pn_pos
));
2969 RootedValue
arg(cx
);
2970 return expression(pn
->pn_kid
, &arg
) &&
2971 builder
.yieldExpression(arg
, Delegating
, &pn
->pn_pos
, dst
);
2976 JS_ASSERT_IF(pn
->pn_kid
, pn
->pn_pos
.encloses(pn
->pn_kid
->pn_pos
));
2978 RootedValue
arg(cx
);
2979 return optExpression(pn
->pn_kid
, &arg
) &&
2980 builder
.yieldExpression(arg
, NotDelegating
, &pn
->pn_pos
, dst
);
2984 JS_ASSERT(pn
->pn_pos
.encloses(pn
->pn_head
->pn_pos
));
2986 /* NB: it's no longer the case that pn_count could be 2. */
2987 LOCAL_ASSERT(pn
->pn_count
== 1);
2988 LOCAL_ASSERT(pn
->pn_head
->isKind(PNK_LEXICALSCOPE
));
2990 return comprehension(pn
->pn_head
->pn_expr
, dst
);
2993 return let(pn
, true, dst
);
2996 LOCAL_NOT_REACHED("unexpected expression type");
3001 ASTSerializer::propertyName(ParseNode
*pn
, MutableHandleValue dst
)
3003 if (pn
->isKind(PNK_COMPUTED_NAME
))
3004 return expression(pn
, dst
);
3005 if (pn
->isKind(PNK_NAME
))
3006 return identifier(pn
, dst
);
3008 LOCAL_ASSERT(pn
->isKind(PNK_STRING
) || pn
->isKind(PNK_NUMBER
));
3010 return literal(pn
, dst
);
3014 ASTSerializer::property(ParseNode
*pn
, MutableHandleValue dst
)
3017 switch (pn
->getOp()) {
3022 case JSOP_INITPROP_GETTER
:
3026 case JSOP_INITPROP_SETTER
:
3031 LOCAL_NOT_REACHED("unexpected object-literal property");
3034 bool isShorthand
= pn
->isKind(PNK_SHORTHAND
);
3035 bool isMethod
= pn
->pn_right
->isKind(PNK_FUNCTION
) && kind
== PROP_INIT
;
3036 RootedValue
key(cx
), val(cx
);
3037 return propertyName(pn
->pn_left
, &key
) &&
3038 expression(pn
->pn_right
, &val
) &&
3039 builder
.propertyInitializer(key
, val
, kind
, isShorthand
, isMethod
, &pn
->pn_pos
, dst
);
3043 ASTSerializer::literal(ParseNode
*pn
, MutableHandleValue dst
)
3045 RootedValue
val(cx
);
3046 switch (pn
->getKind()) {
3047 case PNK_TEMPLATE_STRING
:
3049 val
.setString(pn
->pn_atom
);
3054 RootedObject
re1(cx
, pn
->as
<RegExpLiteral
>().objbox()->object
);
3055 LOCAL_ASSERT(re1
&& re1
->is
<RegExpObject
>());
3057 RootedObject
re2(cx
, CloneRegExpObject(cx
, re1
));
3061 val
.setObject(*re2
);
3066 val
.setNumber(pn
->pn_dval
);
3074 val
.setBoolean(true);
3078 val
.setBoolean(false);
3082 LOCAL_NOT_REACHED("unexpected literal type");
3085 return builder
.literal(val
, &pn
->pn_pos
, dst
);
3089 ASTSerializer::arrayPattern(ParseNode
*pn
, VarDeclKind
*pkind
, MutableHandleValue dst
)
3091 JS_ASSERT(pn
->isKind(PNK_ARRAY
));
3093 NodeVector
elts(cx
);
3094 if (!elts
.reserve(pn
->pn_count
))
3097 for (ParseNode
*next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
3098 if (next
->isKind(PNK_ELISION
)) {
3099 elts
.infallibleAppend(NullValue());
3100 } else if (next
->isKind(PNK_SPREAD
)) {
3101 RootedValue
target(cx
);
3102 RootedValue
spread(cx
);
3103 if (!pattern(next
->pn_kid
, pkind
, &target
))
3105 if(!builder
.spreadExpression(target
, &next
->pn_pos
, &spread
))
3107 elts
.infallibleAppend(spread
);
3109 RootedValue
patt(cx
);
3110 if (!pattern(next
, pkind
, &patt
))
3112 elts
.infallibleAppend(patt
);
3116 return builder
.arrayPattern(elts
, &pn
->pn_pos
, dst
);
3120 ASTSerializer::objectPattern(ParseNode
*pn
, VarDeclKind
*pkind
, MutableHandleValue dst
)
3122 JS_ASSERT(pn
->isKind(PNK_OBJECT
));
3124 NodeVector
elts(cx
);
3125 if (!elts
.reserve(pn
->pn_count
))
3128 for (ParseNode
*next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
3129 LOCAL_ASSERT(next
->isOp(JSOP_INITPROP
));
3131 RootedValue
key(cx
), patt(cx
), prop(cx
);
3132 if (!propertyName(next
->pn_left
, &key
) ||
3133 !pattern(next
->pn_right
, pkind
, &patt
) ||
3134 !builder
.propertyPattern(key
, patt
, next
->isKind(PNK_SHORTHAND
), &next
->pn_pos
,
3139 elts
.infallibleAppend(prop
);
3142 return builder
.objectPattern(elts
, &pn
->pn_pos
, dst
);
3146 ASTSerializer::pattern(ParseNode
*pn
, VarDeclKind
*pkind
, MutableHandleValue dst
)
3148 JS_CHECK_RECURSION(cx
, return false);
3149 switch (pn
->getKind()) {
3151 return objectPattern(pn
, pkind
, dst
);
3154 return arrayPattern(pn
, pkind
, dst
);
3157 if (pkind
&& (pn
->pn_dflags
& PND_CONST
))
3158 *pkind
= VARDECL_CONST
;
3162 return expression(pn
, dst
);
3167 ASTSerializer::identifier(HandleAtom atom
, TokenPos
*pos
, MutableHandleValue dst
)
3169 RootedValue
atomContentsVal(cx
, unrootedAtomContents(atom
));
3170 return builder
.identifier(atomContentsVal
, pos
, dst
);
3174 ASTSerializer::identifier(ParseNode
*pn
, MutableHandleValue dst
)
3176 LOCAL_ASSERT(pn
->isArity(PN_NAME
) || pn
->isArity(PN_NULLARY
));
3177 LOCAL_ASSERT(pn
->pn_atom
);
3179 RootedAtom
pnAtom(cx
, pn
->pn_atom
);
3180 return identifier(pnAtom
, &pn
->pn_pos
, dst
);
3184 ASTSerializer::function(ParseNode
*pn
, ASTType type
, MutableHandleValue dst
)
3186 RootedFunction
func(cx
, pn
->pn_funbox
->function());
3188 // FIXME: Provide more information (legacy generator vs star generator).
3189 bool isGenerator
= pn
->pn_funbox
->isGenerator();
3192 #if JS_HAS_EXPR_CLOSURES
3193 func
->isExprClosure();
3199 RootedAtom
funcAtom(cx
, func
->atom());
3200 if (!optIdentifier(funcAtom
, nullptr, &id
))
3203 NodeVector
args(cx
);
3204 NodeVector
defaults(cx
);
3206 RootedValue
body(cx
), rest(cx
);
3207 if (func
->hasRest())
3208 rest
.setUndefined();
3211 return functionArgsAndBody(pn
->pn_body
, args
, defaults
, &body
, &rest
) &&
3212 builder
.function(type
, &pn
->pn_pos
, id
, args
, defaults
, body
,
3213 rest
, isGenerator
, isExpression
, dst
);
3217 ASTSerializer::functionArgsAndBody(ParseNode
*pn
, NodeVector
&args
, NodeVector
&defaults
,
3218 MutableHandleValue body
, MutableHandleValue rest
)
3223 /* Extract the args and body separately. */
3224 if (pn
->isKind(PNK_ARGSBODY
)) {
3226 pnbody
= pn
->last();
3232 ParseNode
*pndestruct
;
3234 /* Extract the destructuring assignments. */
3235 if (pnbody
->isArity(PN_LIST
) && (pnbody
->pn_xflags
& PNX_DESTRUCT
)) {
3236 ParseNode
*head
= pnbody
->pn_head
;
3237 LOCAL_ASSERT(head
&& head
->isKind(PNK_SEMI
));
3239 pndestruct
= head
->pn_kid
;
3240 LOCAL_ASSERT(pndestruct
);
3241 LOCAL_ASSERT(pndestruct
->isKind(PNK_VAR
));
3243 pndestruct
= nullptr;
3246 /* Serialize the arguments and body. */
3247 switch (pnbody
->getKind()) {
3248 case PNK_RETURN
: /* expression closure, no destructured args */
3249 return functionArgs(pn
, pnargs
, nullptr, pnbody
, args
, defaults
, rest
) &&
3250 expression(pnbody
->pn_kid
, body
);
3252 case PNK_SEQ
: /* expression closure with destructured args */
3254 ParseNode
*pnstart
= pnbody
->pn_head
->pn_next
;
3255 LOCAL_ASSERT(pnstart
&& pnstart
->isKind(PNK_RETURN
));
3257 return functionArgs(pn
, pnargs
, pndestruct
, pnbody
, args
, defaults
, rest
) &&
3258 expression(pnstart
->pn_kid
, body
);
3261 case PNK_STATEMENTLIST
: /* statement closure */
3263 ParseNode
*pnstart
= (pnbody
->pn_xflags
& PNX_DESTRUCT
)
3264 ? pnbody
->pn_head
->pn_next
3267 return functionArgs(pn
, pnargs
, pndestruct
, pnbody
, args
, defaults
, rest
) &&
3268 functionBody(pnstart
, &pnbody
->pn_pos
, body
);
3272 LOCAL_NOT_REACHED("unexpected function contents");
3277 ASTSerializer::functionArgs(ParseNode
*pn
, ParseNode
*pnargs
, ParseNode
*pndestruct
,
3278 ParseNode
*pnbody
, NodeVector
&args
, NodeVector
&defaults
,
3279 MutableHandleValue rest
)
3282 ParseNode
*arg
= pnargs
? pnargs
->pn_head
: nullptr;
3283 ParseNode
*destruct
= pndestruct
? pndestruct
->pn_head
: nullptr;
3284 RootedValue
node(cx
);
3287 * Arguments are found in potentially two different places: 1) the
3288 * argsbody sequence (which ends with the body node), or 2) a
3289 * destructuring initialization at the beginning of the body. Loop
3290 * |arg| through the argsbody and |destruct| through the initial
3291 * destructuring assignments, stopping only when we've exhausted
3294 while ((arg
&& arg
!= pnbody
) || destruct
) {
3295 if (destruct
&& destruct
->pn_right
->frameSlot() == i
) {
3296 if (!pattern(destruct
->pn_left
, nullptr, &node
) || !args
.append(node
))
3298 destruct
= destruct
->pn_next
;
3299 } else if (arg
&& arg
!= pnbody
) {
3301 * We don't check that arg->frameSlot() == i since we
3302 * can't call that method if the arg def has been turned
3305 * function(a) { function a() { } }
3307 * There's no other way to ask a non-destructuring arg its
3308 * index in the formals list, so we rely on the ability to
3309 * ask destructuring args their index above.
3311 JS_ASSERT(arg
->isKind(PNK_NAME
) || arg
->isKind(PNK_ASSIGN
));
3312 ParseNode
*argName
= arg
->isKind(PNK_NAME
) ? arg
: arg
->pn_left
;
3313 if (!identifier(argName
, &node
))
3315 if (rest
.isUndefined() && arg
->pn_next
== pnbody
)
3316 rest
.setObject(node
.toObject());
3317 else if (!args
.append(node
))
3319 if (arg
->pn_dflags
& PND_DEFAULT
) {
3320 ParseNode
*expr
= arg
->expr();
3321 RootedValue
def(cx
);
3322 if (!expression(expr
, &def
) || !defaults
.append(def
))
3327 LOCAL_NOT_REACHED("missing function argument");
3331 JS_ASSERT(!rest
.isUndefined());
3337 ASTSerializer::functionBody(ParseNode
*pn
, TokenPos
*pos
, MutableHandleValue dst
)
3339 NodeVector
elts(cx
);
3341 /* We aren't sure how many elements there are up front, so we'll check each append. */
3342 for (ParseNode
*next
= pn
; next
; next
= next
->pn_next
) {
3343 RootedValue
child(cx
);
3344 if (!sourceElement(next
, &child
) || !elts
.append(child
))
3348 return builder
.blockStatement(elts
, pos
, dst
);
3352 reflect_parse(JSContext
*cx
, uint32_t argc
, jsval
*vp
)
3354 CallArgs args
= CallArgsFromVp(argc
, vp
);
3356 if (args
.length() < 1) {
3357 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, nullptr, JSMSG_MORE_ARGS_NEEDED
,
3358 "Reflect.parse", "0", "s");
3362 RootedString
src(cx
, ToString
<CanGC
>(cx
, args
[0]));
3366 ScopedJSFreePtr
<char> filename
;
3367 uint32_t lineno
= 1;
3370 RootedObject
builder(cx
);
3372 RootedValue
arg(cx
, args
.get(1));
3374 if (!arg
.isNullOrUndefined()) {
3375 if (!arg
.isObject()) {
3376 js_ReportValueErrorFlags(cx
, JSREPORT_ERROR
, JSMSG_UNEXPECTED_TYPE
,
3377 JSDVG_SEARCH_STACK
, arg
, js::NullPtr(),
3378 "not an object", nullptr);
3382 RootedObject
config(cx
, &arg
.toObject());
3384 RootedValue
prop(cx
);
3387 RootedId
locId(cx
, NameToId(cx
->names().loc
));
3388 RootedValue
trueVal(cx
, BooleanValue(true));
3389 if (!GetPropertyDefault(cx
, config
, locId
, trueVal
, &prop
))
3392 loc
= ToBoolean(prop
);
3396 RootedId
sourceId(cx
, NameToId(cx
->names().source
));
3397 RootedValue
nullVal(cx
, NullValue());
3398 if (!GetPropertyDefault(cx
, config
, sourceId
, nullVal
, &prop
))
3401 if (!prop
.isNullOrUndefined()) {
3402 RootedString
str(cx
, ToString
<CanGC
>(cx
, prop
));
3406 filename
= JS_EncodeString(cx
, str
);
3412 RootedId
lineId(cx
, NameToId(cx
->names().line
));
3413 RootedValue
oneValue(cx
, Int32Value(1));
3414 if (!GetPropertyDefault(cx
, config
, lineId
, oneValue
, &prop
) ||
3415 !ToUint32(cx
, prop
, &lineno
)) {
3420 /* config.builder */
3421 RootedId
builderId(cx
, NameToId(cx
->names().builder
));
3422 RootedValue
nullVal(cx
, NullValue());
3423 if (!GetPropertyDefault(cx
, config
, builderId
, nullVal
, &prop
))
3426 if (!prop
.isNullOrUndefined()) {
3427 if (!prop
.isObject()) {
3428 js_ReportValueErrorFlags(cx
, JSREPORT_ERROR
, JSMSG_UNEXPECTED_TYPE
,
3429 JSDVG_SEARCH_STACK
, prop
, js::NullPtr(),
3430 "not an object", nullptr);
3433 builder
= &prop
.toObject();
3437 /* Extract the builder methods first to report errors before parsing. */
3438 ASTSerializer
serialize(cx
, loc
, filename
, lineno
);
3439 if (!serialize
.init(builder
))
3442 JSFlatString
*flat
= src
->ensureFlat(cx
);
3446 AutoStableStringChars
flatChars(cx
);
3447 if (!flatChars
.initTwoByte(cx
, flat
))
3450 CompileOptions
options(cx
);
3451 options
.setFileAndLine(filename
, lineno
);
3452 options
.setCanLazilyParse(false);
3453 mozilla::Range
<const jschar
> chars
= flatChars
.twoByteRange();
3454 Parser
<FullParseHandler
> parser(cx
, &cx
->tempLifoAlloc(), options
, chars
.start().get(),
3455 chars
.length(), /* foldConstants = */ false, nullptr, nullptr);
3457 serialize
.setParser(&parser
);
3459 ParseNode
*pn
= parser
.parse(nullptr);
3463 RootedValue
val(cx
);
3464 if (!serialize
.program(pn
, &val
)) {
3465 args
.rval().setNull();
3469 args
.rval().set(val
);
3473 JS_PUBLIC_API(JSObject
*)
3474 JS_InitReflect(JSContext
*cx
, HandleObject obj
)
3476 static const JSFunctionSpec static_methods
[] = {
3477 JS_FN("parse", reflect_parse
, 1, 0),
3481 RootedObject
proto(cx
, obj
->as
<GlobalObject
>().getOrCreateObjectPrototype(cx
));
3484 RootedObject
Reflect(cx
, NewObjectWithGivenProto(cx
, &JSObject::class_
, proto
,
3485 obj
, SingletonObject
));
3489 if (!JS_DefineProperty(cx
, obj
, "Reflect", Reflect
, 0,
3490 JS_PropertyStub
, JS_StrictPropertyStub
)) {
3494 if (!JS_DefineFunctions(cx
, Reflect
, static_methods
))