@@ -36,6 +36,10 @@ const Queue = require("./util/Queue");
3636const SortableSet = require ( "./util/SortableSet" ) ;
3737const GraphHelpers = require ( "./GraphHelpers" ) ;
3838
39+ /** @typedef {import("./Module") } Module */
40+ /** @typedef {import("./DependenciesBlock") } DependenciesBlock */
41+ /** @typedef {import("./AsyncDependenciesBlock") } AsyncDependenciesBlock */
42+
3943const 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+
92102function 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
0 commit comments