UNPKG

34.9 kBJavaScriptView Raw
1// Copyright 2014 Simon Lydell
2// X11 (“MIT”) Licensed. (See LICENSE.)
3
4var test = require("tape")
5var asyncify = require("simple-asyncify")
6var common = require("./common")
7var u = common.u
8var read = common.read
9var Throws = common.Throws
10var identity = common.identity
11
12var sourceMapResolve = require("../")
13
14// Polyfills.
15require("setimmediate")
16if (typeof window !== "undefined" && !window.atob) {
17 window.atob = require("Base64").atob
18}
19
20"use strict"
21
22var map = {
23 simple: {
24 mappings: "AAAA",
25 sources: ["foo.js"],
26 names: []
27 },
28 sourceRoot: {
29 mappings: "AAAA",
30 sourceRoot: "/static/js/app/",
31 sources: ["foo.js", "lib/bar.js", "../vendor/dom.js", "/version.js", "//foo.org/baz.js"],
32 names: []
33 },
34 sourceRootNoSlash: {
35 mappings: "AAAA",
36 sourceRoot: "/static/js/app",
37 sources: ["foo.js", "lib/bar.js", "../vendor/dom.js", "/version.js", "//foo.org/baz.js"],
38 names: []
39 },
40 sourceRootEmpty: {
41 mappings: "AAAA",
42 sourceRoot: "",
43 sources: ["foo.js", "lib/bar.js", "../vendor/dom.js", "/version.js", "//foo.org/baz.js"],
44 names: []
45 },
46 sourcesContent: {
47 mappings: "AAAA",
48 sourceRoot: "/static/js/app/",
49 sources: ["foo.js", "lib/bar.js", "../vendor/dom.js", "/version.js", "//foo.org/baz.js"],
50 sourcesContent: ["foo.js", "lib/bar.js", "../vendor/dom.js", "/version.js", "//foo.org/baz.js"],
51 names: []
52 },
53 mixed: {
54 mappings: "AAAA",
55 sources: ["foo.js", "lib/bar.js", "../vendor/dom.js", "/version.js", "//foo.org/baz.js"],
56 sourcesContent: ["foo.js", null , null , "/version.js", "//foo.org/baz.js"],
57 names: []
58 }
59}
60map.simpleString = JSON.stringify(map.simple)
61map.XSSIsafe = ")]}'" + map.simpleString
62
63var code = {
64 fileRelative: u("foo.js.map"),
65 domainRelative: u("/foo.js.map"),
66 schemeRelative: u("//foo.org/foo.js.map"),
67 absolute: u("https://foo.org/foo.js.map"),
68 dataUri: u("data:application/json," +
69 "%7B%22mappings%22%3A%22AAAA%22%2C%22sources%22%3A%5B%22" +
70 "foo.js%22%5D%2C%22names%22%3A%5B%5D%7D"),
71 base64: u("data:application/json;base64," +
72 "eyJtYXBwaW5ncyI6IkFBQUEiLCJzb3VyY2VzIjpbImZvby5qcyJdLCJuYW1lcyI6W119"),
73 dataUriText: u("data:text/json," +
74 "%7B%22mappings%22%3A%22AAAA%22%2C%22sources%22%3A%5B%22" +
75 "foo.js%22%5D%2C%22names%22%3A%5B%5D%7D"),
76 dataUriParameter: u("data:application/json;charset=UTF-8;foo=bar," +
77 "%7B%22mappings%22%3A%22AAAA%22%2C%22sources%22%3A%5B%22" +
78 "foo.js%22%5D%2C%22names%22%3A%5B%5D%7D"),
79 dataUriNoMime: u("data:,foo"),
80 dataUriInvalidMime: u("data:text/html,foo"),
81 dataUriInvalidJSON: u("data:application/json,foo"),
82 dataUriXSSIsafe: u("data:application/json," + ")%5D%7D%27" +
83 "%7B%22mappings%22%3A%22AAAA%22%2C%22sources%22%3A%5B%22" +
84 "foo.js%22%5D%2C%22names%22%3A%5B%5D%7D"),
85 dataUriEmpty: u("data:"),
86 noMap: ""
87}
88
89
90function testResolveSourceMap(method, sync) {
91 return function(t) {
92 var wrap = (sync ? identity : asyncify)
93
94 var codeUrl = "http://example.com/a/b/c/foo.js"
95
96 t.plan(1 + 18*3)
97
98 t.equal(typeof method, "function", "is a function")
99
100 if (sync) {
101 method = asyncify(method)
102 }
103
104 var next = false
105 function isAsync() { t.ok(next, "is async") }
106
107 method(code.fileRelative, codeUrl, wrap(read(map.simpleString)), function(error, result) {
108 t.error(error)
109 t.deepEqual(result, {
110 sourceMappingURL: "foo.js.map",
111 url: "http://example.com/a/b/c/foo.js.map",
112 sourcesRelativeTo: "http://example.com/a/b/c/foo.js.map",
113 map: map.simple
114 }, "fileRelative")
115 isAsync()
116 })
117
118 method(code.domainRelative, codeUrl, wrap(read(map.simpleString)), function(error, result) {
119 t.error(error)
120 t.deepEqual(result, {
121 sourceMappingURL: "/foo.js.map",
122 url: "http://example.com/foo.js.map",
123 sourcesRelativeTo: "http://example.com/foo.js.map",
124 map: map.simple
125 }, "domainRelative")
126 isAsync()
127 })
128
129 method(code.schemeRelative, codeUrl, wrap(read(map.simpleString)), function(error, result) {
130 t.error(error)
131 t.deepEqual(result, {
132 sourceMappingURL: "//foo.org/foo.js.map",
133 url: "http://foo.org/foo.js.map",
134 sourcesRelativeTo: "http://foo.org/foo.js.map",
135 map: map.simple
136 }, "schemeRelative")
137 isAsync()
138 })
139
140 method(code.absolute, codeUrl, wrap(read(map.simpleString)), function(error, result) {
141 t.error(error)
142 t.deepEqual(result, {
143 sourceMappingURL: "https://foo.org/foo.js.map",
144 url: "https://foo.org/foo.js.map",
145 sourcesRelativeTo: "https://foo.org/foo.js.map",
146 map: map.simple
147 }, "absolute")
148 isAsync()
149 })
150
151 method(code.dataUri, codeUrl, wrap(Throws), function(error, result) {
152 t.error(error)
153 t.deepEqual(result, {
154 sourceMappingURL: "data:application/json," +
155 "%7B%22mappings%22%3A%22AAAA%22%2C%22sources%22%3A%5B%22" +
156 "foo.js%22%5D%2C%22names%22%3A%5B%5D%7D",
157 url: null,
158 sourcesRelativeTo: codeUrl,
159 map: map.simple
160 }, "dataUri")
161 isAsync()
162 })
163
164 method(code.base64, codeUrl, wrap(Throws), function(error, result) {
165 t.error(error)
166 t.deepEqual(result, {
167 sourceMappingURL: "data:application/json;base64," +
168 "eyJtYXBwaW5ncyI6IkFBQUEiLCJzb3VyY2VzIjpbImZvby5qcyJdLCJuYW1lcyI6W119",
169 url: null,
170 sourcesRelativeTo: codeUrl,
171 map: map.simple
172 }, "base64")
173 isAsync()
174 })
175
176 method(code.dataUriText, codeUrl, wrap(Throws), function(error, result) {
177 t.error(error)
178 t.deepEqual(result, {
179 sourceMappingURL: "data:text/json," +
180 "%7B%22mappings%22%3A%22AAAA%22%2C%22sources%22%3A%5B%22" +
181 "foo.js%22%5D%2C%22names%22%3A%5B%5D%7D",
182 url: null,
183 sourcesRelativeTo: codeUrl,
184 map: map.simple
185 }, "dataUriText")
186 isAsync()
187 })
188
189 method(code.dataUriParameter, codeUrl, wrap(Throws), function(error, result) {
190 t.error(error)
191 t.deepEqual(result, {
192 sourceMappingURL: "data:application/json;charset=UTF-8;foo=bar," +
193 "%7B%22mappings%22%3A%22AAAA%22%2C%22sources%22%3A%5B%22" +
194 "foo.js%22%5D%2C%22names%22%3A%5B%5D%7D",
195 url: null,
196 sourcesRelativeTo: codeUrl,
197 map: map.simple
198 }, "dataUriParameter")
199 isAsync()
200 })
201
202 method(code.dataUriNoMime, codeUrl, wrap(Throws), function(error, result) {
203 t.ok(error.message.match(/mime type.+text\/plain/), "dataUriNoMime")
204 t.notOk(result)
205 isAsync()
206 })
207
208 method(code.dataUriInvalidMime, codeUrl, wrap(Throws), function(error, result) {
209 t.ok(error.message.match(/mime type.+text\/html/), "dataUriInvalidMime")
210 t.notOk(result)
211 isAsync()
212 })
213
214 method(code.dataUriInvalidJSON, codeUrl, wrap(Throws), function(error, result) {
215 t.ok(error instanceof SyntaxError && error.message !== "data:application/json,foo",
216 "dataUriInvalidJSON")
217 t.notOk(result)
218 isAsync()
219 })
220
221 method(code.dataUriXSSIsafe, codeUrl, wrap(Throws), function(error, result) {
222 t.error(error)
223 t.deepEqual(result, {
224 sourceMappingURL: "data:application/json," + ")%5D%7D%27" +
225 "%7B%22mappings%22%3A%22AAAA%22%2C%22sources%22%3A%5B%22" +
226 "foo.js%22%5D%2C%22names%22%3A%5B%5D%7D",
227 url: null,
228 sourcesRelativeTo: codeUrl,
229 map: map.simple
230 }, "dataUriXSSIsafe")
231 isAsync()
232 })
233
234 method(code.dataUriEmpty, codeUrl, wrap(Throws), function(error, result) {
235 t.ok(error.message.match(/mime type.+text\/plain/), "dataUriEmpty")
236 t.notOk(result)
237 isAsync()
238 })
239
240 method(code.noMap, codeUrl, wrap(Throws), function(error, result) {
241 t.error(error)
242 t.equal(result, null, "noMap")
243 isAsync()
244 })
245
246 method(code.absolute, codeUrl, wrap(read([map.simpleString])), function(error, result) {
247 t.error(error)
248 t.deepEqual(result, {
249 sourceMappingURL: "https://foo.org/foo.js.map",
250 url: "https://foo.org/foo.js.map",
251 sourcesRelativeTo: "https://foo.org/foo.js.map",
252 map: map.simple
253 }, "read non-string")
254 isAsync()
255 })
256
257 method(code.absolute, codeUrl, wrap(read("invalid JSON")), function(error, result) {
258 t.ok(error instanceof SyntaxError, "read invalid JSON")
259 t.notOk(result)
260 isAsync()
261 })
262
263 method(code.absolute, codeUrl, wrap(read(map.XSSIsafe)), function(error, result) {
264 t.error(error)
265 t.deepEqual(result, {
266 sourceMappingURL: "https://foo.org/foo.js.map",
267 url: "https://foo.org/foo.js.map",
268 sourcesRelativeTo: "https://foo.org/foo.js.map",
269 map: map.simple
270 }, "XSSIsafe map")
271 isAsync()
272 })
273
274 method(code.absolute, codeUrl, wrap(Throws), function(error, result) {
275 t.equal(error.message, "https://foo.org/foo.js.map", "read throws")
276 t.notOk(result)
277 isAsync()
278 })
279
280 next = true
281 }
282}
283
284test(".resolveSourceMap", testResolveSourceMap(sourceMapResolve.resolveSourceMap, false))
285
286test(".resolveSourceMapSync", testResolveSourceMap(sourceMapResolve.resolveSourceMapSync, true))
287
288
289function testResolveSources(method, sync) {
290 return function(t) {
291 var wrap = (sync ? identity : asyncify)
292
293 var mapUrl = "http://example.com/a/b/c/foo.js.map"
294
295 t.plan(1 + 9*3 + 4)
296
297 t.equal(typeof method, "function", "is a function")
298
299 if (sync) {
300 method = asyncify(method)
301 }
302
303 var next = false
304 function isAsync() { t.ok(next, "is async") }
305
306 var options
307
308 method(map.simple, mapUrl, wrap(identity), function(error, result) {
309 t.error(error)
310 t.deepEqual(result, {
311 sourcesResolved: ["http://example.com/a/b/c/foo.js"],
312 sourcesContent: ["http://example.com/a/b/c/foo.js"]
313 }, "simple")
314 isAsync()
315 })
316
317 method(map.sourceRoot, mapUrl, wrap(identity), function(error, result) {
318 t.error(error)
319 t.deepEqual(result, {
320 sourcesResolved: [
321 "http://example.com/static/js/app/foo.js",
322 "http://example.com/static/js/app/lib/bar.js",
323 "http://example.com/static/js/vendor/dom.js",
324 "http://example.com/version.js",
325 "http://foo.org/baz.js"
326 ],
327 sourcesContent: [
328 "http://example.com/static/js/app/foo.js",
329 "http://example.com/static/js/app/lib/bar.js",
330 "http://example.com/static/js/vendor/dom.js",
331 "http://example.com/version.js",
332 "http://foo.org/baz.js"
333 ]
334 }, "sourceRoot")
335 isAsync()
336 })
337
338 options = {sourceRoot: false}
339 method(map.sourceRoot, mapUrl, wrap(identity), options, function(error, result) {
340 t.error(error)
341 t.deepEqual(result, {
342 sourcesResolved: [
343 "http://example.com/a/b/c/foo.js",
344 "http://example.com/a/b/c/lib/bar.js",
345 "http://example.com/a/b/vendor/dom.js",
346 "http://example.com/version.js",
347 "http://foo.org/baz.js"
348 ],
349 sourcesContent: [
350 "http://example.com/a/b/c/foo.js",
351 "http://example.com/a/b/c/lib/bar.js",
352 "http://example.com/a/b/vendor/dom.js",
353 "http://example.com/version.js",
354 "http://foo.org/baz.js"
355 ]
356 }, "ignore sourceRoot")
357 isAsync()
358 })
359
360 options = {sourceRoot: "/static/js/"}
361 method(map.sourceRoot, mapUrl, wrap(identity), options, function(error, result) {
362 t.error(error)
363 t.deepEqual(result, {
364 sourcesResolved: [
365 "http://example.com/static/js/foo.js",
366 "http://example.com/static/js/lib/bar.js",
367 "http://example.com/static/vendor/dom.js",
368 "http://example.com/version.js",
369 "http://foo.org/baz.js"
370 ],
371 sourcesContent: [
372 "http://example.com/static/js/foo.js",
373 "http://example.com/static/js/lib/bar.js",
374 "http://example.com/static/vendor/dom.js",
375 "http://example.com/version.js",
376 "http://foo.org/baz.js"
377 ]
378 }, "custom sourceRoot")
379 isAsync()
380 })
381
382 method(map.sourceRootNoSlash, mapUrl, wrap(identity), function(error, result) {
383 t.error(error)
384 t.deepEqual(result, {
385 sourcesResolved: [
386 "http://example.com/static/js/app/foo.js",
387 "http://example.com/static/js/app/lib/bar.js",
388 "http://example.com/static/js/vendor/dom.js",
389 "http://example.com/version.js",
390 "http://foo.org/baz.js"
391 ],
392 sourcesContent: [
393 "http://example.com/static/js/app/foo.js",
394 "http://example.com/static/js/app/lib/bar.js",
395 "http://example.com/static/js/vendor/dom.js",
396 "http://example.com/version.js",
397 "http://foo.org/baz.js"
398 ]
399 }, "sourceRootNoSlash")
400 isAsync()
401 })
402
403 method(map.sourceRootEmpty, mapUrl, wrap(identity), function(error, result) {
404 t.error(error)
405 t.deepEqual(result, {
406 sourcesResolved: [
407 "http://example.com/a/b/c/foo.js",
408 "http://example.com/a/b/c/lib/bar.js",
409 "http://example.com/a/b/vendor/dom.js",
410 "http://example.com/version.js",
411 "http://foo.org/baz.js"
412 ],
413 sourcesContent: [
414 "http://example.com/a/b/c/foo.js",
415 "http://example.com/a/b/c/lib/bar.js",
416 "http://example.com/a/b/vendor/dom.js",
417 "http://example.com/version.js",
418 "http://foo.org/baz.js"
419 ]
420 }, "sourceRootEmpty")
421 isAsync()
422 })
423
424 method(map.sourcesContent, mapUrl, wrap(Throws), function(error, result) {
425 t.error(error)
426 t.deepEqual(result, {
427 sourcesResolved: [
428 "http://example.com/static/js/app/foo.js",
429 "http://example.com/static/js/app/lib/bar.js",
430 "http://example.com/static/js/vendor/dom.js",
431 "http://example.com/version.js",
432 "http://foo.org/baz.js"
433 ],
434 sourcesContent: [
435 "foo.js",
436 "lib/bar.js",
437 "../vendor/dom.js",
438 "/version.js",
439 "//foo.org/baz.js"
440 ]
441 }, "sourcesContent")
442 isAsync()
443 })
444
445 method(map.mixed, mapUrl, wrap(identity), function(error, result) {
446 t.error(error)
447 t.deepEqual(result, {
448 sourcesResolved: [
449 "http://example.com/a/b/c/foo.js",
450 "http://example.com/a/b/c/lib/bar.js",
451 "http://example.com/a/b/vendor/dom.js",
452 "http://example.com/version.js",
453 "http://foo.org/baz.js"
454 ],
455 sourcesContent: [
456 "foo.js",
457 "http://example.com/a/b/c/lib/bar.js",
458 "http://example.com/a/b/vendor/dom.js",
459 "/version.js",
460 "//foo.org/baz.js"
461 ]
462 }, "mixed")
463 isAsync()
464 })
465
466 method(map.simple, mapUrl, wrap(read(["non", "string"])), function(error, result) {
467 t.error(error)
468 t.deepEqual(result, {
469 sourcesResolved: ["http://example.com/a/b/c/foo.js"],
470 sourcesContent: ["non,string"]
471 }, "read non-string")
472 isAsync()
473 })
474
475 var calledBack = false
476 method(map.mixed, mapUrl, wrap(Throws), function(error, result) {
477 t.equal(calledBack, false)
478 calledBack = true
479 t.equal(error.message, "http://example.com/a/b/c/lib/bar.js", "read throws")
480 t.notOk(result)
481 isAsync()
482 })
483
484 next = true
485 }
486}
487
488test(".resolveSources", testResolveSources(sourceMapResolve.resolveSources, false))
489
490test(".resolveSourcesSync", testResolveSources(sourceMapResolve.resolveSourcesSync, true))
491
492test(".resolveSourcesSync no read", function(t) {
493 t.plan(1)
494
495 var mapUrl = "http://example.com/a/b/c/foo.js.map"
496 var result = sourceMapResolve.resolveSourcesSync(map.mixed, mapUrl, null)
497
498 t.deepEqual(result, {
499 sourcesResolved: [
500 "http://example.com/a/b/c/foo.js",
501 "http://example.com/a/b/c/lib/bar.js",
502 "http://example.com/a/b/vendor/dom.js",
503 "http://example.com/version.js",
504 "http://foo.org/baz.js"
505 ],
506 sourcesContent: []
507 })
508})
509
510
511function testResolve(method, sync) {
512 return function(t) {
513 var wrap = (sync ? identity : asyncify)
514 var wrapMap = function(mapFn, fn) {
515 return wrap(function(url) {
516 if (/\.map$/.test(url)) {
517 return mapFn(url)
518 }
519 return fn(url)
520 })
521 }
522
523 var codeUrl = "http://example.com/a/b/c/foo.js"
524
525 t.plan(1 + 23*3 + 11*4 + 4)
526
527 t.equal(typeof method, "function", "is a function")
528
529 if (sync) {
530 method = asyncify(method)
531 }
532
533 var next = false
534 function isAsync() { t.ok(next, "is async") }
535
536 var readSimple = wrapMap(read(map.simpleString), identity)
537
538 method(code.fileRelative, codeUrl, readSimple, function(error, result) {
539 t.error(error)
540 t.deepEqual(result, {
541 sourceMappingURL: "foo.js.map",
542 url: "http://example.com/a/b/c/foo.js.map",
543 sourcesRelativeTo: "http://example.com/a/b/c/foo.js.map",
544 map: map.simple,
545 sourcesResolved: ["http://example.com/a/b/c/foo.js"],
546 sourcesContent: ["http://example.com/a/b/c/foo.js"]
547 }, "fileRelative")
548 isAsync()
549 })
550
551 method(code.domainRelative, codeUrl, readSimple, function(error, result) {
552 t.error(error)
553 t.deepEqual(result, {
554 sourceMappingURL: "/foo.js.map",
555 url: "http://example.com/foo.js.map",
556 sourcesRelativeTo: "http://example.com/foo.js.map",
557 map: map.simple,
558 sourcesResolved: ["http://example.com/foo.js"],
559 sourcesContent: ["http://example.com/foo.js"]
560 }, "domainRelative")
561 isAsync()
562 })
563
564 method(code.schemeRelative, codeUrl, readSimple, function(error, result) {
565 t.error(error)
566 t.deepEqual(result, {
567 sourceMappingURL: "//foo.org/foo.js.map",
568 url: "http://foo.org/foo.js.map",
569 sourcesRelativeTo: "http://foo.org/foo.js.map",
570 map: map.simple,
571 sourcesResolved: ["http://foo.org/foo.js"],
572 sourcesContent: ["http://foo.org/foo.js"]
573 }, "schemeRelative")
574 isAsync()
575 })
576
577 method(code.absolute, codeUrl, readSimple, function(error, result) {
578 t.error(error)
579 t.deepEqual(result, {
580 sourceMappingURL: "https://foo.org/foo.js.map",
581 url: "https://foo.org/foo.js.map",
582 sourcesRelativeTo: "https://foo.org/foo.js.map",
583 map: map.simple,
584 sourcesResolved: ["https://foo.org/foo.js"],
585 sourcesContent: ["https://foo.org/foo.js"]
586 }, "absolute")
587 isAsync()
588 })
589
590 method(code.dataUri, codeUrl, wrapMap(Throws, identity), function(error, result) {
591 t.error(error)
592 t.deepEqual(result, {
593 sourceMappingURL: "data:application/json," +
594 "%7B%22mappings%22%3A%22AAAA%22%2C%22sources%22%3A%5B%22" +
595 "foo.js%22%5D%2C%22names%22%3A%5B%5D%7D",
596 url: null,
597 sourcesRelativeTo: codeUrl,
598 map: map.simple,
599 sourcesResolved: ["http://example.com/a/b/c/foo.js"],
600 sourcesContent: ["http://example.com/a/b/c/foo.js"]
601 }, "dataUri")
602 isAsync()
603 })
604
605 method(code.base64, codeUrl, wrapMap(Throws, identity), function(error, result) {
606 t.error(error)
607 t.deepEqual(result, {
608 sourceMappingURL: "data:application/json;base64," +
609 "eyJtYXBwaW5ncyI6IkFBQUEiLCJzb3VyY2VzIjpbImZvby5qcyJdLCJuYW1lcyI6W119",
610 url: null,
611 sourcesRelativeTo: codeUrl,
612 map: map.simple,
613 sourcesResolved: ["http://example.com/a/b/c/foo.js"],
614 sourcesContent: ["http://example.com/a/b/c/foo.js"]
615 }, "base64")
616 isAsync()
617 })
618
619 method(code.dataUriText, codeUrl, wrapMap(Throws, identity), function(error, result) {
620 t.error(error)
621 t.deepEqual(result, {
622 sourceMappingURL: "data:text/json," +
623 "%7B%22mappings%22%3A%22AAAA%22%2C%22sources%22%3A%5B%22" +
624 "foo.js%22%5D%2C%22names%22%3A%5B%5D%7D",
625 url: null,
626 sourcesRelativeTo: codeUrl,
627 map: map.simple,
628 sourcesResolved: ["http://example.com/a/b/c/foo.js"],
629 sourcesContent: ["http://example.com/a/b/c/foo.js"]
630 }, "dataUriText")
631 isAsync()
632 })
633
634 method(code.dataUriParameter, codeUrl, wrapMap(Throws, identity), function(error, result) {
635 t.error(error)
636 t.deepEqual(result, {
637 sourceMappingURL: "data:application/json;charset=UTF-8;foo=bar," +
638 "%7B%22mappings%22%3A%22AAAA%22%2C%22sources%22%3A%5B%22" +
639 "foo.js%22%5D%2C%22names%22%3A%5B%5D%7D",
640 url: null,
641 sourcesRelativeTo: codeUrl,
642 map: map.simple,
643 sourcesResolved: ["http://example.com/a/b/c/foo.js"],
644 sourcesContent: ["http://example.com/a/b/c/foo.js"]
645 }, "dataUriParameter")
646 isAsync()
647 })
648
649 method(code.dataUriNoMime, codeUrl, wrap(Throws), function(error, result) {
650 t.ok(error.message.match(/mime type.+text\/plain/), "dataUriNoMime")
651 t.notOk(result)
652 isAsync()
653 })
654
655 method(code.dataUriInvalidMime, codeUrl, wrap(Throws), function(error, result) {
656 t.ok(error.message.match(/mime type.+text\/html/), "dataUriInvalidMime")
657 t.notOk(result)
658 isAsync()
659 })
660
661 method(code.dataUriInvalidJSON, codeUrl, wrap(Throws), function(error, result) {
662 t.ok(error instanceof SyntaxError && error.message !== "data:application/json,foo",
663 "dataUriInvalidJSON")
664 t.notOk(result)
665 isAsync()
666 })
667
668 method(code.dataUriXSSIsafe, codeUrl, wrapMap(Throws, identity), function(error, result) {
669 t.error(error)
670 t.deepEqual(result, {
671 sourceMappingURL: "data:application/json," + ")%5D%7D%27" +
672 "%7B%22mappings%22%3A%22AAAA%22%2C%22sources%22%3A%5B%22" +
673 "foo.js%22%5D%2C%22names%22%3A%5B%5D%7D",
674 url: null,
675 sourcesRelativeTo: codeUrl,
676 map: map.simple,
677 sourcesResolved: ["http://example.com/a/b/c/foo.js"],
678 sourcesContent: ["http://example.com/a/b/c/foo.js"]
679 }, "dataUriXSSIsafe")
680 isAsync()
681 })
682
683 method(code.dataUriEmpty, codeUrl, wrap(Throws), function(error, result) {
684 t.ok(error.message.match(/mime type.+text\/plain/), "dataUriEmpty")
685 t.notOk(result)
686 isAsync()
687 })
688
689 method(code.noMap, codeUrl, wrap(Throws), function(error, result) {
690 t.error(error)
691 t.equal(result, null, "noMap")
692 isAsync()
693 })
694
695 method(code.absolute, codeUrl, wrap(read([map.simpleString])), function(error, result) {
696 t.error(error)
697 t.deepEqual(result, {
698 sourceMappingURL: "https://foo.org/foo.js.map",
699 url: "https://foo.org/foo.js.map",
700 sourcesRelativeTo: "https://foo.org/foo.js.map",
701 map: map.simple,
702 sourcesResolved: ["https://foo.org/foo.js"],
703 sourcesContent: [map.simpleString]
704 }, "read non-string")
705 isAsync()
706 })
707
708 method(code.absolute, codeUrl, wrap(read("invalid JSON")), function(error, result) {
709 t.ok(error instanceof SyntaxError, "read invalid JSON")
710 t.notOk(result)
711 isAsync()
712 })
713
714 method(code.absolute, codeUrl, wrapMap(read(map.XSSIsafe), identity), function(error, result) {
715 t.error(error)
716 t.deepEqual(result, {
717 sourceMappingURL: "https://foo.org/foo.js.map",
718 url: "https://foo.org/foo.js.map",
719 sourcesRelativeTo: "https://foo.org/foo.js.map",
720 map: map.simple,
721 sourcesResolved: ["https://foo.org/foo.js"],
722 sourcesContent: ["https://foo.org/foo.js"]
723 }, "XSSIsafe map")
724 isAsync()
725 })
726
727 method(code.absolute, codeUrl, wrap(Throws), function(error, result) {
728 t.equal(error.message, "https://foo.org/foo.js.map", "read throws")
729 t.notOk(result)
730 isAsync()
731 })
732
733 function readMap(what) {
734 return wrapMap(read(JSON.stringify(what)), identity)
735 }
736
737 var options
738
739 method(code.fileRelative, codeUrl, readMap(map.simple), function(error, result) {
740 t.error(error)
741 t.deepEqual(result.sourcesResolved, ["http://example.com/a/b/c/foo.js"], "simple")
742 t.deepEqual(result.sourcesContent, ["http://example.com/a/b/c/foo.js"], "simple")
743 isAsync()
744 })
745
746 method(code.fileRelative, codeUrl, readMap(map.sourceRoot), function(error, result) {
747 t.error(error)
748 t.deepEqual(result.sourcesResolved, [
749 "http://example.com/static/js/app/foo.js",
750 "http://example.com/static/js/app/lib/bar.js",
751 "http://example.com/static/js/vendor/dom.js",
752 "http://example.com/version.js",
753 "http://foo.org/baz.js"
754 ], "sourceRoot")
755 t.deepEqual(result.sourcesContent, [
756 "http://example.com/static/js/app/foo.js",
757 "http://example.com/static/js/app/lib/bar.js",
758 "http://example.com/static/js/vendor/dom.js",
759 "http://example.com/version.js",
760 "http://foo.org/baz.js"
761 ], "sourceRoot")
762 isAsync()
763 })
764
765 options = {sourceRoot: false}
766 method(code.fileRelative, codeUrl, readMap(map.sourceRoot), options, function(error, result) {
767 t.error(error)
768 t.deepEqual(result.sourcesResolved, [
769 "http://example.com/a/b/c/foo.js",
770 "http://example.com/a/b/c/lib/bar.js",
771 "http://example.com/a/b/vendor/dom.js",
772 "http://example.com/version.js",
773 "http://foo.org/baz.js"
774 ], "ignore sourceRoot")
775 t.deepEqual(result.sourcesContent, [
776 "http://example.com/a/b/c/foo.js",
777 "http://example.com/a/b/c/lib/bar.js",
778 "http://example.com/a/b/vendor/dom.js",
779 "http://example.com/version.js",
780 "http://foo.org/baz.js"
781 ], "ignore sourceRoot")
782 isAsync()
783 })
784
785 options = {sourceRoot: "/static/js/"}
786 method(code.fileRelative, codeUrl, readMap(map.sourceRoot), options, function(error, result) {
787 t.error(error)
788 t.deepEqual(result.sourcesResolved, [
789 "http://example.com/static/js/foo.js",
790 "http://example.com/static/js/lib/bar.js",
791 "http://example.com/static/vendor/dom.js",
792 "http://example.com/version.js",
793 "http://foo.org/baz.js"
794 ], "custom sourceRoot")
795 t.deepEqual(result.sourcesContent, [
796 "http://example.com/static/js/foo.js",
797 "http://example.com/static/js/lib/bar.js",
798 "http://example.com/static/vendor/dom.js",
799 "http://example.com/version.js",
800 "http://foo.org/baz.js"
801 ], "custom sourceRoot")
802 isAsync()
803 })
804
805 method(code.fileRelative, codeUrl, readMap(map.sourceRootNoSlash), function(error, result) {
806 t.error(error)
807 t.deepEqual(result.sourcesResolved, [
808 "http://example.com/static/js/app/foo.js",
809 "http://example.com/static/js/app/lib/bar.js",
810 "http://example.com/static/js/vendor/dom.js",
811 "http://example.com/version.js",
812 "http://foo.org/baz.js"
813 ], "sourceRootNoSlash")
814 t.deepEqual(result.sourcesContent, [
815 "http://example.com/static/js/app/foo.js",
816 "http://example.com/static/js/app/lib/bar.js",
817 "http://example.com/static/js/vendor/dom.js",
818 "http://example.com/version.js",
819 "http://foo.org/baz.js"
820 ], "sourceRootNoSlash")
821 isAsync()
822 })
823
824 method(code.fileRelative, codeUrl, readMap(map.sourceRootEmpty), function(error, result) {
825 t.error(error)
826 t.deepEqual(result.sourcesResolved, [
827 "http://example.com/a/b/c/foo.js",
828 "http://example.com/a/b/c/lib/bar.js",
829 "http://example.com/a/b/vendor/dom.js",
830 "http://example.com/version.js",
831 "http://foo.org/baz.js"
832 ], "sourceRootEmpty")
833 t.deepEqual(result.sourcesContent, [
834 "http://example.com/a/b/c/foo.js",
835 "http://example.com/a/b/c/lib/bar.js",
836 "http://example.com/a/b/vendor/dom.js",
837 "http://example.com/version.js",
838 "http://foo.org/baz.js"
839 ], "sourceRootEmpty")
840 isAsync()
841 })
842
843 method(code.fileRelative, codeUrl, readMap(map.sourcesContent), function(error, result) {
844 t.error(error)
845 t.deepEqual(result.sourcesResolved, [
846 "http://example.com/static/js/app/foo.js",
847 "http://example.com/static/js/app/lib/bar.js",
848 "http://example.com/static/js/vendor/dom.js",
849 "http://example.com/version.js",
850 "http://foo.org/baz.js"
851 ], "sourcesContent")
852 t.deepEqual(result.sourcesContent, [
853 "foo.js",
854 "lib/bar.js",
855 "../vendor/dom.js",
856 "/version.js",
857 "//foo.org/baz.js"
858 ], "sourcesContent")
859 isAsync()
860 })
861
862 method(code.fileRelative, codeUrl, readMap(map.mixed), function(error, result) {
863 t.error(error)
864 t.deepEqual(result.sourcesResolved, [
865 "http://example.com/a/b/c/foo.js",
866 "http://example.com/a/b/c/lib/bar.js",
867 "http://example.com/a/b/vendor/dom.js",
868 "http://example.com/version.js",
869 "http://foo.org/baz.js"
870 ], "mixed")
871 t.deepEqual(result.sourcesContent, [
872 "foo.js",
873 "http://example.com/a/b/c/lib/bar.js",
874 "http://example.com/a/b/vendor/dom.js",
875 "/version.js",
876 "//foo.org/baz.js"
877 ], "mixed")
878 isAsync()
879 })
880
881 method(code.fileRelative, codeUrl, wrap(read([map.simpleString])), function(error, result) {
882 t.error(error)
883 t.deepEqual(result.sourcesResolved, ["http://example.com/a/b/c/foo.js"], "read non-string")
884 t.deepEqual(result.sourcesContent, [map.simpleString], "read non-string")
885 isAsync()
886 })
887
888 function ThrowsMap(what) {
889 return wrapMap(read(JSON.stringify(what)), Throws)
890 }
891
892 var calledBack = false
893 method(code.fileRelative, codeUrl, ThrowsMap(map.mixed), function(error, result) {
894 t.equal(calledBack, false)
895 calledBack = true
896 t.equal(error.message, "http://example.com/a/b/c/lib/bar.js", "read throws")
897 t.notOk(result)
898 isAsync()
899 })
900
901 var mapUrl = "https://foo.org/foo.js.map"
902
903 method(null, mapUrl, readSimple, function(error, result) {
904 t.error(error)
905 t.deepEqual(result, {
906 sourceMappingURL: null,
907 url: "https://foo.org/foo.js.map",
908 sourcesRelativeTo: "https://foo.org/foo.js.map",
909 map: map.simple,
910 sourcesResolved: ["https://foo.org/foo.js"],
911 sourcesContent: ["https://foo.org/foo.js"]
912 }, "mapUrl simple")
913 isAsync()
914 })
915
916 method(null, mapUrl, wrap(read([map.simpleString])), function(error, result) {
917 t.error(error)
918 t.deepEqual(result, {
919 sourceMappingURL: null,
920 url: "https://foo.org/foo.js.map",
921 sourcesRelativeTo: "https://foo.org/foo.js.map",
922 map: map.simple,
923 sourcesResolved: ["https://foo.org/foo.js"],
924 sourcesContent: [map.simpleString]
925 }, "mapUrl read non-string")
926 isAsync()
927 })
928
929 method(null, mapUrl, wrap(read("invalid JSON")), function(error, result) {
930 t.ok(error instanceof SyntaxError, "mapUrl read invalid JSON")
931 t.notOk(result)
932 isAsync()
933 })
934
935 method(null, mapUrl, wrapMap(read(map.XSSIsafe), identity), function(error, result) {
936 t.error(error)
937 t.deepEqual(result, {
938 sourceMappingURL: null,
939 url: "https://foo.org/foo.js.map",
940 sourcesRelativeTo: "https://foo.org/foo.js.map",
941 map: map.simple,
942 sourcesResolved: ["https://foo.org/foo.js"],
943 sourcesContent: ["https://foo.org/foo.js"]
944 }, "mapUrl XSSIsafe map")
945 isAsync()
946 })
947
948 method(null, mapUrl, wrap(Throws), function(error, result) {
949 t.equal(error.message, "https://foo.org/foo.js.map", "mapUrl read throws")
950 t.notOk(result)
951 isAsync()
952 })
953
954 mapUrl = "http://example.com/a/b/c/foo.js.map"
955
956 options = {sourceRoot: "/static/js/"}
957 method(null, mapUrl, readMap(map.sourceRoot), options, function(error, result) {
958 t.error(error)
959 t.deepEqual(result.sourcesResolved, [
960 "http://example.com/static/js/foo.js",
961 "http://example.com/static/js/lib/bar.js",
962 "http://example.com/static/vendor/dom.js",
963 "http://example.com/version.js",
964 "http://foo.org/baz.js"
965 ], "mapUrl custom sourceRoot")
966 t.deepEqual(result.sourcesContent, [
967 "http://example.com/static/js/foo.js",
968 "http://example.com/static/js/lib/bar.js",
969 "http://example.com/static/vendor/dom.js",
970 "http://example.com/version.js",
971 "http://foo.org/baz.js"
972 ], "mapUrl custom sourceRoot")
973 isAsync()
974 })
975
976 method(null, mapUrl, readMap(map.mixed), function(error, result) {
977 t.error(error)
978 t.deepEqual(result.sourcesResolved, [
979 "http://example.com/a/b/c/foo.js",
980 "http://example.com/a/b/c/lib/bar.js",
981 "http://example.com/a/b/vendor/dom.js",
982 "http://example.com/version.js",
983 "http://foo.org/baz.js"
984 ], "mapUrl mixed")
985 t.deepEqual(result.sourcesContent, [
986 "foo.js",
987 "http://example.com/a/b/c/lib/bar.js",
988 "http://example.com/a/b/vendor/dom.js",
989 "/version.js",
990 "//foo.org/baz.js"
991 ], "mapUrl mixed")
992 isAsync()
993 })
994
995 next = true
996 }
997}
998
999test(".resolve", testResolve(sourceMapResolve.resolve, false))
1000
1001test(".resolveSync", testResolve(sourceMapResolve.resolveSync, true))
1002
1003test(".parseMapToJSON", function(t) {
1004 t.plan(1)
1005 t.deepEqual(sourceMapResolve.parseMapToJSON(map.XSSIsafe), map.simple)
1006})