Skip to content

Commit 9f60f50

Browse files
committed
Prevent multi compiler from running twice at a time
1 parent e225d10 commit 9f60f50

File tree

3 files changed

+136
-5
lines changed

3 files changed

+136
-5
lines changed

lib/MultiCompiler.js

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ module.exports = class MultiCompiler extends Tapable {
5353
}
5454
});
5555
}
56+
this.running = false;
5657
}
5758

5859
get outputPath() {
@@ -185,10 +186,24 @@ module.exports = class MultiCompiler extends Tapable {
185186
}
186187

187188
watch(watchOptions, handler) {
189+
if (this.running)
190+
return handler(
191+
new Error(
192+
"You ran Webpack twice. Each instance only supports a single concurrent compilation at a time."
193+
)
194+
);
195+
196+
const finalHandler = (err, stats) => {
197+
this.running = false;
198+
199+
if (handler !== undefined) handler(err, stats);
200+
};
201+
188202
let watchings = [];
189203
let allStats = this.compilers.map(() => null);
190204
let compilerStatus = this.compilers.map(() => false);
191-
if (this.validateDependencies(handler)) {
205+
if (this.validateDependencies(finalHandler)) {
206+
this.running = true;
192207
this.runWithDependencies(
193208
this.compilers,
194209
(compiler, callback) => {
@@ -199,7 +214,7 @@ module.exports = class MultiCompiler extends Tapable {
199214
? watchOptions[compilerIdx]
200215
: watchOptions,
201216
(err, stats) => {
202-
if (err) handler(err);
217+
if (err) finalHandler(err);
203218
if (stats) {
204219
allStats[compilerIdx] = stats;
205220
compilerStatus[compilerIdx] = "new";
@@ -209,7 +224,7 @@ module.exports = class MultiCompiler extends Tapable {
209224
});
210225
compilerStatus.fill(true);
211226
const multiStats = new MultiStats(freshStats);
212-
handler(null, multiStats);
227+
finalHandler(null, multiStats);
213228
}
214229
}
215230
if (firstRun && !err) {
@@ -230,8 +245,22 @@ module.exports = class MultiCompiler extends Tapable {
230245
}
231246

232247
run(callback) {
248+
if (this.running)
249+
return callback(
250+
new Error(
251+
"You ran Webpack twice. Each instance only supports a single concurrent compilation at a time."
252+
)
253+
);
254+
255+
const finalCallback = (err, stats) => {
256+
this.running = false;
257+
258+
if (callback !== undefined) return callback(err, stats);
259+
};
260+
233261
const allStats = this.compilers.map(() => null);
234262
if (this.validateDependencies(callback)) {
263+
this.running = true;
235264
this.runWithDependencies(
236265
this.compilers,
237266
(compiler, callback) => {
@@ -243,8 +272,8 @@ module.exports = class MultiCompiler extends Tapable {
243272
});
244273
},
245274
err => {
246-
if (err) return callback(err);
247-
callback(null, new MultiStats(allStats));
275+
if (err) return finalCallback(err);
276+
finalCallback(null, new MultiStats(allStats));
248277
}
249278
);
250279
}

lib/MultiWatching.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class MultiWatching {
2727
err => {
2828
this.compiler.hooks.watchClose.call();
2929
if (typeof callback === "function") {
30+
this.compiler.running = false;
3031
callback(err);
3132
}
3233
}

test/MultiCompiler.test.js

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,105 @@ describe("MultiCompiler", function() {
5252
}
5353
});
5454
});
55+
56+
it("should not be run twice at a time (run)", function(done) {
57+
const compiler = createMultiCompiler();
58+
compiler.run((err, stats) => {
59+
if (err) return done(err);
60+
});
61+
compiler.run((err, stats) => {
62+
if (err) return done();
63+
});
64+
});
65+
it("should not be run twice at a time (watch)", function(done) {
66+
const compiler = createMultiCompiler();
67+
compiler.watch({}, (err, stats) => {
68+
if (err) return done(err);
69+
});
70+
compiler.watch({}, (err, stats) => {
71+
if (err) return done();
72+
});
73+
});
74+
it("should not be run twice at a time (run - watch)", function(done) {
75+
const compiler = createMultiCompiler();
76+
compiler.run((err, stats) => {
77+
if (err) return done(err);
78+
});
79+
compiler.watch({}, (err, stats) => {
80+
if (err) return done();
81+
});
82+
});
83+
it("should not be run twice at a time (watch - run)", function(done) {
84+
const compiler = createMultiCompiler();
85+
compiler.watch({}, (err, stats) => {
86+
if (err) return done(err);
87+
});
88+
compiler.run((err, stats) => {
89+
if (err) return done();
90+
});
91+
});
92+
it("should not be run twice at a time (instance cb)", function(done) {
93+
const compiler = webpack(
94+
{
95+
context: __dirname,
96+
mode: "production",
97+
entry: "./c",
98+
output: {
99+
path: "/",
100+
filename: "bundle.js"
101+
}
102+
},
103+
() => {}
104+
);
105+
compiler.outputFileSystem = new MemoryFs();
106+
compiler.run((err, stats) => {
107+
if (err) return done();
108+
});
109+
});
110+
it("should run again correctly after first compilation", function(done) {
111+
const compiler = createMultiCompiler();
112+
compiler.run((err, stats) => {
113+
if (err) return done(err);
114+
115+
compiler.run((err, stats) => {
116+
if (err) return done(err);
117+
done();
118+
});
119+
});
120+
});
121+
it("should watch again correctly after first compilation", function(done) {
122+
const compiler = createMultiCompiler();
123+
compiler.run((err, stats) => {
124+
if (err) return done(err);
125+
126+
compiler.watch({}, (err, stats) => {
127+
if (err) return done(err);
128+
done();
129+
});
130+
});
131+
});
132+
it("should run again correctly after first closed watch", function(done) {
133+
const compiler = createMultiCompiler();
134+
const watching = compiler.watch({}, (err, stats) => {
135+
if (err) return done(err);
136+
});
137+
watching.close(() => {
138+
compiler.run((err, stats) => {
139+
if (err) return done(err);
140+
done();
141+
});
142+
});
143+
});
144+
it("should watch again correctly after first closed watch", function(done) {
145+
const compiler = createMultiCompiler();
146+
const watching = compiler.watch({}, (err, stats) => {
147+
if (err) return done(err);
148+
});
149+
watching.close(() => {
150+
compiler.watch({}, (err, stats) => {
151+
if (err) return done(err);
152+
done();
153+
});
154+
});
155+
});
55156
});

0 commit comments

Comments
 (0)