mirror of
https://github.com/swc-project/swc.git
synced 2024-10-05 04:39:06 +03:00
fix(es/compat): Fix private methods of a class (#3123)
swc_ecma_transforms_compat: - `class_properties`: Handle private method calls properly. (Closes #3055)
This commit is contained in:
parent
836cbd63a8
commit
1b6ac25d5c
8
crates/swc/tests/fixture/issue-3055/1/input/.swcrc
Normal file
8
crates/swc/tests/fixture/issue-3055/1/input/.swcrc
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"jsc": {
|
||||
"parser": {
|
||||
"syntax": "typescript"
|
||||
},
|
||||
"target": "es2019"
|
||||
}
|
||||
}
|
16
crates/swc/tests/fixture/issue-3055/1/input/index.ts
Normal file
16
crates/swc/tests/fixture/issue-3055/1/input/index.ts
Normal file
@ -0,0 +1,16 @@
|
||||
export class Node {
|
||||
childNodes: Node[] = [];
|
||||
parent?: Node;
|
||||
|
||||
link(): void {
|
||||
this.#link(this);
|
||||
}
|
||||
|
||||
#link(parent: Node): void {
|
||||
this.parent = parent;
|
||||
|
||||
for (const childNode of this.childNodes) {
|
||||
childNode.#link(this);
|
||||
}
|
||||
}
|
||||
}
|
22
crates/swc/tests/fixture/issue-3055/1/output/index.ts
Normal file
22
crates/swc/tests/fixture/issue-3055/1/output/index.ts
Normal file
@ -0,0 +1,22 @@
|
||||
function _classPrivateMethodGet(receiver, privateSet, fn) {
|
||||
if (!privateSet.has(receiver)) {
|
||||
throw new TypeError("attempted to get private field on non-instance");
|
||||
}
|
||||
return fn;
|
||||
}
|
||||
var _link = new WeakSet();
|
||||
export class Node {
|
||||
link() {
|
||||
_classPrivateMethodGet(this, _link, link).call(this, this);
|
||||
}
|
||||
constructor(){
|
||||
_link.add(this);
|
||||
this.childNodes = [];
|
||||
}
|
||||
}
|
||||
function link(parent) {
|
||||
this.parent = parent;
|
||||
for (const childNode of this.childNodes){
|
||||
_classPrivateMethodGet(childNode, _link, link).call(childNode, this);
|
||||
}
|
||||
}
|
@ -624,33 +624,32 @@ impl<'a> FieldAccessFolder<'a> {
|
||||
};
|
||||
}
|
||||
|
||||
if is_method {
|
||||
let h = helper!(class_private_method_get, "classPrivateMethodGet");
|
||||
|
||||
return (
|
||||
CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: h,
|
||||
args: vec![obj.as_arg(), ident.as_arg(), method_name.as_arg()],
|
||||
type_args: Default::default(),
|
||||
}
|
||||
.into(),
|
||||
Some(Expr::This(ThisExpr { span: DUMMY_SP })),
|
||||
);
|
||||
}
|
||||
|
||||
let get = helper!(class_private_field_get, "classPrivateFieldGet");
|
||||
let get = if is_method {
|
||||
helper!(class_private_method_get, "classPrivateMethodGet")
|
||||
} else {
|
||||
helper!(class_private_field_get, "classPrivateFieldGet")
|
||||
};
|
||||
|
||||
match &*obj {
|
||||
Expr::This(this) => (
|
||||
CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: get,
|
||||
args: vec![this.as_arg(), ident.as_arg()],
|
||||
if is_method {
|
||||
CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: get,
|
||||
args: vec![obj.clone().as_arg(), ident.as_arg(), method_name.as_arg()],
|
||||
type_args: Default::default(),
|
||||
}
|
||||
.into()
|
||||
} else {
|
||||
CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: get,
|
||||
args: vec![this.as_arg(), ident.as_arg()],
|
||||
|
||||
type_args: Default::default(),
|
||||
}
|
||||
.into(),
|
||||
type_args: Default::default(),
|
||||
}
|
||||
.into()
|
||||
},
|
||||
Some(Expr::This(*this)),
|
||||
),
|
||||
_ => {
|
||||
@ -669,31 +668,33 @@ impl<'a> FieldAccessFolder<'a> {
|
||||
var
|
||||
});
|
||||
|
||||
let first_arg = if is_alias_initialized {
|
||||
var.clone().as_arg()
|
||||
} else {
|
||||
if aliased {
|
||||
AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Pat(Box::new(Pat::Ident(var.clone().into()))),
|
||||
op: op!("="),
|
||||
right: obj.take(),
|
||||
}
|
||||
.as_arg()
|
||||
} else {
|
||||
var.clone().as_arg()
|
||||
}
|
||||
};
|
||||
|
||||
let args = if is_method {
|
||||
vec![first_arg, ident.as_arg(), method_name.as_arg()]
|
||||
} else {
|
||||
vec![first_arg, ident.as_arg()]
|
||||
};
|
||||
|
||||
(
|
||||
CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: get,
|
||||
args: vec![
|
||||
if is_alias_initialized {
|
||||
var.clone().as_arg()
|
||||
} else {
|
||||
if aliased {
|
||||
AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Pat(Box::new(Pat::Ident(
|
||||
var.clone().into(),
|
||||
))),
|
||||
op: op!("="),
|
||||
right: obj.take(),
|
||||
}
|
||||
.as_arg()
|
||||
} else {
|
||||
var.clone().as_arg()
|
||||
}
|
||||
},
|
||||
ident.as_arg(),
|
||||
],
|
||||
|
||||
args,
|
||||
type_args: Default::default(),
|
||||
}
|
||||
.into(),
|
||||
|
@ -5236,6 +5236,45 @@ test!(
|
||||
"
|
||||
);
|
||||
|
||||
test!(
|
||||
syntax(),
|
||||
|_| class_properties(class_properties::Config { loose: false }),
|
||||
issue_3055_1,
|
||||
"
|
||||
export class Node {
|
||||
foo() {
|
||||
this.#bar(this);
|
||||
}
|
||||
|
||||
#bar(parent) {
|
||||
parent.#baz(this);
|
||||
parent.baz.#baz(this);
|
||||
}
|
||||
|
||||
#baz(child) { }
|
||||
}
|
||||
",
|
||||
"
|
||||
var _bar = new WeakSet(),
|
||||
_baz = new WeakSet();
|
||||
export class Node {
|
||||
foo() {
|
||||
_classPrivateMethodGet(this, _bar, bar).call(this, this);
|
||||
}
|
||||
constructor() {
|
||||
_bar.add(this);
|
||||
_baz.add(this);
|
||||
}
|
||||
}
|
||||
function bar(parent) {
|
||||
var _baz1;
|
||||
_classPrivateMethodGet(parent, _baz, baz).call(parent, this);
|
||||
_classPrivateMethodGet(_baz1 = parent.baz, _baz, baz).call(_baz1, this);
|
||||
}
|
||||
function baz(child) {}
|
||||
"
|
||||
);
|
||||
|
||||
test!(
|
||||
syntax(),
|
||||
|_| chain!(
|
||||
|
Loading…
Reference in New Issue
Block a user