Skip to content

Commit

Permalink
Fix bugs (#1132)
Browse files Browse the repository at this point in the history
swc_ecma_transforms:
 - Handle typescript class properties correctly. (#1122)
 - Handle optional chaining properly. (#1130)
 - Inject variables for nullisn coalescing in correct scope. (#1123)
  • Loading branch information
kdy1 authored Oct 4, 2020
1 parent 81490de commit aa95558
Show file tree
Hide file tree
Showing 7 changed files with 240 additions and 15 deletions.
4 changes: 2 additions & 2 deletions ecmascript/transforms/src/compat/es2020/class_properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ impl ClassProperties {
MemberExpr {
span: DUMMY_SP,
obj: ident.clone().as_obj(),
computed: false,
computed: prop.computed,
prop: key,
}
.into(),
Expand All @@ -460,7 +460,7 @@ impl ClassProperties {
MemberExpr {
span: DUMMY_SP,
obj: ThisExpr { span: DUMMY_SP }.as_obj(),
computed: false,
computed: prop.computed,
prop: key,
}
.into(),
Expand Down
10 changes: 10 additions & 0 deletions ecmascript/transforms/src/compat/es2020/nullish_coalescing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@ impl NullishCoalescing {
impl Fold for NullishCoalescing {
noop_fold_type!();

/// Prevents #1123
fn fold_block_stmt(&mut self, s: BlockStmt) -> BlockStmt {
s.fold_children_with(&mut NullishCoalescing::default())
}

/// Prevents #1123
fn fold_switch_case(&mut self, s: SwitchCase) -> SwitchCase {
s.fold_children_with(&mut NullishCoalescing::default())
}

fn fold_module_items(&mut self, n: Vec<ModuleItem>) -> Vec<ModuleItem> {
self.fold_stmt_like(n)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use super::*;
use swc_ecma_parser::{EsConfig, Syntax};
use crate::typescript::strip;
use swc_common::chain;
use swc_ecma_parser::{EsConfig, Syntax, TsConfig};

fn tr(_: ()) -> impl Fold {
nullish_coalescing()
Expand Down Expand Up @@ -106,3 +108,54 @@ function foo() {
"#
);

test!(
Syntax::Typescript(TsConfig {
..Default::default()
}),
|_| chain!(strip(), tr(())),
issue_1123_1,
r#"
interface SuperSubmission {
[key: string]: any;
}
const normalizedQuestionSet: any = {};
const submissions: SuperSubmission[] = (
normalizedQuestionSet.submissionIds ?? []
).map(
(id, index): SuperSubmission => {
const submission = normalizedQuestionSet.submissions?.[id];
const submissionAnswers = (submission.answers ?? []).map(
(answerId) => normalizedQuestionSet.answers?.[answerId]
);
console.log(id, index);
return {
type: "super-submission",
};
}
);
console.log(submissions);
"#,
r#"
const normalizedQuestionSet = {
};
var _submissionIds;
const submissions = ((_submissionIds = normalizedQuestionSet.submissionIds) !== null && _submissionIds !== void 0 ? _submissionIds : []).map((id, index)=>{
const submission = normalizedQuestionSet.submissions?.[id];
var _answers;
const submissionAnswers = ((_answers = submission.answers) !== null && _answers !== void 0 ? _answers : []).map((answerId)=>normalizedQuestionSet.answers?.[answerId]
);
console.log(id, index);
return {
type: "super-submission"
};
});
console.log(submissions);
"#
);
50 changes: 41 additions & 9 deletions ecmascript/transforms/src/compat/es2020/opt_chaining.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ impl Fold for OptChaining {
Ok(v) => v,
Err(v) => v,
},
Expr::Call(e) => validate!(self.handle_call(e)),
Expr::Call(e) => match self.handle_call(e).map(Expr::Cond) {
Ok(v) => v,
Err(v) => v,
},
_ => e,
};

Expand Down Expand Up @@ -129,28 +132,28 @@ impl OptChaining {
}

/// Only called from [Fold].
fn handle_call(&mut self, e: CallExpr) -> Expr {
fn handle_call(&mut self, e: CallExpr) -> Result<CondExpr, Expr> {
match e.callee {
ExprOrSuper::Expr(callee) if callee.is_opt_chain() => {
let callee = callee.opt_chain().unwrap();
let expr = self.unwrap(callee);

return CondExpr {
return Ok(CondExpr {
span: DUMMY_SP,
alt: Box::new(Expr::Call(CallExpr {
callee: ExprOrSuper::Expr(expr.alt),
..e
})),
..expr
}
.into();
});
}
ExprOrSuper::Expr(callee) if callee.is_member() => {
let callee = callee.member().unwrap();
let callee = self.handle_member(callee);

return match callee {
Ok(expr) => Expr::Cond(CondExpr {
Ok(expr) => Ok(CondExpr {
span: e.span,
alt: Box::new(Expr::Call(CallExpr {
span: DUMMY_SP,
callee: expr.alt.as_callee(),
Expand All @@ -159,16 +162,16 @@ impl OptChaining {
})),
..expr
}),
Err(callee) => Expr::Call(CallExpr {
Err(callee) => Err(Expr::Call(CallExpr {
callee: callee.as_callee(),
..e
}),
})),
};
}
_ => {}
}

Expr::Call(e)
Err(Expr::Call(e))
}

/// Returns `Ok` if it handled optional chaining.
Expand Down Expand Up @@ -202,6 +205,35 @@ impl OptChaining {
_ => ExprOrSuper::Expr(Box::new(obj)),
}
}

ExprOrSuper::Expr(obj) if obj.is_call() => {
let obj = obj.call().unwrap();
let obj = self.handle_call(obj).map(Expr::Cond);
let (obj, handled) = match obj {
Ok(v) => (v, true),
Err(v) => (v, false),
};

match obj {
Expr::Cond(obj) => {
let cond_expr = CondExpr {
span: DUMMY_SP,
alt: Box::new(Expr::Member(MemberExpr {
obj: ExprOrSuper::Expr(obj.alt),
..e
})),
..obj
};
//
return if handled {
Ok(cond_expr)
} else {
Err(Expr::Cond(cond_expr))
};
}
_ => ExprOrSuper::Expr(Box::new(obj)),
}
}
_ => e.obj,
};

Expand Down
106 changes: 105 additions & 1 deletion ecmascript/transforms/tests/es2020_class_properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use swc_ecma_transforms::{
es2015::{arrow, block_scoping, classes, function_name},
es2016::exponentation,
es2017::async_to_generator,
es2020::class_properties,
es2020::{class_properties, typescript_class_properties},
es3::reserved_words,
},
proposals::decorators,
Expand Down Expand Up @@ -4858,3 +4858,107 @@ expect(foo.y).toBe('bar');
"#
);

test!(
syntax(),
|_| typescript_class_properties(),
issue_1122_1,
"
const identifier = 'bar';
class Foo {
[identifier] = 5;
}
",
"
const identifier = \"bar\";
class Foo {
constructor(){
this[identifier] = 5;
}
}
"
);

test!(
syntax(),
|_| typescript_class_properties(),
issue_1122_2,
"
const identifier = 'bar';
class Foo {
identifier = 5;
}
",
"
const identifier = \"bar\";
class Foo {
constructor(){
this.identifier = 5;
}
}
"
);

test!(
syntax(),
|_| typescript_class_properties(),
issue_1122_3,
"
const identifier = 'bar';
class Foo {
['identifier'] = 5;
}
",
"
const identifier = \"bar\";
class Foo {
constructor(){
this[\"identifier\"] = 5;
}
}
"
);

test!(
syntax(),
|_| typescript_class_properties(),
issue_1122_4,
"
const identifier = 'bar';
class Foo {
static [identifier] = 5;
}
",
"
const identifier = \"bar\";
class Foo {
}
Foo[identifier] = 5;
"
);

test!(
syntax(),
|_| typescript_class_properties(),
issue_1122_5,
"
const identifier = 'bar';
class Foo {
static identifier = 5;
}
",
"
const identifier = \"bar\";
class Foo {
}
Foo.identifier = 5;
"
);
28 changes: 27 additions & 1 deletion ecmascript/transforms/tests/es2020_optional_chaining.rs
Original file line number Diff line number Diff line change
Expand Up @@ -636,8 +636,34 @@ test!(
expect(obj?.a?.b?.c()).toBe(2)
",
"
var ref, ref1;
var ref, ref1;
expect(obj === null || obj === void 0 ? void 0 : (ref = obj.a) === null || ref === void 0 ? void 0 \
: (ref1 = ref.b) === null || ref1 === void 0 ? void 0 : ref1.c()).toBe(2);
"
);

test!(
syntax(),
|_| tr(()),
issue_1130_1,
"
const result = data?.filter(item => Math.random() > 0.5).map(item => JSON.stringify(item));
",
"
const result = data === null || data === void 0 ? void 0 : data.filter(item => Math.random() > \
0.5).map(item => JSON.stringify(item));
"
);

test!(
syntax(),
|_| tr(()),
issue_1130_2,
"
const r = d?.filter(i => Math.random() > 0.5).map(i => JSON.stringify(i));
",
"
const r = d === null || d === void 0 ? void 0 : d.filter(i => Math.random() > 0.5).map(i => \
JSON.stringify(i));
"
);
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@swc/core",
"version": "1.2.34",
"version": "1.2.35",
"description": "Super-fast alternative for babel",
"homepage": "https://swc.rs",
"main": "./index.js",
Expand Down

0 comments on commit aa95558

Please sign in to comment.