From 03be31592148c5664aad660a246558c393dfeb5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Thu, 8 Jul 2021 20:48:07 +0900 Subject: [PATCH] fix(es/transforms): Fix decorator bugs (#1905) swc_ecma_transforms_proposal: - Initialze decorators lazily. (#1278) --- common/Cargo.toml | 5 +- ecmascript/transforms/proposal/Cargo.toml | 2 +- .../proposal/src/decorators/legacy.rs | 71 ++- ecmascript/transforms/tests/decorators.rs | 469 ++++++++++-------- .../transforms/typescript/tests/strip.rs | 5 +- package.json | 2 +- tests/fixture/issue-1160/output/entry.ts | 5 +- tests/fixture/issue-1278/input/.swcrc | 21 + tests/fixture/issue-1278/input/index.ts | 13 + tests/fixture/issue-1278/output/index.ts | 55 ++ tests/fixture/issue-1345/output/index.ts | 62 +-- .../fixture/issue-1421/case1/output/index.ts | 5 +- wasm/Cargo.toml | 2 +- 13 files changed, 459 insertions(+), 258 deletions(-) create mode 100644 tests/fixture/issue-1278/input/.swcrc create mode 100644 tests/fixture/issue-1278/input/index.ts create mode 100644 tests/fixture/issue-1278/output/index.ts diff --git a/common/Cargo.toml b/common/Cargo.toml index cbf3f2ce962c..d6744f557856 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -6,10 +6,7 @@ edition = "2018" license = "Apache-2.0/MIT" name = "swc_common" repository = "https://github.com/swc-project/swc.git" -version = "0.10.22" - -[package.metadata.docs.rs] -all-features = true +version = "0.10.23" [features] concurrent = ["parking_lot"] diff --git a/ecmascript/transforms/proposal/Cargo.toml b/ecmascript/transforms/proposal/Cargo.toml index 026b7c042ca3..78e0934ffdfd 100644 --- a/ecmascript/transforms/proposal/Cargo.toml +++ b/ecmascript/transforms/proposal/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "Apache-2.0/MIT" name = "swc_ecma_transforms_proposal" repository = "https://github.com/swc-project/swc.git" -version = "0.25.0" +version = "0.25.1" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/ecmascript/transforms/proposal/src/decorators/legacy.rs b/ecmascript/transforms/proposal/src/decorators/legacy.rs index 28740f14e863..c5506804a226 100644 --- a/ecmascript/transforms/proposal/src/decorators/legacy.rs +++ b/ecmascript/transforms/proposal/src/decorators/legacy.rs @@ -4,6 +4,7 @@ use super::DecoratorFinder; use fxhash::FxHashMap; use smallvec::SmallVec; use std::mem::replace; +use std::mem::take; use swc_common::{util::move_map::MoveMap, DUMMY_SP}; use swc_ecma_ast::*; use swc_ecma_transforms_base::helper; @@ -15,6 +16,9 @@ use swc_ecma_utils::{ ExprFactory, ModuleItemLike, StmtLike, }; use swc_ecma_utils::{ident::IdentLike, Id}; +use swc_ecma_visit::noop_visit_mut_type; +use swc_ecma_visit::VisitMut; +use swc_ecma_visit::VisitMutWith; use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, Node, Visit, VisitWith}; mod metadata; @@ -147,7 +151,7 @@ impl Fold for Legacy { Stmt::Decl(Decl::Var(VarDecl { span: DUMMY_SP, kind: VarDeclKind::Var, - decls: replace(&mut self.uninitialized_vars, Default::default()), + decls: take(&mut self.uninitialized_vars), declare: false, })) .into(), @@ -157,7 +161,7 @@ impl Fold for Legacy { if !self.exports.is_empty() { let decl = ModuleDecl::ExportNamed(NamedExport { span: DUMMY_SP, - specifiers: replace(&mut self.exports, Default::default()), + specifiers: take(&mut self.exports), src: None, type_only: false, asserts: None, @@ -291,6 +295,11 @@ impl Legacy { definite: false, }); + // We initialize decorators lazily. + // + // See https://github.com/swc-project/swc/issues/1278 + let mut dec_init_exprs = vec![]; + // Injected to sequence expression which is wrapped with parenthesis. let mut extra_exprs = vec![]; // Injected to constructor @@ -367,10 +376,24 @@ impl Legacy { PropName::Computed(e) => { let (name, aliased) = alias_if_required(&e.expr, "key"); if aliased { - self.initialized_vars.push(VarDeclarator { + let mut init = e.expr.clone(); + if let Some(name) = &cls_name { + init.visit_mut_with(&mut IdentReplacer { + from: name, + to: &cls_ident, + }); + } + + dec_init_exprs.push(Box::new(Expr::Assign(AssignExpr { + span: DUMMY_SP, + op: op!("="), + left: PatOrExpr::Pat(Box::new(Pat::Ident(name.clone().into()))), + right: init, + }))); + self.uninitialized_vars.push(VarDeclarator { span: DUMMY_SP, name: Pat::Ident(name.clone().into()), - init: Some(e.expr.clone()), + init: None, definite: Default::default(), }) } @@ -476,13 +499,26 @@ impl Legacy { let mut value = Some(p.value); let mut dec_exprs = vec![]; - for dec in p.decorators.into_iter() { + for mut dec in p.decorators.into_iter() { let (i, aliased) = alias_if_required(&dec.expr, "_dec"); if aliased { - self.initialized_vars.push(VarDeclarator { + if let Some(name) = &cls_name { + dec.expr.visit_mut_with(&mut IdentReplacer { + from: name, + to: &cls_ident, + }); + } + + dec_init_exprs.push(Box::new(Expr::Assign(AssignExpr { + span: DUMMY_SP, + op: op!("="), + left: PatOrExpr::Pat(Box::new(Pat::Ident(i.clone().into()))), + right: dec.expr, + }))); + self.uninitialized_vars.push(VarDeclarator { span: DUMMY_SP, name: Pat::Ident(i.clone().into()), - init: Some(dec.expr), + init: None, definite: false, }); } @@ -765,6 +801,12 @@ impl Legacy { right: Box::new(Expr::Ident(cls_ident.clone())), })); + let mut extra_exprs = { + let mut buf = dec_init_exprs; + buf.extend(extra_exprs); + buf + }; + let expr = self.apply( &cls_ident, if extra_exprs.is_empty() { @@ -862,3 +904,18 @@ impl Fold for ClassFieldAccessConverter { } } } + +struct IdentReplacer<'a> { + from: &'a Ident, + to: &'a Ident, +} + +impl VisitMut for IdentReplacer<'_> { + noop_visit_mut_type!(); + + fn visit_mut_ident(&mut self, i: &mut Ident) { + if self.from.sym == i.sym && self.from.span.ctxt == i.span.ctxt { + *i = self.to.clone(); + } + } +} diff --git a/ecmascript/transforms/tests/decorators.rs b/ecmascript/transforms/tests/decorators.rs index 4dc93fcd71b1..774757746bed 100644 --- a/ecmascript/transforms/tests/decorators.rs +++ b/ecmascript/transforms/tests/decorators.rs @@ -4211,29 +4211,34 @@ export class Example { @foo() bar = '1'; @foo() baz = '2'; }", - "var _class, _descriptor, _descriptor1; -var _dec = foo(), _dec1 = foo(); -export let Example = ((_class = class Example{ - constructor(){ - _initializerDefineProperty(this, 'bar', _descriptor, this); - _initializerDefineProperty(this, 'baz', _descriptor1, this); - } -}) || _class, _descriptor = _applyDecoratedDescriptor(_class.prototype, 'bar', [_dec], { - configurable: true, - enumerable: true, - writable: true, - initializer: function() { - return '1'; - } -}), _descriptor1 = _applyDecoratedDescriptor(_class.prototype, 'baz', [_dec1], { - configurable: true, - enumerable: true, - writable: true, - initializer: function() { - return '2'; - } -}), _class); -" + " + var _class, _descriptor, _dec, _descriptor1, _dec1; + export let Example = ((_class = class Example { + constructor(){ + _initializerDefineProperty(this, 'bar', _descriptor, this); + _initializerDefineProperty(this, 'baz', _descriptor1, this); + } + }) || _class, _dec = foo(), _dec1 = foo(), _descriptor = \ + _applyDecoratedDescriptor(_class.prototype, 'bar', [ + _dec + ], { + configurable: true, + enumerable: true, + writable: true, + initializer: function() { + return '1'; + } + }), _descriptor1 = _applyDecoratedDescriptor(_class.prototype, 'baz', [ + _dec1 + ], { + configurable: true, + enumerable: true, + writable: true, + initializer: function() { + return '2'; + } + }), _class); + " ); test!( @@ -4247,29 +4252,34 @@ test!( @foo() bar = '1'; @foo() baz = '2'; }", - "var _class, _descriptor, _descriptor1; -var _dec = foo(), _dec1 = foo(); -let Example = ((_class = class Example{ - constructor(){ - _initializerDefineProperty(this, 'bar', _descriptor, this); - _initializerDefineProperty(this, 'baz', _descriptor1, this); - } -}) || _class, _descriptor = _applyDecoratedDescriptor(_class.prototype, 'bar', [_dec], { - configurable: true, - enumerable: true, - writable: true, - initializer: function() { - return '1'; - } -}), _descriptor1 = _applyDecoratedDescriptor(_class.prototype, 'baz', [_dec1], { - configurable: true, - enumerable: true, - writable: true, - initializer: function() { - return '2'; - } -}), _class); -" + " + var _class, _descriptor, _dec, _descriptor1, _dec1; + let Example = ((_class = class Example { + constructor(){ + _initializerDefineProperty(this, 'bar', _descriptor, this); + _initializerDefineProperty(this, 'baz', _descriptor1, this); + } + }) || _class, _dec = foo(), _dec1 = foo(), _descriptor = \ + _applyDecoratedDescriptor(_class.prototype, 'bar', [ + _dec + ], { + configurable: true, + enumerable: true, + writable: true, + initializer: function() { + return '1'; + } + }), _descriptor1 = _applyDecoratedDescriptor(_class.prototype, 'baz', [ + _dec1 + ], { + configurable: true, + enumerable: true, + writable: true, + initializer: function() { + return '2'; + } + }), _class); + " ); test!( @@ -4432,15 +4442,9 @@ export class Product extends TimestampedEntity { public discounts!: Discount[]; } ", - "var _class, _descriptor, _descriptor1, _descriptor2, _descriptor3, _descriptor4, \ - _descriptor5; -var _dec = PrimaryGeneratedColumn('uuid'), _dec1 = Column(), _dec2 = Column({ - enum: ProductType -}), _dec3 = Column(), _dec4 = OneToMany(()=>Order -, (order)=>order.product -), _dec5 = OneToMany(()=>Discount -, (discount)=>discount.product -), _dec6 = Entity(); + "var _class, _descriptor, _dec, _descriptor1, _dec1, _descriptor2, _dec2, _descriptor3, \ + _dec3, _descriptor4, _dec4, _descriptor5, _dec5; + var _dec6 = Entity(); export let Product = _class = _dec6(((_class = class Product extends TimestampedEntity { constructor(...args){ super(...args); @@ -4451,7 +4455,13 @@ export let Product = _class = _dec6(((_class = class Product extends Timestamped _initializerDefineProperty(this, 'orders', _descriptor4, this); _initializerDefineProperty(this, 'discounts', _descriptor5, this); } - }) || _class, _descriptor = _applyDecoratedDescriptor(_class.prototype, 'id', [ + }) || _class, _dec = PrimaryGeneratedColumn('uuid'), _dec1 = Column(), _dec2 = Column({ + enum: ProductType + }), _dec3 = Column(), _dec4 = OneToMany(()=>Order + , (order)=>order.product + ), _dec5 = OneToMany(()=>Discount + , (discount)=>discount.product + ), _descriptor = _applyDecoratedDescriptor(_class.prototype,'id', [ _dec ], { configurable: true, @@ -4507,22 +4517,24 @@ export class Product extends TimestampedEntity { public id!: string; } ", - "var _class, _descriptor; - var _dec = PrimaryGeneratedColumn(\"uuid\"), _dec1 = Entity(); + " + var _class, _descriptor, _dec; + var _dec1 = Entity(); export let Product = _class = _dec1(((_class = class Product extends TimestampedEntity { constructor(...args){ super(...args); _initializerDefineProperty(this, 'id', _descriptor, this); } - }) || _class, _descriptor = _applyDecoratedDescriptor(_class.prototype, 'id', [ - _dec -], { - configurable: true, - enumerable: true, - writable: true, - initializer: void 0 -}), _class)) || _class; -" + }) || _class, _dec = PrimaryGeneratedColumn('uuid'), _descriptor = \ + _applyDecoratedDescriptor(_class.prototype, 'id', [ + _dec + ], { + configurable: true, + enumerable: true, + writable: true, + initializer: void 0 + }), _class)) || _class; + " ); test_exec!( @@ -4748,62 +4760,64 @@ test!( return res.redirect(state.returnUrl ?? '/') } }", - r#"var _class, _descriptor, _descriptor1, _dec, _dec1, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7; - import { AppService } from "./app.service"; - import { Session, Res } from "@nestjs/common"; - import * as express from "express"; - var _dec8 = Inject(), _dec9 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", typeof AppService === "undefined" ? Object : AppService), _dec10 = Inject(), _dec11 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", typeof AppService === "undefined" ? Object : AppService), _dec12 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:paramtypes", [ - typeof AppService === "undefined" ? Object : AppService - ]), _dec13 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec14 = Controller(); - export let AppController = _class = _dec14(_class = _dec13(_class = _dec12(((_class = class AppController { - constructor(private appService: AppService){ - _initializerDefineProperty(this, "appService", _descriptor, this); - _initializerDefineProperty(this, "appService2", _descriptor1, this); - } - getHello(): string { - return this.appService.getHello(); - } - callback(res: express.Response, session: express.Express.Session) { - const token = await this.getToken(code); - const user = await this.getUserInfo(token.access_token); - session.oauth2Token = token; - session.user = user; - return res.redirect(state.returnUrl ?? "/"); - } - }) || _class, _descriptor = _applyDecoratedDescriptor(_class.prototype, "appService", [ - _dec8, - _dec9 - ], { - configurable: true, - enumerable: true, - writable: true, - initializer: void 0, - }), _descriptor1 = _applyDecoratedDescriptor(_class.prototype, "appService2", [ - _dec10, - _dec11 - ], { - configurable: true, - enumerable: true, - writable: true, - initializer: void 0, - }), _dec = Get(), _dec1 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec2 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:paramtypes", []), _applyDecoratedDescriptor(_class.prototype, "getHello", [ - _dec, - _dec1, - _dec2 - ], Object.getOwnPropertyDescriptor(_class.prototype, "getHello"), _class.prototype), _dec3 = Get("/callback"), _dec4 = function(target, key) { - return Res()(target, key, 0); - }, _dec5 = function(target, key) { - return Session()(target, key, 1); - }, _dec6 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec7 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:paramtypes", [ - typeof express === "undefined" || typeof express.Response === "undefined" ? Object : express.Response, - typeof express === "undefined" || typeof express.Express === "undefined" || typeof express.Express.Session === "undefined" ? Object : express.Express.Session - ]), _applyDecoratedDescriptor(_class.prototype, "callback", [ - _dec3, - _dec4, - _dec5, - _dec6, - _dec7 - ], Object.getOwnPropertyDescriptor(_class.prototype, "callback"), _class.prototype), _class)) || _class) || _class) || _class;"# + r#" + var _class, _descriptor, _dec, _dec1, _descriptor1, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8, _dec9, _dec10, _dec11; +import { AppService } from "./app.service"; +import { Session, Res } from "@nestjs/common"; +import * as express from "express"; +var _dec12 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:paramtypes", [ + typeof AppService === "undefined" ? Object : AppService +]), _dec13 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec14 = Controller(); +export let AppController = _class = _dec14(_class = _dec13(_class = _dec12(((_class = class AppController { + constructor(private appService: AppService){ + _initializerDefineProperty(this, "appService", _descriptor, this); + _initializerDefineProperty(this, "appService2", _descriptor1, this); + } + getHello(): string { + return this.appService.getHello(); + } + callback(res: express.Response, session: express.Express.Session) { + const token = await this.getToken(code); + const user = await this.getUserInfo(token.access_token); + session.oauth2Token = token; + session.user = user; + return res.redirect(state.returnUrl ?? "/"); + } +}) || _class, _dec = Inject(), _dec1 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", typeof AppService === "undefined" ? Object : AppService), _dec2 = Inject(), _dec3 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", typeof AppService === "undefined" ? Object : AppService), _descriptor = _applyDecoratedDescriptor(_class.prototype, "appService", [ + _dec, + _dec1 +], { + configurable: true, + enumerable: true, + writable: true, + initializer: void 0 +}), _descriptor1 = _applyDecoratedDescriptor(_class.prototype, "appService2", [ + _dec2, + _dec3 +], { + configurable: true, + enumerable: true, + writable: true, + initializer: void 0 +}), _dec4 = Get(), _dec5 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec6 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:paramtypes", []), _applyDecoratedDescriptor(_class.prototype, "getHello", [ + _dec4, + _dec5, + _dec6 +], Object.getOwnPropertyDescriptor(_class.prototype, "getHello"), _class.prototype), _dec7 = Get("/callback"), _dec8 = function(target, key) { + return Res()(target, key, 0); +}, _dec9 = function(target, key) { + return Session()(target, key, 1); +}, _dec10 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec11 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:paramtypes", [ + typeof express === "undefined" || typeof express.Response === "undefined" ? Object : express.Response, + typeof express === "undefined" || typeof express.Express === "undefined" || typeof express.Express.Session === "undefined" ? Object : express.Express.Session +]), _applyDecoratedDescriptor(_class.prototype, "callback", [ + _dec7, + _dec8, + _dec9, + _dec10, + _dec11 +], Object.getOwnPropertyDescriptor(_class.prototype, "callback"), _class.prototype), _class)) || _class) || _class) || _class; + "# ); test!( @@ -5093,30 +5107,30 @@ test!( } ", " - var _class, _descriptor; -enum MyEnum { - x = \"xxx\", - y = \"yyy\" -} -var _dec = Decorator(), _dec1 = typeof Reflect !== \"undefined\" && typeof Reflect.metadata === \ - \"function\" && Reflect.metadata(\"design:type\", String); -let Xpto = ((_class = class Xpto { - constructor(){ - _initializerDefineProperty(this, \"value\", _descriptor, this); + var _class, _descriptor, _dec, _dec1; + enum MyEnum { + x = 'xxx', + y = 'yyy' + } + let Xpto = ((_class = class Xpto { + constructor(){ + _initializerDefineProperty(this, 'value', _descriptor, this); + } + }) || _class, _dec = Decorator(), _dec1 = typeof Reflect !== 'undefined' && typeof \ + Reflect.metadata === 'function' && Reflect.metadata('design:type', String), _descriptor = \ + _applyDecoratedDescriptor(_class.prototype, 'value', [ + _dec, + _dec1 + ], { + configurable: true, + enumerable: true, + writable: true, + initializer: void 0 + }), _class); + function Decorator() { + return function(...args) { + }; } -}) || _class, _descriptor = _applyDecoratedDescriptor(_class.prototype, \"value\", [ - _dec, - _dec1 -], { - configurable: true, - enumerable: true, - writable: true, - initializer: void 0 -}), _class); -function Decorator() { - return function(...args) { - }; -} ", ok_if_code_eq ); @@ -5693,14 +5707,14 @@ test!( } ", " - var _class, _descriptor; - var _dec = column(), _dec1 = typeof Reflect !== 'undefined' && typeof Reflect.metadata === \ - 'function' && Reflect.metadata('design:type', String); + var _class, _descriptor, _dec, _dec1; let User = ((_class = class User { constructor(){ _initializerDefineProperty(this, 'currency', _descriptor, this); } - }) || _class, _descriptor = _applyDecoratedDescriptor(_class.prototype, 'currency', [ + }) || _class, _dec = column(), _dec1 = typeof Reflect !== 'undefined' && typeof \ + Reflect.metadata === 'function' && Reflect.metadata('design:type', String), _descriptor = \ + _applyDecoratedDescriptor(_class.prototype, 'currency', [ _dec, _dec1 ], { @@ -5746,63 +5760,110 @@ test!( }), issue_846_1, " - class SomeClass { - @dec - someMethod() {} + class SomeClass { + @dec + someMethod() {} + } + + class OtherClass extends SomeClass { + @dec + anotherMethod() { + super.someMethod() } - - class OtherClass extends SomeClass { - @dec - anotherMethod() { - super.someMethod() - } + } + ", + " + let SomeClass = _decorate([], function(_initialize) { + class SomeClass { + constructor(){ + _initialize(this); + } + } + return { + F: SomeClass, + d: [ + { + kind: 'method', + decorators: [ + dec + ], + key: 'someMethod', + value: function someMethod() { + } + } + ] + }; + }); + let OtherClass = _decorate([], function(_initialize, _SomeClass) { + class OtherClass extends _SomeClass { + constructor(...args){ + super(...args); + _initialize(this); + } + } + return { + F: OtherClass, + d: [ + { + kind: 'method', + decorators: [ + dec + ], + key: 'anotherMethod', + value: function anotherMethod() { + _get(_getPrototypeOf(OtherClass.prototype), 'someMethod', this).call(this); + } + } + ] + }; + }, SomeClass); + " +); + +test!( + ts(), + |_| decorators(decorators::Config { + legacy: true, + emit_metadata: true, + ..Default::default() + }), + issue_1278_1, + " + function MyDecorator(klass) { + return () => { + // do something + console.log(klass); + } + } + + class MyClass { + @MyDecorator(MyClass) prop: ''; } + + console.log(new MyClass()); ", " - let SomeClass = _decorate([], function(_initialize) { - class SomeClass { - constructor(){ - _initialize(this); - } - } - return { - F: SomeClass, - d: [ - { - kind: 'method', - decorators: [ - dec - ], - key: 'someMethod', - value: function someMethod() { - } - } - ] - }; - }); - let OtherClass = _decorate([], function(_initialize, _SomeClass) { - class OtherClass extends _SomeClass { - constructor(...args){ - super(...args); - _initialize(this); - } - } - return { - F: OtherClass, - d: [ - { - kind: 'method', - decorators: [ - dec - ], - key: 'anotherMethod', - value: function anotherMethod() { - _get(_getPrototypeOf(OtherClass.prototype), 'someMethod', \ - this).call(this); - } - } - ] - }; - }, SomeClass); + var _class, _descriptor, _dec, _dec1; + function MyDecorator(klass) { + return ()=>{ + console.log(klass); + }; + } + let MyClass = ((_class = class MyClass { + constructor(){ + _initializerDefineProperty(this, 'prop', _descriptor, this); + } + }) || _class, _dec = MyDecorator(_class), _dec1 = typeof Reflect !== 'undefined' && typeof \ + Reflect.metadata === 'function' && Reflect.metadata('design:type', String), _descriptor = \ + _applyDecoratedDescriptor(_class.prototype, 'prop', [ + _dec, + _dec1 + ], { + configurable: true, + enumerable: true, + writable: true, + initializer: void 0 + }), _class); + console.log(new MyClass()); " ); diff --git a/ecmascript/transforms/typescript/tests/strip.rs b/ecmascript/transforms/typescript/tests/strip.rs index b64837191ddd..c119437227a4 100644 --- a/ecmascript/transforms/typescript/tests/strip.rs +++ b/ecmascript/transforms/typescript/tests/strip.rs @@ -860,7 +860,7 @@ test!( } } ", - r#"var _class, _descriptor; + r#"var _class, _descriptor, _dec; function DefineAction() { return (target, property)=>{ console.log(target, property); @@ -871,7 +871,6 @@ test!( this.action = new Subject(); } } - var _dec = DefineAction(); let Child = ((_class = class Child extends Base { callApi() { console.log(this.action); @@ -880,7 +879,7 @@ test!( super(...args); _initializerDefineProperty(this, "action", _descriptor, this); } - }) || _class, _descriptor = _applyDecoratedDescriptor(_class.prototype, "action", [ + }) || _class, _dec = DefineAction(), _descriptor = _applyDecoratedDescriptor(_class.prototype, "action", [ _dec ], { configurable: true, diff --git a/package.json b/package.json index 18344cdee3a7..eb801a972532 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@swc/core", - "version": "1.2.63", + "version": "1.2.64", "description": "Super-fast alternative for babel", "homepage": "https://swc.rs", "main": "./index.js", diff --git a/tests/fixture/issue-1160/output/entry.ts b/tests/fixture/issue-1160/output/entry.ts index a416053eb994..2b35033cffd1 100644 --- a/tests/fixture/issue-1160/output/entry.ts +++ b/tests/fixture/issue-1160/output/entry.ts @@ -32,19 +32,18 @@ function _initializerDefineProperty(target, property, descriptor, context) { value: descriptor.initializer ? descriptor.initializer.call(context) : void 0 }); } -var _class, _descriptor; +var _class, _descriptor, _dec, _dec1; var MyEnum; (function(MyEnum1) { MyEnum1["x"] = "xxx"; MyEnum1["y"] = "yyy"; })(MyEnum || (MyEnum = { })); -var _dec = Decorator(), _dec1 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", String); let Xpto = ((_class = class Xpto1 { constructor(){ _initializerDefineProperty(this, "value", _descriptor, this); } -}) || _class, _descriptor = _applyDecoratedDescriptor(_class.prototype, "value", [ +}) || _class, _dec = Decorator(), _dec1 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", String), _descriptor = _applyDecoratedDescriptor(_class.prototype, "value", [ _dec, _dec1 ], { diff --git a/tests/fixture/issue-1278/input/.swcrc b/tests/fixture/issue-1278/input/.swcrc new file mode 100644 index 000000000000..d699e9f80fa3 --- /dev/null +++ b/tests/fixture/issue-1278/input/.swcrc @@ -0,0 +1,21 @@ +{ + "jsc": { + "parser": { + "syntax": "typescript", + "tsx": false, + "decorators": true, + "dynamicImport": false + }, + "externalHelpers": false, + "target": "es2020", + "loose": true, + "transform": { + "legacyDecorator": false, + "decoratorMetadata": true + } + }, + "module": { + "type": "commonjs", + "strictMode": true + } +} \ No newline at end of file diff --git a/tests/fixture/issue-1278/input/index.ts b/tests/fixture/issue-1278/input/index.ts new file mode 100644 index 000000000000..badf2595ca93 --- /dev/null +++ b/tests/fixture/issue-1278/input/index.ts @@ -0,0 +1,13 @@ +type Klass = { new(...args: any[]): T }; +function MyDecorator(klass: Klass): PropertyDecorator { + return () => { + // do something + console.log(klass); + } +} + +class MyClass { + @MyDecorator(MyClass) prop: ''; +} + +console.log(new MyClass()); \ No newline at end of file diff --git a/tests/fixture/issue-1278/output/index.ts b/tests/fixture/issue-1278/output/index.ts new file mode 100644 index 000000000000..ba1e11405568 --- /dev/null +++ b/tests/fixture/issue-1278/output/index.ts @@ -0,0 +1,55 @@ +"use strict"; +function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { + var desc = { + }; + Object.keys(descriptor).forEach(function(key) { + desc[key] = descriptor[key]; + }); + desc.enumerable = !!desc.enumerable; + desc.configurable = !!desc.configurable; + if ("value" in desc || desc.initializer) { + desc.writable = true; + } + desc = decorators.slice().reverse().reduce(function(desc, decorator) { + return decorator(target, property, desc) || desc; + }, desc); + if (context && desc.initializer !== void 0) { + desc.value = desc.initializer ? desc.initializer.call(context) : void 0; + desc.initializer = undefined; + } + if (desc.initializer === void 0) { + Object.defineProperty(target, property, desc); + desc = null; + } + return desc; +} +function _initializerDefineProperty(target, property, descriptor, context) { + if (!descriptor) return; + Object.defineProperty(target, property, { + enumerable: descriptor.enumerable, + configurable: descriptor.configurable, + writable: descriptor.writable, + value: descriptor.initializer ? descriptor.initializer.call(context) : void 0 + }); +} +var _class, _descriptor, _dec, _dec1; +function MyDecorator(klass) { + return ()=>{ + // do something + console.log(klass); + }; +} +let MyClass = ((_class = class MyClass1 { + constructor(){ + _initializerDefineProperty(this, "prop", _descriptor, this); + } +}) || _class, _dec = MyDecorator(_class), _dec1 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", String), _descriptor = _applyDecoratedDescriptor(_class.prototype, "prop", [ + _dec, + _dec1 +], { + configurable: true, + enumerable: true, + writable: true, + initializer: void 0 +}), _class); +console.log(new MyClass()); diff --git a/tests/fixture/issue-1345/output/index.ts b/tests/fixture/issue-1345/output/index.ts index c0a32d87f22a..1e259c913c94 100644 --- a/tests/fixture/issue-1345/output/index.ts +++ b/tests/fixture/issue-1345/output/index.ts @@ -36,24 +36,12 @@ function _initializerDefineProperty(target, property, descriptor, context) { value: descriptor.initializer ? descriptor.initializer.call(context) : void 0 }); } -var _class, _descriptor, _descriptor1, _descriptor2, _descriptor3, _descriptor4, _descriptor5, _descriptor6, _descriptor7; -var _dec = ViewColumn({ - name: "tmcode" -}), _dec1 = ViewColumn({ - name: "mid" -}), _dec2 = ViewColumn({ - name: "accea" -}), _dec3 = ViewColumn({ - name: "qaccea" -}), _dec4 = ViewColumn({ - name: "endday" -}), _dec5 = ViewColumn({ - name: "quick_endday" -}), _dec6 = ViewColumn(), _dec7 = ViewColumn(), _dec8 = ViewEntity({ +var _class, _descriptor, _dec, _dec1, _descriptor1, _dec2, _dec3, _descriptor2, _dec4, _dec5, _descriptor3, _dec6, _dec7, _descriptor4, _dec8, _dec9, _descriptor5, _dec10, _dec11, _descriptor6, _dec12, _dec13, _descriptor7, _dec14, _dec15; +var _dec16 = ViewEntity({ name: "AccountMemberView", expression: "\n SELECT\n m.tmcode, m.mid, m.accea, m.qaccea, m.endday, m.quick_endday,\n (SELECT COUNT(*) FROM TBLACCOUNT a WHERE m.mid = a.mid AND a.use_quick=\"F\") as accountCnt,\n (SELECT COUNT(*) FROM TBLACCOUNT a WHERE m.mid = a.mid AND a.use_quick=\"T\") as accountQuickCnt\n FROM TBLMEMBER m\n " }); -export var AccountMemberView = _class = _dec8((_class = function AccountMemberView1() { +export var AccountMemberView = _class = _dec16((_class = function AccountMemberView1() { "use strict"; _classCallCheck(this, AccountMemberView1); _initializerDefineProperty(this, "memberId", _descriptor, this); @@ -64,65 +52,77 @@ export var AccountMemberView = _class = _dec8((_class = function AccountMemberVi _initializerDefineProperty(this, "accountQuickEnddedAt", _descriptor5, this); _initializerDefineProperty(this, "accountCnt", _descriptor6, this); _initializerDefineProperty(this, "accountQuickCnt", _descriptor7, this); -}, _descriptor = _applyDecoratedDescriptor(_class.prototype, "memberId", [ +}, _dec = ViewColumn({ + name: "tmcode" +}), _dec1 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Number), _dec2 = ViewColumn({ + name: "mid" +}), _dec3 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", String), _dec4 = ViewColumn({ + name: "accea" +}), _dec5 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Number), _dec6 = ViewColumn({ + name: "qaccea" +}), _dec7 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Number), _dec8 = ViewColumn({ + name: "endday" +}), _dec9 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", typeof Date === "undefined" ? Object : Date), _dec10 = ViewColumn({ + name: "quick_endday" +}), _dec11 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", typeof Date === "undefined" ? Object : Date), _dec12 = ViewColumn(), _dec13 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Number), _dec14 = ViewColumn(), _dec15 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Number), _descriptor = _applyDecoratedDescriptor(_class.prototype, "memberId", [ _dec, - typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Number) + _dec1 ], { configurable: true, enumerable: true, writable: true, initializer: void 0 }), _descriptor1 = _applyDecoratedDescriptor(_class.prototype, "mallId", [ - _dec1, - typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", String) + _dec2, + _dec3 ], { configurable: true, enumerable: true, writable: true, initializer: void 0 }), _descriptor2 = _applyDecoratedDescriptor(_class.prototype, "allowAccountCnt", [ - _dec2, - typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Number) + _dec4, + _dec5 ], { configurable: true, enumerable: true, writable: true, initializer: void 0 }), _descriptor3 = _applyDecoratedDescriptor(_class.prototype, "allowQuickAccountCnt", [ - _dec3, - typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Number) + _dec6, + _dec7 ], { configurable: true, enumerable: true, writable: true, initializer: void 0 }), _descriptor4 = _applyDecoratedDescriptor(_class.prototype, "accountEnddedAt", [ - _dec4, - typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", typeof Date === "undefined" ? Object : Date) + _dec8, + _dec9 ], { configurable: true, enumerable: true, writable: true, initializer: void 0 }), _descriptor5 = _applyDecoratedDescriptor(_class.prototype, "accountQuickEnddedAt", [ - _dec5, - typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", typeof Date === "undefined" ? Object : Date) + _dec10, + _dec11 ], { configurable: true, enumerable: true, writable: true, initializer: void 0 }), _descriptor6 = _applyDecoratedDescriptor(_class.prototype, "accountCnt", [ - _dec6, - typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Number) + _dec12, + _dec13 ], { configurable: true, enumerable: true, writable: true, initializer: void 0 }), _descriptor7 = _applyDecoratedDescriptor(_class.prototype, "accountQuickCnt", [ - _dec7, - typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Number) + _dec14, + _dec15 ], { configurable: true, enumerable: true, diff --git a/tests/fixture/issue-1421/case1/output/index.ts b/tests/fixture/issue-1421/case1/output/index.ts index dd983bb8cc2a..7c2a3bfc372a 100644 --- a/tests/fixture/issue-1421/case1/output/index.ts +++ b/tests/fixture/issue-1421/case1/output/index.ts @@ -38,19 +38,18 @@ function _initializerDefineProperty(target, property, descriptor, context) { value: descriptor.initializer ? descriptor.initializer.call(context) : void 0 }); } -var _class, _descriptor; +var _class, _descriptor, _dec, _dec1; var COL_KEY = Symbol('col'); var column = function() { return function(object, key) { Reflect.defineMetadata(COL_KEY, 'value', object, key); }; }; -var _dec = column(), _dec1 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", String); var User = ((_class = function User1() { "use strict"; _classCallCheck(this, User1); _initializerDefineProperty(this, "currency", _descriptor, this); -}) || _class, _descriptor = _applyDecoratedDescriptor(_class.prototype, "currency", [ +}) || _class, _dec = column(), _dec1 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", String), _descriptor = _applyDecoratedDescriptor(_class.prototype, "currency", [ _dec, _dec1 ], { diff --git a/wasm/Cargo.toml b/wasm/Cargo.toml index 316f2402393c..dbdb3e7e1980 100644 --- a/wasm/Cargo.toml +++ b/wasm/Cargo.toml @@ -6,7 +6,7 @@ license = "Apache-2.0 AND MIT" name = "wasm" publish = false repository = "https://github.com/swc-project/swc.git" -version = "1.2.63" +version = "1.2.64" [lib] crate-type = ["cdylib"]