You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
307 lines
9.1 KiB
JavaScript
307 lines
9.1 KiB
JavaScript
var path = require("path");
|
|
var fs = require("fs");
|
|
var should = require("should");
|
|
var loader = require("../");
|
|
|
|
function execLoader(filename, callback) {
|
|
var async = false;
|
|
var deps = [];
|
|
var warns = [];
|
|
var context = {
|
|
context: path.dirname(filename),
|
|
resolve: function(context, request, callback) {
|
|
process.nextTick(function() {
|
|
var p = path.isAbsolute(request) ? request : path.resolve(context, request);
|
|
if(fs.existsSync(p))
|
|
callback(null, p);
|
|
else
|
|
callback(new Error("File not found"));
|
|
});
|
|
},
|
|
addDependency: function(dep) {
|
|
deps.push(dep);
|
|
},
|
|
emitWarning: function(warn) {
|
|
warns.push(warn);
|
|
},
|
|
callback: function(err, res, map) {
|
|
async = true;
|
|
callback(err, res, map, deps, warns);
|
|
},
|
|
async: function() {
|
|
async = true;
|
|
return this.callback;
|
|
}
|
|
};
|
|
// Remove CRs to make test line ending invariant
|
|
var fixtureContent = fs.readFileSync(filename, "utf-8").replace(/\r/g, '');
|
|
var res = loader.call(context, fixtureContent);
|
|
if(!async) return callback(null, res, null, deps, warns);
|
|
}
|
|
|
|
describe("source-map-loader", function() {
|
|
const fixturesPath = path.join(__dirname, "fixtures");
|
|
const dataPath = path.join(fixturesPath, "data");
|
|
|
|
it("should leave normal files untouched", function(done) {
|
|
execLoader(path.join(fixturesPath, "normal-file.js"), function(err, res, map, deps, warns) {
|
|
should.equal(err, null);
|
|
warns.should.be.eql([]);
|
|
should.equal(res, "without SourceMap"),
|
|
should.equal(map, null);
|
|
deps.should.be.eql([]);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it("should process inlined SourceMaps", function(done) {
|
|
execLoader(path.join(fixturesPath, "inline-source-map.js"), function(err, res, map, deps, warns) {
|
|
should.equal(err, null);
|
|
warns.should.be.eql([]);
|
|
should.equal(res, "with SourceMap\n// comment"),
|
|
map.should.be.eql({
|
|
"version":3,
|
|
"file":"inline-source-map.js",
|
|
"sources":[
|
|
"inline-source-map.txt"
|
|
],
|
|
"sourcesContent":["with SourceMap"],
|
|
"mappings":"AAAA"
|
|
});
|
|
deps.should.be.eql([]);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it("should process external SourceMaps", function(done) {
|
|
execLoader(path.join(fixturesPath, "external-source-map.js"), function(err, res, map, deps, warns) {
|
|
should.equal(err, null);
|
|
warns.should.be.eql([]);
|
|
should.equal(res, "with SourceMap\n// comment"),
|
|
map.should.be.eql({
|
|
"version":3,
|
|
"file":"external-source-map.js",
|
|
"sources":[
|
|
"external-source-map.txt"
|
|
],
|
|
"sourcesContent":["with SourceMap"],
|
|
"mappings":"AAAA"
|
|
});
|
|
deps.should.be.eql([
|
|
path.join(fixturesPath, "external-source-map.map")
|
|
]);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it("should process external SourceMaps (external sources)", function(done) {
|
|
execLoader(path.join(fixturesPath, "external-source-map2.js"), function(err, res, map, deps, warns) {
|
|
should.equal(err, null);
|
|
warns.should.be.eql([]);
|
|
should.equal(res, "with SourceMap\n// comment"),
|
|
map.should.be.eql({
|
|
"version":3,
|
|
"file":"external-source-map2.js",
|
|
"sources":[
|
|
path.join(fixturesPath, "external-source-map2.txt")
|
|
],
|
|
"sourcesContent":["with SourceMap"],
|
|
"mappings":"AAAA"
|
|
});
|
|
deps.should.be.eql([
|
|
path.join(dataPath, "external-source-map2.map"),
|
|
path.join(fixturesPath, "external-source-map2.txt")
|
|
]);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it("should use last SourceMap directive", function (done) {
|
|
execLoader(path.join(fixturesPath, "multi-source-map.js"), function (err, res, map, deps, warns) {
|
|
should.equal(err, null);
|
|
warns.should.be.eql([]);
|
|
should.equal(res, "with SourceMap\nanInvalidDirective = \"\\n/*# sourceMappingURL=data:application/json;base64,\"+btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))))+\" */\";\n// comment"),
|
|
map.should.be.eql({
|
|
"version": 3,
|
|
"file": "inline-source-map.js",
|
|
"sources": [
|
|
"inline-source-map.txt"
|
|
],
|
|
"sourcesContent": ["with SourceMap"],
|
|
"mappings": "AAAA"
|
|
});
|
|
deps.should.be.eql([]);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it("should skip invalid base64 SourceMap", function (done) {
|
|
execLoader(path.join(fixturesPath, "invalid-inline-source-map.js"), function (err, res, map, deps, warns) {
|
|
should.equal(err, null);
|
|
warns.should.be.eql([]);
|
|
should.equal(res, "without SourceMap\n// @sourceMappingURL=data:application/source-map;base64,\"something invalid\"\n// comment");
|
|
should.equal(map, null);
|
|
deps.should.be.eql([]);
|
|
done();
|
|
});
|
|
});
|
|
it("should warn on invalid base64 SourceMap", function (done) {
|
|
execLoader(path.join(fixturesPath, "invalid-inline-source-map2.js"), function (err, res, map, deps, warns) {
|
|
should.equal(err, null);
|
|
warns.should.matchEach(
|
|
new RegExp("Cannot parse inline SourceMap 'invalid\/base64=': SyntaxError: Unexpected token")
|
|
);
|
|
should.equal(res, "without SourceMap\n// @sourceMappingURL=data:application/source-map;base64,invalid/base64=\n// comment");
|
|
should.equal(map, null);
|
|
deps.should.be.eql([]);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it("should warn on invalid SourceMap", function (done) {
|
|
execLoader(path.join(fixturesPath, "invalid-source-map.js"), function (err, res, map, deps, warns) {
|
|
should.equal(err, null);
|
|
warns.should.matchEach(
|
|
new RegExp("Cannot parse SourceMap 'invalid-source-map.map': SyntaxError: Unexpected string in JSON at position 102")
|
|
);
|
|
should.equal(res, "with SourceMap\n//#sourceMappingURL=invalid-source-map.map\n// comment");
|
|
should.equal(map, null);
|
|
deps.should.be.eql([
|
|
path.join(fixturesPath, "invalid-source-map.map")
|
|
]);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it("should warn on missing SourceMap", function(done) {
|
|
execLoader(path.join(fixturesPath, "missing-source-map.js"), function(err, res, map, deps, warns) {
|
|
should.equal(err, null);
|
|
warns.should.be.eql([
|
|
"Cannot find SourceMap 'missing-source-map.map': Error: File not found"
|
|
]);
|
|
should.equal(res, "with SourceMap\n//#sourceMappingURL=missing-source-map.map\n// comment"),
|
|
should.equal(map, null);
|
|
deps.should.be.eql([]);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it("should warn on missing source file", function(done) {
|
|
execLoader(path.join(fixturesPath, "missing-source-map2.js"), function(err, res, map, deps, warns) {
|
|
should.equal(err, null);
|
|
warns.should.be.eql([
|
|
"Cannot find source file 'missing-source-map2.txt': Error: File not found"
|
|
]);
|
|
should.equal(res, "with SourceMap\n// comment"),
|
|
map.should.be.eql({
|
|
"version":3,
|
|
"file":"missing-source-map2.js",
|
|
"sources":[
|
|
"missing-source-map2.txt"
|
|
],
|
|
"sourcesContent":[null],
|
|
"mappings":"AAAA"
|
|
});
|
|
deps.should.be.eql([
|
|
path.join(fixturesPath, "missing-source-map2.map")
|
|
]);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it("should process inlined SourceMaps with charset", function(done) {
|
|
execLoader(path.join(fixturesPath, "charset-inline-source-map.js"), function(err, res, map, deps, warns) {
|
|
should.equal(err, null);
|
|
warns.should.be.eql([]);
|
|
should.equal(res, "with SourceMap\n// comment"),
|
|
map.should.be.eql({
|
|
"version":3,
|
|
"file":"charset-inline-source-map.js",
|
|
"sources":[
|
|
"charset-inline-source-map.txt"
|
|
],
|
|
"sourcesContent":["with SourceMap"],
|
|
"mappings":"AAAA"
|
|
});
|
|
deps.should.be.eql([]);
|
|
done();
|
|
});
|
|
});
|
|
|
|
it("should support absolute sourceRoot paths in sourcemaps", (done) => {
|
|
const sourceRoot = path.join(fixturesPath);
|
|
const javaScriptFilename = "absolute-sourceRoot-source-map.js";
|
|
const sourceFilename = "absolute-sourceRoot-source-map.txt";
|
|
const rootRelativeSourcePath = path.join(sourceRoot, sourceFilename);
|
|
const sourceMapPath = path.join(sourceRoot, "absolute-sourceRoot-source-map.map");
|
|
|
|
// Create the sourcemap file
|
|
const rawSourceMap = {
|
|
"version": 3,
|
|
"file": javaScriptFilename,
|
|
"sourceRoot": sourceRoot,
|
|
"sources": [
|
|
sourceFilename
|
|
],
|
|
"mappings": "AAAA"
|
|
};
|
|
fs.writeFileSync(sourceMapPath, JSON.stringify(rawSourceMap));
|
|
|
|
execLoader(
|
|
path.join(fixturesPath, javaScriptFilename),
|
|
(err, res, map, deps, warns) => {
|
|
should.equal(err, null);
|
|
warns.should.be.eql([]);
|
|
should.equal(res, "with SourceMap\n// comment"),
|
|
map.should.be.eql({
|
|
"version": 3,
|
|
"file": javaScriptFilename,
|
|
"sources": [
|
|
rootRelativeSourcePath
|
|
],
|
|
"sourcesContent": [
|
|
"with SourceMap\n// comment"
|
|
],
|
|
"mappings": "AAAA"
|
|
});
|
|
deps.should.be.eql([
|
|
sourceMapPath,
|
|
rootRelativeSourcePath
|
|
]);
|
|
done();
|
|
}
|
|
);
|
|
});
|
|
|
|
it("should support relative sourceRoot paths in sourcemaps", (done) => {
|
|
const javaScriptFilename = "relative-sourceRoot-source-map.js";
|
|
const sourceFilename = "relative-sourceRoot-source-map.txt";
|
|
const rootRelativeSourcePath = path.join(dataPath, sourceFilename);
|
|
const sourceMapPath = path.join(fixturesPath, "relative-sourceRoot-source-map.map");
|
|
|
|
execLoader(
|
|
path.join(fixturesPath, javaScriptFilename),
|
|
(err, res, map, deps, warns) => {
|
|
should.equal(err, null);
|
|
warns.should.be.eql([]);
|
|
should.equal(res, "with SourceMap\n// comment"),
|
|
map.should.be.eql({
|
|
"version": 3,
|
|
"file": javaScriptFilename,
|
|
"sources": [
|
|
rootRelativeSourcePath
|
|
],
|
|
"sourcesContent": [
|
|
"with SourceMap\n// comment"
|
|
],
|
|
"mappings": "AAAA"
|
|
});
|
|
deps.should.be.eql([
|
|
sourceMapPath,
|
|
rootRelativeSourcePath
|
|
]);
|
|
done();
|
|
}
|
|
);
|
|
});
|
|
}); |