mirror of
https://github.com/swc-project/swc.git
synced 2024-12-25 22:56:11 +03:00
feat(es/optimization): Accept top level mark from simplifiers (#4434)
This commit is contained in:
parent
d6c82b3b3a
commit
8048597c9e
@ -20,12 +20,6 @@ default = ["es3"]
|
|||||||
# You can disable this feature to reduce binary size.
|
# You can disable this feature to reduce binary size.
|
||||||
es3 = []
|
es3 = []
|
||||||
|
|
||||||
concurrent = [
|
|
||||||
"swc_ecma_utils/concurrent",
|
|
||||||
"swc_ecma_transforms_base/concurrent",
|
|
||||||
"swc_ecma_transforms_compat/concurrent",
|
|
||||||
"swc_ecma_transforms_optimization/concurrent",
|
|
||||||
]
|
|
||||||
debug = ["swc_ecma_visit/debug"]
|
debug = ["swc_ecma_visit/debug"]
|
||||||
node = ["napi", "napi-derive"]
|
node = ["napi", "napi-derive"]
|
||||||
plugin = ["swc_plugin_runner", "swc_plugin_proxy/plugin-rt"]
|
plugin = ["swc_plugin_runner", "swc_plugin_proxy/plugin-rt"]
|
||||||
|
@ -414,7 +414,10 @@ impl Options {
|
|||||||
const_modules,
|
const_modules,
|
||||||
optimization,
|
optimization,
|
||||||
Optional::new(export_default_from(), syntax.export_default_from()),
|
Optional::new(export_default_from(), syntax.export_default_from()),
|
||||||
Optional::new(simplifier(Default::default()), enable_simplifier),
|
Optional::new(
|
||||||
|
simplifier(top_level_mark, Default::default()),
|
||||||
|
enable_simplifier
|
||||||
|
),
|
||||||
json_parse_pass
|
json_parse_pass
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ where
|
|||||||
as_folder(compressor),
|
as_folder(compressor),
|
||||||
Optional {
|
Optional {
|
||||||
enabled: options.evaluate || options.side_effects,
|
enabled: options.evaluate || options.side_effects,
|
||||||
visitor: expr_simplifier(ExprSimplifierConfig {})
|
visitor: expr_simplifier(marks.top_level_mark, ExprSimplifierConfig {})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -278,7 +278,7 @@ where
|
|||||||
|
|
||||||
let start_time = now();
|
let start_time = now();
|
||||||
|
|
||||||
let mut visitor = expr_simplifier(ExprSimplifierConfig {});
|
let mut visitor = expr_simplifier(self.marks.top_level_mark, ExprSimplifierConfig {});
|
||||||
n.apply(&mut visitor);
|
n.apply(&mut visitor);
|
||||||
|
|
||||||
self.changed |= visitor.changed();
|
self.changed |= visitor.changed();
|
||||||
@ -370,7 +370,7 @@ where
|
|||||||
|
|
||||||
let start_time = now();
|
let start_time = now();
|
||||||
|
|
||||||
let mut v = dead_branch_remover();
|
let mut v = dead_branch_remover(self.marks.top_level_mark);
|
||||||
n.apply(&mut v);
|
n.apply(&mut v);
|
||||||
|
|
||||||
if let Some(start_time) = start_time {
|
if let Some(start_time) = start_time {
|
||||||
|
@ -410,7 +410,9 @@ where
|
|||||||
// Sign does not matter for NaN
|
// Sign does not matter for NaN
|
||||||
*e = Expr::Ident(Ident::new(
|
*e = Expr::Ident(Ident::new(
|
||||||
js_word!("NaN"),
|
js_word!("NaN"),
|
||||||
bin.span.with_ctxt(SyntaxContext::empty()),
|
bin.span.with_ctxt(
|
||||||
|
SyntaxContext::empty().apply_mark(self.marks.top_level_mark),
|
||||||
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
(FpCategory::Normal, FpCategory::Zero) => {
|
(FpCategory::Normal, FpCategory::Zero) => {
|
||||||
|
@ -191,7 +191,10 @@ impl Evaluator {
|
|||||||
prop: prop.clone(),
|
prop: prop.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
e.visit_mut_with(&mut expr_simplifier(ExprSimplifierConfig {}));
|
e.visit_mut_with(&mut expr_simplifier(
|
||||||
|
self.marks.top_level_mark,
|
||||||
|
ExprSimplifierConfig {},
|
||||||
|
));
|
||||||
return Some(Box::new(e));
|
return Some(Box::new(e));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -48,8 +48,6 @@ use testing::assert_eq;
|
|||||||
"drop_unused/issue_1830_2/",
|
"drop_unused/issue_1830_2/",
|
||||||
"drop_unused/var_catch_toplevel/",
|
"drop_unused/var_catch_toplevel/",
|
||||||
"evaluate/issue_1760_1/",
|
"evaluate/issue_1760_1/",
|
||||||
"evaluate/prop_function/",
|
|
||||||
"functions/hoist_funs_strict/",
|
|
||||||
"functions/issue_2620_4/",
|
"functions/issue_2620_4/",
|
||||||
"functions/issue_3016_3/",
|
"functions/issue_3016_3/",
|
||||||
"functions/issue_3076/",
|
"functions/issue_3076/",
|
||||||
@ -82,6 +80,11 @@ fn terser_exec(input: PathBuf) {
|
|||||||
eprintln!("This test is not executable test");
|
eprintln!("This test is not executable test");
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
// Formmating
|
||||||
|
if input_stdout.contains("function") {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
let expected_src = read_to_string(&dir.join("output.terser.js")).map_err(|_| {
|
let expected_src = read_to_string(&dir.join("output.terser.js")).map_err(|_| {
|
||||||
eprintln!("This test does not have `output.terser.js`");
|
eprintln!("This test does not have `output.terser.js`");
|
||||||
})?;
|
})?;
|
||||||
|
@ -15,36 +15,29 @@ bench = false
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
debug = []
|
debug = []
|
||||||
# Process in parallel.
|
|
||||||
concurrent = [
|
|
||||||
"swc_common/concurrent",
|
|
||||||
"swc_ecma_utils/concurrent",
|
|
||||||
"swc_ecma_transforms_base/concurrent",
|
|
||||||
"rayon",
|
|
||||||
]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ahash = "0.7.4"
|
ahash = "0.7.4"
|
||||||
dashmap = "5.1.0"
|
dashmap = "5.1.0"
|
||||||
indexmap = "1.6.1"
|
indexmap = "1.6.1"
|
||||||
once_cell = "1.10.0"
|
once_cell = "1.10.0"
|
||||||
rayon = { version = "1.5.1", optional = true }
|
rayon = {version = "1.5.1", optional = true}
|
||||||
serde_json = "1.0.61"
|
serde_json = "1.0.61"
|
||||||
swc_atoms = { version = "0.2", path = "../swc_atoms" }
|
swc_atoms = {version = "0.2", path = "../swc_atoms"}
|
||||||
swc_common = { version = "0.17.23", path = "../swc_common" }
|
swc_common = {version = "0.17.23", path = "../swc_common"}
|
||||||
swc_ecma_ast = { version = "0.76.0", path = "../swc_ecma_ast" }
|
swc_ecma_ast = {version = "0.76.0", path = "../swc_ecma_ast"}
|
||||||
swc_ecma_parser = { version = "0.102.0", path = "../swc_ecma_parser" }
|
swc_ecma_parser = {version = "0.102.0", path = "../swc_ecma_parser"}
|
||||||
swc_ecma_transforms_base = { version = "0.79.0", path = "../swc_ecma_transforms_base" }
|
swc_ecma_transforms_base = {version = "0.79.0", path = "../swc_ecma_transforms_base"}
|
||||||
swc_ecma_transforms_macros = { version = "0.3.0", path = "../swc_ecma_transforms_macros" }
|
swc_ecma_transforms_macros = {version = "0.3.0", path = "../swc_ecma_transforms_macros"}
|
||||||
swc_ecma_utils = { version = "0.82.0", path = "../swc_ecma_utils" }
|
swc_ecma_utils = {version = "0.82.0", path = "../swc_ecma_utils"}
|
||||||
swc_ecma_visit = { version = "0.62.0", path = "../swc_ecma_visit" }
|
swc_ecma_visit = {version = "0.62.0", path = "../swc_ecma_visit"}
|
||||||
tracing = "0.1.32"
|
tracing = "0.1.32"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
swc_ecma_transforms_compat = { version = "0.93.0", path = "../swc_ecma_transforms_compat" }
|
swc_ecma_transforms_compat = {version = "0.93.0", path = "../swc_ecma_transforms_compat"}
|
||||||
swc_ecma_transforms_module = { version = "0.106.0", path = "../swc_ecma_transforms_module" }
|
swc_ecma_transforms_module = {version = "0.106.0", path = "../swc_ecma_transforms_module"}
|
||||||
swc_ecma_transforms_proposal = { version = "0.101.0", path = "../swc_ecma_transforms_proposal" }
|
swc_ecma_transforms_proposal = {version = "0.101.0", path = "../swc_ecma_transforms_proposal"}
|
||||||
swc_ecma_transforms_react = { version = "0.108.0", path = "../swc_ecma_transforms_react" }
|
swc_ecma_transforms_react = {version = "0.108.0", path = "../swc_ecma_transforms_react"}
|
||||||
swc_ecma_transforms_testing = { version = "0.81.0", path = "../swc_ecma_transforms_testing" }
|
swc_ecma_transforms_testing = {version = "0.81.0", path = "../swc_ecma_transforms_testing"}
|
||||||
swc_ecma_transforms_typescript = { version = "0.111.0", path = "../swc_ecma_transforms_typescript" }
|
swc_ecma_transforms_typescript = {version = "0.111.0", path = "../swc_ecma_transforms_typescript"}
|
||||||
testing = { version = "0.19.0", path = "../testing" }
|
testing = {version = "0.19.0", path = "../testing"}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#![deny(clippy::all)]
|
#![deny(clippy::all)]
|
||||||
|
#![deny(unused)]
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
const_modules::const_modules,
|
const_modules::const_modules,
|
||||||
@ -11,4 +12,3 @@ mod const_modules;
|
|||||||
mod inline_globals;
|
mod inline_globals;
|
||||||
mod json_parse;
|
mod json_parse;
|
||||||
pub mod simplify;
|
pub mod simplify;
|
||||||
mod util;
|
|
||||||
|
@ -4,7 +4,7 @@ use swc_atoms::js_word;
|
|||||||
use swc_common::{
|
use swc_common::{
|
||||||
pass::{CompilerPass, Repeated},
|
pass::{CompilerPass, Repeated},
|
||||||
util::{move_map::MoveMap, take::Take},
|
util::{move_map::MoveMap, take::Take},
|
||||||
Spanned, DUMMY_SP,
|
Mark, Spanned, DUMMY_SP,
|
||||||
};
|
};
|
||||||
use swc_ecma_ast::*;
|
use swc_ecma_ast::*;
|
||||||
use swc_ecma_transforms_base::pass::RepeatedJsPass;
|
use swc_ecma_transforms_base::pass::RepeatedJsPass;
|
||||||
@ -23,7 +23,7 @@ mod tests;
|
|||||||
/// Not intended for general use. Use [simplifier] instead.
|
/// Not intended for general use. Use [simplifier] instead.
|
||||||
///
|
///
|
||||||
/// Ported from `PeepholeRemoveDeadCode` of google closure compiler.
|
/// Ported from `PeepholeRemoveDeadCode` of google closure compiler.
|
||||||
pub fn dead_branch_remover() -> impl RepeatedJsPass + VisitMut + 'static {
|
pub fn dead_branch_remover(_top_level_mark: Mark) -> impl RepeatedJsPass + VisitMut + 'static {
|
||||||
as_folder(Remover::default())
|
as_folder(Remover::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use swc_common::chain;
|
use swc_common::{chain, Mark};
|
||||||
|
use swc_ecma_transforms_base::resolver::resolver_with_mark;
|
||||||
|
|
||||||
use super::{super::expr_simplifier, dead_branch_remover};
|
use super::{super::expr_simplifier, dead_branch_remover};
|
||||||
|
|
||||||
@ -6,7 +7,15 @@ macro_rules! test_stmt {
|
|||||||
($l:expr, $r:expr) => {
|
($l:expr, $r:expr) => {
|
||||||
swc_ecma_transforms_testing::test_transform(
|
swc_ecma_transforms_testing::test_transform(
|
||||||
::swc_ecma_parser::Syntax::default(),
|
::swc_ecma_parser::Syntax::default(),
|
||||||
|_| chain!(expr_simplifier(Default::default()), dead_branch_remover()),
|
|_| {
|
||||||
|
let top_level_mark = Mark::fresh(Mark::root());
|
||||||
|
|
||||||
|
chain!(
|
||||||
|
resolver_with_mark(top_level_mark),
|
||||||
|
expr_simplifier(top_level_mark, Default::default()),
|
||||||
|
dead_branch_remover(top_level_mark)
|
||||||
|
)
|
||||||
|
},
|
||||||
$l,
|
$l,
|
||||||
$r,
|
$r,
|
||||||
true,
|
true,
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
#[cfg(feature = "concurrent")]
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
#[cfg(feature = "concurrent")]
|
|
||||||
use rayon::prelude::*;
|
|
||||||
use swc_common::{
|
use swc_common::{
|
||||||
collections::{AHashMap, AHashSet},
|
collections::{AHashMap, AHashSet},
|
||||||
pass::{CompilerPass, Repeated},
|
pass::{CompilerPass, Repeated},
|
||||||
@ -19,8 +15,6 @@ use swc_ecma_visit::{
|
|||||||
};
|
};
|
||||||
use tracing::{debug, span, trace, Level};
|
use tracing::{debug, span, trace, Level};
|
||||||
|
|
||||||
use crate::util::Readonly;
|
|
||||||
|
|
||||||
/// Note: This becomes parallel if `concurrent` feature is enabled.
|
/// Note: This becomes parallel if `concurrent` feature is enabled.
|
||||||
pub fn dce(config: Config) -> impl Fold + VisitMut + Repeated + CompilerPass {
|
pub fn dce(config: Config) -> impl Fold + VisitMut + Repeated + CompilerPass {
|
||||||
as_folder(TreeShaker {
|
as_folder(TreeShaker {
|
||||||
@ -28,7 +22,6 @@ pub fn dce(config: Config) -> impl Fold + VisitMut + Repeated + CompilerPass {
|
|||||||
changed: false,
|
changed: false,
|
||||||
pass: 0,
|
pass: 0,
|
||||||
data: Default::default(),
|
data: Default::default(),
|
||||||
par_depth: 0,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,11 +39,7 @@ struct TreeShaker {
|
|||||||
config: Config,
|
config: Config,
|
||||||
changed: bool,
|
changed: bool,
|
||||||
pass: u16,
|
pass: u16,
|
||||||
data: Readonly<Data>,
|
data: Data,
|
||||||
|
|
||||||
#[cfg_attr(not(feature = "concurrent"), allow(dead_code))]
|
|
||||||
/// Used to avoid cost of being overly parallel.
|
|
||||||
par_depth: u16,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompilerPass for TreeShaker {
|
impl CompilerPass for TreeShaker {
|
||||||
@ -220,41 +209,12 @@ impl Repeated for TreeShaker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TreeShaker {
|
impl TreeShaker {
|
||||||
fn visit_maybe_par_stmt_likes<T>(&mut self, stmts: &mut Vec<T>)
|
|
||||||
where
|
|
||||||
T: StmtLike + ModuleItemLike + VisitMutWith<Self> + Send + Sync,
|
|
||||||
Vec<T>: VisitMutWith<Self>,
|
|
||||||
{
|
|
||||||
#[cfg(feature = "concurrent")]
|
|
||||||
if self.par_depth < 2 {
|
|
||||||
let changed = stmts
|
|
||||||
.par_iter_mut()
|
|
||||||
.map(|s| {
|
|
||||||
let mut v = TreeShaker {
|
|
||||||
config: self.config,
|
|
||||||
changed: false,
|
|
||||||
pass: self.pass,
|
|
||||||
data: Arc::clone(&self.data),
|
|
||||||
par_depth: self.par_depth + 1,
|
|
||||||
};
|
|
||||||
s.visit_mut_with(&mut v);
|
|
||||||
|
|
||||||
v.changed
|
|
||||||
})
|
|
||||||
.reduce(|| false, |a, b| a || b);
|
|
||||||
self.changed |= changed;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
stmts.visit_mut_children_with(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_mut_stmt_likes<T>(&mut self, stmts: &mut Vec<T>)
|
fn visit_mut_stmt_likes<T>(&mut self, stmts: &mut Vec<T>)
|
||||||
where
|
where
|
||||||
T: StmtLike + ModuleItemLike + VisitMutWith<Self> + Send + Sync,
|
T: StmtLike + ModuleItemLike + VisitMutWith<Self> + Send + Sync,
|
||||||
Vec<T>: VisitMutWith<Self>,
|
Vec<T>: VisitMutWith<Self>,
|
||||||
{
|
{
|
||||||
self.visit_maybe_par_stmt_likes(stmts);
|
stmts.visit_mut_children_with(self);
|
||||||
|
|
||||||
stmts.retain(|s| match s.as_stmt() {
|
stmts.retain(|s| match s.as_stmt() {
|
||||||
Some(Stmt::Empty(..)) => false,
|
Some(Stmt::Empty(..)) => false,
|
||||||
@ -423,7 +383,7 @@ impl VisitMut for TreeShaker {
|
|||||||
};
|
};
|
||||||
m.visit_with(&mut analyzer);
|
m.visit_with(&mut analyzer);
|
||||||
}
|
}
|
||||||
self.data = data.into();
|
self.data = data;
|
||||||
trace!("Used = {:?}", self.data.used_names);
|
trace!("Used = {:?}", self.data.used_names);
|
||||||
|
|
||||||
m.visit_mut_children_with(self);
|
m.visit_mut_children_with(self);
|
||||||
|
@ -4,7 +4,7 @@ use swc_atoms::{js_word, JsWord};
|
|||||||
use swc_common::{
|
use swc_common::{
|
||||||
pass::{CompilerPass, Repeated},
|
pass::{CompilerPass, Repeated},
|
||||||
util::take::Take,
|
util::take::Take,
|
||||||
Span, Spanned, DUMMY_SP,
|
Mark, Span, Spanned, SyntaxContext, DUMMY_SP,
|
||||||
};
|
};
|
||||||
use swc_ecma_ast::{Ident, Lit, *};
|
use swc_ecma_ast::{Ident, Lit, *};
|
||||||
use swc_ecma_transforms_base::{ext::ExprRefExt, pass::RepeatedJsPass};
|
use swc_ecma_transforms_base::{ext::ExprRefExt, pass::RepeatedJsPass};
|
||||||
@ -35,7 +35,10 @@ pub struct Config {}
|
|||||||
/// Not intended for general use. Use [simplifier] instead.
|
/// Not intended for general use. Use [simplifier] instead.
|
||||||
///
|
///
|
||||||
/// Ported from `PeepholeFoldConstants` of google closure compiler.
|
/// Ported from `PeepholeFoldConstants` of google closure compiler.
|
||||||
pub fn expr_simplifier(config: Config) -> impl RepeatedJsPass + VisitMut + 'static {
|
pub fn expr_simplifier(
|
||||||
|
top_level_mark: Mark,
|
||||||
|
config: Config,
|
||||||
|
) -> impl RepeatedJsPass + VisitMut + 'static {
|
||||||
as_folder(SimplifyExpr {
|
as_folder(SimplifyExpr {
|
||||||
config,
|
config,
|
||||||
changed: false,
|
changed: false,
|
||||||
@ -43,12 +46,15 @@ pub fn expr_simplifier(config: Config) -> impl RepeatedJsPass + VisitMut + 'stat
|
|||||||
is_arg_of_update: false,
|
is_arg_of_update: false,
|
||||||
is_modifying: false,
|
is_modifying: false,
|
||||||
in_callee: false,
|
in_callee: false,
|
||||||
|
top_level_ctxt: SyntaxContext::empty().apply_mark(top_level_mark),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct SimplifyExpr {
|
struct SimplifyExpr {
|
||||||
|
top_level_ctxt: SyntaxContext,
|
||||||
config: Config,
|
config: Config,
|
||||||
|
|
||||||
changed: bool,
|
changed: bool,
|
||||||
/// Uninitialized variables.
|
/// Uninitialized variables.
|
||||||
vars: Vec<VarDeclarator>,
|
vars: Vec<VarDeclarator>,
|
||||||
@ -1278,6 +1284,7 @@ impl VisitMut for SimplifyExpr {
|
|||||||
|
|
||||||
fn visit_mut_module_items(&mut self, n: &mut Vec<ModuleItem>) {
|
fn visit_mut_module_items(&mut self, n: &mut Vec<ModuleItem>) {
|
||||||
let mut child = SimplifyExpr {
|
let mut child = SimplifyExpr {
|
||||||
|
top_level_ctxt: self.top_level_ctxt,
|
||||||
config: self.config,
|
config: self.config,
|
||||||
changed: Default::default(),
|
changed: Default::default(),
|
||||||
vars: Default::default(),
|
vars: Default::default(),
|
||||||
@ -1415,6 +1422,7 @@ impl VisitMut for SimplifyExpr {
|
|||||||
|
|
||||||
fn visit_mut_stmts(&mut self, n: &mut Vec<Stmt>) {
|
fn visit_mut_stmts(&mut self, n: &mut Vec<Stmt>) {
|
||||||
let mut child = SimplifyExpr {
|
let mut child = SimplifyExpr {
|
||||||
|
top_level_ctxt: self.top_level_ctxt,
|
||||||
config: self.config,
|
config: self.config,
|
||||||
changed: Default::default(),
|
changed: Default::default(),
|
||||||
vars: Default::default(),
|
vars: Default::default(),
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use swc_common::{chain, Mark};
|
||||||
|
use swc_ecma_transforms_base::resolver::resolver_with_mark;
|
||||||
use swc_ecma_transforms_testing::test_transform;
|
use swc_ecma_transforms_testing::test_transform;
|
||||||
|
|
||||||
use super::expr_simplifier;
|
use super::expr_simplifier;
|
||||||
@ -5,7 +7,14 @@ use super::expr_simplifier;
|
|||||||
fn fold(src: &str, expected: &str) {
|
fn fold(src: &str, expected: &str) {
|
||||||
test_transform(
|
test_transform(
|
||||||
::swc_ecma_parser::Syntax::default(),
|
::swc_ecma_parser::Syntax::default(),
|
||||||
|_| expr_simplifier(Default::default()),
|
|_| {
|
||||||
|
let top_level_mark = Mark::fresh(Mark::root());
|
||||||
|
|
||||||
|
chain!(
|
||||||
|
resolver_with_mark(top_level_mark),
|
||||||
|
expr_simplifier(top_level_mark, Default::default())
|
||||||
|
)
|
||||||
|
},
|
||||||
src,
|
src,
|
||||||
expected,
|
expected,
|
||||||
true,
|
true,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
//! Ported from closure compiler.
|
//! Ported from closure compiler.
|
||||||
use swc_common::{chain, pass::Repeat};
|
use swc_common::{chain, pass::Repeat, Mark};
|
||||||
use swc_ecma_transforms_base::pass::RepeatedJsPass;
|
use swc_ecma_transforms_base::pass::RepeatedJsPass;
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
@ -22,11 +22,11 @@ pub struct Config {
|
|||||||
|
|
||||||
/// Performs simplify-expr, inlining, remove-dead-branch and dce until nothing
|
/// Performs simplify-expr, inlining, remove-dead-branch and dce until nothing
|
||||||
/// changes.
|
/// changes.
|
||||||
pub fn simplifier(c: Config) -> impl RepeatedJsPass {
|
pub fn simplifier(top_level_mark: Mark, c: Config) -> impl RepeatedJsPass {
|
||||||
Repeat::new(chain!(
|
Repeat::new(chain!(
|
||||||
expr_simplifier(c.expr),
|
expr_simplifier(top_level_mark, c.expr),
|
||||||
inlining::inlining(c.inlining),
|
inlining::inlining(c.inlining),
|
||||||
dead_branch_remover(),
|
dead_branch_remover(top_level_mark),
|
||||||
dce::dce(c.dce)
|
dce::dce(c.dce)
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
use std::ops::Deref;
|
|
||||||
|
|
||||||
#[cfg(feature = "concurrent")]
|
|
||||||
pub(crate) type Readonly<T> = std::sync::Arc<T>;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "concurrent"))]
|
|
||||||
#[derive(Default)]
|
|
||||||
pub(crate) struct Readonly<T>(T);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "concurrent"))]
|
|
||||||
impl<T> Deref for Readonly<T> {
|
|
||||||
type Target = T;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "concurrent"))]
|
|
||||||
impl<T> From<T> for Readonly<T> {
|
|
||||||
fn from(v: T) -> Self {
|
|
||||||
Self(v)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use swc_common::{chain, pass::Repeat};
|
use swc_common::{chain, pass::Repeat, Mark};
|
||||||
use swc_ecma_parser::{EsConfig, Syntax};
|
use swc_ecma_parser::{EsConfig, Syntax};
|
||||||
use swc_ecma_transforms_base::fixer::paren_remover;
|
use swc_ecma_transforms_base::fixer::paren_remover;
|
||||||
use swc_ecma_transforms_optimization::simplify::{dce::dce, expr_simplifier};
|
use swc_ecma_transforms_optimization::simplify::{dce::dce, expr_simplifier};
|
||||||
@ -67,7 +67,14 @@ fn expr(input: PathBuf) {
|
|||||||
Syntax::Es(EsConfig {
|
Syntax::Es(EsConfig {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
&|t| chain!(remover(t), Repeat::new(expr_simplifier(Default::default()))),
|
&|t| {
|
||||||
|
let top_level_mark = Mark::fresh(Mark::root());
|
||||||
|
|
||||||
|
chain!(
|
||||||
|
remover(t),
|
||||||
|
Repeat::new(expr_simplifier(top_level_mark, Default::default()))
|
||||||
|
)
|
||||||
|
},
|
||||||
&input,
|
&input,
|
||||||
&output,
|
&output,
|
||||||
);
|
);
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
//! Copied from PeepholeIntegrationTest from the google closure compiler.
|
//! Copied from PeepholeIntegrationTest from the google closure compiler.
|
||||||
|
|
||||||
|
#![deny(warnings)]
|
||||||
|
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
use swc_common::{chain, pass::Repeat, Mark};
|
use swc_common::{chain, pass::Repeat, Mark};
|
||||||
use swc_ecma_parser::{EsConfig, Syntax, TsConfig};
|
use swc_ecma_parser::{EsConfig, Syntax, TsConfig};
|
||||||
use swc_ecma_transforms_base::{
|
use swc_ecma_transforms_base::{helpers::inject_helpers, resolver::resolver_with_mark};
|
||||||
helpers::inject_helpers,
|
|
||||||
resolver::{resolver, resolver_with_mark},
|
|
||||||
};
|
|
||||||
use swc_ecma_transforms_compat::{es2015, es2016, es2017, es2018, es2022::class_properties, es3};
|
use swc_ecma_transforms_compat::{es2015, es2016, es2017, es2018, es2022::class_properties, es3};
|
||||||
use swc_ecma_transforms_module::{
|
use swc_ecma_transforms_module::{
|
||||||
common_js::common_js, import_analysis::import_analyzer, util::Scope,
|
common_js::common_js, import_analysis::import_analyzer, util::Scope,
|
||||||
@ -22,7 +21,14 @@ use swc_ecma_transforms_typescript::strip;
|
|||||||
fn test(src: &str, expected: &str) {
|
fn test(src: &str, expected: &str) {
|
||||||
test_transform(
|
test_transform(
|
||||||
::swc_ecma_parser::Syntax::default(),
|
::swc_ecma_parser::Syntax::default(),
|
||||||
|_| chain!(resolver(), simplifier(Default::default())),
|
|_| {
|
||||||
|
let top_level_mark = Mark::fresh(Mark::root());
|
||||||
|
|
||||||
|
chain!(
|
||||||
|
resolver_with_mark(top_level_mark),
|
||||||
|
simplifier(top_level_mark, Default::default())
|
||||||
|
)
|
||||||
|
},
|
||||||
src,
|
src,
|
||||||
expected,
|
expected,
|
||||||
true,
|
true,
|
||||||
@ -37,7 +43,14 @@ macro_rules! to {
|
|||||||
($name:ident, $src:expr, $expected:expr) => {
|
($name:ident, $src:expr, $expected:expr) => {
|
||||||
test!(
|
test!(
|
||||||
Default::default(),
|
Default::default(),
|
||||||
|_| chain!(resolver(), simplifier(Default::default())),
|
|_| {
|
||||||
|
let top_level_mark = Mark::fresh(Mark::root());
|
||||||
|
|
||||||
|
chain!(
|
||||||
|
resolver_with_mark(top_level_mark),
|
||||||
|
simplifier(top_level_mark, Default::default())
|
||||||
|
)
|
||||||
|
},
|
||||||
$name,
|
$name,
|
||||||
$src,
|
$src,
|
||||||
$expected
|
$expected
|
||||||
@ -549,14 +562,14 @@ test!(
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
|t| {
|
|t| {
|
||||||
let mark = Mark::fresh(Mark::root());
|
let top_level_mark = Mark::fresh(Mark::root());
|
||||||
let scope = Rc::new(RefCell::new(Scope::default()));
|
let scope = Rc::new(RefCell::new(Scope::default()));
|
||||||
chain!(
|
chain!(
|
||||||
decorators(Default::default()),
|
decorators(Default::default()),
|
||||||
resolver_with_mark(mark),
|
resolver_with_mark(top_level_mark),
|
||||||
strip(mark),
|
strip(top_level_mark),
|
||||||
class_properties(Some(t.comments.clone()), Default::default()),
|
class_properties(Some(t.comments.clone()), Default::default()),
|
||||||
simplifier(Default::default()),
|
simplifier(top_level_mark, Default::default()),
|
||||||
es2018(Default::default()),
|
es2018(Default::default()),
|
||||||
es2017(Default::default()),
|
es2017(Default::default()),
|
||||||
es2016(),
|
es2016(),
|
||||||
@ -590,7 +603,11 @@ _foo.default.bar = true;
|
|||||||
|
|
||||||
test!(
|
test!(
|
||||||
Syntax::default(),
|
Syntax::default(),
|
||||||
|_| expr_simplifier(Default::default()),
|
|_| {
|
||||||
|
let top_level_mark = Mark::fresh(Mark::root());
|
||||||
|
|
||||||
|
expr_simplifier(top_level_mark, Default::default())
|
||||||
|
},
|
||||||
issue_1619_1,
|
issue_1619_1,
|
||||||
r#"
|
r#"
|
||||||
"use strict";
|
"use strict";
|
||||||
@ -607,7 +624,11 @@ test!(
|
|||||||
|
|
||||||
test!(
|
test!(
|
||||||
Syntax::default(),
|
Syntax::default(),
|
||||||
|_| dead_branch_remover(),
|
|_| {
|
||||||
|
let top_level_mark = Mark::fresh(Mark::root());
|
||||||
|
|
||||||
|
dead_branch_remover(top_level_mark)
|
||||||
|
},
|
||||||
issue_2466_1,
|
issue_2466_1,
|
||||||
"
|
"
|
||||||
const X = {
|
const X = {
|
||||||
@ -633,7 +654,11 @@ test!(
|
|||||||
|
|
||||||
test!(
|
test!(
|
||||||
Syntax::default(),
|
Syntax::default(),
|
||||||
|_| dead_branch_remover(),
|
|_| {
|
||||||
|
let top_level_mark = Mark::fresh(Mark::root());
|
||||||
|
|
||||||
|
dead_branch_remover(top_level_mark)
|
||||||
|
},
|
||||||
issue_4272,
|
issue_4272,
|
||||||
"
|
"
|
||||||
function oe() {
|
function oe() {
|
||||||
@ -651,10 +676,17 @@ test!(
|
|||||||
|
|
||||||
test!(
|
test!(
|
||||||
Syntax::default(),
|
Syntax::default(),
|
||||||
|_| chain!(
|
|_| {
|
||||||
resolver(),
|
let top_level_mark = Mark::fresh(Mark::root());
|
||||||
Repeat::new(chain!(inlining(Default::default()), dead_branch_remover()))
|
|
||||||
),
|
chain!(
|
||||||
|
resolver_with_mark(top_level_mark),
|
||||||
|
Repeat::new(chain!(
|
||||||
|
inlining(Default::default()),
|
||||||
|
dead_branch_remover(top_level_mark)
|
||||||
|
))
|
||||||
|
)
|
||||||
|
},
|
||||||
issue_4173,
|
issue_4173,
|
||||||
"
|
"
|
||||||
function emit(type) {
|
function emit(type) {
|
||||||
|
@ -13,7 +13,7 @@ use swc_common::{
|
|||||||
comments::SingleThreadedComments,
|
comments::SingleThreadedComments,
|
||||||
errors::{Handler, HANDLER},
|
errors::{Handler, HANDLER},
|
||||||
sync::Lrc,
|
sync::Lrc,
|
||||||
FileName, DUMMY_SP,
|
FileName, Mark, DUMMY_SP,
|
||||||
};
|
};
|
||||||
use swc_ecma_ast::{EsVersion, Expr, Lit, Module, Program, Str};
|
use swc_ecma_ast::{EsVersion, Expr, Lit, Module, Program, Str};
|
||||||
use swc_ecma_parser::{parse_file_as_module, Syntax};
|
use swc_ecma_parser::{parse_file_as_module, Syntax};
|
||||||
@ -24,8 +24,9 @@ use swc_ecma_transforms::{
|
|||||||
simplify::{dead_branch_remover, expr_simplifier},
|
simplify::{dead_branch_remover, expr_simplifier},
|
||||||
},
|
},
|
||||||
pass::noop,
|
pass::noop,
|
||||||
|
resolver_with_mark,
|
||||||
};
|
};
|
||||||
use swc_ecma_visit::FoldWith;
|
use swc_ecma_visit::{FoldWith, VisitMutWith};
|
||||||
|
|
||||||
use crate::loaders::json::load_json_as_module;
|
use crate::loaders::json::load_json_as_module;
|
||||||
|
|
||||||
@ -164,14 +165,17 @@ impl SwcLoader {
|
|||||||
|
|
||||||
helpers::HELPERS.set(&helpers, || {
|
helpers::HELPERS.set(&helpers, || {
|
||||||
HANDLER.set(handler, || {
|
HANDLER.set(handler, || {
|
||||||
let program = program.fold_with(&mut inline_globals(
|
let mut program = program.fold_with(&mut inline_globals(
|
||||||
self.env_map(),
|
self.env_map(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
));
|
));
|
||||||
let program = program.fold_with(&mut expr_simplifier(Default::default()));
|
let top_level_mark = Mark::fresh(Mark::root());
|
||||||
|
program.visit_mut_with(&mut resolver_with_mark(top_level_mark));
|
||||||
|
let program =
|
||||||
|
program.fold_with(&mut expr_simplifier(top_level_mark, Default::default()));
|
||||||
|
|
||||||
program.fold_with(&mut dead_branch_remover())
|
program.fold_with(&mut dead_branch_remover(top_level_mark))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -235,13 +239,16 @@ impl SwcLoader {
|
|||||||
|
|
||||||
helpers::HELPERS.set(&helpers, || {
|
helpers::HELPERS.set(&helpers, || {
|
||||||
HANDLER.set(handler, || {
|
HANDLER.set(handler, || {
|
||||||
let program = program.fold_with(&mut inline_globals(
|
let mut program = program.fold_with(&mut inline_globals(
|
||||||
self.env_map(),
|
self.env_map(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
));
|
));
|
||||||
let program = program.fold_with(&mut expr_simplifier(Default::default()));
|
let top_level_mark = Mark::fresh(Mark::root());
|
||||||
let program = program.fold_with(&mut dead_branch_remover());
|
program.visit_mut_with(&mut resolver_with_mark(top_level_mark));
|
||||||
|
let program = program
|
||||||
|
.fold_with(&mut expr_simplifier(top_level_mark, Default::default()));
|
||||||
|
let program = program.fold_with(&mut dead_branch_remover(top_level_mark));
|
||||||
|
|
||||||
program.fold_with(&mut pass)
|
program.fold_with(&mut pass)
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user