Native: fix thread state when calling ObjC completion for Kotlin suspend

This commit is contained in:
Svyatoslav Scherbina
2021-06-18 18:37:40 +03:00
committed by Space
parent 87c6ab493b
commit b961812efd
2 changed files with 40 additions and 1 deletions
@@ -95,6 +95,40 @@ private func testCall() throws {
try testSuspendFuncAsync(doThrow: true) try testSuspendFuncAsync(doThrow: true)
} }
private func testCallSuspendFunChain(doSuspend: Bool, doThrow: Bool) throws {
class C {}
let expectedResult = C()
var completionCalled = 0
var result: AnyObject? = nil
var error: Error? = nil
CoroutinesKt.suspendFun(result: expectedResult, doSuspend: doSuspend, doThrow: doThrow) { _resultOuter, _errorOuter in
CoroutinesKt.suspendFun(result: expectedResult, doSuspend: doSuspend, doThrow: doThrow) { _result, _error in
completionCalled += 1
result = _result as AnyObject?
error = _error
}
}
try assertEquals(actual: completionCalled, expected: 1)
if doThrow {
try assertNil(result)
try assertTrue(error?.kotlinException is CoroutineException)
} else {
try assertSame(actual: result, expected: expectedResult)
try assertNil(error)
}
}
private func testCallChain() throws {
try testCallSuspendFunChain(doSuspend: true, doThrow: false)
try testCallSuspendFunChain(doSuspend: false, doThrow: false)
try testCallSuspendFunChain(doSuspend: true, doThrow: true)
try testCallSuspendFunChain(doSuspend: false, doThrow: true)
}
private class SuspendFunImpl : SuspendFun { private class SuspendFunImpl : SuspendFun {
class E : Error {} class E : Error {}
@@ -336,6 +370,7 @@ class CoroutinesTests : SimpleTestProvider {
test("TestCallSimple", testCallSimple) test("TestCallSimple", testCallSimple)
test("TestCall", testCall) test("TestCall", testCall)
test("TestCallChain", testCallChain)
test("TestOverride", testOverride) test("TestOverride", testOverride)
test("TestBridges", testBridges) test("TestBridges", testBridges)
test("TestImplicitThrows1", testImplicitThrows1) test("TestImplicitThrows1", testImplicitThrows1)
@@ -9,6 +9,7 @@
#import <Foundation/NSException.h> #import <Foundation/NSException.h>
#import <Foundation/NSObject.h> #import <Foundation/NSObject.h>
#import "Memory.h"
#import "ObjCExport.h" #import "ObjCExport.h"
#import "ObjCExportErrors.h" #import "ObjCExportErrors.h"
@@ -16,7 +17,9 @@ typedef void (^Completion)(id _Nullable, NSError* _Nullable);
extern "C" void Kotlin_ObjCExport_runCompletionSuccess(KRef completionHolder, KRef result) { extern "C" void Kotlin_ObjCExport_runCompletionSuccess(KRef completionHolder, KRef result) {
Completion completion = (Completion)GetAssociatedObject(completionHolder); Completion completion = (Completion)GetAssociatedObject(completionHolder);
completion(Kotlin_ObjCExport_refToObjC(result), nullptr); id objCResult = Kotlin_ObjCExport_refToObjC(result);
kotlin::ThreadStateGuard guard(kotlin::ThreadState::kNative);
completion(objCResult, nullptr);
} }
extern "C" void Kotlin_ObjCExport_runCompletionFailure( extern "C" void Kotlin_ObjCExport_runCompletionFailure(
@@ -26,6 +29,7 @@ extern "C" void Kotlin_ObjCExport_runCompletionFailure(
) { ) {
id error = Kotlin_ObjCExport_ExceptionAsNSError(exception, exceptionTypes); id error = Kotlin_ObjCExport_ExceptionAsNSError(exception, exceptionTypes);
Completion completion = (Completion)GetAssociatedObject(completionHolder); Completion completion = (Completion)GetAssociatedObject(completionHolder);
kotlin::ThreadStateGuard guard(kotlin::ThreadState::kNative);
completion(nullptr, error); completion(nullptr, error);
} }