Repository: webpack/webpack
Pull request #6365 (2018-01-23 07:36:11)

perf: refactor various timestamp caches into ES6 Maps
<!-- Thanks for submitting a pull request! Please provide enough information so that others can review your pull request. -->

**What kind of change does this PR introduce?**

refactoring

<!-- E.g. a bugfix, feature, refactoring, build related change, etc… -->

**Did you add tests for your changes?**

modified existing unit tests

<!-- Note that we won't merge your changes if you don't add tests -->

**If relevant, link to documentation update:**

n/a
<!-- Link PR from webpack/webpack.js.org here, or N/A -->

**Summary**

This change satisfies https://github.com/webpack/webpack/issues/6234 which desires to change the timestamp caches from plain objects to the ES6 Map type to avoid deopts, since v8 expects things to be added to Maps but objects are only fast if properties aren't added dynamically after initial assignment.

<!-- Explain the **motivation** for making this change. What existing problem does the pull request solve? -->
<!-- Try to link to an open issue for more information. -->

**Does this PR introduce a breaking change?**

I think yes if anything is downstream is using `compiler.fileTimestamps` or `compiler.contextTimestamps`.

<!-- If this PR introduces a breaking change, please describe the impact and a migration path for existing applications. -->



Patch:
diff --git a/lib/CachePlugin.js b/lib/CachePlugin.js
index 7aa563b95..161418de8 100644
--- a/lib/CachePlugin.js
+++ b/lib/CachePlugin.js
@@ -42,7 +42,7 @@ class CachePlugin {
 			compiler.hooks.run.tapAsync("CachePlugin", (compiler, callback) => {
 				if(!compiler._lastCompilationFileDependencies) return callback();
 				const fs = compiler.inputFileSystem;
-				const fileTs = compiler.fileTimestamps = {};
+				const fileTs = compiler.fileTimestamps = new Map();
 				asyncLib.forEach(compiler._lastCompilationFileDependencies, (file, callback) => {
 					fs.stat(file, (err, stat) => {
 						if(err) {
@@ -53,14 +53,17 @@ class CachePlugin {
 						if(stat.mtime)
 							this.applyMtime(+stat.mtime);
 
-						fileTs[file] = +stat.mtime || Infinity;
+						fileTs.set(file, +stat.mtime || Infinity);
+
 						callback();
 					});
 				}, err => {
 					if(err) return callback(err);
-					Object.keys(fileTs).forEach(key => {
-						fileTs[key] += this.FS_ACCURENCY;
-					});
+
+					for(const [file, ts] of fileTs) {
+						fileTs.set(file, ts + this.FS_ACCURENCY);
+					}
+
 					callback();
 				});
 			});
diff --git a/lib/Chunk.js b/lib/Chunk.js
index bea776f2c..14bdad062 100644
--- a/lib/Chunk.js
+++ b/lib/Chunk.js
@@ -162,7 +162,7 @@ class Chunk {
 	}
 
 	getNumberOfGroups() {
-		return this._groups.size;
+		return this._groups.siz;
 	}
 
 	get groupsIterable() {
diff --git a/lib/Compiler.js b/lib/Compiler.js
index 3521e41d3..8f092dd48 100644
--- a/lib/Compiler.js
+++ b/lib/Compiler.js
@@ -78,8 +78,8 @@ class Compiler extends Tapable {
 		this.recordsOutputPath = null;
 		this.records = {};
 
-		this.fileTimestamps = {};
-		this.contextTimestamps = {};
+		this.fileTimestamps = new Map();
+		this.contextTimestamps = new Map();
 
 		this.resolverFactory = new ResolverFactory();
 		this.resolvers = {
@@ -177,8 +177,8 @@ class Compiler extends Tapable {
 	}
 
 	watch(watchOptions, handler) {
-		this.fileTimestamps = {};
-		this.contextTimestamps = {};
+		this.fileTimestamps = new Map();
+		this.contextTimestamps = new Map();
 		return new Watching(this, watchOptions, handler);
 	}
 
diff --git a/lib/ContextModule.js b/lib/ContextModule.js
index 86c5c6dd9..046f19188 100644
--- a/lib/ContextModule.js
+++ b/lib/ContextModule.js
@@ -129,7 +129,7 @@ class ContextModule extends Module {
 	}
 
 	needRebuild(fileTimestamps, contextTimestamps) {
-		const ts = contextTimestamps[this.context];
+		const ts = contextTimestamps.get(this.context);
 		if(!ts) {
 			return true;
 		}
diff --git a/lib/NormalModule.js b/lib/NormalModule.js
index f8609fc4f..3d68a7f8d 100644
--- a/lib/NormalModule.js
+++ b/lib/NormalModule.js
@@ -543,12 +543,12 @@ class NormalModule extends Module {
 		// Missing timestamp -> need rebuild
 		// Timestamp bigger than buildTimestamp -> need rebuild
 		for(const file of this.buildInfo.fileDependencies) {
-			const timestamp = fileTimestamps[file];
+			const timestamp = fileTimestamps.get(file);
 			if(!timestamp) return true;
 			if(timestamp >= this.buildTimestamp) return true;
 		}
 		for(const file of this.buildInfo.contextDependencies) {
-			const timestamp = contextTimestamps[file];
+			const timestamp = contextTimestamps.get(file);
 			if(!timestamp) return true;
 			if(timestamp >= this.buildTimestamp) return true;
 		}
diff --git a/lib/WatchIgnorePlugin.js b/lib/WatchIgnorePlugin.js
index f3410e832..35a020a3c 100644
--- a/lib/WatchIgnorePlugin.js
+++ b/lib/WatchIgnorePlugin.js
@@ -40,11 +40,11 @@ class IgnoringWatchFileSystem {
 			if(err) return callback(err);
 
 			ignoredFiles.forEach(path => {
-				fileTimestamps[path] = 1;
+				fileTimestamps.set(path, 1);
 			});
 
 			ignoredDirs.forEach(path => {
-				dirTimestamps[path] = 1;
+				dirTimestamps.set(path, 1);
 			});
 
 			callback(err, filesModified, dirsModified, missingModified, fileTimestamps, dirTimestamps);
@@ -56,14 +56,14 @@ class IgnoringWatchFileSystem {
 			getContextTimestamps: () => {
 				const dirTimestamps = watcher.getContextTimestamps();
 				ignoredDirs.forEach(path => {
-					dirTimestamps[path] = 1;
+					dirTimestamps.set(path, 1);
 				});
 				return dirTimestamps;
 			},
 			getFileTimestamps: () => {
 				const fileTimestamps = watcher.getFileTimestamps();
 				ignoredFiles.forEach(path => {
-					fileTimestamps[path] = 1;
+					fileTimestamps.set(path, 1);
 				});
 				return fileTimestamps;
 			}
diff --git a/lib/node/NodeWatchFileSystem.js b/lib/node/NodeWatchFileSystem.js
index c3af39189..f6af06f46 100644
--- a/lib/node/NodeWatchFileSystem.js
+++ b/lib/node/NodeWatchFileSystem.js
@@ -5,6 +5,7 @@
 "use strict";
 
 const Watchpack = require("watchpack");
+const objectToMap = require("../util/objectToMap");
 
 class NodeWatchFileSystem {
 	constructor(inputFileSystem) {
@@ -41,7 +42,7 @@ class NodeWatchFileSystem {
 			if(this.inputFileSystem && this.inputFileSystem.purge) {
 				this.inputFileSystem.purge(changes);
 			}
-			const times = this.watcher.getTimes();
+			const times = objectToMap(this.watcher.getTimes());
 			callback(null,
 				changes.filter(file => files.includes(file)).sort(),
 				changes.filter(file => dirs.includes(file)).sort(),
@@ -67,15 +68,15 @@ class NodeWatchFileSystem {
 			},
 			getFileTimestamps: () => {
 				if(this.watcher)
-					return this.watcher.getTimes();
+					return objectToMap(this.watcher.getTimes());
 				else
-					return {};
+					return new Map();
 			},
 			getContextTimestamps: () => {
 				if(this.watcher)
-					return this.watcher.getTimes();
+					return objectToMap(this.watcher.getTimes());
 				else
-					return {};
+					return new Map();
 			}
 		};
 	}
diff --git a/lib/util/objectToMap.js b/lib/util/objectToMap.js
new file mode 100644
index 000000000..f67140a8e
--- /dev/null
+++ b/lib/util/objectToMap.js
@@ -0,0 +1,10 @@
+/**
+ * convert an object into its 2D array equivalent to be turned
+ * into an ES6 map
+ *
+ * @param {object} obj - any object type that works with Object.keys()
+ * @returns {Map} an ES6 Map of KV pairs
+ */
+module.exports = function objectToMap(obj) {
+	return new Map(Object.keys(obj).map(key => [key, obj[key]]));
+};
diff --git a/lib/webpack.js b/lib/webpack.js
index 865ed9fd0..e241a4e0a 100644
--- a/lib/webpack.js
+++ b/lib/webpack.js
@@ -69,64 +69,61 @@ const exportPlugins = (obj, mappings) => {
 };
 
 exportPlugins(exports, {
-	"AutomaticPrefetchPlugin": () => require("./AutomaticPrefetchPlugin"),
-	"BannerPlugin": () => require("./BannerPlugin"),
-	"CachePlugin": () => require("./CachePlugin"),
-	"ContextExclusionPlugin": () => require("./ContextExclusionPlugin"),
-	"ContextReplacementPlugin": () => require("./ContextReplacementPlugin"),
+	"Stats": () => require("./Stats"),
 	"DefinePlugin": () => require("./DefinePlugin"),
-	"DllPlugin": () => require("./DllPlugin"),
-	"DllReferencePlugin": () => require("./DllReferencePlugin"),
-	"EnvironmentPlugin": () => require("./EnvironmentPlugin"),
-	"EvalDevToolModulePlugin": () => require("./EvalDevToolModulePlugin"),
+	"NormalModuleReplacementPlugin": () => require("./NormalModuleReplacementPlugin"),
+	"ContextReplacementPlugin": () => require("./ContextReplacementPlugin"),
+	"ContextExclusionPlugin": () => require("./ContextExclusionPlugin"),
+	"IgnorePlugin": () => require("./IgnorePlugin"),
+	"WatchIgnorePlugin": () => require("./WatchIgnorePlugin"),
+	"BannerPlugin": () => require("./BannerPlugin"),
+	"PrefetchPlugin": () => require("./PrefetchPlugin"),
+	"AutomaticPrefetchPlugin": () => require("./AutomaticPrefetchPlugin"),
+	"ProvidePlugin": () => require("./ProvidePlugin"),
+	"HotModuleReplacementPlugin": () => require("./HotModuleReplacementPlugin"),
+	"SourceMapDevToolPlugin": () => require("./SourceMapDevToolPlugin"),
 	"EvalSourceMapDevToolPlugin": () => require("./EvalSourceMapDevToolPlugin"),
+	"EvalDevToolModulePlugin": () => require("./EvalDevToolModulePlugin"),
+	"CachePlugin": () => require("./CachePlugin"),
 	"ExtendedAPIPlugin": () => require("./ExtendedAPIPlugin"),
 	"ExternalsPlugin": () => require("./ExternalsPlugin"),
-	"HashedModuleIdsPlugin": () => require("./HashedModuleIdsPlugin"),
-	"HotModuleReplacementPlugin": () => require("./HotModuleReplacementPlugin"),
-	"IgnorePlugin": () => require("./IgnorePlugin"),
 	"LibraryTemplatePlugin": () => require("./LibraryTemplatePlugin"),
-	"LoaderOptionsPlugin": () => require("./LoaderOptionsPlugin"),
 	"LoaderTargetPlugin": () => require("./LoaderTargetPlugin"),
 	"MemoryOutputFileSystem": () => require("./MemoryOutputFileSystem"),
-	"ModuleFilenameHelpers": () => require("./ModuleFilenameHelpers"),
-	"NamedChunksPlugin": () => require("./NamedChunksPlugin"),
-	"NamedModulesPlugin": () => require("./NamedModulesPlugin"),
-	"NoEmitOnErrorsPlugin": () => require("./NoEmitOnErrorsPlugin"),
-	"NormalModuleReplacementPlugin": () => require("./NormalModuleReplacementPlugin"),
-	"PrefetchPlugin": () => require("./PrefetchPlugin"),
 	"ProgressPlugin": () => require("./ProgressPlugin"),
-	"ProvidePlugin": () => require("./ProvidePlugin"),
 	"SetVarMainTemplatePlugin": () => require("./SetVarMainTemplatePlugin"),
-	"SingleEntryPlugin": () => require("./SingleEntryPlugin"),
-	"SourceMapDevToolPlugin": () => require("./SourceMapDevToolPlugin"),
-	"Stats": () => require("./Stats"),
 	"UmdMainTemplatePlugin": () => require("./UmdMainTemplatePlugin"),
-	"WatchIgnorePlugin": () => require("./WatchIgnorePlugin"),
+	"NoEmitOnErrorsPlugin": () => require("./NoEmitOnErrorsPlugin"),
+	"EnvironmentPlugin": () => require("./EnvironmentPlugin"),
+	"DllPlugin": () => require("./DllPlugin"),
+	"DllReferencePlugin": () => require("./DllReferencePlugin"),
+	"LoaderOptionsPlugin": () => require("./LoaderOptionsPlugin"),
+	"NamedModulesPlugin": () => require("./NamedModulesPlugin"),
+	"NamedChunksPlugin": () => require("./NamedChunksPlugin"),
+	"HashedModuleIdsPlugin": () => require("./HashedModuleIdsPlugin"),
+	"ModuleFilenameHelpers": () => require("./ModuleFilenameHelpers")
 });
 exportPlugins(exports.optimize = {}, {
 	"AggressiveMergingPlugin": () => require("./optimize/AggressiveMergingPlugin"),
 	"AggressiveSplittingPlugin": () => require("./optimize/AggressiveSplittingPlugin"),
+	"SplitChunksPlugin": () => require("./optimize/SplitChunksPlugin"),
+	"RuntimeChunkPlugin": () => require("./optimize/RuntimeChunkPlugin"),
 	"ChunkModuleIdRangePlugin": () => require("./optimize/ChunkModuleIdRangePlugin"),
 	"LimitChunkCountPlugin": () => require("./optimize/LimitChunkCountPlugin"),
 	"MinChunkSizePlugin": () => require("./optimize/MinChunkSizePlugin"),
 	"ModuleConcatenationPlugin": () => require("./optimize/ModuleConcatenationPlugin"),
-	"OccurrenceOrderPlugin": () => require("./optimize/OccurrenceOrderPlugin"),
-	"RuntimeChunkPlugin": () => require("./optimize/RuntimeChunkPlugin"),
 	"SideEffectsFlagPlugin": () => require("./optimize/SideEffectsFlagPlugin"),
-	"SplitChunksPlugin": () => require("./optimize/SplitChunksPlugin"),
+	"OccurrenceOrderPlugin": () => require("./optimize/OccurrenceOrderPlugin")
 });
 exportPlugins(exports.web = {}, {
-	"FetchCompileWasmTemplatePlugin": () => require("./web/FetchCompileWasmTemplatePlugin"),
 	"JsonpTemplatePlugin": () => require("./web/JsonpTemplatePlugin"),
-});
-exportPlugins(exports.webworker = {}, {
-	"WebWorkerTemplatePlugin": () => require("./webworker/WebWorkerTemplatePlugin"),
+	"FetchCompileWasmTemplatePlugin": () => require("./web/FetchCompileWasmTemplatePlugin"),
 });
 exportPlugins(exports.node = {}, {
 	"NodeTemplatePlugin": () => require("./node/NodeTemplatePlugin"),
 	"ReadFileCompileWasmTemplatePlugin": () => require("./node/ReadFileCompileWasmTemplatePlugin"),
 });
+
 exportPlugins(exports.debug = {}, {
-	"ProfilingPlugin": () => require("./debug/ProfilingPlugin"),
+	"ProfilingPlugin": () => require("./debug/ProfilingPlugin")
 });


Test patch:
diff --git a/test/Chunk.unittest.js b/test/Chunk.unittest.js
index 317ec5973..8b9d8ca52 100644
--- a/test/Chunk.unittest.js
+++ b/test/Chunk.unittest.js
@@ -59,42 +59,26 @@ describe("Chunk", () => {
 	describe("removeModule", function() {
 		let module;
 		let removeChunkSpy;
-
 		beforeEach(function() {
 			removeChunkSpy = sinon.spy();
-
 			module = {
 				removeChunk: removeChunkSpy
 			};
 		});
-
 		describe("and the chunk does not contain this module", function() {
 			it("returns false", function() {
 				ChunkInstance.removeModule(module).should.eql(false);
 			});
 		});
-
 		describe("and the chunk does contain this module", function() {
 			beforeEach(function() {
 				ChunkInstance._modules = new Set([module]);
 			});
-
 			it("calls module.removeChunk with itself and returns true", function() {
 				ChunkInstance.removeModule(module).should.eql(true);
-
 				removeChunkSpy.callCount.should.eql(1);
 				removeChunkSpy.args[0][0].should.eql(ChunkInstance);
 			});
 		});
-
-		describe("getNumberOfGroups", function() {
-			beforeEach(function() {
-				ChunkInstance._groups = new Set();
-			});
-
-			it("should return the number of chunk groups contained by the chunk", function() {
-				ChunkInstance.getNumberOfGroups().should.eql(0);
-			});
-		});
 	});
 });
diff --git a/test/NodeWatchFileSystem.unittest.js b/test/NodeWatchFileSystem.unittest.js
index c992e0c4a..f9e43c7bd 100644
--- a/test/NodeWatchFileSystem.unittest.js
+++ b/test/NodeWatchFileSystem.unittest.js
@@ -68,7 +68,7 @@ describe("NodeWatchFileSystem", function() {
 			if(err) throw err;
 			filesModified.should.be.eql([fileDirect]);
 			dirsModified.should.be.eql([]);
-			Object.assign({}, fileTimestamps).should.have.property(fileDirect).have.type("number");
+			(typeof fileTimestamps.get(fileDirect)).should.be.eql("number");
 			watcher.close();
 			done();
 		});
@@ -87,7 +87,7 @@ describe("NodeWatchFileSystem", function() {
 				if(err) throw err;
 				filesModified.should.be.eql([fileDirect]);
 				dirsModified.should.be.eql([]);
-				Object.assign({}, fileTimestamps).should.have.property(fileDirect).have.type("number");
+				(typeof fileTimestamps.get(fileDirect)).should.be.eql("number");
 				watcher.close();
 				done();
 			});
@@ -104,7 +104,7 @@ describe("NodeWatchFileSystem", function() {
 			if(err) throw err;
 			filesModified.should.be.eql([]);
 			dirsModified.should.be.eql([fixtures]);
-			Object.assign({}, dirTimestamps).should.have.property(fixtures).have.type("number");
+			(typeof dirTimestamps.get(fixtures)).should.be.eql("number");
 			watcher.close();
 			done();
 		});
@@ -123,7 +123,7 @@ describe("NodeWatchFileSystem", function() {
 				if(err) throw err;
 				filesModified.should.be.eql([]);
 				dirsModified.should.be.eql([fixtures]);
-				Object.assign({}, dirTimestamps).should.have.property(fixtures).have.type("number");
+				(typeof dirTimestamps.get(fixtures)).should.be.eql("number");
 				watcher.close();
 				done();
 			});
@@ -140,7 +140,7 @@ describe("NodeWatchFileSystem", function() {
 			if(err) throw err;
 			filesModified.should.be.eql([]);
 			dirsModified.should.be.eql([fixtures]);
-			Object.assign({}, dirTimestamps).should.have.property(fixtures).have.type("number");
+			(typeof dirTimestamps.get(fixtures)).should.be.eql("number");
 			watcher.close();
 			done();
 		});
@@ -159,7 +159,7 @@ describe("NodeWatchFileSystem", function() {
 				if(err) throw err;
 				filesModified.should.be.eql([]);
 				dirsModified.should.be.eql([fixtures]);
-				Object.assign({}, dirTimestamps).should.have.property(fixtures).have.type("number");
+				(typeof dirTimestamps.get(fixtures)).should.be.eql("number");
 				watcher.close();
 				done();
 			});
@@ -177,9 +177,9 @@ describe("NodeWatchFileSystem", function() {
 				if(err) throw err;
 				filesModified.should.be.eql([fileSubdir, fileDirect]);
 				dirsModified.should.be.eql([fixtures]);
-				Object.assign({}, fileTimestamps).should.have.property(fileDirect).have.type("number");
-				Object.assign({}, fileTimestamps).should.have.property(fileSubdir).have.type("number");
-				Object.assign({}, dirTimestamps).should.have.property(fixtures).have.type("number");
+				(typeof fileTimestamps.get(fileDirect)).should.be.eql("number");
+				(typeof fileTimestamps.get(fileSubdir)).should.be.eql("number");
+				(typeof dirTimestamps.get(fixtures)).should.be.eql("number");
 				watcher.close();
 				done();
 			});
@@ -197,9 +197,9 @@ describe("NodeWatchFileSystem", function() {
 			if(err) throw err;
 			filesModified.should.be.eql([fileSubdir, fileDirect]);
 			dirsModified.should.be.eql([fixtures]);
-			Object.assign({}, fileTimestamps).should.have.property(fileDirect).have.type("number");
-			Object.assign({}, fileTimestamps).should.have.property(fileSubdir).have.type("number");
-			Object.assign({}, dirTimestamps).should.have.property(fixtures).have.type("number");
+			(typeof fileTimestamps.get(fileDirect)).should.be.eql("number");
+			(typeof fileTimestamps.get(fileSubdir)).should.be.eql("number");
+			(typeof dirTimestamps.get(fixtures)).should.be.eql("number");
 			watcher.close();
 			done();
 		});
diff --git a/test/NormalModule.unittest.js b/test/NormalModule.unittest.js
index 15726af01..7cf7351e9 100644
--- a/test/NormalModule.unittest.js
+++ b/test/NormalModule.unittest.js
@@ -241,14 +241,14 @@ describe("NormalModule", function() {
 			fileB = "fileB";
 			fileDependencies = [fileA, fileB];
 			contextDependencies = [fileA, fileB];
-			fileTimestamps = {
-				[fileA]: 1,
-				[fileB]: 1,
-			};
-			contextTimestamps = {
-				[fileA]: 1,
-				[fileB]: 1,
-			};
+			fileTimestamps = new Map([
+				[fileA, 1],
+				[fileB, 1]
+			]);
+			contextTimestamps = new Map([
+				[fileA, 1],
+				[fileB, 1],
+			]);
 			normalModule.buildTimestamp = 2;
 			setDeps(fileDependencies, contextDependencies);
 		});
@@ -259,7 +259,7 @@ describe("NormalModule", function() {
 		});
 		describe("given a file timestamp is newer than the buildTimestamp", function() {
 			beforeEach(function() {
-				fileTimestamps[fileA] = 3;
+				fileTimestamps.set(fileA, 3);
 			});
 			it("returns true", function() {
 				normalModule.needRebuild(fileTimestamps, contextTimestamps).should.eql(true);
@@ -267,7 +267,7 @@ describe("NormalModule", function() {
 		});
 		describe("given a no file timestamp exists", function() {
 			beforeEach(function() {
-				fileTimestamps = {};
+				fileTimestamps = new Map();
 			});
 			it("returns true", function() {
 				normalModule.needRebuild(fileTimestamps, contextTimestamps).should.eql(true);
@@ -275,7 +275,7 @@ describe("NormalModule", function() {
 		});
 		describe("given a context timestamp is newer than the buildTimestamp", function() {
 			beforeEach(function() {
-				contextTimestamps[fileA] = 3;
+				contextTimestamps.set(fileA, 3);
 			});
 			it("returns true", function() {
 				normalModule.needRebuild(fileTimestamps, contextTimestamps).should.eql(true);
@@ -283,7 +283,7 @@ describe("NormalModule", function() {
 		});
 		describe("given a no context timestamp exists", function() {
 			beforeEach(function() {
-				contextTimestamps = {};
+				contextTimestamps = new Map();
 			});
 			it("returns true", function() {
 				normalModule.needRebuild(fileTimestamps, contextTimestamps).should.eql(true);
diff --git a/test/objectToMap.unittest.js b/test/objectToMap.unittest.js
new file mode 100644
index 000000000..c0f1aff7b
--- /dev/null
+++ b/test/objectToMap.unittest.js
@@ -0,0 +1,17 @@
+/* globals describe it */
+
+require("should");
+
+var objectToMap = require("../lib/util/objectToMap");
+
+describe("objectToMap", function() {
+	it("should convert a plain object into a Map successfully", function() {
+		const map = objectToMap({
+			foo: "bar",
+			bar: "baz"
+		});
+
+		map.get("foo").should.eql("bar");
+		map.get("bar").should.eql("baz");
+	});
+});
diff --git a/test/statsCases/async-commons-chunk-auto/expected.txt b/test/statsCases/async-commons-chunk-auto/expected.txt
index 038a6142b..03425701e 100644
--- a/test/statsCases/async-commons-chunk-auto/expected.txt
+++ b/test/statsCases/async-commons-chunk-auto/expected.txt
@@ -131,59 +131,59 @@ Child vendors:
     Entrypoint a = vendors/vendors.js vendors/a.js
     Entrypoint b = vendors/vendors.js vendors/b.js
     Entrypoint c = vendors/vendors.js vendors/c.js
-    chunk    {0} vendors/async-g.js (async-g) 54 bytes <{1}> <{4}> <{6}> [rendered]
+    chunk    {0} vendors/async-g.js (async-g) 54 bytes <{1}> <{8}> <{5}> [rendered]
         > ./g [] 6:0-47
         > ./g [] 6:0-47
-        [2] ./f.js 20 bytes {0} {2} {3} {7} {8} [built]
+        [2] ./f.js 20 bytes {0} {2} {3} {6} {7} [built]
         [9] ./g.js 34 bytes {0} [built]
-    chunk    {1} vendors/async-a.js (async-a) 216 bytes <{5}> >{0}< [rendered]
+    chunk    {1} vendors/async-a.js (async-a) 216 bytes <{4}> >{0}< [rendered]
         > ./a [8] ./index.js 1:0-47
-        [0] ./d.js 20 bytes {1} {2} {3} {6} {7} {8} [built]
-        [1] ./node_modules/x.js 20 bytes {1} {2} {3} {4} [built]
-        [3] ./node_modules/y.js 20 bytes {1} {2} {4} [built]
-        [7] ./a.js + 1 modules 156 bytes {1} {6} [built]
+        [0] ./d.js 20 bytes {1} {2} {3} {5} {6} {7} [built]
+        [1] ./node_modules/x.js 20 bytes {1} {2} {3} {8} [built]
+        [3] ./node_modules/y.js 20 bytes {1} {2} {8} [built]
+        [7] ./a.js + 1 modules 156 bytes {1} {5} [built]
             | ./a.js 121 bytes [built]
             | ./e.js 20 bytes [built]
-    chunk    {2} vendors/async-b.js (async-b) 152 bytes <{5}> [rendered]
+    chunk    {2} vendors/async-b.js (async-b) 152 bytes <{4}> [rendered]
         > ./b [8] ./index.js 2:0-47
-        [0] ./d.js 20 bytes {1} {2} {3} {6} {7} {8} [built]
-        [1] ./node_modules/x.js 20 bytes {1} {2} {3} {4} [built]
-        [2] ./f.js 20 bytes {0} {2} {3} {7} {8} [built]
-        [3] ./node_modules/y.js 20 bytes {1} {2} {4} [built]
-        [5] ./b.js 72 bytes {2} {7} [built]
-    chunk    {3} vendors/async-c.js (async-c) 152 bytes <{5}> [rendered]
+        [0] ./d.js 20 bytes {1} {2} {3} {5} {6} {7} [built]
+        [1] ./node_modules/x.js 20 bytes {1} {2} {3} {8} [built]
+        [2] ./f.js 20 bytes {0} {2} {3} {6} {7} [built]
+        [3] ./node_modules/y.js 20 bytes {1} {2} {8} [built]
+        [5] ./b.js 72 bytes {2} {6} [built]
+    chunk    {3} vendors/async-c.js (async-c) 152 bytes <{4}> [rendered]
         > ./c [8] ./index.js 3:0-47
-        [0] ./d.js 20 bytes {1} {2} {3} {6} {7} {8} [built]
-        [1] ./node_modules/x.js 20 bytes {1} {2} {3} {4} [built]
-        [2] ./f.js 20 bytes {0} {2} {3} {7} {8} [built]
-        [4] ./node_modules/z.js 20 bytes {3} {4} [built]
-        [6] ./c.js 72 bytes {3} {8} [built]
-    chunk    {4} vendors/vendors.js (vendors) 60 bytes ={8}= ={7}= ={6}= >{0}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors)
-        > ./c c
-        > ./b b
-        > ./a a
-        [1] ./node_modules/x.js 20 bytes {1} {2} {3} {4} [built]
-        [3] ./node_modules/y.js 20 bytes {1} {2} {4} [built]
-        [4] ./node_modules/z.js 20 bytes {3} {4} [built]
-    chunk    {5} vendors/main.js (main) 147 bytes >{1}< >{2}< >{3}< [entry] [rendered]
+        [0] ./d.js 20 bytes {1} {2} {3} {5} {6} {7} [built]
+        [1] ./node_modules/x.js 20 bytes {1} {2} {3} {8} [built]
+        [2] ./f.js 20 bytes {0} {2} {3} {6} {7} [built]
+        [4] ./node_modules/z.js 20 bytes {3} {8} [built]
+        [6] ./c.js 72 bytes {3} {7} [built]
+    chunk    {4} vendors/main.js (main) 147 bytes >{1}< >{2}< >{3}< [entry] [rendered]
         > ./ main
-        [8] ./index.js 147 bytes {5} [built]
-    chunk    {6} vendors/a.js (a) 176 bytes ={4}= >{0}< [entry] [rendered]
+        [8] ./index.js 147 bytes {4} [built]
+    chunk    {5} vendors/a.js (a) 176 bytes ={8}= >{0}< [entry] [rendered]
         > ./a a
-        [0] ./d.js 20 bytes {1} {2} {3} {6} {7} {8} [built]
-        [7] ./a.js + 1 modules 156 bytes {1} {6} [built]
+        [0] ./d.js 20 bytes {1} {2} {3} {5} {6} {7} [built]
+        [7] ./a.js + 1 modules 156 bytes {1} {5} [built]
             | ./a.js 121 bytes [built]
             | ./e.js 20 bytes [built]
-    chunk    {7} vendors/b.js (b) 112 bytes ={4}= [entry] [rendered]
+    chunk    {6} vendors/b.js (b) 112 bytes ={8}= [entry] [rendered]
         > ./b b
-        [0] ./d.js 20 bytes {1} {2} {3} {6} {7} {8} [built]
-        [2] ./f.js 20 bytes {0} {2} {3} {7} {8} [built]
-        [5] ./b.js 72 bytes {2} {7} [built]
-    chunk    {8} vendors/c.js (c) 112 bytes ={4}= [entry] [rendered]
+        [0] ./d.js 20 bytes {1} {2} {3} {5} {6} {7} [built]
+        [2] ./f.js 20 bytes {0} {2} {3} {6} {7} [built]
+        [5] ./b.js 72 bytes {2} {6} [built]
+    chunk    {7} vendors/c.js (c) 112 bytes ={8}= [entry] [rendered]
         > ./c c
-        [0] ./d.js 20 bytes {1} {2} {3} {6} {7} {8} [built]
-        [2] ./f.js 20 bytes {0} {2} {3} {7} {8} [built]
-        [6] ./c.js 72 bytes {3} {8} [built]
+        [0] ./d.js 20 bytes {1} {2} {3} {5} {6} {7} [built]
+        [2] ./f.js 20 bytes {0} {2} {3} {6} {7} [built]
+        [6] ./c.js 72 bytes {3} {7} [built]
+    chunk    {8} vendors/vendors.js (vendors) 60 bytes ={7}= ={6}= ={5}= >{0}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors)
+        > ./c c
+        > ./b b
+        > ./a a
+        [1] ./node_modules/x.js 20 bytes {1} {2} {3} {8} [built]
+        [3] ./node_modules/y.js 20 bytes {1} {2} {8} [built]
+        [4] ./node_modules/z.js 20 bytes {3} {8} [built]
 Child multiple-vendors:
     Entrypoint main = multiple-vendors/main.js
     Entrypoint a = multiple-vendors/libs-x.js multiple-vendors/a.js
@@ -255,7 +255,7 @@ Child all:
     Entrypoint a = all/vendors~a~async-a~async-b~async-c~b~c.js all/a~async-a~async-b~b.js all/a.js
     Entrypoint b = all/vendors~a~async-a~async-b~async-c~b~c.js all/a~async-a~async-b~b.js all/b.js
     Entrypoint c = all/vendors~a~async-a~async-b~async-c~b~c.js all/vendors~async-c~c.js all/c.js
-    chunk    {0} all/vendors~a~async-a~async-b~async-c~b~c.js (vendors~a~async-a~async-b~async-c~b~c) 20 bytes <{9}> ={4}= ={12}= ={2}= ={11}= ={10}= ={1}= ={3}= ={8}= ={7}= ={6}= >{1}< >{5}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors~a~async-a~async-b~async-c~b~c)
+    chunk    {0} all/vendors~a~async-a~async-b~async-c~b~c.js (vendors~a~async-a~async-b~async-c~b~c) 20 bytes <{9}> ={8}= ={12}= ={2}= ={11}= ={10}= ={1}= ={3}= ={7}= ={6}= ={5}= >{1}< >{4}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors~a~async-a~async-b~async-c~b~c)
         > ./c c
         > ./b b
         > ./a a
@@ -263,59 +263,59 @@ Child all:
         > ./b [8] ./index.js 2:0-47
         > ./a [8] ./index.js 1:0-47
         [1] ./node_modules/x.js 20 bytes {0} {3} [built]
-    chunk    {1} all/async-b~async-c~async-g~b~c.js (async-b~async-c~async-g~b~c) 20 bytes <{0}> <{2}> <{10}> <{3}> <{6}> <{9}> ={5}= ={0}= ={4}= ={3}= ={8}= ={2}= ={7}= [rendered] split chunk (cache group: default) (name: async-b~async-c~async-g~b~c)
+    chunk    {1} all/async-b~async-c~async-g~b~c.js (async-b~async-c~async-g~b~c) 20 bytes <{0}> <{2}> <{10}> <{3}> <{5}> <{9}> ={4}= ={0}= ={8}= ={3}= ={7}= ={2}= ={6}= [rendered] split chunk (cache group: default) (name: async-b~async-c~async-g~b~c)
         > ./g [] 6:0-47
         > ./g [] 6:0-47
         > ./c [8] ./index.js 3:0-47
         > ./b [8] ./index.js 2:0-47
         [2] ./f.js 20 bytes {1} {11} {12} [built]
-    chunk    {2} all/a~async-a~async-b~b.js (a~async-a~async-b~b) 20 bytes <{9}> ={0}= ={11}= ={10}= ={1}= ={7}= ={3}= ={6}= >{1}< >{5}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors~a~async-a~async-b~b)
+    chunk    {2} all/a~async-a~async-b~b.js (a~async-a~async-b~b) 20 bytes <{9}> ={0}= ={11}= ={10}= ={1}= ={6}= ={3}= ={5}= >{1}< >{4}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors~a~async-a~async-b~b)
         > ./b b
         > ./a a
         > ./b [8] ./index.js 2:0-47
         > ./a [8] ./index.js 1:0-47
         [3] ./node_modules/y.js 20 bytes {2} [built]
-    chunk    {3} all/a~async-a~async-b~async-c~b~c.js (a~async-a~async-b~async-c~b~c) 40 bytes <{9}> ={0}= ={4}= ={1}= ={8}= ={2}= ={6}= >{1}< >{5}< [rendered] split chunk (cache group: default) (name: a~async-a~async-b~async-c~b~c)
+    chunk    {3} all/a~async-a~async-b~async-c~b~c.js (a~async-a~async-b~async-c~b~c) 40 bytes <{9}> ={0}= ={8}= ={1}= ={7}= ={2}= ={5}= >{1}< >{4}< [rendered] split chunk (cache group: default) (name: a~async-a~async-b~async-c~b~c)
         > ./c [8] ./index.js 3:0-47
         > ./a [8] ./index.js 1:0-47
-        [0] ./d.js 20 bytes {3} {7} {10} {11} {12} [built]
+        [0] ./d.js 20 bytes {3} {6} {10} {11} {12} [built]
         [1] ./node_modules/x.js 20 bytes {0} {3} [built]
-    chunk    {4} all/vendors~async-c~c.js (vendors~async-c~c) 20 bytes <{9}> ={0}= ={12}= ={1}= ={3}= ={8}= [initial] [rendered] split chunk (cache group: vendors) (name: vendors~async-c~c)
-        > ./c c
-        > ./c [8] ./index.js 3:0-47
-        [7] ./node_modules/z.js 20 bytes {4} [built]
-    chunk    {5} all/async-g.js (async-g) 34 bytes <{0}> <{2}> <{10}> <{3}> <{6}> ={1}= [rendered]
+    chunk    {4} all/async-g.js (async-g) 34 bytes <{0}> <{2}> <{10}> <{3}> <{5}> ={1}= [rendered]
         > ./g [] 6:0-47
         > ./g [] 6:0-47
-        [9] ./g.js 34 bytes {5} [built]
-    chunk    {6} all/async-a.js (async-a) 156 bytes <{9}> ={0}= ={2}= ={3}= >{1}< >{5}< [rendered]
+        [9] ./g.js 34 bytes {4} [built]
+    chunk    {5} all/async-a.js (async-a) 156 bytes <{9}> ={0}= ={2}= ={3}= >{1}< >{4}< [rendered]
         > ./a [8] ./index.js 1:0-47
-        [6] ./a.js + 1 modules 156 bytes {6} {10} [built]
+        [6] ./a.js + 1 modules 156 bytes {5} {10} [built]
             | ./a.js 121 bytes [built]
             | ./e.js 20 bytes [built]
-    chunk    {7} all/async-b.js (async-b) 92 bytes <{9}> ={0}= ={2}= ={1}= [rendered]
+    chunk    {6} all/async-b.js (async-b) 92 bytes <{9}> ={0}= ={2}= ={1}= [rendered]
         > ./b [8] ./index.js 2:0-47
-        [0] ./d.js 20 bytes {3} {7} {10} {11} {12} [built]
-        [4] ./b.js 72 bytes {7} {11} [built]
-    chunk    {8} all/async-c.js (async-c) 72 bytes <{9}> ={0}= ={4}= ={1}= ={3}= [rendered]
+        [0] ./d.js 20 bytes {3} {6} {10} {11} {12} [built]
+        [4] ./b.js 72 bytes {6} {11} [built]
+    chunk    {7} all/async-c.js (async-c) 72 bytes <{9}> ={0}= ={8}= ={1}= ={3}= [rendered]
+        > ./c [8] ./index.js 3:0-47
+        [5] ./c.js 72 bytes {7} {12} [built]
+    chunk    {8} all/vendors~async-c~c.js (vendors~async-c~c) 20 bytes <{9}> ={0}= ={12}= ={1}= ={3}= ={7}= [initial] [rendered] split chunk (cache group: vendors) (name: vendors~async-c~c)
+        > ./c c
         > ./c [8] ./index.js 3:0-47
-        [5] ./c.js 72 bytes {8} {12} [built]
-    chunk    {9} all/main.js (main) 147 bytes >{0}< >{2}< >{1}< >{7}< >{3}< >{6}< >{4}< >{8}< [entry] [rendered]
+        [7] ./node_modules/z.js 20 bytes {8} [built]
+    chunk    {9} all/main.js (main) 147 bytes >{0}< >{2}< >{1}< >{6}< >{3}< >{5}< >{8}< >{7}< [entry] [rendered]
         > ./ main
         [8] ./index.js 147 bytes {9} [built]
-    chunk   {10} all/a.js (a) 176 bytes ={0}= ={2}= >{1}< >{5}< [entry] [rendered]
+    chunk   {10} all/a.js (a) 176 bytes ={0}= ={2}= >{1}< >{4}< [entry] [rendered]
         > ./a a
-        [0] ./d.js 20 bytes {3} {7} {10} {11} {12} [built]
-        [6] ./a.js + 1 modules 156 bytes {6} {10} [built]
+        [0] ./d.js 20 bytes {3} {6} {10} {11} {12} [built]
+        [6] ./a.js + 1 modules 156 bytes {5} {10} [built]
             | ./a.js 121 bytes [built]
             | ./e.js 20 bytes [built]
     chunk   {11} all/b.js (b) 112 bytes ={0}= ={2}= [entry] [rendered]
         > ./b b
-        [0] ./d.js 20 bytes {3} {7} {10} {11} {12} [built]
+        [0] ./d.js 20 bytes {3} {6} {10} {11} {12} [built]
         [2] ./f.js 20 bytes {1} {11} {12} [built]
-        [4] ./b.js 72 bytes {7} {11} [built]
-    chunk   {12} all/c.js (c) 112 bytes ={0}= ={4}= [entry] [rendered]
+        [4] ./b.js 72 bytes {6} {11} [built]
+    chunk   {12} all/c.js (c) 112 bytes ={0}= ={8}= [entry] [rendered]
         > ./c c
-        [0] ./d.js 20 bytes {3} {7} {10} {11} {12} [built]
+        [0] ./d.js 20 bytes {3} {6} {10} {11} {12} [built]
         [2] ./f.js 20 bytes {1} {11} {12} [built]
-        [5] ./c.js 72 bytes {8} {12} [built]
\ No newline at end of file
+        [5] ./c.js 72 bytes {7} {12} [built]
\ No newline at end of file
diff --git a/test/statsCases/optimize-chunks/expected.txt b/test/statsCases/optimize-chunks/expected.txt
index c1803d309..792cc6c6c 100644
--- a/test/statsCases/optimize-chunks/expected.txt
+++ b/test/statsCases/optimize-chunks/expected.txt
@@ -1,46 +1,46 @@
-Hash: 6032753dfe117b1c3893
+Hash: d4d639483dab93af23e4
 Time: Xms
             Asset       Size  Chunks             Chunk Names
-          cir1.js  299 bytes       0  [emitted]  cir1
-            ab.js  183 bytes       1  [emitted]  ab
-           abd.js  277 bytes    2, 1  [emitted]  abd
+            ab.js  183 bytes       0  [emitted]  ab
+           abd.js  277 bytes    1, 0  [emitted]  abd
+          cir1.js  299 bytes       2  [emitted]  cir1
           cir2.js  299 bytes       3  [emitted]  cir2
           main.js    7.8 KiB       4  [emitted]  main
 cir2 from cir1.js  359 bytes    5, 3  [emitted]  cir2 from cir1
          chunk.js  190 bytes    6, 7  [emitted]  chunk
       ac in ab.js  130 bytes       7  [emitted]  ac in ab
 Entrypoint main = main.js
-chunk    {0} cir1.js (cir1) 81 bytes <{4}> <{3}> <{5}> >{5}< [rendered]
+chunk    {0} ab.js (ab) 0 bytes <{4}> >{7}< [rendered]
+    > [8] ./index.js 1:0-6:8
+    [0] ./modules/a.js 0 bytes {0} {1} [built]
+    [1] ./modules/b.js 0 bytes {0} {1} [built]
+chunk    {1} abd.js (abd) 0 bytes <{4}> >{6}< [rendered]
+    > [8] ./index.js 8:0-11:9
+    [0] ./modules/a.js 0 bytes {0} {1} [built]
+    [1] ./modules/b.js 0 bytes {0} {1} [built]
+    [6] ./modules/d.js 0 bytes {1} {6} [built]
+chunk    {2} cir1.js (cir1) 81 bytes <{4}> <{3}> <{5}> >{5}< [rendered]
     > [8] ./index.js 13:0-54
     > [3] ./circular2.js 1:0-79
     > [3] ./circular2.js 1:0-79
-    [2] ./circular1.js 81 bytes {0} [built]
-chunk    {1} ab.js (ab) 0 bytes <{4}> >{7}< [rendered]
-    > [8] ./index.js 1:0-6:8
-    [0] ./modules/a.js 0 bytes {1} {2} [built]
-    [1] ./modules/b.js 0 bytes {1} {2} [built]
-chunk    {2} abd.js (abd) 0 bytes <{4}> >{6}< [rendered]
-    > [8] ./index.js 8:0-11:9
-    [0] ./modules/a.js 0 bytes {1} {2} [built]
-    [1] ./modules/b.js 0 bytes {1} {2} [built]
-    [6] ./modules/d.js 0 bytes {2} {6} [built]
-chunk    {3} cir2.js (cir2) 81 bytes <{4}> >{0}< [rendered]
+    [2] ./circular1.js 81 bytes {2} [built]
+chunk    {3} cir2.js (cir2) 81 bytes <{4}> >{2}< [rendered]
     > [8] ./index.js 14:0-54
     [3] ./circular2.js 81 bytes {3} {5} [built]
 chunk    {4} main.js (main) 523 bytes >{0}< >{1}< >{2}< >{3}< [entry] [rendered]
     > ./index main
     [4] ./modules/f.js 0 bytes {4} [built]
     [8] ./index.js 523 bytes {4} [built]
-chunk    {5} cir2 from cir1.js (cir2 from cir1) 81 bytes <{0}> >{0}< [rendered]
+chunk    {5} cir2 from cir1.js (cir2 from cir1) 81 bytes <{2}> >{2}< [rendered]
     > [2] ./circular1.js 1:0-79
     > [2] ./circular1.js 1:0-79
     [3] ./circular2.js 81 bytes {3} {5} [built]
     [7] ./modules/e.js 0 bytes {5} [built]
-chunk    {6} chunk.js (chunk) 0 bytes <{2}> <{7}> [rendered]
+chunk    {6} chunk.js (chunk) 0 bytes <{1}> <{7}> [rendered]
     > [8] ./index.js 3:2-4:13
     > [8] ./index.js 9:1-10:12
     [5] ./modules/c.js 0 bytes {6} {7} [built]
-    [6] ./modules/d.js 0 bytes {2} {6} [built]
-chunk    {7} ac in ab.js (ac in ab) 0 bytes <{1}> >{6}< [rendered]
+    [6] ./modules/d.js 0 bytes {1} {6} [built]
+chunk    {7} ac in ab.js (ac in ab) 0 bytes <{0}> >{6}< [rendered]
     > [8] ./index.js 2:1-5:15
     [5] ./modules/c.js 0 bytes {6} {7} [built]
\ No newline at end of file
diff --git a/test/statsCases/scope-hoisting-multi/expected.txt b/test/statsCases/scope-hoisting-multi/expected.txt
index cb9084259..83ef4c0a3 100644
--- a/test/statsCases/scope-hoisting-multi/expected.txt
+++ b/test/statsCases/scope-hoisting-multi/expected.txt
@@ -1,38 +1,38 @@
-Hash: f987d10439866c1320274e05ad6ebdcc88f97d91
+Hash: 5374f3d607ef77b77b87b191764cf9a5b21374f0
 Child
-    Hash: f987d10439866c132027
+    Hash: 5374f3d607ef77b77b87
     Time: Xms
     Entrypoint first = vendor.js first.js
     Entrypoint second = vendor.js second.js
        [0] ./common_lazy_shared.js 25 bytes {0} {1} {2} [built]
-       [1] ./common2.js 25 bytes {4} {5} [built]
+       [1] ./common2.js 25 bytes {3} {4} [built]
        [2] ./common_lazy.js 25 bytes {1} {2} [built]
-       [3] ./common.js 37 bytes {4} {5} [built]
+       [3] ./common.js 37 bytes {3} {4} [built]
        [4] ./lazy_shared.js 31 bytes {0} [built]
-       [5] ./vendor.js 25 bytes {3} [built]
+       [5] ./vendor.js 25 bytes {5} [built]
        [6] ./lazy_first.js 55 bytes {2} [built]
        [7] ./lazy_second.js 55 bytes {1} [built]
-       [8] ./first.js 207 bytes {4} [built]
-       [9] ./module_first.js 31 bytes {4} [built]
-      [10] ./second.js 177 bytes {5} [built]
+       [8] ./first.js 207 bytes {3} [built]
+       [9] ./module_first.js 31 bytes {3} [built]
+      [10] ./second.js 177 bytes {4} [built]
 Child
-    Hash: 4e05ad6ebdcc88f97d91
+    Hash: b191764cf9a5b21374f0
     Time: Xms
     Entrypoint first = vendor.js first.js
     Entrypoint second = vendor.js second.js
        [0] ./common_lazy_shared.js 25 bytes {0} {1} {2} [built]
        [1] ./common_lazy.js 25 bytes {1} {2} [built]
-       [2] ./common.js + 1 modules 62 bytes {4} {5} [built]
+       [2] ./common.js + 1 modules 62 bytes {3} {4} [built]
            | ./common.js 37 bytes [built]
            | ./common2.js 25 bytes [built]
-       [3] ./vendor.js 25 bytes {3} [built]
+       [3] ./vendor.js 25 bytes {5} [built]
        [4] ./lazy_shared.js 31 bytes {0} [built]
            ModuleConcatenation bailout: Module is referenced from these modules with unsupported syntax: ./first.js (referenced with import()), ./second.js (referenced with import())
        [5] ./lazy_second.js 55 bytes {1} [built]
            ModuleConcatenation bailout: Module is referenced from these modules with unsupported syntax: ./second.js (referenced with import())
-       [6] ./second.js 177 bytes {5} [built]
+       [6] ./second.js 177 bytes {4} [built]
            ModuleConcatenation bailout: Module is an entry point
-       [7] ./first.js + 1 modules 248 bytes {4} [built]
+       [7] ./first.js + 1 modules 248 bytes {3} [built]
            ModuleConcatenation bailout: Cannot concat with ./common.js
            ModuleConcatenation bailout: Cannot concat with ./vendor.js
            | ./first.js 207 bytes [built]
diff --git a/test/statsCases/split-chunks/expected.txt b/test/statsCases/split-chunks/expected.txt
index 2b44d6ad6..8c8767f4b 100644
--- a/test/statsCases/split-chunks/expected.txt
+++ b/test/statsCases/split-chunks/expected.txt
@@ -72,7 +72,7 @@ Child all-chunks:
     Entrypoint a = default/vendors~a~async-a~async-b~async-c~b~c.js default/a~async-a~async-b~b.js default/a.js
     Entrypoint b = default/vendors~a~async-a~async-b~async-c~b~c.js default/a~async-a~async-b~b.js default/b.js
     Entrypoint c = default/vendors~a~async-a~async-b~async-c~b~c.js default/vendors~async-c~c.js default/c.js
-    chunk    {0} default/vendors~a~async-a~async-b~async-c~b~c.js (vendors~a~async-a~async-b~async-c~b~c) 20 bytes <{9}> ={4}= ={12}= ={2}= ={11}= ={10}= ={1}= ={3}= ={8}= ={7}= ={6}= >{1}< >{5}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors~a~async-a~async-b~async-c~b~c)
+    chunk    {0} default/vendors~a~async-a~async-b~async-c~b~c.js (vendors~a~async-a~async-b~async-c~b~c) 20 bytes <{9}> ={8}= ={12}= ={2}= ={11}= ={10}= ={1}= ={3}= ={7}= ={6}= ={5}= >{1}< >{4}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors~a~async-a~async-b~async-c~b~c)
         > ./c c
         > ./b b
         > ./a a
@@ -80,62 +80,62 @@ Child all-chunks:
         > ./b [8] ./index.js 2:0-47
         > ./a [8] ./index.js 1:0-47
         [1] ./node_modules/x.js 20 bytes {0} {3} [built]
-    chunk    {1} default/async-b~async-c~async-g~b~c.js (async-b~async-c~async-g~b~c) 20 bytes <{0}> <{2}> <{10}> <{3}> <{6}> <{9}> ={5}= ={0}= ={4}= ={3}= ={8}= ={2}= ={7}= [rendered] split chunk (cache group: default) (name: async-b~async-c~async-g~b~c)
+    chunk    {1} default/async-b~async-c~async-g~b~c.js (async-b~async-c~async-g~b~c) 20 bytes <{0}> <{2}> <{10}> <{3}> <{5}> <{9}> ={4}= ={0}= ={8}= ={3}= ={7}= ={2}= ={6}= [rendered] split chunk (cache group: default) (name: async-b~async-c~async-g~b~c)
         > ./g [] 6:0-47
         > ./g [] 6:0-47
         > ./c [8] ./index.js 3:0-47
         > ./b [8] ./index.js 2:0-47
         [2] ./f.js 20 bytes {1} {11} {12} [built]
-    chunk    {2} default/a~async-a~async-b~b.js (a~async-a~async-b~b) 20 bytes <{9}> ={0}= ={11}= ={10}= ={1}= ={7}= ={3}= ={6}= >{1}< >{5}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors~a~async-a~async-b~b)
+    chunk    {2} default/a~async-a~async-b~b.js (a~async-a~async-b~b) 20 bytes <{9}> ={0}= ={11}= ={10}= ={1}= ={6}= ={3}= ={5}= >{1}< >{4}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors~a~async-a~async-b~b)
         > ./b b
         > ./a a
         > ./b [8] ./index.js 2:0-47
         > ./a [8] ./index.js 1:0-47
         [3] ./node_modules/y.js 20 bytes {2} [built]
-    chunk    {3} default/a~async-a~async-b~async-c~b~c.js (a~async-a~async-b~async-c~b~c) 40 bytes <{9}> ={0}= ={4}= ={1}= ={8}= ={2}= ={6}= >{1}< >{5}< [rendered] split chunk (cache group: default) (name: a~async-a~async-b~async-c~b~c)
+    chunk    {3} default/a~async-a~async-b~async-c~b~c.js (a~async-a~async-b~async-c~b~c) 40 bytes <{9}> ={0}= ={8}= ={1}= ={7}= ={2}= ={5}= >{1}< >{4}< [rendered] split chunk (cache group: default) (name: a~async-a~async-b~async-c~b~c)
         > ./c [8] ./index.js 3:0-47
         > ./a [8] ./index.js 1:0-47
-        [0] ./d.js 20 bytes {3} {7} {10} {11} {12} [built]
+        [0] ./d.js 20 bytes {3} {6} {10} {11} {12} [built]
         [1] ./node_modules/x.js 20 bytes {0} {3} [built]
-    chunk    {4} default/vendors~async-c~c.js (vendors~async-c~c) 20 bytes <{9}> ={0}= ={12}= ={1}= ={3}= ={8}= [initial] [rendered] split chunk (cache group: vendors) (name: vendors~async-c~c)
-        > ./c c
-        > ./c [8] ./index.js 3:0-47
-        [7] ./node_modules/z.js 20 bytes {4} [built]
-    chunk    {5} default/async-g.js (async-g) 34 bytes <{0}> <{2}> <{10}> <{3}> <{6}> ={1}= [rendered]
+    chunk    {4} default/async-g.js (async-g) 34 bytes <{0}> <{2}> <{10}> <{3}> <{5}> ={1}= [rendered]
         > ./g [] 6:0-47
         > ./g [] 6:0-47
-        [9] ./g.js 34 bytes {5} [built]
-    chunk    {6} default/async-a.js (async-a) 156 bytes <{9}> ={0}= ={2}= ={3}= >{1}< >{5}< [rendered]
+        [9] ./g.js 34 bytes {4} [built]
+    chunk    {5} default/async-a.js (async-a) 156 bytes <{9}> ={0}= ={2}= ={3}= >{1}< >{4}< [rendered]
         > ./a [8] ./index.js 1:0-47
-        [6] ./a.js + 1 modules 156 bytes {6} {10} [built]
+        [6] ./a.js + 1 modules 156 bytes {5} {10} [built]
             | ./a.js 121 bytes [built]
             | ./e.js 20 bytes [built]
-    chunk    {7} default/async-b.js (async-b) 92 bytes <{9}> ={0}= ={2}= ={1}= [rendered]
+    chunk    {6} default/async-b.js (async-b) 92 bytes <{9}> ={0}= ={2}= ={1}= [rendered]
         > ./b [8] ./index.js 2:0-47
-        [0] ./d.js 20 bytes {3} {7} {10} {11} {12} [built]
-        [4] ./b.js 72 bytes {7} {11} [built]
-    chunk    {8} default/async-c.js (async-c) 72 bytes <{9}> ={0}= ={4}= ={1}= ={3}= [rendered]
+        [0] ./d.js 20 bytes {3} {6} {10} {11} {12} [built]
+        [4] ./b.js 72 bytes {6} {11} [built]
+    chunk    {7} default/async-c.js (async-c) 72 bytes <{9}> ={0}= ={8}= ={1}= ={3}= [rendered]
+        > ./c [8] ./index.js 3:0-47
+        [5] ./c.js 72 bytes {7} {12} [built]
+    chunk    {8} default/vendors~async-c~c.js (vendors~async-c~c) 20 bytes <{9}> ={0}= ={12}= ={1}= ={3}= ={7}= [initial] [rendered] split chunk (cache group: vendors) (name: vendors~async-c~c)
+        > ./c c
         > ./c [8] ./index.js 3:0-47
-        [5] ./c.js 72 bytes {8} {12} [built]
-    chunk    {9} default/main.js (main) 147 bytes >{0}< >{2}< >{1}< >{7}< >{3}< >{6}< >{4}< >{8}< [entry] [rendered]
+        [7] ./node_modules/z.js 20 bytes {8} [built]
+    chunk    {9} default/main.js (main) 147 bytes >{0}< >{2}< >{1}< >{6}< >{3}< >{5}< >{8}< >{7}< [entry] [rendered]
         > ./ main
         [8] ./index.js 147 bytes {9} [built]
-    chunk   {10} default/a.js (a) 176 bytes ={0}= ={2}= >{1}< >{5}< [entry] [rendered]
+    chunk   {10} default/a.js (a) 176 bytes ={0}= ={2}= >{1}< >{4}< [entry] [rendered]
         > ./a a
-        [0] ./d.js 20 bytes {3} {7} {10} {11} {12} [built]
-        [6] ./a.js + 1 modules 156 bytes {6} {10} [built]
+        [0] ./d.js 20 bytes {3} {6} {10} {11} {12} [built]
+        [6] ./a.js + 1 modules 156 bytes {5} {10} [built]
             | ./a.js 121 bytes [built]
             | ./e.js 20 bytes [built]
     chunk   {11} default/b.js (b) 112 bytes ={0}= ={2}= [entry] [rendered]
         > ./b b
-        [0] ./d.js 20 bytes {3} {7} {10} {11} {12} [built]
+        [0] ./d.js 20 bytes {3} {6} {10} {11} {12} [built]
         [2] ./f.js 20 bytes {1} {11} {12} [built]
-        [4] ./b.js 72 bytes {7} {11} [built]
-    chunk   {12} default/c.js (c) 112 bytes ={0}= ={4}= [entry] [rendered]
+        [4] ./b.js 72 bytes {6} {11} [built]
+    chunk   {12} default/c.js (c) 112 bytes ={0}= ={8}= [entry] [rendered]
         > ./c c
-        [0] ./d.js 20 bytes {3} {7} {10} {11} {12} [built]
+        [0] ./d.js 20 bytes {3} {6} {10} {11} {12} [built]
         [2] ./f.js 20 bytes {1} {11} {12} [built]
-        [5] ./c.js 72 bytes {8} {12} [built]
+        [5] ./c.js 72 bytes {7} {12} [built]
 Child manual:
     Entrypoint main = default/main.js
     Entrypoint a = default/vendors.js default/a.js