Skip to content

Commit

Permalink
fix(netstring): Fix writer early return during chunked write
Browse files Browse the repository at this point in the history
  • Loading branch information
kriskowal committed Sep 26, 2023
1 parent 6ad3b8f commit ae1d93b
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 6 deletions.
1 change: 1 addition & 0 deletions packages/netstring/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
},
"dependencies": {
"@endo/init": "^0.5.60",
"@endo/promise-kit": "^0.2.60",
"@endo/stream": "^0.3.29",
"ses": "^0.18.8"
},
Expand Down
32 changes: 26 additions & 6 deletions packages/netstring/writer.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// @ts-check
/// <reference types="ses"/>

import { makePromiseKit } from '@endo/promise-kit';

const COMMA_BUFFER = new Uint8Array([','.charCodeAt(0)]);

/** @param {number} length */
Expand Down Expand Up @@ -39,14 +41,32 @@ export const makeNetstringWriter = (output, { chunked = false } = {}) => {
const prefix = getLengthPrefixCharCodes(messageLength);

if (chunked) {
return Promise.all([
const ack = makePromiseKit();

const partsWritten = [
output.next(new Uint8Array(prefix)),
...messageChunks.map(async chunk => output.next(chunk)),
...messageChunks.map(chunk => output.next(chunk)),
output.next(COMMA_BUFFER),
]).then(([r1, r2, r3]) => ({
done: !!(r1.done || r2.done || r3.done),
value: undefined,
}));
];

// Resolve early if the output writer closes early.
for (const promise of partsWritten) {
promise.then(partWritten => {
if (partWritten.done) {
ack.resolve(partWritten);
}
});
}

Promise.all(partsWritten).then(results => {
// Redundant resolution is safe and clean.
ack.resolve({
done: results.some(({ done }) => done),
value: undefined,
});
}, ack.reject);

return ack.promise;
} else {
const buffer = new Uint8Array(prefix.length + messageLength + 1);
buffer.set(prefix, 0);
Expand Down

0 comments on commit ae1d93b

Please sign in to comment.