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
var util = require('./util');
16
17
exports['test some simple stuff'] = function (assert, util) {
18
var map = new SourceMapGenerator({
19
file: 'foo.js',
20
sourceRoot: '.'
21
});
22
assert.ok(true);
23
24
var map = new SourceMapGenerator().toJSON();
25
assert.ok(!('file' in map));
26
assert.ok(!('sourceRoot' in map));
27
};
28
29
exports['test JSON serialization'] = function (assert, util) {
30
var map = new SourceMapGenerator({
31
file: 'foo.js',
32
sourceRoot: '.'
33
});
34
assert.equal(map.toString(), JSON.stringify(map));
35
};
36
37
exports['test adding mappings (case 1)'] = function (assert, util) {
38
var map = new SourceMapGenerator({
39
file: 'generated-foo.js',
40
sourceRoot: '.'
41
});
42
43
assert.doesNotThrow(function () {
44
map.addMapping({
45
generated: { line: 1, column: 1 }
46
});
47
});
48
};
49
50
exports['test adding mappings (case 2)'] = function (assert, util) {
51
var map = new SourceMapGenerator({
52
file: 'generated-foo.js',
53
sourceRoot: '.'
54
});
55
56
assert.doesNotThrow(function () {
57
map.addMapping({
58
generated: { line: 1, column: 1 },
59
source: 'bar.js',
60
original: { line: 1, column: 1 }
61
});
62
});
63
};
64
65
exports['test adding mappings (case 3)'] = function (assert, util) {
66
var map = new SourceMapGenerator({
67
file: 'generated-foo.js',
68
sourceRoot: '.'
69
});
70
71
assert.doesNotThrow(function () {
72
map.addMapping({
73
generated: { line: 1, column: 1 },
74
source: 'bar.js',
75
original: { line: 1, column: 1 },
76
name: 'someToken'
77
});
78
});
79
};
80
81
exports['test adding mappings (invalid)'] = function (assert, util) {
82
var map = new SourceMapGenerator({
83
file: 'generated-foo.js',
84
sourceRoot: '.'
85
});
86
87
// Not enough info.
88
assert.throws(function () {
89
map.addMapping({});
90
});
91
92
// Original file position, but no source.
93
assert.throws(function () {
94
map.addMapping({
95
generated: { line: 1, column: 1 },
96
original: { line: 1, column: 1 }
97
});
98
});
99
};
100
101
exports['test adding mappings with skipValidation'] = function (assert, util) {
102
var map = new SourceMapGenerator({
103
file: 'generated-foo.js',
104
sourceRoot: '.',
105
skipValidation: true
106
});
107
108
// Not enough info, caught by `util.getArgs`
109
assert.throws(function () {
110
map.addMapping({});
111
});
112
113
// Original file position, but no source. Not checked.
114
assert.doesNotThrow(function () {
115
map.addMapping({
116
generated: { line: 1, column: 1 },
117
original: { line: 1, column: 1 }
118
});
119
});
120
};
121
122
exports['test that the correct mappings are being generated'] = function (assert, util) {
123
var map = new SourceMapGenerator({
124
file: 'min.js',
125
sourceRoot: '/the/root'
126
});
127
128
map.addMapping({
129
generated: { line: 1, column: 1 },
130
original: { line: 1, column: 1 },
131
source: 'one.js'
132
});
133
map.addMapping({
134
generated: { line: 1, column: 5 },
135
original: { line: 1, column: 5 },
136
source: 'one.js'
137
});
138
map.addMapping({
139
generated: { line: 1, column: 9 },
140
original: { line: 1, column: 11 },
141
source: 'one.js'
142
});
143
map.addMapping({
144
generated: { line: 1, column: 18 },
145
original: { line: 1, column: 21 },
146
source: 'one.js',
147
name: 'bar'
148
});
149
map.addMapping({
150
generated: { line: 1, column: 21 },
151
original: { line: 2, column: 3 },
152
source: 'one.js'
153
});
154
map.addMapping({
155
generated: { line: 1, column: 28 },
156
original: { line: 2, column: 10 },
157
source: 'one.js',
158
name: 'baz'
159
});
160
map.addMapping({
161
generated: { line: 1, column: 32 },
162
original: { line: 2, column: 14 },
163
source: 'one.js',
164
name: 'bar'
165
});
166
167
map.addMapping({
168
generated: { line: 2, column: 1 },
169
original: { line: 1, column: 1 },
170
source: 'two.js'
171
});
172
map.addMapping({
173
generated: { line: 2, column: 5 },
174
original: { line: 1, column: 5 },
175
source: 'two.js'
176
});
177
map.addMapping({
178
generated: { line: 2, column: 9 },
179
original: { line: 1, column: 11 },
180
source: 'two.js'
181
});
182
map.addMapping({
183
generated: { line: 2, column: 18 },
184
original: { line: 1, column: 21 },
185
source: 'two.js',
186
name: 'n'
187
});
188
map.addMapping({
189
generated: { line: 2, column: 21 },
190
original: { line: 2, column: 3 },
191
source: 'two.js'
192
});
193
map.addMapping({
194
generated: { line: 2, column: 28 },
195
original: { line: 2, column: 10 },
196
source: 'two.js',
197
name: 'n'
198
});
199
200
map = JSON.parse(map.toString());
201
202
util.assertEqualMaps(assert, map, util.testMap);
203
};
204
205
exports['test that adding a mapping with an empty string name does not break generation'] = function (assert, util) {
206
var map = new SourceMapGenerator({
207
file: 'generated-foo.js',
208
sourceRoot: '.'
209
});
210
211
map.addMapping({
212
generated: { line: 1, column: 1 },
213
source: 'bar.js',
214
original: { line: 1, column: 1 },
215
name: ''
216
});
217
218
assert.doesNotThrow(function () {
219
JSON.parse(map.toString());
220
});
221
};
222
223
exports['test that source content can be set'] = function (assert, util) {
224
var map = new SourceMapGenerator({
225
file: 'min.js',
226
sourceRoot: '/the/root'
227
});
228
map.addMapping({
229
generated: { line: 1, column: 1 },
230
original: { line: 1, column: 1 },
231
source: 'one.js'
232
});
233
map.addMapping({
234
generated: { line: 2, column: 1 },
235
original: { line: 1, column: 1 },
236
source: 'two.js'
237
});
238
map.setSourceContent('one.js', 'one file content');
239
240
map = JSON.parse(map.toString());
241
assert.equal(map.sources[0], 'one.js');
242
assert.equal(map.sources[1], 'two.js');
243
assert.equal(map.sourcesContent[0], 'one file content');
244
assert.equal(map.sourcesContent[1], null);
245
};
246
247
exports['test .fromSourceMap'] = function (assert, util) {
248
var map = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(util.testMap));
249
util.assertEqualMaps(assert, map.toJSON(), util.testMap);
250
};
251
252
exports['test .fromSourceMap with sourcesContent'] = function (assert, util) {
253
var map = SourceMapGenerator.fromSourceMap(
254
new SourceMapConsumer(util.testMapWithSourcesContent));
255
util.assertEqualMaps(assert, map.toJSON(), util.testMapWithSourcesContent);
256
};
257
258
exports['test applySourceMap'] = function (assert, util) {
259
var node = new SourceNode(null, null, null, [
260
new SourceNode(2, 0, 'fileX', 'lineX2\n'),
261
'genA1\n',
262
new SourceNode(2, 0, 'fileY', 'lineY2\n'),
263
'genA2\n',
264
new SourceNode(1, 0, 'fileX', 'lineX1\n'),
265
'genA3\n',
266
new SourceNode(1, 0, 'fileY', 'lineY1\n')
267
]);
268
var mapStep1 = node.toStringWithSourceMap({
269
file: 'fileA'
270
}).map;
271
mapStep1.setSourceContent('fileX', 'lineX1\nlineX2\n');
272
mapStep1 = mapStep1.toJSON();
273
274
node = new SourceNode(null, null, null, [
275
'gen1\n',
276
new SourceNode(1, 0, 'fileA', 'lineA1\n'),
277
new SourceNode(2, 0, 'fileA', 'lineA2\n'),
278
new SourceNode(3, 0, 'fileA', 'lineA3\n'),
279
new SourceNode(4, 0, 'fileA', 'lineA4\n'),
280
new SourceNode(1, 0, 'fileB', 'lineB1\n'),
281
new SourceNode(2, 0, 'fileB', 'lineB2\n'),
282
'gen2\n'
283
]);
284
var mapStep2 = node.toStringWithSourceMap({
285
file: 'fileGen'
286
}).map;
287
mapStep2.setSourceContent('fileB', 'lineB1\nlineB2\n');
288
mapStep2 = mapStep2.toJSON();
289
290
node = new SourceNode(null, null, null, [
291
'gen1\n',
292
new SourceNode(2, 0, 'fileX', 'lineA1\n'),
293
new SourceNode(2, 0, 'fileA', 'lineA2\n'),
294
new SourceNode(2, 0, 'fileY', 'lineA3\n'),
295
new SourceNode(4, 0, 'fileA', 'lineA4\n'),
296
new SourceNode(1, 0, 'fileB', 'lineB1\n'),
297
new SourceNode(2, 0, 'fileB', 'lineB2\n'),
298
'gen2\n'
299
]);
300
var expectedMap = node.toStringWithSourceMap({
301
file: 'fileGen'
302
}).map;
303
expectedMap.setSourceContent('fileX', 'lineX1\nlineX2\n');
304
expectedMap.setSourceContent('fileB', 'lineB1\nlineB2\n');
305
expectedMap = expectedMap.toJSON();
306
307
// apply source map "mapStep1" to "mapStep2"
308
var generator = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(mapStep2));
309
generator.applySourceMap(new SourceMapConsumer(mapStep1));
310
var actualMap = generator.toJSON();
311
312
util.assertEqualMaps(assert, actualMap, expectedMap);
313
};
314
315
exports['test applySourceMap throws when file is missing'] = function (assert, util) {
316
var map = new SourceMapGenerator({
317
file: 'test.js'
318
});
319
var map2 = new SourceMapGenerator();
320
assert.throws(function() {
321
map.applySourceMap(new SourceMapConsumer(map2.toJSON()));
322
});
323
};
324
325
exports['test the two additional parameters of applySourceMap'] = function (assert, util) {
326
// Assume the following directory structure:
327
//
328
// http://foo.org/
329
// bar.coffee
330
// app/
331
// coffee/
332
// foo.coffee
333
// temp/
334
// bundle.js
335
// temp_maps/
336
// bundle.js.map
337
// public/
338
// bundle.min.js
339
// bundle.min.js.map
340
//
341
// http://www.example.com/
342
// baz.coffee
343
344
var bundleMap = new SourceMapGenerator({
345
file: 'bundle.js'
346
});
347
bundleMap.addMapping({
348
generated: { line: 3, column: 3 },
349
original: { line: 2, column: 2 },
350
source: '../../coffee/foo.coffee'
351
});
352
bundleMap.setSourceContent('../../coffee/foo.coffee', 'foo coffee');
353
bundleMap.addMapping({
354
generated: { line: 13, column: 13 },
355
original: { line: 12, column: 12 },
356
source: '/bar.coffee'
357
});
358
bundleMap.setSourceContent('/bar.coffee', 'bar coffee');
359
bundleMap.addMapping({
360
generated: { line: 23, column: 23 },
361
original: { line: 22, column: 22 },
362
source: 'http://www.example.com/baz.coffee'
363
});
364
bundleMap.setSourceContent(
365
'http://www.example.com/baz.coffee',
366
'baz coffee'
367
);
368
bundleMap = new SourceMapConsumer(bundleMap.toJSON());
369
370
var minifiedMap = new SourceMapGenerator({
371
file: 'bundle.min.js',
372
sourceRoot: '..'
373
});
374
minifiedMap.addMapping({
375
generated: { line: 1, column: 1 },
376
original: { line: 3, column: 3 },
377
source: 'temp/bundle.js'
378
});
379
minifiedMap.addMapping({
380
generated: { line: 11, column: 11 },
381
original: { line: 13, column: 13 },
382
source: 'temp/bundle.js'
383
});
384
minifiedMap.addMapping({
385
generated: { line: 21, column: 21 },
386
original: { line: 23, column: 23 },
387
source: 'temp/bundle.js'
388
});
389
minifiedMap = new SourceMapConsumer(minifiedMap.toJSON());
390
391
var expectedMap = function (sources) {
392
var map = new SourceMapGenerator({
393
file: 'bundle.min.js',
394
sourceRoot: '..'
395
});
396
map.addMapping({
397
generated: { line: 1, column: 1 },
398
original: { line: 2, column: 2 },
399
source: sources[0]
400
});
401
map.setSourceContent(sources[0], 'foo coffee');
402
map.addMapping({
403
generated: { line: 11, column: 11 },
404
original: { line: 12, column: 12 },
405
source: sources[1]
406
});
407
map.setSourceContent(sources[1], 'bar coffee');
408
map.addMapping({
409
generated: { line: 21, column: 21 },
410
original: { line: 22, column: 22 },
411
source: sources[2]
412
});
413
map.setSourceContent(sources[2], 'baz coffee');
414
return map.toJSON();
415
}
416
417
var actualMap = function (aSourceMapPath) {
418
var map = SourceMapGenerator.fromSourceMap(minifiedMap);
419
// Note that relying on `bundleMap.file` (which is simply 'bundle.js')
420
// instead of supplying the second parameter wouldn't work here.
421
map.applySourceMap(bundleMap, '../temp/bundle.js', aSourceMapPath);
422
return map.toJSON();
423
}
424
425
util.assertEqualMaps(assert, actualMap('../temp/temp_maps'), expectedMap([
426
'coffee/foo.coffee',
427
'/bar.coffee',
428
'http://www.example.com/baz.coffee'
429
]));
430
431
util.assertEqualMaps(assert, actualMap('/app/temp/temp_maps'), expectedMap([
432
'/app/coffee/foo.coffee',
433
'/bar.coffee',
434
'http://www.example.com/baz.coffee'
435
]));
436
437
util.assertEqualMaps(assert, actualMap('http://foo.org/app/temp/temp_maps'), expectedMap([
438
'http://foo.org/app/coffee/foo.coffee',
439
'http://foo.org/bar.coffee',
440
'http://www.example.com/baz.coffee'
441
]));
442
443
// If the third parameter is omitted or set to the current working
444
// directory we get incorrect source paths:
445
446
util.assertEqualMaps(assert, actualMap(), expectedMap([
447
'../coffee/foo.coffee',
448
'/bar.coffee',
449
'http://www.example.com/baz.coffee'
450
]));
451
452
util.assertEqualMaps(assert, actualMap(''), expectedMap([
453
'../coffee/foo.coffee',
454
'/bar.coffee',
455
'http://www.example.com/baz.coffee'
456
]));
457
458
util.assertEqualMaps(assert, actualMap('.'), expectedMap([
459
'../coffee/foo.coffee',
460
'/bar.coffee',
461
'http://www.example.com/baz.coffee'
462
]));
463
464
util.assertEqualMaps(assert, actualMap('./'), expectedMap([
465
'../coffee/foo.coffee',
466
'/bar.coffee',
467
'http://www.example.com/baz.coffee'
468
]));
469
};
470
471
exports['test applySourceMap name handling'] = function (assert, util) {
472
// Imagine some CoffeeScript code being compiled into JavaScript and then
473
// minified.
474
475
var assertName = function(coffeeName, jsName, expectedName) {
476
var minifiedMap = new SourceMapGenerator({
477
file: 'test.js.min'
478
});
479
minifiedMap.addMapping({
480
generated: { line: 1, column: 4 },
481
original: { line: 1, column: 4 },
482
source: 'test.js',
483
name: jsName
484
});
485
486
var coffeeMap = new SourceMapGenerator({
487
file: 'test.js'
488
});
489
coffeeMap.addMapping({
490
generated: { line: 1, column: 4 },
491
original: { line: 1, column: 0 },
492
source: 'test.coffee',
493
name: coffeeName
494
});
495
496
minifiedMap.applySourceMap(new SourceMapConsumer(coffeeMap.toJSON()));
497
498
new SourceMapConsumer(minifiedMap.toJSON()).eachMapping(function(mapping) {
499
assert.equal(mapping.name, expectedName);
500
});
501
};
502
503
// `foo = 1` -> `var foo = 1;` -> `var a=1`
504
// CoffeeScript doesn’t rename variables, so there’s no need for it to
505
// provide names in its source maps. Minifiers do rename variables and
506
// therefore do provide names in their source maps. So that name should be
507
// retained if the original map lacks names.
508
assertName(null, 'foo', 'foo');
509
510
// `foo = 1` -> `var coffee$foo = 1;` -> `var a=1`
511
// Imagine that CoffeeScript prefixed all variables with `coffee$`. Even
512
// though the minifier then also provides a name, the original name is
513
// what corresponds to the source.
514
assertName('foo', 'coffee$foo', 'foo');
515
516
// `foo = 1` -> `var coffee$foo = 1;` -> `var coffee$foo=1`
517
// Minifiers can turn off variable mangling. Then there’s no need to
518
// provide names in the source map, but the names from the original map are
519
// still needed.
520
assertName('foo', null, 'foo');
521
522
// `foo = 1` -> `var foo = 1;` -> `var foo=1`
523
// No renaming at all.
524
assertName(null, null, null);
525
};
526
527
exports['test sorting with duplicate generated mappings'] = function (assert, util) {
528
var map = new SourceMapGenerator({
529
file: 'test.js'
530
});
531
map.addMapping({
532
generated: { line: 3, column: 0 },
533
original: { line: 2, column: 0 },
534
source: 'a.js'
535
});
536
map.addMapping({
537
generated: { line: 2, column: 0 }
538
});
539
map.addMapping({
540
generated: { line: 2, column: 0 }
541
});
542
map.addMapping({
543
generated: { line: 1, column: 0 },
544
original: { line: 1, column: 0 },
545
source: 'a.js'
546
});
547
548
util.assertEqualMaps(assert, map.toJSON(), {
549
version: 3,
550
file: 'test.js',
551
sources: ['a.js'],
552
names: [],
553
mappings: 'AAAA;A;AACA'
554
});
555
};
556
557
exports['test ignore duplicate mappings.'] = function (assert, util) {
558
var init = { file: 'min.js', sourceRoot: '/the/root' };
559
var map1, map2;
560
561
// null original source location
562
var nullMapping1 = {
563
generated: { line: 1, column: 0 }
564
};
565
var nullMapping2 = {
566
generated: { line: 2, column: 2 }
567
};
568
569
map1 = new SourceMapGenerator(init);
570
map2 = new SourceMapGenerator(init);
571
572
map1.addMapping(nullMapping1);
573
map1.addMapping(nullMapping1);
574
575
map2.addMapping(nullMapping1);
576
577
util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON());
578
579
map1.addMapping(nullMapping2);
580
map1.addMapping(nullMapping1);
581
582
map2.addMapping(nullMapping2);
583
584
util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON());
585
586
// original source location
587
var srcMapping1 = {
588
generated: { line: 1, column: 0 },
589
original: { line: 11, column: 0 },
590
source: 'srcMapping1.js'
591
};
592
var srcMapping2 = {
593
generated: { line: 2, column: 2 },
594
original: { line: 11, column: 0 },
595
source: 'srcMapping2.js'
596
};
597
598
map1 = new SourceMapGenerator(init);
599
map2 = new SourceMapGenerator(init);
600
601
map1.addMapping(srcMapping1);
602
map1.addMapping(srcMapping1);
603
604
map2.addMapping(srcMapping1);
605
606
util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON());
607
608
map1.addMapping(srcMapping2);
609
map1.addMapping(srcMapping1);
610
611
map2.addMapping(srcMapping2);
612
613
util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON());
614
615
// full original source and name information
616
var fullMapping1 = {
617
generated: { line: 1, column: 0 },
618
original: { line: 11, column: 0 },
619
source: 'fullMapping1.js',
620
name: 'fullMapping1'
621
};
622
var fullMapping2 = {
623
generated: { line: 2, column: 2 },
624
original: { line: 11, column: 0 },
625
source: 'fullMapping2.js',
626
name: 'fullMapping2'
627
};
628
629
map1 = new SourceMapGenerator(init);
630
map2 = new SourceMapGenerator(init);
631
632
map1.addMapping(fullMapping1);
633
map1.addMapping(fullMapping1);
634
635
map2.addMapping(fullMapping1);
636
637
util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON());
638
639
map1.addMapping(fullMapping2);
640
map1.addMapping(fullMapping1);
641
642
map2.addMapping(fullMapping2);
643
644
util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON());
645
};
646
647
exports['test github issue #72, check for duplicate names or sources'] = function (assert, util) {
648
var map = new SourceMapGenerator({
649
file: 'test.js'
650
});
651
map.addMapping({
652
generated: { line: 1, column: 1 },
653
original: { line: 2, column: 2 },
654
source: 'a.js',
655
name: 'foo'
656
});
657
map.addMapping({
658
generated: { line: 3, column: 3 },
659
original: { line: 4, column: 4 },
660
source: 'a.js',
661
name: 'foo'
662
});
663
util.assertEqualMaps(assert, map.toJSON(), {
664
version: 3,
665
file: 'test.js',
666
sources: ['a.js'],
667
names: ['foo'],
668
mappings: 'CACEA;;GAEEA'
669
});
670
};
671
672
exports['test setting sourcesContent to null when already null'] = function (assert, util) {
673
var smg = new SourceMapGenerator({ file: "foo.js" });
674
assert.doesNotThrow(function() {
675
smg.setSourceContent("bar.js", null);
676
});
677
};
678
679
});
680
681