Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 // |reftest| skip-if(!xulRuntime.shell)
2 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /*
4 * Any copyright is dedicated to the Public Domain.
5 * http://creativecommons.org/licenses/publicdomain/
6 */
8 (function runtest(main) {
9 try {
10 main();
11 } catch (exc) {
12 print(exc.stack);
13 throw exc;
14 }
15 })(function main() {
17 var { Pattern, MatchError } = Match;
19 var _ = Pattern.ANY;
21 function program(elts) Pattern({ type: "Program", body: elts })
22 function exprStmt(expr) Pattern({ type: "ExpressionStatement", expression: expr })
23 function throwStmt(expr) Pattern({ type: "ThrowStatement", argument: expr })
24 function returnStmt(expr) Pattern({ type: "ReturnStatement", argument: expr })
25 function yieldExpr(expr) Pattern({ type: "YieldExpression", argument: expr })
26 function lit(val) Pattern({ type: "Literal", value: val })
27 function spread(val) Pattern({ type: "SpreadExpression", expression: val})
28 var thisExpr = Pattern({ type: "ThisExpression" });
29 function funDecl(id, params, body, defaults=[], rest=null) Pattern(
30 { type: "FunctionDeclaration",
31 id: id,
32 params: params,
33 defaults: defaults,
34 body: body,
35 rest: rest,
36 generator: false })
37 function genFunDecl(id, params, body) Pattern({ type: "FunctionDeclaration",
38 id: id,
39 params: params,
40 defaults: [],
41 body: body,
42 generator: true })
43 function varDecl(decls) Pattern({ type: "VariableDeclaration", declarations: decls, kind: "var" })
44 function letDecl(decls) Pattern({ type: "VariableDeclaration", declarations: decls, kind: "let" })
45 function constDecl(decls) Pattern({ type: "VariableDeclaration", declarations: decls, kind: "const" })
46 function ident(name) Pattern({ type: "Identifier", name: name })
47 function dotExpr(obj, id) Pattern({ type: "MemberExpression", computed: false, object: obj, property: id })
48 function memExpr(obj, id) Pattern({ type: "MemberExpression", computed: true, object: obj, property: id })
49 function forStmt(init, test, update, body) Pattern({ type: "ForStatement", init: init, test: test, update: update, body: body })
50 function forOfStmt(lhs, rhs, body) Pattern({ type: "ForOfStatement", left: lhs, right: rhs, body: body })
51 function forInStmt(lhs, rhs, body) Pattern({ type: "ForInStatement", left: lhs, right: rhs, body: body, each: false })
52 function forEachInStmt(lhs, rhs, body) Pattern({ type: "ForInStatement", left: lhs, right: rhs, body: body, each: true })
53 function breakStmt(lab) Pattern({ type: "BreakStatement", label: lab })
54 function continueStmt(lab) Pattern({ type: "ContinueStatement", label: lab })
55 function blockStmt(body) Pattern({ type: "BlockStatement", body: body })
56 var emptyStmt = Pattern({ type: "EmptyStatement" })
57 function ifStmt(test, cons, alt) Pattern({ type: "IfStatement", test: test, alternate: alt, consequent: cons })
58 function labStmt(lab, stmt) Pattern({ type: "LabeledStatement", label: lab, body: stmt })
59 function withStmt(obj, stmt) Pattern({ type: "WithStatement", object: obj, body: stmt })
60 function whileStmt(test, stmt) Pattern({ type: "WhileStatement", test: test, body: stmt })
61 function doStmt(stmt, test) Pattern({ type: "DoWhileStatement", test: test, body: stmt })
62 function switchStmt(disc, cases) Pattern({ type: "SwitchStatement", discriminant: disc, cases: cases })
63 function caseClause(test, stmts) Pattern({ type: "SwitchCase", test: test, consequent: stmts })
64 function defaultClause(stmts) Pattern({ type: "SwitchCase", test: null, consequent: stmts })
65 function catchClause(id, guard, body) Pattern({ type: "CatchClause", param: id, guard: guard, body: body })
66 function tryStmt(body, guarded, unguarded, fin) Pattern({ type: "TryStatement", block: body, guardedHandlers: guarded, handler: unguarded, finalizer: fin })
67 function letStmt(head, body) Pattern({ type: "LetStatement", head: head, body: body })
68 function funExpr(id, args, body, gen) Pattern({ type: "FunctionExpression",
69 id: id,
70 params: args,
71 body: body,
72 generator: false })
73 function genFunExpr(id, args, body) Pattern({ type: "FunctionExpression",
74 id: id,
75 params: args,
76 body: body,
77 generator: true })
78 function arrowExpr(args, body) Pattern({ type: "ArrowExpression",
79 params: args,
80 body: body })
82 function unExpr(op, arg) Pattern({ type: "UnaryExpression", operator: op, argument: arg })
83 function binExpr(op, left, right) Pattern({ type: "BinaryExpression", operator: op, left: left, right: right })
84 function aExpr(op, left, right) Pattern({ type: "AssignmentExpression", operator: op, left: left, right: right })
85 function updExpr(op, arg, prefix) Pattern({ type: "UpdateExpression", operator: op, argument: arg, prefix: prefix })
86 function logExpr(op, left, right) Pattern({ type: "LogicalExpression", operator: op, left: left, right: right })
88 function condExpr(test, cons, alt) Pattern({ type: "ConditionalExpression", test: test, consequent: cons, alternate: alt })
89 function seqExpr(exprs) Pattern({ type: "SequenceExpression", expressions: exprs })
90 function newExpr(callee, args) Pattern({ type: "NewExpression", callee: callee, arguments: args })
91 function callExpr(callee, args) Pattern({ type: "CallExpression", callee: callee, arguments: args })
92 function arrExpr(elts) Pattern({ type: "ArrayExpression", elements: elts })
93 function objExpr(elts) Pattern({ type: "ObjectExpression", properties: elts })
94 function compExpr(body, blocks, filter) Pattern({ type: "ComprehensionExpression", body: body, blocks: blocks, filter: filter })
95 function genExpr(body, blocks, filter) Pattern({ type: "GeneratorExpression", body: body, blocks: blocks, filter: filter })
96 function graphExpr(idx, body) Pattern({ type: "GraphExpression", index: idx, expression: body })
97 function letExpr(head, body) Pattern({ type: "LetExpression", head: head, body: body })
98 function idxExpr(idx) Pattern({ type: "GraphIndexExpression", index: idx })
100 function compBlock(left, right) Pattern({ type: "ComprehensionBlock", left: left, right: right, each: false, of: false })
101 function compEachBlock(left, right) Pattern({ type: "ComprehensionBlock", left: left, right: right, each: true, of: false })
102 function compOfBlock(left, right) Pattern({ type: "ComprehensionBlock", left: left, right: right, each: false, of: true })
104 function arrPatt(elts) Pattern({ type: "ArrayPattern", elements: elts })
105 function objPatt(elts) Pattern({ type: "ObjectPattern", properties: elts })
107 function localSrc(src) "(function(){ " + src + " })"
108 function localPatt(patt) program([exprStmt(funExpr(null, [], blockStmt([patt])))])
109 function blockSrc(src) "(function(){ { " + src + " } })"
110 function blockPatt(patt) program([exprStmt(funExpr(null, [], blockStmt([blockStmt([patt])])))])
112 function assertBlockStmt(src, patt) {
113 blockPatt(patt).assert(Reflect.parse(blockSrc(src)));
114 }
116 function assertBlockExpr(src, patt) {
117 assertBlockStmt(src, exprStmt(patt));
118 }
120 function assertBlockDecl(src, patt, builder) {
121 blockPatt(patt).assert(Reflect.parse(blockSrc(src), {builder: builder}));
122 }
124 function assertLocalStmt(src, patt) {
125 localPatt(patt).assert(Reflect.parse(localSrc(src)));
126 }
128 function assertLocalExpr(src, patt) {
129 assertLocalStmt(src, exprStmt(patt));
130 }
132 function assertLocalDecl(src, patt) {
133 localPatt(patt).assert(Reflect.parse(localSrc(src)));
134 }
136 function assertGlobalStmt(src, patt, builder) {
137 program([patt]).assert(Reflect.parse(src, {builder: builder}));
138 }
140 function assertGlobalExpr(src, patt, builder) {
141 program([exprStmt(patt)]).assert(Reflect.parse(src, {builder: builder}));
142 //assertStmt(src, exprStmt(patt));
143 }
145 function assertGlobalDecl(src, patt) {
146 program([patt]).assert(Reflect.parse(src));
147 }
149 function assertProg(src, patt) {
150 program(patt).assert(Reflect.parse(src));
151 }
153 function assertStmt(src, patt) {
154 assertLocalStmt(src, patt);
155 assertGlobalStmt(src, patt);
156 assertBlockStmt(src, patt);
157 }
159 function assertExpr(src, patt) {
160 assertLocalExpr(src, patt);
161 assertGlobalExpr(src, patt);
162 assertBlockExpr(src, patt);
163 }
165 function assertDecl(src, patt) {
166 assertLocalDecl(src, patt);
167 assertGlobalDecl(src, patt);
168 assertBlockDecl(src, patt);
169 }
171 function assertError(src, errorType) {
172 try {
173 Reflect.parse(src);
174 } catch (expected if expected instanceof errorType) {
175 return;
176 }
177 throw new Error("expected " + errorType.name + " for " + uneval(src));
178 }
181 // general tests
183 // NB: These are useful but for now jit-test doesn't do I/O reliably.
185 //program(_).assert(Reflect.parse(snarf('data/flapjax.txt')));
186 //program(_).assert(Reflect.parse(snarf('data/jquery-1.4.2.txt')));
187 //program(_).assert(Reflect.parse(snarf('data/prototype.js')));
188 //program(_).assert(Reflect.parse(snarf('data/dojo.js.uncompressed.js')));
189 //program(_).assert(Reflect.parse(snarf('data/mootools-1.2.4-core-nc.js')));
192 // declarations
194 assertDecl("var x = 1, y = 2, z = 3",
195 varDecl([{ id: ident("x"), init: lit(1) },
196 { id: ident("y"), init: lit(2) },
197 { id: ident("z"), init: lit(3) }]));
198 assertDecl("var x, y, z",
199 varDecl([{ id: ident("x"), init: null },
200 { id: ident("y"), init: null },
201 { id: ident("z"), init: null }]));
202 assertDecl("function foo() { }",
203 funDecl(ident("foo"), [], blockStmt([])));
204 assertDecl("function foo() { return 42 }",
205 funDecl(ident("foo"), [], blockStmt([returnStmt(lit(42))])));
207 assertDecl("function foo(...rest) { }",
208 funDecl(ident("foo"), [], blockStmt([]), [], ident("rest")));
210 assertDecl("function foo(a=4) { }", funDecl(ident("foo"), [ident("a")], blockStmt([]), [lit(4)]));
211 assertDecl("function foo(a, b=4) { }", funDecl(ident("foo"), [ident("a"), ident("b")], blockStmt([]), [lit(4)]));
212 assertDecl("function foo(a, b=4, ...rest) { }",
213 funDecl(ident("foo"), [ident("a"), ident("b")], blockStmt([]), [lit(4)], ident("rest")));
214 assertDecl("function foo(a=(function () {})) { function a() {} }",
215 funDecl(ident("foo"), [ident("a")], blockStmt([funDecl(ident("a"), [], blockStmt([]))]),
216 [funExpr(ident("a"), [], blockStmt([]))]));
219 // Bug 591437: rebound args have their defs turned into uses
220 assertDecl("function f(a) { function a() { } }",
221 funDecl(ident("f"), [ident("a")], blockStmt([funDecl(ident("a"), [], blockStmt([]))])));
222 assertDecl("function f(a,b,c) { function b() { } }",
223 funDecl(ident("f"), [ident("a"),ident("b"),ident("c")], blockStmt([funDecl(ident("b"), [], blockStmt([]))])));
224 assertDecl("function f(a,[x,y]) { function a() { } }",
225 funDecl(ident("f"),
226 [ident("a"), arrPatt([ident("x"), ident("y")])],
227 blockStmt([funDecl(ident("a"), [], blockStmt([]))])));
229 // Bug 632027: array holes should reflect as null
230 assertExpr("[,]=[,]", aExpr("=", arrPatt([null]), arrExpr([null])));
232 // Bug 591450: this test currently crashes because of a bug in jsparse
233 // assertDecl("function f(a,[x,y],b,[w,z],c) { function b() { } }",
234 // funDecl(ident("f"),
235 // [ident("a"), arrPatt([ident("x"), ident("y")]), ident("b"), arrPatt([ident("w"), ident("z")]), ident("c")],
236 // blockStmt([funDecl(ident("b"), [], blockStmt([]))])));
239 // expressions
241 assertExpr("true", lit(true));
242 assertExpr("false", lit(false));
243 assertExpr("42", lit(42));
244 assertExpr("(/asdf/)", lit(/asdf/));
245 assertExpr("this", thisExpr);
246 assertExpr("foo", ident("foo"));
247 assertExpr("foo.bar", dotExpr(ident("foo"), ident("bar")));
248 assertExpr("foo[bar]", memExpr(ident("foo"), ident("bar")));
249 assertExpr("foo['bar']", memExpr(ident("foo"), lit("bar")));
250 assertExpr("foo[42]", memExpr(ident("foo"), lit(42)));
251 assertExpr("(function(){})", funExpr(null, [], blockStmt([])));
252 assertExpr("(function f() {})", funExpr(ident("f"), [], blockStmt([])));
253 assertExpr("(function f(x,y,z) {})", funExpr(ident("f"), [ident("x"),ident("y"),ident("z")], blockStmt([])));
254 assertExpr("a => a", arrowExpr([ident("a")], ident("a")));
255 assertExpr("(a) => a", arrowExpr([ident("a")], ident("a")));
256 assertExpr("a => b => a", arrowExpr([ident("a")], arrowExpr([ident("b")], ident("a"))));
257 assertExpr("a => {}", arrowExpr([ident("a")], blockStmt([])));
258 assertExpr("a => ({})", arrowExpr([ident("a")], objExpr([])));
259 assertExpr("(a, b, c) => {}", arrowExpr([ident("a"), ident("b"), ident("c")], blockStmt([])));
260 assertExpr("([a, b]) => {}", arrowExpr([arrPatt([ident("a"), ident("b")])], blockStmt([])));
261 assertExpr("(++x)", updExpr("++", ident("x"), true));
262 assertExpr("(x++)", updExpr("++", ident("x"), false));
263 assertExpr("(+x)", unExpr("+", ident("x")));
264 assertExpr("(-x)", unExpr("-", ident("x")));
265 assertExpr("(!x)", unExpr("!", ident("x")));
266 assertExpr("(~x)", unExpr("~", ident("x")));
267 assertExpr("(delete x)", unExpr("delete", ident("x")));
268 assertExpr("(typeof x)", unExpr("typeof", ident("x")));
269 assertExpr("(void x)", unExpr("void", ident("x")));
270 assertExpr("(x == y)", binExpr("==", ident("x"), ident("y")));
271 assertExpr("(x != y)", binExpr("!=", ident("x"), ident("y")));
272 assertExpr("(x === y)", binExpr("===", ident("x"), ident("y")));
273 assertExpr("(x !== y)", binExpr("!==", ident("x"), ident("y")));
274 assertExpr("(x < y)", binExpr("<", ident("x"), ident("y")));
275 assertExpr("(x <= y)", binExpr("<=", ident("x"), ident("y")));
276 assertExpr("(x > y)", binExpr(">", ident("x"), ident("y")));
277 assertExpr("(x >= y)", binExpr(">=", ident("x"), ident("y")));
278 assertExpr("(x << y)", binExpr("<<", ident("x"), ident("y")));
279 assertExpr("(x >> y)", binExpr(">>", ident("x"), ident("y")));
280 assertExpr("(x >>> y)", binExpr(">>>", ident("x"), ident("y")));
281 assertExpr("(x + y)", binExpr("+", ident("x"), ident("y")));
282 assertExpr("(w + x + y + z)", binExpr("+", binExpr("+", binExpr("+", ident("w"), ident("x")), ident("y")), ident("z")));
283 assertExpr("(x - y)", binExpr("-", ident("x"), ident("y")));
284 assertExpr("(w - x - y - z)", binExpr("-", binExpr("-", binExpr("-", ident("w"), ident("x")), ident("y")), ident("z")));
285 assertExpr("(x * y)", binExpr("*", ident("x"), ident("y")));
286 assertExpr("(x / y)", binExpr("/", ident("x"), ident("y")));
287 assertExpr("(x % y)", binExpr("%", ident("x"), ident("y")));
288 assertExpr("(x | y)", binExpr("|", ident("x"), ident("y")));
289 assertExpr("(x ^ y)", binExpr("^", ident("x"), ident("y")));
290 assertExpr("(x & y)", binExpr("&", ident("x"), ident("y")));
291 assertExpr("(x in y)", binExpr("in", ident("x"), ident("y")));
292 assertExpr("(x instanceof y)", binExpr("instanceof", ident("x"), ident("y")));
293 assertExpr("(x = y)", aExpr("=", ident("x"), ident("y")));
294 assertExpr("(x += y)", aExpr("+=", ident("x"), ident("y")));
295 assertExpr("(x -= y)", aExpr("-=", ident("x"), ident("y")));
296 assertExpr("(x *= y)", aExpr("*=", ident("x"), ident("y")));
297 assertExpr("(x /= y)", aExpr("/=", ident("x"), ident("y")));
298 assertExpr("(x %= y)", aExpr("%=", ident("x"), ident("y")));
299 assertExpr("(x <<= y)", aExpr("<<=", ident("x"), ident("y")));
300 assertExpr("(x >>= y)", aExpr(">>=", ident("x"), ident("y")));
301 assertExpr("(x >>>= y)", aExpr(">>>=", ident("x"), ident("y")));
302 assertExpr("(x |= y)", aExpr("|=", ident("x"), ident("y")));
303 assertExpr("(x ^= y)", aExpr("^=", ident("x"), ident("y")));
304 assertExpr("(x &= y)", aExpr("&=", ident("x"), ident("y")));
305 assertExpr("(x || y)", logExpr("||", ident("x"), ident("y")));
306 assertExpr("(x && y)", logExpr("&&", ident("x"), ident("y")));
307 assertExpr("(w || x || y || z)", logExpr("||", logExpr("||", logExpr("||", ident("w"), ident("x")), ident("y")), ident("z")))
308 assertExpr("(x ? y : z)", condExpr(ident("x"), ident("y"), ident("z")));
309 assertExpr("(x,y)", seqExpr([ident("x"),ident("y")]))
310 assertExpr("(x,y,z)", seqExpr([ident("x"),ident("y"),ident("z")]))
311 assertExpr("(a,b,c,d,e,f,g)", seqExpr([ident("a"),ident("b"),ident("c"),ident("d"),ident("e"),ident("f"),ident("g")]));
312 assertExpr("(new Object)", newExpr(ident("Object"), []));
313 assertExpr("(new Object())", newExpr(ident("Object"), []));
314 assertExpr("(new Object(42))", newExpr(ident("Object"), [lit(42)]));
315 assertExpr("(new Object(1,2,3))", newExpr(ident("Object"), [lit(1),lit(2),lit(3)]));
316 assertExpr("(String())", callExpr(ident("String"), []));
317 assertExpr("(String(42))", callExpr(ident("String"), [lit(42)]));
318 assertExpr("(String(1,2,3))", callExpr(ident("String"), [lit(1),lit(2),lit(3)]));
319 assertExpr("[]", arrExpr([]));
320 assertExpr("[1]", arrExpr([lit(1)]));
321 assertExpr("[1,2]", arrExpr([lit(1),lit(2)]));
322 assertExpr("[1,2,3]", arrExpr([lit(1),lit(2),lit(3)]));
323 assertExpr("[1,,2,3]", arrExpr([lit(1),null,lit(2),lit(3)]));
324 assertExpr("[1,,,2,3]", arrExpr([lit(1),null,null,lit(2),lit(3)]));
325 assertExpr("[1,,,2,,3]", arrExpr([lit(1),null,null,lit(2),null,lit(3)]));
326 assertExpr("[1,,,2,,,3]", arrExpr([lit(1),null,null,lit(2),null,null,lit(3)]));
327 assertExpr("[,1,2,3]", arrExpr([null,lit(1),lit(2),lit(3)]));
328 assertExpr("[,,1,2,3]", arrExpr([null,null,lit(1),lit(2),lit(3)]));
329 assertExpr("[,,,1,2,3]", arrExpr([null,null,null,lit(1),lit(2),lit(3)]));
330 assertExpr("[,,,1,2,3,]", arrExpr([null,null,null,lit(1),lit(2),lit(3)]));
331 assertExpr("[,,,1,2,3,,]", arrExpr([null,null,null,lit(1),lit(2),lit(3),null]));
332 assertExpr("[,,,1,2,3,,,]", arrExpr([null,null,null,lit(1),lit(2),lit(3),null,null]));
333 assertExpr("[,,,,,]", arrExpr([null,null,null,null,null]));
334 assertExpr("[1, ...a, 2]", arrExpr([lit(1), spread(ident("a")), lit(2)]));
335 assertExpr("[,, ...a,, ...b, 42]", arrExpr([null,null, spread(ident("a")),, spread(ident("b")), lit(42)]));
336 assertExpr("[1,(2,3)]", arrExpr([lit(1),seqExpr([lit(2),lit(3)])]));
337 assertExpr("[,(2,3)]", arrExpr([null,seqExpr([lit(2),lit(3)])]));
338 assertExpr("({})", objExpr([]));
339 assertExpr("({x:1})", objExpr([{ key: ident("x"), value: lit(1) }]));
340 assertExpr("({x:1, y:2})", objExpr([{ key: ident("x"), value: lit(1) },
341 { key: ident("y"), value: lit(2) } ]));
342 assertExpr("({x:1, y:2, z:3})", objExpr([{ key: ident("x"), value: lit(1) },
343 { key: ident("y"), value: lit(2) },
344 { key: ident("z"), value: lit(3) } ]));
345 assertExpr("({x:1, 'y':2, z:3})", objExpr([{ key: ident("x"), value: lit(1) },
346 { key: lit("y"), value: lit(2) },
347 { key: ident("z"), value: lit(3) } ]));
348 assertExpr("({'x':1, 'y':2, z:3})", objExpr([{ key: lit("x"), value: lit(1) },
349 { key: lit("y"), value: lit(2) },
350 { key: ident("z"), value: lit(3) } ]));
351 assertExpr("({'x':1, 'y':2, 3:3})", objExpr([{ key: lit("x"), value: lit(1) },
352 { key: lit("y"), value: lit(2) },
353 { key: lit(3), value: lit(3) } ]));
355 // Bug 571617: eliminate constant-folding
356 assertExpr("2 + 3", binExpr("+", lit(2), lit(3)));
358 // Bug 632026: constant-folding
359 assertExpr("typeof(0?0:a)", unExpr("typeof", condExpr(lit(0), lit(0), ident("a"))));
361 // Bug 632029: constant-folding
362 assertExpr("[x for each (x in y) if (false)]", compExpr(ident("x"), [compEachBlock(ident("x"), ident("y"))], lit(false)));
364 // Bug 632056: constant-folding
365 program([exprStmt(ident("f")),
366 ifStmt(lit(1),
367 funDecl(ident("f"), [], blockStmt([])),
368 null)]).assert(Reflect.parse("f; if (1) function f(){}"));
370 // statements
372 assertStmt("throw 42", throwStmt(lit(42)));
373 assertStmt("for (;;) break", forStmt(null, null, null, breakStmt(null)));
374 assertStmt("for (x; y; z) break", forStmt(ident("x"), ident("y"), ident("z"), breakStmt(null)));
375 assertStmt("for (var x; y; z) break", forStmt(varDecl([{ id: ident("x"), init: null }]), ident("y"), ident("z")));
376 assertStmt("for (var x = 42; y; z) break", forStmt(varDecl([{ id: ident("x"), init: lit(42) }]), ident("y"), ident("z")));
377 assertStmt("for (x; ; z) break", forStmt(ident("x"), null, ident("z"), breakStmt(null)));
378 assertStmt("for (var x; ; z) break", forStmt(varDecl([{ id: ident("x"), init: null }]), null, ident("z")));
379 assertStmt("for (var x = 42; ; z) break", forStmt(varDecl([{ id: ident("x"), init: lit(42) }]), null, ident("z")));
380 assertStmt("for (x; y; ) break", forStmt(ident("x"), ident("y"), null, breakStmt(null)));
381 assertStmt("for (var x; y; ) break", forStmt(varDecl([{ id: ident("x"), init: null }]), ident("y"), null, breakStmt(null)));
382 assertStmt("for (var x = 42; y; ) break", forStmt(varDecl([{ id: ident("x"), init: lit(42) }]), ident("y"), null, breakStmt(null)));
383 assertStmt("for (var x in y) break", forInStmt(varDecl([{ id: ident("x"), init: null }]), ident("y"), breakStmt(null)));
384 assertStmt("for (x in y) break", forInStmt(ident("x"), ident("y"), breakStmt(null)));
385 assertStmt("{ }", blockStmt([]));
386 assertStmt("{ throw 1; throw 2; throw 3; }", blockStmt([ throwStmt(lit(1)), throwStmt(lit(2)), throwStmt(lit(3))]));
387 assertStmt(";", emptyStmt);
388 assertStmt("if (foo) throw 42;", ifStmt(ident("foo"), throwStmt(lit(42)), null));
389 assertStmt("if (foo) throw 42; else true;", ifStmt(ident("foo"), throwStmt(lit(42)), exprStmt(lit(true))));
390 assertStmt("if (foo) { throw 1; throw 2; throw 3; }",
391 ifStmt(ident("foo"),
392 blockStmt([throwStmt(lit(1)), throwStmt(lit(2)), throwStmt(lit(3))]),
393 null));
394 assertStmt("if (foo) { throw 1; throw 2; throw 3; } else true;",
395 ifStmt(ident("foo"),
396 blockStmt([throwStmt(lit(1)), throwStmt(lit(2)), throwStmt(lit(3))]),
397 exprStmt(lit(true))));
398 assertStmt("foo: for(;;) break foo;", labStmt(ident("foo"), forStmt(null, null, null, breakStmt(ident("foo")))));
399 assertStmt("foo: for(;;) continue foo;", labStmt(ident("foo"), forStmt(null, null, null, continueStmt(ident("foo")))));
400 assertStmt("with (obj) { }", withStmt(ident("obj"), blockStmt([])));
401 assertStmt("with (obj) { obj; }", withStmt(ident("obj"), blockStmt([exprStmt(ident("obj"))])));
402 assertStmt("while (foo) { }", whileStmt(ident("foo"), blockStmt([])));
403 assertStmt("while (foo) { foo; }", whileStmt(ident("foo"), blockStmt([exprStmt(ident("foo"))])));
404 assertStmt("do { } while (foo);", doStmt(blockStmt([]), ident("foo")));
405 assertStmt("do { foo; } while (foo)", doStmt(blockStmt([exprStmt(ident("foo"))]), ident("foo")));
406 assertStmt("switch (foo) { case 1: 1; break; case 2: 2; break; default: 3; }",
407 switchStmt(ident("foo"),
408 [ caseClause(lit(1), [ exprStmt(lit(1)), breakStmt(null) ]),
409 caseClause(lit(2), [ exprStmt(lit(2)), breakStmt(null) ]),
410 defaultClause([ exprStmt(lit(3)) ]) ]));
411 assertStmt("switch (foo) { case 1: 1; break; case 2: 2; break; default: 3; case 42: 42; }",
412 switchStmt(ident("foo"),
413 [ caseClause(lit(1), [ exprStmt(lit(1)), breakStmt(null) ]),
414 caseClause(lit(2), [ exprStmt(lit(2)), breakStmt(null) ]),
415 defaultClause([ exprStmt(lit(3)) ]),
416 caseClause(lit(42), [ exprStmt(lit(42)) ]) ]));
417 assertStmt("try { } catch (e) { }",
418 tryStmt(blockStmt([]),
419 [],
420 catchClause(ident("e"), null, blockStmt([])),
421 null));
422 assertStmt("try { } catch (e) { } finally { }",
423 tryStmt(blockStmt([]),
424 [],
425 catchClause(ident("e"), null, blockStmt([])),
426 blockStmt([])));
427 assertStmt("try { } finally { }",
428 tryStmt(blockStmt([]),
429 [],
430 null,
431 blockStmt([])));
432 assertStmt("try { } catch (e if foo) { } catch (e if bar) { } finally { }",
433 tryStmt(blockStmt([]),
434 [ catchClause(ident("e"), ident("foo"), blockStmt([])),
435 catchClause(ident("e"), ident("bar"), blockStmt([])) ],
436 null,
437 blockStmt([])));
438 assertStmt("try { } catch (e if foo) { } catch (e if bar) { } catch (e) { } finally { }",
439 tryStmt(blockStmt([]),
440 [ catchClause(ident("e"), ident("foo"), blockStmt([])),
441 catchClause(ident("e"), ident("bar"), blockStmt([])) ],
442 catchClause(ident("e"), null, blockStmt([])),
443 blockStmt([])));
445 // Bug 632028: yield outside of a function should throw
446 (function() {
447 var threw = false;
448 try {
449 Reflect.parse("yield 0");
450 } catch (expected) {
451 threw = true;
452 }
453 assertEq(threw, true);
454 })();
456 // redeclarations (TOK_NAME nodes with lexdef)
458 assertStmt("function f() { function g() { } function g() { } }",
459 funDecl(ident("f"), [], blockStmt([emptyStmt,
460 funDecl(ident("g"), [], blockStmt([]))])));
462 // Fails due to parser quirks (bug 638577)
463 //assertStmt("function f() { function g() { } function g() { return 42 } }",
464 // funDecl(ident("f"), [], blockStmt([funDecl(ident("g"), [], blockStmt([])),
465 // funDecl(ident("g"), [], blockStmt([returnStmt(lit(42))]))])));
467 assertStmt("function f() { var x = 42; var x = 43; }",
468 funDecl(ident("f"), [], blockStmt([varDecl([{ id: ident("x"), init: lit(42) }]),
469 varDecl([{ id: ident("x"), init: lit(43) }])])));
472 assertDecl("var {x:y} = foo;", varDecl([{ id: objPatt([{ key: ident("x"), value: ident("y") }]),
473 init: ident("foo") }]));
475 // Bug 632030: redeclarations between var and funargs, var and function
476 assertStmt("function g(x) { var x }",
477 funDecl(ident("g"), [ident("x")], blockStmt([varDecl[{ id: ident("x"), init: null }]])));
478 assertProg("f.p = 1; var f; f.p; function f(){}",
479 [exprStmt(aExpr("=", dotExpr(ident("f"), ident("p")), lit(1))),
480 varDecl([{ id: ident("f"), init: null }]),
481 exprStmt(dotExpr(ident("f"), ident("p"))),
482 funDecl(ident("f"), [], blockStmt([]))]);
484 // global let is var
485 assertGlobalDecl("let {x:y} = foo;", varDecl([{ id: objPatt([{ key: ident("x"), value: ident("y") }]),
486 init: ident("foo") }]));
487 // function-global let is var
488 assertLocalDecl("let {x:y} = foo;", varDecl([{ id: objPatt([{ key: ident("x"), value: ident("y") }]),
489 init: ident("foo") }]));
490 // block-local let is let
491 assertBlockDecl("let {x:y} = foo;", letDecl([{ id: objPatt([{ key: ident("x"), value: ident("y") }]),
492 init: ident("foo") }]));
494 assertDecl("const {x:y} = foo;", constDecl([{ id: objPatt([{ key: ident("x"), value: ident("y") }]),
495 init: ident("foo") }]));
498 // various combinations of identifiers and destructuring patterns:
499 function makePatternCombinations(id, destr)
500 [
501 [ id(1) ],
502 [ id(1), id(2) ],
503 [ id(1), id(2), id(3) ],
504 [ id(1), id(2), id(3), id(4) ],
505 [ id(1), id(2), id(3), id(4), id(5) ],
507 [ destr(1) ],
508 [ destr(1), destr(2) ],
509 [ destr(1), destr(2), destr(3) ],
510 [ destr(1), destr(2), destr(3), destr(4) ],
511 [ destr(1), destr(2), destr(3), destr(4), destr(5) ],
513 [ destr(1), id(2) ],
515 [ destr(1), id(2), id(3) ],
516 [ destr(1), id(2), id(3), id(4) ],
517 [ destr(1), id(2), id(3), id(4), id(5) ],
518 [ destr(1), id(2), id(3), id(4), destr(5) ],
519 [ destr(1), id(2), id(3), destr(4) ],
520 [ destr(1), id(2), id(3), destr(4), id(5) ],
521 [ destr(1), id(2), id(3), destr(4), destr(5) ],
523 [ destr(1), id(2), destr(3) ],
524 [ destr(1), id(2), destr(3), id(4) ],
525 [ destr(1), id(2), destr(3), id(4), id(5) ],
526 [ destr(1), id(2), destr(3), id(4), destr(5) ],
527 [ destr(1), id(2), destr(3), destr(4) ],
528 [ destr(1), id(2), destr(3), destr(4), id(5) ],
529 [ destr(1), id(2), destr(3), destr(4), destr(5) ],
531 [ id(1), destr(2) ],
533 [ id(1), destr(2), id(3) ],
534 [ id(1), destr(2), id(3), id(4) ],
535 [ id(1), destr(2), id(3), id(4), id(5) ],
536 [ id(1), destr(2), id(3), id(4), destr(5) ],
537 [ id(1), destr(2), id(3), destr(4) ],
538 [ id(1), destr(2), id(3), destr(4), id(5) ],
539 [ id(1), destr(2), id(3), destr(4), destr(5) ],
541 [ id(1), destr(2), destr(3) ],
542 [ id(1), destr(2), destr(3), id(4) ],
543 [ id(1), destr(2), destr(3), id(4), id(5) ],
544 [ id(1), destr(2), destr(3), id(4), destr(5) ],
545 [ id(1), destr(2), destr(3), destr(4) ],
546 [ id(1), destr(2), destr(3), destr(4), id(5) ],
547 [ id(1), destr(2), destr(3), destr(4), destr(5) ]
548 ]
550 // destructuring function parameters
552 function testParamPatternCombinations(makePattSrc, makePattPatt) {
553 var pattSrcs = makePatternCombinations(function(n) ("x" + n), makePattSrc);
554 var pattPatts = makePatternCombinations(function(n) (ident("x" + n)), makePattPatt);
556 for (var i = 0; i < pattSrcs.length; i++) {
557 function makeSrc(body) ("(function(" + pattSrcs[i].join(",") + ") " + body + ")")
558 function makePatt(body) (funExpr(null, pattPatts[i], body))
560 // no upvars, block body
561 assertExpr(makeSrc("{ }", makePatt(blockStmt([]))));
562 // upvars, block body
563 assertExpr(makeSrc("{ return [x1,x2,x3,x4,x5]; }"),
564 makePatt(blockStmt([returnStmt(arrExpr([ident("x1"), ident("x2"), ident("x3"), ident("x4"), ident("x5")]))])));
565 // no upvars, expression body
566 assertExpr(makeSrc("(0)"), makePatt(lit(0)));
567 // upvars, expression body
568 assertExpr(makeSrc("[x1,x2,x3,x4,x5]"),
569 makePatt(arrExpr([ident("x1"), ident("x2"), ident("x3"), ident("x4"), ident("x5")])));
570 }
571 }
573 testParamPatternCombinations(function(n) ("{a" + n + ":x" + n + "," + "b" + n + ":y" + n + "," + "c" + n + ":z" + n + "}"),
574 function(n) (objPatt([{ key: ident("a" + n), value: ident("x" + n) },
575 { key: ident("b" + n), value: ident("y" + n) },
576 { key: ident("c" + n), value: ident("z" + n) }])));
578 testParamPatternCombinations(function(n) ("[x" + n + "," + "y" + n + "," + "z" + n + "]"),
579 function(n) (arrPatt([ident("x" + n), ident("y" + n), ident("z" + n)])));
582 // destructuring variable declarations
584 function testVarPatternCombinations(makePattSrc, makePattPatt) {
585 var pattSrcs = makePatternCombinations(function(n) ("x" + n), makePattSrc);
586 var pattPatts = makePatternCombinations(function(n) ({ id: ident("x" + n), init: null }), makePattPatt);
588 for (var i = 0; i < pattSrcs.length; i++) {
589 // variable declarations in blocks
590 assertDecl("var " + pattSrcs[i].join(",") + ";", varDecl(pattPatts[i]));
592 assertGlobalDecl("let " + pattSrcs[i].join(",") + ";", varDecl(pattPatts[i]));
593 assertLocalDecl("let " + pattSrcs[i].join(",") + ";", varDecl(pattPatts[i]));
594 assertBlockDecl("let " + pattSrcs[i].join(",") + ";", letDecl(pattPatts[i]));
596 assertDecl("const " + pattSrcs[i].join(",") + ";", constDecl(pattPatts[i]));
598 // variable declarations in for-loop heads
599 assertStmt("for (var " + pattSrcs[i].join(",") + "; foo; bar);",
600 forStmt(varDecl(pattPatts[i]), ident("foo"), ident("bar"), emptyStmt));
601 assertStmt("for (let " + pattSrcs[i].join(",") + "; foo; bar);",
602 letStmt(pattPatts[i], forStmt(null, ident("foo"), ident("bar"), emptyStmt)));
603 assertStmt("for (const " + pattSrcs[i].join(",") + "; foo; bar);",
604 forStmt(constDecl(pattPatts[i]), ident("foo"), ident("bar"), emptyStmt));
605 }
606 }
608 testVarPatternCombinations(function (n) ("{a" + n + ":x" + n + "," + "b" + n + ":y" + n + "," + "c" + n + ":z" + n + "} = 0"),
609 function (n) ({ id: objPatt([{ key: ident("a" + n), value: ident("x" + n) },
610 { key: ident("b" + n), value: ident("y" + n) },
611 { key: ident("c" + n), value: ident("z" + n) }]),
612 init: lit(0) }));
614 testVarPatternCombinations(function(n) ("[x" + n + "," + "y" + n + "," + "z" + n + "] = 0"),
615 function(n) ({ id: arrPatt([ident("x" + n), ident("y" + n), ident("z" + n)]),
616 init: lit(0) }));
618 // destructuring assignment
620 function testAssignmentCombinations(makePattSrc, makePattPatt) {
621 var pattSrcs = makePatternCombinations(function(n) ("x" + n + " = 0"), makePattSrc);
622 var pattPatts = makePatternCombinations(function(n) (aExpr("=", ident("x" + n), lit(0))), makePattPatt);
624 for (var i = 0; i < pattSrcs.length; i++) {
625 var src = pattSrcs[i].join(",");
626 var patt = pattPatts[i].length === 1 ? pattPatts[i][0] : seqExpr(pattPatts[i]);
628 // assignment expression statement
629 assertExpr("(" + src + ")", patt);
631 // for-loop head assignment
632 assertStmt("for (" + src + "; foo; bar);",
633 forStmt(patt, ident("foo"), ident("bar"), emptyStmt));
634 }
635 }
637 testAssignmentCombinations(function (n) ("{a" + n + ":x" + n + "," + "b" + n + ":y" + n + "," + "c" + n + ":z" + n + "} = 0"),
638 function (n) (aExpr("=",
639 objPatt([{ key: ident("a" + n), value: ident("x" + n) },
640 { key: ident("b" + n), value: ident("y" + n) },
641 { key: ident("c" + n), value: ident("z" + n) }]),
642 lit(0))));
645 // destructuring in for-in and for-each-in loop heads
647 var axbycz = objPatt([{ key: ident("a"), value: ident("x") },
648 { key: ident("b"), value: ident("y") },
649 { key: ident("c"), value: ident("z") }]);
650 var xyz = arrPatt([ident("x"), ident("y"), ident("z")]);
652 assertStmt("for (var {a:x,b:y,c:z} in foo);", forInStmt(varDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
653 assertStmt("for (let {a:x,b:y,c:z} in foo);", forInStmt(letDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
654 assertStmt("for ({a:x,b:y,c:z} in foo);", forInStmt(axbycz, ident("foo"), emptyStmt));
655 assertStmt("for (var [x,y,z] in foo);", forInStmt(varDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
656 assertStmt("for (let [x,y,z] in foo);", forInStmt(letDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
657 assertStmt("for ([x,y,z] in foo);", forInStmt(xyz, ident("foo"), emptyStmt));
658 assertStmt("for (var {a:x,b:y,c:z} of foo);", forOfStmt(varDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
659 assertStmt("for (let {a:x,b:y,c:z} of foo);", forOfStmt(letDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
660 assertStmt("for ({a:x,b:y,c:z} of foo);", forOfStmt(axbycz, ident("foo"), emptyStmt));
661 assertStmt("for (var [x,y,z] of foo);", forOfStmt(varDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
662 assertStmt("for (let [x,y,z] of foo);", forOfStmt(letDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
663 assertStmt("for ([x,y,z] of foo);", forOfStmt(xyz, ident("foo"), emptyStmt));
664 assertStmt("for each (var {a:x,b:y,c:z} in foo);", forEachInStmt(varDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
665 assertStmt("for each (let {a:x,b:y,c:z} in foo);", forEachInStmt(letDecl([{ id: axbycz, init: null }]), ident("foo"), emptyStmt));
666 assertStmt("for each ({a:x,b:y,c:z} in foo);", forEachInStmt(axbycz, ident("foo"), emptyStmt));
667 assertStmt("for each (var [x,y,z] in foo);", forEachInStmt(varDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
668 assertStmt("for each (let [x,y,z] in foo);", forEachInStmt(letDecl([{ id: xyz, init: null }]), ident("foo"), emptyStmt));
669 assertStmt("for each ([x,y,z] in foo);", forEachInStmt(xyz, ident("foo"), emptyStmt));
670 assertError("for (const x in foo);", SyntaxError);
671 assertError("for (const {a:x,b:y,c:z} in foo);", SyntaxError);
672 assertError("for (const [x,y,z] in foo);", SyntaxError);
673 assertError("for (const x of foo);", SyntaxError);
674 assertError("for (const {a:x,b:y,c:z} of foo);", SyntaxError);
675 assertError("for (const [x,y,z] of foo);", SyntaxError);
676 assertError("for each (const x in foo);", SyntaxError);
677 assertError("for each (const {a:x,b:y,c:z} in foo);", SyntaxError);
678 assertError("for each (const [x,y,z] in foo);", SyntaxError);
680 // destructuring in for-in and for-each-in loop heads with initializers
682 assertStmt("for (var {a:x,b:y,c:z} = 22 in foo);", forInStmt(varDecl([{ id: axbycz, init: lit(22) }]), ident("foo"), emptyStmt));
683 assertStmt("for (var [x,y,z] = 22 in foo);", forInStmt(varDecl([{ id: xyz, init: lit(22) }]), ident("foo"), emptyStmt));
684 assertStmt("for each (var {a:x,b:y,c:z} = 22 in foo);", forEachInStmt(varDecl([{ id: axbycz, init: lit(22) }]), ident("foo"), emptyStmt));
685 assertStmt("for each (var [x,y,z] = 22 in foo);", forEachInStmt(varDecl([{ id: xyz, init: lit(22) }]), ident("foo"), emptyStmt));
686 assertError("for (x = 22 in foo);", SyntaxError);
687 assertError("for ({a:x,b:y,c:z} = 22 in foo);", SyntaxError);
688 assertError("for ([x,y,z] = 22 in foo);", SyntaxError);
689 assertError("for (const x = 22 in foo);", SyntaxError);
690 assertError("for (const {a:x,b:y,c:z} = 22 in foo);", SyntaxError);
691 assertError("for (const [x,y,z] = 22 in foo);", SyntaxError);
692 assertError("for each (const x = 22 in foo);", SyntaxError);
693 assertError("for each (const {a:x,b:y,c:z} = 22 in foo);", SyntaxError);
694 assertError("for each (const [x,y,z] = 22 in foo);", SyntaxError);
696 // expression closures
698 assertDecl("function inc(x) (x + 1)", funDecl(ident("inc"), [ident("x")], binExpr("+", ident("x"), lit(1))));
699 assertExpr("(function(x) (x+1))", funExpr(null, [ident("x")], binExpr("+"), ident("x"), lit(1)));
701 // generators
703 assertDecl("function gen(x) { yield }", genFunDecl(ident("gen"), [ident("x")], blockStmt([exprStmt(yieldExpr(null))])));
704 assertExpr("(function(x) { yield })", genFunExpr(null, [ident("x")], blockStmt([exprStmt(yieldExpr(null))])));
705 assertDecl("function gen(x) { yield 42 }", genFunDecl(ident("gen"), [ident("x")], blockStmt([exprStmt(yieldExpr(lit(42)))])));
706 assertExpr("(function(x) { yield 42 })", genFunExpr(null, [ident("x")], blockStmt([exprStmt(yieldExpr(lit(42)))])));
708 // getters and setters
710 assertExpr("({ get x() { return 42 } })",
711 objExpr([ { key: ident("x"),
712 value: funExpr(null, [], blockStmt([returnStmt(lit(42))])),
713 kind: "get" } ]));
714 assertExpr("({ set x(v) { return 42 } })",
715 objExpr([ { key: ident("x"),
716 value: funExpr(null, [ident("v")], blockStmt([returnStmt(lit(42))])),
717 kind: "set" } ]));
719 // comprehensions
721 assertExpr("[ x for (x in foo)]",
722 compExpr(ident("x"), [compBlock(ident("x"), ident("foo"))], null));
723 assertExpr("[ [x,y] for (x in foo) for (y in bar)]",
724 compExpr(arrExpr([ident("x"), ident("y")]), [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar"))], null));
725 assertExpr("[ [x,y,z] for (x in foo) for (y in bar) for (z in baz)]",
726 compExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
727 [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar")), compBlock(ident("z"), ident("baz"))],
728 null));
730 assertExpr("[ x for (x in foo) if (p)]",
731 compExpr(ident("x"), [compBlock(ident("x"), ident("foo"))], ident("p")));
732 assertExpr("[ [x,y] for (x in foo) for (y in bar) if (p)]",
733 compExpr(arrExpr([ident("x"), ident("y")]), [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar"))], ident("p")));
734 assertExpr("[ [x,y,z] for (x in foo) for (y in bar) for (z in baz) if (p) ]",
735 compExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
736 [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar")), compBlock(ident("z"), ident("baz"))],
737 ident("p")));
739 assertExpr("[ x for each (x in foo)]",
740 compExpr(ident("x"), [compEachBlock(ident("x"), ident("foo"))], null));
741 assertExpr("[ [x,y] for each (x in foo) for each (y in bar)]",
742 compExpr(arrExpr([ident("x"), ident("y")]), [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar"))], null));
743 assertExpr("[ [x,y,z] for each (x in foo) for each (y in bar) for each (z in baz)]",
744 compExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
745 [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar")), compEachBlock(ident("z"), ident("baz"))],
746 null));
748 assertExpr("[ x for each (x in foo) if (p)]",
749 compExpr(ident("x"), [compEachBlock(ident("x"), ident("foo"))], ident("p")));
750 assertExpr("[ [x,y] for each (x in foo) for each (y in bar) if (p)]",
751 compExpr(arrExpr([ident("x"), ident("y")]), [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar"))], ident("p")));
752 assertExpr("[ [x,y,z] for each (x in foo) for each (y in bar) for each (z in baz) if (p) ]",
753 compExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
754 [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar")), compEachBlock(ident("z"), ident("baz"))],
755 ident("p")));
757 assertExpr("[ x for (x of foo)]",
758 compExpr(ident("x"), [compOfBlock(ident("x"), ident("foo"))], null));
759 assertExpr("[ [x,y] for (x of foo) for (y of bar)]",
760 compExpr(arrExpr([ident("x"), ident("y")]), [compOfBlock(ident("x"), ident("foo")), compOfBlock(ident("y"), ident("bar"))], null));
761 assertExpr("[ [x,y,z] for (x of foo) for (y of bar) for (z of baz)]",
762 compExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
763 [compOfBlock(ident("x"), ident("foo")), compOfBlock(ident("y"), ident("bar")), compOfBlock(ident("z"), ident("baz"))],
764 null));
766 assertExpr("[ x for (x of foo) if (p)]",
767 compExpr(ident("x"), [compOfBlock(ident("x"), ident("foo"))], ident("p")));
768 assertExpr("[ [x,y] for (x of foo) for (y of bar) if (p)]",
769 compExpr(arrExpr([ident("x"), ident("y")]), [compOfBlock(ident("x"), ident("foo")), compOfBlock(ident("y"), ident("bar"))], ident("p")));
770 assertExpr("[ [x,y,z] for (x of foo) for (y of bar) for (z of baz) if (p) ]",
771 compExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
772 [compOfBlock(ident("x"), ident("foo")), compOfBlock(ident("y"), ident("bar")), compOfBlock(ident("z"), ident("baz"))],
773 ident("p")));
775 // generator expressions
777 assertExpr("( x for (x in foo))",
778 genExpr(ident("x"), [compBlock(ident("x"), ident("foo"))], null));
779 assertExpr("( [x,y] for (x in foo) for (y in bar))",
780 genExpr(arrExpr([ident("x"), ident("y")]), [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar"))], null));
781 assertExpr("( [x,y,z] for (x in foo) for (y in bar) for (z in baz))",
782 genExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
783 [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar")), compBlock(ident("z"), ident("baz"))],
784 null));
786 assertExpr("( x for (x in foo) if (p))",
787 genExpr(ident("x"), [compBlock(ident("x"), ident("foo"))], ident("p")));
788 assertExpr("( [x,y] for (x in foo) for (y in bar) if (p))",
789 genExpr(arrExpr([ident("x"), ident("y")]), [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar"))], ident("p")));
790 assertExpr("( [x,y,z] for (x in foo) for (y in bar) for (z in baz) if (p) )",
791 genExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
792 [compBlock(ident("x"), ident("foo")), compBlock(ident("y"), ident("bar")), compBlock(ident("z"), ident("baz"))],
793 ident("p")));
795 assertExpr("( x for each (x in foo))",
796 genExpr(ident("x"), [compEachBlock(ident("x"), ident("foo"))], null));
797 assertExpr("( [x,y] for each (x in foo) for each (y in bar))",
798 genExpr(arrExpr([ident("x"), ident("y")]), [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar"))], null));
799 assertExpr("( [x,y,z] for each (x in foo) for each (y in bar) for each (z in baz))",
800 genExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
801 [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar")), compEachBlock(ident("z"), ident("baz"))],
802 null));
804 assertExpr("( x for each (x in foo) if (p))",
805 genExpr(ident("x"), [compEachBlock(ident("x"), ident("foo"))], ident("p")));
806 assertExpr("( [x,y] for each (x in foo) for each (y in bar) if (p))",
807 genExpr(arrExpr([ident("x"), ident("y")]), [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar"))], ident("p")));
808 assertExpr("( [x,y,z] for each (x in foo) for each (y in bar) for each (z in baz) if (p) )",
809 genExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
810 [compEachBlock(ident("x"), ident("foo")), compEachBlock(ident("y"), ident("bar")), compEachBlock(ident("z"), ident("baz"))],
811 ident("p")));
813 assertExpr("( x for (x of foo))",
814 genExpr(ident("x"), [compOfBlock(ident("x"), ident("foo"))], null));
815 assertExpr("( [x,y] for (x of foo) for (y of bar))",
816 genExpr(arrExpr([ident("x"), ident("y")]), [compOfBlock(ident("x"), ident("foo")), compOfBlock(ident("y"), ident("bar"))], null));
817 assertExpr("( [x,y,z] for (x of foo) for (y of bar) for (z of baz))",
818 genExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
819 [compOfBlock(ident("x"), ident("foo")), compOfBlock(ident("y"), ident("bar")), compOfBlock(ident("z"), ident("baz"))],
820 null));
822 assertExpr("( x for (x of foo) if (p))",
823 genExpr(ident("x"), [compOfBlock(ident("x"), ident("foo"))], ident("p")));
824 assertExpr("( [x,y] for (x of foo) for (y of bar) if (p))",
825 genExpr(arrExpr([ident("x"), ident("y")]), [compOfBlock(ident("x"), ident("foo")), compOfBlock(ident("y"), ident("bar"))], ident("p")));
826 assertExpr("( [x,y,z] for (x of foo) for (y of bar) for (z of baz) if (p) )",
827 genExpr(arrExpr([ident("x"), ident("y"), ident("z")]),
828 [compOfBlock(ident("x"), ident("foo")), compOfBlock(ident("y"), ident("bar")), compOfBlock(ident("z"), ident("baz"))],
829 ident("p")));
831 // NOTE: it would be good to test generator expressions both with and without upvars, just like functions above.
834 // let expressions
836 assertExpr("(let (x=1) x)", letExpr([{ id: ident("x"), init: lit(1) }], ident("x")));
837 assertExpr("(let (x=1,y=2) y)", letExpr([{ id: ident("x"), init: lit(1) },
838 { id: ident("y"), init: lit(2) }],
839 ident("y")));
840 assertExpr("(let (x=1,y=2,z=3) z)", letExpr([{ id: ident("x"), init: lit(1) },
841 { id: ident("y"), init: lit(2) },
842 { id: ident("z"), init: lit(3) }],
843 ident("z")));
844 assertExpr("(let (x) x)", letExpr([{ id: ident("x"), init: null }], ident("x")));
845 assertExpr("(let (x,y) y)", letExpr([{ id: ident("x"), init: null },
846 { id: ident("y"), init: null }],
847 ident("y")));
848 assertExpr("(let (x,y,z) z)", letExpr([{ id: ident("x"), init: null },
849 { id: ident("y"), init: null },
850 { id: ident("z"), init: null }],
851 ident("z")));
852 assertExpr("(let (x = 1, y = x) y)", letExpr([{ id: ident("x"), init: lit(1) },
853 { id: ident("y"), init: ident("x") }],
854 ident("y")));
855 assertError("(let (x = 1, x = 2) x)", TypeError);
857 // let statements
859 assertStmt("let (x=1) { }", letStmt([{ id: ident("x"), init: lit(1) }], blockStmt([])));
860 assertStmt("let (x=1,y=2) { }", letStmt([{ id: ident("x"), init: lit(1) },
861 { id: ident("y"), init: lit(2) }],
862 blockStmt([])));
863 assertStmt("let (x=1,y=2,z=3) { }", letStmt([{ id: ident("x"), init: lit(1) },
864 { id: ident("y"), init: lit(2) },
865 { id: ident("z"), init: lit(3) }],
866 blockStmt([])));
867 assertStmt("let (x) { }", letStmt([{ id: ident("x"), init: null }], blockStmt([])));
868 assertStmt("let (x,y) { }", letStmt([{ id: ident("x"), init: null },
869 { id: ident("y"), init: null }],
870 blockStmt([])));
871 assertStmt("let (x,y,z) { }", letStmt([{ id: ident("x"), init: null },
872 { id: ident("y"), init: null },
873 { id: ident("z"), init: null }],
874 blockStmt([])));
875 assertStmt("let (x = 1, y = x) { }", letStmt([{ id: ident("x"), init: lit(1) },
876 { id: ident("y"), init: ident("x") }],
877 blockStmt([])));
878 assertError("let (x = 1, x = 2) { }", TypeError);
881 // Bug 632024: no crashing on stack overflow
882 try {
883 Reflect.parse(Array(3000).join("x + y - ") + "z")
884 } catch (e) { }
887 // Source location information
890 var withoutFileOrLine = Reflect.parse("42");
891 var withFile = Reflect.parse("42", {source:"foo.js"});
892 var withFileAndLine = Reflect.parse("42", {source:"foo.js", line:111});
894 Pattern({ source: null, start: { line: 1, column: 0 }, end: { line: 1, column: 2 } }).match(withoutFileOrLine.loc);
895 Pattern({ source: "foo.js", start: { line: 1, column: 0 }, end: { line: 1, column: 2 } }).match(withFile.loc);
896 Pattern({ source: "foo.js", start: { line: 111, column: 0 }, end: { line: 111, column: 2 } }).match(withFileAndLine.loc);
898 var withoutFileOrLine2 = Reflect.parse("foo +\nbar");
899 var withFile2 = Reflect.parse("foo +\nbar", {source:"foo.js"});
900 var withFileAndLine2 = Reflect.parse("foo +\nbar", {source:"foo.js", line:111});
902 Pattern({ source: null, start: { line: 1, column: 0 }, end: { line: 2, column: 3 } }).match(withoutFileOrLine2.loc);
903 Pattern({ source: "foo.js", start: { line: 1, column: 0 }, end: { line: 2, column: 3 } }).match(withFile2.loc);
904 Pattern({ source: "foo.js", start: { line: 111, column: 0 }, end: { line: 112, column: 3 } }).match(withFileAndLine2.loc);
906 var nested = Reflect.parse("(-b + sqrt(sqr(b) - 4 * a * c)) / (2 * a)", {source:"quad.js"});
907 var fourAC = nested.body[0].expression.left.right.arguments[0].right;
909 Pattern({ source: "quad.js", start: { line: 1, column: 20 }, end: { line: 1, column: 29 } }).match(fourAC.loc);
912 // No source location
914 assertEq(Reflect.parse("42", {loc:false}).loc, null);
915 program([exprStmt(lit(42))]).assert(Reflect.parse("42", {loc:false}));
918 // Builder tests
920 Pattern("program").match(Reflect.parse("42", {builder:{program:function()"program"}}));
922 assertGlobalStmt("throw 42", 1, { throwStatement: function() 1 });
923 assertGlobalStmt("for (;;);", 2, { forStatement: function() 2 });
924 assertGlobalStmt("for (x in y);", 3, { forInStatement: function() 3 });
925 assertGlobalStmt("{ }", 4, { blockStatement: function() 4 });
926 assertGlobalStmt("foo: { }", 5, { labeledStatement: function() 5 });
927 assertGlobalStmt("with (o) { }", 6, { withStatement: function() 6 });
928 assertGlobalStmt("while (x) { }", 7, { whileStatement: function() 7 });
929 assertGlobalStmt("do { } while(false);", 8, { doWhileStatement: function() 8 });
930 assertGlobalStmt("switch (x) { }", 9, { switchStatement: function() 9 });
931 assertGlobalStmt("try { } catch(e) { }", 10, { tryStatement: function() 10 });
932 assertGlobalStmt(";", 11, { emptyStatement: function() 11 });
933 assertGlobalStmt("debugger;", 12, { debuggerStatement: function() 12 });
934 assertGlobalStmt("42;", 13, { expressionStatement: function() 13 });
935 assertGlobalStmt("for (;;) break", forStmt(null, null, null, 14), { breakStatement: function() 14 });
936 assertGlobalStmt("for (;;) continue", forStmt(null, null, null, 15), { continueStatement: function() 15 });
938 assertBlockDecl("var x", "var", { variableDeclaration: function(kind) kind });
939 assertBlockDecl("let x", "let", { variableDeclaration: function(kind) kind });
940 assertBlockDecl("const x", "const", { variableDeclaration: function(kind) kind });
941 assertBlockDecl("function f() { }", "function", { functionDeclaration: function() "function" });
943 assertGlobalExpr("(x,y,z)", 1, { sequenceExpression: function() 1 });
944 assertGlobalExpr("(x ? y : z)", 2, { conditionalExpression: function() 2 });
945 assertGlobalExpr("x + y", 3, { binaryExpression: function() 3 });
946 assertGlobalExpr("delete x", 4, { unaryExpression: function() 4 });
947 assertGlobalExpr("x = y", 5, { assignmentExpression: function() 5 });
948 assertGlobalExpr("x || y", 6, { logicalExpression: function() 6 });
949 assertGlobalExpr("x++", 7, { updateExpression: function() 7 });
950 assertGlobalExpr("new x", 8, { newExpression: function() 8 });
951 assertGlobalExpr("x()", 9, { callExpression: function() 9 });
952 assertGlobalExpr("x.y", 10, { memberExpression: function() 10 });
953 assertGlobalExpr("(function() { })", 11, { functionExpression: function() 11 });
954 assertGlobalExpr("[1,2,3]", 12, { arrayExpression: function() 12 });
955 assertGlobalExpr("({ x: y })", 13, { objectExpression: function() 13 });
956 assertGlobalExpr("this", 14, { thisExpression: function() 14 });
957 assertGlobalExpr("[x for (x in y)]", 17, { comprehensionExpression: function() 17 });
958 assertGlobalExpr("(x for (x in y))", 18, { generatorExpression: function() 18 });
959 assertGlobalExpr("(function() { yield 42 })", genFunExpr(null, [], blockStmt([exprStmt(19)])), { yieldExpression: function() 19 });
960 assertGlobalExpr("(let (x) x)", 20, { letExpression: function() 20 });
962 assertGlobalStmt("switch (x) { case y: }", switchStmt(ident("x"), [1]), { switchCase: function() 1 });
963 assertGlobalStmt("try { } catch (e) { }", 2, { tryStatement: (function(b, g, u, f) u), catchClause: function() 2 });
964 assertGlobalStmt("try { } catch (e if e instanceof A) { } catch (e if e instanceof B) { }", [2, 2], { tryStatement: (function(b, g, u, f) g), catchClause: function() 2 });
965 assertGlobalStmt("try { } catch (e) { }", tryStmt(blockStmt([]), [], 2, null), { catchClause: function() 2 });
966 assertGlobalStmt("try { } catch (e if e instanceof A) { } catch (e if e instanceof B) { }",
967 tryStmt(blockStmt([]), [2, 2], null, null),
968 { catchClause: function() 2 });
969 assertGlobalExpr("[x for (y in z) for (x in y)]", compExpr(ident("x"), [3, 3], null), { comprehensionBlock: function() 3 });
971 assertGlobalExpr("({ x: y } = z)", aExpr("=", 1, ident("z")), { objectPattern: function() 1 });
972 assertGlobalExpr("({ x: y } = z)", aExpr("=", objPatt([2]), ident("z")), { propertyPattern: function() 2 });
973 assertGlobalExpr("[ x ] = y", aExpr("=", 3, ident("y")), { arrayPattern: function() 3 });
975 // Ensure that exceptions thrown by builder methods propagate.
976 var thrown = false;
977 try {
978 Reflect.parse("42", { builder: { program: function() { throw "expected" } } });
979 } catch (e if e === "expected") {
980 thrown = true;
981 }
982 if (!thrown)
983 throw new Error("builder exception not propagated");
985 // Missing property RHS's in an object literal should throw.
986 try {
987 Reflect.parse("({foo})");
988 throw new Error("object literal missing property RHS didn't throw");
989 } catch (e if e instanceof SyntaxError) { }
992 // A simple proof-of-concept that the builder API can be used to generate other
993 // formats, such as JsonMLAst:
994 //
995 // http://code.google.com/p/es-lab/wiki/JsonMLASTFormat
996 //
997 // It's incomplete (e.g., it doesn't convert source-location information and
998 // doesn't use all the direct-eval rules), but I think it proves the point.
1000 var JsonMLAst = (function() {
1001 function reject() {
1002 throw new SyntaxError("node type not supported");
1003 }
1005 function isDirectEval(expr) {
1006 // an approximation to the actual rules. you get the idea
1007 return (expr[0] === "IdExpr" && expr[1].name === "eval");
1008 }
1010 function functionNode(type) {
1011 return function(id, args, body, isGenerator, isExpression) {
1012 if (isExpression)
1013 body = ["ReturnStmt", {}, body];
1015 if (!id)
1016 id = ["Empty"];
1018 // Patch up the argument node types: s/IdExpr/IdPatt/g
1019 for (var i = 0; i < args.length; i++) {
1020 args[i][0] = "IdPatt";
1021 }
1023 args.unshift("ParamDecl", {});
1025 return [type, {}, id, args, body];
1026 }
1027 }
1029 return {
1030 program: function(stmts) {
1031 stmts.unshift("Program", {});
1032 return stmts;
1033 },
1034 identifier: function(name) {
1035 return ["IdExpr", { name: name }];
1036 },
1037 literal: function(val) {
1038 return ["LiteralExpr", { value: val }];
1039 },
1040 expressionStatement: function(expr) expr,
1041 conditionalExpression: function(test, cons, alt) {
1042 return ["ConditionalExpr", {}, test, cons, alt];
1043 },
1044 unaryExpression: function(op, expr) {
1045 return ["UnaryExpr", {op: op}, expr];
1046 },
1047 binaryExpression: function(op, left, right) {
1048 return ["BinaryExpr", {op: op}, left, right];
1049 },
1050 property: function(kind, key, val) {
1051 return [kind === "init"
1052 ? "DataProp"
1053 : kind === "get"
1054 ? "GetterProp"
1055 : "SetterProp",
1056 {name: key[1].name}, val];
1057 },
1058 functionDeclaration: functionNode("FunctionDecl"),
1059 variableDeclaration: function(kind, elts) {
1060 if (kind === "let" || kind === "const")
1061 throw new SyntaxError("let and const not supported");
1062 elts.unshift("VarDecl", {});
1063 return elts;
1064 },
1065 variableDeclarator: function(id, init) {
1066 id[0] = "IdPatt";
1067 if (!init)
1068 return id;
1069 return ["InitPatt", {}, id, init];
1070 },
1071 sequenceExpression: function(exprs) {
1072 var length = exprs.length;
1073 var result = ["BinaryExpr", {op:","}, exprs[exprs.length - 2], exprs[exprs.length - 1]];
1074 for (var i = exprs.length - 3; i >= 0; i--) {
1075 result = ["BinaryExpr", {op:","}, exprs[i], result];
1076 }
1077 return result;
1078 },
1079 assignmentExpression: function(op, lhs, expr) {
1080 return ["AssignExpr", {op: op}, lhs, expr];
1081 },
1082 logicalExpression: function(op, left, right) {
1083 return [op === "&&" ? "LogicalAndExpr" : "LogicalOrExpr", {}, left, right];
1084 },
1085 updateExpression: function(expr, op, isPrefix) {
1086 return ["CountExpr", {isPrefix:isPrefix, op:op}, expr];
1087 },
1088 newExpression: function(callee, args) {
1089 args.unshift("NewExpr", {}, callee);
1090 return args;
1091 },
1092 callExpression: function(callee, args) {
1093 args.unshift(isDirectEval(callee) ? "EvalExpr" : "CallExpr", {}, callee);
1094 return args;
1095 },
1096 memberExpression: function(isComputed, expr, member) {
1097 return ["MemberExpr", {}, expr, isComputed ? member : ["LiteralExpr", {type: "string", value: member[1].name}]];
1098 },
1099 functionExpression: functionNode("FunctionExpr"),
1100 arrayExpression: function(elts) {
1101 for (var i = 0; i < elts.length; i++) {
1102 if (!elts[i])
1103 elts[i] = ["Empty"];
1104 }
1105 elts.unshift("ArrayExpr", {});
1106 return elts;
1107 },
1108 objectExpression: function(props) {
1109 props.unshift("ObjectExpr", {});
1110 return props;
1111 },
1112 thisExpression: function() {
1113 return ["ThisExpr", {}];
1114 },
1116 graphExpression: reject,
1117 graphIndexExpression: reject,
1118 comprehensionExpression: reject,
1119 generatorExpression: reject,
1120 yieldExpression: reject,
1121 letExpression: reject,
1123 emptyStatement: function() ["EmptyStmt", {}],
1124 blockStatement: function(stmts) {
1125 stmts.unshift("BlockStmt", {});
1126 return stmts;
1127 },
1128 labeledStatement: function(lab, stmt) {
1129 return ["LabelledStmt", {label: lab}, stmt];
1130 },
1131 ifStatement: function(test, cons, alt) {
1132 return ["IfStmt", {}, test, cons, alt || ["EmptyStmt", {}]];
1133 },
1134 switchStatement: function(test, clauses, isLexical) {
1135 clauses.unshift("SwitchStmt", {}, test);
1136 return clauses;
1137 },
1138 whileStatement: function(expr, stmt) {
1139 return ["WhileStmt", {}, expr, stmt];
1140 },
1141 doWhileStatement: function(stmt, expr) {
1142 return ["DoWhileStmt", {}, stmt, expr];
1143 },
1144 forStatement: function(init, test, update, body) {
1145 return ["ForStmt", {}, init || ["Empty"], test || ["Empty"], update || ["Empty"], body];
1146 },
1147 forInStatement: function(lhs, rhs, body) {
1148 return ["ForInStmt", {}, lhs, rhs, body];
1149 },
1150 breakStatement: function(lab) {
1151 return lab ? ["BreakStmt", {}, lab] : ["BreakStmt", {}];
1152 },
1153 continueStatement: function(lab) {
1154 return lab ? ["ContinueStmt", {}, lab] : ["ContinueStmt", {}];
1155 },
1156 withStatement: function(expr, stmt) {
1157 return ["WithStmt", {}, expr, stmt];
1158 },
1159 returnStatement: function(expr) {
1160 return expr ? ["ReturnStmt", {}, expr] : ["ReturnStmt", {}];
1161 },
1162 tryStatement: function(body, catches, fin) {
1163 if (catches.length > 1)
1164 throw new SyntaxError("multiple catch clauses not supported");
1165 var node = ["TryStmt", body, catches[0] || ["Empty"]];
1166 if (fin)
1167 node.push(fin);
1168 return node;
1169 },
1170 throwStatement: function(expr) {
1171 return ["ThrowStmt", {}, expr];
1172 },
1173 debuggerStatement: function() ["DebuggerStmt", {}],
1174 letStatement: reject,
1175 switchCase: function(expr, stmts) {
1176 if (expr)
1177 stmts.unshift("SwitchCase", {}, expr);
1178 else
1179 stmts.unshift("DefaultCase", {});
1180 return stmts;
1181 },
1182 catchClause: function(param, guard, body) {
1183 if (guard)
1184 throw new SyntaxError("catch guards not supported");
1185 param[0] = "IdPatt";
1186 return ["CatchClause", {}, param, body];
1187 },
1188 comprehensionBlock: reject,
1190 arrayPattern: reject,
1191 objectPattern: reject,
1192 propertyPattern: reject,
1193 };
1194 })();
1196 Pattern(["Program", {},
1197 ["BinaryExpr", {op: "+"},
1198 ["LiteralExpr", {value: 2}],
1199 ["BinaryExpr", {op: "*"},
1200 ["UnaryExpr", {op: "-"}, ["IdExpr", {name: "x"}]],
1201 ["IdExpr", {name: "y"}]]]]).match(Reflect.parse("2 + (-x * y)", {loc: false, builder: JsonMLAst}));
1203 reportCompare(true, true);
1205 });