From ffee2ee739c31d8e4fd7229e3690594f70f72728 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Mon, 17 Jan 2022 12:09:33 +0800 Subject: [PATCH 1/6] fix: add test cases --- .../babel-traverse/test/arrow-transform.js | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) diff --git a/packages/babel-traverse/test/arrow-transform.js b/packages/babel-traverse/test/arrow-transform.js index 268c73ce04be..30a70df77292 100644 --- a/packages/babel-traverse/test/arrow-transform.js +++ b/packages/babel-traverse/test/arrow-transform.js @@ -518,6 +518,152 @@ describe("arrow function conversion", () => { ); }); + it("should convert super.prop operator logical assign `??=`", () => { + assertConversion( + ` + () => { + super.foo ??= 4; + }; + super.foo ??= 4; + () => super.foo ??= 4; + `, + ` + var _superprop_setFoo = _value => super.foo = _value, + _superprop_getFoo = () => super.foo; + + (function () { + _superprop_setFoo(_superprop_getFoo() ?? 4); + }); + super.foo ??= 4; + () => super.foo ??= 4; + `, + ); + }); + + it("should convert super.prop operator logical assign `&&=`", () => { + assertConversion( + ` + () => { + super.foo &&= true; + }; + super.foo &&= true; + () => super.foo &&= true; + `, + ` + var _superprop_setFoo = _value => super.foo = _value, + _superprop_getFoo = () => super.foo; + + (function () { + _superprop_setFoo(_superprop_getFoo() && true); + }); + super.foo &&= true; + () => super.foo &&= true; + `, + ); + }); + + it("should convert super.prop operator logical assign `||=`", () => { + assertConversion( + ` + () => { + super.foo ||= true; + }; + super.foo ||= true; + () => super.foo ||= true; + `, + ` + var _superprop_setFoo = _value => super.foo = _value, + _superprop_getFoo = () => super.foo; + + (function () { + _superprop_setFoo(_superprop_getFoo() || true); + }); + super.foo ||= true; + () => super.foo ||= true; + `, + ); + }); + + // + + it("should convert super[prop] operator logical assign `??=`", () => { + assertConversion( + ` + () => { + super[foo] ??= 4; + }; + super[foo] ??= 4; + () => super[foo] ??= 4; + `, + ` + var _superprop_set = (_prop, _value) => super[_prop] = _value, + _superprop_get = _prop2 => super[_prop2]; + + (function () { + var _tmp; + + _superprop_set(_tmp = foo, _superprop_get(_tmp) ?? 4); + }); + + super[foo] ??= 4; + + () => super[foo] ??= 4; + `, + ); + }); + + it("should convert super[prop] operator logical assign `&&=`", () => { + assertConversion( + ` + () => { + super[foo] &&= true; + }; + super[foo] &&= true; + () => super[foo] &&= true; + `, + ` + var _superprop_set = (_prop, _value) => super[_prop] = _value, + _superprop_get = _prop2 => super[_prop2]; + + (function () { + var _tmp; + + _superprop_set(_tmp = foo, _superprop_get(_tmp) && true); + }); + + super[foo] &&= true; + + () => super[foo] &&= true; + `, + ); + }); + + it("should convert super[prop] operator logical assign `||=`", () => { + assertConversion( + ` + () => { + super[foo] ||= true; + }; + super[foo] ||= true; + () => super[foo] ||= true; + `, + ` + var _superprop_set = (_prop, _value) => super[_prop] = _value, + _superprop_get = _prop2 => super[_prop2]; + + (function () { + var _tmp; + + _superprop_set(_tmp = foo, _superprop_get(_tmp) || true); + }); + + super[foo] ||= true; + + () => super[foo] ||= true; + `, + ); + }); + it("should convert `++super.prop` prefix update", () => { assertConversion( ` From 50a2449e7e40c257c2afe008ab9fa357eafab757 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Mon, 17 Jan 2022 12:11:27 +0800 Subject: [PATCH 2/6] Fix logical assignment in super property transforms --- .../babel-traverse/src/path/conversion.ts | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/babel-traverse/src/path/conversion.ts b/packages/babel-traverse/src/path/conversion.ts index 3aed8568f6d1..39e30a4eaac3 100644 --- a/packages/babel-traverse/src/path/conversion.ts +++ b/packages/babel-traverse/src/path/conversion.ts @@ -11,6 +11,7 @@ import { identifier, isIdentifier, jsxIdentifier, + logicalExpression, memberExpression, metaProperty, numericLiteral, @@ -424,7 +425,7 @@ function standardizeSuperProperty(superProp) { assignmentPath .get("right") .replaceWith( - binaryExpression( + rightExpression( op, memberExpression( superProp.node.object, @@ -444,7 +445,7 @@ function standardizeSuperProperty(superProp) { assignmentPath .get("right") .replaceWith( - binaryExpression( + rightExpression( op, memberExpression( superProp.node.object, @@ -506,6 +507,21 @@ function standardizeSuperProperty(superProp) { } return [superProp]; + + type LogicalOp = Parameters[0]; + type BinaryOp = Parameters[0]; + + function rightExpression( + op: LogicalOp | BinaryOp, + left: t.Expression, + right: t.Expression, + ) { + if (["||", "&&", "??"].includes(op)) { + return logicalExpression(op as LogicalOp, left, right); + } else { + return binaryExpression(op as BinaryOp, left, right); + } + } } function hasSuperClass(thisEnvFn) { From a2cd315b7aebd28db02eac2ef17e7420d0ebf101 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Mon, 17 Jan 2022 19:26:50 +0800 Subject: [PATCH 3/6] fix: test cases --- .../babel-traverse/test/arrow-transform.js | 68 ++++++++++--------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/packages/babel-traverse/test/arrow-transform.js b/packages/babel-traverse/test/arrow-transform.js index 30a70df77292..7e36e0c8375b 100644 --- a/packages/babel-traverse/test/arrow-transform.js +++ b/packages/babel-traverse/test/arrow-transform.js @@ -528,14 +528,16 @@ describe("arrow function conversion", () => { () => super.foo ??= 4; `, ` - var _superprop_setFoo = _value => super.foo = _value, - _superprop_getFoo = () => super.foo; + var _superprop_getFoo = () => super.foo, + _superprop_setFoo = _value => super.foo = _value; - (function () { - _superprop_setFoo(_superprop_getFoo() ?? 4); - }); - super.foo ??= 4; - () => super.foo ??= 4; + (function () { + _superprop_getFoo() ?? _superprop_setFoo(4); + }); + + super.foo ??= 4; + + () => super.foo ??= 4; `, ); }); @@ -550,14 +552,16 @@ describe("arrow function conversion", () => { () => super.foo &&= true; `, ` - var _superprop_setFoo = _value => super.foo = _value, - _superprop_getFoo = () => super.foo; + var _superprop_getFoo = () => super.foo, + _superprop_setFoo = _value => super.foo = _value; - (function () { - _superprop_setFoo(_superprop_getFoo() && true); - }); - super.foo &&= true; - () => super.foo &&= true; + (function () { + _superprop_getFoo() && _superprop_setFoo(true); + }); + + super.foo &&= true; + + () => super.foo &&= true; `, ); }); @@ -572,20 +576,20 @@ describe("arrow function conversion", () => { () => super.foo ||= true; `, ` - var _superprop_setFoo = _value => super.foo = _value, - _superprop_getFoo = () => super.foo; + var _superprop_getFoo = () => super.foo, + _superprop_setFoo = _value => super.foo = _value; - (function () { - _superprop_setFoo(_superprop_getFoo() || true); - }); - super.foo ||= true; - () => super.foo ||= true; + (function () { + _superprop_getFoo() || _superprop_setFoo(true); + }); + + super.foo ||= true; + + () => super.foo ||= true; `, ); }); - // - it("should convert super[prop] operator logical assign `??=`", () => { assertConversion( ` @@ -596,13 +600,13 @@ describe("arrow function conversion", () => { () => super[foo] ??= 4; `, ` - var _superprop_set = (_prop, _value) => super[_prop] = _value, - _superprop_get = _prop2 => super[_prop2]; + var _superprop_get = _prop => super[_prop], + _superprop_set = (_prop2, _value) => super[_prop2] = _value; (function () { var _tmp; - _superprop_set(_tmp = foo, _superprop_get(_tmp) ?? 4); + _superprop_get(_tmp = foo) ?? _superprop_set(_tmp, 4); }); super[foo] ??= 4; @@ -622,13 +626,13 @@ describe("arrow function conversion", () => { () => super[foo] &&= true; `, ` - var _superprop_set = (_prop, _value) => super[_prop] = _value, - _superprop_get = _prop2 => super[_prop2]; + var _superprop_get = _prop => super[_prop], + _superprop_set = (_prop2, _value) => super[_prop2] = _value; (function () { var _tmp; - _superprop_set(_tmp = foo, _superprop_get(_tmp) && true); + _superprop_get(_tmp = foo) && _superprop_set(_tmp, true); }); super[foo] &&= true; @@ -648,13 +652,13 @@ describe("arrow function conversion", () => { () => super[foo] ||= true; `, ` - var _superprop_set = (_prop, _value) => super[_prop] = _value, - _superprop_get = _prop2 => super[_prop2]; + var _superprop_get = _prop => super[_prop], + _superprop_set = (_prop2, _value) => super[_prop2] = _value; (function () { var _tmp; - _superprop_set(_tmp = foo, _superprop_get(_tmp) || true); + _superprop_get(_tmp = foo) || _superprop_set(_tmp, true); }); super[foo] ||= true; From f47fb15ae47a5d7b4888a09a9ac79d4f93eef556 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Mon, 17 Jan 2022 21:34:47 +0800 Subject: [PATCH 4/6] Fix logical assignment in super property transforms --- .../babel-traverse/src/path/conversion.ts | 78 +++++++++++++------ 1 file changed, 54 insertions(+), 24 deletions(-) diff --git a/packages/babel-traverse/src/path/conversion.ts b/packages/babel-traverse/src/path/conversion.ts index 39e30a4eaac3..c5a02c5a1a58 100644 --- a/packages/babel-traverse/src/path/conversion.ts +++ b/packages/babel-traverse/src/path/conversion.ts @@ -398,26 +398,39 @@ function hoistFunctionEnvironment( return { thisBinding, fnPath }; } -function standardizeSuperProperty(superProp) { +function standardizeSuperProperty(superProp: NodePath) { if ( superProp.parentPath.isAssignmentExpression() && superProp.parentPath.node.operator !== "=" ) { const assignmentPath = superProp.parentPath; - const op = assignmentPath.node.operator.slice(0, -1); + const op = assignmentPath.node.operator.slice(0, -1) as + | LogicalOp + | BinaryOp; + const value = assignmentPath.node.right; - assignmentPath.node.operator = "="; + const isLogicalAssignment = op === "||" || op === "&&" || op === "??"; + if (superProp.node.computed) { + // from: super[foo] **= 4; + // to: super[tmp = foo] = super[tmp] ** 4; + + // from: super[foo] ??= 4; + // to: super[tmp = foo] ?? super[tmp] = 4; + const tmp = superProp.scope.generateDeclaredUidIdentifier("tmp"); + const object = superProp.node.object; + const property = superProp.node.property as t.Expression; + assignmentPath .get("left") .replaceWith( memberExpression( - superProp.node.object, - assignmentExpression("=", tmp, superProp.node.property), + object, + assignmentExpression("=", tmp, property), true /* computed */, ), ); @@ -426,35 +439,48 @@ function standardizeSuperProperty(superProp) { .get("right") .replaceWith( rightExpression( - op, - memberExpression( - superProp.node.object, - identifier(tmp.name), - true /* computed */, - ), + isLogicalAssignment ? "=" : op, + memberExpression(object, identifier(tmp.name), true /* computed */), value, ), ); } else { + // from: super.foo **= 4; + // to: super.foo = super.foo ** 4; + + // from: super.foo ??= 4; + // to: super.foo ?? super.foo = 4; + + const object = superProp.node.object; + const property = superProp.node.property as t.Identifier; + assignmentPath .get("left") - .replaceWith( - memberExpression(superProp.node.object, superProp.node.property), - ); + .replaceWith(memberExpression(object, property)); assignmentPath .get("right") .replaceWith( rightExpression( - op, - memberExpression( - superProp.node.object, - identifier(superProp.node.property.name), - ), + isLogicalAssignment ? "=" : op, + memberExpression(object, identifier(property.name)), value, ), ); } + + if (isLogicalAssignment) { + assignmentPath.replaceWith( + logicalExpression( + op as LogicalOp, + assignmentPath.node.left as t.Expression, + assignmentPath.node.right as t.Expression, + ), + ); + } else { + assignmentPath.node.operator = "="; + } + return [ assignmentPath.get("left"), assignmentPath.get("right").get("left"), @@ -474,7 +500,11 @@ function standardizeSuperProperty(superProp) { memberExpression( superProp.node.object, computedKey - ? assignmentExpression("=", computedKey, superProp.node.property) + ? assignmentExpression( + "=", + computedKey, + superProp.node.property as t.Expression, + ) : superProp.node.property, superProp.node.computed, ), @@ -512,12 +542,12 @@ function standardizeSuperProperty(superProp) { type BinaryOp = Parameters[0]; function rightExpression( - op: LogicalOp | BinaryOp, - left: t.Expression, + op: BinaryOp | "=", + left: t.MemberExpression, right: t.Expression, ) { - if (["||", "&&", "??"].includes(op)) { - return logicalExpression(op as LogicalOp, left, right); + if (op === "=") { + return assignmentExpression("=", left, right); } else { return binaryExpression(op as BinaryOp, left, right); } From bc988164c01d7714f8be9089f665dbf0ca73f91a Mon Sep 17 00:00:00 2001 From: magic-akari Date: Mon, 17 Jan 2022 22:08:49 +0800 Subject: [PATCH 5/6] chore: clean code --- packages/babel-traverse/src/path/conversion.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/babel-traverse/src/path/conversion.ts b/packages/babel-traverse/src/path/conversion.ts index c5a02c5a1a58..aa06378a4065 100644 --- a/packages/babel-traverse/src/path/conversion.ts +++ b/packages/babel-traverse/src/path/conversion.ts @@ -472,7 +472,7 @@ function standardizeSuperProperty(superProp: NodePath) { if (isLogicalAssignment) { assignmentPath.replaceWith( logicalExpression( - op as LogicalOp, + op, assignmentPath.node.left as t.Expression, assignmentPath.node.right as t.Expression, ), @@ -549,7 +549,7 @@ function standardizeSuperProperty(superProp: NodePath) { if (op === "=") { return assignmentExpression("=", left, right); } else { - return binaryExpression(op as BinaryOp, left, right); + return binaryExpression(op, left, right); } } } From b171bba4773f01442a428b9d7047c40a544fc682 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Tue, 18 Jan 2022 00:35:37 +0800 Subject: [PATCH 6/6] chore: clean code --- packages/babel-traverse/src/path/conversion.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/babel-traverse/src/path/conversion.ts b/packages/babel-traverse/src/path/conversion.ts index aa06378a4065..fb4fc3fbf755 100644 --- a/packages/babel-traverse/src/path/conversion.ts +++ b/packages/babel-traverse/src/path/conversion.ts @@ -12,6 +12,7 @@ import { isIdentifier, jsxIdentifier, logicalExpression, + LOGICAL_OPERATORS, memberExpression, metaProperty, numericLiteral, @@ -398,6 +399,13 @@ function hoistFunctionEnvironment( return { thisBinding, fnPath }; } +type LogicalOp = Parameters[0]; +type BinaryOp = Parameters[0]; + +function isLogicalOp(op: string): op is LogicalOp { + return LOGICAL_OPERATORS.includes(op); +} + function standardizeSuperProperty(superProp: NodePath) { if ( superProp.parentPath.isAssignmentExpression() && @@ -411,7 +419,7 @@ function standardizeSuperProperty(superProp: NodePath) { const value = assignmentPath.node.right; - const isLogicalAssignment = op === "||" || op === "&&" || op === "??"; + const isLogicalAssignment = isLogicalOp(op); if (superProp.node.computed) { // from: super[foo] **= 4; @@ -538,9 +546,6 @@ function standardizeSuperProperty(superProp: NodePath) { return [superProp]; - type LogicalOp = Parameters[0]; - type BinaryOp = Parameters[0]; - function rightExpression( op: BinaryOp | "=", left: t.MemberExpression,