Skip to content

Carry files and drag data transfers in event payloads - #26

Merged
lannbot merged 1 commit into
mainfrom
feat/file-payloads
Sep 5, 2026
Merged

Carry files and drag data transfers in event payloads#26
lannbot merged 1 commit into
mainfrom
feat/file-payloads

Conversation

@lannbot

@lannbot lannbot commented Sep 5, 2026

Copy link
Copy Markdown
Owner

Closes the last event-payload gap against dioxus-web.

WIT (interface events): form-data.files: list<own<file>>; new payload.drag(drag-data { mouse, transfer: option<own<data-transfer>> }) replacing the mouse-family reuse for drag names; resource file (name/size/last-modified/content-type, read() -> stream<u8>); resource data-transfer mirroring NativeDataTransfer one to one.

Both are resources rather than snapshots because the DOM makes them so: File contents read asynchronously; DataTransfer setters only work live during dragstart, and protected mode hides getData outside dragstart/drop.

Guest: WitFile/WitDataTransfer; handles lifted once at WitEventData construction (dioxus may convert a dispatch more than once); byte_stream via unfold over chunked reads; Send bounds asserted as dioxus-web does.

Host: HostFile (read returns File.stream(), verified end-to-end through the runtime), HostDataTransfer (refused setters → ComponentException), registered under events with DomEvent.

Tests: unit tests for both classes and the payload shapes; platform-probe fixture gains a file input and a drop target — e2e asserts read_string and byte_stream agree on a real File, and that a guest set_data in dragstart is read back on drop. 151 deno tests; full just gate set passes.

Clipboard/media/selection/toggle remain empty: dioxus-html's data types for them have no accessors.

Automerge armed (merge commit).

`form-data` gains `files: list<own<file>>`, and drag events move from the
`mouse` family to `drag-data { mouse, transfer: option<own<data-transfer>> }`.
Both new types are host resources, for reasons the DOM dictates: a File's
contents are only readable asynchronously (so `file.read` returns a
`stream<u8>`, the shape `eval` already uses), and a DataTransfer's setters
mean something only against the live object during `dragstart`, while
protected mode hides `getData` outside `dragstart`/`drop` — a snapshot
would have to fake both. This is what dioxus-web's users already see.

Guest: `WitFile` / `WitDataTransfer` back dioxus-html's `NativeFileData`
and `NativeDataTransfer` one to one. Owned handles are lifted out of the
payload once at `WitEventData` construction, since dioxus may convert the
same dispatch more than once and a handle moves only once. `byte_stream`
is `unfold` over chunked reads, yielding a final chunk that arrives with
`Dropped`; the `Send` bounds are satisfied the way dioxus-web satisfies
them, by assertion on a single-threaded target.

Host: `HostFile` wraps a `File` (metadata as bigint where the WIT says
u64; `read` returns `File.stream()`), `HostDataTransfer` wraps the live
DataTransfer and reports refused setters as `ComponentException`. Both
register under the `events` import beside `DomEvent`; instances nested in
a payload passed to `handle-event` register on the way through, as the
contract says.

The other families that still dispatch as `empty` — clipboard, media,
selection, toggle — carry nothing because dioxus-html's own data types
for them expose no accessors; there is nothing to add.
@lannbot
lannbot enabled auto-merge September 5, 2026 13:37
@lannbot
lannbot merged commit fdc0d52 into main Sep 5, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants