Skip to content

Commit

Permalink
make wasm::WebSocket::new() Send
Browse files Browse the repository at this point in the history
  • Loading branch information
jgraef committed Dec 28, 2024
1 parent 40aef96 commit df60a10
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 24 deletions.
18 changes: 13 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -490,9 +490,17 @@ pub mod tests {
assert_eq!(u16::from(text), 1001u16);
}

// assert that our types are Send + Sync
trait AssertSendSync: Send + Sync {}
impl AssertSendSync for UpgradedRequestBuilder {}
impl AssertSendSync for UpgradeResponse {}
impl AssertSendSync for WebSocket {}
#[test]
fn assert_send() {
// assert that our types are Send
trait AssertSend: Send {}
impl AssertSend for UpgradedRequestBuilder {}
impl AssertSend for UpgradeResponse {}
impl AssertSend for WebSocket {}

fn assert_send<T: Send>(_value: T) {}

let connect_fut = websocket("https://echo.websocket.org/");
assert_send(connect_fut);
}
}
41 changes: 22 additions & 19 deletions src/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,6 @@ impl WebSocket {
return Err(Error::InvalidUrl(url));
}

// create the websocket
let websocket = web_sys::WebSocket::new_with_str_sequence(
&url.to_string(),
&protocols
.into_iter()
.map(|s| JsString::from(s.to_owned()))
.collect::<Array>(),
)
.map_err(|_| Error::ConnectionFailed)?;
websocket.set_binary_type(web_sys::BinaryType::Arraybuffer);

// outgoing channel. only needs a capacity of 1, as we wait for acks anyway
let (outgoing_tx, outgoing_rx) = mpsc::channel(1);

Expand All @@ -93,13 +82,27 @@ impl WebSocket {
// channel for connect acks. message type: `Result<String, Error>`, where `String` is the protocol reported by the websocket
let (connect_ack_tx, connect_ack_rx) = oneshot::channel();

// spawn a task for the websocket locally. this way our `WebSocket` struct is `Send + Sync`, while the code that has the
// `web_sys::Websocket` (which is not `Send + Sync`) stays on the same thread.
tracing::debug!("spawning websocket task");
let task_span = tracing::info_span!("websocket");
wasm_bindgen_futures::spawn_local(
run_websocket(websocket, connect_ack_tx, outgoing_rx, incoming_tx).instrument(task_span),
);
// create the websocket
{
let websocket = web_sys::WebSocket::new_with_str_sequence(
&url.to_string(),
&protocols
.into_iter()
.map(|s| JsString::from(s.to_owned()))
.collect::<Array>(),
)
.map_err(|_| Error::ConnectionFailed)?;
websocket.set_binary_type(web_sys::BinaryType::Arraybuffer);

// spawn a task for the websocket locally. this way our `WebSocket` struct is `Send + Sync`, while the code that has the
// `web_sys::Websocket` (which is not `Send + Sync`) stays on the same thread.
tracing::debug!("spawning websocket task");
let task_span = tracing::info_span!("websocket");
wasm_bindgen_futures::spawn_local(
run_websocket(websocket, connect_ack_tx, outgoing_rx, incoming_tx)
.instrument(task_span),
);
}

// wait for connection ack, or error
tracing::debug!("waiting for ack");
Expand Down Expand Up @@ -321,4 +324,4 @@ fn send_message(websocket: &web_sys::WebSocket, message: Message) -> Result<(),
}
}
Ok::<(), Error>(())
}
}

0 comments on commit df60a10

Please sign in to comment.