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,
|
||||
]);
|
||||
|
||||
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(
|
||||
path,
|
||||
ref,
|
||||
@ -676,8 +687,13 @@ function replaceThisContext(
|
||||
file,
|
||||
isStaticBlock,
|
||||
constantSuper,
|
||||
innerBindingRef,
|
||||
) {
|
||||
const state = { classRef: ref, needsClassRef: false };
|
||||
const state = {
|
||||
classRef: ref,
|
||||
needsClassRef: false,
|
||||
innerBinding: innerBindingRef,
|
||||
};
|
||||
|
||||
const replacer = new ReplaceSupers({
|
||||
methodPath: path,
|
||||
@ -696,6 +712,11 @@ function replaceThisContext(
|
||||
if (isStaticBlock || path.isProperty()) {
|
||||
path.traverse(thisContextVisitor, state);
|
||||
}
|
||||
|
||||
if (state.classRef?.name && state.classRef.name !== innerBindingRef?.name) {
|
||||
path.traverse(innerReferencesVisitor, state);
|
||||
}
|
||||
|
||||
return state.needsClassRef;
|
||||
}
|
||||
|
||||
@ -708,6 +729,7 @@ export function buildFieldsInitNodes(
|
||||
setPublicClassFields,
|
||||
privateFieldsAsProperties,
|
||||
constantSuper,
|
||||
innerBindingRef,
|
||||
) {
|
||||
let needsClassRef = false;
|
||||
let injectSuperRef;
|
||||
@ -743,6 +765,7 @@ export function buildFieldsInitNodes(
|
||||
state,
|
||||
isStaticBlock,
|
||||
constantSuper,
|
||||
innerBindingRef,
|
||||
);
|
||||
needsClassRef = needsClassRef || replaced;
|
||||
}
|
||||
|
||||
@ -168,9 +168,9 @@ export function createClassFeaturePlugin({
|
||||
|
||||
if (!props.length && !isDecorated) return;
|
||||
|
||||
const innerBinding = path.node.id;
|
||||
let ref;
|
||||
|
||||
if (path.isClassExpression() || !path.node.id) {
|
||||
if (!innerBinding || path.isClassExpression()) {
|
||||
nameFunction(path);
|
||||
ref = path.scope.generateUidIdentifier("class");
|
||||
} else {
|
||||
@ -220,6 +220,7 @@ export function createClassFeaturePlugin({
|
||||
setPublicClassFields ?? loose,
|
||||
privateFieldsAsProperties ?? 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