Private Static Fields Features: Stage 3 (#8205)

* Private Static Class Fields Implementation

* Redo testing without class transform for static private

* Add a call() test for private static

* Use Object.defineProperty in loose mode
This commit is contained in:
Robin Ricard 2018-09-01 00:42:18 -04:00 committed by Justin Ridgewell
parent eda804da11
commit fb66fa6f90
59 changed files with 957 additions and 166 deletions

View File

@ -1053,3 +1053,35 @@ helpers.classPrivateFieldSet = helper("7.0.0-beta.0")`
return value;
}
`;
helpers.classStaticPrivateFieldLooseBase = helper("7.0.0-beta.0")`
export default function _classStaticPrivateFieldLooseBase(receiver, classConstructor) {
if (receiver !== classConstructor) {
throw new TypeError("Private static access of wrong provenance");
}
return classConstructor;
}
`;
helpers.classStaticPrivateFieldSpecGet = helper("7.0.0-beta.0")`
export default function _classStaticPrivateFieldSpecGet(
receiver, classConstructor, privateClass, privateId
) {
if (receiver !== classConstructor) {
throw new TypeError("Private static access of wrong provenance");
}
return privateClass[privateId];
}
`;
helpers.classStaticPrivateFieldSpecSet = helper("7.0.0-beta.0")`
export default function _classStaticPrivateFieldSpecSet(
receiver, classConstructor, privateClass, privateId, value
) {
if (receiver !== classConstructor) {
throw new TypeError("Private static access of wrong provenance");
}
privateClass[privateId] = value;
return value;
}
`;

View File

@ -160,6 +160,60 @@ export default declare((api, options) => {
},
};
const staticPrivatePropertyHandlerSpec = {
...privateNameHandlerSpec,
get(member) {
const { file, name, privateClassId, classRef } = this;
return t.callExpression(
file.addHelper("classStaticPrivateFieldSpecGet"),
[
this.receiver(member),
classRef,
privateClassId,
t.stringLiteral(name),
],
);
},
set(member, value) {
const { file, name, privateClassId, classRef } = this;
return t.callExpression(
file.addHelper("classStaticPrivateFieldSpecSet"),
[
this.receiver(member),
classRef,
privateClassId,
t.stringLiteral(name),
value,
],
);
},
call(member, args) {
// The first access (the get) should do the memo assignment.
this.memoise(member, 1);
return optimiseCall(this.get(member), this.receiver(member), args);
},
};
const staticPrivatePropertyHandlerLoose = {
handle(member) {
const { file, privateId, classRef } = this;
member.replaceWith(
template.expression`BASE(RECEIVER, CLASS).PRIVATE_ID`({
BASE: file.addHelper("classStaticPrivateFieldLooseBase"),
RECEIVER: member.node.object,
CLASS: classRef,
PRIVATE_ID: privateId,
}),
);
},
};
function buildClassPropertySpec(ref, path, state) {
const { scope } = path;
const { key, value, computed } = path.node;
@ -255,6 +309,80 @@ export default declare((api, options) => {
});
}
function buildClassStaticPrivatePropertySpec(
ref,
path,
state,
privateClassId,
) {
const { scope, parentPath } = path;
const { key, value } = path.node;
const { name } = key.id;
const staticNodesToAdd = [];
if (!privateClassId) {
// Create a private static "host" object if it does not exist
privateClassId = path.scope.generateUidIdentifier(ref.name + "Statics");
staticNodesToAdd.push(
template.statement`const PRIVATE_CLASS_ID = Object.create(null);`({
PRIVATE_CLASS_ID: privateClassId,
}),
);
}
memberExpressionToFunctions(parentPath, privateNameVisitor, {
name,
privateClassId,
classRef: ref,
file: state,
...staticPrivatePropertyHandlerSpec,
});
staticNodesToAdd.push(
t.expressionStatement(
t.callExpression(state.addHelper("defineProperty"), [
privateClassId,
t.stringLiteral(name),
value || scope.buildUndefinedNode(),
]),
),
);
return [staticNodesToAdd, privateClassId];
}
function buildClassStaticPrivatePropertyLoose(ref, path, state) {
const { scope, parentPath } = path;
const { key, value } = path.node;
const { name } = key.id;
const privateId = scope.generateUidIdentifier(name);
parentPath.traverse(privateNameVisitor, {
name,
privateId,
classRef: ref,
file: state,
...staticPrivatePropertyHandlerLoose,
});
const staticNodesToAdd = [
template.statement`
Object.defineProperty(OBJ, KEY, {
value: VALUE,
enumerable: false,
configurable: false,
writable: true
});
`({
OBJ: ref,
KEY: t.stringLiteral(privateId.name),
VALUE: value || scope.buildUndefinedNode(),
}),
];
return [staticNodesToAdd];
}
const buildClassProperty = loose
? buildClassPropertyLoose
: buildClassPropertySpec;
@ -263,6 +391,10 @@ export default declare((api, options) => {
? buildClassPrivatePropertyLoose
: buildClassPrivatePropertySpec;
const buildClassStaticPrivateProperty = loose
? buildClassStaticPrivatePropertyLoose
: buildClassStaticPrivatePropertySpec;
return {
inherits: syntaxClassProperties,
@ -288,17 +420,11 @@ export default declare((api, options) => {
if (path.isClassPrivateProperty()) {
const {
static: isStatic,
key: {
id: { name },
},
} = path.node;
if (isStatic) {
throw path.buildCodeFrameError(
"Static class fields are not spec'ed yet.",
);
}
if (privateNames.has(name)) {
throw path.buildCodeFrameError("Duplicate private field");
}
@ -354,7 +480,7 @@ export default declare((api, options) => {
const privateMaps = [];
const privateMapInits = [];
for (const prop of props) {
if (prop.isPrivate()) {
if (prop.isPrivate() && !prop.node.static) {
const inits = [];
privateMapInits.push(inits);
@ -363,11 +489,27 @@ export default declare((api, options) => {
);
}
}
let p = 0;
let privateClassId;
for (const prop of props) {
if (prop.node.static) {
staticNodes.push(buildClassProperty(t.cloneNode(ref), prop, state));
if (prop.isPrivate()) {
let staticNodesToAdd;
[
staticNodesToAdd,
privateClassId,
] = buildClassStaticPrivateProperty(
t.cloneNode(ref),
prop,
state,
privateClassId,
);
staticNodes.push(...staticNodesToAdd);
} else {
staticNodes.push(
buildClassProperty(t.cloneNode(ref), prop, state),
);
}
} else if (prop.isPrivate()) {
instanceBody.push(privateMaps[p]());
staticNodes.push(...privateMapInits[p]);

View File

@ -1,3 +1,3 @@
{
"throws": "Static class fields are not spec'ed yet."
"plugins": ["external-helpers", ["proposal-class-properties", { "loose": true }], "transform-block-scoping", "syntax-class-properties"]
}

View File

@ -0,0 +1,32 @@
class Foo {
constructor() {
Object.defineProperty(this, _bar, {
writable: true,
value: "bar"
});
}
static test() {
return babelHelpers.classStaticPrivateFieldLooseBase(Foo, Foo)._foo;
}
test() {
return babelHelpers.classPrivateFieldLooseBase(this, _bar)[_bar];
}
}
Object.defineProperty(Foo, "_foo", {
value: "foo",
enumerable: false,
configurable: false,
writable: true
});
var _bar = babelHelpers.classPrivateFieldLooseKey("bar");
var f = new Foo();
expect("foo" in Foo).toBe(false);
expect("bar" in f).toBe(false);
expect(Foo.test()).toBe("foo");
expect(f.test()).toBe("bar");

View File

@ -1,3 +1,3 @@
{
"throws": "Static class fields are not spec'ed yet."
"plugins": ["external-helpers", ["proposal-class-properties", { "loose": true }], "transform-block-scoping", "syntax-class-properties"]
}

View File

@ -0,0 +1,18 @@
export default (param => {
var _class, _temp;
return _temp = _class = class App {
getParam() {
return param;
}
}, Object.defineProperty(_class, "_props", {
value: {
prop1: 'prop1',
prop2: 'prop2'
},
enumerable: false,
configurable: false,
writable: true
}), _temp;
});

View File

@ -1,3 +1,3 @@
{
"throws": "Static class fields are not spec'ed yet."
"plugins": ["external-helpers", ["proposal-class-properties", { "loose": true }], "transform-block-scoping", "syntax-class-properties"]
}

View File

@ -0,0 +1,51 @@
function classFactory() {
var _class, _temp, _foo;
return _temp = _class = class Foo {
constructor() {
Object.defineProperty(this, _foo, {
writable: true,
value: "foo"
});
}
instance() {
return babelHelpers.classPrivateFieldLooseBase(this, _foo)[_foo];
}
static() {
return babelHelpers.classStaticPrivateFieldLooseBase(Foo, _class)._bar;
}
static instance(inst) {
return babelHelpers.classPrivateFieldLooseBase(inst, _foo)[_foo];
}
static static() {
return babelHelpers.classStaticPrivateFieldLooseBase(Foo, _class)._bar;
}
}, _foo = babelHelpers.classPrivateFieldLooseKey("foo"), Object.defineProperty(_class, "_bar", {
value: "bar",
enumerable: false,
configurable: false,
writable: true
}), _temp;
}
var Foo1 = classFactory();
var Foo2 = classFactory();
var f1 = new Foo1();
var f2 = new Foo2();
expect(f1.instance()).toBe("foo");
expect(f1.static()).toBe("bar");
expect(f2.instance()).toBe("foo");
expect(f2.static()).toBe("bar");
expect(Foo1.instance(f1)).toBe("foo");
expect(Foo1.static()).toBe("bar");
expect(Foo2.instance(f2)).toBe("foo");
expect(Foo2.static()).toBe("bar");
assert.throws(() => f1.instance.call(f2));
assert.throws(() => f2.instance.call(f1));
assert.throws(() => Foo1.instance(f2));
assert.throws(() => Foo2.instance(f1));

View File

@ -0,0 +1,13 @@
class Foo {
static #foo = function(x) {
return x;
}
test(x) {
return Foo.#foo(x);
}
}
const f = new Foo;
const test = f.test();
expect(f.test("bar")).toBe("bar");

View File

@ -0,0 +1,10 @@
class Foo {
static #foo = function(x) {
return x;
}
test(x) {
return Foo.#foo(x);
}
}

View File

@ -0,0 +1,26 @@
var Foo =
/*#__PURE__*/
function () {
"use strict";
function Foo() {
babelHelpers.classCallCheck(this, Foo);
}
babelHelpers.createClass(Foo, [{
key: "test",
value: function test(x) {
return babelHelpers.classStaticPrivateFieldLooseBase(Foo, Foo)._foo(x);
}
}]);
return Foo;
}();
Object.defineProperty(Foo, "_foo", {
value: function (x) {
return x;
},
enumerable: false,
configurable: false,
writable: true
});

View File

@ -1,3 +1,3 @@
{
"throws": "Static class fields are not spec'ed yet."
"plugins": ["external-helpers", ["proposal-class-properties", { "loose": true }], "transform-block-scoping", "syntax-class-properties"]
}

View File

@ -0,0 +1,14 @@
export class MyClass {}
Object.defineProperty(MyClass, "_property", {
value: value,
enumerable: false,
configurable: false,
writable: true
});
export default class MyClass2 {}
Object.defineProperty(MyClass2, "_property2", {
value: value,
enumerable: false,
configurable: false,
writable: true
});

View File

@ -1,3 +1,3 @@
{
"throws": "Static class fields are not spec'ed yet."
"plugins": ["external-helpers", ["proposal-class-properties", { "loose": true }], "transform-block-scoping", "syntax-class-properties"]
}

View File

@ -0,0 +1,8 @@
var _class, _temp;
var Foo = (_temp = _class = class Foo {}, Object.defineProperty(_class, "_num", {
value: 0,
enumerable: false,
configurable: false,
writable: true
}), _temp);

View File

@ -0,0 +1,69 @@
class Base {
static #foo = 1;
static getThis() {
return this.#foo;
}
static updateThis(val) {
return (this.#foo = val);
}
static getClass() {
return Base.#foo;
}
static updateClass(val) {
return (Base.#foo = val);
}
}
class Sub1 extends Base {
static #foo = 2;
static update(val) {
return (this.#foo = val);
}
}
class Sub2 extends Base {}
expect(Base.getThis()).toBe(1);
expect(Base.getClass()).toBe(1);
expect(() => Sub1.getThis()).toThrow();
expect(Sub1.getClass()).toBe(1);
expect(() => Sub2.getThis()).toThrow();
expect(Sub2.getClass()).toBe(1);
expect(Sub1.update(3)).toBe(3);
expect(Base.getThis()).toBe(1);
expect(Base.getClass()).toBe(1);
expect(() => Sub1.getThis()).toThrow();
expect(Sub1.getClass()).toBe(1);
expect(() => Sub2.getThis()).toThrow();
expect(Sub2.getClass()).toBe(1);
expect(Base.updateThis(4)).toBe(4);
expect(Base.getThis()).toBe(4);
expect(Base.getClass()).toBe(4);
expect(() => Sub1.getThis()).toThrow();
expect(Sub1.getClass()).toBe(4);
expect(() => Sub2.getThis()).toThrow();
expect(Sub2.getClass()).toBe(4);
expect(Base.updateClass(5)).toBe(5);
expect(Base.getThis()).toBe(5);
expect(Base.getClass()).toBe(5);
expect(() => Sub1.getThis()).toThrow();
expect(Sub1.getClass()).toBe(5);
expect(() => Sub2.getThis()).toThrow();
expect(Sub2.getClass()).toBe(5);
expect(() => Sub2.updateThis(6)).toThrow();
expect(Sub2.updateClass(7)).toBe(7);
expect(Base.getThis()).toBe(7);
expect(Base.getClass()).toBe(7);
expect(() => Sub1.getThis()).toThrow();
expect(Sub1.getClass()).toBe(7);
expect(() => Sub2.getThis()).toThrow();
expect(Sub2.getClass()).toBe(7);

View File

@ -6,7 +6,7 @@ class Base {
}
static updateThis(val) {
return this.#foo = val;
return (this.#foo = val);
}
static getClass() {
@ -14,7 +14,7 @@ class Base {
}
static updateClass(val) {
return Base.#foo = val;
return (Base.#foo = val);
}
}
@ -22,49 +22,8 @@ class Sub1 extends Base {
static #foo = 2;
static update(val) {
return this.#foo = val;
return (this.#foo = val);
}
}
class Sub2 extends Base {
}
expect(Base.getThis()).toBe(1);
expect(Base.getClass()).toBe(1);
assert.throws(() => Sub1.getThis());
expect(Sub1.getClass()).toBe(1);
assert.throws(() => Sub2.getThis());
expect(Sub2.getClass()).toBe(1);
expect(Sub1.update(3)).toBe(3);
expect(Base.getThis()).toBe(1);
expect(Base.getClass()).toBe(1);
assert.throws(() => Sub1.getThis());
expect(Sub1.getClass()).toBe(1);
assert.throws(() => Sub2.getThis());
expect(Sub2.getClass()).toBe(1);
expect(Base.updateThis(4)).toBe(4);
expect(Base.getThis()).toBe(4);
expect(Base.getClass()).toBe(4);
assert.throws(() => Sub1.getThis());
expect(Sub1.getClass()).toBe(4);
assert.throws(() => Sub2.getThis());
expect(Sub2.getClass()).toBe(4);
expect(Base.updateClass(5)).toBe(5);
expect(Base.getThis()).toBe(5);
expect(Base.getClass()).toBe(5);
assert.throws(() => Sub1.getThis());
expect(Sub1.getClass()).toBe(5);
assert.throws(() => Sub2.getThis());
expect(Sub2.getClass()).toBe(5);
assert.throws(() => Sub2.updateThis(6));
expect(Sub2.updateClass(7)).toBe(7);
expect(Base.getThis()).toBe(7);
expect(Base.getClass()).toBe(7);
assert.throws(() => Sub1.getThis());
expect(Sub1.getClass()).toBe(7);
assert.throws(() => Sub2.getThis());
expect(Sub2.getClass()).toBe(7);
class Sub2 extends Base {}

View File

@ -1,3 +1,3 @@
{
"throws": "Static class fields are not spec'ed yet."
"plugins": ["external-helpers", ["proposal-class-properties", { "loose": true }], "transform-block-scoping", "syntax-class-properties"]
}

View File

@ -0,0 +1,41 @@
class Base {
static getThis() {
return babelHelpers.classStaticPrivateFieldLooseBase(this, Base)._foo;
}
static updateThis(val) {
return babelHelpers.classStaticPrivateFieldLooseBase(this, Base)._foo = val;
}
static getClass() {
return babelHelpers.classStaticPrivateFieldLooseBase(Base, Base)._foo;
}
static updateClass(val) {
return babelHelpers.classStaticPrivateFieldLooseBase(Base, Base)._foo = val;
}
}
Object.defineProperty(Base, "_foo", {
value: 1,
enumerable: false,
configurable: false,
writable: true
});
class Sub1 extends Base {
static update(val) {
return babelHelpers.classStaticPrivateFieldLooseBase(this, Sub1)._foo2 = val;
}
}
Object.defineProperty(Sub1, "_foo2", {
value: 2,
enumerable: false,
configurable: false,
writable: true
});
class Sub2 extends Base {}

View File

@ -0,0 +1,15 @@
class Foo {
static #bar;
static test() {
return Foo.#bar;
}
test() {
return Foo.#bar;
}
}
expect("bar" in Foo).toBe(false);
expect(Foo.test()).toBe(undefined);
expect(Foo.test()).toBe(undefined);

View File

@ -9,7 +9,3 @@ class Foo {
return Foo.#bar;
}
}
expect("bar" in Foo).toBe(false)
expect(Foo.test()).toBe(undefined)
expect(Foo.test()).toBe(undefined)

View File

@ -1,3 +1,3 @@
{
"throws": "Static class fields are not spec'ed yet."
"plugins": ["external-helpers", ["proposal-class-properties", { "loose": true }], "transform-block-scoping", "syntax-class-properties"]
}

View File

@ -0,0 +1,17 @@
class Foo {
static test() {
return babelHelpers.classStaticPrivateFieldLooseBase(Foo, Foo)._bar;
}
test() {
return babelHelpers.classStaticPrivateFieldLooseBase(Foo, Foo)._bar;
}
}
Object.defineProperty(Foo, "_bar", {
value: void 0,
enumerable: false,
configurable: false,
writable: true
});

View File

@ -0,0 +1,15 @@
class Foo {
static #bar = "foo";
static test() {
return Foo.#bar;
}
test() {
return Foo.#bar;
}
}
expect("bar" in Foo).toBe(false);
expect(Foo.test()).toBe("foo");
expect(Foo.test()).toBe("foo");

View File

@ -9,7 +9,3 @@ class Foo {
return Foo.#bar;
}
}
expect("bar" in Foo).toBe(false)
expect(Foo.test()).toBe("foo")
expect(Foo.test()).toBe("foo")

View File

@ -1,3 +1,3 @@
{
"throws": "Static class fields are not spec'ed yet."
"plugins": ["external-helpers", ["proposal-class-properties", { "loose": true }], "transform-block-scoping", "syntax-class-properties"]
}

View File

@ -0,0 +1,17 @@
class Foo {
static test() {
return babelHelpers.classStaticPrivateFieldLooseBase(Foo, Foo)._bar;
}
test() {
return babelHelpers.classStaticPrivateFieldLooseBase(Foo, Foo)._bar;
}
}
Object.defineProperty(Foo, "_bar", {
value: "foo",
enumerable: false,
configurable: false,
writable: true
});

View File

@ -0,0 +1,18 @@
class Foo {
static #foo = "foo";
#bar = "bar";
static test() {
return Foo.#foo;
}
test() {
return this.#bar;
}
}
const f = new Foo();
expect("foo" in Foo).toBe(false)
expect("bar" in f).toBe(false)
expect(Foo.test()).toBe("foo")
expect(f.test()).toBe("bar")

View File

@ -10,9 +10,3 @@ class Foo {
return this.#bar;
}
}
const f = new Foo();
expect("foo" in Foo).toBe(false)
expect("bar" in f).toBe(false)
expect(Foo.test()).toBe("foo")
expect(f.test()).toBe("bar")

View File

@ -1,3 +1,3 @@
{
"throws": "Static class fields are not spec'ed yet."
"plugins": ["external-helpers", "proposal-class-properties", "transform-block-scoping", "syntax-class-properties"]
}

View File

@ -0,0 +1,23 @@
class Foo {
constructor() {
_bar.set(this, {
writable: true,
value: "bar"
});
}
static test() {
return babelHelpers.classStaticPrivateFieldSpecGet(Foo, Foo, _FooStatics, "foo");
}
test() {
return babelHelpers.classPrivateFieldGet(this, _bar);
}
}
var _FooStatics = Object.create(null);
babelHelpers.defineProperty(_FooStatics, "foo", "foo");
var _bar = new WeakMap();

View File

@ -1,3 +1,3 @@
{
"throws": "Static class fields are not spec'ed yet."
"plugins": ["external-helpers", "proposal-class-properties", "transform-block-scoping", "syntax-class-properties"]
}

View File

@ -0,0 +1,20 @@
export default (param => {
var _class, _temp;
return function () {
_temp = _class = class App {
getParam() {
return param;
}
};
var _classStatics = Object.create(null);
babelHelpers.defineProperty(_classStatics, "props", {
prop1: 'prop1',
prop2: 'prop2'
});
return _temp;
}();
});

View File

@ -0,0 +1,51 @@
function classFactory() {
return class Foo {
#foo = "foo";
static #bar = "bar";
instance() {
return this.#foo;
}
static() {
return Foo.#bar;
}
static instance(inst) {
return inst.#foo;
}
static static() {
return Foo.#bar;
}
};
}
const Foo1 = classFactory();
const Foo2 = classFactory();
const f1 = new Foo1();
const f2 = new Foo2();
expect(f1.instance()).toBe("foo");
expect(f1.static()).toBe("bar");
expect(f2.instance()).toBe("foo");
expect(f2.static()).toBe("bar");
expect(Foo1.instance(f1)).toBe("foo");
expect(Foo1.static()).toBe("bar");
expect(Foo2.instance(f2)).toBe("foo");
expect(Foo2.static()).toBe("bar");
expect(() => {
f1.instance.call(f2), undefined;
}).toThrow();
expect(() => {
f2.instance.call(f1), undefined;
}).toThrow();
expect(() => {
Foo1.instance(f2), undefined;
}).toThrow();
expect(() => {
Foo2.instance(f1), undefined;
}).toThrow();

View File

@ -18,34 +18,5 @@ function classFactory() {
static static() {
return Foo.#bar;
}
};
}
}
const Foo1 = classFactory();
const Foo2 = classFactory();
const f1 = new Foo1;
const f2 = new Foo2;
expect(f1.instance()).toBe("foo");
expect(f1.static()).toBe("bar");
expect(f2.instance()).toBe("foo");
expect(f2.static()).toBe("bar");
expect(Foo1.instance(f1)).toBe("foo");
expect(Foo1.static()).toBe("bar");
expect(Foo2.instance(f2)).toBe("foo");
expect(Foo2.static()).toBe("bar");
assert.throws(() => {
f1.instance.call(f2), undefined;
});
assert.throws(() => {
f2.instance.call(f1), undefined;
});
assert.throws(() => {
Foo1.instance(f2), undefined;
});
assert.throws(() => {
Foo2.instance(f1), undefined;
});

View File

@ -1,3 +1,3 @@
{
"throws": "Static class fields are not spec'ed yet."
"plugins": ["external-helpers", "proposal-class-properties", "transform-block-scoping", "syntax-class-properties"]
}

View File

@ -0,0 +1,38 @@
function classFactory() {
var _class, _temp;
return function () {
_temp = _class = class Foo {
constructor() {
_foo.set(this, {
writable: true,
value: "foo"
});
}
instance() {
return babelHelpers.classPrivateFieldGet(this, _foo);
}
static() {
return babelHelpers.classStaticPrivateFieldSpecGet(Foo, _class, _classStatics, "bar");
}
static instance(inst) {
return babelHelpers.classPrivateFieldGet(inst, _foo);
}
static static() {
return babelHelpers.classStaticPrivateFieldSpecGet(Foo, _class, _classStatics, "bar");
}
};
var _foo = new WeakMap();
var _classStatics = Object.create(null);
babelHelpers.defineProperty(_classStatics, "bar", "bar");
return _temp;
}();
}

View File

@ -1,3 +1,3 @@
{
"throws": "Static class fields are not spec'ed yet."
"plugins": ["external-helpers", "proposal-class-properties", "transform-block-scoping", "syntax-class-properties"]
}

View File

@ -0,0 +1,16 @@
var _class, _temp;
call(function () {
_temp = _class = class {};
var _classStatics = Object.create(null);
babelHelpers.defineProperty(_classStatics, "test", true);
return _temp;
}());
export default class _class2 {}
var _class2Statics = Object.create(null);
babelHelpers.defineProperty(_class2Statics, "test", true);
;

View File

@ -1,3 +1,3 @@
{
"throws": "Static class fields are not spec'ed yet."
"plugins": ["external-helpers", "proposal-class-properties", "transform-block-scoping", "syntax-class-properties"]
}

View File

@ -0,0 +1,18 @@
function withContext(ComposedComponent) {
var _class, _temp;
return function () {
_temp = _class = class WithContext extends Component {};
var _classStatics = Object.create(null);
babelHelpers.defineProperty(_classStatics, "propTypes", {
context: PropTypes.shape({
addCss: PropTypes.func,
setTitle: PropTypes.func,
setMeta: PropTypes.func
})
});
return _temp;
}();
}

View File

@ -0,0 +1,13 @@
class Foo {
static #foo = function(x) {
return x;
}
test(x) {
return Foo.#foo(x);
}
}
const f = new Foo;
const test = f.test();
expect(f.test("bar")).toBe("bar");

View File

@ -0,0 +1,10 @@
class Foo {
static #foo = function(x) {
return x;
}
test(x) {
return Foo.#foo(x);
}
}

View File

@ -0,0 +1,23 @@
var Foo =
/*#__PURE__*/
function () {
"use strict";
function Foo() {
babelHelpers.classCallCheck(this, Foo);
}
babelHelpers.createClass(Foo, [{
key: "test",
value: function test(x) {
return babelHelpers.classStaticPrivateFieldSpecGet(Foo, Foo, _FooStatics, "foo").call(Foo, x);
}
}]);
return Foo;
}();
var _FooStatics = Object.create(null);
babelHelpers.defineProperty(_FooStatics, "foo", function (x) {
return x;
});

View File

@ -1,3 +1,3 @@
{
"throws": "Static class fields are not spec'ed yet."
"plugins": ["external-helpers", "proposal-class-properties", "transform-block-scoping", "syntax-class-properties"]
}

View File

@ -0,0 +1,10 @@
export class MyClass {}
var _MyClassStatics = Object.create(null);
babelHelpers.defineProperty(_MyClassStatics, "property", value);
export default class MyClass2 {}
var _MyClass2Statics = Object.create(null);
babelHelpers.defineProperty(_MyClass2Statics, "property", value);

View File

@ -1,3 +1,3 @@
{
"throws": "Static class fields are not spec'ed yet."
"plugins": ["external-helpers", "proposal-class-properties", "transform-block-scoping", "syntax-class-properties"]
}

View File

@ -0,0 +1,10 @@
var _class, _temp;
var Foo = function () {
_temp = _class = class Foo {};
var _classStatics = Object.create(null);
babelHelpers.defineProperty(_classStatics, "num", 0);
return _temp;
}();

View File

@ -0,0 +1,69 @@
class Base {
static #foo = 1;
static getThis() {
return this.#foo;
}
static updateThis(val) {
return (this.#foo = val);
}
static getClass() {
return Base.#foo;
}
static updateClass(val) {
return (Base.#foo = val);
}
}
class Sub1 extends Base {
static #foo = 2;
static update(val) {
return (this.#foo = val);
}
}
class Sub2 extends Base {}
expect(Base.getThis()).toBe(1);
expect(Base.getClass()).toBe(1);
expect(() => Sub1.getThis()).toThrow();
expect(Sub1.getClass()).toBe(1);
expect(() => Sub2.getThis()).toThrow();
expect(Sub2.getClass()).toBe(1);
expect(Sub1.update(3)).toBe(3);
expect(Base.getThis()).toBe(1);
expect(Base.getClass()).toBe(1);
expect(() => Sub1.getThis()).toThrow();
expect(Sub1.getClass()).toBe(1);
expect(() => Sub2.getThis()).toThrow();
expect(Sub2.getClass()).toBe(1);
expect(Base.updateThis(4)).toBe(4);
expect(Base.getThis()).toBe(4);
expect(Base.getClass()).toBe(4);
expect(() => Sub1.getThis()).toThrow();
expect(Sub1.getClass()).toBe(4);
expect(() => Sub2.getThis()).toThrow();
expect(Sub2.getClass()).toBe(4);
expect(Base.updateClass(5)).toBe(5);
expect(Base.getThis()).toBe(5);
expect(Base.getClass()).toBe(5);
expect(() => Sub1.getThis()).toThrow();
expect(Sub1.getClass()).toBe(5);
expect(() => Sub2.getThis()).toThrow();
expect(Sub2.getClass()).toBe(5);
expect(() => Sub2.updateThis(6)).toThrow();
expect(Sub2.updateClass(7)).toBe(7);
expect(Base.getThis()).toBe(7);
expect(Base.getClass()).toBe(7);
expect(() => Sub1.getThis()).toThrow();
expect(Sub1.getClass()).toBe(7);
expect(() => Sub2.getThis()).toThrow();
expect(Sub2.getClass()).toBe(7);

View File

@ -6,7 +6,7 @@ class Base {
}
static updateThis(val) {
return this.#foo = val;
return (this.#foo = val);
}
static getClass() {
@ -14,7 +14,7 @@ class Base {
}
static updateClass(val) {
return Base.#foo = val;
return (Base.#foo = val);
}
}
@ -22,49 +22,8 @@ class Sub1 extends Base {
static #foo = 2;
static update(val) {
return this.#foo = val;
return (this.#foo = val);
}
}
class Sub2 extends Base {
}
expect(Base.getThis()).toBe(1);
expect(Base.getClass()).toBe(1);
assert.throws(() => Sub1.getThis());
expect(Sub1.getClass()).toBe(1);
assert.throws(() => Sub2.getThis());
expect(Sub2.getClass()).toBe(1);
expect(Sub1.update(3)).toBe(3);
expect(Base.getThis()).toBe(1);
expect(Base.getClass()).toBe(1);
assert.throws(() => Sub1.getThis());
expect(Sub1.getClass()).toBe(1);
assert.throws(() => Sub2.getThis());
expect(Sub2.getClass()).toBe(1);
expect(Base.updateThis(4)).toBe(4);
expect(Base.getThis()).toBe(4);
expect(Base.getClass()).toBe(4);
assert.throws(() => Sub1.getThis());
expect(Sub1.getClass()).toBe(4);
assert.throws(() => Sub2.getThis());
expect(Sub2.getClass()).toBe(4);
expect(Base.updateClass(5)).toBe(5);
expect(Base.getThis()).toBe(5);
expect(Base.getClass()).toBe(5);
assert.throws(() => Sub1.getThis());
expect(Sub1.getClass()).toBe(5);
assert.throws(() => Sub2.getThis());
expect(Sub2.getClass()).toBe(5);
assert.throws(() => Sub2.updateThis(6));
expect(Sub2.updateClass(7)).toBe(7);
expect(Base.getThis()).toBe(7);
expect(Base.getClass()).toBe(7);
assert.throws(() => Sub1.getThis());
expect(Sub1.getClass()).toBe(7);
assert.throws(() => Sub2.getThis());
expect(Sub2.getClass()).toBe(7);
class Sub2 extends Base {}

View File

@ -1,3 +1,3 @@
{
"throws": "Static class fields are not spec'ed yet."
"plugins": ["external-helpers", "proposal-class-properties", "transform-block-scoping", "syntax-class-properties"]
}

View File

@ -0,0 +1,35 @@
class Base {
static getThis() {
return babelHelpers.classStaticPrivateFieldSpecGet(this, Base, _BaseStatics, "foo");
}
static updateThis(val) {
return babelHelpers.classStaticPrivateFieldSpecSet(this, Base, _BaseStatics, "foo", val);
}
static getClass() {
return babelHelpers.classStaticPrivateFieldSpecGet(Base, Base, _BaseStatics, "foo");
}
static updateClass(val) {
return babelHelpers.classStaticPrivateFieldSpecSet(Base, Base, _BaseStatics, "foo", val);
}
}
var _BaseStatics = Object.create(null);
babelHelpers.defineProperty(_BaseStatics, "foo", 1);
class Sub1 extends Base {
static update(val) {
return babelHelpers.classStaticPrivateFieldSpecSet(this, Sub1, _Sub1Statics, "foo", val);
}
}
var _Sub1Statics = Object.create(null);
babelHelpers.defineProperty(_Sub1Statics, "foo", 2);
class Sub2 extends Base {}

View File

@ -0,0 +1,15 @@
class Foo {
static #bar;
static test() {
return Foo.#bar;
}
test() {
return Foo.#bar;
}
}
expect("bar" in Foo).toBe(false);
expect(Foo.test()).toBe(undefined);
expect(Foo.test()).toBe(undefined);

View File

@ -9,7 +9,3 @@ class Foo {
return Foo.#bar;
}
}
expect("bar" in Foo).toBe(false)
expect(Foo.test()).toBe(undefined)
expect(Foo.test()).toBe(undefined)

View File

@ -1,3 +1,3 @@
{
"throws": "Static class fields are not spec'ed yet."
"plugins": ["external-helpers", "proposal-class-properties", "transform-block-scoping", "syntax-class-properties"]
}

View File

@ -0,0 +1,14 @@
class Foo {
static test() {
return babelHelpers.classStaticPrivateFieldSpecGet(Foo, Foo, _FooStatics, "bar");
}
test() {
return babelHelpers.classStaticPrivateFieldSpecGet(Foo, Foo, _FooStatics, "bar");
}
}
var _FooStatics = Object.create(null);
babelHelpers.defineProperty(_FooStatics, "bar", void 0);

View File

@ -1,3 +1,3 @@
{
"throws": "Static class fields are not spec'ed yet."
"plugins": ["external-helpers", "proposal-class-properties", "transform-block-scoping", "syntax-class-properties"]
}

View File

@ -0,0 +1,17 @@
class Foo {
static test() {
return babelHelpers.classStaticPrivateFieldSpecGet(Foo, Foo, _FooStatics, "bar");
}
test() {
return babelHelpers.classStaticPrivateFieldSpecGet(Foo, Foo, _FooStatics, "bar");
}
}
var _FooStatics = Object.create(null);
babelHelpers.defineProperty(_FooStatics, "bar", "foo");
expect("bar" in Foo).toBe(false);
expect(Foo.test()).toBe("foo");
expect(Foo.test()).toBe("foo");