Skip to content

[web] Wrap browser-API unwraps in Result helpers #128

@intendednull

Description

@intendednull

Parent: #108

Problem

crates/web/src/ has ~46 .unwrap() calls on browser APIs. Any browser failure (sandboxed iframe, denied permissions, blocked AudioContext, broken FileReader) panics the entire WASM module.

Hotspots:

  • crates/web/src/voice.rs:149, 155, 366, 505, 524 — VoiceManager critical paths
  • crates/web/src/components/file_share.rs:47, 56, 60-61 — file upload / FileReader / ArrayBuffer
  • crates/web/src/components/member_list.rs:24-25 — context access
  • crates/web/src/components/sidebar.rs:46-47 — context access

Fix

  1. Create a small web_helpers module (or util.rs) with Result-returning getters for the common browser APIs:

    pub fn window() -> Result<web_sys::Window, WebError> {
        web_sys::window().ok_or(WebError::NoWindow)
    }
    
    pub fn document() -> Result<web_sys::Document, WebError> {
        window()?.document().ok_or(WebError::NoDocument)
    }
    
    pub fn media_devices() -> Result<web_sys::MediaDevices, WebError> {
        window()?
            .navigator()
            .media_devices()
            .map_err(|_| WebError::NoMediaDevices)
    }
  2. Replace each .unwrap() on those APIs with ? propagation.

  3. For file upload errors, surface a user-visible toast notification instead of panicking.

  4. For context access (member_list.rs, sidebar.rs), the context should always be provided by the parent App — if it's missing, that's a bug, but it should at least render an error state rather than crashing the whole app.

Scope control

This is a medium-size refactor. Scope it to the voice and file_share modules in the first PR (the highest-impact sites). Component context access can be a follow-up.

Test

Browser tests in crates/web/tests/browser.rs:

  1. Mount CallPage in a context where getUserMedia fails (mock or simulate rejection). Assert the app does not panic and shows an error state.
  2. Mount FileShare with an oversized/corrupt file. Assert the app does not panic and shows an error toast.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions