1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/devtools/pretty-fast/tests/unit/test.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,524 @@ 1.4 +/* 1.5 + * Copyright 2013 Mozilla Foundation and contributors 1.6 + * Licensed under the New BSD license. See LICENSE.md or: 1.7 + * http://opensource.org/licenses/BSD-2-Clause 1.8 + */ 1.9 +var prettyFast = this.prettyFast || require("./pretty-fast"); 1.10 + 1.11 +var testCases = [ 1.12 + 1.13 + { 1.14 + name: "Simple function", 1.15 + input: "function foo() { bar(); }", 1.16 + output: "function foo() {\n" + 1.17 + " bar();\n" + 1.18 + "}\n", 1.19 + mappings: [ 1.20 + // function foo() { 1.21 + { 1.22 + inputLine: 1, 1.23 + outputLine: 1 1.24 + }, 1.25 + // bar(); 1.26 + { 1.27 + inputLine: 1, 1.28 + outputLine: 2 1.29 + }, 1.30 + // } 1.31 + { 1.32 + inputLine: 1, 1.33 + outputLine: 3 1.34 + }, 1.35 + ] 1.36 + }, 1.37 + 1.38 + { 1.39 + name: "Nested function", 1.40 + input: "function foo() { function bar() { debugger; } bar(); }", 1.41 + output: "function foo() {\n" + 1.42 + " function bar() {\n" + 1.43 + " debugger;\n" + 1.44 + " }\n" + 1.45 + " bar();\n" + 1.46 + "}\n", 1.47 + mappings: [ 1.48 + // function bar() { 1.49 + { 1.50 + inputLine: 1, 1.51 + outputLine: 2 1.52 + }, 1.53 + // debugger; 1.54 + { 1.55 + inputLine: 1, 1.56 + outputLine: 3 1.57 + }, 1.58 + // bar(); 1.59 + { 1.60 + inputLine: 1, 1.61 + outputLine: 5 1.62 + }, 1.63 + ] 1.64 + }, 1.65 + 1.66 + { 1.67 + name: "Immediately invoked function expression", 1.68 + input: "(function(){thingy()}())", 1.69 + output: "(function () {\n" + 1.70 + " thingy()\n" + 1.71 + "}())\n" 1.72 + }, 1.73 + 1.74 + { 1.75 + name: "Single line comment", 1.76 + input: "// Comment\n" + 1.77 + "function foo() { bar(); }\n", 1.78 + output: "// Comment\n" + 1.79 + "function foo() {\n" + 1.80 + " bar();\n" + 1.81 + "}\n", 1.82 + mappings: [ 1.83 + // // Comment 1.84 + { 1.85 + inputLine: 1, 1.86 + outputLine: 1 1.87 + } 1.88 + ] 1.89 + }, 1.90 + 1.91 + { 1.92 + name: "Multi line comment", 1.93 + input: "/* Comment\n" + 1.94 + "more comment */\n" + 1.95 + "function foo() { bar(); }\n", 1.96 + output: "/* Comment\n" + 1.97 + "more comment */\n" + 1.98 + "function foo() {\n" + 1.99 + " bar();\n" + 1.100 + "}\n", 1.101 + mappings: [ 1.102 + // /* Comment 1.103 + { 1.104 + inputLine: 1, 1.105 + outputLine: 1 1.106 + }, 1.107 + // \nmore comment */ 1.108 + { 1.109 + inputLine: 1, 1.110 + outputLine: 2 1.111 + } 1.112 + ] 1.113 + }, 1.114 + 1.115 + { 1.116 + name: "Null assignment", 1.117 + input: "var i=null;\n", 1.118 + output: "var i = null;\n", 1.119 + mappings: [ 1.120 + { 1.121 + inputLine: 1, 1.122 + outputLine: 1 1.123 + } 1.124 + ] 1.125 + }, 1.126 + 1.127 + { 1.128 + name: "Undefined assignment", 1.129 + input: "var i=undefined;\n", 1.130 + output: "var i = undefined;\n" 1.131 + }, 1.132 + 1.133 + { 1.134 + name: "Void 0 assignment", 1.135 + input: "var i=void 0;\n", 1.136 + output: "var i = void 0;\n" 1.137 + }, 1.138 + 1.139 + { 1.140 + name: "This property access", 1.141 + input: "var foo=this.foo;\n", 1.142 + output: "var foo = this.foo;\n" 1.143 + }, 1.144 + 1.145 + { 1.146 + name: "True assignment", 1.147 + input: "var foo=true;\n", 1.148 + output: "var foo = true;\n" 1.149 + }, 1.150 + 1.151 + { 1.152 + name: "False assignment", 1.153 + input: "var foo=false;\n", 1.154 + output: "var foo = false;\n" 1.155 + }, 1.156 + 1.157 + { 1.158 + name: "For loop", 1.159 + input: "for (var i = 0; i < n; i++) { console.log(i); }", 1.160 + output: "for (var i = 0; i < n; i++) {\n" + 1.161 + " console.log(i);\n" + 1.162 + "}\n", 1.163 + mappings: [ 1.164 + // for (var i = 0; i < n; i++) { 1.165 + { 1.166 + inputLine: 1, 1.167 + outputLine: 1 1.168 + }, 1.169 + // console.log(i); 1.170 + { 1.171 + inputLine: 1, 1.172 + outputLine: 2 1.173 + }, 1.174 + ] 1.175 + }, 1.176 + 1.177 + { 1.178 + name: "String with semicolon", 1.179 + input: "var foo = ';';\n", 1.180 + output: "var foo = ';';\n" 1.181 + }, 1.182 + 1.183 + { 1.184 + name: "String with quote", 1.185 + input: "var foo = \"'\";\n", 1.186 + output: "var foo = '\\'';\n" 1.187 + }, 1.188 + 1.189 + { 1.190 + name: "Function calls", 1.191 + input: "var result=func(a,b,c,d);", 1.192 + output: "var result = func(a, b, c, d);\n" 1.193 + }, 1.194 + 1.195 + { 1.196 + name: "Regexp", 1.197 + input: "var r=/foobar/g;", 1.198 + output: "var r = /foobar/g;\n" 1.199 + }, 1.200 + 1.201 + { 1.202 + name: "In operator", 1.203 + input: "if(foo in bar){doThing()}", 1.204 + output: "if (foo in bar) {\n" + 1.205 + " doThing()\n" + 1.206 + "}\n" 1.207 + }, 1.208 + 1.209 + { 1.210 + name: "With statement", 1.211 + input: "with(obj){crock()}", 1.212 + output: "with (obj) {\n" + 1.213 + " crock()\n" + 1.214 + "}\n" 1.215 + }, 1.216 + 1.217 + { 1.218 + name: "New expression", 1.219 + input: "var foo=new Foo();", 1.220 + output: "var foo = new Foo();\n" 1.221 + }, 1.222 + 1.223 + { 1.224 + name: "Continue/break statements", 1.225 + input: "while(1){if(x){continue}if(y){break}if(z){break foo}}", 1.226 + output: "while (1) {\n" + 1.227 + " if (x) {\n" + 1.228 + " continue\n" + 1.229 + " }\n" + 1.230 + " if (y) {\n" + 1.231 + " break\n" + 1.232 + " }\n" + 1.233 + " if (z) {\n" + 1.234 + " break foo\n" + 1.235 + " }\n" + 1.236 + "}\n" 1.237 + }, 1.238 + 1.239 + { 1.240 + name: "Instanceof", 1.241 + input: "var a=x instanceof y;", 1.242 + output: "var a = x instanceof y;\n" 1.243 + }, 1.244 + 1.245 + { 1.246 + name: "Binary operators", 1.247 + input: "var a=5*30;var b=5>>3;", 1.248 + output: "var a = 5 * 30;\n" + 1.249 + "var b = 5 >> 3;\n" 1.250 + }, 1.251 + 1.252 + { 1.253 + name: "Delete", 1.254 + input: "delete obj.prop;", 1.255 + output: "delete obj.prop;\n" 1.256 + }, 1.257 + 1.258 + { 1.259 + name: "Try/catch/finally statement", 1.260 + input: "try{dangerous()}catch(e){handle(e)}finally{cleanup()}", 1.261 + output: "try {\n" + 1.262 + " dangerous()\n" + 1.263 + "} catch (e) {\n" + 1.264 + " handle(e)\n" + 1.265 + "} finally {\n" + 1.266 + " cleanup()\n" + 1.267 + "}\n" 1.268 + }, 1.269 + 1.270 + { 1.271 + name: "If/else statement", 1.272 + input: "if(c){then()}else{other()}", 1.273 + output: "if (c) {\n" + 1.274 + " then()\n" + 1.275 + "} else {\n" + 1.276 + " other()\n" + 1.277 + "}\n" 1.278 + }, 1.279 + 1.280 + { 1.281 + name: "If/else without curlies", 1.282 + input: "if(c) a else b", 1.283 + output: "if (c) a else b\n" 1.284 + }, 1.285 + 1.286 + { 1.287 + name: "Objects", 1.288 + input: "var o={a:1,\n" + 1.289 + " b:2};", 1.290 + output: "var o = {\n" + 1.291 + " a: 1,\n" + 1.292 + " b: 2\n" + 1.293 + "};\n", 1.294 + mappings: [ 1.295 + // a: 1, 1.296 + { 1.297 + inputLine: 1, 1.298 + outputLine: 2 1.299 + }, 1.300 + // b: 2 1.301 + { 1.302 + inputLine: 2, 1.303 + outputLine: 3 1.304 + }, 1.305 + ] 1.306 + }, 1.307 + 1.308 + { 1.309 + name: "Do/while loop", 1.310 + input: "do{x}while(y)", 1.311 + output: "do {\n" + 1.312 + " x\n" + 1.313 + "} while (y)\n" 1.314 + }, 1.315 + 1.316 + { 1.317 + name: "Arrays", 1.318 + input: "var a=[1,2,3];", 1.319 + output: "var a = [\n" + 1.320 + " 1,\n" + 1.321 + " 2,\n" + 1.322 + " 3\n" + 1.323 + "];\n" 1.324 + }, 1.325 + 1.326 + { 1.327 + name: "Code that relies on ASI", 1.328 + input: "var foo = 10\n" + 1.329 + "var bar = 20\n" + 1.330 + "function g() {\n" + 1.331 + " a()\n" + 1.332 + " b()\n" + 1.333 + "}", 1.334 + output: "var foo = 10\n" + 1.335 + "var bar = 20\n" + 1.336 + "function g() {\n" + 1.337 + " a()\n" + 1.338 + " b()\n" + 1.339 + "}\n" 1.340 + }, 1.341 + 1.342 + { 1.343 + name: "Ternary operator", 1.344 + input: "bar?baz:bang;", 1.345 + output: "bar ? baz : bang;\n" 1.346 + }, 1.347 + 1.348 + { 1.349 + name: "Switch statements", 1.350 + input: "switch(x){case a:foo();break;default:bar()}", 1.351 + output: "switch (x) {\n" + 1.352 + "case a:\n" + 1.353 + " foo();\n" + 1.354 + " break;\n" + 1.355 + "default:\n" + 1.356 + " bar()\n" + 1.357 + "}\n" 1.358 + }, 1.359 + 1.360 + { 1.361 + name: "Multiple single line comments", 1.362 + input: "function f() {\n" + 1.363 + " // a\n" + 1.364 + " // b\n" + 1.365 + " // c\n" + 1.366 + "}\n", 1.367 + output: "function f() {\n" + 1.368 + " // a\n" + 1.369 + " // b\n" + 1.370 + " // c\n" + 1.371 + "}\n", 1.372 + }, 1.373 + 1.374 + { 1.375 + name: "Indented multiline comment", 1.376 + input: "function foo() {\n" + 1.377 + " /**\n" + 1.378 + " * java doc style comment\n" + 1.379 + " * more comment\n" + 1.380 + " */\n" + 1.381 + " bar();\n" + 1.382 + "}\n", 1.383 + output: "function foo() {\n" + 1.384 + " /**\n" + 1.385 + " * java doc style comment\n" + 1.386 + " * more comment\n" + 1.387 + " */\n" + 1.388 + " bar();\n" + 1.389 + "}\n", 1.390 + }, 1.391 + 1.392 + { 1.393 + name: "ASI return", 1.394 + input: "function f() {\n" + 1.395 + " return\n" + 1.396 + " {}\n" + 1.397 + "}\n", 1.398 + output: "function f() {\n" + 1.399 + " return\n" + 1.400 + " {\n" + 1.401 + " }\n" + 1.402 + "}\n", 1.403 + }, 1.404 + 1.405 + { 1.406 + name: "Non-ASI property access", 1.407 + input: "[1,2,3]\n" + 1.408 + "[0]", 1.409 + output: "[\n" + 1.410 + " 1,\n" + 1.411 + " 2,\n" + 1.412 + " 3\n" + 1.413 + "]\n" + 1.414 + "[0]\n" 1.415 + }, 1.416 + 1.417 + { 1.418 + name: "Non-ASI in", 1.419 + input: "'x'\n" + 1.420 + "in foo", 1.421 + output: "'x' in foo\n" 1.422 + }, 1.423 + 1.424 + { 1.425 + name: "Non-ASI function call", 1.426 + input: "f\n" + 1.427 + "()", 1.428 + output: "f()\n" 1.429 + }, 1.430 + 1.431 + { 1.432 + name: "Non-ASI new", 1.433 + input: "new\n" + 1.434 + "F()", 1.435 + output: "new F()\n" 1.436 + }, 1.437 + 1.438 + { 1.439 + name: "Getter and setter literals", 1.440 + input: "var obj={get foo(){return this._foo},set foo(v){this._foo=v}}", 1.441 + output: "var obj = {\n" + 1.442 + " get foo() {\n" + 1.443 + " return this._foo\n" + 1.444 + " },\n" + 1.445 + " set foo(v) {\n" + 1.446 + " this._foo = v\n" + 1.447 + " }\n" + 1.448 + "}\n" 1.449 + }, 1.450 + 1.451 + { 1.452 + name: "Escaping backslashes in strings", 1.453 + input: "'\\\\'\n", 1.454 + output: "'\\\\'\n" 1.455 + }, 1.456 + 1.457 + { 1.458 + name: "Escaping carriage return in strings", 1.459 + input: "'\\r'\n", 1.460 + output: "'\\r'\n" 1.461 + }, 1.462 + 1.463 + { 1.464 + name: "Escaping tab in strings", 1.465 + input: "'\\t'\n", 1.466 + output: "'\\t'\n" 1.467 + }, 1.468 + 1.469 + { 1.470 + name: "Escaping vertical tab in strings", 1.471 + input: "'\\v'\n", 1.472 + output: "'\\v'\n" 1.473 + }, 1.474 + 1.475 + { 1.476 + name: "Escaping form feed in strings", 1.477 + input: "'\\f'\n", 1.478 + output: "'\\f'\n" 1.479 + }, 1.480 + 1.481 + { 1.482 + name: "Escaping null character in strings", 1.483 + input: "'\\0'\n", 1.484 + output: "'\\0'\n" 1.485 + }, 1.486 + 1.487 +]; 1.488 + 1.489 +var sourceMap = this.sourceMap || require("source-map"); 1.490 + 1.491 +function run_test() { 1.492 + testCases.forEach(function (test) { 1.493 + console.log(test.name); 1.494 + 1.495 + var actual = prettyFast(test.input, { 1.496 + indent: " ", 1.497 + url: "test.js" 1.498 + }); 1.499 + 1.500 + if (actual.code !== test.output) { 1.501 + throw new Error("Expected:\n" + test.output 1.502 + + "\nGot:\n" + actual.code); 1.503 + } 1.504 + 1.505 + if (test.mappings) { 1.506 + var smc = new sourceMap.SourceMapConsumer(actual.map.toJSON()); 1.507 + test.mappings.forEach(function (m) { 1.508 + var query = { line: m.outputLine, column: 0 }; 1.509 + var original = smc.originalPositionFor(query); 1.510 + if (original.line != m.inputLine) { 1.511 + throw new Error("Querying:\n" + JSON.stringify(query, null, 2) + "\n" 1.512 + + "Expected line:\n" + m.inputLine + "\n" 1.513 + + "Got:\n" + JSON.stringify(original, null, 2)); 1.514 + } 1.515 + }); 1.516 + } 1.517 + }); 1.518 + console.log("✓ All tests pass!"); 1.519 +} 1.520 + 1.521 +// Only run the tests if this is node and we are running this file 1.522 +// directly. (Firefox's test runner will import this test file, and then call 1.523 +// run_test itself.) 1.524 +if (typeof require == "function" && typeof module == "object" 1.525 + && require.main === module) { 1.526 + run_test(); 1.527 +}