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:
+2
@@ -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>(
|
||||
|
||||
+3
@@ -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
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -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)
|
||||
|
||||
+26
@@ -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,
|
||||
}
|
||||
+1
@@ -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
|
||||
|
||||
+46
-7
@@ -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) {
|
||||
|
||||
+3
-3
@@ -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
|
||||
|
||||
|
||||
+3
-2
@@ -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,
|
||||
|
||||
+10
-6
@@ -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"))
|
||||
)
|
||||
|
||||
+3
-1
@@ -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)
|
||||
|
||||
|
||||
+5
-3
@@ -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 {
|
||||
|
||||
+4
-3
@@ -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)
|
||||
|
||||
+3
-3
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user