fix(parsers): preserve format boundaries and query occurrence identity

Normalize parsed facts at their owning boundaries across PE exports and certificates, ELF section names, GPU bundles, IL2CPP generic types, dyld slice selection, source maps, environment replay, and JavaScript mapped arguments. Preserve partial facts and explicit unsupported cases; clarify the corresponding documentation.

Validation: 831 affected tests passed with one existing skip across 23 files; build, typecheck/lint, documentation, formatting, and 2133-file test discovery passed. Format controls are synthetic; real Unity, GPU, and ARM-device execution is unverified.

Fixes #6709
Fixes #6688
Fixes #6719
Fixes #6718
Fixes #6704
Fixes #6703
Fixes #6692
Fixes #6723
Fixes #6687
Fixes #6726
Fixes #6696
Fixes #6691
Fixes #6727
This commit is contained in:
morluto committed 2026-10-23 22:01:16 +08:00
1 parent 4193bc5bf8
commit 5f702dd6cc
60 files changed
+2069 -211

No files matched your search

+52 -6
View File
@@ -15,10 +15,13 @@ import {
FIXTURE_RETURN_TYPE_NAME,
type Il2cppBinaryFixtureOptions,
} from "../../fixtures/il2cpp/binary.js";
import { createIl2cppMetadataFixture } from "../../fixtures/il2cpp/metadata.js";
import {
createIl2cppMetadataFixture,
createLinkedIl2cppMetadataFixture,
} from "../../fixtures/il2cpp/metadata.js";
const { metadata, link: facts } = readIl2cppMetadataForLinking(
createIl2cppMetadataFixture().bytes,
createLinkedIl2cppMetadataFixture().bytes,
);
const expectedAddress = (value: bigint | "no-body" | "unknown") =>
typeof value === "bigint"
@@ -233,6 +236,38 @@ it("reports type indices without names for metadata version 27", () => {
);
});
it("renders nested generic arguments on the components that declare them", () => {
const renderedName = (
typeNames: Readonly<Record<number, string>>,
genericTypeArgumentCounts: Readonly<Record<number, number>>,
genericArgumentTypeIndices: readonly number[],
) => {
const { metadata: nestedMetadata, link: nestedFacts } =
readIl2cppMetadataForLinking(
createLinkedIl2cppMetadataFixture({
typeNames,
typeNamespaces: { 0: "Game", 1: "" },
genericTypeArgumentCounts,
}).bytes,
);
return linkIl2cppBinary(
createIl2cppBinaryFixture({
genericDefinitionTypeIndex: 1,
genericArgumentTypeIndices,
}),
nestedMetadata,
nestedFacts,
).return_types[0]?.name;
};
expect(
renderedName({ 0: "Outer`1", 1: "Inner`2" }, { 0: 1, 1: 2 }, [3, 3]),
).toBe("Game.Outer<int>+Inner<int>[]");
expect(renderedName({ 0: "Outer`1", 1: "Leaf`1" }, { 0: 1, 1: 1 }, [3])).toBe(
"Game.Outer<int>+Leaf[]",
);
});
it("does not search for an empty image name", () => {
const unnamed = {
...metadata,
@@ -486,6 +521,11 @@ it("rejects a recursive binary type graph without overflowing the JavaScript sta
});
it("guards a shared generic expansion before concatenating unchecked text", () => {
const expanded = readIl2cppMetadataForLinking(
createLinkedIl2cppMetadataFixture({
genericTypeArgumentCounts: { 3: 2 },
}).bytes,
);
const bytes = Buffer.alloc(0x4000);
createIl2cppBinaryFixture().copy(bytes);
bytes.writeBigUInt64LE(BigInt(bytes.length), 64);
@@ -506,11 +546,17 @@ it("guards a shared generic expansion before concatenating unchecked text", () =
}
bytes.writeBigUInt64LE(prior, 0x900);
const stopped = new Error("type text admission");
const steps = linkIl2cppBinarySteps(bytes, metadata, facts, undefined, {
beforeText: (size) => {
if (size > 1024) throw stopped;
const steps = linkIl2cppBinarySteps(
bytes,
expanded.metadata,
expanded.link,
undefined,
{
beforeText: (size) => {
if (size > 1024) throw stopped;
},
},
});
);
expect(() => {
for (;;) {
if (steps.next().done) break;