Skip to content

Commit

Permalink
fix(websocket-websys): Add support for different WASM environments
Browse files Browse the repository at this point in the history
Add support different WASM environments (such as workers, NodeJS)
that don't have a `window` global. This is done by binding to the
global `setInterval` and `clearInterval` functions directly.
This uses the same approach used by gloo-timers implemented in
[rustwasm/gloo#185](rustwasm/gloo#185) and
[rustwasm/gloo#283](rustwasm/gloo#283) given
the `web-sys` lack of interes to support this (see discussion in
[this issue](rustwasm/wasm-bindgen#1046)).

Co-authored-by: sisou <[email protected]>
  • Loading branch information
jsdanielh and sisou committed Nov 19, 2023
1 parent 0ceb658 commit 6b06148
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 12 deletions.
7 changes: 7 additions & 0 deletions transports/websocket-websys/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 0.3.1

- Add support for different WASM environments by binding to the global
`setInterval` and `clearInterval` functions directly. See [PR 4889].

[PR 4889]: https://github.com/libp2p/rust-libp2p/pull/4889

## 0.3.0


Expand Down
2 changes: 1 addition & 1 deletion transports/websocket-websys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "libp2p-websocket-websys"
edition = "2021"
rust-version = "1.60.0"
description = "WebSocket for libp2p under WASM environment"
version = "0.3.0"
version = "0.3.1"
authors = ["Vince Vasta <[email protected]>"]
license = "MIT"
repository = "https://github.com/libp2p/rust-libp2p"
Expand Down
30 changes: 19 additions & 11 deletions transports/websocket-websys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
use bytes::BytesMut;
use futures::task::AtomicWaker;
use futures::{future::Ready, io, prelude::*};
use js_sys::Array;
use js_sys::Function;
use libp2p_core::{
multiaddr::{Multiaddr, Protocol},
transport::{ListenerId, TransportError, TransportEvent},
Expand All @@ -35,7 +35,16 @@ use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Mutex;
use std::{pin::Pin, task::Context, task::Poll};
use wasm_bindgen::{prelude::*, JsCast};
use web_sys::{window, CloseEvent, Event, MessageEvent, WebSocket};
use web_sys::{CloseEvent, Event, MessageEvent, WebSocket};

#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_name = "setInterval", catch)]
fn set_interval(handler: &Function, timeout: i32) -> Result<JsValue, JsValue>;

#[wasm_bindgen(js_name = "clearInterval")]
fn clear_interval(handle: JsValue) -> JsValue;
}

/// A Websocket transport that can be used in a wasm environment.
///
Expand Down Expand Up @@ -188,7 +197,7 @@ struct Inner {
_on_close_closure: Rc<Closure<dyn FnMut(CloseEvent)>>,
_on_error_closure: Rc<Closure<dyn FnMut(CloseEvent)>>,
_on_message_closure: Rc<Closure<dyn FnMut(MessageEvent)>>,
buffered_amount_low_interval: i32,
buffered_amount_low_interval: Option<JsValue>,
}

impl Inner {
Expand Down Expand Up @@ -300,14 +309,13 @@ impl Connection {
}
}
});
let buffered_amount_low_interval = window()
.expect("to have a window")
.set_interval_with_callback_and_timeout_and_arguments(
let buffered_amount_low_interval = Some(
set_interval(
on_buffered_amount_low_closure.as_ref().unchecked_ref(),
100, // Chosen arbitrarily and likely worth tuning. Due to low impact of the /ws transport, no further effort was invested at the time.
&Array::new(),
)
.expect("to be able to set an interval");
.expect("to be able to set an interval"),
);

Self {
inner: SendWrapper::new(Inner {
Expand Down Expand Up @@ -439,8 +447,8 @@ impl Drop for Connection {
.close_with_code_and_reason(GO_AWAY_STATUS_CODE, "connection dropped");
}

window()
.expect("to have a window")
.clear_interval_with_handle(self.inner.buffered_amount_low_interval)
if let Some(id) = self.inner.buffered_amount_low_interval.take() {
clear_interval(id);
}
}
}

0 comments on commit 6b06148

Please sign in to comment.