Skip to content

Commit

Permalink
fix(es/transforms): Fix bugs (#2089)
Browse files Browse the repository at this point in the history
swc_ecma_minifier:
 - Expose hygiene optimizer.
 - `mangle_names`: Handle private names in member expressions. (#2086)

swc_visit:
 - Make `Optional::new` const function.

swc:
 - Make `es3` optional via cargo feature.
 - Ensure that #1554 is already fixed. (#1554)
  • Loading branch information
kdy1 authored Aug 16, 2021
1 parent e84ed13 commit a309b36
Show file tree
Hide file tree
Showing 21 changed files with 241 additions and 51 deletions.
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 7 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion ecmascript/minifier/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 = []
Expand Down
8 changes: 3 additions & 5 deletions ecmascript/minifier/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,19 @@
//! 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,
metadata::info_marker,
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};
Expand Down Expand Up @@ -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 {
Expand Down
48 changes: 38 additions & 10 deletions ecmascript/minifier/src/pass/hygiene/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,26 @@ 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;

/// Optimize hygiene info to get minified output.
///
/// 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 {
Expand Down Expand Up @@ -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(),
Expand Down
8 changes: 8 additions & 0 deletions ecmascript/minifier/src/pass/mangle_names/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
_ => {}
}
}
}

Expand Down
48 changes: 25 additions & 23 deletions ecmascript/minifier/src/pass/mangle_props.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<AHashSet<JsWord>> = Lazy::new(|| {
let domprops: Vec<JsWord> = serde_json::from_str(include_str!("../lists/domprops.json"))
Expand Down Expand Up @@ -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);

Expand All @@ -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 {
Expand Down Expand Up @@ -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);

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down Expand Up @@ -90,4 +90,4 @@
"type": "opencollective",
"url": "https://opencollective.com/swc"
}
}
}
2 changes: 1 addition & 1 deletion src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
))
};
Expand Down
5 changes: 5 additions & 0 deletions tests/fixture/issue-1554/case1/input/.swcrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"module": {
"type": "commonjs"
}
}
1 change: 1 addition & 0 deletions tests/fixture/issue-1554/case1/input/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as X, Y } from './Z';
40 changes: 40 additions & 0 deletions tests/fixture/issue-1554/case1/output/index.js
Original file line number Diff line number Diff line change
@@ -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;
}
}
5 changes: 5 additions & 0 deletions tests/fixture/issue-1554/case2/input/.swcrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"module": {
"type": "commonjs"
}
}
4 changes: 4 additions & 0 deletions tests/fixture/issue-1554/case2/input/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import X from './module'

export { X }
export { Y, Z } from './module'
Loading

0 comments on commit a309b36

Please sign in to comment.