Skip to content

Commit

Permalink
Use a Set to store modules in a chunk
Browse files Browse the repository at this point in the history
  • Loading branch information
sokra committed Apr 21, 2017
1 parent 8aa8a7b commit 8fb1ee0
Show file tree
Hide file tree
Showing 19 changed files with 156 additions and 116 deletions.
12 changes: 1 addition & 11 deletions lib/AsyncDependenciesBlock.js
Expand Up @@ -37,17 +37,7 @@ module.exports = class AsyncDependenciesBlock extends DependenciesBlock {
sortItems() {
super.sortItems();
if(this.chunks) {
this.chunks.sort((a, b) => {
let i = 0;
while(true) { // eslint-disable-line no-constant-condition
if(!a.modules[i] && !b.modules[i]) return 0;
if(!a.modules[i]) return -1;
if(!b.modules[i]) return 1;
if(a.modules[i].id > b.modules[i].id) return 1;
if(a.modules[i].id < b.modules[i].id) return -1;
i++;
}
});
this.chunks.sort((a, b) => a.compareTo(b));
}
}
};
111 changes: 94 additions & 17 deletions lib/Chunk.js
Expand Up @@ -4,6 +4,7 @@
*/
"use strict";

const util = require("util");
const compareLocations = require("./compareLocations");
let debugId = 1000;

Expand All @@ -20,7 +21,8 @@ class Chunk {
this.ids = null;
this.debugId = debugId++;
this.name = name;
this.modules = [];
this._modules = new Set();
this._modulesIsSorted = true;
this.entrypoints = [];
this.chunks = [];
this.parents = [];
Expand Down Expand Up @@ -88,17 +90,20 @@ class Chunk {
}

addModule(module) {
return this.addToCollection(this.modules, module);
if(!this._modules.has(module)) {
this._modules.add(module);
this._modulesIsSorted = false;
return true;
}
return false;
}

addBlock(block) {
return this.addToCollection(this.blocks, block);
}

removeModule(module) {
const idx = this.modules.indexOf(module);
if(idx >= 0) {
this.modules.splice(idx, 1);
if(this._modules.delete(module)) {
module.removeChunk(this);
return true;
}
Expand Down Expand Up @@ -133,9 +138,72 @@ class Chunk {
});
}

setModules(modules) {
this._modules = new Set(modules);
this._modulesIsSorted = false;
}

getNumberOfModules() {
return this._modules.size;
}

get modulesIterable() {
return this._modules;
}

forEachModule(fn) {
this._modules.forEach(fn);
}

mapModules(fn) {
const modules = this._modules;
const array = new Array(modules.size);
let idx = 0;
for(let module of modules) {
array[idx++] = fn(module, idx, modules);
}
return array;
}

_ensureModulesSorted() {
if(this._modulesIsSorted) return;
this._modules = new Set(Array.from(this._modules).sort((a, b) => {
if(a.identifier() > b.identifier()) return 1;
if(a.identifier() < b.identifier()) return -1;
return 0;
}));
this._modulesIsSorted = true;
}

compareTo(otherChunk) {
this._ensureModulesSorted();
otherChunk._ensureModulesSorted();
if(this._modules.size > otherChunk._modules.size) return -1;
if(this._modules.size < otherChunk._modules.size) return 1;
const a = this._modules[Symbol.iterator]();
const b = otherChunk._modules[Symbol.iterator]();
while(true) { // eslint-disable-line
const aItem = a.next();
const bItem = b.next();
if(aItem.done) return 0;
const aModuleIdentifier = aItem.value.identifier();
const bModuleIdentifier = bItem.value.identifier();
if(aModuleIdentifier > bModuleIdentifier) return -1;
if(aModuleIdentifier < bModuleIdentifier) return 1;
}
}

containsModule(module) {
return this._modules.has(module);
}

getModules() {
return Array.from(this._modules);
}

remove(reason) {
// cleanup modules
this.modules.slice().forEach(module => {
Array.from(this._modules).forEach(module => {
module.removeChunk(this);
});

Expand Down Expand Up @@ -219,9 +287,9 @@ class Chunk {
return false;
}

const otherChunkModules = otherChunk.modules.slice();
const otherChunkModules = Array.from(otherChunk._modules);
otherChunkModules.forEach(module => otherChunk.moveModule(module, this));
otherChunk.modules.length = 0;
otherChunk._modules.clear();

otherChunk.parents.forEach(parentChunk => parentChunk.replaceChunk(otherChunk, this));
otherChunk.parents.length = 0;
Expand Down Expand Up @@ -276,14 +344,14 @@ class Chunk {
}

isEmpty() {
return this.modules.length === 0;
return this._modules.size === 0;
}

updateHash(hash) {
hash.update(`${this.id} `);
hash.update(this.ids ? this.ids.join(",") : "");
hash.update(`${this.name || ""} `);
this.modules.forEach(m => m.updateHash(hash));
this._modules.forEach(m => m.updateHash(hash));
}

canBeIntegrated(otherChunk) {
Expand All @@ -307,8 +375,8 @@ class Chunk {

modulesSize() {
let count = 0;
for(let i = 0; i < this.modules.length; i++) {
count += this.modules[i].size();
for(let module of this._modules) {
count += module.size();
}
return count;
}
Expand All @@ -325,9 +393,8 @@ class Chunk {

let integratedModulesSize = this.modulesSize();
// only count modules that do not exist in this chunk!
for(let i = 0; i < otherChunk.modules.length; i++) {
const otherModule = otherChunk.modules[i];
if(this.modules.indexOf(otherModule) === -1) {
for(let otherModule of otherChunk._modules) {
if(!this._modules.has(otherModule)) {
integratedModulesSize += otherModule.size();
}
}
Expand Down Expand Up @@ -356,7 +423,7 @@ class Chunk {
}

sortItems() {
this.modules.sort(byId);
this._modules = new Set(Array.from(this._modules).sort(byId));
this.origins.sort((a, b) => {
const aIdent = a.module.identifier();
const bIdent = b.module.identifier();
Expand All @@ -373,7 +440,7 @@ class Chunk {
}

toString() {
return `Chunk[${this.modules.join()}]`;
return `Chunk[${Array.from(this._modules).join()}]`;
}

checkConstraints() {
Expand All @@ -393,4 +460,14 @@ class Chunk {
}
}

Object.defineProperty(Chunk.prototype, "modules", {
configurable: false,
get: util.deprecate(function() {
return Array.from(this._modules);
}, "Chunk.modules is deprecated. Use Chunk.getNumberOfModules/mapModules/forEachModule/containsModule instead."),
set: util.deprecate(function(value) {
this.setModules(value);
}, "Chunk.modules is deprecated. Use Chunk.addModule/removeModule instead.")
})

module.exports = Chunk;
2 changes: 1 addition & 1 deletion lib/FlagInitialModulesAsUsedPlugin.js
Expand Up @@ -12,7 +12,7 @@ class FlagInitialModulesAsUsedPlugin {
if(!chunk.isInitial()) {
return;
}
chunk.modules.forEach((module) => {
chunk.forEachModule((module) => {
module.usedExports = true;
});
});
Expand Down
6 changes: 3 additions & 3 deletions lib/HotModuleReplacementPlugin.js
Expand Up @@ -54,7 +54,7 @@ HotModuleReplacementPlugin.prototype.apply = function(compiler) {
});
records.chunkModuleIds = {};
this.chunks.forEach(function(chunk) {
records.chunkModuleIds[chunk.id] = chunk.modules.map(function(m) {
records.chunkModuleIds[chunk.id] = chunk.mapModules(function(m) {
return m.id;
});
});
Expand Down Expand Up @@ -112,11 +112,11 @@ HotModuleReplacementPlugin.prototype.apply = function(compiler) {
chunkId = isNaN(+chunkId) ? chunkId : +chunkId;
var currentChunk = this.chunks.find(chunk => chunk.id === chunkId);
if(currentChunk) {
var newModules = currentChunk.modules.filter(function(module) {
var newModules = currentChunk.mapModules(m => m).filter(function(module) {
return module.hotUpdate;
});
var allModules = {};
currentChunk.modules.forEach(function(module) {
currentChunk.forEachModule(function(module) {
allModules[module.id] = true;
});
var removedModules = records.chunkModuleIds[chunkId].filter(function(id) {
Expand Down
11 changes: 6 additions & 5 deletions lib/HotUpdateChunkTemplate.js
Expand Up @@ -5,18 +5,19 @@
"use strict";

const Template = require("./Template");
const Chunk = require("./Chunk");

module.exports = class HotUpdateChunkTemplate extends Template {
constructor(outputOptions) {
super(outputOptions);
}

render(id, modules, removedModules, hash, moduleTemplate, dependencyTemplates) {
const modulesSource = this.renderChunkModules({
id: id,
modules: modules,
removedModules: removedModules
}, moduleTemplate, dependencyTemplates);
const hotUpdateChunk = new Chunk();
hotUpdateChunk.id = id;
hotUpdateChunk.setModules(modules);
hotUpdateChunk.removedModules = removedModules;
const modulesSource = this.renderChunkModules(hotUpdateChunk, moduleTemplate, dependencyTemplates);
const core = this.applyPluginsWaterfall("modules", modulesSource, modules, removedModules, moduleTemplate, dependencyTemplates);
const source = this.applyPluginsWaterfall("render", core, modules, removedModules, hash, id, moduleTemplate, dependencyTemplates);
return source;
Expand Down
15 changes: 10 additions & 5 deletions lib/LibManifestPlugin.js
Expand Up @@ -30,19 +30,24 @@ class LibManifestPlugin {
const manifest = {
name,
type: this.options.type,
content: chunk.modules.reduce((obj, module) => {
content: chunk.mapModules(module => {
if(module.libIdent) {
const ident = module.libIdent({
context: this.options.context || compiler.options.context
});
if(ident) {
obj[ident] = {
id: module.id,
meta: module.meta,
exports: Array.isArray(module.providedExports) ? module.providedExports : undefined
return {
ident,
data: {
id: module.id,
meta: module.meta,
exports: Array.isArray(module.providedExports) ? module.providedExports : undefined
}
};
}
}
}).filter(Boolean).reduce((obj, item) => {
obj[item.ident] = item.data;
return obj;
}, {})
};
Expand Down
8 changes: 4 additions & 4 deletions lib/Stats.js
Expand Up @@ -327,19 +327,19 @@ class Stats {
entry: chunk.hasRuntime(),
recorded: chunk.recorded,
extraAsync: !!chunk.extraAsync,
size: chunk.modules.reduce((size, module) => size + module.size(), 0),
size: chunk.mapModules(m => m.size()).reduce((size, moduleSize) => size + moduleSize, 0),
names: chunk.name ? [chunk.name] : [],
files: chunk.files.slice(),
hash: chunk.renderedHash,
parents: chunk.parents.map(c => c.id)
};
if(showChunkModules) {
obj.modules = chunk.modules
.slice()
obj.modules = chunk
.mapModules(m => m)
.sort(sortByField("depth"))
.filter(createModuleFilter())
.map(fnModule);
obj.filteredModules = chunk.modules.length - obj.modules.length;
obj.filteredModules = chunk.getNumberOfModules() - obj.modules.length;
obj.modules.sort(sortByField(sortModules));
}
if(showChunkOrigins) {
Expand Down
6 changes: 3 additions & 3 deletions lib/Template.js
Expand Up @@ -94,12 +94,12 @@ module.exports = class Template extends Tapable {
renderChunkModules(chunk, moduleTemplate, dependencyTemplates, prefix) {
if(!prefix) prefix = "";
var source = new ConcatSource();
if(chunk.modules.length === 0) {
if(chunk.getNumberOfModules() === 0) {
source.add("[]");
return source;
}
var removedModules = chunk.removedModules;
var allModules = chunk.modules.map(function(module) {
var allModules = chunk.mapModules(function(module) {
return {
id: module.id,
source: moduleTemplate.render(module, dependencyTemplates, chunk)
Expand All @@ -113,7 +113,7 @@ module.exports = class Template extends Tapable {
});
});
}
var bounds = this.getModulesArrayBounds(chunk.modules);
var bounds = this.getModulesArrayBounds(allModules);

if(bounds) {
// Render a spare array
Expand Down
2 changes: 1 addition & 1 deletion lib/UmdMainTemplatePlugin.js
Expand Up @@ -32,7 +32,7 @@ class UmdMainTemplatePlugin {
apply(compilation) {
const mainTemplate = compilation.mainTemplate;
compilation.templatesPlugin("render-with-entry", function(source, chunk, hash) {
let externals = chunk.modules.filter(m => m.external);
let externals = chunk.mapModules(m => m).filter(m => m.external);
const optionalExternals = [];
let requiredExternals = [];
if(this.optionalAmdExternalAsGlobal) {
Expand Down

0 comments on commit 8fb1ee0

Please sign in to comment.