diff --git a/packages/babel-helper-create-class-features-plugin/src/fields.js b/packages/babel-helper-create-class-features-plugin/src/fields.js index bfe6fc5da1..fd8f6d311b 100644 --- a/packages/babel-helper-create-class-features-plugin/src/fields.js +++ b/packages/babel-helper-create-class-features-plugin/src/fields.js @@ -232,8 +232,11 @@ const privateNameHandlerSpec = { if (isAccessor) { if (!getId && setId) { if (file.availableHelper("writeOnlyError")) { - return t.callExpression(file.addHelper("writeOnlyError"), [ - t.stringLiteral(`#${name}`), + return t.sequenceExpression([ + this.receiver(member), + t.callExpression(file.addHelper("writeOnlyError"), [ + t.stringLiteral(`#${name}`), + ]), ]); } console.warn( @@ -299,8 +302,12 @@ const privateNameHandlerSpec = { value, ]); } - return t.callExpression(file.addHelper("readOnlyError"), [ - t.stringLiteral(`#${name}`), + return t.sequenceExpression([ + this.receiver(member), + value, + t.callExpression(file.addHelper("readOnlyError"), [ + t.stringLiteral(`#${name}`), + ]), ]); } return t.callExpression(file.addHelper("classPrivateFieldSet"), [ diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-loose/reassignment/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-loose/reassignment/exec.js new file mode 100644 index 0000000000..0a11c8cb80 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-loose/reassignment/exec.js @@ -0,0 +1,13 @@ +let counter = 0; +class Foo { + constructor() { + this.#privateFieldValue = ++counter; + } + + get #privateFieldValue() { + return 42; + } +} + +expect(() => new Foo).toThrow(); +expect(counter).toBe(1); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-loose/reassignment/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-loose/reassignment/input.js new file mode 100644 index 0000000000..c98c910e30 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-loose/reassignment/input.js @@ -0,0 +1,10 @@ +let counter = 0; +class Foo { + constructor() { + this.#privateFieldValue = ++counter; + } + + get #privateFieldValue() { + return 42; + } +} diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-loose/reassignment/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-loose/reassignment/output.js new file mode 100644 index 0000000000..1f11f3b3e9 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors-loose/reassignment/output.js @@ -0,0 +1,18 @@ +var counter = 0; + +var _privateFieldValue = babelHelpers.classPrivateFieldLooseKey("privateFieldValue"); + +class Foo { + constructor() { + Object.defineProperty(this, _privateFieldValue, { + get: _get_privateFieldValue, + set: void 0 + }); + babelHelpers.classPrivateFieldLooseBase(this, _privateFieldValue)[_privateFieldValue] = ++counter; + } + +} + +var _get_privateFieldValue = function () { + return 42; +}; diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/get-only-setter/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/get-only-setter/output.js index 723c7b1459..6d4429a6d3 100644 --- a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/get-only-setter/output.js +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/get-only-setter/output.js @@ -14,7 +14,7 @@ class Cl { value: 0 }); - this.publicField = babelHelpers.writeOnlyError("#privateFieldValue"); + this.publicField = (this, babelHelpers.writeOnlyError("#privateFieldValue")); } } diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/reassignment/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/reassignment/exec.js new file mode 100644 index 0000000000..546574fbbd --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/reassignment/exec.js @@ -0,0 +1,18 @@ +let results = []; +class Foo { + constructor() { + this.self.#privateFieldValue = results.push(2); + } + + get self() { + results.push(1); + return this; + } + + get #privateFieldValue() { + return 42; + } +} + +expect(() => new Foo).toThrow(TypeError); +expect(results).toStrictEqual([1, 2]); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/reassignment/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/reassignment/input.js new file mode 100644 index 0000000000..822848f339 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/reassignment/input.js @@ -0,0 +1,15 @@ +let results = []; +class Foo { + constructor() { + this.self.#privateFieldValue = results.push(2); + } + + get self() { + results.push(1); + return this; + } + + get #privateFieldValue() { + return 42; + } +} diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/reassignment/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/reassignment/output.js new file mode 100644 index 0000000000..fde918b03f --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/reassignment/output.js @@ -0,0 +1,24 @@ +var results = []; + +var _privateFieldValue = new WeakMap(); + +class Foo { + constructor() { + _privateFieldValue.set(this, { + get: _get_privateFieldValue, + set: void 0 + }); + + this.self, results.push(2), babelHelpers.readOnlyError("#privateFieldValue"); + } + + get self() { + results.push(1); + return this; + } + +} + +var _get_privateFieldValue = function () { + return 42; +}; diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/set-only-getter/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/set-only-getter/exec.js index 64dd9738fd..7467e26271 100644 --- a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/set-only-getter/exec.js +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/set-only-getter/exec.js @@ -1,12 +1,19 @@ class Cl { #privateField = 0; + counter = 0; get #privateFieldValue() { return this.#privateField; } + get self() { + this.counter++; + return this; + } + constructor() { - expect(() => this.#privateFieldValue = 1).toThrow(TypeError); + expect(() => this.self.#privateFieldValue = 1).toThrow(TypeError); + expect(this.counter).toBe(1); } } diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/set-only-getter/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/set-only-getter/input.js index a3385ef160..f48aebaff2 100644 --- a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/set-only-getter/input.js +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/set-only-getter/input.js @@ -1,11 +1,19 @@ class Cl { #privateField = 0; + counter = 0; get #privateFieldValue() { return this.#privateField; } + get self() { + this.counter++; + return this; + } + constructor() { - this.#privateFieldValue = 1; + this.self.#privateFieldValue = 1 } } + +const cl = new Cl(); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/set-only-getter/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/set-only-getter/output.js index 7fe1e2be6f..c6c0ca1757 100644 --- a/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/set-only-getter/output.js +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/accessors/set-only-getter/output.js @@ -3,6 +3,11 @@ var _privateField = new WeakMap(); var _privateFieldValue = new WeakMap(); class Cl { + get self() { + this.counter++; + return this; + } + constructor() { _privateFieldValue.set(this, { get: _get_privateFieldValue, @@ -14,7 +19,8 @@ class Cl { value: 0 }); - babelHelpers.readOnlyError("#privateFieldValue"); + babelHelpers.defineProperty(this, "counter", 0); + this.self, 1, babelHelpers.readOnlyError("#privateFieldValue"); } } @@ -22,3 +28,5 @@ class Cl { var _get_privateFieldValue = function () { return babelHelpers.classPrivateFieldGet(this, _privateField); }; + +var cl = new Cl(); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-loose/reassignment/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-loose/reassignment/exec.js new file mode 100644 index 0000000000..7690d12830 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-loose/reassignment/exec.js @@ -0,0 +1,13 @@ +let counter = 0; +class Foo { + constructor() { + this.#privateMethod = ++counter; + } + + #privateMethod() { + return 42; + } +} + +expect(() => new Foo).toThrow(); +expect(counter).toBe(1); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-loose/reassignment/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-loose/reassignment/input.js new file mode 100644 index 0000000000..e8814772bf --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-loose/reassignment/input.js @@ -0,0 +1,10 @@ +let counter = 0; +class Foo { + constructor() { + this.#privateMethod = ++counter; + } + + #privateMethod() { + return 42; + } +} diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-loose/reassignment/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-loose/reassignment/output.js new file mode 100644 index 0000000000..fc2edb845b --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-loose/reassignment/output.js @@ -0,0 +1,17 @@ +var counter = 0; + +var _privateMethod = babelHelpers.classPrivateFieldLooseKey("privateMethod"); + +class Foo { + constructor() { + Object.defineProperty(this, _privateMethod, { + value: _privateMethod2 + }); + babelHelpers.classPrivateFieldLooseBase(this, _privateMethod)[_privateMethod] = ++counter; + } + +} + +var _privateMethod2 = function _privateMethod2() { + return 42; +}; diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/read-only/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/read-only/exec.js index 4bdbb3b3ac..4c02ddac7c 100644 --- a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/read-only/exec.js +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/read-only/exec.js @@ -1,9 +1,15 @@ class A { + counter = 0; #method() {} + self() { + this.counter++; + return this; + } - run() { - this.#method = 2; + constructor() { + expect(() => this.self().#method = 2).toThrow(TypeError); + expect(this.counter).toBe(1); } } -expect(() => new A().run()).toThrow(TypeError); +new A; diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/read-only/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/read-only/input.js index 6667af5411..ac074319f2 100644 --- a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/read-only/input.js +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/read-only/input.js @@ -1,7 +1,12 @@ class A { + counter = 0; #method() {} + self() { + this.counter++; + return this; + } - run() { - this.#method = 2; + constructor() { + this.self().#method = 2; } } diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/read-only/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/read-only/output.js index 72ecfd2576..7c1aa27900 100644 --- a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/read-only/output.js +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/read-only/output.js @@ -1,12 +1,16 @@ var _method = new WeakSet(); class A { - constructor() { - _method.add(this); + self() { + this.counter++; + return this; } - run() { - babelHelpers.readOnlyError("#method"); + constructor() { + _method.add(this); + + babelHelpers.defineProperty(this, "counter", 0); + this.self(), 2, babelHelpers.readOnlyError("#method"); } } diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/reassignment/exec.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/reassignment/exec.js new file mode 100644 index 0000000000..dc27b2dd1b --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/reassignment/exec.js @@ -0,0 +1,18 @@ +let results = []; +class Foo { + constructor() { + this.self.#privateFieldValue = results.push(2); + } + + get self() { + results.push(1); + return this; + } + + #privateFieldValue() { + return 42; + } +} + +expect(() => new Foo).toThrow(TypeError); +expect(results).toStrictEqual([1, 2]); diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/reassignment/input.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/reassignment/input.js new file mode 100644 index 0000000000..d6058a2683 --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/reassignment/input.js @@ -0,0 +1,15 @@ +let results = []; +class Foo { + constructor() { + this.self.#privateFieldValue = results.push(2); + } + + get self() { + results.push(1); + return this; + } + + #privateFieldValue() { + return 42; + } +} diff --git a/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/reassignment/output.js b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/reassignment/output.js new file mode 100644 index 0000000000..f4e9be344c --- /dev/null +++ b/packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/reassignment/output.js @@ -0,0 +1,21 @@ +var results = []; + +var _privateFieldValue = new WeakSet(); + +class Foo { + constructor() { + _privateFieldValue.add(this); + + this.self, results.push(2), babelHelpers.readOnlyError("#privateFieldValue"); + } + + get self() { + results.push(1); + return this; + } + +} + +var _privateFieldValue2 = function _privateFieldValue2() { + return 42; +};