Fix isa swizzling for Kotlin subclasses of Obj-C classes

Don't rely on indexed ivars of instance's isa since isa swizzling
replaces it. Use method instead, it works on the replacement too
(if it is a subclass of the original isa).

 #KT-42482 Fixed.
This commit is contained in:
SvyatoslavScherbina
2020-12-04 15:37:48 +03:00
committed by Stanislav Erokhin
parent e1d9a36de3
commit 62272f54c1
6 changed files with 162 additions and 24 deletions
@@ -0,0 +1,10 @@
#import <Foundation/NSObject.h>
extern BOOL kt42482Deallocated;
extern id kt42482Global;
@interface KT42482 : NSObject
-(int)fortyTwo;
@end;
void kt42482Swizzle(id obj);
@@ -0,0 +1,35 @@
import kotlin.native.ref.WeakReference
import kotlinx.cinterop.*
import kotlin.test.*
import objcTests.*
@Test
fun testKT42482() {
// Attempt to make the state predictable:
kotlin.native.internal.GC.collect()
kt42482Deallocated = false
assertFalse(kt42482Deallocated);
{
assertEquals(41, KT42482().fortyTwo())
val obj: KT42482 = KT42482Impl()
assertEquals(42, obj.fortyTwo())
kt42482Swizzle(obj)
assertEquals(43, obj.fortyTwo())
// Test retain and release on swizzled object:
kt42482Global = obj
kt42482Global = null
}()
kotlin.native.internal.GC.collect()
assertTrue(kt42482Deallocated)
}
class KT42482Impl : KT42482() {
override fun fortyTwo() = 42
}
@@ -0,0 +1,36 @@
#import "kt42482.h"
#import "assert.h"
#import <objc/runtime.h>
BOOL kt42482Deallocated = NO;
id kt42482Global = nil;
@implementation KT42482
-(int)fortyTwo {
return 41;
}
-(void)dealloc {
kt42482Deallocated = YES;
}
@end;
int fortyTwoSwizzledImp(id self, SEL _cmd) {
return 43;
}
void kt42482Swizzle(id obj) {
Class oldClass = object_getClass(obj);
SEL selector = @selector(fortyTwo);
Class newClass = objc_allocateClassPair(oldClass, "KT42482Swizzled", 0);
assert(newClass != nil);
objc_registerClassPair(newClass);
Method method = class_getInstanceMethod([KT42482 class], selector);
assert(method != nil);
class_addMethod(newClass, selector, (IMP)&fortyTwoSwizzledImp, method_getTypeEncoding(method));
object_setClass(obj, newClass);
}