fix: reference to class expression in private method (#13429)
Co-authored-by: Henry Zhu <hi@henryzoo.com> Co-authored-by: Federico Ciardi <fed.ciardi@gmail.com> Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
This commit is contained in:
parent
69f423b873
commit
903b600522
@ -669,6 +669,17 @@ const thisContextVisitor = traverse.visitors.merge([
|
|||||||
environmentVisitor,
|
environmentVisitor,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const innerReferencesVisitor = {
|
||||||
|
ReferencedIdentifier(path, state) {
|
||||||
|
if (
|
||||||
|
path.scope.bindingIdentifierEquals(path.node.name, state.innerBinding)
|
||||||
|
) {
|
||||||
|
state.needsClassRef = true;
|
||||||
|
path.node.name = state.classRef.name;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
function replaceThisContext(
|
function replaceThisContext(
|
||||||
path,
|
path,
|
||||||
ref,
|
ref,
|
||||||
@ -676,8 +687,13 @@ function replaceThisContext(
|
|||||||
file,
|
file,
|
||||||
isStaticBlock,
|
isStaticBlock,
|
||||||
constantSuper,
|
constantSuper,
|
||||||
|
innerBindingRef,
|
||||||
) {
|
) {
|
||||||
const state = { classRef: ref, needsClassRef: false };
|
const state = {
|
||||||
|
classRef: ref,
|
||||||
|
needsClassRef: false,
|
||||||
|
innerBinding: innerBindingRef,
|
||||||
|
};
|
||||||
|
|
||||||
const replacer = new ReplaceSupers({
|
const replacer = new ReplaceSupers({
|
||||||
methodPath: path,
|
methodPath: path,
|
||||||
@ -696,6 +712,11 @@ function replaceThisContext(
|
|||||||
if (isStaticBlock || path.isProperty()) {
|
if (isStaticBlock || path.isProperty()) {
|
||||||
path.traverse(thisContextVisitor, state);
|
path.traverse(thisContextVisitor, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state.classRef?.name && state.classRef.name !== innerBindingRef?.name) {
|
||||||
|
path.traverse(innerReferencesVisitor, state);
|
||||||
|
}
|
||||||
|
|
||||||
return state.needsClassRef;
|
return state.needsClassRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -708,6 +729,7 @@ export function buildFieldsInitNodes(
|
|||||||
setPublicClassFields,
|
setPublicClassFields,
|
||||||
privateFieldsAsProperties,
|
privateFieldsAsProperties,
|
||||||
constantSuper,
|
constantSuper,
|
||||||
|
innerBindingRef,
|
||||||
) {
|
) {
|
||||||
let needsClassRef = false;
|
let needsClassRef = false;
|
||||||
let injectSuperRef;
|
let injectSuperRef;
|
||||||
@ -743,6 +765,7 @@ export function buildFieldsInitNodes(
|
|||||||
state,
|
state,
|
||||||
isStaticBlock,
|
isStaticBlock,
|
||||||
constantSuper,
|
constantSuper,
|
||||||
|
innerBindingRef,
|
||||||
);
|
);
|
||||||
needsClassRef = needsClassRef || replaced;
|
needsClassRef = needsClassRef || replaced;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -168,9 +168,9 @@ export function createClassFeaturePlugin({
|
|||||||
|
|
||||||
if (!props.length && !isDecorated) return;
|
if (!props.length && !isDecorated) return;
|
||||||
|
|
||||||
|
const innerBinding = path.node.id;
|
||||||
let ref;
|
let ref;
|
||||||
|
if (!innerBinding || path.isClassExpression()) {
|
||||||
if (path.isClassExpression() || !path.node.id) {
|
|
||||||
nameFunction(path);
|
nameFunction(path);
|
||||||
ref = path.scope.generateUidIdentifier("class");
|
ref = path.scope.generateUidIdentifier("class");
|
||||||
} else {
|
} else {
|
||||||
@ -220,6 +220,7 @@ export function createClassFeaturePlugin({
|
|||||||
setPublicClassFields ?? loose,
|
setPublicClassFields ?? loose,
|
||||||
privateFieldsAsProperties ?? loose,
|
privateFieldsAsProperties ?? loose,
|
||||||
constantSuper ?? loose,
|
constantSuper ?? loose,
|
||||||
|
innerBinding,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
15
packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-self-field/exec.js
vendored
Normal file
15
packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-self-field/exec.js
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
const f = class Foo {
|
||||||
|
static #x = Foo;
|
||||||
|
static y = Foo;
|
||||||
|
|
||||||
|
static extract() {
|
||||||
|
return {
|
||||||
|
x: Foo.#x,
|
||||||
|
y: Foo.y,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const { x, y } = f.extract();
|
||||||
|
expect(x).toBe(f)
|
||||||
|
expect(y).toBe(f)
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
const f = class Foo {
|
||||||
|
static #x = Foo;
|
||||||
|
static y = Foo;
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["proposal-class-properties", "transform-block-scoping"]
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
var _class, _temp, _x;
|
||||||
|
|
||||||
|
var f = (_temp = _class = class Foo {}, _x = {
|
||||||
|
writable: true,
|
||||||
|
value: _class
|
||||||
|
}, babelHelpers.defineProperty(_class, "y", _class), _temp);
|
||||||
31
packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-self-method/exec.js
vendored
Normal file
31
packages/babel-plugin-proposal-class-properties/test/fixtures/private/static-self-method/exec.js
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
const f = class Foo {
|
||||||
|
static #bar() {
|
||||||
|
return Foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
static #method() {
|
||||||
|
return function inner() {
|
||||||
|
return Foo;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
static #method_shadowed() {
|
||||||
|
new Foo();
|
||||||
|
return function inner() {
|
||||||
|
let Foo = 3;
|
||||||
|
return Foo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static extract() {
|
||||||
|
return {
|
||||||
|
bar: Foo.#bar,
|
||||||
|
method: Foo.#method,
|
||||||
|
method_shadowed: Foo.#method_shadowed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const { bar, method, method_shadowed } = f.extract();
|
||||||
|
expect(bar()).toBe(f)
|
||||||
|
expect(method()()).toBe(f)
|
||||||
|
expect(method_shadowed()()).toBe(3)
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
const f = class Foo {
|
||||||
|
static #bar() {
|
||||||
|
return Foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
static #method() {
|
||||||
|
return function inner() {
|
||||||
|
return Foo;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
static #method_shadowed() {
|
||||||
|
new Foo();
|
||||||
|
return function inner() {
|
||||||
|
let Foo = 3;
|
||||||
|
return Foo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["proposal-class-properties", "transform-block-scoping"]
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
var _class;
|
||||||
|
|
||||||
|
var f = _class = class Foo {};
|
||||||
|
|
||||||
|
function _bar() {
|
||||||
|
return _class;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _method() {
|
||||||
|
return function inner() {
|
||||||
|
return _class;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function _method_shadowed() {
|
||||||
|
new _class();
|
||||||
|
return function inner() {
|
||||||
|
var Foo = 3;
|
||||||
|
return Foo;
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user