fix(javascript): correct lexical and dynamic scope analysis (#538)

* fix(javascript): gate CommonJS exports on unshadowed globals and record dynamic scope

* fix(javascript): correct dynamic and switch scope boundaries
This commit is contained in:
morluto authored and GitHub committed 2026-10-05 23:42:48 +08:00
1 parent 00fa97422f
commit 6fa6f1f9b1
13 files changed
+337 -28

No files matched your search

@@ -255,22 +255,32 @@ export const projectSemanticClosureCaptures = (
});
};
/** Retain bounded unresolved dynamic-call and dynamic-property frontiers. */
/** Retain bounded unresolved dynamic-call, dynamic-property and dynamic-scope frontiers. */
export const projectSemanticFrontiers = (
context: SemanticFlowProjectionContext,
): void => {
for (const frontier of context.ir.frontiers) {
// Dynamic environments leave identifier reads and writes unresolved.
const family =
frontier.kind === "dynamic-call"
? "call-flow"
: frontier.kind === "dynamic-scope"
? "data-flow"
: "object-flow";
const relationKinds =
frontier.kind === "dynamic-call"
? (["calls"] as const)
: frontier.kind === "dynamic-scope"
? (["reads", "writes"] as const)
: (["reads-property", "writes-property"] as const);
const unknown = createJavaScriptSemanticGraphUnknown({
node_id:
frontier.callableId === null
? context.moduleNode.node_id
: (context.callableNodes.get(frontier.callableId)?.node_id ??
context.moduleNode.node_id),
family: frontier.kind === "dynamic-call" ? "call-flow" : "object-flow",
relation_kinds:
frontier.kind === "dynamic-call"
? ["calls"]
: ["reads-property", "writes-property"],
family,
relation_kinds: [...relationKinds],
reason: frontier.kind,
detail: frontier.reason,
candidate_node_ids: [],