Skip to content

Commit 441dea2

Browse files
authored
fix: Only abort pipeablestream if not already closed (#417)
* fix: Only abort pipeablestream if not complete * docs: Add changeset
1 parent 27f340b commit 441dea2

File tree

4 files changed

+30
-3
lines changed

4 files changed

+30
-3
lines changed

.changeset/yellow-hounds-jog.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'preact-render-to-string': patch
3+
---
4+
5+
Only abort/report errors from `renderToPipeableStream()` if the stream hasn't already been closed

src/stream-node.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,14 @@ export function renderToPipeableStream(vnode, options, context) {
6060
/**
6161
* @param {unknown} [reason]
6262
*/
63-
abort(reason = new Error('The render was aborted by the server without a reason.')) {
63+
abort(
64+
reason = new Error(
65+
'The render was aborted by the server without a reason.'
66+
)
67+
) {
68+
// Remix/React-Router will always call abort after a timeout, even on success
69+
if (stream.closed) return;
70+
6471
controller.abort();
6572
stream.destroy();
6673
if (options.onError) {

test/compat/stream-node.test.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,19 @@ describe('renderToPipeableStream', () => {
7373
'</div>'
7474
]);
7575
});
76+
77+
it('should not error if the stream has already been closed', async () => {
78+
let error;
79+
const sink = createSink();
80+
const { pipe, abort } = renderToPipeableStream(<div class="foo">bar</div>, {
81+
onAllReady: () => {
82+
pipe(sink.stream);
83+
},
84+
onError: (e) => (error = e)
85+
});
86+
await sink.promise;
87+
abort();
88+
89+
expect(error).to.be.undefined;
90+
});
7691
});

test/compat/stream.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,10 @@ describe('renderToReadableStream', () => {
8282
const result = await sink.promise;
8383

8484
expect(result).to.deep.equal([
85-
'<div><!--preact-island:54-->loading...<!--/preact-island:54--></div>',
85+
'<div><!--preact-island:56-->loading...<!--/preact-island:56--></div>',
8686
'<div hidden>',
8787
createInitScript(),
88-
createSubtree('54', '<p>it works</p>'),
88+
createSubtree('56', '<p>it works</p>'),
8989
'</div>'
9090
]);
9191
});

0 commit comments

Comments
 (0)