diff --git a/build.gradle.kts b/build.gradle.kts index a6b7aa66..f144cc18 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,14 +4,20 @@ import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion import util.kotlinVersionParsed +import util.libs plugins { alias(libs.plugins.serialization) apply false alias(libs.plugins.kotlinx.rpc) apply false - alias(libs.plugins.atomicfu) apply false alias(libs.plugins.conventions.kover) alias(libs.plugins.conventions.gradle.doctor) alias(libs.plugins.binary.compatibility.validator) + + if (libs.versions.atomicfu.get() >= "0.24.0") { + alias(libs.plugins.atomicfu.new) + } else { + alias(libs.plugins.atomicfu.old) + } } // useful for dependencies introspection diff --git a/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RPCIrContext.kt b/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RPCIrContext.kt index b8806b14..a178a42b 100644 --- a/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RPCIrContext.kt +++ b/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RPCIrContext.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.ir.types.makeNullable import org.jetbrains.kotlin.ir.util.functions import org.jetbrains.kotlin.ir.util.isVararg import org.jetbrains.kotlin.ir.util.properties +import org.jetbrains.kotlin.platform.isWasm import org.jetbrains.kotlin.platform.konan.isNative import org.jetbrains.kotlin.types.Variance @@ -131,6 +132,10 @@ internal class RPCIrContext( return pluginContext.platform.isNative() } + fun isWasmTarget(): Boolean { + return pluginContext.platform.isWasm() + } + val functions = Functions() inner class Functions { diff --git a/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RPCStubGenerator.kt b/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RPCStubGenerator.kt index d5b01715..e30fa060 100644 --- a/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RPCStubGenerator.kt +++ b/compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/extension/RPCStubGenerator.kt @@ -1209,10 +1209,10 @@ internal class RPCStubGenerator( } } - // Associated object annotation works on JS and Native platforms. + // Associated object annotation works on JS, WASM, and Native platforms. // See https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.reflect/find-associated-object.html private fun addAssociatedObjectAnnotationIfPossible() { - if (ctx.isJsTarget() || ctx.isNativeTarget()) { + if (ctx.isJsTarget() || ctx.isNativeTarget() || ctx.isWasmTarget()) { addAssociatedObjectAnnotation() } } diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 3d3b5e22..467a5f60 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,12 +1,21 @@ +/* + * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. + */ + +import util.applyAtomicfuPlugin + /* * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. */ plugins { alias(libs.plugins.conventions.kmp) - alias(libs.plugins.atomicfu) + alias(libs.plugins.kotlinx.rpc) + alias(libs.plugins.serialization) } +applyAtomicfuPlugin() + kotlin { sourceSets { commonMain { @@ -24,5 +33,11 @@ kotlin { implementation(libs.kotlin.js.wrappers) } } + + wasmJsMain { + dependencies { + implementation(libs.kotlinx.browser) + } + } } } diff --git a/core/src/wasmJsMain/kotlin/kotlinx/rpc/internal/ReflectionUtils.wasm.kt b/core/src/wasmJsMain/kotlin/kotlinx/rpc/internal/ReflectionUtils.wasm.kt new file mode 100644 index 00000000..f24dc855 --- /dev/null +++ b/core/src/wasmJsMain/kotlin/kotlinx/rpc/internal/ReflectionUtils.wasm.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. + */ + +@file:Suppress("detekt.MatchingDeclarationName") + +package kotlinx.rpc.internal + +import kotlinx.rpc.internal.utils.InternalRPCApi +import kotlin.reflect.KClass + +@InternalRPCApi +public actual val KClass<*>.qualifiedClassNameOrNull: String? + get() = toString() + +@InternalRPCApi +public actual val KClass<*>.typeName: String? + get() = qualifiedClassNameOrNull diff --git a/core/src/wasmJsMain/kotlin/kotlinx/rpc/internal/WithRPCStubObject.wasm.kt b/core/src/wasmJsMain/kotlin/kotlinx/rpc/internal/WithRPCStubObject.wasm.kt new file mode 100644 index 00000000..054f9fbe --- /dev/null +++ b/core/src/wasmJsMain/kotlin/kotlinx/rpc/internal/WithRPCStubObject.wasm.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. + */ + +@file:Suppress("detekt.MatchingDeclarationName") + +package kotlinx.rpc.internal + +import kotlinx.rpc.RPC +import kotlinx.rpc.internal.utils.InternalRPCApi +import kotlin.reflect.AssociatedObjectKey +import kotlin.reflect.ExperimentalAssociatedObjects +import kotlin.reflect.KClass +import kotlin.reflect.findAssociatedObject + +@InternalRPCApi +@AssociatedObjectKey +@OptIn(ExperimentalAssociatedObjects::class) +@Target(AnnotationTarget.CLASS) +public annotation class WithRPCStubObject( + @Suppress("unused") + val stub: KClass> +) + +@OptIn(ExperimentalAssociatedObjects::class) +@InternalRPCApi +public actual fun findRPCStubProvider(kClass: KClass<*>, resultKClass: KClass): R { + val associatedObject = kClass.findAssociatedObject() + ?: internalError("Unable to find $kClass associated object") + + if (resultKClass.isInstance(associatedObject)) { + @Suppress("UNCHECKED_CAST") + return associatedObject as R + } + + internalError( + "Located associated object is not of desired type $resultKClass, " + + "instead found $associatedObject of class " + + (associatedObject::class.qualifiedClassNameOrNull ?: associatedObject::class) + ) +} diff --git a/core/src/wasmWasiMain/kotlin/kotlinx/rpc/internal/ReflectionUtils.wasi.kt b/core/src/wasmWasiMain/kotlin/kotlinx/rpc/internal/ReflectionUtils.wasi.kt new file mode 100644 index 00000000..f24dc855 --- /dev/null +++ b/core/src/wasmWasiMain/kotlin/kotlinx/rpc/internal/ReflectionUtils.wasi.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. + */ + +@file:Suppress("detekt.MatchingDeclarationName") + +package kotlinx.rpc.internal + +import kotlinx.rpc.internal.utils.InternalRPCApi +import kotlin.reflect.KClass + +@InternalRPCApi +public actual val KClass<*>.qualifiedClassNameOrNull: String? + get() = toString() + +@InternalRPCApi +public actual val KClass<*>.typeName: String? + get() = qualifiedClassNameOrNull diff --git a/core/src/wasmWasiMain/kotlin/kotlinx/rpc/internal/WithRPCStubObject.wasi.kt b/core/src/wasmWasiMain/kotlin/kotlinx/rpc/internal/WithRPCStubObject.wasi.kt new file mode 100644 index 00000000..054f9fbe --- /dev/null +++ b/core/src/wasmWasiMain/kotlin/kotlinx/rpc/internal/WithRPCStubObject.wasi.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. + */ + +@file:Suppress("detekt.MatchingDeclarationName") + +package kotlinx.rpc.internal + +import kotlinx.rpc.RPC +import kotlinx.rpc.internal.utils.InternalRPCApi +import kotlin.reflect.AssociatedObjectKey +import kotlin.reflect.ExperimentalAssociatedObjects +import kotlin.reflect.KClass +import kotlin.reflect.findAssociatedObject + +@InternalRPCApi +@AssociatedObjectKey +@OptIn(ExperimentalAssociatedObjects::class) +@Target(AnnotationTarget.CLASS) +public annotation class WithRPCStubObject( + @Suppress("unused") + val stub: KClass> +) + +@OptIn(ExperimentalAssociatedObjects::class) +@InternalRPCApi +public actual fun findRPCStubProvider(kClass: KClass<*>, resultKClass: KClass): R { + val associatedObject = kClass.findAssociatedObject() + ?: internalError("Unable to find $kClass associated object") + + if (resultKClass.isInstance(associatedObject)) { + @Suppress("UNCHECKED_CAST") + return associatedObject as R + } + + internalError( + "Located associated object is not of desired type $resultKClass, " + + "instead found $associatedObject of class " + + (associatedObject::class.qualifiedClassNameOrNull ?: associatedObject::class) + ) +} diff --git a/gradle-conventions-settings/src/main/kotlin/util/JsTarget.kt b/gradle-conventions-settings/src/main/kotlin/util/JsTarget.kt index a53c3b46..7c3ba27a 100644 --- a/gradle-conventions-settings/src/main/kotlin/util/JsTarget.kt +++ b/gradle-conventions-settings/src/main/kotlin/util/JsTarget.kt @@ -4,27 +4,50 @@ package util -import org.gradle.api.Project +import org.gradle.api.Action import org.gradle.kotlin.dsl.invoke +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet +import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl +import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsTargetDsl +import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget import java.io.File -fun Project.configureJs() { - configureJsTasks() +fun ProjectKotlinConfig.configureJsAndWasmJs() { + configureJsAndWasmJsTasks() kotlin { sourceSets { - jsTest { - dependencies { - implementation(npm("puppeteer", "*")) + if (js) { + jsTest { + puppeteer() + } + } + + if (wasmJs) { + wasmJsMain { + dependencies { + implementation(libs.kotlinx.browser) + } + } + + wasmJsTest { + puppeteer() } } } } } -private fun Project.configureJsTasks() { +private fun KotlinSourceSet.puppeteer() { + dependencies { + implementation(npm("puppeteer", "*")) + } +} + +private fun ProjectKotlinConfig.configureJsAndWasmJsTasks() { kotlin { - js(IR) { + jsAnsWasmJs(this@configureJsAndWasmJsTasks) { nodejs { testTask { useMocha { @@ -33,7 +56,7 @@ private fun Project.configureJsTasks() { } } - browser { + (this as KotlinJsIrTarget).whenBrowserConfigured { testTask { useKarma { useChromeHeadless() @@ -41,8 +64,17 @@ private fun Project.configureJsTasks() { } } } - - binaries.library() } } } + +@OptIn(ExperimentalWasmDsl::class) +private fun KotlinMultiplatformExtension.jsAnsWasmJs( + config: ProjectKotlinConfig, + configure: Action, +) { + listOfNotNull( + if (config.js) js(IR) else null, + if (config.wasmJs) wasmJs() else null, + ).forEach { configure(it) } +} diff --git a/gradle-conventions-settings/src/main/kotlin/util/OptionalProperty.kt b/gradle-conventions-settings/src/main/kotlin/util/OptionalProperty.kt index 2a705c02..4542b515 100644 --- a/gradle-conventions-settings/src/main/kotlin/util/OptionalProperty.kt +++ b/gradle-conventions-settings/src/main/kotlin/util/OptionalProperty.kt @@ -8,7 +8,7 @@ import org.gradle.api.Project import kotlin.reflect.KProperty class OptionalProperty(private val target: Project) { - operator fun getValue(thisRef: Any, property: KProperty<*>): Boolean { + operator fun getValue(thisRef: Any?, property: KProperty<*>): Boolean { return getValue("kotlinx.rpc.${property.name}") } diff --git a/gradle-conventions-settings/src/main/kotlin/util/ProjectKotlinConfig.kt b/gradle-conventions-settings/src/main/kotlin/util/ProjectKotlinConfig.kt new file mode 100644 index 00000000..1026978d --- /dev/null +++ b/gradle-conventions-settings/src/main/kotlin/util/ProjectKotlinConfig.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. + */ + +package util + +import org.gradle.api.Project +import org.gradle.kotlin.dsl.extra +import org.gradle.kotlin.dsl.provideDelegate + +class ProjectKotlinConfig( + project: Project, + val kotlinVersion: KotlinVersion, + val jvm: Boolean = true, + val js: Boolean = true, + val wasmJs: Boolean = true, + val wasmWasi: Boolean = true, + val native: Boolean = true, +) : Project by project + +fun Project.withKotlinConfig(configure: ProjectKotlinConfig.() -> Unit) { + val kotlinVersion: KotlinVersion by extra + val excludeJvm: Boolean by optionalProperty() + val excludeJs: Boolean by optionalProperty() + val excludeWasmJs: Boolean by optionalProperty() + val excludeWasmWasi: Boolean by optionalProperty() + val excludeNative: Boolean by optionalProperty() + + ProjectKotlinConfig( + project = project, + kotlinVersion = kotlinVersion, + jvm = !excludeJvm, + js = !excludeJs, + wasmJs = !excludeWasmJs, + wasmWasi = !excludeWasmWasi, + native = !excludeNative, + ).configure() +} diff --git a/gradle-conventions-settings/src/main/kotlin/util/TargetUtils.kt b/gradle-conventions-settings/src/main/kotlin/util/TargetUtils.kt index bcc03e0e..153a5cf8 100644 --- a/gradle-conventions-settings/src/main/kotlin/util/TargetUtils.kt +++ b/gradle-conventions-settings/src/main/kotlin/util/TargetUtils.kt @@ -12,6 +12,7 @@ import org.gradle.jvm.toolchain.JavaLanguageVersion import org.gradle.kotlin.dsl.the import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.plugin.KotlinTarget +import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl import java.io.File import kotlin.reflect.full.memberFunctions @@ -21,9 +22,9 @@ const val TARGETS_SINCE_KOTLIN_LOOKUP_PATH = "versions-root/targets-since-kotlin /** * In the lookup table: - * "*" - target supported any Kotlin compiler version - * "-" - target supported none of Kotlin compiler versions - * "" - target supported since kotlin version including that version + * "*" – target supported any Kotlin compiler version + * "-" – target supported none of Kotlin compiler versions + * "" – target supported since a Kotlin version including that version */ @Suppress("UNCHECKED_CAST") private fun loadTargetsSinceKotlinLookupTable(rootDir: String): Map { @@ -40,22 +41,25 @@ private fun isIncluded(targetName: String, kotlinVersion: KotlinVersion, lookupT } ?: false } +@OptIn(ExperimentalWasmDsl::class) private fun KotlinMultiplatformExtension.configureTargets( - project: Project, - kotlinVersion: KotlinVersion, targetsLookup: Map, - jvm: Boolean = true, - js: Boolean = true, - native: Boolean = true, + config: ProjectKotlinConfig, ): List { val targets = mutableListOf() - if (native) { - val nativeLookup = targetsLookup.filterKeys { key -> key != "jvm" && key != "js" } + if (config.native) { + val nativeLookup = targetsLookup.filterKeys { key -> + key != "jvm" && key != "js" && !key.startsWith("wasm") + } val nativeTargets = this::class.memberFunctions .filter { targetFunction -> - targetFunction.parameters.size == 1 && isIncluded(targetFunction.name, kotlinVersion, nativeLookup) + targetFunction.parameters.size == 1 && isIncluded( + targetName = targetFunction.name, + kotlinVersion = config.kotlinVersion, + lookupTable = nativeLookup, + ) }.map { function -> function.call(this) as KotlinTarget } @@ -65,7 +69,7 @@ private fun KotlinMultiplatformExtension.configureTargets( // TLDR: Default hierarchy template is enabled by default since 1.9.20 // // https://kotlinlang.org/docs/multiplatform-hierarchy.html#default-hierarchy-template - if (nativeTargets.isNotEmpty() && !kotlinVersion.isAtLeast(1, 9, 20)) { + if (nativeTargets.isNotEmpty() && !config.kotlinVersion.isAtLeast(1, 9, 20)) { val commonMain = sourceSets.findByName("commonMain")!! val commonTest = sourceSets.findByName("commonTest")!! val nativeMain = sourceSets.create("nativeMain") @@ -81,20 +85,39 @@ private fun KotlinMultiplatformExtension.configureTargets( } } - if (jvm && isIncluded("jvm", kotlinVersion, targetsLookup)) { + if (config.jvm && isIncluded("jvm", config.kotlinVersion, targetsLookup)) { jvm().also { targets.add(it) } } - if (js && isIncluded("js", kotlinVersion, targetsLookup)) { + if (config.js && isIncluded("js", config.kotlinVersion, targetsLookup)) { js(IR) { nodejs() browser() + + binaries.library() }.also { targets.add(it) } } + if (config.wasmJs && isIncluded("wasmJs", config.kotlinVersion, targetsLookup)) { + wasmJs { + browser() + nodejs() + + binaries.library() + } + } + + if (config.wasmWasi && isIncluded("wasmWasi", config.kotlinVersion, targetsLookup)) { + wasmWasi { + nodejs() + + binaries.library() + } + } + targets.forEach { target -> target.mavenPublication { - setPublicArtifactId(project) + setPublicArtifactId(config.project) } } @@ -102,28 +125,20 @@ private fun KotlinMultiplatformExtension.configureTargets( } private fun Project.configureDetekt(targets: List) { - val sources = (targets.map { it.name} + "common" + "native").flatMap { name -> + val sources = (targets.map { it.name } + "common" + "native").flatMap { name -> listOf("src/${name}Main/kotlin", "src/${name}Test/kotlin") } the().source.from(sources) } -fun Project.configureKotlin( - kotlinVersion: KotlinVersion, - jvm: Boolean = true, - js: Boolean = true, - native: Boolean = true, - action: Action = Action { }, -) { +fun ProjectKotlinConfig.configureKotlin(action: Action = Action { }) { val lookupTable = loadTargetsSinceKotlinLookupTable(rootProject.rootDir.absolutePath) - if (js) { - configureJs() - } + configureJsAndWasmJs() kotlin { - val includedTargets = configureTargets(project, kotlinVersion, lookupTable, jvm, js, native) + val includedTargets = configureTargets(lookupTable, this@configureKotlin) configureDetekt(includedTargets) diff --git a/gradle-conventions-settings/src/main/kotlin/util/atomicfu.kt b/gradle-conventions-settings/src/main/kotlin/util/atomicfu.kt new file mode 100644 index 00000000..45acf13b --- /dev/null +++ b/gradle-conventions-settings/src/main/kotlin/util/atomicfu.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. + */ + +package util + +import org.gradle.api.Project + +fun Project.applyAtomicfuPlugin() { + if (libs.versions.atomicfu.get() >= "0.24.0") { + plugins.apply(libs.plugins.atomicfu.new.get().pluginId) + } else { + plugins.apply(libs.plugins.atomicfu.old.get().pluginId) + } +} diff --git a/gradle-conventions/src/main/kotlin/conventions-kmp.gradle.kts b/gradle-conventions/src/main/kotlin/conventions-kmp.gradle.kts index c0e14974..3a51958a 100644 --- a/gradle-conventions/src/main/kotlin/conventions-kmp.gradle.kts +++ b/gradle-conventions/src/main/kotlin/conventions-kmp.gradle.kts @@ -6,7 +6,7 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import util.configureJvm import util.configureKotlin import util.optInForRPCApi -import util.optionalProperty +import util.withKotlinConfig plugins { id("conventions-common") @@ -19,17 +19,8 @@ configure { explicitApi() } -val excludeJs: Boolean by optionalProperty() -val excludeJvm: Boolean by optionalProperty() -val excludeNative: Boolean by optionalProperty() - -val kotlinVersion: KotlinVersion by extra - -configureKotlin( - kotlinVersion = kotlinVersion, - jvm = !excludeJvm, - js = !excludeJs, - native = !excludeNative, -) +withKotlinConfig { + configureKotlin() +} configureJvm(isKmp = true) diff --git a/krpc/gradle.properties b/krpc/gradle.properties new file mode 100644 index 00000000..ae9b5585 --- /dev/null +++ b/krpc/gradle.properties @@ -0,0 +1,6 @@ +# +# Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. +# + +# https://github.com/oshai/kotlin-logging/issues/433 +kotlinx.rpc.excludeWasmWasi=true diff --git a/krpc/krpc-client/build.gradle.kts b/krpc/krpc-client/build.gradle.kts index d8a62f85..d1871a40 100644 --- a/krpc/krpc-client/build.gradle.kts +++ b/krpc/krpc-client/build.gradle.kts @@ -2,12 +2,15 @@ * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. */ +import util.applyAtomicfuPlugin + plugins { alias(libs.plugins.conventions.kmp) alias(libs.plugins.serialization) - alias(libs.plugins.atomicfu) } +applyAtomicfuPlugin() + kotlin { sourceSets { commonMain { diff --git a/krpc/krpc-core/build.gradle.kts b/krpc/krpc-core/build.gradle.kts index eb4a967a..906052f2 100644 --- a/krpc/krpc-core/build.gradle.kts +++ b/krpc/krpc-core/build.gradle.kts @@ -2,12 +2,15 @@ * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. */ +import util.applyAtomicfuPlugin + plugins { alias(libs.plugins.conventions.kmp) - alias(libs.plugins.atomicfu) alias(libs.plugins.serialization) } +applyAtomicfuPlugin() + kotlin { sourceSets { commonMain { diff --git a/krpc/krpc-core/src/wasmJsMain/kotlin/kotlinx/rpc/krpc/internal/ExceptionUtils.wasm.kt b/krpc/krpc-core/src/wasmJsMain/kotlin/kotlinx/rpc/krpc/internal/ExceptionUtils.wasm.kt new file mode 100644 index 00000000..67babd76 --- /dev/null +++ b/krpc/krpc-core/src/wasmJsMain/kotlin/kotlinx/rpc/krpc/internal/ExceptionUtils.wasm.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. + */ + +@file:Suppress("detekt.MatchingDeclarationName") + +package kotlinx.rpc.krpc.internal + +import kotlinx.rpc.internal.utils.InternalRPCApi + +internal actual class DeserializedException actual constructor( + private val toStringMessage: String, + actual override val message: String, + stacktrace: List, + cause: SerializedException?, + className: String +) : Throwable() { + + override val cause: Throwable? = cause?.deserialize() + + override fun toString(): String = toStringMessage +} + + +internal actual fun Throwable.stackElements(): List = emptyList() + +@InternalRPCApi +public actual fun SerializedException.deserialize(): Throwable { + return DeserializedException(toStringMessage, message, stacktrace, cause, className) +} diff --git a/krpc/krpc-ktor/krpc-ktor-server/src/jvmMain/kotlin/kotlinx/rpc/krpc/ktor/server/KtorServerDsl.kt b/krpc/krpc-ktor/krpc-ktor-server/src/jvmMain/kotlin/kotlinx/rpc/krpc/ktor/server/KtorServerDsl.kt index 0ab93b50..0a93956d 100644 --- a/krpc/krpc-ktor/krpc-ktor-server/src/jvmMain/kotlin/kotlinx/rpc/krpc/ktor/server/KtorServerDsl.kt +++ b/krpc/krpc-ktor/krpc-ktor-server/src/jvmMain/kotlin/kotlinx/rpc/krpc/ktor/server/KtorServerDsl.kt @@ -7,7 +7,7 @@ package kotlinx.rpc.krpc.ktor.server import io.ktor.server.application.* import io.ktor.server.routing.* import io.ktor.server.websocket.* -import io.ktor.util.* +import io.ktor.utils.io.* import kotlinx.coroutines.job import kotlinx.rpc.krpc.rpcServerConfig diff --git a/krpc/krpc-server/build.gradle.kts b/krpc/krpc-server/build.gradle.kts index f1eaf3ed..2d9879d0 100644 --- a/krpc/krpc-server/build.gradle.kts +++ b/krpc/krpc-server/build.gradle.kts @@ -2,12 +2,15 @@ * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. */ +import util.applyAtomicfuPlugin + plugins { alias(libs.plugins.conventions.kmp) alias(libs.plugins.serialization) - alias(libs.plugins.atomicfu) } +applyAtomicfuPlugin() + kotlin { sourceSets { commonMain { diff --git a/krpc/krpc-test/build.gradle.kts b/krpc/krpc-test/build.gradle.kts index df52fedd..f3227b52 100644 --- a/krpc/krpc-test/build.gradle.kts +++ b/krpc/krpc-test/build.gradle.kts @@ -5,15 +5,17 @@ import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode import org.jetbrains.kotlin.gradle.targets.jvm.tasks.KotlinJvmTest import org.jetbrains.kotlin.utils.fileUtils.withReplacedExtensionOrNull +import util.applyAtomicfuPlugin import java.nio.file.Files plugins { alias(libs.plugins.conventions.kmp) alias(libs.plugins.serialization) alias(libs.plugins.kotlinx.rpc) - alias(libs.plugins.atomicfu) } +applyAtomicfuPlugin() + kotlin { sourceSets { jvmMain { diff --git a/utils/build.gradle.kts b/utils/build.gradle.kts index 3c5c5468..35bbe433 100644 --- a/utils/build.gradle.kts +++ b/utils/build.gradle.kts @@ -3,12 +3,14 @@ */ import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode +import util.applyAtomicfuPlugin plugins { alias(libs.plugins.conventions.kmp) - alias(libs.plugins.atomicfu) } +applyAtomicfuPlugin() + kotlin { sourceSets { commonMain { diff --git a/utils/src/wasmJsMain/kotlin/kotlinx/rpc/internal/utils/map/ConcurrentHashMap.wasm.kt b/utils/src/wasmJsMain/kotlin/kotlinx/rpc/internal/utils/map/ConcurrentHashMap.wasm.kt new file mode 100644 index 00000000..0a01e1ce --- /dev/null +++ b/utils/src/wasmJsMain/kotlin/kotlinx/rpc/internal/utils/map/ConcurrentHashMap.wasm.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.rpc.internal.utils.map + +import kotlinx.rpc.internal.utils.InternalRPCApi + +@InternalRPCApi +actual fun ConcurrentHashMap(initialSize: Int): ConcurrentHashMap { + return SynchronizedHashMap() +} diff --git a/utils/src/wasmWasiMain/kotlin/kotlinx/rpc/internal/utils/map/ConcurrentHashMap.wasi.kt b/utils/src/wasmWasiMain/kotlin/kotlinx/rpc/internal/utils/map/ConcurrentHashMap.wasi.kt new file mode 100644 index 00000000..0a01e1ce --- /dev/null +++ b/utils/src/wasmWasiMain/kotlin/kotlinx/rpc/internal/utils/map/ConcurrentHashMap.wasi.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.rpc.internal.utils.map + +import kotlinx.rpc.internal.utils.InternalRPCApi + +@InternalRPCApi +actual fun ConcurrentHashMap(initialSize: Int): ConcurrentHashMap { + return SynchronizedHashMap() +} diff --git a/versions-root/kotlin-versions-lookup.csv b/versions-root/kotlin-versions-lookup.csv index c6baa99b..787eeab2 100644 --- a/versions-root/kotlin-versions-lookup.csv +++ b/versions-root/kotlin-versions-lookup.csv @@ -1,6 +1,6 @@ Kotlin,ksp,atomicfu,serialization,detekt-gradle-plugin,gradle-kotlin-dsl,binary-compatibility-validator,kover -2.0.10,0.0.0,0.22.0,1.6.1,1.23.6,4.3.0,0.14.0,0.8.0 -2.0.0,0.0.0,0.22.0,1.6.1,1.23.6,4.3.0,0.14.0,0.8.0 +2.0.10,0.0.0,0.25.0,1.7.1,1.23.6,4.3.0,0.14.0,0.8.0 +2.0.0,0.0.0,0.25.0,1.7.1,1.23.6,4.3.0,0.14.0,0.8.0 1.9.25,1.0.20,0.22.0,1.6.1,1.23.6,4.1.0,0.14.0,0.8.0 1.9.24,1.0.20,0.22.0,1.6.1,1.23.6,4.1.0,0.14.0,0.8.0 1.9.23,1.0.19,0.22.0,1.6.1,1.23.6,4.1.0,0.14.0,0.8.0 @@ -18,4 +18,4 @@ Kotlin,ksp,atomicfu,serialization,detekt-gradle-plugin,gradle-kotlin-dsl,binary- 1.7.21,1.0.8,0.18.5,1.4.1,1.22.0,2.3.3,0.12.0,0.0.0 1.7.20,1.0.8,0.18.5,1.4.1,1.22.0,2.3.3,0.12.0,0.0.0 1.7.10,1.0.6,0.18.0,1.4.0,1.22.0,2.3.3,0.12.0,0.0.0 -1.7.0,1.0.6,0.18.0,1.4.0,1.22.0,2.3.3,0.12.0,0.0.0 \ No newline at end of file +1.7.0,1.0.6,0.18.0,1.4.0,1.22.0,2.3.3,0.12.0,0.0.0 diff --git a/versions-root/libs.versions.toml b/versions-root/libs.versions.toml index 91ad9b08..fce3d1c1 100644 --- a/versions-root/libs.versions.toml +++ b/versions-root/libs.versions.toml @@ -7,9 +7,9 @@ kotlin-lang = "2.0.10" # kotlin independent versions detekt-analyzer = "1.23.6" -coroutines = "1.8.1" -ktor = "2.3.11" -kotlin-logging = "6.0.9" +coroutines = "1.9.0-RC.2" +ktor = "3.0.0-rc-1" +kotlin-logging = "7.0.0" slf4j = "2.0.13" logback = "1.3.14" gradle-plugin-publish = "1.2.1" @@ -18,9 +18,10 @@ junit4 = "4.13.2" junit5 = "5.10.3" intellij = "213.7172.53" gradle-doctor = "0.10.0" +kotlinx-browser = "0.1" # stub versions – relpaced based on kotlin, mostly for gradle-related (plugins) dependencies -# but also for dependencies for compiler specific modules +# but also for dependencies for compiler-specific modules ksp = "" atomicfu = "" serialization = "" @@ -49,6 +50,7 @@ kotlin-compiler = { module = "org.jetbrains.kotlin:kotlin-compiler", version.ref kotlin-compiler-embeddable = { module = "org.jetbrains.kotlin:kotlin-compiler-embeddable" } kotlin-compiler-test-framework = { module = "org.jetbrains.kotlin:kotlin-compiler-internal-test-framework", version.ref = "kotlin-lang" } serialization-plugin = { module = "org.jetbrains.kotlin:kotlin-serialization-compiler-plugin", version.ref = "kotlin-lang" } +kotlinx-browser = { module = "org.jetbrains.kotlinx:kotlinx-browser", version.ref = "kotlinx-browser" } # serialization serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core", version.ref = "serialization" } @@ -104,7 +106,8 @@ serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt-gradle-plugin" } binary-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binary-compatibility-validator" } -atomicfu = { id = "kotlinx-atomicfu", version.ref = "atomicfu" } +atomicfu-old = { id = "kotlinx-atomicfu", version.ref = "atomicfu" } +atomicfu-new = { id = "org.jetbrains.kotlinx.atomicfu", version.ref = "atomicfu" } gradle-kotlin-dsl = { id = "org.gradle.kotlin.kotlin-dsl", version.ref = "gradle-kotlin-dsl" } kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" } gradle-plugin-publish = { id = "com.gradle.plugin-publish", version.ref = "gradle-plugin-publish" } diff --git a/versions-root/targets-since-kotlin-lookup.json b/versions-root/targets-since-kotlin-lookup.json index fc0dbb50..c78a27a8 100644 --- a/versions-root/targets-since-kotlin-lookup.json +++ b/versions-root/targets-since-kotlin-lookup.json @@ -2,6 +2,9 @@ "jvm": "*", "js": "*", + "wasmJs": "2.0.0", + "wasmWasi": "2.0.0", + "mingwX64": "-", "linuxX64": "1.9.10",