mirror of
https://github.com/swc-project/swc.git
synced 2024-12-23 05:32:09 +03:00
perf(es/minifier): Enable parallel processing (#5705)
This commit is contained in:
parent
748142e681
commit
1085667049
6
.github/workflows/cargo.yml
vendored
6
.github/workflows/cargo.yml
vendored
@ -440,14 +440,18 @@ jobs:
|
||||
- name: Run cargo test (concurrent)
|
||||
if: runner.os == 'Linux' && matrix.settings.crate != 'swc_ecma_minifier'
|
||||
shell: bash
|
||||
env:
|
||||
SWC_FORCE_CONCURRENT: "1"
|
||||
run: |
|
||||
./scripts/ci/test-concurrent.sh ${{ matrix.settings.crate }}
|
||||
|
||||
- name: Run cargo test (swc, concurrent)
|
||||
shell: bash
|
||||
if: matrix.settings.crate == 'swc' && runner.os == 'Linux'
|
||||
env:
|
||||
SWC_FORCE_CONCURRENT: "1"
|
||||
run: |
|
||||
cargo test --color always -p swc --features concurrent
|
||||
cargo test --color always -p swc --all-targets --features concurrent
|
||||
|
||||
- name: Install cargo-hack
|
||||
uses: baptiste0928/cargo-install@v1.1.0
|
||||
|
@ -9,7 +9,7 @@ use anyhow::Error;
|
||||
use ntest::timeout;
|
||||
use swc_atoms::js_word;
|
||||
use swc_bundler::{Bundler, Load, ModuleRecord};
|
||||
use swc_common::{collections::AHashSet, FileName, Mark, Span, GLOBALS};
|
||||
use swc_common::{collections::AHashSet, errors::HANDLER, FileName, Mark, Span, GLOBALS};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_codegen::{
|
||||
text_writer::{omit_trailing_semi, JsWriter, WriteJs},
|
||||
@ -1020,83 +1020,85 @@ fn run(url: &str, exports: &[&str]) {
|
||||
}
|
||||
|
||||
fn bundle(url: &str, minify: bool) -> String {
|
||||
testing::run_test2(false, |cm, _handler| {
|
||||
testing::run_test2(false, |cm, handler| {
|
||||
GLOBALS.with(|globals| {
|
||||
let mut bundler = Bundler::new(
|
||||
globals,
|
||||
cm.clone(),
|
||||
Loader { cm: cm.clone() },
|
||||
NodeResolver,
|
||||
swc_bundler::Config {
|
||||
require: false,
|
||||
disable_inliner: false,
|
||||
..Default::default()
|
||||
},
|
||||
Box::new(Hook),
|
||||
);
|
||||
let mut entries = HashMap::new();
|
||||
entries.insert(
|
||||
"main".to_string(),
|
||||
if url.starts_with("http") {
|
||||
FileName::Custom(url.to_string())
|
||||
} else {
|
||||
FileName::Real(url.to_string().into())
|
||||
},
|
||||
);
|
||||
let output = bundler.bundle(entries).unwrap();
|
||||
let mut module = output.into_iter().next().unwrap().module;
|
||||
|
||||
if minify {
|
||||
let unresolved_mark = Mark::new();
|
||||
let top_level_mark = Mark::new();
|
||||
|
||||
module.visit_mut_with(&mut resolver(unresolved_mark, top_level_mark, false));
|
||||
|
||||
module = swc_ecma_minifier::optimize(
|
||||
module.into(),
|
||||
HANDLER.set(&handler, || {
|
||||
let mut bundler = Bundler::new(
|
||||
globals,
|
||||
cm.clone(),
|
||||
None,
|
||||
None,
|
||||
&swc_ecma_minifier::option::MinifyOptions {
|
||||
compress: Some(Default::default()),
|
||||
mangle: Some(MangleOptions {
|
||||
top_level: true,
|
||||
..Default::default()
|
||||
}),
|
||||
Loader { cm: cm.clone() },
|
||||
NodeResolver,
|
||||
swc_bundler::Config {
|
||||
require: false,
|
||||
disable_inliner: false,
|
||||
..Default::default()
|
||||
},
|
||||
&swc_ecma_minifier::option::ExtraOptions {
|
||||
unresolved_mark,
|
||||
top_level_mark,
|
||||
Box::new(Hook),
|
||||
);
|
||||
let mut entries = HashMap::new();
|
||||
entries.insert(
|
||||
"main".to_string(),
|
||||
if url.starts_with("http") {
|
||||
FileName::Custom(url.to_string())
|
||||
} else {
|
||||
FileName::Real(url.to_string().into())
|
||||
},
|
||||
)
|
||||
.expect_module();
|
||||
module.visit_mut_with(&mut fixer(None));
|
||||
}
|
||||
|
||||
let mut buf = vec![];
|
||||
{
|
||||
let mut wr: Box<dyn WriteJs> =
|
||||
Box::new(JsWriter::new(cm.clone(), "\n", &mut buf, None));
|
||||
);
|
||||
let output = bundler.bundle(entries).unwrap();
|
||||
let mut module = output.into_iter().next().unwrap().module;
|
||||
|
||||
if minify {
|
||||
wr = Box::new(omit_trailing_semi(wr));
|
||||
let unresolved_mark = Mark::new();
|
||||
let top_level_mark = Mark::new();
|
||||
|
||||
module.visit_mut_with(&mut resolver(unresolved_mark, top_level_mark, false));
|
||||
|
||||
module = swc_ecma_minifier::optimize(
|
||||
module.into(),
|
||||
cm.clone(),
|
||||
None,
|
||||
None,
|
||||
&swc_ecma_minifier::option::MinifyOptions {
|
||||
compress: Some(Default::default()),
|
||||
mangle: Some(MangleOptions {
|
||||
top_level: true,
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
&swc_ecma_minifier::option::ExtraOptions {
|
||||
unresolved_mark,
|
||||
top_level_mark,
|
||||
},
|
||||
)
|
||||
.expect_module();
|
||||
module.visit_mut_with(&mut fixer(None));
|
||||
}
|
||||
|
||||
Emitter {
|
||||
cfg: swc_ecma_codegen::Config {
|
||||
minify,
|
||||
..Default::default()
|
||||
},
|
||||
cm: cm.clone(),
|
||||
comments: None,
|
||||
wr,
|
||||
}
|
||||
.emit_module(&module)
|
||||
.unwrap();
|
||||
}
|
||||
let mut buf = vec![];
|
||||
{
|
||||
let mut wr: Box<dyn WriteJs> =
|
||||
Box::new(JsWriter::new(cm.clone(), "\n", &mut buf, None));
|
||||
|
||||
Ok(String::from_utf8_lossy(&buf).to_string())
|
||||
if minify {
|
||||
wr = Box::new(omit_trailing_semi(wr));
|
||||
}
|
||||
|
||||
Emitter {
|
||||
cfg: swc_ecma_codegen::Config {
|
||||
minify,
|
||||
..Default::default()
|
||||
},
|
||||
cm: cm.clone(),
|
||||
comments: None,
|
||||
wr,
|
||||
}
|
||||
.emit_module(&module)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
Ok(String::from_utf8_lossy(&buf).to_string())
|
||||
})
|
||||
})
|
||||
})
|
||||
.unwrap()
|
||||
|
@ -17,9 +17,11 @@ version = "0.150.5"
|
||||
bench = false
|
||||
|
||||
[features]
|
||||
# This enables global concurrent mode
|
||||
concurrent = [
|
||||
"swc_common/concurrent",
|
||||
"swc_ecma_transforms_base/concurrent-renamer",
|
||||
"swc_ecma_transforms_optimization/concurrent",
|
||||
"rayon",
|
||||
"indexmap/rayon",
|
||||
]
|
||||
|
@ -5,7 +5,7 @@ extern crate swc_node_base;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||
use swc_common::{sync::Lrc, FileName, Mark, SourceMap};
|
||||
use swc_common::{errors::HANDLER, sync::Lrc, FileName, Mark, SourceMap};
|
||||
use swc_ecma_codegen::text_writer::JsWriter;
|
||||
use swc_ecma_minifier::{
|
||||
optimize,
|
||||
@ -49,60 +49,62 @@ criterion_main!(files);
|
||||
|
||||
fn run(src: &str) {
|
||||
testing::run_test2(false, |cm, handler| {
|
||||
let fm = cm.new_source_file(FileName::Anon, src.into());
|
||||
HANDLER.set(&handler, || {
|
||||
let fm = cm.new_source_file(FileName::Anon, src.into());
|
||||
|
||||
let unresolved_mark = Mark::new();
|
||||
let top_level_mark = Mark::new();
|
||||
let unresolved_mark = Mark::new();
|
||||
let top_level_mark = Mark::new();
|
||||
|
||||
let program = parse_file_as_module(
|
||||
&fm,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
None,
|
||||
&mut vec![],
|
||||
)
|
||||
.map_err(|err| {
|
||||
err.into_diagnostic(&handler).emit();
|
||||
let program = parse_file_as_module(
|
||||
&fm,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
None,
|
||||
&mut vec![],
|
||||
)
|
||||
.map_err(|err| {
|
||||
err.into_diagnostic(&handler).emit();
|
||||
})
|
||||
.map(|module| module.fold_with(&mut resolver(unresolved_mark, top_level_mark, false)))
|
||||
.unwrap();
|
||||
|
||||
let output = optimize(
|
||||
program.into(),
|
||||
cm.clone(),
|
||||
None,
|
||||
None,
|
||||
&MinifyOptions {
|
||||
rename: false,
|
||||
compress: Some(CompressOptions {
|
||||
..Default::default()
|
||||
}),
|
||||
mangle: Some(MangleOptions {
|
||||
props: None,
|
||||
top_level: true,
|
||||
keep_class_names: false,
|
||||
keep_fn_names: false,
|
||||
keep_private_props: false,
|
||||
ie8: false,
|
||||
safari10: false,
|
||||
reserved: Default::default(),
|
||||
}),
|
||||
wrap: false,
|
||||
enclose: false,
|
||||
},
|
||||
&ExtraOptions {
|
||||
unresolved_mark,
|
||||
top_level_mark,
|
||||
},
|
||||
)
|
||||
.expect_module();
|
||||
|
||||
let output = output.fold_with(&mut fixer(None));
|
||||
|
||||
let code = print(cm, &[output], true);
|
||||
|
||||
black_box(code);
|
||||
Ok(())
|
||||
})
|
||||
.map(|module| module.fold_with(&mut resolver(unresolved_mark, top_level_mark, false)))
|
||||
.unwrap();
|
||||
|
||||
let output = optimize(
|
||||
program.into(),
|
||||
cm.clone(),
|
||||
None,
|
||||
None,
|
||||
&MinifyOptions {
|
||||
rename: false,
|
||||
compress: Some(CompressOptions {
|
||||
..Default::default()
|
||||
}),
|
||||
mangle: Some(MangleOptions {
|
||||
props: None,
|
||||
top_level: true,
|
||||
keep_class_names: false,
|
||||
keep_fn_names: false,
|
||||
keep_private_props: false,
|
||||
ie8: false,
|
||||
safari10: false,
|
||||
reserved: Default::default(),
|
||||
}),
|
||||
wrap: false,
|
||||
enclose: false,
|
||||
},
|
||||
&ExtraOptions {
|
||||
unresolved_mark,
|
||||
top_level_mark,
|
||||
},
|
||||
)
|
||||
.expect_module();
|
||||
|
||||
let output = output.fold_with(&mut fixer(None));
|
||||
|
||||
let code = print(cm, &[output], true);
|
||||
|
||||
black_box(code);
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
use once_cell::sync::Lazy;
|
||||
use swc_common::{comments::Comments, pass::Repeat, sync::Lrc, SourceMap, GLOBALS};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::helpers::{Helpers, HELPERS};
|
||||
use swc_ecma_visit::VisitMutWith;
|
||||
use swc_timer::timer;
|
||||
|
||||
@ -76,173 +77,177 @@ pub fn optimize(
|
||||
options: &MinifyOptions,
|
||||
extra: &ExtraOptions,
|
||||
) -> Program {
|
||||
let _timer = timer!("minify");
|
||||
HELPERS.set(&Helpers::new(true), || {
|
||||
let _timer = timer!("minify");
|
||||
|
||||
let mut marks = Marks::new();
|
||||
marks.unresolved_mark = extra.unresolved_mark;
|
||||
let mut marks = Marks::new();
|
||||
marks.unresolved_mark = extra.unresolved_mark;
|
||||
|
||||
if let Some(defs) = options.compress.as_ref().map(|c| &c.global_defs) {
|
||||
let _timer = timer!("inline global defs");
|
||||
// Apply global defs.
|
||||
//
|
||||
// As terser treats `CONFIG['VALUE']` and `CONFIG.VALUE` differently, we don't
|
||||
// have to see if optimized code matches global definition and we can run
|
||||
// this at startup.
|
||||
if let Some(defs) = options.compress.as_ref().map(|c| &c.global_defs) {
|
||||
let _timer = timer!("inline global defs");
|
||||
// Apply global defs.
|
||||
//
|
||||
// As terser treats `CONFIG['VALUE']` and `CONFIG.VALUE` differently, we don't
|
||||
// have to see if optimized code matches global definition and we can run
|
||||
// this at startup.
|
||||
|
||||
if !defs.is_empty() {
|
||||
let defs = defs.iter().map(|(k, v)| (k.clone(), v.clone())).collect();
|
||||
m.visit_mut_with(&mut global_defs::globals_defs(
|
||||
defs,
|
||||
if !defs.is_empty() {
|
||||
let defs = defs.iter().map(|(k, v)| (k.clone(), v.clone())).collect();
|
||||
m.visit_mut_with(&mut global_defs::globals_defs(
|
||||
defs,
|
||||
extra.unresolved_mark,
|
||||
extra.top_level_mark,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let module_info = match &m {
|
||||
Program::Script(_) => ModuleInfo::default(),
|
||||
Program::Module(m) => ModuleInfo {
|
||||
blackbox_imports: m
|
||||
.body
|
||||
.iter()
|
||||
.filter_map(|v| v.as_module_decl())
|
||||
.filter_map(|v| match v {
|
||||
ModuleDecl::Import(i) => Some(i),
|
||||
_ => None,
|
||||
})
|
||||
.filter(|i| !i.src.value.starts_with("@swc/helpers"))
|
||||
.flat_map(|v| v.specifiers.iter())
|
||||
.map(|v| match v {
|
||||
ImportSpecifier::Named(v) => v.local.to_id(),
|
||||
ImportSpecifier::Default(v) => v.local.to_id(),
|
||||
ImportSpecifier::Namespace(v) => v.local.to_id(),
|
||||
})
|
||||
.collect(),
|
||||
// exports: m
|
||||
// .body
|
||||
// .iter()
|
||||
// .filter_map(|v| v.as_module_decl())
|
||||
// .filter_map(|v| match v {
|
||||
// ModuleDecl::ExportNamed(i) if i.src.is_none() => Some(i),
|
||||
// _ => None,
|
||||
// })
|
||||
// .flat_map(|v| v.specifiers.iter())
|
||||
// .filter_map(|v| match v {
|
||||
// ExportSpecifier::Named(v) => Some(v),
|
||||
// _ => None,
|
||||
// })
|
||||
// .filter_map(|v| match &v.orig {
|
||||
// ModuleExportName::Ident(i) => Some(i.to_id()),
|
||||
// ModuleExportName::Str(_) => None,
|
||||
// })
|
||||
// .collect(),
|
||||
},
|
||||
};
|
||||
|
||||
if let Some(options) = &options.compress {
|
||||
let _timer = timer!("precompress");
|
||||
|
||||
m.visit_mut_with(&mut precompress_optimizer(&module_info, options, marks));
|
||||
}
|
||||
|
||||
if options.compress.is_some() {
|
||||
m.visit_mut_with(&mut info_marker(
|
||||
options.compress.as_ref(),
|
||||
comments,
|
||||
marks,
|
||||
extra.unresolved_mark,
|
||||
extra.top_level_mark,
|
||||
));
|
||||
}
|
||||
}
|
||||
m.visit_mut_with(&mut unique_scope());
|
||||
|
||||
let module_info = match &m {
|
||||
Program::Script(_) => ModuleInfo::default(),
|
||||
Program::Module(m) => ModuleInfo {
|
||||
blackbox_imports: m
|
||||
.body
|
||||
.iter()
|
||||
.filter_map(|v| v.as_module_decl())
|
||||
.filter_map(|v| match v {
|
||||
ModuleDecl::Import(i) => Some(i),
|
||||
_ => None,
|
||||
})
|
||||
.filter(|i| !i.src.value.starts_with("@swc/helpers"))
|
||||
.flat_map(|v| v.specifiers.iter())
|
||||
.map(|v| match v {
|
||||
ImportSpecifier::Named(v) => v.local.to_id(),
|
||||
ImportSpecifier::Default(v) => v.local.to_id(),
|
||||
ImportSpecifier::Namespace(v) => v.local.to_id(),
|
||||
})
|
||||
.collect(),
|
||||
// exports: m
|
||||
// .body
|
||||
// .iter()
|
||||
// .filter_map(|v| v.as_module_decl())
|
||||
// .filter_map(|v| match v {
|
||||
// ModuleDecl::ExportNamed(i) if i.src.is_none() => Some(i),
|
||||
// _ => None,
|
||||
// })
|
||||
// .flat_map(|v| v.specifiers.iter())
|
||||
// .filter_map(|v| match v {
|
||||
// ExportSpecifier::Named(v) => Some(v),
|
||||
// _ => None,
|
||||
// })
|
||||
// .filter_map(|v| match &v.orig {
|
||||
// ModuleExportName::Ident(i) => Some(i.to_id()),
|
||||
// ModuleExportName::Str(_) => None,
|
||||
// })
|
||||
// .collect(),
|
||||
},
|
||||
};
|
||||
|
||||
if let Some(options) = &options.compress {
|
||||
let _timer = timer!("precompress");
|
||||
|
||||
m.visit_mut_with(&mut precompress_optimizer(&module_info, options, marks));
|
||||
}
|
||||
|
||||
if options.compress.is_some() {
|
||||
m.visit_mut_with(&mut info_marker(
|
||||
options.compress.as_ref(),
|
||||
comments,
|
||||
marks,
|
||||
extra.unresolved_mark,
|
||||
));
|
||||
}
|
||||
m.visit_mut_with(&mut unique_scope());
|
||||
|
||||
if options.wrap {
|
||||
// TODO: wrap_common_js
|
||||
// toplevel = toplevel.wrap_commonjs(options.wrap);
|
||||
}
|
||||
|
||||
if options.enclose {
|
||||
// TODO: enclose
|
||||
// toplevel = toplevel.wrap_enclose(options.enclose);
|
||||
}
|
||||
|
||||
// We don't need validation.
|
||||
|
||||
if let Some(ref mut _t) = timings {
|
||||
// TODO: store `rename`
|
||||
}
|
||||
|
||||
// Noop.
|
||||
// https://github.com/mishoo/UglifyJS2/issues/2794
|
||||
if options.rename && DISABLE_BUGGY_PASSES {
|
||||
// toplevel.figure_out_scope(options.mangle);
|
||||
// TODO: Pass `options.mangle` to name expander.
|
||||
m.visit_mut_with(&mut name_expander());
|
||||
}
|
||||
|
||||
if let Some(ref mut t) = timings {
|
||||
t.section("compress");
|
||||
}
|
||||
if let Some(options) = &options.compress {
|
||||
{
|
||||
let _timer = timer!("compress ast");
|
||||
|
||||
GLOBALS.with(|globals| {
|
||||
m.visit_mut_with(&mut compressor(
|
||||
globals,
|
||||
&module_info,
|
||||
marks,
|
||||
options,
|
||||
&Minification,
|
||||
))
|
||||
});
|
||||
if options.wrap {
|
||||
// TODO: wrap_common_js
|
||||
// toplevel = toplevel.wrap_commonjs(options.wrap);
|
||||
}
|
||||
|
||||
// Again, we don't need to validate ast
|
||||
if options.enclose {
|
||||
// TODO: enclose
|
||||
// toplevel = toplevel.wrap_enclose(options.enclose);
|
||||
}
|
||||
|
||||
let _timer = timer!("postcompress");
|
||||
// We don't need validation.
|
||||
|
||||
m.visit_mut_with(&mut postcompress_optimizer(options));
|
||||
m.visit_mut_with(&mut Repeat::new(pure_optimizer(
|
||||
options,
|
||||
None,
|
||||
marks,
|
||||
PureOptimizerConfig {
|
||||
force_str_for_tpl: Minification::force_str_for_tpl(),
|
||||
enable_join_vars: true,
|
||||
#[cfg(feature = "debug")]
|
||||
debug_infinite_loop: false,
|
||||
},
|
||||
)));
|
||||
}
|
||||
if let Some(ref mut _t) = timings {
|
||||
// TODO: store `rename`
|
||||
}
|
||||
|
||||
if let Some(ref mut _t) = timings {
|
||||
// TODO: store `scope`
|
||||
}
|
||||
if options.mangle.is_some() {
|
||||
// toplevel.figure_out_scope(options.mangle);
|
||||
}
|
||||
// Noop.
|
||||
// https://github.com/mishoo/UglifyJS2/issues/2794
|
||||
if options.rename && DISABLE_BUGGY_PASSES {
|
||||
// toplevel.figure_out_scope(options.mangle);
|
||||
// TODO: Pass `options.mangle` to name expander.
|
||||
m.visit_mut_with(&mut name_expander());
|
||||
}
|
||||
|
||||
if let Some(ref mut t) = timings {
|
||||
t.section("mangle");
|
||||
}
|
||||
if let Some(ref mut t) = timings {
|
||||
t.section("compress");
|
||||
}
|
||||
if let Some(options) = &options.compress {
|
||||
{
|
||||
let _timer = timer!("compress ast");
|
||||
|
||||
if let Some(mangle) = &options.mangle {
|
||||
let _timer = timer!("mangle names");
|
||||
// TODO: base54.reset();
|
||||
GLOBALS.with(|globals| {
|
||||
m.visit_mut_with(&mut compressor(
|
||||
globals,
|
||||
&module_info,
|
||||
marks,
|
||||
options,
|
||||
&Minification,
|
||||
))
|
||||
});
|
||||
}
|
||||
|
||||
m.visit_mut_with(&mut name_mangler(mangle.clone(), &m));
|
||||
}
|
||||
// Again, we don't need to validate ast
|
||||
|
||||
if let Some(property_mangle_options) = options.mangle.as_ref().and_then(|o| o.props.as_ref()) {
|
||||
mangle_properties(&mut m, &module_info, property_mangle_options.clone());
|
||||
}
|
||||
let _timer = timer!("postcompress");
|
||||
|
||||
m.visit_mut_with(&mut merge_exports());
|
||||
m.visit_mut_with(&mut postcompress_optimizer(options));
|
||||
m.visit_mut_with(&mut Repeat::new(pure_optimizer(
|
||||
options,
|
||||
None,
|
||||
marks,
|
||||
PureOptimizerConfig {
|
||||
force_str_for_tpl: Minification::force_str_for_tpl(),
|
||||
enable_join_vars: true,
|
||||
#[cfg(feature = "debug")]
|
||||
debug_infinite_loop: false,
|
||||
},
|
||||
)));
|
||||
}
|
||||
|
||||
if let Some(ref mut t) = timings {
|
||||
t.section("hygiene");
|
||||
t.end_section();
|
||||
}
|
||||
if let Some(ref mut _t) = timings {
|
||||
// TODO: store `scope`
|
||||
}
|
||||
if options.mangle.is_some() {
|
||||
// toplevel.figure_out_scope(options.mangle);
|
||||
}
|
||||
|
||||
m
|
||||
if let Some(ref mut t) = timings {
|
||||
t.section("mangle");
|
||||
}
|
||||
|
||||
if let Some(mangle) = &options.mangle {
|
||||
let _timer = timer!("mangle names");
|
||||
// TODO: base54.reset();
|
||||
|
||||
m.visit_mut_with(&mut name_mangler(mangle.clone(), &m));
|
||||
}
|
||||
|
||||
if let Some(property_mangle_options) =
|
||||
options.mangle.as_ref().and_then(|o| o.props.as_ref())
|
||||
{
|
||||
mangle_properties(&mut m, &module_info, property_mangle_options.clone());
|
||||
}
|
||||
|
||||
m.visit_mut_with(&mut merge_exports());
|
||||
|
||||
if let Some(ref mut t) = timings {
|
||||
t.section("hygiene");
|
||||
t.end_section();
|
||||
}
|
||||
|
||||
m
|
||||
})
|
||||
}
|
||||
|
@ -16,8 +16,11 @@ use anyhow::Error;
|
||||
use once_cell::sync::Lazy;
|
||||
use serde::Deserialize;
|
||||
use swc_common::{
|
||||
comments::SingleThreadedComments, errors::Handler, sync::Lrc, util::take::Take, EqIgnoreSpan,
|
||||
FileName, Mark, SourceMap, Spanned,
|
||||
comments::SingleThreadedComments,
|
||||
errors::{Handler, HANDLER},
|
||||
sync::Lrc,
|
||||
util::take::Take,
|
||||
EqIgnoreSpan, FileName, Mark, SourceMap, Spanned,
|
||||
};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_codegen::{
|
||||
@ -140,120 +143,118 @@ fn run(
|
||||
mangle: Option<TestMangleOptions>,
|
||||
skip_hygiene: bool,
|
||||
) -> Option<Module> {
|
||||
let _ = rayon::ThreadPoolBuilder::new()
|
||||
.thread_name(|i| format!("rayon-{}", i + 1))
|
||||
.build_global();
|
||||
HANDLER.set(handler, || {
|
||||
let disable_hygiene = mangle.is_some() || skip_hygiene;
|
||||
|
||||
let disable_hygiene = mangle.is_some() || skip_hygiene;
|
||||
let (_module, config) = parse_compressor_config(cm.clone(), config);
|
||||
|
||||
let (_module, config) = parse_compressor_config(cm.clone(), config);
|
||||
let fm = cm.load_file(input).expect("failed to load input.js");
|
||||
let comments = SingleThreadedComments::default();
|
||||
|
||||
let fm = cm.load_file(input).expect("failed to load input.js");
|
||||
let comments = SingleThreadedComments::default();
|
||||
eprintln!("---- {} -----\n{}", Color::Green.paint("Input"), fm.src);
|
||||
|
||||
eprintln!("---- {} -----\n{}", Color::Green.paint("Input"), fm.src);
|
||||
|
||||
if env::var("SWC_RUN").unwrap_or_default() == "1" {
|
||||
let stdout = stdout_of(&fm.src);
|
||||
match stdout {
|
||||
Ok(stdout) => {
|
||||
eprintln!(
|
||||
"---- {} -----\n{}",
|
||||
Color::Green.paint("Stdout (expected)"),
|
||||
stdout
|
||||
);
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!(
|
||||
"---- {} -----\n{:?}",
|
||||
Color::Green.paint("Error (of original source code)"),
|
||||
err
|
||||
);
|
||||
if env::var("SWC_RUN").unwrap_or_default() == "1" {
|
||||
let stdout = stdout_of(&fm.src);
|
||||
match stdout {
|
||||
Ok(stdout) => {
|
||||
eprintln!(
|
||||
"---- {} -----\n{}",
|
||||
Color::Green.paint("Stdout (expected)"),
|
||||
stdout
|
||||
);
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!(
|
||||
"---- {} -----\n{:?}",
|
||||
Color::Green.paint("Error (of original source code)"),
|
||||
err
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let unresolved_mark = Mark::new();
|
||||
let top_level_mark = Mark::new();
|
||||
let unresolved_mark = Mark::new();
|
||||
let top_level_mark = Mark::new();
|
||||
|
||||
let minification_start = Instant::now();
|
||||
let minification_start = Instant::now();
|
||||
|
||||
let lexer = Lexer::new(
|
||||
Syntax::Es(EsConfig {
|
||||
jsx: true,
|
||||
..Default::default()
|
||||
}),
|
||||
Default::default(),
|
||||
SourceFileInput::from(&*fm),
|
||||
Some(&comments),
|
||||
);
|
||||
|
||||
let mut parser = Parser::new_from(lexer);
|
||||
let program = parser
|
||||
.parse_module()
|
||||
.map_err(|err| {
|
||||
err.into_diagnostic(handler).emit();
|
||||
})
|
||||
.map(|module| module.fold_with(&mut resolver(unresolved_mark, top_level_mark, false)));
|
||||
|
||||
// Ignore parser errors.
|
||||
//
|
||||
// This is typically related to strict mode caused by module context.
|
||||
let program = match program {
|
||||
Ok(v) => v,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let optimization_start = Instant::now();
|
||||
let mut output = optimize(
|
||||
program.into(),
|
||||
cm,
|
||||
Some(&comments),
|
||||
None,
|
||||
&MinifyOptions {
|
||||
compress: Some(config),
|
||||
mangle: mangle.and_then(|v| match v {
|
||||
TestMangleOptions::Bool(v) => {
|
||||
if v {
|
||||
Some(MangleOptions {
|
||||
top_level: false,
|
||||
..Default::default()
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
TestMangleOptions::Normal(v) => Some(v),
|
||||
let lexer = Lexer::new(
|
||||
Syntax::Es(EsConfig {
|
||||
jsx: true,
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
&ExtraOptions {
|
||||
unresolved_mark,
|
||||
top_level_mark,
|
||||
},
|
||||
)
|
||||
.expect_module();
|
||||
let end = Instant::now();
|
||||
tracing::info!(
|
||||
"optimize({}) took {:?}",
|
||||
input.display(),
|
||||
end - optimization_start
|
||||
);
|
||||
Default::default(),
|
||||
SourceFileInput::from(&*fm),
|
||||
Some(&comments),
|
||||
);
|
||||
|
||||
if !disable_hygiene {
|
||||
output.visit_mut_with(&mut hygiene())
|
||||
}
|
||||
let mut parser = Parser::new_from(lexer);
|
||||
let program = parser
|
||||
.parse_module()
|
||||
.map_err(|err| {
|
||||
err.into_diagnostic(handler).emit();
|
||||
})
|
||||
.map(|module| module.fold_with(&mut resolver(unresolved_mark, top_level_mark, false)));
|
||||
|
||||
let output = output.fold_with(&mut fixer(None));
|
||||
// Ignore parser errors.
|
||||
//
|
||||
// This is typically related to strict mode caused by module context.
|
||||
let program = match program {
|
||||
Ok(v) => v,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let end = Instant::now();
|
||||
tracing::info!(
|
||||
"process({}) took {:?}",
|
||||
input.display(),
|
||||
end - minification_start
|
||||
);
|
||||
let optimization_start = Instant::now();
|
||||
let mut output = optimize(
|
||||
program.into(),
|
||||
cm,
|
||||
Some(&comments),
|
||||
None,
|
||||
&MinifyOptions {
|
||||
compress: Some(config),
|
||||
mangle: mangle.and_then(|v| match v {
|
||||
TestMangleOptions::Bool(v) => {
|
||||
if v {
|
||||
Some(MangleOptions {
|
||||
top_level: false,
|
||||
..Default::default()
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
TestMangleOptions::Normal(v) => Some(v),
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
&ExtraOptions {
|
||||
unresolved_mark,
|
||||
top_level_mark,
|
||||
},
|
||||
)
|
||||
.expect_module();
|
||||
let end = Instant::now();
|
||||
tracing::info!(
|
||||
"optimize({}) took {:?}",
|
||||
input.display(),
|
||||
end - optimization_start
|
||||
);
|
||||
|
||||
Some(output)
|
||||
if !disable_hygiene {
|
||||
output.visit_mut_with(&mut hygiene())
|
||||
}
|
||||
|
||||
let output = output.fold_with(&mut fixer(None));
|
||||
|
||||
let end = Instant::now();
|
||||
tracing::info!(
|
||||
"process({}) took {:?}",
|
||||
input.display(),
|
||||
end - minification_start
|
||||
);
|
||||
|
||||
Some(output)
|
||||
})
|
||||
}
|
||||
|
||||
fn stdout_of(code: &str) -> Result<String, Error> {
|
||||
|
@ -6,7 +6,10 @@ use ansi_term::Color;
|
||||
use anyhow::Error;
|
||||
use serde::Deserialize;
|
||||
use swc_common::{
|
||||
comments::SingleThreadedComments, errors::Handler, sync::Lrc, FileName, Mark, SourceMap,
|
||||
comments::SingleThreadedComments,
|
||||
errors::{Handler, HANDLER},
|
||||
sync::Lrc,
|
||||
FileName, Mark, SourceMap,
|
||||
};
|
||||
use swc_ecma_ast::Module;
|
||||
use swc_ecma_codegen::{
|
||||
@ -174,27 +177,29 @@ fn run_exec_test(input_src: &str, config: &str, skip_mangle: bool) {
|
||||
);
|
||||
|
||||
testing::run_test2(false, |cm, handler| {
|
||||
let _tracing = span!(Level::ERROR, "compress-only").entered();
|
||||
HANDLER.set(&handler, || {
|
||||
let _tracing = span!(Level::ERROR, "compress-only").entered();
|
||||
|
||||
let output = run(cm.clone(), &handler, input_src, Some(config), None);
|
||||
let output = output.expect("Parsing in base test should not fail");
|
||||
let output = print(cm, &[output], false, false);
|
||||
let output = run(cm.clone(), &handler, input_src, Some(config), None);
|
||||
let output = output.expect("Parsing in base test should not fail");
|
||||
let output = print(cm, &[output], false, false);
|
||||
|
||||
eprintln!(
|
||||
"---- {} -----\n{}",
|
||||
Color::Green.paint("Optimized code"),
|
||||
output
|
||||
);
|
||||
eprintln!(
|
||||
"---- {} -----\n{}",
|
||||
Color::Green.paint("Optimized code"),
|
||||
output
|
||||
);
|
||||
|
||||
let actual_output = stdout_of(&output).expect("failed to execute the optimized code");
|
||||
assert_ne!(actual_output, "");
|
||||
let actual_output = stdout_of(&output).expect("failed to execute the optimized code");
|
||||
assert_ne!(actual_output, "");
|
||||
|
||||
assert_eq!(
|
||||
DebugUsingDisplay(&actual_output),
|
||||
DebugUsingDisplay(&expected_output)
|
||||
);
|
||||
assert_eq!(
|
||||
DebugUsingDisplay(&actual_output),
|
||||
DebugUsingDisplay(&expected_output)
|
||||
);
|
||||
|
||||
Ok(())
|
||||
Ok(())
|
||||
})
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
|
@ -13,7 +13,12 @@ use std::{
|
||||
use ansi_term::Color;
|
||||
use anyhow::{anyhow, bail, Context, Error};
|
||||
use serde::Deserialize;
|
||||
use swc_common::{comments::SingleThreadedComments, errors::Handler, sync::Lrc, Mark, SourceMap};
|
||||
use swc_common::{
|
||||
comments::SingleThreadedComments,
|
||||
errors::{Handler, HANDLER},
|
||||
sync::Lrc,
|
||||
Mark, SourceMap,
|
||||
};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_codegen::{
|
||||
text_writer::{omit_trailing_semi, JsWriter, WriteJs},
|
||||
@ -160,87 +165,85 @@ fn parse_compressor_config(cm: Lrc<SourceMap>, s: &str) -> Result<(bool, Compres
|
||||
}
|
||||
|
||||
fn run(cm: Lrc<SourceMap>, handler: &Handler, input: &Path, config: &str) -> Option<Module> {
|
||||
let _ = rayon::ThreadPoolBuilder::new()
|
||||
.thread_name(|i| format!("rayon-{}", i + 1))
|
||||
.build_global();
|
||||
HANDLER.set(handler, || {
|
||||
let (_module, config) = parse_compressor_config(cm.clone(), config).ok()?;
|
||||
if config.ie8 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let (_module, config) = parse_compressor_config(cm.clone(), config).ok()?;
|
||||
if config.ie8 {
|
||||
return None;
|
||||
}
|
||||
let fm = cm.load_file(input).expect("failed to load input.js");
|
||||
let comments = SingleThreadedComments::default();
|
||||
|
||||
let fm = cm.load_file(input).expect("failed to load input.js");
|
||||
let comments = SingleThreadedComments::default();
|
||||
eprintln!("---- {} -----\n{}", Color::Green.paint("Input"), fm.src);
|
||||
|
||||
eprintln!("---- {} -----\n{}", Color::Green.paint("Input"), fm.src);
|
||||
let unresolved_mark = Mark::new();
|
||||
let top_level_mark = Mark::new();
|
||||
|
||||
let unresolved_mark = Mark::new();
|
||||
let top_level_mark = Mark::new();
|
||||
let minification_start = Instant::now();
|
||||
|
||||
let minification_start = Instant::now();
|
||||
let lexer = Lexer::new(
|
||||
Syntax::Es(EsConfig {
|
||||
jsx: true,
|
||||
..Default::default()
|
||||
}),
|
||||
Default::default(),
|
||||
SourceFileInput::from(&*fm),
|
||||
Some(&comments),
|
||||
);
|
||||
|
||||
let lexer = Lexer::new(
|
||||
Syntax::Es(EsConfig {
|
||||
jsx: true,
|
||||
..Default::default()
|
||||
}),
|
||||
Default::default(),
|
||||
SourceFileInput::from(&*fm),
|
||||
Some(&comments),
|
||||
);
|
||||
let mut parser = Parser::new_from(lexer);
|
||||
let program = parser
|
||||
.parse_module()
|
||||
.map_err(|err| {
|
||||
err.into_diagnostic(handler).emit();
|
||||
})
|
||||
.map(|module| module.fold_with(&mut resolver(unresolved_mark, top_level_mark, false)));
|
||||
|
||||
let mut parser = Parser::new_from(lexer);
|
||||
let program = parser
|
||||
.parse_module()
|
||||
.map_err(|err| {
|
||||
err.into_diagnostic(handler).emit();
|
||||
})
|
||||
.map(|module| module.fold_with(&mut resolver(unresolved_mark, top_level_mark, false)));
|
||||
// Ignore parser errors.
|
||||
//
|
||||
// This is typically related to strict mode caused by module context.
|
||||
let program = match program {
|
||||
Ok(v) => v,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
// Ignore parser errors.
|
||||
//
|
||||
// This is typically related to strict mode caused by module context.
|
||||
let program = match program {
|
||||
Ok(v) => v,
|
||||
_ => return None,
|
||||
};
|
||||
let optimization_start = Instant::now();
|
||||
let mut output = optimize(
|
||||
program.into(),
|
||||
cm,
|
||||
Some(&comments),
|
||||
None,
|
||||
&MinifyOptions {
|
||||
compress: Some(config),
|
||||
mangle: None,
|
||||
..Default::default()
|
||||
},
|
||||
&ExtraOptions {
|
||||
unresolved_mark,
|
||||
top_level_mark,
|
||||
},
|
||||
)
|
||||
.expect_module();
|
||||
let end = Instant::now();
|
||||
tracing::info!(
|
||||
"optimize({}) took {:?}",
|
||||
input.display(),
|
||||
end - optimization_start
|
||||
);
|
||||
|
||||
let optimization_start = Instant::now();
|
||||
let mut output = optimize(
|
||||
program.into(),
|
||||
cm,
|
||||
Some(&comments),
|
||||
None,
|
||||
&MinifyOptions {
|
||||
compress: Some(config),
|
||||
mangle: None,
|
||||
..Default::default()
|
||||
},
|
||||
&ExtraOptions {
|
||||
unresolved_mark,
|
||||
top_level_mark,
|
||||
},
|
||||
)
|
||||
.expect_module();
|
||||
let end = Instant::now();
|
||||
tracing::info!(
|
||||
"optimize({}) took {:?}",
|
||||
input.display(),
|
||||
end - optimization_start
|
||||
);
|
||||
output.visit_mut_with(&mut hygiene());
|
||||
|
||||
output.visit_mut_with(&mut hygiene());
|
||||
let output = output.fold_with(&mut fixer(None));
|
||||
|
||||
let output = output.fold_with(&mut fixer(None));
|
||||
let end = Instant::now();
|
||||
tracing::info!(
|
||||
"process({}) took {:?}",
|
||||
input.display(),
|
||||
end - minification_start
|
||||
);
|
||||
|
||||
let end = Instant::now();
|
||||
tracing::info!(
|
||||
"process({}) took {:?}",
|
||||
input.display(),
|
||||
end - minification_start
|
||||
);
|
||||
|
||||
Some(output)
|
||||
Some(output)
|
||||
})
|
||||
}
|
||||
|
||||
fn stdout_of(code: &str, timeout: Duration) -> Result<String, Error> {
|
||||
|
@ -69,7 +69,7 @@ where
|
||||
where
|
||||
N: Send + Sync + VisitWith<Self>,
|
||||
{
|
||||
if nodes.len() >= threshold {
|
||||
if nodes.len() >= threshold || option_env!("SWC_FORCE_CONCURRENT") == Some("1") {
|
||||
GLOBALS.with(|globals| {
|
||||
HELPERS.with(|helpers| {
|
||||
HANDLER.with(|handler| {
|
||||
@ -127,7 +127,7 @@ where
|
||||
where
|
||||
N: Send + Sync + VisitMutWith<Self>,
|
||||
{
|
||||
if nodes.len() >= threshold {
|
||||
if nodes.len() >= threshold || option_env!("SWC_FORCE_CONCURRENT") == Some("1") {
|
||||
GLOBALS.with(|globals| {
|
||||
HELPERS.with(|helpers| {
|
||||
HANDLER.with(|handler| {
|
||||
@ -185,7 +185,7 @@ where
|
||||
where
|
||||
N: Send + Sync + FoldWith<Self>,
|
||||
{
|
||||
if nodes.len() >= threshold {
|
||||
if nodes.len() >= threshold || option_env!("SWC_FORCE_CONCURRENT") == Some("1") {
|
||||
use rayon::prelude::*;
|
||||
|
||||
let (visitor, nodes) = GLOBALS.with(|globals| {
|
||||
|
@ -359,58 +359,43 @@ impl<'a> VisitMut for Operator<'a> {
|
||||
|
||||
#[cfg(feature = "concurrent")]
|
||||
if nodes.len() >= 64 * cpu_count() {
|
||||
use swc_common::errors::HANDLER;
|
||||
|
||||
use crate::helpers::HELPERS;
|
||||
|
||||
::swc_common::GLOBALS.with(|globals| {
|
||||
HELPERS.with(|helpers| {
|
||||
HANDLER.with(|handler| {
|
||||
use rayon::prelude::*;
|
||||
use rayon::prelude::*;
|
||||
|
||||
let (visitor, new_nodes) = take(nodes)
|
||||
.into_par_iter()
|
||||
.map(|mut node| {
|
||||
::swc_common::GLOBALS.set(globals, || {
|
||||
HELPERS.set(helpers, || {
|
||||
HANDLER.set(handler, || {
|
||||
let mut visitor = Parallel::create(&*self);
|
||||
node.visit_mut_with(&mut visitor);
|
||||
let (visitor, new_nodes) = take(nodes)
|
||||
.into_par_iter()
|
||||
.map(|mut node| {
|
||||
::swc_common::GLOBALS.set(globals, || {
|
||||
let mut visitor = Parallel::create(&*self);
|
||||
node.visit_mut_with(&mut visitor);
|
||||
|
||||
let mut nodes = Vec::with_capacity(4);
|
||||
let mut nodes = Vec::with_capacity(4);
|
||||
|
||||
ParExplode::after_one_module_item(
|
||||
&mut visitor,
|
||||
&mut nodes,
|
||||
);
|
||||
ParExplode::after_one_module_item(&mut visitor, &mut nodes);
|
||||
|
||||
nodes.push(node);
|
||||
nodes.push(node);
|
||||
|
||||
(visitor, nodes)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
.reduce(
|
||||
|| (Parallel::create(&*self), vec![]),
|
||||
|mut a, b| {
|
||||
Parallel::merge(&mut a.0, b.0);
|
||||
|
||||
a.1.extend(b.1);
|
||||
|
||||
a
|
||||
},
|
||||
);
|
||||
|
||||
Parallel::merge(self, visitor);
|
||||
|
||||
{
|
||||
self.after_module_items(nodes);
|
||||
}
|
||||
|
||||
*nodes = new_nodes;
|
||||
(visitor, nodes)
|
||||
})
|
||||
})
|
||||
})
|
||||
.reduce(
|
||||
|| (Parallel::create(&*self), vec![]),
|
||||
|mut a, b| {
|
||||
Parallel::merge(&mut a.0, b.0);
|
||||
|
||||
a.1.extend(b.1);
|
||||
|
||||
a
|
||||
},
|
||||
);
|
||||
|
||||
Parallel::merge(self, visitor);
|
||||
|
||||
{
|
||||
self.after_module_items(nodes);
|
||||
}
|
||||
|
||||
*nodes = new_nodes;
|
||||
});
|
||||
|
||||
return;
|
||||
|
@ -2,7 +2,6 @@ use swc_atoms::JsWord;
|
||||
use swc_common::{collections::AHashSet, Spanned};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::perf::Parallel;
|
||||
use swc_ecma_transforms_macros::parallel;
|
||||
use swc_ecma_utils::quote_str;
|
||||
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};
|
||||
use swc_trace_macro::swc_trace;
|
||||
@ -22,7 +21,6 @@ impl Parallel for DuplicateKeys {
|
||||
}
|
||||
|
||||
#[swc_trace]
|
||||
#[parallel]
|
||||
impl VisitMut for DuplicateKeys {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
use swc_common::util::take::Take;
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::perf::Parallel;
|
||||
use swc_ecma_transforms_macros::parallel;
|
||||
use swc_ecma_utils::{private_ident, IdentUsageFinder};
|
||||
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};
|
||||
use swc_trace_macro::swc_trace;
|
||||
@ -53,7 +52,6 @@ fn prepare(i: Ident) -> Ident {
|
||||
}
|
||||
|
||||
#[swc_trace]
|
||||
#[parallel]
|
||||
impl VisitMut for FnName {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
use swc_common::{util::take::Take, Span, Spanned};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::{helper, perf::Parallel};
|
||||
use swc_ecma_transforms_macros::parallel;
|
||||
use swc_ecma_utils::ExprFactory;
|
||||
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};
|
||||
use swc_trace_macro::swc_trace;
|
||||
@ -46,7 +45,6 @@ impl Parallel for InstanceOf {
|
||||
}
|
||||
|
||||
#[swc_trace]
|
||||
#[parallel]
|
||||
impl VisitMut for InstanceOf {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
use swc_common::util::take::Take;
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::perf::Parallel;
|
||||
use swc_ecma_transforms_macros::parallel;
|
||||
use swc_ecma_utils::quote_ident;
|
||||
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};
|
||||
use swc_trace_macro::swc_trace;
|
||||
@ -57,7 +56,6 @@ impl Parallel for Shorthand {
|
||||
}
|
||||
|
||||
#[swc_trace]
|
||||
#[parallel]
|
||||
impl VisitMut for Shorthand {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::perf::Parallel;
|
||||
use swc_ecma_transforms_macros::parallel;
|
||||
use swc_ecma_utils::{quote_ident, ExprFactory};
|
||||
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};
|
||||
use swc_trace_macro::swc_trace;
|
||||
@ -35,7 +34,6 @@ impl Parallel for StickyRegex {
|
||||
}
|
||||
|
||||
#[swc_trace]
|
||||
#[parallel]
|
||||
impl VisitMut for StickyRegex {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
|
@ -5,7 +5,6 @@ use swc_atoms::{js_word, JsWord};
|
||||
use swc_common::{util::take::Take, BytePos, Spanned, DUMMY_SP};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::{helper, perf::Parallel};
|
||||
use swc_ecma_transforms_macros::parallel;
|
||||
use swc_ecma_utils::{
|
||||
is_literal, prepend_stmts, private_ident, quote_ident, undefined, ExprFactory, StmtLike,
|
||||
};
|
||||
@ -46,7 +45,6 @@ impl Parallel for TemplateLiteral {
|
||||
}
|
||||
|
||||
#[swc_trace]
|
||||
#[parallel]
|
||||
impl VisitMut for TemplateLiteral {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
|
@ -2,7 +2,6 @@ use swc_atoms::js_word;
|
||||
use swc_common::{util::take::Take, DUMMY_SP};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::{helper, perf::Parallel};
|
||||
use swc_ecma_transforms_macros::parallel;
|
||||
use swc_ecma_utils::{quote_str, ExprFactory};
|
||||
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};
|
||||
use swc_trace_macro::swc_trace;
|
||||
@ -25,7 +24,6 @@ impl Parallel for TypeOfSymbol {
|
||||
}
|
||||
|
||||
#[swc_trace]
|
||||
#[parallel]
|
||||
impl VisitMut for TypeOfSymbol {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
|
@ -10,7 +10,7 @@ use swc_ecma_transforms_base::{
|
||||
helper, helper_expr,
|
||||
perf::{Check, Parallel},
|
||||
};
|
||||
use swc_ecma_transforms_macros::{fast_path, parallel};
|
||||
use swc_ecma_transforms_macros::fast_path;
|
||||
use swc_ecma_utils::{
|
||||
alias_ident_for, alias_if_required, is_literal, private_ident, quote_ident, var::VarCollector,
|
||||
ExprFactory, StmtLike,
|
||||
@ -1084,7 +1084,6 @@ impl Parallel for ObjectSpread {
|
||||
}
|
||||
|
||||
#[swc_trace]
|
||||
#[parallel]
|
||||
impl VisitMut for ObjectSpread {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
use swc_common::{util::take::Take, DUMMY_SP};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::perf::Parallel;
|
||||
use swc_ecma_transforms_macros::parallel;
|
||||
use swc_ecma_utils::{alias_ident_for, prepend_stmt};
|
||||
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};
|
||||
use swc_trace_macro::swc_trace;
|
||||
@ -57,7 +56,6 @@ impl Parallel for Operators {
|
||||
}
|
||||
|
||||
#[swc_trace]
|
||||
#[parallel]
|
||||
impl VisitMut for Operators {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
use swc_atoms::{js_word, JsWord};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::perf::Parallel;
|
||||
use swc_ecma_transforms_macros::parallel;
|
||||
use swc_ecma_visit::{
|
||||
as_folder, noop_visit_mut_type, visit_mut_obj_and_computed, Fold, VisitMut, VisitMutWith,
|
||||
};
|
||||
@ -21,7 +20,6 @@ impl Parallel for EsReservedWord {
|
||||
fn merge(&mut self, _: Self) {}
|
||||
}
|
||||
|
||||
#[parallel]
|
||||
impl VisitMut for EsReservedWord {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
|
@ -115,7 +115,8 @@ fn make_par_visit_method(
|
||||
use swc_ecma_visit::FoldWith;
|
||||
|
||||
#[cfg(feature = "rayon")]
|
||||
if nodes.len() >= threshold {
|
||||
if nodes.len() >= threshold || option_env!("SWC_FORCE_CONCURRENT") == Some("1")
|
||||
{
|
||||
use rayon::prelude::*;
|
||||
|
||||
let (visitor, mut nodes) = ::swc_common::GLOBALS.with(|globals| {
|
||||
@ -204,7 +205,8 @@ fn make_par_visit_method(
|
||||
use swc_ecma_visit::FoldWith;
|
||||
|
||||
#[cfg(feature = "rayon")]
|
||||
if nodes.len() >= threshold {
|
||||
if nodes.len() >= threshold || option_env!("SWC_FORCE_CONCURRENT") == Some("1")
|
||||
{
|
||||
use rayon::prelude::*;
|
||||
|
||||
let (visitor, mut nodes) = ::swc_common::GLOBALS.with(|globals| {
|
||||
@ -289,7 +291,8 @@ fn make_par_visit_method(
|
||||
use swc_ecma_visit::VisitMutWith;
|
||||
|
||||
#[cfg(feature = "rayon")]
|
||||
if nodes.len() >= threshold {
|
||||
if nodes.len() >= threshold || option_env!("SWC_FORCE_CONCURRENT") == Some("1")
|
||||
{
|
||||
::swc_common::GLOBALS.with(|globals| {
|
||||
swc_ecma_transforms_base::helpers::HELPERS.with(|helpers| {
|
||||
HANDLER.with(|handler| {
|
||||
@ -380,7 +383,8 @@ fn make_par_visit_method(
|
||||
use swc_ecma_visit::VisitMutWith;
|
||||
|
||||
#[cfg(feature = "rayon")]
|
||||
if nodes.len() >= threshold {
|
||||
if nodes.len() >= threshold || option_env!("SWC_FORCE_CONCURRENT") == Some("1")
|
||||
{
|
||||
::swc_common::GLOBALS.with(|globals| {
|
||||
swc_ecma_transforms_base::helpers::HELPERS.with(|helpers| {
|
||||
HANDLER.with(|handler| {
|
||||
|
@ -14,8 +14,12 @@ version = "0.158.0"
|
||||
bench = false
|
||||
|
||||
[features]
|
||||
concurrent = ["swc_common/concurrent", "rayon"]
|
||||
debug = []
|
||||
concurrent = [
|
||||
"swc_common/concurrent",
|
||||
"swc_ecma_transforms_base/concurrent",
|
||||
"rayon",
|
||||
]
|
||||
debug = []
|
||||
|
||||
[dependencies]
|
||||
ahash = "0.7.4"
|
||||
|
@ -1,7 +1,6 @@
|
||||
use swc_common::DUMMY_SP;
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::perf::Parallel;
|
||||
use swc_ecma_transforms_macros::parallel;
|
||||
use swc_ecma_utils::quote_ident;
|
||||
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut};
|
||||
|
||||
@ -28,7 +27,6 @@ impl Parallel for JsxSelf {
|
||||
fn merge(&mut self, _: Self) {}
|
||||
}
|
||||
|
||||
#[parallel]
|
||||
impl VisitMut for JsxSelf {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
use swc_common::{sync::Lrc, SourceMap, DUMMY_SP};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_transforms_base::perf::Parallel;
|
||||
use swc_ecma_transforms_macros::parallel;
|
||||
use swc_ecma_utils::quote_ident;
|
||||
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut};
|
||||
|
||||
@ -27,7 +26,6 @@ impl Parallel for JsxSrc {
|
||||
fn merge(&mut self, _: Self) {}
|
||||
}
|
||||
|
||||
#[parallel]
|
||||
impl VisitMut for JsxSrc {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
|
@ -14,5 +14,5 @@ if [[ "swc" == "$1" ]]; then
|
||||
fi
|
||||
|
||||
if [[ $CRATES == *"$1"* ]]; then
|
||||
cargo test --color always -p $1 --features "$1/concurrent"
|
||||
cargo test --color always -p $1 --all-targets --features "$1/concurrent"
|
||||
fi
|
Loading…
Reference in New Issue
Block a user