swc_ecma_compiler/es2020/
export_namespace_from.rs1use std::borrow::Cow;
2
3use swc_atoms::Atom;
4use swc_ecma_ast::*;
5use swc_ecma_utils::private_ident;
6
7use crate::CompilerImpl;
8
9impl<'a> CompilerImpl<'a> {
10 pub(crate) fn transform_export_namespace_from(&mut self, items: &mut Vec<ModuleItem>) {
11 let count = items
12 .iter()
13 .filter(|m| {
14 matches!(m, ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(NamedExport {
15 specifiers,
16 src: Some(..),
17 type_only: false,
18 ..
19 })) if specifiers.iter().any(|s| s.is_namespace()))
20 })
21 .count();
22
23 if count == 0 {
24 return;
25 }
26
27 let mut stmts = Vec::<ModuleItem>::with_capacity(items.len() + count);
28
29 for item in items.drain(..) {
30 match item {
31 ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(NamedExport {
32 span,
33 specifiers,
34 src: Some(src),
35 type_only: false,
36 with,
37 })) if specifiers.iter().any(|s| s.is_namespace()) => {
38 let mut origin_specifiers = Vec::new();
39
40 let mut import_specifiers = Vec::new();
41 let mut export_specifiers = Vec::new();
42
43 for s in specifiers.into_iter() {
44 match s {
45 ExportSpecifier::Namespace(ExportNamespaceSpecifier { span, name }) => {
46 let local_bridge =
47 private_ident!(format!("_{}", normalize_name(&name)));
48
49 import_specifiers.push(ImportSpecifier::Namespace(
50 ImportStarAsSpecifier {
51 span,
52 local: local_bridge.clone(),
53 },
54 ));
55 export_specifiers.push(ExportSpecifier::Named(
56 ExportNamedSpecifier {
57 span,
58 orig: local_bridge.into(),
59 exported: Some(name),
60 is_type_only: false,
61 },
62 ))
63 }
64 ExportSpecifier::Default(..) | ExportSpecifier::Named(..) => {
65 origin_specifiers.push(s);
66 }
67 #[cfg(swc_ast_unknown)]
68 _ => panic!("unable to access unknown nodes"),
69 }
70 }
71
72 stmts.push(
73 ImportDecl {
74 span,
75 specifiers: import_specifiers,
76 src: src.clone(),
77 type_only: false,
78 with: with.clone(),
79 phase: Default::default(),
80 }
81 .into(),
82 );
83
84 stmts.push(
85 NamedExport {
86 span,
87 specifiers: export_specifiers,
88 src: None,
89 type_only: false,
90 with: None,
91 }
92 .into(),
93 );
94
95 if !origin_specifiers.is_empty() {
96 stmts.push(
97 NamedExport {
98 span,
99 specifiers: origin_specifiers,
100 src: Some(src),
101 type_only: false,
102 with,
103 }
104 .into(),
105 );
106 }
107 }
108 _ => {
109 stmts.push(item);
110 }
111 }
112 }
113
114 *items = stmts;
115 }
116}
117
118fn normalize_name(module_export_name: &ModuleExportName) -> Cow<Atom> {
119 match module_export_name {
120 ModuleExportName::Ident(Ident { sym: name, .. }) => Cow::Borrowed(name),
121 ModuleExportName::Str(Str { value: name, .. }) => {
122 Cow::Owned(Atom::from(name.to_string_lossy()))
128 }
129 #[cfg(swc_ast_unknown)]
130 _ => panic!("unable to access unknown nodes"),
131 }
132}