@actuallab/rpc 14.3.5 → 14.3.16

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/index.cjs CHANGED
@@ -2025,6 +2025,7 @@ function _compactBufferedUnsentSuffix(buffer, firstUnsentIndex, canSkipTo) {
2025
2025
  var { warnLog: warnLog6 } = getLogs("RpcStream");
2026
2026
  var DEFAULT_ACK_PERIOD2 = 30;
2027
2027
  var DEFAULT_ACK_ADVANCE2 = 61;
2028
+ var MAX_BATCH_SIZE = 1024;
2028
2029
  function parseStreamRef(value) {
2029
2030
  if (typeof value === "string") {
2030
2031
  const parts = value.split(",");
@@ -2212,6 +2213,10 @@ var RpcStream = class _RpcStream {
2212
2213
  this._failProtocol(`invalid $sys.B index/length: ${String(index)}/${String(items.length)}`);
2213
2214
  return;
2214
2215
  }
2216
+ if (items.length > MAX_BATCH_SIZE) {
2217
+ this._failProtocol(`$sys.B batch is too large: ${items.length} > ${MAX_BATCH_SIZE}`);
2218
+ return;
2219
+ }
2215
2220
  if (index > this._nextExpectedIndex) {
2216
2221
  warnLog6?.log(`batch index gap: localId=${this.id.localId}, expected=${this._nextExpectedIndex}, received=${index}`);
2217
2222
  if (!this.allowReconnect) {
@@ -2346,11 +2351,23 @@ var RpcStream = class _RpcStream {
2346
2351
  // last acknowledged index. The sending side is the only place that window
2347
2352
  // was ever enforced, which left a flooding remote free to grow our buffer
2348
2353
  // without bound (I6) — so we enforce our half of the contract here.
2354
+ //
2355
+ // The window is credited by consumption, never by `_ackSentUpTo`: a reset ack
2356
+ // re-bases to what we've *received*, so crediting it would let a peer ratchet
2357
+ // its own limit up by alternating "fill the window" with a forced gap.
2358
+ // Twice ackAdvance is what a conforming sender can leave buffered (ackAdvance
2359
+ // in steady state, plus ackAdvance more after a reset re-bases it), and
2360
+ // ackPeriod covers the lag of acks behind consumption.
2349
2361
  _isBeyondAckWindow(nextExpectedIndex) {
2350
- return this.ackAdvance > 0 && nextExpectedIndex > this._ackSentUpTo + this.ackAdvance;
2362
+ if (this.ackAdvance <= 0)
2363
+ return false;
2364
+ return nextExpectedIndex > this._nextConsumedIndex + this._ackWindowSize();
2365
+ }
2366
+ _ackWindowSize() {
2367
+ return 2 * this.ackAdvance + this.ackPeriod;
2351
2368
  }
2352
2369
  _ackWindowError(nextExpectedIndex) {
2353
- return `Stream ran past its ack window: reached ${nextExpectedIndex}, acked ${this._ackSentUpTo}, ackAdvance ${this.ackAdvance}`;
2370
+ return `Stream ran past its ack window: reached ${nextExpectedIndex}, consumed ${this._nextConsumedIndex}, ackAdvance ${this.ackAdvance}`;
2354
2371
  }
2355
2372
  _gapError(index) {
2356
2373
  return new Error(