diff --git a/Cargo.lock b/Cargo.lock index d6faea1685bc..53a6e179fdac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2104,7 +2104,7 @@ checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" [[package]] name = "swc" -version = "0.41.0" +version = "0.41.1" dependencies = [ "ahash", "anyhow", @@ -2351,7 +2351,7 @@ dependencies = [ [[package]] name = "swc_ecma_minifier" -version = "0.21.0" +version = "0.21.1" dependencies = [ "ansi_term 0.12.1", "anyhow", @@ -2768,7 +2768,7 @@ dependencies = [ [[package]] name = "swc_visit" -version = "0.2.5" +version = "0.2.6" dependencies = [ "either", "swc_visit_macros", @@ -3056,7 +3056,7 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasm" -version = "1.2.77" +version = "1.2.78" dependencies = [ "anyhow", "console_error_panic_hook", diff --git a/Cargo.toml b/Cargo.toml index 8deb0570dd5a..869b28457919 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,18 +9,23 @@ edition = "2018" license = "Apache-2.0/MIT" name = "swc" repository = "https://github.com/swc-project/swc.git" -version = "0.41.0" +version = "0.41.1" [lib] name = "swc" +[features] +default = ["es3"] +# You can disable this feautre to reduce binary size. +es3 = [] + [dependencies] ahash = "0.7.2" -fxhash = "0.2.1" anyhow = "1" base64 = "0.13.0" dashmap = "4.0.2" either = "1" +fxhash = "0.2.1" log = {version = "0.4", features = ["release_max_level_info"]} lru = "0.6.1" once_cell = "1" diff --git a/ecmascript/minifier/Cargo.toml b/ecmascript/minifier/Cargo.toml index f7c6e0011816..fd4e61ce6f1a 100644 --- a/ecmascript/minifier/Cargo.toml +++ b/ecmascript/minifier/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs", "src/lists/*.json"] license = "Apache-2.0/MIT" name = "swc_ecma_minifier" repository = "https://github.com/swc-project/swc.git" -version = "0.21.0" +version = "0.21.1" [features] debug = [] diff --git a/ecmascript/minifier/src/lib.rs b/ecmascript/minifier/src/lib.rs index b24ed3a120e5..3c523c40a02e 100644 --- a/ecmascript/minifier/src/lib.rs +++ b/ecmascript/minifier/src/lib.rs @@ -12,7 +12,7 @@ //! them something other. Don't call methods like `visit_mut_script` nor //! `visit_mut_module_items`. -pub use crate::pass::hygiene::optimize_hygiene; +pub use crate::pass::hygiene::{hygiene_optimizer, optimize_hygiene}; use crate::{ compress::compressor, marks::Marks, @@ -20,12 +20,11 @@ use crate::{ option::{ExtraOptions, MinifyOptions}, pass::{ compute_char_freq::compute_char_freq, expand_names::name_expander, global_defs, - hygiene::hygiene_optimizer, mangle_names::name_mangler, mangle_props::mangle_properties, + mangle_names::name_mangler, mangle_props::mangle_properties, precompress::precompress_optimizer, }, util::now, }; -use analyzer::analyze; use pass::postcompress::postcompress_optimizer; use std::time::Instant; use swc_common::{comments::Comments, sync::Lrc, SourceMap, GLOBALS}; @@ -153,8 +152,7 @@ pub fn optimize( } { - let data = analyze(&m, None); - m.visit_mut_with(&mut hygiene_optimizer(data, extra.top_level_mark)); + m.visit_mut_with(&mut hygiene_optimizer(extra.top_level_mark)); } if let Some(ref mut t) = timings { diff --git a/ecmascript/minifier/src/pass/hygiene/mod.rs b/ecmascript/minifier/src/pass/hygiene/mod.rs index 196037cc3ceb..d1ba6bbb3af7 100644 --- a/ecmascript/minifier/src/pass/hygiene/mod.rs +++ b/ecmascript/minifier/src/pass/hygiene/mod.rs @@ -7,7 +7,7 @@ use std::time::Instant; use swc_common::{Mark, SyntaxContext, DUMMY_SP}; use swc_ecma_ast::*; use swc_ecma_utils::ident::IdentLike; -use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith, VisitWith}; +use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith, VisitWith}; mod analyzer; @@ -15,22 +15,18 @@ mod analyzer; /// /// Requires [swc_common::GLOBALS]. pub fn optimize_hygiene(m: &mut Module, top_level_mark: Mark) { - let data = analyze(&*m, None); - m.visit_mut_with(&mut hygiene_optimizer(data, top_level_mark)) + m.visit_mut_with(&mut hygiene_optimizer(top_level_mark)) } /// Create a hygiene optimizer. /// /// Hygiene optimizer removes span hygiene without renaming if it's ok to do so. -pub(crate) fn hygiene_optimizer( - data: ProgramData, - top_level_mark: Mark, -) -> impl 'static + VisitMut { - Optimizer { - data, +pub fn hygiene_optimizer(top_level_mark: Mark) -> impl 'static + VisitMut + Fold { + as_folder(Optimizer { + data: Default::default(), hygiene: Default::default(), top_level_mark, - } + }) } struct Optimizer { @@ -70,6 +66,38 @@ impl VisitMut for Optimizer { log::info!("hygiene: Analyzing span hygiene"); let start = now(); + self.data = analyze(&*n, None); + + let mut analyzer = HygieneAnalyzer { + data: &self.data, + hygiene: Default::default(), + top_level_mark: self.top_level_mark, + cur_scope: None, + }; + n.visit_with(&Invalid { span: DUMMY_SP }, &mut analyzer); + self.hygiene = analyzer.hygiene; + + if let Some(start) = start { + let end = Instant::now(); + log::info!("hygiene: Span hygiene analysis took {:?}", end - start); + } + let start = now(); + + log::info!("hygiene: Optimizing span hygiene"); + n.visit_mut_children_with(self); + + if let Some(start) = start { + let end = Instant::now(); + log::info!("hygiene: Span hygiene optimiation took {:?}", end - start); + } + } + + fn visit_mut_script(&mut self, n: &mut Script) { + log::info!("hygiene: Analyzing span hygiene"); + let start = now(); + + self.data = analyze(&*n, None); + let mut analyzer = HygieneAnalyzer { data: &self.data, hygiene: Default::default(), diff --git a/ecmascript/minifier/src/pass/mangle_names/mod.rs b/ecmascript/minifier/src/pass/mangle_names/mod.rs index 8d9ffc3e3999..7df6bcd183c0 100644 --- a/ecmascript/minifier/src/pass/mangle_names/mod.rs +++ b/ecmascript/minifier/src/pass/mangle_names/mod.rs @@ -167,8 +167,16 @@ impl VisitMut for Mangler { fn visit_mut_member_expr(&mut self, n: &mut MemberExpr) { n.obj.visit_mut_with(self); + if n.computed { n.prop.visit_mut_with(self); + } else { + match &*n.prop { + Expr::PrivateName(..) => { + n.prop.visit_mut_with(self); + } + _ => {} + } } } diff --git a/ecmascript/minifier/src/pass/mangle_props.rs b/ecmascript/minifier/src/pass/mangle_props.rs index 69a5ee37c97f..42474e89e8dc 100644 --- a/ecmascript/minifier/src/pass/mangle_props.rs +++ b/ecmascript/minifier/src/pass/mangle_props.rs @@ -12,7 +12,7 @@ use swc_ecma_ast::{ StrKind, }; use swc_ecma_utils::ident::IdentLike; -use swc_ecma_visit::{VisitMut, VisitMutWith}; +use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith}; pub static JS_ENVIRONMENT_PROPS: Lazy> = Lazy::new(|| { let domprops: Vec = serde_json::from_str(include_str!("../lists/domprops.json")) @@ -130,28 +130,6 @@ pub struct PropertyCollector<'a> { } impl VisitMut for PropertyCollector<'_> { - fn visit_mut_prop_name(&mut self, name: &mut PropName) { - name.visit_mut_children_with(self); - - match name { - PropName::Ident(ident) => { - self.state.add(&ident.sym); - } - PropName::Str(s) => { - self.state.add(&s.value); - } - _ => {} - }; - } - - fn visit_mut_prop(&mut self, prop: &mut Prop) { - prop.visit_mut_children_with(self); - - if let Prop::Shorthand(ident) = prop { - self.state.add(&ident.sym); - } - } - fn visit_mut_call_expr(&mut self, call: &mut CallExpr) { call.visit_mut_children_with(self); @@ -171,6 +149,28 @@ impl VisitMut for PropertyCollector<'_> { } } } + + fn visit_mut_prop(&mut self, prop: &mut Prop) { + prop.visit_mut_children_with(self); + + if let Prop::Shorthand(ident) = prop { + self.state.add(&ident.sym); + } + } + + fn visit_mut_prop_name(&mut self, name: &mut PropName) { + name.visit_mut_children_with(self); + + match name { + PropName::Ident(ident) => { + self.state.add(&ident.sym); + } + PropName::Str(s) => { + self.state.add(&s.value); + } + _ => {} + }; + } } fn is_root_of_member_expr_declared(member_expr: &MemberExpr, data: &ProgramData) -> bool { @@ -248,6 +248,8 @@ impl Mangler<'_> { } impl VisitMut for Mangler<'_> { + noop_visit_mut_type!(); + fn visit_mut_prop_name(&mut self, name: &mut PropName) { name.visit_mut_children_with(self); diff --git a/package.json b/package.json index 7ae5a144f3db..283667a3a09f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@swc/core", - "version": "1.2.77", + "version": "1.2.78", "description": "Super-fast alternative for babel", "homepage": "https://swc.rs", "main": "./index.js", @@ -90,4 +90,4 @@ "type": "opencollective", "url": "https://opencollective.com/swc" } -} \ No newline at end of file +} diff --git a/src/builder.rs b/src/builder.rs index e801e8489957..37c10190319d 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -192,7 +192,7 @@ impl<'a, 'b, P: swc_ecma_visit::Fold> PassBuilder<'a, 'b, P> { ), Optional::new( compat::es3(syntax.dynamic_import()), - self.target <= JscTarget::Es3 + cfg!(feature = "es3") && self.target <= JscTarget::Es3 ) )) }; diff --git a/tests/fixture/issue-1554/case1/input/.swcrc b/tests/fixture/issue-1554/case1/input/.swcrc new file mode 100644 index 000000000000..3f013e729084 --- /dev/null +++ b/tests/fixture/issue-1554/case1/input/.swcrc @@ -0,0 +1,5 @@ +{ + "module": { + "type": "commonjs" + } +} \ No newline at end of file diff --git a/tests/fixture/issue-1554/case1/input/index.js b/tests/fixture/issue-1554/case1/input/index.js new file mode 100644 index 000000000000..7f0d69b88129 --- /dev/null +++ b/tests/fixture/issue-1554/case1/input/index.js @@ -0,0 +1 @@ +export { default as X, Y } from './Z'; diff --git a/tests/fixture/issue-1554/case1/output/index.js b/tests/fixture/issue-1554/case1/output/index.js new file mode 100644 index 000000000000..27aaea928e31 --- /dev/null +++ b/tests/fixture/issue-1554/case1/output/index.js @@ -0,0 +1,40 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "X", { + enumerable: true, + get: function() { + return _z.default; + } +}); +Object.defineProperty(exports, "Y", { + enumerable: true, + get: function() { + return _z.Y; + } +}); +var _z = _interopRequireWildcard(require("./Z")); +function _interopRequireWildcard(obj) { + if (obj && obj.__esModule) { + return obj; + } else { + var newObj = { + }; + if (obj != null) { + for(var key in obj){ + if (Object.prototype.hasOwnProperty.call(obj, key)) { + var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : { + }; + if (desc.get || desc.set) { + Object.defineProperty(newObj, key, desc); + } else { + newObj[key] = obj[key]; + } + } + } + } + newObj.default = obj; + return newObj; + } +} diff --git a/tests/fixture/issue-1554/case2/input/.swcrc b/tests/fixture/issue-1554/case2/input/.swcrc new file mode 100644 index 000000000000..3f013e729084 --- /dev/null +++ b/tests/fixture/issue-1554/case2/input/.swcrc @@ -0,0 +1,5 @@ +{ + "module": { + "type": "commonjs" + } +} \ No newline at end of file diff --git a/tests/fixture/issue-1554/case2/input/index.js b/tests/fixture/issue-1554/case2/input/index.js new file mode 100644 index 000000000000..e032391b3096 --- /dev/null +++ b/tests/fixture/issue-1554/case2/input/index.js @@ -0,0 +1,4 @@ +import X from './module' + +export { X } +export { Y, Z } from './module' \ No newline at end of file diff --git a/tests/fixture/issue-1554/case2/output/index.js b/tests/fixture/issue-1554/case2/output/index.js new file mode 100644 index 000000000000..d6dc334d643a --- /dev/null +++ b/tests/fixture/issue-1554/case2/output/index.js @@ -0,0 +1,46 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "X", { + enumerable: true, + get: function() { + return _module.default; + } +}); +Object.defineProperty(exports, "Y", { + enumerable: true, + get: function() { + return _module.Y; + } +}); +Object.defineProperty(exports, "Z", { + enumerable: true, + get: function() { + return _module.Z; + } +}); +var _module = _interopRequireWildcard(require("./module")); +function _interopRequireWildcard(obj) { + if (obj && obj.__esModule) { + return obj; + } else { + var newObj = { + }; + if (obj != null) { + for(var key in obj){ + if (Object.prototype.hasOwnProperty.call(obj, key)) { + var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : { + }; + if (desc.get || desc.set) { + Object.defineProperty(newObj, key, desc); + } else { + newObj[key] = obj[key]; + } + } + } + } + newObj.default = obj; + return newObj; + } +} diff --git a/tests/fixture/issue-2086/input/.swcrc b/tests/fixture/issue-2086/input/.swcrc new file mode 100644 index 000000000000..156312084e15 --- /dev/null +++ b/tests/fixture/issue-2086/input/.swcrc @@ -0,0 +1,30 @@ +{ + "jsc": { + "parser": { + "syntax": "typescript", + "dynamicImport": true, + "decorators": true, + "importAssertions": true + }, + "transform": { + "legacyDecorator": true, + "optimizer": { + "jsonify": { + "minCost": 0 + } + } + }, + "target": "es2020", + "loose": true, + "externalHelpers": false, + "keepClassNames": false, + "minify": { + "compress": { + "comparisons": false, + "inline": 2 + }, + "mangle": true + } + }, + "minify": true +} \ No newline at end of file diff --git a/tests/fixture/issue-2086/input/index.ts b/tests/fixture/issue-2086/input/index.ts new file mode 100644 index 000000000000..28bbb2dbcac5 --- /dev/null +++ b/tests/fixture/issue-2086/input/index.ts @@ -0,0 +1,17 @@ +export default class Test { + #element: HTMLElement; + + constructor(element: HTMLElement) { + this.#element = element; + } + + #run() { + setTimeout(() => { + this.#element.textContent = 'TESTED'; + }, 1000); + } + + run() { + this.#run(); + } +} \ No newline at end of file diff --git a/tests/fixture/issue-2086/output/index.ts b/tests/fixture/issue-2086/output/index.ts new file mode 100644 index 000000000000..0f84aac2292c --- /dev/null +++ b/tests/fixture/issue-2086/output/index.ts @@ -0,0 +1 @@ +class Test{#a;constructor(a){this.#a=a} #b(){setTimeout(()=>{this.#a.textContent="TESTED"},1e3)}run(){this.#b()}}export{Test as default} diff --git a/visit/Cargo.toml b/visit/Cargo.toml index 879f36f860b5..650110e90299 100644 --- a/visit/Cargo.toml +++ b/visit/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" license = "Apache-2.0/MIT" name = "swc_visit" repository = "https://github.com/swc-project/swc.git" -version = "0.2.5" +version = "0.2.6" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/visit/src/lib.rs b/visit/src/lib.rs index 5c96bf6d1d60..cd45ac9a1b6d 100644 --- a/visit/src/lib.rs +++ b/visit/src/lib.rs @@ -87,7 +87,7 @@ pub struct Optional { } impl Optional { - pub fn new(visitor: V, enabled: bool) -> Self { + pub const fn new(visitor: V, enabled: bool) -> Self { Self { enabled, visitor } } } diff --git a/wasm/Cargo.toml b/wasm/Cargo.toml index 6f49edeb55ac..da1b1901ee16 100644 --- a/wasm/Cargo.toml +++ b/wasm/Cargo.toml @@ -6,7 +6,7 @@ license = "Apache-2.0 AND MIT" name = "wasm" publish = false repository = "https://github.com/swc-project/swc.git" -version = "1.2.77" +version = "1.2.78" [lib] crate-type = ["cdylib"]