1
1
use std:: { borrow:: Cow , collections:: BTreeMap , ops:: ControlFlow } ;
2
2
3
3
use anyhow:: { Result , bail} ;
4
+ use indexmap:: map:: Entry ;
4
5
use rustc_hash:: FxHashSet ;
5
6
use serde:: { Deserialize , Serialize } ;
6
7
use smallvec:: { SmallVec , smallvec} ;
@@ -189,30 +190,44 @@ pub async fn follow_reexports(
189
190
// Try to find the export in the star exports
190
191
if !exports_ref. star_exports . is_empty ( ) && & * export_name != "default" {
191
192
let result = find_export_from_reexports ( * module, export_name. clone ( ) ) . await ?;
192
- if let Some ( m) = result. esm_export {
193
- module = m;
194
- continue ;
195
- }
196
- return match & result. dynamic_exporting_modules [ ..] {
197
- [ ] => Ok ( FollowExportsResult {
198
- module,
199
- export_name : Some ( export_name) ,
200
- ty : FoundExportType :: NotFound ,
193
+ match & * result {
194
+ FindExportFromReexportsResult :: NotFound => {
195
+ return Ok ( FollowExportsResult :: cell ( FollowExportsResult {
196
+ module,
197
+ export_name : Some ( export_name) ,
198
+ ty : FoundExportType :: NotFound ,
199
+ } ) ) ;
201
200
}
202
- . cell ( ) ) ,
203
- [ module] => Ok ( FollowExportsResult {
204
- module : * module,
205
- export_name : Some ( export_name) ,
206
- ty : FoundExportType :: Dynamic ,
201
+ FindExportFromReexportsResult :: EsmExport ( esm_export) => {
202
+ match handle_declared_export ( module, export_name, esm_export) . await ? {
203
+ ControlFlow :: Continue ( ( m, n) ) => {
204
+ module = m. to_resolved ( ) . await ?;
205
+ export_name = n;
206
+ continue ;
207
+ }
208
+ ControlFlow :: Break ( result) => {
209
+ return Ok ( result. cell ( ) ) ;
210
+ }
211
+ }
207
212
}
208
- . cell ( ) ) ,
209
- _ => Ok ( FollowExportsResult {
210
- module,
211
- export_name : Some ( export_name) ,
212
- ty : FoundExportType :: Dynamic ,
213
+ FindExportFromReexportsResult :: Dynamic ( dynamic_exporting_modules) => {
214
+ return match & dynamic_exporting_modules[ ..] {
215
+ [ ] => unreachable ! ( ) ,
216
+ [ module] => Ok ( FollowExportsResult {
217
+ module : * module,
218
+ export_name : Some ( export_name) ,
219
+ ty : FoundExportType :: Dynamic ,
220
+ }
221
+ . cell ( ) ) ,
222
+ _ => Ok ( FollowExportsResult {
223
+ module,
224
+ export_name : Some ( export_name) ,
225
+ ty : FoundExportType :: Dynamic ,
226
+ }
227
+ . cell ( ) ) ,
228
+ } ;
213
229
}
214
- . cell ( ) ) ,
215
- } ;
230
+ }
216
231
}
217
232
218
233
return Ok ( FollowExportsResult :: cell ( FollowExportsResult {
@@ -270,9 +285,10 @@ async fn handle_declared_export(
270
285
}
271
286
272
287
#[ turbo_tasks:: value]
273
- struct FindExportFromReexportsResult {
274
- esm_export : Option < ResolvedVc < Box < dyn EcmascriptChunkPlaceable > > > ,
275
- dynamic_exporting_modules : Vec < ResolvedVc < Box < dyn EcmascriptChunkPlaceable > > > ,
288
+ enum FindExportFromReexportsResult {
289
+ NotFound ,
290
+ EsmExport ( EsmExport ) ,
291
+ Dynamic ( Vec < ResolvedVc < Box < dyn EcmascriptChunkPlaceable > > > ) ,
276
292
}
277
293
278
294
#[ turbo_tasks:: function]
@@ -301,17 +317,25 @@ async fn find_export_from_reexports(
301
317
}
302
318
303
319
let all_export_names = get_all_export_names ( * module) . await ?;
304
- let esm_export = all_export_names. esm_exports . get ( & export_name) . copied ( ) ;
305
- Ok ( FindExportFromReexportsResult {
306
- esm_export,
307
- dynamic_exporting_modules : all_export_names. dynamic_exporting_modules . clone ( ) ,
308
- }
309
- . cell ( ) )
320
+ Ok (
321
+ if let Some ( esm_export) = all_export_names. esm_exports . get ( & export_name) {
322
+ FindExportFromReexportsResult :: EsmExport ( esm_export. clone ( ) )
323
+ } else if all_export_names. dynamic_exporting_modules . is_empty ( ) {
324
+ FindExportFromReexportsResult :: NotFound
325
+ } else {
326
+ FindExportFromReexportsResult :: Dynamic (
327
+ all_export_names. dynamic_exporting_modules . clone ( ) ,
328
+ )
329
+ }
330
+ . cell ( ) ,
331
+ )
310
332
}
311
333
312
334
#[ turbo_tasks:: value]
313
335
struct AllExportNamesResult {
314
- esm_exports : FxIndexMap < RcStr , ResolvedVc < Box < dyn EcmascriptChunkPlaceable > > > ,
336
+ /// A map from export name to the immediate referenced module.
337
+ esm_exports : FxIndexMap < RcStr , EsmExport > ,
338
+ /// A list of all direct or indirectly referenced modules that are dynamically exporting
315
339
dynamic_exporting_modules : Vec < ResolvedVc < Box < dyn EcmascriptChunkPlaceable > > > ,
316
340
}
317
341
@@ -331,7 +355,12 @@ async fn get_all_export_names(
331
355
let exports = exports. await ?;
332
356
let mut esm_exports = FxIndexMap :: default ( ) ;
333
357
let mut dynamic_exporting_modules = Vec :: new ( ) ;
334
- esm_exports. extend ( exports. exports . keys ( ) . cloned ( ) . map ( |n| ( n, module) ) ) ;
358
+ esm_exports. extend (
359
+ exports
360
+ . exports
361
+ . iter ( )
362
+ . map ( |( name, esm_export) | ( name. clone ( ) , esm_export. clone ( ) ) ) ,
363
+ ) ;
335
364
let star_export_names = exports
336
365
. star_exports
337
366
. iter ( )
@@ -340,7 +369,7 @@ async fn get_all_export_names(
340
369
if let ReferencedAsset :: Some ( m) =
341
370
* ReferencedAsset :: from_resolve_result ( esm_ref. resolve_reference ( ) ) . await ?
342
371
{
343
- Some ( expand_star_exports ( * m) )
372
+ Some ( expand_star_exports ( * * esm_ref , * m) )
344
373
} else {
345
374
None
346
375
} ,
@@ -354,7 +383,7 @@ async fn get_all_export_names(
354
383
star_export_names
355
384
. esm_exports
356
385
. iter ( )
357
- . map ( |( k, & v) | ( k. clone ( ) , v) ) ,
386
+ . map ( |( k, v) | ( k. clone ( ) , v. clone ( ) ) ) ,
358
387
) ;
359
388
dynamic_exporting_modules
360
389
. extend ( star_export_names. dynamic_exporting_modules . iter ( ) . copied ( ) ) ;
@@ -369,35 +398,45 @@ async fn get_all_export_names(
369
398
370
399
#[ turbo_tasks:: value]
371
400
pub struct ExpandStarResult {
372
- pub esm_exports : FxIndexMap < RcStr , ResolvedVc < Box < dyn EcmascriptChunkPlaceable > > > ,
401
+ pub esm_exports : FxIndexMap < RcStr , EsmExport > ,
373
402
pub dynamic_exporting_modules : Vec < ResolvedVc < Box < dyn EcmascriptChunkPlaceable > > > ,
374
403
}
375
404
376
405
#[ turbo_tasks:: function]
377
406
pub async fn expand_star_exports (
407
+ root_reference : ResolvedVc < Box < dyn ModuleReference > > ,
378
408
root_module : ResolvedVc < Box < dyn EcmascriptChunkPlaceable > > ,
379
409
) -> Result < Vc < ExpandStarResult > > {
380
410
let mut esm_exports = FxIndexMap :: default ( ) ;
381
411
let mut dynamic_exporting_modules = Vec :: new ( ) ;
382
412
let mut checked_modules = FxHashSet :: default ( ) ;
383
413
checked_modules. insert ( root_module) ;
384
- let mut queue = vec ! [ ( root_module, root_module. get_exports( ) ) ] ;
385
- while let Some ( ( asset, exports) ) = queue. pop ( ) {
414
+ let mut queue = vec ! [ ( root_reference , root_module, root_module. get_exports( ) ) ] ;
415
+ while let Some ( ( reference , asset, exports) ) = queue. pop ( ) {
386
416
match & * exports. await ? {
387
417
EcmascriptExports :: EsmExports ( exports) => {
388
418
let exports = exports. await ?;
389
- for key in exports. exports . keys ( ) {
419
+ for ( key, esm_export ) in exports. exports . iter ( ) {
390
420
if key == "default" {
391
421
continue ;
392
422
}
393
- esm_exports. entry ( key. clone ( ) ) . or_insert_with ( || asset) ;
423
+ if let Entry :: Vacant ( entry) = esm_exports. entry ( key. clone ( ) ) {
424
+ entry. insert ( match esm_export {
425
+ & EsmExport :: LocalBinding ( _, mutable) => EsmExport :: ImportedBinding (
426
+ ResolvedVc :: upcast ( reference) ,
427
+ key. clone ( ) ,
428
+ mutable,
429
+ ) ,
430
+ _ => esm_export. clone ( ) ,
431
+ } ) ;
432
+ }
394
433
}
395
434
for esm_ref in exports. star_exports . iter ( ) {
396
435
if let ReferencedAsset :: Some ( asset) =
397
436
& * ReferencedAsset :: from_resolve_result ( esm_ref. resolve_reference ( ) ) . await ?
398
437
&& checked_modules. insert ( * asset)
399
438
{
400
- queue. push ( ( * asset, asset. get_exports ( ) ) ) ;
439
+ queue. push ( ( * esm_ref , * asset, asset. get_exports ( ) ) ) ;
401
440
}
402
441
}
403
442
}
@@ -518,7 +557,7 @@ impl EsmExports {
518
557
continue ;
519
558
} ;
520
559
521
- let export_info = expand_star_exports ( * * asset) . await ?;
560
+ let export_info = expand_star_exports ( * esm_ref , * * asset) . await ?;
522
561
523
562
for export in export_info. esm_exports . keys ( ) {
524
563
if export == "default" {
0 commit comments