Skip to content

Commit 66300f9

Browse files
fix: delete the asset that was read, not whatever holds its name
The generators of a pass run together, so another may have written over the original first — deleting then destroys that file instead.
1 parent 70c42d9 commit 66300f9

2 files changed

Lines changed: 49 additions & 2 deletions

File tree

‎src/index.js‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1780,9 +1780,13 @@ class MinimizerPlugin {
17801780
: generator.deleteOriginalAssets;
17811781

17821782
if (deletes) {
1783+
const still = compilation.getAsset(name);
1784+
17831785
// A generator writing under the original's own name leaves nothing to
1784-
// delete: that file is now the generated one.
1785-
if (generatedName !== name && compilation.getAsset(name)) {
1786+
// delete: that file is now the generated one. Another generator of this
1787+
// pass may have written over it too, which is the same thing — what the
1788+
// name holds is no longer what this one read.
1789+
if (generatedName !== name && still && still.source === source) {
17861790
// Deleting an asset takes everything its `related` names with it — a
17871791
// source map, another generator's file — so it goes alone.
17881792
compilation.updateAsset(name, source, (was) => {

‎test/generate-option.test.js‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2591,6 +2591,49 @@ describe("deleting the asset a file was written beside", () => {
25912591
);
25922592
});
25932593

2594+
it("should not delete what another generator wrote over the original", async () => {
2595+
const compiler = getCompiler({
2596+
entry: { one: path.resolve(__dirname, "./fixtures/entry.js") },
2597+
});
2598+
2599+
/**
2600+
* @param {string} mark what its output opens with
2601+
* @param {EXPECTED_ANY} extra what else to say about it
2602+
* @returns {EXPECTED_ANY} one generator
2603+
*/
2604+
const marking = (mark, extra) => ({
2605+
implementation: (
2606+
/** @type {{ [file: string]: string | Buffer }} */ input,
2607+
) => ({ code: `/* ${mark} */${Object.values(input)[0]}` }),
2608+
type: "asset",
2609+
...extra,
2610+
});
2611+
2612+
new MinimizerPlugin({
2613+
parallel: false,
2614+
test: /\.js$/i,
2615+
minify: [],
2616+
generate: {
2617+
inPlace: marking("in place", { filename: "[path][base]" }),
2618+
beside: marking("beside", {
2619+
filename: "[path][base].gz",
2620+
deleteOriginalAssets: true,
2621+
}),
2622+
},
2623+
}).apply(compiler);
2624+
2625+
const stats = await compile(compiler);
2626+
2627+
// The generators run together, so the one deleting may reach the original
2628+
// after another has written over it — and what it holds is not what it read.
2629+
expect(getErrors(stats)).toEqual([]);
2630+
expect(Object.keys(stats.compilation.assets).sort()).toEqual([
2631+
"one.js",
2632+
"one.js.gz",
2633+
]);
2634+
expect(readAsset("one.js", compiler, stats)).toMatch(/^\/\* in place \*\//);
2635+
});
2636+
25942637
it("should keep a file written under the original's own name", async () => {
25952638
const compiler = getCompiler({
25962639
entry: { one: path.resolve(__dirname, "./fixtures/entry.js") },

0 commit comments

Comments
 (0)