1. /**
    
  2.  * Copyright (c) Meta Platforms, Inc. and affiliates.
    
  3.  *
    
  4.  * This source code is licensed under the MIT license found in the
    
  5.  * LICENSE file in the root directory of this source tree.
    
  6.  *
    
  7.  * @emails react-core
    
  8.  */
    
  9. 
    
  10. 'use strict';
    
  11. 
    
  12. import {
    
  13.   getVisibleChildren,
    
  14.   insertNodesAndExecuteScripts,
    
  15. } from '../test-utils/FizzTestUtils';
    
  16. 
    
  17. // Polyfills for test environment
    
  18. global.ReadableStream =
    
  19.   require('web-streams-polyfill/ponyfill/es6').ReadableStream;
    
  20. global.TextEncoder = require('util').TextEncoder;
    
  21. 
    
  22. let React;
    
  23. let ReactDOM;
    
  24. let ReactDOMFizzServer;
    
  25. let ReactDOMFizzStatic;
    
  26. let Suspense;
    
  27. let container;
    
  28. 
    
  29. describe('ReactDOMFizzStaticFloat', () => {
    
  30.   beforeEach(() => {
    
  31.     jest.resetModules();
    
  32.     React = require('react');
    
  33.     ReactDOM = require('react-dom');
    
  34.     ReactDOMFizzServer = require('react-dom/server.browser');
    
  35.     if (__EXPERIMENTAL__) {
    
  36.       ReactDOMFizzStatic = require('react-dom/static.browser');
    
  37.     }
    
  38.     Suspense = React.Suspense;
    
  39.     container = document.createElement('div');
    
  40.     document.body.appendChild(container);
    
  41.   });
    
  42. 
    
  43.   afterEach(() => {
    
  44.     document.body.removeChild(container);
    
  45.   });
    
  46. 
    
  47.   async function readIntoContainer(stream) {
    
  48.     const reader = stream.getReader();
    
  49.     let result = '';
    
  50.     while (true) {
    
  51.       const {done, value} = await reader.read();
    
  52.       if (done) {
    
  53.         break;
    
  54.       }
    
  55.       result += Buffer.from(value).toString('utf8');
    
  56.     }
    
  57.     const temp = document.createElement('div');
    
  58.     temp.innerHTML = result;
    
  59.     await insertNodesAndExecuteScripts(temp, container, null);
    
  60.   }
    
  61. 
    
  62.   // @gate enablePostpone
    
  63.   it('should transfer connection credentials across prerender and resume for stylesheets, scripts, and moduleScripts', async () => {
    
  64.     let prerendering = true;
    
  65.     function Postpone() {
    
  66.       if (prerendering) {
    
  67.         React.unstable_postpone();
    
  68.       }
    
  69.       return (
    
  70.         <>
    
  71.           <link rel="stylesheet" href="style creds" precedence="default" />
    
  72.           <script async={true} src="script creds" data-meaningful="" />
    
  73.           <script
    
  74.             type="module"
    
  75.             async={true}
    
  76.             src="module creds"
    
  77.             data-meaningful=""
    
  78.           />
    
  79.           <link rel="stylesheet" href="style anon" precedence="default" />
    
  80.           <script async={true} src="script anon" data-meaningful="" />
    
  81.           <script
    
  82.             type="module"
    
  83.             async={true}
    
  84.             src="module default"
    
  85.             data-meaningful=""
    
  86.           />
    
  87.         </>
    
  88.       );
    
  89.     }
    
  90. 
    
  91.     function App() {
    
  92.       ReactDOM.preload('style creds', {
    
  93.         as: 'style',
    
  94.         crossOrigin: 'use-credentials',
    
  95.       });
    
  96.       ReactDOM.preload('script creds', {
    
  97.         as: 'script',
    
  98.         crossOrigin: 'use-credentials',
    
  99.         integrity: 'script-hash',
    
  100.       });
    
  101.       ReactDOM.preloadModule('module creds', {
    
  102.         crossOrigin: 'use-credentials',
    
  103.         integrity: 'module-hash',
    
  104.       });
    
  105.       ReactDOM.preload('style anon', {
    
  106.         as: 'style',
    
  107.         crossOrigin: 'anonymous',
    
  108.       });
    
  109.       ReactDOM.preload('script anon', {
    
  110.         as: 'script',
    
  111.         crossOrigin: 'foobar',
    
  112.       });
    
  113.       ReactDOM.preloadModule('module default', {
    
  114.         integrity: 'module-hash',
    
  115.       });
    
  116.       return (
    
  117.         <div>
    
  118.           <Suspense fallback="Loading...">
    
  119.             <Postpone />
    
  120.           </Suspense>
    
  121.         </div>
    
  122.       );
    
  123.     }
    
  124. 
    
  125.     jest.mock('script creds', () => {}, {
    
  126.       virtual: true,
    
  127.     });
    
  128.     jest.mock('module creds', () => {}, {
    
  129.       virtual: true,
    
  130.     });
    
  131.     jest.mock('script anon', () => {}, {
    
  132.       virtual: true,
    
  133.     });
    
  134.     jest.mock('module default', () => {}, {
    
  135.       virtual: true,
    
  136.     });
    
  137. 
    
  138.     const prerendered = await ReactDOMFizzStatic.prerender(<App />);
    
  139.     expect(prerendered.postponed).not.toBe(null);
    
  140. 
    
  141.     await readIntoContainer(prerendered.prelude);
    
  142. 
    
  143.     expect(getVisibleChildren(container)).toEqual([
    
  144.       <link
    
  145.         rel="preload"
    
  146.         as="style"
    
  147.         href="style creds"
    
  148.         crossorigin="use-credentials"
    
  149.       />,
    
  150.       <link
    
  151.         rel="preload"
    
  152.         as="script"
    
  153.         href="script creds"
    
  154.         crossorigin="use-credentials"
    
  155.         integrity="script-hash"
    
  156.       />,
    
  157.       <link
    
  158.         rel="modulepreload"
    
  159.         href="module creds"
    
  160.         crossorigin="use-credentials"
    
  161.         integrity="module-hash"
    
  162.       />,
    
  163.       <link rel="preload" as="style" href="style anon" crossorigin="" />,
    
  164.       <link rel="preload" as="script" href="script anon" crossorigin="" />,
    
  165.       <link
    
  166.         rel="modulepreload"
    
  167.         href="module default"
    
  168.         integrity="module-hash"
    
  169.       />,
    
  170.       <div>Loading...</div>,
    
  171.     ]);
    
  172. 
    
  173.     prerendering = false;
    
  174.     const content = await ReactDOMFizzServer.resume(
    
  175.       <App />,
    
  176.       JSON.parse(JSON.stringify(prerendered.postponed)),
    
  177.     );
    
  178. 
    
  179.     await readIntoContainer(content);
    
  180. 
    
  181.     // Dispatch load event to injected stylesheet
    
  182.     const linkCreds = document.querySelector(
    
  183.       'link[rel="stylesheet"][href="style creds"]',
    
  184.     );
    
  185.     const linkAnon = document.querySelector(
    
  186.       'link[rel="stylesheet"][href="style anon"]',
    
  187.     );
    
  188.     const event = document.createEvent('Events');
    
  189.     event.initEvent('load', true, true);
    
  190.     linkCreds.dispatchEvent(event);
    
  191.     linkAnon.dispatchEvent(event);
    
  192. 
    
  193.     // Wait for the instruction microtasks to flush.
    
  194.     await 0;
    
  195.     await 0;
    
  196. 
    
  197.     expect(getVisibleChildren(document)).toEqual(
    
  198.       <html>
    
  199.         <head>
    
  200.           <link
    
  201.             rel="stylesheet"
    
  202.             data-precedence="default"
    
  203.             href="style creds"
    
  204.             crossorigin="use-credentials"
    
  205.           />
    
  206.           <link
    
  207.             rel="stylesheet"
    
  208.             data-precedence="default"
    
  209.             href="style anon"
    
  210.             crossorigin=""
    
  211.           />
    
  212.         </head>
    
  213.         <body>
    
  214.           <div>
    
  215.             <link
    
  216.               rel="preload"
    
  217.               as="style"
    
  218.               href="style creds"
    
  219.               crossorigin="use-credentials"
    
  220.             />
    
  221.             <link
    
  222.               rel="preload"
    
  223.               as="script"
    
  224.               href="script creds"
    
  225.               crossorigin="use-credentials"
    
  226.               integrity="script-hash"
    
  227.             />
    
  228.             <link
    
  229.               rel="modulepreload"
    
  230.               href="module creds"
    
  231.               crossorigin="use-credentials"
    
  232.               integrity="module-hash"
    
  233.             />
    
  234.             <link rel="preload" as="style" href="style anon" crossorigin="" />
    
  235.             <link rel="preload" as="script" href="script anon" crossorigin="" />
    
  236.             <link
    
  237.               rel="modulepreload"
    
  238.               href="module default"
    
  239.               integrity="module-hash"
    
  240.             />
    
  241.             <div />
    
  242.             <script
    
  243.               async=""
    
  244.               src="script creds"
    
  245.               crossorigin="use-credentials"
    
  246.               integrity="script-hash"
    
  247.               data-meaningful=""
    
  248.             />
    
  249.             <script
    
  250.               type="module"
    
  251.               async=""
    
  252.               src="module creds"
    
  253.               crossorigin="use-credentials"
    
  254.               integrity="module-hash"
    
  255.               data-meaningful=""
    
  256.             />
    
  257.             <script
    
  258.               async=""
    
  259.               src="script anon"
    
  260.               crossorigin=""
    
  261.               data-meaningful=""
    
  262.             />
    
  263.             <script
    
  264.               type="module"
    
  265.               async=""
    
  266.               src="module default"
    
  267.               integrity="module-hash"
    
  268.               data-meaningful=""
    
  269.             />
    
  270.           </div>
    
  271.         </body>
    
  272.       </html>,
    
  273.     );
    
  274.   });
    
  275. });