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.  * @flow
    
  8.  */
    
  9. 
    
  10. import type {ReactNodeList, ReactCustomFormAction} from 'shared/ReactTypes';
    
  11. import type {
    
  12.   CrossOriginEnum,
    
  13.   PreloadImplOptions,
    
  14.   PreloadModuleImplOptions,
    
  15.   PreinitStyleOptions,
    
  16.   PreinitScriptOptions,
    
  17.   PreinitModuleScriptOptions,
    
  18.   ImportMap,
    
  19. } from 'react-dom/src/shared/ReactDOMTypes';
    
  20. 
    
  21. import {
    
  22.   checkHtmlStringCoercion,
    
  23.   checkCSSPropertyStringCoercion,
    
  24.   checkAttributeStringCoercion,
    
  25. } from 'shared/CheckStringCoercion';
    
  26. 
    
  27. import {Children} from 'react';
    
  28. 
    
  29. import {
    
  30.   enableFilterEmptyStringAttributesDOM,
    
  31.   enableCustomElementPropertySupport,
    
  32.   enableFloat,
    
  33.   enableFormActions,
    
  34.   enableFizzExternalRuntime,
    
  35. } from 'shared/ReactFeatureFlags';
    
  36. 
    
  37. import type {
    
  38.   Destination,
    
  39.   Chunk,
    
  40.   PrecomputedChunk,
    
  41. } from 'react-server/src/ReactServerStreamConfig';
    
  42. 
    
  43. import type {FormStatus} from '../shared/ReactDOMFormActions';
    
  44. 
    
  45. import {
    
  46.   writeChunk,
    
  47.   writeChunkAndReturn,
    
  48.   stringToChunk,
    
  49.   stringToPrecomputedChunk,
    
  50.   clonePrecomputedChunk,
    
  51. } from 'react-server/src/ReactServerStreamConfig';
    
  52. import {
    
  53.   resolveRequest,
    
  54.   getResumableState,
    
  55.   getRenderState,
    
  56.   flushResources,
    
  57. } from 'react-server/src/ReactFizzServer';
    
  58. 
    
  59. import isAttributeNameSafe from '../shared/isAttributeNameSafe';
    
  60. import isUnitlessNumber from '../shared/isUnitlessNumber';
    
  61. import getAttributeAlias from '../shared/getAttributeAlias';
    
  62. 
    
  63. import {checkControlledValueProps} from '../shared/ReactControlledValuePropTypes';
    
  64. import {validateProperties as validateARIAProperties} from '../shared/ReactDOMInvalidARIAHook';
    
  65. import {validateProperties as validateInputProperties} from '../shared/ReactDOMNullInputValuePropHook';
    
  66. import {validateProperties as validateUnknownProperties} from '../shared/ReactDOMUnknownPropertyHook';
    
  67. import warnValidStyle from '../shared/warnValidStyle';
    
  68. 
    
  69. import escapeTextForBrowser from './escapeTextForBrowser';
    
  70. import hyphenateStyleName from '../shared/hyphenateStyleName';
    
  71. import hasOwnProperty from 'shared/hasOwnProperty';
    
  72. import sanitizeURL from '../shared/sanitizeURL';
    
  73. import isArray from 'shared/isArray';
    
  74. 
    
  75. import {
    
  76.   clientRenderBoundary as clientRenderFunction,
    
  77.   completeBoundary as completeBoundaryFunction,
    
  78.   completeBoundaryWithStyles as styleInsertionFunction,
    
  79.   completeSegment as completeSegmentFunction,
    
  80.   formReplaying as formReplayingRuntime,
    
  81. } from './fizz-instruction-set/ReactDOMFizzInstructionSetInlineCodeStrings';
    
  82. 
    
  83. import {getValueDescriptorExpectingObjectForWarning} from '../shared/ReactDOMResourceValidation';
    
  84. 
    
  85. import {NotPending} from '../shared/ReactDOMFormActions';
    
  86. 
    
  87. import ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals';
    
  88. const ReactDOMCurrentDispatcher = ReactDOMSharedInternals.Dispatcher;
    
  89. 
    
  90. const ReactDOMServerDispatcher = {
    
  91.   prefetchDNS,
    
  92.   preconnect,
    
  93.   preload,
    
  94.   preloadModule,
    
  95.   preinitStyle,
    
  96.   preinitScript,
    
  97.   preinitModuleScript,
    
  98. };
    
  99. 
    
  100. export function prepareHostDispatcher() {
    
  101.   ReactDOMCurrentDispatcher.current = ReactDOMServerDispatcher;
    
  102. }
    
  103. 
    
  104. // Used to distinguish these contexts from ones used in other renderers.
    
  105. // E.g. this can be used to distinguish legacy renderers from this modern one.
    
  106. export const isPrimaryRenderer = true;
    
  107. 
    
  108. export type StreamingFormat = 0 | 1;
    
  109. const ScriptStreamingFormat: StreamingFormat = 0;
    
  110. const DataStreamingFormat: StreamingFormat = 1;
    
  111. 
    
  112. export type InstructionState = number;
    
  113. const NothingSent /*                      */ = 0b00000;
    
  114. const SentCompleteSegmentFunction /*      */ = 0b00001;
    
  115. const SentCompleteBoundaryFunction /*     */ = 0b00010;
    
  116. const SentClientRenderFunction /*         */ = 0b00100;
    
  117. const SentStyleInsertionFunction /*       */ = 0b01000;
    
  118. const SentFormReplayingRuntime /*         */ = 0b10000;
    
  119. 
    
  120. // Per request, global state that is not contextual to the rendering subtree.
    
  121. // This cannot be resumed and therefore should only contain things that are
    
  122. // temporary working state or are never used in the prerender pass.
    
  123. export type RenderState = {
    
  124.   // These can be recreated from resumable state.
    
  125.   placeholderPrefix: PrecomputedChunk,
    
  126.   segmentPrefix: PrecomputedChunk,
    
  127.   boundaryPrefix: PrecomputedChunk,
    
  128. 
    
  129.   // inline script streaming format, unused if using external runtime / data
    
  130.   startInlineScript: PrecomputedChunk,
    
  131. 
    
  132.   // the preamble must always flush before resuming, so all these chunks must
    
  133.   // be null or empty when resuming.
    
  134. 
    
  135.   // preamble chunks
    
  136.   htmlChunks: null | Array<Chunk | PrecomputedChunk>,
    
  137.   headChunks: null | Array<Chunk | PrecomputedChunk>,
    
  138. 
    
  139.   // external runtime script chunks
    
  140.   externalRuntimeScript: null | ExternalRuntimeScript,
    
  141.   bootstrapChunks: Array<Chunk | PrecomputedChunk>,
    
  142. 
    
  143.   // Hoistable chunks
    
  144.   charsetChunks: Array<Chunk | PrecomputedChunk>,
    
  145.   preconnectChunks: Array<Chunk | PrecomputedChunk>,
    
  146.   importMapChunks: Array<Chunk | PrecomputedChunk>,
    
  147.   preloadChunks: Array<Chunk | PrecomputedChunk>,
    
  148.   hoistableChunks: Array<Chunk | PrecomputedChunk>,
    
  149. 
    
  150.   // Flushing queues for Resource dependencies
    
  151.   preconnects: Set<Resource>,
    
  152.   fontPreloads: Set<Resource>,
    
  153.   highImagePreloads: Set<Resource>,
    
  154.   // usedImagePreloads: Set<PreloadResource>,
    
  155.   styles: Map<string, StyleQueue>,
    
  156.   bootstrapScripts: Set<Resource>,
    
  157.   scripts: Set<Resource>,
    
  158.   bulkPreloads: Set<Resource>,
    
  159. 
    
  160.   // Temporarily keeps track of key to preload resources before shell flushes.
    
  161.   preloads: {
    
  162.     images: Map<string, Resource>,
    
  163.     stylesheets: Map<string, Resource>,
    
  164.     scripts: Map<string, Resource>,
    
  165.     moduleScripts: Map<string, Resource>,
    
  166.   },
    
  167. 
    
  168.   // Module-global-like reference for current boundary resources
    
  169.   boundaryResources: ?BoundaryResources,
    
  170. 
    
  171.   // Module-global-like reference for flushing/hoisting state of style resources
    
  172.   // We need to track whether the current request has flushed any style resources
    
  173.   // without sending an instruction to hoist them. we do that here
    
  174.   stylesToHoist: boolean,
    
  175. 
    
  176.   // We allow the legacy renderer to extend this object.
    
  177. 
    
  178.   ...
    
  179. };
    
  180. 
    
  181. type Exists = null;
    
  182. type Preloaded = [];
    
  183. // Credentials here are things that affect whether a browser will make a request
    
  184. // as well as things that affect which connection the browser will use for that request.
    
  185. // We want these to be aligned across preloads and resources because otherwise the preload
    
  186. // will be wasted.
    
  187. // We investigated whether referrerPolicy should be included here but from experimentation
    
  188. // it seems that browsers do not treat this as part of the http cache key and does not affect
    
  189. // which connection is used.
    
  190. type PreloadedWithCredentials = [
    
  191.   /* crossOrigin */ ?string,
    
  192.   /* integrity */ ?string,
    
  193. ];
    
  194. 
    
  195. const EXISTS: Exists = null;
    
  196. // This constant is to mark preloads that have no unique credentials
    
  197. // to convey. It should never be checked by identity and we should not
    
  198. // assume Preload values in ResumableState equal this value because they
    
  199. // will have come from some parsed input.
    
  200. const PRELOAD_NO_CREDS: Preloaded = [];
    
  201. if (__DEV__) {
    
  202.   Object.freeze(PRELOAD_NO_CREDS);
    
  203. }
    
  204. 
    
  205. // Per response, global state that is not contextual to the rendering subtree.
    
  206. // This is resumable and therefore should be serializable.
    
  207. export type ResumableState = {
    
  208.   idPrefix: string,
    
  209.   nextFormID: number,
    
  210.   streamingFormat: StreamingFormat,
    
  211. 
    
  212.   // state for script streaming format, unused if using external runtime / data
    
  213.   instructions: InstructionState,
    
  214. 
    
  215.   // postamble state
    
  216.   hasBody: boolean,
    
  217.   hasHtml: boolean,
    
  218. 
    
  219.   // Resources - Request local cache
    
  220.   unknownResources: {
    
  221.     [asType: string]: {
    
  222.       [href: string]: Preloaded,
    
  223.     },
    
  224.   },
    
  225.   dnsResources: {[key: string]: Exists},
    
  226.   connectResources: {
    
  227.     default: {[key: string]: Exists},
    
  228.     anonymous: {[key: string]: Exists},
    
  229.     credentials: {[key: string]: Exists},
    
  230.   },
    
  231.   imageResources: {
    
  232.     [key: string]: Preloaded,
    
  233.   },
    
  234.   styleResources: {
    
  235.     [key: string]: Exists | Preloaded | PreloadedWithCredentials,
    
  236.   },
    
  237.   scriptResources: {
    
  238.     [key: string]: Exists | Preloaded | PreloadedWithCredentials,
    
  239.   },
    
  240.   moduleUnknownResources: {
    
  241.     [asType: string]: {
    
  242.       [href: string]: Preloaded,
    
  243.     },
    
  244.   },
    
  245.   moduleScriptResources: {
    
  246.     [key: string]: Exists | Preloaded | PreloadedWithCredentials,
    
  247.   },
    
  248. };
    
  249. 
    
  250. const dataElementQuotedEnd = stringToPrecomputedChunk('"></template>');
    
  251. 
    
  252. const startInlineScript = stringToPrecomputedChunk('<script>');
    
  253. const endInlineScript = stringToPrecomputedChunk('</script>');
    
  254. 
    
  255. const startScriptSrc = stringToPrecomputedChunk('<script src="');
    
  256. const startModuleSrc = stringToPrecomputedChunk('<script type="module" src="');
    
  257. const scriptNonce = stringToPrecomputedChunk('" nonce="');
    
  258. const scriptIntegirty = stringToPrecomputedChunk('" integrity="');
    
  259. const scriptCrossOrigin = stringToPrecomputedChunk('" crossorigin="');
    
  260. const endAsyncScript = stringToPrecomputedChunk('" async=""></script>');
    
  261. 
    
  262. /**
    
  263.  * This escaping function is designed to work with bootstrapScriptContent and importMap only.
    
  264.  * because we know we are escaping the entire script. We can avoid for instance
    
  265.  * escaping html comment string sequences that are valid javascript as well because
    
  266.  * if there are no sebsequent <script sequences the html parser will never enter
    
  267.  * script data double escaped state (see: https://www.w3.org/TR/html53/syntax.html#script-data-double-escaped-state)
    
  268.  *
    
  269.  * While untrusted script content should be made safe before using this api it will
    
  270.  * ensure that the script cannot be early terminated or never terminated state
    
  271.  */
    
  272. function escapeBootstrapAndImportMapScriptContent(scriptText: string) {
    
  273.   if (__DEV__) {
    
  274.     checkHtmlStringCoercion(scriptText);
    
  275.   }
    
  276.   return ('' + scriptText).replace(scriptRegex, scriptReplacer);
    
  277. }
    
  278. const scriptRegex = /(<\/|<)(s)(cript)/gi;
    
  279. const scriptReplacer = (
    
  280.   match: string,
    
  281.   prefix: string,
    
  282.   s: string,
    
  283.   suffix: string,
    
  284. ) => `${prefix}${s === 's' ? '\\u0073' : '\\u0053'}${suffix}`;
    
  285. 
    
  286. export type BootstrapScriptDescriptor = {
    
  287.   src: string,
    
  288.   integrity?: string,
    
  289.   crossOrigin?: string,
    
  290. };
    
  291. export type ExternalRuntimeScript = {
    
  292.   src: string,
    
  293.   chunks: Array<Chunk | PrecomputedChunk>,
    
  294. };
    
  295. 
    
  296. const importMapScriptStart = stringToPrecomputedChunk(
    
  297.   '<script type="importmap">',
    
  298. );
    
  299. const importMapScriptEnd = stringToPrecomputedChunk('</script>');
    
  300. 
    
  301. // Allows us to keep track of what we've already written so we can refer back to it.
    
  302. // if passed externalRuntimeConfig and the enableFizzExternalRuntime feature flag
    
  303. // is set, the server will send instructions via data attributes (instead of inline scripts)
    
  304. export function createRenderState(
    
  305.   resumableState: ResumableState,
    
  306.   nonce: string | void,
    
  307.   bootstrapScriptContent: string | void,
    
  308.   bootstrapScripts: $ReadOnlyArray<string | BootstrapScriptDescriptor> | void,
    
  309.   bootstrapModules: $ReadOnlyArray<string | BootstrapScriptDescriptor> | void,
    
  310.   externalRuntimeConfig: string | BootstrapScriptDescriptor | void,
    
  311.   importMap: ImportMap | void,
    
  312. ): RenderState {
    
  313.   const inlineScriptWithNonce =
    
  314.     nonce === undefined
    
  315.       ? startInlineScript
    
  316.       : stringToPrecomputedChunk(
    
  317.           '<script nonce="' + escapeTextForBrowser(nonce) + '">',
    
  318.         );
    
  319.   const idPrefix = resumableState.idPrefix;
    
  320. 
    
  321.   const bootstrapChunks: Array<Chunk | PrecomputedChunk> = [];
    
  322.   let externalRuntimeScript: null | ExternalRuntimeScript = null;
    
  323.   if (bootstrapScriptContent !== undefined) {
    
  324.     bootstrapChunks.push(
    
  325.       inlineScriptWithNonce,
    
  326.       stringToChunk(
    
  327.         escapeBootstrapAndImportMapScriptContent(bootstrapScriptContent),
    
  328.       ),
    
  329.       endInlineScript,
    
  330.     );
    
  331.   }
    
  332.   if (enableFizzExternalRuntime) {
    
  333.     if (!enableFloat) {
    
  334.       throw new Error(
    
  335.         'enableFizzExternalRuntime without enableFloat is not supported. This should never appear in production, since it means you are using a misconfigured React bundle.',
    
  336.       );
    
  337.     }
    
  338.     if (externalRuntimeConfig !== undefined) {
    
  339.       if (typeof externalRuntimeConfig === 'string') {
    
  340.         externalRuntimeScript = {
    
  341.           src: externalRuntimeConfig,
    
  342.           chunks: [],
    
  343.         };
    
  344.         pushScriptImpl(externalRuntimeScript.chunks, {
    
  345.           src: externalRuntimeConfig,
    
  346.           async: true,
    
  347.           integrity: undefined,
    
  348.           nonce: nonce,
    
  349.         });
    
  350.       } else {
    
  351.         externalRuntimeScript = {
    
  352.           src: externalRuntimeConfig.src,
    
  353.           chunks: [],
    
  354.         };
    
  355.         pushScriptImpl(externalRuntimeScript.chunks, {
    
  356.           src: externalRuntimeConfig.src,
    
  357.           async: true,
    
  358.           integrity: externalRuntimeConfig.integrity,
    
  359.           nonce: nonce,
    
  360.         });
    
  361.       }
    
  362.     }
    
  363.   }
    
  364. 
    
  365.   const importMapChunks: Array<Chunk | PrecomputedChunk> = [];
    
  366.   if (importMap !== undefined) {
    
  367.     const map = importMap;
    
  368.     importMapChunks.push(importMapScriptStart);
    
  369.     importMapChunks.push(
    
  370.       stringToChunk(
    
  371.         escapeBootstrapAndImportMapScriptContent(JSON.stringify(map)),
    
  372.       ),
    
  373.     );
    
  374.     importMapChunks.push(importMapScriptEnd);
    
  375.   }
    
  376.   const renderState: RenderState = {
    
  377.     placeholderPrefix: stringToPrecomputedChunk(idPrefix + 'P:'),
    
  378.     segmentPrefix: stringToPrecomputedChunk(idPrefix + 'S:'),
    
  379.     boundaryPrefix: stringToPrecomputedChunk(idPrefix + 'B:'),
    
  380.     startInlineScript: inlineScriptWithNonce,
    
  381.     htmlChunks: null,
    
  382.     headChunks: null,
    
  383. 
    
  384.     externalRuntimeScript: externalRuntimeScript,
    
  385.     bootstrapChunks: bootstrapChunks,
    
  386. 
    
  387.     charsetChunks: [],
    
  388.     preconnectChunks: [],
    
  389.     importMapChunks,
    
  390.     preloadChunks: [],
    
  391.     hoistableChunks: [],
    
  392.     // cleared on flush
    
  393.     preconnects: new Set(),
    
  394.     fontPreloads: new Set(),
    
  395.     highImagePreloads: new Set(),
    
  396.     // usedImagePreloads: new Set(),
    
  397.     styles: new Map(),
    
  398.     bootstrapScripts: new Set(),
    
  399.     scripts: new Set(),
    
  400.     bulkPreloads: new Set(),
    
  401. 
    
  402.     preloads: {
    
  403.       images: new Map(),
    
  404.       stylesheets: new Map(),
    
  405.       scripts: new Map(),
    
  406.       moduleScripts: new Map(),
    
  407.     },
    
  408. 
    
  409.     nonce,
    
  410.     // like a module global for currently rendering boundary
    
  411.     boundaryResources: null,
    
  412.     stylesToHoist: false,
    
  413.   };
    
  414. 
    
  415.   if (bootstrapScripts !== undefined) {
    
  416.     for (let i = 0; i < bootstrapScripts.length; i++) {
    
  417.       const scriptConfig = bootstrapScripts[i];
    
  418.       let src, crossOrigin, integrity;
    
  419.       const props: PreloadAsProps = ({
    
  420.         rel: 'preload',
    
  421.         as: 'script',
    
  422.         fetchPriority: 'low',
    
  423.         nonce,
    
  424.       }: any);
    
  425.       if (typeof scriptConfig === 'string') {
    
  426.         props.href = src = scriptConfig;
    
  427.       } else {
    
  428.         props.href = src = scriptConfig.src;
    
  429.         props.integrity = integrity =
    
  430.           typeof scriptConfig.integrity === 'string'
    
  431.             ? scriptConfig.integrity
    
  432.             : undefined;
    
  433.         props.crossOrigin = crossOrigin =
    
  434.           typeof scriptConfig === 'string' || scriptConfig.crossOrigin == null
    
  435.             ? undefined
    
  436.             : scriptConfig.crossOrigin === 'use-credentials'
    
  437.             ? 'use-credentials'
    
  438.             : '';
    
  439.       }
    
  440. 
    
  441.       preloadBootstrapScriptOrModule(resumableState, renderState, src, props);
    
  442. 
    
  443.       bootstrapChunks.push(
    
  444.         startScriptSrc,
    
  445.         stringToChunk(escapeTextForBrowser(src)),
    
  446.       );
    
  447.       if (nonce) {
    
  448.         bootstrapChunks.push(
    
  449.           scriptNonce,
    
  450.           stringToChunk(escapeTextForBrowser(nonce)),
    
  451.         );
    
  452.       }
    
  453.       if (typeof integrity === 'string') {
    
  454.         bootstrapChunks.push(
    
  455.           scriptIntegirty,
    
  456.           stringToChunk(escapeTextForBrowser(integrity)),
    
  457.         );
    
  458.       }
    
  459.       if (typeof crossOrigin === 'string') {
    
  460.         bootstrapChunks.push(
    
  461.           scriptCrossOrigin,
    
  462.           stringToChunk(escapeTextForBrowser(crossOrigin)),
    
  463.         );
    
  464.       }
    
  465.       bootstrapChunks.push(endAsyncScript);
    
  466.     }
    
  467.   }
    
  468.   if (bootstrapModules !== undefined) {
    
  469.     for (let i = 0; i < bootstrapModules.length; i++) {
    
  470.       const scriptConfig = bootstrapModules[i];
    
  471.       let src, crossOrigin, integrity;
    
  472.       const props: PreloadModuleProps = ({
    
  473.         rel: 'modulepreload',
    
  474.         fetchPriority: 'low',
    
  475.         nonce,
    
  476.       }: any);
    
  477.       if (typeof scriptConfig === 'string') {
    
  478.         props.href = src = scriptConfig;
    
  479.       } else {
    
  480.         props.href = src = scriptConfig.src;
    
  481.         props.integrity = integrity =
    
  482.           typeof scriptConfig.integrity === 'string'
    
  483.             ? scriptConfig.integrity
    
  484.             : undefined;
    
  485.         props.crossOrigin = crossOrigin =
    
  486.           typeof scriptConfig === 'string' || scriptConfig.crossOrigin == null
    
  487.             ? undefined
    
  488.             : scriptConfig.crossOrigin === 'use-credentials'
    
  489.             ? 'use-credentials'
    
  490.             : '';
    
  491.       }
    
  492. 
    
  493.       preloadBootstrapScriptOrModule(resumableState, renderState, src, props);
    
  494. 
    
  495.       bootstrapChunks.push(
    
  496.         startModuleSrc,
    
  497.         stringToChunk(escapeTextForBrowser(src)),
    
  498.       );
    
  499. 
    
  500.       if (nonce) {
    
  501.         bootstrapChunks.push(
    
  502.           scriptNonce,
    
  503.           stringToChunk(escapeTextForBrowser(nonce)),
    
  504.         );
    
  505.       }
    
  506.       if (typeof integrity === 'string') {
    
  507.         bootstrapChunks.push(
    
  508.           scriptIntegirty,
    
  509.           stringToChunk(escapeTextForBrowser(integrity)),
    
  510.         );
    
  511.       }
    
  512.       if (typeof crossOrigin === 'string') {
    
  513.         bootstrapChunks.push(
    
  514.           scriptCrossOrigin,
    
  515.           stringToChunk(escapeTextForBrowser(crossOrigin)),
    
  516.         );
    
  517.       }
    
  518.       bootstrapChunks.push(endAsyncScript);
    
  519.     }
    
  520.   }
    
  521. 
    
  522.   return renderState;
    
  523. }
    
  524. 
    
  525. export function resumeRenderState(
    
  526.   resumableState: ResumableState,
    
  527.   nonce: string | void,
    
  528. ): RenderState {
    
  529.   return createRenderState(
    
  530.     resumableState,
    
  531.     nonce,
    
  532.     // These should have already been flushed in the prerender.
    
  533.     undefined,
    
  534.     undefined,
    
  535.     undefined,
    
  536.     undefined,
    
  537.     undefined,
    
  538.   );
    
  539. }
    
  540. 
    
  541. export function createResumableState(
    
  542.   identifierPrefix: string | void,
    
  543.   externalRuntimeConfig: string | BootstrapScriptDescriptor | void,
    
  544. ): ResumableState {
    
  545.   const idPrefix = identifierPrefix === undefined ? '' : identifierPrefix;
    
  546. 
    
  547.   let streamingFormat = ScriptStreamingFormat;
    
  548.   if (enableFizzExternalRuntime) {
    
  549.     if (externalRuntimeConfig !== undefined) {
    
  550.       streamingFormat = DataStreamingFormat;
    
  551.     }
    
  552.   }
    
  553.   return {
    
  554.     idPrefix: idPrefix,
    
  555.     nextFormID: 0,
    
  556.     streamingFormat,
    
  557.     instructions: NothingSent,
    
  558.     hasBody: false,
    
  559.     hasHtml: false,
    
  560. 
    
  561.     // @TODO add bootstrap script to implicit preloads
    
  562. 
    
  563.     // persistent
    
  564.     unknownResources: {},
    
  565.     dnsResources: {},
    
  566.     connectResources: {
    
  567.       default: {},
    
  568.       anonymous: {},
    
  569.       credentials: {},
    
  570.     },
    
  571.     imageResources: {},
    
  572.     styleResources: {},
    
  573.     scriptResources: {},
    
  574.     moduleUnknownResources: {},
    
  575.     moduleScriptResources: {},
    
  576.   };
    
  577. }
    
  578. 
    
  579. export function resetResumableState(
    
  580.   resumableState: ResumableState,
    
  581.   renderState: RenderState,
    
  582. ): void {
    
  583.   // Resets the resumable state based on what didn't manage to fully flush in the render state.
    
  584.   // This currently assumes nothing was flushed.
    
  585.   resumableState.nextFormID = 0;
    
  586.   resumableState.hasBody = false;
    
  587.   resumableState.hasHtml = false;
    
  588.   resumableState.unknownResources = {};
    
  589.   resumableState.dnsResources = {};
    
  590.   resumableState.connectResources = {
    
  591.     default: {},
    
  592.     anonymous: {},
    
  593.     credentials: {},
    
  594.   };
    
  595.   resumableState.imageResources = {};
    
  596.   resumableState.styleResources = {};
    
  597.   resumableState.scriptResources = {};
    
  598.   resumableState.moduleUnknownResources = {};
    
  599.   resumableState.moduleScriptResources = {};
    
  600. }
    
  601. 
    
  602. // Constants for the insertion mode we're currently writing in. We don't encode all HTML5 insertion
    
  603. // modes. We only include the variants as they matter for the sake of our purposes.
    
  604. // We don't actually provide the namespace therefore we use constants instead of the string.
    
  605. export const ROOT_HTML_MODE = 0; // Used for the root most element tag.
    
  606. // We have a less than HTML_HTML_MODE check elsewhere. If you add more cases here, make sure it
    
  607. // still makes sense
    
  608. const HTML_HTML_MODE = 1; // Used for the <html> if it is at the top level.
    
  609. const HTML_MODE = 2;
    
  610. const SVG_MODE = 3;
    
  611. const MATHML_MODE = 4;
    
  612. const HTML_TABLE_MODE = 5;
    
  613. const HTML_TABLE_BODY_MODE = 6;
    
  614. const HTML_TABLE_ROW_MODE = 7;
    
  615. const HTML_COLGROUP_MODE = 8;
    
  616. // We have a greater than HTML_TABLE_MODE check elsewhere. If you add more cases here, make sure it
    
  617. // still makes sense
    
  618. 
    
  619. type InsertionMode = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
    
  620. 
    
  621. const NO_SCOPE = /*         */ 0b00;
    
  622. const NOSCRIPT_SCOPE = /*   */ 0b01;
    
  623. const PICTURE_SCOPE = /*    */ 0b10;
    
  624. 
    
  625. // Lets us keep track of contextual state and pick it back up after suspending.
    
  626. export type FormatContext = {
    
  627.   insertionMode: InsertionMode, // root/svg/html/mathml/table
    
  628.   selectedValue: null | string | Array<string>, // the selected value(s) inside a <select>, or null outside <select>
    
  629.   tagScope: number,
    
  630. };
    
  631. 
    
  632. function createFormatContext(
    
  633.   insertionMode: InsertionMode,
    
  634.   selectedValue: null | string,
    
  635.   tagScope: number,
    
  636. ): FormatContext {
    
  637.   return {
    
  638.     insertionMode,
    
  639.     selectedValue,
    
  640.     tagScope,
    
  641.   };
    
  642. }
    
  643. 
    
  644. export function createRootFormatContext(namespaceURI?: string): FormatContext {
    
  645.   const insertionMode =
    
  646.     namespaceURI === 'http://www.w3.org/2000/svg'
    
  647.       ? SVG_MODE
    
  648.       : namespaceURI === 'http://www.w3.org/1998/Math/MathML'
    
  649.       ? MATHML_MODE
    
  650.       : ROOT_HTML_MODE;
    
  651.   return createFormatContext(insertionMode, null, NO_SCOPE);
    
  652. }
    
  653. 
    
  654. export function getChildFormatContext(
    
  655.   parentContext: FormatContext,
    
  656.   type: string,
    
  657.   props: Object,
    
  658. ): FormatContext {
    
  659.   switch (type) {
    
  660.     case 'noscript':
    
  661.       return createFormatContext(
    
  662.         HTML_MODE,
    
  663.         null,
    
  664.         parentContext.tagScope | NOSCRIPT_SCOPE,
    
  665.       );
    
  666.     case 'select':
    
  667.       return createFormatContext(
    
  668.         HTML_MODE,
    
  669.         props.value != null ? props.value : props.defaultValue,
    
  670.         parentContext.tagScope,
    
  671.       );
    
  672.     case 'svg':
    
  673.       return createFormatContext(SVG_MODE, null, parentContext.tagScope);
    
  674.     case 'picture':
    
  675.       return createFormatContext(
    
  676.         HTML_MODE,
    
  677.         null,
    
  678.         parentContext.tagScope | PICTURE_SCOPE,
    
  679.       );
    
  680.     case 'math':
    
  681.       return createFormatContext(MATHML_MODE, null, parentContext.tagScope);
    
  682.     case 'foreignObject':
    
  683.       return createFormatContext(HTML_MODE, null, parentContext.tagScope);
    
  684.     // Table parents are special in that their children can only be created at all if they're
    
  685.     // wrapped in a table parent. So we need to encode that we're entering this mode.
    
  686.     case 'table':
    
  687.       return createFormatContext(HTML_TABLE_MODE, null, parentContext.tagScope);
    
  688.     case 'thead':
    
  689.     case 'tbody':
    
  690.     case 'tfoot':
    
  691.       return createFormatContext(
    
  692.         HTML_TABLE_BODY_MODE,
    
  693.         null,
    
  694.         parentContext.tagScope,
    
  695.       );
    
  696.     case 'colgroup':
    
  697.       return createFormatContext(
    
  698.         HTML_COLGROUP_MODE,
    
  699.         null,
    
  700.         parentContext.tagScope,
    
  701.       );
    
  702.     case 'tr':
    
  703.       return createFormatContext(
    
  704.         HTML_TABLE_ROW_MODE,
    
  705.         null,
    
  706.         parentContext.tagScope,
    
  707.       );
    
  708.   }
    
  709.   if (parentContext.insertionMode >= HTML_TABLE_MODE) {
    
  710.     // Whatever tag this was, it wasn't a table parent or other special parent, so we must have
    
  711.     // entered plain HTML again.
    
  712.     return createFormatContext(HTML_MODE, null, parentContext.tagScope);
    
  713.   }
    
  714.   if (parentContext.insertionMode === ROOT_HTML_MODE) {
    
  715.     if (type === 'html') {
    
  716.       // We've emitted the root and is now in <html> mode.
    
  717.       return createFormatContext(HTML_HTML_MODE, null, parentContext.tagScope);
    
  718.     } else {
    
  719.       // We've emitted the root and is now in plain HTML mode.
    
  720.       return createFormatContext(HTML_MODE, null, parentContext.tagScope);
    
  721.     }
    
  722.   } else if (parentContext.insertionMode === HTML_HTML_MODE) {
    
  723.     // We've emitted the document element and is now in plain HTML mode.
    
  724.     return createFormatContext(HTML_MODE, null, parentContext.tagScope);
    
  725.   }
    
  726.   return parentContext;
    
  727. }
    
  728. 
    
  729. export function makeId(
    
  730.   resumableState: ResumableState,
    
  731.   treeId: string,
    
  732.   localId: number,
    
  733. ): string {
    
  734.   const idPrefix = resumableState.idPrefix;
    
  735. 
    
  736.   let id = ':' + idPrefix + 'R' + treeId;
    
  737. 
    
  738.   // Unless this is the first id at this level, append a number at the end
    
  739.   // that represents the position of this useId hook among all the useId
    
  740.   // hooks for this fiber.
    
  741.   if (localId > 0) {
    
  742.     id += 'H' + localId.toString(32);
    
  743.   }
    
  744. 
    
  745.   return id + ':';
    
  746. }
    
  747. 
    
  748. function encodeHTMLTextNode(text: string): string {
    
  749.   return escapeTextForBrowser(text);
    
  750. }
    
  751. 
    
  752. const textSeparator = stringToPrecomputedChunk('<!-- -->');
    
  753. 
    
  754. export function pushTextInstance(
    
  755.   target: Array<Chunk | PrecomputedChunk>,
    
  756.   text: string,
    
  757.   renderState: RenderState,
    
  758.   textEmbedded: boolean,
    
  759. ): boolean {
    
  760.   if (text === '') {
    
  761.     // Empty text doesn't have a DOM node representation and the hydration is aware of this.
    
  762.     return textEmbedded;
    
  763.   }
    
  764.   if (textEmbedded) {
    
  765.     target.push(textSeparator);
    
  766.   }
    
  767.   target.push(stringToChunk(encodeHTMLTextNode(text)));
    
  768.   return true;
    
  769. }
    
  770. 
    
  771. // Called when Fizz is done with a Segment. Currently the only purpose is to conditionally
    
  772. // emit a text separator when we don't know for sure it is safe to omit
    
  773. export function pushSegmentFinale(
    
  774.   target: Array<Chunk | PrecomputedChunk>,
    
  775.   renderState: RenderState,
    
  776.   lastPushedText: boolean,
    
  777.   textEmbedded: boolean,
    
  778. ): void {
    
  779.   if (lastPushedText && textEmbedded) {
    
  780.     target.push(textSeparator);
    
  781.   }
    
  782. }
    
  783. 
    
  784. const styleNameCache: Map<string, PrecomputedChunk> = new Map();
    
  785. function processStyleName(styleName: string): PrecomputedChunk {
    
  786.   const chunk = styleNameCache.get(styleName);
    
  787.   if (chunk !== undefined) {
    
  788.     return chunk;
    
  789.   }
    
  790.   const result = stringToPrecomputedChunk(
    
  791.     escapeTextForBrowser(hyphenateStyleName(styleName)),
    
  792.   );
    
  793.   styleNameCache.set(styleName, result);
    
  794.   return result;
    
  795. }
    
  796. 
    
  797. const styleAttributeStart = stringToPrecomputedChunk(' style="');
    
  798. const styleAssign = stringToPrecomputedChunk(':');
    
  799. const styleSeparator = stringToPrecomputedChunk(';');
    
  800. 
    
  801. function pushStyleAttribute(
    
  802.   target: Array<Chunk | PrecomputedChunk>,
    
  803.   style: Object,
    
  804. ): void {
    
  805.   if (typeof style !== 'object') {
    
  806.     throw new Error(
    
  807.       'The `style` prop expects a mapping from style properties to values, ' +
    
  808.         "not a string. For example, style={{marginRight: spacing + 'em'}} when " +
    
  809.         'using JSX.',
    
  810.     );
    
  811.   }
    
  812. 
    
  813.   let isFirst = true;
    
  814.   for (const styleName in style) {
    
  815.     if (!hasOwnProperty.call(style, styleName)) {
    
  816.       continue;
    
  817.     }
    
  818.     // If you provide unsafe user data here they can inject arbitrary CSS
    
  819.     // which may be problematic (I couldn't repro this):
    
  820.     // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
    
  821.     // http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/
    
  822.     // This is not an XSS hole but instead a potential CSS injection issue
    
  823.     // which has lead to a greater discussion about how we're going to
    
  824.     // trust URLs moving forward. See #2115901
    
  825.     const styleValue = style[styleName];
    
  826.     if (
    
  827.       styleValue == null ||
    
  828.       typeof styleValue === 'boolean' ||
    
  829.       styleValue === ''
    
  830.     ) {
    
  831.       // TODO: We used to set empty string as a style with an empty value. Does that ever make sense?
    
  832.       continue;
    
  833.     }
    
  834. 
    
  835.     let nameChunk;
    
  836.     let valueChunk;
    
  837.     const isCustomProperty = styleName.indexOf('--') === 0;
    
  838.     if (isCustomProperty) {
    
  839.       nameChunk = stringToChunk(escapeTextForBrowser(styleName));
    
  840.       if (__DEV__) {
    
  841.         checkCSSPropertyStringCoercion(styleValue, styleName);
    
  842.       }
    
  843.       valueChunk = stringToChunk(
    
  844.         escapeTextForBrowser(('' + styleValue).trim()),
    
  845.       );
    
  846.     } else {
    
  847.       if (__DEV__) {
    
  848.         warnValidStyle(styleName, styleValue);
    
  849.       }
    
  850. 
    
  851.       nameChunk = processStyleName(styleName);
    
  852.       if (typeof styleValue === 'number') {
    
  853.         if (styleValue !== 0 && !isUnitlessNumber(styleName)) {
    
  854.           valueChunk = stringToChunk(styleValue + 'px'); // Presumes implicit 'px' suffix for unitless numbers
    
  855.         } else {
    
  856.           valueChunk = stringToChunk('' + styleValue);
    
  857.         }
    
  858.       } else {
    
  859.         if (__DEV__) {
    
  860.           checkCSSPropertyStringCoercion(styleValue, styleName);
    
  861.         }
    
  862.         valueChunk = stringToChunk(
    
  863.           escapeTextForBrowser(('' + styleValue).trim()),
    
  864.         );
    
  865.       }
    
  866.     }
    
  867.     if (isFirst) {
    
  868.       isFirst = false;
    
  869.       // If it's first, we don't need any separators prefixed.
    
  870.       target.push(styleAttributeStart, nameChunk, styleAssign, valueChunk);
    
  871.     } else {
    
  872.       target.push(styleSeparator, nameChunk, styleAssign, valueChunk);
    
  873.     }
    
  874.   }
    
  875.   if (!isFirst) {
    
  876.     target.push(attributeEnd);
    
  877.   }
    
  878. }
    
  879. 
    
  880. const attributeSeparator = stringToPrecomputedChunk(' ');
    
  881. const attributeAssign = stringToPrecomputedChunk('="');
    
  882. const attributeEnd = stringToPrecomputedChunk('"');
    
  883. const attributeEmptyString = stringToPrecomputedChunk('=""');
    
  884. 
    
  885. function pushBooleanAttribute(
    
  886.   target: Array<Chunk | PrecomputedChunk>,
    
  887.   name: string,
    
  888.   value: string | boolean | number | Function | Object, // not null or undefined
    
  889. ): void {
    
  890.   if (value && typeof value !== 'function' && typeof value !== 'symbol') {
    
  891.     target.push(attributeSeparator, stringToChunk(name), attributeEmptyString);
    
  892.   }
    
  893. }
    
  894. 
    
  895. function pushStringAttribute(
    
  896.   target: Array<Chunk | PrecomputedChunk>,
    
  897.   name: string,
    
  898.   value: string | boolean | number | Function | Object, // not null or undefined
    
  899. ): void {
    
  900.   if (
    
  901.     typeof value !== 'function' &&
    
  902.     typeof value !== 'symbol' &&
    
  903.     typeof value !== 'boolean'
    
  904.   ) {
    
  905.     target.push(
    
  906.       attributeSeparator,
    
  907.       stringToChunk(name),
    
  908.       attributeAssign,
    
  909.       stringToChunk(escapeTextForBrowser(value)),
    
  910.       attributeEnd,
    
  911.     );
    
  912.   }
    
  913. }
    
  914. 
    
  915. function makeFormFieldPrefix(resumableState: ResumableState): string {
    
  916.   const id = resumableState.nextFormID++;
    
  917.   return resumableState.idPrefix + id;
    
  918. }
    
  919. 
    
  920. // Since this will likely be repeated a lot in the HTML, we use a more concise message
    
  921. // than on the client and hopefully it's googleable.
    
  922. const actionJavaScriptURL = stringToPrecomputedChunk(
    
  923.   escapeTextForBrowser(
    
  924.     // eslint-disable-next-line no-script-url
    
  925.     "javascript:throw new Error('A React form was unexpectedly submitted.')",
    
  926.   ),
    
  927. );
    
  928. 
    
  929. const startHiddenInputChunk = stringToPrecomputedChunk('<input type="hidden"');
    
  930. 
    
  931. function pushAdditionalFormField(
    
  932.   this: Array<Chunk | PrecomputedChunk>,
    
  933.   value: string | File,
    
  934.   key: string,
    
  935. ): void {
    
  936.   const target: Array<Chunk | PrecomputedChunk> = this;
    
  937.   target.push(startHiddenInputChunk);
    
  938.   if (typeof value !== 'string') {
    
  939.     throw new Error(
    
  940.       'File/Blob fields are not yet supported in progressive forms. ' +
    
  941.         'It probably means you are closing over binary data or FormData in a Server Action.',
    
  942.     );
    
  943.   }
    
  944.   pushStringAttribute(target, 'name', key);
    
  945.   pushStringAttribute(target, 'value', value);
    
  946.   target.push(endOfStartTagSelfClosing);
    
  947. }
    
  948. 
    
  949. function pushAdditionalFormFields(
    
  950.   target: Array<Chunk | PrecomputedChunk>,
    
  951.   formData: null | FormData,
    
  952. ) {
    
  953.   if (formData !== null) {
    
  954.     // $FlowFixMe[prop-missing]: FormData has forEach.
    
  955.     formData.forEach(pushAdditionalFormField, target);
    
  956.   }
    
  957. }
    
  958. 
    
  959. function pushFormActionAttribute(
    
  960.   target: Array<Chunk | PrecomputedChunk>,
    
  961.   resumableState: ResumableState,
    
  962.   renderState: RenderState,
    
  963.   formAction: any,
    
  964.   formEncType: any,
    
  965.   formMethod: any,
    
  966.   formTarget: any,
    
  967.   name: any,
    
  968. ): null | FormData {
    
  969.   let formData = null;
    
  970.   if (enableFormActions && typeof formAction === 'function') {
    
  971.     // Function form actions cannot control the form properties
    
  972.     if (__DEV__) {
    
  973.       if (name !== null && !didWarnFormActionName) {
    
  974.         didWarnFormActionName = true;
    
  975.         console.error(
    
  976.           'Cannot specify a "name" prop for a button that specifies a function as a formAction. ' +
    
  977.             'React needs it to encode which action should be invoked. It will get overridden.',
    
  978.         );
    
  979.       }
    
  980.       if (
    
  981.         (formEncType !== null || formMethod !== null) &&
    
  982.         !didWarnFormActionMethod
    
  983.       ) {
    
  984.         didWarnFormActionMethod = true;
    
  985.         console.error(
    
  986.           'Cannot specify a formEncType or formMethod for a button that specifies a ' +
    
  987.             'function as a formAction. React provides those automatically. They will get overridden.',
    
  988.         );
    
  989.       }
    
  990.       if (formTarget !== null && !didWarnFormActionTarget) {
    
  991.         didWarnFormActionTarget = true;
    
  992.         console.error(
    
  993.           'Cannot specify a formTarget for a button that specifies a function as a formAction. ' +
    
  994.             'The function will always be executed in the same window.',
    
  995.         );
    
  996.       }
    
  997.     }
    
  998.     const customAction: ReactCustomFormAction = formAction.$$FORM_ACTION;
    
  999.     if (typeof customAction === 'function') {
    
  1000.       // This action has a custom progressive enhancement form that can submit the form
    
  1001.       // back to the server if it's invoked before hydration. Such as a Server Action.
    
  1002.       const prefix = makeFormFieldPrefix(resumableState);
    
  1003.       const customFields = formAction.$$FORM_ACTION(prefix);
    
  1004.       name = customFields.name;
    
  1005.       formAction = customFields.action || '';
    
  1006.       formEncType = customFields.encType;
    
  1007.       formMethod = customFields.method;
    
  1008.       formTarget = customFields.target;
    
  1009.       formData = customFields.data;
    
  1010.     } else {
    
  1011.       // Set a javascript URL that doesn't do anything. We don't expect this to be invoked
    
  1012.       // because we'll preventDefault in the Fizz runtime, but it can happen if a form is
    
  1013.       // manually submitted or if someone calls stopPropagation before React gets the event.
    
  1014.       // If CSP is used to block javascript: URLs that's fine too. It just won't show this
    
  1015.       // error message but the URL will be logged.
    
  1016.       target.push(
    
  1017.         attributeSeparator,
    
  1018.         stringToChunk('formAction'),
    
  1019.         attributeAssign,
    
  1020.         actionJavaScriptURL,
    
  1021.         attributeEnd,
    
  1022.       );
    
  1023.       name = null;
    
  1024.       formAction = null;
    
  1025.       formEncType = null;
    
  1026.       formMethod = null;
    
  1027.       formTarget = null;
    
  1028.       injectFormReplayingRuntime(resumableState, renderState);
    
  1029.     }
    
  1030.   }
    
  1031.   if (name != null) {
    
  1032.     pushAttribute(target, 'name', name);
    
  1033.   }
    
  1034.   if (formAction != null) {
    
  1035.     pushAttribute(target, 'formAction', formAction);
    
  1036.   }
    
  1037.   if (formEncType != null) {
    
  1038.     pushAttribute(target, 'formEncType', formEncType);
    
  1039.   }
    
  1040.   if (formMethod != null) {
    
  1041.     pushAttribute(target, 'formMethod', formMethod);
    
  1042.   }
    
  1043.   if (formTarget != null) {
    
  1044.     pushAttribute(target, 'formTarget', formTarget);
    
  1045.   }
    
  1046.   return formData;
    
  1047. }
    
  1048. 
    
  1049. function pushAttribute(
    
  1050.   target: Array<Chunk | PrecomputedChunk>,
    
  1051.   name: string,
    
  1052.   value: string | boolean | number | Function | Object, // not null or undefined
    
  1053. ): void {
    
  1054.   switch (name) {
    
  1055.     // These are very common props and therefore are in the beginning of the switch.
    
  1056.     // TODO: aria-label is a very common prop but allows booleans so is not like the others
    
  1057.     // but should ideally go in this list too.
    
  1058.     case 'className': {
    
  1059.       pushStringAttribute(target, 'class', value);
    
  1060.       break;
    
  1061.     }
    
  1062.     case 'tabIndex': {
    
  1063.       pushStringAttribute(target, 'tabindex', value);
    
  1064.       break;
    
  1065.     }
    
  1066.     case 'dir':
    
  1067.     case 'role':
    
  1068.     case 'viewBox':
    
  1069.     case 'width':
    
  1070.     case 'height': {
    
  1071.       pushStringAttribute(target, name, value);
    
  1072.       break;
    
  1073.     }
    
  1074.     case 'style': {
    
  1075.       pushStyleAttribute(target, value);
    
  1076.       return;
    
  1077.     }
    
  1078.     case 'src':
    
  1079.     case 'href': {
    
  1080.       if (enableFilterEmptyStringAttributesDOM) {
    
  1081.         if (value === '') {
    
  1082.           if (__DEV__) {
    
  1083.             if (name === 'src') {
    
  1084.               console.error(
    
  1085.                 'An empty string ("") was passed to the %s attribute. ' +
    
  1086.                   'This may cause the browser to download the whole page again over the network. ' +
    
  1087.                   'To fix this, either do not render the element at all ' +
    
  1088.                   'or pass null to %s instead of an empty string.',
    
  1089.                 name,
    
  1090.                 name,
    
  1091.               );
    
  1092.             } else {
    
  1093.               console.error(
    
  1094.                 'An empty string ("") was passed to the %s attribute. ' +
    
  1095.                   'To fix this, either do not render the element at all ' +
    
  1096.                   'or pass null to %s instead of an empty string.',
    
  1097.                 name,
    
  1098.                 name,
    
  1099.               );
    
  1100.             }
    
  1101.           }
    
  1102.           return;
    
  1103.         }
    
  1104.       }
    
  1105.     }
    
  1106.     // Fall through to the last case which shouldn't remove empty strings.
    
  1107.     case 'action':
    
  1108.     case 'formAction': {
    
  1109.       // TODO: Consider only special casing these for each tag.
    
  1110.       if (
    
  1111.         value == null ||
    
  1112.         typeof value === 'function' ||
    
  1113.         typeof value === 'symbol' ||
    
  1114.         typeof value === 'boolean'
    
  1115.       ) {
    
  1116.         return;
    
  1117.       }
    
  1118.       if (__DEV__) {
    
  1119.         checkAttributeStringCoercion(value, name);
    
  1120.       }
    
  1121.       const sanitizedValue = sanitizeURL('' + value);
    
  1122.       target.push(
    
  1123.         attributeSeparator,
    
  1124.         stringToChunk(name),
    
  1125.         attributeAssign,
    
  1126.         stringToChunk(escapeTextForBrowser(sanitizedValue)),
    
  1127.         attributeEnd,
    
  1128.       );
    
  1129.       return;
    
  1130.     }
    
  1131.     case 'defaultValue':
    
  1132.     case 'defaultChecked': // These shouldn't be set as attributes on generic HTML elements.
    
  1133.     case 'innerHTML': // Must use dangerouslySetInnerHTML instead.
    
  1134.     case 'suppressContentEditableWarning':
    
  1135.     case 'suppressHydrationWarning':
    
  1136.       // Ignored. These are built-in to React on the client.
    
  1137.       return;
    
  1138.     case 'autoFocus':
    
  1139.     case 'multiple':
    
  1140.     case 'muted': {
    
  1141.       pushBooleanAttribute(target, name.toLowerCase(), value);
    
  1142.       return;
    
  1143.     }
    
  1144.     case 'xlinkHref': {
    
  1145.       if (
    
  1146.         typeof value === 'function' ||
    
  1147.         typeof value === 'symbol' ||
    
  1148.         typeof value === 'boolean'
    
  1149.       ) {
    
  1150.         return;
    
  1151.       }
    
  1152.       if (__DEV__) {
    
  1153.         checkAttributeStringCoercion(value, name);
    
  1154.       }
    
  1155.       const sanitizedValue = sanitizeURL('' + value);
    
  1156.       target.push(
    
  1157.         attributeSeparator,
    
  1158.         stringToChunk('xlink:href'),
    
  1159.         attributeAssign,
    
  1160.         stringToChunk(escapeTextForBrowser(sanitizedValue)),
    
  1161.         attributeEnd,
    
  1162.       );
    
  1163.       return;
    
  1164.     }
    
  1165.     case 'contentEditable':
    
  1166.     case 'spellCheck':
    
  1167.     case 'draggable':
    
  1168.     case 'value':
    
  1169.     case 'autoReverse':
    
  1170.     case 'externalResourcesRequired':
    
  1171.     case 'focusable':
    
  1172.     case 'preserveAlpha': {
    
  1173.       // Booleanish String
    
  1174.       // These are "enumerated" attributes that accept "true" and "false".
    
  1175.       // In React, we let users pass `true` and `false` even though technically
    
  1176.       // these aren't boolean attributes (they are coerced to strings).
    
  1177.       if (typeof value !== 'function' && typeof value !== 'symbol') {
    
  1178.         target.push(
    
  1179.           attributeSeparator,
    
  1180.           stringToChunk(name),
    
  1181.           attributeAssign,
    
  1182.           stringToChunk(escapeTextForBrowser(value)),
    
  1183.           attributeEnd,
    
  1184.         );
    
  1185.       }
    
  1186.       return;
    
  1187.     }
    
  1188.     case 'allowFullScreen':
    
  1189.     case 'async':
    
  1190.     case 'autoPlay':
    
  1191.     case 'controls':
    
  1192.     case 'default':
    
  1193.     case 'defer':
    
  1194.     case 'disabled':
    
  1195.     case 'disablePictureInPicture':
    
  1196.     case 'disableRemotePlayback':
    
  1197.     case 'formNoValidate':
    
  1198.     case 'hidden':
    
  1199.     case 'loop':
    
  1200.     case 'noModule':
    
  1201.     case 'noValidate':
    
  1202.     case 'open':
    
  1203.     case 'playsInline':
    
  1204.     case 'readOnly':
    
  1205.     case 'required':
    
  1206.     case 'reversed':
    
  1207.     case 'scoped':
    
  1208.     case 'seamless':
    
  1209.     case 'itemScope': {
    
  1210.       // Boolean
    
  1211.       if (value && typeof value !== 'function' && typeof value !== 'symbol') {
    
  1212.         target.push(
    
  1213.           attributeSeparator,
    
  1214.           stringToChunk(name),
    
  1215.           attributeEmptyString,
    
  1216.         );
    
  1217.       }
    
  1218.       return;
    
  1219.     }
    
  1220.     case 'capture':
    
  1221.     case 'download': {
    
  1222.       // Overloaded Boolean
    
  1223.       if (value === true) {
    
  1224.         target.push(
    
  1225.           attributeSeparator,
    
  1226.           stringToChunk(name),
    
  1227.           attributeEmptyString,
    
  1228.         );
    
  1229.       } else if (value === false) {
    
  1230.         // Ignored
    
  1231.       } else if (typeof value !== 'function' && typeof value !== 'symbol') {
    
  1232.         target.push(
    
  1233.           attributeSeparator,
    
  1234.           stringToChunk(name),
    
  1235.           attributeAssign,
    
  1236.           stringToChunk(escapeTextForBrowser(value)),
    
  1237.           attributeEnd,
    
  1238.         );
    
  1239.       }
    
  1240.       return;
    
  1241.     }
    
  1242.     case 'cols':
    
  1243.     case 'rows':
    
  1244.     case 'size':
    
  1245.     case 'span': {
    
  1246.       // These are HTML attributes that must be positive numbers.
    
  1247.       if (
    
  1248.         typeof value !== 'function' &&
    
  1249.         typeof value !== 'symbol' &&
    
  1250.         !isNaN(value) &&
    
  1251.         (value: any) >= 1
    
  1252.       ) {
    
  1253.         target.push(
    
  1254.           attributeSeparator,
    
  1255.           stringToChunk(name),
    
  1256.           attributeAssign,
    
  1257.           stringToChunk(escapeTextForBrowser(value)),
    
  1258.           attributeEnd,
    
  1259.         );
    
  1260.       }
    
  1261.       return;
    
  1262.     }
    
  1263.     case 'rowSpan':
    
  1264.     case 'start': {
    
  1265.       // These are HTML attributes that must be numbers.
    
  1266.       if (
    
  1267.         typeof value !== 'function' &&
    
  1268.         typeof value !== 'symbol' &&
    
  1269.         !isNaN(value)
    
  1270.       ) {
    
  1271.         target.push(
    
  1272.           attributeSeparator,
    
  1273.           stringToChunk(name),
    
  1274.           attributeAssign,
    
  1275.           stringToChunk(escapeTextForBrowser(value)),
    
  1276.           attributeEnd,
    
  1277.         );
    
  1278.       }
    
  1279.       return;
    
  1280.     }
    
  1281.     case 'xlinkActuate':
    
  1282.       pushStringAttribute(target, 'xlink:actuate', value);
    
  1283.       return;
    
  1284.     case 'xlinkArcrole':
    
  1285.       pushStringAttribute(target, 'xlink:arcrole', value);
    
  1286.       return;
    
  1287.     case 'xlinkRole':
    
  1288.       pushStringAttribute(target, 'xlink:role', value);
    
  1289.       return;
    
  1290.     case 'xlinkShow':
    
  1291.       pushStringAttribute(target, 'xlink:show', value);
    
  1292.       return;
    
  1293.     case 'xlinkTitle':
    
  1294.       pushStringAttribute(target, 'xlink:title', value);
    
  1295.       return;
    
  1296.     case 'xlinkType':
    
  1297.       pushStringAttribute(target, 'xlink:type', value);
    
  1298.       return;
    
  1299.     case 'xmlBase':
    
  1300.       pushStringAttribute(target, 'xml:base', value);
    
  1301.       return;
    
  1302.     case 'xmlLang':
    
  1303.       pushStringAttribute(target, 'xml:lang', value);
    
  1304.       return;
    
  1305.     case 'xmlSpace':
    
  1306.       pushStringAttribute(target, 'xml:space', value);
    
  1307.       return;
    
  1308.     default:
    
  1309.       if (
    
  1310.         // shouldIgnoreAttribute
    
  1311.         // We have already filtered out null/undefined and reserved words.
    
  1312.         name.length > 2 &&
    
  1313.         (name[0] === 'o' || name[0] === 'O') &&
    
  1314.         (name[1] === 'n' || name[1] === 'N')
    
  1315.       ) {
    
  1316.         return;
    
  1317.       }
    
  1318. 
    
  1319.       const attributeName = getAttributeAlias(name);
    
  1320.       if (isAttributeNameSafe(attributeName)) {
    
  1321.         // shouldRemoveAttribute
    
  1322.         switch (typeof value) {
    
  1323.           case 'function':
    
  1324.           case 'symbol': // eslint-disable-line
    
  1325.             return;
    
  1326.           case 'boolean': {
    
  1327.             const prefix = attributeName.toLowerCase().slice(0, 5);
    
  1328.             if (prefix !== 'data-' && prefix !== 'aria-') {
    
  1329.               return;
    
  1330.             }
    
  1331.           }
    
  1332.         }
    
  1333.         target.push(
    
  1334.           attributeSeparator,
    
  1335.           stringToChunk(attributeName),
    
  1336.           attributeAssign,
    
  1337.           stringToChunk(escapeTextForBrowser(value)),
    
  1338.           attributeEnd,
    
  1339.         );
    
  1340.       }
    
  1341.   }
    
  1342. }
    
  1343. 
    
  1344. const endOfStartTag = stringToPrecomputedChunk('>');
    
  1345. const endOfStartTagSelfClosing = stringToPrecomputedChunk('/>');
    
  1346. 
    
  1347. function pushInnerHTML(
    
  1348.   target: Array<Chunk | PrecomputedChunk>,
    
  1349.   innerHTML: any,
    
  1350.   children: any,
    
  1351. ) {
    
  1352.   if (innerHTML != null) {
    
  1353.     if (children != null) {
    
  1354.       throw new Error(
    
  1355.         'Can only set one of `children` or `props.dangerouslySetInnerHTML`.',
    
  1356.       );
    
  1357.     }
    
  1358. 
    
  1359.     if (typeof innerHTML !== 'object' || !('__html' in innerHTML)) {
    
  1360.       throw new Error(
    
  1361.         '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' +
    
  1362.           'Please visit https://reactjs.org/link/dangerously-set-inner-html ' +
    
  1363.           'for more information.',
    
  1364.       );
    
  1365.     }
    
  1366. 
    
  1367.     const html = innerHTML.__html;
    
  1368.     if (html !== null && html !== undefined) {
    
  1369.       if (__DEV__) {
    
  1370.         checkHtmlStringCoercion(html);
    
  1371.       }
    
  1372.       target.push(stringToChunk('' + html));
    
  1373.     }
    
  1374.   }
    
  1375. }
    
  1376. 
    
  1377. // TODO: Move these to RenderState so that we warn for every request.
    
  1378. // It would help debugging in stateful servers (e.g. service worker).
    
  1379. let didWarnDefaultInputValue = false;
    
  1380. let didWarnDefaultChecked = false;
    
  1381. let didWarnDefaultSelectValue = false;
    
  1382. let didWarnDefaultTextareaValue = false;
    
  1383. let didWarnInvalidOptionChildren = false;
    
  1384. let didWarnInvalidOptionInnerHTML = false;
    
  1385. let didWarnSelectedSetOnOption = false;
    
  1386. let didWarnFormActionType = false;
    
  1387. let didWarnFormActionName = false;
    
  1388. let didWarnFormActionTarget = false;
    
  1389. let didWarnFormActionMethod = false;
    
  1390. 
    
  1391. function checkSelectProp(props: any, propName: string) {
    
  1392.   if (__DEV__) {
    
  1393.     const value = props[propName];
    
  1394.     if (value != null) {
    
  1395.       const array = isArray(value);
    
  1396.       if (props.multiple && !array) {
    
  1397.         console.error(
    
  1398.           'The `%s` prop supplied to <select> must be an array if ' +
    
  1399.             '`multiple` is true.',
    
  1400.           propName,
    
  1401.         );
    
  1402.       } else if (!props.multiple && array) {
    
  1403.         console.error(
    
  1404.           'The `%s` prop supplied to <select> must be a scalar ' +
    
  1405.             'value if `multiple` is false.',
    
  1406.           propName,
    
  1407.         );
    
  1408.       }
    
  1409.     }
    
  1410.   }
    
  1411. }
    
  1412. 
    
  1413. function pushStartSelect(
    
  1414.   target: Array<Chunk | PrecomputedChunk>,
    
  1415.   props: Object,
    
  1416. ): ReactNodeList {
    
  1417.   if (__DEV__) {
    
  1418.     checkControlledValueProps('select', props);
    
  1419. 
    
  1420.     checkSelectProp(props, 'value');
    
  1421.     checkSelectProp(props, 'defaultValue');
    
  1422. 
    
  1423.     if (
    
  1424.       props.value !== undefined &&
    
  1425.       props.defaultValue !== undefined &&
    
  1426.       !didWarnDefaultSelectValue
    
  1427.     ) {
    
  1428.       console.error(
    
  1429.         'Select elements must be either controlled or uncontrolled ' +
    
  1430.           '(specify either the value prop, or the defaultValue prop, but not ' +
    
  1431.           'both). Decide between using a controlled or uncontrolled select ' +
    
  1432.           'element and remove one of these props. More info: ' +
    
  1433.           'https://reactjs.org/link/controlled-components',
    
  1434.       );
    
  1435.       didWarnDefaultSelectValue = true;
    
  1436.     }
    
  1437.   }
    
  1438. 
    
  1439.   target.push(startChunkForTag('select'));
    
  1440. 
    
  1441.   let children = null;
    
  1442.   let innerHTML = null;
    
  1443.   for (const propKey in props) {
    
  1444.     if (hasOwnProperty.call(props, propKey)) {
    
  1445.       const propValue = props[propKey];
    
  1446.       if (propValue == null) {
    
  1447.         continue;
    
  1448.       }
    
  1449.       switch (propKey) {
    
  1450.         case 'children':
    
  1451.           children = propValue;
    
  1452.           break;
    
  1453.         case 'dangerouslySetInnerHTML':
    
  1454.           // TODO: This doesn't really make sense for select since it can't use the controlled
    
  1455.           // value in the innerHTML.
    
  1456.           innerHTML = propValue;
    
  1457.           break;
    
  1458.         case 'defaultValue':
    
  1459.         case 'value':
    
  1460.           // These are set on the Context instead and applied to the nested options.
    
  1461.           break;
    
  1462.         default:
    
  1463.           pushAttribute(target, propKey, propValue);
    
  1464.           break;
    
  1465.       }
    
  1466.     }
    
  1467.   }
    
  1468. 
    
  1469.   target.push(endOfStartTag);
    
  1470.   pushInnerHTML(target, innerHTML, children);
    
  1471.   return children;
    
  1472. }
    
  1473. 
    
  1474. function flattenOptionChildren(children: mixed): string {
    
  1475.   let content = '';
    
  1476.   // Flatten children and warn if they aren't strings or numbers;
    
  1477.   // invalid types are ignored.
    
  1478.   Children.forEach((children: any), function (child) {
    
  1479.     if (child == null) {
    
  1480.       return;
    
  1481.     }
    
  1482.     content += (child: any);
    
  1483.     if (__DEV__) {
    
  1484.       if (
    
  1485.         !didWarnInvalidOptionChildren &&
    
  1486.         typeof child !== 'string' &&
    
  1487.         typeof child !== 'number'
    
  1488.       ) {
    
  1489.         didWarnInvalidOptionChildren = true;
    
  1490.         console.error(
    
  1491.           'Cannot infer the option value of complex children. ' +
    
  1492.             'Pass a `value` prop or use a plain string as children to <option>.',
    
  1493.         );
    
  1494.       }
    
  1495.     }
    
  1496.   });
    
  1497.   return content;
    
  1498. }
    
  1499. 
    
  1500. const selectedMarkerAttribute = stringToPrecomputedChunk(' selected=""');
    
  1501. 
    
  1502. function pushStartOption(
    
  1503.   target: Array<Chunk | PrecomputedChunk>,
    
  1504.   props: Object,
    
  1505.   formatContext: FormatContext,
    
  1506. ): ReactNodeList {
    
  1507.   const selectedValue = formatContext.selectedValue;
    
  1508. 
    
  1509.   target.push(startChunkForTag('option'));
    
  1510. 
    
  1511.   let children = null;
    
  1512.   let value = null;
    
  1513.   let selected = null;
    
  1514.   let innerHTML = null;
    
  1515.   for (const propKey in props) {
    
  1516.     if (hasOwnProperty.call(props, propKey)) {
    
  1517.       const propValue = props[propKey];
    
  1518.       if (propValue == null) {
    
  1519.         continue;
    
  1520.       }
    
  1521.       switch (propKey) {
    
  1522.         case 'children':
    
  1523.           children = propValue;
    
  1524.           break;
    
  1525.         case 'selected':
    
  1526.           // ignore
    
  1527.           selected = propValue;
    
  1528.           if (__DEV__) {
    
  1529.             // TODO: Remove support for `selected` in <option>.
    
  1530.             if (!didWarnSelectedSetOnOption) {
    
  1531.               console.error(
    
  1532.                 'Use the `defaultValue` or `value` props on <select> instead of ' +
    
  1533.                   'setting `selected` on <option>.',
    
  1534.               );
    
  1535.               didWarnSelectedSetOnOption = true;
    
  1536.             }
    
  1537.           }
    
  1538.           break;
    
  1539.         case 'dangerouslySetInnerHTML':
    
  1540.           innerHTML = propValue;
    
  1541.           break;
    
  1542.         case 'value':
    
  1543.           value = propValue;
    
  1544.         // We intentionally fallthrough to also set the attribute on the node.
    
  1545.         default:
    
  1546.           pushAttribute(target, propKey, propValue);
    
  1547.           break;
    
  1548.       }
    
  1549.     }
    
  1550.   }
    
  1551. 
    
  1552.   if (selectedValue != null) {
    
  1553.     let stringValue;
    
  1554.     if (value !== null) {
    
  1555.       if (__DEV__) {
    
  1556.         checkAttributeStringCoercion(value, 'value');
    
  1557.       }
    
  1558.       stringValue = '' + value;
    
  1559.     } else {
    
  1560.       if (__DEV__) {
    
  1561.         if (innerHTML !== null) {
    
  1562.           if (!didWarnInvalidOptionInnerHTML) {
    
  1563.             didWarnInvalidOptionInnerHTML = true;
    
  1564.             console.error(
    
  1565.               'Pass a `value` prop if you set dangerouslyInnerHTML so React knows ' +
    
  1566.                 'which value should be selected.',
    
  1567.             );
    
  1568.           }
    
  1569.         }
    
  1570.       }
    
  1571.       stringValue = flattenOptionChildren(children);
    
  1572.     }
    
  1573.     if (isArray(selectedValue)) {
    
  1574.       // multiple
    
  1575.       for (let i = 0; i < selectedValue.length; i++) {
    
  1576.         if (__DEV__) {
    
  1577.           checkAttributeStringCoercion(selectedValue[i], 'value');
    
  1578.         }
    
  1579.         const v = '' + selectedValue[i];
    
  1580.         if (v === stringValue) {
    
  1581.           target.push(selectedMarkerAttribute);
    
  1582.           break;
    
  1583.         }
    
  1584.       }
    
  1585.     } else {
    
  1586.       if (__DEV__) {
    
  1587.         checkAttributeStringCoercion(selectedValue, 'select.value');
    
  1588.       }
    
  1589.       if ('' + selectedValue === stringValue) {
    
  1590.         target.push(selectedMarkerAttribute);
    
  1591.       }
    
  1592.     }
    
  1593.   } else if (selected) {
    
  1594.     target.push(selectedMarkerAttribute);
    
  1595.   }
    
  1596. 
    
  1597.   target.push(endOfStartTag);
    
  1598.   pushInnerHTML(target, innerHTML, children);
    
  1599.   return children;
    
  1600. }
    
  1601. 
    
  1602. const formReplayingRuntimeScript =
    
  1603.   stringToPrecomputedChunk(formReplayingRuntime);
    
  1604. 
    
  1605. function injectFormReplayingRuntime(
    
  1606.   resumableState: ResumableState,
    
  1607.   renderState: RenderState,
    
  1608. ): void {
    
  1609.   // If we haven't sent it yet, inject the runtime that tracks submitted JS actions
    
  1610.   // for later replaying by Fiber. If we use an external runtime, we don't need
    
  1611.   // to emit anything. It's always used.
    
  1612.   if (
    
  1613.     (resumableState.instructions & SentFormReplayingRuntime) === NothingSent &&
    
  1614.     (!enableFizzExternalRuntime || !renderState.externalRuntimeScript)
    
  1615.   ) {
    
  1616.     resumableState.instructions |= SentFormReplayingRuntime;
    
  1617.     renderState.bootstrapChunks.unshift(
    
  1618.       renderState.startInlineScript,
    
  1619.       formReplayingRuntimeScript,
    
  1620.       endInlineScript,
    
  1621.     );
    
  1622.   }
    
  1623. }
    
  1624. 
    
  1625. const formStateMarkerIsMatching = stringToPrecomputedChunk('<!--F!-->');
    
  1626. const formStateMarkerIsNotMatching = stringToPrecomputedChunk('<!--F-->');
    
  1627. 
    
  1628. export function pushFormStateMarkerIsMatching(
    
  1629.   target: Array<Chunk | PrecomputedChunk>,
    
  1630. ) {
    
  1631.   target.push(formStateMarkerIsMatching);
    
  1632. }
    
  1633. 
    
  1634. export function pushFormStateMarkerIsNotMatching(
    
  1635.   target: Array<Chunk | PrecomputedChunk>,
    
  1636. ) {
    
  1637.   target.push(formStateMarkerIsNotMatching);
    
  1638. }
    
  1639. 
    
  1640. function pushStartForm(
    
  1641.   target: Array<Chunk | PrecomputedChunk>,
    
  1642.   props: Object,
    
  1643.   resumableState: ResumableState,
    
  1644.   renderState: RenderState,
    
  1645. ): ReactNodeList {
    
  1646.   target.push(startChunkForTag('form'));
    
  1647. 
    
  1648.   let children = null;
    
  1649.   let innerHTML = null;
    
  1650.   let formAction = null;
    
  1651.   let formEncType = null;
    
  1652.   let formMethod = null;
    
  1653.   let formTarget = null;
    
  1654. 
    
  1655.   for (const propKey in props) {
    
  1656.     if (hasOwnProperty.call(props, propKey)) {
    
  1657.       const propValue = props[propKey];
    
  1658.       if (propValue == null) {
    
  1659.         continue;
    
  1660.       }
    
  1661.       switch (propKey) {
    
  1662.         case 'children':
    
  1663.           children = propValue;
    
  1664.           break;
    
  1665.         case 'dangerouslySetInnerHTML':
    
  1666.           innerHTML = propValue;
    
  1667.           break;
    
  1668.         case 'action':
    
  1669.           formAction = propValue;
    
  1670.           break;
    
  1671.         case 'encType':
    
  1672.           formEncType = propValue;
    
  1673.           break;
    
  1674.         case 'method':
    
  1675.           formMethod = propValue;
    
  1676.           break;
    
  1677.         case 'target':
    
  1678.           formTarget = propValue;
    
  1679.           break;
    
  1680.         default:
    
  1681.           pushAttribute(target, propKey, propValue);
    
  1682.           break;
    
  1683.       }
    
  1684.     }
    
  1685.   }
    
  1686. 
    
  1687.   let formData = null;
    
  1688.   let formActionName = null;
    
  1689.   if (enableFormActions && typeof formAction === 'function') {
    
  1690.     // Function form actions cannot control the form properties
    
  1691.     if (__DEV__) {
    
  1692.       if (
    
  1693.         (formEncType !== null || formMethod !== null) &&
    
  1694.         !didWarnFormActionMethod
    
  1695.       ) {
    
  1696.         didWarnFormActionMethod = true;
    
  1697.         console.error(
    
  1698.           'Cannot specify a encType or method for a form that specifies a ' +
    
  1699.             'function as the action. React provides those automatically. ' +
    
  1700.             'They will get overridden.',
    
  1701.         );
    
  1702.       }
    
  1703.       if (formTarget !== null && !didWarnFormActionTarget) {
    
  1704.         didWarnFormActionTarget = true;
    
  1705.         console.error(
    
  1706.           'Cannot specify a target for a form that specifies a function as the action. ' +
    
  1707.             'The function will always be executed in the same window.',
    
  1708.         );
    
  1709.       }
    
  1710.     }
    
  1711.     const customAction: ReactCustomFormAction = formAction.$$FORM_ACTION;
    
  1712.     if (typeof customAction === 'function') {
    
  1713.       // This action has a custom progressive enhancement form that can submit the form
    
  1714.       // back to the server if it's invoked before hydration. Such as a Server Action.
    
  1715.       const prefix = makeFormFieldPrefix(resumableState);
    
  1716.       const customFields = formAction.$$FORM_ACTION(prefix);
    
  1717.       formAction = customFields.action || '';
    
  1718.       formEncType = customFields.encType;
    
  1719.       formMethod = customFields.method;
    
  1720.       formTarget = customFields.target;
    
  1721.       formData = customFields.data;
    
  1722.       formActionName = customFields.name;
    
  1723.     } else {
    
  1724.       // Set a javascript URL that doesn't do anything. We don't expect this to be invoked
    
  1725.       // because we'll preventDefault in the Fizz runtime, but it can happen if a form is
    
  1726.       // manually submitted or if someone calls stopPropagation before React gets the event.
    
  1727.       // If CSP is used to block javascript: URLs that's fine too. It just won't show this
    
  1728.       // error message but the URL will be logged.
    
  1729.       target.push(
    
  1730.         attributeSeparator,
    
  1731.         stringToChunk('action'),
    
  1732.         attributeAssign,
    
  1733.         actionJavaScriptURL,
    
  1734.         attributeEnd,
    
  1735.       );
    
  1736.       formAction = null;
    
  1737.       formEncType = null;
    
  1738.       formMethod = null;
    
  1739.       formTarget = null;
    
  1740.       injectFormReplayingRuntime(resumableState, renderState);
    
  1741.     }
    
  1742.   }
    
  1743.   if (formAction != null) {
    
  1744.     pushAttribute(target, 'action', formAction);
    
  1745.   }
    
  1746.   if (formEncType != null) {
    
  1747.     pushAttribute(target, 'encType', formEncType);
    
  1748.   }
    
  1749.   if (formMethod != null) {
    
  1750.     pushAttribute(target, 'method', formMethod);
    
  1751.   }
    
  1752.   if (formTarget != null) {
    
  1753.     pushAttribute(target, 'target', formTarget);
    
  1754.   }
    
  1755. 
    
  1756.   target.push(endOfStartTag);
    
  1757. 
    
  1758.   if (formActionName !== null) {
    
  1759.     target.push(startHiddenInputChunk);
    
  1760.     pushStringAttribute(target, 'name', formActionName);
    
  1761.     target.push(endOfStartTagSelfClosing);
    
  1762.     pushAdditionalFormFields(target, formData);
    
  1763.   }
    
  1764. 
    
  1765.   pushInnerHTML(target, innerHTML, children);
    
  1766.   if (typeof children === 'string') {
    
  1767.     // Special case children as a string to avoid the unnecessary comment.
    
  1768.     // TODO: Remove this special case after the general optimization is in place.
    
  1769.     target.push(stringToChunk(encodeHTMLTextNode(children)));
    
  1770.     return null;
    
  1771.   }
    
  1772.   return children;
    
  1773. }
    
  1774. 
    
  1775. function pushInput(
    
  1776.   target: Array<Chunk | PrecomputedChunk>,
    
  1777.   props: Object,
    
  1778.   resumableState: ResumableState,
    
  1779.   renderState: RenderState,
    
  1780. ): ReactNodeList {
    
  1781.   if (__DEV__) {
    
  1782.     checkControlledValueProps('input', props);
    
  1783.   }
    
  1784. 
    
  1785.   target.push(startChunkForTag('input'));
    
  1786. 
    
  1787.   let name = null;
    
  1788.   let formAction = null;
    
  1789.   let formEncType = null;
    
  1790.   let formMethod = null;
    
  1791.   let formTarget = null;
    
  1792.   let value = null;
    
  1793.   let defaultValue = null;
    
  1794.   let checked = null;
    
  1795.   let defaultChecked = null;
    
  1796. 
    
  1797.   for (const propKey in props) {
    
  1798.     if (hasOwnProperty.call(props, propKey)) {
    
  1799.       const propValue = props[propKey];
    
  1800.       if (propValue == null) {
    
  1801.         continue;
    
  1802.       }
    
  1803.       switch (propKey) {
    
  1804.         case 'children':
    
  1805.         case 'dangerouslySetInnerHTML':
    
  1806.           throw new Error(
    
  1807.             `${'input'} is a self-closing tag and must neither have \`children\` nor ` +
    
  1808.               'use `dangerouslySetInnerHTML`.',
    
  1809.           );
    
  1810.         case 'name':
    
  1811.           name = propValue;
    
  1812.           break;
    
  1813.         case 'formAction':
    
  1814.           formAction = propValue;
    
  1815.           break;
    
  1816.         case 'formEncType':
    
  1817.           formEncType = propValue;
    
  1818.           break;
    
  1819.         case 'formMethod':
    
  1820.           formMethod = propValue;
    
  1821.           break;
    
  1822.         case 'formTarget':
    
  1823.           formTarget = propValue;
    
  1824.           break;
    
  1825.         case 'defaultChecked':
    
  1826.           defaultChecked = propValue;
    
  1827.           break;
    
  1828.         case 'defaultValue':
    
  1829.           defaultValue = propValue;
    
  1830.           break;
    
  1831.         case 'checked':
    
  1832.           checked = propValue;
    
  1833.           break;
    
  1834.         case 'value':
    
  1835.           value = propValue;
    
  1836.           break;
    
  1837.         default:
    
  1838.           pushAttribute(target, propKey, propValue);
    
  1839.           break;
    
  1840.       }
    
  1841.     }
    
  1842.   }
    
  1843. 
    
  1844.   if (__DEV__) {
    
  1845.     if (
    
  1846.       formAction !== null &&
    
  1847.       props.type !== 'image' &&
    
  1848.       props.type !== 'submit' &&
    
  1849.       !didWarnFormActionType
    
  1850.     ) {
    
  1851.       didWarnFormActionType = true;
    
  1852.       console.error(
    
  1853.         'An input can only specify a formAction along with type="submit" or type="image".',
    
  1854.       );
    
  1855.     }
    
  1856.   }
    
  1857. 
    
  1858.   const formData = pushFormActionAttribute(
    
  1859.     target,
    
  1860.     resumableState,
    
  1861.     renderState,
    
  1862.     formAction,
    
  1863.     formEncType,
    
  1864.     formMethod,
    
  1865.     formTarget,
    
  1866.     name,
    
  1867.   );
    
  1868. 
    
  1869.   if (__DEV__) {
    
  1870.     if (checked !== null && defaultChecked !== null && !didWarnDefaultChecked) {
    
  1871.       console.error(
    
  1872.         '%s contains an input of type %s with both checked and defaultChecked props. ' +
    
  1873.           'Input elements must be either controlled or uncontrolled ' +
    
  1874.           '(specify either the checked prop, or the defaultChecked prop, but not ' +
    
  1875.           'both). Decide between using a controlled or uncontrolled input ' +
    
  1876.           'element and remove one of these props. More info: ' +
    
  1877.           'https://reactjs.org/link/controlled-components',
    
  1878.         'A component',
    
  1879.         props.type,
    
  1880.       );
    
  1881.       didWarnDefaultChecked = true;
    
  1882.     }
    
  1883.     if (value !== null && defaultValue !== null && !didWarnDefaultInputValue) {
    
  1884.       console.error(
    
  1885.         '%s contains an input of type %s with both value and defaultValue props. ' +
    
  1886.           'Input elements must be either controlled or uncontrolled ' +
    
  1887.           '(specify either the value prop, or the defaultValue prop, but not ' +
    
  1888.           'both). Decide between using a controlled or uncontrolled input ' +
    
  1889.           'element and remove one of these props. More info: ' +
    
  1890.           'https://reactjs.org/link/controlled-components',
    
  1891.         'A component',
    
  1892.         props.type,
    
  1893.       );
    
  1894.       didWarnDefaultInputValue = true;
    
  1895.     }
    
  1896.   }
    
  1897. 
    
  1898.   if (checked !== null) {
    
  1899.     pushBooleanAttribute(target, 'checked', checked);
    
  1900.   } else if (defaultChecked !== null) {
    
  1901.     pushBooleanAttribute(target, 'checked', defaultChecked);
    
  1902.   }
    
  1903.   if (value !== null) {
    
  1904.     pushAttribute(target, 'value', value);
    
  1905.   } else if (defaultValue !== null) {
    
  1906.     pushAttribute(target, 'value', defaultValue);
    
  1907.   }
    
  1908. 
    
  1909.   target.push(endOfStartTagSelfClosing);
    
  1910. 
    
  1911.   // We place any additional hidden form fields after the input.
    
  1912.   pushAdditionalFormFields(target, formData);
    
  1913. 
    
  1914.   return null;
    
  1915. }
    
  1916. 
    
  1917. function pushStartButton(
    
  1918.   target: Array<Chunk | PrecomputedChunk>,
    
  1919.   props: Object,
    
  1920.   resumableState: ResumableState,
    
  1921.   renderState: RenderState,
    
  1922. ): ReactNodeList {
    
  1923.   target.push(startChunkForTag('button'));
    
  1924. 
    
  1925.   let children = null;
    
  1926.   let innerHTML = null;
    
  1927.   let name = null;
    
  1928.   let formAction = null;
    
  1929.   let formEncType = null;
    
  1930.   let formMethod = null;
    
  1931.   let formTarget = null;
    
  1932. 
    
  1933.   for (const propKey in props) {
    
  1934.     if (hasOwnProperty.call(props, propKey)) {
    
  1935.       const propValue = props[propKey];
    
  1936.       if (propValue == null) {
    
  1937.         continue;
    
  1938.       }
    
  1939.       switch (propKey) {
    
  1940.         case 'children':
    
  1941.           children = propValue;
    
  1942.           break;
    
  1943.         case 'dangerouslySetInnerHTML':
    
  1944.           innerHTML = propValue;
    
  1945.           break;
    
  1946.         case 'name':
    
  1947.           name = propValue;
    
  1948.           break;
    
  1949.         case 'formAction':
    
  1950.           formAction = propValue;
    
  1951.           break;
    
  1952.         case 'formEncType':
    
  1953.           formEncType = propValue;
    
  1954.           break;
    
  1955.         case 'formMethod':
    
  1956.           formMethod = propValue;
    
  1957.           break;
    
  1958.         case 'formTarget':
    
  1959.           formTarget = propValue;
    
  1960.           break;
    
  1961.         default:
    
  1962.           pushAttribute(target, propKey, propValue);
    
  1963.           break;
    
  1964.       }
    
  1965.     }
    
  1966.   }
    
  1967. 
    
  1968.   if (__DEV__) {
    
  1969.     if (
    
  1970.       formAction !== null &&
    
  1971.       props.type != null &&
    
  1972.       props.type !== 'submit' &&
    
  1973.       !didWarnFormActionType
    
  1974.     ) {
    
  1975.       didWarnFormActionType = true;
    
  1976.       console.error(
    
  1977.         'A button can only specify a formAction along with type="submit" or no type.',
    
  1978.       );
    
  1979.     }
    
  1980.   }
    
  1981. 
    
  1982.   const formData = pushFormActionAttribute(
    
  1983.     target,
    
  1984.     resumableState,
    
  1985.     renderState,
    
  1986.     formAction,
    
  1987.     formEncType,
    
  1988.     formMethod,
    
  1989.     formTarget,
    
  1990.     name,
    
  1991.   );
    
  1992. 
    
  1993.   target.push(endOfStartTag);
    
  1994. 
    
  1995.   // We place any additional hidden form fields we need to include inside the button itself.
    
  1996.   pushAdditionalFormFields(target, formData);
    
  1997. 
    
  1998.   pushInnerHTML(target, innerHTML, children);
    
  1999.   if (typeof children === 'string') {
    
  2000.     // Special case children as a string to avoid the unnecessary comment.
    
  2001.     // TODO: Remove this special case after the general optimization is in place.
    
  2002.     target.push(stringToChunk(encodeHTMLTextNode(children)));
    
  2003.     return null;
    
  2004.   }
    
  2005. 
    
  2006.   return children;
    
  2007. }
    
  2008. 
    
  2009. function pushStartTextArea(
    
  2010.   target: Array<Chunk | PrecomputedChunk>,
    
  2011.   props: Object,
    
  2012. ): ReactNodeList {
    
  2013.   if (__DEV__) {
    
  2014.     checkControlledValueProps('textarea', props);
    
  2015.     if (
    
  2016.       props.value !== undefined &&
    
  2017.       props.defaultValue !== undefined &&
    
  2018.       !didWarnDefaultTextareaValue
    
  2019.     ) {
    
  2020.       console.error(
    
  2021.         'Textarea elements must be either controlled or uncontrolled ' +
    
  2022.           '(specify either the value prop, or the defaultValue prop, but not ' +
    
  2023.           'both). Decide between using a controlled or uncontrolled textarea ' +
    
  2024.           'and remove one of these props. More info: ' +
    
  2025.           'https://reactjs.org/link/controlled-components',
    
  2026.       );
    
  2027.       didWarnDefaultTextareaValue = true;
    
  2028.     }
    
  2029.   }
    
  2030. 
    
  2031.   target.push(startChunkForTag('textarea'));
    
  2032. 
    
  2033.   let value = null;
    
  2034.   let defaultValue = null;
    
  2035.   let children = null;
    
  2036.   for (const propKey in props) {
    
  2037.     if (hasOwnProperty.call(props, propKey)) {
    
  2038.       const propValue = props[propKey];
    
  2039.       if (propValue == null) {
    
  2040.         continue;
    
  2041.       }
    
  2042.       switch (propKey) {
    
  2043.         case 'children':
    
  2044.           children = propValue;
    
  2045.           break;
    
  2046.         case 'value':
    
  2047.           value = propValue;
    
  2048.           break;
    
  2049.         case 'defaultValue':
    
  2050.           defaultValue = propValue;
    
  2051.           break;
    
  2052.         case 'dangerouslySetInnerHTML':
    
  2053.           throw new Error(
    
  2054.             '`dangerouslySetInnerHTML` does not make sense on <textarea>.',
    
  2055.           );
    
  2056.         default:
    
  2057.           pushAttribute(target, propKey, propValue);
    
  2058.           break;
    
  2059.       }
    
  2060.     }
    
  2061.   }
    
  2062.   if (value === null && defaultValue !== null) {
    
  2063.     value = defaultValue;
    
  2064.   }
    
  2065. 
    
  2066.   target.push(endOfStartTag);
    
  2067. 
    
  2068.   // TODO (yungsters): Remove support for children content in <textarea>.
    
  2069.   if (children != null) {
    
  2070.     if (__DEV__) {
    
  2071.       console.error(
    
  2072.         'Use the `defaultValue` or `value` props instead of setting ' +
    
  2073.           'children on <textarea>.',
    
  2074.       );
    
  2075.     }
    
  2076. 
    
  2077.     if (value != null) {
    
  2078.       throw new Error(
    
  2079.         'If you supply `defaultValue` on a <textarea>, do not pass children.',
    
  2080.       );
    
  2081.     }
    
  2082. 
    
  2083.     if (isArray(children)) {
    
  2084.       if (children.length > 1) {
    
  2085.         throw new Error('<textarea> can only have at most one child.');
    
  2086.       }
    
  2087. 
    
  2088.       // TODO: remove the coercion and the DEV check below because it will
    
  2089.       // always be overwritten by the coercion several lines below it. #22309
    
  2090.       if (__DEV__) {
    
  2091.         checkHtmlStringCoercion(children[0]);
    
  2092.       }
    
  2093.       value = '' + children[0];
    
  2094.     }
    
  2095.     if (__DEV__) {
    
  2096.       checkHtmlStringCoercion(children);
    
  2097.     }
    
  2098.     value = '' + children;
    
  2099.   }
    
  2100. 
    
  2101.   if (typeof value === 'string' && value[0] === '\n') {
    
  2102.     // text/html ignores the first character in these tags if it's a newline
    
  2103.     // Prefer to break application/xml over text/html (for now) by adding
    
  2104.     // a newline specifically to get eaten by the parser. (Alternately for
    
  2105.     // textareas, replacing "^\n" with "\r\n" doesn't get eaten, and the first
    
  2106.     // \r is normalized out by HTMLTextAreaElement#value.)
    
  2107.     // See: <http://www.w3.org/TR/html-polyglot/#newlines-in-textarea-and-pre>
    
  2108.     // See: <http://www.w3.org/TR/html5/syntax.html#element-restrictions>
    
  2109.     // See: <http://www.w3.org/TR/html5/syntax.html#newlines>
    
  2110.     // See: Parsing of "textarea" "listing" and "pre" elements
    
  2111.     //  from <http://www.w3.org/TR/html5/syntax.html#parsing-main-inbody>
    
  2112.     target.push(leadingNewline);
    
  2113.   }
    
  2114. 
    
  2115.   // ToString and push directly instead of recurse over children.
    
  2116.   // We don't really support complex children in the value anyway.
    
  2117.   // This also currently avoids a trailing comment node which breaks textarea.
    
  2118.   if (value !== null) {
    
  2119.     if (__DEV__) {
    
  2120.       checkAttributeStringCoercion(value, 'value');
    
  2121.     }
    
  2122.     target.push(stringToChunk(encodeHTMLTextNode('' + value)));
    
  2123.   }
    
  2124. 
    
  2125.   return null;
    
  2126. }
    
  2127. 
    
  2128. function pushMeta(
    
  2129.   target: Array<Chunk | PrecomputedChunk>,
    
  2130.   props: Object,
    
  2131.   renderState: RenderState,
    
  2132.   textEmbedded: boolean,
    
  2133.   insertionMode: InsertionMode,
    
  2134.   noscriptTagInScope: boolean,
    
  2135. ): null {
    
  2136.   if (enableFloat) {
    
  2137.     if (
    
  2138.       insertionMode === SVG_MODE ||
    
  2139.       noscriptTagInScope ||
    
  2140.       props.itemProp != null
    
  2141.     ) {
    
  2142.       return pushSelfClosing(target, props, 'meta');
    
  2143.     } else {
    
  2144.       if (textEmbedded) {
    
  2145.         // This link follows text but we aren't writing a tag. while not as efficient as possible we need
    
  2146.         // to be safe and assume text will follow by inserting a textSeparator
    
  2147.         target.push(textSeparator);
    
  2148.       }
    
  2149. 
    
  2150.       if (typeof props.charSet === 'string') {
    
  2151.         return pushSelfClosing(renderState.charsetChunks, props, 'meta');
    
  2152.       } else if (props.name === 'viewport') {
    
  2153.         // "viewport" isn't related to preconnect but it has the right priority
    
  2154.         return pushSelfClosing(renderState.preconnectChunks, props, 'meta');
    
  2155.       } else {
    
  2156.         return pushSelfClosing(renderState.hoistableChunks, props, 'meta');
    
  2157.       }
    
  2158.     }
    
  2159.   } else {
    
  2160.     return pushSelfClosing(target, props, 'meta');
    
  2161.   }
    
  2162. }
    
  2163. 
    
  2164. function pushLink(
    
  2165.   target: Array<Chunk | PrecomputedChunk>,
    
  2166.   props: Object,
    
  2167.   resumableState: ResumableState,
    
  2168.   renderState: RenderState,
    
  2169.   textEmbedded: boolean,
    
  2170.   insertionMode: InsertionMode,
    
  2171.   noscriptTagInScope: boolean,
    
  2172. ): null {
    
  2173.   if (enableFloat) {
    
  2174.     const rel = props.rel;
    
  2175.     const href = props.href;
    
  2176.     const precedence = props.precedence;
    
  2177.     if (
    
  2178.       insertionMode === SVG_MODE ||
    
  2179.       noscriptTagInScope ||
    
  2180.       props.itemProp != null ||
    
  2181.       typeof rel !== 'string' ||
    
  2182.       typeof href !== 'string' ||
    
  2183.       href === ''
    
  2184.     ) {
    
  2185.       if (__DEV__) {
    
  2186.         if (rel === 'stylesheet' && typeof props.precedence === 'string') {
    
  2187.           if (typeof href !== 'string' || !href) {
    
  2188.             console.error(
    
  2189.               'React encountered a `<link rel="stylesheet" .../>` with a `precedence` prop and expected the `href` prop to be a non-empty string but ecountered %s instead. If your intent was to have React hoist and deduplciate this stylesheet using the `precedence` prop ensure there is a non-empty string `href` prop as well, otherwise remove the `precedence` prop.',
    
  2190.               getValueDescriptorExpectingObjectForWarning(href),
    
  2191.             );
    
  2192.           }
    
  2193.         }
    
  2194.       }
    
  2195.       pushLinkImpl(target, props);
    
  2196.       return null;
    
  2197.     }
    
  2198. 
    
  2199.     if (props.rel === 'stylesheet') {
    
  2200.       // This <link> may hoistable as a Stylesheet Resource, otherwise it will emit in place
    
  2201.       const key = getResourceKey(href);
    
  2202.       if (
    
  2203.         typeof precedence !== 'string' ||
    
  2204.         props.disabled != null ||
    
  2205.         props.onLoad ||
    
  2206.         props.onError
    
  2207.       ) {
    
  2208.         // This stylesheet is either not opted into Resource semantics or has conflicting properties which
    
  2209.         // disqualify it for such. We can still create a preload resource to help it load faster on the
    
  2210.         // client
    
  2211.         if (__DEV__) {
    
  2212.           if (typeof precedence === 'string') {
    
  2213.             if (props.disabled != null) {
    
  2214.               console.error(
    
  2215.                 'React encountered a `<link rel="stylesheet" .../>` with a `precedence` prop and a `disabled` prop. The presence of the `disabled` prop indicates an intent to manage the stylesheet active state from your from your Component code and React will not hoist or deduplicate this stylesheet. If your intent was to have React hoist and deduplciate this stylesheet using the `precedence` prop remove the `disabled` prop, otherwise remove the `precedence` prop.',
    
  2216.               );
    
  2217.             } else if (props.onLoad || props.onError) {
    
  2218.               const propDescription =
    
  2219.                 props.onLoad && props.onError
    
  2220.                   ? '`onLoad` and `onError` props'
    
  2221.                   : props.onLoad
    
  2222.                   ? '`onLoad` prop'
    
  2223.                   : '`onError` prop';
    
  2224.               console.error(
    
  2225.                 'React encountered a `<link rel="stylesheet" .../>` with a `precedence` prop and %s. The presence of loading and error handlers indicates an intent to manage the stylesheet loading state from your from your Component code and React will not hoist or deduplicate this stylesheet. If your intent was to have React hoist and deduplciate this stylesheet using the `precedence` prop remove the %s, otherwise remove the `precedence` prop.',
    
  2226.                 propDescription,
    
  2227.                 propDescription,
    
  2228.               );
    
  2229.             }
    
  2230.           }
    
  2231.         }
    
  2232.         return pushLinkImpl(target, props);
    
  2233.       } else {
    
  2234.         // This stylesheet refers to a Resource and we create a new one if necessary
    
  2235.         let styleQueue = renderState.styles.get(precedence);
    
  2236.         const hasKey = resumableState.styleResources.hasOwnProperty(key);
    
  2237.         const resourceState = hasKey
    
  2238.           ? resumableState.styleResources[key]
    
  2239.           : undefined;
    
  2240.         if (resourceState !== EXISTS) {
    
  2241.           // We are going to create this resource now so it is marked as Exists
    
  2242.           resumableState.styleResources[key] = EXISTS;
    
  2243. 
    
  2244.           // If this is the first time we've encountered this precedence we need
    
  2245.           // to create a StyleQueue
    
  2246.           if (!styleQueue) {
    
  2247.             styleQueue = {
    
  2248.               precedence: stringToChunk(escapeTextForBrowser(precedence)),
    
  2249.               rules: ([]: Array<Chunk | PrecomputedChunk>),
    
  2250.               hrefs: ([]: Array<Chunk | PrecomputedChunk>),
    
  2251.               sheets: (new Map(): Map<string, StylesheetResource>),
    
  2252.             };
    
  2253.             renderState.styles.set(precedence, styleQueue);
    
  2254.           }
    
  2255. 
    
  2256.           const resource: StylesheetResource = {
    
  2257.             state: PENDING,
    
  2258.             props: stylesheetPropsFromRawProps(props),
    
  2259.           };
    
  2260. 
    
  2261.           if (resourceState) {
    
  2262.             // When resourceState is truty it is a Preload state. We cast it for clarity
    
  2263.             const preloadState: Preloaded | PreloadedWithCredentials =
    
  2264.               resourceState;
    
  2265.             if (preloadState.length === 2) {
    
  2266.               adoptPreloadCredentials(resource.props, preloadState);
    
  2267.             }
    
  2268. 
    
  2269.             const preloadResource = renderState.preloads.stylesheets.get(key);
    
  2270.             if (preloadResource && preloadResource.length > 0) {
    
  2271.               // The Preload for this resource was created in this render pass and has not flushed yet so
    
  2272.               // we need to clear it to avoid it flushing.
    
  2273.               preloadResource.length = 0;
    
  2274.             } else {
    
  2275.               // Either the preload resource from this render already flushed in this render pass
    
  2276.               // or the preload flushed in a prior pass (prerender). In either case we need to mark
    
  2277.               // this resource as already having been preloaded.
    
  2278.               resource.state = PRELOADED;
    
  2279.             }
    
  2280.           } else {
    
  2281.             // We don't need to check whether a preloadResource exists in the renderState
    
  2282.             // because if it did exist then the resourceState would also exist and we would
    
  2283.             // have hit the primary if condition above.
    
  2284.           }
    
  2285. 
    
  2286.           // We add the newly created resource to our StyleQueue and if necessary
    
  2287.           // track the resource with the currently rendering boundary
    
  2288.           styleQueue.sheets.set(key, resource);
    
  2289.           if (renderState.boundaryResources) {
    
  2290.             renderState.boundaryResources.stylesheets.add(resource);
    
  2291.           }
    
  2292.         } else {
    
  2293.           // We need to track whether this boundary should wait on this resource or not.
    
  2294.           // Typically this resource should always exist since we either had it or just created
    
  2295.           // it. However, it's possible when you resume that the style has already been emitted
    
  2296.           // and then it wouldn't be recreated in the RenderState and there's no need to track
    
  2297.           // it again since we should've hoisted it to the shell already.
    
  2298.           if (styleQueue) {
    
  2299.             const resource = styleQueue.sheets.get(key);
    
  2300.             if (resource) {
    
  2301.               if (renderState.boundaryResources) {
    
  2302.                 renderState.boundaryResources.stylesheets.add(resource);
    
  2303.               }
    
  2304.             }
    
  2305.           }
    
  2306.         }
    
  2307.         if (textEmbedded) {
    
  2308.           // This link follows text but we aren't writing a tag. while not as efficient as possible we need
    
  2309.           // to be safe and assume text will follow by inserting a textSeparator
    
  2310.           target.push(textSeparator);
    
  2311.         }
    
  2312.         return null;
    
  2313.       }
    
  2314.     } else if (props.onLoad || props.onError) {
    
  2315.       // When using load handlers we cannot hoist and need to emit links in place
    
  2316.       return pushLinkImpl(target, props);
    
  2317.     } else {
    
  2318.       // We can hoist this link so we may need to emit a text separator.
    
  2319.       // @TODO refactor text separators so we don't have to defensively add
    
  2320.       // them when we don't end up emitting a tag as a result of pushStartInstance
    
  2321.       if (textEmbedded) {
    
  2322.         // This link follows text but we aren't writing a tag. while not as efficient as possible we need
    
  2323.         // to be safe and assume text will follow by inserting a textSeparator
    
  2324.         target.push(textSeparator);
    
  2325.       }
    
  2326. 
    
  2327.       switch (props.rel) {
    
  2328.         case 'preconnect':
    
  2329.         case 'dns-prefetch':
    
  2330.           return pushLinkImpl(renderState.preconnectChunks, props);
    
  2331.         case 'preload':
    
  2332.           return pushLinkImpl(renderState.preloadChunks, props);
    
  2333.         default:
    
  2334.           return pushLinkImpl(renderState.hoistableChunks, props);
    
  2335.       }
    
  2336.     }
    
  2337.   } else {
    
  2338.     return pushLinkImpl(target, props);
    
  2339.   }
    
  2340. }
    
  2341. 
    
  2342. function pushLinkImpl(
    
  2343.   target: Array<Chunk | PrecomputedChunk>,
    
  2344.   props: Object,
    
  2345. ): null {
    
  2346.   target.push(startChunkForTag('link'));
    
  2347. 
    
  2348.   for (const propKey in props) {
    
  2349.     if (hasOwnProperty.call(props, propKey)) {
    
  2350.       const propValue = props[propKey];
    
  2351.       if (propValue == null) {
    
  2352.         continue;
    
  2353.       }
    
  2354.       switch (propKey) {
    
  2355.         case 'children':
    
  2356.         case 'dangerouslySetInnerHTML':
    
  2357.           throw new Error(
    
  2358.             `${'link'} is a self-closing tag and must neither have \`children\` nor ` +
    
  2359.               'use `dangerouslySetInnerHTML`.',
    
  2360.           );
    
  2361.         default:
    
  2362.           pushAttribute(target, propKey, propValue);
    
  2363.           break;
    
  2364.       }
    
  2365.     }
    
  2366.   }
    
  2367. 
    
  2368.   target.push(endOfStartTagSelfClosing);
    
  2369.   return null;
    
  2370. }
    
  2371. 
    
  2372. function pushStyle(
    
  2373.   target: Array<Chunk | PrecomputedChunk>,
    
  2374.   props: Object,
    
  2375.   resumableState: ResumableState,
    
  2376.   renderState: RenderState,
    
  2377.   textEmbedded: boolean,
    
  2378.   insertionMode: InsertionMode,
    
  2379.   noscriptTagInScope: boolean,
    
  2380. ): ReactNodeList {
    
  2381.   if (__DEV__) {
    
  2382.     if (hasOwnProperty.call(props, 'children')) {
    
  2383.       const children = props.children;
    
  2384. 
    
  2385.       const child = Array.isArray(children)
    
  2386.         ? children.length < 2
    
  2387.           ? children[0]
    
  2388.           : null
    
  2389.         : children;
    
  2390. 
    
  2391.       if (
    
  2392.         typeof child === 'function' ||
    
  2393.         typeof child === 'symbol' ||
    
  2394.         Array.isArray(child)
    
  2395.       ) {
    
  2396.         const childType =
    
  2397.           typeof child === 'function'
    
  2398.             ? 'a Function'
    
  2399.             : typeof child === 'symbol'
    
  2400.             ? 'a Sybmol'
    
  2401.             : 'an Array';
    
  2402.         console.error(
    
  2403.           'React expect children of <style> tags to be a string, number, or object with a `toString` method but found %s instead. ' +
    
  2404.             'In browsers style Elements can only have `Text` Nodes as children.',
    
  2405.           childType,
    
  2406.         );
    
  2407.       }
    
  2408.     }
    
  2409.   }
    
  2410.   if (enableFloat) {
    
  2411.     const precedence = props.precedence;
    
  2412.     const href = props.href;
    
  2413. 
    
  2414.     if (
    
  2415.       insertionMode === SVG_MODE ||
    
  2416.       noscriptTagInScope ||
    
  2417.       props.itemProp != null ||
    
  2418.       typeof precedence !== 'string' ||
    
  2419.       typeof href !== 'string' ||
    
  2420.       href === ''
    
  2421.     ) {
    
  2422.       // This style tag is not able to be turned into a Style Resource
    
  2423.       return pushStyleImpl(target, props);
    
  2424.     }
    
  2425. 
    
  2426.     if (__DEV__) {
    
  2427.       if (href.includes(' ')) {
    
  2428.         console.error(
    
  2429.           'React expected the `href` prop for a <style> tag opting into hoisting semantics using the `precedence` prop to not have any spaces but ecountered spaces instead. using spaces in this prop will cause hydration of this style to fail on the client. The href for the <style> where this ocurred is "%s".',
    
  2430.           href,
    
  2431.         );
    
  2432.       }
    
  2433.     }
    
  2434. 
    
  2435.     const key = getResourceKey(href);
    
  2436.     let styleQueue = renderState.styles.get(precedence);
    
  2437.     const hasKey = resumableState.styleResources.hasOwnProperty(key);
    
  2438.     const resourceState = hasKey
    
  2439.       ? resumableState.styleResources[key]
    
  2440.       : undefined;
    
  2441.     if (resourceState !== EXISTS) {
    
  2442.       // We are going to create this resource now so it is marked as Exists
    
  2443.       resumableState.styleResources[key] = EXISTS;
    
  2444. 
    
  2445.       if (__DEV__) {
    
  2446.         if (resourceState) {
    
  2447.           console.error(
    
  2448.             'React encountered a hoistable style tag for the same href as a preload: "%s". When using a style tag to inline styles you should not also preload it as a stylsheet.',
    
  2449.             href,
    
  2450.           );
    
  2451.         }
    
  2452.       }
    
  2453. 
    
  2454.       if (!styleQueue) {
    
  2455.         // This is the first time we've encountered this precedence we need
    
  2456.         // to create a StyleQueue.
    
  2457.         styleQueue = {
    
  2458.           precedence: stringToChunk(escapeTextForBrowser(precedence)),
    
  2459.           rules: ([]: Array<Chunk | PrecomputedChunk>),
    
  2460.           hrefs: [stringToChunk(escapeTextForBrowser(href))],
    
  2461.           sheets: (new Map(): Map<string, StylesheetResource>),
    
  2462.         };
    
  2463.         renderState.styles.set(precedence, styleQueue);
    
  2464.       } else {
    
  2465.         // We have seen this precedence before and need to track this href
    
  2466.         styleQueue.hrefs.push(stringToChunk(escapeTextForBrowser(href)));
    
  2467.       }
    
  2468.       pushStyleContents(styleQueue.rules, props);
    
  2469.     }
    
  2470.     if (styleQueue) {
    
  2471.       // We need to track whether this boundary should wait on this resource or not.
    
  2472.       // Typically this resource should always exist since we either had it or just created
    
  2473.       // it. However, it's possible when you resume that the style has already been emitted
    
  2474.       // and then it wouldn't be recreated in the RenderState and there's no need to track
    
  2475.       // it again since we should've hoisted it to the shell already.
    
  2476.       if (renderState.boundaryResources) {
    
  2477.         renderState.boundaryResources.styles.add(styleQueue);
    
  2478.       }
    
  2479.     }
    
  2480. 
    
  2481.     if (textEmbedded) {
    
  2482.       // This link follows text but we aren't writing a tag. while not as efficient as possible we need
    
  2483.       // to be safe and assume text will follow by inserting a textSeparator
    
  2484.       target.push(textSeparator);
    
  2485.     }
    
  2486.   } else {
    
  2487.     return pushStartGenericElement(target, props, 'style');
    
  2488.   }
    
  2489. }
    
  2490. 
    
  2491. function pushStyleImpl(
    
  2492.   target: Array<Chunk | PrecomputedChunk>,
    
  2493.   props: Object,
    
  2494. ): ReactNodeList {
    
  2495.   target.push(startChunkForTag('style'));
    
  2496. 
    
  2497.   let children = null;
    
  2498.   let innerHTML = null;
    
  2499.   for (const propKey in props) {
    
  2500.     if (hasOwnProperty.call(props, propKey)) {
    
  2501.       const propValue = props[propKey];
    
  2502.       if (propValue == null) {
    
  2503.         continue;
    
  2504.       }
    
  2505.       switch (propKey) {
    
  2506.         case 'children':
    
  2507.           children = propValue;
    
  2508.           break;
    
  2509.         case 'dangerouslySetInnerHTML':
    
  2510.           innerHTML = propValue;
    
  2511.           break;
    
  2512.         default:
    
  2513.           pushAttribute(target, propKey, propValue);
    
  2514.           break;
    
  2515.       }
    
  2516.     }
    
  2517.   }
    
  2518.   target.push(endOfStartTag);
    
  2519. 
    
  2520.   const child = Array.isArray(children)
    
  2521.     ? children.length < 2
    
  2522.       ? children[0]
    
  2523.       : null
    
  2524.     : children;
    
  2525.   if (
    
  2526.     typeof child !== 'function' &&
    
  2527.     typeof child !== 'symbol' &&
    
  2528.     child !== null &&
    
  2529.     child !== undefined
    
  2530.   ) {
    
  2531.     // eslint-disable-next-line react-internal/safe-string-coercion
    
  2532.     target.push(stringToChunk(escapeTextForBrowser('' + child)));
    
  2533.   }
    
  2534.   pushInnerHTML(target, innerHTML, children);
    
  2535.   target.push(endChunkForTag('style'));
    
  2536.   return null;
    
  2537. }
    
  2538. 
    
  2539. function pushStyleContents(
    
  2540.   target: Array<Chunk | PrecomputedChunk>,
    
  2541.   props: Object,
    
  2542. ): void {
    
  2543.   let children = null;
    
  2544.   let innerHTML = null;
    
  2545.   for (const propKey in props) {
    
  2546.     if (hasOwnProperty.call(props, propKey)) {
    
  2547.       const propValue = props[propKey];
    
  2548.       if (propValue == null) {
    
  2549.         continue;
    
  2550.       }
    
  2551.       switch (propKey) {
    
  2552.         case 'children':
    
  2553.           children = propValue;
    
  2554.           break;
    
  2555.         case 'dangerouslySetInnerHTML':
    
  2556.           innerHTML = propValue;
    
  2557.           break;
    
  2558.       }
    
  2559.     }
    
  2560.   }
    
  2561. 
    
  2562.   const child = Array.isArray(children)
    
  2563.     ? children.length < 2
    
  2564.       ? children[0]
    
  2565.       : null
    
  2566.     : children;
    
  2567.   if (
    
  2568.     typeof child !== 'function' &&
    
  2569.     typeof child !== 'symbol' &&
    
  2570.     child !== null &&
    
  2571.     child !== undefined
    
  2572.   ) {
    
  2573.     // eslint-disable-next-line react-internal/safe-string-coercion
    
  2574.     target.push(stringToChunk(escapeTextForBrowser('' + child)));
    
  2575.   }
    
  2576.   pushInnerHTML(target, innerHTML, children);
    
  2577.   return;
    
  2578. }
    
  2579. 
    
  2580. function pushImg(
    
  2581.   target: Array<Chunk | PrecomputedChunk>,
    
  2582.   props: Object,
    
  2583.   resumableState: ResumableState,
    
  2584.   renderState: RenderState,
    
  2585.   pictureTagInScope: boolean,
    
  2586. ): null {
    
  2587.   const {src, srcSet} = props;
    
  2588.   if (
    
  2589.     props.loading !== 'lazy' &&
    
  2590.     (src || srcSet) &&
    
  2591.     (typeof src === 'string' || src == null) &&
    
  2592.     (typeof srcSet === 'string' || srcSet == null) &&
    
  2593.     props.fetchPriority !== 'low' &&
    
  2594.     pictureTagInScope === false &&
    
  2595.     // We exclude data URIs in src and srcSet since these should not be preloaded
    
  2596.     !(
    
  2597.       typeof src === 'string' &&
    
  2598.       src[4] === ':' &&
    
  2599.       (src[0] === 'd' || src[0] === 'D') &&
    
  2600.       (src[1] === 'a' || src[1] === 'A') &&
    
  2601.       (src[2] === 't' || src[2] === 'T') &&
    
  2602.       (src[3] === 'a' || src[3] === 'A')
    
  2603.     ) &&
    
  2604.     !(
    
  2605.       typeof srcSet === 'string' &&
    
  2606.       srcSet[4] === ':' &&
    
  2607.       (srcSet[0] === 'd' || srcSet[0] === 'D') &&
    
  2608.       (srcSet[1] === 'a' || srcSet[1] === 'A') &&
    
  2609.       (srcSet[2] === 't' || srcSet[2] === 'T') &&
    
  2610.       (srcSet[3] === 'a' || srcSet[3] === 'A')
    
  2611.     )
    
  2612.   ) {
    
  2613.     // We have a suspensey image and ought to preload it to optimize the loading of display blocking
    
  2614.     // resumableState.
    
  2615.     const sizes = typeof props.sizes === 'string' ? props.sizes : undefined;
    
  2616.     const key = getImageResourceKey(src, srcSet, sizes);
    
  2617. 
    
  2618.     const promotablePreloads = renderState.preloads.images;
    
  2619. 
    
  2620.     let resource = promotablePreloads.get(key);
    
  2621.     if (resource) {
    
  2622.       // We consider whether this preload can be promoted to higher priority flushing queue.
    
  2623.       // The only time a resource will exist here is if it was created during this render
    
  2624.       // and was not already in the high priority queue.
    
  2625.       if (
    
  2626.         props.fetchPriority === 'high' ||
    
  2627.         renderState.highImagePreloads.size < 10
    
  2628.       ) {
    
  2629.         // Delete the resource from the map since we are promoting it and don't want to
    
  2630.         // reenter this branch in a second pass for duplicate img hrefs.
    
  2631.         promotablePreloads.delete(key);
    
  2632. 
    
  2633.         // $FlowFixMe - Flow should understand that this is a Resource if the condition was true
    
  2634.         renderState.highImagePreloads.add(resource);
    
  2635.       }
    
  2636.     } else if (!resumableState.imageResources.hasOwnProperty(key)) {
    
  2637.       // We must construct a new preload resource
    
  2638.       resumableState.imageResources[key] = PRELOAD_NO_CREDS;
    
  2639.       resource = [];
    
  2640.       pushLinkImpl(
    
  2641.         resource,
    
  2642.         ({
    
  2643.           rel: 'preload',
    
  2644.           as: 'image',
    
  2645.           // There is a bug in Safari where imageSrcSet is not respected on preload links
    
  2646.           // so we omit the href here if we have imageSrcSet b/c safari will load the wrong image.
    
  2647.           // This harms older browers that do not support imageSrcSet by making their preloads not work
    
  2648.           // but this population is shrinking fast and is already small so we accept this tradeoff.
    
  2649.           href: srcSet ? undefined : src,
    
  2650.           imageSrcSet: srcSet,
    
  2651.           imageSizes: sizes,
    
  2652.           crossOrigin: props.crossOrigin,
    
  2653.           integrity: props.integrity,
    
  2654.           type: props.type,
    
  2655.           fetchPriority: props.fetchPriority,
    
  2656.           referrerPolicy: props.referrerPolicy,
    
  2657.         }: PreloadProps),
    
  2658.       );
    
  2659.       if (
    
  2660.         props.fetchPriority === 'high' ||
    
  2661.         renderState.highImagePreloads.size < 10
    
  2662.       ) {
    
  2663.         renderState.highImagePreloads.add(resource);
    
  2664.       } else {
    
  2665.         renderState.bulkPreloads.add(resource);
    
  2666.         // We can bump the priority up if the same img is rendered later
    
  2667.         // with fetchPriority="high"
    
  2668.         promotablePreloads.set(key, resource);
    
  2669.       }
    
  2670.     }
    
  2671.   }
    
  2672.   return pushSelfClosing(target, props, 'img');
    
  2673. }
    
  2674. 
    
  2675. function pushSelfClosing(
    
  2676.   target: Array<Chunk | PrecomputedChunk>,
    
  2677.   props: Object,
    
  2678.   tag: string,
    
  2679. ): null {
    
  2680.   target.push(startChunkForTag(tag));
    
  2681. 
    
  2682.   for (const propKey in props) {
    
  2683.     if (hasOwnProperty.call(props, propKey)) {
    
  2684.       const propValue = props[propKey];
    
  2685.       if (propValue == null) {
    
  2686.         continue;
    
  2687.       }
    
  2688.       switch (propKey) {
    
  2689.         case 'children':
    
  2690.         case 'dangerouslySetInnerHTML':
    
  2691.           throw new Error(
    
  2692.             `${tag} is a self-closing tag and must neither have \`children\` nor ` +
    
  2693.               'use `dangerouslySetInnerHTML`.',
    
  2694.           );
    
  2695.         default:
    
  2696.           pushAttribute(target, propKey, propValue);
    
  2697.           break;
    
  2698.       }
    
  2699.     }
    
  2700.   }
    
  2701. 
    
  2702.   target.push(endOfStartTagSelfClosing);
    
  2703.   return null;
    
  2704. }
    
  2705. 
    
  2706. function pushStartMenuItem(
    
  2707.   target: Array<Chunk | PrecomputedChunk>,
    
  2708.   props: Object,
    
  2709. ): ReactNodeList {
    
  2710.   target.push(startChunkForTag('menuitem'));
    
  2711. 
    
  2712.   for (const propKey in props) {
    
  2713.     if (hasOwnProperty.call(props, propKey)) {
    
  2714.       const propValue = props[propKey];
    
  2715.       if (propValue == null) {
    
  2716.         continue;
    
  2717.       }
    
  2718.       switch (propKey) {
    
  2719.         case 'children':
    
  2720.         case 'dangerouslySetInnerHTML':
    
  2721.           throw new Error(
    
  2722.             'menuitems cannot have `children` nor `dangerouslySetInnerHTML`.',
    
  2723.           );
    
  2724.         default:
    
  2725.           pushAttribute(target, propKey, propValue);
    
  2726.           break;
    
  2727.       }
    
  2728.     }
    
  2729.   }
    
  2730. 
    
  2731.   target.push(endOfStartTag);
    
  2732.   return null;
    
  2733. }
    
  2734. 
    
  2735. function pushTitle(
    
  2736.   target: Array<Chunk | PrecomputedChunk>,
    
  2737.   props: Object,
    
  2738.   renderState: RenderState,
    
  2739.   insertionMode: InsertionMode,
    
  2740.   noscriptTagInScope: boolean,
    
  2741. ): ReactNodeList {
    
  2742.   if (__DEV__) {
    
  2743.     if (hasOwnProperty.call(props, 'children')) {
    
  2744.       const children = props.children;
    
  2745. 
    
  2746.       const child = Array.isArray(children)
    
  2747.         ? children.length < 2
    
  2748.           ? children[0]
    
  2749.           : null
    
  2750.         : children;
    
  2751. 
    
  2752.       if (Array.isArray(children) && children.length > 1) {
    
  2753.         console.error(
    
  2754.           'React expects the `children` prop of <title> tags to be a string, number, or object with a novel `toString` method but found an Array with length %s instead.' +
    
  2755.             ' Browsers treat all child Nodes of <title> tags as Text content and React expects to be able to convert `children` of <title> tags to a single string value' +
    
  2756.             ' which is why Arrays of length greater than 1 are not supported. When using JSX it can be commong to combine text nodes and value nodes.' +
    
  2757.             ' For example: <title>hello {nameOfUser}</title>. While not immediately apparent, `children` in this case is an Array with length 2. If your `children` prop' +
    
  2758.             ' is using this form try rewriting it using a template string: <title>{`hello ${nameOfUser}`}</title>.',
    
  2759.           children.length,
    
  2760.         );
    
  2761.       } else if (typeof child === 'function' || typeof child === 'symbol') {
    
  2762.         const childType =
    
  2763.           typeof child === 'function' ? 'a Function' : 'a Sybmol';
    
  2764.         console.error(
    
  2765.           'React expect children of <title> tags to be a string, number, or object with a novel `toString` method but found %s instead.' +
    
  2766.             ' Browsers treat all child Nodes of <title> tags as Text content and React expects to be able to convert children of <title>' +
    
  2767.             ' tags to a single string value.',
    
  2768.           childType,
    
  2769.         );
    
  2770.       } else if (child && child.toString === {}.toString) {
    
  2771.         if (child.$$typeof != null) {
    
  2772.           console.error(
    
  2773.             'React expects the `children` prop of <title> tags to be a string, number, or object with a novel `toString` method but found an object that appears to be' +
    
  2774.               ' a React element which never implements a suitable `toString` method. Browsers treat all child Nodes of <title> tags as Text content and React expects to' +
    
  2775.               ' be able to convert children of <title> tags to a single string value which is why rendering React elements is not supported. If the `children` of <title> is' +
    
  2776.               ' a React Component try moving the <title> tag into that component. If the `children` of <title> is some HTML markup change it to be Text only to be valid HTML.',
    
  2777.           );
    
  2778.         } else {
    
  2779.           console.error(
    
  2780.             'React expects the `children` prop of <title> tags to be a string, number, or object with a novel `toString` method but found an object that does not implement' +
    
  2781.               ' a suitable `toString` method. Browsers treat all child Nodes of <title> tags as Text content and React expects to be able to convert children of <title> tags' +
    
  2782.               ' to a single string value. Using the default `toString` method available on every object is almost certainly an error. Consider whether the `children` of this <title>' +
    
  2783.               ' is an object in error and change it to a string or number value if so. Otherwise implement a `toString` method that React can use to produce a valid <title>.',
    
  2784.           );
    
  2785.         }
    
  2786.       }
    
  2787.     }
    
  2788.   }
    
  2789. 
    
  2790.   if (enableFloat) {
    
  2791.     if (
    
  2792.       insertionMode !== SVG_MODE &&
    
  2793.       !noscriptTagInScope &&
    
  2794.       props.itemProp == null
    
  2795.     ) {
    
  2796.       pushTitleImpl(renderState.hoistableChunks, props);
    
  2797.       return null;
    
  2798.     } else {
    
  2799.       return pushTitleImpl(target, props);
    
  2800.     }
    
  2801.   } else {
    
  2802.     return pushTitleImpl(target, props);
    
  2803.   }
    
  2804. }
    
  2805. 
    
  2806. function pushTitleImpl(
    
  2807.   target: Array<Chunk | PrecomputedChunk>,
    
  2808.   props: Object,
    
  2809. ): null {
    
  2810.   target.push(startChunkForTag('title'));
    
  2811. 
    
  2812.   let children = null;
    
  2813.   let innerHTML = null;
    
  2814.   for (const propKey in props) {
    
  2815.     if (hasOwnProperty.call(props, propKey)) {
    
  2816.       const propValue = props[propKey];
    
  2817.       if (propValue == null) {
    
  2818.         continue;
    
  2819.       }
    
  2820.       switch (propKey) {
    
  2821.         case 'children':
    
  2822.           children = propValue;
    
  2823.           break;
    
  2824.         case 'dangerouslySetInnerHTML':
    
  2825.           innerHTML = propValue;
    
  2826.           break;
    
  2827.         default:
    
  2828.           pushAttribute(target, propKey, propValue);
    
  2829.           break;
    
  2830.       }
    
  2831.     }
    
  2832.   }
    
  2833.   target.push(endOfStartTag);
    
  2834. 
    
  2835.   const child = Array.isArray(children)
    
  2836.     ? children.length < 2
    
  2837.       ? children[0]
    
  2838.       : null
    
  2839.     : children;
    
  2840.   if (
    
  2841.     typeof child !== 'function' &&
    
  2842.     typeof child !== 'symbol' &&
    
  2843.     child !== null &&
    
  2844.     child !== undefined
    
  2845.   ) {
    
  2846.     // eslint-disable-next-line react-internal/safe-string-coercion
    
  2847.     target.push(stringToChunk(escapeTextForBrowser('' + child)));
    
  2848.   }
    
  2849.   pushInnerHTML(target, innerHTML, children);
    
  2850.   target.push(endChunkForTag('title'));
    
  2851.   return null;
    
  2852. }
    
  2853. 
    
  2854. function pushStartTitle(
    
  2855.   target: Array<Chunk | PrecomputedChunk>,
    
  2856.   props: Object,
    
  2857. ): ReactNodeList {
    
  2858.   target.push(startChunkForTag('title'));
    
  2859. 
    
  2860.   let children = null;
    
  2861.   for (const propKey in props) {
    
  2862.     if (hasOwnProperty.call(props, propKey)) {
    
  2863.       const propValue = props[propKey];
    
  2864.       if (propValue == null) {
    
  2865.         continue;
    
  2866.       }
    
  2867.       switch (propKey) {
    
  2868.         case 'children':
    
  2869.           children = propValue;
    
  2870.           break;
    
  2871.         case 'dangerouslySetInnerHTML':
    
  2872.           throw new Error(
    
  2873.             '`dangerouslySetInnerHTML` does not make sense on <title>.',
    
  2874.           );
    
  2875.         default:
    
  2876.           pushAttribute(target, propKey, propValue);
    
  2877.           break;
    
  2878.       }
    
  2879.     }
    
  2880.   }
    
  2881.   target.push(endOfStartTag);
    
  2882. 
    
  2883.   if (__DEV__) {
    
  2884.     const childForValidation =
    
  2885.       Array.isArray(children) && children.length < 2
    
  2886.         ? children[0] || null
    
  2887.         : children;
    
  2888.     if (Array.isArray(children) && children.length > 1) {
    
  2889.       console.error(
    
  2890.         'A title element received an array with more than 1 element as children. ' +
    
  2891.           'In browsers title Elements can only have Text Nodes as children. If ' +
    
  2892.           'the children being rendered output more than a single text node in aggregate the browser ' +
    
  2893.           'will display markup and comments as text in the title and hydration will likely fail and ' +
    
  2894.           'fall back to client rendering',
    
  2895.       );
    
  2896.     } else if (
    
  2897.       childForValidation != null &&
    
  2898.       childForValidation.$$typeof != null
    
  2899.     ) {
    
  2900.       console.error(
    
  2901.         'A title element received a React element for children. ' +
    
  2902.           'In the browser title Elements can only have Text Nodes as children. If ' +
    
  2903.           'the children being rendered output more than a single text node in aggregate the browser ' +
    
  2904.           'will display markup and comments as text in the title and hydration will likely fail and ' +
    
  2905.           'fall back to client rendering',
    
  2906.       );
    
  2907.     } else if (
    
  2908.       childForValidation != null &&
    
  2909.       typeof childForValidation !== 'string' &&
    
  2910.       typeof childForValidation !== 'number'
    
  2911.     ) {
    
  2912.       console.error(
    
  2913.         'A title element received a value that was not a string or number for children. ' +
    
  2914.           'In the browser title Elements can only have Text Nodes as children. If ' +
    
  2915.           'the children being rendered output more than a single text node in aggregate the browser ' +
    
  2916.           'will display markup and comments as text in the title and hydration will likely fail and ' +
    
  2917.           'fall back to client rendering',
    
  2918.       );
    
  2919.     }
    
  2920.   }
    
  2921. 
    
  2922.   return children;
    
  2923. }
    
  2924. 
    
  2925. function pushStartHead(
    
  2926.   target: Array<Chunk | PrecomputedChunk>,
    
  2927.   props: Object,
    
  2928.   renderState: RenderState,
    
  2929.   insertionMode: InsertionMode,
    
  2930. ): ReactNodeList {
    
  2931.   if (enableFloat) {
    
  2932.     if (insertionMode < HTML_MODE && renderState.headChunks === null) {
    
  2933.       // This <head> is the Document.head and should be part of the preamble
    
  2934.       renderState.headChunks = [];
    
  2935.       return pushStartGenericElement(renderState.headChunks, props, 'head');
    
  2936.     } else {
    
  2937.       // This <head> is deep and is likely just an error. we emit it inline though.
    
  2938.       // Validation should warn that this tag is the the wrong spot.
    
  2939.       return pushStartGenericElement(target, props, 'head');
    
  2940.     }
    
  2941.   } else {
    
  2942.     return pushStartGenericElement(target, props, 'head');
    
  2943.   }
    
  2944. }
    
  2945. 
    
  2946. function pushStartHtml(
    
  2947.   target: Array<Chunk | PrecomputedChunk>,
    
  2948.   props: Object,
    
  2949.   renderState: RenderState,
    
  2950.   insertionMode: InsertionMode,
    
  2951. ): ReactNodeList {
    
  2952.   if (enableFloat) {
    
  2953.     if (insertionMode === ROOT_HTML_MODE && renderState.htmlChunks === null) {
    
  2954.       // This <html> is the Document.documentElement and should be part of the preamble
    
  2955.       renderState.htmlChunks = [DOCTYPE];
    
  2956.       return pushStartGenericElement(renderState.htmlChunks, props, 'html');
    
  2957.     } else {
    
  2958.       // This <html> is deep and is likely just an error. we emit it inline though.
    
  2959.       // Validation should warn that this tag is the the wrong spot.
    
  2960.       return pushStartGenericElement(target, props, 'html');
    
  2961.     }
    
  2962.   } else {
    
  2963.     if (insertionMode === ROOT_HTML_MODE) {
    
  2964.       // If we're rendering the html tag and we're at the root (i.e. not in foreignObject)
    
  2965.       // then we also emit the DOCTYPE as part of the root content as a convenience for
    
  2966.       // rendering the whole document.
    
  2967.       target.push(DOCTYPE);
    
  2968.     }
    
  2969.     return pushStartGenericElement(target, props, 'html');
    
  2970.   }
    
  2971. }
    
  2972. 
    
  2973. function pushScript(
    
  2974.   target: Array<Chunk | PrecomputedChunk>,
    
  2975.   props: Object,
    
  2976.   resumableState: ResumableState,
    
  2977.   renderState: RenderState,
    
  2978.   textEmbedded: boolean,
    
  2979.   insertionMode: InsertionMode,
    
  2980.   noscriptTagInScope: boolean,
    
  2981. ): null {
    
  2982.   if (enableFloat) {
    
  2983.     const asyncProp = props.async;
    
  2984.     if (
    
  2985.       typeof props.src !== 'string' ||
    
  2986.       !props.src ||
    
  2987.       !(
    
  2988.         asyncProp &&
    
  2989.         typeof asyncProp !== 'function' &&
    
  2990.         typeof asyncProp !== 'symbol'
    
  2991.       ) ||
    
  2992.       props.onLoad ||
    
  2993.       props.onError ||
    
  2994.       insertionMode === SVG_MODE ||
    
  2995.       noscriptTagInScope ||
    
  2996.       props.itemProp != null
    
  2997.     ) {
    
  2998.       // This script will not be a resource, we bailout early and emit it in place.
    
  2999.       return pushScriptImpl(target, props);
    
  3000.     }
    
  3001. 
    
  3002.     const src = props.src;
    
  3003.     const key = getResourceKey(src);
    
  3004.     // We can make this <script> into a ScriptResource
    
  3005. 
    
  3006.     let resources, preloads;
    
  3007.     if (props.type === 'module') {
    
  3008.       resources = resumableState.moduleScriptResources;
    
  3009.       preloads = renderState.preloads.moduleScripts;
    
  3010.     } else {
    
  3011.       resources = resumableState.scriptResources;
    
  3012.       preloads = renderState.preloads.scripts;
    
  3013.     }
    
  3014. 
    
  3015.     const hasKey = resources.hasOwnProperty(key);
    
  3016.     const resourceState = hasKey ? resources[key] : undefined;
    
  3017.     if (resourceState !== EXISTS) {
    
  3018.       // We are going to create this resource now so it is marked as Exists
    
  3019.       resources[key] = EXISTS;
    
  3020. 
    
  3021.       let scriptProps = props;
    
  3022.       if (resourceState) {
    
  3023.         // When resourceState is truty it is a Preload state. We cast it for clarity
    
  3024.         const preloadState: Preloaded | PreloadedWithCredentials =
    
  3025.           resourceState;
    
  3026.         if (preloadState.length === 2) {
    
  3027.           scriptProps = {...props};
    
  3028.           adoptPreloadCredentials(scriptProps, preloadState);
    
  3029.         }
    
  3030. 
    
  3031.         const preloadResource = preloads.get(key);
    
  3032.         if (preloadResource) {
    
  3033.           // the preload resource exists was created in this render. Now that we have
    
  3034.           // a script resource which will emit earlier than a preload would if it
    
  3035.           // hasn't already flushed we prevent it from flushing by zeroing the length
    
  3036.           preloadResource.length = 0;
    
  3037.         }
    
  3038.       }
    
  3039. 
    
  3040.       const resource: Resource = [];
    
  3041.       // Add to the script flushing queue
    
  3042.       renderState.scripts.add(resource);
    
  3043.       // encode the tag as Chunks
    
  3044.       pushScriptImpl(resource, scriptProps);
    
  3045.     }
    
  3046. 
    
  3047.     if (textEmbedded) {
    
  3048.       // This script follows text but we aren't writing a tag. while not as efficient as possible we need
    
  3049.       // to be safe and assume text will follow by inserting a textSeparator
    
  3050.       target.push(textSeparator);
    
  3051.     }
    
  3052.     return null;
    
  3053.   } else {
    
  3054.     return pushScriptImpl(target, props);
    
  3055.   }
    
  3056. }
    
  3057. 
    
  3058. function pushScriptImpl(
    
  3059.   target: Array<Chunk | PrecomputedChunk>,
    
  3060.   props: Object,
    
  3061. ): null {
    
  3062.   target.push(startChunkForTag('script'));
    
  3063. 
    
  3064.   let children = null;
    
  3065.   let innerHTML = null;
    
  3066.   for (const propKey in props) {
    
  3067.     if (hasOwnProperty.call(props, propKey)) {
    
  3068.       const propValue = props[propKey];
    
  3069.       if (propValue == null) {
    
  3070.         continue;
    
  3071.       }
    
  3072.       switch (propKey) {
    
  3073.         case 'children':
    
  3074.           children = propValue;
    
  3075.           break;
    
  3076.         case 'dangerouslySetInnerHTML':
    
  3077.           innerHTML = propValue;
    
  3078.           break;
    
  3079.         default:
    
  3080.           pushAttribute(target, propKey, propValue);
    
  3081.           break;
    
  3082.       }
    
  3083.     }
    
  3084.   }
    
  3085.   target.push(endOfStartTag);
    
  3086. 
    
  3087.   if (__DEV__) {
    
  3088.     if (children != null && typeof children !== 'string') {
    
  3089.       const descriptiveStatement =
    
  3090.         typeof children === 'number'
    
  3091.           ? 'a number for children'
    
  3092.           : Array.isArray(children)
    
  3093.           ? 'an array for children'
    
  3094.           : 'something unexpected for children';
    
  3095.       console.error(
    
  3096.         'A script element was rendered with %s. If script element has children it must be a single string.' +
    
  3097.           ' Consider using dangerouslySetInnerHTML or passing a plain string as children.',
    
  3098.         descriptiveStatement,
    
  3099.       );
    
  3100.     }
    
  3101.   }
    
  3102. 
    
  3103.   pushInnerHTML(target, innerHTML, children);
    
  3104.   if (typeof children === 'string') {
    
  3105.     target.push(stringToChunk(encodeHTMLTextNode(children)));
    
  3106.   }
    
  3107.   target.push(endChunkForTag('script'));
    
  3108.   return null;
    
  3109. }
    
  3110. 
    
  3111. function pushStartGenericElement(
    
  3112.   target: Array<Chunk | PrecomputedChunk>,
    
  3113.   props: Object,
    
  3114.   tag: string,
    
  3115. ): ReactNodeList {
    
  3116.   target.push(startChunkForTag(tag));
    
  3117. 
    
  3118.   let children = null;
    
  3119.   let innerHTML = null;
    
  3120.   for (const propKey in props) {
    
  3121.     if (hasOwnProperty.call(props, propKey)) {
    
  3122.       const propValue = props[propKey];
    
  3123.       if (propValue == null) {
    
  3124.         continue;
    
  3125.       }
    
  3126.       switch (propKey) {
    
  3127.         case 'children':
    
  3128.           children = propValue;
    
  3129.           break;
    
  3130.         case 'dangerouslySetInnerHTML':
    
  3131.           innerHTML = propValue;
    
  3132.           break;
    
  3133.         default:
    
  3134.           pushAttribute(target, propKey, propValue);
    
  3135.           break;
    
  3136.       }
    
  3137.     }
    
  3138.   }
    
  3139. 
    
  3140.   target.push(endOfStartTag);
    
  3141.   pushInnerHTML(target, innerHTML, children);
    
  3142.   if (typeof children === 'string') {
    
  3143.     // Special case children as a string to avoid the unnecessary comment.
    
  3144.     // TODO: Remove this special case after the general optimization is in place.
    
  3145.     target.push(stringToChunk(encodeHTMLTextNode(children)));
    
  3146.     return null;
    
  3147.   }
    
  3148.   return children;
    
  3149. }
    
  3150. 
    
  3151. function pushStartCustomElement(
    
  3152.   target: Array<Chunk | PrecomputedChunk>,
    
  3153.   props: Object,
    
  3154.   tag: string,
    
  3155. ): ReactNodeList {
    
  3156.   target.push(startChunkForTag(tag));
    
  3157. 
    
  3158.   let children = null;
    
  3159.   let innerHTML = null;
    
  3160.   for (const propKey in props) {
    
  3161.     if (hasOwnProperty.call(props, propKey)) {
    
  3162.       let propValue = props[propKey];
    
  3163.       if (propValue == null) {
    
  3164.         continue;
    
  3165.       }
    
  3166.       let attributeName = propKey;
    
  3167.       switch (propKey) {
    
  3168.         case 'children':
    
  3169.           children = propValue;
    
  3170.           break;
    
  3171.         case 'dangerouslySetInnerHTML':
    
  3172.           innerHTML = propValue;
    
  3173.           break;
    
  3174.         case 'style':
    
  3175.           pushStyleAttribute(target, propValue);
    
  3176.           break;
    
  3177.         case 'suppressContentEditableWarning':
    
  3178.         case 'suppressHydrationWarning':
    
  3179.           // Ignored. These are built-in to React on the client.
    
  3180.           break;
    
  3181.         case 'className':
    
  3182.           if (enableCustomElementPropertySupport) {
    
  3183.             // className gets rendered as class on the client, so it should be
    
  3184.             // rendered as class on the server.
    
  3185.             attributeName = 'class';
    
  3186.           }
    
  3187.         // intentional fallthrough
    
  3188.         default:
    
  3189.           if (
    
  3190.             isAttributeNameSafe(propKey) &&
    
  3191.             typeof propValue !== 'function' &&
    
  3192.             typeof propValue !== 'symbol'
    
  3193.           ) {
    
  3194.             if (enableCustomElementPropertySupport) {
    
  3195.               if (propValue === false) {
    
  3196.                 continue;
    
  3197.               } else if (propValue === true) {
    
  3198.                 propValue = '';
    
  3199.               } else if (typeof propValue === 'object') {
    
  3200.                 continue;
    
  3201.               }
    
  3202.             }
    
  3203.             target.push(
    
  3204.               attributeSeparator,
    
  3205.               stringToChunk(attributeName),
    
  3206.               attributeAssign,
    
  3207.               stringToChunk(escapeTextForBrowser(propValue)),
    
  3208.               attributeEnd,
    
  3209.             );
    
  3210.           }
    
  3211.           break;
    
  3212.       }
    
  3213.     }
    
  3214.   }
    
  3215. 
    
  3216.   target.push(endOfStartTag);
    
  3217.   pushInnerHTML(target, innerHTML, children);
    
  3218.   return children;
    
  3219. }
    
  3220. 
    
  3221. const leadingNewline = stringToPrecomputedChunk('\n');
    
  3222. 
    
  3223. function pushStartPreformattedElement(
    
  3224.   target: Array<Chunk | PrecomputedChunk>,
    
  3225.   props: Object,
    
  3226.   tag: string,
    
  3227. ): ReactNodeList {
    
  3228.   target.push(startChunkForTag(tag));
    
  3229. 
    
  3230.   let children = null;
    
  3231.   let innerHTML = null;
    
  3232.   for (const propKey in props) {
    
  3233.     if (hasOwnProperty.call(props, propKey)) {
    
  3234.       const propValue = props[propKey];
    
  3235.       if (propValue == null) {
    
  3236.         continue;
    
  3237.       }
    
  3238.       switch (propKey) {
    
  3239.         case 'children':
    
  3240.           children = propValue;
    
  3241.           break;
    
  3242.         case 'dangerouslySetInnerHTML':
    
  3243.           innerHTML = propValue;
    
  3244.           break;
    
  3245.         default:
    
  3246.           pushAttribute(target, propKey, propValue);
    
  3247.           break;
    
  3248.       }
    
  3249.     }
    
  3250.   }
    
  3251. 
    
  3252.   target.push(endOfStartTag);
    
  3253. 
    
  3254.   // text/html ignores the first character in these tags if it's a newline
    
  3255.   // Prefer to break application/xml over text/html (for now) by adding
    
  3256.   // a newline specifically to get eaten by the parser. (Alternately for
    
  3257.   // textareas, replacing "^\n" with "\r\n" doesn't get eaten, and the first
    
  3258.   // \r is normalized out by HTMLTextAreaElement#value.)
    
  3259.   // See: <http://www.w3.org/TR/html-polyglot/#newlines-in-textarea-and-pre>
    
  3260.   // See: <http://www.w3.org/TR/html5/syntax.html#element-restrictions>
    
  3261.   // See: <http://www.w3.org/TR/html5/syntax.html#newlines>
    
  3262.   // See: Parsing of "textarea" "listing" and "pre" elements
    
  3263.   //  from <http://www.w3.org/TR/html5/syntax.html#parsing-main-inbody>
    
  3264.   // TODO: This doesn't deal with the case where the child is an array
    
  3265.   // or component that returns a string.
    
  3266.   if (innerHTML != null) {
    
  3267.     if (children != null) {
    
  3268.       throw new Error(
    
  3269.         'Can only set one of `children` or `props.dangerouslySetInnerHTML`.',
    
  3270.       );
    
  3271.     }
    
  3272. 
    
  3273.     if (typeof innerHTML !== 'object' || !('__html' in innerHTML)) {
    
  3274.       throw new Error(
    
  3275.         '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' +
    
  3276.           'Please visit https://reactjs.org/link/dangerously-set-inner-html ' +
    
  3277.           'for more information.',
    
  3278.       );
    
  3279.     }
    
  3280. 
    
  3281.     const html = innerHTML.__html;
    
  3282.     if (html !== null && html !== undefined) {
    
  3283.       if (typeof html === 'string' && html.length > 0 && html[0] === '\n') {
    
  3284.         target.push(leadingNewline, stringToChunk(html));
    
  3285.       } else {
    
  3286.         if (__DEV__) {
    
  3287.           checkHtmlStringCoercion(html);
    
  3288.         }
    
  3289.         target.push(stringToChunk('' + html));
    
  3290.       }
    
  3291.     }
    
  3292.   }
    
  3293.   if (typeof children === 'string' && children[0] === '\n') {
    
  3294.     target.push(leadingNewline);
    
  3295.   }
    
  3296.   return children;
    
  3297. }
    
  3298. 
    
  3299. // We accept any tag to be rendered but since this gets injected into arbitrary
    
  3300. // HTML, we want to make sure that it's a safe tag.
    
  3301. // http://www.w3.org/TR/REC-xml/#NT-Name
    
  3302. const VALID_TAG_REGEX = /^[a-zA-Z][a-zA-Z:_\.\-\d]*$/; // Simplified subset
    
  3303. const validatedTagCache = new Map<string, PrecomputedChunk>();
    
  3304. function startChunkForTag(tag: string): PrecomputedChunk {
    
  3305.   let tagStartChunk = validatedTagCache.get(tag);
    
  3306.   if (tagStartChunk === undefined) {
    
  3307.     if (!VALID_TAG_REGEX.test(tag)) {
    
  3308.       throw new Error(`Invalid tag: ${tag}`);
    
  3309.     }
    
  3310. 
    
  3311.     tagStartChunk = stringToPrecomputedChunk('<' + tag);
    
  3312.     validatedTagCache.set(tag, tagStartChunk);
    
  3313.   }
    
  3314.   return tagStartChunk;
    
  3315. }
    
  3316. 
    
  3317. export const doctypeChunk: PrecomputedChunk =
    
  3318.   stringToPrecomputedChunk('<!DOCTYPE html>');
    
  3319. 
    
  3320. import {doctypeChunk as DOCTYPE} from 'react-server/src/ReactFizzConfig';
    
  3321. 
    
  3322. export function pushStartInstance(
    
  3323.   target: Array<Chunk | PrecomputedChunk>,
    
  3324.   type: string,
    
  3325.   props: Object,
    
  3326.   resumableState: ResumableState,
    
  3327.   renderState: RenderState,
    
  3328.   formatContext: FormatContext,
    
  3329.   textEmbedded: boolean,
    
  3330. ): ReactNodeList {
    
  3331.   if (__DEV__) {
    
  3332.     validateARIAProperties(type, props);
    
  3333.     validateInputProperties(type, props);
    
  3334.     validateUnknownProperties(type, props, null);
    
  3335. 
    
  3336.     if (
    
  3337.       !props.suppressContentEditableWarning &&
    
  3338.       props.contentEditable &&
    
  3339.       props.children != null
    
  3340.     ) {
    
  3341.       console.error(
    
  3342.         'A component is `contentEditable` and contains `children` managed by ' +
    
  3343.           'React. It is now your responsibility to guarantee that none of ' +
    
  3344.           'those nodes are unexpectedly modified or duplicated. This is ' +
    
  3345.           'probably not intentional.',
    
  3346.       );
    
  3347.     }
    
  3348. 
    
  3349.     if (
    
  3350.       formatContext.insertionMode !== SVG_MODE &&
    
  3351.       formatContext.insertionMode !== MATHML_MODE
    
  3352.     ) {
    
  3353.       if (type.indexOf('-') === -1 && type.toLowerCase() !== type) {
    
  3354.         console.error(
    
  3355.           '<%s /> is using incorrect casing. ' +
    
  3356.             'Use PascalCase for React components, ' +
    
  3357.             'or lowercase for HTML elements.',
    
  3358.           type,
    
  3359.         );
    
  3360.       }
    
  3361.     }
    
  3362.   }
    
  3363. 
    
  3364.   switch (type) {
    
  3365.     case 'div':
    
  3366.     case 'span':
    
  3367.     case 'svg':
    
  3368.     case 'path':
    
  3369.     case 'a':
    
  3370.     case 'g':
    
  3371.     case 'p':
    
  3372.     case 'li':
    
  3373.       // Fast track very common tags
    
  3374.       break;
    
  3375.     // Special tags
    
  3376.     case 'select':
    
  3377.       return pushStartSelect(target, props);
    
  3378.     case 'option':
    
  3379.       return pushStartOption(target, props, formatContext);
    
  3380.     case 'textarea':
    
  3381.       return pushStartTextArea(target, props);
    
  3382.     case 'input':
    
  3383.       return pushInput(target, props, resumableState, renderState);
    
  3384.     case 'button':
    
  3385.       return pushStartButton(target, props, resumableState, renderState);
    
  3386.     case 'form':
    
  3387.       return pushStartForm(target, props, resumableState, renderState);
    
  3388.     case 'menuitem':
    
  3389.       return pushStartMenuItem(target, props);
    
  3390.     case 'title':
    
  3391.       return enableFloat
    
  3392.         ? pushTitle(
    
  3393.             target,
    
  3394.             props,
    
  3395.             renderState,
    
  3396.             formatContext.insertionMode,
    
  3397.             !!(formatContext.tagScope & NOSCRIPT_SCOPE),
    
  3398.           )
    
  3399.         : pushStartTitle(target, props);
    
  3400.     case 'link':
    
  3401.       return pushLink(
    
  3402.         target,
    
  3403.         props,
    
  3404.         resumableState,
    
  3405.         renderState,
    
  3406.         textEmbedded,
    
  3407.         formatContext.insertionMode,
    
  3408.         !!(formatContext.tagScope & NOSCRIPT_SCOPE),
    
  3409.       );
    
  3410.     case 'script':
    
  3411.       return enableFloat
    
  3412.         ? pushScript(
    
  3413.             target,
    
  3414.             props,
    
  3415.             resumableState,
    
  3416.             renderState,
    
  3417.             textEmbedded,
    
  3418.             formatContext.insertionMode,
    
  3419.             !!(formatContext.tagScope & NOSCRIPT_SCOPE),
    
  3420.           )
    
  3421.         : pushStartGenericElement(target, props, type);
    
  3422.     case 'style':
    
  3423.       return pushStyle(
    
  3424.         target,
    
  3425.         props,
    
  3426.         resumableState,
    
  3427.         renderState,
    
  3428.         textEmbedded,
    
  3429.         formatContext.insertionMode,
    
  3430.         !!(formatContext.tagScope & NOSCRIPT_SCOPE),
    
  3431.       );
    
  3432.     case 'meta':
    
  3433.       return pushMeta(
    
  3434.         target,
    
  3435.         props,
    
  3436.         renderState,
    
  3437.         textEmbedded,
    
  3438.         formatContext.insertionMode,
    
  3439.         !!(formatContext.tagScope & NOSCRIPT_SCOPE),
    
  3440.       );
    
  3441.     // Newline eating tags
    
  3442.     case 'listing':
    
  3443.     case 'pre': {
    
  3444.       return pushStartPreformattedElement(target, props, type);
    
  3445.     }
    
  3446.     case 'img': {
    
  3447.       return enableFloat
    
  3448.         ? pushImg(
    
  3449.             target,
    
  3450.             props,
    
  3451.             resumableState,
    
  3452.             renderState,
    
  3453.             !!(formatContext.tagScope & PICTURE_SCOPE),
    
  3454.           )
    
  3455.         : pushSelfClosing(target, props, type);
    
  3456.     }
    
  3457.     // Omitted close tags
    
  3458.     case 'base':
    
  3459.     case 'area':
    
  3460.     case 'br':
    
  3461.     case 'col':
    
  3462.     case 'embed':
    
  3463.     case 'hr':
    
  3464.     case 'keygen':
    
  3465.     case 'param':
    
  3466.     case 'source':
    
  3467.     case 'track':
    
  3468.     case 'wbr': {
    
  3469.       return pushSelfClosing(target, props, type);
    
  3470.     }
    
  3471.     // These are reserved SVG and MathML elements, that are never custom elements.
    
  3472.     // https://w3c.github.io/webcomponents/spec/custom/#custom-elements-core-concepts
    
  3473.     case 'annotation-xml':
    
  3474.     case 'color-profile':
    
  3475.     case 'font-face':
    
  3476.     case 'font-face-src':
    
  3477.     case 'font-face-uri':
    
  3478.     case 'font-face-format':
    
  3479.     case 'font-face-name':
    
  3480.     case 'missing-glyph': {
    
  3481.       break;
    
  3482.     }
    
  3483.     // Preamble start tags
    
  3484.     case 'head':
    
  3485.       return pushStartHead(
    
  3486.         target,
    
  3487.         props,
    
  3488.         renderState,
    
  3489.         formatContext.insertionMode,
    
  3490.       );
    
  3491.     case 'html': {
    
  3492.       return pushStartHtml(
    
  3493.         target,
    
  3494.         props,
    
  3495.         renderState,
    
  3496.         formatContext.insertionMode,
    
  3497.       );
    
  3498.     }
    
  3499.     default: {
    
  3500.       if (type.indexOf('-') !== -1) {
    
  3501.         // Custom element
    
  3502.         return pushStartCustomElement(target, props, type);
    
  3503.       }
    
  3504.     }
    
  3505.   }
    
  3506.   // Generic element
    
  3507.   return pushStartGenericElement(target, props, type);
    
  3508. }
    
  3509. 
    
  3510. const endTagCache = new Map<string, PrecomputedChunk>();
    
  3511. function endChunkForTag(tag: string): PrecomputedChunk {
    
  3512.   let chunk = endTagCache.get(tag);
    
  3513.   if (chunk === undefined) {
    
  3514.     chunk = stringToPrecomputedChunk('</' + tag + '>');
    
  3515.     endTagCache.set(tag, chunk);
    
  3516.   }
    
  3517.   return chunk;
    
  3518. }
    
  3519. 
    
  3520. export function pushEndInstance(
    
  3521.   target: Array<Chunk | PrecomputedChunk>,
    
  3522.   type: string,
    
  3523.   props: Object,
    
  3524.   resumableState: ResumableState,
    
  3525.   formatContext: FormatContext,
    
  3526. ): void {
    
  3527.   switch (type) {
    
  3528.     // When float is on we expect title and script tags to always be pushed in
    
  3529.     // a unit and never return children. when we end up pushing the end tag we
    
  3530.     // want to ensure there is no extra closing tag pushed
    
  3531.     case 'title':
    
  3532.     case 'style':
    
  3533.     case 'script': {
    
  3534.       if (!enableFloat) {
    
  3535.         break;
    
  3536.       }
    
  3537.       // Fall through
    
  3538.     }
    
  3539. 
    
  3540.     // Omitted close tags
    
  3541.     // TODO: Instead of repeating this switch we could try to pass a flag from above.
    
  3542.     // That would require returning a tuple. Which might be ok if it gets inlined.
    
  3543.     case 'area':
    
  3544.     case 'base':
    
  3545.     case 'br':
    
  3546.     case 'col':
    
  3547.     case 'embed':
    
  3548.     case 'hr':
    
  3549.     case 'img':
    
  3550.     case 'input':
    
  3551.     case 'keygen':
    
  3552.     case 'link':
    
  3553.     case 'meta':
    
  3554.     case 'param':
    
  3555.     case 'source':
    
  3556.     case 'track':
    
  3557.     case 'wbr': {
    
  3558.       // No close tag needed.
    
  3559.       return;
    
  3560.     }
    
  3561.     // Postamble end tags
    
  3562.     // When float is enabled we omit the end tags for body and html when
    
  3563.     // they represent the Document.body and Document.documentElement Nodes.
    
  3564.     // This is so we can withhold them until the postamble when we know
    
  3565.     // we won't emit any more tags
    
  3566.     case 'body': {
    
  3567.       if (enableFloat && formatContext.insertionMode <= HTML_HTML_MODE) {
    
  3568.         resumableState.hasBody = true;
    
  3569.         return;
    
  3570.       }
    
  3571.       break;
    
  3572.     }
    
  3573.     case 'html':
    
  3574.       if (enableFloat && formatContext.insertionMode === ROOT_HTML_MODE) {
    
  3575.         resumableState.hasHtml = true;
    
  3576.         return;
    
  3577.       }
    
  3578.       break;
    
  3579.   }
    
  3580.   target.push(endChunkForTag(type));
    
  3581. }
    
  3582. 
    
  3583. function writeBootstrap(
    
  3584.   destination: Destination,
    
  3585.   renderState: RenderState,
    
  3586. ): boolean {
    
  3587.   const bootstrapChunks = renderState.bootstrapChunks;
    
  3588.   let i = 0;
    
  3589.   for (; i < bootstrapChunks.length - 1; i++) {
    
  3590.     writeChunk(destination, bootstrapChunks[i]);
    
  3591.   }
    
  3592.   if (i < bootstrapChunks.length) {
    
  3593.     const lastChunk = bootstrapChunks[i];
    
  3594.     bootstrapChunks.length = 0;
    
  3595.     return writeChunkAndReturn(destination, lastChunk);
    
  3596.   }
    
  3597.   return true;
    
  3598. }
    
  3599. 
    
  3600. export function writeCompletedRoot(
    
  3601.   destination: Destination,
    
  3602.   renderState: RenderState,
    
  3603. ): boolean {
    
  3604.   return writeBootstrap(destination, renderState);
    
  3605. }
    
  3606. 
    
  3607. // Structural Nodes
    
  3608. 
    
  3609. // A placeholder is a node inside a hidden partial tree that can be filled in later, but before
    
  3610. // display. It's never visible to users. We use the template tag because it can be used in every
    
  3611. // type of parent. <script> tags also work in every other tag except <colgroup>.
    
  3612. const placeholder1 = stringToPrecomputedChunk('<template id="');
    
  3613. const placeholder2 = stringToPrecomputedChunk('"></template>');
    
  3614. export function writePlaceholder(
    
  3615.   destination: Destination,
    
  3616.   renderState: RenderState,
    
  3617.   id: number,
    
  3618. ): boolean {
    
  3619.   writeChunk(destination, placeholder1);
    
  3620.   writeChunk(destination, renderState.placeholderPrefix);
    
  3621.   const formattedID = stringToChunk(id.toString(16));
    
  3622.   writeChunk(destination, formattedID);
    
  3623.   return writeChunkAndReturn(destination, placeholder2);
    
  3624. }
    
  3625. 
    
  3626. // Suspense boundaries are encoded as comments.
    
  3627. const startCompletedSuspenseBoundary = stringToPrecomputedChunk('<!--$-->');
    
  3628. const startPendingSuspenseBoundary1 = stringToPrecomputedChunk(
    
  3629.   '<!--$?--><template id="',
    
  3630. );
    
  3631. const startPendingSuspenseBoundary2 = stringToPrecomputedChunk('"></template>');
    
  3632. const startClientRenderedSuspenseBoundary =
    
  3633.   stringToPrecomputedChunk('<!--$!-->');
    
  3634. const endSuspenseBoundary = stringToPrecomputedChunk('<!--/$-->');
    
  3635. 
    
  3636. const clientRenderedSuspenseBoundaryError1 =
    
  3637.   stringToPrecomputedChunk('<template');
    
  3638. const clientRenderedSuspenseBoundaryErrorAttrInterstitial =
    
  3639.   stringToPrecomputedChunk('"');
    
  3640. const clientRenderedSuspenseBoundaryError1A =
    
  3641.   stringToPrecomputedChunk(' data-dgst="');
    
  3642. const clientRenderedSuspenseBoundaryError1B =
    
  3643.   stringToPrecomputedChunk(' data-msg="');
    
  3644. const clientRenderedSuspenseBoundaryError1C =
    
  3645.   stringToPrecomputedChunk(' data-stck="');
    
  3646. const clientRenderedSuspenseBoundaryError2 =
    
  3647.   stringToPrecomputedChunk('></template>');
    
  3648. 
    
  3649. export function pushStartCompletedSuspenseBoundary(
    
  3650.   target: Array<Chunk | PrecomputedChunk>,
    
  3651. ) {
    
  3652.   target.push(startCompletedSuspenseBoundary);
    
  3653. }
    
  3654. 
    
  3655. export function pushEndCompletedSuspenseBoundary(
    
  3656.   target: Array<Chunk | PrecomputedChunk>,
    
  3657. ) {
    
  3658.   target.push(endSuspenseBoundary);
    
  3659. }
    
  3660. 
    
  3661. export function writeStartCompletedSuspenseBoundary(
    
  3662.   destination: Destination,
    
  3663.   renderState: RenderState,
    
  3664. ): boolean {
    
  3665.   return writeChunkAndReturn(destination, startCompletedSuspenseBoundary);
    
  3666. }
    
  3667. export function writeStartPendingSuspenseBoundary(
    
  3668.   destination: Destination,
    
  3669.   renderState: RenderState,
    
  3670.   id: number,
    
  3671. ): boolean {
    
  3672.   writeChunk(destination, startPendingSuspenseBoundary1);
    
  3673. 
    
  3674.   if (id === null) {
    
  3675.     throw new Error(
    
  3676.       'An ID must have been assigned before we can complete the boundary.',
    
  3677.     );
    
  3678.   }
    
  3679. 
    
  3680.   writeChunk(destination, renderState.boundaryPrefix);
    
  3681.   writeChunk(destination, stringToChunk(id.toString(16)));
    
  3682.   return writeChunkAndReturn(destination, startPendingSuspenseBoundary2);
    
  3683. }
    
  3684. export function writeStartClientRenderedSuspenseBoundary(
    
  3685.   destination: Destination,
    
  3686.   renderState: RenderState,
    
  3687.   errorDigest: ?string,
    
  3688.   errorMesssage: ?string,
    
  3689.   errorComponentStack: ?string,
    
  3690. ): boolean {
    
  3691.   let result;
    
  3692.   result = writeChunkAndReturn(
    
  3693.     destination,
    
  3694.     startClientRenderedSuspenseBoundary,
    
  3695.   );
    
  3696.   writeChunk(destination, clientRenderedSuspenseBoundaryError1);
    
  3697.   if (errorDigest) {
    
  3698.     writeChunk(destination, clientRenderedSuspenseBoundaryError1A);
    
  3699.     writeChunk(destination, stringToChunk(escapeTextForBrowser(errorDigest)));
    
  3700.     writeChunk(
    
  3701.       destination,
    
  3702.       clientRenderedSuspenseBoundaryErrorAttrInterstitial,
    
  3703.     );
    
  3704.   }
    
  3705.   if (__DEV__) {
    
  3706.     if (errorMesssage) {
    
  3707.       writeChunk(destination, clientRenderedSuspenseBoundaryError1B);
    
  3708.       writeChunk(
    
  3709.         destination,
    
  3710.         stringToChunk(escapeTextForBrowser(errorMesssage)),
    
  3711.       );
    
  3712.       writeChunk(
    
  3713.         destination,
    
  3714.         clientRenderedSuspenseBoundaryErrorAttrInterstitial,
    
  3715.       );
    
  3716.     }
    
  3717.     if (errorComponentStack) {
    
  3718.       writeChunk(destination, clientRenderedSuspenseBoundaryError1C);
    
  3719.       writeChunk(
    
  3720.         destination,
    
  3721.         stringToChunk(escapeTextForBrowser(errorComponentStack)),
    
  3722.       );
    
  3723.       writeChunk(
    
  3724.         destination,
    
  3725.         clientRenderedSuspenseBoundaryErrorAttrInterstitial,
    
  3726.       );
    
  3727.     }
    
  3728.   }
    
  3729.   result = writeChunkAndReturn(
    
  3730.     destination,
    
  3731.     clientRenderedSuspenseBoundaryError2,
    
  3732.   );
    
  3733.   return result;
    
  3734. }
    
  3735. export function writeEndCompletedSuspenseBoundary(
    
  3736.   destination: Destination,
    
  3737.   renderState: RenderState,
    
  3738. ): boolean {
    
  3739.   return writeChunkAndReturn(destination, endSuspenseBoundary);
    
  3740. }
    
  3741. export function writeEndPendingSuspenseBoundary(
    
  3742.   destination: Destination,
    
  3743.   renderState: RenderState,
    
  3744. ): boolean {
    
  3745.   return writeChunkAndReturn(destination, endSuspenseBoundary);
    
  3746. }
    
  3747. export function writeEndClientRenderedSuspenseBoundary(
    
  3748.   destination: Destination,
    
  3749.   renderState: RenderState,
    
  3750. ): boolean {
    
  3751.   return writeChunkAndReturn(destination, endSuspenseBoundary);
    
  3752. }
    
  3753. 
    
  3754. const startSegmentHTML = stringToPrecomputedChunk('<div hidden id="');
    
  3755. const startSegmentHTML2 = stringToPrecomputedChunk('">');
    
  3756. const endSegmentHTML = stringToPrecomputedChunk('</div>');
    
  3757. 
    
  3758. const startSegmentSVG = stringToPrecomputedChunk(
    
  3759.   '<svg aria-hidden="true" style="display:none" id="',
    
  3760. );
    
  3761. const startSegmentSVG2 = stringToPrecomputedChunk('">');
    
  3762. const endSegmentSVG = stringToPrecomputedChunk('</svg>');
    
  3763. 
    
  3764. const startSegmentMathML = stringToPrecomputedChunk(
    
  3765.   '<math aria-hidden="true" style="display:none" id="',
    
  3766. );
    
  3767. const startSegmentMathML2 = stringToPrecomputedChunk('">');
    
  3768. const endSegmentMathML = stringToPrecomputedChunk('</math>');
    
  3769. 
    
  3770. const startSegmentTable = stringToPrecomputedChunk('<table hidden id="');
    
  3771. const startSegmentTable2 = stringToPrecomputedChunk('">');
    
  3772. const endSegmentTable = stringToPrecomputedChunk('</table>');
    
  3773. 
    
  3774. const startSegmentTableBody = stringToPrecomputedChunk(
    
  3775.   '<table hidden><tbody id="',
    
  3776. );
    
  3777. const startSegmentTableBody2 = stringToPrecomputedChunk('">');
    
  3778. const endSegmentTableBody = stringToPrecomputedChunk('</tbody></table>');
    
  3779. 
    
  3780. const startSegmentTableRow = stringToPrecomputedChunk('<table hidden><tr id="');
    
  3781. const startSegmentTableRow2 = stringToPrecomputedChunk('">');
    
  3782. const endSegmentTableRow = stringToPrecomputedChunk('</tr></table>');
    
  3783. 
    
  3784. const startSegmentColGroup = stringToPrecomputedChunk(
    
  3785.   '<table hidden><colgroup id="',
    
  3786. );
    
  3787. const startSegmentColGroup2 = stringToPrecomputedChunk('">');
    
  3788. const endSegmentColGroup = stringToPrecomputedChunk('</colgroup></table>');
    
  3789. 
    
  3790. export function writeStartSegment(
    
  3791.   destination: Destination,
    
  3792.   renderState: RenderState,
    
  3793.   formatContext: FormatContext,
    
  3794.   id: number,
    
  3795. ): boolean {
    
  3796.   switch (formatContext.insertionMode) {
    
  3797.     case ROOT_HTML_MODE:
    
  3798.     case HTML_HTML_MODE:
    
  3799.     case HTML_MODE: {
    
  3800.       writeChunk(destination, startSegmentHTML);
    
  3801.       writeChunk(destination, renderState.segmentPrefix);
    
  3802.       writeChunk(destination, stringToChunk(id.toString(16)));
    
  3803.       return writeChunkAndReturn(destination, startSegmentHTML2);
    
  3804.     }
    
  3805.     case SVG_MODE: {
    
  3806.       writeChunk(destination, startSegmentSVG);
    
  3807.       writeChunk(destination, renderState.segmentPrefix);
    
  3808.       writeChunk(destination, stringToChunk(id.toString(16)));
    
  3809.       return writeChunkAndReturn(destination, startSegmentSVG2);
    
  3810.     }
    
  3811.     case MATHML_MODE: {
    
  3812.       writeChunk(destination, startSegmentMathML);
    
  3813.       writeChunk(destination, renderState.segmentPrefix);
    
  3814.       writeChunk(destination, stringToChunk(id.toString(16)));
    
  3815.       return writeChunkAndReturn(destination, startSegmentMathML2);
    
  3816.     }
    
  3817.     case HTML_TABLE_MODE: {
    
  3818.       writeChunk(destination, startSegmentTable);
    
  3819.       writeChunk(destination, renderState.segmentPrefix);
    
  3820.       writeChunk(destination, stringToChunk(id.toString(16)));
    
  3821.       return writeChunkAndReturn(destination, startSegmentTable2);
    
  3822.     }
    
  3823.     // TODO: For the rest of these, there will be extra wrapper nodes that never
    
  3824.     // get deleted from the document. We need to delete the table too as part
    
  3825.     // of the injected scripts. They are invisible though so it's not too terrible
    
  3826.     // and it's kind of an edge case to suspend in a table. Totally supported though.
    
  3827.     case HTML_TABLE_BODY_MODE: {
    
  3828.       writeChunk(destination, startSegmentTableBody);
    
  3829.       writeChunk(destination, renderState.segmentPrefix);
    
  3830.       writeChunk(destination, stringToChunk(id.toString(16)));
    
  3831.       return writeChunkAndReturn(destination, startSegmentTableBody2);
    
  3832.     }
    
  3833.     case HTML_TABLE_ROW_MODE: {
    
  3834.       writeChunk(destination, startSegmentTableRow);
    
  3835.       writeChunk(destination, renderState.segmentPrefix);
    
  3836.       writeChunk(destination, stringToChunk(id.toString(16)));
    
  3837.       return writeChunkAndReturn(destination, startSegmentTableRow2);
    
  3838.     }
    
  3839.     case HTML_COLGROUP_MODE: {
    
  3840.       writeChunk(destination, startSegmentColGroup);
    
  3841.       writeChunk(destination, renderState.segmentPrefix);
    
  3842.       writeChunk(destination, stringToChunk(id.toString(16)));
    
  3843.       return writeChunkAndReturn(destination, startSegmentColGroup2);
    
  3844.     }
    
  3845.     default: {
    
  3846.       throw new Error('Unknown insertion mode. This is a bug in React.');
    
  3847.     }
    
  3848.   }
    
  3849. }
    
  3850. export function writeEndSegment(
    
  3851.   destination: Destination,
    
  3852.   formatContext: FormatContext,
    
  3853. ): boolean {
    
  3854.   switch (formatContext.insertionMode) {
    
  3855.     case ROOT_HTML_MODE:
    
  3856.     case HTML_HTML_MODE:
    
  3857.     case HTML_MODE: {
    
  3858.       return writeChunkAndReturn(destination, endSegmentHTML);
    
  3859.     }
    
  3860.     case SVG_MODE: {
    
  3861.       return writeChunkAndReturn(destination, endSegmentSVG);
    
  3862.     }
    
  3863.     case MATHML_MODE: {
    
  3864.       return writeChunkAndReturn(destination, endSegmentMathML);
    
  3865.     }
    
  3866.     case HTML_TABLE_MODE: {
    
  3867.       return writeChunkAndReturn(destination, endSegmentTable);
    
  3868.     }
    
  3869.     case HTML_TABLE_BODY_MODE: {
    
  3870.       return writeChunkAndReturn(destination, endSegmentTableBody);
    
  3871.     }
    
  3872.     case HTML_TABLE_ROW_MODE: {
    
  3873.       return writeChunkAndReturn(destination, endSegmentTableRow);
    
  3874.     }
    
  3875.     case HTML_COLGROUP_MODE: {
    
  3876.       return writeChunkAndReturn(destination, endSegmentColGroup);
    
  3877.     }
    
  3878.     default: {
    
  3879.       throw new Error('Unknown insertion mode. This is a bug in React.');
    
  3880.     }
    
  3881.   }
    
  3882. }
    
  3883. 
    
  3884. const completeSegmentScript1Full = stringToPrecomputedChunk(
    
  3885.   completeSegmentFunction + '$RS("',
    
  3886. );
    
  3887. const completeSegmentScript1Partial = stringToPrecomputedChunk('$RS("');
    
  3888. const completeSegmentScript2 = stringToPrecomputedChunk('","');
    
  3889. const completeSegmentScriptEnd = stringToPrecomputedChunk('")</script>');
    
  3890. 
    
  3891. const completeSegmentData1 = stringToPrecomputedChunk(
    
  3892.   '<template data-rsi="" data-sid="',
    
  3893. );
    
  3894. const completeSegmentData2 = stringToPrecomputedChunk('" data-pid="');
    
  3895. const completeSegmentDataEnd = dataElementQuotedEnd;
    
  3896. 
    
  3897. export function writeCompletedSegmentInstruction(
    
  3898.   destination: Destination,
    
  3899.   resumableState: ResumableState,
    
  3900.   renderState: RenderState,
    
  3901.   contentSegmentID: number,
    
  3902. ): boolean {
    
  3903.   const scriptFormat =
    
  3904.     !enableFizzExternalRuntime ||
    
  3905.     resumableState.streamingFormat === ScriptStreamingFormat;
    
  3906.   if (scriptFormat) {
    
  3907.     writeChunk(destination, renderState.startInlineScript);
    
  3908.     if (
    
  3909.       (resumableState.instructions & SentCompleteSegmentFunction) ===
    
  3910.       NothingSent
    
  3911.     ) {
    
  3912.       // The first time we write this, we'll need to include the full implementation.
    
  3913.       resumableState.instructions |= SentCompleteSegmentFunction;
    
  3914.       writeChunk(destination, completeSegmentScript1Full);
    
  3915.     } else {
    
  3916.       // Future calls can just reuse the same function.
    
  3917.       writeChunk(destination, completeSegmentScript1Partial);
    
  3918.     }
    
  3919.   } else {
    
  3920.     writeChunk(destination, completeSegmentData1);
    
  3921.   }
    
  3922. 
    
  3923.   // Write function arguments, which are string literals
    
  3924.   writeChunk(destination, renderState.segmentPrefix);
    
  3925.   const formattedID = stringToChunk(contentSegmentID.toString(16));
    
  3926.   writeChunk(destination, formattedID);
    
  3927.   if (scriptFormat) {
    
  3928.     writeChunk(destination, completeSegmentScript2);
    
  3929.   } else {
    
  3930.     writeChunk(destination, completeSegmentData2);
    
  3931.   }
    
  3932.   writeChunk(destination, renderState.placeholderPrefix);
    
  3933.   writeChunk(destination, formattedID);
    
  3934. 
    
  3935.   if (scriptFormat) {
    
  3936.     return writeChunkAndReturn(destination, completeSegmentScriptEnd);
    
  3937.   } else {
    
  3938.     return writeChunkAndReturn(destination, completeSegmentDataEnd);
    
  3939.   }
    
  3940. }
    
  3941. 
    
  3942. const completeBoundaryScript1Full = stringToPrecomputedChunk(
    
  3943.   completeBoundaryFunction + '$RC("',
    
  3944. );
    
  3945. const completeBoundaryScript1Partial = stringToPrecomputedChunk('$RC("');
    
  3946. 
    
  3947. const completeBoundaryWithStylesScript1FullBoth = stringToPrecomputedChunk(
    
  3948.   completeBoundaryFunction + styleInsertionFunction + '$RR("',
    
  3949. );
    
  3950. const completeBoundaryWithStylesScript1FullPartial = stringToPrecomputedChunk(
    
  3951.   styleInsertionFunction + '$RR("',
    
  3952. );
    
  3953. 
    
  3954. const completeBoundaryWithStylesScript1Partial =
    
  3955.   stringToPrecomputedChunk('$RR("');
    
  3956. const completeBoundaryScript2 = stringToPrecomputedChunk('","');
    
  3957. const completeBoundaryScript3a = stringToPrecomputedChunk('",');
    
  3958. const completeBoundaryScript3b = stringToPrecomputedChunk('"');
    
  3959. const completeBoundaryScriptEnd = stringToPrecomputedChunk(')</script>');
    
  3960. 
    
  3961. const completeBoundaryData1 = stringToPrecomputedChunk(
    
  3962.   '<template data-rci="" data-bid="',
    
  3963. );
    
  3964. const completeBoundaryWithStylesData1 = stringToPrecomputedChunk(
    
  3965.   '<template data-rri="" data-bid="',
    
  3966. );
    
  3967. const completeBoundaryData2 = stringToPrecomputedChunk('" data-sid="');
    
  3968. const completeBoundaryData3a = stringToPrecomputedChunk('" data-sty="');
    
  3969. const completeBoundaryDataEnd = dataElementQuotedEnd;
    
  3970. 
    
  3971. export function writeCompletedBoundaryInstruction(
    
  3972.   destination: Destination,
    
  3973.   resumableState: ResumableState,
    
  3974.   renderState: RenderState,
    
  3975.   id: number,
    
  3976.   boundaryResources: BoundaryResources,
    
  3977. ): boolean {
    
  3978.   let requiresStyleInsertion;
    
  3979.   if (enableFloat) {
    
  3980.     requiresStyleInsertion = renderState.stylesToHoist;
    
  3981.     // If necessary stylesheets will be flushed with this instruction.
    
  3982.     // Any style tags not yet hoisted in the Document will also be hoisted.
    
  3983.     // We reset this state since after this instruction executes all styles
    
  3984.     // up to this point will have been hoisted
    
  3985.     renderState.stylesToHoist = false;
    
  3986.   }
    
  3987.   const scriptFormat =
    
  3988.     !enableFizzExternalRuntime ||
    
  3989.     resumableState.streamingFormat === ScriptStreamingFormat;
    
  3990.   if (scriptFormat) {
    
  3991.     writeChunk(destination, renderState.startInlineScript);
    
  3992.     if (enableFloat && requiresStyleInsertion) {
    
  3993.       if (
    
  3994.         (resumableState.instructions & SentCompleteBoundaryFunction) ===
    
  3995.         NothingSent
    
  3996.       ) {
    
  3997.         resumableState.instructions |=
    
  3998.           SentStyleInsertionFunction | SentCompleteBoundaryFunction;
    
  3999.         writeChunk(
    
  4000.           destination,
    
  4001.           clonePrecomputedChunk(completeBoundaryWithStylesScript1FullBoth),
    
  4002.         );
    
  4003.       } else if (
    
  4004.         (resumableState.instructions & SentStyleInsertionFunction) ===
    
  4005.         NothingSent
    
  4006.       ) {
    
  4007.         resumableState.instructions |= SentStyleInsertionFunction;
    
  4008.         writeChunk(destination, completeBoundaryWithStylesScript1FullPartial);
    
  4009.       } else {
    
  4010.         writeChunk(destination, completeBoundaryWithStylesScript1Partial);
    
  4011.       }
    
  4012.     } else {
    
  4013.       if (
    
  4014.         (resumableState.instructions & SentCompleteBoundaryFunction) ===
    
  4015.         NothingSent
    
  4016.       ) {
    
  4017.         resumableState.instructions |= SentCompleteBoundaryFunction;
    
  4018.         writeChunk(destination, completeBoundaryScript1Full);
    
  4019.       } else {
    
  4020.         writeChunk(destination, completeBoundaryScript1Partial);
    
  4021.       }
    
  4022.     }
    
  4023.   } else {
    
  4024.     if (enableFloat && requiresStyleInsertion) {
    
  4025.       writeChunk(destination, completeBoundaryWithStylesData1);
    
  4026.     } else {
    
  4027.       writeChunk(destination, completeBoundaryData1);
    
  4028.     }
    
  4029.   }
    
  4030. 
    
  4031.   const idChunk = stringToChunk(id.toString(16));
    
  4032. 
    
  4033.   writeChunk(destination, renderState.boundaryPrefix);
    
  4034.   writeChunk(destination, idChunk);
    
  4035. 
    
  4036.   // Write function arguments, which are string and array literals
    
  4037.   if (scriptFormat) {
    
  4038.     writeChunk(destination, completeBoundaryScript2);
    
  4039.   } else {
    
  4040.     writeChunk(destination, completeBoundaryData2);
    
  4041.   }
    
  4042.   writeChunk(destination, renderState.segmentPrefix);
    
  4043.   writeChunk(destination, idChunk);
    
  4044.   if (enableFloat && requiresStyleInsertion) {
    
  4045.     // Script and data writers must format this differently:
    
  4046.     //  - script writer emits an array literal, whose string elements are
    
  4047.     //    escaped for javascript  e.g. ["A", "B"]
    
  4048.     //  - data writer emits a string literal, which is escaped as html
    
  4049.     //    e.g. [&#34;A&#34;, &#34;B&#34;]
    
  4050.     if (scriptFormat) {
    
  4051.       writeChunk(destination, completeBoundaryScript3a);
    
  4052.       // boundaryResources encodes an array literal
    
  4053.       writeStyleResourceDependenciesInJS(destination, boundaryResources);
    
  4054.     } else {
    
  4055.       writeChunk(destination, completeBoundaryData3a);
    
  4056.       writeStyleResourceDependenciesInAttr(destination, boundaryResources);
    
  4057.     }
    
  4058.   } else {
    
  4059.     if (scriptFormat) {
    
  4060.       writeChunk(destination, completeBoundaryScript3b);
    
  4061.     }
    
  4062.   }
    
  4063.   let writeMore;
    
  4064.   if (scriptFormat) {
    
  4065.     writeMore = writeChunkAndReturn(destination, completeBoundaryScriptEnd);
    
  4066.   } else {
    
  4067.     writeMore = writeChunkAndReturn(destination, completeBoundaryDataEnd);
    
  4068.   }
    
  4069.   return writeBootstrap(destination, renderState) && writeMore;
    
  4070. }
    
  4071. 
    
  4072. const clientRenderScript1Full = stringToPrecomputedChunk(
    
  4073.   clientRenderFunction + ';$RX("',
    
  4074. );
    
  4075. const clientRenderScript1Partial = stringToPrecomputedChunk('$RX("');
    
  4076. const clientRenderScript1A = stringToPrecomputedChunk('"');
    
  4077. const clientRenderErrorScriptArgInterstitial = stringToPrecomputedChunk(',');
    
  4078. const clientRenderScriptEnd = stringToPrecomputedChunk(')</script>');
    
  4079. 
    
  4080. const clientRenderData1 = stringToPrecomputedChunk(
    
  4081.   '<template data-rxi="" data-bid="',
    
  4082. );
    
  4083. const clientRenderData2 = stringToPrecomputedChunk('" data-dgst="');
    
  4084. const clientRenderData3 = stringToPrecomputedChunk('" data-msg="');
    
  4085. const clientRenderData4 = stringToPrecomputedChunk('" data-stck="');
    
  4086. const clientRenderDataEnd = dataElementQuotedEnd;
    
  4087. 
    
  4088. export function writeClientRenderBoundaryInstruction(
    
  4089.   destination: Destination,
    
  4090.   resumableState: ResumableState,
    
  4091.   renderState: RenderState,
    
  4092.   id: number,
    
  4093.   errorDigest: ?string,
    
  4094.   errorMessage?: string,
    
  4095.   errorComponentStack?: string,
    
  4096. ): boolean {
    
  4097.   const scriptFormat =
    
  4098.     !enableFizzExternalRuntime ||
    
  4099.     resumableState.streamingFormat === ScriptStreamingFormat;
    
  4100.   if (scriptFormat) {
    
  4101.     writeChunk(destination, renderState.startInlineScript);
    
  4102.     if (
    
  4103.       (resumableState.instructions & SentClientRenderFunction) ===
    
  4104.       NothingSent
    
  4105.     ) {
    
  4106.       // The first time we write this, we'll need to include the full implementation.
    
  4107.       resumableState.instructions |= SentClientRenderFunction;
    
  4108.       writeChunk(destination, clientRenderScript1Full);
    
  4109.     } else {
    
  4110.       // Future calls can just reuse the same function.
    
  4111.       writeChunk(destination, clientRenderScript1Partial);
    
  4112.     }
    
  4113.   } else {
    
  4114.     // <template data-rxi="" data-bid="
    
  4115.     writeChunk(destination, clientRenderData1);
    
  4116.   }
    
  4117. 
    
  4118.   writeChunk(destination, renderState.boundaryPrefix);
    
  4119.   writeChunk(destination, stringToChunk(id.toString(16)));
    
  4120.   if (scriptFormat) {
    
  4121.     // " needs to be inserted for scripts, since ArgInterstitual does not contain
    
  4122.     // leading or trailing quotes
    
  4123.     writeChunk(destination, clientRenderScript1A);
    
  4124.   }
    
  4125. 
    
  4126.   if (errorDigest || errorMessage || errorComponentStack) {
    
  4127.     if (scriptFormat) {
    
  4128.       // ,"JSONString"
    
  4129.       writeChunk(destination, clientRenderErrorScriptArgInterstitial);
    
  4130.       writeChunk(
    
  4131.         destination,
    
  4132.         stringToChunk(escapeJSStringsForInstructionScripts(errorDigest || '')),
    
  4133.       );
    
  4134.     } else {
    
  4135.       // " data-dgst="HTMLString
    
  4136.       writeChunk(destination, clientRenderData2);
    
  4137.       writeChunk(
    
  4138.         destination,
    
  4139.         stringToChunk(escapeTextForBrowser(errorDigest || '')),
    
  4140.       );
    
  4141.     }
    
  4142.   }
    
  4143.   if (errorMessage || errorComponentStack) {
    
  4144.     if (scriptFormat) {
    
  4145.       // ,"JSONString"
    
  4146.       writeChunk(destination, clientRenderErrorScriptArgInterstitial);
    
  4147.       writeChunk(
    
  4148.         destination,
    
  4149.         stringToChunk(escapeJSStringsForInstructionScripts(errorMessage || '')),
    
  4150.       );
    
  4151.     } else {
    
  4152.       // " data-msg="HTMLString
    
  4153.       writeChunk(destination, clientRenderData3);
    
  4154.       writeChunk(
    
  4155.         destination,
    
  4156.         stringToChunk(escapeTextForBrowser(errorMessage || '')),
    
  4157.       );
    
  4158.     }
    
  4159.   }
    
  4160.   if (errorComponentStack) {
    
  4161.     // ,"JSONString"
    
  4162.     if (scriptFormat) {
    
  4163.       writeChunk(destination, clientRenderErrorScriptArgInterstitial);
    
  4164.       writeChunk(
    
  4165.         destination,
    
  4166.         stringToChunk(
    
  4167.           escapeJSStringsForInstructionScripts(errorComponentStack),
    
  4168.         ),
    
  4169.       );
    
  4170.     } else {
    
  4171.       // " data-stck="HTMLString
    
  4172.       writeChunk(destination, clientRenderData4);
    
  4173.       writeChunk(
    
  4174.         destination,
    
  4175.         stringToChunk(escapeTextForBrowser(errorComponentStack)),
    
  4176.       );
    
  4177.     }
    
  4178.   }
    
  4179. 
    
  4180.   if (scriptFormat) {
    
  4181.     // ></script>
    
  4182.     return writeChunkAndReturn(destination, clientRenderScriptEnd);
    
  4183.   } else {
    
  4184.     // "></template>
    
  4185.     return writeChunkAndReturn(destination, clientRenderDataEnd);
    
  4186.   }
    
  4187. }
    
  4188. 
    
  4189. const regexForJSStringsInInstructionScripts = /[<\u2028\u2029]/g;
    
  4190. function escapeJSStringsForInstructionScripts(input: string): string {
    
  4191.   const escaped = JSON.stringify(input);
    
  4192.   return escaped.replace(regexForJSStringsInInstructionScripts, match => {
    
  4193.     switch (match) {
    
  4194.       // santizing breaking out of strings and script tags
    
  4195.       case '<':
    
  4196.         return '\\u003c';
    
  4197.       case '\u2028':
    
  4198.         return '\\u2028';
    
  4199.       case '\u2029':
    
  4200.         return '\\u2029';
    
  4201.       default: {
    
  4202.         // eslint-disable-next-line react-internal/prod-error-codes
    
  4203.         throw new Error(
    
  4204.           'escapeJSStringsForInstructionScripts encountered a match it does not know how to replace. this means the match regex and the replacement characters are no longer in sync. This is a bug in React',
    
  4205.         );
    
  4206.       }
    
  4207.     }
    
  4208.   });
    
  4209. }
    
  4210. 
    
  4211. const regexForJSStringsInScripts = /[&><\u2028\u2029]/g;
    
  4212. function escapeJSObjectForInstructionScripts(input: Object): string {
    
  4213.   const escaped = JSON.stringify(input);
    
  4214.   return escaped.replace(regexForJSStringsInScripts, match => {
    
  4215.     switch (match) {
    
  4216.       // santizing breaking out of strings and script tags
    
  4217.       case '&':
    
  4218.         return '\\u0026';
    
  4219.       case '>':
    
  4220.         return '\\u003e';
    
  4221.       case '<':
    
  4222.         return '\\u003c';
    
  4223.       case '\u2028':
    
  4224.         return '\\u2028';
    
  4225.       case '\u2029':
    
  4226.         return '\\u2029';
    
  4227.       default: {
    
  4228.         // eslint-disable-next-line react-internal/prod-error-codes
    
  4229.         throw new Error(
    
  4230.           'escapeJSObjectForInstructionScripts encountered a match it does not know how to replace. this means the match regex and the replacement characters are no longer in sync. This is a bug in React',
    
  4231.         );
    
  4232.       }
    
  4233.     }
    
  4234.   });
    
  4235. }
    
  4236. 
    
  4237. const lateStyleTagResourceOpen1 = stringToPrecomputedChunk(
    
  4238.   '<style media="not all" data-precedence="',
    
  4239. );
    
  4240. const lateStyleTagResourceOpen2 = stringToPrecomputedChunk('" data-href="');
    
  4241. const lateStyleTagResourceOpen3 = stringToPrecomputedChunk('">');
    
  4242. const lateStyleTagTemplateClose = stringToPrecomputedChunk('</style>');
    
  4243. 
    
  4244. // Tracks whether the boundary currently flushing is flushign style tags or has any
    
  4245. // stylesheet dependencies not flushed in the Preamble.
    
  4246. let currentlyRenderingBoundaryHasStylesToHoist = false;
    
  4247. 
    
  4248. // Acts as a return value for the forEach execution of style tag flushing.
    
  4249. let destinationHasCapacity = true;
    
  4250. 
    
  4251. function flushStyleTagsLateForBoundary(
    
  4252.   this: Destination,
    
  4253.   styleQueue: StyleQueue,
    
  4254. ) {
    
  4255.   const rules = styleQueue.rules;
    
  4256.   const hrefs = styleQueue.hrefs;
    
  4257.   if (__DEV__) {
    
  4258.     if (rules.length > 0 && hrefs.length === 0) {
    
  4259.       console.error(
    
  4260.         'React expected to have at least one href for an a hoistable style but found none. This is a bug in React.',
    
  4261.       );
    
  4262.     }
    
  4263.   }
    
  4264.   let i = 0;
    
  4265.   if (hrefs.length) {
    
  4266.     writeChunk(this, lateStyleTagResourceOpen1);
    
  4267.     writeChunk(this, styleQueue.precedence);
    
  4268.     writeChunk(this, lateStyleTagResourceOpen2);
    
  4269.     for (; i < hrefs.length - 1; i++) {
    
  4270.       writeChunk(this, hrefs[i]);
    
  4271.       writeChunk(this, spaceSeparator);
    
  4272.     }
    
  4273.     writeChunk(this, hrefs[i]);
    
  4274.     writeChunk(this, lateStyleTagResourceOpen3);
    
  4275.     for (i = 0; i < rules.length; i++) {
    
  4276.       writeChunk(this, rules[i]);
    
  4277.     }
    
  4278.     destinationHasCapacity = writeChunkAndReturn(
    
  4279.       this,
    
  4280.       lateStyleTagTemplateClose,
    
  4281.     );
    
  4282. 
    
  4283.     // We wrote style tags for this boundary and we may need to emit a script
    
  4284.     // to hoist them.
    
  4285.     currentlyRenderingBoundaryHasStylesToHoist = true;
    
  4286. 
    
  4287.     // style resources can flush continuously since more rules may be written into
    
  4288.     // them with new hrefs. Instead of marking it flushed, we simply reset the chunks
    
  4289.     // and hrefs
    
  4290.     rules.length = 0;
    
  4291.     hrefs.length = 0;
    
  4292.   }
    
  4293. }
    
  4294. 
    
  4295. function hasStylesToHoist(stylesheet: StylesheetResource): boolean {
    
  4296.   // We need to reveal boundaries with styles whenever a stylesheet it depends on is either
    
  4297.   // not flushed or flushed after the preamble (shell).
    
  4298.   if (stylesheet.state !== PREAMBLE) {
    
  4299.     currentlyRenderingBoundaryHasStylesToHoist = true;
    
  4300.     return true;
    
  4301.   }
    
  4302.   return false;
    
  4303. }
    
  4304. 
    
  4305. export function writeResourcesForBoundary(
    
  4306.   destination: Destination,
    
  4307.   boundaryResources: BoundaryResources,
    
  4308.   renderState: RenderState,
    
  4309. ): boolean {
    
  4310.   // Reset these on each invocation, they are only safe to read in this function
    
  4311.   currentlyRenderingBoundaryHasStylesToHoist = false;
    
  4312.   destinationHasCapacity = true;
    
  4313. 
    
  4314.   // Flush style tags for each precedence this boundary depends on
    
  4315.   boundaryResources.styles.forEach(flushStyleTagsLateForBoundary, destination);
    
  4316. 
    
  4317.   // Determine if this boundary has stylesheets that need to be awaited upon completion
    
  4318.   boundaryResources.stylesheets.forEach(hasStylesToHoist);
    
  4319. 
    
  4320.   if (currentlyRenderingBoundaryHasStylesToHoist) {
    
  4321.     renderState.stylesToHoist = true;
    
  4322.   }
    
  4323.   return destinationHasCapacity;
    
  4324. }
    
  4325. 
    
  4326. function flushResource(this: Destination, resource: Resource) {
    
  4327.   for (let i = 0; i < resource.length; i++) {
    
  4328.     writeChunk(this, resource[i]);
    
  4329.   }
    
  4330.   resource.length = 0;
    
  4331. }
    
  4332. 
    
  4333. const stylesheetFlushingQueue: Array<Chunk | PrecomputedChunk> = [];
    
  4334. 
    
  4335. function flushStyleInPreamble(
    
  4336.   this: Destination,
    
  4337.   stylesheet: StylesheetResource,
    
  4338.   key: string,
    
  4339.   map: Map<string, StylesheetResource>,
    
  4340. ) {
    
  4341.   // We still need to encode stylesheet chunks
    
  4342.   // because unlike most Hoistables and Resources we do not eagerly encode
    
  4343.   // them during render. This is because if we flush late we have to send a
    
  4344.   // different encoding and we don't want to encode multiple times
    
  4345.   pushLinkImpl(stylesheetFlushingQueue, stylesheet.props);
    
  4346.   for (let i = 0; i < stylesheetFlushingQueue.length; i++) {
    
  4347.     writeChunk(this, stylesheetFlushingQueue[i]);
    
  4348.   }
    
  4349.   stylesheetFlushingQueue.length = 0;
    
  4350.   stylesheet.state = PREAMBLE;
    
  4351. }
    
  4352. 
    
  4353. const styleTagResourceOpen1 = stringToPrecomputedChunk(
    
  4354.   '<style data-precedence="',
    
  4355. );
    
  4356. const styleTagResourceOpen2 = stringToPrecomputedChunk('" data-href="');
    
  4357. const spaceSeparator = stringToPrecomputedChunk(' ');
    
  4358. const styleTagResourceOpen3 = stringToPrecomputedChunk('">');
    
  4359. 
    
  4360. const styleTagResourceClose = stringToPrecomputedChunk('</style>');
    
  4361. 
    
  4362. function flushStylesInPreamble(
    
  4363.   this: Destination,
    
  4364.   styleQueue: StyleQueue,
    
  4365.   precedence: string,
    
  4366. ) {
    
  4367.   const hasStylesheets = styleQueue.sheets.size > 0;
    
  4368.   styleQueue.sheets.forEach(flushStyleInPreamble, this);
    
  4369.   styleQueue.sheets.clear();
    
  4370. 
    
  4371.   const rules = styleQueue.rules;
    
  4372.   const hrefs = styleQueue.hrefs;
    
  4373.   // If we don't emit any stylesheets at this precedence we still need to maintain the precedence
    
  4374.   // order so even if there are no rules for style tags at this precedence we emit an empty style
    
  4375.   // tag with the data-precedence attribute
    
  4376.   if (!hasStylesheets || hrefs.length) {
    
  4377.     writeChunk(this, styleTagResourceOpen1);
    
  4378.     writeChunk(this, styleQueue.precedence);
    
  4379.     let i = 0;
    
  4380.     if (hrefs.length) {
    
  4381.       writeChunk(this, styleTagResourceOpen2);
    
  4382.       for (; i < hrefs.length - 1; i++) {
    
  4383.         writeChunk(this, hrefs[i]);
    
  4384.         writeChunk(this, spaceSeparator);
    
  4385.       }
    
  4386.       writeChunk(this, hrefs[i]);
    
  4387.     }
    
  4388.     writeChunk(this, styleTagResourceOpen3);
    
  4389.     for (i = 0; i < rules.length; i++) {
    
  4390.       writeChunk(this, rules[i]);
    
  4391.     }
    
  4392.     writeChunk(this, styleTagResourceClose);
    
  4393. 
    
  4394.     // style resources can flush continuously since more rules may be written into
    
  4395.     // them with new hrefs. Instead of marking it flushed, we simply reset the chunks
    
  4396.     // and hrefs
    
  4397.     rules.length = 0;
    
  4398.     hrefs.length = 0;
    
  4399.   }
    
  4400. }
    
  4401. 
    
  4402. function preloadLateStyle(this: Destination, stylesheet: StylesheetResource) {
    
  4403.   if (stylesheet.state === PENDING) {
    
  4404.     stylesheet.state = PRELOADED;
    
  4405.     const preloadProps = preloadAsStylePropsFromProps(
    
  4406.       stylesheet.props.href,
    
  4407.       stylesheet.props,
    
  4408.     );
    
  4409.     pushLinkImpl(stylesheetFlushingQueue, preloadProps);
    
  4410.     for (let i = 0; i < stylesheetFlushingQueue.length; i++) {
    
  4411.       writeChunk(this, stylesheetFlushingQueue[i]);
    
  4412.     }
    
  4413.     stylesheetFlushingQueue.length = 0;
    
  4414.   }
    
  4415. }
    
  4416. 
    
  4417. function preloadLateStyles(this: Destination, styleQueue: StyleQueue) {
    
  4418.   styleQueue.sheets.forEach(preloadLateStyle, this);
    
  4419.   styleQueue.sheets.clear();
    
  4420. }
    
  4421. 
    
  4422. // We don't bother reporting backpressure at the moment because we expect to
    
  4423. // flush the entire preamble in a single pass. This probably should be modified
    
  4424. // in the future to be backpressure sensitive but that requires a larger refactor
    
  4425. // of the flushing code in Fizz.
    
  4426. export function writePreamble(
    
  4427.   destination: Destination,
    
  4428.   resumableState: ResumableState,
    
  4429.   renderState: RenderState,
    
  4430.   willFlushAllSegments: boolean,
    
  4431. ): void {
    
  4432.   // This function must be called exactly once on every request
    
  4433.   if (
    
  4434.     enableFizzExternalRuntime &&
    
  4435.     !willFlushAllSegments &&
    
  4436.     renderState.externalRuntimeScript
    
  4437.   ) {
    
  4438.     // If the root segment is incomplete due to suspended tasks
    
  4439.     // (e.g. willFlushAllSegments = false) and we are using data
    
  4440.     // streaming format, ensure the external runtime is sent.
    
  4441.     // (User code could choose to send this even earlier by calling
    
  4442.     //  preinit(...), if they know they will suspend).
    
  4443.     const {src, chunks} = renderState.externalRuntimeScript;
    
  4444.     internalPreinitScript(resumableState, renderState, src, chunks);
    
  4445.   }
    
  4446. 
    
  4447.   const htmlChunks = renderState.htmlChunks;
    
  4448.   const headChunks = renderState.headChunks;
    
  4449. 
    
  4450.   let i = 0;
    
  4451. 
    
  4452.   // Emit open tags before Hoistables and Resources
    
  4453.   if (htmlChunks) {
    
  4454.     // We have an <html> to emit as part of the preamble
    
  4455.     for (i = 0; i < htmlChunks.length; i++) {
    
  4456.       writeChunk(destination, htmlChunks[i]);
    
  4457.     }
    
  4458.     if (headChunks) {
    
  4459.       for (i = 0; i < headChunks.length; i++) {
    
  4460.         writeChunk(destination, headChunks[i]);
    
  4461.       }
    
  4462.     } else {
    
  4463.       // We did not render a head but we emitted an <html> so we emit one now
    
  4464.       writeChunk(destination, startChunkForTag('head'));
    
  4465.       writeChunk(destination, endOfStartTag);
    
  4466.     }
    
  4467.   } else if (headChunks) {
    
  4468.     // We do not have an <html> but we do have a <head>
    
  4469.     for (i = 0; i < headChunks.length; i++) {
    
  4470.       writeChunk(destination, headChunks[i]);
    
  4471.     }
    
  4472.   }
    
  4473. 
    
  4474.   // Emit high priority Hoistables
    
  4475.   const charsetChunks = renderState.charsetChunks;
    
  4476.   for (i = 0; i < charsetChunks.length; i++) {
    
  4477.     writeChunk(destination, charsetChunks[i]);
    
  4478.   }
    
  4479.   charsetChunks.length = 0;
    
  4480. 
    
  4481.   // emit preconnect resources
    
  4482.   renderState.preconnects.forEach(flushResource, destination);
    
  4483.   renderState.preconnects.clear();
    
  4484. 
    
  4485.   const preconnectChunks = renderState.preconnectChunks;
    
  4486.   for (i = 0; i < preconnectChunks.length; i++) {
    
  4487.     writeChunk(destination, preconnectChunks[i]);
    
  4488.   }
    
  4489.   preconnectChunks.length = 0;
    
  4490. 
    
  4491.   renderState.fontPreloads.forEach(flushResource, destination);
    
  4492.   renderState.fontPreloads.clear();
    
  4493. 
    
  4494.   renderState.highImagePreloads.forEach(flushResource, destination);
    
  4495.   renderState.highImagePreloads.clear();
    
  4496. 
    
  4497.   // Flush unblocked stylesheets by precedence
    
  4498.   renderState.styles.forEach(flushStylesInPreamble, destination);
    
  4499. 
    
  4500.   const importMapChunks = renderState.importMapChunks;
    
  4501.   for (i = 0; i < importMapChunks.length; i++) {
    
  4502.     writeChunk(destination, importMapChunks[i]);
    
  4503.   }
    
  4504.   importMapChunks.length = 0;
    
  4505. 
    
  4506.   renderState.bootstrapScripts.forEach(flushResource, destination);
    
  4507. 
    
  4508.   renderState.scripts.forEach(flushResource, destination);
    
  4509.   renderState.scripts.clear();
    
  4510. 
    
  4511.   renderState.bulkPreloads.forEach(flushResource, destination);
    
  4512.   renderState.bulkPreloads.clear();
    
  4513. 
    
  4514.   // Write embedding preloadChunks
    
  4515.   const preloadChunks = renderState.preloadChunks;
    
  4516.   for (i = 0; i < preloadChunks.length; i++) {
    
  4517.     writeChunk(destination, preloadChunks[i]);
    
  4518.   }
    
  4519.   preloadChunks.length = 0;
    
  4520. 
    
  4521.   // Write embedding hoistableChunks
    
  4522.   const hoistableChunks = renderState.hoistableChunks;
    
  4523.   for (i = 0; i < hoistableChunks.length; i++) {
    
  4524.     writeChunk(destination, hoistableChunks[i]);
    
  4525.   }
    
  4526.   hoistableChunks.length = 0;
    
  4527. 
    
  4528.   // Flush closing head if necessary
    
  4529.   if (htmlChunks && headChunks === null) {
    
  4530.     // We have an <html> rendered but no <head> rendered. We however inserted
    
  4531.     // a <head> up above so we need to emit the </head> now. This is safe because
    
  4532.     // if the main content contained the </head> it would also have provided a
    
  4533.     // <head>. This means that all the content inside <html> is either <body> or
    
  4534.     // invalid HTML
    
  4535.     writeChunk(destination, endChunkForTag('head'));
    
  4536.   }
    
  4537. }
    
  4538. 
    
  4539. // We don't bother reporting backpressure at the moment because we expect to
    
  4540. // flush the entire preamble in a single pass. This probably should be modified
    
  4541. // in the future to be backpressure sensitive but that requires a larger refactor
    
  4542. // of the flushing code in Fizz.
    
  4543. export function writeHoistables(
    
  4544.   destination: Destination,
    
  4545.   resumableState: ResumableState,
    
  4546.   renderState: RenderState,
    
  4547. ): void {
    
  4548.   let i = 0;
    
  4549. 
    
  4550.   // Emit high priority Hoistables
    
  4551. 
    
  4552.   // We omit charsetChunks because we have already sent the shell and if it wasn't
    
  4553.   // already sent it is too late now.
    
  4554. 
    
  4555.   renderState.preconnects.forEach(flushResource, destination);
    
  4556.   renderState.preconnects.clear();
    
  4557. 
    
  4558.   const preconnectChunks = renderState.preconnectChunks;
    
  4559.   for (i = 0; i < preconnectChunks.length; i++) {
    
  4560.     writeChunk(destination, preconnectChunks[i]);
    
  4561.   }
    
  4562.   preconnectChunks.length = 0;
    
  4563. 
    
  4564.   renderState.fontPreloads.forEach(flushResource, destination);
    
  4565.   renderState.fontPreloads.clear();
    
  4566. 
    
  4567.   renderState.highImagePreloads.forEach(flushResource, destination);
    
  4568.   renderState.highImagePreloads.clear();
    
  4569. 
    
  4570.   // Preload any stylesheets. these will emit in a render instruction that follows this
    
  4571.   // but we want to kick off preloading as soon as possible
    
  4572.   renderState.styles.forEach(preloadLateStyles, destination);
    
  4573. 
    
  4574.   // We only hoist importmaps that are configured through createResponse and that will
    
  4575.   // always flush in the preamble. Generally we don't expect people to render them as
    
  4576.   // tags when using React but if you do they are going to be treated like regular inline
    
  4577.   // scripts and flush after other hoistables which is problematic
    
  4578. 
    
  4579.   // bootstrap scripts should flush above script priority but these can only flush in the preamble
    
  4580.   // so we elide the code here for performance
    
  4581. 
    
  4582.   renderState.scripts.forEach(flushResource, destination);
    
  4583.   renderState.scripts.clear();
    
  4584. 
    
  4585.   renderState.bulkPreloads.forEach(flushResource, destination);
    
  4586.   renderState.bulkPreloads.clear();
    
  4587. 
    
  4588.   // Write embedding preloadChunks
    
  4589.   const preloadChunks = renderState.preloadChunks;
    
  4590.   for (i = 0; i < preloadChunks.length; i++) {
    
  4591.     writeChunk(destination, preloadChunks[i]);
    
  4592.   }
    
  4593.   preloadChunks.length = 0;
    
  4594. 
    
  4595.   // Write embedding hoistableChunks
    
  4596.   const hoistableChunks = renderState.hoistableChunks;
    
  4597.   for (i = 0; i < hoistableChunks.length; i++) {
    
  4598.     writeChunk(destination, hoistableChunks[i]);
    
  4599.   }
    
  4600.   hoistableChunks.length = 0;
    
  4601. }
    
  4602. 
    
  4603. export function writePostamble(
    
  4604.   destination: Destination,
    
  4605.   resumableState: ResumableState,
    
  4606. ): void {
    
  4607.   if (resumableState.hasBody) {
    
  4608.     writeChunk(destination, endChunkForTag('body'));
    
  4609.   }
    
  4610.   if (resumableState.hasHtml) {
    
  4611.     writeChunk(destination, endChunkForTag('html'));
    
  4612.   }
    
  4613. }
    
  4614. 
    
  4615. const arrayFirstOpenBracket = stringToPrecomputedChunk('[');
    
  4616. const arraySubsequentOpenBracket = stringToPrecomputedChunk(',[');
    
  4617. const arrayInterstitial = stringToPrecomputedChunk(',');
    
  4618. const arrayCloseBracket = stringToPrecomputedChunk(']');
    
  4619. 
    
  4620. // This function writes a 2D array of strings to be embedded in javascript.
    
  4621. // E.g.
    
  4622. //  [["JS_escaped_string1", "JS_escaped_string2"]]
    
  4623. function writeStyleResourceDependenciesInJS(
    
  4624.   destination: Destination,
    
  4625.   boundaryResources: BoundaryResources,
    
  4626. ): void {
    
  4627.   writeChunk(destination, arrayFirstOpenBracket);
    
  4628. 
    
  4629.   let nextArrayOpenBrackChunk = arrayFirstOpenBracket;
    
  4630.   boundaryResources.stylesheets.forEach(resource => {
    
  4631.     if (resource.state === PREAMBLE) {
    
  4632.       // We can elide this dependency because it was flushed in the shell and
    
  4633.       // should be ready before content is shown on the client
    
  4634.     } else if (resource.state === LATE) {
    
  4635.       // We only need to emit the href because this resource flushed in an earlier
    
  4636.       // boundary already which encoded the attributes necessary to construct
    
  4637.       // the resource instance on the client.
    
  4638.       writeChunk(destination, nextArrayOpenBrackChunk);
    
  4639.       writeStyleResourceDependencyHrefOnlyInJS(
    
  4640.         destination,
    
  4641.         resource.props.href,
    
  4642.       );
    
  4643.       writeChunk(destination, arrayCloseBracket);
    
  4644.       nextArrayOpenBrackChunk = arraySubsequentOpenBracket;
    
  4645.     } else {
    
  4646.       // We need to emit the whole resource for insertion on the client
    
  4647.       writeChunk(destination, nextArrayOpenBrackChunk);
    
  4648.       writeStyleResourceDependencyInJS(
    
  4649.         destination,
    
  4650.         resource.props.href,
    
  4651.         resource.props['data-precedence'],
    
  4652.         resource.props,
    
  4653.       );
    
  4654.       writeChunk(destination, arrayCloseBracket);
    
  4655.       nextArrayOpenBrackChunk = arraySubsequentOpenBracket;
    
  4656. 
    
  4657.       resource.state = LATE;
    
  4658.     }
    
  4659.   });
    
  4660.   writeChunk(destination, arrayCloseBracket);
    
  4661. }
    
  4662. 
    
  4663. /* Helper functions */
    
  4664. function writeStyleResourceDependencyHrefOnlyInJS(
    
  4665.   destination: Destination,
    
  4666.   href: string,
    
  4667. ) {
    
  4668.   // We should actually enforce this earlier when the resource is created but for
    
  4669.   // now we make sure we are actually dealing with a string here.
    
  4670.   if (__DEV__) {
    
  4671.     checkAttributeStringCoercion(href, 'href');
    
  4672.   }
    
  4673.   const coercedHref = '' + (href: any);
    
  4674.   writeChunk(
    
  4675.     destination,
    
  4676.     stringToChunk(escapeJSObjectForInstructionScripts(coercedHref)),
    
  4677.   );
    
  4678. }
    
  4679. 
    
  4680. function writeStyleResourceDependencyInJS(
    
  4681.   destination: Destination,
    
  4682.   href: mixed,
    
  4683.   precedence: mixed,
    
  4684.   props: Object,
    
  4685. ) {
    
  4686.   // eslint-disable-next-line react-internal/safe-string-coercion
    
  4687.   const coercedHref = sanitizeURL('' + (href: any));
    
  4688.   writeChunk(
    
  4689.     destination,
    
  4690.     stringToChunk(escapeJSObjectForInstructionScripts(coercedHref)),
    
  4691.   );
    
  4692. 
    
  4693.   if (__DEV__) {
    
  4694.     checkAttributeStringCoercion(precedence, 'precedence');
    
  4695.   }
    
  4696.   const coercedPrecedence = '' + (precedence: any);
    
  4697.   writeChunk(destination, arrayInterstitial);
    
  4698.   writeChunk(
    
  4699.     destination,
    
  4700.     stringToChunk(escapeJSObjectForInstructionScripts(coercedPrecedence)),
    
  4701.   );
    
  4702. 
    
  4703.   for (const propKey in props) {
    
  4704.     if (hasOwnProperty.call(props, propKey)) {
    
  4705.       const propValue = props[propKey];
    
  4706.       if (propValue == null) {
    
  4707.         continue;
    
  4708.       }
    
  4709.       switch (propKey) {
    
  4710.         case 'href':
    
  4711.         case 'rel':
    
  4712.         case 'precedence':
    
  4713.         case 'data-precedence': {
    
  4714.           break;
    
  4715.         }
    
  4716.         case 'children':
    
  4717.         case 'dangerouslySetInnerHTML':
    
  4718.           throw new Error(
    
  4719.             `${'link'} is a self-closing tag and must neither have \`children\` nor ` +
    
  4720.               'use `dangerouslySetInnerHTML`.',
    
  4721.           );
    
  4722.         default:
    
  4723.           writeStyleResourceAttributeInJS(destination, propKey, propValue);
    
  4724.           break;
    
  4725.       }
    
  4726.     }
    
  4727.   }
    
  4728.   return null;
    
  4729. }
    
  4730. 
    
  4731. function writeStyleResourceAttributeInJS(
    
  4732.   destination: Destination,
    
  4733.   name: string,
    
  4734.   value: string | boolean | number | Function | Object, // not null or undefined
    
  4735. ): void {
    
  4736.   let attributeName = name.toLowerCase();
    
  4737.   let attributeValue;
    
  4738.   switch (typeof value) {
    
  4739.     case 'function':
    
  4740.     case 'symbol':
    
  4741.       return;
    
  4742.   }
    
  4743. 
    
  4744.   switch (name) {
    
  4745.     // Reserved names
    
  4746.     case 'innerHTML':
    
  4747.     case 'dangerouslySetInnerHTML':
    
  4748.     case 'suppressContentEditableWarning':
    
  4749.     case 'suppressHydrationWarning':
    
  4750.     case 'style':
    
  4751.       // Ignored
    
  4752.       return;
    
  4753. 
    
  4754.     // Attribute renames
    
  4755.     case 'className': {
    
  4756.       attributeName = 'class';
    
  4757.       if (__DEV__) {
    
  4758.         checkAttributeStringCoercion(value, attributeName);
    
  4759.       }
    
  4760.       attributeValue = '' + (value: any);
    
  4761.       break;
    
  4762.     }
    
  4763.     // Booleans
    
  4764.     case 'hidden': {
    
  4765.       if (value === false) {
    
  4766.         return;
    
  4767.       }
    
  4768.       attributeValue = '';
    
  4769.       break;
    
  4770.     }
    
  4771.     // Santized URLs
    
  4772.     case 'src':
    
  4773.     case 'href': {
    
  4774.       value = sanitizeURL(value);
    
  4775.       if (__DEV__) {
    
  4776.         checkAttributeStringCoercion(value, attributeName);
    
  4777.       }
    
  4778.       attributeValue = '' + (value: any);
    
  4779.       break;
    
  4780.     }
    
  4781.     default: {
    
  4782.       if (
    
  4783.         // unrecognized event handlers are not SSR'd and we (apparently)
    
  4784.         // use on* as hueristic for these handler props
    
  4785.         name.length > 2 &&
    
  4786.         (name[0] === 'o' || name[0] === 'O') &&
    
  4787.         (name[1] === 'n' || name[1] === 'N')
    
  4788.       ) {
    
  4789.         return;
    
  4790.       }
    
  4791.       if (!isAttributeNameSafe(name)) {
    
  4792.         return;
    
  4793.       }
    
  4794.       if (__DEV__) {
    
  4795.         checkAttributeStringCoercion(value, attributeName);
    
  4796.       }
    
  4797.       attributeValue = '' + (value: any);
    
  4798.     }
    
  4799.   }
    
  4800.   writeChunk(destination, arrayInterstitial);
    
  4801.   writeChunk(
    
  4802.     destination,
    
  4803.     stringToChunk(escapeJSObjectForInstructionScripts(attributeName)),
    
  4804.   );
    
  4805.   writeChunk(destination, arrayInterstitial);
    
  4806.   writeChunk(
    
  4807.     destination,
    
  4808.     stringToChunk(escapeJSObjectForInstructionScripts(attributeValue)),
    
  4809.   );
    
  4810. }
    
  4811. 
    
  4812. // This function writes a 2D array of strings to be embedded in an attribute
    
  4813. // value and read with JSON.parse in ReactDOMServerExternalRuntime.js
    
  4814. // E.g.
    
  4815. //  [[&quot;JSON_escaped_string1&quot;, &quot;JSON_escaped_string2&quot;]]
    
  4816. function writeStyleResourceDependenciesInAttr(
    
  4817.   destination: Destination,
    
  4818.   boundaryResources: BoundaryResources,
    
  4819. ): void {
    
  4820.   writeChunk(destination, arrayFirstOpenBracket);
    
  4821. 
    
  4822.   let nextArrayOpenBrackChunk = arrayFirstOpenBracket;
    
  4823.   boundaryResources.stylesheets.forEach(resource => {
    
  4824.     if (resource.state === PREAMBLE) {
    
  4825.       // We can elide this dependency because it was flushed in the shell and
    
  4826.       // should be ready before content is shown on the client
    
  4827.     } else if (resource.state === LATE) {
    
  4828.       // We only need to emit the href because this resource flushed in an earlier
    
  4829.       // boundary already which encoded the attributes necessary to construct
    
  4830.       // the resource instance on the client.
    
  4831.       writeChunk(destination, nextArrayOpenBrackChunk);
    
  4832.       writeStyleResourceDependencyHrefOnlyInAttr(
    
  4833.         destination,
    
  4834.         resource.props.href,
    
  4835.       );
    
  4836.       writeChunk(destination, arrayCloseBracket);
    
  4837.       nextArrayOpenBrackChunk = arraySubsequentOpenBracket;
    
  4838.     } else {
    
  4839.       // We need to emit the whole resource for insertion on the client
    
  4840.       writeChunk(destination, nextArrayOpenBrackChunk);
    
  4841.       writeStyleResourceDependencyInAttr(
    
  4842.         destination,
    
  4843.         resource.props.href,
    
  4844.         resource.props['data-precedence'],
    
  4845.         resource.props,
    
  4846.       );
    
  4847.       writeChunk(destination, arrayCloseBracket);
    
  4848.       nextArrayOpenBrackChunk = arraySubsequentOpenBracket;
    
  4849. 
    
  4850.       resource.state = LATE;
    
  4851.     }
    
  4852.   });
    
  4853.   writeChunk(destination, arrayCloseBracket);
    
  4854. }
    
  4855. 
    
  4856. /* Helper functions */
    
  4857. function writeStyleResourceDependencyHrefOnlyInAttr(
    
  4858.   destination: Destination,
    
  4859.   href: string,
    
  4860. ) {
    
  4861.   // We should actually enforce this earlier when the resource is created but for
    
  4862.   // now we make sure we are actually dealing with a string here.
    
  4863.   if (__DEV__) {
    
  4864.     checkAttributeStringCoercion(href, 'href');
    
  4865.   }
    
  4866.   const coercedHref = '' + (href: any);
    
  4867.   writeChunk(
    
  4868.     destination,
    
  4869.     stringToChunk(escapeTextForBrowser(JSON.stringify(coercedHref))),
    
  4870.   );
    
  4871. }
    
  4872. 
    
  4873. function writeStyleResourceDependencyInAttr(
    
  4874.   destination: Destination,
    
  4875.   href: mixed,
    
  4876.   precedence: mixed,
    
  4877.   props: Object,
    
  4878. ) {
    
  4879.   // eslint-disable-next-line react-internal/safe-string-coercion
    
  4880.   const coercedHref = sanitizeURL('' + (href: any));
    
  4881.   writeChunk(
    
  4882.     destination,
    
  4883.     stringToChunk(escapeTextForBrowser(JSON.stringify(coercedHref))),
    
  4884.   );
    
  4885. 
    
  4886.   if (__DEV__) {
    
  4887.     checkAttributeStringCoercion(precedence, 'precedence');
    
  4888.   }
    
  4889.   const coercedPrecedence = '' + (precedence: any);
    
  4890.   writeChunk(destination, arrayInterstitial);
    
  4891.   writeChunk(
    
  4892.     destination,
    
  4893.     stringToChunk(escapeTextForBrowser(JSON.stringify(coercedPrecedence))),
    
  4894.   );
    
  4895. 
    
  4896.   for (const propKey in props) {
    
  4897.     if (hasOwnProperty.call(props, propKey)) {
    
  4898.       const propValue = props[propKey];
    
  4899.       if (propValue == null) {
    
  4900.         continue;
    
  4901.       }
    
  4902.       switch (propKey) {
    
  4903.         case 'href':
    
  4904.         case 'rel':
    
  4905.         case 'precedence':
    
  4906.         case 'data-precedence': {
    
  4907.           break;
    
  4908.         }
    
  4909.         case 'children':
    
  4910.         case 'dangerouslySetInnerHTML':
    
  4911.           throw new Error(
    
  4912.             `${'link'} is a self-closing tag and must neither have \`children\` nor ` +
    
  4913.               'use `dangerouslySetInnerHTML`.',
    
  4914.           );
    
  4915.         default:
    
  4916.           writeStyleResourceAttributeInAttr(destination, propKey, propValue);
    
  4917.           break;
    
  4918.       }
    
  4919.     }
    
  4920.   }
    
  4921.   return null;
    
  4922. }
    
  4923. 
    
  4924. function writeStyleResourceAttributeInAttr(
    
  4925.   destination: Destination,
    
  4926.   name: string,
    
  4927.   value: string | boolean | number | Function | Object, // not null or undefined
    
  4928. ): void {
    
  4929.   let attributeName = name.toLowerCase();
    
  4930.   let attributeValue;
    
  4931.   switch (typeof value) {
    
  4932.     case 'function':
    
  4933.     case 'symbol':
    
  4934.       return;
    
  4935.   }
    
  4936. 
    
  4937.   switch (name) {
    
  4938.     // Reserved names
    
  4939.     case 'innerHTML':
    
  4940.     case 'dangerouslySetInnerHTML':
    
  4941.     case 'suppressContentEditableWarning':
    
  4942.     case 'suppressHydrationWarning':
    
  4943.     case 'style':
    
  4944.       // Ignored
    
  4945.       return;
    
  4946. 
    
  4947.     // Attribute renames
    
  4948.     case 'className': {
    
  4949.       attributeName = 'class';
    
  4950.       if (__DEV__) {
    
  4951.         checkAttributeStringCoercion(value, attributeName);
    
  4952.       }
    
  4953.       attributeValue = '' + (value: any);
    
  4954.       break;
    
  4955.     }
    
  4956. 
    
  4957.     // Booleans
    
  4958.     case 'hidden': {
    
  4959.       if (value === false) {
    
  4960.         return;
    
  4961.       }
    
  4962.       attributeValue = '';
    
  4963.       break;
    
  4964.     }
    
  4965. 
    
  4966.     // Santized URLs
    
  4967.     case 'src':
    
  4968.     case 'href': {
    
  4969.       value = sanitizeURL(value);
    
  4970.       if (__DEV__) {
    
  4971.         checkAttributeStringCoercion(value, attributeName);
    
  4972.       }
    
  4973.       attributeValue = '' + (value: any);
    
  4974.       break;
    
  4975.     }
    
  4976.     default: {
    
  4977.       if (
    
  4978.         // unrecognized event handlers are not SSR'd and we (apparently)
    
  4979.         // use on* as hueristic for these handler props
    
  4980.         name.length > 2 &&
    
  4981.         (name[0] === 'o' || name[0] === 'O') &&
    
  4982.         (name[1] === 'n' || name[1] === 'N')
    
  4983.       ) {
    
  4984.         return;
    
  4985.       }
    
  4986.       if (!isAttributeNameSafe(name)) {
    
  4987.         return;
    
  4988.       }
    
  4989.       if (__DEV__) {
    
  4990.         checkAttributeStringCoercion(value, attributeName);
    
  4991.       }
    
  4992.       attributeValue = '' + (value: any);
    
  4993.     }
    
  4994.   }
    
  4995.   writeChunk(destination, arrayInterstitial);
    
  4996.   writeChunk(
    
  4997.     destination,
    
  4998.     stringToChunk(escapeTextForBrowser(JSON.stringify(attributeName))),
    
  4999.   );
    
  5000.   writeChunk(destination, arrayInterstitial);
    
  5001.   writeChunk(
    
  5002.     destination,
    
  5003.     stringToChunk(escapeTextForBrowser(JSON.stringify(attributeValue))),
    
  5004.   );
    
  5005. }
    
  5006. 
    
  5007. /**
    
  5008.  * Resources
    
  5009.  */
    
  5010. 
    
  5011. type StylesheetState = 0 | 1 | 2 | 3;
    
  5012. const PENDING: StylesheetState = 0;
    
  5013. const PRELOADED: StylesheetState = 1;
    
  5014. const PREAMBLE: StylesheetState = 2;
    
  5015. const LATE: StylesheetState = 3;
    
  5016. 
    
  5017. type PreconnectProps = {
    
  5018.   rel: 'preconnect' | 'dns-prefetch',
    
  5019.   href: string,
    
  5020.   [string]: mixed,
    
  5021. };
    
  5022. 
    
  5023. type PreloadAsProps = {
    
  5024.   rel: 'preload',
    
  5025.   as: string,
    
  5026.   href: ?string,
    
  5027.   [string]: ?string,
    
  5028. };
    
  5029. type PreloadModuleProps = {
    
  5030.   rel: 'modulepreload',
    
  5031.   href: ?string,
    
  5032.   [string]: ?string,
    
  5033. };
    
  5034. type PreloadProps = PreloadAsProps | PreloadModuleProps;
    
  5035. 
    
  5036. type ScriptProps = {
    
  5037.   async: true,
    
  5038.   src: string,
    
  5039.   [string]: mixed,
    
  5040. };
    
  5041. type ModuleScriptProps = {
    
  5042.   async: true,
    
  5043.   src: string,
    
  5044.   type: 'module',
    
  5045.   [string]: mixed,
    
  5046. };
    
  5047. 
    
  5048. export type Resource = Array<Chunk | PrecomputedChunk>;
    
  5049. 
    
  5050. type StylesheetProps = {
    
  5051.   rel: 'stylesheet',
    
  5052.   href: string,
    
  5053.   'data-precedence': string,
    
  5054.   [string]: mixed,
    
  5055. };
    
  5056. type StylesheetResource = {
    
  5057.   props: StylesheetProps,
    
  5058.   state: StylesheetState,
    
  5059. };
    
  5060. 
    
  5061. export type BoundaryResources = {
    
  5062.   styles: Set<StyleQueue>,
    
  5063.   stylesheets: Set<StylesheetResource>,
    
  5064. };
    
  5065. 
    
  5066. export type StyleQueue = {
    
  5067.   precedence: Chunk | PrecomputedChunk,
    
  5068.   rules: Array<Chunk | PrecomputedChunk>,
    
  5069.   hrefs: Array<Chunk | PrecomputedChunk>,
    
  5070.   sheets: Map<string, StylesheetResource>,
    
  5071. };
    
  5072. 
    
  5073. export function createBoundaryResources(): BoundaryResources {
    
  5074.   return {
    
  5075.     styles: new Set(),
    
  5076.     stylesheets: new Set(),
    
  5077.   };
    
  5078. }
    
  5079. 
    
  5080. export function setCurrentlyRenderingBoundaryResourcesTarget(
    
  5081.   renderState: RenderState,
    
  5082.   boundaryResources: null | BoundaryResources,
    
  5083. ) {
    
  5084.   renderState.boundaryResources = boundaryResources;
    
  5085. }
    
  5086. 
    
  5087. function getResourceKey(href: string): string {
    
  5088.   return href;
    
  5089. }
    
  5090. 
    
  5091. function getImageResourceKey(
    
  5092.   href: string,
    
  5093.   imageSrcSet?: ?string,
    
  5094.   imageSizes?: ?string,
    
  5095. ): string {
    
  5096.   if (imageSrcSet) {
    
  5097.     return imageSrcSet + '\n' + (imageSizes || '');
    
  5098.   }
    
  5099.   return href;
    
  5100. }
    
  5101. 
    
  5102. function prefetchDNS(href: string) {
    
  5103.   if (!enableFloat) {
    
  5104.     return;
    
  5105.   }
    
  5106.   const request = resolveRequest();
    
  5107.   if (!request) {
    
  5108.     // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also
    
  5109.     // possibly get them from the stack if we are not in an async context. Since we were not able to resolve
    
  5110.     // the resources for this call in either case we opt to do nothing. We can consider making this a warning
    
  5111.     // but there may be times where calling a function outside of render is intentional (i.e. to warm up data
    
  5112.     // fetching) and we don't want to warn in those cases.
    
  5113.     return;
    
  5114.   }
    
  5115.   const resumableState = getResumableState(request);
    
  5116.   const renderState = getRenderState(request);
    
  5117. 
    
  5118.   if (typeof href === 'string' && href) {
    
  5119.     const key = getResourceKey(href);
    
  5120.     if (!resumableState.dnsResources.hasOwnProperty(key)) {
    
  5121.       const resource: Resource = [];
    
  5122.       resumableState.dnsResources[key] = EXISTS;
    
  5123.       pushLinkImpl(resource, ({href, rel: 'dns-prefetch'}: PreconnectProps));
    
  5124.       renderState.preconnects.add(resource);
    
  5125.     }
    
  5126.     flushResources(request);
    
  5127.   }
    
  5128. }
    
  5129. 
    
  5130. function preconnect(href: string, crossOrigin: ?CrossOriginEnum) {
    
  5131.   if (!enableFloat) {
    
  5132.     return;
    
  5133.   }
    
  5134.   const request = resolveRequest();
    
  5135.   if (!request) {
    
  5136.     // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also
    
  5137.     // possibly get them from the stack if we are not in an async context. Since we were not able to resolve
    
  5138.     // the resources for this call in either case we opt to do nothing. We can consider making this a warning
    
  5139.     // but there may be times where calling a function outside of render is intentional (i.e. to warm up data
    
  5140.     // fetching) and we don't want to warn in those cases.
    
  5141.     return;
    
  5142.   }
    
  5143.   const resumableState = getResumableState(request);
    
  5144.   const renderState = getRenderState(request);
    
  5145. 
    
  5146.   if (typeof href === 'string' && href) {
    
  5147.     const resources =
    
  5148.       crossOrigin === 'use-credentials'
    
  5149.         ? resumableState.connectResources.credentials
    
  5150.         : typeof crossOrigin === 'string'
    
  5151.         ? resumableState.connectResources.anonymous
    
  5152.         : resumableState.connectResources.default;
    
  5153.     const key = getResourceKey(href);
    
  5154.     if (!resources.hasOwnProperty(key)) {
    
  5155.       const resource: Resource = [];
    
  5156.       resources[key] = EXISTS;
    
  5157.       pushLinkImpl(
    
  5158.         resource,
    
  5159.         ({rel: 'preconnect', href, crossOrigin}: PreconnectProps),
    
  5160.       );
    
  5161.       renderState.preconnects.add(resource);
    
  5162.     }
    
  5163.     flushResources(request);
    
  5164.   }
    
  5165. }
    
  5166. 
    
  5167. function preload(href: string, as: string, options?: ?PreloadImplOptions) {
    
  5168.   if (!enableFloat) {
    
  5169.     return;
    
  5170.   }
    
  5171.   const request = resolveRequest();
    
  5172.   if (!request) {
    
  5173.     // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also
    
  5174.     // possibly get them from the stack if we are not in an async context. Since we were not able to resolve
    
  5175.     // the resources for this call in either case we opt to do nothing. We can consider making this a warning
    
  5176.     // but there may be times where calling a function outside of render is intentional (i.e. to warm up data
    
  5177.     // fetching) and we don't want to warn in those cases.
    
  5178.     return;
    
  5179.   }
    
  5180.   const resumableState = getResumableState(request);
    
  5181.   const renderState = getRenderState(request);
    
  5182.   if (as && href) {
    
  5183.     switch (as) {
    
  5184.       case 'image': {
    
  5185.         let imageSrcSet, imageSizes, fetchPriority;
    
  5186.         if (options) {
    
  5187.           imageSrcSet = options.imageSrcSet;
    
  5188.           imageSizes = options.imageSizes;
    
  5189.           fetchPriority = options.fetchPriority;
    
  5190.         }
    
  5191.         const key = getImageResourceKey(href, imageSrcSet, imageSizes);
    
  5192.         if (resumableState.imageResources.hasOwnProperty(key)) {
    
  5193.           // we can return if we already have this resource
    
  5194.           return;
    
  5195.         }
    
  5196.         resumableState.imageResources[key] = PRELOAD_NO_CREDS;
    
  5197.         const resource = ([]: Resource);
    
  5198.         pushLinkImpl(
    
  5199.           resource,
    
  5200.           Object.assign(
    
  5201.             ({
    
  5202.               rel: 'preload',
    
  5203.               // There is a bug in Safari where imageSrcSet is not respected on preload links
    
  5204.               // so we omit the href here if we have imageSrcSet b/c safari will load the wrong image.
    
  5205.               // This harms older browers that do not support imageSrcSet by making their preloads not work
    
  5206.               // but this population is shrinking fast and is already small so we accept this tradeoff.
    
  5207.               href: imageSrcSet ? undefined : href,
    
  5208.               as,
    
  5209.             }: PreloadAsProps),
    
  5210.             options,
    
  5211.           ),
    
  5212.         );
    
  5213.         if (fetchPriority === 'high') {
    
  5214.           renderState.highImagePreloads.add(resource);
    
  5215.         } else {
    
  5216.           renderState.bulkPreloads.add(resource);
    
  5217.           // Stash the resource in case we need to promote it to higher priority
    
  5218.           // when an img tag is rendered
    
  5219.           renderState.preloads.images.set(key, resource);
    
  5220.         }
    
  5221.         break;
    
  5222.       }
    
  5223.       case 'style': {
    
  5224.         const key = getResourceKey(href);
    
  5225.         if (resumableState.styleResources.hasOwnProperty(key)) {
    
  5226.           // we can return if we already have this resource
    
  5227.           return;
    
  5228.         }
    
  5229.         const resource = ([]: Resource);
    
  5230.         pushLinkImpl(
    
  5231.           resource,
    
  5232.           Object.assign(({rel: 'preload', href, as}: PreloadAsProps), options),
    
  5233.         );
    
  5234.         resumableState.styleResources[key] =
    
  5235.           options &&
    
  5236.           (typeof options.crossOrigin === 'string' ||
    
  5237.             typeof options.integrity === 'string')
    
  5238.             ? [options.crossOrigin, options.integrity]
    
  5239.             : PRELOAD_NO_CREDS;
    
  5240.         renderState.preloads.stylesheets.set(key, resource);
    
  5241.         renderState.bulkPreloads.add(resource);
    
  5242.         break;
    
  5243.       }
    
  5244.       case 'script': {
    
  5245.         const key = getResourceKey(href);
    
  5246.         if (resumableState.scriptResources.hasOwnProperty(key)) {
    
  5247.           // we can return if we already have this resource
    
  5248.           return;
    
  5249.         }
    
  5250.         const resource = ([]: Resource);
    
  5251.         renderState.preloads.scripts.set(key, resource);
    
  5252.         renderState.bulkPreloads.add(resource);
    
  5253.         pushLinkImpl(
    
  5254.           resource,
    
  5255.           Object.assign(({rel: 'preload', href, as}: PreloadAsProps), options),
    
  5256.         );
    
  5257.         resumableState.scriptResources[key] =
    
  5258.           options &&
    
  5259.           (typeof options.crossOrigin === 'string' ||
    
  5260.             typeof options.integrity === 'string')
    
  5261.             ? [options.crossOrigin, options.integrity]
    
  5262.             : PRELOAD_NO_CREDS;
    
  5263.         break;
    
  5264.       }
    
  5265.       default: {
    
  5266.         const key = getResourceKey(href);
    
  5267.         const hasAsType = resumableState.unknownResources.hasOwnProperty(as);
    
  5268.         let resources;
    
  5269.         if (hasAsType) {
    
  5270.           resources = resumableState.unknownResources[as];
    
  5271.           if (resources.hasOwnProperty(key)) {
    
  5272.             // we can return if we already have this resource
    
  5273.             return;
    
  5274.           }
    
  5275.         } else {
    
  5276.           resources = ({}: ResumableState['unknownResources']['asType']);
    
  5277.           resumableState.unknownResources[as] = resources;
    
  5278.         }
    
  5279.         const resource = ([]: Resource);
    
  5280.         const props = Object.assign(
    
  5281.           ({
    
  5282.             rel: 'preload',
    
  5283.             href,
    
  5284.             as,
    
  5285.           }: PreloadAsProps),
    
  5286.           options,
    
  5287.         );
    
  5288.         switch (as) {
    
  5289.           case 'font':
    
  5290.             renderState.fontPreloads.add(resource);
    
  5291.             break;
    
  5292.           // intentional fall through
    
  5293.           default:
    
  5294.             renderState.bulkPreloads.add(resource);
    
  5295.         }
    
  5296.         pushLinkImpl(resource, props);
    
  5297.         resources[key] = PRELOAD_NO_CREDS;
    
  5298.       }
    
  5299.     }
    
  5300.     // If we got this far we created a new resource
    
  5301.     flushResources(request);
    
  5302.   }
    
  5303. }
    
  5304. 
    
  5305. function preloadModule(
    
  5306.   href: string,
    
  5307.   options?: ?PreloadModuleImplOptions,
    
  5308. ): void {
    
  5309.   if (!enableFloat) {
    
  5310.     return;
    
  5311.   }
    
  5312.   const request = resolveRequest();
    
  5313.   if (!request) {
    
  5314.     // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also
    
  5315.     // possibly get them from the stack if we are not in an async context. Since we were not able to resolve
    
  5316.     // the resources for this call in either case we opt to do nothing. We can consider making this a warning
    
  5317.     // but there may be times where calling a function outside of render is intentional (i.e. to warm up data
    
  5318.     // fetching) and we don't want to warn in those cases.
    
  5319.     return;
    
  5320.   }
    
  5321.   const resumableState = getResumableState(request);
    
  5322.   const renderState = getRenderState(request);
    
  5323.   if (href) {
    
  5324.     const key = getResourceKey(href);
    
  5325.     const as =
    
  5326.       options && typeof options.as === 'string' ? options.as : 'script';
    
  5327. 
    
  5328.     let resource;
    
  5329.     switch (as) {
    
  5330.       case 'script': {
    
  5331.         if (resumableState.moduleScriptResources.hasOwnProperty(key)) {
    
  5332.           // we can return if we already have this resource
    
  5333.           return;
    
  5334.         }
    
  5335.         resource = ([]: Resource);
    
  5336.         resumableState.moduleScriptResources[key] =
    
  5337.           options &&
    
  5338.           (typeof options.crossOrigin === 'string' ||
    
  5339.             typeof options.integrity === 'string')
    
  5340.             ? [options.crossOrigin, options.integrity]
    
  5341.             : PRELOAD_NO_CREDS;
    
  5342.         renderState.preloads.moduleScripts.set(key, resource);
    
  5343.         break;
    
  5344.       }
    
  5345.       default: {
    
  5346.         const hasAsType =
    
  5347.           resumableState.moduleUnknownResources.hasOwnProperty(as);
    
  5348.         let resources;
    
  5349.         if (hasAsType) {
    
  5350.           resources = resumableState.unknownResources[as];
    
  5351.           if (resources.hasOwnProperty(key)) {
    
  5352.             // we can return if we already have this resource
    
  5353.             return;
    
  5354.           }
    
  5355.         } else {
    
  5356.           resources = ({}: ResumableState['moduleUnknownResources']['asType']);
    
  5357.           resumableState.moduleUnknownResources[as] = resources;
    
  5358.         }
    
  5359.         resource = ([]: Resource);
    
  5360.         resources[key] = PRELOAD_NO_CREDS;
    
  5361.       }
    
  5362.     }
    
  5363. 
    
  5364.     pushLinkImpl(
    
  5365.       resource,
    
  5366.       Object.assign(
    
  5367.         ({
    
  5368.           rel: 'modulepreload',
    
  5369.           href,
    
  5370.         }: PreloadModuleProps),
    
  5371.         options,
    
  5372.       ),
    
  5373.     );
    
  5374.     renderState.bulkPreloads.add(resource);
    
  5375.     // If we got this far we created a new resource
    
  5376.     flushResources(request);
    
  5377.   }
    
  5378. }
    
  5379. 
    
  5380. function preinitStyle(
    
  5381.   href: string,
    
  5382.   precedence: ?string,
    
  5383.   options?: ?PreinitStyleOptions,
    
  5384. ): void {
    
  5385.   if (!enableFloat) {
    
  5386.     return;
    
  5387.   }
    
  5388.   const request = resolveRequest();
    
  5389.   if (!request) {
    
  5390.     // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also
    
  5391.     // possibly get them from the stack if we are not in an async context. Since we were not able to resolve
    
  5392.     // the resources for this call in either case we opt to do nothing. We can consider making this a warning
    
  5393.     // but there may be times where calling a function outside of render is intentional (i.e. to warm up data
    
  5394.     // fetching) and we don't want to warn in those cases.
    
  5395.     return;
    
  5396.   }
    
  5397.   const resumableState = getResumableState(request);
    
  5398.   const renderState = getRenderState(request);
    
  5399.   if (href) {
    
  5400.     precedence = precedence || 'default';
    
  5401.     const key = getResourceKey(href);
    
  5402. 
    
  5403.     let styleQueue = renderState.styles.get(precedence);
    
  5404.     const hasKey = resumableState.styleResources.hasOwnProperty(key);
    
  5405.     const resourceState = hasKey
    
  5406.       ? resumableState.styleResources[key]
    
  5407.       : undefined;
    
  5408.     if (resourceState !== EXISTS) {
    
  5409.       // We are going to create this resource now so it is marked as Exists
    
  5410.       resumableState.styleResources[key] = EXISTS;
    
  5411. 
    
  5412.       // If this is the first time we've encountered this precedence we need
    
  5413.       // to create a StyleQueue
    
  5414.       if (!styleQueue) {
    
  5415.         styleQueue = {
    
  5416.           precedence: stringToChunk(escapeTextForBrowser(precedence)),
    
  5417.           rules: ([]: Array<Chunk | PrecomputedChunk>),
    
  5418.           hrefs: ([]: Array<Chunk | PrecomputedChunk>),
    
  5419.           sheets: (new Map(): Map<string, StylesheetResource>),
    
  5420.         };
    
  5421.         renderState.styles.set(precedence, styleQueue);
    
  5422.       }
    
  5423. 
    
  5424.       const resource = {
    
  5425.         state: PENDING,
    
  5426.         props: Object.assign(
    
  5427.           ({
    
  5428.             rel: 'stylesheet',
    
  5429.             href,
    
  5430.             'data-precedence': precedence,
    
  5431.           }: StylesheetProps),
    
  5432.           options,
    
  5433.         ),
    
  5434.       };
    
  5435. 
    
  5436.       if (resourceState) {
    
  5437.         // When resourceState is truty it is a Preload state. We cast it for clarity
    
  5438.         const preloadState: Preloaded | PreloadedWithCredentials =
    
  5439.           resourceState;
    
  5440.         if (preloadState.length === 2) {
    
  5441.           adoptPreloadCredentials(resource.props, preloadState);
    
  5442.         }
    
  5443. 
    
  5444.         const preloadResource = renderState.preloads.stylesheets.get(key);
    
  5445.         if (preloadResource && preloadResource.length > 0) {
    
  5446.           // The Preload for this resource was created in this render pass and has not flushed yet so
    
  5447.           // we need to clear it to avoid it flushing.
    
  5448.           preloadResource.length = 0;
    
  5449.         } else {
    
  5450.           // Either the preload resource from this render already flushed in this render pass
    
  5451.           // or the preload flushed in a prior pass (prerender). In either case we need to mark
    
  5452.           // this resource as already having been preloaded.
    
  5453.           resource.state = PRELOADED;
    
  5454.         }
    
  5455.       } else {
    
  5456.         // We don't need to check whether a preloadResource exists in the renderState
    
  5457.         // because if it did exist then the resourceState would also exist and we would
    
  5458.         // have hit the primary if condition above.
    
  5459.       }
    
  5460. 
    
  5461.       // We add the newly created resource to our StyleQueue and if necessary
    
  5462.       // track the resource with the currently rendering boundary
    
  5463.       styleQueue.sheets.set(key, resource);
    
  5464. 
    
  5465.       // Notify the request that there are resources to flush even if no work is currently happening
    
  5466.       flushResources(request);
    
  5467.     }
    
  5468.   }
    
  5469. }
    
  5470. 
    
  5471. function preinitScript(src: string, options?: ?PreinitScriptOptions): void {
    
  5472.   if (!enableFloat) {
    
  5473.     return;
    
  5474.   }
    
  5475.   const request = resolveRequest();
    
  5476.   if (!request) {
    
  5477.     // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also
    
  5478.     // possibly get them from the stack if we are not in an async context. Since we were not able to resolve
    
  5479.     // the resources for this call in either case we opt to do nothing. We can consider making this a warning
    
  5480.     // but there may be times where calling a function outside of render is intentional (i.e. to warm up data
    
  5481.     // fetching) and we don't want to warn in those cases.
    
  5482.     return;
    
  5483.   }
    
  5484.   const resumableState = getResumableState(request);
    
  5485.   const renderState = getRenderState(request);
    
  5486.   if (src) {
    
  5487.     const key = getResourceKey(src);
    
  5488. 
    
  5489.     const hasKey = resumableState.scriptResources.hasOwnProperty(key);
    
  5490.     const resourceState = hasKey
    
  5491.       ? resumableState.scriptResources[key]
    
  5492.       : undefined;
    
  5493.     if (resourceState !== EXISTS) {
    
  5494.       // We are going to create this resource now so it is marked as Exists
    
  5495.       resumableState.scriptResources[key] = EXISTS;
    
  5496. 
    
  5497.       const props: ScriptProps = Object.assign(
    
  5498.         ({
    
  5499.           src,
    
  5500.           async: true,
    
  5501.         }: ScriptProps),
    
  5502.         options,
    
  5503.       );
    
  5504.       if (resourceState) {
    
  5505.         // When resourceState is truty it is a Preload state. We cast it for clarity
    
  5506.         const preloadState: Preloaded | PreloadedWithCredentials =
    
  5507.           resourceState;
    
  5508.         if (preloadState.length === 2) {
    
  5509.           adoptPreloadCredentials(props, preloadState);
    
  5510.         }
    
  5511. 
    
  5512.         const preloadResource = renderState.preloads.scripts.get(key);
    
  5513.         if (preloadResource) {
    
  5514.           // the preload resource exists was created in this render. Now that we have
    
  5515.           // a script resource which will emit earlier than a preload would if it
    
  5516.           // hasn't already flushed we prevent it from flushing by zeroing the length
    
  5517.           preloadResource.length = 0;
    
  5518.         }
    
  5519.       }
    
  5520. 
    
  5521.       const resource: Resource = [];
    
  5522.       // Add to the script flushing queue
    
  5523.       renderState.scripts.add(resource);
    
  5524.       // encode the tag as Chunks
    
  5525.       pushScriptImpl(resource, props);
    
  5526.       // Notify the request that there are resources to flush even if no work is currently happening
    
  5527.       flushResources(request);
    
  5528.     }
    
  5529.     return;
    
  5530.   }
    
  5531. }
    
  5532. 
    
  5533. function preinitModuleScript(
    
  5534.   src: string,
    
  5535.   options?: ?PreinitModuleScriptOptions,
    
  5536. ): void {
    
  5537.   if (!enableFloat) {
    
  5538.     return;
    
  5539.   }
    
  5540.   const request = resolveRequest();
    
  5541.   if (!request) {
    
  5542.     // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also
    
  5543.     // possibly get them from the stack if we are not in an async context. Since we were not able to resolve
    
  5544.     // the resources for this call in either case we opt to do nothing. We can consider making this a warning
    
  5545.     // but there may be times where calling a function outside of render is intentional (i.e. to warm up data
    
  5546.     // fetching) and we don't want to warn in those cases.
    
  5547.     return;
    
  5548.   }
    
  5549.   const resumableState = getResumableState(request);
    
  5550.   const renderState = getRenderState(request);
    
  5551.   if (src) {
    
  5552.     const key = getResourceKey(src);
    
  5553.     const hasKey = resumableState.moduleScriptResources.hasOwnProperty(key);
    
  5554.     const resourceState = hasKey
    
  5555.       ? resumableState.moduleScriptResources[key]
    
  5556.       : undefined;
    
  5557.     if (resourceState !== EXISTS) {
    
  5558.       // We are going to create this resource now so it is marked as Exists
    
  5559.       resumableState.moduleScriptResources[key] = EXISTS;
    
  5560. 
    
  5561.       const props = Object.assign(
    
  5562.         ({
    
  5563.           src,
    
  5564.           type: 'module',
    
  5565.           async: true,
    
  5566.         }: ModuleScriptProps),
    
  5567.         options,
    
  5568.       );
    
  5569.       if (resourceState) {
    
  5570.         // When resourceState is truty it is a Preload state. We cast it for clarity
    
  5571.         const preloadState: Preloaded | PreloadedWithCredentials =
    
  5572.           resourceState;
    
  5573.         if (preloadState.length === 2) {
    
  5574.           adoptPreloadCredentials(props, preloadState);
    
  5575.         }
    
  5576. 
    
  5577.         const preloadResource = renderState.preloads.moduleScripts.get(key);
    
  5578.         if (preloadResource) {
    
  5579.           // the preload resource exists was created in this render. Now that we have
    
  5580.           // a script resource which will emit earlier than a preload would if it
    
  5581.           // hasn't already flushed we prevent it from flushing by zeroing the length
    
  5582.           preloadResource.length = 0;
    
  5583.         }
    
  5584.       }
    
  5585. 
    
  5586.       const resource: Resource = [];
    
  5587.       // Add to the script flushing queue
    
  5588.       renderState.scripts.add(resource);
    
  5589.       // encode the tag as Chunks
    
  5590.       pushScriptImpl(resource, props);
    
  5591.       // Notify the request that there are resources to flush even if no work is currently happening
    
  5592.       flushResources(request);
    
  5593.     }
    
  5594.     return;
    
  5595.   }
    
  5596. }
    
  5597. 
    
  5598. // This function is only safe to call at Request start time since it assumes
    
  5599. // that each module has not already been preloaded. If we find a need to preload
    
  5600. // scripts at any other point in time we will need to check whether the preload
    
  5601. // already exists and not assume it
    
  5602. function preloadBootstrapScriptOrModule(
    
  5603.   resumableState: ResumableState,
    
  5604.   renderState: RenderState,
    
  5605.   href: string,
    
  5606.   props: PreloadProps,
    
  5607. ): void {
    
  5608.   if (!enableFloat) {
    
  5609.     return;
    
  5610.   }
    
  5611.   const key = getResourceKey(href);
    
  5612. 
    
  5613.   if (__DEV__) {
    
  5614.     if (
    
  5615.       resumableState.scriptResources.hasOwnProperty(key) ||
    
  5616.       resumableState.moduleScriptResources.hasOwnProperty(key)
    
  5617.     ) {
    
  5618.       // This is coded as a React error because it should be impossible for a userspace preload to preempt this call
    
  5619.       // If a userspace preload can preempt it then this assumption is broken and we need to reconsider this strategy
    
  5620.       // rather than instruct the user to not preload their bootstrap scripts themselves
    
  5621.       console.error(
    
  5622.         'Internal React Error: React expected bootstrap script or module with src "%s" to not have been preloaded already. please file an issue',
    
  5623.         href,
    
  5624.       );
    
  5625.     }
    
  5626.   }
    
  5627. 
    
  5628.   // The href used for bootstrap scripts and bootstrap modules should never be
    
  5629.   // used to preinit the resource. If a script can be preinited then it shouldn't
    
  5630.   // be a bootstrap script/module and if it is a bootstrap script/module then it
    
  5631.   // must not be safe to emit early. To avoid possibly allowing for preinits of
    
  5632.   // bootstrap scripts/modules we occlude these keys.
    
  5633.   resumableState.scriptResources[key] = EXISTS;
    
  5634.   resumableState.moduleScriptResources[key] = EXISTS;
    
  5635. 
    
  5636.   const resource: Resource = [];
    
  5637.   pushLinkImpl(resource, props);
    
  5638.   renderState.bootstrapScripts.add(resource);
    
  5639. }
    
  5640. 
    
  5641. function internalPreinitScript(
    
  5642.   resumableState: ResumableState,
    
  5643.   renderState: RenderState,
    
  5644.   src: string,
    
  5645.   chunks: Array<Chunk | PrecomputedChunk>,
    
  5646. ): void {
    
  5647.   const key = getResourceKey(src);
    
  5648.   if (!resumableState.scriptResources.hasOwnProperty(key)) {
    
  5649.     const resource: Resource = chunks;
    
  5650.     resumableState.scriptResources[key] = EXISTS;
    
  5651.     renderState.scripts.add(resource);
    
  5652.   }
    
  5653.   return;
    
  5654. }
    
  5655. 
    
  5656. function preloadAsStylePropsFromProps(href: string, props: any): PreloadProps {
    
  5657.   return {
    
  5658.     rel: 'preload',
    
  5659.     as: 'style',
    
  5660.     href: href,
    
  5661.     crossOrigin: props.crossOrigin,
    
  5662.     fetchPriority: props.fetchPriority,
    
  5663.     integrity: props.integrity,
    
  5664.     media: props.media,
    
  5665.     hrefLang: props.hrefLang,
    
  5666.     referrerPolicy: props.referrerPolicy,
    
  5667.   };
    
  5668. }
    
  5669. 
    
  5670. function stylesheetPropsFromRawProps(rawProps: any): StylesheetProps {
    
  5671.   return {
    
  5672.     ...rawProps,
    
  5673.     'data-precedence': rawProps.precedence,
    
  5674.     precedence: null,
    
  5675.   };
    
  5676. }
    
  5677. 
    
  5678. function adoptPreloadCredentials(
    
  5679.   target: StylesheetProps | ScriptProps | ModuleScriptProps,
    
  5680.   preloadState: PreloadedWithCredentials,
    
  5681. ): void {
    
  5682.   if (target.crossOrigin == null) target.crossOrigin = preloadState[0];
    
  5683.   if (target.integrity == null) target.integrity = preloadState[1];
    
  5684. }
    
  5685. 
    
  5686. function hoistStyleQueueDependency(
    
  5687.   this: BoundaryResources,
    
  5688.   styleQueue: StyleQueue,
    
  5689. ) {
    
  5690.   this.styles.add(styleQueue);
    
  5691. }
    
  5692. 
    
  5693. function hoistStylesheetDependency(
    
  5694.   this: BoundaryResources,
    
  5695.   stylesheet: StylesheetResource,
    
  5696. ) {
    
  5697.   this.stylesheets.add(stylesheet);
    
  5698. }
    
  5699. 
    
  5700. export function hoistResources(
    
  5701.   renderState: RenderState,
    
  5702.   source: BoundaryResources,
    
  5703. ): void {
    
  5704.   const currentBoundaryResources = renderState.boundaryResources;
    
  5705.   if (currentBoundaryResources) {
    
  5706.     source.styles.forEach(hoistStyleQueueDependency, currentBoundaryResources);
    
  5707.     source.stylesheets.forEach(
    
  5708.       hoistStylesheetDependency,
    
  5709.       currentBoundaryResources,
    
  5710.     );
    
  5711.   }
    
  5712. }
    
  5713. 
    
  5714. export type TransitionStatus = FormStatus;
    
  5715. export const NotPendingTransition: TransitionStatus = NotPending;