DioxusLabs / DioxusLabs/dioxus
EventData direct deserialization silently matches the wrong variant
- Dominant language
- Rust
- Stars
- 39.1k
- Forks
- 1.9k
- Avg merge
- 4d 10h
- Merged PRs (30d)
- 4
Description
**Problem**
`EventData` (in `packages/html/src/transit.rs`) is `#[serde(untagged)]` and its first variant `Cancel(SerializedCancelData)` wraps `pub struct SerializedCancelData {}`. The empty struct matches any JSON object, so `serde_json::from_str::` returns `Cancel` for every payload regardless of shape, silently dropping the data.
The happy path doesn't hit this — `HtmlEvent::Deserialize` is hand-written and dispatches by `name` via `deserialize_raw_event`. But `EventData` is `pub` with derived `Deserialize`, so any external use (tooling, log replay, embedding `EventData` in another struct) hits it.
Removing the empty `Cancel` doesn't fix the shape: most other variants are `#[serde(default)]` on every field with no `deny_unknown_fields`, so the wrong-winner just shifts to whichever variant sits first.
**Steps To Reproduce**
```rust
#[test]
fn repro() {
let mouse = r#"{"client_x": 10, "client_y": 20, "button": 0}"#;
let data: dioxus_html::EventData = serde_json::from_str(mouse).unwrap();
assert!(matches!(data, dioxus_html::EventData::Mouse(_)), "got {data:?}");
}
```
`cargo test -p dioxus-html --features serialize repro` → `expected EventData::Mouse, got Cancel(SerializedCancelData)`.
**Expected behavior**
Either:
1. Internally-tagged repr carrying the event name as a discriminator, or
2. `EventData::Deserialize` becomes `pub(crate)` — `HtmlEvent::Deserialize` is the only correct entry point.
**Environment:**
- Dioxus version: `main` and earlier
- Rust version: any
- OS info: any
- App platform: any consumer of `dioxus_html::EventData` via serde
**Questionnaire**
I'm interested in fixing this myself but would like guidance on direction before opening a PR.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.