JS: support SAM conversion

The SAM adapter is generate on declaration site. This is different
from the JVM approach.

`external fun interface` is banned for now.

Reusing interface declaration for the adapter is a hack which
reduces code size and makes importing/exporting the adapter
effortless.
This commit is contained in:
Anton Bannykh
2020-02-14 16:12:50 +03:00
parent 2742e643c1
commit 23e218396e
18 changed files with 249 additions and 7 deletions
@@ -1,6 +1,5 @@
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS
// SKIP_DCE_DRIVEN
fun interface Foo {
@@ -0,0 +1,33 @@
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
// IGNORE_BACKEND: JVM, JVM_IR, JS_IR
// IGNORE_BACKEND_FIR: JVM_IR
// SKIP_DCE_DRIVEN
fun interface Base {
fun doStuff(): String
}
fun interface I : Base
fun interface Proxy : I {
override fun doStuff(): String = doStuffInt().toString()
fun doStuffInt(): Int
}
fun runBase(b: Base) = b.doStuff()
fun runI(i: I) = i.doStuff()
fun runProxy(p: Proxy) = p.doStuff()
fun box(): String {
if (runI { "i" } != "i") return "fail1"
if (runProxy { 10 } != "10") return "fail2"
return runBase { "OK" }
}
@@ -0,0 +1,32 @@
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
// IGNORE_BACKEND_FIR: JVM_IR
// SKIP_DCE_DRIVEN
// MODULE: m1
// FILE: m1.kt
fun interface I {
fun f(): String
}
fun rn(i: I) = i.f()
inline fun rnInline(i: I) = i.f()
// MODULE: m2(m1)
// FILE: m2.kt
fun rn2(f: () -> String) = rn(f)
inline fun rn2Inline(noinline f: () -> String) = rnInline(f)
// MODULE: main(m2)
// FILE: main.kt
fun box(): String {
if (rn2Inline { "inline" } != "inline") return "fail"
return rn2 { "OK" }
}
@@ -1,6 +1,5 @@
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS
// WITH_RUNTIME
// SKIP_DCE_DRIVEN
@@ -1,6 +1,5 @@
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS
// WITH_RUNTIME
// SKIP_DCE_DRIVEN
@@ -0,0 +1,20 @@
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
// IGNORE_BACKEND_FIR: JVM_IR
// SKIP_DCE_DRIVEN
// This test should check argument coercion between the SAM and the lambda.
// For now it checks that Char is boxed in JS
fun interface CharToAny {
fun invoke(c: Char): Any
}
fun foo(c: CharToAny): Any = c.invoke('O')
fun box(): String {
if (foo { it } !is Char) return "fail"
return "OK"
}
@@ -1,6 +1,5 @@
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS
// WITH_RUNTIME
// SKIP_DCE_DRIVEN
@@ -1,11 +1,11 @@
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS, JS_IR
// IGNORE_BACKEND: JS_IR
// WITH_COROUTINES
// WITH_RUNTIME
import helpers.*
import kotlin.coroutines.startCoroutine
import kotlin.coroutines.*
fun interface SuspendRunnable {
suspend fun invoke()
@@ -17,11 +17,25 @@ fun run(r: SuspendRunnable) {
var result = "initial"
var resumingCallback: () -> Unit = {}
suspend fun bar() {
// Generate proper state machine
suspendCoroutine<Unit> { cont ->
resumingCallback = {
cont.resume(Unit)
}
}
result = "OK"
}
fun box(): String {
run(::bar)
if (result != "initial") return "fail"
resumingCallback()
return result
}