From 84d7d43a0d2486cdde461cdaf469a9910e3e6144 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Sat, 11 Nov 2023 16:03:08 +0100 Subject: [PATCH 01/11] Load web workers in a way that Webpack 5 can bundle them --- src/BlurhashEncoder.ts | 6 ++++-- src/WorkerManager.ts | 4 ++-- src/audio/Playback.ts | 6 ++++-- src/utils/createMatrixClient.ts | 5 +---- test/WorkerManager-test.ts | 4 ++-- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/BlurhashEncoder.ts b/src/BlurhashEncoder.ts index 89ed2b56e54..30c1bc80d12 100644 --- a/src/BlurhashEncoder.ts +++ b/src/BlurhashEncoder.ts @@ -15,7 +15,7 @@ limitations under the License. */ // @ts-ignore - `.ts` is needed here to make TS happy -import BlurhashWorker, { Request, Response } from "./workers/blurhash.worker.ts"; +import { Request, Response } from "./workers/blurhash.worker.ts"; import { WorkerManager } from "./WorkerManager"; export class BlurhashEncoder { @@ -25,7 +25,9 @@ export class BlurhashEncoder { return BlurhashEncoder.internalInstance; } - private readonly worker = new WorkerManager(BlurhashWorker); + private readonly worker = new WorkerManager( + new Worker(new URL("./workers/blurhash.worker.ts", import.meta.url)), + ); public getBlurhash(imageData: ImageData): Promise { return this.worker.call({ imageData }).then((resp) => resp.blurhash); diff --git a/src/WorkerManager.ts b/src/WorkerManager.ts index 5dcb56c6109..2ad5191b246 100644 --- a/src/WorkerManager.ts +++ b/src/WorkerManager.ts @@ -23,8 +23,8 @@ export class WorkerManager { private seq = 0; private pendingDeferredMap = new Map>(); - public constructor(WorkerConstructor: { new (): Worker }) { - this.worker = new WorkerConstructor(); + public constructor(worker: Worker) { + this.worker = worker; this.worker.onmessage = this.onMessage; } diff --git a/src/audio/Playback.ts b/src/audio/Playback.ts index 43cbf904c0e..bd45703d2e5 100644 --- a/src/audio/Playback.ts +++ b/src/audio/Playback.ts @@ -20,7 +20,7 @@ import { logger } from "matrix-js-sdk/src/logger"; import { defer } from "matrix-js-sdk/src/utils"; // @ts-ignore - `.ts` is needed here to make TS happy -import PlaybackWorker, { Request, Response } from "../workers/playback.worker.ts"; +import { Request, Response } from "../workers/playback.worker.ts"; import { UPDATE_EVENT } from "../stores/AsyncStore"; import { arrayFastResample } from "../utils/arrays"; import { IDestroyable } from "../utils/IDestroyable"; @@ -63,7 +63,9 @@ export class Playback extends EventEmitter implements IDestroyable, PlaybackInte private waveformObservable = new SimpleObservable(); private readonly clock: PlaybackClock; private readonly fileSize: number; - private readonly worker = new WorkerManager(PlaybackWorker); + private readonly worker = new WorkerManager( + new Worker(new URL("../workers/playback.worker.ts", import.meta.url)), + ); /** * Creates a new playback instance from a buffer. diff --git a/src/utils/createMatrixClient.ts b/src/utils/createMatrixClient.ts index 1bcfcba19e1..77dc7ef25c9 100644 --- a/src/utils/createMatrixClient.ts +++ b/src/utils/createMatrixClient.ts @@ -24,9 +24,6 @@ import { LocalStorageCryptoStore, } from "matrix-js-sdk/src/matrix"; -// @ts-ignore - `.ts` is needed here to make TS happy -import IndexedDBWorker from "../workers/indexeddb.worker.ts"; - const localStorage = window.localStorage; // just *accessing* indexedDB throws an exception in firefox with @@ -55,7 +52,7 @@ export default function createMatrixClient(opts: ICreateClientOpts): MatrixClien indexedDB: indexedDB, dbName: "riot-web-sync", localStorage, - workerFactory: () => new IndexedDBWorker(), + workerFactory: () => new Worker(new URL("../workers/indexeddb.worker.ts", import.meta.url)), }); } else if (localStorage) { storeOpts.store = new MemoryStore({ localStorage }); diff --git a/test/WorkerManager-test.ts b/test/WorkerManager-test.ts index 39057ee04dc..8d02c0619a0 100644 --- a/test/WorkerManager-test.ts +++ b/test/WorkerManager-test.ts @@ -19,7 +19,7 @@ import { WorkerManager } from "../src/WorkerManager"; describe("WorkerManager", () => { it("should generate consecutive sequence numbers for each call", () => { const postMessage = jest.fn(); - const manager = new WorkerManager(jest.fn(() => ({ postMessage } as unknown as Worker))); + const manager = new WorkerManager({ postMessage } as unknown as Worker); manager.call({ data: "One" }); manager.call({ data: "Two" }); @@ -37,7 +37,7 @@ describe("WorkerManager", () => { it("should support resolving out of order", async () => { const postMessage = jest.fn(); const worker = { postMessage } as unknown as Worker; - const manager = new WorkerManager(jest.fn(() => worker)); + const manager = new WorkerManager(worker); const oneProm = manager.call({ data: "One" }); const twoProm = manager.call({ data: "Two" }); From 74961dbfb13b61cbe4cb3369c4b5f88033463a8e Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Mon, 13 Nov 2023 19:35:04 +0100 Subject: [PATCH 02/11] Extract worker creation into factories and mack them in tests --- __mocks__/workerFactoryMock.js | 19 +++++++++++++++++++ __mocks__/workerMock.js | 1 - jest.config.ts | 2 +- src/BlurhashEncoder.ts | 5 ++--- src/audio/Playback.ts | 5 ++--- src/utils/createMatrixClient.ts | 3 ++- src/workers/blurhashWorkerFactory.ts | 19 +++++++++++++++++++ src/workers/indexeddbWorkerFactory.ts | 19 +++++++++++++++++++ src/workers/playbackWorkerFactory.ts | 19 +++++++++++++++++++ tsconfig.json | 2 +- 10 files changed, 84 insertions(+), 10 deletions(-) create mode 100644 __mocks__/workerFactoryMock.js delete mode 100644 __mocks__/workerMock.js create mode 100644 src/workers/blurhashWorkerFactory.ts create mode 100644 src/workers/indexeddbWorkerFactory.ts create mode 100644 src/workers/playbackWorkerFactory.ts diff --git a/__mocks__/workerFactoryMock.js b/__mocks__/workerFactoryMock.js new file mode 100644 index 00000000000..d86d2f0f5f9 --- /dev/null +++ b/__mocks__/workerFactoryMock.js @@ -0,0 +1,19 @@ +/* +Copyright 2023 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 default function workerFactory(options) { + return jest.fn; +} diff --git a/__mocks__/workerMock.js b/__mocks__/workerMock.js deleted file mode 100644 index 6ee585673ed..00000000000 --- a/__mocks__/workerMock.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = jest.fn(); diff --git a/jest.config.ts b/jest.config.ts index 58bec7684e8..3e282958aa0 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -31,7 +31,7 @@ const config: Config = { "decoderWorker\\.min\\.js": "/__mocks__/empty.js", "decoderWorker\\.min\\.wasm": "/__mocks__/empty.js", "waveWorker\\.min\\.js": "/__mocks__/empty.js", - "workers/(.+)\\.worker\\.ts": "/__mocks__/workerMock.js", + "workers/(.+)Factory": "/__mocks__/workerFactoryMock.js", "^!!raw-loader!.*": "jest-raw-loader", "RecorderWorklet": "/__mocks__/empty.js", }, diff --git a/src/BlurhashEncoder.ts b/src/BlurhashEncoder.ts index 30c1bc80d12..90cd9fa8e10 100644 --- a/src/BlurhashEncoder.ts +++ b/src/BlurhashEncoder.ts @@ -17,6 +17,7 @@ limitations under the License. // @ts-ignore - `.ts` is needed here to make TS happy import { Request, Response } from "./workers/blurhash.worker.ts"; import { WorkerManager } from "./WorkerManager"; +import blurhashWorkerFactory from "./workers/blurhashWorkerFactory.js"; export class BlurhashEncoder { private static internalInstance = new BlurhashEncoder(); @@ -25,9 +26,7 @@ export class BlurhashEncoder { return BlurhashEncoder.internalInstance; } - private readonly worker = new WorkerManager( - new Worker(new URL("./workers/blurhash.worker.ts", import.meta.url)), - ); + private readonly worker = new WorkerManager(blurhashWorkerFactory()); public getBlurhash(imageData: ImageData): Promise { return this.worker.call({ imageData }).then((resp) => resp.blurhash); diff --git a/src/audio/Playback.ts b/src/audio/Playback.ts index bd45703d2e5..d9482f51afc 100644 --- a/src/audio/Playback.ts +++ b/src/audio/Playback.ts @@ -29,6 +29,7 @@ import { createAudioContext, decodeOgg } from "./compat"; import { clamp } from "../utils/numbers"; import { WorkerManager } from "../WorkerManager"; import { DEFAULT_WAVEFORM, PLAYBACK_WAVEFORM_SAMPLES } from "./consts"; +import playbackWorkerFactory from "../workers/playbackWorkerFactory.js"; export enum PlaybackState { Decoding = "decoding", @@ -63,9 +64,7 @@ export class Playback extends EventEmitter implements IDestroyable, PlaybackInte private waveformObservable = new SimpleObservable(); private readonly clock: PlaybackClock; private readonly fileSize: number; - private readonly worker = new WorkerManager( - new Worker(new URL("../workers/playback.worker.ts", import.meta.url)), - ); + private readonly worker = new WorkerManager(playbackWorkerFactory()); /** * Creates a new playback instance from a buffer. diff --git a/src/utils/createMatrixClient.ts b/src/utils/createMatrixClient.ts index 77dc7ef25c9..1569231bda2 100644 --- a/src/utils/createMatrixClient.ts +++ b/src/utils/createMatrixClient.ts @@ -23,6 +23,7 @@ import { IndexedDBStore, LocalStorageCryptoStore, } from "matrix-js-sdk/src/matrix"; +import indexeddbWorkerFactory from "../workers/indexeddbWorkerFactory"; const localStorage = window.localStorage; @@ -52,7 +53,7 @@ export default function createMatrixClient(opts: ICreateClientOpts): MatrixClien indexedDB: indexedDB, dbName: "riot-web-sync", localStorage, - workerFactory: () => new Worker(new URL("../workers/indexeddb.worker.ts", import.meta.url)), + workerFactory: indexeddbWorkerFactory, }); } else if (localStorage) { storeOpts.store = new MemoryStore({ localStorage }); diff --git a/src/workers/blurhashWorkerFactory.ts b/src/workers/blurhashWorkerFactory.ts new file mode 100644 index 00000000000..ba66a27ef14 --- /dev/null +++ b/src/workers/blurhashWorkerFactory.ts @@ -0,0 +1,19 @@ +/* +Copyright 2023 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 default function blurhashWorkerFactory(options?: WorkerOptions | undefined): Worker { + return new Worker(new URL("./workers/blurhash.worker.ts", import.meta.url), options); +} \ No newline at end of file diff --git a/src/workers/indexeddbWorkerFactory.ts b/src/workers/indexeddbWorkerFactory.ts new file mode 100644 index 00000000000..a2cb9c65912 --- /dev/null +++ b/src/workers/indexeddbWorkerFactory.ts @@ -0,0 +1,19 @@ +/* +Copyright 2023 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 default function blurhashWorkerFactory(options?: WorkerOptions | undefined): Worker { + return new Worker(new URL("../workers/indexeddb.worker.ts", import.meta.url), options) +} \ No newline at end of file diff --git a/src/workers/playbackWorkerFactory.ts b/src/workers/playbackWorkerFactory.ts new file mode 100644 index 00000000000..6cca41841ac --- /dev/null +++ b/src/workers/playbackWorkerFactory.ts @@ -0,0 +1,19 @@ +/* +Copyright 2023 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 default function blurhashWorkerFactory(options?: WorkerOptions | undefined): Worker { + return new Worker(new URL("../workers/playback.worker.ts", import.meta.url), options) +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index e7689727ac9..3d5f96e1c27 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,7 @@ "emitDecoratorMetadata": false, "resolveJsonModule": true, "esModuleInterop": true, - "module": "commonjs", + "module": "es2022", "moduleResolution": "node", "target": "es2016", "noUnusedLocals": true, From 64ba0b4130e886d8b9890ebaa4c4087d91bedf4d Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Mon, 13 Nov 2023 19:39:45 +0100 Subject: [PATCH 03/11] Squashed commit of the following: commit 01a62b36a484d65664a641c4db2a7f3373251b47 Merge: 10edf06898 74961dbfb1 Author: Johannes Marbach Date: Mon Nov 13 19:38:47 2023 +0100 Merge branch 'johannes/webpack5-workers' into johannes/worklet-path commit 10edf068980f11b99bf2b18dce72e27065fd5727 Author: Johannes Marbach Date: Sun Nov 12 12:21:43 2023 +0100 Document syntax and use .ts commit 4040f2ce4121ddaf5254cb68e2e9b8716b0431d0 Author: Johannes Marbach Date: Sat Nov 11 21:38:09 2023 +0100 Switch to URL and use syntax compatible with Webpack commit b4f96f17cc1819bd84b8e6735a8c3f69948e97c4 Merge: eed2ffdc1c 94484692f8 Author: Johannes Marbach Date: Thu Nov 9 21:04:06 2023 +0100 Merge branch 'develop' into johannes/worklet-path commit eed2ffdc1c27e8748719b64e002c44e3dc6500e7 Author: Johannes Marbach Date: Thu Nov 9 21:03:45 2023 +0100 Restore unused import to fix dead code analysis commit 689cea2f061120070f3db405289bd9ded108def5 Author: Johannes Marbach Date: Thu Nov 9 16:50:56 2023 +0100 Use literal path in audioWorklet.addModule for compatibility with Webpack 5 --- src/audio/VoiceRecording.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/audio/VoiceRecording.ts b/src/audio/VoiceRecording.ts index 2e1f5634fbe..53656c1a34d 100644 --- a/src/audio/VoiceRecording.ts +++ b/src/audio/VoiceRecording.ts @@ -28,6 +28,10 @@ import { UPDATE_EVENT } from "../stores/AsyncStore"; import { createAudioContext } from "./compat"; import { FixedRollingArray } from "../utils/FixedRollingArray"; import { clamp } from "../utils/numbers"; +// This import is needed for dead code analysis but not actually used because the +// built-in worker / worklet handling in Webpack 5 only supports static paths +// @ts-ignore no-unused-locals +// eslint-disable-next-line @typescript-eslint/no-unused-vars import mxRecorderWorkletPath from "./RecorderWorklet"; const CHANNELS = 1; // stereo isn't important @@ -129,7 +133,13 @@ export class VoiceRecording extends EventEmitter implements IDestroyable { if (this.recorderContext.audioWorklet) { // Set up our worklet. We use this for timing information and waveform analysis: the // web audio API prefers this be done async to avoid holding the main thread with math. - await this.recorderContext.audioWorklet.addModule(mxRecorderWorkletPath); + + // The audioWorklet.addModule syntax is required for Webpack 5 to correctly recognise + // this as a worklet rather than an asset. This also requires the parser.javascript.worker + // configuration described in https://github.com/webpack/webpack.js.org/issues/6869. + const audioWorklet = this.recorderContext.audioWorklet; + await audioWorklet.addModule(new URL("./RecorderWorklet.ts", import.meta.url)); + this.recorderWorklet = new AudioWorkletNode(this.recorderContext, WORKLET_NAME); this.recorderSource.connect(this.recorderWorklet); this.recorderWorklet.connect(this.recorderContext.destination); From 5855930221203679b5755866f98144b4969862a5 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Mon, 13 Nov 2023 19:52:15 +0100 Subject: [PATCH 04/11] Extra worklet module loading and mock it in tests --- jest.config.ts | 2 +- src/audio/VoiceRecording.ts | 13 ++----------- src/audio/recorderWorkletFactory.ts | 28 ++++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 src/audio/recorderWorkletFactory.ts diff --git a/jest.config.ts b/jest.config.ts index 3e282958aa0..4c62324bcc9 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -33,7 +33,7 @@ const config: Config = { "waveWorker\\.min\\.js": "/__mocks__/empty.js", "workers/(.+)Factory": "/__mocks__/workerFactoryMock.js", "^!!raw-loader!.*": "jest-raw-loader", - "RecorderWorklet": "/__mocks__/empty.js", + "recorderWorkletFactory": "/__mocks__/empty.js", }, transformIgnorePatterns: ["/node_modules/(?!matrix-js-sdk).+$"], collectCoverageFrom: [ diff --git a/src/audio/VoiceRecording.ts b/src/audio/VoiceRecording.ts index 53656c1a34d..9f12dc33f7b 100644 --- a/src/audio/VoiceRecording.ts +++ b/src/audio/VoiceRecording.ts @@ -28,11 +28,7 @@ import { UPDATE_EVENT } from "../stores/AsyncStore"; import { createAudioContext } from "./compat"; import { FixedRollingArray } from "../utils/FixedRollingArray"; import { clamp } from "../utils/numbers"; -// This import is needed for dead code analysis but not actually used because the -// built-in worker / worklet handling in Webpack 5 only supports static paths -// @ts-ignore no-unused-locals -// eslint-disable-next-line @typescript-eslint/no-unused-vars -import mxRecorderWorkletPath from "./RecorderWorklet"; +import recorderWorkletFactory from "./recorderWorkletFactory"; const CHANNELS = 1; // stereo isn't important export const SAMPLE_RATE = 48000; // 48khz is what WebRTC uses. 12khz is where we lose quality. @@ -133,12 +129,7 @@ export class VoiceRecording extends EventEmitter implements IDestroyable { if (this.recorderContext.audioWorklet) { // Set up our worklet. We use this for timing information and waveform analysis: the // web audio API prefers this be done async to avoid holding the main thread with math. - - // The audioWorklet.addModule syntax is required for Webpack 5 to correctly recognise - // this as a worklet rather than an asset. This also requires the parser.javascript.worker - // configuration described in https://github.com/webpack/webpack.js.org/issues/6869. - const audioWorklet = this.recorderContext.audioWorklet; - await audioWorklet.addModule(new URL("./RecorderWorklet.ts", import.meta.url)); + await recorderWorkletFactory(this.recorderContext); this.recorderWorklet = new AudioWorkletNode(this.recorderContext, WORKLET_NAME); this.recorderSource.connect(this.recorderWorklet); diff --git a/src/audio/recorderWorkletFactory.ts b/src/audio/recorderWorkletFactory.ts new file mode 100644 index 00000000000..697d8bd7d20 --- /dev/null +++ b/src/audio/recorderWorkletFactory.ts @@ -0,0 +1,28 @@ +/* +Copyright 2023 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. +*/ + +// This import is needed for dead code analysis but not actually used because the +// built-in worker / worklet handling in Webpack 5 only supports static paths +// @ts-ignore no-unused-locals +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import mxRecorderWorkletPath from "./RecorderWorklet"; + +export default function recorderWorkletFactory(context: AudioContext): Promise { + // The context.audioWorklet.addModule syntax is required for Webpack 5 to correctly recognise + // this as a worklet rather than an asset. This also requires the parser.javascript.worker + // configuration described in https://github.com/webpack/webpack.js.org/issues/6869. + return context.audioWorklet.addModule(new URL("./RecorderWorklet.ts", import.meta.url)); +} From 99ad1781a51ec54fae3e2f876b0243abe1c10cf1 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Mon, 13 Nov 2023 19:54:04 +0100 Subject: [PATCH 05/11] Appease the linter --- __mocks__/workerFactoryMock.js | 2 +- src/audio/recorderWorkletFactory.ts | 8 ++++---- src/utils/createMatrixClient.ts | 1 + src/workers/blurhashWorkerFactory.ts | 4 ++-- src/workers/indexeddbWorkerFactory.ts | 4 ++-- src/workers/playbackWorkerFactory.ts | 4 ++-- 6 files changed, 12 insertions(+), 11 deletions(-) diff --git a/__mocks__/workerFactoryMock.js b/__mocks__/workerFactoryMock.js index d86d2f0f5f9..56dc085cd3c 100644 --- a/__mocks__/workerFactoryMock.js +++ b/__mocks__/workerFactoryMock.js @@ -15,5 +15,5 @@ limitations under the License. */ export default function workerFactory(options) { - return jest.fn; + return jest.fn; } diff --git a/src/audio/recorderWorkletFactory.ts b/src/audio/recorderWorkletFactory.ts index 697d8bd7d20..925c9e911fa 100644 --- a/src/audio/recorderWorkletFactory.ts +++ b/src/audio/recorderWorkletFactory.ts @@ -21,8 +21,8 @@ limitations under the License. import mxRecorderWorkletPath from "./RecorderWorklet"; export default function recorderWorkletFactory(context: AudioContext): Promise { - // The context.audioWorklet.addModule syntax is required for Webpack 5 to correctly recognise - // this as a worklet rather than an asset. This also requires the parser.javascript.worker - // configuration described in https://github.com/webpack/webpack.js.org/issues/6869. - return context.audioWorklet.addModule(new URL("./RecorderWorklet.ts", import.meta.url)); + // The context.audioWorklet.addModule syntax is required for Webpack 5 to correctly recognise + // this as a worklet rather than an asset. This also requires the parser.javascript.worker + // configuration described in https://github.com/webpack/webpack.js.org/issues/6869. + return context.audioWorklet.addModule(new URL("./RecorderWorklet.ts", import.meta.url)); } diff --git a/src/utils/createMatrixClient.ts b/src/utils/createMatrixClient.ts index 1569231bda2..cdc96164266 100644 --- a/src/utils/createMatrixClient.ts +++ b/src/utils/createMatrixClient.ts @@ -23,6 +23,7 @@ import { IndexedDBStore, LocalStorageCryptoStore, } from "matrix-js-sdk/src/matrix"; + import indexeddbWorkerFactory from "../workers/indexeddbWorkerFactory"; const localStorage = window.localStorage; diff --git a/src/workers/blurhashWorkerFactory.ts b/src/workers/blurhashWorkerFactory.ts index ba66a27ef14..422b8ab6af0 100644 --- a/src/workers/blurhashWorkerFactory.ts +++ b/src/workers/blurhashWorkerFactory.ts @@ -15,5 +15,5 @@ limitations under the License. */ export default function blurhashWorkerFactory(options?: WorkerOptions | undefined): Worker { - return new Worker(new URL("./workers/blurhash.worker.ts", import.meta.url), options); -} \ No newline at end of file + return new Worker(new URL("./workers/blurhash.worker.ts", import.meta.url), options); +} diff --git a/src/workers/indexeddbWorkerFactory.ts b/src/workers/indexeddbWorkerFactory.ts index a2cb9c65912..a2f6287cbe6 100644 --- a/src/workers/indexeddbWorkerFactory.ts +++ b/src/workers/indexeddbWorkerFactory.ts @@ -15,5 +15,5 @@ limitations under the License. */ export default function blurhashWorkerFactory(options?: WorkerOptions | undefined): Worker { - return new Worker(new URL("../workers/indexeddb.worker.ts", import.meta.url), options) -} \ No newline at end of file + return new Worker(new URL("../workers/indexeddb.worker.ts", import.meta.url), options); +} diff --git a/src/workers/playbackWorkerFactory.ts b/src/workers/playbackWorkerFactory.ts index 6cca41841ac..1d9ebc33d90 100644 --- a/src/workers/playbackWorkerFactory.ts +++ b/src/workers/playbackWorkerFactory.ts @@ -15,5 +15,5 @@ limitations under the License. */ export default function blurhashWorkerFactory(options?: WorkerOptions | undefined): Worker { - return new Worker(new URL("../workers/playback.worker.ts", import.meta.url), options) -} \ No newline at end of file + return new Worker(new URL("../workers/playback.worker.ts", import.meta.url), options); +} From 253ff78c00026d1d56513150a6539f4aa716676a Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Mon, 13 Nov 2023 20:01:02 +0100 Subject: [PATCH 06/11] Also use es2022 in Cypress tsconfig --- cypress/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cypress/tsconfig.json b/cypress/tsconfig.json index d8a522d4174..a7f97875ec6 100644 --- a/cypress/tsconfig.json +++ b/cypress/tsconfig.json @@ -7,7 +7,7 @@ "resolveJsonModule": true, "esModuleInterop": true, "moduleResolution": "node", - "module": "commonjs" + "module": "es2022" }, "include": ["**/*.ts"] } From 624be1a7fa4bd0e1053fd545aa8d1abaccbd3e7b Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Mon, 13 Nov 2023 20:10:55 +0100 Subject: [PATCH 07/11] Fix paths and extensions --- src/BlurhashEncoder.ts | 2 +- src/audio/Playback.ts | 2 +- src/workers/blurhashWorkerFactory.ts | 2 +- src/workers/indexeddbWorkerFactory.ts | 2 +- src/workers/playbackWorkerFactory.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/BlurhashEncoder.ts b/src/BlurhashEncoder.ts index 90cd9fa8e10..457fe01e7d9 100644 --- a/src/BlurhashEncoder.ts +++ b/src/BlurhashEncoder.ts @@ -17,7 +17,7 @@ limitations under the License. // @ts-ignore - `.ts` is needed here to make TS happy import { Request, Response } from "./workers/blurhash.worker.ts"; import { WorkerManager } from "./WorkerManager"; -import blurhashWorkerFactory from "./workers/blurhashWorkerFactory.js"; +import blurhashWorkerFactory from "./workers/blurhashWorkerFactory"; export class BlurhashEncoder { private static internalInstance = new BlurhashEncoder(); diff --git a/src/audio/Playback.ts b/src/audio/Playback.ts index d9482f51afc..a40e0a463cd 100644 --- a/src/audio/Playback.ts +++ b/src/audio/Playback.ts @@ -29,7 +29,7 @@ import { createAudioContext, decodeOgg } from "./compat"; import { clamp } from "../utils/numbers"; import { WorkerManager } from "../WorkerManager"; import { DEFAULT_WAVEFORM, PLAYBACK_WAVEFORM_SAMPLES } from "./consts"; -import playbackWorkerFactory from "../workers/playbackWorkerFactory.js"; +import playbackWorkerFactory from "../workers/playbackWorkerFactory"; export enum PlaybackState { Decoding = "decoding", diff --git a/src/workers/blurhashWorkerFactory.ts b/src/workers/blurhashWorkerFactory.ts index 422b8ab6af0..a75546be1bf 100644 --- a/src/workers/blurhashWorkerFactory.ts +++ b/src/workers/blurhashWorkerFactory.ts @@ -15,5 +15,5 @@ limitations under the License. */ export default function blurhashWorkerFactory(options?: WorkerOptions | undefined): Worker { - return new Worker(new URL("./workers/blurhash.worker.ts", import.meta.url), options); + return new Worker(new URL("./blurhash.worker.ts", import.meta.url), options); } diff --git a/src/workers/indexeddbWorkerFactory.ts b/src/workers/indexeddbWorkerFactory.ts index a2f6287cbe6..c3b7975569c 100644 --- a/src/workers/indexeddbWorkerFactory.ts +++ b/src/workers/indexeddbWorkerFactory.ts @@ -15,5 +15,5 @@ limitations under the License. */ export default function blurhashWorkerFactory(options?: WorkerOptions | undefined): Worker { - return new Worker(new URL("../workers/indexeddb.worker.ts", import.meta.url), options); + return new Worker(new URL("./indexeddb.worker.ts", import.meta.url), options); } diff --git a/src/workers/playbackWorkerFactory.ts b/src/workers/playbackWorkerFactory.ts index 1d9ebc33d90..f6aba5f8002 100644 --- a/src/workers/playbackWorkerFactory.ts +++ b/src/workers/playbackWorkerFactory.ts @@ -15,5 +15,5 @@ limitations under the License. */ export default function blurhashWorkerFactory(options?: WorkerOptions | undefined): Worker { - return new Worker(new URL("../workers/playback.worker.ts", import.meta.url), options); + return new Worker(new URL("./playback.worker.ts", import.meta.url), options); } From 327437777dcdc6c76fa57c2760f605ef99d59f83 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Tue, 14 Nov 2023 14:32:16 +0100 Subject: [PATCH 08/11] Fix worker factory and chunk names --- src/workers/blurhashWorkerFactory.ts | 4 ++-- src/workers/indexeddbWorkerFactory.ts | 4 ++-- src/workers/playbackWorkerFactory.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/workers/blurhashWorkerFactory.ts b/src/workers/blurhashWorkerFactory.ts index a75546be1bf..cd5bfe31ff6 100644 --- a/src/workers/blurhashWorkerFactory.ts +++ b/src/workers/blurhashWorkerFactory.ts @@ -14,6 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -export default function blurhashWorkerFactory(options?: WorkerOptions | undefined): Worker { - return new Worker(new URL("./blurhash.worker.ts", import.meta.url), options); +export default function factory(options?: WorkerOptions | undefined): Worker { + return new Worker(/* webpackChunkName: "blurhash.worker" */ new URL("./blurhash.worker.ts", import.meta.url), options); } diff --git a/src/workers/indexeddbWorkerFactory.ts b/src/workers/indexeddbWorkerFactory.ts index c3b7975569c..1ea3df3c79f 100644 --- a/src/workers/indexeddbWorkerFactory.ts +++ b/src/workers/indexeddbWorkerFactory.ts @@ -14,6 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -export default function blurhashWorkerFactory(options?: WorkerOptions | undefined): Worker { - return new Worker(new URL("./indexeddb.worker.ts", import.meta.url), options); +export default function factory(options?: WorkerOptions | undefined): Worker { + return new Worker(/* webpackChunkName: "indexeddb.worker" */ new URL("./indexeddb.worker.ts", import.meta.url), options); } diff --git a/src/workers/playbackWorkerFactory.ts b/src/workers/playbackWorkerFactory.ts index f6aba5f8002..36eaf5e180f 100644 --- a/src/workers/playbackWorkerFactory.ts +++ b/src/workers/playbackWorkerFactory.ts @@ -14,6 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -export default function blurhashWorkerFactory(options?: WorkerOptions | undefined): Worker { - return new Worker(new URL("./playback.worker.ts", import.meta.url), options); +export default function factory(options?: WorkerOptions | undefined): Worker { + return new Worker(/* webpackChunkName: "playback.worker" */ new URL("./playback.worker.ts", import.meta.url), options); } From 8a6c590b7da5acb22753427f2cd38c0e6db99b1a Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Tue, 14 Nov 2023 14:40:51 +0100 Subject: [PATCH 09/11] Set name for worklet chunk --- src/audio/recorderWorkletFactory.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio/recorderWorkletFactory.ts b/src/audio/recorderWorkletFactory.ts index 925c9e911fa..efd4a9f23f2 100644 --- a/src/audio/recorderWorkletFactory.ts +++ b/src/audio/recorderWorkletFactory.ts @@ -24,5 +24,5 @@ export default function recorderWorkletFactory(context: AudioContext): Promise Date: Sat, 18 Nov 2023 21:36:11 +0100 Subject: [PATCH 10/11] Revert back to worklet-loader compatible syntax --- src/audio/recorderWorkletFactory.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/audio/recorderWorkletFactory.ts b/src/audio/recorderWorkletFactory.ts index efd4a9f23f2..0a0c15a121b 100644 --- a/src/audio/recorderWorkletFactory.ts +++ b/src/audio/recorderWorkletFactory.ts @@ -14,15 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -// This import is needed for dead code analysis but not actually used because the -// built-in worker / worklet handling in Webpack 5 only supports static paths -// @ts-ignore no-unused-locals -// eslint-disable-next-line @typescript-eslint/no-unused-vars import mxRecorderWorkletPath from "./RecorderWorklet"; export default function recorderWorkletFactory(context: AudioContext): Promise { - // The context.audioWorklet.addModule syntax is required for Webpack 5 to correctly recognise - // this as a worklet rather than an asset. This also requires the parser.javascript.worker - // configuration described in https://github.com/webpack/webpack.js.org/issues/6869. - return context.audioWorklet.addModule(/* webpackChunkName: "recorder.worklet" */ new URL("./RecorderWorklet.ts", import.meta.url)); + // In future we should be using the built-in worklet support in Webpack 5 with the syntax + // described in https://github.com/webpack/webpack.js.org/issues/6869: + // addModule(/* webpackChunkName: "recorder.worklet" */ new URL("./RecorderWorklet.ts", import.meta.url)); + return context.audioWorklet.addModule(mxRecorderWorkletPath); } From e35b2135b46bb79a000af0062c753c7ce08e66c1 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Sat, 18 Nov 2023 21:37:49 +0100 Subject: [PATCH 11/11] Appease the linter --- src/workers/blurhashWorkerFactory.ts | 5 ++++- src/workers/indexeddbWorkerFactory.ts | 5 ++++- src/workers/playbackWorkerFactory.ts | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/workers/blurhashWorkerFactory.ts b/src/workers/blurhashWorkerFactory.ts index cd5bfe31ff6..17e3af2fba2 100644 --- a/src/workers/blurhashWorkerFactory.ts +++ b/src/workers/blurhashWorkerFactory.ts @@ -15,5 +15,8 @@ limitations under the License. */ export default function factory(options?: WorkerOptions | undefined): Worker { - return new Worker(/* webpackChunkName: "blurhash.worker" */ new URL("./blurhash.worker.ts", import.meta.url), options); + return new Worker( + /* webpackChunkName: "blurhash.worker" */ new URL("./blurhash.worker.ts", import.meta.url), + options, + ); } diff --git a/src/workers/indexeddbWorkerFactory.ts b/src/workers/indexeddbWorkerFactory.ts index 1ea3df3c79f..46de5cfe3c0 100644 --- a/src/workers/indexeddbWorkerFactory.ts +++ b/src/workers/indexeddbWorkerFactory.ts @@ -15,5 +15,8 @@ limitations under the License. */ export default function factory(options?: WorkerOptions | undefined): Worker { - return new Worker(/* webpackChunkName: "indexeddb.worker" */ new URL("./indexeddb.worker.ts", import.meta.url), options); + return new Worker( + /* webpackChunkName: "indexeddb.worker" */ new URL("./indexeddb.worker.ts", import.meta.url), + options, + ); } diff --git a/src/workers/playbackWorkerFactory.ts b/src/workers/playbackWorkerFactory.ts index 36eaf5e180f..091b426ef91 100644 --- a/src/workers/playbackWorkerFactory.ts +++ b/src/workers/playbackWorkerFactory.ts @@ -15,5 +15,8 @@ limitations under the License. */ export default function factory(options?: WorkerOptions | undefined): Worker { - return new Worker(/* webpackChunkName: "playback.worker" */ new URL("./playback.worker.ts", import.meta.url), options); + return new Worker( + /* webpackChunkName: "playback.worker" */ new URL("./playback.worker.ts", import.meta.url), + options, + ); }