1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sw=4 et tw=99 ft=cpp:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
20 * The Initial Developer of the Original Code is
21 * the Mozilla Corporation.
24 * Dave Herman <dherman@mozilla.com>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
41 * JS reflection package.
44 #include <string.h> /* for jsparse.h */
48 #include "jsreflect.h"
49 #include "jscntxt.h" /* for jsparse.h */
50 #include "jsbit.h" /* for jsparse.h */
51 #include "jsscript.h" /* for jsparse.h */
52 #include "jsinterp.h" /* for jsparse.h */
63 #include "jsobjinlines.h"
71 char const *aopNames
[] = {
80 ">>>=", /* AOP_URSH */
82 "^=", /* AOP_BITXOR */
86 char const *binopNames
[] = {
89 "===", /* BINOP_STRICTEQ */
90 "!==", /* BINOP_STRICTNE */
97 ">>>", /* BINOP_URSH */
99 "-", /* BINOP_MINUS */
100 "*", /* BINOP_STAR */
103 "|", /* BINOP_BITOR */
104 "^", /* BINOP_BITXOR */
105 "&", /* BINOP_BITAND */
107 "instanceof", /* BINOP_INSTANCEOF */
108 "..", /* BINOP_DBLDOT */
111 char const *unopNames
[] = {
112 "delete", /* UNOP_DELETE */
116 "~", /* UNOP_BITNOT */
117 "typeof", /* UNOP_TYPEOF */
118 "void" /* UNOP_VOID */
121 char const *nodeTypeNames
[] = {
122 #define ASTDEF(ast, str) str,
128 typedef Vector
<Value
, 8> NodeVector
;
131 * JSParseNode is a somewhat intricate data structure, and its invariants have
132 * evolved, making it more likely that there could be a disconnect between the
133 * parser and the AST serializer. We use these macros to check invariants on a
134 * parse node and raise a dynamic error on failure.
136 #define LOCAL_ASSERT(expr) \
140 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_PARSE_NODE); \
145 #define LOCAL_NOT_REACHED(expr) \
147 JS_NOT_REACHED(expr); \
148 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_PARSE_NODE); \
154 * Builder class that constructs JavaScript AST node objects. See:
156 * https://developer.mozilla.org/en/SpiderMonkey/Parser_API
158 * Bug 569487: generalize builder interface
163 char const *src
; /* source filename or null */
164 Value srcval
; /* source filename JS value or null */
167 NodeBuilder(JSContext
*c
, char const *s
)
173 return atomValue(src
, &srcval
);
180 bool atomValue(const char *s
, Value
*dst
) {
182 * Bug 575416: instead of js_Atomize, lookup constant atoms in tbl file
184 JSAtom
*atom
= js_Atomize(cx
, s
, strlen(s
), 0);
188 *dst
= Valueify(ATOM_TO_JSVAL(atom
));
192 bool newObject(JSObject
**dst
) {
193 JSObject
*nobj
= NewNonFunction
<WithProto::Class
>(cx
, &js_ObjectClass
, NULL
, NULL
);
201 bool newArray(NodeVector
&elts
, Value
*dst
);
203 bool newNode(ASTType type
, TokenPos
*pos
, JSObject
**dst
);
205 bool newNode(ASTType type
, TokenPos
*pos
, Value
*dst
) {
207 return newNode(type
, pos
, &node
) &&
208 setResult(node
, dst
);
211 bool newNode(ASTType type
, TokenPos
*pos
, const char *childName
, Value child
, Value
*dst
) {
213 return newNode(type
, pos
, &node
) &&
214 setProperty(node
, childName
, child
) &&
215 setResult(node
, dst
);
218 bool newNode(ASTType type
, TokenPos
*pos
,
219 const char *childName1
, Value child1
,
220 const char *childName2
, Value child2
,
223 return newNode(type
, pos
, &node
) &&
224 setProperty(node
, childName1
, child1
) &&
225 setProperty(node
, childName2
, child2
) &&
226 setResult(node
, dst
);
229 bool newNode(ASTType type
, TokenPos
*pos
,
230 const char *childName1
, Value child1
,
231 const char *childName2
, Value child2
,
232 const char *childName3
, Value child3
,
235 return newNode(type
, pos
, &node
) &&
236 setProperty(node
, childName1
, child1
) &&
237 setProperty(node
, childName2
, child2
) &&
238 setProperty(node
, childName3
, child3
) &&
239 setResult(node
, dst
);
242 bool newNode(ASTType type
, TokenPos
*pos
,
243 const char *childName1
, Value child1
,
244 const char *childName2
, Value child2
,
245 const char *childName3
, Value child3
,
246 const char *childName4
, Value child4
,
249 return newNode(type
, pos
, &node
) &&
250 setProperty(node
, childName1
, child1
) &&
251 setProperty(node
, childName2
, child2
) &&
252 setProperty(node
, childName3
, child3
) &&
253 setProperty(node
, childName4
, child4
) &&
254 setResult(node
, dst
);
257 bool newNode(ASTType type
, TokenPos
*pos
,
258 const char *childName1
, Value child1
,
259 const char *childName2
, Value child2
,
260 const char *childName3
, Value child3
,
261 const char *childName4
, Value child4
,
262 const char *childName5
, Value child5
,
265 return newNode(type
, pos
, &node
) &&
266 setProperty(node
, childName1
, child1
) &&
267 setProperty(node
, childName2
, child2
) &&
268 setProperty(node
, childName3
, child3
) &&
269 setProperty(node
, childName4
, child4
) &&
270 setProperty(node
, childName5
, child5
) &&
271 setResult(node
, dst
);
274 bool newListNode(ASTType type
, TokenPos
*pos
, const char *propName
,
275 NodeVector
&elts
, Value
*dst
) {
277 return newArray(elts
, &array
) &&
278 newNode(type
, pos
, propName
, array
, dst
);
281 bool setProperty(JSObject
*obj
, const char *name
, Value val
) {
282 JS_ASSERT_IF(val
.isMagic(), val
.whyMagic() == JS_SERIALIZE_NO_NODE
);
284 /* Represent "no node" as null and ensure users are not exposed to magic values. */
285 if (val
.isMagic(JS_SERIALIZE_NO_NODE
))
289 * Bug 575416: instead of js_Atomize, lookup constant atoms in tbl file
291 JSAtom
*atom
= js_Atomize(cx
, name
, strlen(name
), 0);
295 return obj
->defineProperty(cx
, ATOM_TO_JSID(atom
), val
);
298 bool setNodeLoc(JSObject
*obj
, TokenPos
*pos
);
300 bool setResult(JSObject
*obj
, Value
*dst
) {
302 dst
->setObject(*obj
);
308 * All of the public builder methods take as their last two
309 * arguments a nullable token position and a non-nullable, rooted
312 * All Value arguments are rooted. Any Value arguments representing
313 * optional subnodes may be a JS_SERIALIZE_NO_NODE magic value.
320 bool program(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
);
322 bool literal(Value val
, TokenPos
*pos
, Value
*dst
);
324 bool identifier(Value name
, TokenPos
*pos
, Value
*dst
);
326 bool function(ASTType type
, TokenPos
*pos
,
327 Value id
, NodeVector
&args
, Value body
,
328 bool isGenerator
, bool isExpression
, Value
*dst
);
330 bool variableDeclarator(Value id
, Value init
, TokenPos
*pos
, Value
*dst
);
332 bool switchCase(Value expr
, NodeVector
&elts
, TokenPos
*pos
, Value
*dst
);
334 bool catchClause(Value var
, Value guard
, Value body
, TokenPos
*pos
, Value
*dst
);
336 bool propertyInitializer(Value key
, Value val
, PropKind kind
, TokenPos
*pos
, Value
*dst
);
343 bool blockStatement(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
);
345 bool expressionStatement(Value expr
, TokenPos
*pos
, Value
*dst
);
347 bool emptyStatement(TokenPos
*pos
, Value
*dst
);
349 bool ifStatement(Value test
, Value cons
, Value alt
, TokenPos
*pos
, Value
*dst
);
351 bool breakStatement(Value label
, TokenPos
*pos
, Value
*dst
);
353 bool continueStatement(Value label
, TokenPos
*pos
, Value
*dst
);
355 bool labeledStatement(Value label
, Value stmt
, TokenPos
*pos
, Value
*dst
);
357 bool throwStatement(Value arg
, TokenPos
*pos
, Value
*dst
);
359 bool returnStatement(Value arg
, TokenPos
*pos
, Value
*dst
);
361 bool forStatement(Value init
, Value test
, Value update
, Value stmt
,
362 TokenPos
*pos
, Value
*dst
);
364 bool forInStatement(Value var
, Value expr
, Value stmt
,
365 bool isForEach
, TokenPos
*pos
, Value
*dst
);
367 bool withStatement(Value expr
, Value stmt
, TokenPos
*pos
, Value
*dst
);
369 bool whileStatement(Value test
, Value stmt
, TokenPos
*pos
, Value
*dst
);
371 bool doWhileStatement(Value stmt
, Value test
, TokenPos
*pos
, Value
*dst
);
373 bool switchStatement(Value disc
, NodeVector
&elts
, bool lexical
, TokenPos
*pos
, Value
*dst
);
375 bool tryStatement(Value body
, NodeVector
&catches
, Value finally
, TokenPos
*pos
, Value
*dst
);
377 bool debuggerStatement(TokenPos
*pos
, Value
*dst
);
383 bool binaryExpression(BinaryOperator op
, Value left
, Value right
, TokenPos
*pos
, Value
*dst
);
385 bool unaryExpression(UnaryOperator op
, Value expr
, TokenPos
*pos
, Value
*dst
);
387 bool assignmentExpression(AssignmentOperator op
, Value lhs
, Value rhs
,
388 TokenPos
*pos
, Value
*dst
);
390 bool updateExpression(Value expr
, bool incr
, bool prefix
, TokenPos
*pos
, Value
*dst
);
392 bool logicalExpression(bool lor
, Value left
, Value right
, TokenPos
*pos
, Value
*dst
);
394 bool conditionalExpression(Value test
, Value cons
, Value alt
, TokenPos
*pos
, Value
*dst
);
396 bool sequenceExpression(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
);
398 bool newExpression(Value callee
, NodeVector
&args
, TokenPos
*pos
, Value
*dst
);
400 bool callExpression(Value callee
, NodeVector
&args
, TokenPos
*pos
, Value
*dst
);
402 bool memberExpression(bool computed
, Value expr
, Value member
, TokenPos
*pos
, Value
*dst
);
404 bool arrayExpression(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
);
406 bool objectExpression(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
);
408 bool thisExpression(TokenPos
*pos
, Value
*dst
);
410 bool yieldExpression(Value arg
, TokenPos
*pos
, Value
*dst
);
412 bool comprehensionBlock(Value patt
, Value src
, bool isForEach
, TokenPos
*pos
, Value
*dst
);
414 bool comprehensionExpression(Value body
, NodeVector
&blocks
, Value filter
,
415 TokenPos
*pos
, Value
*dst
);
417 bool generatorExpression(Value body
, NodeVector
&blocks
, Value filter
,
418 TokenPos
*pos
, Value
*dst
);
420 bool graphExpression(jsint idx
, Value expr
, TokenPos
*pos
, Value
*dst
);
422 bool graphIndexExpression(jsint idx
, TokenPos
*pos
, Value
*dst
);
428 bool variableDeclaration(NodeVector
&elts
, VarDeclKind kind
, TokenPos
*pos
, Value
*dst
);
434 bool arrayPattern(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
);
436 bool objectPattern(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
);
438 bool propertyPattern(Value key
, Value patt
, TokenPos
*pos
, Value
*dst
);
444 bool xmlAnyName(TokenPos
*pos
, Value
*dst
);
446 bool xmlEscapeExpression(Value expr
, TokenPos
*pos
, Value
*dst
);
448 bool xmlDefaultNamespace(Value ns
, TokenPos
*pos
, Value
*dst
);
450 bool xmlFilterExpression(Value left
, Value right
, TokenPos
*pos
, Value
*dst
);
452 bool xmlAttributeSelector(Value expr
, TokenPos
*pos
, Value
*dst
);
454 bool xmlQualifiedIdentifier(Value left
, Value right
, bool computed
, TokenPos
*pos
, Value
*dst
);
456 bool xmlElement(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
);
458 bool xmlText(Value text
, TokenPos
*pos
, Value
*dst
);
460 bool xmlList(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
);
462 bool xmlStartTag(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
);
464 bool xmlEndTag(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
);
466 bool xmlPointTag(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
);
468 bool xmlName(Value text
, TokenPos
*pos
, Value
*dst
);
470 bool xmlName(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
);
472 bool xmlAttribute(Value text
, TokenPos
*pos
, Value
*dst
);
474 bool xmlCdata(Value text
, TokenPos
*pos
, Value
*dst
);
476 bool xmlComment(Value text
, TokenPos
*pos
, Value
*dst
);
478 bool xmlPI(Value target
, TokenPos
*pos
, Value
*dst
);
480 bool xmlPI(Value target
, Value content
, TokenPos
*pos
, Value
*dst
);
484 NodeBuilder::newNode(ASTType type
, TokenPos
*pos
, JSObject
**dst
)
486 JS_ASSERT(type
> AST_ERROR
&& type
< AST_LIMIT
);
490 JSObject
*node
= NewNonFunction
<WithProto::Class
>(cx
, &js_ObjectClass
, NULL
, NULL
);
492 !setNodeLoc(node
, pos
) ||
493 !atomValue(nodeTypeNames
[type
], &tv
) ||
494 !setProperty(node
, "type", tv
))
502 NodeBuilder::newArray(NodeVector
&elts
, Value
*dst
)
504 JSObject
*array
= js_NewArrayObject(cx
, 0, NULL
);
508 const size_t len
= elts
.length();
509 for (size_t i
= 0; i
< len
; i
++) {
512 JS_ASSERT_IF(val
.isMagic(), val
.whyMagic() == JS_SERIALIZE_NO_NODE
);
514 /* Represent "no node" as null and ensure users are not exposed to magic values. */
515 if (val
.isMagic(JS_SERIALIZE_NO_NODE
))
518 if (!js_ArrayCompPush(cx
, array
, val
))
522 dst
->setObject(*array
);
527 NodeBuilder::setNodeLoc(JSObject
*node
, TokenPos
*pos
)
530 return setProperty(node
, "loc", NullValue());
535 return newObject(&loc
) &&
536 setProperty(node
, "loc", ObjectValue(*loc
)) &&
537 setProperty(loc
, "source", srcval
) &&
540 setProperty(loc
, "start", ObjectValue(*to
)) &&
541 (tv
.setNumber(pos
->begin
.lineno
), true) &&
542 setProperty(to
, "line", tv
) &&
543 (tv
.setNumber(pos
->begin
.index
), true) &&
544 setProperty(to
, "column", tv
) &&
547 setProperty(loc
, "end", ObjectValue(*to
)) &&
548 (tv
.setNumber(pos
->end
.lineno
), true) &&
549 setProperty(to
, "line", tv
) &&
550 (tv
.setNumber(pos
->end
.index
), true) &&
551 setProperty(to
, "column", tv
);
555 NodeBuilder::program(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
)
558 return newArray(elts
, &array
) &&
559 newNode(AST_PROGRAM
, pos
, "body", array
, dst
);
563 NodeBuilder::blockStatement(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
)
566 return newArray(elts
, &array
) &&
567 newNode(AST_BLOCK_STMT
, pos
, "body", array
, dst
);
571 NodeBuilder::expressionStatement(Value expr
, TokenPos
*pos
, Value
*dst
)
573 return newNode(AST_EXPR_STMT
, pos
, "expression", expr
, dst
);
577 NodeBuilder::emptyStatement(TokenPos
*pos
, Value
*dst
)
579 return newNode(AST_EMPTY_STMT
, pos
, dst
);
583 NodeBuilder::ifStatement(Value test
, Value cons
, Value alt
, TokenPos
*pos
, Value
*dst
)
585 return newNode(AST_IF_STMT
, pos
,
593 NodeBuilder::breakStatement(Value label
, TokenPos
*pos
, Value
*dst
)
595 return newNode(AST_BREAK_STMT
, pos
, "label", label
, dst
);
599 NodeBuilder::continueStatement(Value label
, TokenPos
*pos
, Value
*dst
)
601 return newNode(AST_CONTINUE_STMT
, pos
, "label", label
, dst
);
605 NodeBuilder::labeledStatement(Value label
, Value stmt
, TokenPos
*pos
, Value
*dst
)
607 return newNode(AST_LAB_STMT
, pos
,
614 NodeBuilder::throwStatement(Value arg
, TokenPos
*pos
, Value
*dst
)
616 return newNode(AST_THROW_STMT
, pos
, "argument", arg
, dst
);
620 NodeBuilder::returnStatement(Value arg
, TokenPos
*pos
, Value
*dst
)
622 return newNode(AST_RETURN_STMT
, pos
, "argument", arg
, dst
);
626 NodeBuilder::forStatement(Value init
, Value test
, Value update
, Value stmt
,
627 TokenPos
*pos
, Value
*dst
)
629 return newNode(AST_FOR_STMT
, pos
,
638 NodeBuilder::forInStatement(Value var
, Value expr
, Value stmt
, bool isForEach
,
639 TokenPos
*pos
, Value
*dst
)
641 return newNode(AST_FOR_IN_STMT
, pos
,
645 "each", BooleanValue(isForEach
),
650 NodeBuilder::withStatement(Value expr
, Value stmt
, TokenPos
*pos
, Value
*dst
)
652 return newNode(AST_WITH_STMT
, pos
,
659 NodeBuilder::whileStatement(Value test
, Value stmt
, TokenPos
*pos
, Value
*dst
)
661 return newNode(AST_WHILE_STMT
, pos
,
668 NodeBuilder::doWhileStatement(Value stmt
, Value test
, TokenPos
*pos
, Value
*dst
)
670 return newNode(AST_DO_STMT
, pos
,
677 NodeBuilder::switchStatement(Value disc
, NodeVector
&elts
, bool lexical
, TokenPos
*pos
, Value
*dst
)
680 return newArray(elts
, &array
) &&
681 newNode(AST_SWITCH_STMT
, pos
,
682 "discriminant", disc
,
684 "lexical", BooleanValue(lexical
),
689 NodeBuilder::tryStatement(Value body
, NodeVector
&catches
, Value finally
,
690 TokenPos
*pos
, Value
*dst
)
695 else if (catches
.length() == 1)
696 handler
= catches
[0];
697 else if (!newArray(catches
, &handler
))
700 return newNode(AST_TRY_STMT
, pos
,
703 "finalizer", finally
,
708 NodeBuilder::debuggerStatement(TokenPos
*pos
, Value
*dst
)
710 return newNode(AST_DEBUGGER_STMT
, pos
, dst
);
714 NodeBuilder::binaryExpression(BinaryOperator op
, Value left
, Value right
, TokenPos
*pos
, Value
*dst
)
716 JS_ASSERT(op
> BINOP_ERR
&& op
< BINOP_LIMIT
);
720 return atomValue(binopNames
[op
], &opName
) &&
721 newNode(AST_BINARY_EXPR
, pos
,
729 NodeBuilder::unaryExpression(UnaryOperator unop
, Value expr
, TokenPos
*pos
, Value
*dst
)
731 JS_ASSERT(unop
> UNOP_ERR
&& unop
< UNOP_LIMIT
);
735 return atomValue(unopNames
[unop
], &opName
) &&
736 newNode(AST_UNARY_EXPR
, pos
,
739 "prefix", BooleanValue(true),
744 NodeBuilder::assignmentExpression(AssignmentOperator aop
, Value lhs
, Value rhs
,
745 TokenPos
*pos
, Value
*dst
)
747 JS_ASSERT(aop
> AOP_ERR
&& aop
< AOP_LIMIT
);
751 return atomValue(aopNames
[aop
], &opName
) &&
752 newNode(AST_ASSIGN_EXPR
, pos
,
760 NodeBuilder::updateExpression(Value expr
, bool incr
, bool prefix
, TokenPos
*pos
, Value
*dst
)
764 return atomValue(incr
? "++" : "--", &opName
) &&
765 newNode(AST_UPDATE_EXPR
, pos
,
768 "prefix", BooleanValue(prefix
),
773 NodeBuilder::logicalExpression(bool lor
, Value left
, Value right
, TokenPos
*pos
, Value
*dst
)
777 return atomValue(lor
? "||" : "&&", &opName
) &&
778 newNode(AST_LOGICAL_EXPR
, pos
,
786 NodeBuilder::conditionalExpression(Value test
, Value cons
, Value alt
, TokenPos
*pos
, Value
*dst
)
788 return newNode(AST_COND_EXPR
, pos
,
796 NodeBuilder::sequenceExpression(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
)
798 return newListNode(AST_LIST_EXPR
, pos
,
804 NodeBuilder::callExpression(Value callee
, NodeVector
&args
, TokenPos
*pos
, Value
*dst
)
807 return newArray(args
, &array
) &&
808 newNode(AST_CALL_EXPR
, pos
,
815 NodeBuilder::newExpression(Value callee
, NodeVector
&args
, TokenPos
*pos
, Value
*dst
)
818 return newArray(args
, &array
) &&
819 newNode(AST_NEW_EXPR
, pos
,
826 NodeBuilder::memberExpression(bool computed
, Value expr
, Value member
, TokenPos
*pos
, Value
*dst
)
828 return newNode(AST_MEMBER_EXPR
, pos
,
831 "computed", BooleanValue(computed
),
836 NodeBuilder::arrayExpression(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
)
838 return newListNode(AST_ARRAY_EXPR
, pos
,
844 NodeBuilder::propertyPattern(Value key
, Value patt
, TokenPos
*pos
, Value
*dst
)
848 return atomValue("init", &kindName
) &&
849 newNode(AST_PROPERTY
, pos
,
857 NodeBuilder::propertyInitializer(Value key
, Value val
, PropKind kind
, TokenPos
*pos
, Value
*dst
)
861 return atomValue(kind
== PROP_INIT
863 : kind
== PROP_GETTER
865 : "set", &kindName
) &&
866 newNode(AST_PROPERTY
, pos
,
874 NodeBuilder::objectExpression(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
)
876 return newListNode(AST_OBJECT_EXPR
, pos
, "properties", elts
, dst
);
880 NodeBuilder::thisExpression(TokenPos
*pos
, Value
*dst
)
882 return newNode(AST_THIS_EXPR
, pos
, dst
);
886 NodeBuilder::yieldExpression(Value arg
, TokenPos
*pos
, Value
*dst
)
888 return newNode(AST_YIELD_EXPR
, pos
, "argument", arg
, dst
);
892 NodeBuilder::comprehensionBlock(Value patt
, Value src
, bool isForEach
, TokenPos
*pos
, Value
*dst
)
894 return newNode(AST_COMP_BLOCK
, pos
,
897 "each", BooleanValue(isForEach
),
902 NodeBuilder::comprehensionExpression(Value body
, NodeVector
&blocks
, Value filter
,
903 TokenPos
*pos
, Value
*dst
)
907 return newArray(blocks
, &array
) &&
908 newNode(AST_COMP_EXPR
, pos
,
916 NodeBuilder::generatorExpression(Value body
, NodeVector
&blocks
, Value filter
, TokenPos
*pos
, Value
*dst
)
920 return newArray(blocks
, &array
) &&
921 newNode(AST_GENERATOR_EXPR
, pos
,
929 NodeBuilder::graphExpression(jsint idx
, Value expr
, TokenPos
*pos
, Value
*dst
)
931 return newNode(AST_GRAPH_EXPR
, pos
,
932 "index", NumberValue(idx
),
938 NodeBuilder::graphIndexExpression(jsint idx
, TokenPos
*pos
, Value
*dst
)
940 return newNode(AST_GRAPH_IDX_EXPR
, pos
, "index", NumberValue(idx
), dst
);
944 NodeBuilder::variableDeclaration(NodeVector
&elts
, VarDeclKind kind
, TokenPos
*pos
, Value
*dst
)
946 JS_ASSERT(kind
> VARDECL_ERR
&& kind
< VARDECL_LIMIT
);
948 Value array
, kindName
;
950 return atomValue(kind
== VARDECL_CONST
952 : kind
== VARDECL_LET
954 : "var", &kindName
) &&
955 newArray(elts
, &array
) &&
956 newNode(AST_VAR_DECL
, pos
,
957 "declarations", array
,
963 NodeBuilder::variableDeclarator(Value id
, Value init
, TokenPos
*pos
, Value
*dst
)
965 return newNode(AST_VAR_DTOR
, pos
, "id", id
, "init", init
, dst
);
969 NodeBuilder::switchCase(Value expr
, NodeVector
&elts
, TokenPos
*pos
, Value
*dst
)
973 return newArray(elts
, &array
) &&
974 newNode(AST_CASE
, pos
,
981 NodeBuilder::catchClause(Value var
, Value guard
, Value body
, TokenPos
*pos
, Value
*dst
)
983 return newNode(AST_CATCH
, pos
,
991 NodeBuilder::literal(Value val
, TokenPos
*pos
, Value
*dst
)
993 return newNode(AST_LITERAL
, pos
, "value", val
, dst
);
997 NodeBuilder::identifier(Value name
, TokenPos
*pos
, Value
*dst
)
999 return newNode(AST_IDENTIFIER
, pos
, "name", name
, dst
);
1003 NodeBuilder::objectPattern(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
)
1005 return newListNode(AST_OBJECT_PATT
, pos
, "properties", elts
, dst
);
1009 NodeBuilder::arrayPattern(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
)
1011 return newListNode(AST_ARRAY_PATT
, pos
, "elements", elts
, dst
);
1015 NodeBuilder::function(ASTType type
, TokenPos
*pos
,
1016 Value id
, NodeVector
&args
, Value body
,
1017 bool isGenerator
, bool isExpression
,
1022 return newArray(args
, &array
) &&
1027 "generator", BooleanValue(isGenerator
),
1028 "expression", BooleanValue(isExpression
),
1033 NodeBuilder::xmlAnyName(TokenPos
*pos
, Value
*dst
)
1035 return newNode(AST_XMLANYNAME
, pos
, dst
);
1039 NodeBuilder::xmlEscapeExpression(Value expr
, TokenPos
*pos
, Value
*dst
)
1041 return newNode(AST_XMLESCAPE
, pos
, "expression", expr
, dst
);
1045 NodeBuilder::xmlFilterExpression(Value left
, Value right
, TokenPos
*pos
, Value
*dst
)
1047 return newNode(AST_XMLFILTER
, pos
, "left", left
, "right", right
, dst
);
1051 NodeBuilder::xmlDefaultNamespace(Value ns
, TokenPos
*pos
, Value
*dst
)
1053 return newNode(AST_XMLDEFAULT
, pos
, "namespace", ns
, dst
);
1057 NodeBuilder::xmlAttributeSelector(Value expr
, TokenPos
*pos
, Value
*dst
)
1059 return newNode(AST_XMLATTR_SEL
, pos
, "attribute", expr
, dst
);
1063 NodeBuilder::xmlQualifiedIdentifier(Value left
, Value right
, bool computed
,
1064 TokenPos
*pos
, Value
*dst
)
1066 return newNode(AST_XMLQUAL
, pos
,
1069 "computed", BooleanValue(computed
),
1074 NodeBuilder::xmlElement(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
)
1076 return newListNode(AST_XMLELEM
, pos
, "contents", elts
, dst
);
1080 NodeBuilder::xmlText(Value text
, TokenPos
*pos
, Value
*dst
)
1082 return newNode(AST_XMLTEXT
, pos
, "text", text
, dst
);
1086 NodeBuilder::xmlList(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
)
1088 return newListNode(AST_XMLLIST
, pos
, "contents", elts
, dst
);
1092 NodeBuilder::xmlStartTag(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
)
1094 return newListNode(AST_XMLSTART
, pos
, "contents", elts
, dst
);
1098 NodeBuilder::xmlEndTag(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
)
1100 return newListNode(AST_XMLEND
, pos
, "contents", elts
, dst
);
1104 NodeBuilder::xmlPointTag(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
)
1106 return newListNode(AST_XMLPOINT
, pos
, "contents", elts
, dst
);
1110 NodeBuilder::xmlName(Value text
, TokenPos
*pos
, Value
*dst
)
1112 return newNode(AST_XMLNAME
, pos
, "contents", text
, dst
);
1116 NodeBuilder::xmlName(NodeVector
&elts
, TokenPos
*pos
, Value
*dst
)
1118 return newListNode(AST_XMLNAME
, pos
, "contents", elts
, dst
);
1122 NodeBuilder::xmlAttribute(Value text
, TokenPos
*pos
, Value
*dst
)
1124 return newNode(AST_XMLATTR
, pos
, "value", text
, dst
);
1128 NodeBuilder::xmlCdata(Value text
, TokenPos
*pos
, Value
*dst
)
1130 return newNode(AST_XMLCDATA
, pos
, "contents", text
, dst
);
1134 NodeBuilder::xmlComment(Value text
, TokenPos
*pos
, Value
*dst
)
1136 return newNode(AST_XMLCOMMENT
, pos
, "contents", text
, dst
);
1140 NodeBuilder::xmlPI(Value target
, TokenPos
*pos
, Value
*dst
)
1142 return xmlPI(target
, NullValue(), pos
, dst
);
1146 NodeBuilder::xmlPI(Value target
, Value contents
, TokenPos
*pos
, Value
*dst
)
1148 return newNode(AST_XMLPI
, pos
,
1150 "contents", contents
,
1156 * Serialization of parse nodes to JavaScript objects.
1158 * All serialization methods take a non-nullable JSParseNode pointer.
1164 NodeBuilder builder
;
1167 Value
atomContents(JSAtom
*atom
) {
1168 return Valueify(ATOM_TO_JSVAL(atom
? atom
: cx
->runtime
->atomState
.emptyAtom
));
1171 BinaryOperator
binop(TokenKind tk
, JSOp op
);
1172 UnaryOperator
unop(TokenKind tk
, JSOp op
);
1173 AssignmentOperator
aop(JSOp op
);
1175 bool statements(JSParseNode
*pn
, NodeVector
&elts
);
1176 bool expressions(JSParseNode
*pn
, NodeVector
&elts
);
1177 bool xmls(JSParseNode
*pn
, NodeVector
&elts
);
1178 bool leftAssociate(JSParseNode
*pn
, Value
*dst
);
1179 bool binaryOperands(JSParseNode
*pn
, NodeVector
&elts
);
1180 bool functionArgs(JSParseNode
*pn
, JSParseNode
*pnargs
, JSParseNode
*pndestruct
,
1181 JSParseNode
*pnbody
, NodeVector
&args
);
1183 bool sourceElement(JSParseNode
*pn
, Value
*dst
);
1185 bool declaration(JSParseNode
*pn
, Value
*dst
);
1186 bool variableDeclaration(JSParseNode
*pn
, bool let
, Value
*dst
);
1187 bool variableDeclarator(JSParseNode
*pn
, VarDeclKind
*pkind
, Value
*dst
);
1189 bool optStatement(JSParseNode
*pn
, Value
*dst
) {
1191 dst
->setMagic(JS_SERIALIZE_NO_NODE
);
1194 return statement(pn
, dst
);
1197 bool forInit(JSParseNode
*pn
, Value
*dst
);
1198 bool statement(JSParseNode
*pn
, Value
*dst
);
1199 bool blockStatement(JSParseNode
*pn
, Value
*dst
);
1200 bool switchStatement(JSParseNode
*pn
, Value
*dst
);
1201 bool switchCase(JSParseNode
*pn
, Value
*dst
);
1202 bool tryStatement(JSParseNode
*pn
, Value
*dst
);
1203 bool catchClause(JSParseNode
*pn
, Value
*dst
);
1205 bool optExpression(JSParseNode
*pn
, Value
*dst
) {
1207 dst
->setMagic(JS_SERIALIZE_NO_NODE
);
1210 return expression(pn
, dst
);
1213 bool expression(JSParseNode
*pn
, Value
*dst
);
1215 bool propertyName(JSParseNode
*pn
, Value
*dst
);
1216 bool property(JSParseNode
*pn
, Value
*dst
);
1218 bool optIdentifier(JSAtom
*atom
, TokenPos
*pos
, Value
*dst
) {
1220 dst
->setMagic(JS_SERIALIZE_NO_NODE
);
1223 return identifier(atom
, pos
, dst
);
1226 bool identifier(JSAtom
*atom
, TokenPos
*pos
, Value
*dst
);
1227 bool identifier(JSParseNode
*pn
, Value
*dst
);
1228 bool literal(JSParseNode
*pn
, Value
*dst
);
1230 bool pattern(JSParseNode
*pn
, VarDeclKind
*pkind
, Value
*dst
);
1231 bool arrayPattern(JSParseNode
*pn
, VarDeclKind
*pkind
, Value
*dst
);
1232 bool objectPattern(JSParseNode
*pn
, VarDeclKind
*pkind
, Value
*dst
);
1234 bool function(JSParseNode
*pn
, ASTType type
, Value
*dst
);
1235 bool functionArgsAndBody(JSParseNode
*pn
, NodeVector
&args
, Value
*body
);
1236 bool functionBody(JSParseNode
*pn
, TokenPos
*pos
, Value
*dst
);
1238 bool comprehensionBlock(JSParseNode
*pn
, Value
*dst
);
1239 bool comprehension(JSParseNode
*pn
, Value
*dst
);
1240 bool generatorExpression(JSParseNode
*pn
, Value
*dst
);
1242 bool xml(JSParseNode
*pn
, Value
*dst
);
1245 ASTSerializer(JSContext
*c
, char const *src
, uintN ln
)
1246 : cx(c
), builder(c
, src
), lineno(ln
) {
1250 return builder
.init();
1253 bool program(JSParseNode
*pn
, Value
*dst
);
1257 ASTSerializer::aop(JSOp op
)
1290 ASTSerializer::unop(TokenKind tk
, JSOp op
)
1292 if (tk
== TOK_DELETE
)
1305 case JSOP_TYPEOFEXPR
:
1315 ASTSerializer::binop(TokenKind tk
, JSOp op
)
1325 return BINOP_STRICTEQ
;
1327 return BINOP_STRICTNE
;
1365 return (op
== JSOP_MOD
) ? BINOP_MOD
: BINOP_DIV
;
1369 return BINOP_BITXOR
;
1371 return BINOP_BITAND
;
1374 case TOK_INSTANCEOF
:
1375 return BINOP_INSTANCEOF
;
1377 return BINOP_DBLDOT
;
1384 ASTSerializer::statements(JSParseNode
*pn
, NodeVector
&elts
)
1386 JS_ASSERT(PN_TYPE(pn
) == TOK_LC
&& pn
->pn_arity
== PN_LIST
);
1388 if (!elts
.reserve(pn
->pn_count
))
1391 for (JSParseNode
*next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
1393 if (!sourceElement(next
, &elt
))
1395 (void)elts
.append(elt
); /* space check above */
1402 ASTSerializer::expressions(JSParseNode
*pn
, NodeVector
&elts
)
1404 if (!elts
.reserve(pn
->pn_count
))
1407 for (JSParseNode
*next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
1409 if (!expression(next
, &elt
))
1411 (void)elts
.append(elt
); /* space check above */
1418 ASTSerializer::xmls(JSParseNode
*pn
, NodeVector
&elts
)
1420 if (!elts
.reserve(pn
->pn_count
))
1423 for (JSParseNode
*next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
1425 if (!xml(next
, &elt
))
1427 (void)elts
.append(elt
); /* space check above */
1434 ASTSerializer::blockStatement(JSParseNode
*pn
, Value
*dst
)
1436 JS_ASSERT(PN_TYPE(pn
) == TOK_LC
);
1438 NodeVector
stmts(cx
);
1439 return statements(pn
, stmts
) &&
1440 builder
.blockStatement(stmts
, &pn
->pn_pos
, dst
);
1444 ASTSerializer::program(JSParseNode
*pn
, Value
*dst
)
1448 /* Workaround for bug 588061: parser's reported start position is always 0:0. */
1449 pn
->pn_pos
.begin
.lineno
= lineno
;
1451 NodeVector
stmts(cx
);
1452 return statements(pn
, stmts
) &&
1453 builder
.program(stmts
, &pn
->pn_pos
, dst
);
1457 ASTSerializer::sourceElement(JSParseNode
*pn
, Value
*dst
)
1459 /* SpiderMonkey allows declarations even in pure statement contexts. */
1460 return statement(pn
, dst
);
1464 ASTSerializer::declaration(JSParseNode
*pn
, Value
*dst
)
1466 JS_ASSERT(PN_TYPE(pn
) == TOK_FUNCTION
||
1467 PN_TYPE(pn
) == TOK_VAR
||
1468 PN_TYPE(pn
) == TOK_LET
);
1470 switch (PN_TYPE(pn
)) {
1472 return function(pn
, AST_FUNC_DECL
, dst
);
1475 return variableDeclaration(pn
, false, dst
);
1478 JS_ASSERT(PN_TYPE(pn
) == TOK_LET
);
1479 return variableDeclaration(pn
, true, dst
);
1484 ASTSerializer::variableDeclaration(JSParseNode
*pn
, bool let
, Value
*dst
)
1486 JS_ASSERT(let
? PN_TYPE(pn
) == TOK_LET
: PN_TYPE(pn
) == TOK_VAR
);
1488 /* Later updated to VARDECL_CONST if we find a PND_CONST declarator. */
1489 VarDeclKind kind
= let
? VARDECL_LET
: VARDECL_VAR
;
1491 NodeVector
dtors(cx
);
1492 if (!dtors
.reserve(pn
->pn_count
))
1495 /* In a for-in context, variable declarations contain just a single pattern. */
1496 if (pn
->pn_xflags
& PNX_FORINVAR
) {
1498 return pattern(pn
->pn_head
, &kind
, &patt
) &&
1499 builder
.variableDeclarator(patt
, NullValue(), &pn
->pn_head
->pn_pos
, &child
) &&
1500 dtors
.append(child
) &&
1501 builder
.variableDeclaration(dtors
, kind
, &pn
->pn_pos
, dst
);
1504 for (JSParseNode
*next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
1506 if (!variableDeclarator(next
, &kind
, &child
))
1508 (void)dtors
.append(child
); /* space check above */
1511 return builder
.variableDeclaration(dtors
, kind
, &pn
->pn_pos
, dst
);
1515 ASTSerializer::variableDeclarator(JSParseNode
*pn
, VarDeclKind
*pkind
, Value
*dst
)
1517 /* A destructuring declarator is always a TOK_ASSIGN. */
1518 JS_ASSERT(PN_TYPE(pn
) == TOK_NAME
|| PN_TYPE(pn
) == TOK_ASSIGN
);
1520 JSParseNode
*pnleft
;
1521 JSParseNode
*pnright
;
1523 if (PN_TYPE(pn
) == TOK_NAME
) {
1525 pnright
= pn
->pn_expr
;
1527 JS_ASSERT(PN_TYPE(pn
) == TOK_ASSIGN
);
1528 pnleft
= pn
->pn_left
;
1529 pnright
= pn
->pn_right
;
1533 return pattern(pnleft
, pkind
, &left
) &&
1534 optExpression(pnright
, &right
) &&
1535 builder
.variableDeclarator(left
, right
, &pn
->pn_pos
, dst
);
1539 ASTSerializer::switchCase(JSParseNode
*pn
, Value
*dst
)
1541 NodeVector
stmts(cx
);
1545 return optExpression(pn
->pn_left
, &expr
) &&
1546 statements(pn
->pn_right
, stmts
) &&
1547 builder
.switchCase(expr
, stmts
, &pn
->pn_pos
, dst
);
1551 ASTSerializer::switchStatement(JSParseNode
*pn
, Value
*dst
)
1555 if (!expression(pn
->pn_left
, &disc
))
1558 JSParseNode
*listNode
;
1561 if (PN_TYPE(pn
->pn_right
) == TOK_LEXICALSCOPE
) {
1562 listNode
= pn
->pn_right
->pn_expr
;
1565 listNode
= pn
->pn_right
;
1569 NodeVector
cases(cx
);
1570 if (!cases
.reserve(listNode
->pn_count
))
1573 for (JSParseNode
*next
= listNode
->pn_head
; next
; next
= next
->pn_next
) {
1575 if (!switchCase(next
, &child
))
1577 (void)cases
.append(child
); /* space check above */
1580 return builder
.switchStatement(disc
, cases
, lexical
, &pn
->pn_pos
, dst
);
1584 ASTSerializer::catchClause(JSParseNode
*pn
, Value
*dst
)
1586 Value var
, guard
, body
;
1588 return pattern(pn
->pn_kid1
, NULL
, &var
) &&
1589 optExpression(pn
->pn_kid2
, &guard
) &&
1590 statement(pn
->pn_kid3
, &body
) &&
1591 builder
.catchClause(var
, guard
, body
, &pn
->pn_pos
, dst
);
1595 ASTSerializer::tryStatement(JSParseNode
*pn
, Value
*dst
)
1598 if (!statement(pn
->pn_kid1
, &body
))
1601 NodeVector
clauses(cx
);
1603 if (!clauses
.reserve(pn
->pn_kid2
->pn_count
))
1606 for (JSParseNode
*next
= pn
->pn_kid2
->pn_head
; next
; next
= next
->pn_next
) {
1608 if (!catchClause(next
->pn_expr
, &clause
))
1610 (void)clauses
.append(clause
); /* space check above */
1615 return optStatement(pn
->pn_kid3
, &finally
) &&
1616 builder
.tryStatement(body
, clauses
, finally
, &pn
->pn_pos
, dst
);
1620 ASTSerializer::forInit(JSParseNode
*pn
, Value
*dst
)
1623 dst
->setMagic(JS_SERIALIZE_NO_NODE
);
1627 return (PN_TYPE(pn
) == TOK_VAR
)
1628 ? variableDeclaration(pn
, false, dst
)
1629 : (PN_TYPE(pn
) == TOK_LET
)
1630 ? variableDeclaration(pn
, true, dst
)
1631 : expression(pn
, dst
);
1635 ASTSerializer::statement(JSParseNode
*pn
, Value
*dst
)
1637 switch (PN_TYPE(pn
)) {
1641 return declaration(pn
, dst
);
1646 return expression(pn
->pn_kid
, &expr
) &&
1647 builder
.expressionStatement(expr
, &pn
->pn_pos
, dst
);
1649 return builder
.emptyStatement(&pn
->pn_pos
, dst
);
1651 case TOK_LEXICALSCOPE
:
1653 if (PN_TYPE(pn
) != TOK_LC
)
1654 return statement(pn
, dst
);
1658 return blockStatement(pn
, dst
);
1662 Value test
, cons
, alt
;
1664 return expression(pn
->pn_kid1
, &test
) &&
1665 statement(pn
->pn_kid2
, &cons
) &&
1666 optStatement(pn
->pn_kid3
, &alt
) &&
1667 builder
.ifStatement(test
, cons
, alt
, &pn
->pn_pos
, dst
);
1671 return switchStatement(pn
, dst
);
1674 return tryStatement(pn
, dst
);
1681 return expression(pn
->pn_left
, &expr
) &&
1682 statement(pn
->pn_right
, &stmt
) &&
1683 (PN_TYPE(pn
) == TOK_WITH
)
1684 ? builder
.withStatement(expr
, stmt
, &pn
->pn_pos
, dst
)
1685 : builder
.whileStatement(expr
, stmt
, &pn
->pn_pos
, dst
);
1692 return statement(pn
->pn_left
, &stmt
) &&
1693 expression(pn
->pn_right
, &test
) &&
1694 builder
.doWhileStatement(stmt
, test
, &pn
->pn_pos
, dst
);
1699 JSParseNode
*head
= pn
->pn_left
;
1702 if (!statement(pn
->pn_right
, &stmt
))
1705 bool isForEach
= pn
->pn_iflags
& JSITER_FOREACH
;
1707 if (PN_TYPE(head
) == TOK_IN
) {
1710 return (PN_TYPE(head
->pn_left
) == TOK_VAR
1711 ? variableDeclaration(head
->pn_left
, false, &var
)
1712 : PN_TYPE(head
->pn_left
) == TOK_LET
1713 ? variableDeclaration(head
->pn_left
, true, &var
)
1714 : pattern(head
->pn_left
, NULL
, &var
)) &&
1715 expression(head
->pn_right
, &expr
) &&
1716 builder
.forInStatement(var
, expr
, stmt
, isForEach
, &pn
->pn_pos
, dst
);
1719 Value init
, test
, update
;
1721 return forInit(head
->pn_kid1
, &init
) &&
1722 optExpression(head
->pn_kid2
, &test
) &&
1723 optExpression(head
->pn_kid3
, &update
) &&
1724 builder
.forStatement(init
, test
, update
, stmt
, &pn
->pn_pos
, dst
);
1732 return optIdentifier(pn
->pn_atom
, NULL
, &label
) &&
1733 (PN_TYPE(pn
) == TOK_BREAK
1734 ? builder
.breakStatement(label
, &pn
->pn_pos
, dst
)
1735 : builder
.continueStatement(label
, &pn
->pn_pos
, dst
));
1742 return identifier(pn
->pn_atom
, NULL
, &label
) &&
1743 statement(pn
->pn_expr
, &stmt
) &&
1744 builder
.labeledStatement(label
, stmt
, &pn
->pn_pos
, dst
);
1752 return optExpression(pn
->pn_kid
, &arg
) &&
1753 (PN_TYPE(pn
) == TOK_THROW
1754 ? builder
.throwStatement(arg
, &pn
->pn_pos
, dst
)
1755 : builder
.returnStatement(arg
, &pn
->pn_pos
, dst
));
1759 return builder
.debuggerStatement(&pn
->pn_pos
, dst
);
1761 #if JS_HAS_XML_SUPPORT
1764 LOCAL_ASSERT(pn
->pn_arity
== PN_UNARY
&& PN_TYPE(pn
->pn_kid
) == TOK_STRING
);
1768 return literal(pn
->pn_kid
, &ns
) &&
1769 builder
.xmlDefaultNamespace(ns
, &pn
->pn_pos
, dst
);
1774 LOCAL_NOT_REACHED("unexpected statement type");
1779 ASTSerializer::leftAssociate(JSParseNode
*pn
, Value
*dst
)
1781 JS_ASSERT(pn
->pn_arity
== PN_LIST
);
1783 const size_t len
= pn
->pn_count
;
1784 JS_ASSERT(len
>= 1);
1787 return expression(pn
->pn_head
, dst
);
1789 JS_ASSERT(len
>= 2);
1791 Vector
<JSParseNode
*, 8> list(cx
);
1792 if (!list
.reserve(len
))
1795 for (JSParseNode
*next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
1796 (void)list
.append(next
); /* space check above */
1799 TokenKind tk
= PN_TYPE(pn
);
1801 bool lor
= tk
== TOK_OR
;
1802 bool logop
= lor
|| (tk
== TOK_AND
);
1806 if (!expression(list
[len
- 1], &right
))
1812 JSParseNode
*next
= list
[i
];
1815 if (!expression(next
, &left
))
1818 TokenPos subpos
= { next
->pn_pos
.begin
, pn
->pn_pos
.end
};
1821 if (!builder
.logicalExpression(lor
, left
, right
, &subpos
, &right
))
1824 BinaryOperator op
= binop(PN_TYPE(pn
), PN_OP(pn
));
1825 LOCAL_ASSERT(op
> BINOP_ERR
&& op
< BINOP_LIMIT
);
1827 if (!builder
.binaryExpression(op
, left
, right
, &subpos
, &right
))
1837 ASTSerializer::binaryOperands(JSParseNode
*pn
, NodeVector
&elts
)
1839 if (pn
->pn_arity
== PN_BINARY
) {
1842 return expression(pn
->pn_left
, &left
) &&
1843 elts
.append(left
) &&
1844 expression(pn
->pn_right
, &right
) &&
1848 LOCAL_ASSERT(pn
->pn_arity
== PN_LIST
);
1850 return expressions(pn
, elts
);
1854 ASTSerializer::comprehensionBlock(JSParseNode
*pn
, Value
*dst
)
1856 LOCAL_ASSERT(pn
->pn_arity
== PN_BINARY
);
1858 JSParseNode
*in
= pn
->pn_left
;
1860 LOCAL_ASSERT(in
&& PN_TYPE(in
) == TOK_IN
);
1862 bool isForEach
= pn
->pn_iflags
& JSITER_FOREACH
;
1865 return pattern(in
->pn_left
, NULL
, &patt
) &&
1866 expression(in
->pn_right
, &src
) &&
1867 builder
.comprehensionBlock(patt
, src
, isForEach
, &in
->pn_pos
, dst
);
1871 ASTSerializer::comprehension(JSParseNode
*pn
, Value
*dst
)
1873 LOCAL_ASSERT(PN_TYPE(pn
) == TOK_FOR
);
1875 NodeVector
blocks(cx
);
1877 JSParseNode
*next
= pn
;
1878 while (PN_TYPE(next
) == TOK_FOR
) {
1880 if (!comprehensionBlock(next
, &block
) ||
1881 !blocks
.append(block
))
1883 next
= next
->pn_right
;
1886 Value filter
= MagicValue(JS_SERIALIZE_NO_NODE
);
1888 if (PN_TYPE(next
) == TOK_IF
) {
1889 if (!optExpression(next
->pn_kid1
, &filter
))
1891 next
= next
->pn_kid2
;
1892 } else if (PN_TYPE(next
) == TOK_LC
&& next
->pn_count
== 0) {
1893 /* js_FoldConstants optimized away the push. */
1894 NodeVector
empty(cx
);
1895 return builder
.arrayExpression(empty
, &pn
->pn_pos
, dst
);
1898 LOCAL_ASSERT(PN_TYPE(next
) == TOK_ARRAYPUSH
);
1902 return expression(next
->pn_kid
, &body
) &&
1903 builder
.comprehensionExpression(body
, blocks
, filter
, &pn
->pn_pos
, dst
);
1907 ASTSerializer::generatorExpression(JSParseNode
*pn
, Value
*dst
)
1909 LOCAL_ASSERT(PN_TYPE(pn
) == TOK_FOR
);
1911 NodeVector
blocks(cx
);
1913 JSParseNode
*next
= pn
;
1914 while (PN_TYPE(next
) == TOK_FOR
) {
1916 if (!comprehensionBlock(next
, &block
) ||
1917 !blocks
.append(block
))
1919 next
= next
->pn_right
;
1922 Value filter
= MagicValue(JS_SERIALIZE_NO_NODE
);
1924 if (PN_TYPE(next
) == TOK_IF
) {
1925 if (!optExpression(next
->pn_kid1
, &filter
))
1927 next
= next
->pn_kid2
;
1930 LOCAL_ASSERT(PN_TYPE(next
) == TOK_SEMI
&&
1931 PN_TYPE(next
->pn_kid
) == TOK_YIELD
&&
1932 next
->pn_kid
->pn_kid
);
1936 return expression(next
->pn_kid
->pn_kid
, &body
) &&
1937 builder
.generatorExpression(body
, blocks
, filter
, &pn
->pn_pos
, dst
);
1941 ASTSerializer::expression(JSParseNode
*pn
, Value
*dst
)
1943 switch (PN_TYPE(pn
)) {
1945 return function(pn
, AST_FUNC_EXPR
, dst
);
1949 NodeVector
exprs(cx
);
1950 return expressions(pn
, exprs
) &&
1951 builder
.sequenceExpression(exprs
, &pn
->pn_pos
, dst
);
1956 Value test
, cons
, alt
;
1958 return expression(pn
->pn_kid1
, &test
) &&
1959 expression(pn
->pn_kid2
, &cons
) &&
1960 expression(pn
->pn_kid3
, &alt
) &&
1961 builder
.conditionalExpression(test
, cons
, alt
, &pn
->pn_pos
, dst
);
1967 if (pn
->pn_arity
== PN_BINARY
) {
1969 return expression(pn
->pn_left
, &left
) &&
1970 expression(pn
->pn_right
, &right
) &&
1971 builder
.logicalExpression(PN_TYPE(pn
) == TOK_OR
, left
, right
, &pn
->pn_pos
, dst
);
1973 return leftAssociate(pn
, dst
);
1979 bool incr
= PN_TYPE(pn
) == TOK_INC
;
1980 bool prefix
= PN_OP(pn
) >= JSOP_INCNAME
&& PN_OP(pn
) <= JSOP_DECELEM
;
1983 return expression(pn
->pn_kid
, &expr
) &&
1984 builder
.updateExpression(expr
, incr
, prefix
, &pn
->pn_pos
, dst
);
1989 AssignmentOperator op
= aop(PN_OP(pn
));
1990 LOCAL_ASSERT(op
> AOP_ERR
&& op
< AOP_LIMIT
);
1993 return pattern(pn
->pn_left
, NULL
, &lhs
) &&
1994 expression(pn
->pn_right
, &rhs
) &&
1995 builder
.assignmentExpression(op
, lhs
, rhs
, &pn
->pn_pos
, dst
);
2009 case TOK_INSTANCEOF
:
2011 if (pn
->pn_arity
== PN_BINARY
) {
2012 BinaryOperator op
= binop(PN_TYPE(pn
), PN_OP(pn
));
2013 LOCAL_ASSERT(op
> BINOP_ERR
&& op
< BINOP_LIMIT
);
2016 return expression(pn
->pn_left
, &left
) &&
2017 expression(pn
->pn_right
, &right
) &&
2018 builder
.binaryExpression(op
, left
, right
, &pn
->pn_pos
, dst
);
2020 return leftAssociate(pn
, dst
);
2024 #if JS_HAS_XML_SUPPORT
2025 if (PN_OP(pn
) == JSOP_XMLNAME
)
2026 return expression(pn
->pn_kid
, dst
);
2030 UnaryOperator op
= unop(PN_TYPE(pn
), PN_OP(pn
));
2031 LOCAL_ASSERT(op
> UNOP_ERR
&& op
< UNOP_LIMIT
);
2034 return expression(pn
->pn_kid
, &expr
) &&
2035 builder
.unaryExpression(op
, expr
, &pn
->pn_pos
, dst
);
2041 #ifdef JS_HAS_GENERATOR_EXPRS
2042 if (pn
->isGeneratorExpr())
2043 return generatorExpression(pn
->generatorExpr(), dst
);
2046 JSParseNode
*next
= pn
->pn_head
;
2049 if (!expression(next
, &callee
))
2052 NodeVector
args(cx
);
2053 if (!args
.reserve(pn
->pn_count
- 1))
2056 for (next
= next
->pn_next
; next
; next
= next
->pn_next
) {
2058 if (!expression(next
, &arg
))
2060 (void)args
.append(arg
); /* space check above */
2063 return PN_TYPE(pn
) == TOK_NEW
2064 ? builder
.newExpression(callee
, args
, &pn
->pn_pos
, dst
)
2065 : builder
.callExpression(callee
, args
, &pn
->pn_pos
, dst
);
2071 return expression(pn
->pn_expr
, &expr
) &&
2072 identifier(pn
->pn_atom
, NULL
, &id
) &&
2073 builder
.memberExpression(false, expr
, id
, &pn
->pn_pos
, dst
);
2079 return expression(pn
->pn_left
, &left
) &&
2080 expression(pn
->pn_right
, &right
) &&
2081 builder
.memberExpression(true, left
, right
, &pn
->pn_pos
, dst
);
2086 NodeVector
elts(cx
);
2087 if (!elts
.reserve(pn
->pn_count
))
2090 for (JSParseNode
*next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
2091 if (PN_TYPE(next
) == TOK_COMMA
) {
2092 (void)elts
.append(MagicValue(JS_SERIALIZE_NO_NODE
)); /* space check above */
2095 if (!expression(next
, &expr
))
2097 (void)elts
.append(expr
); /* space check above */
2101 return builder
.arrayExpression(elts
, &pn
->pn_pos
, dst
);
2106 NodeVector
elts(cx
);
2107 if (!elts
.reserve(pn
->pn_count
))
2110 for (JSParseNode
*next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
2112 if (!property(next
, &prop
))
2114 (void)elts
.append(prop
); /* space check above */
2117 return builder
.objectExpression(elts
, &pn
->pn_pos
, dst
);
2121 return identifier(pn
, dst
);
2127 return PN_OP(pn
) == JSOP_THIS
? builder
.thisExpression(&pn
->pn_pos
, dst
) : literal(pn
, dst
);
2132 return optExpression(pn
->pn_kid
, &arg
) &&
2133 builder
.yieldExpression(arg
, &pn
->pn_pos
, dst
);
2139 return expression(pn
->pn_kid
, &expr
) &&
2140 builder
.graphExpression(pn
->pn_num
, expr
, &pn
->pn_pos
, dst
);
2144 return builder
.graphIndexExpression(pn
->pn_num
, &pn
->pn_pos
, dst
);
2147 /* NB: it's no longer the case that pn_count could be 2. */
2148 LOCAL_ASSERT(pn
->pn_count
== 1);
2149 LOCAL_ASSERT(PN_TYPE(pn
->pn_head
) == TOK_LEXICALSCOPE
);
2151 return comprehension(pn
->pn_head
->pn_expr
, dst
);
2153 #ifdef JS_HAS_XML_SUPPORT
2155 return builder
.xmlAnyName(&pn
->pn_pos
, dst
);
2161 LOCAL_ASSERT(pn
->pn_arity
== PN_NAME
|| pn
->pn_arity
== PN_BINARY
);
2163 bool computed
= pn
->pn_arity
== PN_BINARY
;
2166 ? (expression(pn
->pn_left
, &left
) &&
2167 expression(pn
->pn_right
, &right
))
2168 : (expression(pn
->pn_expr
, &left
) &&
2169 identifier(pn
->pn_atom
, NULL
, &right
))) &&
2170 builder
.xmlQualifiedIdentifier(left
, right
, computed
,
2177 return expression(pn
->pn_kid
, &expr
) &&
2178 builder
.xmlAttributeSelector(expr
, &pn
->pn_pos
, dst
);
2184 return expression(pn
->pn_left
, &left
) &&
2185 expression(pn
->pn_right
, &right
) &&
2186 builder
.xmlFilterExpression(left
, right
, &pn
->pn_pos
, dst
);
2190 return xml(pn
, dst
);
2194 LOCAL_NOT_REACHED("unexpected expression type");
2200 ASTSerializer::xml(JSParseNode
*pn
, Value
*dst
)
2202 switch (PN_TYPE(pn
)) {
2203 #ifdef JS_HAS_XML_SUPPORT
2207 return expression(pn
->pn_kid
, &expr
) &&
2208 builder
.xmlEscapeExpression(expr
, &pn
->pn_pos
, dst
);
2213 NodeVector
elts(cx
);
2214 if (!xmls(pn
, elts
))
2216 return builder
.xmlElement(elts
, &pn
->pn_pos
, dst
);
2221 NodeVector
elts(cx
);
2222 if (!xmls(pn
, elts
))
2224 return builder
.xmlList(elts
, &pn
->pn_pos
, dst
);
2229 NodeVector
elts(cx
);
2230 if (!xmls(pn
, elts
))
2232 return builder
.xmlStartTag(elts
, &pn
->pn_pos
, dst
);
2237 NodeVector
elts(cx
);
2238 if (!xmls(pn
, elts
))
2240 return builder
.xmlEndTag(elts
, &pn
->pn_pos
, dst
);
2245 NodeVector
elts(cx
);
2246 if (!xmls(pn
, elts
))
2248 return builder
.xmlPointTag(elts
, &pn
->pn_pos
, dst
);
2252 return builder
.xmlText(atomContents(pn
->pn_atom
), &pn
->pn_pos
, dst
);
2255 if (pn
->pn_arity
== PN_NULLARY
)
2256 return builder
.xmlName(atomContents(pn
->pn_atom
), &pn
->pn_pos
, dst
);
2258 LOCAL_ASSERT(pn
->pn_arity
== PN_LIST
);
2261 NodeVector
elts(cx
);
2262 return xmls(pn
, elts
) &&
2263 builder
.xmlName(elts
, &pn
->pn_pos
, dst
);
2267 return builder
.xmlAttribute(atomContents(pn
->pn_atom
), &pn
->pn_pos
, dst
);
2270 return builder
.xmlCdata(atomContents(pn
->pn_atom
), &pn
->pn_pos
, dst
);
2272 case TOK_XMLCOMMENT
:
2273 return builder
.xmlComment(atomContents(pn
->pn_atom
), &pn
->pn_pos
, dst
);
2277 return builder
.xmlPI(atomContents(pn
->pn_atom
), &pn
->pn_pos
, dst
);
2279 return builder
.xmlPI(atomContents(pn
->pn_atom
),
2280 atomContents(pn
->pn_atom2
),
2286 LOCAL_NOT_REACHED("unexpected XML node type");
2291 ASTSerializer::propertyName(JSParseNode
*pn
, Value
*dst
)
2293 if (PN_TYPE(pn
) == TOK_NAME
)
2294 return identifier(pn
, dst
);
2296 LOCAL_ASSERT(PN_TYPE(pn
) == TOK_STRING
|| PN_TYPE(pn
) == TOK_NUMBER
);
2298 return literal(pn
, dst
);
2302 ASTSerializer::property(JSParseNode
*pn
, Value
*dst
)
2305 switch (PN_OP(pn
)) {
2319 LOCAL_NOT_REACHED("unexpected object-literal property");
2323 return propertyName(pn
->pn_left
, &key
) &&
2324 expression(pn
->pn_right
, &val
) &&
2325 builder
.propertyInitializer(key
, val
, kind
, &pn
->pn_pos
, dst
);
2329 ASTSerializer::literal(JSParseNode
*pn
, Value
*dst
)
2332 switch (PN_TYPE(pn
)) {
2334 val
= Valueify(ATOM_TO_JSVAL(pn
->pn_atom
));
2339 JSObject
*re1
= pn
->pn_objbox
? pn
->pn_objbox
->object
: NULL
;
2340 LOCAL_ASSERT(re1
&& re1
->isRegExp());
2343 if (!js_GetClassPrototype(cx
, cx
->fp()->getScopeChain(), JSProto_RegExp
, &proto
))
2346 JSObject
*re2
= js_CloneRegExpObject(cx
, re1
, proto
);
2350 val
.setObject(*re2
);
2355 val
.setNumber(pn
->pn_dval
);
2359 if (PN_OP(pn
) == JSOP_NULL
)
2362 val
.setBoolean(PN_OP(pn
) == JSOP_TRUE
);
2366 LOCAL_NOT_REACHED("unexpected literal type");
2369 return builder
.literal(val
, &pn
->pn_pos
, dst
);
2373 ASTSerializer::arrayPattern(JSParseNode
*pn
, VarDeclKind
*pkind
, Value
*dst
)
2375 JS_ASSERT(PN_TYPE(pn
) == TOK_RB
);
2377 NodeVector
elts(cx
);
2378 if (!elts
.reserve(pn
->pn_count
))
2381 for (JSParseNode
*next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
2382 if (PN_TYPE(next
) == TOK_COMMA
) {
2383 (void)elts
.append(MagicValue(JS_SERIALIZE_NO_NODE
)); /* space check above */
2386 if (!pattern(next
, pkind
, &patt
))
2388 (void)elts
.append(patt
); /* space check above */
2392 return builder
.arrayPattern(elts
, &pn
->pn_pos
, dst
);
2396 ASTSerializer::objectPattern(JSParseNode
*pn
, VarDeclKind
*pkind
, Value
*dst
)
2398 JS_ASSERT(PN_TYPE(pn
) == TOK_RC
);
2400 NodeVector
elts(cx
);
2401 if (!elts
.reserve(pn
->pn_count
))
2404 for (JSParseNode
*next
= pn
->pn_head
; next
; next
= next
->pn_next
) {
2405 LOCAL_ASSERT(PN_OP(next
) == JSOP_INITPROP
);
2407 Value key
, patt
, prop
;
2408 if (!propertyName(next
->pn_left
, &key
) ||
2409 !pattern(next
->pn_right
, pkind
, &patt
) ||
2410 !builder
.propertyPattern(key
, patt
, &next
->pn_pos
, &prop
))
2413 (void)elts
.append(prop
); /* space check above */
2416 return builder
.objectPattern(elts
, &pn
->pn_pos
, dst
);
2420 ASTSerializer::pattern(JSParseNode
*pn
, VarDeclKind
*pkind
, Value
*dst
)
2422 switch (PN_TYPE(pn
)) {
2424 return objectPattern(pn
, pkind
, dst
);
2427 return arrayPattern(pn
, pkind
, dst
);
2430 if (pkind
&& (pn
->pn_dflags
& PND_CONST
))
2431 *pkind
= VARDECL_CONST
;
2435 return expression(pn
, dst
);
2440 ASTSerializer::identifier(JSAtom
*atom
, TokenPos
*pos
, Value
*dst
)
2442 return builder
.identifier(atomContents(atom
), pos
, dst
);
2446 ASTSerializer::identifier(JSParseNode
*pn
, Value
*dst
)
2448 LOCAL_ASSERT(pn
->pn_arity
== PN_NAME
|| pn
->pn_arity
== PN_NULLARY
);
2449 LOCAL_ASSERT(pn
->pn_atom
);
2451 return identifier(pn
->pn_atom
, &pn
->pn_pos
, dst
);
2455 ASTSerializer::function(JSParseNode
*pn
, ASTType type
, Value
*dst
)
2457 JSFunction
*func
= (JSFunction
*)pn
->pn_funbox
->object
;
2460 #ifdef JS_HAS_GENERATORS
2461 pn
->pn_funbox
->tcflags
& TCF_FUN_IS_GENERATOR
;
2467 #ifdef JS_HAS_EXPR_CLOSURES
2468 func
->flags
& JSFUN_EXPR_CLOSURE
;
2474 if (!optIdentifier(func
->atom
, NULL
, &id
))
2477 NodeVector
args(cx
);
2479 JSParseNode
*argsAndBody
= (PN_TYPE(pn
->pn_body
) == TOK_UPVARS
)
2480 ? pn
->pn_body
->pn_tree
2484 return functionArgsAndBody(argsAndBody
, args
, &body
) &&
2485 builder
.function(type
, &pn
->pn_pos
, id
, args
, body
, isGenerator
, isExpression
, dst
);
2489 ASTSerializer::functionArgsAndBody(JSParseNode
*pn
, NodeVector
&args
, Value
*body
)
2491 JSParseNode
*pnargs
;
2492 JSParseNode
*pnbody
;
2494 /* Extract the args and body separately. */
2495 if (PN_TYPE(pn
) == TOK_ARGSBODY
) {
2497 pnbody
= pn
->last();
2503 JSParseNode
*pndestruct
;
2505 /* Extract the destructuring assignments. */
2506 if (pnbody
->pn_arity
== PN_LIST
&& (pnbody
->pn_xflags
& PNX_DESTRUCT
)) {
2507 JSParseNode
*head
= pnbody
->pn_head
;
2508 LOCAL_ASSERT(head
&& PN_TYPE(head
) == TOK_SEMI
);
2510 pndestruct
= head
->pn_kid
;
2511 LOCAL_ASSERT(pndestruct
&& PN_TYPE(pndestruct
) == TOK_COMMA
);
2516 /* Serialize the arguments and body. */
2517 switch (PN_TYPE(pnbody
)) {
2518 case TOK_RETURN
: /* expression closure, no destructured args */
2519 return functionArgs(pn
, pnargs
, NULL
, pnbody
, args
) &&
2520 expression(pnbody
->pn_kid
, body
);
2522 case TOK_SEQ
: /* expression closure with destructured args */
2524 JSParseNode
*pnstart
= pnbody
->pn_head
->pn_next
;
2525 LOCAL_ASSERT(pnstart
&& PN_TYPE(pnstart
) == TOK_RETURN
);
2527 return functionArgs(pn
, pnargs
, pndestruct
, pnbody
, args
) &&
2528 expression(pnstart
->pn_kid
, body
);
2531 case TOK_LC
: /* statement closure */
2533 JSParseNode
*pnstart
= (pnbody
->pn_xflags
& PNX_DESTRUCT
)
2534 ? pnbody
->pn_head
->pn_next
2537 return functionArgs(pn
, pnargs
, pndestruct
, pnbody
, args
) &&
2538 functionBody(pnstart
, &pnbody
->pn_pos
, body
);
2542 LOCAL_NOT_REACHED("unexpected function contents");
2547 ASTSerializer::functionArgs(JSParseNode
*pn
, JSParseNode
*pnargs
, JSParseNode
*pndestruct
,
2548 JSParseNode
*pnbody
, NodeVector
&args
)
2551 JSParseNode
*arg
= pnargs
? pnargs
->pn_head
: NULL
;
2552 JSParseNode
*destruct
= pndestruct
? pndestruct
->pn_head
: NULL
;
2556 * Arguments are found in potentially two different places: 1) the
2557 * argsbody sequence (which ends with the body node), or 2) a
2558 * destructuring initialization at the beginning of the body. Loop
2559 * |arg| through the argsbody and |destruct| through the initial
2560 * destructuring assignments, stopping only when we've exhausted
2563 while ((arg
&& arg
!= pnbody
) || destruct
) {
2564 if (arg
&& arg
!= pnbody
&& arg
->frameSlot() == i
) {
2565 if (!identifier(arg
, &node
) ||
2569 } else if (destruct
&& destruct
->pn_right
->frameSlot() == i
) {
2570 if (!pattern(destruct
->pn_left
, NULL
, &node
) ||
2573 destruct
= destruct
->pn_next
;
2575 LOCAL_NOT_REACHED("missing function argument");
2584 ASTSerializer::functionBody(JSParseNode
*pn
, TokenPos
*pos
, Value
*dst
)
2586 NodeVector
elts(cx
);
2588 /* We aren't sure how many elements there are up front, so we'll check each append. */
2589 for (JSParseNode
*next
= pn
; next
; next
= next
->pn_next
) {
2591 if (!sourceElement(next
, &child
) ||
2592 !elts
.append(child
))
2596 return builder
.blockStatement(elts
, pos
, dst
);
2599 } /* namespace js */
2603 Class js_ReflectClass
= {
2605 JSCLASS_HAS_CACHED_PROTO(JSProto_Reflect
),
2616 reflect_parse(JSContext
*cx
, uintN argc
, jsval
*vp
)
2619 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_MORE_ARGS_NEEDED
,
2620 "Reflect.parse", "0", "s");
2624 JSString
*src
= js_ValueToString(cx
, Valueify(JS_ARGV(cx
, vp
)[0]));
2628 const char *filename
= NULL
;
2630 JSString
*str
= js_ValueToString(cx
, Valueify(JS_ARGV(cx
, vp
)[1]));
2633 filename
= js_GetStringBytes(NULL
, str
);
2638 if (!ValueToECMAUint32(cx
, Valueify(JS_ARGV(cx
, vp
)[2]), &lineno
))
2642 const jschar
*chars
;
2645 src
->getCharsAndLength(chars
, length
);
2649 if (!parser
.init(chars
, length
, NULL
, filename
, lineno
))
2652 JSParseNode
*pn
= parser
.parse(NULL
);
2656 ASTSerializer
serialize(cx
, filename
, lineno
);
2657 if (!serialize
.init())
2661 if (!serialize
.program(pn
, &val
)) {
2662 JS_SET_RVAL(cx
, vp
, JSVAL_NULL
);
2666 JS_SET_RVAL(cx
, vp
, Jsvalify(val
));
2670 static JSFunctionSpec static_methods
[] = {
2671 JS_FN("parse", reflect_parse
, 1, 0),
2677 js_InitReflectClass(JSContext
*cx
, JSObject
*obj
)
2679 JSObject
*Reflect
= NewNonFunction
<WithProto::Class
>(cx
, &js_ReflectClass
, NULL
, obj
);
2683 if (!JS_DefineProperty(cx
, obj
, js_Reflect_str
, OBJECT_TO_JSVAL(Reflect
),
2684 JS_PropertyStub
, JS_PropertyStub
, 0))
2687 if (!JS_DefineFunctions(cx
, Reflect
, static_methods
))