Skip to content

Commit e8bc9c2

Browse files
committed
use a Set for Module.chunks
1 parent 25ae65e commit e8bc9c2

6 files changed

Lines changed: 95 additions & 53 deletions

File tree

lib/Compilation.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ class Compilation extends Tapable {
507507
if(err) return callback(err);
508508
deps.forEach(d => {
509509
if(d.module && d.module.removeReason(module, d)) {
510-
module.chunks.forEach(chunk => {
510+
module.forEachChunk(chunk => {
511511
if(!d.module.hasReasonForChunk(chunk)) {
512512
if(d.module.removeChunk(chunk)) {
513513
this.removeChunkFromDependencies(d.module, chunk);

lib/Module.js

Lines changed: 77 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
"use strict";
66

7+
const util = require("util");
78
const DependenciesBlock = require("./DependenciesBlock");
89
const ModuleReason = require("./ModuleReason");
910
const Template = require("./Template");
@@ -36,7 +37,9 @@ class Module extends DependenciesBlock {
3637
this.used = null;
3738
this.usedExports = null;
3839
this.providedExports = null;
39-
this.chunks = [];
40+
this._chunks = new Set();
41+
this._chunksIsSorted = true;
42+
this._chunksDebugIdent = undefined;
4043
this.warnings = [];
4144
this.dependenciesWarnings = [];
4245
this.errors = [];
@@ -55,7 +58,9 @@ class Module extends DependenciesBlock {
5558
this.used = null;
5659
this.usedExports = null;
5760
this.providedExports = null;
58-
this.chunks.length = 0;
61+
this._chunks.clear();
62+
this._chunksDebugIdent = undefined;
63+
this._chunksIsSorted = false;
5964
super.disconnect();
6065
}
6166

@@ -65,26 +70,74 @@ class Module extends DependenciesBlock {
6570
this.index = null;
6671
this.index2 = null;
6772
this.depth = null;
68-
this.chunks.length = 0;
73+
this._chunks.clear();
74+
this._chunksDebugIdent = undefined;
75+
this._chunksIsSorted = false;
6976
super.unseal();
7077
}
7178

7279
addChunk(chunk) {
73-
let idx = this.chunks.indexOf(chunk);
74-
if(idx < 0)
75-
this.chunks.push(chunk);
80+
this._chunks.add(chunk);
81+
this._chunksDebugIdent = undefined;
82+
this._chunksIsSorted = false;
7683
}
7784

7885
removeChunk(chunk) {
79-
let idx = this.chunks.indexOf(chunk);
80-
if(idx >= 0) {
81-
this.chunks.splice(idx, 1);
86+
if(this._chunks.delete(chunk)) {
87+
this._chunksDebugIdent = undefined;
8288
chunk.removeModule(this);
8389
return true;
8490
}
8591
return false;
8692
}
8793

94+
isInChunk(chunk) {
95+
return this._chunks.has(chunk);
96+
}
97+
98+
getChunkIdsIdent() {
99+
if(this._chunksDebugIdent !== undefined) return this._chunksDebugIdent;
100+
this._ensureChunksSorted();
101+
const chunks = this._chunks;
102+
const list = [];
103+
for(let chunk of chunks) {
104+
const debugId = chunk.debugId;
105+
106+
if(typeof debugId !== "number") {
107+
return this._chunksDebugIdent = null;
108+
}
109+
110+
list.push(debugId);
111+
}
112+
113+
return this._chunksDebugIdent = list.join(",");
114+
}
115+
116+
forEachChunk(fn) {
117+
this._chunks.forEach(fn);
118+
}
119+
120+
mapChunks(fn) {
121+
const chunks = this._chunks;
122+
const size = chunks.size;
123+
const array = new Array(size);
124+
let idx = 0;
125+
for(let chunk of chunks) {
126+
array[idx++] = fn(chunk, idx, chunks);
127+
}
128+
return array;
129+
}
130+
131+
getNumberOfChunks() {
132+
return this._chunks.size;
133+
}
134+
135+
_ensureChunksSorted() {
136+
if(this._chunksIsSorted) return;
137+
this._chunks = new Set(Array.from(this._chunks).sort(byId));
138+
this._chunksIsSorted = true;
139+
}
140+
88141
addReason(module, dependency) {
89142
this.reasons.push(new ModuleReason(module, dependency));
90143
}
@@ -105,7 +158,7 @@ class Module extends DependenciesBlock {
105158
if(r.chunks) {
106159
if(r.chunks.indexOf(chunk) >= 0)
107160
return true;
108-
} else if(r.module.chunks.indexOf(chunk) >= 0)
161+
} else if(r.module._chunks.has(chunk))
109162
return true;
110163
}
111164
return false;
@@ -114,9 +167,9 @@ class Module extends DependenciesBlock {
114167
rewriteChunkInReasons(oldChunk, newChunks) {
115168
this.reasons.forEach(r => {
116169
if(!r.chunks) {
117-
if(r.module.chunks.indexOf(oldChunk) < 0)
170+
if(!r.module._chunks.has(oldChunk))
118171
return;
119-
r.chunks = r.module.chunks;
172+
r.chunks = Array.from(r.module._chunks);
120173
}
121174
r.chunks = r.chunks.reduce((arr, c) => {
122175
addToSet(arr, c !== oldChunk ? [c] : newChunks);
@@ -160,7 +213,7 @@ class Module extends DependenciesBlock {
160213

161214
sortItems() {
162215
super.sortItems();
163-
this.chunks.sort(byId);
216+
this._ensureChunksSorted();
164217
this.reasons.sort((a, b) => byId(a.module, b.module));
165218
}
166219

@@ -178,6 +231,17 @@ Object.defineProperty(Module.prototype, "entry", {
178231
throw new Error("Module.entry was removed. Use Chunk.entryModule");
179232
}
180233
});
234+
235+
Object.defineProperty(Module.prototype, "chunks", {
236+
configurable: false,
237+
get: util.deprecate(() => {
238+
return Array.from(this._chunks);
239+
}, "Module.chunks: Use Module.forEachChunk/mapChunks/getNumberOfChunks/isInChunk/addChunk/removeChunk instead"),
240+
set() {
241+
throw new Error("Readonly. Use Module.addChunk/removeChunk to modify chunks.");
242+
}
243+
});
244+
181245
Module.prototype.identifier = null;
182246
Module.prototype.readableIdentifier = null;
183247
Module.prototype.build = null;

lib/ModuleFilenameHelpers.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ ModuleFilenameHelpers.createFooter = function createFooter(module, requestShorte
112112
"// WEBPACK FOOTER",
113113
`// ${module.readableIdentifier(requestShortener)}`,
114114
`// module id = ${module.id}`,
115-
`// module chunks = ${module.chunks.map(c => c.id).join(" ")}`
115+
`// module chunks = ${module.mapChunks(c => c.id).join(" ")}`
116116
].join("\n");
117117
}
118118
};

lib/Stats.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ class Stats {
279279
built: !!module.built,
280280
optional: !!module.optional,
281281
prefetched: !!module.prefetched,
282-
chunks: module.chunks.map(chunk => chunk.id),
282+
chunks: module.mapChunks(chunk => chunk.id),
283283
assets: Object.keys(module.assets || {}),
284284
issuer: module.issuer && module.issuer.identifier(),
285285
issuerId: module.issuer && module.issuer.id,

lib/optimize/OccurrenceOrderPlugin.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ class OccurrenceOrderPlugin {
1616
compiler.plugin("compilation", (compilation) => {
1717
compilation.plugin("optimize-module-order", (modules) => {
1818
function entryChunks(m) {
19-
return m.chunks.map((c) => {
19+
let total = 0;
20+
m.forEachChunk(c => {
2021
const sum = (c.isInitial() ? 1 : 0) + (c.entryModule === m ? 1 : 0);
21-
return sum;
22-
}).reduce((a, b) => {
23-
return a + b;
24-
}, 0);
22+
total += sum;
23+
});
24+
return total;
2525
}
2626

2727
function occursInEntry(m) {
@@ -37,14 +37,17 @@ class OccurrenceOrderPlugin {
3737

3838
function occurs(m) {
3939
if(typeof m.__OccurenceOrderPlugin_occurs === "number") return m.__OccurenceOrderPlugin_occurs;
40+
let numberEntry = 0;
41+
m.forEachChunk(c => {
42+
if(c.entryModule === m)
43+
numberEntry++;
44+
});
4045
const result = m.reasons.map((r) => {
4146
if(!r.module) return 0;
42-
return r.module.chunks.length;
47+
return r.module.getNumberOfChunks();
4348
}).reduce((a, b) => {
4449
return a + b;
45-
}, 0) + m.chunks.length + m.chunks.filter((c) => {
46-
return c.entryModule === m;
47-
}).length;
50+
}, 0) + m.getNumberOfChunks() + numberEntry;
4851
return m.__OccurenceOrderPlugin_occurs = result;
4952
}
5053
modules.sort((a, b) => {

lib/optimize/RemoveParentModulesPlugin.js

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,8 @@
44
*/
55
"use strict";
66

7-
function chunkContainsModule(chunk, module) {
8-
const chunks = module.chunks;
9-
const modules = chunk.modules;
10-
if(chunks.length < modules.length) {
11-
return chunks.indexOf(chunk) >= 0;
12-
} else {
13-
return modules.indexOf(module) >= 0;
14-
}
15-
}
16-
177
function hasModule(chunk, module, checkedChunks) {
18-
if(chunkContainsModule(chunk, module)) return [chunk];
8+
if(module.isInChunk(chunk)) return [chunk];
199
if(chunk.parents.length === 0) return false;
2010
return allHaveModule(chunk.parents.filter((c) => {
2111
return checkedChunks.indexOf(c) < 0;
@@ -41,21 +31,6 @@ function allHaveModule(someChunks, module, checkedChunks) {
4131
return chunks;
4232
}
4333

44-
function debugIds(chunks) {
45-
var list = [];
46-
for(var i = 0; i < chunks.length; i++) {
47-
var debugId = chunks[i].debugId;
48-
49-
if(typeof debugId !== "number") {
50-
return "no";
51-
}
52-
53-
list.push(debugId);
54-
}
55-
56-
list.sort();
57-
return list.join(",");
58-
}
5934

6035
class RemoveParentModulesPlugin {
6136
apply(compiler) {
@@ -71,9 +46,9 @@ class RemoveParentModulesPlugin {
7146
for(var i = 0; i < modules.length; i++) {
7247
var module = modules[i];
7348

74-
var dId = debugIds(module.chunks);
49+
var dId = module.getChunkIdsIdent();
7550
var parentChunksWithModule;
76-
if((dId in cache) && dId !== "no") {
51+
if(dId !== null && (dId in cache)) {
7752
parentChunksWithModule = cache[dId];
7853
} else {
7954
parentChunksWithModule = cache[dId] = allHaveModule(chunk.parents, module);

0 commit comments

Comments
 (0)