Skip to content

Commit 850e209

Browse files
committed
add per chunk index and index2
1 parent c39c963 commit 850e209

File tree

18 files changed

+341
-47
lines changed

18 files changed

+341
-47
lines changed

lib/ChunkGroup.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ class ChunkGroup {
7070
this.chunks = [];
7171
/** @type {OriginRecord[]} */
7272
this.origins = [];
73+
/** Indicies in top-down order */
74+
/** @private @type {Map<Module, number>} */
75+
this._moduleIndicies = new Map();
76+
/** Indicies in bottom-up order */
77+
/** @private @type {Map<Module, number>} */
78+
this._moduleIndicies2 = new Map();
7379
}
7480

7581
/**
@@ -441,6 +447,44 @@ class ChunkGroup {
441447
return result;
442448
}
443449

450+
/**
451+
* Sets the top-down index of a module in this ChunkGroup
452+
* @param {Module} module module for which the index should be set
453+
* @param {number} index the index of the module
454+
* @returns {void}
455+
*/
456+
setModuleIndex(module, index) {
457+
this._moduleIndicies.set(module, index);
458+
}
459+
460+
/**
461+
* Gets the top-down index of a module in this ChunkGroup
462+
* @param {Module} module the module
463+
* @returns {number} index
464+
*/
465+
getModuleIndex(module) {
466+
return this._moduleIndicies.get(module);
467+
}
468+
469+
/**
470+
* Sets the bottom-up index of a module in this ChunkGroup
471+
* @param {Module} module module for which the index should be set
472+
* @param {number} index the index of the module
473+
* @returns {void}
474+
*/
475+
setModuleIndex2(module, index) {
476+
this._moduleIndicies2.set(module, index);
477+
}
478+
479+
/**
480+
* Gets the bottom-up index of a module in this ChunkGroup
481+
* @param {Module} module the module
482+
* @returns {number} index
483+
*/
484+
getModuleIndex2(module) {
485+
return this._moduleIndicies2.get(module);
486+
}
487+
444488
checkConstraints() {
445489
const chunk = this;
446490
for (const child of chunk._children) {

lib/Compilation.js

Lines changed: 150 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ const Queue = require("./util/Queue");
3636
const SortableSet = require("./util/SortableSet");
3737
const GraphHelpers = require("./GraphHelpers");
3838

39+
/** @typedef {import("./Module")} Module */
40+
/** @typedef {import("./DependenciesBlock")} DependenciesBlock */
41+
/** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
42+
3943
const byId = (a, b) => {
4044
if (a.id < b.id) return -1;
4145
if (a.id > b.id) return 1;
@@ -89,6 +93,12 @@ const iterationOfArrayCallback = (arr, fn) => {
8993
}
9094
};
9195

96+
const reverseIterationOfArrayCallback = (arr, fn) => {
97+
for (let index = arr.length - 1; index >= 0; index--) {
98+
fn(arr[index]);
99+
}
100+
};
101+
92102
function addAllToSet(set, otherSet) {
93103
for (const item of otherSet) {
94104
set.add(item);
@@ -1006,6 +1016,13 @@ class Compilation extends Tapable {
10061016
}
10071017
}
10081018

1019+
/**
1020+
* @param {TODO} groupOptions options for the chunk group
1021+
* @param {Module} module the module the references the chunk group
1022+
* @param {TODO} loc the location from with the chunk group is reference (inside of module)
1023+
* @param {string} request the request from which the the chunk group is referenced
1024+
* @returns {ChunkGroup} the new or existing chunk group
1025+
*/
10091026
addChunkInGroup(groupOptions, module, loc, request) {
10101027
if (typeof groupOptions === "string") {
10111028
groupOptions = { name: groupOptions };
@@ -1155,7 +1172,12 @@ class Compilation extends Tapable {
11551172
}
11561173
}
11571174

1158-
// This method creates the Chunk graph from the Module graph
1175+
/**
1176+
* This method creates the Chunk graph from the Module graph
1177+
* @private
1178+
* @param {TODO[]} inputChunkGroups chunk groups which are processed
1179+
* @returns {void}
1180+
*/
11591181
processDependenciesBlocksForChunkGroups(inputChunkGroups) {
11601182
// Process is splitting into two parts:
11611183
// Part one traverse the module graph and builds a very basic chunks graph
@@ -1169,14 +1191,10 @@ class Compilation extends Tapable {
11691191
const allCreatedChunkGroups = new Set();
11701192

11711193
// PREPARE
1194+
/** @type {Map<DependenciesBlock, { modules: Module[], blocks: AsyncDependenciesBlock[]}>} */
11721195
const blockInfoMap = new Map();
11731196

1174-
const iteratorDependency = d => {
1175-
// We skip Dependencies without Reference
1176-
const ref = d.getReference();
1177-
if (!ref) {
1178-
return;
1179-
}
1197+
const iteratorDependencyReference = ref => {
11801198
// We skip Dependencies without Module pointer
11811199
const refModule = ref.module;
11821200
if (!refModule) {
@@ -1190,12 +1208,32 @@ class Compilation extends Tapable {
11901208
blockInfoModules.add(refModule);
11911209
};
11921210

1211+
/**
1212+
* @param {Dependency} d dependency
1213+
* @returns {void}
1214+
*/
1215+
const iteratorDependency = d => {
1216+
// We skip Dependencies without Reference
1217+
const refs = d.getReference(true);
1218+
if (Array.isArray(refs))
1219+
iterationOfArrayCallback(refs, iteratorDependencyReference);
1220+
else if (refs) iteratorDependencyReference(refs);
1221+
};
1222+
11931223
const iteratorBlockPrepare = b => {
11941224
blockInfoBlocks.push(b);
11951225
blockQueue.push(b);
11961226
};
11971227

1198-
let block, blockQueue, blockInfoModules, blockInfoBlocks;
1228+
/** @type {DependenciesBlock} */
1229+
let block;
1230+
/** @type {TODO} */
1231+
let blockQueue;
1232+
/** @type {Set<TODO>} */
1233+
let blockInfoModules;
1234+
/** @type {TODO[]} */
1235+
let blockInfoBlocks;
1236+
11991237
for (const module of this.modules) {
12001238
blockQueue = [module];
12011239
while (blockQueue.length > 0) {
@@ -1216,7 +1254,7 @@ class Compilation extends Tapable {
12161254
}
12171255

12181256
const blockInfo = {
1219-
modules: blockInfoModules,
1257+
modules: Array.from(blockInfoModules),
12201258
blocks: blockInfoBlocks
12211259
};
12221260
blockInfoMap.set(block, blockInfo);
@@ -1225,15 +1263,44 @@ class Compilation extends Tapable {
12251263

12261264
// PART ONE
12271265

1266+
/** @type {Map<ChunkGroup, { index: number, index2: number }>} */
1267+
const chunkGroupCounters = new Map();
1268+
for (const chunkGroup of inputChunkGroups) {
1269+
chunkGroupCounters.set(chunkGroup, { index: 0, index2: 0 });
1270+
}
1271+
12281272
const blockChunkGroups = new Map();
12291273

1230-
// Start with the provided modules/chunks
1231-
const queue = inputChunkGroups.map(chunkGroup => ({
1274+
const ENTER = 0;
1275+
const LEAVE = 1;
1276+
const ASYNC = 2;
1277+
1278+
/**
1279+
* @typedef {Object} QueueItem
1280+
* @property {number} action
1281+
* @property {DependenciesBlock} block
1282+
* @property {Module} module
1283+
* @property {Chunk} chunk
1284+
* @property {ChunkGroup} chunkGroup
1285+
*/
1286+
1287+
/**
1288+
* @param {ChunkGroup} chunkGroup chunk group
1289+
* @returns {QueueItem} queue item
1290+
*/
1291+
const chunkGroupToQueueItem = chunkGroup => ({
1292+
action: ENTER,
12321293
block: chunkGroup.chunks[0].entryModule,
12331294
module: chunkGroup.chunks[0].entryModule,
12341295
chunk: chunkGroup.chunks[0],
12351296
chunkGroup
1236-
}));
1297+
});
1298+
1299+
// Start with the provided modules/chunks
1300+
/** @type {QueueItem[]} */
1301+
let queue = inputChunkGroups.map(chunkGroupToQueueItem).reverse();
1302+
/** @type {QueueItem[]} */
1303+
let queueDelayed = [];
12371304

12381305
let module, chunk, chunkGroup;
12391306

@@ -1256,6 +1323,7 @@ class Compilation extends Tapable {
12561323
b.loc,
12571324
b.request
12581325
);
1326+
chunkGroupCounters.set(c, { index: 0, index2: 0 });
12591327
blockChunkGroups.set(b, c);
12601328
allCreatedChunkGroups.add(c);
12611329
}
@@ -1274,7 +1342,8 @@ class Compilation extends Tapable {
12741342
});
12751343

12761344
// 3. We enqueue the DependenciesBlock for traversal
1277-
queue.push({
1345+
queueDelayed.push({
1346+
action: ASYNC,
12781347
block: b,
12791348
module: module,
12801349
chunk: c.chunks[0],
@@ -1285,33 +1354,77 @@ class Compilation extends Tapable {
12851354
// Iterative traversal of the Module graph
12861355
// Recursive would be simpler to write but could result in Stack Overflows
12871356
while (queue.length) {
1288-
const queueItem = queue.pop();
1289-
module = queueItem.module;
1290-
block = queueItem.block;
1291-
chunk = queueItem.chunk;
1292-
chunkGroup = queueItem.chunkGroup;
1357+
while (queue.length) {
1358+
const queueItem = queue.pop();
1359+
module = queueItem.module;
1360+
block = queueItem.block;
1361+
chunk = queueItem.chunk;
1362+
chunkGroup = queueItem.chunkGroup;
1363+
1364+
switch (queueItem.action) {
1365+
case ENTER: {
1366+
queue.push({
1367+
action: LEAVE,
1368+
block,
1369+
module,
1370+
chunk,
1371+
chunkGroup
1372+
});
12931373

1294-
// get prepared block info
1295-
const blockInfo = blockInfoMap.get(block);
1296-
1297-
// Traverse all referenced modules
1298-
for (const refModule of blockInfo.modules) {
1299-
// We connect Module and Chunk when not already done
1300-
if (chunk.addModule(refModule)) {
1301-
refModule.addChunk(chunk);
1302-
1303-
// And enqueue the Module for traversal
1304-
queue.push({
1305-
block: refModule,
1306-
module: refModule,
1307-
chunk,
1308-
chunkGroup
1309-
});
1374+
if (chunkGroup !== undefined) {
1375+
const index = chunkGroup.getModuleIndex(module);
1376+
if (index === undefined) {
1377+
chunkGroup.setModuleIndex(
1378+
module,
1379+
chunkGroupCounters.get(chunkGroup).index++
1380+
);
1381+
}
1382+
}
1383+
}
1384+
// fallthrough
1385+
case ASYNC: {
1386+
// get prepared block info
1387+
const blockInfo = blockInfoMap.get(block);
1388+
1389+
// Traverse all referenced modules
1390+
for (let i = blockInfo.modules.length - 1; i >= 0; i--) {
1391+
const refModule = blockInfo.modules[i];
1392+
// We connect Module and Chunk when not already done
1393+
if (chunk.addModule(refModule)) {
1394+
refModule.addChunk(chunk);
1395+
1396+
// And enqueue the Module for traversal
1397+
queue.push({
1398+
action: ENTER,
1399+
block: refModule,
1400+
module: refModule,
1401+
chunk,
1402+
chunkGroup
1403+
});
1404+
}
1405+
}
1406+
1407+
// Traverse all Blocks
1408+
reverseIterationOfArrayCallback(blockInfo.blocks, iteratorBlock);
1409+
break;
1410+
}
1411+
case LEAVE: {
1412+
if (chunkGroup !== undefined) {
1413+
const index = chunkGroup.getModuleIndex2(module);
1414+
if (index === undefined) {
1415+
chunkGroup.setModuleIndex2(
1416+
module,
1417+
chunkGroupCounters.get(chunkGroup).index2++
1418+
);
1419+
}
1420+
}
1421+
break;
1422+
}
13101423
}
13111424
}
1312-
1313-
// Traverse all Blocks
1314-
iterationOfArrayCallback(blockInfo.blocks, iteratorBlock);
1425+
const tempQueue = queue;
1426+
queue = queueDelayed;
1427+
queueDelayed = tempQueue;
13151428
}
13161429

13171430
// PART TWO

lib/Dependency.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,13 @@ class Dependency {
1919
return null;
2020
}
2121

22-
// Returns the referenced module and export
23-
getReference() {
22+
// TODO webpack 5: rename to getReferences and always return an array
23+
/**
24+
* Returns the referenced modules and exports
25+
* @param {boolean=} allowMultiple opt-in into new behavior returning an array of references
26+
* @returns {DependencyReference|DependencyReference[]} reference(s)
27+
*/
28+
getReference(allowMultiple) {
2429
if (!this.module) return null;
2530
return new DependencyReference(this.module, true, this.weak);
2631
}

lib/FlagDependencyUsagePlugin.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,15 @@ class FlagDependencyUsagePlugin {
6666
};
6767

6868
const processDependency = dep => {
69-
const reference = dep.getReference && dep.getReference();
70-
if (!reference) return;
69+
const references = dep.getReference && dep.getReference(true);
70+
if (Array.isArray(references)) {
71+
for (const ref of references) processDependencyReference(ref);
72+
} else if (references) {
73+
processDependencyReference(references);
74+
}
75+
};
76+
77+
const processDependencyReference = reference => {
7178
const module = reference.module;
7279
const importedNames = reference.importedNames;
7380
const oldUsed = module.used;

lib/dependencies/HarmonyImportDependency.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ class HarmonyImportDependency extends ModuleDependency {
2121
return new DependencyReference(this.module, false, this.weak);
2222
}
2323

24+
getHarmonyInitOrder() {
25+
return this.sourceOrder;
26+
}
27+
2428
getImportVar() {
2529
let importVarMap = this.parserScope.importVarMap;
2630
if (!importVarMap) this.parserScope.importVarMap = importVarMap = new Map();
@@ -65,7 +69,7 @@ HarmonyImportDependency.Template = class HarmonyImportDependencyTemplate {
6569
}
6670

6771
getHarmonyInitOrder(dep) {
68-
return dep.sourceOrder;
72+
return dep.getHarmonyInitOrder();
6973
}
7074

7175
static isImportEmitted(dep, source) {

0 commit comments

Comments
 (0)