{"record":{"id":"f650d2c359b242c9","repo":"emilk/egui","slug":"should-have-a-window","errorCode":null,"errorMessage":"should have a Window","messagePattern":"should have a Window","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/eframe/src/web/mod.rs","lineNumber":105,"sourceCode":"}\n\n/// Focus the given element without scrolling it into view.\n///\n/// Scrolling the element into view would scroll the whole page when\n/// the app is embedded in a larger scrollable page,\n/// see <https://github.com/emilk/egui/issues/8295>.\npub(crate) fn focus_without_scroll(element: &web_sys::HtmlElement) -> Result<(), JsValue> {\n    let options = web_sys::FocusOptions::new();\n    options.set_prevent_scroll(true);\n    element.focus_with_options(&options)\n}\n\n/// Current time in seconds (since undefined point in time).\n///\n/// Monotonically increasing.\npub fn now_sec() -> f64 {\n    web_sys::window()\n        .expect(\"should have a Window\")\n        .performance()\n        .expect(\"should have a Performance\")\n        .now()\n        / 1000.0\n}\n\n/// The native GUI scale factor, taking into account the browser zoom.\n///\n/// Corresponds to [`window.devicePixelRatio`](https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio) in JavaScript.\npub fn native_pixels_per_point() -> f32 {\n    let pixels_per_point = web_sys::window().unwrap().device_pixel_ratio() as f32;\n    if pixels_per_point > 0.0 && pixels_per_point.is_finite() {\n        pixels_per_point\n    } else {\n        1.0\n    }\n}\n","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/emilk/egui/blob/441971a776322a482e371775219380eca812cfa9/crates/eframe/src/web/mod.rs#L87-L123","documentation":"now_sec in eframe's web module calls web_sys::window(), which returns None when there is no global Window object, and panics with 'should have a Window'. This function is only valid inside a browser (WASM) context where a window exists.","triggerScenarios":"Calling eframe web code (now_sec directly, or indirectly via AppRunner::auto_save_if_needed / save / time tracking) in a non-browser WASM environment such as Node.js, a worker without a window, or running the crate natively.","commonSituations":"Unit tests running on native targets or in Node; WASM code running in a Web Worker that lacks a global window; accidentally compiling eframe's web backend into a server-side WASM binary.","solutions":["Run the code in a browser main thread context where `window` exists.","In workers, construct or access a WindowProxy/DedicatedWorkerGlobalScope instead, or avoid eframe's timing helpers there.","For tests, stub time functions or run tests with wasm-bindgen-test in a browser rather than native test runners."],"exampleFix":"// before\nlet t = eframe::web::now_sec();\n// after\nlet t = web_sys::window().map(|w| w.performance().map(|p| p.now() / 1000.0)).flatten().unwrap_or(0.0);","handlingStrategy":"fallback","validationCode":"let has_window = js_sys::global().dyn_into::<web_sys::Window>().is_ok();\nif !has_window { /* skip now_sec-dependent path */ }","typeGuard":"fn window_available() -> bool { web_sys::window().is_some() }","tryCatchPattern":"// Panic-based; wrap calls in std::panic::catch_unwind(AssertUnwindSafe(|| eframe::web::now_sec())) if recovery is essential, else guard with window().is_some().","preventionTips":["Only call eframe web timing helpers from browser main-thread code.","Use cfg(target_arch = \"wasm32\") guards plus a window check before use.","Run wasm tests via wasm-bindgen-test in a real browser, not native test harnesses."],"tags":["wasm","web","browser-environment","panic"],"backgroundTag":"unsupported-platform","analyzedSha":"441971a776322a482e371775219380eca812cfa9","analyzedAt":"2026-09-12T04:29:21.500Z","contentChangedAt":"2026-09-12T04:29:21.500Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}