Initial javascript shim working

This commit is contained in:
Jeremy Wall 2022-10-02 18:16:10 -04:00
commit 3d2a1a285e
3 changed files with 114 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
/Cargo.lock

39
Cargo.toml Normal file
View File

@ -0,0 +1,39 @@
[package]
name = "web-component-rs"
version = "0.1.0"
edition = "2021"
author = "Jeremy Wall <jeremy@marzhillstudios.com>"
[lib]
crate-type = ["cdylib", "rlib"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies.wasm-bindgen-test]
version = "0.3"
[dependencies.wasm-bindgen]
version = "= 0.2.81"
[dependencies.js-sys]
version = "0.3"
[dependencies.web-sys]
version = "0.3"
features = [
"CustomElementRegistry",
"Document",
#"DocumentFragment",
"KeyboardEvent",
"Event",
"EventTarget",
"Element",
"HtmlBaseElement",
"HtmlElement",
"HtmlTemplateElement",
"HtmlSlotElement",
"Node",
"ShadowRoot",
"ShadowRootInit",
"ShadowRootMode",
"Window",
]

73
src/lib.rs Normal file
View File

@ -0,0 +1,73 @@
use js_sys::Function;
use wasm_bindgen::JsValue;
use web_sys::window;
type Result<T> = std::result::Result<T, JsValue>;
pub trait CustomElementImpl {
fn class_name() -> &'static str;
fn element_name() -> &'static str;
}
pub fn define_web_component<T: CustomElementImpl>() -> Result<JsValue> {
let body = format!(
"class {name} extends HTMLElement {{
constructor() {{
super();
}}
}}
customElements.define(\"{element_name}\", {name});
var element = customElements.get(\"{element_name}\");
return element;",
name = T::class_name(),
element_name = T::element_name(),
);
let fun = Function::new_no_args(&body);
Ok(fun.call0(&window().unwrap())?)
}
#[cfg(test)]
mod tests {
use super::*;
use wasm_bindgen::{prelude::*, JsCast};
use wasm_bindgen_test::wasm_bindgen_test;
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
pub struct MyElementImpl();
impl CustomElementImpl for MyElementImpl {
fn class_name() -> &'static str {
"MyElement"
}
fn element_name() -> &'static str {
"my-element"
}
}
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console, js_name = log)]
pub fn log(message: String);
#[wasm_bindgen(js_namespace = console, js_name = log)]
pub fn log_with_val(message: String, val: &JsValue);
}
#[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();
assert_eq!(fun.name(), MyElementImpl::class_name());
let element = window()
.unwrap()
.document()
.unwrap()
.create_element(MyElementImpl::element_name())
.unwrap();
assert_eq!(
element.tag_name().to_uppercase(),
MyElementImpl::element_name().to_uppercase()
);
}
}