diff --git a/package.json b/package.json
index 3f94012915c174..0873d1ef98220e 100644
--- a/package.json
+++ b/package.json
@@ -194,14 +194,14 @@
"random-seed": "0.3.0",
"react": "18.2.0",
"react-17": "npm:react@17.0.2",
- "react-builtin": "npm:react@18.3.0-canary-dd480ef92-20230822",
+ "react-builtin": "npm:react@18.3.0-canary-d6dcad6a8-20230914",
"react-dom": "18.2.0",
"react-dom-17": "npm:react-dom@17.0.2",
- "react-dom-builtin": "npm:react-dom@18.3.0-canary-dd480ef92-20230822",
- "react-dom-experimental-builtin": "npm:react-dom@0.0.0-experimental-dd480ef92-20230822",
- "react-experimental-builtin": "npm:react@0.0.0-experimental-dd480ef92-20230822",
- "react-server-dom-webpack": "18.3.0-canary-dd480ef92-20230822",
- "react-server-dom-webpack-experimental": "npm:react-server-dom-webpack@0.0.0-experimental-dd480ef92-20230822",
+ "react-dom-builtin": "npm:react-dom@18.3.0-canary-d6dcad6a8-20230914",
+ "react-dom-experimental-builtin": "npm:react-dom@0.0.0-experimental-d6dcad6a8-20230914",
+ "react-experimental-builtin": "npm:react@0.0.0-experimental-d6dcad6a8-20230914",
+ "react-server-dom-webpack": "18.3.0-canary-d6dcad6a8-20230914",
+ "react-server-dom-webpack-experimental": "npm:react-server-dom-webpack@0.0.0-experimental-d6dcad6a8-20230914",
"react-ssr-prepass": "1.0.8",
"react-virtualized": "9.22.3",
"relay-compiler": "13.0.2",
@@ -211,8 +211,8 @@
"resolve-from": "5.0.0",
"sass": "1.54.0",
"satori": "0.10.3",
- "scheduler-builtin": "npm:scheduler@0.24.0-canary-dd480ef92-20230822",
- "scheduler-experimental-builtin": "npm:scheduler@0.0.0-experimental-dd480ef92-20230822",
+ "scheduler-builtin": "npm:scheduler@0.24.0-canary-d6dcad6a8-20230914",
+ "scheduler-experimental-builtin": "npm:scheduler@0.0.0-experimental-d6dcad6a8-20230914",
"seedrandom": "3.0.5",
"selenium-webdriver": "4.0.0-beta.4",
"semver": "7.3.7",
diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.development.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.development.js
index 15a3a5bd195b25..38cec9357cd237 100644
--- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.development.js
+++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.development.js
@@ -17,7 +17,7 @@ if (process.env.NODE_ENV !== "production") {
var React = require("next/dist/compiled/react-experimental");
var ReactDOM = require('react-dom');
-var ReactVersion = '18.3.0-experimental-dd480ef92-20230822';
+var ReactVersion = '18.3.0-experimental-d6dcad6a8-20230914';
var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
@@ -1511,9 +1511,6 @@ var formReplaying = 'addEventListener("submit",function(a){if(!a.defaultPrevente
function getValueDescriptorExpectingObjectForWarning(thing) {
return thing === null ? '`null`' : thing === undefined ? '`undefined`' : thing === '' ? 'an empty string' : "something with type \"" + typeof thing + "\"";
}
-function getValueDescriptorExpectingEnumForWarning(thing) {
- return thing === null ? '`null`' : thing === undefined ? '`undefined`' : thing === '' ? 'an empty string' : typeof thing === 'string' ? JSON.stringify(thing) : "something with type \"" + typeof thing + "\"";
-}
// same object across all transitions.
@@ -1533,8 +1530,9 @@ var ReactDOMServerDispatcher = {
preconnect: preconnect,
preload: preload,
preloadModule: preloadModule,
- preinit: preinit,
- preinitModule: preinitModule
+ preinitStyle: preinitStyle,
+ preinitScript: preinitScript,
+ preinitModuleScript: preinitModuleScript
};
function prepareHostDispatcher() {
ReactDOMCurrentDispatcher.current = ReactDOMServerDispatcher;
@@ -1558,7 +1556,11 @@ var SentStyleInsertionFunction
= 8;
var SentFormReplayingRuntime
/* */
-= 16; // Per response, global state that is not contextual to the rendering subtree.
+= 16; // Per request, global state that is not contextual to the rendering subtree.
+// This cannot be resumed and therefore should only contain things that are
+// temporary working state or are never used in the prerender pass.
+// Per response, global state that is not contextual to the rendering subtree.
+// This is resumable and therefore should be serializable.
var dataElementQuotedEnd = stringToPrecomputedChunk('">');
var startInlineScript = stringToPrecomputedChunk('');
/**
- * This escaping function is designed to work with bootstrapScriptContent only.
+ * This escaping function is designed to work with bootstrapScriptContent and importMap only.
* because we know we are escaping the entire script. We can avoid for instance
* escaping html comment string sequences that are valid javascript as well because
* if there are no sebsequent ');
* ensure that the script cannot be early terminated or never terminated state
*/
-function escapeBootstrapScriptContent(scriptText) {
+function escapeBootstrapAndImportMapScriptContent(scriptText) {
{
checkHtmlStringCoercion(scriptText);
}
@@ -1592,20 +1594,52 @@ var scriptRegex = /(<\/|<)(s)(cript)/gi;
var scriptReplacer = function (match, prefix, s, suffix) {
return "" + prefix + (s === 's' ? "\\u0073" : "\\u0053") + suffix;
-}; // Allows us to keep track of what we've already written so we can refer back to it.
+};
+
+var importMapScriptStart = stringToPrecomputedChunk(''); // Allows us to keep track of what we've already written so we can refer back to it.
// if passed externalRuntimeConfig and the enableFizzExternalRuntime feature flag
// is set, the server will send instructions via data attributes (instead of inline scripts)
+function createRenderState$1(resumableState, nonce, importMap) {
+ var inlineScriptWithNonce = nonce === undefined ? startInlineScript : stringToPrecomputedChunk('');
var completeSegmentData1 = stringToPrecomputedChunk('` tag.%s', encountered);
- }
- }
+ var resumableState = getResumableState(request);
- if (typeof href === 'string' && href && typeof options === 'object' && options !== null && typeof options.as === 'string' && options.as) {
- var as = options.as;
+ if (as && href) {
+ options = options || {};
var key;
if (as === 'image') {
// For image preloads the key contains either the imageSrcSet + imageSizes or the href but not
// both. This is to prevent identical calls with the same srcSet and sizes to be duplicated
// by varying the href. this is an edge case but it is the most correct behavior.
- var imageSrcSet = options.imageSrcSet,
- imageSizes = options.imageSizes;
- key = getImagePreloadKey(href, imageSrcSet, imageSizes);
+ key = getImagePreloadKey(href, options.imageSrcSet, options.imageSizes);
} else {
key = getResourceKey(as, href);
}
- var resource = resources.preloadsMap.get(key);
+ var resource = resumableState.preloadsMap.get(key);
if (!resource) {
+ var props = assign({
+ rel: 'preload',
+ href: as === 'image' && options.imageSrcSet ? undefined : href,
+ as: as
+ }, options);
+
resource = {
type: 'preload',
chunks: [],
state: NoState,
- props: preloadPropsFromPreloadOptions(href, as, options)
+ props: props
};
- resources.preloadsMap.set(key, resource);
+ resumableState.preloadsMap.set(key, resource);
pushLinkImpl(resource.chunks, resource.props);
}
if (as === 'font') {
- resources.fontPreloads.add(resource);
- } else if (as === 'image' && options.fetchPriority === 'high') {
- resources.highImagePreloads.add(resource);
+ resumableState.fontPreloads.add(resource);
+ } else if (as === 'image' && resource.props.fetchPriority === 'high') {
+ resumableState.highImagePreloads.add(resource);
} else {
- resources.bulkPreloads.add(resource);
+ resumableState.bulkPreloads.add(resource);
}
flushResources(request);
@@ -5532,48 +5550,35 @@ function preloadModule(href, options) {
return;
}
- var resources = getResources(request);
+ var resumableState = getResumableState(request);
- {
- var encountered = '';
-
- if (typeof href !== 'string' || !href) {
- encountered += " The `href` argument encountered was " + getValueDescriptorExpectingObjectForWarning(href) + ".";
- }
-
- if (options !== undefined && typeof options !== 'object') {
- encountered += " The `options` argument encountered was " + getValueDescriptorExpectingObjectForWarning(options) + ".";
- } else if (options && 'as' in options && typeof options.as !== 'string') {
- encountered += " The `as` option encountered was " + getValueDescriptorExpectingObjectForWarning(options.as) + ".";
- }
-
- if (encountered) {
- error('ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally, an `options` object with an `as` property valid for a `` tag.%s', encountered);
- }
- }
-
- if (typeof href === 'string' && href) {
+ if (href) {
var as = options && typeof options.as === 'string' ? options.as : 'script';
var key = getResourceKey(as, href);
- var resource = resources.preloadsMap.get(key);
+ var resource = resumableState.preloadsMap.get(key);
+
+ var props = assign({
+ rel: 'modulepreload',
+ href: href
+ }, options);
if (!resource) {
resource = {
type: 'preload',
chunks: [],
state: NoState,
- props: preloadModulePropsFromPreloadModuleOptions(href, as, options)
+ props: props
};
- resources.preloadsMap.set(key, resource);
+ resumableState.preloadsMap.set(key, resource);
pushLinkImpl(resource.chunks, resource.props);
}
- resources.bulkPreloads.add(resource);
+ resumableState.bulkPreloads.add(resource);
flushResources(request);
}
}
-function preinit(href, options) {
+function preinitStyle(href, precedence, options) {
var request = resolveRequest();
@@ -5586,104 +5591,69 @@ function preinit(href, options) {
return;
}
- var resources = getResources(request);
-
- {
- if (typeof href !== 'string' || !href) {
- error('ReactDOM.preinit(): Expected the `href` argument (first) to be a non-empty string but encountered %s instead.', getValueDescriptorExpectingObjectForWarning(href));
- } else if (options == null || typeof options !== 'object') {
- error('ReactDOM.preinit(): Expected the `options` argument (second) to be an object with an `as` property describing the type of resource to be preinitialized but encountered %s instead.', getValueDescriptorExpectingEnumForWarning(options));
- } else if (options.as !== 'style' && options.as !== 'script') {
- error('ReactDOM.preinit(): Expected the `as` property in the `options` argument (second) to contain a valid value describing the type of resource to be preinitialized but encountered %s instead. Valid values for `as` are "style" and "script".', getValueDescriptorExpectingEnumForWarning(options.as));
- }
- }
-
- if (typeof href === 'string' && href && typeof options === 'object' && options !== null) {
- var as = options.as;
+ var resumableState = getResumableState(request);
- switch (as) {
- case 'style':
- {
- var key = getResourceKey(as, href);
- var resource = resources.stylesMap.get(key);
- var precedence = options.precedence || 'default';
-
- if (!resource) {
- var state = NoState;
- var preloadResource = resources.preloadsMap.get(key);
+ if (href) {
+ var as = 'style';
+ var key = getResourceKey(as, href);
+ var resource = resumableState.stylesMap.get(key);
- if (preloadResource && preloadResource.state & Flushed) {
- state = PreloadFlushed;
- }
+ if (!resource) {
+ precedence = precedence || 'default';
+ var state = NoState;
+ var preloadResource = resumableState.preloadsMap.get(key);
- resource = {
- type: 'stylesheet',
- chunks: [],
- state: state,
- props: stylesheetPropsFromPreinitOptions(href, precedence, options)
- };
- resources.stylesMap.set(key, resource);
- var precedenceSet = resources.precedences.get(precedence);
-
- if (!precedenceSet) {
- precedenceSet = new Set();
- resources.precedences.set(precedence, precedenceSet);
- var emptyStyleResource = {
- type: 'style',
- chunks: [],
- state: NoState,
- props: {
- precedence: precedence,
- hrefs: []
- }
- };
- precedenceSet.add(emptyStyleResource);
+ if (preloadResource && preloadResource.state & Flushed) {
+ state = PreloadFlushed;
+ }
- {
- if (resources.stylePrecedences.has(precedence)) {
- error('React constructed an empty style resource when a style resource already exists for this precedence: "%s". This is a bug in React.', precedence);
- }
- }
+ var props = assign({
+ rel: 'stylesheet',
+ href: href,
+ 'data-precedence': precedence
+ }, options);
- resources.stylePrecedences.set(precedence, emptyStyleResource);
- }
+ resource = {
+ type: 'stylesheet',
+ chunks: [],
+ state: state,
+ props: props
+ };
+ resumableState.stylesMap.set(key, resource);
+ var precedenceSet = resumableState.precedences.get(precedence);
- precedenceSet.add(resource);
- flushResources(request);
+ if (!precedenceSet) {
+ precedenceSet = new Set();
+ resumableState.precedences.set(precedence, precedenceSet);
+ var emptyStyleResource = {
+ type: 'style',
+ chunks: [],
+ state: NoState,
+ props: {
+ precedence: precedence,
+ hrefs: []
}
+ };
+ precedenceSet.add(emptyStyleResource);
- return;
- }
-
- case 'script':
{
- var src = href;
-
- var _key = getResourceKey(as, src);
-
- var _resource = resources.scriptsMap.get(_key);
-
- if (!_resource) {
- _resource = {
- type: 'script',
- chunks: [],
- state: NoState,
- props: null
- };
- resources.scriptsMap.set(_key, _resource);
- var resourceProps = scriptPropsFromPreinitOptions(src, options);
- resources.scripts.add(_resource);
- pushScriptImpl(_resource.chunks, resourceProps);
- flushResources(request);
+ if (resumableState.stylePrecedences.has(precedence)) {
+ error('React constructed an empty style resource when a style resource already exists for this precedence: "%s". This is a bug in React.', precedence);
}
-
- return;
}
+
+ resumableState.stylePrecedences.set(precedence, emptyStyleResource);
+ }
+
+ precedenceSet.add(resource);
+ flushResources(request);
}
+
+ return;
}
}
-function preinitModule(href, options) {
+function preinitScript(src, options) {
var request = resolveRequest();
@@ -5696,70 +5666,75 @@ function preinitModule(href, options) {
return;
}
- var resources = getResources(request);
+ var resumableState = getResumableState(request);
- {
- var encountered = '';
+ if (src) {
+ var key = getResourceKey('script', src);
+ var resource = resumableState.scriptsMap.get(key);
- if (typeof href !== 'string' || !href) {
- encountered += " The `href` argument encountered was " + getValueDescriptorExpectingObjectForWarning(href) + ".";
- }
+ if (!resource) {
+ resource = {
+ type: 'script',
+ chunks: [],
+ state: NoState,
+ props: null
+ };
+ resumableState.scriptsMap.set(key, resource);
+
+ var props = assign({
+ src: src,
+ async: true
+ }, options);
- if (options !== undefined && typeof options !== 'object') {
- encountered += " The `options` argument encountered was " + getValueDescriptorExpectingObjectForWarning(options) + ".";
- } else if (options && 'as' in options && options.as !== 'script') {
- encountered += " The `as` option encountered was " + getValueDescriptorExpectingEnumForWarning(options.as) + ".";
+ resumableState.scripts.add(resource);
+ pushScriptImpl(resource.chunks, props);
+ flushResources(request);
}
- if (encountered) {
- error('ReactDOM.preinitModule(): Expected up to two arguments, a non-empty `href` string and, optionally, an `options` object with a valid `as` property.%s', encountered);
- } else {
- var as = options && typeof options.as === 'string' ? options.as : 'script';
+ return;
+ }
+}
- switch (as) {
- case 'script':
- {
- break;
- }
- // We have an invalid as type and need to warn
+function preinitModuleScript(src, options) {
- default:
- {
- var typeOfAs = getValueDescriptorExpectingEnumForWarning(as);
+ var request = resolveRequest();
- error('ReactDOM.preinitModule(): Currently the only supported "as" type for this function is "script"' + ' but received "%s" instead. This warning was generated for `href` "%s". In the future other' + ' module types will be supported, aligning with the import-attributes proposal. Learn more here:' + ' (https://github.com/tc39/proposal-import-attributes)', typeOfAs, href);
- }
- }
- }
+ if (!request) {
+ // In async contexts we can sometimes resolve resources from AsyncLocalStorage. If we can't we can also
+ // possibly get them from the stack if we are not in an async context. Since we were not able to resolve
+ // the resources for this call in either case we opt to do nothing. We can consider making this a warning
+ // but there may be times where calling a function outside of render is intentional (i.e. to warm up data
+ // fetching) and we don't want to warn in those cases.
+ return;
}
- if (typeof href === 'string' && href) {
- var _as = options && typeof options.as === 'string' ? options.as : 'script';
+ var resumableState = getResumableState(request);
- switch (_as) {
- case 'script':
- {
- var src = href;
- var key = getResourceKey(_as, src);
- var resource = resources.scriptsMap.get(key);
+ if (src) {
+ var key = getResourceKey('script', src);
+ var resource = resumableState.scriptsMap.get(key);
- if (!resource) {
- resource = {
- type: 'script',
- chunks: [],
- state: NoState,
- props: null
- };
- resources.scriptsMap.set(key, resource);
- var resourceProps = modulePropsFromPreinitModuleOptions(src, options);
- resources.scripts.add(resource);
- pushScriptImpl(resource.chunks, resourceProps);
- flushResources(request);
- }
+ if (!resource) {
+ resource = {
+ type: 'script',
+ chunks: [],
+ state: NoState,
+ props: null
+ };
+ resumableState.scriptsMap.set(key, resource);
- return;
- }
+ var props = assign({
+ src: src,
+ type: 'module',
+ async: true
+ }, options);
+
+ resumableState.scripts.add(resource);
+ pushScriptImpl(resource.chunks, props);
+ flushResources(request);
}
+
+ return;
}
} // This function is only safe to call at Request start time since it assumes
// that each script has not already been preloaded. If we find a need to preload
@@ -5767,11 +5742,11 @@ function preinitModule(href, options) {
// already exists and not assume it
-function preloadBootstrapScript(resources, src, nonce, integrity, crossOrigin) {
+function preloadBootstrapScript(resumableState, src, nonce, integrity, crossOrigin) {
var key = getResourceKey('script', src);
{
- if (resources.preloadsMap.has(key)) {
+ if (resumableState.preloadsMap.has(key)) {
// This is coded as a React error because it should be impossible for a userspace preload to preempt this call
// If a userspace preload can preempt it then this assumption is broken and we need to reconsider this strategy
// rather than instruct the user to not preload their bootstrap scripts themselves
@@ -5794,8 +5769,8 @@ function preloadBootstrapScript(resources, src, nonce, integrity, crossOrigin) {
state: NoState,
props: props
};
- resources.preloadsMap.set(key, resource);
- resources.bootstrapScripts.add(resource);
+ resumableState.preloadsMap.set(key, resource);
+ resumableState.bootstrapScripts.add(resource);
pushLinkImpl(resource.chunks, props);
} // This function is only safe to call at Request start time since it assumes
// that each module has not already been preloaded. If we find a need to preload
@@ -5803,11 +5778,11 @@ function preloadBootstrapScript(resources, src, nonce, integrity, crossOrigin) {
// already exists and not assume it
-function preloadBootstrapModule(resources, src, nonce, integrity, crossOrigin) {
+function preloadBootstrapModule(resumableState, src, nonce, integrity, crossOrigin) {
var key = getResourceKey('script', src);
{
- if (resources.preloadsMap.has(key)) {
+ if (resumableState.preloadsMap.has(key)) {
// This is coded as a React error because it should be impossible for a userspace preload to preempt this call
// If a userspace preload can preempt it then this assumption is broken and we need to reconsider this strategy
// rather than instruct the user to not preload their bootstrap scripts themselves
@@ -5829,15 +5804,15 @@ function preloadBootstrapModule(resources, src, nonce, integrity, crossOrigin) {
state: NoState,
props: props
};
- resources.preloadsMap.set(key, resource);
- resources.bootstrapScripts.add(resource);
+ resumableState.preloadsMap.set(key, resource);
+ resumableState.bootstrapScripts.add(resource);
pushLinkImpl(resource.chunks, props);
return;
}
-function internalPreinitScript(resources, src, chunks) {
+function internalPreinitScript(resumableState, src, chunks) {
var key = getResourceKey('script', src);
- var resource = resources.scriptsMap.get(key);
+ var resource = resumableState.scriptsMap.get(key);
if (!resource) {
resource = {
@@ -5846,43 +5821,13 @@ function internalPreinitScript(resources, src, chunks) {
state: NoState,
props: null
};
- resources.scriptsMap.set(key, resource);
- resources.scripts.add(resource);
+ resumableState.scriptsMap.set(key, resource);
+ resumableState.scripts.add(resource);
}
return;
}
-function preloadPropsFromPreloadOptions(href, as, options) {
- return {
- rel: 'preload',
- as: as,
- // There is a bug in Safari where imageSrcSet is not respected on preload links
- // so we omit the href here if we have imageSrcSet b/c safari will load the wrong image.
- // This harms older browers that do not support imageSrcSet by making their preloads not work
- // but this population is shrinking fast and is already small so we accept this tradeoff.
- href: as === 'image' && options.imageSrcSet ? undefined : href,
- crossOrigin: as === 'font' ? '' : options.crossOrigin,
- integrity: options.integrity,
- type: options.type,
- nonce: options.nonce,
- fetchPriority: options.fetchPriority,
- imageSrcSet: options.imageSrcSet,
- imageSizes: options.imageSizes,
- referrerPolicy: options.referrerPolicy
- };
-}
-
-function preloadModulePropsFromPreloadModuleOptions(href, as, options) {
- return {
- rel: 'modulepreload',
- as: as !== 'script' ? as : undefined,
- href: href,
- crossOrigin: options ? options.crossOrigin : undefined,
- integrity: options ? options.integrity : undefined
- };
-}
-
function preloadAsStylePropsFromProps(href, props) {
return {
rel: 'preload',
@@ -5897,17 +5842,6 @@ function preloadAsStylePropsFromProps(href, props) {
};
}
-function stylesheetPropsFromPreinitOptions(href, precedence, options) {
- return {
- rel: 'stylesheet',
- href: href,
- 'data-precedence': precedence,
- crossOrigin: options.crossOrigin,
- integrity: options.integrity,
- fetchPriority: options.fetchPriority
- };
-}
-
function stylesheetPropsFromRawProps(rawProps) {
return assign({}, rawProps, {
'data-precedence': rawProps.precedence,
@@ -5920,27 +5854,6 @@ function adoptPreloadPropsForStylesheetProps(resourceProps, preloadProps) {
if (resourceProps.integrity == null) resourceProps.integrity = preloadProps.integrity;
}
-function scriptPropsFromPreinitOptions(src, options) {
- return {
- src: src,
- async: true,
- crossOrigin: options.crossOrigin,
- integrity: options.integrity,
- nonce: options.nonce,
- fetchPriority: options.fetchPriority
- };
-}
-
-function modulePropsFromPreinitModuleOptions(src, options) {
- return {
- src: src,
- type: 'module',
- async: true,
- crossOrigin: options ? options.crossOrigin : undefined,
- integrity: options ? options.integrity : undefined
- };
-}
-
function adoptPreloadPropsForScriptProps(resourceProps, preloadProps) {
if (resourceProps.crossOrigin == null) resourceProps.crossOrigin = preloadProps.crossOrigin;
if (resourceProps.integrity == null) resourceProps.integrity = preloadProps.integrity;
@@ -5950,65 +5863,54 @@ function hoistStyleResource(resource) {
this.add(resource);
}
-function hoistResources(resources, source) {
- var currentBoundaryResources = resources.boundaryResources;
+function hoistResources(renderState, source) {
+ var currentBoundaryResources = renderState.boundaryResources;
if (currentBoundaryResources) {
source.forEach(hoistStyleResource, currentBoundaryResources);
}
}
-function createResponseState(resources, generateStaticMarkup, identifierPrefix, externalRuntimeConfig) {
- var responseState = createResponseState$1(resources, identifierPrefix, undefined, undefined, undefined, undefined, externalRuntimeConfig);
+function createRenderState(resumableState, nonce, generateStaticMarkup) {
+ var renderState = createRenderState$1(resumableState, nonce);
return {
// Keep this in sync with ReactFizzConfigDOM
- bootstrapChunks: responseState.bootstrapChunks,
- placeholderPrefix: responseState.placeholderPrefix,
- segmentPrefix: responseState.segmentPrefix,
- boundaryPrefix: responseState.boundaryPrefix,
- idPrefix: responseState.idPrefix,
- nextSuspenseID: responseState.nextSuspenseID,
- streamingFormat: responseState.streamingFormat,
- startInlineScript: responseState.startInlineScript,
- instructions: responseState.instructions,
- externalRuntimeScript: responseState.externalRuntimeScript,
- htmlChunks: responseState.htmlChunks,
- headChunks: responseState.headChunks,
- hasBody: responseState.hasBody,
- charsetChunks: responseState.charsetChunks,
- preconnectChunks: responseState.preconnectChunks,
- preloadChunks: responseState.preloadChunks,
- hoistableChunks: responseState.hoistableChunks,
- stylesToHoist: responseState.stylesToHoist,
+ placeholderPrefix: renderState.placeholderPrefix,
+ segmentPrefix: renderState.segmentPrefix,
+ boundaryPrefix: renderState.boundaryPrefix,
+ startInlineScript: renderState.startInlineScript,
+ htmlChunks: renderState.htmlChunks,
+ headChunks: renderState.headChunks,
+ charsetChunks: renderState.charsetChunks,
+ preconnectChunks: renderState.preconnectChunks,
+ importMapChunks: renderState.importMapChunks,
+ preloadChunks: renderState.preloadChunks,
+ hoistableChunks: renderState.hoistableChunks,
+ boundaryResources: renderState.boundaryResources,
+ stylesToHoist: renderState.stylesToHoist,
// This is an extra field for the legacy renderer
generateStaticMarkup: generateStaticMarkup
};
}
-function createRootFormatContext() {
- return {
- insertionMode: HTML_MODE,
- // We skip the root mode because we don't want to emit the DOCTYPE in legacy mode.
- selectedValue: null,
- noscriptTagInScope: false
- };
-}
-function pushTextInstance(target, text, responseState, textEmbedded) {
- if (responseState.generateStaticMarkup) {
+
+var doctypeChunk = stringToPrecomputedChunk('');
+function pushTextInstance(target, text, renderState, textEmbedded) {
+ if (renderState.generateStaticMarkup) {
target.push(stringToChunk(escapeTextForBrowser(text)));
return false;
} else {
- return pushTextInstance$1(target, text, responseState, textEmbedded);
+ return pushTextInstance$1(target, text, renderState, textEmbedded);
}
}
-function pushSegmentFinale(target, responseState, lastPushedText, textEmbedded) {
- if (responseState.generateStaticMarkup) {
+function pushSegmentFinale(target, renderState, lastPushedText, textEmbedded) {
+ if (renderState.generateStaticMarkup) {
return;
} else {
- return pushSegmentFinale$1(target, responseState, lastPushedText, textEmbedded);
+ return pushSegmentFinale$1(target, renderState, lastPushedText, textEmbedded);
}
}
-function writeStartCompletedSuspenseBoundary(destination, responseState) {
- if (responseState.generateStaticMarkup) {
+function writeStartCompletedSuspenseBoundary(destination, renderState) {
+ if (renderState.generateStaticMarkup) {
// A completed boundary is done and doesn't need a representation in the HTML
// if we're not going to be hydrating it.
return true;
@@ -6016,25 +5918,25 @@ function writeStartCompletedSuspenseBoundary(destination, responseState) {
return writeStartCompletedSuspenseBoundary$1(destination);
}
-function writeStartClientRenderedSuspenseBoundary(destination, responseState, // flushing these error arguments are not currently supported in this legacy streaming format.
+function writeStartClientRenderedSuspenseBoundary(destination, renderState, // flushing these error arguments are not currently supported in this legacy streaming format.
errorDigest, errorMessage, errorComponentStack) {
- if (responseState.generateStaticMarkup) {
+ if (renderState.generateStaticMarkup) {
// A client rendered boundary is done and doesn't need a representation in the HTML
// since we'll never hydrate it. This is arguably an error in static generation.
return true;
}
- return writeStartClientRenderedSuspenseBoundary$1(destination, responseState, errorDigest, errorMessage, errorComponentStack);
+ return writeStartClientRenderedSuspenseBoundary$1(destination, renderState, errorDigest, errorMessage, errorComponentStack);
}
-function writeEndCompletedSuspenseBoundary(destination, responseState) {
- if (responseState.generateStaticMarkup) {
+function writeEndCompletedSuspenseBoundary(destination, renderState) {
+ if (renderState.generateStaticMarkup) {
return true;
}
return writeEndCompletedSuspenseBoundary$1(destination);
}
-function writeEndClientRenderedSuspenseBoundary(destination, responseState) {
- if (responseState.generateStaticMarkup) {
+function writeEndClientRenderedSuspenseBoundary(destination, renderState) {
+ if (renderState.generateStaticMarkup) {
return true;
}
@@ -7623,6 +7525,8 @@ typeof Object.is === 'function' ? Object.is : is;
var currentlyRenderingComponent = null;
var currentlyRenderingTask = null;
+var currentlyRenderingRequest = null;
+var currentlyRenderingKeyPath = null;
var firstWorkInProgressHook = null;
var workInProgressHook = null; // Whether the work-in-progress hook is a re-rendered hook
@@ -7630,7 +7534,14 @@ var isReRender = false; // Whether an update was scheduled during the currently
var didScheduleRenderPhaseUpdate = false; // Counts the number of useId hooks in this component
-var localIdCounter = 0; // Counts the number of use(thenable) calls in this component
+var localIdCounter = 0; // Chunks that should be pushed to the stream once the component
+// finishes rendering.
+// Counts the number of useFormState calls in this component
+
+var formStateCounter = 0; // The index of the useFormState hook that matches the one passed in at the
+// root during an MPA navigation, if any.
+
+var formStateMatchingIndex = -1; // Counts the number of use(thenable) calls in this component
var thenableIndexCounter = 0;
var thenableState = null; // Lazily created map of render-phase updates
@@ -7725,9 +7636,11 @@ function createWorkInProgressHook() {
return workInProgressHook;
}
-function prepareToUseHooks(task, componentIdentity, prevThenableState) {
+function prepareToUseHooks(request, task, keyPath, componentIdentity, prevThenableState) {
currentlyRenderingComponent = componentIdentity;
currentlyRenderingTask = task;
+ currentlyRenderingRequest = request;
+ currentlyRenderingKeyPath = keyPath;
{
isInHookUserCodeInDev = false;
@@ -7740,6 +7653,8 @@ function prepareToUseHooks(task, componentIdentity, prevThenableState) {
localIdCounter = 0;
+ formStateCounter = 0;
+ formStateMatchingIndex = -1;
thenableIndexCounter = 0;
thenableState = prevThenableState;
}
@@ -7753,6 +7668,8 @@ function finishHooks(Component, props, children, refOrContext) {
// restarting until no more updates are scheduled.
didScheduleRenderPhaseUpdate = false;
localIdCounter = 0;
+ formStateCounter = 0;
+ formStateMatchingIndex = -1;
thenableIndexCounter = 0;
numberOfReRenders += 1; // Start over from the beginning of the list
@@ -7774,6 +7691,18 @@ function checkDidRenderIdHook() {
// separate function to avoid using an array tuple.
var didRenderIdHook = localIdCounter !== 0;
return didRenderIdHook;
+}
+function getFormStateCount() {
+ // This should be called immediately after every finishHooks call.
+ // Conceptually, it's part of the return value of finishHooks; it's only a
+ // separate function to avoid using an array tuple.
+ return formStateCounter;
+}
+function getFormStateMatchingIndex() {
+ // This should be called immediately after every finishHooks call.
+ // Conceptually, it's part of the return value of finishHooks; it's only a
+ // separate function to avoid using an array tuple.
+ return formStateMatchingIndex;
} // Reset the internal hooks state if an error occurs while rendering a component
function resetHooksState() {
@@ -7783,6 +7712,8 @@ function resetHooksState() {
currentlyRenderingComponent = null;
currentlyRenderingTask = null;
+ currentlyRenderingRequest = null;
+ currentlyRenderingKeyPath = null;
didScheduleRenderPhaseUpdate = false;
firstWorkInProgressHook = null;
numberOfReRenders = 0;
@@ -8054,17 +7985,125 @@ function useOptimistic(passthrough, reducer) {
return [passthrough, unsupportedSetOptimisticState];
}
+function createPostbackFormStateKey(permalink, componentKeyPath, hookIndex) {
+ if (permalink !== undefined) {
+ return 'p' + permalink;
+ } else {
+ // Append a node to the key path that represents the form state hook.
+ var keyPath = [componentKeyPath, null, hookIndex];
+ return 'k' + JSON.stringify(keyPath);
+ }
+}
+
+function useFormState(action, initialState, permalink) {
+ resolveCurrentlyRenderingComponent(); // Count the number of useFormState hooks per component. We also use this to
+ // track the position of this useFormState hook relative to the other ones in
+ // this component, so we can generate a unique key for each one.
+
+ var formStateHookIndex = formStateCounter++;
+ var request = currentlyRenderingRequest; // $FlowIgnore[prop-missing]
+
+ var formAction = action.$$FORM_ACTION;
+
+ if (typeof formAction === 'function') {
+ // This is a server action. These have additional features to enable
+ // MPA-style form submissions with progressive enhancement.
+ // TODO: If the same permalink is passed to multiple useFormStates, and
+ // they all have the same action signature, Fizz will pass the postback
+ // state to all of them. We should probably only pass it to the first one,
+ // and/or warn.
+ // The key is lazily generated and deduped so the that the keypath doesn't
+ // get JSON.stringify-ed unnecessarily, and at most once.
+ var nextPostbackStateKey = null; // Determine the current form state. If we received state during an MPA form
+ // submission, then we will reuse that, if the action identity matches.
+ // Otherwise we'll use the initial state argument. We will emit a comment
+ // marker into the stream that indicates whether the state was reused.
+
+ var state = initialState;
+ var componentKeyPath = currentlyRenderingKeyPath;
+ var postbackFormState = getFormState(request); // $FlowIgnore[prop-missing]
+
+ var isSignatureEqual = action.$$IS_SIGNATURE_EQUAL;
+
+ if (postbackFormState !== null && typeof isSignatureEqual === 'function') {
+ var postbackKey = postbackFormState[1];
+ var postbackReferenceId = postbackFormState[2];
+ var postbackBoundArity = postbackFormState[3];
+
+ if (isSignatureEqual.call(action, postbackReferenceId, postbackBoundArity)) {
+ nextPostbackStateKey = createPostbackFormStateKey(permalink, componentKeyPath, formStateHookIndex);
+
+ if (postbackKey === nextPostbackStateKey) {
+ // This was a match
+ formStateMatchingIndex = formStateHookIndex; // Reuse the state that was submitted by the form.
+
+ state = postbackFormState[0];
+ }
+ }
+ } // Bind the state to the first argument of the action.
+
+
+ var boundAction = action.bind(null, state); // Wrap the action so the return value is void.
+
+ var dispatch = function (payload) {
+ boundAction(payload);
+ }; // $FlowIgnore[prop-missing]
+
+
+ if (typeof boundAction.$$FORM_ACTION === 'function') {
+ // $FlowIgnore[prop-missing]
+ dispatch.$$FORM_ACTION = function (prefix) {
+ var metadata = boundAction.$$FORM_ACTION(prefix); // Override the action URL
+
+ if (permalink !== undefined) {
+ {
+ checkAttributeStringCoercion(permalink, 'target');
+ }
+
+ permalink += '';
+ metadata.action = permalink;
+ }
+
+ var formData = metadata.data;
+
+ if (formData) {
+ if (nextPostbackStateKey === null) {
+ nextPostbackStateKey = createPostbackFormStateKey(permalink, componentKeyPath, formStateHookIndex);
+ }
+
+ formData.append('$ACTION_KEY', nextPostbackStateKey);
+ }
+
+ return metadata;
+ };
+ }
+
+ return [state, dispatch];
+ } else {
+ // This is not a server action, so the implementation is much simpler.
+ // Bind the state to the first argument of the action.
+ var _boundAction = action.bind(null, initialState); // Wrap the action so the return value is void.
+
+
+ var _dispatch2 = function (payload) {
+ _boundAction(payload);
+ };
+
+ return [initialState, _dispatch2];
+ }
+}
+
function useId() {
var task = currentlyRenderingTask;
var treeId = getTreeId(task.treeContext);
- var responseState = currentResponseState;
+ var resumableState = currentResumableState;
- if (responseState === null) {
+ if (resumableState === null) {
throw new Error('Invalid hook call. Hooks can only be called inside of the body of a function component.');
}
var localId = localIdCounter++;
- return makeId(responseState, treeId, localId);
+ return makeId(resumableState, treeId, localId);
}
function use(usable) {
@@ -8157,11 +8196,12 @@ var HooksDispatcher = {
{
HooksDispatcher.useOptimistic = useOptimistic;
+ HooksDispatcher.useFormState = useFormState;
}
-var currentResponseState = null;
-function setCurrentResponseState(responseState) {
- currentResponseState = responseState;
+var currentResumableState = null;
+function setCurrentResumableState(resumableState) {
+ currentResumableState = resumableState;
}
function getCacheSignal() {
@@ -8213,11 +8253,18 @@ var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; // Lin
// The name might be minified but we assume that it's going to be the same generated name. Typically
// because it's just the same compiled output in practice.
+var REPLAY_NODE = 0;
+var REPLAY_SUSPENSE_BOUNDARY = 1;
+var RESUME_ELEMENT = 2;
+var RESUME_SLOT = 3;
+var CLIENT_RENDERED = 4; // if it errors or infinitely suspends
+
var PENDING = 0;
var COMPLETED = 1;
var FLUSHED = 2;
var ABORTED = 3;
var ERRORED = 4;
+var POSTPONED = 5;
var OPEN = 0;
var CLOSING = 1;
var CLOSED = 2; // This is a default heuristic for how to split up the HTML content into progressive
@@ -8246,40 +8293,43 @@ function defaultErrorHandler(error) {
function noop() {}
-function createRequest(children, resources, responseState, rootFormatContext, progressiveChunkSize, onError, onAllReady, onShellReady, onShellError, onFatalError, onPostpone) {
+function createRequest(children, resumableState, renderState, rootFormatContext, progressiveChunkSize, onError, onAllReady, onShellReady, onShellError, onFatalError, onPostpone, formState) {
prepareHostDispatcher();
var pingedTasks = [];
var abortSet = new Set();
var request = {
destination: null,
flushScheduled: false,
- responseState: responseState,
+ resumableState: resumableState,
+ renderState: renderState,
+ rootFormatContext: rootFormatContext,
progressiveChunkSize: progressiveChunkSize === undefined ? DEFAULT_PROGRESSIVE_CHUNK_SIZE : progressiveChunkSize,
status: OPEN,
fatalError: null,
nextSegmentId: 0,
allPendingTasks: 0,
pendingRootTasks: 0,
- resources: resources,
completedRootSegment: null,
abortableTasks: abortSet,
pingedTasks: pingedTasks,
clientRenderedBoundaries: [],
completedBoundaries: [],
partialBoundaries: [],
+ trackedPostpones: null,
onError: onError === undefined ? defaultErrorHandler : onError,
onPostpone: onPostpone === undefined ? noop : onPostpone,
onAllReady: onAllReady === undefined ? noop : onAllReady,
onShellReady: onShellReady === undefined ? noop : onShellReady,
onShellError: onShellError === undefined ? noop : onShellError,
- onFatalError: onFatalError === undefined ? noop : onFatalError
+ onFatalError: onFatalError === undefined ? noop : onFatalError,
+ formState: formState === undefined ? null : formState
}; // This segment represents the root fallback.
var rootSegment = createPendingSegment(request, 0, null, rootFormatContext, // Root segments are never embedded in Text on either edge
false, false); // There is no parent so conceptually, we're unblocked to flush this segment.
rootSegment.parentFlushed = true;
- var rootTask = createTask(request, null, children, null, rootSegment, abortSet, null, emptyContextObject, rootContextSnapshot, emptyTreeContext);
+ var rootTask = createTask(request, null, children, -1, null, rootSegment, abortSet, null, rootFormatContext, emptyContextObject, rootContextSnapshot, emptyTreeContext);
pingedTasks.push(rootTask);
return request;
}
@@ -8302,22 +8352,23 @@ function pingTask(request, task) {
}
}
-function createSuspenseBoundary(request, fallbackAbortableTasks) {
+function createSuspenseBoundary(request, fallbackAbortableTasks, keyPath) {
return {
+ status: PENDING,
id: UNINITIALIZED_SUSPENSE_BOUNDARY_ID,
rootSegmentID: -1,
parentFlushed: false,
pendingTasks: 0,
- forceClientRender: false,
completedSegments: [],
byteSize: 0,
fallbackAbortableTasks: fallbackAbortableTasks,
errorDigest: null,
- resources: createBoundaryResources()
+ resources: createBoundaryResources(),
+ keyPath: keyPath
};
}
-function createTask(request, thenableState, node, blockedBoundary, blockedSegment, abortSet, keyPath, legacyContext, context, treeContext) {
+function createTask(request, thenableState, node, childIndex, blockedBoundary, blockedSegment, abortSet, keyPath, formatContext, legacyContext, context, treeContext) {
request.allPendingTasks++;
if (blockedBoundary === null) {
@@ -8328,6 +8379,7 @@ function createTask(request, thenableState, node, blockedBoundary, blockedSegmen
var task = {
node: node,
+ childIndex: childIndex,
ping: function () {
return pingTask(request, task);
},
@@ -8335,6 +8387,7 @@ function createTask(request, thenableState, node, blockedBoundary, blockedSegmen
blockedSegment: blockedSegment,
abortSet: abortSet,
keyPath: keyPath,
+ formatContext: formatContext,
legacyContext: legacyContext,
context: context,
treeContext: treeContext,
@@ -8349,7 +8402,7 @@ function createTask(request, thenableState, node, blockedBoundary, blockedSegmen
return task;
}
-function createPendingSegment(request, index, boundary, formatContext, lastPushedText, textEmbedded) {
+function createPendingSegment(request, index, boundary, parentFormatContext, lastPushedText, textEmbedded) {
return {
status: PENDING,
id: -1,
@@ -8358,7 +8411,7 @@ function createPendingSegment(request, index, boundary, formatContext, lastPushe
parentFlushed: false,
chunks: [],
children: [],
- formatContext: formatContext,
+ parentFormatContext: parentFormatContext,
boundary: boundary,
lastPushedText: lastPushedText,
textEmbedded: textEmbedded
@@ -8478,8 +8531,9 @@ function fatalError(request, error) {
}
}
-function renderSuspenseBoundary(request, task, props) {
+function renderSuspenseBoundary(request, task, keyPath, props) {
pushBuiltInComponentStackInDEV(task, 'Suspense');
+ var prevKeyPath = task.keyPath;
var parentBoundary = task.blockedBoundary;
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.
@@ -8489,16 +8543,16 @@ function renderSuspenseBoundary(request, task, props) {
var fallback = props.fallback;
var content = props.children;
var fallbackAbortSet = new Set();
- var newBoundary = createSuspenseBoundary(request, fallbackAbortSet);
+ var newBoundary = createSuspenseBoundary(request, fallbackAbortSet, keyPath);
var insertionIndex = parentSegment.chunks.length; // The children of the boundary segment is actually the fallback.
- var boundarySegment = createPendingSegment(request, insertionIndex, newBoundary, parentSegment.formatContext, // boundaries never require text embedding at their edges because comment nodes bound them
+ var boundarySegment = createPendingSegment(request, insertionIndex, newBoundary, task.formatContext, // boundaries never require text embedding at their edges because comment nodes bound them
false, false);
parentSegment.children.push(boundarySegment); // The parentSegment has a child Segment at this index so we reset the lastPushedText marker on the parent
parentSegment.lastPushedText = false; // This segment is the actual child content. We can start rendering that immediately.
- var contentRootSegment = createPendingSegment(request, 0, null, parentSegment.formatContext, // boundaries never require text embedding at their edges because comment nodes bound them
+ var contentRootSegment = createPendingSegment(request, 0, null, task.formatContext, // boundaries never require text embedding at their edges because comment nodes bound them
false, false); // We mark the root segment as having its parent flushed. It's not really flushed but there is
// no parent segment so there's nothing to wait on.
@@ -8514,26 +8568,29 @@ function renderSuspenseBoundary(request, task, props) {
task.blockedSegment = contentRootSegment;
{
- setCurrentlyRenderingBoundaryResourcesTarget(request.resources, newBoundary.resources);
+ setCurrentlyRenderingBoundaryResourcesTarget(request.renderState, newBoundary.resources);
}
+ task.keyPath = keyPath;
+
try {
// We use the safe form because we don't handle suspending here. Only error handling.
- renderNode(request, task, content, 0);
- pushSegmentFinale(contentRootSegment.chunks, request.responseState, contentRootSegment.lastPushedText, contentRootSegment.textEmbedded);
+ renderNode(request, task, content, -1);
+ pushSegmentFinale(contentRootSegment.chunks, request.renderState, contentRootSegment.lastPushedText, contentRootSegment.textEmbedded);
contentRootSegment.status = COMPLETED;
queueCompletedSegment(newBoundary, contentRootSegment);
- if (newBoundary.pendingTasks === 0) {
- // This must have been the last segment we were waiting on. This boundary is now complete.
+ if (newBoundary.pendingTasks === 0 && newBoundary.status === PENDING) {
+ newBoundary.status = COMPLETED; // This must have been the last segment we were waiting on. This boundary is now complete.
// Therefore we won't need the fallback. We early return so that we don't have to create
// the fallback.
+
popComponentStackInDEV(task);
return;
}
} catch (error) {
contentRootSegment.status = ERRORED;
- newBoundary.forceClientRender = true;
+ newBoundary.status = CLIENT_RENDERED;
var errorDigest;
if (typeof error === 'object' && error !== null && error.$$typeof === REACT_POSTPONE_TYPE) {
@@ -8555,16 +8612,18 @@ function renderSuspenseBoundary(request, task, props) {
} finally {
{
- setCurrentlyRenderingBoundaryResourcesTarget(request.resources, parentBoundary ? parentBoundary.resources : null);
+ setCurrentlyRenderingBoundaryResourcesTarget(request.renderState, parentBoundary ? parentBoundary.resources : null);
}
task.blockedBoundary = parentBoundary;
task.blockedSegment = parentSegment;
+ task.keyPath = prevKeyPath;
} // We create suspended task for the fallback because we don't want to actually work
// on it yet in case we finish the main content, so we queue for later.
- var suspendedFallbackTask = createTask(request, null, fallback, parentBoundary, boundarySegment, fallbackAbortSet, task.keyPath, task.legacyContext, task.context, task.treeContext);
+ var suspendedFallbackTask = createTask(request, null, fallback, -1, parentBoundary, boundarySegment, fallbackAbortSet, // TODO: Should distinguish key path of fallback and primary tasks
+ keyPath, task.formatContext, task.legacyContext, task.context, task.treeContext);
{
suspendedFallbackTask.componentStack = task.componentStack;
@@ -8576,20 +8635,23 @@ function renderSuspenseBoundary(request, task, props) {
popComponentStackInDEV(task);
}
-function renderHostElement(request, task, type, props) {
+function renderHostElement(request, task, keyPath, type, props) {
pushBuiltInComponentStackInDEV(task, type);
var segment = task.blockedSegment;
- var children = pushStartInstance(segment.chunks, type, props, request.resources, request.responseState, segment.formatContext, segment.lastPushedText);
+ var children = pushStartInstance(segment.chunks, type, props, request.resumableState, request.renderState, task.formatContext, segment.lastPushedText);
segment.lastPushedText = false;
- var prevContext = segment.formatContext;
- segment.formatContext = getChildFormatContext(prevContext, type, props); // We use the non-destructive form because if something suspends, we still
+ var prevContext = task.formatContext;
+ var prevKeyPath = task.keyPath;
+ task.formatContext = getChildFormatContext(prevContext, type, props);
+ task.keyPath = keyPath; // We use the non-destructive form because if something suspends, we still
// need to pop back up and finish this subtree of HTML.
- renderNode(request, task, children, 0); // We expect that errors will fatal the whole task and that we don't need
+ renderNode(request, task, children, -1); // We expect that errors will fatal the whole task and that we don't need
// the correct context. Therefore this is not in a finally.
- segment.formatContext = prevContext;
- pushEndInstance(segment.chunks, type, props, request.responseState, prevContext);
+ task.formatContext = prevContext;
+ task.keyPath = prevKeyPath;
+ pushEndInstance(segment.chunks, type, props, request.resumableState, prevContext);
segment.lastPushedText = false;
popComponentStackInDEV(task);
}
@@ -8598,14 +8660,14 @@ function shouldConstruct(Component) {
return Component.prototype && Component.prototype.isReactComponent;
}
-function renderWithHooks(request, task, prevThenableState, Component, props, secondArg) {
+function renderWithHooks(request, task, keyPath, prevThenableState, Component, props, secondArg) {
var componentIdentity = {};
- prepareToUseHooks(task, componentIdentity, prevThenableState);
+ prepareToUseHooks(request, task, keyPath, componentIdentity, prevThenableState);
var result = Component(props, secondArg);
return finishHooks(Component, props, result, secondArg);
}
-function finishClassComponent(request, task, instance, Component, props) {
+function finishClassComponent(request, task, keyPath, instance, Component, props) {
var nextChildren = instance.render();
{
@@ -8625,21 +8687,24 @@ function finishClassComponent(request, task, instance, Component, props) {
var previousContext = task.legacyContext;
var mergedContext = processChildContext(instance, Component, previousContext, childContextTypes);
task.legacyContext = mergedContext;
- renderNodeDestructive(request, task, null, nextChildren, 0);
+ renderNodeDestructive(request, task, null, nextChildren, -1);
task.legacyContext = previousContext;
return;
}
}
- renderNodeDestructive(request, task, null, nextChildren, 0);
+ var prevKeyPath = task.keyPath;
+ task.keyPath = keyPath;
+ renderNodeDestructive(request, task, null, nextChildren, -1);
+ task.keyPath = prevKeyPath;
}
-function renderClassComponent(request, task, Component, props) {
+function renderClassComponent(request, task, keyPath, Component, props) {
pushClassComponentStackInDEV(task, Component);
var maskedContext = getMaskedContext(Component, task.legacyContext) ;
var instance = constructClassInstance(Component, props, maskedContext);
mountClassInstance(instance, Component, props, maskedContext);
- finishClassComponent(request, task, instance, Component, props);
+ finishClassComponent(request, task, keyPath, instance, Component, props);
popComponentStackInDEV(task);
}
@@ -8654,7 +8719,7 @@ var didWarnAboutMaps = false;
var hasWarnedAboutUsingContextAsConsumer = false; // This would typically be a function component but we still support module pattern
// components for some reason.
-function renderIndeterminateComponent(request, task, prevThenableState, Component, props) {
+function renderIndeterminateComponent(request, task, keyPath, prevThenableState, Component, props) {
var legacyContext;
{
@@ -8675,8 +8740,10 @@ function renderIndeterminateComponent(request, task, prevThenableState, Componen
}
}
- var value = renderWithHooks(request, task, prevThenableState, Component, props, legacyContext);
+ var value = renderWithHooks(request, task, keyPath, prevThenableState, Component, props, legacyContext);
var hasId = checkDidRenderIdHook();
+ var formStateCount = getFormStateCount();
+ var formStateMatchingIndex = getFormStateMatchingIndex();
{
// Support for module components is deprecated and is removed behind a flag.
@@ -8706,34 +8773,71 @@ function renderIndeterminateComponent(request, task, prevThenableState, Componen
}
mountClassInstance(value, Component, props, legacyContext);
- finishClassComponent(request, task, value, Component, props);
+ finishClassComponent(request, task, keyPath, value, Component, props);
} else {
{
validateFunctionComponentInDev(Component);
- } // We're now successfully past this task, and we don't have to pop back to
- // the previous task every again, so we can use the destructive recursive form.
+ }
+ finishFunctionComponent(request, task, keyPath, value, hasId, formStateCount, formStateMatchingIndex);
+ }
- if (hasId) {
- // This component materialized an id. We treat this as its own level, with
- // a single "child" slot.
- var prevTreeContext = task.treeContext;
- var totalChildren = 1;
- var index = 0;
- task.treeContext = pushTreeContext(prevTreeContext, totalChildren, index);
+ popComponentStackInDEV(task);
+}
- try {
- renderNodeDestructive(request, task, null, value, 0);
- } finally {
- task.treeContext = prevTreeContext;
+function finishFunctionComponent(request, task, keyPath, children, hasId, formStateCount, formStateMatchingIndex) {
+ var didEmitFormStateMarkers = false;
+
+ if (formStateCount !== 0 && request.formState !== null) {
+ // For each useFormState hook, emit a marker that indicates whether we
+ // rendered using the form state passed at the root. We only emit these
+ // markers if form state is passed at the root.
+ var segment = task.blockedSegment;
+
+ if (segment === null) ; else {
+ didEmitFormStateMarkers = true;
+ var target = segment.chunks;
+
+ for (var i = 0; i < formStateCount; i++) {
+ if (i === formStateMatchingIndex) {
+ pushFormStateMarkerIsMatching(target);
+ } else {
+ pushFormStateMarkerIsNotMatching(target);
+ }
}
- } else {
- renderNodeDestructive(request, task, null, value, 0);
}
}
- popComponentStackInDEV(task);
+ var prevKeyPath = task.keyPath;
+ task.keyPath = keyPath;
+
+ if (hasId) {
+ // This component materialized an id. We treat this as its own level, with
+ // a single "child" slot.
+ var prevTreeContext = task.treeContext;
+ var totalChildren = 1;
+ var index = 0; // Modify the id context. Because we'll need to reset this if something
+ // suspends or errors, we'll use the non-destructive render path.
+
+ task.treeContext = pushTreeContext(prevTreeContext, totalChildren, index);
+ renderNode(request, task, children, -1); // Like the other contexts, this does not need to be in a finally block
+ // because renderNode takes care of unwinding the stack.
+
+ task.treeContext = prevTreeContext;
+ } else if (didEmitFormStateMarkers) {
+ // If there were formState hooks, we must use the non-destructive path
+ // because this component is not a pure indirection; we emitted markers
+ // to the stream.
+ renderNode(request, task, children, -1);
+ } else {
+ // We're now successfully past this task, and we haven't modified the
+ // context stack. We don't have to pop back to the previous task every
+ // again, so we can use the destructive recursive form.
+ renderNodeDestructive(request, task, null, children, -1);
+ }
+
+ task.keyPath = prevKeyPath;
}
function validateFunctionComponentInDev(Component) {
@@ -8794,38 +8898,23 @@ function resolveDefaultProps(Component, baseProps) {
return baseProps;
}
-function renderForwardRef(request, task, prevThenableState, type, props, ref) {
+function renderForwardRef(request, task, keyPath, prevThenableState, type, props, ref) {
pushFunctionComponentStackInDEV(task, type.render);
- var children = renderWithHooks(request, task, prevThenableState, type.render, props, ref);
+ var children = renderWithHooks(request, task, keyPath, prevThenableState, type.render, props, ref);
var hasId = checkDidRenderIdHook();
-
- if (hasId) {
- // This component materialized an id. We treat this as its own level, with
- // a single "child" slot.
- var prevTreeContext = task.treeContext;
- var totalChildren = 1;
- var index = 0;
- task.treeContext = pushTreeContext(prevTreeContext, totalChildren, index);
-
- try {
- renderNodeDestructive(request, task, null, children, 0);
- } finally {
- task.treeContext = prevTreeContext;
- }
- } else {
- renderNodeDestructive(request, task, null, children, 0);
- }
-
+ var formStateCount = getFormStateCount();
+ var formStateMatchingIndex = getFormStateMatchingIndex();
+ finishFunctionComponent(request, task, keyPath, children, hasId, formStateCount, formStateMatchingIndex);
popComponentStackInDEV(task);
}
-function renderMemo(request, task, prevThenableState, type, props, ref) {
+function renderMemo(request, task, keyPath, prevThenableState, type, props, ref) {
var innerType = type.type;
var resolvedProps = resolveDefaultProps(innerType, props);
- renderElement(request, task, prevThenableState, innerType, resolvedProps, ref);
+ renderElement(request, task, keyPath, prevThenableState, innerType, resolvedProps, ref);
}
-function renderContextConsumer(request, task, context, props) {
+function renderContextConsumer(request, task, keyPath, context, props) {
// The logic below for Context differs depending on PROD or DEV mode. In
// DEV mode, we create a separate object for Context.Consumer that acts
// like a proxy to Context. This proxy object adds unnecessary code in PROD
@@ -8860,10 +8949,13 @@ function renderContextConsumer(request, task, context, props) {
var newValue = readContext$1(context);
var newChildren = render(newValue);
- renderNodeDestructive(request, task, null, newChildren, 0);
+ var prevKeyPath = task.keyPath;
+ task.keyPath = keyPath;
+ renderNodeDestructive(request, task, null, newChildren, -1);
+ task.keyPath = prevKeyPath;
}
-function renderContextProvider(request, task, type, props) {
+function renderContextProvider(request, task, keyPath, type, props) {
var context = type._context;
var value = props.value;
var children = props.children;
@@ -8873,9 +8965,12 @@ function renderContextProvider(request, task, type, props) {
prevSnapshot = task.context;
}
+ var prevKeyPath = task.keyPath;
task.context = pushProvider(context, value);
- renderNodeDestructive(request, task, null, children, 0);
+ task.keyPath = keyPath;
+ renderNodeDestructive(request, task, null, children, -1);
task.context = popProvider(context);
+ task.keyPath = prevKeyPath;
{
if (prevSnapshot !== task.context) {
@@ -8884,39 +8979,42 @@ function renderContextProvider(request, task, type, props) {
}
}
-function renderLazyComponent(request, task, prevThenableState, lazyComponent, props, ref) {
+function renderLazyComponent(request, task, keyPath, prevThenableState, lazyComponent, props, ref) {
pushBuiltInComponentStackInDEV(task, 'Lazy');
var payload = lazyComponent._payload;
var init = lazyComponent._init;
var Component = init(payload);
var resolvedProps = resolveDefaultProps(Component, props);
- renderElement(request, task, prevThenableState, Component, resolvedProps, ref);
+ renderElement(request, task, keyPath, prevThenableState, Component, resolvedProps, ref);
popComponentStackInDEV(task);
}
-function renderOffscreen(request, task, props) {
+function renderOffscreen(request, task, keyPath, props) {
var mode = props.mode;
if (mode === 'hidden') ; else {
// A visible Offscreen boundary is treated exactly like a fragment: a
// pure indirection.
- renderNodeDestructive(request, task, null, props.children, 0);
+ var prevKeyPath = task.keyPath;
+ task.keyPath = keyPath;
+ renderNodeDestructive(request, task, null, props.children, -1);
+ task.keyPath = prevKeyPath;
}
}
-function renderElement(request, task, prevThenableState, type, props, ref) {
+function renderElement(request, task, keyPath, prevThenableState, type, props, ref) {
if (typeof type === 'function') {
if (shouldConstruct(type)) {
- renderClassComponent(request, task, type, props);
+ renderClassComponent(request, task, keyPath, type, props);
return;
} else {
- renderIndeterminateComponent(request, task, prevThenableState, type, props);
+ renderIndeterminateComponent(request, task, keyPath, prevThenableState, type, props);
return;
}
}
if (typeof type === 'string') {
- renderHostElement(request, task, type, props);
+ renderHostElement(request, task, keyPath, type, props);
return;
}
@@ -8936,13 +9034,16 @@ function renderElement(request, task, prevThenableState, type, props, ref) {
case REACT_PROFILER_TYPE:
case REACT_FRAGMENT_TYPE:
{
- renderNodeDestructive(request, task, null, props.children, 0);
+ var prevKeyPath = task.keyPath;
+ task.keyPath = keyPath;
+ renderNodeDestructive(request, task, null, props.children, -1);
+ task.keyPath = prevKeyPath;
return;
}
case REACT_OFFSCREEN_TYPE:
{
- renderOffscreen(request, task, props);
+ renderOffscreen(request, task, keyPath, props);
return;
}
@@ -8950,7 +9051,10 @@ function renderElement(request, task, prevThenableState, type, props, ref) {
{
pushBuiltInComponentStackInDEV(task, 'SuspenseList'); // TODO: SuspenseList should control the boundaries.
- renderNodeDestructive(request, task, null, props.children, 0);
+ var _prevKeyPath = task.keyPath;
+ task.keyPath = keyPath;
+ renderNodeDestructive(request, task, null, props.children, -1);
+ task.keyPath = _prevKeyPath;
popComponentStackInDEV(task);
return;
}
@@ -8964,7 +9068,7 @@ function renderElement(request, task, prevThenableState, type, props, ref) {
case REACT_SUSPENSE_TYPE:
{
{
- renderSuspenseBoundary(request, task, props);
+ renderSuspenseBoundary(request, task, keyPath, props);
}
return;
@@ -8975,31 +9079,31 @@ function renderElement(request, task, prevThenableState, type, props, ref) {
switch (type.$$typeof) {
case REACT_FORWARD_REF_TYPE:
{
- renderForwardRef(request, task, prevThenableState, type, props, ref);
+ renderForwardRef(request, task, keyPath, prevThenableState, type, props, ref);
return;
}
case REACT_MEMO_TYPE:
{
- renderMemo(request, task, prevThenableState, type, props, ref);
+ renderMemo(request, task, keyPath, prevThenableState, type, props, ref);
return;
}
case REACT_PROVIDER_TYPE:
{
- renderContextProvider(request, task, type, props);
+ renderContextProvider(request, task, keyPath, type, props);
return;
}
case REACT_CONTEXT_TYPE:
{
- renderContextConsumer(request, task, type, props);
+ renderContextConsumer(request, task, keyPath, type, props);
return;
}
case REACT_LAZY_TYPE:
{
- renderLazyComponent(request, task, prevThenableState, type, props);
+ renderLazyComponent(request, task, keyPath, prevThenableState, type, props);
return;
}
}
@@ -9066,7 +9170,8 @@ prevThenableState, node, childIndex) {
function renderNodeDestructiveImpl(request, task, prevThenableState, node, childIndex) {
// Stash the node we're working on. We'll pick up from this task in case
// something suspends.
- task.node = node; // Handle object types
+ task.node = node;
+ task.childIndex = childIndex; // Handle object types
if (typeof node === 'object' && node !== null) {
switch (node.$$typeof) {
@@ -9078,10 +9183,8 @@ function renderNodeDestructiveImpl(request, task, prevThenableState, node, child
var props = element.props;
var ref = element.ref;
var name = getComponentNameFromType(type);
- var prevKeyPath = task.keyPath;
- task.keyPath = [task.keyPath, name, key == null ? childIndex : key];
- renderElement(request, task, prevThenableState, type, props, ref);
- task.keyPath = prevKeyPath;
+ var keyPath = [task.keyPath, name, key == null ? childIndex === -1 ? 0 : childIndex : key];
+ renderElement(request, task, keyPath, prevThenableState, type, props, ref);
return;
}
@@ -9182,13 +9285,13 @@ function renderNodeDestructiveImpl(request, task, prevThenableState, node, child
if (typeof node === 'string') {
var segment = task.blockedSegment;
- segment.lastPushedText = pushTextInstance(task.blockedSegment.chunks, node, request.responseState, segment.lastPushedText);
+ segment.lastPushedText = pushTextInstance(task.blockedSegment.chunks, node, request.renderState, segment.lastPushedText);
return;
}
if (typeof node === 'number') {
var _segment = task.blockedSegment;
- _segment.lastPushedText = pushTextInstance(task.blockedSegment.chunks, '' + node, request.responseState, _segment.lastPushedText);
+ _segment.lastPushedText = pushTextInstance(task.blockedSegment.chunks, '' + node, request.renderState, _segment.lastPushedText);
return;
}
@@ -9201,42 +9304,94 @@ function renderNodeDestructiveImpl(request, task, prevThenableState, node, child
function renderChildrenArray(request, task, children, childIndex) {
var prevKeyPath = task.keyPath;
+
+ if (childIndex !== -1) {
+ task.keyPath = [task.keyPath, '', childIndex];
+ }
+
+ var prevTreeContext = task.treeContext;
var totalChildren = children.length;
for (var i = 0; i < totalChildren; i++) {
- var prevTreeContext = task.treeContext;
- task.treeContext = pushTreeContext(prevTreeContext, totalChildren, i);
+ var node = children[i];
+ task.treeContext = pushTreeContext(prevTreeContext, totalChildren, i); // We need to use the non-destructive form so that we can safely pop back
+ // up and render the sibling if something suspends.
- try {
- var node = children[i];
+ renderNode(request, task, node, i);
+ } // Because this context is always set right before rendering every child, we
+ // only need to reset it to the previous value at the very end.
+
+
+ task.treeContext = prevTreeContext;
+ task.keyPath = prevKeyPath;
+}
+
+function trackPostpone(request, trackedPostpones, task, segment) {
+ segment.status = POSTPONED; // We know that this will leave a hole so we might as well assign an ID now.
+
+ segment.id = request.nextSegmentId++;
+ var boundary = task.blockedBoundary;
- if (isArray(node) || getIteratorFn(node)) {
- // Nested arrays behave like a "fragment node" which is keyed.
- // Therefore we need to add the current index as a parent key.
- task.keyPath = [task.keyPath, '', childIndex];
- } // We need to use the non-destructive form so that we can safely pop back
- // up and render the sibling if something suspends.
+ if (boundary !== null && boundary.status === PENDING) {
+ boundary.status = POSTPONED; // We need to eagerly assign it an ID because we'll need to refer to
+ // it before flushing and we know that we can't inline it.
+ boundary.id = assignSuspenseBoundaryID(request.renderState, request.resumableState);
+ boundary.rootSegmentID = request.nextSegmentId++;
+ var boundaryKeyPath = boundary.keyPath;
- renderNode(request, task, node, i);
- } finally {
- task.treeContext = prevTreeContext;
- task.keyPath = prevKeyPath;
+ if (boundaryKeyPath === null) {
+ throw new Error('It should not be possible to postpone at the root. This is a bug in React.');
}
+
+ var children = [];
+ var boundaryNode = [REPLAY_SUSPENSE_BOUNDARY, boundaryKeyPath[1], boundaryKeyPath[2], children, boundary.id, boundary.rootSegmentID];
+ trackedPostpones.workingMap.set(boundaryKeyPath, boundaryNode);
+ addToReplayParent(boundaryNode, boundaryKeyPath[0], trackedPostpones);
+ }
+
+ var keyPath = task.keyPath;
+
+ if (keyPath === null) {
+ throw new Error('It should not be possible to postpone at the root. This is a bug in React.');
+ }
+
+ if (task.childIndex === -1) {
+ // Resume at the position before the first array
+ var resumableElement = [RESUME_ELEMENT, keyPath[1], keyPath[2], segment.id];
+ addToReplayParent(resumableElement, keyPath[0], trackedPostpones);
+ } else {
+ // Resume at the slot within the array
+ var resumableNode = [RESUME_SLOT, task.childIndex, segment.id];
+ addToReplayParent(resumableNode, keyPath, trackedPostpones);
}
}
+function injectPostponedHole(request, task, reason) {
+ logPostpone(request, reason); // Something suspended, we'll need to create a new segment and resolve it later.
+
+ var segment = task.blockedSegment;
+ var insertionIndex = segment.chunks.length;
+ var newSegment = createPendingSegment(request, insertionIndex, null, task.formatContext, // Adopt the parent segment's leading text embed
+ segment.lastPushedText, // Assume we are text embedded at the trailing edge
+ true);
+ segment.children.push(newSegment); // Reset lastPushedText for current Segment since the new Segment "consumed" it
+
+ segment.lastPushedText = false;
+ return newSegment;
+}
+
function spawnNewSuspendedTask(request, task, thenableState, x) {
// Something suspended, we'll need to create a new segment and resolve it later.
var segment = task.blockedSegment;
var insertionIndex = segment.chunks.length;
- var newSegment = createPendingSegment(request, insertionIndex, null, segment.formatContext, // Adopt the parent segment's leading text embed
+ var newSegment = createPendingSegment(request, insertionIndex, null, task.formatContext, // Adopt the parent segment's leading text embed
segment.lastPushedText, // Assume we are text embedded at the trailing edge
true);
segment.children.push(newSegment); // Reset lastPushedText for current Segment since the new Segment "consumed" it
segment.lastPushedText = false;
- var newTask = createTask(request, thenableState, task.node, task.blockedBoundary, newSegment, task.abortSet, task.keyPath, task.legacyContext, task.context, task.treeContext);
+ var newTask = createTask(request, thenableState, task.node, task.childIndex, task.blockedBoundary, newSegment, task.abortSet, task.keyPath, task.formatContext, task.legacyContext, task.context, task.treeContext);
{
if (task.componentStack !== null) {
@@ -9260,10 +9415,11 @@ function renderNode(request, task, node, childIndex) {
var chunkLength = segment.chunks.length; // Snapshot the current context in case something throws to interrupt the
// process.
- var previousFormatContext = task.blockedSegment.formatContext;
+ var previousFormatContext = task.formatContext;
var previousLegacyContext = task.legacyContext;
var previousContext = task.context;
var previousKeyPath = task.keyPath;
+ var previousTreeContext = task.treeContext;
var previousComponentStack = null;
{
@@ -9282,44 +9438,76 @@ function renderNode(request, task, node, childIndex) {
// value to be a thenable, because before `use` existed that was the
// (unstable) API for suspending. This implementation detail can change
// later, once we deprecate the old API in favor of `use`.
- getSuspendedThenable() : thrownValue; // $FlowFixMe[method-unbinding]
+ getSuspendedThenable() : thrownValue;
- if (typeof x === 'object' && x !== null && typeof x.then === 'function') {
- var wakeable = x;
- var thenableState = getThenableStateAfterSuspending();
- spawnNewSuspendedTask(request, task, thenableState, wakeable); // Restore the context. We assume that this will be restored by the inner
- // functions in case nothing throws so we don't use "finally" here.
+ if (typeof x === 'object' && x !== null) {
+ // $FlowFixMe[method-unbinding]
+ if (typeof x.then === 'function') {
+ var wakeable = x;
+ var thenableState = getThenableStateAfterSuspending();
+ spawnNewSuspendedTask(request, task, thenableState, wakeable); // Restore the context. We assume that this will be restored by the inner
+ // functions in case nothing throws so we don't use "finally" here.
- task.blockedSegment.formatContext = previousFormatContext;
- task.legacyContext = previousLegacyContext;
- task.context = previousContext;
- task.keyPath = previousKeyPath; // Restore all active ReactContexts to what they were before.
+ task.formatContext = previousFormatContext;
+ task.legacyContext = previousLegacyContext;
+ task.context = previousContext;
+ task.keyPath = previousKeyPath;
+ task.treeContext = previousTreeContext; // Restore all active ReactContexts to what they were before.
- switchContext(previousContext);
+ switchContext(previousContext);
- {
- task.componentStack = previousComponentStack;
+ {
+ task.componentStack = previousComponentStack;
+ }
+
+ return;
}
- return;
- } else {
- // Restore the context. We assume that this will be restored by the inner
- // functions in case nothing throws so we don't use "finally" here.
- task.blockedSegment.formatContext = previousFormatContext;
- task.legacyContext = previousLegacyContext;
- task.context = previousContext;
- task.keyPath = previousKeyPath; // Restore all active ReactContexts to what they were before.
+ if (request.trackedPostpones !== null && x.$$typeof === REACT_POSTPONE_TYPE && task.blockedBoundary !== null // TODO: Support holes in the shell
+ ) {
+ // If we're tracking postpones, we inject a hole here and continue rendering
+ // sibling. Similar to suspending. If we're not tracking, we treat it more like
+ // an error. Notably this doesn't spawn a new task since nothing will fill it
+ // in during this prerender.
+ var postponeInstance = x;
+ var trackedPostpones = request.trackedPostpones;
+ var postponedSegment = injectPostponedHole(request, task, postponeInstance.message);
+ trackPostpone(request, trackedPostpones, task, postponedSegment); // Restore the context. We assume that this will be restored by the inner
+ // functions in case nothing throws so we don't use "finally" here.
- switchContext(previousContext);
+ task.formatContext = previousFormatContext;
+ task.legacyContext = previousLegacyContext;
+ task.context = previousContext;
+ task.keyPath = previousKeyPath;
+ task.treeContext = previousTreeContext; // Restore all active ReactContexts to what they were before.
- {
- task.componentStack = previousComponentStack;
- } // We assume that we don't need the correct context.
- // Let's terminate the rest of the tree and don't render any siblings.
+ switchContext(previousContext);
+ {
+ task.componentStack = previousComponentStack;
+ }
- throw x;
- }
+ return;
+ }
+ } // Restore the context. We assume that this will be restored by the inner
+ // functions in case nothing throws so we don't use "finally" here.
+
+
+ task.formatContext = previousFormatContext;
+ task.legacyContext = previousLegacyContext;
+ task.context = previousContext;
+ task.keyPath = previousKeyPath;
+ task.treeContext = previousTreeContext; // Restore all active ReactContexts to what they were before.
+
+ switchContext(previousContext);
+
+ {
+ task.componentStack = previousComponentStack;
+ } // We assume that we don't need the correct context.
+ // Let's terminate the rest of the tree and don't render any siblings.
+
+
+ throw x;
}
}
@@ -9341,8 +9529,8 @@ function erroredTask(request, boundary, segment, error) {
} else {
boundary.pendingTasks--;
- if (!boundary.forceClientRender) {
- boundary.forceClientRender = true;
+ if (boundary.status !== CLIENT_RENDERED) {
+ boundary.status = CLIENT_RENDERED;
boundary.errorDigest = errorDigest;
{
@@ -9398,8 +9586,8 @@ function abortTask(task, request, error) {
} else {
boundary.pendingTasks--;
- if (!boundary.forceClientRender) {
- boundary.forceClientRender = true;
+ if (boundary.status !== CLIENT_RENDERED) {
+ boundary.status = CLIENT_RENDERED;
boundary.errorDigest = request.onError(error);
{
@@ -9444,7 +9632,8 @@ function abortTask(task, request, error) {
}
function queueCompletedSegment(boundary, segment) {
- if (segment.chunks.length === 0 && segment.children.length === 1 && segment.children[0].boundary === null) {
+ if (segment.chunks.length === 0 && segment.children.length === 1 && segment.children[0].boundary === null && // Typically the id would not be assigned yet but if it's a postponed segment it might be.
+ segment.children[0].id === -1) {
// This is an empty segment. There's nothing to write, so we can instead transfer the ID
// to the child. That way any existing references point to the child.
var childSegment = segment.children[0];
@@ -9481,8 +9670,12 @@ function finishedTask(request, boundary, segment) {
} else {
boundary.pendingTasks--;
- if (boundary.forceClientRender) ; else if (boundary.pendingTasks === 0) {
- // This must have been the last segment we were waiting on. This boundary is now complete.
+ if (boundary.status === CLIENT_RENDERED) ; else if (boundary.pendingTasks === 0) {
+ if (boundary.status === PENDING) {
+ boundary.status = COMPLETED;
+ } // This must have been the last segment we were waiting on. This boundary is now complete.
+
+
if (segment.parentFlushed) {
// Our parent segment already flushed, so we need to schedule this segment to be emitted.
// If it is a segment that was aborted, we'll write other content instead so we don't need
@@ -9538,7 +9731,7 @@ function finishedTask(request, boundary, segment) {
function retryTask(request, task) {
{
var blockedBoundary = task.blockedBoundary;
- setCurrentlyRenderingBoundaryResourcesTarget(request.resources, blockedBoundary ? blockedBoundary.resources : null);
+ setCurrentlyRenderingBoundaryResourcesTarget(request.renderState, blockedBoundary ? blockedBoundary.resources : null);
}
var segment = task.blockedSegment;
@@ -9570,8 +9763,8 @@ function retryTask(request, task) {
// component suspends again, the thenable state will be restored.
var prevThenableState = task.thenableState;
task.thenableState = null;
- renderNodeDestructive(request, task, prevThenableState, task.node, 0);
- pushSegmentFinale(segment.chunks, request.responseState, segment.lastPushedText, segment.textEmbedded);
+ renderNodeDestructive(request, task, prevThenableState, task.node, task.childIndex);
+ pushSegmentFinale(segment.chunks, request.renderState, segment.lastPushedText, segment.textEmbedded);
task.abortSet.delete(task);
segment.status = COMPLETED;
finishedTask(request, task.blockedBoundary, segment);
@@ -9585,21 +9778,38 @@ function retryTask(request, task) {
// value to be a thenable, because before `use` existed that was the
// (unstable) API for suspending. This implementation detail can change
// later, once we deprecate the old API in favor of `use`.
- getSuspendedThenable() : thrownValue; // $FlowFixMe[method-unbinding]
-
- if (typeof x === 'object' && x !== null && typeof x.then === 'function') {
- // Something suspended again, let's pick it back up later.
- var ping = task.ping;
- x.then(ping, ping);
- task.thenableState = getThenableStateAfterSuspending();
- } else {
- task.abortSet.delete(task);
- segment.status = ERRORED;
- erroredTask(request, task.blockedBoundary, segment, x);
+ getSuspendedThenable() : thrownValue;
+
+ if (typeof x === 'object' && x !== null) {
+ // $FlowFixMe[method-unbinding]
+ if (typeof x.then === 'function') {
+ // Something suspended again, let's pick it back up later.
+ var ping = task.ping;
+ x.then(ping, ping);
+ task.thenableState = getThenableStateAfterSuspending();
+ return;
+ } else if (request.trackedPostpones !== null && x.$$typeof === REACT_POSTPONE_TYPE && task.blockedBoundary !== null // TODO: Support holes in the shell
+ ) {
+ // If we're tracking postpones, we mark this segment as postponed and finish
+ // the task without filling it in. If we're not tracking, we treat it more like
+ // an error.
+ var trackedPostpones = request.trackedPostpones;
+ task.abortSet.delete(task);
+ var postponeInstance = x;
+ logPostpone(request, postponeInstance.message);
+ trackPostpone(request, trackedPostpones, task, segment);
+ finishedTask(request, task.blockedBoundary, segment);
+ return;
+ }
}
+
+ task.abortSet.delete(task);
+ segment.status = ERRORED;
+ erroredTask(request, task.blockedBoundary, segment, x);
+ return;
} finally {
{
- setCurrentlyRenderingBoundaryResourcesTarget(request.resources, null);
+ setCurrentlyRenderingBoundaryResourcesTarget(request.renderState, null);
}
{
@@ -9632,8 +9842,8 @@ function performWork(request) {
ReactDebugCurrentFrame.getCurrentStack = getCurrentStackInDEV;
}
- var prevResponseState = currentResponseState;
- setCurrentResponseState(request.responseState);
+ var prevResumableState = currentResumableState;
+ setCurrentResumableState(request.resumableState);
try {
var pingedTasks = request.pingedTasks;
@@ -9653,7 +9863,7 @@ function performWork(request) {
logRecoverableError(request, error);
fatalError(request, error);
} finally {
- setCurrentResponseState(prevResponseState);
+ setCurrentResumableState(prevResumableState);
ReactCurrentDispatcher.current = prevDispatcher;
{
@@ -9687,11 +9897,16 @@ function flushSubtree(request, destination, segment) {
{
// We're emitting a placeholder for this segment to be filled in later.
// Therefore we'll need to assign it an ID - to refer to it by.
- var segmentID = segment.id = request.nextSegmentId++; // When this segment finally completes it won't be embedded in text since it will flush separately
+ segment.id = request.nextSegmentId++; // Fallthrough
+ }
+
+ case POSTPONED:
+ {
+ var segmentID = segment.id; // When this segment finally completes it won't be embedded in text since it will flush separately
segment.lastPushedText = false;
segment.textEmbedded = false;
- return writePlaceholder(destination, request.responseState, segmentID);
+ return writePlaceholder(destination, request.renderState, segmentID);
}
case COMPLETED:
@@ -9742,26 +9957,30 @@ function flushSegment(request, destination, segment) {
boundary.parentFlushed = true; // This segment is a Suspense boundary. We need to decide whether to
// emit the content or the fallback now.
- if (boundary.forceClientRender) {
+ if (boundary.status === CLIENT_RENDERED) {
// Emit a client rendered suspense boundary wrapper.
// We never queue the inner boundary so we'll never emit its content or partial segments.
- writeStartClientRenderedSuspenseBoundary(destination, request.responseState, boundary.errorDigest, boundary.errorMessage, boundary.errorComponentStack); // Flush the fallback.
+ writeStartClientRenderedSuspenseBoundary(destination, request.renderState, boundary.errorDigest, boundary.errorMessage, boundary.errorComponentStack); // Flush the fallback.
flushSubtree(request, destination, segment);
- return writeEndClientRenderedSuspenseBoundary(destination, request.responseState);
- } else if (boundary.pendingTasks > 0) {
- // This boundary is still loading. Emit a pending suspense boundary wrapper.
- // Assign an ID to refer to the future content by.
- boundary.rootSegmentID = request.nextSegmentId++;
+ return writeEndClientRenderedSuspenseBoundary(destination, request.renderState);
+ } else if (boundary.status !== COMPLETED) {
+ if (boundary.status === PENDING) {
+ // For pending boundaries we lazily assign an ID to the boundary
+ // and root segment.
+ boundary.id = assignSuspenseBoundaryID(request.renderState, request.resumableState);
+ boundary.rootSegmentID = request.nextSegmentId++;
+ }
if (boundary.completedSegments.length > 0) {
// If this is at least partially complete, we can queue it to be partially emitted early.
request.partialBoundaries.push(boundary);
- } /// This is the first time we should have referenced this ID.
+ } // This boundary is still loading. Emit a pending suspense boundary wrapper.
+ /// This is the first time we should have referenced this ID.
- var id = boundary.id = assignSuspenseBoundaryID(request.responseState);
- writeStartPendingSuspenseBoundary(destination, request.responseState, id); // Flush the fallback.
+ var id = boundary.id;
+ writeStartPendingSuspenseBoundary(destination, request.renderState, id); // Flush the fallback.
flushSubtree(request, destination, segment);
return writeEndPendingSuspenseBoundary(destination);
@@ -9775,17 +9994,17 @@ function flushSegment(request, destination, segment) {
boundary.rootSegmentID = request.nextSegmentId++;
request.completedBoundaries.push(boundary); // Emit a pending rendered suspense boundary wrapper.
- writeStartPendingSuspenseBoundary(destination, request.responseState, boundary.id); // Flush the fallback.
+ writeStartPendingSuspenseBoundary(destination, request.renderState, boundary.id); // Flush the fallback.
flushSubtree(request, destination, segment);
return writeEndPendingSuspenseBoundary(destination);
} else {
{
- hoistResources(request.resources, boundary.resources);
+ hoistResources(request.renderState, boundary.resources);
} // We can inline this boundary's content as a complete boundary.
- writeStartCompletedSuspenseBoundary(destination, request.responseState);
+ writeStartCompletedSuspenseBoundary(destination, request.renderState);
var completedSegments = boundary.completedSegments;
if (completedSegments.length !== 1) {
@@ -9794,23 +10013,23 @@ function flushSegment(request, destination, segment) {
var contentSegment = completedSegments[0];
flushSegment(request, destination, contentSegment);
- return writeEndCompletedSuspenseBoundary(destination, request.responseState);
+ return writeEndCompletedSuspenseBoundary(destination, request.renderState);
}
}
function flushClientRenderedBoundary(request, destination, boundary) {
- return writeClientRenderBoundaryInstruction(destination, request.responseState, boundary.id, boundary.errorDigest, boundary.errorMessage, boundary.errorComponentStack);
+ return writeClientRenderBoundaryInstruction(destination, request.resumableState, request.renderState, boundary.id, boundary.errorDigest, boundary.errorMessage, boundary.errorComponentStack);
}
function flushSegmentContainer(request, destination, segment) {
- writeStartSegment(destination, request.responseState, segment.formatContext, segment.id);
+ writeStartSegment(destination, request.renderState, segment.parentFormatContext, segment.id);
flushSegment(request, destination, segment);
- return writeEndSegment(destination, segment.formatContext);
+ return writeEndSegment(destination, segment.parentFormatContext);
}
function flushCompletedBoundary(request, destination, boundary) {
{
- setCurrentlyRenderingBoundaryResourcesTarget(request.resources, boundary.resources);
+ setCurrentlyRenderingBoundaryResourcesTarget(request.renderState, boundary.resources);
}
var completedSegments = boundary.completedSegments;
@@ -9824,15 +10043,15 @@ function flushCompletedBoundary(request, destination, boundary) {
completedSegments.length = 0;
{
- writeResourcesForBoundary(destination, boundary.resources, request.responseState);
+ writeResourcesForBoundary(destination, boundary.resources, request.renderState);
}
- return writeCompletedBoundaryInstruction(destination, request.responseState, boundary.id, boundary.rootSegmentID, boundary.resources);
+ return writeCompletedBoundaryInstruction(destination, request.resumableState, request.renderState, boundary.id, boundary.rootSegmentID, boundary.resources);
}
function flushPartialBoundary(request, destination, boundary) {
{
- setCurrentlyRenderingBoundaryResourcesTarget(request.resources, boundary.resources);
+ setCurrentlyRenderingBoundaryResourcesTarget(request.renderState, boundary.resources);
}
var completedSegments = boundary.completedSegments;
@@ -9857,7 +10076,7 @@ function flushPartialBoundary(request, destination, boundary) {
// 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(destination, boundary.resources, request.responseState);
+ return writeResourcesForBoundary(destination, boundary.resources, request.renderState);
}
}
@@ -9878,10 +10097,14 @@ function flushPartiallyCompletedSegment(request, destination, boundary, segment)
throw new Error('A root segment ID must have been assigned by now. This is a bug in React.');
}
+ return flushSegmentContainer(request, destination, segment);
+ } 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);
} else {
flushSegmentContainer(request, destination, segment);
- return writeCompletedSegmentInstruction(destination, request.responseState, segmentID);
+ return writeCompletedSegmentInstruction(destination, request.resumableState, request.renderState, segmentID);
}
}
@@ -9898,12 +10121,12 @@ function flushCompletedQueues(request, destination) {
if (completedRootSegment !== null) {
if (request.pendingRootTasks === 0) {
if (enableFloat) {
- writePreamble(destination, request.resources, request.responseState, request.allPendingTasks === 0);
+ writePreamble(destination, request.resumableState, request.renderState, request.allPendingTasks === 0);
}
flushSegment(request, destination, completedRootSegment);
request.completedRootSegment = null;
- writeCompletedRoot(destination, request.responseState);
+ writeCompletedRoot(destination, request.resumableState);
} else {
// We haven't flushed the root yet so we don't need to check any other branches further down
return;
@@ -9914,7 +10137,7 @@ function flushCompletedQueues(request, destination) {
}
if (enableFloat) {
- writeHoistables(destination, request.resources, request.responseState);
+ writeHoistables(destination, request.resumableState, request.renderState);
} // We emit client rendering instructions for already emitted boundaries first.
// This is so that we can signal to the client to start client rendering them as
// soon as possible.
@@ -9996,7 +10219,11 @@ function flushCompletedQueues(request, destination) {
request.flushScheduled = false;
{
- writePostamble(destination, request.responseState);
+ // We write the trailing tags but only if don't have any data to resume.
+ // If we need to resume we'll write the postamble in the resume instead.
+ if (request.trackedPostpones === null || request.trackedPostpones.root.length === 0) {
+ writePostamble(destination, request.resumableState);
+ }
}
{
@@ -10083,14 +10310,34 @@ function abort(request, reason) {
function flushResources(request) {
enqueueFlush(request);
}
-function getResources(request) {
- return request.resources;
+function getFormState(request) {
+ return request.formState;
+}
+function getResumableState(request) {
+ return request.resumableState;
}
+function addToReplayParent(node, parentKeyPath, trackedPostpones) {
+ if (parentKeyPath === null) {
+ trackedPostpones.root.push(node);
+ } else {
+ var workingMap = trackedPostpones.workingMap;
+ var parentNode = workingMap.get(parentKeyPath);
+
+ if (parentNode === undefined) {
+ parentNode = [REPLAY_NODE, parentKeyPath[1], parentKeyPath[2], []];
+ workingMap.set(parentKeyPath, parentNode);
+ addToReplayParent(parentNode, parentKeyPath[0], trackedPostpones);
+ }
+
+ parentNode[3].push(node);
+ }
+} // Returns the state of a postponed request or null if nothing was postponed.
+
function onError() {// Non-fatal errors are ignored.
}
-function renderToStringImpl(children, options, generateStaticMarkup, abortReason, unstable_externalRuntimeSrc) {
+function renderToStringImpl(children, options, generateStaticMarkup, abortReason) {
var didFatal = false;
var fatalError = null;
var result = '';
@@ -10115,8 +10362,8 @@ function renderToStringImpl(children, options, generateStaticMarkup, abortReason
readyToStream = true;
}
- var resources = createResources();
- var request = createRequest(children, resources, createResponseState(resources, generateStaticMarkup, options ? options.identifierPrefix : undefined, unstable_externalRuntimeSrc), createRootFormatContext(), Infinity, onError, undefined, onShellReady, undefined, undefined, undefined);
+ var resumableState = createResumableState(options ? options.identifierPrefix : undefined, undefined, undefined, undefined, undefined, undefined);
+ var request = createRequest(children, resumableState, createRenderState(resumableState, undefined, generateStaticMarkup), createRootFormatContext(), Infinity, onError, undefined, onShellReady, undefined, undefined, undefined);
startWork(request); // If anything suspended and is still pending, we'll abort it before writing.
// That way we write only client-rendered boundaries from the start.
diff --git a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.production.min.js b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.production.min.js
index 1fd88592e6fc2a..580536f8e55132 100644
--- a/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.production.min.js
+++ b/packages/next/src/compiled/react-dom-experimental/cjs/react-dom-server-legacy.browser.production.min.js
@@ -7,142 +7,152 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
-'use strict';var ca=require("next/dist/compiled/react-experimental"),da=require("react-dom");function l(a){for(var b="https://reactjs.org/docs/error-decoder.html?invariant="+a,c=1;c]/;
-function t(a){if("boolean"===typeof a||"number"===typeof a)return""+a;a=""+a;var b=ya.exec(a);if(b){var c="",d,e=0;for(d=b.index;d")}
-function tb(a,b,c,d,e,g,f){var h=null;"function"===typeof c&&("function"===typeof c.$$FORM_ACTION?(d=qb(b),b=c.$$FORM_ACTION(d),f=b.name,c=b.action||"",d=b.encType,e=b.method,g=b.target,h=b.data):(a.push(" ","formAction",'="',rb,'"'),g=e=d=c=f=null,ub(b)));null!=f&&z(a,"name",f);null!=c&&z(a,"formAction",c);null!=d&&z(a,"formEncType",d);null!=e&&z(a,"formMethod",e);null!=g&&z(a,"formTarget",g);return h}
-function z(a,b,c){switch(b){case "className":v(a,"class",c);break;case "tabIndex":v(a,"tabindex",c);break;case "dir":case "role":case "viewBox":case "width":case "height":v(a,b,c);break;case "style":ob(a,c);break;case "src":case "href":if(""===c)break;case "action":case "formAction":if(null==c||"function"===typeof c||"symbol"===typeof c||"boolean"===typeof c)break;a.push(" ",b,'="',t(""+c),'"');break;case "defaultValue":case "defaultChecked":case "innerHTML":case "suppressContentEditableWarning":case "suppressHydrationWarning":break;
-case "autoFocus":case "multiple":case "muted":pb(a,b.toLowerCase(),c);break;case "xlinkHref":if("function"===typeof c||"symbol"===typeof c||"boolean"===typeof c)break;a.push(" ","xlink:href",'="',t(""+c),'"');break;case "contentEditable":case "spellCheck":case "draggable":case "value":case "autoReverse":case "externalResourcesRequired":case "focusable":case "preserveAlpha":"function"!==typeof c&&"symbol"!==typeof c&&a.push(" ",b,'="',t(c),'"');break;case "allowFullScreen":case "async":case "autoPlay":case "controls":case "default":case "defer":case "disabled":case "disablePictureInPicture":case "disableRemotePlayback":case "formNoValidate":case "hidden":case "loop":case "noModule":case "noValidate":case "open":case "playsInline":case "readOnly":case "required":case "reversed":case "scoped":case "seamless":case "itemScope":c&&
-"function"!==typeof c&&"symbol"!==typeof c&&a.push(" ",b,'=""');break;case "capture":case "download":!0===c?a.push(" ",b,'=""'):!1!==c&&"function"!==typeof c&&"symbol"!==typeof c&&a.push(" ",b,'="',t(c),'"');break;case "cols":case "rows":case "size":case "span":"function"!==typeof c&&"symbol"!==typeof c&&!isNaN(c)&&1<=c&&a.push(" ",b,'="',t(c),'"');break;case "rowSpan":case "start":"function"===typeof c||"symbol"===typeof c||isNaN(c)||a.push(" ",b,'="',t(c),'"');break;case "xlinkActuate":v(a,"xlink:actuate",
-c);break;case "xlinkArcrole":v(a,"xlink:arcrole",c);break;case "xlinkRole":v(a,"xlink:role",c);break;case "xlinkShow":v(a,"xlink:show",c);break;case "xlinkTitle":v(a,"xlink:title",c);break;case "xlinkType":v(a,"xlink:type",c);break;case "xmlBase":v(a,"xml:base",c);break;case "xmlLang":v(a,"xml:lang",c);break;case "xmlSpace":v(a,"xml:space",c);break;default:if(!(2"))}
-function wb(a,b,c,d,e,g,f){var h=b.rel,k=b.href,p=b.precedence;if(3===g||f||null!=b.itemProp||"string"!==typeof h||"string"!==typeof k||""===k)return B(a,b),null;if("stylesheet"===b.rel){c="[style]"+k;if("string"!==typeof p||null!=b.disabled||b.onLoad||b.onError)return B(a,b);g=d.stylesMap.get(c);g||(b=ea({},b,{"data-precedence":b.precedence,precedence:null}),g=d.preloadsMap.get(c),f=0,g&&(g.state|=4,h=g.props,null==b.crossOrigin&&(b.crossOrigin=h.crossOrigin),null==b.integrity&&(b.integrity=h.integrity),
-g.state&3&&(f=8)),g={type:"stylesheet",chunks:[],state:f,props:b},d.stylesMap.set(c,g),b=d.precedences.get(p),b||(b=new Set,d.precedences.set(p,b),c={type:"style",chunks:[],state:0,props:{precedence:p,hrefs:[]}},b.add(c),d.stylePrecedences.set(p,c)),b.add(g));d.boundaryResources&&d.boundaryResources.add(g);e&&a.push("\x3c!-- --\x3e");return null}if(b.onLoad||b.onError)return B(a,b);e&&a.push("\x3c!-- --\x3e");switch(b.rel){case "preconnect":case "dns-prefetch":return B(c.preconnectChunks,b);case "preload":return B(c.preloadChunks,
-b);default:return B(c.hoistableChunks,b)}}function B(a,b){a.push(D("link"));for(var c in b)if(q.call(b,c)){var d=b[c];if(null!=d)switch(c){case "children":case "dangerouslySetInnerHTML":throw Error(l(399,"link"));default:z(a,c,d)}}a.push("/>");return null}function xb(a,b,c){var d="";"string"===typeof b&&""!==b?(d+="["+b+"]","string"===typeof c&&(d+="["+c+"]")):d+="[][]"+a;return"[image]"+d}
-function yb(a,b,c){a.push(D(c));for(var d in b)if(q.call(b,d)){var e=b[d];if(null!=e)switch(d){case "children":case "dangerouslySetInnerHTML":throw Error(l(399,c));default:z(a,d,e)}}a.push("/>");return null}
-function zb(a,b){a.push(D("title"));var c=null,d=null,e;for(e in b)if(q.call(b,e)){var g=b[e];if(null!=g)switch(e){case "children":c=g;break;case "dangerouslySetInnerHTML":d=g;break;default:z(a,e,g)}}a.push(">");b=Array.isArray(c)?2>c.length?c[0]:null:c;"function"!==typeof b&&"symbol"!==typeof b&&null!==b&&void 0!==b&&a.push(t(""+b));A(a,d,c);a.push("","title",">");return null}
-function Ab(a,b){a.push(D("script"));var c=null,d=null,e;for(e in b)if(q.call(b,e)){var g=b[e];if(null!=g)switch(e){case "children":c=g;break;case "dangerouslySetInnerHTML":d=g;break;default:z(a,e,g)}}a.push(">");A(a,d,c);"string"===typeof c&&a.push(t(c));a.push("","script",">");return null}
-function Bb(a,b,c){a.push(D(c));var d=c=null,e;for(e in b)if(q.call(b,e)){var g=b[e];if(null!=g)switch(e){case "children":c=g;break;case "dangerouslySetInnerHTML":d=g;break;default:z(a,e,g)}}a.push(">");A(a,d,c);return"string"===typeof c?(a.push(t(c)),null):c}var Cb=/^[a-zA-Z][a-zA-Z:_\.\-\d]*$/,Jb=new Map;function D(a){var b=Jb.get(a);if(void 0===b){if(!Cb.test(a))throw Error(l(65,a));b="<"+a;Jb.set(a,b)}return b}
-function Kb(a,b,c,d,e,g,f){switch(b){case "div":case "span":case "svg":case "path":case "a":case "g":case "p":case "li":break;case "select":a.push(D("select"));var h=null,k=null,p;for(p in c)if(q.call(c,p)){var r=c[p];if(null!=r)switch(p){case "children":h=r;break;case "dangerouslySetInnerHTML":k=r;break;case "defaultValue":case "value":break;default:z(a,p,r)}}a.push(">");A(a,k,h);return h;case "option":var m=g.selectedValue;a.push(D("option"));var O=null,S=null,X=null,L=null,M;for(M in c)if(q.call(c,
-M)){var n=c[M];if(null!=n)switch(M){case "children":O=n;break;case "selected":X=n;break;case "dangerouslySetInnerHTML":L=n;break;case "value":S=n;default:z(a,M,n)}}if(null!=m){var E=null!==S?""+S:vb(O);if(Ba(m))for(var C=0;C");A(a,L,O);return O;case "textarea":a.push(D("textarea"));var w=null,T=null,x=null,I;for(I in c)if(q.call(c,I)){var y=c[I];if(null!=y)switch(I){case "children":x=
-y;break;case "value":w=y;break;case "defaultValue":T=y;break;case "dangerouslySetInnerHTML":throw Error(l(91));default:z(a,I,y)}}null===w&&null!==T&&(w=T);a.push(">");if(null!=x){if(null!=w)throw Error(l(92));if(Ba(x)&&1");null!==ia&&ia.forEach(sb,a);return null;case "button":a.push(D("button"));
-var Q=null,ja=null,ka=null,Ha=null,la=null,kc=null,lc=null,Ia;for(Ia in c)if(q.call(c,Ia)){var V=c[Ia];if(null!=V)switch(Ia){case "children":Q=V;break;case "dangerouslySetInnerHTML":ja=V;break;case "name":ka=V;break;case "formAction":Ha=V;break;case "formEncType":la=V;break;case "formMethod":kc=V;break;case "formTarget":lc=V;break;default:z(a,Ia,V)}}var mc=tb(a,e,Ha,la,kc,lc,ka);a.push(">");null!==mc&&mc.forEach(sb,a);A(a,ja,Q);if("string"===typeof Q){a.push(t(Q));var nc=null}else nc=Q;return nc;
-case "form":a.push(D("form"));var Ja=null,oc=null,Z=null,Ka=null,La=null,Ma=null,Na;for(Na in c)if(q.call(c,Na)){var aa=c[Na];if(null!=aa)switch(Na){case "children":Ja=aa;break;case "dangerouslySetInnerHTML":oc=aa;break;case "action":Z=aa;break;case "encType":Ka=aa;break;case "method":La=aa;break;case "target":Ma=aa;break;default:z(a,Na,aa)}}var Db=null,Eb=null;if("function"===typeof Z)if("function"===typeof Z.$$FORM_ACTION){var Td=qb(e),va=Z.$$FORM_ACTION(Td);Z=va.action||"";Ka=va.encType;La=va.method;
-Ma=va.target;Db=va.data;Eb=va.name}else a.push(" ","action",'="',rb,'"'),Ma=La=Ka=Z=null,ub(e);null!=Z&&z(a,"action",Z);null!=Ka&&z(a,"encType",Ka);null!=La&&z(a,"method",La);null!=Ma&&z(a,"target",Ma);a.push(">");null!==Eb&&(a.push('"),null!==Db&&Db.forEach(sb,a));A(a,oc,Ja);if("string"===typeof Ja){a.push(t(Ja));var pc=null}else pc=Ja;return pc;case "menuitem":a.push(D("menuitem"));for(var db in c)if(q.call(c,db)){var qc=c[db];if(null!=qc)switch(db){case "children":case "dangerouslySetInnerHTML":throw Error(l(400));
-default:z(a,db,qc)}}a.push(">");return null;case "title":if(3===g.insertionMode||g.noscriptTagInScope||null!=c.itemProp)var rc=zb(a,c);else zb(e.hoistableChunks,c),rc=null;return rc;case "link":return wb(a,c,e,d,f,g.insertionMode,g.noscriptTagInScope);case "script":var Fb=c.async;if("string"!==typeof c.src||!c.src||!Fb||"function"===typeof Fb||"symbol"===typeof Fb||c.onLoad||c.onError||3===g.insertionMode||g.noscriptTagInScope||null!=c.itemProp)var sc=Ab(a,c);else{var Gb="[script]"+c.src,Oa=d.scriptsMap.get(Gb);
-if(!Oa){Oa={type:"script",chunks:[],state:0,props:null};d.scriptsMap.set(Gb,Oa);d.scripts.add(Oa);var tc=c,eb=d.preloadsMap.get(Gb);if(eb){eb.state|=4;var fb=tc=ea({},c),uc=eb.props;null==fb.crossOrigin&&(fb.crossOrigin=uc.crossOrigin);null==fb.integrity&&(fb.integrity=uc.integrity)}Ab(Oa.chunks,tc)}f&&a.push("\x3c!-- --\x3e");sc=null}return sc;case "style":var Pa=c.precedence,Qa=c.href;if(3===g.insertionMode||g.noscriptTagInScope||null!=c.itemProp||"string"!==typeof Pa||"string"!==typeof Qa||""===
-Qa){a.push(D("style"));var wa=null,vc=null,Ra;for(Ra in c)if(q.call(c,Ra)){var gb=c[Ra];if(null!=gb)switch(Ra){case "children":wa=gb;break;case "dangerouslySetInnerHTML":vc=gb;break;default:z(a,Ra,gb)}}a.push(">");var Sa=Array.isArray(wa)?2>wa.length?wa[0]:null:wa;"function"!==typeof Sa&&"symbol"!==typeof Sa&&null!==Sa&&void 0!==Sa&&a.push(t(""+Sa));A(a,vc,wa);a.push("","style",">");var wc=null}else{var xc="[style]"+Qa,W=d.stylesMap.get(xc);if(!W){if(W=d.stylePrecedences.get(Pa))W.props.hrefs.push(Qa);
-else{W={type:"style",chunks:[],state:0,props:{precedence:Pa,hrefs:[Qa]}};d.stylePrecedences.set(Pa,W);var yc=new Set;yc.add(W);d.precedences.set(Pa,yc)}d.stylesMap.set(xc,W);d.boundaryResources&&d.boundaryResources.add(W);var zc=W.chunks,xa=null,Ac=null,hb;for(hb in c)if(q.call(c,hb)){var Hb=c[hb];if(null!=Hb)switch(hb){case "children":xa=Hb;break;case "dangerouslySetInnerHTML":Ac=Hb}}var Ta=Array.isArray(xa)?2>xa.length?xa[0]:null:xa;"function"!==typeof Ta&&"symbol"!==typeof Ta&&null!==Ta&&void 0!==
-Ta&&zc.push(t(""+Ta));A(zc,Ac,xa)}f&&a.push("\x3c!-- --\x3e");wc=void 0}return wc;case "meta":if(3===g.insertionMode||g.noscriptTagInScope||null!=c.itemProp)var Bc=yb(a,c,"meta");else f&&a.push("\x3c!-- --\x3e"),Bc="string"===typeof c.charSet?yb(e.charsetChunks,c,"meta"):"viewport"===c.name?yb(e.preconnectChunks,c,"meta"):yb(e.hoistableChunks,c,"meta");return Bc;case "listing":case "pre":a.push(D(b));var Ua=null,Va=null,Wa;for(Wa in c)if(q.call(c,Wa)){var ib=c[Wa];if(null!=ib)switch(Wa){case "children":Ua=
-ib;break;case "dangerouslySetInnerHTML":Va=ib;break;default:z(a,Wa,ib)}}a.push(">");if(null!=Va){if(null!=Ua)throw Error(l(60));if("object"!==typeof Va||!("__html"in Va))throw Error(l(61));var ma=Va.__html;null!==ma&&void 0!==ma&&("string"===typeof ma&&0d.highImagePreloads.size?d.highImagePreloads.add(na):d.bulkPreloads.add(na)}return yb(a,c,"img");case "base":case "area":case "br":case "col":case "embed":case "hr":case "keygen":case "param":case "source":case "track":case "wbr":return yb(a,c,b);case "annotation-xml":case "color-profile":case "font-face":case "font-face-src":case "font-face-uri":case "font-face-format":case "font-face-name":case "missing-glyph":break;
-case "head":if(2>g.insertionMode&&null===e.headChunks){e.headChunks=[];var Ec=Bb(e.headChunks,c,"head")}else Ec=Bb(a,c,"head");return Ec;case "html":if(0===g.insertionMode&&null===e.htmlChunks){e.htmlChunks=[""];var Fc=Bb(e.htmlChunks,c,"html")}else Fc=Bb(a,c,"html");return Fc;default:if(-1!==b.indexOf("-")){a.push(D(b));var Ib=null,Gc=null,ba;for(ba in c)if(q.call(c,ba)){var N=c[ba];if(null!=N&&"function"!==typeof N&&"object"!==typeof N&&!1!==N)switch(!0===N&&(N=""),"className"===
-ba&&(ba="class"),ba){case "children":Ib=N;break;case "dangerouslySetInnerHTML":Gc=N;break;case "style":ob(a,N);break;case "suppressContentEditableWarning":case "suppressHydrationWarning":break;default:ra(ba)&&"function"!==typeof N&&"symbol"!==typeof N&&a.push(" ",ba,'="',t(N),'"')}}a.push(">");A(a,Gc,Ib);return Ib}}return Bb(a,c,b)}function Lb(a,b){b=b.bootstrapChunks;for(var c=0;c')}
-function Nb(a,b,c,d){switch(c.insertionMode){case 0:case 1:case 2:return a.push('