jsgar 4.13.0 → 4.13.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/dist/gar.umd.js +32 -0
- package/gar.js +32 -0
- package/package.json +3 -1
package/dist/gar.umd.js
CHANGED
|
@@ -852,6 +852,31 @@
|
|
|
852
852
|
*/
|
|
853
853
|
sendMessage(message) {
|
|
854
854
|
this.messageQueue.push(message);
|
|
855
|
+
// Drain synchronously when possible: background tabs throttle timers — the polling
|
|
856
|
+
// drain loop (and any setInterval sender) can stretch from 100ms to minutes — but
|
|
857
|
+
// synchronous sends from an event or enqueue are never throttled.
|
|
858
|
+
this._flushQueue();
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
/**
|
|
862
|
+
* Synchronously send everything sendable. Safe alongside the polling loop (same JS
|
|
863
|
+
* thread); leaves the null shutdown sentinel for the loop's exit handling.
|
|
864
|
+
*/
|
|
865
|
+
_flushQueue() {
|
|
866
|
+
while (this.connected && this.messageQueue.length > 0 && this._isSocketOpen()) {
|
|
867
|
+
if (this.messageQueue[0] === null) return;
|
|
868
|
+
const message = this.messageQueue.shift();
|
|
869
|
+
try {
|
|
870
|
+
this.websocket.send(JSON.stringify(message));
|
|
871
|
+
if (this.logEveryMessage) {
|
|
872
|
+
this.log('INFO', `Sent: ${JSON.stringify(message)}`);
|
|
873
|
+
}
|
|
874
|
+
} catch (e) {
|
|
875
|
+
this.log('WARNING', `Error sending message: ${e.message}`);
|
|
876
|
+
this.halt();
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
}
|
|
855
880
|
}
|
|
856
881
|
|
|
857
882
|
/**
|
|
@@ -979,6 +1004,13 @@
|
|
|
979
1004
|
this.invalidatedKeyIds.add(message.value.client_introduced_key_id);
|
|
980
1005
|
} else if (msgType === 'Heartbeat') {
|
|
981
1006
|
this.lastHeartbeatTime = Date.now() / 1000;
|
|
1007
|
+
// Echo our own heartbeat on the server's cadence. A hidden tab's throttled timers
|
|
1008
|
+
// can silence the periodic sender far past the server's timeout while this
|
|
1009
|
+
// (unthrottled) receive path keeps delivering — the server then rightly declares
|
|
1010
|
+
// us dead. Event-driven liveness: receive -> reply, flushed synchronously above.
|
|
1011
|
+
if (this.running) {
|
|
1012
|
+
this.sendMessage({ message_type: 'Heartbeat', value: { u_milliseconds: Date.now() } });
|
|
1013
|
+
}
|
|
982
1014
|
if (this._initialGracePeriod) {
|
|
983
1015
|
// Resolve first-heartbeat waiters and end the initial grace window
|
|
984
1016
|
if (this._firstHeartbeatResolve) {
|
package/gar.js
CHANGED
|
@@ -845,6 +845,31 @@ class GARClient {
|
|
|
845
845
|
*/
|
|
846
846
|
sendMessage(message) {
|
|
847
847
|
this.messageQueue.push(message);
|
|
848
|
+
// Drain synchronously when possible: background tabs throttle timers — the polling
|
|
849
|
+
// drain loop (and any setInterval sender) can stretch from 100ms to minutes — but
|
|
850
|
+
// synchronous sends from an event or enqueue are never throttled.
|
|
851
|
+
this._flushQueue();
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
/**
|
|
855
|
+
* Synchronously send everything sendable. Safe alongside the polling loop (same JS
|
|
856
|
+
* thread); leaves the null shutdown sentinel for the loop's exit handling.
|
|
857
|
+
*/
|
|
858
|
+
_flushQueue() {
|
|
859
|
+
while (this.connected && this.messageQueue.length > 0 && this._isSocketOpen()) {
|
|
860
|
+
if (this.messageQueue[0] === null) return;
|
|
861
|
+
const message = this.messageQueue.shift();
|
|
862
|
+
try {
|
|
863
|
+
this.websocket.send(JSON.stringify(message));
|
|
864
|
+
if (this.logEveryMessage) {
|
|
865
|
+
this.log('INFO', `Sent: ${JSON.stringify(message)}`);
|
|
866
|
+
}
|
|
867
|
+
} catch (e) {
|
|
868
|
+
this.log('WARNING', `Error sending message: ${e.message}`);
|
|
869
|
+
this.halt();
|
|
870
|
+
return;
|
|
871
|
+
}
|
|
872
|
+
}
|
|
848
873
|
}
|
|
849
874
|
|
|
850
875
|
/**
|
|
@@ -972,6 +997,13 @@ class GARClient {
|
|
|
972
997
|
this.invalidatedKeyIds.add(message.value.client_introduced_key_id);
|
|
973
998
|
} else if (msgType === 'Heartbeat') {
|
|
974
999
|
this.lastHeartbeatTime = Date.now() / 1000;
|
|
1000
|
+
// Echo our own heartbeat on the server's cadence. A hidden tab's throttled timers
|
|
1001
|
+
// can silence the periodic sender far past the server's timeout while this
|
|
1002
|
+
// (unthrottled) receive path keeps delivering — the server then rightly declares
|
|
1003
|
+
// us dead. Event-driven liveness: receive -> reply, flushed synchronously above.
|
|
1004
|
+
if (this.running) {
|
|
1005
|
+
this.sendMessage({ message_type: 'Heartbeat', value: { u_milliseconds: Date.now() } });
|
|
1006
|
+
}
|
|
975
1007
|
if (this._initialGracePeriod) {
|
|
976
1008
|
// Resolve first-heartbeat waiters and end the initial grace window
|
|
977
1009
|
if (this._firstHeartbeatResolve) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jsgar",
|
|
3
|
-
"version": "4.13.
|
|
3
|
+
"version": "4.13.2",
|
|
4
4
|
"description": "A Javascript client for the GAR protocol",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/gar.umd.js",
|
|
@@ -36,6 +36,8 @@
|
|
|
36
36
|
"@eslint/json": "^0.13.2",
|
|
37
37
|
"@rollup/plugin-commonjs": "^24.0.0",
|
|
38
38
|
"@rollup/plugin-node-resolve": "^15.0.0",
|
|
39
|
+
"@xterm/addon-fit": "^0.10.0",
|
|
40
|
+
"@xterm/xterm": "^5.5.0",
|
|
39
41
|
"ag-grid-community": "^34.1.1",
|
|
40
42
|
"ag-grid-enterprise": "^34.1.1",
|
|
41
43
|
"eslint": "^9.39.4",
|