118 lines
4.3 KiB
JavaScript
118 lines
4.3 KiB
JavaScript
/*
|
|
MIT License http://www.opensource.org/licenses/mit-license.php
|
|
Author Tobias Koppers @sokra
|
|
*/
|
|
"use strict";
|
|
|
|
const identifierUtils = require("./util/identifier");
|
|
|
|
class RecordIdsPlugin {
|
|
|
|
apply(compiler) {
|
|
compiler.plugin("compilation", compilation => {
|
|
compilation.plugin("record-modules", (modules, records) => {
|
|
if(!records.modules) records.modules = {};
|
|
if(!records.modules.byIdentifier) records.modules.byIdentifier = {};
|
|
if(!records.modules.usedIds) records.modules.usedIds = {};
|
|
modules.forEach(function(module) {
|
|
if(!module.portableId) module.portableId = identifierUtils.makePathsRelative(compiler.context, module.identifier());
|
|
const identifier = module.portableId;
|
|
records.modules.byIdentifier[identifier] = module.id;
|
|
records.modules.usedIds[module.id] = module.id;
|
|
});
|
|
});
|
|
compilation.plugin("revive-modules", (modules, records) => {
|
|
if(!records.modules) return;
|
|
if(records.modules.byIdentifier) {
|
|
const usedIds = {};
|
|
modules.forEach(function(module) {
|
|
if(module.id !== null) return;
|
|
if(!module.portableId) module.portableId = identifierUtils.makePathsRelative(compiler.context, module.identifier());
|
|
const identifier = module.portableId;
|
|
const id = records.modules.byIdentifier[identifier];
|
|
if(id === undefined) return;
|
|
if(usedIds[id]) return;
|
|
usedIds[id] = true;
|
|
module.id = id;
|
|
});
|
|
}
|
|
compilation.usedModuleIds = records.modules.usedIds;
|
|
});
|
|
|
|
function getDepBlockIdent(chunk, block) {
|
|
const ident = [];
|
|
if(block.chunks.length > 1)
|
|
ident.push(block.chunks.indexOf(chunk));
|
|
while(block.parent) {
|
|
const p = block.parent;
|
|
const idx = p.blocks.indexOf(block);
|
|
const l = p.blocks.length - 1;
|
|
ident.push(`${idx}/${l}`);
|
|
block = block.parent;
|
|
}
|
|
if(!block.identifier) return null;
|
|
ident.push(identifierUtils.makePathsRelative(compiler.context, block.identifier()));
|
|
return ident.reverse().join(":");
|
|
}
|
|
compilation.plugin("record-chunks", (chunks, records) => {
|
|
records.nextFreeChunkId = compilation.nextFreeChunkId;
|
|
if(!records.chunks) records.chunks = {};
|
|
if(!records.chunks.byName) records.chunks.byName = {};
|
|
if(!records.chunks.byBlocks) records.chunks.byBlocks = {};
|
|
records.chunks.usedIds = {};
|
|
chunks.forEach(chunk => {
|
|
const name = chunk.name;
|
|
const blockIdents = chunk.blocks.map(getDepBlockIdent.bind(null, chunk)).filter(Boolean);
|
|
if(name) records.chunks.byName[name] = chunk.id;
|
|
blockIdents.forEach((blockIdent) => {
|
|
records.chunks.byBlocks[blockIdent] = chunk.id;
|
|
});
|
|
records.chunks.usedIds[chunk.id] = chunk.id;
|
|
});
|
|
});
|
|
compilation.plugin("revive-chunks", (chunks, records) => {
|
|
if(!records.chunks) return;
|
|
const usedIds = {};
|
|
if(records.chunks.byName) {
|
|
chunks.forEach(function(chunk) {
|
|
if(chunk.id !== null) return;
|
|
if(!chunk.name) return;
|
|
const id = records.chunks.byName[chunk.name];
|
|
if(id === undefined) return;
|
|
if(usedIds[id]) return;
|
|
usedIds[id] = true;
|
|
chunk.id = id;
|
|
});
|
|
}
|
|
if(records.chunks.byBlocks) {
|
|
const argumentedChunks = chunks.filter(chunk => chunk.id === null).map(chunk => ({
|
|
chunk,
|
|
blockIdents: chunk.blocks.map(getDepBlockIdent.bind(null, chunk)).filter(Boolean)
|
|
})).filter(arg => arg.blockIdents.length > 0);
|
|
let blockIdentsCount = {};
|
|
argumentedChunks.forEach((arg, idx) => {
|
|
arg.blockIdents.forEach(blockIdent => {
|
|
const id = records.chunks.byBlocks[blockIdent];
|
|
if(typeof id !== "number") return;
|
|
const accessor = `${id}:${idx}`;
|
|
blockIdentsCount[accessor] = (blockIdentsCount[accessor] || 0) + 1;
|
|
});
|
|
});
|
|
blockIdentsCount = Object.keys(blockIdentsCount).map(accessor => [blockIdentsCount[accessor]].concat(accessor.split(":").map(Number))).sort((a, b) => b[0] - a[0]);
|
|
blockIdentsCount.forEach(function(arg) {
|
|
const id = arg[1];
|
|
if(usedIds[id]) return;
|
|
const idx = arg[2];
|
|
const chunk = argumentedChunks[idx].chunk;
|
|
if(chunk.id !== null) return;
|
|
usedIds[id] = true;
|
|
chunk.id = id;
|
|
});
|
|
}
|
|
compilation.usedChunkIds = records.chunks.usedIds;
|
|
});
|
|
});
|
|
}
|
|
}
|
|
module.exports = RecordIdsPlugin;
|