kage-baileys 3.0.6 → 3.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/Example/connection.cjs +4 -0
  2. package/README.MD +4726 -48
  3. package/README.md +5941 -0
  4. package/WAProto/WAProto.proto +3395 -415
  5. package/WAProto/compat.cjs +12 -0
  6. package/WAProto/index.d.ts +47104 -19888
  7. package/WAProto/index.js +131979 -57361
  8. package/lib/Addon/http-error.js +43 -0
  9. package/lib/Addon/index.js +32 -0
  10. package/lib/Addon/keyed-db.js +250 -0
  11. package/lib/Addon/link-preview.js +82 -0
  12. package/lib/Defaults/baileys-version.json +3 -0
  13. package/lib/Defaults/connection.js +110 -0
  14. package/lib/Defaults/constants.js +156 -0
  15. package/lib/Defaults/history.js +46 -0
  16. package/lib/Defaults/index.js +230 -0
  17. package/lib/Defaults/media.js +104 -0
  18. package/lib/Defaults/phonenumber-mcc.json +223 -0
  19. package/lib/Defaults/prefix.js +44 -0
  20. package/lib/Extensions/business-advanced.js +382 -0
  21. package/lib/Extensions/business.js +159 -0
  22. package/lib/Extensions/chats-advanced.js +1106 -0
  23. package/lib/Extensions/chats.js +349 -0
  24. package/lib/Extensions/communities-advanced.js +430 -0
  25. package/lib/Extensions/community.js +94 -0
  26. package/lib/Extensions/groups-advanced.js +343 -0
  27. package/lib/Extensions/index.js +30 -0
  28. package/lib/Extensions/messages-recv-advanced.js +1690 -0
  29. package/lib/Extensions/messages-send-advanced.js +622 -0
  30. package/lib/Extensions/messages-send.js +1380 -0
  31. package/lib/Extensions/newsletter-advanced.js +228 -0
  32. package/lib/Extensions/newsletter.js +72 -0
  33. package/lib/Extensions/socket.js +389 -0
  34. package/lib/Modded/message_builder.js +2084 -4
  35. package/lib/Signal/Group/ciphertext-message.js +54 -0
  36. package/lib/Signal/Group/group-session-builder.js +124 -0
  37. package/lib/Signal/Group/group_cipher.js +216 -0
  38. package/lib/Signal/Group/index.js +124 -0
  39. package/lib/Signal/Group/keyhelper.js +108 -0
  40. package/lib/Signal/Group/sender-chain-key.js +83 -0
  41. package/lib/Signal/Group/sender-key-distribution-message.js +157 -0
  42. package/lib/Signal/Group/sender-key-message.js +166 -0
  43. package/lib/Signal/Group/sender-key-name.js +130 -0
  44. package/lib/Signal/Group/sender-key-record.js +113 -0
  45. package/lib/Signal/Group/sender-key-state.js +208 -0
  46. package/lib/Signal/Group/sender-message-key.js +82 -0
  47. package/lib/Signal/libsignal.js +935 -0
  48. package/lib/Signal/lid-mapping.js +545 -1
  49. package/lib/Socket/Client/index.js +60 -0
  50. package/lib/Socket/Client/types.js +51 -0
  51. package/lib/Socket/Client/websocket.js +152 -0
  52. package/lib/Socket/business.js +831 -0
  53. package/lib/Socket/chats.js +2535 -49
  54. package/lib/Socket/communities.js +450 -1
  55. package/lib/Socket/community.js +1022 -0
  56. package/lib/Socket/dugong.js +1 -1
  57. package/lib/Socket/groups.js +747 -0
  58. package/lib/Socket/index.js +60 -2
  59. package/lib/Socket/messages-recv.js +3450 -5
  60. package/lib/Socket/messages-send.js +3123 -0
  61. package/lib/Socket/mex.js +126 -1
  62. package/lib/Socket/newsletter.js +465 -0
  63. package/lib/Socket/socket.js +2217 -1
  64. package/lib/Store/index.js +79 -0
  65. package/lib/Store/make-cache-manager-store.js +186 -0
  66. package/lib/Store/make-in-memory-store.js +878 -0
  67. package/lib/Store/make-ordered-dictionary.js +187 -0
  68. package/lib/Store/object-repository.js +78 -0
  69. package/lib/Types/Auth.js +25 -0
  70. package/lib/Types/Bussines.js +25 -1
  71. package/lib/Types/Call.js +25 -0
  72. package/lib/Types/Chat.js +39 -0
  73. package/lib/Types/Contact.js +25 -0
  74. package/lib/Types/Events.js +25 -0
  75. package/lib/Types/GroupMetadata.js +25 -0
  76. package/lib/Types/Label.js +76 -0
  77. package/lib/Types/LabelAssociation.js +40 -0
  78. package/lib/Types/Message.js +57 -0
  79. package/lib/Types/Mex.js +56 -1
  80. package/lib/Types/MexUpdates.js +46 -0
  81. package/lib/Types/Newsletter.js +56 -0
  82. package/lib/Types/Product.js +25 -0
  83. package/lib/Types/RichType.js +23 -0
  84. package/lib/Types/Signal.js +25 -0
  85. package/lib/Types/Socket.js +25 -0
  86. package/lib/Types/State.js +92 -0
  87. package/lib/Types/USync.js +25 -0
  88. package/lib/Types/index.js +133 -0
  89. package/lib/Utils/auth-utils.js +703 -0
  90. package/lib/Utils/automation-tools.js +51 -16
  91. package/lib/Utils/baileys-event-stream.js +146 -0
  92. package/lib/Utils/browser-utils.js +95 -0
  93. package/lib/Utils/business.js +525 -0
  94. package/lib/Utils/chat-utils.js +1861 -0
  95. package/lib/Utils/companion-reg-client-utils.js +55 -1
  96. package/lib/Utils/crypto.js +355 -0
  97. package/lib/Utils/decode-wa-message.js +709 -0
  98. package/lib/Utils/event-buffer.js +1323 -8
  99. package/lib/Utils/generics.js +945 -1
  100. package/lib/Utils/history.js +266 -0
  101. package/lib/Utils/identity-change-handler.js +62 -1
  102. package/lib/Utils/index.js +114 -0
  103. package/lib/Utils/link-preview.js +179 -0
  104. package/lib/Utils/logger.js +42 -0
  105. package/lib/Utils/lt-hash.js +73 -0
  106. package/lib/Utils/make-mutex.js +104 -0
  107. package/lib/Utils/message-inspector.js +110 -0
  108. package/lib/Utils/message-retry-manager.js +507 -2
  109. package/lib/Utils/messages-media.js +1931 -1
  110. package/lib/Utils/messages.js +3748 -0
  111. package/lib/Utils/noise-handler.js +423 -0
  112. package/lib/Utils/offline-node-processor.js +53 -1
  113. package/lib/Utils/pre-key-manager.js +255 -1
  114. package/lib/Utils/process-message.js +1592 -0
  115. package/lib/Utils/reporting-utils.js +272 -1
  116. package/lib/Utils/rich-message-utils.js +377 -0
  117. package/lib/Utils/rich-messages.js +1 -1
  118. package/lib/Utils/signal.js +437 -0
  119. package/lib/Utils/stanza-ack.js +51 -1
  120. package/lib/Utils/status-refresh.js +37 -0
  121. package/lib/Utils/status-tools.js +4 -2
  122. package/lib/Utils/sync-action-utils.js +63 -1
  123. package/lib/Utils/tc-token-utils.js +185 -1
  124. package/lib/Utils/terminal-banner.js +31 -0
  125. package/lib/Utils/use-multi-file-auth-state.js +271 -0
  126. package/lib/Utils/use-single-file-auth-state.js +108 -0
  127. package/lib/Utils/use-sqlite-auth-state.js +142 -0
  128. package/lib/Utils/validate-connection.js +497 -1
  129. package/lib/Utils/view-once-compat.js +13 -5
  130. package/lib/VoIP/audio-feeder.js +150 -0
  131. package/lib/VoIP/index.js +289 -0
  132. package/lib/VoIP/relay-transport.js +608 -0
  133. package/lib/VoIP/signaling.js +583 -0
  134. package/lib/VoIP/types.js +30 -0
  135. package/lib/VoIP/wasm-engine.js +1261 -2
  136. package/lib/VoIP/worker-bootstrap.js +1090 -2
  137. package/lib/WABinary/constants.js +2805 -0
  138. package/lib/WABinary/decode.js +649 -2
  139. package/lib/WABinary/encode.js +564 -2
  140. package/lib/WABinary/generic-utils.js +401 -0
  141. package/lib/WABinary/index.js +82 -0
  142. package/lib/WABinary/jid-utils.js +290 -0
  143. package/lib/WABinary/types.js +25 -0
  144. package/lib/WAM/BinaryInfo.js +50 -0
  145. package/lib/WAM/constants.js +45747 -0
  146. package/lib/WAM/encode.js +393 -0
  147. package/lib/WAM/index.js +78 -0
  148. package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +135 -0
  149. package/lib/WAUSync/Protocols/USyncContactProtocol.js +110 -0
  150. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +142 -0
  151. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +85 -0
  152. package/lib/WAUSync/Protocols/USyncLIDProtocol.js +69 -0
  153. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +107 -0
  154. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +38 -1
  155. package/lib/WAUSync/Protocols/index.js +83 -0
  156. package/lib/WAUSync/USyncQuery.js +241 -2
  157. package/lib/WAUSync/USyncUser.js +86 -0
  158. package/lib/WAUSync/index.js +78 -0
  159. package/lib/assets/wasm/loader.js +1875 -1
  160. package/lib/assets/wasm/worker-modules.js +11047 -1
  161. package/lib/index.d.ts +126 -0
  162. package/lib/index.js +53 -21
  163. package/lib/index.mjs +437 -0
  164. package/licenses/upstream-MIT.txt +22 -0
  165. package/maintenance/api-coverage.json +1642 -0
  166. package/maintenance/archivos-sha256.json +207 -0
  167. package/maintenance/consumer-validation.log +3 -0
  168. package/maintenance/dependency-audit.json +4 -4
  169. package/maintenance/extension-inventory.json +57 -0
  170. package/maintenance/protocol-update.json +1101 -0
  171. package/maintenance/protocol-wire-audit.json +4 -0
  172. package/maintenance/reference-socket-surface.json +209 -0
  173. package/maintenance/resumen-validacion.json +50 -0
  174. package/maintenance/validation.log +2725 -0
  175. package/maintenance/verification.json +566 -0
  176. package/package.json +107 -9
  177. package/scripts/check-imports.cjs +10 -0
  178. package/scripts/check-package.cjs +40 -0
  179. package/scripts/check-syntax.cjs +1 -1
  180. package/scripts/generate-protobuf.cjs +6 -1
  181. package/scripts/generate-public-types.cjs +9 -0
  182. package/scripts/kage-base64-fix.cjs +45 -0
  183. package/scripts/maintenance.cjs +10 -0
  184. package/test/advanced.test.cjs +24 -0
  185. package/test/base64-fix.test.cjs +49 -0
  186. package/test/maintenance.test.cjs +1 -1
  187. package/test/npm-publication.test.cjs +141 -0
  188. package/test/recepcion-reparada.test.cjs +98 -0
  189. package/test/resilience-binary.test.cjs +69 -0
  190. package/test/resilience-transport.test.cjs +34 -0
  191. package/test/types.test.ts +5 -0
  192. package/test/upgrade.test.cjs +104 -0
  193. package/tsconfig.json +20 -0
  194. package/WAProto/p.html +0 -1
  195. package/lib/KageExtra/Modded/message_builder.js +0 -2330
  196. package/lib/KageExtra/VoIP/audio-feeder.js +0 -136
  197. package/lib/KageExtra/VoIP/index.js +0 -282
  198. package/lib/KageExtra/VoIP/relay-transport.js +0 -559
  199. package/lib/KageExtra/VoIP/signaling.js +0 -603
  200. package/lib/KageExtra/VoIP/types.js +0 -17
  201. package/lib/KageExtra/VoIP/wasm-engine.js +0 -1214
  202. package/lib/KageExtra/VoIP/worker-bootstrap.js +0 -1042
  203. package/lib/KageExtra/assets/wasm/loader.js +0 -5
  204. package/lib/KageExtra/assets/wasm/whatsapp.wasm +0 -0
  205. package/lib/KageExtra/assets/wasm/worker-modules.js +0 -273
  206. package/lib/KageExtra/index.js +0 -3
  207. package/lib/KageExtra/package.json +0 -1
  208. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +0 -53
  209. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +0 -24
  210. package/maintenance/revision-full-check.txt +0 -1097
  211. package/maintenance/revision-library-tests.tap +0 -1088
  212. package/maintenance/revision-protobuf.txt +0 -5
  213. package/maintenance/revision-syntax.txt +0 -5
  214. package/maintenance/schema-coverage.json +0 -23
  215. package/maintenance/schema-merge.json +0 -30
  216. package/maintenance/validation-node20.txt +0 -191
  217. package/maintenance/validation-node22.txt +0 -237
