mirror of
https://github.com/morluto/rea.git
synced 2026-11-15 11:13:21 +00:00
refactor: remove redundant seams and preserve cleanup ownership (#10375)
* refactor: remove redundant seams and preserve cleanup ownership * fix: validate PE resource extents before budget checks
This commit is contained in:
1 parent
4b26f38d6f
commit
cdc4541ef7
369 files changed
+3847
-3662
No files matched your search
@@ -7,7 +7,6 @@ import {
|
||||
import {
|
||||
createJavaScriptApplicationGraph,
|
||||
createJavaScriptApplicationEdge,
|
||||
type JavaScriptApplicationGraph,
|
||||
} from "./javascriptApplicationGraph.js";
|
||||
import { compareJavaScriptApplicationVersions } from "./javascriptApplicationVersionComparison.js";
|
||||
|
||||
|
||||
@@ -34,8 +34,6 @@ import {
|
||||
GLOBAL_OBJECT_NAMES,
|
||||
globalObjectName,
|
||||
globalReferenceNamespace,
|
||||
isUnmodifiedGlobalReference,
|
||||
isUnmodifiedImportMetaUrl,
|
||||
} from "./javascriptSemanticGlobalReference.js";
|
||||
import { readSemanticRequireLoader } from "./javascriptSemanticRequireOriginSlot.js";
|
||||
import {
|
||||
|
||||
@@ -119,7 +119,6 @@ import {
|
||||
} from "./javascriptSemanticCoverage.js";
|
||||
import { semanticResourceLimitReason } from "./javascriptSemanticResourceLimits.js";
|
||||
import {
|
||||
javaScriptRuntimeContext,
|
||||
javaScriptProgramStrictness,
|
||||
parseJavaScriptSource,
|
||||
type ParsedJavaScriptSource,
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
import { readdirSync, readFileSync, statSync } from "node:fs";
|
||||
import { dirname, join, relative, resolve } from "node:path";
|
||||
import { dirname } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { describe, it } from "vitest";
|
||||
|
||||
import { readImportSpecifiers } from "../../../scripts/lib/import-specifiers.mjs";
|
||||
import { expectImportCycles } from "../../../tests/fixtures/importCycles.js";
|
||||
|
||||
const root = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
const relativeSpecifiers = (source: string): readonly string[] =>
|
||||
readImportSpecifiers(source)
|
||||
.map(({ specifier }) => specifier)
|
||||
.filter((specifier) => specifier.startsWith("."));
|
||||
|
||||
/**
|
||||
* Cycles that already existed outside the semantic analysis hub. Membership is
|
||||
* exact so a new edge cannot hide inside the allow-list.
|
||||
@@ -42,97 +36,8 @@ const allowedCycleEdges = [
|
||||
"javascriptStaticAnalysisState.ts -> javascriptStaticAnalysisFindings.ts",
|
||||
].sort();
|
||||
|
||||
const productionFiles = (directory: string): string[] => {
|
||||
const files: string[] = [];
|
||||
for (const name of readdirSync(directory)) {
|
||||
const path = join(directory, name);
|
||||
if (statSync(path).isDirectory()) files.push(...productionFiles(path));
|
||||
else if (name.endsWith(".ts") && !name.includes(".test.")) files.push(path);
|
||||
}
|
||||
return files;
|
||||
};
|
||||
|
||||
const importGraph = (): Map<string, Set<string>> => {
|
||||
const files = new Set(
|
||||
productionFiles(root).map((path) => relative(root, path)),
|
||||
);
|
||||
const graph = new Map<string, Set<string>>();
|
||||
for (const file of files) {
|
||||
const source = readFileSync(join(root, file), "utf8");
|
||||
const edges = new Set<string>();
|
||||
for (const spec of relativeSpecifiers(source)) {
|
||||
const resolved = resolve(dirname(join(root, file)), spec).replace(
|
||||
/\.js$/,
|
||||
".ts",
|
||||
);
|
||||
const target = relative(root, resolved);
|
||||
if (files.has(target)) edges.add(target);
|
||||
}
|
||||
graph.set(file, edges);
|
||||
}
|
||||
return graph;
|
||||
};
|
||||
|
||||
const stronglyConnected = (
|
||||
graph: Map<string, Set<string>>,
|
||||
): readonly (readonly string[])[] => {
|
||||
let index = 0;
|
||||
const stack: string[] = [];
|
||||
const onStack = new Set<string>();
|
||||
const indices = new Map<string, number>();
|
||||
const low = new Map<string, number>();
|
||||
const components: string[][] = [];
|
||||
const visit = (node: string): void => {
|
||||
indices.set(node, index);
|
||||
low.set(node, index);
|
||||
index += 1;
|
||||
stack.push(node);
|
||||
onStack.add(node);
|
||||
for (const next of graph.get(node) ?? []) {
|
||||
if (!indices.has(next)) {
|
||||
visit(next);
|
||||
low.set(node, Math.min(low.get(node) ?? index, low.get(next) ?? index));
|
||||
} else if (onStack.has(next)) {
|
||||
low.set(
|
||||
node,
|
||||
Math.min(low.get(node) ?? index, indices.get(next) ?? index),
|
||||
);
|
||||
}
|
||||
}
|
||||
if (low.get(node) === indices.get(node)) {
|
||||
const component: string[] = [];
|
||||
let member = "";
|
||||
while (member !== node) {
|
||||
member = stack.pop() ?? node;
|
||||
onStack.delete(member);
|
||||
component.push(member);
|
||||
}
|
||||
if (component.length > 1) components.push(component.sort());
|
||||
}
|
||||
};
|
||||
for (const node of [...graph.keys()].sort()) {
|
||||
if (!indices.has(node)) visit(node);
|
||||
}
|
||||
return components.sort(
|
||||
(left, right) =>
|
||||
right.length - left.length || left.join().localeCompare(right.join()),
|
||||
);
|
||||
};
|
||||
|
||||
describe("javascript semantic import cycles", () => {
|
||||
it("keeps the semantic modules out of one import cycle", () => {
|
||||
const graph = importGraph();
|
||||
const cycles = stronglyConnected(graph).map((cycle) => cycle.join("\n"));
|
||||
expect(cycles).toEqual(
|
||||
allowedCycles.map((cycle) => [...cycle].sort().join("\n")),
|
||||
);
|
||||
const internalEdges = allowedCycles.flatMap((cycle) =>
|
||||
cycle.flatMap((source) =>
|
||||
[...(graph.get(source) ?? [])]
|
||||
.filter((target) => cycle.includes(target))
|
||||
.map((target) => `${source} -> ${target}`),
|
||||
),
|
||||
);
|
||||
expect(internalEdges.sort()).toEqual(allowedCycleEdges);
|
||||
expectImportCycles(root, allowedCycles, allowedCycleEdges);
|
||||
});
|
||||
});
|
||||
@@ -9,7 +9,6 @@ import { semanticReferenceSourcesInactive } from "./javascriptSemanticReferenceS
|
||||
import {
|
||||
resolveSemanticBindingState,
|
||||
type JavaScriptSemanticBindingState,
|
||||
type JavaScriptSemanticAnalysisState,
|
||||
} from "./javascriptSemanticState.js";
|
||||
import type { JavaScriptSemanticObjectReference as Reference } from "./javascriptSemanticObjectReference.js";
|
||||
import type { JavaScriptSemanticPropertyPath as PropertyPath } from "./javascriptSemanticPropertyPaths.js";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { escapeJsonPointerToken } from "../jsonPointer.js";
|
||||
import type {
|
||||
JavaScriptSemanticProperty,
|
||||
JavaScriptSemanticValue,
|
||||
@@ -100,6 +101,4 @@ export const semanticSlotAtPath = (
|
||||
|
||||
/** Encode path segments as an unambiguous JSON Pointer, preserving empty keys. */
|
||||
export const semanticPropertyPointer = (path: readonly string[]): string =>
|
||||
path
|
||||
.map((key) => `/${key.replaceAll("~", "~0").replaceAll("/", "~1")}`)
|
||||
.join("");
|
||||
path.map((key) => `/${escapeJsonPointerToken(key)}`).join("");
|
||||
@@ -507,20 +507,6 @@ const isRequestUrlOrPathLiteral = (value: string): boolean =>
|
||||
value.startsWith("./") ||
|
||||
value.startsWith("../");
|
||||
|
||||
/** Explicit request references, classified after receiver-specific exclusions. */
|
||||
const isRequestUrlReference = (value: string): boolean => {
|
||||
if (
|
||||
isRequestUrlOrPathLiteral(value) ||
|
||||
value.startsWith("?") ||
|
||||
value.startsWith("#")
|
||||
)
|
||||
return true;
|
||||
// WHATWG accepts HTTP/WS scheme forms without authority slashes. Parse
|
||||
// without a base so bare keys stay ambiguous, and keep the source spelling.
|
||||
if (!/^(?:https?|wss?):/iu.test(value)) return false;
|
||||
return URL.parse(value) !== null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Browsing-context and document `open` take a URL or type first and a target
|
||||
* name second. The name is only a spelling, since `parent` or `self` may be a
|
||||
|
||||
Reference in new issue
Block a user