Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80559 views
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
});
613
614