tinybase 9.4.0-beta.0 → 9.4.0-beta.2
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/@types/persisters/index.d.ts +4 -0
- package/@types/persisters/persister-durable-object-sql-storage/index.d.ts +9 -2
- package/@types/persisters/persister-durable-object-sql-storage/with-schemas/index.d.ts +9 -2
- package/@types/persisters/with-schemas/index.d.ts +4 -0
- package/@types/queries/index.d.ts +145 -7
- package/@types/queries/with-schemas/index.d.ts +157 -7
- package/@types/synchronizers/synchronizer-ws-client/index.d.ts +7 -3
- package/@types/synchronizers/synchronizer-ws-client/with-schemas/index.d.ts +7 -3
- package/@types/synchronizers/synchronizer-ws-server/index.d.ts +9 -3
- package/@types/synchronizers/synchronizer-ws-server/with-schemas/index.d.ts +9 -3
- package/@types/synchronizers/synchronizer-ws-server-simple/index.d.ts +6 -3
- package/@types/synchronizers/synchronizer-ws-server-simple/with-schemas/index.d.ts +6 -3
- package/index.js +315 -22
- package/min/index.js +1 -1
- package/min/index.js.gz +0 -0
- package/min/omni/index.js +1 -1
- package/min/omni/index.js.gz +0 -0
- package/min/omni/with-schemas/index.js +1 -1
- package/min/omni/with-schemas/index.js.gz +0 -0
- package/min/persisters/index.js +1 -1
- package/min/persisters/index.js.gz +0 -0
- package/min/persisters/persister-automerge/index.js +1 -1
- package/min/persisters/persister-automerge/index.js.gz +0 -0
- package/min/persisters/persister-automerge/with-schemas/index.js +1 -1
- package/min/persisters/persister-automerge/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-browser/index.js +1 -1
- package/min/persisters/persister-browser/index.js.gz +0 -0
- package/min/persisters/persister-browser/with-schemas/index.js +1 -1
- package/min/persisters/persister-browser/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-cr-sqlite-wasm/index.js +1 -1
- package/min/persisters/persister-cr-sqlite-wasm/index.js.gz +0 -0
- package/min/persisters/persister-cr-sqlite-wasm/with-schemas/index.js +1 -1
- package/min/persisters/persister-cr-sqlite-wasm/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-durable-object-sql-storage/index.js +1 -1
- package/min/persisters/persister-durable-object-sql-storage/index.js.gz +0 -0
- package/min/persisters/persister-durable-object-sql-storage/with-schemas/index.js +1 -1
- package/min/persisters/persister-durable-object-sql-storage/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-durable-object-storage/index.js +1 -1
- package/min/persisters/persister-durable-object-storage/index.js.gz +0 -0
- package/min/persisters/persister-durable-object-storage/with-schemas/index.js +1 -1
- package/min/persisters/persister-durable-object-storage/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-electric-sql/index.js +1 -1
- package/min/persisters/persister-electric-sql/index.js.gz +0 -0
- package/min/persisters/persister-electric-sql/with-schemas/index.js +1 -1
- package/min/persisters/persister-electric-sql/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-expo-sqlite/index.js +1 -1
- package/min/persisters/persister-expo-sqlite/index.js.gz +0 -0
- package/min/persisters/persister-expo-sqlite/with-schemas/index.js +1 -1
- package/min/persisters/persister-expo-sqlite/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-file/index.js +1 -1
- package/min/persisters/persister-file/index.js.gz +0 -0
- package/min/persisters/persister-file/with-schemas/index.js +1 -1
- package/min/persisters/persister-file/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-indexed-db/index.js +1 -1
- package/min/persisters/persister-indexed-db/index.js.gz +0 -0
- package/min/persisters/persister-indexed-db/with-schemas/index.js +1 -1
- package/min/persisters/persister-indexed-db/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-libsql/index.js +1 -1
- package/min/persisters/persister-libsql/index.js.gz +0 -0
- package/min/persisters/persister-libsql/with-schemas/index.js +1 -1
- package/min/persisters/persister-libsql/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-partykit-client/index.js +1 -1
- package/min/persisters/persister-partykit-client/index.js.gz +0 -0
- package/min/persisters/persister-partykit-client/with-schemas/index.js +1 -1
- package/min/persisters/persister-partykit-client/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-pglite/index.js +1 -1
- package/min/persisters/persister-pglite/index.js.gz +0 -0
- package/min/persisters/persister-pglite/with-schemas/index.js +1 -1
- package/min/persisters/persister-pglite/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-postgres/index.js +1 -1
- package/min/persisters/persister-postgres/index.js.gz +0 -0
- package/min/persisters/persister-postgres/with-schemas/index.js +1 -1
- package/min/persisters/persister-postgres/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-powersync/index.js +1 -1
- package/min/persisters/persister-powersync/index.js.gz +0 -0
- package/min/persisters/persister-powersync/with-schemas/index.js +1 -1
- package/min/persisters/persister-powersync/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-react-native-mmkv/index.js +1 -1
- package/min/persisters/persister-react-native-mmkv/index.js.gz +0 -0
- package/min/persisters/persister-react-native-mmkv/with-schemas/index.js +1 -1
- package/min/persisters/persister-react-native-mmkv/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-react-native-sqlite/index.js +1 -1
- package/min/persisters/persister-react-native-sqlite/index.js.gz +0 -0
- package/min/persisters/persister-react-native-sqlite/with-schemas/index.js +1 -1
- package/min/persisters/persister-react-native-sqlite/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-remote/index.js +1 -1
- package/min/persisters/persister-remote/index.js.gz +0 -0
- package/min/persisters/persister-remote/with-schemas/index.js +1 -1
- package/min/persisters/persister-remote/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-sqlite-bun/index.js +1 -1
- package/min/persisters/persister-sqlite-bun/index.js.gz +0 -0
- package/min/persisters/persister-sqlite-bun/with-schemas/index.js +1 -1
- package/min/persisters/persister-sqlite-bun/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-sqlite-wasm/index.js +1 -1
- package/min/persisters/persister-sqlite-wasm/index.js.gz +0 -0
- package/min/persisters/persister-sqlite-wasm/with-schemas/index.js +1 -1
- package/min/persisters/persister-sqlite-wasm/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-sqlite3/index.js +1 -1
- package/min/persisters/persister-sqlite3/index.js.gz +0 -0
- package/min/persisters/persister-sqlite3/with-schemas/index.js +1 -1
- package/min/persisters/persister-sqlite3/with-schemas/index.js.gz +0 -0
- package/min/persisters/persister-yjs/index.js +1 -1
- package/min/persisters/persister-yjs/index.js.gz +0 -0
- package/min/persisters/persister-yjs/with-schemas/index.js +1 -1
- package/min/persisters/persister-yjs/with-schemas/index.js.gz +0 -0
- package/min/persisters/with-schemas/index.js +1 -1
- package/min/persisters/with-schemas/index.js.gz +0 -0
- package/min/queries/index.js +1 -1
- package/min/queries/index.js.gz +0 -0
- package/min/queries/with-schemas/index.js +1 -1
- package/min/queries/with-schemas/index.js.gz +0 -0
- package/min/synchronizers/index.js +1 -1
- package/min/synchronizers/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-broadcast-channel/index.js +1 -1
- package/min/synchronizers/synchronizer-broadcast-channel/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-broadcast-channel/with-schemas/index.js +1 -1
- package/min/synchronizers/synchronizer-broadcast-channel/with-schemas/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-local/index.js +1 -1
- package/min/synchronizers/synchronizer-local/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-local/with-schemas/index.js +1 -1
- package/min/synchronizers/synchronizer-local/with-schemas/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-ws-client/index.js +1 -1
- package/min/synchronizers/synchronizer-ws-client/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-ws-client/with-schemas/index.js +1 -1
- package/min/synchronizers/synchronizer-ws-client/with-schemas/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-ws-server/index.js +1 -1
- package/min/synchronizers/synchronizer-ws-server/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-ws-server/with-schemas/index.js +1 -1
- package/min/synchronizers/synchronizer-ws-server/with-schemas/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-ws-server-durable-object/index.js +1 -1
- package/min/synchronizers/synchronizer-ws-server-durable-object/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js +1 -1
- package/min/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-ws-server-simple/index.js +1 -1
- package/min/synchronizers/synchronizer-ws-server-simple/index.js.gz +0 -0
- package/min/synchronizers/synchronizer-ws-server-simple/with-schemas/index.js +1 -1
- package/min/synchronizers/synchronizer-ws-server-simple/with-schemas/index.js.gz +0 -0
- package/min/synchronizers/with-schemas/index.js +1 -1
- package/min/synchronizers/with-schemas/index.js.gz +0 -0
- package/min/ui-react-inspector/index.js +1 -1
- package/min/ui-react-inspector/index.js.gz +0 -0
- package/min/ui-react-inspector/with-schemas/index.js +1 -1
- package/min/ui-react-inspector/with-schemas/index.js.gz +0 -0
- package/min/ui-solid-inspector/index.js +1 -1
- package/min/ui-solid-inspector/index.js.gz +0 -0
- package/min/ui-solid-inspector/with-schemas/index.js +1 -1
- package/min/ui-solid-inspector/with-schemas/index.js.gz +0 -0
- package/min/ui-svelte-inspector/index.js +1 -1
- package/min/ui-svelte-inspector/index.js.gz +0 -0
- package/min/ui-svelte-inspector/with-schemas/index.js +1 -1
- package/min/ui-svelte-inspector/with-schemas/index.js.gz +0 -0
- package/min/with-schemas/index.js +1 -1
- package/min/with-schemas/index.js.gz +0 -0
- package/omni/index.js +730 -127
- package/omni/with-schemas/index.js +730 -127
- package/package.json +8 -4
- package/persisters/index.js +49 -10
- package/persisters/persister-automerge/index.js +29 -5
- package/persisters/persister-automerge/with-schemas/index.js +29 -5
- package/persisters/persister-browser/index.js +29 -5
- package/persisters/persister-browser/with-schemas/index.js +29 -5
- package/persisters/persister-cr-sqlite-wasm/index.js +29 -5
- package/persisters/persister-cr-sqlite-wasm/with-schemas/index.js +29 -5
- package/persisters/persister-durable-object-sql-storage/index.js +44 -8
- package/persisters/persister-durable-object-sql-storage/with-schemas/index.js +44 -8
- package/persisters/persister-durable-object-storage/index.js +31 -5
- package/persisters/persister-durable-object-storage/with-schemas/index.js +31 -5
- package/persisters/persister-electric-sql/index.js +29 -5
- package/persisters/persister-electric-sql/with-schemas/index.js +29 -5
- package/persisters/persister-expo-sqlite/index.js +29 -5
- package/persisters/persister-expo-sqlite/with-schemas/index.js +29 -5
- package/persisters/persister-file/index.js +31 -5
- package/persisters/persister-file/with-schemas/index.js +31 -5
- package/persisters/persister-indexed-db/index.js +29 -5
- package/persisters/persister-indexed-db/with-schemas/index.js +29 -5
- package/persisters/persister-libsql/index.js +29 -5
- package/persisters/persister-libsql/with-schemas/index.js +29 -5
- package/persisters/persister-partykit-client/index.js +31 -5
- package/persisters/persister-partykit-client/with-schemas/index.js +31 -5
- package/persisters/persister-pglite/index.js +49 -10
- package/persisters/persister-pglite/with-schemas/index.js +49 -10
- package/persisters/persister-postgres/index.js +49 -10
- package/persisters/persister-postgres/with-schemas/index.js +49 -10
- package/persisters/persister-powersync/index.js +29 -5
- package/persisters/persister-powersync/with-schemas/index.js +29 -5
- package/persisters/persister-react-native-mmkv/index.js +31 -5
- package/persisters/persister-react-native-mmkv/with-schemas/index.js +31 -5
- package/persisters/persister-react-native-sqlite/index.js +29 -5
- package/persisters/persister-react-native-sqlite/with-schemas/index.js +29 -5
- package/persisters/persister-remote/index.js +31 -5
- package/persisters/persister-remote/with-schemas/index.js +31 -5
- package/persisters/persister-sqlite-bun/index.js +29 -5
- package/persisters/persister-sqlite-bun/with-schemas/index.js +29 -5
- package/persisters/persister-sqlite-wasm/index.js +29 -5
- package/persisters/persister-sqlite-wasm/with-schemas/index.js +29 -5
- package/persisters/persister-sqlite3/index.js +29 -5
- package/persisters/persister-sqlite3/with-schemas/index.js +29 -5
- package/persisters/persister-yjs/index.js +29 -5
- package/persisters/persister-yjs/with-schemas/index.js +29 -5
- package/persisters/with-schemas/index.js +49 -10
- package/queries/index.js +334 -22
- package/queries/with-schemas/index.js +334 -22
- package/readme.md +14 -14
- package/releases.md +84 -67
- package/synchronizers/index.js +31 -5
- package/synchronizers/synchronizer-broadcast-channel/index.js +39 -13
- package/synchronizers/synchronizer-broadcast-channel/with-schemas/index.js +39 -13
- package/synchronizers/synchronizer-local/index.js +31 -5
- package/synchronizers/synchronizer-local/with-schemas/index.js +31 -5
- package/synchronizers/synchronizer-ws-client/index.js +220 -61
- package/synchronizers/synchronizer-ws-client/with-schemas/index.js +220 -61
- package/synchronizers/synchronizer-ws-server/index.js +253 -73
- package/synchronizers/synchronizer-ws-server/with-schemas/index.js +253 -73
- package/synchronizers/synchronizer-ws-server-durable-object/index.js +88 -40
- package/synchronizers/synchronizer-ws-server-durable-object/with-schemas/index.js +88 -40
- package/synchronizers/synchronizer-ws-server-simple/index.js +184 -60
- package/synchronizers/synchronizer-ws-server-simple/with-schemas/index.js +184 -60
- package/synchronizers/with-schemas/index.js +31 -5
- package/ui-react-inspector/index.js +29 -5
- package/ui-react-inspector/with-schemas/index.js +29 -5
- package/ui-solid-inspector/index.js +29 -5
- package/ui-solid-inspector/with-schemas/index.js +29 -5
- package/ui-svelte-inspector/index.js +29 -5
- package/ui-svelte-inspector/with-schemas/index.js +29 -5
- package/with-schemas/index.js +315 -22
|
@@ -228,6 +228,8 @@ const tryCatch = async (action, onError) => {
|
|
|
228
228
|
onError?.(error);
|
|
229
229
|
}
|
|
230
230
|
};
|
|
231
|
+
const tryCatchIgnore = (action, onIgnoredError) =>
|
|
232
|
+
tryCatch(action, (error) => void tryCatch(() => onIgnoredError?.(error)));
|
|
231
233
|
const tryCatchSync = (action, onError) => {
|
|
232
234
|
try {
|
|
233
235
|
return action();
|
|
@@ -321,6 +323,8 @@ const FRAGMENT_PAYLOAD = /^[^\n]*\n[-0-9A-Z_a-z]{16}\n\d+\n\d+\n/;
|
|
|
321
323
|
const INVALID_CHANNEL_ID_CHARACTERS = /[\n\r?#]/;
|
|
322
324
|
const MAX_FRAGMENT_BUFFERS = 100;
|
|
323
325
|
const MAX_FRAGMENT_COUNT = 1e3;
|
|
326
|
+
const MAX_MULTIPLE_CHANNELS = 100;
|
|
327
|
+
const MAX_MULTIPLE_CHANNEL_ID_SIZE = 1024;
|
|
324
328
|
const MAX_PENDING_REQUESTS = 100;
|
|
325
329
|
const MAX_WEBSOCKET_BUFFER_SIZE = 16777216;
|
|
326
330
|
const MAX_WEBSOCKET_QUEUE_SIZE = 1e3;
|
|
@@ -458,21 +462,30 @@ const createPayloadDecoder = (
|
|
|
458
462
|
receive,
|
|
459
463
|
fragmentTimeoutSeconds = 1,
|
|
460
464
|
onInvalid,
|
|
465
|
+
sharedBuffer,
|
|
461
466
|
) => {
|
|
462
467
|
const buffer = mapNew();
|
|
468
|
+
const payloadBuffer = sharedBuffer ?? [0, 0];
|
|
463
469
|
let bufferedSize = 0;
|
|
464
470
|
let valid = true;
|
|
465
471
|
const delPending = (bufferKey, pending) => {
|
|
466
472
|
stopTimeout(pending[4]);
|
|
467
473
|
bufferedSize -= pending[5];
|
|
474
|
+
payloadBuffer[0]--;
|
|
475
|
+
payloadBuffer[1] -= pending[5];
|
|
468
476
|
collDel(buffer, bufferKey);
|
|
469
477
|
};
|
|
478
|
+
const clear = () => {
|
|
479
|
+
mapForEach(buffer, (_bufferKey, pending) => stopTimeout(pending[4]));
|
|
480
|
+
payloadBuffer[0] -= collSize(buffer);
|
|
481
|
+
payloadBuffer[1] -= bufferedSize;
|
|
482
|
+
collClear(buffer);
|
|
483
|
+
bufferedSize = 0;
|
|
484
|
+
};
|
|
470
485
|
const invalid = (error = errorNew(ERROR_SYNC_MESSAGE)) => {
|
|
471
486
|
if (valid) {
|
|
472
487
|
valid = false;
|
|
473
|
-
|
|
474
|
-
collClear(buffer);
|
|
475
|
-
bufferedSize = 0;
|
|
488
|
+
clear();
|
|
476
489
|
onInvalid?.(error);
|
|
477
490
|
}
|
|
478
491
|
};
|
|
@@ -484,7 +497,7 @@ const createPayloadDecoder = (
|
|
|
484
497
|
invalid();
|
|
485
498
|
}
|
|
486
499
|
};
|
|
487
|
-
|
|
500
|
+
const decode = (payload) => {
|
|
488
501
|
if (!valid) {
|
|
489
502
|
return;
|
|
490
503
|
}
|
|
@@ -517,42 +530,52 @@ const createPayloadDecoder = (
|
|
|
517
530
|
const bufferKey = clientId + MESSAGE_SEPARATOR + messageId;
|
|
518
531
|
let pending = mapGet(buffer, bufferKey);
|
|
519
532
|
if (!pending) {
|
|
520
|
-
if (
|
|
533
|
+
if (payloadBuffer[0] >= MAX_FRAGMENT_BUFFERS) {
|
|
521
534
|
invalid(errorNew(ERROR_SYNC_OVERFLOW, 'fragments'));
|
|
522
535
|
return;
|
|
523
536
|
}
|
|
524
|
-
pending = [
|
|
525
|
-
[],
|
|
526
|
-
[],
|
|
527
|
-
total,
|
|
528
|
-
total,
|
|
529
|
-
startTimeout(() => {
|
|
530
|
-
const timedOut = mapGet(buffer, bufferKey);
|
|
531
|
-
if (timedOut) {
|
|
532
|
-
delPending(bufferKey, timedOut);
|
|
533
|
-
}
|
|
534
|
-
}, fragmentTimeoutSeconds),
|
|
535
|
-
0,
|
|
536
|
-
];
|
|
537
|
-
mapSet(buffer, bufferKey, pending);
|
|
538
537
|
}
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
538
|
+
if (
|
|
539
|
+
(isUndefined(pending) || total == pending[3]) &&
|
|
540
|
+
isUndefined(pending?.[0][index])
|
|
541
|
+
) {
|
|
542
|
+
const retainedSize =
|
|
543
|
+
getWebSocketPayloadSize(remainder) +
|
|
544
|
+
(pending ? 0 : getWebSocketPayloadSize(bufferKey));
|
|
545
|
+
if (payloadBuffer[1] + retainedSize > MAX_WEBSOCKET_BUFFER_SIZE) {
|
|
543
546
|
invalid(errorNew(ERROR_SYNC_OVERFLOW, 'fragments'));
|
|
544
547
|
return;
|
|
545
548
|
}
|
|
549
|
+
if (!pending) {
|
|
550
|
+
pending = [
|
|
551
|
+
[],
|
|
552
|
+
[],
|
|
553
|
+
total,
|
|
554
|
+
total,
|
|
555
|
+
startTimeout(() => {
|
|
556
|
+
const timedOut = mapGet(buffer, bufferKey);
|
|
557
|
+
if (timedOut) {
|
|
558
|
+
delPending(bufferKey, timedOut);
|
|
559
|
+
}
|
|
560
|
+
}, fragmentTimeoutSeconds),
|
|
561
|
+
0,
|
|
562
|
+
];
|
|
563
|
+
mapSet(buffer, bufferKey, pending);
|
|
564
|
+
payloadBuffer[0]++;
|
|
565
|
+
}
|
|
566
|
+
const [fragments, remainders] = pending;
|
|
546
567
|
fragments[index] = fragment;
|
|
547
568
|
remainders[index] = remainder;
|
|
548
569
|
pending[2]--;
|
|
549
|
-
pending[5] +=
|
|
550
|
-
bufferedSize +=
|
|
570
|
+
pending[5] += retainedSize;
|
|
571
|
+
bufferedSize += retainedSize;
|
|
572
|
+
payloadBuffer[1] += retainedSize;
|
|
551
573
|
} else {
|
|
552
574
|
invalid();
|
|
553
575
|
return;
|
|
554
576
|
}
|
|
555
577
|
if (pending[2] == 0) {
|
|
578
|
+
const [fragments, remainders] = pending;
|
|
556
579
|
delPending(bufferKey, pending);
|
|
557
580
|
receiveRemainder(clientId, remainders, arrayJoin(fragments));
|
|
558
581
|
}
|
|
@@ -565,6 +588,7 @@ const createPayloadDecoder = (
|
|
|
565
588
|
invalid();
|
|
566
589
|
}
|
|
567
590
|
};
|
|
591
|
+
return [decode, clear];
|
|
568
592
|
};
|
|
569
593
|
const isWebSocketBackpressured = (webSocket, payloadSize) =>
|
|
570
594
|
(webSocket.bufferedAmount ?? 0) + payloadSize > MAX_WEBSOCKET_BUFFER_SIZE;
|
|
@@ -572,12 +596,14 @@ const createPayloadReceiver = (
|
|
|
572
596
|
receive,
|
|
573
597
|
fragmentTimeoutSeconds = 1,
|
|
574
598
|
onInvalid,
|
|
599
|
+
sharedBuffer,
|
|
575
600
|
) =>
|
|
576
601
|
createPayloadDecoder(
|
|
577
602
|
(fromClientId, _remainders, requestId, message, body) =>
|
|
578
603
|
receive(fromClientId, requestId, message, body),
|
|
579
604
|
fragmentTimeoutSeconds,
|
|
580
605
|
onInvalid,
|
|
606
|
+
sharedBuffer,
|
|
581
607
|
);
|
|
582
608
|
const createRawPayload = (clientId, remainder) =>
|
|
583
609
|
clientId + MESSAGE_SEPARATOR + remainder;
|
|
@@ -610,12 +636,15 @@ const getFragments = (remainder, maxFragmentSize) => {
|
|
|
610
636
|
};
|
|
611
637
|
const createMultiplePayload = (channelId, payload) =>
|
|
612
638
|
createRawPayload(MULTIPLE_CLIENT_ID, createRawPayload(channelId, payload));
|
|
613
|
-
const ifMultiplePayloadValid = (payload, then) => {
|
|
639
|
+
const ifMultiplePayloadValid = (payload, then, onOversized) => {
|
|
614
640
|
let valid = false;
|
|
615
641
|
ifPayloadValid(payload, (multipleClientId, remainder) => {
|
|
616
642
|
if (multipleClientId == MULTIPLE_CLIENT_ID) {
|
|
617
643
|
ifPayloadValid(remainder, (channelId, channelPayload) => {
|
|
618
|
-
if (
|
|
644
|
+
if (isMultipleChannelIdTooLarge(channelId)) {
|
|
645
|
+
valid = true;
|
|
646
|
+
onOversized?.();
|
|
647
|
+
} else if (isMultipleChannelIdStructureValid(channelId)) {
|
|
619
648
|
valid = true;
|
|
620
649
|
then(channelId, channelPayload);
|
|
621
650
|
}
|
|
@@ -629,6 +658,15 @@ const createMultipleControlPayload = (requestId, control, body) =>
|
|
|
629
658
|
SERVER_CLIENT_ID,
|
|
630
659
|
jsonStringWithUndefined([requestId, MULTIPLE_MESSAGE, [control, body]]),
|
|
631
660
|
);
|
|
661
|
+
const isMultipleChannelIdTooLarge = (channelId) =>
|
|
662
|
+
getWebSocketPayloadSize(channelId) > MAX_MULTIPLE_CHANNEL_ID_SIZE;
|
|
663
|
+
const isMultipleChannelIdStructureValid = (channelId) =>
|
|
664
|
+
!isEmpty(channelId) &&
|
|
665
|
+
!INVALID_CHANNEL_ID_CHARACTERS.test(channelId) &&
|
|
666
|
+
arrayEvery(
|
|
667
|
+
strSplit(channelId, '/'),
|
|
668
|
+
(part) => !isEmpty(part) && part != '.' && part != '..',
|
|
669
|
+
);
|
|
632
670
|
const ifMultipleControlPayloadValid = (payload, then) => {
|
|
633
671
|
let valid = false;
|
|
634
672
|
ifPayloadValid(payload, (serverClientId, remainder) => {
|
|
@@ -646,11 +684,13 @@ const ifMultipleControlPayloadValid = (payload, then) => {
|
|
|
646
684
|
: control == 1 /* Subscribe */
|
|
647
685
|
? isString(requestId) &&
|
|
648
686
|
isString(body) &&
|
|
649
|
-
|
|
687
|
+
(isMultipleChannelIdTooLarge(body) ||
|
|
688
|
+
isMultipleChannelIdStructureValid(body))
|
|
650
689
|
: control == 2 /* Unsubscribe */ &&
|
|
651
690
|
isNull(requestId) &&
|
|
652
691
|
isString(body) &&
|
|
653
|
-
|
|
692
|
+
(isMultipleChannelIdTooLarge(body) ||
|
|
693
|
+
isMultipleChannelIdStructureValid(body)))
|
|
654
694
|
) {
|
|
655
695
|
valid = true;
|
|
656
696
|
then(requestId, control, body);
|
|
@@ -660,12 +700,8 @@ const ifMultipleControlPayloadValid = (payload, then) => {
|
|
|
660
700
|
return valid;
|
|
661
701
|
};
|
|
662
702
|
const isMultipleChannelIdValid = (channelId) =>
|
|
663
|
-
!
|
|
664
|
-
|
|
665
|
-
arrayEvery(
|
|
666
|
-
strSplit(channelId, '/'),
|
|
667
|
-
(part) => !isEmpty(part) && part != '.' && part != '..',
|
|
668
|
-
);
|
|
703
|
+
!isMultipleChannelIdTooLarge(channelId) &&
|
|
704
|
+
isMultipleChannelIdStructureValid(channelId);
|
|
669
705
|
const createPayloads = (toClientId, requestId, message, body, fragmentSize) => {
|
|
670
706
|
const clientId = toClientId ?? EMPTY_STRING;
|
|
671
707
|
const remainder = jsonStringWithUndefined([requestId, message, body]);
|
|
@@ -1138,11 +1174,35 @@ const createCustomPersister = (
|
|
|
1138
1174
|
initialContent,
|
|
1139
1175
|
startSaveFirst = false,
|
|
1140
1176
|
) => {
|
|
1141
|
-
const [call1, call2] = startSaveFirst
|
|
1142
|
-
? [startAutoSave, startAutoLoad]
|
|
1143
|
-
: [startAutoLoad, startAutoSave];
|
|
1144
|
-
|
|
1145
|
-
|
|
1177
|
+
const [call1, call2, stop1, stop2] = startSaveFirst
|
|
1178
|
+
? [startAutoSave, startAutoLoad, stopAutoSave, stopAutoLoad]
|
|
1179
|
+
: [startAutoLoad, startAutoSave, stopAutoLoad, stopAutoSave];
|
|
1180
|
+
const start1 = call1(initialContent);
|
|
1181
|
+
const generation1 = startSaveFirst
|
|
1182
|
+
? autoSaveGeneration
|
|
1183
|
+
: autoLoadGeneration;
|
|
1184
|
+
await start1;
|
|
1185
|
+
const start2 = call2(initialContent);
|
|
1186
|
+
const generation2 = startSaveFirst
|
|
1187
|
+
? autoLoadGeneration
|
|
1188
|
+
: autoSaveGeneration;
|
|
1189
|
+
try {
|
|
1190
|
+
await start2;
|
|
1191
|
+
} catch (error) {
|
|
1192
|
+
if (
|
|
1193
|
+
generation2 ==
|
|
1194
|
+
(startSaveFirst ? autoLoadGeneration : autoSaveGeneration)
|
|
1195
|
+
) {
|
|
1196
|
+
await tryCatchIgnore(stop2);
|
|
1197
|
+
}
|
|
1198
|
+
if (
|
|
1199
|
+
generation1 ==
|
|
1200
|
+
(startSaveFirst ? autoSaveGeneration : autoLoadGeneration)
|
|
1201
|
+
) {
|
|
1202
|
+
await tryCatchIgnore(stop1);
|
|
1203
|
+
}
|
|
1204
|
+
throw error;
|
|
1205
|
+
}
|
|
1146
1206
|
return persister;
|
|
1147
1207
|
};
|
|
1148
1208
|
const stopAutoPersisting = async (stopSaveFirst = false) => {
|
|
@@ -1543,6 +1603,7 @@ const createConnection = () => {
|
|
|
1543
1603
|
const createMultipleState = (webSocket) => {
|
|
1544
1604
|
const channels = mapNew();
|
|
1545
1605
|
const pendingControls = mapNew();
|
|
1606
|
+
const payloadBuffer = [0, 0];
|
|
1546
1607
|
const removeListeners = [];
|
|
1547
1608
|
let connection = createConnection();
|
|
1548
1609
|
let connected = false;
|
|
@@ -1554,6 +1615,7 @@ const createMultipleState = (webSocket) => {
|
|
|
1554
1615
|
let overflowing = false;
|
|
1555
1616
|
let queuedCount = 0;
|
|
1556
1617
|
let queuedSize = 0;
|
|
1618
|
+
let receiving = true;
|
|
1557
1619
|
const notifyChannelIgnoredError = (channel, error) =>
|
|
1558
1620
|
tryReturn(() => channel[6 /* OnIgnoredError */]?.(error));
|
|
1559
1621
|
const notifyIgnoredError = (error) =>
|
|
@@ -1565,11 +1627,10 @@ const createMultipleState = (webSocket) => {
|
|
|
1565
1627
|
disconnect();
|
|
1566
1628
|
tryReturn(() => webSocket.close());
|
|
1567
1629
|
};
|
|
1568
|
-
const invalid = createInvalidPayloadHandler(webSocket, notifyIgnoredError);
|
|
1569
1630
|
const addWebSocketListener = (event, handler) =>
|
|
1570
1631
|
arrayPush(removeListeners, addEventListener(webSocket, event, handler));
|
|
1571
1632
|
const rejectPendingControls = (error) =>
|
|
1572
|
-
mapForEach(pendingControls, (requestId, [, , reject, timeout]) => {
|
|
1633
|
+
mapForEach(pendingControls, (requestId, [, , , reject, timeout]) => {
|
|
1573
1634
|
stopTimeout(timeout);
|
|
1574
1635
|
collDel(pendingControls, requestId);
|
|
1575
1636
|
reject(error);
|
|
@@ -1600,11 +1661,43 @@ const createMultipleState = (webSocket) => {
|
|
|
1600
1661
|
channel[7 /* Dirty */] = void 0;
|
|
1601
1662
|
}
|
|
1602
1663
|
};
|
|
1664
|
+
const clearReceive = (channel) => channel[0 /* Receive */]?.[1]();
|
|
1665
|
+
const clearReceives = () =>
|
|
1666
|
+
mapForEach(channels, (_channelId, channel) => clearReceive(channel));
|
|
1667
|
+
const handleInvalid = createInvalidPayloadHandler(
|
|
1668
|
+
webSocket,
|
|
1669
|
+
notifyIgnoredError,
|
|
1670
|
+
);
|
|
1671
|
+
const invalid = (error) => {
|
|
1672
|
+
if (receiving) {
|
|
1673
|
+
receiving = false;
|
|
1674
|
+
disconnected = true;
|
|
1675
|
+
connected = false;
|
|
1676
|
+
clearReceives();
|
|
1677
|
+
connection[2](error);
|
|
1678
|
+
rejectPendingControls(error);
|
|
1679
|
+
failChannels(error);
|
|
1680
|
+
mapForEach(channels, (_channelId, channel) => {
|
|
1681
|
+
clearIncoming(channel);
|
|
1682
|
+
clearOutgoing(channel, true);
|
|
1683
|
+
channel[3 /* Subscribed */] = false;
|
|
1684
|
+
channel[4 /* Subscribing */] = void 0;
|
|
1685
|
+
channel[12 /* SubscribeConnection */] = void 0;
|
|
1686
|
+
});
|
|
1687
|
+
if (flushTimeout) {
|
|
1688
|
+
stopTimeout(flushTimeout);
|
|
1689
|
+
flushTimeout = void 0;
|
|
1690
|
+
}
|
|
1691
|
+
handleInvalid(error);
|
|
1692
|
+
}
|
|
1693
|
+
};
|
|
1603
1694
|
const overflow = (details) => {
|
|
1604
1695
|
const error = errorNew(ERROR_SYNC_OVERFLOW, details);
|
|
1605
1696
|
if (!overflowing && !destroyed) {
|
|
1606
1697
|
overflowing = true;
|
|
1698
|
+
receiving = false;
|
|
1607
1699
|
connected = false;
|
|
1700
|
+
clearReceives();
|
|
1608
1701
|
notifyIgnoredError(error);
|
|
1609
1702
|
rejectPendingControls(error);
|
|
1610
1703
|
failChannels(error);
|
|
@@ -1613,6 +1706,7 @@ const createMultipleState = (webSocket) => {
|
|
|
1613
1706
|
clearOutgoing(channel, true);
|
|
1614
1707
|
channel[3 /* Subscribed */] = false;
|
|
1615
1708
|
channel[4 /* Subscribing */] = void 0;
|
|
1709
|
+
channel[12 /* SubscribeConnection */] = void 0;
|
|
1616
1710
|
});
|
|
1617
1711
|
if (flushTimeout) {
|
|
1618
1712
|
stopTimeout(flushTimeout);
|
|
@@ -1634,7 +1728,7 @@ const createMultipleState = (webSocket) => {
|
|
|
1634
1728
|
});
|
|
1635
1729
|
return timeoutSeconds;
|
|
1636
1730
|
};
|
|
1637
|
-
const sendControl = (control, body, timeoutSeconds) => {
|
|
1731
|
+
const sendControl = (control, body, timeoutSeconds, onSent) => {
|
|
1638
1732
|
const requestId = getUniqueId();
|
|
1639
1733
|
return promiseNew((resolve, reject) => {
|
|
1640
1734
|
if (collSize(pendingControls) >= MAX_PENDING_REQUESTS) {
|
|
@@ -1654,9 +1748,16 @@ const createMultipleState = (webSocket) => {
|
|
|
1654
1748
|
collDel(pendingControls, requestId);
|
|
1655
1749
|
reject(errorNew(ERROR_MULTIPLEX_RESPONSE, control));
|
|
1656
1750
|
}, timeoutSeconds);
|
|
1657
|
-
mapSet(pendingControls, requestId, [
|
|
1751
|
+
mapSet(pendingControls, requestId, [
|
|
1752
|
+
control,
|
|
1753
|
+
body,
|
|
1754
|
+
resolve,
|
|
1755
|
+
reject,
|
|
1756
|
+
timeout,
|
|
1757
|
+
]);
|
|
1658
1758
|
try {
|
|
1659
1759
|
webSocket.send(payload);
|
|
1760
|
+
onSent?.();
|
|
1660
1761
|
} catch (error) {
|
|
1661
1762
|
stopTimeout(timeout);
|
|
1662
1763
|
collDel(pendingControls, requestId);
|
|
@@ -1839,23 +1940,45 @@ const createMultipleState = (webSocket) => {
|
|
|
1839
1940
|
const subscribe = async (channelId, channel, timeoutSeconds) => {
|
|
1840
1941
|
if (!channel[3 /* Subscribed */]) {
|
|
1841
1942
|
let subscribing = channel[4 /* Subscribing */];
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1943
|
+
const subscribingConnection = connection;
|
|
1944
|
+
if (subscribing?.[0] !== subscribingConnection) {
|
|
1945
|
+
const subscribingPromise = (async () => {
|
|
1946
|
+
await subscribingConnection[0];
|
|
1947
|
+
if (
|
|
1948
|
+
mapGet(channels, channelId) !== channel ||
|
|
1949
|
+
connection !== subscribingConnection ||
|
|
1950
|
+
!connected
|
|
1951
|
+
) {
|
|
1952
|
+
return;
|
|
1953
|
+
}
|
|
1845
1954
|
await sendControl(
|
|
1846
1955
|
MultipleControl.Subscribe,
|
|
1847
1956
|
channelId,
|
|
1848
1957
|
timeoutSeconds,
|
|
1958
|
+
() => {
|
|
1959
|
+
if (
|
|
1960
|
+
mapGet(channels, channelId) === channel &&
|
|
1961
|
+
connection === subscribingConnection &&
|
|
1962
|
+
connected
|
|
1963
|
+
) {
|
|
1964
|
+
channel[12 /* SubscribeConnection */] = subscribingConnection;
|
|
1965
|
+
}
|
|
1966
|
+
},
|
|
1849
1967
|
);
|
|
1850
|
-
if (
|
|
1968
|
+
if (
|
|
1969
|
+
mapGet(channels, channelId) === channel &&
|
|
1970
|
+
connection === subscribingConnection &&
|
|
1971
|
+
connected
|
|
1972
|
+
) {
|
|
1851
1973
|
channel[3 /* Subscribed */] = true;
|
|
1852
1974
|
flushOutgoing(channelId, channel);
|
|
1853
1975
|
}
|
|
1854
1976
|
})();
|
|
1977
|
+
subscribing = [subscribingConnection, subscribingPromise];
|
|
1855
1978
|
channel[4 /* Subscribing */] = subscribing;
|
|
1856
1979
|
}
|
|
1857
1980
|
try {
|
|
1858
|
-
await subscribing;
|
|
1981
|
+
await subscribing[1];
|
|
1859
1982
|
} finally {
|
|
1860
1983
|
if (channel[4 /* Subscribing */] === subscribing) {
|
|
1861
1984
|
channel[4 /* Subscribing */] = void 0;
|
|
@@ -1864,7 +1987,7 @@ const createMultipleState = (webSocket) => {
|
|
|
1864
1987
|
}
|
|
1865
1988
|
};
|
|
1866
1989
|
const onOpen = () => {
|
|
1867
|
-
if (destroyed || opening?.[0] === connection) {
|
|
1990
|
+
if (destroyed || !receiving || connected || opening?.[0] === connection) {
|
|
1868
1991
|
return;
|
|
1869
1992
|
}
|
|
1870
1993
|
disconnected = false;
|
|
@@ -1877,7 +2000,7 @@ const createMultipleState = (webSocket) => {
|
|
|
1877
2000
|
MULTIPLE_VERSION,
|
|
1878
2001
|
getConnectionTimeoutSeconds(),
|
|
1879
2002
|
);
|
|
1880
|
-
if (connection === openingConnection) {
|
|
2003
|
+
if (connection === openingConnection && receiving && !destroyed) {
|
|
1881
2004
|
connected = true;
|
|
1882
2005
|
openingConnection[1]();
|
|
1883
2006
|
mapForEach(channels, (channelId, channel) =>
|
|
@@ -1925,13 +2048,18 @@ const createMultipleState = (webSocket) => {
|
|
|
1925
2048
|
}
|
|
1926
2049
|
connection = createConnection();
|
|
1927
2050
|
mapForEach(channels, (_channelId, channel) => {
|
|
2051
|
+
clearReceive(channel);
|
|
1928
2052
|
channel[3 /* Subscribed */] = false;
|
|
1929
2053
|
channel[4 /* Subscribing */] = void 0;
|
|
2054
|
+
channel[12 /* SubscribeConnection */] = void 0;
|
|
1930
2055
|
});
|
|
1931
2056
|
}
|
|
1932
2057
|
};
|
|
1933
2058
|
const onClose = disconnect;
|
|
1934
2059
|
addWebSocketListener(MESSAGE, ({data}) => {
|
|
2060
|
+
if (!receiving) {
|
|
2061
|
+
return;
|
|
2062
|
+
}
|
|
1935
2063
|
const payload = data.toString(UTF8);
|
|
1936
2064
|
if (isWebSocketPayloadTooLarge(getWebSocketPayloadSize(payload))) {
|
|
1937
2065
|
invalid(errorNew(ERROR_SYNC_OVERFLOW, 'socket'));
|
|
@@ -1939,14 +2067,23 @@ const createMultipleState = (webSocket) => {
|
|
|
1939
2067
|
}
|
|
1940
2068
|
const control = ifMultipleControlPayloadValid(
|
|
1941
2069
|
payload,
|
|
1942
|
-
(requestId, control2,
|
|
2070
|
+
(requestId, control2, body) => {
|
|
2071
|
+
if (
|
|
2072
|
+
(control2 == MultipleControl.Subscribe ||
|
|
2073
|
+
control2 == MultipleControl.Unsubscribe) &&
|
|
2074
|
+
isString(body) &&
|
|
2075
|
+
!isMultipleChannelIdValid(body)
|
|
2076
|
+
) {
|
|
2077
|
+
overflow('channels');
|
|
2078
|
+
return;
|
|
2079
|
+
}
|
|
1943
2080
|
const pendingControl = requestId
|
|
1944
2081
|
? mapGet(pendingControls, requestId)
|
|
1945
2082
|
: void 0;
|
|
1946
|
-
if (pendingControl?.[0] == control2) {
|
|
1947
|
-
stopTimeout(pendingControl[
|
|
2083
|
+
if (pendingControl?.[0] == control2 && pendingControl[1] === body) {
|
|
2084
|
+
stopTimeout(pendingControl[4]);
|
|
1948
2085
|
collDel(pendingControls, requestId);
|
|
1949
|
-
pendingControl[
|
|
2086
|
+
pendingControl[2]();
|
|
1950
2087
|
}
|
|
1951
2088
|
},
|
|
1952
2089
|
);
|
|
@@ -1956,7 +2093,7 @@ const createMultipleState = (webSocket) => {
|
|
|
1956
2093
|
const channel2 = mapGet(channels, channelId);
|
|
1957
2094
|
if (channel2) {
|
|
1958
2095
|
if (channel2[0 /* Receive */]) {
|
|
1959
|
-
channel2[0 /* Receive */](channelPayload);
|
|
2096
|
+
channel2[0 /* Receive */][0](channelPayload);
|
|
1960
2097
|
} else {
|
|
1961
2098
|
queueIncoming(channel2, channelPayload);
|
|
1962
2099
|
}
|
|
@@ -1964,6 +2101,7 @@ const createMultipleState = (webSocket) => {
|
|
|
1964
2101
|
invalid(errorNew(ERROR_SYNC_MESSAGE));
|
|
1965
2102
|
}
|
|
1966
2103
|
},
|
|
2104
|
+
() => overflow('channels'),
|
|
1967
2105
|
);
|
|
1968
2106
|
if (!control && !channel) {
|
|
1969
2107
|
invalid(errorNew(ERROR_SYNC_MESSAGE));
|
|
@@ -1976,12 +2114,18 @@ const createMultipleState = (webSocket) => {
|
|
|
1976
2114
|
failChannels(errorNew(ERROR_MULTIPLEX_SOCKET));
|
|
1977
2115
|
});
|
|
1978
2116
|
const addChannel = async (channelId, timeoutSeconds, onIgnoredError) => {
|
|
2117
|
+
if (!receiving || destroyed) {
|
|
2118
|
+
errorThrow(ERROR_MULTIPLEX_SOCKET);
|
|
2119
|
+
}
|
|
1979
2120
|
if (!isMultipleChannelIdValid(channelId)) {
|
|
1980
2121
|
errorThrow(ERROR_MULTIPLEX_CHANNEL, channelId);
|
|
1981
2122
|
}
|
|
1982
2123
|
if (collHas(channels, channelId)) {
|
|
1983
2124
|
errorThrow(ERROR_MULTIPLEX_CHANNEL_DUPLICATE, channelId);
|
|
1984
2125
|
}
|
|
2126
|
+
if (collSize(channels) >= MAX_MULTIPLE_CHANNELS) {
|
|
2127
|
+
errorThrow(ERROR_SYNC_OVERFLOW, 'channels');
|
|
2128
|
+
}
|
|
1985
2129
|
const channel = [
|
|
1986
2130
|
void 0,
|
|
1987
2131
|
[],
|
|
@@ -1995,6 +2139,7 @@ const createMultipleState = (webSocket) => {
|
|
|
1995
2139
|
0,
|
|
1996
2140
|
0,
|
|
1997
2141
|
void 0,
|
|
2142
|
+
void 0,
|
|
1998
2143
|
];
|
|
1999
2144
|
mapSet(channels, channelId, channel);
|
|
2000
2145
|
if (webSocket.readyState == webSocket.OPEN) {
|
|
@@ -2028,7 +2173,7 @@ const createMultipleState = (webSocket) => {
|
|
|
2028
2173
|
queuedCount--;
|
|
2029
2174
|
queuedSize -= payloadSize;
|
|
2030
2175
|
incomingIndex++;
|
|
2031
|
-
receive(payload);
|
|
2176
|
+
receive[0](payload);
|
|
2032
2177
|
}
|
|
2033
2178
|
},
|
|
2034
2179
|
() => arrayClear(incoming, incomingIndex),
|
|
@@ -2036,6 +2181,9 @@ const createMultipleState = (webSocket) => {
|
|
|
2036
2181
|
}
|
|
2037
2182
|
};
|
|
2038
2183
|
const send = (channelId, payloads, coalesce) => {
|
|
2184
|
+
if (!receiving) {
|
|
2185
|
+
return;
|
|
2186
|
+
}
|
|
2039
2187
|
const channel = mapGet(channels, channelId);
|
|
2040
2188
|
if (channel) {
|
|
2041
2189
|
if (
|
|
@@ -2056,6 +2204,9 @@ const createMultipleState = (webSocket) => {
|
|
|
2056
2204
|
const destroyIfEmpty = () => {
|
|
2057
2205
|
if (collIsEmpty(channels) && !destroyed) {
|
|
2058
2206
|
destroyed = true;
|
|
2207
|
+
const closeWebSocket = receiving && !overflowing;
|
|
2208
|
+
receiving = false;
|
|
2209
|
+
clearReceives();
|
|
2059
2210
|
const error = errorNew(ERROR_MULTIPLEX_DESTROYED);
|
|
2060
2211
|
rejectPendingControls(error);
|
|
2061
2212
|
if (flushTimeout) {
|
|
@@ -2067,7 +2218,7 @@ const createMultipleState = (webSocket) => {
|
|
|
2067
2218
|
);
|
|
2068
2219
|
arrayClear(removeListeners);
|
|
2069
2220
|
multipleStates.delete(webSocket);
|
|
2070
|
-
if (
|
|
2221
|
+
if (closeWebSocket) {
|
|
2071
2222
|
tryReturn(() => webSocket.close());
|
|
2072
2223
|
}
|
|
2073
2224
|
}
|
|
@@ -2076,9 +2227,10 @@ const createMultipleState = (webSocket) => {
|
|
|
2076
2227
|
const channel = mapGet(channels, channelId);
|
|
2077
2228
|
if (channel) {
|
|
2078
2229
|
try {
|
|
2230
|
+
clearReceive(channel);
|
|
2079
2231
|
clearIncoming(channel);
|
|
2080
2232
|
clearOutgoing(channel, true);
|
|
2081
|
-
if (connected && channel[
|
|
2233
|
+
if (connected && channel[12 /* SubscribeConnection */] === connection) {
|
|
2082
2234
|
const payload = createMultipleControlPayload(
|
|
2083
2235
|
null,
|
|
2084
2236
|
MultipleControl.Unsubscribe,
|
|
@@ -2107,6 +2259,7 @@ const createMultipleState = (webSocket) => {
|
|
|
2107
2259
|
delChannel,
|
|
2108
2260
|
destroyIfEmpty,
|
|
2109
2261
|
invalid,
|
|
2262
|
+
payloadBuffer,
|
|
2110
2263
|
registerReceive,
|
|
2111
2264
|
send,
|
|
2112
2265
|
};
|
|
@@ -2162,7 +2315,12 @@ const createMultipleWsSynchronizer = async (
|
|
|
2162
2315
|
(receive, fail) =>
|
|
2163
2316
|
state.registerReceive(
|
|
2164
2317
|
channelId,
|
|
2165
|
-
createPayloadReceiver(
|
|
2318
|
+
createPayloadReceiver(
|
|
2319
|
+
receive,
|
|
2320
|
+
requestTimeoutSeconds,
|
|
2321
|
+
state.invalid,
|
|
2322
|
+
state.payloadBuffer,
|
|
2323
|
+
),
|
|
2166
2324
|
fail,
|
|
2167
2325
|
),
|
|
2168
2326
|
() => state.delChannel(channelId),
|
|
@@ -2204,13 +2362,14 @@ const createLegacyWsSynchronizer = async (
|
|
|
2204
2362
|
};
|
|
2205
2363
|
const registerReceive = (receive, fail) => {
|
|
2206
2364
|
const invalid = createInvalidPayloadHandler(webSocket, notifyIgnoredError);
|
|
2207
|
-
const receivePayload = createPayloadReceiver(
|
|
2365
|
+
const [receivePayload, clearReceivePayload] = createPayloadReceiver(
|
|
2208
2366
|
receive,
|
|
2209
2367
|
requestTimeoutSeconds,
|
|
2210
2368
|
invalid,
|
|
2211
2369
|
);
|
|
2212
2370
|
let removeListeners = [];
|
|
2213
2371
|
removeTransportListeners = () => {
|
|
2372
|
+
clearReceivePayload();
|
|
2214
2373
|
arrayForEach(removeListeners, (removeListener) =>
|
|
2215
2374
|
tryReturn(removeListener),
|
|
2216
2375
|
);
|