From 544b1c6742514a9580850c0d35a21abe15813013 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 12 Jul 2022 19:27:41 +0100 Subject: [PATCH] Merge develop into group call branch again (#2513) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Send call version `1` as a string (#2471) * test typescriptification - backup.spec (#2468) * renamed: spec/unit/crypto/crypto-utils.js -> spec/unit/crypto/crypto-utils.ts * ts fixes in crypto-utils * renamed: spec/unit/crypto/backup.spec.js -> spec/unit/crypto/backup.spec.ts * ts fixes in backup.spec * remove fit * remove debug * Prepare changelog for v19.0.0-rc.1 * v19.0.0-rc.1 * Update jest monorepo (#2476) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update all (#2475) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update dependency @types/jest to v28 (#2478) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Fix call.collectCallStats() (#2480) Regressed by https://github.com/matrix-org/matrix-js-sdk/pull/2352 (you can just use RTCStatsReport as an iterator directly (which was was what that code was doing before) which uses entries( which gives you key/value pairs, but using forEach gives you just the value. * Go back to forEach in collectcallstats (#2481) Older typescript library doesn't know about .values() on the stats object, so it was failing in react sdk which had an older typescript. https://github.com/matrix-org/matrix-react-sdk/pull/8935 was an attempt to upgrade it but did not seem to be helping on CI, despite being fine locally. * Update babel monorepo to v7.18.6 (#2477) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Expose KNOWN_SAFE_ROOM_VERSION (#2474) * Fix return type on funcs in matrixClient to be optionally null (#2488) * Update pull_request.yaml (#2490) * Lock file maintenance (#2491) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Prepare changelog for v19.0.0 * v19.0.0 * Resetting package fields for development * Improve VoIP integrations testing (#2495) * Remove MSC3244 support (#2504) * Actually store the identity server in the client when given as an option (#2503) * Actually store the identity server in the client when given as an option * Update requestRegisterEmailToken to a modern spec version too * Properly re-insert room ID in bundled thread relation messages from sync (#2505) Events returned by the `/sync` endpoint, including relations bundled with other events, may have their `room_id`s stripped out. This causes decryption errors if the IDs aren't repopulated. Fixes vector-im/element-web#22094. * Remove `setNow` from `realtime-callbacks.ts` (#2509) Signed-off-by: Šimon Brandner * Remove dead code (#2510) * Don't crash with undefined room in `processBeaconEvents()` (#2500) * Add a basic PR checklist for all PRs (#2511) It'll be mildly annoying for core developers who have to constantly remove or edit this, but it'll also serve as a good reminder to do these things. Note that signoff is not required for core developers. * Fix tests Co-authored-by: Šimon Brandner Co-authored-by: Kerry Co-authored-by: RiotRobot Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Michael Weimann Co-authored-by: texuf Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> Co-authored-by: Travis Ralston Co-authored-by: Faye Duxovni --- .github/PULL_REQUEST_TEMPLATE.md | 14 +- .github/workflows/pull_request.yaml | 1 - CHANGELOG.md | 28 + package.json | 6 +- spec/TestClient.ts | 4 + ...s => matrix-client-event-timeline.spec.ts} | 186 +- spec/integ/matrix-client-methods.spec.js | 70 +- spec/test-utils/test-utils.ts | 29 +- spec/test-utils/webrtc.ts | 157 ++ .../crypto/{backup.spec.js => backup.spec.ts} | 231 +- .../{crypto-utils.js => crypto-utils.ts} | 14 +- spec/unit/realtime-callbacks.spec.js | 10 +- spec/unit/utils.spec.ts | 12 - spec/unit/webrtc/call.spec.ts | 521 ++-- spec/unit/webrtc/callFeed.spec.ts | 61 + src/client.ts | 35 +- src/crypto/api.ts | 5 - src/crypto/verification/Error.ts | 12 - src/models/room.ts | 2 +- src/models/thread.ts | 5 +- src/realtime-callbacks.ts | 20 +- src/utils.ts | 80 - src/webrtc/call.ts | 12 +- yarn.lock | 2354 ++++++++--------- 24 files changed, 2168 insertions(+), 1701 deletions(-) rename spec/integ/{matrix-client-event-timeline.spec.js => matrix-client-event-timeline.spec.ts} (86%) create mode 100644 spec/test-utils/webrtc.ts rename spec/unit/crypto/{backup.spec.js => backup.spec.ts} (78%) rename spec/unit/crypto/{crypto-utils.js => crypto-utils.ts} (78%) create mode 100644 spec/unit/webrtc/callFeed.spec.ts diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index a71d86006..c0b7939a6 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,7 +1,13 @@ - + - +## Checklist - diff --git a/.github/workflows/pull_request.yaml b/.github/workflows/pull_request.yaml index 6cb936888..5f8168116 100644 --- a/.github/workflows/pull_request.yaml +++ b/.github/workflows/pull_request.yaml @@ -16,7 +16,6 @@ concurrency: ${{ github.workflow }}-${{ github.event.pull_request.head.ref }} jobs: changelog: name: Preview Changelog - if: github.event.action != 'synchronize' runs-on: ubuntu-latest steps: - uses: matrix-org/allchange@main diff --git a/CHANGELOG.md b/CHANGELOG.md index bf48bc37e..9c8e28925 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,31 @@ +Changes in [19.0.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v19.0.0) (2022-07-05) +================================================================================================== + +## 🚨 BREAKING CHANGES + * Remove unused sessionStore ([\#2455](https://github.com/matrix-org/matrix-js-sdk/pull/2455)). + +## ✨ Features + * Implement MSC3827: Filtering of `/publicRooms` by room type ([\#2469](https://github.com/matrix-org/matrix-js-sdk/pull/2469)). + * expose latestLocationEvent on beacon model ([\#2467](https://github.com/matrix-org/matrix-js-sdk/pull/2467)). Contributed by @kerryarchibald. + * Live location share - add start time leniency ([\#2465](https://github.com/matrix-org/matrix-js-sdk/pull/2465)). Contributed by @kerryarchibald. + * Log real errors and not just their messages, traces are useful ([\#2464](https://github.com/matrix-org/matrix-js-sdk/pull/2464)). + * Various changes to `src/crypto` files for correctness ([\#2137](https://github.com/matrix-org/matrix-js-sdk/pull/2137)). Contributed by @ShadowJonathan. + * Update MSC3786 implementation: Check the `state_key` ([\#2429](https://github.com/matrix-org/matrix-js-sdk/pull/2429)). + * Timeline needs to refresh when we see a MSC2716 marker event ([\#2299](https://github.com/matrix-org/matrix-js-sdk/pull/2299)). Contributed by @MadLittleMods. + * Try to load keys from key backup when a message fails to decrypt ([\#2373](https://github.com/matrix-org/matrix-js-sdk/pull/2373)). Fixes vector-im/element-web#21026. Contributed by @duxovni. + +## 🐛 Bug Fixes + * Send call version `1` as a string ([\#2471](https://github.com/matrix-org/matrix-js-sdk/pull/2471)). Fixes vector-im/element-web#22629. + * Fix issue with `getEventTimeline` returning undefined for thread roots in main timeline ([\#2454](https://github.com/matrix-org/matrix-js-sdk/pull/2454)). Fixes vector-im/element-web#22539. + * Add missing `type` property on `IAuthData` ([\#2463](https://github.com/matrix-org/matrix-js-sdk/pull/2463)). + * Clearly indicate that `lastReply` on a Thread can return falsy ([\#2462](https://github.com/matrix-org/matrix-js-sdk/pull/2462)). + * Fix issues with getEventTimeline and thread roots ([\#2444](https://github.com/matrix-org/matrix-js-sdk/pull/2444)). Fixes vector-im/element-web#21613. + * Live location sharing - monitor liveness of beacons yet to start ([\#2437](https://github.com/matrix-org/matrix-js-sdk/pull/2437)). Contributed by @kerryarchibald. + * Refactor Relations to not be per-EventTimelineSet ([\#2412](https://github.com/matrix-org/matrix-js-sdk/pull/2412)). Fixes #2399 and vector-im/element-web#22298. + * Add tests for sendEvent threadId handling ([\#2435](https://github.com/matrix-org/matrix-js-sdk/pull/2435)). Fixes vector-im/element-web#22433. + * Make sure `encryptAndSendKeysToDevices` assumes devices are unique per-user. ([\#2136](https://github.com/matrix-org/matrix-js-sdk/pull/2136)). Fixes #2135. Contributed by @ShadowJonathan. + * Don't bug the user while re-checking key backups after decryption failures ([\#2430](https://github.com/matrix-org/matrix-js-sdk/pull/2430)). Fixes vector-im/element-web#22416. Contributed by @duxovni. + Changes in [18.1.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v18.1.0) (2022-06-07) ================================================================================================== diff --git a/package.json b/package.json index 034a3b599..efe0bbfe0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-js-sdk", - "version": "18.1.0", + "version": "19.0.0", "description": "Matrix Client-Server SDK for Javascript", "engines": { "node": ">=12.9.0" @@ -83,7 +83,7 @@ "@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.8.tgz", "@types/bs58": "^4.0.1", "@types/content-type": "^1.1.5", - "@types/jest": "^27.0.0", + "@types/jest": "^28.0.0", "@types/node": "12", "@types/request": "^2.48.5", "@typescript-eslint/eslint-plugin": "^5.6.0", @@ -94,7 +94,7 @@ "better-docs": "^2.4.0-beta.9", "browserify": "^17.0.0", "docdash": "^1.2.0", - "eslint": "8.16.0", + "eslint": "8.18.0", "eslint-config-google": "^0.14.0", "eslint-plugin-import": "^2.25.4", "eslint-plugin-matrix-org": "^0.5.0", diff --git a/spec/TestClient.ts b/spec/TestClient.ts index 244a9d6e3..52d7eb378 100644 --- a/spec/TestClient.ts +++ b/spec/TestClient.ts @@ -236,4 +236,8 @@ export class TestClient { public isFallbackICEServerAllowed(): boolean { return true; } + + public getUserId(): string { + return this.userId; + } } diff --git a/spec/integ/matrix-client-event-timeline.spec.js b/spec/integ/matrix-client-event-timeline.spec.ts similarity index 86% rename from spec/integ/matrix-client-event-timeline.spec.js rename to spec/integ/matrix-client-event-timeline.spec.ts index c165a7057..3bde9dd6d 100644 --- a/spec/integ/matrix-client-event-timeline.spec.js +++ b/spec/integ/matrix-client-event-timeline.spec.ts @@ -1,5 +1,21 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + import * as utils from "../test-utils/test-utils"; -import { EventTimeline, Filter, MatrixEvent } from "../../src/matrix"; +import { ClientEvent, EventTimeline, Filter, IEvent, MatrixClient, MatrixEvent, Room } from "../../src/matrix"; import { logger } from "../../src/logger"; import { TestClient } from "../TestClient"; import { Thread, THREAD_RELATION_TYPE } from "../../src/models/thread"; @@ -10,8 +26,14 @@ const accessToken = "aseukfgwef"; const roomId = "!foo:bar"; const otherUserId = "@bob:localhost"; +const withoutRoomId = (e: Partial): Partial => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { room_id: _, ...copy } = e; + return copy; +}; + const USER_MEMBERSHIP_EVENT = utils.mkMembership({ - room: roomId, mship: "join", user: userId, name: userName, + room: roomId, mship: "join", user: userId, name: userName, event: false, }); const ROOM_NAME_EVENT = utils.mkEvent({ @@ -19,34 +41,37 @@ const ROOM_NAME_EVENT = utils.mkEvent({ content: { name: "Old room name", }, + event: false, }); const INITIAL_SYNC_DATA = { next_batch: "s_5_3", rooms: { join: { - "!foo:bar": { // roomId + [roomId]: { timeline: { events: [ utils.mkMessage({ - room: roomId, user: otherUserId, msg: "hello", + user: otherUserId, msg: "hello", event: false, }), ], prev_batch: "f_1_1", }, state: { events: [ - ROOM_NAME_EVENT, + withoutRoomId(ROOM_NAME_EVENT), utils.mkMembership({ - room: roomId, mship: "join", + mship: "join", user: otherUserId, name: "Bob", + event: false, }), - USER_MEMBERSHIP_EVENT, + withoutRoomId(USER_MEMBERSHIP_EVENT), utils.mkEvent({ - type: "m.room.create", room: roomId, user: userId, + type: "m.room.create", user: userId, content: { creator: userId, }, + event: false, }), ], }, @@ -57,16 +82,16 @@ const INITIAL_SYNC_DATA = { const EVENTS = [ utils.mkMessage({ - room: roomId, user: userId, msg: "we", + room: roomId, user: userId, msg: "we", event: false, }), utils.mkMessage({ - room: roomId, user: userId, msg: "could", + room: roomId, user: userId, msg: "could", event: false, }), utils.mkMessage({ - room: roomId, user: userId, msg: "be", + room: roomId, user: userId, msg: "be", event: false, }), utils.mkMessage({ - room: roomId, user: userId, msg: "heroes", + room: roomId, user: userId, msg: "heroes", event: false, }), ]; @@ -81,12 +106,13 @@ const THREAD_ROOT = utils.mkEvent({ unsigned: { "m.relations": { "io.element.thread": { - "latest_event": undefined, + //"latest_event": undefined, "count": 1, "current_user_participated": true, }, }, }, + event: false, }); const THREAD_REPLY = utils.mkEvent({ @@ -102,12 +128,25 @@ const THREAD_REPLY = utils.mkEvent({ event_id: THREAD_ROOT.event_id, }, }, + event: false, }); THREAD_ROOT.unsigned["m.relations"]["io.element.thread"].latest_event = THREAD_REPLY; +const SYNC_THREAD_ROOT = withoutRoomId(THREAD_ROOT); +const SYNC_THREAD_REPLY = withoutRoomId(THREAD_REPLY); +SYNC_THREAD_ROOT.unsigned = { + "m.relations": { + "io.element.thread": { + "latest_event": SYNC_THREAD_REPLY, + "count": 1, + "current_user_participated": true, + }, + }, +}; + // start the client, and wait for it to initialise -function startClient(httpBackend, client) { +function startClient(httpBackend: TestClient["httpBackend"], client: MatrixClient) { httpBackend.when("GET", "/versions").respond(200, {}); httpBackend.when("GET", "/pushrules").respond(200, {}); httpBackend.when("POST", "/filter").respond(200, { filter_id: "fid" }); @@ -116,8 +155,8 @@ function startClient(httpBackend, client) { client.startClient(); // set up a promise which will resolve once the client is initialised - const prom = new Promise((resolve) => { - client.on("sync", function(state) { + const prom = new Promise((resolve) => { + client.on(ClientEvent.Sync, function(state) { logger.log("sync", state); if (state != "SYNCING") { return; @@ -133,8 +172,8 @@ function startClient(httpBackend, client) { } describe("getEventTimeline support", function() { - let httpBackend; - let client; + let httpBackend: TestClient["httpBackend"]; + let client: MatrixClient; beforeEach(function() { const testClient = new TestClient(userId, "DEVICE", accessToken); @@ -177,7 +216,7 @@ describe("getEventTimeline support", function() { it("scrollback should be able to scroll back to before a gappy /sync", function() { // need a client with timelineSupport disabled to make this work - let room; + let room: Room; return startClient(httpBackend, client).then(function() { room = client.getRoom(roomId); @@ -189,7 +228,7 @@ describe("getEventTimeline support", function() { "!foo:bar": { timeline: { events: [ - EVENTS[0], + withoutRoomId(EVENTS[0]), ], prev_batch: "f_1_1", }, @@ -205,7 +244,7 @@ describe("getEventTimeline support", function() { "!foo:bar": { timeline: { events: [ - EVENTS[1], + withoutRoomId(EVENTS[1]), ], limited: true, prev_batch: "f_1_2", @@ -240,8 +279,8 @@ describe("getEventTimeline support", function() { }); describe("MatrixClient event timelines", function() { - let client = null; - let httpBackend = null; + let client: MatrixClient; + let httpBackend: TestClient["httpBackend"]; beforeEach(function() { const testClient = new TestClient( @@ -260,7 +299,7 @@ describe("MatrixClient event timelines", function() { afterEach(function() { httpBackend.verifyNoOutstandingExpectation(); client.stopClient(); - Thread.setServerSideSupport(false); + Thread.setServerSideSupport(false, false); }); describe("getEventTimeline", function() { @@ -308,7 +347,7 @@ describe("MatrixClient event timelines", function() { "!foo:bar": { timeline: { events: [ - EVENTS[0], + withoutRoomId(EVENTS[0]), ], prev_batch: "f_1_2", }, @@ -343,7 +382,7 @@ describe("MatrixClient event timelines", function() { "!foo:bar": { timeline: { events: [ - EVENTS[3], + withoutRoomId(EVENTS[3]), ], prev_batch: "f_1_2", }, @@ -366,7 +405,7 @@ describe("MatrixClient event timelines", function() { }); const prom = new Promise((resolve, reject) => { - client.on("sync", function() { + client.on(ClientEvent.Sync, function() { client.getEventTimeline(timelineSet, EVENTS[2].event_id, ).then(function(tl) { expect(tl.getEvents().length).toEqual(4); @@ -511,8 +550,9 @@ describe("MatrixClient event timelines", function() { }); it("should handle thread replies with server support by fetching a contiguous thread timeline", async () => { + // @ts-ignore client.clientOpts.experimentalThreadSupport = true; - Thread.setServerSideSupport(true); + Thread.setServerSideSupport(true, false); client.stopClient(); // we don't need the client to be syncing at this time const room = client.getRoom(roomId); const thread = room.createThread(THREAD_ROOT.event_id, undefined, [], false); @@ -556,8 +596,9 @@ describe("MatrixClient event timelines", function() { }); it("should return relevant timeline from non-thread timelineSet when asking for the thread root", async () => { + // @ts-ignore client.clientOpts.experimentalThreadSupport = true; - Thread.setServerSideSupport(true); + Thread.setServerSideSupport(true, false); client.stopClient(); // we don't need the client to be syncing at this time const room = client.getRoom(roomId); const threadRoot = new MatrixEvent(THREAD_ROOT); @@ -587,8 +628,9 @@ describe("MatrixClient event timelines", function() { }); it("should return undefined when event is not in the thread that the given timelineSet is representing", () => { + // @ts-ignore client.clientOpts.experimentalThreadSupport = true; - Thread.setServerSideSupport(true); + Thread.setServerSideSupport(true, false); client.stopClient(); // we don't need the client to be syncing at this time const room = client.getRoom(roomId); const threadRoot = new MatrixEvent(THREAD_ROOT); @@ -614,8 +656,9 @@ describe("MatrixClient event timelines", function() { }); it("should return undefined when event is within a thread but timelineSet is not", () => { + // @ts-ignore client.clientOpts.experimentalThreadSupport = true; - Thread.setServerSideSupport(true); + Thread.setServerSideSupport(true, false); client.stopClient(); // we don't need the client to be syncing at this time const room = client.getRoom(roomId); const timelineSet = room.getTimelineSets()[0]; @@ -639,6 +682,7 @@ describe("MatrixClient event timelines", function() { }); it("should should add lazy loading filter when requested", async () => { + // @ts-ignore client.clientOpts.lazyLoadMembers = true; client.stopClient(); // we don't need the client to be syncing at this time const room = client.getRoom(roomId); @@ -656,7 +700,7 @@ describe("MatrixClient event timelines", function() { }; }); req.check((request) => { - expect(request.opts.qs.filter).toEqual(JSON.stringify(Filter.LAZY_LOADING_MESSAGES_FILTER)); + expect(request.queryParams.filter).toEqual(JSON.stringify(Filter.LAZY_LOADING_MESSAGES_FILTER)); }); await Promise.all([ @@ -863,7 +907,7 @@ describe("MatrixClient event timelines", function() { "!foo:bar": { timeline: { events: [ - event, + withoutRoomId(event), ], prev_batch: "f_1_1", }, @@ -941,11 +985,10 @@ describe("MatrixClient event timelines", function() { // a state event, followed by a redaction thereof const event = utils.mkMembership({ - room: roomId, mship: "join", user: otherUserId, + mship: "join", user: otherUserId, }); const redaction = utils.mkEvent({ type: "m.room.redaction", - room_id: roomId, sender: otherUserId, content: {}, }); @@ -987,7 +1030,7 @@ describe("MatrixClient event timelines", function() { timeline: { events: [ utils.mkMessage({ - room: roomId, user: otherUserId, msg: "world", + user: otherUserId, msg: "world", }), ], limited: true, @@ -1006,4 +1049,75 @@ describe("MatrixClient event timelines", function() { expect(tl.getEvents().length).toEqual(1); }); }); + + it("should re-insert room IDs for bundled thread relation events", async () => { + // @ts-ignore + client.clientOpts.experimentalThreadSupport = true; + Thread.setServerSideSupport(true, false); + + httpBackend.when("GET", "/sync").respond(200, { + next_batch: "s_5_4", + rooms: { + join: { + [roomId]: { + timeline: { + events: [ + SYNC_THREAD_ROOT, + ], + prev_batch: "f_1_1", + }, + }, + }, + }, + }); + await Promise.all([httpBackend.flushAllExpected(), utils.syncPromise(client)]); + + const room = client.getRoom(roomId); + const thread = room.getThread(THREAD_ROOT.event_id); + const timelineSet = thread.timelineSet; + + httpBackend.when("GET", "/rooms/!foo%3Abar/context/" + encodeURIComponent(THREAD_ROOT.event_id)) + .respond(200, { + start: "start_token", + events_before: [], + event: THREAD_ROOT, + events_after: [], + state: [], + end: "end_token", + }); + httpBackend.when("GET", "/rooms/!foo%3Abar/relations/" + + encodeURIComponent(THREAD_ROOT.event_id) + "/" + + encodeURIComponent(THREAD_RELATION_TYPE.name) + "?limit=20") + .respond(200, function() { + return { + original_event: THREAD_ROOT, + chunk: [THREAD_REPLY], + // no next batch as this is the oldest end of the timeline + }; + }); + await Promise.all([ + client.getEventTimeline(timelineSet, THREAD_ROOT.event_id), + httpBackend.flushAllExpected(), + ]); + + httpBackend.when("GET", "/sync").respond(200, { + next_batch: "s_5_5", + rooms: { + join: { + [roomId]: { + timeline: { + events: [ + SYNC_THREAD_REPLY, + ], + prev_batch: "f_1_2", + }, + }, + }, + }, + }); + + await Promise.all([httpBackend.flushAllExpected(), utils.syncPromise(client)]); + + expect(thread.liveTimeline.getEvents()[1].event).toEqual(THREAD_REPLY); + }); }); diff --git a/spec/integ/matrix-client-methods.spec.js b/spec/integ/matrix-client-methods.spec.js index 5c9855b2e..0dd33a02c 100644 --- a/spec/integ/matrix-client-methods.spec.js +++ b/spec/integ/matrix-client-methods.spec.js @@ -27,11 +27,19 @@ describe("MatrixClient", function() { let store = null; const userId = "@alice:localhost"; const accessToken = "aseukfgwef"; + const idServerDomain = "identity.localhost"; // not a real server + const identityAccessToken = "woop-i-am-a-secret"; beforeEach(function() { store = new MemoryStore(); - const testClient = new TestClient(userId, "aliceDevice", accessToken, undefined, { store }); + const testClient = new TestClient(userId, "aliceDevice", accessToken, undefined, { + store, + identityServer: { + getAccessToken: () => Promise.resolve(identityAccessToken), + }, + idBaseUrl: `https://${idServerDomain}`, + }); httpBackend = testClient.httpBackend; client = testClient.client; }); @@ -993,7 +1001,7 @@ describe("MatrixClient", function() { }; httpBackend.when("GET", "/_matrix/client/versions").respond(200, { - versions: ["r0.5.0"], + versions: ["r0.6.0"], }); const prom = client.requestRegisterEmailToken("bob@email", "secret", 1); @@ -1008,6 +1016,64 @@ describe("MatrixClient", function() { expect(await prom).toStrictEqual(response); }); }); + + describe("inviteByThreePid", () => { + it("should supply an id_access_token", async () => { + const targetEmail = "gerald@example.org"; + + httpBackend.when("GET", "/_matrix/client/versions").respond(200, { + versions: ["r0.6.0"], + }); + + httpBackend.when("POST", "/invite").check(req => { + expect(req.data).toStrictEqual({ + id_server: idServerDomain, + id_access_token: identityAccessToken, + medium: "email", + address: targetEmail, + }); + }).respond(200, {}); + + const prom = client.inviteByThreePid("!room:example.org", "email", targetEmail); + await httpBackend.flush(); + await prom; // returns empty object, so no validation needed + }); + }); + + describe("createRoom", () => { + it("should populate id_access_token on 3pid invites", async () => { + const targetEmail = "gerald@example.org"; + const response = { + room_id: "!room:localhost", + }; + const input = { + invite_3pid: [{ + // we intentionally exclude the access token here, so it can be populated for us + id_server: idServerDomain, + medium: "email", + address: targetEmail, + }], + }; + + httpBackend.when("GET", "/_matrix/client/versions").respond(200, { + versions: ["r0.6.0"], + }); + + httpBackend.when("POST", "/createRoom").check(req => { + expect(req.data).toMatchObject({ + invite_3pid: expect.arrayContaining([{ + ...input.invite_3pid[0], + id_access_token: identityAccessToken, + }]), + }); + expect(req.data.invite_3pid.length).toBe(1); + }).respond(200, response); + + const prom = client.createRoom(input); + await httpBackend.flush(); + expect(await prom).toStrictEqual(response); + }); + }); }); function withThreadId(event, newThreadId) { diff --git a/spec/test-utils/test-utils.ts b/spec/test-utils/test-utils.ts index 84a9662e4..4e0a311a0 100644 --- a/spec/test-utils/test-utils.ts +++ b/spec/test-utils/test-utils.ts @@ -70,7 +70,7 @@ export function mock(constr: { new(...args: any[]): T }, name: string): T { interface IEventOpts { type: EventType | string; - room: string; + room?: string; sender?: string; skey?: string; content: IContent; @@ -93,8 +93,8 @@ let testEventIndex = 1; // counter for events, easier for comparison of randomly * @return {Object} a JSON object representing this event. */ export function mkEvent(opts: IEventOpts & { event: true }, client?: MatrixClient): MatrixEvent; -export function mkEvent(opts: IEventOpts & { event?: false }, client?: MatrixClient): object; -export function mkEvent(opts: IEventOpts & { event?: boolean }, client?: MatrixClient): object | MatrixEvent { +export function mkEvent(opts: IEventOpts & { event?: false }, client?: MatrixClient): Partial; +export function mkEvent(opts: IEventOpts & { event?: boolean }, client?: MatrixClient): Partial | MatrixEvent { if (!opts.type || !opts.content) { throw new Error("Missing .type or .content =>" + JSON.stringify(opts)); } @@ -145,8 +145,8 @@ interface IPresenceOpts { * @return {Object|MatrixEvent} The event */ export function mkPresence(opts: IPresenceOpts & { event: true }): MatrixEvent; -export function mkPresence(opts: IPresenceOpts & { event?: false }): object; -export function mkPresence(opts: IPresenceOpts & { event?: boolean }): object | MatrixEvent { +export function mkPresence(opts: IPresenceOpts & { event?: false }): Partial; +export function mkPresence(opts: IPresenceOpts & { event?: boolean }): Partial | MatrixEvent { const event = { event_id: "$" + Math.random() + "-" + Math.random(), type: "m.presence", @@ -162,7 +162,7 @@ export function mkPresence(opts: IPresenceOpts & { event?: boolean }): object | } interface IMembershipOpts { - room: string; + room?: string; mship: string; sender?: string; user?: string; @@ -186,8 +186,8 @@ interface IMembershipOpts { * @return {Object|MatrixEvent} The event */ export function mkMembership(opts: IMembershipOpts & { event: true }): MatrixEvent; -export function mkMembership(opts: IMembershipOpts & { event?: false }): object; -export function mkMembership(opts: IMembershipOpts & { event?: boolean }): object | MatrixEvent { +export function mkMembership(opts: IMembershipOpts & { event?: false }): Partial; +export function mkMembership(opts: IMembershipOpts & { event?: boolean }): Partial | MatrixEvent { const eventOpts: IEventOpts = { ...opts, type: EventType.RoomMember, @@ -209,7 +209,7 @@ export function mkMembership(opts: IMembershipOpts & { event?: boolean }): objec } interface IMessageOpts { - room: string; + room?: string; user: string; msg?: string; event?: boolean; @@ -226,8 +226,11 @@ interface IMessageOpts { * @return {Object|MatrixEvent} The event */ export function mkMessage(opts: IMessageOpts & { event: true }, client?: MatrixClient): MatrixEvent; -export function mkMessage(opts: IMessageOpts & { event?: false }, client?: MatrixClient): object; -export function mkMessage(opts: IMessageOpts & { event?: boolean }, client?: MatrixClient): object | MatrixEvent { +export function mkMessage(opts: IMessageOpts & { event?: false }, client?: MatrixClient): Partial; +export function mkMessage( + opts: IMessageOpts & { event?: boolean }, + client?: MatrixClient, +): Partial | MatrixEvent { const eventOpts: IEventOpts = { ...opts, type: EventType.RoomMessage, @@ -260,11 +263,11 @@ interface IReplyMessageOpts extends IMessageOpts { * @return {Object|MatrixEvent} The event */ export function mkReplyMessage(opts: IReplyMessageOpts & { event: true }, client?: MatrixClient): MatrixEvent; -export function mkReplyMessage(opts: IReplyMessageOpts & { event?: false }, client?: MatrixClient): object; +export function mkReplyMessage(opts: IReplyMessageOpts & { event?: false }, client?: MatrixClient): Partial; export function mkReplyMessage( opts: IReplyMessageOpts & { event?: boolean }, client?: MatrixClient, -): object | MatrixEvent { +): Partial | MatrixEvent { const eventOpts: IEventOpts = { ...opts, type: EventType.RoomMessage, diff --git a/spec/test-utils/webrtc.ts b/spec/test-utils/webrtc.ts new file mode 100644 index 000000000..8b5946912 --- /dev/null +++ b/spec/test-utils/webrtc.ts @@ -0,0 +1,157 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +export const DUMMY_SDP = ( + "v=0\r\n" + + "o=- 5022425983810148698 2 IN IP4 127.0.0.1\r\n" + + "s=-\r\nt=0 0\r\na=group:BUNDLE 0\r\n" + + "a=msid-semantic: WMS h3wAi7s8QpiQMH14WG3BnDbmlOqo9I5ezGZA\r\n" + + "m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126\r\n" + + "c=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:hLDR\r\n" + + "a=ice-pwd:bMGD9aOldHWiI+6nAq/IIlRw\r\n" + + "a=ice-options:trickle\r\n" + + "a=fingerprint:sha-256 E4:94:84:F9:4A:98:8A:56:F5:5F:FD:AF:72:B9:32:89:49:5C:4B:9A:" + + "4A:15:8E:41:8A:F3:69:E4:39:52:DC:D6\r\n" + + "a=setup:active\r\n" + + "a=mid:0\r\n" + + "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n" + + "a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\n" + + "a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\n" + + "a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\r\n" + + "a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id\r\n" + + "a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id\r\n" + + "a=sendrecv\r\n" + + "a=msid:h3wAi7s8QpiQMH14WG3BnDbmlOqo9I5ezGZA 4357098f-3795-4131-bff4-9ba9c0348c49\r\n" + + "a=rtcp-mux\r\n" + + "a=rtpmap:111 opus/48000/2\r\n" + + "a=rtcp-fb:111 transport-cc\r\n" + + "a=fmtp:111 minptime=10;useinbandfec=1\r\n" + + "a=rtpmap:103 ISAC/16000\r\n" + + "a=rtpmap:104 ISAC/32000\r\n" + + "a=rtpmap:9 G722/8000\r\n" + + "a=rtpmap:0 PCMU/8000\r\n" + + "a=rtpmap:8 PCMA/8000\r\n" + + "a=rtpmap:106 CN/32000\r\n" + + "a=rtpmap:105 CN/16000\r\n" + + "a=rtpmap:13 CN/8000\r\n" + + "a=rtpmap:110 telephone-event/48000\r\n" + + "a=rtpmap:112 telephone-event/32000\r\n" + + "a=rtpmap:113 telephone-event/16000\r\n" + + "a=rtpmap:126 telephone-event/8000\r\n" + + "a=ssrc:3619738545 cname:2RWtmqhXLdoF4sOi\r\n" +); + +class MockMediaStreamAudioSourceNode { + connect() {} +} + +export class MockAudioContext { + constructor() {} + createAnalyser() { return {}; } + createMediaStreamSource() { return new MockMediaStreamAudioSourceNode(); } + close() {} +} + +export class MockRTCPeerConnection { + localDescription: RTCSessionDescription; + + constructor() { + this.localDescription = { + sdp: DUMMY_SDP, + type: 'offer', + toJSON: function() { }, + }; + } + + addEventListener() { } + createDataChannel(label: string, opts: RTCDataChannelInit) { return { label, ...opts }; } + createOffer() { + return Promise.resolve({}); + } + setRemoteDescription() { + return Promise.resolve(); + } + setLocalDescription() { + return Promise.resolve(); + } + close() { } + getStats() { return []; } + addTrack(track: MockMediaStreamTrack) { return new MockRTCRtpSender(track); } +} + +export class MockRTCRtpSender { + constructor(public track: MockMediaStreamTrack) { } + + replaceTrack(track: MockMediaStreamTrack) { this.track = track; } +} + +export class MockMediaStreamTrack { + constructor(public readonly id: string, public readonly kind: "audio" | "video", public enabled = true) { } + + stop() { } +} + +// XXX: Using EventTarget in jest doesn't seem to work, so we write our own +// implementation +export class MockMediaStream { + constructor( + public id: string, + private tracks: MockMediaStreamTrack[] = [], + ) {} + + listeners: [string, (...args: any[]) => any][] = []; + + dispatchEvent(eventType: string) { + this.listeners.forEach(([t, c]) => { + if (t !== eventType) return; + c(); + }); + } + getTracks() { return this.tracks; } + getAudioTracks() { return this.tracks.filter((track) => track.kind === "audio"); } + getVideoTracks() { return this.tracks.filter((track) => track.kind === "video"); } + addEventListener(eventType: string, callback: (...args: any[]) => any) { + this.listeners.push([eventType, callback]); + } + removeEventListener(eventType: string, callback: (...args: any[]) => any) { + this.listeners.filter(([t, c]) => { + return t !== eventType || c !== callback; + }); + } + addTrack(track: MockMediaStreamTrack) { + this.tracks.push(track); + this.dispatchEvent("addtrack"); + } + removeTrack(track: MockMediaStreamTrack) { this.tracks.splice(this.tracks.indexOf(track), 1); } +} + +export class MockMediaDeviceInfo { + constructor( + public kind: "audio" | "video", + ) { } +} + +export class MockMediaHandler { + getUserMediaStream(audio: boolean, video: boolean) { + const tracks = []; + if (audio) tracks.push(new MockMediaStreamTrack("audio_track", "audio")); + if (video) tracks.push(new MockMediaStreamTrack("video_track", "video")); + + return new MockMediaStream("mock_stream_from_media_handler", tracks); + } + stopUserMediaStream() { } + hasAudioDevice() { return true; } +} diff --git a/spec/unit/crypto/backup.spec.js b/spec/unit/crypto/backup.spec.ts similarity index 78% rename from spec/unit/crypto/backup.spec.js rename to spec/unit/crypto/backup.spec.ts index cab0c0d0d..6759fe161 100644 --- a/spec/unit/crypto/backup.spec.js +++ b/spec/unit/crypto/backup.spec.ts @@ -15,6 +15,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +import { MockedObject } from "jest-mock"; + import '../../olm-loader'; import { logger } from "../../../src/logger"; import * as olmlib from "../../../src/crypto/olmlib"; @@ -22,12 +24,13 @@ import { MatrixClient } from "../../../src/client"; import { MatrixEvent } from "../../../src/models/event"; import * as algorithms from "../../../src/crypto/algorithms"; import { MemoryCryptoStore } from "../../../src/crypto/store/memory-crypto-store"; -import { MockStorageApi } from "../../MockStorageApi"; import * as testUtils from "../../test-utils/test-utils"; import { OlmDevice } from "../../../src/crypto/OlmDevice"; import { Crypto } from "../../../src/crypto"; import { resetCrossSigningKeys } from "./crypto-utils"; import { BackupManager } from "../../../src/crypto/backup"; +import { StubStore } from "../../../src/store/stub"; +import { IAbortablePromise, MatrixScheduler } from '../../../src'; const Olm = global.Olm; @@ -92,8 +95,8 @@ const AES256_KEY_BACKUP_DATA = { }; const CURVE25519_BACKUP_INFO = { - algorithm: "m.megolm_backup.v1.curve25519-aes-sha2", - version: 1, + algorithm: olmlib.MEGOLM_BACKUP_ALGORITHM, + version: '1', auth_data: { public_key: "hSDwCYkwp1R0i33ctD73Wg2/Og0mOBr066SpjqqbTmo", }, @@ -101,7 +104,7 @@ const CURVE25519_BACKUP_INFO = { const AES256_BACKUP_INFO = { algorithm: "org.matrix.msc3270.v1.aes-hmac-sha2", - version: 1, + version: '1', auth_data: { // FIXME: add iv and mac }, @@ -121,21 +124,14 @@ function makeTestClient(cryptoStore) { const scheduler = [ "getQueueForEvent", "queueEvent", "removeEventFromQueue", "setProcessFunction", - ].reduce((r, k) => {r[k] = jest.fn(); return r;}, {}); - const store = [ - "getRoom", "getRooms", "getUser", "getSyncToken", "scrollback", - "save", "wantsSave", "setSyncToken", "storeEvents", "storeRoom", - "storeUser", "getFilterIdByName", "setFilterIdByName", "getFilter", - "storeFilter", "getSyncAccumulator", "startup", "deleteAllData", - ].reduce((r, k) => {r[k] = jest.fn(); return r;}, {}); - store.getSavedSync = jest.fn().mockReturnValue(Promise.resolve(null)); - store.getSavedSyncToken = jest.fn().mockReturnValue(Promise.resolve(null)); - store.setSyncData = jest.fn().mockReturnValue(Promise.resolve(null)); + ].reduce((r, k) => {r[k] = jest.fn(); return r;}, {}) as MockedObject; + const store = new StubStore(); + return new MatrixClient({ baseUrl: "https://my.home.server", idBaseUrl: "https://identity.server", accessToken: "my.access.token", - request: function() {}, // NOP + request: jest.fn(), // NOP store: store, scheduler: scheduler, userId: "@alice:bar", @@ -158,7 +154,6 @@ describe("MegolmBackup", function() { let olmDevice; let mockOlmLib; let mockCrypto; - let mockStorage; let cryptoStore; let megolmDecryption; beforeEach(async function() { @@ -170,8 +165,7 @@ describe("MegolmBackup", function() { ); mockCrypto.backupInfo = CURVE25519_BACKUP_INFO; - mockStorage = new MockStorageApi(); - cryptoStore = new MemoryCryptoStore(mockStorage); + cryptoStore = new MemoryCryptoStore(); olmDevice = new OlmDevice(cryptoStore); @@ -184,7 +178,6 @@ describe("MegolmBackup", function() { describe("backup", function() { let mockBaseApis; - let realSetTimeout; beforeEach(function() { mockBaseApis = {}; @@ -202,14 +195,14 @@ describe("MegolmBackup", function() { // clobber the setTimeout function to run 100x faster. // ideally we would use lolex, but we have no oportunity // to tick the clock between the first try and the retry. - realSetTimeout = global.setTimeout; - global.setTimeout = function(f, n) { + const realSetTimeout = global.setTimeout; + jest.spyOn(global, 'setTimeout').mockImplementation(function(f, n) { return realSetTimeout(f, n/100); - }; + }); }); afterEach(function() { - global.setTimeout = realSetTimeout; + jest.spyOn(global, 'setTimeout').mockRestore(); }); it('automatically calls the key back up', function() { @@ -289,16 +282,16 @@ describe("MegolmBackup", function() { txn); }); }) - .then(() => { - client.enableKeyBackup({ - algorithm: "m.megolm_backup.v1.curve25519-aes-sha2", - version: 1, + .then(async () => { + await client.enableKeyBackup({ + algorithm: olmlib.MEGOLM_BACKUP_ALGORITHM, + version: '1', auth_data: { public_key: "hSDwCYkwp1R0i33ctD73Wg2/Og0mOBr066SpjqqbTmo", }, }); let numCalls = 0; - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { client.http.authedRequest = function( callback, method, path, queryParams, data, opts, ) { @@ -307,17 +300,17 @@ describe("MegolmBackup", function() { if (numCalls >= 2) { // exit out of retry loop if there's something wrong reject(new Error("authedRequest called too many timmes")); - return Promise.resolve({}); + return Promise.resolve({}) as IAbortablePromise; } expect(method).toBe("PUT"); expect(path).toBe("/room_keys/keys"); - expect(queryParams.version).toBe(1); + expect(queryParams.version).toBe('1'); expect(data.rooms[ROOM_ID].sessions).toBeDefined(); expect(data.rooms[ROOM_ID].sessions).toHaveProperty( groupSession.session_id(), ); resolve(); - return Promise.resolve({}); + return Promise.resolve({}) as IAbortablePromise; }; client.crypto.backupManager.backupGroupSession( "F0Q2NmyJNgUVj9DGsb4ZQt3aVxhVcUQhg7+gvW0oyKI", @@ -371,17 +364,17 @@ describe("MegolmBackup", function() { txn); }); }) - .then(() => { - client.enableKeyBackup({ + .then(async () => { + await client.enableKeyBackup({ algorithm: "org.matrix.msc3270.v1.aes-hmac-sha2", - version: 1, + version: '1', auth_data: { iv: "PsCAtR7gMc4xBd9YS3A9Ow", mac: "ZSDsTFEZK7QzlauCLMleUcX96GQZZM7UNtk4sripSqQ", }, }); let numCalls = 0; - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { client.http.authedRequest = function( callback, method, path, queryParams, data, opts, ) { @@ -390,17 +383,17 @@ describe("MegolmBackup", function() { if (numCalls >= 2) { // exit out of retry loop if there's something wrong reject(new Error("authedRequest called too many timmes")); - return Promise.resolve({}); + return Promise.resolve({}) as IAbortablePromise; } expect(method).toBe("PUT"); expect(path).toBe("/room_keys/keys"); - expect(queryParams.version).toBe(1); + expect(queryParams.version).toBe('1'); expect(data.rooms[ROOM_ID].sessions).toBeDefined(); expect(data.rooms[ROOM_ID].sessions).toHaveProperty( groupSession.session_id(), ); resolve(); - return Promise.resolve({}); + return Promise.resolve({}) as IAbortablePromise; }; client.crypto.backupManager.backupGroupSession( "F0Q2NmyJNgUVj9DGsb4ZQt3aVxhVcUQhg7+gvW0oyKI", @@ -432,19 +425,12 @@ describe("MegolmBackup", function() { megolmDecryption.olmlib = mockOlmLib; await client.initCrypto(); - let privateKeys; - client.uploadDeviceSigningKeys = async function(e) {return;}; - client.uploadKeySignatures = async function(e) {return;}; - client.on("crossSigning.saveCrossSigningKeys", function(e) { - privateKeys = e; - }); - client.on("crossSigning.getKey", function(e) { - e.done(privateKeys[e.type]); - }); + client.uploadDeviceSigningKeys = async function(e) {return {};}; + client.uploadKeySignatures = async function(e) {return { failures: {} };}; await resetCrossSigningKeys(client); let numCalls = 0; await Promise.all([ - new Promise((resolve, reject) => { + new Promise((resolve, reject) => { let backupInfo; client.http.authedRequest = function( callback, method, path, queryParams, data, opts, @@ -461,24 +447,24 @@ describe("MegolmBackup", function() { ); } catch (e) { reject(e); - return Promise.resolve({}); + return Promise.resolve({}) as IAbortablePromise; } backupInfo = data; - return Promise.resolve({}); + return Promise.resolve({}) as IAbortablePromise; } else if (numCalls === 2) { expect(method).toBe("GET"); expect(path).toBe("/room_keys/version"); resolve(); - return Promise.resolve(backupInfo); + return Promise.resolve(backupInfo) as IAbortablePromise; } else { // exit out of retry loop if there's something wrong reject(new Error("authedRequest called too many times")); - return Promise.resolve({}); + return Promise.resolve({}) as IAbortablePromise; } }; }), client.createKeyBackupVersion({ - algorithm: "m.megolm_backup.v1.curve25519-aes-sha2", + algorithm: olmlib.MEGOLM_BACKUP_ALGORITHM, auth_data: { public_key: "hSDwCYkwp1R0i33ctD73Wg2/Og0mOBr066SpjqqbTmo", }, @@ -488,7 +474,7 @@ describe("MegolmBackup", function() { client.stopClient(); }); - it('retries when a backup fails', function() { + it('retries when a backup fails', async function() { const groupSession = new Olm.OutboundGroupSession(); groupSession.create(); const ibGroupSession = new Olm.InboundGroupSession(); @@ -497,21 +483,13 @@ describe("MegolmBackup", function() { const scheduler = [ "getQueueForEvent", "queueEvent", "removeEventFromQueue", "setProcessFunction", - ].reduce((r, k) => {r[k] = jest.fn(); return r;}, {}); - const store = [ - "getRoom", "getRooms", "getUser", "getSyncToken", "scrollback", - "save", "wantsSave", "setSyncToken", "storeEvents", "storeRoom", - "storeUser", "getFilterIdByName", "setFilterIdByName", "getFilter", - "storeFilter", "getSyncAccumulator", "startup", "deleteAllData", - ].reduce((r, k) => {r[k] = jest.fn(); return r;}, {}); - store.getSavedSync = jest.fn().mockReturnValue(Promise.resolve(null)); - store.getSavedSyncToken = jest.fn().mockReturnValue(Promise.resolve(null)); - store.setSyncData = jest.fn().mockReturnValue(Promise.resolve(null)); + ].reduce((r, k) => {r[k] = jest.fn(); return r;}, {}) as MockedObject; + const store = new StubStore(); const client = new MatrixClient({ baseUrl: "https://my.home.server", idBaseUrl: "https://identity.server", accessToken: "my.access.token", - request: function() {}, // NOP + request: jest.fn(), // NOP store: store, scheduler: scheduler, userId: "@alice:bar", @@ -529,71 +507,68 @@ describe("MegolmBackup", function() { megolmDecryption.olmlib = mockOlmLib; - return client.initCrypto() - .then(() => { - return cryptoStore.doTxn( - "readwrite", - [cryptoStore.STORE_SESSION], - (txn) => { - cryptoStore.addEndToEndInboundGroupSession( - "F0Q2NmyJNgUVj9DGsb4ZQt3aVxhVcUQhg7+gvW0oyKI", - groupSession.session_id(), - { - forwardingCurve25519KeyChain: undefined, - keysClaimed: { - ed25519: "SENDER_ED25519", - }, - room_id: ROOM_ID, - session: ibGroupSession.pickle(olmDevice.pickleKey), - }, - txn); - }); - }) - .then(() => { - client.enableKeyBackup({ - algorithm: "m.megolm_backup.v1.curve25519-aes-sha2", - version: 1, - auth_data: { - public_key: "hSDwCYkwp1R0i33ctD73Wg2/Og0mOBr066SpjqqbTmo", + await client.initCrypto(); + await cryptoStore.doTxn( + "readwrite", + [cryptoStore.STORE_SESSION], + (txn) => { + cryptoStore.addEndToEndInboundGroupSession( + "F0Q2NmyJNgUVj9DGsb4ZQt3aVxhVcUQhg7+gvW0oyKI", + groupSession.session_id(), + { + forwardingCurve25519KeyChain: undefined, + keysClaimed: { + ed25519: "SENDER_ED25519", + }, + room_id: ROOM_ID, + session: ibGroupSession.pickle(olmDevice.pickleKey), }, - }); - let numCalls = 0; - return new Promise((resolve, reject) => { - client.http.authedRequest = function( - callback, method, path, queryParams, data, opts, - ) { - ++numCalls; - expect(numCalls).toBeLessThanOrEqual(2); - if (numCalls >= 3) { - // exit out of retry loop if there's something wrong - reject(new Error("authedRequest called too many timmes")); - return Promise.resolve({}); - } - expect(method).toBe("PUT"); - expect(path).toBe("/room_keys/keys"); - expect(queryParams.version).toBe(1); - expect(data.rooms[ROOM_ID].sessions).toBeDefined(); - expect(data.rooms[ROOM_ID].sessions).toHaveProperty( - groupSession.session_id(), - ); - if (numCalls > 1) { - resolve(); - return Promise.resolve({}); - } else { - return Promise.reject( - new Error("this is an expected failure"), - ); - } - }; - client.crypto.backupManager.backupGroupSession( - "F0Q2NmyJNgUVj9DGsb4ZQt3aVxhVcUQhg7+gvW0oyKI", - groupSession.session_id(), - ); - }).then(() => { - expect(numCalls).toBe(2); - client.stopClient(); - }); + txn); }); + + await client.enableKeyBackup({ + algorithm: olmlib.MEGOLM_BACKUP_ALGORITHM, + version: '1', + auth_data: { + public_key: "hSDwCYkwp1R0i33ctD73Wg2/Og0mOBr066SpjqqbTmo", + }, + }); + let numCalls = 0; + + await new Promise((resolve, reject) => { + client.http.authedRequest = function( + callback, method, path, queryParams, data, opts, + ) { + ++numCalls; + expect(numCalls).toBeLessThanOrEqual(2); + if (numCalls >= 3) { + // exit out of retry loop if there's something wrong + reject(new Error("authedRequest called too many timmes")); + return Promise.resolve({}) as IAbortablePromise; + } + expect(method).toBe("PUT"); + expect(path).toBe("/room_keys/keys"); + expect(queryParams.version).toBe('1'); + expect(data.rooms[ROOM_ID].sessions).toBeDefined(); + expect(data.rooms[ROOM_ID].sessions).toHaveProperty( + groupSession.session_id(), + ); + if (numCalls > 1) { + resolve(); + return Promise.resolve({}) as IAbortablePromise; + } else { + return Promise.reject( + new Error("this is an expected failure"), + ) as IAbortablePromise; + } + }; + return client.crypto.backupManager.backupGroupSession( + "F0Q2NmyJNgUVj9DGsb4ZQt3aVxhVcUQhg7+gvW0oyKI", + groupSession.session_id(), + ); + }); + expect(numCalls).toBe(2); + client.stopClient(); }); }); diff --git a/spec/unit/crypto/crypto-utils.js b/spec/unit/crypto/crypto-utils.ts similarity index 78% rename from spec/unit/crypto/crypto-utils.js rename to spec/unit/crypto/crypto-utils.ts index ecc6fc4b0..3535edaab 100644 --- a/spec/unit/crypto/crypto-utils.js +++ b/spec/unit/crypto/crypto-utils.ts @@ -1,11 +1,13 @@ +import { IRecoveryKey } from '../../../src/crypto/api'; +import { CrossSigningLevel } from '../../../src/crypto/CrossSigning'; import { IndexedDBCryptoStore } from '../../../src/crypto/store/indexeddb-crypto-store'; // needs to be phased out and replaced with bootstrapSecretStorage, // but that is doing too much extra stuff for it to be an easy transition. -export async function resetCrossSigningKeys(client, { - level, - authUploadDeviceSigningKeys = async func => await func(), -} = {}) { +export async function resetCrossSigningKeys( + client, + { level }: { level?: CrossSigningLevel} = {}, +): Promise { const crypto = client.crypto; const oldKeys = Object.assign({}, crypto.crossSigningInfo.keys); @@ -30,14 +32,14 @@ export async function resetCrossSigningKeys(client, { await crypto.afterCrossSigningLocalKeyChange(); } -export async function createSecretStorageKey() { +export async function createSecretStorageKey(): Promise { const decryption = new global.Olm.PkDecryption(); const storagePublicKey = decryption.generate_key(); const storagePrivateKey = decryption.get_private_key(); decryption.free(); return { // `pubkey` not used anymore with symmetric 4S - keyInfo: { pubkey: storagePublicKey }, + keyInfo: { pubkey: storagePublicKey, key: undefined }, privateKey: storagePrivateKey, }; } diff --git a/spec/unit/realtime-callbacks.spec.js b/spec/unit/realtime-callbacks.spec.js index f99152968..8e57e48e6 100644 --- a/spec/unit/realtime-callbacks.spec.js +++ b/spec/unit/realtime-callbacks.spec.js @@ -1,7 +1,7 @@ import * as callbacks from "../../src/realtime-callbacks"; let wallTime = 1234567890; -jest.useFakeTimers(); +jest.useFakeTimers().setSystemTime(wallTime); describe("realtime-callbacks", function() { function tick(millis) { @@ -9,14 +9,6 @@ describe("realtime-callbacks", function() { jest.advanceTimersByTime(millis); } - beforeEach(function() { - callbacks.setNow(() => wallTime); - }); - - afterEach(function() { - callbacks.setNow(); - }); - describe("setTimeout", function() { it("should call the callback after the timeout", function() { const callback = jest.fn(); diff --git a/spec/unit/utils.spec.ts b/spec/unit/utils.spec.ts index 340acf92d..03f663ab3 100644 --- a/spec/unit/utils.spec.ts +++ b/spec/unit/utils.spec.ts @@ -109,18 +109,6 @@ describe("utils", function() { }); }); - describe("checkObjectHasNoAdditionalKeys", function() { - it("should throw for extra keys", function() { - expect(function() { - utils.checkObjectHasNoAdditionalKeys({ foo: "bar", baz: 4 }, ["foo"]); - }).toThrow(); - - expect(function() { - utils.checkObjectHasNoAdditionalKeys({ foo: "bar" }, ["foo"]); - }).not.toThrow(); - }); - }); - describe("deepCompare", function() { const assert = { isTrue: function(x: any) { diff --git a/spec/unit/webrtc/call.spec.ts b/spec/unit/webrtc/call.spec.ts index 9195327be..6fc8a5a5d 100644 --- a/spec/unit/webrtc/call.spec.ts +++ b/spec/unit/webrtc/call.spec.ts @@ -1,5 +1,5 @@ /* -Copyright 2020 The Matrix.org Foundation C.I.C. +Copyright 2020 - 2022 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -15,130 +15,26 @@ limitations under the License. */ import { TestClient } from '../../TestClient'; -import { MatrixCall, CallErrorCode, CallEvent, supportsMatrixCall } from '../../../src/webrtc/call'; +import { MatrixCall, CallErrorCode, CallEvent, supportsMatrixCall, CallType } from '../../../src/webrtc/call'; import { SDPStreamMetadataKey, SDPStreamMetadataPurpose } from '../../../src/webrtc/callEventTypes'; -import { RoomMember } from "../../../src"; +import { + DUMMY_SDP, + MockMediaHandler, + MockMediaStream, + MockMediaStreamTrack, + MockMediaDeviceInfo, + MockRTCPeerConnection, + MockAudioContext, +} from "../../test-utils/webrtc"; +import { CallFeed } from "../../../src/webrtc/callFeed"; -const DUMMY_SDP = ( - "v=0\r\n" + - "o=- 5022425983810148698 2 IN IP4 127.0.0.1\r\n" + - "s=-\r\nt=0 0\r\na=group:BUNDLE 0\r\n" + - "a=msid-semantic: WMS h3wAi7s8QpiQMH14WG3BnDbmlOqo9I5ezGZA\r\n" + - "m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126\r\n" + - "c=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:hLDR\r\n" + - "a=ice-pwd:bMGD9aOldHWiI+6nAq/IIlRw\r\n" + - "a=ice-options:trickle\r\n" + - "a=fingerprint:sha-256 E4:94:84:F9:4A:98:8A:56:F5:5F:FD:AF:72:B9:32:89:49:5C:4B:9A:" + - "4A:15:8E:41:8A:F3:69:E4:39:52:DC:D6\r\n" + - "a=setup:active\r\n" + - "a=mid:0\r\n" + - "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n" + - "a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\n" + - "a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\n" + - "a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\r\n" + - "a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id\r\n" + - "a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id\r\n" + - "a=sendrecv\r\n" + - "a=msid:h3wAi7s8QpiQMH14WG3BnDbmlOqo9I5ezGZA 4357098f-3795-4131-bff4-9ba9c0348c49\r\n" + - "a=rtcp-mux\r\n" + - "a=rtpmap:111 opus/48000/2\r\n" + - "a=rtcp-fb:111 transport-cc\r\n" + - "a=fmtp:111 minptime=10;useinbandfec=1\r\n" + - "a=rtpmap:103 ISAC/16000\r\n" + - "a=rtpmap:104 ISAC/32000\r\n" + - "a=rtpmap:9 G722/8000\r\n" + - "a=rtpmap:0 PCMU/8000\r\n" + - "a=rtpmap:8 PCMA/8000\r\n" + - "a=rtpmap:106 CN/32000\r\n" + - "a=rtpmap:105 CN/16000\r\n" + - "a=rtpmap:13 CN/8000\r\n" + - "a=rtpmap:110 telephone-event/48000\r\n" + - "a=rtpmap:112 telephone-event/32000\r\n" + - "a=rtpmap:113 telephone-event/16000\r\n" + - "a=rtpmap:126 telephone-event/8000\r\n" + - "a=ssrc:3619738545 cname:2RWtmqhXLdoF4sOi\r\n" -); +const startVoiceCall = async (client: TestClient, call: MatrixCall): Promise => { + const callPromise = call.placeVoiceCall(); + await client.httpBackend.flush(""); + await callPromise; -class MockMediaStreamAudioSourceNode { - connect() {} -} - -class MockAudioContext { - constructor() {} - createAnalyser() { return {}; } - createMediaStreamSource() { return new MockMediaStreamAudioSourceNode(); } - close() {} -} - -class MockRTCPeerConnection { - localDescription: RTCSessionDescription; - - constructor() { - this.localDescription = { - sdp: DUMMY_SDP, - type: 'offer', - toJSON: function() {}, - }; - } - - addEventListener() {} - createOffer() { - return Promise.resolve({}); - } - setRemoteDescription() { - return Promise.resolve(); - } - setLocalDescription() { - return Promise.resolve(); - } - close() {} - getStats() { return []; } - addTrack(track: MockMediaStreamTrack) {return new MockRTCRtpSender(track);} -} - -class MockRTCRtpSender { - constructor(public track: MockMediaStreamTrack) {} - - replaceTrack(track: MockMediaStreamTrack) {this.track = track;} -} - -class MockMediaStreamTrack { - constructor(public readonly id: string, public readonly kind: "audio" | "video", public enabled = true) {} - - stop() {} -} - -class MockMediaStream { - constructor( - public id: string, - private tracks: MockMediaStreamTrack[] = [], - ) {} - - getTracks() { return this.tracks; } - getAudioTracks() { return this.tracks.filter((track) => track.kind === "audio"); } - getVideoTracks() { return this.tracks.filter((track) => track.kind === "video"); } - addEventListener() {} - removeEventListener() { } - addTrack(track: MockMediaStreamTrack) {this.tracks.push(track);} - removeTrack(track: MockMediaStreamTrack) {this.tracks.splice(this.tracks.indexOf(track), 1);} -} - -class MockMediaDeviceInfo { - constructor( - public kind: "audio" | "video", - ) {} -} - -class MockMediaHandler { - getUserMediaStream(audio: boolean, video: boolean) { - const tracks = []; - if (audio) tracks.push(new MockMediaStreamTrack("audio_track", "audio")); - if (video) tracks.push(new MockMediaStreamTrack("video_track", "video")); - - return new MockMediaStream("mock_stream_from_media_handler", tracks); - } - stopUserMediaStream() {} -} + call.getOpponentMember = jest.fn().mockReturnValue({ userId: "@bob:bar.uk" }); +}; describe('Call', function() { let client; @@ -207,9 +103,8 @@ describe('Call', function() { }); it('should ignore candidate events from non-matching party ID', async function() { - const callPromise = call.placeVoiceCall(); - await client.httpBackend.flush(); - await callPromise; + await startVoiceCall(client, call); + await call.onAnswerReceived({ getContent: () => { return { @@ -266,9 +161,7 @@ describe('Call', function() { }); it('should add candidates received before answer if party ID is correct', async function() { - const callPromise = call.placeVoiceCall(); - await client.httpBackend.flush(); - await callPromise; + await startVoiceCall(client, call); call.peerConn.addIceCandidate = jest.fn(); call.onRemoteIceCandidatesReceived({ @@ -329,9 +222,7 @@ describe('Call', function() { }); it('should map asserted identity messages to remoteAssertedIdentity', async function() { - const callPromise = call.placeVoiceCall(); - await client.httpBackend.flush(); - await callPromise; + await startVoiceCall(client, call); await call.onAnswerReceived({ getContent: () => { return { @@ -375,13 +266,7 @@ describe('Call', function() { }); it("should map SDPStreamMetadata to feeds", async () => { - const callPromise = call.placeVoiceCall(); - await client.httpBackend.flush(); - await callPromise; - - call.getOpponentMember = () => { - return { userId: "@bob:bar.uk" }; - }; + await startVoiceCall(client, call); await call.onAnswerReceived({ getContent: () => { @@ -420,13 +305,7 @@ describe('Call', function() { }); it("should fallback to replaceTrack() if the other side doesn't support SPDStreamMetadata", async () => { - const callPromise = call.placeVoiceCall(); - await client.httpBackend.flush(); - await callPromise; - - call.getOpponentMember = () => { - return { userId: "@bob:bar.uk" } as RoomMember; - }; + await startVoiceCall(client, call); await call.onAnswerReceived({ getContent: () => { @@ -470,9 +349,7 @@ describe('Call', function() { ), ); - const callPromise = call.placeVideoCall(); - await client.httpBackend.flush(); - await callPromise; + await startVoiceCall(client, call); await call.onAnswerReceived({ getContent: () => { @@ -509,9 +386,7 @@ describe('Call', function() { }); it("should handle upgrade to video call", async () => { - const callPromise = call.placeVoiceCall(); - await client.httpBackend.flush(); - await callPromise; + await startVoiceCall(client, call); await call.onAnswerReceived({ getContent: () => { @@ -540,6 +415,350 @@ describe('Call', function() { }).track.id).toBe("video_track"); }); + describe("should handle stream replacement", () => { + it("with both purpose and id", async () => { + await startVoiceCall(client, call); + + call.updateRemoteSDPStreamMetadata({ + "remote_stream1": { + purpose: SDPStreamMetadataPurpose.Usermedia, + }, + }); + call.pushRemoteFeed(new MockMediaStream("remote_stream1", [])); + const feed = call.getFeeds().find((feed) => feed.stream.id === "remote_stream1"); + + call.updateRemoteSDPStreamMetadata({ + "remote_stream2": { + purpose: SDPStreamMetadataPurpose.Usermedia, + }, + }); + call.pushRemoteFeed(new MockMediaStream("remote_stream2", [])); + + expect(feed?.stream?.id).toBe("remote_stream2"); + }); + + it("with just purpose", async () => { + await startVoiceCall(client, call); + + call.updateRemoteSDPStreamMetadata({ + "remote_stream1": { + purpose: SDPStreamMetadataPurpose.Usermedia, + }, + }); + call.pushRemoteFeed(new MockMediaStream("remote_stream1", [])); + const feed = call.getFeeds().find((feed) => feed.stream.id === "remote_stream1"); + + call.updateRemoteSDPStreamMetadata({ + "remote_stream2": { + purpose: SDPStreamMetadataPurpose.Usermedia, + }, + }); + call.pushRemoteFeed(new MockMediaStream("remote_stream2", [])); + + expect(feed?.stream?.id).toBe("remote_stream2"); + }); + + it("should not replace purpose is different", async () => { + await startVoiceCall(client, call); + + call.updateRemoteSDPStreamMetadata({ + "remote_stream1": { + purpose: SDPStreamMetadataPurpose.Usermedia, + }, + }); + call.pushRemoteFeed(new MockMediaStream("remote_stream1", [])); + const feed = call.getFeeds().find((feed) => feed.stream.id === "remote_stream1"); + + call.updateRemoteSDPStreamMetadata({ + "remote_stream2": { + purpose: SDPStreamMetadataPurpose.Screenshare, + }, + }); + call.pushRemoteFeed(new MockMediaStream("remote_stream2", [])); + + expect(feed?.stream?.id).toBe("remote_stream1"); + }); + }); + + it("should handle SDPStreamMetadata changes", async () => { + await startVoiceCall(client, call); + + call.updateRemoteSDPStreamMetadata({ + "remote_stream": { + purpose: SDPStreamMetadataPurpose.Usermedia, + audio_muted: false, + video_muted: false, + }, + }); + call.pushRemoteFeed(new MockMediaStream("remote_stream", [])); + const feed = call.getFeeds().find((feed) => feed.stream.id === "remote_stream"); + + call.onSDPStreamMetadataChangedReceived({ + getContent: () => ({ + [SDPStreamMetadataKey]: { + "remote_stream": { + purpose: SDPStreamMetadataPurpose.Screenshare, + audio_muted: true, + video_muted: true, + id: "feed_id2", + }, + }, + }), + }); + + expect(feed?.purpose).toBe(SDPStreamMetadataPurpose.Screenshare); + expect(feed?.audioMuted).toBe(true); + expect(feed?.videoMuted).toBe(true); + }); + + it("should choose opponent member", async () => { + const callPromise = call.placeVoiceCall(); + await client.httpBackend.flush(); + await callPromise; + + const opponentMember = { + roomId: call.roomId, + userId: "opponentUserId", + }; + + client.client.getRoom = () => { + return { + getMember: (userId) => { + if (userId === opponentMember.userId) { + return opponentMember; + } + }, + }; + }; + + const opponentCaps = { + "m.call.transferee": true, + "m.call.dtmf": false, + }; + call.chooseOpponent({ + getContent: () => ({ + version: 1, + party_id: "party_id", + capabilities: opponentCaps, + }), + getSender: () => opponentMember.userId, + }); + + expect(call.getOpponentMember()).toBe(opponentMember); + expect(call.opponentPartyId).toBe("party_id"); + expect(call.opponentCaps).toBe(opponentCaps); + expect(call.opponentCanBeTransferred()).toBe(true); + expect(call.opponentSupportsDTMF()).toBe(false); + }); + + describe("should deduce the call type correctly", () => { + it("if no video", async () => { + call.getOpponentMember = jest.fn().mockReturnValue({ userId: "@bob:bar.uk" }); + + call.pushRemoteFeed(new MockMediaStream("remote_stream1", [])); + expect(call.type).toBe(CallType.Voice); + }); + + it("if remote video", async () => { + call.getOpponentMember = jest.fn().mockReturnValue({ userId: "@bob:bar.uk" }); + + call.pushRemoteFeed(new MockMediaStream("remote_stream1", [new MockMediaStreamTrack("track_id", "video")])); + expect(call.type).toBe(CallType.Video); + }); + + it("if local video", async () => { + call.getOpponentMember = jest.fn().mockReturnValue({ userId: "@bob:bar.uk" }); + + call.pushNewLocalFeed( + new MockMediaStream("remote_stream1", [new MockMediaStreamTrack("track_id", "video")]), + SDPStreamMetadataPurpose.Usermedia, + false, + ); + expect(call.type).toBe(CallType.Video); + }); + }); + + it("should correctly generate local SDPStreamMetadata", async () => { + const callPromise = call.placeCallWithCallFeeds([new CallFeed({ + client, + // @ts-ignore Mock + stream: new MockMediaStream("local_stream1", [new MockMediaStreamTrack("track_id", "audio")]), + roomId: call.roomId, + userId: client.getUserId(), + purpose: SDPStreamMetadataPurpose.Usermedia, + audioMuted: false, + videoMuted: false, + })]); + await client.httpBackend.flush(); + await callPromise; + call.getOpponentMember = jest.fn().mockReturnValue({ userId: "@bob:bar.uk" }); + + call.pushNewLocalFeed( + new MockMediaStream("local_stream2", [new MockMediaStreamTrack("track_id", "video")]), + SDPStreamMetadataPurpose.Screenshare, "feed_id2", + ); + await call.setMicrophoneMuted(true); + + expect(call.getLocalSDPStreamMetadata()).toStrictEqual({ + "local_stream1": { + "purpose": SDPStreamMetadataPurpose.Usermedia, + "audio_muted": true, + "video_muted": true, + }, + "local_stream2": { + "purpose": SDPStreamMetadataPurpose.Screenshare, + "audio_muted": true, + "video_muted": false, + }, + }); + }); + + it("feed and stream getters return correctly", async () => { + const localUsermediaStream = new MockMediaStream("local_usermedia_stream_id", []); + const localScreensharingStream = new MockMediaStream("local_screensharing_stream_id", []); + const remoteUsermediaStream = new MockMediaStream("remote_usermedia_stream_id", []); + const remoteScreensharingStream = new MockMediaStream("remote_screensharing_stream_id", []); + + const callPromise = call.placeCallWithCallFeeds([ + new CallFeed({ + client, + userId: client.getUserId(), + // @ts-ignore Mock + stream: localUsermediaStream, + purpose: SDPStreamMetadataPurpose.Usermedia, + id: "local_usermedia_feed_id", + audioMuted: false, + videoMuted: false, + }), + new CallFeed({ + client, + userId: client.getUserId(), + // @ts-ignore Mock + stream: localScreensharingStream, + purpose: SDPStreamMetadataPurpose.Screenshare, + id: "local_screensharing_feed_id", + audioMuted: false, + videoMuted: false, + }), + ]); + await client.httpBackend.flush(); + await callPromise; + call.getOpponentMember = jest.fn().mockReturnValue({ userId: "@bob:bar.uk" }); + + call.updateRemoteSDPStreamMetadata({ + "remote_usermedia_stream_id": { + purpose: SDPStreamMetadataPurpose.Usermedia, + id: "remote_usermedia_feed_id", + audio_muted: false, + video_muted: false, + }, + "remote_screensharing_stream_id": { + purpose: SDPStreamMetadataPurpose.Screenshare, + id: "remote_screensharing_feed_id", + audio_muted: false, + video_muted: false, + }, + }); + call.pushRemoteFeed(remoteUsermediaStream); + call.pushRemoteFeed(remoteScreensharingStream); + + expect(call.localUsermediaFeed.stream).toBe(localUsermediaStream); + expect(call.localUsermediaStream).toBe(localUsermediaStream); + expect(call.localScreensharingFeed.stream).toBe(localScreensharingStream); + expect(call.localScreensharingStream).toBe(localScreensharingStream); + expect(call.remoteUsermediaFeed.stream).toBe(remoteUsermediaStream); + expect(call.remoteUsermediaStream).toBe(remoteUsermediaStream); + expect(call.remoteScreensharingFeed.stream).toBe(remoteScreensharingStream); + expect(call.remoteScreensharingStream).toBe(remoteScreensharingStream); + expect(call.hasRemoteUserMediaAudioTrack).toBe(false); + }); + + it("should end call after receiving a select event with a different party id", async () => { + const callPromise = call.initWithInvite({ + getContent: () => ({ + version: 1, + call_id: "call_id", + party_id: "remote_party_id", + offer: { + sdp: DUMMY_SDP, + }, + }), + getSender: () => "@test:foo", + getLocalAge: () => null, + }); + call.feeds.push(new CallFeed({ + client, + userId: "remote_user_id", + // @ts-ignore Mock + stream: new MockMediaStream("remote_stream_id", [new MockMediaStreamTrack("remote_tack_id")]), + id: "remote_feed_id", + purpose: SDPStreamMetadataPurpose.Usermedia, + })); + await client.httpBackend.flush(); + await callPromise; + + const callHangupCallback = jest.fn(); + call.on(CallEvent.Hangup, callHangupCallback); + + await call.onSelectAnswerReceived({ + getContent: () => ({ + version: 1, + call_id: call.callId, + party_id: 'party_id', + selected_party_id: "different_party_id", + }), + }); + + expect(callHangupCallback).toHaveBeenCalled(); + }); + + describe("turn servers", () => { + it("should fallback if allowed", async () => { + client.client.isFallbackICEServerAllowed = () => true; + const localCall = new MatrixCall({ + client: client.client, + roomId: '!room_id', + }); + + expect((localCall as any).turnServers).toStrictEqual([{ urls: ["stun:turn.matrix.org"] }]); + }); + + it("should not fallback if not allowed", async () => { + client.client.isFallbackICEServerAllowed = () => false; + const localCall = new MatrixCall({ + client: client.client, + roomId: '!room_id', + }); + + expect((localCall as any).turnServers).toStrictEqual([]); + }); + + it("should not fallback if we supplied turn servers", async () => { + client.client.isFallbackICEServerAllowed = () => true; + const turnServers = [{ urls: ["turn.server.org"] }]; + const localCall = new MatrixCall({ + client: client.client, + roomId: '!room_id', + turnServers, + }); + + expect((localCall as any).turnServers).toStrictEqual(turnServers); + }); + }); + + it("should handle creating a data channel", async () => { + await startVoiceCall(client, call); + + const dataChannelCallback = jest.fn(); + call.on(CallEvent.DataChannel, dataChannelCallback); + + const dataChannel = call.createDataChannel("data_channel_label", { id: 123 }); + + expect(dataChannelCallback).toHaveBeenCalledWith(dataChannel); + expect(dataChannel.label).toBe("data_channel_label"); + expect(dataChannel.id).toBe(123); + }); + describe("supportsMatrixCall", () => { it("should return true when the environment is right", () => { expect(supportsMatrixCall()).toBe(true); diff --git a/spec/unit/webrtc/callFeed.spec.ts b/spec/unit/webrtc/callFeed.spec.ts new file mode 100644 index 000000000..e8881781d --- /dev/null +++ b/spec/unit/webrtc/callFeed.spec.ts @@ -0,0 +1,61 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { SDPStreamMetadataPurpose } from "../../../src/webrtc/callEventTypes"; +import { CallFeed, CallFeedEvent } from "../../../src/webrtc/callFeed"; +import { MockMediaStream, MockMediaStreamTrack } from "../../test-utils/webrtc"; +import { TestClient } from "../../TestClient"; + +describe("CallFeed", () => { + const roomId = "room_id"; + + let client; + + beforeEach(() => { + client = new TestClient("@alice:foo", "somedevice", "token", undefined, {}); + }); + + afterEach(() => { + client.stop(); + }); + + it("should handle stream replacement", () => { + const feedNewStreamCallback = jest.fn(); + const feed = new CallFeed({ + client, + roomId, + userId: "user1", + // @ts-ignore Mock + stream: new MockMediaStream("stream1"), + id: "id", + purpose: SDPStreamMetadataPurpose.Usermedia, + audioMuted: false, + videoMuted: false, + }); + feed.on(CallFeedEvent.NewStream, feedNewStreamCallback); + + const replacementStream = new MockMediaStream("stream2"); + // @ts-ignore Mock + feed.setNewStream(replacementStream); + expect(feedNewStreamCallback).toHaveBeenCalledWith(replacementStream); + expect(feed.stream).toBe(replacementStream); + + feedNewStreamCallback.mockReset(); + + replacementStream.addTrack(new MockMediaStreamTrack("track_id", "audio")); + expect(feedNewStreamCallback).toHaveBeenCalledWith(replacementStream); + }); +}); diff --git a/src/client.ts b/src/client.ts index 3deed4e92..a6937f948 100644 --- a/src/client.ts +++ b/src/client.ts @@ -437,15 +437,9 @@ export enum RoomVersionStability { Unstable = "unstable", } -export interface IRoomCapability { // MSC3244 - preferred: string | null; - support: string[]; -} - export interface IRoomVersionsCapability { default: string; available: Record; - "org.matrix.msc3244.room_capabilities"?: Record; // MSC3244 } export interface ICapability { @@ -970,6 +964,7 @@ export class MatrixClient extends TypedEventEmitter !i.id_access_token); if ( invitesNeedingToken.length > 0 && - this.identityServer && - this.identityServer.getAccessToken && + this.identityServer?.getAccessToken && await this.doesServerAcceptIdentityAccessToken() ) { const identityAccessToken = await this.identityServer.getAccessToken(); @@ -8990,7 +8983,7 @@ export class MatrixClient extends TypedEventEmitter { this.replyCount = bundledRelationship.count; this._currentUserParticipated = bundledRelationship.current_user_participated; - const event = new MatrixEvent(bundledRelationship.latest_event); + const event = new MatrixEvent({ + room_id: this.rootEvent.getRoomId(), + ...bundledRelationship.latest_event, + }); this.setEventMetadata(event); event.setThread(this); this.lastEvent = event; diff --git a/src/realtime-callbacks.ts b/src/realtime-callbacks.ts index 68e41be53..67b261515 100644 --- a/src/realtime-callbacks.ts +++ b/src/realtime-callbacks.ts @@ -48,20 +48,6 @@ const callbackList: { // var debuglog = logger.log.bind(logger); const debuglog = function(...params: any[]) {}; -/** - * Replace the function used by this module to get the current time. - * - * Intended for use by the unit tests. - * - * @param {function} [f] function which should return a millisecond counter - * - * @internal - */ -export function setNow(f: () => number): void { - now = f || Date.now; -} -let now = Date.now; - /** * reimplementation of window.setTimeout, which will call the callback if * the wallclock time goes past the deadline. @@ -78,7 +64,7 @@ export function setTimeout(func: (...params: any[]) => void, delayMs: number, .. delayMs = 0; } - const runAt = now() + delayMs; + const runAt = Date.now() + delayMs; const key = count++; debuglog("setTimeout: scheduling cb", key, "at", runAt, "(delay", delayMs, ")"); @@ -141,7 +127,7 @@ function scheduleRealCallback(): void { return; } - const timestamp = now(); + const timestamp = Date.now(); const delayMs = Math.min(first.runAt - timestamp, TIMER_CHECK_PERIOD_MS); debuglog("scheduleRealCallback: now:", timestamp, "delay:", delayMs); @@ -150,7 +136,7 @@ function scheduleRealCallback(): void { function runCallbacks(): void { let cb; - const timestamp = now(); + const timestamp = Date.now(); debuglog("runCallbacks: now:", timestamp); // get the list of things to call diff --git a/src/utils.ts b/src/utils.ts index 4885fb948..6cf459097 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -144,23 +144,6 @@ export function checkObjectHasKeys(obj: object, keys: string[]) { } } -/** - * Checks that the given object has no extra keys other than the specified ones. - * @param {Object} obj The object to check. - * @param {string[]} allowedKeys The list of allowed key names. - * @throws If there are extra keys. - */ -export function checkObjectHasNoAdditionalKeys(obj: object, allowedKeys: string[]): void { - for (const key in obj) { - if (!obj.hasOwnProperty(key)) { - continue; - } - if (allowedKeys.indexOf(key) === -1) { - throw new Error("Unknown key: " + key); - } - } -} - /** * Deep copy the given object. The object MUST NOT have circular references and * MUST NOT have functions. @@ -283,69 +266,6 @@ export function deepSortedObjectEntries(obj: any): [string, any][] { return pairs; } -/** - * Inherit the prototype methods from one constructor into another. This is a - * port of the Node.js implementation with an Object.create polyfill. - * - * @param {function} ctor Constructor function which needs to inherit the - * prototype. - * @param {function} superCtor Constructor function to inherit prototype from. - */ -export function inherits(ctor: Function, superCtor: Function) { - // Add util.inherits from Node.js - // Source: - // https://github.com/joyent/node/blob/master/lib/util.js - // Copyright Joyent, Inc. and other Node contributors. - // - // Permission is hereby granted, free of charge, to any person obtaining a - // copy of this software and associated documentation files (the - // "Software"), to deal in the Software without restriction, including - // without limitation the rights to use, copy, modify, merge, publish, - // distribute, sublicense, and/or sell copies of the Software, and to permit - // persons to whom the Software is furnished to do so, subject to the - // following conditions: - // - // The above copyright notice and this permission notice shall be included - // in all copies or substantial portions of the Software. - // - // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - // USE OR OTHER DEALINGS IN THE SOFTWARE. - (ctor as any).super_ = superCtor; - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true, - }, - }); -} - -/** - * Polyfills inheritance for prototypes by allowing different kinds of - * super types. Typically prototypes would use `SuperType.call(this, params)` - * though this doesn't always work in some environments - this function - * falls back to using `Object.assign()` to clone a constructed copy - * of the super type onto `thisArg`. - * @param {any} thisArg The child instance. Modified in place. - * @param {any} SuperType The type to act as a super instance - * @param {any} params Arguments to supply to the super type's constructor - */ -export function polyfillSuper(thisArg: any, SuperType: any, ...params: any[]) { - try { - SuperType.call(thisArg, ...params); - } catch (e) { - // fall back to Object.assign to just clone the thing - const fakeSuper = new SuperType(...params); - Object.assign(thisArg, fakeSuper); - } -} - /** * Returns whether the given value is a finite number without type-coercion * diff --git a/src/webrtc/call.ts b/src/webrtc/call.ts index c23133ea4..ad97246c8 100644 --- a/src/webrtc/call.ts +++ b/src/webrtc/call.ts @@ -246,7 +246,7 @@ export enum CallErrorCode { /** * The version field that we set in m.call.* events */ -const VOIP_PROTO_VERSION = 1; +const VOIP_PROTO_VERSION = "1"; /** The fallback ICE server to use for STUN or TURN protocols. */ const FALLBACK_ICE_SERVER = 'stun:turn.matrix.org'; @@ -804,9 +804,9 @@ export class MatrixCall extends TypedEventEmitter { stats.push(item); - } + }); return stats; } @@ -1019,7 +1019,7 @@ export class MatrixCall extends TypedEventEmitter= 1) || reason !== CallErrorCode.UserHangup) { + if ((this.opponentVersion && this.opponentVersion !== 0) || reason !== CallErrorCode.UserHangup) { content["reason"] = reason; } this.sendVoipEvent(EventType.CallHangup, content); @@ -1035,7 +1035,7 @@ export class MatrixCall extends TypedEventEmitter=2.2.7 <3" ace-builds@^1.4.13: - version "1.5.3" - resolved "https://registry.yarnpkg.com/ace-builds/-/ace-builds-1.5.3.tgz#05f81d3464a9ea19696e5e6fd0f924d37dab442f" - integrity sha512-WN5BKR2aTSuBmisO8jo3Fytk6sOmJGki82v/Boeic81IgYN8pFHNkXq2anDF0XkmfDWMqLbRoW9sjc/GtKzQbQ== + version "1.7.1" + resolved "https://registry.yarnpkg.com/ace-builds/-/ace-builds-1.7.1.tgz#be796fbd98610dda5e138aed98d309cac2ab0872" + integrity sha512-1mcbP5kXvr729sJ9dA/8tul0pjuvKbma0LF/ZMRwPEwjoNWNpe/x0OXpaPJo36aRpZCjRZMl5zsME3hAKTiaNw== acorn-globals@^3.0.0: version "3.1.0" @@ -1961,15 +1965,15 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== -babel-jest@^28.0.0, babel-jest@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-28.1.0.tgz#95a67f8e2e7c0042e7b3ad3951b8af41a533b5ea" - integrity sha512-zNKk0yhDZ6QUwfxh9k07GII6siNGMJWVUU49gmFj5gfdqDKLqa2RArXOF2CODp4Dr7dLxN2cvAV+667dGJ4b4w== +babel-jest@^28.0.0, babel-jest@^28.1.2: + version "28.1.2" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-28.1.2.tgz#2b37fb81439f14d34d8b2cc4a4bd7efabf9acbfe" + integrity sha512-pfmoo6sh4L/+5/G2OOfQrGJgvH7fTa1oChnuYH2G/6gA+JwDvO8PELwvwnofKBMNrQsam0Wy/Rw+QSrBNewq2Q== dependencies: - "@jest/transform" "^28.1.0" + "@jest/transform" "^28.1.2" "@types/babel__core" "^7.1.14" babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^28.0.2" + babel-preset-jest "^28.1.1" chalk "^4.0.0" graceful-fs "^4.2.9" slash "^3.0.0" @@ -1992,17 +1996,17 @@ babel-plugin-istanbul@^6.1.1: istanbul-lib-instrument "^5.0.4" test-exclude "^6.0.0" -babel-plugin-jest-hoist@^28.0.2: - version "28.0.2" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-28.0.2.tgz#9307d03a633be6fc4b1a6bc5c3a87e22bd01dd3b" - integrity sha512-Kizhn/ZL+68ZQHxSnHyuvJv8IchXD62KQxV77TBDV/xoBFBOfgRAk97GNs6hXdTTCiVES9nB2I6+7MXXrk5llQ== +babel-plugin-jest-hoist@^28.1.1: + version "28.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-28.1.1.tgz#5e055cdcc47894f28341f87f5e35aad2df680b11" + integrity sha512-NovGCy5Hn25uMJSAU8FaHqzs13cFoOI4lhIujiepssjCKRsAo3TA734RDWSGxuFTsUJXerYOqQQodlxgmtqbzw== dependencies: "@babel/template" "^7.3.3" "@babel/types" "^7.3.3" "@types/babel__core" "^7.1.14" "@types/babel__traverse" "^7.0.6" -babel-plugin-polyfill-corejs2@^0.3.0: +babel-plugin-polyfill-corejs2@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz#440f1b70ccfaabc6b676d196239b138f8a2cfba5" integrity sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w== @@ -2011,7 +2015,7 @@ babel-plugin-polyfill-corejs2@^0.3.0: "@babel/helper-define-polyfill-provider" "^0.3.1" semver "^6.1.1" -babel-plugin-polyfill-corejs3@^0.5.0: +babel-plugin-polyfill-corejs3@^0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz#aabe4b2fa04a6e038b688c5e55d44e78cd3a5f72" integrity sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ== @@ -2019,7 +2023,7 @@ babel-plugin-polyfill-corejs3@^0.5.0: "@babel/helper-define-polyfill-provider" "^0.3.1" core-js-compat "^3.21.0" -babel-plugin-polyfill-regenerator@^0.3.0: +babel-plugin-polyfill-regenerator@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz#2c0678ea47c75c8cc2fbb1852278d8fb68233990" integrity sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A== @@ -2044,12 +2048,12 @@ babel-preset-current-node-syntax@^1.0.0: "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-top-level-await" "^7.8.3" -babel-preset-jest@^28.0.2: - version "28.0.2" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-28.0.2.tgz#d8210fe4e46c1017e9fa13d7794b166e93aa9f89" - integrity sha512-sYzXIdgIXXroJTFeB3S6sNDWtlJ2dllCdTEsnZ65ACrMojj3hVNFRmnJ1HZtomGi+Be7aqpY/HJ92fr8OhKVkQ== +babel-preset-jest@^28.1.1: + version "28.1.1" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-28.1.1.tgz#5b6e5e69f963eb2d70f739c607b8f723c0ee75e4" + integrity sha512-FCq9Oud0ReTeWtcneYf/48981aTfXYuB9gbU4rBNNJVBSQ6ssv7E6v/qvbBxtOWwZFXjLZwpg+W3q7J6vhH25g== dependencies: - babel-plugin-jest-hoist "^28.0.2" + babel-plugin-jest-hoist "^28.1.1" babel-preset-current-node-syntax "^1.0.0" babel-runtime@^6.26.0: @@ -2312,16 +2316,15 @@ browserify@^17.0.0: vm-browserify "^1.0.0" xtend "^4.0.0" -browserslist@^4.20.2, browserslist@^4.20.3: - version "4.20.3" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.3.tgz#eb7572f49ec430e054f56d52ff0ebe9be915f8bf" - integrity sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg== +browserslist@^4.20.2, browserslist@^4.21.0: + version "4.21.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.1.tgz#c9b9b0a54c7607e8dc3e01a0d311727188011a00" + integrity sha512-Nq8MFCSrnJXSc88yliwlzQe3qNe3VntIjhsArW9IJOEPSHNx23FalwApUVbzAWABLhYJJ7y8AynWI/XM8OdfjQ== dependencies: - caniuse-lite "^1.0.30001332" - electron-to-chromium "^1.4.118" - escalade "^3.1.1" - node-releases "^2.0.3" - picocolors "^1.0.0" + caniuse-lite "^1.0.30001359" + electron-to-chromium "^1.4.172" + node-releases "^2.0.5" + update-browserslist-db "^1.0.4" bs58@^4.0.1: version "4.0.1" @@ -2411,10 +2414,10 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001332: - version "1.0.30001344" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001344.tgz#8a1e7fdc4db9c2ec79a05e9fd68eb93a761888bb" - integrity sha512-0ZFjnlCaXNOAYcV7i+TtdKBp0L/3XEU2MF/x6Du1lrh+SRX4IfzIVL4HNJg5pB2PmFb8rszIGyOvsZnqqRoc2g== +caniuse-lite@^1.0.30001359: + version "1.0.30001363" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001363.tgz#26bec2d606924ba318235944e1193304ea7c4f15" + integrity sha512-HpQhpzTGGPVMnCjIomjt+jvyUu8vNFo3TaDiZ/RcoTrlOq/5+tC8zHdsbgFB6MxmaY+jCpsH09aD80Bb4Ow3Sg== caseless@~0.12.0: version "0.12.0" @@ -2481,9 +2484,9 @@ chokidar@^3.4.0: fsevents "~2.3.2" ci-info@^3.2.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.1.tgz#58331f6f472a25fe3a50a351ae3052936c2c7f32" - integrity sha512-SXgeMX9VwDe7iFFaEWkA5AstuER9YKqy4EhHqr4DVqkwmD9rpVimkMKWHdjn30Ja45txyjhSn63lVX69eVCckg== + version "3.3.2" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.2.tgz#6d2967ffa407466481c6c90b6e16b3098f080128" + integrity sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg== cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" @@ -2662,11 +2665,11 @@ convert-source-map@~1.1.0: integrity sha512-Y8L5rp6jo+g9VEPgvqNfEopjTR4OTYct8lXlS8iVQdmnjDvbdbzYe9rjtFCB9egC86JoNCU61WRY+ScjkZpnIg== core-js-compat@^3.21.0, core-js-compat@^3.22.1: - version "3.22.7" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.22.7.tgz#8359eb66ecbf726dd0cfced8e48d5e73f3224239" - integrity sha512-uI9DAQKKiiE/mclIC5g4AjRpio27g+VMRhe6rQoz+q4Wm4L6A/fJhiLtBw+sfOpDG9wZ3O0pxIw7GbfOlBgjOA== + version "3.23.3" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.23.3.tgz#7d8503185be76bb6d8d592c291a4457a8e440aa9" + integrity sha512-WSzUs2h2vvmKsacLHNTdpyOC9k43AEhcGoFlVgCY4L7aw98oSBKtPL6vD0/TqZjRWRQYdDSLkzZIni4Crbbiqw== dependencies: - browserslist "^4.20.3" + browserslist "^4.21.0" semver "7.0.0" core-js@^2.4.0: @@ -2675,9 +2678,9 @@ core-js@^2.4.0: integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== core-js@^3.4: - version "3.22.7" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.22.7.tgz#8d6c37f630f6139b8732d10f2c114c3f1d00024f" - integrity sha512-Jt8SReuDKVNZnZEzyEQT5eK6T2RRCXkfTq7Lo09kpm+fHjgGewSbNjV+Wt4yZMhPDdzz2x1ulI5z/w4nxpBseg== + version "3.23.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.23.3.tgz#3b977612b15da6da0c9cc4aec487e8d24f371112" + integrity sha512-oAKwkj9xcWNBAvGbT//WiCdOMpb9XQG92/Fe3ABFM/R16BsHgePG00mFOgKf7IsCtfj8tA1kHtf/VwErhriz5Q== core-util-is@1.0.2: version "1.0.2" @@ -2872,15 +2875,10 @@ diff-match-patch@^1.0.5: resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.5.tgz#abb584d5f10cd1196dfc55aa03701592ae3f7b37" integrity sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw== -diff-sequences@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" - integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== - -diff-sequences@^28.0.2: - version "28.0.2" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-28.0.2.tgz#40f8d4ffa081acbd8902ba35c798458d0ff1af41" - integrity sha512-YtEoNynLDFCRznv/XDalsKGSZDoj0U5kLnXvY0JSq3nBboRrZXjD81+eSiwi+nzcZDwedMmcowcxNwwgFW23mQ== +diff-sequences@^28.1.1: + version "28.1.1" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-28.1.1.tgz#9989dc731266dc2903457a70e996f3a041913ac6" + integrity sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw== diffie-hellman@^5.0.0: version "5.0.3" @@ -2949,10 +2947,10 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -electron-to-chromium@^1.4.118: - version "1.4.142" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.142.tgz#70cc8871f7c0122b29256089989e67cee637b40d" - integrity sha512-ea8Q1YX0JRp4GylOmX4gFHIizi0j9GfRW4EkaHnkZp0agRCBB4ZGeCv17IEzIvBkiYVwfoKVhKZJbTfqCRdQdg== +electron-to-chromium@^1.4.172: + version "1.4.177" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.177.tgz#b6a4436eb788ca732556cd69f384b8a3c82118c5" + integrity sha512-FYPir3NSBEGexSZUEeht81oVhHfLFl6mhUKSkjHN/iB/TwEIt/WHQrqVGfTLN5gQxwJCQkIJBe05eOXjI7omgg== elliptic@^6.5.3: version "6.5.4" @@ -3173,10 +3171,10 @@ eslint-visitor-keys@^3.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== -eslint@8.16.0: - version "8.16.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.16.0.tgz#6d936e2d524599f2a86c708483b4c372c5d3bbae" - integrity sha512-MBndsoXY/PeVTDJeWsYj7kLZ5hQpJOfMYLsF6LicLHQWbRDG19lK5jOix4DPl8yY4SUFcE3txy86OzFLWT+yoA== +eslint@8.18.0: + version "8.18.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.18.0.tgz#78d565d16c993d0b73968c523c0446b13da784fd" + integrity sha512-As1EfFMVk7Xc6/CvhssHUjsAQSkpfXvUGMFC3ce8JDe6WvqCgRrLOBQbVpsBFr1X1V+RACOadnzVvcUS5ni2bA== dependencies: "@eslint/eslintrc" "^1.3.0" "@humanwhocodes/config-array" "^0.9.2" @@ -3317,16 +3315,16 @@ exorcist@^1.0.1: mkdirp "~0.5.1" mold-source-map "~0.4.0" -expect@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-28.1.0.tgz#10e8da64c0850eb8c39a480199f14537f46e8360" - integrity sha512-qFXKl8Pmxk8TBGfaFKRtcQjfXEnKAs+dmlxdwvukJZorwrAabT7M3h8oLOG01I2utEhkmUTi17CHaPBovZsKdw== +expect@^28.1.0, expect@^28.1.1: + version "28.1.1" + resolved "https://registry.yarnpkg.com/expect/-/expect-28.1.1.tgz#ca6fff65f6517cf7220c2e805a49c19aea30b420" + integrity sha512-/AANEwGL0tWBwzLNOvO0yUdy2D52jVdNXppOqswC49sxMN2cPWsGCQdzuIf9tj6hHoBQzNvx75JUYuQAckPo3w== dependencies: - "@jest/expect-utils" "^28.1.0" + "@jest/expect-utils" "^28.1.1" jest-get-type "^28.0.2" - jest-matcher-utils "^28.1.0" - jest-message-util "^28.1.0" - jest-util "^28.1.0" + jest-matcher-utils "^28.1.1" + jest-message-util "^28.1.1" + jest-util "^28.1.1" ext@^1.1.2: version "1.6.0" @@ -3351,9 +3349,9 @@ extsprintf@^1.2.0: integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== fake-indexeddb@^3.1.2: - version "3.1.7" - resolved "https://registry.yarnpkg.com/fake-indexeddb/-/fake-indexeddb-3.1.7.tgz#d9efbeade113c15efbe862e4598a4b0a1797ed9f" - integrity sha512-CUGeCzCOVjmeKi2C0pcvSh6NDU6uQIaS+7YyR++tO/atJJujkBYVhDvfePdz/U8bD33BMVWirsr1MKczfAqbjA== + version "3.1.8" + resolved "https://registry.yarnpkg.com/fake-indexeddb/-/fake-indexeddb-3.1.8.tgz#229e3cff6fa7355aebb3f147b908d2efa4605d70" + integrity sha512-7umIgcdnDfNcjw0ZaoD6yR2BflngKmPsyzZC+sV2fdttwz5bH6B6CCaNzzD+MURfRg8pvr/aL0trfNx65FLiDg== dependencies: realistic-structured-clone "^2.0.1" @@ -3464,9 +3462,9 @@ flat-cache@^3.0.4: rimraf "^3.0.2" flatted@^3.1.0: - version "3.2.5" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" - integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== + version "3.2.6" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.6.tgz#022e9218c637f9f3fc9c35ab9c9193f05add60b2" + integrity sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ== for-each@^0.3.3: version "0.3.3" @@ -3562,13 +3560,13 @@ get-caller-file@^2.0.5: integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== + version "1.1.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598" + integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA== dependencies: function-bind "^1.1.1" has "^1.0.3" - has-symbols "^1.0.1" + has-symbols "^1.0.3" get-package-type@^0.1.0: version "0.1.0" @@ -3726,7 +3724,7 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" -he@^1.1.0: +he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== @@ -3895,7 +3893,7 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.4: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== -is-core-module@^2.8.1: +is-core-module@^2.8.1, is-core-module@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== @@ -4117,210 +4115,185 @@ jest-changed-files@^28.0.2: execa "^5.0.0" throat "^6.0.1" -jest-circus@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-28.1.0.tgz#e229f590911bd54d60efaf076f7acd9360296dae" - integrity sha512-rNYfqfLC0L0zQKRKsg4n4J+W1A2fbyGH7Ss/kDIocp9KXD9iaL111glsLu7+Z7FHuZxwzInMDXq+N1ZIBkI/TQ== +jest-circus@^28.1.2: + version "28.1.2" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-28.1.2.tgz#0d5a5623eccb244efe87d1edc365696e4fcf80ce" + integrity sha512-E2vdPIJG5/69EMpslFhaA46WkcrN74LI5V/cSJ59L7uS8UNoXbzTxmwhpi9XrIL3zqvMt5T0pl5k2l2u2GwBNQ== dependencies: - "@jest/environment" "^28.1.0" - "@jest/expect" "^28.1.0" - "@jest/test-result" "^28.1.0" - "@jest/types" "^28.1.0" + "@jest/environment" "^28.1.2" + "@jest/expect" "^28.1.2" + "@jest/test-result" "^28.1.1" + "@jest/types" "^28.1.1" "@types/node" "*" chalk "^4.0.0" co "^4.6.0" dedent "^0.7.0" is-generator-fn "^2.0.0" - jest-each "^28.1.0" - jest-matcher-utils "^28.1.0" - jest-message-util "^28.1.0" - jest-runtime "^28.1.0" - jest-snapshot "^28.1.0" - jest-util "^28.1.0" - pretty-format "^28.1.0" + jest-each "^28.1.1" + jest-matcher-utils "^28.1.1" + jest-message-util "^28.1.1" + jest-runtime "^28.1.2" + jest-snapshot "^28.1.2" + jest-util "^28.1.1" + pretty-format "^28.1.1" slash "^3.0.0" stack-utils "^2.0.3" throat "^6.0.1" -jest-cli@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-28.1.0.tgz#cd1d8adb9630102d5ba04a22895f63decdd7ac1f" - integrity sha512-fDJRt6WPRriHrBsvvgb93OxgajHHsJbk4jZxiPqmZbMDRcHskfJBBfTyjFko0jjfprP544hOktdSi9HVgl4VUQ== +jest-cli@^28.1.2: + version "28.1.2" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-28.1.2.tgz#b89012e5bad14135e71b1628b85475d3773a1bbc" + integrity sha512-l6eoi5Do/IJUXAFL9qRmDiFpBeEJAnjJb1dcd9i/VWfVWbp3mJhuH50dNtX67Ali4Ecvt4eBkWb4hXhPHkAZTw== dependencies: - "@jest/core" "^28.1.0" - "@jest/test-result" "^28.1.0" - "@jest/types" "^28.1.0" + "@jest/core" "^28.1.2" + "@jest/test-result" "^28.1.1" + "@jest/types" "^28.1.1" chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.9" import-local "^3.0.2" - jest-config "^28.1.0" - jest-util "^28.1.0" - jest-validate "^28.1.0" + jest-config "^28.1.2" + jest-util "^28.1.1" + jest-validate "^28.1.1" prompts "^2.0.1" yargs "^17.3.1" -jest-config@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-28.1.0.tgz#fca22ca0760e746fe1ce1f9406f6b307ab818501" - integrity sha512-aOV80E9LeWrmflp7hfZNn/zGA4QKv/xsn2w8QCBP0t0+YqObuCWTSgNbHJ0j9YsTuCO08ZR/wsvlxqqHX20iUA== +jest-config@^28.1.2: + version "28.1.2" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-28.1.2.tgz#ba00ad30caf62286c86e7c1099e915218a0ac8c6" + integrity sha512-g6EfeRqddVbjPVBVY4JWpUY4IvQoFRIZcv4V36QkqzE0IGhEC/VkugFeBMAeUE7PRgC8KJF0yvJNDeQRbamEVA== dependencies: "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^28.1.0" - "@jest/types" "^28.1.0" - babel-jest "^28.1.0" + "@jest/test-sequencer" "^28.1.1" + "@jest/types" "^28.1.1" + babel-jest "^28.1.2" chalk "^4.0.0" ci-info "^3.2.0" deepmerge "^4.2.2" glob "^7.1.3" graceful-fs "^4.2.9" - jest-circus "^28.1.0" - jest-environment-node "^28.1.0" + jest-circus "^28.1.2" + jest-environment-node "^28.1.2" jest-get-type "^28.0.2" jest-regex-util "^28.0.2" - jest-resolve "^28.1.0" - jest-runner "^28.1.0" - jest-util "^28.1.0" - jest-validate "^28.1.0" + jest-resolve "^28.1.1" + jest-runner "^28.1.2" + jest-util "^28.1.1" + jest-validate "^28.1.1" micromatch "^4.0.4" parse-json "^5.2.0" - pretty-format "^28.1.0" + pretty-format "^28.1.1" slash "^3.0.0" strip-json-comments "^3.1.1" -jest-diff@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def" - integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw== +jest-diff@^28.1.1: + version "28.1.1" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-28.1.1.tgz#1a3eedfd81ae79810931c63a1d0f201b9120106c" + integrity sha512-/MUUxeR2fHbqHoMMiffe/Afm+U8U4olFRJ0hiVG2lZatPJcnGxx292ustVu7bULhjV65IYMxRdploAKLbcrsyg== dependencies: chalk "^4.0.0" - diff-sequences "^27.5.1" - jest-get-type "^27.5.1" - pretty-format "^27.5.1" - -jest-diff@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-28.1.0.tgz#77686fef899ec1873dbfbf9330e37dd429703269" - integrity sha512-8eFd3U3OkIKRtlasXfiAQfbovgFgRDb0Ngcs2E+FMeBZ4rUezqIaGjuyggJBp+llosQXNEWofk/Sz4Hr5gMUhA== - dependencies: - chalk "^4.0.0" - diff-sequences "^28.0.2" + diff-sequences "^28.1.1" jest-get-type "^28.0.2" - pretty-format "^28.1.0" + pretty-format "^28.1.1" -jest-docblock@^28.0.2: - version "28.0.2" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-28.0.2.tgz#3cab8abea53275c9d670cdca814fc89fba1298c2" - integrity sha512-FH10WWw5NxLoeSdQlJwu+MTiv60aXV/t8KEwIRGEv74WARE1cXIqh1vGdy2CraHuWOOrnzTWj/azQKqW4fO7xg== +jest-docblock@^28.1.1: + version "28.1.1" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-28.1.1.tgz#6f515c3bf841516d82ecd57a62eed9204c2f42a8" + integrity sha512-3wayBVNiOYx0cwAbl9rwm5kKFP8yHH3d/fkEaL02NPTkDojPtheGB7HZSFY4wzX+DxyrvhXz0KSCVksmCknCuA== dependencies: detect-newline "^3.0.0" -jest-each@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-28.1.0.tgz#54ae66d6a0a5b1913e9a87588d26c2687c39458b" - integrity sha512-a/XX02xF5NTspceMpHujmOexvJ4GftpYXqr6HhhmKmExtMXsyIN/fvanQlt/BcgFoRKN4OCXxLQKth9/n6OPFg== +jest-each@^28.1.1: + version "28.1.1" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-28.1.1.tgz#ba5238dacf4f31d9fe23ddc2c44c01e7c23885c4" + integrity sha512-A042rqh17ZvEhRceDMi784ppoXR7MWGDEKTXEZXb4svt0eShMZvijGxzKsx+yIjeE8QYmHPrnHiTSQVhN4nqaw== dependencies: - "@jest/types" "^28.1.0" + "@jest/types" "^28.1.1" chalk "^4.0.0" jest-get-type "^28.0.2" - jest-util "^28.1.0" - pretty-format "^28.1.0" + jest-util "^28.1.1" + pretty-format "^28.1.1" -jest-environment-node@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-28.1.0.tgz#6ed2150aa31babba0c488c5b4f4d813a585c68e6" - integrity sha512-gBLZNiyrPw9CSMlTXF1yJhaBgWDPVvH0Pq6bOEwGMXaYNzhzhw2kA/OijNF8egbCgDS0/veRv97249x2CX+udQ== +jest-environment-node@^28.1.2: + version "28.1.2" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-28.1.2.tgz#3e2eb47f6d173b0648d5f7c717cb1c26651d5c8a" + integrity sha512-oYsZz9Qw27XKmOgTtnl0jW7VplJkN2oeof+SwAwKFQacq3CLlG9u4kTGuuLWfvu3J7bVutWlrbEQMOCL/jughw== dependencies: - "@jest/environment" "^28.1.0" - "@jest/fake-timers" "^28.1.0" - "@jest/types" "^28.1.0" + "@jest/environment" "^28.1.2" + "@jest/fake-timers" "^28.1.2" + "@jest/types" "^28.1.1" "@types/node" "*" - jest-mock "^28.1.0" - jest-util "^28.1.0" - -jest-get-type@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" - integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw== + jest-mock "^28.1.1" + jest-util "^28.1.1" jest-get-type@^28.0.2: version "28.0.2" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-28.0.2.tgz#34622e628e4fdcd793d46db8a242227901fcf203" integrity sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA== -jest-haste-map@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-28.1.0.tgz#6c1ee2daf1c20a3e03dbd8e5b35c4d73d2349cf0" - integrity sha512-xyZ9sXV8PtKi6NCrJlmq53PyNVHzxmcfXNVvIRHpHmh1j/HChC4pwKgyjj7Z9us19JMw8PpQTJsFWOsIfT93Dw== +jest-haste-map@^28.1.1: + version "28.1.1" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-28.1.1.tgz#471685f1acd365a9394745bb97c8fc16289adca3" + integrity sha512-ZrRSE2o3Ezh7sb1KmeLEZRZ4mgufbrMwolcFHNRSjKZhpLa8TdooXOOFlSwoUzlbVs1t0l7upVRW2K7RWGHzbQ== dependencies: - "@jest/types" "^28.1.0" + "@jest/types" "^28.1.1" "@types/graceful-fs" "^4.1.3" "@types/node" "*" anymatch "^3.0.3" fb-watchman "^2.0.0" graceful-fs "^4.2.9" jest-regex-util "^28.0.2" - jest-util "^28.1.0" - jest-worker "^28.1.0" + jest-util "^28.1.1" + jest-worker "^28.1.1" micromatch "^4.0.4" - walker "^1.0.7" + walker "^1.0.8" optionalDependencies: fsevents "^2.3.2" -jest-leak-detector@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-28.1.0.tgz#b65167776a8787443214d6f3f54935a4c73c8a45" - integrity sha512-uIJDQbxwEL2AMMs2xjhZl2hw8s77c3wrPaQ9v6tXJLGaaQ+4QrNJH5vuw7hA7w/uGT/iJ42a83opAqxGHeyRIA== +jest-leak-detector@^28.1.1: + version "28.1.1" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-28.1.1.tgz#537f37afd610a4b3f4cab15e06baf60484548efb" + integrity sha512-4jvs8V8kLbAaotE+wFR7vfUGf603cwYtFf1/PYEsyX2BAjSzj8hQSVTP6OWzseTl0xL6dyHuKs2JAks7Pfubmw== dependencies: jest-get-type "^28.0.2" - pretty-format "^28.1.0" + pretty-format "^28.1.1" jest-localstorage-mock@^2.4.6: version "2.4.21" resolved "https://registry.yarnpkg.com/jest-localstorage-mock/-/jest-localstorage-mock-2.4.21.tgz#920aa6fc8f8ab2f81e40433e48e2efdb2d81a6e0" integrity sha512-IBXPBufnfPyr4VkoQeJ+zlfWlG84P0KbL4ejcV9j3xNI0v6OWznQlH6Ke9xjSarleR11090oSeWADSUow0PmFw== -jest-matcher-utils@^27.0.0: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab" - integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw== +jest-matcher-utils@^28.0.0, jest-matcher-utils@^28.1.1: + version "28.1.1" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-28.1.1.tgz#a7c4653c2b782ec96796eb3088060720f1e29304" + integrity sha512-NPJPRWrbmR2nAJ+1nmnfcKKzSwgfaciCCrYZzVnNoxVoyusYWIjkBMNvu0RHJe7dNj4hH3uZOPZsQA+xAYWqsw== dependencies: chalk "^4.0.0" - jest-diff "^27.5.1" - jest-get-type "^27.5.1" - pretty-format "^27.5.1" - -jest-matcher-utils@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-28.1.0.tgz#2ae398806668eeabd293c61712227cb94b250ccf" - integrity sha512-onnax0n2uTLRQFKAjC7TuaxibrPSvZgKTcSCnNUz/tOjJ9UhxNm7ZmPpoQavmTDUjXvUQ8KesWk2/VdrxIFzTQ== - dependencies: - chalk "^4.0.0" - jest-diff "^28.1.0" + jest-diff "^28.1.1" jest-get-type "^28.0.2" - pretty-format "^28.1.0" + pretty-format "^28.1.1" -jest-message-util@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-28.1.0.tgz#7e8f0b9049e948e7b94c2a52731166774ba7d0af" - integrity sha512-RpA8mpaJ/B2HphDMiDlrAZdDytkmwFqgjDZovM21F35lHGeUeCvYmm6W+sbQ0ydaLpg5bFAUuWG1cjqOl8vqrw== +jest-message-util@^28.1.1: + version "28.1.1" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-28.1.1.tgz#60aa0b475cfc08c8a9363ed2fb9108514dd9ab89" + integrity sha512-xoDOOT66fLfmTRiqkoLIU7v42mal/SqwDKvfmfiWAdJMSJiU+ozgluO7KbvoAgiwIrrGZsV7viETjc8GNrA/IQ== dependencies: "@babel/code-frame" "^7.12.13" - "@jest/types" "^28.1.0" + "@jest/types" "^28.1.1" "@types/stack-utils" "^2.0.0" chalk "^4.0.0" graceful-fs "^4.2.9" micromatch "^4.0.4" - pretty-format "^28.1.0" + pretty-format "^28.1.1" slash "^3.0.0" stack-utils "^2.0.3" -jest-mock@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-28.1.0.tgz#ccc7cc12a9b330b3182db0c651edc90d163ff73e" - integrity sha512-H7BrhggNn77WhdL7O1apG0Q/iwl0Bdd5E1ydhCJzL3oBLh/UYxAwR3EJLsBZ9XA3ZU4PA3UNw4tQjduBTCTmLw== +jest-mock@^28.1.1: + version "28.1.1" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-28.1.1.tgz#37903d269427fa1ef5b2447be874e1c62a39a371" + integrity sha512-bDCb0FjfsmKweAvE09dZT59IMkzgN0fYBH6t5S45NoJfd2DHkS3ySG2K+hucortryhO3fVuXdlxWcbtIuV/Skw== dependencies: - "@jest/types" "^28.1.0" + "@jest/types" "^28.1.1" "@types/node" "*" jest-pnp-resolver@^1.2.2: @@ -4333,111 +4306,111 @@ jest-regex-util@^28.0.2: resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-28.0.2.tgz#afdc377a3b25fb6e80825adcf76c854e5bf47ead" integrity sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw== -jest-resolve-dependencies@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.0.tgz#167becb8bee6e20b5ef4a3a728ec67aef6b0b79b" - integrity sha512-Ue1VYoSZquPwEvng7Uefw8RmZR+me/1kr30H2jMINjGeHgeO/JgrR6wxj2ofkJ7KSAA11W3cOrhNCbj5Dqqd9g== +jest-resolve-dependencies@^28.1.2: + version "28.1.2" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.2.tgz#ca528858e0c6642d5a1dda8fc7cda10230c275bc" + integrity sha512-OXw4vbOZuyRTBi3tapWBqdyodU+T33ww5cPZORuTWkg+Y8lmsxQlVu3MWtJh6NMlKRTHQetF96yGPv01Ye7Mbg== dependencies: jest-regex-util "^28.0.2" - jest-snapshot "^28.1.0" + jest-snapshot "^28.1.2" -jest-resolve@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-28.1.0.tgz#b1f32748a6cee7d1779c7ef639c0a87078de3d35" - integrity sha512-vvfN7+tPNnnhDvISuzD1P+CRVP8cK0FHXRwPAcdDaQv4zgvwvag2n55/h5VjYcM5UJG7L4TwE5tZlzcI0X2Lhw== +jest-resolve@^28.1.1: + version "28.1.1" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-28.1.1.tgz#bc2eaf384abdcc1aaf3ba7c50d1adf01e59095e5" + integrity sha512-/d1UbyUkf9nvsgdBildLe6LAD4DalgkgZcKd0nZ8XUGPyA/7fsnaQIlKVnDiuUXv/IeZhPEDrRJubVSulxrShA== dependencies: chalk "^4.0.0" graceful-fs "^4.2.9" - jest-haste-map "^28.1.0" + jest-haste-map "^28.1.1" jest-pnp-resolver "^1.2.2" - jest-util "^28.1.0" - jest-validate "^28.1.0" + jest-util "^28.1.1" + jest-validate "^28.1.1" resolve "^1.20.0" resolve.exports "^1.1.0" slash "^3.0.0" -jest-runner@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-28.1.0.tgz#aefe2a1e618a69baa0b24a50edc54fdd7e728eaa" - integrity sha512-FBpmuh1HB2dsLklAlRdOxNTTHKFR6G1Qmd80pVDvwbZXTriqjWqjei5DKFC1UlM732KjYcE6yuCdiF0WUCOS2w== +jest-runner@^28.1.2: + version "28.1.2" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-28.1.2.tgz#f293409592a62234285a71237e38499a3554e350" + integrity sha512-6/k3DlAsAEr5VcptCMdhtRhOoYClZQmxnVMZvZ/quvPGRpN7OBQYPIC32tWSgOnbgqLXNs5RAniC+nkdFZpD4A== dependencies: - "@jest/console" "^28.1.0" - "@jest/environment" "^28.1.0" - "@jest/test-result" "^28.1.0" - "@jest/transform" "^28.1.0" - "@jest/types" "^28.1.0" + "@jest/console" "^28.1.1" + "@jest/environment" "^28.1.2" + "@jest/test-result" "^28.1.1" + "@jest/transform" "^28.1.2" + "@jest/types" "^28.1.1" "@types/node" "*" chalk "^4.0.0" emittery "^0.10.2" graceful-fs "^4.2.9" - jest-docblock "^28.0.2" - jest-environment-node "^28.1.0" - jest-haste-map "^28.1.0" - jest-leak-detector "^28.1.0" - jest-message-util "^28.1.0" - jest-resolve "^28.1.0" - jest-runtime "^28.1.0" - jest-util "^28.1.0" - jest-watcher "^28.1.0" - jest-worker "^28.1.0" + jest-docblock "^28.1.1" + jest-environment-node "^28.1.2" + jest-haste-map "^28.1.1" + jest-leak-detector "^28.1.1" + jest-message-util "^28.1.1" + jest-resolve "^28.1.1" + jest-runtime "^28.1.2" + jest-util "^28.1.1" + jest-watcher "^28.1.1" + jest-worker "^28.1.1" source-map-support "0.5.13" throat "^6.0.1" -jest-runtime@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-28.1.0.tgz#4847dcb2a4eb4b0f9eaf41306897e51fb1665631" - integrity sha512-wNYDiwhdH/TV3agaIyVF0lsJ33MhyujOe+lNTUiolqKt8pchy1Hq4+tDMGbtD5P/oNLA3zYrpx73T9dMTOCAcg== +jest-runtime@^28.1.2: + version "28.1.2" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-28.1.2.tgz#d68f34f814a848555a345ceda23289f14d59a688" + integrity sha512-i4w93OsWzLOeMXSi9epmakb2+3z0AchZtUQVF1hesBmcQQy4vtaql5YdVe9KexdJaVRyPDw8DoBR0j3lYsZVYw== dependencies: - "@jest/environment" "^28.1.0" - "@jest/fake-timers" "^28.1.0" - "@jest/globals" "^28.1.0" - "@jest/source-map" "^28.0.2" - "@jest/test-result" "^28.1.0" - "@jest/transform" "^28.1.0" - "@jest/types" "^28.1.0" + "@jest/environment" "^28.1.2" + "@jest/fake-timers" "^28.1.2" + "@jest/globals" "^28.1.2" + "@jest/source-map" "^28.1.2" + "@jest/test-result" "^28.1.1" + "@jest/transform" "^28.1.2" + "@jest/types" "^28.1.1" chalk "^4.0.0" cjs-module-lexer "^1.0.0" collect-v8-coverage "^1.0.0" execa "^5.0.0" glob "^7.1.3" graceful-fs "^4.2.9" - jest-haste-map "^28.1.0" - jest-message-util "^28.1.0" - jest-mock "^28.1.0" + jest-haste-map "^28.1.1" + jest-message-util "^28.1.1" + jest-mock "^28.1.1" jest-regex-util "^28.0.2" - jest-resolve "^28.1.0" - jest-snapshot "^28.1.0" - jest-util "^28.1.0" + jest-resolve "^28.1.1" + jest-snapshot "^28.1.2" + jest-util "^28.1.1" slash "^3.0.0" strip-bom "^4.0.0" -jest-snapshot@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-28.1.0.tgz#4b74fa8816707dd10fe9d551c2c258e5a67b53b6" - integrity sha512-ex49M2ZrZsUyQLpLGxQtDbahvgBjlLPgklkqGM0hq/F7W/f8DyqZxVHjdy19QKBm4O93eDp+H5S23EiTbbUmHw== +jest-snapshot@^28.1.2: + version "28.1.2" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-28.1.2.tgz#93d31b87b11b384f5946fe0767541496135f8d52" + integrity sha512-wzrieFttZYfLvrCVRJxX+jwML2YTArOUqFpCoSVy1QUapx+LlV9uLbV/mMEhYj4t7aMeE9aSQFHSvV/oNoDAMA== dependencies: "@babel/core" "^7.11.6" "@babel/generator" "^7.7.2" "@babel/plugin-syntax-typescript" "^7.7.2" "@babel/traverse" "^7.7.2" "@babel/types" "^7.3.3" - "@jest/expect-utils" "^28.1.0" - "@jest/transform" "^28.1.0" - "@jest/types" "^28.1.0" + "@jest/expect-utils" "^28.1.1" + "@jest/transform" "^28.1.2" + "@jest/types" "^28.1.1" "@types/babel__traverse" "^7.0.6" "@types/prettier" "^2.1.5" babel-preset-current-node-syntax "^1.0.0" chalk "^4.0.0" - expect "^28.1.0" + expect "^28.1.1" graceful-fs "^4.2.9" - jest-diff "^28.1.0" + jest-diff "^28.1.1" jest-get-type "^28.0.2" - jest-haste-map "^28.1.0" - jest-matcher-utils "^28.1.0" - jest-message-util "^28.1.0" - jest-util "^28.1.0" + jest-haste-map "^28.1.1" + jest-matcher-utils "^28.1.1" + jest-message-util "^28.1.1" + jest-util "^28.1.1" natural-compare "^1.4.0" - pretty-format "^28.1.0" + pretty-format "^28.1.1" semver "^7.3.5" jest-sonar-reporter@^2.0.0: @@ -4447,61 +4420,62 @@ jest-sonar-reporter@^2.0.0: dependencies: xml "^1.0.1" -jest-util@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-28.1.0.tgz#d54eb83ad77e1dd441408738c5a5043642823be5" - integrity sha512-qYdCKD77k4Hwkose2YBEqQk7PzUf/NSE+rutzceduFveQREeH6b+89Dc9+wjX9dAwHcgdx4yedGA3FQlU/qCTA== +jest-util@^28.1.1: + version "28.1.1" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-28.1.1.tgz#ff39e436a1aca397c0ab998db5a51ae2b7080d05" + integrity sha512-FktOu7ca1DZSyhPAxgxB6hfh2+9zMoJ7aEQA759Z6p45NuO8mWcqujH+UdHlCm/V6JTWwDztM2ITCzU1ijJAfw== dependencies: - "@jest/types" "^28.1.0" + "@jest/types" "^28.1.1" "@types/node" "*" chalk "^4.0.0" ci-info "^3.2.0" graceful-fs "^4.2.9" picomatch "^2.2.3" -jest-validate@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-28.1.0.tgz#8a6821f48432aba9f830c26e28226ad77b9a0e18" - integrity sha512-Lly7CJYih3vQBfjLeANGgBSBJ7pEa18cxpQfQEq2go2xyEzehnHfQTjoUia8xUv4x4J80XKFIDwJJThXtRFQXQ== +jest-validate@^28.1.1: + version "28.1.1" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-28.1.1.tgz#59b7b339b3c85b5144bd0c06ad3600f503a4acc8" + integrity sha512-Kpf6gcClqFCIZ4ti5++XemYJWUPCFUW+N2gknn+KgnDf549iLul3cBuKVe1YcWRlaF8tZV8eJCap0eECOEE3Ug== dependencies: - "@jest/types" "^28.1.0" + "@jest/types" "^28.1.1" camelcase "^6.2.0" chalk "^4.0.0" jest-get-type "^28.0.2" leven "^3.1.0" - pretty-format "^28.1.0" + pretty-format "^28.1.1" -jest-watcher@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-28.1.0.tgz#aaa7b4164a4e77eeb5f7d7b25ede5e7b4e9c9aaf" - integrity sha512-tNHMtfLE8Njcr2IRS+5rXYA4BhU90gAOwI9frTGOqd+jX0P/Au/JfRSNqsf5nUTcWdbVYuLxS1KjnzILSoR5hA== +jest-watcher@^28.1.1: + version "28.1.1" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-28.1.1.tgz#533597fb3bfefd52b5cd115cd916cffd237fb60c" + integrity sha512-RQIpeZ8EIJMxbQrXpJQYIIlubBnB9imEHsxxE41f54ZwcqWLysL/A0ZcdMirf+XsMn3xfphVQVV4EW0/p7i7Ug== dependencies: - "@jest/test-result" "^28.1.0" - "@jest/types" "^28.1.0" + "@jest/test-result" "^28.1.1" + "@jest/types" "^28.1.1" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" emittery "^0.10.2" - jest-util "^28.1.0" + jest-util "^28.1.1" string-length "^4.0.1" -jest-worker@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-28.1.0.tgz#ced54757a035e87591e1208253a6e3aac1a855e5" - integrity sha512-ZHwM6mNwaWBR52Snff8ZvsCTqQsvhCxP/bT1I6T6DAnb6ygkshsyLQIMxFwHpYxht0HOoqt23JlC01viI7T03A== +jest-worker@^28.1.1: + version "28.1.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-28.1.1.tgz#3480c73247171dfd01eda77200f0063ab6a3bf28" + integrity sha512-Au7slXB08C6h+xbJPp7VIb6U0XX5Kc9uel/WFc6/rcTzGiaVCBRngBExSYuXSLFPULPSYU3cJ3ybS988lNFQhQ== dependencies: "@types/node" "*" merge-stream "^2.0.0" supports-color "^8.0.0" jest@^28.0.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-28.1.0.tgz#f420e41c8f2395b9a30445a97189ebb57593d831" - integrity sha512-TZR+tHxopPhzw3c3560IJXZWLNHgpcz1Zh0w5A65vynLGNcg/5pZ+VildAd7+XGOu6jd58XMY/HNn0IkZIXVXg== + version "28.1.2" + resolved "https://registry.yarnpkg.com/jest/-/jest-28.1.2.tgz#451ff24081ce31ca00b07b60c61add13aa96f8eb" + integrity sha512-Tuf05DwLeCh2cfWCQbcz9UxldoDyiR1E9Igaei5khjonKncYdc6LDfynKCEWozK0oLE3GD+xKAo2u8x/0s6GOg== dependencies: - "@jest/core" "^28.1.0" + "@jest/core" "^28.1.2" + "@jest/types" "^28.1.1" import-local "^3.0.2" - jest-cli "^28.1.0" + jest-cli "^28.1.2" js-stringify@^1.0.1: version "1.0.2" @@ -4829,9 +4803,9 @@ markdown-it@^12.3.2: uc.micro "^1.0.5" marked@^4.0.10: - version "4.0.16" - resolved "https://registry.yarnpkg.com/marked/-/marked-4.0.16.tgz#9ec18fc1a723032eb28666100344d9428cf7a264" - integrity sha512-wahonIQ5Jnyatt2fn8KqF/nIqZM8mh3oRu2+l5EANGMhu6RFjiSG52QNE2eWzFMI94HqYSgN184NurgNG6CztA== + version "4.0.17" + resolved "https://registry.yarnpkg.com/marked/-/marked-4.0.17.tgz#1186193d85bb7882159cdcfc57d1dfccaffb3fe9" + integrity sha512-Wfk0ATOK5iPxM4ptrORkFemqroz0ZDxp5MWfYA7H/F+wO17NRWV5Ypxi6p3g2Xmw2bKeiYOl6oVnLHKxBA0VhA== matrix-events-sdk@^0.0.1-beta.7: version "0.0.1-beta.7" @@ -4839,9 +4813,9 @@ matrix-events-sdk@^0.0.1-beta.7: integrity sha512-9jl4wtWanUFSy2sr2lCjErN/oC8KTAtaeaozJtrgot1JiQcEI4Rda9OLgQ7nLKaqb4Z/QUx/fR3XpDzm5Jy1JA== matrix-mock-request@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/matrix-mock-request/-/matrix-mock-request-2.0.1.tgz#1cf7b516f8525de8373f1d9985a4a447db80bb96" - integrity sha512-NqCSDRBUTXKY7TS5H6Fqu6oxSsWKGkyh3LTXa/T6mSGABi2zMkeqGa2r2H3rnH6waJRt5N7xn+u7vEmSpg0oBQ== + version "2.1.0" + resolved "https://registry.yarnpkg.com/matrix-mock-request/-/matrix-mock-request-2.1.0.tgz#86f5b0ef846865d0767d3a8e64f5bcd6ca94c178" + integrity sha512-Cjpl3yP6h0yu5GKG89m1XZXZlm69Kg/qHV41N/t6SrQsgcfM3Bfavqx9YrtG0UnuXGy4bBSZIe1QiWVeFPZw1A== dependencies: expect "^28.1.0" @@ -5027,7 +5001,7 @@ next-tick@1, next-tick@^1.1.0: node-dir@^0.1.10: version "0.1.17" resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5" - integrity sha1-X1Zl2TNRM1yqvvjxxVRRbPXx5OU= + integrity sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg== dependencies: minimatch "^3.0.2" @@ -5041,9 +5015,9 @@ node-fetch@^2.6.7: node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" - integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== -node-releases@^2.0.3: +node-releases@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.5.tgz#280ed5bc3eba0d96ce44897d8aee478bfb3d9666" integrity sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q== @@ -5068,7 +5042,7 @@ oauth-sign@~0.9.0: object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== object-inspect@^1.12.0, object-inspect@^1.9.0: version "1.12.2" @@ -5102,7 +5076,7 @@ object.values@^1.1.5: once@^1.3.0, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" @@ -5128,7 +5102,7 @@ optionator@^0.9.1: os-browserify@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= + integrity sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A== p-limit@^1.1.0: version "1.3.0" @@ -5154,7 +5128,7 @@ p-limit@^3.0.2: p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== dependencies: p-limit "^1.1.0" @@ -5190,7 +5164,7 @@ p-retry@^4.5.0: p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== p-try@^2.0.0: version "2.2.0" @@ -5212,7 +5186,7 @@ parent-module@^1.0.0: parents@^1.0.0, parents@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/parents/-/parents-1.0.1.tgz#fedd4d2bf193a77745fe71e371d73c3307d9c751" - integrity sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E= + integrity sha512-mXKF3xkoUt5td2DoxpLmtOmZvko9VfFpwRwkKDHSNvgmpLAeBo18YDhcPbBzJq+QLCHMbGOfzia2cX4U+0v9Mg== dependencies: path-platform "~0.11.15" @@ -5230,7 +5204,7 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.5: parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= + integrity sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ== dependencies: error-ex "^1.2.0" @@ -5252,7 +5226,7 @@ path-browserify@^1.0.0: path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== path-exists@^4.0.0: version "4.0.0" @@ -5262,7 +5236,7 @@ path-exists@^4.0.0: path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" @@ -5277,7 +5251,7 @@ path-parse@^1.0.7: path-platform@~0.11.15: version "0.11.15" resolved "https://registry.yarnpkg.com/path-platform/-/path-platform-0.11.15.tgz#e864217f74c36850f0852b78dc7bf7d4a5721bf2" - integrity sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I= + integrity sha512-Y30dB6rab1A/nfEKsZxmr01nUotHX0c/ZiIAsCTatEe1CmS5Pm5He7fZ195bPT7RdquoaL8lLxFCMQi/bS7IJg== path-type@^4.0.0: version "4.0.0" @@ -5298,7 +5272,7 @@ pbkdf2@^3.0.3: performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== picocolors@^1.0.0: version "1.0.0" @@ -5339,19 +5313,10 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -pretty-format@^27.0.0, pretty-format@^27.5.1: - version "27.5.1" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" - integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== - dependencies: - ansi-regex "^5.0.1" - ansi-styles "^5.0.0" - react-is "^17.0.1" - -pretty-format@^28.1.0: - version "28.1.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-28.1.0.tgz#8f5836c6a0dfdb834730577ec18029052191af55" - integrity sha512-79Z4wWOYCdvQkEoEuSlBhHJqWeZ8D8YRPiPctJFCtvuaClGpiwiQYSCUOE6IEKUbbFukKOTFIUAXE8N4EQTo1Q== +pretty-format@^28.0.0, pretty-format@^28.1.1: + version "28.1.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-28.1.1.tgz#f731530394e0f7fcd95aba6b43c50e02d86b95cb" + integrity sha512-wwJbVTGFHeucr5Jw2bQ9P+VYHyLdAqedFLEkdQUVaBF/eiidDwH5OpilINq4mEfhbCjLnirt6HTTDhv1HaTIQw== dependencies: "@jest/schemas" "^28.0.2" ansi-regex "^5.0.1" @@ -5371,7 +5336,7 @@ process-nextick-args@~2.0.0: process@~0.11.0: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== promise@^7.0.1: version "7.3.1" @@ -5400,12 +5365,12 @@ prop-types@^15.7.2: pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== psl@^1.1.28: - version "1.8.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== public-encrypt@^4.0.0: version "4.0.3" @@ -5527,12 +5492,12 @@ pug@^2.0.3: punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= + integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== punycode@^1.3.2: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" @@ -5540,9 +5505,9 @@ punycode@^2.1.0, punycode@^2.1.1: integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== qs@^6.9.6: - version "6.10.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" - integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== dependencies: side-channel "^1.0.4" @@ -5554,12 +5519,12 @@ qs@~6.5.2: querystring-es3@~0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= + integrity sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA== querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== queue-microtask@^1.2.2: version "1.2.3" @@ -5593,9 +5558,9 @@ react-ace@^9.5.0: prop-types "^15.7.2" react-docgen@^5.4.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/react-docgen/-/react-docgen-5.4.1.tgz#867168accce39e25095a23a922eaa90722e9d182" - integrity sha512-TZqD1aApirw86NV6tHrmDoxUn8wlinkVyutFarzbdwuhEurAzDN0y5sSj64o+BrHLPqjwpH9tunpfwgy+3Uyww== + version "5.4.3" + resolved "https://registry.yarnpkg.com/react-docgen/-/react-docgen-5.4.3.tgz#7d297f73b977d0c7611402e5fc2a168acf332b26" + integrity sha512-xlLJyOlnfr8lLEEeaDZ+X2J/KJoe6Nr9AzxnkdQWush5hz2ZSu66w6iLMOScMmxoSHWpWMn+k3v5ZiyCfcWsOA== dependencies: "@babel/core" "^7.7.5" "@babel/generator" "^7.12.11" @@ -5618,20 +5583,15 @@ react-is@^16.13.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -react-is@^17.0.1: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" - integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== - react-is@^18.0.0: - version "18.1.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.1.0.tgz#61aaed3096d30eacf2a2127118b5b41387d32a67" - integrity sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg== + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" + integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== read-only-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-only-stream/-/read-only-stream-2.0.0.tgz#2724fd6a8113d73764ac288d4386270c1dbf17f0" - integrity sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A= + integrity sha512-3ALe0bjBVZtkdWKIcThYpQCLbBMd/+Tbh2CDSrAIDO3UsZ4Xs+tnyjv2MjCOMMgBG+AsUOeuP1cgtY1INISc8w== dependencies: readable-stream "^2.0.2" @@ -5727,10 +5687,10 @@ regexpp@^3.2.0: resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== -regexpu-core@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.0.1.tgz#c531122a7840de743dcf9c83e923b5560323ced3" - integrity sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw== +regexpu-core@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.1.0.tgz#2f8504c3fd0ebe11215783a41541e21c79942c6d" + integrity sha512-bb6hk+xWd2PEOkj5It46A16zFMs2mv86Iwpdu94la4S3sJ7C973h2dHpYKwIBGaWSO7cIRJ+UX0IeMaWcO4qwA== dependencies: regenerate "^1.4.2" regenerate-unicode-properties "^10.0.1" @@ -5754,7 +5714,7 @@ regjsparser@^0.8.2: repeat-string@^1.5.2: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== request@^2.88.2: version "2.88.2" @@ -5785,7 +5745,7 @@ request@^2.88.2: require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== requizzle@^0.2.3: version "0.2.3" @@ -5817,11 +5777,11 @@ resolve.exports@^1.1.0: integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== resolve@^1.1.4, resolve@^1.1.6, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.4.0: - version "1.22.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" - integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== dependencies: - is-core-module "^2.8.1" + is-core-module "^2.9.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -5838,7 +5798,7 @@ reusify@^1.0.4: right-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" - integrity sha1-YTObci/mo1FWiSENJOFMlhSGE+8= + integrity sha512-yqINtL/G7vs2v+dFIZmFUDbnVyFUJFKd6gK22Kgo6R4jfJGFtisKyncWDDULgjfqf4ASQuIQyjJ7XZ+3aWpsAg== dependencies: align-text "^0.1.1" @@ -6003,12 +5963,12 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: source-map@~0.5.1, source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== sshpk@^1.7.0: version "1.17.0" @@ -6043,7 +6003,7 @@ stream-browserify@^3.0.0: stream-combiner2@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/stream-combiner2/-/stream-combiner2-1.1.1.tgz#fb4d8a1420ea362764e21ad4780397bebcb41cbe" - integrity sha1-+02KFCDqNidk4hrUeAOXvry0HL4= + integrity sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw== dependencies: duplexer2 "~0.1.0" readable-stream "^2.0.2" @@ -6125,14 +6085,14 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= + integrity sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g== dependencies: is-utf8 "^0.2.0" strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== strip-bom@^4.0.0: version "4.0.0" @@ -6154,7 +6114,7 @@ strip-indent@^3.0.0: strip-json-comments@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" @@ -6164,7 +6124,7 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: subarg@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/subarg/-/subarg-1.0.0.tgz#f62cf17581e996b48fc965699f54c06ae268b8d2" - integrity sha1-9izxdYHplrSPyWVpn1TAauJouNI= + integrity sha512-RIrIdRY0X1xojthNcVtgT9sjpOGagEUKpZdgBUi054OEPFo282yg+zE+t1Rj3+RqKq2xStL7uUHhY+AjbC4BXg== dependencies: minimist "^1.1.0" @@ -6212,7 +6172,7 @@ syntax-error@^1.1.1: taffydb@2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/taffydb/-/taffydb-2.6.2.tgz#7cbcb64b5a141b6a2efc2c5d2c67b4e150b2a268" - integrity sha1-fLy2S1oUG2ou/CxdLGe04VCyomg= + integrity sha512-y3JaeRSplks6NYQuCOj3ZFMO3j60rTwbuKCvZxsAraGYH2epusatvZ0baZYA01WsGqJBq/Dl6vOrMUJqyMj8kA== terminal-link@^2.0.0: version "2.1.1" @@ -6223,9 +6183,9 @@ terminal-link@^2.0.0: supports-hyperlinks "^2.0.0" terser@^5.5.1: - version "5.14.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.14.0.tgz#eefeec9af5153f55798180ee2617f390bdd285e2" - integrity sha512-JC6qfIEkPBd9j1SMO3Pfn+A6w2kQV54tv+ABQLgZr7dA3k/DL/OBoYSWxzVpZev3J+bUHXfr55L8Mox7AaNo6g== + version "5.14.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.14.1.tgz#7c95eec36436cb11cf1902cc79ac564741d19eca" + integrity sha512-+ahUAE+iheqBTDxXhTisdA8hgvbEG1hHOQ9xmNjeUJSoi6DU/gMrKNcfZjHkyY6Alnuyc+ikYJaxxfHkT3+WuQ== dependencies: "@jridgewell/source-map" "^0.3.2" acorn "^8.5.0" @@ -6244,7 +6204,7 @@ test-exclude@^6.0.0: text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== throat@^6.0.1: version "6.0.1" @@ -6262,17 +6222,17 @@ through2@^2.0.0: "through@>=2.2.7 <3": version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== through@~2.2.7: version "2.2.7" resolved "https://registry.yarnpkg.com/through/-/through-2.2.7.tgz#6e8e21200191d4eb6a99f6f010df46aa1c6eb2bd" - integrity sha1-bo4hIAGR1OtqmfbwEN9Gqhxusr0= + integrity sha512-JIR0m0ybkmTcR8URann+HbwKmodP+OE8UCbsifQDYMLD5J3em1Cdn3MYPpbEd5elGDwmP98T+WbqP/tvzA5Mjg== timers-browserify@^1.0.1: version "1.4.2" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-1.4.2.tgz#c9c58b575be8407375cb5e2462dacee74359f41d" - integrity sha1-ycWLV1voQHN1y14kYtrO50NZ9B0= + integrity sha512-PIxwAupJZiYU4JmVZYwXp9FKsHMXb5h0ZEFyuXTAn8WLHOlcij+FEcbrvDsom1o5dr1YggEtFbECvGCW2sT53Q== dependencies: process "~0.11.0" @@ -6292,12 +6252,12 @@ tmpl@1.0.5: to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= + integrity sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og== to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== to-regex-range@^5.0.1: version "5.0.1" @@ -6309,7 +6269,7 @@ to-regex-range@^5.0.1: token-stream@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-0.0.1.tgz#ceeefc717a76c4316f126d0b9dbaa55d7e7df01a" - integrity sha1-zu78cXp2xDFvEm0LnbqlXX598Bo= + integrity sha512-nfjOAu/zAWmX9tgwi5NRp7O7zTDUD1miHiB40klUnAh9qnL1iXdgzcz/i5dMaL5jahcBAaSfmNOBBJBLJW8TEg== tough-cookie@~2.5.0: version "2.5.0" @@ -6329,7 +6289,7 @@ tr46@^2.1.0: tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== ts-map@^1.0.3: version "1.0.3" @@ -6349,7 +6309,7 @@ tsconfig-paths@^3.14.1: tsconfig@^5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/tsconfig/-/tsconfig-5.0.3.tgz#5f4278e701800967a8fc383fd19648878f2a6e3a" - integrity sha1-X0J45wGACWeo/Dg/0ZZIh48qbjo= + integrity sha512-Cq65A3kVp6BbsUgg9DRHafaGmbMb9EhAc7fjWvudNWKjkbWrt43FnrtZt6awshH1R0ocfF2Z0uxock3lVqEgOg== dependencies: any-promise "^1.3.0" parse-json "^2.2.0" @@ -6393,7 +6353,7 @@ tty-browserify@0.0.1: tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== dependencies: safe-buffer "^5.0.1" @@ -6405,7 +6365,7 @@ tunnel@^0.0.6: tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" @@ -6442,7 +6402,7 @@ type@^2.5.0: typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== typescript@^3.2.2: version "3.9.10" @@ -6450,9 +6410,9 @@ typescript@^3.2.2: integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q== typescript@^4.5.3, typescript@^4.5.4: - version "4.7.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.2.tgz#1f9aa2ceb9af87cca227813b4310fff0b51593c4" - integrity sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A== + version "4.7.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235" + integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ== typeson-registry@^1.0.0-alpha.20: version "1.0.0-alpha.39" @@ -6476,7 +6436,7 @@ uc.micro@^1.0.1, uc.micro@^1.0.5: uglify-js@^2.6.1: version "2.8.29" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" - integrity sha1-KcVzMUgFe7Th913zW3qcty5qWd0= + integrity sha512-qLq/4y2pjcU3vhlhseXGGJ7VbFO4pBANu0kwl8VCa9KEI0V8VfZIx2Fy3w01iSTA/pGwKZSmu/+I4etLNDdt5w== dependencies: source-map "~0.5.1" yargs "~3.10.0" @@ -6486,7 +6446,7 @@ uglify-js@^2.6.1: uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" - integrity sha1-bgkk1r2mta/jSeOabWMoUKD4grc= + integrity sha512-vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q== umd@^3.0.0: version "3.0.3" @@ -6515,9 +6475,9 @@ undeclared-identifiers@^1.1.2: xtend "^4.0.1" underscore@^1.13.2, underscore@~1.13.2: - version "1.13.3" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.3.tgz#54bc95f7648c5557897e5e968d0f76bc062c34ee" - integrity sha512-QvjkYpiD+dJJraRA8+dGAU4i7aBbb2s0S3jA45TFOvg2VgqvdCDd/3N6CqA8gluk1W91GLoXg5enMUx560QzuA== + version "1.13.4" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.4.tgz#7886b46bbdf07f768e0052f1828e1dcab40c0dee" + integrity sha512-BQFnUDuAQ4Yf/cYY5LNrK9NCJFKriaRbD9uR1fTeXnBeoa97W0i41qkZfGO9pSo8I5KzjAcSY2XYtdf0oKd7KQ== unhomoglyph@^1.0.6: version "1.0.6" @@ -6552,6 +6512,14 @@ universal-user-agent@^6.0.0: resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== +update-browserslist-db@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz#dbfc5a789caa26b1db8990796c2c8ebbce304824" + integrity sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -6562,7 +6530,7 @@ uri-js@^4.2.2: url@~0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= + integrity sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ== dependencies: punycode "1.3.2" querystring "0.2.0" @@ -6570,12 +6538,12 @@ url@~0.11.0: util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== util@0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= + integrity sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ== dependencies: inherits "2.0.1" @@ -6601,19 +6569,19 @@ v8-compile-cache@^2.0.3: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== -v8-to-istanbul@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.0.0.tgz#be0dae58719fc53cb97e5c7ac1d7e6d4f5b19511" - integrity sha512-HcvgY/xaRm7isYmyx+lFKA4uQmfUbN0J4M0nNItvzTvH/iQ9kW5j/t4YSR+Ge323/lrgDAWJoF46tzGQHwBHFw== +v8-to-istanbul@^9.0.0, v8-to-istanbul@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz#b6f994b0b5d4ef255e17a0d17dc444a9f5132fa4" + integrity sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w== dependencies: - "@jridgewell/trace-mapping" "^0.3.7" + "@jridgewell/trace-mapping" "^0.3.12" "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^1.6.0" verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" @@ -6627,7 +6595,7 @@ vm-browserify@^1.0.0: void-elements@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" - integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w= + integrity sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung== vue-docgen-api@^3.26.0: version "3.26.0" @@ -6646,12 +6614,12 @@ vue-docgen-api@^3.26.0: vue-template-compiler "^2.0.0" vue-template-compiler@^2.0.0: - version "2.6.14" - resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.14.tgz#a2f0e7d985670d42c9c9ee0d044fed7690f4f763" - integrity sha512-ODQS1SyMbjKoO1JBJZojSw6FE4qnh9rIpUZn2EUT86FKizx9uH5z6uXiIrm4/Nb/gwxTi/o17ZDEGWAXHvtC7g== + version "2.7.1" + resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.7.1.tgz#ebbefd9cc9a7b9ee9ee6862fa1ec3a9bf3959963" + integrity sha512-ku/H1k1yHAgY0BEdoXVj7xZIjuFSwB2IV3nQWnmUMJ6U1jzK56LPHLWzEe5bTzt0WR0b/rJRkuiig44SUoaBoQ== dependencies: de-indent "^1.0.2" - he "^1.1.0" + he "^1.2.0" vue2-ace-editor@^0.0.15: version "0.0.15" @@ -6660,7 +6628,7 @@ vue2-ace-editor@^0.0.15: dependencies: brace "^0.11.0" -walker@^1.0.7: +walker@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== @@ -6670,7 +6638,7 @@ walker@^1.0.7: webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== webidl-conversions@^4.0.2: version "4.0.2" @@ -6685,7 +6653,7 @@ webidl-conversions@^6.1.0: whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== dependencies: tr46 "~0.0.3" webidl-conversions "^3.0.0" @@ -6732,12 +6700,12 @@ which@^2.0.1: window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" - integrity sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0= + integrity sha512-1pTPQDKTdd61ozlKGNCjhNRd+KPmgLSGa3mZTHoOliaGcESD8G1PXhh7c1fgiPjVbNVfgy2Faw4BI8/m0cC8Mg== with@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/with/-/with-5.1.1.tgz#fa4daa92daf32c4ea94ed453c81f04686b575dfe" - integrity sha1-+k2qktrzLE6pTtRTyB8EaGtXXf4= + integrity sha512-uAnSsFGfSpF6DNhBXStvlZILfHJfJu4eUkfbRGk94kGO1Ta7bg6FwfvoOhhyHAJuFbCw+0xk4uJ3u57jLvlCJg== dependencies: acorn "^3.1.0" acorn-globals "^3.0.0" @@ -6750,7 +6718,7 @@ word-wrap@^1.2.3: wordwrap@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" - integrity sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8= + integrity sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q== wrap-ansi@^7.0.0: version "7.0.0" @@ -6764,7 +6732,7 @@ wrap-ansi@^7.0.0: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== write-file-atomic@^4.0.1: version "4.0.1" @@ -6777,7 +6745,7 @@ write-file-atomic@^4.0.1: xml@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5" - integrity sha1-eLpyAgApxbyHuKgaPPzXS0ovweU= + integrity sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw== xmlcreate@^2.0.4: version "2.0.4" @@ -6797,7 +6765,7 @@ y18n@^5.0.5: yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= + integrity sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A== yallist@^4.0.0: version "4.0.0" @@ -6843,7 +6811,7 @@ yargs@^17.0.1, yargs@^17.3.1: yargs@~3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" - integrity sha1-9+572FfdfB0tOMDnTvvWgdFDH9E= + integrity sha512-QFzUah88GAGy9lyDKGBqZdkYApt63rCXYBGYnEP4xDJPXNqXXnBDACnbrXnViV6jRSqAePwrATi2i8mfYm4L1A== dependencies: camelcase "^1.0.2" cliui "^2.1.0"