Skip to content

Commit

Permalink
feat: Remove the need for the downcast function.
Browse files Browse the repository at this point in the history
The `downcast` function is removed in this patch because it was
incompatible with JS code minifier.

Instead, we now rely on the new `wasm_bindgen::convert::TryFromJsValue`
API.

This patch also replaces `&Array` by `Vec<T>`. It's fine, except that JS
arrays that are sent to Rust are going to be dropped after the functions
return. It's quite unsual for JS, but documentations have been updated
accordingly.
  • Loading branch information
Hywan committed Jan 8, 2024
1 parent c1a12eb commit c556316
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 80 deletions.
29 changes: 0 additions & 29 deletions src/js.rs

This file was deleted.

1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ pub mod events;
mod future;
pub mod identifiers;
pub mod identities;
mod js;
pub mod libolm_migration;
pub mod machine;
mod macros;
Expand Down
63 changes: 31 additions & 32 deletions src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,15 @@ use matrix_sdk_crypto::{
use serde_json::json;
use serde_wasm_bindgen;
use tracing::warn;
use wasm_bindgen::prelude::*;
use wasm_bindgen::{convert::TryFromJsValue, prelude::*};
use wasm_bindgen_futures::{spawn_local, JsFuture};

use crate::{
backup::{BackupDecryptionKey, BackupKeys, RoomKeyCounts},
device, encryption,
error::MegolmDecryptionError,
future::{future_to_promise, future_to_promise_with_custom_error},
identifiers, identities,
js::downcast,
olm, requests,
identifiers, identities, olm, requests,
requests::{outgoing_request_to_js_value, CrossSigningBootstrapRequests, ToDeviceRequest},
responses::{self, response_from_string},
store,
Expand Down Expand Up @@ -227,16 +225,19 @@ impl OlmMachine {
/// "changed" notification for that user in the future.
///
/// Users that were already in the list are unaffected.
///
/// `users` is going to be dropped on the JS part after the function
/// returns. Be careful to not used `users` after that.
#[wasm_bindgen(js_name = "updateTrackedUsers")]
pub fn update_tracked_users(&self, users: &Array) -> Result<Promise, JsError> {
let users = user_ids_to_owned_user_ids(users)?;
pub fn update_tracked_users(&self, users: Vec<identifiers::UserId>) -> Promise {
let users = users.iter().map(|user| user.inner.clone()).collect::<Vec<_>>();

let me = self.inner.clone();

Ok(future_to_promise(async move {
future_to_promise(async move {
me.update_tracked_users(users.iter().map(AsRef::as_ref)).await?;
Ok(JsValue::UNDEFINED)
}))
})
}

/// Handle to-device events and one-time key counts from a sync
Expand Down Expand Up @@ -636,21 +637,24 @@ impl OlmMachine {
/// time is in flight for the same room, e.g. using a lock.
///
/// Returns an array of `ToDeviceRequest`s.
///
/// `users` is going to be dropped on the JS part after the function
/// returns. Be careful to not used `users` after that.
#[wasm_bindgen(js_name = "shareRoomKey")]
pub fn share_room_key(
&self,
room_id: &identifiers::RoomId,
users: &Array,
users: Vec<identifiers::UserId>,
encryption_settings: &encryption::EncryptionSettings,
) -> Result<Promise, JsError> {
) -> Promise {
let room_id = room_id.inner.clone();
let users = user_ids_to_owned_user_ids(users)?;
let users = users.iter().map(|user| user.inner.clone()).collect::<Vec<_>>();
let encryption_settings =
matrix_sdk_crypto::olm::EncryptionSettings::from(encryption_settings);

let me = self.inner.clone();

Ok(future_to_promise(async move {
future_to_promise(async move {
let to_device_requests = me
.share_room_key(&room_id, users.iter().map(AsRef::as_ref), encryption_settings)
.await?;
Expand All @@ -664,7 +668,7 @@ impl OlmMachine {
.into_iter()
.map(|td| ToDeviceRequest::try_from(td.deref()).map(JsValue::from))
.collect::<Result<Array, _>>()?)
}))
})
}

/// Generate an "out-of-band" key query request for the given set of users.
Expand All @@ -674,12 +678,15 @@ impl OlmMachine {
///
/// Returns a `KeysQueryRequest` object. The response of the request should
/// be passed to the `OlmMachine` with the `mark_request_as_sent`.
///
/// `users` is going to be dropped on the JS part after the function
/// returns. Be careful to not used `users` after that.
#[wasm_bindgen(js_name = "queryKeysForUsers")]
pub fn query_keys_for_users(
&self,
users: &Array,
users: Vec<identifiers::UserId>,
) -> Result<requests::KeysQueryRequest, JsError> {
let users = user_ids_to_owned_user_ids(users)?;
let users = users.iter().map(|user| user.inner.clone()).collect::<Vec<_>>();

let (request_id, request) =
self.inner.query_keys_for_users(users.iter().map(AsRef::as_ref));
Expand Down Expand Up @@ -712,13 +719,16 @@ impl OlmMachine {
/// `users` represents the list of users that we should check if
/// we lack a session with one of their devices. This can be an
/// empty iterator when calling this method between sync requests.
///
/// `users` is going to be dropped on the JS part after the function
/// returns. Be careful to not used `users` after that.
#[wasm_bindgen(js_name = "getMissingSessions")]
pub fn get_missing_sessions(&self, users: &Array) -> Result<Promise, JsError> {
let users = user_ids_to_owned_user_ids(users)?;
pub fn get_missing_sessions(&self, users: Vec<identifiers::UserId>) -> Promise {
let users = users.iter().map(|user| user.inner.clone()).collect::<Vec<_>>();

let me = self.inner.clone();

Ok(future_to_promise(async move {
future_to_promise(async move {
match me.get_missing_sessions(users.iter().map(AsRef::as_ref)).await? {
Some((transaction_id, keys_claim_request)) => {
Ok(JsValue::from(requests::KeysClaimRequest::try_from((
Expand All @@ -729,7 +739,7 @@ impl OlmMachine {

None => Ok(JsValue::NULL),
}
}))
})
}

/// Get a map holding all the devices of a user.
Expand Down Expand Up @@ -999,9 +1009,7 @@ impl OlmMachine {
let mut keys: BTreeMap<_, BTreeMap<_, _>> = BTreeMap::new();
for backed_up_room_keys_entry in backed_up_room_keys.entries() {
let backed_up_room_keys_entry: Array = backed_up_room_keys_entry?.dyn_into()?;
let room_id =
&downcast::<identifiers::RoomId>(&backed_up_room_keys_entry.get(0), "RoomId")?
.inner;
let room_id = identifiers::RoomId::try_from_js_value(backed_up_room_keys_entry.get(0))?;

let room_room_keys: Map = backed_up_room_keys_entry.get(1).dyn_into()?;

Expand All @@ -1011,7 +1019,7 @@ impl OlmMachine {
let key: BackedUpRoomKey =
serde_wasm_bindgen::from_value(room_room_keys_entry.get(1))?;

keys.entry(room_id.clone()).or_default().insert(session_id.into(), key);
keys.entry(room_id.inner.clone()).or_default().insert(session_id.into(), key);
}
}

Expand Down Expand Up @@ -1457,12 +1465,3 @@ pub(crate) async fn promise_result_to_future(
}
}
}

/// Helper function to take a Javascript array of `UserId`s and turn it into
/// a Rust `Vec` of `OwnedUserId`s
fn user_ids_to_owned_user_ids(users: &Array) -> Result<Vec<ruma::OwnedUserId>, JsError> {
users
.iter()
.map(|user| Ok(downcast::<identifiers::UserId>(&user, "UserId")?.inner.clone()))
.collect()
}
20 changes: 7 additions & 13 deletions src/sync_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use js_sys::Array;
use matrix_sdk_common::ruma;
use wasm_bindgen::prelude::*;

use crate::{identifiers, js::downcast};
use crate::identifiers;

/// Information on E2E device updates.
#[wasm_bindgen]
Expand All @@ -19,20 +19,14 @@ impl DeviceLists {
///
/// `changed` and `left` must be an array of `UserId`.
#[wasm_bindgen(constructor)]
pub fn new(changed: Option<Array>, left: Option<Array>) -> Result<DeviceLists, JsError> {
pub fn new(
changed: Option<Vec<identifiers::UserId>>,
left: Option<Vec<identifiers::UserId>>,
) -> Result<DeviceLists, JsError> {
let mut inner = ruma::api::client::sync::sync_events::DeviceLists::default();

inner.changed = changed
.unwrap_or_default()
.iter()
.map(|user| Ok(downcast::<identifiers::UserId>(&user, "UserId")?.inner.clone()))
.collect::<Result<Vec<ruma::OwnedUserId>, JsError>>()?;

inner.left = left
.unwrap_or_default()
.iter()
.map(|user| Ok(downcast::<identifiers::UserId>(&user, "UserId")?.inner.clone()))
.collect::<Result<Vec<ruma::OwnedUserId>, JsError>>()?;
inner.changed = changed.unwrap_or_default().iter().map(|user| user.inner.clone()).collect();
inner.left = left.unwrap_or_default().iter().map(|user| user.inner.clone()).collect();

Ok(Self { inner })
}
Expand Down
9 changes: 4 additions & 5 deletions tests/machine.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ describe(OlmMachine.name, () => {
test("can update tracked users", async () => {
const m = await machine();

expect(await m.updateTrackedUsers([user])).toStrictEqual(undefined);
expect(await m.updateTrackedUsers([new UserId("@alice:example.org")])).toStrictEqual(undefined);
});

test("can receive sync changes", async () => {
Expand Down Expand Up @@ -509,9 +509,7 @@ describe(OlmMachine.name, () => {
});

test("can share a room key", async () => {
const otherUsers = [new UserId("@example:localhost")];

const requests = await m.shareRoomKey(room, otherUsers, new EncryptionSettings());
const requests = await m.shareRoomKey(room, [new UserId("@example:localhost")], new EncryptionSettings());

expect(requests).toHaveLength(1);
expect(requests[0]).toBeInstanceOf(ToDeviceRequest);
Expand All @@ -524,7 +522,8 @@ describe(OlmMachine.name, () => {
expect(messageContent["org.matrix.msgid"]).toBeDefined();

await m.markRequestAsSent(requests[0].id, RequestType.ToDevice, "{}");
const requestsAfterMarkedAsSent = await m.shareRoomKey(room, otherUsers, new EncryptionSettings());

const requestsAfterMarkedAsSent = await m.shareRoomKey(room, [new UserId("@example:localhost")], new EncryptionSettings());
expect(requestsAfterMarkedAsSent).toHaveLength(0);
});

Expand Down

0 comments on commit c556316

Please sign in to comment.