swc_ecma_transforms_module/rewriter/
import_rewriter_swc.rs

1use std::sync::Arc;
2
3use anyhow::Context;
4use swc_common::FileName;
5use swc_ecma_ast::*;
6use swc_ecma_visit::{visit_mut_pass, VisitMut, VisitMutWith};
7
8use crate::{path::ImportResolver, wtf8::wtf8_to_cow_str};
9
10/// Import rewriter, which rewrites imports as es modules.
11pub fn swc_import_rewriter(base: FileName, resolver: Arc<dyn ImportResolver>) -> impl Pass {
12    visit_mut_pass(Rewriter { base, resolver })
13}
14
15struct Rewriter {
16    base: FileName,
17    resolver: Arc<dyn ImportResolver>,
18}
19
20impl VisitMut for Rewriter {
21    fn visit_mut_call_expr(&mut self, e: &mut CallExpr) {
22        e.visit_mut_children_with(self);
23
24        if !e.callee.is_import() {
25            return;
26        }
27
28        if let Some(ExprOrSpread { spread: None, expr }) = &mut e.args.get_mut(0) {
29            if let Expr::Lit(Lit::Str(s)) = &mut **expr {
30                let spec = wtf8_to_cow_str(&s.value);
31                let src = self
32                    .resolver
33                    .resolve_import(&self.base, &spec)
34                    .with_context(|| {
35                        format!("failed to resolve import `{}`", s.value.to_string_lossy())
36                    })
37                    .unwrap();
38
39                s.raw = None;
40                s.value = src.into();
41            }
42        }
43    }
44
45    fn visit_mut_import_decl(&mut self, i: &mut ImportDecl) {
46        let spec = wtf8_to_cow_str(&i.src.value);
47        let src = self
48            .resolver
49            .resolve_import(&self.base, &spec)
50            .with_context(|| {
51                format!(
52                    "failed to resolve import `{}`",
53                    i.src.value.to_string_lossy()
54                )
55            })
56            .unwrap();
57
58        i.src.raw = None;
59        i.src.value = src.into();
60    }
61
62    fn visit_mut_named_export(&mut self, e: &mut NamedExport) {
63        if let Some(src) = &mut e.src {
64            let spec = wtf8_to_cow_str(&src.value);
65            let new = self
66                .resolver
67                .resolve_import(&self.base, &spec)
68                .with_context(|| {
69                    format!("failed to resolve import `{}`", src.value.to_string_lossy())
70                })
71                .unwrap();
72
73            src.raw = None;
74            src.value = new.into();
75        }
76    }
77
78    fn visit_mut_export_all(&mut self, n: &mut ExportAll) {
79        let src = &mut n.src;
80
81        let spec = wtf8_to_cow_str(&src.value);
82        let new = self
83            .resolver
84            .resolve_import(&self.base, &spec)
85            .with_context(|| format!("failed to resolve import `{}`", src.value.to_string_lossy()))
86            .unwrap();
87
88        src.raw = None;
89        src.value = new.into();
90    }
91}