diff --git a/crates/swc/tests/fixture/issues-3xxx/3686/1/output/index.ts b/crates/swc/tests/fixture/issues-3xxx/3686/1/output/index.ts index 06d807e4b694..25a9dd7e1aeb 100644 --- a/crates/swc/tests/fixture/issues-3xxx/3686/1/output/index.ts +++ b/crates/swc/tests/fixture/issues-3xxx/3686/1/output/index.ts @@ -9,7 +9,7 @@ Object.defineProperty(exports, "ServiceError", { const _tsDecorate = require("@swc/helpers/lib/_ts_decorate.js").default; const CD = ()=>{}; const PD = ()=>{}; -let ServiceError = class ServiceError extends Error { +let ServiceError = class ServiceError1 extends Error { constructor(...args){ super(...args); this.code = ServiceError.Code.badResponse; diff --git a/crates/swc/tests/fixture/issues-5xxx/5258/input/.swcrc b/crates/swc/tests/fixture/issues-5xxx/5258/input/.swcrc new file mode 100644 index 000000000000..258cabeb3faa --- /dev/null +++ b/crates/swc/tests/fixture/issues-5xxx/5258/input/.swcrc @@ -0,0 +1,22 @@ +{ + "$schema": "http://json.schemastore.org/swcrc", + "exclude": "\\.js$", + "jsc": { + "parser": { + "syntax": "typescript", + "tsx": false, + "decorators": true + }, + "target": "es2020", + "loose": false, + "minify": { + "compress": false, + "mangle": false + } + }, + "module": { + "type": "amd", + "noInterop": true + }, + "minify": false +} \ No newline at end of file diff --git a/crates/swc/tests/fixture/issues-5xxx/5258/input/index.ts b/crates/swc/tests/fixture/issues-5xxx/5258/input/index.ts new file mode 100644 index 000000000000..b9e60a7165ab --- /dev/null +++ b/crates/swc/tests/fixture/issues-5xxx/5258/input/index.ts @@ -0,0 +1,53 @@ +function es5ClassCompat(target: Function): any { + ///@ts-expect-error + function _() { return Reflect.construct(target, arguments, this.constructor); } + Object.defineProperty(_, 'name', Object.getOwnPropertyDescriptor(target, 'name')!); + Object.setPrototypeOf(_, target); + Object.setPrototypeOf(_.prototype, target.prototype); + return _; +} +@es5ClassCompat +export class FileSystemError extends Error { + + static FileExists(messageOrUri?: string | URI): FileSystemError { + return new FileSystemError(messageOrUri, FileSystemProviderErrorCode.FileExists, FileSystemError.FileExists); + } + static FileNotFound(messageOrUri?: string | URI): FileSystemError { + return new FileSystemError(messageOrUri, FileSystemProviderErrorCode.FileNotFound, FileSystemError.FileNotFound); + } + static FileNotADirectory(messageOrUri?: string | URI): FileSystemError { + return new FileSystemError(messageOrUri, FileSystemProviderErrorCode.FileNotADirectory, FileSystemError.FileNotADirectory); + } + static FileIsADirectory(messageOrUri?: string | URI): FileSystemError { + return new FileSystemError(messageOrUri, FileSystemProviderErrorCode.FileIsADirectory, FileSystemError.FileIsADirectory); + } + static NoPermissions(messageOrUri?: string | URI): FileSystemError { + return new FileSystemError(messageOrUri, FileSystemProviderErrorCode.NoPermissions, FileSystemError.NoPermissions); + } + static Unavailable(messageOrUri?: string | URI): FileSystemError { + return new FileSystemError(messageOrUri, FileSystemProviderErrorCode.Unavailable, FileSystemError.Unavailable); + } + + readonly code: string; + + constructor(uriOrMessage?: string | URI, code: FileSystemProviderErrorCode = FileSystemProviderErrorCode.Unknown, terminator?: Function) { + super(URI.isUri(uriOrMessage) ? uriOrMessage.toString(true) : uriOrMessage); + + this.code = terminator?.name ?? 'Unknown'; + + // mark the error as file system provider error so that + // we can extract the error code on the receiving side + markAsFileSystemProviderError(this, code); + + // workaround when extending builtin objects and when compiling to ES5, see: + // https://github.com/microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work + if (typeof (Object).setPrototypeOf === 'function') { + (Object).setPrototypeOf(this, FileSystemError.prototype); + } + + if (typeof Error.captureStackTrace === 'function' && typeof terminator === 'function') { + // nice stack traces + Error.captureStackTrace(this, terminator); + } + } +} \ No newline at end of file diff --git a/crates/swc/tests/fixture/issues-5xxx/5258/output/index.ts b/crates/swc/tests/fixture/issues-5xxx/5258/output/index.ts new file mode 100644 index 000000000000..cf9c1f390b5c --- /dev/null +++ b/crates/swc/tests/fixture/issues-5xxx/5258/output/index.ts @@ -0,0 +1,55 @@ +define([ + "require", + "exports", + "@swc/helpers/src/_ts_decorate.mjs" +], function(require, exports, _tsDecorate) { + "use strict"; + Object.defineProperty(exports, "FileSystemError", { + enumerable: true, + get: ()=>FileSystemError + }); + _tsDecorate = _tsDecorate.default; + function es5ClassCompat(target) { + function _() { + return Reflect.construct(target, arguments, this.constructor); + } + Object.defineProperty(_, 'name', Object.getOwnPropertyDescriptor(target, 'name')); + Object.setPrototypeOf(_, target); + Object.setPrototypeOf(_.prototype, target.prototype); + return _; + } + let FileSystemError = class FileSystemError1 extends Error { + static FileExists(messageOrUri) { + return new FileSystemError(messageOrUri, FileSystemProviderErrorCode.FileExists, FileSystemError.FileExists); + } + static FileNotFound(messageOrUri) { + return new FileSystemError(messageOrUri, FileSystemProviderErrorCode.FileNotFound, FileSystemError.FileNotFound); + } + static FileNotADirectory(messageOrUri) { + return new FileSystemError(messageOrUri, FileSystemProviderErrorCode.FileNotADirectory, FileSystemError.FileNotADirectory); + } + static FileIsADirectory(messageOrUri) { + return new FileSystemError(messageOrUri, FileSystemProviderErrorCode.FileIsADirectory, FileSystemError.FileIsADirectory); + } + static NoPermissions(messageOrUri) { + return new FileSystemError(messageOrUri, FileSystemProviderErrorCode.NoPermissions, FileSystemError.NoPermissions); + } + static Unavailable(messageOrUri) { + return new FileSystemError(messageOrUri, FileSystemProviderErrorCode.Unavailable, FileSystemError.Unavailable); + } + constructor(uriOrMessage, code = FileSystemProviderErrorCode.Unknown, terminator){ + super(URI.isUri(uriOrMessage) ? uriOrMessage.toString(true) : uriOrMessage); + this.code = terminator?.name ?? 'Unknown'; + markAsFileSystemProviderError(this, code); + if (typeof Object.setPrototypeOf === 'function') { + Object.setPrototypeOf(this, FileSystemError.prototype); + } + if (typeof Error.captureStackTrace === 'function' && typeof terminator === 'function') { + Error.captureStackTrace(this, terminator); + } + } + }; + FileSystemError = _tsDecorate([ + es5ClassCompat + ], FileSystemError); +}); diff --git a/crates/swc_ecma_transforms_proposal/src/decorators/legacy/mod.rs b/crates/swc_ecma_transforms_proposal/src/decorators/legacy/mod.rs index ea78b1094a82..e22f44d3c3f8 100644 --- a/crates/swc_ecma_transforms_proposal/src/decorators/legacy/mod.rs +++ b/crates/swc_ecma_transforms_proposal/src/decorators/legacy/mod.rs @@ -413,11 +413,26 @@ impl VisitMut for TscDecorator { decl.visit_mut_with(self); if convert_to_let { + let inner_ident = private_ident!(decl.ident.sym.clone()); + + decl.class.body.iter_mut().for_each(|m| match m { + ClassMember::PrivateProp(PrivateProp { + is_static: true, .. + }) + | ClassMember::StaticBlock(..) + | ClassMember::ClassProp(ClassProp { + is_static: true, .. + }) => { + replace_ident(m, decl.ident.to_id(), &inner_ident); + } + _ => {} + }); + let d = VarDeclarator { span: DUMMY_SP, name: decl.ident.clone().into(), init: Some(Box::new(Expr::Class(ClassExpr { - ident: Some(decl.ident.clone()), + ident: Some(inner_ident), class: decl.class.take(), }))), definite: Default::default(), @@ -449,10 +464,28 @@ impl VisitMut for TscDecorator { if convert_to_let { let ident = decl.ident.clone().unwrap(); + let inner_ident = private_ident!(ident.sym.clone()); + + decl.class.body.iter_mut().for_each(|m| match m { + ClassMember::PrivateProp(PrivateProp { + is_static: true, .. + }) + | ClassMember::StaticBlock(..) + | ClassMember::ClassProp(ClassProp { + is_static: true, .. + }) => { + replace_ident(m, ident.to_id(), &inner_ident); + } + _ => {} + }); + let d = VarDeclarator { span: DUMMY_SP, name: ident.clone().into(), - init: Some(Box::new(Expr::Class(decl.take()))), + init: Some(Box::new(Expr::Class(ClassExpr { + ident: Some(inner_ident), + ..decl.take() + }))), definite: Default::default(), }; *module_item = ModuleItem::Stmt(Stmt::Decl(Decl::Var(VarDecl {