Skip to content

Commit

Permalink
fix(es/minifier): Respect pure_funcs for tagged tpls (#8280)
Browse files Browse the repository at this point in the history
**Related issue:**

 - Closes #8275.
  • Loading branch information
kdy1 authored Nov 14, 2023
1 parent 2f6af92 commit 1ccfc07
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 24 deletions.
22 changes: 22 additions & 0 deletions crates/swc/tests/fixture/issues-8xxx/8275/input/.swcrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"jsc": {
"parser": {
"syntax": "ecmascript",
"jsx": false
},
"target": "es2022",
"loose": false,
"minify": {
"compress": {
"pure_funcs": [
"pure_html"
]
},
"mangle": false
}
},
"module": {
"type": "es6"
},
"isModule": true
}
15 changes: 15 additions & 0 deletions crates/swc/tests/fixture/issues-8xxx/8275/input/1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*#__PURE__*/
function pure_html(strings, ...values) {
return { strings, values };
}

// ✅ This is tree-shaken from the minified output.
const a = `<span>aaaa</span>`;

// ❌ This is not tree-shaken from the minified output,
// despite the "html" function being declare using
// `jsc.minify.compress.pure_funcs` configuration.
const b = pure_html`<span>bbbb</span>`;

// ✅ This is not tree-shaken from the minified output.
export const c = pure_html`<span>cccc</span>`;
6 changes: 6 additions & 0 deletions crates/swc/tests/fixture/issues-8xxx/8275/output/1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const c = (function(strings, ...values) {
return {
strings,
values
};
})`<span>cccc</span>`;
41 changes: 28 additions & 13 deletions crates/swc_ecma_minifier/src/compress/pure/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -928,20 +928,35 @@ impl Pure<'_> {
_ => {}
}

if let Expr::Call(CallExpr {
callee: Callee::Expr(callee),
args,
..
}) = e
{
if callee.is_pure_callee(&self.expr_ctx) {
self.changed = true;
report_change!("Dropping pure call as callee is pure");
*e = self
.make_ignored_expr(args.take().into_iter().map(|arg| arg.expr))
.unwrap_or(Expr::Invalid(Invalid { span: DUMMY_SP }));
return;
match e {
Expr::Call(CallExpr {
callee: Callee::Expr(callee),
args,
..
}) => {
if callee.is_pure_callee(&self.expr_ctx) {
self.changed = true;
report_change!("Dropping pure call as callee is pure");
*e = self
.make_ignored_expr(args.take().into_iter().map(|arg| arg.expr))
.unwrap_or(Expr::Invalid(Invalid { span: DUMMY_SP }));
return;
}
}

Expr::TaggedTpl(TaggedTpl {
tag: callee, tpl, ..
}) => {
if callee.is_pure_callee(&self.expr_ctx) {
self.changed = true;
report_change!("Dropping pure tag tpl as callee is pure");
*e = self
.make_ignored_expr(tpl.exprs.take().into_iter())
.unwrap_or(Expr::Invalid(Invalid { span: DUMMY_SP }));
return;
}
}
_ => (),
}

if self.options.unused {
Expand Down
55 changes: 44 additions & 11 deletions crates/swc_ecma_minifier/src/metadata/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,39 @@ struct InfoMarker<'a> {
state: State,
}

impl InfoMarker<'_> {
fn is_pure_callee(&self, callee: &Expr) -> bool {
match callee {
Expr::Ident(callee) => {
if self.pure_callee.contains(&callee.to_id()) {
return true;
}
}

Expr::Seq(callee) => {
if has_pure(self.comments, callee.span) {
return true;
}
}
_ => (),
}

if let Some(pure_fns) = &self.pure_funcs {
if let Expr::Ident(..) = callee {
// Check for pure_funcs
if Ident::within_ignored_ctxt(|| {
//
pure_fns.contains(&NodeIgnoringSpan::borrowed(callee))
}) {
return true;
}
}
}

has_pure(self.comments, callee.span())
}
}

impl VisitMut for InfoMarker<'_> {
noop_visit_mut_type!();

Expand All @@ -71,19 +104,9 @@ impl VisitMut for InfoMarker<'_> {
// We check callee in some cases because we move comments
// See https://github.com/swc-project/swc/issues/7241
if match &n.callee {
Callee::Expr(e) => match &**e {
Expr::Ident(callee) => self.pure_callee.contains(&callee.to_id()),
_ => false,
},
Callee::Expr(e) => self.is_pure_callee(e),
_ => false,
} || has_pure(self.comments, n.span)
|| match &n.callee {
Callee::Expr(e) => match &**e {
Expr::Seq(callee) => has_pure(self.comments, callee.span),
_ => false,
},
_ => false,
}
{
if !n.span.is_dummy_ignoring_cmt() {
n.span = n.span.apply_mark(self.marks.pure);
Expand Down Expand Up @@ -185,6 +208,16 @@ impl VisitMut for InfoMarker<'_> {
}
}

fn visit_mut_tagged_tpl(&mut self, n: &mut TaggedTpl) {
n.visit_mut_children_with(self);

if has_pure(self.comments, n.span) || self.is_pure_callee(&n.tag) {
if !n.span.is_dummy_ignoring_cmt() {
n.span = n.span.apply_mark(self.marks.pure);
}
}
}

fn visit_mut_var_decl(&mut self, n: &mut VarDecl) {
n.visit_mut_children_with(self);

Expand Down

0 comments on commit 1ccfc07

Please sign in to comment.