Fix super Method Calls in Class Private Methods (#9704)
This fixes an issue with the use of super method calls in class private methods. See https://github.com/babel/babel/issues/9580 for more info re: behavior of the bug.
This commit is contained in:
parent
48d66eb648
commit
e068281e28
@ -501,10 +501,9 @@ function replaceThisContext(path, ref, superRef, file, loose) {
|
|||||||
file,
|
file,
|
||||||
getObjectRef() {
|
getObjectRef() {
|
||||||
state.needsClassRef = true;
|
state.needsClassRef = true;
|
||||||
return ref;
|
return path.node.static ? ref : t.thisExpression();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
replacer.isStatic = true;
|
|
||||||
replacer.replace();
|
replacer.replace();
|
||||||
if (path.isProperty()) {
|
if (path.isProperty()) {
|
||||||
path.traverse(thisContextVisitor, state);
|
path.traverse(thisContextVisitor, state);
|
||||||
@ -532,7 +531,7 @@ export function buildFieldsInitNodes(
|
|||||||
const isField = prop.isProperty();
|
const isField = prop.isProperty();
|
||||||
const isMethod = !isField;
|
const isMethod = !isField;
|
||||||
|
|
||||||
if (isStatic) {
|
if (isStatic || (isMethod && isPrivate)) {
|
||||||
const replaced = replaceThisContext(prop, ref, superRef, state, loose);
|
const replaced = replaceThisContext(prop, ref, superRef, state, loose);
|
||||||
needsClassRef = needsClassRef || replaced;
|
needsClassRef = needsClassRef || replaced;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,9 +15,10 @@ import * as t from "@babel/types";
|
|||||||
*
|
*
|
||||||
* helpers.getPrototypeOf(CLASS.prototype)
|
* helpers.getPrototypeOf(CLASS.prototype)
|
||||||
*/
|
*/
|
||||||
function getPrototypeOfExpression(objectRef, isStatic, file) {
|
function getPrototypeOfExpression(objectRef, isStatic, file, isPrivateMethod) {
|
||||||
objectRef = t.cloneNode(objectRef);
|
objectRef = t.cloneNode(objectRef);
|
||||||
const targetRef = isStatic
|
const targetRef =
|
||||||
|
isStatic || isPrivateMethod
|
||||||
? objectRef
|
? objectRef
|
||||||
: t.memberExpression(objectRef, t.identifier("prototype"));
|
: t.memberExpression(objectRef, t.identifier("prototype"));
|
||||||
|
|
||||||
@ -98,7 +99,12 @@ const specHandlers = {
|
|||||||
|
|
||||||
get(superMember) {
|
get(superMember) {
|
||||||
return t.callExpression(this.file.addHelper("get"), [
|
return t.callExpression(this.file.addHelper("get"), [
|
||||||
getPrototypeOfExpression(this.getObjectRef(), this.isStatic, this.file),
|
getPrototypeOfExpression(
|
||||||
|
this.getObjectRef(),
|
||||||
|
this.isStatic,
|
||||||
|
this.file,
|
||||||
|
this.isPrivateMethod,
|
||||||
|
),
|
||||||
this.prop(superMember),
|
this.prop(superMember),
|
||||||
t.thisExpression(),
|
t.thisExpression(),
|
||||||
]);
|
]);
|
||||||
@ -106,7 +112,12 @@ const specHandlers = {
|
|||||||
|
|
||||||
set(superMember, value) {
|
set(superMember, value) {
|
||||||
return t.callExpression(this.file.addHelper("set"), [
|
return t.callExpression(this.file.addHelper("set"), [
|
||||||
getPrototypeOfExpression(this.getObjectRef(), this.isStatic, this.file),
|
getPrototypeOfExpression(
|
||||||
|
this.getObjectRef(),
|
||||||
|
this.isStatic,
|
||||||
|
this.file,
|
||||||
|
this.isPrivateMethod,
|
||||||
|
),
|
||||||
this.prop(superMember),
|
this.prop(superMember),
|
||||||
value,
|
value,
|
||||||
t.thisExpression(),
|
t.thisExpression(),
|
||||||
@ -170,8 +181,8 @@ export default class ReplaceSupers {
|
|||||||
const path = opts.methodPath;
|
const path = opts.methodPath;
|
||||||
|
|
||||||
this.methodPath = path;
|
this.methodPath = path;
|
||||||
this.isStatic =
|
this.isStatic = path.isObjectMethod() || path.node.static;
|
||||||
path.isClassMethod({ static: true }) || path.isObjectMethod();
|
this.isPrivateMethod = path.isPrivate() && path.isMethod();
|
||||||
|
|
||||||
this.file = opts.file;
|
this.file = opts.file;
|
||||||
this.superRef = opts.superRef;
|
this.superRef = opts.superRef;
|
||||||
@ -202,6 +213,7 @@ export default class ReplaceSupers {
|
|||||||
memberExpressionToFunctions(this.methodPath, visitor, {
|
memberExpressionToFunctions(this.methodPath, visitor, {
|
||||||
file: this.file,
|
file: this.file,
|
||||||
isStatic: this.isStatic,
|
isStatic: this.isStatic,
|
||||||
|
isPrivateMethod: this.isPrivateMethod,
|
||||||
getObjectRef: this.getObjectRef.bind(this),
|
getObjectRef: this.getObjectRef.bind(this),
|
||||||
superRef: this.superRef,
|
superRef: this.superRef,
|
||||||
...handler,
|
...handler,
|
||||||
|
|||||||
17
packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-loose/super/exec.js
vendored
Normal file
17
packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-loose/super/exec.js
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
class Base {
|
||||||
|
superMethod() {
|
||||||
|
return 1017;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Sub extends Base {
|
||||||
|
#privateMethod() {
|
||||||
|
return super.superMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
publicMethod() {
|
||||||
|
return this.#privateMethod();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expect((new Sub()).publicMethod()).toEqual(1017);
|
||||||
15
packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-loose/super/input.js
vendored
Normal file
15
packages/babel-plugin-proposal-private-methods/test/fixtures/private-method-loose/super/input.js
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
class Base {
|
||||||
|
superMethod() {
|
||||||
|
return 1017;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Sub extends Base {
|
||||||
|
#privateMethod() {
|
||||||
|
return super.superMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
publicMethod() {
|
||||||
|
return this.#privateMethod();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
class Base {
|
||||||
|
superMethod() {
|
||||||
|
return 1017;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Sub extends Base {
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
Object.defineProperty(this, _privateMethod, {
|
||||||
|
value: _privateMethod2
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
publicMethod() {
|
||||||
|
return babelHelpers.classPrivateFieldLooseBase(this, _privateMethod)[_privateMethod]();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var _privateMethod = babelHelpers.classPrivateFieldLooseKey("privateMethod");
|
||||||
|
|
||||||
|
var _privateMethod2 = function _privateMethod2() {
|
||||||
|
return Base.prototype.superMethod.call(this);
|
||||||
|
};
|
||||||
17
packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/super/exec.js
vendored
Normal file
17
packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/super/exec.js
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
class Base {
|
||||||
|
superMethod() {
|
||||||
|
return 1017;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Sub extends Base {
|
||||||
|
#privateMethod() {
|
||||||
|
return super.superMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
publicMethod() {
|
||||||
|
return this.#privateMethod();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expect((new Sub()).publicMethod()).toEqual(1017);
|
||||||
15
packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/super/input.js
vendored
Normal file
15
packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/super/input.js
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
class Base {
|
||||||
|
superMethod() {
|
||||||
|
return 1017;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Sub extends Base {
|
||||||
|
#privateMethod() {
|
||||||
|
return super.superMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
publicMethod() {
|
||||||
|
return this.#privateMethod();
|
||||||
|
}
|
||||||
|
}
|
||||||
25
packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/super/output.js
vendored
Normal file
25
packages/babel-plugin-proposal-private-methods/test/fixtures/private-method/super/output.js
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
class Base {
|
||||||
|
superMethod() {
|
||||||
|
return 1017;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Sub extends Base {
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
|
||||||
|
_privateMethod.add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
publicMethod() {
|
||||||
|
return babelHelpers.classPrivateMethodGet(this, _privateMethod, _privateMethod2).call(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var _privateMethod = new WeakSet();
|
||||||
|
|
||||||
|
var _privateMethod2 = function _privateMethod2() {
|
||||||
|
return babelHelpers.get(babelHelpers.getPrototypeOf(this), "superMethod", this).call(this);
|
||||||
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user