mirror of
https://github.com/swc-project/swc.git
synced 2024-11-28 02:29:04 +03:00
Allow using properties with legacy decorators (#824)
This commit is contained in:
parent
d82e6ab69d
commit
3b1ebdd2e9
@ -761,7 +761,12 @@ impl<'a> Emitter<'a> {
|
|||||||
fn emit_ts_const_assertion(&mut self, n: &TsConstAssertion) -> Result {
|
fn emit_ts_const_assertion(&mut self, n: &TsConstAssertion) -> Result {
|
||||||
self.emit_leading_comments_of_pos(n.span().lo())?;
|
self.emit_leading_comments_of_pos(n.span().lo())?;
|
||||||
|
|
||||||
unimplemented!("emit_ts_const_assertion")
|
emit!(n.expr);
|
||||||
|
|
||||||
|
space!();
|
||||||
|
keyword!("as");
|
||||||
|
space!();
|
||||||
|
keyword!("const");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[emitter]
|
#[emitter]
|
||||||
|
@ -196,6 +196,7 @@ impl Fold<Decl> for Legacy {
|
|||||||
impl Legacy {
|
impl Legacy {
|
||||||
fn handle(&mut self, mut c: ClassExpr) -> Box<Expr> {
|
fn handle(&mut self, mut c: ClassExpr) -> Box<Expr> {
|
||||||
let cls_ident = private_ident!("_class");
|
let cls_ident = private_ident!("_class");
|
||||||
|
let cls_name = c.ident.clone();
|
||||||
|
|
||||||
self.uninitialized_vars.push(VarDeclarator {
|
self.uninitialized_vars.push(VarDeclarator {
|
||||||
span: DUMMY_SP,
|
span: DUMMY_SP,
|
||||||
@ -228,15 +229,44 @@ impl Legacy {
|
|||||||
// _class2.prototype)
|
// _class2.prototype)
|
||||||
|
|
||||||
let mut dec_exprs = vec![];
|
let mut dec_exprs = vec![];
|
||||||
|
let mut dec_inits = vec![];
|
||||||
for dec in m.function.decorators.into_iter() {
|
for dec in m.function.decorators.into_iter() {
|
||||||
let (i, aliased) = alias_if_required(&dec.expr, "_dec");
|
let (i, aliased) = alias_if_required(&dec.expr, "_dec");
|
||||||
if aliased {
|
if aliased {
|
||||||
self.initialized_vars.push(VarDeclarator {
|
self.uninitialized_vars.push(VarDeclarator {
|
||||||
span: DUMMY_SP,
|
span: DUMMY_SP,
|
||||||
name: Pat::Ident(i.clone()),
|
name: Pat::Ident(i.clone()),
|
||||||
init: Some(dec.expr),
|
init: None,
|
||||||
definite: false,
|
definite: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// We use _class.staticField instead of Person.staticField because while
|
||||||
|
// initializing the class,
|
||||||
|
//
|
||||||
|
// _dec = Debounce(Person.debounceTime)
|
||||||
|
//
|
||||||
|
// fails while
|
||||||
|
//
|
||||||
|
// _dec = Debounce(_class.debounceTime)
|
||||||
|
//
|
||||||
|
// works.
|
||||||
|
//
|
||||||
|
// See: https://github.com/swc-project/swc/issues/823
|
||||||
|
let right = if let Some(cls_name) = cls_name.clone() {
|
||||||
|
dec.expr.fold_with(&mut ClassFieldAccessConverter {
|
||||||
|
cls_name,
|
||||||
|
alias: cls_ident.clone(),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
dec.expr
|
||||||
|
};
|
||||||
|
|
||||||
|
dec_inits.push(box Expr::Assign(AssignExpr {
|
||||||
|
span: dec.span,
|
||||||
|
op: op!("="),
|
||||||
|
left: PatOrExpr::Pat(box Pat::Ident(i.clone())),
|
||||||
|
right,
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
dec_exprs.push(Some(i.as_arg()))
|
dec_exprs.push(Some(i.as_arg()))
|
||||||
@ -251,6 +281,8 @@ impl Legacy {
|
|||||||
_ => prop_name_to_expr_value(m.key.clone()),
|
_ => prop_name_to_expr_value(m.key.clone()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extra_exprs.extend(dec_inits);
|
||||||
|
|
||||||
extra_exprs.push(box Expr::Call(CallExpr {
|
extra_exprs.push(box Expr::Call(CallExpr {
|
||||||
span: DUMMY_SP,
|
span: DUMMY_SP,
|
||||||
callee,
|
callee,
|
||||||
@ -635,3 +667,38 @@ impl Legacy {
|
|||||||
expr
|
expr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ClassFieldAccessConverter {
|
||||||
|
cls_name: Ident,
|
||||||
|
/// `_class`
|
||||||
|
alias: Ident,
|
||||||
|
}
|
||||||
|
|
||||||
|
noop_fold_type!(ClassFieldAccessConverter);
|
||||||
|
|
||||||
|
impl Fold<MemberExpr> for ClassFieldAccessConverter {
|
||||||
|
fn fold(&mut self, node: MemberExpr) -> MemberExpr {
|
||||||
|
if node.computed {
|
||||||
|
MemberExpr {
|
||||||
|
obj: node.obj.fold_with(self),
|
||||||
|
prop: node.prop.fold_with(self),
|
||||||
|
..node
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MemberExpr {
|
||||||
|
obj: node.obj.fold_with(self),
|
||||||
|
..node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Fold<Ident> for ClassFieldAccessConverter {
|
||||||
|
fn fold(&mut self, node: Ident) -> Ident {
|
||||||
|
if node.sym == self.cls_name.sym && node.span.ctxt() == self.cls_name.span.ctxt() {
|
||||||
|
return self.alias.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -434,7 +434,7 @@ impl Strip {
|
|||||||
node
|
node
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_enum(&mut self, mut e: TsEnumDecl, stmts: &mut Vec<ModuleItem>) {
|
fn handle_enum(&mut self, e: TsEnumDecl, stmts: &mut Vec<ModuleItem>) {
|
||||||
/// Value does not contain TsLit::Bool
|
/// Value does not contain TsLit::Bool
|
||||||
type EnumValues = FxHashMap<Id, TsLit>;
|
type EnumValues = FxHashMap<Id, TsLit>;
|
||||||
|
|
||||||
@ -637,7 +637,7 @@ impl Strip {
|
|||||||
.collect::<Result<Vec<_>, _>>()
|
.collect::<Result<Vec<_>, _>>()
|
||||||
.unwrap_or_else(|_| panic!("invalid value for enum is detected"));
|
.unwrap_or_else(|_| panic!("invalid value for enum is detected"));
|
||||||
|
|
||||||
let is_all_str = members.iter().all(|(m, v)| match v {
|
let is_all_str = members.iter().all(|(_, v)| match v {
|
||||||
Expr::Lit(Lit::Str(..)) => true,
|
Expr::Lit(Lit::Str(..)) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
});
|
});
|
||||||
@ -671,7 +671,7 @@ impl Strip {
|
|||||||
stmts: members
|
stmts: members
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, (m, val))| {
|
.map(|(_, (m, val))| {
|
||||||
let value = match m.id {
|
let value = match m.id {
|
||||||
TsEnumMemberId::Str(s) => s,
|
TsEnumMemberId::Str(s) => s,
|
||||||
TsEnumMemberId::Ident(i) => Str {
|
TsEnumMemberId::Ident(i) => Str {
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
use swc_common::chain;
|
use swc_common::chain;
|
||||||
use swc_ecma_parser::{EsConfig, Syntax, TsConfig};
|
use swc_ecma_parser::{EsConfig, Syntax, TsConfig};
|
||||||
use swc_ecma_transforms::{
|
use swc_ecma_transforms::{
|
||||||
|
compat::es2015::classes::Classes,
|
||||||
pass::Pass,
|
pass::Pass,
|
||||||
proposals::{class_properties, decorators, decorators::Config},
|
proposals::{class_properties, decorators, decorators::Config},
|
||||||
resolver, typescript,
|
resolver, typescript,
|
||||||
@ -4203,3 +4204,132 @@ let Example = ((_class = class Example{
|
|||||||
}), _class);
|
}), _class);
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test!(
|
||||||
|
Syntax::Typescript(TsConfig {
|
||||||
|
decorators: true,
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
|_| chain!(typescript::strip(), decorators(Config { legacy: true })),
|
||||||
|
issue_823_1,
|
||||||
|
"import {Debounce} from 'lodash-decorators';
|
||||||
|
class Person {
|
||||||
|
private static debounceTime: number = 500 as const;
|
||||||
|
|
||||||
|
@Debounce(Person.debounceTime)
|
||||||
|
save() {
|
||||||
|
console.log('Hello World!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const p = new Person();
|
||||||
|
p.save();",
|
||||||
|
"var _class, _dec;
|
||||||
|
import { Debounce } from 'lodash-decorators';
|
||||||
|
let Person = ((_class = class Person {
|
||||||
|
static debounceTime = 500;
|
||||||
|
save() {
|
||||||
|
console.log('Hello World!');
|
||||||
|
}
|
||||||
|
}) || _class, _dec = Debounce(_class.debounceTime), _applyDecoratedDescriptor(_class.prototype, \
|
||||||
|
'save', [
|
||||||
|
_dec
|
||||||
|
], Object.getOwnPropertyDescriptor(_class.prototype, 'save'), _class.prototype), _class);
|
||||||
|
const p = new Person();
|
||||||
|
p.save();"
|
||||||
|
);
|
||||||
|
|
||||||
|
test!(
|
||||||
|
Syntax::Typescript(TsConfig {
|
||||||
|
decorators: true,
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
|_| chain!(
|
||||||
|
typescript::strip(),
|
||||||
|
decorators(Config { legacy: true }),
|
||||||
|
class_properties(),
|
||||||
|
// Classes::default(),
|
||||||
|
),
|
||||||
|
issue_823_2,
|
||||||
|
"import {Debounce} from 'lodash-decorators';
|
||||||
|
class Person {
|
||||||
|
private static debounceTime: number = 500 as const;
|
||||||
|
|
||||||
|
@Debounce(Person.debounceTime)
|
||||||
|
save() {
|
||||||
|
console.log('Hello World!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const p = new Person();
|
||||||
|
p.save();",
|
||||||
|
"var _class, _dec;
|
||||||
|
import { Debounce } from 'lodash-decorators';
|
||||||
|
let Person = ((_class = function() {
|
||||||
|
class Person {
|
||||||
|
save() {
|
||||||
|
console.log('Hello World!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_defineProperty(Person, 'debounceTime', 500);
|
||||||
|
return Person;
|
||||||
|
}()) || _class, _dec = Debounce(_class.debounceTime), _applyDecoratedDescriptor(_class.prototype, \
|
||||||
|
'save', [
|
||||||
|
_dec
|
||||||
|
], Object.getOwnPropertyDescriptor(_class.prototype, 'save'), _class.prototype), _class);
|
||||||
|
const p = new Person();
|
||||||
|
p.save();
|
||||||
|
"
|
||||||
|
);
|
||||||
|
|
||||||
|
test!(
|
||||||
|
Syntax::Typescript(TsConfig {
|
||||||
|
decorators: true,
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
|_| chain!(
|
||||||
|
typescript::strip(),
|
||||||
|
decorators(Config { legacy: true }),
|
||||||
|
class_properties(),
|
||||||
|
Classes::default(),
|
||||||
|
),
|
||||||
|
issue_823_3,
|
||||||
|
"import {Debounce} from 'lodash-decorators';
|
||||||
|
class Person {
|
||||||
|
private static debounceTime: number = 500 as const;
|
||||||
|
|
||||||
|
@Debounce(Person.debounceTime)
|
||||||
|
save() {
|
||||||
|
console.log('Hello World!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const p = new Person();
|
||||||
|
p.save();",
|
||||||
|
"var _class, _dec;
|
||||||
|
import { Debounce } from 'lodash-decorators';
|
||||||
|
let Person = ((_class = function() {
|
||||||
|
let Person = function() {
|
||||||
|
'use strict';
|
||||||
|
function Person() {
|
||||||
|
_classCallCheck(this, Person);
|
||||||
|
}
|
||||||
|
_createClass(Person, [
|
||||||
|
{
|
||||||
|
key: 'save',
|
||||||
|
value: function save() {
|
||||||
|
console.log('Hello World!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
return Person;
|
||||||
|
}();
|
||||||
|
_defineProperty(Person, 'debounceTime', 500);
|
||||||
|
return Person;
|
||||||
|
}()) || _class, _dec = Debounce(_class.debounceTime), _applyDecoratedDescriptor(_class.prototype, \
|
||||||
|
'save', [
|
||||||
|
_dec
|
||||||
|
], Object.getOwnPropertyDescriptor(_class.prototype, 'save'), _class.prototype), _class);
|
||||||
|
const p = new Person();
|
||||||
|
p.save();"
|
||||||
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user