js/src/tests/js1_8_5/extensions/reflect-parse.js

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

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.

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

mercurial