|
1 /* |
|
2 * Copyright 2013 Mozilla Foundation and contributors |
|
3 * Licensed under the New BSD license. See LICENSE.md or: |
|
4 * http://opensource.org/licenses/BSD-2-Clause |
|
5 */ |
|
6 var prettyFast = this.prettyFast || require("./pretty-fast"); |
|
7 |
|
8 var testCases = [ |
|
9 |
|
10 { |
|
11 name: "Simple function", |
|
12 input: "function foo() { bar(); }", |
|
13 output: "function foo() {\n" + |
|
14 " bar();\n" + |
|
15 "}\n", |
|
16 mappings: [ |
|
17 // function foo() { |
|
18 { |
|
19 inputLine: 1, |
|
20 outputLine: 1 |
|
21 }, |
|
22 // bar(); |
|
23 { |
|
24 inputLine: 1, |
|
25 outputLine: 2 |
|
26 }, |
|
27 // } |
|
28 { |
|
29 inputLine: 1, |
|
30 outputLine: 3 |
|
31 }, |
|
32 ] |
|
33 }, |
|
34 |
|
35 { |
|
36 name: "Nested function", |
|
37 input: "function foo() { function bar() { debugger; } bar(); }", |
|
38 output: "function foo() {\n" + |
|
39 " function bar() {\n" + |
|
40 " debugger;\n" + |
|
41 " }\n" + |
|
42 " bar();\n" + |
|
43 "}\n", |
|
44 mappings: [ |
|
45 // function bar() { |
|
46 { |
|
47 inputLine: 1, |
|
48 outputLine: 2 |
|
49 }, |
|
50 // debugger; |
|
51 { |
|
52 inputLine: 1, |
|
53 outputLine: 3 |
|
54 }, |
|
55 // bar(); |
|
56 { |
|
57 inputLine: 1, |
|
58 outputLine: 5 |
|
59 }, |
|
60 ] |
|
61 }, |
|
62 |
|
63 { |
|
64 name: "Immediately invoked function expression", |
|
65 input: "(function(){thingy()}())", |
|
66 output: "(function () {\n" + |
|
67 " thingy()\n" + |
|
68 "}())\n" |
|
69 }, |
|
70 |
|
71 { |
|
72 name: "Single line comment", |
|
73 input: "// Comment\n" + |
|
74 "function foo() { bar(); }\n", |
|
75 output: "// Comment\n" + |
|
76 "function foo() {\n" + |
|
77 " bar();\n" + |
|
78 "}\n", |
|
79 mappings: [ |
|
80 // // Comment |
|
81 { |
|
82 inputLine: 1, |
|
83 outputLine: 1 |
|
84 } |
|
85 ] |
|
86 }, |
|
87 |
|
88 { |
|
89 name: "Multi line comment", |
|
90 input: "/* Comment\n" + |
|
91 "more comment */\n" + |
|
92 "function foo() { bar(); }\n", |
|
93 output: "/* Comment\n" + |
|
94 "more comment */\n" + |
|
95 "function foo() {\n" + |
|
96 " bar();\n" + |
|
97 "}\n", |
|
98 mappings: [ |
|
99 // /* Comment |
|
100 { |
|
101 inputLine: 1, |
|
102 outputLine: 1 |
|
103 }, |
|
104 // \nmore comment */ |
|
105 { |
|
106 inputLine: 1, |
|
107 outputLine: 2 |
|
108 } |
|
109 ] |
|
110 }, |
|
111 |
|
112 { |
|
113 name: "Null assignment", |
|
114 input: "var i=null;\n", |
|
115 output: "var i = null;\n", |
|
116 mappings: [ |
|
117 { |
|
118 inputLine: 1, |
|
119 outputLine: 1 |
|
120 } |
|
121 ] |
|
122 }, |
|
123 |
|
124 { |
|
125 name: "Undefined assignment", |
|
126 input: "var i=undefined;\n", |
|
127 output: "var i = undefined;\n" |
|
128 }, |
|
129 |
|
130 { |
|
131 name: "Void 0 assignment", |
|
132 input: "var i=void 0;\n", |
|
133 output: "var i = void 0;\n" |
|
134 }, |
|
135 |
|
136 { |
|
137 name: "This property access", |
|
138 input: "var foo=this.foo;\n", |
|
139 output: "var foo = this.foo;\n" |
|
140 }, |
|
141 |
|
142 { |
|
143 name: "True assignment", |
|
144 input: "var foo=true;\n", |
|
145 output: "var foo = true;\n" |
|
146 }, |
|
147 |
|
148 { |
|
149 name: "False assignment", |
|
150 input: "var foo=false;\n", |
|
151 output: "var foo = false;\n" |
|
152 }, |
|
153 |
|
154 { |
|
155 name: "For loop", |
|
156 input: "for (var i = 0; i < n; i++) { console.log(i); }", |
|
157 output: "for (var i = 0; i < n; i++) {\n" + |
|
158 " console.log(i);\n" + |
|
159 "}\n", |
|
160 mappings: [ |
|
161 // for (var i = 0; i < n; i++) { |
|
162 { |
|
163 inputLine: 1, |
|
164 outputLine: 1 |
|
165 }, |
|
166 // console.log(i); |
|
167 { |
|
168 inputLine: 1, |
|
169 outputLine: 2 |
|
170 }, |
|
171 ] |
|
172 }, |
|
173 |
|
174 { |
|
175 name: "String with semicolon", |
|
176 input: "var foo = ';';\n", |
|
177 output: "var foo = ';';\n" |
|
178 }, |
|
179 |
|
180 { |
|
181 name: "String with quote", |
|
182 input: "var foo = \"'\";\n", |
|
183 output: "var foo = '\\'';\n" |
|
184 }, |
|
185 |
|
186 { |
|
187 name: "Function calls", |
|
188 input: "var result=func(a,b,c,d);", |
|
189 output: "var result = func(a, b, c, d);\n" |
|
190 }, |
|
191 |
|
192 { |
|
193 name: "Regexp", |
|
194 input: "var r=/foobar/g;", |
|
195 output: "var r = /foobar/g;\n" |
|
196 }, |
|
197 |
|
198 { |
|
199 name: "In operator", |
|
200 input: "if(foo in bar){doThing()}", |
|
201 output: "if (foo in bar) {\n" + |
|
202 " doThing()\n" + |
|
203 "}\n" |
|
204 }, |
|
205 |
|
206 { |
|
207 name: "With statement", |
|
208 input: "with(obj){crock()}", |
|
209 output: "with (obj) {\n" + |
|
210 " crock()\n" + |
|
211 "}\n" |
|
212 }, |
|
213 |
|
214 { |
|
215 name: "New expression", |
|
216 input: "var foo=new Foo();", |
|
217 output: "var foo = new Foo();\n" |
|
218 }, |
|
219 |
|
220 { |
|
221 name: "Continue/break statements", |
|
222 input: "while(1){if(x){continue}if(y){break}if(z){break foo}}", |
|
223 output: "while (1) {\n" + |
|
224 " if (x) {\n" + |
|
225 " continue\n" + |
|
226 " }\n" + |
|
227 " if (y) {\n" + |
|
228 " break\n" + |
|
229 " }\n" + |
|
230 " if (z) {\n" + |
|
231 " break foo\n" + |
|
232 " }\n" + |
|
233 "}\n" |
|
234 }, |
|
235 |
|
236 { |
|
237 name: "Instanceof", |
|
238 input: "var a=x instanceof y;", |
|
239 output: "var a = x instanceof y;\n" |
|
240 }, |
|
241 |
|
242 { |
|
243 name: "Binary operators", |
|
244 input: "var a=5*30;var b=5>>3;", |
|
245 output: "var a = 5 * 30;\n" + |
|
246 "var b = 5 >> 3;\n" |
|
247 }, |
|
248 |
|
249 { |
|
250 name: "Delete", |
|
251 input: "delete obj.prop;", |
|
252 output: "delete obj.prop;\n" |
|
253 }, |
|
254 |
|
255 { |
|
256 name: "Try/catch/finally statement", |
|
257 input: "try{dangerous()}catch(e){handle(e)}finally{cleanup()}", |
|
258 output: "try {\n" + |
|
259 " dangerous()\n" + |
|
260 "} catch (e) {\n" + |
|
261 " handle(e)\n" + |
|
262 "} finally {\n" + |
|
263 " cleanup()\n" + |
|
264 "}\n" |
|
265 }, |
|
266 |
|
267 { |
|
268 name: "If/else statement", |
|
269 input: "if(c){then()}else{other()}", |
|
270 output: "if (c) {\n" + |
|
271 " then()\n" + |
|
272 "} else {\n" + |
|
273 " other()\n" + |
|
274 "}\n" |
|
275 }, |
|
276 |
|
277 { |
|
278 name: "If/else without curlies", |
|
279 input: "if(c) a else b", |
|
280 output: "if (c) a else b\n" |
|
281 }, |
|
282 |
|
283 { |
|
284 name: "Objects", |
|
285 input: "var o={a:1,\n" + |
|
286 " b:2};", |
|
287 output: "var o = {\n" + |
|
288 " a: 1,\n" + |
|
289 " b: 2\n" + |
|
290 "};\n", |
|
291 mappings: [ |
|
292 // a: 1, |
|
293 { |
|
294 inputLine: 1, |
|
295 outputLine: 2 |
|
296 }, |
|
297 // b: 2 |
|
298 { |
|
299 inputLine: 2, |
|
300 outputLine: 3 |
|
301 }, |
|
302 ] |
|
303 }, |
|
304 |
|
305 { |
|
306 name: "Do/while loop", |
|
307 input: "do{x}while(y)", |
|
308 output: "do {\n" + |
|
309 " x\n" + |
|
310 "} while (y)\n" |
|
311 }, |
|
312 |
|
313 { |
|
314 name: "Arrays", |
|
315 input: "var a=[1,2,3];", |
|
316 output: "var a = [\n" + |
|
317 " 1,\n" + |
|
318 " 2,\n" + |
|
319 " 3\n" + |
|
320 "];\n" |
|
321 }, |
|
322 |
|
323 { |
|
324 name: "Code that relies on ASI", |
|
325 input: "var foo = 10\n" + |
|
326 "var bar = 20\n" + |
|
327 "function g() {\n" + |
|
328 " a()\n" + |
|
329 " b()\n" + |
|
330 "}", |
|
331 output: "var foo = 10\n" + |
|
332 "var bar = 20\n" + |
|
333 "function g() {\n" + |
|
334 " a()\n" + |
|
335 " b()\n" + |
|
336 "}\n" |
|
337 }, |
|
338 |
|
339 { |
|
340 name: "Ternary operator", |
|
341 input: "bar?baz:bang;", |
|
342 output: "bar ? baz : bang;\n" |
|
343 }, |
|
344 |
|
345 { |
|
346 name: "Switch statements", |
|
347 input: "switch(x){case a:foo();break;default:bar()}", |
|
348 output: "switch (x) {\n" + |
|
349 "case a:\n" + |
|
350 " foo();\n" + |
|
351 " break;\n" + |
|
352 "default:\n" + |
|
353 " bar()\n" + |
|
354 "}\n" |
|
355 }, |
|
356 |
|
357 { |
|
358 name: "Multiple single line comments", |
|
359 input: "function f() {\n" + |
|
360 " // a\n" + |
|
361 " // b\n" + |
|
362 " // c\n" + |
|
363 "}\n", |
|
364 output: "function f() {\n" + |
|
365 " // a\n" + |
|
366 " // b\n" + |
|
367 " // c\n" + |
|
368 "}\n", |
|
369 }, |
|
370 |
|
371 { |
|
372 name: "Indented multiline comment", |
|
373 input: "function foo() {\n" + |
|
374 " /**\n" + |
|
375 " * java doc style comment\n" + |
|
376 " * more comment\n" + |
|
377 " */\n" + |
|
378 " bar();\n" + |
|
379 "}\n", |
|
380 output: "function foo() {\n" + |
|
381 " /**\n" + |
|
382 " * java doc style comment\n" + |
|
383 " * more comment\n" + |
|
384 " */\n" + |
|
385 " bar();\n" + |
|
386 "}\n", |
|
387 }, |
|
388 |
|
389 { |
|
390 name: "ASI return", |
|
391 input: "function f() {\n" + |
|
392 " return\n" + |
|
393 " {}\n" + |
|
394 "}\n", |
|
395 output: "function f() {\n" + |
|
396 " return\n" + |
|
397 " {\n" + |
|
398 " }\n" + |
|
399 "}\n", |
|
400 }, |
|
401 |
|
402 { |
|
403 name: "Non-ASI property access", |
|
404 input: "[1,2,3]\n" + |
|
405 "[0]", |
|
406 output: "[\n" + |
|
407 " 1,\n" + |
|
408 " 2,\n" + |
|
409 " 3\n" + |
|
410 "]\n" + |
|
411 "[0]\n" |
|
412 }, |
|
413 |
|
414 { |
|
415 name: "Non-ASI in", |
|
416 input: "'x'\n" + |
|
417 "in foo", |
|
418 output: "'x' in foo\n" |
|
419 }, |
|
420 |
|
421 { |
|
422 name: "Non-ASI function call", |
|
423 input: "f\n" + |
|
424 "()", |
|
425 output: "f()\n" |
|
426 }, |
|
427 |
|
428 { |
|
429 name: "Non-ASI new", |
|
430 input: "new\n" + |
|
431 "F()", |
|
432 output: "new F()\n" |
|
433 }, |
|
434 |
|
435 { |
|
436 name: "Getter and setter literals", |
|
437 input: "var obj={get foo(){return this._foo},set foo(v){this._foo=v}}", |
|
438 output: "var obj = {\n" + |
|
439 " get foo() {\n" + |
|
440 " return this._foo\n" + |
|
441 " },\n" + |
|
442 " set foo(v) {\n" + |
|
443 " this._foo = v\n" + |
|
444 " }\n" + |
|
445 "}\n" |
|
446 }, |
|
447 |
|
448 { |
|
449 name: "Escaping backslashes in strings", |
|
450 input: "'\\\\'\n", |
|
451 output: "'\\\\'\n" |
|
452 }, |
|
453 |
|
454 { |
|
455 name: "Escaping carriage return in strings", |
|
456 input: "'\\r'\n", |
|
457 output: "'\\r'\n" |
|
458 }, |
|
459 |
|
460 { |
|
461 name: "Escaping tab in strings", |
|
462 input: "'\\t'\n", |
|
463 output: "'\\t'\n" |
|
464 }, |
|
465 |
|
466 { |
|
467 name: "Escaping vertical tab in strings", |
|
468 input: "'\\v'\n", |
|
469 output: "'\\v'\n" |
|
470 }, |
|
471 |
|
472 { |
|
473 name: "Escaping form feed in strings", |
|
474 input: "'\\f'\n", |
|
475 output: "'\\f'\n" |
|
476 }, |
|
477 |
|
478 { |
|
479 name: "Escaping null character in strings", |
|
480 input: "'\\0'\n", |
|
481 output: "'\\0'\n" |
|
482 }, |
|
483 |
|
484 ]; |
|
485 |
|
486 var sourceMap = this.sourceMap || require("source-map"); |
|
487 |
|
488 function run_test() { |
|
489 testCases.forEach(function (test) { |
|
490 console.log(test.name); |
|
491 |
|
492 var actual = prettyFast(test.input, { |
|
493 indent: " ", |
|
494 url: "test.js" |
|
495 }); |
|
496 |
|
497 if (actual.code !== test.output) { |
|
498 throw new Error("Expected:\n" + test.output |
|
499 + "\nGot:\n" + actual.code); |
|
500 } |
|
501 |
|
502 if (test.mappings) { |
|
503 var smc = new sourceMap.SourceMapConsumer(actual.map.toJSON()); |
|
504 test.mappings.forEach(function (m) { |
|
505 var query = { line: m.outputLine, column: 0 }; |
|
506 var original = smc.originalPositionFor(query); |
|
507 if (original.line != m.inputLine) { |
|
508 throw new Error("Querying:\n" + JSON.stringify(query, null, 2) + "\n" |
|
509 + "Expected line:\n" + m.inputLine + "\n" |
|
510 + "Got:\n" + JSON.stringify(original, null, 2)); |
|
511 } |
|
512 }); |
|
513 } |
|
514 }); |
|
515 console.log("✓ All tests pass!"); |
|
516 } |
|
517 |
|
518 // Only run the tests if this is node and we are running this file |
|
519 // directly. (Firefox's test runner will import this test file, and then call |
|
520 // run_test itself.) |
|
521 if (typeof require == "function" && typeof module == "object" |
|
522 && require.main === module) { |
|
523 run_test(); |
|
524 } |