Files
rea/src/domain/javascript/javascriptSemanticReferenceSources.ts
T
To3akaRin dea770d5d9 fix(javascript): retain getter receivers through local aliases (#2778)
* fix(javascript): retain getter receivers through local aliases

* fix(javascript): resolve projected private getter receivers

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-13 21:26:13 +08:00

54 lines
1.9 KiB
TypeScript

import type * as t from "@babel/types";
import type { JavaScriptSemanticAnalysisState } from "./javascriptSemanticState.js";
import type { JavaScriptSemanticPropertyPath as PropertyPath } from "./javascriptSemanticPropertyPaths.js";
import { evaluateSemanticExpression } from "./javascriptSemanticValues.js";
import { semanticSlotAtPath } from "./javascriptSemanticSlots.js";
interface ReferenceSource {
readonly node: t.Node;
readonly projection: PropertyPath;
}
/** Exclude references whose source slot or destructuring fallback is absent. */
export const semanticReferenceSourcesInactive = (
reference: {
readonly requiredSources?: readonly ReferenceSource[];
readonly fallbackSources?: readonly ReferenceSource[];
},
state: JavaScriptSemanticAnalysisState,
): boolean =>
reference.requiredSources?.some(
(source) =>
semanticSelectedReferenceSlot(source, state, source.node)?.presence ===
"absent",
) === true ||
reference.fallbackSources?.some((source) => {
// Selection precedes effects through the chosen reference. A later escape
// cannot make a fallback that was excluded at destructuring reachable.
const slot = semanticSelectedReferenceSlot(source, state, source.node);
return (
slot?.presence === "present" &&
(slot.value.status === "literal" ||
slot.value.status === "union" ||
slot.value.status === "object" ||
slot.value.status === "array")
);
}) === true;
/** Select a retained source slot at its capture, before later effects. */
export const semanticSelectedReferenceSlot = (
source: ReferenceSource,
state: JavaScriptSemanticAnalysisState,
capturePoint?: t.Node,
) => {
const path: string[] = [];
for (const key of source.projection) {
if (key === null || typeof key === "object") return undefined;
path.push(String(key));
}
return semanticSlotAtPath(
evaluateSemanticExpression(source.node, state, capturePoint),
path,
);
};