Skip to content

Commit 24e8798

Browse files
devongovettkdy1
andauthoredJul 31, 2024··
fix(es/minifier): Preserve flags while dropping elements of SeqExpr (#8907)
Co-authored-by: 강동윤 (Donny) <kdy1997.dev@gmail.com>
1 parent 81d7d9d commit 24e8798

File tree

18 files changed

+126
-88
lines changed

18 files changed

+126
-88
lines changed
 

‎.changeset/gorgeous-ties-fail.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
swc_ecma_minifier: patch
3+
---
4+
5+
dead_branch_remover removes PURE annotations on sequence expressions

‎Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ resolver = "2"
6666
copyless = "0.1.5"
6767
crc = "2.1.0"
6868
criterion = "0.5.1"
69+
crossbeam-queue = "0.3.11"
6970
dashmap = "5.5.3"
7071
dialoguer = "0.10.2"
7172
difference = "2"

‎crates/swc_ecma_minifier/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ serde = { workspace = true, features = ["derive"] }
5151
serde_json = { workspace = true }
5252
tracing = { workspace = true }
5353

54+
5455
swc_allocator = { version = "0.1.7", path = "../swc_allocator", default-features = false }
5556
swc_atoms = { version = "0.6.5", path = "../swc_atoms" }
5657
swc_common = { version = "0.36.0", path = "../swc_common" }

‎crates/swc_ecma_minifier/src/compress/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,6 @@ impl Compressor<'_> {
235235

236236
let mut visitor = pure_optimizer(
237237
self.options,
238-
None,
239238
self.marks,
240239
PureOptimizerConfig {
241240
enable_join_vars: self.pass > 1,

‎crates/swc_ecma_minifier/src/compress/optimize/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1817,7 +1817,9 @@ impl VisitMut for Optimizer<'_> {
18171817

18181818
match e {
18191819
Expr::Seq(seq) if seq.exprs.len() == 1 => {
1820+
let span = seq.span;
18201821
*e = *seq.exprs[0].take();
1822+
e.set_span(span);
18211823
}
18221824

18231825
Expr::Assign(AssignExpr {

‎crates/swc_ecma_minifier/src/compress/pure/misc.rs

+49-23
Original file line numberDiff line numberDiff line change
@@ -870,7 +870,11 @@ impl Pure<'_> {
870870
}
871871
}
872872

873-
fn make_ignored_expr(&mut self, exprs: impl Iterator<Item = Box<Expr>>) -> Option<Expr> {
873+
fn make_ignored_expr(
874+
&mut self,
875+
span: Span,
876+
exprs: impl Iterator<Item = Box<Expr>>,
877+
) -> Option<Expr> {
874878
let mut exprs = exprs
875879
.filter_map(|mut e| {
876880
self.ignore_return_value(
@@ -894,7 +898,9 @@ impl Pure<'_> {
894898
return None;
895899
}
896900
if exprs.len() == 1 {
897-
return Some(*exprs.remove(0));
901+
let mut new = *exprs.remove(0);
902+
new.set_span(span);
903+
return Some(new);
898904
}
899905

900906
Some(
@@ -970,32 +976,41 @@ impl Pure<'_> {
970976
}
971977
}
972978

973-
Expr::Call(CallExpr { ctxt, args, .. }) if ctxt.has_mark(self.marks.pure) => {
979+
Expr::Call(CallExpr {
980+
span, ctxt, args, ..
981+
}) if ctxt.has_mark(self.marks.pure) => {
974982
report_change!("ignore_return_value: Dropping a pure call");
975983
self.changed = true;
976984

977-
let new = self.make_ignored_expr(args.take().into_iter().map(|arg| arg.expr));
985+
let new =
986+
self.make_ignored_expr(*span, args.take().into_iter().map(|arg| arg.expr));
978987

979988
*e = new.unwrap_or(Invalid { span: DUMMY_SP }.into());
980989
return;
981990
}
982991

983-
Expr::TaggedTpl(TaggedTpl { ctxt, tpl, .. }) if ctxt.has_mark(self.marks.pure) => {
992+
Expr::TaggedTpl(TaggedTpl {
993+
span, ctxt, tpl, ..
994+
}) if ctxt.has_mark(self.marks.pure) => {
984995
report_change!("ignore_return_value: Dropping a pure call");
985996
self.changed = true;
986997

987-
let new = self.make_ignored_expr(tpl.exprs.take().into_iter());
998+
let new = self.make_ignored_expr(*span, tpl.exprs.take().into_iter());
988999

9891000
*e = new.unwrap_or(Invalid { span: DUMMY_SP }.into());
9901001
return;
9911002
}
9921003

993-
Expr::New(NewExpr { ctxt, args, .. }) if ctxt.has_mark(self.marks.pure) => {
1004+
Expr::New(NewExpr {
1005+
span, ctxt, args, ..
1006+
}) if ctxt.has_mark(self.marks.pure) => {
9941007
report_change!("ignore_return_value: Dropping a pure call");
9951008
self.changed = true;
9961009

997-
let new =
998-
self.make_ignored_expr(args.take().into_iter().flatten().map(|arg| arg.expr));
1010+
let new = self.make_ignored_expr(
1011+
*span,
1012+
args.take().into_iter().flatten().map(|arg| arg.expr),
1013+
);
9991014

10001015
*e = new.unwrap_or(Invalid { span: DUMMY_SP }.into());
10011016
return;
@@ -1006,6 +1021,7 @@ impl Pure<'_> {
10061021

10071022
match e {
10081023
Expr::Call(CallExpr {
1024+
span,
10091025
callee: Callee::Expr(callee),
10101026
args,
10111027
..
@@ -1014,20 +1030,23 @@ impl Pure<'_> {
10141030
self.changed = true;
10151031
report_change!("Dropping pure call as callee is pure");
10161032
*e = self
1017-
.make_ignored_expr(args.take().into_iter().map(|arg| arg.expr))
1033+
.make_ignored_expr(*span, args.take().into_iter().map(|arg| arg.expr))
10181034
.unwrap_or(Invalid { span: DUMMY_SP }.into());
10191035
return;
10201036
}
10211037
}
10221038

10231039
Expr::TaggedTpl(TaggedTpl {
1024-
tag: callee, tpl, ..
1040+
span,
1041+
tag: callee,
1042+
tpl,
1043+
..
10251044
}) => {
10261045
if callee.is_pure_callee(&self.expr_ctx) {
10271046
self.changed = true;
10281047
report_change!("Dropping pure tag tpl as callee is pure");
10291048
*e = self
1030-
.make_ignored_expr(tpl.exprs.take().into_iter())
1049+
.make_ignored_expr(*span, tpl.exprs.take().into_iter())
10311050
.unwrap_or(Invalid { span: DUMMY_SP }.into());
10321051
return;
10331052
}
@@ -1357,24 +1376,29 @@ impl Pure<'_> {
13571376

13581377
if self.options.side_effects && self.options.pristine_globals {
13591378
match e {
1360-
Expr::New(NewExpr { callee, args, .. })
1361-
if callee.is_one_of_global_ref_to(
1362-
&self.expr_ctx,
1363-
&[
1364-
"Map", "Set", "Array", "Object", "Boolean", "Number", "String",
1365-
],
1366-
) =>
1379+
Expr::New(NewExpr {
1380+
span, callee, args, ..
1381+
}) if callee.is_one_of_global_ref_to(
1382+
&self.expr_ctx,
1383+
&[
1384+
"Map", "Set", "Array", "Object", "Boolean", "Number", "String",
1385+
],
1386+
) =>
13671387
{
13681388
report_change!("Dropping a pure new expression");
13691389

13701390
self.changed = true;
13711391
*e = self
1372-
.make_ignored_expr(args.iter_mut().flatten().map(|arg| arg.expr.take()))
1392+
.make_ignored_expr(
1393+
*span,
1394+
args.iter_mut().flatten().map(|arg| arg.expr.take()),
1395+
)
13731396
.unwrap_or(Invalid { span: DUMMY_SP }.into());
13741397
return;
13751398
}
13761399

13771400
Expr::Call(CallExpr {
1401+
span,
13781402
callee: Callee::Expr(callee),
13791403
args,
13801404
..
@@ -1387,7 +1411,7 @@ impl Pure<'_> {
13871411

13881412
self.changed = true;
13891413
*e = self
1390-
.make_ignored_expr(args.iter_mut().map(|arg| arg.expr.take()))
1414+
.make_ignored_expr(*span, args.iter_mut().map(|arg| arg.expr.take()))
13911415
.unwrap_or(Invalid { span: DUMMY_SP }.into());
13921416
return;
13931417
}
@@ -1427,7 +1451,7 @@ impl Pure<'_> {
14271451
}
14281452

14291453
*e = self
1430-
.make_ignored_expr(exprs.into_iter())
1454+
.make_ignored_expr(obj.span, exprs.into_iter())
14311455
.unwrap_or(Invalid { span: DUMMY_SP }.into());
14321456
report_change!("Ignored an object literal");
14331457
self.changed = true;
@@ -1499,7 +1523,7 @@ impl Pure<'_> {
14991523
}
15001524

15011525
*e = self
1502-
.make_ignored_expr(exprs.into_iter())
1526+
.make_ignored_expr(arr.span, exprs.into_iter())
15031527
.unwrap_or(Invalid { span: DUMMY_SP }.into());
15041528
report_change!("Ignored an array literal");
15051529
self.changed = true;
@@ -1514,6 +1538,7 @@ impl Pure<'_> {
15141538
//
15151539
// foo(),basr(),foo;
15161540
Expr::Member(MemberExpr {
1541+
span,
15171542
obj,
15181543
prop: MemberProp::Computed(prop),
15191544
..
@@ -1526,6 +1551,7 @@ impl Pure<'_> {
15261551
_ => {
15271552
*e = self
15281553
.make_ignored_expr(
1554+
*span,
15291555
vec![obj.take(), prop.expr.take()].into_iter(),
15301556
)
15311557
.unwrap_or(Invalid { span: DUMMY_SP }.into());

‎crates/swc_ecma_minifier/src/compress/pure/mod.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,7 @@ use self::{ctx::Ctx, misc::DropOpts};
1515
use super::util::is_pure_undefined_or_null;
1616
#[cfg(feature = "debug")]
1717
use crate::debug::dump;
18-
use crate::{
19-
debug::AssertValid, maybe_par, option::CompressOptions, program_data::ProgramData,
20-
util::ModuleItemExt,
21-
};
18+
use crate::{debug::AssertValid, maybe_par, option::CompressOptions, util::ModuleItemExt};
2219

2320
mod arrows;
2421
mod bools;
@@ -52,7 +49,6 @@ pub(crate) struct PureOptimizerConfig {
5249
#[allow(clippy::needless_lifetimes)]
5350
pub(crate) fn pure_optimizer<'a>(
5451
options: &'a CompressOptions,
55-
data: Option<&'a ProgramData>,
5652
marks: Marks,
5753
config: PureOptimizerConfig,
5854
) -> impl 'a + VisitMut + Repeated {
@@ -64,7 +60,6 @@ pub(crate) fn pure_optimizer<'a>(
6460
unresolved_ctxt: SyntaxContext::empty().apply_mark(marks.unresolved_mark),
6561
is_unresolved_ref_safe: false,
6662
},
67-
data,
6863
ctx: Default::default(),
6964
changed: Default::default(),
7065
}
@@ -76,8 +71,6 @@ struct Pure<'a> {
7671
marks: Marks,
7772
expr_ctx: ExprCtx,
7873

79-
#[allow(unused)]
80-
data: Option<&'a ProgramData>,
8174
ctx: Ctx,
8275
changed: bool,
8376
}

‎crates/swc_ecma_minifier/src/eval.rs

-1
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,6 @@ impl Evaluator {
242242
{
243243
e.visit_mut_with(&mut pure_optimizer(
244244
&Default::default(),
245-
None,
246245
self.marks,
247246
PureOptimizerConfig {
248247
enable_join_vars: false,

‎crates/swc_ecma_minifier/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,6 @@ pub fn optimize(
202202

203203
let mut v = pure_optimizer(
204204
c,
205-
None,
206205
marks,
207206
PureOptimizerConfig {
208207
force_str_for_tpl: Minification.force_str_for_tpl(),

‎crates/swc_ecma_minifier/tests/benches-full/terser.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -4437,8 +4437,7 @@
44374437
let printed_comments = new Set();
44384438
var to_utf8 = options.ascii_only ? function(str, identifier = !1, regexp = !1) {
44394439
return !(options.ecma >= 2015) || options.safari10 || regexp || (str = str.replace(/[\ud800-\udbff][\udc00-\udfff]/g, function(ch) {
4440-
return "\\u{" + // https://en.wikipedia.org/wiki/Universal_Character_Set_characters#Surrogates
4441-
(is_surrogate_pair_head(ch.charCodeAt(0)) ? 0x10000 + (ch.charCodeAt(0) - 0xd800 << 10) + ch.charCodeAt(1) - 0xdc00 : ch.charCodeAt(0)).toString(16) + "}";
4440+
return "\\u{" + (is_surrogate_pair_head(ch.charCodeAt(0)) ? 0x10000 + (ch.charCodeAt(0) - 0xd800 << 10) + ch.charCodeAt(1) - 0xdc00 : ch.charCodeAt(0)).toString(16) + "}";
44424441
})), str.replace(/[\u0000-\u001f\u007f-\uffff]/g, function(ch) {
44434442
var code = ch.charCodeAt(0).toString(16);
44444443
if (code.length <= 2 && !identifier) {

‎crates/swc_ecma_minifier/tests/benches-full/victory.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -11730,8 +11730,7 @@ object-assign
1173011730
// Equivalent of `typeof` but with special handling for array and regexp.
1173111731
function getPropType(propValue) {
1173211732
var propType = typeof propValue;
11733-
return Array.isArray(propValue) ? 'array' : propValue instanceof RegExp ? 'object' : // Native Symbol.
11734-
'symbol' === propType || propValue && ('Symbol' === propValue['@@toStringTag'] || 'function' == typeof Symbol && propValue instanceof Symbol) ? 'symbol' : propType;
11733+
return Array.isArray(propValue) ? 'array' : propValue instanceof RegExp ? 'object' : 'symbol' === propType || propValue && ('Symbol' === propValue['@@toStringTag'] || 'function' == typeof Symbol && propValue instanceof Symbol) ? 'symbol' : propType;
1173511734
}
1173611735
// This handles more types than `getPropType`. Only used for error messages.
1173711736
// See `createPrimitiveTypeChecker`.

0 commit comments

Comments
 (0)
Please sign in to comment.