From 25924058c9bfe3e3edfbf1cc8106ad3611998ae2 Mon Sep 17 00:00:00 2001 From: Daniel Salinas Date: Sat, 12 Oct 2024 13:45:10 -0400 Subject: [PATCH] Make the matrix-sdk-ui crate support wasm32-unknown-unknown This commit adjusts types and traits to support targeting wasm32. --- crates/matrix-sdk-base/src/client.rs | 3 - crates/matrix-sdk-base/src/read_receipts.rs | 7 +- crates/matrix-sdk-base/src/store/mod.rs | 3 - .../src/store/observable_map.rs | 13 ++- crates/matrix-sdk-common/Cargo.toml | 5 +- crates/matrix-sdk-common/src/executor.rs | 88 +++++++++++++++++-- crates/matrix-sdk-common/src/lib.rs | 9 -- crates/matrix-sdk-crypto/src/machine/mod.rs | 2 +- .../src/room_list_service/filters/mod.rs | 3 + crates/matrix-sdk-ui/src/sync_service.rs | 10 +-- crates/matrix-sdk-ui/src/timeline/futures.rs | 4 +- .../src/timeline/pinned_events_loader.rs | 12 +-- .../matrix-sdk-ui/src/timeline/tests/mod.rs | 17 ++-- crates/matrix-sdk-ui/src/timeline/traits.rs | 43 ++++++--- .../src/unable_to_decrypt_hook.rs | 8 +- crates/matrix-sdk/Cargo.toml | 2 +- crates/matrix-sdk/src/client/mod.rs | 14 +-- crates/matrix-sdk/src/event_handler/mod.rs | 5 +- crates/matrix-sdk/src/room/futures.rs | 1 - crates/matrix-sdk/src/sliding_sync/error.rs | 2 +- crates/matrix-sdk/src/sliding_sync/mod.rs | 11 +-- crates/matrix-sdk/src/sliding_sync/utils.rs | 43 --------- 22 files changed, 176 insertions(+), 129 deletions(-) delete mode 100644 crates/matrix-sdk/src/sliding_sync/utils.rs diff --git a/crates/matrix-sdk-base/src/client.rs b/crates/matrix-sdk-base/src/client.rs index 36485c13e26..94b394a5fa8 100644 --- a/crates/matrix-sdk-base/src/client.rs +++ b/crates/matrix-sdk-base/src/client.rs @@ -22,9 +22,7 @@ use std::{ }; use eyeball::{SharedObservable, Subscriber}; -#[cfg(not(target_arch = "wasm32"))] use eyeball_im::{Vector, VectorDiff}; -#[cfg(not(target_arch = "wasm32"))] use futures_util::Stream; #[cfg(feature = "e2e-encryption")] use matrix_sdk_crypto::{ @@ -234,7 +232,6 @@ impl BaseClient { /// Get a stream of all the rooms changes, in addition to the existing /// rooms. - #[cfg(not(target_arch = "wasm32"))] pub fn rooms_stream(&self) -> (Vector, impl Stream>>) { self.store.rooms_stream() } diff --git a/crates/matrix-sdk-base/src/read_receipts.rs b/crates/matrix-sdk-base/src/read_receipts.rs index f582bdd5ade..5faa3712613 100644 --- a/crates/matrix-sdk-base/src/read_receipts.rs +++ b/crates/matrix-sdk-base/src/read_receipts.rs @@ -123,7 +123,10 @@ use std::{ }; use eyeball_im::Vector; -use matrix_sdk_common::{deserialized_responses::SyncTimelineEvent, ring_buffer::RingBuffer}; +use matrix_sdk_common::{ + deserialized_responses::SyncTimelineEvent, ring_buffer::RingBuffer, SendOutsideWasm, + SyncOutsideWasm, +}; use ruma::{ events::{ poll::{start::PollStartEventContent, unstable_start::UnstablePollStartEventContent}, @@ -266,7 +269,7 @@ impl RoomReadReceipts { } /// Provider for timeline events prior to the current sync. -pub trait PreviousEventsProvider: Send + Sync { +pub trait PreviousEventsProvider: SendOutsideWasm + SyncOutsideWasm { /// Returns the list of known timeline events, in sync order, for the given /// room. fn for_room(&self, room_id: &RoomId) -> Vector; diff --git a/crates/matrix-sdk-base/src/store/mod.rs b/crates/matrix-sdk-base/src/store/mod.rs index cd4b7c67cd1..c605d939ee1 100644 --- a/crates/matrix-sdk-base/src/store/mod.rs +++ b/crates/matrix-sdk-base/src/store/mod.rs @@ -29,9 +29,7 @@ use std::{ sync::{Arc, RwLock as StdRwLock}, }; -#[cfg(not(target_arch = "wasm32"))] use eyeball_im::{Vector, VectorDiff}; -#[cfg(not(target_arch = "wasm32"))] use futures_util::Stream; use once_cell::sync::OnceCell; @@ -266,7 +264,6 @@ impl Store { /// Get a stream of all the rooms changes, in addition to the existing /// rooms. - #[cfg(not(target_arch = "wasm32"))] pub fn rooms_stream(&self) -> (Vector, impl Stream>>) { self.rooms.read().unwrap().stream() } diff --git a/crates/matrix-sdk-base/src/store/observable_map.rs b/crates/matrix-sdk-base/src/store/observable_map.rs index 1650d08a160..85be983ea2b 100644 --- a/crates/matrix-sdk-base/src/store/observable_map.rs +++ b/crates/matrix-sdk-base/src/store/observable_map.rs @@ -149,6 +149,9 @@ mod impl_non_wasm32 { mod impl_wasm32 { use std::{borrow::Borrow, collections::BTreeMap, hash::Hash}; + use eyeball_im::{Vector, VectorDiff}; + use futures_util::{stream, Stream, StreamExt}; + /// An observable map for Wasm. It's a simple wrapper around `BTreeMap`. #[derive(Debug)] pub(crate) struct ObservableMap(BTreeMap) @@ -197,15 +200,21 @@ mod impl_wasm32 { self.0.values() } + /// Get a [`Stream`] of the values. + pub(crate) fn stream(&self) -> (Vector, impl Stream>>) { + self.values.subscribe().into_values_and_batched_stream() + } + /// Remove a `V` value based on their ID, if it exists. /// /// Returns the removed value. pub(crate) fn remove(&mut self, key: &L) -> Option where K: Borrow, - L: Hash + Eq + Ord + ?Sized, + L: Hash + Eq + ?Sized, { - self.0.remove(key) + let position = self.mapping.remove(key)?; + Some(self.values.remove(position)) } } } diff --git a/crates/matrix-sdk-common/Cargo.toml b/crates/matrix-sdk-common/Cargo.toml index 87d52a1f3fe..acce1456447 100644 --- a/crates/matrix-sdk-common/Cargo.toml +++ b/crates/matrix-sdk-common/Cargo.toml @@ -31,13 +31,16 @@ tokio = { workspace = true, features = ["rt", "time"] } uniffi = { workspace = true, optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] -futures-util = { workspace = true, features = ["channel"] } wasm-bindgen-futures = { version = "0.4.33", optional = true } gloo-timers = { version = "0.3.0", features = ["futures"] } +futures-util = { workspace = true, features = ["channel"] } web-sys = { version = "0.3.60", features = ["console"] } tracing-subscriber = { workspace = true, features = ["fmt", "ansi"] } wasm-bindgen = "0.2.84" +[target.'cfg(not(target_arch = "wasm32"))'.dependencies] +futures-util = { workspace = true } + [dev-dependencies] assert_matches = { workspace = true } proptest = { version = "1.4.0", default-features = false, features = ["std"] } diff --git a/crates/matrix-sdk-common/src/executor.rs b/crates/matrix-sdk-common/src/executor.rs index b1cb1a7bf13..0083b857f18 100644 --- a/crates/matrix-sdk-common/src/executor.rs +++ b/crates/matrix-sdk-common/src/executor.rs @@ -14,8 +14,6 @@ //! Abstraction over an executor so we can spawn tasks under WASM the same way //! we do usually. - -#[cfg(target_arch = "wasm32")] use std::{ future::Future, pin::Pin, @@ -25,13 +23,17 @@ use std::{ #[cfg(target_arch = "wasm32")] pub use futures_util::future::Aborted as JoinError; #[cfg(target_arch = "wasm32")] -use futures_util::{ - future::{AbortHandle, Abortable, RemoteHandle}, - FutureExt, -}; +use futures_util::future::{AbortHandle, Abortable, RemoteHandle}; +use futures_util::FutureExt; #[cfg(not(target_arch = "wasm32"))] pub use tokio::task::{spawn, JoinError, JoinHandle}; +/// A `Box::pin` future that is `Send` on non-wasm, and without `Send` on wasm. +#[cfg(target_arch = "wasm32")] +pub type BoxFuture<'a, T> = Pin + 'a>>; +#[cfg(not(target_arch = "wasm32"))] +pub type BoxFuture<'a, T> = Pin + Send + 'a>>; + #[cfg(target_arch = "wasm32")] pub fn spawn(future: F) -> JoinHandle where @@ -50,6 +52,32 @@ where JoinHandle { remote_handle, abort_handle } } +pub trait BoxFutureExt<'a, T: 'a> { + fn box_future(self) -> BoxFuture<'a, T>; +} + +#[cfg(not(target_arch = "wasm32"))] +impl<'a, F, T> BoxFutureExt<'a, T> for F +where + F: Future + 'a + Send, + T: 'a, +{ + fn box_future(self) -> BoxFuture<'a, T> { + self.boxed() + } +} + +#[cfg(target_arch = "wasm32")] +impl<'a, F, T> BoxFutureExt<'a, T> for F +where + F: Future + 'a, + T: 'a, +{ + fn box_future(self) -> BoxFuture<'a, T> { + self.boxed_local() + } +} + #[cfg(target_arch = "wasm32")] #[derive(Debug)] pub struct JoinHandle { @@ -78,6 +106,54 @@ impl Future for JoinHandle { } } +#[derive(Debug)] +pub struct AbortOnDrop(JoinHandle); + +impl AbortOnDrop { + pub fn new(join_handle: JoinHandle) -> Self { + Self(join_handle) + } +} + +impl Drop for AbortOnDrop { + fn drop(&mut self) { + self.0.abort(); + } +} + +#[cfg(not(target_arch = "wasm32"))] +impl Future for AbortOnDrop { + type Output = Result; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + Pin::new(&mut self.0).poll(cx) + } +} + +#[cfg(target_arch = "wasm32")] +impl Future for AbortOnDrop { + type Output = Result; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + if self.0.abort_handle.is_aborted() { + // The future has been aborted. It is not possible to poll it again. + Poll::Ready(Err(JoinError)) + } else { + Pin::new(&mut self.0.remote_handle).poll(cx).map(Ok) + } + } +} + +/// Trait to create a `AbortOnDrop` from a `JoinHandle`. +pub trait JoinHandleExt { + fn abort_on_drop(self) -> AbortOnDrop; +} + +impl JoinHandleExt for JoinHandle { + fn abort_on_drop(self) -> AbortOnDrop { + AbortOnDrop::new(self) + } +} #[cfg(test)] mod tests { use assert_matches::assert_matches; diff --git a/crates/matrix-sdk-common/src/lib.rs b/crates/matrix-sdk-common/src/lib.rs index 451a86fa16c..851dc16b576 100644 --- a/crates/matrix-sdk-common/src/lib.rs +++ b/crates/matrix-sdk-common/src/lib.rs @@ -15,9 +15,6 @@ #![doc = include_str!("../README.md")] #![warn(missing_debug_implementations)] -use std::pin::Pin; - -use futures_core::Future; #[doc(no_inline)] pub use ruma; @@ -90,11 +87,5 @@ macro_rules! boxed_into_future { }; } -/// A `Box::pin` future that is `Send` on non-wasm, and without `Send` on wasm. -#[cfg(target_arch = "wasm32")] -pub type BoxFuture<'a, T> = Pin + 'a>>; -#[cfg(not(target_arch = "wasm32"))] -pub type BoxFuture<'a, T> = Pin + Send + 'a>>; - #[cfg(feature = "uniffi")] uniffi::setup_scaffolding!(); diff --git a/crates/matrix-sdk-crypto/src/machine/mod.rs b/crates/matrix-sdk-crypto/src/machine/mod.rs index 9439a83dea4..a7e82f71cb5 100644 --- a/crates/matrix-sdk-crypto/src/machine/mod.rs +++ b/crates/matrix-sdk-crypto/src/machine/mod.rs @@ -25,7 +25,7 @@ use matrix_sdk_common::{ UnableToDecryptReason, UnsignedDecryptionResult, UnsignedEventLocation, VerificationLevel, VerificationState, }, - BoxFuture, + executor::BoxFuture, }; use ruma::{ api::client::{ diff --git a/crates/matrix-sdk-ui/src/room_list_service/filters/mod.rs b/crates/matrix-sdk-ui/src/room_list_service/filters/mod.rs index 2eb01063da0..1085400f4e9 100644 --- a/crates/matrix-sdk-ui/src/room_list_service/filters/mod.rs +++ b/crates/matrix-sdk-ui/src/room_list_service/filters/mod.rs @@ -102,7 +102,10 @@ pub trait Filter: Fn(&Room) -> bool {} impl Filter for F where F: Fn(&Room) -> bool {} /// Type alias for a boxed filter function. +#[cfg(not(target_arch = "wasm32"))] pub type BoxedFilterFn = Box; +#[cfg(target_arch = "wasm32")] +pub type BoxedFilterFn = Box; /// Normalize a string, i.e. decompose it into NFD (Normalization Form D, i.e. a /// canonical decomposition, see http://www.unicode.org/reports/tr15/) and diff --git a/crates/matrix-sdk-ui/src/sync_service.rs b/crates/matrix-sdk-ui/src/sync_service.rs index 23c8166cafe..25186263bdc 100644 --- a/crates/matrix-sdk-ui/src/sync_service.rs +++ b/crates/matrix-sdk-ui/src/sync_service.rs @@ -29,13 +29,11 @@ use eyeball::{SharedObservable, Subscriber}; use futures_core::Future; use futures_util::{pin_mut, StreamExt as _}; use matrix_sdk::Client; +use matrix_sdk_base::executor::{spawn, JoinHandle}; use thiserror::Error; -use tokio::{ - sync::{ - mpsc::{Receiver, Sender}, - Mutex as AsyncMutex, OwnedMutexGuard, - }, - task::{spawn, JoinHandle}, +use tokio::sync::{ + mpsc::{Receiver, Sender}, + Mutex as AsyncMutex, OwnedMutexGuard, }; use tracing::{error, info, instrument, trace, warn, Instrument, Level}; diff --git a/crates/matrix-sdk-ui/src/timeline/futures.rs b/crates/matrix-sdk-ui/src/timeline/futures.rs index 91d20e708d9..3aa20525b38 100644 --- a/crates/matrix-sdk-ui/src/timeline/futures.rs +++ b/crates/matrix-sdk-ui/src/timeline/futures.rs @@ -1,6 +1,8 @@ use std::{fs, future::IntoFuture, path::PathBuf}; -use eyeball::{SharedObservable, Subscriber}; +use eyeball::SharedObservable; +#[cfg(not(target_arch = "wasm32"))] +use eyeball::Subscriber; use matrix_sdk::{attachment::AttachmentConfig, TransmissionProgress}; use matrix_sdk_base::boxed_into_future; use mime::Mime; diff --git a/crates/matrix-sdk-ui/src/timeline/pinned_events_loader.rs b/crates/matrix-sdk-ui/src/timeline/pinned_events_loader.rs index 1deb853607d..87c590edd23 100644 --- a/crates/matrix-sdk-ui/src/timeline/pinned_events_loader.rs +++ b/crates/matrix-sdk-ui/src/timeline/pinned_events_loader.rs @@ -14,10 +14,12 @@ use std::{fmt::Formatter, sync::Arc}; -use futures_util::{stream, FutureExt as _, StreamExt}; +use futures_util::{stream, StreamExt}; use matrix_sdk::{ - config::RequestConfig, event_cache::paginator::PaginatorError, BoxFuture, Room, - SendOutsideWasm, SyncOutsideWasm, + config::RequestConfig, + event_cache::paginator::PaginatorError, + executor::{BoxFuture, BoxFutureExt}, + Room, }; use matrix_sdk_base::deserialized_responses::SyncTimelineEvent; use ruma::{events::relation::RelationType, EventId, MilliSecondsSinceUnixEpoch, OwnedEventId}; @@ -120,7 +122,7 @@ impl PinnedEventsLoader { } } -pub trait PinnedEventsRoom: SendOutsideWasm + SyncOutsideWasm { +pub trait PinnedEventsRoom: Send + Sync { /// Load a single room event using the cache or network and any events /// related to it, if they are cached. /// @@ -166,7 +168,7 @@ impl PinnedEventsRoom for Room { .map(|e| (e.into(), Vec::new())) .map_err(|err| PaginatorError::SdkError(Box::new(err))) } - .boxed() + .box_future() } fn pinned_event_ids(&self) -> Option> { diff --git a/crates/matrix-sdk-ui/src/timeline/tests/mod.rs b/crates/matrix-sdk-ui/src/timeline/tests/mod.rs index 356a2ad2228..a1b73bae528 100644 --- a/crates/matrix-sdk-ui/src/timeline/tests/mod.rs +++ b/crates/matrix-sdk-ui/src/timeline/tests/mod.rs @@ -23,16 +23,15 @@ use std::{ use eyeball::{SharedObservable, Subscriber}; use eyeball_im::VectorDiff; use futures_core::Stream; -use futures_util::FutureExt as _; use indexmap::IndexMap; use matrix_sdk::{ config::RequestConfig, deserialized_responses::{SyncTimelineEvent, TimelineEvent}, event_cache::paginator::{PaginableRoom, PaginatorError}, + executor::{BoxFuture, BoxFutureExt}, room::{EventWithContextResponse, Messages, MessagesOptions}, send_queue::RoomSendQueueUpdate, test_utils::events::EventFactory, - BoxFuture, }; use matrix_sdk_base::{latest_event::LatestEvent, RoomInfo, RoomState}; use matrix_sdk_test::{EventBuilder, ALICE, BOB, DEFAULT_TEST_ROOM_ID}; @@ -370,7 +369,7 @@ impl RoomDataProvider for TestRoomDataProvider { } fn profile_from_user_id<'a>(&'a self, _user_id: &'a UserId) -> BoxFuture<'a, Option> { - ready(None).boxed() + ready(None).box_future() } fn profile_from_latest_event(&self, _latest_event: &LatestEvent) -> Option { @@ -390,7 +389,7 @@ impl RoomDataProvider for TestRoomDataProvider { .and_then(|user_map| user_map.get(user_id)) .cloned(), ) - .boxed() + .box_future() } fn load_event_receipts( @@ -402,7 +401,7 @@ impl RoomDataProvider for TestRoomDataProvider { } else { IndexMap::new() }) - .boxed() + .box_future() } fn push_rules_and_context(&self) -> BoxFuture<'_, Option<(Ruleset, PushConditionRoomCtx)>> { @@ -420,11 +419,11 @@ impl RoomDataProvider for TestRoomDataProvider { power_levels: Some(power_levels), }; - ready(Some((push_rules, push_context))).boxed() + ready(Some((push_rules, push_context))).box_future() } fn load_fully_read_marker(&self) -> BoxFuture<'_, Option> { - ready(self.fully_read_marker.clone()).boxed() + ready(self.fully_read_marker.clone()).box_future() } fn send(&self, content: AnyMessageLikeEventContent) -> BoxFuture<'_, Result<(), super::Error>> { @@ -432,7 +431,7 @@ impl RoomDataProvider for TestRoomDataProvider { self.sent_events.write().await.push(content); Ok(()) } - .boxed() + .box_future() } fn redact<'a>( @@ -445,7 +444,7 @@ impl RoomDataProvider for TestRoomDataProvider { self.redacted.write().await.push(event_id.to_owned()); Ok(()) } - .boxed() + .box_future() } fn room_info(&self) -> Subscriber { diff --git a/crates/matrix-sdk-ui/src/timeline/traits.rs b/crates/matrix-sdk-ui/src/timeline/traits.rs index 158488eb06f..3a1edcab2f1 100644 --- a/crates/matrix-sdk-ui/src/timeline/traits.rs +++ b/crates/matrix-sdk-ui/src/timeline/traits.rs @@ -15,13 +15,14 @@ use std::future::Future; use eyeball::Subscriber; -use futures_util::FutureExt as _; use indexmap::IndexMap; #[cfg(test)] use matrix_sdk::crypto::{DecryptionSettings, TrustRequirement}; use matrix_sdk::{ - deserialized_responses::TimelineEvent, event_cache::paginator::PaginableRoom, BoxFuture, - Result, Room, + deserialized_responses::TimelineEvent, + event_cache::paginator::PaginableRoom, + executor::{BoxFuture, BoxFutureExt as _}, + Result, Room, SendOutsideWasm, SyncOutsideWasm, }; use matrix_sdk_base::{latest_event::LatestEvent, RoomInfo}; use ruma::{ @@ -47,8 +48,19 @@ pub trait RoomExt { /// independent events. /// /// This is the same as using `room.timeline_builder().build()`. + #[cfg(not(target_arch = "wasm32"))] fn timeline(&self) -> impl Future> + Send; + /// Get a [`Timeline`] for this room. + /// + /// This offers a higher-level API than event handlers, in treating things + /// like edits and reactions as updates of existing items rather than new + /// independent events. + /// + /// This is the same as using `room.timeline_builder().build()`. + #[cfg(target_arch = "wasm32")] + fn timeline(&self) -> impl Future>; + /// Get a [`TimelineBuilder`] for this room. /// /// [`Timeline`] offers a higher-level API than event handlers, in treating @@ -71,7 +83,7 @@ impl RoomExt for Room { } pub(super) trait RoomDataProvider: - Clone + Send + Sync + 'static + PaginableRoom + PinnedEventsRoom + Clone + SendOutsideWasm + SyncOutsideWasm + 'static + PaginableRoom + PinnedEventsRoom { fn own_user_id(&self) -> &UserId; fn room_version(&self) -> RoomVersionId; @@ -137,7 +149,7 @@ impl RoomDataProvider for Room { } } } - .boxed() + .box_future() } fn profile_from_latest_event(&self, latest_event: &LatestEvent) -> Option { @@ -172,7 +184,7 @@ impl RoomDataProvider for Room { } } } - .boxed() + .box_future() } fn load_event_receipts<'a>( @@ -205,7 +217,7 @@ impl RoomDataProvider for Room { unthreaded_receipts.extend(main_thread_receipts); unthreaded_receipts } - .boxed() + .box_future() } fn push_rules_and_context(&self) -> BoxFuture<'_, Option<(Ruleset, PushConditionRoomCtx)>> { @@ -228,7 +240,7 @@ impl RoomDataProvider for Room { } } } - .boxed() + .box_future() } fn load_fully_read_marker(&self) -> BoxFuture<'_, Option> { @@ -248,7 +260,7 @@ impl RoomDataProvider for Room { _ => None, } } - .boxed() + .box_future() } fn send(&self, content: AnyMessageLikeEventContent) -> BoxFuture<'_, Result<(), super::Error>> { @@ -256,7 +268,7 @@ impl RoomDataProvider for Room { let _ = self.send_queue().send(content).await?; Ok(()) } - .boxed() + .box_future() } fn redact<'a>( @@ -273,7 +285,7 @@ impl RoomDataProvider for Room { .map_err(super::Error::RedactError)?; Ok(()) } - .boxed() + .box_future() } fn room_info(&self) -> Subscriber { @@ -283,11 +295,18 @@ impl RoomDataProvider for Room { // Internal helper to make most of retry_event_decryption independent of a room // object, which is annoying to create for testing and not really needed -pub(super) trait Decryptor: Clone + Send + Sync + 'static { +pub(super) trait Decryptor: Clone + SendOutsideWasm + SyncOutsideWasm + 'static { + #[cfg(not(target_arch = "wasm32"))] fn decrypt_event_impl( &self, raw: &Raw, ) -> impl Future> + Send; + + #[cfg(target_arch = "wasm32")] + fn decrypt_event_impl( + &self, + raw: &Raw, + ) -> impl Future>; } impl Decryptor for Room { diff --git a/crates/matrix-sdk-ui/src/unable_to_decrypt_hook.rs b/crates/matrix-sdk-ui/src/unable_to_decrypt_hook.rs index 14f72aee824..7fe284b7f0d 100644 --- a/crates/matrix-sdk-ui/src/unable_to_decrypt_hook.rs +++ b/crates/matrix-sdk-ui/src/unable_to_decrypt_hook.rs @@ -25,13 +25,15 @@ use std::{ }; use growable_bloom_filter::{GrowableBloom, GrowableBloomBuilder}; -use matrix_sdk::{crypto::types::events::UtdCause, Client}; +use matrix_sdk::{ + crypto::types::events::UtdCause, + executor::{spawn, JoinHandle}, + Client, +}; use matrix_sdk_base::{StateStoreDataKey, StateStoreDataValue, StoreError}; use ruma::{EventId, OwnedEventId}; use tokio::{ - spawn, sync::{Mutex as AsyncMutex, MutexGuard}, - task::JoinHandle, time::sleep, }; use tracing::error; diff --git a/crates/matrix-sdk/Cargo.toml b/crates/matrix-sdk/Cargo.toml index 27f91ed7ef4..48495813375 100644 --- a/crates/matrix-sdk/Cargo.toml +++ b/crates/matrix-sdk/Cargo.toml @@ -16,7 +16,7 @@ features = ["docsrs"] rustdoc-args = ["--cfg", "docsrs"] [features] -default = ["e2e-encryption", "automatic-room-key-forwarding", "sqlite", "native-tls"] +default = ["e2e-encryption", "automatic-room-key-forwarding", "sqlite", "native-tls", "js"] testing = ["matrix-sdk-sqlite?/testing", "matrix-sdk-indexeddb?/testing", "matrix-sdk-base/testing", "wiremock", "matrix-sdk-test", "assert_matches2"] e2e-encryption = [ diff --git a/crates/matrix-sdk/src/client/mod.rs b/crates/matrix-sdk/src/client/mod.rs index 20268e75d39..2eb4fcfebe4 100644 --- a/crates/matrix-sdk/src/client/mod.rs +++ b/crates/matrix-sdk/src/client/mod.rs @@ -23,12 +23,8 @@ use std::{ }; use eyeball::{SharedObservable, Subscriber}; -#[cfg(not(target_arch = "wasm32"))] use eyeball_im::VectorDiff; -use futures_core::Stream; -#[cfg(not(target_arch = "wasm32"))] -use futures_util::StreamExt; -#[cfg(not(target_arch = "wasm32"))] +use futures_util::{Stream, StreamExt}; use imbl::Vector; #[cfg(feature = "e2e-encryption")] use matrix_sdk_base::crypto::store::LockableCryptoStore; @@ -37,7 +33,7 @@ use matrix_sdk_base::{ store::{DynStateStore, ServerCapabilities}, sync::{Notification, RoomUpdates}, BaseClient, RoomInfoNotableUpdate, RoomState, RoomStateFilter, SendOutsideWasm, SessionMeta, - StateStoreDataKey, StateStoreDataValue, SyncOutsideWasm, + StateStoreDataKey, StateStoreDataValue, }; #[cfg(feature = "e2e-encryption")] use ruma::events::{room::encryption::RoomEncryptionEventContent, InitialStateEvent}; @@ -114,11 +110,8 @@ type NotificationHandlerFut = Pin + Send>>; #[cfg(target_arch = "wasm32")] type NotificationHandlerFut = Pin>>; -#[cfg(not(target_arch = "wasm32"))] type NotificationHandlerFn = Box NotificationHandlerFut + Send + Sync>; -#[cfg(target_arch = "wasm32")] -type NotificationHandlerFn = Box NotificationHandlerFut>; /// Enum controlling if a loop running callbacks should continue or abort. /// @@ -903,7 +896,7 @@ impl Client { /// [`Client`] for now. pub async fn register_notification_handler(&self, handler: H) -> &Self where - H: Fn(Notification, Room, Client) -> Fut + SendOutsideWasm + SyncOutsideWasm + 'static, + H: Fn(Notification, Room, Client) -> Fut + Send + Sync + 'static, Fut: Future + SendOutsideWasm + 'static, { self.inner.notification_handlers.write().await.push(Box::new( @@ -957,7 +950,6 @@ impl Client { } /// Get a stream of all the rooms, in addition to the existing rooms. - #[cfg(not(target_arch = "wasm32"))] pub fn rooms_stream(&self) -> (Vector, impl Stream>> + '_) { let (rooms, stream) = self.base_client().rooms_stream(); diff --git a/crates/matrix-sdk/src/event_handler/mod.rs b/crates/matrix-sdk/src/event_handler/mod.rs index c375619811d..25a96ed8792 100644 --- a/crates/matrix-sdk/src/event_handler/mod.rs +++ b/crates/matrix-sdk/src/event_handler/mod.rs @@ -69,10 +69,7 @@ type EventHandlerFut = Pin + Send>>; #[cfg(target_arch = "wasm32")] type EventHandlerFut = Pin>>; -#[cfg(not(target_arch = "wasm32"))] type EventHandlerFn = dyn Fn(EventHandlerData<'_>) -> EventHandlerFut + Send + Sync; -#[cfg(target_arch = "wasm32")] -type EventHandlerFn = dyn Fn(EventHandlerData<'_>) -> EventHandlerFut; type AnyMap = anymap2::Map; @@ -197,7 +194,7 @@ pub struct EventHandlerHandle { /// /// ¹ the only thing stopping such types from existing in stable Rust is that /// all manual implementations of the `Fn` traits require a Nightly feature -pub trait EventHandler: Clone + SendOutsideWasm + SyncOutsideWasm + 'static { +pub trait EventHandler: Clone + Send + Sync + 'static { /// The future returned by `handle_event`. #[doc(hidden)] type Future: EventHandlerFuture; diff --git a/crates/matrix-sdk/src/room/futures.rs b/crates/matrix-sdk/src/room/futures.rs index f1b91463fe7..87ea7f6b22b 100644 --- a/crates/matrix-sdk/src/room/futures.rs +++ b/crates/matrix-sdk/src/room/futures.rs @@ -271,7 +271,6 @@ impl<'a> SendAttachment<'a> { /// Replace the default `SharedObservable` used for tracking upload /// progress. - #[cfg(not(target_arch = "wasm32"))] pub fn with_send_progress_observable( mut self, send_progress: SharedObservable, diff --git a/crates/matrix-sdk/src/sliding_sync/error.rs b/crates/matrix-sdk/src/sliding_sync/error.rs index c72d5333e03..774e31510e3 100644 --- a/crates/matrix-sdk/src/sliding_sync/error.rs +++ b/crates/matrix-sdk/src/sliding_sync/error.rs @@ -1,7 +1,7 @@ //! Sliding Sync errors. +use matrix_sdk_common::executor::JoinError; use thiserror::Error; -use tokio::task::JoinError; /// Internal representation of errors in Sliding Sync. #[derive(Error, Debug)] diff --git a/crates/matrix-sdk/src/sliding_sync/mod.rs b/crates/matrix-sdk/src/sliding_sync/mod.rs index 322a7563f00..bfd883d048e 100644 --- a/crates/matrix-sdk/src/sliding_sync/mod.rs +++ b/crates/matrix-sdk/src/sliding_sync/mod.rs @@ -22,7 +22,6 @@ mod error; mod list; mod room; mod sticky_parameters; -mod utils; use std::{ collections::{btree_map::Entry, BTreeMap, HashSet}, @@ -36,20 +35,20 @@ use async_stream::stream; pub use client::{Version, VersionBuilder}; use futures_core::stream::Stream; pub use matrix_sdk_base::sliding_sync::http; -use matrix_sdk_common::{deserialized_responses::SyncTimelineEvent, timer}; +#[cfg(feature = "e2e-encryption")] +use matrix_sdk_common::executor::JoinHandleExt as _; +use matrix_sdk_common::{executor::spawn, deserialized_responses::SyncTimelineEvent, timer}; use ruma::{ api::{client::error::ErrorKind, OutgoingRequest}, assign, OwnedEventId, OwnedRoomId, RoomId, }; use serde::{Deserialize, Serialize}; use tokio::{ - select, spawn, + select, sync::{broadcast::Sender, Mutex as AsyncMutex, OwnedMutexGuard, RwLock as AsyncRwLock}, }; use tracing::{debug, error, info, instrument, trace, warn, Instrument, Span}; -#[cfg(feature = "e2e-encryption")] -use self::utils::JoinHandleExt as _; pub use self::{builder::*, client::VersionBuilderError, error::*, list::*, room::*}; use self::{ cache::restore_sliding_sync_state, @@ -609,6 +608,7 @@ impl SlidingSync { // aborted as soon as possible. let client = self.inner.client.clone(); + #[cfg(feature = "e2e-encryption")] let e2ee_uploads = spawn(async move { if let Err(error) = client.send_outgoing_requests().await { error!(?error, "Error while sending outgoing E2EE requests"); @@ -625,6 +625,7 @@ impl SlidingSync { // `e2ee_uploads`. It did run concurrently, so it should not be blocking for too // long. Otherwise —if `request` has failed— `e2ee_uploads` has // been dropped, so aborted. + #[cfg(feature = "e2e-encryption")] e2ee_uploads.await.map_err(|error| Error::JoinError { task_description: "e2ee_uploads".to_owned(), error, diff --git a/crates/matrix-sdk/src/sliding_sync/utils.rs b/crates/matrix-sdk/src/sliding_sync/utils.rs deleted file mode 100644 index 0bc1e998d43..00000000000 --- a/crates/matrix-sdk/src/sliding_sync/utils.rs +++ /dev/null @@ -1,43 +0,0 @@ -//! Moaaar features for Sliding Sync. - -use std::{ - future::Future, - pin::Pin, - task::{Context, Poll}, -}; - -use tokio::task::{JoinError, JoinHandle}; - -/// Private type to ensure a task is aborted on drop. -pub(crate) struct AbortOnDrop(JoinHandle); - -impl AbortOnDrop { - fn new(join_handle: JoinHandle) -> Self { - Self(join_handle) - } -} - -impl Drop for AbortOnDrop { - fn drop(&mut self) { - self.0.abort(); - } -} - -impl Future for AbortOnDrop { - type Output = Result; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - Pin::new(&mut self.0).poll(cx) - } -} - -/// Private trait to create a `AbortOnDrop` from a `JoinHandle`. -pub(crate) trait JoinHandleExt { - fn abort_on_drop(self) -> AbortOnDrop; -} - -impl JoinHandleExt for JoinHandle { - fn abort_on_drop(self) -> AbortOnDrop { - AbortOnDrop::new(self) - } -}