1use wasm_bindgen::JsValue;
4use wasm_bindgen_futures::JsFuture;
5
6pub async fn settled(promise: js_sys::Promise) -> std::io::Result<JsValue> {
11 JsFuture::from(promise).await.map_err(faulted)
12}
13
14#[expect(clippy::needless_pass_by_value)]
24pub fn faulted(why: JsValue) -> std::io::Error {
25 let named = read(&why, "name").unwrap_or_default();
26 let said = read(&why, "message").unwrap_or_else(|| format!("{why:?}"));
27 let told = if named.is_empty() {
28 said
29 } else {
30 format!("{named}: {said}")
31 };
32 match named.as_str() {
33 "NotFoundError" => std::io::Error::new(std::io::ErrorKind::NotFound, told),
34 "TypeMismatchError" | "InvalidModificationError" => {
35 std::io::Error::new(std::io::ErrorKind::InvalidInput, told)
36 }
37 "NoModificationAllowedError" | "NotAllowedError" | "SecurityError" => {
38 std::io::Error::new(std::io::ErrorKind::PermissionDenied, told)
39 }
40 _ => std::io::Error::other(told),
41 }
42}
43
44fn read(value: &JsValue, field: &str) -> Option<String> {
45 js_sys::Reflect::get(value, &JsValue::from_str(field))
46 .ok()
47 .and_then(|read| read.as_string())
48}
49
50pub fn mistaken(asked: &'static str) -> impl FnOnce(JsValue) -> std::io::Error {
53 move |was| {
54 std::io::Error::new(
55 std::io::ErrorKind::InvalidData,
56 format!("origin-private storage answered {was:?} where {asked} was asked for"),
57 )
58 }
59}