rea-agents 2.4.0 → 3.0.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 +91 -19
- package/bridge/ghidra/ReaGhidraBridge.java +524 -4
- package/bridge/hopper_bridge.py +313 -28
- package/dist/application/AnalysisClientCleanup.js +14 -0
- package/dist/application/AnalysisContextQueries.js +130 -0
- package/dist/application/AnalysisSnapshotCache.js +4 -2
- package/dist/application/ApplicationWorkflowEvidenceResolver.js +31 -13
- package/dist/application/ArtifactInventory/scanCanonical.js +1 -1
- package/dist/application/BinarySession.js +20 -8
- package/dist/application/BinarySessionComposition.js +21 -0
- package/dist/application/BinarySessionRecords.js +79 -9
- package/dist/application/BinarySessionStatus.js +31 -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 +84 -14
- package/dist/application/ClientRegistrationStatus.js +4 -1
- package/dist/application/CompositeProvider.js +10 -1
- package/dist/application/DirectAnalysis.js +13 -4
- package/dist/application/EnhancedLiteralTracing.js +118 -0
- package/dist/application/EnhancedTools.js +71 -127
- package/dist/application/EvidenceLedger.js +45 -16
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +13 -0
- package/dist/application/JavaScriptApplicationWorkflowService.js +27 -1
- package/dist/application/JavaScriptArtifactAnalysis.js +13 -4
- 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/LazyAnalysisProvider.js +77 -0
- package/dist/application/LoopbackReplay.js +1 -1
- package/dist/application/NativeApiInspection.js +80 -0
- package/dist/application/ProcessReactiveEffects.js +6 -0
- package/dist/application/ProcessReactiveHarness.js +16 -1
- 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/application/SessionProviderRouter.js +6 -6
- package/dist/application/SetupClientConfiguration.js +4 -2
- package/dist/application/runtime.js +26 -9
- 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 +259 -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 +11 -3
- package/dist/cli/artifactCommands.js +44 -3
- package/dist/cli/coreAnalysisCommands.js +78 -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 +9 -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 +29 -2
- 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 +35 -6
- package/dist/contracts/functionInstructionContract.js +8 -0
- package/dist/contracts/functionWorkflowToolContracts.js +30 -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/promptContracts.js +14 -15
- package/dist/contracts/reconstructionReadinessExample.js +436 -0
- package/dist/contracts/toolContractExamples.js +8 -0
- package/dist/contracts/toolContractTypes.js +1 -0
- package/dist/contracts/toolContracts.js +34 -25
- package/dist/contracts/toolEffects.js +25 -0
- package/dist/contracts/toolOutputSchemaGroups.js +120 -30
- package/dist/contracts/toolOutputSchemaPrimitives.js +37 -0
- package/dist/domain/analysisErrorPresentation.js +8 -2
- package/dist/domain/analysisErrorProjection.js +9 -0
- package/dist/domain/artifactInspection.js +347 -0
- 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/bytecodeProvider.js +179 -0
- package/dist/domain/conformancePackage.js +169 -0
- package/dist/domain/conformanceReplay.js +104 -0
- package/dist/domain/conformanceTrustGate.js +193 -0
- package/dist/domain/customProtocolCapture.js +137 -0
- package/dist/domain/eventProcessTree.js +214 -0
- package/dist/domain/evidenceBundle.js +47 -0
- package/dist/domain/hopperStartupFailure.js +1 -1
- package/dist/domain/hopperValues.js +14 -1
- package/dist/domain/inputIssueProjection.js +7 -1
- 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 +13 -16
- 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/javascriptSourceParser.js +15 -0
- package/dist/domain/javascriptStaticAnalysis.js +12 -15
- package/dist/domain/javascriptStaticAnalysisBundler.js +38 -0
- package/dist/domain/javascriptStaticAnalysisCalls.js +23 -1
- package/dist/domain/javascriptStaticAnalysisHelpers.js +8 -0
- package/dist/domain/mobileApplicationInvestigation.js +159 -0
- package/dist/domain/nativeApiBoundary.js +130 -0
- package/dist/domain/objcSwiftMetadata.js +150 -0
- package/dist/domain/packageAnalysis.js +123 -0
- package/dist/domain/peInspection.js +196 -0
- package/dist/domain/processCapture.js +8 -2
- package/dist/domain/processReactiveScenario.js +1 -0
- package/dist/domain/processReactiveTransition.js +9 -4
- package/dist/domain/protocolCapture.js +243 -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/dotnet/ManagedStaticProvider.js +34 -5
- package/dist/generatedMcpToolCatalog.js +37 -0
- package/dist/generatedPackageMetadata.js +4 -4
- package/dist/ghidra/GhidraDefaults.js +1 -1
- package/dist/ghidra/GhidraFunctionValues.js +40 -2
- package/dist/ghidra/GhidraProviderCapabilities.js +47 -38
- package/dist/hopper/HopperCleanup.js +158 -0
- package/dist/hopper/HopperClient.js +93 -99
- package/dist/hopper/HopperProvider.js +61 -30
- package/dist/hopper/HopperRequestQueue.js +215 -0
- package/dist/hopper/HopperResponseStream.js +46 -0
- package/dist/hopper/protocol.js +63 -20
- package/dist/main/transport.js +24 -27
- package/dist/main.js +14 -6
- package/dist/mcpDoctor.js +27 -4
- package/dist/mcpStartupPolicy.js +14 -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/LazyToolCatalog.js +134 -0
- package/dist/server/createServer.js +92 -154
- package/dist/server/hydrateServerTools.js +191 -0
- 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 +28 -7
- package/dist/server/registerEvidenceResources.js +54 -101
- package/dist/server/registerEvidenceTools.js +9 -2
- package/dist/server/registerInvestigationTools.js +1 -2
- package/dist/server/registerJavaScriptApplicationGraphResource.js +0 -4
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +37 -0
- package/dist/server/registerReconstructionObligationLedgerResource.js +32 -0
- package/dist/server/registerReconstructionReadinessResource.js +32 -0
- package/dist/server/registerSessionRecordTools.js +82 -12
- package/dist/server/registerSessionStatusTool.js +11 -8
- package/dist/server/registerSessionTools.js +32 -58
- package/dist/server/sessionAvailabilityPolicy.js +10 -8
- package/dist/server/toolRegistrationOptions.js +21 -6
- package/dist/server/toolResult.js +12 -0
- package/package.json +28 -11
- package/scripts/package-runner-bootstrap.mjs +72 -0
- package/scripts/rea.mjs +11 -1
- package/skills/reverse-engineer-anything/SKILL.md +10 -3
|
@@ -0,0 +1,147 @@
|
|
|
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 literal EventEmitter registrations, removals, and dispatches. */
|
|
6
|
+
export const projectSemanticEvents = (context) => {
|
|
7
|
+
const eventNodes = new Map();
|
|
8
|
+
for (const operation of context.ir.eventOperations) {
|
|
9
|
+
const eventKey = operation.eventName === null
|
|
10
|
+
? operation.eventId
|
|
11
|
+
: `${operation.emitterKey}\u0000${operation.eventName}`;
|
|
12
|
+
const event = eventNodes.get(eventKey) ?? addEventNode(context, operation, eventKey);
|
|
13
|
+
if (event === null)
|
|
14
|
+
continue;
|
|
15
|
+
eventNodes.set(eventKey, event);
|
|
16
|
+
const relation = eventRelation(operation);
|
|
17
|
+
if (operation.kind === "dispatch")
|
|
18
|
+
addSemanticGraphRelation(context.state, {
|
|
19
|
+
source: eventEmitterNode(context, operation),
|
|
20
|
+
target: event,
|
|
21
|
+
relation,
|
|
22
|
+
resolution: operation.resolution === "complete" ? "resolved" : "candidate",
|
|
23
|
+
});
|
|
24
|
+
else {
|
|
25
|
+
const listener = addListenerNode(context, operation);
|
|
26
|
+
addSemanticGraphRelation(context.state, {
|
|
27
|
+
source: event,
|
|
28
|
+
target: listener,
|
|
29
|
+
relation,
|
|
30
|
+
resolution: operation.resolution === "complete" ? "resolved" : "candidate",
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (operation.resolution !== "complete")
|
|
34
|
+
addEventUnknown(context, operation, event, relation);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
const addEventNode = (context, operation, eventKey) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
|
|
38
|
+
kind: "event",
|
|
39
|
+
roleKey: `event:${eventKey}`,
|
|
40
|
+
location: operation.eventName === null ? operation.location : null,
|
|
41
|
+
label: operation.eventName,
|
|
42
|
+
functionNodeId: null,
|
|
43
|
+
properties: {
|
|
44
|
+
emitter_key: operation.emitterKey,
|
|
45
|
+
event_name: operation.eventName,
|
|
46
|
+
},
|
|
47
|
+
}, context.state));
|
|
48
|
+
const addListenerNode = (context, operation) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
|
|
49
|
+
kind: "listener",
|
|
50
|
+
roleKey: `listener:${operation.eventId}`,
|
|
51
|
+
location: operation.listenerLocation ?? operation.location,
|
|
52
|
+
label: operation.eventName === null
|
|
53
|
+
? operation.method
|
|
54
|
+
: `${operation.method}:${operation.eventName}`,
|
|
55
|
+
functionNodeId: operation.ownerCallableId === null
|
|
56
|
+
? null
|
|
57
|
+
: (context.callableNodes.get(operation.ownerCallableId)?.node_id ??
|
|
58
|
+
null),
|
|
59
|
+
properties: {
|
|
60
|
+
emitter_key: operation.emitterKey,
|
|
61
|
+
event_name: operation.eventName,
|
|
62
|
+
method: operation.method,
|
|
63
|
+
},
|
|
64
|
+
}, context.state));
|
|
65
|
+
const eventEmitterNode = (context, operation) => (operation.emitterBindingId === null
|
|
66
|
+
? undefined
|
|
67
|
+
: context.bindingNodes.get(operation.emitterBindingId)) ??
|
|
68
|
+
(operation.ownerCallableId === null
|
|
69
|
+
? context.moduleNode
|
|
70
|
+
: (context.callableNodes.get(operation.ownerCallableId) ??
|
|
71
|
+
context.moduleNode));
|
|
72
|
+
const eventRelation = (operation) => operation.kind === "register"
|
|
73
|
+
? "registers-listener"
|
|
74
|
+
: operation.kind === "remove"
|
|
75
|
+
? "removes-listener"
|
|
76
|
+
: "dispatches-candidate";
|
|
77
|
+
const addEventUnknown = (context, operation, event, relation) => {
|
|
78
|
+
addSemanticGraphUnknown(context.state, createJavaScriptSemanticGraphUnknown({
|
|
79
|
+
node_id: event.node_id,
|
|
80
|
+
family: "event",
|
|
81
|
+
relation_kinds: [relation],
|
|
82
|
+
reason: "ambiguous-target",
|
|
83
|
+
detail: operation.eventName === null
|
|
84
|
+
? `Dynamic ${operation.method} event name remains unresolved.`
|
|
85
|
+
: `Static ${operation.method} emitter identity is partial.`,
|
|
86
|
+
candidate_node_ids: [],
|
|
87
|
+
evidence: unknownSemanticEvidence(context.file, operation.location),
|
|
88
|
+
}));
|
|
89
|
+
};
|
|
90
|
+
/** Project Node timer scheduling and exact local handle cancellation. */
|
|
91
|
+
export const projectSemanticTimers = (context) => {
|
|
92
|
+
const timerNodes = new Map(context.ir.timerOperations.flatMap((operation) => {
|
|
93
|
+
if (operation.kind !== "schedule")
|
|
94
|
+
return [];
|
|
95
|
+
const owner = operation.ownerCallableId === null
|
|
96
|
+
? undefined
|
|
97
|
+
: context.callableNodes.get(operation.ownerCallableId);
|
|
98
|
+
const timer = addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
|
|
99
|
+
kind: "timer",
|
|
100
|
+
roleKey: operation.timerId,
|
|
101
|
+
location: operation.location,
|
|
102
|
+
label: operation.method,
|
|
103
|
+
functionNodeId: owner?.node_id ?? null,
|
|
104
|
+
properties: {
|
|
105
|
+
delay_milliseconds: operation.delayMilliseconds,
|
|
106
|
+
method: operation.method,
|
|
107
|
+
},
|
|
108
|
+
}, context.state));
|
|
109
|
+
return timer === null ? [] : [[operation.timerId, timer]];
|
|
110
|
+
}));
|
|
111
|
+
for (const operation of context.ir.timerOperations)
|
|
112
|
+
if (operation.kind === "schedule")
|
|
113
|
+
projectTimerSchedule(context, operation, timerNodes);
|
|
114
|
+
else
|
|
115
|
+
projectTimerCancellation(context, operation, timerNodes);
|
|
116
|
+
};
|
|
117
|
+
const projectTimerSchedule = (context, operation, timerNodes) => {
|
|
118
|
+
addSemanticGraphRelation(context.state, {
|
|
119
|
+
source: semanticCallSiteAt(context, operation.location),
|
|
120
|
+
target: timerNodes.get(operation.timerId),
|
|
121
|
+
relation: "schedules-timer",
|
|
122
|
+
resolution: "resolved",
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
const projectTimerCancellation = (context, operation, timerNodes) => {
|
|
126
|
+
const callSite = semanticCallSiteAt(context, operation.location);
|
|
127
|
+
const target = operation.linkedTimerId === null
|
|
128
|
+
? undefined
|
|
129
|
+
: timerNodes.get(operation.linkedTimerId);
|
|
130
|
+
addSemanticGraphRelation(context.state, {
|
|
131
|
+
source: callSite,
|
|
132
|
+
target,
|
|
133
|
+
relation: "cancels-timer",
|
|
134
|
+
resolution: operation.resolution === "complete" ? "resolved" : "candidate",
|
|
135
|
+
});
|
|
136
|
+
if (operation.resolution === "complete")
|
|
137
|
+
return;
|
|
138
|
+
addSemanticGraphUnknown(context.state, createJavaScriptSemanticGraphUnknown({
|
|
139
|
+
node_id: callSite?.node_id ?? null,
|
|
140
|
+
family: "timer",
|
|
141
|
+
relation_kinds: ["cancels-timer"],
|
|
142
|
+
reason: "ambiguous-target",
|
|
143
|
+
detail: `Static ${operation.method} handle resolution was ${operation.resolution}.`,
|
|
144
|
+
candidate_node_ids: [],
|
|
145
|
+
evidence: unknownSemanticEvidence(context.file, operation.location),
|
|
146
|
+
}));
|
|
147
|
+
};
|
|
@@ -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
|
+
});
|