return new Buffer(str).toString("base64");
} : btoa;
-function read_source_map(code) {
+function read_source_map(name, code) {
var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(.*)/.exec(code);
if (!match) {
- AST_Node.warn("inline source map not found");
+ AST_Node.warn("inline source map not found: " + name);
return null;
}
return to_ascii(match[2]);
}
+function parse_source_map(content) {
+ try {
+ return JSON.parse(content);
+ } catch (ex) {
+ throw new Error("invalid input source map: " + content);
+ }
+}
+
function set_shorthand(name, options, keys) {
if (options[name]) {
keys.forEach(function(key) {
};
}
if (timings) timings.parse = Date.now();
- var toplevel;
+ var source_maps, toplevel;
if (files instanceof AST_Toplevel) {
toplevel = files;
} else {
}
options.parse = options.parse || {};
options.parse.toplevel = null;
+ var source_map_content = options.sourceMap && options.sourceMap.content;
+ if (typeof source_map_content == "string" && source_map_content != "inline") {
+ source_map_content = parse_source_map(source_map_content);
+ }
+ source_maps = source_map_content && Object.create(null);
for (var name in files) if (HOP(files, name)) {
options.parse.filename = name;
options.parse.toplevel = parse(files[name], options.parse);
- if (options.sourceMap && options.sourceMap.content == "inline") {
- if (Object.keys(files).length > 1)
- throw new Error("inline source map only works with singular input");
- options.sourceMap.content = read_source_map(files[name]);
+ if (source_maps) {
+ if (source_map_content == "inline") {
+ var inlined_content = read_source_map(name, files[name]);
+ if (inlined_content) {
+ source_maps[name] = parse_source_map(inlined_content);
+ }
+ } else {
+ source_maps[name] = source_map_content;
+ }
}
}
toplevel = options.parse.toplevel;
}
if (!HOP(options.output, "code") || options.output.code) {
if (options.sourceMap) {
- if (typeof options.sourceMap.content == "string") {
- try {
- options.sourceMap.content = JSON.parse(options.sourceMap.content);
- } catch (ex) {
- throw new Error("invalid input source map: " + options.sourceMap.content);
- }
- }
options.output.source_map = SourceMap({
file: options.sourceMap.filename,
- orig: options.sourceMap.content,
+ orig: source_maps,
root: options.sourceMap.root
});
if (options.sourceMap.includeSources) {
file : options.file,
sourceRoot : options.root
});
- var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig);
-
- if (orig_map && Array.isArray(options.orig.sources)) {
- orig_map._sources.toArray().forEach(function(source) {
- var sourceContent = orig_map.sourceContentFor(source, true);
- if (sourceContent) {
- generator.setSourceContent(source, sourceContent);
- }
- });
+ var maps = options.orig && Object.create(null);
+ if (maps) for (var source in options.orig) {
+ var map = new MOZ_SourceMap.SourceMapConsumer(options.orig[source]);
+ if (Array.isArray(options.orig[source].sources)) {
+ map._sources.toArray().forEach(function(source) {
+ var sourceContent = map.sourceContentFor(source, true);
+ if (sourceContent) generator.setSourceContent(source, sourceContent);
+ });
+ }
+ maps[source] = map;
}
function add(source, gen_line, gen_col, orig_line, orig_col, name) {
- if (orig_map) {
- var info = orig_map.originalPositionFor({
+ var map = maps && maps[source];
+ if (map) {
+ var info = map.originalPositionFor({
line: orig_line,
column: orig_col
});
- if (info.source === null) {
- return;
- }
+ if (info.source === null) return;
source = info.source;
orig_line = info.line;
orig_col = info.column;
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
"",
].join("\n"));
- assert.strictEqual(stderr, "WARN: inline source map not found\n");
+ assert.strictEqual(stderr, "WARN: inline source map not found: test/input/issue-1323/sample.js\n");
done();
});
});
- it("Should fail with multiple input and inline source map", function(done) {
- var command = uglifyjscmd + " test/input/issue-520/input.js test/input/issue-520/output.js --source-map content=inline,url=inline";
+ it("Should handle multiple input and inline source map", function(done) {
+ var command = [
+ uglifyjscmd,
+ "test/input/issue-520/input.js",
+ "test/input/issue-1323/sample.js",
+ "--source-map", "content=inline,url=inline",
+ ].join(" ");
exec(command, function (err, stdout, stderr) {
- assert.ok(err);
- assert.strictEqual(stderr.split(/\n/)[0], "ERROR: inline source map only works with singular input");
+ if (err) throw err;
+
+ assert.strictEqual(stdout, [
+ "var Foo=function Foo(){console.log(1+2)};new Foo;var bar=function(){function foo(bar){return bar}return foo}();",
+ "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwidGVzdC9pbnB1dC9pc3N1ZS0xMzIzL3NhbXBsZS5qcyJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFNBQUFBLE1BQWdCQyxRQUFRQyxJQUFJLEVBQUUsSUFBTyxJQUFJRixJQ0FuRCxJQUFJRyxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
+ "",
+ ].join("\n"));
+ assert.strictEqual(stderr, "WARN: inline source map not found: test/input/issue-1323/sample.js\n");
done();
});
});
});
assert.strictEqual(result.code, "var bar=function(bar){return bar};");
assert.strictEqual(warnings.length, 1);
- assert.strictEqual(warnings[0], "inline source map not found");
+ assert.strictEqual(warnings[0], "inline source map not found: 0");
} finally {
Uglify.AST_Node.warn_function = warn_function;
}
});
- it("Should fail with multiple input and inline source map", function() {
- var result = Uglify.minify([
- read("./test/input/issue-520/input.js"),
- read("./test/input/issue-520/output.js")
- ], {
- sourceMap: {
- content: "inline",
- url: "inline"
- }
- });
- var err = result.error;
- assert.ok(err instanceof Error);
- assert.strictEqual(err.stack.split(/\n/)[0], "Error: inline source map only works with singular input");
+ it("Should handle multiple input and inline source map", function() {
+ var warn_function = Uglify.AST_Node.warn_function;
+ var warnings = [];
+ Uglify.AST_Node.warn_function = function(txt) {
+ warnings.push(txt);
+ };
+ try {
+ var result = Uglify.minify([
+ read("./test/input/issue-520/input.js"),
+ read("./test/input/issue-1323/sample.js"),
+ ], {
+ sourceMap: {
+ content: "inline",
+ url: "inline",
+ }
+ });
+ if (result.error) throw result.error;
+ assert.strictEqual(result.code, [
+ "var Foo=function(){console.log(3)};new Foo;var bar=function(o){return o};",
+ "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwiMSJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFdBQWdCQyxRQUFRQyxJQUFJLElBQVMsSUFBSUYsSUNBbkQsSUFBSUcsSUFDQSxTQUFjQSxHQUNWLE9BQU9BIn0=",
+ ].join("\n"));
+ assert.strictEqual(warnings.length, 1);
+ assert.strictEqual(warnings[0], "inline source map not found: 1");
+ } finally {
+ Uglify.AST_Node.warn_function = warn_function;
+ }
});
it("Should drop source contents for includeSources=false", function() {
var result = Uglify.minify(read("./test/input/issue-520/input.js"), {