From fb66fa6f90aa8fe228b29fcf886689ecea2557c4 Mon Sep 17 00:00:00 2001 From: Robin Ricard Date: Sat, 1 Sep 2018 00:42:18 -0400 Subject: [PATCH] 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 --- packages/babel-helpers/src/helpers.js | 32 ++++ .../src/index.js | 160 +++++++++++++++++- .../private-loose/native-classes/options.json | 2 +- .../private-loose/native-classes/output.js | 32 ++++ .../non-block-arrow-func/options.json | 2 +- .../non-block-arrow-func/output.mjs | 18 ++ .../test/fixtures/private-loose/options.json | 2 +- .../private-loose/reevaluated/options.json | 2 +- .../private-loose/reevaluated/output.js | 51 ++++++ .../private-loose/static-call/exec.js | 13 ++ .../private-loose/static-call/input.js | 10 ++ .../private-loose/static-call/output.js | 26 +++ .../private-loose/static-export/options.json | 2 +- .../private-loose/static-export/output.mjs | 14 ++ .../static-infer-name/options.json | 2 +- .../private-loose/static-infer-name/output.js | 8 + .../private-loose/static-inherited/exec.js | 69 ++++++++ .../private-loose/static-inherited/input.js | 49 +----- .../static-inherited/options.json | 2 +- .../private-loose/static-inherited/output.js | 41 +++++ .../private-loose/static-undefined/exec.js | 15 ++ .../private-loose/static-undefined/input.js | 4 - .../static-undefined/options.json | 2 +- .../private-loose/static-undefined/output.js | 17 ++ .../fixtures/private-loose/static/exec.js | 15 ++ .../fixtures/private-loose/static/input.js | 4 - .../private-loose/static/options.json | 2 +- .../fixtures/private-loose/static/output.js | 17 ++ .../fixtures/private/native-classes/exec.js | 18 ++ .../fixtures/private/native-classes/input.js | 6 - .../private/native-classes/options.json | 2 +- .../fixtures/private/native-classes/output.js | 23 +++ .../private/non-block-arrow-func/options.json | 2 +- .../private/non-block-arrow-func/output.mjs | 20 +++ .../test/fixtures/private/reevaluated/exec.js | 51 ++++++ .../fixtures/private/reevaluated/input.js | 31 +--- .../fixtures/private/reevaluated/options.json | 2 +- .../fixtures/private/reevaluated/output.js | 38 +++++ .../private/regression-T2983/options.json | 2 +- .../private/regression-T2983/output.mjs | 16 ++ .../private/regression-T6719/options.json | 2 +- .../private/regression-T6719/output.js | 18 ++ .../test/fixtures/private/static-call/exec.js | 13 ++ .../fixtures/private/static-call/input.js | 10 ++ .../fixtures/private/static-call/output.js | 23 +++ .../private/static-export/options.json | 2 +- .../fixtures/private/static-export/output.mjs | 10 ++ .../private/static-infer-name/options.json | 2 +- .../private/static-infer-name/output.js | 10 ++ .../fixtures/private/static-inherited/exec.js | 69 ++++++++ .../private/static-inherited/input.js | 49 +----- .../private/static-inherited/options.json | 2 +- .../private/static-inherited/output.js | 35 ++++ .../fixtures/private/static-undefined/exec.js | 15 ++ .../private/static-undefined/input.js | 4 - .../private/static-undefined/options.json | 2 +- .../private/static-undefined/output.js | 14 ++ .../test/fixtures/private/static/options.json | 2 +- .../test/fixtures/private/static/output.js | 17 ++ 59 files changed, 957 insertions(+), 166 deletions(-) create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/native-classes/output.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/non-block-arrow-func/output.mjs create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/reevaluated/output.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-call/exec.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-call/input.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-call/output.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-export/output.mjs create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-infer-name/output.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-inherited/exec.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-inherited/output.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-undefined/exec.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-undefined/output.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static/exec.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static/output.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private/native-classes/exec.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private/native-classes/output.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private/non-block-arrow-func/output.mjs create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private/reevaluated/exec.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private/reevaluated/output.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private/regression-T2983/output.mjs create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private/regression-T6719/output.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-call/exec.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-call/input.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-call/output.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-export/output.mjs create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-infer-name/output.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-inherited/exec.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-inherited/output.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-undefined/exec.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-undefined/output.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/private/static/output.js diff --git a/packages/babel-helpers/src/helpers.js b/packages/babel-helpers/src/helpers.js index db38c28b8a..051f918337 100644 --- a/packages/babel-helpers/src/helpers.js +++ b/packages/babel-helpers/src/helpers.js @@ -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; + } +`; diff --git a/packages/babel-plugin-proposal-class-properties/src/index.js b/packages/babel-plugin-proposal-class-properties/src/index.js index 3c333fdd36..7211a57968 100644 --- a/packages/babel-plugin-proposal-class-properties/src/index.js +++ b/packages/babel-plugin-proposal-class-properties/src/index.js @@ -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]); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/native-classes/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/native-classes/options.json index 03872554af..f14606ac1b 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/native-classes/options.json +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/native-classes/options.json @@ -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"] } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/native-classes/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/native-classes/output.js new file mode 100644 index 0000000000..9b3baaca50 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/native-classes/output.js @@ -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"); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/non-block-arrow-func/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/non-block-arrow-func/options.json index 03872554af..f14606ac1b 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/non-block-arrow-func/options.json +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/non-block-arrow-func/options.json @@ -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"] } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/non-block-arrow-func/output.mjs b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/non-block-arrow-func/output.mjs new file mode 100644 index 0000000000..b08ae2f56a --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/non-block-arrow-func/output.mjs @@ -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; +}); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/options.json index 38f1a44c55..ad77e9a210 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/options.json +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/options.json @@ -1,3 +1,3 @@ { - "plugins": ["external-helpers",["proposal-class-properties", { "loose": true }], "transform-classes", "transform-block-scoping", "syntax-class-properties"] + "plugins": ["external-helpers", ["proposal-class-properties", { "loose": true }], "transform-classes", "transform-block-scoping", "syntax-class-properties"] } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/reevaluated/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/reevaluated/options.json index 03872554af..f14606ac1b 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/reevaluated/options.json +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/reevaluated/options.json @@ -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"] } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/reevaluated/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/reevaluated/output.js new file mode 100644 index 0000000000..2716ec6785 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/reevaluated/output.js @@ -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)); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-call/exec.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-call/exec.js new file mode 100644 index 0000000000..a35aa6ade8 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-call/exec.js @@ -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"); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-call/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-call/input.js new file mode 100644 index 0000000000..9c6e3a2872 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-call/input.js @@ -0,0 +1,10 @@ +class Foo { + static #foo = function(x) { + return x; + } + + test(x) { + return Foo.#foo(x); + } +} + diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-call/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-call/output.js new file mode 100644 index 0000000000..32118df7e5 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-call/output.js @@ -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 +}); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-export/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-export/options.json index 03872554af..f14606ac1b 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-export/options.json +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-export/options.json @@ -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"] } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-export/output.mjs b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-export/output.mjs new file mode 100644 index 0000000000..ce77229f9c --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-export/output.mjs @@ -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 +}); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-infer-name/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-infer-name/options.json index 03872554af..f14606ac1b 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-infer-name/options.json +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-infer-name/options.json @@ -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"] } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-infer-name/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-infer-name/output.js new file mode 100644 index 0000000000..f75395dfd3 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-infer-name/output.js @@ -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); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-inherited/exec.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-inherited/exec.js new file mode 100644 index 0000000000..11fa8ce294 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-inherited/exec.js @@ -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); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-inherited/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-inherited/input.js index 66202d9f9d..d20e166098 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-inherited/input.js +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-inherited/input.js @@ -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 {} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-inherited/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-inherited/options.json index 03872554af..f14606ac1b 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-inherited/options.json +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-inherited/options.json @@ -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"] } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-inherited/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-inherited/output.js new file mode 100644 index 0000000000..908ed1d020 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-inherited/output.js @@ -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 {} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-undefined/exec.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-undefined/exec.js new file mode 100644 index 0000000000..e607ac72e7 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-undefined/exec.js @@ -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); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-undefined/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-undefined/input.js index d639688898..1f475fcdab 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-undefined/input.js +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-undefined/input.js @@ -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) diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-undefined/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-undefined/options.json index 03872554af..f14606ac1b 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-undefined/options.json +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-undefined/options.json @@ -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"] } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-undefined/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-undefined/output.js new file mode 100644 index 0000000000..a4b138fc3d --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static-undefined/output.js @@ -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 +}); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static/exec.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static/exec.js new file mode 100644 index 0000000000..e7ceb271af --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static/exec.js @@ -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"); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static/input.js index c905fa85d5..3497e0c62c 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static/input.js +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static/input.js @@ -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") diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static/options.json index 03872554af..f14606ac1b 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static/options.json +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static/options.json @@ -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"] } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static/output.js new file mode 100644 index 0000000000..620fe4f20c --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private-loose/static/output.js @@ -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 +}); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/native-classes/exec.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/native-classes/exec.js new file mode 100644 index 0000000000..e0c4dfe70b --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/native-classes/exec.js @@ -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") diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/native-classes/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/native-classes/input.js index e0c4dfe70b..38d9087340 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/native-classes/input.js +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/native-classes/input.js @@ -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") diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/native-classes/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/native-classes/options.json index 03872554af..c9f60de72d 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/native-classes/options.json +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/native-classes/options.json @@ -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"] } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/native-classes/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/native-classes/output.js new file mode 100644 index 0000000000..102388d493 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/native-classes/output.js @@ -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(); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/non-block-arrow-func/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/non-block-arrow-func/options.json index 03872554af..c9f60de72d 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/non-block-arrow-func/options.json +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/non-block-arrow-func/options.json @@ -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"] } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/non-block-arrow-func/output.mjs b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/non-block-arrow-func/output.mjs new file mode 100644 index 0000000000..1d3e803c83 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/non-block-arrow-func/output.mjs @@ -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; + }(); +}); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/reevaluated/exec.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/reevaluated/exec.js new file mode 100644 index 0000000000..407881827c --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/reevaluated/exec.js @@ -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(); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/reevaluated/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/reevaluated/input.js index 9e8222eb71..1adebbee27 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/reevaluated/input.js +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/reevaluated/input.js @@ -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; -}); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/reevaluated/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/reevaluated/options.json index 03872554af..c9f60de72d 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/reevaluated/options.json +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/reevaluated/options.json @@ -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"] } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/reevaluated/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/reevaluated/output.js new file mode 100644 index 0000000000..14bb63f68b --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/reevaluated/output.js @@ -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; + }(); +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/regression-T2983/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/regression-T2983/options.json index 03872554af..c9f60de72d 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/regression-T2983/options.json +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/regression-T2983/options.json @@ -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"] } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/regression-T2983/output.mjs b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/regression-T2983/output.mjs new file mode 100644 index 0000000000..5f724845bf --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/regression-T2983/output.mjs @@ -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); +; diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/regression-T6719/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/regression-T6719/options.json index 03872554af..c9f60de72d 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/regression-T6719/options.json +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/regression-T6719/options.json @@ -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"] } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/regression-T6719/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/regression-T6719/output.js new file mode 100644 index 0000000000..cb17fedd37 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/regression-T6719/output.js @@ -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; + }(); +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-call/exec.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-call/exec.js new file mode 100644 index 0000000000..a35aa6ade8 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-call/exec.js @@ -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"); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-call/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-call/input.js new file mode 100644 index 0000000000..9c6e3a2872 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-call/input.js @@ -0,0 +1,10 @@ +class Foo { + static #foo = function(x) { + return x; + } + + test(x) { + return Foo.#foo(x); + } +} + diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-call/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-call/output.js new file mode 100644 index 0000000000..2bfe473332 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-call/output.js @@ -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; +}); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-export/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-export/options.json index 03872554af..c9f60de72d 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-export/options.json +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-export/options.json @@ -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"] } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-export/output.mjs b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-export/output.mjs new file mode 100644 index 0000000000..4e3e7b3310 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-export/output.mjs @@ -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); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-infer-name/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-infer-name/options.json index 03872554af..c9f60de72d 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-infer-name/options.json +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-infer-name/options.json @@ -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"] } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-infer-name/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-infer-name/output.js new file mode 100644 index 0000000000..ad334d9a95 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-infer-name/output.js @@ -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; +}(); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-inherited/exec.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-inherited/exec.js new file mode 100644 index 0000000000..11fa8ce294 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-inherited/exec.js @@ -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); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-inherited/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-inherited/input.js index 66202d9f9d..d20e166098 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-inherited/input.js +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-inherited/input.js @@ -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 {} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-inherited/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-inherited/options.json index 03872554af..c9f60de72d 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-inherited/options.json +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-inherited/options.json @@ -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"] } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-inherited/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-inherited/output.js new file mode 100644 index 0000000000..e76bbac6cd --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-inherited/output.js @@ -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 {} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-undefined/exec.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-undefined/exec.js new file mode 100644 index 0000000000..e607ac72e7 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-undefined/exec.js @@ -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); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-undefined/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-undefined/input.js index d639688898..1f475fcdab 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-undefined/input.js +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-undefined/input.js @@ -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) diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-undefined/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-undefined/options.json index 03872554af..c9f60de72d 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-undefined/options.json +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-undefined/options.json @@ -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"] } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-undefined/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-undefined/output.js new file mode 100644 index 0000000000..c4861cce5c --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-undefined/output.js @@ -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); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static/options.json index 03872554af..c9f60de72d 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static/options.json +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static/options.json @@ -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"] } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static/output.js new file mode 100644 index 0000000000..4dacd6aa8e --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/private/static/output.js @@ -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");