In the JavaScript console, I can execute the following to create an <input>
element and demonstrate that it has a click
method.
let input = document.createElement("input");
input.type = "file";
console.log(input.click);
// ƒ click() { [native code] }
If I attempted to do the following in Rust compiled to wasm
, I get an error:
let document: Document = Document::new().unwrap();
let input: Element = document.create_element("input").unwrap();
input.set_attribute("type", "file").unwrap();
# For debugging purposes, save a reference to a global variable so I can inspect it from the JavaScript console
let input_jsval : JsValue = input.clone().into();
js_sys::Reflect::set(&js_sys::global(), &JsValue::from_str("debug_input"), &input_jsval).unwrap();
# Attempt to click it
let input_html_element: HtmlElement = input_jsval.clone().into();
input_html_element.click();
When I run the wasm
tests it produces:
failures:
---- wasm_tests::tests::input_test output ----
log output:
error output:
wasm-bindgen: imported JS function that was not marked as `catch` threw an error: getObject(...).click is not a function
Stack:
TypeError: getObject(...).click is not a function
at http://127.0.0.1:8000/wasm-bindgen-test:589:25
If I check the JavaScript console, I can see that there is no click
method on the reference that I saved.
debug_input.click
// undefined
So why is it that when I create an <input>
via JavaScript it gets a click
method but if I do essentially the same thing via wasm
it does not? I suspect the conversion from Element
to HtmlElement
via JsValue
is lossy? Is there a more direct conversion?
Q1: Is there a more direct conversion for
Element
intoHtmlElement
?A1: Yes, if you know it really is an
HtmlElement
then you canlet input_html_element: HtmlElement = input.dyn_into().unwrap();
. However, this will fail if the input isn't really anHtmlElement
and this case, it's not.Q2: Why wouldn't it be an
HtmlElement
?A2: The MDN says that
Document::createElement
will return "[a] newHTMLElement
... if the document is anHTMLDocument
, which is the most common case. Otherwise a newElement
is returned. TheDocument::new()
API doesn't get a reference to the current window'sdocument
, rather it creates a new (non-HTML) document. Instead, use: