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:
David Sherret 2024-02-12 21:57:03 -05:00 committed by GitHub
parent 3b76b9b094
commit 21a447f35a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 101 additions and 35 deletions

View File

@ -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) {

View File

@ -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,

View File

@ -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];
}
}

View File

@ -0,0 +1,2 @@
export default class T {
}

View File

@ -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
];
}
}

View File

@ -0,0 +1,3 @@
{
"plugins": [["proposal-decorators", { "version": "2022-03" }]]
}