Class Private Static Accessors (#10217)

* Remove error for static private accessors

* Private static accessors strict

* Add loose mode support

* Move `value` decl for early return

* Reuse getter/setter template

* Reuse getter/setter templates

* Use `buildUndefinedNode` in accessor templates

* Extract `isAccessor` variable
This commit is contained in:
Tim McClure 2019-09-06 12:08:10 -04:00 committed by Nicolò Ribaudo
parent da0af5fd99
commit 3e4889d649
35 changed files with 749 additions and 90 deletions

View File

@ -66,12 +66,6 @@ export function verifyUsedFeatures(path, file) {
if (!hasFeature(file, FEATURES.privateMethods)) { if (!hasFeature(file, FEATURES.privateMethods)) {
throw path.buildCodeFrameError("Class private methods are not enabled."); throw path.buildCodeFrameError("Class private methods are not enabled.");
} }
if (path.node.static && path.node.kind !== "method") {
throw path.buildCodeFrameError(
"@babel/plugin-class-features doesn't support class static private accessors yet.",
);
}
} }
if ( if (

View File

@ -44,6 +44,7 @@ export function buildPrivateNamesNodes(privateNamesMap, loose, state) {
// because static fields are directly assigned to a variable in the // because static fields are directly assigned to a variable in the
// buildPrivateStaticFieldInitSpec function. // buildPrivateStaticFieldInitSpec function.
const { id, static: isStatic, method: isMethod, getId, setId } = value; const { id, static: isStatic, method: isMethod, getId, setId } = value;
const isAccessor = getId || setId;
if (loose) { if (loose) {
initNodes.push( initNodes.push(
template.statement.ast` template.statement.ast`
@ -51,7 +52,7 @@ export function buildPrivateNamesNodes(privateNamesMap, loose, state) {
`, `,
); );
} else if (isMethod && !isStatic) { } else if (isMethod && !isStatic) {
if (getId || setId) { if (isAccessor) {
initNodes.push(template.statement.ast`var ${id} = new WeakMap();`); initNodes.push(template.statement.ast`var ${id} = new WeakMap();`);
} else { } else {
initNodes.push(template.statement.ast`var ${id} = new WeakSet();`); initNodes.push(template.statement.ast`var ${id} = new WeakSet();`);
@ -140,9 +141,11 @@ const privateNameHandlerSpec = {
getId, getId,
setId, setId,
} = privateNamesMap.get(name); } = privateNamesMap.get(name);
const isAccessor = getId || setId;
if (isStatic) { if (isStatic) {
const helperName = isMethod const helperName =
isMethod && !isAccessor
? "classStaticPrivateMethodGet" ? "classStaticPrivateMethodGet"
: "classStaticPrivateFieldSpecGet"; : "classStaticPrivateFieldSpecGet";
@ -154,7 +157,7 @@ const privateNameHandlerSpec = {
} }
if (isMethod) { if (isMethod) {
if (getId || setId) { if (isAccessor) {
return t.callExpression(file.addHelper("classPrivateFieldGet"), [ return t.callExpression(file.addHelper("classPrivateFieldGet"), [
this.receiver(member), this.receiver(member),
t.cloneNode(id), t.cloneNode(id),
@ -180,10 +183,13 @@ const privateNameHandlerSpec = {
static: isStatic, static: isStatic,
method: isMethod, method: isMethod,
setId, setId,
getId,
} = privateNamesMap.get(name); } = privateNamesMap.get(name);
const isAccessor = getId || setId;
if (isStatic) { if (isStatic) {
const helperName = isMethod const helperName =
isMethod && !isAccessor
? "classStaticPrivateMethodSet" ? "classStaticPrivateMethodSet"
: "classStaticPrivateFieldSpecSet"; : "classStaticPrivateFieldSpecSet";
@ -300,9 +306,30 @@ function buildPrivateInstanceFieldInitSpec(ref, prop, privateNamesMap) {
} }
function buildPrivateStaticFieldInitSpec(prop, privateNamesMap) { function buildPrivateStaticFieldInitSpec(prop, privateNamesMap) {
const { id } = privateNamesMap.get(prop.node.key.id.name); const privateName = privateNamesMap.get(prop.node.key.id.name);
const value = prop.node.value || prop.scope.buildUndefinedNode(); const { id, getId, setId, initAdded } = privateName;
const isAccessor = getId || setId;
if (!prop.isProperty() && (initAdded || !isAccessor)) return;
if (isAccessor) {
privateNamesMap.set(prop.node.key.id.name, {
...privateName,
initAdded: true,
});
return template.statement.ast`
var ${id.name} = {
// configurable is false by default
// enumerable is false by default
// writable is false by default
get: ${getId ? getId.name : prop.scope.buildUndefinedNode()},
set: ${setId ? setId.name : prop.scope.buildUndefinedNode()}
}
`;
}
const value = prop.node.value || prop.scope.buildUndefinedNode();
return template.statement.ast` return template.statement.ast`
var ${id} = { var ${id} = {
// configurable is false by default // configurable is false by default
@ -328,76 +355,44 @@ function buildPrivateMethodInitLoose(ref, prop, privateNamesMap) {
}); });
`; `;
} }
const isAccessor = getId || setId;
if (getId || setId) { if (isAccessor) {
privateNamesMap.set(prop.node.key.id.name, { privateNamesMap.set(prop.node.key.id.name, {
...privateName, ...privateName,
initAdded: true, initAdded: true,
}); });
if (getId && setId) {
return template.statement.ast` return template.statement.ast`
Object.defineProperty(${ref}, ${id}, { Object.defineProperty(${ref}, ${id}, {
// configurable is false by default // configurable is false by default
// enumerable is false by default // enumerable is false by default
// writable is false by default // writable is false by default
get: ${getId.name}, get: ${getId ? getId.name : prop.scope.buildUndefinedNode()},
set: ${setId.name} set: ${setId ? setId.name : prop.scope.buildUndefinedNode()}
}); });
`; `;
} else if (getId && !setId) {
return template.statement.ast`
Object.defineProperty(${ref}, ${id}, {
// configurable is false by default
// enumerable is false by default
// writable is false by default
get: ${getId.name}
});
`;
} else if (!getId && setId) {
return template.statement.ast`
Object.defineProperty(${ref}, ${id}, {
// configurable is false by default
// enumerable is false by default
// writable is false by default
set: ${setId.name}
});
`;
}
} }
} }
function buildPrivateInstanceMethodInitSpec(ref, prop, privateNamesMap) { function buildPrivateInstanceMethodInitSpec(ref, prop, privateNamesMap) {
const privateName = privateNamesMap.get(prop.node.key.id.name); const privateName = privateNamesMap.get(prop.node.key.id.name);
const { id, getId, setId, initAdded } = privateName; const { id, getId, setId, initAdded } = privateName;
if (initAdded) return; if (initAdded) return;
if (getId || setId) { const isAccessor = getId || setId;
if (isAccessor) {
privateNamesMap.set(prop.node.key.id.name, { privateNamesMap.set(prop.node.key.id.name, {
...privateName, ...privateName,
initAdded: true, initAdded: true,
}); });
if (getId && setId) {
return template.statement.ast` return template.statement.ast`
${id}.set(${ref}, { ${id}.set(${ref}, {
get: ${getId.name}, get: ${getId ? getId.name : prop.scope.buildUndefinedNode()},
set: ${setId.name} set: ${setId ? setId.name : prop.scope.buildUndefinedNode()}
}); });
`; `;
} else if (getId && !setId) {
return template.statement.ast`
${id}.set(${ref}, {
get: ${getId.name}
});
`;
} else if (!getId && setId) {
return template.statement.ast`
${id}.set(${ref}, {
set: ${setId.name}
});
`;
}
} }
return template.statement.ast`${id}.add(${ref})`; return template.statement.ast`${id}.add(${ref})`;
} }
@ -429,7 +424,29 @@ function buildPublicFieldInitSpec(ref, prop, state) {
} }
function buildPrivateStaticMethodInitLoose(ref, prop, state, privateNamesMap) { function buildPrivateStaticMethodInitLoose(ref, prop, state, privateNamesMap) {
const { id, methodId } = privateNamesMap.get(prop.node.key.id.name); const privateName = privateNamesMap.get(prop.node.key.id.name);
const { id, methodId, getId, setId, initAdded } = privateName;
if (initAdded) return;
const isAccessor = getId || setId;
if (isAccessor) {
privateNamesMap.set(prop.node.key.id.name, {
...privateName,
initAdded: true,
});
return template.statement.ast`
Object.defineProperty(${ref}, ${id}, {
// configurable is false by default
// enumerable is false by default
// writable is false by default
get: ${getId ? getId.name : prop.scope.buildUndefinedNode()},
set: ${setId ? setId.name : prop.scope.buildUndefinedNode()}
})
`;
}
return template.statement.ast` return template.statement.ast`
Object.defineProperty(${ref}, ${id}, { Object.defineProperty(${ref}, ${id}, {
// configurable is false by default // configurable is false by default
@ -615,14 +632,14 @@ export function buildFieldsInitNodes(
case isStatic && isPrivate && isMethod && !loose: case isStatic && isPrivate && isMethod && !loose:
needsClassRef = true; needsClassRef = true;
staticNodes.push( staticNodes.push(
buildPrivateStaticFieldInitSpec(prop, privateNamesMap),
);
staticNodes.unshift(
buildPrivateMethodDeclaration(prop, privateNamesMap, loose), buildPrivateMethodDeclaration(prop, privateNamesMap, loose),
); );
break; break;
case isStatic && isPrivate && isMethod && loose: case isStatic && isPrivate && isMethod && loose:
needsClassRef = true; needsClassRef = true;
staticNodes.push(
buildPrivateMethodDeclaration(prop, privateNamesMap, loose),
);
staticNodes.push( staticNodes.push(
buildPrivateStaticMethodInitLoose( buildPrivateStaticMethodInitLoose(
t.cloneNode(ref), t.cloneNode(ref),
@ -631,6 +648,9 @@ export function buildFieldsInitNodes(
privateNamesMap, privateNamesMap,
), ),
); );
staticNodes.unshift(
buildPrivateMethodDeclaration(prop, privateNamesMap, loose),
);
break; break;
case isInstance && isPublic && isField && loose: case isInstance && isPublic && isField && loose:
instanceNodes.push(buildPublicFieldInitLoose(t.thisExpression(), prop)); instanceNodes.push(buildPublicFieldInitLoose(t.thisExpression(), prop));
@ -646,7 +666,7 @@ export function buildFieldsInitNodes(
} }
return { return {
staticNodes, staticNodes: staticNodes.filter(Boolean),
instanceNodes: instanceNodes.filter(Boolean), instanceNodes: instanceNodes.filter(Boolean),
wrapClass(path) { wrapClass(path) {
for (const prop of props) { for (const prop of props) {

View File

@ -1177,6 +1177,9 @@ helpers.classStaticPrivateFieldSpecGet = helper("7.0.2")`
if (receiver !== classConstructor) { if (receiver !== classConstructor) {
throw new TypeError("Private static access of wrong provenance"); throw new TypeError("Private static access of wrong provenance");
} }
if (descriptor.get) {
return descriptor.get.call(receiver);
}
return descriptor.value; return descriptor.value;
} }
`; `;
@ -1186,6 +1189,9 @@ helpers.classStaticPrivateFieldSpecSet = helper("7.0.2")`
if (receiver !== classConstructor) { if (receiver !== classConstructor) {
throw new TypeError("Private static access of wrong provenance"); throw new TypeError("Private static access of wrong provenance");
} }
if (descriptor.set) {
descriptor.set.call(receiver, value);
} else {
if (!descriptor.writable) { if (!descriptor.writable) {
// This should only throw in strict mode, but class bodies are // This should only throw in strict mode, but class bodies are
// always strict and private fields can only be used inside // always strict and private fields can only be used inside
@ -1193,6 +1199,8 @@ helpers.classStaticPrivateFieldSpecSet = helper("7.0.2")`
throw new TypeError("attempted to set read only private field"); throw new TypeError("attempted to set read only private field");
} }
descriptor.value = value; descriptor.value = value;
}
return value; return value;
} }
`; `;

View File

@ -1,6 +1,7 @@
class Cl { class Cl {
constructor() { constructor() {
Object.defineProperty(this, _privateFieldValue, { Object.defineProperty(this, _privateFieldValue, {
get: void 0,
set: _set_privateFieldValue set: _set_privateFieldValue
}); });
Object.defineProperty(this, _privateField, { Object.defineProperty(this, _privateField, {

View File

@ -1,7 +1,8 @@
class Cl { class Cl {
constructor() { constructor() {
Object.defineProperty(this, _privateFieldValue, { Object.defineProperty(this, _privateFieldValue, {
get: _get_privateFieldValue get: _get_privateFieldValue,
set: void 0
}); });
Object.defineProperty(this, _privateField, { Object.defineProperty(this, _privateField, {
writable: true, writable: true,

View File

@ -1,6 +1,7 @@
class Cl { class Cl {
constructor() { constructor() {
_privateFieldValue.set(this, { _privateFieldValue.set(this, {
get: void 0,
set: _set_privateFieldValue set: _set_privateFieldValue
}); });

View File

@ -1,7 +1,8 @@
class Cl { class Cl {
constructor() { constructor() {
_privateFieldValue.set(this, { _privateFieldValue.set(this, {
get: _get_privateFieldValue get: _get_privateFieldValue,
set: void 0
}); });
_privateField.set(this, { _privateField.set(this, {

View File

@ -20,6 +20,10 @@ var _getA = babelHelpers.classPrivateFieldLooseKey("getA");
var _getB = babelHelpers.classPrivateFieldLooseKey("getB"); var _getB = babelHelpers.classPrivateFieldLooseKey("getB");
var _getB2 = function _getB2() {
return this.b;
};
var _getA2 = function _getA2() { var _getA2 = function _getA2() {
return A.a; return A.a;
}; };
@ -27,11 +31,6 @@ var _getA2 = function _getA2() {
Object.defineProperty(B, _getA, { Object.defineProperty(B, _getA, {
value: _getA2 value: _getA2
}); });
var _getB2 = function _getB2() {
return this.b;
};
Object.defineProperty(B, _getB, { Object.defineProperty(B, _getB, {
value: _getB2 value: _getB2
}); });

View File

@ -16,12 +16,12 @@ class B extends A {
} }
var _getA = function _getA() {
return babelHelpers.get(babelHelpers.getPrototypeOf(B), "a", this);
};
var _getB = function _getB() { var _getB = function _getB() {
return this.b; return this.b;
}; };
var _getA = function _getA() {
return babelHelpers.get(babelHelpers.getPrototypeOf(B), "a", this);
};
var [getA, getB] = B.extract(); var [getA, getB] = B.extract();

View File

@ -0,0 +1,23 @@
class Cl {
static #PRIVATE_STATIC_FIELD = "top secret string";
static get #privateStaticFieldValue() {
return Cl.#PRIVATE_STATIC_FIELD;
}
static set #privateStaticFieldValue(newValue) {
Cl.#PRIVATE_STATIC_FIELD = `Updated: ${newValue}`;
}
static getValue() {
return Cl.#privateStaticFieldValue;
}
static setValue() {
Cl.#privateStaticFieldValue = "dank";
}
}
expect(Cl.getValue()).toEqual("top secret string");
Cl.setValue();
expect(Cl.getValue()).toEqual("Updated: dank");

View File

@ -0,0 +1,19 @@
class Cl {
static #PRIVATE_STATIC_FIELD = "top secret string";
static get #privateStaticFieldValue() {
return Cl.#PRIVATE_STATIC_FIELD;
}
static set #privateStaticFieldValue(newValue) {
Cl.#PRIVATE_STATIC_FIELD = `Updated: ${newValue}`;
}
static getValue() {
return Cl.#privateStaticFieldValue;
}
static setValue() {
Cl.#privateStaticFieldValue = "dank";
}
}

View File

@ -0,0 +1,31 @@
class Cl {
static getValue() {
return babelHelpers.classPrivateFieldLooseBase(Cl, _privateStaticFieldValue)[_privateStaticFieldValue];
}
static setValue() {
babelHelpers.classPrivateFieldLooseBase(Cl, _privateStaticFieldValue)[_privateStaticFieldValue] = "dank";
}
}
var _PRIVATE_STATIC_FIELD = babelHelpers.classPrivateFieldLooseKey("PRIVATE_STATIC_FIELD");
var _privateStaticFieldValue = babelHelpers.classPrivateFieldLooseKey("privateStaticFieldValue");
var _set_privateStaticFieldValue = function (newValue) {
babelHelpers.classPrivateFieldLooseBase(Cl, _PRIVATE_STATIC_FIELD)[_PRIVATE_STATIC_FIELD] = `Updated: ${newValue}`;
};
var _get_privateStaticFieldValue = function () {
return babelHelpers.classPrivateFieldLooseBase(Cl, _PRIVATE_STATIC_FIELD)[_PRIVATE_STATIC_FIELD];
};
Object.defineProperty(Cl, _PRIVATE_STATIC_FIELD, {
writable: true,
value: "top secret string"
});
Object.defineProperty(Cl, _privateStaticFieldValue, {
get: _get_privateStaticFieldValue,
set: _set_privateStaticFieldValue
});

View File

@ -0,0 +1,13 @@
class Cl {
static #PRIVATE_STATIC_FIELD = 0;
static set #privateStaticFieldValue(newValue) {
Cl.#PRIVATE_STATIC_FIELD = newValue;
}
static getPrivateStaticFieldValue() {
return Cl.#privateStaticFieldValue;
}
}
expect(Cl.getPrivateStaticFieldValue()).toBeUndefined();

View File

@ -0,0 +1,11 @@
class Cl {
static #PRIVATE_STATIC_FIELD = 0;
static set #privateStaticFieldValue(newValue) {
Cl.#PRIVATE_STATIC_FIELD = newValue;
}
static getPrivateStaticFieldValue() {
return Cl.#privateStaticFieldValue;
}
}

View File

@ -0,0 +1,23 @@
class Cl {
static getPrivateStaticFieldValue() {
return babelHelpers.classPrivateFieldLooseBase(Cl, _privateStaticFieldValue)[_privateStaticFieldValue];
}
}
var _PRIVATE_STATIC_FIELD = babelHelpers.classPrivateFieldLooseKey("PRIVATE_STATIC_FIELD");
var _privateStaticFieldValue = babelHelpers.classPrivateFieldLooseKey("privateStaticFieldValue");
var _set_privateStaticFieldValue = function (newValue) {
babelHelpers.classPrivateFieldLooseBase(Cl, _PRIVATE_STATIC_FIELD)[_PRIVATE_STATIC_FIELD] = newValue;
};
Object.defineProperty(Cl, _PRIVATE_STATIC_FIELD, {
writable: true,
value: 0
});
Object.defineProperty(Cl, _privateStaticFieldValue, {
get: void 0,
set: _set_privateStaticFieldValue
});

View File

@ -0,0 +1,14 @@
{
"plugins": [
[
"external-helpers",
{
"helperVersion": "7.1000.0"
}
],
["proposal-private-methods", { "loose": true }],
["proposal-class-properties", { "loose": true }],
"transform-block-scoping",
"syntax-class-properties"
]
}

View File

@ -0,0 +1,13 @@
class Cl {
static #PRIVATE_STATIC_FIELD = 0;
static get #privateStaticFieldValue() {
return Cl.#PRIVATE_STATIC_FIELD;
}
static setPrivateStaticFieldValue() {
Cl.#privateStaticFieldValue = 1;
}
}
expect(() => Cl.setPrivateStaticFieldValue()).toThrow(TypeError);

View File

@ -0,0 +1,11 @@
class Cl {
static #PRIVATE_STATIC_FIELD = 0;
static get #privateStaticFieldValue() {
return Cl.#PRIVATE_STATIC_FIELD;
}
static setPrivateStaticFieldValue() {
Cl.#privateStaticFieldValue = 1;
}
}

View File

@ -0,0 +1,23 @@
class Cl {
static setPrivateStaticFieldValue() {
babelHelpers.classPrivateFieldLooseBase(Cl, _privateStaticFieldValue)[_privateStaticFieldValue] = 1;
}
}
var _PRIVATE_STATIC_FIELD = babelHelpers.classPrivateFieldLooseKey("PRIVATE_STATIC_FIELD");
var _privateStaticFieldValue = babelHelpers.classPrivateFieldLooseKey("privateStaticFieldValue");
var _get_privateStaticFieldValue = function () {
return babelHelpers.classPrivateFieldLooseBase(Cl, _PRIVATE_STATIC_FIELD)[_PRIVATE_STATIC_FIELD];
};
Object.defineProperty(Cl, _PRIVATE_STATIC_FIELD, {
writable: true,
value: 0
});
Object.defineProperty(Cl, _privateStaticFieldValue, {
get: _get_privateStaticFieldValue,
set: void 0
});

View File

@ -0,0 +1,46 @@
class Cl {
static #privateField = "top secret string";
static publicField = "not secret string";
static get #privateFieldValue() {
return Cl.#privateField;
}
static set #privateFieldValue(newValue) {
Cl.#privateField = newValue;
}
static publicGetPrivateField() {
return Cl.#privateFieldValue;
}
static publicSetPrivateField(newValue) {
Cl.#privateFieldValue = newValue;
}
static get publicFieldValue() {
return Cl.publicField;
}
static set publicFieldValue(newValue) {
Cl.publicField = newValue;
}
static testUpdates() {
Cl.#privateField = 0;
Cl.publicField = 0;
Cl.#privateFieldValue = Cl.#privateFieldValue++;
Cl.publicFieldValue = Cl.publicFieldValue++;
expect(Cl.#privateField).toEqual(Cl.publicField);
++Cl.#privateFieldValue;
++Cl.publicFieldValue;
expect(Cl.#privateField).toEqual(Cl.publicField);
Cl.#privateFieldValue += 1;
Cl.publicFieldValue += 1;
expect(Cl.#privateField).toEqual(Cl.publicField);
}
}
Cl.testUpdates();

View File

@ -0,0 +1,44 @@
class Cl {
static #privateField = "top secret string";
static publicField = "not secret string";
static get #privateFieldValue() {
return Cl.#privateField;
}
static set #privateFieldValue(newValue) {
Cl.#privateField = newValue;
}
static publicGetPrivateField() {
return Cl.#privateFieldValue;
}
static publicSetPrivateField(newValue) {
Cl.#privateFieldValue = newValue;
}
static get publicFieldValue() {
return Cl.publicField;
}
static set publicFieldValue(newValue) {
Cl.publicField = newValue;
}
static testUpdates() {
Cl.#privateField = 0;
Cl.publicField = 0;
Cl.#privateFieldValue = Cl.#privateFieldValue++;
Cl.publicFieldValue = Cl.publicFieldValue++;
++Cl.#privateFieldValue;
++Cl.publicFieldValue;
Cl.#privateFieldValue += 1;
Cl.publicFieldValue += 1;
Cl.#privateFieldValue = -(Cl.#privateFieldValue ** Cl.#privateFieldValue);
Cl.publicFieldValue = -(Cl.publicFieldValue ** Cl.publicFieldValue);
}
}

View File

@ -0,0 +1,53 @@
class Cl {
static publicGetPrivateField() {
return babelHelpers.classPrivateFieldLooseBase(Cl, _privateFieldValue)[_privateFieldValue];
}
static publicSetPrivateField(newValue) {
babelHelpers.classPrivateFieldLooseBase(Cl, _privateFieldValue)[_privateFieldValue] = newValue;
}
static get publicFieldValue() {
return Cl.publicField;
}
static set publicFieldValue(newValue) {
Cl.publicField = newValue;
}
static testUpdates() {
babelHelpers.classPrivateFieldLooseBase(Cl, _privateField)[_privateField] = 0;
Cl.publicField = 0;
babelHelpers.classPrivateFieldLooseBase(Cl, _privateFieldValue)[_privateFieldValue] = babelHelpers.classPrivateFieldLooseBase(Cl, _privateFieldValue)[_privateFieldValue]++;
Cl.publicFieldValue = Cl.publicFieldValue++;
++babelHelpers.classPrivateFieldLooseBase(Cl, _privateFieldValue)[_privateFieldValue];
++Cl.publicFieldValue;
babelHelpers.classPrivateFieldLooseBase(Cl, _privateFieldValue)[_privateFieldValue] += 1;
Cl.publicFieldValue += 1;
babelHelpers.classPrivateFieldLooseBase(Cl, _privateFieldValue)[_privateFieldValue] = -(babelHelpers.classPrivateFieldLooseBase(Cl, _privateFieldValue)[_privateFieldValue] ** babelHelpers.classPrivateFieldLooseBase(Cl, _privateFieldValue)[_privateFieldValue]);
Cl.publicFieldValue = -(Cl.publicFieldValue ** Cl.publicFieldValue);
}
}
var _privateField = babelHelpers.classPrivateFieldLooseKey("privateField");
var _privateFieldValue = babelHelpers.classPrivateFieldLooseKey("privateFieldValue");
var _set_privateFieldValue = function (newValue) {
babelHelpers.classPrivateFieldLooseBase(Cl, _privateField)[_privateField] = newValue;
};
var _get_privateFieldValue = function () {
return babelHelpers.classPrivateFieldLooseBase(Cl, _privateField)[_privateField];
};
Object.defineProperty(Cl, _privateField, {
writable: true,
value: "top secret string"
});
Cl.publicField = "not secret string";
Object.defineProperty(Cl, _privateFieldValue, {
get: _get_privateFieldValue,
set: _set_privateFieldValue
});

View File

@ -0,0 +1,23 @@
class Cl {
static #PRIVATE_STATIC_FIELD = "top secret string";
static get #privateStaticFieldValue() {
return Cl.#PRIVATE_STATIC_FIELD;
}
static set #privateStaticFieldValue(newValue) {
Cl.#PRIVATE_STATIC_FIELD = `Updated: ${newValue}`;
}
static getValue() {
return Cl.#privateStaticFieldValue;
}
static setValue() {
Cl.#privateStaticFieldValue = "dank";
}
}
expect(Cl.getValue()).toEqual("top secret string");
Cl.setValue();
expect(Cl.getValue()).toEqual("Updated: dank");

View File

@ -0,0 +1,19 @@
class Cl {
static #PRIVATE_STATIC_FIELD = "top secret string";
static get #privateStaticFieldValue() {
return Cl.#PRIVATE_STATIC_FIELD;
}
static set #privateStaticFieldValue(newValue) {
Cl.#PRIVATE_STATIC_FIELD = `Updated: ${newValue}`;
}
static getValue() {
return Cl.#privateStaticFieldValue;
}
static setValue() {
Cl.#privateStaticFieldValue = "dank";
}
}

View File

@ -0,0 +1,27 @@
class Cl {
static getValue() {
return babelHelpers.classStaticPrivateFieldSpecGet(Cl, Cl, _privateStaticFieldValue);
}
static setValue() {
babelHelpers.classStaticPrivateFieldSpecSet(Cl, Cl, _privateStaticFieldValue, "dank");
}
}
var _set_privateStaticFieldValue = function (newValue) {
babelHelpers.classStaticPrivateFieldSpecSet(Cl, Cl, _PRIVATE_STATIC_FIELD, `Updated: ${newValue}`);
};
var _get_privateStaticFieldValue = function () {
return babelHelpers.classStaticPrivateFieldSpecGet(Cl, Cl, _PRIVATE_STATIC_FIELD);
};
var _PRIVATE_STATIC_FIELD = {
writable: true,
value: "top secret string"
};
var _privateStaticFieldValue = {
get: _get_privateStaticFieldValue,
set: _set_privateStaticFieldValue
};

View File

@ -0,0 +1,13 @@
class Cl {
static #PRIVATE_STATIC_FIELD = 0;
static set #privateStaticFieldValue(newValue) {
Cl.#PRIVATE_STATIC_FIELD = newValue;
}
static getPrivateStaticFieldValue() {
return Cl.#privateStaticFieldValue;
}
}
expect(Cl.getPrivateStaticFieldValue()).toBeUndefined();

View File

@ -0,0 +1,11 @@
class Cl {
static #PRIVATE_STATIC_FIELD = 0;
static set #privateStaticFieldValue(newValue) {
Cl.#PRIVATE_STATIC_FIELD = newValue;
}
static getPrivateStaticFieldValue() {
return Cl.#privateStaticFieldValue;
}
}

View File

@ -0,0 +1,19 @@
class Cl {
static getPrivateStaticFieldValue() {
return babelHelpers.classStaticPrivateFieldSpecGet(Cl, Cl, _privateStaticFieldValue);
}
}
var _set_privateStaticFieldValue = function (newValue) {
babelHelpers.classStaticPrivateFieldSpecSet(Cl, Cl, _PRIVATE_STATIC_FIELD, newValue);
};
var _PRIVATE_STATIC_FIELD = {
writable: true,
value: 0
};
var _privateStaticFieldValue = {
get: void 0,
set: _set_privateStaticFieldValue
};

View File

@ -0,0 +1,14 @@
{
"plugins": [
[
"external-helpers",
{
"helperVersion": "7.1000.0"
}
],
"proposal-private-methods",
"proposal-class-properties",
"transform-block-scoping",
"syntax-class-properties"
]
}

View File

@ -0,0 +1,13 @@
class Cl {
static #PRIVATE_STATIC_FIELD = 0;
static get #privateStaticFieldValue() {
return Cl.#PRIVATE_STATIC_FIELD;
}
static setPrivateStaticFieldValue() {
Cl.#privateStaticFieldValue = 1;
}
}
expect(() => Cl.setPrivateStaticFieldValue()).toThrow(TypeError);

View File

@ -0,0 +1,11 @@
class Cl {
static #PRIVATE_STATIC_FIELD = 0;
static get #privateStaticFieldValue() {
return Cl.#PRIVATE_STATIC_FIELD;
}
static setPrivateStaticFieldValue() {
Cl.#privateStaticFieldValue = 1;
}
}

View File

@ -0,0 +1,19 @@
class Cl {
static setPrivateStaticFieldValue() {
babelHelpers.classStaticPrivateFieldSpecSet(Cl, Cl, _privateStaticFieldValue, 1);
}
}
var _get_privateStaticFieldValue = function () {
return babelHelpers.classStaticPrivateFieldSpecGet(Cl, Cl, _PRIVATE_STATIC_FIELD);
};
var _PRIVATE_STATIC_FIELD = {
writable: true,
value: 0
};
var _privateStaticFieldValue = {
get: _get_privateStaticFieldValue,
set: void 0
};

View File

@ -0,0 +1,46 @@
class Cl {
static #privateField = "top secret string";
static publicField = "not secret string";
static get #privateFieldValue() {
return Cl.#privateField;
}
static set #privateFieldValue(newValue) {
Cl.#privateField = newValue;
}
static publicGetPrivateField() {
return Cl.#privateFieldValue;
}
static publicSetPrivateField(newValue) {
Cl.#privateFieldValue = newValue;
}
static get publicFieldValue() {
return Cl.publicField;
}
static set publicFieldValue(newValue) {
Cl.publicField = newValue;
}
static testUpdates() {
Cl.#privateField = 0;
Cl.publicField = 0;
Cl.#privateFieldValue = Cl.#privateFieldValue++;
Cl.publicFieldValue = Cl.publicFieldValue++;
expect(Cl.#privateField).toEqual(Cl.publicField);
++Cl.#privateFieldValue;
++Cl.publicFieldValue;
expect(Cl.#privateField).toEqual(Cl.publicField);
Cl.#privateFieldValue += 1;
Cl.publicFieldValue += 1;
expect(Cl.#privateField).toEqual(Cl.publicField);
}
}
Cl.testUpdates();

View File

@ -0,0 +1,44 @@
class Cl {
static #privateField = "top secret string";
static publicField = "not secret string";
static get #privateFieldValue() {
return Cl.#privateField;
}
static set #privateFieldValue(newValue) {
Cl.#privateField = newValue;
}
static publicGetPrivateField() {
return Cl.#privateFieldValue;
}
static publicSetPrivateField(newValue) {
Cl.#privateFieldValue = newValue;
}
static get publicFieldValue() {
return Cl.publicField;
}
static set publicFieldValue(newValue) {
Cl.publicField = newValue;
}
static testUpdates() {
Cl.#privateField = 0;
Cl.publicField = 0;
Cl.#privateFieldValue = Cl.#privateFieldValue++;
Cl.publicFieldValue = Cl.publicFieldValue++;
++Cl.#privateFieldValue;
++Cl.publicFieldValue;
Cl.#privateFieldValue += 1;
Cl.publicFieldValue += 1;
Cl.#privateFieldValue = -(Cl.#privateFieldValue ** Cl.#privateFieldValue);
Cl.publicFieldValue = -(Cl.publicFieldValue ** Cl.publicFieldValue);
}
}

View File

@ -0,0 +1,51 @@
class Cl {
static publicGetPrivateField() {
return babelHelpers.classStaticPrivateFieldSpecGet(Cl, Cl, _privateFieldValue);
}
static publicSetPrivateField(newValue) {
babelHelpers.classStaticPrivateFieldSpecSet(Cl, Cl, _privateFieldValue, newValue);
}
static get publicFieldValue() {
return Cl.publicField;
}
static set publicFieldValue(newValue) {
Cl.publicField = newValue;
}
static testUpdates() {
var _Cl$privateFieldValue, _Cl$privateFieldValue2;
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));
Cl.publicFieldValue = Cl.publicFieldValue++;
babelHelpers.classStaticPrivateFieldSpecSet(Cl, Cl, _privateFieldValue, +babelHelpers.classStaticPrivateFieldSpecGet(Cl, Cl, _privateFieldValue) + 1);
++Cl.publicFieldValue;
babelHelpers.classStaticPrivateFieldSpecSet(Cl, Cl, _privateFieldValue, babelHelpers.classStaticPrivateFieldSpecGet(Cl, Cl, _privateFieldValue) + 1);
Cl.publicFieldValue += 1;
babelHelpers.classStaticPrivateFieldSpecSet(Cl, Cl, _privateFieldValue, -(babelHelpers.classStaticPrivateFieldSpecGet(Cl, Cl, _privateFieldValue) ** babelHelpers.classStaticPrivateFieldSpecGet(Cl, Cl, _privateFieldValue)));
Cl.publicFieldValue = -(Cl.publicFieldValue ** Cl.publicFieldValue);
}
}
var _set_privateFieldValue = function (newValue) {
babelHelpers.classStaticPrivateFieldSpecSet(Cl, Cl, _privateField, newValue);
};
var _get_privateFieldValue = function () {
return babelHelpers.classStaticPrivateFieldSpecGet(Cl, Cl, _privateField);
};
var _privateField = {
writable: true,
value: "top secret string"
};
babelHelpers.defineProperty(Cl, "publicField", "not secret string");
var _privateFieldValue = {
get: _get_privateFieldValue,
set: _set_privateFieldValue
};