Skip to content

Commit 03f97d4

Browse files
committed
feat: move arrpc server into a worker thread
1 parent 5a72491 commit 03f97d4

File tree

6 files changed

+154
-25
lines changed

6 files changed

+154
-25
lines changed

Diff for: package.json

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"electron": "^33.2.1",
4141
"electron-builder": "^25.1.8",
4242
"esbuild": "^0.24.0",
43+
"esbuild-plugin-inline-import": "^1.1.0",
4344
"eslint": "^9.16.0",
4445
"eslint-import-resolver-alias": "^1.1.2",
4546
"eslint-plugin-path-alias": "^2.1.0",

Diff for: pnpm-lock.yaml

+17-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: scripts/build/build.mts

+20-2
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
* Copyright (c) 2023 Vendicated and Vencord contributors
55
*/
66

7-
import { BuildContext, BuildOptions, context } from "esbuild";
7+
import { build, BuildContext, BuildOptions, context } from "esbuild";
88
import { copyFile } from "fs/promises";
99

10+
import inlineImportPlugin from "esbuild-plugin-inline-import";
1011
import vencordDep from "./vencordDep.mjs";
1112

1213
const isDev = process.argv.includes("--dev");
@@ -22,8 +23,25 @@ const NodeCommonOpts: BuildOptions = {
2223
...CommonOpts,
2324
format: "cjs",
2425
platform: "node",
25-
external: ["electron"],
26+
external: ["electron", "inline:./arrpcWorker.ts"],
2627
target: ["esnext"],
28+
plugins: [
29+
inlineImportPlugin({
30+
transform: async (_, args) => {
31+
const { outputFiles } = await build({
32+
entryPoints: [args.path],
33+
bundle: true,
34+
write: false,
35+
format: "cjs",
36+
platform: "node",
37+
target: ["esnext"]
38+
});
39+
40+
const { contents } = outputFiles[0];
41+
return Buffer.from(contents).toString();
42+
}
43+
})
44+
],
2745
define: {
2846
IS_DEV: JSON.stringify(isDev)
2947
}

Diff for: src/main/arrpc.ts

+48-14
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,65 @@
44
* Copyright (c) 2023 Vendicated and Vencord contributors
55
*/
66

7-
import Server from "arrpc";
87
import { IpcEvents } from "shared/IpcEvents";
8+
import { MessageChannel, Worker } from "worker_threads";
9+
const { port1: hostPort, port2: workerPort } = new MessageChannel();
10+
11+
// @ts-ignore: ts error looking for type defintions
12+
import arrpcWorkerScript from "inline:./arrpcWorker.ts";
913

1014
import { mainWin } from "./mainWindow";
1115
import { Settings } from "./settings";
16+
import { ArrpcEvent, ArrpcHostEvent } from "./utils/arrpcWorkerTypes";
1217

13-
let server: any;
18+
let worker: any;
1419

1520
const inviteCodeRegex = /^(\w|-)+$/;
1621

1722
export async function initArRPC() {
18-
if (server || !Settings.store.arRPC) return;
23+
if (worker || !Settings.store.arRPC) return;
1924

2025
try {
21-
server = await new Server();
22-
server.on("activity", (data: any) => mainWin.webContents.send(IpcEvents.ARRPC_ACTIVITY, JSON.stringify(data)));
23-
server.on("invite", (invite: string, callback: (valid: boolean) => void) => {
24-
invite = String(invite);
25-
if (!inviteCodeRegex.test(invite)) return callback(false);
26-
27-
mainWin.webContents
28-
// Safety: Result of JSON.stringify should always be safe to equal
29-
// Also, just to be super super safe, invite is regex validated above
30-
.executeJavaScript(`Vesktop.openInviteModal(${JSON.stringify(invite)})`)
31-
.then(callback);
26+
worker = new Worker(arrpcWorkerScript, {
27+
workerData: {
28+
workerPort
29+
},
30+
transferList: [workerPort],
31+
eval: true
32+
});
33+
hostPort.on("message", (e: ArrpcEvent) => {
34+
switch (e.eventType) {
35+
case IpcEvents.ARRPC_ACTIVITY: {
36+
mainWin.webContents.send(IpcEvents.ARRPC_ACTIVITY, e.data);
37+
break;
38+
}
39+
case "invite": {
40+
const invite = String(e.data);
41+
42+
if (!inviteCodeRegex.test(invite)) {
43+
const hostEvent: ArrpcHostEvent = {
44+
eventType: "ack-invite",
45+
data: false,
46+
inviteId: e.inviteId
47+
};
48+
return hostPort.postMessage(hostEvent);
49+
}
50+
51+
mainWin.webContents
52+
// Safety: Result of JSON.stringify should always be safe to equal
53+
// Also, just to be super super safe, invite is regex validated above
54+
.executeJavaScript(`Vesktop.openInviteModal(${JSON.stringify(invite)})`)
55+
.then(() => {
56+
const hostEvent: ArrpcHostEvent = {
57+
eventType: "ack-invite",
58+
data: true,
59+
inviteId: e.inviteId
60+
};
61+
hostPort.postMessage(hostEvent);
62+
});
63+
break;
64+
}
65+
}
3266
});
3367
} catch (e) {
3468
console.error("Failed to start arRPC server", e);

Diff for: src/main/arrpcWorker.ts

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* SPDX-License-Identifier: GPL-3.0
3+
* Vesktop, a desktop app aiming to give you a snappier Discord Experience
4+
* Copyright (c) 2023 Vendicated and Vencord contributors
5+
*/
6+
7+
import Server from "arrpc";
8+
import { IpcEvents } from "shared/IpcEvents";
9+
import { MessagePort, workerData } from "worker_threads";
10+
11+
import { ArrpcEvent, ArrpcHostEvent } from "./utils/arrpcWorkerTypes";
12+
13+
let server: any;
14+
15+
type InviteCallback = (valid: boolean) => void;
16+
17+
let inviteCallbacks: Array<InviteCallback> = [];
18+
19+
(async function () {
20+
const { workerPort }: { workerPort: MessagePort } = workerData;
21+
server = await new Server();
22+
server.on("activity", (data: any) => {
23+
const event: ArrpcEvent = {
24+
eventType: IpcEvents.ARRPC_ACTIVITY,
25+
data: JSON.stringify(data)
26+
};
27+
workerPort.postMessage(event);
28+
});
29+
server.on("invite", (invite: string, callback: InviteCallback) => {
30+
const event: ArrpcEvent = {
31+
eventType: "invite",
32+
data: invite,
33+
inviteId: inviteCallbacks.push(callback) - 1
34+
};
35+
workerPort.postMessage(event);
36+
});
37+
38+
workerPort.on("message", (e: ArrpcHostEvent) => {
39+
inviteCallbacks[e.inviteId](e.data);
40+
inviteCallbacks = [...inviteCallbacks.slice(0, e.inviteId), ...inviteCallbacks.slice(e.inviteId + 1)];
41+
});
42+
})();

Diff for: src/main/utils/arrpcWorkerTypes.ts

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* SPDX-License-Identifier: GPL-3.0
3+
* Vesktop, a desktop app aiming to give you a snappier Discord Experience
4+
* Copyright (c) 2023 Vendicated and Vencord contributors
5+
*/
6+
7+
import { IpcEvents } from "shared/IpcEvents";
8+
9+
export type ArrpcEvent = ArrpcActivityEvent | ArrpcInviteEvent;
10+
11+
export interface ArrpcActivityEvent {
12+
eventType: IpcEvents.ARRPC_ACTIVITY;
13+
data: string;
14+
}
15+
16+
export interface ArrpcInviteEvent {
17+
eventType: "invite";
18+
data: string;
19+
inviteId: number;
20+
}
21+
22+
export interface ArrpcHostEvent {
23+
eventType: "ack-invite";
24+
inviteId: number;
25+
data: boolean;
26+
}

0 commit comments

Comments
 (0)