Skip to content

Commit 88ffe00

Browse files
committed
Tweaks to Hook.originalImp
1 parent b870a22 commit 88ffe00

3 files changed

Lines changed: 25 additions & 8 deletions

File tree

Sources/InterposeKit/Hooks/Hook.swift

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,14 @@ public final class Hook {
128128
// MARK: Original Implementation
129129
// ============================================================================ //
130130

131-
// TODO: Make originalIMP private
132-
133-
/// The effective original implementation of the hook. Might be looked up at runtime.
134-
/// Do not cache this.
135-
internal var originalIMP: IMP? {
131+
/// The effective original implementation of the method being hooked.
132+
///
133+
/// Resolved via the active strategy. If the hook has been applied, it returns a stored
134+
/// original implementation. Otherwise, it performs a dynamic lookup at runtime.
135+
///
136+
/// Provided to the hook builder via a proxy to enable calls to the original implementation.
137+
/// This value is dynamic and must not be cached.
138+
internal var originalIMP: IMP {
136139
self.strategy.originalIMP
137140
}
138141

Sources/InterposeKit/Hooks/HookStrategy/HookStrategy.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,12 @@ extension HookStrategy {
4949
return originalIMP
5050
}
5151

52-
fatalError()
52+
fatalError(
53+
"""
54+
No original implementation found for selector \(self.selector) on \(self.class).
55+
This likely indicates a corrupted or misconfigured class.
56+
"""
57+
)
5358
}
5459

5560
/// Dynamically resolves the current implementation of the hooked method by walking the class

Tests/InterposeKitTests/HookDynamicLookupTests.swift

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,14 @@ class HookDynamicLookupTests: XCTestCase {
2121
object: object,
2222
selector: #selector(ExampleClass.greet(name:)),
2323
build: { (hook: HookProxy<MethodSignature>) -> HookSignature in
24-
// Build a replacement block that calls the original implementation via the hook proxy.
2524
return { `self`, name in
2625
return hook.original(self, hook.selector, name)
2726
}
2827
}
2928
)
3029

3130
// Force the dynamic lookup path by ensuring no original IMP has been cached.
32-
// The following call will use `lookupOrigIMP` to find the method implementation.
31+
// The following call will use `strategy.lookUpIMP()` to find the method implementation.
3332
let original = unsafeBitCast(
3433
hook.originalIMP,
3534
to: (@convention(c) (ExampleClass, Selector, String) -> String).self
@@ -38,5 +37,15 @@ class HookDynamicLookupTests: XCTestCase {
3837
// Call the original implementation via the looked-up IMP.
3938
let result = original(object, #selector(ExampleClass.greet(name:)), "World")
4039
XCTAssertEqual(result, "Hello, World!")
40+
41+
try hook.apply()
42+
43+
let original2 = unsafeBitCast(
44+
hook.originalIMP,
45+
to: (@convention(c) (ExampleClass, Selector, String) -> String).self
46+
)
47+
48+
let result2 = original2(object, #selector(ExampleClass.greet(name:)), "World")
49+
XCTAssertEqual(result2, "Hello, World!")
4150
}
4251
}

0 commit comments

Comments
 (0)