@@ -1,1214 +0,0 @@
1
- var _a;
2
- /**
3
- * WhatsApp VoIP WASM engine.
4
- *
5
- * Loads the WhatsApp Web VoIP WASM stack inside a Node.js `vm.Context`,
6
- * spawns a 20-thread `worker_threads` pool to mirror the browser's pthread
7
- * model, and exposes a callback-based JS bridge. Audio-only (no video).
8
- *
9
- * @author ShellTear
10
- */
11
- import * as vm from "node:vm";
12
- import * as fs from "node:fs";
13
- import * as path from "node:path";
14
- import { randomFillSync } from "node:crypto";
15
- import { Worker } from "node:worker_threads";
16
- import { fileURLToPath } from "node:url";
17
- const __filename = fileURLToPath(require("url").pathToFileURL(__filename).href);
18
- const __dirname = path.dirname(__filename);
19
- const CALL_WASM_AB_PROPS_JSON = process.env.CALL_WASM_AB_PROPS_JSON ?? "";
20
- const PTHREAD_POOL_SIZE = 20;
21
- const VOIP_READY_TIMEOUT_MS = 15_000;
22
- const parseJsonObjectEnv = (raw) => {
23
- if (!raw)
24
- return {};
25
- try {
26
- const parsed = JSON.parse(raw);
27
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed))
28
- return parsed;
29
- }
30
- catch { }
31
- return {};
32
- };
33
- const toByteArray = (input) => {
34
- if (!input)
35
- return new Uint8Array(0);
36
- if (input instanceof Uint8Array)
37
- return input;
38
- if (typeof input === "string")
39
- return new TextEncoder().encode(input);
40
- if (ArrayBuffer.isView(input))
41
- return new Uint8Array(input.buffer, input.byteOffset, input.byteLength);
42
- if (input instanceof ArrayBuffer)
43
- return new Uint8Array(input);
44
- if (typeof input === "object" && typeof input.length === "number") {
45
- const arr = new Uint8Array(input.length);
46
- for (let i = 0; i < input.length; i += 1)
47
- arr[i] = input[i] ?? 0;
48
- return arr;
49
- }
50
- return new Uint8Array(0);
51
- };
52
- const filterWorkerStderr = (chunk) => {
53
- const line = chunk.toString().trim();
54
- if (line && !line.startsWith("voip:") && !line.startsWith("still waiting")) {
55
- process.stderr.write(chunk);
56
- }
57
- };
58
- const resolveWorkerScriptPath = () => {
59
- const compiled = path.join(__dirname, "worker-bootstrap.js");
60
- return fs.existsSync(compiled) ? compiled : path.join(__dirname, "worker-bootstrap.mts");
61
- };
62
- class NodeWorkerMessagePort {
63
- #listeners = new Map();
64
- #worker;
65
- fullyConnected;
66
- name;
67
- workerID = 0;
68
- pthread_ptr = 0;
69
- constructor(worker, name = "WAWebVoipWebWasmWorker") {
70
- this.#worker = worker;
71
- this.name = name;
72
- this.fullyConnected = new Promise((resolve) => {
73
- const loadedHandler = (msg) => {
74
- if (msg && msg.cmd === "loaded") {
75
- this.workerID = msg.workerID ?? 0;
76
- resolve(this);
77
- }
78
- };
79
- this.addMessageListener("cmd", loadedHandler);
80
- });
81
- if (typeof worker.on === "function") {
82
- worker.on("message", (data) => this.#handleMessage(data));
83
- worker.on("error", () => { });
84
- }
85
- else if (typeof worker.addEventListener === "function") {
86
- worker.addEventListener("message", (ev) => this.#handleMessage(ev?.data ?? ev));
87
- }
88
- }
89
- postMessage = (msg, transferList) => {
90
- const out = msg && typeof msg === "object" && msg.cmd && !msg.type ? { ...msg, type: "cmd" } : msg;
91
- this.#worker.postMessage(out, transferList);
92
- };
93
- addMessageListener = (type, handler) => {
94
- let set = this.#listeners.get(type);
95
- if (!set) {
96
- set = new Set();
97
- this.#listeners.set(type, set);
98
- }
99
- set.add(handler);
100
- return handler;
101
- };
102
- removeMessageListener = (type, handler) => this.#listeners.get(type)?.delete(handler) ?? false;
103
- removeAllMessageListeners = (type) => {
104
- if (type)
105
- this.#listeners.get(type)?.clear();
106
- else
107
- this.#listeners.clear();
108
- };
109
- terminate = () => { this.#worker.terminate(); };
110
- close = () => { };
111
- isWrappingVirtualMessagePort = () => false;
112
- getWorker = () => this.#worker;
113
- #handleMessage = (data) => {
114
- if (!data || typeof data !== "object")
115
- return;
116
- if (data.type === "callback" || data.type === "waWasmWorkerCompatibleCallback") {
117
- let callbackName;
118
- let callbackArgs;
119
- if (data.__name) {
120
- callbackName = data.__name;
121
- callbackArgs = {};
122
- for (const key in data) {
123
- if (key !== "type" && key !== "__name" && key !== "prototype" && key !== "args" && !key.startsWith("__")) {
124
- callbackArgs[key] = data[key];
125
- }
126
- }
127
- }
128
- else if (data.name) {
129
- callbackName = data.name;
130
- callbackArgs = data.args ?? {};
131
- }
132
- else if (data.payload?.name) {
133
- callbackName = data.payload.name;
134
- callbackArgs = data.payload.args ?? {};
135
- }
136
- else {
137
- return;
138
- }
139
- if (callbackName === "onSignalingXmpp" &&
140
- (!callbackArgs || Object.keys(callbackArgs).length === 0)) {
141
- callbackArgs = {
142
- peerJid: data.peerJid, callId: data.callId, xmlPayload: data.xmlPayload,
143
- };
144
- }
145
- let listenerData = callbackArgs;
146
- if (!callbackArgs || Object.keys(callbackArgs).length === 0 ||
147
- (Object.keys(callbackArgs).length === 1 && callbackArgs.prototype)) {
148
- listenerData = {};
149
- for (const key in data) {
150
- if (key !== "type" && key !== "__name" && key !== "prototype" && key !== "args" && !key.startsWith("__")) {
151
- listenerData[key] = data[key];
152
- }
153
- }
154
- }
155
- else if (callbackName === "sendDataToRelay") {
156
- listenerData = { ...callbackArgs };
157
- if (data.data !== undefined)
158
- listenerData.data = data.data;
159
- if (data.len !== undefined)
160
- listenerData.len = data.len;
161
- if (data.ip !== undefined)
162
- listenerData.ip = data.ip;
163
- if (data.port !== undefined)
164
- listenerData.port = data.port;
165
- }
166
- else if (callbackName === "onCallEvent") {
167
- listenerData = { ...callbackArgs };
168
- if (data.eventType !== undefined)
169
- listenerData.eventType = data.eventType;
170
- if (data.userData !== undefined)
171
- listenerData.userData = data.userData;
172
- if (data.eventDataJson !== undefined)
173
- listenerData.eventDataJson = data.eventDataJson;
174
- }
175
- WasmEngine.notifyGlobalCallbackListeners(callbackName, listenerData);
176
- return;
177
- }
178
- const dispatch = (key) => {
179
- if (!key)
180
- return;
181
- for (const handler of this.#listeners.get(key) ?? []) {
182
- try {
183
- handler(data);
184
- }
185
- catch { }
186
- }
187
- };
188
- dispatch(data.type);
189
- if (data.cmd !== data.type)
190
- dispatch(data.cmd);
191
- };
192
- }
193
- export class WasmEngine {
194
- static #globalCallbackListeners = new Map();
195
- static #globalCallbacksRegistered = false;
196
- static registerGlobalCallbackListener = (callbackName, handler) => {
197
- const key = `callback:${callbackName}`;
198
- let set = _a.#globalCallbackListeners.get(key);
199
- if (!set) {
200
- set = new Set();
201
- _a.#globalCallbackListeners.set(key, set);
202
- }
203
- set.add(handler);
204
- };
205
- static notifyGlobalCallbackListeners = (callbackName, data) => {
206
- const set = _a.#globalCallbackListeners.get(`callback:${callbackName}`);
207
- if (!set)
208
- return;
209
- for (const handler of set) {
210
- try {
211
- handler(data);
212
- }
213
- catch { }
214
- }
215
- };
216
- #config;
217
- #instance = null;
218
- #initialized = false;
219
- #moduleRegistry = new Map();
220
- #vmContext = null;
221
- #unusedWorkers = [];
222
- #runningWorkers = [];
223
- #pthreads = {};
224
- #nextWorkerID = 1;
225
- #wasmModule = null;
226
- #wasmMemory = null;
227
- #removeRunDependencyCallback = null;
228
- #workersLoadedCount = 0;
229
- #audioPlaybackLoopInterval = null;
230
- #audioPlaybackBuffer = null;
231
- #isPlaybackActive = false;
232
- #voipStackInitialized = false;
233
- #voipStackInitPromise = null;
234
- #voipReadyResolver = null;
235
- #voipReadyPromise = null;
236
- #workerModulesCode = "";
237
- #loaderCode = "";
238
- constructor(config = {}) {
239
- const basePath = config.resourcesPath
240
- ? (path.isAbsolute(config.resourcesPath) ? config.resourcesPath : path.resolve(process.cwd(), config.resourcesPath))
241
- : path.resolve(__dirname, "..");
242
- const wasmPath = config.wasmPath
243
- ? (path.isAbsolute(config.wasmPath) ? config.wasmPath : path.resolve(process.cwd(), config.wasmPath))
244
- : path.join(basePath, "assets", "wasm", "whatsapp.wasm");
245
- this.#config = {
246
- ...config,
247
- wasmPath,
248
- resourcesPath: basePath,
249
- enableLogs: config.enableLogs ?? true,
250
- options: {
251
- heartbeatInterval: 30,
252
- lobbyTimeout: 1,
253
- maxParticipantsScreenShare: 32,
254
- maxGroupSizeLongRingtone: 32,
255
- ...config.options,
256
- },
257
- };
258
- }
259
- initialize = async () => {
260
- if (this.#initialized)
261
- throw new Error("WasmEngine already initialized");
262
- const voipStorageDir = "/tmp/voip";
263
- try {
264
- if (!fs.existsSync(voipStorageDir))
265
- fs.mkdirSync(voipStorageDir, { recursive: true });
266
- }
267
- catch { }
268
- const loaderFile = path.join(this.#config.resourcesPath, "assets", "wasm", "loader.js");
269
- const workerFile = path.join(this.#config.resourcesPath, "assets", "wasm", "worker-modules.js");
270
- if (!this.#config.wasmBinary && !fs.existsSync(this.#config.wasmPath)) {
271
- throw new Error(`WASM file not found: ${this.#config.wasmPath}`);
272
- }
273
- const wasmBuffer = this.#config.wasmBinary
274
- ? Buffer.from(this.#config.wasmBinary)
275
- : fs.readFileSync(this.#config.wasmPath);
276
- const diskWorkerCode = fs.existsSync(workerFile) ? fs.readFileSync(workerFile, "utf8") : "";
277
- this.#workerModulesCode = this.#config.workerModulesCode ?? diskWorkerCode;
278
- const workerBundleHasLoader = typeof this.#workerModulesCode === "string" && /WAWebVoipWebWasmLoader/.test(this.#workerModulesCode);
279
- // Skip the on-disk loader.js if the worker bundle already has a loader —
280
- // the standalone loader.js is older and would clobber the freshly fetched
281
- // bindings inside worker-modules.js.
282
- this.#loaderCode = this.#config.loaderCode ??
283
- (workerBundleHasLoader ? "" : fs.existsSync(loaderFile) ? fs.readFileSync(loaderFile, "utf8") : "");
284
- if (!this.#loaderCode && !this.#workerModulesCode) {
285
- throw new Error("No loader/worker code available to initialize VoIP");
286
- }
287
- const memory = new WebAssembly.Memory({ initial: 256, maximum: 32768, shared: true });
288
- this.#wasmMemory = memory;
289
- this.#wasmModule = await WebAssembly.compile(wasmBuffer);
290
- this.#vmContext = this.#createVMContext(memory);
291
- const runModuleCode = (code) => { if (code)
292
- vm.runInContext(code, this.#vmContext); };
293
- runModuleCode(this.#workerModulesCode);
294
- runModuleCode(this.#loaderCode);
295
- this.#vmContext.WAWebVoipWebWasmWorkerResource = this.#requireModule("WAWebVoipWebWasmWorkerResource");
296
- const loaderModuleNames = [
297
- this.#config.loaderModuleName,
298
- "WAWebVoipWebWasmLoader",
299
- "WAWebVoipWebWasmLoader.worker",
300
- "WAWebVoipWebWasmLoader_ProdLab_internal.worker",
301
- "WAWebVoipWebWasmLoader_ProdLabvideo_internal.worker",
302
- ].filter((v, i, a) => !!v && a.indexOf(v) === i);
303
- let wasmLoader = null;
304
- for (const moduleName of loaderModuleNames) {
305
- const candidate = this.#requireModule(moduleName);
306
- if (typeof candidate === "function") {
307
- wasmLoader = candidate;
308
- break;
309
- }
310
- if (typeof candidate?.default === "function") {
311
- wasmLoader = candidate.default;
312
- break;
313
- }
314
- }
315
- if (typeof wasmLoader !== "function") {
316
- throw new Error(`No compatible WASM loader found. Tried: ${loaderModuleNames.join(", ")}`);
317
- }
318
- if (!_a.#globalCallbacksRegistered)
319
- this.#registerGlobalCallbacks();
320
- await this.#initPThreadPool();
321
- const workersLoadingPromise = this.#loadWasmModuleToAllWorkers();
322
- const readyPromise = wasmLoader({
323
- wasmBinary: wasmBuffer,
324
- wasmMemory: memory,
325
- locateFile: () => this.#config.wasmPath,
326
- onRuntimeInitialized: () => { },
327
- });
328
- const [instance] = await Promise.all([readyPromise, workersLoadingPromise]);
329
- this.#instance = instance;
330
- this.#initialized = true;
331
- };
332
- isInitialized = () => this.#initialized;
333
- destroy = () => {
334
- this.#stopAudioPlaybackLoop();
335
- if (this.#instance && typeof this.#instance.endCall === "function") {
336
- try {
337
- this.#instance.endCall(0, false);
338
- }
339
- catch { }
340
- }
341
- for (const worker of [...this.#runningWorkers, ...this.#unusedWorkers]) {
342
- try {
343
- worker.terminate();
344
- }
345
- catch { }
346
- }
347
- this.#runningWorkers = [];
348
- this.#unusedWorkers = [];
349
- this.#instance = null;
350
- this.#vmContext = null;
351
- this.#moduleRegistry.clear();
352
- this.#wasmModule = null;
353
- this.#wasmMemory = null;
354
- this.#initialized = false;
355
- };
356
- initVoipStack = (selfJid, meUserJid, selfLid) => {
357
- this.#ensureInitialized();
358
- if (this.#voipStackInitialized || this.#voipStackInitPromise)
359
- return;
360
- this.#voipStackInitPromise = new Promise((resolveInit) => {
361
- this.#voipReadyPromise = new Promise((readyResolve) => {
362
- this.#voipReadyResolver = () => {
363
- this.#voipStackInitialized = true;
364
- this.#voipReadyResolver = null;
365
- this.#voipReadyPromise = null;
366
- readyResolve();
367
- };
368
- });
369
- try {
370
- this.#applyDefaultAbProps();
371
- try {
372
- this.#instance.initVoipStack(selfJid, meUserJid, selfLid);
373
- }
374
- catch (modernErr) {
375
- if (modernErr?.name === "BindingError" &&
376
- (String(modernErr?.message ?? "").includes("expected 8 args") ||
377
- String(modernErr?.message ?? "").includes("takes 8"))) {
378
- this.#instance.initVoipStack(selfJid, meUserJid, selfLid, true, 5, 0, 8, 16);
379
- }
380
- else {
381
- throw modernErr;
382
- }
383
- }
384
- Promise.race([
385
- this.#voipReadyPromise,
386
- new Promise((r) => setTimeout(() => {
387
- this.#voipStackInitialized = true;
388
- r();
389
- }, VOIP_READY_TIMEOUT_MS)),
390
- ]).finally(() => {
391
- this.#voipStackInitPromise = null;
392
- resolveInit();
393
- });
394
- }
395
- catch {
396
- this.#voipReadyResolver = null;
397
- this.#voipReadyPromise = null;
398
- this.#voipStackInitPromise = null;
399
- resolveInit();
400
- }
401
- });
402
- };
403
- waitForVoipStackReady = async () => {
404
- if (this.#voipStackInitialized)
405
- return;
406
- if (this.#voipStackInitPromise) {
407
- await this.#voipStackInitPromise;
408
- }
409
- else {
410
- await new Promise((r) => setTimeout(r, 100));
411
- }
412
- };
413
- isVoipStackReady = () => this.#voipStackInitialized;
414
- startCall = (options) => {
415
- this.#ensureInitialized();
416
- const peers = this.#makeStringList(options.peerList ?? [options.peerJid]);
417
- const tcToken = this.#createUint8List(options.extraData);
418
- const isLidCall = options.isLidCall ?? options.peerJid.includes("@lid");
419
- const isFromDialer = options.isFromDialer ?? false;
420
- const peerJid = String(options.peerJid);
421
- try {
422
- try {
423
- return this.#instance.startVoipCall(peerJid, peers, options.callId, options.isVideo, options.peerPn, isLidCall, isFromDialer, tcToken);
424
- }
425
- catch (error) {
426
- if (error?.name !== "BindingError")
427
- throw error;
428
- return this.#instance.startVoipCall(peerJid, peers, options.callId, options.isVideo, options.peerPn, isFromDialer, tcToken);
429
- }
430
- }
431
- finally {
432
- peers?.delete?.();
433
- tcToken?.delete?.();
434
- }
435
- };
436
- endCall = (reason = 0, sendTerminate = true) => {
437
- this.#ensureInitialized();
438
- this.#instance.endCall(reason, sendTerminate);
439
- };
440
- setMute = (muted) => {
441
- this.#ensureInitialized();
442
- return this.#instance.setCallMute(muted);
443
- };
444
- updateNetworkMedium = (networkMedium, networkMtu = 0) => {
445
- this.#ensureInitialized();
446
- this.#instance.updateNetworkMedium?.(networkMedium, networkMtu);
447
- };
448
- handleSignalingOffer = (msg) => {
449
- this.#ensureInitialized();
450
- const tcTokenList = this.#createUint8List(msg.tcToken);
451
- try {
452
- this.#instance.handleIncomingSignalingOffer(msg.payload, String(msg.peerPlatform ?? 0), String(msg.peerAppVersion ?? "0"), String(msg.epochId ?? "0"), String(msg.timestamp ?? "0"), msg.isOffline ?? false, msg.isOfferNotContact ?? false, String(msg.peerJid), tcTokenList);
453
- }
454
- finally {
455
- tcTokenList?.delete?.();
456
- }
457
- };
458
- handleSignalingMessage = (msg) => {
459
- this.#ensureInitialized();
460
- const tcTokenList = this.#createUint8List(msg.tcToken);
461
- try {
462
- this.#instance.handleIncomingSignalingMessage(msg.payload, String(msg.peerPlatform ?? "0"), String(msg.peerAppVersion ?? "0"), String(msg.epochId ?? "0"), String(msg.timestamp ?? "0"), msg.isOffline ?? false, String(msg.peerJid), tcTokenList);
463
- }
464
- finally {
465
- tcTokenList?.delete?.();
466
- }
467
- };
468
- handleSignalingAck = (msg) => {
469
- this.#ensureInitialized();
470
- const options = this.#createUint8List(msg.extraData);
471
- try {
472
- this.#instance.handleIncomingSignalingAck(msg.payload, String(msg.ackError ?? "0"), String(msg.msgType ?? ""), msg.peerJid ?? "", options);
473
- }
474
- finally {
475
- options?.delete?.();
476
- }
477
- };
478
- handleSignalingReceipt = (msg) => {
479
- this.#ensureInitialized();
480
- const tcTokenList = this.#createUint8List(msg.tcToken);
481
- try {
482
- this.#instance.handleIncomingSignalingReceipt?.(msg.payload, msg.peerJid, tcTokenList);
483
- }
484
- finally {
485
- tcTokenList?.delete?.();
486
- }
487
- };
488
- handleOnTransportMessage = (data, ip, port) => {
489
- this.#ensureInitialized();
490
- if (typeof this.#instance.handleOnMessageFromHeap === "function") {
491
- const ptr = this.malloc(data.byteLength);
492
- if (!ptr)
493
- return;
494
- try {
495
- const heapU8 = this.#instance.GROWABLE_HEAP_U8?.() ?? this.#instance.HEAPU8;
496
- if (!heapU8)
497
- return;
498
- heapU8.set(data, ptr);
499
- this.#instance.handleOnMessageFromHeap(ptr, data.byteLength, ip, port);
500
- }
501
- finally {
502
- this.free(ptr);
503
- }
504
- return;
505
- }
506
- if (typeof this.#instance.handleOnMessage !== "function")
507
- return;
508
- const dataList = this.#createUint8List(data);
509
- try {
510
- this.#instance.handleOnMessage(dataList, ip, port);
511
- }
512
- finally {
513
- dataList?.delete?.();
514
- }
515
- };
516
- updateIceRtt = (rttMs, relayIp, relayPort) => {
517
- this.#ensureInitialized();
518
- this.#instance.updateIceRtt?.(rttMs, relayIp, relayPort);
519
- };
520
- sendAudioData = (data, ptr) => {
521
- this.#ensureInitialized();
522
- if (!data || data.length === 0 || !ptr)
523
- return;
524
- if (typeof this.#instance.onAudioDataFromJs !== "function")
525
- return;
526
- try {
527
- const heapF32 = this.#instance.GROWABLE_HEAP_F32?.() ?? this.#instance.HEAPF32;
528
- if (!heapF32)
529
- return;
530
- const index = Math.floor(ptr / 4);
531
- if (index < 0 || index + data.length > heapF32.length)
532
- return;
533
- heapF32.set(data, index);
534
- this.#instance.onAudioDataFromJs(ptr, data.length);
535
- }
536
- catch { }
537
- };
538
- malloc = (size) => {
539
- this.#ensureInitialized();
540
- return this.#instance._malloc(size);
541
- };
542
- free = (ptr) => {
543
- this.#ensureInitialized();
544
- this.#instance._free(ptr);
545
- };
546
- // ─── private ──────────────────────────────────────────────────────────────
547
- #ensureInitialized = () => {
548
- if (!this.#initialized || !this.#instance) {
549
- throw new Error("WasmEngine not initialized. Call initialize() first.");
550
- }
551
- };
552
- #makeStringList = (arr) => {
553
- const list = new this.#instance.StringList();
554
- for (const v of arr)
555
- list.push_back(v);
556
- return list;
557
- };
558
- #createUint8List = (data) => {
559
- if (!this.#instance?.Uint8List)
560
- return null;
561
- const list = new this.#instance.Uint8List();
562
- if (data)
563
- data.forEach((byte) => list.push_back(byte));
564
- return list;
565
- };
566
- #startAudioPlaybackLoop = () => {
567
- if (this.#audioPlaybackLoopInterval)
568
- return;
569
- this.#ensureInitialized();
570
- this.#isPlaybackActive = true;
571
- if (typeof this.#instance.requestAudioDataFromWasmVoip !== "function")
572
- return;
573
- const framesPerChunk = 320;
574
- const bufferSize = framesPerChunk * 4;
575
- try {
576
- const _malloc = this.#instance._malloc ?? this.#instance.malloc;
577
- if (!_malloc)
578
- return;
579
- this.#audioPlaybackBuffer = _malloc(bufferSize);
580
- }
581
- catch {
582
- return;
583
- }
584
- if (!this.#audioPlaybackBuffer || this.#audioPlaybackBuffer <= 0)
585
- return;
586
- this.#audioPlaybackLoopInterval = setInterval(() => {
587
- if (!this.#isPlaybackActive || !this.#instance || !this.#initialized) {
588
- this.#stopAudioPlaybackLoop();
589
- return;
590
- }
591
- try {
592
- this.#instance.requestAudioDataFromWasmVoip(this.#audioPlaybackBuffer, bufferSize);
593
- const heapF32 = this.#instance.GROWABLE_HEAP_F32?.();
594
- if (!heapF32)
595
- return;
596
- const index = Math.floor(this.#audioPlaybackBuffer / 4);
597
- const numFloats = Math.floor(bufferSize / 4);
598
- if (index < 0 || index + numFloats > heapF32.length)
599
- return;
600
- const audioData = new Float32Array(heapF32.buffer, heapF32.byteOffset + index * 4, numFloats);
601
- const hasNonZero = audioData.some((s) => Math.abs(s) > 0.0001);
602
- if (hasNonZero)
603
- this.#config.callbacks?.onAudioPlaybackData?.(audioData);
604
- }
605
- catch { }
606
- }, 16);
607
- };
608
- #stopAudioPlaybackLoop = () => {
609
- this.#isPlaybackActive = false;
610
- if (this.#audioPlaybackLoopInterval) {
611
- clearInterval(this.#audioPlaybackLoopInterval);
612
- this.#audioPlaybackLoopInterval = null;
613
- }
614
- if (this.#audioPlaybackBuffer && this.#audioPlaybackBuffer > 0) {
615
- try {
616
- this.#instance?._free?.(this.#audioPlaybackBuffer);
617
- }
618
- catch { }
619
- this.#audioPlaybackBuffer = null;
620
- }
621
- };
622
- #applyDefaultAbProps = () => {
623
- if (!this.#instance)
624
- return;
625
- const setInt = typeof this.#instance.setABPropInt === "function"
626
- ? (k, v) => { this.#instance.setABPropInt(k, v); }
627
- : null;
628
- const setBool = typeof this.#instance.setABPropBool === "function"
629
- ? (k, v) => { this.#instance.setABPropBool(k, v); }
630
- : null;
631
- const setString = typeof this.#instance.setABPropString === "function"
632
- ? (k, v) => { this.#instance.setABPropString(k, v); }
633
- : null;
634
- if (!setInt && !setBool && !setString)
635
- return;
636
- const opts = this.#config.options ?? {};
637
- const intProps = {
638
- heartbeat_interval_s: opts.heartbeatInterval ?? 30,
639
- lobby_timeout_min: opts.lobbyTimeout ?? 1,
640
- max_num_participants_for_ss: opts.maxParticipantsScreenShare ?? 32,
641
- max_group_size_for_long_ringtone: opts.maxGroupSizeLongRingtone ?? 32,
642
- app_exit_reason_version: 1,
643
- log_level: opts.logLevel ?? 3,
644
- calling_rust_migration_bitmap: 0,
645
- calling_rust_migration_incoming_stanza_bitmap: 0,
646
- default_endpoint_thread_poll_timeout: 0,
647
- aigc_version: 0,
648
- call_admin_version: 0,
649
- vid_stream_pause_resume_jb_reset_threshold_ms: 0,
650
- // Opus: max bandwidth WB (16 kHz). FB (48 kHz) needs native audio device
651
- // hooks not available in this JS-only WASM context.
652
- opus_max_bandwidth: 1103, // OPUS_BANDWIDTH_WIDEBAND
653
- };
654
- const boolProps = {
655
- enable_av_downgrade: false,
656
- enable_new_user_action_stanza_for_raise_hand_sender: false,
657
- enable_webcodec_video_encode: false,
658
- enable_init_bwe_for_group_call: false,
659
- enable_ring_for_gc_on_offer_expire: false,
660
- allow_reporting_call_replayer_id: false,
661
- enable_offer_v2_upgrade: false,
662
- enable_silent_offer: false,
663
- voice_ai_conversation_starter_latency_tracking: false,
664
- enable_waiting_room_logging: false,
665
- attach_transport_rtx: false,
666
- ignore_joinable_terminate_on_expired_offer: false,
667
- enable_passthrough_video_decoder: false,
668
- };
669
- for (const [key, value] of Object.entries(intProps)) {
670
- if (setInt && Number.isFinite(value))
671
- try {
672
- setInt(key, value);
673
- }
674
- catch { }
675
- }
676
- for (const [key, value] of Object.entries(boolProps)) {
677
- if (setBool)
678
- try {
679
- setBool(key, value);
680
- }
681
- catch { }
682
- }
683
- const overrideProps = parseJsonObjectEnv(CALL_WASM_AB_PROPS_JSON);
684
- for (const [key, value] of Object.entries(overrideProps)) {
685
- try {
686
- if (typeof value === "boolean" && setBool)
687
- setBool(key, value);
688
- else if (typeof value === "number" && setInt)
689
- setInt(key, value);
690
- else if (typeof value === "string" && setString)
691
- setString(key, value);
692
- }
693
- catch { }
694
- }
695
- };
696
- #allocateUnusedWorker = () => {
697
- const workerScriptPath = resolveWorkerScriptPath();
698
- if (!fs.existsSync(workerScriptPath))
699
- return;
700
- try {
701
- const worker = new Worker(workerScriptPath, {
702
- stdout: true, stderr: true,
703
- workerData: {
704
- wasmPath: this.#config.wasmPath,
705
- wasmBinary: this.#config.wasmBinary,
706
- workerModulesCode: this.#workerModulesCode,
707
- loaderCode: this.#loaderCode,
708
- loaderModuleName: this.#config.loaderModuleName,
709
- resourcesPath: this.#config.resourcesPath,
710
- enableLogs: this.#config.enableLogs,
711
- },
712
- });
713
- const port = new NodeWorkerMessagePort(worker, "WAWebVoipWebWasmWorker");
714
- worker.stdout?.on("data", () => { }); // suppress noisy worker stdout
715
- worker.stderr?.on("data", filterWorkerStderr);
716
- this.#unusedWorkers.push(port);
717
- }
718
- catch { }
719
- };
720
- #initPThreadPool = async () => {
721
- for (let i = 0; i < PTHREAD_POOL_SIZE; i += 1)
722
- this.#allocateUnusedWorker();
723
- };
724
- #loadWasmModuleToWorker = (worker) => new Promise((resolve) => {
725
- const loadedHandler = (msg) => {
726
- if (msg && msg.cmd === "loaded") {
727
- worker.removeMessageListener("cmd", loadedHandler);
728
- this.#workersLoadedCount += 1;
729
- if (this.#workersLoadedCount >= PTHREAD_POOL_SIZE && this.#removeRunDependencyCallback) {
730
- this.#removeRunDependencyCallback("loading-workers");
731
- }
732
- resolve();
733
- }
734
- };
735
- worker.addMessageListener("cmd", loadedHandler);
736
- worker.workerID = this.#nextWorkerID++;
737
- worker.postMessage({
738
- cmd: "load", type: "cmd",
739
- wasmMemory: this.#wasmMemory,
740
- wasmModule: this.#wasmModule,
741
- workerID: worker.workerID,
742
- handlers: [],
743
- });
744
- });
745
- #loadWasmModuleToAllWorkers = async () => {
746
- this.#workersLoadedCount = 0;
747
- await Promise.all(this.#unusedWorkers.map((w) => this.#loadWasmModuleToWorker(w)));
748
- };
749
- #registerGlobalCallbacks = () => {
750
- const callbacks = this.#config.callbacks ?? {};
751
- _a.registerGlobalCallbackListener("loggingCallback", (data) => {
752
- if (!this.#config.enableLogs)
753
- return;
754
- const level = data?.level;
755
- const msg = data?.message ?? "";
756
- const mapped = level === 1 ? "error" : level === 2 ? "warn" : level === 3 ? "log" : "debug";
757
- callbacks.onLog?.(mapped, msg);
758
- });
759
- if (callbacks.onAudioCaptureInit) {
760
- _a.registerGlobalCallbackListener("initCaptureDriverJS", (data) => {
761
- callbacks.onAudioCaptureInit({
762
- sampleRate: data?.sample_rate ?? data?.sampleRate,
763
- channels: data?.channels,
764
- bitsPerSample: data?.bits_per_sample ?? data?.bitsPerSample,
765
- framesPerChunk: data?.frames_per_chunk ?? data?.framesPerChunk,
766
- });
767
- });
768
- }
769
- _a.registerGlobalCallbackListener("startCaptureJS", () => callbacks.onAudioCaptureStart?.());
770
- _a.registerGlobalCallbackListener("stopCaptureJS", () => callbacks.onAudioCaptureStop?.());
771
- if (callbacks.onAudioPlaybackInit) {
772
- _a.registerGlobalCallbackListener("initPlaybackDriverJS", (data) => {
773
- callbacks.onAudioPlaybackInit({
774
- sampleRate: data?.sample_rate ?? data?.sampleRate,
775
- channels: data?.channels,
776
- bitsPerSample: data?.bits_per_sample ?? data?.bitsPerSample,
777
- framesPerChunk: data?.frames_per_chunk ?? data?.framesPerChunk,
778
- });
779
- });
780
- }
781
- _a.registerGlobalCallbackListener("startPlaybackJS", () => {
782
- callbacks.onAudioPlaybackStart?.();
783
- this.#startAudioPlaybackLoop();
784
- });
785
- _a.registerGlobalCallbackListener("stopPlaybackJS", () => {
786
- this.#stopAudioPlaybackLoop();
787
- callbacks.onAudioPlaybackStop?.();
788
- });
789
- if (callbacks.onSignalingXmpp) {
790
- _a.registerGlobalCallbackListener("onSignalingXmpp", (data) => {
791
- const peerJid = data.peerJid ?? data.args?.peerJid;
792
- const callId = data.callId ?? data.args?.callId;
793
- let xmlPayload = data.xmlPayload ?? data.args?.xmlPayload;
794
- if (Array.isArray(xmlPayload))
795
- xmlPayload = new Uint8Array(xmlPayload);
796
- else if (xmlPayload && typeof xmlPayload === "object" &&
797
- !(xmlPayload instanceof Uint8Array) && !Buffer.isBuffer(xmlPayload)) {
798
- xmlPayload = new Uint8Array(xmlPayload);
799
- }
800
- callbacks.onSignalingXmpp(peerJid, callId, xmlPayload);
801
- });
802
- }
803
- if (callbacks.onCallEvent) {
804
- _a.registerGlobalCallbackListener("onCallEvent", (data) => {
805
- callbacks.onCallEvent(data.eventType, data.eventDataJson);
806
- });
807
- }
808
- if (callbacks.sendDataToRelay) {
809
- _a.registerGlobalCallbackListener("sendDataToRelay", (data) => {
810
- let relayData = data.data ?? data.args?.data;
811
- const ip = data.ip ?? data.args?.ip;
812
- const portNum = data.port ?? data.args?.port;
813
- if (relayData instanceof Uint8Array) { /* ok */ }
814
- else if (Array.isArray(relayData))
815
- relayData = new Uint8Array(relayData);
816
- else if (Buffer.isBuffer(relayData))
817
- relayData = new Uint8Array(relayData);
818
- else if (relayData && typeof relayData === "object" && relayData.buffer) {
819
- relayData = new Uint8Array(relayData.buffer, relayData.byteOffset ?? 0, relayData.byteLength ?? relayData.length);
820
- }
821
- else if (relayData instanceof ArrayBuffer)
822
- relayData = new Uint8Array(relayData);
823
- else
824
- return 0;
825
- if (!ip || !portNum)
826
- return 0;
827
- callbacks.sendDataToRelay(relayData, ip, portNum);
828
- return relayData.byteLength;
829
- });
830
- }
831
- _a.#globalCallbacksRegistered = true;
832
- };
833
- #requireModule = (name) => {
834
- const preDefinedModules = {
835
- Promise,
836
- WAWebVoipWebWasmWorkerResource: {
837
- resourcePath: resolveWorkerScriptPath(),
838
- name: "WAWebVoipWebWasmWorker",
839
- },
840
- WorkerBundleResource: {
841
- createDedicatedWebWorker: (resource) => {
842
- const scriptPath = resource?.resourcePath && fs.existsSync(resource.resourcePath)
843
- ? resource.resourcePath
844
- : resolveWorkerScriptPath();
845
- const worker = new Worker(scriptPath, {
846
- stdout: true, stderr: true,
847
- workerData: {
848
- wasmPath: this.#config.wasmPath,
849
- wasmBinary: this.#config.wasmBinary,
850
- workerModulesCode: this.#workerModulesCode,
851
- loaderCode: this.#loaderCode,
852
- loaderModuleName: this.#config.loaderModuleName,
853
- resourcesPath: this.#config.resourcesPath,
854
- enableLogs: this.#config.enableLogs,
855
- },
856
- });
857
- worker.stdout?.on("data", () => { });
858
- worker.stderr?.on("data", filterWorkerStderr);
859
- return worker;
860
- },
861
- },
862
- WorkerClient: { init: () => { } },
863
- WorkerMessagePort: {
864
- WorkerMessagePort: NodeWorkerMessagePort,
865
- CastWorkerMessagePort: (w) => w,
866
- WorkerSyncedMessagePort: NodeWorkerMessagePort,
867
- },
868
- bx: Object.assign((id) => String(id), { getURL: () => "" }),
869
- HasteSupportData: { handle: () => { } },
870
- ServiceWorkerDynamicModules: { handle: () => { } },
871
- WhatsAppWebServiceWorker: { default: true },
872
- WAWebLogger: { initializeWAWebLogger: () => { } },
873
- WAWebSw: { initHandlers: () => { } },
874
- WAWebWamRuntimeProvider: { setWamRuntime: () => { } },
875
- WAWebWamWorkerInterface: { commit: () => { }, set: () => { } },
876
- ServerJSDefine: { handleDefine: () => { } },
877
- ix: { add: () => { } },
878
- MetaConfigMap: { add: () => { } },
879
- QPLHasteSupportDataStorage: { default: { add: () => { }, get: () => null } },
880
- getFalcoLogPolicy_DO_NOT_USE: { add: () => { } },
881
- gkx: { add: () => { } },
882
- justknobx: { add: () => { } },
883
- qex: { add: () => { } },
884
- };
885
- if (preDefinedModules[name])
886
- return preDefinedModules[name];
887
- const mod = this.#moduleRegistry.get(name);
888
- if (!mod)
889
- return {};
890
- if (mod.exports !== undefined)
891
- return mod.exports;
892
- const requireFn = this.#requireModule;
893
- const normalizeModuleResult = (value) => {
894
- if (value && typeof value === "object" && "exports" in value && Object.keys(value).length === 1) {
895
- return value.exports;
896
- }
897
- return value;
898
- };
899
- const importDefaultFn = (dep) => {
900
- const v = requireFn(dep);
901
- return v && v.__esModule ? v.default : v;
902
- };
903
- const importAllFn = (dep) => {
904
- const v = requireFn(dep);
905
- if (v == null)
906
- return { default: v };
907
- if (v.__esModule)
908
- return v;
909
- if (typeof v !== "object" && typeof v !== "function")
910
- return { default: v };
911
- const ns = {};
912
- for (const key of Object.keys(v))
913
- ns[key] = v[key];
914
- ns.default = v;
915
- return ns;
916
- };
917
- const tryMetro = () => {
918
- const module = { exports: {} };
919
- mod.factory(this.#vmContext ?? globalThis, requireFn, importDefaultFn, importAllFn, null, module, module.exports);
920
- return normalizeModuleResult(module.exports);
921
- };
922
- const tryLegacy = () => {
923
- const exports = {};
924
- const module = { exports };
925
- const resolvedDeps = mod.deps.map((dep) => requireFn(dep));
926
- mod.factory(this.#vmContext ?? globalThis, requireFn, requireFn, requireFn, module, exports, ...resolvedDeps);
927
- return normalizeModuleResult(module.exports);
928
- };
929
- let result = {};
930
- let metroError = null;
931
- try {
932
- result = tryMetro();
933
- }
934
- catch (e) {
935
- metroError = e;
936
- }
937
- if (metroError != null || (result && typeof result === "object" && Object.keys(result).length === 0)) {
938
- try {
939
- const legacyResult = tryLegacy();
940
- if (typeof legacyResult === "function" || (legacyResult && Object.keys(legacyResult).length > 0)) {
941
- result = legacyResult;
942
- }
943
- }
944
- catch { }
945
- }
946
- mod.exports = result;
947
- return result;
948
- };
949
- #createVMContext = (memory) => {
950
- const callbacks = this.#config.callbacks ?? {};
951
- const wasmCallbacks = {
952
- onVoipReady: () => {
953
- this.#voipReadyResolver?.();
954
- callbacks.onVoipReady?.();
955
- },
956
- onSignalingXmpp: (data) => callbacks.onSignalingXmpp?.(data?.peerJid, data?.callId, data?.xmlPayload),
957
- onCallEvent: (data) => callbacks.onCallEvent?.(data?.eventType, data?.eventDataJson),
958
- sendDataToRelay: (data) => callbacks.sendDataToRelay?.(data?.data, data?.ip, data?.port),
959
- loggingCallback: (data) => {
960
- if (!this.#config.enableLogs)
961
- return;
962
- const level = data?.level;
963
- const msg = data?.message ?? "";
964
- const mapped = level === 1 ? "error" : level === 2 ? "warn" : level === 3 ? "log" : "debug";
965
- callbacks.onLog?.(mapped, msg);
966
- },
967
- initCaptureDriverJS: (data) => {
968
- callbacks.onAudioCaptureInit?.({
969
- sampleRate: data?.sample_rate, channels: data?.channels,
970
- bitsPerSample: data?.bits_per_sample, framesPerChunk: data?.frames_per_chunk,
971
- });
972
- return 0;
973
- },
974
- startCaptureJS: () => { callbacks.onAudioCaptureStart?.(); return 0; },
975
- stopCaptureJS: () => { callbacks.onAudioCaptureStop?.(); return 0; },
976
- initPlaybackDriverJS: (data) => {
977
- callbacks.onAudioPlaybackInit?.({
978
- sampleRate: data?.sample_rate, channels: data?.channels,
979
- bitsPerSample: data?.bits_per_sample, framesPerChunk: data?.frames_per_chunk,
980
- });
981
- return 0;
982
- },
983
- startPlaybackJS: () => {
984
- callbacks.onAudioPlaybackStart?.();
985
- this.#startAudioPlaybackLoop();
986
- return 0;
987
- },
988
- stopPlaybackJS: () => {
989
- this.#stopAudioPlaybackLoop();
990
- callbacks.onAudioPlaybackStop?.();
991
- return 0;
992
- },
993
- startVideoCaptureJS: () => 0,
994
- stopVideoCaptureJS: () => 0,
995
- startDesktopCaptureJS: () => 0,
996
- stopDesktopCaptureJS: () => 0,
997
- dataChannelStateCallback: () => 0,
998
- getBrowserAudioProcessingStatus: () => 7,
999
- getBweModelPath: () => null,
1000
- videoFrameConsumed: () => 0,
1001
- cryptoHkdfExtractWithSaltAndExpand: (data) => {
1002
- const key = toByteArray(data?.key_);
1003
- const salt = data?.salt_ ? toByteArray(data.salt_) : new Uint8Array(0);
1004
- const info = toByteArray(data?.info_);
1005
- const length = data?.length ?? 32;
1006
- return callbacks.cryptoHkdf?.(key, salt, info, length) ?? new Uint8Array(length);
1007
- },
1008
- hmacSha256KeyGenerator: (data) => {
1009
- const hmacData = new Uint8Array(data?.data_ ?? []);
1010
- const hmacKey = new Uint8Array(data?.key_ ?? []);
1011
- return callbacks.hmacSha256?.(hmacData, hmacKey) ?? new Uint8Array(32);
1012
- },
1013
- isParticipantKnownContact: () => true,
1014
- getPersistentDirectoryPath: () => {
1015
- const dir = "/tmp/voip";
1016
- try {
1017
- if (!fs.existsSync(dir))
1018
- fs.mkdirSync(dir, { recursive: true });
1019
- }
1020
- catch { }
1021
- return dir;
1022
- },
1023
- };
1024
- const __d = (name, deps, factory) => {
1025
- this.#moduleRegistry.set(name, { deps, factory, exports: undefined });
1026
- };
1027
- const babelHelpers = {
1028
- extends: Object.assign,
1029
- inheritsLoose: (sub, sup) => {
1030
- sub.prototype = Object.create(sup.prototype);
1031
- sub.prototype.constructor = sub;
1032
- sub.__proto__ = sup;
1033
- },
1034
- objectWithoutPropertiesLoose: (source, excluded) => {
1035
- if (source == null)
1036
- return {};
1037
- const target = {};
1038
- for (const key of Object.keys(source)) {
1039
- if (excluded.indexOf(key) >= 0)
1040
- continue;
1041
- target[key] = source[key];
1042
- }
1043
- return target;
1044
- },
1045
- taggedTemplateLiteralLoose: (strings, raw) => {
1046
- if (!raw)
1047
- raw = strings.slice(0);
1048
- strings.raw = raw;
1049
- return strings;
1050
- },
1051
- wrapNativeSuper: (Class) => Class,
1052
- };
1053
- const addRunDependency = (dep) => {
1054
- if (dep === "loading-workers" && this.#workersLoadedCount >= PTHREAD_POOL_SIZE) {
1055
- setImmediate(() => this.#removeRunDependencyCallback?.(dep));
1056
- }
1057
- };
1058
- const removeRunDependency = (_dep) => { };
1059
- this.#removeRunDependencyCallback = removeRunDependency;
1060
- const webCrypto = {
1061
- getRandomValues: (arr) => {
1062
- if (!arr || !ArrayBuffer.isView(arr)) {
1063
- throw new TypeError("crypto.getRandomValues expects a TypedArray");
1064
- }
1065
- const bytes = Buffer.from(arr.buffer, arr.byteOffset, arr.byteLength);
1066
- randomFillSync(bytes);
1067
- return arr;
1068
- },
1069
- };
1070
- const selfObj = {
1071
- __swData: { dynamic_data: { hsdp: {}, dynamic_modules: [] } },
1072
- WhatsAppVoipWasmCallbacks: wasmCallbacks,
1073
- WhatsAppVoipWasmWorkerCompatibleCallbacks: wasmCallbacks,
1074
- crypto: webCrypto,
1075
- };
1076
- selfObj.self = selfObj;
1077
- selfObj.window = selfObj;
1078
- selfObj.globalThis = selfObj;
1079
- if (typeof global !== "undefined") {
1080
- global.WhatsAppVoipWasmCallbacks = wasmCallbacks;
1081
- global.WhatsAppVoipWasmWorkerCompatibleCallbacks = wasmCallbacks;
1082
- }
1083
- const context = vm.createContext({
1084
- self: selfObj, globalThis: selfObj, global: selfObj, window: selfObj,
1085
- console, setTimeout, setInterval, clearTimeout, clearInterval,
1086
- queueMicrotask, performance, babelHelpers, __d,
1087
- require: this.#requireModule,
1088
- addRunDependency, removeRunDependency,
1089
- WebAssembly, SharedArrayBuffer,
1090
- Atomics: this.#createAtomicsWrapper(memory),
1091
- Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array,
1092
- Float32Array, Float64Array, BigInt64Array, BigUint64Array,
1093
- ArrayBuffer, DataView, Error, TypeError, RangeError, Promise,
1094
- Map, Set, WeakMap, WeakSet, Symbol, Object, Array, String, Number,
1095
- Boolean, Math, Date, JSON, RegExp, Function, Proxy, Reflect,
1096
- crypto: webCrypto,
1097
- WhatsAppVoipWasmCallbacks: wasmCallbacks,
1098
- WhatsAppVoipWasmWorkerCompatibleCallbacks: wasmCallbacks,
1099
- navigator: {
1100
- userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
1101
- hardwareConcurrency: 4,
1102
- },
1103
- process: undefined,
1104
- document: { currentScript: null },
1105
- location: { href: "file:///wasm" },
1106
- Worker: class {
1107
- constructor() { }
1108
- postMessage() { }
1109
- terminate() { }
1110
- addEventListener() { }
1111
- },
1112
- fetch: async () => { throw new Error("fetch not supported"); },
1113
- XMLHttpRequest: class {
1114
- open() { }
1115
- send() { }
1116
- setRequestHeader() { }
1117
- },
1118
- Blob: class {
1119
- constructor() { }
1120
- },
1121
- URL: { createObjectURL: () => "blob:fake", revokeObjectURL: () => { } },
1122
- Image: class {
1123
- src = "";
1124
- onload = null;
1125
- onerror = null;
1126
- },
1127
- Audio: class {
1128
- src = "";
1129
- addEventListener() { }
1130
- },
1131
- __NODE_PTHREAD: {
1132
- getUnusedWorker: () => {
1133
- if (this.#unusedWorkers.length === 0)
1134
- return null;
1135
- const worker = this.#unusedWorkers.pop();
1136
- this.#runningWorkers.push(worker);
1137
- return worker;
1138
- },
1139
- returnWorkerToPool: (worker) => {
1140
- const idx = this.#runningWorkers.indexOf(worker);
1141
- if (idx >= 0) {
1142
- this.#runningWorkers.splice(idx, 1);
1143
- this.#unusedWorkers.push(worker);
1144
- }
1145
- },
1146
- spawnThread: (params) => {
1147
- const worker = this.#unusedWorkers.pop();
1148
- if (!worker)
1149
- return 6;
1150
- this.#runningWorkers.push(worker);
1151
- this.#pthreads[params.pthread_ptr] = worker;
1152
- worker.pthread_ptr = params.pthread_ptr;
1153
- const pthreadTable = this.#instance?.PThread?.pthreads;
1154
- if (pthreadTable)
1155
- pthreadTable[params.pthread_ptr] = worker;
1156
- worker.postMessage({
1157
- cmd: "run",
1158
- start_routine: params.startRoutine,
1159
- arg: params.arg,
1160
- pthread_ptr: params.pthread_ptr,
1161
- });
1162
- return 0;
1163
- },
1164
- unusedWorkersCount: () => this.#unusedWorkers.length,
1165
- runningWorkersCount: () => this.#runningWorkers.length,
1166
- },
1167
- __IS_NODE_PTHREAD_ENV: true,
1168
- });
1169
- context.self = context;
1170
- context.globalThis = context;
1171
- context.global = context;
1172
- context.window = context;
1173
- return context;
1174
- };
1175
- #createAtomicsWrapper = (_memory) => {
1176
- const atomicsWrapper = {
1177
- add: Atomics.add.bind(Atomics),
1178
- and: Atomics.and.bind(Atomics),
1179
- compareExchange: Atomics.compareExchange.bind(Atomics),
1180
- exchange: Atomics.exchange.bind(Atomics),
1181
- isLockFree: Atomics.isLockFree.bind(Atomics),
1182
- load: Atomics.load.bind(Atomics),
1183
- or: Atomics.or.bind(Atomics),
1184
- store: Atomics.store.bind(Atomics),
1185
- sub: Atomics.sub.bind(Atomics),
1186
- xor: Atomics.xor.bind(Atomics),
1187
- notify: (typedArray, index, count) => {
1188
- try {
1189
- return Atomics.notify(typedArray, index, count);
1190
- }
1191
- catch (e) {
1192
- if (e?.message?.includes("futex_wake") || e?.message?.includes("main_browser_thread"))
1193
- return 0;
1194
- throw e;
1195
- }
1196
- },
1197
- waitAsync: Atomics.waitAsync
1198
- ? Atomics.waitAsync.bind(Atomics)
1199
- : () => ({ async: true, value: Promise.resolve("ok") }),
1200
- wait: (typedArray, index, value, timeout) => {
1201
- const currentValue = Atomics.load(typedArray, index);
1202
- if (currentValue !== value)
1203
- return "not-equal";
1204
- if (timeout !== undefined && timeout <= 0)
1205
- return "timed-out";
1206
- return "timed-out";
1207
- },
1208
- [Symbol.toStringTag]: "Atomics",
1209
- };
1210
- return atomicsWrapper;
1211
- };
1212
- }
1213
- _a = WasmEngine;
1214
- export default WasmEngine;