1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-11-25 05:23:13 +03:00

Make sure to drop references to user device lists (#3610)

Empirically, this seems to fix some problems with leaking references to
IndexedDB.
This commit is contained in:
Richard van der Hoff
2023-07-20 09:47:30 +01:00
committed by GitHub
parent 66492e7ba8
commit 7dffd8ffd3

View File

@@ -296,15 +296,31 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
*/ */
private async getUserDevices(userId: string): Promise<Map<string, Device>> { private async getUserDevices(userId: string): Promise<Map<string, Device>> {
const rustUserId = new RustSdkCryptoJs.UserId(userId); const rustUserId = new RustSdkCryptoJs.UserId(userId);
const devices: RustSdkCryptoJs.UserDevices = await this.olmMachine.getUserDevices(rustUserId);
return new Map( // For reasons I don't really understand, the Javascript FinalizationRegistry doesn't seem to run the
devices // registered callbacks when `userDevices` goes out of scope, nor when the individual devices in the array
.devices() // returned by `userDevices.devices` do so.
.map((device: RustSdkCryptoJs.Device) => [ //
device.deviceId.toString(), // This is particularly problematic, because each of those structures holds a reference to the
rustDeviceToJsDevice(device, rustUserId), // VerificationMachine, which in turn holds a reference to the IndexeddbCryptoStore. Hence, we end up leaking
]), // open connections to the crypto store, which means the store can't be deleted on logout.
); //
// To fix this, we explicitly call `.free` on each of the objects, which tells the rust code to drop the
// allocated memory and decrement the refcounts for the crypto store.
const userDevices: RustSdkCryptoJs.UserDevices = await this.olmMachine.getUserDevices(rustUserId);
try {
const deviceArray: RustSdkCryptoJs.Device[] = userDevices.devices();
try {
return new Map(
deviceArray.map((device) => [device.deviceId.toString(), rustDeviceToJsDevice(device, rustUserId)]),
);
} finally {
deviceArray.forEach((d) => d.free());
}
} finally {
userDevices.free();
}
} }
/** /**