From 1c14c891aaa1dae38cb1693867355552f4099d39 Mon Sep 17 00:00:00 2001 From: eDO Team Date: Fri, 14 Feb 2025 10:54:25 -0800 Subject: [PATCH] Internal change PiperOrigin-RevId: 726987181 --- Service/Sources/EDORuntimeUtils.m | 25 ++++++------- Service/Sources/EDOSwiftObject.m | 59 +++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 15 deletions(-) create mode 100644 Service/Sources/EDOSwiftObject.m diff --git a/Service/Sources/EDORuntimeUtils.m b/Service/Sources/EDORuntimeUtils.m index 76edcfe..920890f 100644 --- a/Service/Sources/EDORuntimeUtils.m +++ b/Service/Sources/EDORuntimeUtils.m @@ -6,19 +6,14 @@ // eDO uses the last object of the -forwardingTargetForSelector: chain to perform // -methodSignatureForSelector:. id forwardedObject = target; - Class klass = object_getClass(forwardedObject); - Method method = sel ? class_getInstanceMethod(klass, sel) : nil; - id nextForwardedObject = [forwardedObject forwardingTargetForSelector:sel]; - while (method == nil && nextForwardedObject != nil) { - forwardedObject = nextForwardedObject; - klass = object_getClass(forwardedObject); - method = sel ? class_getInstanceMethod(klass, sel) : nil; - nextForwardedObject = [forwardedObject forwardingTargetForSelector:sel]; - } - - if (method) { - return [NSMethodSignature signatureWithObjCTypes:method_getTypeEncoding(method)]; - } else { - return [forwardedObject methodSignatureForSelector:sel]; - } + id lastObjectInForwardingChain; + do { + Class klass = object_getClass(forwardedObject); + Method method = sel ? class_getInstanceMethod(klass, sel) : nil; + if (method) { + return [NSMethodSignature signatureWithObjCTypes:method_getTypeEncoding(method)]; + } + lastObjectInForwardingChain = forwardedObject; + } while ((forwardedObject = [forwardedObject forwardingTargetForSelector:sel])); + return [lastObjectInForwardingChain methodSignatureForSelector:sel]; } diff --git a/Service/Sources/EDOSwiftObject.m b/Service/Sources/EDOSwiftObject.m new file mode 100644 index 0000000..7c50476 --- /dev/null +++ b/Service/Sources/EDOSwiftObject.m @@ -0,0 +1,59 @@ +// +// Copyright 2025 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include + +#import "Service/Sources/EDOHostService+Private.h" +#import "Service/Sources/EDOHostService.h" +#import "Service/Sources/EDOParameter.h" + +@interface EDOSwiftObject : NSObject +@end + +@implementation EDOSwiftObject + ++ (void)load { + // @c SwiftObject is the base Objective-C class of all pure Swift class types and was renamed to + // @c Swift._SwiftObject in Swift stable ABI. + // https://github.com/swiftlang/swift/commit/9637b4a6e11ddca72f5f6dbe528efc7c92f14d01 + Class swiftObjectClass = + (NSClassFromString(@"Swift._SwiftObject") ?: NSClassFromString(@"SwiftObject")); + if (swiftObjectClass) { + [self swizzleSelector:@selector(edo_parameterForTarget:service:hostPort:) + toClass:swiftObjectClass]; + } +} + ++ (void)swizzleSelector:(SEL)sel toClass:(Class)klass { + Method method = class_getInstanceMethod(self, sel); + BOOL selectorAdded = + class_addMethod(klass, sel, method_getImplementation(method), method_getTypeEncoding(method)); + if (!selectorAdded) { + NSLog(@"Failed to add %@ to %@", NSStringFromSelector(sel), klass); + abort(); + } +} + +- (EDOParameter *)edo_parameterForTarget:(EDOObject *)target + service:(EDOHostService *)service + hostPort:(EDOHostPort *)hostPort { + NSAssert(service, @"The service isn't set up to create the remote object."); + + id boxedObject = [service distantObjectForLocalObject:self hostPort:hostPort]; + return [EDOParameter parameterWithObject:boxedObject]; +} + +@end