fix(javascript): omit self-referential import edges with disclosure (#1130)

* fix(javascript): omit self-referential import edges with disclosure

A specifier that resolves back to the importing module itself produced an
imports edge from a module to itself, which the application graph schema
forbids; one such specifier failed result validation and lost the whole
analysis. Skip those edges at composition time and disclose the omission
count in the graph limitations.

Fixes #1129

* test(javascript): verify self-import behavior through the compiled CLI

---------

Co-authored-by: BaaRai <baarai@users.noreply.github.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
This commit is contained in:
BaaRai
2026-10-09 01:10:38 +02:00
committed by GitHub
parent c1d0002470
commit 1d7115b7b4
3 changed files with 180 additions and 7 deletions
@@ -15,6 +15,7 @@ import {
import { addJavaScriptStaticFindings } from "./JavaScriptArtifactGraphFindings.js";
import {
addJavaScriptModuleRelationships,
type JavaScriptModuleRelationshipOmissions,
addJavaScriptSourceModules,
} from "./JavaScriptModuleRelationships.js";
import {
@@ -88,7 +89,7 @@ const buildJavaScriptArtifactGraphInput = (
const packageRoots = addJavaScriptPackageNodes(context);
addJavaScriptSourceModules(context);
addJavaScriptBundlerNodes(context);
addJavaScriptModuleRelationships(context);
const relationshipOmissions = addJavaScriptModuleRelationships(context);
addJavaScriptStaticFindings(context);
addElectronBoundaries(context);
addJavaScriptHtmlRoles(context);
@@ -103,7 +104,11 @@ const buildJavaScriptArtifactGraphInput = (
nodes: accumulator.nodes(),
edges: accumulator.edges(),
coverage,
limitations: graphLimitations(context, coverage.status),
limitations: graphLimitations(
context,
coverage.status,
relationshipOmissions,
),
};
};
@@ -171,6 +176,7 @@ const applicationGraphResourceLimit = (
const graphLimitations = (
context: JavaScriptArtifactGraphContext,
coverage: "complete" | "partial" | "unknown" | "unavailable",
relationshipOmissions: JavaScriptModuleRelationshipOmissions,
): string[] => {
const ipc = collectElectronIpcRecords(context.analysis);
const pairings = classifyElectronIpcPairings(ipc);
@@ -189,6 +195,11 @@ const graphLimitations = (
);
return [
...context.analysis.limitations,
...(relationshipOmissions.selfImports > 0
? [
`${String(relationshipOmissions.selfImports)} import ${relationshipOmissions.selfImports === 1 ? "specifier" : "specifiers"} resolved back to the importing module itself and ${relationshipOmissions.selfImports === 1 ? "was" : "were"} omitted; application graph edges cannot be self-referential.`,
]
: []),
"CommonJS and ESM binding relationships were recovered from inert syntax and resolved only within the inventoried artifact container.",
"Webpack/Rspack factories were recovered from AST literals; REA did not invoke push handlers or bundle bootstrap code.",
"Static imports, entrypoints, workers, endpoints, and storage relationships do not prove runtime execution.",