diff --git a/ecmascript/Cargo.toml b/ecmascript/Cargo.toml index d9f7296e55c3..9a8f4c3a240d 100644 --- a/ecmascript/Cargo.toml +++ b/ecmascript/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "swc_ecmascript" -version = "0.2.0" +version = "0.3.0" authors = ["강동윤 "] license = "Apache-2.0/MIT" repository = "https://github.com/swc-project/swc.git" @@ -20,7 +20,7 @@ swc_ecma_ast = { version = "0.28.0", path ="./ast" } swc_ecma_codegen = { version = "0.31.0", path ="./codegen", optional = true } swc_ecma_parser = { version = "0.33.0", path ="./parser", optional = true } swc_ecma_utils = { version = "0.17.0", path ="./utils", optional = true } -swc_ecma_transforms = { version = "0.18.0", path ="./transforms", optional = true } +swc_ecma_transforms = { version = "0.19.0", path ="./transforms", optional = true } swc_ecma_visit = { version = "0.13.0", path ="./visit", optional = true } [dev-dependencies] diff --git a/ecmascript/transforms/Cargo.toml b/ecmascript/transforms/Cargo.toml index e3b2d285b1d8..25f2915f12dc 100644 --- a/ecmascript/transforms/Cargo.toml +++ b/ecmascript/transforms/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "swc_ecma_transforms" -version = "0.18.1" +version = "0.19.0" authors = ["강동윤 "] license = "Apache-2.0/MIT" repository = "https://github.com/swc-project/swc.git" diff --git a/ecmascript/transforms/src/proposals/decorators.rs b/ecmascript/transforms/src/proposals/decorators.rs index 22cce50445cc..d0c86746a637 100644 --- a/ecmascript/transforms/src/proposals/decorators.rs +++ b/ecmascript/transforms/src/proposals/decorators.rs @@ -1,4 +1,3 @@ -use self::legacy::Legacy; use crate::util::{ alias_ident_for, constructor::inject_after_super, prop_name_to_expr_value, undefined, ExprFactory, IdentExt, @@ -55,8 +54,11 @@ mod usage; /// ``` pub fn decorators(c: Config) -> impl Fold { if c.legacy { - Either::Left(Legacy::default()) + Either::Left(self::legacy::new(c.emit_metadata)) } else { + if c.emit_metadata { + unimplemented!("emitting decorator metadata while using new proposal") + } Either::Right(Decorators { is_in_strict: false, }) @@ -64,8 +66,11 @@ pub fn decorators(c: Config) -> impl Fold { } #[derive(Debug, Default, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct Config { pub legacy: bool, + #[serde(default)] + pub emit_metadata: bool, } #[derive(Debug, Default)] diff --git a/ecmascript/transforms/src/proposals/decorators/legacy.rs b/ecmascript/transforms/src/proposals/decorators/legacy.rs index 7f36851d5ae4..f26160506ff0 100644 --- a/ecmascript/transforms/src/proposals/decorators/legacy.rs +++ b/ecmascript/transforms/src/proposals/decorators/legacy.rs @@ -1,3 +1,4 @@ +use self::metadata::{Metadata, ParamMetadata}; use super::usage::DecoratorFinder; use crate::util::{ alias_if_required, default_constructor, prepend, prop_name_to_expr_value, undefined, @@ -9,13 +10,25 @@ use swc_common::{util::move_map::MoveMap, DUMMY_SP}; use swc_ecma_ast::*; use swc_ecma_visit::{Fold, FoldWith, VisitWith}; -#[derive(Debug, Default)] +mod metadata; + +#[derive(Debug)] pub(super) struct Legacy { + metadata: bool, uninitialized_vars: Vec, initialized_vars: Vec, exports: Vec, } +pub(super) fn new(metadata: bool) -> Legacy { + Legacy { + metadata, + uninitialized_vars: Default::default(), + initialized_vars: Default::default(), + exports: Default::default(), + } +} + noop_fold_type!(Legacy); impl Fold for Legacy { @@ -197,6 +210,14 @@ impl Legacy { impl Legacy { fn handle(&mut self, mut c: ClassExpr) -> Box { + if self.metadata { + let i = c.ident.clone(); + + c = c.fold_with(&mut ParamMetadata).fold_with(&mut Metadata { + class_name: i.as_ref(), + }); + } + let cls_ident = private_ident!("_class"); let cls_name = c.ident.clone(); @@ -663,12 +684,13 @@ impl Legacy { })); let expr = self.apply( + &cls_ident, if extra_exprs.is_empty() { var_init } else { extra_exprs.insert(0, var_init); // Return value. - extra_exprs.push(Box::new(Expr::Ident(cls_ident))); + extra_exprs.push(Box::new(Expr::Ident(cls_ident.clone()))); Box::new(Expr::Seq(SeqExpr { span: DUMMY_SP, @@ -682,7 +704,12 @@ impl Legacy { } /// Apply class decorators. - fn apply(&mut self, mut expr: Box, decorators: Vec) -> Box { + fn apply( + &mut self, + class_ident: &Ident, + mut expr: Box, + decorators: Vec, + ) -> Box { for dec in decorators.into_iter().rev() { let (i, aliased) = alias_if_required(&dec.expr, "_dec"); if aliased { @@ -694,12 +721,27 @@ impl Legacy { }); } - expr = Box::new(Expr::Call(CallExpr { + let dec_call_expr = Box::new(Expr::Call(CallExpr { span: DUMMY_SP, callee: i.as_callee(), args: vec![expr.as_arg()], type_args: None, })); + + // _class = dec(_class = funciton() {}) || _class + let class_expr = Box::new(Expr::Assign(AssignExpr { + span: DUMMY_SP, + left: PatOrExpr::Pat(Box::new(Pat::Ident(class_ident.clone()))), + op: op!("="), + right: Box::new(Expr::Bin(BinExpr { + span: DUMMY_SP, + left: dec_call_expr, + op: op!("||"), + right: Box::new(Expr::Ident(class_ident.clone())), + })), + })); + + expr = class_expr; } expr diff --git a/ecmascript/transforms/src/proposals/decorators/legacy/metadata.rs b/ecmascript/transforms/src/proposals/decorators/legacy/metadata.rs new file mode 100644 index 000000000000..9b955f5c763a --- /dev/null +++ b/ecmascript/transforms/src/proposals/decorators/legacy/metadata.rs @@ -0,0 +1,502 @@ +use swc_common::{util::move_map::MoveMap, Spanned, DUMMY_SP}; +use swc_ecma_ast::*; +use swc_ecma_utils::{undefined, ExprFactory}; +use swc_ecma_visit::{Fold, FoldWith}; + +/// https://github.com/leonardfactory/babel-plugin-transform-typescript-metadata/blob/master/src/parameter/parameterVisitor.ts +pub(super) struct ParamMetadata; + +impl Fold for ParamMetadata { + fn fold_class(&mut self, mut cls: Class) -> Class { + cls = cls.fold_children_with(self); + let mut decorators = cls.decorators; + + cls.body = cls.body.move_map(|m| match m { + ClassMember::Constructor(mut c) => { + for (idx, param) in c.params.iter_mut().enumerate() { + // + match param { + ParamOrTsParamProp::TsParamProp(p) => { + for decorator in p.decorators.drain(..) { + let new_dec = + self.create_param_decorator(idx, decorator.expr, true); + decorators.push(new_dec); + } + } + ParamOrTsParamProp::Param(param) => { + for decorator in param.decorators.drain(..) { + let new_dec = + self.create_param_decorator(idx, decorator.expr, true); + decorators.push(new_dec); + } + } + } + } + + ClassMember::Constructor(c) + } + _ => m, + }); + cls.decorators = decorators; + + cls + } + + fn fold_class_method(&mut self, mut m: ClassMethod) -> ClassMethod { + for (idx, param) in m.function.params.iter_mut().enumerate() { + for decorator in param.decorators.drain(..) { + let new_dec = self.create_param_decorator(idx, decorator.expr, false); + m.function.decorators.push(new_dec); + } + } + + m + } +} + +impl ParamMetadata { + fn create_param_decorator( + &self, + param_index: usize, + decorator_expr: Box, + is_constructor: bool, + ) -> Decorator { + Decorator { + span: DUMMY_SP, + expr: Box::new(Expr::Fn(FnExpr { + ident: None, + function: Function { + params: vec![ + Param { + span: DUMMY_SP, + decorators: Default::default(), + pat: Pat::Ident(quote_ident!("target")), + }, + Param { + span: DUMMY_SP, + decorators: Default::default(), + pat: Pat::Ident(quote_ident!("target")), + }, + ], + body: Some(BlockStmt { + span: DUMMY_SP, + stmts: vec![Stmt::Return(ReturnStmt { + span: DUMMY_SP, + arg: Some(Box::new(Expr::Call(CallExpr { + span: DUMMY_SP, + callee: decorator_expr.as_callee(), + args: vec![ + quote_ident!("target").as_arg(), + if is_constructor { + quote_ident!("undefined").as_arg() + } else { + quote_ident!("key").as_arg() + }, + Lit::Num(Number { + span: DUMMY_SP, + value: param_index as _, + }) + .as_arg(), + ], + type_args: Default::default(), + }))), + })], + }), + decorators: Default::default(), + span: Default::default(), + is_generator: Default::default(), + is_async: Default::default(), + type_params: Default::default(), + return_type: Default::default(), + }, + })), + } + } +} + +/// https://github.com/leonardfactory/babel-plugin-transform-typescript-metadata/blob/master/src/metadata/metadataVisitor.ts +pub(super) struct Metadata<'a> { + pub(super) class_name: Option<&'a Ident>, +} + +impl Fold for Metadata<'_> { + fn fold_class(&mut self, mut c: Class) -> Class { + c = c.fold_children_with(self); + + if c.decorators.is_empty() { + return c; + } + + let constructor = c.body.iter().find_map(|m| match m { + ClassMember::Constructor(c) => Some(c), + _ => None, + }); + if constructor.is_none() { + return c; + } + + { + let dec = self + .create_metadata_design_decorator("design:type", quote_ident!("Function").as_arg()); + c.decorators.push(dec); + } + { + let dec = self.create_metadata_design_decorator( + "design:paramtypes", + ArrayLit { + span: DUMMY_SP, + elems: constructor + .as_ref() + .unwrap() + .params + .iter() + .map(|v| match v { + ParamOrTsParamProp::TsParamProp(p) => { + let ann = match &p.param { + TsParamPropParam::Ident(i) => i.type_ann.as_ref(), + TsParamPropParam::Assign(a) => get_type_ann_of_pat(&a.left), + }; + Some(serialize_type(self.class_name, ann).as_arg()) + } + ParamOrTsParamProp::Param(p) => Some( + serialize_type(self.class_name, get_type_ann_of_pat(&p.pat)) + .as_arg(), + ), + }) + .collect(), + } + .as_arg(), + ); + c.decorators.push(dec); + } + c + } + + fn fold_class_method(&mut self, mut m: ClassMethod) -> ClassMethod { + if m.function.decorators.is_empty() { + return m; + } + + { + let dec = self + .create_metadata_design_decorator("design:type", quote_ident!("Function").as_arg()); + m.function.decorators.push(dec); + } + { + let dec = self.create_metadata_design_decorator( + "design:paramtypes", + ArrayLit { + span: DUMMY_SP, + elems: m + .function + .params + .iter() + .map(|v| { + Some( + serialize_type(self.class_name, get_type_ann_of_pat(&v.pat)) + .as_arg(), + ) + }) + .collect(), + } + .as_arg(), + ); + m.function.decorators.push(dec); + } + m + } + + fn fold_class_prop(&mut self, mut p: ClassProp) -> ClassProp { + if p.decorators.is_empty() { + return p; + } + + if p.type_ann.is_none() { + return p; + } + + let dec = self.create_metadata_design_decorator( + "design:type", + serialize_type(self.class_name, p.type_ann.as_ref()).as_arg(), + ); + p.decorators.push(dec); + + p + } +} + +impl Metadata<'_> { + fn create_metadata_design_decorator(&self, design: &str, type_arg: ExprOrSpread) -> Decorator { + Decorator { + span: DUMMY_SP, + expr: Box::new(Expr::Call(CallExpr { + span: DUMMY_SP, + callee: member_expr!(DUMMY_SP, Reflect.metadata).as_callee(), + args: vec![ + Str { + span: DUMMY_SP, + value: design.into(), + has_escape: false, + } + .as_arg(), + type_arg, + ], + + type_args: Default::default(), + })), + } + } +} + +fn serialize_type(class_name: Option<&Ident>, param: Option<&TsTypeAnn>) -> Expr { + fn serialize_type_ref(class_name: &str, ty: &TsTypeRef) -> Expr { + match &ty.type_name { + // We should omit references to self (class) since it will throw a ReferenceError at + // runtime due to babel transpile output. + TsEntityName::Ident(i) if &*i.sym == class_name => { + return quote_ident!("Object").into() + } + _ => {} + } + + let member_expr = ts_entity_to_member_expr(&ty.type_name); + + // We don't know if type is just a type (interface, etc.) or a concrete value + // (class, etc.) + // + // `typeof` operator allows us to use the expression even if it is not defined, + // fallback is just `Object`. + + Expr::Cond(CondExpr { + span: DUMMY_SP, + test: Box::new(Expr::Bin(BinExpr { + span: DUMMY_SP, + left: Box::new(Expr::Unary(UnaryExpr { + span: DUMMY_SP, + op: op!("typeof"), + arg: Box::new(member_expr.clone()), + })), + op: op!("==="), + right: undefined(DUMMY_SP), + })), + cons: Box::new(quote_ident!("Object").into()), + alt: Box::new(member_expr), + }) + } + + fn serialize_type_list(class_name: &str, types: &[Box]) -> Expr { + let mut u = None; + + for ty in types { + // Skip parens if need be + let ty = match &**ty { + TsType::TsParenthesizedType(ty) => &ty.type_ann, + _ => ty, + }; + + match &**ty { + // Always elide `never` from the union/intersection if possible + TsType::TsKeywordType(TsKeywordType { + kind: TsKeywordTypeKind::TsNeverKeyword, + .. + }) => { + continue; + } + + // Elide null and undefined from unions for metadata, just like what we did prior to + // the implementation of strict null checks + TsType::TsKeywordType(TsKeywordType { + kind: TsKeywordTypeKind::TsNullKeyword, + .. + }) + | TsType::TsKeywordType(TsKeywordType { + kind: TsKeywordTypeKind::TsUndefinedKeyword, + .. + }) => { + continue; + } + + _ => {} + } + + let item = serialize_type_node(class_name, &ty); + + // One of the individual is global object, return immediately + match item { + Expr::Ident(Ident { + sym: js_word!("Object"), + .. + }) => return item, + _ => {} + } + + // If there exists union that is not void 0 expression, check if the + // the common type is identifier. anything more complex + // and we will just default to Object + + // + match &u { + None => { + u = Some(item); + } + + Some(prev) => { + // Check for different types + match prev { + Expr::Ident(prev) => match &item { + Expr::Ident(item) if prev.sym == item.sym => {} + _ => return quote_ident!("Object").into(), + }, + + _ => return quote_ident!("Object").into(), + } + } + } + } + + *undefined(DUMMY_SP) + } + + fn serialize_type_node(class_name: &str, ty: &TsType) -> Expr { + let span = ty.span(); + match ty { + TsType::TsKeywordType(TsKeywordType { + kind: TsKeywordTypeKind::TsVoidKeyword, + .. + }) + | TsType::TsKeywordType(TsKeywordType { + kind: TsKeywordTypeKind::TsUndefinedKeyword, + .. + }) + | TsType::TsKeywordType(TsKeywordType { + kind: TsKeywordTypeKind::TsNullKeyword, + .. + }) + | TsType::TsKeywordType(TsKeywordType { + kind: TsKeywordTypeKind::TsNeverKeyword, + .. + }) => return *undefined(span), + + TsType::TsParenthesizedType(ty) => serialize_type_node(class_name, &*ty.type_ann), + + TsType::TsFnOrConstructorType(_) => quote_ident!("Function").into(), + + TsType::TsArrayType(_) | TsType::TsTupleType(_) => quote_ident!("Array").into(), + + TsType::TsLitType(TsLitType { + lit: TsLit::Bool(..), + .. + }) + | TsType::TsTypePredicate(_) + | TsType::TsKeywordType(TsKeywordType { + kind: TsKeywordTypeKind::TsBooleanKeyword, + .. + }) => quote_ident!("Boolean").into(), + + TsType::TsLitType(TsLitType { + lit: TsLit::Str(..), + .. + }) + | TsType::TsKeywordType(TsKeywordType { + kind: TsKeywordTypeKind::TsStringKeyword, + .. + }) => quote_ident!("String").into(), + + TsType::TsKeywordType(TsKeywordType { + kind: TsKeywordTypeKind::TsObjectKeyword, + .. + }) => quote_ident!("Object").into(), + + TsType::TsLitType(TsLitType { + lit: TsLit::Number(..), + .. + }) + | TsType::TsKeywordType(TsKeywordType { + kind: TsKeywordTypeKind::TsNumberKeyword, + .. + }) + | TsType::TsKeywordType(TsKeywordType { + kind: TsKeywordTypeKind::TsBigIntKeyword, + .. + }) => quote_ident!("Number").into(), + + TsType::TsLitType(ty) => { + // TODO: Proper error reporting + panic!("Bad type for decoration: {:?}", ty); + } + + TsType::TsKeywordType(TsKeywordType { + kind: TsKeywordTypeKind::TsSymbolKeyword, + .. + }) => quote_ident!("Symbol").into(), + + TsType::TsTypeQuery(_) + | TsType::TsTypeOperator(_) + | TsType::TsIndexedAccessType(_) + | TsType::TsTypeLit(_) + | TsType::TsMappedType(_) + | TsType::TsKeywordType(TsKeywordType { + kind: TsKeywordTypeKind::TsAnyKeyword, + .. + }) + | TsType::TsKeywordType(TsKeywordType { + kind: TsKeywordTypeKind::TsUnknownKeyword, + .. + }) + | TsType::TsThisType(..) => quote_ident!("Object").into(), + + TsType::TsUnionOrIntersectionType(ty) => match ty { + TsUnionOrIntersectionType::TsUnionType(ty) => { + serialize_type_list(class_name, &ty.types) + } + TsUnionOrIntersectionType::TsIntersectionType(ty) => { + serialize_type_list(class_name, &ty.types) + } + }, + + TsType::TsConditionalType(ty) => { + serialize_type_list(class_name, &[ty.true_type.clone(), ty.false_type.clone()]) + } + + TsType::TsTypeRef(ty) => serialize_type_ref(class_name, ty), + + _ => panic!("Bad type for decorator: {:?}", ty), + } + } + + let param = match param { + Some(v) => &v.type_ann, + None => return *undefined(DUMMY_SP), + }; + + serialize_type_node(class_name.map(|v| &*v.sym).unwrap_or(""), &**param) +} + +fn ts_entity_to_member_expr(type_name: &TsEntityName) -> Expr { + match type_name { + TsEntityName::TsQualifiedName(q) => { + let obj = ts_entity_to_member_expr(&q.left); + + Expr::Member(MemberExpr { + span: DUMMY_SP, + obj: obj.as_obj(), + prop: Box::new(Expr::Ident(q.right.clone())), + computed: false, + }) + } + TsEntityName::Ident(i) => Expr::Ident(i.clone()), + } +} + +fn get_type_ann_of_pat(p: &Pat) -> Option<&TsTypeAnn> { + match p { + Pat::Ident(p) => &p.type_ann, + Pat::Array(p) => &p.type_ann, + Pat::Rest(p) => &p.type_ann, + Pat::Object(p) => &p.type_ann, + Pat::Assign(p) => &p.type_ann, + Pat::Invalid(_) => return None, + Pat::Expr(_) => return None, + } + .as_ref() +} diff --git a/ecmascript/transforms/tests/es2015_function_name.rs b/ecmascript/transforms/tests/es2015_function_name.rs index fb855a5b5d35..197a142e469b 100644 --- a/ecmascript/transforms/tests/es2015_function_name.rs +++ b/ecmascript/transforms/tests/es2015_function_name.rs @@ -154,7 +154,10 @@ test!( syntax(), |_| chain!( resolver(), - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), Classes::default(), function_name(), ), @@ -275,7 +278,10 @@ test!( syntax(), |_| chain!( resolver(), - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), Classes::default(), function_name(), ), @@ -333,7 +339,10 @@ test!( syntax(), |_| chain!( resolver(), - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), Classes::default(), function_name(), common_js(Mark::fresh(Mark::root()), Default::default()) @@ -456,7 +465,10 @@ test!( syntax(), |_| chain!( resolver(), - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), Classes::default(), function_name(), ), @@ -482,7 +494,10 @@ test!( syntax(), |_| chain!( resolver(), - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), Classes::default(), function_name(), ), @@ -540,7 +555,10 @@ test!( syntax(), |_| chain!( resolver(), - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), Classes::default(), function_name(), ), @@ -638,7 +656,10 @@ test!( resolver(), function_name(), Classes::default(), - decorators(decorators::Config { legacy: true }) + decorators(decorators::Config { + legacy: true, + ..Default::default() + }) ), function_name_object, r#" @@ -696,7 +717,10 @@ test!( resolver(), function_name(), Classes::default(), - decorators(decorators::Config { legacy: true }) + decorators(decorators::Config { + legacy: true, + ..Default::default() + }) ), function_name_export, r#" @@ -755,7 +779,10 @@ test!( syntax(), |_| chain!( resolver(), - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), function_name(), Classes::default(), ), @@ -823,7 +850,10 @@ test!( syntax(), |_| chain!( resolver(), - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), Classes::default(), function_name(), common_js(Mark::fresh(Mark::root()), Default::default()), @@ -875,7 +905,10 @@ test!( resolver(), function_name(), Classes::default(), - decorators(decorators::Config { legacy: true }) + decorators(decorators::Config { + legacy: true, + ..Default::default() + }) ), function_name_eval, r#" @@ -903,7 +936,10 @@ test!( resolver(), function_name(), Classes::default(), - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), common_js(Mark::fresh(Mark::root()), Default::default()) ), function_name_modules_3, @@ -957,7 +993,10 @@ test!( syntax(), |_| chain!( resolver(), - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), Classes::default(), function_name(), ), @@ -1116,7 +1155,10 @@ test!( syntax(), |_| chain!( resolver(), - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), function_name(), Classes::default() ), @@ -1181,7 +1223,10 @@ test!( syntax(), |_| chain!( resolver(), - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), Classes::default(), function_name(), ), @@ -1206,7 +1251,10 @@ test!( syntax(), |_| chain!( resolver(), - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), Classes::default(), function_name(), ), diff --git a/ecmascript/transforms/tests/es2020_class_properties.rs b/ecmascript/transforms/tests/es2020_class_properties.rs index c6b6ed159b17..30e13ca05e95 100644 --- a/ecmascript/transforms/tests/es2020_class_properties.rs +++ b/ecmascript/transforms/tests/es2020_class_properties.rs @@ -3548,7 +3548,10 @@ test!( ignore, syntax(), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), Classes::default(), ), @@ -4433,7 +4436,10 @@ test!( ignore, syntax(), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), Classes::default() ), diff --git a/ecmascript/transforms/tests/proposal_decorators.rs b/ecmascript/transforms/tests/proposal_decorators.rs index 2a1fcb0799c5..178590f060ee 100644 --- a/ecmascript/transforms/tests/proposal_decorators.rs +++ b/ecmascript/transforms/tests/proposal_decorators.rs @@ -2049,7 +2049,10 @@ let A = _decorate([], function(_initialize) { test_exec!( syntax(true), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_class_constructors_return_new_constructor_exec, @@ -2076,7 +2079,10 @@ test!( syntax(true), |_| chain!( typescript::strip(), - decorators(decorators::Config { legacy: true }) + decorators(decorators::Config { + legacy: true, + ..Default::default() + }) ), legacy_regression_10264, r#" @@ -2090,8 +2096,8 @@ export default class {} var _class; function myDecorator(decoratee) { } -let _class1 = myDecorator((_class = class{ -}) || _class); +let _class1 = _class = myDecorator((_class = class { +}) || _class) || _class; export { _class1 as default } @@ -2481,18 +2487,21 @@ export { _class1 as default } // legacy_decl_to_expression_class_decorators test!( syntax(false), - |_| decorators(Config { legacy: true }), + |_| decorators(Config { + legacy: true, + ..Default::default() + }), legacy_decl_to_expression_class_decorators, r#" export default @dec class A {} @dec class B {} "#, r#" -var _class, _class1; -export default dec((_class = class A{ -}) || _class); -let B = dec((_class1 = class B{ -}) || _class1); + var _class, _class1; + export default _class = dec((_class = class A { + }) || _class) || _class; + let B = _class1 = dec((_class1 = class B { + }) || _class1) || _class1; "# ); @@ -2500,7 +2509,10 @@ let B = dec((_class1 = class B{ test_exec!( syntax(false), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_class_prototype_methods_numeric_props_exec, @@ -2523,7 +2535,10 @@ class Example { test_exec!( syntax(false), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_class_static_properties_mutate_descriptor_exec, @@ -2635,7 +2650,10 @@ expect(Example._).toBe("__8__"); test_exec!( syntax(false), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_class_static_methods_string_props_exec, @@ -2658,7 +2676,10 @@ class Example { test_exec!( syntax(false), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_class_prototype_properties_string_literal_properties_exec, @@ -2700,7 +2721,10 @@ expect(descs["a-prop"].configurable).toBeTruthy(); test_exec!( syntax(false), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_class_prototype_methods_mutate_descriptor_exec, @@ -2830,7 +2854,10 @@ test_exec!( ignore, syntax(false), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_object_properties_numeric_props_exec, @@ -2852,7 +2879,10 @@ const inst = { // legacy_decl_to_expression_method_decorators test!( syntax(false), - |_| decorators(Config { legacy: true }), + |_| decorators(Config { + legacy: true, + ..Default::default() + }), legacy_decl_to_expression_method_decorators, r#" export default class A { @@ -2881,7 +2911,10 @@ export { A as default } test_exec!( syntax(false), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_class_prototype_properties_return_descriptor_exec, @@ -2995,7 +3028,10 @@ test_exec!( ignore, syntax(false), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_object_properties_string_props_exec, @@ -3020,7 +3056,10 @@ test_exec!( ignore, syntax(false), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_object_properties_return_descriptor_exec, @@ -3130,7 +3169,10 @@ expect(inst._).toBe("__8__"); test_exec!( syntax(false), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_class_prototype_methods_string_props_exec, @@ -3153,7 +3195,10 @@ class Example { test!( syntax(false), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_regression_8041, @@ -3181,7 +3226,10 @@ export { _class1 as default } test_exec!( syntax(false), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_class_prototype_methods_return_descriptor_exec, @@ -3313,7 +3361,10 @@ test_exec!( ignore, syntax(false), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_object_ordering_reverse_order_exec, @@ -3354,7 +3405,10 @@ test_exec!( ignore, syntax(false), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_object_methods_numeric_props_exec, @@ -3378,7 +3432,10 @@ const inst = { test_exec!( syntax(false), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_class_static_properties_return_descriptor_exec, @@ -3495,7 +3552,10 @@ test_exec!( ignore, syntax(true), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_class_export_default_exec, @@ -3522,7 +3582,10 @@ expect(calls).toEqual(["Foo"]); test_exec!( syntax(true), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_class_ordering_reverse_order_exec, @@ -3566,7 +3629,10 @@ test_exec!( ignore, syntax(true), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_object_methods_mutate_descriptor_exec, @@ -3692,7 +3758,10 @@ expect(inst._()).toBe("__8__"); test_exec!( syntax(false), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_class_static_methods_return_descriptor_exec, @@ -3821,7 +3890,10 @@ test_exec!( ignore, syntax(false), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_object_methods_return_descriptor_exec, @@ -3949,7 +4021,10 @@ test_exec!( ignore, syntax(false), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_object_methods_string_props_exec, @@ -3974,7 +4049,10 @@ const inst = { test_exec!( syntax(false), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_class_prototype_properties_child_classes_properties_exec, @@ -4014,7 +4092,10 @@ expect(inst.prop2).toBe("__4__"); test_exec!( syntax(false), |_| chain!( - decorators(decorators::Config { legacy: true }), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), class_properties(), ), legacy_class_static_methods_mutate_descriptor_exec, @@ -4139,7 +4220,10 @@ expect(Example._()).toBe("__8__"); // legacy_regression_8512 test_exec!( syntax(false), - |_| decorators(Config { legacy: true }), + |_| decorators(Config { + legacy: true, + ..Default::default() + }), legacy_regression_8512_exec, r#" function dec(Class, key, desc) { @@ -4156,7 +4240,10 @@ class Foo { test!( syntax(false), - |_| decorators(Config { legacy: true }), + |_| decorators(Config { + legacy: true, + ..Default::default() + }), issue_591_1, " export class Example { @@ -4190,7 +4277,10 @@ export let Example = ((_class = class Example{ test!( syntax(false), - |_| decorators(Config { legacy: true }), + |_| decorators(Config { + legacy: true, + ..Default::default() + }), issue_591_2, "class Example { @foo() bar = '1'; @@ -4226,7 +4316,13 @@ test!( decorators: true, ..Default::default() }), - |_| chain!(typescript::strip(), decorators(Config { legacy: true })), + |_| chain!( + typescript::strip(), + decorators(Config { + legacy: true, + ..Default::default() + }) + ), issue_823_1, "import {Debounce} from 'lodash-decorators'; class Person { @@ -4262,7 +4358,10 @@ test!( }), |_| chain!( typescript::strip(), - decorators(Config { legacy: true }), + decorators(Config { + legacy: true, + ..Default::default() + }), class_properties(), // Classes::default(), ), @@ -4305,7 +4404,10 @@ test!( }), |_| chain!( typescript::strip(), - decorators(Config { legacy: true }), + decorators(Config { + legacy: true, + ..Default::default() + }), class_properties(), Classes::default(), ), @@ -4386,7 +4488,7 @@ var _dec = PrimaryGeneratedColumn('uuid'), _dec1 = Column(), _dec2 = Column({ ), _dec5 = OneToMany(()=>Discount , (discount)=>discount.product ), _dec6 = Entity(); -export let Product = _dec6(((_class = function() { +export let Product = _class = _dec6(((_class = function() { class Product extends TimestampedEntity { constructor(...args){ super(...args); @@ -4453,7 +4555,7 @@ export let Product = _dec6(((_class = function() { initializer: function() { return; } -}), _class)); +}), _class)) || _class; " ); @@ -4468,8 +4570,8 @@ export class Product extends TimestampedEntity { } ", "var _class, _descriptor; -var _dec = PrimaryGeneratedColumn('uuid'), _dec1 = Entity(); -export let Product = _dec1(((_class = function() { + var _dec = PrimaryGeneratedColumn(\"uuid\"), _dec1 = Entity(); + export let Product = _class = _dec1(((_class = function() { class Product extends TimestampedEntity { constructor(...args){ super(...args); @@ -4486,7 +4588,7 @@ export let Product = _dec1(((_class = function() { initializer: function() { return; } -}), _class)); +}), _class)) || _class; " ); @@ -4611,3 +4713,400 @@ let X = ((_class = function() { export { X as default }; " ); + +test!( + ts(), + |_| decorators(Config { + legacy: true, + emit_metadata: true, + }), + legacy_metadata_generics_base, + "@Decorate + class MyClass { + constructor( + private generic: Generic, + generic2: Generic + ) {} + + @Run + method( + generic: Inter, + @Arg() generic2: InterGen + ) {} + }", + r#" + var _class, _dec, _dec1, _dec2; +var _dec3 = Reflect.metadata("design:paramtypes", [ + typeof Generic === void 0 ? Object : Generic, + typeof Generic === void 0 ? Object : Generic +]), _dec4 = Reflect.metadata("design:type", Function); +let MyClass = _class = Decorate(_class = _dec4(_class = _dec3(((_class = class MyClass { + constructor(private generic: Generic, generic2: Generic){ + } + method(generic: Inter, generic2: InterGen) { + } +}) || _class, _dec = function(target, target) { + return Arg()(target, key, 1); +}, _dec1 = Reflect.metadata("design:type", Function), _dec2 = Reflect.metadata("design:paramtypes", [ + typeof Inter === void 0 ? Object : Inter, + typeof InterGen === void 0 ? Object : InterGen +]), _applyDecoratedDescriptor(_class.prototype, "method", [ + Run, + _dec, + _dec1, + _dec2 +], Object.getOwnPropertyDescriptor(_class.prototype, "method"), _class.prototype), _class)) || _class) || _class) || _class; +"# +); + +test!( + ts(), + |_| decorators(Config { + legacy: true, + emit_metadata: true, + }), + legacy_metadata_generics_1, + "@Decorate +class MyClass { + constructor( + private generic: Generic, + generic2: Generic + ) {} +}", + r#"var _class; + var _dec = Reflect.metadata("design:paramtypes", [ + typeof Generic === void 0 ? Object : Generic, + typeof Generic === void 0 ? Object : Generic + ]), _dec1 = Reflect.metadata("design:type", Function); + let MyClass = _class = Decorate(_class = _dec1(_class = _dec((_class = class MyClass { + constructor(private generic: Generic, generic2: Generic){ + } + }) || _class) || _class) || _class) || _class; + "# +); + +test!( + ts(), + |_| decorators(Config { + legacy: true, + emit_metadata: true, + }), + legacy_metadata_nest_injection, + "import { AppService } from './app.service'; + + @Controller() + export class AppController { + constructor(private appService: AppService) {} + + @Inject() + appService: AppService; + + @Inject() + private appService2: AppService; + + @Get() + getHello(): string { + return this.appService.getHello(); + } + }", + r#"var _class, _descriptor, _descriptor1, _dec, _dec1, _dec2; + import { AppService } from "./app.service"; + var _dec3 = Inject(), _dec4 = Reflect.metadata("design:type", typeof AppService === void 0 ? Object : AppService), _dec5 = Inject(), _dec6 = Reflect.metadata("design:type", typeof AppService === void 0 ? Object : AppService), _dec7 = Reflect.metadata("design:paramtypes", [ + typeof AppService === void 0 ? Object : AppService + ]), _dec8 = Reflect.metadata("design:type", Function), _dec9 = Controller(); + export let AppController = _class = _dec9(_class = _dec8(_class = _dec7(((_class = class AppController { + constructor(private appService: AppService){ + _initializerDefineProperty(this, "appService", _descriptor, this); + _initializerDefineProperty(this, "appService2", _descriptor1, this); + } + getHello(): string { + return this.appService.getHello(); + } + }) || _class, _descriptor = _applyDecoratedDescriptor(_class.prototype, "appService", [ + _dec3, + _dec4 + ], { + configurable: true, + enumerable: true, + writable: true, + initializer: function() { + return; + } + }), _descriptor1 = _applyDecoratedDescriptor(_class.prototype, "appService2", [ + _dec5, + _dec6 + ], { + configurable: true, + enumerable: true, + writable: true, + initializer: function() { + return; + } + }), _dec = Get(), _dec1 = Reflect.metadata("design:type", Function), _dec2 = Reflect.metadata("design:paramtypes", []), _applyDecoratedDescriptor(_class.prototype, "getHello", [ + _dec, + _dec1, + _dec2 + ], Object.getOwnPropertyDescriptor(_class.prototype, "getHello"), _class.prototype), _class)) || _class) || _class) || _class;"# +); + +test!( + ts(), + |_| decorators(Config { + legacy: true, + emit_metadata: true, + }), + legacy_metadata_parameter_decorated_types, + "class Injected {} + + class MyClass { + constructor(@inject() parameter: Injected) {} + } + + class MyOtherClass { + constructor( + @inject() private readonly parameter: Injected, + @inject('KIND') otherParam: Injected + ) {} + + methodUndecorated(@demo() param: string, otherParam) {} + + @decorate('named') + method(@inject() param: Injected, @arg() schema: Schema) {} + } + + @Decorate + class DecoratedClass { + constructor( + @inject() private readonly module: Injected, + @inject() otherModule: Injected + ) {} + + @decorate('example') + method(@inject() param: string) {} + }", + r##"var _class, _class1, _dec, _dec1, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _class2, _dec8, _dec9, _dec10, _dec11; + class Injected { + } + var _dec12 = Reflect.metadata("design:paramtypes", [ + typeof Injected === void 0 ? Object : Injected + ]), _dec13 = Reflect.metadata("design:type", Function), _dec14 = function(target, target) { + return inject()(target, undefined, 0); + }; + let MyClass = _class = _dec14(_class = _dec13(_class = _dec12((_class = class MyClass { + constructor(parameter: Injected){ + } + }) || _class) || _class) || _class) || _class; + var _dec15 = Reflect.metadata("design:paramtypes", [ + typeof Injected === void 0 ? Object : Injected, + typeof Injected === void 0 ? Object : Injected + ]), _dec16 = Reflect.metadata("design:type", Function), _dec17 = function(target, target) { + return inject("KIND")(target, undefined, 1); + }, _dec18 = function(target, target) { + return inject()(target, undefined, 0); + }; + let MyOtherClass = _class1 = _dec18(_class1 = _dec17(_class1 = _dec16(_class1 = _dec15(((_class1 = class MyOtherClass { + constructor(private readonly parameter: Injected, otherParam: Injected){ + } + methodUndecorated(param: string, otherParam) { + } + method(param: Injected, schema: Schema) { + } + }) || _class1, _dec = function(target, target) { + return demo()(target, key, 0); + }, _dec1 = Reflect.metadata("design:type", Function), _dec2 = Reflect.metadata("design:paramtypes", [ + String, + void 0 + ]), _applyDecoratedDescriptor(_class1.prototype, "methodUndecorated", [ + _dec, + _dec1, + _dec2 + ], Object.getOwnPropertyDescriptor(_class1.prototype, "methodUndecorated"), _class1.prototype), _dec3 = decorate("named"), _dec4 = function(target, target) { + return inject()(target, key, 0); + }, _dec5 = function(target, target) { + return arg()(target, key, 1); + }, _dec6 = Reflect.metadata("design:type", Function), _dec7 = Reflect.metadata("design:paramtypes", [ + typeof Injected === void 0 ? Object : Injected, + typeof Schema === void 0 ? Object : Schema + ]), _applyDecoratedDescriptor(_class1.prototype, "method", [ + _dec3, + _dec4, + _dec5, + _dec6, + _dec7 + ], Object.getOwnPropertyDescriptor(_class1.prototype, "method"), _class1.prototype), _class1)) || _class1) || _class1) || _class1) || _class1; + var _dec35 = Reflect.metadata("design:paramtypes", [ + typeof Injected === void 0 ? Object : Injected, + typeof Injected === void 0 ? Object : Injected + ]), _dec36 = Reflect.metadata("design:type", Function), _dec37 = function(target, target) { + return inject()(target, undefined, 1); + }, _dec38 = function(target, target) { + return inject()(target, undefined, 0); + }; + let DecoratedClass = _class2 = Decorate(_class2 = _dec38(_class2 = _dec37(_class2 = _dec36(_class2 = _dec35(((_class2 = class DecoratedClass { + constructor(private readonly module: Injected, otherModule: Injected){ + } + method(param: string) { + } + }) || _class2, _dec8 = decorate("example"), _dec9 = function(target, target) { + return inject()(target, key, 0); + }, _dec10 = Reflect.metadata("design:type", Function), _dec11 = Reflect.metadata("design:paramtypes", [ + String + ]), _applyDecoratedDescriptor(_class2.prototype, "method", [ + _dec8, + _dec9, + _dec10, + _dec11 + ], Object.getOwnPropertyDescriptor(_class2.prototype, "method"), _class2.prototype), _class2)) || _class2) || _class2) || _class2) || _class2) || _class2;"## +); + +test!( + ts(), + |_| decorators(Config { + legacy: true, + emit_metadata: true, + }), + legacy_metadata_type_serialization, + "import { Service } from './service'; + import { Decorate } from './Decorate'; + + const sym = Symbol(); + + @Decorate() + class Sample { + constructor( + private p0: String, + p1: Number, + p2: 10, + p3: 'ABC', + p4: boolean, + p5: string, + p6: number, + p7: Object, + p8: () => any, + p9: 'abc' | 'def', + p10: String | Number, + p11: Function, + p12: null, + p13: undefined, + p14: any, + p15: (abc: any) => void, + p16: false, + p17: true, + p18: string = 'abc' + ) {} + + @Decorate + method( + @Arg() p0: Symbol, + p1: typeof sym, + p2: string | null, + p3: never, + p4: string | never, + p5: (string | null), + p6: Maybe, + p7: Object | string, + p8: string & MyStringType, + p9: string[], + p10: [string, number], + p11: void, + p12: this is number, + p13: null | undefined, + p14: (string | (string | null)), + p15: Object, + p16: any, + p17: bigint, + ) {} + + /** + * Member Expression + */ + @Decorate() + method2( + p0: Decorate.Name = 'abc', + p1: Decorate.Name + ) {} + + /** + * Assignments + */ + @Decorate() + assignments( + p0: string = 'abc' + ) {} + }", + r##"var _class, _dec, _dec1, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8; +import { Service } from "./service"; +import { Decorate } from "./Decorate"; +const sym = Symbol(); +var _dec9 = Reflect.metadata("design:paramtypes", [ + typeof String === void 0 ? Object : String, + typeof Number === void 0 ? Object : Number, + Number, + String, + Boolean, + String, + Number, + typeof Object === void 0 ? Object : Object, + Function, + void 0, + Object, + typeof Function === void 0 ? Object : Function, + void 0, + void 0, + Object, + Function, + Boolean, + Boolean, + void 0 +]), _dec10 = Reflect.metadata("design:type", Function), _dec11 = Decorate(); +let Sample = _class = _dec11(_class = _dec10(_class = _dec9(((_class = class Sample { + constructor(private p0: String, p1: Number, p2: 10, p3: "ABC", p4: boolean, p5: string, p6: number, p7: Object, p8: () => any, p9: "abc" | "def", p10: String | Number, p11: Function, p12: null, p13: undefined, p14: any, p15: (abc: any) => void, p16: falsee, p17: true, p18: string = "abc"){ + } + method(p0: Symbol, p1: typeof sym, p2: string | null, p3: never, p4: string | never, p5: (string | null), p6: Maybe, p7: Object | string, p8: string & MyStringType, p9: string[], p10: [string, number], p11: void, p12: this is number, p13: null | undefined, p14: (string | (string | null)), p15: Object, p16: any, p17: bigint) { + } + method2(p0: Decorate.Name. = "abc", p1: Decorate.Name.) { + } + assignments(p0: string = "abc") { + } +}) || _class, _dec = function(target, target) { + return Arg()(target, key, 0); +}, _dec1 = Reflect.metadata("design:type", Function), _dec2 = Reflect.metadata("design:paramtypes", [ + typeof Symbol === void 0 ? Object : Symbol, + Object, + void 0, + void 0, + void 0, + void 0, + typeof Maybe === void 0 ? Object : Maybe, + Object, + Object, + Array, + Array, + void 0, + Boolean, + void 0, + Object, + typeof Object === void 0 ? Object : Object, + Object, + Number +]), _applyDecoratedDescriptor(_class.prototype, "method", [ + Decorate, + _dec, + _dec1, + _dec2 +], Object.getOwnPropertyDescriptor(_class.prototype, "method"), _class.prototype), _dec3 = Decorate(), _dec4 = Reflect.metadata("design:type", Function), _dec5 = Reflect.metadata("design:paramtypes", [ + void 0, + typeof Decorate.Name === void 0 ? Object : Decorate.Name +]), _applyDecoratedDescriptor(_class.prototype, "method2", [ + _dec3, + _dec4, + _dec5 +], Object.getOwnPropertyDescriptor(_class.prototype, "method2"), _class.prototype), _dec6 = Decorate(), _dec7 = Reflect.metadata("design:type", Function), _dec8 = Reflect.metadata("design:paramtypes", [ + void 0 +]), _applyDecoratedDescriptor(_class.prototype, "assignments", [ + _dec6, + _dec7, + _dec8 +], Object.getOwnPropertyDescriptor(_class.prototype, "assignments"), _class.prototype), _class)) || _class) || _class) || _class;"##, + ok_if_code_eq +); diff --git a/package.json b/package.json index b03f6ec4c5bf..9bbbf9446fd6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@swc/core", - "version": "1.2.12", + "version": "1.2.13", "description": "Super-fast alternative for babel", "main": "./index.js", "author": "강동윤 ", diff --git a/src/config.rs b/src/config.rs index 8cc5dabf785d..6825e8f5c805 100644 --- a/src/config.rs +++ b/src/config.rs @@ -226,16 +226,18 @@ impl Options { let pass = chain!( // handle jsx Optional::new(react::react(cm.clone(), transform.react), syntax.jsx()), - Optional::new(typescript::strip(), syntax.typescript()), - resolver_with_mark(root_mark), - const_modules, - optimization, + // Decorators may use type information Optional::new( decorators(decorators::Config { - legacy: transform.legacy_decorator + legacy: transform.legacy_decorator, + emit_metadata: transform.decorator_metadata, }), syntax.decorators() ), + Optional::new(typescript::strip(), syntax.typescript()), + resolver_with_mark(root_mark), + const_modules, + optimization, Optional::new( export(), syntax.export_default_from() || syntax.export_namespace_from() @@ -570,6 +572,9 @@ pub struct TransformConfig { #[serde(default)] pub legacy_decorator: bool, + + #[serde(default)] + pub decorator_metadata: bool, } #[derive(Debug, Default, Clone, Serialize, Deserialize)]