libzapitu 1.0.0-alpha.25 → 1.0.0-alpha.26
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.
- package/lib/worker/child.js +40 -3
- package/lib/worker/proxy.js +70 -5
- package/package.json +1 -1
package/lib/worker/child.js
CHANGED
|
@@ -77,8 +77,8 @@ function proxyCallback(socketId, key, log, ...args) {
|
|
|
77
77
|
// ---------------------------------------------------------------------------
|
|
78
78
|
/**
|
|
79
79
|
* Recursively clone a value for postMessage, replacing non-cloneable types
|
|
80
|
-
* (Error, Function) with plain serializable representations
|
|
81
|
-
* protobufjs message instances to JSON.
|
|
80
|
+
* (Error, Function) with plain serializable representations, preserving
|
|
81
|
+
* built-in value objects, and converting protobufjs message instances to JSON.
|
|
82
82
|
*
|
|
83
83
|
* Protobuf messages (e.g. proto.Message, proto.WebMessageInfo) carry a
|
|
84
84
|
* toJSON() method that serializes byte fields as base64 strings and 64-bit
|
|
@@ -90,11 +90,42 @@ function proxyCallback(socketId, key, log, ...args) {
|
|
|
90
90
|
*/
|
|
91
91
|
function serializeForPostMessage(value, seen = new WeakSet()) {
|
|
92
92
|
if (value instanceof Error) {
|
|
93
|
+
// Boom carries critical metadata (statusCode, output, data, isServer).
|
|
94
|
+
// Preserve it so the parent can reconstruct a real Boom instance.
|
|
95
|
+
if (value.isBoom) {
|
|
96
|
+
return {
|
|
97
|
+
__error__: true,
|
|
98
|
+
__boom__: true,
|
|
99
|
+
message: value.message,
|
|
100
|
+
name: value.name,
|
|
101
|
+
stack: value.stack,
|
|
102
|
+
data: value.data,
|
|
103
|
+
output: value.output,
|
|
104
|
+
isServer: value.isServer
|
|
105
|
+
};
|
|
106
|
+
}
|
|
93
107
|
return { __error__: true, message: value.message, name: value.name, stack: value.stack };
|
|
94
108
|
}
|
|
95
109
|
if (typeof value === 'function') {
|
|
96
110
|
return '__fn__';
|
|
97
111
|
}
|
|
112
|
+
// Preserve built-in value objects that structured clone handles, but tag
|
|
113
|
+
// them so the parent can reconstruct the exact same runtime type.
|
|
114
|
+
if (value instanceof Date) {
|
|
115
|
+
return { __date__: true, value: value.toISOString() };
|
|
116
|
+
}
|
|
117
|
+
if (value instanceof RegExp) {
|
|
118
|
+
return { __regexp__: true, source: value.source, flags: value.flags };
|
|
119
|
+
}
|
|
120
|
+
if (value instanceof URL) {
|
|
121
|
+
return { __url__: true, href: value.href };
|
|
122
|
+
}
|
|
123
|
+
if (value instanceof Map) {
|
|
124
|
+
return { __map__: true, entries: serializeForPostMessage(Array.from(value.entries()), seen) };
|
|
125
|
+
}
|
|
126
|
+
if (value instanceof Set) {
|
|
127
|
+
return { __set__: true, entries: serializeForPostMessage(Array.from(value.values()), seen) };
|
|
128
|
+
}
|
|
98
129
|
if (value !== null && typeof value === 'object') {
|
|
99
130
|
if (seen.has(value))
|
|
100
131
|
return '[Circular]';
|
|
@@ -214,6 +245,8 @@ function createSocket(socketId, rawConfig) {
|
|
|
214
245
|
log.info('socket created successfully');
|
|
215
246
|
// Send user and authState to the parent when they become available.
|
|
216
247
|
// These are needed for wsocket.user and wsocket.authState on the proxy side.
|
|
248
|
+
// authState.keys contains forwarding functions, so we must serialize the
|
|
249
|
+
// info before postMessage or the whole message is dropped.
|
|
217
250
|
const sendSocketInfo = () => {
|
|
218
251
|
try {
|
|
219
252
|
const info = {};
|
|
@@ -222,7 +255,11 @@ function createSocket(socketId, rawConfig) {
|
|
|
222
255
|
if (sock.authState)
|
|
223
256
|
info.authState = sock.authState;
|
|
224
257
|
if (Object.keys(info).length > 0) {
|
|
225
|
-
worker_threads_1.parentPort.postMessage({
|
|
258
|
+
worker_threads_1.parentPort.postMessage({
|
|
259
|
+
type: 'socket-info',
|
|
260
|
+
socketId,
|
|
261
|
+
info: serializeForPostMessage(info)
|
|
262
|
+
});
|
|
226
263
|
}
|
|
227
264
|
}
|
|
228
265
|
catch (_) {
|
package/lib/worker/proxy.js
CHANGED
|
@@ -36,6 +36,7 @@ const stream_1 = require("stream");
|
|
|
36
36
|
const util_1 = require("util");
|
|
37
37
|
const os_2 = require("os");
|
|
38
38
|
const long_1 = __importDefault(require("long"));
|
|
39
|
+
const boom_1 = require("@hapi/boom");
|
|
39
40
|
const WAProto_1 = require("../../WAProto");
|
|
40
41
|
const pipelineAsync = (0, util_1.promisify)(stream_1.pipeline);
|
|
41
42
|
// ---------------------------------------------------------------------------
|
|
@@ -254,6 +255,7 @@ const PROTOBUF_TYPE_REGISTRY = buildProtobufTypeRegistry(WAProto_1.proto);
|
|
|
254
255
|
* to direct mode (base64 strings for bytes, strings for 64-bit integers).
|
|
255
256
|
*/
|
|
256
257
|
function revivePostMessage(value) {
|
|
258
|
+
var _a;
|
|
257
259
|
// After structured clone, Buffer subclasses become plain Uint8Arrays.
|
|
258
260
|
// Restore them to Buffer so downstream code gets the same type as in
|
|
259
261
|
// direct mode for non-protobuf binary fields.
|
|
@@ -262,11 +264,42 @@ function revivePostMessage(value) {
|
|
|
262
264
|
}
|
|
263
265
|
if (value !== null && typeof value === 'object') {
|
|
264
266
|
if (value.__error__) {
|
|
267
|
+
// Boom errors carry status codes, payloads, and extra data. Rebuild
|
|
268
|
+
// a real Boom instance so callers can inspect err.output.statusCode.
|
|
269
|
+
if (value.__boom__) {
|
|
270
|
+
const boom = new boom_1.Boom(value.message, {
|
|
271
|
+
statusCode: (_a = value.output) === null || _a === void 0 ? void 0 : _a.statusCode,
|
|
272
|
+
data: value.data
|
|
273
|
+
});
|
|
274
|
+
// Restore the exact output payload/headers from the worker so the
|
|
275
|
+
// status code and error name match direct mode.
|
|
276
|
+
if (value.output) {
|
|
277
|
+
Object.assign(boom.output, value.output);
|
|
278
|
+
}
|
|
279
|
+
boom.stack = value.stack || boom.stack;
|
|
280
|
+
return boom;
|
|
281
|
+
}
|
|
265
282
|
const err = new Error(value.message);
|
|
266
283
|
err.name = value.name;
|
|
267
284
|
err.stack = value.stack;
|
|
268
285
|
return err;
|
|
269
286
|
}
|
|
287
|
+
// Revive built-in value objects tagged by the child.
|
|
288
|
+
if (value.__date__) {
|
|
289
|
+
return new Date(value.value);
|
|
290
|
+
}
|
|
291
|
+
if (value.__regexp__) {
|
|
292
|
+
return new RegExp(value.source, value.flags);
|
|
293
|
+
}
|
|
294
|
+
if (value.__url__) {
|
|
295
|
+
return new URL(value.href);
|
|
296
|
+
}
|
|
297
|
+
if (value.__map__) {
|
|
298
|
+
return new Map(revivePostMessage(value.entries));
|
|
299
|
+
}
|
|
300
|
+
if (value.__set__) {
|
|
301
|
+
return new Set(revivePostMessage(value.entries));
|
|
302
|
+
}
|
|
270
303
|
// Revive protobuf messages tagged by the child. fromObject() will
|
|
271
304
|
// recursively recreate nested protobuf instances and convert base64
|
|
272
305
|
// strings back into Buffer instances.
|
|
@@ -279,7 +312,7 @@ function revivePostMessage(value) {
|
|
|
279
312
|
try {
|
|
280
313
|
return type.fromObject(copy);
|
|
281
314
|
}
|
|
282
|
-
catch (
|
|
315
|
+
catch (_b) {
|
|
283
316
|
// Fall back to the plain JSON object if fromObject fails;
|
|
284
317
|
// downstream code will see base64 strings instead of Buffers.
|
|
285
318
|
}
|
|
@@ -292,7 +325,7 @@ function revivePostMessage(value) {
|
|
|
292
325
|
return new long_1.default(value.low, value.high, value.unsigned);
|
|
293
326
|
}
|
|
294
327
|
if (Array.isArray(value)) {
|
|
295
|
-
// Arrays: recurse to revive any Error sentinels / Longs / Uint8Arrays / protobuf messages inside
|
|
328
|
+
// Arrays: recurse to revive any Error sentinels / Longs / Uint8Arrays / protobuf messages / built-ins inside
|
|
296
329
|
let changed = false;
|
|
297
330
|
const result = value.map(v => {
|
|
298
331
|
const revived = revivePostMessage(v);
|
|
@@ -303,7 +336,7 @@ function revivePostMessage(value) {
|
|
|
303
336
|
return changed ? result : value;
|
|
304
337
|
}
|
|
305
338
|
// Plain objects: only recurse if they might contain __error__ sentinels,
|
|
306
|
-
// Long-like objects, Uint8Arrays, or
|
|
339
|
+
// Long-like objects, Uint8Arrays, protobuf markers, or built-in tags.
|
|
307
340
|
if (value.constructor === Object || value.constructor === undefined) {
|
|
308
341
|
let changed = false;
|
|
309
342
|
const result = {};
|
|
@@ -515,7 +548,12 @@ async function handleCallbackCall(slot, socketId, msg) {
|
|
|
515
548
|
try {
|
|
516
549
|
log === null || log === void 0 ? void 0 : log.debug({ keystoreMethod: method, argCount: args.length }, 'invoking keystore method');
|
|
517
550
|
const result = await keystore[method](...args);
|
|
518
|
-
slot.worker.postMessage({
|
|
551
|
+
slot.worker.postMessage({
|
|
552
|
+
type: 'callback-result',
|
|
553
|
+
socketId,
|
|
554
|
+
id,
|
|
555
|
+
result: deepStripFunctions(result)
|
|
556
|
+
});
|
|
519
557
|
}
|
|
520
558
|
catch (err) {
|
|
521
559
|
log === null || log === void 0 ? void 0 : log.error({ err, keystoreMethod: method }, 'keystore method threw error');
|
|
@@ -543,7 +581,12 @@ async function handleCallbackCall(slot, socketId, msg) {
|
|
|
543
581
|
try {
|
|
544
582
|
log === null || log === void 0 ? void 0 : log.debug({ callbackKey: key, argCount: args.length }, 'invoking proxied callback');
|
|
545
583
|
const result = await fn(...args);
|
|
546
|
-
slot.worker.postMessage({
|
|
584
|
+
slot.worker.postMessage({
|
|
585
|
+
type: 'callback-result',
|
|
586
|
+
socketId,
|
|
587
|
+
id,
|
|
588
|
+
result: deepStripFunctions(result)
|
|
589
|
+
});
|
|
547
590
|
}
|
|
548
591
|
catch (err) {
|
|
549
592
|
log === null || log === void 0 ? void 0 : log.error({ err, callbackKey: key }, 'proxied callback threw error');
|
|
@@ -616,8 +659,30 @@ async function drainPool() {
|
|
|
616
659
|
* Recursively clone a value, replacing all functions with the sentinel
|
|
617
660
|
* string '__proxy_fn__'. This ensures the config can be sent via
|
|
618
661
|
* postMessage (structured clone).
|
|
662
|
+
*
|
|
663
|
+
* Built-in value objects (Date, RegExp, URL, Map, Set) are preserved in
|
|
664
|
+
* their serializable tagged form so they survive the boundary instead of
|
|
665
|
+
* being reduced to empty objects by Object.keys().
|
|
619
666
|
*/
|
|
620
667
|
function deepStripFunctions(value, seen = new WeakSet()) {
|
|
668
|
+
if (typeof value === 'function') {
|
|
669
|
+
return '__proxy_fn__';
|
|
670
|
+
}
|
|
671
|
+
if (value instanceof Date) {
|
|
672
|
+
return { __date__: true, value: value.toISOString() };
|
|
673
|
+
}
|
|
674
|
+
if (value instanceof RegExp) {
|
|
675
|
+
return { __regexp__: true, source: value.source, flags: value.flags };
|
|
676
|
+
}
|
|
677
|
+
if (value instanceof URL) {
|
|
678
|
+
return { __url__: true, href: value.href };
|
|
679
|
+
}
|
|
680
|
+
if (value instanceof Map) {
|
|
681
|
+
return { __map__: true, entries: deepStripFunctions(Array.from(value.entries()), seen) };
|
|
682
|
+
}
|
|
683
|
+
if (value instanceof Set) {
|
|
684
|
+
return { __set__: true, entries: deepStripFunctions(Array.from(value.values()), seen) };
|
|
685
|
+
}
|
|
621
686
|
if (typeof value === 'function') {
|
|
622
687
|
return '__proxy_fn__';
|
|
623
688
|
}
|