Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fizz] Start initial work immediately #31079

Merged
merged 1 commit into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8119,7 +8119,7 @@ describe('ReactDOMFizzServer', () => {

prerendering = false;

const resumed = await ReactDOMFizzServer.resumeToPipeableStream(
const resumed = ReactDOMFizzServer.resumeToPipeableStream(
<App />,
JSON.parse(JSON.stringify(prerendered.postponed)),
{
Expand Down Expand Up @@ -8187,7 +8187,7 @@ describe('ReactDOMFizzServer', () => {
function onPostpone(reason) {
postpones.push(reason);
}
const result = await renderToPipeableStream(<App />, {
const result = renderToPipeableStream(<App />, {
onError,
onShellError,
onPostpone,
Expand Down
237 changes: 124 additions & 113 deletions packages/react-dom/src/__tests__/ReactDOMFizzServerNode-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ let Stream;
let React;
let ReactDOMFizzServer;
let Suspense;
let act;

describe('ReactDOMFizzServerNode', () => {
beforeEach(() => {
Expand All @@ -22,6 +23,7 @@ describe('ReactDOMFizzServerNode', () => {
ReactDOMFizzServer = require('react-dom/server');
Stream = require('stream');
Suspense = React.Suspense;
act = require('internal-test-utils').act;
});

function getTestWritable() {
Expand Down Expand Up @@ -54,54 +56,59 @@ describe('ReactDOMFizzServerNode', () => {
throw theInfinitePromise;
}

it('should call renderToPipeableStream', () => {
it('should call renderToPipeableStream', async () => {
const {writable, output} = getTestWritable();
const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
<div>hello world</div>,
);
pipe(writable);
jest.runAllTimers();
await act(() => {
const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
<div>hello world</div>,
);
pipe(writable);
});
expect(output.result).toMatchInlineSnapshot(`"<div>hello world</div>"`);
});

it('should emit DOCTYPE at the root of the document', () => {
it('should emit DOCTYPE at the root of the document', async () => {
const {writable, output} = getTestWritable();
const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
<html>
<body>hello world</body>
</html>,
);
pipe(writable);
jest.runAllTimers();
await act(() => {
const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
<html>
<body>hello world</body>
</html>,
);
pipe(writable);
});
// with Float, we emit empty heads if they are elided when rendering <html>
expect(output.result).toMatchInlineSnapshot(
`"<!DOCTYPE html><html><head></head><body>hello world</body></html>"`,
);
});

it('should emit bootstrap script src at the end', () => {
it('should emit bootstrap script src at the end', async () => {
const {writable, output} = getTestWritable();
const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
<div>hello world</div>,
{
bootstrapScriptContent: 'INIT();',
bootstrapScripts: ['init.js'],
bootstrapModules: ['init.mjs'],
},
);
pipe(writable);
jest.runAllTimers();
await act(() => {
const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
<div>hello world</div>,
{
bootstrapScriptContent: 'INIT();',
bootstrapScripts: ['init.js'],
bootstrapModules: ['init.mjs'],
},
);
pipe(writable);
});
expect(output.result).toMatchInlineSnapshot(
`"<link rel="preload" as="script" fetchPriority="low" href="init.js"/><link rel="modulepreload" fetchPriority="low" href="init.mjs"/><div>hello world</div><script>INIT();</script><script src="init.js" async=""></script><script type="module" src="init.mjs" async=""></script>"`,
);
});

it('should start writing after pipe', () => {
it('should start writing after pipe', async () => {
const {writable, output} = getTestWritable();
const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
<div>hello world</div>,
);
jest.runAllTimers();
let pipe;
await act(() => {
pipe = ReactDOMFizzServer.renderToPipeableStream(
<div>hello world</div>,
).pipe;
});
// First we write our header.
output.result +=
'<!doctype html><html><head><title>test</title><head><body>';
Expand Down Expand Up @@ -281,24 +288,26 @@ describe('ReactDOMFizzServerNode', () => {
let isCompleteCalls = 0;
const errors = [];
const {writable, output, completed} = getTestWritable();
const {pipe, abort} = ReactDOMFizzServer.renderToPipeableStream(
<div>
<Suspense fallback={<div>Loading</div>}>
<InfiniteSuspend />
</Suspense>
</div>,
{
onError(x) {
errors.push(x.message);
},
onAllReady() {
isCompleteCalls++;
let abort;
await act(() => {
const pipeable = ReactDOMFizzServer.renderToPipeableStream(
<div>
<Suspense fallback={<div>Loading</div>}>
<InfiniteSuspend />
</Suspense>
</div>,
{
onError(x) {
errors.push(x.message);
},
onAllReady() {
isCompleteCalls++;
},
},
},
);
pipe(writable);

jest.runAllTimers();
);
pipeable.pipe(writable);
abort = pipeable.abort;
});

expect(output.result).toContain('Loading');
expect(isCompleteCalls).toBe(0);
Expand Down Expand Up @@ -360,26 +369,28 @@ describe('ReactDOMFizzServerNode', () => {
let isCompleteCalls = 0;
const errors = [];
const {writable, output, completed} = getTestWritable();
const {pipe, abort} = ReactDOMFizzServer.renderToPipeableStream(
<div>
<Suspense fallback="Loading">
<Suspense fallback={<InfiniteSuspend />}>
<InfiniteSuspend />
let abort;
await act(() => {
const pipeable = ReactDOMFizzServer.renderToPipeableStream(
<div>
<Suspense fallback="Loading">
<Suspense fallback={<InfiniteSuspend />}>
<InfiniteSuspend />
</Suspense>
</Suspense>
</Suspense>
</div>,
{
onError(x) {
errors.push(x.message);
},
onAllReady() {
isCompleteCalls++;
</div>,
{
onError(x) {
errors.push(x.message);
},
onAllReady() {
isCompleteCalls++;
},
},
},
);
pipe(writable);

jest.runAllTimers();
);
pipeable.pipe(writable);
abort = pipeable.abort;
});

expect(output.result).toContain('Loading');
expect(isCompleteCalls).toBe(0);
Expand Down Expand Up @@ -428,15 +439,15 @@ describe('ReactDOMFizzServerNode', () => {

const client = new DelayClient();
const {writable, output, completed} = getTestWritable();
ReactDOMFizzServer.renderToPipeableStream(
<DelayContext.Provider value={client}>
<Suspense fallback="loading">
<Component />
</Suspense>
</DelayContext.Provider>,
).pipe(writable);

jest.runAllTimers();
await act(() => {
ReactDOMFizzServer.renderToPipeableStream(
<DelayContext.Provider value={client}>
<Suspense fallback="loading">
<Component />
</Suspense>
</DelayContext.Provider>,
).pipe(writable);
});

expect(output.error).toBe(undefined);
expect(output.result).toContain('loading');
Expand Down Expand Up @@ -481,29 +492,28 @@ describe('ReactDOMFizzServerNode', () => {
output: output0,
completed: completed0,
} = getTestWritable();
ReactDOMFizzServer.renderToPipeableStream(
<DelayContext.Provider value={client0}>
<Suspense fallback="loading">
<Component />
</Suspense>
</DelayContext.Provider>,
).pipe(writable0);

const client1 = new DelayClient();
const {
writable: writable1,
output: output1,
completed: completed1,
} = getTestWritable();
ReactDOMFizzServer.renderToPipeableStream(
<DelayContext.Provider value={client1}>
<Suspense fallback="loading">
<Component />
</Suspense>
</DelayContext.Provider>,
).pipe(writable1);

jest.runAllTimers();
await act(() => {
ReactDOMFizzServer.renderToPipeableStream(
<DelayContext.Provider value={client0}>
<Suspense fallback="loading">
<Component />
</Suspense>
</DelayContext.Provider>,
).pipe(writable0);
ReactDOMFizzServer.renderToPipeableStream(
<DelayContext.Provider value={client1}>
<Suspense fallback="loading">
<Component />
</Suspense>
</DelayContext.Provider>,
).pipe(writable1);
});

expect(output0.error).toBe(undefined);
expect(output0.result).toContain('loading');
Expand Down Expand Up @@ -552,22 +562,22 @@ describe('ReactDOMFizzServerNode', () => {

const client = new DelayClient();
const {writable, output, completed} = getTestWritable();
ReactDOMFizzServer.renderToPipeableStream(
<>
<DelayContext.Provider value={client}>
<Suspense fallback="loading">
<Component />
</Suspense>
</DelayContext.Provider>
<DelayContext.Provider value={client}>
<Suspense fallback="loading">
<Component />
</Suspense>
</DelayContext.Provider>
</>,
).pipe(writable);

jest.runAllTimers();
await act(() => {
ReactDOMFizzServer.renderToPipeableStream(
<>
<DelayContext.Provider value={client}>
<Suspense fallback="loading">
<Component />
</Suspense>
</DelayContext.Provider>
<DelayContext.Provider value={client}>
<Suspense fallback="loading">
<Component />
</Suspense>
</DelayContext.Provider>
</>,
).pipe(writable);
});

expect(output.error).toBe(undefined);
expect(output.result).toContain('loading');
Expand Down Expand Up @@ -630,13 +640,14 @@ describe('ReactDOMFizzServerNode', () => {
expect(isComplete).toBe(true);
});

it('should encode multibyte characters correctly without nulls (#24985)', () => {
it('should encode multibyte characters correctly without nulls (#24985)', async () => {
const {writable, output} = getTestWritable();
const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
<div>{Array(700).fill('ののの')}</div>,
);
pipe(writable);
jest.runAllTimers();
await act(() => {
const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
<div>{Array(700).fill('ののの')}</div>,
);
pipe(writable);
});
expect(output.result.indexOf('\u0000')).toBe(-1);
expect(output.result).toEqual(
'<div>' + Array(700).fill('ののの').join('<!-- -->') + '</div>',
Expand Down
Loading
Loading