fix(sdk): Make event handler futures non-Send on wasm

This commit is contained in:
Jonas Platte
2022-08-08 17:22:48 +02:00
committed by Jonas Platte
parent 0701561e45
commit ad80839ffd
3 changed files with 34 additions and 6 deletions

View File

@@ -1,6 +1,8 @@
#![doc = include_str!("../README.md")]
#![warn(missing_debug_implementations)]
use std::future::Future;
pub use instant;
pub mod deserialized_responses;
@@ -36,6 +38,13 @@ pub trait SyncOutsideWasm {}
#[cfg(target_arch = "wasm32")]
impl<T> SyncOutsideWasm for T {}
/// Alias for `Future + SendOutsideWasm`.
///
/// Useful as a separate trait because the former trait bound can't be used
/// with `dyn`.
pub trait FutureSendOutsideWasm: Future + SendOutsideWasm {}
impl<T: Future + SendOutsideWasm> FutureSendOutsideWasm for T {}
/// Super trait that is used for our store traits, this trait will differ if
/// it's used on WASM. WASM targets will not require `Send` and `Sync` to have
/// implemented, while other targets will.

View File

@@ -32,7 +32,7 @@ use futures_signals::signal::Signal;
use matrix_sdk_base::{
deserialized_responses::SyncResponse,
media::{MediaEventContent, MediaFormat, MediaRequest, MediaThumbnailSize},
BaseClient, Session, SessionMeta, SessionTokens, StateStore,
BaseClient, FutureSendOutsideWasm, Session, SessionMeta, SessionTokens, StateStore,
};
use matrix_sdk_common::{
instant::{Duration, Instant},
@@ -110,7 +110,7 @@ const MIN_UPLOAD_REQUEST_TIMEOUT: Duration = Duration::from_secs(60 * 5);
type EventHandlerMap = BTreeMap<EventHandlerKey, Vec<EventHandlerWrapper>>;
type NotificationHandlerFut = Pin<Box<dyn Future<Output = ()> + Send>>;
type NotificationHandlerFut = Pin<Box<dyn FutureSendOutsideWasm<Output = ()>>>;
type NotificationHandlerFn =
Box<dyn Fn(Notification, room::Room, Client) -> NotificationHandlerFut + Send + Sync>;

View File

@@ -43,7 +43,10 @@ use std::{
sync::atomic::Ordering::SeqCst,
};
use matrix_sdk_base::deserialized_responses::{EncryptionInfo, SyncRoomEvent};
use matrix_sdk_base::{
deserialized_responses::{EncryptionInfo, SyncRoomEvent},
FutureSendOutsideWasm, SendOutsideWasm,
};
use ruma::{events::AnySyncStateEvent, serde::Raw, OwnedRoomId};
use serde::{de::DeserializeOwned, Deserialize};
use serde_json::value::RawValue as RawJsonValue;
@@ -51,7 +54,7 @@ use tracing::{error, warn};
use crate::{room, Client};
type EventHandlerFut = Pin<Box<dyn Future<Output = ()> + Send>>;
type EventHandlerFut = Pin<Box<dyn FutureSendOutsideWasm<Output = ()>>>;
type EventHandlerFn = dyn Fn(EventHandlerData<'_>) -> EventHandlerFut + Send + Sync;
#[doc(hidden)]
@@ -181,7 +184,7 @@ impl EventHandlerContext for EventHandlerHandle {
pub trait EventHandler<Ev, Ctx>: Send + Sync + 'static {
/// The future returned by `handle_event`.
#[doc(hidden)]
type Future: Future + Send + 'static;
type Future: Future + SendOutsideWasm + 'static;
/// Create a future for handling the given event.
///
@@ -540,7 +543,7 @@ macro_rules! impl_event_handler {
where
Ev: SyncEvent,
Fun: Fn(Ev, $($ty),*) -> Fut + Send + Sync + 'static,
Fut: Future + Send + 'static,
Fut: Future + SendOutsideWasm + 'static,
Fut::Output: EventHandlerResult,
$($ty: EventHandlerContext),*
{
@@ -949,4 +952,20 @@ mod tests {
assert_eq!(client.event_handlers().len(), 0);
}
#[async_test]
async fn use_client_in_handler() {
// This used to not work because we were requiring `Send` of event
// handler futures even on WASM, where practically all futures that do
// I/O aren't.
let client = no_retry_test_client(None).await;
client.add_event_handler(|_ev: OriginalSyncRoomMemberEvent, client: Client| async move {
// All of Client's async methods that do network requests (and
// possibly some that don't) are `!Send` on wasm. We obviously want
// to be able to use them in event handlers.
let _caps = client.get_capabilities().await?;
anyhow::Ok(())
});
}
}