diff --git a/compiled/facebook-www/REVISION b/compiled/facebook-www/REVISION index d1100a6727..abc52c1de2 100644 --- a/compiled/facebook-www/REVISION +++ b/compiled/facebook-www/REVISION @@ -1 +1 @@ -1c958aa4abf9e6b638489b1d73cdb1b6dc7c3ab6 +554fc49f41465d914b15dc8eb2ec094f37824f7e diff --git a/compiled/facebook-www/React-dev.modern.js b/compiled/facebook-www/React-dev.modern.js index 115fe4d5a6..b3640cb69a 100644 --- a/compiled/facebook-www/React-dev.modern.js +++ b/compiled/facebook-www/React-dev.modern.js @@ -24,7 +24,7 @@ if (__DEV__) { ) { __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error()); } - var ReactVersion = "18.3.0-www-modern-2c842b55"; + var ReactVersion = "18.3.0-www-modern-afe290cd"; // ATTENTION // When adding new symbols to this file, diff --git a/compiled/facebook-www/ReactDOMServer-dev.classic.js b/compiled/facebook-www/ReactDOMServer-dev.classic.js index e09b988fa7..13da746fd9 100644 --- a/compiled/facebook-www/ReactDOMServer-dev.classic.js +++ b/compiled/facebook-www/ReactDOMServer-dev.classic.js @@ -19,7 +19,7 @@ if (__DEV__) { var React = require("react"); var ReactDOM = require("react-dom"); - var ReactVersion = "18.3.0-www-classic-12c301cf"; + var ReactVersion = "18.3.0-www-classic-ac038d0e"; // This refers to a WWW module. var warningWWW = require("warning"); @@ -2221,6 +2221,7 @@ if (__DEV__) { headChunks: null, externalRuntimeScript: externalRuntimeScript, bootstrapChunks: bootstrapChunks, + importMapChunks: importMapChunks, onHeaders: onHeaders, headers: headers, resets: { @@ -2235,9 +2236,7 @@ if (__DEV__) { style: {} }, charsetChunks: [], - preconnectChunks: [], - importMapChunks: importMapChunks, - preloadChunks: [], + viewportChunks: [], hoistableChunks: [], // cleared on flush preconnects: new Set(), @@ -2256,7 +2255,7 @@ if (__DEV__) { }, nonce: nonce, // like a module global for currently rendering boundary - boundaryResources: null, + hoistableState: null, stylesToHoist: false }; @@ -3903,7 +3902,8 @@ if (__DEV__) { renderState, textEmbedded, insertionMode, - noscriptTagInScope + noscriptTagInScope, + isFallback ) { { if ( @@ -3919,11 +3919,24 @@ if (__DEV__) { target.push(textSeparator); } - if (typeof props.charSet === "string") { + if (isFallback) { + // Hoistable Elements for fallbacks are simply omitted. we don't want to emit them early + // because they are likely superceded by primary content and we want to avoid needing to clean + // them up when the primary content is ready. They are never hydrated on the client anyway because + // boundaries in fallback are awaited or client render, in either case there is never hydration + return null; + } else if (typeof props.charSet === "string") { + // "charset" Should really be config and not picked up from tags however since this is + // the only way to embed the tag today we flush it on a special queue on the Request so it + // can go before everything else. Like viewport this means that the tag will escape it's + // parent container. return pushSelfClosing(renderState.charsetChunks, props, "meta"); } else if (props.name === "viewport") { - // "viewport" isn't related to preconnect but it has the right priority - return pushSelfClosing(renderState.preconnectChunks, props, "meta"); + // "viewport" is flushed on the Request so it can go earlier that Float resources that + // might be affected by it. This means it can escape the boundary it is rendered within. + // This is a pragmatic solution to viewport being incredibly sensitive to document order + // without requiring all hoistables to be flushed too early. + return pushSelfClosing(renderState.viewportChunks, props, "meta"); } else { return pushSelfClosing(renderState.hoistableChunks, props, "meta"); } @@ -3936,9 +3949,11 @@ if (__DEV__) { props, resumableState, renderState, + hoistableState, textEmbedded, insertionMode, - noscriptTagInScope + noscriptTagInScope, + isFallback ) { { var rel = props.rel; @@ -4058,8 +4073,8 @@ if (__DEV__) { styleQueue.sheets.set(key, resource); - if (renderState.boundaryResources) { - renderState.boundaryResources.stylesheets.add(resource); + if (hoistableState) { + hoistableState.stylesheets.add(resource); } } else { // We need to track whether this boundary should wait on this resource or not. @@ -4071,8 +4086,8 @@ if (__DEV__) { var _resource = styleQueue.sheets.get(key); if (_resource) { - if (renderState.boundaryResources) { - renderState.boundaryResources.stylesheets.add(_resource); + if (hoistableState) { + hoistableState.stylesheets.add(_resource); } } } @@ -4099,16 +4114,14 @@ if (__DEV__) { target.push(textSeparator); } - switch (props.rel) { - case "preconnect": - case "dns-prefetch": - return pushLinkImpl(renderState.preconnectChunks, props); - - case "preload": - return pushLinkImpl(renderState.preloadChunks, props); - - default: - return pushLinkImpl(renderState.hoistableChunks, props); + if (isFallback) { + // Hoistable Elements for fallbacks are simply omitted. we don't want to emit them early + // because they are likely superceded by primary content and we want to avoid needing to clean + // them up when the primary content is ready. They are never hydrated on the client anyway because + // boundaries in fallback are awaited or client render, in either case there is never hydration + return null; + } else { + return pushLinkImpl(renderState.hoistableChunks, props); } } } @@ -4150,6 +4163,7 @@ if (__DEV__) { props, resumableState, renderState, + hoistableState, textEmbedded, insertionMode, noscriptTagInScope @@ -4253,8 +4267,8 @@ if (__DEV__) { // it. However, it's possible when you resume that the style has already been emitted // and then it wouldn't be recreated in the RenderState and there's no need to track // it again since we should've hoisted it to the shell already. - if (renderState.boundaryResources) { - renderState.boundaryResources.styles.add(styleQueue); + if (hoistableState) { + hoistableState.styles.add(styleQueue); } } @@ -4566,7 +4580,8 @@ if (__DEV__) { props, renderState, insertionMode, - noscriptTagInScope + noscriptTagInScope, + isFallback ) { { if (hasOwnProperty.call(props, "children")) { @@ -4622,8 +4637,15 @@ if (__DEV__) { !noscriptTagInScope && props.itemProp == null ) { - pushTitleImpl(renderState.hoistableChunks, props); - return null; + if (isFallback) { + // Hoistable Elements for fallbacks are simply omitted. we don't want to emit them early + // because they are likely superceded by primary content and we want to avoid needing to clean + // them up when the primary content is ready. They are never hydrated on the client anyway because + // boundaries in fallback are awaited or client render, in either case there is never hydration + return null; + } else { + pushTitleImpl(renderState.hoistableChunks, props); + } } else { return pushTitleImpl(target, props); } @@ -5083,8 +5105,10 @@ if (__DEV__) { props, resumableState, renderState, + hoistableState, formatContext, - textEmbedded + textEmbedded, + isFallback ) { { validateProperties$2(type, props); @@ -5159,7 +5183,8 @@ if (__DEV__) { props, renderState, formatContext.insertionMode, - !!(formatContext.tagScope & NOSCRIPT_SCOPE) + !!(formatContext.tagScope & NOSCRIPT_SCOPE), + isFallback ); case "link": @@ -5168,9 +5193,11 @@ if (__DEV__) { props, resumableState, renderState, + hoistableState, textEmbedded, formatContext.insertionMode, - !!(formatContext.tagScope & NOSCRIPT_SCOPE) + !!(formatContext.tagScope & NOSCRIPT_SCOPE), + isFallback ); case "script": @@ -5190,6 +5217,7 @@ if (__DEV__) { props, resumableState, renderState, + hoistableState, textEmbedded, formatContext.insertionMode, !!(formatContext.tagScope & NOSCRIPT_SCOPE) @@ -5202,7 +5230,8 @@ if (__DEV__) { renderState, textEmbedded, formatContext.insertionMode, - !!(formatContext.tagScope & NOSCRIPT_SCOPE) + !!(formatContext.tagScope & NOSCRIPT_SCOPE), + isFallback ); // Newline eating tags @@ -5711,7 +5740,7 @@ if (__DEV__) { resumableState, renderState, id, - boundaryResources + hoistableState ) { var requiresStyleInsertion; @@ -5792,12 +5821,12 @@ if (__DEV__) { // - data writer emits a string literal, which is escaped as html // e.g. ["A", "B"] if (scriptFormat) { - writeChunk(destination, completeBoundaryScript3a); // boundaryResources encodes an array literal + writeChunk(destination, completeBoundaryScript3a); // hoistableState encodes an array literal - writeStyleResourceDependenciesInJS(destination, boundaryResources); + writeStyleResourceDependenciesInJS(destination, hoistableState); } else { writeChunk(destination, completeBoundaryData3a); - writeStyleResourceDependenciesInAttr(destination, boundaryResources); + writeStyleResourceDependenciesInAttr(destination, hoistableState); } } else { if (scriptFormat) { @@ -6067,21 +6096,21 @@ if (__DEV__) { return false; } - function writeResourcesForBoundary( + function writeHoistablesForBoundary( destination, - boundaryResources, + hoistableState, renderState ) { // Reset these on each invocation, they are only safe to read in this function currentlyRenderingBoundaryHasStylesToHoist = false; destinationHasCapacity = true; // Flush style tags for each precedence this boundary depends on - boundaryResources.styles.forEach( - flushStyleTagsLateForBoundary, - destination - ); // Determine if this boundary has stylesheets that need to be awaited upon completion + hoistableState.styles.forEach(flushStyleTagsLateForBoundary, destination); // Determine if this boundary has stylesheets that need to be awaited upon completion - boundaryResources.stylesheets.forEach(hasStylesToHoist); + hoistableState.stylesheets.forEach(hasStylesToHoist); // We don't actually want to flush any hoistables until the boundary is complete so we omit + // any further writing here. This is becuase unlike Resources, Hoistable Elements act more like + // regular elements, each rendered element has a unique representation in the DOM. We don't want + // these elements to appear in the DOM early, before the boundary has actually completed if (currentlyRenderingBoundaryHasStylesToHoist) { renderState.stylesToHoist = true; @@ -6243,13 +6272,13 @@ if (__DEV__) { renderState.preconnects.forEach(flushResource, destination); renderState.preconnects.clear(); - var preconnectChunks = renderState.preconnectChunks; + var viewportChunks = renderState.viewportChunks; - for (i = 0; i < preconnectChunks.length; i++) { - writeChunk(destination, preconnectChunks[i]); + for (i = 0; i < viewportChunks.length; i++) { + writeChunk(destination, viewportChunks[i]); } - preconnectChunks.length = 0; + viewportChunks.length = 0; renderState.fontPreloads.forEach(flushResource, destination); renderState.fontPreloads.clear(); renderState.highImagePreloads.forEach(flushResource, destination); @@ -6267,15 +6296,7 @@ if (__DEV__) { renderState.scripts.forEach(flushResource, destination); renderState.scripts.clear(); renderState.bulkPreloads.forEach(flushResource, destination); - renderState.bulkPreloads.clear(); // Write embedding preloadChunks - - var preloadChunks = renderState.preloadChunks; - - for (i = 0; i < preloadChunks.length; i++) { - writeChunk(destination, preloadChunks[i]); - } - - preloadChunks.length = 0; // Write embedding hoistableChunks + renderState.bulkPreloads.clear(); // Write embedding hoistableChunks var hoistableChunks = renderState.hoistableChunks; @@ -6283,14 +6304,11 @@ if (__DEV__) { writeChunk(destination, hoistableChunks[i]); } - hoistableChunks.length = 0; // Flush closing head if necessary + hoistableChunks.length = 0; if (htmlChunks && headChunks === null) { - // We have an rendered but no
rendered. We however inserted - // a up above so we need to emit the now. This is safe because - // if the main content contained the it would also have provided a - // . This means that all the content inside is either or - // invalid HTML + // we have an but we inserted an implicit tag. We need + // to close it since the main content won't have it writeChunk(destination, endChunkForTag("head")); } } // We don't bother reporting backpressure at the moment because we expect to @@ -6303,15 +6321,15 @@ if (__DEV__) { // We omit charsetChunks because we have already sent the shell and if it wasn't // already sent it is too late now. - renderState.preconnects.forEach(flushResource, destination); - renderState.preconnects.clear(); - var preconnectChunks = renderState.preconnectChunks; + var viewportChunks = renderState.viewportChunks; - for (i = 0; i < preconnectChunks.length; i++) { - writeChunk(destination, preconnectChunks[i]); + for (i = 0; i < viewportChunks.length; i++) { + writeChunk(destination, viewportChunks[i]); } - preconnectChunks.length = 0; + viewportChunks.length = 0; + renderState.preconnects.forEach(flushResource, destination); + renderState.preconnects.clear(); renderState.fontPreloads.forEach(flushResource, destination); renderState.fontPreloads.clear(); renderState.highImagePreloads.forEach(flushResource, destination); @@ -6328,15 +6346,7 @@ if (__DEV__) { renderState.scripts.forEach(flushResource, destination); renderState.scripts.clear(); renderState.bulkPreloads.forEach(flushResource, destination); - renderState.bulkPreloads.clear(); // Write embedding preloadChunks - - var preloadChunks = renderState.preloadChunks; - - for (i = 0; i < preloadChunks.length; i++) { - writeChunk(destination, preloadChunks[i]); - } - - preloadChunks.length = 0; // Write embedding hoistableChunks + renderState.bulkPreloads.clear(); // Write embedding hoistableChunks var hoistableChunks = renderState.hoistableChunks; @@ -6362,13 +6372,10 @@ if (__DEV__) { // E.g. // [["JS_escaped_string1", "JS_escaped_string2"]] - function writeStyleResourceDependenciesInJS( - destination, - boundaryResources - ) { + function writeStyleResourceDependenciesInJS(destination, hoistableState) { writeChunk(destination, arrayFirstOpenBracket); var nextArrayOpenBrackChunk = arrayFirstOpenBracket; - boundaryResources.stylesheets.forEach(function (resource) { + hoistableState.stylesheets.forEach(function (resource) { if (resource.state === PREAMBLE); else if (resource.state === LATE) { // We only need to emit the href because this resource flushed in an earlier @@ -6565,13 +6572,10 @@ if (__DEV__) { // E.g. // [["JSON_escaped_string1", "JSON_escaped_string2"]] - function writeStyleResourceDependenciesInAttr( - destination, - boundaryResources - ) { + function writeStyleResourceDependenciesInAttr(destination, hoistableState) { writeChunk(destination, arrayFirstOpenBracket); var nextArrayOpenBrackChunk = arrayFirstOpenBracket; - boundaryResources.stylesheets.forEach(function (resource) { + hoistableState.stylesheets.forEach(function (resource) { if (resource.state === PREAMBLE); else if (resource.state === LATE) { // We only need to emit the href because this resource flushed in an earlier @@ -6776,18 +6780,12 @@ if (__DEV__) { var PRELOADED = 1; var PREAMBLE = 2; var LATE = 3; - function createBoundaryResources() { + function createHoistableState() { return { styles: new Set(), stylesheets: new Set() }; } - function setCurrentlyRenderingBoundaryResourcesTarget( - renderState, - boundaryResources - ) { - renderState.boundaryResources = boundaryResources; - } function getResourceKey(href) { return href; @@ -7677,19 +7675,9 @@ if (__DEV__) { this.stylesheets.add(stylesheet); } - function hoistResources(renderState, source) { - var currentBoundaryResources = renderState.boundaryResources; - - if (currentBoundaryResources) { - source.styles.forEach( - hoistStyleQueueDependency, - currentBoundaryResources - ); - source.stylesheets.forEach( - hoistStylesheetDependency, - currentBoundaryResources - ); - } + function hoistHoistables(parentState, childState) { + childState.styles.forEach(hoistStyleQueueDependency, parentState); + childState.stylesheets.forEach(hoistStylesheetDependency, parentState); } // This function is called at various times depending on whether we are rendering // or prerendering. In this implementation we only actually emit headers once and // subsequent calls are ignored. We track whether the request has a completed shell @@ -7815,13 +7803,12 @@ if (__DEV__) { headChunks: renderState.headChunks, externalRuntimeScript: renderState.externalRuntimeScript, bootstrapChunks: renderState.bootstrapChunks, + importMapChunks: renderState.importMapChunks, onHeaders: renderState.onHeaders, headers: renderState.headers, resets: renderState.resets, charsetChunks: renderState.charsetChunks, - preconnectChunks: renderState.preconnectChunks, - importMapChunks: renderState.importMapChunks, - preloadChunks: renderState.preloadChunks, + viewportChunks: renderState.viewportChunks, hoistableChunks: renderState.hoistableChunks, preconnects: renderState.preconnects, fontPreloads: renderState.fontPreloads, @@ -7832,7 +7819,6 @@ if (__DEV__) { scripts: renderState.scripts, bulkPreloads: renderState.bulkPreloads, preloads: renderState.preloads, - boundaryResources: renderState.boundaryResources, stylesToHoist: renderState.stylesToHoist, // This is an extra field for the legacy renderer generateStaticMarkup: generateStaticMarkup @@ -10835,13 +10821,15 @@ if (__DEV__) { -1, null, rootSegment, + null, abortSet, null, rootFormatContext, emptyContextObject, rootContextSnapshot, emptyTreeContext, - null + null, + false ); pingedTasks.push(rootTask); return request; @@ -10875,7 +10863,8 @@ if (__DEV__) { byteSize: 0, fallbackAbortableTasks: fallbackAbortableTasks, errorDigest: null, - resources: createBoundaryResources(), + contentState: createHoistableState(), + fallbackState: createHoistableState(), trackedContentKeyPath: null, trackedFallbackNode: null }; @@ -10888,13 +10877,15 @@ if (__DEV__) { childIndex, blockedBoundary, blockedSegment, + hoistableState, abortSet, keyPath, formatContext, legacyContext, context, treeContext, - componentStack + componentStack, + isFallback ) { request.allPendingTasks++; @@ -10913,6 +10904,7 @@ if (__DEV__) { }, blockedBoundary: blockedBoundary, blockedSegment: blockedSegment, + hoistableState: hoistableState, abortSet: abortSet, keyPath: keyPath, formatContext: formatContext, @@ -10920,7 +10912,8 @@ if (__DEV__) { context: context, treeContext: treeContext, componentStack: componentStack, - thenableState: thenableState + thenableState: thenableState, + isFallback: isFallback }; abortSet.add(task); return task; @@ -10933,13 +10926,15 @@ if (__DEV__) { node, childIndex, blockedBoundary, + hoistableState, abortSet, keyPath, formatContext, legacyContext, context, treeContext, - componentStack + componentStack, + isFallback ) { request.allPendingTasks++; @@ -10959,6 +10954,7 @@ if (__DEV__) { }, blockedBoundary: blockedBoundary, blockedSegment: null, + hoistableState: hoistableState, abortSet: abortSet, keyPath: keyPath, formatContext: formatContext, @@ -10966,7 +10962,8 @@ if (__DEV__) { context: context, treeContext: treeContext, componentStack: componentStack, - thenableState: thenableState + thenableState: thenableState, + isFallback: isFallback }; abortSet.add(task); return task; @@ -11140,6 +11137,7 @@ if (__DEV__) { createBuiltInComponentStack(task, "Suspense")); var prevKeyPath = task.keyPath; var parentBoundary = task.blockedBoundary; + var parentHoistableState = task.hoistableState; var parentSegment = task.blockedSegment; // Each time we enter a suspense boundary, we split out into a new segment for // the fallback so that we can later replace that segment with the content. // This also lets us split out the main content even if it doesn't suspend, @@ -11187,15 +11185,8 @@ if (__DEV__) { // we're writing to. If something suspends, it'll spawn new suspended task with that context. task.blockedBoundary = newBoundary; + task.hoistableState = newBoundary.contentState; task.blockedSegment = contentRootSegment; - - { - setCurrentlyRenderingBoundaryResourcesTarget( - request.renderState, - newBoundary.resources - ); - } - task.keyPath = keyPath; try { @@ -11234,14 +11225,8 @@ if (__DEV__) { // We don't need to schedule any task because we know the parent has written yet. // We do need to fallthrough to create the fallback though. } finally { - { - setCurrentlyRenderingBoundaryResourcesTarget( - request.renderState, - parentBoundary ? parentBoundary.resources : null - ); - } - task.blockedBoundary = parentBoundary; + task.hoistableState = parentHoistableState; task.blockedSegment = parentSegment; task.keyPath = prevKeyPath; task.componentStack = previousComponentStack; @@ -11279,6 +11264,7 @@ if (__DEV__) { -1, parentBoundary, boundarySegment, + newBoundary.fallbackState, fallbackAbortSet, fallbackKeyPath, task.formatContext, @@ -11286,7 +11272,8 @@ if (__DEV__) { task.context, task.treeContext, // This stack should be the Suspense boundary stack because while the fallback is actually a child segment // of the parent boundary from a component standpoint the fallback is a child of the Suspense boundary itself - suspenseComponentStack + suspenseComponentStack, + true ); // TODO: This should be queued at a separate lower priority queue so that we only work // on preparing fallbacks if we don't have any more main content to task on. @@ -11312,6 +11299,7 @@ if (__DEV__) { var prevKeyPath = task.keyPath; var previousReplaySet = task.replay; var parentBoundary = task.blockedBoundary; + var parentHoistableState = task.hoistableState; var content = props.children; var fallback = props.fallback; var fallbackAbortSet = new Set(); @@ -11323,19 +11311,13 @@ if (__DEV__) { // we're writing to. If something suspends, it'll spawn new suspended task with that context. task.blockedBoundary = resumedBoundary; + task.hoistableState = resumedBoundary.contentState; task.replay = { nodes: childNodes, slots: childSlots, pendingTasks: 1 }; - { - setCurrentlyRenderingBoundaryResourcesTarget( - request.renderState, - resumedBoundary.resources - ); - } - try { // We use the safe form because we don't handle suspending here. Only error handling. renderNode(request, task, content, -1); @@ -11379,14 +11361,8 @@ if (__DEV__) { // We don't need to schedule any task because we know the parent has written yet. // We do need to fallthrough to create the fallback though. } finally { - { - setCurrentlyRenderingBoundaryResourcesTarget( - request.renderState, - parentBoundary ? parentBoundary.resources : null - ); - } - task.blockedBoundary = parentBoundary; + task.hoistableState = parentHoistableState; task.replay = previousReplaySet; task.keyPath = prevKeyPath; task.componentStack = previousComponentStack; @@ -11407,6 +11383,7 @@ if (__DEV__) { fallback, -1, parentBoundary, + resumedBoundary.fallbackState, fallbackAbortSet, fallbackKeyPath, task.formatContext, @@ -11414,7 +11391,8 @@ if (__DEV__) { task.context, task.treeContext, // This stack should be the Suspense boundary stack because while the fallback is actually a child segment // of the parent boundary from a component standpoint the fallback is a child of the Suspense boundary itself - suspenseComponentStack + suspenseComponentStack, + true ); // TODO: This should be queued at a separate lower priority queue so that we only work // on preparing fallbacks if we don't have any more main content to task on. @@ -11449,8 +11427,10 @@ if (__DEV__) { props, request.resumableState, request.renderState, + task.hoistableState, task.formatContext, - segment.lastPushedText + segment.lastPushedText, + task.isFallback ); segment.lastPushedText = false; @@ -12657,6 +12637,7 @@ if (__DEV__) { task.node, task.childIndex, task.blockedBoundary, + task.hoistableState, task.abortSet, task.keyPath, task.formatContext, @@ -12664,7 +12645,8 @@ if (__DEV__) { task.context, task.treeContext, // We pop one task off the stack because the node that suspended will be tried again, // which will add it back onto the stack. - task.componentStack !== null ? task.componentStack.parent : null + task.componentStack !== null ? task.componentStack.parent : null, + task.isFallback ); var ping = newTask.ping; x.then(ping, ping); @@ -12692,6 +12674,7 @@ if (__DEV__) { task.childIndex, task.blockedBoundary, newSegment, + task.hoistableState, task.abortSet, task.keyPath, task.formatContext, @@ -12699,7 +12682,8 @@ if (__DEV__) { task.context, task.treeContext, // We pop one task off the stack because the node that suspended will be tried again, // which will add it back onto the stack. - task.componentStack !== null ? task.componentStack.parent : null + task.componentStack !== null ? task.componentStack.parent : null, + task.isFallback ); var ping = newTask.ping; x.then(ping, ping); @@ -13254,14 +13238,6 @@ if (__DEV__) { } function retryTask(request, task) { - { - var blockedBoundary = task.blockedBoundary; - setCurrentlyRenderingBoundaryResourcesTarget( - request.renderState, - blockedBoundary ? blockedBoundary.resources : null - ); - } - var segment = task.blockedSegment; if (segment === null) { @@ -13341,13 +13317,6 @@ if (__DEV__) { erroredTask(request, task.blockedBoundary, x, errorInfo); return; } finally { - { - setCurrentlyRenderingBoundaryResourcesTarget( - request.renderState, - null - ); - } - { currentTaskInDEV = prevTaskInDEV; } @@ -13432,13 +13401,6 @@ if (__DEV__) { return; } finally { - { - setCurrentlyRenderingBoundaryResourcesTarget( - request.renderState, - null - ); - } - { currentTaskInDEV = prevTaskInDEV; } @@ -13517,7 +13479,18 @@ if (__DEV__) { } } - function flushSubtree(request, destination, segment) { + function flushPreamble(request, destination, rootSegment) { + var willFlushAllSegments = + request.allPendingTasks === 0 && request.trackedPostpones === null; + writePreamble( + destination, + request.resumableState, + request.renderState, + willFlushAllSegments + ); + } + + function flushSubtree(request, destination, segment, hoistableState) { segment.parentFlushed = true; switch (segment.status) { @@ -13549,7 +13522,7 @@ if (__DEV__) { writeChunk(destination, chunks[chunkIdx]); } - r = flushSegment(request, destination, nextChild); + r = flushSegment(request, destination, nextChild, hoistableState); } // Finally just write all the remaining chunks for (; chunkIdx < chunks.length - 1; chunkIdx++) { @@ -13571,12 +13544,12 @@ if (__DEV__) { } } - function flushSegment(request, destination, segment) { + function flushSegment(request, destination, segment, hoistableState) { var boundary = segment.boundary; if (boundary === null) { // Not a suspense boundary. - return flushSubtree(request, destination, segment); + return flushSubtree(request, destination, segment, hoistableState); } boundary.parentFlushed = true; // This segment is a Suspense boundary. We need to decide whether to @@ -13593,7 +13566,7 @@ if (__DEV__) { boundary.errorComponentStack ); // Flush the fallback. - flushSubtree(request, destination, segment); + flushSubtree(request, destination, segment, hoistableState); return writeEndClientRenderedSuspenseBoundary( destination, request.renderState @@ -13611,9 +13584,16 @@ if (__DEV__) { } // This boundary is still loading. Emit a pending suspense boundary wrapper. var id = boundary.rootSegmentID; - writeStartPendingSuspenseBoundary(destination, request.renderState, id); // Flush the fallback. + writeStartPendingSuspenseBoundary(destination, request.renderState, id); // We are going to flush the fallback so we need to hoist the fallback + // state to the parent boundary - flushSubtree(request, destination, segment); + { + if (hoistableState) { + hoistHoistables(hoistableState, boundary.fallbackState); + } + } // Flush the fallback. + + flushSubtree(request, destination, segment, hoistableState); return writeEndPendingSuspenseBoundary(destination); } else if (boundary.byteSize > request.progressiveChunkSize) { // This boundary is large and will be emitted separately so that we can progressively show @@ -13629,13 +13609,19 @@ if (__DEV__) { destination, request.renderState, boundary.rootSegmentID - ); // Flush the fallback. + ); // While we are going to flush the fallback we are going to follow it up with + // the completed boundary immediately so we make the choice to omit fallback + // boundary state from the parent since it will be replaced when the boundary + // flushes later in this pass or in a future flush + // Flush the fallback. - flushSubtree(request, destination, segment); + flushSubtree(request, destination, segment, hoistableState); return writeEndPendingSuspenseBoundary(destination); } else { { - hoistResources(request.renderState, boundary.resources); + if (hoistableState) { + hoistHoistables(hoistableState, boundary.contentState); + } } // We can inline this boundary's content as a complete boundary. writeStartCompletedSuspenseBoundary(destination, request.renderState); @@ -13648,7 +13634,7 @@ if (__DEV__) { } var contentSegment = completedSegments[0]; - flushSegment(request, destination, contentSegment); + flushSegment(request, destination, contentSegment, hoistableState); return writeEndCompletedSuspenseBoundary( destination, request.renderState @@ -13668,25 +13654,23 @@ if (__DEV__) { ); } - function flushSegmentContainer(request, destination, segment) { + function flushSegmentContainer( + request, + destination, + segment, + hoistableState + ) { writeStartSegment( destination, request.renderState, segment.parentFormatContext, segment.id ); - flushSegment(request, destination, segment); + flushSegment(request, destination, segment, hoistableState); return writeEndSegment(destination, segment.parentFormatContext); } function flushCompletedBoundary(request, destination, boundary) { - { - setCurrentlyRenderingBoundaryResourcesTarget( - request.renderState, - boundary.resources - ); - } - var completedSegments = boundary.completedSegments; var i = 0; @@ -13698,9 +13682,9 @@ if (__DEV__) { completedSegments.length = 0; { - writeResourcesForBoundary( + writeHoistablesForBoundary( destination, - boundary.resources, + boundary.contentState, request.renderState ); } @@ -13710,18 +13694,11 @@ if (__DEV__) { request.resumableState, request.renderState, boundary.rootSegmentID, - boundary.resources + boundary.contentState ); } function flushPartialBoundary(request, destination, boundary) { - { - setCurrentlyRenderingBoundaryResourcesTarget( - request.renderState, - boundary.resources - ); - } - var completedSegments = boundary.completedSegments; var i = 0; @@ -13747,13 +13724,9 @@ if (__DEV__) { completedSegments.splice(0, i); { - // The way this is structured we only write resources for partial boundaries - // if there is no backpressure. Later before we complete the boundary we - // will write resources regardless of backpressure before we emit the - // completion instruction - return writeResourcesForBoundary( + return writeHoistablesForBoundary( destination, - boundary.resources, + boundary.contentState, request.renderState ); } @@ -13770,6 +13743,7 @@ if (__DEV__) { return true; } + var hoistableState = boundary.contentState; var segmentID = segment.id; if (segmentID === -1) { @@ -13783,13 +13757,23 @@ if (__DEV__) { ); } - return flushSegmentContainer(request, destination, segment); + return flushSegmentContainer( + request, + destination, + segment, + hoistableState + ); } else if (segmentID === boundary.rootSegmentID) { // When we emit postponed boundaries, we might have assigned the ID already // but it's still the root segment so we can't inject it into the parent yet. - return flushSegmentContainer(request, destination, segment); + return flushSegmentContainer( + request, + destination, + segment, + hoistableState + ); } else { - flushSegmentContainer(request, destination, segment); + flushSegmentContainer(request, destination, segment, hoistableState); return writeCompletedSegmentInstruction( destination, request.resumableState, @@ -13814,16 +13798,10 @@ if (__DEV__) { return; } else if (request.pendingRootTasks === 0) { if (enableFloat) { - writePreamble( - destination, - request.resumableState, - request.renderState, - request.allPendingTasks === 0 && - request.trackedPostpones === null - ); + flushPreamble(request, destination, completedRootSegment); } - flushSegment(request, destination, completedRootSegment); + flushSegment(request, destination, completedRootSegment, null); request.completedRootSegment = null; writeCompletedRoot(destination, request.renderState); } else { diff --git a/compiled/facebook-www/ReactDOMServer-dev.modern.js b/compiled/facebook-www/ReactDOMServer-dev.modern.js index fac1cf5665..23bbb2a263 100644 --- a/compiled/facebook-www/ReactDOMServer-dev.modern.js +++ b/compiled/facebook-www/ReactDOMServer-dev.modern.js @@ -19,7 +19,7 @@ if (__DEV__) { var React = require("react"); var ReactDOM = require("react-dom"); - var ReactVersion = "18.3.0-www-modern-4a47c827"; + var ReactVersion = "18.3.0-www-modern-c10a0d4f"; // This refers to a WWW module. var warningWWW = require("warning"); @@ -2221,6 +2221,7 @@ if (__DEV__) { headChunks: null, externalRuntimeScript: externalRuntimeScript, bootstrapChunks: bootstrapChunks, + importMapChunks: importMapChunks, onHeaders: onHeaders, headers: headers, resets: { @@ -2235,9 +2236,7 @@ if (__DEV__) { style: {} }, charsetChunks: [], - preconnectChunks: [], - importMapChunks: importMapChunks, - preloadChunks: [], + viewportChunks: [], hoistableChunks: [], // cleared on flush preconnects: new Set(), @@ -2256,7 +2255,7 @@ if (__DEV__) { }, nonce: nonce, // like a module global for currently rendering boundary - boundaryResources: null, + hoistableState: null, stylesToHoist: false }; @@ -3903,7 +3902,8 @@ if (__DEV__) { renderState, textEmbedded, insertionMode, - noscriptTagInScope + noscriptTagInScope, + isFallback ) { { if ( @@ -3919,11 +3919,24 @@ if (__DEV__) { target.push(textSeparator); } - if (typeof props.charSet === "string") { + if (isFallback) { + // Hoistable Elements for fallbacks are simply omitted. we don't want to emit them early + // because they are likely superceded by primary content and we want to avoid needing to clean + // them up when the primary content is ready. They are never hydrated on the client anyway because + // boundaries in fallback are awaited or client render, in either case there is never hydration + return null; + } else if (typeof props.charSet === "string") { + // "charset" Should really be config and not picked up from tags however since this is + // the only way to embed the tag today we flush it on a special queue on the Request so it + // can go before everything else. Like viewport this means that the tag will escape it's + // parent container. return pushSelfClosing(renderState.charsetChunks, props, "meta"); } else if (props.name === "viewport") { - // "viewport" isn't related to preconnect but it has the right priority - return pushSelfClosing(renderState.preconnectChunks, props, "meta"); + // "viewport" is flushed on the Request so it can go earlier that Float resources that + // might be affected by it. This means it can escape the boundary it is rendered within. + // This is a pragmatic solution to viewport being incredibly sensitive to document order + // without requiring all hoistables to be flushed too early. + return pushSelfClosing(renderState.viewportChunks, props, "meta"); } else { return pushSelfClosing(renderState.hoistableChunks, props, "meta"); } @@ -3936,9 +3949,11 @@ if (__DEV__) { props, resumableState, renderState, + hoistableState, textEmbedded, insertionMode, - noscriptTagInScope + noscriptTagInScope, + isFallback ) { { var rel = props.rel; @@ -4058,8 +4073,8 @@ if (__DEV__) { styleQueue.sheets.set(key, resource); - if (renderState.boundaryResources) { - renderState.boundaryResources.stylesheets.add(resource); + if (hoistableState) { + hoistableState.stylesheets.add(resource); } } else { // We need to track whether this boundary should wait on this resource or not. @@ -4071,8 +4086,8 @@ if (__DEV__) { var _resource = styleQueue.sheets.get(key); if (_resource) { - if (renderState.boundaryResources) { - renderState.boundaryResources.stylesheets.add(_resource); + if (hoistableState) { + hoistableState.stylesheets.add(_resource); } } } @@ -4099,16 +4114,14 @@ if (__DEV__) { target.push(textSeparator); } - switch (props.rel) { - case "preconnect": - case "dns-prefetch": - return pushLinkImpl(renderState.preconnectChunks, props); - - case "preload": - return pushLinkImpl(renderState.preloadChunks, props); - - default: - return pushLinkImpl(renderState.hoistableChunks, props); + if (isFallback) { + // Hoistable Elements for fallbacks are simply omitted. we don't want to emit them early + // because they are likely superceded by primary content and we want to avoid needing to clean + // them up when the primary content is ready. They are never hydrated on the client anyway because + // boundaries in fallback are awaited or client render, in either case there is never hydration + return null; + } else { + return pushLinkImpl(renderState.hoistableChunks, props); } } } @@ -4150,6 +4163,7 @@ if (__DEV__) { props, resumableState, renderState, + hoistableState, textEmbedded, insertionMode, noscriptTagInScope @@ -4253,8 +4267,8 @@ if (__DEV__) { // it. However, it's possible when you resume that the style has already been emitted // and then it wouldn't be recreated in the RenderState and there's no need to track // it again since we should've hoisted it to the shell already. - if (renderState.boundaryResources) { - renderState.boundaryResources.styles.add(styleQueue); + if (hoistableState) { + hoistableState.styles.add(styleQueue); } } @@ -4566,7 +4580,8 @@ if (__DEV__) { props, renderState, insertionMode, - noscriptTagInScope + noscriptTagInScope, + isFallback ) { { if (hasOwnProperty.call(props, "children")) { @@ -4622,8 +4637,15 @@ if (__DEV__) { !noscriptTagInScope && props.itemProp == null ) { - pushTitleImpl(renderState.hoistableChunks, props); - return null; + if (isFallback) { + // Hoistable Elements for fallbacks are simply omitted. we don't want to emit them early + // because they are likely superceded by primary content and we want to avoid needing to clean + // them up when the primary content is ready. They are never hydrated on the client anyway because + // boundaries in fallback are awaited or client render, in either case there is never hydration + return null; + } else { + pushTitleImpl(renderState.hoistableChunks, props); + } } else { return pushTitleImpl(target, props); } @@ -5083,8 +5105,10 @@ if (__DEV__) { props, resumableState, renderState, + hoistableState, formatContext, - textEmbedded + textEmbedded, + isFallback ) { { validateProperties$2(type, props); @@ -5159,7 +5183,8 @@ if (__DEV__) { props, renderState, formatContext.insertionMode, - !!(formatContext.tagScope & NOSCRIPT_SCOPE) + !!(formatContext.tagScope & NOSCRIPT_SCOPE), + isFallback ); case "link": @@ -5168,9 +5193,11 @@ if (__DEV__) { props, resumableState, renderState, + hoistableState, textEmbedded, formatContext.insertionMode, - !!(formatContext.tagScope & NOSCRIPT_SCOPE) + !!(formatContext.tagScope & NOSCRIPT_SCOPE), + isFallback ); case "script": @@ -5190,6 +5217,7 @@ if (__DEV__) { props, resumableState, renderState, + hoistableState, textEmbedded, formatContext.insertionMode, !!(formatContext.tagScope & NOSCRIPT_SCOPE) @@ -5202,7 +5230,8 @@ if (__DEV__) { renderState, textEmbedded, formatContext.insertionMode, - !!(formatContext.tagScope & NOSCRIPT_SCOPE) + !!(formatContext.tagScope & NOSCRIPT_SCOPE), + isFallback ); // Newline eating tags @@ -5711,7 +5740,7 @@ if (__DEV__) { resumableState, renderState, id, - boundaryResources + hoistableState ) { var requiresStyleInsertion; @@ -5792,12 +5821,12 @@ if (__DEV__) { // - data writer emits a string literal, which is escaped as html // e.g. ["A", "B"] if (scriptFormat) { - writeChunk(destination, completeBoundaryScript3a); // boundaryResources encodes an array literal + writeChunk(destination, completeBoundaryScript3a); // hoistableState encodes an array literal - writeStyleResourceDependenciesInJS(destination, boundaryResources); + writeStyleResourceDependenciesInJS(destination, hoistableState); } else { writeChunk(destination, completeBoundaryData3a); - writeStyleResourceDependenciesInAttr(destination, boundaryResources); + writeStyleResourceDependenciesInAttr(destination, hoistableState); } } else { if (scriptFormat) { @@ -6067,21 +6096,21 @@ if (__DEV__) { return false; } - function writeResourcesForBoundary( + function writeHoistablesForBoundary( destination, - boundaryResources, + hoistableState, renderState ) { // Reset these on each invocation, they are only safe to read in this function currentlyRenderingBoundaryHasStylesToHoist = false; destinationHasCapacity = true; // Flush style tags for each precedence this boundary depends on - boundaryResources.styles.forEach( - flushStyleTagsLateForBoundary, - destination - ); // Determine if this boundary has stylesheets that need to be awaited upon completion + hoistableState.styles.forEach(flushStyleTagsLateForBoundary, destination); // Determine if this boundary has stylesheets that need to be awaited upon completion - boundaryResources.stylesheets.forEach(hasStylesToHoist); + hoistableState.stylesheets.forEach(hasStylesToHoist); // We don't actually want to flush any hoistables until the boundary is complete so we omit + // any further writing here. This is becuase unlike Resources, Hoistable Elements act more like + // regular elements, each rendered element has a unique representation in the DOM. We don't want + // these elements to appear in the DOM early, before the boundary has actually completed if (currentlyRenderingBoundaryHasStylesToHoist) { renderState.stylesToHoist = true; @@ -6243,13 +6272,13 @@ if (__DEV__) { renderState.preconnects.forEach(flushResource, destination); renderState.preconnects.clear(); - var preconnectChunks = renderState.preconnectChunks; + var viewportChunks = renderState.viewportChunks; - for (i = 0; i < preconnectChunks.length; i++) { - writeChunk(destination, preconnectChunks[i]); + for (i = 0; i < viewportChunks.length; i++) { + writeChunk(destination, viewportChunks[i]); } - preconnectChunks.length = 0; + viewportChunks.length = 0; renderState.fontPreloads.forEach(flushResource, destination); renderState.fontPreloads.clear(); renderState.highImagePreloads.forEach(flushResource, destination); @@ -6267,15 +6296,7 @@ if (__DEV__) { renderState.scripts.forEach(flushResource, destination); renderState.scripts.clear(); renderState.bulkPreloads.forEach(flushResource, destination); - renderState.bulkPreloads.clear(); // Write embedding preloadChunks - - var preloadChunks = renderState.preloadChunks; - - for (i = 0; i < preloadChunks.length; i++) { - writeChunk(destination, preloadChunks[i]); - } - - preloadChunks.length = 0; // Write embedding hoistableChunks + renderState.bulkPreloads.clear(); // Write embedding hoistableChunks var hoistableChunks = renderState.hoistableChunks; @@ -6283,14 +6304,11 @@ if (__DEV__) { writeChunk(destination, hoistableChunks[i]); } - hoistableChunks.length = 0; // Flush closing head if necessary + hoistableChunks.length = 0; if (htmlChunks && headChunks === null) { - // We have an rendered but no rendered. We however inserted - // a up above so we need to emit the now. This is safe because - // if the main content contained the it would also have provided a - // . This means that all the content inside is either or - // invalid HTML + // we have an but we inserted an implicit tag. We need + // to close it since the main content won't have it writeChunk(destination, endChunkForTag("head")); } } // We don't bother reporting backpressure at the moment because we expect to @@ -6303,15 +6321,15 @@ if (__DEV__) { // We omit charsetChunks because we have already sent the shell and if it wasn't // already sent it is too late now. - renderState.preconnects.forEach(flushResource, destination); - renderState.preconnects.clear(); - var preconnectChunks = renderState.preconnectChunks; + var viewportChunks = renderState.viewportChunks; - for (i = 0; i < preconnectChunks.length; i++) { - writeChunk(destination, preconnectChunks[i]); + for (i = 0; i < viewportChunks.length; i++) { + writeChunk(destination, viewportChunks[i]); } - preconnectChunks.length = 0; + viewportChunks.length = 0; + renderState.preconnects.forEach(flushResource, destination); + renderState.preconnects.clear(); renderState.fontPreloads.forEach(flushResource, destination); renderState.fontPreloads.clear(); renderState.highImagePreloads.forEach(flushResource, destination); @@ -6328,15 +6346,7 @@ if (__DEV__) { renderState.scripts.forEach(flushResource, destination); renderState.scripts.clear(); renderState.bulkPreloads.forEach(flushResource, destination); - renderState.bulkPreloads.clear(); // Write embedding preloadChunks - - var preloadChunks = renderState.preloadChunks; - - for (i = 0; i < preloadChunks.length; i++) { - writeChunk(destination, preloadChunks[i]); - } - - preloadChunks.length = 0; // Write embedding hoistableChunks + renderState.bulkPreloads.clear(); // Write embedding hoistableChunks var hoistableChunks = renderState.hoistableChunks; @@ -6362,13 +6372,10 @@ if (__DEV__) { // E.g. // [["JS_escaped_string1", "JS_escaped_string2"]] - function writeStyleResourceDependenciesInJS( - destination, - boundaryResources - ) { + function writeStyleResourceDependenciesInJS(destination, hoistableState) { writeChunk(destination, arrayFirstOpenBracket); var nextArrayOpenBrackChunk = arrayFirstOpenBracket; - boundaryResources.stylesheets.forEach(function (resource) { + hoistableState.stylesheets.forEach(function (resource) { if (resource.state === PREAMBLE); else if (resource.state === LATE) { // We only need to emit the href because this resource flushed in an earlier @@ -6565,13 +6572,10 @@ if (__DEV__) { // E.g. // [["JSON_escaped_string1", "JSON_escaped_string2"]] - function writeStyleResourceDependenciesInAttr( - destination, - boundaryResources - ) { + function writeStyleResourceDependenciesInAttr(destination, hoistableState) { writeChunk(destination, arrayFirstOpenBracket); var nextArrayOpenBrackChunk = arrayFirstOpenBracket; - boundaryResources.stylesheets.forEach(function (resource) { + hoistableState.stylesheets.forEach(function (resource) { if (resource.state === PREAMBLE); else if (resource.state === LATE) { // We only need to emit the href because this resource flushed in an earlier @@ -6776,18 +6780,12 @@ if (__DEV__) { var PRELOADED = 1; var PREAMBLE = 2; var LATE = 3; - function createBoundaryResources() { + function createHoistableState() { return { styles: new Set(), stylesheets: new Set() }; } - function setCurrentlyRenderingBoundaryResourcesTarget( - renderState, - boundaryResources - ) { - renderState.boundaryResources = boundaryResources; - } function getResourceKey(href) { return href; @@ -7677,19 +7675,9 @@ if (__DEV__) { this.stylesheets.add(stylesheet); } - function hoistResources(renderState, source) { - var currentBoundaryResources = renderState.boundaryResources; - - if (currentBoundaryResources) { - source.styles.forEach( - hoistStyleQueueDependency, - currentBoundaryResources - ); - source.stylesheets.forEach( - hoistStylesheetDependency, - currentBoundaryResources - ); - } + function hoistHoistables(parentState, childState) { + childState.styles.forEach(hoistStyleQueueDependency, parentState); + childState.stylesheets.forEach(hoistStylesheetDependency, parentState); } // This function is called at various times depending on whether we are rendering // or prerendering. In this implementation we only actually emit headers once and // subsequent calls are ignored. We track whether the request has a completed shell @@ -7815,13 +7803,12 @@ if (__DEV__) { headChunks: renderState.headChunks, externalRuntimeScript: renderState.externalRuntimeScript, bootstrapChunks: renderState.bootstrapChunks, + importMapChunks: renderState.importMapChunks, onHeaders: renderState.onHeaders, headers: renderState.headers, resets: renderState.resets, charsetChunks: renderState.charsetChunks, - preconnectChunks: renderState.preconnectChunks, - importMapChunks: renderState.importMapChunks, - preloadChunks: renderState.preloadChunks, + viewportChunks: renderState.viewportChunks, hoistableChunks: renderState.hoistableChunks, preconnects: renderState.preconnects, fontPreloads: renderState.fontPreloads, @@ -7832,7 +7819,6 @@ if (__DEV__) { scripts: renderState.scripts, bulkPreloads: renderState.bulkPreloads, preloads: renderState.preloads, - boundaryResources: renderState.boundaryResources, stylesToHoist: renderState.stylesToHoist, // This is an extra field for the legacy renderer generateStaticMarkup: generateStaticMarkup @@ -10574,13 +10560,15 @@ if (__DEV__) { -1, null, rootSegment, + null, abortSet, null, rootFormatContext, emptyContextObject, rootContextSnapshot, emptyTreeContext, - null + null, + false ); pingedTasks.push(rootTask); return request; @@ -10614,7 +10602,8 @@ if (__DEV__) { byteSize: 0, fallbackAbortableTasks: fallbackAbortableTasks, errorDigest: null, - resources: createBoundaryResources(), + contentState: createHoistableState(), + fallbackState: createHoistableState(), trackedContentKeyPath: null, trackedFallbackNode: null }; @@ -10627,13 +10616,15 @@ if (__DEV__) { childIndex, blockedBoundary, blockedSegment, + hoistableState, abortSet, keyPath, formatContext, legacyContext, context, treeContext, - componentStack + componentStack, + isFallback ) { request.allPendingTasks++; @@ -10652,6 +10643,7 @@ if (__DEV__) { }, blockedBoundary: blockedBoundary, blockedSegment: blockedSegment, + hoistableState: hoistableState, abortSet: abortSet, keyPath: keyPath, formatContext: formatContext, @@ -10659,7 +10651,8 @@ if (__DEV__) { context: context, treeContext: treeContext, componentStack: componentStack, - thenableState: thenableState + thenableState: thenableState, + isFallback: isFallback }; abortSet.add(task); return task; @@ -10672,13 +10665,15 @@ if (__DEV__) { node, childIndex, blockedBoundary, + hoistableState, abortSet, keyPath, formatContext, legacyContext, context, treeContext, - componentStack + componentStack, + isFallback ) { request.allPendingTasks++; @@ -10698,6 +10693,7 @@ if (__DEV__) { }, blockedBoundary: blockedBoundary, blockedSegment: null, + hoistableState: hoistableState, abortSet: abortSet, keyPath: keyPath, formatContext: formatContext, @@ -10705,7 +10701,8 @@ if (__DEV__) { context: context, treeContext: treeContext, componentStack: componentStack, - thenableState: thenableState + thenableState: thenableState, + isFallback: isFallback }; abortSet.add(task); return task; @@ -10879,6 +10876,7 @@ if (__DEV__) { createBuiltInComponentStack(task, "Suspense")); var prevKeyPath = task.keyPath; var parentBoundary = task.blockedBoundary; + var parentHoistableState = task.hoistableState; var parentSegment = task.blockedSegment; // Each time we enter a suspense boundary, we split out into a new segment for // the fallback so that we can later replace that segment with the content. // This also lets us split out the main content even if it doesn't suspend, @@ -10926,15 +10924,8 @@ if (__DEV__) { // we're writing to. If something suspends, it'll spawn new suspended task with that context. task.blockedBoundary = newBoundary; + task.hoistableState = newBoundary.contentState; task.blockedSegment = contentRootSegment; - - { - setCurrentlyRenderingBoundaryResourcesTarget( - request.renderState, - newBoundary.resources - ); - } - task.keyPath = keyPath; try { @@ -10973,14 +10964,8 @@ if (__DEV__) { // We don't need to schedule any task because we know the parent has written yet. // We do need to fallthrough to create the fallback though. } finally { - { - setCurrentlyRenderingBoundaryResourcesTarget( - request.renderState, - parentBoundary ? parentBoundary.resources : null - ); - } - task.blockedBoundary = parentBoundary; + task.hoistableState = parentHoistableState; task.blockedSegment = parentSegment; task.keyPath = prevKeyPath; task.componentStack = previousComponentStack; @@ -11018,6 +11003,7 @@ if (__DEV__) { -1, parentBoundary, boundarySegment, + newBoundary.fallbackState, fallbackAbortSet, fallbackKeyPath, task.formatContext, @@ -11025,7 +11011,8 @@ if (__DEV__) { task.context, task.treeContext, // This stack should be the Suspense boundary stack because while the fallback is actually a child segment // of the parent boundary from a component standpoint the fallback is a child of the Suspense boundary itself - suspenseComponentStack + suspenseComponentStack, + true ); // TODO: This should be queued at a separate lower priority queue so that we only work // on preparing fallbacks if we don't have any more main content to task on. @@ -11051,6 +11038,7 @@ if (__DEV__) { var prevKeyPath = task.keyPath; var previousReplaySet = task.replay; var parentBoundary = task.blockedBoundary; + var parentHoistableState = task.hoistableState; var content = props.children; var fallback = props.fallback; var fallbackAbortSet = new Set(); @@ -11062,19 +11050,13 @@ if (__DEV__) { // we're writing to. If something suspends, it'll spawn new suspended task with that context. task.blockedBoundary = resumedBoundary; + task.hoistableState = resumedBoundary.contentState; task.replay = { nodes: childNodes, slots: childSlots, pendingTasks: 1 }; - { - setCurrentlyRenderingBoundaryResourcesTarget( - request.renderState, - resumedBoundary.resources - ); - } - try { // We use the safe form because we don't handle suspending here. Only error handling. renderNode(request, task, content, -1); @@ -11118,14 +11100,8 @@ if (__DEV__) { // We don't need to schedule any task because we know the parent has written yet. // We do need to fallthrough to create the fallback though. } finally { - { - setCurrentlyRenderingBoundaryResourcesTarget( - request.renderState, - parentBoundary ? parentBoundary.resources : null - ); - } - task.blockedBoundary = parentBoundary; + task.hoistableState = parentHoistableState; task.replay = previousReplaySet; task.keyPath = prevKeyPath; task.componentStack = previousComponentStack; @@ -11146,6 +11122,7 @@ if (__DEV__) { fallback, -1, parentBoundary, + resumedBoundary.fallbackState, fallbackAbortSet, fallbackKeyPath, task.formatContext, @@ -11153,7 +11130,8 @@ if (__DEV__) { task.context, task.treeContext, // This stack should be the Suspense boundary stack because while the fallback is actually a child segment // of the parent boundary from a component standpoint the fallback is a child of the Suspense boundary itself - suspenseComponentStack + suspenseComponentStack, + true ); // TODO: This should be queued at a separate lower priority queue so that we only work // on preparing fallbacks if we don't have any more main content to task on. @@ -11188,8 +11166,10 @@ if (__DEV__) { props, request.resumableState, request.renderState, + task.hoistableState, task.formatContext, - segment.lastPushedText + segment.lastPushedText, + task.isFallback ); segment.lastPushedText = false; @@ -12385,6 +12365,7 @@ if (__DEV__) { task.node, task.childIndex, task.blockedBoundary, + task.hoistableState, task.abortSet, task.keyPath, task.formatContext, @@ -12392,7 +12373,8 @@ if (__DEV__) { task.context, task.treeContext, // We pop one task off the stack because the node that suspended will be tried again, // which will add it back onto the stack. - task.componentStack !== null ? task.componentStack.parent : null + task.componentStack !== null ? task.componentStack.parent : null, + task.isFallback ); var ping = newTask.ping; x.then(ping, ping); @@ -12420,6 +12402,7 @@ if (__DEV__) { task.childIndex, task.blockedBoundary, newSegment, + task.hoistableState, task.abortSet, task.keyPath, task.formatContext, @@ -12427,7 +12410,8 @@ if (__DEV__) { task.context, task.treeContext, // We pop one task off the stack because the node that suspended will be tried again, // which will add it back onto the stack. - task.componentStack !== null ? task.componentStack.parent : null + task.componentStack !== null ? task.componentStack.parent : null, + task.isFallback ); var ping = newTask.ping; x.then(ping, ping); @@ -12982,14 +12966,6 @@ if (__DEV__) { } function retryTask(request, task) { - { - var blockedBoundary = task.blockedBoundary; - setCurrentlyRenderingBoundaryResourcesTarget( - request.renderState, - blockedBoundary ? blockedBoundary.resources : null - ); - } - var segment = task.blockedSegment; if (segment === null) { @@ -13069,13 +13045,6 @@ if (__DEV__) { erroredTask(request, task.blockedBoundary, x, errorInfo); return; } finally { - { - setCurrentlyRenderingBoundaryResourcesTarget( - request.renderState, - null - ); - } - { currentTaskInDEV = prevTaskInDEV; } @@ -13160,13 +13129,6 @@ if (__DEV__) { return; } finally { - { - setCurrentlyRenderingBoundaryResourcesTarget( - request.renderState, - null - ); - } - { currentTaskInDEV = prevTaskInDEV; } @@ -13245,7 +13207,18 @@ if (__DEV__) { } } - function flushSubtree(request, destination, segment) { + function flushPreamble(request, destination, rootSegment) { + var willFlushAllSegments = + request.allPendingTasks === 0 && request.trackedPostpones === null; + writePreamble( + destination, + request.resumableState, + request.renderState, + willFlushAllSegments + ); + } + + function flushSubtree(request, destination, segment, hoistableState) { segment.parentFlushed = true; switch (segment.status) { @@ -13277,7 +13250,7 @@ if (__DEV__) { writeChunk(destination, chunks[chunkIdx]); } - r = flushSegment(request, destination, nextChild); + r = flushSegment(request, destination, nextChild, hoistableState); } // Finally just write all the remaining chunks for (; chunkIdx < chunks.length - 1; chunkIdx++) { @@ -13299,12 +13272,12 @@ if (__DEV__) { } } - function flushSegment(request, destination, segment) { + function flushSegment(request, destination, segment, hoistableState) { var boundary = segment.boundary; if (boundary === null) { // Not a suspense boundary. - return flushSubtree(request, destination, segment); + return flushSubtree(request, destination, segment, hoistableState); } boundary.parentFlushed = true; // This segment is a Suspense boundary. We need to decide whether to @@ -13321,7 +13294,7 @@ if (__DEV__) { boundary.errorComponentStack ); // Flush the fallback. - flushSubtree(request, destination, segment); + flushSubtree(request, destination, segment, hoistableState); return writeEndClientRenderedSuspenseBoundary( destination, request.renderState @@ -13339,9 +13312,16 @@ if (__DEV__) { } // This boundary is still loading. Emit a pending suspense boundary wrapper. var id = boundary.rootSegmentID; - writeStartPendingSuspenseBoundary(destination, request.renderState, id); // Flush the fallback. + writeStartPendingSuspenseBoundary(destination, request.renderState, id); // We are going to flush the fallback so we need to hoist the fallback + // state to the parent boundary - flushSubtree(request, destination, segment); + { + if (hoistableState) { + hoistHoistables(hoistableState, boundary.fallbackState); + } + } // Flush the fallback. + + flushSubtree(request, destination, segment, hoistableState); return writeEndPendingSuspenseBoundary(destination); } else if (boundary.byteSize > request.progressiveChunkSize) { // This boundary is large and will be emitted separately so that we can progressively show @@ -13357,13 +13337,19 @@ if (__DEV__) { destination, request.renderState, boundary.rootSegmentID - ); // Flush the fallback. + ); // While we are going to flush the fallback we are going to follow it up with + // the completed boundary immediately so we make the choice to omit fallback + // boundary state from the parent since it will be replaced when the boundary + // flushes later in this pass or in a future flush + // Flush the fallback. - flushSubtree(request, destination, segment); + flushSubtree(request, destination, segment, hoistableState); return writeEndPendingSuspenseBoundary(destination); } else { { - hoistResources(request.renderState, boundary.resources); + if (hoistableState) { + hoistHoistables(hoistableState, boundary.contentState); + } } // We can inline this boundary's content as a complete boundary. writeStartCompletedSuspenseBoundary(destination, request.renderState); @@ -13376,7 +13362,7 @@ if (__DEV__) { } var contentSegment = completedSegments[0]; - flushSegment(request, destination, contentSegment); + flushSegment(request, destination, contentSegment, hoistableState); return writeEndCompletedSuspenseBoundary( destination, request.renderState @@ -13396,25 +13382,23 @@ if (__DEV__) { ); } - function flushSegmentContainer(request, destination, segment) { + function flushSegmentContainer( + request, + destination, + segment, + hoistableState + ) { writeStartSegment( destination, request.renderState, segment.parentFormatContext, segment.id ); - flushSegment(request, destination, segment); + flushSegment(request, destination, segment, hoistableState); return writeEndSegment(destination, segment.parentFormatContext); } function flushCompletedBoundary(request, destination, boundary) { - { - setCurrentlyRenderingBoundaryResourcesTarget( - request.renderState, - boundary.resources - ); - } - var completedSegments = boundary.completedSegments; var i = 0; @@ -13426,9 +13410,9 @@ if (__DEV__) { completedSegments.length = 0; { - writeResourcesForBoundary( + writeHoistablesForBoundary( destination, - boundary.resources, + boundary.contentState, request.renderState ); } @@ -13438,18 +13422,11 @@ if (__DEV__) { request.resumableState, request.renderState, boundary.rootSegmentID, - boundary.resources + boundary.contentState ); } function flushPartialBoundary(request, destination, boundary) { - { - setCurrentlyRenderingBoundaryResourcesTarget( - request.renderState, - boundary.resources - ); - } - var completedSegments = boundary.completedSegments; var i = 0; @@ -13475,13 +13452,9 @@ if (__DEV__) { completedSegments.splice(0, i); { - // The way this is structured we only write resources for partial boundaries - // if there is no backpressure. Later before we complete the boundary we - // will write resources regardless of backpressure before we emit the - // completion instruction - return writeResourcesForBoundary( + return writeHoistablesForBoundary( destination, - boundary.resources, + boundary.contentState, request.renderState ); } @@ -13498,6 +13471,7 @@ if (__DEV__) { return true; } + var hoistableState = boundary.contentState; var segmentID = segment.id; if (segmentID === -1) { @@ -13511,13 +13485,23 @@ if (__DEV__) { ); } - return flushSegmentContainer(request, destination, segment); + return flushSegmentContainer( + request, + destination, + segment, + hoistableState + ); } else if (segmentID === boundary.rootSegmentID) { // When we emit postponed boundaries, we might have assigned the ID already // but it's still the root segment so we can't inject it into the parent yet. - return flushSegmentContainer(request, destination, segment); + return flushSegmentContainer( + request, + destination, + segment, + hoistableState + ); } else { - flushSegmentContainer(request, destination, segment); + flushSegmentContainer(request, destination, segment, hoistableState); return writeCompletedSegmentInstruction( destination, request.resumableState, @@ -13542,16 +13526,10 @@ if (__DEV__) { return; } else if (request.pendingRootTasks === 0) { if (enableFloat) { - writePreamble( - destination, - request.resumableState, - request.renderState, - request.allPendingTasks === 0 && - request.trackedPostpones === null - ); + flushPreamble(request, destination, completedRootSegment); } - flushSegment(request, destination, completedRootSegment); + flushSegment(request, destination, completedRootSegment, null); request.completedRootSegment = null; writeCompletedRoot(destination, request.renderState); } else { diff --git a/compiled/facebook-www/ReactDOMServer-prod.classic.js b/compiled/facebook-www/ReactDOMServer-prod.classic.js index 79028d5862..07232e7695 100644 --- a/compiled/facebook-www/ReactDOMServer-prod.classic.js +++ b/compiled/facebook-www/ReactDOMServer-prod.classic.js @@ -613,85 +613,6 @@ function flattenOptionChildren(children) { }); return content; } -function pushLink( - target, - props, - resumableState, - renderState, - textEmbedded, - insertionMode, - noscriptTagInScope -) { - var rel = props.rel, - href = props.href, - precedence = props.precedence; - if ( - 3 === insertionMode || - noscriptTagInScope || - null != props.itemProp || - "string" !== typeof rel || - "string" !== typeof href || - "" === href - ) - return pushLinkImpl(target, props), null; - if ("stylesheet" === props.rel) { - if ( - "string" !== typeof precedence || - null != props.disabled || - props.onLoad || - props.onError - ) - return pushLinkImpl(target, props); - insertionMode = renderState.styles.get(precedence); - noscriptTagInScope = resumableState.styleResources.hasOwnProperty(href) - ? resumableState.styleResources[href] - : void 0; - null !== noscriptTagInScope - ? ((resumableState.styleResources[href] = null), - insertionMode || - ((insertionMode = { - precedence: escapeTextForBrowser(precedence), - rules: [], - hrefs: [], - sheets: new Map() - }), - renderState.styles.set(precedence, insertionMode)), - (props = { - state: 0, - props: assign({}, props, { - "data-precedence": props.precedence, - precedence: null - }) - }), - noscriptTagInScope && - (2 === noscriptTagInScope.length && - adoptPreloadCredentials(props.props, noscriptTagInScope), - (resumableState = renderState.preloads.stylesheets.get(href)) && - 0 < resumableState.length - ? (resumableState.length = 0) - : (props.state = 1)), - insertionMode.sheets.set(href, props), - renderState.boundaryResources && - renderState.boundaryResources.stylesheets.add(props)) - : insertionMode && - (href = insertionMode.sheets.get(href)) && - renderState.boundaryResources && - renderState.boundaryResources.stylesheets.add(href); - textEmbedded && target.push("\x3c!-- --\x3e"); - return null; - } - if (props.onLoad || props.onError) return pushLinkImpl(target, props); - textEmbedded && target.push("\x3c!-- --\x3e"); - switch (props.rel) { - case "preconnect": - case "dns-prefetch": - return pushLinkImpl(renderState.preconnectChunks, props); - case "preload": - return pushLinkImpl(renderState.preloadChunks, props); - default: - return pushLinkImpl(renderState.hoistableChunks, props); - } -} function pushLinkImpl(target, props) { target.push(startChunkForTag("link")); for (var propKey in props) @@ -830,8 +751,10 @@ function pushStartInstance( props, resumableState, renderState, + hoistableState, formatContext, - textEmbedded + textEmbedded, + isFallback ) { switch (type) { case "div": @@ -1195,19 +1118,88 @@ function pushStartInstance( props ); else - pushTitleImpl(renderState.hoistableChunks, props), - (JSCompiler_inline_result$jscomp$1 = null); + isFallback + ? (JSCompiler_inline_result$jscomp$1 = null) + : (pushTitleImpl(renderState.hoistableChunks, props), + (JSCompiler_inline_result$jscomp$1 = void 0)); return JSCompiler_inline_result$jscomp$1; case "link": - return pushLink( - target$jscomp$0, - props, - resumableState, - renderState, - textEmbedded, - formatContext.insertionMode, - !!(formatContext.tagScope & 1) - ); + var rel = props.rel, + href = props.href, + precedence = props.precedence; + if ( + 3 === formatContext.insertionMode || + formatContext.tagScope & 1 || + null != props.itemProp || + "string" !== typeof rel || + "string" !== typeof href || + "" === href + ) { + pushLinkImpl(target$jscomp$0, props); + var JSCompiler_inline_result$jscomp$2 = null; + } else if ("stylesheet" === props.rel) + if ( + "string" !== typeof precedence || + null != props.disabled || + props.onLoad || + props.onError + ) + JSCompiler_inline_result$jscomp$2 = pushLinkImpl( + target$jscomp$0, + props + ); + else { + var styleQueue = renderState.styles.get(precedence), + resourceState = resumableState.styleResources.hasOwnProperty(href) + ? resumableState.styleResources[href] + : void 0; + if (null !== resourceState) { + resumableState.styleResources[href] = null; + styleQueue || + ((styleQueue = { + precedence: escapeTextForBrowser(precedence), + rules: [], + hrefs: [], + sheets: new Map() + }), + renderState.styles.set(precedence, styleQueue)); + var resource = { + state: 0, + props: assign({}, props, { + "data-precedence": props.precedence, + precedence: null + }) + }; + if (resourceState) { + 2 === resourceState.length && + adoptPreloadCredentials(resource.props, resourceState); + var preloadResource = renderState.preloads.stylesheets.get(href); + preloadResource && 0 < preloadResource.length + ? (preloadResource.length = 0) + : (resource.state = 1); + } + styleQueue.sheets.set(href, resource); + hoistableState && hoistableState.stylesheets.add(resource); + } else if (styleQueue) { + var resource$8 = styleQueue.sheets.get(href); + resource$8 && + hoistableState && + hoistableState.stylesheets.add(resource$8); + } + textEmbedded && target$jscomp$0.push("\x3c!-- --\x3e"); + JSCompiler_inline_result$jscomp$2 = null; + } + else + props.onLoad || props.onError + ? (JSCompiler_inline_result$jscomp$2 = pushLinkImpl( + target$jscomp$0, + props + )) + : (textEmbedded && target$jscomp$0.push("\x3c!-- --\x3e"), + (JSCompiler_inline_result$jscomp$2 = isFallback + ? null + : pushLinkImpl(renderState.hoistableChunks, props))); + return JSCompiler_inline_result$jscomp$2; case "script": var asyncProp = props.async; if ( @@ -1222,7 +1214,7 @@ function pushStartInstance( formatContext.tagScope & 1 || null != props.itemProp ) - var JSCompiler_inline_result$jscomp$2 = pushScriptImpl( + var JSCompiler_inline_result$jscomp$3 = pushScriptImpl( target$jscomp$0, props ); @@ -1234,37 +1226,37 @@ function pushStartInstance( } else (resources = resumableState.scriptResources), (preloads = renderState.preloads.scripts); - var resourceState = resources.hasOwnProperty(key) + var resourceState$jscomp$0 = resources.hasOwnProperty(key) ? resources[key] : void 0; - if (null !== resourceState) { + if (null !== resourceState$jscomp$0) { resources[key] = null; var scriptProps = props; - if (resourceState) { - 2 === resourceState.length && + if (resourceState$jscomp$0) { + 2 === resourceState$jscomp$0.length && ((scriptProps = assign({}, props)), - adoptPreloadCredentials(scriptProps, resourceState)); - var preloadResource = preloads.get(key); - preloadResource && (preloadResource.length = 0); + adoptPreloadCredentials(scriptProps, resourceState$jscomp$0)); + var preloadResource$jscomp$0 = preloads.get(key); + preloadResource$jscomp$0 && (preloadResource$jscomp$0.length = 0); } - var resource = []; - renderState.scripts.add(resource); - pushScriptImpl(resource, scriptProps); + var resource$jscomp$0 = []; + renderState.scripts.add(resource$jscomp$0); + pushScriptImpl(resource$jscomp$0, scriptProps); } textEmbedded && target$jscomp$0.push("\x3c!-- --\x3e"); - JSCompiler_inline_result$jscomp$2 = null; + JSCompiler_inline_result$jscomp$3 = null; } - return JSCompiler_inline_result$jscomp$2; + return JSCompiler_inline_result$jscomp$3; case "style": - var precedence = props.precedence, - href = props.href; + var precedence$jscomp$0 = props.precedence, + href$jscomp$0 = props.href; if ( 3 === formatContext.insertionMode || formatContext.tagScope & 1 || null != props.itemProp || - "string" !== typeof precedence || - "string" !== typeof href || - "" === href + "string" !== typeof precedence$jscomp$0 || + "string" !== typeof href$jscomp$0 || + "" === href$jscomp$0 ) { target$jscomp$0.push(startChunkForTag("style")); var children$jscomp$4 = null, @@ -1302,26 +1294,28 @@ function pushStartInstance( target$jscomp$0.push(escapeTextForBrowser("" + child)); pushInnerHTML(target$jscomp$0, innerHTML$jscomp$3, children$jscomp$4); target$jscomp$0.push(endChunkForTag("style")); - var JSCompiler_inline_result$jscomp$3 = null; + var JSCompiler_inline_result$jscomp$4 = null; } else { - var styleQueue = renderState.styles.get(precedence); + var styleQueue$jscomp$0 = renderState.styles.get(precedence$jscomp$0); if ( null !== - (resumableState.styleResources.hasOwnProperty(href) - ? resumableState.styleResources[href] + (resumableState.styleResources.hasOwnProperty(href$jscomp$0) + ? resumableState.styleResources[href$jscomp$0] : void 0) ) { - resumableState.styleResources[href] = null; - styleQueue - ? styleQueue.hrefs.push(escapeTextForBrowser(href)) - : ((styleQueue = { - precedence: escapeTextForBrowser(precedence), + resumableState.styleResources[href$jscomp$0] = null; + styleQueue$jscomp$0 + ? styleQueue$jscomp$0.hrefs.push( + escapeTextForBrowser(href$jscomp$0) + ) + : ((styleQueue$jscomp$0 = { + precedence: escapeTextForBrowser(precedence$jscomp$0), rules: [], - hrefs: [escapeTextForBrowser(href)], + hrefs: [escapeTextForBrowser(href$jscomp$0)], sheets: new Map() }), - renderState.styles.set(precedence, styleQueue)); - var target = styleQueue.rules, + renderState.styles.set(precedence$jscomp$0, styleQueue$jscomp$0)); + var target = styleQueue$jscomp$0.rules, children$jscomp$5 = null, innerHTML$jscomp$4 = null, propKey$jscomp$7; @@ -1349,33 +1343,34 @@ function pushStartInstance( target.push(escapeTextForBrowser("" + child$jscomp$0)); pushInnerHTML(target, innerHTML$jscomp$4, children$jscomp$5); } - styleQueue && - renderState.boundaryResources && - renderState.boundaryResources.styles.add(styleQueue); + styleQueue$jscomp$0 && + hoistableState && + hoistableState.styles.add(styleQueue$jscomp$0); textEmbedded && target$jscomp$0.push("\x3c!-- --\x3e"); - JSCompiler_inline_result$jscomp$3 = void 0; + JSCompiler_inline_result$jscomp$4 = void 0; } - return JSCompiler_inline_result$jscomp$3; + return JSCompiler_inline_result$jscomp$4; case "meta": if ( 3 === formatContext.insertionMode || formatContext.tagScope & 1 || null != props.itemProp ) - var JSCompiler_inline_result$jscomp$4 = pushSelfClosing( + var JSCompiler_inline_result$jscomp$5 = pushSelfClosing( target$jscomp$0, props, "meta" ); else textEmbedded && target$jscomp$0.push("\x3c!-- --\x3e"), - (JSCompiler_inline_result$jscomp$4 = - "string" === typeof props.charSet - ? pushSelfClosing(renderState.charsetChunks, props, "meta") - : "viewport" === props.name - ? pushSelfClosing(renderState.preconnectChunks, props, "meta") - : pushSelfClosing(renderState.hoistableChunks, props, "meta")); - return JSCompiler_inline_result$jscomp$4; + (JSCompiler_inline_result$jscomp$5 = isFallback + ? null + : "string" === typeof props.charSet + ? pushSelfClosing(renderState.charsetChunks, props, "meta") + : "viewport" === props.name + ? pushSelfClosing(renderState.viewportChunks, props, "meta") + : pushSelfClosing(renderState.hoistableChunks, props, "meta")); + return JSCompiler_inline_result$jscomp$5; case "listing": case "pre": target$jscomp$0.push(startChunkForTag(type)); @@ -1448,20 +1443,20 @@ function pushStartInstance( var sizes = "string" === typeof props.sizes ? props.sizes : void 0, key$jscomp$0 = srcSet ? srcSet + "\n" + (sizes || "") : src, promotablePreloads = renderState.preloads.images, - resource$jscomp$0 = promotablePreloads.get(key$jscomp$0); - if (resource$jscomp$0) { + resource$jscomp$1 = promotablePreloads.get(key$jscomp$0); + if (resource$jscomp$1) { if ( "high" === props.fetchPriority || 10 > renderState.highImagePreloads.size ) promotablePreloads.delete(key$jscomp$0), - renderState.highImagePreloads.add(resource$jscomp$0); + renderState.highImagePreloads.add(resource$jscomp$1); } else if ( !resumableState.imageResources.hasOwnProperty(key$jscomp$0) ) { resumableState.imageResources[key$jscomp$0] = PRELOAD_NO_CREDS; var input = props.crossOrigin; - var JSCompiler_inline_result$jscomp$5 = + var JSCompiler_inline_result$jscomp$6 = "string" === typeof input ? "use-credentials" === input ? input @@ -1476,7 +1471,7 @@ function pushStartInstance( ((header = getPreloadAsHeader(src, "image", { imageSrcSet: props.srcSet, imageSizes: props.sizes, - crossOrigin: JSCompiler_inline_result$jscomp$5, + crossOrigin: JSCompiler_inline_result$jscomp$6, integrity: props.integrity, nonce: props.nonce, type: props.type, @@ -1487,14 +1482,14 @@ function pushStartInstance( ? ((renderState.resets.image[key$jscomp$0] = PRELOAD_NO_CREDS), headers.highImagePreloads && (headers.highImagePreloads += ", "), (headers.highImagePreloads += header)) - : ((resource$jscomp$0 = []), - pushLinkImpl(resource$jscomp$0, { + : ((resource$jscomp$1 = []), + pushLinkImpl(resource$jscomp$1, { rel: "preload", as: "image", href: srcSet ? void 0 : src, imageSrcSet: srcSet, imageSizes: sizes, - crossOrigin: JSCompiler_inline_result$jscomp$5, + crossOrigin: JSCompiler_inline_result$jscomp$6, integrity: props.integrity, type: props.type, fetchPriority: props.fetchPriority, @@ -1502,9 +1497,9 @@ function pushStartInstance( }), "high" === props.fetchPriority || 10 > renderState.highImagePreloads.size - ? renderState.highImagePreloads.add(resource$jscomp$0) - : (renderState.bulkPreloads.add(resource$jscomp$0), - promotablePreloads.set(key$jscomp$0, resource$jscomp$0))); + ? renderState.highImagePreloads.add(resource$jscomp$1) + : (renderState.bulkPreloads.add(resource$jscomp$1), + promotablePreloads.set(key$jscomp$0, resource$jscomp$1))); } } return pushSelfClosing(target$jscomp$0, props, "img"); @@ -1532,36 +1527,36 @@ function pushStartInstance( case "head": if (2 > formatContext.insertionMode && null === renderState.headChunks) { renderState.headChunks = []; - var JSCompiler_inline_result$jscomp$6 = pushStartGenericElement( + var JSCompiler_inline_result$jscomp$7 = pushStartGenericElement( renderState.headChunks, props, "head" ); } else - JSCompiler_inline_result$jscomp$6 = pushStartGenericElement( + JSCompiler_inline_result$jscomp$7 = pushStartGenericElement( target$jscomp$0, props, "head" ); - return JSCompiler_inline_result$jscomp$6; + return JSCompiler_inline_result$jscomp$7; case "html": if ( 0 === formatContext.insertionMode && null === renderState.htmlChunks ) { renderState.htmlChunks = [""]; - var JSCompiler_inline_result$jscomp$7 = pushStartGenericElement( + var JSCompiler_inline_result$jscomp$8 = pushStartGenericElement( renderState.htmlChunks, props, "html" ); } else - JSCompiler_inline_result$jscomp$7 = pushStartGenericElement( + JSCompiler_inline_result$jscomp$8 = pushStartGenericElement( target$jscomp$0, props, "html" ); - return JSCompiler_inline_result$jscomp$7; + return JSCompiler_inline_result$jscomp$8; default: if (-1 !== type.indexOf("-")) { target$jscomp$0.push(startChunkForTag(type)); @@ -1795,15 +1790,11 @@ function hasStylesToHoist(stylesheet) { ? (currentlyRenderingBoundaryHasStylesToHoist = !0) : !1; } -function writeResourcesForBoundary( - destination, - boundaryResources, - renderState -) { +function writeHoistablesForBoundary(destination, hoistableState, renderState) { currentlyRenderingBoundaryHasStylesToHoist = !1; destinationHasCapacity = !0; - boundaryResources.styles.forEach(flushStyleTagsLateForBoundary, destination); - boundaryResources.stylesheets.forEach(hasStylesToHoist); + hoistableState.styles.forEach(flushStyleTagsLateForBoundary, destination); + hoistableState.stylesheets.forEach(hasStylesToHoist); currentlyRenderingBoundaryHasStylesToHoist && (renderState.stylesToHoist = !0); return destinationHasCapacity; @@ -1875,10 +1866,10 @@ function preloadLateStyles(styleQueue) { styleQueue.sheets.forEach(preloadLateStyle, this); styleQueue.sheets.clear(); } -function writeStyleResourceDependenciesInJS(destination, boundaryResources) { +function writeStyleResourceDependenciesInJS(destination, hoistableState) { destination.push("["); var nextArrayOpenBrackChunk = "["; - boundaryResources.stylesheets.forEach(function (resource) { + hoistableState.stylesheets.forEach(function (resource) { if (2 !== resource.state) if (3 === resource.state) destination.push(nextArrayOpenBrackChunk), @@ -1971,10 +1962,10 @@ function writeStyleResourceAttributeInJS(destination, name, value) { attributeName = escapeJSObjectForInstructionScripts(name); destination.push(attributeName); } -function writeStyleResourceDependenciesInAttr(destination, boundaryResources) { +function writeStyleResourceDependenciesInAttr(destination, hoistableState) { destination.push("["); var nextArrayOpenBrackChunk = "["; - boundaryResources.stylesheets.forEach(function (resource) { + hoistableState.stylesheets.forEach(function (resource) { if (2 !== resource.state) if (3 === resource.state) destination.push(nextArrayOpenBrackChunk), @@ -2067,6 +2058,9 @@ function writeStyleResourceAttributeInAttr(destination, name, value) { attributeName = escapeTextForBrowser(JSON.stringify(name)); destination.push(attributeName); } +function createHoistableState() { + return { styles: new Set(), stylesheets: new Set() }; +} function prefetchDNS(href) { var request = currentRequest ? currentRequest : null; if (request) { @@ -2482,16 +2476,16 @@ function createRenderState(resumableState, generateStaticMarkup) { "\x3c/script>" ); bootstrapScriptContent = idPrefix + "P:"; - var JSCompiler_object_inline_segmentPrefix_1645 = idPrefix + "S:"; + var JSCompiler_object_inline_segmentPrefix_1594 = idPrefix + "S:"; idPrefix += "B:"; - var JSCompiler_object_inline_preconnects_1660 = new Set(), - JSCompiler_object_inline_fontPreloads_1661 = new Set(), - JSCompiler_object_inline_highImagePreloads_1662 = new Set(), - JSCompiler_object_inline_styles_1663 = new Map(), - JSCompiler_object_inline_bootstrapScripts_1664 = new Set(), - JSCompiler_object_inline_scripts_1665 = new Set(), - JSCompiler_object_inline_bulkPreloads_1666 = new Set(), - JSCompiler_object_inline_preloads_1667 = { + var JSCompiler_object_inline_preconnects_1608 = new Set(), + JSCompiler_object_inline_fontPreloads_1609 = new Set(), + JSCompiler_object_inline_highImagePreloads_1610 = new Set(), + JSCompiler_object_inline_styles_1611 = new Map(), + JSCompiler_object_inline_bootstrapScripts_1612 = new Set(), + JSCompiler_object_inline_scripts_1613 = new Set(), + JSCompiler_object_inline_bulkPreloads_1614 = new Set(), + JSCompiler_object_inline_preloads_1615 = { images: new Map(), stylesheets: new Map(), scripts: new Map(), @@ -2528,7 +2522,7 @@ function createRenderState(resumableState, generateStaticMarkup) { scriptConfig.moduleScriptResources[href] = null; scriptConfig = []; pushLinkImpl(scriptConfig, props); - JSCompiler_object_inline_bootstrapScripts_1664.add(scriptConfig); + JSCompiler_object_inline_bootstrapScripts_1612.add(scriptConfig); bootstrapChunks.push('