Compare commits

...
Author SHA1 Message Date
Kaoru0822 5755b2863f Merge remote-tracking branch 'origin/main' into fix/nib-boolean-value-types
# Conflicts:
#	src/artifacts/apple/NibArchive.test.ts
2026-10-21 02:48:04 +00:00
Kaoru0822andClaude Opus 5.5 26b65b8008 fix(apple): decode NIBArchive boolean value types with the correct polarity
The NIBArchive decoder read value type 4 as true and 5 as false, so
decode-interface-builder reversed every serialized boolean in compiled nibs
(for example NSControlContinuous). Type 4 is false and 5 is true. The test
fixture encoder mirrored the same reversal, which hid it; correct it and pin
the raw type bytes in a decoder test.

Fixes #5541

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 14:55:42 +00:00
3 changed files with 23 additions and 3 deletions

No files matched your search

+1 -1
View File
@@ -75,7 +75,7 @@ const varint = (value: number): Buffer => {
const encodeValue = (
value: number | string | boolean | null | { ref: number },
): Buffer => {
if (typeof value === "boolean") return Buffer.from([value ? 4 : 5]);
if (typeof value === "boolean") return Buffer.from([value ? 5 : 4]);
if (value === null) return Buffer.from([9]);
if (typeof value === "number") {
const bytes = Buffer.alloc(5);
+18
View File
@@ -77,6 +77,24 @@ describe("NIBArchive decoder", () => {
expect(decoded.coder_version).toBe(10);
});
it("decodes boolean value type 4 as false and 5 as true", () => {
const archive = encodeArchive({
classes: ["NSButton"],
objects: [{ classIndex: 0, values: { NSControlContinuous: null } }],
});
// The only value record is key varint 0x80 then one-byte type 9 (nil);
// overwrite that type byte to pin the format's own boolean encoding.
const typeOffset = archive.readUInt32LE(38) + 1;
expect(archive[typeOffset]).toBe(9);
const decodeType = (type: number) => {
const bytes = Buffer.from(archive);
bytes[typeOffset] = type;
return decodeNibArchive(bytes).objects[0]?.values.NSControlContinuous;
};
expect(decodeType(4)).toBe(false);
expect(decodeType(5)).toBe(true);
});
it("counts AppKit outlet, action, and binding connector objects", () => {
const archive = encodeArchive({
classes: [
+4 -2
View File
@@ -374,10 +374,12 @@ const readValue = (
? Number(value)
: value.toString();
}
// NIBArchive value type 4 is false and 5 is true, as ibtool --export
// reports for the same compiled fields.
case 4:
return true;
case 5:
return false;
case 5:
return true;
case 6:
ensureRange(cursor.offset, 4, end, `value ${index}`);
{