[Wasm] Allow implementing function interfaces
diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt index 73407a8..b39d664 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt
@@ -391,6 +391,9 @@ if (isIrBackendEnabled()) { this[LanguageFeature.JsAllowValueClassesInExternals] = LanguageFeature.State.ENABLED } + if (wasm) { + this[LanguageFeature.JsAllowImplementingFunctionInterface] = LanguageFeature.State.ENABLED + } } } }
diff --git a/compiler/testData/codegen/box/classes/kt1535.kt b/compiler/testData/codegen/box/classes/kt1535.kt index b97b80e..de7816b 100644 --- a/compiler/testData/codegen/box/classes/kt1535.kt +++ b/compiler/testData/codegen/box/classes/kt1535.kt
@@ -1,5 +1,3 @@ -// IGNORE_BACKEND: WASM -// WASM_MUTE_REASON: IMPLEMENTING_FUNCTION_INTERFACE // IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: JS_IR_ES6 // TODO: Enable when JS backend supports Java class library, since FunctionX are required for interoperation
diff --git a/compiler/testData/codegen/box/closures/closureOnTopLevel1.kt b/compiler/testData/codegen/box/closures/closureOnTopLevel1.kt index cfc94f1..1975736 100644 --- a/compiler/testData/codegen/box/closures/closureOnTopLevel1.kt +++ b/compiler/testData/codegen/box/closures/closureOnTopLevel1.kt
@@ -1,5 +1,3 @@ -// IGNORE_BACKEND: WASM -// WASM_MUTE_REASON: IMPLEMENTING_FUNCTION_INTERFACE // IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: JS_IR_ES6 // TODO: muted automatically, investigate should it be ran for JS or not
diff --git a/compiler/testData/codegen/box/closures/closureOnTopLevel2.kt b/compiler/testData/codegen/box/closures/closureOnTopLevel2.kt index 5f25ce4..642b069 100644 --- a/compiler/testData/codegen/box/closures/closureOnTopLevel2.kt +++ b/compiler/testData/codegen/box/closures/closureOnTopLevel2.kt
@@ -1,5 +1,3 @@ -// IGNORE_BACKEND: WASM -// WASM_MUTE_REASON: IMPLEMENTING_FUNCTION_INTERFACE // IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: JS_IR_ES6 // TODO: muted automatically, investigate should it be ran for JS or not
diff --git a/compiler/testData/codegen/box/coroutines/suspendConversion/intersectionTypeToSubtypeConversion.kt b/compiler/testData/codegen/box/coroutines/suspendConversion/intersectionTypeToSubtypeConversion.kt index bb6d30f..261346e 100644 --- a/compiler/testData/codegen/box/coroutines/suspendConversion/intersectionTypeToSubtypeConversion.kt +++ b/compiler/testData/codegen/box/coroutines/suspendConversion/intersectionTypeToSubtypeConversion.kt
@@ -4,8 +4,6 @@ // IGNORE_BACKEND: JVM, JS, JS_IR // IGNORE_BACKEND: JS_IR_ES6 // IGNORE_LIGHT_ANALYSIS -// IGNORE_BACKEND: WASM -// WASM_MUTE_REASON: IGNORED_IN_JS import helpers.* import kotlin.coroutines.*
diff --git a/compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt b/compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt index 966652c..ccc9968 100644 --- a/compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt +++ b/compiler/testData/codegen/box/coroutines/suspendConversion/subtypeOfFunctionalTypeToSuspendConversion.kt
@@ -4,8 +4,6 @@ // IGNORE_BACKEND: JVM, JS, JS_IR // IGNORE_BACKEND: JS_IR_ES6 // IGNORE_LIGHT_ANALYSIS -// IGNORE_BACKEND: WASM -// WASM_MUTE_REASON: IGNORED_IN_JS import helpers.* import kotlin.coroutines.*
diff --git a/compiler/testData/codegen/box/extensionFunctions/extensionFunctionAsSupertype.kt b/compiler/testData/codegen/box/extensionFunctions/extensionFunctionAsSupertype.kt index 72e5f37..9fb4bb9 100644 --- a/compiler/testData/codegen/box/extensionFunctions/extensionFunctionAsSupertype.kt +++ b/compiler/testData/codegen/box/extensionFunctions/extensionFunctionAsSupertype.kt
@@ -1,5 +1,5 @@ // !LANGUAGE: +FunctionalTypeWithExtensionAsSupertype -// IGNORE_BACKEND: JS, JS_IR, WASM +// IGNORE_BACKEND: JS, JS_IR interface I: (String) -> String
diff --git a/compiler/testData/codegen/box/funInterface/intersectionTypeToFunInterfaceConversion.kt b/compiler/testData/codegen/box/funInterface/intersectionTypeToFunInterfaceConversion.kt index ceac246..3d5c955 100644 --- a/compiler/testData/codegen/box/funInterface/intersectionTypeToFunInterfaceConversion.kt +++ b/compiler/testData/codegen/box/funInterface/intersectionTypeToFunInterfaceConversion.kt
@@ -1,5 +1,3 @@ -// IGNORE_BACKEND: WASM -// WASM_MUTE_REASON: IGNORED_IN_JS // IGNORE_BACKEND: JS, JS_IR // IGNORE_BACKEND: JS_IR_ES6
diff --git a/compiler/testData/codegen/box/funInterface/kt46908_functionSupertype.kt b/compiler/testData/codegen/box/funInterface/kt46908_functionSupertype.kt index 7790259..dcf948e 100644 --- a/compiler/testData/codegen/box/funInterface/kt46908_functionSupertype.kt +++ b/compiler/testData/codegen/box/funInterface/kt46908_functionSupertype.kt
@@ -1,4 +1,4 @@ -// IGNORE_BACKEND: JS, JS_IR, WASM +// IGNORE_BACKEND: JS, JS_IR fun interface Foo : () -> Int
diff --git a/compiler/testData/codegen/box/funInterface/subtypeOfFunctionalTypeToFunInterfaceConversion.kt b/compiler/testData/codegen/box/funInterface/subtypeOfFunctionalTypeToFunInterfaceConversion.kt index 5084a208..95339eb 100644 --- a/compiler/testData/codegen/box/funInterface/subtypeOfFunctionalTypeToFunInterfaceConversion.kt +++ b/compiler/testData/codegen/box/funInterface/subtypeOfFunctionalTypeToFunInterfaceConversion.kt
@@ -1,5 +1,3 @@ -// IGNORE_BACKEND: WASM -// WASM_MUTE_REASON: IGNORED_IN_JS // IGNORE_BACKEND: JS, JS_IR // IGNORE_BACKEND: JS_IR_ES6
diff --git a/compiler/testData/codegen/box/functions/bigArity/subclass.kt b/compiler/testData/codegen/box/functions/bigArity/subclass.kt index 86f7537..98af6b6 100644 --- a/compiler/testData/codegen/box/functions/bigArity/subclass.kt +++ b/compiler/testData/codegen/box/functions/bigArity/subclass.kt
@@ -1,5 +1,3 @@ -// IGNORE_BACKEND: WASM -// WASM_MUTE_REASON: IGNORED_IN_JS // !LANGUAGE: +FunctionTypesWithBigArity // Implementing function interface is prohibited in JavaScript
diff --git a/compiler/testData/codegen/box/functions/invoke/kt3190.kt b/compiler/testData/codegen/box/functions/invoke/kt3190.kt index ade3888..4786050 100644 --- a/compiler/testData/codegen/box/functions/invoke/kt3190.kt +++ b/compiler/testData/codegen/box/functions/invoke/kt3190.kt
@@ -1,5 +1,3 @@ -// IGNORE_BACKEND: WASM -// WASM_MUTE_REASON: IGNORED_IN_JS // IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: JS_IR_ES6 //KT-3190 Compiler crash if function called 'invoke' calls a closure
diff --git a/compiler/testData/codegen/box/functions/invoke/kt3822invokeOnThis.kt b/compiler/testData/codegen/box/functions/invoke/kt3822invokeOnThis.kt index 8e561ee..5279ca2 100644 --- a/compiler/testData/codegen/box/functions/invoke/kt3822invokeOnThis.kt +++ b/compiler/testData/codegen/box/functions/invoke/kt3822invokeOnThis.kt
@@ -1,5 +1,3 @@ -// IGNORE_BACKEND: WASM -// WASM_MUTE_REASON: IMPLEMENTING_FUNCTION_INTERFACE // IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: JS_IR_ES6 //KT-3822 Compiler crashes when use invoke convention with `this` in class which extends Function0<T>
diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/CompilerTestLanguageVersionSettings.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/CompilerTestLanguageVersionSettings.kt index e6e234d..c420549 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/CompilerTestLanguageVersionSettings.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/CompilerTestLanguageVersionSettings.kt
@@ -53,7 +53,11 @@ fun parseLanguageVersionSettingsOrDefault(directiveMap: Directives): CompilerTestLanguageVersionSettings = parseLanguageVersionSettings(directiveMap) ?: defaultLanguageVersionSettings() -fun parseLanguageVersionSettings(directives: Directives): CompilerTestLanguageVersionSettings? { +@JvmOverloads +fun parseLanguageVersionSettings( + directives: Directives, + extraLanguageFeatures: Map<LanguageFeature, LanguageFeature.State> = emptyMap() +): CompilerTestLanguageVersionSettings? { val apiVersionString = directives[API_VERSION_DIRECTIVE] val languageFeaturesString = directives[LANGUAGE_DIRECTIVE] @@ -81,7 +85,7 @@ val languageVersion = maxOf(LanguageVersion.LATEST_STABLE, LanguageVersion.fromVersionString(apiVersion.versionString)!!) - val languageFeatures = languageFeaturesString?.let(::collectLanguageFeatureMap).orEmpty() + val languageFeatures = languageFeaturesString?.let(::collectLanguageFeatureMap).orEmpty() + extraLanguageFeatures return CompilerTestLanguageVersionSettings(languageFeatures, apiVersion, languageVersion, mapOf(*analysisFlags.toTypedArray())) }
diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index a5cfce4..4877766 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt
@@ -315,6 +315,7 @@ ValueClasses(sinceVersion = null, kind = UNSTABLE_FEATURE), JavaSamConversionEqualsHashCode(sinceVersion = null, kind = UNSTABLE_FEATURE), UnitConversionsOnArbitraryExpressions(sinceVersion = null), + JsAllowImplementingFunctionInterface(sinceVersion = null, kind = UNSTABLE_FEATURE), ; init {
diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsInheritanceChecker.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsInheritanceChecker.kt index 927ac3c..a3e48c4 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsInheritanceChecker.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsInheritanceChecker.kt
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.builtins.isBuiltinFunctionalTypeOrSubtype import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor @@ -44,10 +45,12 @@ } } - if (descriptor is ClassDescriptor && - descriptor.defaultType.immediateSupertypes().any { it.isBuiltinFunctionalTypeOrSubtype && !it.isSuspendFunctionTypeOrSubtype } - ) { - context.trace.report(ErrorsJs.IMPLEMENTING_FUNCTION_INTERFACE.on(declaration as KtClassOrObject)) + if (!context.languageVersionSettings.supportsFeature(LanguageFeature.JsAllowImplementingFunctionInterface)) { + if (descriptor is ClassDescriptor && + descriptor.defaultType.immediateSupertypes().any { it.isBuiltinFunctionalTypeOrSubtype && !it.isSuspendFunctionTypeOrSubtype } + ) { + context.trace.report(ErrorsJs.IMPLEMENTING_FUNCTION_INTERFACE.on(declaration as KtClassOrObject)) + } } }
diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/testOld/BasicWasmBoxTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/testOld/BasicWasmBoxTest.kt index 0a8e5c9..1085e99 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/testOld/BasicWasmBoxTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/testOld/BasicWasmBoxTest.kt
@@ -48,6 +48,10 @@ private val COMMON_FILES_NAME = "_common" + private val extraLanguageFeatures = mapOf( + LanguageFeature.JsAllowImplementingFunctionInterface to LanguageFeature.State.ENABLED, + ) + fun doTest(filePath: String) = doTestWithTransformer(filePath) { it } fun doTestWithTransformer(filePath: String, transformer: java.util.function.Function<String, String>) { val file = File(filePath) @@ -244,7 +248,7 @@ configuration.put(JSConfigurationKeys.WASM_ENABLE_ARRAY_RANGE_CHECKS, true) configuration.put(JSConfigurationKeys.WASM_ENABLE_ASSERTS, true) configuration.languageVersionSettings = languageVersionSettings - ?: LanguageVersionSettingsImpl(LanguageVersion.LATEST_STABLE, ApiVersion.LATEST_STABLE) + ?: LanguageVersionSettingsImpl(LanguageVersion.LATEST_STABLE, ApiVersion.LATEST_STABLE, specificFeatures = extraLanguageFeatures) return JsConfig(project, configuration, CompilerEnvironment, null, null) } @@ -259,7 +263,7 @@ } } - val languageVersionSettings = parseLanguageVersionSettings(directives) + val languageVersionSettings = parseLanguageVersionSettings(directives, extraLanguageFeatures) val temporaryFile = File(tmpDir, "WASM_TEST/$fileName") KtTestUtil.mkdirs(temporaryFile.parentFile)