Repository: matrix-org/matrix-rust-sdk (rust)

Issue:
Switch to another crate instead of `instant`
We use `instant` to provide an implementation of `std::time::Instant` on wasm.

However, as https://github.com/sebcrozet/instant/issues/52 notes, that crate isn't very well maintained. Consider the use of `web-time` instead.

Pull request:
chore: Use `ruma::time` instead of instant
This is a reexport of web-time.

- [x] Public API changes documented in changelogs (optional)

Closes #2937.

Patch:
diff --git a/Cargo.lock b/Cargo.lock
index a65a9edad..6c6f10491 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2620,9 +2620,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
 dependencies = [
  "cfg-if",
- "js-sys",
- "wasm-bindgen",
- "web-sys",
 ]
 
 [[package]]
@@ -3216,7 +3213,6 @@ dependencies = [
  "tracing",
  "uniffi",
  "wasm-bindgen-test",
- "web-time",
 ]
 
 [[package]]
@@ -3228,7 +3224,6 @@ dependencies = [
  "futures-core",
  "futures-util",
  "gloo-timers",
- "instant",
  "js-sys",
  "matrix-sdk-test",
  "proptest",
diff --git a/crates/matrix-sdk-base/CHANGELOG.md b/crates/matrix-sdk-base/CHANGELOG.md
index fc1b21e7f..dab46a947 100644
--- a/crates/matrix-sdk-base/CHANGELOG.md
+++ b/crates/matrix-sdk-base/CHANGELOG.md
@@ -15,6 +15,7 @@
   - They both take a `MediaThumbnailSettings` instead of `MediaThumbnailSize`.
 - The `StateStore` methods to access data in the media cache where moved to a separate
   `EventCacheStore` trait.
+- The `instant` module was removed, use the `ruma::time` module instead.
 
 # 0.7.0
 
diff --git a/crates/matrix-sdk-base/Cargo.toml b/crates/matrix-sdk-base/Cargo.toml
index 23bc4e02b..4243806ff 100644
--- a/crates/matrix-sdk-base/Cargo.toml
+++ b/crates/matrix-sdk-base/Cargo.toml
@@ -71,7 +71,6 @@ futures-executor = { workspace = true }
 http = { workspace = true }
 matrix-sdk-test = { workspace = true }
 stream_assert = { workspace = true }
-web-time = "1.1.0"
 
 [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
 tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
diff --git a/crates/matrix-sdk-base/src/client.rs b/crates/matrix-sdk-base/src/client.rs
index f2e08e63e..be8df36bb 100644
--- a/crates/matrix-sdk-base/src/client.rs
+++ b/crates/matrix-sdk-base/src/client.rs
@@ -26,7 +26,6 @@ use eyeball::{SharedObservable, Subscriber};
 use eyeball_im::{Vector, VectorDiff};
 #[cfg(not(target_arch = "wasm32"))]
 use futures_util::Stream;
-use matrix_sdk_common::instant::Instant;
 #[cfg(feature = "e2e-encryption")]
 use matrix_sdk_crypto::{
     store::DynCryptoStore, CollectStrategy, EncryptionSettings, EncryptionSyncChanges, OlmError,
@@ -57,6 +56,7 @@ use ruma::{
     },
     push::{Action, PushConditionRoomCtx, Ruleset},
     serde::Raw,
+    time::Instant,
     OwnedRoomId, OwnedUserId, RoomId, RoomVersionId, UInt, UserId,
 };
 use tokio::sync::{broadcast, Mutex};
diff --git a/crates/matrix-sdk-base/src/rooms/normal.rs b/crates/matrix-sdk-base/src/rooms/normal.rs
index 94b112722..7028e88d0 100644
--- a/crates/matrix-sdk-base/src/rooms/normal.rs
+++ b/crates/matrix-sdk-base/src/rooms/normal.rs
@@ -1659,6 +1659,7 @@ mod tests {
         ops::{Not, Sub},
         str::FromStr,
         sync::Arc,
+        time::Duration,
     };
 
     use assign::assign;
@@ -1687,12 +1688,12 @@ mod tests {
         },
         owned_event_id, room_alias_id, room_id,
         serde::Raw,
+        time::SystemTime,
         user_id, EventEncryptionAlgorithm, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedUserId,
         UserId,
     };
     use serde_json::json;
     use stream_assert::{assert_pending, assert_ready};
-    use web_time::{Duration, SystemTime};
 
     use super::{compute_display_name_from_heroes, Room, RoomHero, RoomInfo, RoomState, SyncInfo};
     #[cfg(any(feature = "experimental-sliding-sync", feature = "e2e-encryption"))]
diff --git a/crates/matrix-sdk-base/src/store/memory_store.rs b/crates/matrix-sdk-base/src/store/memory_store.rs
index 3fdb3121a..46c9f090a 100644
--- a/crates/matrix-sdk-base/src/store/memory_store.rs
+++ b/crates/matrix-sdk-base/src/store/memory_store.rs
@@ -19,7 +19,6 @@ use std::{
 
 use async_trait::async_trait;
 use growable_bloom_filter::GrowableBloom;
-use matrix_sdk_common::instant::Instant;
 use ruma::{
     canonical_json::{redact, RedactedBecause},
     events::{
@@ -30,6 +29,7 @@ use ruma::{
         AnySyncStateEvent, GlobalAccountDataEventType, RoomAccountDataEventType, StateEventType,
     },
     serde::Raw,
+    time::Instant,
     CanonicalJsonObject, EventId, OwnedEventId, OwnedMxcUri, OwnedRoomId, OwnedTransactionId,
     OwnedUserId, RoomId, RoomVersionId, TransactionId, UserId,
 };
diff --git a/crates/matrix-sdk-base/src/store/traits.rs b/crates/matrix-sdk-base/src/store/traits.rs
index 8bd300958..906ffdc27 100644
--- a/crates/matrix-sdk-base/src/store/traits.rs
+++ b/crates/matrix-sdk-base/src/store/traits.rs
@@ -23,7 +23,7 @@ use std::{
 use as_variant::as_variant;
 use async_trait::async_trait;
 use growable_bloom_filter::GrowableBloom;
-use matrix_sdk_common::{instant, AsyncTraitDeps};
+use matrix_sdk_common::AsyncTraitDeps;
 use ruma::{
     api::MatrixVersion,
     events::{
@@ -36,6 +36,7 @@ use ruma::{
         StateEventType, StaticEventContent, StaticStateEventContent,
     },
     serde::Raw,
+    time::SystemTime,
     EventId, OwnedEventId, OwnedMxcUri, OwnedRoomId, OwnedTransactionId, OwnedUserId, RoomId,
     TransactionId, UserId,
 };
@@ -951,7 +952,7 @@ impl ServerCapabilities {
         Self {
             versions: versions.iter().map(|item| item.to_string()).collect(),
             unstable_features,
-            last_fetch_ts: instant::now(),
+            last_fetch_ts: now_timestamp_ms(),
         }
     }
 
@@ -961,7 +962,7 @@ impl ServerCapabilities {
     /// [`Self::STALE_THRESHOLD`] milliseconds since the last time we stored
     /// it.
     pub fn maybe_decode(&self) -> Option<(Vec<MatrixVersion>, BTreeMap<String, bool>)> {
-        if instant::now() - self.last_fetch_ts >= Self::STALE_THRESHOLD {
+        if now_timestamp_ms() - self.last_fetch_ts >= Self::STALE_THRESHOLD {
             None
         } else {
             Some((
@@ -972,6 +973,15 @@ impl ServerCapabilities {
     }
 }
 
+/// Get the current timestamp as the number of milliseconds since Unix Epoch.
+fn now_timestamp_ms() -> f64 {
+    SystemTime::now()
+        .duration_since(SystemTime::UNIX_EPOCH)
+        .expect("System clock was before 1970.")
+        .as_secs_f64()
+        * 1000.0
+}
+
 /// A value for key-value data that should be persisted into the store.
 #[derive(Debug, Clone)]
 pub enum StateStoreDataValue {
@@ -1276,23 +1286,21 @@ impl fmt::Debug for QueuedEvent {
 
 #[cfg(test)]
 mod tests {
-    use matrix_sdk_common::instant;
-
-    use super::ServerCapabilities;
+    use super::{now_timestamp_ms, ServerCapabilities};
 
     #[test]
     fn test_stale_server_capabilities() {
         let mut caps = ServerCapabilities {
             versions: Default::default(),
             unstable_features: Default::default(),
-            last_fetch_ts: instant::now() - ServerCapabilities::STALE_THRESHOLD - 1.0,
+            last_fetch_ts: now_timestamp_ms() - ServerCapabilities::STALE_THRESHOLD - 1.0,
         };
 
         // Definitely stale.
         assert!(caps.maybe_decode().is_none());
 
         // Definitely not stale.
-        caps.last_fetch_ts = instant::now() - 1.0;
+        caps.last_fetch_ts = now_timestamp_ms() - 1.0;
         assert!(caps.maybe_decode().is_some());
     }
 }
diff --git a/crates/matrix-sdk-common/Cargo.toml b/crates/matrix-sdk-common/Cargo.toml
index 86f84132a..87d52a1f3 100644
--- a/crates/matrix-sdk-common/Cargo.toml
+++ b/crates/matrix-sdk-common/Cargo.toml
@@ -16,13 +16,12 @@ default-target = "x86_64-unknown-linux-gnu"
 targets = ["x86_64-unknown-linux-gnu", "wasm32-unknown-unknown"]
 
 [features]
-js = ["instant/wasm-bindgen", "wasm-bindgen-futures"]
+js = ["wasm-bindgen-futures"]
 uniffi = ["dep:uniffi"]
 
 [dependencies]
 async-trait = { workspace = true }
 futures-core = { workspace = true }
-instant = "0.1.12"
 ruma = { workspace = true }
 serde = { workspace = true }
 serde_json = { workspace = true }
diff --git a/crates/matrix-sdk-common/src/failures_cache.rs b/crates/matrix-sdk-common/src/failures_cache.rs
index bc8642ca6..cbed0930f 100644
--- a/crates/matrix-sdk-common/src/failures_cache.rs
+++ b/crates/matrix-sdk-common/src/failures_cache.rs
@@ -23,7 +23,7 @@ use std::{
     time::Duration,
 };
 
-use super::instant::Instant;
+use ruma::time::Instant;
 
 const MAX_DELAY: u64 = 15 * 60;
 const MULTIPLIER: u64 = 15;
diff --git a/crates/matrix-sdk-common/src/lib.rs b/crates/matrix-sdk-common/src/lib.rs
index 2e81ab8cc..451a86fa1 100644
--- a/crates/matrix-sdk-common/src/lib.rs
+++ b/crates/matrix-sdk-common/src/lib.rs
@@ -19,8 +19,6 @@ use std::pin::Pin;
 
 use futures_core::Future;
 #[doc(no_inline)]
-pub use instant;
-#[doc(no_inline)]
 pub use ruma;
 
 pub mod debug;
diff --git a/crates/matrix-sdk-common/src/tracing_timer.rs b/crates/matrix-sdk-common/src/tracing_timer.rs
index afd65cadc..7ec5f35ad 100644
--- a/crates/matrix-sdk-common/src/tracing_timer.rs
+++ b/crates/matrix-sdk-common/src/tracing_timer.rs
@@ -114,7 +114,7 @@ mod tests {
         mod time123 {
             pub async fn run() {
                 let _timer_guard = timer!(tracing::Level::DEBUG, "test");
-                tokio::time::sleep(instant::Duration::from_millis(123)).await;
+                tokio::time::sleep(ruma::time::Duration::from_millis(123)).await;
                 // Displays: 2023-08-25T15:18:31.169498Z DEBUG
                 // matrix_sdk_common::tracing_timer::tests: test finished in
                 // 124ms
@@ -127,7 +127,7 @@ mod tests {
         let _guard = span.enter();
 
         let _timer_guard = timer!("in span");
-        tokio::time::sleep(instant::Duration::from_millis(256)).await;
+        tokio::time::sleep(ruma::time::Duration::from_millis(256)).await;
 
         tracing::warn!("Test about to finish.");
         // Displays: 2023-08-25T15:18:31.427070Z DEBUG le 256ms span:
diff --git a/crates/matrix-sdk-crypto/src/session_manager/sessions.rs b/crates/matrix-sdk-crypto/src/session_manager/sessions.rs
index 0ef089e7e..53a3dfce8 100644
--- a/crates/matrix-sdk-crypto/src/session_manager/sessions.rs
+++ b/crates/matrix-sdk-crypto/src/session_manager/sessions.rs
@@ -832,8 +832,7 @@ mod tests {
     #[async_test]
     #[cfg(target_os = "linux")]
     async fn test_session_unwedging() {
-        use matrix_sdk_common::instant::{Duration, SystemTime};
-        use ruma::SecondsSinceUnixEpoch;
+        use ruma::{time::SystemTime, SecondsSinceUnixEpoch};
 
         let (manager, _identity_manager) = session_manager_test_helper().await;
         let mut bob = bob_account();
diff --git a/crates/matrix-sdk-crypto/src/verification/machine.rs b/crates/matrix-sdk-crypto/src/verification/machine.rs
index 0d68c9a92..e2817e2d1 100644
--- a/crates/matrix-sdk-crypto/src/verification/machine.rs
+++ b/crates/matrix-sdk-crypto/src/verification/machine.rs
@@ -642,7 +642,7 @@ mod tests {
     async fn timing_out() {
         use std::time::Duration;
 
-        use matrix_sdk_common::instant::Instant;
+        use ruma::time::Instant;
 
         let (alice_machine, bob) = setup_verification_machine().await;
         let alice = alice_machine.get_sas(bob.user_id(), bob.flow_id().as_str()).unwrap();
diff --git a/crates/matrix-sdk-crypto/src/verification/requests.rs b/crates/matrix-sdk-crypto/src/verification/requests.rs
index ab3f3053a..6fe9fe227 100644
--- a/crates/matrix-sdk-crypto/src/verification/requests.rs
+++ b/crates/matrix-sdk-crypto/src/verification/requests.rs
@@ -18,7 +18,6 @@ use as_variant::as_variant;
 use eyeball::{ObservableWriteGuard, SharedObservable, WeakObservable};
 use futures_core::Stream;
 use futures_util::StreamExt;
-use matrix_sdk_common::instant::Instant;
 #[cfg(feature = "qrcode")]
 use matrix_sdk_qrcode::QrVerificationData;
 use ruma::{
@@ -34,6 +33,7 @@ use ruma::{
         room::message::KeyVerificationRequestEventContent,
         AnyMessageLikeEventContent, AnyToDeviceEventContent,
     },
+    time::Instant,
     to_device::DeviceIdOrAllDevices,
     DeviceId, MilliSecondsSinceUnixEpoch, OwnedDeviceId, OwnedUserId, RoomId, TransactionId,
     UserId,
diff --git a/crates/matrix-sdk-crypto/src/verification/sas/inner_sas.rs b/crates/matrix-sdk-crypto/src/verification/sas/inner_sas.rs
index e2ccfb4d2..300f73a15 100644
--- a/crates/matrix-sdk-crypto/src/verification/sas/inner_sas.rs
+++ b/crates/matrix-sdk-crypto/src/verification/sas/inner_sas.rs
@@ -16,7 +16,7 @@ use std::sync::Arc;
 
 use as_variant::as_variant;
 #[cfg(test)]
-use matrix_sdk_common::instant::Instant;
+use ruma::time::Instant;
 use ruma::{
     events::key::verification::{cancel::CancelCode, ShortAuthenticationString},
     TransactionId, UserId,
diff --git a/crates/matrix-sdk-crypto/src/verification/sas/mod.rs b/crates/matrix-sdk-crypto/src/verification/sas/mod.rs
index 75c6d0c7b..c0fbe5506 100644
--- a/crates/matrix-sdk-crypto/src/verification/sas/mod.rs
+++ b/crates/matrix-sdk-crypto/src/verification/sas/mod.rs
@@ -308,7 +308,7 @@ impl Sas {
 
     #[cfg(test)]
     #[allow(dead_code)]
-    pub(crate) fn set_creation_time(&self, time: matrix_sdk_common::instant::Instant) {
+    pub(crate) fn set_creation_time(&self, time: ruma::time::Instant) {
         self.inner.update(|inner| {
             inner.set_creation_time(time);
         });
diff --git a/crates/matrix-sdk-crypto/src/verification/sas/sas_state.rs b/crates/matrix-sdk-crypto/src/verification/sas/sas_state.rs
index fa86f96b6..295335bb7 100644
--- a/crates/matrix-sdk-crypto/src/verification/sas/sas_state.rs
+++ b/crates/matrix-sdk-crypto/src/verification/sas/sas_state.rs
@@ -18,7 +18,6 @@ use std::{
     time::Duration,
 };
 
-use matrix_sdk_common::instant::Instant;
 use ruma::{
     events::{
         key::verification::{
@@ -40,6 +39,7 @@ use ruma::{
         AnyMessageLikeEventContent, AnyToDeviceEventContent,
     },
     serde::Base64,
+    time::Instant,
     DeviceId, OwnedTransactionId, TransactionId, UserId,
 };
 use serde::{Deserialize, Serialize};
diff --git a/crates/matrix-sdk-indexeddb/Cargo.toml b/crates/matrix-sdk-indexeddb/Cargo.toml
index a2249b490..f224453d0 100644
--- a/crates/matrix-sdk-indexeddb/Cargo.toml
+++ b/crates/matrix-sdk-indexeddb/Cargo.toml
@@ -58,6 +58,7 @@ rand = { workspace = true }
 tracing-subscriber = { workspace = true, features = ["registry", "tracing-log"] }
 uuid = "1.3.0"
 wasm-bindgen-test = "0.3.33"
+web-sys = { version = "0.3.57", features = ["IdbKeyRange", "Window", "Performance"] }
 
 [lints]
 workspace = true
diff --git a/crates/matrix-sdk/CHANGELOG.md b/crates/matrix-sdk/CHANGELOG.md
index 701f7c5bd..025535fff 100644
--- a/crates/matrix-sdk/CHANGELOG.md
+++ b/crates/matrix-sdk/CHANGELOG.md
@@ -22,6 +22,7 @@ Breaking changes:
 - The widget capabilities in the FFI now need two additional flags: `update_delayed_event`, `send_delayed_event`.
 - `Room::event` now takes an optional `RequestConfig` to allow for tweaking the network behavior.
 - `NotificationSettings::subscribe_to_changes` has been removed.
+- The `instant` module was removed, use the `ruma::time` module instead.
 
 Additions:
 
diff --git a/crates/matrix-sdk/README.md b/crates/matrix-sdk/README.md
index adfca9bd7..5015e5e92 100644
--- a/crates/matrix-sdk/README.md
+++ b/crates/matrix-sdk/README.md
@@ -62,7 +62,7 @@ The following crate feature flags are available:
 | `eyre`              |   No    | Better logging for event handlers that return `eyre::Result`                                                               |
 | `image-proc`        |   No    | Image processing for generating thumbnails                                                                                 |
 | `image-rayon`       |   No    | Enables faster image processing                                                                                            |
-| `js`                |   No    | Enables JavaScript API usage for things like the current system time on WASM (does nothing on other targets)               |
+| `js`                |   No    | Enables JavaScript API usage on WASM (does nothing on other targets)                                                       |
 | `markdown`          |   No    | Support for sending Markdown-formatted messages                                                                            |
 | `qrcode`            |   Yes   | QR code verification support                                                                                               |
 | `sqlite`            |   Yes   | Persistent storage of state and E2EE data (optionally, if feature `e2e-encryption` is enabled), via SQLite available on system  |
diff --git a/crates/matrix-sdk/src/client/mod.rs b/crates/matrix-sdk/src/client/mod.rs
index a96f8d072..ccc4892e9 100644
--- a/crates/matrix-sdk/src/client/mod.rs
+++ b/crates/matrix-sdk/src/client/mod.rs
@@ -39,7 +39,6 @@ use matrix_sdk_base::{
     BaseClient, RoomInfoNotableUpdate, RoomState, RoomStateFilter, SendOutsideWasm, SessionMeta,
     StateStoreDataKey, StateStoreDataValue, SyncOutsideWasm,
 };
-use matrix_sdk_common::instant::Instant;
 #[cfg(feature = "e2e-encryption")]
 use ruma::events::{room::encryption::RoomEncryptionEventContent, InitialStateEvent};
 use ruma::{
@@ -66,6 +65,7 @@ use ruma::{
     },
     assign,
     push::Ruleset,
+    time::Instant,
     DeviceId, OwnedDeviceId, OwnedEventId, OwnedRoomId, OwnedServerName, RoomAliasId, RoomId,
     RoomOrAliasId, ServerName, UInt, UserId,
 };
diff --git a/crates/matrix-sdk/src/room/mod.rs b/crates/matrix-sdk/src/room/mod.rs
index 43a10aac9..6ddab10c8 100644
--- a/crates/matrix-sdk/src/room/mod.rs
+++ b/crates/matrix-sdk/src/room/mod.rs
@@ -18,7 +18,6 @@ use matrix_sdk_base::{
     deserialized_responses::{
         RawAnySyncOrStrippedState, RawSyncOrStrippedState, SyncOrStrippedState, TimelineEvent,
     },
-    instant::Instant,
     store::StateStoreExt,
     ComposerDraft, RoomInfoNotableUpdateReasons, RoomMemberships, StateChanges, StateStoreDataKey,
     StateStoreDataValue,
@@ -80,6 +79,7 @@ use ruma::{
     },
     push::{Action, PushConditionRoomCtx},
     serde::Raw,
+    time::Instant,
     EventId, Int, MatrixToUri, MatrixUri, MxcUri, OwnedEventId, OwnedRoomId, OwnedServerName,
     OwnedTransactionId, OwnedUserId, RoomId, TransactionId, UInt, UserId,
 };
diff --git a/crates/matrix-sdk/src/sync.rs b/crates/matrix-sdk/src/sync.rs
index 1aa3792c2..a9f490aa9 100644
--- a/crates/matrix-sdk/src/sync.rs
+++ b/crates/matrix-sdk/src/sync.rs
@@ -23,13 +23,13 @@ use std::{
 pub use matrix_sdk_base::sync::*;
 use matrix_sdk_base::{
     debug::{DebugInvitedRoom, DebugListOfRawEventsNoId},
-    instant::Instant,
     sync::SyncResponse as BaseSyncResponse,
 };
 use ruma::{
     api::client::sync::sync_events::{self, v3::InvitedRoom},
     events::{presence::PresenceEvent, AnyGlobalAccountDataEvent, AnyToDeviceEvent},
     serde::Raw,
+    time::Instant,
     OwnedRoomId, RoomId,
 };
 use tracing::{debug, error, warn};


Test patch:
diff --git a/crates/matrix-sdk/tests/integration/room/beacon/mod.rs b/crates/matrix-sdk/tests/integration/room/beacon/mod.rs
index d9e95c5af..d83bfda7c 100644
--- a/crates/matrix-sdk/tests/integration/room/beacon/mod.rs
+++ b/crates/matrix-sdk/tests/integration/room/beacon/mod.rs
@@ -1,8 +1,8 @@
 use std::time::{Duration, UNIX_EPOCH};
 
-use matrix_sdk::{config::SyncSettings, instant::SystemTime};
+use matrix_sdk::config::SyncSettings;
 use matrix_sdk_test::{async_test, mocks::mock_encryption_state, test_json, DEFAULT_TEST_ROOM_ID};
-use ruma::event_id;
+use ruma::{event_id, time::SystemTime};
 use serde_json::json;
 use wiremock::{
     matchers::{body_partial_json, header, method, path_regex},