swc_ecma_preset_env/corejs2/
entry.rs1use std::sync::Arc;
2
3use indexmap::IndexSet;
4use preset_env_base::{version::should_enable, Versions};
5use rustc_hash::FxBuildHasher;
6use swc_atoms::atom;
7use swc_common::DUMMY_SP;
8use swc_ecma_ast::*;
9use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith};
10
11use super::builtin::BUILTINS;
12
13#[derive(Debug)]
14pub struct Entry {
15 is_any_target: bool,
16 target: Arc<Versions>,
17 pub imports: IndexSet<&'static str, FxBuildHasher>,
18}
19
20impl Entry {
21 pub fn new(target: Arc<Versions>, regenerator: bool) -> Self {
22 let is_any_target = target.is_any_target();
23 let is_web_target = target.into_iter().any(|(k, v)| {
24 if k == "node" {
25 return false;
26 }
27
28 v.is_some()
29 });
30
31 let mut v = Entry {
32 is_any_target: target.is_any_target(),
33 target,
34 imports: Default::default(),
35 };
36 if is_any_target || is_web_target {
37 v.imports.insert("web.timers");
38 v.imports.insert("web.immediate");
39 v.imports.insert("web.dom.iterable");
40 }
41
42 if regenerator {
43 v.imports.insert("regenerator-runtime/runtime.js");
44 }
45
46 v
47 }
48
49 fn add_all(&mut self, src: &str) -> bool {
52 if src != "@babel/polyfill" && src != "@swc/polyfill" && src != "core-js" {
53 return false;
54 }
55
56 for (feature, version) in BUILTINS.iter() {
57 self.add_inner(feature, version);
58 }
59
60 true
61 }
62
63 fn add_inner(&mut self, feature: &'static str, version: &Versions) {
64 if self.is_any_target || should_enable(&self.target, version, true) {
65 self.imports.insert(feature);
66 }
67 }
68}
69
70impl VisitMut for Entry {
71 noop_visit_mut_type!(fail);
72
73 fn visit_mut_import_decl(&mut self, i: &mut ImportDecl) {
74 let remove = i.specifiers.is_empty() && self.add_all(&i.src.value.to_string_lossy());
75
76 if remove {
77 i.src.value = atom!("").into();
78 i.src.span = DUMMY_SP;
79 }
80 }
81
82 fn visit_mut_module_items(&mut self, items: &mut Vec<ModuleItem>) {
83 items.retain_mut(|item| {
84 item.visit_mut_children_with(self);
85 if let ModuleItem::Stmt(Stmt::Expr(ExprStmt { expr, .. })) = &item {
86 if let Expr::Call(CallExpr {
87 callee: Callee::Expr(callee),
88 ref args,
89 ..
90 }) = &**expr
91 {
92 if callee.is_ident_ref_to("require")
93 && args.len() == 1
94 && if let ExprOrSpread { spread: None, expr } = &args[0] {
95 if let Expr::Lit(Lit::Str(s)) = &**expr {
96 s.value == *"core-js"
97 || s.value == *"@swc/polyfill"
98 || s.value == *"@babel/polyfill"
99 } else {
100 false
101 }
102 } else {
103 false
104 }
105 && self.add_all("@swc/polyfill")
106 {
107 return false;
108 }
109 }
110 }
111 true
112 })
113 }
114}