<NME> run.js
<BEF> const path = require("path");
const webpack = require("../../..");
// eslint-disable-next-line node/no-missing-require
const value = require("../../js/buildDepsInput/config-dependency");

process.exitCode = 1;

webpack(
	{
		mode: "development",
		context: __dirname,
if (esm) {
	require("require-dependency-with-exports");
	import("./esm.mjs").then(module => {
		run(module);
	});
} else {
	run({ default: 1, asyncDep: 1 });
}

function run({ default: value2, asyncDep: value3 }) {
	const compiler = webpack(
				)
			})
		],
		cache: {
			type: "filesystem",
			cacheDirectory: path.resolve(__dirname, "../../js/buildDepsCache"),
				new webpack.DefinePlugin({
				config: [
					__filename,
					path.resolve(__dirname, "../../../node_modules/.yarn-integrity")
				]
			}
		},
		snapshot: {
					VALUE3: webpack.DefinePlugin.runtimeValue(
						() => JSON.stringify(value3),
						{ version: "no" }
					),
					VALUE_UNCACHEABLE: webpack.DefinePlugin.runtimeValue(
						() => JSON.stringify(value),
						true
		if (stats.hasErrors()) {
			return console.log(stats.toString({ all: false, errors: true }));
		}
		process.exitCode = 0;
		console.log("OK");
	}
);
					].concat(esm ? ["../../fixtures/buildDependencies/esm.mjs"] : []),
					invalid: options.invalidBuildDependencies
						? ["should-fail-resolving"]
						: [],
					optionalDepsTest: [
						path.resolve(__dirname, "node_modules/dependency-with-optional") +
							"/"
					]
				}
			}
		},
		(err, stats) => {
			if (err) {
				return console.log(err);
			}
			if (stats.hasErrors()) {
				return console.log(stats.toString({ all: false, errors: true }));
			}
			if (options.buildTwice) {
				compiler.run((err, stats) => {
					if (err) {
						return console.log(err);
					}
					if (stats.hasErrors()) {
						return console.log(stats.toString({ all: false, errors: true }));
					}
					process.exitCode = 0;
					console.log("OK");
				});
			} else {
				console.log(stats.toString());
				process.exitCode = 0;
				console.log("OK");
			}
		}
	);
}

<MSG> Merge pull request #12207 from webpack/bugfix/cache-without-build-deps

errors in initial cache no longer cause build dependencies to be ignored
<DFF> @@ -5,7 +5,9 @@ const value = require("../../js/buildDepsInput/config-dependency");
 
 process.exitCode = 1;
 
-webpack(
+const options = JSON.parse(process.argv[3]);
+
+const compiler = webpack(
 	{
 		mode: "development",
 		context: __dirname,
@@ -23,6 +25,9 @@ webpack(
 				)
 			})
 		],
+		infrastructureLogging: {
+			level: "verbose"
+		},
 		cache: {
 			type: "filesystem",
 			cacheDirectory: path.resolve(__dirname, "../../js/buildDepsCache"),
@@ -30,7 +35,8 @@ webpack(
 				config: [
 					__filename,
 					path.resolve(__dirname, "../../../node_modules/.yarn-integrity")
-				]
+				],
+				invalid: options.invalidBuildDepdencies ? ["should-fail-resolving"] : []
 			}
 		},
 		snapshot: {
@@ -44,7 +50,20 @@ webpack(
 		if (stats.hasErrors()) {
 			return console.log(stats.toString({ all: false, errors: true }));
 		}
-		process.exitCode = 0;
-		console.log("OK");
+		if (options.buildTwice) {
+			compiler.run((err, stats) => {
+				if (err) {
+					return console.log(err);
+				}
+				if (stats.hasErrors()) {
+					return console.log(stats.toString({ all: false, errors: true }));
+				}
+				process.exitCode = 0;
+				console.log("OK");
+			});
+		} else {
+			process.exitCode = 0;
+			console.log("OK");
+		}
 	}
 );

