Skip to content

Commit

Permalink
[Fizz] Don't perform work when closing (#30497)
Browse files Browse the repository at this point in the history
When a Fizz render is closing but not yet closed it's possible that
pinged tasks can spawn more work. The point of the closing state is to
allow time to start piping/reading the underlying stream but
semantically the render is finished at that point so work should no
longer happen.
  • Loading branch information
gnoff authored Jul 29, 2024
1 parent 93b12b8 commit 9938e24
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 1 deletion.
61 changes: 61 additions & 0 deletions packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3994,6 +3994,67 @@ describe('ReactDOMFizzServer', () => {
expect(headers.Link.length).toBe(306);
});

it('does not perform any additional work after fatally erroring', async () => {
let resolve: () => void;
const promise = new Promise(r => {
resolve = r;
});
function AsyncComp() {
React.use(promise);
return <DidRender>Async</DidRender>;
}

let didRender = false;
function DidRender({children}) {
didRender = true;
return children;
}

function ErrorComp() {
throw new Error('boom');
}

function App() {
return (
<div>
<Suspense fallback="loading...">
<AsyncComp />
</Suspense>
<ErrorComp />
</div>
);
}

let pipe;
const errors = [];
let didFatal = true;
await act(() => {
pipe = renderToPipeableStream(<App />, {
onError(error) {
errors.push(error.message);
},
onShellError(error) {
didFatal = true;
},
}).pipe;
});

expect(didRender).toBe(false);
await act(() => {
resolve();
});
expect(didRender).toBe(false);

const testWritable = new Stream.Writable();
await act(() => pipe(testWritable));
expect(didRender).toBe(false);
expect(didFatal).toBe(didFatal);
expect(errors).toEqual([
'boom',
'The destination stream errored while writing data.',
]);
});

describe('error escaping', () => {
it('escapes error hash, message, and component stack values in directly flushed errors (html escaping)', async () => {
window.__outlet = {};
Expand Down
2 changes: 1 addition & 1 deletion packages/react-server/src/ReactFizzServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -4215,7 +4215,7 @@ function retryReplayTask(request: Request, task: ReplayTask): void {
}

export function performWork(request: Request): void {
if (request.status === CLOSED) {
if (request.status === CLOSED || request.status === CLOSING) {
return;
}
const prevContext = getActiveContext();
Expand Down

0 comments on commit 9938e24

Please sign in to comment.