Skip to content

Commit 3ea2061

Browse files
authored
Merge pull request #12778 from webpack/bugfix/12770
MultiCompiler Watching fixes
2 parents 8a362fb + 1ebc7ca commit 3ea2061

File tree

6 files changed

+64
-30
lines changed

6 files changed

+64
-30
lines changed

lib/MultiCompiler.js

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,12 @@ module.exports = class MultiCompiler {
350350
let errored = false;
351351
let running = 0;
352352
const parallelism = this._options.parallelism;
353+
/**
354+
* @param {Node} node node
355+
* @param {Error=} err error
356+
* @param {Stats=} stats result
357+
* @returns {void}
358+
*/
353359
const nodeDone = (node, err, stats) => {
354360
if (errored) return;
355361
if (err) {
@@ -367,27 +373,35 @@ module.exports = class MultiCompiler {
367373
);
368374
}
369375
node.result = stats;
376+
running--;
370377
if (node.state === "running") {
371-
running--;
372378
node.state = "done";
373-
for (const child of node.children) {
374-
if (child.state !== "blocked") continue;
375-
if (child.parents.every(p => p.state === "done")) {
376-
child.state = "queued";
377-
queue.enqueue(child);
378-
}
379+
}
380+
for (const child of node.children) {
381+
if (child.state !== "blocked") continue;
382+
if (child.parents.every(p => p.state === "done")) {
383+
child.state = "queued";
384+
queue.enqueue(child);
379385
}
380-
process.nextTick(processQueue);
381386
}
387+
process.nextTick(processQueue);
382388
};
389+
/**
390+
* @param {Node} node node
391+
* @returns {void}
392+
*/
383393
const nodeInvalid = node => {
384-
if (node.state === "done") {
394+
if (node.state === "done" || node.state === "running") {
385395
node.state = "blocked";
386-
for (const child of node.children) {
387-
nodeInvalid(child);
388-
}
396+
}
397+
for (const child of node.children) {
398+
nodeInvalid(child);
389399
}
390400
};
401+
/**
402+
* @param {Node} node node
403+
* @returns {void}
404+
*/
391405
const nodeChange = node => {
392406
nodeInvalid(node);
393407
if (
@@ -415,6 +429,7 @@ module.exports = class MultiCompiler {
415429
const processQueue = () => {
416430
while (running < parallelism && queue.length > 0 && !errored) {
417431
const node = queue.dequeue();
432+
if (node.state !== "queued") continue;
418433
running++;
419434
node.state = "running";
420435
run(node.compiler, nodeDone.bind(null, node));
@@ -446,6 +461,7 @@ module.exports = class MultiCompiler {
446461
if (this.running) {
447462
return handler(new ConcurrentCompilationError());
448463
}
464+
this.running = true;
449465

450466
if (this.validateDependencies(handler)) {
451467
const watchings = this._runGraph(
@@ -480,6 +496,7 @@ module.exports = class MultiCompiler {
480496
if (this.running) {
481497
return callback(new ConcurrentCompilationError());
482498
}
499+
this.running = true;
483500

484501
if (this.validateDependencies(callback)) {
485502
this._runGraph(

lib/Watching.js

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ class Watching {
5454
this.running = false;
5555
this._initial = true;
5656
this._needRecords = true;
57-
this._needWatcherInfo = false;
5857
this.watcher = undefined;
5958
this.pausedWatcher = undefined;
6059
this._done = this._done.bind(this);
@@ -84,21 +83,6 @@ class Watching {
8483
});
8584
}
8685
this.invalid = false;
87-
if (this._needWatcherInfo) {
88-
this._needWatcherInfo = false;
89-
const watcher = this.pausedWatcher;
90-
if (watcher) {
91-
this.compiler.modifiedFiles = watcher.aggregatedChanges;
92-
this.compiler.removedFiles = watcher.aggregatedRemovals;
93-
this.compiler.fileTimestamps = watcher.getFileTimeInfoEntries();
94-
this.compiler.contextTimestamps = watcher.getContextTimeInfoEntries();
95-
} else {
96-
this.compiler.modifiedFiles = undefined;
97-
this.compiler.removedFiles = undefined;
98-
this.compiler.fileTimestamps = undefined;
99-
this.compiler.contextTimestamps = undefined;
100-
}
101-
}
10286
this.compiler.hooks.watchRun.callAsync(this.compiler, err => {
10387
if (err) return this._done(err);
10488
const onCompiled = (err, compilation) => {
@@ -277,6 +261,11 @@ class Watching {
277261
this.compiler.contextTimestamps = contextTimeInfoEntries;
278262
this.compiler.removedFiles = removedFiles;
279263
this.compiler.modifiedFiles = changedFiles;
264+
if (this.watcher) {
265+
this.pausedWatcher = this.watcher;
266+
this.watcher.pause();
267+
this.watcher = null;
268+
}
280269
this._invalidate();
281270
this._onChange();
282271
},
@@ -297,7 +286,6 @@ class Watching {
297286
}
298287
if (!this._initial) {
299288
this.compiler.hooks.invalid.call(null, Date.now());
300-
this._needWatcherInfo = true;
301289
}
302290
this._invalidate();
303291
}
@@ -309,6 +297,14 @@ class Watching {
309297
return;
310298
}
311299
if (this.watcher) {
300+
this.compiler.modifiedFiles =
301+
this.watcher.getAggregatedChanges &&
302+
this.watcher.getAggregatedChanges();
303+
this.compiler.removedFiles =
304+
this.watcher.getAggregatedRemovals &&
305+
this.watcher.getAggregatedRemovals();
306+
this.compiler.fileTimestamps = this.watcher.getFileTimeInfoEntries();
307+
this.compiler.contextTimestamps = this.watcher.getContextTimeInfoEntries();
312308
this.pausedWatcher = this.watcher;
313309
this.watcher.pause();
314310
this.watcher = null;
@@ -328,7 +324,6 @@ class Watching {
328324
resume() {
329325
if (this.suspended) {
330326
this.suspended = false;
331-
this._needWatcherInfo = true;
332327
this._invalidate();
333328
}
334329
}

lib/node/NodeWatchFileSystem.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,12 @@ class NodeWatchFileSystem {
9898
this.watcher.pause();
9999
}
100100
},
101+
getAggregatedRemovals: () => {
102+
return this.watcher && this.watcher.aggregatedRemovals;
103+
},
104+
getAggregatedChanges: () => {
105+
return this.watcher && this.watcher.aggregatedChanges;
106+
},
101107
getFileTimeInfoEntries: () => {
102108
if (this.watcher) {
103109
return this.watcher.getTimeInfoEntries();

lib/util/fs.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ const path = require("path");
6464
* @typedef {Object} Watcher
6565
* @property {function(): void} close closes the watcher and all underlying file watchers
6666
* @property {function(): void} pause closes the watcher, but keeps underlying file watchers alive until the next watch call
67+
* @property {function(): Set<string>=} getAggregatedChanges get current aggregated changes that have not yet send to callback
68+
* @property {function(): Set<string>=} getAggregatedRemovals get current aggregated removals that have not yet send to callback
6769
* @property {function(): Map<string, FileSystemInfoEntry | "ignore">} getFileTimeInfoEntries get info about files
6870
* @property {function(): Map<string, FileSystemInfoEntry | "ignore">} getContextTimeInfoEntries get info about directories
6971
*/

test/MultiCompiler.test.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,8 @@ describe("MultiCompiler", function () {
270270
c:
271271
c compiled successfully"
272272
`);
273+
expect(compiler.compilers[0].modifiedFiles).toBe(undefined);
274+
expect(compiler.compilers[0].removedFiles).toBe(undefined);
273275
expect(events).toMatchInlineSnapshot(`
274276
Array [
275277
"b run",
@@ -295,6 +297,8 @@ describe("MultiCompiler", function () {
295297
b:
296298
b compiled successfully"
297299
`);
300+
expect(compiler.compilers[1].modifiedFiles).toEqual(new Set());
301+
expect(compiler.compilers[1].removedFiles).toEqual(new Set());
298302
expect(events).toMatchInlineSnapshot(`
299303
Array [
300304
"b run",

types.d.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10786,6 +10786,16 @@ declare interface Watcher {
1078610786
*/
1078710787
pause: () => void;
1078810788

10789+
/**
10790+
* get current aggregated changes that have not yet send to callback
10791+
*/
10792+
getAggregatedChanges?: () => Set<string>;
10793+
10794+
/**
10795+
* get current aggregated removals that have not yet send to callback
10796+
*/
10797+
getAggregatedRemovals?: () => Set<string>;
10798+
1078910799
/**
1079010800
* get info about files
1079110801
*/

0 commit comments

Comments
 (0)