From df60a1056304989409fdb0f0bc8dab90d1f9b0c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Janosch=20Gr=C3=A4f?= Date: Sat, 28 Dec 2024 01:29:17 +0100 Subject: [PATCH] make wasm::WebSocket::new() Send --- src/lib.rs | 18 +++++++++++++----- src/wasm.rs | 41 ++++++++++++++++++++++------------------- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index cb16526..32c1645 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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(_value: T) {} + + let connect_fut = websocket("https://echo.websocket.org/"); + assert_send(connect_fut); + } } diff --git a/src/wasm.rs b/src/wasm.rs index 1138b4a..044527c 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -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::(), - ) - .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); @@ -93,13 +82,27 @@ impl WebSocket { // channel for connect acks. message type: `Result`, 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::(), + ) + .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"); @@ -321,4 +324,4 @@ fn send_message(websocket: &web_sys::WebSocket, message: Message) -> Result<(), } } Ok::<(), Error>(()) -} \ No newline at end of file +}