use alloc::string::String; use js_sys::{JsString, Object}; use wasm_bindgen::{prelude::*, JsCast, JsValue}; #[derive(Clone)] enum GlobalType { Window(web_sys::Window), Worker(web_sys::WorkerGlobalScope), } /// Returns a handle to the global scope object. /// /// Simplified version of https://github.com/rustwasm/wasm-bindgen/blob/main/crates/js-sys/src/lib.rs, /// which we can't use directly because it discards information about how it /// retrieved the global. fn global() -> GlobalType { #[wasm_bindgen] extern "C" { type Global; #[wasm_bindgen(getter, catch, static_method_of = Global, js_class = window, js_name = window)] fn get_window() -> Result; #[wasm_bindgen(getter, catch, static_method_of = Global, js_class = self, js_name = self)] fn get_self() -> Result; } if let Ok(window) = Global::get_window() { GlobalType::Window( window .dyn_into::() .expect("expected window to be an instance of Window"), ) } else if let Ok(worker) = Global::get_self() { GlobalType::Worker( worker .dyn_into::() .expect("expected self to be an instance of WorkerGlobalScope"), ) } else { panic!("Unable to find global in this environment") } } pub(crate) fn get() -> impl Iterator { let languages = match global() { GlobalType::Window(window) => window.navigator().languages(), GlobalType::Worker(worker) => worker.navigator().languages(), }; languages .values() .into_iter() .flat_map(|v| v.and_then(|v| v.dyn_into::())) .map(String::from) }