ObjCExport: remove KotlinUnit from suspend funs returning Unit (#4635)

With `unitSuspendFunctionObjCExport=proper` binary option,
for Unit-returning suspend functions ObjCExport now generates
completion handlers without redundant `KotlinUnit*` result parameter.

So Swift (5.5+) can import these functions as Void-returning async
functions.

^KT-47399 Fixed
This commit is contained in:
Nikolay Kasyanov
2021-11-18 08:01:33 +01:00
committed by GitHub
parent 7f6afcabf1
commit 4dcfd38236
23 changed files with 3093 additions and 64 deletions
@@ -23,6 +23,8 @@ object BinaryOptions : BinaryOptionRegistry() {
val sourceInfoType by option<SourceInfoType>()
val androidProgramType by option<AndroidProgramType>()
val unitSuspendFunctionObjCExport by option<UnitSuspendFunctionObjCExport>()
}
open class BinaryOption<T : Any>(
@@ -38,6 +38,9 @@ internal fun StorageComponentContainer.initContainer(config: KonanConfig) {
override val objcGenerics: Boolean
get() = config.configuration.getBoolean(KonanConfigKeys.OBJC_GENERICS)
override val unitSuspendFunctionExport: UnitSuspendFunctionObjCExport
get() = config.unitSuspendFunctionObjCExport
})
}
}
@@ -303,6 +303,9 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
}
"Konan_main"
}
internal val unitSuspendFunctionObjCExport: UnitSuspendFunctionObjCExport
get() = configuration.get(BinaryOptions.unitSuspendFunctionObjCExport) ?: UnitSuspendFunctionObjCExport.LEGACY
}
fun CompilerConfiguration.report(priority: CompilerMessageSeverity, message: String)
@@ -0,0 +1,26 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.konan
enum class UnitSuspendFunctionObjCExport {
/**
* In this mode suspend functions and methods with [Unit] return type are exported to Objective-C with an additional argument,
* continuation callback, with the following Objective-C signature: `(^)(KtKotlinUnit * _Nullable, NSError * _Nullable)`.
*/
LEGACY,
/**
* In this mode suspend functions and methods with [Unit] return type are exported to Objective-C with an additional argument,
* continuation callback, with the following Objective-C signature: `(^)(NSError * _Nullable)`.
*
* Methods overriding superclass methods or implementing interface requirements narrowing down a more general return type
* to [Unit] are exported like in [LEGACY] mode.
*
* Note that in Swift 5.5 and higher suspend functions exported this way are transparently mapped to
* async functions with `Void` return type
*/
PROPER,
}
@@ -503,6 +503,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) : Runti
val Kotlin_ObjCExport_RethrowNSErrorAsException by lazyRtFunction
val Kotlin_ObjCExport_AllocInstanceWithAssociatedObject by lazyRtFunction
val Kotlin_ObjCExport_createContinuationArgument by lazyRtFunction
val Kotlin_ObjCExport_createUnitContinuationArgument by lazyRtFunction
val Kotlin_ObjCExport_resumeContinuation by lazyRtFunction
private val Kotlin_ObjCExport_NSIntegerTypeProvider by lazyRtFunction
@@ -243,6 +243,10 @@ internal class ObjCExportCodeGenerator(
generateContinuationToRetainedCompletionConverter(blockGenerator)
}
internal val unitContinuationToRetainedCompletionConverter: LLVMValueRef by lazy {
generateUnitContinuationToRetainedCompletionConverter(blockGenerator)
}
fun meaningfulBridgeNameOrNull(irFunction: IrFunction?): String? {
if (!context.config.configuration.getBoolean(KonanConfigKeys.MEANINGFUL_BRIDGE_NAMES)) {
return null
@@ -771,7 +775,31 @@ private fun ObjCExportCodeGenerator.generateContinuationToRetainedCompletionConv
invokeName = "invokeCompletion"
) { continuation, arguments ->
check(arguments.size == 2)
callFromBridge(context.llvm.Kotlin_ObjCExport_resumeContinuation, listOf(continuation) + arguments)
val resultArgument = objCReferenceToKotlin(arguments[0], Lifetime.ARGUMENT)
val errorArgument = arguments[1]
callFromBridge(context.llvm.Kotlin_ObjCExport_resumeContinuation, listOf(continuation, resultArgument, errorArgument))
ret(null)
}
}
private fun ObjCExportCodeGenerator.generateUnitContinuationToRetainedCompletionConverter(
blockGenerator: BlockGenerator
): LLVMValueRef = with(blockGenerator) {
generateWrapKotlinObjectToRetainedBlock(
BlockType(numberOfParameters = 1, returnsVoid = true),
convertName = "convertUnitContinuation",
invokeName = "invokeUnitCompletion"
) { continuation, arguments ->
check(arguments.size == 1)
val errorArgument = arguments[0]
val resultArgument = ifThenElse(icmpNe(errorArgument, kNullInt8Ptr), kNullObjHeaderPtr) {
codegen.theUnitInstanceRef.llvm
}
callFromBridge(context.llvm.Kotlin_ObjCExport_resumeContinuation, listOf(continuation, resultArgument, errorArgument))
ret(null)
}
}
@@ -979,9 +1007,14 @@ private fun ObjCExportCodeGenerator.generateObjCImp(
null
}
MethodBridgeValueParameter.SuspendCompletion -> {
is MethodBridgeValueParameter.SuspendCompletion -> {
val createContinuationArgument = if (paramBridge.useUnitCompletion) {
context.llvm.Kotlin_ObjCExport_createUnitContinuationArgument
} else {
context.llvm.Kotlin_ObjCExport_createContinuationArgument
}
callFromBridge(
context.llvm.Kotlin_ObjCExport_createContinuationArgument,
createContinuationArgument,
listOf(parameter, generateExceptionTypeInfoArray(baseMethod!!)),
Lifetime.ARGUMENT
).also {
@@ -1187,7 +1220,7 @@ private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge(
errorOutPtr = it
}
MethodBridgeValueParameter.SuspendCompletion -> {
is MethodBridgeValueParameter.SuspendCompletion -> {
val continuation = param(irFunction.allParametersCount) // The last argument.
// TODO: consider placing interception into the converter to reduce code size.
val intercepted = callFromBridge(
@@ -1195,7 +1228,13 @@ private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge(
listOf(continuation),
Lifetime.ARGUMENT
)
val retainedCompletion = callFromBridge(continuationToRetainedCompletionConverter, listOf(intercepted))
val converter = if (bridge.useUnitCompletion) {
unitContinuationToRetainedCompletionConverter
} else {
continuationToRetainedCompletionConverter
}
val retainedCompletion = callFromBridge(converter, listOf(intercepted))
callFromBridge(objcAutorelease, listOf(retainedCompletion)) // TODO: use stack-allocated block here instead.
}
}
@@ -1771,7 +1810,7 @@ private fun MethodBridgeParameter.toLlvmParamType(): LlvmParamType = when (this)
is MethodBridgeReceiver -> ReferenceBridge.toLlvmParamType()
MethodBridgeSelector -> LlvmParamType(int8TypePtr)
MethodBridgeValueParameter.ErrorOutParameter -> LlvmParamType(pointerType(ReferenceBridge.toLlvmParamType().llvmType))
MethodBridgeValueParameter.SuspendCompletion -> LlvmParamType(int8TypePtr)
is MethodBridgeValueParameter.SuspendCompletion -> LlvmParamType(int8TypePtr)
}
private fun MethodBridge.ReturnValue.toLlvmRetType(
@@ -1827,7 +1866,7 @@ private val MethodBridgeParameter.objCEncoding: String get() = when (this) {
is MethodBridgeReceiver -> ReferenceBridge.objCEncoding
MethodBridgeSelector -> ":"
MethodBridgeValueParameter.ErrorOutParameter -> "^${ReferenceBridge.objCEncoding}"
MethodBridgeValueParameter.SuspendCompletion -> "@"
is MethodBridgeValueParameter.SuspendCompletion -> "@"
}
private val TypeBridge.objCEncoding: String get() = when (this) {
@@ -35,7 +35,7 @@ internal object MethodBridgeSelector : MethodBridgeParameter()
internal sealed class MethodBridgeValueParameter : MethodBridgeParameter() {
data class Mapped(val bridge: TypeBridge) : MethodBridgeValueParameter()
object ErrorOutParameter : MethodBridgeValueParameter()
object SuspendCompletion : MethodBridgeValueParameter()
data class SuspendCompletion(val useUnitCompletion: Boolean) : MethodBridgeValueParameter()
}
internal data class MethodBridge(
@@ -92,7 +92,7 @@ internal fun MethodBridge.valueParametersAssociated(
when (it) {
is MethodBridgeValueParameter.Mapped -> it to kotlinParameters.next()
MethodBridgeValueParameter.SuspendCompletion,
is MethodBridgeValueParameter.SuspendCompletion,
is MethodBridgeValueParameter.ErrorOutParameter -> it to null
}
}.also { assert(!kotlinParameters.hasNext()) }
@@ -108,7 +108,7 @@ internal fun MethodBridge.parametersAssociated(
is MethodBridgeValueParameter.Mapped, MethodBridgeReceiver.Instance ->
it to kotlinParameters.next()
MethodBridgeValueParameter.SuspendCompletion,
is MethodBridgeValueParameter.SuspendCompletion,
MethodBridgeReceiver.Static, MethodBridgeSelector, MethodBridgeValueParameter.ErrorOutParameter ->
it to null
@@ -56,7 +56,8 @@ internal class ObjCExport(val context: Context, symbolTable: SymbolTable) {
val produceFramework = context.config.produce == CompilerOutputKind.FRAMEWORK
return if (produceFramework) {
val mapper = ObjCExportMapper(context.frontendServices.deprecationResolver)
val unitSuspendFunctionExport = context.config.unitSuspendFunctionObjCExport
val mapper = ObjCExportMapper(context.frontendServices.deprecationResolver, unitSuspendFunctionExport = unitSuspendFunctionExport)
val moduleDescriptors = listOf(context.moduleDescriptor) + context.getExportedDependencies()
val objcGenerics = context.configuration.getBoolean(KonanConfigKeys.OBJC_GENERICS)
val namer = ObjCExportNamerImpl(
@@ -86,7 +87,7 @@ internal class ObjCExport(val context: Context, symbolTable: SymbolTable) {
if (!context.config.produce.isFinalBinary) return // TODO: emit RTTI to the same modules as classes belong to.
val mapper = exportedInterface?.mapper ?: ObjCExportMapper()
val mapper = exportedInterface?.mapper ?: ObjCExportMapper(unitSuspendFunctionExport = context.config.unitSuspendFunctionObjCExport)
namer = exportedInterface?.namer ?: ObjCExportNamerImpl(
setOf(codegen.context.moduleDescriptor),
context.moduleDescriptor.builtIns,
@@ -644,7 +644,7 @@ internal class ObjCExportTranslatorImpl(
}
}
MethodBridgeValueParameter.ErrorOutParameter -> "error"
MethodBridgeValueParameter.SuspendCompletion -> "completionHandler"
is MethodBridgeValueParameter.SuspendCompletion -> "completionHandler"
}
val uniqueName = unifyName(candidateName, usedNames)
@@ -655,14 +655,18 @@ internal class ObjCExportTranslatorImpl(
MethodBridgeValueParameter.ErrorOutParameter ->
ObjCPointerType(ObjCNullableReferenceType(ObjCClassType("NSError")), nullable = true)
MethodBridgeValueParameter.SuspendCompletion -> {
val resultType = when (val it = mapReferenceType(method.returnType!!, objCExportScope)) {
is ObjCNonNullReferenceType -> ObjCNullableReferenceType(it, isNullableResult = false)
is ObjCNullableReferenceType -> ObjCNullableReferenceType(it.nonNullType, isNullableResult = true)
is MethodBridgeValueParameter.SuspendCompletion -> {
val resultType = if (bridge.useUnitCompletion) {
null
} else {
when (val it = mapReferenceType(method.returnType!!, objCExportScope)) {
is ObjCNonNullReferenceType -> ObjCNullableReferenceType(it, isNullableResult = false)
is ObjCNullableReferenceType -> ObjCNullableReferenceType(it.nonNullType, isNullableResult = true)
}
}
ObjCBlockPointerType(
returnType = ObjCVoidType,
parameterTypes = listOf(
parameterTypes = listOfNotNull(
resultType,
ObjCNullableReferenceType(ObjCClassType("NSError"))
)
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.konan.objcexport
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.backend.konan.UnitSuspendFunctionObjCExport
import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
@@ -43,6 +44,7 @@ interface ObjCExportLazy {
fun isIncluded(moduleInfo: ModuleInfo): Boolean
fun getCompilerModuleName(moduleInfo: ModuleInfo): String
val objcGenerics: Boolean
val unitSuspendFunctionExport: UnitSuspendFunctionObjCExport
}
fun generateBase(): List<ObjCTopLevel<*>>
@@ -86,7 +88,7 @@ internal class ObjCExportLazyImpl(
private val nameTranslator: ObjCExportNameTranslator = ObjCExportNameTranslatorImpl(namerConfiguration)
private val mapper = ObjCExportMapper(deprecationResolver, local = true)
private val mapper = ObjCExportMapper(deprecationResolver, local = true, configuration.unitSuspendFunctionExport)
private val namer = ObjCExportNamerImpl(namerConfiguration, builtIns, mapper, local = true)
@@ -25,7 +25,8 @@ import org.jetbrains.kotlin.types.typeUtil.isUnit
internal class ObjCExportMapper(
internal val deprecationResolver: DeprecationResolver? = null,
private val local: Boolean = false
private val local: Boolean = false,
internal val unitSuspendFunctionExport: UnitSuspendFunctionObjCExport
) {
fun getCustomTypeMapper(descriptor: ClassDescriptor): CustomTypeMapper? = CustomTypeMappers.getMapper(descriptor)
@@ -331,7 +332,8 @@ private fun ObjCExportMapper.bridgeMethodImpl(descriptor: FunctionDescriptor): M
val returnBridge = bridgeReturnType(descriptor, convertExceptionsToErrors)
if (descriptor.isSuspend) {
valueParameters += MethodBridgeValueParameter.SuspendCompletion
val useUnitCompletion = (unitSuspendFunctionExport == UnitSuspendFunctionObjCExport.PROPER) && (descriptor.returnType!!.isUnit())
valueParameters += MethodBridgeValueParameter.SuspendCompletion(useUnitCompletion)
} else if (convertExceptionsToErrors) {
// Add error out parameter before tail block parameters. The convention allows this.
// Placing it after would trigger https://bugs.swift.org/browse/SR-12201
@@ -349,7 +351,7 @@ private fun MethodBridgeValueParameter.isBlockPointer(): Boolean = when (this) {
is BlockPointerBridge -> true
}
MethodBridgeValueParameter.ErrorOutParameter -> false
MethodBridgeValueParameter.SuspendCompletion -> true
is MethodBridgeValueParameter.SuspendCompletion -> true
}
internal fun ObjCExportMapper.bridgePropertyType(descriptor: PropertyDescriptor): TypeBridge {
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.konan.objcexport
import org.jetbrains.kotlin.backend.common.serialization.findSourceFile
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.UnitSuspendFunctionObjCExport
import org.jetbrains.kotlin.backend.konan.cKeywords
import org.jetbrains.kotlin.backend.konan.descriptors.isArray
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
@@ -89,7 +90,7 @@ fun createNamer(
): ObjCExportNamer = ObjCExportNamerImpl(
(exportedDependencies + moduleDescriptor).toSet(),
moduleDescriptor.builtIns,
ObjCExportMapper(local = true),
ObjCExportMapper(local = true, unitSuspendFunctionExport = UnitSuspendFunctionObjCExport.LEGACY),
topLevelNamePrefix,
local = true
)
@@ -472,7 +473,7 @@ internal class ObjCExportNamerImpl(
else -> it!!.name.asString().toIdentifier()
}
MethodBridgeValueParameter.ErrorOutParameter -> "error"
MethodBridgeValueParameter.SuspendCompletion -> "completionHandler"
is MethodBridgeValueParameter.SuspendCompletion -> "completionHandler"
}
if (index == 0) {
@@ -525,7 +526,7 @@ internal class ObjCExportNamerImpl(
else -> it!!.name.asString().toIdentifier()
}
MethodBridgeValueParameter.ErrorOutParameter -> continue@parameters
MethodBridgeValueParameter.SuspendCompletion -> "completionHandler"
is MethodBridgeValueParameter.SuspendCompletion -> "completionHandler"
}
append(label)
@@ -10,9 +10,9 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
class ObjCExportTranslatorMobile internal constructor(private val delegate: ObjCExportTranslatorImpl) : ObjCExportTranslator by delegate {
companion object {
fun create(namer: ObjCExportNamer): ObjCExportTranslatorMobile {
val mapper = ObjCExportMapper(local = true)
return ObjCExportTranslatorMobile(ObjCExportTranslatorImpl(null, mapper, namer, ObjCExportProblemCollector.SILENT, false))
fun create(namer: ObjCExportNamer, configuration: ObjCExportLazy.Configuration): ObjCExportTranslatorMobile {
val mapper = ObjCExportMapper(local = true, unitSuspendFunctionExport = configuration.unitSuspendFunctionExport)
return ObjCExportTranslatorMobile(ObjCExportTranslatorImpl(null, mapper, namer, ObjCExportProblemCollector.SILENT, configuration.objcGenerics))
}
}
@@ -24,7 +24,7 @@ class ObjcExportHeaderGeneratorMobile internal constructor(
deprecationResolver: DeprecationResolver? = null,
local: Boolean = false,
restrictToLocalModules: Boolean = false): ObjCExportHeaderGenerator {
val mapper = ObjCExportMapper(deprecationResolver, local)
val mapper = ObjCExportMapper(deprecationResolver, local, configuration.unitSuspendFunctionExport)
val namerConfiguration = createNamerConfiguration(configuration)
val namer = ObjCExportNamerImpl(namerConfiguration, builtIns, mapper, local)
@@ -5321,7 +5321,7 @@ if (isAppleTarget(project)) {
framework(frameworkName) {
sources = ['objcexport']
library = libraryName
opts = ["-Xemit-lazy-objc-header=$lazyHeader", "-Xexport-kdoc", "-Xbundle-id=foo.bar"]
opts = ["-Xemit-lazy-objc-header=$lazyHeader", "-Xexport-kdoc", "-Xbundle-id=foo.bar", "-Xbinary=unitSuspendFunctionObjCExport=proper"]
}
swiftSources = ['objcexport']
if (isNoopGC) {
@@ -5375,7 +5375,7 @@ if (isAppleTarget(project)) {
sources = ['objcexport']
artifact = frameworkArtifactName
library = libraryName
opts = ["-Xemit-lazy-objc-header=$lazyHeader", "-Xno-objc-generics"]
opts = ["-Xemit-lazy-objc-header=$lazyHeader", "-Xno-objc-generics", "-Xbinary=unitSuspendFunctionObjCExport=proper"]
}
swiftSources = ['objcexport']
swiftExtraOpts = [ '-D', 'NO_GENERICS' ]
@@ -5384,6 +5384,61 @@ if (isAppleTarget(project)) {
}
}
frameworkTest('testObjCExportLegacySuspendUnit') {
final String frameworkName = 'KtLegacySuspendUnit'
final String frameworkArtifactName = 'Kt'
final String dir = "$testOutputFramework/testObjCExportLegacySuspendUnit"
final File lazyHeader = file("$dir/$target-lazy.h")
doLast {
final String expectedLazyHeaderName = "expectedLazyLegacySuspendUnit.h"
final String expectedLazyHeaderDir = file("objcexport/")
final File expectedLazyHeader = new File(expectedLazyHeaderDir, expectedLazyHeaderName)
if (expectedLazyHeader.readLines() != lazyHeader.readLines()) {
exec {
commandLine 'diff', '-u', expectedLazyHeader, lazyHeader
ignoreExitValue = true
}
copy {
from(lazyHeader)
into(expectedLazyHeaderDir)
rename { expectedLazyHeaderName }
}
throw new Error("$expectedLazyHeader file patched;\nre-run the test and don't forget to commit the patch")
}
}
def libraryName = frameworkName + "Library"
konanArtifacts {
library(libraryName, targets: [target.name]) {
srcDir "objcexport/library"
artifactName "test-library"
if (!useCustomDist) {
dependsOn ":${target.name}CrossDistRuntime", ':distCompiler'
}
extraOpts "-Xshort-module-name=MyLibrary"
extraOpts "-module-name", "org.jetbrains.kotlin.native.test-library"
}
}
framework(frameworkName) {
sources = ['objcexport']
artifact = frameworkArtifactName
library = libraryName
opts = ["-Xemit-lazy-objc-header=$lazyHeader"]
}
swiftSources = ['objcexport']
swiftExtraOpts = [ '-D', 'LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT' ]
if (isNoopGC) {
swiftExtraOpts += ["-D", "NOOP_GC"]
}
}
frameworkTest('testObjCExportStatic') {
final String frameworkName = 'KtStatic'
final String frameworkArtifactName = 'Kt'
@@ -5410,6 +5465,7 @@ if (isAppleTarget(project)) {
artifact = frameworkArtifactName
library = libraryName
isStatic = true
opts = ["-Xbinary=unitSuspendFunctionObjCExport=proper"]
}
swiftSources = ['objcexport']
if (isNoopGC) {
@@ -15,6 +15,7 @@ import kotlin.test.*
class CoroutineException : Throwable()
suspend fun suspendFun() = 42
suspend fun unitSuspendFun() = Unit
@Throws(CoroutineException::class, CancellationException::class)
suspend fun suspendFun(result: Any?, doSuspend: Boolean, doThrow: Boolean): Any? {
@@ -30,6 +31,18 @@ suspend fun suspendFun(result: Any?, doSuspend: Boolean, doThrow: Boolean): Any?
return result
}
@Throws(CoroutineException::class, CancellationException::class)
suspend fun unitSuspendFun(doSuspend: Boolean, doThrow: Boolean) {
if (doSuspend) {
suspendCoroutineUninterceptedOrReturn<Unit> {
it.resume(Unit)
COROUTINE_SUSPENDED
}
}
if (doThrow) throw CoroutineException()
}
class ContinuationHolder<T> {
internal lateinit var continuation: Continuation<T>
@@ -96,6 +109,7 @@ interface SuspendBridge<T> {
suspend fun unit(value: T): Unit
suspend fun unitAsAny(value: T): Any?
suspend fun nullableUnit(value: T): Unit?
@Throws(Throwable::class) suspend fun nothing(value: T): Nothing
@Throws(Throwable::class) suspend fun nothingAsInt(value: T): Int
@@ -106,7 +120,9 @@ interface SuspendBridge<T> {
abstract class AbstractSuspendBridge : SuspendBridge<Int> {
override suspend fun intAsAny(value: Int): Int = TODO()
override suspend fun unit(value: Int): Unit = TODO()
override suspend fun unitAsAny(value: Int): Unit = TODO()
override suspend fun nullableUnit(value: Int): Unit? = TODO()
override suspend fun nothingAsInt(value: Int): Nothing = TODO()
override suspend fun nothingAsAny(value: Int): Nothing = TODO()
@@ -116,21 +132,25 @@ abstract class AbstractSuspendBridge : SuspendBridge<Int> {
private suspend fun callSuspendBridgeImpl(bridge: SuspendBridge<Int>) {
assertEquals(1, bridge.intAsAny(1))
assertSame(Unit, bridge.unitAsAny(2))
assertSame(Unit, bridge.unit(2))
assertSame(Unit, bridge.unitAsAny(3))
assertSame(Unit, bridge.nullableUnit(4))
assertFailsWith<ObjCErrorException> { bridge.nothingAsInt(3) }
assertFailsWith<ObjCErrorException> { bridge.nothingAsAny(4) }
assertFailsWith<ObjCErrorException> { bridge.nothingAsUnit(5) }
assertFailsWith<ObjCErrorException> { bridge.nothingAsInt(5) }
assertFailsWith<ObjCErrorException> { bridge.nothingAsAny(6) }
assertFailsWith<ObjCErrorException> { bridge.nothingAsUnit(7) }
}
private suspend fun callAbstractSuspendBridgeImpl(bridge: AbstractSuspendBridge) {
assertEquals(6, bridge.intAsAny(6))
assertEquals(8, bridge.intAsAny(8))
assertSame(Unit, bridge.unitAsAny(7))
assertSame(Unit, bridge.unit(9))
assertSame(Unit, bridge.unitAsAny(10))
assertSame(Unit, bridge.nullableUnit(11))
assertFailsWith<ObjCErrorException> { bridge.nothingAsInt(8) }
assertFailsWith<ObjCErrorException> { bridge.nothingAsAny(9) }
assertFailsWith<ObjCErrorException> { bridge.nothingAsUnit(10) }
assertFailsWith<ObjCErrorException> { bridge.nothingAsInt(12) }
assertFailsWith<ObjCErrorException> { bridge.nothingAsAny(13) }
assertFailsWith<ObjCErrorException> { bridge.nothingAsUnit(14) }
}
@Throws(Throwable::class)
@@ -21,6 +21,33 @@ private func testCallSimple() throws {
try assertNil(error)
}
private func testUnitCallSimple() throws {
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
var result: KotlinUnit? = nil
#endif
var error: Error? = nil
var completionCalled = 0
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
CoroutinesKt.unitSuspendFun { _result, _error in
completionCalled += 1
result = _result
error = _error
}
#else
CoroutinesKt.unitSuspendFun { _error in
completionCalled += 1
error = _error
}
#endif
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
try assertSame(actual: result, expected: KotlinUnit.shared)
#endif
try assertEquals(actual: completionCalled, expected: 1)
try assertNil(error)
}
private func testCallSuspendFun(doSuspend: Bool, doThrow: Bool) throws {
class C {}
let expectedResult = C()
@@ -46,6 +73,39 @@ private func testCallSuspendFun(doSuspend: Bool, doThrow: Bool) throws {
}
}
private func testCallUnitSuspendFun(doSuspend: Bool, doThrow: Bool) throws {
var completionCalled = 0
var result: AnyObject? = nil
var error: Error? = nil
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
CoroutinesKt.unitSuspendFun(doSuspend: doSuspend, doThrow: doThrow) { _result, _error in
completionCalled += 1
result = _result as AnyObject?
error = _error
}
#else
CoroutinesKt.unitSuspendFun(doSuspend: doSuspend, doThrow: doThrow) { _error in
completionCalled += 1
error = _error
}
#endif
try assertEquals(actual: completionCalled, expected: 1)
if doThrow {
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
try assertNil(result)
#endif
try assertTrue(error?.kotlinException is CoroutineException)
} else {
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
try assertSame(actual: result, expected: KotlinUnit.shared)
#endif
try assertNil(error)
}
}
private func testSuspendFuncAsync(doThrow: Bool) throws {
var completionCalled = 0
var result: AnyObject? = nil
@@ -91,6 +151,11 @@ private func testCall() throws {
try testCallSuspendFun(doSuspend: true, doThrow: true)
try testCallSuspendFun(doSuspend: false, doThrow: true)
try testCallUnitSuspendFun(doSuspend: true, doThrow: false)
try testCallUnitSuspendFun(doSuspend: false, doThrow: false)
try testCallUnitSuspendFun(doSuspend: true, doThrow: true)
try testCallUnitSuspendFun(doSuspend: false, doThrow: true)
try testSuspendFuncAsync(doThrow: false)
try testSuspendFuncAsync(doThrow: true)
}
@@ -237,10 +302,24 @@ private class SwiftSuspendBridge : AbstractSuspendBridge {
completionHandler(value, nil)
}
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
override func unit(value: KotlinInt, completionHandler: @escaping (KotlinUnit?, Error?) -> Void) {
completionHandler(KotlinUnit(), nil)
}
#else
override func unit(value: KotlinInt, completionHandler: @escaping (Error?) -> Void) {
completionHandler(nil)
}
#endif
override func unitAsAny(value: KotlinInt, completionHandler: @escaping (KotlinUnit?, Error?) -> Void) {
completionHandler(KotlinUnit(), nil)
}
override func nullableUnit(value: KotlinInt, completionHandler: @escaping (KotlinUnit?, Error?) -> Void) {
completionHandler(KotlinUnit(), nil)
}
override func nothingAsInt(value: KotlinInt, completionHandler: @escaping (KotlinNothing?, Error?) -> Void) {
completionHandler(nil, E())
}
@@ -249,9 +328,15 @@ private class SwiftSuspendBridge : AbstractSuspendBridge {
completionHandler(nil, E())
}
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
override func nothingAsUnit(value: KotlinInt, completionHandler: @escaping (KotlinNothing?, Error?) -> Void) {
completionHandler(nil, E())
}
#else
override func nothingAsUnit(value: KotlinInt, completionHandler: @escaping (Error?) -> Void) {
completionHandler(E())
}
#endif
}
private func testBridges() throws {
@@ -268,34 +353,52 @@ private func testBridges() throws {
}
private func testImplicitThrows1() throws {
var result: KotlinUnit? = nil
var error: Error? = nil
var completionCalled = 0
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
var result: KotlinUnit? = nil
CoroutinesKt.throwCancellationException { _result, _error in
completionCalled += 1
result = _result
error = _error
}
try assertEquals(actual: completionCalled, expected: 1)
try assertNil(result)
#else
CoroutinesKt.throwCancellationException { _error in
completionCalled += 1
error = _error
}
#endif
try assertEquals(actual: completionCalled, expected: 1)
try assertTrue(error?.kotlinException is KotlinCancellationException)
}
private func testImplicitThrows2() throws {
var result: KotlinUnit? = nil
var error: Error? = nil
var completionCalled = 0
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
var result: KotlinUnit? = nil
ThrowCancellationExceptionImpl().throwCancellationException { _result, _error in
completionCalled += 1
result = _result
error = _error
completionCalled += 1
result = _result
error = _error
}
try assertEquals(actual: completionCalled, expected: 1)
try assertNil(result)
#else
ThrowCancellationExceptionImpl().throwCancellationException { _error in
completionCalled += 1
error = _error
}
#endif
try assertEquals(actual: completionCalled, expected: 1)
try assertTrue(error?.kotlinException is KotlinCancellationException)
}
@@ -369,6 +472,7 @@ class CoroutinesTests : SimpleTestProvider {
super.init()
test("TestCallSimple", testCallSimple)
test("TestCallUnitSimple", testUnitCallSimple)
test("TestCall", testCall)
test("TestCallChain", testCallChain)
test("TestOverride", testOverride)
@@ -180,7 +180,7 @@ __attribute__((swift_name("SuspendBridge")))
@note This method converts instances of CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
*/
- (void)unitValue:(id _Nullable)value completionHandler:(void (^)(KtKotlinUnit * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("unit(value:completionHandler:)")));
- (void)unitValue:(id _Nullable)value completionHandler:(void (^)(NSError * _Nullable))completionHandler __attribute__((swift_name("unit(value:completionHandler:)")));
/**
@note This method converts instances of CancellationException to errors.
@@ -188,6 +188,12 @@ __attribute__((swift_name("SuspendBridge")))
*/
- (void)unitAsAnyValue:(id _Nullable)value completionHandler:(void (^)(id _Nullable_result, NSError * _Nullable))completionHandler __attribute__((swift_name("unitAsAny(value:completionHandler:)")));
/**
@note This method converts instances of CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
*/
- (void)nullableUnitValue:(id _Nullable)value completionHandler:(void (^)(KtKotlinUnit * _Nullable_result, NSError * _Nullable))completionHandler __attribute__((swift_name("nullableUnit(value:completionHandler:)")));
/**
@note This method converts all Kotlin exceptions to errors.
*/
@@ -206,7 +212,7 @@ __attribute__((swift_name("SuspendBridge")))
/**
@note This method converts all Kotlin exceptions to errors.
*/
- (void)nothingAsUnitValue:(id _Nullable)value completionHandler:(void (^)(KtKotlinUnit * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("nothingAsUnit(value:completionHandler:)")));
- (void)nothingAsUnitValue:(id _Nullable)value completionHandler:(void (^)(NSError * _Nullable))completionHandler __attribute__((swift_name("nothingAsUnit(value:completionHandler:)")));
@end;
__attribute__((swift_name("AbstractSuspendBridge")))
@@ -220,12 +226,24 @@ __attribute__((swift_name("AbstractSuspendBridge")))
*/
- (void)intAsAnyValue:(KtInt *)value completionHandler:(void (^)(KtInt * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("intAsAny(value:completionHandler:)")));
/**
@note This method converts instances of CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
*/
- (void)unitValue:(KtInt *)value completionHandler:(void (^)(NSError * _Nullable))completionHandler __attribute__((swift_name("unit(value:completionHandler:)")));
/**
@note This method converts instances of CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
*/
- (void)unitAsAnyValue:(KtInt *)value completionHandler:(void (^)(KtKotlinUnit * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("unitAsAny(value:completionHandler:)")));
/**
@note This method converts instances of CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
*/
- (void)nullableUnitValue:(KtInt *)value completionHandler:(void (^)(KtKotlinUnit * _Nullable_result, NSError * _Nullable))completionHandler __attribute__((swift_name("nullableUnit(value:completionHandler:)")));
/**
@note This method converts all Kotlin exceptions to errors.
*/
@@ -239,7 +257,7 @@ __attribute__((swift_name("AbstractSuspendBridge")))
/**
@note This method converts all Kotlin exceptions to errors.
*/
- (void)nothingAsUnitValue:(KtInt *)value completionHandler:(void (^)(KtKotlinNothing * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("nothingAsUnit(value:completionHandler:)")));
- (void)nothingAsUnitValue:(KtInt *)value completionHandler:(void (^)(NSError * _Nullable))completionHandler __attribute__((swift_name("nothingAsUnit(value:completionHandler:)")));
@end;
__attribute__((swift_name("ThrowCancellationException")))
@@ -258,7 +276,7 @@ __attribute__((swift_name("ThrowCancellationExceptionImpl")))
@note This method converts instances of CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
*/
- (void)throwCancellationExceptionWithCompletionHandler:(void (^)(KtKotlinUnit * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("throwCancellationException(completionHandler:)")));
- (void)throwCancellationExceptionWithCompletionHandler:(void (^)(NSError * _Nullable))completionHandler __attribute__((swift_name("throwCancellationException(completionHandler:)")));
@end;
__attribute__((objc_subclassing_restricted))
@@ -271,12 +289,24 @@ __attribute__((swift_name("CoroutinesKt")))
*/
+ (void)suspendFunWithCompletionHandler:(void (^)(KtInt * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("suspendFun(completionHandler:)")));
/**
@note This method converts instances of CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
*/
+ (void)unitSuspendFunWithCompletionHandler:(void (^)(NSError * _Nullable))completionHandler __attribute__((swift_name("unitSuspendFun(completionHandler:)")));
/**
@note This method converts instances of CoroutineException, CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
*/
+ (void)suspendFunResult:(id _Nullable)result doSuspend:(BOOL)doSuspend doThrow:(BOOL)doThrow completionHandler:(void (^)(id _Nullable_result, NSError * _Nullable))completionHandler __attribute__((swift_name("suspendFun(result:doSuspend:doThrow:completionHandler:)")));
/**
@note This method converts instances of CoroutineException, CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
*/
+ (void)unitSuspendFunDoSuspend:(BOOL)doSuspend doThrow:(BOOL)doThrow completionHandler:(void (^)(NSError * _Nullable))completionHandler __attribute__((swift_name("unitSuspendFun(doSuspend:doThrow:completionHandler:)")));
/**
@note This method converts instances of CoroutineException, CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
@@ -305,7 +335,7 @@ __attribute__((swift_name("CoroutinesKt")))
@note This method converts instances of CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
*/
+ (void)throwCancellationExceptionWithCompletionHandler:(void (^)(KtKotlinUnit * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("throwCancellationException(completionHandler:)")));
+ (void)throwCancellationExceptionWithCompletionHandler:(void (^)(NSError * _Nullable))completionHandler __attribute__((swift_name("throwCancellationException(completionHandler:)")));
+ (id<KtKotlinSuspendFunction0>)getSuspendLambda0 __attribute__((swift_name("getSuspendLambda0()")));
+ (id<KtKotlinSuspendFunction0>)getSuspendCallableReference0 __attribute__((swift_name("getSuspendCallableReference0()")));
+ (id<KtKotlinSuspendFunction1>)getSuspendLambda1 __attribute__((swift_name("getSuspendLambda1()")));
@@ -1191,7 +1221,7 @@ __attribute__((swift_name("ThrowsThrowableAsErrorSuspend")))
@note This method converts instances of CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
*/
- (void)throwErrorWithCompletionHandler:(void (^)(KtKotlinUnit * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("throwError(completionHandler:)")));
- (void)throwErrorWithCompletionHandler:(void (^)(NSError * _Nullable))completionHandler __attribute__((swift_name("throwError(completionHandler:)")));
@end;
__attribute__((objc_subclassing_restricted))
File diff suppressed because it is too large Load Diff
@@ -180,7 +180,7 @@ __attribute__((swift_name("SuspendBridge")))
@note This method converts instances of CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
*/
- (void)unitValue:(id _Nullable)value completionHandler:(void (^)(KtKotlinUnit * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("unit(value:completionHandler:)")));
- (void)unitValue:(id _Nullable)value completionHandler:(void (^)(NSError * _Nullable))completionHandler __attribute__((swift_name("unit(value:completionHandler:)")));
/**
@note This method converts instances of CancellationException to errors.
@@ -188,6 +188,12 @@ __attribute__((swift_name("SuspendBridge")))
*/
- (void)unitAsAnyValue:(id _Nullable)value completionHandler:(void (^)(id _Nullable_result, NSError * _Nullable))completionHandler __attribute__((swift_name("unitAsAny(value:completionHandler:)")));
/**
@note This method converts instances of CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
*/
- (void)nullableUnitValue:(id _Nullable)value completionHandler:(void (^)(KtKotlinUnit * _Nullable_result, NSError * _Nullable))completionHandler __attribute__((swift_name("nullableUnit(value:completionHandler:)")));
/**
@note This method converts all Kotlin exceptions to errors.
*/
@@ -206,7 +212,7 @@ __attribute__((swift_name("SuspendBridge")))
/**
@note This method converts all Kotlin exceptions to errors.
*/
- (void)nothingAsUnitValue:(id _Nullable)value completionHandler:(void (^)(KtKotlinUnit * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("nothingAsUnit(value:completionHandler:)")));
- (void)nothingAsUnitValue:(id _Nullable)value completionHandler:(void (^)(NSError * _Nullable))completionHandler __attribute__((swift_name("nothingAsUnit(value:completionHandler:)")));
@end;
__attribute__((swift_name("AbstractSuspendBridge")))
@@ -220,12 +226,24 @@ __attribute__((swift_name("AbstractSuspendBridge")))
*/
- (void)intAsAnyValue:(KtInt *)value completionHandler:(void (^)(KtInt * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("intAsAny(value:completionHandler:)")));
/**
@note This method converts instances of CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
*/
- (void)unitValue:(KtInt *)value completionHandler:(void (^)(NSError * _Nullable))completionHandler __attribute__((swift_name("unit(value:completionHandler:)")));
/**
@note This method converts instances of CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
*/
- (void)unitAsAnyValue:(KtInt *)value completionHandler:(void (^)(KtKotlinUnit * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("unitAsAny(value:completionHandler:)")));
/**
@note This method converts instances of CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
*/
- (void)nullableUnitValue:(KtInt *)value completionHandler:(void (^)(KtKotlinUnit * _Nullable_result, NSError * _Nullable))completionHandler __attribute__((swift_name("nullableUnit(value:completionHandler:)")));
/**
@note This method converts all Kotlin exceptions to errors.
*/
@@ -239,7 +257,7 @@ __attribute__((swift_name("AbstractSuspendBridge")))
/**
@note This method converts all Kotlin exceptions to errors.
*/
- (void)nothingAsUnitValue:(KtInt *)value completionHandler:(void (^)(KtKotlinNothing * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("nothingAsUnit(value:completionHandler:)")));
- (void)nothingAsUnitValue:(KtInt *)value completionHandler:(void (^)(NSError * _Nullable))completionHandler __attribute__((swift_name("nothingAsUnit(value:completionHandler:)")));
@end;
__attribute__((swift_name("ThrowCancellationException")))
@@ -258,7 +276,7 @@ __attribute__((swift_name("ThrowCancellationExceptionImpl")))
@note This method converts instances of CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
*/
- (void)throwCancellationExceptionWithCompletionHandler:(void (^)(KtKotlinUnit * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("throwCancellationException(completionHandler:)")));
- (void)throwCancellationExceptionWithCompletionHandler:(void (^)(NSError * _Nullable))completionHandler __attribute__((swift_name("throwCancellationException(completionHandler:)")));
@end;
__attribute__((objc_subclassing_restricted))
@@ -271,12 +289,24 @@ __attribute__((swift_name("CoroutinesKt")))
*/
+ (void)suspendFunWithCompletionHandler:(void (^)(KtInt * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("suspendFun(completionHandler:)")));
/**
@note This method converts instances of CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
*/
+ (void)unitSuspendFunWithCompletionHandler:(void (^)(NSError * _Nullable))completionHandler __attribute__((swift_name("unitSuspendFun(completionHandler:)")));
/**
@note This method converts instances of CoroutineException, CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
*/
+ (void)suspendFunResult:(id _Nullable)result doSuspend:(BOOL)doSuspend doThrow:(BOOL)doThrow completionHandler:(void (^)(id _Nullable_result, NSError * _Nullable))completionHandler __attribute__((swift_name("suspendFun(result:doSuspend:doThrow:completionHandler:)")));
/**
@note This method converts instances of CoroutineException, CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
*/
+ (void)unitSuspendFunDoSuspend:(BOOL)doSuspend doThrow:(BOOL)doThrow completionHandler:(void (^)(NSError * _Nullable))completionHandler __attribute__((swift_name("unitSuspendFun(doSuspend:doThrow:completionHandler:)")));
/**
@note This method converts instances of CoroutineException, CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
@@ -305,7 +335,7 @@ __attribute__((swift_name("CoroutinesKt")))
@note This method converts instances of CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
*/
+ (void)throwCancellationExceptionWithCompletionHandler:(void (^)(KtKotlinUnit * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("throwCancellationException(completionHandler:)")));
+ (void)throwCancellationExceptionWithCompletionHandler:(void (^)(NSError * _Nullable))completionHandler __attribute__((swift_name("throwCancellationException(completionHandler:)")));
+ (id<KtKotlinSuspendFunction0>)getSuspendLambda0 __attribute__((swift_name("getSuspendLambda0()")));
+ (id<KtKotlinSuspendFunction0>)getSuspendCallableReference0 __attribute__((swift_name("getSuspendCallableReference0()")));
+ (id<KtKotlinSuspendFunction1>)getSuspendLambda1 __attribute__((swift_name("getSuspendLambda1()")));
@@ -1133,7 +1163,7 @@ __attribute__((swift_name("ThrowsThrowableAsErrorSuspend")))
@note This method converts instances of CancellationException to errors.
Other uncaught Kotlin exceptions are fatal.
*/
- (void)throwErrorWithCompletionHandler:(void (^)(KtKotlinUnit * _Nullable, NSError * _Nullable))completionHandler __attribute__((swift_name("throwError(completionHandler:)")));
- (void)throwErrorWithCompletionHandler:(void (^)(NSError * _Nullable))completionHandler __attribute__((swift_name("throwError(completionHandler:)")));
@end;
__attribute__((objc_subclassing_restricted))
@@ -38,9 +38,15 @@ private class ThrowsThrowableAsErrorSuspendImpl : ThrowsThrowableAsErrorSuspend
self.throwable = throwable
}
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
func throwError(completionHandler: @escaping (KotlinUnit?, Error?) -> Void) {
completionHandler(nil, throwable.asError())
}
#else
func throwError(completionHandler: @escaping (Error?) -> Void) {
completionHandler(throwable.asError())
}
#endif
}
class ThrowableAsErrorTests : SimpleTestProvider {
@@ -48,12 +48,21 @@ extern "C" OBJ_GETTER(Kotlin_ObjCExport_createContinuationArgument, id completio
RETURN_RESULT_OF(Kotlin_ObjCExport_createContinuationArgumentImpl, completionHolder, exceptionTypes);
}
extern "C" OBJ_GETTER(Kotlin_ObjCExport_createUnitContinuationArgument, id completion, const TypeInfo** exceptionTypes) {
void (^typedCompletion)(NSError * _Nullable) = completion;
Completion twoArgumentCompletion = ^(_Nullable id result, NSError* _Nullable error) {
// typedCompletion will be retained by the containing block when the latter is copied
// from stack to heap via objc_retainBlock.
typedCompletion(error);
};
RETURN_RESULT_OF(Kotlin_ObjCExport_createContinuationArgument, twoArgumentCompletion, exceptionTypes);
}
extern "C" void Kotlin_ObjCExport_resumeContinuationSuccess(KRef continuation, KRef result);
extern "C" void Kotlin_ObjCExport_resumeContinuationFailure(KRef continuation, KRef exception);
extern "C" void Kotlin_ObjCExport_resumeContinuation(KRef continuation, id result, id error) {
ObjHolder holder;
extern "C" void Kotlin_ObjCExport_resumeContinuation(KRef continuation, KRef result, id error) {
if (error != nullptr) {
if (result != nullptr) {
[NSException raise:NSGenericException
@@ -61,11 +70,12 @@ extern "C" void Kotlin_ObjCExport_resumeContinuation(KRef continuation, id resul
result, error];
}
ObjHolder holder;
KRef exception = Kotlin_ObjCExport_NSErrorAsException(error, holder.slot());
Kotlin_ObjCExport_resumeContinuationFailure(continuation, exception);
} else {
KRef kotlinResult = Kotlin_ObjCExport_refFromObjC(result, holder.slot());
Kotlin_ObjCExport_resumeContinuationSuccess(continuation, kotlinResult);
Kotlin_ObjCExport_resumeContinuationSuccess(continuation, result);
}
}
@@ -185,6 +185,7 @@ extern "C" const char* Kotlin_callsCheckerGoodFunctionNames[] = {
"CFStringCreateCopy",
"CFStringGetCharacters",
"CFStringGetLength",
"_Block_object_assign",
"class_addIvar",
"class_addMethod",
"class_addProtocol",