Skip to content

Commit

Permalink
Add private method loose support
Browse files Browse the repository at this point in the history
  • Loading branch information
tim-mc committed Nov 24, 2018
1 parent c1ed468 commit fdabc63
Show file tree
Hide file tree
Showing 10 changed files with 226 additions and 0 deletions.
24 changes: 24 additions & 0 deletions packages/babel-plugin-class-features/src/fields.js
Expand Up @@ -257,6 +257,19 @@ function buildPrivateStaticFieldInitSpec(prop, privateNamesMap) {
`;
}

function buildPrivateMethodInitLoose(ref, prop, privateNamesMap) {
const { methodId, id } = privateNamesMap.get(prop.node.key.id.name);

return template.statement.ast`
Object.defineProperty(${ref}, ${id}, {
// configurable is false by default
// enumerable is false by default
writable: false,
value: ${methodId.name}
});
`;
}

function buildPrivateInstanceMethodInitSpec(ref, prop, privateNamesMap) {
const { id } = privateNamesMap.get(prop.node.key.id.name);

Expand Down Expand Up @@ -348,6 +361,17 @@ export function buildFieldsInitNodes(
);
break;
case !isStatic && isPrivateMethod && loose:
instanceNodes.push(
buildPrivateMethodInitLoose(
t.thisExpression(),
prop,
privateNamesMap,
),
);
staticNodes.push(
buildPrivateInstanceMethodDeclaration(prop, privateNamesMap),
);
break;
case !isStatic && isPrivateMethod && !loose:
instanceNodes.push(
buildPrivateInstanceMethodInitSpec(
Expand Down
@@ -0,0 +1,11 @@
class Foo {
constructor() {
this.publicField = this.#privateMethod();
}

#privateMethod() {
return 42;
}
}

expect((new Foo).publicField).toEqual(42);
@@ -0,0 +1,9 @@
class Foo {
constructor() {
this.publicField = this.#privateMethod();
}

#privateMethod() {
return 42;
}
}
@@ -0,0 +1,16 @@
var Foo = function Foo() {
"use strict";

babelHelpers.classCallCheck(this, Foo);
Object.defineProperty(this, _privateMethod, {
writable: false,
value: _privateMethod2
});
this.publicField = babelHelpers.classPrivateFieldLooseBase(this, _privateMethod)[_privateMethod]();
};

var _privateMethod = babelHelpers.classPrivateFieldLooseKey("privateMethod");

var _privateMethod2 = function _privateMethod2() {
return 42;
};
@@ -0,0 +1,41 @@
class Foo {
constructor(status) {
this.status = status;
expect(() => this.#getStatus = null).toThrow(TypeError);
}

#getStatus() {
return this.status;
}

getCurrentStatus() {
return this.#getStatus();
}

setCurrentStatus(newStatus) {
this.status = newStatus;
}

getFakeStatus(fakeStatus) {
const getStatus = this.#getStatus;
return function () {
return getStatus.call({ status: fakeStatus });
};
}

getFakeStatusFunc() {
return {
status: 'fake-status',
getFakeStatus: this.#getStatus,
};
}
}

const f = new Foo('inactive');
expect(f.getCurrentStatus()).toBe('inactive');

f.setCurrentStatus('new-status');
expect(f.getCurrentStatus()).toBe('new-status');

expect(f.getFakeStatus('fake')()).toBe('fake');
expect(f.getFakeStatusFunc().getFakeStatus()).toBe('fake-status');
@@ -0,0 +1,31 @@
class Foo {
constructor(status) {
this.status = status;
}

#getStatus() {
return this.status;
}

getCurrentStatus() {
return this.#getStatus();
}

setCurrentStatus(newStatus) {
this.status = newStatus;
}

getFakeStatus(fakeStatus) {
const fakeGetStatus = this.#getStatus;
return function() {
return fakeGetStatus.call({ status: fakeStatus });
};
}

getFakeStatusFunc() {
return {
status: 'fake-status',
getFakeStatus: this.#getStatus,
};
}
}
@@ -0,0 +1,52 @@
var Foo =
/*#__PURE__*/
function () {
"use strict";

function Foo(status) {
babelHelpers.classCallCheck(this, Foo);
Object.defineProperty(this, _getStatus, {
writable: false,
value: _getStatus2
});
this.status = status;
}

babelHelpers.createClass(Foo, [{
key: "getCurrentStatus",
value: function getCurrentStatus() {
return babelHelpers.classPrivateFieldLooseBase(this, _getStatus)[_getStatus]();
}
}, {
key: "setCurrentStatus",
value: function setCurrentStatus(newStatus) {
this.status = newStatus;
}
}, {
key: "getFakeStatus",
value: function getFakeStatus(fakeStatus) {
var fakeGetStatus = babelHelpers.classPrivateFieldLooseBase(this, _getStatus)[_getStatus];

return function () {
return fakeGetStatus.call({
status: fakeStatus
});
};
}
}, {
key: "getFakeStatusFunc",
value: function getFakeStatusFunc() {
return {
status: 'fake-status',
getFakeStatus: babelHelpers.classPrivateFieldLooseBase(this, _getStatus)[_getStatus]
};
}
}]);
return Foo;
}();

var _getStatus = babelHelpers.classPrivateFieldLooseKey("getStatus");

var _getStatus2 = function _getStatus2() {
return this.status;
};
@@ -0,0 +1,13 @@
let exfiltrated;
class Foo {
#privateMethod() {}

constructor() {
if (exfiltrated === undefined) {
exfiltrated = this.#privateMethod;
}
expect(exfiltrated).toStrictEqual(this.#privateMethod);
}
}

new Foo();
@@ -0,0 +1,10 @@
let exfiltrated;
class Foo {
#privateMethod() {}

constructor() {
if (exfiltrated === undefined) {
exfiltrated = this.#privateMethod;
}
}
}
@@ -0,0 +1,19 @@
var exfiltrated;

var Foo = function Foo() {
"use strict";

babelHelpers.classCallCheck(this, Foo);
Object.defineProperty(this, _privateMethod, {
writable: false,
value: _privateMethod2
});

if (exfiltrated === undefined) {
exfiltrated = babelHelpers.classPrivateFieldLooseBase(this, _privateMethod)[_privateMethod];
}
};

var _privateMethod = babelHelpers.classPrivateFieldLooseKey("privateMethod");

var _privateMethod2 = function _privateMethod2() {};

0 comments on commit fdabc63

Please sign in to comment.