rea-agents 2.3.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -18
- package/bridge/ghidra/ReaGhidraBridge.java +48 -1
- package/bridge/hopper_bridge.py +259 -24
- package/dist/application/AnalysisClientCleanup.js +14 -0
- package/dist/application/ApplicationWorkflowEvidenceResolver.js +31 -13
- package/dist/application/ArtifactExtraction.js +5 -1
- package/dist/application/ArtifactGraphConstruction.js +3 -15
- package/dist/application/ArtifactInventory/classify.js +5 -1
- package/dist/application/ArtifactInventory/reader.js +2 -0
- package/dist/application/BinarySession.js +15 -4
- package/dist/application/BinarySessionStatus.js +32 -1
- package/dist/application/BrowserEvidence.js +14 -0
- package/dist/application/BrowserScenarioCapturePort.js +1 -0
- package/dist/application/BrowserScenarioCaptureService.js +53 -0
- package/dist/application/BrowserScenarioEvidence.js +40 -0
- package/dist/application/CallPathTracing.js +160 -0
- package/dist/application/CapabilityInventory.js +79 -15
- package/dist/application/CompositeProvider.js +10 -1
- package/dist/application/DirectAnalysis.js +7 -2
- package/dist/application/EnhancedLiteralTracing.js +118 -0
- package/dist/application/EnhancedTools.js +35 -121
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +13 -0
- package/dist/application/JavaScriptApplicationWorkflowService.js +27 -1
- package/dist/application/JavaScriptRuntimeObservationEvidence.js +34 -0
- package/dist/application/JavaScriptRuntimeObservationPort.js +1 -0
- package/dist/application/JavaScriptRuntimeObservationService.js +46 -0
- package/dist/application/JavaScriptSemanticGraphAsyncProjection.js +147 -0
- package/dist/application/JavaScriptSemanticGraphBuilder.js +34 -6
- package/dist/application/JavaScriptSemanticGraphChildProcessProjection.js +156 -0
- package/dist/application/JavaScriptSemanticGraphConstruction.js +2 -2
- package/dist/application/JavaScriptSemanticGraphDataProjection.js +203 -0
- package/dist/application/JavaScriptSemanticGraphFingerprintProjection.js +25 -0
- package/dist/application/JavaScriptSemanticGraphFlowProjection.js +129 -8
- package/dist/application/JavaScriptSemanticGraphObjectProjection.js +81 -0
- package/dist/application/JavaScriptSemanticGraphProjection.js +14 -7
- package/dist/application/JavaScriptSemanticGraphResourceProjection.js +59 -0
- package/dist/application/JavaScriptSemanticGraphValueProjection.js +77 -0
- package/dist/application/ProcessCaptureEnvironment.js +26 -0
- package/dist/application/ProcessCaptureLifecycle.js +1 -0
- package/dist/application/ProcessCheckpoints.js +5 -0
- package/dist/application/ProcessHarness.js +45 -34
- package/dist/application/ProcessNormalization.js +6 -0
- package/dist/application/ProcessReactiveCoordinator.js +10 -3
- package/dist/application/ProcessReactiveEffects.js +15 -1
- package/dist/application/ProcessReactiveHarness.js +100 -0
- package/dist/application/ProcessReactiveObservations.js +101 -16
- package/dist/application/ProjectPermissionStore.js +1 -0
- package/dist/application/ReconstructionObligationAuthority.js +72 -0
- package/dist/application/ReconstructionObligationCandidates.js +265 -0
- package/dist/application/ReconstructionObligationLedgerDiagnostics.js +47 -0
- package/dist/application/ReconstructionObligationLedgerEvaluation.js +263 -0
- package/dist/application/ReconstructionObligationLedgerProjection.js +86 -0
- package/dist/application/ReconstructionObligationLedgerService.js +72 -0
- package/dist/application/ReconstructionObligationOriginalCases.js +33 -0
- package/dist/application/ReconstructionObligationPolicies.js +132 -0
- package/dist/application/ReconstructionReadinessService.js +48 -0
- package/dist/artifacts/ArtifactProvider.js +87 -22
- package/dist/browser/BrowserScenarioSecrets.js +53 -0
- package/dist/browser/BrowserScenarioSessionPort.js +1 -0
- package/dist/browser/CdpBrowserProvider.js +2 -2
- package/dist/browser/CdpCaptureDocuments.js +57 -0
- package/dist/browser/CdpCaptureStorage.js +71 -29
- package/dist/browser/CdpCaptureStorageFingerprints.js +328 -0
- package/dist/browser/CdpEndpoint.js +8 -6
- package/dist/browser/CdpPageCapture.js +2 -0
- package/dist/browser/JavaScriptRuntimeScope.js +38 -0
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +253 -0
- package/dist/browser/PlaywrightExecutionBoundary.js +42 -0
- package/dist/browser/PlaywrightScenarioActions.js +62 -0
- package/dist/browser/PlaywrightScenarioArtifacts.js +238 -0
- package/dist/browser/PlaywrightScenarioBrowser.js +144 -0
- package/dist/browser/PlaywrightScenarioEvents.js +301 -0
- package/dist/browser/PlaywrightScenarioSession.js +300 -0
- package/dist/browser/V8InspectorCaptureProjection.js +110 -0
- package/dist/browser/V8InspectorEndpoint.js +72 -0
- package/dist/browser/V8InspectorProvider.js +267 -0
- package/dist/catalogIdentity.js +8 -0
- package/dist/cli/artifactCommands.js +39 -0
- package/dist/cli/coreAnalysisCommands.js +37 -0
- package/dist/cli.js +4 -0
- package/dist/cliApplicationCommands.js +30 -2
- package/dist/cliBrowserAdvancedCommands.js +17 -5
- package/dist/cliBrowserCommands.js +1 -0
- package/dist/cliBrowserScenarioCommands.js +43 -0
- package/dist/cliCommandNames.js +8 -0
- package/dist/cliJavaScriptRuntimeCommands.js +164 -0
- package/dist/cliObservationOptions.js +4 -0
- package/dist/cliPolicyCommands.js +1 -0
- package/dist/config/environment.js +12 -0
- package/dist/config/parseConfig.js +88 -17
- package/dist/contracts/analysisSearchContract.js +14 -0
- package/dist/contracts/applicationToolContracts.js +86 -2
- package/dist/contracts/applicationWorkflowInputContracts.js +18 -0
- package/dist/contracts/artifactToolContracts.js +22 -0
- package/dist/contracts/browserProviderToolContracts.js +7 -0
- package/dist/contracts/browserScenarioToolContracts.js +81 -0
- package/dist/contracts/browserToolContracts.js +88 -98
- package/dist/contracts/enhancedInputs.js +25 -6
- package/dist/contracts/functionInstructionContract.js +8 -0
- package/dist/contracts/hopperMemoryContracts.js +22 -0
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +42 -0
- package/dist/contracts/javascriptRuntimeObservationToolContracts.js +58 -0
- package/dist/contracts/reconstructionReadinessExample.js +436 -0
- package/dist/contracts/toolContractExamples.js +5 -0
- package/dist/contracts/toolContractTypes.js +1 -0
- package/dist/contracts/toolContracts.js +13 -21
- package/dist/contracts/toolEffects.js +21 -0
- package/dist/contracts/toolOutputSchemaGroups.js +70 -20
- package/dist/contracts/toolOutputSchemaPrimitives.js +40 -0
- package/dist/domain/analysisErrorProjection.js +8 -0
- package/dist/domain/analysisSnapshot.js +2 -0
- package/dist/domain/artifactGraph.js +2 -0
- package/dist/domain/artifactInspection.js +347 -0
- package/dist/domain/binaryTarget.js +3 -6
- package/dist/domain/browserCaptureComparison.js +82 -0
- package/dist/domain/browserObservation.js +8 -1
- package/dist/domain/browserObservationErrors.js +1 -0
- package/dist/domain/browserObservationSchemas.js +26 -0
- package/dist/domain/browserScenario.js +165 -0
- package/dist/domain/browserScenarioCapture.js +57 -0
- package/dist/domain/browserScenarioCaptureValues.js +204 -0
- package/dist/domain/browserScenarioDiff.js +324 -0
- package/dist/domain/browserScenarioDiffValues.js +157 -0
- package/dist/domain/browserScenarioNormalization.js +45 -0
- package/dist/domain/browserScenarioValues.js +372 -0
- package/dist/domain/evidence.js +2 -0
- package/dist/domain/hopperValues.js +10 -0
- package/dist/domain/javascriptRuntimeObservation.js +170 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +120 -2
- package/dist/domain/javascriptRuntimeReconciliationResult.js +3 -3
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +2 -2
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +1 -1
- package/dist/domain/javascriptSemanticAnalysis.js +5 -4
- package/dist/domain/javascriptSemanticAsyncEffects.js +253 -0
- package/dist/domain/javascriptSemanticChildProcesses.js +237 -0
- package/dist/domain/javascriptSemanticDataEffectHelpers.js +125 -0
- package/dist/domain/javascriptSemanticDataEffects.js +284 -0
- package/dist/domain/javascriptSemanticDerivedAnalysis.js +41 -0
- package/dist/domain/javascriptSemanticFingerprints.js +174 -0
- package/dist/domain/javascriptSemanticIr.js +21 -1
- package/dist/domain/javascriptSemanticObjects.js +115 -0
- package/dist/domain/javascriptSemanticPromises.js +290 -0
- package/dist/domain/javascriptSemanticResources.js +136 -0
- package/dist/domain/javascriptStaticAnalysis.js +4 -3
- package/dist/domain/javascriptStaticAnalysisBundler.js +38 -0
- package/dist/domain/javascriptStaticAnalysisCalls.js +23 -1
- package/dist/domain/javascriptStaticAnalysisHelpers.js +8 -0
- package/dist/domain/processCapture.js +71 -1
- package/dist/domain/processCaptureReactiveValidation.js +175 -0
- package/dist/domain/processCaptureValidation.js +2 -0
- package/dist/domain/processObservation.js +15 -6
- package/dist/domain/processReactiveRuntime.js +21 -10
- package/dist/domain/processReactiveScenario.js +1 -0
- package/dist/domain/processReactiveTransition.js +17 -10
- package/dist/domain/processScenario.js +21 -0
- package/dist/domain/providerCleanupError.js +11 -0
- package/dist/domain/reconstructionObligationLedgerSchemas.js +278 -0
- package/dist/domain/reconstructionReadiness.js +121 -0
- package/dist/domain/reconstructionReadinessFindingHelpers.js +17 -0
- package/dist/domain/reconstructionReadinessIntegrityFindings.js +118 -0
- package/dist/domain/reconstructionReadinessJourneyFindings.js +193 -0
- package/dist/domain/reconstructionReadinessSchemas.js +240 -0
- package/dist/domain/sourceToBundleComparison.js +335 -0
- package/dist/domain/sourceToBundleComparisonSchemas.js +133 -0
- package/dist/domain/sourceToBundleSignals.js +202 -0
- package/dist/domain/webCaptureDiff.js +141 -27
- package/dist/domain/webScreenshot.js +1 -1
- package/dist/domain/zipPackageFormat.js +20 -0
- package/dist/generatedPackageMetadata.js +1 -1
- package/dist/ghidra/GhidraDefaults.js +1 -1
- package/dist/ghidra/GhidraFunctionValues.js +13 -1
- package/dist/ghidra/GhidraProviderCapabilities.js +7 -0
- package/dist/hopper/HopperCleanup.js +158 -0
- package/dist/hopper/HopperClient.js +69 -99
- package/dist/hopper/HopperProvider.js +20 -1
- package/dist/hopper/HopperRequestQueue.js +187 -0
- package/dist/hopper/HopperResponseStream.js +46 -0
- package/dist/hopper/protocol.js +1 -0
- package/dist/main/transport.js +24 -24
- package/dist/main.js +6 -0
- package/dist/mcpDoctor.js +25 -2
- package/dist/native/NativeMacOSProvider.js +1 -0
- package/dist/process/ProcessCommandIdentity.js +19 -0
- package/dist/process/ProcessOwnership.js +11 -8
- package/dist/server/DynamicToolAvailability.js +70 -0
- package/dist/server/createServer.js +46 -1
- package/dist/server/lifecycleProgress.js +10 -0
- package/dist/server/permissionFailure.js +12 -0
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +35 -0
- package/dist/server/registerApplicationTools/helpers.js +11 -7
- package/dist/server/registerApplicationTools/obligationLedger.js +27 -0
- package/dist/server/registerApplicationTools/readiness.js +55 -0
- package/dist/server/registerApplicationTools.js +6 -0
- package/dist/server/registerArtifactTools.js +9 -1
- package/dist/server/registerBrowserScenarioTool.js +25 -0
- package/dist/server/registerBrowserTools.js +2 -2
- package/dist/server/registerCloseLifecycleTool.js +57 -0
- package/dist/server/registerEnhancedTools.js +16 -5
- package/dist/server/registerEvidenceResources.js +4 -0
- package/dist/server/registerEvidenceTools.js +9 -2
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +37 -0
- package/dist/server/registerReconstructionObligationLedgerResource.js +39 -0
- package/dist/server/registerReconstructionReadinessResource.js +39 -0
- package/dist/server/registerSessionStatusTool.js +11 -8
- package/dist/server/registerSessionTools.js +11 -57
- package/dist/server/sessionAvailabilityPolicy.js +10 -8
- package/package.json +12 -6
- package/skills/reverse-engineer-anything/SKILL.md +4 -3
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +2 -2
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
import { createJavaScriptSemanticGraph, } from "../domain/javascriptSemanticGraph.js";
|
|
2
2
|
import { JAVASCRIPT_SEMANTIC_RELATION_FAMILIES, JAVASCRIPT_SEMANTIC_RELATION_FAMILY, } from "../domain/javascriptSemanticGraphSchemas.js";
|
|
3
|
+
import { sourceRangesEqual as rangesEqual } from "../domain/javascriptStaticAnalysisHelpers.js";
|
|
4
|
+
import { projectSemanticEvents, projectSemanticTimers, } from "./JavaScriptSemanticGraphAsyncProjection.js";
|
|
5
|
+
import { projectSemanticChildProcesses } from "./JavaScriptSemanticGraphChildProcessProjection.js";
|
|
6
|
+
import { projectSemanticBoundaries, projectSemanticConfiguration, projectSemanticRequests, } from "./JavaScriptSemanticGraphDataProjection.js";
|
|
7
|
+
import { projectSemanticResources } from "./JavaScriptSemanticGraphResourceProjection.js";
|
|
8
|
+
import { projectSemanticObjects } from "./JavaScriptSemanticGraphObjectProjection.js";
|
|
9
|
+
import { projectSemanticValues } from "./JavaScriptSemanticGraphValueProjection.js";
|
|
3
10
|
import { inferredSemanticEvidenceAt } from "./JavaScriptSemanticGraphEvidence.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
11
|
+
import { projectSemanticFunctionFingerprints } from "./JavaScriptSemanticGraphFingerprintProjection.js";
|
|
12
|
+
import { projectSemanticClosureCaptures, projectSemanticFrontiers, projectSemanticPromises, projectSemanticReturnValues, semanticRecoveryLimits, } from "./JavaScriptSemanticGraphFlowProjection.js";
|
|
13
|
+
import { owningSemanticCallableNode, semanticFamilyStatus, semanticNodesWithinRange, } from "./JavaScriptSemanticGraphProjection.js";
|
|
6
14
|
import { addSemanticFallbackRoot as addFallbackRoot, addSemanticGraphNode as addNode, addSemanticGraphRelation as addRelation, constructSemanticGraphNode as semanticNode, createSemanticGraphProjectionState as emptyState, MAX_APPLICATION_NODE_IDS_PER_SEMANTIC_NODE, MAX_SEMANTIC_GRAPH_NODES, MAX_SEMANTIC_GRAPH_RELATIONS, MAX_SEMANTIC_GRAPH_UNKNOWNS, } from "./JavaScriptSemanticGraphConstruction.js";
|
|
7
15
|
/** Project bounded per-file semantic IR into an artifact-bound companion graph. */
|
|
8
16
|
export const buildJavaScriptSemanticGraph = ({ rootArtifactSha256, applicationGraph, analysis, }) => {
|
|
9
17
|
const state = emptyState(applicationGraph);
|
|
18
|
+
const fingerprints = [];
|
|
10
19
|
for (const analyzed of analysis.files) {
|
|
11
20
|
if (analyzed.semantic === null)
|
|
12
21
|
continue;
|
|
13
|
-
projectFile(analyzed.file, analyzed.semantic.ir, state);
|
|
22
|
+
fingerprints.push(...projectFile(analyzed.file, analyzed.semantic.ir, state));
|
|
14
23
|
}
|
|
15
24
|
if (state.roots.size === 0)
|
|
16
25
|
addFallbackRoot(rootArtifactSha256, state);
|
|
@@ -25,7 +34,7 @@ export const buildJavaScriptSemanticGraph = ({ rootArtifactSha256, applicationGr
|
|
|
25
34
|
root_node_ids: [...state.roots],
|
|
26
35
|
nodes: [...state.nodes.values()],
|
|
27
36
|
relations: [...state.relations.values()],
|
|
28
|
-
fingerprints
|
|
37
|
+
fingerprints,
|
|
29
38
|
unknowns,
|
|
30
39
|
coverage: {
|
|
31
40
|
status: truncated ? "partial" : "unknown",
|
|
@@ -68,7 +77,15 @@ export const buildJavaScriptSemanticGraph = ({ rootArtifactSha256, applicationGr
|
|
|
68
77
|
limitations: [
|
|
69
78
|
"The semantic graph contains static syntax observations and conservative relationship candidates; it does not claim runtime execution.",
|
|
70
79
|
"Local data flow does not claim control-flow-sensitive reaching definitions or arbitrary dynamic property resolution.",
|
|
71
|
-
"
|
|
80
|
+
"Promise ownership covers explicit unshadowed Promise construction, static factories, aggregation, chaining, and await syntax only.",
|
|
81
|
+
"Function fingerprints are bounded static candidates; equal digests can remain ambiguous and do not prove behavioral equivalence.",
|
|
82
|
+
"Event extraction covers EventEmitter-style literal registrations, removals, and dispatch candidates; dynamic names remain unknown.",
|
|
83
|
+
"Timer extraction covers global or node:timers scheduling and exact local-handle cancellation.",
|
|
84
|
+
"Child-process extraction covers asynchronous node:child_process creation, literal argv/env/stdio options, exit/error listeners, and kill signals.",
|
|
85
|
+
"Configuration extraction covers process.env, process.argv, node:fs reads, and direct logical defaults.",
|
|
86
|
+
"Request extraction covers fetch, WebSocket, node:http/node:https construction, direct option fields, and exact local response consumers.",
|
|
87
|
+
"Boundary extraction covers unshadowed JSON/global coercions plus parse and validation method candidates.",
|
|
88
|
+
"Resource extraction covers built-in filesystem/network acquisition and exact local close/destroy/end handles.",
|
|
72
89
|
...(truncated
|
|
73
90
|
? [
|
|
74
91
|
"Semantic graph projection reached one or more explicit hard limits.",
|
|
@@ -86,7 +103,7 @@ const projectFile = (file, ir, state) => {
|
|
|
86
103
|
functionNodeId: null,
|
|
87
104
|
}, state));
|
|
88
105
|
if (moduleNode === null)
|
|
89
|
-
return;
|
|
106
|
+
return [];
|
|
90
107
|
state.roots.add(moduleNode.node_id);
|
|
91
108
|
const callableNodes = new Map(ir.callables.flatMap((callable) => {
|
|
92
109
|
const node = addNode(state, semanticNode(file, {
|
|
@@ -130,9 +147,20 @@ const projectFile = (file, ir, state) => {
|
|
|
130
147
|
])),
|
|
131
148
|
};
|
|
132
149
|
projectDefinitionsAndReferences(context);
|
|
150
|
+
projectSemanticValues(context);
|
|
151
|
+
projectSemanticObjects(context);
|
|
133
152
|
projectCalls(context);
|
|
153
|
+
projectSemanticPromises(context);
|
|
154
|
+
projectSemanticEvents(context);
|
|
155
|
+
projectSemanticTimers(context);
|
|
156
|
+
projectSemanticChildProcesses(context);
|
|
157
|
+
projectSemanticConfiguration(context);
|
|
158
|
+
projectSemanticRequests(context);
|
|
159
|
+
projectSemanticBoundaries(context);
|
|
160
|
+
projectSemanticResources(context);
|
|
134
161
|
projectSemanticClosureCaptures(context);
|
|
135
162
|
projectSemanticFrontiers(context);
|
|
163
|
+
return projectSemanticFunctionFingerprints(file, ir, callableNodes);
|
|
136
164
|
};
|
|
137
165
|
const createReturnSiteNodes = (file, ir, callables, state) => {
|
|
138
166
|
const result = new Map();
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { createJavaScriptSemanticGraphUnknown } from "../domain/javascriptSemanticGraph.js";
|
|
2
|
+
import { addSemanticGraphNode, addSemanticGraphRelation, addSemanticGraphUnknown, constructSemanticGraphNode, } from "./JavaScriptSemanticGraphConstruction.js";
|
|
3
|
+
import { unknownSemanticEvidence } from "./JavaScriptSemanticGraphEvidence.js";
|
|
4
|
+
import { semanticCallSiteAt, } from "./JavaScriptSemanticGraphFlowProjection.js";
|
|
5
|
+
/** Project child creation, argv/env/stdio, listeners, and signals. */
|
|
6
|
+
export const projectSemanticChildProcesses = (context) => {
|
|
7
|
+
const processNodes = new Map(context.ir.childProcessSpawns.flatMap((spawn) => {
|
|
8
|
+
const node = addChildProcessNode(context, spawn);
|
|
9
|
+
return node === null ? [] : [[spawn.processId, node]];
|
|
10
|
+
}));
|
|
11
|
+
for (const spawn of context.ir.childProcessSpawns) {
|
|
12
|
+
const child = processNodes.get(spawn.processId);
|
|
13
|
+
if (child === undefined)
|
|
14
|
+
continue;
|
|
15
|
+
projectSpawn(context, spawn, child);
|
|
16
|
+
}
|
|
17
|
+
for (const interaction of context.ir.childProcessInteractions)
|
|
18
|
+
projectInteraction(context, interaction, processNodes);
|
|
19
|
+
};
|
|
20
|
+
const addChildProcessNode = (context, spawn) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
|
|
21
|
+
kind: "child-process",
|
|
22
|
+
roleKey: spawn.processId,
|
|
23
|
+
location: spawn.location,
|
|
24
|
+
label: spawn.command ?? spawn.method,
|
|
25
|
+
functionNodeId: spawn.ownerCallableId === null
|
|
26
|
+
? null
|
|
27
|
+
: (context.callableNodes.get(spawn.ownerCallableId)?.node_id ??
|
|
28
|
+
null),
|
|
29
|
+
properties: {
|
|
30
|
+
argv_count: spawn.argvCount,
|
|
31
|
+
command: spawn.command,
|
|
32
|
+
environment_supplied: spawn.environmentSupplied,
|
|
33
|
+
method: spawn.method,
|
|
34
|
+
stdio_mode: spawn.stdioMode,
|
|
35
|
+
},
|
|
36
|
+
}, context.state));
|
|
37
|
+
const projectSpawn = (context, spawn, child) => {
|
|
38
|
+
const callSite = semanticCallSiteAt(context, spawn.location);
|
|
39
|
+
addSemanticGraphRelation(context.state, {
|
|
40
|
+
source: callSite,
|
|
41
|
+
target: child,
|
|
42
|
+
relation: "spawns",
|
|
43
|
+
resolution: spawn.resolution === "complete" ? "resolved" : "candidate",
|
|
44
|
+
});
|
|
45
|
+
if (spawn.argvCount !== null)
|
|
46
|
+
addSemanticGraphRelation(context.state, {
|
|
47
|
+
source: callSite,
|
|
48
|
+
target: child,
|
|
49
|
+
relation: "supplies-argv",
|
|
50
|
+
resolution: "resolved",
|
|
51
|
+
properties: { argument_count: spawn.argvCount },
|
|
52
|
+
});
|
|
53
|
+
if (spawn.environmentSupplied)
|
|
54
|
+
addSemanticGraphRelation(context.state, {
|
|
55
|
+
source: callSite,
|
|
56
|
+
target: child,
|
|
57
|
+
relation: "supplies-env",
|
|
58
|
+
resolution: "resolved",
|
|
59
|
+
});
|
|
60
|
+
const stdio = addStdioNode(context, spawn, child);
|
|
61
|
+
addSemanticGraphRelation(context.state, {
|
|
62
|
+
source: child,
|
|
63
|
+
target: stdio,
|
|
64
|
+
relation: "connects-stdio",
|
|
65
|
+
resolution: spawn.stdioMode === "dynamic" ? "candidate" : "resolved",
|
|
66
|
+
});
|
|
67
|
+
if (spawn.resolution !== "complete")
|
|
68
|
+
addChildUnknown({
|
|
69
|
+
context,
|
|
70
|
+
node: child,
|
|
71
|
+
location: spawn.location,
|
|
72
|
+
relationKinds: ["spawns"],
|
|
73
|
+
detail: `Static ${spawn.method} command remains unresolved.`,
|
|
74
|
+
candidateNodeIds: [],
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
const addStdioNode = (context, spawn, child) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
|
|
78
|
+
kind: "stdio",
|
|
79
|
+
roleKey: `stdio:${spawn.processId}`,
|
|
80
|
+
location: spawn.location,
|
|
81
|
+
label: spawn.stdioMode,
|
|
82
|
+
functionNodeId: child.function_node_id,
|
|
83
|
+
properties: { mode: spawn.stdioMode },
|
|
84
|
+
}, context.state));
|
|
85
|
+
const projectInteraction = (context, interaction, processNodes) => {
|
|
86
|
+
const children = interaction.linkedProcessIds.flatMap((identifier) => {
|
|
87
|
+
const child = processNodes.get(identifier);
|
|
88
|
+
return child === undefined ? [] : [child];
|
|
89
|
+
});
|
|
90
|
+
const effect = interaction.kind === "listener"
|
|
91
|
+
? addChildListenerNode(context, interaction)
|
|
92
|
+
: addSignalNode(context, interaction);
|
|
93
|
+
for (const child of children)
|
|
94
|
+
addSemanticGraphRelation(context.state, {
|
|
95
|
+
source: interaction.kind === "listener" ? child : effect,
|
|
96
|
+
target: interaction.kind === "listener" ? effect : child,
|
|
97
|
+
relation: interaction.kind === "signal"
|
|
98
|
+
? "forwards-signal"
|
|
99
|
+
: interaction.eventName === "exit"
|
|
100
|
+
? "listens-exit"
|
|
101
|
+
: "listens-error",
|
|
102
|
+
resolution: interaction.resolution === "complete" ? "resolved" : "candidate",
|
|
103
|
+
});
|
|
104
|
+
if (interaction.resolution !== "complete")
|
|
105
|
+
addChildUnknown({
|
|
106
|
+
context,
|
|
107
|
+
node: effect,
|
|
108
|
+
location: interaction.location,
|
|
109
|
+
relationKinds: [
|
|
110
|
+
interaction.kind === "signal"
|
|
111
|
+
? "forwards-signal"
|
|
112
|
+
: interaction.eventName === "exit"
|
|
113
|
+
? "listens-exit"
|
|
114
|
+
: "listens-error",
|
|
115
|
+
],
|
|
116
|
+
detail: `Static child ${interaction.method} ownership is ambiguous.`,
|
|
117
|
+
candidateNodeIds: children.map(({ node_id: identifier }) => identifier),
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
const addChildListenerNode = (context, interaction) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
|
|
121
|
+
kind: "listener",
|
|
122
|
+
roleKey: interaction.interactionId,
|
|
123
|
+
location: interaction.listenerLocation ?? interaction.location,
|
|
124
|
+
label: interaction.eventName,
|
|
125
|
+
functionNodeId: interaction.ownerCallableId === null
|
|
126
|
+
? null
|
|
127
|
+
: (context.callableNodes.get(interaction.ownerCallableId)
|
|
128
|
+
?.node_id ?? null),
|
|
129
|
+
properties: {
|
|
130
|
+
event_name: interaction.eventName,
|
|
131
|
+
method: interaction.method,
|
|
132
|
+
},
|
|
133
|
+
}, context.state));
|
|
134
|
+
const addSignalNode = (context, interaction) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
|
|
135
|
+
kind: "signal",
|
|
136
|
+
roleKey: interaction.interactionId,
|
|
137
|
+
location: interaction.location,
|
|
138
|
+
label: interaction.signalName,
|
|
139
|
+
functionNodeId: interaction.ownerCallableId === null
|
|
140
|
+
? null
|
|
141
|
+
: (context.callableNodes.get(interaction.ownerCallableId)
|
|
142
|
+
?.node_id ?? null),
|
|
143
|
+
properties: { signal_name: interaction.signalName },
|
|
144
|
+
}, context.state));
|
|
145
|
+
const addChildUnknown = (input) => {
|
|
146
|
+
const { context, node, location, relationKinds, detail, candidateNodeIds } = input;
|
|
147
|
+
addSemanticGraphUnknown(context.state, createJavaScriptSemanticGraphUnknown({
|
|
148
|
+
node_id: node?.node_id ?? null,
|
|
149
|
+
family: "child-process",
|
|
150
|
+
relation_kinds: relationKinds,
|
|
151
|
+
reason: "ambiguous-target",
|
|
152
|
+
detail,
|
|
153
|
+
candidate_node_ids: candidateNodeIds,
|
|
154
|
+
evidence: unknownSemanticEvidence(context.file, location),
|
|
155
|
+
}));
|
|
156
|
+
};
|
|
@@ -32,7 +32,7 @@ export const constructSemanticGraphNode = (file, input, state) => createJavaScri
|
|
|
32
32
|
function_node_id: input.functionNodeId,
|
|
33
33
|
application_node_ids: matchingApplicationNodeIds(file, input, state),
|
|
34
34
|
label: input.label,
|
|
35
|
-
properties: {},
|
|
35
|
+
properties: input.properties ?? {},
|
|
36
36
|
evidence: observedSemanticEvidence(file, input.location),
|
|
37
37
|
});
|
|
38
38
|
/** Retain one canonical node unless the hard graph bound was reached. */
|
|
@@ -60,7 +60,7 @@ export const addSemanticGraphRelation = (state, input) => {
|
|
|
60
60
|
target_node_id: input.target.node_id,
|
|
61
61
|
relation: input.relation,
|
|
62
62
|
resolution: input.resolution ?? "candidate",
|
|
63
|
-
properties: {},
|
|
63
|
+
properties: input.properties ?? {},
|
|
64
64
|
evidence: input.evidence ?? inferredSemanticEvidence(input.source),
|
|
65
65
|
});
|
|
66
66
|
if (state.relations.has(value.relation_id))
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { createJavaScriptSemanticGraphUnknown } from "../domain/javascriptSemanticGraph.js";
|
|
2
|
+
import { addSemanticGraphNode, addSemanticGraphRelation, addSemanticGraphUnknown, constructSemanticGraphNode, } from "./JavaScriptSemanticGraphConstruction.js";
|
|
3
|
+
import { unknownSemanticEvidence } from "./JavaScriptSemanticGraphEvidence.js";
|
|
4
|
+
import { semanticCallSiteAt, } from "./JavaScriptSemanticGraphFlowProjection.js";
|
|
5
|
+
/** Project environment, argv, file, default, and precedence candidates. */
|
|
6
|
+
export const projectSemanticConfiguration = (context) => {
|
|
7
|
+
const configNodes = new Map(context.ir.configurationOperations.flatMap((operation) => {
|
|
8
|
+
const node = addConfigurationNode(context, operation);
|
|
9
|
+
return node === null ? [] : [[operation.configId, node]];
|
|
10
|
+
}));
|
|
11
|
+
for (const operation of context.ir.configurationOperations) {
|
|
12
|
+
const config = configNodes.get(operation.configId);
|
|
13
|
+
if (config === undefined)
|
|
14
|
+
continue;
|
|
15
|
+
const target = bindingOrOwner(context, operation.resultBindingId, operation.ownerCallableId);
|
|
16
|
+
addSemanticGraphRelation(context.state, {
|
|
17
|
+
source: config,
|
|
18
|
+
target,
|
|
19
|
+
relation: configurationRelation(operation),
|
|
20
|
+
resolution: operation.resolution === "complete" ? "resolved" : "candidate",
|
|
21
|
+
});
|
|
22
|
+
if (operation.kind === "default" && operation.sourceConfigId !== null)
|
|
23
|
+
addSemanticGraphRelation(context.state, {
|
|
24
|
+
source: configNodes.get(operation.sourceConfigId),
|
|
25
|
+
target: config,
|
|
26
|
+
relation: "overrides",
|
|
27
|
+
resolution: operation.resolution === "complete" ? "resolved" : "candidate",
|
|
28
|
+
});
|
|
29
|
+
if (operation.resolution !== "complete")
|
|
30
|
+
addDataUnknown({
|
|
31
|
+
context,
|
|
32
|
+
node: config,
|
|
33
|
+
family: "configuration",
|
|
34
|
+
relationKinds: [
|
|
35
|
+
configurationRelation(operation),
|
|
36
|
+
...(operation.kind === "default" ? ["overrides"] : []),
|
|
37
|
+
],
|
|
38
|
+
location: operation.location,
|
|
39
|
+
detail: `Static ${operation.kind} configuration identity is partial.`,
|
|
40
|
+
candidateNodeIds: [],
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
const addConfigurationNode = (context, operation) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
|
|
45
|
+
kind: "config-source",
|
|
46
|
+
roleKey: operation.configId,
|
|
47
|
+
location: operation.location,
|
|
48
|
+
label: operation.key ?? operation.kind,
|
|
49
|
+
functionNodeId: operation.ownerCallableId === null
|
|
50
|
+
? null
|
|
51
|
+
: (context.callableNodes.get(operation.ownerCallableId)?.node_id ??
|
|
52
|
+
null),
|
|
53
|
+
properties: {
|
|
54
|
+
key: operation.key,
|
|
55
|
+
source_kind: operation.kind,
|
|
56
|
+
value: operation.value,
|
|
57
|
+
},
|
|
58
|
+
}, context.state));
|
|
59
|
+
const configurationRelation = (operation) => operation.kind === "environment"
|
|
60
|
+
? "reads-environment"
|
|
61
|
+
: operation.kind === "argv"
|
|
62
|
+
? "reads-argv"
|
|
63
|
+
: operation.kind === "file"
|
|
64
|
+
? "reads-config"
|
|
65
|
+
: "defaults";
|
|
66
|
+
/** Project request construction, field provenance, and response consumers. */
|
|
67
|
+
export const projectSemanticRequests = (context) => {
|
|
68
|
+
const requestNodes = new Map(context.ir.requestOperations.flatMap((operation) => {
|
|
69
|
+
const node = addRequestNode(context, operation);
|
|
70
|
+
return node === null ? [] : [[operation.requestId, node]];
|
|
71
|
+
}));
|
|
72
|
+
for (const operation of context.ir.requestOperations) {
|
|
73
|
+
const request = requestNodes.get(operation.requestId);
|
|
74
|
+
if (request === undefined)
|
|
75
|
+
continue;
|
|
76
|
+
if (operation.kind === "request")
|
|
77
|
+
projectRequestConstruction(context, operation, request);
|
|
78
|
+
else
|
|
79
|
+
projectResponseConsumer(context, operation, request);
|
|
80
|
+
if (operation.resolution !== "complete")
|
|
81
|
+
addDataUnknown({
|
|
82
|
+
context,
|
|
83
|
+
node: request,
|
|
84
|
+
family: "request",
|
|
85
|
+
relationKinds: operation.kind === "request"
|
|
86
|
+
? ["constructs-request", "supplies-request-field"]
|
|
87
|
+
: ["consumed-by"],
|
|
88
|
+
location: operation.location,
|
|
89
|
+
detail: `Static ${operation.method} request resolution was ${operation.resolution}.`,
|
|
90
|
+
candidateNodeIds: operation.linkedRequestIds.flatMap((identifier) => {
|
|
91
|
+
const candidate = requestNodes.get(identifier);
|
|
92
|
+
return candidate === undefined ? [] : [candidate.node_id];
|
|
93
|
+
}),
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
const addRequestNode = (context, operation) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
|
|
98
|
+
kind: operation.kind === "request" ? "request" : "response",
|
|
99
|
+
roleKey: operation.requestId,
|
|
100
|
+
location: operation.location,
|
|
101
|
+
label: operation.endpoint ?? operation.method,
|
|
102
|
+
functionNodeId: operation.ownerCallableId === null
|
|
103
|
+
? null
|
|
104
|
+
: (context.callableNodes.get(operation.ownerCallableId)?.node_id ??
|
|
105
|
+
null),
|
|
106
|
+
properties: {
|
|
107
|
+
endpoint: operation.endpoint,
|
|
108
|
+
method: operation.method,
|
|
109
|
+
operation_kind: operation.kind,
|
|
110
|
+
},
|
|
111
|
+
}, context.state));
|
|
112
|
+
const projectRequestConstruction = (context, operation, request) => {
|
|
113
|
+
const callSite = semanticCallSiteAt(context, operation.location);
|
|
114
|
+
addSemanticGraphRelation(context.state, {
|
|
115
|
+
source: callSite,
|
|
116
|
+
target: request,
|
|
117
|
+
relation: "constructs-request",
|
|
118
|
+
resolution: operation.resolution === "complete" ? "resolved" : "candidate",
|
|
119
|
+
});
|
|
120
|
+
for (const field of operation.fields)
|
|
121
|
+
addSemanticGraphRelation(context.state, {
|
|
122
|
+
source: field.sourceBindingId === null
|
|
123
|
+
? callSite
|
|
124
|
+
: context.bindingNodes.get(field.sourceBindingId),
|
|
125
|
+
target: request,
|
|
126
|
+
relation: "supplies-request-field",
|
|
127
|
+
resolution: field.sourceBindingId === null ? "candidate" : "resolved",
|
|
128
|
+
properties: { field: field.name },
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
const projectResponseConsumer = (context, operation, response) => {
|
|
132
|
+
addSemanticGraphRelation(context.state, {
|
|
133
|
+
source: response,
|
|
134
|
+
target: semanticCallSiteAt(context, operation.location),
|
|
135
|
+
relation: "consumed-by",
|
|
136
|
+
resolution: operation.resolution === "complete" ? "resolved" : "candidate",
|
|
137
|
+
properties: { method: operation.method },
|
|
138
|
+
});
|
|
139
|
+
};
|
|
140
|
+
/** Project parse, coercion, and validation consumers as static boundaries. */
|
|
141
|
+
export const projectSemanticBoundaries = (context) => {
|
|
142
|
+
for (const operation of context.ir.boundaryOperations) {
|
|
143
|
+
const boundary = addBoundaryNode(context, operation);
|
|
144
|
+
if (boundary === null)
|
|
145
|
+
continue;
|
|
146
|
+
addSemanticGraphRelation(context.state, {
|
|
147
|
+
source: bindingOrOwner(context, operation.sourceBindingId, operation.ownerCallableId),
|
|
148
|
+
target: boundary,
|
|
149
|
+
relation: operation.kind === "parse"
|
|
150
|
+
? "parses"
|
|
151
|
+
: operation.kind === "coerce"
|
|
152
|
+
? "coerces"
|
|
153
|
+
: "validates",
|
|
154
|
+
resolution: operation.resolution === "complete" ? "resolved" : "candidate",
|
|
155
|
+
});
|
|
156
|
+
if (operation.resolution !== "complete")
|
|
157
|
+
addDataUnknown({
|
|
158
|
+
context,
|
|
159
|
+
node: boundary,
|
|
160
|
+
family: "boundary",
|
|
161
|
+
relationKinds: [
|
|
162
|
+
operation.kind === "parse"
|
|
163
|
+
? "parses"
|
|
164
|
+
: operation.kind === "coerce"
|
|
165
|
+
? "coerces"
|
|
166
|
+
: "validates",
|
|
167
|
+
],
|
|
168
|
+
location: operation.location,
|
|
169
|
+
detail: `Static ${operation.method} boundary kind is a candidate.`,
|
|
170
|
+
candidateNodeIds: [],
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
const addBoundaryNode = (context, operation) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
|
|
175
|
+
kind: "boundary",
|
|
176
|
+
roleKey: operation.boundaryId,
|
|
177
|
+
location: operation.location,
|
|
178
|
+
label: operation.method,
|
|
179
|
+
functionNodeId: operation.ownerCallableId === null
|
|
180
|
+
? null
|
|
181
|
+
: (context.callableNodes.get(operation.ownerCallableId)?.node_id ??
|
|
182
|
+
null),
|
|
183
|
+
properties: {
|
|
184
|
+
boundary_kind: operation.kind,
|
|
185
|
+
method: operation.method,
|
|
186
|
+
},
|
|
187
|
+
}, context.state));
|
|
188
|
+
const bindingOrOwner = (context, bindingId, callableId) => (bindingId === null ? undefined : context.bindingNodes.get(bindingId)) ??
|
|
189
|
+
(callableId === null
|
|
190
|
+
? context.moduleNode
|
|
191
|
+
: (context.callableNodes.get(callableId) ?? context.moduleNode));
|
|
192
|
+
const addDataUnknown = (input) => {
|
|
193
|
+
const { context, node, family, relationKinds, location, detail, candidateNodeIds, } = input;
|
|
194
|
+
addSemanticGraphUnknown(context.state, createJavaScriptSemanticGraphUnknown({
|
|
195
|
+
node_id: node.node_id,
|
|
196
|
+
family,
|
|
197
|
+
relation_kinds: relationKinds,
|
|
198
|
+
reason: "ambiguous-target",
|
|
199
|
+
detail,
|
|
200
|
+
candidate_node_ids: candidateNodeIds,
|
|
201
|
+
evidence: unknownSemanticEvidence(context.file, location),
|
|
202
|
+
}));
|
|
203
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createJavaScriptSemanticFingerprint, } from "../domain/javascriptSemanticGraph.js";
|
|
2
|
+
import { observedSemanticEvidence } from "./JavaScriptSemanticGraphEvidence.js";
|
|
3
|
+
/** Bind domain fingerprint components to exact semantic function nodes. */
|
|
4
|
+
export const projectSemanticFunctionFingerprints = (file, ir, callableNodes) => ir.functionFingerprints.flatMap((fingerprint) => {
|
|
5
|
+
const callable = callableNodes.get(fingerprint.callableId);
|
|
6
|
+
if (callable === undefined)
|
|
7
|
+
return [];
|
|
8
|
+
return [
|
|
9
|
+
createJavaScriptSemanticFingerprint({
|
|
10
|
+
function_node_id: callable.node_id,
|
|
11
|
+
algorithm: "rea.javascript-semantic-function/v1",
|
|
12
|
+
status: fingerprint.status,
|
|
13
|
+
components: {
|
|
14
|
+
parameter_arity: fingerprint.components.parameterArity,
|
|
15
|
+
normalized_ast_sha256: fingerprint.components.normalizedAstSha256,
|
|
16
|
+
control_flow_sha256: fingerprint.components.controlFlowSha256,
|
|
17
|
+
relation_shape_sha256: fingerprint.components.relationShapeSha256,
|
|
18
|
+
literal_set_sha256: fingerprint.components.literalSetSha256,
|
|
19
|
+
effects: fingerprint.components.effects,
|
|
20
|
+
},
|
|
21
|
+
limitations: fingerprint.limitations,
|
|
22
|
+
evidence: observedSemanticEvidence(file, callable.identity.source_range),
|
|
23
|
+
}),
|
|
24
|
+
];
|
|
25
|
+
});
|
|
@@ -1,7 +1,134 @@
|
|
|
1
1
|
import { createJavaScriptSemanticGraphUnknown } from "../domain/javascriptSemanticGraph.js";
|
|
2
|
-
import {
|
|
2
|
+
import { sourceRangesEqual } from "../domain/javascriptStaticAnalysisHelpers.js";
|
|
3
|
+
import { addSemanticGraphNode, addSemanticGraphRelation, addSemanticGraphUnknown, constructSemanticGraphNode, } from "./JavaScriptSemanticGraphConstruction.js";
|
|
3
4
|
import { inferredSemanticEvidenceAt, unknownSemanticEvidence, } from "./JavaScriptSemanticGraphEvidence.js";
|
|
4
5
|
import { semanticNodesWithinRange } from "./JavaScriptSemanticGraphProjection.js";
|
|
6
|
+
/** Find the retained call-site node at one exact semantic source range. */
|
|
7
|
+
export const semanticCallSiteAt = (context, location) => {
|
|
8
|
+
const call = context.ir.callSites.find(({ location: candidate }) => sourceRangesEqual(candidate, location));
|
|
9
|
+
return call === undefined
|
|
10
|
+
? undefined
|
|
11
|
+
: context.callSiteNodes.get(call.callSiteId);
|
|
12
|
+
};
|
|
13
|
+
/** Project explicit static Promise/task ownership without runtime claims. */
|
|
14
|
+
export const projectSemanticPromises = (context) => {
|
|
15
|
+
const promiseNodes = new Map(context.ir.promiseOperations.flatMap((operation) => {
|
|
16
|
+
const owner = operation.ownerCallableId === null
|
|
17
|
+
? undefined
|
|
18
|
+
: context.callableNodes.get(operation.ownerCallableId);
|
|
19
|
+
const node = addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
|
|
20
|
+
kind: operation.kind === "awaited-expression" ? "task" : "promise",
|
|
21
|
+
roleKey: operation.promiseId,
|
|
22
|
+
location: operation.location,
|
|
23
|
+
label: promiseLabel(operation),
|
|
24
|
+
functionNodeId: owner?.node_id ?? null,
|
|
25
|
+
properties: {
|
|
26
|
+
method: operation.method,
|
|
27
|
+
operation_kind: operation.kind,
|
|
28
|
+
ownership: operation.ownership,
|
|
29
|
+
source_resolution: operation.sourceResolution,
|
|
30
|
+
},
|
|
31
|
+
}, context.state));
|
|
32
|
+
return node === null ? [] : [[operation.promiseId, node]];
|
|
33
|
+
}));
|
|
34
|
+
for (const operation of context.ir.promiseOperations) {
|
|
35
|
+
const promise = promiseNodes.get(operation.promiseId);
|
|
36
|
+
if (promise === undefined)
|
|
37
|
+
continue;
|
|
38
|
+
projectPromiseCreation(context, operation, promise);
|
|
39
|
+
projectPromiseSources(context, operation, promise, promiseNodes);
|
|
40
|
+
projectPromiseOwnership(context, operation, promise);
|
|
41
|
+
if (operation.sourceResolution !== "complete" &&
|
|
42
|
+
["chain", "aggregate", "awaited-expression"].includes(operation.kind))
|
|
43
|
+
addPromiseUnknown(context, operation, promise, promiseNodes);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const promiseLabel = (operation) => operation.kind === "awaited-expression"
|
|
47
|
+
? "awaited expression"
|
|
48
|
+
: `Promise.${operation.method}`;
|
|
49
|
+
const projectPromiseCreation = (context, operation, promise) => {
|
|
50
|
+
if (operation.kind === "awaited-expression")
|
|
51
|
+
return;
|
|
52
|
+
addSemanticGraphRelation(context.state, {
|
|
53
|
+
source: semanticCallSiteAt(context, operation.location),
|
|
54
|
+
target: promise,
|
|
55
|
+
relation: "creates-promise",
|
|
56
|
+
resolution: operation.kind === "chain" || operation.sourceResolution !== "complete"
|
|
57
|
+
? "candidate"
|
|
58
|
+
: "resolved",
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
const projectPromiseSources = (context, operation, promise, promiseNodes) => {
|
|
62
|
+
for (const sourceId of operation.sourcePromiseIds) {
|
|
63
|
+
const source = promiseNodes.get(sourceId);
|
|
64
|
+
if (operation.kind === "aggregate")
|
|
65
|
+
addSemanticGraphRelation(context.state, {
|
|
66
|
+
source: promise,
|
|
67
|
+
target: source,
|
|
68
|
+
relation: "aggregates",
|
|
69
|
+
resolution: operation.sourceResolution === "complete" ? "resolved" : "candidate",
|
|
70
|
+
});
|
|
71
|
+
else
|
|
72
|
+
addSemanticGraphRelation(context.state, {
|
|
73
|
+
source,
|
|
74
|
+
target: promise,
|
|
75
|
+
relation: "chains",
|
|
76
|
+
resolution: operation.sourceResolution === "complete" ? "resolved" : "candidate",
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
const projectPromiseOwnership = (context, operation, promise) => {
|
|
81
|
+
const owner = operation.ownerCallableId === null
|
|
82
|
+
? context.moduleNode
|
|
83
|
+
: context.callableNodes.get(operation.ownerCallableId);
|
|
84
|
+
if (operation.ownership === "awaited")
|
|
85
|
+
addSemanticGraphRelation(context.state, {
|
|
86
|
+
source: owner,
|
|
87
|
+
target: promise,
|
|
88
|
+
relation: "awaits",
|
|
89
|
+
resolution: "resolved",
|
|
90
|
+
});
|
|
91
|
+
else if (operation.ownership === "assigned")
|
|
92
|
+
addSemanticGraphRelation(context.state, {
|
|
93
|
+
source: operation.ownerBindingId === null
|
|
94
|
+
? undefined
|
|
95
|
+
: context.bindingNodes.get(operation.ownerBindingId),
|
|
96
|
+
target: promise,
|
|
97
|
+
relation: "owns",
|
|
98
|
+
resolution: "resolved",
|
|
99
|
+
});
|
|
100
|
+
else if (operation.ownership === "returned")
|
|
101
|
+
addSemanticGraphRelation(context.state, {
|
|
102
|
+
source: operation.returnSiteId === null
|
|
103
|
+
? undefined
|
|
104
|
+
: context.returnSiteNodes.get(operation.returnSiteId),
|
|
105
|
+
target: promise,
|
|
106
|
+
relation: "returns-task",
|
|
107
|
+
resolution: "resolved",
|
|
108
|
+
});
|
|
109
|
+
else if (operation.ownership === "detached")
|
|
110
|
+
addSemanticGraphRelation(context.state, {
|
|
111
|
+
source: owner,
|
|
112
|
+
target: promise,
|
|
113
|
+
relation: "detaches-task",
|
|
114
|
+
resolution: "resolved",
|
|
115
|
+
});
|
|
116
|
+
};
|
|
117
|
+
const addPromiseUnknown = (context, operation, promise, promiseNodes) => {
|
|
118
|
+
const relation = operation.kind === "aggregate" ? "aggregates" : "chains";
|
|
119
|
+
addSemanticGraphUnknown(context.state, createJavaScriptSemanticGraphUnknown({
|
|
120
|
+
node_id: promise.node_id,
|
|
121
|
+
family: "promise-ownership",
|
|
122
|
+
relation_kinds: [relation],
|
|
123
|
+
reason: "ambiguous-target",
|
|
124
|
+
detail: `Static ${operation.method} source resolution was ${operation.sourceResolution}.`,
|
|
125
|
+
candidate_node_ids: operation.sourcePromiseIds.flatMap((identifier) => {
|
|
126
|
+
const candidate = promiseNodes.get(identifier);
|
|
127
|
+
return candidate === undefined ? [] : [candidate.node_id];
|
|
128
|
+
}),
|
|
129
|
+
evidence: unknownSemanticEvidence(context.file, operation.location),
|
|
130
|
+
}));
|
|
131
|
+
};
|
|
5
132
|
/** Link direct return expressions to their retained semantic references. */
|
|
6
133
|
export const projectSemanticReturnValues = (context) => {
|
|
7
134
|
for (const callable of context.ir.callables)
|
|
@@ -14,18 +141,12 @@ export const projectSemanticReturnValues = (context) => {
|
|
|
14
141
|
target: returnNode,
|
|
15
142
|
relation: "aliases",
|
|
16
143
|
resolution: site.identityReferenceLocation !== null &&
|
|
17
|
-
|
|
144
|
+
sourceRangesEqual(reference.identity.source_range, site.identityReferenceLocation)
|
|
18
145
|
? "resolved"
|
|
19
146
|
: "candidate",
|
|
20
147
|
});
|
|
21
148
|
}
|
|
22
149
|
};
|
|
23
|
-
const rangesEqual = (left, right) => left !== null &&
|
|
24
|
-
right !== null &&
|
|
25
|
-
left.start.line === right.start.line &&
|
|
26
|
-
left.start.column === right.start.column &&
|
|
27
|
-
left.end.line === right.end.line &&
|
|
28
|
-
left.end.column === right.end.column;
|
|
29
150
|
/** Link each captured binding to the callable at the exact reference site. */
|
|
30
151
|
export const projectSemanticClosureCaptures = (context) => {
|
|
31
152
|
for (const capture of context.ir.closureCaptures)
|