Fix typescript class properties pass (#951)

This commit is contained in:
강동윤 2020-08-10 01:22:15 +09:00 committed by GitHub
parent ca246d3df7
commit e1f5d681e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 119 additions and 38 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "swc_ecma_transforms"
version = "0.19.1"
version = "0.19.2"
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"

View File

@ -11,9 +11,9 @@ use crate::{
undefined, ExprFactory, ModuleItemLike, StmtLike,
},
};
use std::collections::HashSet;
use std::{collections::HashSet, mem::take};
use swc_atoms::JsWord;
use swc_common::{Mark, Spanned, DUMMY_SP};
use swc_common::{util::move_map::MoveMap, Mark, Spanned, DUMMY_SP};
use swc_ecma_ast::*;
use swc_ecma_visit::{Fold, FoldWith, VisitWith};
@ -281,6 +281,8 @@ impl ClassProperties {
let has_super = class.super_class.is_some();
let mut typescript_constructor_properties = vec![];
let (mut constructor_exprs, mut vars, mut extra_stmts, mut members, mut constructor) =
(vec![], vec![], vec![], vec![], None);
let mut used_names = vec![];
@ -562,10 +564,61 @@ impl ClassProperties {
})));
}
ClassMember::Constructor(c) => constructor = Some(c),
ClassMember::Constructor(mut c) => {
if self.typescript {
let store = |i: &Ident| {
Box::new(
AssignExpr {
span: DUMMY_SP,
left: PatOrExpr::Expr(Box::new(Expr::Member(MemberExpr {
span: DUMMY_SP,
obj: ThisExpr { span: DUMMY_SP }.as_obj(),
computed: false,
prop: Box::new(i.clone().into()),
}))),
op: op!("="),
right: Box::new(i.clone().into()),
}
.into(),
)
};
c.params = c.params.move_map(|mut param| match &mut param {
ParamOrTsParamProp::TsParamProp(p) => match &p.param {
TsParamPropParam::Ident(i) => {
typescript_constructor_properties.push(store(i));
ParamOrTsParamProp::Param(Param {
span: p.span,
decorators: take(&mut p.decorators),
pat: Pat::Ident(i.clone()),
})
}
TsParamPropParam::Assign(pat) => match &*pat.left {
Pat::Ident(i) => {
typescript_constructor_properties.push(store(i));
ParamOrTsParamProp::Param(Param {
span: p.span,
decorators: take(&mut p.decorators),
pat: Pat::Ident(i.clone()),
})
}
_ => param,
},
},
ParamOrTsParamProp::Param(_) => param,
});
}
constructor = Some(c);
}
}
}
let constructor_exprs = {
typescript_constructor_properties.extend(constructor_exprs);
typescript_constructor_properties
};
let constructor =
self.process_constructor(constructor, has_super, &used_names, constructor_exprs);
if let Some(c) = constructor {
@ -668,19 +721,9 @@ impl ClassProperties {
}
});
if let Some(mut c) = constructor {
if self.typescript {
// Append properties
c.body
.as_mut()
.unwrap()
.stmts
.extend(constructor_exprs.into_iter().map(|v| v.into_stmt()));
Some(c)
} else {
// Prepend properties
Some(inject_after_super(c, constructor_exprs))
}
if let Some(c) = constructor {
// Prepend properties
Some(inject_after_super(c, constructor_exprs))
} else {
None
}

View File

@ -1,5 +1,6 @@
#![cfg_attr(test, feature(test))]
#![recursion_limit = "1024"]
#![deny(unused)]
#[macro_use]
extern crate swc_ecma_utils;

View File

@ -705,12 +705,11 @@ to!(
test!(
::swc_ecma_parser::Syntax::Typescript(Default::default()),
|_| chain!(tr(), typescript_class_properties()),
|_| chain!(typescript_class_properties(), tr()),
issue_930_instance,
"class A {
b = this.a;
constructor(a){
this.a = a;
constructor(readonly a){
}
}",
"class A {
@ -723,7 +722,7 @@ test!(
test!(
::swc_ecma_parser::Syntax::Typescript(Default::default()),
|_| chain!(tr(), typescript_class_properties()),
|_| chain!(typescript_class_properties(), tr()),
issue_930_static,
"class A {
static b = 'foo';
@ -736,3 +735,46 @@ test!(
}
A.b = 'foo';"
);
test!(
::swc_ecma_parser::Syntax::Typescript(Default::default()),
|_| chain!(typescript_class_properties(), tr()),
typescript_001,
"class A {
foo = new Subject()
constructor() {
this.foo.subscribe()
}
}",
"class A {
constructor() {
this.foo = new Subject()
this.foo.subscribe()
}
}"
);
test!(
::swc_ecma_parser::Syntax::Typescript(Default::default()),
|_| chain!(typescript_class_properties(), tr()),
typescript_002,
"class A extends B {
foo = 'foo'
b = this.a;
constructor(readonly a) {
super()
this.foo.subscribe()
}
}",
"class A extends B {
constructor(a) {
super();
this.a = a;
this.foo = 'foo';
this.b = this.a;
this.foo.subscribe();
}
}"
);

