Skip to content

Commit

Permalink
Evaluate object and initializer when setting a private method (#12707)
Browse files Browse the repository at this point in the history
* fix: evaluate initializer when a private method is set as a field

* make legacy node happy

* add accessor test cases

* fix: evaluate object before RHS

* fix: evaluate object before throwing writeOnlyError
  • Loading branch information
JLHwung committed Mar 1, 2021
1 parent 78d1950 commit 82e089c
Show file tree
Hide file tree
Showing 20 changed files with 253 additions and 16 deletions.
15 changes: 11 additions & 4 deletions packages/babel-helper-create-class-features-plugin/src/fields.js
Expand Up @@ -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(
Expand Down Expand Up @@ -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"), [
Expand Down
@@ -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);
@@ -0,0 +1,10 @@
let counter = 0;
class Foo {
constructor() {
this.#privateFieldValue = ++counter;
}

get #privateFieldValue() {
return 42;
}
}
@@ -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;
};
Expand Up @@ -14,7 +14,7 @@ class Cl {
value: 0
});

this.publicField = babelHelpers.writeOnlyError("#privateFieldValue");
this.publicField = (this, babelHelpers.writeOnlyError("#privateFieldValue"));
}

}
Expand Down
@@ -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]);
@@ -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;
}
}
@@ -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;
};
@@ -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);
}
}

Expand Down
@@ -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();
Expand Up @@ -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,
Expand All @@ -14,11 +19,14 @@ class Cl {
value: 0
});

babelHelpers.readOnlyError("#privateFieldValue");
babelHelpers.defineProperty(this, "counter", 0);
this.self, 1, babelHelpers.readOnlyError("#privateFieldValue");
}

}

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

var cl = new Cl();
@@ -0,0 +1,13 @@
let counter = 0;
class Foo {
constructor() {
this.#privateMethod = ++counter;
}

#privateMethod() {
return 42;
}
}

expect(() => new Foo).toThrow();
expect(counter).toBe(1);
@@ -0,0 +1,10 @@
let counter = 0;
class Foo {
constructor() {
this.#privateMethod = ++counter;
}

#privateMethod() {
return 42;
}
}
@@ -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;
};
@@ -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;
@@ -1,7 +1,12 @@
class A {
counter = 0;
#method() {}
self() {
this.counter++;
return this;
}

run() {
this.#method = 2;
constructor() {
this.self().#method = 2;
}
}
@@ -1,12 +1,16 @@
var _method = new WeakSet();

class A {
self() {
this.counter++;
return this;
}

constructor() {
_method.add(this);
}

run() {
babelHelpers.readOnlyError("#method");
babelHelpers.defineProperty(this, "counter", 0);
this.self(), 2, babelHelpers.readOnlyError("#method");
}

}
Expand Down
@@ -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]);
@@ -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;
}
}
@@ -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;
};

0 comments on commit 82e089c

Please sign in to comment.