wasm-bindgen
wasm-bindgen copied to clipboard
Runtime name clashes and undefined behaviour
Describe the Bug
If two JS functions bound via the FFI are given the same Rust name across different Rust modules, there will be clashes at runtime leading to errors and other undefined behaviour.
Steps to Reproduce
I am building a Browser Extension in Rust, and currently the Web Extensions API does not yet have first-class bindings in Rust (as web_sys
does). So, I have been writing the bindings myself as needed.
It is common to add listeners for events. These follow the pattern foo.bar.onBaz.addListener(function)
in Javascript. So on the Rust side one can have:
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = ["browser", "runtime", "onMessage"], js_name = "addListener")]
fn add_listener_js(handle: &Closure<dyn Fn(JsValue, JsValue) -> JsValue>);
}
And then write a pub fn add_listener
sugar over top of it that presents nicer types to the user. If there is more than one function named add_listener_js
bound to across my internal Rust modules, there will be errors and/or misdirected events at runtime. For example, in another module:
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = ["browser", "browserAction", "onClicked"], js_name = "addListener")]
fn add_listener_js(handle: &Closure<dyn Fn(JsValue)>);
}
Similar issues occur not just with listeners, but if bound functions have the same name in general.
Unfortunate the current project I'm working on is not open source, or else I'd point you right to it.
Expected Behavior
JS functions bounds to via the FFI should be given unique names. At the very least, a compiler warning should be issued about a name clash.
Actual Behavior
I should be able to name my JS-to-Rust bound functions whatever I want without fear of namespace clashes.
The errors are described as "there will be errors and/or misdirected events at runtime". Have done a small project with integration towards mdc webcomponents, the later is a bonanza of nested namespaces with similar methods names. Haven't actually experienced this behavior, but could maybe try to reproduce.
In more detail what are the errors and in which setup does they occur? When JS events are sent towards Rust compiled wasm, then they hit wrong callback registered with the other add_listener_js
?
Thanks for the report! This is definitely something where the generated code could do better. I unfortunately never got around to making this area of wasm-bindgen more robust, but I think there's nothing technical stopping something like this from being implemented. I'd be happy to review a PR to fix this!
I'd be happy to review a PR to fix this!
Could you point to a code location where such a fix could be explored?
JS code generation happens here -- https://github.com/rustwasm/wasm-bindgen/blob/master/crates/cli-support/src/js/mod.rs -- and this would probably involve some form of abstraction which is a layer between user-provided identifiers and what we actually generate in the source code itself. There's some of that already but it's not widely used throughout the file.
Is there anything new here?
@flosse Since opening this issue originally, I've just been very careful to give FFI functions different names. It's a manual process and obviously not scalable, though.