View File

@ -1,6 +1,6 @@
{
"name": "@swc/core",
"version": "1.2.15",
"version": "1.2.16",
"description": "Super-fast alternative for babel",
"main": "./index.js",
"author": "강동윤 <kdy1997.dev@gmail.com>",

View File

@ -88,10 +88,6 @@ impl<'a, 'b, P: swc_ecma_visit::Fold> PassBuilder<'a, 'b, P> {
self.then(pass)
}
pub fn strip_typescript(self) -> PassBuilder<'a, 'b, impl swc_ecma_visit::Fold> {
self.then(typescript::strip())
}
pub fn target(mut self, target: JscTarget) -> Self {
self.target = target;
self
@ -133,7 +129,10 @@ impl<'a, 'b, P: swc_ecma_visit::Fold> PassBuilder<'a, 'b, P> {
// compat
let compat_pass = if let Some(env) = self.env {
Either::Left(swc_ecma_preset_env::preset_env(self.global_mark, env))
Either::Left(chain!(
Optional::new(typescript::strip(), syntax.typescript()),
swc_ecma_preset_env::preset_env(self.global_mark, env)
))
} else {
Either::Right(chain!(
Optional::new(
@ -144,17 +143,11 @@ impl<'a, 'b, P: swc_ecma_visit::Fold> PassBuilder<'a, 'b, P> {
compat::es2020::optional_chaining(),
self.target < JscTarget::Es2020
),
if syntax.typescript() {
Either::Left(Optional::new(
compat::es2020::typescript_class_properties(),
self.target < JscTarget::Es2020,
))
} else {
Either::Right(Optional::new(
compat::es2020::class_properties(),
self.target < JscTarget::Es2020,
))
},
Optional::new(
compat::es2020::class_properties(),
self.target < JscTarget::Es2020,
),
Optional::new(typescript::strip(), syntax.typescript()),
Optional::new(compat::es2018(), self.target <= JscTarget::Es2018),
Optional::new(compat::es2017(), self.target <= JscTarget::Es2017),
Optional::new(compat::es2016(), self.target <= JscTarget::Es2016),

View File

@ -18,6 +18,7 @@ use swc_ecma_ast::{Expr, ExprStmt, ModuleItem, Stmt};
pub use swc_ecma_parser::JscTarget;
use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax, TsConfig};
use swc_ecma_transforms::{
compat::es2020::typescript_class_properties,
const_modules, modules,
optimization::{simplifier, InlineGlobals, JsonParse},
pass::{noop, Optional},
@ -234,6 +235,7 @@ impl Options {
}),
syntax.decorators()
),
Optional::new(typescript_class_properties(), syntax.typescript()),
Optional::new(typescript::strip(), syntax.typescript()),
resolver_with_mark(root_mark),
const_modules,