rea-agents 2.0.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.
- package/README.md +78 -32
- package/bridge/ghidra/ReaGhidraBridge.java +96 -11
- package/dist/application/ArtifactExtraction.js +1 -1
- package/dist/application/ArtifactInventory/classify.js +42 -0
- package/dist/application/ArtifactInventory/hash.js +43 -0
- package/dist/application/ArtifactInventory/reader.js +41 -0
- package/dist/application/ArtifactInventory/scanCanonical.js +155 -0
- package/dist/application/ArtifactInventory/scanReader.js +124 -0
- package/dist/application/ArtifactInventory/types.js +10 -0
- package/dist/application/ArtifactInventory.js +9 -351
- package/dist/application/AuthorizedArtifactInventory.js +2 -2
- package/dist/application/BinarySession.js +47 -270
- package/dist/application/BinarySessionExecution.js +28 -0
- package/dist/application/BinarySessionOpen.js +39 -0
- package/dist/application/BinarySessionRecords.js +149 -0
- package/dist/application/BinarySessionStatus.js +75 -0
- package/dist/application/CapabilityInventory.js +24 -2
- package/dist/application/ClientRegistrationStatus.js +1 -1
- package/dist/application/CrossVersionInventory.js +8 -2
- package/dist/application/CrossVersionInvestigation.js +1 -23
- package/dist/application/CrossVersionInvestigationCollections.js +23 -0
- package/dist/application/DirectAnalysis.js +47 -44
- package/dist/application/Doctor.js +156 -238
- package/dist/application/DoctorDiagnostics.js +180 -0
- package/dist/application/ElectronBoundaryAnalysis.js +23 -7
- package/dist/application/ElectronBoundaryGraphWindows.js +32 -8
- package/dist/application/EnhancedToolPagination.js +22 -0
- package/dist/application/EnhancedToolTypes.js +4 -0
- package/dist/application/EnhancedTools.js +20 -37
- package/dist/application/InstrumentedJavaScriptReplayHost.js +36 -0
- package/dist/application/InvestigationWorkspaceStore.js +24 -10
- package/dist/application/JavaScriptArtifactAnalysis.js +45 -6
- package/dist/application/JavaScriptArtifactFiles.js +6 -2
- package/dist/application/JavaScriptArtifactGraphBuilder.js +23 -1
- package/dist/application/JavaScriptArtifactGraphBundlers.js +225 -0
- package/dist/application/JavaScriptArtifactGraphContext.js +37 -36
- package/dist/application/JavaScriptArtifactGraphDocuments.js +27 -4
- package/dist/application/JavaScriptArtifactGraphFindings.js +54 -8
- package/dist/application/JavaScriptArtifactGraphStructure.js +29 -101
- package/dist/application/JavaScriptArtifactPathResolution.js +269 -0
- package/dist/application/JavaScriptArtifactReconstruction.js +1 -1
- package/dist/application/JavaScriptJsonModules.js +39 -0
- package/dist/application/JavaScriptModuleRelationships.js +262 -0
- package/dist/application/JavaScriptReplayPermission.js +16 -0
- package/dist/application/JavaScriptReplayService.js +182 -156
- package/dist/application/LinuxHopper.js +10 -0
- package/dist/application/MacHopper.js +22 -11
- package/dist/application/NodeRuntimeCharacterizationService.js +196 -0
- package/dist/application/PermissionAuthority.js +106 -63
- package/dist/application/ProcessCaptureCapability.js +1 -1
- package/dist/application/ProcessCapturePermission.js +13 -0
- package/dist/application/ProcessCli.js +2 -12
- package/dist/application/ProcessHarness.js +1 -1
- package/dist/application/ProjectPermissionStore.js +48 -9
- package/dist/application/RealHopperAssertions.js +76 -0
- package/dist/application/ReconstructionCoverageService.js +69 -0
- package/dist/application/ReconstructionCoverageWorkspaceStore.js +31 -0
- package/dist/application/RuntimeExecutableDiagnostics.js +172 -0
- package/dist/application/Setup.js +147 -259
- package/dist/application/SetupClientConfiguration.js +220 -0
- package/dist/application/SetupClients.js +24 -2
- package/dist/application/SetupPlan.js +123 -12
- package/dist/application/SetupSkill.js +26 -12
- package/dist/application/SupportedClients.js +1 -0
- package/dist/application/Uninstall.js +6 -3
- package/dist/application/WindowsCapabilities.js +86 -0
- package/dist/artifacts/AsarArtifactReader.js +11 -0
- package/dist/browser/BrowserProcessStartup.js +88 -0
- package/dist/browser/CdpCaptureDocuments.js +12 -8
- package/dist/browser/CdpCaptureEventBodyShapes.js +75 -0
- package/dist/browser/CdpCaptureEventHandlers.js +336 -0
- package/dist/browser/CdpCaptureEventHelpers.js +71 -0
- package/dist/browser/CdpCaptureEventState.js +1 -0
- package/dist/browser/CdpCaptureEventTypes.js +1 -0
- package/dist/browser/CdpCaptureEvents.js +29 -496
- package/dist/browser/CdpObservationSession.js +51 -8
- package/dist/browser/CdpPageCapture.js +12 -133
- package/dist/browser/CdpPageCaptureScripts.js +97 -0
- package/dist/browser/CdpPageCaptureWorkers.js +46 -0
- package/dist/browser/CdpWebMcpDiscovery.js +38 -14
- package/dist/browser/PngVisualDiff.js +9 -2
- package/dist/catalogIdentity.js +4 -0
- package/dist/cli/artifactCommands.js +82 -0
- package/dist/cli/coreAnalysisCommands.js +232 -0
- package/dist/cli/managedCommands.js +397 -0
- package/dist/cli/managedProjectGraphCommand.js +24 -0
- package/dist/cli/options.js +9 -0
- package/dist/cli/setupCommands.js +108 -0
- package/dist/cli/types.js +1 -0
- package/dist/cli/utilityCommands.js +122 -0
- package/dist/cli.js +10 -768
- package/dist/cliApplicationCommands.js +118 -4
- package/dist/cliBrowserAdvancedCommands.js +73 -16
- package/dist/cliBrowserCommands.js +39 -115
- package/dist/cliCommandNames.js +4 -0
- package/dist/cliElectronCommands.js +33 -62
- package/dist/cliEvidenceCommands.js +13 -2
- package/dist/cliInvestigationCommands.js +53 -10
- package/dist/cliObservationOptions.js +137 -0
- package/dist/cliPolicyCommands.js +80 -46
- package/dist/cliSetup.js +289 -0
- package/dist/config/environment.js +107 -0
- package/dist/config/parseConfig.js +228 -0
- package/dist/config/parsers.js +68 -0
- package/dist/config/permissions.js +30 -0
- package/dist/config/types.js +1 -0
- package/dist/config.js +1 -375
- package/dist/contracts/applicationToolContracts.js +134 -0
- package/dist/contracts/managedToolContracts.js +1 -1
- package/dist/contracts/managedWorkflowToolContracts.js +3 -3
- package/dist/contracts/providerSelection.js +2 -0
- package/dist/contracts/toolContracts.js +2 -2
- package/dist/contracts/toolEffects.js +14 -0
- package/dist/contracts/toolOutputSchemaGroups.js +232 -0
- package/dist/contracts/toolOutputSchemaPrimitives.js +327 -0
- package/dist/contracts/toolOutputSchemas.js +2 -550
- package/dist/domain/analysisErrorPresentation.js +234 -0
- package/dist/domain/analysisErrorProjection.js +284 -0
- package/dist/domain/artifactComparison.js +34 -15
- package/dist/domain/binaryTarget.js +87 -37
- package/dist/domain/browserObservation.js +1 -285
- package/dist/domain/browserObservationSchemas.js +286 -0
- package/dist/domain/electronStaticAnalysisBrowser.js +14 -2
- package/dist/domain/errors.js +4 -486
- package/dist/domain/functionComparison.js +4 -165
- package/dist/domain/functionComparisonDimensions.js +164 -0
- package/dist/domain/javascriptApplicationVersionItems.js +18 -6
- package/dist/domain/javascriptApplicationVersionKeys.js +8 -8
- package/dist/domain/javascriptExportInstrumentation.js +97 -0
- package/dist/domain/javascriptFeatureTraversal.js +19 -7
- package/dist/domain/javascriptRuntimeStaticCandidates.js +3 -1
- package/dist/domain/javascriptSemanticAnalysis.js +386 -0
- package/dist/domain/javascriptSemanticIr.js +30 -0
- package/dist/domain/javascriptSemanticProjection.js +366 -0
- package/dist/domain/javascriptSemanticState.js +40 -0
- package/dist/domain/javascriptSemanticTraversal.js +22 -0
- package/dist/domain/javascriptSemanticValues.js +352 -0
- package/dist/domain/javascriptStaticAnalysis.js +5 -221
- package/dist/domain/javascriptStaticAnalysisBundler.js +209 -0
- package/dist/domain/javascriptStaticAnalysisCalls.js +180 -0
- package/dist/domain/javascriptStaticAnalysisHelpers.js +71 -2
- package/dist/domain/knownPageCoverage.js +21 -0
- package/dist/domain/managedApplicationGraph.js +14 -364
- package/dist/domain/managedApplicationGraphCoverage.js +170 -0
- package/dist/domain/managedApplicationGraphNodeCoverage.js +6 -0
- package/dist/domain/managedApplicationGraphNodes.js +336 -0
- package/dist/domain/managedArtifact.js +16 -8
- package/dist/domain/managedMemberComparison.js +37 -391
- package/dist/domain/managedMemberComparisonCoverage.js +72 -0
- package/dist/domain/managedMemberComparisonMatch.js +356 -0
- package/dist/domain/managedNativeVerification.js +27 -389
- package/dist/domain/managedNativeVerificationMatch.js +272 -0
- package/dist/domain/managedNativeVerificationSchemas.js +141 -0
- package/dist/domain/managedReconstruction.js +82 -69
- package/dist/domain/managedRuntimeCorrelation.js +12 -3
- package/dist/domain/nodeRuntimeCharacterization.js +66 -0
- package/dist/domain/permissionPolicy.js +2 -0
- package/dist/domain/reconstructionCoverage.js +387 -0
- package/dist/domain/reconstructionCoverageEvaluation.js +212 -0
- package/dist/domain/reconstructionVerificationSchemas.js +8 -0
- package/dist/domain/runtimeCharacterization.js +85 -0
- package/dist/domain/webBundleAnalyzer.js +3 -409
- package/dist/domain/webBundleAnalyzerAst.js +77 -0
- package/dist/domain/webBundleAnalyzerInspection.js +307 -0
- package/dist/domain/webBundleAnalyzerResult.js +120 -0
- package/dist/dotnet/ManagedArtifactInspector.js +50 -29
- package/dist/dotnet/ManagedMemberInspector.js +51 -785
- package/dist/dotnet/ManagedMemberInspectorCore.js +297 -0
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +427 -0
- package/dist/dotnet/ManagedMemberRows.js +120 -0
- package/dist/dotnet/ManagedMetadataInventory.js +42 -306
- package/dist/dotnet/ManagedMetadataInventoryRows.js +292 -0
- package/dist/dotnet/ManagedMetadataLayout.js +48 -111
- package/dist/dotnet/ManagedMetadataRowSizes.js +54 -0
- package/dist/dotnet/ManagedMethodBodyReader.js +143 -0
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +311 -0
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +102 -350
- package/dist/dotnet/ManagedPeReader.js +59 -28
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraClient.js +76 -91
- package/dist/ghidra/GhidraClientStartup.js +29 -0
- package/dist/ghidra/GhidraClientWire.js +34 -0
- package/dist/ghidra/GhidraDefaults.js +1 -1
- package/dist/ghidra/GhidraDiagnostics.js +6 -1
- package/dist/ghidra/GhidraInstallation.js +20 -15
- package/dist/ghidra/GhidraLauncher.js +93 -29
- package/dist/ghidra/GhidraProvider.js +61 -161
- package/dist/ghidra/GhidraProviderCapabilities.js +173 -0
- package/dist/ghidra/GhidraSessionValues.js +2 -0
- package/dist/ghidra/GhidraSocketConnection.js +44 -7
- package/dist/ghidra/GhidraTargetSnapshot.js +30 -0
- package/dist/ghidra/GhidraTransport.js +71 -0
- package/dist/identity.js +3 -2
- package/dist/main/messages.js +5 -0
- package/dist/main/reload.js +49 -0
- package/dist/main/shutdown.js +25 -0
- package/dist/main/startup.js +14 -0
- package/dist/main/state.js +26 -0
- package/dist/main/transport.js +61 -0
- package/dist/main/types.js +1 -0
- package/dist/main.js +35 -146
- package/dist/process/PrivateRuntimeRoot.js +3 -2
- package/dist/process/ProcessOwnership.js +35 -0
- package/dist/process/ProviderProcess.js +2 -0
- package/dist/replay/JavaScriptReplayWorker.js +64 -50
- package/dist/replay/LinuxJavaScriptReplayRunner.js +173 -390
- package/dist/replay/LinuxJavaScriptReplaySandbox.js +140 -0
- package/dist/replay/ReplayOutcome.js +95 -0
- package/dist/replay/ReplayProcessLifecycle.js +71 -0
- package/dist/server/ProcessCaptureElicitation.js +157 -0
- package/dist/server/createServer.js +119 -54
- package/dist/server/registerApplicationTools/characterization.js +57 -0
- package/dist/server/registerApplicationTools/compareVersions.js +34 -0
- package/dist/server/registerApplicationTools/controlledReplay.js +38 -0
- package/dist/server/registerApplicationTools/coverage.js +84 -0
- package/dist/server/registerApplicationTools/helpers.js +42 -0
- package/dist/server/registerApplicationTools/traceFeature.js +26 -0
- package/dist/server/registerApplicationTools/types.js +1 -0
- package/dist/server/registerApplicationTools.js +10 -112
- package/dist/server/registerBrowserTools.js +59 -83
- package/dist/server/registerElectronTools.js +31 -46
- package/dist/server/registerEnhancedTools.js +34 -42
- package/dist/server/registerEvidenceResources.js +54 -0
- package/dist/server/registerInvestigationTools/helpers.js +74 -0
- package/dist/server/registerInvestigationTools/types.js +1 -0
- package/dist/server/registerInvestigationTools.js +83 -116
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +65 -0
- package/dist/server/registerManagedWorkflowTools/contract.js +8 -0
- package/dist/server/registerManagedWorkflowTools/evidence.js +43 -0
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +39 -0
- package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +39 -0
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +52 -0
- package/dist/server/registerManagedWorkflowTools/types.js +1 -0
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +75 -0
- package/dist/server/registerManagedWorkflowTools.js +10 -274
- package/dist/server/registerOfficialTools.js +73 -59
- package/dist/server/registerSessionRecordTools.js +137 -0
- package/dist/server/registerSessionStatusTool.js +2 -1
- package/dist/server/registerSessionTools.js +60 -164
- package/dist/server/sessionAvailabilityPolicy.js +10 -0
- package/dist/server/toolRegistrationOptions.js +101 -3
- package/dist/server/toolResult.js +5 -0
- package/package.json +10 -11
- package/skills/{rea-analysis → reverse-engineer-anything}/SKILL.md +20 -7
- package/scripts/prepare-node-pty.mjs +0 -35
- package/scripts/rebuild-native.mjs +0 -22
|
@@ -3,6 +3,7 @@ import { JavaScriptArtifactGraphAccumulator } from "./JavaScriptArtifactGraphAcc
|
|
|
3
3
|
import { javaScriptAnalysisLimits, } from "./JavaScriptArtifactGraphContext.js";
|
|
4
4
|
import { addJavaScriptHtmlRoles, addJavaScriptSourceMapOriginals, } from "./JavaScriptArtifactGraphDocuments.js";
|
|
5
5
|
import { addJavaScriptStaticFindings } from "./JavaScriptArtifactGraphFindings.js";
|
|
6
|
+
import { addJavaScriptModuleRelationships, addJavaScriptSourceModules, } from "./JavaScriptModuleRelationships.js";
|
|
6
7
|
import { completeReconstructionCoverage, partialReconstructionCoverage, } from "./JavaScriptArtifactGraphEvidence.js";
|
|
7
8
|
import { addJavaScriptArtifactContainers, addJavaScriptArtifactFiles, addJavaScriptBundlerNodes, addJavaScriptPackageNodes, createJavaScriptArtifactRootNode, } from "./JavaScriptArtifactGraphStructure.js";
|
|
8
9
|
import { addElectronBoundaries } from "./ElectronBoundaryGraph.js";
|
|
@@ -21,13 +22,17 @@ export const buildJavaScriptArtifactGraph = (snapshot, fileSet, analysis, input)
|
|
|
21
22
|
filesByPath: new Map(fileSet.files.map((file) => [file.path, file])),
|
|
22
23
|
fileNodes: new Map(),
|
|
23
24
|
assetNodes: new Map(),
|
|
25
|
+
sourceModuleNodes: new Map(),
|
|
26
|
+
chunkNodes: new Map(),
|
|
24
27
|
moduleNodes: new Map(),
|
|
25
28
|
containerNodes: new Map([[snapshot.manifest.root_sha256, root]]),
|
|
26
29
|
};
|
|
27
30
|
addJavaScriptArtifactContainers(context);
|
|
28
31
|
addJavaScriptArtifactFiles(context);
|
|
29
32
|
const packageRoots = addJavaScriptPackageNodes(context);
|
|
33
|
+
addJavaScriptSourceModules(context);
|
|
30
34
|
addJavaScriptBundlerNodes(context);
|
|
35
|
+
addJavaScriptModuleRelationships(context);
|
|
31
36
|
addJavaScriptStaticFindings(context);
|
|
32
37
|
addElectronBoundaries(context);
|
|
33
38
|
addJavaScriptHtmlRoles(context);
|
|
@@ -50,6 +55,7 @@ const graphCoverage = (context) => {
|
|
|
50
55
|
context.accumulator.omittedObservations();
|
|
51
56
|
const sourceMapPolicyGap = context.analysis.source_maps.some(({ status }) => status === "not-approved");
|
|
52
57
|
const malformedStructuredData = context.analysis.packages.some(({ status }) => status !== "included") ||
|
|
58
|
+
context.analysis.json_modules.some(({ status }) => status !== "included") ||
|
|
53
59
|
context.analysis.source_maps.some(({ status }) => status === "invalid");
|
|
54
60
|
const partialJavaScript = context.analysis.files.some(({ javascript }) => javascript !== null && javascript.parse_status === "partial");
|
|
55
61
|
const unknownGap = context.analysis.parse_failures > 0 ||
|
|
@@ -58,13 +64,28 @@ const graphCoverage = (context) => {
|
|
|
58
64
|
malformedStructuredData ||
|
|
59
65
|
partialJavaScript;
|
|
60
66
|
if (context.analysis.truncated_scopes > 0)
|
|
61
|
-
return partialReconstructionCoverage(reconstructionLimits(context.input),
|
|
67
|
+
return partialReconstructionCoverage(reconstructionLimits(context.input), truncationOmittedCount(context), true);
|
|
62
68
|
if (exactLimitOmissions > 0)
|
|
63
69
|
return partialReconstructionCoverage(reconstructionLimits(context.input), exactLimitOmissions, true);
|
|
64
70
|
if (unknownGap)
|
|
65
71
|
return partialReconstructionCoverage(reconstructionLimits(context.input), null, false);
|
|
66
72
|
return completeReconstructionCoverage(reconstructionLimits(context.input));
|
|
67
73
|
};
|
|
74
|
+
const truncationOmittedCount = (context) => {
|
|
75
|
+
const staticTruncations = context.analysis.files.filter(({ javascript }) => javascript?.parse_status === "truncated");
|
|
76
|
+
if (staticTruncations.length > 0)
|
|
77
|
+
return null;
|
|
78
|
+
const semanticTruncations = context.analysis.files.flatMap(({ semantic }) => semantic?.ir.coverage.status === "truncated" ? [semantic.ir.coverage] : []);
|
|
79
|
+
const sourceMapTruncations = context.analysis.source_maps.filter(({ status }) => status === "truncated");
|
|
80
|
+
if (sourceMapTruncations.length > 0)
|
|
81
|
+
return null;
|
|
82
|
+
if (semanticTruncations.length !== context.analysis.truncated_scopes)
|
|
83
|
+
return null;
|
|
84
|
+
const omissions = semanticTruncations.map(({ omittedCount }) => omittedCount);
|
|
85
|
+
return omissions.some((omitted) => omitted === null)
|
|
86
|
+
? null
|
|
87
|
+
: omissions.reduce((total, omitted) => total + (omitted ?? 0), 0);
|
|
88
|
+
};
|
|
68
89
|
const graphLimitations = (context, coverage) => {
|
|
69
90
|
const ipc = collectElectronIpcRecords(context.analysis);
|
|
70
91
|
const pairings = classifyElectronIpcPairings(ipc);
|
|
@@ -79,6 +100,7 @@ const graphLimitations = (context, coverage) => {
|
|
|
79
100
|
javascript.electron.native_addon_bindings.length), 0);
|
|
80
101
|
return [
|
|
81
102
|
...context.analysis.limitations,
|
|
103
|
+
"CommonJS and ESM binding relationships were recovered from inert syntax and resolved only within the inventoried artifact container.",
|
|
82
104
|
"Webpack/Rspack factories were recovered from AST literals; REA did not invoke push handlers or bundle bootstrap code.",
|
|
83
105
|
"Static imports, entrypoints, workers, endpoints, and storage relationships do not prove runtime execution.",
|
|
84
106
|
...(electronFindings === 0
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { addAstContainsEdge, artifactLocalIdentity, chunkLookupKey, javascriptAnalysisCoverage, moduleLookupKey, } from "./JavaScriptArtifactGraphContext.js";
|
|
2
|
+
import { astObservationEvidence, staticInferenceEvidence, } from "./JavaScriptArtifactGraphEvidence.js";
|
|
3
|
+
/** Project Webpack/Rspack chunk and factory literals recovered from AST. */
|
|
4
|
+
export const addJavaScriptBundlerNodes = (context) => {
|
|
5
|
+
for (const analyzed of context.analysis.files) {
|
|
6
|
+
const { file, javascript } = analyzed;
|
|
7
|
+
const asset = context.assetNodes.get(file.path);
|
|
8
|
+
if (javascript === null || asset === undefined)
|
|
9
|
+
continue;
|
|
10
|
+
const coverage = javascriptAnalysisCoverage(javascript, context.input);
|
|
11
|
+
const records = [];
|
|
12
|
+
for (const registration of javascript.bundler_registrations) {
|
|
13
|
+
const input = {
|
|
14
|
+
file,
|
|
15
|
+
registration,
|
|
16
|
+
coverage,
|
|
17
|
+
limitations: javascript.limitations,
|
|
18
|
+
};
|
|
19
|
+
const chunk = createBundlerChunkNode(context, input);
|
|
20
|
+
addAstContainsEdge(context, {
|
|
21
|
+
source: asset,
|
|
22
|
+
target: chunk,
|
|
23
|
+
file,
|
|
24
|
+
range: registration.location,
|
|
25
|
+
coverage,
|
|
26
|
+
properties: { bundler: registration.bundler },
|
|
27
|
+
});
|
|
28
|
+
for (const key of registration.chunk_keys)
|
|
29
|
+
context.chunkNodes.set(chunkLookupKey(file.path, registration.runtime, key), chunk);
|
|
30
|
+
records.push({ file, registration, chunk, coverage });
|
|
31
|
+
addBundlerModuleNodes(context, { ...input, chunk });
|
|
32
|
+
}
|
|
33
|
+
for (const record of records)
|
|
34
|
+
addBundlerRuntimeEdges(context, record);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
const createBundlerChunkNode = (context, input) => {
|
|
38
|
+
const { file, registration, coverage, limitations } = input;
|
|
39
|
+
const chunkKey = `${registration.runtime}:${registration.chunk_keys.join(",")}`;
|
|
40
|
+
return context.accumulator.addNode({
|
|
41
|
+
kind: "javascript-chunk",
|
|
42
|
+
identity: artifactLocalIdentity(file.sha256, "bundler-chunk", chunkKey),
|
|
43
|
+
observations: [
|
|
44
|
+
{
|
|
45
|
+
label: chunkKey,
|
|
46
|
+
properties: {
|
|
47
|
+
path: file.path,
|
|
48
|
+
bundler: registration.bundler,
|
|
49
|
+
runtime: registration.runtime,
|
|
50
|
+
chunk_keys: registration.chunk_keys,
|
|
51
|
+
omitted_chunk_keys: registration.omitted_chunk_keys,
|
|
52
|
+
unknown_chunk_keys: registration.unknown_chunk_keys,
|
|
53
|
+
runtime_require_name: registration.runtime_require_name,
|
|
54
|
+
runtime_module_cache_status: registration.runtime_module_cache_status,
|
|
55
|
+
entry_module_keys: registration.entry_module_keys,
|
|
56
|
+
omitted_entry_module_keys: registration.omitted_entry_module_keys,
|
|
57
|
+
unknown_entry_module_keys: registration.unknown_entry_module_keys,
|
|
58
|
+
async_chunk_keys: registration.async_chunk_keys,
|
|
59
|
+
omitted_async_chunk_keys: registration.omitted_async_chunk_keys,
|
|
60
|
+
unknown_async_chunk_keys: registration.unknown_async_chunk_keys,
|
|
61
|
+
module_count: registration.modules.length,
|
|
62
|
+
},
|
|
63
|
+
evidence: astObservationEvidence({
|
|
64
|
+
sha256: file.sha256,
|
|
65
|
+
path: file.path,
|
|
66
|
+
range: registration.location,
|
|
67
|
+
operation: "extract-bundler-registration",
|
|
68
|
+
coverage,
|
|
69
|
+
limitations,
|
|
70
|
+
}),
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
const addBundlerModuleNodes = (context, input) => {
|
|
76
|
+
const { file, registration, chunk, coverage, limitations } = input;
|
|
77
|
+
for (const moduleValue of registration.modules) {
|
|
78
|
+
const module = context.accumulator.addNode({
|
|
79
|
+
kind: "javascript-module",
|
|
80
|
+
identity: artifactLocalIdentity(file.sha256, `${registration.runtime}:module`, moduleValue.module_key),
|
|
81
|
+
observations: [
|
|
82
|
+
{
|
|
83
|
+
label: moduleValue.module_key,
|
|
84
|
+
properties: {
|
|
85
|
+
path: file.path,
|
|
86
|
+
bundler: registration.bundler,
|
|
87
|
+
runtime: registration.runtime,
|
|
88
|
+
chunk_keys: registration.chunk_keys,
|
|
89
|
+
module_key: moduleValue.module_key,
|
|
90
|
+
factory_require_name: moduleValue.factory_require_name,
|
|
91
|
+
runtime_entry: registration.entry_module_keys.includes(moduleValue.module_key),
|
|
92
|
+
source_sha256: moduleValue.source_sha256,
|
|
93
|
+
structural_fingerprint_sha256: moduleValue.structural_fingerprint_sha256,
|
|
94
|
+
structural_fingerprint_algorithm: moduleValue.structural_fingerprint_algorithm,
|
|
95
|
+
structural_fingerprint_status: moduleValue.structural_fingerprint_status,
|
|
96
|
+
exports: moduleValue.exports,
|
|
97
|
+
exports_truncated: moduleValue.exports_truncated,
|
|
98
|
+
},
|
|
99
|
+
evidence: astObservationEvidence({
|
|
100
|
+
sha256: file.sha256,
|
|
101
|
+
path: file.path,
|
|
102
|
+
range: moduleValue.location,
|
|
103
|
+
operation: "extract-bundler-module",
|
|
104
|
+
coverage,
|
|
105
|
+
limitations,
|
|
106
|
+
}),
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
});
|
|
110
|
+
context.moduleNodes.set(moduleLookupKey(file.path, moduleValue.module_key), module);
|
|
111
|
+
addAstContainsEdge(context, {
|
|
112
|
+
source: chunk,
|
|
113
|
+
target: module,
|
|
114
|
+
file,
|
|
115
|
+
range: moduleValue.location,
|
|
116
|
+
coverage,
|
|
117
|
+
properties: {
|
|
118
|
+
bundler: registration.bundler,
|
|
119
|
+
runtime: registration.runtime,
|
|
120
|
+
chunk_keys: registration.chunk_keys,
|
|
121
|
+
module_key: moduleValue.module_key,
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
const addBundlerRuntimeEdges = (context, record) => {
|
|
127
|
+
const { file, registration, chunk, coverage } = record;
|
|
128
|
+
for (const moduleKey of registration.entry_module_keys) {
|
|
129
|
+
const resolved = context.moduleNodes.get(moduleLookupKey(file.path, moduleKey));
|
|
130
|
+
const target = resolved ?? unresolvedBundlerModuleNode(context, record, moduleKey);
|
|
131
|
+
context.accumulator.addEdge({
|
|
132
|
+
source_node_id: chunk.node_id,
|
|
133
|
+
target_node_id: target.node_id,
|
|
134
|
+
relation: "loads",
|
|
135
|
+
properties: {
|
|
136
|
+
kind: "bundler-entry-module",
|
|
137
|
+
bundler: registration.bundler,
|
|
138
|
+
runtime: registration.runtime,
|
|
139
|
+
module_key: moduleKey,
|
|
140
|
+
resolution_status: resolved === undefined ? "not-found" : "resolved",
|
|
141
|
+
},
|
|
142
|
+
evidence: staticInferenceEvidence({
|
|
143
|
+
sha256: file.sha256,
|
|
144
|
+
path: file.path,
|
|
145
|
+
range: registration.location,
|
|
146
|
+
operation: "resolve-bundler-entry-module",
|
|
147
|
+
coverage,
|
|
148
|
+
confidence: resolved === undefined ? "low" : "high",
|
|
149
|
+
}),
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
for (const chunkKey of registration.async_chunk_keys) {
|
|
153
|
+
const lookup = chunkLookupKey(file.path, registration.runtime, chunkKey);
|
|
154
|
+
const resolved = context.chunkNodes.get(lookup);
|
|
155
|
+
const target = resolved ?? unresolvedBundlerChunkNode(context, record, chunkKey);
|
|
156
|
+
context.accumulator.addEdge({
|
|
157
|
+
source_node_id: chunk.node_id,
|
|
158
|
+
target_node_id: target.node_id,
|
|
159
|
+
relation: "imports",
|
|
160
|
+
properties: {
|
|
161
|
+
kind: "bundler-async-chunk",
|
|
162
|
+
bundler: registration.bundler,
|
|
163
|
+
runtime: registration.runtime,
|
|
164
|
+
chunk_key: chunkKey,
|
|
165
|
+
resolution_status: resolved === undefined ? "not-found" : "resolved",
|
|
166
|
+
},
|
|
167
|
+
evidence: staticInferenceEvidence({
|
|
168
|
+
sha256: file.sha256,
|
|
169
|
+
path: file.path,
|
|
170
|
+
range: registration.location,
|
|
171
|
+
operation: "resolve-bundler-async-chunk",
|
|
172
|
+
coverage,
|
|
173
|
+
confidence: resolved === undefined ? "low" : "high",
|
|
174
|
+
}),
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
const unresolvedBundlerModuleNode = (context, record, moduleKey) => context.accumulator.addNode({
|
|
179
|
+
kind: "javascript-module",
|
|
180
|
+
identity: artifactLocalIdentity(record.file.sha256, `${record.registration.runtime}:unresolved-entry-module`, moduleKey),
|
|
181
|
+
observations: [
|
|
182
|
+
{
|
|
183
|
+
label: moduleKey,
|
|
184
|
+
properties: {
|
|
185
|
+
semantic_role: "bundler-module-reference",
|
|
186
|
+
bundler: record.registration.bundler,
|
|
187
|
+
runtime: record.registration.runtime,
|
|
188
|
+
module_key: moduleKey,
|
|
189
|
+
resolution_status: "not-found",
|
|
190
|
+
},
|
|
191
|
+
evidence: staticInferenceEvidence({
|
|
192
|
+
sha256: record.file.sha256,
|
|
193
|
+
path: record.file.path,
|
|
194
|
+
range: record.registration.location,
|
|
195
|
+
operation: "retain-unresolved-bundler-entry-module",
|
|
196
|
+
coverage: record.coverage,
|
|
197
|
+
confidence: "low",
|
|
198
|
+
}),
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
});
|
|
202
|
+
const unresolvedBundlerChunkNode = (context, record, chunkKey) => context.accumulator.addNode({
|
|
203
|
+
kind: "javascript-chunk",
|
|
204
|
+
identity: artifactLocalIdentity(record.file.sha256, `${record.registration.runtime}:unresolved-async-chunk`, chunkKey),
|
|
205
|
+
observations: [
|
|
206
|
+
{
|
|
207
|
+
label: chunkKey,
|
|
208
|
+
properties: {
|
|
209
|
+
semantic_role: "bundler-chunk-reference",
|
|
210
|
+
bundler: record.registration.bundler,
|
|
211
|
+
runtime: record.registration.runtime,
|
|
212
|
+
chunk_key: chunkKey,
|
|
213
|
+
resolution_status: "not-found",
|
|
214
|
+
},
|
|
215
|
+
evidence: staticInferenceEvidence({
|
|
216
|
+
sha256: record.file.sha256,
|
|
217
|
+
path: record.file.path,
|
|
218
|
+
range: record.registration.location,
|
|
219
|
+
operation: "retain-unresolved-bundler-async-chunk",
|
|
220
|
+
coverage: record.coverage,
|
|
221
|
+
confidence: "low",
|
|
222
|
+
}),
|
|
223
|
+
},
|
|
224
|
+
],
|
|
225
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { posix } from "node:path";
|
|
2
1
|
import { JavaScriptArtifactGraphAccumulator } from "./JavaScriptArtifactGraphAccumulator.js";
|
|
3
2
|
import { artifactObservationEvidence, astObservationEvidence, completeReconstructionCoverage, partialReconstructionCoverage, staticInferenceEvidence, unavailableAstEvidence, } from "./JavaScriptArtifactGraphEvidence.js";
|
|
3
|
+
import { resolveArtifactPathByContext, } from "./JavaScriptArtifactPathResolution.js";
|
|
4
4
|
/** Add a direct artifact-containment edge. */
|
|
5
5
|
export const addArtifactContainsEdge = (context, input) => {
|
|
6
6
|
context.accumulator.addEdge({
|
|
@@ -103,16 +103,27 @@ export const artifactLocalIdentity = (sha256, namespace, key) => ({
|
|
|
103
103
|
namespace: namespace.slice(0, 512),
|
|
104
104
|
key: key.slice(0, 4_096),
|
|
105
105
|
});
|
|
106
|
+
/** Select the graph node kind for one inventoried relevant file. */
|
|
107
|
+
export const artifactFileNodeKind = (kind) => kind === "javascript"
|
|
108
|
+
? "javascript-asset"
|
|
109
|
+
: kind === "source-map"
|
|
110
|
+
? "source-map"
|
|
111
|
+
: kind === "native-addon"
|
|
112
|
+
? "native-addon"
|
|
113
|
+
: "artifact";
|
|
106
114
|
/** Create or merge an Electron role inferred from static syntax or metadata. */
|
|
107
115
|
export const createElectronRoleNode = (context, input) => context.accumulator.addNode({
|
|
108
116
|
kind: input.kind,
|
|
109
|
-
identity: artifactLocalIdentity(input.anchor.sha256, "electron-role", `${input.kind}:${input.
|
|
117
|
+
identity: artifactLocalIdentity(input.anchor.sha256, "electron-role", `${input.kind}:${input.resolution.resolution_context}:${input.resolution.resolved_path ?? input.resolution.declared_path}`),
|
|
110
118
|
observations: [
|
|
111
119
|
{
|
|
112
|
-
label: input.
|
|
120
|
+
label: input.resolution.resolved_path ?? input.resolution.declared_path,
|
|
113
121
|
properties: {
|
|
114
|
-
declared_path: input.
|
|
115
|
-
|
|
122
|
+
declared_path: input.resolution.declared_path,
|
|
123
|
+
resolution_context: input.resolution.resolution_context,
|
|
124
|
+
resolved_path: input.resolution.resolved_path,
|
|
125
|
+
resolution_status: input.resolution.resolution_status,
|
|
126
|
+
limitations: input.resolution.limitations,
|
|
116
127
|
mechanism: input.mechanism,
|
|
117
128
|
},
|
|
118
129
|
evidence: staticInferenceEvidence({
|
|
@@ -120,6 +131,7 @@ export const createElectronRoleNode = (context, input) => context.accumulator.ad
|
|
|
120
131
|
path: input.anchor.path,
|
|
121
132
|
operation: "discover-electron-entrypoint",
|
|
122
133
|
coverage: input.coverage ?? completeReconstructionCoverage(),
|
|
134
|
+
limitations: input.resolution.limitations,
|
|
123
135
|
...(input.range === undefined ? {} : { range: input.range }),
|
|
124
136
|
}),
|
|
125
137
|
},
|
|
@@ -127,59 +139,48 @@ export const createElectronRoleNode = (context, input) => context.accumulator.ad
|
|
|
127
139
|
});
|
|
128
140
|
/** Resolve an Electron role to an inventoried asset when available. */
|
|
129
141
|
export const linkElectronRoleToAsset = (context, input) => {
|
|
130
|
-
|
|
142
|
+
const path = input.resolution.resolved_path;
|
|
143
|
+
if (path === null)
|
|
131
144
|
return;
|
|
132
|
-
const asset = context.assetNodes.get(
|
|
145
|
+
const asset = context.assetNodes.get(path) ?? context.fileNodes.get(path);
|
|
133
146
|
if (asset === undefined)
|
|
134
147
|
return;
|
|
135
148
|
context.accumulator.addEdge({
|
|
136
149
|
source_node_id: input.role.node_id,
|
|
137
150
|
target_node_id: asset.node_id,
|
|
138
151
|
relation: "maps_to",
|
|
139
|
-
properties: {
|
|
152
|
+
properties: {
|
|
153
|
+
declared_path: input.resolution.declared_path,
|
|
154
|
+
resolution_context: input.resolution.resolution_context,
|
|
155
|
+
resolved_path: path,
|
|
156
|
+
resolution_status: input.resolution.resolution_status,
|
|
157
|
+
},
|
|
140
158
|
evidence: staticInferenceEvidence({
|
|
141
159
|
sha256: input.anchor.sha256,
|
|
142
160
|
path: input.anchor.path,
|
|
143
161
|
operation: "resolve-electron-entrypoint",
|
|
144
162
|
coverage: input.coverage ?? completeReconstructionCoverage(),
|
|
163
|
+
limitations: input.resolution.limitations,
|
|
145
164
|
...(input.range === undefined ? {} : { range: input.range }),
|
|
146
165
|
}),
|
|
147
166
|
});
|
|
148
167
|
};
|
|
149
168
|
/** Deterministic key for one recovered module inside a bundle asset. */
|
|
150
169
|
export const moduleLookupKey = (path, moduleKey) => `${path}\0${moduleKey}`;
|
|
170
|
+
/** Deterministic key for one recovered bundler chunk inside a bundle asset. */
|
|
171
|
+
export const chunkLookupKey = (path, runtime, chunkKey) => `${path}\0${runtime}\0${chunkKey}`;
|
|
151
172
|
/** Resolve a relative static specifier without escaping the artifact root. */
|
|
152
|
-
export const resolveArtifactPath = (specifier, sourcePath, files) => {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
? clean.slice(1)
|
|
160
|
-
: posix.join(posix.dirname(sourcePath), clean));
|
|
161
|
-
if (candidate === ".." || candidate.startsWith("../"))
|
|
162
|
-
return null;
|
|
163
|
-
for (const path of pathCandidates(candidate))
|
|
164
|
-
if (files.has(path))
|
|
165
|
-
return path;
|
|
166
|
-
return null;
|
|
167
|
-
};
|
|
173
|
+
export const resolveArtifactPath = (specifier, sourcePath, files, moduleKind) => resolveArtifactPathByContext({
|
|
174
|
+
declaredPath: specifier,
|
|
175
|
+
sourcePath,
|
|
176
|
+
context: "module-specifier",
|
|
177
|
+
files,
|
|
178
|
+
...(moduleKind === undefined ? {} : { moduleKind }),
|
|
179
|
+
}).resolved_path;
|
|
168
180
|
/** Locate the recovered module that owns a static finding. */
|
|
169
181
|
export const sourceNodeFor = (context, path, moduleKey) => moduleKey === null
|
|
170
|
-
?
|
|
182
|
+
? context.sourceModuleNodes.get(path)
|
|
171
183
|
: context.moduleNodes.get(moduleLookupKey(path, moduleKey));
|
|
172
|
-
const pathCandidates = (path) => [
|
|
173
|
-
path,
|
|
174
|
-
`${path}.js`,
|
|
175
|
-
`${path}.mjs`,
|
|
176
|
-
`${path}.cjs`,
|
|
177
|
-
`${path}.ts`,
|
|
178
|
-
`${path}.tsx`,
|
|
179
|
-
`${path}.node`,
|
|
180
|
-
posix.join(path, "index.js"),
|
|
181
|
-
posix.join(path, "index.ts"),
|
|
182
|
-
];
|
|
183
184
|
/** Named AST budgets committed to graph evidence coverage. */
|
|
184
185
|
export const javaScriptAnalysisLimits = (input) => [
|
|
185
186
|
{
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { addArtifactContainsEdge, addStaticInferenceEdge, createElectronRoleNode,
|
|
1
|
+
import { addArtifactContainsEdge, addStaticInferenceEdge, createElectronRoleNode, linkElectronRoleToAsset, } from "./JavaScriptArtifactGraphContext.js";
|
|
2
2
|
import { artifactObservationEvidence, completeReconstructionCoverage, partialReconstructionCoverage, } from "./JavaScriptArtifactGraphEvidence.js";
|
|
3
|
+
import { resolveArtifactPathByContext } from "./JavaScriptArtifactPathResolution.js";
|
|
3
4
|
/** Project HTML renderer entrypoints and their local script assets. */
|
|
4
5
|
export const addJavaScriptHtmlRoles = (context) => {
|
|
5
6
|
const byHtml = new Map();
|
|
@@ -11,11 +12,17 @@ export const addJavaScriptHtmlRoles = (context) => {
|
|
|
11
12
|
const html = context.filesByPath.get(htmlPath);
|
|
12
13
|
if (html === undefined)
|
|
13
14
|
continue;
|
|
15
|
+
const roleResolution = {
|
|
16
|
+
declared_path: html.path,
|
|
17
|
+
resolution_context: "html-reference",
|
|
18
|
+
resolved_path: html.path,
|
|
19
|
+
resolution_status: "resolved",
|
|
20
|
+
limitations: [],
|
|
21
|
+
};
|
|
14
22
|
const role = createElectronRoleNode(context, {
|
|
15
23
|
kind: "electron-renderer",
|
|
16
24
|
anchor: html,
|
|
17
|
-
|
|
18
|
-
resolvedPath: html.path,
|
|
25
|
+
resolution: roleResolution,
|
|
19
26
|
mechanism: "html-script-entrypoint",
|
|
20
27
|
});
|
|
21
28
|
addArtifactContainsEdge(context, {
|
|
@@ -24,8 +31,20 @@ export const addJavaScriptHtmlRoles = (context) => {
|
|
|
24
31
|
file: html,
|
|
25
32
|
operation: "discover-html-renderer",
|
|
26
33
|
});
|
|
34
|
+
linkElectronRoleToAsset(context, {
|
|
35
|
+
role,
|
|
36
|
+
anchor: html,
|
|
37
|
+
resolution: roleResolution,
|
|
38
|
+
});
|
|
27
39
|
for (const script of scripts) {
|
|
28
|
-
const
|
|
40
|
+
const resolution = resolveArtifactPathByContext({
|
|
41
|
+
declaredPath: script.script_path,
|
|
42
|
+
sourcePath: html.path,
|
|
43
|
+
context: "html-reference",
|
|
44
|
+
files: context.filesByPath,
|
|
45
|
+
htmlBaseHref: script.base_href,
|
|
46
|
+
});
|
|
47
|
+
const resolvedPath = resolution.resolved_path;
|
|
29
48
|
if (resolvedPath === null)
|
|
30
49
|
continue;
|
|
31
50
|
const resolved = context.fileNodes.get(resolvedPath);
|
|
@@ -40,7 +59,11 @@ export const addJavaScriptHtmlRoles = (context) => {
|
|
|
40
59
|
relation: "loads",
|
|
41
60
|
properties: {
|
|
42
61
|
script_path: script.script_path,
|
|
62
|
+
base_href: script.base_href,
|
|
63
|
+
resolution_context: resolution.resolution_context,
|
|
43
64
|
resolved_path: resolvedPath,
|
|
65
|
+
resolution_status: resolution.resolution_status,
|
|
66
|
+
limitations: resolution.limitations,
|
|
44
67
|
},
|
|
45
68
|
});
|
|
46
69
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { addStaticInferenceEdge, artifactLocalIdentity, createElectronRoleNode, javascriptAnalysisCoverage, linkElectronRoleToAsset, moduleLookupKey, resolveArtifactPath, sourceNodeFor, } from "./JavaScriptArtifactGraphContext.js";
|
|
1
|
+
import { addStaticInferenceEdge, artifactLocalIdentity, chunkLookupKey, createElectronRoleNode, javascriptAnalysisCoverage, linkElectronRoleToAsset, moduleLookupKey, resolveArtifactPath, sourceNodeFor, } from "./JavaScriptArtifactGraphContext.js";
|
|
2
2
|
import { astObservationEvidence, staticInferenceEvidence, } from "./JavaScriptArtifactGraphEvidence.js";
|
|
3
|
+
import { resolveArtifactPathByContext } from "./JavaScriptArtifactPathResolution.js";
|
|
3
4
|
/** Project imports, workers, roles, endpoints, storage, and source-map links. */
|
|
4
5
|
export const addJavaScriptStaticFindings = (context) => {
|
|
5
6
|
for (const analyzed of context.analysis.files) {
|
|
@@ -25,7 +26,7 @@ const addReference = (context, input) => {
|
|
|
25
26
|
input.asset;
|
|
26
27
|
const resolved = input.value.specifier === null
|
|
27
28
|
? null
|
|
28
|
-
: resolveReference(context, input.file.path, input.value
|
|
29
|
+
: resolveReference(context, input.file.path, input.value);
|
|
29
30
|
if (input.value.kind === "worker" || input.value.kind === "service-worker") {
|
|
30
31
|
const worker = context.accumulator.addNode({
|
|
31
32
|
kind: input.value.kind === "worker" ? "worker" : "service-worker",
|
|
@@ -155,12 +156,16 @@ const addStorage = (context, input) => {
|
|
|
155
156
|
});
|
|
156
157
|
};
|
|
157
158
|
const addDiscoveredRole = (context, input) => {
|
|
158
|
-
const
|
|
159
|
+
const resolution = resolveArtifactPathByContext({
|
|
160
|
+
declaredPath: input.value.path,
|
|
161
|
+
sourcePath: input.file.path,
|
|
162
|
+
context: input.value.resolution_context,
|
|
163
|
+
files: context.filesByPath,
|
|
164
|
+
});
|
|
159
165
|
const role = createElectronRoleNode(context, {
|
|
160
166
|
kind: input.value.role === "preload" ? "electron-preload" : "electron-renderer",
|
|
161
167
|
anchor: input.file,
|
|
162
|
-
|
|
163
|
-
resolvedPath,
|
|
168
|
+
resolution,
|
|
164
169
|
mechanism: input.value.mechanism,
|
|
165
170
|
range: input.value.location,
|
|
166
171
|
coverage: input.coverage,
|
|
@@ -179,7 +184,7 @@ const addDiscoveredRole = (context, input) => {
|
|
|
179
184
|
linkElectronRoleToAsset(context, {
|
|
180
185
|
role,
|
|
181
186
|
anchor: input.file,
|
|
182
|
-
|
|
187
|
+
resolution,
|
|
183
188
|
range: input.value.location,
|
|
184
189
|
coverage: input.coverage,
|
|
185
190
|
});
|
|
@@ -228,7 +233,13 @@ const addSourceMapEdge = (context, input) => {
|
|
|
228
233
|
},
|
|
229
234
|
});
|
|
230
235
|
};
|
|
231
|
-
const resolveReference = (context, sourcePath,
|
|
236
|
+
const resolveReference = (context, sourcePath, reference) => {
|
|
237
|
+
const specifier = reference.specifier;
|
|
238
|
+
if (specifier === null)
|
|
239
|
+
return null;
|
|
240
|
+
const chunk = resolveBundlerChunkReference(context, sourcePath, reference);
|
|
241
|
+
if (chunk !== null)
|
|
242
|
+
return chunk;
|
|
232
243
|
const module = context.moduleNodes.get(moduleLookupKey(sourcePath, specifier));
|
|
233
244
|
if (module !== undefined) {
|
|
234
245
|
const file = context.filesByPath.get(sourcePath);
|
|
@@ -236,13 +247,48 @@ const resolveReference = (context, sourcePath, specifier) => {
|
|
|
236
247
|
? null
|
|
237
248
|
: { path: `${sourcePath}#module:${specifier}`, file, node: module };
|
|
238
249
|
}
|
|
239
|
-
const path = resolveArtifactPath(specifier, sourcePath, context.filesByPath
|
|
250
|
+
const path = resolveArtifactPath(specifier, sourcePath, context.filesByPath, reference.kind === "require"
|
|
251
|
+
? "require"
|
|
252
|
+
: reference.kind === "static-import" ||
|
|
253
|
+
reference.kind === "dynamic-import"
|
|
254
|
+
? "import"
|
|
255
|
+
: undefined);
|
|
240
256
|
if (path === null)
|
|
241
257
|
return null;
|
|
242
258
|
const file = context.filesByPath.get(path);
|
|
243
259
|
const node = context.fileNodes.get(path);
|
|
244
260
|
return file === undefined || node === undefined ? null : { path, file, node };
|
|
245
261
|
};
|
|
262
|
+
const resolveBundlerChunkReference = (context, sourcePath, reference) => {
|
|
263
|
+
const key = reference.specifier?.startsWith("chunk:")
|
|
264
|
+
? reference.specifier.slice("chunk:".length)
|
|
265
|
+
: null;
|
|
266
|
+
if (key === null)
|
|
267
|
+
return null;
|
|
268
|
+
const file = context.filesByPath.get(sourcePath);
|
|
269
|
+
if (file === undefined)
|
|
270
|
+
return null;
|
|
271
|
+
const registrations = context.analysis.files
|
|
272
|
+
.find(({ file: analyzedFile }) => analyzedFile.path === sourcePath)
|
|
273
|
+
?.javascript?.bundler_registrations.filter(({ modules }) => reference.module_key === null
|
|
274
|
+
? true
|
|
275
|
+
: modules.some(({ module_key: moduleKey }) => moduleKey === reference.module_key));
|
|
276
|
+
if (registrations === undefined)
|
|
277
|
+
return null;
|
|
278
|
+
const candidates = registrations.flatMap(({ runtime }) => {
|
|
279
|
+
const node = context.chunkNodes.get(chunkLookupKey(sourcePath, runtime, key));
|
|
280
|
+
return node === undefined ? [] : [node];
|
|
281
|
+
});
|
|
282
|
+
const unique = [
|
|
283
|
+
...new Map(candidates.map((node) => [node.node_id, node])).values(),
|
|
284
|
+
];
|
|
285
|
+
if (unique.length !== 1)
|
|
286
|
+
return null;
|
|
287
|
+
const node = unique[0];
|
|
288
|
+
return node === undefined
|
|
289
|
+
? null
|
|
290
|
+
: { path: `${sourcePath}#chunk:${key}`, file, node };
|
|
291
|
+
};
|
|
246
292
|
const unresolvedReferenceNode = (context, file, reference, coverage) => context.accumulator.addNode({
|
|
247
293
|
kind: "javascript-module",
|
|
248
294
|
identity: artifactLocalIdentity(file.sha256, "unresolved-reference", `${reference.kind}:${reference.specifier ?? reference.expression ?? "[dynamic]"}`),
|