mirror of
https://github.com/morluto/rea.git
synced 2026-11-09 16:26:36 +00:00
fix(javascript): preserve loader authority for exact suffixes (#9477)
* fix(javascript): require exact loader suffix case * fix(javascript): share exact loader mode across import resolution * test(process): align symlink fixture with filesystem checkpoints * test(javascript): normalize the module resolution oracle path separators * test(frida): assert the CLI spawn Evidence contract * test(mcp): use an unsupported analysis-view parent * test(browser): separate source-location line bounds from parity * fix(javascript): preserve uncertain loader provenance * test(javascript): cover uncertain require resolution * fix(javascript): retain conditional Electron evidence * fix(javascript): preserve timed semantic provenance * fix(javascript): retain conditional builtin effects * test(javascript): distinguish bundled host authority * fix(javascript): preserve nested loader invocation identity * test(javascript): qualify Electron fixture authority * fix(javascript): preserve loader invocation authority * fix(javascript): respect source order for resolver escapes * fix(javascript): check nested loader callable mutations * fix(javascript): retain conditional constructor requests * fix(reference): retain constructor loader relationships * fix(reference): follow nested loader callable paths * refactor(javascript): share callable mutation interpretation * fix(javascript): require exact package loader suffixes * refactor(javascript): unify conditional relation evidence * refactor(javascript): unify conditional node evidence * fix(javascript): retain unknown authority for mixed case sources * fix(javascript): preserve loader uncertainty for dotfiles * fix(reference): classify javascript suffix dotfiles * test(reference): cover suffix dotfiles through cli * fix(javascript): retain equivalent conditional built-in origins * fix(javascript): preserve wrapped resolver operation * fix(javascript): retain nested conditional built-in receivers * test(javascript): declare CommonJS in native addon fixtures * fix(javascript): retain wrapped resolver candidates * style: format merged native command schema * fix(javascript): preserve uncertain loader authority * test(javascript): require candidate preload evidence * test(javascript): cover reference loader member writes --------- Co-authored-by: ShuaixinHuang <1836656514@qq.com>
This commit is contained in:
1 parent
78a84d75c0
commit
b46f4fcebd
112 files changed
+5156
-797
No files matched your search
@@ -1,6 +1,16 @@
|
||||
import { expect, it } from "vitest";
|
||||
|
||||
import { analyzeJavaScriptStaticSource } from "../../domain/javascript/javascriptStaticAnalysis.js";
|
||||
import {
|
||||
analyzeJavaScriptStaticSource,
|
||||
analyzeParsedJavaScriptStaticSource,
|
||||
} from "../../domain/javascript/javascriptStaticAnalysis.js";
|
||||
import { parseJavaScriptSource } from "../../domain/javascript/javascriptSourceParser.js";
|
||||
|
||||
const analyzeCommonJsSource = (source: string) => {
|
||||
const file = parseJavaScriptSource(source, "fixture.cjs");
|
||||
if (file === null) throw new Error("Expected valid CommonJS fixture");
|
||||
return analyzeParsedJavaScriptStaticSource(source, file);
|
||||
};
|
||||
import {
|
||||
javaScriptWorkerModuleHeaderSchema,
|
||||
javaScriptWorkerModuleRecordSchema,
|
||||
@@ -54,7 +64,7 @@ it("transfers bounded alias selection coverage across the worker boundary", () =
|
||||
});
|
||||
|
||||
it("retains application path change identity and provenance across the worker boundary", () => {
|
||||
const facts = analyzeJavaScriptStaticSource(`
|
||||
const facts = analyzeCommonJsSource(`
|
||||
const { app } = require("electron");
|
||||
app.setAppPath("./other");
|
||||
`);
|
||||
@@ -85,6 +95,61 @@ it("transfers getter expansion limits and unknown bindings across the worker bou
|
||||
expect(ir.coverage.resourceLimits).toEqual(["getter-expansion"]);
|
||||
});
|
||||
|
||||
it("retains conditional CommonJS provenance and links across the worker boundary", () => {
|
||||
const ir = analyzeJavaScriptSemantics(
|
||||
'const { readFile } = require("node:fs");',
|
||||
);
|
||||
const binding = ir.bindings.find(({ name }) => name === "readFile");
|
||||
const link = ir.moduleLinks.find(({ specifier }) => specifier === "node:fs");
|
||||
expect(binding?.provenance).toMatchObject({
|
||||
status: "ambiguous",
|
||||
origins: [{ loaderAuthority: "candidate" }],
|
||||
});
|
||||
expect(link).toMatchObject({ loaderAuthority: "candidate" });
|
||||
expect(
|
||||
javaScriptWorkerModuleRecordSchema.safeParse({
|
||||
kind: "binding",
|
||||
value: {
|
||||
...binding,
|
||||
provenance: { ...binding?.provenance, status: "module", reason: null },
|
||||
},
|
||||
}).success,
|
||||
).toBe(false);
|
||||
for (const record of [
|
||||
{ kind: "binding", value: binding },
|
||||
{ kind: "module-link", value: link },
|
||||
]) {
|
||||
expect(
|
||||
javaScriptWorkerModuleRecordSchema.parse(
|
||||
JSON.parse(JSON.stringify(record)),
|
||||
),
|
||||
).toEqual(record);
|
||||
}
|
||||
});
|
||||
|
||||
it("transfers conditional require requests without claiming a loader", () => {
|
||||
const facts = analyzeJavaScriptStaticSource(
|
||||
'require("./dep.cjs"); require.resolve("./config.json");',
|
||||
);
|
||||
expect(facts.references).toEqual([
|
||||
expect.objectContaining({
|
||||
specifier: "./dep.cjs",
|
||||
operation: "load",
|
||||
loader_authority: "candidate",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
specifier: "./config.json",
|
||||
operation: "resolve",
|
||||
loader_authority: "candidate",
|
||||
}),
|
||||
]);
|
||||
expect(
|
||||
javaScriptWorkerStaticAnalysisSchema.parse(
|
||||
JSON.parse(JSON.stringify(facts)),
|
||||
),
|
||||
).toEqual(facts);
|
||||
});
|
||||
|
||||
it("retains candidate endpoint interpretation across the worker boundary", () => {
|
||||
const facts = analyzeJavaScriptStaticSource(`
|
||||
client.get("settingKey");
|
||||
@@ -176,7 +241,7 @@ it("preserves partial request targets through the strict worker schema", () => {
|
||||
|
||||
it("preserves scoped IPC receiver provenance and rejects malformed scope metadata", () => {
|
||||
const facts =
|
||||
analyzeJavaScriptStaticSource(`const {BrowserWindow} = require("electron");
|
||||
analyzeCommonJsSource(`const {BrowserWindow} = require("electron");
|
||||
const window = new BrowserWindow(); window.webContents.mainFrame.ipc.handle("scoped", () => {});`);
|
||||
expect(facts.electron.ipc).toHaveLength(1);
|
||||
expect(facts.electron.ipc[0]?.receiver?.kind).toBe("main-frame");
|
||||
|
||||
@@ -28,6 +28,10 @@ const findingContext = {
|
||||
module_runtime: z.string().optional(),
|
||||
location: range,
|
||||
};
|
||||
const electronFindingContext = {
|
||||
...findingContext,
|
||||
loader_authority: z.literal("candidate").exactOptional(),
|
||||
};
|
||||
const withRuntime = <
|
||||
Value extends {
|
||||
module_runtime?: string | undefined;
|
||||
@@ -78,7 +82,7 @@ const ipcReceiver = z
|
||||
const ipcChannel = <Shape extends z.ZodRawShape>(shape: Shape) =>
|
||||
z.union([
|
||||
z.strictObject({
|
||||
...findingContext,
|
||||
...electronFindingContext,
|
||||
receiver: ipcReceiver,
|
||||
invocation_location: range.optional(),
|
||||
resolution_basis: z.literal("wrapper-substitution").optional(),
|
||||
@@ -87,7 +91,7 @@ const ipcChannel = <Shape extends z.ZodRawShape>(shape: Shape) =>
|
||||
channel_expression: z.null(),
|
||||
}),
|
||||
z.strictObject({
|
||||
...findingContext,
|
||||
...electronFindingContext,
|
||||
receiver: ipcReceiver,
|
||||
invocation_location: range.optional(),
|
||||
resolution_basis: z.literal("wrapper-substitution").optional(),
|
||||
@@ -148,7 +152,7 @@ const ipc = z
|
||||
};
|
||||
});
|
||||
const windowShape = {
|
||||
...findingContext,
|
||||
...electronFindingContext,
|
||||
options_status: z.enum(["object-literal", "dynamic", "missing"]),
|
||||
web_preferences_status: z.enum(["object-literal", "dynamic", "missing"]),
|
||||
web_preferences: z.array(
|
||||
@@ -158,22 +162,26 @@ const windowShape = {
|
||||
};
|
||||
const bridgeShape = {
|
||||
resolution_basis: z.literal("wrapper-substitution").optional(),
|
||||
...findingContext,
|
||||
...electronFindingContext,
|
||||
world: z.enum(["main", "isolated"]),
|
||||
world_id: staticValue.nullable(),
|
||||
api_status: z.enum(["object-literal", "dynamic", "missing"]),
|
||||
members: strings,
|
||||
unknown_members: count,
|
||||
};
|
||||
const utilityShape = { ...findingContext, service_name: z.string().nullable() };
|
||||
const utilityShape = {
|
||||
...electronFindingContext,
|
||||
service_name: z.string().nullable(),
|
||||
};
|
||||
const electron = z
|
||||
.strictObject({
|
||||
app_path_changes: z
|
||||
.array(z.strictObject(findingContext).transform(withRuntime))
|
||||
.array(z.strictObject(electronFindingContext).transform(withRuntime))
|
||||
.optional(),
|
||||
call_paths: z
|
||||
.array(
|
||||
z.strictObject({
|
||||
loader_authority: z.literal("candidate").exactOptional(),
|
||||
entry_kind: z.enum(["bridge-member", "ipc-handler"]),
|
||||
entry: z.string(),
|
||||
entry_path: strings.optional(),
|
||||
@@ -255,7 +263,7 @@ const electron = z
|
||||
ipc: z.array(ipc),
|
||||
sender_validations: z.array(
|
||||
z.strictObject({
|
||||
...findingContext,
|
||||
...electronFindingContext,
|
||||
subject: z.enum([
|
||||
"sender-url",
|
||||
"sender-origin",
|
||||
@@ -291,7 +299,7 @@ const electron = z
|
||||
),
|
||||
native_addon_bindings: z.array(
|
||||
z.strictObject({
|
||||
...findingContext,
|
||||
...electronFindingContext,
|
||||
specifier: z.string(),
|
||||
binding_kind: z.enum(["import", "require", "re-export"]),
|
||||
module_kind: z.enum(["import", "require"]),
|
||||
@@ -303,7 +311,7 @@ const electron = z
|
||||
protocols: z.array(
|
||||
z
|
||||
.strictObject({
|
||||
...findingContext,
|
||||
...electronFindingContext,
|
||||
api: z.string(),
|
||||
role: z.enum([
|
||||
"os-default-client",
|
||||
@@ -327,6 +335,7 @@ const referenceShape = {
|
||||
...findingContext,
|
||||
operation: z.enum(["load", "resolve"]),
|
||||
resolution_base_path: z.string().exactOptional(),
|
||||
loader_authority: z.literal("candidate").exactOptional(),
|
||||
// A `factory-loader` specifier is a recovered bundle module key rather than a
|
||||
// package specifier, so the loader identity travels with the reference.
|
||||
loader: z
|
||||
@@ -424,6 +433,7 @@ export const javaScriptWorkerStaticAnalysisSchema = z
|
||||
z.strictObject({
|
||||
...findingContext,
|
||||
role: z.enum(["preload", "renderer"]),
|
||||
loader_authority: z.literal("candidate").exactOptional(),
|
||||
path: z.string(),
|
||||
path_base: z.literal("source-directory").exactOptional(),
|
||||
resolution_context: pathContext,
|
||||
@@ -528,20 +538,26 @@ const semanticValue: z.ZodType<JavaScriptSemanticValue> = z.lazy(() =>
|
||||
);
|
||||
const origin = z
|
||||
.strictObject({
|
||||
loaderAuthority: z.literal("candidate").optional(),
|
||||
specifier: z.string(),
|
||||
importedPath: strings,
|
||||
resolutionMode: z
|
||||
.enum(["import", "require", "compiler-dependent"])
|
||||
.optional(),
|
||||
})
|
||||
.transform(({ resolutionMode, ...rest }) => ({
|
||||
.transform(({ resolutionMode, loaderAuthority, ...rest }) => ({
|
||||
...rest,
|
||||
...(resolutionMode === undefined ? {} : { resolutionMode }),
|
||||
...(loaderAuthority === undefined ? {} : { loaderAuthority }),
|
||||
}));
|
||||
const provenOrigin = origin.refine(
|
||||
(value) => value.loaderAuthority !== "candidate",
|
||||
"Candidate loader authority cannot establish exact module provenance.",
|
||||
);
|
||||
const provenance = z.discriminatedUnion("status", [
|
||||
z.strictObject({
|
||||
status: z.literal("module"),
|
||||
origins: z.tuple([origin]),
|
||||
origins: z.tuple([provenOrigin]),
|
||||
reason: z.null(),
|
||||
}),
|
||||
z.strictObject({
|
||||
@@ -593,6 +609,7 @@ const coverage = z
|
||||
});
|
||||
const moduleLink = z
|
||||
.strictObject({
|
||||
loaderAuthority: z.literal("candidate").optional(),
|
||||
resolutionMode: z
|
||||
.enum(["import", "require", "compiler-dependent"])
|
||||
.optional(),
|
||||
@@ -611,9 +628,10 @@ const moduleLink = z
|
||||
callableId: z.string().nullable(),
|
||||
location: range,
|
||||
})
|
||||
.transform(({ resolutionMode, ...rest }) => ({
|
||||
.transform(({ resolutionMode, loaderAuthority, ...rest }) => ({
|
||||
...rest,
|
||||
...(resolutionMode === undefined ? {} : { resolutionMode }),
|
||||
...(loaderAuthority === undefined ? {} : { loaderAuthority }),
|
||||
}));
|
||||
const definitionKind = z.enum([
|
||||
"import",
|
||||
|
||||
Reference in new issue
Block a user