From 7dc1a97d6787610a15d10823222c95540707df90 Mon Sep 17 00:00:00 2001 From: mofeiZ <34200447+mofeiZ@users.noreply.github.com> Date: Tue, 1 Nov 2022 12:04:50 -0400 Subject: [PATCH] [ServerRenderer] Setup for adding data attributes streaming format (#25567) --- .../src/__tests__/ReactDOMFizzServer-test.js | 222 ++++++++---------- .../src/__tests__/ReactDOMFloat-test.js | 113 ++++----- .../server/ReactDOMServerExternalRuntime.js | 11 +- .../react-dom/src/test-utils/FizzTestUtils.js | 123 ++++++++++ packages/shared/ReactFeatureFlags.js | 2 + 5 files changed, 291 insertions(+), 180 deletions(-) create mode 100644 packages/react-dom/src/test-utils/FizzTestUtils.js diff --git a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js index 62a0bc4d10294..2333f366f50e5 100644 --- a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js @@ -8,6 +8,7 @@ */ 'use strict'; +import {replaceScriptsAndMove, mergeOptions} from '../test-utils/FizzTestUtils'; let JSDOM; let Stream; @@ -30,6 +31,7 @@ let container; let buffer = ''; let hasErrored = false; let fatalError = undefined; +const renderOptions = {}; describe('ReactDOMFizzServer', () => { beforeEach(() => { @@ -134,17 +136,7 @@ describe('ReactDOMFizzServer', () => { container.nodeName === '#document' ? container.body : container; while (fakeBody.firstChild) { const node = fakeBody.firstChild; - if ( - node.nodeName === 'SCRIPT' && - (CSPnonce === null || node.getAttribute('nonce') === CSPnonce) - ) { - const script = document.createElement('script'); - script.textContent = node.textContent; - fakeBody.removeChild(node); - parent.appendChild(script); - } else { - parent.appendChild(node); - } + await replaceScriptsAndMove(window, CSPnonce, node, parent); } } @@ -170,6 +162,7 @@ describe('ReactDOMFizzServer', () => { document = jsdom.window.document; container = document; buffer = ''; + await replaceScriptsAndMove(window, CSPnonce, document.documentElement); } function getVisibleChildren(element) { @@ -179,6 +172,7 @@ describe('ReactDOMFizzServer', () => { if (node.nodeType === 1) { if ( node.tagName !== 'SCRIPT' && + node.tagName !== 'script' && node.tagName !== 'TEMPLATE' && node.tagName !== 'template' && !node.hasAttribute('hidden') && @@ -288,6 +282,13 @@ describe('ReactDOMFizzServer', () => { const As = as; return {readText(text)}; } + function renderToPipeableStream(jsx, options) { + // Merge options with renderOptions, which may contain featureFlag specific behavior + return ReactDOMFizzServer.renderToPipeableStream( + jsx, + mergeOptions(options, renderOptions), + ); + } it('should asynchronously load a lazy component', async () => { let resolveA; @@ -313,7 +314,7 @@ describe('ReactDOMFizzServer', () => { }; await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( + const {pipe} = renderToPipeableStream(
}> @@ -379,7 +380,7 @@ describe('ReactDOMFizzServer', () => { // Server-side const [App, resolve] = makeApp(); await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream(); + const {pipe} = renderToPipeableStream(); pipe(writable); }); expect(getVisibleChildren(container)).toEqual( @@ -432,7 +433,7 @@ describe('ReactDOMFizzServer', () => { }); await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( + const {pipe} = renderToPipeableStream(
}> @@ -492,13 +493,10 @@ describe('ReactDOMFizzServer', () => { loggedErrors.length = 0; await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( - , - { - bootstrapScriptContent: '__INIT__();', - onError, - }, - ); + const {pipe} = renderToPipeableStream(, { + bootstrapScriptContent: '__INIT__();', + onError, + }); pipe(writable); }); expect(loggedErrors).toEqual([]); @@ -554,7 +552,7 @@ describe('ReactDOMFizzServer', () => { }); await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( + const {pipe} = renderToPipeableStream(
}> {lazyElement} @@ -567,7 +565,7 @@ describe('ReactDOMFizzServer', () => { // Because there is no content inside the Suspense boundary that could've // been written, we expect to not see any additional partial data flushed // yet. - expect(container.firstChild.nextSibling).toBe(null); + expect(container.childNodes.length).toBe(1); await act(async () => { resolveElement({default: }); }); @@ -603,7 +601,7 @@ describe('ReactDOMFizzServer', () => { } await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( + const {pipe} = renderToPipeableStream( , { @@ -699,7 +697,7 @@ describe('ReactDOMFizzServer', () => { loggedErrors.length = 0; await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( + const {pipe} = renderToPipeableStream( , { @@ -767,7 +765,7 @@ describe('ReactDOMFizzServer', () => { loggedErrors.length = 0; await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( + const {pipe} = renderToPipeableStream( , { @@ -823,7 +821,7 @@ describe('ReactDOMFizzServer', () => { it('should asynchronously load the suspense boundary', async () => { await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( + const {pipe} = renderToPipeableStream(
}> @@ -862,7 +860,7 @@ describe('ReactDOMFizzServer', () => { }; await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream(, { + const {pipe} = renderToPipeableStream(, { bootstrapScriptContent: '__INIT__();', }); pipe(writable); @@ -936,7 +934,7 @@ describe('ReactDOMFizzServer', () => { // We originally suspend the boundary and start streaming the loading state. await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( + const {pipe} = renderToPipeableStream( , { @@ -1018,9 +1016,7 @@ describe('ReactDOMFizzServer', () => { // We originally suspend the boundary and start streaming the loading state. await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( - , - ); + const {pipe} = renderToPipeableStream(); pipe(writable); }); @@ -1093,7 +1089,7 @@ describe('ReactDOMFizzServer', () => { let controls; await act(async () => { - controls = ReactDOMFizzServer.renderToPipeableStream(, {onError}); + controls = renderToPipeableStream(, {onError}); controls.pipe(writable); }); @@ -1163,7 +1159,7 @@ describe('ReactDOMFizzServer', () => { }; await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( + const {pipe} = renderToPipeableStream( // We use two nested boundaries to flush out coverage of an old reentrancy bug. }> @@ -1187,7 +1183,7 @@ describe('ReactDOMFizzServer', () => { }); await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( + const {pipe} = renderToPipeableStream( }>
@@ -1283,7 +1279,7 @@ describe('ReactDOMFizzServer', () => { } await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream(); + const {pipe} = renderToPipeableStream(); pipe(writable); }); @@ -1370,7 +1366,7 @@ describe('ReactDOMFizzServer', () => { } await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream(); + const {pipe} = renderToPipeableStream(); pipe(writable); }); @@ -1423,7 +1419,7 @@ describe('ReactDOMFizzServer', () => { } await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( + const {pipe} = renderToPipeableStream( , { @@ -1509,7 +1505,7 @@ describe('ReactDOMFizzServer', () => { try { await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream(); + const {pipe} = renderToPipeableStream(); pipe(writable); }); @@ -1607,7 +1603,7 @@ describe('ReactDOMFizzServer', () => { } await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( + const {pipe} = renderToPipeableStream(
, ]}> @@ -1664,7 +1660,7 @@ describe('ReactDOMFizzServer', () => { } await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( + const {pipe} = renderToPipeableStream(
@@ -1725,7 +1721,7 @@ describe('ReactDOMFizzServer', () => { const loggedErrors = []; await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( + const {pipe} = renderToPipeableStream(
@@ -1793,7 +1789,7 @@ describe('ReactDOMFizzServer', () => { let controls; await act(async () => { - controls = ReactDOMFizzServer.renderToPipeableStream( + controls = renderToPipeableStream( , { @@ -1876,7 +1872,7 @@ describe('ReactDOMFizzServer', () => { it('should be able to abort the fallback if the main content finishes first', async () => { await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( + const {pipe} = renderToPipeableStream( }>
{ await jest.runAllTimers(); await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( - , - ); + const {pipe} = renderToPipeableStream(); pipe(writable); }); @@ -2085,7 +2079,7 @@ describe('ReactDOMFizzServer', () => { const loggedErrors = []; await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( + const {pipe} = renderToPipeableStream( , @@ -2170,7 +2164,7 @@ describe('ReactDOMFizzServer', () => { } const loggedErrors = []; await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( + const {pipe} = renderToPipeableStream( , @@ -2259,7 +2253,7 @@ describe('ReactDOMFizzServer', () => { } await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream(); + const {pipe} = renderToPipeableStream(); pipe(writable); }); expect(Scheduler).toHaveYielded(['Yay!']); @@ -2349,7 +2343,7 @@ describe('ReactDOMFizzServer', () => { } await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream(); + const {pipe} = renderToPipeableStream(); pipe(writable); }); expect(Scheduler).toHaveYielded(['Yay!']); @@ -2439,7 +2433,7 @@ describe('ReactDOMFizzServer', () => { } await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream(); + const {pipe} = renderToPipeableStream(); pipe(writable); }); expect(Scheduler).toHaveYielded(['Yay!']); @@ -2492,7 +2486,7 @@ describe('ReactDOMFizzServer', () => { ); } await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream(, { + const {pipe} = renderToPipeableStream(, { onError(error) { Scheduler.unstable_yieldValue('[s!] ' + error.message); }, @@ -2577,14 +2571,11 @@ describe('ReactDOMFizzServer', () => { ); } await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( - , - { - onError(error) { - Scheduler.unstable_yieldValue('[s!] ' + error.message); - }, + const {pipe} = renderToPipeableStream(, { + onError(error) { + Scheduler.unstable_yieldValue('[s!] ' + error.message); }, - ); + }); pipe(writable); }); expect(Scheduler).toHaveYielded(['[s!] Oops.']); @@ -2678,7 +2669,7 @@ describe('ReactDOMFizzServer', () => { } await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( + const {pipe} = renderToPipeableStream( , { onError(error) { @@ -2807,7 +2798,7 @@ describe('ReactDOMFizzServer', () => { } await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream(); + const {pipe} = renderToPipeableStream(); pipe(writable); }); expect(Scheduler).toHaveYielded(['Yay!']); @@ -2959,7 +2950,7 @@ describe('ReactDOMFizzServer', () => { } await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream(); + const {pipe} = renderToPipeableStream(); pipe(writable); }); expect(Scheduler).toHaveYielded(['A', 'B']); @@ -3025,7 +3016,7 @@ describe('ReactDOMFizzServer', () => { } await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream(); + const {pipe} = renderToPipeableStream(); pipe(writable); }); @@ -3047,9 +3038,7 @@ describe('ReactDOMFizzServer', () => { ]).map(item =>
  • {item.get('name')}
  • ); await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( -
      {mappedJSX}
    , - ); + const {pipe} = renderToPipeableStream(
      {mappedJSX}
    ); pipe(writable); }); expect(getVisibleChildren(container)).toEqual( @@ -3081,10 +3070,7 @@ describe('ReactDOMFizzServer', () => { let abort; const loggedErrors = []; await act(async () => { - const { - pipe, - abort: abortImpl, - } = ReactDOMFizzServer.renderToPipeableStream(, { + const {pipe, abort: abortImpl} = renderToPipeableStream(, { onError(error) { // In this test we contrive erroring with strings so we push the error whereas in most // other tests we contrive erroring with Errors and push the message. @@ -3167,10 +3153,7 @@ describe('ReactDOMFizzServer', () => { let abort; const loggedErrors = []; await act(async () => { - const { - pipe, - abort: abortImpl, - } = ReactDOMFizzServer.renderToPipeableStream(, { + const {pipe, abort: abortImpl} = renderToPipeableStream(, { onError(error) { loggedErrors.push(error.message); return 'a digest'; @@ -3232,7 +3215,7 @@ describe('ReactDOMFizzServer', () => { it('warns in dev if you access digest from errorInfo in onRecoverableError', async () => { await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( + const {pipe} = renderToPipeableStream(
    @@ -3309,7 +3292,7 @@ describe('ReactDOMFizzServer', () => { } await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream(, { + const {pipe} = renderToPipeableStream(, { onError, }); pipe(writable); @@ -3357,7 +3340,7 @@ describe('ReactDOMFizzServer', () => { } await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream(, { + const {pipe} = renderToPipeableStream(, { onError, }); pipe(writable); @@ -3397,7 +3380,7 @@ describe('ReactDOMFizzServer', () => { loggedErrors.length = 0; await act(async () => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream(, { + const {pipe} = renderToPipeableStream(, { onError, }); pipe(writable); @@ -3435,7 +3418,7 @@ describe('ReactDOMFizzServer', () => { it('accepts an integrity property for bootstrapScripts and bootstrapModules', async () => { await actIntoEmptyDocument(() => { - const {pipe} = ReactDOMFizzServer.renderToPipeableStream( + const {pipe} = renderToPipeableStream( @@ -3494,7 +3477,7 @@ describe('ReactDOMFizzServer', () => { const stringWithScriptsInIt = 'prescription pre