Skip to content

Commit cb3f5ec

Browse files
committed
Convert some async functions into future_to_promise
`async` doesn't work well in OlmMachine, because it might get dropped before the function starts. This also lays groundwork for the forthcoming logging changes.
1 parent 23aeaea commit cb3f5ec

File tree

4 files changed

+74
-50
lines changed

4 files changed

+74
-50
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ thiserror = "2.0.12"
7474
tracing = { version = "0.1.36", default-features = false, features = ["std"] }
7575
tracing-subscriber = { version = "0.3.14", default-features = false, features = ["registry", "std", "ansi"] }
7676
url = "2.5.0"
77-
wasm-bindgen = "0.2.89"
77+
wasm-bindgen = "0.2.100"
7878
wasm-bindgen-futures = "0.4.33"
7979
zeroize = "1.6.0"
8080
wasm-bindgen-test = "0.3.37"

src/machine.rs

Lines changed: 62 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ impl OlmMachine {
6060
/// the `initialize` method.
6161
///
6262
/// Why this pattern? `initialize` returns a `Promise`. Returning a
63-
// `Promise` from a constructor is not idiomatic in JavaScript.
63+
/// `Promise` from a constructor is not idiomatic in JavaScript.
6464
#[wasm_bindgen(constructor)]
6565
pub fn new() -> Result<OlmMachine, JsError> {
6666
Err(JsError::new("To build an `OlmMachine`, please use the `initialize` method"))
@@ -87,17 +87,19 @@ impl OlmMachine {
8787
///
8888
/// * `store_passphrase` - The passphrase that should be used to encrypt the
8989
/// IndexedDB-based store.
90-
pub async fn initialize(
90+
#[wasm_bindgen(unchecked_return_type = "Promise<OlmMachine>")]
91+
pub fn initialize(
9192
user_id: &identifiers::UserId,
9293
device_id: &identifiers::DeviceId,
9394
store_name: Option<String>,
9495
store_passphrase: Option<String>,
95-
) -> Result<JsValue, JsValue> {
96+
) -> Promise {
9697
let user_id = user_id.inner.clone();
9798
let device_id = device_id.inner.clone();
98-
99-
let store_handle = StoreHandle::open(store_name, store_passphrase).await?;
100-
Self::init_helper(user_id, device_id, store_handle).await
99+
future_to_promise(async {
100+
let store_handle = StoreHandle::open(store_name, store_passphrase).await?;
101+
Self::init_helper(user_id, device_id, store_handle).await
102+
})
101103
}
102104

103105
/// Create a new `OlmMachine` backed by an existing store.
@@ -112,33 +114,34 @@ impl OlmMachine {
112114
///
113115
/// * `store_handle` - the connection to the crypto store to be used for
114116
/// this machine.
115-
#[wasm_bindgen(js_name = "initFromStore")]
116-
pub async fn init_from_store(
117+
#[wasm_bindgen(js_name = "initFromStore", unchecked_return_type = "Promise<OlmMachine>")]
118+
pub fn init_from_store(
117119
user_id: &identifiers::UserId,
118120
device_id: &identifiers::DeviceId,
119121
store_handle: &StoreHandle,
120-
) -> Result<JsValue, JsValue> {
122+
) -> Promise {
121123
let user_id = user_id.inner.clone();
122124
let device_id = device_id.inner.clone();
123-
Self::init_helper(user_id, device_id, store_handle.clone()).await
125+
let store_handle = store_handle.clone();
126+
future_to_promise(async move {
127+
Self::init_helper(user_id, device_id, store_handle).await
128+
})
124129
}
125130

126131
async fn init_helper(
127132
user_id: OwnedUserId,
128133
device_id: OwnedDeviceId,
129134
store_handle: StoreHandle,
130-
) -> Result<JsValue, JsValue> {
135+
) -> Result<OlmMachine, JsError> {
131136
Ok(OlmMachine {
132137
inner: matrix_sdk_crypto::OlmMachine::with_store(
133138
user_id.as_ref(),
134139
device_id.as_ref(),
135140
store_handle,
136141
None,
137142
)
138-
.await
139-
.map_err(JsError::from)?,
140-
}
141-
.into())
143+
.await?,
144+
})
142145
}
143146

144147
/// The unique user ID that owns this `OlmMachine` instance.
@@ -266,10 +269,13 @@ impl OlmMachine {
266269
///
267270
/// All users *whose device lists we are tracking* are flagged as needing a
268271
/// key query. Users whose devices we are not tracking are ignored.
269-
#[wasm_bindgen(js_name = "markAllTrackedUsersAsDirty")]
270-
pub async fn mark_all_tracked_users_as_dirty(&self) -> Result<(), JsError> {
271-
self.inner.mark_all_tracked_users_as_dirty().await?;
272-
Ok(())
272+
#[wasm_bindgen(js_name = "markAllTrackedUsersAsDirty", unchecked_return_type = "Promise<void>")]
273+
pub fn mark_all_tracked_users_as_dirty(&self) -> Promise {
274+
let me = self.inner.clone();
275+
future_to_promise(async move {
276+
me.mark_all_tracked_users_as_dirty().await?;
277+
Ok(JsValue::UNDEFINED)
278+
})
273279
}
274280

275281
/// Handle to-device events and one-time key counts from a sync
@@ -577,9 +583,15 @@ impl OlmMachine {
577583
///
578584
/// **Warning**: Only export this and share it with a trusted recipient,
579585
/// i.e. if an existing device is sharing this with a new device.
580-
#[wasm_bindgen(js_name = "exportSecretsBundle")]
581-
pub async fn export_secrets_bundle(&self) -> Result<store::SecretsBundle, JsError> {
582-
Ok(self.inner.store().export_secrets_bundle().await?.into())
586+
#[wasm_bindgen(
587+
js_name = "exportSecretsBundle",
588+
unchecked_return_type = "Promise<SecretsBundle>"
589+
)]
590+
pub async fn export_secrets_bundle(&self) -> Promise {
591+
let me = self.inner.clone();
592+
future_to_promise(async move {
593+
Ok(store::SecretsBundle::from(me.store().export_secrets_bundle().await?))
594+
})
583595
}
584596

585597
/// Import and persists secrets from a {@link SecretsBundle}.
@@ -597,10 +609,13 @@ impl OlmMachine {
597609
///
598610
/// The provided `SecretsBundle` is freed by this method; be careful not to
599611
/// use it once this method has been called.
600-
#[wasm_bindgen(js_name = "importSecretsBundle")]
601-
pub async fn import_secrets_bundle(&self, bundle: store::SecretsBundle) -> Result<(), JsError> {
602-
self.inner.store().import_secrets_bundle(&bundle.inner).await?;
603-
Ok(())
612+
#[wasm_bindgen(js_name = "importSecretsBundle", unchecked_return_type = "Promise<void>")]
613+
pub fn import_secrets_bundle(&self, bundle: store::SecretsBundle) -> Promise {
614+
let me = self.inner.clone();
615+
future_to_promise(async move {
616+
me.store().import_secrets_bundle(&bundle.inner).await?;
617+
Ok(JsValue::UNDEFINED)
618+
})
604619
}
605620

606621
/// Export all the private cross signing keys we have.
@@ -1550,13 +1565,17 @@ impl OlmMachine {
15501565
/// # Returns
15511566
///
15521567
/// `Promise<RoomSettings|undefined>`
1553-
#[wasm_bindgen(js_name = "getRoomSettings")]
1554-
pub async fn get_room_settings(
1555-
&self,
1556-
room_id: &identifiers::RoomId,
1557-
) -> Result<JsValue, JsError> {
1558-
let result = self.inner.room_settings(&room_id.inner).await?;
1559-
Ok(result.map(RoomSettings::from).into())
1568+
#[wasm_bindgen(
1569+
js_name = "getRoomSettings",
1570+
unchecked_return_type = "Promise<RoomSettings|undefined>"
1571+
)]
1572+
pub async fn get_room_settings(&self, room_id: &identifiers::RoomId) -> Promise {
1573+
let me = self.inner.clone();
1574+
let room = room_id.inner.clone();
1575+
future_to_promise(async move {
1576+
let result = me.room_settings(&room).await?;
1577+
Ok(result.map(RoomSettings::from))
1578+
})
15601579
}
15611580

15621581
/// Store encryption settings for the given room.
@@ -1568,14 +1587,19 @@ impl OlmMachine {
15681587
/// If the settings are valid, they will be persisted to the crypto store.
15691588
/// These settings are not used directly by this library, but the saved
15701589
/// settings can be retrieved via {@link getRoomSettings}.
1571-
#[wasm_bindgen(js_name = "setRoomSettings")]
1572-
pub async fn set_room_settings(
1590+
#[wasm_bindgen(js_name = "setRoomSettings", unchecked_return_type = "Promise<void>")]
1591+
pub fn set_room_settings(
15731592
&self,
15741593
room_id: &identifiers::RoomId,
15751594
room_settings: &RoomSettings,
1576-
) -> Result<(), JsError> {
1577-
self.inner.set_room_settings(&room_id.inner, &room_settings.into()).await?;
1578-
Ok(())
1595+
) -> Promise {
1596+
let me = self.inner.clone();
1597+
let room = room_id.inner.clone();
1598+
let room_settings = room_settings.into();
1599+
future_to_promise(async move {
1600+
me.set_room_settings(&room, &room_settings).await?;
1601+
Ok(JsValue::UNDEFINED)
1602+
})
15791603
}
15801604

15811605
/// Manage dehydrated devices

tests/dehydrated_devices.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ describe("dehydrated devices", () => {
3232

3333
await dehydratedDevices.saveDehydratedDeviceKey(key);
3434

35-
const loaded_key: DehydratedDeviceKey = await dehydratedDevices.getDehydratedDeviceKey();
35+
const loaded_key = await dehydratedDevices.getDehydratedDeviceKey();
3636

37-
expect(key.toBase64()).toEqual(loaded_key.toBase64());
37+
expect(key.toBase64()).toEqual(loaded_key!.toBase64());
3838
});
3939

4040
test("can delete a previously saved dehydrated device key", async () => {

tests/machine.test.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,7 +1422,7 @@ describe(OlmMachine.name, () => {
14221422
expect(request).toBeInstanceOf(KeysQueryRequest);
14231423

14241424
await secondMachine.markRequestAsSent(
1425-
request.id,
1425+
request.id!,
14261426
RequestType.KeysQuery,
14271427
JSON.stringify(hypotheticalResponse),
14281428
);
@@ -1568,10 +1568,10 @@ describe(OlmMachine.name, () => {
15681568
await m.setRoomSettings(new RoomId("!test:room"), settings);
15691569

15701570
const loadedSettings = await m.getRoomSettings(new RoomId("!test:room"));
1571-
expect(loadedSettings.algorithm).toEqual(EncryptionAlgorithm.MegolmV1AesSha2);
1572-
expect(loadedSettings.onlyAllowTrustedDevices).toBe(true);
1573-
expect(loadedSettings.sessionRotationPeriodMs).toEqual(10000);
1574-
expect(loadedSettings.sessionRotationPeriodMessages).toEqual(1234);
1571+
expect(loadedSettings!.algorithm).toEqual(EncryptionAlgorithm.MegolmV1AesSha2);
1572+
expect(loadedSettings!.onlyAllowTrustedDevices).toBe(true);
1573+
expect(loadedSettings!.sessionRotationPeriodMs).toEqual(10000);
1574+
expect(loadedSettings!.sessionRotationPeriodMessages).toEqual(1234);
15751575
});
15761576

15771577
test("Should reject unsupported algorithms", async () => {
@@ -1596,10 +1596,10 @@ describe(OlmMachine.name, () => {
15961596

15971597
// Check the old settings persist
15981598
const loadedSettings = await m.getRoomSettings(new RoomId("!test:room"));
1599-
expect(loadedSettings.algorithm).toEqual(EncryptionAlgorithm.MegolmV1AesSha2);
1600-
expect(loadedSettings.onlyAllowTrustedDevices).toBe(true);
1601-
expect(loadedSettings.sessionRotationPeriodMs).toEqual(100);
1602-
expect(loadedSettings.sessionRotationPeriodMessages).toEqual(10);
1599+
expect(loadedSettings!.algorithm).toEqual(EncryptionAlgorithm.MegolmV1AesSha2);
1600+
expect(loadedSettings!.onlyAllowTrustedDevices).toBe(true);
1601+
expect(loadedSettings!.sessionRotationPeriodMs).toEqual(100);
1602+
expect(loadedSettings!.sessionRotationPeriodMessages).toEqual(10);
16031603
});
16041604

16051605
test("Should ignore no-op changes", async () => {

0 commit comments

Comments
 (0)