Skip to content

Commit 0975d13

Browse files
committed
assign correct cache to child compilation
fixes webpack-contrib/extract-text-webpack-plugin#612
1 parent cc03d8e commit 0975d13

File tree

9 files changed

+159
-91
lines changed

9 files changed

+159
-91
lines changed

lib/CachePlugin.js

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,37 @@ class CachePlugin {
1313
}
1414

1515
apply(compiler) {
16+
const cacheMap = new Map();
17+
cacheMap.set(compiler, this.cache);
1618
if(Array.isArray(compiler.compilers)) {
1719
compiler.compilers.forEach((c, idx) => {
1820
c.apply(new CachePlugin(this.cache[idx] = this.cache[idx] || {}));
1921
});
2022
} else {
21-
compiler.plugin("compilation", compilation => {
22-
if(!compilation.notCacheable) {
23-
compilation.cache = this.cache;
24-
} else if(this.watching) {
25-
compilation.warnings.push(
26-
new Error(`CachePlugin - Cache cannot be used because of: ${compilation.notCacheable}`)
27-
);
28-
}
29-
});
23+
const registerCacheToCompiler = (compiler, cache) => {
24+
compiler.plugin("this-compilation", compilation => {
25+
if(!compilation.notCacheable) {
26+
compilation.cache = cache;
27+
compilation.plugin("child-compiler", (childCompiler, compilerName, compilerIndex) => {
28+
if(cache) {
29+
let childCache;
30+
if(!cache.children) cache.children = {};
31+
if(!cache.children[compilerName]) cache.children[compilerName] = [];
32+
if(cache.children[compilerName][compilerIndex])
33+
childCache = cache.children[compilerName][compilerIndex];
34+
else
35+
cache.children[compilerName].push(childCache = {});
36+
registerCacheToCompiler(childCompiler, childCache);
37+
}
38+
});
39+
} else if(this.watching) {
40+
compilation.warnings.push(
41+
new Error(`CachePlugin - Cache cannot be used because of: ${compilation.notCacheable}`)
42+
);
43+
}
44+
});
45+
};
46+
registerCacheToCompiler(compiler, this.cache);
3047
compiler.plugin("watch-run", (compiler, callback) => {
3148
this.watching = true;
3249
callback();

lib/Compiler.js

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -438,21 +438,15 @@ class Compiler extends Tapable {
438438
else
439439
this.records[relativeCompilerName].push(childCompiler.records = {});
440440

441-
if(this.cache) {
442-
if(!this.cache.children) this.cache.children = {};
443-
if(!this.cache.children[compilerName]) this.cache.children[compilerName] = [];
444-
if(this.cache.children[compilerName][compilerIndex])
445-
childCompiler.cache = this.cache.children[compilerName][compilerIndex];
446-
else
447-
this.cache.children[compilerName].push(childCompiler.cache = {});
448-
}
449-
450441
childCompiler.options = Object.create(this.options);
451442
childCompiler.options.output = Object.create(childCompiler.options.output);
452443
for(const name in outputOptions) {
453444
childCompiler.options.output[name] = outputOptions[name];
454445
}
455446
childCompiler.parentCompilation = compilation;
447+
448+
compilation.applyPlugins("child-compiler", childCompiler, compilerName, compilerIndex);
449+
456450
return childCompiler;
457451
}
458452

test/WatchTestCases.test.js

Lines changed: 88 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -108,89 +108,104 @@ describe("WatchTestCases", () => {
108108

109109
const state = {};
110110
let runIdx = 0;
111+
let waitMode = false;
111112
let run = runs[runIdx];
113+
let triggeringFilename;
112114
let lastHash = "";
115+
const currentWatchStepModule = require("./helpers/currentWatchStep");
116+
currentWatchStepModule.step = run.name;
113117
copyDiff(path.join(testDirectory, run.name), tempDirectory);
114118

115-
const compiler = webpack(options);
116-
const watching = compiler.watch({
117-
aggregateTimeout: 1000
118-
}, (err, stats) => {
119-
if(err)
120-
return done(err);
121-
if(!stats)
122-
return done(new Error("No stats reported from Compiler"));
123-
if(stats.hash === lastHash)
124-
return;
125-
lastHash = stats.hash;
126-
if(run.done)
127-
return done(new Error("Compilation changed but no change was issued " + lastHash + " != " + stats.hash + " (run " + runIdx + ")"));
128-
run.done = true;
129-
if(err) return done(err);
130-
const statOptions = Stats.presetToOptions("verbose");
131-
statOptions.colors = false;
132-
fs.writeFileSync(path.join(outputDirectory, "stats.txt"), stats.toString(statOptions), "utf-8");
133-
const jsonStats = stats.toJson({
134-
errorDetails: true
119+
setTimeout(() => {
120+
const compiler = webpack(options);
121+
compiler.plugin("invalid", (filename, mtime) => {
122+
triggeringFilename = filename;
135123
});
136-
if(checkArrayExpectation(path.join(testDirectory, run.name), jsonStats, "error", "Error", done)) return;
137-
if(checkArrayExpectation(path.join(testDirectory, run.name), jsonStats, "warning", "Warning", done)) return;
138-
let exportedTests = 0;
124+
const watching = compiler.watch({
125+
aggregateTimeout: 1000
126+
}, (err, stats) => {
127+
if(err)
128+
return done(err);
129+
if(!stats)
130+
return done(new Error("No stats reported from Compiler"));
131+
if(stats.hash === lastHash)
132+
return;
133+
lastHash = stats.hash;
134+
if(run.done && lastHash !== stats.hash) {
135+
return done(new Error("Compilation changed but no change was issued " + lastHash + " != " + stats.hash + " (run " + runIdx + ")\n" +
136+
"Triggering change: " + triggeringFilename));
137+
}
138+
if(waitMode) return;
139+
run.done = true;
140+
if(err) return done(err);
141+
const statOptions = Stats.presetToOptions("verbose");
142+
statOptions.colors = false;
143+
fs.writeFileSync(path.join(outputDirectory, "stats.txt"), stats.toString(statOptions), "utf-8");
144+
const jsonStats = stats.toJson({
145+
errorDetails: true
146+
});
147+
if(checkArrayExpectation(path.join(testDirectory, run.name), jsonStats, "error", "Error", done)) return;
148+
if(checkArrayExpectation(path.join(testDirectory, run.name), jsonStats, "warning", "Warning", done)) return;
149+
let exportedTests = 0;
139150

140-
function _it(title, fn) {
141-
const test = new Test(title, fn);
142-
run.suite.addTest(test);
143-
exportedTests++;
144-
return test;
145-
}
151+
function _it(title, fn) {
152+
const test = new Test(title, fn);
153+
run.suite.addTest(test);
154+
exportedTests++;
155+
return test;
156+
}
146157

147-
function _require(currentDirectory, module) {
148-
if(Array.isArray(module) || /^\.\.?\//.test(module)) {
149-
let fn;
150-
let content;
151-
let p;
152-
if(Array.isArray(module)) {
153-
p = path.join(currentDirectory, module[0]);
154-
content = module.map((arg) => {
155-
p = path.join(currentDirectory, arg);
156-
return fs.readFileSync(p, "utf-8");
157-
}).join("\n");
158-
} else {
159-
p = path.join(currentDirectory, module);
160-
content = fs.readFileSync(p, "utf-8");
161-
}
162-
fn = vm.runInThisContext("(function(require, module, exports, __dirname, __filename, it, WATCH_STEP, STATS_JSON, STATE) {" + content + "\n})", p);
163-
const m = {
164-
exports: {}
165-
};
166-
fn.call(m.exports, _require.bind(null, path.dirname(p)), m, m.exports, path.dirname(p), p, _it, run.name, jsonStats, state);
167-
return module.exports;
168-
} else if(testConfig.modules && module in testConfig.modules) {
169-
return testConfig.modules[module];
170-
} else return require(module);
171-
}
158+
function _require(currentDirectory, module) {
159+
if(Array.isArray(module) || /^\.\.?\//.test(module)) {
160+
let fn;
161+
let content;
162+
let p;
163+
if(Array.isArray(module)) {
164+
p = path.join(currentDirectory, module[0]);
165+
content = module.map((arg) => {
166+
p = path.join(currentDirectory, arg);
167+
return fs.readFileSync(p, "utf-8");
168+
}).join("\n");
169+
} else {
170+
p = path.join(currentDirectory, module);
171+
content = fs.readFileSync(p, "utf-8");
172+
}
173+
fn = vm.runInThisContext("(function(require, module, exports, __dirname, __filename, it, WATCH_STEP, STATS_JSON, STATE) {" + content + "\n})", p);
174+
const m = {
175+
exports: {}
176+
};
177+
fn.call(m.exports, _require.bind(null, path.dirname(p)), m, m.exports, path.dirname(p), p, _it, run.name, jsonStats, state);
178+
return module.exports;
179+
} else if(testConfig.modules && module in testConfig.modules) {
180+
return testConfig.modules[module];
181+
} else return require(module);
182+
}
172183

173-
let testConfig = {};
174-
try {
175-
// try to load a test file
176-
testConfig = require(path.join(testDirectory, "test.config.js"));
177-
} catch(e) {}
184+
let testConfig = {};
185+
try {
186+
// try to load a test file
187+
testConfig = require(path.join(testDirectory, "test.config.js"));
188+
} catch(e) {}
178189

179-
if(testConfig.noTests) return process.nextTick(done);
180-
_require(outputDirectory, "./bundle.js");
190+
if(testConfig.noTests) return process.nextTick(done);
191+
_require(outputDirectory, "./bundle.js");
181192

182-
if(exportedTests < 1) return done(new Error("No tests exported by test case"));
183-
runIdx++;
184-
if(runIdx < runs.length) {
185-
run = runs[runIdx];
186-
setTimeout(() => {
187-
copyDiff(path.join(testDirectory, run.name), tempDirectory);
188-
}, 1500);
189-
} else {
190-
watching.close();
191-
process.nextTick(done);
192-
}
193-
});
193+
if(exportedTests < 1) return done(new Error("No tests exported by test case"));
194+
runIdx++;
195+
if(runIdx < runs.length) {
196+
run = runs[runIdx];
197+
waitMode = true;
198+
setTimeout(() => {
199+
waitMode = false;
200+
currentWatchStepModule.step = run.name;
201+
copyDiff(path.join(testDirectory, run.name), tempDirectory);
202+
}, 1500);
203+
} else {
204+
watching.close();
205+
process.nextTick(done);
206+
}
207+
});
208+
}, 300);
194209
});
195210
});
196211
});

test/helpers/currentWatchStep.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
exports.step = undefined;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
123
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
it("should use correct caches in compilation and child compilations", function() {
2+
var x = require("./report-cache-counters-loader!./changing-file");
3+
switch(WATCH_STEP) {
4+
case "0":
5+
x.should.be.eql([1, 1]);
6+
break;
7+
case "1":
8+
x.should.be.eql([2, 1]);
9+
break;
10+
case "2":
11+
x.should.be.eql([3, 2]);
12+
break;
13+
default:
14+
throw new Error("Not handled step");
15+
}
16+
});
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
var map = new Map();
2+
var currentWatchStepModule = require("../../../../helpers/currentWatchStep");
3+
4+
module.exports = function(source) {
5+
if(map.has(currentWatchStepModule.step)) return map.get(currentWatchStepModule.step);
6+
this._compilation.cache.counter = (this._compilation.cache.counter || 0) + 1;
7+
8+
var childCompiler = this._compilation.createChildCompiler("my-compiler " + source.trim(), {
9+
filename: "test"
10+
});
11+
var callback = this.async();
12+
childCompiler.runAsChild((err, entries, compilation) => {
13+
if(err) return callback(err);
14+
15+
var childCache = compilation.cache;
16+
childCache.counter = (childCache.counter || 0) + 1;
17+
18+
var result = `module.exports = [${this._compilation.cache.counter}, ${childCache.counter}]; // ${source}`;
19+
map.set(currentWatchStepModule.step, result);
20+
callback(null, result);
21+
});
22+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
456
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
123

0 commit comments

Comments
 (0)