@@ -46,6 +46,7 @@ interface DebugOptions {
46
46
47
47
interface BundleDefinition {
48
48
name : string ;
49
+ description ?: string ;
49
50
dependencies : BundleDependency [ ] ;
50
51
}
51
52
@@ -74,6 +75,12 @@ enum Mode {
74
75
Local = 'local'
75
76
}
76
77
78
+ enum SpecialImport {
79
+ Default = 'default import' ,
80
+ Sizeeffect = 'side effect import' ,
81
+ Namespace = 'namespace import'
82
+ }
83
+
77
84
export async function run ( {
78
85
input,
79
86
bundler,
@@ -247,7 +254,9 @@ async function analyzeBundle(
247
254
) : Promise < BundleAnalysis > {
248
255
const analysis : BundleAnalysis = {
249
256
name : bundleDefinition . name ,
250
- results : [ ]
257
+ description : bundleDefinition . description ?? '' ,
258
+ results : [ ] ,
259
+ dependencies : bundleDefinition . dependencies
251
260
} ;
252
261
253
262
let moduleDirectory : string | undefined ;
@@ -392,15 +401,23 @@ async function analyzeBundleWithBundler(
392
401
393
402
function createEntryFileContent ( bundleDefinition : BundleDefinition ) : string {
394
403
const contentArray = [ ] ;
404
+ // cache used symbols. Used to avoid symbol collision when multiple modules export symbols with the same name.
405
+ const symbolsCache = new Set < string > ( ) ;
395
406
for ( const dep of bundleDefinition . dependencies ) {
396
407
for ( const imp of dep . imports ) {
397
408
if ( typeof imp === 'string' ) {
398
- contentArray . push ( `export {${ imp } } from '${ dep . packageName } ';` ) ;
409
+ contentArray . push (
410
+ ...createImportExport ( imp , dep . packageName , symbolsCache )
411
+ ) ;
399
412
} else {
400
- // Import object
413
+ // submodule imports
401
414
for ( const subImp of imp . imports ) {
402
415
contentArray . push (
403
- `export {${ subImp } } from '${ dep . packageName } /${ imp . path } ';`
416
+ ...createImportExport (
417
+ subImp ,
418
+ `${ dep . packageName } /${ imp . path } ` ,
419
+ symbolsCache
420
+ )
404
421
) ;
405
422
}
406
423
}
@@ -410,8 +427,64 @@ function createEntryFileContent(bundleDefinition: BundleDefinition): string {
410
427
return contentArray . join ( '\n' ) ;
411
428
}
412
429
430
+ function createImportExport (
431
+ symbol : string ,
432
+ modulePath : string ,
433
+ symbolsCache : Set < string >
434
+ ) : string [ ] {
435
+ const contentArray = [ ] ;
436
+
437
+ switch ( symbol ) {
438
+ case SpecialImport . Default : {
439
+ const nameToUse = createSymbolName ( 'default_import' , symbolsCache ) ;
440
+ contentArray . push ( `import ${ nameToUse } from '${ modulePath } ';` ) ;
441
+ contentArray . push ( `console.log(${ nameToUse } )` ) ; // prevent import from being tree shaken
442
+ break ;
443
+ }
444
+ case SpecialImport . Namespace : {
445
+ const nameToUse = createSymbolName ( 'namespace' , symbolsCache ) ;
446
+ contentArray . push ( `import * as ${ nameToUse } from '${ modulePath } ';` ) ;
447
+ contentArray . push ( `console.log(${ nameToUse } )` ) ; // prevent import from being tree shaken
448
+ break ;
449
+ }
450
+ case SpecialImport . Sizeeffect :
451
+ contentArray . push ( `import '${ modulePath } ';` ) ;
452
+ break ;
453
+ default :
454
+ // named imports
455
+ const nameToUse = createSymbolName ( symbol , symbolsCache ) ;
456
+
457
+ if ( nameToUse !== symbol ) {
458
+ contentArray . push (
459
+ `export {${ symbol } as ${ nameToUse } } from '${ modulePath } ';`
460
+ ) ;
461
+ } else {
462
+ contentArray . push ( `export {${ symbol } } from '${ modulePath } ';` ) ;
463
+ }
464
+ }
465
+
466
+ return contentArray ;
467
+ }
468
+
469
+ /**
470
+ * In case a symbol with the same name is already imported from another module, we need to give this symbol another name
471
+ * using "originalname as anothername" syntax, otherwise it returns the original symbol name.
472
+ */
473
+ function createSymbolName ( symbol : string , symbolsCache : Set < string > ) : string {
474
+ let nameToUse = symbol ;
475
+ const max = 100 ;
476
+ while ( symbolsCache . has ( nameToUse ) ) {
477
+ nameToUse = `${ symbol } _${ Math . floor ( Math . random ( ) * max ) } ` ;
478
+ }
479
+
480
+ symbolsCache . add ( nameToUse ) ;
481
+ return nameToUse ;
482
+ }
483
+
413
484
interface BundleAnalysis {
414
485
name : string ; // the bundle name defined in the bundle definition
486
+ description : string ;
487
+ dependencies : BundleDependency [ ] ;
415
488
results : BundleAnalysisResult [ ] ;
416
489
}
417
490
0 commit comments