rea-agents 1.7.0 → 2.1.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.
Files changed (333) hide show
  1. package/README.md +112 -59
  2. package/bridge/ghidra/ReaGhidraBridge.java +96 -11
  3. package/dist/application/ArtifactExtraction.js +1 -1
  4. package/dist/application/ArtifactInventory/classify.js +42 -0
  5. package/dist/application/ArtifactInventory/hash.js +43 -0
  6. package/dist/application/ArtifactInventory/reader.js +41 -0
  7. package/dist/application/ArtifactInventory/scanCanonical.js +155 -0
  8. package/dist/application/ArtifactInventory/scanReader.js +124 -0
  9. package/dist/application/ArtifactInventory/types.js +10 -0
  10. package/dist/application/ArtifactInventory.js +9 -351
  11. package/dist/application/AuthorizedArtifactInventory.js +2 -2
  12. package/dist/application/BinarySession.js +47 -270
  13. package/dist/application/BinarySessionExecution.js +28 -0
  14. package/dist/application/BinarySessionOpen.js +39 -0
  15. package/dist/application/BinarySessionRecords.js +149 -0
  16. package/dist/application/BinarySessionStatus.js +75 -0
  17. package/dist/application/CapabilityInventory.js +42 -2
  18. package/dist/application/ClientRegistrationStatus.js +1 -1
  19. package/dist/application/CrossVersionInventory.js +8 -2
  20. package/dist/application/CrossVersionInvestigation.js +11 -29
  21. package/dist/application/CrossVersionInvestigationCollections.js +23 -0
  22. package/dist/application/DirectAnalysis.js +47 -44
  23. package/dist/application/Doctor.js +165 -197
  24. package/dist/application/DoctorDiagnostics.js +180 -0
  25. package/dist/application/ElectronBoundaryAnalysis.js +112 -0
  26. package/dist/application/ElectronBoundaryGraph.js +9 -0
  27. package/dist/application/ElectronBoundaryGraphContext.js +62 -0
  28. package/dist/application/ElectronBoundaryGraphIpc.js +242 -0
  29. package/dist/application/ElectronBoundaryGraphNative.js +86 -0
  30. package/dist/application/ElectronBoundaryGraphWindows.js +223 -0
  31. package/dist/application/EnhancedToolPagination.js +22 -0
  32. package/dist/application/EnhancedToolTypes.js +4 -0
  33. package/dist/application/EnhancedTools.js +58 -50
  34. package/dist/application/InstrumentedJavaScriptReplayHost.js +36 -0
  35. package/dist/application/InvestigationProviders.js +30 -0
  36. package/dist/application/InvestigationWorkspaceStore.js +24 -10
  37. package/dist/application/JavaScriptApplicationEvidence.js +26 -0
  38. package/dist/application/JavaScriptApplicationEvidenceGraph.js +89 -0
  39. package/dist/application/JavaScriptApplicationService.js +74 -0
  40. package/dist/application/JavaScriptApplicationWorkflowEvidence.js +29 -0
  41. package/dist/application/JavaScriptApplicationWorkflowService.js +90 -0
  42. package/dist/application/JavaScriptArtifactAnalysis.js +52 -7
  43. package/dist/application/JavaScriptArtifactFiles.js +6 -2
  44. package/dist/application/JavaScriptArtifactGraphBuilder.js +82 -17
  45. package/dist/application/JavaScriptArtifactGraphBundlers.js +225 -0
  46. package/dist/application/JavaScriptArtifactGraphContext.js +37 -36
  47. package/dist/application/JavaScriptArtifactGraphDocuments.js +27 -4
  48. package/dist/application/JavaScriptArtifactGraphEvidence.js +24 -14
  49. package/dist/application/JavaScriptArtifactGraphFindings.js +54 -8
  50. package/dist/application/JavaScriptArtifactGraphStructure.js +29 -101
  51. package/dist/application/JavaScriptArtifactPathResolution.js +269 -0
  52. package/dist/application/JavaScriptArtifactReconstruction.js +4 -1
  53. package/dist/application/JavaScriptArtifactReconstructionInput.js +2 -83
  54. package/dist/application/JavaScriptJsonModules.js +39 -0
  55. package/dist/application/JavaScriptModuleRelationships.js +262 -0
  56. package/dist/application/JavaScriptReplayPermission.js +16 -0
  57. package/dist/application/JavaScriptReplayPlanning.js +201 -0
  58. package/dist/application/JavaScriptReplayService.js +292 -0
  59. package/dist/application/JavaScriptRuntimeReconciliationEvidence.js +25 -0
  60. package/dist/application/JavaScriptRuntimeReconciliationService.js +27 -0
  61. package/dist/application/LinuxHopper.js +10 -0
  62. package/dist/application/MacHopper.js +22 -11
  63. package/dist/application/ManagedApplicationGraphService.js +55 -0
  64. package/dist/application/ManagedMemberComparisonService.js +122 -0
  65. package/dist/application/ManagedNativeVerificationService.js +39 -0
  66. package/dist/application/ManagedReconstructionService.js +58 -0
  67. package/dist/application/ManagedRuntimeCorrelationService.js +103 -0
  68. package/dist/application/NodeRuntimeCharacterizationService.js +196 -0
  69. package/dist/application/PermissionAuthority.js +106 -63
  70. package/dist/application/ProcessCaptureCapability.js +1 -1
  71. package/dist/application/ProcessCapturePermission.js +13 -0
  72. package/dist/application/ProcessCli.js +2 -12
  73. package/dist/application/ProcessHarness.js +1 -1
  74. package/dist/application/ProcessSampling.js +15 -11
  75. package/dist/application/ProjectPermissionStore.js +49 -9
  76. package/dist/application/RealHopperAssertions.js +76 -0
  77. package/dist/application/ReconstructionCoverageService.js +69 -0
  78. package/dist/application/ReconstructionCoverageWorkspaceStore.js +31 -0
  79. package/dist/application/RuntimeExecutableDiagnostics.js +172 -0
  80. package/dist/application/Setup.js +147 -259
  81. package/dist/application/SetupClientConfiguration.js +220 -0
  82. package/dist/application/SetupClients.js +24 -2
  83. package/dist/application/SetupPlan.js +123 -12
  84. package/dist/application/SetupSkill.js +26 -12
  85. package/dist/application/SupportedClients.js +1 -0
  86. package/dist/application/Uninstall.js +6 -3
  87. package/dist/application/WindowsCapabilities.js +86 -0
  88. package/dist/application/runtime.js +2 -0
  89. package/dist/artifacts/AsarArtifactReader.js +11 -0
  90. package/dist/browser/BrowserProcessStartup.js +88 -0
  91. package/dist/browser/CdpCaptureDocuments.js +12 -8
  92. package/dist/browser/CdpCaptureEventBodyShapes.js +75 -0
  93. package/dist/browser/CdpCaptureEventHandlers.js +336 -0
  94. package/dist/browser/CdpCaptureEventHelpers.js +71 -0
  95. package/dist/browser/CdpCaptureEventState.js +1 -0
  96. package/dist/browser/CdpCaptureEventTypes.js +1 -0
  97. package/dist/browser/CdpCaptureEvents.js +46 -464
  98. package/dist/browser/CdpElectronInspection.js +106 -162
  99. package/dist/browser/CdpElectronProvider.js +5 -1
  100. package/dist/browser/CdpElectronScriptEvents.js +69 -0
  101. package/dist/browser/CdpElectronScripts.js +94 -0
  102. package/dist/browser/CdpElectronWorkers.js +56 -0
  103. package/dist/browser/CdpObservationSession.js +51 -8
  104. package/dist/browser/CdpPageCapture.js +12 -129
  105. package/dist/browser/CdpPageCaptureScripts.js +97 -0
  106. package/dist/browser/CdpPageCaptureWorkers.js +46 -0
  107. package/dist/browser/CdpWebMcpDiscovery.js +38 -14
  108. package/dist/browser/PngVisualDiff.js +9 -2
  109. package/dist/catalogIdentity.js +8 -1
  110. package/dist/cli/artifactCommands.js +82 -0
  111. package/dist/cli/coreAnalysisCommands.js +232 -0
  112. package/dist/cli/managedCommands.js +397 -0
  113. package/dist/cli/managedProjectGraphCommand.js +24 -0
  114. package/dist/cli/options.js +9 -0
  115. package/dist/cli/setupCommands.js +108 -0
  116. package/dist/cli/types.js +1 -0
  117. package/dist/cli/utilityCommands.js +122 -0
  118. package/dist/cli.js +13 -383
  119. package/dist/cliApplicationCommands.js +176 -0
  120. package/dist/cliBrowserAdvancedCommands.js +73 -16
  121. package/dist/cliBrowserCommands.js +39 -115
  122. package/dist/cliCommandNames.js +17 -0
  123. package/dist/cliElectronCommands.js +100 -27
  124. package/dist/cliEvidenceCommands.js +13 -2
  125. package/dist/cliInvestigationCommands.js +53 -10
  126. package/dist/cliJsonInput.js +54 -0
  127. package/dist/cliObservationOptions.js +137 -0
  128. package/dist/cliPolicyCommands.js +80 -46
  129. package/dist/cliSetup.js +289 -0
  130. package/dist/config/environment.js +107 -0
  131. package/dist/config/parseConfig.js +228 -0
  132. package/dist/config/parsers.js +68 -0
  133. package/dist/config/permissions.js +30 -0
  134. package/dist/config/types.js +1 -0
  135. package/dist/config.js +1 -292
  136. package/dist/contracts/applicationToolContracts.js +225 -0
  137. package/dist/contracts/artifactToolContracts.js +5 -9
  138. package/dist/contracts/browserToolContracts.js +14 -62
  139. package/dist/contracts/electronToolContracts.js +45 -19
  140. package/dist/contracts/errorSchemas.js +1 -0
  141. package/dist/contracts/investigationExamples.js +0 -6
  142. package/dist/contracts/javascriptApplicationWorkflowExamples.js +46 -0
  143. package/dist/contracts/javascriptRuntimeReconciliationExample.js +208 -0
  144. package/dist/contracts/managedToolContracts.js +153 -0
  145. package/dist/contracts/managedWorkflowExamples.js +346 -0
  146. package/dist/contracts/managedWorkflowToolContracts.js +203 -0
  147. package/dist/contracts/nativeToolContracts.js +2 -6
  148. package/dist/contracts/promptContracts.js +18 -2
  149. package/dist/contracts/providerSelection.js +2 -0
  150. package/dist/contracts/toolContractExamples.js +10 -25
  151. package/dist/contracts/toolContracts.js +49 -47
  152. package/dist/contracts/toolEffects.js +174 -0
  153. package/dist/contracts/toolOutputSchemaGroups.js +232 -0
  154. package/dist/contracts/toolOutputSchemaPrimitives.js +327 -0
  155. package/dist/contracts/toolOutputSchemas.js +2 -535
  156. package/dist/doctorRuntime.js +42 -1
  157. package/dist/domain/analysisErrorPresentation.js +234 -0
  158. package/dist/domain/analysisErrorProjection.js +284 -0
  159. package/dist/domain/artifactComparison.js +37 -19
  160. package/dist/domain/binaryTarget.js +87 -37
  161. package/dist/domain/browserObservation.js +1 -282
  162. package/dist/domain/browserObservationSchemas.js +286 -0
  163. package/dist/domain/bundleComparison.js +4 -4
  164. package/dist/domain/electronObservation.js +13 -0
  165. package/dist/domain/electronStaticAnalysis.js +9 -0
  166. package/dist/domain/electronStaticAnalysisBrowser.js +206 -0
  167. package/dist/domain/electronStaticAnalysisIpc.js +171 -0
  168. package/dist/domain/electronStaticAnalysisNative.js +164 -0
  169. package/dist/domain/electronStaticAnalysisTypes.js +1 -0
  170. package/dist/domain/electronStaticAnalysisValues.js +103 -0
  171. package/dist/domain/errors.js +32 -448
  172. package/dist/domain/functionComparison.js +4 -165
  173. package/dist/domain/functionComparisonDimensions.js +164 -0
  174. package/dist/domain/functionComparisonSchemas.js +3 -8
  175. package/dist/domain/inputIssueProjection.js +52 -0
  176. package/dist/domain/javascriptApplicationAnalysis.js +155 -0
  177. package/dist/domain/javascriptApplicationChangeGraph.js +231 -0
  178. package/dist/domain/javascriptApplicationEvidenceSchemas.js +18 -0
  179. package/dist/domain/javascriptApplicationGraph.js +2 -1
  180. package/dist/domain/javascriptApplicationGraphSchemas.js +7 -0
  181. package/dist/domain/javascriptApplicationVersionComparison.js +116 -0
  182. package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +139 -0
  183. package/dist/domain/javascriptApplicationVersionItems.js +233 -0
  184. package/dist/domain/javascriptApplicationVersionKeys.js +170 -0
  185. package/dist/domain/javascriptExportInstrumentation.js +97 -0
  186. package/dist/domain/javascriptFeatureSeed.js +140 -0
  187. package/dist/domain/javascriptFeatureTrace.js +232 -0
  188. package/dist/domain/javascriptFeatureTraceSchemas.js +136 -0
  189. package/dist/domain/javascriptFeatureTraversal.js +100 -0
  190. package/dist/domain/javascriptNativeHandoff.js +85 -0
  191. package/dist/domain/javascriptReplay.js +361 -0
  192. package/dist/domain/javascriptRuntimeLoadState.js +106 -0
  193. package/dist/domain/javascriptRuntimeReconciliation.js +42 -0
  194. package/dist/domain/javascriptRuntimeReconciliationGraph.js +169 -0
  195. package/dist/domain/javascriptRuntimeReconciliationMatching.js +247 -0
  196. package/dist/domain/javascriptRuntimeReconciliationParsing.js +160 -0
  197. package/dist/domain/javascriptRuntimeReconciliationResult.js +119 -0
  198. package/dist/domain/javascriptRuntimeReconciliationRuntime.js +316 -0
  199. package/dist/domain/javascriptRuntimeReconciliationSchemas.js +245 -0
  200. package/dist/domain/javascriptRuntimeStaticCandidates.js +193 -0
  201. package/dist/domain/javascriptSemanticAnalysis.js +386 -0
  202. package/dist/domain/javascriptSemanticIr.js +30 -0
  203. package/dist/domain/javascriptSemanticProjection.js +366 -0
  204. package/dist/domain/javascriptSemanticState.js +40 -0
  205. package/dist/domain/javascriptSemanticTraversal.js +22 -0
  206. package/dist/domain/javascriptSemanticValues.js +352 -0
  207. package/dist/domain/javascriptStaticAnalysis.js +26 -254
  208. package/dist/domain/javascriptStaticAnalysisBundler.js +209 -0
  209. package/dist/domain/javascriptStaticAnalysisCalls.js +180 -0
  210. package/dist/domain/javascriptStaticAnalysisFindings.js +39 -0
  211. package/dist/domain/javascriptStaticAnalysisHelpers.js +81 -2
  212. package/dist/domain/javascriptStaticAnalysisState.js +6 -0
  213. package/dist/domain/knownPageCoverage.js +21 -0
  214. package/dist/domain/managedApplicationGraph.js +206 -0
  215. package/dist/domain/managedApplicationGraphCoverage.js +170 -0
  216. package/dist/domain/managedApplicationGraphNodeCoverage.js +6 -0
  217. package/dist/domain/managedApplicationGraphNodes.js +336 -0
  218. package/dist/domain/managedArtifact.js +452 -0
  219. package/dist/domain/managedMemberComparison.js +211 -0
  220. package/dist/domain/managedMemberComparisonCoverage.js +72 -0
  221. package/dist/domain/managedMemberComparisonMatch.js +356 -0
  222. package/dist/domain/managedNativeVerification.js +46 -0
  223. package/dist/domain/managedNativeVerificationMatch.js +272 -0
  224. package/dist/domain/managedNativeVerificationSchemas.js +141 -0
  225. package/dist/domain/managedReconstruction.js +196 -0
  226. package/dist/domain/managedRuntimeCorrelation.js +184 -0
  227. package/dist/domain/nodeRuntimeCharacterization.js +66 -0
  228. package/dist/domain/permissionPolicy.js +2 -0
  229. package/dist/domain/reconstructionCoverage.js +387 -0
  230. package/dist/domain/reconstructionCoverageEvaluation.js +212 -0
  231. package/dist/domain/reconstructionVerificationSchemas.js +9 -3
  232. package/dist/domain/runtimeCharacterization.js +85 -0
  233. package/dist/domain/webBundleAnalyzer.js +3 -409
  234. package/dist/domain/webBundleAnalyzerAst.js +77 -0
  235. package/dist/domain/webBundleAnalyzerInspection.js +307 -0
  236. package/dist/domain/webBundleAnalyzerResult.js +120 -0
  237. package/dist/dotnet/ManagedArtifactInspector.js +339 -0
  238. package/dist/dotnet/ManagedMemberInspector.js +153 -0
  239. package/dist/dotnet/ManagedMemberInspectorCore.js +297 -0
  240. package/dist/dotnet/ManagedMemberInstructionDecoder.js +427 -0
  241. package/dist/dotnet/ManagedMemberRows.js +120 -0
  242. package/dist/dotnet/ManagedMetadataHeaps.js +131 -0
  243. package/dist/dotnet/ManagedMetadataInventory.js +104 -0
  244. package/dist/dotnet/ManagedMetadataInventoryRows.js +292 -0
  245. package/dist/dotnet/ManagedMetadataLayout.js +259 -0
  246. package/dist/dotnet/ManagedMetadataRowSizes.js +54 -0
  247. package/dist/dotnet/ManagedMethodBodyReader.js +143 -0
  248. package/dist/dotnet/ManagedNativeBoundaryHelpers.js +311 -0
  249. package/dist/dotnet/ManagedNativeBoundaryInspector.js +143 -0
  250. package/dist/dotnet/ManagedPeReader.js +188 -0
  251. package/dist/dotnet/ManagedReaderFailure.js +10 -0
  252. package/dist/dotnet/ManagedStaticProvider.js +203 -0
  253. package/dist/generatedPackageMetadata.js +2 -2
  254. package/dist/ghidra/GhidraClient.js +76 -91
  255. package/dist/ghidra/GhidraClientStartup.js +29 -0
  256. package/dist/ghidra/GhidraClientWire.js +34 -0
  257. package/dist/ghidra/GhidraDefaults.js +1 -1
  258. package/dist/ghidra/GhidraDiagnostics.js +6 -1
  259. package/dist/ghidra/GhidraInstallation.js +20 -15
  260. package/dist/ghidra/GhidraLauncher.js +93 -29
  261. package/dist/ghidra/GhidraProvider.js +67 -161
  262. package/dist/ghidra/GhidraProviderCapabilities.js +173 -0
  263. package/dist/ghidra/GhidraSessionValues.js +2 -0
  264. package/dist/ghidra/GhidraSocketConnection.js +44 -7
  265. package/dist/ghidra/GhidraTargetSnapshot.js +30 -0
  266. package/dist/ghidra/GhidraTransport.js +71 -0
  267. package/dist/identity.js +3 -2
  268. package/dist/main/messages.js +5 -0
  269. package/dist/main/reload.js +49 -0
  270. package/dist/main/shutdown.js +25 -0
  271. package/dist/main/startup.js +14 -0
  272. package/dist/main/state.js +26 -0
  273. package/dist/main/transport.js +61 -0
  274. package/dist/main/types.js +1 -0
  275. package/dist/main.js +35 -132
  276. package/dist/process/PrivateRuntimeRoot.js +3 -2
  277. package/dist/process/ProcessOwnership.js +35 -0
  278. package/dist/process/ProviderProcess.js +2 -0
  279. package/dist/replay/JavaScriptReplayWorker.js +300 -0
  280. package/dist/replay/LinuxJavaScriptReplayRunner.js +217 -0
  281. package/dist/replay/LinuxJavaScriptReplaySandbox.js +140 -0
  282. package/dist/replay/LinuxRuntimeClosure.js +46 -0
  283. package/dist/replay/LinuxSeccompPolicy.js +40 -0
  284. package/dist/replay/ReplayOutcome.js +95 -0
  285. package/dist/replay/ReplayProcessLifecycle.js +71 -0
  286. package/dist/replay/ReplayWorkerProtocol.js +55 -0
  287. package/dist/replay/SystemJavaScriptReplayHost.js +182 -0
  288. package/dist/server/ProcessCaptureElicitation.js +157 -0
  289. package/dist/server/createServer.js +158 -41
  290. package/dist/server/registerApplicationTools/characterization.js +57 -0
  291. package/dist/server/registerApplicationTools/compareVersions.js +34 -0
  292. package/dist/server/registerApplicationTools/controlledReplay.js +38 -0
  293. package/dist/server/registerApplicationTools/coverage.js +84 -0
  294. package/dist/server/registerApplicationTools/helpers.js +42 -0
  295. package/dist/server/registerApplicationTools/traceFeature.js +26 -0
  296. package/dist/server/registerApplicationTools/types.js +1 -0
  297. package/dist/server/registerApplicationTools.js +13 -0
  298. package/dist/server/registerArtifactComparisonTool.js +16 -9
  299. package/dist/server/registerBrowserTools.js +61 -60
  300. package/dist/server/registerBundleComparisonTool.js +17 -20
  301. package/dist/server/registerElectronTools.js +39 -12
  302. package/dist/server/registerEnhancedTools.js +52 -15
  303. package/dist/server/registerEvidenceResources.js +54 -0
  304. package/dist/server/registerEvidenceTools.js +5 -1
  305. package/dist/server/registerFunctionComparisonTool.js +14 -7
  306. package/dist/server/registerInvestigationTools/helpers.js +74 -0
  307. package/dist/server/registerInvestigationTools/types.js +1 -0
  308. package/dist/server/registerInvestigationTools.js +103 -132
  309. package/dist/server/registerManagedTools.js +6 -0
  310. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +65 -0
  311. package/dist/server/registerManagedWorkflowTools/contract.js +8 -0
  312. package/dist/server/registerManagedWorkflowTools/evidence.js +43 -0
  313. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +39 -0
  314. package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +39 -0
  315. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +52 -0
  316. package/dist/server/registerManagedWorkflowTools/types.js +1 -0
  317. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +75 -0
  318. package/dist/server/registerManagedWorkflowTools.js +13 -0
  319. package/dist/server/registerOfficialTools.js +81 -67
  320. package/dist/server/registerProcessComparisonTool.js +25 -47
  321. package/dist/server/registerSessionRecordTools.js +137 -0
  322. package/dist/server/registerSessionStatusTool.js +9 -8
  323. package/dist/server/registerSessionTools.js +77 -216
  324. package/dist/server/sessionAvailabilityPolicy.js +10 -0
  325. package/dist/server/sessionEvidence.js +14 -19
  326. package/dist/server/toolInputValidation.js +77 -0
  327. package/dist/server/toolRegistrationOptions.js +177 -2
  328. package/dist/server/toolResult.js +30 -17
  329. package/package.json +21 -14
  330. package/scripts/rea.mjs +1 -1
  331. package/skills/{rea-analysis → reverse-engineer-anything}/SKILL.md +75 -6
  332. package/scripts/prepare-node-pty.mjs +0 -35
  333. package/scripts/rebuild-native.mjs +0 -22
