From 15150b3b334ac7b0f75c3beff92aa2ede4b65594 Mon Sep 17 00:00:00 2001 From: Ujjwal Sharma Date: Wed, 10 Jun 2020 20:59:18 +0530 Subject: [PATCH] add support for logical assignments with private properties Patches the logic for handling assignment operators and adds support for handling the logical assignment operators appropriately. Fixes: https://github.com/babel/babel/issues/11646 --- .../src/index.js | 20 +++++++--- .../private/logical-assignment/input.js | 11 ++++++ .../private/logical-assignment/options.json | 6 +++ .../private/logical-assignment/output.js | 37 +++++++++++++++++++ 4 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private/logical-assignment/input.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private/logical-assignment/options.json create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private/logical-assignment/output.js diff --git a/packages/babel-helper-member-expression-to-functions/src/index.js b/packages/babel-helper-member-expression-to-functions/src/index.js index 7724406d2b46..e4e2421783c4 100644 --- a/packages/babel-helper-member-expression-to-functions/src/index.js +++ b/packages/babel-helper-member-expression-to-functions/src/index.js @@ -306,11 +306,21 @@ const handle = { // assignment. this.memoise(member, 2); - value = t.binaryExpression( - operator.slice(0, -1), - this.get(member), - value, - ); + const operatorTrunc = operator.slice(0, -1); + switch (operatorTrunc) { + case "??": + case "||": + case "&&": + value = t.logicalExpression(operatorTrunc, this.get(member), value); + break; + default: + value = t.binaryExpression( + operator.slice(0, -1), + this.get(member), + value, + ); + break; + } } parentPath.replaceWith(this.set(member, value)); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/logical-assignment/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/logical-assignment/input.js new file mode 100644 index 000000000000..c79508638f55 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/logical-assignment/input.js @@ -0,0 +1,11 @@ +class Foo { + #nullish = 0; + #and = 0; + #or = 0; + + test() { + this.#nullish ??= 42; + this.#and &&= 0; + this.#or ||= 0; + } +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/logical-assignment/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/logical-assignment/options.json new file mode 100644 index 000000000000..26f2ddc95852 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/logical-assignment/options.json @@ -0,0 +1,6 @@ +{ + "plugins": [ + "proposal-logical-assignment-operators", + "proposal-class-properties" + ] +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/logical-assignment/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/logical-assignment/output.js new file mode 100644 index 000000000000..4603fdc257c7 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/logical-assignment/output.js @@ -0,0 +1,37 @@ +function _classPrivateFieldSet(receiver, privateMap, value) { var descriptor = privateMap.get(receiver); if (!descriptor) { throw new TypeError("attempted to set private field on non-instance"); } if (descriptor.set) { descriptor.set.call(receiver, value); } else { if (!descriptor.writable) { throw new TypeError("attempted to set read only private field"); } descriptor.value = value; } return value; } + +function _classPrivateFieldGet(receiver, privateMap) { var descriptor = privateMap.get(receiver); if (!descriptor) { throw new TypeError("attempted to get private field on non-instance"); } if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; } + +var _nullish = new WeakMap(); + +var _and = new WeakMap(); + +var _or = new WeakMap(); + +class Foo { + constructor() { + _nullish.set(this, { + writable: true, + value: 0 + }); + + _and.set(this, { + writable: true, + value: 0 + }); + + _or.set(this, { + writable: true, + value: 0 + }); + } + + test() { + _classPrivateFieldSet(this, _nullish, _classPrivateFieldGet(this, _nullish) ?? 42); + + _classPrivateFieldSet(this, _and, _classPrivateFieldGet(this, _and) && 0); + + _classPrivateFieldSet(this, _or, _classPrivateFieldGet(this, _or) || 0); + } + +}