@@ -7,21 +7,21 @@ use swc_ecma_ast::*;
7
7
use swc_ecma_utils:: quote_ident;
8
8
use swc_ecma_visit:: { noop_fold_type, Fold , FoldWith } ;
9
9
10
- pub fn aleph_resolve_fold ( resolver : Rc < RefCell < Resolver > > , source : Rc < SourceMap > ) -> impl Fold {
11
- AlephResolveFold {
10
+ pub fn resolve_fold ( resolver : Rc < RefCell < Resolver > > , source : Rc < SourceMap > ) -> impl Fold {
11
+ ResolveFold {
12
12
deno_hooks_idx : 0 ,
13
13
resolver,
14
14
source,
15
15
}
16
16
}
17
17
18
- pub struct AlephResolveFold {
18
+ pub struct ResolveFold {
19
19
deno_hooks_idx : i32 ,
20
20
resolver : Rc < RefCell < Resolver > > ,
21
21
source : Rc < SourceMap > ,
22
22
}
23
23
24
- impl AlephResolveFold {
24
+ impl ResolveFold {
25
25
fn new_use_deno_hook_ident ( & mut self , callback_span : & Span ) -> String {
26
26
let resolver = self . resolver . borrow_mut ( ) ;
27
27
self . deno_hooks_idx = self . deno_hooks_idx + 1 ;
@@ -42,7 +42,7 @@ impl AlephResolveFold {
42
42
}
43
43
}
44
44
45
- impl Fold for AlephResolveFold {
45
+ impl Fold for ResolveFold {
46
46
noop_fold_type ! ( ) ;
47
47
48
48
// resolve import/export url
@@ -367,6 +367,96 @@ impl Fold for AlephResolveFold {
367
367
}
368
368
}
369
369
370
+ pub struct ExportsParser {
371
+ pub names : Vec < String > ,
372
+ }
373
+
374
+ impl ExportsParser {
375
+ fn push_pat ( & mut self , pat : & Pat ) {
376
+ match pat {
377
+ Pat :: Ident ( id) => self . names . push ( id. sym . as_ref ( ) . into ( ) ) ,
378
+ Pat :: Array ( ArrayPat { elems, .. } ) => elems. into_iter ( ) . for_each ( |e| {
379
+ if let Some ( el) = e {
380
+ self . push_pat ( el)
381
+ }
382
+ } ) ,
383
+ Pat :: Assign ( AssignPat { left, .. } ) => self . push_pat ( left. as_ref ( ) ) ,
384
+ Pat :: Object ( ObjectPat { props, .. } ) => props. into_iter ( ) . for_each ( |prop| match prop {
385
+ ObjectPatProp :: Assign ( AssignPatProp { key, .. } ) => {
386
+ self . names . push ( key. sym . as_ref ( ) . into ( ) )
387
+ }
388
+ ObjectPatProp :: KeyValue ( KeyValuePatProp { value, .. } ) => self . push_pat ( value. as_ref ( ) ) ,
389
+ ObjectPatProp :: Rest ( RestPat { arg, .. } ) => self . push_pat ( arg. as_ref ( ) ) ,
390
+ } ) ,
391
+ Pat :: Rest ( RestPat { arg, .. } ) => self . push_pat ( arg. as_ref ( ) ) ,
392
+ _ => { }
393
+ }
394
+ }
395
+ }
396
+
397
+ impl Fold for ExportsParser {
398
+ noop_fold_type ! ( ) ;
399
+
400
+ fn fold_module_items ( & mut self , module_items : Vec < ModuleItem > ) -> Vec < ModuleItem > {
401
+ for item in & module_items {
402
+ match item {
403
+ ModuleItem :: ModuleDecl ( decl) => match decl {
404
+ // match: export const foo = 'bar'
405
+ // match: export function foo() {}
406
+ // match: export class foo {}
407
+ ModuleDecl :: ExportDecl ( ExportDecl { decl, .. } ) => match decl {
408
+ Decl :: Class ( ClassDecl { ident, .. } ) => self . names . push ( ident. sym . as_ref ( ) . into ( ) ) ,
409
+ Decl :: Fn ( FnDecl { ident, .. } ) => self . names . push ( ident. sym . as_ref ( ) . into ( ) ) ,
410
+ Decl :: Var ( VarDecl { decls, .. } ) => decls. into_iter ( ) . for_each ( |decl| {
411
+ self . push_pat ( & decl. name ) ;
412
+ } ) ,
413
+ _ => { }
414
+ } ,
415
+ // match: export default function
416
+ // match: export default class
417
+ ModuleDecl :: ExportDefaultDecl ( _) => self . names . push ( "default" . into ( ) ) ,
418
+ // match: export default foo
419
+ ModuleDecl :: ExportDefaultExpr ( _) => self . names . push ( "default" . into ( ) ) ,
420
+ // match: export { default as React, useState } from "https://esm.sh/react"
421
+ // match: export * as React from "https://esm.sh/react"
422
+ ModuleDecl :: ExportNamed ( NamedExport {
423
+ type_only,
424
+ specifiers,
425
+ ..
426
+ } ) => {
427
+ if !type_only {
428
+ specifiers
429
+ . into_iter ( )
430
+ . for_each ( |specifier| match specifier {
431
+ ExportSpecifier :: Named ( ExportNamedSpecifier { orig, exported, .. } ) => {
432
+ match exported {
433
+ Some ( name) => self . names . push ( name. sym . as_ref ( ) . into ( ) ) ,
434
+ None => self . names . push ( orig. sym . as_ref ( ) . into ( ) ) ,
435
+ }
436
+ }
437
+ ExportSpecifier :: Default ( ExportDefaultSpecifier { exported, .. } ) => {
438
+ self . names . push ( exported. sym . as_ref ( ) . into ( ) ) ;
439
+ }
440
+ ExportSpecifier :: Namespace ( ExportNamespaceSpecifier { name, .. } ) => {
441
+ self . names . push ( name. sym . as_ref ( ) . into ( ) )
442
+ }
443
+ } ) ;
444
+ }
445
+ }
446
+ // match: export * from "https://esm.sh/react"
447
+ ModuleDecl :: ExportAll ( ExportAll { src, .. } ) => {
448
+ self . names . push ( format ! ( "{{{}}}" , src. value) )
449
+ }
450
+ _ => { }
451
+ } ,
452
+ _ => { }
453
+ } ;
454
+ }
455
+
456
+ module_items
457
+ }
458
+ }
459
+
370
460
pub fn is_call_expr_by_name ( call : & CallExpr , name : & str ) -> bool {
371
461
let callee = match & call. callee {
372
462
ExprOrSuper :: Super ( _) => return false ,
@@ -454,7 +544,7 @@ mod tests {
454
544
use super :: * ;
455
545
use crate :: import_map:: ImportHashMap ;
456
546
use crate :: resolve:: Resolver ;
457
- use crate :: swc:: { st, EmitOptions , ParsedModule } ;
547
+ use crate :: swc:: { st, EmitOptions , SWC } ;
458
548
use sha1:: { Digest , Sha1 } ;
459
549
460
550
#[ test]
@@ -545,8 +635,7 @@ mod tests {
545
635
)
546
636
}
547
637
"# ;
548
- let module =
549
- ParsedModule :: parse ( "/pages/index.tsx" , source, None ) . expect ( "could not parse module" ) ;
638
+ let module = SWC :: parse ( "/pages/index.tsx" , source, None ) . expect ( "could not parse module" ) ;
550
639
let resolver = Rc :: new ( RefCell :: new ( Resolver :: new (
551
640
"/pages/index.tsx" ,
552
641
ImportHashMap :: default ( ) ,
@@ -581,4 +670,55 @@ mod tests {
581
670
assert ! ( code. contains( "export const ReactDom = __ALEPH.pack[\" https://esm.sh/react-dom\" ]" ) ) ;
582
671
assert ! ( code. contains( "export const { render } = __ALEPH.pack[\" https://esm.sh/react-dom\" ]" ) ) ;
583
672
}
673
+
674
+ #[ test]
675
+ fn parse_export_names ( ) {
676
+ let source = r#"
677
+ export const name = "alephjs"
678
+ export const version = "1.0.1"
679
+ const start = () => {}
680
+ export default start
681
+ export const { build } = { build: () => {} }
682
+ export function dev() {}
683
+ export class Server {}
684
+ export const { a: { a1, a2 }, 'b': [ b1, b2 ], c, ...rest } = { a: { a1: 0, a2: 0 }, b: [ 0, 0 ], c: 0, d: 0 }
685
+ export const [ d, e, ...{f, g, rest3} ] = [0, 0, {f:0,g:0,h:0}]
686
+ let i
687
+ export const j = i = [0, 0]
688
+ export { exists, existsSync } from "https://deno.land/std/fs/exists.ts"
689
+ export * as DenoStdServer from "https://deno.land/std/http/sever.ts"
690
+ export * from "https://deno.land/std/http/sever.ts"
691
+ "# ;
692
+ let module = SWC :: parse ( "/app.ts" , source, None ) . expect ( "could not parse module" ) ;
693
+ assert_eq ! (
694
+ module. parse_export_names( ) . unwrap( ) ,
695
+ vec![
696
+ "name" ,
697
+ "version" ,
698
+ "default" ,
699
+ "build" ,
700
+ "dev" ,
701
+ "Server" ,
702
+ "a1" ,
703
+ "a2" ,
704
+ "b1" ,
705
+ "b2" ,
706
+ "c" ,
707
+ "rest" ,
708
+ "d" ,
709
+ "e" ,
710
+ "f" ,
711
+ "g" ,
712
+ "rest3" ,
713
+ "j" ,
714
+ "exists" ,
715
+ "existsSync" ,
716
+ "DenoStdServer" ,
717
+ "{https://deno.land/std/http/sever.ts}" ,
718
+ ]
719
+ . into_iter( )
720
+ . map( |s| s. to_owned( ) )
721
+ . collect:: <Vec <String >>( )
722
+ )
723
+ }
584
724
}
0 commit comments