Skip to content

Commit 453262f

Browse files
authored
Merge pull request #105 from kjvalencik/main
safety: Use send_wrapper in WASM instead of unsafe
2 parents 0a54b06 + e62818f commit 453262f

File tree

2 files changed

+10
-25
lines changed

2 files changed

+10
-25
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ js-sys = { version = "0.3.25", optional = true }
6868
wasm-bindgen = { version = "0.2.48", optional = true }
6969
wasm-bindgen-futures = { version = "0.4.5", optional = true }
7070
futures = { version = "0.3.1", optional = true }
71+
send_wrapper = { version = "0.6.0", features = ["futures"] }
7172

7273
[target.'cfg(target_arch = "wasm32")'.dependencies.web-sys]
7374
version = "0.3.25"

src/wasm.rs

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
33
use std::convert::{Infallible, TryFrom};
44
use std::pin::Pin;
5-
use std::task::{Context, Poll};
65

76
use futures::prelude::*;
7+
use send_wrapper::SendWrapper;
88

99
use crate::Config;
1010

@@ -42,7 +42,7 @@ impl HttpClient for WasmClient {
4242
{
4343
let config = self.config.clone();
4444

45-
InnerFuture::new(async move {
45+
wrap_send(async move {
4646
let req: fetch::Request = fetch::Request::new(req).await?;
4747
let conn = req.send();
4848
let mut res = if let Some(timeout) = config.timeout {
@@ -87,29 +87,13 @@ impl TryFrom<Config> for WasmClient {
8787
}
8888
}
8989

90-
struct InnerFuture {
91-
fut: Pin<Box<dyn Future<Output = Result<Response, Error>> + 'static>>,
92-
}
93-
94-
impl InnerFuture {
95-
fn new<F: Future<Output = Result<Response, Error>> + 'static>(fut: F) -> Pin<Box<Self>> {
96-
Box::pin(Self { fut: Box::pin(fut) })
97-
}
98-
}
99-
100-
// This is safe because WASM doesn't have threads yet. Once WASM supports threads we should use a
101-
// thread to park the blocking implementation until it's been completed.
102-
unsafe impl Send for InnerFuture {}
103-
104-
impl Future for InnerFuture {
105-
type Output = Result<Response, Error>;
106-
107-
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
108-
// This is safe because we're only using this future as a pass-through for the inner
109-
// future, in order to implement `Send`. If it's safe to poll the inner future, it's safe
110-
// to proxy it too.
111-
unsafe { Pin::new_unchecked(&mut self.fut).poll(cx) }
112-
}
90+
// This should not panic because WASM doesn't have threads yet. Once WASM supports threads
91+
// we can use a thread to park the blocking implementation until it's been completed.
92+
fn wrap_send<Fut, O>(f: Fut) -> Pin<Box<dyn Future<Output = O> + Send + Sync + 'static>>
93+
where
94+
Fut: Future<Output = O> + 'static,
95+
{
96+
Box::pin(SendWrapper::new(f))
11397
}
11498

11599
mod fetch {

0 commit comments

Comments
 (0)