refactor(javascript): break the semantic analysis import cycle (#8063)

* refactor(javascript): break the semantic analysis import cycle

Split shared semantic facts out of the analysis hub so projectors of
effects, evaluation, and identity no longer import one another in a cycle.

* refactor(javascript): share the import specifier reader

Read static imports in one module used by the boundary checker and both
cycle guards, so those rules cannot drift apart.

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
This commit is contained in:
morlutoandCursor Agent authored and GitHub committed 2026-10-30 06:07:49 +08:00
1 parent 940d71a45a
commit 249b90c5e3
33 files changed
+1043 -772

No files matched your search

@@ -0,0 +1,48 @@
import type * as t from "@babel/types";
import type { JavaScriptModuleOrigin } from "./javascriptSemanticIr.js";
import type { JavaScriptSemanticAnalysisState } from "./javascriptSemanticState.js";
/** An unshadowed literal require and the member path selected from its result. */
export interface JavaScriptRequireOrigin {
readonly origin: JavaScriptModuleOrigin;
readonly call: t.CallExpression;
}
export type JavaScriptRequireLoaderFact =
| "commonjs-loader"
| "factory-loader"
| "create-require"
| "local"
| "unknown";
type RequireOriginReader = (
node: t.Node | null | undefined,
state: JavaScriptSemanticAnalysisState,
) => JavaScriptRequireOrigin | undefined;
type RequireLoaderReader = (
node: t.CallExpression | t.OptionalCallExpression | t.NewExpression,
state: JavaScriptSemanticAnalysisState,
factoryBindingIds: ReadonlySet<string>,
) => JavaScriptRequireLoaderFact;
/**
* Require-origin queries are owned by javascriptSemanticRequireOrigin.ts, which
* also depends on evaluation. Lower layers read them through this slot so the
* import edge stays one way. The owner assigns both readers when it loads.
*/
export const semanticRequireOriginReaders: {
origin: RequireOriginReader | undefined;
loader: RequireLoaderReader | undefined;
} = { origin: undefined, loader: undefined };
export const readSemanticRequireOrigin: RequireOriginReader = (node, state) =>
semanticRequireOriginReaders.origin?.(node, state);
export const readSemanticRequireLoader: RequireLoaderReader = (
node,
state,
factoryBindingIds,
) =>
semanticRequireOriginReaders.loader?.(node, state, factoryBindingIds) ??
"unknown";