Javet
Javet copied to clipboard
Crash by Nodejs Circular API
Thanks for this brilliant project. I found that some Nodejs Api which act as a builder pattern cause a cricular reference in this project which makes it crash.
class Block(private val block: java.lang.Runnable): IJavetDirectCallable.NoThisAndNoResult<RuntimeException> {
override fun call(vararg v8Values: V8Value) {
block.run()
}
}
val runtime = V8Host.getNodeInstance().createV8Runtime<V8Runtime>()
val call = it.createV8ValueFunction(
JavetCallbackContext(
"block",
V8ValueSymbolType.None,
JavetCallbackType.DirectCallNoThisAndNoResult,
Block{
println("fooo")
}
)
)
val foo = runtime.globalObject.invoke<V8ValueObject>("setImmediate", call, it.globalObject)
and then
// Boom!
foo.invokeObject<V8ValueObject>("unref").invokeObject<V8ValueObject>("ref")
or
foo.invokeObject<V8ValueObject>("unref")
runtime.globalObject.set("foo", foo)
// Boom!
runtime.getExecutor("foo.ref().unref().ref().unref()").executeVoid()
NodeJS setImmediate
returns Immediate, which returns self when calling ref
and unref
.
which make stacktrace like below
Exception in thread "main" com.caoccao.javet.exceptions.JavetConverterException: Circular structure is detected with max depth 20 reached
at com.caoccao.javet.exceptions.JavetConverterException.circularStructure(JavetConverterException.java:60)
at com.caoccao.javet.interop.converters.BaseJavetConverter.validateDepth(BaseJavetConverter.java:111)
at com.caoccao.javet.interop.converters.JavetPrimitiveConverter.toObject(JavetPrimitiveConverter.java:51)
at com.caoccao.javet.interop.converters.JavetObjectConverter.toObject(JavetObjectConverter.java:203)
at com.caoccao.javet.interop.converters.JavetObjectConverter.lambda$toObject$4(JavetObjectConverter.java:306)
at com.caoccao.javet.values.reference.V8ValueObject.forEach(V8ValueObject.java:310)
at com.caoccao.javet.values.reference.IV8ValueObject.forEach(IV8ValueObject.java:302)
at com.caoccao.javet.interop.converters.JavetObjectConverter.toObject(JavetObjectConverter.java:297)
at com.caoccao.javet.interop.converters.JavetObjectConverter.lambda$toObject$4(JavetObjectConverter.java:306)
at com.caoccao.javet.values.reference.V8ValueObject.forEach(V8ValueObject.java:310)
at com.caoccao.javet.values.reference.IV8ValueObject.forEach(IV8ValueObject.java:302)
at com.caoccao.javet.interop.converters.JavetObjectConverter.toObject(JavetObjectConverter.java:297)
at com.caoccao.javet.interop.converters.JavetObjectConverter.lambda$toObject$4(JavetObjectConverter.java:306)
at com.caoccao.javet.values.reference.V8ValueObject.forEach(V8ValueObject.java:310)
at com.caoccao.javet.values.reference.IV8ValueObject.forEach(IV8ValueObject.java:302)
at com.caoccao.javet.interop.converters.JavetObjectConverter.toObject(JavetObjectConverter.java:297)
at com.caoccao.javet.interop.converters.JavetObjectConverter.lambda$toObject$4(JavetObjectConverter.java:306)
at com.caoccao.javet.values.reference.V8ValueObject.forEach(V8ValueObject.java:310)
at com.caoccao.javet.values.reference.IV8ValueObject.forEach(IV8ValueObject.java:302)
at com.caoccao.javet.interop.converters.JavetObjectConverter.toObject(JavetObjectConverter.java:297)
at com.caoccao.javet.interop.converters.JavetObjectConverter.lambda$toObject$4(JavetObjectConverter.java:306)
at com.caoccao.javet.values.reference.V8ValueObject.forEach(V8ValueObject.java:310)
at com.caoccao.javet.values.reference.IV8ValueObject.forEach(IV8ValueObject.java:302)
at com.caoccao.javet.interop.converters.JavetObjectConverter.toObject(JavetObjectConverter.java:297)
at com.caoccao.javet.interop.converters.JavetObjectConverter.lambda$toObject$4(JavetObjectConverter.java:306)
at com.caoccao.javet.values.reference.V8ValueObject.forEach(V8ValueObject.java:310)
at com.caoccao.javet.values.reference.IV8ValueObject.forEach(IV8ValueObject.java:302)
at com.caoccao.javet.interop.converters.JavetObjectConverter.toObject(JavetObjectConverter.java:297)
at com.caoccao.javet.interop.converters.JavetObjectConverter.lambda$toObject$4(JavetObjectConverter.java:306)
at com.caoccao.javet.values.reference.V8ValueObject.forEach(V8ValueObject.java:310)
at com.caoccao.javet.values.reference.IV8ValueObject.forEach(IV8ValueObject.java:302)
at com.caoccao.javet.interop.converters.JavetObjectConverter.toObject(JavetObjectConverter.java:297)
at com.caoccao.javet.interop.converters.JavetObjectConverter.lambda$toObject$4(JavetObjectConverter.java:306)
at com.caoccao.javet.values.reference.V8ValueObject.forEach(V8ValueObject.java:310)
at com.caoccao.javet.values.reference.IV8ValueObject.forEach(IV8ValueObject.java:302)
at com.caoccao.javet.interop.converters.JavetObjectConverter.toObject(JavetObjectConverter.java:297)
at com.caoccao.javet.interop.converters.JavetObjectConverter.lambda$toObject$4(JavetObjectConverter.java:306)
at com.caoccao.javet.values.reference.V8ValueObject.forEach(V8ValueObject.java:310)
at com.caoccao.javet.values.reference.IV8ValueObject.forEach(IV8ValueObject.java:302)
at com.caoccao.javet.interop.converters.JavetObjectConverter.toObject(JavetObjectConverter.java:297)
at com.caoccao.javet.interop.converters.JavetObjectConverter.lambda$toObject$4(JavetObjectConverter.java:306)
at com.caoccao.javet.values.reference.V8ValueObject.forEach(V8ValueObject.java:310)
at com.caoccao.javet.values.reference.IV8ValueObject.forEach(IV8ValueObject.java:302)
at com.caoccao.javet.interop.converters.JavetObjectConverter.toObject(JavetObjectConverter.java:297)
at com.caoccao.javet.interop.converters.JavetObjectConverter.lambda$toObject$4(JavetObjectConverter.java:306)
at com.caoccao.javet.values.reference.V8ValueObject.forEach(V8ValueObject.java:310)
at com.caoccao.javet.values.reference.IV8ValueObject.forEach(IV8ValueObject.java:302)
at com.caoccao.javet.interop.converters.JavetObjectConverter.toObject(JavetObjectConverter.java:297)
at com.caoccao.javet.interop.converters.JavetObjectConverter.lambda$toObject$4(JavetObjectConverter.java:306)
at com.caoccao.javet.values.reference.V8ValueObject.forEach(V8ValueObject.java:310)
at com.caoccao.javet.values.reference.IV8ValueObject.forEach(IV8ValueObject.java:302)
at com.caoccao.javet.interop.converters.JavetObjectConverter.toObject(JavetObjectConverter.java:297)
at com.caoccao.javet.interop.converters.JavetObjectConverter.lambda$toObject$4(JavetObjectConverter.java:306)
at com.caoccao.javet.values.reference.V8ValueObject.forEach(V8ValueObject.java:310)
at com.caoccao.javet.values.reference.IV8ValueObject.forEach(IV8ValueObject.java:302)
at com.caoccao.javet.interop.converters.JavetObjectConverter.toObject(JavetObjectConverter.java:297)
at com.caoccao.javet.interop.converters.JavetObjectConverter.lambda$toObject$4(JavetObjectConverter.java:306)
at com.caoccao.javet.values.reference.V8ValueObject.forEach(V8ValueObject.java:310)
at com.caoccao.javet.values.reference.IV8ValueObject.forEach(IV8ValueObject.java:302)
at com.caoccao.javet.interop.converters.JavetObjectConverter.toObject(JavetObjectConverter.java:297)
at com.caoccao.javet.interop.converters.JavetObjectConverter.lambda$toObject$4(JavetObjectConverter.java:306)
at com.caoccao.javet.values.reference.V8ValueObject.forEach(V8ValueObject.java:310)
at com.caoccao.javet.values.reference.IV8ValueObject.forEach(IV8ValueObject.java:302)
at com.caoccao.javet.interop.converters.JavetObjectConverter.toObject(JavetObjectConverter.java:297)
at com.caoccao.javet.interop.converters.JavetObjectConverter.lambda$toObject$4(JavetObjectConverter.java:306)
at com.caoccao.javet.values.reference.V8ValueObject.forEach(V8ValueObject.java:310)
at com.caoccao.javet.values.reference.IV8ValueObject.forEach(IV8ValueObject.java:302)
at com.caoccao.javet.interop.converters.JavetObjectConverter.toObject(JavetObjectConverter.java:297)
at com.caoccao.javet.interop.converters.JavetObjectConverter.lambda$toObject$4(JavetObjectConverter.java:306)
at com.caoccao.javet.values.reference.V8ValueObject.forEach(V8ValueObject.java:310)
at com.caoccao.javet.values.reference.IV8ValueObject.forEach(IV8ValueObject.java:302)
at com.caoccao.javet.interop.converters.JavetObjectConverter.toObject(JavetObjectConverter.java:297)
at com.caoccao.javet.interop.converters.JavetObjectConverter.lambda$toObject$4(JavetObjectConverter.java:306)
at com.caoccao.javet.values.reference.V8ValueObject.forEach(V8ValueObject.java:310)
at com.caoccao.javet.values.reference.IV8ValueObject.forEach(IV8ValueObject.java:302)
at com.caoccao.javet.interop.converters.JavetObjectConverter.toObject(JavetObjectConverter.java:297)
at com.caoccao.javet.interop.converters.JavetObjectConverter.lambda$toObject$0(JavetObjectConverter.java:210)
at com.caoccao.javet.values.reference.V8ValueArray.forEach(V8ValueArray.java:88)
at com.caoccao.javet.values.reference.V8ValueArray.forEach(V8ValueArray.java:68)
at com.caoccao.javet.interop.converters.JavetObjectConverter.toObject(JavetObjectConverter.java:210)
at com.caoccao.javet.interop.converters.JavetObjectConverter.lambda$toObject$4(JavetObjectConverter.java:306)
at com.caoccao.javet.values.reference.V8ValueObject.forEach(V8ValueObject.java:310)
at com.caoccao.javet.values.reference.IV8ValueObject.forEach(IV8ValueObject.java:302)
at com.caoccao.javet.interop.converters.JavetObjectConverter.toObject(JavetObjectConverter.java:297)
at com.caoccao.javet.interop.converters.BaseJavetConverter.toObject(BaseJavetConverter.java:66)
at com.caoccao.javet.interop.V8Runtime.toObject(V8Runtime.java:3666)
at com.caoccao.javet.interop.IV8Convertible.toObject(IV8Convertible.java:58)
at com.caoccao.javet.values.reference.IV8ValueObject.invokeObject(IV8ValueObject.java:1142)
WorkAround
Just not using builder pattern or using it only in nodejs world resolve for this kind of case.
foo.invokeVoid("ref", null)
foo.invokeVoid("unref", null)
or
it.getExecutor("foo.ref().unref().ref().unref()").executeVoid()