refactor(javascript): share result binding projection and facts

This commit is contained in:
morluto
2026-10-22 10:33:18 +08:00
parent 34fd7bdf7d
commit dbcec4cf56
7 changed files with 57 additions and 56 deletions
@@ -10,7 +10,10 @@ import {
addSemanticGraphUnknown,
} from "./JavaScriptSemanticGraphConstruction.js";
import { unknownSemanticEvidence } from "./JavaScriptSemanticGraphEvidence.js";
import type { SemanticFlowProjectionContext } from "./JavaScriptSemanticGraphFlowProjection.js";
import {
projectSemanticResultBindings,
type SemanticFlowProjectionContext,
} from "./JavaScriptSemanticGraphFlowProjection.js";
/** Project literal EventEmitter registrations, removals, and dispatches. */
export const projectSemanticEvents = (
@@ -180,18 +183,11 @@ const projectTimerSchedule = (
relation: "schedules-timer",
resolution: "resolved",
});
for (const projected of operation.projectedResultBindings)
addSemanticGraphRelation(context.state, {
source: timerNodes.get(operation.timerId),
target: context.bindingNodes.get(projected.bindingId),
relation: "destructures",
resolution:
projected.resolution === "complete" ? "resolved" : "candidate",
properties: {
projection_path: [...projected.projectionPath],
projection_resolution: projected.resolution,
},
});
projectSemanticResultBindings(
context,
timerNodes.get(operation.timerId),
operation.projectedResultBindings,
);
};
const projectTimerCancellation = (
@@ -9,7 +9,10 @@ import {
addSemanticGraphUnknown,
} from "./JavaScriptSemanticGraphConstruction.js";
import { unknownSemanticEvidence } from "./JavaScriptSemanticGraphEvidence.js";
import type { SemanticFlowProjectionContext } from "./JavaScriptSemanticGraphFlowProjection.js";
import {
projectSemanticResultBindings,
type SemanticFlowProjectionContext,
} from "./JavaScriptSemanticGraphFlowProjection.js";
interface ChildUnknownInput {
readonly context: SemanticFlowProjectionContext;
@@ -80,18 +83,7 @@ const projectSpawn = (
relation: "spawns",
resolution: spawn.resolution === "complete" ? "resolved" : "candidate",
});
for (const projected of spawn.projectedResultBindings)
addSemanticGraphRelation(context.state, {
source: child,
target: context.bindingNodes.get(projected.bindingId),
relation: "destructures",
resolution:
projected.resolution === "complete" ? "resolved" : "candidate",
properties: {
projection_path: [...projected.projectionPath],
projection_resolution: projected.resolution,
},
});
projectSemanticResultBindings(context, child, spawn.projectedResultBindings);
if (spawn.argvCount !== null)
addSemanticGraphRelation(context.state, {
source: callSite,
@@ -10,7 +10,10 @@ import {
addSemanticGraphUnknown,
} from "./JavaScriptSemanticGraphConstruction.js";
import { unknownSemanticEvidence } from "./JavaScriptSemanticGraphEvidence.js";
import type { SemanticFlowProjectionContext } from "./JavaScriptSemanticGraphFlowProjection.js";
import {
projectSemanticResultBindings,
type SemanticFlowProjectionContext,
} from "./JavaScriptSemanticGraphFlowProjection.js";
import { semanticResourceLimitReason } from "../../domain/javascript/javascriptSemanticResourceLimits.js";
/** Project environment, argv, file, default, and precedence candidates. */
@@ -179,18 +182,11 @@ const projectRequestConstruction = (
relation: "constructs-request",
resolution: operation.resolution === "complete" ? "resolved" : "candidate",
});
for (const projected of operation.projectedResultBindings)
addSemanticGraphRelation(context.state, {
source: request,
target: context.bindingNodes.get(projected.bindingId),
relation: "destructures",
resolution:
projected.resolution === "complete" ? "resolved" : "candidate",
properties: {
projection_path: [...projected.projectionPath],
projection_resolution: projected.resolution,
},
});
projectSemanticResultBindings(
context,
request,
operation.projectedResultBindings,
);
for (const field of operation.fields)
addSemanticGraphRelation(context.state, {
source:
@@ -1,6 +1,9 @@
import type { JavaScriptSemanticGraphNode } from "../../domain/javascript/javascriptSemanticGraphSchemas.js";
import { javaScriptSemanticNodeId } from "../../domain/javascript/javascriptSemanticGraph.js";
import type { JavaScriptSemanticIr } from "../../domain/javascript/javascriptSemanticIr.js";
import type {
JavaScriptSemanticIr,
JavaScriptSemanticProjectedResultBinding,
} from "../../domain/javascript/javascriptSemanticIr.js";
import { sourceRangesEqual } from "../../domain/javascript/javascriptStaticAnalysisHelpers.js";
import type { JavaScriptSourceRange } from "../../domain/javascript/javascriptStaticAnalysisTypes.js";
import type { JavaScriptArtifactFile } from "../../domain/javascript/javascriptArtifactFiles.js";
@@ -34,6 +37,26 @@ export interface SemanticFlowProjectionContext {
) => JavaScriptSemanticGraphNode | undefined;
}
/** Project result destructuring consistently for timers, child processes, and requests. */
export const projectSemanticResultBindings = (
context: Pick<SemanticFlowProjectionContext, "state" | "bindingNodes">,
source: JavaScriptSemanticGraphNode | undefined,
bindings: readonly JavaScriptSemanticProjectedResultBinding[],
): void => {
for (const projected of bindings)
addSemanticGraphRelation(context.state, {
source,
target: context.bindingNodes.get(projected.bindingId),
relation: "destructures",
resolution:
projected.resolution === "complete" ? "resolved" : "candidate",
properties: {
projection_path: [...projected.projectionPath],
projection_resolution: projected.resolution,
},
});
};
/** Project explicit static Promise/task ownership without runtime claims. */
export const projectSemanticPromises = (
context: SemanticFlowProjectionContext,