@@ -79,20 +79,22 @@ function flatten(arr) {
7979}
8080
8181/**
82- * @param {StatsCompilation } bundleStats bundle stats
82+ * @param {StatsCompilation[] } children child stats list
8383 * @param {string } assetName asset name
84- * @returns {boolean } child asset bundlers
84+ * @returns {StatsCompilation | undefined } child asset compilation
8585 */
86- function getChildAssetBundles ( bundleStats , assetName ) {
87- return flatten (
88- ( bundleStats . children || /** @type {StatsCompilation } */ ( [ ] ) ) . find (
89- /**
90- * @param {StatsCompilation } child child stats
91- * @returns {string[][] } assets by chunk name
92- */
93- ( child ) => Object . values ( child . assetsByChunkName || [ ] ) ,
94- ) ,
95- ) . includes ( assetName ) ;
86+ function getChildAssetBundles ( children , assetName ) {
87+ return children . find ( ( child ) => {
88+ if ( ! child ) return false ;
89+ if (
90+ Array . isArray ( child . assets ) &&
91+ child . assets . some ( ( asset ) => asset && asset . name === assetName )
92+ ) {
93+ return true ;
94+ }
95+ const chunkAssets = flatten ( Object . values ( child . assetsByChunkName || { } ) ) ;
96+ return chunkAssets . includes ( assetName ) ;
97+ } ) ;
9698}
9799
98100/**
@@ -195,7 +197,7 @@ function getAssetModulesByChunk(statsAsset, modulesByChunk) {
195197/** @typedef {Record<string, Record<string, boolean>> } ChunkToInitialByEntrypoint */
196198
197199/**
198- * @param {StatsCompilation } bundleStats bundle stats
200+ * @param {StatsCompilation | undefined } bundleStats bundle stats
199201 * @returns {ChunkToInitialByEntrypoint } chunk to initial by entrypoint
200202 */
201203function getChunkToInitialByEntrypoint ( bundleStats ) {
@@ -206,8 +208,10 @@ function getChunkToInitialByEntrypoint(bundleStats) {
206208 const chunkToEntrypointInititalMap = { } ;
207209 for ( const entrypoint of Object . values ( bundleStats . entrypoints || { } ) ) {
208210 for ( const asset of entrypoint . assets || [ ] ) {
209- chunkToEntrypointInititalMap [ asset . name ] ??= { } ;
210- chunkToEntrypointInititalMap [ asset . name ] [
211+ const assetName = typeof asset === "string" ? asset : asset ?. name ;
212+ if ( ! assetName ) continue ;
213+ chunkToEntrypointInititalMap [ assetName ] ??= { } ;
214+ chunkToEntrypointInititalMap [ assetName ] [
211215 /** @type {string } */
212216 ( entrypoint . name )
213217 ] = true ;
@@ -255,7 +259,7 @@ function isEntryModule(statsModule) {
255259 */
256260
257261/**
258- * @param {StatsCompilation } bundleStats bundle stats
262+ * @param {StatsCompilation | StatsCompilation[] } bundleStats bundle stats
259263 * @param {string | null } bundleDir bundle dir
260264 * @param {ViewerDataOptions= } opts options
261265 * @returns {ChartData } chart data
@@ -267,34 +271,54 @@ function getViewerData(bundleStats, bundleDir, opts) {
267271 excludeAssets = null ,
268272 } = opts || { } ;
269273
274+ if ( ! bundleStats ) return [ ] ;
275+
276+ if ( Array . isArray ( bundleStats ) ) {
277+ bundleStats = {
278+ children : bundleStats ,
279+ } ;
280+ }
281+
270282 const isAssetIncluded = createAssetsFilter ( excludeAssets ) ;
271283
284+ // Preserve all children from the root bundleStats (e.g. for MultiCompiler or child compilations)
285+ const allChildren = Array . isArray ( bundleStats . children )
286+ ? [ ...bundleStats . children ]
287+ : [ ] ;
288+ /** @type {WeakMap<StatsAsset, StatsCompilation> } */
289+ const childAssetBundles = new WeakMap ( ) ;
290+
272291 // Sometimes all the information is located in `children` array (e.g. problem in #10)
273292 if (
274293 ( bundleStats . assets === null ||
275294 bundleStats . assets === undefined ||
276295 bundleStats . assets . length === 0 ) &&
277- bundleStats . children &&
278- bundleStats . children . length > 0
296+ allChildren . length > 0
279297 ) {
280- const { children } = bundleStats ;
281- [ bundleStats ] = bundleStats . children ;
298+ bundleStats = { ...allChildren [ 0 ] } ;
299+ bundleStats . assets = Array . isArray ( bundleStats . assets )
300+ ? [ ...bundleStats . assets ]
301+ : [ ] ;
302+
282303 // Sometimes if there are additional child chunks produced add them as child assets,
283304 // leave the 1st one as that is considered the 'root' asset.
284- for ( let i = 1 ; i < children . length ; i ++ ) {
285- for ( const asset of children [ i ] . assets || [ ] ) {
305+ for ( let i = 1 ; i < allChildren . length ; i ++ ) {
306+ const child = allChildren [ i ] ;
307+ for ( const asset of child ?. assets || [ ] ) {
308+ childAssetBundles . set ( asset , child ) ;
286309 asset . isChild = true ;
287- /** @type {StatsAsset[] } */
288- ( bundleStats . assets ) . push ( asset ) ;
310+ bundleStats . assets . push ( asset ) ;
289311 }
290312 }
291- } else if ( bundleStats . children && bundleStats . children . length > 0 ) {
313+ } else if ( allChildren . length > 0 ) {
314+ bundleStats . assets = [ .../** @type {StatsAsset[] } */ ( bundleStats . assets ) ] ;
315+
292316 // Sometimes if there are additional child chunks produced add them as child assets
293- for ( const child of bundleStats . children ) {
294- for ( const asset of child . assets || [ ] ) {
317+ for ( const child of allChildren ) {
318+ for ( const asset of child ?. assets || [ ] ) {
319+ childAssetBundles . set ( asset , child ) ;
295320 asset . isChild = true ;
296- /** @type {StatsAsset[] } */
297- ( bundleStats . assets ) . push ( asset ) ;
321+ bundleStats . assets . push ( asset ) ;
298322 }
299323 }
300324 }
@@ -395,27 +419,35 @@ function getViewerData(bundleStats, bundleDir, opts) {
395419 }
396420 }
397421
398- /** @typedef {{ size: number, parsedSize?: number, gzipSize?: number, brotliSize?: number, zstdSize?: number, modules: StatsModule[], tree: Folder } } Asset */
422+ const rootChunkToInitialByEntrypoint =
423+ getChunkToInitialByEntrypoint ( bundleStats ) ;
424+
425+ /** @typedef {{ size: number, parsedSize?: number, gzipSize?: number, brotliSize?: number, zstdSize?: number, modules: StatsModule[], tree: Folder, isInitialByEntrypoint: Record<string, boolean> } } Asset */
399426
400427 const assets = bundleStats . assets . reduce ( ( result , statAsset ) => {
401428 /** @type {StatsModule[] } */
402429 let assetModules ;
430+ /** @type {Record<string, boolean> } */
431+ let isInitialByEntrypoint ;
403432
404433 if ( statAsset . isChild ) {
405434 // Preserve child-compilation matching because child assets use a different module list.
406- const assetBundles = getChildAssetBundles ( bundleStats , statAsset . name ) ;
435+ const assetBundles =
436+ childAssetBundles . get ( statAsset ) ||
437+ getChildAssetBundles ( allChildren , statAsset . name ) ;
407438 /** @type {StatsModule[] } */
408- const modules = assetBundles
409- ? // @ts -expect-error TODO looks like we have a bug with child compilation parsing, need to add test cases
410- getBundleModules ( assetBundles )
411- : [ ] ;
439+ const modules = assetBundles ? getBundleModules ( assetBundles ) : [ ] ;
412440 assetModules = modules . filter ( ( statModule ) =>
413441 assetHasModule ( statAsset , statModule ) ,
414442 ) ;
443+ isInitialByEntrypoint =
444+ getChunkToInitialByEntrypoint ( assetBundles ) [ statAsset . name ] ?? { } ;
415445 } else {
416446 assetModules = /** @type {StatsModule[] } */ (
417- rootAssetModules . get ( statAsset )
447+ rootAssetModules . get ( statAsset ) || [ ]
418448 ) ;
449+ isInitialByEntrypoint =
450+ rootChunkToInitialByEntrypoint [ statAsset . name ] ?? { } ;
419451 }
420452
421453 // A module that is a part of more than one asset is one stats object. Every asset that
@@ -426,6 +458,7 @@ function getViewerData(bundleStats, bundleDir, opts) {
426458
427459 const asset = ( result [ statAsset . name ] = /** @type {Asset } */ ( {
428460 size : statAsset . size ,
461+ isInitialByEntrypoint,
429462 } ) ) ;
430463 const assetSources =
431464 bundlesSources && Object . hasOwn ( bundlesSources , statAsset . name )
@@ -503,8 +536,6 @@ function getViewerData(bundleStats, bundleDir, opts) {
503536 return result ;
504537 } , /** @type {Record<string, Asset> } */ ( { } ) ) ;
505538
506- const chunkToInitialByEntrypoint = getChunkToInitialByEntrypoint ( bundleStats ) ;
507-
508539 return Object . entries ( assets ) . map ( ( [ filename , asset ] ) => ( {
509540 label : filename ,
510541 isAsset : true ,
@@ -518,7 +549,7 @@ function getViewerData(bundleStats, bundleDir, opts) {
518549 brotliSize : asset . brotliSize ,
519550 zstdSize : asset . zstdSize ,
520551 groups : Object . values ( asset . tree . children ) . map ( ( i ) => i . toChartData ( ) ) ,
521- isInitialByEntrypoint : chunkToInitialByEntrypoint [ filename ] ?? { } ,
552+ isInitialByEntrypoint : asset . isInitialByEntrypoint ,
522553 } ) ) ;
523554}
524555
0 commit comments