@@ -74,6 +74,12 @@ enum Mode {
74
74
Local = 'local'
75
75
}
76
76
77
+ enum SpecialImport {
78
+ Default = 'default import' ,
79
+ Sizeeffect = 'side effect import' ,
80
+ Namespace = 'namespace import'
81
+ }
82
+
77
83
export async function run ( {
78
84
input,
79
85
bundler,
@@ -392,15 +398,23 @@ async function analyzeBundleWithBundler(
392
398
393
399
function createEntryFileContent ( bundleDefinition : BundleDefinition ) : string {
394
400
const contentArray = [ ] ;
401
+ // cache used symbols. Used to avoid symbol collision when multiple modules export symbols with the same name.
402
+ const symbolsCache = new Set < string > ( ) ;
395
403
for ( const dep of bundleDefinition . dependencies ) {
396
404
for ( const imp of dep . imports ) {
397
405
if ( typeof imp === 'string' ) {
398
- contentArray . push ( `export {${ imp } } from '${ dep . packageName } ';` ) ;
406
+ contentArray . push (
407
+ ...createImportExport ( imp , dep . packageName , symbolsCache )
408
+ ) ;
399
409
} else {
400
- // Import object
410
+ // submodule imports
401
411
for ( const subImp of imp . imports ) {
402
412
contentArray . push (
403
- `export {${ subImp } } from '${ dep . packageName } /${ imp . path } ';`
413
+ ...createImportExport (
414
+ subImp ,
415
+ `${ dep . packageName } /${ imp . path } ` ,
416
+ symbolsCache
417
+ )
404
418
) ;
405
419
}
406
420
}
@@ -410,6 +424,58 @@ function createEntryFileContent(bundleDefinition: BundleDefinition): string {
410
424
return contentArray . join ( '\n' ) ;
411
425
}
412
426
427
+ function createImportExport (
428
+ symbol : string ,
429
+ modulePath : string ,
430
+ symbolsCache : Set < string >
431
+ ) : string [ ] {
432
+ const contentArray = [ ] ;
433
+
434
+ switch ( symbol ) {
435
+ case SpecialImport . Default :
436
+ contentArray . push (
437
+ `import * as ${ createSymbolName ( 'default_import' , symbolsCache ) } `
438
+ ) ;
439
+ break ;
440
+ case SpecialImport . Namespace :
441
+ contentArray . push (
442
+ `import * as ${ createSymbolName ( 'namespace' , symbolsCache ) } `
443
+ ) ;
444
+ break ;
445
+ case SpecialImport . Sizeeffect :
446
+ contentArray . push ( `import '${ modulePath } ';` ) ;
447
+ break ;
448
+ default :
449
+ // named imports
450
+ const nameToUse = createSymbolName ( symbol , symbolsCache ) ;
451
+
452
+ if ( nameToUse !== symbol ) {
453
+ contentArray . push (
454
+ `export {${ symbol } as ${ nameToUse } } from '${ modulePath } ';`
455
+ ) ;
456
+ } else {
457
+ contentArray . push ( `export {${ symbol } } from '${ modulePath } ';` ) ;
458
+ }
459
+ }
460
+
461
+ return contentArray ;
462
+ }
463
+
464
+ /**
465
+ * In case a symbol with the same name is already imported from another module, we need to give this symbol another name
466
+ * using "originalname as anothername" syntax, otherwise it returns the original symbol name.
467
+ */
468
+ function createSymbolName ( symbol : string , symbolsCache : Set < string > ) : string {
469
+ let nameToUse = symbol ;
470
+ const max = 100 ;
471
+ while ( symbolsCache . has ( nameToUse ) ) {
472
+ nameToUse = `${ symbol } _${ Math . floor ( Math . random ( ) * max ) } ` ;
473
+ }
474
+
475
+ symbolsCache . add ( nameToUse ) ;
476
+ return nameToUse ;
477
+ }
478
+
413
479
interface BundleAnalysis {
414
480
name : string ; // the bundle name defined in the bundle definition
415
481
results : BundleAnalysisResult [ ] ;
0 commit comments