Skip to content

Commit

Permalink
Don't mutate options object. Fixes terser#1341
Browse files Browse the repository at this point in the history
  • Loading branch information
robhogan committed Feb 17, 2023
1 parent e0acb3c commit 3e99aab
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 11 deletions.
25 changes: 14 additions & 11 deletions lib/minify.js
Expand Up @@ -280,10 +280,13 @@ async function minify(files, options, _fs_module) {
if (options.format.spidermonkey) {
result.ast = toplevel.to_mozilla_ast();
}
let formatOptions;
if (!HOP(options.format, "code") || options.format.code) {
if (!options.format.ast) {
// Make a shallow copy so that we can modify without mutating the user's input.
formatOptions = {...options.format};
if (!formatOptions.ast) {
// Destroy stuff to save RAM. (unless the deprecated `ast` option is on)
options.format._destroy_ast = true;
formatOptions._destroy_ast = true;

walk(toplevel, node => {
if (node instanceof AST_Scope) {
Expand All @@ -303,25 +306,25 @@ async function minify(files, options, _fs_module) {
if (options.sourceMap.includeSources && files instanceof AST_Toplevel) {
throw new Error("original source content unavailable");
}
options.format.source_map = await SourceMap({
formatOptions.source_map = await SourceMap({
file: options.sourceMap.filename,
orig: options.sourceMap.content,
root: options.sourceMap.root,
files: options.sourceMap.includeSources ? files : null,
});
}
delete options.format.ast;
delete options.format.code;
delete options.format.spidermonkey;
var stream = OutputStream(options.format);
delete formatOptions.ast;
delete formatOptions.code;
delete formatOptions.spidermonkey;
var stream = OutputStream(formatOptions);
toplevel.print(stream);
result.code = stream.get();
if (options.sourceMap) {
Object.defineProperty(result, "map", {
configurable: true,
enumerable: true,
get() {
const map = options.format.source_map.getEncoded();
const map = formatOptions.source_map.getEncoded();
return (result.map = options.sourceMap.asObject ? map : JSON.stringify(map));
},
set(value) {
Expand All @@ -331,7 +334,7 @@ async function minify(files, options, _fs_module) {
});
}
});
result.decoded_map = options.format.source_map.getDecoded();
result.decoded_map = formatOptions.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);
Expand All @@ -346,8 +349,8 @@ async function minify(files, options, _fs_module) {
options.nameCache.props = cache_to_json(options.mangle.properties.cache);
}
}
if (options.format && options.format.source_map) {
options.format.source_map.destroy();
if (formatOptions && formatOptions.source_map) {
formatOptions.source_map.destroy();
}
if (timings) {
timings.end = Date.now();
Expand Down
33 changes: 33 additions & 0 deletions test/mocha/no-mutate-input.js
@@ -0,0 +1,33 @@
import assert from "assert";
import { minify } from "../../main.js";

describe("no-mutate-input", function() {

it("does not modify the options object", async function() {
const originalConfig = {
format: {},
sourceMap: true,
};
const config = {...originalConfig};

await minify('"foo";', config);

assert.deepEqual(originalConfig, config);
});

it("does not clobber source maps with a subsequent minification", async function() {
const originalConfig = {
format: {},
sourceMap: true,
};
const config = {...originalConfig};

const fooResult = await minify('"foo";', config);
const barResult = await minify('module.exports = "bar";', config);

const fooMap = fooResult.map;
const barMap = barResult.map;

assert.notEqual(barMap, fooMap);
});
});

0 comments on commit 3e99aab

Please sign in to comment.