mirror of
https://github.com/swc-project/swc.git
synced 2024-11-23 09:38:16 +03:00
fix(es/decorators): Do not insert duplicate constructors (#8631)
**Description:** Doesn't insert a duplicate ctor when the ctor uses overloads in TS. **Related issue:** - Closes #8630.
This commit is contained in:
parent
3b76b9b094
commit
21a447f35a
@ -276,39 +276,49 @@ impl Decorator202203 {
|
||||
}
|
||||
|
||||
fn ensure_constructor<'a>(&mut self, c: &'a mut Class) -> &'a mut Constructor {
|
||||
for member in c.body.iter_mut() {
|
||||
let mut insert_index = 0;
|
||||
for (i, member) in c.body.iter_mut().enumerate() {
|
||||
if let ClassMember::Constructor(constructor) = member {
|
||||
return unsafe {
|
||||
// Safety: We need polonius
|
||||
transmute::<&mut Constructor, &'a mut Constructor>(constructor)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
c.body
|
||||
.insert(0, default_constructor(c.super_class.is_some()).into());
|
||||
|
||||
for member in c.body.iter_mut() {
|
||||
if let ClassMember::Constructor(constructor) = member {
|
||||
return constructor;
|
||||
}
|
||||
}
|
||||
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
fn ensure_identity_constructor<'a>(&mut self, c: &'a mut Class) -> &'a mut Constructor {
|
||||
for member in c.body.iter_mut() {
|
||||
if let ClassMember::Constructor(constructor) = member {
|
||||
return unsafe {
|
||||
// Safety: We need polonius
|
||||
transmute::<&mut Constructor, &'a mut Constructor>(constructor)
|
||||
};
|
||||
insert_index = i + 1;
|
||||
// decorators occur before typescript's type strip, so skip ctor overloads
|
||||
if constructor.body.is_some() {
|
||||
return unsafe {
|
||||
// Safety: We need polonius
|
||||
transmute::<&mut Constructor, &'a mut Constructor>(constructor)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.body.insert(
|
||||
0,
|
||||
insert_index,
|
||||
default_constructor(c.super_class.is_some()).into(),
|
||||
);
|
||||
|
||||
if let Some(ClassMember::Constructor(c)) = c.body.get_mut(insert_index) {
|
||||
c
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
fn ensure_identity_constructor<'a>(&mut self, c: &'a mut Class) -> &'a mut Constructor {
|
||||
let mut insert_index = 0;
|
||||
for (i, member) in c.body.iter_mut().enumerate() {
|
||||
if let ClassMember::Constructor(constructor) = member {
|
||||
insert_index = i + 1;
|
||||
// decorators occur before typescript's type strip, so skip ctor overloads
|
||||
if constructor.body.is_some() {
|
||||
return unsafe {
|
||||
// Safety: We need polonius
|
||||
transmute::<&mut Constructor, &'a mut Constructor>(constructor)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.body.insert(
|
||||
insert_index,
|
||||
ClassMember::Constructor(Constructor {
|
||||
span: DUMMY_SP,
|
||||
key: PropName::Ident(quote_ident!("constructor")),
|
||||
@ -322,13 +332,11 @@ impl Decorator202203 {
|
||||
}),
|
||||
);
|
||||
|
||||
for member in c.body.iter_mut() {
|
||||
if let ClassMember::Constructor(constructor) = member {
|
||||
return constructor;
|
||||
}
|
||||
if let Some(ClassMember::Constructor(c)) = c.body.get_mut(insert_index) {
|
||||
c
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
fn handle_super_class(&mut self, class: &mut Class) {
|
||||
|
@ -23,6 +23,13 @@ fn syntax_default() -> Syntax {
|
||||
})
|
||||
}
|
||||
|
||||
fn syntax_default_ts() -> Syntax {
|
||||
Syntax::Typescript(TsConfig {
|
||||
decorators: true,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
#[testing::fixture("tests/decorators/**/exec.js")]
|
||||
fn exec(input: PathBuf) {
|
||||
exec_inner(input)
|
||||
@ -44,6 +51,7 @@ fn exec_inner(input: PathBuf) {
|
||||
|
||||
#[testing::fixture("tests/decorators/**/input.js")]
|
||||
#[testing::fixture("tests/decorators/**/input.mjs")]
|
||||
#[testing::fixture("tests/decorators/**/input.ts")]
|
||||
fn fixture(input: PathBuf) {
|
||||
fixture_inner(input)
|
||||
}
|
||||
@ -57,7 +65,11 @@ fn fixture_inner(input: PathBuf) {
|
||||
));
|
||||
|
||||
test_fixture(
|
||||
syntax_default(),
|
||||
if input.to_string_lossy().ends_with(".ts") {
|
||||
syntax_default_ts()
|
||||
} else {
|
||||
syntax_default()
|
||||
},
|
||||
&|t| create_pass(t.comments.clone(), &input),
|
||||
&input,
|
||||
&output,
|
||||
|
@ -0,0 +1,13 @@
|
||||
const decorate = (target: unknown, context: DecoratorContext) => {
|
||||
console.log("decorated");
|
||||
};
|
||||
|
||||
export class Color {
|
||||
constructor(hex: string);
|
||||
constructor(r: number, g: number, b: number, a?: number);
|
||||
constructor(r: string | number, g?: number, b?: number, a = 1) {}
|
||||
|
||||
@decorate get rgba() {
|
||||
return [0, 0, 0, 1];
|
||||
}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
export default class T {
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
var _initProto;
|
||||
const decorate = (target: unknown, context: DecoratorContext)=>{
|
||||
console.log("decorated");
|
||||
};
|
||||
export class Color {
|
||||
static{
|
||||
({ e: [_initProto] } = _apply_decs_2203_r(this, [
|
||||
[
|
||||
decorate,
|
||||
3,
|
||||
"rgba"
|
||||
]
|
||||
], []));
|
||||
}
|
||||
constructor(hex: string);
|
||||
constructor(r: number, g: number, b: number, a?: number);
|
||||
constructor(r: string | number, g?: number, b?: number, a = 1){
|
||||
_initProto(this);
|
||||
}
|
||||
get rgba() {
|
||||
return [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"plugins": [["proposal-decorators", { "version": "2022-03" }]]
|
||||
}
|
Loading…
Reference in New Issue
Block a user