Skip to content

Commit

Permalink
assign correct cache to child compilation
Browse files Browse the repository at this point in the history
  • Loading branch information
sokra committed Sep 13, 2017
1 parent cc03d8e commit 0975d13
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 91 deletions.
35 changes: 26 additions & 9 deletions lib/CachePlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,37 @@ class CachePlugin {
}

apply(compiler) {
const cacheMap = new Map();
cacheMap.set(compiler, this.cache);
if(Array.isArray(compiler.compilers)) {
compiler.compilers.forEach((c, idx) => {
c.apply(new CachePlugin(this.cache[idx] = this.cache[idx] || {}));
});
} else {
compiler.plugin("compilation", compilation => {
if(!compilation.notCacheable) {
compilation.cache = this.cache;
} else if(this.watching) {
compilation.warnings.push(
new Error(`CachePlugin - Cache cannot be used because of: ${compilation.notCacheable}`)
);
}
});
const registerCacheToCompiler = (compiler, cache) => {
compiler.plugin("this-compilation", compilation => {
if(!compilation.notCacheable) {
compilation.cache = cache;
compilation.plugin("child-compiler", (childCompiler, compilerName, compilerIndex) => {
if(cache) {
let childCache;
if(!cache.children) cache.children = {};
if(!cache.children[compilerName]) cache.children[compilerName] = [];
if(cache.children[compilerName][compilerIndex])
childCache = cache.children[compilerName][compilerIndex];
else
cache.children[compilerName].push(childCache = {});
registerCacheToCompiler(childCompiler, childCache);
}
});
} else if(this.watching) {
compilation.warnings.push(
new Error(`CachePlugin - Cache cannot be used because of: ${compilation.notCacheable}`)
);
}
});
};
registerCacheToCompiler(compiler, this.cache);
compiler.plugin("watch-run", (compiler, callback) => {
this.watching = true;
callback();
Expand Down
12 changes: 3 additions & 9 deletions lib/Compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -438,21 +438,15 @@ class Compiler extends Tapable {
else
this.records[relativeCompilerName].push(childCompiler.records = {});

if(this.cache) {
if(!this.cache.children) this.cache.children = {};
if(!this.cache.children[compilerName]) this.cache.children[compilerName] = [];
if(this.cache.children[compilerName][compilerIndex])
childCompiler.cache = this.cache.children[compilerName][compilerIndex];
else
this.cache.children[compilerName].push(childCompiler.cache = {});
}

childCompiler.options = Object.create(this.options);
childCompiler.options.output = Object.create(childCompiler.options.output);
for(const name in outputOptions) {
childCompiler.options.output[name] = outputOptions[name];
}
childCompiler.parentCompilation = compilation;

compilation.applyPlugins("child-compiler", childCompiler, compilerName, compilerIndex);

return childCompiler;
}

Expand Down
161 changes: 88 additions & 73 deletions test/WatchTestCases.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,89 +108,104 @@ describe("WatchTestCases", () => {

const state = {};
let runIdx = 0;
let waitMode = false;
let run = runs[runIdx];
let triggeringFilename;
let lastHash = "";
const currentWatchStepModule = require("./helpers/currentWatchStep");
currentWatchStepModule.step = run.name;
copyDiff(path.join(testDirectory, run.name), tempDirectory);

const compiler = webpack(options);
const watching = compiler.watch({
aggregateTimeout: 1000
}, (err, stats) => {
if(err)
return done(err);
if(!stats)
return done(new Error("No stats reported from Compiler"));
if(stats.hash === lastHash)
return;
lastHash = stats.hash;
if(run.done)
return done(new Error("Compilation changed but no change was issued " + lastHash + " != " + stats.hash + " (run " + runIdx + ")"));
run.done = true;
if(err) return done(err);
const statOptions = Stats.presetToOptions("verbose");
statOptions.colors = false;
fs.writeFileSync(path.join(outputDirectory, "stats.txt"), stats.toString(statOptions), "utf-8");
const jsonStats = stats.toJson({
errorDetails: true
setTimeout(() => {
const compiler = webpack(options);
compiler.plugin("invalid", (filename, mtime) => {
triggeringFilename = filename;
});
if(checkArrayExpectation(path.join(testDirectory, run.name), jsonStats, "error", "Error", done)) return;
if(checkArrayExpectation(path.join(testDirectory, run.name), jsonStats, "warning", "Warning", done)) return;
let exportedTests = 0;
const watching = compiler.watch({
aggregateTimeout: 1000
}, (err, stats) => {
if(err)
return done(err);
if(!stats)
return done(new Error("No stats reported from Compiler"));
if(stats.hash === lastHash)
return;
lastHash = stats.hash;
if(run.done && lastHash !== stats.hash) {
return done(new Error("Compilation changed but no change was issued " + lastHash + " != " + stats.hash + " (run " + runIdx + ")\n" +
"Triggering change: " + triggeringFilename));
}
if(waitMode) return;
run.done = true;
if(err) return done(err);
const statOptions = Stats.presetToOptions("verbose");
statOptions.colors = false;
fs.writeFileSync(path.join(outputDirectory, "stats.txt"), stats.toString(statOptions), "utf-8");
const jsonStats = stats.toJson({
errorDetails: true
});
if(checkArrayExpectation(path.join(testDirectory, run.name), jsonStats, "error", "Error", done)) return;
if(checkArrayExpectation(path.join(testDirectory, run.name), jsonStats, "warning", "Warning", done)) return;
let exportedTests = 0;

function _it(title, fn) {
const test = new Test(title, fn);
run.suite.addTest(test);
exportedTests++;
return test;
}
function _it(title, fn) {
const test = new Test(title, fn);
run.suite.addTest(test);
exportedTests++;
return test;
}

function _require(currentDirectory, module) {
if(Array.isArray(module) || /^\.\.?\//.test(module)) {
let fn;
let content;
let p;
if(Array.isArray(module)) {
p = path.join(currentDirectory, module[0]);
content = module.map((arg) => {
p = path.join(currentDirectory, arg);
return fs.readFileSync(p, "utf-8");
}).join("\n");
} else {
p = path.join(currentDirectory, module);
content = fs.readFileSync(p, "utf-8");
}
fn = vm.runInThisContext("(function(require, module, exports, __dirname, __filename, it, WATCH_STEP, STATS_JSON, STATE) {" + content + "\n})", p);
const m = {
exports: {}
};
fn.call(m.exports, _require.bind(null, path.dirname(p)), m, m.exports, path.dirname(p), p, _it, run.name, jsonStats, state);
return module.exports;
} else if(testConfig.modules && module in testConfig.modules) {
return testConfig.modules[module];
} else return require(module);
}
function _require(currentDirectory, module) {
if(Array.isArray(module) || /^\.\.?\//.test(module)) {
let fn;
let content;
let p;
if(Array.isArray(module)) {
p = path.join(currentDirectory, module[0]);
content = module.map((arg) => {
p = path.join(currentDirectory, arg);
return fs.readFileSync(p, "utf-8");
}).join("\n");
} else {
p = path.join(currentDirectory, module);
content = fs.readFileSync(p, "utf-8");
}
fn = vm.runInThisContext("(function(require, module, exports, __dirname, __filename, it, WATCH_STEP, STATS_JSON, STATE) {" + content + "\n})", p);
const m = {
exports: {}
};
fn.call(m.exports, _require.bind(null, path.dirname(p)), m, m.exports, path.dirname(p), p, _it, run.name, jsonStats, state);
return module.exports;
} else if(testConfig.modules && module in testConfig.modules) {
return testConfig.modules[module];
} else return require(module);
}

let testConfig = {};
try {
// try to load a test file
testConfig = require(path.join(testDirectory, "test.config.js"));
} catch(e) {}
let testConfig = {};
try {
// try to load a test file
testConfig = require(path.join(testDirectory, "test.config.js"));
} catch(e) {}

if(testConfig.noTests) return process.nextTick(done);
_require(outputDirectory, "./bundle.js");
if(testConfig.noTests) return process.nextTick(done);
_require(outputDirectory, "./bundle.js");

if(exportedTests < 1) return done(new Error("No tests exported by test case"));
runIdx++;
if(runIdx < runs.length) {
run = runs[runIdx];
setTimeout(() => {
copyDiff(path.join(testDirectory, run.name), tempDirectory);
}, 1500);
} else {
watching.close();
process.nextTick(done);
}
});
if(exportedTests < 1) return done(new Error("No tests exported by test case"));
runIdx++;
if(runIdx < runs.length) {
run = runs[runIdx];
waitMode = true;
setTimeout(() => {
waitMode = false;
currentWatchStepModule.step = run.name;
copyDiff(path.join(testDirectory, run.name), tempDirectory);
}, 1500);
} else {
watching.close();
process.nextTick(done);
}
});
}, 300);
});
});
});
Expand Down
1 change: 1 addition & 0 deletions test/helpers/currentWatchStep.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
exports.step = undefined;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
123
16 changes: 16 additions & 0 deletions test/watchCases/cache/child-compilation-cache/0/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
it("should use correct caches in compilation and child compilations", function() {
var x = require("./report-cache-counters-loader!./changing-file");
switch(WATCH_STEP) {
case "0":
x.should.be.eql([1, 1]);
break;
case "1":
x.should.be.eql([2, 1]);
break;
case "2":
x.should.be.eql([3, 2]);
break;
default:
throw new Error("Not handled step");
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
var map = new Map();
var currentWatchStepModule = require("../../../../helpers/currentWatchStep");

module.exports = function(source) {
if(map.has(currentWatchStepModule.step)) return map.get(currentWatchStepModule.step);
this._compilation.cache.counter = (this._compilation.cache.counter || 0) + 1;

var childCompiler = this._compilation.createChildCompiler("my-compiler " + source.trim(), {
filename: "test"
});
var callback = this.async();
childCompiler.runAsChild((err, entries, compilation) => {
if(err) return callback(err);

var childCache = compilation.cache;
childCache.counter = (childCache.counter || 0) + 1;

var result = `module.exports = [${this._compilation.cache.counter}, ${childCache.counter}]; // ${source}`;
map.set(currentWatchStepModule.step, result);
callback(null, result);
});
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
456
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
123

0 comments on commit 0975d13

Please sign in to comment.