diff --git a/.jazzy.yaml b/.jazzy.yaml index cb48f5d..8dad2a1 100644 --- a/.jazzy.yaml +++ b/.jazzy.yaml @@ -33,7 +33,6 @@ custom_categories: - name: All Hooks children: - AnyHook - - AnyHookBase - name: Groups children: - HookGroup diff --git a/Orion.xcodeproj/project.pbxproj b/Orion.xcodeproj/project.pbxproj index 9c1f712..c246678 100644 --- a/Orion.xcodeproj/project.pbxproj +++ b/Orion.xcodeproj/project.pbxproj @@ -30,6 +30,8 @@ 56AFA08B25A3CE5F00884E2D /* dealloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 56AFA08A25A3CE5F00884E2D /* dealloc.h */; settings = {ATTRIBUTES = (Public, ); }; }; 56AFA08D25A3CE6500884E2D /* dealloc.m in Sources */ = {isa = PBXBuildFile; fileRef = 56AFA08C25A3CE6500884E2D /* dealloc.m */; }; 56AFA08F25A3CE8B00884E2D /* ClassHook+Deinit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56AFA08E25A3CE8A00884E2D /* ClassHook+Deinit.swift */; }; + 56D50FAE25F11DEE00AE26FA /* ClassHook+Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56D50FAD25F11DEE00AE26FA /* ClassHook+Glue.swift */; }; + 56D50FB125F11DF500AE26FA /* FunctionHook+Glue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56D50FB025F11DF500AE26FA /* FunctionHook+Glue.swift */; }; 56D5B37F258F6F9D00F3DB6E /* ErrorHandling.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56D5B37E258F6F9D00F3DB6E /* ErrorHandling.swift */; }; 56D9F14925C4940900EDB315 /* LazyAtomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56D9F14825C4940900EDB315 /* LazyAtomic.swift */; }; /* End PBXBuildFile section */ @@ -68,6 +70,8 @@ 56AFA08A25A3CE5F00884E2D /* dealloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dealloc.h; sourceTree = ""; }; 56AFA08C25A3CE6500884E2D /* dealloc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = dealloc.m; sourceTree = ""; }; 56AFA08E25A3CE8A00884E2D /* ClassHook+Deinit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ClassHook+Deinit.swift"; sourceTree = ""; }; + 56D50FAD25F11DEE00AE26FA /* ClassHook+Glue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ClassHook+Glue.swift"; sourceTree = ""; }; + 56D50FB025F11DF500AE26FA /* FunctionHook+Glue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FunctionHook+Glue.swift"; sourceTree = ""; }; 56D5B37E258F6F9D00F3DB6E /* ErrorHandling.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErrorHandling.swift; sourceTree = ""; }; 56D9F14825C4940900EDB315 /* LazyAtomic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LazyAtomic.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -195,10 +199,12 @@ 568974A4252BBA15006F48E9 /* Backend.swift */, 5689749C252BBA15006F48E9 /* ClassHook.swift */, 56AFA08E25A3CE8A00884E2D /* ClassHook+Deinit.swift */, + 56D50FAD25F11DEE00AE26FA /* ClassHook+Glue.swift */, 568974A0252BBA15006F48E9 /* ClassHook+Super.swift */, 5689749D252BBA15006F48E9 /* Dynamic.swift */, 56D5B37E258F6F9D00F3DB6E /* ErrorHandling.swift */, 5689749E252BBA15006F48E9 /* FunctionHook.swift */, + 56D50FB025F11DF500AE26FA /* FunctionHook+Glue.swift */, 56080B5B25C1F8BE005803BC /* Group.swift */, 568974A8252BBA15006F48E9 /* Hook.swift */, 5689749F252BBA15006F48E9 /* InternalBackend.swift */, @@ -397,6 +403,8 @@ 568974B5252BBA15006F48E9 /* ReadWriteLock.swift in Sources */, 56D9F14925C4940900EDB315 /* LazyAtomic.swift in Sources */, 568974C4252BBA4F006F48E9 /* super.m in Sources */, + 56D50FB125F11DF500AE26FA /* FunctionHook+Glue.swift in Sources */, + 56D50FAE25F11DEE00AE26FA /* ClassHook+Glue.swift in Sources */, 568974AA252BBA15006F48E9 /* ClassHook.swift in Sources */, 568974B1252BBA15006F48E9 /* Property.swift in Sources */, 568974B3252BBA15006F48E9 /* MutexLock.swift in Sources */, diff --git a/Sources/Orion/Backend.swift b/Sources/Orion/Backend.swift index 591ff9a..476910f 100644 --- a/Sources/Orion/Backend.swift +++ b/Sources/Orion/Backend.swift @@ -60,7 +60,7 @@ public protocol Backend { } extension Backend { - func activate(hooks: [_AnyGlueHook.Type]) { + func activate(hooks: [_GlueAnyHook.Type]) { let hooksToActivate = hooks.filter { $0.hookWillActivate() } apply(descriptors: hooksToActivate.flatMap { $0.activate() }) hooksToActivate.forEach { $0.hookDidActivate() } diff --git a/Sources/Orion/ClassHook+Deinit.swift b/Sources/Orion/ClassHook+Deinit.swift index c029ab7..83344b8 100644 --- a/Sources/Orion/ClassHook+Deinit.swift +++ b/Sources/Orion/ClassHook+Deinit.swift @@ -15,7 +15,7 @@ public enum DeinitPolicy { } /// :nodoc: -extension _ClassHookBuilder { +extension _GlueClassHookBuilder { private static let deallocSelector = NSSelectorFromString("dealloc") public typealias Deinitializer = @convention(c) (Any, Selector) -> Void @@ -23,7 +23,7 @@ extension _ClassHookBuilder { // for some reason using `@escaping Deinitializer` instead of `Code` // works in SPM but not with the binary framework (maybe a swiftinterface // bug or library evolution thing?) - public mutating func addDeinitializer( + public mutating func addDeinitializer( to classHook: T.Type, getOrig: @escaping () -> Deinitializer, setOrig: @escaping (Code) -> Void @@ -60,7 +60,7 @@ extension _ClassHookBuilder { } /// :nodoc: -extension _GlueClassHook { +extension _GlueClassHookTrampoline { public func deinitOrigError(file: StaticString = #file, line: UInt = #line) -> Never { orionError("Do not call `orig.deinitializer()`.", file: file, line: line) } diff --git a/Sources/Orion/ClassHook+Glue.swift b/Sources/Orion/ClassHook+Glue.swift new file mode 100644 index 0000000..da10f32 --- /dev/null +++ b/Sources/Orion/ClassHook+Glue.swift @@ -0,0 +1,166 @@ +import Foundation + +/// Internal storage associated with a `ClassHook`. Do not use this yourself. +/// +/// :nodoc: +public final class _GlueClassHookStorage { + let hookType: AnyClass + @LazyAtomic private(set) var targetType: AnyObject.Type + @LazyAtomic private(set) var group: HookGroup + + // additional fields may be added here in the future + + init( + hookType: AnyClass, + loadTargetType: @escaping () -> AnyObject.Type, + loadGroup: @escaping () -> HookGroup + ) { + self.hookType = hookType + _targetType = LazyAtomic(wrappedValue: loadTargetType()) + _group = LazyAtomic(wrappedValue: loadGroup()) + } +} + +/// A placeholder class hook glue type. Do not use this yourself. +/// +/// This type is the default value for the `ClassHookProtocol._Glue` constraint, +/// used to satisfy the compiler until the actual glue is provided. +/// +/// :nodoc: +public enum _GlueClassHookPlaceholder: _GlueClassHook { + public typealias OrigType = HookType + public typealias SuprType = HookType + + public static var storage: _GlueClassHookStorage { error() } + public static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) { error() } + + private static func error() -> Never { + orionError("Placeholder class hook used. Has the glue file been compiled?") + } +} + +/// A marker protocol to which `_GlueClassHook`'s orig/supr trampolines conform. Do +/// not use this yourself. +/// +/// :nodoc: +public protocol _GlueClassHookTrampoline: ClassHookProtocol {} + +/// A helper type used in the glue file for applying class hooks. Do not +/// use this directly. +/// +/// :nodoc: +public struct _GlueClassHookBuilder { + let target: AnyClass + + var descriptors: [HookDescriptor] = [] + + public mutating func addHook( + _ sel: Selector, + _ replacement: Code, + isClassMethod: Bool, + saveOrig: @escaping (Code) -> Void + ) { + let cls: AnyClass = isClassMethod ? object_getClass(target)! : target + descriptors.append( + .method(cls: cls, sel: sel, replacement: unsafeBitCast(replacement, to: UnsafeMutableRawPointer.self)) { + saveOrig(unsafeBitCast($0, to: Code.self)) + } + ) + } +} + +/// A concrete class hook, implemented in the glue file. Do not use +/// this directly. +/// +/// :nodoc: +public protocol _GlueClassHook: _GlueAnyHook { + associatedtype HookType: ClassHookProtocol + associatedtype OrigType: ClassHookProtocol where OrigType.Target == HookType.Target + associatedtype SuprType: ClassHookProtocol where SuprType.Target == HookType.Target + + static var storage: _GlueClassHookStorage { get } + static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) +} + +/// :nodoc: +extension _GlueClassHook { + public static func addMethod(_ selector: Selector, _ implementation: Code, isClassMethod: Bool) { + let methodDescription = { "\(isClassMethod ? "+" : "-")[\(self) \(selector)]" } + guard let method = (isClassMethod ? class_getClassMethod : class_getInstanceMethod)(HookType.self, selector) + else { orionError("Could not find method \(methodDescription())") } + guard let types = method_getTypeEncoding(method) + else { orionError("Could not get method signature for \(methodDescription())") } + let cls: AnyClass = isClassMethod ? object_getClass(HookType.target)! : HookType.target + guard class_addMethod(cls, selector, unsafeBitCast(implementation, to: IMP.self), types) + else { orionError("Failed to add method \(methodDescription())") } + } + + public static func activate() -> [HookDescriptor] { + var classHookBuilder = _GlueClassHookBuilder(target: HookType.target) + activate(withClassHookBuilder: &classHookBuilder) + return classHookBuilder.descriptors + } + + public static var groupType: HookGroup.Type { + HookType.Group.self + } + + public static func hookWillActivate() -> Bool { + HookType.hookWillActivate() + } + + public static func hookDidActivate() { + HookType.hookDidActivate() + } + + public static func initializeStorage() -> _GlueClassHookStorage { + // this gives us the type of the user's hook rather than + // our concrete subclass + _GlueClassHookStorage( + hookType: HookType.self, + loadTargetType: HookType.initializeTargetType, + loadGroup: HookType.loadGroup + ) + } +} + +extension SubclassMode { + fileprivate func subclassName(withType type: AnyClass) -> String? { + switch self { + case .none: + return nil + case .createSubclass: + return "OrionSubclass.\(NSStringFromClass(type))" + case .createSubclassNamed(let name): + return name + } + } +} + +/// :nodoc: +extension ClassHookProtocol { + // since `target` is referred to in `activate()`, this will deterministically be called + // when a class hook is activated. + fileprivate static func initializeTargetType() -> Target.Type { + let targetName = self.targetName // only call getter once + let baseTarget = targetName.isEmpty ? Target.self : Dynamic(targetName).as(type: Target.self) + + let target: Target.Type + if let subclassName = subclassMode.subclassName(withType: _Glue.storage.hookType) { + guard let pair: AnyClass = objc_allocateClassPair(baseTarget, subclassName, 0) + else { orionError("Could not allocate subclass for \(self)") } + objc_registerClassPair(pair) + guard let _target = pair as? Target.Type + else { orionError("Allocated invalid subclass for \(self)") } + target = _target + } else { + target = baseTarget + } + + protocols.forEach { + guard class_addProtocol(target, $0) + else { orionError("Could not add protocol \($0) to \(target)") } + } + return target + } +} diff --git a/Sources/Orion/ClassHook+Super.swift b/Sources/Orion/ClassHook+Super.swift index d83070f..0826b1f 100644 --- a/Sources/Orion/ClassHook+Super.swift +++ b/Sources/Orion/ClassHook+Super.swift @@ -47,7 +47,7 @@ enum MessageSendSuperType { } /// :nodoc: -extension _GlueClassHook { +extension _GlueClassHookTrampoline { private static func callSuper( _ type: MessageType.Type, receiver: Any, diff --git a/Sources/Orion/ClassHook.swift b/Sources/Orion/ClassHook.swift index 2960755..31f6c40 100644 --- a/Sources/Orion/ClassHook.swift +++ b/Sources/Orion/ClassHook.swift @@ -12,38 +12,6 @@ public enum SubclassMode { /// Create a subclass with the provided name. case createSubclassNamed(String) - fileprivate func subclassName(withType type: AnyClass) -> String? { - switch self { - case .none: - return nil - case .createSubclass: - return "OrionSubclass.\(NSStringFromClass(type))" - case .createSubclassNamed(let name): - return name - } - } - -} - -/// Internal storage associated with a `ClassHook`. Do not use this yourself. -/// -/// :nodoc: -public final class _ClassHookStorage { - let hookType: AnyClass - @LazyAtomic private(set) var targetType: AnyObject.Type - @LazyAtomic private(set) var group: HookGroup - - // additional fields may be added here in the future - - init( - hookType: AnyClass, - loadTargetType: @escaping () -> AnyObject.Type, - loadGroup: @escaping () -> HookGroup - ) { - self.hookType = hookType - _targetType = LazyAtomic(wrappedValue: loadTargetType()) - _group = LazyAtomic(wrappedValue: loadGroup()) - } } /// The protocol to which class hooks conform. Do not conform to this @@ -57,11 +25,14 @@ public protocol ClassHookProtocol: class, AnyHook { /// its inheritance chain. associatedtype Target: AnyObject - /// Internal storage associated with the class hook. - /// Do not implement or use this yourself. + /// The glue type associated with this hook. Do not implement or use + /// this yourself. + /// + /// - See: `_GlueAnyHook` /// /// :nodoc: - static var _storage: _ClassHookStorage { get } + associatedtype _Glue: _GlueClassHook = _GlueClassHookPlaceholder + where _Glue.HookType == Self /// The name of the target class, or the empty string to use `Target.self`. /// @@ -95,11 +66,11 @@ public protocol ClassHookProtocol: class, AnyHook { /// The current instance of the hooked class, upon which a hooked method /// has been called. /// - /// Do not attempt to implement this yourself; use the default implementation. + /// - Warning: Do not attempt to implement this yourself; use the default + /// implementation. var target: Target { get } - /// Initializes the type with the provided target instance. Do not invoke - /// or override this. + /// Initializes the type with the provided target instance. Do not override this. init(target: Target) /// A function which is run before a `target` is deallocated. @@ -123,10 +94,6 @@ extension ClassHookProtocol { public static var targetName: String { "" } - public static var _storage: _ClassHookStorage { - orionError("Could not retrieve class hook storage. Has the Orion glue file been compiled?") - } - public static var subclassMode: SubclassMode { .none } public static var protocols: [Protocol] { [] } @@ -145,8 +112,7 @@ extension ClassHookProtocol { /// has been called. public let target: Target - /// Initializes the type with the provided target instance. Do not invoke - /// or override this. + /// Initializes the type with the provided target instance. Do not override this. public required init(target: Target) { self.target = target } } @@ -276,93 +242,16 @@ public typealias ClassHook = ClassHookClass & ClassHo // result in ClassHookClass inheriting the default implementations of ClassHookProtocol and // AnyHook requirements, making it more difficult to override them -/// :nodoc: -extension ClassHookProtocol { - public static var group: Group { - guard let group = _storage.group as? Group else { - orionError("Got unexpected group type from \(self)._storage") - } - return group - } -} - -extension ClassHookProtocol { - - /// The concrete type of the hooked target (or its subclass depending on - /// `subclassMode`). - public static var target: Target.Type { - // this is in an extension so users can't accidentally override it - guard let target = _storage.targetType as? Target.Type else { - orionError("Got unexpected target type from \(self)._storage") - } - return target - } - - /// Initializes the hook's internal storage. Do not call this yourself. - /// - /// :nodoc: - public static func _initializeStorage() -> _ClassHookStorage { - // this gives us the type of the user's hook rather than - // our concrete subclass - _ClassHookStorage( - hookType: self, - loadTargetType: initializeTargetType, - loadGroup: loadGroup - ) - } - - // since `target` is referred to in `activate()`, this will deterministically be called - // when a class hook is activated. - private static func initializeTargetType() -> Target.Type { - let targetName = self.targetName // only call getter once - let baseTarget = targetName.isEmpty ? Target.self : Dynamic(targetName).as(type: Target.self) - - let target: Target.Type - if let subclassName = subclassMode.subclassName(withType: _storage.hookType) { - guard let pair: AnyClass = objc_allocateClassPair(baseTarget, subclassName, 0) - else { orionError("Could not allocate subclass for \(self)") } - objc_registerClassPair(pair) - guard let _target = pair as? Target.Type - else { orionError("Allocated invalid subclass for \(self)") } - target = _target - } else { - target = baseTarget - } - - protocols.forEach { - guard class_addProtocol(target, $0) - else { orionError("Could not add protocol \($0) to \(target)") } - } - return target - } - -} - -/// An existential for glue class hooks. Do not use this directly. -/// -/// :nodoc: -public protocol _AnyGlueClassHook { - static var _orig: AnyClass { get } - var _orig: AnyObject { get } - - static var _supr: AnyClass { get } - var _supr: AnyObject { get } -} - extension ClassHookProtocol { - // @_transparent allows the compiler to incorporate these methods into the - // control flow analysis of the caller. This means it sees the possibility - // for the fatal errors, thereby not thinking that the function is infinitely - // recursive which it would otherwise do (see https://bugs.swift.org/browse/SR-7925) - // While that bug has technically been fixed, it still affects us because Swift - // won't normally see the glue overrides and so it'll not realise that there is - // an override point. + // These are `@_transparent` to allow control flow information from + // `disableRecursionCheck()` to carry through to callers. /// A proxy to access the original instance methods of the hooked class. @_transparent public var orig: Self { - guard let unwrapped = (self as? _AnyGlueClassHook)?._orig as? Self + disableRecursionCheck() + guard let unwrapped = _Glue.OrigType(target: target) as? Self else { orionError("Could not get orig") } return unwrapped } @@ -370,7 +259,8 @@ extension ClassHookProtocol { /// A proxy to access the original class methods of the hooked class. @_transparent public static var orig: Self.Type { - guard let unwrapped = (self as? _AnyGlueClassHook.Type)?._orig as? Self.Type + disableRecursionCheck() + guard let unwrapped = _Glue.OrigType.self as? Self.Type else { orionError("Could not get orig") } return unwrapped } @@ -378,7 +268,8 @@ extension ClassHookProtocol { /// A proxy to access the hooked class' superclass instance methods. @_transparent public var supr: Self { - guard let unwrapped = (self as? _AnyGlueClassHook)?._supr as? Self + disableRecursionCheck() + guard let unwrapped = _Glue.SuprType(target: target) as? Self else { orionError("Could not get supr") } return unwrapped } @@ -386,70 +277,32 @@ extension ClassHookProtocol { /// A proxy to access the hooked class' superclass class methods. @_transparent public static var supr: Self.Type { - guard let unwrapped = (self as? _AnyGlueClassHook.Type)?._supr as? Self.Type + disableRecursionCheck() + guard let unwrapped = _Glue.SuprType.self as? Self.Type else { orionError("Could not get supr") } return unwrapped } } -/// A helper type used in the glue file for applying class hooks. Do not -/// use this directly. -/// -/// :nodoc: -public struct _ClassHookBuilder { - let target: AnyClass - - var descriptors: [HookDescriptor] = [] - - public mutating func addHook( - _ sel: Selector, - _ replacement: Code, - isClassMethod: Bool, - saveOrig: @escaping (Code) -> Void - ) { - let cls: AnyClass = isClassMethod ? object_getClass(target)! : target - descriptors.append( - .method(cls: cls, sel: sel, replacement: unsafeBitCast(replacement, to: UnsafeMutableRawPointer.self)) { - saveOrig(unsafeBitCast($0, to: Code.self)) - } - ) +extension ClassHookProtocol { + /// The concrete type of the hooked target (or its subclass depending on + /// `subclassMode`). + public static var target: Target.Type { + // this is in an extension so users can't accidentally override it + guard let target = _Glue.storage.targetType as? Target.Type else { + orionError("Got unexpected target type for \(self)") + } + return target } } -/// A concrete class hook, implemented in the glue file. Do not use -/// this directly. -/// -/// :nodoc: -public protocol _GlueClassHook: _AnyGlueClassHook, ClassHookProtocol, _AnyGlueHook { - associatedtype OrigType: ClassHookProtocol where OrigType.Target == Target - associatedtype SuprType: ClassHookProtocol where SuprType.Target == Target - - static func activate(withClassHookBuilder builder: inout _ClassHookBuilder) -} - /// :nodoc: -extension _GlueClassHook { - public static var _orig: AnyClass { OrigType.self } - public var _orig: AnyObject { OrigType(target: target) } - - public static var _supr: AnyClass { SuprType.self } - public var _supr: AnyObject { SuprType(target: target) } - - public static func addMethod(_ selector: Selector, _ implementation: Code, isClassMethod: Bool) { - let methodDescription = { "\(isClassMethod ? "+" : "-")[\(self) \(selector)]" } - guard let method = (isClassMethod ? class_getClassMethod : class_getInstanceMethod)(self, selector) - else { orionError("Could not find method \(methodDescription())") } - guard let types = method_getTypeEncoding(method) - else { orionError("Could not get method signature for \(methodDescription())") } - let cls: AnyClass = isClassMethod ? object_getClass(target)! : target - guard class_addMethod(cls, selector, unsafeBitCast(implementation, to: IMP.self), types) - else { orionError("Failed to add method \(methodDescription())") } - } - - public static func activate() -> [HookDescriptor] { - var classHookBuilder = _ClassHookBuilder(target: target) - activate(withClassHookBuilder: &classHookBuilder) - return classHookBuilder.descriptors +extension ClassHookProtocol { + public static var group: Group { + guard let group = _Glue.storage.group as? Group else { + orionError("Got unexpected group type for \(self)") + } + return group } } diff --git a/Sources/Orion/ErrorHandling.swift b/Sources/Orion/ErrorHandling.swift index 0929848..b532827 100644 --- a/Sources/Orion/ErrorHandling.swift +++ b/Sources/Orion/ErrorHandling.swift @@ -84,13 +84,38 @@ public func orionError( } } +@inlinable func alwaysFalse() -> Bool { false } + +/// Disables a spurious warning emitted by the Swift compiler in +/// hooked methods that call their original implementations. +/// +/// When the glue file has not been compiled, Swift warns that +/// calls to `orig.foo()` will always recurse. We, however, know +/// that the glue file _will_ eventually be compiled and so the +/// warning is incorrect. This method suppresses that warning. +/// +/// Since the function is `@_transparent`, Swift includes the +/// `orionError(...)` path in its control flow analysis of the caller, +/// which causes Swift to think that there is indeed a non-recursive +/// path for the function, suppressing the warning. Furthermore, since +/// `alwaysFalse()` isn't transparent, Swift doesn't go deep enough +/// while computing the warning to realize that the branch will never +/// execute, however the optimizer does indeed see this since the code +/// is still inlined, and therefore the method call is entirely +/// optimized out. +@_transparent @inlinable func disableRecursionCheck() { + if alwaysFalse() { + orionError("should never be executed") + } +} + // TODO: Use this // usage: someOptional !! "Error message" infix operator !!: CastingPrecedence extension Optional { - static func !! (lhs: Self, message: @autoclosure () -> String) -> Wrapped { + @inlinable static func !! (lhs: Self, message: @autoclosure () -> String) -> Wrapped { switch lhs { case .some(let unwrapped): return unwrapped diff --git a/Sources/Orion/FunctionHook+Glue.swift b/Sources/Orion/FunctionHook+Glue.swift new file mode 100644 index 0000000..6e773f2 --- /dev/null +++ b/Sources/Orion/FunctionHook+Glue.swift @@ -0,0 +1,79 @@ +import Foundation + +/// Internal storage associated with a `FunctionHook`. Do not use this yourself. +/// +/// :nodoc: +public final class _GlueFunctionHookStorage { + @LazyAtomic private(set) var group: HookGroup + + init(loadGroup: @escaping () -> HookGroup) { + _group = LazyAtomic(wrappedValue: loadGroup()) + } +} + +/// A placeholder function hook glue type. Do not use this yourself. +/// +/// This type is the default value for the `FunctionHookProtocol._Glue` constraint, +/// used to satisfy the compiler until the actual glue is provided. +/// +/// :nodoc: +public enum _GlueFunctionHookPlaceholder: _GlueFunctionHook { + public typealias OrigType = HookType + + public static var origFunction: Void { + get { error() } + // swiftlint:disable:next unused_setter_value + set { error() } + } + + public static var storage: _GlueFunctionHookStorage { error() } + public static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) { error() } + + private static func error() -> Never { + orionError("Placeholder function hook used. Has the glue file been compiled?") + } +} + +/// A marker protocol to which `_GlueClassHook`'s orig/supr trampolines conform. Do +/// not use this yourself. +/// +/// :nodoc: +public protocol _GlueFunctionHookTrampoline: FunctionHookProtocol {} + +/// A concrete function hook, implemented in the glue file. Do not use +/// this directly. +/// +/// :nodoc: +public protocol _GlueFunctionHook: _GlueAnyHook { + associatedtype HookType: FunctionHookProtocol + associatedtype OrigType: FunctionHookProtocol + associatedtype Code + + static var storage: _GlueFunctionHookStorage { get } + static var origFunction: Code { get set } +} + +/// :nodoc: +extension _GlueFunctionHook { + public static func activate() -> [HookDescriptor] { + [.function(function: HookType.target, replacement: unsafeBitCast(origFunction, to: UnsafeMutableRawPointer.self)) { + origFunction = unsafeBitCast($0, to: Code.self) + }] + } + + public static var groupType: HookGroup.Type { + HookType.Group.self + } + + public static func hookWillActivate() -> Bool { + HookType.hookWillActivate() + } + + public static func hookDidActivate() { + HookType.hookDidActivate() + } + + public static func initializeStorage() -> _GlueFunctionHookStorage { + _GlueFunctionHookStorage(loadGroup: HookType.loadGroup) + } +} diff --git a/Sources/Orion/FunctionHook.swift b/Sources/Orion/FunctionHook.swift index 2ab23f3..30e0ec0 100644 --- a/Sources/Orion/FunctionHook.swift +++ b/Sources/Orion/FunctionHook.swift @@ -38,61 +38,29 @@ public enum Function: CustomStringConvertible { } } -/// Internal storage associated with a `FunctionHook`. Do not use this yourself. -/// -/// :nodoc: -public final class _FunctionHookStorage { - @LazyAtomic private(set) var group: HookGroup - - init(loadGroup: @escaping () -> HookGroup) { - _group = LazyAtomic(wrappedValue: loadGroup()) - } -} - /// The protocol to which function hooks conform. Do not conform to this /// directly; use `FunctionHook`. public protocol FunctionHookProtocol: class, AnyHook { - /// The function which is to be hooked. - static var target: Function { get } - - /// Internal storage associated with the function hook. - /// Do not implement or use this yourself. + /// The glue type associated with this hook. Do not implement or use + /// this yourself. + /// + /// - See: `_GlueAnyHook` /// /// :nodoc: - static var _storage: _FunctionHookStorage { get } + associatedtype _Glue: _GlueFunctionHook = _GlueFunctionHookPlaceholder + where _Glue.HookType == Self + + /// The function which is to be hooked. + static var target: Function { get } /// Initialize the function hook type. Do not invoke or override this; - /// use `AnyHookBase.hookWillActivate()` or `AnyHookBase.hookDidActivate()` - /// for lifecycle events. + /// use `AnyHook.hookWillActivate()` or `AnyHook.hookDidActivate()` for + /// lifecycle events. init() } -/// :nodoc: -extension FunctionHookProtocol { - public static var _storage: _FunctionHookStorage { - orionError("Could not retrieve function hook storage. Has the Orion glue file been compiled?") - } - - /// Initializes the hook's internal storage. Do not call this yourself. - /// - /// :nodoc: - public static func _initializeStorage() -> _FunctionHookStorage { - _FunctionHookStorage(loadGroup: loadGroup) - } -} - -/// :nodoc: -extension FunctionHookProtocol { - public static var group: Group { - guard let group = _storage.group as? Group else { - orionError("Got unexpected group type from \(self)._storage") - } - return group - } -} - /// The class which all function hooks inherit from. Do not subclass /// this directly; use `FunctionHook`. /// @@ -100,8 +68,8 @@ extension FunctionHookProtocol { open class FunctionHookClass { /// Initialize the function hook type. Do not invoke or override this; - /// use `AnyHookBase.hookWillActivate()` or `AnyHookBase.hookDidActivate()` - /// for lifecycle events. + /// use `AnyHook.hookWillActivate()` or `AnyHook.hookDidActivate()` for + /// lifecycle events. required public init() {} } @@ -135,14 +103,6 @@ open class FunctionHookClass { /// ``` public typealias FunctionHook = FunctionHookClass & FunctionHookProtocol -/// An existential for glue function hooks. Do not use this directly. -/// -/// :nodoc: -public protocol _AnyGlueFunctionHook { - static var _orig: AnyClass { get } - var _orig: AnyObject { get } -} - extension FunctionHookProtocol { /// A proxy which allows invoking the original function. @@ -154,32 +114,20 @@ extension FunctionHookProtocol { /// information on how this is used. @_transparent public var orig: Self { - guard let unwrapped = (self as? _AnyGlueFunctionHook)?._orig as? Self + disableRecursionCheck() + guard let unwrapped = _Glue.OrigType() as? Self else { orionError("Could not get orig") } return unwrapped } } -/// A concrete function hook, implemented in the glue file. Do not use -/// this directly. -/// -/// :nodoc: -public protocol _GlueFunctionHook: _AnyGlueFunctionHook, FunctionHookProtocol, _AnyGlueHook { - associatedtype Code - static var origFunction: Code { get set } - - associatedtype OrigType: FunctionHookProtocol -} - /// :nodoc: -extension _GlueFunctionHook { - public static func activate() -> [HookDescriptor] { - [.function(function: target, replacement: unsafeBitCast(origFunction, to: UnsafeMutableRawPointer.self)) { - origFunction = unsafeBitCast($0, to: Code.self) - }] +extension FunctionHookProtocol { + public static var group: Group { + guard let group = _Glue.storage.group as? Group else { + orionError("Got unexpected group type for \(self)") + } + return group } - - public static var _orig: AnyClass { OrigType.self } - public var _orig: AnyObject { OrigType() } } diff --git a/Sources/Orion/Group.swift b/Sources/Orion/Group.swift index 6b8516b..cbbfc92 100644 --- a/Sources/Orion/Group.swift +++ b/Sources/Orion/Group.swift @@ -121,7 +121,7 @@ class GroupRegistry { private init() {} // returns default hooks which should be activated immediately - func register(_ hooks: [_AnyGlueHook.Type], withBackend backend: Backend) -> [_AnyGlueHook.Type] { + func register(_ hooks: [_GlueAnyHook.Type], withBackend backend: Backend) -> [_GlueAnyHook.Type] { var newGroups = Dictionary(grouping: hooks) { $0.groupType.id } let defaultHooks = newGroups.removeValue(forKey: DefaultGroup.id) if !newGroups.isEmpty { diff --git a/Sources/Orion/Hook.swift b/Sources/Orion/Hook.swift index 714bea0..090f84a 100644 --- a/Sources/Orion/Hook.swift +++ b/Sources/Orion/Hook.swift @@ -1,11 +1,22 @@ import Foundation -/// The base existential protocol for all hook types. Do not use this directly. +/// Base protocol requirements for hooks. Do not use this directly. /// -/// - See: `AnyHook`, `ClassHook`, and `FunctionHook`. -public protocol AnyHookBase { - // This protocol should never have any Self/PAT requirements, to allow it to be - // usable as an existential. To add a Self/PAT requirement, use `AnyHook`. +/// - See: `ClassHook`, and `FunctionHook`. +public protocol AnyHook { + + /// The `HookGroup` to which this hook is assigned. + /// + /// Defaults to `DefaultGroup`. + /// + /// - See: `HookGroup` + associatedtype Group: HookGroup = DefaultGroup + + /// The `HookGroup` associated with this hook type. + /// + /// Do not attempt to implement this yourself; use the default + /// implementation. + static var group: Group { get } // these are named hook[Will|Did]Activate instead of [will|did]Activate because // they're special cased in the generator so that in class hooks, we don't end @@ -26,50 +37,49 @@ public protocol AnyHookBase { /// /// The default implementation does nothing. static func hookDidActivate() -} - -/// Additional protocol requirements for hooks, beyond those of `AnyHookBase`. -/// Do not use this directly. -/// -/// - See: `AnyHookBase`, `ClassHook`, and `FunctionHook`. -public protocol AnyHook: AnyHookBase { - - /// The `HookGroup` to which this hook is assigned. - /// - /// Defaults to `DefaultGroup`. - /// - /// - See: `HookGroup` - associatedtype Group: HookGroup = DefaultGroup - - /// The `HookGroup` associated with this hook type. - /// - /// Do not attempt to implement this yourself; use the default - /// implementation. - static var group: Group { get } } -extension AnyHookBase { +/// :nodoc: +extension AnyHook { public static func hookWillActivate() -> Bool { true } public static func hookDidActivate() {} } -/// A concrete hook, implemented in the glue file. Do not use -/// this directly. +/// A protocol that is implemented in Orion's glue file for each +/// hook, which performs the actual hooking. +/// +/// This protocol (and its refinements) serve as the bridge between +/// the user's code and the glue file. For every hook that the user +/// declares, the glue file extends it with a `_Glue` associatedtype +/// that conforms to one of the `_Glue*Hook` types and contains the +/// actual hook implementation. +/// +/// The source files still compile in the absence of such an extension +/// since the `_Glue` associatedtype has a placeholder value, which +/// allows SourceKit to play nicely with the user's source files even +/// if the glue file hasn't been compiled yet. On the other hand, if +/// the glue file _is_ compiled then the compiler prefers the `_Glue` +/// type provided by the glue file's extensions over the placeholder, +/// which changes the code's behavior and enables it to actually perform +/// the desired hooking. /// /// :nodoc: -public protocol _AnyGlueHook: AnyHookBase { +public protocol _GlueAnyHook { /// Activates the hook. Do not call this directly. static func activate() -> [HookDescriptor] + /// Trampoline for `AnyHook.hookWillActivate()`. Do not call + /// this directly. + static func hookWillActivate() -> Bool + + /// Trampoline for `AnyHook.hookDidActivate()`. Do not call + /// this directly. + static func hookDidActivate() + /// The type-erased `HookGroup` associated with this hook. Do /// not use this yourself. static var groupType: HookGroup.Type { get } } - -/// :nodoc: -extension _AnyGlueHook where Self: AnyHook { - public static var groupType: HookGroup.Type { Group.self } -} diff --git a/Sources/Orion/Tweak.swift b/Sources/Orion/Tweak.swift index bc84fab..ea44bdc 100644 --- a/Sources/Orion/Tweak.swift +++ b/Sources/Orion/Tweak.swift @@ -35,7 +35,7 @@ extension Tweak { /// Activates the tweak. Do not call this yourself. /// /// :nodoc: - public static func activate(backend: BackendType, hooks: [_AnyGlueHook.Type]) { + public static func activate(backend: BackendType, hooks: [_GlueAnyHook.Type]) { #if SWIFT_PACKAGE // this is effectively a no-op but we need it in order to prevent the // compiler from stripping out the constructor because it doesn't see @@ -73,7 +73,7 @@ extension TweakWithBackend { /// Activates the tweak. Do not call this yourself. /// /// :nodoc: - public static func activate(hooks: [_AnyGlueHook.Type]) { + public static func activate(hooks: [_GlueAnyHook.Type]) { activate(backend: backend, hooks: hooks) } diff --git a/Sources/OrionProcessor/OrionGenerator.swift b/Sources/OrionProcessor/OrionGenerator.swift index fbdb7cd..36a1429 100644 --- a/Sources/OrionProcessor/OrionGenerator.swift +++ b/Sources/OrionProcessor/OrionGenerator.swift @@ -110,7 +110,7 @@ public final class OrionGenerator { """ register = """ - builder.addDeinitializer(to: self, getOrig: { \(origIdent) }, setOrig: { \(origIdent) = $0 }) + builder.addDeinitializer(to: \(className).self, getOrig: { \(origIdent) }, setOrig: { \(origIdent) = $0 }) """ let main = """ @@ -132,13 +132,13 @@ public final class OrionGenerator { orig = """ \(funcOverride) { - Self.\(origIdent)(target, Self.\(selIdent)\(commaArgs)) + _Glue.\(origIdent)(target, _Glue.\(selIdent)\(commaArgs)) } """ supr = """ \(funcOverride) { - callSuper((@convention(c) \(method.superClosure)).self) { $0($1, Self.\(selIdent)\(commaArgs)) } + callSuper((@convention(c) \(method.superClosure)).self) { $0($1, _Glue.\(selIdent)\(commaArgs)) } } """ @@ -149,9 +149,9 @@ public final class OrionGenerator { // say there's a method foo() and another named foo(bar:). #selector(foo) will result in an error // because it could refer to either. Adding the signature disambiguates. - let selSig = "\(method.isClassMethod ? "" : "(Self) -> ")\(method.function.closure)" + let selSig = "\(method.isClassMethod ? "" : "(\(className)) -> ")\(method.function.closure)" let main = """ - private static let \(selIdent) = #selector(\(method.function.identifier) as \(selSig)) + private static let \(selIdent) = #selector(\(className).\(method.function.identifier) as \(selSig)) private static var \(origIdent): @convention(c) \(method.methodClosure) = { target, _cmd\(commaArgs) in \(className)\(method.isClassMethod ? "" : "(target: target)").\(method.function.identifier)(\(argsList)) } @@ -171,61 +171,59 @@ public final class OrionGenerator { return "\n\(joined)\n\(outdent)" } - let className = "Orion_ClassHook\(idx)" - let (origs, suprs, mains, registers) = classHook.methods.enumerated() - .map { generateConcreteMethodData(from: $1, className: className, index: $0 + 1) } + .map { generateConcreteMethodData(from: $1, className: classHook.name, index: $0 + 1) } .unzip() - let indentedOrigs = indentAndJoin(origs.compactMap { $0 }, by: 2) - let indentedSuprs = indentAndJoin(suprs.compactMap { $0 }, by: 2) - let indentedMains = indentAndJoin(mains, by: 1) + let indentedOrigs = indentAndJoin(origs.compactMap { $0 }, by: 3) + let indentedSuprs = indentAndJoin(suprs.compactMap { $0 }, by: 3) + let indentedMains = indentAndJoin(mains, by: 2) let hook = """ extension \(classHook.name) { - public static let _storage = _initializeStorage() - } + enum _Glue: _GlueClassHook { + typealias HookType = \(classHook.name) + + final class OrigType: \(classHook.name), _GlueClassHookTrampoline {\(indentedOrigs)} - private class \(className): \(classHook.name), _GlueClassHook { - final class OrigType: \(className) {\(indentedOrigs)} + final class SuprType: \(classHook.name), _GlueClassHookTrampoline {\(indentedSuprs)} - final class SuprType: \(className) {\(indentedSuprs)} + static let storage = initializeStorage() \(indentedMains) - static func activate(withClassHookBuilder builder: inout _ClassHookBuilder) { - \(registers.joined(separator: "\n ")) + static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) { + \(registers.joined(separator: "\n ")) + } } } """ - return (hook, className) + return (hook, "\(classHook.name)._Glue") } private func generateConcreteFunctionHook(from functionHook: OrionData.FunctionHook, idx: Int) -> (hook: String, name: String) { - let className = "Orion_FunctionHook\(idx)" - let shared = "orion_shared" let args = arguments(for: functionHook.function) let argsList = args.joined(separator: ", ") let argsIn = args.isEmpty ? "" : "\(argsList) in" let hook = """ extension \(functionHook.name) { - public static let _storage = _initializeStorage() - } + enum _Glue: _GlueFunctionHook { + typealias HookType = \(functionHook.name) - private class \(className): \(functionHook.name), _GlueFunctionHook { - static let \(shared) = \(className)() - - static var origFunction: @convention(c) \(functionHook.function.closure) = { \(argsIn) - \(className).\(shared).\(functionHook.function.identifier)(\(argsList)) - } + final class OrigType: \(functionHook.name), _GlueFunctionHookTrampoline { + \(functionHook.function.function) { + _Glue.origFunction(\(argsList)) + } + } - final class OrigType: \(className) { - \(functionHook.function.function) { - Self.origFunction(\(argsList)) + static var origFunction: @convention(c) \(functionHook.function.closure) = { \(argsIn) + \(functionHook.name)().\(functionHook.function.identifier)(\(argsList)) } + + static let storage = initializeStorage() } } """ - return (hook, className) + return (hook, "\(functionHook.name)._Glue") } private func join(_ items: [String], separation: String = "\n\n") -> String { diff --git a/Sources/OrionProcessor/OrionVisitor.swift b/Sources/OrionProcessor/OrionVisitor.swift index 4ef5619..b3d81f0 100644 --- a/Sources/OrionProcessor/OrionVisitor.swift +++ b/Sources/OrionProcessor/OrionVisitor.swift @@ -95,7 +95,7 @@ class OrionVisitor: SyntaxVisitor { // don't consider these names as method hooks private static let ignoredMethodNames: Set = [ - // these are the optional AnyHookBase protocol methods; don't treat them as hooks + // these are the optional AnyHook protocol methods; don't treat them as hooks "hookWillActivate", "hookDidActivate" ] diff --git a/Tests/OrionTests/Generated.xc.swift b/Tests/OrionTests/Generated.xc.swift index 874f0fb..c600c1b 100644 --- a/Tests/OrionTests/Generated.xc.swift +++ b/Tests/OrionTests/Generated.xc.swift @@ -6,710 +6,748 @@ import OrionBackend_Fishhook import OrionTestSupport extension BasicHook { - public static let _storage = _initializeStorage() -} + enum _Glue: _GlueClassHook { + typealias HookType = BasicHook -private class Orion_ClassHook1: BasicHook, _GlueClassHook { - final class OrigType: Orion_ClassHook1 { - @objc override func someTestMethod() -> String { - Self.orion_orig1(target, Self.orion_sel1) - } + final class OrigType: BasicHook, _GlueClassHookTrampoline { + @objc override func someTestMethod() -> String { + _Glue.orion_orig1(target, _Glue.orion_sel1) + } - @objc override func someTestMethod(withArgument arg1: Int32) -> String { - Self.orion_orig2(target, Self.orion_sel2, arg1) - } + @objc override func someTestMethod(withArgument arg1: Int32) -> String { + _Glue.orion_orig2(target, _Glue.orion_sel2, arg1) + } - @objc class override func someTestMethod2(withArgument arg1: Int32) -> String { - Self.orion_orig3(target, Self.orion_sel3, arg1) + @objc class override func someTestMethod2(withArgument arg1: Int32) -> String { + _Glue.orion_orig3(target, _Glue.orion_sel3, arg1) + } } - } - final class SuprType: Orion_ClassHook1 { - @objc override func someTestMethod() -> String { - callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, Self.orion_sel1) } - } + final class SuprType: BasicHook, _GlueClassHookTrampoline { + @objc override func someTestMethod() -> String { + callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, _Glue.orion_sel1) } + } - @objc override func someTestMethod(withArgument arg1: Int32) -> String { - callSuper((@convention(c) (UnsafeRawPointer, Selector, Int32) -> String).self) { $0($1, Self.orion_sel2, arg1) } - } + @objc override func someTestMethod(withArgument arg1: Int32) -> String { + callSuper((@convention(c) (UnsafeRawPointer, Selector, Int32) -> String).self) { $0($1, _Glue.orion_sel2, arg1) } + } - @objc class override func someTestMethod2(withArgument arg1: Int32) -> String { - callSuper((@convention(c) (UnsafeRawPointer, Selector, Int32) -> String).self) { $0($1, Self.orion_sel3, arg1) } + @objc class override func someTestMethod2(withArgument arg1: Int32) -> String { + callSuper((@convention(c) (UnsafeRawPointer, Selector, Int32) -> String).self) { $0($1, _Glue.orion_sel3, arg1) } + } } - } - private static let orion_sel1 = #selector(someTestMethod as (Self) -> () -> String) - private static var orion_orig1: @convention(c) (Target, Selector) -> String = { target, _cmd in - Orion_ClassHook1(target: target).someTestMethod() - } + static let storage = initializeStorage() - private static let orion_sel2 = #selector(someTestMethod(withArgument:) as (Self) -> (Int32) -> String) - private static var orion_orig2: @convention(c) (Target, Selector, Int32) -> String = { target, _cmd, arg1 in - Orion_ClassHook1(target: target).someTestMethod(withArgument:)(arg1) - } + private static let orion_sel1 = #selector(BasicHook.someTestMethod as (BasicHook) -> () -> String) + private static var orion_orig1: @convention(c) (Target, Selector) -> String = { target, _cmd in + BasicHook(target: target).someTestMethod() + } - private static let orion_sel3 = #selector(someTestMethod2(withArgument:) as (Int32) -> String) - private static var orion_orig3: @convention(c) (AnyClass, Selector, Int32) -> String = { target, _cmd, arg1 in - Orion_ClassHook1.someTestMethod2(withArgument:)(arg1) - } + private static let orion_sel2 = #selector(BasicHook.someTestMethod(withArgument:) as (BasicHook) -> (Int32) -> String) + private static var orion_orig2: @convention(c) (Target, Selector, Int32) -> String = { target, _cmd, arg1 in + BasicHook(target: target).someTestMethod(withArgument:)(arg1) + } - static func activate(withClassHookBuilder builder: inout _ClassHookBuilder) { - builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } - builder.addHook(orion_sel2, orion_orig2, isClassMethod: false) { orion_orig2 = $0 } - builder.addHook(orion_sel3, orion_orig3, isClassMethod: true) { orion_orig3 = $0 } + private static let orion_sel3 = #selector(BasicHook.someTestMethod2(withArgument:) as (Int32) -> String) + private static var orion_orig3: @convention(c) (AnyClass, Selector, Int32) -> String = { target, _cmd, arg1 in + BasicHook.someTestMethod2(withArgument:)(arg1) + } + + static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) { + builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } + builder.addHook(orion_sel2, orion_orig2, isClassMethod: false) { orion_orig2 = $0 } + builder.addHook(orion_sel3, orion_orig3, isClassMethod: true) { orion_orig3 = $0 } + } } } extension ActivationHook { - public static let _storage = _initializeStorage() -} + enum _Glue: _GlueClassHook { + typealias HookType = ActivationHook -private class Orion_ClassHook2: ActivationHook, _GlueClassHook { - final class OrigType: Orion_ClassHook2 { - @objc override func someDidActivateMethod() -> String { - Self.orion_orig1(target, Self.orion_sel1) + final class OrigType: ActivationHook, _GlueClassHookTrampoline { + @objc override func someDidActivateMethod() -> String { + _Glue.orion_orig1(target, _Glue.orion_sel1) + } } - } - final class SuprType: Orion_ClassHook2 { - @objc override func someDidActivateMethod() -> String { - callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, Self.orion_sel1) } + final class SuprType: ActivationHook, _GlueClassHookTrampoline { + @objc override func someDidActivateMethod() -> String { + callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, _Glue.orion_sel1) } + } } - } - private static let orion_sel1 = #selector(someDidActivateMethod as (Self) -> () -> String) - private static var orion_orig1: @convention(c) (Target, Selector) -> String = { target, _cmd in - Orion_ClassHook2(target: target).someDidActivateMethod() - } + static let storage = initializeStorage() - static func activate(withClassHookBuilder builder: inout _ClassHookBuilder) { - builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } + private static let orion_sel1 = #selector(ActivationHook.someDidActivateMethod as (ActivationHook) -> () -> String) + private static var orion_orig1: @convention(c) (Target, Selector) -> String = { target, _cmd in + ActivationHook(target: target).someDidActivateMethod() + } + + static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) { + builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } + } } } extension NotHook { - public static let _storage = _initializeStorage() -} + enum _Glue: _GlueClassHook { + typealias HookType = NotHook -private class Orion_ClassHook3: NotHook, _GlueClassHook { - final class OrigType: Orion_ClassHook3 { - @objc override func someUnhookedMethod() -> String { - Self.orion_orig1(target, Self.orion_sel1) + final class OrigType: NotHook, _GlueClassHookTrampoline { + @objc override func someUnhookedMethod() -> String { + _Glue.orion_orig1(target, _Glue.orion_sel1) + } } - } - final class SuprType: Orion_ClassHook3 { - @objc override func someUnhookedMethod() -> String { - callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, Self.orion_sel1) } + final class SuprType: NotHook, _GlueClassHookTrampoline { + @objc override func someUnhookedMethod() -> String { + callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, _Glue.orion_sel1) } + } } - } - private static let orion_sel1 = #selector(someUnhookedMethod as (Self) -> () -> String) - private static var orion_orig1: @convention(c) (Target, Selector) -> String = { target, _cmd in - Orion_ClassHook3(target: target).someUnhookedMethod() - } + static let storage = initializeStorage() - static func activate(withClassHookBuilder builder: inout _ClassHookBuilder) { - builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } + private static let orion_sel1 = #selector(NotHook.someUnhookedMethod as (NotHook) -> () -> String) + private static var orion_orig1: @convention(c) (Target, Selector) -> String = { target, _cmd in + NotHook(target: target).someUnhookedMethod() + } + + static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) { + builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } + } } } extension NamedBasicHook { - public static let _storage = _initializeStorage() -} + enum _Glue: _GlueClassHook { + typealias HookType = NamedBasicHook -private class Orion_ClassHook4: NamedBasicHook, _GlueClassHook { - final class OrigType: Orion_ClassHook4 { - @objc override func methodForNamedTest() -> Bool { - Self.orion_orig1(target, Self.orion_sel1) - } + final class OrigType: NamedBasicHook, _GlueClassHookTrampoline { + @objc override func methodForNamedTest() -> Bool { + _Glue.orion_orig1(target, _Glue.orion_sel1) + } - @objc class override func classMethodForNamedTest(withArgument arg1: String) -> [String] { - Self.orion_orig2(target, Self.orion_sel2, arg1) + @objc class override func classMethodForNamedTest(withArgument arg1: String) -> [String] { + _Glue.orion_orig2(target, _Glue.orion_sel2, arg1) + } } - } - final class SuprType: Orion_ClassHook4 { - @objc override func methodForNamedTest() -> Bool { - callSuper((@convention(c) (UnsafeRawPointer, Selector) -> Bool).self) { $0($1, Self.orion_sel1) } - } + final class SuprType: NamedBasicHook, _GlueClassHookTrampoline { + @objc override func methodForNamedTest() -> Bool { + callSuper((@convention(c) (UnsafeRawPointer, Selector) -> Bool).self) { $0($1, _Glue.orion_sel1) } + } - @objc class override func classMethodForNamedTest(withArgument arg1: String) -> [String] { - callSuper((@convention(c) (UnsafeRawPointer, Selector, String) -> [String]).self) { $0($1, Self.orion_sel2, arg1) } + @objc class override func classMethodForNamedTest(withArgument arg1: String) -> [String] { + callSuper((@convention(c) (UnsafeRawPointer, Selector, String) -> [String]).self) { $0($1, _Glue.orion_sel2, arg1) } + } } - } - private static let orion_sel1 = #selector(methodForNamedTest as (Self) -> () -> Bool) - private static var orion_orig1: @convention(c) (Target, Selector) -> Bool = { target, _cmd in - Orion_ClassHook4(target: target).methodForNamedTest() - } + static let storage = initializeStorage() - private static let orion_sel2 = #selector(classMethodForNamedTest(withArgument:) as (String) -> [String]) - private static var orion_orig2: @convention(c) (AnyClass, Selector, String) -> [String] = { target, _cmd, arg1 in - Orion_ClassHook4.classMethodForNamedTest(withArgument:)(arg1) - } + private static let orion_sel1 = #selector(NamedBasicHook.methodForNamedTest as (NamedBasicHook) -> () -> Bool) + private static var orion_orig1: @convention(c) (Target, Selector) -> Bool = { target, _cmd in + NamedBasicHook(target: target).methodForNamedTest() + } - static func activate(withClassHookBuilder builder: inout _ClassHookBuilder) { - builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } - builder.addHook(orion_sel2, orion_orig2, isClassMethod: true) { orion_orig2 = $0 } + private static let orion_sel2 = #selector(NamedBasicHook.classMethodForNamedTest(withArgument:) as (String) -> [String]) + private static var orion_orig2: @convention(c) (AnyClass, Selector, String) -> [String] = { target, _cmd, arg1 in + NamedBasicHook.classMethodForNamedTest(withArgument:)(arg1) + } + + static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) { + builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } + builder.addHook(orion_sel2, orion_orig2, isClassMethod: true) { orion_orig2 = $0 } + } } } extension BasicSubclass { - public static let _storage = _initializeStorage() -} + enum _Glue: _GlueClassHook { + typealias HookType = BasicSubclass -private class Orion_ClassHook5: BasicSubclass, _GlueClassHook { - final class OrigType: Orion_ClassHook5 { - @objc override func someTestMethod() -> String { - Self.orion_orig1(target, Self.orion_sel1) - } + final class OrigType: BasicSubclass, _GlueClassHookTrampoline { + @objc override func someTestMethod() -> String { + _Glue.orion_orig1(target, _Glue.orion_sel1) + } - @objc override func subclassableTestMethod() -> String { - Self.orion_orig3(target, Self.orion_sel3) - } + @objc override func subclassableTestMethod() -> String { + _Glue.orion_orig3(target, _Glue.orion_sel3) + } - @objc class override func subclassableTestMethod1() -> String { - Self.orion_orig4(target, Self.orion_sel4) + @objc class override func subclassableTestMethod1() -> String { + _Glue.orion_orig4(target, _Glue.orion_sel4) + } } - } - final class SuprType: Orion_ClassHook5 { - @objc override func someTestMethod() -> String { - callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, Self.orion_sel1) } - } + final class SuprType: BasicSubclass, _GlueClassHookTrampoline { + @objc override func someTestMethod() -> String { + callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, _Glue.orion_sel1) } + } - @objc override func subclassableTestMethod() -> String { - callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, Self.orion_sel3) } - } + @objc override func subclassableTestMethod() -> String { + callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, _Glue.orion_sel3) } + } - @objc class override func subclassableTestMethod1() -> String { - callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, Self.orion_sel4) } + @objc class override func subclassableTestMethod1() -> String { + callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, _Glue.orion_sel4) } + } } - } - private static let orion_sel1 = #selector(someTestMethod as (Self) -> () -> String) - private static var orion_orig1: @convention(c) (Target, Selector) -> String = { target, _cmd in - Orion_ClassHook5(target: target).someTestMethod() - } + static let storage = initializeStorage() - private static let orion_sel2 = #selector(someNewMethod as (Self) -> () -> String) - private static var orion_imp2: @convention(c) (Target, Selector) -> String = { target, _cmd in - Orion_ClassHook5(target: target).someNewMethod() - } + private static let orion_sel1 = #selector(BasicSubclass.someTestMethod as (BasicSubclass) -> () -> String) + private static var orion_orig1: @convention(c) (Target, Selector) -> String = { target, _cmd in + BasicSubclass(target: target).someTestMethod() + } - private static let orion_sel3 = #selector(subclassableTestMethod as (Self) -> () -> String) - private static var orion_orig3: @convention(c) (Target, Selector) -> String = { target, _cmd in - Orion_ClassHook5(target: target).subclassableTestMethod() - } + private static let orion_sel2 = #selector(BasicSubclass.someNewMethod as (BasicSubclass) -> () -> String) + private static var orion_imp2: @convention(c) (Target, Selector) -> String = { target, _cmd in + BasicSubclass(target: target).someNewMethod() + } - private static let orion_sel4 = #selector(subclassableTestMethod1 as () -> String) - private static var orion_orig4: @convention(c) (AnyClass, Selector) -> String = { target, _cmd in - Orion_ClassHook5.subclassableTestMethod1() - } + private static let orion_sel3 = #selector(BasicSubclass.subclassableTestMethod as (BasicSubclass) -> () -> String) + private static var orion_orig3: @convention(c) (Target, Selector) -> String = { target, _cmd in + BasicSubclass(target: target).subclassableTestMethod() + } - static func activate(withClassHookBuilder builder: inout _ClassHookBuilder) { - builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } - addMethod(orion_sel2, orion_imp2, isClassMethod: false) - builder.addHook(orion_sel3, orion_orig3, isClassMethod: false) { orion_orig3 = $0 } - builder.addHook(orion_sel4, orion_orig4, isClassMethod: true) { orion_orig4 = $0 } + private static let orion_sel4 = #selector(BasicSubclass.subclassableTestMethod1 as () -> String) + private static var orion_orig4: @convention(c) (AnyClass, Selector) -> String = { target, _cmd in + BasicSubclass.subclassableTestMethod1() + } + + static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) { + builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } + addMethod(orion_sel2, orion_imp2, isClassMethod: false) + builder.addHook(orion_sel3, orion_orig3, isClassMethod: false) { orion_orig3 = $0 } + builder.addHook(orion_sel4, orion_orig4, isClassMethod: true) { orion_orig4 = $0 } + } } } extension NamedBasicSubclass { - public static let _storage = _initializeStorage() -} + enum _Glue: _GlueClassHook { + typealias HookType = NamedBasicSubclass -private class Orion_ClassHook6: NamedBasicSubclass, _GlueClassHook { - final class OrigType: Orion_ClassHook6 { - @objc override func subclassableNamedTestMethod() -> String { - Self.orion_orig1(target, Self.orion_sel1) - } + final class OrigType: NamedBasicSubclass, _GlueClassHookTrampoline { + @objc override func subclassableNamedTestMethod() -> String { + _Glue.orion_orig1(target, _Glue.orion_sel1) + } - @objc class override func subclassableNamedTestMethod1() -> String { - Self.orion_orig2(target, Self.orion_sel2) + @objc class override func subclassableNamedTestMethod1() -> String { + _Glue.orion_orig2(target, _Glue.orion_sel2) + } } - } - final class SuprType: Orion_ClassHook6 { - @objc override func subclassableNamedTestMethod() -> String { - callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, Self.orion_sel1) } - } + final class SuprType: NamedBasicSubclass, _GlueClassHookTrampoline { + @objc override func subclassableNamedTestMethod() -> String { + callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, _Glue.orion_sel1) } + } - @objc class override func subclassableNamedTestMethod1() -> String { - callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, Self.orion_sel2) } + @objc class override func subclassableNamedTestMethod1() -> String { + callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, _Glue.orion_sel2) } + } } - } - private static let orion_sel1 = #selector(subclassableNamedTestMethod as (Self) -> () -> String) - private static var orion_orig1: @convention(c) (Target, Selector) -> String = { target, _cmd in - Orion_ClassHook6(target: target).subclassableNamedTestMethod() - } + static let storage = initializeStorage() - private static let orion_sel2 = #selector(subclassableNamedTestMethod1 as () -> String) - private static var orion_orig2: @convention(c) (AnyClass, Selector) -> String = { target, _cmd in - Orion_ClassHook6.subclassableNamedTestMethod1() - } + private static let orion_sel1 = #selector(NamedBasicSubclass.subclassableNamedTestMethod as (NamedBasicSubclass) -> () -> String) + private static var orion_orig1: @convention(c) (Target, Selector) -> String = { target, _cmd in + NamedBasicSubclass(target: target).subclassableNamedTestMethod() + } - static func activate(withClassHookBuilder builder: inout _ClassHookBuilder) { - builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } - builder.addHook(orion_sel2, orion_orig2, isClassMethod: true) { orion_orig2 = $0 } + private static let orion_sel2 = #selector(NamedBasicSubclass.subclassableNamedTestMethod1 as () -> String) + private static var orion_orig2: @convention(c) (AnyClass, Selector) -> String = { target, _cmd in + NamedBasicSubclass.subclassableNamedTestMethod1() + } + + static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) { + builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } + builder.addHook(orion_sel2, orion_orig2, isClassMethod: true) { orion_orig2 = $0 } + } } } extension AdditionHook { - public static let _storage = _initializeStorage() -} + enum _Glue: _GlueClassHook { + typealias HookType = AdditionHook -private class Orion_ClassHook7: AdditionHook, _GlueClassHook { - final class OrigType: Orion_ClassHook7 {} + final class OrigType: AdditionHook, _GlueClassHookTrampoline {} - final class SuprType: Orion_ClassHook7 {} + final class SuprType: AdditionHook, _GlueClassHookTrampoline {} - private static let orion_sel1 = #selector(someTestProtocolMethod as (Self) -> () -> String) - private static var orion_imp1: @convention(c) (Target, Selector) -> String = { target, _cmd in - Orion_ClassHook7(target: target).someTestProtocolMethod() - } + static let storage = initializeStorage() - private static let orion_sel2 = #selector(someTestProtocolClassMethod as () -> String) - private static var orion_imp2: @convention(c) (AnyClass, Selector) -> String = { target, _cmd in - Orion_ClassHook7.someTestProtocolClassMethod() - } + private static let orion_sel1 = #selector(AdditionHook.someTestProtocolMethod as (AdditionHook) -> () -> String) + private static var orion_imp1: @convention(c) (Target, Selector) -> String = { target, _cmd in + AdditionHook(target: target).someTestProtocolMethod() + } - static func activate(withClassHookBuilder builder: inout _ClassHookBuilder) { - addMethod(orion_sel1, orion_imp1, isClassMethod: false) - addMethod(orion_sel2, orion_imp2, isClassMethod: true) + private static let orion_sel2 = #selector(AdditionHook.someTestProtocolClassMethod as () -> String) + private static var orion_imp2: @convention(c) (AnyClass, Selector) -> String = { target, _cmd in + AdditionHook.someTestProtocolClassMethod() + } + + static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) { + addMethod(orion_sel1, orion_imp1, isClassMethod: false) + addMethod(orion_sel2, orion_imp2, isClassMethod: true) + } } } extension InheritedHook { - public static let _storage = _initializeStorage() -} + enum _Glue: _GlueClassHook { + typealias HookType = InheritedHook -private class Orion_ClassHook8: InheritedHook, _GlueClassHook { - final class OrigType: Orion_ClassHook8 { - @objc class override func someTestMethod3() -> String { - Self.orion_orig1(target, Self.orion_sel1) + final class OrigType: InheritedHook, _GlueClassHookTrampoline { + @objc class override func someTestMethod3() -> String { + _Glue.orion_orig1(target, _Glue.orion_sel1) + } } - } - final class SuprType: Orion_ClassHook8 { - @objc class override func someTestMethod3() -> String { - callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, Self.orion_sel1) } + final class SuprType: InheritedHook, _GlueClassHookTrampoline { + @objc class override func someTestMethod3() -> String { + callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, _Glue.orion_sel1) } + } } - } - private static let orion_sel1 = #selector(someTestMethod3 as () -> String) - private static var orion_orig1: @convention(c) (AnyClass, Selector) -> String = { target, _cmd in - Orion_ClassHook8.someTestMethod3() - } + static let storage = initializeStorage() - static func activate(withClassHookBuilder builder: inout _ClassHookBuilder) { - builder.addHook(orion_sel1, orion_orig1, isClassMethod: true) { orion_orig1 = $0 } + private static let orion_sel1 = #selector(InheritedHook.someTestMethod3 as () -> String) + private static var orion_orig1: @convention(c) (AnyClass, Selector) -> String = { target, _cmd in + InheritedHook.someTestMethod3() + } + + static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) { + builder.addHook(orion_sel1, orion_orig1, isClassMethod: true) { orion_orig1 = $0 } + } } } extension InitHook { - public static let _storage = _initializeStorage() -} + enum _Glue: _GlueClassHook { + typealias HookType = InitHook -private class Orion_ClassHook9: InitHook, _GlueClassHook { - final class OrigType: Orion_ClassHook9 { - @objc override func `init`() -> Target { - Self.orion_orig1(target, Self.orion_sel1) - } + final class OrigType: InitHook, _GlueClassHookTrampoline { + @objc override func `init`() -> Target { + _Glue.orion_orig1(target, _Glue.orion_sel1) + } - @objc override func `init`(withX arg1: Int32) -> Target { - Self.orion_orig2(target, Self.orion_sel2, arg1) + @objc override func `init`(withX arg1: Int32) -> Target { + _Glue.orion_orig2(target, _Glue.orion_sel2, arg1) + } } - } - final class SuprType: Orion_ClassHook9 { - @objc override func `init`() -> Target { - callSuper((@convention(c) (UnsafeRawPointer, Selector) -> Target).self) { $0($1, Self.orion_sel1) } - } + final class SuprType: InitHook, _GlueClassHookTrampoline { + @objc override func `init`() -> Target { + callSuper((@convention(c) (UnsafeRawPointer, Selector) -> Target).self) { $0($1, _Glue.orion_sel1) } + } - @objc override func `init`(withX arg1: Int32) -> Target { - callSuper((@convention(c) (UnsafeRawPointer, Selector, Int32) -> Target).self) { $0($1, Self.orion_sel2, arg1) } + @objc override func `init`(withX arg1: Int32) -> Target { + callSuper((@convention(c) (UnsafeRawPointer, Selector, Int32) -> Target).self) { $0($1, _Glue.orion_sel2, arg1) } + } } - } - private static let orion_sel1 = #selector(`init` as (Self) -> () -> Target) - private static var orion_orig1: @convention(c) (Target, Selector) -> Target = { target, _cmd in - Orion_ClassHook9(target: target).`init`() - } + static let storage = initializeStorage() - private static let orion_sel2 = #selector(`init`(withX:) as (Self) -> (Int32) -> Target) - private static var orion_orig2: @convention(c) (Target, Selector, Int32) -> Target = { target, _cmd, arg1 in - Orion_ClassHook9(target: target).`init`(withX:)(arg1) - } + private static let orion_sel1 = #selector(InitHook.`init` as (InitHook) -> () -> Target) + private static var orion_orig1: @convention(c) (Target, Selector) -> Target = { target, _cmd in + InitHook(target: target).`init`() + } - static func activate(withClassHookBuilder builder: inout _ClassHookBuilder) { - builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } - builder.addHook(orion_sel2, orion_orig2, isClassMethod: false) { orion_orig2 = $0 } + private static let orion_sel2 = #selector(InitHook.`init`(withX:) as (InitHook) -> (Int32) -> Target) + private static var orion_orig2: @convention(c) (Target, Selector, Int32) -> Target = { target, _cmd, arg1 in + InitHook(target: target).`init`(withX:)(arg1) + } + + static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) { + builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } + builder.addHook(orion_sel2, orion_orig2, isClassMethod: false) { orion_orig2 = $0 } + } } } extension SuperHook { - public static let _storage = _initializeStorage() -} + enum _Glue: _GlueClassHook { + typealias HookType = SuperHook -private class Orion_ClassHook10: SuperHook, _GlueClassHook { - final class OrigType: Orion_ClassHook10 { - @objc override func description() -> String { - Self.orion_orig1(target, Self.orion_sel1) - } + final class OrigType: SuperHook, _GlueClassHookTrampoline { + @objc override func description() -> String { + _Glue.orion_orig1(target, _Glue.orion_sel1) + } - @objc override func hooked() -> String { - Self.orion_orig2(target, Self.orion_sel2) + @objc override func hooked() -> String { + _Glue.orion_orig2(target, _Glue.orion_sel2) + } } - } - final class SuprType: Orion_ClassHook10 { - @objc override func description() -> String { - callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, Self.orion_sel1) } - } + final class SuprType: SuperHook, _GlueClassHookTrampoline { + @objc override func description() -> String { + callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, _Glue.orion_sel1) } + } - @objc override func hooked() -> String { - callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, Self.orion_sel2) } + @objc override func hooked() -> String { + callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, _Glue.orion_sel2) } + } } - } - private static let orion_sel1 = #selector(description as (Self) -> () -> String) - private static var orion_orig1: @convention(c) (Target, Selector) -> String = { target, _cmd in - Orion_ClassHook10(target: target).description() - } + static let storage = initializeStorage() - private static let orion_sel2 = #selector(hooked as (Self) -> () -> String) - private static var orion_orig2: @convention(c) (Target, Selector) -> String = { target, _cmd in - Orion_ClassHook10(target: target).hooked() - } + private static let orion_sel1 = #selector(SuperHook.description as (SuperHook) -> () -> String) + private static var orion_orig1: @convention(c) (Target, Selector) -> String = { target, _cmd in + SuperHook(target: target).description() + } - static func activate(withClassHookBuilder builder: inout _ClassHookBuilder) { - builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } - builder.addHook(orion_sel2, orion_orig2, isClassMethod: false) { orion_orig2 = $0 } + private static let orion_sel2 = #selector(SuperHook.hooked as (SuperHook) -> () -> String) + private static var orion_orig2: @convention(c) (Target, Selector) -> String = { target, _cmd in + SuperHook(target: target).hooked() + } + + static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) { + builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } + builder.addHook(orion_sel2, orion_orig2, isClassMethod: false) { orion_orig2 = $0 } + } } } extension PropertyHookX { - public static let _storage = _initializeStorage() -} + enum _Glue: _GlueClassHook { + typealias HookType = PropertyHookX -private class Orion_ClassHook11: PropertyHookX, _GlueClassHook { - final class OrigType: Orion_ClassHook11 { - @objc override func getXValue() -> Int { - Self.orion_orig1(target, Self.orion_sel1) - } + final class OrigType: PropertyHookX, _GlueClassHookTrampoline { + @objc override func getXValue() -> Int { + _Glue.orion_orig1(target, _Glue.orion_sel1) + } - @objc override func setXValue(_ arg1: Int) { - Self.orion_orig2(target, Self.orion_sel2, arg1) + @objc override func setXValue(_ arg1: Int) { + _Glue.orion_orig2(target, _Glue.orion_sel2, arg1) + } } - } - final class SuprType: Orion_ClassHook11 { - @objc override func getXValue() -> Int { - callSuper((@convention(c) (UnsafeRawPointer, Selector) -> Int).self) { $0($1, Self.orion_sel1) } - } + final class SuprType: PropertyHookX, _GlueClassHookTrampoline { + @objc override func getXValue() -> Int { + callSuper((@convention(c) (UnsafeRawPointer, Selector) -> Int).self) { $0($1, _Glue.orion_sel1) } + } - @objc override func setXValue(_ arg1: Int) { - callSuper((@convention(c) (UnsafeRawPointer, Selector, Int) -> Void).self) { $0($1, Self.orion_sel2, arg1) } + @objc override func setXValue(_ arg1: Int) { + callSuper((@convention(c) (UnsafeRawPointer, Selector, Int) -> Void).self) { $0($1, _Glue.orion_sel2, arg1) } + } } - } - private static let orion_sel1 = #selector(getXValue as (Self) -> () -> Int) - private static var orion_orig1: @convention(c) (Target, Selector) -> Int = { target, _cmd in - Orion_ClassHook11(target: target).getXValue() - } + static let storage = initializeStorage() - private static let orion_sel2 = #selector(setXValue(_:) as (Self) -> (Int) -> Void) - private static var orion_orig2: @convention(c) (Target, Selector, Int) -> Void = { target, _cmd, arg1 in - Orion_ClassHook11(target: target).setXValue(_:)(arg1) - } + private static let orion_sel1 = #selector(PropertyHookX.getXValue as (PropertyHookX) -> () -> Int) + private static var orion_orig1: @convention(c) (Target, Selector) -> Int = { target, _cmd in + PropertyHookX(target: target).getXValue() + } - static func activate(withClassHookBuilder builder: inout _ClassHookBuilder) { - builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } - builder.addHook(orion_sel2, orion_orig2, isClassMethod: false) { orion_orig2 = $0 } + private static let orion_sel2 = #selector(PropertyHookX.setXValue(_:) as (PropertyHookX) -> (Int) -> Void) + private static var orion_orig2: @convention(c) (Target, Selector, Int) -> Void = { target, _cmd, arg1 in + PropertyHookX(target: target).setXValue(_:)(arg1) + } + + static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) { + builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } + builder.addHook(orion_sel2, orion_orig2, isClassMethod: false) { orion_orig2 = $0 } + } } } extension PropertyHookY { - public static let _storage = _initializeStorage() -} + enum _Glue: _GlueClassHook { + typealias HookType = PropertyHookY -private class Orion_ClassHook12: PropertyHookY, _GlueClassHook { - final class OrigType: Orion_ClassHook12 { - @objc override func getYValue() -> Int { - Self.orion_orig1(target, Self.orion_sel1) - } + final class OrigType: PropertyHookY, _GlueClassHookTrampoline { + @objc override func getYValue() -> Int { + _Glue.orion_orig1(target, _Glue.orion_sel1) + } - @objc override func setYValue(_ arg1: Int) { - Self.orion_orig2(target, Self.orion_sel2, arg1) + @objc override func setYValue(_ arg1: Int) { + _Glue.orion_orig2(target, _Glue.orion_sel2, arg1) + } } - } - final class SuprType: Orion_ClassHook12 { - @objc override func getYValue() -> Int { - callSuper((@convention(c) (UnsafeRawPointer, Selector) -> Int).self) { $0($1, Self.orion_sel1) } - } + final class SuprType: PropertyHookY, _GlueClassHookTrampoline { + @objc override func getYValue() -> Int { + callSuper((@convention(c) (UnsafeRawPointer, Selector) -> Int).self) { $0($1, _Glue.orion_sel1) } + } - @objc override func setYValue(_ arg1: Int) { - callSuper((@convention(c) (UnsafeRawPointer, Selector, Int) -> Void).self) { $0($1, Self.orion_sel2, arg1) } + @objc override func setYValue(_ arg1: Int) { + callSuper((@convention(c) (UnsafeRawPointer, Selector, Int) -> Void).self) { $0($1, _Glue.orion_sel2, arg1) } + } } - } - private static let orion_sel1 = #selector(getYValue as (Self) -> () -> Int) - private static var orion_orig1: @convention(c) (Target, Selector) -> Int = { target, _cmd in - Orion_ClassHook12(target: target).getYValue() - } + static let storage = initializeStorage() - private static let orion_sel2 = #selector(setYValue(_:) as (Self) -> (Int) -> Void) - private static var orion_orig2: @convention(c) (Target, Selector, Int) -> Void = { target, _cmd, arg1 in - Orion_ClassHook12(target: target).setYValue(_:)(arg1) - } + private static let orion_sel1 = #selector(PropertyHookY.getYValue as (PropertyHookY) -> () -> Int) + private static var orion_orig1: @convention(c) (Target, Selector) -> Int = { target, _cmd in + PropertyHookY(target: target).getYValue() + } - static func activate(withClassHookBuilder builder: inout _ClassHookBuilder) { - builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } - builder.addHook(orion_sel2, orion_orig2, isClassMethod: false) { orion_orig2 = $0 } + private static let orion_sel2 = #selector(PropertyHookY.setYValue(_:) as (PropertyHookY) -> (Int) -> Void) + private static var orion_orig2: @convention(c) (Target, Selector, Int) -> Void = { target, _cmd, arg1 in + PropertyHookY(target: target).setYValue(_:)(arg1) + } + + static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) { + builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } + builder.addHook(orion_sel2, orion_orig2, isClassMethod: false) { orion_orig2 = $0 } + } } } extension PropertyHook2 { - public static let _storage = _initializeStorage() -} + enum _Glue: _GlueClassHook { + typealias HookType = PropertyHook2 -private class Orion_ClassHook13: PropertyHook2, _GlueClassHook { - final class OrigType: Orion_ClassHook13 { - @objc override func getXValue() -> Int { - Self.orion_orig1(target, Self.orion_sel1) - } + final class OrigType: PropertyHook2, _GlueClassHookTrampoline { + @objc override func getXValue() -> Int { + _Glue.orion_orig1(target, _Glue.orion_sel1) + } - @objc override func setXValue(_ arg1: Int) { - Self.orion_orig2(target, Self.orion_sel2, arg1) + @objc override func setXValue(_ arg1: Int) { + _Glue.orion_orig2(target, _Glue.orion_sel2, arg1) + } } - } - final class SuprType: Orion_ClassHook13 { - @objc override func getXValue() -> Int { - callSuper((@convention(c) (UnsafeRawPointer, Selector) -> Int).self) { $0($1, Self.orion_sel1) } - } + final class SuprType: PropertyHook2, _GlueClassHookTrampoline { + @objc override func getXValue() -> Int { + callSuper((@convention(c) (UnsafeRawPointer, Selector) -> Int).self) { $0($1, _Glue.orion_sel1) } + } - @objc override func setXValue(_ arg1: Int) { - callSuper((@convention(c) (UnsafeRawPointer, Selector, Int) -> Void).self) { $0($1, Self.orion_sel2, arg1) } + @objc override func setXValue(_ arg1: Int) { + callSuper((@convention(c) (UnsafeRawPointer, Selector, Int) -> Void).self) { $0($1, _Glue.orion_sel2, arg1) } + } } - } - private static let orion_sel1 = #selector(getXValue as (Self) -> () -> Int) - private static var orion_orig1: @convention(c) (Target, Selector) -> Int = { target, _cmd in - Orion_ClassHook13(target: target).getXValue() - } + static let storage = initializeStorage() - private static let orion_sel2 = #selector(setXValue(_:) as (Self) -> (Int) -> Void) - private static var orion_orig2: @convention(c) (Target, Selector, Int) -> Void = { target, _cmd, arg1 in - Orion_ClassHook13(target: target).setXValue(_:)(arg1) - } + private static let orion_sel1 = #selector(PropertyHook2.getXValue as (PropertyHook2) -> () -> Int) + private static var orion_orig1: @convention(c) (Target, Selector) -> Int = { target, _cmd in + PropertyHook2(target: target).getXValue() + } - static func activate(withClassHookBuilder builder: inout _ClassHookBuilder) { - builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } - builder.addHook(orion_sel2, orion_orig2, isClassMethod: false) { orion_orig2 = $0 } + private static let orion_sel2 = #selector(PropertyHook2.setXValue(_:) as (PropertyHook2) -> (Int) -> Void) + private static var orion_orig2: @convention(c) (Target, Selector, Int) -> Void = { target, _cmd, arg1 in + PropertyHook2(target: target).setXValue(_:)(arg1) + } + + static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) { + builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } + builder.addHook(orion_sel2, orion_orig2, isClassMethod: false) { orion_orig2 = $0 } + } } } extension DeHook { - public static let _storage = _initializeStorage() -} + enum _Glue: _GlueClassHook { + typealias HookType = DeHook -private class Orion_ClassHook14: DeHook, _GlueClassHook { - final class OrigType: Orion_ClassHook14 { - override func deinitializer() -> DeinitPolicy { - deinitOrigError() + final class OrigType: DeHook, _GlueClassHookTrampoline { + override func deinitializer() -> DeinitPolicy { + deinitOrigError() + } } - } - final class SuprType: Orion_ClassHook14 { - override func deinitializer() -> DeinitPolicy { - deinitSuprError() + final class SuprType: DeHook, _GlueClassHookTrampoline { + override func deinitializer() -> DeinitPolicy { + deinitSuprError() + } } - } - private static var orion_orig1: @convention(c) (Any, Selector) -> Void = { _, _ in } + static let storage = initializeStorage() - static func activate(withClassHookBuilder builder: inout _ClassHookBuilder) { - builder.addDeinitializer(to: self, getOrig: { orion_orig1 }, setOrig: { orion_orig1 = $0 }) + private static var orion_orig1: @convention(c) (Any, Selector) -> Void = { _, _ in } + + static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) { + builder.addDeinitializer(to: DeHook.self, getOrig: { orion_orig1 }, setOrig: { orion_orig1 = $0 }) + } } } extension DeSubHook1 { - public static let _storage = _initializeStorage() -} + enum _Glue: _GlueClassHook { + typealias HookType = DeSubHook1 -private class Orion_ClassHook15: DeSubHook1, _GlueClassHook { - final class OrigType: Orion_ClassHook15 {} + final class OrigType: DeSubHook1, _GlueClassHookTrampoline {} - final class SuprType: Orion_ClassHook15 {} + final class SuprType: DeSubHook1, _GlueClassHookTrampoline {} - private static var orion_imp1: @convention(c) (Any, Selector) -> Void = { _, _ in } + static let storage = initializeStorage() - static func activate(withClassHookBuilder builder: inout _ClassHookBuilder) { - builder.addDeinitializer(to: self, getOrig: { orion_imp1 }, setOrig: { orion_imp1 = $0 }) + private static var orion_imp1: @convention(c) (Any, Selector) -> Void = { _, _ in } + + static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) { + builder.addDeinitializer(to: DeSubHook1.self, getOrig: { orion_imp1 }, setOrig: { orion_imp1 = $0 }) + } } } extension DeSubHook2 { - public static let _storage = _initializeStorage() -} + enum _Glue: _GlueClassHook { + typealias HookType = DeSubHook2 -private class Orion_ClassHook16: DeSubHook2, _GlueClassHook { - final class OrigType: Orion_ClassHook16 { - override func deinitializer() -> DeinitPolicy { - deinitOrigError() + final class OrigType: DeSubHook2, _GlueClassHookTrampoline { + override func deinitializer() -> DeinitPolicy { + deinitOrigError() + } } - } - final class SuprType: Orion_ClassHook16 { - override func deinitializer() -> DeinitPolicy { - deinitSuprError() + final class SuprType: DeSubHook2, _GlueClassHookTrampoline { + override func deinitializer() -> DeinitPolicy { + deinitSuprError() + } } - } - private static var orion_orig1: @convention(c) (Any, Selector) -> Void = { _, _ in } + static let storage = initializeStorage() - static func activate(withClassHookBuilder builder: inout _ClassHookBuilder) { - builder.addDeinitializer(to: self, getOrig: { orion_orig1 }, setOrig: { orion_orig1 = $0 }) + private static var orion_orig1: @convention(c) (Any, Selector) -> Void = { _, _ in } + + static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) { + builder.addDeinitializer(to: DeSubHook2.self, getOrig: { orion_orig1 }, setOrig: { orion_orig1 = $0 }) + } } } extension GrHook { - public static let _storage = _initializeStorage() -} + enum _Glue: _GlueClassHook { + typealias HookType = GrHook -private class Orion_ClassHook17: GrHook, _GlueClassHook { - final class OrigType: Orion_ClassHook17 { - @objc override func myString() -> String { - Self.orion_orig1(target, Self.orion_sel1) + final class OrigType: GrHook, _GlueClassHookTrampoline { + @objc override func myString() -> String { + _Glue.orion_orig1(target, _Glue.orion_sel1) + } } - } - final class SuprType: Orion_ClassHook17 { - @objc override func myString() -> String { - callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, Self.orion_sel1) } + final class SuprType: GrHook, _GlueClassHookTrampoline { + @objc override func myString() -> String { + callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, _Glue.orion_sel1) } + } } - } - private static let orion_sel1 = #selector(myString as (Self) -> () -> String) - private static var orion_orig1: @convention(c) (Target, Selector) -> String = { target, _cmd in - Orion_ClassHook17(target: target).myString() - } + static let storage = initializeStorage() - static func activate(withClassHookBuilder builder: inout _ClassHookBuilder) { - builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } + private static let orion_sel1 = #selector(GrHook.myString as (GrHook) -> () -> String) + private static var orion_orig1: @convention(c) (Target, Selector) -> String = { target, _cmd in + GrHook(target: target).myString() + } + + static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) { + builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } + } } } extension GrHook2 { - public static let _storage = _initializeStorage() -} + enum _Glue: _GlueClassHook { + typealias HookType = GrHook2 -private class Orion_ClassHook18: GrHook2, _GlueClassHook { - final class OrigType: Orion_ClassHook18 { - @objc override func mySecondString() -> String { - Self.orion_orig1(target, Self.orion_sel1) + final class OrigType: GrHook2, _GlueClassHookTrampoline { + @objc override func mySecondString() -> String { + _Glue.orion_orig1(target, _Glue.orion_sel1) + } } - } - final class SuprType: Orion_ClassHook18 { - @objc override func mySecondString() -> String { - callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, Self.orion_sel1) } + final class SuprType: GrHook2, _GlueClassHookTrampoline { + @objc override func mySecondString() -> String { + callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, _Glue.orion_sel1) } + } } - } - private static let orion_sel1 = #selector(mySecondString as (Self) -> () -> String) - private static var orion_orig1: @convention(c) (Target, Selector) -> String = { target, _cmd in - Orion_ClassHook18(target: target).mySecondString() - } + static let storage = initializeStorage() - static func activate(withClassHookBuilder builder: inout _ClassHookBuilder) { - builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } + private static let orion_sel1 = #selector(GrHook2.mySecondString as (GrHook2) -> () -> String) + private static var orion_orig1: @convention(c) (Target, Selector) -> String = { target, _cmd in + GrHook2(target: target).mySecondString() + } + + static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) { + builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } + } } } extension GrHook3 { - public static let _storage = _initializeStorage() -} + enum _Glue: _GlueClassHook { + typealias HookType = GrHook3 -private class Orion_ClassHook19: GrHook3, _GlueClassHook { - final class OrigType: Orion_ClassHook19 { - @objc override func myThirdString() -> String { - Self.orion_orig1(target, Self.orion_sel1) + final class OrigType: GrHook3, _GlueClassHookTrampoline { + @objc override func myThirdString() -> String { + _Glue.orion_orig1(target, _Glue.orion_sel1) + } } - } - final class SuprType: Orion_ClassHook19 { - @objc override func myThirdString() -> String { - callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, Self.orion_sel1) } + final class SuprType: GrHook3, _GlueClassHookTrampoline { + @objc override func myThirdString() -> String { + callSuper((@convention(c) (UnsafeRawPointer, Selector) -> String).self) { $0($1, _Glue.orion_sel1) } + } } - } - private static let orion_sel1 = #selector(myThirdString as (Self) -> () -> String) - private static var orion_orig1: @convention(c) (Target, Selector) -> String = { target, _cmd in - Orion_ClassHook19(target: target).myThirdString() - } + static let storage = initializeStorage() - static func activate(withClassHookBuilder builder: inout _ClassHookBuilder) { - builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } + private static let orion_sel1 = #selector(GrHook3.myThirdString as (GrHook3) -> () -> String) + private static var orion_orig1: @convention(c) (Target, Selector) -> String = { target, _cmd in + GrHook3(target: target).myThirdString() + } + + static func activate(withClassHookBuilder builder: inout _GlueClassHookBuilder) { + builder.addHook(orion_sel1, orion_orig1, isClassMethod: false) { orion_orig1 = $0 } + } } } extension AtoiHook { - public static let _storage = _initializeStorage() -} - -private class Orion_FunctionHook1: AtoiHook, _GlueFunctionHook { - static let orion_shared = Orion_FunctionHook1() + enum _Glue: _GlueFunctionHook { + typealias HookType = AtoiHook - static var origFunction: @convention(c) (UnsafePointer) -> Int32 = { arg1 in - Orion_FunctionHook1.orion_shared.function(_:)(arg1) - } + final class OrigType: AtoiHook, _GlueFunctionHookTrampoline { + override func function(_ arg1: UnsafePointer) -> Int32 { + _Glue.origFunction(arg1) + } + } - final class OrigType: Orion_FunctionHook1 { - override func function(_ arg1: UnsafePointer) -> Int32 { - Self.origFunction(arg1) + static var origFunction: @convention(c) (UnsafePointer) -> Int32 = { arg1 in + AtoiHook().function(_:)(arg1) } + + static let storage = initializeStorage() } } extension AtofHook { - public static let _storage = _initializeStorage() -} - -private class Orion_FunctionHook2: AtofHook, _GlueFunctionHook { - static let orion_shared = Orion_FunctionHook2() + enum _Glue: _GlueFunctionHook { + typealias HookType = AtofHook - static var origFunction: @convention(c) (UnsafePointer) -> Double = { arg1 in - Orion_FunctionHook2.orion_shared.function(_:)(arg1) - } + final class OrigType: AtofHook, _GlueFunctionHookTrampoline { + override func function(_ arg1: UnsafePointer) -> Double { + _Glue.origFunction(arg1) + } + } - final class OrigType: Orion_FunctionHook2 { - override func function(_ arg1: UnsafePointer) -> Double { - Self.origFunction(arg1) + static var origFunction: @convention(c) (UnsafePointer) -> Double = { arg1 in + AtofHook().function(_:)(arg1) } + + static let storage = initializeStorage() } } extension StringCompareHook { - public static let _storage = _initializeStorage() -} - -private class Orion_FunctionHook3: StringCompareHook, _GlueFunctionHook { - static let orion_shared = Orion_FunctionHook3() + enum _Glue: _GlueFunctionHook { + typealias HookType = StringCompareHook - static var origFunction: @convention(c) (UnsafePointer?, UnsafePointer?) -> Int32 = { arg1, arg2 in - Orion_FunctionHook3.orion_shared.function(_:_:)(arg1, arg2) - } + final class OrigType: StringCompareHook, _GlueFunctionHookTrampoline { + override func function(_ arg1: UnsafePointer?, _ arg2: UnsafePointer?) -> Int32 { + _Glue.origFunction(arg1, arg2) + } + } - final class OrigType: Orion_FunctionHook3 { - override func function(_ arg1: UnsafePointer?, _ arg2: UnsafePointer?) -> Int32 { - Self.origFunction(arg1, arg2) + static var origFunction: @convention(c) (UnsafePointer?, UnsafePointer?) -> Int32 = { arg1, arg2 in + StringCompareHook().function(_:_:)(arg1, arg2) } + + static let storage = initializeStorage() } } @@ -717,28 +755,28 @@ private class Orion_FunctionHook3: StringCompareHook, _GlueFunctionHook { func orion_init() { HooksTweak.activate( hooks: [ - Orion_ClassHook1.self, - Orion_ClassHook2.self, - Orion_ClassHook3.self, - Orion_ClassHook4.self, - Orion_ClassHook5.self, - Orion_ClassHook6.self, - Orion_ClassHook7.self, - Orion_ClassHook8.self, - Orion_ClassHook9.self, - Orion_ClassHook10.self, - Orion_ClassHook11.self, - Orion_ClassHook12.self, - Orion_ClassHook13.self, - Orion_ClassHook14.self, - Orion_ClassHook15.self, - Orion_ClassHook16.self, - Orion_ClassHook17.self, - Orion_ClassHook18.self, - Orion_ClassHook19.self, - Orion_FunctionHook1.self, - Orion_FunctionHook2.self, - Orion_FunctionHook3.self + BasicHook._Glue.self, + ActivationHook._Glue.self, + NotHook._Glue.self, + NamedBasicHook._Glue.self, + BasicSubclass._Glue.self, + NamedBasicSubclass._Glue.self, + AdditionHook._Glue.self, + InheritedHook._Glue.self, + InitHook._Glue.self, + SuperHook._Glue.self, + PropertyHookX._Glue.self, + PropertyHookY._Glue.self, + PropertyHook2._Glue.self, + DeHook._Glue.self, + DeSubHook1._Glue.self, + DeSubHook2._Glue.self, + GrHook._Glue.self, + GrHook2._Glue.self, + GrHook3._Glue.self, + AtoiHook._Glue.self, + AtofHook._Glue.self, + StringCompareHook._Glue.self ] ) }