Compare commits

...
Author SHA1 Message Date
morluto 4091a40797 fix(symbols): match exact Objective-C protocol labels 2026-11-10 22:27:18 -05:00
3 changed files with 31 additions and 9 deletions

No files matched your search

+7 -2
View File
@@ -8,8 +8,7 @@ export const objcClassSymbol = (
readonly metaclass: boolean;
}
| undefined => {
const namespace = name.lastIndexOf("::");
const leaf = namespace < 0 ? name : name.slice(namespace + 2);
const leaf = objcSymbolLeaf(name);
const match = /^_?(OBJC_(META)?CLASS_\$_([^\s]+))$/u.exec(leaf);
if (match?.[1] === undefined || match[3] === undefined) return undefined;
return {
@@ -18,3 +17,9 @@ export const objcClassSymbol = (
metaclass: match[2] !== undefined,
};
};
/** Preserve the exact runtime symbol leaf after a provider namespace. */
export const objcSymbolLeaf = (name: string): string => {
const namespace = name.lastIndexOf("::");
return namespace < 0 ? name : name.slice(namespace + 2);
};
+20
View File
@@ -282,3 +282,23 @@ it("distinguishes protocol identity from protocol member contexts", () => {
unclassified: [],
});
});
it("selects exact Objective-C protocol symbol leaves", () => {
const declarations = [
"OBJC_PROTOCOL_$_Runnable",
"_OBJC_PROTOCOL_$_Runnable",
"__OBJC_PROTOCOL_$_Runnable",
"Framework::__OBJC_PROTOCOL_$_Runnable",
].map((name, index) => ({ address: `0x${index}`, name }));
const otherNames = [
"s__OBJC_PROTOCOL_$_Runnable_1000",
"PTR__OBJC_PROTOCOL_$_Runnable_1000",
"-[Example useOBJC_PROTOCOL_$_Runnable]",
"__OBJC_PROTOCOL_REFERENCE_$_Runnable",
"__OBJC_PROTOCOL_$_",
].map((name, index) => ({ address: `0x${index + 4}`, name }));
expect(discoverObjcProtocols([...otherNames, ...declarations])).toEqual({
count: declarations.length,
protocols: declarations,
});
});
+4 -7
View File
@@ -1,4 +1,4 @@
import { objcClassSymbol } from "./objcClassSymbol.js";
import { objcClassSymbol, objcSymbolLeaf } from "./objcClassSymbol.js";
import type { JsonValue } from "./jsonValue.js";
import type { AddressedName } from "./native/nativeInventory.js";
import type {
@@ -14,11 +14,8 @@ import {
/** Local class records emitted by Apple's fragile Objective-C ABI. */
const LEGACY_OBJC_CLASS_PREFIX = "l_OBJC_CLASS_" as const;
/**
* Objective-C protocol declaration marker. `PROTOCOL_REFERENCE` slots
* share the substring but are uses, not definitions.
*/
const OBJC_PROTOCOL_MARKER = "OBJC_PROTOCOL_$_" as const;
/** Objective-C protocol declaration labels with their object-file prefixes. */
const OBJC_PROTOCOL_SYMBOL = /^_{0,2}OBJC_PROTOCOL_\$_[^\s]+$/u;
export interface ObjcClassImportBindingScan {
readonly bindings: readonly MachoImportBinding[];
@@ -66,7 +63,7 @@ export const discoverObjcProtocols = (
const protocols = uniqueByName(
names.filter(
({ name }) =>
name.includes(OBJC_PROTOCOL_MARKER) ||
OBJC_PROTOCOL_SYMBOL.test(objcSymbolLeaf(name)) ||
classifySwiftSymbol(name)?.protocolIdentity === true,
),
);