mirror of
https://github.com/swc-project/swc.git
synced 2024-11-29 22:51:38 +03:00
feat(es/compat): Support readonly and writeonly for private fields (#6182)
This commit is contained in:
parent
a029ca2430
commit
aefc11b8a7
@ -57,7 +57,7 @@ fn init_helpers() -> Arc<PathBuf> {
|
||||
let helper_dir = project_root.join("packages").join("swc-helpers");
|
||||
|
||||
let yarn = find_executable("yarn").expect("failed to find yarn");
|
||||
let npm = find_executable("npm").expect("failed to find yarn");
|
||||
let npm = find_executable("npm").expect("failed to find npm");
|
||||
{
|
||||
let mut cmd = if cfg!(target_os = "windows") {
|
||||
let mut c = Command::new("cmd");
|
||||
|
@ -2,6 +2,7 @@
|
||||
import _class_private_field_get from "@swc/helpers/src/_class_private_field_get.mjs";
|
||||
import _class_private_field_init from "@swc/helpers/src/_class_private_field_init.mjs";
|
||||
import _class_private_field_set from "@swc/helpers/src/_class_private_field_set.mjs";
|
||||
import _read_only_error from "@swc/helpers/src/_read_only_error.mjs";
|
||||
var _prop = /*#__PURE__*/ new WeakMap(), _roProp = /*#__PURE__*/ new WeakMap();
|
||||
class A1 {
|
||||
constructor(name){
|
||||
@ -14,7 +15,7 @@ class A1 {
|
||||
set: void 0
|
||||
});
|
||||
_class_private_field_set(this, _prop, "");
|
||||
_class_private_field_set(this, _roProp, ""); // Error
|
||||
this, _read_only_error("#roProp"); // Error
|
||||
console.log(_class_private_field_get(this, _prop));
|
||||
console.log(_class_private_field_get(this, _roProp));
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
//// [privateNameMethodAssignment.ts]
|
||||
import _class_private_field_set from "@swc/helpers/src/_class_private_field_set.mjs";
|
||||
import _class_private_field_update from "@swc/helpers/src/_class_private_field_update.mjs";
|
||||
import _class_private_method_get from "@swc/helpers/src/_class_private_method_get.mjs";
|
||||
import _class_private_method_init from "@swc/helpers/src/_class_private_method_init.mjs";
|
||||
import _read_only_error from "@swc/helpers/src/_read_only_error.mjs";
|
||||
import _class_private_field_destructure from "@swc/helpers/src/_class_private_field_destructure.mjs";
|
||||
var _method = /*#__PURE__*/ new WeakSet();
|
||||
class A3 {
|
||||
constructor(a, b){
|
||||
_class_private_method_init(this, _method);
|
||||
_class_private_field_set(this, _method, ()=>{} // Error, not writable
|
||||
);
|
||||
_class_private_field_set(a, _method, ()=>{}); // Error, not writable
|
||||
_class_private_field_set(b, _method, ()=>{} //Error, not writable
|
||||
);
|
||||
this, _read_only_error("#method") // Error, not writable
|
||||
;
|
||||
a, _read_only_error("#method"); // Error, not writable
|
||||
b, _read_only_error("#method") //Error, not writable
|
||||
;
|
||||
({ x: _class_private_field_destructure(this, _method).value } = {
|
||||
x: ()=>{}
|
||||
}); //Error, not writable
|
||||
|
@ -1,10 +1,10 @@
|
||||
//// [privateNameReadonly.ts]
|
||||
import _class_private_field_set from "@swc/helpers/src/_class_private_field_set.mjs";
|
||||
import _class_private_method_init from "@swc/helpers/src/_class_private_method_init.mjs";
|
||||
import _read_only_error from "@swc/helpers/src/_read_only_error.mjs";
|
||||
var _bar, _class;
|
||||
const C = (_bar = /*#__PURE__*/ new WeakSet(), _class = class {
|
||||
foo() {
|
||||
_class_private_field_set(this, _bar, console.log("should log this then throw"));
|
||||
this, console.log("should log this then throw"), _read_only_error("#bar");
|
||||
}
|
||||
constructor(){
|
||||
_class_private_method_init(this, _bar);
|
||||
|
@ -1,10 +1,10 @@
|
||||
//// [privateNameReadonly.ts]
|
||||
var _bar;
|
||||
import _class_private_field_set from "@swc/helpers/src/_class_private_field_set.mjs";
|
||||
import _class_private_method_init from "@swc/helpers/src/_class_private_method_init.mjs";
|
||||
import _read_only_error from "@swc/helpers/src/_read_only_error.mjs";
|
||||
let C = (_bar = new WeakSet(), class {
|
||||
foo() {
|
||||
_class_private_field_set(this, _bar, console.log("should log this then throw"));
|
||||
console.log("should log this then throw"), _read_only_error("#bar");
|
||||
}
|
||||
constructor(){
|
||||
_class_private_method_init(this, _bar);
|
||||
|
@ -1,11 +1,11 @@
|
||||
//// [privateNameSetterNoGetter.ts]
|
||||
import _class_private_field_get from "@swc/helpers/src/_class_private_field_get.mjs";
|
||||
import _class_private_field_init from "@swc/helpers/src/_class_private_field_init.mjs";
|
||||
import _class_private_field_set from "@swc/helpers/src/_class_private_field_set.mjs";
|
||||
import _write_only_error from "@swc/helpers/src/_write_only_error.mjs";
|
||||
var _x, _class;
|
||||
const C = (_x = /*#__PURE__*/ new WeakMap(), _class = class {
|
||||
m() {
|
||||
_class_private_field_set(this, _x, _class_private_field_get(this, _x) + 2); // Error
|
||||
_class_private_field_set(this, _x, (this, _write_only_error("#x")) + 2); // Error
|
||||
}
|
||||
constructor(){
|
||||
_class_private_field_init(this, _x, {
|
||||
|
@ -1,11 +1,11 @@
|
||||
//// [privateNameSetterNoGetter.ts]
|
||||
var _x;
|
||||
import _class_private_field_get from "@swc/helpers/src/_class_private_field_get.mjs";
|
||||
import _class_private_field_init from "@swc/helpers/src/_class_private_field_init.mjs";
|
||||
import _class_private_field_set from "@swc/helpers/src/_class_private_field_set.mjs";
|
||||
import _write_only_error from "@swc/helpers/src/_write_only_error.mjs";
|
||||
let C = (_x = new WeakMap(), class {
|
||||
m() {
|
||||
_class_private_field_set(this, _x, _class_private_field_get(this, _x) + 2);
|
||||
_class_private_field_set(this, _x, _write_only_error("#x") + 2);
|
||||
}
|
||||
constructor(){
|
||||
_class_private_field_init(this, _x, {
|
||||
|
@ -1,8 +1,8 @@
|
||||
//// [privateWriteOnlyAccessorRead.ts]
|
||||
import _class_private_field_get from "@swc/helpers/src/_class_private_field_get.mjs";
|
||||
import _class_private_field_init from "@swc/helpers/src/_class_private_field_init.mjs";
|
||||
import _class_private_field_set from "@swc/helpers/src/_class_private_field_set.mjs";
|
||||
import _extends from "@swc/helpers/src/_extends.mjs";
|
||||
import _write_only_error from "@swc/helpers/src/_write_only_error.mjs";
|
||||
import _class_private_field_destructure from "@swc/helpers/src/_class_private_field_destructure.mjs";
|
||||
var _value = /*#__PURE__*/ new WeakMap(), _valueRest = /*#__PURE__*/ new WeakMap(), _valueOne = /*#__PURE__*/ new WeakMap(), _valueCompound = /*#__PURE__*/ new WeakMap();
|
||||
class Test {
|
||||
@ -10,14 +10,14 @@ class Test {
|
||||
const foo = {
|
||||
bar: 1
|
||||
};
|
||||
console.log(_class_private_field_get(this, _value)); // error
|
||||
console.log((this, _write_only_error("#value"))); // error
|
||||
_class_private_field_set(this, _value, {
|
||||
foo
|
||||
}); // ok
|
||||
_class_private_field_set(this, _value, {
|
||||
foo
|
||||
}); // ok
|
||||
_class_private_field_get(this, _value).foo = foo; // error
|
||||
(this, _write_only_error("#value")).foo = foo; // error
|
||||
({ o: _class_private_field_destructure(this, _value).value } = {
|
||||
o: {
|
||||
foo
|
||||
@ -27,15 +27,15 @@ class Test {
|
||||
_tmp = {
|
||||
foo
|
||||
}, _class_private_field_destructure(this, _value).value = _extends({}, _tmp), _tmp; //ok
|
||||
({ foo: _class_private_field_get(this, _value).foo } = {
|
||||
({ foo: (this, _write_only_error("#value")).foo } = {
|
||||
foo
|
||||
}); //error
|
||||
var _tmp1;
|
||||
_tmp1 = {
|
||||
foo
|
||||
}, _class_private_field_get(this, _value).foo = _extends({}, _tmp1.foo), ({ foo: {} } = _tmp1), _tmp1; //error
|
||||
}, (this, _write_only_error("#value")).foo = _extends({}, _tmp1.foo), ({ foo: {} } = _tmp1), _tmp1; //error
|
||||
let r = {
|
||||
o: _class_private_field_get(this, _value)
|
||||
o: (this, _write_only_error("#value"))
|
||||
}; //error
|
||||
[_class_private_field_destructure(this, _valueOne).value, ..._class_private_field_destructure(this, _valueRest).value] = [
|
||||
1,
|
||||
@ -43,10 +43,10 @@ class Test {
|
||||
3
|
||||
];
|
||||
let arr = [
|
||||
_class_private_field_get(this, _valueOne),
|
||||
..._class_private_field_get(this, _valueRest)
|
||||
(this, _write_only_error("#valueOne")),
|
||||
...(this, _write_only_error("#valueRest"))
|
||||
];
|
||||
_class_private_field_set(this, _valueCompound, _class_private_field_get(this, _valueCompound) + 3);
|
||||
_class_private_field_set(this, _valueCompound, (this, _write_only_error("#valueCompound")) + 3);
|
||||
}
|
||||
constructor(){
|
||||
_class_private_field_init(this, _value, {
|
||||
|
@ -1,8 +1,8 @@
|
||||
//// [privateWriteOnlyAccessorRead.ts]
|
||||
import _class_private_field_get from "@swc/helpers/src/_class_private_field_get.mjs";
|
||||
import _class_private_field_init from "@swc/helpers/src/_class_private_field_init.mjs";
|
||||
import _class_private_field_set from "@swc/helpers/src/_class_private_field_set.mjs";
|
||||
import _extends from "@swc/helpers/src/_extends.mjs";
|
||||
import _write_only_error from "@swc/helpers/src/_write_only_error.mjs";
|
||||
import _class_private_field_destructure from "@swc/helpers/src/_class_private_field_destructure.mjs";
|
||||
var _value = new WeakMap(), _valueRest = new WeakMap(), _valueOne = new WeakMap(), _valueCompound = new WeakMap();
|
||||
function set_value(v) {}
|
||||
@ -15,28 +15,28 @@ new class {
|
||||
let foo = {
|
||||
bar: 1
|
||||
};
|
||||
console.log(_class_private_field_get(this, _value)), _class_private_field_set(this, _value, {
|
||||
console.log(_write_only_error("#value")), _class_private_field_set(this, _value, {
|
||||
foo
|
||||
}), _class_private_field_set(this, _value, {
|
||||
foo
|
||||
}), _class_private_field_get(this, _value).foo = foo, ({ o: _class_private_field_destructure(this, _value).value } = {
|
||||
}), _write_only_error("#value").foo = foo, ({ o: _class_private_field_destructure(this, _value).value } = {
|
||||
o: {
|
||||
foo
|
||||
}
|
||||
}), _class_private_field_destructure(this, _value).value = _extends({}, {
|
||||
foo
|
||||
}), ({ foo: _class_private_field_get(this, _value).foo } = {
|
||||
}), ({ foo: _write_only_error("#value").foo } = {
|
||||
foo
|
||||
}), _tmp = {
|
||||
foo
|
||||
}, _class_private_field_get(this, _value).foo = _extends({}, _tmp.foo), _class_private_field_get(this, _value), [_class_private_field_destructure(this, _valueOne).value, ..._class_private_field_destructure(this, _valueRest).value] = [
|
||||
}, _write_only_error("#value").foo = _extends({}, _tmp.foo), _write_only_error("#value"), [_class_private_field_destructure(this, _valueOne).value, ..._class_private_field_destructure(this, _valueRest).value] = [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
], [
|
||||
_class_private_field_get(this, _valueOne),
|
||||
..._class_private_field_get(this, _valueRest)
|
||||
], _class_private_field_set(this, _valueCompound, _class_private_field_get(this, _valueCompound) + 3);
|
||||
_write_only_error("#valueOne"),
|
||||
..._write_only_error("#valueRest")
|
||||
], _class_private_field_set(this, _valueCompound, _write_only_error("#valueCompound") + 3);
|
||||
}
|
||||
constructor(){
|
||||
_class_private_field_init(this, _value, {
|
||||
|
@ -1,5 +1,8 @@
|
||||
function _classApplyDescriptorUpdate(receiver, descriptor) {
|
||||
if (descriptor.set) {
|
||||
if (!descriptor.get) {
|
||||
throw new TypeError("attempted to read set only private field");
|
||||
}
|
||||
if (!("__destrWrapper" in descriptor)) {
|
||||
descriptor.__destrWrapper = {
|
||||
set value(v) {
|
||||
|
@ -1,3 +1,3 @@
|
||||
function _readOnlyError(name) {
|
||||
throw new Error("\"" + name + "\" is read-only");
|
||||
throw new TypeError("\"" + name + "\" is read-only");
|
||||
}
|
||||
|
@ -0,0 +1,3 @@
|
||||
function _writeOnlyError(name) {
|
||||
throw new TypeError("\"" + name + "\" is write-only");
|
||||
}
|
@ -334,6 +334,7 @@ define_helpers!(Helpers {
|
||||
set_prototype_of,
|
||||
is_native_function
|
||||
),
|
||||
write_only_error: (),
|
||||
|
||||
class_private_field_destructure: (
|
||||
class_extract_field_descriptor,
|
||||
|
@ -70,6 +70,15 @@ pub(super) struct PrivateKind {
|
||||
}
|
||||
|
||||
impl PrivateKind {
|
||||
fn is_readonly(&self) -> bool {
|
||||
self.is_method && !self.has_setter
|
||||
}
|
||||
|
||||
fn is_writeonly(&self) -> bool {
|
||||
// a private method can still be read
|
||||
self.is_method && !self.has_getter && self.has_setter
|
||||
}
|
||||
|
||||
fn is_method(&self) -> bool {
|
||||
self.is_method && !self.has_getter && !self.has_setter
|
||||
}
|
||||
@ -274,9 +283,9 @@ impl<'a> VisitMut for PrivateAccessVisitor<'a> {
|
||||
let var = alias_ident_for(&obj, "_ref");
|
||||
|
||||
let this = if matches!(*obj, Expr::This(..)) {
|
||||
ThisExpr { span: DUMMY_SP }.as_arg()
|
||||
Box::new(ThisExpr { span: DUMMY_SP }.into())
|
||||
} else if *op == op!("=") {
|
||||
obj.as_arg()
|
||||
obj
|
||||
} else {
|
||||
self.vars.push(VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
@ -284,27 +293,31 @@ impl<'a> VisitMut for PrivateAccessVisitor<'a> {
|
||||
init: None,
|
||||
definite: false,
|
||||
});
|
||||
AssignExpr {
|
||||
span: obj.span(),
|
||||
left: PatOrExpr::Pat(var.clone().into()),
|
||||
op: op!("="),
|
||||
right: obj,
|
||||
}
|
||||
.as_arg()
|
||||
Box::new(
|
||||
AssignExpr {
|
||||
span: obj.span(),
|
||||
left: PatOrExpr::Pat(var.clone().into()),
|
||||
op: op!("="),
|
||||
right: obj,
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
};
|
||||
|
||||
let value = if *op == op!("=") {
|
||||
right.take().as_arg()
|
||||
right.take()
|
||||
} else {
|
||||
let left = Box::new(self.visit_mut_private_get(&mut left, Some(var)).0);
|
||||
|
||||
BinExpr {
|
||||
span: DUMMY_SP,
|
||||
left,
|
||||
op: op.to_update().unwrap(),
|
||||
right: right.take(),
|
||||
}
|
||||
.as_arg()
|
||||
Box::new(
|
||||
BinExpr {
|
||||
span: DUMMY_SP,
|
||||
left,
|
||||
op: op.to_update().unwrap(),
|
||||
right: right.take(),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
};
|
||||
|
||||
if kind.is_static {
|
||||
@ -314,17 +327,34 @@ impl<'a> VisitMut for PrivateAccessVisitor<'a> {
|
||||
class_static_private_field_spec_set,
|
||||
"classStaticPrivateFieldSpecSet"
|
||||
),
|
||||
args: vec![this, class_name.clone().as_arg(), ident.as_arg(), value],
|
||||
args: vec![
|
||||
this.as_arg(),
|
||||
class_name.clone().as_arg(),
|
||||
ident.as_arg(),
|
||||
value.as_arg(),
|
||||
],
|
||||
|
||||
type_args: Default::default(),
|
||||
});
|
||||
} else if kind.is_readonly() {
|
||||
let err = Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: helper!(read_only_error, "readOnlyError"),
|
||||
args: vec![format!("#{}", n.id.sym).as_arg()],
|
||||
type_args: None,
|
||||
})
|
||||
.into();
|
||||
*e = Expr::Seq(SeqExpr {
|
||||
span: *span,
|
||||
exprs: vec![this, value, err],
|
||||
});
|
||||
} else {
|
||||
let set = helper!(class_private_field_set, "classPrivateFieldSet");
|
||||
|
||||
*e = Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: set,
|
||||
args: vec![this, ident.as_arg(), value],
|
||||
args: vec![this.as_arg(), ident.as_arg(), value.as_arg()],
|
||||
|
||||
type_args: Default::default(),
|
||||
});
|
||||
@ -642,7 +672,7 @@ impl<'a> PrivateAccessVisitor<'a> {
|
||||
"classPrivateFieldDestructureSet"
|
||||
);
|
||||
|
||||
return (
|
||||
(
|
||||
CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: set,
|
||||
@ -652,12 +682,12 @@ impl<'a> PrivateAccessVisitor<'a> {
|
||||
}
|
||||
.make_member(quote_ident!("value")),
|
||||
Some(*obj),
|
||||
);
|
||||
)
|
||||
}
|
||||
PrivateAccessType::Update => {
|
||||
let set = helper!(class_private_field_update, "classPrivateFieldUpdate");
|
||||
|
||||
return (
|
||||
(
|
||||
CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: set,
|
||||
@ -667,88 +697,114 @@ impl<'a> PrivateAccessVisitor<'a> {
|
||||
}
|
||||
.make_member(quote_ident!("value")),
|
||||
Some(*obj),
|
||||
);
|
||||
)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let get = if self.c.private_as_properties {
|
||||
helper!(class_private_field_loose_base, "classPrivateFieldLooseBase")
|
||||
} else if kind.is_method() {
|
||||
helper!(class_private_method_get, "classPrivateMethodGet")
|
||||
} else {
|
||||
helper!(class_private_field_get, "classPrivateFieldGet")
|
||||
};
|
||||
|
||||
match &*obj {
|
||||
Expr::This(this) => (
|
||||
if kind.is_method() && !self.c.private_as_properties {
|
||||
PrivateAccessType::Get if kind.is_writeonly() => {
|
||||
let helper = helper!(write_only_error, "writeOnlyError");
|
||||
let expr = Box::new(
|
||||
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()
|
||||
},
|
||||
Some(Expr::This(*this)),
|
||||
),
|
||||
_ => {
|
||||
let mut aliased = false;
|
||||
let var = obj_alias.unwrap_or_else(|| {
|
||||
let (var, a) = alias_if_required(&obj, "_ref");
|
||||
if a {
|
||||
aliased = true;
|
||||
self.vars.push(VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: var.clone().into(),
|
||||
init: None,
|
||||
definite: false,
|
||||
});
|
||||
}
|
||||
var
|
||||
});
|
||||
|
||||
let first_arg = if is_alias_initialized {
|
||||
var.clone().as_arg()
|
||||
} else if aliased {
|
||||
AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Pat(var.clone().into()),
|
||||
op: op!("="),
|
||||
right: obj.take(),
|
||||
}
|
||||
.as_arg()
|
||||
} else {
|
||||
var.clone().as_arg()
|
||||
};
|
||||
|
||||
let args = if kind.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,
|
||||
type_args: Default::default(),
|
||||
callee: helper,
|
||||
args: vec![format!("#{}", n.id.sym).as_arg()],
|
||||
type_args: None,
|
||||
}
|
||||
.into(),
|
||||
Some(Expr::Ident(var)),
|
||||
);
|
||||
(
|
||||
SeqExpr {
|
||||
span: DUMMY_SP,
|
||||
exprs: vec![obj.clone(), expr],
|
||||
}
|
||||
.into(),
|
||||
Some(*obj),
|
||||
)
|
||||
}
|
||||
|
||||
PrivateAccessType::Get => {
|
||||
let get = if self.c.private_as_properties {
|
||||
helper!(class_private_field_loose_base, "classPrivateFieldLooseBase")
|
||||
} else if kind.is_method() {
|
||||
helper!(class_private_method_get, "classPrivateMethodGet")
|
||||
} else {
|
||||
helper!(class_private_field_get, "classPrivateFieldGet")
|
||||
};
|
||||
|
||||
match &*obj {
|
||||
Expr::This(this) => (
|
||||
if kind.is_method() && !self.c.private_as_properties {
|
||||
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()
|
||||
},
|
||||
Some(Expr::This(*this)),
|
||||
),
|
||||
_ => {
|
||||
let mut aliased = false;
|
||||
let var = obj_alias.unwrap_or_else(|| {
|
||||
let (var, a) = alias_if_required(&obj, "_ref");
|
||||
if a {
|
||||
aliased = true;
|
||||
self.vars.push(VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: var.clone().into(),
|
||||
init: None,
|
||||
definite: false,
|
||||
});
|
||||
}
|
||||
var
|
||||
});
|
||||
|
||||
let first_arg = if is_alias_initialized {
|
||||
var.clone().as_arg()
|
||||
} else if aliased {
|
||||
AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
left: PatOrExpr::Pat(var.clone().into()),
|
||||
op: op!("="),
|
||||
right: obj.take(),
|
||||
}
|
||||
.as_arg()
|
||||
} else {
|
||||
var.clone().as_arg()
|
||||
};
|
||||
|
||||
let args = if kind.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,
|
||||
type_args: Default::default(),
|
||||
}
|
||||
.into(),
|
||||
Some(Expr::Ident(var)),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6549,6 +6549,100 @@ function set_privateFieldValue(newValue) {
|
||||
"#
|
||||
);
|
||||
|
||||
test!(
|
||||
syntax(),
|
||||
|t| class_properties(Some(t.comments.clone()), Default::default()),
|
||||
set_only_getter,
|
||||
r#"
|
||||
class Cl {
|
||||
#privateField = 0;
|
||||
counter = 0;
|
||||
|
||||
get #privateFieldValue() {
|
||||
return this.#privateField;
|
||||
}
|
||||
|
||||
get self() {
|
||||
this.counter++;
|
||||
return this;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
this.self.#privateFieldValue = 1;
|
||||
([this.self.#privateFieldValue] = [1]);
|
||||
}
|
||||
}
|
||||
|
||||
const cl = new Cl();
|
||||
"#,
|
||||
r##"
|
||||
var _privateField = new WeakMap(), _privateFieldValue = new WeakMap();
|
||||
class Cl {
|
||||
get self() {
|
||||
this.counter++;
|
||||
return this;
|
||||
}
|
||||
constructor(){
|
||||
_classPrivateFieldInit(this, _privateFieldValue, {
|
||||
get: get_privateFieldValue,
|
||||
set: void 0
|
||||
});
|
||||
_classPrivateFieldInit(this, _privateField, {
|
||||
writable: true,
|
||||
value: 0
|
||||
});
|
||||
_defineProperty(this, "counter", 0);
|
||||
this.self, _readOnlyError("#privateFieldValue");
|
||||
[_classPrivateFieldDestructureSet(this.self, _privateFieldValue).value] = [
|
||||
1
|
||||
];
|
||||
}
|
||||
}
|
||||
function get_privateFieldValue() {
|
||||
return _classPrivateFieldGet(this, _privateField);
|
||||
}
|
||||
const cl = new Cl();
|
||||
"##
|
||||
);
|
||||
|
||||
test!(
|
||||
syntax(),
|
||||
|t| class_properties(Some(t.comments.clone()), Default::default()),
|
||||
get_only_setter,
|
||||
r#"
|
||||
class Cl {
|
||||
#privateField = 0;
|
||||
|
||||
set #privateFieldValue(newValue) {
|
||||
this.#privateField = newValue;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
this.publicField = this.#privateFieldValue;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r##"
|
||||
var _privateField = new WeakMap(), _privateFieldValue = new WeakMap();
|
||||
class Cl {
|
||||
constructor(){
|
||||
_classPrivateFieldInit(this, _privateFieldValue, {
|
||||
get: void 0,
|
||||
set: set_privateFieldValue
|
||||
});
|
||||
_classPrivateFieldInit(this, _privateField, {
|
||||
writable: true,
|
||||
value: 0
|
||||
});
|
||||
this.publicField = (this, _writeOnlyError("#privateFieldValue"));
|
||||
}
|
||||
}
|
||||
function set_privateFieldValue(newValue) {
|
||||
_classPrivateFieldSet(this, _privateField, newValue);
|
||||
}
|
||||
"##
|
||||
);
|
||||
|
||||
#[testing::fixture("tests/classes/**/exec.js")]
|
||||
fn exec(input: PathBuf) {
|
||||
let src = read_to_string(&input).unwrap();
|
||||
|
@ -1,5 +1,8 @@
|
||||
export default function _classApplyDescriptorUpdate(receiver, descriptor) {
|
||||
if (descriptor.set) {
|
||||
if (!descriptor.get) {
|
||||
throw new TypeError("attempted to read set only private field");
|
||||
}
|
||||
if (!("__destrWrapper" in descriptor)) {
|
||||
descriptor.__destrWrapper = {
|
||||
set value(v) {
|
||||
|
@ -1,3 +1,3 @@
|
||||
export default function _readOnlyError(name) {
|
||||
throw new Error("\"" + name + "\" is read-only");
|
||||
throw new TypeError("\"" + name + "\" is read-only");
|
||||
}
|
||||
|
3
packages/swc-helpers/src/_write_only_error.mjs
Normal file
3
packages/swc-helpers/src/_write_only_error.mjs
Normal file
@ -0,0 +1,3 @@
|
||||
export default function _writeOnlyError(name) {
|
||||
throw new TypeError("\"" + name + "\" is write-only");
|
||||
}
|
@ -78,4 +78,5 @@ export { default as typeOf } from './_type_of.mjs';
|
||||
export { default as unsupportedIterableToArray } from './_unsupported_iterable_to_array.mjs';
|
||||
export { default as wrapAsyncGenerator } from './_wrap_async_generator.mjs';
|
||||
export { default as wrapNativeSuper } from './_wrap_native_super.mjs';
|
||||
export { default as writeOnlyError } from './_write_only_error.mjs';
|
||||
export { __decorate, __generator, __metadata, __param, __values } from 'tslib'
|
Loading…
Reference in New Issue
Block a user