Merge pull request #11869 from matrix-org/johannes/webpack-5
commit
0a03b09f5d
|
@ -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;
|
||||||
|
}
|
|
@ -1 +0,0 @@
|
||||||
module.exports = jest.fn();
|
|
|
@ -7,7 +7,7 @@
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"module": "commonjs"
|
"module": "es2022"
|
||||||
},
|
},
|
||||||
"include": ["**/*.ts"]
|
"include": ["**/*.ts"]
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,9 +31,9 @@ const config: Config = {
|
||||||
"decoderWorker\\.min\\.js": "<rootDir>/__mocks__/empty.js",
|
"decoderWorker\\.min\\.js": "<rootDir>/__mocks__/empty.js",
|
||||||
"decoderWorker\\.min\\.wasm": "<rootDir>/__mocks__/empty.js",
|
"decoderWorker\\.min\\.wasm": "<rootDir>/__mocks__/empty.js",
|
||||||
"waveWorker\\.min\\.js": "<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",
|
"^!!raw-loader!.*": "jest-raw-loader",
|
||||||
"RecorderWorklet": "<rootDir>/__mocks__/empty.js",
|
"recorderWorkletFactory": "<rootDir>/__mocks__/empty.js",
|
||||||
},
|
},
|
||||||
transformIgnorePatterns: ["/node_modules/(?!matrix-js-sdk).+$"],
|
transformIgnorePatterns: ["/node_modules/(?!matrix-js-sdk).+$"],
|
||||||
collectCoverageFrom: [
|
collectCoverageFrom: [
|
||||||
|
|
|
@ -15,8 +15,9 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @ts-ignore - `.ts` is needed here to make TS happy
|
// @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 { WorkerManager } from "./WorkerManager";
|
||||||
|
import blurhashWorkerFactory from "./workers/blurhashWorkerFactory";
|
||||||
|
|
||||||
export class BlurhashEncoder {
|
export class BlurhashEncoder {
|
||||||
private static internalInstance = new BlurhashEncoder();
|
private static internalInstance = new BlurhashEncoder();
|
||||||
|
@ -25,7 +26,7 @@ export class BlurhashEncoder {
|
||||||
return BlurhashEncoder.internalInstance;
|
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> {
|
public getBlurhash(imageData: ImageData): Promise<string> {
|
||||||
return this.worker.call({ imageData }).then((resp) => resp.blurhash);
|
return this.worker.call({ imageData }).then((resp) => resp.blurhash);
|
||||||
|
|
|
@ -23,8 +23,8 @@ export class WorkerManager<Request extends {}, Response> {
|
||||||
private seq = 0;
|
private seq = 0;
|
||||||
private pendingDeferredMap = new Map<number, IDeferred<Response>>();
|
private pendingDeferredMap = new Map<number, IDeferred<Response>>();
|
||||||
|
|
||||||
public constructor(WorkerConstructor: { new (): Worker }) {
|
public constructor(worker: Worker) {
|
||||||
this.worker = new WorkerConstructor();
|
this.worker = worker;
|
||||||
this.worker.onmessage = this.onMessage;
|
this.worker.onmessage = this.onMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ import { logger } from "matrix-js-sdk/src/logger";
|
||||||
import { defer } from "matrix-js-sdk/src/utils";
|
import { defer } from "matrix-js-sdk/src/utils";
|
||||||
|
|
||||||
// @ts-ignore - `.ts` is needed here to make TS happy
|
// @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 { UPDATE_EVENT } from "../stores/AsyncStore";
|
||||||
import { arrayFastResample } from "../utils/arrays";
|
import { arrayFastResample } from "../utils/arrays";
|
||||||
import { IDestroyable } from "../utils/IDestroyable";
|
import { IDestroyable } from "../utils/IDestroyable";
|
||||||
|
@ -29,6 +29,7 @@ import { createAudioContext, decodeOgg } from "./compat";
|
||||||
import { clamp } from "../utils/numbers";
|
import { clamp } from "../utils/numbers";
|
||||||
import { WorkerManager } from "../WorkerManager";
|
import { WorkerManager } from "../WorkerManager";
|
||||||
import { DEFAULT_WAVEFORM, PLAYBACK_WAVEFORM_SAMPLES } from "./consts";
|
import { DEFAULT_WAVEFORM, PLAYBACK_WAVEFORM_SAMPLES } from "./consts";
|
||||||
|
import playbackWorkerFactory from "../workers/playbackWorkerFactory";
|
||||||
|
|
||||||
export enum PlaybackState {
|
export enum PlaybackState {
|
||||||
Decoding = "decoding",
|
Decoding = "decoding",
|
||||||
|
@ -63,7 +64,7 @@ export class Playback extends EventEmitter implements IDestroyable, PlaybackInte
|
||||||
private waveformObservable = new SimpleObservable<number[]>();
|
private waveformObservable = new SimpleObservable<number[]>();
|
||||||
private readonly clock: PlaybackClock;
|
private readonly clock: PlaybackClock;
|
||||||
private readonly fileSize: number;
|
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.
|
* Creates a new playback instance from a buffer.
|
||||||
|
|
|
@ -28,7 +28,7 @@ import { UPDATE_EVENT } from "../stores/AsyncStore";
|
||||||
import { createAudioContext } from "./compat";
|
import { createAudioContext } from "./compat";
|
||||||
import { FixedRollingArray } from "../utils/FixedRollingArray";
|
import { FixedRollingArray } from "../utils/FixedRollingArray";
|
||||||
import { clamp } from "../utils/numbers";
|
import { clamp } from "../utils/numbers";
|
||||||
import mxRecorderWorkletPath from "./RecorderWorklet";
|
import recorderWorkletFactory from "./recorderWorkletFactory";
|
||||||
|
|
||||||
const CHANNELS = 1; // stereo isn't important
|
const CHANNELS = 1; // stereo isn't important
|
||||||
export const SAMPLE_RATE = 48000; // 48khz is what WebRTC uses. 12khz is where we lose quality.
|
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) {
|
if (this.recorderContext.audioWorklet) {
|
||||||
// Set up our worklet. We use this for timing information and waveform analysis: the
|
// 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.
|
// 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.recorderWorklet = new AudioWorkletNode(this.recorderContext, WORKLET_NAME);
|
||||||
this.recorderSource.connect(this.recorderWorklet);
|
this.recorderSource.connect(this.recorderWorklet);
|
||||||
this.recorderWorklet.connect(this.recorderContext.destination);
|
this.recorderWorklet.connect(this.recorderContext.destination);
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -24,8 +24,7 @@ import {
|
||||||
LocalStorageCryptoStore,
|
LocalStorageCryptoStore,
|
||||||
} from "matrix-js-sdk/src/matrix";
|
} from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
// @ts-ignore - `.ts` is needed here to make TS happy
|
import indexeddbWorkerFactory from "../workers/indexeddbWorkerFactory";
|
||||||
import IndexedDBWorker from "../workers/indexeddb.worker.ts";
|
|
||||||
|
|
||||||
const localStorage = window.localStorage;
|
const localStorage = window.localStorage;
|
||||||
|
|
||||||
|
@ -55,7 +54,7 @@ export default function createMatrixClient(opts: ICreateClientOpts): MatrixClien
|
||||||
indexedDB: indexedDB,
|
indexedDB: indexedDB,
|
||||||
dbName: "riot-web-sync",
|
dbName: "riot-web-sync",
|
||||||
localStorage,
|
localStorage,
|
||||||
workerFactory: () => new IndexedDBWorker(),
|
workerFactory: indexeddbWorkerFactory,
|
||||||
});
|
});
|
||||||
} else if (localStorage) {
|
} else if (localStorage) {
|
||||||
storeOpts.store = new MemoryStore({ localStorage });
|
storeOpts.store = new MemoryStore({ localStorage });
|
||||||
|
|
|
@ -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,
|
||||||
|
);
|
||||||
|
}
|
|
@ -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,
|
||||||
|
);
|
||||||
|
}
|
|
@ -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,
|
||||||
|
);
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ import { WorkerManager } from "../src/WorkerManager";
|
||||||
describe("WorkerManager", () => {
|
describe("WorkerManager", () => {
|
||||||
it("should generate consecutive sequence numbers for each call", () => {
|
it("should generate consecutive sequence numbers for each call", () => {
|
||||||
const postMessage = jest.fn();
|
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: "One" });
|
||||||
manager.call({ data: "Two" });
|
manager.call({ data: "Two" });
|
||||||
|
@ -37,7 +37,7 @@ describe("WorkerManager", () => {
|
||||||
it("should support resolving out of order", async () => {
|
it("should support resolving out of order", async () => {
|
||||||
const postMessage = jest.fn();
|
const postMessage = jest.fn();
|
||||||
const worker = { postMessage } as unknown as Worker;
|
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 oneProm = manager.call({ data: "One" });
|
||||||
const twoProm = manager.call({ data: "Two" });
|
const twoProm = manager.call({ data: "Two" });
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"emitDecoratorMetadata": false,
|
"emitDecoratorMetadata": false,
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"module": "commonjs",
|
"module": "es2022",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"target": "es2016",
|
"target": "es2016",
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
|
|
Loading…
Reference in New Issue