diff --git a/bundler/tests/fixture/deno-9591/output/entry.inlined.ts b/bundler/tests/fixture/deno-9591/output/entry.inlined.ts index cc0a57aff025..f108c6a7d1e3 100644 --- a/bundler/tests/fixture/deno-9591/output/entry.inlined.ts +++ b/bundler/tests/fixture/deno-9591/output/entry.inlined.ts @@ -2256,10 +2256,10 @@ class ConsoleHandler extends BaseHandler { } } class WriterHandler extends BaseHandler { - #encoder=new TextEncoder(); + #encoder = new TextEncoder(); } class FileHandler extends WriterHandler { - #unloadCallback=()=>this.destroy() + #unloadCallback = ()=>this.destroy() ; constructor(levelName3, options3){ super(levelName3, options3); @@ -2305,7 +2305,7 @@ class FileHandler extends WriterHandler { class RotatingFileHandler extends FileHandler { #maxBytes; #maxBackupCount; - #currentFileSize=0; + #currentFileSize = 0; constructor(levelName4, options4){ super(levelName4, options4); this.#maxBytes = options4.maxBytes; diff --git a/bundler/tests/fixture/deno-9591/output/entry.ts b/bundler/tests/fixture/deno-9591/output/entry.ts index c79b599ae22b..f0709f596f9b 100644 --- a/bundler/tests/fixture/deno-9591/output/entry.ts +++ b/bundler/tests/fixture/deno-9591/output/entry.ts @@ -2267,10 +2267,10 @@ class ConsoleHandler extends BaseHandler { } } class WriterHandler extends BaseHandler { - #encoder=new TextEncoder(); + #encoder = new TextEncoder(); } class FileHandler extends WriterHandler { - #unloadCallback=()=>this.destroy() + #unloadCallback = ()=>this.destroy() ; constructor(levelName3, options3){ super(levelName3, options3); @@ -2316,7 +2316,7 @@ class FileHandler extends WriterHandler { class RotatingFileHandler extends FileHandler { #maxBytes; #maxBackupCount; - #currentFileSize=0; + #currentFileSize = 0; constructor(levelName4, options4){ super(levelName4, options4); this.#maxBytes = options4.maxBytes; diff --git a/ecmascript/codegen/src/lib.rs b/ecmascript/codegen/src/lib.rs index 88120c3026bb..cb88c1efb962 100644 --- a/ecmascript/codegen/src/lib.rs +++ b/ecmascript/codegen/src/lib.rs @@ -986,8 +986,17 @@ impl<'a> Emitter<'a> { } if let Some(value) = &n.value { + formatting_space!(); punct!("="); - emit!(value); + formatting_space!(); + + if value.is_seq() { + punct!("("); + emit!(value); + punct!(")"); + } else { + emit!(value); + } } formatting_semi!(); @@ -1030,7 +1039,13 @@ impl<'a> Emitter<'a> { punct!("="); formatting_space!(); - emit!(v); + if v.is_seq() { + punct!("("); + emit!(v); + punct!(")"); + } else { + emit!(v); + } } formatting_semi!(); diff --git a/ecmascript/transforms/tests/decorators.rs b/ecmascript/transforms/tests/decorators.rs index e94d5acbeeae..583dee9e0f14 100644 --- a/ecmascript/transforms/tests/decorators.rs +++ b/ecmascript/transforms/tests/decorators.rs @@ -4291,20 +4291,17 @@ class Person { const p = new Person(); p.save();", - "var _class, _dec; + "var _class; +var _class1, _dec; import { Debounce } from 'lodash-decorators'; -let Person = ((_class = function() { - class Person { - save() { - console.log('Hello World!'); - } +let Person = ((_class1 = (_class = class Person { + save() { + console.log('Hello World!'); } - Person.debounceTime = 500; - return Person; -}()) || _class, _dec = Debounce(_class.debounceTime), _applyDecoratedDescriptor(_class.prototype, \ - 'save', [ +}, _class.debounceTime = 500, _class)) || _class1, _dec = Debounce(_class1.debounceTime), \ + _applyDecoratedDescriptor(_class1.prototype, 'save', [ _dec -], Object.getOwnPropertyDescriptor(_class.prototype, 'save'), _class.prototype), _class); +], Object.getOwnPropertyDescriptor(_class1.prototype, 'save'), _class1.prototype), _class1); const p = new Person(); p.save();" ); @@ -4335,20 +4332,17 @@ class Person { const p = new Person(); p.save();", - "var _class, _dec; + "var _class; +var _class1, _dec; import { Debounce } from 'lodash-decorators'; -let Person = ((_class = function() { - class Person { - save() { - console.log('Hello World!'); - } +let Person = ((_class1 = (_class = class Person { + save() { + console.log('Hello World!'); } - Person.debounceTime = 500; - return Person; -}()) || _class, _dec = Debounce(_class.debounceTime), _applyDecoratedDescriptor(_class.prototype, \ - 'save', [ +}, _class.debounceTime = 500, _class)) || _class1, _dec = Debounce(_class1.debounceTime), \ + _applyDecoratedDescriptor(_class1.prototype, 'save', [ _dec -], Object.getOwnPropertyDescriptor(_class.prototype, 'save'), _class.prototype), _class); +], Object.getOwnPropertyDescriptor(_class1.prototype, 'save'), _class1.prototype), _class1); const p = new Person(); p.save(); " @@ -4380,30 +4374,27 @@ class Person { const p = new Person(); p.save();", - "var _class, _dec; + "var _class; +var _class1, _dec; import { Debounce } from 'lodash-decorators'; -let Person = ((_class = function() { - let Person = function() { - 'use strict'; - function Person() { - _classCallCheck(this, Person); - } - _createClass(Person, [ - { - key: 'save', - value: function save() { - console.log('Hello World!'); - } +let Person = ((_class1 = (_class = function() { + 'use strict'; + function Person() { + _classCallCheck(this, Person); + } + _createClass(Person, [ + { + key: 'save', + value: function save() { + console.log('Hello World!'); } - ]); - return Person; - }(); - Person.debounceTime = 500; + } + ]); return Person; -}()) || _class, _dec = Debounce(_class.debounceTime), _applyDecoratedDescriptor(_class.prototype, \ - 'save', [ +}(), _class.debounceTime = 500, _class)) || _class1, _dec = Debounce(_class1.debounceTime), \ + _applyDecoratedDescriptor(_class1.prototype, 'save', [ _dec -], Object.getOwnPropertyDescriptor(_class.prototype, 'save'), _class.prototype), _class); +], Object.getOwnPropertyDescriptor(_class1.prototype, 'save'), _class1.prototype), _class1); const p = new Person(); p.save();" ); diff --git a/ecmascript/transforms/typescript/Cargo.toml b/ecmascript/transforms/typescript/Cargo.toml index 880ce9c39365..8095dd534d21 100644 --- a/ecmascript/transforms/typescript/Cargo.toml +++ b/ecmascript/transforms/typescript/Cargo.toml @@ -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.2" +version = "0.11.3" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/ecmascript/transforms/typescript/src/strip.rs b/ecmascript/transforms/typescript/src/strip.rs index 089459d2dc69..d8b1430defad 100644 --- a/ecmascript/transforms/typescript/src/strip.rs +++ b/ecmascript/transforms/typescript/src/strip.rs @@ -184,13 +184,13 @@ impl Strip { } impl Strip { - fn fold_class_as_decl(&mut self, ident: Ident, mut class: Class) -> (Decl, Vec) { + fn fold_class_as_decl(&mut self, ident: Ident, mut class: Class) -> (Decl, Vec>) { class.is_abstract = false; class.type_params = None; class.super_type_params = None; class.implements = Default::default(); - let mut extra_stmts = vec![]; + let mut extra_exprs = vec![]; if self.config.use_define_for_class_fields { let mut param_class_fields = vec![]; for member in &class.body { @@ -313,15 +313,12 @@ impl Strip { prop: class_field.key, computed, }))); - extra_stmts.push( - AssignExpr { - span: DUMMY_SP, - op: op!("="), - left: assign_lhs, - right: value, - } - .into_stmt(), - ); + extra_exprs.push(Box::new(Expr::Assign(AssignExpr { + span: DUMMY_SP, + op: op!("="), + left: assign_lhs, + right: value, + }))); } } ClassMember::Method(mut method) => { @@ -365,27 +362,21 @@ impl Strip { } } class.body = new_body; - extra_stmts = { - let mut stmts = key_computations - .into_iter() - .map(|e| e.into_stmt()) - .collect::>(); - stmts.append(&mut extra_stmts); - stmts - }; + key_computations.append(&mut extra_exprs); + extra_exprs = key_computations; } 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); + extra_exprs.visit_mut_with(self); ( Decl::Class(ClassDecl { ident, declare: false, class, }), - extra_stmts, + extra_exprs, ) } @@ -401,9 +392,9 @@ impl Strip { declare: false, class, })) => { - let (decl, extra_stmts) = self.fold_class_as_decl(ident, class); + let (decl, extra_exprs) = 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.extend(extra_exprs.into_iter().map(|e| T::from_stmt(e.into_stmt()))); } _ => stmts.push(T::from_stmt(stmt)), }, @@ -415,9 +406,11 @@ impl Strip { .. }) => { let ident = ident.unwrap_or_else(|| private_ident!("_class")); - let (decl, extra_stmts) = self.fold_class_as_decl(ident.clone(), class); + let (decl, extra_exprs) = 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.extend( + extra_exprs.into_iter().map(|e| T::from_stmt(e.into_stmt())), + ); stmts.push( match T::try_from_module_decl(ModuleDecl::ExportNamed( NamedExport { @@ -451,7 +444,7 @@ impl Strip { }), .. }) => { - let (decl, extra_stmts) = self.fold_class_as_decl(ident, class); + let (decl, extra_exprs) = self.fold_class_as_decl(ident, class); stmts.push( match T::try_from_module_decl(ModuleDecl::ExportDecl(ExportDecl { span, @@ -461,7 +454,9 @@ impl Strip { Err(..) => unreachable!(), }, ); - stmts.extend(extra_stmts.into_iter().map(T::from_stmt)); + stmts.extend( + extra_exprs.into_iter().map(|e| T::from_stmt(e.into_stmt())), + ); } _ => stmts.push(match T::try_from_module_decl(decl) { Ok(t) => t, @@ -477,55 +472,42 @@ impl Strip { /// 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, - }); + let ident = private_ident!("_class"); + let (decl, extra_exprs) = self.fold_class_as_decl(ident.clone(), class); + let class_expr = Box::new(Expr::Class(ClassExpr { + ident: old_ident, + class: decl.class().unwrap().class, + })); + if extra_exprs.is_empty() { + *n = *class_expr; } else { - let mut stmts = vec![]; - stmts.push(Stmt::Decl(decl)); - stmts.extend(extra_stmts); - stmts.push(Stmt::Return(ReturnStmt { + self.uninitialized_vars.push(VarDeclarator { span: DUMMY_SP, - arg: Some(Box::new(Expr::Ident(ident))), + name: Pat::Ident(ident.clone().into()), + init: None, + definite: false, + }); + let assign_lhs = PatOrExpr::Pat(Box::new(Pat::Ident(BindingIdent { + id: ident.clone(), + type_ann: None, + }))); + let assign_expr = Box::new(Expr::Assign(AssignExpr { + span: n.span(), + op: op!("="), + left: assign_lhs, + right: class_expr, })); - *n = Expr::Call(CallExpr { + let mut exprs = vec![]; + exprs.push(assign_expr); + exprs.extend(extra_exprs); + exprs.push(Box::new(Expr::Ident(ident))); + *n = Expr::Seq(SeqExpr { 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(), + exprs, }); } return vec![]; @@ -1219,10 +1201,15 @@ impl VisitMut for Strip { 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 (decl, extra_exprs) = self.fold_class_as_decl(ident, class); let mut stmts = vec![]; stmts.push(Stmt::Decl(decl)); - stmts.extend(extra_stmts); + stmts.extend( + extra_exprs + .into_iter() + .map(|e| e.into_stmt()) + .collect::>(), + ); *n = BlockStmtOrExpr::BlockStmt(BlockStmt { span: n.span(), stmts, diff --git a/ecmascript/transforms/typescript/tests/strip.rs b/ecmascript/transforms/typescript/tests/strip.rs index aafb1662a679..ac6556108d03 100644 --- a/ecmascript/transforms/typescript/tests/strip.rs +++ b/ecmascript/transforms/typescript/tests/strip.rs @@ -3659,3 +3659,18 @@ to!( })); " ); + +to!( + class_expression_sequence, + " + const A = class { + static a = 1; + } + ", + " + var _class; + const A = (_class = class {}, + _class.a = 1, + _class); + " +);