Skip to content

Commit df2a926

Browse files
authored
fix(es/transforms/module): Use correct this (#1561)
swc_ecma_transforms_module: - Preserve semantics of `this` in imported functions. (#1556)
1 parent 92bbde3 commit df2a926

File tree

16 files changed

+202
-70
lines changed

16 files changed

+202
-70
lines changed

ecmascript/transforms/base/src/fixer.rs

+96-28
Original file line numberDiff line numberDiff line change
@@ -454,18 +454,27 @@ impl VisitMut for Fixer<'_> {
454454

455455
impl Fixer<'_> {
456456
fn wrap_with_paren_if_required(&mut self, e: &mut Expr) {
457+
let mut has_padding_value = false;
457458
match e {
458459
// Flatten seq expr
459460
Expr::Seq(SeqExpr { span, exprs }) => {
460461
let len = exprs
461462
.iter()
462463
.map(|expr| match **expr {
464+
Expr::Paren(ParenExpr { ref expr, .. }) => {
465+
if let Expr::Seq(SeqExpr { exprs, .. }) = expr.as_ref() {
466+
exprs.len()
467+
} else {
468+
1
469+
}
470+
}
463471
Expr::Seq(SeqExpr { ref exprs, .. }) => exprs.len(),
464472
_ => 1,
465473
})
466474
.sum();
467475

468476
let exprs_len = exprs.len();
477+
// don't has child seq
469478
let expr = if len == exprs_len {
470479
let mut exprs = exprs
471480
.into_iter()
@@ -475,14 +484,15 @@ impl Fixer<'_> {
475484
if is_last {
476485
Some(e.take())
477486
} else {
478-
ignore_return_value(e.take())
487+
ignore_return_value(e.take(), &mut has_padding_value)
479488
}
480489
})
481490
.collect::<Vec<_>>();
482491
if exprs.len() == 1 {
483492
*e = *exprs.pop().unwrap();
484493
return;
485494
}
495+
let exprs = ignore_padding_value(exprs);
486496
Expr::Seq(SeqExpr { span: *span, exprs })
487497
} else {
488498
let mut buf = Vec::with_capacity(len);
@@ -493,15 +503,20 @@ impl Fixer<'_> {
493503
Expr::Seq(SeqExpr { ref mut exprs, .. }) => {
494504
let exprs = exprs.take();
495505
if !is_last {
496-
buf.extend(exprs.into_iter().filter_map(ignore_return_value));
506+
buf.extend(exprs.into_iter().filter_map(|expr| {
507+
ignore_return_value(expr, &mut has_padding_value)
508+
}));
497509
} else {
498510
let exprs_len = exprs.len();
499511
for (i, expr) in exprs.into_iter().enumerate() {
500512
let is_last = i + 1 == exprs_len;
501513
if is_last {
502514
buf.push(expr);
503515
} else {
504-
buf.extend(ignore_return_value(expr));
516+
buf.extend(ignore_return_value(
517+
expr,
518+
&mut has_padding_value,
519+
));
505520
}
506521
}
507522
}
@@ -510,7 +525,10 @@ impl Fixer<'_> {
510525
if is_last {
511526
buf.push(expr.take());
512527
} else {
513-
buf.extend(ignore_return_value(expr.take()));
528+
buf.extend(ignore_return_value(
529+
expr.take(),
530+
&mut has_padding_value,
531+
));
514532
}
515533
}
516534
}
@@ -520,16 +538,14 @@ impl Fixer<'_> {
520538
*e = *buf.pop().unwrap();
521539
return;
522540
}
523-
buf.shrink_to_fit();
524541

525-
Expr::Seq(SeqExpr {
526-
span: *span,
527-
exprs: buf,
528-
})
542+
let exprs = ignore_padding_value(buf);
543+
544+
Expr::Seq(SeqExpr { span: *span, exprs })
529545
};
530546

531547
match self.ctx {
532-
Context::ForcedExpr { .. } | Context::Callee { .. } => {
548+
Context::ForcedExpr { .. } => {
533549
*e = Expr::Paren(ParenExpr {
534550
span: *span,
535551
expr: Box::new(expr),
@@ -569,6 +585,16 @@ impl Fixer<'_> {
569585
}
570586
}
571587

588+
Expr::Call(CallExpr {
589+
callee: ExprOrSuper::Expr(ref mut callee),
590+
..
591+
}) if callee.is_seq() => {
592+
*callee = Box::new(Expr::Paren(ParenExpr {
593+
span: callee.span(),
594+
expr: callee.take(),
595+
}))
596+
}
597+
572598
Expr::Call(CallExpr {
573599
callee: ExprOrSuper::Expr(ref mut callee),
574600
..
@@ -676,9 +702,16 @@ impl Fixer<'_> {
676702
}
677703
}
678704

679-
fn ignore_return_value(expr: Box<Expr>) -> Option<Box<Expr>> {
705+
fn ignore_return_value(expr: Box<Expr>, has_padding_value: &mut bool) -> Option<Box<Expr>> {
680706
match *expr {
681-
Expr::Ident(..) | Expr::Fn(..) | Expr::Lit(..) => None,
707+
Expr::Fn(..) | Expr::Arrow(..) | Expr::Lit(..) => {
708+
if *has_padding_value {
709+
None
710+
} else {
711+
*has_padding_value = true;
712+
Some(expr)
713+
}
714+
}
682715
Expr::Seq(SeqExpr { span, exprs }) => {
683716
let len = exprs.len();
684717
let mut exprs: Vec<_> = exprs
@@ -688,7 +721,7 @@ fn ignore_return_value(expr: Box<Expr>) -> Option<Box<Expr>> {
688721
if i + 1 == len {
689722
Some(expr)
690723
} else {
691-
ignore_return_value(expr)
724+
ignore_return_value(expr, has_padding_value)
692725
}
693726
})
694727
.collect();
@@ -702,11 +735,30 @@ fn ignore_return_value(expr: Box<Expr>) -> Option<Box<Expr>> {
702735
op: op!("void"),
703736
arg,
704737
..
705-
}) => ignore_return_value(arg),
738+
}) => ignore_return_value(arg, has_padding_value),
706739
_ => Some(expr),
707740
}
708741
}
709742

743+
// at least 3 element in seq, which means we can safely
744+
// remove that padding, if not at last position
745+
fn ignore_padding_value(exprs: Vec<Box<Expr>>) -> Vec<Box<Expr>> {
746+
let len = exprs.len();
747+
748+
if len > 2 {
749+
exprs
750+
.into_iter()
751+
.enumerate()
752+
.filter_map(|(i, e)| match e.as_ref() {
753+
Expr::Fn(..) | Expr::Arrow(..) | Expr::Lit(..) if i + 1 != len => None,
754+
_ => Some(e),
755+
})
756+
.collect()
757+
} else {
758+
exprs
759+
}
760+
}
761+
710762
#[cfg(test)]
711763
mod tests {
712764
use super::fixer;
@@ -821,36 +873,44 @@ const _ref = {}, { c =( _tmp = {}, d = _extends({}, _tmp), _tmp) } = _ref;"
821873
((a, b), (c())) + ((d, e), (f()));
822874
",
823875
"var a, b, c, d, e, f;
824-
c() + f()"
876+
(a, b, c()) + (d, e, f())"
825877
);
826878

827-
test_fixer!(fixer_02, "(b, c), d;", "d;");
879+
test_fixer!(fixer_02, "(b, c), d;", "b, c, d;");
828880

829-
test_fixer!(fixer_03, "((a, b), (c && d)) && e;", "c && d && e;");
881+
test_fixer!(fixer_03, "((a, b), (c && d)) && e;", "(a, b, c && d) && e;");
830882

831-
test_fixer!(fixer_04, "for ((a, b), c;;) ;", "for(c;;);");
883+
test_fixer!(fixer_04, "for ((a, b), c;;) ;", "for(a, b, c;;);");
832884

833885
test_fixer!(
834886
fixer_05,
835887
"var a, b, c = (1), d, e, f = (2);
836888
((a, b), c) + ((d, e), f);",
837889
"var a, b, c = 1, d, e, f = 2;
838-
c + f;"
890+
(a, b, c) + (d, e, f);"
839891
);
840892

841893
test_fixer!(
842894
fixer_06,
843895
"var a, b, c, d;
844896
a = ((b, c), d);",
845897
"var a, b, c, d;
846-
a = d;"
898+
a = (b, c, d);"
847899
);
848900

849-
test_fixer!(fixer_07, "a => ((b, c) => ((a, b), c));", "(a)=>(b, c)=>c;");
901+
test_fixer!(
902+
fixer_07,
903+
"a => ((b, c) => ((a, b), c));",
904+
"(a)=>(b, c)=>(a, b, c);"
905+
);
850906

851-
test_fixer!(fixer_08, "typeof (((1), a), (2));", "typeof 2");
907+
test_fixer!(fixer_08, "typeof (((1), a), (2));", "typeof (a, 2)");
852908

853-
test_fixer!(fixer_09, "(((a, b), c), d) ? e : f;", "d ? e : f;");
909+
test_fixer!(
910+
fixer_09,
911+
"(((a, b), c), d) ? e : f;",
912+
"(a, b, c, d) ? e : f;"
913+
);
854914

855915
test_fixer!(
856916
fixer_10,
@@ -861,16 +921,18 @@ function a() {
861921
",
862922
"
863923
function a() {
864-
return void 3;
924+
return a, void 3;
865925
}
866926
"
867927
);
868928

869-
test_fixer!(fixer_11, "c && ((((2), (3)), d), b);", "c && b");
929+
test_fixer!(fixer_11, "c && ((((2), (3)), d), b);", "c && (d, b)");
930+
931+
test_fixer!(fixer_12, "(((a, b), c), d) + e;", "(a, b, c, d) + e;");
870932

871-
test_fixer!(fixer_12, "(((a, b), c), d) + e;", "d + e;");
933+
test_fixer!(fixer_13, "delete (((1), a), (2));", "delete (a, 2)");
872934

873-
test_fixer!(fixer_13, "delete (((1), a), (2));", "delete 2");
935+
test_fixer!(fixer_14, "(1, 2, a)", "1, a");
874936

875937
identical!(issue_231, "'' + (truthy && '?') + truthy;");
876938

@@ -950,7 +1012,7 @@ var store = global[SHARED] || (global[SHARED] = {});
9501012

9511013
identical!(bin_seq_expr_1, "(foo(), op) || (seq(), foo)");
9521014

953-
test_fixer!(bin_seq_expr_2, "(foo, op) || (seq, foo)", "op || foo");
1015+
identical!(bin_seq_expr_2, "(foo, op) || (seq, foo)");
9541016

9551017
identical!(cond_object_1, "let foo = {} ? 1 : 2;");
9561018

@@ -1088,6 +1150,12 @@ var store = global[SHARED] || (global[SHARED] = {});
10881150
identical!(issue_1493, "('a' ?? 'b') || ''");
10891151
identical!(call_seq, "let x = ({}, () => 2)();");
10901152

1153+
test_fixer!(
1154+
call_seq_with_padding,
1155+
"let x = ({}, (1, 2), () => 2)();",
1156+
"let x = ({}, () => 2)();"
1157+
);
1158+
10911159
identical!(
10921160
param_seq,
10931161
"function t(x = ({}, 2)) {

ecmascript/transforms/compat/tests/es2015_destructuring.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ test!(
8686
[{ a = 1 }] = foo"#,
8787
r#"let a;
8888
var ref, ref1, ref2;
89-
ref = foo, ref1 = ref[0], ref2 = ref1.a, a = ref2 === void 0 ? 1 : ref2, ref;"#
89+
ref = foo, ref1 = ref[0], ref2 = ref1.a, a = ref2 === void 0 ? 1 : ref2, ref1, ref;"#
9090
);
9191

9292
test!(
@@ -1118,7 +1118,7 @@ var x = z[x],
11181118
11191119
var _o;
11201120
var ref;
1121-
_o = o, z = _objectWithoutProperties(_o, ['x', 'y']), ref = _o, x = ref.x, y = ref.y, _o;
1121+
_o = o, z = _objectWithoutProperties(_o, ['x', 'y']), ref = _o, x = ref.x, y = ref.y, ref, _o;
11221122
11231123
11241124
"#

ecmascript/transforms/compat/tests/es2020_class_properties.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3942,7 +3942,7 @@ class SuperClass extends Obj {
39423942
constructor() {
39433943
var _temp;
39443944
3945-
class B extends (_temp = super(), _defineProperty(this, 'field', 1), Obj) {
3945+
class B extends (_temp = super(), _defineProperty(this, 'field', 1), _temp, Obj) {
39463946
constructor() {
39473947
super();
39483948
expect(this.field).toBeUndefined();

ecmascript/transforms/compat/tests/es2020_optional_chaining.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,8 @@ orders === null || orders === void 0 ? void 0 : orders[0].price;
221221
orders === null || orders === void 0 ? void 0 : (ref5 = orders[0]) === null || ref5 === void 0 ? void 0 : ref5.price;
222222
orders[client === null || client === void 0 ? void 0 : client.key].price;
223223
(ref6 = orders[client.key]) === null || ref6 === void 0 ? void 0 : ref6.price;
224-
(a === null || a === void 0 ? void 0 : a.b).c;
225-
((ref7 = (a === null || a === void 0 ? void 0 : a.b).c) === null || ref7 === void 0 ? void 0 : ref7.d).e;
224+
(0, a === null || a === void 0 ? void 0 : a.b).c;
225+
(0, (ref7 = (0, a === null || a === void 0 ? void 0 : a.b).c) === null || ref7 === void 0 ? void 0 : ref7.d).e;
226226
"#
227227
);
228228

ecmascript/transforms/module/src/util.rs

+49-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use std::{
99
use swc_atoms::{js_word, JsWord};
1010
use swc_common::{Mark, Span, SyntaxContext, DUMMY_SP};
1111
use swc_ecma_ast::*;
12+
use swc_ecma_transforms_base::ext::MapWithMut;
1213
use swc_ecma_utils::member_expr;
1314
use swc_ecma_utils::private_ident;
1415
use swc_ecma_utils::quote_ident;
@@ -489,7 +490,54 @@ impl Scope {
489490
_ => false,
490491
} =>
491492
{
492-
return folder.make_dynamic_import(span, args)
493+
folder.make_dynamic_import(span, args)
494+
}
495+
496+
Expr::Call(CallExpr {
497+
span,
498+
callee,
499+
args,
500+
type_args,
501+
}) => {
502+
let callee = if let ExprOrSuper::Expr(expr) = callee {
503+
let callee = if let Expr::Ident(ident) = *expr {
504+
match Self::fold_ident(folder, top_level, ident) {
505+
Ok(mut expr) => {
506+
if let Expr::Member(member) = &mut expr {
507+
if let ExprOrSuper::Expr(expr) = &mut member.obj {
508+
if let Expr::Ident(ident) = expr.as_mut() {
509+
member.obj = ExprOrSuper::Expr(Box::new(Expr::Paren(
510+
ParenExpr {
511+
expr: Box::new(Expr::Seq(SeqExpr {
512+
span,
513+
exprs: vec![
514+
Box::new(0_f64.into()),
515+
Box::new(ident.take().into()),
516+
],
517+
})),
518+
span,
519+
},
520+
)))
521+
}
522+
}
523+
};
524+
expr
525+
}
526+
Err(ident) => Expr::Ident(ident),
527+
}
528+
} else {
529+
*expr.fold_with(folder)
530+
};
531+
ExprOrSuper::Expr(Box::new(callee))
532+
} else {
533+
callee.fold_with(folder)
534+
};
535+
Expr::Call(CallExpr {
536+
span,
537+
callee,
538+
args: args.fold_with(folder),
539+
type_args,
540+
})
493541
}
494542

495543
Expr::Member(e) => {

ecmascript/transforms/module/tests/amd.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ obj[bar('bas')] = '123'",
3434
"define(['bar'], function(_bar) {
3535
'use strict';
3636
_bar = _interopRequireDefault(_bar);
37-
obj[_bar.default('bas')] = '123';
37+
obj[(0, _bar).default('bas')] = '123';
3838
});"
3939
);
4040

@@ -835,7 +835,7 @@ define(["exports", "./evens"], function (_exports, _evens) {
835835
_exports.isOdd = void 0;
836836
837837
function nextOdd(n) {
838-
return _evens.isEven(n) ? n + 1 : n + 2;
838+
return (0, _evens).isEven(n) ? n + 1 : n + 2;
839839
}
840840
841841
var isOdd = function (isEven) {

0 commit comments

Comments
 (0)