]> git.r.bdr.sh - rbdr/dotfiles/blob
139af4e44eba6631eac30a3f11e90e5213d6dc15
[rbdr/dotfiles] /
1 /* -*- Mode: js; js-indent-level: 2; -*- */
2 /*
3 * Copyright 2011 Mozilla Foundation and contributors
4 * Licensed under the New BSD license. See LICENSE or:
5 * http://opensource.org/licenses/BSD-3-Clause
6 */
7 if (typeof define !== 'function') {
8 var define = require('amdefine')(module, require);
9 }
10 define(function (require, exports, module) {
11
12 var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator;
13 var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer;
14 var SourceNode = require('../../lib/source-map/source-node').SourceNode;
15
16 function forEachNewline(fn) {
17 return function (assert, util) {
18 ['\n', '\r\n'].forEach(fn.bind(null, assert, util));
19 }
20 }
21
22 exports['test .add()'] = function (assert, util) {
23 var node = new SourceNode(null, null, null);
24
25 // Adding a string works.
26 node.add('function noop() {}');
27
28 // Adding another source node works.
29 node.add(new SourceNode(null, null, null));
30
31 // Adding an array works.
32 node.add(['function foo() {',
33 new SourceNode(null, null, null,
34 'return 10;'),
35 '}']);
36
37 // Adding other stuff doesn't.
38 assert.throws(function () {
39 node.add({});
40 });
41 assert.throws(function () {
42 node.add(function () {});
43 });
44 };
45
46 exports['test .prepend()'] = function (assert, util) {
47 var node = new SourceNode(null, null, null);
48
49 // Prepending a string works.
50 node.prepend('function noop() {}');
51 assert.equal(node.children[0], 'function noop() {}');
52 assert.equal(node.children.length, 1);
53
54 // Prepending another source node works.
55 node.prepend(new SourceNode(null, null, null));
56 assert.equal(node.children[0], '');
57 assert.equal(node.children[1], 'function noop() {}');
58 assert.equal(node.children.length, 2);
59
60 // Prepending an array works.
61 node.prepend(['function foo() {',
62 new SourceNode(null, null, null,
63 'return 10;'),
64 '}']);
65 assert.equal(node.children[0], 'function foo() {');
66 assert.equal(node.children[1], 'return 10;');
67 assert.equal(node.children[2], '}');
68 assert.equal(node.children[3], '');
69 assert.equal(node.children[4], 'function noop() {}');
70 assert.equal(node.children.length, 5);
71
72 // Prepending other stuff doesn't.
73 assert.throws(function () {
74 node.prepend({});
75 });
76 assert.throws(function () {
77 node.prepend(function () {});
78 });
79 };
80
81 exports['test .toString()'] = function (assert, util) {
82 assert.equal((new SourceNode(null, null, null,
83 ['function foo() {',
84 new SourceNode(null, null, null, 'return 10;'),
85 '}'])).toString(),
86 'function foo() {return 10;}');
87 };
88
89 exports['test .join()'] = function (assert, util) {
90 assert.equal((new SourceNode(null, null, null,
91 ['a', 'b', 'c', 'd'])).join(', ').toString(),
92 'a, b, c, d');
93 };
94
95 exports['test .walk()'] = function (assert, util) {
96 var node = new SourceNode(null, null, null,
97 ['(function () {\n',
98 ' ', new SourceNode(1, 0, 'a.js', ['someCall()']), ';\n',
99 ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';\n',
100 '}());']);
101 var expected = [
102 { str: '(function () {\n', source: null, line: null, column: null },
103 { str: ' ', source: null, line: null, column: null },
104 { str: 'someCall()', source: 'a.js', line: 1, column: 0 },
105 { str: ';\n', source: null, line: null, column: null },
106 { str: ' ', source: null, line: null, column: null },
107 { str: 'if (foo) bar()', source: 'b.js', line: 2, column: 0 },
108 { str: ';\n', source: null, line: null, column: null },
109 { str: '}());', source: null, line: null, column: null },
110 ];
111 var i = 0;
112 node.walk(function (chunk, loc) {
113 assert.equal(expected[i].str, chunk);
114 assert.equal(expected[i].source, loc.source);
115 assert.equal(expected[i].line, loc.line);
116 assert.equal(expected[i].column, loc.column);
117 i++;
118 });
119 };
120
121 exports['test .replaceRight'] = function (assert, util) {
122 var node;
123
124 // Not nested
125 node = new SourceNode(null, null, null, 'hello world');
126 node.replaceRight(/world/, 'universe');
127 assert.equal(node.toString(), 'hello universe');
128
129 // Nested
130 node = new SourceNode(null, null, null,
131 [new SourceNode(null, null, null, 'hey sexy mama, '),
132 new SourceNode(null, null, null, 'want to kill all humans?')]);
133 node.replaceRight(/kill all humans/, 'watch Futurama');
134 assert.equal(node.toString(), 'hey sexy mama, want to watch Futurama?');
135 };
136
137 exports['test .toStringWithSourceMap()'] = forEachNewline(function (assert, util, nl) {
138 var node = new SourceNode(null, null, null,
139 ['(function () {' + nl,
140 ' ',
141 new SourceNode(1, 0, 'a.js', 'someCall', 'originalCall'),
142 new SourceNode(1, 8, 'a.js', '()'),
143 ';' + nl,
144 ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';' + nl,
145 '}());']);
146 var result = node.toStringWithSourceMap({
147 file: 'foo.js'
148 });
149
150 assert.equal(result.code, [
151 '(function () {',
152 ' someCall();',
153 ' if (foo) bar();',
154 '}());'
155 ].join(nl));
156
157 var map = result.map;
158 var mapWithoutOptions = node.toStringWithSourceMap().map;
159
160 assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator');
161 assert.ok(mapWithoutOptions instanceof SourceMapGenerator, 'mapWithoutOptions instanceof SourceMapGenerator');
162 assert.ok(!('file' in mapWithoutOptions));
163 mapWithoutOptions._file = 'foo.js';
164 util.assertEqualMaps(assert, map.toJSON(), mapWithoutOptions.toJSON());
165
166 map = new SourceMapConsumer(map.toString());
167
168 var actual;
169
170 actual = map.originalPositionFor({
171 line: 1,
172 column: 4
173 });
174 assert.equal(actual.source, null);
175 assert.equal(actual.line, null);
176 assert.equal(actual.column, null);
177
178 actual = map.originalPositionFor({
179 line: 2,
180 column: 2
181 });
182 assert.equal(actual.source, 'a.js');
183 assert.equal(actual.line, 1);
184 assert.equal(actual.column, 0);
185 assert.equal(actual.name, 'originalCall');
186
187 actual = map.originalPositionFor({
188 line: 3,
189 column: 2
190 });
191 assert.equal(actual.source, 'b.js');
192 assert.equal(actual.line, 2);
193 assert.equal(actual.column, 0);
194
195 actual = map.originalPositionFor({
196 line: 3,
197 column: 16
198 });
199 assert.equal(actual.source, null);
200 assert.equal(actual.line, null);
201 assert.equal(actual.column, null);
202
203 actual = map.originalPositionFor({
204 line: 4,
205 column: 2
206 });
207 assert.equal(actual.source, null);
208 assert.equal(actual.line, null);
209 assert.equal(actual.column, null);
210 });
211
212 exports['test .fromStringWithSourceMap()'] = forEachNewline(function (assert, util, nl) {
213 var testCode = util.testGeneratedCode.replace(/\n/g, nl);
214 var node = SourceNode.fromStringWithSourceMap(
215 testCode,
216 new SourceMapConsumer(util.testMap));
217
218 var result = node.toStringWithSourceMap({
219 file: 'min.js'
220 });
221 var map = result.map;
222 var code = result.code;
223
224 assert.equal(code, testCode);
225 assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator');
226 map = map.toJSON();
227 assert.equal(map.version, util.testMap.version);
228 assert.equal(map.file, util.testMap.file);
229 assert.equal(map.mappings, util.testMap.mappings);
230 });
231
232 exports['test .fromStringWithSourceMap() empty map'] = forEachNewline(function (assert, util, nl) {
233 var node = SourceNode.fromStringWithSourceMap(
234 util.testGeneratedCode.replace(/\n/g, nl),
235 new SourceMapConsumer(util.emptyMap));
236 var result = node.toStringWithSourceMap({
237 file: 'min.js'
238 });
239 var map = result.map;
240 var code = result.code;
241
242 assert.equal(code, util.testGeneratedCode.replace(/\n/g, nl));
243 assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator');
244 map = map.toJSON();
245 assert.equal(map.version, util.emptyMap.version);
246 assert.equal(map.file, util.emptyMap.file);
247 assert.equal(map.mappings.length, util.emptyMap.mappings.length);
248 assert.equal(map.mappings, util.emptyMap.mappings);
249 });
250
251 exports['test .fromStringWithSourceMap() complex version'] = forEachNewline(function (assert, util, nl) {
252 var input = new SourceNode(null, null, null, [
253 "(function() {" + nl,
254 " var Test = {};" + nl,
255 " ", new SourceNode(1, 0, "a.js", "Test.A = { value: 1234 };" + nl),
256 " ", new SourceNode(2, 0, "a.js", "Test.A.x = 'xyz';"), nl,
257 "}());" + nl,
258 "/* Generated Source */"]);
259 input = input.toStringWithSourceMap({
260 file: 'foo.js'
261 });
262
263 var node = SourceNode.fromStringWithSourceMap(
264 input.code,
265 new SourceMapConsumer(input.map.toString()));
266
267 var result = node.toStringWithSourceMap({
268 file: 'foo.js'
269 });
270 var map = result.map;
271 var code = result.code;
272
273 assert.equal(code, input.code);
274 assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator');
275 map = map.toJSON();
276 var inputMap = input.map.toJSON();
277 util.assertEqualMaps(assert, map, inputMap);
278 });
279
280 exports['test .fromStringWithSourceMap() third argument'] = function (assert, util) {
281 // Assume the following directory structure:
282 //
283 // http://foo.org/
284 // bar.coffee
285 // app/
286 // coffee/
287 // foo.coffee
288 // coffeeBundle.js # Made from {foo,bar,baz}.coffee
289 // maps/
290 // coffeeBundle.js.map
291 // js/
292 // foo.js
293 // public/
294 // app.js # Made from {foo,coffeeBundle}.js
295 // app.js.map
296 //
297 // http://www.example.com/
298 // baz.coffee
299
300 var coffeeBundle = new SourceNode(1, 0, 'foo.coffee', 'foo(coffee);\n');
301 coffeeBundle.setSourceContent('foo.coffee', 'foo coffee');
302 coffeeBundle.add(new SourceNode(2, 0, '/bar.coffee', 'bar(coffee);\n'));
303 coffeeBundle.add(new SourceNode(3, 0, 'http://www.example.com/baz.coffee', 'baz(coffee);'));
304 coffeeBundle = coffeeBundle.toStringWithSourceMap({
305 file: 'foo.js',
306 sourceRoot: '..'
307 });
308
309 var foo = new SourceNode(1, 0, 'foo.js', 'foo(js);');
310
311 var test = function(relativePath, expectedSources) {
312 var app = new SourceNode();
313 app.add(SourceNode.fromStringWithSourceMap(
314 coffeeBundle.code,
315 new SourceMapConsumer(coffeeBundle.map.toString()),
316 relativePath));
317 app.add(foo);
318 var i = 0;
319 app.walk(function (chunk, loc) {
320 assert.equal(loc.source, expectedSources[i]);
321 i++;
322 });
323 app.walkSourceContents(function (sourceFile, sourceContent) {
324 assert.equal(sourceFile, expectedSources[0]);
325 assert.equal(sourceContent, 'foo coffee');
326 })
327 };
328
329 test('../coffee/maps', [
330 '../coffee/foo.coffee',
331 '/bar.coffee',
332 'http://www.example.com/baz.coffee',
333 'foo.js'
334 ]);
335
336 // If the third parameter is omitted or set to the current working
337 // directory we get incorrect source paths:
338
339 test(undefined, [
340 '../foo.coffee',
341 '/bar.coffee',
342 'http://www.example.com/baz.coffee',
343 'foo.js'
344 ]);
345
346 test('', [
347 '../foo.coffee',
348 '/bar.coffee',
349 'http://www.example.com/baz.coffee',
350 'foo.js'
351 ]);
352
353 test('.', [
354 '../foo.coffee',
355 '/bar.coffee',
356 'http://www.example.com/baz.coffee',
357 'foo.js'
358 ]);
359
360 test('./', [
361 '../foo.coffee',
362 '/bar.coffee',
363 'http://www.example.com/baz.coffee',
364 'foo.js'
365 ]);
366 };
367
368 exports['test .toStringWithSourceMap() merging duplicate mappings'] = forEachNewline(function (assert, util, nl) {
369 var input = new SourceNode(null, null, null, [
370 new SourceNode(1, 0, "a.js", "(function"),
371 new SourceNode(1, 0, "a.js", "() {" + nl),
372 " ",
373 new SourceNode(1, 0, "a.js", "var Test = "),
374 new SourceNode(1, 0, "b.js", "{};" + nl),
375 new SourceNode(2, 0, "b.js", "Test"),
376 new SourceNode(2, 0, "b.js", ".A", "A"),
377 new SourceNode(2, 20, "b.js", " = { value: ", "A"),
378 "1234",
379 new SourceNode(2, 40, "b.js", " };" + nl, "A"),
380 "}());" + nl,
381 "/* Generated Source */"
382 ]);
383 input = input.toStringWithSourceMap({
384 file: 'foo.js'
385 });
386
387 assert.equal(input.code, [
388 "(function() {",
389 " var Test = {};",
390 "Test.A = { value: 1234 };",
391 "}());",
392 "/* Generated Source */"
393 ].join(nl))
394
395 var correctMap = new SourceMapGenerator({
396 file: 'foo.js'
397 });
398 correctMap.addMapping({
399 generated: { line: 1, column: 0 },
400 source: 'a.js',
401 original: { line: 1, column: 0 }
402 });
403 // Here is no need for a empty mapping,
404 // because mappings ends at eol
405 correctMap.addMapping({
406 generated: { line: 2, column: 2 },
407 source: 'a.js',
408 original: { line: 1, column: 0 }
409 });
410 correctMap.addMapping({
411 generated: { line: 2, column: 13 },
412 source: 'b.js',
413 original: { line: 1, column: 0 }
414 });
415 correctMap.addMapping({
416 generated: { line: 3, column: 0 },
417 source: 'b.js',
418 original: { line: 2, column: 0 }
419 });
420 correctMap.addMapping({
421 generated: { line: 3, column: 4 },
422 source: 'b.js',
423 name: 'A',
424 original: { line: 2, column: 0 }
425 });
426 correctMap.addMapping({
427 generated: { line: 3, column: 6 },
428 source: 'b.js',
429 name: 'A',
430 original: { line: 2, column: 20 }
431 });
432 // This empty mapping is required,
433 // because there is a hole in the middle of the line
434 correctMap.addMapping({
435 generated: { line: 3, column: 18 }
436 });
437 correctMap.addMapping({
438 generated: { line: 3, column: 22 },
439 source: 'b.js',
440 name: 'A',
441 original: { line: 2, column: 40 }
442 });
443 // Here is no need for a empty mapping,
444 // because mappings ends at eol
445
446 var inputMap = input.map.toJSON();
447 correctMap = correctMap.toJSON();
448 util.assertEqualMaps(assert, inputMap, correctMap);
449 });
450
451 exports['test .toStringWithSourceMap() multi-line SourceNodes'] = forEachNewline(function (assert, util, nl) {
452 var input = new SourceNode(null, null, null, [
453 new SourceNode(1, 0, "a.js", "(function() {" + nl + "var nextLine = 1;" + nl + "anotherLine();" + nl),
454 new SourceNode(2, 2, "b.js", "Test.call(this, 123);" + nl),
455 new SourceNode(2, 2, "b.js", "this['stuff'] = 'v';" + nl),
456 new SourceNode(2, 2, "b.js", "anotherLine();" + nl),
457 "/*" + nl + "Generated" + nl + "Source" + nl + "*/" + nl,
458 new SourceNode(3, 4, "c.js", "anotherLine();" + nl),
459 "/*" + nl + "Generated" + nl + "Source" + nl + "*/"
460 ]);
461 input = input.toStringWithSourceMap({
462 file: 'foo.js'
463 });
464
465 assert.equal(input.code, [
466 "(function() {",
467 "var nextLine = 1;",
468 "anotherLine();",
469 "Test.call(this, 123);",
470 "this['stuff'] = 'v';",
471 "anotherLine();",
472 "/*",
473 "Generated",
474 "Source",
475 "*/",
476 "anotherLine();",
477 "/*",
478 "Generated",
479 "Source",
480 "*/"
481 ].join(nl));
482
483 var correctMap = new SourceMapGenerator({
484 file: 'foo.js'
485 });
486 correctMap.addMapping({
487 generated: { line: 1, column: 0 },
488 source: 'a.js',
489 original: { line: 1, column: 0 }
490 });
491 correctMap.addMapping({
492 generated: { line: 2, column: 0 },
493 source: 'a.js',
494 original: { line: 1, column: 0 }
495 });
496 correctMap.addMapping({
497 generated: { line: 3, column: 0 },
498 source: 'a.js',
499 original: { line: 1, column: 0 }
500 });
501 correctMap.addMapping({
502 generated: { line: 4, column: 0 },
503 source: 'b.js',
504 original: { line: 2, column: 2 }
505 });
506 correctMap.addMapping({
507 generated: { line: 5, column: 0 },
508 source: 'b.js',
509 original: { line: 2, column: 2 }
510 });
511 correctMap.addMapping({
512 generated: { line: 6, column: 0 },
513 source: 'b.js',
514 original: { line: 2, column: 2 }
515 });
516 correctMap.addMapping({
517 generated: { line: 11, column: 0 },
518 source: 'c.js',
519 original: { line: 3, column: 4 }
520 });
521
522 var inputMap = input.map.toJSON();
523 correctMap = correctMap.toJSON();
524 util.assertEqualMaps(assert, inputMap, correctMap);
525 });
526
527 exports['test .toStringWithSourceMap() with empty string'] = function (assert, util) {
528 var node = new SourceNode(1, 0, 'empty.js', '');
529 var result = node.toStringWithSourceMap();
530 assert.equal(result.code, '');
531 };
532
533 exports['test .toStringWithSourceMap() with consecutive newlines'] = forEachNewline(function (assert, util, nl) {
534 var input = new SourceNode(null, null, null, [
535 "/***/" + nl + nl,
536 new SourceNode(1, 0, "a.js", "'use strict';" + nl),
537 new SourceNode(2, 0, "a.js", "a();"),
538 ]);
539 input = input.toStringWithSourceMap({
540 file: 'foo.js'
541 });
542
543 assert.equal(input.code, [
544 "/***/",
545 "",
546 "'use strict';",
547 "a();",
548 ].join(nl));
549
550 var correctMap = new SourceMapGenerator({
551 file: 'foo.js'
552 });
553 correctMap.addMapping({
554 generated: { line: 3, column: 0 },
555 source: 'a.js',
556 original: { line: 1, column: 0 }
557 });
558 correctMap.addMapping({
559 generated: { line: 4, column: 0 },
560 source: 'a.js',
561 original: { line: 2, column: 0 }
562 });
563
564 var inputMap = input.map.toJSON();
565 correctMap = correctMap.toJSON();
566 util.assertEqualMaps(assert, inputMap, correctMap);
567 });
568
569 exports['test setSourceContent with toStringWithSourceMap'] = function (assert, util) {
570 var aNode = new SourceNode(1, 1, 'a.js', 'a');
571 aNode.setSourceContent('a.js', 'someContent');
572 var node = new SourceNode(null, null, null,
573 ['(function () {\n',
574 ' ', aNode,
575 ' ', new SourceNode(1, 1, 'b.js', 'b'),
576 '}());']);
577 node.setSourceContent('b.js', 'otherContent');
578 var map = node.toStringWithSourceMap({
579 file: 'foo.js'
580 }).map;
581
582 assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator');
583 map = new SourceMapConsumer(map.toString());
584
585 assert.equal(map.sources.length, 2);
586 assert.equal(map.sources[0], 'a.js');
587 assert.equal(map.sources[1], 'b.js');
588 assert.equal(map.sourcesContent.length, 2);
589 assert.equal(map.sourcesContent[0], 'someContent');
590 assert.equal(map.sourcesContent[1], 'otherContent');
591 };
592
593 exports['test walkSourceContents'] = function (assert, util) {
594 var aNode = new SourceNode(1, 1, 'a.js', 'a');
595 aNode.setSourceContent('a.js', 'someContent');
596 var node = new SourceNode(null, null, null,
597 ['(function () {\n',
598 ' ', aNode,
599 ' ', new SourceNode(1, 1, 'b.js', 'b'),
600 '}());']);
601 node.setSourceContent('b.js', 'otherContent');
602 var results = [];
603 node.walkSourceContents(function (sourceFile, sourceContent) {
604 results.push([sourceFile, sourceContent]);
605 });
606 assert.equal(results.length, 2);
607 assert.equal(results[0][0], 'a.js');
608 assert.equal(results[0][1], 'someContent');
609 assert.equal(results[1][0], 'b.js');
610 assert.equal(results[1][1], 'otherContent');
611 };
612 });