mirror of
https://github.com/zaphar/wasm-web-components.git
synced 2025-07-21 19:40:30 -04:00
Allow specifying the window to create elements in
This commit is contained in:
parent
ff6e9a5079
commit
7ffcab1416
@ -126,12 +126,10 @@ fn expand_struct_trait_shim(struct_name: &Ident, observed_attrs: Literal) -> syn
|
||||
|
||||
connectedCallback() {{
|
||||
this._impl.connected_impl(this);
|
||||
console.log(this.textContent);
|
||||
}}
|
||||
|
||||
disconnectedCallback() {{
|
||||
this._impl.disconnected_impl(this);
|
||||
console.log(this.textContent);
|
||||
}}
|
||||
|
||||
static get observedAttributes() {{
|
||||
@ -139,7 +137,6 @@ fn expand_struct_trait_shim(struct_name: &Ident, observed_attrs: Literal) -> syn
|
||||
}}
|
||||
|
||||
adoptedCallback() {{
|
||||
console.log('In adoptedCallback');
|
||||
this._impl.adopted_impl(this);
|
||||
}}
|
||||
|
||||
@ -185,16 +182,6 @@ fn expand_wasm_shim(struct_name: &Ident) -> syn::ItemImpl {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
#[wasm_bindgen::prelude::wasm_bindgen]
|
||||
pub fn create() -> web_sys::Element {
|
||||
window()
|
||||
.unwrap()
|
||||
.document()
|
||||
.unwrap()
|
||||
.create_element(Self::element_name())
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[wasm_bindgen::prelude::wasm_bindgen]
|
||||
pub fn connected_impl(&self, element: &web_sys::HtmlElement) {
|
||||
use #trait_path;
|
||||
|
@ -42,4 +42,5 @@ features = [
|
||||
"ShadowRootInit",
|
||||
"ShadowRootMode",
|
||||
"Window",
|
||||
"console"
|
||||
]
|
@ -1,6 +1,6 @@
|
||||
use js_sys::Function;
|
||||
use wasm_bindgen::{convert::IntoWasmAbi, prelude::Closure, JsValue};
|
||||
use web_sys::{window, Element, HtmlElement};
|
||||
use web_sys::{window, Element, Event, HtmlElement, Window};
|
||||
|
||||
/// This attribute proc-macro will generate the following trait implementations
|
||||
/// * [WebComponentDef](trait@WebComponentDef)
|
||||
@ -27,8 +27,11 @@ pub trait WebComponentDef: IntoWasmAbi + Default {
|
||||
}
|
||||
|
||||
fn create() -> Element {
|
||||
window()
|
||||
.unwrap()
|
||||
Self::create_in_window(window().unwrap())
|
||||
}
|
||||
|
||||
fn create_in_window(window: Window) -> Element {
|
||||
window
|
||||
.document()
|
||||
.unwrap()
|
||||
.create_element(Self::element_name())
|
||||
@ -88,7 +91,7 @@ mod tests {
|
||||
use wasm_bindgen::{JsCast, JsValue};
|
||||
use wasm_bindgen_test::wasm_bindgen_test;
|
||||
use web_sys::Text;
|
||||
use web_sys::{window, HtmlElement};
|
||||
use web_sys::{console, window, HtmlElement};
|
||||
|
||||
use wasm_web_component_macros::web_component;
|
||||
|
||||
@ -102,6 +105,76 @@ mod tests {
|
||||
pub fn log_with_val(message: String, val: &JsValue);
|
||||
}
|
||||
|
||||
pub struct Timer<'a> {
|
||||
name: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> Timer<'a> {
|
||||
pub fn new(name: &'a str) -> Timer<'a> {
|
||||
console::time_with_label(name);
|
||||
Timer { name }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for Timer<'a> {
|
||||
fn drop(&mut self) {
|
||||
console::time_end_with_label(self.name);
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
pub fn bench_mark_elements() {
|
||||
#[web_component(observed_attrs = "['class']")]
|
||||
pub struct BenchElement {}
|
||||
|
||||
impl WebComponentBinding for BenchElement {
|
||||
fn connected(&self, element: &HtmlElement) {
|
||||
let node = Text::new().unwrap();
|
||||
node.set_text_content(Some("Added a text node on connect".into()));
|
||||
element.append_child(&node).unwrap();
|
||||
}
|
||||
|
||||
fn disconnected(&self, element: &HtmlElement) {
|
||||
let node = element.first_child().unwrap();
|
||||
element.remove_child(&node).unwrap();
|
||||
}
|
||||
|
||||
fn adopted(&self, element: &HtmlElement) {
|
||||
let node = Text::new().unwrap();
|
||||
node.set_text_content(Some("Added a text node on adopt".into()));
|
||||
element.append_child(&node).unwrap();
|
||||
}
|
||||
|
||||
fn attribute_changed(
|
||||
&self,
|
||||
element: &HtmlElement,
|
||||
name: JsValue,
|
||||
old_value: JsValue,
|
||||
new_value: JsValue,
|
||||
) {
|
||||
let node = element.first_child().unwrap();
|
||||
node.set_text_content(Some(&format!(
|
||||
"Setting {} from {} to {}",
|
||||
name.as_string().unwrap_or("None".to_owned()),
|
||||
old_value.as_string().unwrap_or("None".to_owned()),
|
||||
new_value.as_string().unwrap_or("None".to_owned()),
|
||||
)));
|
||||
element.append_child(&node).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
Timer::new("custom-element::timing");
|
||||
let handle = BenchElement::define();
|
||||
|
||||
let body = window().unwrap().document().unwrap().body().unwrap();
|
||||
for _ in 1..100000 {
|
||||
let el = BenchElement::create();
|
||||
body.append_child(&el).unwrap();
|
||||
el.set_attribute("class", "foo").unwrap();
|
||||
body.remove_child(&el).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(jwall): We can only construct the web component once and since the lifetime of the component internals is tied
|
||||
// to the handle we run this all in one single function.
|
||||
#[wasm_bindgen_test]
|
||||
@ -115,28 +188,20 @@ mod tests {
|
||||
|
||||
impl WebComponentBinding for MyElementImpl {
|
||||
fn connected(&self, element: &HtmlElement) {
|
||||
log("Firing connected call back".to_owned());
|
||||
let node = Text::new().unwrap();
|
||||
node.set_text_content(Some("Added a text node on connect".into()));
|
||||
element.append_child(&node).unwrap();
|
||||
log(format!(
|
||||
"element contents: {}",
|
||||
&element.text_content().unwrap()
|
||||
));
|
||||
}
|
||||
|
||||
fn disconnected(&self, element: &HtmlElement) {
|
||||
log("Firing discconnected call back".to_owned());
|
||||
let node = element.first_child().unwrap();
|
||||
element.remove_child(&node).unwrap();
|
||||
}
|
||||
|
||||
fn adopted(&self, element: &HtmlElement) {
|
||||
log("Firing adopted call back".to_owned());
|
||||
let node = Text::new().unwrap();
|
||||
node.set_text_content(Some("Added a text node on adopt".into()));
|
||||
element.append_child(&node).unwrap();
|
||||
log_with_val("element: ".to_owned(), element);
|
||||
}
|
||||
|
||||
fn attribute_changed(
|
||||
@ -146,7 +211,6 @@ mod tests {
|
||||
old_value: JsValue,
|
||||
new_value: JsValue,
|
||||
) {
|
||||
log("Firing attribute changed callback".to_owned());
|
||||
let node = element.first_child().unwrap();
|
||||
node.set_text_content(Some(&format!(
|
||||
"Setting {} from {} to {}",
|
||||
@ -155,7 +219,6 @@ mod tests {
|
||||
new_value.as_string().unwrap_or("None".to_owned()),
|
||||
)));
|
||||
element.append_child(&node).unwrap();
|
||||
log_with_val("element: ".to_owned(), element);
|
||||
}
|
||||
}
|
||||
let obj = MyElementImpl::define().expect("Failed to define web component");
|
||||
@ -187,15 +250,18 @@ mod tests {
|
||||
"Setting class from None to foo"
|
||||
);
|
||||
|
||||
// Test the adopted callback
|
||||
// First we need a new window with a new document to perform the adoption with.
|
||||
let new_window = window().unwrap().open().unwrap().unwrap();
|
||||
// NOTE(jwall): If we are running headless then this can fail sometimes.
|
||||
// We don't fail the test when that happens.
|
||||
if let Ok(Some(new_window)) = window().unwrap().open() {
|
||||
// Test the adopted callback
|
||||
// First we need a new window with a new document to perform the adoption with.
|
||||
new_window.document().unwrap().adopt_node(&element).unwrap();
|
||||
assert_eq!(
|
||||
element.text_content().unwrap(),
|
||||
"Added a text node on adopt"
|
||||
);
|
||||
}
|
||||
// Then we can have the new document adopt this node.
|
||||
new_window.document().unwrap().adopt_node(&element).unwrap();
|
||||
assert_eq!(
|
||||
element.text_content().unwrap(),
|
||||
"Added a text node on adopt"
|
||||
);
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
|
Loading…
x
Reference in New Issue
Block a user