Closed BjoernAkAManf closed 2 years ago
Note: Proper introspection also requires the type information. That is currently lost through the conversion to string.
I'm currently trying to implement an alternative that would implement accessing that properly.
I need to add additional tests for the other types that could be imported, otherwise i think this works great.
One thing i noticed, that some Errors are not handled by the generated Wrapper in a way, that does not just throw a meaningless "Method not found". Is there any way i can handle that gracefully without manually handeling errors?
For example:
fn imports(env: &JNIEnv, this: JObject) -> std::result::Result<jobjectArray, Self::Error> {
println!("X");
let r = imports_impl(env, this);
return match r {
Ok(a) => {
println!("YYY: {a:?}");
Ok(a)
}
Err(b) => {
let x = env.throw(b);
println!("YYYYY #{x:?}");
Err(Error::NotImplemented)
}
};
}
Will cause a dump, due to an uncaught exception. Passing in more information would make debugging Tests easier without necessarily configuring a Rust Debugger / Print Debugging.
Otherwise the Global Implementation is almost done.
Is there any way i can handle that gracefully without manually handeling errors?
Hmm, I don't get what's the problem here. Can you explain much detail, or apparently it's no longer a problem?
Looking the latest implementation, GlobalType
looks good indeed. So for the remaining Memory memory()
and Table table()
methods of ImportType
, you can choice either to implement MemoryType
and TableType
to fix the method signature, or delete them for now.
The problem seems to be, that some Java Errors are not handled properly. One such issue was specifying the Java Constructor Signature correctly once. I was able to catch that with the code above, but not the code that was generated.
This is a somewhat minor issue, but can be quite annoying. Might also be me being bad at debugging Rust <-> Java Code though.
The only thing i will leave unimplemented will be Instance and Module, the module linking proposal will be more problematic to implement as is. In particular, as far as i understand it, we would have to create Disposable Objects for Instance or Modules and manage them both in Java and Rust. However i might be wrong there, yet to read about that proposal in more detail.
So the error caused by mismatching method (constructor) signature is a "no such method" exception and it is handled here, then set to be thrown again as-is: https://github.com/kawamuray/wasmtime-java/blob/master/wasmtime-jni/src/errors.rs#L45
So it is handled in the generated code, but I guess your point is that at java code level it is difficult to know where of the Rust code caused that exception? Then it makes sense.
One possible improvement is to embed backtrace information when such exception is generated, but that's not easy with the current impl as in jni::errors::Error
automatically gets converted into a Error::Jni
by ?
operator. Hopefully, such error occurs only when we make a mistake while implementing Rust glue code and can catch it at testing so that we can embed arbitrary debug code to figure out why.
This is required to load arbitrary WASM, where the order of imports may not be known beforehand. Also helpful to understand potential blast radius of a module in case it has been compromised.
I feel like the current design is not great, given that you cannot try catch with an array and need to manually dispose of the ImportType. Also the need to export a custom struct does not feel good. However as a novice in regards to rust, i felt like this was the most accessible way.