fix(es/decorators): Fix a regression about class expressions (#8102)

**Related issue:**

 - Closes #8095
This commit is contained in:
Donny/강동윤 2023-10-12 01:45:21 +09:00 committed by GitHub
parent 1183c32e3c
commit cb4361f293
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 216 additions and 20 deletions

View File

@ -1 +1 @@
export default class t{#t;constructor(t){this.#t=t}#e(){setTimeout(()=>{this.#t.textContent="TESTED"},1e3)}run(){this.#e()}}
var t;t=class{#t;constructor(t){this.#t=t}#e(){setTimeout(()=>{this.#t.textContent="TESTED"},1e3)}run(){this.#e()}};export{t as default};

View File

@ -17,13 +17,14 @@ define([
function state() {}
class Controller {
}
class _class extends Controller {
var _class;
_class = class _$class extends Controller {
onChange() {}
constructor(...args){
super(...args);
_define_property._(this, "isTest", false);
}
}
};
_ts_decorate._([
state
], _class.prototype, "isTest", void 0);

View File

@ -12,7 +12,8 @@ const _ts_decorate = require("@swc/helpers/_/_ts_decorate");
function test(constructor) {
console.log(constructor);
}
let _class = class _class {
var _class;
_class = class _$class {
};
_class = _ts_decorate._([
test

View File

@ -2,7 +2,8 @@ import { _ as _ts_decorate } from "@swc/helpers/_/_ts_decorate";
function test(constructor) {
console.log(constructor);
}
let _class = class _class {
var _class;
_class = class _$class {
};
_class = _ts_decorate([
test

View File

@ -5,13 +5,14 @@ import { _ as _ts_metadata } from "@swc/helpers/_/_ts_metadata";
function Prop() {
return function() {};
}
var Example = function Example() {
var Example;
Example = function Example() {
"use strict";
_class_call_check(this, Example);
_define_property(this, "prop", void 0);
};
export { Example as default };
_ts_decorate([
Prop(),
_ts_metadata("design:type", typeof BigInt === "undefined" ? Object : BigInt)
], Example.prototype, "prop", void 0);
export { Example as default };

View File

@ -5,7 +5,8 @@ import { _ as _create_super } from "@swc/helpers/_/_create_super";
import { _ as _ts_decorate } from "@swc/helpers/_/_ts_decorate";
import React from "react";
import { withRouter } from "react-router-dom";
var App = /*#__PURE__*/ function(_React_Component) {
var App;
App = /*#__PURE__*/ function(_React_Component) {
"use strict";
_inherits(App, _React_Component);
var _super = _create_super(App);

View File

@ -0,0 +1,20 @@
{
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": false,
"decorators": true
},
"target": "es2020",
"loose": false,
"minify": {
"compress": false,
"mangle": false
}
},
"module": {
"type": "es6"
},
"minify": false,
"isModule": true
}

View File

@ -0,0 +1 @@
const foo = class { @foo foo(v) { return v } }

View File

@ -0,0 +1,10 @@
import { _ as _ts_decorate } from "@swc/helpers/_/_ts_decorate";
var _class;
const foo = _class = class _$class {
foo(v) {
return v;
}
};
_ts_decorate([
foo
], _class.prototype, "foo", null);

View File

@ -0,0 +1,20 @@
{
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": false,
"decorators": true
},
"target": "es2022",
"loose": false,
"minify": {
"compress": false,
"mangle": false
}
},
"module": {
"type": "es6"
},
"minify": false,
"isModule": true
}

View File

@ -0,0 +1 @@
const foo = class { @foo foo(v) { return v } }

View File

@ -0,0 +1,10 @@
import { _ as _ts_decorate } from "@swc/helpers/_/_ts_decorate";
var _class;
const foo = _class = class _$class {
foo(v) {
return v;
}
};
_ts_decorate([
foo
], _class.prototype, "foo", null);

View File

@ -0,0 +1,20 @@
{
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": false,
"decorators": true
},
"target": "es5",
"loose": false,
"minify": {
"compress": false,
"mangle": false
}
},
"module": {
"type": "es6"
},
"minify": false,
"isModule": true
}

View File

@ -0,0 +1 @@
const foo = class { @foo foo(v) { return v } }

View File

@ -0,0 +1,22 @@
import { _ as _class_call_check } from "@swc/helpers/_/_class_call_check";
import { _ as _create_class } from "@swc/helpers/_/_create_class";
import { _ as _ts_decorate } from "@swc/helpers/_/_ts_decorate";
var _class;
var foo = _class = /*#__PURE__*/ function() {
"use strict";
function _$class() {
_class_call_check(this, _$class);
}
_create_class(_$class, [
{
key: "foo",
value: function foo(v) {
return v;
}
}
]);
return _$class;
}();
_ts_decorate([
foo
], _class.prototype, "foo", null);

View File

@ -1,4 +1,5 @@
let A = class A {
var A;
A = class A {
};
A = _ts_decorate([
dec

View File

@ -1,6 +1,7 @@
export default class A {
var A;
A = class A {
foo() {}
}
};
_ts_decorate([
dec
], A.prototype, "foo", null);
@ -10,3 +11,4 @@ class B {
_ts_decorate([
dec
], B.prototype, "foo", null);
export { A as default };

View File

@ -1,6 +1,8 @@
export default class X {
var X;
X = class X {
prop: string = "";
}
};
_ts_decorate([
networked
], X.prototype, "prop", void 0);
export { X as default };

View File

@ -1,5 +1,6 @@
function myDecorator(decoratee) {}
let _class = class _class {
var _class;
_class = class _$class {
};
_class = _ts_decorate([
myDecorator

View File

@ -1,6 +1,8 @@
export default class _class {
var _class;
_class = class _$class {
bar() {}
}
};
_ts_decorate([
foo
], _class.prototype, "bar", null);
export { _class as default };

View File

@ -30,6 +30,7 @@ pub(super) fn new(metadata: bool) -> TscDecorator {
class_name: Default::default(),
constructor_exprs: Default::default(),
exports: Default::default(),
assign_class_expr_to: Default::default(),
}
}
@ -49,6 +50,8 @@ pub(super) struct TscDecorator {
constructor_exprs: Vec<Box<Expr>>,
exports: Vec<ExportSpecifier>,
assign_class_expr_to: Option<Ident>,
}
impl TscDecorator {
@ -291,14 +294,49 @@ impl VisitMut for TscDecorator {
self.class_name = old;
}
fn visit_mut_expr(&mut self, e: &mut Expr) {
e.visit_mut_children_with(self);
if let Some(var_name) = self.assign_class_expr_to.take() {
*e = Expr::Assign(AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: var_name.into(),
right: Box::new(e.take()),
});
}
}
fn visit_mut_class_expr(&mut self, n: &mut ClassExpr) {
let old = self.class_name.take();
if contains_decorator(n) && n.ident.is_none() {
n.ident = Some(private_ident!("_class"));
}
if contains_decorator(n) && n.ident.is_none() {
let ident = private_ident!("_$class");
let var_name = private_ident!("_class");
self.vars.push(VarDeclarator {
span: DUMMY_SP,
name: Pat::Ident(var_name.clone().into()),
init: None,
definite: Default::default(),
});
self.class_name = Some(var_name.clone());
n.ident = Some(ident);
n.visit_mut_children_with(self);
self.class_name = old;
self.assign_class_expr_to = Some(var_name);
return;
}
if let Some(ident) = &n.ident {
self.class_name = Some(ident.clone());
if self.class_name.is_none() {
self.class_name = Some(ident.clone());
}
}
n.visit_mut_children_with(self);
@ -405,6 +443,46 @@ impl VisitMut for TscDecorator {
fn visit_mut_module_item(&mut self, module_item: &mut ModuleItem) {
match module_item {
ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(ExportDefaultDecl {
decl: DefaultDecl::Class(c),
..
})) => {
c.visit_mut_with(self);
if self.assign_class_expr_to.is_none() {
if let Some(var_name) = c.ident.clone() {
self.vars.push(VarDeclarator {
span: DUMMY_SP,
name: Pat::Ident(var_name.clone().into()),
init: None,
definite: Default::default(),
});
self.assign_class_expr_to = Some(var_name);
}
}
if let Some(var_name) = self.assign_class_expr_to.take() {
*module_item = ModuleItem::Stmt(
Expr::Assign(AssignExpr {
span: DUMMY_SP,
op: op!("="),
left: var_name.clone().into(),
right: Box::new(Expr::Class(c.take())),
})
.into_stmt(),
);
self.exports
.push(ExportSpecifier::Named(ExportNamedSpecifier {
span: DUMMY_SP,
orig: ModuleExportName::Ident(var_name),
exported: Some(ModuleExportName::Ident(quote_ident!("default"))),
is_type_only: Default::default(),
}));
}
}
ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(n)) => {
let export_decl_span = n.span;