1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use js_ffi::*;
extern crate alloc;
use alloc::sync::Arc;
use spin::Mutex;
pub struct JSNoDrop(pub JSValue);
impl ToJSValue for JSNoDrop {
#[inline]
fn to_js_value(&self) -> JSValue {
self.0
}
#[inline]
fn to_js_type(&self) -> JSType {
TYPE_OBJECT
}
}
pub trait CustomElement {
fn new(element: JSObject) -> Self
where
Self: core::marker::Sized + core::marker::Sync + core::marker::Send + 'static;
fn register(name: &str)
where
Self: core::marker::Sized + core::marker::Sync + core::marker::Send + 'static,
{
let construct = create_callback_1(|element| {
let el = Arc::new(Mutex::new(Self::new(JSObject(element))));
let el1 = el.clone();
let el2 = el.clone();
let el3 = el.clone();
let connect = create_callback_0(move ||{
el1.lock().connected();
});
let disconnect = create_callback_0(move ||{
el2.lock().disconnected();
});
let attribute_change = create_callback_3(move |name,old,new|{
el3.lock().attribute_changed(name,old,new);
});
js!((e,a,b,c)=>{
e.addHooks(a,b,c);
}).invoke_4(JSNoDrop(element),connect,disconnect,attribute_change);
});
js!(
(construct,elementName)=>{
class GeneratedCustomElement extends HTMLElement {
constructor() {
super();
construct(this);
}
connectedCallback() {
self.connect();
}
disconnectedCallback() {
self.disconnect();
}
attributeChangedCallback(attributeName, oldValue, newValue) {
self.attributeChange(attributeName,oldValue,newValue)
}
addHooks(connect,disconnect,attributeChange){
self.connect = connect;
self.disconnect = disconnect;
self.attributeChange = attributeChange;
}
}
customElements.define(elementName, GeneratedCustomElement);
}
)
.invoke_2(construct, name);
}
fn created(&mut self) {}
fn connected(&mut self) {}
fn disconnected(&mut self) {}
fn attribute_changed(&mut self, _name: JSValue, _old_value: JSValue, _new_value: JSValue) {}
}