mirror of
https://github.com/zaphar/wasm-web-components.git
synced 2025-07-23 19:59:48 -04:00
Store an instance of the Rust type in the Element Class
This commit is contained in:
parent
3d2a1a285e
commit
793a949053
42
src/lib.rs
42
src/lib.rs
@ -1,19 +1,30 @@
|
||||
use js_sys::Function;
|
||||
use wasm_bindgen::JsValue;
|
||||
use wasm_bindgen::{convert::IntoWasmAbi, prelude::*, JsCast, JsValue};
|
||||
use web_sys::window;
|
||||
|
||||
type Result<T> = std::result::Result<T, JsValue>;
|
||||
|
||||
pub trait CustomElementImpl {
|
||||
pub trait CustomElementImpl: IntoWasmAbi {
|
||||
fn class_name() -> &'static str;
|
||||
fn element_name() -> &'static str;
|
||||
|
||||
fn construct() -> Self;
|
||||
}
|
||||
|
||||
pub fn define_web_component<T: CustomElementImpl>() -> Result<JsValue> {
|
||||
pub struct WebComponentHandle<T: CustomElementImpl + 'static> {
|
||||
pub impl_handle: Closure<dyn FnMut() -> T>,
|
||||
pub element_constructor: Function,
|
||||
}
|
||||
|
||||
pub fn define_web_component<T>() -> Result<WebComponentHandle<T>>
|
||||
where
|
||||
T: CustomElementImpl + 'static,
|
||||
{
|
||||
let body = format!(
|
||||
"class {name} extends HTMLElement {{
|
||||
constructor() {{
|
||||
super();
|
||||
//this.impl = impl();
|
||||
}}
|
||||
}}
|
||||
customElements.define(\"{element_name}\", {name});
|
||||
@ -22,17 +33,30 @@ return element;",
|
||||
name = T::class_name(),
|
||||
element_name = T::element_name(),
|
||||
);
|
||||
let fun = Function::new_no_args(&body);
|
||||
Ok(fun.call0(&window().unwrap())?)
|
||||
let fun = Function::new_with_args("impl", &body);
|
||||
let f: Box<dyn FnMut() -> T> = Box::new(|| T::construct());
|
||||
// TODO(jwall): Check the lifetimes on this guy.
|
||||
let constructor_handle = Closure::wrap(f);
|
||||
let element = fun
|
||||
.call1(
|
||||
&window().unwrap(),
|
||||
constructor_handle.as_ref().unchecked_ref::<Function>(),
|
||||
)?
|
||||
.dyn_into()?;
|
||||
Ok(WebComponentHandle {
|
||||
element_constructor: element,
|
||||
impl_handle: constructor_handle,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use wasm_bindgen::{prelude::*, JsCast};
|
||||
use wasm_bindgen::JsCast;
|
||||
use wasm_bindgen_test::wasm_bindgen_test;
|
||||
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct MyElementImpl();
|
||||
|
||||
impl CustomElementImpl for MyElementImpl {
|
||||
@ -43,6 +67,10 @@ mod tests {
|
||||
fn element_name() -> &'static str {
|
||||
"my-element"
|
||||
}
|
||||
|
||||
fn construct() -> Self {
|
||||
Self()
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
@ -56,7 +84,7 @@ mod tests {
|
||||
#[wasm_bindgen_test]
|
||||
fn test_component_definition() {
|
||||
let obj = define_web_component::<MyElementImpl>().expect("Failed to define web component");
|
||||
let fun = obj.dyn_ref::<Function>().unwrap();
|
||||
let fun = obj.element_constructor.dyn_ref::<Function>().unwrap();
|
||||
assert_eq!(fun.name(), MyElementImpl::class_name());
|
||||
|
||||
let element = window()
|
||||
|
Loading…
x
Reference in New Issue
Block a user