A page host can report a new dirty state while post_dirty's event is still
dispatching. Remember the state first so that later report wins, and restore
the previous state only when the send fails and nothing else recorded one.
Co-authored-by: Cursor <cursoragent@cursor.com>
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.
A page host dispatches its events synchronously, so it can answer (a
saved for the save the handler just posted) while the handler is still
running. The nested borrow_mut then panicked. Both transports now hand
messages to an Inbox that queues each one and drains the queue one call
at a time, in order; nothing is dropped. The new test fails with the old
borrow ("already borrowed").
FileData::size() reads a Blob's length from the Blob; a host's size
field is no longer trusted for an app's size check. lib.rs gets the
crate-level deny of unwrap, expect, panic and the like.
The messages between a Craft app's web build and the page that hosts it
(ready, host, open, save, saved, dirty, failed, handoff, handoff-done),
as proposed on #358. The contract part (message kinds, the version, the
?host=parent / data-host="page" switch, file-name clean-up) builds
everywhere and is tested natively; the web module (wasm32) is the bridge
an app's web shell calls: same-origin parent only, files as bytes or a
Blob without copying, saves as a transferred ArrayBuffer, dirty repeats
suppressed. Compatible with the bridges shipped before it: optional
fields stay optional, and a host treats an unknown ready.version as 1.