swc_ecma_preset_env/corejs3/
entry.rs1use std::{ops::Range, sync::Arc};
2
3use indexmap::IndexSet;
4use preset_env_base::{
5 version::{should_enable, Version},
6 Versions,
7};
8use rustc_hash::FxBuildHasher;
9use swc_atoms::atom;
10use swc_common::DUMMY_SP;
11use swc_ecma_ast::*;
12use swc_ecma_visit::VisitMut;
13
14use super::{compat::DATA as CORE_JS_COMPAT_DATA, data};
15use crate::util::{PooledStr, SwcFold};
16
17include!(concat!(env!("OUT_DIR"), "/corejs3_entries/lib.rs"));
18
19pub struct FeatureSet(Range<u32>);
20
21pub fn entries_get(name: &str) -> Option<FeatureSet> {
22 let index = ENTRY_INDEX.get(name)?;
23 ENTRY_VALUES_LIST.get(index).cloned().map(FeatureSet)
24}
25
26impl FeatureSet {
27 pub fn iter(&self) -> impl ExactSizeIterator<Item = &'static str> {
28 use precomputed_map::store::AccessSeq;
29
30 use crate::util::PooledStr;
31
32 self.0
33 .clone()
34 .map(|idx| EntryValuesStringId::index(idx as usize).unwrap())
35 .map(|id| PooledStr(id).as_str())
36 }
37}
38
39#[derive(Debug)]
40pub struct Entry {
41 is_any_target: bool,
42 target: Arc<Versions>,
43 corejs_version: Version,
44 pub imports: IndexSet<&'static str, FxBuildHasher>,
45 remove_regenerator: bool,
46}
47
48impl Entry {
49 pub fn new(target: Arc<Versions>, corejs_version: Version, remove_regenerator: bool) -> Self {
50 assert_eq!(corejs_version.major, 3);
51
52 Entry {
53 is_any_target: target.is_any_target(),
54 target,
55 corejs_version,
56 imports: Default::default(),
57 remove_regenerator,
58 }
59 }
60
61 fn add(&mut self, src: &str) -> bool {
64 let Entry {
65 is_any_target,
66 target,
67 corejs_version,
68 remove_regenerator,
69 ..
70 } = self;
71
72 if *remove_regenerator && src == "regenerator-runtime/runtime.js" {
73 return true;
74 }
75
76 if let Some(features) = entries_get(src) {
77 self.imports.extend(features.iter().filter(|f| {
78 let feature = CORE_JS_COMPAT_DATA.get(*f);
79
80 if !*is_any_target {
81 if let Some(feature) = feature {
82 if !should_enable(target, feature, true) {
83 return false;
84 }
85 }
86 }
87
88 if let Some(version) = data::modules_by_version(f) {
89 return version <= *corejs_version;
90 }
91
92 true
93 }));
94
95 true
96 } else {
97 false
98 }
99 }
100}
101
102impl VisitMut for Entry {
103 fn visit_mut_import_decl(&mut self, i: &mut ImportDecl) {
104 let remove = i.specifiers.is_empty() && self.add(&i.src.value.to_string_lossy());
105
106 if remove {
107 i.src.span = DUMMY_SP;
108 i.src.value = atom!("").into();
109 }
110 }
111}