Skip to content

Commit

Permalink
fix: support bigints in update expressions for private fields (#14311)
Browse files Browse the repository at this point in the history
  • Loading branch information
magic-akari committed Feb 27, 2022
1 parent dd6a53d commit 7ff3084
Show file tree
Hide file tree
Showing 12 changed files with 216 additions and 41 deletions.
49 changes: 30 additions & 19 deletions packages/babel-helper-member-expression-to-functions/src/index.ts
Expand Up @@ -16,11 +16,10 @@ import {
logicalExpression,
memberExpression,
nullLiteral,
numericLiteral,
optionalCallExpression,
optionalMemberExpression,
sequenceExpression,
unaryExpression,
updateExpression,
} from "@babel/types";
import type * as t from "@babel/types";
import { willPathCastToBoolean } from "./util";
Expand Down Expand Up @@ -350,8 +349,8 @@ const handle = {
return;
}

// MEMBER++ -> _set(MEMBER, (_ref = (+_get(MEMBER))) + 1), _ref
// ++MEMBER -> _set(MEMBER, (+_get(MEMBER)) + 1)
// MEMBER++ -> _set(MEMBER, (ref = _get(MEMBER), ref2 = ref++, ref)), ref2
// ++MEMBER -> _set(MEMBER, (ref = _get(MEMBER), ++ref))
if (isUpdateExpression(parent, { argument: node })) {
if (this.simpleSet) {
member.replaceWith(this.simpleSet(member));
Expand All @@ -365,31 +364,43 @@ const handle = {
// assignment.
this.memoise(member, 2);

const value = binaryExpression(
operator[0] as "+" | "-",
unaryExpression("+", this.get(member)),
numericLiteral(1),
);
const ref = scope.generateUidIdentifierBasedOnNode(node);
scope.push({ id: ref });

const seq: t.Expression[] = [
// ref = _get(MEMBER)
assignmentExpression("=", cloneNode(ref), this.get(member)),
];

if (prefix) {
seq.push(updateExpression(operator, cloneNode(ref), prefix));

// (ref = _get(MEMBER), ++ref)
const value = sequenceExpression(seq);
parentPath.replaceWith(this.set(member, value));
} else {
const { scope } = member;
const ref = scope.generateUidIdentifierBasedOnNode(node);
scope.push({ id: ref });

value.left = assignmentExpression(
"=",
return;
} else {
const ref2 = scope.generateUidIdentifierBasedOnNode(node);
scope.push({ id: ref2 });

seq.push(
assignmentExpression(
"=",
cloneNode(ref2),
updateExpression(operator, cloneNode(ref), prefix),
),
cloneNode(ref),
// @ts-expect-error todo(flow->ts) value.left is possibly PrivateName, which is not usable here
value.left,
);

// (ref = _get(MEMBER), ref2 = ref++, ref)
const value = sequenceExpression(seq);
parentPath.replaceWith(
sequenceExpression([this.set(member, value), cloneNode(ref)]),
sequenceExpression([this.set(member, value), cloneNode(ref2)]),
);

return;
}
return;
}

// MEMBER = VALUE -> _set(MEMBER, VALUE)
Expand Down
Expand Up @@ -14,12 +14,12 @@ var Foo = /*#__PURE__*/function () {
babelHelpers.createClass(Foo, [{
key: "test",
value: function test(other) {
var _this$foo, _other$obj, _other$obj$foo, _other$obj2;
var _this$foo, _this$foo2, _this$foo3, _other$obj, _other$obj$foo, _other$obj$foo2, _other$obj2, _other$obj$foo3;

babelHelpers.classPrivateFieldSet(this, _foo, (_this$foo = +babelHelpers.classPrivateFieldGet(this, _foo)) + 1), _this$foo;
babelHelpers.classPrivateFieldSet(this, _foo, +babelHelpers.classPrivateFieldGet(this, _foo) + 1);
babelHelpers.classPrivateFieldSet(_other$obj = other.obj, _foo, (_other$obj$foo = +babelHelpers.classPrivateFieldGet(_other$obj, _foo)) + 1), _other$obj$foo;
babelHelpers.classPrivateFieldSet(_other$obj2 = other.obj, _foo, +babelHelpers.classPrivateFieldGet(_other$obj2, _foo) + 1);
babelHelpers.classPrivateFieldSet(this, _foo, (_this$foo = babelHelpers.classPrivateFieldGet(this, _foo), _this$foo2 = _this$foo++, _this$foo)), _this$foo2;
babelHelpers.classPrivateFieldSet(this, _foo, (_this$foo3 = babelHelpers.classPrivateFieldGet(this, _foo), ++_this$foo3));
babelHelpers.classPrivateFieldSet(_other$obj = other.obj, _foo, (_other$obj$foo = babelHelpers.classPrivateFieldGet(_other$obj, _foo), _other$obj$foo2 = _other$obj$foo++, _other$obj$foo)), _other$obj$foo2;
babelHelpers.classPrivateFieldSet(_other$obj2 = other.obj, _foo, (_other$obj$foo3 = babelHelpers.classPrivateFieldGet(_other$obj2, _foo), ++_other$obj$foo3));
}
}]);
return Foo;
Expand Down
@@ -0,0 +1,50 @@
class Cl {
#privateField = "top secret string";

constructor() {
this.publicField = "not secret string";
}

get #privateFieldValue() {
return this.#privateField;
}

set #privateFieldValue(newValue) {
this.#privateField = newValue;
}

publicGetPrivateField() {
return this.#privateFieldValue;
}

publicSetPrivateField(newValue) {
this.#privateFieldValue = newValue;
}

get publicFieldValue() {
return this.publicField;
}

set publicFieldValue(newValue) {
this.publicField = newValue;
}

testUpdates() {
this.#privateField = 0n;
this.publicField = 0n;
this.#privateFieldValue = this.#privateFieldValue++;
this.publicFieldValue = this.publicFieldValue++;
expect(this.#privateField).toEqual(this.publicField);

++this.#privateFieldValue;
++this.publicFieldValue;
expect(this.#privateField).toEqual(this.publicField);

this.#privateFieldValue += 1n;
this.publicFieldValue += 1n;
expect(this.#privateField).toEqual(this.publicField);
}
}

const cl = new Cl();
cl.testUpdates();
@@ -0,0 +1,47 @@
class Cl {
#privateField = "top secret string";

constructor() {
this.publicField = "not secret string";
}

get #privateFieldValue() {
return this.#privateField;
}

set #privateFieldValue(newValue) {
this.#privateField = newValue;
}

publicGetPrivateField() {
return this.#privateFieldValue;
}

publicSetPrivateField(newValue) {
this.#privateFieldValue = newValue;
}

get publicFieldValue() {
return this.publicField;
}

set publicFieldValue(newValue) {
this.publicField = newValue;
}

testUpdates() {
this.#privateField = 0n;
this.publicField = 0n;
this.#privateFieldValue = this.#privateFieldValue++;
this.publicFieldValue = this.publicFieldValue++;

++this.#privateFieldValue;
++this.publicFieldValue;

this.#privateFieldValue += 1n;
this.publicFieldValue += 1n;

this.#privateFieldValue = -(this.#privateFieldValue ** this.#privateFieldValue);
this.publicFieldValue = -(this.publicFieldValue ** this.publicFieldValue);
}
}
@@ -0,0 +1,8 @@
{
"minNodeVersion": "10.0.0",
"plugins": [
"proposal-private-methods",
"proposal-class-properties",
"transform-block-scoping"
]
}
@@ -0,0 +1,57 @@
var _privateField = /*#__PURE__*/new WeakMap();

var _privateFieldValue = /*#__PURE__*/new WeakMap();

class Cl {
constructor() {
babelHelpers.classPrivateFieldInitSpec(this, _privateFieldValue, {
get: _get_privateFieldValue,
set: _set_privateFieldValue
});
babelHelpers.classPrivateFieldInitSpec(this, _privateField, {
writable: true,
value: "top secret string"
});
this.publicField = "not secret string";
}

publicGetPrivateField() {
return babelHelpers.classPrivateFieldGet(this, _privateFieldValue);
}

publicSetPrivateField(newValue) {
babelHelpers.classPrivateFieldSet(this, _privateFieldValue, newValue);
}

get publicFieldValue() {
return this.publicField;
}

set publicFieldValue(newValue) {
this.publicField = newValue;
}

testUpdates() {
var _this$privateFieldVal, _this$privateFieldVal2, _this$privateFieldVal3, _this$privateFieldVal4, _this$privateFieldVal5;

babelHelpers.classPrivateFieldSet(this, _privateField, 0n);
this.publicField = 0n;
babelHelpers.classPrivateFieldSet(this, _privateFieldValue, (babelHelpers.classPrivateFieldSet(this, _privateFieldValue, (_this$privateFieldVal3 = babelHelpers.classPrivateFieldGet(this, _privateFieldValue), _this$privateFieldVal4 = _this$privateFieldVal3++, _this$privateFieldVal3)), _this$privateFieldVal4));
this.publicFieldValue = this.publicFieldValue++;
babelHelpers.classPrivateFieldSet(this, _privateFieldValue, (_this$privateFieldVal5 = babelHelpers.classPrivateFieldGet(this, _privateFieldValue), ++_this$privateFieldVal5));
++this.publicFieldValue;
babelHelpers.classPrivateFieldSet(this, _privateFieldValue, babelHelpers.classPrivateFieldGet(this, _privateFieldValue) + 1n);
this.publicFieldValue += 1n;
babelHelpers.classPrivateFieldSet(this, _privateFieldValue, -(babelHelpers.classPrivateFieldGet(this, _privateFieldValue) ** babelHelpers.classPrivateFieldGet(this, _privateFieldValue)));
this.publicFieldValue = -(this.publicFieldValue ** this.publicFieldValue);
}

}

function _get_privateFieldValue() {
return babelHelpers.classPrivateFieldGet(this, _privateField);
}

function _set_privateFieldValue(newValue) {
babelHelpers.classPrivateFieldSet(this, _privateField, newValue);
}
Expand Up @@ -32,13 +32,13 @@ class Cl {
}

testUpdates() {
var _this$privateFieldVal, _this$privateFieldVal2;
var _this$privateFieldVal, _this$privateFieldVal2, _this$privateFieldVal3, _this$privateFieldVal4, _this$privateFieldVal5;

babelHelpers.classPrivateFieldSet(this, _privateField, 0);
this.publicField = 0;
babelHelpers.classPrivateFieldSet(this, _privateFieldValue, (babelHelpers.classPrivateFieldSet(this, _privateFieldValue, (_this$privateFieldVal2 = +babelHelpers.classPrivateFieldGet(this, _privateFieldValue)) + 1), _this$privateFieldVal2));
babelHelpers.classPrivateFieldSet(this, _privateFieldValue, (babelHelpers.classPrivateFieldSet(this, _privateFieldValue, (_this$privateFieldVal3 = babelHelpers.classPrivateFieldGet(this, _privateFieldValue), _this$privateFieldVal4 = _this$privateFieldVal3++, _this$privateFieldVal3)), _this$privateFieldVal4));
this.publicFieldValue = this.publicFieldValue++;
babelHelpers.classPrivateFieldSet(this, _privateFieldValue, +babelHelpers.classPrivateFieldGet(this, _privateFieldValue) + 1);
babelHelpers.classPrivateFieldSet(this, _privateFieldValue, (_this$privateFieldVal5 = babelHelpers.classPrivateFieldGet(this, _privateFieldValue), ++_this$privateFieldVal5));
++this.publicFieldValue;
babelHelpers.classPrivateFieldSet(this, _privateFieldValue, babelHelpers.classPrivateFieldGet(this, _privateFieldValue) + 1);
this.publicFieldValue += 1;
Expand Down
Expand Up @@ -16,13 +16,13 @@ class Cl {
}

static testUpdates() {
var _Cl$privateFieldValue, _Cl$privateFieldValue2;
var _Cl$privateFieldValue, _Cl$privateFieldValue2, _Cl$privateFieldValue3, _Cl$privateFieldValue4, _Cl$privateFieldValue5;

babelHelpers.classStaticPrivateFieldSpecSet(Cl, Cl, _privateField, 0);
Cl.publicField = 0;
babelHelpers.classStaticPrivateFieldSpecSet(Cl, Cl, _privateFieldValue, (babelHelpers.classStaticPrivateFieldSpecSet(Cl, Cl, _privateFieldValue, (_Cl$privateFieldValue2 = +babelHelpers.classStaticPrivateFieldSpecGet(Cl, Cl, _privateFieldValue)) + 1), _Cl$privateFieldValue2));
babelHelpers.classStaticPrivateFieldSpecSet(Cl, Cl, _privateFieldValue, (babelHelpers.classStaticPrivateFieldSpecSet(Cl, Cl, _privateFieldValue, (_Cl$privateFieldValue3 = babelHelpers.classStaticPrivateFieldSpecGet(Cl, Cl, _privateFieldValue), _Cl$privateFieldValue4 = _Cl$privateFieldValue3++, _Cl$privateFieldValue3)), _Cl$privateFieldValue4));
Cl.publicFieldValue = Cl.publicFieldValue++;
babelHelpers.classStaticPrivateFieldSpecSet(Cl, Cl, _privateFieldValue, +babelHelpers.classStaticPrivateFieldSpecGet(Cl, Cl, _privateFieldValue) + 1);
babelHelpers.classStaticPrivateFieldSpecSet(Cl, Cl, _privateFieldValue, (_Cl$privateFieldValue5 = babelHelpers.classStaticPrivateFieldSpecGet(Cl, Cl, _privateFieldValue), ++_Cl$privateFieldValue5));
++Cl.publicFieldValue;
babelHelpers.classStaticPrivateFieldSpecSet(Cl, Cl, _privateFieldValue, babelHelpers.classStaticPrivateFieldSpecGet(Cl, Cl, _privateFieldValue) + 1);
Cl.publicFieldValue += 1;
Expand Down
Expand Up @@ -30,15 +30,15 @@ let Obj = /*#__PURE__*/function (_Base) {
var _proto = Obj.prototype;

_proto.update = function update() {
var _proper$prop, _super$proper$prop;
var _proper$prop, _super$proper$prop, _super$proper$prop2;

this[_proper$prop = proper.prop] = (_super$proper$prop = +_Base.prototype[_proper$prop]) + 1, _super$proper$prop;
this[_proper$prop = proper.prop] = (_super$proper$prop = _Base.prototype[_proper$prop], _super$proper$prop2 = _super$proper$prop++, _super$proper$prop), _super$proper$prop2;
};

_proto.update2 = function update2() {
var _i, _super$i;
var _i, _super$i, _super$i2;

this[_i = i] = (_super$i = +_Base.prototype[_i]) + 1, _super$i;
this[_i = i] = (_super$i = _Base.prototype[_i], _super$i2 = _super$i++, _super$i), _super$i2;
};

return Obj;
Expand Down
Expand Up @@ -34,16 +34,16 @@ let Obj = /*#__PURE__*/function (_Base) {
babelHelpers.createClass(Obj, [{
key: "update",
value: function update() {
var _proper$prop, _super$proper$prop;
var _proper$prop, _super$proper$prop, _super$proper$prop2;

babelHelpers.set(babelHelpers.getPrototypeOf(Obj.prototype), _proper$prop = proper.prop, (_super$proper$prop = +babelHelpers.get(babelHelpers.getPrototypeOf(Obj.prototype), _proper$prop, this)) + 1, this, true), _super$proper$prop;
babelHelpers.set(babelHelpers.getPrototypeOf(Obj.prototype), _proper$prop = proper.prop, (_super$proper$prop = babelHelpers.get(babelHelpers.getPrototypeOf(Obj.prototype), _proper$prop, this), _super$proper$prop2 = _super$proper$prop++, _super$proper$prop), this, true), _super$proper$prop2;
}
}, {
key: "update2",
value: function update2() {
var _i, _super$i;
var _i, _super$i, _super$i2;

babelHelpers.set(babelHelpers.getPrototypeOf(Obj.prototype), _i = i, (_super$i = +babelHelpers.get(babelHelpers.getPrototypeOf(Obj.prototype), _i, this)) + 1, this, true), _super$i;
babelHelpers.set(babelHelpers.getPrototypeOf(Obj.prototype), _i = i, (_super$i = babelHelpers.get(babelHelpers.getPrototypeOf(Obj.prototype), _i, this), _super$i2 = _super$i++, _super$i), this, true), _super$i2;
}
}]);
return Obj;
Expand Down
Expand Up @@ -5,9 +5,9 @@ var Base = {
};
var obj = _obj = {
bar: function () {
var _super$test;
var _super$test, _super$test2;

return babelHelpers.set(babelHelpers.getPrototypeOf(_obj), "test", (_super$test = +babelHelpers.get(babelHelpers.getPrototypeOf(_obj), "test", this)) + 1, this, false), _super$test;
return babelHelpers.set(babelHelpers.getPrototypeOf(_obj), "test", (_super$test = babelHelpers.get(babelHelpers.getPrototypeOf(_obj), "test", this), _super$test2 = _super$test++, _super$test), this, false), _super$test2;
}
};
Object.setPrototypeOf(obj, Base);
Expand Down
Expand Up @@ -5,7 +5,9 @@ var Base = {
};
var obj = _obj = {
bar: function () {
return babelHelpers.set(babelHelpers.getPrototypeOf(_obj), "test", +babelHelpers.get(babelHelpers.getPrototypeOf(_obj), "test", this) + 1, this, false);
var _super$test;

return babelHelpers.set(babelHelpers.getPrototypeOf(_obj), "test", (_super$test = babelHelpers.get(babelHelpers.getPrototypeOf(_obj), "test", this), ++_super$test), this, false);
}
};
Object.setPrototypeOf(obj, Base);
Expand Down

0 comments on commit 7ff3084

Please sign in to comment.