Merge pull request #11869 from matrix-org/johannes/webpack-5

This commit is contained in:
Johannes Marbach 2023-11-20 13:30:30 +01:00 committed by GitHub
commit 0a03b09f5d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 128 additions and 18 deletions

View file

@ -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;
}

View file

@ -1 +0,0 @@
module.exports = jest.fn();

View file

@ -7,7 +7,7 @@
"resolveJsonModule": true,
"esModuleInterop": true,
"moduleResolution": "node",
"module": "commonjs"
"module": "es2022"
},
"include": ["**/*.ts"]
}

View file

@ -31,9 +31,9 @@ const config: Config = {
"decoderWorker\\.min\\.js": "<rootDir>/__mocks__/empty.js",
"decoderWorker\\.min\\.wasm": "<rootDir>/__mocks__/empty.js",
"waveWorker\\.min\\.js": "<rootDir>/__mocks__/empty.js",
"workers/(.+)\\.worker\\.ts": "<rootDir>/__mocks__/workerMock.js",
"workers/(.+)Factory": "<rootDir>/__mocks__/workerFactoryMock.js",
"^!!raw-loader!.*": "jest-raw-loader",
"RecorderWorklet": "<rootDir>/__mocks__/empty.js",
"recorderWorkletFactory": "<rootDir>/__mocks__/empty.js",
},
transformIgnorePatterns: ["/node_modules/(?!matrix-js-sdk).+$"],
collectCoverageFrom: [

View file

@ -15,8 +15,9 @@ 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";
import blurhashWorkerFactory from "./workers/blurhashWorkerFactory";
export class BlurhashEncoder {
private static internalInstance = new BlurhashEncoder();
@ -25,7 +26,7 @@ export class BlurhashEncoder {
return BlurhashEncoder.internalInstance;
}
private readonly worker = new WorkerManager<Request, Response>(BlurhashWorker);
private readonly worker = new WorkerManager<Request, Response>(blurhashWorkerFactory());
public getBlurhash(imageData: ImageData): Promise<string> {
return this.worker.call({ imageData }).then((resp) => resp.blurhash);

View file

@ -23,8 +23,8 @@ export class WorkerManager<Request extends {}, Response> {
private seq = 0;
private pendingDeferredMap = new Map<number, IDeferred<Response>>();
public constructor(WorkerConstructor: { new (): Worker }) {
this.worker = new WorkerConstructor();
public constructor(worker: Worker) {
this.worker = worker;
this.worker.onmessage = this.onMessage;
}

View file

@ -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";
@ -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";
export enum PlaybackState {
Decoding = "decoding",
@ -63,7 +64,7 @@ export class Playback extends EventEmitter implements IDestroyable, PlaybackInte
private waveformObservable = new SimpleObservable<number[]>();
private readonly clock: PlaybackClock;
private readonly fileSize: number;
private readonly worker = new WorkerManager<Request, Response>(PlaybackWorker);
private readonly worker = new WorkerManager<Request, Response>(playbackWorkerFactory());
/**
* Creates a new playback instance from a buffer.

View file

@ -28,7 +28,7 @@ import { UPDATE_EVENT } from "../stores/AsyncStore";
import { createAudioContext } from "./compat";
import { FixedRollingArray } from "../utils/FixedRollingArray";
import { clamp } from "../utils/numbers";
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.
@ -129,7 +129,8 @@ 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);
await recorderWorkletFactory(this.recorderContext);
this.recorderWorklet = new AudioWorkletNode(this.recorderContext, WORKLET_NAME);
this.recorderSource.connect(this.recorderWorklet);
this.recorderWorklet.connect(this.recorderContext.destination);

View file

@ -0,0 +1,24 @@
/*
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.
*/
import mxRecorderWorkletPath from "./RecorderWorklet";
export default function recorderWorkletFactory(context: AudioContext): Promise<void> {
// 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);
}

View file

@ -24,8 +24,7 @@ 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";
import indexeddbWorkerFactory from "../workers/indexeddbWorkerFactory";
const localStorage = window.localStorage;
@ -55,7 +54,7 @@ export default function createMatrixClient(opts: ICreateClientOpts): MatrixClien
indexedDB: indexedDB,
dbName: "riot-web-sync",
localStorage,
workerFactory: () => new IndexedDBWorker(),
workerFactory: indexeddbWorkerFactory,
});
} else if (localStorage) {
storeOpts.store = new MemoryStore({ localStorage });

View file

@ -0,0 +1,22 @@
/*
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 factory(options?: WorkerOptions | undefined): Worker {
return new Worker(
/* webpackChunkName: "blurhash.worker" */ new URL("./blurhash.worker.ts", import.meta.url),
options,
);
}

View file

@ -0,0 +1,22 @@
/*
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 factory(options?: WorkerOptions | undefined): Worker {
return new Worker(
/* webpackChunkName: "indexeddb.worker" */ new URL("./indexeddb.worker.ts", import.meta.url),
options,
);
}

View file

@ -0,0 +1,22 @@
/*
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 factory(options?: WorkerOptions | undefined): Worker {
return new Worker(
/* webpackChunkName: "playback.worker" */ new URL("./playback.worker.ts", import.meta.url),
options,
);
}

View file

@ -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" });

View file

@ -4,7 +4,7 @@
"emitDecoratorMetadata": false,
"resolveJsonModule": true,
"esModuleInterop": true,
"module": "commonjs",
"module": "es2022",
"moduleResolution": "node",
"target": "es2016",
"noUnusedLocals": true,