@promistream/from-node-stream 0.1.5 → 0.1.6

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.
Files changed (3) hide show
  1. package/package.json +4 -3
  2. package/src/index.js +15 -3
  3. package/test.js +45 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@promistream/from-node-stream",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "main": "src/index.js",
5
5
  "repository": "https://codeberg.org/promistream/from-node-stream.git",
6
6
  "author": "Sven Slootweg <admin@cryto.net>",
@@ -14,11 +14,11 @@
14
14
  "@promistream/is-end-of-stream": "^0.1.1",
15
15
  "@promistream/propagate-abort": "^0.1.7",
16
16
  "@promistream/propagate-peek": "^0.1.2",
17
- "@promistream/simple-sink": "^0.3.4",
17
+ "@promistream/simple-sink": "^0.3.5",
18
18
  "@promistream/simple-source": "^0.1.10",
19
19
  "debug-instanced": "^1.0.0",
20
20
  "promisify-event": "^1.0.0",
21
- "push-buffer": "^1.5.5",
21
+ "push-buffer": "^1.5.7",
22
22
  "single-concurrent": "^1.0.0",
23
23
  "split-filter": "^1.1.3"
24
24
  },
@@ -32,6 +32,7 @@
32
32
  "@promistream/pipe": "^0.1.8",
33
33
  "@promistream/range-numbers": "^0.1.2",
34
34
  "bluebird": "^3.7.2",
35
+ "p-defer": "^4.0.1",
35
36
  "through2": "^4.0.2"
36
37
  }
37
38
  }
package/src/index.js CHANGED
@@ -9,6 +9,7 @@ const isEndOfStream = require("@promistream/is-end-of-stream");
9
9
  const isAborted = require("@promistream/is-aborted");
10
10
  const makeDebug = require("debug-instanced")("promistream:from-node-stream");
11
11
 
12
+ const { once } = require("node:events");
12
13
  const pushBuffer = require("push-buffer");
13
14
  const promisifyEvent = require("promisify-event");
14
15
  const singleConcurrent = require("single-concurrent");
@@ -126,6 +127,14 @@ function wireWritable(debug, stream) {
126
127
  errorEncountered = ensureValidError(error);
127
128
  });
128
129
 
130
+ async function maybeWaitForDrain() {
131
+ if (stream.writableNeedDrain) {
132
+ /* Wait for the write buffer to be fully processed */
133
+ // FIXME: Verify that this cannot cause a never-ending wait; if we wait to close the stream until it has drained, then during that time writes to it can continue to happen indefinitely, never letting it drain? Or is this prevented by the backpressure mechanisms we already have (re: .pause and .resume)?
134
+ await once(stream, "drain");
135
+ }
136
+ }
137
+
129
138
  // We're not wiring into the `finish` event here because we detect the ended stream on the next write attempt instead (inside of `tryWrite`).
130
139
 
131
140
  return {
@@ -133,12 +142,14 @@ function wireWritable(debug, stream) {
133
142
  // TODO: Do we need to detach any event handlers prior to destroying streams? ref. https://www.npmjs.com/package/yauzl:
134
143
  // "You must unpipe() the readStream from any destination before calling readStream.destroy()."
135
144
  // TODO: In a previous version, we skipped the .destroy step if the stream didn't have a .destroy method. What was this for? Streams v1?
145
+ await maybeWaitForDrain();
136
146
  if (!isStdioStream(stream) && !isWritableStreamEnded(stream)) {
137
147
  debug("Calling .destroy on Writable stream");
138
148
  stream.destroy(error);
139
149
  }
140
150
  },
141
151
  end: async function () {
152
+ await maybeWaitForDrain();
142
153
  if (!isStdioStream(stream) && !isWritableStreamEnded(stream)) {
143
154
  debug("Calling .end on Writable stream");
144
155
  stream.end();
@@ -182,10 +193,11 @@ function convertFromWritable(stream) {
182
193
 
183
194
  return simpleSink({
184
195
  onAbort: async (error) => {
185
- if (error === true) {
186
- return end();
187
- } else {
196
+ // TODO: this is mostly-duplicated logic with that in the transform stream implementation
197
+ if (error instanceof Error) {
188
198
  return destroy(error);
199
+ } else {
200
+ return end();
189
201
  }
190
202
  },
191
203
  onEnd: async () => {
package/test.js CHANGED
@@ -5,6 +5,8 @@ const assert = require("node:assert");
5
5
  const fs = require("node:fs");
6
6
  const path = require("node:path");
7
7
  const stream = require("node:stream");
8
+ const net = require("node:net");
9
+ const pDefer = require("p-defer").default;
8
10
 
9
11
  const pipe = require("@promistream/pipe");
10
12
  const fromIterable = require("@promistream/from-iterable");
@@ -112,3 +114,46 @@ test("transform stream, parallel", async () => {
112
114
 
113
115
  assert.deepStrictEqual(result, [ 0, 0, 1, 2, 2, 4, 3, 6, 4, 8, 5, 10, 6, 12, 7, 14, 8, 16, 9, 18, 10, 20 ]);
114
116
  });
117
+
118
+ /* FIXME: Do network socket test with both happy abort and error abort */
119
+ test("network socket", async () => {
120
+ let { resolve, promise } = pDefer();
121
+
122
+ let server = net.createServer((socket) => {
123
+ // console.log("connected", socket);
124
+ let serverRead = fromNodeStream.fromReadable(socket);
125
+ let serverWrite = fromNodeStream.fromWritable(socket);
126
+ resolve({ serverRead, serverWrite });
127
+ });
128
+ server.listen(14292);
129
+
130
+ try {
131
+ let client = net.connect({ host: "localhost", port: 14292 });
132
+ let clientRead = fromNodeStream.fromReadable(client);
133
+ let clientWrite = fromNodeStream.fromWritable(client);
134
+ let { serverRead, serverWrite } = await promise;
135
+
136
+ let serverPipe = pipe([ serverRead, collect() ]);
137
+ let serverWritePipe = pipe([ fromIterable([ Buffer.from("c"), Buffer.from("d") ]), serverWrite ]);
138
+ let clientPipe = pipe([ clientRead, collect() ]);
139
+ let clientWritePipe = pipe([ fromIterable([ Buffer.from("a"), Buffer.from("b") ]), clientWrite ]);
140
+
141
+ let clientWritePromise = clientWritePipe.read();
142
+ await new Promise((resolve) => setTimeout(resolve, 1)); /* give it a couple ticks to actually read from the iterable source before aborting */
143
+ clientWritePipe.abort(true);
144
+
145
+ let [ serverResult, serverWriteResult, clientResult, clientWriteResult ] = await Promise.all([
146
+ serverPipe.read(),
147
+ serverWritePipe.read(),
148
+ clientPipe.read(),
149
+ clientWritePromise,
150
+ ]);
151
+
152
+ assert.deepStrictEqual(Buffer.concat(serverResult), Buffer.from("ab"));
153
+ assert.deepStrictEqual(Buffer.concat(clientResult), Buffer.from("cd"));
154
+ assert.deepStrictEqual(serverWriteResult, undefined);
155
+ assert.deepStrictEqual(clientWriteResult, undefined);
156
+ } finally {
157
+ server.close();
158
+ }
159
+ });