mirror of https://github.com/http-rs/http-client
safety: Use send_wrapper in WASM instead of unsafe
Resolves https://github.com/http-rs/http-client/issues/40
This commit is contained in:
parent
88e93dffca
commit
e62818f068
|
@ -68,6 +68,7 @@ js-sys = { version = "0.3.25", optional = true }
|
|||
wasm-bindgen = { version = "0.2.48", optional = true }
|
||||
wasm-bindgen-futures = { version = "0.4.5", optional = true }
|
||||
futures = { version = "0.3.1", optional = true }
|
||||
send_wrapper = { version = "0.6.0", features = ["futures"] }
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies.web-sys]
|
||||
version = "0.3.25"
|
||||
|
|
34
src/wasm.rs
34
src/wasm.rs
|
@ -2,9 +2,9 @@
|
|||
|
||||
use std::convert::{Infallible, TryFrom};
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use futures::prelude::*;
|
||||
use send_wrapper::SendWrapper;
|
||||
|
||||
use crate::Config;
|
||||
|
||||
|
@ -42,7 +42,7 @@ impl HttpClient for WasmClient {
|
|||
{
|
||||
let config = self.config.clone();
|
||||
|
||||
InnerFuture::new(async move {
|
||||
wrap_send(async move {
|
||||
let req: fetch::Request = fetch::Request::new(req).await?;
|
||||
let conn = req.send();
|
||||
let mut res = if let Some(timeout) = config.timeout {
|
||||
|
@ -87,29 +87,13 @@ impl TryFrom<Config> for WasmClient {
|
|||
}
|
||||
}
|
||||
|
||||
struct InnerFuture {
|
||||
fut: Pin<Box<dyn Future<Output = Result<Response, Error>> + 'static>>,
|
||||
}
|
||||
|
||||
impl InnerFuture {
|
||||
fn new<F: Future<Output = Result<Response, Error>> + 'static>(fut: F) -> Pin<Box<Self>> {
|
||||
Box::pin(Self { fut: Box::pin(fut) })
|
||||
}
|
||||
}
|
||||
|
||||
// This is safe because WASM doesn't have threads yet. Once WASM supports threads we should use a
|
||||
// thread to park the blocking implementation until it's been completed.
|
||||
unsafe impl Send for InnerFuture {}
|
||||
|
||||
impl Future for InnerFuture {
|
||||
type Output = Result<Response, Error>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
// This is safe because we're only using this future as a pass-through for the inner
|
||||
// future, in order to implement `Send`. If it's safe to poll the inner future, it's safe
|
||||
// to proxy it too.
|
||||
unsafe { Pin::new_unchecked(&mut self.fut).poll(cx) }
|
||||
}
|
||||
// This should not panic because WASM doesn't have threads yet. Once WASM supports threads
|
||||
// we can use a thread to park the blocking implementation until it's been completed.
|
||||
fn wrap_send<Fut, O>(f: Fut) -> Pin<Box<dyn Future<Output = O> + Send + Sync + 'static>>
|
||||
where
|
||||
Fut: Future<Output = O> + 'static,
|
||||
{
|
||||
Box::pin(SendWrapper::new(f))
|
||||
}
|
||||
|
||||
mod fetch {
|
||||
|
|
Loading…
Reference in New Issue