From 8dcb90dbbdc5a70d3f4b6c6d19db18d5bb8d59eb Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Sat, 6 Mar 2021 12:07:57 +0100 Subject: [PATCH] avoid making the package.json in context a build dependency --- lib/SourceMapDevToolPlugin.js | 5 +- lib/config/defaults.js | 7 +- test/BuildDependencies.test.js | 121 ++++++++++++++++--------- test/fixtures/buildDependencies/run.js | 6 +- 4 files changed, 92 insertions(+), 47 deletions(-) diff --git a/lib/SourceMapDevToolPlugin.js b/lib/SourceMapDevToolPlugin.js index 6562ecc2626..4b26e1cb3e4 100644 --- a/lib/SourceMapDevToolPlugin.js +++ b/lib/SourceMapDevToolPlugin.js @@ -211,7 +211,10 @@ class SourceMapDevToolPlugin { } const cacheItem = cache.getItemCache( file, - cache.getLazyHashedEtag(asset.source) + cache.mergeEtags( + cache.getLazyHashedEtag(asset.source), + namespace + ) ); cacheItem.get((err, cacheEntry) => { diff --git a/lib/config/defaults.js b/lib/config/defaults.js index d45303d81e5..83725d7b24c 100644 --- a/lib/config/defaults.js +++ b/lib/config/defaults.js @@ -562,10 +562,15 @@ const applyOutputDefaults = ( F(output, "uniqueName", () => { const libraryName = getLibraryName(output.library); if (libraryName) return libraryName; + const pkgPath = path.resolve(context, "package.json"); try { - const packageInfo = require(`${context}/package.json`); + const packageInfo = JSON.parse(fs.readFileSync(pkgPath, "utf-8")); return packageInfo.name || ""; } catch (e) { + if (e.code !== "ENOENT") { + e.message += `\nwhile determining default 'output.uniqueName' from 'name' in ${pkgPath}`; + throw e; + } return ""; } }); diff --git a/test/BuildDependencies.test.js b/test/BuildDependencies.test.js index fcf227a4233..25c828a8eb5 100644 --- a/test/BuildDependencies.test.js +++ b/test/BuildDependencies.test.js @@ -50,6 +50,13 @@ describe("BuildDependencies", () => { fs.mkdir(inputDirectory, { recursive: true }, done); }); it("should capture loader and config dependencies", async () => { + fs.writeFileSync( + path.resolve(inputDirectory, "package.json"), + JSON.stringify({ + name: "yep", + version: "1.0.0" + }) + ); fs.writeFileSync( path.resolve(inputDirectory, "loader-dependency.js"), "module.exports = 0;" @@ -89,16 +96,32 @@ describe("BuildDependencies", () => { "module.exports = Date.now();" ); const now1 = Date.now(); - expect(await exec("2")).toMatch(/Captured build dependencies/); - expect(await exec("3")).not.toMatch(/Captured build dependencies/); + const output2 = await exec("2"); + expect(output2).toMatch(/but build dependencies have changed/); + expect(output2).toMatch(/Captured build dependencies/); + const output3 = await exec("3"); + expect(output3).not.toMatch(/resolving of build dependencies is invalid/); + expect(output3).not.toMatch(/but build dependencies have changed/); + expect(output3).not.toMatch(/Captured build dependencies/); + fs.writeFileSync( + path.resolve(inputDirectory, "package.json"), + JSON.stringify({ + name: "other", + version: "2.0.0" + }) + ); + const output4 = await exec("4"); + expect(output4).toMatch(/resolving of build dependencies is invalid/); + expect(output4).not.toMatch(/but build dependencies have changed/); + expect(output4).toMatch(/Captured build dependencies/); fs.writeFileSync( path.resolve(inputDirectory, "config-dependency"), "module.exports = Date.now();" ); const now2 = Date.now(); - await exec("4"); - const now3 = Date.now(); await exec("5"); + const now3 = Date.now(); + await exec("6"); let now4, now5; if (supportsEsm) { fs.writeFileSync( @@ -106,15 +129,15 @@ describe("BuildDependencies", () => { "module.exports = Date.now();" ); now4 = Date.now(); - await exec("6"); + await exec("7"); fs.writeFileSync( path.resolve(inputDirectory, "esm-async-dependency.mjs"), "export default Date.now();" ); now5 = Date.now(); - await exec("7"); + await exec("8"); } - const results = Array.from({ length: supportsEsm ? 8 : 6 }).map((_, i) => + const results = Array.from({ length: supportsEsm ? 9 : 7 }).map((_, i) => require(`./js/buildDeps/${i}/main.js`) ); for (const r of results) { @@ -122,46 +145,60 @@ describe("BuildDependencies", () => { expect(typeof r.config).toBe("number"); expect(typeof r.uncached).toBe("number"); } - expect(results[0].loader).toBe(0); - expect(results[0].config).toBe(0); - if (supportsEsm) expect(results[0].esmConfig).toBe(0); - expect(results[0].uncached).toBe(0); + let result = results.shift(); + expect(result.loader).toBe(0); + expect(result.config).toBe(0); + if (supportsEsm) expect(result.esmConfig).toBe(0); + expect(result.uncached).toBe(0); // 0 -> 1 should not cache at all because of invalid buildDeps - expect(results[1].loader).toBe(1); - expect(results[1].config).toBe(1); - expect(results[1].esmConfig).toBe(1); - expect(results[1].uncached).toBe(1); + result = results.shift(); + expect(result.loader).toBe(1); + expect(result.config).toBe(1); + expect(result.esmConfig).toBe(1); + expect(result.uncached).toBe(1); // 1 -> 2 should be invalidated - expect(results[2].loader).toBeGreaterThan(now1); - expect(results[2].config).toBe(1); - expect(results[2].esmConfig).toBe(1); - expect(results[2].uncached).toBe(1); + result = results.shift(); + expect(result.loader).toBeGreaterThan(now1); + expect(result.config).toBe(1); + expect(result.esmConfig).toBe(1); + expect(result.uncached).toBe(1); // 2 -> 3 should stay cached - expect(results[3].loader).toBe(results[2].loader); - expect(results[3].config).toBe(1); - expect(results[3].esmConfig).toBe(1); - expect(results[3].uncached).toBe(1); - // 3 -> 4 should be invalidated - expect(results[4].loader).toBeGreaterThan(now2); - expect(results[4].config).toBeGreaterThan(now2); - expect(results[4].esmConfig).toBe(1); - expect(results[4].uncached).toBe(results[4].config); - // 4 -> 5 should stay cached, but uncacheable module still rebuilds - expect(results[5].loader).toBe(results[4].loader); - expect(results[5].config).toBe(results[4].config); - expect(results[5].uncached).toBeGreaterThan(now3); + result = results.shift(); + expect(result.loader).toBe(result.loader); + expect(result.config).toBe(1); + expect(result.esmConfig).toBe(1); + expect(result.uncached).toBe(1); + // 3 -> 4 should stay cached + result = results.shift(); + expect(result.loader).toBe(result.loader); + expect(result.config).toBe(1); + expect(result.esmConfig).toBe(1); + expect(result.uncached).toBe(1); + // 4 -> 5 should be invalidated + result = results.shift(); + expect(result.loader).toBeGreaterThan(now2); + expect(result.config).toBeGreaterThan(now2); + expect(result.esmConfig).toBe(1); + expect(result.uncached).toBe(result.config); + // 5 -> 6 should stay cached, but uncacheable module still rebuilds + result = results.shift(); + expect(result.loader).toBe(result.loader); + expect(result.config).toBe(result.config); + expect(result.uncached).toBeGreaterThan(now3); if (supportsEsm) { - // 5 -> 6 should be invalidated - expect(results[6].loader).toBeGreaterThan(now4); - expect(results[6].config).toBeGreaterThan(now4); - expect(results[6].esmConfig).toBeGreaterThan(now4); - expect(results[6].uncached).toBeGreaterThan(now4); // 6 -> 7 should be invalidated - expect(results[7].loader).toBeGreaterThan(now5); - expect(results[7].config).toBeGreaterThan(now5); - expect(results[7].esmConfig).toBeGreaterThan(now5); - expect(results[7].esmAsyncConfig).toBeGreaterThan(now5); - expect(results[7].uncached).toBeGreaterThan(now5); + result = results.shift(); + expect(result.loader).toBeGreaterThan(now4); + expect(result.config).toBeGreaterThan(now4); + expect(result.esmConfig).toBeGreaterThan(now4); + expect(result.uncached).toBeGreaterThan(now4); + // 7 -> 8 should be invalidated + result = results.shift(); + expect(result.loader).toBeGreaterThan(now5); + expect(result.config).toBeGreaterThan(now5); + expect(result.esmConfig).toBeGreaterThan(now5); + expect(result.esmAsyncConfig).toBeGreaterThan(now5); + expect(result.uncached).toBeGreaterThan(now5); } }, 100000); }); diff --git a/test/fixtures/buildDependencies/run.js b/test/fixtures/buildDependencies/run.js index d5e9df835a8..f82652c4c8d 100644 --- a/test/fixtures/buildDependencies/run.js +++ b/test/fixtures/buildDependencies/run.js @@ -21,8 +21,8 @@ function run({ default: value2, asyncDep: value3 }) { const compiler = webpack( { mode: "development", - context: __dirname, - entry: "./index", + context: path.resolve(__dirname, "../../js/buildDepsInput"), + entry: path.resolve(__dirname, "./index"), output: { path: path.resolve(__dirname, "../../js/buildDeps/" + process.argv[2]), libraryTarget: "commonjs2" @@ -49,7 +49,7 @@ function run({ default: value2, asyncDep: value3 }) { config: [ __filename, path.resolve(__dirname, "../../../node_modules/.yarn-integrity") - ].concat(esm ? ["./esm.mjs"] : []), + ].concat(esm ? ["../../fixtures/buildDependencies/esm.mjs"] : []), invalid: options.invalidBuildDepdencies ? ["should-fail-resolving"] : []