fix(strip): Transform static class fields to assignments (#1487)

swc_ecam_transforms_compat:
 - Deprecate `typescript_class_properties`.

swc_ecma_tranforms_typescript:
 - Merge `typescript_class_properties` into `strip`.

Co-authored-by: 강동윤 <kdy1997.dev@gmail.com>
This commit is contained in:
Nayeem Rahman 2021-03-26 04:48:55 +00:00 committed by GitHub
parent 0351a47678
commit fa3d65cd58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 414 additions and 258 deletions

View File

@ -11,7 +11,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc"
repository = "https://github.com/swc-project/swc.git"
version = "0.12.0"
version = "0.12.1"
[lib]
name = "swc"
@ -33,8 +33,8 @@ swc_ecma_ast = {version = "0.41.0", path = "./ecmascript/ast"}
swc_ecma_codegen = {version = "0.49.0", path = "./ecmascript/codegen"}
swc_ecma_ext_transforms = {version = "0.9.0", path = "./ecmascript/ext-transforms"}
swc_ecma_parser = {version = "0.51.0", path = "./ecmascript/parser"}
swc_ecma_preset_env = {version = "0.12.0", path = "./ecmascript/preset_env"}
swc_ecma_transforms = {version = "0.42.0", path = "./ecmascript/transforms", features = [
swc_ecma_preset_env = {version = "0.12.1", path = "./ecmascript/preset_env"}
swc_ecma_transforms = {version = "0.42.1", path = "./ecmascript/transforms", features = [
"compat",
"module",
"optimization",

View File

@ -9,7 +9,7 @@ include = ["Cargo.toml", "build.rs", "src/**/*.rs", "src/**/*.js"]
license = "Apache-2.0/MIT"
name = "swc_bundler"
repository = "https://github.com/swc-project/swc.git"
version = "0.29.0"
version = "0.29.1"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
@ -35,7 +35,7 @@ swc_common = {version = "0.10.10", path = "../common"}
swc_ecma_ast = {version = "0.41.0", path = "../ecmascript/ast"}
swc_ecma_codegen = {version = "0.49.0", path = "../ecmascript/codegen"}
swc_ecma_parser = {version = "0.51.0", path = "../ecmascript/parser"}
swc_ecma_transforms = {version = "0.42.0", path = "../ecmascript/transforms", features = ["optimization"]}
swc_ecma_transforms = {version = "0.42.1", path = "../ecmascript/transforms", features = ["optimization"]}
swc_ecma_utils = {version = "0.32.0", path = "../ecmascript/utils"}
swc_ecma_visit = {version = "0.27.0", path = "../ecmascript/visit"}
@ -44,7 +44,7 @@ hex = "0.4"
ntest = "0.7.2"
reqwest = {version = "0.10.8", features = ["blocking"]}
sha-1 = "0.9"
swc_ecma_transforms = {version = "0.42.0", path = "../ecmascript/transforms", features = ["react", "typescript"]}
swc_ecma_transforms = {version = "0.42.1", path = "../ecmascript/transforms", features = ["react", "typescript"]}
tempfile = "3.1.0"
testing = {version = "0.10.3", path = "../testing"}
url = "2.1.1"

View File

@ -548,7 +548,9 @@ where
Some(exported) => {
debug_assert_eq!(
exported.span.ctxt, self.module_ctxt,
"Exported names should have same (local) context as top-level module items"
"Exported names should have same (local) context as top-level module \
items\n{}\n{:?}",
self.path, s
);
}
None => {

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_ecmascript"
repository = "https://github.com/swc-project/swc.git"
version = "0.28.0"
version = "0.28.1"
[package.metadata.docs.rs]
all-features = true
@ -31,7 +31,7 @@ swc_ecma_ast = {version = "0.41.0", path = "./ast"}
swc_ecma_codegen = {version = "0.49.0", path = "./codegen", optional = true}
swc_ecma_dep_graph = {version = "0.19.0", path = "./dep-graph", optional = true}
swc_ecma_parser = {version = "0.51.0", path = "./parser", optional = true}
swc_ecma_transforms = {version = "0.42.0", path = "./transforms", optional = true}
swc_ecma_transforms = {version = "0.42.1", path = "./transforms", optional = true}
swc_ecma_utils = {version = "0.32.0", path = "./utils", optional = true}
swc_ecma_visit = {version = "0.27.0", path = "./visit", optional = true}

View File

@ -5,7 +5,7 @@ documentation = "https://swc.rs/rustdoc/swc_ecma_preset_env/"
edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_ecma_preset_env"
version = "0.12.0"
version = "0.12.1"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -21,7 +21,7 @@ string_enum = {version = "0.3.1", path = "../../macros/string_enum"}
swc_atoms = {version = "0.2", path = "../../atoms"}
swc_common = {version = "0.10.10", path = "../../common"}
swc_ecma_ast = {version = "0.41.0", path = "../ast"}
swc_ecma_transforms = {version = "0.42.0", path = "../transforms", features = ["compat", "proposal"]}
swc_ecma_transforms = {version = "0.42.1", path = "../transforms", features = ["compat", "proposal"]}
swc_ecma_utils = {version = "0.32.0", path = "../utils"}
swc_ecma_visit = {version = "0.27.0", path = "../visit"}
walkdir = "2"

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_ecma_transforms"
repository = "https://github.com/swc-project/swc.git"
version = "0.42.0"
version = "0.42.1"
[package.metadata.docs.rs]
all-features = true
@ -26,12 +26,12 @@ swc_common = {version = "0.10.10", path = "../../common"}
swc_ecma_ast = {version = "0.41.0", path = "../ast"}
swc_ecma_parser = {version = "0.51.0", path = "../parser"}
swc_ecma_transforms_base = {version = "0.9.0", path = "./base"}
swc_ecma_transforms_compat = {version = "0.10.0", path = "./compat", optional = true}
swc_ecma_transforms_module = {version = "0.10.0", path = "./module", optional = true}
swc_ecma_transforms_optimization = {version = "0.12.0", path = "./optimization", optional = true}
swc_ecma_transforms_proposal = {version = "0.10.0", path = "./proposal", optional = true}
swc_ecma_transforms_react = {version = "0.11.0", path = "./react", optional = true}
swc_ecma_transforms_typescript = {version = "0.11.0", path = "./typescript", optional = true}
swc_ecma_transforms_compat = {version = "0.10.1", path = "./compat", optional = true}
swc_ecma_transforms_module = {version = "0.10.1", path = "./module", optional = true}
swc_ecma_transforms_optimization = {version = "0.12.1", path = "./optimization", optional = true}
swc_ecma_transforms_proposal = {version = "0.10.1", path = "./proposal", optional = true}
swc_ecma_transforms_react = {version = "0.11.1", path = "./react", optional = true}
swc_ecma_transforms_typescript = {version = "0.11.1", path = "./typescript", optional = true}
swc_ecma_utils = {version = "0.32.0", path = "../utils"}
swc_ecma_visit = {version = "0.27.0", path = "../visit"}
unicode-xid = "0.2"

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_ecma_transforms_compat"
repository = "https://github.com/swc-project/swc.git"
version = "0.10.0"
version = "0.10.1"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@ -1,3 +1,4 @@
#[allow(deprecated)]
pub use self::{
class_properties::{class_properties, typescript_class_properties},
export_namespace_from::export_namespace_from,

View File

@ -41,6 +41,7 @@ pub fn class_properties() -> impl Fold {
}
/// Class properties pass for the typescript.
#[deprecated = "The logic is merged into typescript::strip"]
pub fn typescript_class_properties() -> impl Fold {
ClassProperties {
typescript: true,

View File

@ -1,4 +1,6 @@
#![feature(test)]
#![allow(deprecated)]
use swc_common::chain;
use swc_ecma_parser::{EsConfig, Syntax, TsConfig};
use swc_ecma_transforms_base::resolver::resolver;

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_ecma_transforms_module"
repository = "https://github.com/swc-project/swc.git"
version = "0.10.0"
version = "0.10.1"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
@ -23,6 +23,6 @@ swc_ecma_utils = {version = "0.32.0", path = "../../utils"}
swc_ecma_visit = {version = "0.27.0", path = "../../visit"}
[dev-dependencies]
swc_ecma_transforms_compat = {version = "0.10.0", path = "../compat"}
swc_ecma_transforms_compat = {version = "0.10.1", path = "../compat"}
swc_ecma_transforms_testing = {version = "0.9.0", path = "../testing/"}
testing = {version = "0.10.3", path = "../../../testing/"}

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_ecma_transforms_optimization"
repository = "https://github.com/swc-project/swc.git"
version = "0.12.0"
version = "0.12.1"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
@ -26,10 +26,10 @@ swc_ecma_utils = {version = "0.32.0", path = "../../utils"}
swc_ecma_visit = {version = "0.27.0", path = "../../visit"}
[dev-dependencies]
swc_ecma_transforms_compat = {version = "0.10.0", path = "../compat"}
swc_ecma_transforms_module = {version = "0.10.0", path = "../module"}
swc_ecma_transforms_proposal = {version = "0.10.0", path = "../proposal"}
swc_ecma_transforms_react = {version = "0.11.0", path = "../react"}
swc_ecma_transforms_compat = {version = "0.10.1", path = "../compat"}
swc_ecma_transforms_module = {version = "0.10.1", path = "../module"}
swc_ecma_transforms_proposal = {version = "0.10.1", path = "../proposal"}
swc_ecma_transforms_react = {version = "0.11.1", path = "../react"}
swc_ecma_transforms_testing = {version = "0.9.0", path = "../testing"}
swc_ecma_transforms_typescript = {version = "0.11.0", path = "../typescript"}
swc_ecma_transforms_typescript = {version = "0.11.1", path = "../typescript"}
testing = {version = "0.10.0", path = "../../../testing"}

View File

@ -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.10.0"
version = "0.10.1"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -29,6 +29,6 @@ swc_ecma_utils = {version = "0.32.0", path = "../../utils"}
swc_ecma_visit = {version = "0.27.0", path = "../../visit"}
[dev-dependencies]
swc_ecma_transforms_compat = {version = "0.10.0", path = "../compat"}
swc_ecma_transforms_module = {version = "0.10.0", path = "../module"}
swc_ecma_transforms_compat = {version = "0.10.1", path = "../compat"}
swc_ecma_transforms_module = {version = "0.10.1", path = "../module"}
swc_ecma_transforms_testing = {version = "0.9.0", path = "../testing"}

View File

@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"]
license = "Apache-2.0/MIT"
name = "swc_ecma_transforms_react"
repository = "https://github.com/swc-project/swc.git"
version = "0.11.0"
version = "0.11.1"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
@ -25,7 +25,7 @@ swc_ecma_utils = {version = "0.32.0", path = "../../utils"}
swc_ecma_visit = {version = "0.27.0", path = "../../visit"}
[dev-dependencies]
swc_ecma_transforms_compat = {version = "0.10.0", path = "../compat/"}
swc_ecma_transforms_module = {version = "0.10.0", path = "../module"}
swc_ecma_transforms_compat = {version = "0.10.1", path = "../compat/"}
swc_ecma_transforms_module = {version = "0.10.1", path = "../module"}
swc_ecma_transforms_testing = {version = "0.9.0", path = "../testing/"}
testing = {version = "0.10.3", path = "../../../testing"}

View File

@ -43,18 +43,17 @@ fn tr() -> impl Fold {
fn ts_transform() -> impl Fold {
chain!(
strip(),
decorators(Config {
legacy: true,
..Default::default()
}),
class_properties(),
strip(),
)
}
/// Folder for `transformation_*` tests
fn transformation() -> impl Fold {
chain!(strip(), decorators(Default::default()), class_properties(),)
chain!(decorators(Default::default()), strip(),)
}
// transformation_declaration
@ -2034,11 +2033,11 @@ expect(typeof Parent.prototype.child).toBe("function");
test!(
syntax(true),
|_| chain!(
strip(),
decorators(decorators::Config {
legacy: true,
..Default::default()
})
}),
strip()
),
legacy_regression_10264,
r#"
@ -4273,11 +4272,11 @@ test!(
..Default::default()
}),
|_| chain!(
strip(),
decorators(Config {
legacy: true,
..Default::default()
})
}),
strip()
),
issue_823_1,
"import {Debounce} from 'lodash-decorators';
@ -4294,12 +4293,15 @@ 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!');
let Person = ((_class = function() {
class Person {
save() {
console.log('Hello World!');
}
}
}) || _class, _dec = Debounce(_class.debounceTime), _applyDecoratedDescriptor(_class.prototype, \
Person.debounceTime = 500;
return Person;
}()) || _class, _dec = Debounce(_class.debounceTime), _applyDecoratedDescriptor(_class.prototype, \
'save', [
_dec
], Object.getOwnPropertyDescriptor(_class.prototype, 'save'), _class.prototype), _class);
@ -4313,12 +4315,11 @@ test!(
..Default::default()
}),
|_| chain!(
strip(),
decorators(Config {
legacy: true,
..Default::default()
}),
class_properties(),
strip(),
// classes(),
),
issue_823_2,
@ -4342,7 +4343,7 @@ let Person = ((_class = function() {
console.log('Hello World!');
}
}
_defineProperty(Person, 'debounceTime', 500);
Person.debounceTime = 500;
return Person;
}()) || _class, _dec = Debounce(_class.debounceTime), _applyDecoratedDescriptor(_class.prototype, \
'save', [
@ -4359,12 +4360,11 @@ test!(
..Default::default()
}),
|_| chain!(
strip(),
decorators(Config {
legacy: true,
..Default::default()
}),
class_properties(),
strip(),
classes(),
),
issue_823_3,
@ -4398,7 +4398,7 @@ let Person = ((_class = function() {
]);
return Person;
}();
_defineProperty(Person, 'debounceTime', 500);
Person.debounceTime = 500;
return Person;
}()) || _class, _dec = Debounce(_class.debounceTime), _applyDecoratedDescriptor(_class.prototype, \
'save', [
@ -4444,20 +4444,17 @@ var _dec = PrimaryGeneratedColumn('uuid'), _dec1 = Column(), _dec2 = Column({
), _dec5 = OneToMany(()=>Discount
, (discount)=>discount.product
), _dec6 = Entity();
export let Product = _class = _dec6(((_class = function() {
class Product extends TimestampedEntity {
constructor(...args){
super(...args);
_initializerDefineProperty(this, 'id', _descriptor, this);
_initializerDefineProperty(this, 'price', _descriptor1, this);
_initializerDefineProperty(this, 'type', _descriptor2, this);
_initializerDefineProperty(this, 'productEntityId', _descriptor3, this);
_initializerDefineProperty(this, 'orders', _descriptor4, this);
_initializerDefineProperty(this, 'discounts', _descriptor5, this);
}
}
return Product;
}()) || _class, _descriptor = _applyDecoratedDescriptor(_class.prototype, 'id', [
export let Product = _class = _dec6(((_class = class Product extends TimestampedEntity {
constructor(...args){
super(...args);
_initializerDefineProperty(this, 'id', _descriptor, this);
_initializerDefineProperty(this, 'price', _descriptor1, this);
_initializerDefineProperty(this, 'type', _descriptor2, this);
_initializerDefineProperty(this, 'productEntityId', _descriptor3, this);
_initializerDefineProperty(this, 'orders', _descriptor4, this);
_initializerDefineProperty(this, 'discounts', _descriptor5, this);
}
}) || _class, _descriptor = _applyDecoratedDescriptor(_class.prototype, 'id', [
_dec
], {
configurable: true,
@ -4515,15 +4512,12 @@ export class Product extends TimestampedEntity {
",
"var _class, _descriptor;
var _dec = PrimaryGeneratedColumn(\"uuid\"), _dec1 = Entity();
export let Product = _class = _dec1(((_class = function() {
class Product extends TimestampedEntity {
export let Product = _class = _dec1(((_class = class Product extends TimestampedEntity {
constructor(...args){
super(...args);
_initializerDefineProperty(this, 'id', _descriptor, this);
}
}
return Product;
}()) || _class, _descriptor = _applyDecoratedDescriptor(_class.prototype, 'id', [
}) || _class, _descriptor = _applyDecoratedDescriptor(_class.prototype, 'id', [
_dec
], {
configurable: true,
@ -4572,13 +4566,10 @@ test!(
}
}",
" var _class, _dec;
let ProductController = ((_class = function() {
class ProductController {
findById(id) {
}
let ProductController = ((_class = class ProductController {
findById(id) {
}
return ProductController;
}()) || _class, foo()(_class.prototype, 'findById', 0), _dec = bar(), \
}) || _class, foo()(_class.prototype, 'findById', 0), _dec = bar(), \
_applyDecoratedDescriptor(_class.prototype, 'findById', [
_dec
], Object.getOwnPropertyDescriptor(_class.prototype, 'findById'), _class.prototype), _class);"
@ -4621,13 +4612,12 @@ c.findById(100);
test!(
ts(),
|_| chain!(
strip(),
inlining::inlining(inlining::Config {}),
decorators(Config {
legacy: true,
..Default::default()
}),
class_properties(),
strip(),
),
issue_879_1,
"export default class X {
@ -4635,14 +4625,11 @@ test!(
prop: string = '';
}",
"var _class, _descriptor;
let X = ((_class = function() {
class X {
constructor(){
_initializerDefineProperty(this, 'prop', _descriptor, this);
}
let X = ((_class = class X {
constructor(){
_initializerDefineProperty(this, 'prop', _descriptor, this);
}
return X;
}()) || _class, _descriptor = _applyDecoratedDescriptor(_class.prototype, 'prop', [
}) || _class, _descriptor = _applyDecoratedDescriptor(_class.prototype, 'prop', [
networked
], {
configurable: true,

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_ecma_transforms_typescript"
repository = "https://github.com/swc-project/swc.git"
version = "0.11.0"
version = "0.11.1"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
@ -22,9 +22,9 @@ swc_ecma_visit = {version = "0.27.0", path = "../../visit"}
[dev-dependencies]
swc_ecma_codegen = {version = "0.49.0", path = "../../codegen"}
swc_ecma_transforms_compat = {version = "0.10.0", path = "../compat"}
swc_ecma_transforms_module = {version = "0.10.0", path = "../module"}
swc_ecma_transforms_proposal = {version = "0.10.0", path = "../proposal/"}
swc_ecma_transforms_compat = {version = "0.10.1", path = "../compat"}
swc_ecma_transforms_module = {version = "0.10.1", path = "../module"}
swc_ecma_transforms_proposal = {version = "0.10.1", path = "../proposal/"}
swc_ecma_transforms_testing = {version = "0.9.0", path = "../testing"}
testing = {version = "0.10.3", path = "../../../testing"}
walkdir = "2.3.1"

View File

@ -107,13 +107,6 @@ fn es2020_optional_chaining(b: &mut Bencher) {
});
}
#[bench]
fn es2020_typescript_class_properties(b: &mut Bencher) {
run(b, || {
swc_ecma_transforms_compat::es2020::typescript_class_properties()
});
}
#[bench]
fn es2020_class_properties(b: &mut Bencher) {
run(b, || swc_ecma_transforms_compat::es2020::class_properties());

View File

@ -9,7 +9,7 @@ use swc_ecma_utils::private_ident;
use swc_ecma_utils::var::VarCollector;
use swc_ecma_utils::ExprFactory;
use swc_ecma_utils::{constructor::inject_after_super, default_constructor};
use swc_ecma_utils::{ident::IdentLike, Id, StmtLike};
use swc_ecma_utils::{ident::IdentLike, Id, ModuleItemLike, StmtLike};
use swc_ecma_visit::{as_folder, Fold, Node, Visit, VisitMut, VisitMutWith, VisitWith};
/// Value does not contain TsLit::Bool
@ -153,7 +153,13 @@ impl Strip {
}
impl Strip {
fn transform_class_fields(&mut self, class: &mut Class) {
fn fold_class_as_decl(&mut self, ident: Ident, mut class: Class) -> (Decl, Vec<Stmt>) {
class.is_abstract = false;
class.type_params = None;
class.super_type_params = None;
class.implements = Default::default();
let mut extra_stmts = vec![];
if self.config.use_define_for_class_fields {
let mut param_class_fields = vec![];
for member in &class.body {
@ -197,68 +203,236 @@ impl Strip {
param_class_fields.append(&mut class.body.take());
class.body = param_class_fields;
}
return;
}
let mut assign_exprs = vec![];
let mut new_body = vec![];
for member in take(&mut class.body) {
match member {
// This handling is for non-static fields only. Also preserve
// fields with decorators for now, these should be transformed
// differently during the `decorators()` pass.
ClassMember::ClassProp(mut class_field)
if !class_field.is_static && class_field.decorators.is_empty() =>
{
if let Some(value) = class_field.value.take() {
let computed = class_field.computed
|| !matches!(class_field.key.borrow(), Expr::Ident(_));
let assign_lhs = PatOrExpr::Expr(Box::new(Expr::Member(MemberExpr {
span: class_field.span,
obj: ExprOrSuper::Expr(Box::new(Expr::This(ThisExpr {
span: class.span,
}))),
prop: class_field.key,
computed,
})));
let assign_expr = Box::new(Expr::Assign(AssignExpr {
span: class_field.span,
op: op!("="),
left: assign_lhs,
right: value,
}));
assign_exprs.push(assign_expr);
}
}
// TODO(nayeemrmn): Static fields should also be moved to
// assignments after the class. Figure out how. They are
// preserved for now.
// ClassMember::ClassProp(_) => { ... }
_ => {
new_body.push(member);
}
}
}
if !assign_exprs.is_empty() {
for member in &mut new_body {
} else {
let mut assign_exprs = vec![];
let mut new_body = vec![];
for member in take(&mut class.body) {
match member {
ClassMember::Constructor(constructor) => {
inject_after_super(constructor, take(&mut assign_exprs));
break;
ClassMember::ClassProp(mut class_field)
if !class_field.is_static && class_field.decorators.is_empty() =>
{
if let Some(value) = class_field.value.take() {
let computed = class_field.computed
|| !matches!(class_field.key.borrow(), Expr::Ident(_));
let assign_lhs = PatOrExpr::Expr(Box::new(Expr::Member(MemberExpr {
span: class_field.span,
obj: ExprOrSuper::Expr(Box::new(Expr::This(ThisExpr {
span: class.span,
}))),
prop: class_field.key,
computed,
})));
let assign_expr = Box::new(Expr::Assign(AssignExpr {
span: class_field.span,
op: op!("="),
left: assign_lhs,
right: value,
}));
assign_exprs.push(assign_expr);
}
}
ClassMember::ClassProp(mut class_field)
if class_field.is_static && class_field.decorators.is_empty() =>
{
if let Some(value) = class_field.value.take() {
let computed = class_field.computed
|| !matches!(class_field.key.borrow(), Expr::Ident(_));
let assign_lhs = PatOrExpr::Expr(Box::new(Expr::Member(MemberExpr {
span: DUMMY_SP,
obj: ident.clone().as_obj(),
prop: class_field.key,
computed,
})));
extra_stmts.push(
AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: assign_lhs,
right: value,
}
.into_stmt(),
);
}
}
_ => {
new_body.push(member);
}
_ => {}
}
}
if !assign_exprs.is_empty() {
let mut constructor = default_constructor(class.super_class.is_some());
inject_after_super(&mut constructor, assign_exprs);
new_body.push(ClassMember::Constructor(constructor));
for member in &mut new_body {
match member {
ClassMember::Constructor(constructor) => {
inject_after_super(constructor, take(&mut assign_exprs));
break;
}
_ => {}
}
}
if !assign_exprs.is_empty() {
let mut constructor = default_constructor(class.super_class.is_some());
inject_after_super(&mut constructor, assign_exprs);
new_body.push(ClassMember::Constructor(constructor));
}
}
class.body = new_body;
}
class.decorators.visit_mut_with(self);
class.body.visit_mut_with(self);
class.super_class.visit_mut_with(self);
extra_stmts.visit_mut_with(self);
(
Decl::Class(ClassDecl {
ident,
declare: false,
class,
}),
extra_stmts,
)
}
fn visit_mut_stmt_like<T>(&mut self, stmts: &mut Vec<T>)
where
T: StmtLike + ModuleItemLike + VisitMutWith<Self>,
{
for stmt in take(stmts) {
match T::try_into_stmt(stmt) {
Ok(stmt) => match stmt {
Stmt::Decl(Decl::Class(ClassDecl {
ident,
declare: false,
class,
})) => {
let (decl, extra_stmts) = self.fold_class_as_decl(ident, class);
stmts.push(T::from_stmt(Stmt::Decl(decl)));
stmts.extend(extra_stmts.into_iter().map(T::from_stmt));
}
_ => stmts.push(T::from_stmt(stmt)),
},
Err(node) => match node.try_into_module_decl() {
Ok(decl) => match decl {
ModuleDecl::ExportDefaultDecl(ExportDefaultDecl {
span,
decl: DefaultDecl::Class(ClassExpr { ident, class }),
..
}) => {
let ident = ident.unwrap_or_else(|| private_ident!("_class"));
let (decl, extra_stmts) = self.fold_class_as_decl(ident.clone(), class);
stmts.push(T::from_stmt(Stmt::Decl(decl)));
stmts.extend(extra_stmts.into_iter().map(T::from_stmt));
stmts.push(
match T::try_from_module_decl(ModuleDecl::ExportNamed(
NamedExport {
span,
specifiers: vec![ExportNamedSpecifier {
span: DUMMY_SP,
orig: ident,
exported: Some(Ident::new(
js_word!("default"),
DUMMY_SP,
)),
}
.into()],
src: None,
type_only: false,
asserts: None,
},
)) {
Ok(t) => t,
Err(..) => unreachable!(),
},
);
}
ModuleDecl::ExportDecl(ExportDecl {
span,
decl:
Decl::Class(ClassDecl {
ident,
declare: false,
class,
}),
..
}) => {
let (decl, extra_stmts) = self.fold_class_as_decl(ident, class);
stmts.push(
match T::try_from_module_decl(ModuleDecl::ExportDecl(ExportDecl {
span,
decl,
})) {
Ok(t) => t,
Err(..) => unreachable!(),
},
);
stmts.extend(extra_stmts.into_iter().map(T::from_stmt));
}
_ => stmts.push(match T::try_from_module_decl(decl) {
Ok(t) => t,
Err(..) => unreachable!(),
}),
},
Err(_) => unreachable!(),
},
}
}
class.body = new_body;
}
/// Returns [Some] if the method should be called again.
fn handle_expr<'a>(&mut self, n: &'a mut Expr) -> Vec<&'a mut Expr> {
if n.is_class() {
// TODO(kdy1): Make it generate smaller code.
//
// We currently creates a iife for a class expression.
// Although this results in a large code, but it's ok as class expression is
// rarely used in wild.
let ClassExpr {
ident: old_ident,
class,
} = n.take().class().unwrap();
let ident = old_ident
.clone()
.unwrap_or_else(|| private_ident!("_class"));
let (decl, extra_stmts) = self.fold_class_as_decl(ident.clone(), class);
if extra_stmts.is_empty() {
*n = Expr::Class(ClassExpr {
ident: old_ident,
class: decl.class().unwrap().class,
});
} else {
let mut stmts = vec![];
stmts.push(Stmt::Decl(decl));
stmts.extend(extra_stmts);
stmts.push(Stmt::Return(ReturnStmt {
span: DUMMY_SP,
arg: Some(Box::new(Expr::Ident(ident))),
}));
*n = Expr::Call(CallExpr {
span: DUMMY_SP,
callee: FnExpr {
ident: None,
function: Function {
span: DUMMY_SP,
decorators: vec![],
is_async: false,
is_generator: false,
params: vec![],
body: Some(BlockStmt {
span: DUMMY_SP,
stmts,
}),
type_params: Default::default(),
return_type: Default::default(),
},
}
.as_callee(),
args: vec![],
type_args: Default::default(),
});
}
return vec![];
}
match n {
Expr::Bin(BinExpr { left, right, .. }) => return vec![&mut **left, &mut **right],
@ -939,26 +1113,29 @@ macro_rules! type_to_none {
}
impl VisitMut for Strip {
fn visit_mut_block_stmt_or_expr(&mut self, n: &mut BlockStmtOrExpr) {
match n {
BlockStmtOrExpr::Expr(expr) if expr.is_class() => {
let ClassExpr { ident, class } = expr.take().class().unwrap();
let ident = ident.unwrap_or_else(|| private_ident!("_class"));
let (decl, extra_stmts) = self.fold_class_as_decl(ident, class);
let mut stmts = vec![];
stmts.push(Stmt::Decl(decl));
stmts.extend(extra_stmts);
*n = BlockStmtOrExpr::BlockStmt(BlockStmt {
span: n.span(),
stmts,
});
}
_ => n.visit_mut_children_with(self),
};
}
fn visit_mut_array_pat(&mut self, n: &mut ArrayPat) {
n.visit_mut_children_with(self);
n.optional = false;
}
fn visit_mut_class(&mut self, n: &mut Class) {
n.is_abstract = false;
n.type_params = None;
n.super_type_params = None;
n.implements = Default::default();
self.transform_class_fields(n);
n.decorators.visit_mut_with(self);
n.body.visit_mut_with(self);
n.super_class.visit_mut_with(self);
}
fn visit_mut_constructor(&mut self, n: &mut Constructor) {
n.visit_mut_children_with(self);
@ -1130,6 +1307,7 @@ impl VisitMut for Strip {
}
fn visit_mut_stmts(&mut self, orig: &mut Vec<Stmt>) {
self.visit_mut_stmt_like(orig);
// Second pass
let mut stmts = Vec::with_capacity(orig.len());
for mut item in take(orig) {
@ -1244,6 +1422,7 @@ impl VisitMut for Strip {
}
fn visit_mut_module_items(&mut self, items: &mut Vec<ModuleItem>) {
self.visit_mut_stmt_like(items);
items.visit_with(&Invalid { span: DUMMY_SP }, self);
let mut stmts = Vec::with_capacity(items.len());

View File

@ -5,7 +5,6 @@ use swc_ecma_transforms_compat::es2017::async_to_generator;
use swc_ecma_transforms_compat::es2020::class_properties;
use swc_ecma_transforms_compat::es2020::nullish_coalescing;
use swc_ecma_transforms_compat::es2020::optional_chaining;
use swc_ecma_transforms_compat::es2020::typescript_class_properties;
use swc_ecma_transforms_proposal::decorators;
use swc_ecma_transforms_testing::test;
use swc_ecma_transforms_testing::test_exec;
@ -604,11 +603,12 @@ to!(
console.log(a)
}
}",
"export default class FeatureSet {
"class FeatureSet {
log(a) {
console.log(a)
}
}"
}
export { FeatureSet as default };"
);
to!(
@ -748,9 +748,7 @@ test!(
test!(
::swc_ecma_parser::Syntax::Typescript(Default::default()),
// TODO(nayeemrmn): This output should be achieved without
// `typescript_class_properties()`.
|_| chain!(typescript_class_properties(), tr()),
|_| tr(),
issue_930_static,
"class A {
static b = 'foo';
@ -3271,12 +3269,7 @@ test!(
decorators: true,
..Default::default()
}),
|_| chain!(
strip(),
resolver(),
decorators(Default::default()),
class_properties()
),
|_| chain!(resolver(), decorators(Default::default()), strip()),
issue_367,
"

View File

@ -44,6 +44,13 @@ class BufReader {
/** return new BufReader unless r is BufReader */ static create(r, size = DEFAULT_BUF_SIZE) {
return r instanceof BufReader ? r : new BufReader(r, size);
}
constructor(rd1, size1 = DEFAULT_BUF_SIZE){
this.r = 0;
this.w = 0;
this.eof = false;
if (size1 < MIN_BUF_SIZE) size1 = MIN_BUF_SIZE;
this._reset(new Uint8Array(size1), rd1);
}
/** Returns the size of the underlying buffer in bytes. */ size() {
return this.buf.byteLength;
}
@ -317,13 +324,6 @@ class BufReader {
else if (avail < n) throw new BufferFullError(this.buf.subarray(this.r, this.w));
return this.buf.subarray(this.r, this.r + n);
}
constructor(rd, size1 = DEFAULT_BUF_SIZE){
this.r = 0;
this.w = 0;
this.eof = false;
if (size1 < MIN_BUF_SIZE) size1 = MIN_BUF_SIZE;
this._reset(new Uint8Array(size1), rd);
}
}
class AbstractBufBase {
/** Size returns the size of the underlying buffer in bytes. */ size() {
@ -346,6 +346,12 @@ class BufWriter extends AbstractBufBase {
/** return new BufWriter unless writer is BufWriter */ static create(writer, size = DEFAULT_BUF_SIZE) {
return writer instanceof BufWriter ? writer : new BufWriter(writer, size);
}
constructor(writer1, size2 = DEFAULT_BUF_SIZE){
super();
this.writer = writer1;
if (size2 <= 0) size2 = DEFAULT_BUF_SIZE;
this.buf = new Uint8Array(size2);
}
/** Discards any unflushed buffered data, clears any error, and
* resets buffer to write its output to w.
*/ reset(w) {
@ -398,17 +404,17 @@ class BufWriter extends AbstractBufBase {
totalBytesWritten += numBytesWritten;
return totalBytesWritten;
}
constructor(writer1, size2 = DEFAULT_BUF_SIZE){
super();
this.writer = writer1;
if (size2 <= 0) size2 = DEFAULT_BUF_SIZE;
this.buf = new Uint8Array(size2);
}
}
class BufWriterSync extends AbstractBufBase {
/** return new BufWriterSync unless writer is BufWriterSync */ static create(writer, size = DEFAULT_BUF_SIZE) {
return writer instanceof BufWriterSync ? writer : new BufWriterSync(writer, size);
}
constructor(writer2, size3 = DEFAULT_BUF_SIZE){
super();
this.writer = writer2;
if (size3 <= 0) size3 = DEFAULT_BUF_SIZE;
this.buf = new Uint8Array(size3);
}
/** Discards any unflushed buffered data, clears any error, and
* resets buffer to write its output to w.
*/ reset(w) {
@ -461,12 +467,6 @@ class BufWriterSync extends AbstractBufBase {
totalBytesWritten += numBytesWritten;
return totalBytesWritten;
}
constructor(writer2, size3 = DEFAULT_BUF_SIZE){
super();
this.writer = writer2;
if (size3 <= 0) size3 = DEFAULT_BUF_SIZE;
this.buf = new Uint8Array(size3);
}
}
const encoder = new TextEncoder();
function encode(input) {
@ -486,6 +486,12 @@ function charCode(s) {
return s.charCodeAt(0);
}
class TextProtoReader {
constructor(r2){
this.r = r2;
}
constructor(r1){
this.r = r1;
}
/** readLine() reads a single line from the TextProtoReader,
* eliding the final \n or \r\n from the returned string.
*/ async readLine() {
@ -553,9 +559,9 @@ class TextProtoReader {
// this.closeDot();
let line;
while(true){
const r = await this.r.readLine();
if (r === null) return null;
const { line: l , more } = r;
const r2 = await this.r.readLine();
if (r2 === null) return null;
const { line: l , more } = r2;
// Avoid the copy if the first call produced a full line.
if (!line && !more) {
// TODO(ry):
@ -577,10 +583,6 @@ class TextProtoReader {
}
return n;
}
constructor(r1){
this.r = r1;
this.r = r1;
}
}
const STATUS_TEXT = new Map([]);
function deferred() {
@ -593,7 +595,6 @@ function deferred() {
});
return Object.assign(promise, methods);
}
var tmp = Symbol.asyncIterator;
class MuxAsyncIterator {
add(iterator) {
++this.iteratorCount;
@ -631,12 +632,13 @@ class MuxAsyncIterator {
this.signal = deferred();
}
}
[tmp]() {
[Symbol.asyncIterator]() {
return this.iterate();
}
constructor(){
this.iteratorCount = 0;
this.yields = [];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this.throws = [];
this.signal = deferred();
}
@ -648,17 +650,17 @@ function emptyReader() {
}
};
}
function bodyReader(contentLength, r1) {
function bodyReader(contentLength, r2) {
let totalRead = 0;
let finished = false;
async function read(buf) {
if (finished) return null;
let result;
const remaining = contentLength - totalRead;
if (remaining >= buf.byteLength) result = await r1.read(buf);
if (remaining >= buf.byteLength) result = await r2.read(buf);
else {
const readBuf = buf.subarray(0, remaining);
result = await r1.read(readBuf);
result = await r2.read(readBuf);
}
if (result !== null) totalRead += result;
finished = totalRead === contentLength;
@ -668,9 +670,9 @@ function bodyReader(contentLength, r1) {
read
};
}
function chunkedBodyReader(h, r1) {
function chunkedBodyReader(h, r2) {
// Based on https://tools.ietf.org/html/rfc2616#section-19.4.6
const tp = new TextProtoReader(r1);
const tp = new TextProtoReader(r2);
let finished = false;
const chunks = [];
async function read(buf) {
@ -696,10 +698,10 @@ function chunkedBodyReader(h, r1) {
if (Number.isNaN(chunkSize) || chunkSize < 0) throw new Error("Invalid chunk size");
if (chunkSize > 0) {
if (chunkSize > buf.byteLength) {
let eof = await r1.readFull(buf);
let eof = await r2.readFull(buf);
if (eof === null) throw new Deno.errors.UnexpectedEof();
const restChunk = new Uint8Array(chunkSize - buf.byteLength);
eof = await r1.readFull(restChunk);
eof = await r2.readFull(restChunk);
if (eof === null) throw new Deno.errors.UnexpectedEof();
else chunks.push({
offset: 0,
@ -708,7 +710,7 @@ function chunkedBodyReader(h, r1) {
return buf.byteLength;
} else {
const bufToFill = buf.subarray(0, chunkSize);
const eof = await r1.readFull(bufToFill);
const eof = await r2.readFull(bufToFill);
if (eof === null) throw new Deno.errors.UnexpectedEof();
// Consume \r\n
if (await tp.readLine() === null) throw new Deno.errors.UnexpectedEof();
@ -717,8 +719,8 @@ function chunkedBodyReader(h, r1) {
} else {
assert(chunkSize === 0);
// Consume \r\n
if (await r1.readLine() === null) throw new Deno.errors.UnexpectedEof();
await readTrailers(h, r1);
if (await r2.readLine() === null) throw new Deno.errors.UnexpectedEof();
await readTrailers(h, r2);
finished = true;
return null;
}
@ -735,13 +737,13 @@ function isProhibidedForTrailer(key) {
]);
return s.has(key.toLowerCase());
}
async function readTrailers(headers, r1) {
async function readTrailers(headers, r2) {
const trailers = parseTrailer(headers.get("trailer"));
if (trailers == null) return;
const trailerNames = [
...trailers.keys()
];
const tp = new TextProtoReader(r1);
const tp = new TextProtoReader(r2);
const result = await tp.readMIMEHeader();
if (result == null) throw new Deno.errors.InvalidData("Missing trailer header.");
const undeclared = [
@ -769,9 +771,9 @@ function parseTrailer(field) {
]
));
}
async function writeChunkedBody(w, r1) {
async function writeChunkedBody(w, r2) {
const writer = BufWriter.create(w);
for await (const chunk of Deno.iter(r1)){
for await (const chunk of Deno.iter(r2)){
if (chunk.byteLength <= 0) continue;
const start = encoder.encode(`${chunk.byteLength.toString(16)}\r\n`);
const end = encoder.encode("\r\n");
@ -802,19 +804,19 @@ async function writeTrailers(w, headers, trailers) {
await writer.write(encoder.encode("\r\n"));
await writer.flush();
}
async function writeResponse(w, r1) {
async function writeResponse(w, r2) {
const protoMajor = 1;
const protoMinor = 1;
const statusCode = r1.status || 200;
const statusCode = r2.status || 200;
const statusText = STATUS_TEXT.get(statusCode);
const writer = BufWriter.create(w);
if (!statusText) throw new Deno.errors.InvalidData("Bad status code");
if (!r1.body) r1.body = new Uint8Array();
if (typeof r1.body === "string") r1.body = encoder.encode(r1.body);
if (!r2.body) r2.body = new Uint8Array();
if (typeof r2.body === "string") r2.body = encoder.encode(r2.body);
let out = `HTTP/${protoMajor}.${protoMinor} ${statusCode} ${statusText}\r\n`;
const headers = r1.headers ?? new Headers();
if (r1.body && !headers.get("content-length")) {
if (r1.body instanceof Uint8Array) out += `content-length: ${r1.body.byteLength}\r\n`;
const headers = r2.headers ?? new Headers();
if (r2.body && !headers.get("content-length")) {
if (r2.body instanceof Uint8Array) out += `content-length: ${r2.body.byteLength}\r\n`;
else if (!headers.get("transfer-encoding")) out += "transfer-encoding: chunked\r\n";
}
for (const [key, value] of headers)out += `${key}: ${value}\r\n`;
@ -822,18 +824,18 @@ async function writeResponse(w, r1) {
const header = encoder.encode(out);
const n = await writer.write(header);
assert(n === header.byteLength);
if (r1.body instanceof Uint8Array) {
const n1 = await writer.write(r1.body);
assert(n1 === r1.body.byteLength);
if (r2.body instanceof Uint8Array) {
const n1 = await writer.write(r2.body);
assert(n1 === r2.body.byteLength);
} else if (headers.has("content-length")) {
const contentLength = headers.get("content-length");
assert(contentLength != null);
const bodyLength = parseInt(contentLength);
const n1 = await Deno.copy(r1.body, writer);
const n1 = await Deno.copy(r2.body, writer);
assert(n1 === bodyLength);
} else await writeChunkedBody(writer, r1.body);
if (r1.trailers) {
const t = await r1.trailers();
} else await writeChunkedBody(writer, r2.body);
if (r2.trailers) {
const t = await r2.trailers();
await writeTrailers(writer, headers, t);
}
await writer.flush();
@ -909,7 +911,6 @@ class ServerRequest {
this.finalized = false;
}
}
var tmp1 = Symbol.asyncIterator;
function parseHTTPVersion(vers) {
switch(vers){
case "HTTP/1.1":
@ -958,6 +959,11 @@ async function readRequest(conn, bufr) {
return req;
}
class Server {
constructor(listener){
this.listener = listener;
this.closing = false;
this.connections = [];
}
close() {
this.closing = true;
this.listener.close();
@ -1033,16 +1039,11 @@ class Server {
// Yield the requests that arrive on the just-accepted connection.
yield* this.iterateHttpRequests(conn);
}
[tmp1]() {
[Symbol.asyncIterator]() {
const mux = new MuxAsyncIterator();
mux.add(this.acceptConnAndIterateHttpRequests(mux));
return mux.iterate();
}
constructor(listener){
this.listener = listener;
this.closing = false;
this.connections = [];
}
}
function _parseAddrFromStr(addr) {
let url;

View File

@ -8,7 +8,6 @@ function deferred() {
});
return Object.assign(promise, methods);
}
var tmp = Symbol.asyncIterator;
class MuxAsyncIterator {
add(iterator) {
++this.iteratorCount;
@ -46,12 +45,13 @@ class MuxAsyncIterator {
this.signal = deferred();
}
}
[tmp]() {
[Symbol.asyncIterator]() {
return this.iterate();
}
constructor(){
this.iteratorCount = 0;
this.yields = [];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this.throws = [];
this.signal = deferred();
}
@ -324,7 +324,6 @@ class ServerRequest {
this.finalized = false;
}
}
var tmp1 = Symbol.asyncIterator;
function parseHTTPVersion(vers) {
switch(vers){
case "HTTP/1.1":
@ -373,6 +372,11 @@ async function readRequest(conn, bufr) {
return req;
}
class Server {
constructor(listener){
this.listener = listener;
this.closing = false;
this.connections = [];
}
close() {
this.closing = true;
this.listener.close();
@ -448,16 +452,11 @@ class Server {
// Yield the requests that arrive on the just-accepted connection.
yield* this.iterateHttpRequests(conn);
}
[tmp1]() {
[Symbol.asyncIterator]() {
const mux = new MuxAsyncIterator();
mux.add(this.acceptConnAndIterateHttpRequests(mux));
return mux.iterate();
}
constructor(listener){
this.listener = listener;
this.closing = false;
this.connections = [];
}
}
function _parseAddrFromStr(addr) {
let url;

View File

@ -21,7 +21,6 @@ pub use swc_ecma_parser::JscTarget;
use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax, TsConfig};
use swc_ecma_transforms::hygiene;
use swc_ecma_transforms::{
compat::es2020::typescript_class_properties,
modules,
optimization::const_modules,
optimization::{inline_globals, json_parse, simplifier},
@ -251,7 +250,6 @@ impl Options {
}),
syntax.decorators()
),
Optional::new(typescript_class_properties(), syntax.typescript()),
Optional::new(typescript::strip(), syntax.typescript()),
resolver_with_mark(root_mark),
const_modules,

View File

@ -41,12 +41,12 @@ var MyEnum;
}));
var _dec = Decorator(), _dec1 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", String);
let Xpto = ((_class = function() {
class Xpto1 {
class Xpto {
constructor(){
_initializerDefineProperty(this, "value", _descriptor, this);
}
}
return Xpto1;
return Xpto;
}()) || _class, _descriptor = _applyDecoratedDescriptor(_class.prototype, "value", [
_dec,
_dec1

View File

@ -54,9 +54,9 @@ var _dec = ViewColumn({
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() {
var AccountMemberView1 = function AccountMemberView1() {
var AccountMemberView = function AccountMemberView() {
"use strict";
_classCallCheck(this, AccountMemberView1);
_classCallCheck(this, AccountMemberView);
_initializerDefineProperty(this, "memberId", _descriptor, this);
_initializerDefineProperty(this, "mallId", _descriptor1, this);
_initializerDefineProperty(this, "allowAccountCnt", _descriptor2, this);
@ -66,7 +66,7 @@ export var AccountMemberView = _class = _dec8((_class = function() {
_initializerDefineProperty(this, "accountCnt", _descriptor6, this);
_initializerDefineProperty(this, "accountQuickCnt", _descriptor7, this);
};
return AccountMemberView1;
return AccountMemberView;
}(), _descriptor = _applyDecoratedDescriptor(_class.prototype, "memberId", [
_dec,
typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Number)

View File

@ -47,12 +47,12 @@ var column = function() {
};
var _dec = column(), _dec1 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", String);
var User = ((_class = function() {
var User1 = function User1() {
var User = function User() {
"use strict";
_classCallCheck(this, User1);
_classCallCheck(this, User);
_initializerDefineProperty(this, "currency", _descriptor, this);
};
return User1;
return User;
}()) || _class, _descriptor = _applyDecoratedDescriptor(_class.prototype, "currency", [
_dec,
_dec1