@promistream/from-node-stream 0.1.5 → 0.1.7
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/package.json +4 -4
- package/src/index.js +17 -5
- 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.
|
|
3
|
+
"version": "0.1.7",
|
|
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,10 @@
|
|
|
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.
|
|
17
|
+
"@promistream/simple-sink": "^0.3.5",
|
|
18
18
|
"@promistream/simple-source": "^0.1.10",
|
|
19
19
|
"debug-instanced": "^1.0.0",
|
|
20
|
-
"
|
|
21
|
-
"push-buffer": "^1.5.5",
|
|
20
|
+
"push-buffer": "^1.5.7",
|
|
22
21
|
"single-concurrent": "^1.0.0",
|
|
23
22
|
"split-filter": "^1.1.3"
|
|
24
23
|
},
|
|
@@ -32,6 +31,7 @@
|
|
|
32
31
|
"@promistream/pipe": "^0.1.8",
|
|
33
32
|
"@promistream/range-numbers": "^0.1.2",
|
|
34
33
|
"bluebird": "^3.7.2",
|
|
34
|
+
"p-defer": "^4.0.1",
|
|
35
35
|
"through2": "^4.0.2"
|
|
36
36
|
}
|
|
37
37
|
}
|
package/src/index.js
CHANGED
|
@@ -9,8 +9,8 @@ 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
|
-
const promisifyEvent = require("promisify-event");
|
|
14
14
|
const singleConcurrent = require("single-concurrent");
|
|
15
15
|
const warning = require("@joepie91/warning");
|
|
16
16
|
const util = require("node:util");
|
|
@@ -126,6 +126,15 @@ function wireWritable(debug, stream) {
|
|
|
126
126
|
errorEncountered = ensureValidError(error);
|
|
127
127
|
});
|
|
128
128
|
|
|
129
|
+
async function maybeWaitForDrain() {
|
|
130
|
+
if (stream.writableNeedDrain) {
|
|
131
|
+
/* Wait for the write buffer to be fully processed */
|
|
132
|
+
// 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)?
|
|
133
|
+
debug("Waiting for internal write queue to drain...");
|
|
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();
|
|
@@ -161,7 +172,7 @@ function wireWritable(debug, stream) {
|
|
|
161
172
|
|
|
162
173
|
if (!canWriteMore) {
|
|
163
174
|
debug("Stream is backlogged, waiting for drain event...");
|
|
164
|
-
await
|
|
175
|
+
await once(stream, "drain");
|
|
165
176
|
debug("Drain event received");
|
|
166
177
|
} else {
|
|
167
178
|
debug("Write successful, can write more");
|
|
@@ -182,10 +193,11 @@ function convertFromWritable(stream) {
|
|
|
182
193
|
|
|
183
194
|
return simpleSink({
|
|
184
195
|
onAbort: async (error) => {
|
|
185
|
-
|
|
186
|
-
|
|
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
|
+
});
|