fix some incorrect properties accesses

fix some edge cases with MultiCompiler

fixes #12770
This commit is contained in:
Tobias Koppers 2021-02-24 20:12:32 +01:00
parent 3849f45961
commit 1ebc7ca974
6 changed files with 65 additions and 31 deletions

View File

@ -350,6 +350,12 @@ module.exports = class MultiCompiler {
let errored = false;
let running = 0;
const parallelism = this._options.parallelism;
/**
* @param {Node} node node
* @param {Error=} err error
* @param {Stats=} stats result
* @returns {void}
*/
const nodeDone = (node, err, stats) => {
if (errored) return;
if (err) {
@ -367,27 +373,35 @@ module.exports = class MultiCompiler {
);
}
node.result = stats;
running--;
if (node.state === "running") {
running--;
node.state = "done";
for (const child of node.children) {
if (child.state !== "blocked") continue;
if (child.parents.every(p => p.state === "done")) {
child.state = "queued";
queue.enqueue(child);
}
}
process.nextTick(processQueue);
}
for (const child of node.children) {
if (child.state !== "blocked") continue;
if (child.parents.every(p => p.state === "done")) {
child.state = "queued";
queue.enqueue(child);
}
}
process.nextTick(processQueue);
};
/**
* @param {Node} node node
* @returns {void}
*/
const nodeInvalid = node => {
if (node.state === "done") {
if (node.state === "done" || node.state === "running") {
node.state = "blocked";
for (const child of node.children) {
nodeInvalid(child);
}
}
for (const child of node.children) {
nodeInvalid(child);
}
};
/**
* @param {Node} node node
* @returns {void}
*/
const nodeChange = node => {
nodeInvalid(node);
if (
@ -415,6 +429,7 @@ module.exports = class MultiCompiler {
const processQueue = () => {
while (running < parallelism && queue.length > 0 && !errored) {
const node = queue.dequeue();
if (node.state !== "queued") continue;
running++;
node.state = "running";
run(node.compiler, nodeDone.bind(null, node));
@ -446,6 +461,7 @@ module.exports = class MultiCompiler {
if (this.running) {
return handler(new ConcurrentCompilationError());
}
this.running = true;
if (this.validateDependencies(handler)) {
const watchings = this._runGraph(
@ -480,6 +496,7 @@ module.exports = class MultiCompiler {
if (this.running) {
return callback(new ConcurrentCompilationError());
}
this.running = true;
if (this.validateDependencies(callback)) {
this._runGraph(

View File

@ -54,7 +54,6 @@ class Watching {
this.running = false;
this._initial = true;
this._needRecords = true;
this._needWatcherInfo = false;
this.watcher = undefined;
this.pausedWatcher = undefined;
this._done = this._done.bind(this);
@ -84,21 +83,6 @@ class Watching {
});
}
this.invalid = false;
if (this._needWatcherInfo) {
this._needWatcherInfo = false;
const watcher = this.pausedWatcher;
if (watcher) {
this.compiler.modifiedFiles = watcher.aggregatedChanges;
this.compiler.removedFiles = watcher.aggregatedRemovals;
this.compiler.fileTimestamps = watcher.getFileTimeInfoEntries();
this.compiler.contextTimestamps = watcher.getContextTimeInfoEntries();
} else {
this.compiler.modifiedFiles = undefined;
this.compiler.removedFiles = undefined;
this.compiler.fileTimestamps = undefined;
this.compiler.contextTimestamps = undefined;
}
}
this.compiler.hooks.watchRun.callAsync(this.compiler, err => {
if (err) return this._done(err);
const onCompiled = (err, compilation) => {
@ -277,6 +261,11 @@ class Watching {
this.compiler.contextTimestamps = contextTimeInfoEntries;
this.compiler.removedFiles = removedFiles;
this.compiler.modifiedFiles = changedFiles;
if (this.watcher) {
this.pausedWatcher = this.watcher;
this.watcher.pause();
this.watcher = null;
}
this._invalidate();
this._onChange();
},
@ -297,7 +286,6 @@ class Watching {
}
if (!this._initial) {
this.compiler.hooks.invalid.call(null, Date.now());
this._needWatcherInfo = true;
}
this._invalidate();
}
@ -309,6 +297,14 @@ class Watching {
return;
}
if (this.watcher) {
this.compiler.modifiedFiles =
this.watcher.getAggregatedChanges &&
this.watcher.getAggregatedChanges();
this.compiler.removedFiles =
this.watcher.getAggregatedRemovals &&
this.watcher.getAggregatedRemovals();
this.compiler.fileTimestamps = this.watcher.getFileTimeInfoEntries();
this.compiler.contextTimestamps = this.watcher.getContextTimeInfoEntries();
this.pausedWatcher = this.watcher;
this.watcher.pause();
this.watcher = null;
@ -328,7 +324,6 @@ class Watching {
resume() {
if (this.suspended) {
this.suspended = false;
this._needWatcherInfo = true;
this._invalidate();
}
}

View File

@ -98,6 +98,12 @@ class NodeWatchFileSystem {
this.watcher.pause();
}
},
getAggregatedRemovals: () => {
return this.watcher && this.watcher.aggregatedRemovals;
},
getAggregatedChanges: () => {
return this.watcher && this.watcher.aggregatedChanges;
},
getFileTimeInfoEntries: () => {
if (this.watcher) {
return this.watcher.getTimeInfoEntries();

View File

@ -64,6 +64,8 @@ const path = require("path");
* @typedef {Object} Watcher
* @property {function(): void} close closes the watcher and all underlying file watchers
* @property {function(): void} pause closes the watcher, but keeps underlying file watchers alive until the next watch call
* @property {function(): Set<string>=} getAggregatedChanges get current aggregated changes that have not yet send to callback
* @property {function(): Set<string>=} getAggregatedRemovals get current aggregated removals that have not yet send to callback
* @property {function(): Map<string, FileSystemInfoEntry | "ignore">} getFileTimeInfoEntries get info about files
* @property {function(): Map<string, FileSystemInfoEntry | "ignore">} getContextTimeInfoEntries get info about directories
*/

View File

@ -270,6 +270,8 @@ describe("MultiCompiler", function () {
c:
c compiled successfully"
`);
expect(compiler.compilers[0].modifiedFiles).toBe(undefined);
expect(compiler.compilers[0].removedFiles).toBe(undefined);
expect(events).toMatchInlineSnapshot(`
Array [
"b run",
@ -295,6 +297,8 @@ describe("MultiCompiler", function () {
b:
b compiled successfully"
`);
expect(compiler.compilers[1].modifiedFiles).toEqual(new Set());
expect(compiler.compilers[1].removedFiles).toEqual(new Set());
expect(events).toMatchInlineSnapshot(`
Array [
"b run",

10
types.d.ts vendored
View File

@ -10786,6 +10786,16 @@ declare interface Watcher {
*/
pause: () => void;
/**
* get current aggregated changes that have not yet send to callback
*/
getAggregatedChanges?: () => Set<string>;
/**
* get current aggregated removals that have not yet send to callback
*/
getAggregatedRemovals?: () => Set<string>;
/**
* get info about files
*/