Add warning message to `isKindOfClass:`.
If the class object doesn't belong to the process of the callee object, the result will always be `NO`. For now, we print warning for this case, so developer may have chance to notice this if this is not the desired result.
PiperOrigin-RevId: 315752083
diff --git a/Service/Sources/EDOObject.m b/Service/Sources/EDOObject.m
index 5396c3e..16589d5 100644
--- a/Service/Sources/EDOObject.m
+++ b/Service/Sources/EDOObject.m
@@ -35,6 +35,9 @@
static NSString *const kEDOObjectCoderClassNameKey = @"edoClassName";
static NSString *const kEDOObjectCoderProcessUUIDKey = @"edoProcessUUID";
+/** Returns the boolean idicating if the two objects are from the same process. */
+static BOOL IsFromSameProcess(id object1, id object2);
+
@interface EDOObject ()
/** The port to connect to the local socket. */
@property(readonly) EDOServicePort *servicePort;
@@ -171,8 +174,7 @@
if (self == object) {
return YES;
}
- if ([object class] == [EDOObject class] &&
- [self.processUUID isEqual:((EDOObject *)object).processUUID]) {
+ if (IsFromSameProcess(self, object)) {
BOOL returnValue = NO;
NSMethodSignature *methodSignature = [NSMethodSignature methodSignatureForSelector:_cmd];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
@@ -186,6 +188,27 @@
return NO;
}
+- (BOOL)isKindOfClass:(Class)aClass {
+ if (!IsFromSameProcess(self, aClass)) {
+ NSLog(@"EDO WARNING: %@'s class is being compared via isKindOfClass: with the class that "
+ @"doesn't belong to the process of the callee object. It will always return NO. To "
+ @"expect isKindOfClass: to return YES, please use a class object that is fetched by "
+ @"EDOClientService::classObjectWithName:hostPort:.",
+ self.className);
+ return NO;
+ }
+
+ NSMethodSignature *methodSignature = [NSMethodSignature methodSignatureForSelector:_cmd];
+ NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
+ invocation.target = self;
+ invocation.selector = _cmd;
+ [invocation setArgument:&aClass atIndex:2];
+ [self forwardInvocation:invocation];
+ BOOL returnValue = NO;
+ [invocation getReturnValue:&returnValue];
+ return returnValue;
+}
+
- (NSUInteger)hash {
NSUInteger remoteHash = 0;
NSMethodSignature *methodSignature = [NSMethodSignature methodSignatureForSelector:_cmd];
@@ -331,3 +354,10 @@
}
@end
+
+static BOOL IsFromSameProcess(id object1, id object2) {
+ Class edoClass = [EDOObject class];
+ return ([object1 class] != edoClass && [object2 class] != edoClass) ||
+ ([object1 class] == edoClass && [object2 class] == edoClass &&
+ [((EDOObject *)object1).processUUID isEqual:((EDOObject *)object2).processUUID]);
+}
diff --git a/Service/Tests/FunctionalTests/EDOServiceUITest.m b/Service/Tests/FunctionalTests/EDOServiceUITest.m
index f0e0149..838dbf9 100644
--- a/Service/Tests/FunctionalTests/EDOServiceUITest.m
+++ b/Service/Tests/FunctionalTests/EDOServiceUITest.m
@@ -18,6 +18,7 @@
#include <objc/runtime.h>
+#import "Channel/Sources/EDOHostPort.h"
#import "Channel/Sources/EDOSocket.h"
#import "Channel/Sources/EDOSocketChannel.h"
#import "Service/Sources/EDOClientService.h"
@@ -328,6 +329,26 @@
free(methods);
}
+/**
+ * Verifies `isKindOfClass:` returns true only if the class object belongs to the callee process.
+ */
+- (void)testIsKindOfClassOnlyResolvesInSameProcess {
+ [self launchApplicationWithPort:EDOTEST_APP_SERVICE_PORT initValue:5];
+ // Create a local service so it can wrap and deref the any returned EDOObjects.
+ EDOHostService *service = [EDOHostService serviceWithPort:2234
+ rootObject:[[EDOTestDummyInTest alloc] init]
+ queue:dispatch_get_main_queue()];
+ EDOTestDummy *remoteDummy = [EDOClientService rootObjectWithPort:EDOTEST_APP_SERVICE_PORT];
+ NSArray<NSNumber *> *remoteArray = [remoteDummy returnArray];
+
+ EDOHostPort *hostPort = [EDOHostPort hostPortWithLocalPort:EDOTEST_APP_SERVICE_PORT];
+ Class remoteArrayClass = [EDOClientService classObjectWithName:@"NSArray" hostPort:hostPort];
+ XCTAssertTrue([remoteArray isKindOfClass:remoteArrayClass]);
+ XCTAssertFalse([remoteArray isKindOfClass:[NSArray class]]);
+
+ [service invalidate];
+}
+
- (void)testRemoteObjectCopy {
[self launchApplicationWithPort:EDOTEST_APP_SERVICE_PORT initValue:5];
EDOTestDummy *dummy = [EDOClientService rootObjectWithPort:EDOTEST_APP_SERVICE_PORT];