I debugged a weird error message (TypeError: getObject(...) is undefined) for a while...

...until I realized that the signature of the get_caret_position function requires an &Element argument and that I didn't pass in any arguments.
When debug-printing the element argument, it shows Element { obj: JsValue(undefined) }.
Is there a clean way to handle the case of JS code not passing in sufficient arguments? Could wasm-bindgen generate a better error message for this case?
And as an intermediate solution, is there a way to check if an &Element value is backed by an undefined JsValue?
This seems reasonable to me! We don't provide a ton of guard rails in debug mode, but we do provide some. I think the best way to handle this would be to generate more type guard glue whenever --debug is passed to the CLI, sort of like we do for strings today.
I would like to take this as my first contribution. Where is a good place to start looking at this?
@pfernandom awesome! All the invocations which go from JS to Rust are located in a js2rust.rs file. That file has a number of "guard rails" already like so which are gated to only get emitted in debug mode.
As I look more into this though... this may be a bit more involved than I originally thought. The problem here is that the wasm-bindgen-facing-type for Element is JsValue, which can assume any arbitrary value. What we really want though is for Element to have type NonNullObject or something like that which would allow us to add guard rails that the object we get isn't null, undefined, or something that isn't an instance of Object in JS.
That does mean that this is actually significantly more complicated than I originally thought, but if you're still interested I can try to help guide through an implementation!
I'm more than happy to take this bug, but If you think that this is too complicated and might require too much hand-holding, I can find another issue to work on.
Maybe I can time box it and see if I can do some significant advance, and if I do, I can take it.
Ok sure! In any case I'll try to write some more details about how this would be handled.
Currently one aspect of wasm-bindgen is that it communicates the actual types of all arguments of exports/imports to the CLI tool. It does this via a pretty roundabound method, but the general idea is that:
WasmDescribe trait. This trait has one method that simply calls inform a number of times in succession. That basically produces a Vec<u32> which we then decode in the CLI later on.ANYREF. That represents "any JS value", and so we'll want to add another, JSOBJECT, which represents "any non-null JS object".WasmDescribe implementation for imported types to manually use JSOBJECT instead of delegating to JsValue.src/describe.rs as well as the enum Descriptor needs a new variant for JsObject.is_anyref method which is largely used to case on anyref, and then in a few locations, if necessary, you'd add an is_jsobject() check and emit necessary debug glue guards.And in theory that's most of it!
Most helpful comment
Ok sure! In any case I'll try to write some more details about how this would be handled.
Currently one aspect of wasm-bindgen is that it communicates the actual types of all arguments of exports/imports to the CLI tool. It does this via a pretty roundabound method, but the general idea is that:
WasmDescribetrait. This trait has one method that simply callsinforma number of times in succession. That basically produces aVec<u32>which we then decode in the CLI later on.ANYREF. That represents "any JS value", and so we'll want to add another,JSOBJECT, which represents "any non-null JS object".WasmDescribeimplementation for imported types to manually useJSOBJECTinstead of delegating toJsValue.src/describe.rsas well as theenum Descriptorneeds a new variant forJsObject.is_anyrefmethod which is largely used to case on anyref, and then in a few locations, if necessary, you'd add anis_jsobject()check and emit necessary debug glue guards.And in theory that's most of it!