{'commit': 'diff --git a/lib/cache/PackFileCacheStrategy.js b/lib/cache/PackFileCacheStrategy.js\nindex 1b355e38a..6edc81773 100644\n--- a/lib/cache/PackFileCacheStrategy.js\n+++ b/lib/cache/PackFileCacheStrategy.js\n@@ -961,10 +961,8 @@ class PackFileCacheStrategy {\n \t\t\t\tfor (const dep of this.newBuildDependencies) {\n \t\t\t\t\tif (!this.buildDependencies.has(dep)) {\n \t\t\t\t\t\tnewBuildDependencies.add(dep);\n-\t\t\t\t\t\tthis.buildDependencies.add(dep);\n \t\t\t\t\t}\n \t\t\t\t}\n-\t\t\t\tthis.newBuildDependencies.clear();\n \t\t\t\tif (newBuildDependencies.size > 0 || !this.buildSnapshot) {\n \t\t\t\t\tif (reportProgress) reportProgress(0.5, "resolve build dependencies");\n \t\t\t\t\tthis.logger.debug(\n@@ -1093,6 +1091,10 @@ class PackFileCacheStrategy {\n \t\t\t\t\t\t\tlogger: this.logger\n \t\t\t\t\t\t})\n \t\t\t\t\t\t.then(() => {\n+\t\t\t\t\t\t\tfor (const dep of newBuildDependencies) {\n+\t\t\t\t\t\t\t\tthis.buildDependencies.add(dep);\n+\t\t\t\t\t\t\t}\n+\t\t\t\t\t\t\tthis.newBuildDependencies.clear();\n \t\t\t\t\t\t\tthis.logger.timeEnd(`store pack`);\n \t\t\t\t\t\t\tthis.logger.log(`Stored pack`);\n \t\t\t\t\t\t})\ndiff --git a/test/BuildDependencies.test.js b/test/BuildDependencies.test.js\nindex 405586092..069fc03c6 100644\n--- a/test/BuildDependencies.test.js\n+++ b/test/BuildDependencies.test.js\n@@ -9,14 +9,15 @@ const cacheDirectory = path.resolve(__dirname, "js/buildDepsCache");\n const outputDirectory = path.resolve(__dirname, "js/buildDeps");\n const inputDirectory = path.resolve(__dirname, "js/buildDepsInput");\n \n-const exec = n => {\n+const exec = (n, options = {}) => {\n \treturn new Promise((resolve, reject) => {\n \t\tconst p = child_process.fork(\n \t\t\tpath.resolve(__dirname, "fixtures/buildDependencies/run.js"),\n-\t\t\t[n],\n-\t\t\t{ stdio: ["ignore", "pipe", "inherit", "ipc"] }\n+\t\t\t[n, JSON.stringify(options)],\n+\t\t\t{ stdio: ["ignore", "pipe", "pipe", "ipc"] }\n \t\t);\n \t\tconst chunks = [];\n+\t\tp.stderr.on("data", chunk => chunks.push(chunk));\n \t\tp.stdout.on("data", chunk => chunks.push(chunk));\n \t\tp.once("exit", code => {\n \t\t\tconst stdout = Buffer.concat(chunks).toString("utf-8");\n@@ -45,6 +46,15 @@ describe("BuildDependencies", () => {\n \t\tfs.mkdir(inputDirectory, { recursive: true }, done);\n \t});\n \tit("should capture loader and config dependencies", async () => {\n+\t\tfs.writeFileSync(\n+\t\t\tpath.resolve(inputDirectory, "loader-dependency.js"),\n+\t\t\t"module.exports = 0;"\n+\t\t);\n+\t\tfs.writeFileSync(\n+\t\t\tpath.resolve(inputDirectory, "config-dependency.js"),\n+\t\t\t"module.exports = 0;"\n+\t\t);\n+\t\tawait exec("0", { invalidBuildDepdencies: true, buildTwice: true });\n \t\tfs.writeFileSync(\n \t\t\tpath.resolve(inputDirectory, "loader-dependency.js"),\n \t\t\t"module.exports = 1;"\n@@ -53,23 +63,23 @@ describe("BuildDependencies", () => {\n \t\t\tpath.resolve(inputDirectory, "config-dependency.js"),\n \t\t\t"module.exports = 1;"\n \t\t);\n-\t\tawait exec("0");\n+\t\tawait exec("1");\n \t\tfs.writeFileSync(\n \t\t\tpath.resolve(inputDirectory, "loader-dependency.js"),\n \t\t\t"module.exports = Date.now();"\n \t\t);\n \t\tconst now1 = Date.now();\n-\t\tawait exec("1");\n \t\tawait exec("2");\n+\t\tawait exec("3");\n \t\tfs.writeFileSync(\n \t\t\tpath.resolve(inputDirectory, "config-dependency"),\n \t\t\t"module.exports = Date.now();"\n \t\t);\n \t\tconst now2 = Date.now();\n-\t\tawait exec("3");\n-\t\tconst now3 = Date.now();\n \t\tawait exec("4");\n-\t\tconst results = Array.from({ length: 5 }).map((_, i) =>\n+\t\tconst now3 = Date.now();\n+\t\tawait exec("5");\n+\t\tconst results = Array.from({ length: 6 }).map((_, i) =>\n \t\t\trequire(`./js/buildDeps/${i}/main.js`)\n \t\t);\n \t\tfor (const r of results) {\n@@ -77,24 +87,28 @@ describe("BuildDependencies", () => {\n \t\t\texpect(typeof r.config).toBe("number");\n \t\t\texpect(typeof r.uncached).toBe("number");\n \t\t}\n-\t\texpect(results[0].loader).toBe(1);\n-\t\texpect(results[0].config).toBe(1);\n-\t\texpect(results[0].uncached).toBe(1);\n-\t\t// 0 -> 1 should be invalidated\n-\t\texpect(results[1].loader).toBeGreaterThan(now1);\n+\t\texpect(results[0].loader).toBe(0);\n+\t\texpect(results[0].config).toBe(0);\n+\t\texpect(results[0].uncached).toBe(0);\n+\t\t// 0 -> 1 should not cache at all because of invalid buildDeps\n+\t\texpect(results[1].loader).toBe(1);\n \t\texpect(results[1].config).toBe(1);\n \t\texpect(results[1].uncached).toBe(1);\n-\t\t// 1 -> 2 should stay cached\n-\t\texpect(results[2].loader).toBe(results[1].loader);\n+\t\t// 1 -> 2 should be invalidated\n+\t\texpect(results[2].loader).toBeGreaterThan(now1);\n \t\texpect(results[2].config).toBe(1);\n \t\texpect(results[2].uncached).toBe(1);\n-\t\t// 2 -> 3 should be invalidated\n-\t\texpect(results[3].loader).toBeGreaterThan(now2);\n-\t\texpect(results[3].config).toBeGreaterThan(now2);\n-\t\texpect(results[3].uncached).toBe(results[3].config);\n-\t\t// 3 -> 4 should stay cached, but uncacheable module still rebuilds\n-\t\texpect(results[4].loader).toBe(results[3].loader);\n-\t\texpect(results[4].config).toBe(results[3].config);\n-\t\texpect(results[4].uncached).toBeGreaterThan(now3);\n+\t\t// 2 -> 3 should stay cached\n+\t\texpect(results[3].loader).toBe(results[2].loader);\n+\t\texpect(results[3].config).toBe(1);\n+\t\texpect(results[3].uncached).toBe(1);\n+\t\t// 3 -> 4 should be invalidated\n+\t\texpect(results[4].loader).toBeGreaterThan(now2);\n+\t\texpect(results[4].config).toBeGreaterThan(now2);\n+\t\texpect(results[4].uncached).toBe(results[4].config);\n+\t\t// 4 -> 5 should stay cached, but uncacheable module still rebuilds\n+\t\texpect(results[5].loader).toBe(results[4].loader);\n+\t\texpect(results[5].config).toBe(results[4].config);\n+\t\texpect(results[5].uncached).toBeGreaterThan(now3);\n \t}, 100000);\n });\ndiff --git a/test/fixtures/buildDependencies/run.js b/test/fixtures/buildDependencies/run.js\nindex 59cdbb474..1e61e5ed1 100644\n--- a/test/fixtures/buildDependencies/run.js\n+++ b/test/fixtures/buildDependencies/run.js\n@@ -5,7 +5,9 @@ const value = require("../../js/buildDepsInput/config-dependency");\n \n process.exitCode = 1;\n \n-webpack(\n+const options = JSON.parse(process.argv[3]);\n+\n+const compiler = webpack(\n \t{\n \t\tmode: "development",\n \t\tcontext: __dirname,\n@@ -23,6 +25,9 @@ webpack(\n \t\t\t\t)\n \t\t\t})\n \t\t],\n+\t\tinfrastructureLogging: {\n+\t\t\tlevel: "verbose"\n+\t\t},\n \t\tcache: {\n \t\t\ttype: "filesystem",\n \t\t\tcacheDirectory: path.resolve(__dirname, "../../js/buildDepsCache"),\n@@ -30,7 +35,8 @@ webpack(\n \t\t\t\tconfig: [\n \t\t\t\t\t__filename,\n \t\t\t\t\tpath.resolve(__dirname, "../../../node_modules/.yarn-integrity")\n-\t\t\t\t]\n+\t\t\t\t],\n+\t\t\t\tinvalid: options.invalidBuildDepdencies ? ["should-fail-resolving"] : []\n \t\t\t}\n \t\t},\n \t\tsnapshot: {\n@@ -44,7 +50,20 @@ webpack(\n \t\tif (stats.hasErrors()) {\n \t\t\treturn console.log(stats.toString({ all: false, errors: true }));\n \t\t}\n-\t\tprocess.exitCode = 0;\n-\t\tconsole.log("OK");\n+\t\tif (options.buildTwice) {\n+\t\t\tcompiler.run((err, stats) => {\n+\t\t\t\tif (err) {\n+\t\t\t\t\treturn console.log(err);\n+\t\t\t\t}\n+\t\t\t\tif (stats.hasErrors()) {\n+\t\t\t\t\treturn console.log(stats.toString({ all: false, errors: true }));\n+\t\t\t\t}\n+\t\t\t\tprocess.exitCode = 0;\n+\t\t\t\tconsole.log("OK");\n+\t\t\t});\n+\t\t} else {\n+\t\t\tprocess.exitCode = 0;\n+\t\t\tconsole.log("OK");\n+\t\t}\n \t}\n );\n', 'commit_subject': 'Merge pull request #12207 from webpack/bugfix/cache-without-build-deps', 'repo_name': 'webpack/webpack', 'committer': {'name': 'GitHub', 'email': '1505422b2465e9a84f6fdfaa161078890c593f06@github.com', 'time_sec': '1608059675', 'tz_offset': '60', 'date': {'seconds': '1608059675'}}, 'commit_tree': '6add6bc38fc99658fd323aefd0b80e4134ba9be2', 'commit_message': 'Merge pull request #12207 from webpack/bugfix/cache-without-build-deps\n\nerrors in initial cache no longer cause build dependencies to be ignored', 'language_name': 'HTML', 'license': 'mit', 'hunks': '@@ -5,7 +5,9 @@ const value = require("../../js/buildDepsInput/config-dependency");\n \n process.exitCode = 1;\n \n-webpack(\n+const options = JSON.parse(process.argv[3]);\n+\n+const compiler = webpack(\n \t{\n \t\tmode: "development",\n \t\tcontext: __dirname,\n@@ -23,6 +25,9 @@ webpack(\n \t\t\t\t)\n \t\t\t})\n \t\t],\n+\t\tinfrastructureLogging: {\n+\t\t\tlevel: "verbose"\n+\t\t},\n \t\tcache: {\n \t\t\ttype: "filesystem",\n \t\t\tcacheDirectory: path.resolve(__dirname, "../../js/buildDepsCache"),\n@@ -30,7 +35,8 @@ webpack(\n \t\t\t\tconfig: [\n \t\t\t\t\t__filename,\n \t\t\t\t\tpath.resolve(__dirname, "../../../node_modules/.yarn-integrity")\n-\t\t\t\t]\n+\t\t\t\t],\n+\t\t\t\tinvalid: options.invalidBuildDepdencies ? ["should-fail-resolving"] : []\n \t\t\t}\n \t\t},\n \t\tsnapshot: {\n@@ -44,7 +50,20 @@ webpack(\n \t\tif (stats.hasErrors()) {\n \t\t\treturn console.log(stats.toString({ all: false, errors: true }));\n \t\t}\n-\t\tprocess.exitCode = 0;\n-\t\tconsole.log("OK");\n+\t\tif (options.buildTwice) {\n+\t\t\tcompiler.run((err, stats) => {\n+\t\t\t\tif (err) {\n+\t\t\t\t\treturn console.log(err);\n+\t\t\t\t}\n+\t\t\t\tif (stats.hasErrors()) {\n+\t\t\t\t\treturn console.log(stats.toString({ all: false, errors: true }));\n+\t\t\t\t}\n+\t\t\t\tprocess.exitCode = 0;\n+\t\t\t\tconsole.log("OK");\n+\t\t\t});\n+\t\t} else {\n+\t\t\tprocess.exitCode = 0;\n+\t\t\tconsole.log("OK");\n+\t\t}\n \t}\n );\n', 'addition_count': 23, 'deletion_count': 4, 'src_file': 'a/test/fixtures/buildDependencies/run.js', 'tgt_file': 'b/test/fixtures/buildDependencies/run.js', 'file_extension': '.js', 'before_file': 'const path = require("path");\nconst webpack = require("../../..");\n// eslint-disable-next-line node/no-missing-require\nconst value = require("../../js/buildDepsInput/config-dependency");\n\nprocess.exitCode = 1;\n\nwebpack(\n\t{\n\t\tmode: "development",\n\t\tcontext: __dirname,\nif (esm) {\n\trequire("require-dependency-with-exports");\n\timport("./esm.mjs").then(module => {\n\t\trun(module);\n\t});\n} else {\n\trun({ default: 1, asyncDep: 1 });\n}\n\nfunction run({ default: value2, asyncDep: value3 }) {\n\tconst compiler = webpack(\n\t\t\t\t)\n\t\t\t})\n\t\t],\n\t\tcache: {\n\t\t\ttype: "filesystem",\n\t\t\tcacheDirectory: path.resolve(__dirname, "../../js/buildDepsCache"),\n\t\t\t\tnew webpack.DefinePlugin({\n\t\t\t\tconfig: [\n\t\t\t\t\t__filename,\n\t\t\t\t\tpath.resolve(__dirname, "../../../node_modules/.yarn-integrity")\n\t\t\t\t]\n\t\t\t}\n\t\t},\n\t\tsnapshot: {\n\t\t\t\t\tVALUE3: webpack.DefinePlugin.runtimeValue(\n\t\t\t\t\t\t() => JSON.stringify(value3),\n\t\t\t\t\t\t{ version: "no" }\n\t\t\t\t\t),\n\t\t\t\t\tVALUE_UNCACHEABLE: webpack.DefinePlugin.runtimeValue(\n\t\t\t\t\t\t() => JSON.stringify(value),\n\t\t\t\t\t\ttrue\n\t\tif (stats.hasErrors()) {\n\t\t\treturn console.log(stats.toString({ all: false, errors: true }));\n\t\t}\n\t\tprocess.exitCode = 0;\n\t\tconsole.log("OK");\n\t}\n);\n\t\t\t\t\t].concat(esm ? ["../../fixtures/buildDependencies/esm.mjs"] : []),\n\t\t\t\t\tinvalid: options.invalidBuildDependencies\n\t\t\t\t\t\t? ["should-fail-resolving"]\n\t\t\t\t\t\t: [],\n\t\t\t\t\toptionalDepsTest: [\n\t\t\t\t\t\tpath.resolve(__dirname, "node_modules/dependency-with-optional") +\n\t\t\t\t\t\t\t"/"\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t(err, stats) => {\n\t\t\tif (err) {\n\t\t\t\treturn console.log(err);\n\t\t\t}\n\t\t\tif (stats.hasErrors()) {\n\t\t\t\treturn console.log(stats.toString({ all: false, errors: true }));\n\t\t\t}\n\t\t\tif (options.buildTwice) {\n\t\t\t\tcompiler.run((err, stats) => {\n\t\t\t\t\tif (err) {\n\t\t\t\t\t\treturn console.log(err);\n\t\t\t\t\t}\n\t\t\t\t\tif (stats.hasErrors()) {\n\t\t\t\t\t\treturn console.log(stats.toString({ all: false, errors: true }));\n\t\t\t\t\t}\n\t\t\t\t\tprocess.exitCode = 0;\n\t\t\t\t\tconsole.log("OK");\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconsole.log(stats.toString());\n\t\t\t\tprocess.exitCode = 0;\n\t\t\t\tconsole.log("OK");\n\t\t\t}\n\t\t}\n\t);\n}\n', 'message': 'Merge pull request #12207 from webpack/bugfix/cache-without-build-deps\n\nerrors in initial cache no longer cause build dependencies to be ignored', 'author_name': 'GitHub', 'lang': 'js'}