dokar3 / quickjs-kt Goto Github PK
View Code? Open in Web Editor NEWA QuickJS binding for idiomatic Kotlin, with Async/DSL/ES Modules support.
License: Apache License 2.0
A QuickJS binding for idiomatic Kotlin, with Async/DSL/ES Modules support.
License: Apache License 2.0
Hi,
I have a Kotlin Multiplatform project that fails at the linking step when building for iOS (device or simulator).
Here is the stack in XCode when trying to build :
Stack Trace :
Undefined symbols for architecture arm64:
"_JS_AtomToValue", referenced from:
_quickjs_JS_AtomToValue_wrapper62 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_Call", referenced from:
_quickjs_JS_Call_wrapper145 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_CallConstructor", referenced from:
_quickjs_JS_CallConstructor_wrapper147 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_DefinePropertyGetSet", referenced from:
_quickjs_JS_DefinePropertyGetSet_wrapper158 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_DefinePropertyValue", referenced from:
_quickjs_JS_DefinePropertyValue_wrapper155 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_DefinePropertyValueStr", referenced from:
_quickjs_JS_DefinePropertyValueStr_wrapper157 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_Eval", referenced from:
_quickjs_JS_Eval_wrapper150 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_EvalFunction", referenced from:
_quickjs_JS_EvalFunction_wrapper188 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_ExecutePendingJob", referenced from:
_quickjs_JS_ExecutePendingJob_wrapper184 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_FreeAtom", referenced from:
_quickjs_JS_FreeAtom_wrapper60 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_FreeCString", referenced from:
_quickjs_JS_FreeCString_wrapper118 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_GetArrayBuffer", referenced from:
_quickjs_JS_GetArrayBuffer_wrapper168 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_GetException", referenced from:
_quickjs_JS_GetException_wrapper91 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_GetGlobalObject", referenced from:
_quickjs_JS_GetGlobalObject_wrapper152 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_GetOwnPropertyNames", referenced from:
_quickjs_JS_GetOwnPropertyNames_wrapper143 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_GetPropertyInternal", referenced from:
_quickjs_JS_GetProperty_wrapper129 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_GetPropertyStr", referenced from:
_quickjs_JS_GetPropertyStr_wrapper130 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_GetPropertyUint32", referenced from:
_quickjs_JS_GetPropertyUint32_wrapper131 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_GetRuntime", referenced from:
_quickjs_JS_GetRuntime_wrapper20 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_IsArray", referenced from:
_quickjs_JS_IsArray_wrapper127 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_IsError", referenced from:
_quickjs_JS_IsError_wrapper92 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_IsFunction", referenced from:
_quickjs_JS_IsFunction_wrapper123 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_IsInstanceOf", referenced from:
_quickjs_JS_IsInstanceOf_wrapper153 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_JSONStringify", referenced from:
_quickjs_JS_JSONStringify_wrapper164 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_NewArray", referenced from:
_quickjs_JS_NewArray_wrapper126 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_NewArrayBuffer", referenced from:
_quickjs_JS_NewArrayBuffer_wrapper165 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_NewAtom", referenced from:
_quickjs_JS_NewAtom_wrapper57 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_NewCFunctionData", referenced from:
_quickjs_JS_NewCFunctionData_wrapper193 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_NewContext", referenced from:
_quickjs_JS_NewContext_wrapper15 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_NewError", referenced from:
_quickjs_JS_NewError_wrapper94 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_NewObject", referenced from:
_quickjs_JS_NewObject_wrapper122 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_NewPromiseCapability", referenced from:
_quickjs_JS_NewPromiseCapability_wrapper171 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_NewRuntime", referenced from:
_quickjs_JS_NewRuntime_wrapper2 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_NewString", referenced from:
_quickjs_JS_NewString_wrapper111 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_PromiseResult", referenced from:
_quickjs_JS_PromiseResult_wrapper173 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_PromiseState", referenced from:
_quickjs_JS_PromiseState_wrapper172 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_ReadObject", referenced from:
_quickjs_JS_ReadObject_wrapper187 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_SetHostPromiseRejectionTracker", referenced from:
_quickjs_JS_SetHostPromiseRejectionTracker_wrapper174 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_SetPropertyStr", referenced from:
_quickjs_JS_SetPropertyStr_wrapper136 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_SetPropertyUint32", referenced from:
_quickjs_JS_SetPropertyUint32_wrapper134 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_Throw", referenced from:
_quickjs_JS_Throw_wrapper90 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_ToBool", referenced from:
_quickjs_JS_ToBool_wrapper102 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_ToCStringLen2", referenced from:
_quickjs_JS_ToCString_wrapper117 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_ToFloat64", referenced from:
_quickjs_JS_ToFloat64_wrapper107 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_ToInt32", referenced from:
_quickjs_JS_ToInt32_wrapper103 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_ToInt64", referenced from:
_quickjs_JS_ToInt64_wrapper105 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_UpdateStackTop", referenced from:
_quickjs_JS_UpdateStackTop_wrapper7 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_JS_WriteObject", referenced from:
_quickjs_JS_WriteObject_wrapper185 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"___JS_FreeValue", referenced from:
_quickjs_JS_FreeValue_wrapper97 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
"_js_free", referenced from:
_quickjs_js_free_wrapper47 in Shared[arm64][9](libquickjs-kt:quickjs-cinterop-quickjs-cache.a.o)
ld: symbol(s) not found for architecture arm64
Steps to reproduce :
sourceSets
in build.gradle.kts
of the shared
modulequickJs
method in Greeting.kt
in commonMain
in shared
moduleiosApp
folderAny idea of where it comes from ?
Thanks for your help !
catch()
currently does not work as expected. The following code will throw an error.
quickJs {
asyncFunction("fetch") { error("Not implemented.") }
}
fetch("SOME_URL")
.catch((e) => {});
Can you add a section to the README on how to properly handle js exceptions?
This does not work if an exception occurs in the js code. An error is thrown but this does not catch it:
val result = try {
wrapper.evaluateJs(jscode)
}
catch (e: Exception) {
Logger.e { "Javascript error: $e" }
null
}
throws this error:
Exception in thread "DefaultDispatcher-worker-10" java.lang.RuntimeException: Exception while trying to handle coroutine exception
at kotlinx.coroutines.CoroutineExceptionHandlerKt.handlerException(CoroutineExceptionHandler.kt:33)
at kotlinx.coroutines.internal.CoroutineExceptionHandlerImpl_commonKt.handleUncaughtCoroutineException(CoroutineExceptionHandlerImpl.common.kt:38)
at kotlinx.coroutines.CoroutineExceptionHandlerKt.handleCoroutineException(CoroutineExceptionHandler.kt:28)
at kotlinx.coroutines.StandaloneCoroutine.handleJobException(Builders.common.kt:190)
at kotlinx.coroutines.JobSupport.finalizeFinishingState(JobSupport.kt:228)
at kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath(JobSupport.kt:907)
at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:864)
at kotlinx.coroutines.JobSupport.makeCompletingOnce$kotlinx_coroutines_core(JobSupport.kt:829)
at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:97)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at kotlinx.coroutines.internal.ScopeCoroutine.afterResume(Scopes.kt:28)
at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:99)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:102)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:585)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:802)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:706)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:693)
Suppressed: java.lang.Error: Error: test
at dictionaryapi (main.js:5)
at <anonymous> (main.js:12)
at search (main.js)
at <eval> (main.js:2)
at com.dokar.quickjs.QuickJs.getEvaluateResult(Native Method)
at com.dokar.quickjs.QuickJs.evalAndAwait(QuickJs.jni.kt:220)
at com.dokar.quickjs.QuickJs.evaluateInternal(QuickJs.jni.kt:210)
...
This js code works as expected when I define my own host.log function, but it would be nicer if I could catch the error in kotlin:
try {
doStuff();
}
catch (err) {
host.log("caught js error: ", err);
}
thanks for all your quick updates!
Have you tried to use a suspend function via reflection, as shown below? I'm getting an error "parameter count mismatched"
class Http {
suspend fun fetch(url: String) = "..."
}
quickJs {
define<Http>("http", Http())
evaluate<Any?>(
"""
await http.fetch("https://www.example.com")
""".trimIndent()
)
}
There are some leaks in the JS runtime after evaluation. They won't crash JS_FreeRuntime
but need to be fixed.
Currently, all jobs will get canceled if one throws an error, regardless of whether they have been caught in JavaScript.
The behavior needs to be implemented correctly.
Related to #12
This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.
These updates have all been created already. Click a checkbox below to force a retry/rebase of any.
org.jetbrains.kotlin.plugin.allopen
, org.jetbrains.kotlin.android
, org.jetbrains.kotlin.jvm
, org.jetbrains.kotlin.multiplatform
, org.jetbrains.kotlin:kotlin-test-junit
, org.jetbrains.kotlin:kotlin-test
)scripts/package.json
@types/bun ^1.0.5
.github/workflows/benchmark.yaml
actions/checkout v4
actions/setup-java v4
jwlawson/actions-setup-cmake v2.0
goto-bus-stop/setup-zig v2
oven-sh/setup-bun v1
gradle/gradle-build-action v3.1.0
stefanzweifel/git-auto-commit-action v5
.github/workflows/build.yaml
actions/checkout v4
actions/setup-java v4
jwlawson/actions-setup-cmake v2.0
goto-bus-stop/setup-zig v2
oven-sh/setup-bun v1
gradle/gradle-build-action v3.1.0
.github/workflows/publish.yaml
actions/checkout v4
actions/setup-java v4
jwlawson/actions-setup-cmake v2.0
goto-bus-stop/setup-zig v2
oven-sh/setup-bun v1
gradle/gradle-build-action v3.1.0
buildSrc/src/main/kotlin/com/dokar/quickjs/Platform.kt
buildSrc/src/main/kotlin/com/dokar/quickjs/applyQuickJsNativeBuildTasks.kt
buildSrc/src/main/kotlin/com/dokar/quickjs/buildQuickJsNativeLibrary.kt
buildSrc/src/main/kotlin/com/dokar/quickjs/disableUnsupportedPlatformTasks.kt
gradle.properties
settings.gradle.kts
build.gradle.kts
benchmark/build.gradle.kts
buildSrc/settings.gradle.kts
buildSrc/build.gradle.kts
gradle/libs.versions.toml
androidx.core:core-ktx 1.12.0
junit:junit 4.13.2
androidx.test.ext:junit 1.1.5
androidx.activity:activity-compose 1.8.2
androidx.compose.ui:ui-tooling 1.6.4
androidx.compose.ui:ui-tooling-preview 1.6.4
org.jetbrains.kotlin:kotlin-test 1.9.22
org.jetbrains.kotlin:kotlin-test-junit 1.9.22
org.jetbrains.kotlinx:kotlinx-coroutines-core 1.8.0
org.jetbrains.kotlinx:kotlinx-coroutines-test 1.8.0
org.jetbrains.kotlinx:kotlinx-benchmark-runtime 0.4.10
com.github.ajalt.clikt:clikt 4.2.2
io.ktor:ktor-client-core 3.0.0-beta-1
io.ktor:ktor-client-cio 3.0.0-beta-1
com.android.application 8.3.1
com.android.library 8.3.1
org.jetbrains.compose 1.6.0
org.jetbrains.kotlin.multiplatform 1.9.22
org.jetbrains.kotlin.jvm 1.9.22
org.jetbrains.kotlin.android 1.9.22
org.jetbrains.kotlinx.benchmark 0.4.10
org.jetbrains.kotlin.plugin.allopen 1.9.22
com.vanniktech.maven.publish 0.28.0
quickjs/gradle.properties
quickjs/build.gradle.kts
samples/js-eval/build.gradle.kts
samples/openai/build.gradle.kts
samples/repl/build.gradle.kts
com.github.johnrengelman.shadow 8.1.1
gradle/wrapper/gradle-wrapper.properties
gradle 8.7
Currently, the detection of circular references not working on deep-level circular references:
// Not able to detect in this case
val set = mutableSetOf<Any?>()
val array = arrayOf(set)
set.add(array)
Need to re-implement the detection code.
val js = """
var response = await kml.requestJson('https://icanhazdadjoke.com/');
let parsed = JSON.parse(response);
parsed.joke;
""".trimIndent()
val joke = quickJs {
define("kml") {
asyncFunction("requestJson") { args ->
delay(500)
"""
{"id":"bxXLeqzP7wc","joke":"Americans can't switch from pounds to kilograms overnight. That would cause mass confusion.","status":200}
""".trimIndent()
}
}
evaluate<Any?>(js)?.toString()
}
Causes this error. Not every time but frequently:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x0000000188e4aa9c, pid=63005, tid=90371
#
# JRE version: OpenJDK Runtime Environment (17.0.7) (build 17.0.7+0-17.0.7b1000.6-10550314)
# Java VM: OpenJDK 64-Bit Server VM (17.0.7+0-17.0.7b1000.6-10550314, mixed mode, tiered, compressed oops, compressed class ptrs, g1 gc, bsd-aarch64)
# Problematic frame:
# C [libsystem_platform.dylib+0xa9c] _platform_strcmp+0xc
#
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
JNI global refs:
JNI global refs: 161, weak refs: 11
JNI global refs memory usage: 2099, weak refs: 833
OOME stack traces (most recent first):
Classloader memory used:
Loader jdk.internal.loader.ClassLoaders$AppClassLoader : 3926K
Loader bootstrap : 2694K
Loader jdk.internal.loader.ClassLoaders$PlatformClassLoader : 18987B
Loader jdk.internal.reflect.DelegatingClassLoader : 4278B
# An error report file with more information is saved as:
# /Users/dmelton/Developer/doug/kmlauncher/compose-multiplatform/composeApp/hs_err_pid63005.log
#
# If you would like to submit a bug report, please visit:
# https://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
I removed any actual networking, but simulated by that delay(500)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.