mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-10 20:42:12 +00:00
craft-web-host: Fn listeners, so a nested event reaches the queue
wasm-bindgen throws "closure invoked recursively" when an FnMut closure is called while it runs, before its body can queue the message. The listeners only read their captures, so they are Fn; the handler's state stays behind the Inbox's RefCell.
This commit is contained in:
1 parent
ae1fa48449
commit
5fcc392302
1 file changed
+6
-3
@@ -92,14 +92,17 @@ impl Host {
|
||||
}
|
||||
}
|
||||
|
||||
/// Hear the host's messages for this app. The listener lives as long as the page.
|
||||
/// Hear the host's messages for this app. The listener lives as long as the page. The
|
||||
/// listeners are `Fn`: a page host can dispatch an event while one is still running (a
|
||||
/// `saved` for the `save` the handler just posted), and wasm-bindgen refuses to re-enter an
|
||||
/// `FnMut` closure before its body runs, so the message would never reach the queue.
|
||||
pub fn listen(&self, handler: impl FnMut(Message) + 'static) {
|
||||
let app = self.app;
|
||||
let inbox = Rc::new(Inbox::new(handler));
|
||||
match &self.transport {
|
||||
Transport::Parent { window, parent, origin } => {
|
||||
let (parent, origin, inbox) = (parent.clone(), origin.clone(), inbox.clone());
|
||||
let on_message = Closure::<dyn FnMut(web_sys::MessageEvent)>::new(move |event: web_sys::MessageEvent| {
|
||||
let on_message = Closure::<dyn Fn(web_sys::MessageEvent)>::new(move |event: web_sys::MessageEvent| {
|
||||
if event.origin() != origin || !event.source().is_some_and(|s| js_sys::Object::is(&s, &parent)) {
|
||||
return;
|
||||
}
|
||||
@@ -116,7 +119,7 @@ impl Host {
|
||||
Transport::Page { canvas } => {
|
||||
for kind in Incoming::ALL {
|
||||
let inbox = inbox.clone();
|
||||
let on_event = Closure::<dyn FnMut(web_sys::CustomEvent)>::new(move |event: web_sys::CustomEvent| {
|
||||
let on_event = Closure::<dyn Fn(web_sys::CustomEvent)>::new(move |event: web_sys::CustomEvent| {
|
||||
if let Some(message) = read(kind, &event.detail()) {
|
||||
inbox.deliver(message);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user