Skip to content

Commit

Permalink
refactor direct usage of window for WASM
Browse files Browse the repository at this point in the history
Signed-off-by: onur-ozkan <work@onurozkan.dev>
  • Loading branch information
onur-ozkan committed Aug 30, 2023
1 parent e4b091b commit a601e05
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 8 deletions.
40 changes: 40 additions & 0 deletions mm2src/common/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use serde::Serialize;
use serde_wasm_bindgen::Serializer;
use std::fmt;
use wasm_bindgen::prelude::*;
use web_sys::{Window, WorkerGlobalScope};

/// Get only the first line of the error.
/// Generally, the `JsValue` error contains the stack trace of an error.
Expand Down Expand Up @@ -139,3 +140,42 @@ pub fn serialize_to_js<T: Serialize>(value: &T) -> Result<JsValue, serde_wasm_bi
pub fn deserialize_from_js<T: DeserializeOwned>(value: JsValue) -> Result<T, serde_wasm_bindgen::Error> {
serde_wasm_bindgen::from_value(value)
}

/// Detects the current execution environment (window or worker) and follows the appropriate way
/// of getting `web_sys::IdbFactory` instance.
pub fn get_idb_factory() -> Result<web_sys::IdbFactory, String> {
let global = js_sys::global();

let idb_factory = match (global.dyn_ref::<Window>(), global.dyn_ref::<WorkerGlobalScope>()) {
(Some(window), None) => window.indexed_db(),
(None, Some(worker)) => worker.indexed_db(),
_ => return Err(String::from("Unknown WASM environment.")),
};

match idb_factory {
Ok(Some(db)) => Ok(db),
Ok(None) => Err(if global.dyn_ref::<Window>().is_some() {
"IndexedDB not supported in window context"
} else {
"IndexedDB not supported in worker context"
}
.to_string()),
Err(e) => Err(stringify_js_error(&e)),
}
}

/// This function is a wrapper around the `fetch_with_request`, providing compatibility across
/// different execution environments, such as window and worker.
pub fn compatible_fetch_with_request(js_request: &web_sys::Request) -> Result<js_sys::Promise, String> {
let global = js_sys::global();

if let Some(scope) = global.dyn_ref::<Window>() {
return Ok(scope.fetch_with_request(js_request));
}

if let Some(scope) = global.dyn_ref::<WorkerGlobalScope>() {
return Ok(scope.fetch_with_request(js_request));
}

Err(String::from("Unknown WASM environment."))
}
8 changes: 2 additions & 6 deletions mm2src/mm2_db/src/indexed_db/drivers/builder.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::{construct_event_closure, DbUpgrader, IdbDatabaseImpl, OnUpgradeError, OnUpgradeNeededCb, OPEN_DATABASES};
use common::get_idb_factory;
use common::{log::info, stringify_js_error};
use derive_more::Display;
use futures::channel::mpsc;
Expand Down Expand Up @@ -73,12 +74,7 @@ impl IdbDatabaseBuilder {
let (table_names, on_upgrade_needed_handlers) = Self::tables_into_parts(self.tables)?;
info!("Open '{}' database with tables: {:?}", self.db_name, table_names);

let window = web_sys::window().expect("!window");
let indexed_db = match window.indexed_db() {
Ok(Some(db)) => db,
Ok(None) => return MmError::err(InitDbError::NotSupported("Unknown error".to_owned())),
Err(e) => return MmError::err(InitDbError::NotSupported(stringify_js_error(&e))),
};
let indexed_db = get_idb_factory().map_err(InitDbError::NotSupported)?;

let db_request = match indexed_db.open_with_u32(&self.db_name, self.db_version) {
Ok(r) => r,
Expand Down
4 changes: 2 additions & 2 deletions mm2src/mm2_net/src/wasm_http.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::transport::{SlurpError, SlurpResult};
use common::compatible_fetch_with_request;
use common::executor::spawn_local;
use common::{stringify_js_error, APPLICATION_JSON};
use futures::channel::oneshot;
Expand Down Expand Up @@ -145,7 +146,6 @@ impl FetchRequest {
}

async fn fetch(request: Self) -> FetchResult<JsResponse> {
let window = web_sys::window().expect("!window");
let uri = request.uri;

let mut req_init = RequestInit::new();
Expand All @@ -165,7 +165,7 @@ impl FetchRequest {
.map_to_mm(|e| SlurpError::Internal(stringify_js_error(&e)))?;
}

let request_promise = window.fetch_with_request(&js_request);
let request_promise = compatible_fetch_with_request(&js_request).map_to_mm(SlurpError::Internal)?;

let future = JsFuture::from(request_promise);
let resp_value = future.await.map_to_mm(|e| SlurpError::Transport {
Expand Down

0 comments on commit a601e05

Please sign in to comment.