@@ -0,0 +1,209 @@
1
+ import * as t from "@babel/types";
2
+ import { collectJavaScriptExports, fingerprintJavaScriptAst, } from "./javascriptAstFingerprint.js";
3
+ import { addBoundedFinding } from "./javascriptStaticAnalysisFindings.js";
4
+ import { argumentValue, calleeName, chunkRuntime, compareCodePoints, factoryRequireName, moduleFactory, modulePropertyName, range, registrationKey, sha256Text, sourceSlice, staticArrayValues, } from "./javascriptStaticAnalysisHelpers.js";
5
+ /** Inspect a bundler registration call and recover its module table. */
6
+ export const inspectBundlerRegistration = (source, call, accumulator, limits) => {
7
+ const runtime = chunkRuntime(call);
8
+ const entry = call.arguments[0];
9
+ if (runtime === undefined || !t.isArrayExpression(entry))
10
+ return;
11
+ const chunkIds = entry.elements[0];
12
+ const table = entry.elements[1];
13
+ const runtimeValue = runtimeMetadata(entry.elements[2], limits.maxFindings);
14
+ if (!t.isArrayExpression(chunkIds) || !t.isObjectExpression(table))
15
+ return;
16
+ const recovered = recoverBundlerModules(source, table, accumulator, limits);
17
+ const chunkKeys = staticArrayValues(chunkIds, Math.min(256, limits.maxFindings));
18
+ if (chunkKeys.omitted > 0) {
19
+ accumulator.droppedFindings += chunkKeys.omitted;
20
+ accumulator.structuralTruncation = true;
21
+ }
22
+ accumulator.unknownFindings += chunkKeys.unknown;
23
+ if (runtimeValue.omittedEntryModuleKeys > 0 ||
24
+ runtimeValue.omittedAsyncChunkKeys > 0 ||
25
+ recovered.omittedAsyncChunkKeys > 0) {
26
+ accumulator.droppedFindings +=
27
+ runtimeValue.omittedEntryModuleKeys +
28
+ runtimeValue.omittedAsyncChunkKeys +
29
+ recovered.omittedAsyncChunkKeys;
30
+ accumulator.structuralTruncation = true;
31
+ }
32
+ accumulator.unknownFindings +=
33
+ runtimeValue.unknownEntryModuleKeys +
34
+ runtimeValue.unknownAsyncChunkKeys +
35
+ recovered.unknownAsyncChunkKeys;
36
+ const asyncChunkKeys = boundedUniqueValues([...runtimeValue.asyncChunkKeys, ...recovered.asyncChunkKeys], Math.min(256, limits.maxFindings));
37
+ if (asyncChunkKeys.omitted > 0) {
38
+ accumulator.droppedFindings += asyncChunkKeys.omitted;
39
+ accumulator.structuralTruncation = true;
40
+ }
41
+ const registration = {
42
+ bundler: runtime.toLowerCase().includes("rspack")
43
+ ? "rspack"
44
+ : "webpack",
45
+ runtime,
46
+ chunk_keys: chunkKeys.values,
47
+ omitted_chunk_keys: chunkKeys.omitted,
48
+ unknown_chunk_keys: chunkKeys.unknown,
49
+ runtime_require_name: runtimeValue.requireName,
50
+ runtime_module_cache_status: bundlerModuleCacheStatus(source),
51
+ entry_module_keys: runtimeValue.entryModuleKeys,
52
+ omitted_entry_module_keys: runtimeValue.omittedEntryModuleKeys,
53
+ unknown_entry_module_keys: runtimeValue.unknownEntryModuleKeys,
54
+ async_chunk_keys: asyncChunkKeys.values,
55
+ omitted_async_chunk_keys: runtimeValue.omittedAsyncChunkKeys +
56
+ recovered.omittedAsyncChunkKeys +
57
+ asyncChunkKeys.omitted,
58
+ unknown_async_chunk_keys: runtimeValue.unknownAsyncChunkKeys + recovered.unknownAsyncChunkKeys,
59
+ modules: recovered.modules.sort((left, right) => compareCodePoints(left.module_key, right.module_key)),
60
+ location: range(call),
61
+ };
62
+ addBoundedFinding(accumulator, `registration\0${registrationKey(registration)}`, limits.maxFindings, () => accumulator.registrations.push(registration));
63
+ };
64
+ const recoverBundlerModules = (source, table, accumulator, limits) => {
65
+ const modules = [];
66
+ const asyncChunkKeys = [];
67
+ let omittedAsyncChunkKeys = 0;
68
+ let unknownAsyncChunkKeys = 0;
69
+ for (const property of table.properties) {
70
+ const recovered = recoverBundlerModule(source, property, accumulator, limits);
71
+ if (recovered === null)
72
+ continue;
73
+ modules.push(recovered.module);
74
+ asyncChunkKeys.push(...recovered.asyncChunkKeys);
75
+ omittedAsyncChunkKeys += recovered.omittedAsyncChunkKeys;
76
+ unknownAsyncChunkKeys += recovered.unknownAsyncChunkKeys;
77
+ }
78
+ return {
79
+ modules,
80
+ asyncChunkKeys,
81
+ omittedAsyncChunkKeys,
82
+ unknownAsyncChunkKeys,
83
+ };
84
+ };
85
+ const recoverBundlerModule = (source, property, accumulator, limits) => {
86
+ const factory = moduleFactory(property);
87
+ if (factory === undefined)
88
+ return null;
89
+ if (accumulator.moduleCount >= limits.maxModules) {
90
+ accumulator.droppedFindings += 1;
91
+ return null;
92
+ }
93
+ accumulator.moduleCount += 1;
94
+ const key = modulePropertyName(property);
95
+ if (key.startsWith("[computed@") || key.startsWith("[unknown@"))
96
+ accumulator.unknownFindings += 1;
97
+ const fingerprint = fingerprintJavaScriptAst(factory, Math.min(limits.maxAstNodes, 100_000));
98
+ const exportsValue = collectJavaScriptExports(factory, 256);
99
+ const requireName = factoryRequireName(factory);
100
+ const asyncChunks = collectBundlerAsyncChunkKeys(factory, requireName, limits.maxFindings);
101
+ if (fingerprint.truncated || exportsValue.truncated) {
102
+ accumulator.droppedFindings += 1;
103
+ accumulator.structuralTruncation = true;
104
+ }
105
+ if (typeof factory.start === "number" && typeof factory.end === "number")
106
+ accumulator.modules.push({
107
+ start: factory.start,
108
+ end: factory.end,
109
+ key,
110
+ requireName,
111
+ });
112
+ return {
113
+ module: {
114
+ module_key: key,
115
+ factory_require_name: requireName,
116
+ source_sha256: sha256Text(sourceSlice(source, factory)),
117
+ structural_fingerprint_sha256: fingerprint.truncated
118
+ ? null
119
+ : fingerprint.sha256,
120
+ structural_fingerprint_algorithm: fingerprint.truncated
121
+ ? null
122
+ : "babel-ast-v1",
123
+ structural_fingerprint_status: fingerprint.truncated
124
+ ? "truncated"
125
+ : "complete",
126
+ exports: exportsValue.values,
127
+ exports_truncated: exportsValue.truncated,
128
+ location: range(factory),
129
+ },
130
+ asyncChunkKeys: asyncChunks.values,
131
+ omittedAsyncChunkKeys: asyncChunks.omitted,
132
+ unknownAsyncChunkKeys: asyncChunks.unknown,
133
+ };
134
+ };
135
+ const runtimeMetadata = (node, maximum) => {
136
+ if (!isBundlerFunction(node))
137
+ return {
138
+ requireName: null,
139
+ entryModuleKeys: [],
140
+ omittedEntryModuleKeys: 0,
141
+ unknownEntryModuleKeys: node === null || node === undefined ? 0 : 1,
142
+ asyncChunkKeys: [],
143
+ omittedAsyncChunkKeys: 0,
144
+ unknownAsyncChunkKeys: 0,
145
+ };
146
+ const parameter = node.params[0];
147
+ const requireName = t.isIdentifier(parameter)
148
+ ? parameter.name.slice(0, 4_096)
149
+ : null;
150
+ if (requireName === null)
151
+ return {
152
+ requireName,
153
+ entryModuleKeys: [],
154
+ omittedEntryModuleKeys: 0,
155
+ unknownEntryModuleKeys: 1,
156
+ asyncChunkKeys: [],
157
+ omittedAsyncChunkKeys: 0,
158
+ unknownAsyncChunkKeys: 0,
159
+ };
160
+ const entries = collectBundlerEntryModuleKeys(node, requireName, maximum);
161
+ const asyncChunks = collectBundlerAsyncChunkKeys(node, requireName, maximum);
162
+ return {
163
+ requireName,
164
+ entryModuleKeys: entries.values,
165
+ omittedEntryModuleKeys: entries.omitted,
166
+ unknownEntryModuleKeys: entries.unknown,
167
+ asyncChunkKeys: asyncChunks.values,
168
+ omittedAsyncChunkKeys: asyncChunks.omitted,
169
+ unknownAsyncChunkKeys: asyncChunks.unknown,
170
+ };
171
+ };
172
+ const collectBundlerEntryModuleKeys = (factory, requireName, maximum) => collectBundlerCallArgumentValues(factory, requireName, maximum);
173
+ const collectBundlerAsyncChunkKeys = (factory, requireName, maximum) => requireName === null
174
+ ? { values: [], omitted: 0, unknown: 0 }
175
+ : collectBundlerCallArgumentValues(factory, `${requireName}.e`, maximum);
176
+ const collectBundlerCallArgumentValues = (factory, callee, maximum) => {
177
+ const values = [];
178
+ let unknown = 0;
179
+ t.traverseFast(factory, (node) => {
180
+ if (!t.isCallExpression(node) && !t.isNewExpression(node))
181
+ return undefined;
182
+ if (calleeName(node.callee) !== callee)
183
+ return undefined;
184
+ const value = argumentValue(node.arguments[0]);
185
+ if (value === undefined)
186
+ unknown += 1;
187
+ else
188
+ values.push(value);
189
+ return undefined;
190
+ });
191
+ return boundedUniqueValues(values, Math.min(256, maximum), unknown);
192
+ };
193
+ const isBundlerFunction = (node) => t.isFunctionExpression(node) ||
194
+ t.isArrowFunctionExpression(node) ||
195
+ t.isObjectMethod(node);
196
+ const boundedUniqueValues = (values, maximum, unknown = 0) => {
197
+ const bounded = [
198
+ ...new Set(values.map((value) => value.slice(0, 4_096))),
199
+ ].sort(compareCodePoints);
200
+ const retained = bounded.slice(0, Math.max(0, maximum));
201
+ return {
202
+ values: retained,
203
+ omitted: Math.max(0, bounded.length - retained.length),
204
+ unknown,
205
+ };
206
+ };
207
+ const bundlerModuleCacheStatus = (source) => /\b(?:__webpack_module_cache__|__rspack_module_cache__|installedModules)\b/u.test(source)
208
+ ? "observed"
209
+ : "not-observed";
@@ -0,0 +1,180 @@
1
+ import * as t from "@babel/types";
2
+ import { addBoundedFinding, addLocatedFinding, moduleAtOffset, } from "./javascriptStaticAnalysisFindings.js";
3
+ import { STATIC_ROUTE_CALL_NAMES, argumentValue, calleeName, endpointArgument as endpointArgumentHelper, prefixedArgument, propertyName, range, rangeForOffsets, sanitizeCandidate, sourceSlice, staticPath, staticPathResolutionContext, storageKind, stringValue, } from "./javascriptStaticAnalysisHelpers.js";
4
+ /** Inspect one call or new expression for references, endpoints, storage, and roles. */
5
+ export const inspectCall = (node, context) => {
6
+ const { accumulator } = context;
7
+ const name = calleeName(node.callee);
8
+ const first = stringValue(node.arguments[0]);
9
+ const module = moduleAtOffset(node.start, context.accumulator.modules);
10
+ const moduleRequireName = module?.requireName ?? null;
11
+ const requireCall = requireCallSpecifier(node, name, moduleRequireName);
12
+ if (requireCall !== null)
13
+ addReference(context, {
14
+ node,
15
+ kind: "require",
16
+ specifier: requireCall.specifier,
17
+ });
18
+ const chunkLoad = chunkLoadSpecifier(node, name, moduleRequireName);
19
+ if (chunkLoad !== null)
20
+ addReference(context, {
21
+ node,
22
+ kind: "dynamic-import",
23
+ specifier: chunkLoad.specifier,
24
+ });
25
+ if (name === "Worker" || name.endsWith(".Worker"))
26
+ addReference(context, { node, kind: "worker", specifier: first });
27
+ if (name.endsWith("serviceWorker.register"))
28
+ addReference(context, { node, kind: "service-worker", specifier: first });
29
+ inspectEndpointCall(node, name, first, context);
30
+ inspectStorageCall(node, name, first, context);
31
+ if (name.endsWith("loadFile") && first !== undefined)
32
+ addLocatedFinding(context, {
33
+ collection: accumulator.roles,
34
+ key: `role\0renderer\0${first}`,
35
+ node,
36
+ value: {
37
+ role: "renderer",
38
+ path: first,
39
+ resolution_context: "filesystem-expression",
40
+ mechanism: `call:${name}`,
41
+ module_key: null,
42
+ location: range(node),
43
+ },
44
+ });
45
+ if (name.endsWith("loadURL") && first !== undefined)
46
+ addLocatedFinding(context, {
47
+ collection: accumulator.roles,
48
+ key: `role\0renderer\0${first}`,
49
+ node,
50
+ value: {
51
+ role: "renderer",
52
+ path: first,
53
+ resolution_context: "module-specifier",
54
+ mechanism: `call:${name}`,
55
+ module_key: null,
56
+ location: range(node),
57
+ },
58
+ });
59
+ };
60
+ const requireCallSpecifier = (node, name, moduleRequireName) => {
61
+ if (name === "require" || name.endsWith(".require"))
62
+ return { specifier: argumentValue(node.arguments[0]) };
63
+ if (name === "__webpack_require__" || name === moduleRequireName)
64
+ return { specifier: argumentValue(node.arguments[0]) };
65
+ if (name === "__webpack_require__.bind" ||
66
+ (moduleRequireName !== null && name === `${moduleRequireName}.bind`))
67
+ return { specifier: argumentValue(node.arguments[1]) };
68
+ return null;
69
+ };
70
+ const chunkLoadSpecifier = (node, name, moduleRequireName) => {
71
+ if (name !== "__webpack_require__.e" &&
72
+ (moduleRequireName === null || name !== `${moduleRequireName}.e`))
73
+ return null;
74
+ return { specifier: prefixedArgument("chunk:", node.arguments[0]) };
75
+ };
76
+ const inspectEndpointCall = (node, name, first, context) => {
77
+ const route = STATIC_ROUTE_CALL_NAMES.some((candidate) => name === candidate || name.endsWith(`.${candidate}`));
78
+ if (route && first !== undefined)
79
+ addEndpoint(context, {
80
+ node,
81
+ kind: "route",
82
+ value: first,
83
+ mechanism: `call:${name}`,
84
+ });
85
+ const endpoint = endpointArgumentHelper(name, node.arguments);
86
+ if (endpoint !== undefined)
87
+ addEndpoint(context, {
88
+ node,
89
+ kind: "network",
90
+ value: endpoint,
91
+ mechanism: `call:${name}`,
92
+ });
93
+ };
94
+ export const inspectRouteProperty = (node, context) => {
95
+ const key = propertyName(node.key);
96
+ if ((key === "path" || key === "route") && t.isStringLiteral(node.value))
97
+ addEndpoint(context, {
98
+ node,
99
+ kind: "route",
100
+ value: node.value.value,
101
+ mechanism: `property:${key}`,
102
+ });
103
+ };
104
+ export const inspectRoleProperty = (node, context) => {
105
+ if (propertyName(node.key) !== "preload")
106
+ return;
107
+ const path = staticPath(node.value);
108
+ if (path === undefined)
109
+ return;
110
+ addLocatedFinding(context, {
111
+ collection: context.accumulator.roles,
112
+ key: `role\0preload\0${path}`,
113
+ node,
114
+ value: {
115
+ role: "preload",
116
+ path,
117
+ resolution_context: staticPathResolutionContext(node.value),
118
+ mechanism: "property:preload",
119
+ module_key: null,
120
+ location: range(node),
121
+ },
122
+ });
123
+ };
124
+ const inspectStorageCall = (node, name, first, context) => {
125
+ const storage = storageKind(name);
126
+ if (storage === undefined)
127
+ return;
128
+ addLocatedFinding(context, {
129
+ collection: context.accumulator.storage,
130
+ key: `storage\0${storage}\0${first ?? ""}`,
131
+ node,
132
+ value: {
133
+ kind: storage,
134
+ name: first ?? null,
135
+ mechanism: `call:${name}`,
136
+ module_key: null,
137
+ location: range(node),
138
+ },
139
+ });
140
+ };
141
+ export const addReference = (context, input) => {
142
+ const boundedSpecifier = input.specifier?.slice(0, 4_096) ?? null;
143
+ const expression = boundedSpecifier === null
144
+ ? sourceSlice(context.source, input.node).slice(0, 4_096)
145
+ : null;
146
+ addLocatedFinding(context, {
147
+ collection: context.accumulator.references,
148
+ key: `reference\0${input.kind}\0${boundedSpecifier ?? expression}`,
149
+ node: input.node,
150
+ value: {
151
+ kind: input.kind,
152
+ specifier: boundedSpecifier,
153
+ expression,
154
+ module_key: null,
155
+ location: range(input.node),
156
+ },
157
+ });
158
+ };
159
+ const addEndpoint = (context, input) => addLocatedFinding(context, {
160
+ collection: context.accumulator.endpoints,
161
+ key: `endpoint\0${input.kind}\0${input.value}`,
162
+ node: input.node,
163
+ value: {
164
+ kind: input.kind,
165
+ value: sanitizeCandidate(input.value),
166
+ mechanism: input.mechanism,
167
+ module_key: null,
168
+ location: range(input.node),
169
+ },
170
+ });
171
+ export const addSourceMapDirectives = (source, accumulator, maximum) => {
172
+ for (const match of source.matchAll(/\/\/[#@]\s*sourceMappingURL\s*=\s*([^\s]+)/gu)) {
173
+ const declared = match[1]?.slice(0, 4_096);
174
+ if (declared === undefined)
175
+ continue;
176
+ const start = match.index;
177
+ const location = rangeForOffsets(source, start, start + match[0].length);
178
+ addBoundedFinding(accumulator, `source-map\0${declared}`, maximum, () => accumulator.sourceMaps.push({ declared_url: declared, location }));
179
+ }
180
+ };
@@ -0,0 +1,39 @@
1
+ /** Add one module-attributable finding under the shared global finding bound. */
2
+ export const addLocatedFinding = (context, input) => addBoundedFinding(context.accumulator, `${input.key}\0${String(input.node.start)}`, context.maximum, () => input.collection.push({
3
+ offset: input.node.start ?? -1,
4
+ value: input.value,
5
+ }));
6
+ /** Reserve one deterministic finding key before mutating an accumulator. */
7
+ export const addBoundedFinding = (accumulator, key, maximum, add) => {
8
+ if (accumulator.seen.has(key))
9
+ return;
10
+ if (accumulatedFindingCount(accumulator) >= maximum) {
11
+ accumulator.droppedFindings += 1;
12
+ return;
13
+ }
14
+ accumulator.seen.add(key);
15
+ add();
16
+ };
17
+ /** Attach recovered bundle-module ownership to findings after traversal. */
18
+ export const finalizeLocatedFindings = (values, modules) => values.map(({ offset, value }) => ({
19
+ ...value,
20
+ module_key: moduleAtOffset(offset, modules)?.key ?? null,
21
+ }));
22
+ /** Locate the recovered bundle factory containing one exact source offset. */
23
+ export const moduleAtOffset = (offset, modules) => {
24
+ if (offset === null || offset === undefined)
25
+ return undefined;
26
+ return modules.find(({ start, end }) => offset >= start && offset <= end);
27
+ };
28
+ const accumulatedFindingCount = (accumulator) => accumulator.references.length +
29
+ accumulator.endpoints.length +
30
+ accumulator.storage.length +
31
+ accumulator.roles.length +
32
+ accumulator.sourceMaps.length +
33
+ accumulator.registrations.length +
34
+ accumulator.browserWindows.length +
35
+ accumulator.contextBridgeApis.length +
36
+ accumulator.ipc.length +
37
+ accumulator.senderValidations.length +
38
+ accumulator.utilityProcesses.length +
39
+ accumulator.nativeAddonBindings.length;
@@ -15,11 +15,21 @@ export const failedJavaScriptStaticAnalysis = () => ({
15
15
  role_paths: [],
16
16
  source_map_urls: [],
17
17
  vendors: [],
18
+ electron: {
19
+ browser_windows: [],
20
+ context_bridge_apis: [],
21
+ ipc: [],
22
+ sender_validations: [],
23
+ utility_processes: [],
24
+ native_addon_bindings: [],
25
+ },
18
26
  limitations: [
19
27
  "JavaScript source could not be parsed; absence of findings is not evidence of absence.",
20
28
  "JavaScript syntax was parsed as data and was never evaluated.",
21
29
  ],
22
30
  });
31
+ /** Normalize one Babel call/new argument into the inert node shared by inspectors. */
32
+ export const argumentNode = (argument) => argument !== null && t.isNode(argument) ? argument : undefined;
23
33
  /** Recognize the bounded runtime name for a Webpack/Rspack push call. */
24
34
  export const chunkRuntime = (call) => {
25
35
  if (!t.isMemberExpression(call.callee) &&
@@ -91,6 +101,10 @@ export const staticArrayValues = (array, maximum) => {
91
101
  };
92
102
  /** Resolve a bounded path composed only from inert literal syntax. */
93
103
  export const staticPath = (node) => staticPathAt(node, 0);
104
+ /** Classify whether inert path syntax is a module specifier or file expression. */
105
+ export const staticPathResolutionContext = (node) => isFilesystemPathExpression(node, 0)
106
+ ? "filesystem-expression"
107
+ : "module-specifier";
94
108
  const staticPathAt = (node, depth) => {
95
109
  if (depth >= 128)
96
110
  return undefined;
@@ -114,12 +128,23 @@ const staticPathAt = (node, depth) => {
114
128
  const staticCallPath = (node, depth) => {
115
129
  const name = calleeName(node.callee);
116
130
  if (name === "URL" || name.endsWith(".URL"))
117
- return stringValue(node.arguments[0]);
131
+ return isFileIdentity(argumentNode(node.arguments[1]))
132
+ ? stringValue(node.arguments[0])
133
+ : undefined;
134
+ if (name === "fileURLToPath" || name.endsWith(".fileURLToPath")) {
135
+ const argument = argumentNode(node.arguments[0]);
136
+ return argument === undefined
137
+ ? undefined
138
+ : staticPathAt(argument, depth + 1);
139
+ }
140
+ if ((name === "dirname" || name.endsWith(".dirname")) &&
141
+ isFileIdentity(argumentNode(node.arguments[0])))
142
+ return "";
118
143
  if (!name.endsWith(".join") && !name.endsWith(".resolve") && name !== "join")
119
144
  return undefined;
120
145
  const parts = [];
121
146
  for (const argument of node.arguments) {
122
- if (t.isIdentifier(argument, { name: "__dirname" }))
147
+ if (isDirectoryIdentity(argumentNode(argument)))
123
148
  continue;
124
149
  const value = t.isNode(argument)
125
150
  ? staticPathAt(argument, depth + 1)
@@ -130,6 +155,60 @@ const staticCallPath = (node, depth) => {
130
155
  }
131
156
  return parts.length === 0 ? undefined : posix.join(...parts).slice(0, 4_096);
132
157
  };
158
+ const isFilesystemPathExpression = (node, depth) => {
159
+ if (depth >= 128)
160
+ return false;
161
+ if (t.isStringLiteral(node))
162
+ return node.value.startsWith("/");
163
+ if (isFileIdentity(node) || isDirectoryIdentity(node))
164
+ return true;
165
+ if (t.isBinaryExpression(node, { operator: "+" }))
166
+ return (isFilesystemPathExpression(node.left, depth + 1) ||
167
+ isFilesystemPathExpression(node.right, depth + 1));
168
+ if (t.isCallExpression(node) || t.isNewExpression(node)) {
169
+ const name = calleeName(node.callee);
170
+ if (name === "URL" || name.endsWith(".URL"))
171
+ return isFileIdentity(argumentNode(node.arguments[1]));
172
+ if (name === "fileURLToPath" || name.endsWith(".fileURLToPath"))
173
+ return node.arguments.some((argument) => {
174
+ const value = argumentNode(argument);
175
+ return (value !== undefined && isFilesystemPathExpression(value, depth + 1));
176
+ });
177
+ return node.arguments.some((argument) => {
178
+ const value = argumentNode(argument);
179
+ return (value !== undefined && isFilesystemPathExpression(value, depth + 1));
180
+ });
181
+ }
182
+ return false;
183
+ };
184
+ const isDirectoryIdentity = (node) => {
185
+ if (t.isIdentifier(node, { name: "__dirname" }))
186
+ return true;
187
+ if (!t.isCallExpression(node) && !t.isNewExpression(node))
188
+ return false;
189
+ const name = calleeName(node.callee);
190
+ if (name === "URL" || name.endsWith(".URL"))
191
+ return isFileIdentity(argumentNode(node.arguments[1]));
192
+ return ((name === "dirname" || name.endsWith(".dirname")) &&
193
+ isFileIdentity(argumentNode(node.arguments[0])));
194
+ };
195
+ const isFileIdentity = (node) => {
196
+ if (t.isIdentifier(node, { name: "__filename" }))
197
+ return true;
198
+ if (node === undefined)
199
+ return false;
200
+ if (t.isMemberExpression(node) &&
201
+ t.isMetaProperty(node.object) &&
202
+ node.object.meta.name === "import" &&
203
+ node.object.property.name === "meta" &&
204
+ propertyName(node.property) === "url")
205
+ return true;
206
+ if (!t.isCallExpression(node))
207
+ return false;
208
+ const name = calleeName(node.callee);
209
+ return ((name === "fileURLToPath" || name.endsWith(".fileURLToPath")) &&
210
+ isFileIdentity(argumentNode(node.arguments[0])));
211
+ };
133
212
  /** Select the literal URL argument for recognized network callees. */
134
213
  export const endpointArgument = (name, args) => {
135
214
  if (name === "fetch" || name.endsWith(".fetch") || name === "WebSocket")
@@ -6,6 +6,12 @@ export const createJavaScriptAnalysisAccumulator = () => ({
6
6
  roles: [],
7
7
  sourceMaps: [],
8
8
  registrations: [],
9
+ browserWindows: [],
10
+ contextBridgeApis: [],
11
+ ipc: [],
12
+ senderValidations: [],
13
+ utilityProcesses: [],
14
+ nativeAddonBindings: [],
9
15
  modules: [],
10
16
  seen: new Set(),
11
17
  visitedNodes: 0,
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Assess source-page and downstream-projection completeness without treating an
3
+ * unreturned row as absent. `includedCount` is the number retained downstream.
4
+ */
5
+ export const assessKnownPageCoverage = (page, includedCount = page.items.length) => {
6
+ const observedCount = Math.min(page.total, page.returned, page.items.length);
7
+ const retainedCount = Math.min(observedCount, Math.max(0, Math.floor(includedCount)));
8
+ const sourceOmittedCount = Math.max(0, page.total - observedCount);
9
+ const sourceComplete = page.complete &&
10
+ page.offset === 0 &&
11
+ page.returned === page.total &&
12
+ sourceOmittedCount === 0;
13
+ const omittedCount = Math.max(0, page.total - retainedCount);
14
+ return {
15
+ complete: sourceComplete && omittedCount === 0,
16
+ sourceComplete,
17
+ includedCount: retainedCount,
18
+ omittedCount,
19
+ sourceOmittedCount,
20
+ };
21
+ };