Skip to content

Commit 0586c73

Browse files
authored
Fix bugs (#1143)
swc_ecma_transforms: - fixer: Fix conditional expression in await expressions. (#1133) - optional_chaining: Fix call expression. (#1136) - hygiene: Fix codegen of computed keys. (#1140)
1 parent e4ddfcc commit 0586c73

File tree

9 files changed

+124
-18
lines changed

9 files changed

+124
-18
lines changed

ecmascript/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ edition = "2018"
66
license = "Apache-2.0/MIT"
77
name = "swc_ecmascript"
88
repository = "https://github.com/swc-project/swc.git"
9-
version = "0.9.0"
9+
version = "0.9.1"
1010

1111
[features]
1212
codegen = ["swc_ecma_codegen"]

ecmascript/transforms/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ edition = "2018"
66
license = "Apache-2.0/MIT"
77
name = "swc_ecma_transforms"
88
repository = "https://github.com/swc-project/swc.git"
9-
version = "0.25.0"
9+
version = "0.25.1"
1010

1111
[features]
1212
const-modules = ["dashmap"]

ecmascript/transforms/src/compat/es2020/opt_chaining.rs

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::{
22
perf::Check,
33
util::{prepend, undefined, ExprFactory, StmtLike},
44
};
5-
use std::{fmt::Debug, iter::once, mem};
5+
use std::{iter::once, mem};
66
use swc_common::{Spanned, DUMMY_SP};
77
use swc_ecma_ast::*;
88
use swc_ecma_transforms_macros::fast_path;
@@ -13,9 +13,10 @@ pub fn optional_chaining() -> impl Fold {
1313
OptChaining::default()
1414
}
1515

16-
#[derive(Debug, Default)]
16+
#[derive(Default)]
1717
struct OptChaining {
18-
vars: Vec<VarDeclarator>,
18+
vars_without_init: Vec<VarDeclarator>,
19+
vars_with_init: Vec<VarDeclarator>,
1920
}
2021

2122
#[fast_path(ShouldWork)]
@@ -56,24 +57,39 @@ impl OptChaining {
5657
Vec<T>: FoldWith<Self>,
5758
{
5859
// This is to support nested block statements
59-
let old = mem::replace(&mut self.vars, vec![]);
60+
let old_no_init = mem::replace(&mut self.vars_without_init, vec![]);
61+
let old_init = mem::replace(&mut self.vars_with_init, vec![]);
62+
63+
let mut new: Vec<T> = vec![];
6064

61-
let mut stmts = stmts.fold_children_with(self);
65+
for stmt in stmts {
66+
let stmt = stmt.fold_with(self);
67+
if !self.vars_with_init.is_empty() {
68+
new.push(T::from_stmt(Stmt::Decl(Decl::Var(VarDecl {
69+
span: DUMMY_SP,
70+
declare: false,
71+
kind: VarDeclKind::Var,
72+
decls: mem::replace(&mut self.vars_with_init, vec![]),
73+
}))));
74+
}
75+
new.push(stmt);
76+
}
6277

63-
if !self.vars.is_empty() {
78+
if !self.vars_without_init.is_empty() {
6479
prepend(
65-
&mut stmts,
80+
&mut new,
6681
T::from_stmt(Stmt::Decl(Decl::Var(VarDecl {
6782
span: DUMMY_SP,
6883
declare: false,
6984
kind: VarDeclKind::Var,
70-
decls: mem::replace(&mut self.vars, vec![]),
85+
decls: mem::replace(&mut self.vars_without_init, vec![]),
7186
}))),
7287
);
7388
}
7489

75-
self.vars = old;
76-
stmts
90+
self.vars_without_init = old_no_init;
91+
self.vars_with_init = old_init;
92+
new
7793
}
7894
}
7995

@@ -335,7 +351,7 @@ impl OptChaining {
335351
Expr::Ident(..) => (Box::new(obj.clone()), Box::new(obj), e.expr),
336352
_ => {
337353
let i = private_ident!(obj_span, "ref");
338-
self.vars.push(VarDeclarator {
354+
self.vars_without_init.push(VarDeclarator {
339355
span: obj_span,
340356
definite: false,
341357
name: Pat::Ident(i.clone()),
@@ -420,7 +436,7 @@ impl OptChaining {
420436
"_obj",
421437
);
422438
let obj = if !is_super_access && aliased {
423-
self.vars.push(VarDeclarator {
439+
self.vars_with_init.push(VarDeclarator {
424440
span: obj_span,
425441
definite: false,
426442
name: Pat::Ident(this_obj.clone()),
@@ -432,7 +448,7 @@ impl OptChaining {
432448
obj
433449
};
434450
let i = private_ident!(obj_span, "ref");
435-
self.vars.push(VarDeclarator {
451+
self.vars_without_init.push(VarDeclarator {
436452
span: obj_span,
437453
definite: false,
438454
name: Pat::Ident(i.clone()),

ecmascript/transforms/src/fixer.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,18 @@ impl VisitMut for Fixer<'_> {
8080
self.ctx = old;
8181
}
8282

83+
fn visit_mut_await_expr(&mut self, expr: &mut AwaitExpr) {
84+
let old = self.ctx;
85+
self.ctx = Context::ForcedExpr { is_var_decl: false };
86+
expr.arg.visit_mut_with(self);
87+
self.ctx = old;
88+
89+
match &*expr.arg {
90+
Expr::Cond(..) => self.wrap(&mut expr.arg),
91+
_ => {}
92+
}
93+
}
94+
8395
fn visit_mut_call_expr(&mut self, node: &mut CallExpr) {
8496
let old = self.ctx;
8597
self.ctx = Context::ForcedExpr { is_var_decl: false };
@@ -970,4 +982,11 @@ var store = global[SHARED] || (global[SHARED] = {});
970982
);
971983

972984
identical!(issue_1093, "const x = (fnA || fnB)();");
985+
986+
identical!(
987+
issue_1133,
988+
"async function foo() {
989+
const item = await (data === null || data === void 0 ? void 0 : data.foo());
990+
}"
991+
);
973992
}

ecmascript/transforms/src/hygiene/ops.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ impl<'a> VisitMut for Operator<'a> {
204204
}
205205

206206
fn visit_mut_key_value_prop(&mut self, p: &mut KeyValueProp) {
207+
p.key.visit_mut_with(self);
207208
p.value.visit_mut_with(self);
208209
}
209210

ecmascript/transforms/src/resolver/tests.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1679,3 +1679,38 @@ to!(
16791679
}
16801680
"
16811681
);
1682+
1683+
to!(
1684+
issue_1140,
1685+
r#"
1686+
const categories = [{ key: "apple" }, { key: "banana" }, { key: "strawberry" }];
1687+
1688+
const item = "some item";
1689+
1690+
const catNames = categories.reduce((a, item) => {
1691+
return { ...a, [item.key.toString()]: item };
1692+
}, {});
1693+
"#,
1694+
r#"
1695+
var categories = [
1696+
{
1697+
key: "apple"
1698+
},
1699+
{
1700+
key: "banana"
1701+
},
1702+
{
1703+
key: "strawberry"
1704+
}
1705+
];
1706+
var item = "some item";
1707+
var catNames = categories.reduce((a, item1)=>{
1708+
return {
1709+
...a,
1710+
[item1.key.toString()]: item1
1711+
};
1712+
}, {
1713+
});
1714+
1715+
"#
1716+
);

ecmascript/transforms/tests/es2020_optional_chaining.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,3 +667,38 @@ const r = d === null || d === void 0 ? void 0 : d.filter(i => Math.random() > 0.
667667
JSON.stringify(i));
668668
"
669669
);
670+
671+
test!(
672+
syntax(),
673+
|_| tr(()),
674+
issue_1133_1,
675+
"
676+
async function foo() {
677+
const item = await data?.foo();
678+
}
679+
",
680+
"
681+
async function foo() {
682+
const item = await (data === null || data === void 0 ? void 0 : data.foo());
683+
}
684+
"
685+
);
686+
687+
test!(
688+
syntax(),
689+
|_| tr(()),
690+
issue_1136_1,
691+
"
692+
const PATCHES = new Map();
693+
694+
const ident = 'foo';
695+
const patch = PATCHES.get(ident)?.();
696+
",
697+
"
698+
var ref;
699+
const PATCHES = new Map();
700+
const ident = \"foo\";
701+
var _obj = PATCHES.get(ident);
702+
const patch = (ref = _obj) === null || ref === void 0 ? void 0 : ref.call(_obj);
703+
"
704+
);

ecmascript/transforms/tests/modules_umd.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1908,7 +1908,7 @@ test!(
19081908
})(this, function() {
19091909
\"use strict\";
19101910
async function foo() {
1911-
await exports === undefined ? new Promise(function(resolve, reject) {
1911+
await (exports === undefined ? new Promise(function(resolve, reject) {
19121912
require([
19131913
\"foo\"
19141914
], function(dep) {
@@ -1918,7 +1918,7 @@ test!(
19181918
});
19191919
}) : Promise.resolve().then(function() {
19201920
return require(\"foo\");
1921-
});
1921+
}));
19221922
}
19231923
});
19241924
",

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@swc/core",
3-
"version": "1.2.35",
3+
"version": "1.2.36",
44
"description": "Super-fast alternative for babel",
55
"homepage": "https://swc.rs",
66
"main": "./index.js",

0 commit comments

Comments
 (0)