1
0
mirror of https://github.com/element-hq/element-web.git synced 2025-08-09 14:42:51 +03:00

Switch from defer to Promise.withResolvers (#29078)

* Switch from defer to PromiseWithResolvers

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Add modernizr check

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski
2025-05-08 11:03:43 +01:00
committed by GitHub
parent 0f783ede5e
commit a3f5d207de
34 changed files with 61 additions and 89 deletions

View File

@@ -10,7 +10,6 @@ Please see LICENSE files in the repository root for full details.
import React, { StrictMode } from "react"; import React, { StrictMode } from "react";
import { createRoot, type Root } from "react-dom/client"; import { createRoot, type Root } from "react-dom/client";
import classNames from "classnames"; import classNames from "classnames";
import { type IDeferred, defer } from "matrix-js-sdk/src/utils";
import { TypedEventEmitter } from "matrix-js-sdk/src/matrix"; import { TypedEventEmitter } from "matrix-js-sdk/src/matrix";
import { Glass, TooltipProvider } from "@vector-im/compound-web"; import { Glass, TooltipProvider } from "@vector-im/compound-web";
@@ -70,7 +69,7 @@ export interface IModal<C extends ComponentType> {
/** A deferred to resolve when the dialog closes, with the results as provided by /** A deferred to resolve when the dialog closes, with the results as provided by
* the call to {@link close} (normally from the `onFinished` callback). * the call to {@link close} (normally from the `onFinished` callback).
*/ */
deferred?: IDeferred<OnFinishedParams<C> | []>; deferred?: PromiseWithResolvers<OnFinishedParams<C> | []>;
} }
/** The result of {@link Modal.createDialog}. /** The result of {@link Modal.createDialog}.
@@ -254,7 +253,7 @@ export class ModalManager extends TypedEventEmitter<ModalManagerEvent, HandlerMa
} }
private getCloseFn<C extends ComponentType>(modal: IModal<C>): [IHandle<C>["close"], IHandle<C>["finished"]] { private getCloseFn<C extends ComponentType>(modal: IModal<C>): [IHandle<C>["close"], IHandle<C>["finished"]] {
modal.deferred = defer<OnFinishedParams<C> | []>(); modal.deferred = Promise.withResolvers<OnFinishedParams<C> | []>();
return [ return [
async (...args: OnFinishedParams<C>): Promise<void> => { async (...args: OnFinishedParams<C>): Promise<void> => {
if (modal.beforeClosePromise) { if (modal.beforeClosePromise) {

View File

@@ -49,7 +49,7 @@ import {
SlidingSyncState, SlidingSyncState,
} from "matrix-js-sdk/src/sliding-sync"; } from "matrix-js-sdk/src/sliding-sync";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { defer, sleep } from "matrix-js-sdk/src/utils"; import { sleep } from "matrix-js-sdk/src/utils";
// how long to long poll for // how long to long poll for
const SLIDING_SYNC_TIMEOUT_MS = 20 * 1000; const SLIDING_SYNC_TIMEOUT_MS = 20 * 1000;
@@ -184,7 +184,7 @@ export class SlidingSyncManager {
public slidingSync?: SlidingSync; public slidingSync?: SlidingSync;
private client?: MatrixClient; private client?: MatrixClient;
private configureDefer = defer<void>(); private configureDefer = Promise.withResolvers<void>();
public static get instance(): SlidingSyncManager { public static get instance(): SlidingSyncManager {
return SlidingSyncManager.internalInstance; return SlidingSyncManager.internalInstance;

View File

@@ -6,14 +6,12 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details. Please see LICENSE files in the repository root for full details.
*/ */
import { defer, type IDeferred } from "matrix-js-sdk/src/utils";
import { type WorkerPayload } from "./workers/worker"; import { type WorkerPayload } from "./workers/worker";
export class WorkerManager<Request extends object, Response> { export class WorkerManager<Request extends object, Response> {
private readonly worker: Worker; private readonly worker: Worker;
private seq = 0; private seq = 0;
private pendingDeferredMap = new Map<number, IDeferred<Response>>(); private pendingDeferredMap = new Map<number, PromiseWithResolvers<Response>>();
public constructor(worker: Worker) { public constructor(worker: Worker) {
this.worker = worker; this.worker = worker;
@@ -30,7 +28,7 @@ export class WorkerManager<Request extends object, Response> {
public call(request: Request): Promise<Response> { public call(request: Request): Promise<Response> {
const seq = this.seq++; const seq = this.seq++;
const deferred = defer<Response>(); const deferred = Promise.withResolvers<Response>();
this.pendingDeferredMap.set(seq, deferred); this.pendingDeferredMap.set(seq, deferred);
this.worker.postMessage({ seq, ...request }); this.worker.postMessage({ seq, ...request });
return deferred.promise; return deferred.promise;

View File

@@ -9,7 +9,6 @@ Please see LICENSE files in the repository root for full details.
import EventEmitter from "events"; import EventEmitter from "events";
import { SimpleObservable } from "matrix-widget-api"; import { SimpleObservable } from "matrix-widget-api";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { defer } from "matrix-js-sdk/src/utils";
import { UPDATE_EVENT } from "../stores/AsyncStore"; import { UPDATE_EVENT } from "../stores/AsyncStore";
import { arrayFastResample } from "../utils/arrays"; import { arrayFastResample } from "../utils/arrays";
@@ -158,7 +157,7 @@ export class Playback extends EventEmitter implements IDestroyable, PlaybackInte
// 5mb // 5mb
logger.log("Audio file too large: processing through <audio /> element"); logger.log("Audio file too large: processing through <audio /> element");
this.element = document.createElement("AUDIO") as HTMLAudioElement; this.element = document.createElement("AUDIO") as HTMLAudioElement;
const deferred = defer<unknown>(); const deferred = Promise.withResolvers<unknown>();
this.element.onloadeddata = deferred.resolve; this.element.onloadeddata = deferred.resolve;
this.element.onerror = deferred.reject; this.element.onerror = deferred.reject;
this.element.src = URL.createObjectURL(new Blob([this.buf])); this.element.src = URL.createObjectURL(new Blob([this.buf]));

View File

@@ -19,7 +19,7 @@ import {
type SyncStateData, type SyncStateData,
type TimelineEvents, type TimelineEvents,
} from "matrix-js-sdk/src/matrix"; } from "matrix-js-sdk/src/matrix";
import { defer, type IDeferred, type QueryDict } from "matrix-js-sdk/src/utils"; import { type QueryDict } from "matrix-js-sdk/src/utils";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { throttle } from "lodash"; import { throttle } from "lodash";
import { CryptoEvent, type KeyBackupInfo } from "matrix-js-sdk/src/crypto-api"; import { CryptoEvent, type KeyBackupInfo } from "matrix-js-sdk/src/crypto-api";
@@ -215,7 +215,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
}; };
private firstSyncComplete = false; private firstSyncComplete = false;
private firstSyncPromise: IDeferred<void>; private firstSyncPromise: PromiseWithResolvers<void>;
private screenAfterLogin?: IScreen; private screenAfterLogin?: IScreen;
private tokenLogin?: boolean; private tokenLogin?: boolean;
@@ -254,7 +254,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
// Used by _viewRoom before getting state from sync // Used by _viewRoom before getting state from sync
this.firstSyncComplete = false; this.firstSyncComplete = false;
this.firstSyncPromise = defer(); this.firstSyncPromise = Promise.withResolvers();
if (this.props.config.sync_timeline_limit) { if (this.props.config.sync_timeline_limit) {
MatrixClientPeg.opts.initialSyncLimit = this.props.config.sync_timeline_limit; MatrixClientPeg.opts.initialSyncLimit = this.props.config.sync_timeline_limit;
@@ -1471,11 +1471,11 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
// since we're about to start the client and therefore about to do the first sync // since we're about to start the client and therefore about to do the first sync
// We resolve the existing promise with the new one to update any existing listeners // We resolve the existing promise with the new one to update any existing listeners
if (!this.firstSyncComplete) { if (!this.firstSyncComplete) {
const firstSyncPromise = defer<void>(); const firstSyncPromise = Promise.withResolvers<void>();
this.firstSyncPromise.resolve(firstSyncPromise.promise); this.firstSyncPromise.resolve(firstSyncPromise.promise);
this.firstSyncPromise = firstSyncPromise; this.firstSyncPromise = firstSyncPromise;
} else { } else {
this.firstSyncPromise = defer(); this.firstSyncPromise = Promise.withResolvers();
} }
this.firstSyncComplete = false; this.firstSyncComplete = false;
const cli = MatrixClientPeg.safeGet(); const cli = MatrixClientPeg.safeGet();

View File

@@ -8,7 +8,6 @@ Please see LICENSE files in the repository root for full details.
import React, { type JSX } from "react"; import React, { type JSX } from "react";
import { type MatrixEvent, EventType, RelationType, type MatrixClient, MatrixError } from "matrix-js-sdk/src/matrix"; import { type MatrixEvent, EventType, RelationType, type MatrixClient, MatrixError } from "matrix-js-sdk/src/matrix";
import { defer } from "matrix-js-sdk/src/utils";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { MatrixClientPeg } from "../../../MatrixClientPeg";
@@ -58,7 +57,7 @@ export default class MessageEditHistoryDialog extends React.PureComponent<IProps
const eventId = this.props.mxEvent.getId()!; const eventId = this.props.mxEvent.getId()!;
const client = MatrixClientPeg.safeGet(); const client = MatrixClientPeg.safeGet();
const { resolve, reject, promise } = defer<boolean>(); const { resolve, reject, promise } = Promise.withResolvers<boolean>();
let result: Awaited<ReturnType<MatrixClient["relations"]>>; let result: Awaited<ReturnType<MatrixClient["relations"]>>;
try { try {

View File

@@ -10,7 +10,6 @@ import React, { createRef, type RefObject } from "react";
import classNames from "classnames"; import classNames from "classnames";
import { flatMap } from "lodash"; import { flatMap } from "lodash";
import { type Room } from "matrix-js-sdk/src/matrix"; import { type Room } from "matrix-js-sdk/src/matrix";
import { defer } from "matrix-js-sdk/src/utils";
import Autocompleter, { import Autocompleter, {
type ICompletion, type ICompletion,
@@ -177,7 +176,7 @@ export default class Autocomplete extends React.PureComponent<IProps, IState> {
} }
} }
const deferred = defer<void>(); const deferred = Promise.withResolvers<void>();
this.setState( this.setState(
{ {
completions, completions,

View File

@@ -9,7 +9,6 @@ Please see LICENSE files in the repository root for full details.
import React, { lazy, Suspense, useCallback, useContext, useEffect, useRef, useState } from "react"; import React, { lazy, Suspense, useCallback, useContext, useEffect, useRef, useState } from "react";
import { type MatrixClient } from "matrix-js-sdk/src/matrix"; import { type MatrixClient } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { defer } from "matrix-js-sdk/src/utils";
import { _t } from "../../../../../languageHandler"; import { _t } from "../../../../../languageHandler";
import Modal from "../../../../../Modal"; import Modal from "../../../../../Modal";
@@ -98,7 +97,7 @@ const useSignOut = (
const url = getManageDeviceUrl(delegatedAuthAccountUrl, deviceId); const url = getManageDeviceUrl(delegatedAuthAccountUrl, deviceId);
window.open(url, "_blank"); window.open(url, "_blank");
} else { } else {
const deferredSuccess = defer<boolean>(); const deferredSuccess = Promise.withResolvers<boolean>();
await deleteDevicesWithInteractiveAuth(matrixClient, deviceIds, async (success) => { await deleteDevicesWithInteractiveAuth(matrixClient, deviceIds, async (success) => {
deferredSuccess.resolve(!!success); deferredSuccess.resolve(!!success);
}); });

View File

@@ -8,7 +8,6 @@ Please see LICENSE files in the repository root for full details.
*/ */
import { type AccountDataEvents, ClientEvent, type MatrixClient, type MatrixEvent } from "matrix-js-sdk/src/matrix"; import { type AccountDataEvents, ClientEvent, type MatrixClient, type MatrixEvent } from "matrix-js-sdk/src/matrix";
import { defer } from "matrix-js-sdk/src/utils";
import { isEqual } from "lodash"; import { isEqual } from "lodash";
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler"; import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
@@ -162,7 +161,7 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa
// Attach a deferred *before* setting the account data to ensure we catch any requests // Attach a deferred *before* setting the account data to ensure we catch any requests
// which race between different lines. // which race between different lines.
const deferred = defer<void>(); const deferred = Promise.withResolvers<void>();
const handler = (event: MatrixEvent): void => { const handler = (event: MatrixEvent): void => {
if (event.getType() !== eventType || !isEqual(event.getContent<AccountDataEvents[K]>()[field], value)) if (event.getType() !== eventType || !isEqual(event.getContent<AccountDataEvents[K]>()[field], value))
return; return;

View File

@@ -8,7 +8,6 @@ Please see LICENSE files in the repository root for full details.
*/ */
import { type MatrixClient, type MatrixEvent, type Room, RoomEvent } from "matrix-js-sdk/src/matrix"; import { type MatrixClient, type MatrixEvent, type Room, RoomEvent } from "matrix-js-sdk/src/matrix";
import { defer } from "matrix-js-sdk/src/utils";
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler"; import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
import { objectClone, objectKeyChanges } from "../../utils/objects"; import { objectClone, objectKeyChanges } from "../../utils/objects";
@@ -99,7 +98,7 @@ export default class RoomAccountSettingsHandler extends MatrixClientBackedSettin
await this.client.setRoomAccountData(roomId, eventType, content); await this.client.setRoomAccountData(roomId, eventType, content);
const deferred = defer<void>(); const deferred = Promise.withResolvers<void>();
const handler = (event: MatrixEvent, room: Room): void => { const handler = (event: MatrixEvent, room: Room): void => {
if (room.roomId !== roomId || event.getType() !== eventType) return; if (room.roomId !== roomId || event.getType() !== eventType) return;
if (field !== null && event.getContent()[field] !== value) return; if (field !== null && event.getContent()[field] !== value) return;

View File

@@ -14,7 +14,6 @@ import {
RoomStateEvent, RoomStateEvent,
type StateEvents, type StateEvents,
} from "matrix-js-sdk/src/matrix"; } from "matrix-js-sdk/src/matrix";
import { defer } from "matrix-js-sdk/src/utils";
import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler"; import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler";
import { objectClone, objectKeyChanges } from "../../utils/objects"; import { objectClone, objectKeyChanges } from "../../utils/objects";
@@ -98,7 +97,7 @@ export default class RoomSettingsHandler extends MatrixClientBackedSettingsHandl
const { event_id: eventId } = await this.client.sendStateEvent(roomId, eventType, content); const { event_id: eventId } = await this.client.sendStateEvent(roomId, eventType, content);
const deferred = defer<void>(); const deferred = Promise.withResolvers<void>();
const handler = (event: MatrixEvent): void => { const handler = (event: MatrixEvent): void => {
if (event.getId() !== eventId) return; if (event.getId() !== eventId) return;
this.client.off(RoomStateEvent.Events, handler); this.client.off(RoomStateEvent.Events, handler);

View File

@@ -21,7 +21,6 @@ import {
} from "matrix-js-sdk/src/matrix"; } from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types"; import { KnownMembership } from "matrix-js-sdk/src/types";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { defer } from "matrix-js-sdk/src/utils";
import { AsyncStoreWithClient } from "../AsyncStoreWithClient"; import { AsyncStoreWithClient } from "../AsyncStoreWithClient";
import defaultDispatcher from "../../dispatcher/dispatcher"; import defaultDispatcher from "../../dispatcher/dispatcher";
@@ -153,7 +152,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<EmptyObject> {
private _enabledMetaSpaces: MetaSpace[] = []; private _enabledMetaSpaces: MetaSpace[] = [];
/** Whether the feature flag is set for MSC3946 */ /** Whether the feature flag is set for MSC3946 */
private _msc3946ProcessDynamicPredecessor: boolean = SettingsStore.getValue("feature_dynamic_room_predecessors"); private _msc3946ProcessDynamicPredecessor: boolean = SettingsStore.getValue("feature_dynamic_room_predecessors");
private _storeReadyDeferred = defer(); private _storeReadyDeferred = Promise.withResolvers<void>();
public constructor() { public constructor() {
super(defaultDispatcher, {}); super(defaultDispatcher, {});

View File

@@ -8,7 +8,6 @@ Please see LICENSE files in the repository root for full details.
import { MatrixError, type MatrixClient, EventType, type EmptyObject } from "matrix-js-sdk/src/matrix"; import { MatrixError, type MatrixClient, EventType, type EmptyObject } from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types"; import { KnownMembership } from "matrix-js-sdk/src/types";
import { defer, type IDeferred } from "matrix-js-sdk/src/utils";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { AddressType, getAddressType } from "../UserAddress"; import { AddressType, getAddressType } from "../UserAddress";
@@ -51,7 +50,7 @@ export default class MultiInviter {
private _fatal = false; private _fatal = false;
private completionStates: CompletionStates = {}; // State of each address (invited or error) private completionStates: CompletionStates = {}; // State of each address (invited or error)
private errors: Record<string, IError> = {}; // { address: {errorText, errcode} } private errors: Record<string, IError> = {}; // { address: {errorText, errcode} }
private deferred: IDeferred<CompletionStates> | null = null; private deferred: PromiseWithResolvers<CompletionStates> | null = null;
private reason: string | undefined; private reason: string | undefined;
/** /**
@@ -93,7 +92,7 @@ export default class MultiInviter {
}; };
} }
} }
this.deferred = defer<CompletionStates>(); this.deferred = Promise.withResolvers<CompletionStates>();
this.inviteMore(0); this.inviteMore(0);
return this.deferred.promise; return this.deferred.promise;

View File

@@ -6,8 +6,6 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details. Please see LICENSE files in the repository root for full details.
*/ */
import { type IDeferred, defer } from "matrix-js-sdk/src/utils";
/** /**
A countdown timer, exposing a promise api. A countdown timer, exposing a promise api.
A timer starts in a non-started state, A timer starts in a non-started state,
@@ -22,7 +20,7 @@ a new one through `clone()` or `cloneIfRun()`.
export default class Timer { export default class Timer {
private timerHandle?: number; private timerHandle?: number;
private startTs?: number; private startTs?: number;
private deferred!: IDeferred<void>; private deferred!: PromiseWithResolvers<void>;
public constructor(private timeout: number) { public constructor(private timeout: number) {
this.setNotStarted(); this.setNotStarted();
@@ -31,7 +29,7 @@ export default class Timer {
private setNotStarted(): void { private setNotStarted(): void {
this.timerHandle = undefined; this.timerHandle = undefined;
this.startTs = undefined; this.startTs = undefined;
this.deferred = defer(); this.deferred = Promise.withResolvers();
this.deferred.promise = this.deferred.promise.finally(() => { this.deferred.promise = this.deferred.promise.finally(() => {
this.timerHandle = undefined; this.timerHandle = undefined;
}); });

View File

@@ -13,7 +13,6 @@ import { renderToStaticMarkup } from "react-dom/server";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import escapeHtml from "escape-html"; import escapeHtml from "escape-html";
import { TooltipProvider } from "@vector-im/compound-web"; import { TooltipProvider } from "@vector-im/compound-web";
import { defer } from "matrix-js-sdk/src/utils";
import Exporter from "./Exporter"; import Exporter from "./Exporter";
import { mediaFromMxc } from "../../customisations/Media"; import { mediaFromMxc } from "../../customisations/Media";
@@ -302,7 +301,7 @@ export default class HTMLExporter extends Exporter {
if (hasAvatar) await this.saveAvatarIfNeeded(mxEv); if (hasAvatar) await this.saveAvatarIfNeeded(mxEv);
// We have to wait for the component to be rendered before we can get the markup // We have to wait for the component to be rendered before we can get the markup
// so pass a deferred as a ref to the component. // so pass a deferred as a ref to the component.
const deferred = defer<void>(); const deferred = Promise.withResolvers<void>();
const EventTile = this.getEventTile(mxEv, continuation, deferred.resolve); const EventTile = this.getEventTile(mxEv, continuation, deferred.resolve);
let eventTileMarkup: string; let eventTileMarkup: string;

View File

@@ -49,6 +49,8 @@ function checkBrowserFeatures(): boolean {
window.Modernizr.addTest("promiseprototypefinally", () => typeof window.Promise?.prototype?.finally === "function"); window.Modernizr.addTest("promiseprototypefinally", () => typeof window.Promise?.prototype?.finally === "function");
// ES2020: http://262.ecma-international.org/#sec-promise.allsettled // ES2020: http://262.ecma-international.org/#sec-promise.allsettled
window.Modernizr.addTest("promiseallsettled", () => typeof window.Promise?.allSettled === "function"); window.Modernizr.addTest("promiseallsettled", () => typeof window.Promise?.allSettled === "function");
// ES2024: https://2ality.com/2024/05/proposal-promise-with-resolvers.html
window.Modernizr.addTest("promisewithresolvers", () => typeof window.Promise?.withResolvers === "function");
// ES2018: https://262.ecma-international.org/9.0/#sec-get-regexp.prototype.dotAll // ES2018: https://262.ecma-international.org/9.0/#sec-get-regexp.prototype.dotAll
window.Modernizr.addTest( window.Modernizr.addTest(
"regexpdotall", "regexpdotall",

View File

@@ -5,7 +5,6 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details. Please see LICENSE files in the repository root for full details.
*/ */
import { defer, type IDeferred } from "matrix-js-sdk/src/utils";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { type ElectronChannel } from "../../@types/global"; import { type ElectronChannel } from "../../@types/global";
@@ -17,7 +16,7 @@ interface IPCPayload {
} }
export class IPCManager { export class IPCManager {
private pendingIpcCalls: { [ipcCallId: number]: IDeferred<any> } = {}; private pendingIpcCalls: { [ipcCallId: number]: PromiseWithResolvers<any> } = {};
private nextIpcCallId = 0; private nextIpcCallId = 0;
public constructor( public constructor(
@@ -33,7 +32,7 @@ export class IPCManager {
public async call(name: string, ...args: any[]): Promise<any> { public async call(name: string, ...args: any[]): Promise<any> {
// TODO this should be moved into the preload.js file. // TODO this should be moved into the preload.js file.
const ipcCallId = ++this.nextIpcCallId; const ipcCallId = ++this.nextIpcCallId;
const deferred = defer<any>(); const deferred = Promise.withResolvers<any>();
this.pendingIpcCalls[ipcCallId] = deferred; this.pendingIpcCalls[ipcCallId] = deferred;
// Maybe add a timeout to these? Probably not necessary. // Maybe add a timeout to these? Probably not necessary.
window.electron!.send(this.sendChannel, { id: ipcCallId, name, args }); window.electron!.send(this.sendChannel, { id: ipcCallId, name, args });

View File

@@ -14,7 +14,6 @@ import {
type UploadResponse, type UploadResponse,
} from "matrix-js-sdk/src/matrix"; } from "matrix-js-sdk/src/matrix";
import { type ImageInfo } from "matrix-js-sdk/src/types"; import { type ImageInfo } from "matrix-js-sdk/src/types";
import { defer } from "matrix-js-sdk/src/utils";
import encrypt, { type IEncryptedFile } from "matrix-encrypt-attachment"; import encrypt, { type IEncryptedFile } from "matrix-encrypt-attachment";
import ContentMessages, { UploadCanceledError, uploadFile } from "../../src/ContentMessages"; import ContentMessages, { UploadCanceledError, uploadFile } from "../../src/ContentMessages";
@@ -338,7 +337,7 @@ describe("ContentMessages", () => {
describe("cancelUpload", () => { describe("cancelUpload", () => {
it("should cancel in-flight upload", async () => { it("should cancel in-flight upload", async () => {
const deferred = defer<UploadResponse>(); const deferred = Promise.withResolvers<UploadResponse>();
mocked(client.uploadContent).mockReturnValue(deferred.promise); mocked(client.uploadContent).mockReturnValue(deferred.promise);
const file1 = new File([], "file1"); const file1 = new File([], "file1");
const prom = contentMessages.sendContentToRoom(file1, roomId, undefined, client, undefined); const prom = contentMessages.sendContentToRoom(file1, roomId, undefined, client, undefined);

View File

@@ -21,7 +21,7 @@ import { completeAuthorizationCodeGrant } from "matrix-js-sdk/src/oidc/authorize
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { OidcError } from "matrix-js-sdk/src/oidc/error"; import { OidcError } from "matrix-js-sdk/src/oidc/error";
import { type BearerTokenResponse } from "matrix-js-sdk/src/oidc/validate"; import { type BearerTokenResponse } from "matrix-js-sdk/src/oidc/validate";
import { defer, type IDeferred, sleep } from "matrix-js-sdk/src/utils"; import { sleep } from "matrix-js-sdk/src/utils";
import { import {
CryptoEvent, CryptoEvent,
type DeviceVerificationStatus, type DeviceVerificationStatus,
@@ -85,7 +85,7 @@ describe("<MatrixChat />", () => {
const deviceId = "qwertyui"; const deviceId = "qwertyui";
const accessToken = "abc123"; const accessToken = "abc123";
const refreshToken = "def456"; const refreshToken = "def456";
let bootstrapDeferred: IDeferred<void>; let bootstrapDeferred: PromiseWithResolvers<void>;
// reused in createClient mock below // reused in createClient mock below
const getMockClientMethods = () => ({ const getMockClientMethods = () => ({
...mockClientMethodsUser(userId), ...mockClientMethodsUser(userId),
@@ -248,7 +248,7 @@ describe("<MatrixChat />", () => {
{} as ValidatedServerConfig, {} as ValidatedServerConfig,
); );
bootstrapDeferred = defer(); bootstrapDeferred = Promise.withResolvers();
await clearAllModals(); await clearAllModals();
}); });
@@ -1513,7 +1513,7 @@ describe("<MatrixChat />", () => {
jest.spyOn(MatrixJs, "createClient").mockReturnValue(client); jest.spyOn(MatrixJs, "createClient").mockReturnValue(client);
// intercept initCrypto and have it block until we complete the deferred // intercept initCrypto and have it block until we complete the deferred
const initCryptoCompleteDefer = defer(); const initCryptoCompleteDefer = Promise.withResolvers<void>();
const initCryptoCalled = new Promise<void>((resolve) => { const initCryptoCalled = new Promise<void>((resolve) => {
client.initRustCrypto.mockImplementation(() => { client.initRustCrypto.mockImplementation(() => {
resolve(); resolve();

View File

@@ -18,7 +18,6 @@ import {
SearchResult, SearchResult,
type ISearchResults, type ISearchResults,
} from "matrix-js-sdk/src/matrix"; } from "matrix-js-sdk/src/matrix";
import { defer } from "matrix-js-sdk/src/utils";
import { RoomSearchView } from "../../../../src/components/structures/RoomSearchView"; import { RoomSearchView } from "../../../../src/components/structures/RoomSearchView";
import ResizeNotifier from "../../../../src/utils/ResizeNotifier"; import ResizeNotifier from "../../../../src/utils/ResizeNotifier";
@@ -53,7 +52,7 @@ describe("<RoomSearchView/>", () => {
}); });
it("should show a spinner before the promise resolves", async () => { it("should show a spinner before the promise resolves", async () => {
const deferred = defer<ISearchResults>(); const deferred = Promise.withResolvers<ISearchResults>();
render( render(
<RoomSearchView <RoomSearchView
@@ -267,7 +266,7 @@ describe("<RoomSearchView/>", () => {
}); });
it("should handle resolutions after unmounting sanely", async () => { it("should handle resolutions after unmounting sanely", async () => {
const deferred = defer<ISearchResults>(); const deferred = Promise.withResolvers<ISearchResults>();
const { unmount } = render( const { unmount } = render(
<MatrixClientContext.Provider value={client}> <MatrixClientContext.Provider value={client}>
@@ -291,7 +290,7 @@ describe("<RoomSearchView/>", () => {
}); });
it("should handle rejections after unmounting sanely", async () => { it("should handle rejections after unmounting sanely", async () => {
const deferred = defer<ISearchResults>(); const deferred = Promise.withResolvers<ISearchResults>();
const { unmount } = render( const { unmount } = render(
<MatrixClientContext.Provider value={client}> <MatrixClientContext.Provider value={client}>
@@ -316,7 +315,7 @@ describe("<RoomSearchView/>", () => {
it("report error if one is encountered", async () => { it("report error if one is encountered", async () => {
const onUpdate = jest.fn(); const onUpdate = jest.fn();
const deferred = defer<ISearchResults>(); const deferred = Promise.withResolvers<ISearchResults>();
render( render(
<MatrixClientContext.Provider value={client}> <MatrixClientContext.Provider value={client}>

View File

@@ -35,7 +35,6 @@ import {
cleanup, cleanup,
} from "jest-matrix-react"; } from "jest-matrix-react";
import userEvent from "@testing-library/user-event"; import userEvent from "@testing-library/user-event";
import { defer } from "matrix-js-sdk/src/utils";
import { import {
stubClient, stubClient,
@@ -368,7 +367,7 @@ describe("RoomView", () => {
it("should not display the timeline when the room encryption is loading", async () => { it("should not display the timeline when the room encryption is loading", async () => {
jest.spyOn(room, "getMyMembership").mockReturnValue(KnownMembership.Join); jest.spyOn(room, "getMyMembership").mockReturnValue(KnownMembership.Join);
jest.spyOn(cli, "getCrypto").mockReturnValue(crypto); jest.spyOn(cli, "getCrypto").mockReturnValue(crypto);
const deferred = defer<boolean>(); const deferred = Promise.withResolvers<boolean>();
jest.spyOn(cli.getCrypto()!, "isEncryptionEnabledInRoom").mockImplementation(() => deferred.promise); jest.spyOn(cli.getCrypto()!, "isEncryptionEnabledInRoom").mockImplementation(() => deferred.promise);
const { asFragment, container } = await mountRoomView(); const { asFragment, container } = await mountRoomView();

View File

@@ -8,7 +8,6 @@ Please see LICENSE files in the repository root for full details.
import React from "react"; import React from "react";
import { fireEvent, render, screen } from "jest-matrix-react"; import { fireEvent, render, screen } from "jest-matrix-react";
import { defer } from "matrix-js-sdk/src/utils";
import PowerSelector from "../../../../../src/components/views/elements/PowerSelector"; import PowerSelector from "../../../../../src/components/views/elements/PowerSelector";
@@ -70,7 +69,7 @@ describe("<PowerSelector />", () => {
}); });
it("should reset when onChange promise rejects", async () => { it("should reset when onChange promise rejects", async () => {
const deferred = defer<void>(); const deferred = Promise.withResolvers<void>();
render( render(
<PowerSelector <PowerSelector
value={25} value={25}

View File

@@ -20,7 +20,6 @@ import {
Device, Device,
} from "matrix-js-sdk/src/matrix"; } from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types"; import { KnownMembership } from "matrix-js-sdk/src/types";
import { defer } from "matrix-js-sdk/src/utils";
import { EventEmitter } from "events"; import { EventEmitter } from "events";
import { import {
UserVerificationStatus, UserVerificationStatus,
@@ -714,7 +713,7 @@ describe("<UserOptionsSection />", () => {
])( ])(
"clicking »message« %s should start a DM", "clicking »message« %s should start a DM",
async (test: string, member: RoomMember | User, expectedAvatarUrl: string | undefined) => { async (test: string, member: RoomMember | User, expectedAvatarUrl: string | undefined) => {
const deferred = defer<string>(); const deferred = Promise.withResolvers<string>();
mocked(startDmOnFirstMessage).mockReturnValue(deferred.promise); mocked(startDmOnFirstMessage).mockReturnValue(deferred.promise);
renderComponent({ member }); renderComponent({ member });

View File

@@ -8,7 +8,6 @@ Please see LICENSE files in the repository root for full details.
import React from "react"; import React from "react";
import { fireEvent, render, screen, within } from "jest-matrix-react"; import { fireEvent, render, screen, within } from "jest-matrix-react";
import { defer, type IDeferred } from "matrix-js-sdk/src/utils";
import EventIndexPanel from "../../../../../src/components/views/settings/EventIndexPanel"; import EventIndexPanel from "../../../../../src/components/views/settings/EventIndexPanel";
import EventIndexPeg from "../../../../../src/indexing/EventIndexPeg"; import EventIndexPeg from "../../../../../src/indexing/EventIndexPeg";
@@ -140,9 +139,9 @@ describe("<EventIndexPanel />", () => {
}); });
it("enables event indexing on enable button click", async () => { it("enables event indexing on enable button click", async () => {
jest.spyOn(EventIndexPeg, "supportIsInstalled").mockReturnValue(true); jest.spyOn(EventIndexPeg, "supportIsInstalled").mockReturnValue(true);
let deferredInitEventIndex: IDeferred<boolean> | undefined; let deferredInitEventIndex: PromiseWithResolvers<boolean> | undefined;
jest.spyOn(EventIndexPeg, "initEventIndex").mockImplementation(() => { jest.spyOn(EventIndexPeg, "initEventIndex").mockImplementation(() => {
deferredInitEventIndex = defer<boolean>(); deferredInitEventIndex = Promise.withResolvers<boolean>();
return deferredInitEventIndex.promise; return deferredInitEventIndex.promise;
}); });

View File

@@ -21,7 +21,6 @@ import {
Visibility, Visibility,
} from "matrix-js-sdk/src/matrix"; } from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types"; import { KnownMembership } from "matrix-js-sdk/src/types";
import { defer, type IDeferred } from "matrix-js-sdk/src/utils";
import { import {
clearAllModals, clearAllModals,
@@ -162,7 +161,7 @@ describe("<JoinRuleSettings />", () => {
}); });
it(`upgrades room when changing join rule to ${joinRule}`, async () => { it(`upgrades room when changing join rule to ${joinRule}`, async () => {
const deferredInvites: IDeferred<any>[] = []; const deferredInvites: PromiseWithResolvers<any>[] = [];
// room that doesn't support the join rule // room that doesn't support the join rule
const room = new Room(roomId, client, userId); const room = new Room(roomId, client, userId);
const parentSpace = new Room("!parentSpace:server.org", client, userId); const parentSpace = new Room("!parentSpace:server.org", client, userId);
@@ -185,7 +184,7 @@ describe("<JoinRuleSettings />", () => {
// resolve invites by hand // resolve invites by hand
// flushPromises is too blunt to test reliably // flushPromises is too blunt to test reliably
client.invite.mockImplementation(() => { client.invite.mockImplementation(() => {
const p = defer<{}>(); const p = Promise.withResolvers<{}>();
deferredInvites.push(p); deferredInvites.push(p);
return p.promise; return p.promise;
}); });

View File

@@ -9,7 +9,6 @@ import React from "react";
import { render, screen, waitFor } from "jest-matrix-react"; import { render, screen, waitFor } from "jest-matrix-react";
import userEvent from "@testing-library/user-event"; import userEvent from "@testing-library/user-event";
import { mocked } from "jest-mock"; import { mocked } from "jest-mock";
import { defer } from "matrix-js-sdk/src/utils";
import type { MatrixClient } from "matrix-js-sdk/src/matrix"; import type { MatrixClient } from "matrix-js-sdk/src/matrix";
import { createTestClient, withClientContextRenderOptions } from "../../../../../test-utils"; import { createTestClient, withClientContextRenderOptions } from "../../../../../test-utils";
@@ -72,7 +71,7 @@ describe("<DeleteKeyStoragePanel />", () => {
}); });
it("should wait with button disabled while setEnabled runs", async () => { it("should wait with button disabled while setEnabled runs", async () => {
const setEnabledDefer = defer(); const setEnabledDefer = Promise.withResolvers<void>();
mocked(useKeyStoragePanelViewModel).mockReturnValue({ mocked(useKeyStoragePanelViewModel).mockReturnValue({
setEnabled: jest.fn().mockReturnValue(setEnabledDefer.promise), setEnabled: jest.fn().mockReturnValue(setEnabledDefer.promise),

View File

@@ -7,7 +7,7 @@
import React from "react"; import React from "react";
import { type MatrixClient } from "matrix-js-sdk/src/matrix"; import { type MatrixClient } from "matrix-js-sdk/src/matrix";
import { sleep, defer } from "matrix-js-sdk/src/utils"; import { sleep } from "matrix-js-sdk/src/utils";
import { render, screen } from "jest-matrix-react"; import { render, screen } from "jest-matrix-react";
import userEvent from "@testing-library/user-event"; import userEvent from "@testing-library/user-event";
@@ -33,7 +33,7 @@ describe("<ResetIdentityPanel />", () => {
// We need to pause the reset so that we can check that it's providing // We need to pause the reset so that we can check that it's providing
// feedback to the user that something is happening. // feedback to the user that something is happening.
const { promise: resetEncryptionPromise, resolve: resolveResetEncryption } = defer(); const { promise: resetEncryptionPromise, resolve: resolveResetEncryption } = Promise.withResolvers<void>();
jest.spyOn(matrixClient.getCrypto()!, "resetEncryption").mockReturnValue(resetEncryptionPromise); jest.spyOn(matrixClient.getCrypto()!, "resetEncryption").mockReturnValue(resetEncryptionPromise);
const continueButton = screen.getByRole("button", { name: "Continue" }); const continueButton = screen.getByRole("button", { name: "Continue" });

View File

@@ -18,7 +18,6 @@ import {
} from "matrix-js-sdk/src/matrix"; } from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types"; import { KnownMembership } from "matrix-js-sdk/src/types";
import { mocked } from "jest-mock"; import { mocked } from "jest-mock";
import { defer } from "matrix-js-sdk/src/utils";
import userEvent from "@testing-library/user-event"; import userEvent from "@testing-library/user-event";
import RolesRoomSettingsTab from "../../../../../../../src/components/views/settings/tabs/room/RolesRoomSettingsTab"; import RolesRoomSettingsTab from "../../../../../../../src/components/views/settings/tabs/room/RolesRoomSettingsTab";
@@ -209,7 +208,7 @@ describe("RolesRoomSettingsTab", () => {
}); });
it("should roll back power level change on error", async () => { it("should roll back power level change on error", async () => {
const deferred = defer<ISendEventResponse>(); const deferred = Promise.withResolvers<ISendEventResponse>();
mocked(cli.sendStateEvent).mockReturnValue(deferred.promise); mocked(cli.sendStateEvent).mockReturnValue(deferred.promise);
mocked(cli.getRoom).mockReturnValue(room); mocked(cli.getRoom).mockReturnValue(room);
// @ts-ignore - mocked doesn't support overloads properly // @ts-ignore - mocked doesn't support overloads properly

View File

@@ -9,7 +9,6 @@ Please see LICENSE files in the repository root for full details.
import { fireEvent, render, screen, within } from "jest-matrix-react"; import { fireEvent, render, screen, within } from "jest-matrix-react";
import React from "react"; import React from "react";
import { type MatrixClient, ThreepidMedium } from "matrix-js-sdk/src/matrix"; import { type MatrixClient, ThreepidMedium } from "matrix-js-sdk/src/matrix";
import { defer } from "matrix-js-sdk/src/utils";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import userEvent from "@testing-library/user-event"; import userEvent from "@testing-library/user-event";
import { type MockedObject } from "jest-mock"; import { type MockedObject } from "jest-mock";
@@ -154,7 +153,7 @@ describe("<AccountUserSettingsTab />", () => {
(settingName) => settingName === UIFeature.Deactivate, (settingName) => settingName === UIFeature.Deactivate,
); );
const finishedDeferred = defer<[boolean]>(); const finishedDeferred = Promise.withResolvers<[boolean]>();
const createDialogFn = jest.fn().mockReturnValue({ finished: finishedDeferred.promise }); const createDialogFn = jest.fn().mockReturnValue({ finished: finishedDeferred.promise });
jest.spyOn(Modal, "createDialog").mockImplementation(createDialogFn); jest.spyOn(Modal, "createDialog").mockImplementation(createDialogFn);
@@ -169,7 +168,7 @@ describe("<AccountUserSettingsTab />", () => {
(settingName) => settingName === UIFeature.Deactivate, (settingName) => settingName === UIFeature.Deactivate,
); );
const finishedDeferred = defer<[boolean]>(); const finishedDeferred = Promise.withResolvers<[boolean]>();
const createDialogFn = jest.fn().mockReturnValue({ finished: finishedDeferred.promise }); const createDialogFn = jest.fn().mockReturnValue({ finished: finishedDeferred.promise });
jest.spyOn(Modal, "createDialog").mockImplementation(createDialogFn); jest.spyOn(Modal, "createDialog").mockImplementation(createDialogFn);
@@ -187,7 +186,7 @@ describe("<AccountUserSettingsTab />", () => {
(settingName) => settingName === UIFeature.Deactivate, (settingName) => settingName === UIFeature.Deactivate,
); );
const finishedDeferred = defer<[boolean]>(); const finishedDeferred = Promise.withResolvers<[boolean]>();
const createDialogFn = jest.fn().mockReturnValue({ finished: finishedDeferred.promise }); const createDialogFn = jest.fn().mockReturnValue({ finished: finishedDeferred.promise });
jest.spyOn(Modal, "createDialog").mockImplementation(createDialogFn); jest.spyOn(Modal, "createDialog").mockImplementation(createDialogFn);

View File

@@ -19,7 +19,7 @@ import {
} from "jest-matrix-react"; } from "jest-matrix-react";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { type CryptoApi, DeviceVerificationStatus, type VerificationRequest } from "matrix-js-sdk/src/crypto-api"; import { type CryptoApi, DeviceVerificationStatus, type VerificationRequest } from "matrix-js-sdk/src/crypto-api";
import { defer, sleep } from "matrix-js-sdk/src/utils"; import { sleep } from "matrix-js-sdk/src/utils";
import { import {
ClientEvent, ClientEvent,
Device, Device,
@@ -899,7 +899,7 @@ describe("<SessionManagerTab />", () => {
}); });
it("deletes a device when interactive auth is not required", async () => { it("deletes a device when interactive auth is not required", async () => {
const deferredDeleteMultipleDevices = defer<{}>(); const deferredDeleteMultipleDevices = Promise.withResolvers<{}>();
mockClient.deleteMultipleDevices.mockReturnValue(deferredDeleteMultipleDevices.promise); mockClient.deleteMultipleDevices.mockReturnValue(deferredDeleteMultipleDevices.promise);
mockClient.getDevices.mockResolvedValue({ mockClient.getDevices.mockResolvedValue({
devices: [alicesDevice, alicesMobileDevice, alicesOlderMobileDevice], devices: [alicesDevice, alicesMobileDevice, alicesOlderMobileDevice],
@@ -1108,7 +1108,7 @@ describe("<SessionManagerTab />", () => {
// get a handle for resolving the delete call // get a handle for resolving the delete call
// because promise flushing after the confirm modal is resolving this too // because promise flushing after the confirm modal is resolving this too
// and we want to test the loading state here // and we want to test the loading state here
const resolveDeleteRequest = defer<IAuthData>(); const resolveDeleteRequest = Promise.withResolvers<IAuthData>();
mockClient.deleteMultipleDevices.mockImplementation(async () => { mockClient.deleteMultipleDevices.mockImplementation(async () => {
await resolveDeleteRequest.promise; await resolveDeleteRequest.promise;
return {}; return {};

View File

@@ -6,8 +6,6 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details. Please see LICENSE files in the repository root for full details.
*/ */
import { defer } from "matrix-js-sdk/src/utils";
import defaultDispatcher from "../../../src/dispatcher/dispatcher"; import defaultDispatcher from "../../../src/dispatcher/dispatcher";
import { Action } from "../../../src/dispatcher/actions"; import { Action } from "../../../src/dispatcher/actions";
import { AsyncActionPayload } from "../../../src/dispatcher/payloads"; import { AsyncActionPayload } from "../../../src/dispatcher/payloads";
@@ -20,8 +18,8 @@ describe("MatrixDispatcher", () => {
}); });
it("should execute callbacks in registered order", async () => { it("should execute callbacks in registered order", async () => {
const deferred1 = defer<number>(); const deferred1 = Promise.withResolvers<number>();
const deferred2 = defer<number>(); const deferred2 = Promise.withResolvers<number>();
const fn1 = jest.fn(() => deferred1.resolve(1)); const fn1 = jest.fn(() => deferred1.resolve(1));
const fn2 = jest.fn(() => deferred2.resolve(2)); const fn2 = jest.fn(() => deferred2.resolve(2));
@@ -36,8 +34,8 @@ describe("MatrixDispatcher", () => {
}); });
it("should skip the queue for the given callback", async () => { it("should skip the queue for the given callback", async () => {
const deferred1 = defer<number>(); const deferred1 = Promise.withResolvers<number>();
const deferred2 = defer<number>(); const deferred2 = Promise.withResolvers<number>();
const fn1 = jest.fn(() => deferred1.resolve(1)); const fn1 = jest.fn(() => deferred1.resolve(1));
const fn2 = jest.fn(() => deferred2.resolve(2)); const fn2 = jest.fn(() => deferred2.resolve(2));

View File

@@ -6,7 +6,6 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details. Please see LICENSE files in the repository root for full details.
*/ */
import { defer } from "matrix-js-sdk/src/utils";
import { type MatrixClient } from "matrix-js-sdk/src/matrix"; import { type MatrixClient } from "matrix-js-sdk/src/matrix";
import ServerSupportUnstableFeatureController from "../../../../src/settings/controllers/ServerSupportUnstableFeatureController"; import ServerSupportUnstableFeatureController from "../../../../src/settings/controllers/ServerSupportUnstableFeatureController";
@@ -34,7 +33,7 @@ describe("ServerSupportUnstableFeatureController", () => {
controller, controller,
}; };
const deferred = defer<any>(); const deferred = Promise.withResolvers<any>();
watchers.watchSetting(setting, null, deferred.resolve); watchers.watchSetting(setting, null, deferred.resolve);
MatrixClientBackedController.matrixClient = cli; MatrixClientBackedController.matrixClient = cli;
await deferred.promise; await deferred.promise;

View File

@@ -20,7 +20,6 @@ import {
type RoomState, type RoomState,
} from "matrix-js-sdk/src/matrix"; } from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types"; import { KnownMembership } from "matrix-js-sdk/src/types";
import { defer } from "matrix-js-sdk/src/utils";
import SpaceStore from "../../../src/stores/spaces/SpaceStore"; import SpaceStore from "../../../src/stores/spaces/SpaceStore";
import { import {
@@ -1010,7 +1009,7 @@ describe("SpaceStore", () => {
await run(); await run();
const deferred = defer<boolean>(); const deferred = Promise.withResolvers<boolean>();
space.loadMembersIfNeeded.mockImplementation(() => { space.loadMembersIfNeeded.mockImplementation(() => {
const event = mkEvent({ const event = mkEvent({
event: true, event: true,

View File

@@ -14,7 +14,7 @@
"outDir": "./lib", "outDir": "./lib",
"declaration": true, "declaration": true,
"jsx": "react", "jsx": "react",
"lib": ["es2022", "dom", "dom.iterable"], "lib": ["es2022", "es2024.promise", "dom", "dom.iterable"],
"strict": true, "strict": true,
"paths": { "paths": {
"jest-matrix-react": ["./test/test-utils/jest-matrix-react"] "jest-matrix-react": ["./test/test-utils/jest-matrix-react"]