Skip to content

Commit d1c4817

Browse files
authored
feat(swc): Expose minifier api (#1978)
swc_ecma_codegen: - Fix codegen of imports when minification is enabled. swc_ecma_minifier: - Mangle identifiers used by imports. swc: - Support specifing `jsc.minify`. (#704, #1371) swc/node: - Add `.minify()`. - Add `.minifySync()`. swc/wasm: - Add `.minifySync()`.
1 parent eecaac1 commit d1c4817

File tree

32 files changed

+838
-184
lines changed

32 files changed

+838
-184
lines changed

Cargo.lock

Lines changed: 6 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ edition = "2018"
99
license = "Apache-2.0/MIT"
1010
name = "swc"
1111
repository = "https://github.com/swc-project/swc.git"
12-
version = "0.32.0"
12+
version = "0.33.0"
1313

1414
[lib]
1515
name = "swc"
@@ -35,6 +35,7 @@ swc_ecma_ast = {version = "0.49.0", path = "./ecmascript/ast"}
3535
swc_ecma_codegen = {version = "0.64.0", path = "./ecmascript/codegen"}
3636
swc_ecma_ext_transforms = {version = "0.23.0", path = "./ecmascript/ext-transforms"}
3737
swc_ecma_loader = {version = "0.12.0", path = "./ecmascript/loader", features = ["lru", "node", "tsc"]}
38+
swc_ecma_minifier = {version = "0.16.0", path = "./ecmascript/minifier"}
3839
swc_ecma_parser = {version = "0.65.0", path = "./ecmascript/parser"}
3940
swc_ecma_preset_env = {version = "0.31.0", path = "./ecmascript/preset-env"}
4041
swc_ecma_transforms = {version = "0.61.0", path = "./ecmascript/transforms", features = [
@@ -45,6 +46,7 @@ swc_ecma_transforms = {version = "0.61.0", path = "./ecmascript/transforms", fea
4546
"react",
4647
"typescript",
4748
]}
49+
swc_ecma_transforms_base = {version = "0.24.1", path = "./ecmascript/transforms/base"}
4850
swc_ecma_utils = {version = "0.41.0", path = "./ecmascript/utils"}
4951
swc_ecma_visit = {version = "0.35.0", path = "./ecmascript/visit"}
5052
swc_node_base = {version = "0.2.0", path = "./node/base"}

ecmascript/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ edition = "2018"
66
license = "Apache-2.0/MIT"
77
name = "swc_ecmascript"
88
repository = "https://github.com/swc-project/swc.git"
9-
version = "0.49.0"
9+
version = "0.50.0"
1010

1111
[package.metadata.docs.rs]
1212
all-features = true
@@ -34,7 +34,7 @@ typescript = ["typescript-parser", "swc_ecma_transforms/typescript"]
3434
swc_ecma_ast = {version = "0.49.0", path = "./ast"}
3535
swc_ecma_codegen = {version = "0.64.0", path = "./codegen", optional = true}
3636
swc_ecma_dep_graph = {version = "0.33.0", path = "./dep-graph", optional = true}
37-
swc_ecma_minifier = {version = "0.15.0", path = "./minifier", optional = true}
37+
swc_ecma_minifier = {version = "0.16.0", path = "./minifier", optional = true}
3838
swc_ecma_parser = {version = "0.65.0", path = "./parser", optional = true, default-features = false}
3939
swc_ecma_transforms = {version = "0.61.0", path = "./transforms", optional = true}
4040
swc_ecma_utils = {version = "0.41.0", path = "./utils", optional = true}

ecmascript/codegen/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"]
77
license = "Apache-2.0/MIT"
88
name = "swc_ecma_codegen"
99
repository = "https://github.com/swc-project/swc.git"
10-
version = "0.64.2"
10+
version = "0.64.3"
1111

1212
[dependencies]
1313
bitflags = "1"

ecmascript/codegen/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,9 @@ impl<'a> Emitter<'a> {
115115

116116
self.emit_trailing_comments_of_pos(node.span().hi, true, true)?;
117117

118-
self.wr.write_line()?;
118+
if !self.cfg.minify {
119+
self.wr.write_line()?;
120+
}
119121
}
120122

121123
#[emitter]
@@ -190,7 +192,7 @@ impl<'a> Emitter<'a> {
190192

191193
if specifiers.is_empty() {
192194
if emitted_ns || emitted_default {
193-
formatting_space!();
195+
space!();
194196
keyword!("from");
195197
formatting_space!();
196198
}

ecmascript/codegen/src/stmt.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ mod tests {
9292
fn import() {
9393
assert_min(
9494
"import colors, { color } from 'patterns/colors';",
95-
"import colors,{color}from'patterns/colors';",
95+
"import colors,{color}from'patterns/colors'",
9696
);
9797
assert_pretty(
9898
"import colors, { color } from 'patterns/colors';",

ecmascript/codegen/src/tests.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ fn empty_named_export() {
231231
fn empty_named_export_min() {
232232
test_from_to_custom_config(
233233
"export { }",
234-
"export{};",
234+
"export{}",
235235
Config { minify: true },
236236
Default::default(),
237237
);
@@ -246,7 +246,7 @@ fn empty_named_export_from() {
246246
fn empty_named_export_from_min() {
247247
test_from_to_custom_config(
248248
"export { } from 'foo';",
249-
"export{}from'foo';",
249+
"export{}from'foo'",
250250
Config { minify: true },
251251
Default::default(),
252252
);
@@ -261,7 +261,7 @@ fn named_export_from() {
261261
fn named_export_from_min() {
262262
test_from_to_custom_config(
263263
"export { bar } from 'foo';",
264-
"export{bar}from'foo';",
264+
"export{bar}from'foo'",
265265
Config { minify: true },
266266
Default::default(),
267267
);
@@ -284,7 +284,7 @@ fn export_namespace_from() {
284284
fn export_namespace_from_min() {
285285
test_from_to_custom_config(
286286
"export * as Foo from 'foo';",
287-
"export*as Foo from'foo';",
287+
"export*as Foo from'foo'",
288288
Config { minify: true },
289289
Syntax::Es(EsConfig {
290290
export_namespace_from: true,
@@ -310,7 +310,7 @@ fn named_and_namespace_export_from() {
310310
fn named_and_namespace_export_from_min() {
311311
test_from_to_custom_config(
312312
"export * as Foo, { bar } from 'foo';",
313-
"export*as Foo,{bar}from'foo';",
313+
"export*as Foo,{bar}from'foo'",
314314
Config { minify: true },
315315
Syntax::Es(EsConfig {
316316
export_namespace_from: true,

ecmascript/minifier/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs", "src/lists/*.json"]
77
license = "Apache-2.0/MIT"
88
name = "swc_ecma_minifier"
99
repository = "https://github.com/swc-project/swc.git"
10-
version = "0.15.0"
10+
version = "0.16.0"
1111

1212
[features]
1313
debug = []

ecmascript/minifier/src/analyzer/mod.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,12 @@ impl Visit for UsageAnalyzer {
482482
}
483483
}
484484

485+
fn visit_fn_decl(&mut self, n: &FnDecl, _: &dyn Node) {
486+
self.declare_decl(&n.ident, true, None, true);
487+
488+
n.visit_children_with(self);
489+
}
490+
485491
fn visit_fn_expr(&mut self, n: &FnExpr, _: &dyn Node) {
486492
n.visit_children_with(self);
487493

@@ -494,12 +500,6 @@ impl Visit for UsageAnalyzer {
494500
}
495501
}
496502

497-
fn visit_fn_decl(&mut self, n: &FnDecl, _: &dyn Node) {
498-
self.declare_decl(&n.ident, true, None, true);
499-
500-
n.visit_children_with(self);
501-
}
502-
503503
fn visit_for_in_stmt(&mut self, n: &ForInStmt, _: &dyn Node) {
504504
n.right.visit_with(n, self);
505505

@@ -584,6 +584,18 @@ impl Visit for UsageAnalyzer {
584584
n.alt.visit_with(n, &mut *self.with_ctx(ctx));
585585
}
586586

587+
fn visit_import_default_specifier(&mut self, n: &ImportDefaultSpecifier, _: &dyn Node) {
588+
self.declare_decl(&n.local, true, None, false);
589+
}
590+
591+
fn visit_import_named_specifier(&mut self, n: &ImportNamedSpecifier, _: &dyn Node) {
592+
self.declare_decl(&n.local, true, None, false);
593+
}
594+
595+
fn visit_import_star_as_specifier(&mut self, n: &ImportStarAsSpecifier, _: &dyn Node) {
596+
self.declare_decl(&n.local, true, None, false);
597+
}
598+
587599
fn visit_member_expr(&mut self, e: &MemberExpr, _: &dyn Node) {
588600
{
589601
let ctx = Ctx {

ecmascript/minifier/src/option/terser.rs

Lines changed: 78 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
//! Compatibility for terser config.
22
3-
use crate::option::PureGetterOption;
4-
3+
use super::true_by_default;
54
use super::CompressOptions;
65
use super::TopLevelOptions;
6+
use crate::option::PureGetterOption;
77
use fxhash::FxHashMap;
8-
use serde::Deserialize;
8+
use serde::{Deserialize, Serialize};
99
use serde_json::Value;
1010
use swc_atoms::JsWord;
1111
use swc_common::input::SourceFileInput;
@@ -18,15 +18,21 @@ use swc_ecma_parser::lexer::Lexer;
1818
use swc_ecma_parser::Parser;
1919
use swc_ecma_utils::drop_span;
2020

21-
#[derive(Debug, Clone, Deserialize)]
21+
#[derive(Debug, Clone, Serialize, Deserialize)]
2222
#[serde(deny_unknown_fields)]
2323
#[serde(untagged)]
2424
pub enum TerserEcmaVersion {
2525
Num(usize),
2626
Str(String),
2727
}
2828

29-
#[derive(Debug, Clone, Deserialize)]
29+
impl Default for TerserEcmaVersion {
30+
fn default() -> Self {
31+
Self::Num(5)
32+
}
33+
}
34+
35+
#[derive(Debug, Clone, Serialize, Deserialize)]
3036
#[serde(deny_unknown_fields)]
3137
#[serde(untagged)]
3238
pub enum TerserPureGetterOption {
@@ -42,39 +48,39 @@ impl Default for TerserPureGetterOption {
4248
}
4349
}
4450

45-
#[derive(Debug, Clone, Copy, Deserialize)]
51+
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
4652
#[serde(deny_unknown_fields)]
4753
#[serde(untagged)]
4854
pub enum TerserInlineOption {
4955
Bool(bool),
5056
Num(u8),
5157
}
5258

53-
#[derive(Debug, Clone, Deserialize)]
59+
#[derive(Debug, Clone, Serialize, Deserialize)]
5460
#[serde(deny_unknown_fields)]
5561
#[serde(untagged)]
5662
pub enum TerserTopLevelOptions {
5763
Bool(bool),
5864
Str(String),
5965
}
6066

61-
#[derive(Debug, Clone, Copy, Deserialize)]
67+
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
6268
#[serde(deny_unknown_fields)]
6369
#[serde(untagged)]
6470
pub enum TerserSequenceOptions {
6571
Bool(bool),
6672
Num(u8),
6773
}
6874

69-
#[derive(Debug, Clone, Deserialize)]
75+
#[derive(Debug, Clone, Serialize, Deserialize)]
7076
#[serde(deny_unknown_fields)]
7177
#[serde(untagged)]
7278
pub enum TerserTopRetainOption {
7379
Str(String),
7480
Seq(Vec<JsWord>),
7581
}
7682

77-
#[derive(Debug, Clone, Deserialize)]
83+
#[derive(Debug, Clone, Serialize, Deserialize)]
7884
#[serde(deny_unknown_fields)]
7985
pub struct TerserCompressorOptions {
8086
#[serde(default)]
@@ -104,7 +110,7 @@ pub struct TerserCompressorOptions {
104110
#[serde(default)]
105111
pub dead_code: bool,
106112

107-
#[serde(default)]
113+
#[serde(default = "true_by_default")]
108114
pub defaults: bool,
109115

110116
#[serde(default)]
@@ -242,6 +248,67 @@ pub struct TerserCompressorOptions {
242248
pub module: bool,
243249
}
244250

251+
impl Default for TerserCompressorOptions {
252+
fn default() -> Self {
253+
Self {
254+
arguments: Default::default(),
255+
arrows: Default::default(),
256+
booleans: Default::default(),
257+
booleans_as_integers: Default::default(),
258+
collapse_vars: Default::default(),
259+
comparisons: Default::default(),
260+
computed_props: Default::default(),
261+
conditionals: Default::default(),
262+
dead_code: Default::default(),
263+
defaults: true,
264+
directives: Default::default(),
265+
drop_console: Default::default(),
266+
drop_debugger: Default::default(),
267+
ecma: Default::default(),
268+
evaluate: Default::default(),
269+
expression: Default::default(),
270+
global_defs: Default::default(),
271+
hoist_funs: Default::default(),
272+
hoist_props: Default::default(),
273+
hoist_vars: Default::default(),
274+
ie8: Default::default(),
275+
if_return: Default::default(),
276+
inline: Default::default(),
277+
join_vars: Default::default(),
278+
keep_classnames: Default::default(),
279+
keep_fargs: Default::default(),
280+
keep_fnames: Default::default(),
281+
keep_infinity: Default::default(),
282+
loops: Default::default(),
283+
negate_iife: Default::default(),
284+
passes: Default::default(),
285+
properties: Default::default(),
286+
pure_getters: Default::default(),
287+
pure_funcs: Default::default(),
288+
reduce_funcs: Default::default(),
289+
reduce_vars: Default::default(),
290+
sequences: Default::default(),
291+
side_effects: Default::default(),
292+
switches: Default::default(),
293+
top_retain: Default::default(),
294+
toplevel: Default::default(),
295+
typeofs: Default::default(),
296+
unsafe_passes: Default::default(),
297+
unsafe_arrows: Default::default(),
298+
unsafe_comps: Default::default(),
299+
unsafe_function: Default::default(),
300+
unsafe_math: Default::default(),
301+
unsafe_symbols: Default::default(),
302+
unsafe_methods: Default::default(),
303+
unsafe_proto: Default::default(),
304+
unsafe_regexp: Default::default(),
305+
unsafe_undefined: Default::default(),
306+
unused: Default::default(),
307+
module: Default::default(),
308+
}
309+
}
310+
}
311+
245312
fn ecma_default() -> TerserEcmaVersion {
246313
TerserEcmaVersion::Num(5)
247314
}

0 commit comments

Comments
 (0)