fix(javascript): retain initialized class self binding at body reads
This commit is contained in:
1 parent
f1a9d85de5
commit
dd55e2c7d5
2 files changed
+42
No files matched your search
@@ -211,3 +211,8 @@ it("owns a class declaration's self reference separately from its outer variable
|
||||
)?.resolution,
|
||||
).toBe("exact");
|
||||
});
|
||||
|
||||
it("does not initialize a class self name during computed-key evaluation", () => {
|
||||
const ir = analyze(`class Service { [Service()]() {} }`, "fixture.mjs");
|
||||
expect(ir.callSites[0]?.resolution).not.toBe("exact");
|
||||
});
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
semanticStaticPropertyKey,
|
||||
unwrapJavaScriptExpression,
|
||||
} from "./javascriptAstValues.js";
|
||||
import { semanticScopeId } from "./javascriptSemanticState.js";
|
||||
import type {
|
||||
JavaScriptSemanticBindingState,
|
||||
JavaScriptSemanticAnalysisState,
|
||||
@@ -746,6 +747,42 @@ export const semanticBindingAtRead = (
|
||||
t.isFunctionDeclaration(soleInitializer.node)
|
||||
)
|
||||
return { status: "ordered", binding, hasDefiniteInitializer: true };
|
||||
if (
|
||||
soleInitializer !== undefined &&
|
||||
t.isClass(soleInitializer.node) &&
|
||||
binding.scopeId === semanticScopeId("class", soleInitializer.node) &&
|
||||
!binding.mutable &&
|
||||
binding.initializers.length === 1 &&
|
||||
binding.referenceInitializers.length === 0 &&
|
||||
!binding.definitions.some(({ kind }) => kind === "assignment")
|
||||
) {
|
||||
// The class self name is initialized before fields/static blocks run and
|
||||
// before a body method can be invoked, but not during heritage/key evaluation.
|
||||
const owner = soleInitializer.node;
|
||||
let child = read;
|
||||
let memberPart: t.Node | undefined;
|
||||
for (
|
||||
let parent = parents.get(child);
|
||||
parent !== undefined;
|
||||
child = parent, parent = parents.get(parent)
|
||||
) {
|
||||
if (parents.get(parent) === owner.body) memberPart = child;
|
||||
if (parent === owner.body) {
|
||||
if (
|
||||
t.isClassMethod(child) || t.isClassPrivateMethod(child)
|
||||
? memberPart === child.body
|
||||
: t.isStaticBlock(child) ||
|
||||
((t.isClassProperty(child) ||
|
||||
t.isClassPrivateProperty(child) ||
|
||||
t.isClassAccessorProperty(child)) &&
|
||||
memberPart === child.value)
|
||||
)
|
||||
return { status: "ordered", binding, hasDefiniteInitializer: true };
|
||||
break;
|
||||
}
|
||||
if (parent === owner) break;
|
||||
}
|
||||
}
|
||||
const initializer = binding.initializers[0];
|
||||
const reference = binding.referenceInitializers[0];
|
||||
const origin = initializer ?? reference;
|
||||
|
||||
Reference in new issue
Block a user