socketduct 0.1.17 → 0.1.19

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.
@@ -7,6 +7,7 @@ import {Duplex} from "node:stream"
7
7
  * @property {(streamId: number, callback: (error?: Error | null) => void) => void} _endStream - End the writable side.
8
8
  * @property {(streamId: number, error: Error | null) => void} _destroyStream - Destroy the virtual stream.
9
9
  * @property {(streamId: number) => void} _resumeReadable - Resume inbound flow.
10
+ * @property {(streamId: number, bytes: number) => void} [_consumeReadable] - Report bytes returned to the application.
10
11
  * @property {() => {address?: string, port?: number}} physicalAddress - Current physical endpoint.
11
12
  * @property {() => unknown} ref - Reference owner resources.
12
13
  * @property {() => unknown} unref - Unreference owner resources.
@@ -60,6 +61,9 @@ export class VirtualSocket extends Duplex {
60
61
  /** @type {boolean} */
61
62
  #remoteEnded = false
62
63
 
64
+ /** @type {number} */
65
+ #emittedDataBytes = 0
66
+
63
67
  /** @type {boolean} */
64
68
  connecting = true
65
69
 
@@ -123,6 +127,44 @@ export class VirtualSocket extends Duplex {
123
127
  this.#connection._resumeReadable(this.#streamId)
124
128
  }
125
129
 
130
+ /**
131
+ * Reports application consumption after Node has emitted flowing data or
132
+ * fulfilled a paused-mode read. Owners that need durable receive ACKs can
133
+ * therefore distinguish consumed bytes from process-local readable bytes.
134
+ * @param {number} [size] - Requested bytes.
135
+ * @returns {Buffer | string | null} Readable chunk.
136
+ * @override
137
+ */
138
+ read(size) {
139
+ const emittedBefore = this.#emittedDataBytes
140
+ const chunk = super.read(size)
141
+ if (chunk !== null) {
142
+ const bytes = typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length
143
+ const emittedBytes = this.#emittedDataBytes - emittedBefore
144
+ if (bytes > emittedBytes) this.#connection._consumeReadable?.(this.#streamId, bytes - emittedBytes)
145
+ }
146
+ return chunk
147
+ }
148
+
149
+ /**
150
+ * A flowing Readable may emit directly from push() without returning a chunk
151
+ * through read(). Report DATA only after application listeners have run.
152
+ * @param {string | symbol} event - Event name.
153
+ * @param {...unknown} args - Event values.
154
+ * @returns {boolean} Whether the event had listeners.
155
+ * @override
156
+ */
157
+ emit(event, ...args) {
158
+ const emitted = super.emit(event, ...args)
159
+ const chunk = args[0]
160
+ if (event === "data" && (typeof chunk === "string" || Buffer.isBuffer(chunk))) {
161
+ const bytes = typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length
162
+ this.#emittedDataBytes += bytes
163
+ this.#connection._consumeReadable?.(this.#streamId, bytes)
164
+ }
165
+ return emitted
166
+ }
167
+
126
168
  /**
127
169
  * @override
128
170
  * @param {Buffer | string | Uint8Array} chunk - Application bytes.