diff --git a/lib/minify.js b/lib/minify.js index c112a17d4..aa3f73d83 100644 --- a/lib/minify.js +++ b/lib/minify.js @@ -297,18 +297,15 @@ async function minify(files, options, _fs_module) { } if (options.sourceMap) { + if (options.sourceMap.includeSources && files instanceof AST_Toplevel) { + throw new Error("original source content unavailable"); + } options.format.source_map = await SourceMap({ file: options.sourceMap.filename, orig: options.sourceMap.content, - root: options.sourceMap.root + root: options.sourceMap.root, + files: options.sourceMap.includeSources ? files : null, }); - if (options.sourceMap.includeSources) { - if (files instanceof AST_Toplevel) { - throw new Error("original source content unavailable"); - } else for (var name in files) if (HOP(files, name)) { - options.format.source_map.get().setSourceContent(name, files[name]); - } - } } delete options.format.ast; delete options.format.code; @@ -317,11 +314,21 @@ async function minify(files, options, _fs_module) { toplevel.print(stream); result.code = stream.get(); if (options.sourceMap) { - if(options.sourceMap.asObject) { - result.map = options.format.source_map.get().toJSON(); - } else { - result.map = options.format.source_map.toString(); - } + Object.defineProperty(result, "map", { + configurable: true, + enumerable: true, + get() { + const map = options.format.source_map.getEncoded(); + return (result.map = options.sourceMap.asObject ? map : JSON.stringify(map)); + }, + set(value) { + Object.defineProperty(result, "map", { + value, + writable: true, + }); + } + }); + result.decoded_map = options.format.source_map.getDecoded(); if (options.sourceMap.url == "inline") { var sourceMap = typeof result.map === "object" ? JSON.stringify(result.map) : result.map; result.code += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + to_base64(sourceMap); diff --git a/lib/sourcemap.js b/lib/sourcemap.js index 598babce6..34bdd0605 100644 --- a/lib/sourcemap.js +++ b/lib/sourcemap.js @@ -43,34 +43,39 @@ "use strict"; -import MOZ_SourceMap from "source-map"; -import {AnyMap, originalPositionFor} from "@jridgewell/trace-mapping"; -import {defaults} from "./utils/index.js"; +import {SourceMapConsumer, SourceMapGenerator} from "@jridgewell/source-map"; +import {defaults, HOP} from "./utils/index.js"; -// a small wrapper around source-map and @jridgewell/trace-mapping -function SourceMap(options) { +// a small wrapper around source-map and @jridgewell/source-map +async function SourceMap(options) { options = defaults(options, { file : null, root : null, orig : null, - - orig_line_diff : 0, - dest_line_diff : 0, + files: {}, }); var orig_map; - var generator = new MOZ_SourceMap.SourceMapGenerator({ + var generator = new SourceMapGenerator({ file : options.file, sourceRoot : options.root }); + let sourcesContent = {__proto__: null}; + let files = options.files; + for (var name in files) if (HOP(files, name)) { + sourcesContent[name] = files[name]; + } if (options.orig) { - orig_map = new AnyMap(options.orig); + // We support both @jridgewell/source-map (which has a sync + // SourceMapConsumer) and source-map (which has an async + // SourceMapConsumer). + orig_map = await new SourceMapConsumer(options.orig); if (orig_map.sourcesContent) { - orig_map.resolvedSources.forEach(function(source, i) { - var sourceContent = orig_map.sourcesContent[i]; - if (sourceContent) { - generator.setSourceContent(source, sourceContent); + orig_map.sources.forEach(function(source, i) { + var content = orig_map.sourcesContent[i]; + if (content) { + sourcesContent[source] = content; } }); } @@ -78,7 +83,7 @@ function SourceMap(options) { function add(source, gen_line, gen_col, orig_line, orig_col, name) { if (orig_map) { - var info = originalPositionFor(orig_map, { + var info = orig_map.originalPositionFor({ line: orig_line, column: orig_col }); @@ -91,18 +96,42 @@ function SourceMap(options) { name = info.name || name; } generator.addMapping({ - generated : { line: gen_line + options.dest_line_diff, column: gen_col }, - original : { line: orig_line + options.orig_line_diff, column: orig_col }, + generated : { line: gen_line, column: gen_col }, + original : { line: orig_line, column: orig_col }, source : source, name : name }); + generator.setSourceContent(source, sourcesContent[source]); + } + + function clean(map) { + const allNull = map.sourcesContent && map.sourcesContent.every(c => c == null); + if (allNull) delete map.sourcesContent; + if (map.file === undefined) delete map.file; + if (map.sourceRoot === undefined) delete map.sourceRoot; + return map; + } + + function getDecoded() { + if (!generator.toDecodedMap) return null; + return clean(generator.toDecodedMap()); + } + + function getEncoded() { + return clean(generator.toJSON()); + } + + function destroy() { + // @jridgewell/source-map's SourceMapConsumer does not need to be + // manually freed. + if (orig_map && orig_map.destroy) orig_map.destroy(); } return { - add : add, - get : function() { return generator; }, - toString : function() { return generator.toString(); }, - destroy : function() {} + add, + getDecoded, + getEncoded, + destroy, }; } diff --git a/package-lock.json b/package-lock.json index 46ee7e167..08594d68e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -83,10 +83,34 @@ "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", "dev": true }, + "@jridgewell/gen-mapping": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.0.tgz", + "integrity": "sha512-bFDbLEZ84DtNwXILbufXeQMz3tcGSfy+ROgvnB9jUm+t48G4Po+1UhhyFh6GIsFOE2R31Ab0ddeMv+Z9gcYC4g==", + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, "@jridgewell/resolve-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", - "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==" + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.6.tgz", + "integrity": "sha512-R7xHtBSNm+9SyvpJkdQl+qrM3Hm2fea3Ef197M3mUug+v+yR+Rhfbs7PBtcBUVnIWJ4JcAdjvij+c8hXS9p5aw==" + }, + "@jridgewell/set-array": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.0.tgz", + "integrity": "sha512-SfJxIxNVYLTsKwzB3MoOQ1yxf4w/E6MdkvTgrgAt1bfxjSrLUoHMKrDOykwN14q65waezZIdqDneUIPh4/sKxg==" + }, + "@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } }, "@jridgewell/sourcemap-codec": { "version": "1.4.11", @@ -94,9 +118,9 @@ "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==" }, "@jridgewell/trace-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.5.tgz", - "integrity": "sha512-JVOWdxPmgNsrNKVyhFNB08go/kCnXUT5m3Ds11F3lh3oKzCHTzs3IHRC9VI0t8mNyL4TfypxTiwQPU+77Sfm6g==", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "requires": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -934,7 +958,8 @@ "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true }, "lodash.truncate": { "version": "4.4.2", @@ -1270,7 +1295,8 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true }, "random-int": { "version": "2.0.1", @@ -1513,6 +1539,7 @@ "version": "0.8.0-beta.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dev": true, "requires": { "whatwg-url": "^7.0.0" } @@ -1654,6 +1681,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, "requires": { "punycode": "^2.1.0" } @@ -1731,12 +1759,14 @@ "webidl-conversions": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true }, "whatwg-url": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, "requires": { "lodash.sortby": "^4.7.0", "tr46": "^1.0.1", diff --git a/package.json b/package.json index 8a6540b21..98894a046 100644 --- a/package.json +++ b/package.json @@ -44,10 +44,9 @@ "main.js" ], "dependencies": { - "@jridgewell/trace-mapping": "^0.3.5", + "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", "commander": "^2.20.0", - "source-map": "~0.8.0-beta.0", "source-map-support": "~0.5.20" }, "devDependencies": { @@ -60,7 +59,8 @@ "pre-commit": "^1.2.2", "rimraf": "^3.0.2", "rollup": "2.56.3", - "semver": "^7.3.4" + "semver": "^7.3.4", + "source-map": "~0.8.0-beta.0" }, "scripts": { "test": "node test/compress.js && mocha test/mocha", diff --git a/rollup.config.js b/rollup.config.js index d32d95af8..377d7ce4e 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -5,7 +5,7 @@ export default () => { file: "dist/bundle.min.js", format: "umd", globals: { - "source-map": "sourceMap", + "@jridgewell/source-map": "sourceMap", }, name: "Terser", sourcemap: false, diff --git a/test/input/issue-505/output.js b/test/input/issue-505/output.js index 5a1bc018b..14f8febaa 100644 --- a/test/input/issue-505/output.js +++ b/test/input/issue-505/output.js @@ -2,4 +2,4 @@ function test(a){ "aaaaaaaaaaaaaaaa" ;a(err,data),a(err,data) } -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsidGVzdCIsImNhbGxiYWNrIiwiZXJyIiwiZGF0YSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsS0FBS0M7QUFDVjtDQUNBQSxFQUFTQyxJQUFLQyxNQUNkRixFQUFTQyxJQUFLQyJ9 \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJ0ZXN0IiwiY2FsbGJhY2siLCJlcnIiLCJkYXRhIl0sInNvdXJjZXMiOlsiMCJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsS0FBS0M7QUFDVjtDQUNBQSxFQUFTQyxJQUFLQyxNQUNkRixFQUFTQyxJQUFLQyJ9 \ No newline at end of file diff --git a/test/input/issue-520/output.js b/test/input/issue-520/output.js index f6d138047..0aa3c9632 100644 --- a/test/input/issue-520/output.js +++ b/test/input/issue-520/output.js @@ -1,2 +1,2 @@ new function(){console.log(3)}; -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl19 +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJjb25zb2xlIiwibG9nIl0sInNvdXJjZXMiOlsic3RkaW4iXSwic291cmNlc0NvbnRlbnQiOlsiY2xhc3MgRm9vIHsgY29uc3RydWN0b3IoKXtjb25zb2xlLmxvZygxKzIpO30gfSBuZXcgRm9vKCk7XG4iXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSJ9 diff --git a/test/input/source-maps/expect.js b/test/input/source-maps/expect.js index b911f3f8d..57cce7b94 100644 --- a/test/input/source-maps/expect.js +++ b/test/input/source-maps/expect.js @@ -1,2 +1,2 @@ function _toConsumableArray(arr){if(Array.isArray(arr)){for(var i=0,arr2=Array(arr.length);i { @@ -191,8 +212,8 @@ describe("sourcemaps", function() { if (result.error) throw result.error; var map = JSON.parse(result.map); assert.equal(map.file, "simple.min.js"); - assert.equal(map.sourcesContent.length, 1); - assert.equal(map.sourcesContent[0], 'let foo = x => "foo " + x;\nconsole.log(foo("bar"));'); + assert.deepEqual(map.sources, ["index.js"]); + assert.deepEqual(map.sourcesContent, ['let foo = x => "foo " + x;\nconsole.log(foo("bar"));']); }); it("Should process inline source map", async function() { var result = await minify(read("./test/input/issue-520/input.js"), { diff --git a/tools/terser.d.ts b/tools/terser.d.ts index 571b5f0fe..0ec08017b 100644 --- a/tools/terser.d.ts +++ b/tools/terser.d.ts @@ -1,6 +1,6 @@ /// -import { RawSourceMap } from 'source-map'; +import { SectionedSourceMapInput, EncodedSourceMap, DecodedSourceMap } from '@jridgewell/source-map'; export type ECMA = 5 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020; @@ -193,12 +193,13 @@ export interface MinifyOptions { export interface MinifyOutput { code?: string; - map?: RawSourceMap | string; + map?: EncodedSourceMap | string; + decoded_map?: DecodedSourceMap | null; } export interface SourceMapOptions { /** Source map object, 'inline' or source map file content */ - content?: RawSourceMap | string; + content?: SectionedSourceMapInput | string; includeSources?: boolean; filename?: string; root?: string;