我目前正在开发一个同样针对 NodeJs 的 Kotlin 多平台项目。 到目前为止,使用 Gradle 构建和执行项目测试运行良好,没有任何问题。
最近我尝试使用 snarkjs 包 作为我的 jsMain 源集的依赖项。
但不知何故,这搞乱了我的构建,我无法弄清楚这个特定包有什么问题。导入包没有问题,但是一旦我使用此包中的任何功能,我的应用程序或单元测试将不再终止。
这是特别令人困惑的,因为到目前为止导入和使用其他包运行良好,Gradle 提示显示所有测试都成功,但不知何故,尽管在日志中没有找到错误,但任务并没有终止。
因此,在(子)项目中,我定义了以下
build.gradle.kts
,其中还包含我的 js 源对 snarkjs
的依赖。
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
group = /*...*/
version = "0.1.0"
plugins {
kotlin("multiplatform")
kotlin("plugin.serialization")
kotlin("plugin.noarg")
id("dev.adamko.dokkatoo-html")
}
kotlin {
@OptIn(ExperimentalKotlinGradlePluginApi::class)
compilerOptions {
freeCompilerArgs.add("-Xexpect-actual-classes")
}
noArg{
annotation(/*...*/)
}
js(IR) {
useCommonJs()
nodejs {
testTask { }
}
binaries.executable()
}
sourceSets {
all {
languageSettings.optIn("kotlin.uuid.ExperimentalUuidApi")
}
commonMain.dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.1")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.0")
implementation(project.dependencies.platform("org.kotlincrypto.hash:bom:0.5.1"))
implementation("org.kotlincrypto.hash:md")
implementation("com.ionspin.kotlin:bignum:0.3.10")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")
}
commonTest.dependencies {
implementation(kotlin("test"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.9.0")
}
jsMain.dependencies {
implementation(npm("snarkjs", ">=0.7.4"))
implementation(kotlinWrappers.node)
}
jsTest.dependencies { }
dependencies { }
}
}
dokkatoo {
dokkatooSourceSets.configureEach {
externalDocumentationLinks {
val `kotlinx-serialization` by creating {
url("https://kotlinlang.org/api/kotlinx.serialization/")
}
val `kotlinx-datetime` by creating {
url("https://kotlinlang.org/api/kotlinx-datetime/")
}
}
}
}
在我的
jsMain/kotlin
src 文件夹中,我将包导入到 snarkjs.kt
文件中:
@file:JsModule("snarkjs")
@file:JsQualifier("groth16")
package snarkjs.groth16
import kotlin.js.Promise
external fun fullProve(_input: dynamic, wasmFile: String, zkeyFileName: String, logger: dynamic): Promise<Any>
并尝试在单元测试中使用它,如下所示:
package /*...*/
import kotlinx.coroutines.test.runTest
import snarkjs.groth16.*
import kotlin.test.Ignore
import kotlin.test.Test
class SnarkJSServiceTest {
@Test
fun awaitProof() = runTest {
val result = fullProve(
JSON.parse("{\"a\": 2, \"b\": 4}"),
"kotlin/test_circuit_js/test_circuit.wasm",
"kotlin/test_circuit.zkey",
null
).await()
println(JSON.stringify(result))
}
}
这就是事情变得疯狂的地方。当测试函数执行成功并且有效结果打印到终端时,
./gradlew :check
任务不会显示任何错误或失败的测试,但也不会终止。
在终端中执行命令将生成以下输出(wallet 是 gradle 子模块的名称)。测试在 6 秒后终止,之后 gradle 永远停留在 85%。 --debug 日志没有显示任何错误或警告。
./gradlew :wallet:check
Type-safe project accessors is an incubating feature.
<===========--> 85% EXECUTING [9s]
> :wallet:jsNodeTest > 63 tests completed, 2 skipped
如果我用
@Ignore
注释上面显示的单元测试,所有命令将毫无问题地终止。
将函数导入 Kotlin/JS 是有效的,因为单元测试将打印正确的结果。 我也非常确定我的项目设置也有效,因为使用 node:fs 包没有任何问题。 那么有什么是我忽略的吗? 我将非常感谢曾经遇到过类似问题的任何人的帮助。
干杯;)
仔细查看 snarkjs 包后,我遇到了以下问题 snarkjs #152 并注意到这确实是包的错误,而不是 Gradle、NodeJS、Kotlin/JS 或任何其他的错误。
解决方案是通过在需要的地方添加以下代码行来终止在后台创建但未由库关闭的全局句柄:
js.globals.globalThis.curve_bn128.terminate()