use a Set for Module.chunks

This commit is contained in:
Tobias Koppers 2017-04-18 22:30:18 +02:00
parent 25ae65ed72
commit e8bc9c2b3b
6 changed files with 95 additions and 53 deletions

View File

@ -507,7 +507,7 @@ class Compilation extends Tapable {
if(err) return callback(err);
deps.forEach(d => {
if(d.module && d.module.removeReason(module, d)) {
module.chunks.forEach(chunk => {
module.forEachChunk(chunk => {
if(!d.module.hasReasonForChunk(chunk)) {
if(d.module.removeChunk(chunk)) {
this.removeChunkFromDependencies(d.module, chunk);

View File

@ -4,6 +4,7 @@
*/
"use strict";
const util = require("util");
const DependenciesBlock = require("./DependenciesBlock");
const ModuleReason = require("./ModuleReason");
const Template = require("./Template");
@ -36,7 +37,9 @@ class Module extends DependenciesBlock {
this.used = null;
this.usedExports = null;
this.providedExports = null;
this.chunks = [];
this._chunks = new Set();
this._chunksIsSorted = true;
this._chunksDebugIdent = undefined;
this.warnings = [];
this.dependenciesWarnings = [];
this.errors = [];
@ -55,7 +58,9 @@ class Module extends DependenciesBlock {
this.used = null;
this.usedExports = null;
this.providedExports = null;
this.chunks.length = 0;
this._chunks.clear();
this._chunksDebugIdent = undefined;
this._chunksIsSorted = false;
super.disconnect();
}
@ -65,26 +70,74 @@ class Module extends DependenciesBlock {
this.index = null;
this.index2 = null;
this.depth = null;
this.chunks.length = 0;
this._chunks.clear();
this._chunksDebugIdent = undefined;
this._chunksIsSorted = false;
super.unseal();
}
addChunk(chunk) {
let idx = this.chunks.indexOf(chunk);
if(idx < 0)
this.chunks.push(chunk);
this._chunks.add(chunk);
this._chunksDebugIdent = undefined;
this._chunksIsSorted = false;
}
removeChunk(chunk) {
let idx = this.chunks.indexOf(chunk);
if(idx >= 0) {
this.chunks.splice(idx, 1);
if(this._chunks.delete(chunk)) {
this._chunksDebugIdent = undefined;
chunk.removeModule(this);
return true;
}
return false;
}
isInChunk(chunk) {
return this._chunks.has(chunk);
}
getChunkIdsIdent() {
if(this._chunksDebugIdent !== undefined) return this._chunksDebugIdent;
this._ensureChunksSorted();
const chunks = this._chunks;
const list = [];
for(let chunk of chunks) {
const debugId = chunk.debugId;
if(typeof debugId !== "number") {
return this._chunksDebugIdent = null;
}
list.push(debugId);
}
return this._chunksDebugIdent = list.join(",");
}
forEachChunk(fn) {
this._chunks.forEach(fn);
}
mapChunks(fn) {
const chunks = this._chunks;
const size = chunks.size;
const array = new Array(size);
let idx = 0;
for(let chunk of chunks) {
array[idx++] = fn(chunk, idx, chunks);
}
return array;
}
getNumberOfChunks() {
return this._chunks.size;
}
_ensureChunksSorted() {
if(this._chunksIsSorted) return;
this._chunks = new Set(Array.from(this._chunks).sort(byId));
this._chunksIsSorted = true;
}
addReason(module, dependency) {
this.reasons.push(new ModuleReason(module, dependency));
}
@ -105,7 +158,7 @@ class Module extends DependenciesBlock {
if(r.chunks) {
if(r.chunks.indexOf(chunk) >= 0)
return true;
} else if(r.module.chunks.indexOf(chunk) >= 0)
} else if(r.module._chunks.has(chunk))
return true;
}
return false;
@ -114,9 +167,9 @@ class Module extends DependenciesBlock {
rewriteChunkInReasons(oldChunk, newChunks) {
this.reasons.forEach(r => {
if(!r.chunks) {
if(r.module.chunks.indexOf(oldChunk) < 0)
if(!r.module._chunks.has(oldChunk))
return;
r.chunks = r.module.chunks;
r.chunks = Array.from(r.module._chunks);
}
r.chunks = r.chunks.reduce((arr, c) => {
addToSet(arr, c !== oldChunk ? [c] : newChunks);
@ -160,7 +213,7 @@ class Module extends DependenciesBlock {
sortItems() {
super.sortItems();
this.chunks.sort(byId);
this._ensureChunksSorted();
this.reasons.sort((a, b) => byId(a.module, b.module));
}
@ -178,6 +231,17 @@ Object.defineProperty(Module.prototype, "entry", {
throw new Error("Module.entry was removed. Use Chunk.entryModule");
}
});
Object.defineProperty(Module.prototype, "chunks", {
configurable: false,
get: util.deprecate(() => {
return Array.from(this._chunks);
}, "Module.chunks: Use Module.forEachChunk/mapChunks/getNumberOfChunks/isInChunk/addChunk/removeChunk instead"),
set() {
throw new Error("Readonly. Use Module.addChunk/removeChunk to modify chunks.");
}
});
Module.prototype.identifier = null;
Module.prototype.readableIdentifier = null;
Module.prototype.build = null;

View File

@ -112,7 +112,7 @@ ModuleFilenameHelpers.createFooter = function createFooter(module, requestShorte
"// WEBPACK FOOTER",
`// ${module.readableIdentifier(requestShortener)}`,
`// module id = ${module.id}`,
`// module chunks = ${module.chunks.map(c => c.id).join(" ")}`
`// module chunks = ${module.mapChunks(c => c.id).join(" ")}`
].join("\n");
}
};

View File

@ -279,7 +279,7 @@ class Stats {
built: !!module.built,
optional: !!module.optional,
prefetched: !!module.prefetched,
chunks: module.chunks.map(chunk => chunk.id),
chunks: module.mapChunks(chunk => chunk.id),
assets: Object.keys(module.assets || {}),
issuer: module.issuer && module.issuer.identifier(),
issuerId: module.issuer && module.issuer.id,

View File

@ -16,12 +16,12 @@ class OccurrenceOrderPlugin {
compiler.plugin("compilation", (compilation) => {
compilation.plugin("optimize-module-order", (modules) => {
function entryChunks(m) {
return m.chunks.map((c) => {
let total = 0;
m.forEachChunk(c => {
const sum = (c.isInitial() ? 1 : 0) + (c.entryModule === m ? 1 : 0);
return sum;
}).reduce((a, b) => {
return a + b;
}, 0);
total += sum;
});
return total;
}
function occursInEntry(m) {
@ -37,14 +37,17 @@ class OccurrenceOrderPlugin {
function occurs(m) {
if(typeof m.__OccurenceOrderPlugin_occurs === "number") return m.__OccurenceOrderPlugin_occurs;
let numberEntry = 0;
m.forEachChunk(c => {
if(c.entryModule === m)
numberEntry++;
});
const result = m.reasons.map((r) => {
if(!r.module) return 0;
return r.module.chunks.length;
return r.module.getNumberOfChunks();
}).reduce((a, b) => {
return a + b;
}, 0) + m.chunks.length + m.chunks.filter((c) => {
return c.entryModule === m;
}).length;
}, 0) + m.getNumberOfChunks() + numberEntry;
return m.__OccurenceOrderPlugin_occurs = result;
}
modules.sort((a, b) => {

View File

@ -4,18 +4,8 @@
*/
"use strict";
function chunkContainsModule(chunk, module) {
const chunks = module.chunks;
const modules = chunk.modules;
if(chunks.length < modules.length) {
return chunks.indexOf(chunk) >= 0;
} else {
return modules.indexOf(module) >= 0;
}
}
function hasModule(chunk, module, checkedChunks) {
if(chunkContainsModule(chunk, module)) return [chunk];
if(module.isInChunk(chunk)) return [chunk];
if(chunk.parents.length === 0) return false;
return allHaveModule(chunk.parents.filter((c) => {
return checkedChunks.indexOf(c) < 0;
@ -41,21 +31,6 @@ function allHaveModule(someChunks, module, checkedChunks) {
return chunks;
}
function debugIds(chunks) {
var list = [];
for(var i = 0; i < chunks.length; i++) {
var debugId = chunks[i].debugId;
if(typeof debugId !== "number") {
return "no";
}
list.push(debugId);
}
list.sort();
return list.join(",");
}
class RemoveParentModulesPlugin {
apply(compiler) {
@ -71,9 +46,9 @@ class RemoveParentModulesPlugin {
for(var i = 0; i < modules.length; i++) {
var module = modules[i];
var dId = debugIds(module.chunks);
var dId = module.getChunkIdsIdent();
var parentChunksWithModule;
if((dId in cache) && dId !== "no") {
if(dId !== null && (dId in cache)) {
parentChunksWithModule = cache[dId];
} else {
parentChunksWithModule = cache[dId] = allHaveModule(chunk.parents, module);