mirror of
https://github.com/swc-project/swc.git
synced 2024-12-22 21:21:31 +03:00
feat(config): Make all configuration overridable (#4575)
This commit is contained in:
parent
29811e28ee
commit
7fc9bbccd9
8
.github/workflows/cargo.yml
vendored
8
.github/workflows/cargo.yml
vendored
@ -93,10 +93,14 @@ jobs:
|
|||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
- crate: better_scoped_tls
|
- crate: better_scoped_tls
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
|
- crate: binding_commons
|
||||||
|
os: ubuntu-latest
|
||||||
- crate: binding_core_node
|
- crate: binding_core_node
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
- crate: binding_core_wasm
|
- crate: binding_core_wasm
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
|
- crate: binding_css_node
|
||||||
|
os: ubuntu-latest
|
||||||
- crate: enum_kind
|
- crate: enum_kind
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
- crate: from_variant
|
- crate: from_variant
|
||||||
@ -136,6 +140,10 @@ jobs:
|
|||||||
cargo hack check --feature-powerset --no-dev-deps
|
cargo hack check --feature-powerset --no-dev-deps
|
||||||
- crate: swc_common
|
- crate: swc_common
|
||||||
os: windows-latest
|
os: windows-latest
|
||||||
|
- crate: swc_config
|
||||||
|
os: ubuntu-latest
|
||||||
|
- crate: swc_config_macro
|
||||||
|
os: ubuntu-latest
|
||||||
- crate: swc_css
|
- crate: swc_css
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
- crate: swc_css_ast
|
- crate: swc_css_ast
|
||||||
|
45
Cargo.lock
generated
45
Cargo.lock
generated
@ -60,9 +60,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.56"
|
version = "1.0.57"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27"
|
checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arbitrary"
|
name = "arbitrary"
|
||||||
@ -2553,9 +2553,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.136"
|
version = "1.0.137"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
|
checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
@ -2593,9 +2593,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.136"
|
version = "1.0.137"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
|
checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -2892,12 +2892,14 @@ dependencies = [
|
|||||||
"pathdiff",
|
"pathdiff",
|
||||||
"rayon",
|
"rayon",
|
||||||
"regex",
|
"regex",
|
||||||
|
"rustc-hash",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sourcemap",
|
"sourcemap",
|
||||||
"swc_atoms",
|
"swc_atoms",
|
||||||
"swc_cached",
|
"swc_cached",
|
||||||
"swc_common",
|
"swc_common",
|
||||||
|
"swc_config",
|
||||||
"swc_ecma_ast",
|
"swc_ecma_ast",
|
||||||
"swc_ecma_codegen",
|
"swc_ecma_codegen",
|
||||||
"swc_ecma_ext_transforms",
|
"swc_ecma_ext_transforms",
|
||||||
@ -3051,6 +3053,28 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "swc_config"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"swc_config_macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "swc_config_macro"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"pmutil",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"swc_macros_common",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "swc_css"
|
name = "swc_css"
|
||||||
version = "0.104.2"
|
version = "0.104.2"
|
||||||
@ -3271,6 +3295,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"swc_atoms",
|
"swc_atoms",
|
||||||
"swc_common",
|
"swc_common",
|
||||||
|
"swc_config",
|
||||||
"swc_ecma_ast",
|
"swc_ecma_ast",
|
||||||
"swc_ecma_codegen",
|
"swc_ecma_codegen",
|
||||||
"swc_ecma_parser",
|
"swc_ecma_parser",
|
||||||
@ -3324,6 +3349,7 @@ dependencies = [
|
|||||||
"swc_atoms",
|
"swc_atoms",
|
||||||
"swc_cached",
|
"swc_cached",
|
||||||
"swc_common",
|
"swc_common",
|
||||||
|
"swc_config",
|
||||||
"swc_ecma_ast",
|
"swc_ecma_ast",
|
||||||
"swc_ecma_codegen",
|
"swc_ecma_codegen",
|
||||||
"swc_ecma_parser",
|
"swc_ecma_parser",
|
||||||
@ -3555,6 +3581,7 @@ dependencies = [
|
|||||||
"indexmap",
|
"indexmap",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rayon",
|
"rayon",
|
||||||
|
"rustc-hash",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"swc_atoms",
|
"swc_atoms",
|
||||||
"swc_common",
|
"swc_common",
|
||||||
@ -3878,7 +3905,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "swc_macros_common"
|
name = "swc_macros_common"
|
||||||
version = "0.3.4"
|
version = "0.3.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pmutil",
|
"pmutil",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@ -4053,9 +4080,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.86"
|
version = "1.0.92"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
|
checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -19,7 +19,7 @@ napi = { version = "2", default-features = false, features = [
|
|||||||
"serde-json",
|
"serde-json",
|
||||||
] }
|
] }
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = { version = "1", features = ["unbounded_depth"] }
|
||||||
swc_node_base = { path = "../swc_node_base" }
|
swc_node_base = { path = "../swc_node_base" }
|
||||||
tracing = { version = "0.1.32", features = ["release_max_level_info"] }
|
tracing = { version = "0.1.32", features = ["release_max_level_info"] }
|
||||||
tracing-subscriber = { version = "0.3.9", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.9", features = ["env-filter"] }
|
||||||
|
@ -115,7 +115,7 @@ impl Task for BundleTask {
|
|||||||
.config
|
.config
|
||||||
.options
|
.options
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|v| v.config.minify)
|
.map(|v| v.config.minify.into_bool())
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
||||||
let output = self.swc.print(
|
let output = self.swc.print(
|
||||||
|
@ -43,7 +43,7 @@ impl Task for PrintTask {
|
|||||||
.unwrap_or(SourceMapsConfig::Bool(false)),
|
.unwrap_or(SourceMapsConfig::Bool(false)),
|
||||||
&Default::default(),
|
&Default::default(),
|
||||||
None,
|
None,
|
||||||
options.config.minify,
|
options.config.minify.into_bool(),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.convert_err()
|
.convert_err()
|
||||||
@ -100,7 +100,7 @@ pub fn print_sync(program: String, options: Buffer) -> napi::Result<TransformOut
|
|||||||
.unwrap_or(SourceMapsConfig::Bool(false)),
|
.unwrap_or(SourceMapsConfig::Bool(false)),
|
||||||
&Default::default(),
|
&Default::default(),
|
||||||
None,
|
None,
|
||||||
options.config.minify,
|
options.config.minify.into_bool(),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.convert_err()
|
.convert_err()
|
||||||
|
@ -48,7 +48,7 @@ impl Task for TransformTask {
|
|||||||
|
|
||||||
try_with(
|
try_with(
|
||||||
self.c.cm.clone(),
|
self.c.cm.clone(),
|
||||||
!options.config.error.filename,
|
!options.config.error.filename.into_bool(),
|
||||||
|handler| {
|
|handler| {
|
||||||
self.c.run(|| match &self.input {
|
self.c.run(|| match &self.input {
|
||||||
Input::Program(ref s) => {
|
Input::Program(ref s) => {
|
||||||
@ -130,25 +130,29 @@ pub fn transform_sync(s: String, is_module: bool, opts: Buffer) -> napi::Result<
|
|||||||
options.config.adjust(Path::new(&options.filename));
|
options.config.adjust(Path::new(&options.filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
try_with(c.cm.clone(), !options.config.error.filename, |handler| {
|
try_with(
|
||||||
c.run(|| {
|
c.cm.clone(),
|
||||||
if is_module {
|
!options.config.error.filename.into_bool(),
|
||||||
let program: Program =
|
|handler| {
|
||||||
deserialize_json(s.as_str()).context("failed to deserialize Program")?;
|
c.run(|| {
|
||||||
c.process_js(handler, program, &options)
|
if is_module {
|
||||||
} else {
|
let program: Program =
|
||||||
let fm = c.cm.new_source_file(
|
deserialize_json(s.as_str()).context("failed to deserialize Program")?;
|
||||||
if options.filename.is_empty() {
|
c.process_js(handler, program, &options)
|
||||||
FileName::Anon
|
} else {
|
||||||
} else {
|
let fm = c.cm.new_source_file(
|
||||||
FileName::Real(options.filename.clone().into())
|
if options.filename.is_empty() {
|
||||||
},
|
FileName::Anon
|
||||||
s,
|
} else {
|
||||||
);
|
FileName::Real(options.filename.clone().into())
|
||||||
c.process_js_file(fm, handler, &options)
|
},
|
||||||
}
|
s,
|
||||||
})
|
);
|
||||||
})
|
c.process_js_file(fm, handler, &options)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
)
|
||||||
.convert_err()
|
.convert_err()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,17 +193,21 @@ pub fn transform_file_sync(
|
|||||||
options.config.adjust(Path::new(&options.filename));
|
options.config.adjust(Path::new(&options.filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
try_with(c.cm.clone(), !options.config.error.filename, |handler| {
|
try_with(
|
||||||
c.run(|| {
|
c.cm.clone(),
|
||||||
if is_module {
|
!options.config.error.filename.into_bool(),
|
||||||
let program: Program =
|
|handler| {
|
||||||
deserialize_json(s.as_str()).context("failed to deserialize Program")?;
|
c.run(|| {
|
||||||
c.process_js(handler, program, &options)
|
if is_module {
|
||||||
} else {
|
let program: Program =
|
||||||
let fm = c.cm.load_file(Path::new(&s)).expect("failed to load file");
|
deserialize_json(s.as_str()).context("failed to deserialize Program")?;
|
||||||
c.process_js_file(fm, handler, &options)
|
c.process_js(handler, program, &options)
|
||||||
}
|
} else {
|
||||||
})
|
let fm = c.cm.load_file(Path::new(&s)).expect("failed to load file");
|
||||||
})
|
c.process_js_file(fm, handler, &options)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
)
|
||||||
.convert_err()
|
.convert_err()
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ pub fn print_sync(s: JsValue, opts: JsValue) -> Result<JsValue, JsValue> {
|
|||||||
.unwrap_or(SourceMapsConfig::Bool(false)),
|
.unwrap_or(SourceMapsConfig::Bool(false)),
|
||||||
&Default::default(),
|
&Default::default(),
|
||||||
None,
|
None,
|
||||||
opts.config.minify,
|
opts.config.minify.into(),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.context("failed to print code")?;
|
.context("failed to print code")?;
|
||||||
|
@ -30,7 +30,7 @@ napi-derive = { version = "2", default-features = false, features = [
|
|||||||
node_macro_deps = { path = "../node_macro_deps" }
|
node_macro_deps = { path = "../node_macro_deps" }
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
swc_common = { path = "../swc_common", features = ["perf"] }
|
swc_common = { path = "../swc_common", features = ["perf", "sourcemap"] }
|
||||||
swc_css_ast = { path = "../swc_css_ast" }
|
swc_css_ast = { path = "../swc_css_ast" }
|
||||||
swc_css_codegen = { path = "../swc_css_codegen" }
|
swc_css_codegen = { path = "../swc_css_codegen" }
|
||||||
swc_css_minifier = { path = "../swc_css_minifier" }
|
swc_css_minifier = { path = "../swc_css_minifier" }
|
||||||
|
@ -30,56 +30,58 @@ anyhow = "1"
|
|||||||
base64 = "0.13.0"
|
base64 = "0.13.0"
|
||||||
dashmap = "5.1.0"
|
dashmap = "5.1.0"
|
||||||
either = "1"
|
either = "1"
|
||||||
indexmap = {version = "1", features = ["serde"]}
|
indexmap = { version = "1", features = ["serde"] }
|
||||||
json_comments = "0.2.0"
|
json_comments = "0.2.0"
|
||||||
lru = "0.7.1"
|
lru = "0.7.1"
|
||||||
once_cell = "1.10.0"
|
once_cell = "1.10.0"
|
||||||
parking_lot = "0.12.0"
|
parking_lot = "0.12.0"
|
||||||
pathdiff = "0.2.0"
|
pathdiff = "0.2.0"
|
||||||
regex = "1"
|
regex = "1"
|
||||||
serde = {version = "1", features = ["derive"]}
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
sourcemap = "6"
|
sourcemap = "6"
|
||||||
swc_atoms = {version = "0.2", path = "../swc_atoms"}
|
swc_atoms = { version = "0.2", path = "../swc_atoms" }
|
||||||
swc_cached = {version = "0.1.0", path = "../swc_cached"}
|
swc_cached = { version = "0.1.0", path = "../swc_cached" }
|
||||||
swc_common = {version = "0.17.23", path = "../swc_common", features = [
|
swc_common = { version = "0.17.23", path = "../swc_common", features = [
|
||||||
"sourcemap",
|
"sourcemap",
|
||||||
"concurrent",
|
"concurrent",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
]}
|
] }
|
||||||
swc_ecma_ast = {version = "0.77.0", path = "../swc_ecma_ast"}
|
swc_config = { version = "0.1.0", path = "../swc_config" }
|
||||||
swc_ecma_codegen = {version = "0.106.0", path = "../swc_ecma_codegen"}
|
swc_ecma_ast = { version = "0.77.0", path = "../swc_ecma_ast" }
|
||||||
swc_ecma_ext_transforms = {version = "0.69.0", path = "../swc_ecma_ext_transforms"}
|
swc_ecma_codegen = { version = "0.106.0", path = "../swc_ecma_codegen" }
|
||||||
swc_ecma_lints = {version = "0.38.0", path = "../swc_ecma_lints"}
|
swc_ecma_ext_transforms = { version = "0.69.0", path = "../swc_ecma_ext_transforms" }
|
||||||
swc_ecma_loader = {version = "0.29.0", path = "../swc_ecma_loader", features = [
|
swc_ecma_lints = { version = "0.38.0", path = "../swc_ecma_lints" }
|
||||||
|
swc_ecma_loader = { version = "0.29.0", path = "../swc_ecma_loader", features = [
|
||||||
"cache",
|
"cache",
|
||||||
"node",
|
"node",
|
||||||
"tsc",
|
"tsc",
|
||||||
]}
|
] }
|
||||||
swc_ecma_minifier = {version = "0.110.0", path = "../swc_ecma_minifier"}
|
swc_ecma_minifier = { version = "0.110.0", path = "../swc_ecma_minifier" }
|
||||||
swc_ecma_parser = {version = "0.103.0", path = "../swc_ecma_parser"}
|
swc_ecma_parser = { version = "0.103.0", path = "../swc_ecma_parser" }
|
||||||
swc_ecma_preset_env = {version = "0.125.0", path = "../swc_ecma_preset_env"}
|
swc_ecma_preset_env = { version = "0.125.0", path = "../swc_ecma_preset_env" }
|
||||||
swc_ecma_transforms = {version = "0.150.0", path = "../swc_ecma_transforms", features = [
|
swc_ecma_transforms = { version = "0.150.0", path = "../swc_ecma_transforms", features = [
|
||||||
"compat",
|
"compat",
|
||||||
"module",
|
"module",
|
||||||
"optimization",
|
"optimization",
|
||||||
"proposal",
|
"proposal",
|
||||||
"react",
|
"react",
|
||||||
"typescript",
|
"typescript",
|
||||||
]}
|
] }
|
||||||
swc_ecma_transforms_base = {version = "0.82.0", path = "../swc_ecma_transforms_base"}
|
swc_ecma_transforms_base = { version = "0.82.0", path = "../swc_ecma_transforms_base" }
|
||||||
swc_ecma_transforms_compat = {version = "0.96.0", path = "../swc_ecma_transforms_compat"}
|
swc_ecma_transforms_compat = { version = "0.96.0", path = "../swc_ecma_transforms_compat" }
|
||||||
swc_ecma_transforms_optimization = {version = "0.120.0", path = "../swc_ecma_transforms_optimization"}
|
swc_ecma_transforms_optimization = { version = "0.120.0", path = "../swc_ecma_transforms_optimization" }
|
||||||
swc_ecma_utils = {version = "0.83.0", path = "../swc_ecma_utils"}
|
swc_ecma_utils = { version = "0.83.0", path = "../swc_ecma_utils" }
|
||||||
swc_ecma_visit = {version = "0.63.0", path = "../swc_ecma_visit"}
|
swc_ecma_visit = { version = "0.63.0", path = "../swc_ecma_visit" }
|
||||||
swc_ecmascript = {version = "0.153.0", path = "../swc_ecmascript"}
|
swc_ecmascript = { version = "0.153.0", path = "../swc_ecmascript" }
|
||||||
swc_error_reporters = {version = "0.1.2", path = "../swc_error_reporters"}
|
swc_error_reporters = { version = "0.1.2", path = "../swc_error_reporters" }
|
||||||
swc_node_comments = {version = "0.4.0", path = "../swc_node_comments"}
|
swc_node_comments = { version = "0.4.0", path = "../swc_node_comments" }
|
||||||
swc_plugin_proxy = {version = "0.2.1", path = "../swc_plugin_proxy", optional = true}
|
swc_plugin_proxy = { version = "0.2.1", path = "../swc_plugin_proxy", optional = true }
|
||||||
swc_plugin_runner = {version = "0.54.0", path = "../swc_plugin_runner", optional = true, default-features = false}
|
swc_plugin_runner = { version = "0.54.0", path = "../swc_plugin_runner", optional = true, default-features = false }
|
||||||
swc_timer = {version = "0.5.0", path = "../swc_timer"}
|
swc_timer = { version = "0.5.0", path = "../swc_timer" }
|
||||||
swc_visit = {version = "0.3.0", path = "../swc_visit"}
|
swc_visit = { version = "0.3.0", path = "../swc_visit" }
|
||||||
tracing = "0.1.32"
|
tracing = "0.1.32"
|
||||||
|
rustc-hash = "1.1.0"
|
||||||
|
|
||||||
[dependencies.napi-derive]
|
[dependencies.napi-derive]
|
||||||
default-features = false
|
default-features = false
|
||||||
@ -97,11 +99,11 @@ version = "2.0.0"
|
|||||||
ansi_term = "0.12"
|
ansi_term = "0.12"
|
||||||
criterion = "0.3"
|
criterion = "0.3"
|
||||||
rayon = "1.5.1"
|
rayon = "1.5.1"
|
||||||
swc_ecma_lints = {version = "0.38.0", path = "../swc_ecma_lints", features = [
|
swc_ecma_lints = { version = "0.38.0", path = "../swc_ecma_lints", features = [
|
||||||
"non_critical_lints",
|
"non_critical_lints",
|
||||||
]}
|
] }
|
||||||
swc_node_base = {version = "0.5.0", path = "../swc_node_base"}
|
swc_node_base = { version = "0.5.0", path = "../swc_node_base" }
|
||||||
testing = {version = "0.19.0", path = "../testing"}
|
testing = { version = "0.19.0", path = "../testing" }
|
||||||
walkdir = "2"
|
walkdir = "2"
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
|
@ -4,7 +4,7 @@ extern crate swc_node_base;
|
|||||||
use std::{path::PathBuf, sync::Arc};
|
use std::{path::PathBuf, sync::Arc};
|
||||||
|
|
||||||
use criterion::{black_box, criterion_group, criterion_main, Bencher, Criterion};
|
use criterion::{black_box, criterion_group, criterion_main, Bencher, Criterion};
|
||||||
use swc::{config::JsMinifyOptions, try_with_handler};
|
use swc::{config::JsMinifyOptions, try_with_handler, BoolOrDataConfig};
|
||||||
use swc_common::{FilePathMapping, SourceMap};
|
use swc_common::{FilePathMapping, SourceMap};
|
||||||
|
|
||||||
fn mk() -> swc::Compiler {
|
fn mk() -> swc::Compiler {
|
||||||
@ -35,8 +35,8 @@ fn bench_minify(b: &mut Bencher, filename: &str) {
|
|||||||
fm,
|
fm,
|
||||||
handler,
|
handler,
|
||||||
&JsMinifyOptions {
|
&JsMinifyOptions {
|
||||||
compress: true.into(),
|
compress: BoolOrDataConfig::from_bool(true),
|
||||||
mangle: true.into(),
|
mangle: BoolOrDataConfig::from_bool(true),
|
||||||
format: Default::default(),
|
format: Default::default(),
|
||||||
ecma: Default::default(),
|
ecma: Default::default(),
|
||||||
keep_classnames: Default::default(),
|
keep_classnames: Default::default(),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::{path::Path, sync::Arc};
|
use std::{path::Path, sync::Arc};
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use swc::{self, config::JsMinifyOptions, try_with_handler, HandlerOpts};
|
use swc::{self, config::JsMinifyOptions, try_with_handler, BoolOrDataConfig, HandlerOpts};
|
||||||
use swc_common::SourceMap;
|
use swc_common::SourceMap;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@ -23,8 +23,8 @@ fn main() {
|
|||||||
fm,
|
fm,
|
||||||
handler,
|
handler,
|
||||||
&JsMinifyOptions {
|
&JsMinifyOptions {
|
||||||
compress: true.into(),
|
compress: BoolOrDataConfig::from_bool(true),
|
||||||
mangle: true.into(),
|
mangle: BoolOrDataConfig::from_bool(true),
|
||||||
format: Default::default(),
|
format: Default::default(),
|
||||||
ecma: Default::default(),
|
ecma: Default::default(),
|
||||||
keep_classnames: Default::default(),
|
keep_classnames: Default::default(),
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use std::{cell::RefCell, collections::HashMap, path::PathBuf, rc::Rc, sync::Arc};
|
use std::{cell::RefCell, path::PathBuf, rc::Rc, sync::Arc};
|
||||||
|
|
||||||
use compat::{es2015::regenerator, es2020::export_namespace_from};
|
use compat::{es2015::regenerator, es2020::export_namespace_from};
|
||||||
use either::Either;
|
use either::Either;
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
use swc_atoms::JsWord;
|
use swc_atoms::JsWord;
|
||||||
use swc_common::{
|
use swc_common::{
|
||||||
chain,
|
chain,
|
||||||
@ -21,9 +22,7 @@ use swc_ecma_transforms::{
|
|||||||
};
|
};
|
||||||
use swc_ecma_visit::{as_folder, noop_visit_mut_type, VisitMut};
|
use swc_ecma_visit::{as_folder, noop_visit_mut_type, VisitMut};
|
||||||
|
|
||||||
use crate::config::{
|
use crate::config::{CompiledPaths, GlobalPassOption, JsMinifyOptions, ModuleConfig};
|
||||||
util::BoolOrObject, CompiledPaths, GlobalPassOption, JsMinifyOptions, ModuleConfig,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Builder is used to create a high performance `Compiler`.
|
/// Builder is used to create a high performance `Compiler`.
|
||||||
pub struct PassBuilder<'a, 'b, P: swc_ecma_visit::Fold> {
|
pub struct PassBuilder<'a, 'b, P: swc_ecma_visit::Fold> {
|
||||||
@ -124,7 +123,7 @@ impl<'a, 'b, P: swc_ecma_visit::Fold> PassBuilder<'a, 'b, P> {
|
|||||||
|
|
||||||
pub fn const_modules(
|
pub fn const_modules(
|
||||||
self,
|
self,
|
||||||
globals: HashMap<JsWord, HashMap<JsWord, String>>,
|
globals: FxHashMap<JsWord, FxHashMap<JsWord, String>>,
|
||||||
) -> PassBuilder<'a, 'b, impl swc_ecma_visit::Fold> {
|
) -> PassBuilder<'a, 'b, impl swc_ecma_visit::Fold> {
|
||||||
let cm = self.cm.clone();
|
let cm = self.cm.clone();
|
||||||
self.then(const_modules(cm, globals))
|
self.then(const_modules(cm, globals))
|
||||||
@ -296,7 +295,7 @@ impl<'a, 'b, P: swc_ecma_visit::Fold> PassBuilder<'a, 'b, P> {
|
|||||||
let is_mangler_enabled = self
|
let is_mangler_enabled = self
|
||||||
.minify
|
.minify
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|v| matches!(v.mangle, BoolOrObject::Bool(true) | BoolOrObject::Obj(_)))
|
.map(|v| v.mangle.is_obj() || v.mangle.is_true())
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
||||||
let module_scope = Rc::new(RefCell::new(Scope::default()));
|
let module_scope = Rc::new(RefCell::new(Scope::default()));
|
||||||
@ -351,17 +350,30 @@ impl VisitMut for MinifierPass {
|
|||||||
fn visit_mut_module(&mut self, m: &mut Module) {
|
fn visit_mut_module(&mut self, m: &mut Module) {
|
||||||
if let Some(options) = &self.options {
|
if let Some(options) = &self.options {
|
||||||
let opts = MinifyOptions {
|
let opts = MinifyOptions {
|
||||||
compress: options.compress.clone().into_obj().map(|mut v| {
|
compress: options
|
||||||
if v.const_to_let.is_none() {
|
.compress
|
||||||
v.const_to_let = Some(true);
|
.clone()
|
||||||
}
|
.unwrap_as_option(|default| match default {
|
||||||
if v.toplevel.is_none() {
|
Some(true) => Some(Default::default()),
|
||||||
v.toplevel = Some(TerserTopLevelOptions::Bool(true));
|
_ => None,
|
||||||
}
|
})
|
||||||
|
.map(|mut v| {
|
||||||
|
if v.const_to_let.is_none() {
|
||||||
|
v.const_to_let = Some(true);
|
||||||
|
}
|
||||||
|
if v.toplevel.is_none() {
|
||||||
|
v.toplevel = Some(TerserTopLevelOptions::Bool(true));
|
||||||
|
}
|
||||||
|
|
||||||
v.into_config(self.cm.clone())
|
v.into_config(self.cm.clone())
|
||||||
}),
|
}),
|
||||||
mangle: options.mangle.clone().into_obj(),
|
mangle: options
|
||||||
|
.mangle
|
||||||
|
.clone()
|
||||||
|
.unwrap_as_option(|default| match default {
|
||||||
|
Some(true) => Some(Default::default()),
|
||||||
|
_ => None,
|
||||||
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ use std::{
|
|||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
env, fmt,
|
env, fmt,
|
||||||
hash::BuildHasher,
|
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
rc::Rc as RustRc,
|
rc::Rc as RustRc,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
@ -15,6 +14,7 @@ use dashmap::DashMap;
|
|||||||
use either::Either;
|
use either::Either;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
use serde::{
|
use serde::{
|
||||||
de::{Unexpected, Visitor},
|
de::{Unexpected, Visitor},
|
||||||
Deserialize, Deserializer, Serialize, Serializer,
|
Deserialize, Deserializer, Serialize, Serializer,
|
||||||
@ -28,6 +28,10 @@ use swc_common::{
|
|||||||
errors::Handler,
|
errors::Handler,
|
||||||
FileName, Mark, SourceMap, SyntaxContext,
|
FileName, Mark, SourceMap, SyntaxContext,
|
||||||
};
|
};
|
||||||
|
use swc_config::{
|
||||||
|
config_types::{BoolConfig, BoolOr, BoolOrDataConfig},
|
||||||
|
merge::Merge,
|
||||||
|
};
|
||||||
use swc_ecma_ast::{EsVersion, Expr, Program};
|
use swc_ecma_ast::{EsVersion, Expr, Program};
|
||||||
use swc_ecma_ext_transforms::jest;
|
use swc_ecma_ext_transforms::jest;
|
||||||
use swc_ecma_lints::{
|
use swc_ecma_lints::{
|
||||||
@ -40,7 +44,7 @@ use swc_ecma_loader::{
|
|||||||
};
|
};
|
||||||
use swc_ecma_minifier::option::{
|
use swc_ecma_minifier::option::{
|
||||||
terser::{TerserCompressorOptions, TerserEcmaVersion, TerserTopLevelOptions},
|
terser::{TerserCompressorOptions, TerserEcmaVersion, TerserTopLevelOptions},
|
||||||
MangleOptions, ManglePropertiesOptions,
|
MangleOptions,
|
||||||
};
|
};
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
pub use swc_ecma_parser::JscTarget;
|
pub use swc_ecma_parser::JscTarget;
|
||||||
@ -61,7 +65,6 @@ use swc_ecma_transforms_compat::es2015::regenerator;
|
|||||||
use swc_ecma_transforms_optimization::{inline_globals2, GlobalExprMap};
|
use swc_ecma_transforms_optimization::{inline_globals2, GlobalExprMap};
|
||||||
use swc_ecma_visit::{Fold, VisitMutWith};
|
use swc_ecma_visit::{Fold, VisitMutWith};
|
||||||
|
|
||||||
use self::util::BoolOrObject;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
builder::PassBuilder,
|
builder::PassBuilder,
|
||||||
dropped_comments_preserver::dropped_comments_preserver,
|
dropped_comments_preserver::dropped_comments_preserver,
|
||||||
@ -71,7 +74,6 @@ use crate::{
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
pub mod util;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Copy)]
|
#[derive(Clone, Debug, Copy)]
|
||||||
pub enum IsModule {
|
pub enum IsModule {
|
||||||
@ -269,7 +271,6 @@ impl Options {
|
|||||||
output_path: Option<&Path>,
|
output_path: Option<&Path>,
|
||||||
source_file_name: Option<String>,
|
source_file_name: Option<String>,
|
||||||
handler: &Handler,
|
handler: &Handler,
|
||||||
is_module: IsModule,
|
|
||||||
config: Option<Config>,
|
config: Option<Config>,
|
||||||
comments: Option<&'a SingleThreadedComments>,
|
comments: Option<&'a SingleThreadedComments>,
|
||||||
custom_before_pass: impl FnOnce(&Program) -> P,
|
custom_before_pass: impl FnOnce(&Program) -> P,
|
||||||
@ -277,11 +278,12 @@ impl Options {
|
|||||||
where
|
where
|
||||||
P: 'a + swc_ecma_visit::Fold,
|
P: 'a + swc_ecma_visit::Fold,
|
||||||
{
|
{
|
||||||
let mut config = config.unwrap_or_default();
|
let mut cfg = self.config.clone();
|
||||||
config.merge(&self.config);
|
cfg.merge(config.unwrap_or_default());
|
||||||
|
let is_module = self.is_module;
|
||||||
|
|
||||||
let mut source_maps = self.source_maps.clone();
|
let mut source_maps = self.source_maps.clone();
|
||||||
source_maps.merge(&config.source_maps);
|
source_maps.merge(cfg.source_maps.clone());
|
||||||
|
|
||||||
let JscConfig {
|
let JscConfig {
|
||||||
assumptions,
|
assumptions,
|
||||||
@ -298,7 +300,11 @@ impl Options {
|
|||||||
lints,
|
lints,
|
||||||
preserve_all_comments,
|
preserve_all_comments,
|
||||||
..
|
..
|
||||||
} = config.jsc;
|
} = cfg.jsc;
|
||||||
|
let loose = loose.into_bool();
|
||||||
|
let preserve_all_comments = preserve_all_comments.into_bool();
|
||||||
|
let keep_class_names = keep_class_names.into_bool();
|
||||||
|
let external_helpers = external_helpers.into_bool();
|
||||||
|
|
||||||
let mut assumptions = assumptions.unwrap_or_else(|| {
|
let mut assumptions = assumptions.unwrap_or_else(|| {
|
||||||
if loose {
|
if loose {
|
||||||
@ -338,7 +344,10 @@ impl Options {
|
|||||||
js_minify = js_minify.map(|c| {
|
js_minify = js_minify.map(|c| {
|
||||||
let compress = c
|
let compress = c
|
||||||
.compress
|
.compress
|
||||||
.into_obj()
|
.unwrap_as_option(|default| match default {
|
||||||
|
Some(true) => Some(Default::default()),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
.map(|mut c| {
|
.map(|mut c| {
|
||||||
if c.toplevel.is_none() {
|
if c.toplevel.is_none() {
|
||||||
c.toplevel = Some(TerserTopLevelOptions::Bool(true));
|
c.toplevel = Some(TerserTopLevelOptions::Bool(true));
|
||||||
@ -346,19 +355,22 @@ impl Options {
|
|||||||
|
|
||||||
c
|
c
|
||||||
})
|
})
|
||||||
.map(BoolOrObject::Obj)
|
.map(BoolOrDataConfig::from_obj)
|
||||||
.unwrap_or(BoolOrObject::Bool(false));
|
.unwrap_or_else(|| BoolOrDataConfig::from_bool(false));
|
||||||
|
|
||||||
let mangle = c
|
let mangle = c
|
||||||
.mangle
|
.mangle
|
||||||
.into_obj()
|
.unwrap_as_option(|default| match default {
|
||||||
|
Some(true) => Some(Default::default()),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
.map(|mut c| {
|
.map(|mut c| {
|
||||||
c.top_level = true;
|
c.top_level = true;
|
||||||
|
|
||||||
c
|
c
|
||||||
})
|
})
|
||||||
.map(BoolOrObject::Obj)
|
.map(BoolOrDataConfig::from_obj)
|
||||||
.unwrap_or(BoolOrObject::Bool(false));
|
.unwrap_or_else(|| BoolOrDataConfig::from_bool(false));
|
||||||
|
|
||||||
JsMinifyOptions {
|
JsMinifyOptions {
|
||||||
compress,
|
compress,
|
||||||
@ -371,9 +383,21 @@ impl Options {
|
|||||||
let regenerator = transform.regenerator.clone();
|
let regenerator = transform.regenerator.clone();
|
||||||
|
|
||||||
let preserve_comments = if preserve_all_comments {
|
let preserve_comments = if preserve_all_comments {
|
||||||
Some(BoolOrObject::from(true))
|
BoolOr::Bool(true)
|
||||||
} else {
|
} else {
|
||||||
js_minify.as_ref().map(|v| v.format.comments.clone())
|
js_minify
|
||||||
|
.as_ref()
|
||||||
|
.map(|v| match v.format.comments.clone().into_inner() {
|
||||||
|
Some(v) => v,
|
||||||
|
None => BoolOr::Bool(false),
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
BoolOr::Data(if cfg.minify.into_bool() {
|
||||||
|
JsMinifyCommentOption::PreserveSomeComments
|
||||||
|
} else {
|
||||||
|
JsMinifyCommentOption::PreserveAllComments
|
||||||
|
})
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
if syntax.typescript() {
|
if syntax.typescript() {
|
||||||
@ -397,7 +421,10 @@ impl Options {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let enable_simplifier = optimizer.as_ref().map(|v| v.simplify).unwrap_or_default();
|
let enable_simplifier = optimizer
|
||||||
|
.as_ref()
|
||||||
|
.map(|v| v.simplify.into_bool())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
let optimization = {
|
let optimization = {
|
||||||
if let Some(opts) = optimizer.and_then(|o| o.globals) {
|
if let Some(opts) = optimizer.and_then(|o| o.globals) {
|
||||||
@ -439,18 +466,18 @@ impl Options {
|
|||||||
Some(hygiene::Config { keep_class_names })
|
Some(hygiene::Config { keep_class_names })
|
||||||
})
|
})
|
||||||
.fixer(!self.disable_fixer)
|
.fixer(!self.disable_fixer)
|
||||||
.preset_env(config.env)
|
.preset_env(cfg.env)
|
||||||
.regenerator(regenerator)
|
.regenerator(regenerator)
|
||||||
.finalize(
|
.finalize(
|
||||||
base_url,
|
base_url,
|
||||||
paths.into_iter().collect(),
|
paths.into_iter().collect(),
|
||||||
base,
|
base,
|
||||||
syntax,
|
syntax,
|
||||||
config.module,
|
cfg.module,
|
||||||
comments,
|
comments,
|
||||||
);
|
);
|
||||||
|
|
||||||
let keep_import_assertions = experimental.keep_import_assertions;
|
let keep_import_assertions = experimental.keep_import_assertions.into_bool();
|
||||||
|
|
||||||
// Embedded runtime plugin target, based on assumption we have
|
// Embedded runtime plugin target, based on assumption we have
|
||||||
// 1. filesystem access for the cache
|
// 1. filesystem access for the cache
|
||||||
@ -570,15 +597,15 @@ impl Options {
|
|||||||
|
|
||||||
Ok(BuiltInput {
|
Ok(BuiltInput {
|
||||||
program,
|
program,
|
||||||
minify: config.minify,
|
minify: cfg.minify.into_bool(),
|
||||||
pass,
|
pass,
|
||||||
external_helpers,
|
external_helpers,
|
||||||
syntax,
|
syntax,
|
||||||
target: es_version,
|
target: es_version,
|
||||||
is_module,
|
is_module,
|
||||||
source_maps: source_maps.unwrap_or(SourceMapsConfig::Bool(false)),
|
source_maps: source_maps.unwrap_or(SourceMapsConfig::Bool(false)),
|
||||||
inline_sources_content: config.inline_sources_content,
|
inline_sources_content: cfg.inline_sources_content.into_bool(),
|
||||||
input_source_map: config.input_source_map.clone(),
|
input_source_map: cfg.input_source_map.clone().unwrap_or_default(),
|
||||||
output_path: output_path.map(|v| v.to_path_buf()),
|
output_path: output_path.map(|v| v.to_path_buf()),
|
||||||
source_file_name,
|
source_file_name,
|
||||||
comments: comments.cloned(),
|
comments: comments.cloned(),
|
||||||
@ -648,17 +675,8 @@ impl Default for Rc {
|
|||||||
exclude: Some(FileMatcher::Regex("\\.tsx?$".into())),
|
exclude: Some(FileMatcher::Regex("\\.tsx?$".into())),
|
||||||
jsc: JscConfig {
|
jsc: JscConfig {
|
||||||
syntax: Some(Default::default()),
|
syntax: Some(Default::default()),
|
||||||
transform: None,
|
|
||||||
external_helpers: false,
|
|
||||||
target: Default::default(),
|
|
||||||
loose: false,
|
|
||||||
keep_class_names: false,
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
module: None,
|
|
||||||
minify: false,
|
|
||||||
source_maps: None,
|
|
||||||
input_source_map: InputSourceMap::default(),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
Config {
|
Config {
|
||||||
@ -670,17 +688,8 @@ impl Default for Rc {
|
|||||||
tsx: true,
|
tsx: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})),
|
})),
|
||||||
transform: None,
|
|
||||||
external_helpers: false,
|
|
||||||
target: Default::default(),
|
|
||||||
loose: false,
|
|
||||||
keep_class_names: false,
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
module: None,
|
|
||||||
minify: false,
|
|
||||||
source_maps: None,
|
|
||||||
input_source_map: InputSourceMap::default(),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
Config {
|
Config {
|
||||||
@ -692,17 +701,8 @@ impl Default for Rc {
|
|||||||
tsx: false,
|
tsx: false,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})),
|
})),
|
||||||
transform: None,
|
|
||||||
external_helpers: false,
|
|
||||||
target: Default::default(),
|
|
||||||
loose: false,
|
|
||||||
keep_class_names: false,
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
module: None,
|
|
||||||
minify: false,
|
|
||||||
source_maps: None,
|
|
||||||
input_source_map: InputSourceMap::default(),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
@ -747,7 +747,7 @@ impl Rc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A single object in the `.swcrc` file
|
/// A single object in the `.swcrc` file
|
||||||
#[derive(Debug, Default, Clone, Deserialize)]
|
#[derive(Debug, Default, Clone, Deserialize, Merge)]
|
||||||
#[serde(deny_unknown_fields, rename_all = "camelCase")]
|
#[serde(deny_unknown_fields, rename_all = "camelCase")]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@ -766,17 +766,17 @@ pub struct Config {
|
|||||||
pub module: Option<ModuleConfig>,
|
pub module: Option<ModuleConfig>,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub minify: bool,
|
pub minify: BoolConfig<false>,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub input_source_map: InputSourceMap,
|
pub input_source_map: Option<InputSourceMap>,
|
||||||
|
|
||||||
/// Possible values are: `'inline'`, `true`, `false`.
|
/// Possible values are: `'inline'`, `true`, `false`.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub source_maps: Option<SourceMapsConfig>,
|
pub source_maps: Option<SourceMapsConfig>,
|
||||||
|
|
||||||
#[serde(default = "true_by_default")]
|
#[serde(default)]
|
||||||
pub inline_sources_content: bool,
|
pub inline_sources_content: BoolConfig<true>,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub error: ErrorConfig,
|
pub error: ErrorConfig,
|
||||||
@ -790,10 +790,10 @@ pub struct Config {
|
|||||||
#[serde(deny_unknown_fields, rename_all = "camelCase")]
|
#[serde(deny_unknown_fields, rename_all = "camelCase")]
|
||||||
pub struct JsMinifyOptions {
|
pub struct JsMinifyOptions {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub compress: BoolOrObject<TerserCompressorOptions>,
|
pub compress: BoolOrDataConfig<TerserCompressorOptions>,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub mangle: BoolOrObject<MangleOptions>,
|
pub mangle: BoolOrDataConfig<MangleOptions>,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub format: JsMinifyFormatOptions,
|
pub format: JsMinifyFormatOptions,
|
||||||
@ -817,7 +817,7 @@ pub struct JsMinifyOptions {
|
|||||||
pub toplevel: bool,
|
pub toplevel: bool,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub source_map: BoolOrObject<TerserSourceMapOption>,
|
pub source_map: BoolOrDataConfig<TerserSourceMapOption>,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub output_path: Option<String>,
|
pub output_path: Option<String>,
|
||||||
@ -864,7 +864,7 @@ pub struct JsMinifyFormatOptions {
|
|||||||
pub braces: bool,
|
pub braces: bool,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub comments: BoolOrObject<JsMinifyCommentOption>,
|
pub comments: BoolOrDataConfig<JsMinifyCommentOption>,
|
||||||
|
|
||||||
/// Not implemented yet.
|
/// Not implemented yet.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@ -872,7 +872,7 @@ pub struct JsMinifyFormatOptions {
|
|||||||
|
|
||||||
/// Not implemented yet.
|
/// Not implemented yet.
|
||||||
#[serde(default, alias = "indent_level")]
|
#[serde(default, alias = "indent_level")]
|
||||||
pub indent_level: usize,
|
pub indent_level: Option<usize>,
|
||||||
|
|
||||||
/// Not implemented yet.
|
/// Not implemented yet.
|
||||||
#[serde(default, alias = "indent_start")]
|
#[serde(default, alias = "indent_start")]
|
||||||
@ -892,7 +892,7 @@ pub struct JsMinifyFormatOptions {
|
|||||||
|
|
||||||
/// Not implemented yet.
|
/// Not implemented yet.
|
||||||
#[serde(default, alias = "max_line_len")]
|
#[serde(default, alias = "max_line_len")]
|
||||||
pub max_line_len: BoolOrObject<usize>,
|
pub max_line_len: usize,
|
||||||
|
|
||||||
/// Not implemented yet.
|
/// Not implemented yet.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@ -1054,13 +1054,13 @@ pub struct BuiltInput<P: swc_ecma_visit::Fold> {
|
|||||||
pub source_file_name: Option<String>,
|
pub source_file_name: Option<String>,
|
||||||
|
|
||||||
pub comments: Option<SingleThreadedComments>,
|
pub comments: Option<SingleThreadedComments>,
|
||||||
pub preserve_comments: Option<BoolOrObject<JsMinifyCommentOption>>,
|
pub preserve_comments: BoolOr<JsMinifyCommentOption>,
|
||||||
|
|
||||||
pub inline_sources_content: bool,
|
pub inline_sources_content: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `jsc` in `.swcrc`.
|
/// `jsc` in `.swcrc`.
|
||||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, Serialize, Deserialize, Merge)]
|
||||||
#[serde(deny_unknown_fields, rename_all = "camelCase")]
|
#[serde(deny_unknown_fields, rename_all = "camelCase")]
|
||||||
pub struct JscConfig {
|
pub struct JscConfig {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@ -1073,16 +1073,16 @@ pub struct JscConfig {
|
|||||||
pub transform: Option<TransformConfig>,
|
pub transform: Option<TransformConfig>,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub external_helpers: bool,
|
pub external_helpers: BoolConfig<false>,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub target: Option<EsVersion>,
|
pub target: Option<EsVersion>,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub loose: bool,
|
pub loose: BoolConfig<false>,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub keep_class_names: bool,
|
pub keep_class_names: BoolConfig<false>,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub base_url: PathBuf,
|
pub base_url: PathBuf,
|
||||||
@ -1100,11 +1100,11 @@ pub struct JscConfig {
|
|||||||
pub lints: LintConfig,
|
pub lints: LintConfig,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub preserve_all_comments: bool,
|
pub preserve_all_comments: BoolConfig<false>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `jsc.experimental` in `.swcrc`
|
/// `jsc.experimental` in `.swcrc`
|
||||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, Serialize, Deserialize, Merge)]
|
||||||
#[serde(deny_unknown_fields, rename_all = "camelCase")]
|
#[serde(deny_unknown_fields, rename_all = "camelCase")]
|
||||||
pub struct JscExperimental {
|
pub struct JscExperimental {
|
||||||
/// This requires cargo feature `plugin`.
|
/// This requires cargo feature `plugin`.
|
||||||
@ -1112,7 +1112,7 @@ pub struct JscExperimental {
|
|||||||
pub plugins: Option<Vec<PluginConfig>>,
|
pub plugins: Option<Vec<PluginConfig>>,
|
||||||
/// If true, keeps import assertions in the output.
|
/// If true, keeps import assertions in the output.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub keep_import_assertions: bool,
|
pub keep_import_assertions: BoolConfig<false>,
|
||||||
/// Location where swc may stores its intermediate cache.
|
/// Location where swc may stores its intermediate cache.
|
||||||
/// Currently this is only being used for wasm plugin's bytecache.
|
/// Currently this is only being used for wasm plugin's bytecache.
|
||||||
/// Path should be absolute directory, which will be created if not exist.
|
/// Path should be absolute directory, which will be created if not exist.
|
||||||
@ -1122,19 +1122,6 @@ pub struct JscExperimental {
|
|||||||
pub cache_root: Option<String>,
|
pub cache_root: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Merge for JscExperimental {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
if self.plugins.is_none() {
|
|
||||||
self.plugins = from.plugins.clone();
|
|
||||||
}
|
|
||||||
if self.cache_root.is_none() {
|
|
||||||
self.cache_root = from.cache_root.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
self.keep_import_assertions |= from.keep_import_assertions;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `paths` section of `tsconfig.json`.
|
/// `paths` section of `tsconfig.json`.
|
||||||
pub type Paths = IndexMap<String, Vec<String>, ahash::RandomState>;
|
pub type Paths = IndexMap<String, Vec<String>, ahash::RandomState>;
|
||||||
pub(crate) type CompiledPaths = Vec<(String, Vec<String>)>;
|
pub(crate) type CompiledPaths = Vec<(String, Vec<String>)>;
|
||||||
@ -1296,21 +1283,21 @@ pub struct HiddenTransformConfig {
|
|||||||
pub jest: bool,
|
pub jest: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, Serialize, Deserialize, Merge)]
|
||||||
#[serde(deny_unknown_fields, rename_all = "camelCase")]
|
#[serde(deny_unknown_fields, rename_all = "camelCase")]
|
||||||
pub struct ConstModulesConfig {
|
pub struct ConstModulesConfig {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub globals: HashMap<JsWord, HashMap<JsWord, String>>,
|
pub globals: FxHashMap<JsWord, FxHashMap<JsWord, String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, Serialize, Deserialize, Merge)]
|
||||||
#[serde(deny_unknown_fields, rename_all = "camelCase")]
|
#[serde(deny_unknown_fields, rename_all = "camelCase")]
|
||||||
pub struct OptimizerConfig {
|
pub struct OptimizerConfig {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub globals: Option<GlobalPassOption>,
|
pub globals: Option<GlobalPassOption>,
|
||||||
|
|
||||||
#[serde(default = "true_by_default")]
|
#[serde(default)]
|
||||||
pub simplify: bool,
|
pub simplify: BoolConfig<true>,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub jsonify: Option<JsonifyOption>,
|
pub jsonify: Option<JsonifyOption>,
|
||||||
@ -1327,15 +1314,10 @@ fn default_jsonify_min_cost() -> usize {
|
|||||||
1024
|
1024
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize, Merge)]
|
||||||
#[serde(deny_unknown_fields, rename_all = "camelCase")]
|
#[serde(deny_unknown_fields, rename_all = "camelCase")]
|
||||||
pub struct ErrorConfig {
|
pub struct ErrorConfig {
|
||||||
pub filename: bool,
|
pub filename: BoolConfig<true>,
|
||||||
}
|
|
||||||
impl Default for ErrorConfig {
|
|
||||||
fn default() -> Self {
|
|
||||||
ErrorConfig { filename: true }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||||
@ -1538,284 +1520,6 @@ fn default_env_name() -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Merge {
|
|
||||||
/// Apply overrides from `from`
|
|
||||||
fn merge(&mut self, from: &Self);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Clone> Merge for Option<T>
|
|
||||||
where
|
|
||||||
T: Merge,
|
|
||||||
{
|
|
||||||
fn merge(&mut self, from: &Option<T>) {
|
|
||||||
if let Some(ref from) = *from {
|
|
||||||
match *self {
|
|
||||||
Some(ref mut v) => v.merge(from),
|
|
||||||
None => *self = Some(from.clone()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for Config {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
self.jsc.merge(&from.jsc);
|
|
||||||
self.module.merge(&from.module);
|
|
||||||
self.minify.merge(&from.minify);
|
|
||||||
self.env.merge(&from.env);
|
|
||||||
self.source_maps.merge(&from.source_maps);
|
|
||||||
self.input_source_map.merge(&from.input_source_map);
|
|
||||||
self.inline_sources_content
|
|
||||||
.merge(&from.inline_sources_content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for JsMinifyOptions {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
self.compress.merge(&from.compress);
|
|
||||||
self.mangle.merge(&from.mangle);
|
|
||||||
self.format.merge(&from.format);
|
|
||||||
self.ecma.merge(&from.ecma);
|
|
||||||
self.keep_classnames |= from.keep_classnames;
|
|
||||||
self.keep_fnames |= from.keep_fnames;
|
|
||||||
self.safari10 |= from.safari10;
|
|
||||||
self.toplevel |= from.toplevel;
|
|
||||||
self.inline_sources_content |= from.inline_sources_content;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for TerserCompressorOptions {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
self.defaults |= from.defaults;
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for MangleOptions {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
self.props.merge(&from.props);
|
|
||||||
|
|
||||||
self.top_level |= from.top_level;
|
|
||||||
self.keep_class_names |= from.keep_class_names;
|
|
||||||
self.keep_fn_names |= from.keep_fn_names;
|
|
||||||
self.keep_private_props |= from.keep_private_props;
|
|
||||||
self.safari10 |= from.safari10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for JsMinifyFormatOptions {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
self.comments.merge(&from.comments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for JsMinifyCommentOption {
|
|
||||||
fn merge(&mut self, _: &Self) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for ManglePropertiesOptions {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
self.undeclared |= from.undeclared;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for TerserEcmaVersion {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
*self = from.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for SourceMapsConfig {
|
|
||||||
fn merge(&mut self, _: &Self) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for InputSourceMap {
|
|
||||||
fn merge(&mut self, r: &Self) {
|
|
||||||
if let InputSourceMap::Bool(false) = *self {
|
|
||||||
*self = r.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for swc_ecma_preset_env::Config {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
*self = from.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for JscConfig {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
self.assumptions.merge(&from.assumptions);
|
|
||||||
self.syntax.merge(&from.syntax);
|
|
||||||
self.transform.merge(&from.transform);
|
|
||||||
self.external_helpers.merge(&from.external_helpers);
|
|
||||||
self.target.merge(&from.target);
|
|
||||||
self.loose.merge(&from.loose);
|
|
||||||
self.keep_class_names.merge(&from.keep_class_names);
|
|
||||||
self.paths.merge(&from.paths);
|
|
||||||
self.minify.merge(&from.minify);
|
|
||||||
self.experimental.merge(&from.experimental);
|
|
||||||
self.preserve_all_comments
|
|
||||||
.merge(&from.preserve_all_comments)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<K, V, S> Merge for IndexMap<K, V, S>
|
|
||||||
where
|
|
||||||
K: Clone + Eq + std::hash::Hash,
|
|
||||||
V: Clone,
|
|
||||||
S: Clone + BuildHasher,
|
|
||||||
{
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
if self.is_empty() {
|
|
||||||
*self = (*from).clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<K, V, S> Merge for HashMap<K, V, S>
|
|
||||||
where
|
|
||||||
K: Clone + Eq + std::hash::Hash,
|
|
||||||
V: Clone,
|
|
||||||
S: Clone + BuildHasher,
|
|
||||||
{
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
if self.is_empty() {
|
|
||||||
*self = (*from).clone();
|
|
||||||
} else {
|
|
||||||
for (k, v) in from {
|
|
||||||
self.entry(k.clone()).or_insert_with(|| v.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for EsVersion {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
if *self < *from {
|
|
||||||
*self = *from
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for Option<ModuleConfig> {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
if let Some(ref c2) = *from {
|
|
||||||
*self = Some(c2.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for bool {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
*self |= *from
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for Syntax {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
match (&mut *self, from) {
|
|
||||||
(Syntax::Es(a), Syntax::Es(b)) => {
|
|
||||||
a.merge(b);
|
|
||||||
}
|
|
||||||
(Syntax::Typescript(a), Syntax::Typescript(b)) => {
|
|
||||||
a.merge(b);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
*self = *from;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for swc_ecma_parser::EsConfig {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
self.jsx |= from.jsx;
|
|
||||||
self.fn_bind |= from.fn_bind;
|
|
||||||
self.decorators |= from.decorators;
|
|
||||||
self.decorators_before_export |= from.decorators_before_export;
|
|
||||||
self.export_default_from |= from.export_default_from;
|
|
||||||
self.import_assertions |= from.import_assertions;
|
|
||||||
self.private_in_object |= from.private_in_object;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for swc_ecma_parser::TsConfig {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
self.tsx |= from.tsx;
|
|
||||||
self.decorators |= from.decorators;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for Assumptions {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
self.array_like_is_iterable |= from.array_like_is_iterable;
|
|
||||||
self.constant_reexports |= from.constant_reexports;
|
|
||||||
self.constant_super |= from.constant_super;
|
|
||||||
self.enumerable_module_meta |= from.enumerable_module_meta;
|
|
||||||
self.ignore_function_length |= from.ignore_function_length;
|
|
||||||
self.ignore_function_name |= from.ignore_function_name;
|
|
||||||
self.ignore_to_primitive_hint |= from.ignore_to_primitive_hint;
|
|
||||||
self.iterable_is_array |= from.iterable_is_array;
|
|
||||||
self.mutable_template_object |= from.mutable_template_object;
|
|
||||||
self.no_class_calls |= from.no_class_calls;
|
|
||||||
self.no_document_all |= from.no_document_all;
|
|
||||||
self.no_incomplete_ns_import_detection |= from.no_incomplete_ns_import_detection;
|
|
||||||
self.no_new_arrows |= from.no_new_arrows;
|
|
||||||
self.object_rest_no_symbols |= from.object_rest_no_symbols;
|
|
||||||
self.private_fields_as_properties |= from.private_fields_as_properties;
|
|
||||||
self.pure_getters |= from.pure_getters;
|
|
||||||
self.set_class_methods |= from.set_class_methods;
|
|
||||||
self.set_computed_properties |= from.set_computed_properties;
|
|
||||||
self.set_public_class_fields |= from.set_public_class_fields;
|
|
||||||
self.set_spread_properties |= from.set_spread_properties;
|
|
||||||
self.skip_for_of_iterator_closing |= from.skip_for_of_iterator_closing;
|
|
||||||
self.super_is_callable_constructor |= from.super_is_callable_constructor;
|
|
||||||
self.ts_enum_is_readonly |= from.ts_enum_is_readonly;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for TransformConfig {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
self.optimizer.merge(&from.optimizer);
|
|
||||||
self.const_modules.merge(&from.const_modules);
|
|
||||||
self.react.merge(&from.react);
|
|
||||||
self.hidden.merge(&from.hidden);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for OptimizerConfig {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
self.globals.merge(&from.globals)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for GlobalPassOption {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
*self = from.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for react::Options {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
if *from != react::Options::default() {
|
|
||||||
*self = from.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for ConstModulesConfig {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
*self = from.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Merge for HiddenTransformConfig {
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
self.jest |= from.jest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_resolver(base_url: PathBuf, paths: CompiledPaths) -> Box<SwcImportResolver> {
|
fn build_resolver(base_url: PathBuf, paths: CompiledPaths) -> Box<SwcImportResolver> {
|
||||||
static CACHE: Lazy<DashMap<(PathBuf, CompiledPaths), SwcImportResolver, ahash::RandomState>> =
|
static CACHE: Lazy<DashMap<(PathBuf, CompiledPaths), SwcImportResolver, ahash::RandomState>> =
|
||||||
Lazy::new(Default::default);
|
Lazy::new(Default::default);
|
||||||
|
@ -1,102 +0,0 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use super::Merge;
|
|
||||||
|
|
||||||
/// Note: `{}` (empty object) is treated as `true`.
|
|
||||||
#[derive(Clone, Serialize, Debug)]
|
|
||||||
#[serde(untagged)]
|
|
||||||
pub enum BoolOrObject<T> {
|
|
||||||
Bool(bool),
|
|
||||||
Obj(T),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> From<bool> for BoolOrObject<T> {
|
|
||||||
fn from(v: bool) -> Self {
|
|
||||||
BoolOrObject::Bool(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Default for BoolOrObject<T> {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::Bool(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> BoolOrObject<T> {
|
|
||||||
pub fn into_obj(self) -> Option<T>
|
|
||||||
where
|
|
||||||
T: Default,
|
|
||||||
{
|
|
||||||
match self {
|
|
||||||
BoolOrObject::Bool(true) => Some(Default::default()),
|
|
||||||
BoolOrObject::Bool(false) => None,
|
|
||||||
BoolOrObject::Obj(o) => Some(o),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Merge for BoolOrObject<T>
|
|
||||||
where
|
|
||||||
T: Clone + Merge + Default,
|
|
||||||
{
|
|
||||||
fn merge(&mut self, from: &Self) {
|
|
||||||
match self {
|
|
||||||
BoolOrObject::Bool(l) => match from {
|
|
||||||
BoolOrObject::Bool(r) => {
|
|
||||||
*l |= *r;
|
|
||||||
}
|
|
||||||
BoolOrObject::Obj(_) => *self = from.clone(),
|
|
||||||
},
|
|
||||||
BoolOrObject::Obj(o) => match from {
|
|
||||||
BoolOrObject::Bool(r) => {
|
|
||||||
if *r {
|
|
||||||
o.merge(&Default::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BoolOrObject::Obj(r) => o.merge(r),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, T> Deserialize<'de> for BoolOrObject<T>
|
|
||||||
where
|
|
||||||
T: Deserialize<'de>,
|
|
||||||
{
|
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: serde::Deserializer<'de>,
|
|
||||||
{
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
#[serde(untagged)]
|
|
||||||
enum Deser<T> {
|
|
||||||
Bool(bool),
|
|
||||||
Obj(T),
|
|
||||||
EmptyObject(EmptyStruct),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
#[serde(deny_unknown_fields)]
|
|
||||||
struct EmptyStruct {}
|
|
||||||
|
|
||||||
let content = swc_common::private::serde::de::Content::deserialize(deserializer)?;
|
|
||||||
|
|
||||||
let deserializer =
|
|
||||||
swc_common::private::serde::de::ContentRefDeserializer::<D::Error>::new(&content);
|
|
||||||
|
|
||||||
let res = Deser::deserialize(deserializer);
|
|
||||||
|
|
||||||
match res {
|
|
||||||
Ok(v) => Ok(match v {
|
|
||||||
Deser::Bool(v) => BoolOrObject::Bool(v),
|
|
||||||
Deser::Obj(v) => BoolOrObject::Obj(v),
|
|
||||||
Deser::EmptyObject(_) => BoolOrObject::Bool(true),
|
|
||||||
}),
|
|
||||||
Err(..) => {
|
|
||||||
let d =
|
|
||||||
swc_common::private::serde::de::ContentDeserializer::<D::Error>::new(content);
|
|
||||||
Ok(BoolOrObject::Obj(T::deserialize(d)?))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -120,8 +120,8 @@ use std::{
|
|||||||
|
|
||||||
use anyhow::{bail, Context, Error};
|
use anyhow::{bail, Context, Error};
|
||||||
use atoms::JsWord;
|
use atoms::JsWord;
|
||||||
use common::{collections::AHashMap, comments::SingleThreadedComments, errors::HANDLER, Span};
|
use common::{collections::AHashMap, comments::SingleThreadedComments, errors::HANDLER};
|
||||||
use config::{util::BoolOrObject, IsModule, JsMinifyCommentOption, JsMinifyOptions};
|
use config::{IsModule, JsMinifyCommentOption, JsMinifyOptions};
|
||||||
use json_comments::StripComments;
|
use json_comments::StripComments;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
@ -135,6 +135,8 @@ use swc_common::{
|
|||||||
sync::Lrc,
|
sync::Lrc,
|
||||||
BytePos, FileName, Globals, Mark, SourceFile, SourceMap, Spanned, GLOBALS,
|
BytePos, FileName, Globals, Mark, SourceFile, SourceMap, Spanned, GLOBALS,
|
||||||
};
|
};
|
||||||
|
pub use swc_config::config_types::{BoolConfig, BoolOr, BoolOrDataConfig};
|
||||||
|
use swc_config::merge::Merge;
|
||||||
use swc_ecma_ast::{EsVersion, Ident, Program};
|
use swc_ecma_ast::{EsVersion, Ident, Program};
|
||||||
use swc_ecma_codegen::{self, text_writer::WriteJs, Emitter, Node};
|
use swc_ecma_codegen::{self, text_writer::WriteJs, Emitter, Node};
|
||||||
use swc_ecma_loader::resolvers::{
|
use swc_ecma_loader::resolvers::{
|
||||||
@ -159,7 +161,7 @@ use swc_timer::timer;
|
|||||||
|
|
||||||
pub use crate::builder::PassBuilder;
|
pub use crate::builder::PassBuilder;
|
||||||
use crate::config::{
|
use crate::config::{
|
||||||
BuiltInput, Config, ConfigFile, InputSourceMap, Merge, Options, Rc, RootMode, SourceMapsConfig,
|
BuiltInput, Config, ConfigFile, InputSourceMap, Options, Rc, RootMode, SourceMapsConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod builder;
|
mod builder;
|
||||||
@ -584,74 +586,14 @@ impl SourceMapGenConfig for SwcSourceMapConfig<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn minify_global_comments(
|
pub(crate) fn minify_file_comments(
|
||||||
comments: &SwcComments,
|
|
||||||
span: Span,
|
|
||||||
minify: bool,
|
|
||||||
preserve_comments: Option<BoolOrObject<JsMinifyCommentOption>>,
|
|
||||||
) {
|
|
||||||
let preserve_comments = preserve_comments.unwrap_or({
|
|
||||||
if minify {
|
|
||||||
BoolOrObject::Obj(JsMinifyCommentOption::PreserveSomeComments)
|
|
||||||
} else {
|
|
||||||
BoolOrObject::Obj(JsMinifyCommentOption::PreserveAllComments)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
match preserve_comments {
|
|
||||||
BoolOrObject::Bool(true)
|
|
||||||
| BoolOrObject::Obj(JsMinifyCommentOption::PreserveAllComments) => {}
|
|
||||||
|
|
||||||
BoolOrObject::Obj(JsMinifyCommentOption::PreserveSomeComments) => {
|
|
||||||
let preserve_excl = |pos: &BytePos, vc: &mut Vec<Comment>| -> bool {
|
|
||||||
if *pos < span.lo || *pos >= span.hi {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Preserve license comments.
|
|
||||||
if vc.iter().any(|c| c.text.contains("@license")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
vc.retain(|c: &Comment| c.text.starts_with('!'));
|
|
||||||
!vc.is_empty()
|
|
||||||
};
|
|
||||||
comments.leading.retain(preserve_excl);
|
|
||||||
comments.trailing.retain(preserve_excl);
|
|
||||||
}
|
|
||||||
|
|
||||||
BoolOrObject::Bool(false) => {
|
|
||||||
let remove_all_in_range = |pos: &BytePos, _: &mut Vec<Comment>| -> bool {
|
|
||||||
if *pos < span.lo || *pos >= span.hi {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
};
|
|
||||||
comments.leading.retain(remove_all_in_range);
|
|
||||||
comments.trailing.retain(remove_all_in_range);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn minify_file_comments(
|
|
||||||
comments: &SingleThreadedComments,
|
comments: &SingleThreadedComments,
|
||||||
minify: bool,
|
preserve_comments: BoolOr<JsMinifyCommentOption>,
|
||||||
preserve_comments: Option<BoolOrObject<JsMinifyCommentOption>>,
|
|
||||||
) {
|
) {
|
||||||
let preserve_comments = preserve_comments.unwrap_or({
|
|
||||||
if minify {
|
|
||||||
BoolOrObject::Obj(JsMinifyCommentOption::PreserveSomeComments)
|
|
||||||
} else {
|
|
||||||
BoolOrObject::Obj(JsMinifyCommentOption::PreserveAllComments)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
match preserve_comments {
|
match preserve_comments {
|
||||||
BoolOrObject::Bool(true)
|
BoolOr::Bool(true) | BoolOr::Data(JsMinifyCommentOption::PreserveAllComments) => {}
|
||||||
| BoolOrObject::Obj(JsMinifyCommentOption::PreserveAllComments) => {}
|
|
||||||
|
|
||||||
BoolOrObject::Obj(JsMinifyCommentOption::PreserveSomeComments) => {
|
BoolOr::Data(JsMinifyCommentOption::PreserveSomeComments) => {
|
||||||
let preserve_excl = |_: &BytePos, vc: &mut Vec<Comment>| -> bool {
|
let preserve_excl = |_: &BytePos, vc: &mut Vec<Comment>| -> bool {
|
||||||
// Preserve license comments.
|
// Preserve license comments.
|
||||||
if vc.iter().any(|c| c.text.contains("@license")) {
|
if vc.iter().any(|c| c.text.contains("@license")) {
|
||||||
@ -667,7 +609,7 @@ pub fn minify_file_comments(
|
|||||||
t.retain(preserve_excl);
|
t.retain(preserve_excl);
|
||||||
}
|
}
|
||||||
|
|
||||||
BoolOrObject::Bool(false) => {
|
BoolOr::Bool(false) => {
|
||||||
let (mut l, mut t) = comments.borrow_all_mut();
|
let (mut l, mut t) = comments.borrow_all_mut();
|
||||||
l.clear();
|
l.clear();
|
||||||
t.clear();
|
t.clear();
|
||||||
@ -725,7 +667,7 @@ impl Compiler {
|
|||||||
.context("failed to process config file")?;
|
.context("failed to process config file")?;
|
||||||
|
|
||||||
if let Some(config_file) = config_file {
|
if let Some(config_file) = config_file {
|
||||||
config.merge(&config_file.into_config(Some(path))?)
|
config.merge(config_file.into_config(Some(path))?)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(c) = &mut config {
|
if let Some(c) = &mut config {
|
||||||
@ -831,7 +773,6 @@ impl Compiler {
|
|||||||
opts.output_path.as_deref(),
|
opts.output_path.as_deref(),
|
||||||
opts.source_file_name.clone(),
|
opts.source_file_name.clone(),
|
||||||
handler,
|
handler,
|
||||||
opts.is_module,
|
|
||||||
Some(config),
|
Some(config),
|
||||||
comments,
|
comments,
|
||||||
before_pass,
|
before_pass,
|
||||||
@ -963,10 +904,10 @@ impl Compiler {
|
|||||||
|
|
||||||
let target = opts.ecma.clone().into();
|
let target = opts.ecma.clone().into();
|
||||||
|
|
||||||
let (source_map, orig) = match &opts.source_map {
|
let (source_map, orig) = opts
|
||||||
BoolOrObject::Bool(false) => (SourceMapsConfig::Bool(false), None),
|
.source_map
|
||||||
BoolOrObject::Bool(true) => (SourceMapsConfig::Bool(true), None),
|
.as_ref()
|
||||||
BoolOrObject::Obj(obj) => {
|
.map(|obj| -> Result<_, Error> {
|
||||||
let orig = obj
|
let orig = obj
|
||||||
.content
|
.content
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@ -975,17 +916,32 @@ impl Compiler {
|
|||||||
Some(v) => Some(v?),
|
Some(v) => Some(v?),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
(SourceMapsConfig::Bool(true), orig)
|
Ok((SourceMapsConfig::Bool(true), orig))
|
||||||
}
|
})
|
||||||
};
|
.unwrap_as_option(|v| {
|
||||||
|
Some(Ok(match v {
|
||||||
|
Some(true) => (SourceMapsConfig::Bool(true), None),
|
||||||
|
_ => (SourceMapsConfig::Bool(false), None),
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
.unwrap()?;
|
||||||
|
|
||||||
let mut min_opts = MinifyOptions {
|
let mut min_opts = MinifyOptions {
|
||||||
compress: opts
|
compress: opts
|
||||||
.compress
|
.compress
|
||||||
.clone()
|
.clone()
|
||||||
.into_obj()
|
.unwrap_as_option(|default| match default {
|
||||||
|
Some(true) | None => Some(Default::default()),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
.map(|v| v.into_config(self.cm.clone())),
|
.map(|v| v.into_config(self.cm.clone())),
|
||||||
mangle: opts.mangle.clone().into_obj(),
|
mangle: opts
|
||||||
|
.mangle
|
||||||
|
.clone()
|
||||||
|
.unwrap_as_option(|default| match default {
|
||||||
|
Some(true) | None => Some(Default::default()),
|
||||||
|
_ => None,
|
||||||
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1065,7 +1021,13 @@ impl Compiler {
|
|||||||
module.fold_with(&mut fixer(Some(&comments as &dyn Comments)))
|
module.fold_with(&mut fixer(Some(&comments as &dyn Comments)))
|
||||||
});
|
});
|
||||||
|
|
||||||
minify_file_comments(&comments, true, Some(opts.format.comments.clone()));
|
let preserve_comments = opts
|
||||||
|
.format
|
||||||
|
.comments
|
||||||
|
.clone()
|
||||||
|
.into_inner()
|
||||||
|
.unwrap_or(BoolOr::Data(JsMinifyCommentOption::PreserveSomeComments));
|
||||||
|
minify_file_comments(&comments, preserve_comments);
|
||||||
|
|
||||||
self.print(
|
self.print(
|
||||||
&module,
|
&module,
|
||||||
@ -1135,7 +1097,7 @@ impl Compiler {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if let Some(comments) = &config.comments {
|
if let Some(comments) = &config.comments {
|
||||||
minify_file_comments(comments, config.minify, config.preserve_comments);
|
minify_file_comments(comments, config.preserve_comments);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.print(
|
self.print(
|
||||||
|
@ -8,7 +8,7 @@ use std::{
|
|||||||
use anyhow::{bail, Context, Error};
|
use anyhow::{bail, Context, Error};
|
||||||
use swc::{
|
use swc::{
|
||||||
config::{Config, JsMinifyOptions, JscConfig, ModuleConfig, Options, SourceMapsConfig},
|
config::{Config, JsMinifyOptions, JscConfig, ModuleConfig, Options, SourceMapsConfig},
|
||||||
try_with_handler, Compiler, HandlerOpts,
|
try_with_handler, BoolOrDataConfig, Compiler, HandlerOpts,
|
||||||
};
|
};
|
||||||
use swc_common::{errors::ColorConfig, SourceMap};
|
use swc_common::{errors::ColorConfig, SourceMap};
|
||||||
use swc_ecma_ast::EsVersion;
|
use swc_ecma_ast::EsVersion;
|
||||||
@ -84,12 +84,12 @@ fn create_matrix(entry: &Path) -> Vec<Options> {
|
|||||||
jsc: JscConfig {
|
jsc: JscConfig {
|
||||||
syntax: Some(syntax),
|
syntax: Some(syntax),
|
||||||
transform: None,
|
transform: None,
|
||||||
external_helpers,
|
external_helpers: external_helpers.into(),
|
||||||
target: Some(target),
|
target: Some(target),
|
||||||
minify: if minify {
|
minify: if minify {
|
||||||
Some(JsMinifyOptions {
|
Some(JsMinifyOptions {
|
||||||
compress: true.into(),
|
compress: BoolOrDataConfig::from_bool(true),
|
||||||
mangle: true.into(),
|
mangle: BoolOrDataConfig::from_bool(true),
|
||||||
format: Default::default(),
|
format: Default::default(),
|
||||||
ecma: Default::default(),
|
ecma: Default::default(),
|
||||||
keep_classnames: Default::default(),
|
keep_classnames: Default::default(),
|
||||||
@ -107,7 +107,7 @@ fn create_matrix(entry: &Path) -> Vec<Options> {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
module: Some(ModuleConfig::CommonJs(Default::default())),
|
module: Some(ModuleConfig::CommonJs(Default::default())),
|
||||||
minify,
|
minify: minify.into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
source_maps: if source_map {
|
source_maps: if source_map {
|
||||||
|
@ -9,7 +9,7 @@ use swc::{
|
|||||||
BuiltInput, Config, IsModule, JscConfig, ModuleConfig, Options, SourceMapsConfig,
|
BuiltInput, Config, IsModule, JscConfig, ModuleConfig, Options, SourceMapsConfig,
|
||||||
TransformConfig,
|
TransformConfig,
|
||||||
},
|
},
|
||||||
minify_file_comments, Compiler, TransformOutput,
|
Compiler, TransformOutput,
|
||||||
};
|
};
|
||||||
use swc_common::{
|
use swc_common::{
|
||||||
chain,
|
chain,
|
||||||
@ -772,8 +772,6 @@ fn should_visit() {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
minify_file_comments(&comments, config.minify, config.preserve_comments);
|
|
||||||
|
|
||||||
Ok(c.print(
|
Ok(c.print(
|
||||||
&program,
|
&program,
|
||||||
None,
|
None,
|
||||||
@ -831,7 +829,7 @@ fn tests(input_dir: PathBuf) {
|
|||||||
output_path: Some(output.join(entry.file_name())),
|
output_path: Some(output.join(entry.file_name())),
|
||||||
config: Config {
|
config: Config {
|
||||||
jsc: JscConfig {
|
jsc: JscConfig {
|
||||||
external_helpers: true,
|
external_helpers: true.into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -139,23 +139,23 @@ fn shopify_2_same_opt() {
|
|||||||
no_early_errors: false,
|
no_early_errors: false,
|
||||||
})),
|
})),
|
||||||
transform: None,
|
transform: None,
|
||||||
external_helpers: false,
|
external_helpers: false.into(),
|
||||||
target: Some(EsVersion::Es5),
|
target: Some(EsVersion::Es5),
|
||||||
loose: false,
|
loose: false.into(),
|
||||||
keep_class_names: false,
|
keep_class_names: false.into(),
|
||||||
base_url: Default::default(),
|
base_url: Default::default(),
|
||||||
paths: Default::default(),
|
paths: Default::default(),
|
||||||
minify: None,
|
minify: None,
|
||||||
experimental: Default::default(),
|
experimental: Default::default(),
|
||||||
lints: Default::default(),
|
lints: Default::default(),
|
||||||
assumptions: Default::default(),
|
assumptions: Default::default(),
|
||||||
preserve_all_comments: false,
|
preserve_all_comments: false.into(),
|
||||||
},
|
},
|
||||||
module: None,
|
module: None,
|
||||||
minify: false,
|
minify: false.into(),
|
||||||
input_source_map: InputSourceMap::Bool(false),
|
input_source_map: Some(InputSourceMap::Bool(false)),
|
||||||
source_maps: None,
|
source_maps: None,
|
||||||
inline_sources_content: false,
|
inline_sources_content: false.into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
skip_helper_injection: false,
|
skip_helper_injection: false,
|
||||||
@ -218,10 +218,10 @@ fn shopify_3_reduce_defaults() {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
module: None,
|
module: None,
|
||||||
minify: false,
|
minify: false.into(),
|
||||||
input_source_map: InputSourceMap::Bool(false),
|
input_source_map: InputSourceMap::Bool(false).into(),
|
||||||
source_maps: None,
|
source_maps: None,
|
||||||
inline_sources_content: false,
|
inline_sources_content: false.into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
cwd: "/Users/kdy1/projects/example-swcify".into(),
|
cwd: "/Users/kdy1/projects/example-swcify".into(),
|
||||||
|
@ -30,7 +30,7 @@ fn file(f: &str) -> Result<(), StdErr> {
|
|||||||
&handler,
|
&handler,
|
||||||
&Options {
|
&Options {
|
||||||
config: Config {
|
config: Config {
|
||||||
inline_sources_content: true,
|
inline_sources_content: true.into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
swcrc: true,
|
swcrc: true,
|
||||||
@ -85,7 +85,7 @@ fn inline(f: &str) -> Result<(), StdErr> {
|
|||||||
&handler,
|
&handler,
|
||||||
&Options {
|
&Options {
|
||||||
config: Config {
|
config: Config {
|
||||||
inline_sources_content: true,
|
inline_sources_content: true.into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
swcrc: true,
|
swcrc: true,
|
||||||
|
@ -137,9 +137,9 @@ fn compile(input: &Path, output: &Path, opts: Options) {
|
|||||||
tsx: input.to_string_lossy().ends_with(".tsx"),
|
tsx: input.to_string_lossy().ends_with(".tsx"),
|
||||||
decorators: true,
|
decorators: true,
|
||||||
dts: false,
|
dts: false,
|
||||||
no_early_errors: true,
|
no_early_errors: false,
|
||||||
})),
|
})),
|
||||||
external_helpers: true,
|
external_helpers: true.into(),
|
||||||
..opts.config.jsc
|
..opts.config.jsc
|
||||||
},
|
},
|
||||||
source_maps: Some(SourceMapsConfig::Bool(
|
source_maps: Some(SourceMapsConfig::Bool(
|
||||||
|
16
crates/swc_config/Cargo.toml
Normal file
16
crates/swc_config/Cargo.toml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
[package]
|
||||||
|
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
|
||||||
|
description = "Types for configuring swc"
|
||||||
|
documentation = "https://rustdoc.swc.rs/swc_config/"
|
||||||
|
edition = "2021"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
name = "swc_config"
|
||||||
|
repository = "https://github.com/swc-project/swc.git"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow = "1"
|
||||||
|
indexmap = "1"
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
serde_json = "1"
|
||||||
|
swc_config_macro = { version = "0.1.0", path = "../swc_config_macro" }
|
51
crates/swc_config/src/config_types/bool_config.rs
Normal file
51
crates/swc_config/src/config_types/bool_config.rs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::merge::Merge;
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
|
||||||
|
)]
|
||||||
|
pub struct BoolConfig<const DEFAULT: bool>(#[serde(default)] Option<bool>);
|
||||||
|
|
||||||
|
impl<const DEFAULT: bool> BoolConfig<DEFAULT> {
|
||||||
|
#[inline]
|
||||||
|
pub fn new(value: Option<bool>) -> Self {
|
||||||
|
Self(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn into_bool(self) -> bool {
|
||||||
|
self.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const DEFAULT: bool> From<BoolConfig<DEFAULT>> for bool {
|
||||||
|
#[inline]
|
||||||
|
fn from(v: BoolConfig<DEFAULT>) -> Self {
|
||||||
|
match v.0 {
|
||||||
|
Some(v) => v,
|
||||||
|
_ => DEFAULT,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const DEFAULT: bool> From<Option<bool>> for BoolConfig<DEFAULT> {
|
||||||
|
#[inline]
|
||||||
|
fn from(v: Option<bool>) -> Self {
|
||||||
|
Self(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const DEFAULT: bool> From<bool> for BoolConfig<DEFAULT> {
|
||||||
|
#[inline]
|
||||||
|
fn from(v: bool) -> Self {
|
||||||
|
Self(Some(v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const DEFAULT: bool> Merge for BoolConfig<DEFAULT> {
|
||||||
|
#[inline]
|
||||||
|
fn merge(&mut self, other: Self) {
|
||||||
|
self.0.merge(other.0);
|
||||||
|
}
|
||||||
|
}
|
140
crates/swc_config/src/config_types/bool_or_data.rs
Normal file
140
crates/swc_config/src/config_types/bool_or_data.rs
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::merge::Merge;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||||
|
pub struct BoolOrDataConfig<T>(#[serde(default)] Option<BoolOr<T>>);
|
||||||
|
|
||||||
|
impl<T> BoolOrDataConfig<T> {
|
||||||
|
pub fn from_bool(v: bool) -> Self {
|
||||||
|
Self(Some(BoolOr::Bool(v)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_obj(v: T) -> Self {
|
||||||
|
v.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_ref(&self) -> BoolOrDataConfig<&T> {
|
||||||
|
match &self.0 {
|
||||||
|
Some(BoolOr::Data(v)) => BoolOrDataConfig::from_obj(v),
|
||||||
|
Some(BoolOr::Bool(b)) => BoolOrDataConfig::from_bool(*b),
|
||||||
|
None => BoolOrDataConfig::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn or<F>(self, default: F) -> Self
|
||||||
|
where
|
||||||
|
F: FnOnce() -> Self,
|
||||||
|
{
|
||||||
|
match self.0 {
|
||||||
|
Some(..) => self,
|
||||||
|
None => default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unwrap_as_option<F>(self, default: F) -> Option<T>
|
||||||
|
where
|
||||||
|
F: FnOnce(Option<bool>) -> Option<T>,
|
||||||
|
{
|
||||||
|
match self.0 {
|
||||||
|
Some(BoolOr::Data(v)) => Some(v),
|
||||||
|
Some(BoolOr::Bool(b)) => default(Some(b)),
|
||||||
|
None => default(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn map<F, N>(self, op: F) -> BoolOrDataConfig<N>
|
||||||
|
where
|
||||||
|
F: FnOnce(T) -> N,
|
||||||
|
{
|
||||||
|
match self.0 {
|
||||||
|
Some(BoolOr::Data(v)) => BoolOrDataConfig::from_obj(op(v)),
|
||||||
|
Some(BoolOr::Bool(b)) => BoolOrDataConfig::from_bool(b),
|
||||||
|
None => BoolOrDataConfig::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_true(&self) -> bool {
|
||||||
|
matches!(self.0, Some(BoolOr::Bool(true)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_false(&self) -> bool {
|
||||||
|
matches!(self.0, Some(BoolOr::Bool(false)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_obj(&self) -> bool {
|
||||||
|
matches!(self.0, Some(BoolOr::Data(_)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_inner(self) -> Option<BoolOr<T>> {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<T> for BoolOrDataConfig<T> {
|
||||||
|
fn from(v: T) -> Self {
|
||||||
|
Self(Some(BoolOr::Data(v)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Default for BoolOrDataConfig<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self(Default::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Merge for BoolOrDataConfig<T> {
|
||||||
|
#[inline]
|
||||||
|
fn merge(&mut self, other: Self) {
|
||||||
|
self.0.merge(other.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum BoolOr<T> {
|
||||||
|
Bool(bool),
|
||||||
|
Data(T),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, T> Deserialize<'de> for BoolOr<T>
|
||||||
|
where
|
||||||
|
T: Deserialize<'de>,
|
||||||
|
{
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
enum Deser<T> {
|
||||||
|
Bool(bool),
|
||||||
|
Obj(T),
|
||||||
|
EmptyObject(EmptyStruct),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
struct EmptyStruct {}
|
||||||
|
|
||||||
|
use serde::__private::de;
|
||||||
|
|
||||||
|
let content = de::Content::deserialize(deserializer)?;
|
||||||
|
|
||||||
|
let deserializer = de::ContentRefDeserializer::<D::Error>::new(&content);
|
||||||
|
|
||||||
|
let res = Deser::deserialize(deserializer);
|
||||||
|
|
||||||
|
match res {
|
||||||
|
Ok(v) => Ok(match v {
|
||||||
|
Deser::Bool(v) => BoolOr::Bool(v),
|
||||||
|
Deser::Obj(v) => BoolOr::Data(v),
|
||||||
|
Deser::EmptyObject(_) => BoolOr::Bool(true),
|
||||||
|
}),
|
||||||
|
Err(..) => {
|
||||||
|
let d = de::ContentDeserializer::<D::Error>::new(content);
|
||||||
|
Ok(BoolOr::Data(T::deserialize(d)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
crates/swc_config/src/config_types/mod.rs
Normal file
7
crates/swc_config/src/config_types/mod.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
pub use self::{
|
||||||
|
bool_config::BoolConfig,
|
||||||
|
bool_or_data::{BoolOr, BoolOrDataConfig},
|
||||||
|
};
|
||||||
|
|
||||||
|
mod bool_config;
|
||||||
|
mod bool_or_data;
|
4
crates/swc_config/src/lib.rs
Normal file
4
crates/swc_config/src/lib.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#[macro_use]
|
||||||
|
mod macros;
|
||||||
|
pub mod config_types;
|
||||||
|
pub mod merge;
|
1
crates/swc_config/src/macros.rs
Normal file
1
crates/swc_config/src/macros.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
83
crates/swc_config/src/merge.rs
Normal file
83
crates/swc_config/src/merge.rs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
use std::{collections::HashMap, path::PathBuf};
|
||||||
|
|
||||||
|
use indexmap::IndexMap;
|
||||||
|
pub use swc_config_macro::Merge;
|
||||||
|
|
||||||
|
/// Deriavable trait for overrding configurations.
|
||||||
|
///
|
||||||
|
/// Typically, correct implementation of this trait for a struct is calling
|
||||||
|
/// merge for all fields, and `#[derive(Merge)]` will do it for you.
|
||||||
|
pub trait Merge: Sized {
|
||||||
|
/// `self` has higher priority.
|
||||||
|
fn merge(&mut self, other: Self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modifies `self` iff `self` is [None]
|
||||||
|
impl<T> Merge for Option<T> {
|
||||||
|
#[inline]
|
||||||
|
fn merge(&mut self, other: Self) {
|
||||||
|
if self.is_none() {
|
||||||
|
*self = other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Merge for Box<T>
|
||||||
|
where
|
||||||
|
T: Merge,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn merge(&mut self, other: Self) {
|
||||||
|
(**self).merge(*other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modifies `self` iff `self` is empty.
|
||||||
|
impl<T> Merge for Vec<T> {
|
||||||
|
#[inline]
|
||||||
|
fn merge(&mut self, other: Self) {
|
||||||
|
if self.is_empty() {
|
||||||
|
*self = other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modifies `self` iff `self` is empty.
|
||||||
|
impl<K, V, S> Merge for HashMap<K, V, S> {
|
||||||
|
#[inline]
|
||||||
|
fn merge(&mut self, other: Self) {
|
||||||
|
if self.is_empty() {
|
||||||
|
*self = other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modifies `self` iff `self` is empty.
|
||||||
|
impl<K, V, S> Merge for IndexMap<K, V, S> {
|
||||||
|
#[inline]
|
||||||
|
fn merge(&mut self, other: Self) {
|
||||||
|
if self.is_empty() {
|
||||||
|
*self = other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modifies `self` iff `self` is empty.
|
||||||
|
impl Merge for String {
|
||||||
|
#[inline]
|
||||||
|
fn merge(&mut self, other: Self) {
|
||||||
|
if self.is_empty() {
|
||||||
|
*self = other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modifies `self` iff `self` is empty.
|
||||||
|
impl Merge for PathBuf {
|
||||||
|
#[inline]
|
||||||
|
fn merge(&mut self, other: Self) {
|
||||||
|
if self.as_os_str().is_empty() {
|
||||||
|
*self = other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
crates/swc_config/tests/config_types.rs
Normal file
29
crates/swc_config/tests/config_types.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
use serde_json::Value;
|
||||||
|
use swc_config::config_types::BoolConfig;
|
||||||
|
|
||||||
|
fn bool_config(v: Value) -> BoolConfig<false> {
|
||||||
|
serde_json::from_value(v).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bool_config_serde() {
|
||||||
|
assert_eq!(bool_config(Value::Null), BoolConfig::new(None));
|
||||||
|
|
||||||
|
assert_eq!(bool_config(Value::Bool(true)), BoolConfig::new(Some(true)));
|
||||||
|
assert_eq!(
|
||||||
|
bool_config(Value::Bool(false)),
|
||||||
|
BoolConfig::new(Some(false))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bool_config_default() {
|
||||||
|
assert_eq!(
|
||||||
|
BoolConfig::<false>::default(),
|
||||||
|
BoolConfig::<false>::new(None)
|
||||||
|
);
|
||||||
|
assert_eq!(BoolConfig::<true>::default(), BoolConfig::<true>::new(None));
|
||||||
|
|
||||||
|
assert!(!BoolConfig::<false>::default().into_bool());
|
||||||
|
assert!(BoolConfig::<true>::default().into_bool());
|
||||||
|
}
|
24
crates/swc_config/tests/derive_merge.rs
Normal file
24
crates/swc_config/tests/derive_merge.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
use swc_config::merge::Merge;
|
||||||
|
|
||||||
|
#[derive(Merge)]
|
||||||
|
struct Fields {
|
||||||
|
a: Option<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fields() {
|
||||||
|
let mut fields = Fields { a: None };
|
||||||
|
fields.merge(Fields { a: Some(()) });
|
||||||
|
|
||||||
|
assert_eq!(fields.a, Some(()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Merge)]
|
||||||
|
struct Tuple(Option<()>);
|
||||||
|
#[test]
|
||||||
|
fn test_tuple() {
|
||||||
|
let mut tuple = Tuple(None);
|
||||||
|
tuple.merge(Tuple(Some(())));
|
||||||
|
|
||||||
|
assert_eq!(tuple.0, Some(()));
|
||||||
|
}
|
19
crates/swc_config_macro/Cargo.toml
Normal file
19
crates/swc_config_macro/Cargo.toml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
[package]
|
||||||
|
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
|
||||||
|
description = "Macros to prevent mistakes"
|
||||||
|
documentation = "https://rustdoc.swc.rs/swc_config_macro/"
|
||||||
|
edition = "2021"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
name = "swc_config_macro"
|
||||||
|
repository = "https://github.com/swc-project/swc.git"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
pmutil = "0.5.3"
|
||||||
|
proc-macro2 = "1"
|
||||||
|
quote = "1"
|
||||||
|
swc_macros_common = { version = "0.3.5", path = "../swc_macros_common" }
|
||||||
|
syn = "1"
|
10
crates/swc_config_macro/src/lib.rs
Normal file
10
crates/swc_config_macro/src/lib.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
extern crate proc_macro;
|
||||||
|
|
||||||
|
mod merge;
|
||||||
|
|
||||||
|
#[proc_macro_derive(Merge)]
|
||||||
|
pub fn derive_merge(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
|
let input = syn::parse(input).expect("failed to parse input as DeriveInput");
|
||||||
|
|
||||||
|
self::merge::expand(input).into()
|
||||||
|
}
|
64
crates/swc_config_macro/src/merge.rs
Normal file
64
crates/swc_config_macro/src/merge.rs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
use pmutil::{q, SpanExt};
|
||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::ToTokens;
|
||||||
|
use swc_macros_common::{access_field, join_stmts};
|
||||||
|
use syn::{DeriveInput, Expr, Field, Fields, Stmt};
|
||||||
|
|
||||||
|
pub fn expand(input: DeriveInput) -> TokenStream {
|
||||||
|
match &input.data {
|
||||||
|
syn::Data::Struct(s) => {
|
||||||
|
let body = call_merge_for_fields(&q!({ self }), &s.fields);
|
||||||
|
let body = join_stmts(&body);
|
||||||
|
|
||||||
|
q!(
|
||||||
|
Vars {
|
||||||
|
Type: &input.ident,
|
||||||
|
body
|
||||||
|
},
|
||||||
|
{
|
||||||
|
#[automatically_derived]
|
||||||
|
impl swc_config::merge::Merge for Type {
|
||||||
|
fn merge(&mut self, _other: Self) {
|
||||||
|
body
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
syn::Data::Enum(_) => unimplemented!("derive(Merge) does not support an enum"),
|
||||||
|
syn::Data::Union(_) => unimplemented!("derive(Merge) does not support a union"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call_merge_for_fields(obj: &dyn ToTokens, fields: &Fields) -> Vec<Stmt> {
|
||||||
|
fn call_merge(obj: &dyn ToTokens, idx: usize, f: &Field) -> Expr {
|
||||||
|
let r = q!({ _other });
|
||||||
|
q!(
|
||||||
|
Vars {
|
||||||
|
l: access_field(obj, idx, f),
|
||||||
|
r: access_field(&r, idx, f),
|
||||||
|
},
|
||||||
|
{ swc_config::merge::Merge::merge(&mut l, r) }
|
||||||
|
)
|
||||||
|
.parse()
|
||||||
|
}
|
||||||
|
|
||||||
|
match fields {
|
||||||
|
Fields::Named(fs) => fs
|
||||||
|
.named
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(idx, f)| call_merge(obj, idx, f))
|
||||||
|
.map(|expr| Stmt::Semi(expr, fs.brace_token.span.as_token()))
|
||||||
|
.collect(),
|
||||||
|
Fields::Unnamed(fs) => fs
|
||||||
|
.unnamed
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(idx, f)| call_merge(obj, idx, f))
|
||||||
|
.map(|expr| Stmt::Semi(expr, fs.paren_token.span.as_token()))
|
||||||
|
.collect(),
|
||||||
|
Fields::Unit => unimplemented!("derive(Merge) does not support a unit struct"),
|
||||||
|
}
|
||||||
|
}
|
@ -24,6 +24,7 @@ swc_atoms = { version = "0.2.9", path = "../swc_atoms" }
|
|||||||
swc_common = { version = "0.17.23", path = "../swc_common", features = [
|
swc_common = { version = "0.17.23", path = "../swc_common", features = [
|
||||||
"concurrent",
|
"concurrent",
|
||||||
] }
|
] }
|
||||||
|
swc_config = { version = "0.1.0", path = "../swc_config" }
|
||||||
swc_ecma_ast = { version = "0.77.0", path = "../swc_ecma_ast" }
|
swc_ecma_ast = { version = "0.77.0", path = "../swc_ecma_ast" }
|
||||||
swc_ecma_utils = { version = "0.83.0", path = "../swc_ecma_utils" }
|
swc_ecma_utils = { version = "0.83.0", path = "../swc_ecma_utils" }
|
||||||
swc_ecma_visit = { version = "0.63.0", path = "../swc_ecma_visit" }
|
swc_ecma_visit = { version = "0.63.0", path = "../swc_ecma_visit" }
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use swc_config::merge::Merge;
|
||||||
|
|
||||||
#[cfg(feature = "non_critical_lints")]
|
#[cfg(feature = "non_critical_lints")]
|
||||||
use crate::rules::non_critical_lints::{
|
use crate::rules::non_critical_lints::{
|
||||||
@ -32,11 +33,12 @@ impl Default for LintRuleReaction {
|
|||||||
enum LintRuleLevel {
|
enum LintRuleLevel {
|
||||||
Str(LintRuleReaction),
|
Str(LintRuleReaction),
|
||||||
Number(u8),
|
Number(u8),
|
||||||
|
Unspecified,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for LintRuleLevel {
|
impl Default for LintRuleLevel {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::Str(LintRuleReaction::Off)
|
Self::Unspecified
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,6 +51,7 @@ impl From<LintRuleLevel> for LintRuleReaction {
|
|||||||
2 => LintRuleReaction::Error,
|
2 => LintRuleReaction::Error,
|
||||||
_ => LintRuleReaction::Off,
|
_ => LintRuleReaction::Off,
|
||||||
},
|
},
|
||||||
|
LintRuleLevel::Unspecified => LintRuleReaction::Off,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,7 +72,19 @@ impl<T: Debug + Clone + Serialize + Default> RuleConfig<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
impl<T> Merge for RuleConfig<T>
|
||||||
|
where
|
||||||
|
T: Debug + Clone + Serialize + Default,
|
||||||
|
{
|
||||||
|
fn merge(&mut self, other: Self) {
|
||||||
|
if let LintRuleLevel::Unspecified = self.0 {
|
||||||
|
self.0 = other.0;
|
||||||
|
self.1 = other.1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, Merge)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub struct LintConfig {
|
pub struct LintConfig {
|
||||||
|
@ -37,6 +37,7 @@ serde_json = "1.0.61"
|
|||||||
swc_atoms = { version = "0.2", path = "../swc_atoms" }
|
swc_atoms = { version = "0.2", path = "../swc_atoms" }
|
||||||
swc_cached = { version = "0.1.0", path = "../swc_cached" }
|
swc_cached = { version = "0.1.0", path = "../swc_cached" }
|
||||||
swc_common = { version = "0.17.23", path = "../swc_common" }
|
swc_common = { version = "0.17.23", path = "../swc_common" }
|
||||||
|
swc_config = { version = "0.1.0", path = "../swc_config" }
|
||||||
swc_ecma_ast = { version = "0.77.0", path = "../swc_ecma_ast" }
|
swc_ecma_ast = { version = "0.77.0", path = "../swc_ecma_ast" }
|
||||||
swc_ecma_codegen = { version = "0.106.0", path = "../swc_ecma_codegen" }
|
swc_ecma_codegen = { version = "0.106.0", path = "../swc_ecma_codegen" }
|
||||||
swc_ecma_parser = { version = "0.103.0", path = "../swc_ecma_parser" }
|
swc_ecma_parser = { version = "0.103.0", path = "../swc_ecma_parser" }
|
||||||
|
@ -2,6 +2,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use swc_atoms::JsWord;
|
use swc_atoms::JsWord;
|
||||||
use swc_cached::regex::CachedRegex;
|
use swc_cached::regex::CachedRegex;
|
||||||
use swc_common::{collections::AHashMap, Mark};
|
use swc_common::{collections::AHashMap, Mark};
|
||||||
|
use swc_config::merge::Merge;
|
||||||
use swc_ecma_ast::{EsVersion, Expr};
|
use swc_ecma_ast::{EsVersion, Expr};
|
||||||
|
|
||||||
pub mod terser;
|
pub mod terser;
|
||||||
@ -68,13 +69,13 @@ pub struct MangleOptions {
|
|||||||
pub reserved: Vec<JsWord>,
|
pub reserved: Vec<JsWord>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, Merge)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct ManglePropertiesOptions {
|
pub struct ManglePropertiesOptions {
|
||||||
#[serde(default, alias = "reserved")]
|
#[serde(default, alias = "reserved")]
|
||||||
pub reserved: Vec<JsWord>,
|
pub reserved: Vec<JsWord>,
|
||||||
#[serde(default, alias = "undeclared")]
|
#[serde(default, alias = "undeclared")]
|
||||||
pub undeclared: bool,
|
pub undeclared: Option<bool>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub regex: Option<CachedRegex>,
|
pub regex: Option<CachedRegex>,
|
||||||
}
|
}
|
||||||
|
@ -75,9 +75,7 @@ fn compressed(compressed_file: PathBuf) {
|
|||||||
&MinifyOptions {
|
&MinifyOptions {
|
||||||
mangle: Some(MangleOptions {
|
mangle: Some(MangleOptions {
|
||||||
props: Some(ManglePropertiesOptions {
|
props: Some(ManglePropertiesOptions {
|
||||||
reserved: Default::default(),
|
..Default::default()
|
||||||
undeclared: false,
|
|
||||||
regex: Default::default(),
|
|
||||||
}),
|
}),
|
||||||
top_level: true,
|
top_level: true,
|
||||||
keep_class_names: false,
|
keep_class_names: false,
|
||||||
|
@ -21,23 +21,24 @@ 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 }
|
||||||
|
rustc-hash = "1.1.0"
|
||||||
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.77.0", path = "../swc_ecma_ast"}
|
swc_ecma_ast = { version = "0.77.0", path = "../swc_ecma_ast" }
|
||||||
swc_ecma_parser = {version = "0.103.0", path = "../swc_ecma_parser"}
|
swc_ecma_parser = { version = "0.103.0", path = "../swc_ecma_parser" }
|
||||||
swc_ecma_transforms_base = {version = "0.82.0", path = "../swc_ecma_transforms_base"}
|
swc_ecma_transforms_base = { version = "0.82.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.83.0", path = "../swc_ecma_utils"}
|
swc_ecma_utils = { version = "0.83.0", path = "../swc_ecma_utils" }
|
||||||
swc_ecma_visit = {version = "0.63.0", path = "../swc_ecma_visit"}
|
swc_ecma_visit = { version = "0.63.0", path = "../swc_ecma_visit" }
|
||||||
tracing = "0.1.32"
|
tracing = "0.1.32"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
swc_ecma_transforms_compat = {version = "0.96.0", path = "../swc_ecma_transforms_compat"}
|
swc_ecma_transforms_compat = { version = "0.96.0", path = "../swc_ecma_transforms_compat" }
|
||||||
swc_ecma_transforms_module = {version = "0.109.0", path = "../swc_ecma_transforms_module"}
|
swc_ecma_transforms_module = { version = "0.109.0", path = "../swc_ecma_transforms_module" }
|
||||||
swc_ecma_transforms_proposal = {version = "0.104.0", path = "../swc_ecma_transforms_proposal"}
|
swc_ecma_transforms_proposal = { version = "0.104.0", path = "../swc_ecma_transforms_proposal" }
|
||||||
swc_ecma_transforms_react = {version = "0.111.0", path = "../swc_ecma_transforms_react"}
|
swc_ecma_transforms_react = { version = "0.111.0", path = "../swc_ecma_transforms_react" }
|
||||||
swc_ecma_transforms_testing = {version = "0.84.0", path = "../swc_ecma_transforms_testing"}
|
swc_ecma_transforms_testing = { version = "0.84.0", path = "../swc_ecma_transforms_testing" }
|
||||||
swc_ecma_transforms_typescript = {version = "0.114.0", path = "../swc_ecma_transforms_typescript"}
|
swc_ecma_transforms_typescript = { version = "0.114.0", path = "../swc_ecma_transforms_typescript" }
|
||||||
testing = {version = "0.19.0", path = "../testing"}
|
testing = { version = "0.19.0", path = "../testing" }
|
||||||
|
@ -2,6 +2,7 @@ use std::{collections::HashMap, sync::Arc};
|
|||||||
|
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
use swc_atoms::JsWord;
|
use swc_atoms::JsWord;
|
||||||
use swc_common::{errors::HANDLER, sync::Lrc, util::move_map::MoveMap, FileName, SourceMap};
|
use swc_common::{errors::HANDLER, sync::Lrc, util::move_map::MoveMap, FileName, SourceMap};
|
||||||
use swc_ecma_ast::*;
|
use swc_ecma_ast::*;
|
||||||
@ -11,7 +12,7 @@ use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
|
|||||||
|
|
||||||
pub fn const_modules(
|
pub fn const_modules(
|
||||||
cm: Lrc<SourceMap>,
|
cm: Lrc<SourceMap>,
|
||||||
globals: HashMap<JsWord, HashMap<JsWord, String>>,
|
globals: FxHashMap<JsWord, FxHashMap<JsWord, String>>,
|
||||||
) -> impl Fold {
|
) -> impl Fold {
|
||||||
ConstModules {
|
ConstModules {
|
||||||
globals: globals
|
globals: globals
|
||||||
|
@ -6,7 +6,7 @@ edition = "2021"
|
|||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
name = "swc_macros_common"
|
name = "swc_macros_common"
|
||||||
repository = "https://github.com/swc-project/swc.git"
|
repository = "https://github.com/swc-project/swc.git"
|
||||||
version = "0.3.4"
|
version = "0.3.5"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
bench = false
|
bench = false
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
|
|
||||||
use pmutil::synom_ext::FromSpan;
|
|
||||||
#[cfg(procmacro2_semver_exempt)]
|
#[cfg(procmacro2_semver_exempt)]
|
||||||
use pmutil::SpanExt;
|
use pmutil::SpanExt;
|
||||||
|
use pmutil::{synom_ext::FromSpan, Quote, SpanExt};
|
||||||
use proc_macro2::Span;
|
use proc_macro2::Span;
|
||||||
|
use quote::ToTokens;
|
||||||
use syn::*;
|
use syn::*;
|
||||||
|
|
||||||
pub mod binder;
|
pub mod binder;
|
||||||
@ -78,6 +79,32 @@ pub fn doc_str(attr: &Attribute) -> Option<String> {
|
|||||||
Some(parse_tts(attr))
|
Some(parse_tts(attr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn access_field(obj: &dyn ToTokens, idx: usize, f: &Field) -> Expr {
|
||||||
|
Expr::Field(ExprField {
|
||||||
|
attrs: Default::default(),
|
||||||
|
base: syn::parse2(obj.to_token_stream())
|
||||||
|
.expect("swc_macros_common::access_field: failed to parse object"),
|
||||||
|
dot_token: Span::call_site().as_token(),
|
||||||
|
member: match &f.ident {
|
||||||
|
Some(id) => Member::Named(id.clone()),
|
||||||
|
_ => Member::Unnamed(Index {
|
||||||
|
index: idx as _,
|
||||||
|
span: Span::call_site(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn join_stmts(stmts: &[Stmt]) -> Quote {
|
||||||
|
let mut q = Quote::new_call_site();
|
||||||
|
|
||||||
|
for s in stmts {
|
||||||
|
q.push_tokens(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
q
|
||||||
|
}
|
||||||
|
|
||||||
/// fail! is a panic! with location reporting.
|
/// fail! is a panic! with location reporting.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! fail {
|
macro_rules! fail {
|
||||||
|
@ -202,12 +202,12 @@ impl SwcLoader {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
external_helpers: true,
|
external_helpers: true.into(),
|
||||||
..c.jsc.clone()
|
..c.jsc.clone()
|
||||||
},
|
},
|
||||||
module: None,
|
module: None,
|
||||||
minify: false,
|
minify: false.into(),
|
||||||
input_source_map: InputSourceMap::Bool(false),
|
input_source_map: InputSourceMap::Bool(false).into(),
|
||||||
..c.clone()
|
..c.clone()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -6,9 +6,7 @@ it("should compress", async () => {
|
|||||||
console.log(foo)
|
console.log(foo)
|
||||||
`);
|
`);
|
||||||
|
|
||||||
expect(code).toMatchInlineSnapshot(
|
expect(code).toMatchInlineSnapshot(`"import a from\\"@src/app\\";console.log(a)"`);
|
||||||
`"import foo from\\"@src/app\\";console.log(foo)"`
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should accept object", async () => {
|
it("should accept object", async () => {
|
||||||
@ -20,9 +18,7 @@ it("should accept object", async () => {
|
|||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(code).toMatchInlineSnapshot(
|
expect(code).toMatchInlineSnapshot(`"import a from\\"@src/app\\";console.log(a)"`);
|
||||||
`"import foo from\\"@src/app\\";console.log(foo)"`
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should accept { mangle = true }", async () => {
|
it("should accept { mangle = true }", async () => {
|
||||||
|
@ -176,18 +176,16 @@ it("should respect `error.filename = false`", async () => {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should merge parser config", async () => {
|
it("should support overring `jsc.externalHelpers` using js api", async () => {
|
||||||
const filename = path.resolve(
|
const filename = path.resolve(
|
||||||
__dirname + "/../../tests/issue-2546/input.ts"
|
__dirname + "/../../tests/issue-3834/input.js"
|
||||||
);
|
);
|
||||||
|
|
||||||
const { code } = await swc.transformFile(filename, {
|
const { code } = await swc.transformFile(filename, {
|
||||||
jsc: {
|
jsc: {
|
||||||
parser: {
|
externalHelpers: false,
|
||||||
syntax: "typescript",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(code).not.toBeFalsy()
|
expect(code).toContain('function _classCallCheck')
|
||||||
});
|
});
|
4
node-swc/src/binding.d.ts
vendored
4
node-swc/src/binding.d.ts
vendored
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
export interface TransformOutput {
|
export interface TransformOutput {
|
||||||
code: string
|
code: string
|
||||||
map?: string | undefined | null
|
map?: string
|
||||||
}
|
}
|
||||||
export function bundle(confItems: Buffer, signal?: AbortSignal | undefined | null): Promise<{ [index: string]: { code: string, map?: string } }>
|
export function bundle(confItems: Buffer, signal?: AbortSignal | undefined | null): Promise<{ [index: string]: { code: string, map?: string } }>
|
||||||
export function minify(code: Buffer, opts: Buffer, signal?: AbortSignal | undefined | null): Promise<TransformOutput>
|
export function minify(code: Buffer, opts: Buffer, signal?: AbortSignal | undefined | null): Promise<TransformOutput>
|
||||||
@ -25,7 +25,7 @@ export function initCustomTraceSubscriber(traceOutFilePath?: string | undefined
|
|||||||
/** Hack for `Type Generation` */
|
/** Hack for `Type Generation` */
|
||||||
export interface TransformOutput {
|
export interface TransformOutput {
|
||||||
code: string
|
code: string
|
||||||
map?: string | undefined | null
|
map?: string
|
||||||
}
|
}
|
||||||
export type JsCompiler = Compiler
|
export type JsCompiler = Compiler
|
||||||
export class Compiler {
|
export class Compiler {
|
||||||
|
8
node-swc/tests/issue-3834/.swcrc
Normal file
8
node-swc/tests/issue-3834/.swcrc
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"jsc": {
|
||||||
|
"externalHelpers": true
|
||||||
|
},
|
||||||
|
"module": {
|
||||||
|
"type": "commonjs"
|
||||||
|
}
|
||||||
|
}
|
4
node-swc/tests/issue-3834/input.js
Normal file
4
node-swc/tests/issue-3834/input.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
|
||||||
|
export default class MyClass {
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user