Skip to content

Commit a36739a

Browse files
authored
Merge pull request #13276 from webpack/bugfix/emit-caching
emit assets even when they were cleaned from fs in the meantime
2 parents 8467ae4 + f243907 commit a36739a

File tree

20 files changed

+156
-13
lines changed

20 files changed

+156
-13
lines changed

lib/Compiler.js

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,8 @@ class Compiler {
263263
this._assetEmittingSourceCache = new WeakMap();
264264
/** @private @type {Map<string, number>} */
265265
this._assetEmittingWrittenFiles = new Map();
266+
/** @private @type {Set<string>} */
267+
this._assetEmittingPreviousFiles = new Set();
266268
}
267269

268270
/**
@@ -556,6 +558,8 @@ class Compiler {
556558
compilation.assets = { ...compilation.assets };
557559
/** @type {Map<string, { path: string, source: Source, size: number, waiting: { cacheEntry: any, file: string }[] }>} */
558560
const caseInsensitiveMap = new Map();
561+
/** @type {Set<string>} */
562+
const allTargetPaths = new Set();
559563
asyncLib.forEachLimit(
560564
assets,
561565
15,
@@ -583,6 +587,7 @@ class Compiler {
583587
outputPath,
584588
targetFile
585589
);
590+
allTargetPaths.add(targetPath);
586591

587592
// check if the target file has already been written by this Compiler
588593
const targetFileGeneration = this._assetEmittingWrittenFiles.get(
@@ -775,18 +780,22 @@ ${other}`);
775780
// check if the Source has been written to this target file
776781
const writtenGeneration = cacheEntry.writtenTo.get(targetPath);
777782
if (writtenGeneration === targetFileGeneration) {
778-
// if yes, we skip writing the file
779-
// as it's already there
780-
// (we assume one doesn't remove files while the Compiler is running)
783+
// if yes, we may skip writing the file
784+
// if it's already there
785+
// (we assume one doesn't modify files while the Compiler is running, other then removing them)
781786

782-
compilation.updateAsset(file, cacheEntry.sizeOnlySource, {
783-
size: cacheEntry.sizeOnlySource.size()
784-
});
785-
786-
return callback();
787-
}
787+
if (this._assetEmittingPreviousFiles.has(targetPath)) {
788+
// We assume that assets from the last compilation say intact on disk (they are not removed)
789+
compilation.updateAsset(file, cacheEntry.sizeOnlySource, {
790+
size: cacheEntry.sizeOnlySource.size()
791+
});
788792

789-
if (!immutable) {
793+
return callback();
794+
} else {
795+
// Settings immutable will make it accept file content without comparing when file exist
796+
immutable = true;
797+
}
798+
} else if (!immutable) {
790799
if (checkSimilarFile()) return;
791800
// We wrote to this file before which has very likely a different content
792801
// skip comparing and assume content is different for performance
@@ -822,7 +831,12 @@ ${other}`);
822831
err => {
823832
// Clear map to free up memory
824833
caseInsensitiveMap.clear();
825-
if (err) return callback(err);
834+
if (err) {
835+
this._assetEmittingPreviousFiles.clear();
836+
return callback(err);
837+
}
838+
839+
this._assetEmittingPreviousFiles = allTargetPaths;
826840

827841
this.hooks.afterEmit.callAsync(compilation, err => {
828842
if (err) return callback(err);

test/watchCases/cache/asset-modules/0/index.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1-
it("should return a valid url when cached", () => {
1+
import { stat } from "fs";
2+
import { promisify } from "util";
3+
4+
it("should return a valid url when cached", async () => {
25
const url = new URL("file.txt", import.meta.url);
36
expect(url.pathname).toMatch(/\.txt$/);
7+
expect((await promisify(stat)(url)).isFile()).toBe(true);
48
});
59

6-
it("should return a valid url when modified", () => {
10+
it("should return a valid url when modified", async () => {
711
const url = new URL("other.txt", import.meta.url);
812
expect(url.pathname).toMatch(/\.txt$/);
13+
expect((await promisify(stat)(url)).isFile()).toBe(true);
914
});
1015

1116
it("should not emit undefined files", () => {
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
it("should not emit files", () => {
2+
expect(STATS_JSON.assets.map(a => a.name)).not.toContainEqual(
3+
expect.stringMatching(/\.txt$/)
4+
);
5+
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { stat } from "fs";
2+
import { promisify } from "util";
3+
4+
it("should return a valid url when cached", async () => {
5+
const url = new URL("file.txt", import.meta.url);
6+
expect(url.pathname).toMatch(/\.txt$/);
7+
expect((await promisify(stat)(url)).isFile()).toBe(true);
8+
});
9+
10+
it("should return a valid url when modified", async () => {
11+
const url = new URL("other.txt", import.meta.url);
12+
expect(url.pathname).toMatch(/\.txt$/);
13+
expect((await promisify(stat)(url)).isFile()).toBe(true);
14+
});
15+
16+
it("should not emit undefined files", () => {
17+
expect(STATS_JSON.assets.map(a => a.name)).not.toContain(undefined);
18+
expect(STATS_JSON.assets.map(a => a.name)).not.toContain("undefined");
19+
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello World
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { stat } from "fs";
2+
import { promisify } from "util";
3+
4+
it("should return a valid url when cached", async () => {
5+
const url = new URL("file.txt", import.meta.url);
6+
expect(url.pathname).toMatch(/\.txt$/);
7+
expect((await promisify(stat)(url)).isFile()).toBe(true);
8+
});
9+
10+
it("should return a valid url when modified", async () => {
11+
const url = new URL("other.txt", import.meta.url);
12+
expect(url.pathname).toMatch(/\.txt$/);
13+
expect((await promisify(stat)(url)).isFile()).toBe(true);
14+
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello World 2
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello World
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello World 3
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
it("should not emit files", () => {
2+
expect(STATS_JSON.assets.map(a => a.name)).not.toContainEqual(
3+
expect.stringMatching(/\.txt$/)
4+
);
5+
});

0 commit comments

Comments
 (0)