feat(es/optimization): Accept top level mark from simplifiers (#4434)

This commit is contained in:
Donny/강동윤 2022-04-26 00:31:59 +09:00 committed by GitHub
parent d6c82b3b3a
commit 8048597c9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 149 additions and 143 deletions

View File

@ -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"]

View File

@ -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
); );

View File

@ -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 {

View File

@ -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) => {

View File

@ -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));
} }
_ => {} _ => {}

View File

@ -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`");
})?; })?;

View File

@ -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"}

View File

@ -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;

View File

@ -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())
} }

View File

@ -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,

View File

@ -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);

View File

@ -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(),

View File

@ -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,

View File

@ -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)
)) ))
} }

View File

@ -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)
}
}

View File

@ -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,
); );

View File

@ -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) {

View File

@ -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)
}) })