diff options
author | 2022-10-31 22:10:28 -0700 | |
---|---|---|
committer | 2022-10-31 22:10:28 -0700 | |
commit | 3a60764f32bf7aaf3d2ec6cb84d81e8384bd2417 (patch) | |
tree | 1f5cc98c77b62510e94773735a967069a26e8cad /test/bun.js/react-dom-server.bun.js | |
parent | 5398ed52d8a0592b4511f8c0c03391dd06e770b2 (diff) | |
download | bun-3a60764f32bf7aaf3d2ec6cb84d81e8384bd2417.tar.gz bun-3a60764f32bf7aaf3d2ec6cb84d81e8384bd2417.tar.zst bun-3a60764f32bf7aaf3d2ec6cb84d81e8384bd2417.zip |
Update React fizz server (#1432)
* Update fizz server
* Use production build
Co-authored-by: Colin McDonnell <colinmcd@alum.mit.edu>
Diffstat (limited to '')
-rw-r--r-- | test/bun.js/react-dom-server.bun.js | 8436 |
1 files changed, 6686 insertions, 1750 deletions
diff --git a/test/bun.js/react-dom-server.bun.js b/test/bun.js/react-dom-server.bun.js index 0285da36f..e5e03dcd2 100644 --- a/test/bun.js/react-dom-server.bun.js +++ b/test/bun.js/react-dom-server.bun.js @@ -1,1883 +1,6819 @@ /** * @license React - * react-dom-server.browser.production.min.js + * react-dom-server.bun.production.js * - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ -var aa = require("react"); -function k(a) { - for ( - var b = "https://reactjs.org/docs/error-decoder.html?invariant=" + a, c = 1; - c < arguments.length; - c++ - ) - b += "&args[]=" + encodeURIComponent(arguments[c]); - return ( - "Minified React error #" + - a + - "; visit " + - b + - " for the full message or use the non-minified dev environment for full errors and additional helpful warnings." - ); + +import { + Children, + __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED as __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED$1, +} from 'react'; +import {__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED} from 'react-dom'; + +// TODO: this is special because it gets imported during build. +// +// TODO: 18.0.0 has not been released to NPM; +// It exists as a placeholder so that DevTools can support work tag changes between releases. +// When we next publish a release, update the matching TODO in backend/renderer.js +// TODO: This module is used both by the release scripts and to expose a version +// at runtime. We should instead inject the version number as part of the build +// process, and use the ReactVersions.js module as the single source of truth. +var ReactVersion = '18.2.0'; + +function scheduleWork(callback) { + callback(); } -var l = null, - n = 0; -function p(controller, b) { - if (0 !== b.length) controller.write(b); -} -function t(a, b) { - p(a, b); - return !0; -} -function ba(a) { - a.flush(false); -} -var ca = new TextEncoder(); -function u(a) { - return a; -} -function v(a) { - return a; -} -function da(a, b) { - "function" === typeof a.error ? a.close(b) : a.end(b); -} -var w = Object.prototype.hasOwnProperty, - ea = - /^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/, - fa = {}, - ha = {}; -function ia(a) { - if (w.call(ha, a)) return !0; - if (w.call(fa, a)) return !1; - if (ea.test(a)) return (ha[a] = !0); - fa[a] = !0; - return !1; -} -function x(a, b, c, d, f, e, g) { - this.acceptsBooleans = 2 === b || 3 === b || 4 === b; - this.attributeName = d; - this.attributeNamespace = f; - this.mustUseProperty = c; - this.propertyName = a; - this.type = b; - this.sanitizeURL = e; - this.removeEmptyString = g; -} -var y = {}; -"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style" - .split(" ") - .forEach(function (a) { - y[a] = new x(a, 0, !1, a, null, !1, !1); - }); +function beginWriting(destination) {} +function writeChunk(destination, chunk) { + if (chunk.length === 0) { + return; + } + + destination.write(chunk); +} +function writeChunkAndReturn(destination, chunk) { + return !!destination.write(chunk); +} +function completeWriting(destination) {} +function close(destination) { + destination.end(); +} +function stringToChunk(content) { + return content; +} +function stringToPrecomputedChunk(content) { + return content; +} +function closeWithError(destination, error) { + // $FlowFixMe[method-unbinding] + if (typeof destination.error === 'function') { + // $FlowFixMe: This is an Error object or the destination accepts other types. + destination.error(error); + } else { + // Earlier implementations doesn't support this method. In that environment you're + // supposed to throw from a promise returned but we don't return a promise in our + // approach. We could fork this implementation but this is environment is an edge + // case to begin with. It's even less common to run this in an older environment. + // Even then, this is not where errors are supposed to happen and they get reported + // to a global callback in addition to this anyway. So it's fine just to close this. + destination.close(); + } +} + +// ----------------------------------------------------------------------------- +const enableFloat = true; // When a node is unmounted, recurse into the Fiber subtree and clean out + +// $FlowFixMe[method-unbinding] +const hasOwnProperty = Object.prototype.hasOwnProperty; + +// A reserved attribute. +// It is handled by React separately and shouldn't be written to the DOM. +const RESERVED = 0; // A simple string attribute. +// Attributes that aren't in the filter are presumed to have this type. + +const STRING = 1; // A string attribute that accepts booleans in React. In HTML, these are called +// "enumerated" attributes with "true" and "false" as possible values. +// When true, it should be set to a "true" string. +// When false, it should be set to a "false" string. + +const BOOLEANISH_STRING = 2; // A real boolean attribute. +// When true, it should be present (set either to an empty string or its name). +// When false, it should be omitted. + +const BOOLEAN = 3; // An attribute that can be used as a flag as well as with a value. +// When true, it should be present (set either to an empty string or its name). +// When false, it should be omitted. +// For any other value, should be present with that value. + +const OVERLOADED_BOOLEAN = 4; // An attribute that must be numeric or parse as a numeric. +// When falsy, it should be removed. + +const NUMERIC = 5; // An attribute that must be positive numeric or parse as a positive numeric. +// When falsy, it should be removed. + +const POSITIVE_NUMERIC = 6; + +/* eslint-disable max-len */ +const ATTRIBUTE_NAME_START_CHAR = + ':A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD'; +/* eslint-enable max-len */ + +const ATTRIBUTE_NAME_CHAR = + ATTRIBUTE_NAME_START_CHAR + '\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040'; +const VALID_ATTRIBUTE_NAME_REGEX = new RegExp( + '^[' + ATTRIBUTE_NAME_START_CHAR + '][' + ATTRIBUTE_NAME_CHAR + ']*$' +); +const illegalAttributeNameCache = {}; +const validatedAttributeNameCache = {}; +function isAttributeNameSafe(attributeName) { + if (hasOwnProperty.call(validatedAttributeNameCache, attributeName)) { + return true; + } + + if (hasOwnProperty.call(illegalAttributeNameCache, attributeName)) { + return false; + } + + if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) { + validatedAttributeNameCache[attributeName] = true; + return true; + } + + illegalAttributeNameCache[attributeName] = true; + + return false; +} +function getPropertyInfo(name) { + return properties.hasOwnProperty(name) ? properties[name] : null; +} + +function PropertyInfoRecord( + name, + type, + mustUseProperty, + attributeName, + attributeNamespace, + sanitizeURL, + removeEmptyString +) { + this.acceptsBooleans = + type === BOOLEANISH_STRING || + type === BOOLEAN || + type === OVERLOADED_BOOLEAN; + this.attributeName = attributeName; + this.attributeNamespace = attributeNamespace; + this.mustUseProperty = mustUseProperty; + this.propertyName = name; + this.type = type; + this.sanitizeURL = sanitizeURL; + this.removeEmptyString = removeEmptyString; +} // When adding attributes to this list, be sure to also add them to +// the `possibleStandardNames` module to ensure casing and incorrect +// name warnings. + +const properties = {}; // These props are reserved by React. They shouldn't be written to the DOM. + +const reservedProps = [ + 'children', + 'dangerouslySetInnerHTML', // TODO: This prevents the assignment of defaultValue to regular + // elements (not just inputs). Now that ReactDOMInput assigns to the + // defaultValue property -- do we need this? + 'defaultValue', + 'defaultChecked', + 'innerHTML', + 'suppressContentEditableWarning', + 'suppressHydrationWarning', + 'style', +]; + +{ + reservedProps.push('innerText', 'textContent'); +} + +reservedProps.forEach((name) => { + // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions + properties[name] = new PropertyInfoRecord( + name, + RESERVED, + false, // mustUseProperty + name, // attributeName + null, // attributeNamespace + false, // sanitizeURL + false + ); +}); // A few React string attributes have a different name. +// This is a mapping from React prop names to the attribute names. + [ - ["acceptCharset", "accept-charset"], - ["className", "class"], - ["htmlFor", "for"], - ["httpEquiv", "http-equiv"], -].forEach(function (a) { - var b = a[0]; - y[b] = new x(b, 1, !1, a[1], null, !1, !1); -}); -["contentEditable", "draggable", "spellCheck", "value"].forEach(function (a) { - y[a] = new x(a, 2, !1, a.toLowerCase(), null, !1, !1); -}); + ['acceptCharset', 'accept-charset'], + ['className', 'class'], + ['htmlFor', 'for'], + ['httpEquiv', 'http-equiv'], +].forEach((_ref) => { + let name = _ref[0], + attributeName = _ref[1]; + // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions + properties[name] = new PropertyInfoRecord( + name, + STRING, + false, // mustUseProperty + attributeName, // attributeName + null, // attributeNamespace + false, // sanitizeURL + false + ); +}); // These are "enumerated" HTML attributes that accept "true" and "false". +// In React, we let users pass `true` and `false` even though technically +// these aren't boolean attributes (they are coerced to strings). + +['contentEditable', 'draggable', 'spellCheck', 'value'].forEach((name) => { + // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions + properties[name] = new PropertyInfoRecord( + name, + BOOLEANISH_STRING, + false, // mustUseProperty + name.toLowerCase(), // attributeName + null, // attributeNamespace + false, // sanitizeURL + false + ); +}); // These are "enumerated" SVG attributes that accept "true" and "false". +// In React, we let users pass `true` and `false` even though technically +// these aren't boolean attributes (they are coerced to strings). +// Since these are SVG attributes, their attribute names are case-sensitive. + [ - "autoReverse", - "externalResourcesRequired", - "focusable", - "preserveAlpha", -].forEach(function (a) { - y[a] = new x(a, 2, !1, a, null, !1, !1); -}); -"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope" - .split(" ") - .forEach(function (a) { - y[a] = new x(a, 3, !1, a.toLowerCase(), null, !1, !1); - }); -["checked", "multiple", "muted", "selected"].forEach(function (a) { - y[a] = new x(a, 3, !0, a, null, !1, !1); -}); -["capture", "download"].forEach(function (a) { - y[a] = new x(a, 4, !1, a, null, !1, !1); -}); -["cols", "rows", "size", "span"].forEach(function (a) { - y[a] = new x(a, 6, !1, a, null, !1, !1); -}); -["rowSpan", "start"].forEach(function (a) { - y[a] = new x(a, 5, !1, a.toLowerCase(), null, !1, !1); -}); -var ja = /[\-:]([a-z])/g; -function ka(a) { - return a[1].toUpperCase(); -} -"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height" - .split(" ") - .forEach(function (a) { - var b = a.replace(ja, ka); - y[b] = new x(b, 1, !1, a, null, !1, !1); - }); -"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type" - .split(" ") - .forEach(function (a) { - var b = a.replace(ja, ka); - y[b] = new x(b, 1, !1, a, "http://www.w3.org/1999/xlink", !1, !1); - }); -["xml:base", "xml:lang", "xml:space"].forEach(function (a) { - var b = a.replace(ja, ka); - y[b] = new x(b, 1, !1, a, "http://www.w3.org/XML/1998/namespace", !1, !1); -}); -["tabIndex", "crossOrigin"].forEach(function (a) { - y[a] = new x(a, 1, !1, a.toLowerCase(), null, !1, !1); + 'autoReverse', + 'externalResourcesRequired', + 'focusable', + 'preserveAlpha', +].forEach((name) => { + // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions + properties[name] = new PropertyInfoRecord( + name, + BOOLEANISH_STRING, + false, // mustUseProperty + name, // attributeName + null, // attributeNamespace + false, // sanitizeURL + false + ); +}); // These are HTML boolean attributes. + +[ + 'allowFullScreen', + 'async', // Note: there is a special case that prevents it from being written to the DOM + // on the client side because the browsers are inconsistent. Instead we call focus(). + 'autoFocus', + 'autoPlay', + 'controls', + 'default', + 'defer', + 'disabled', + 'disablePictureInPicture', + 'disableRemotePlayback', + 'formNoValidate', + 'hidden', + 'loop', + 'noModule', + 'noValidate', + 'open', + 'playsInline', + 'readOnly', + 'required', + 'reversed', + 'scoped', + 'seamless', // Microdata + 'itemScope', +].forEach((name) => { + // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions + properties[name] = new PropertyInfoRecord( + name, + BOOLEAN, + false, // mustUseProperty + name.toLowerCase(), // attributeName + null, // attributeNamespace + false, // sanitizeURL + false + ); +}); // These are the few React props that we set as DOM properties +// rather than attributes. These are all booleans. + +[ + 'checked', // Note: `option.selected` is not updated if `select.multiple` is + // disabled with `removeAttribute`. We have special logic for handling this. + 'multiple', + 'muted', + 'selected', // NOTE: if you add a camelCased prop to this list, + // you'll need to set attributeName to name.toLowerCase() + // instead in the assignment below. +].forEach((name) => { + // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions + properties[name] = new PropertyInfoRecord( + name, + BOOLEAN, + true, // mustUseProperty + name, // attributeName + null, // attributeNamespace + false, // sanitizeURL + false + ); +}); // These are HTML attributes that are "overloaded booleans": they behave like +// booleans, but can also accept a string value. + +[ + 'capture', + 'download', // NOTE: if you add a camelCased prop to this list, + // you'll need to set attributeName to name.toLowerCase() + // instead in the assignment below. +].forEach((name) => { + // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions + properties[name] = new PropertyInfoRecord( + name, + OVERLOADED_BOOLEAN, + false, // mustUseProperty + name, // attributeName + null, // attributeNamespace + false, // sanitizeURL + false + ); +}); // These are HTML attributes that must be positive numbers. + +[ + 'cols', + 'rows', + 'size', + 'span', // NOTE: if you add a camelCased prop to this list, + // you'll need to set attributeName to name.toLowerCase() + // instead in the assignment below. +].forEach((name) => { + // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions + properties[name] = new PropertyInfoRecord( + name, + POSITIVE_NUMERIC, + false, // mustUseProperty + name, // attributeName + null, // attributeNamespace + false, // sanitizeURL + false + ); +}); // These are HTML attributes that must be numbers. + +['rowSpan', 'start'].forEach((name) => { + // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions + properties[name] = new PropertyInfoRecord( + name, + NUMERIC, + false, // mustUseProperty + name.toLowerCase(), // attributeName + null, // attributeNamespace + false, // sanitizeURL + false + ); }); -y.xlinkHref = new x( - "xlinkHref", - 1, - !1, - "xlink:href", - "http://www.w3.org/1999/xlink", - !0, - !1 +const CAMELIZE = /[\-\:]([a-z])/g; + +const capitalize = (token) => token[1].toUpperCase(); // This is a list of all SVG attributes that need special casing, namespacing, +// or boolean value assignment. Regular attributes that just accept strings +// and have the same names are omitted, just like in the HTML attribute filter. +// Some of these attributes can be hard to find. This list was created by +// scraping the MDN documentation. + +[ + 'accent-height', + 'alignment-baseline', + 'arabic-form', + 'baseline-shift', + 'cap-height', + 'clip-path', + 'clip-rule', + 'color-interpolation', + 'color-interpolation-filters', + 'color-profile', + 'color-rendering', + 'dominant-baseline', + 'enable-background', + 'fill-opacity', + 'fill-rule', + 'flood-color', + 'flood-opacity', + 'font-family', + 'font-size', + 'font-size-adjust', + 'font-stretch', + 'font-style', + 'font-variant', + 'font-weight', + 'glyph-name', + 'glyph-orientation-horizontal', + 'glyph-orientation-vertical', + 'horiz-adv-x', + 'horiz-origin-x', + 'image-rendering', + 'letter-spacing', + 'lighting-color', + 'marker-end', + 'marker-mid', + 'marker-start', + 'overline-position', + 'overline-thickness', + 'paint-order', + 'panose-1', + 'pointer-events', + 'rendering-intent', + 'shape-rendering', + 'stop-color', + 'stop-opacity', + 'strikethrough-position', + 'strikethrough-thickness', + 'stroke-dasharray', + 'stroke-dashoffset', + 'stroke-linecap', + 'stroke-linejoin', + 'stroke-miterlimit', + 'stroke-opacity', + 'stroke-width', + 'text-anchor', + 'text-decoration', + 'text-rendering', + 'underline-position', + 'underline-thickness', + 'unicode-bidi', + 'unicode-range', + 'units-per-em', + 'v-alphabetic', + 'v-hanging', + 'v-ideographic', + 'v-mathematical', + 'vector-effect', + 'vert-adv-y', + 'vert-origin-x', + 'vert-origin-y', + 'word-spacing', + 'writing-mode', + 'xmlns:xlink', + 'x-height', // NOTE: if you add a camelCased prop to this list, + // you'll need to set attributeName to name.toLowerCase() + // instead in the assignment below. +].forEach((attributeName) => { + const name = attributeName.replace(CAMELIZE, capitalize); // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions + + properties[name] = new PropertyInfoRecord( + name, + STRING, + false, // mustUseProperty + attributeName, + null, // attributeNamespace + false, // sanitizeURL + false + ); +}); // String SVG attributes with the xlink namespace. + +[ + 'xlink:actuate', + 'xlink:arcrole', + 'xlink:role', + 'xlink:show', + 'xlink:title', + 'xlink:type', // NOTE: if you add a camelCased prop to this list, + // you'll need to set attributeName to name.toLowerCase() + // instead in the assignment below. +].forEach((attributeName) => { + const name = attributeName.replace(CAMELIZE, capitalize); // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions + + properties[name] = new PropertyInfoRecord( + name, + STRING, + false, // mustUseProperty + attributeName, + 'http://www.w3.org/1999/xlink', + false, // sanitizeURL + false + ); +}); // String SVG attributes with the xml namespace. + +[ + 'xml:base', + 'xml:lang', + 'xml:space', // NOTE: if you add a camelCased prop to this list, + // you'll need to set attributeName to name.toLowerCase() + // instead in the assignment below. +].forEach((attributeName) => { + const name = attributeName.replace(CAMELIZE, capitalize); // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions + + properties[name] = new PropertyInfoRecord( + name, + STRING, + false, // mustUseProperty + attributeName, + 'http://www.w3.org/XML/1998/namespace', + false, // sanitizeURL + false + ); +}); // These attribute exists both in HTML and SVG. +// The attribute name is case-sensitive in SVG so we can't just use +// the React name like we do for attributes that exist only in HTML. + +['tabIndex', 'crossOrigin'].forEach((attributeName) => { + // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions + properties[attributeName] = new PropertyInfoRecord( + attributeName, + STRING, + false, // mustUseProperty + attributeName.toLowerCase(), // attributeName + null, // attributeNamespace + false, // sanitizeURL + false + ); +}); // These attributes accept URLs. These must not allow javascript: URLS. +// These will also need to accept Trusted Types object in the future. + +const xlinkHref = 'xlinkHref'; // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions + +properties[xlinkHref] = new PropertyInfoRecord( + 'xlinkHref', + STRING, + false, // mustUseProperty + 'xlink:href', + 'http://www.w3.org/1999/xlink', + true, // sanitizeURL + false ); -["src", "href", "action", "formAction"].forEach(function (a) { - y[a] = new x(a, 1, !1, a.toLowerCase(), null, !0, !0); +['src', 'href', 'action', 'formAction'].forEach((attributeName) => { + // $FlowFixMe[invalid-constructor] Flow no longer supports calling new on functions + properties[attributeName] = new PropertyInfoRecord( + attributeName, + STRING, + false, // mustUseProperty + attributeName.toLowerCase(), // attributeName + null, // attributeNamespace + true, // sanitizeURL + true + ); }); -var z = { - animationIterationCount: !0, - aspectRatio: !0, - borderImageOutset: !0, - borderImageSlice: !0, - borderImageWidth: !0, - boxFlex: !0, - boxFlexGroup: !0, - boxOrdinalGroup: !0, - columnCount: !0, - columns: !0, - flex: !0, - flexGrow: !0, - flexPositive: !0, - flexShrink: !0, - flexNegative: !0, - flexOrder: !0, - gridArea: !0, - gridRow: !0, - gridRowEnd: !0, - gridRowSpan: !0, - gridRowStart: !0, - gridColumn: !0, - gridColumnEnd: !0, - gridColumnSpan: !0, - gridColumnStart: !0, - fontWeight: !0, - lineClamp: !0, - lineHeight: !0, - opacity: !0, - order: !0, - orphans: !0, - tabSize: !0, - widows: !0, - zIndex: !0, - zoom: !0, - fillOpacity: !0, - floodOpacity: !0, - stopOpacity: !0, - strokeDasharray: !0, - strokeDashoffset: !0, - strokeMiterlimit: !0, - strokeOpacity: !0, - strokeWidth: !0, - }, - la = ["Webkit", "ms", "Moz", "O"]; -Object.keys(z).forEach(function (a) { - la.forEach(function (b) { - b = b + a.charAt(0).toUpperCase() + a.substring(1); - z[b] = z[a]; + +/** + * CSS properties which accept numbers but are not in units of "px". + */ +const isUnitlessNumber = { + animationIterationCount: true, + aspectRatio: true, + borderImageOutset: true, + borderImageSlice: true, + borderImageWidth: true, + boxFlex: true, + boxFlexGroup: true, + boxOrdinalGroup: true, + columnCount: true, + columns: true, + flex: true, + flexGrow: true, + flexPositive: true, + flexShrink: true, + flexNegative: true, + flexOrder: true, + gridArea: true, + gridRow: true, + gridRowEnd: true, + gridRowSpan: true, + gridRowStart: true, + gridColumn: true, + gridColumnEnd: true, + gridColumnSpan: true, + gridColumnStart: true, + fontWeight: true, + lineClamp: true, + lineHeight: true, + opacity: true, + order: true, + orphans: true, + tabSize: true, + widows: true, + zIndex: true, + zoom: true, + // SVG-related properties + fillOpacity: true, + floodOpacity: true, + stopOpacity: true, + strokeDasharray: true, + strokeDashoffset: true, + strokeMiterlimit: true, + strokeOpacity: true, + strokeWidth: true, +}; +/** + * @param {string} prefix vendor-specific prefix, eg: Webkit + * @param {string} key style name, eg: transitionDuration + * @return {string} style name prefixed with `prefix`, properly camelCased, eg: + * WebkitTransitionDuration + */ + +function prefixKey(prefix, key) { + return prefix + key.charAt(0).toUpperCase() + key.substring(1); +} +/** + * Support style names that may come passed in prefixed by adding permutations + * of vendor prefixes. + */ + +const prefixes = ['Webkit', 'ms', 'Moz', 'O']; // Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an +// infinite loop, because it iterates over the newly added props too. + +Object.keys(isUnitlessNumber).forEach(function (prop) { + prefixes.forEach(function (prefix) { + isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop]; }); }); -var ma = /["'&<>]/; -function A(a) { - return Bun.escapeHTML(a); -} -var na = /([A-Z])/g, - oa = /^ms-/, - pa = Array.isArray, - qa = v("<script>"), - ra = v("\x3c/script>"), - sa = v('<script src="'), - ta = v('<script type="module" src="'), - ua = v('" async="">\x3c/script>'), - va = /(<\/|<)(s)(cript)/gi; -function wa(a, b, c, d) { - return "" + b + ("s" === c ? "\\u0073" : "\\u0053") + d; -} -function xa(a, b, c, d, f) { - a = void 0 === a ? "" : a; - b = void 0 === b ? qa : v('<script nonce="' + A(b) + '">'); - var e = []; - void 0 !== c && e.push(b, u(("" + c).replace(va, wa)), ra); - if (void 0 !== d) for (c = 0; c < d.length; c++) e.push(sa, u(A(d[c])), ua); - if (void 0 !== f) for (d = 0; d < f.length; d++) e.push(ta, u(A(f[d])), ua); + +// code copied and modified from escape-html +const matchHtmlRegExp = /["'&<>]/; +/** + * Escapes special characters and HTML entities in a given html string. + * + * @param {string} string HTML string to escape for later insertion + * @return {string} + * @public + */ + +function escapeHtml(string) { + const str = '' + string; + const match = matchHtmlRegExp.exec(str); + + if (!match) { + return str; + } + + let escape; + let html = ''; + let index; + let lastIndex = 0; + + for (index = match.index; index < str.length; index++) { + switch (str.charCodeAt(index)) { + case 34: + // " + escape = '"'; + break; + + case 38: + // & + escape = '&'; + break; + + case 39: + // ' + escape = '''; // modified from escape-html; used to be ''' + + break; + + case 60: + // < + escape = '<'; + break; + + case 62: + // > + escape = '>'; + break; + + default: + continue; + } + + if (lastIndex !== index) { + html += str.substring(lastIndex, index); + } + + lastIndex = index + 1; + html += escape; + } + + return lastIndex !== index ? html + str.substring(lastIndex, index) : html; +} // end code copied and modified from escape-html + +/** + * Escapes text to prevent scripting attacks. + * + * @param {*} text Text value to escape. + * @return {string} An escaped string. + */ + +function escapeTextForBrowser(text) { + if (typeof text === 'boolean' || typeof text === 'number') { + // this shortcircuit helps perf for types that we know will never have + // special characters, especially given that this function is used often + // for numeric dom ids. + return '' + text; + } + + return escapeHtml(text); +} + +const uppercasePattern = /([A-Z])/g; +const msPattern = /^ms-/; +/** + * Hyphenates a camelcased CSS property name, for example: + * + * > hyphenateStyleName('backgroundColor') + * < "background-color" + * > hyphenateStyleName('MozTransition') + * < "-moz-transition" + * > hyphenateStyleName('msTransition') + * < "-ms-transition" + * + * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix + * is converted to `-ms-`. + */ + +function hyphenateStyleName(name) { + return name + .replace(uppercasePattern, '-$1') + .toLowerCase() + .replace(msPattern, '-ms-'); +} + +const isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare + +function isArray(a) { + return isArrayImpl(a); +} + +const assign = Object.assign; + +// @TODO add bootstrap script to implicit preloads +function createResources() { return { - bootstrapChunks: e, - startInlineScript: b, - placeholderPrefix: v(a + "P:"), - segmentPrefix: v(a + "S:"), - boundaryPrefix: a + "B:", - idPrefix: a, + // persistent + preloadsMap: new Map(), + stylesMap: new Map(), + scriptsMap: new Map(), + headsMap: new Map(), + // cleared on flush + charset: null, + bases: new Set(), + preconnects: new Set(), + fontPreloads: new Set(), + // usedImagePreloads: new Set(), + precedences: new Map(), + usedStylePreloads: new Set(), + scripts: new Set(), + usedScriptPreloads: new Set(), + explicitStylePreloads: new Set(), + // explicitImagePreloads: new Set(), + explicitScriptPreloads: new Set(), + headResources: new Set(), + // cache for tracking structured meta tags + structuredMetaKeys: new Map(), + // like a module global for currently rendering boundary + boundaryResources: null, + }; +} +function createBoundaryResources() { + return new Set(); +} +let currentResources = null; +const currentResourcesStack = []; +function prepareToRenderResources(resources) { + currentResourcesStack.push(currentResources); + currentResources = resources; +} +function finishRenderingResources() { + currentResources = currentResourcesStack.pop(); +} +function setCurrentlyRenderingBoundaryResourcesTarget( + resources, + boundaryResources +) { + resources.boundaryResources = boundaryResources; +} +const ReactDOMServerDispatcher = { + preload, + preinit, +}; + +function preload(href, options) { + if (!currentResources) { + // While we expect that preload calls are primarily going to be observed + // during render because effects and events don't run on the server it is + // still possible that these get called in module scope. This is valid on + // the client since there is still a document to interact with but on the + // server we need a request to associate the call to. Because of this we + // simply return and do not warn. + return; + } + + const resources = currentResources; + + if ( + typeof href === 'string' && + href && + typeof options === 'object' && + options !== null + ) { + const as = options.as; + let resource = resources.preloadsMap.get(href); + + if (resource); + else { + resource = createPreloadResource( + resources, + href, + as, + preloadPropsFromPreloadOptions(href, as, options) + ); + } + + switch (as) { + case 'font': { + resources.fontPreloads.add(resource); + break; + } + + case 'style': { + resources.explicitStylePreloads.add(resource); + break; + } + + case 'script': { + resources.explicitScriptPreloads.add(resource); + break; + } + } + } +} + +function preinit(href, options) { + if (!currentResources) { + // While we expect that preinit calls are primarily going to be observed + // during render because effects and events don't run on the server it is + // still possible that these get called in module scope. This is valid on + // the client since there is still a document to interact with but on the + // server we need a request to associate the call to. Because of this we + // simply return and do not warn. + return; + } + + const resources = currentResources; + + if ( + typeof href === 'string' && + href && + typeof options === 'object' && + options !== null + ) { + const as = options.as; + + switch (as) { + case 'style': { + let resource = resources.stylesMap.get(href); + + if (resource); + else { + const precedence = options.precedence || 'default'; + const resourceProps = stylePropsFromPreinitOptions( + href, + precedence, + options + ); + resource = createStyleResource( + resources, + href, + precedence, + resourceProps + ); + } + + resource.set.add(resource); + resources.explicitStylePreloads.add(resource.hint); + return; + } + + case 'script': { + const src = href; + let resource = resources.scriptsMap.get(src); + + if (resource); + else { + const scriptProps = scriptPropsFromPreinitOptions(src, options); + resource = createScriptResource(resources, src, scriptProps); + resources.scripts.add(resource); + } + + return; + } + } + } +} + +function preloadPropsFromPreloadOptions(href, as, options) { + return { + href, + rel: 'preload', + as, + crossOrigin: as === 'font' ? '' : options.crossOrigin, + integrity: options.integrity, + }; +} + +function preloadPropsFromRawProps(href, as, rawProps) { + const props = assign({}, rawProps); + + props.href = href; + props.rel = 'preload'; + props.as = as; + + if (as === 'font') { + // Font preloads always need CORS anonymous mode so we set it here + // regardless of the props provided. This should warn elsewhere in + // dev + props.crossOrigin = ''; + } + + return props; +} + +function preloadAsStylePropsFromProps(href, props) { + return { + rel: 'preload', + as: 'style', + href: href, + crossOrigin: props.crossOrigin, + integrity: props.integrity, + media: props.media, + hrefLang: props.hrefLang, + referrerPolicy: props.referrerPolicy, + }; +} + +function preloadAsScriptPropsFromProps(href, props) { + return { + rel: 'preload', + as: 'script', + href, + crossOrigin: props.crossOrigin, + integrity: props.integrity, + referrerPolicy: props.referrerPolicy, + }; +} + +function createPreloadResource(resources, href, as, props) { + const preloadsMap = resources.preloadsMap; + + const resource = { + type: 'preload', + as, + href, + flushed: false, + props, + }; + preloadsMap.set(href, resource); + return resource; +} + +function stylePropsFromRawProps(href, precedence, rawProps) { + const props = assign({}, rawProps); + + props.href = href; + props.rel = 'stylesheet'; + props['data-precedence'] = precedence; + delete props.precedence; + return props; +} + +function stylePropsFromPreinitOptions(href, precedence, options) { + return { + rel: 'stylesheet', + href, + 'data-precedence': precedence, + crossOrigin: options.crossOrigin, + }; +} + +function createStyleResource(resources, href, precedence, props) { + const stylesMap = resources.stylesMap, + preloadsMap = resources.preloadsMap, + precedences = resources.precedences; // If this is the first time we've seen this precedence we encode it's position in our set even though + // we don't add the resource to this set yet + + let precedenceSet = precedences.get(precedence); + + if (!precedenceSet) { + precedenceSet = new Set(); + precedences.set(precedence, precedenceSet); + } + + let hint = preloadsMap.get(href); + + if (hint) { + // If a preload for this style Resource already exists there are certain props we want to adopt + // on the style Resource, primarily focussed on making sure the style network pathways utilize + // the preload pathways. For instance if you have diffreent crossOrigin attributes for a preload + // and a stylesheet the stylesheet will make a new request even if the preload had already loaded + adoptPreloadPropsForStyleProps(props, hint.props); + } else { + const preloadResourceProps = preloadAsStylePropsFromProps(href, props); + hint = createPreloadResource( + resources, + href, + 'style', + preloadResourceProps + ); + + resources.explicitStylePreloads.add(hint); + } + + const resource = { + type: 'style', + href, + precedence, + flushed: false, + inShell: false, + props, + hint, + set: precedenceSet, + }; + stylesMap.set(href, resource); + return resource; +} + +function adoptPreloadPropsForStyleProps(resourceProps, preloadProps) { + if (resourceProps.crossOrigin == null) + resourceProps.crossOrigin = preloadProps.crossOrigin; + if (resourceProps.referrerPolicy == null) + resourceProps.referrerPolicy = preloadProps.referrerPolicy; + if (resourceProps.title == null) resourceProps.title = preloadProps.title; +} + +function scriptPropsFromPreinitOptions(src, options) { + return { + src, + async: true, + crossOrigin: options.crossOrigin, + integrity: options.integrity, + }; +} + +function scriptPropsFromRawProps(src, rawProps) { + const props = assign({}, rawProps); + + props.src = src; + return props; +} + +function createScriptResource(resources, src, props) { + const scriptsMap = resources.scriptsMap, + preloadsMap = resources.preloadsMap; + let hint = preloadsMap.get(src); + + if (hint) { + // If a preload for this style Resource already exists there are certain props we want to adopt + // on the style Resource, primarily focussed on making sure the style network pathways utilize + // the preload pathways. For instance if you have diffreent crossOrigin attributes for a preload + // and a stylesheet the stylesheet will make a new request even if the preload had already loaded + adoptPreloadPropsForScriptProps(props, hint.props); + } else { + const preloadResourceProps = preloadAsScriptPropsFromProps(src, props); + hint = createPreloadResource( + resources, + src, + 'script', + preloadResourceProps + ); + + resources.explicitScriptPreloads.add(hint); + } + + const resource = { + type: 'script', + src, + flushed: false, + props, + hint, + }; + scriptsMap.set(src, resource); + return resource; +} + +function adoptPreloadPropsForScriptProps(resourceProps, preloadProps) { + if (resourceProps.crossOrigin == null) + resourceProps.crossOrigin = preloadProps.crossOrigin; + if (resourceProps.referrerPolicy == null) + resourceProps.referrerPolicy = preloadProps.referrerPolicy; + if (resourceProps.integrity == null) + resourceProps.integrity = preloadProps.integrity; +} + +function titlePropsFromRawProps(child, rawProps) { + const props = assign({}, rawProps); + + props.children = child; + return props; +} + +function resourcesFromElement(type, props) { + if (!currentResources) { + throw new Error( + '"currentResources" was expected to exist. This is a bug in React.' + ); + } + + const resources = currentResources; + + switch (type) { + case 'title': { + let child = props.children; + + if (Array.isArray(child) && child.length === 1) { + child = child[0]; + } + + if (typeof child === 'string' || typeof child === 'number') { + const key = 'title::' + child; + let resource = resources.headsMap.get(key); + + if (!resource) { + resource = { + type: 'title', + props: titlePropsFromRawProps(child, props), + flushed: false, + }; + resources.headsMap.set(key, resource); + resources.headResources.add(resource); + } + } + + return true; + } + + case 'meta': { + let key, propertyPath; + + if (typeof props.charSet === 'string') { + key = 'charSet'; + } else if (typeof props.content === 'string') { + const contentKey = '::' + props.content; + + if (typeof props.httpEquiv === 'string') { + key = 'httpEquiv::' + props.httpEquiv + contentKey; + } else if (typeof props.name === 'string') { + key = 'name::' + props.name + contentKey; + } else if (typeof props.itemProp === 'string') { + key = 'itemProp::' + props.itemProp + contentKey; + } else if (typeof props.property === 'string') { + const property = props.property; + key = 'property::' + property + contentKey; + propertyPath = property; + const parentPath = property.split(':').slice(0, -1).join(':'); + const parentResource = resources.structuredMetaKeys.get(parentPath); + + if (parentResource) { + key = parentResource.key + '::child::' + key; + } + } + } + + if (key) { + if (!resources.headsMap.has(key)) { + const resource = { + type: 'meta', + key, + props: assign({}, props), + flushed: false, + }; + resources.headsMap.set(key, resource); + + if (key === 'charSet') { + resources.charset = resource; + } else { + if (propertyPath) { + resources.structuredMetaKeys.set(propertyPath, resource); + } + + resources.headResources.add(resource); + } + } + } + + return true; + } + + case 'base': { + const target = props.target, + href = props.href; // We mirror the key construction on the client since we will likely unify + // this code in the future to better guarantee key semantics are identical + // in both environments + + let key = 'base'; + key += + typeof href === 'string' ? '[href="' + href + '"]' : ':not([href])'; + key += + typeof target === 'string' + ? '[target="' + target + '"]' + : ':not([target])'; + + if (!resources.headsMap.has(key)) { + const resource = { + type: 'base', + props: assign({}, props), + flushed: false, + }; + resources.headsMap.set(key, resource); + resources.bases.add(resource); + } + + return true; + } + } + + return false; +} // Construct a resource from link props. + +function resourcesFromLink(props) { + if (!currentResources) { + throw new Error( + '"currentResources" was expected to exist. This is a bug in React.' + ); + } + + const resources = currentResources; + const rel = props.rel, + href = props.href; + + if (!href || typeof href !== 'string' || !rel || typeof rel !== 'string') { + return false; + } + + let key = ''; + + switch (rel) { + case 'stylesheet': { + const onLoad = props.onLoad, + onError = props.onError, + precedence = props.precedence, + disabled = props.disabled; + + if ( + typeof precedence !== 'string' || + onLoad || + onError || + disabled != null + ) { + let preloadResource = resources.preloadsMap.get(href); + + if (!preloadResource) { + preloadResource = createPreloadResource( + // $FlowFixMe[incompatible-call] found when upgrading Flow + resources, + href, + 'style', + preloadAsStylePropsFromProps(href, props) + ); + + resources.usedStylePreloads.add(preloadResource); + } + + return false; + } else { + // We are able to convert this link element to a resource exclusively. We construct the relevant Resource + // and return true indicating that this link was fully consumed. + let resource = resources.stylesMap.get(href); + + if (resource); + else { + const resourceProps = stylePropsFromRawProps(href, precedence, props); + resource = createStyleResource( + // $FlowFixMe[incompatible-call] found when upgrading Flow + currentResources, + href, + precedence, + resourceProps + ); + resources.usedStylePreloads.add(resource.hint); + } + + if (resources.boundaryResources) { + resources.boundaryResources.add(resource); + } else { + resource.set.add(resource); + } + + return true; + } + } + + case 'preload': { + const as = props.as; + + switch (as) { + case 'script': + case 'style': + case 'font': { + let resource = resources.preloadsMap.get(href); + + if (resource); + else { + resource = createPreloadResource( + resources, + href, + as, + preloadPropsFromRawProps(href, as, props) + ); + + switch (as) { + case 'script': { + resources.explicitScriptPreloads.add(resource); + break; + } + + case 'style': { + resources.explicitStylePreloads.add(resource); + break; + } + + case 'font': { + resources.fontPreloads.add(resource); + break; + } + } + } + + return true; + } + } + + break; + } + } + + if (props.onLoad || props.onError) { + // When a link has these props we can't treat it is a Resource but if we rendered it on the + // server it would look like a Resource in the rendered html (the onLoad/onError aren't emitted) + // Instead we expect the client to insert them rather than hydrate them which also guarantees + // that the onLoad and onError won't fire before the event handlers are attached + return true; + } + + const sizes = typeof props.sizes === 'string' ? props.sizes : ''; + const media = typeof props.media === 'string' ? props.media : ''; + key = + 'rel:' + rel + '::href:' + href + '::sizes:' + sizes + '::media:' + media; + let resource = resources.headsMap.get(key); + + if (!resource) { + resource = { + type: 'link', + props: assign({}, props), + flushed: false, + }; + resources.headsMap.set(key, resource); + + switch (rel) { + case 'preconnect': + case 'dns-prefetch': { + resources.preconnects.add(resource); + break; + } + + default: { + resources.headResources.add(resource); + } + } + } + + return true; +} // Construct a resource from link props. + +function resourcesFromScript(props) { + if (!currentResources) { + throw new Error( + '"currentResources" was expected to exist. This is a bug in React.' + ); + } + + const resources = currentResources; + const src = props.src, + async = props.async, + onLoad = props.onLoad, + onError = props.onError; + + if (!src || typeof src !== 'string') { + return false; + } + + if (async) { + if (onLoad || onError) { + let preloadResource = resources.preloadsMap.get(src); + + if (!preloadResource) { + preloadResource = createPreloadResource( + // $FlowFixMe[incompatible-call] found when upgrading Flow + resources, + src, + 'script', + preloadAsScriptPropsFromProps(src, props) + ); + + resources.usedScriptPreloads.add(preloadResource); + } + } else { + let resource = resources.scriptsMap.get(src); + + if (resource); + else { + const resourceProps = scriptPropsFromRawProps(src, props); + resource = createScriptResource(resources, src, resourceProps); + resources.scripts.add(resource); + } + } + + return true; + } + + return false; +} +function hoistResources(resources, source) { + const currentBoundaryResources = resources.boundaryResources; + + if (currentBoundaryResources) { + source.forEach((resource) => currentBoundaryResources.add(resource)); + source.clear(); + } +} +function hoistResourcesToRoot(resources, boundaryResources) { + boundaryResources.forEach((resource) => resource.set.add(resource)); + boundaryResources.clear(); +} + +// The build script is at scripts/rollup/generate-inline-fizz-runtime.js. +// Run `yarn generate-inline-fizz-runtime` to generate. +const clientRenderBoundary = + '$RX=function(b,c,d,e){var a=document.getElementById(b);a&&(b=a.previousSibling,b.data="$!",a=a.dataset,c&&(a.dgst=c),d&&(a.msg=d),e&&(a.stck=e),b._reactRetry&&b._reactRetry())};'; +const completeBoundary = + '$RC=function(b,c,e){c=document.getElementById(c);c.parentNode.removeChild(c);var a=document.getElementById(b);if(a){b=a.previousSibling;if(e)b.data="$!",a.setAttribute("data-dgst",e);else{e=b.parentNode;a=b.nextSibling;var f=0;do{if(a&&8===a.nodeType){var d=a.data;if("/$"===d)if(0===f)break;else f--;else"$"!==d&&"$?"!==d&&"$!"!==d||f++}d=a.nextSibling;e.removeChild(a);a=d}while(a);for(;c.firstChild;)e.insertBefore(c.firstChild,a);b.data="$"}b._reactRetry&&b._reactRetry()}};'; +const completeBoundaryWithStyles = + '$RM=new Map;\n$RR=function(p,q,v){function r(l){this.s=l}for(var t=$RC,u=$RM,m=new Map,n=document,g,e,f=n.querySelectorAll("link[data-precedence],style[data-precedence]"),d=0;e=f[d++];)m.set(e.dataset.precedence,g=e);e=0;f=[];for(var c,h,b,a;c=v[e++];){var k=0;h=c[k++];if(b=u.get(h))"l"!==b.s&&f.push(b);else{a=n.createElement("link");a.href=h;a.rel="stylesheet";for(a.dataset.precedence=d=c[k++];b=c[k++];)a.setAttribute(b,c[k++]);b=a._p=new Promise(function(l,w){a.onload=l;a.onerror=w});b.then(r.bind(b,\n"l"),r.bind(b,"e"));u.set(h,b);f.push(b);c=m.get(d)||g;c===g&&(g=a);m.set(d,a);c?c.parentNode.insertBefore(a,c.nextSibling):(d=n.head,d.insertBefore(a,d.firstChild))}}Promise.all(f).then(t.bind(null,p,q,""),t.bind(null,p,q,"Resource failed to load"))};'; +const completeSegment = + '$RS=function(a,b){a=document.getElementById(a);b=document.getElementById(b);for(a.parentNode.removeChild(a);a.firstChild;)b.parentNode.insertBefore(a.firstChild,b);b.parentNode.removeChild(b)};'; + +const ReactDOMSharedInternals = + __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; + +const ReactDOMCurrentDispatcher = ReactDOMSharedInternals.Dispatcher; +function prepareToRender(resources) { + prepareToRenderResources(resources); + const previousHostDispatcher = ReactDOMCurrentDispatcher.current; + ReactDOMCurrentDispatcher.current = ReactDOMServerDispatcher; + return previousHostDispatcher; +} +function cleanupAfterRender(previousDispatcher) { + finishRenderingResources(); + ReactDOMCurrentDispatcher.current = previousDispatcher; +} // Used to distinguish these contexts from ones used in other renderers. + +const startInlineScript = stringToPrecomputedChunk('<script>'); +const endInlineScript = stringToPrecomputedChunk('</script>'); +const startScriptSrc = stringToPrecomputedChunk('<script src="'); +const startModuleSrc = stringToPrecomputedChunk('<script type="module" src="'); +const scriptIntegirty = stringToPrecomputedChunk('" integrity="'); +const endAsyncScript = stringToPrecomputedChunk('" async=""></script>'); +/** + * This escaping function is designed to work with bootstrapScriptContent 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 <script sequences the html parser will never enter + * script data double escaped state (see: https://www.w3.org/TR/html53/syntax.html#script-data-double-escaped-state) + * + * While untrusted script content should be made safe before using this api it will + * ensure that the script cannot be early terminated or never terminated state + */ + +function escapeBootstrapScriptContent(scriptText) { + return ('' + scriptText).replace(scriptRegex, scriptReplacer); +} + +const scriptRegex = /(<\/|<)(s)(cript)/gi; + +const scriptReplacer = (match, prefix, s, suffix) => + '' + prefix + (s === 's' ? '\\u0073' : '\\u0053') + suffix; + +// Allows us to keep track of what we've already written so we can refer back to it. +function createResponseState( + identifierPrefix, + nonce, + bootstrapScriptContent, + bootstrapScripts, + bootstrapModules, + externalRuntimeConfig +) { + const idPrefix = identifierPrefix === undefined ? '' : identifierPrefix; + const inlineScriptWithNonce = + nonce === undefined + ? startInlineScript + : stringToPrecomputedChunk( + '<script nonce="' + escapeTextForBrowser(nonce) + '">' + ); + const bootstrapChunks = []; + + if (bootstrapScriptContent !== undefined) { + bootstrapChunks.push( + inlineScriptWithNonce, + stringToChunk(escapeBootstrapScriptContent(bootstrapScriptContent)), + endInlineScript + ); + } + + if (bootstrapScripts !== undefined) { + for (let i = 0; i < bootstrapScripts.length; i++) { + const scriptConfig = bootstrapScripts[i]; + const src = + typeof scriptConfig === 'string' ? scriptConfig : scriptConfig.src; + const integrity = + typeof scriptConfig === 'string' ? undefined : scriptConfig.integrity; + bootstrapChunks.push( + startScriptSrc, + stringToChunk(escapeTextForBrowser(src)) + ); + + if (integrity) { + bootstrapChunks.push( + scriptIntegirty, + stringToChunk(escapeTextForBrowser(integrity)) + ); + } + + bootstrapChunks.push(endAsyncScript); + } + } + + if (bootstrapModules !== undefined) { + for (let i = 0; i < bootstrapModules.length; i++) { + const scriptConfig = bootstrapModules[i]; + const src = + typeof scriptConfig === 'string' ? scriptConfig : scriptConfig.src; + const integrity = + typeof scriptConfig === 'string' ? undefined : scriptConfig.integrity; + bootstrapChunks.push( + startModuleSrc, + stringToChunk(escapeTextForBrowser(src)) + ); + + if (integrity) { + bootstrapChunks.push( + scriptIntegirty, + stringToChunk(escapeTextForBrowser(integrity)) + ); + } + + bootstrapChunks.push(endAsyncScript); + } + } + + return { + bootstrapChunks: bootstrapChunks, + startInlineScript: inlineScriptWithNonce, + placeholderPrefix: stringToPrecomputedChunk(idPrefix + 'P:'), + segmentPrefix: stringToPrecomputedChunk(idPrefix + 'S:'), + boundaryPrefix: idPrefix + 'B:', + idPrefix: idPrefix, nextSuspenseID: 0, - sentCompleteSegmentFunction: !1, - sentCompleteBoundaryFunction: !1, - sentClientRenderFunction: !1, + sentCompleteSegmentFunction: false, + sentCompleteBoundaryFunction: false, + sentClientRenderFunction: false, + sentStyleInsertionFunction: false, + }; +} // Constants for the insertion mode we're currently writing in. We don't encode all HTML5 insertion +// modes. We only include the variants as they matter for the sake of our purposes. +// We don't actually provide the namespace therefore we use constants instead of the string. + +const ROOT_HTML_MODE = 0; // Used for the root most element tag. + +const HTML_MODE = 1; +const SVG_MODE = 2; +const MATHML_MODE = 3; +const HTML_TABLE_MODE = 4; +const HTML_TABLE_BODY_MODE = 5; +const HTML_TABLE_ROW_MODE = 6; +const HTML_COLGROUP_MODE = 7; // We have a greater than HTML_TABLE_MODE check elsewhere. If you add more cases here, make sure it +// still makes sense + +function createFormatContext(insertionMode, selectedValue, noscriptTagInScope) { + return { + insertionMode, + selectedValue, + noscriptTagInScope, }; } -function B(a, b) { - return { insertionMode: a, selectedValue: b }; -} -function ya(a) { - return B( - "http://www.w3.org/2000/svg" === a - ? 2 - : "http://www.w3.org/1998/Math/MathML" === a - ? 3 - : 0, - null + +function createRootFormatContext(namespaceURI) { + const insertionMode = + namespaceURI === 'http://www.w3.org/2000/svg' + ? SVG_MODE + : namespaceURI === 'http://www.w3.org/1998/Math/MathML' + ? MATHML_MODE + : ROOT_HTML_MODE; + return createFormatContext(insertionMode, null, false); +} +function getChildFormatContext(parentContext, type, props) { + switch (type) { + case 'noscript': + return createFormatContext(HTML_MODE, null, true); + + case 'select': + return createFormatContext( + HTML_MODE, + props.value != null ? props.value : props.defaultValue, + parentContext.noscriptTagInScope + ); + + case 'svg': + return createFormatContext( + SVG_MODE, + null, + parentContext.noscriptTagInScope + ); + + case 'math': + return createFormatContext( + MATHML_MODE, + null, + parentContext.noscriptTagInScope + ); + + case 'foreignObject': + return createFormatContext( + HTML_MODE, + null, + parentContext.noscriptTagInScope + ); + // Table parents are special in that their children can only be created at all if they're + // wrapped in a table parent. So we need to encode that we're entering this mode. + + case 'table': + return createFormatContext( + HTML_TABLE_MODE, + null, + parentContext.noscriptTagInScope + ); + + case 'thead': + case 'tbody': + case 'tfoot': + return createFormatContext( + HTML_TABLE_BODY_MODE, + null, + parentContext.noscriptTagInScope + ); + + case 'colgroup': + return createFormatContext( + HTML_COLGROUP_MODE, + null, + parentContext.noscriptTagInScope + ); + + case 'tr': + return createFormatContext( + HTML_TABLE_ROW_MODE, + null, + parentContext.noscriptTagInScope + ); + } + + if (parentContext.insertionMode >= HTML_TABLE_MODE) { + // Whatever tag this was, it wasn't a table parent or other special parent, so we must have + // entered plain HTML again. + return createFormatContext( + HTML_MODE, + null, + parentContext.noscriptTagInScope + ); + } + + if (parentContext.insertionMode === ROOT_HTML_MODE) { + // We've emitted the root and is now in plain HTML mode. + return createFormatContext( + HTML_MODE, + null, + parentContext.noscriptTagInScope + ); + } + + return parentContext; +} +const UNINITIALIZED_SUSPENSE_BOUNDARY_ID = null; +function assignSuspenseBoundaryID(responseState) { + const generatedID = responseState.nextSuspenseID++; + return stringToPrecomputedChunk( + responseState.boundaryPrefix + generatedID.toString(16) + ); +} +function makeId(responseState, treeId, localId) { + const idPrefix = responseState.idPrefix; + let id = ':' + idPrefix + 'R' + treeId; // Unless this is the first id at this level, append a number at the end + // that represents the position of this useId hook among all the useId + // hooks for this fiber. + + if (localId > 0) { + id += 'H' + localId.toString(32); + } + + return id + ':'; +} + +function encodeHTMLTextNode(text) { + return escapeTextForBrowser(text); +} + +const textSeparator = stringToPrecomputedChunk('<!-- -->'); +function pushTextInstance(target, text, responseState, textEmbedded) { + if (text === '') { + // Empty text doesn't have a DOM node representation and the hydration is aware of this. + return textEmbedded; + } + + if (textEmbedded) { + target.push(textSeparator); + } + + target.push(stringToChunk(encodeHTMLTextNode(text))); + return true; +} // Called when Fizz is done with a Segment. Currently the only purpose is to conditionally +// emit a text separator when we don't know for sure it is safe to omit + +function pushSegmentFinale( + target, + responseState, + lastPushedText, + textEmbedded +) { + if (lastPushedText && textEmbedded) { + target.push(textSeparator); + } +} +const styleNameCache = new Map(); + +function processStyleName(styleName) { + const chunk = styleNameCache.get(styleName); + + if (chunk !== undefined) { + return chunk; + } + + const result = stringToPrecomputedChunk( + escapeTextForBrowser(hyphenateStyleName(styleName)) ); + styleNameCache.set(styleName, result); + return result; } -function za(a, b, c) { - switch (b) { - case "select": - return B(1, null != c.value ? c.value : c.defaultValue); - case "svg": - return B(2, null); - case "math": - return B(3, null); - case "foreignObject": - return B(1, null); - case "table": - return B(4, null); - case "thead": - case "tbody": - case "tfoot": - return B(5, null); - case "colgroup": - return B(7, null); - case "tr": - return B(6, null); - } - return 4 <= a.insertionMode || 0 === a.insertionMode ? B(1, null) : a; -} -var Aa = v("\x3c!-- --\x3e"), - Ba = new Map(), - Ca = v(' style="'), - Da = v(":"), - Ea = v(";"); -function Fa(a, b, c) { - if ("object" !== typeof c) throw Error(k(62)); - b = !0; - for (var d in c) - if (w.call(c, d)) { - var f = c[d]; - if (null != f && "boolean" !== typeof f && "" !== f) { - if (0 === d.indexOf("--")) { - var e = u(A(d)); - f = u(A(("" + f).trim())); + +const styleAttributeStart = stringToPrecomputedChunk(' style="'); +const styleAssign = stringToPrecomputedChunk(':'); +const styleSeparator = stringToPrecomputedChunk(';'); + +function pushStyle(target, responseState, style) { + if (typeof style !== 'object') { + throw new Error( + 'The `style` prop expects a mapping from style properties to values, ' + + "not a string. For example, style={{marginRight: spacing + 'em'}} when " + + 'using JSX.' + ); + } + + let isFirst = true; + + for (const styleName in style) { + if (!hasOwnProperty.call(style, styleName)) { + continue; + } // If you provide unsafe user data here they can inject arbitrary CSS + // which may be problematic (I couldn't repro this): + // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet + // http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/ + // This is not an XSS hole but instead a potential CSS injection issue + // which has lead to a greater discussion about how we're going to + // trust URLs moving forward. See #2115901 + + const styleValue = style[styleName]; + + if ( + styleValue == null || + typeof styleValue === 'boolean' || + styleValue === '' + ) { + // TODO: We used to set empty string as a style with an empty value. Does that ever make sense? + continue; + } + + let nameChunk; + let valueChunk; + const isCustomProperty = styleName.indexOf('--') === 0; + + if (isCustomProperty) { + nameChunk = stringToChunk(escapeTextForBrowser(styleName)); + + valueChunk = stringToChunk( + escapeTextForBrowser(('' + styleValue).trim()) + ); + } else { + nameChunk = processStyleName(styleName); + + if (typeof styleValue === 'number') { + if ( + styleValue !== 0 && + !hasOwnProperty.call(isUnitlessNumber, styleName) + ) { + valueChunk = stringToChunk(styleValue + 'px'); // Presumes implicit 'px' suffix for unitless numbers } else { - e = d; - var g = Ba.get(e); - void 0 !== g - ? (e = g) - : ((g = v( - A(e.replace(na, "-$1").toLowerCase().replace(oa, "-ms-")) - )), - Ba.set(e, g), - (e = g)); - f = - "number" === typeof f - ? 0 === f || w.call(z, d) - ? u("" + f) - : u(f + "px") - : u(A(("" + f).trim())); + valueChunk = stringToChunk('' + styleValue); } - b ? ((b = !1), a.push(Ca, e, Da, f)) : a.push(Ea, e, Da, f); + } else { + valueChunk = stringToChunk( + escapeTextForBrowser(('' + styleValue).trim()) + ); } } - b || a.push(D); + + if (isFirst) { + isFirst = false; // If it's first, we don't need any separators prefixed. + + target.push(styleAttributeStart, nameChunk, styleAssign, valueChunk); + } else { + target.push(styleSeparator, nameChunk, styleAssign, valueChunk); + } + } + + if (!isFirst) { + target.push(attributeEnd); + } } -var G = v(" "), - H = v('="'), - D = v('"'), - Ga = v('=""'); -function I(a, b, c, d) { - switch (c) { - case "style": - Fa(a, b, d); + +const attributeSeparator = stringToPrecomputedChunk(' '); +const attributeAssign = stringToPrecomputedChunk('="'); +const attributeEnd = stringToPrecomputedChunk('"'); +const attributeEmptyString = stringToPrecomputedChunk('=""'); + +function pushAttribute(target, responseState, name, value) { + switch (name) { + case 'style': { + pushStyle(target, responseState, value); return; - case "defaultValue": - case "defaultChecked": - case "innerHTML": - case "suppressContentEditableWarning": - case "suppressHydrationWarning": + } + + case 'defaultValue': + case 'defaultChecked': // These shouldn't be set as attributes on generic HTML elements. + + case 'innerHTML': // Must use dangerouslySetInnerHTML instead. + + case 'suppressContentEditableWarning': + case 'suppressHydrationWarning': + // Ignored. These are built-in to React on the client. return; } + if ( - !(2 < c.length) || - ("o" !== c[0] && "O" !== c[0]) || - ("n" !== c[1] && "N" !== c[1]) - ) - if (((b = y.hasOwnProperty(c) ? y[c] : null), null !== b)) { - switch (typeof d) { - case "function": - case "symbol": + // shouldIgnoreAttribute + // We have already filtered out null/undefined and reserved words. + name.length > 2 && + (name[0] === 'o' || name[0] === 'O') && + (name[1] === 'n' || name[1] === 'N') + ) { + return; + } + + const propertyInfo = getPropertyInfo(name); + + if (propertyInfo !== null) { + // shouldRemoveAttribute + switch (typeof value) { + case 'function': + case 'symbol': + // eslint-disable-line + return; + + case 'boolean': { + if (!propertyInfo.acceptsBooleans) { return; - case "boolean": - if (!b.acceptsBooleans) return; + } + } + } + + const attributeName = propertyInfo.attributeName; + const attributeNameChunk = stringToChunk(attributeName); // TODO: If it's known we can cache the chunk. + + switch (propertyInfo.type) { + case BOOLEAN: + if (value) { + target.push( + attributeSeparator, + attributeNameChunk, + attributeEmptyString + ); + } + + return; + + case OVERLOADED_BOOLEAN: + if (value === true) { + target.push( + attributeSeparator, + attributeNameChunk, + attributeEmptyString + ); + } else if (value === false); + else { + target.push( + attributeSeparator, + attributeNameChunk, + attributeAssign, + stringToChunk(escapeTextForBrowser(value)), + attributeEnd + ); + } + + return; + + case NUMERIC: + if (!isNaN(value)) { + target.push( + attributeSeparator, + attributeNameChunk, + attributeAssign, + stringToChunk(escapeTextForBrowser(value)), + attributeEnd + ); + } + + break; + + case POSITIVE_NUMERIC: + if (!isNaN(value) && value >= 1) { + target.push( + attributeSeparator, + attributeNameChunk, + attributeAssign, + stringToChunk(escapeTextForBrowser(value)), + attributeEnd + ); + } + + break; + + default: + if (propertyInfo.sanitizeURL) { + value = '' + value; + } + + target.push( + attributeSeparator, + attributeNameChunk, + attributeAssign, + stringToChunk(escapeTextForBrowser(value)), + attributeEnd + ); + } + } else if (isAttributeNameSafe(name)) { + // shouldRemoveAttribute + switch (typeof value) { + case 'function': + case 'symbol': + // eslint-disable-line + return; + + case 'boolean': { + const prefix = name.toLowerCase().slice(0, 5); + + if (prefix !== 'data-' && prefix !== 'aria-') { + return; + } + } + } + + target.push( + attributeSeparator, + stringToChunk(name), + attributeAssign, + stringToChunk(escapeTextForBrowser(value)), + attributeEnd + ); + } +} + +const endOfStartTag = stringToPrecomputedChunk('>'); +const endOfStartTagSelfClosing = stringToPrecomputedChunk('/>'); + +function pushInnerHTML(target, innerHTML, children) { + if (innerHTML != null) { + if (children != null) { + throw new Error( + 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.' + ); + } + + if (typeof innerHTML !== 'object' || !('__html' in innerHTML)) { + throw new Error( + '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' + + 'Please visit https://reactjs.org/link/dangerously-set-inner-html ' + + 'for more information.' + ); + } + + const html = innerHTML.__html; + + if (html !== null && html !== undefined) { + target.push(stringToChunk('' + html)); + } + } +} // TODO: Move these to ResponseState so that we warn for every request. + +function pushStartSelect(target, props, responseState) { + target.push(startChunkForTag('select')); + let children = null; + let innerHTML = null; + + for (const propKey in props) { + if (hasOwnProperty.call(props, propKey)) { + const propValue = props[propKey]; + + if (propValue == null) { + continue; } - c = u(b.attributeName); - switch (b.type) { - case 3: - d && a.push(G, c, Ga); + + switch (propKey) { + case 'children': + children = propValue; break; - case 4: - !0 === d ? a.push(G, c, Ga) : !1 !== d && a.push(G, c, H, u(A(d)), D); + + case 'dangerouslySetInnerHTML': + // TODO: This doesn't really make sense for select since it can't use the controlled + // value in the innerHTML. + innerHTML = propValue; break; - case 5: - isNaN(d) || a.push(G, c, H, u(A(d)), D); + + case 'defaultValue': + case 'value': + // These are set on the Context instead and applied to the nested options. break; - case 6: - !isNaN(d) && 1 <= d && a.push(G, c, H, u(A(d)), D); + + default: + pushAttribute(target, responseState, propKey, propValue); + break; + } + } + } + + target.push(endOfStartTag); + pushInnerHTML(target, innerHTML, children); + return children; +} + +function flattenOptionChildren(children) { + let content = ''; // Flatten children and warn if they aren't strings or numbers; + // invalid types are ignored. + + Children.forEach(children, function (child) { + if (child == null) { + return; + } + + content += child; + }); + return content; +} + +const selectedMarkerAttribute = stringToPrecomputedChunk(' selected=""'); + +function pushStartOption(target, props, responseState, formatContext) { + const selectedValue = formatContext.selectedValue; + target.push(startChunkForTag('option')); + let children = null; + let value = null; + let selected = null; + let innerHTML = null; + + for (const propKey in props) { + if (hasOwnProperty.call(props, propKey)) { + const propValue = props[propKey]; + + if (propValue == null) { + continue; + } + + switch (propKey) { + case 'children': + children = propValue; + break; + + case 'selected': + // ignore + selected = propValue; + break; + + case 'dangerouslySetInnerHTML': + innerHTML = propValue; + break; + // eslint-disable-next-line-no-fallthrough + + case 'value': + value = propValue; + // We intentionally fallthrough to also set the attribute on the node. + // eslint-disable-next-line-no-fallthrough + default: - b.sanitizeURL && (d = "" + d), a.push(G, c, H, u(A(d)), D); + pushAttribute(target, responseState, propKey, propValue); + break; } - } else if (ia(c)) { - switch (typeof d) { - case "function": - case "symbol": - return; - case "boolean": + } + } + + if (selectedValue != null) { + let stringValue; + + if (value !== null) { + stringValue = '' + value; + } else { + stringValue = flattenOptionChildren(children); + } + + if (isArray(selectedValue)) { + // multiple + for (let i = 0; i < selectedValue.length; i++) { + const v = '' + selectedValue[i]; + + if (v === stringValue) { + target.push(selectedMarkerAttribute); + break; + } + } + } else { + if ('' + selectedValue === stringValue) { + target.push(selectedMarkerAttribute); + } + } + } else if (selected) { + target.push(selectedMarkerAttribute); + } + + target.push(endOfStartTag); + pushInnerHTML(target, innerHTML, children); + return children; +} + +function pushInput(target, props, responseState) { + target.push(startChunkForTag('input')); + let value = null; + let defaultValue = null; + let checked = null; + let defaultChecked = null; + + for (const propKey in props) { + if (hasOwnProperty.call(props, propKey)) { + const propValue = props[propKey]; + + if (propValue == null) { + continue; + } + + switch (propKey) { + case 'children': + case 'dangerouslySetInnerHTML': + throw new Error( + 'input' + + ' is a self-closing tag and must neither have `children` nor ' + + 'use `dangerouslySetInnerHTML`.' + ); + // eslint-disable-next-line-no-fallthrough + + case 'defaultChecked': + defaultChecked = propValue; + break; + + case 'defaultValue': + defaultValue = propValue; + break; + + case 'checked': + checked = propValue; + break; + + case 'value': + value = propValue; + break; + + default: + pushAttribute(target, responseState, propKey, propValue); + break; + } + } + } + + if (checked !== null) { + pushAttribute(target, responseState, 'checked', checked); + } else if (defaultChecked !== null) { + pushAttribute(target, responseState, 'checked', defaultChecked); + } + + if (value !== null) { + pushAttribute(target, responseState, 'value', value); + } else if (defaultValue !== null) { + pushAttribute(target, responseState, 'value', defaultValue); + } + + target.push(endOfStartTagSelfClosing); + return null; +} + +function pushStartTextArea(target, props, responseState) { + target.push(startChunkForTag('textarea')); + let value = null; + let defaultValue = null; + let children = null; + + for (const propKey in props) { + if (hasOwnProperty.call(props, propKey)) { + const propValue = props[propKey]; + + if (propValue == null) { + continue; + } + + switch (propKey) { + case 'children': + children = propValue; + break; + + case 'value': + value = propValue; + break; + + case 'defaultValue': + defaultValue = propValue; + break; + + case 'dangerouslySetInnerHTML': + throw new Error( + '`dangerouslySetInnerHTML` does not make sense on <textarea>.' + ); + // eslint-disable-next-line-no-fallthrough + + default: + pushAttribute(target, responseState, propKey, propValue); + break; + } + } + } + + if (value === null && defaultValue !== null) { + value = defaultValue; + } + + target.push(endOfStartTag); // TODO (yungsters): Remove support for children content in <textarea>. + + if (children != null) { + if (value != null) { + throw new Error( + 'If you supply `defaultValue` on a <textarea>, do not pass children.' + ); + } + + if (isArray(children)) { + if (children.length > 1) { + throw new Error('<textarea> can only have at most one child.'); + } // TODO: remove the coercion and the DEV check below because it will + + value = '' + children[0]; + } + + value = '' + children; + } + + if (typeof value === 'string' && value[0] === '\n') { + // text/html ignores the first character in these tags if it's a newline + // Prefer to break application/xml over text/html (for now) by adding + // a newline specifically to get eaten by the parser. (Alternately for + // textareas, replacing "^\n" with "\r\n" doesn't get eaten, and the first + // \r is normalized out by HTMLTextAreaElement#value.) + // See: <http://www.w3.org/TR/html-polyglot/#newlines-in-textarea-and-pre> + // See: <http://www.w3.org/TR/html5/syntax.html#element-restrictions> + // See: <http://www.w3.org/TR/html5/syntax.html#newlines> + // See: Parsing of "textarea" "listing" and "pre" elements + // from <http://www.w3.org/TR/html5/syntax.html#parsing-main-inbody> + target.push(leadingNewline); + } // ToString and push directly instead of recurse over children. + // We don't really support complex children in the value anyway. + // This also currently avoids a trailing comment node which breaks textarea. + + if (value !== null) { + target.push(stringToChunk(encodeHTMLTextNode('' + value))); + } + + return null; +} + +function pushBase( + target, + props, + responseState, + textEmbedded, + noscriptTagInScope +) { + if (!noscriptTagInScope && resourcesFromElement('base', props)) { + if (textEmbedded) { + // This link follows text but we aren't writing a tag. while not as efficient as possible we need + // to be safe and assume text will follow by inserting a textSeparator + target.push(textSeparator); + } // We have converted this link exclusively to a resource and no longer + // need to emit it + + return null; + } + + return pushSelfClosing(target, props, 'base', responseState); +} + +function pushMeta( + target, + props, + responseState, + textEmbedded, + noscriptTagInScope +) { + if (!noscriptTagInScope && resourcesFromElement('meta', props)) { + if (textEmbedded) { + // This link follows text but we aren't writing a tag. while not as efficient as possible we need + // to be safe and assume text will follow by inserting a textSeparator + target.push(textSeparator); + } // We have converted this link exclusively to a resource and no longer + // need to emit it + + return null; + } + + return pushSelfClosing(target, props, 'meta', responseState); +} + +function pushLink( + target, + props, + responseState, + textEmbedded, + noscriptTagInScope +) { + if (!noscriptTagInScope && resourcesFromLink(props)) { + if (textEmbedded) { + // This link follows text but we aren't writing a tag. while not as efficient as possible we need + // to be safe and assume text will follow by inserting a textSeparator + target.push(textSeparator); + } // We have converted this link exclusively to a resource and no longer + // need to emit it + + return null; + } + + return pushLinkImpl(target, props, responseState); +} + +function pushLinkImpl(target, props, responseState) { + const isStylesheet = props.rel === 'stylesheet'; + target.push(startChunkForTag('link')); + + for (const propKey in props) { + if (hasOwnProperty.call(props, propKey)) { + const propValue = props[propKey]; + + if (propValue == null) { + continue; + } + + switch (propKey) { + case 'children': + case 'dangerouslySetInnerHTML': + throw new Error( + 'link' + + ' is a self-closing tag and must neither have `children` nor ' + + 'use `dangerouslySetInnerHTML`.' + ); + + case 'precedence': { + if (isStylesheet) { + // precedence is a reversed property for stylesheets to opt-into resource semantcs + continue; + } // intentionally fall through + } + // eslint-disable-next-line-no-fallthrough + + default: + pushAttribute(target, responseState, propKey, propValue); + break; + } + } + } + + target.push(endOfStartTagSelfClosing); + return null; +} + +function pushSelfClosing(target, props, tag, responseState) { + target.push(startChunkForTag(tag)); + + for (const propKey in props) { + if (hasOwnProperty.call(props, propKey)) { + const propValue = props[propKey]; + + if (propValue == null) { + continue; + } + + switch (propKey) { + case 'children': + case 'dangerouslySetInnerHTML': + throw new Error( + tag + + ' is a self-closing tag and must neither have `children` nor ' + + 'use `dangerouslySetInnerHTML`.' + ); + // eslint-disable-next-line-no-fallthrough + + default: + pushAttribute(target, responseState, propKey, propValue); + break; + } + } + } + + target.push(endOfStartTagSelfClosing); + return null; +} + +function pushStartMenuItem(target, props, responseState) { + target.push(startChunkForTag('menuitem')); + + for (const propKey in props) { + if (hasOwnProperty.call(props, propKey)) { + const propValue = props[propKey]; + + if (propValue == null) { + continue; + } + + switch (propKey) { + case 'children': + case 'dangerouslySetInnerHTML': + throw new Error( + 'menuitems cannot have `children` nor `dangerouslySetInnerHTML`.' + ); + // eslint-disable-next-line-no-fallthrough + + default: + pushAttribute(target, responseState, propKey, propValue); + break; + } + } + } + + target.push(endOfStartTag); + return null; +} + +function pushTitle(target, props, responseState, noscriptTagInScope) { + if (!noscriptTagInScope && resourcesFromElement('title', props)) { + // We have converted this link exclusively to a resource and no longer + // need to emit it + return null; + } + + return pushTitleImpl(target, props, responseState); +} + +function pushTitleImpl(target, props, responseState) { + target.push(startChunkForTag('title')); + let children = null; + + for (const propKey in props) { + if (hasOwnProperty.call(props, propKey)) { + const propValue = props[propKey]; + + if (propValue == null) { + continue; + } + + switch (propKey) { + case 'children': + children = propValue; + break; + + case 'dangerouslySetInnerHTML': + throw new Error( + '`dangerouslySetInnerHTML` does not make sense on <title>.' + ); + // eslint-disable-next-line-no-fallthrough + + default: + pushAttribute(target, responseState, propKey, propValue); + break; + } + } + } + + target.push(endOfStartTag); + const child = + Array.isArray(children) && children.length < 2 + ? children[0] || null + : children; + + if (typeof child === 'string' || typeof child === 'number') { + target.push(stringToChunk(escapeTextForBrowser(child))); + } + + target.push(endTag1, stringToChunk('title'), endTag2); + return null; +} + +function pushStartHead(target, preamble, props, tag, responseState) { + return pushStartGenericElement(preamble, props, tag, responseState); +} + +function pushStartHtml( + target, + preamble, + props, + tag, + responseState, + formatContext +) { + target = preamble; + + if (formatContext.insertionMode === ROOT_HTML_MODE) { + // If we're rendering the html tag and we're at the root (i.e. not in foreignObject) + // then we also emit the DOCTYPE as part of the root content as a convenience for + // rendering the whole document. + target.push(DOCTYPE); + } + + return pushStartGenericElement(target, props, tag, responseState); +} + +function pushScript( + target, + props, + responseState, + textEmbedded, + noscriptTagInScope +) { + if (!noscriptTagInScope && resourcesFromScript(props)) { + if (textEmbedded) { + // This link follows text but we aren't writing a tag. while not as efficient as possible we need + // to be safe and assume text will follow by inserting a textSeparator + target.push(textSeparator); + } // We have converted this link exclusively to a resource and no longer + // need to emit it + + return null; + } + + return pushScriptImpl(target, props, responseState); +} + +function pushScriptImpl(target, props, responseState) { + target.push(startChunkForTag('script')); + let children = null; + let innerHTML = null; + + for (const propKey in props) { + if (hasOwnProperty.call(props, propKey)) { + const propValue = props[propKey]; + + if (propValue == null) { + continue; + } + + switch (propKey) { + case 'children': + children = propValue; + break; + + case 'dangerouslySetInnerHTML': + innerHTML = propValue; + break; + + default: + pushAttribute(target, responseState, propKey, propValue); + break; + } + } + } + + target.push(endOfStartTag); + + pushInnerHTML(target, innerHTML, children); + + if (typeof children === 'string') { + target.push(stringToChunk(encodeHTMLTextNode(children))); + } + + target.push(endTag1, stringToChunk('script'), endTag2); + return null; +} + +function pushStartGenericElement(target, props, tag, responseState) { + target.push(startChunkForTag(tag)); + let children = null; + let innerHTML = null; + + for (const propKey in props) { + if (hasOwnProperty.call(props, propKey)) { + const propValue = props[propKey]; + + if (propValue == null) { + continue; + } + + switch (propKey) { + case 'children': + children = propValue; + break; + + case 'dangerouslySetInnerHTML': + innerHTML = propValue; + break; + + default: + pushAttribute(target, responseState, propKey, propValue); + break; + } + } + } + + target.push(endOfStartTag); + pushInnerHTML(target, innerHTML, children); + + if (typeof children === 'string') { + // Special case children as a string to avoid the unnecessary comment. + // TODO: Remove this special case after the general optimization is in place. + target.push(stringToChunk(encodeHTMLTextNode(children))); + return null; + } + + return children; +} + +function pushStartCustomElement(target, props, tag, responseState) { + target.push(startChunkForTag(tag)); + let children = null; + let innerHTML = null; + + for (let propKey in props) { + if (hasOwnProperty.call(props, propKey)) { + let propValue = props[propKey]; + + if (propValue == null) { + continue; + } + + if (typeof propValue === 'function' || typeof propValue === 'object') { + // It is normal to render functions and objects on custom elements when + // client rendering, but when server rendering the output isn't useful, + // so skip it. + continue; + } + + if (propValue === false) { + continue; + } + + if (propValue === true) { + propValue = ''; + } + + if (propKey === 'className') { + // className gets rendered as class on the client, so it should be + // rendered as class on the server. + propKey = 'class'; + } + + switch (propKey) { + case 'children': + children = propValue; + break; + + case 'dangerouslySetInnerHTML': + innerHTML = propValue; + break; + + case 'style': + pushStyle(target, responseState, propValue); + break; + + case 'suppressContentEditableWarning': + case 'suppressHydrationWarning': + // Ignored. These are built-in to React on the client. + break; + + default: if ( - ((b = c.toLowerCase().slice(0, 5)), "data-" !== b && "aria-" !== b) - ) - return; + isAttributeNameSafe(propKey) && + typeof propValue !== 'function' && + typeof propValue !== 'symbol' + ) { + target.push( + attributeSeparator, + stringToChunk(propKey), + attributeAssign, + stringToChunk(escapeTextForBrowser(propValue)), + attributeEnd + ); + } + + break; + } + } + } + + target.push(endOfStartTag); + pushInnerHTML(target, innerHTML, children); + return children; +} + +const leadingNewline = stringToPrecomputedChunk('\n'); + +function pushStartPreformattedElement(target, props, tag, responseState) { + target.push(startChunkForTag(tag)); + let children = null; + let innerHTML = null; + + for (const propKey in props) { + if (hasOwnProperty.call(props, propKey)) { + const propValue = props[propKey]; + + if (propValue == null) { + continue; + } + + switch (propKey) { + case 'children': + children = propValue; + break; + + case 'dangerouslySetInnerHTML': + innerHTML = propValue; + break; + + default: + pushAttribute(target, responseState, propKey, propValue); + break; + } + } + } + + target.push(endOfStartTag); // text/html ignores the first character in these tags if it's a newline + // Prefer to break application/xml over text/html (for now) by adding + // a newline specifically to get eaten by the parser. (Alternately for + // textareas, replacing "^\n" with "\r\n" doesn't get eaten, and the first + // \r is normalized out by HTMLTextAreaElement#value.) + // See: <http://www.w3.org/TR/html-polyglot/#newlines-in-textarea-and-pre> + // See: <http://www.w3.org/TR/html5/syntax.html#element-restrictions> + // See: <http://www.w3.org/TR/html5/syntax.html#newlines> + // See: Parsing of "textarea" "listing" and "pre" elements + // from <http://www.w3.org/TR/html5/syntax.html#parsing-main-inbody> + // TODO: This doesn't deal with the case where the child is an array + // or component that returns a string. + + if (innerHTML != null) { + if (children != null) { + throw new Error( + 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.' + ); + } + + if (typeof innerHTML !== 'object' || !('__html' in innerHTML)) { + throw new Error( + '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' + + 'Please visit https://reactjs.org/link/dangerously-set-inner-html ' + + 'for more information.' + ); + } + + const html = innerHTML.__html; + + if (html !== null && html !== undefined) { + if (typeof html === 'string' && html.length > 0 && html[0] === '\n') { + target.push(leadingNewline, stringToChunk(html)); + } else { + target.push(stringToChunk('' + html)); + } + } + } + + if (typeof children === 'string' && children[0] === '\n') { + target.push(leadingNewline); + } + + return children; +} // We accept any tag to be rendered but since this gets injected into arbitrary +// HTML, we want to make sure that it's a safe tag. +// http://www.w3.org/TR/REC-xml/#NT-Name + +const VALID_TAG_REGEX = /^[a-zA-Z][a-zA-Z:_\.\-\d]*$/; // Simplified subset + +const validatedTagCache = new Map(); + +function startChunkForTag(tag) { + let tagStartChunk = validatedTagCache.get(tag); + + if (tagStartChunk === undefined) { + if (!VALID_TAG_REGEX.test(tag)) { + throw new Error('Invalid tag: ' + tag); + } + + tagStartChunk = stringToPrecomputedChunk('<' + tag); + validatedTagCache.set(tag, tagStartChunk); + } + + return tagStartChunk; +} + +const DOCTYPE = stringToPrecomputedChunk('<!DOCTYPE html>'); +function pushStartInstance( + target, + preamble, + type, + props, + responseState, + formatContext, + textEmbedded +) { + switch (type) { + // Special tags + case 'select': + return pushStartSelect(target, props, responseState); + + case 'option': + return pushStartOption(target, props, responseState, formatContext); + + case 'textarea': + return pushStartTextArea(target, props, responseState); + + case 'input': + return pushInput(target, props, responseState); + + case 'menuitem': + return pushStartMenuItem(target, props, responseState); + + case 'title': + return pushTitle( + target, + props, + responseState, + formatContext.noscriptTagInScope + ); + + case 'link': + return pushLink( + target, + props, + responseState, + textEmbedded, + formatContext.noscriptTagInScope + ); + + case 'script': + return pushScript( + target, + props, + responseState, + textEmbedded, + formatContext.noscriptTagInScope + ); + + case 'meta': + return pushMeta( + target, + props, + responseState, + textEmbedded, + formatContext.noscriptTagInScope + ); + + case 'base': + return pushBase( + target, + props, + responseState, + textEmbedded, + formatContext.noscriptTagInScope + ); + // Newline eating tags + + case 'listing': + case 'pre': { + return pushStartPreformattedElement(target, props, type, responseState); + } + // Omitted close tags + + case 'area': + case 'br': + case 'col': + case 'embed': + case 'hr': + case 'img': + case 'keygen': + case 'param': + case 'source': + case 'track': + case 'wbr': { + return pushSelfClosing(target, props, type, responseState); + } + // These are reserved SVG and MathML elements, that are never custom elements. + // https://w3c.github.io/webcomponents/spec/custom/#custom-elements-core-concepts + + 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': { + return pushStartGenericElement(target, props, type, responseState); + } + // Preamble start tags + + case 'head': + return pushStartHead(target, preamble, props, type, responseState); + + case 'html': { + return pushStartHtml( + target, + preamble, + props, + type, + responseState, + formatContext + ); + } + + default: { + if (type.indexOf('-') === -1 && typeof props.is !== 'string') { + // Generic element + return pushStartGenericElement(target, props, type, responseState); + } else { + // Custom element + return pushStartCustomElement(target, props, type, responseState); + } + } + } +} +const endTag1 = stringToPrecomputedChunk('</'); +const endTag2 = stringToPrecomputedChunk('>'); +function pushEndInstance(target, postamble, type, props) { + switch (type) { + // When float is on we expect title and script tags to always be pushed in + // a unit and never return children. when we end up pushing the end tag we + // want to ensure there is no extra closing tag pushed + case 'title': + case 'script': + // Omitted close tags + // TODO: Instead of repeating this switch we could try to pass a flag from above. + // That would require returning a tuple. Which might be ok if it gets inlined. + // eslint-disable-next-line-no-fallthrough + + case 'area': + case 'base': + case 'br': + case 'col': + case 'embed': + case 'hr': + case 'img': + case 'input': + case 'keygen': + case 'link': + case 'meta': + case 'param': + case 'source': + case 'track': + case 'wbr': { + // No close tag needed. + return; + } + // Postamble end tags + + case 'body': { + { + postamble.unshift(endTag1, stringToChunk(type), endTag2); + return; } - a.push(G, u(c), H, u(A(d)), D); } + + case 'html': { + postamble.push(endTag1, stringToChunk(type), endTag2); + return; + } + } + + target.push(endTag1, stringToChunk(type), endTag2); } -var J = v(">"), - Ha = v("/>"); -function K(a, b, c) { - if (null != b) { - if (null != c) throw Error(k(60)); - if ("object" !== typeof b || !("__html" in b)) throw Error(k(61)); - b = b.__html; - null !== b && void 0 !== b && a.push(u("" + b)); +function writeCompletedRoot(destination, responseState) { + const bootstrapChunks = responseState.bootstrapChunks; + let i = 0; + + for (; i < bootstrapChunks.length - 1; i++) { + writeChunk(destination, bootstrapChunks[i]); + } + + if (i < bootstrapChunks.length) { + return writeChunkAndReturn(destination, bootstrapChunks[i]); } + + return true; +} // Structural Nodes +// A placeholder is a node inside a hidden partial tree that can be filled in later, but before +// display. It's never visible to users. We use the template tag because it can be used in every +// type of parent. <script> tags also work in every other tag except <colgroup>. + +const placeholder1 = stringToPrecomputedChunk('<template id="'); +const placeholder2 = stringToPrecomputedChunk('"></template>'); +function writePlaceholder(destination, responseState, id) { + writeChunk(destination, placeholder1); + writeChunk(destination, responseState.placeholderPrefix); + const formattedID = stringToChunk(id.toString(16)); + writeChunk(destination, formattedID); + return writeChunkAndReturn(destination, placeholder2); +} // Suspense boundaries are encoded as comments. + +const startCompletedSuspenseBoundary = stringToPrecomputedChunk('<!--$-->'); +const startPendingSuspenseBoundary1 = stringToPrecomputedChunk( + '<!--$?--><template id="' +); +const startPendingSuspenseBoundary2 = stringToPrecomputedChunk('"></template>'); +const startClientRenderedSuspenseBoundary = + stringToPrecomputedChunk('<!--$!-->'); +const endSuspenseBoundary = stringToPrecomputedChunk('<!--/$-->'); +const clientRenderedSuspenseBoundaryError1 = + stringToPrecomputedChunk('<template'); +const clientRenderedSuspenseBoundaryErrorAttrInterstitial = + stringToPrecomputedChunk('"'); +const clientRenderedSuspenseBoundaryError1A = + stringToPrecomputedChunk(' data-dgst="'); +const clientRenderedSuspenseBoundaryError2 = + stringToPrecomputedChunk('></template>'); +function writeStartCompletedSuspenseBoundary(destination, responseState) { + return writeChunkAndReturn(destination, startCompletedSuspenseBoundary); } -function Ia(a) { - var b = ""; - aa.Children.forEach(a, function (a) { - null != a && (b += a); +function writeStartPendingSuspenseBoundary(destination, responseState, id) { + writeChunk(destination, startPendingSuspenseBoundary1); + + if (id === null) { + throw new Error( + 'An ID must have been assigned before we can complete the boundary.' + ); + } + + writeChunk(destination, id); + return writeChunkAndReturn(destination, startPendingSuspenseBoundary2); +} +function writeStartClientRenderedSuspenseBoundary( + destination, + responseState, + errorDigest, + errorMesssage, + errorComponentStack +) { + let result; + result = writeChunkAndReturn( + destination, + startClientRenderedSuspenseBoundary + ); + writeChunk(destination, clientRenderedSuspenseBoundaryError1); + + if (errorDigest) { + writeChunk(destination, clientRenderedSuspenseBoundaryError1A); + writeChunk(destination, stringToChunk(escapeTextForBrowser(errorDigest))); + writeChunk( + destination, + clientRenderedSuspenseBoundaryErrorAttrInterstitial + ); + } + + result = writeChunkAndReturn( + destination, + clientRenderedSuspenseBoundaryError2 + ); + return result; +} +function writeEndCompletedSuspenseBoundary(destination, responseState) { + return writeChunkAndReturn(destination, endSuspenseBoundary); +} +function writeEndPendingSuspenseBoundary(destination, responseState) { + return writeChunkAndReturn(destination, endSuspenseBoundary); +} +function writeEndClientRenderedSuspenseBoundary(destination, responseState) { + return writeChunkAndReturn(destination, endSuspenseBoundary); +} +const startSegmentHTML = stringToPrecomputedChunk('<div hidden id="'); +const startSegmentHTML2 = stringToPrecomputedChunk('">'); +const endSegmentHTML = stringToPrecomputedChunk('</div>'); +const startSegmentSVG = stringToPrecomputedChunk( + '<svg aria-hidden="true" style="display:none" id="' +); +const startSegmentSVG2 = stringToPrecomputedChunk('">'); +const endSegmentSVG = stringToPrecomputedChunk('</svg>'); +const startSegmentMathML = stringToPrecomputedChunk( + '<math aria-hidden="true" style="display:none" id="' +); +const startSegmentMathML2 = stringToPrecomputedChunk('">'); +const endSegmentMathML = stringToPrecomputedChunk('</math>'); +const startSegmentTable = stringToPrecomputedChunk('<table hidden id="'); +const startSegmentTable2 = stringToPrecomputedChunk('">'); +const endSegmentTable = stringToPrecomputedChunk('</table>'); +const startSegmentTableBody = stringToPrecomputedChunk( + '<table hidden><tbody id="' +); +const startSegmentTableBody2 = stringToPrecomputedChunk('">'); +const endSegmentTableBody = stringToPrecomputedChunk('</tbody></table>'); +const startSegmentTableRow = stringToPrecomputedChunk('<table hidden><tr id="'); +const startSegmentTableRow2 = stringToPrecomputedChunk('">'); +const endSegmentTableRow = stringToPrecomputedChunk('</tr></table>'); +const startSegmentColGroup = stringToPrecomputedChunk( + '<table hidden><colgroup id="' +); +const startSegmentColGroup2 = stringToPrecomputedChunk('">'); +const endSegmentColGroup = stringToPrecomputedChunk('</colgroup></table>'); +function writeStartSegment(destination, responseState, formatContext, id) { + switch (formatContext.insertionMode) { + case ROOT_HTML_MODE: + case HTML_MODE: { + writeChunk(destination, startSegmentHTML); + writeChunk(destination, responseState.segmentPrefix); + writeChunk(destination, stringToChunk(id.toString(16))); + return writeChunkAndReturn(destination, startSegmentHTML2); + } + + case SVG_MODE: { + writeChunk(destination, startSegmentSVG); + writeChunk(destination, responseState.segmentPrefix); + writeChunk(destination, stringToChunk(id.toString(16))); + return writeChunkAndReturn(destination, startSegmentSVG2); + } + + case MATHML_MODE: { + writeChunk(destination, startSegmentMathML); + writeChunk(destination, responseState.segmentPrefix); + writeChunk(destination, stringToChunk(id.toString(16))); + return writeChunkAndReturn(destination, startSegmentMathML2); + } + + case HTML_TABLE_MODE: { + writeChunk(destination, startSegmentTable); + writeChunk(destination, responseState.segmentPrefix); + writeChunk(destination, stringToChunk(id.toString(16))); + return writeChunkAndReturn(destination, startSegmentTable2); + } + // TODO: For the rest of these, there will be extra wrapper nodes that never + // get deleted from the document. We need to delete the table too as part + // of the injected scripts. They are invisible though so it's not too terrible + // and it's kind of an edge case to suspend in a table. Totally supported though. + + case HTML_TABLE_BODY_MODE: { + writeChunk(destination, startSegmentTableBody); + writeChunk(destination, responseState.segmentPrefix); + writeChunk(destination, stringToChunk(id.toString(16))); + return writeChunkAndReturn(destination, startSegmentTableBody2); + } + + case HTML_TABLE_ROW_MODE: { + writeChunk(destination, startSegmentTableRow); + writeChunk(destination, responseState.segmentPrefix); + writeChunk(destination, stringToChunk(id.toString(16))); + return writeChunkAndReturn(destination, startSegmentTableRow2); + } + + case HTML_COLGROUP_MODE: { + writeChunk(destination, startSegmentColGroup); + writeChunk(destination, responseState.segmentPrefix); + writeChunk(destination, stringToChunk(id.toString(16))); + return writeChunkAndReturn(destination, startSegmentColGroup2); + } + + default: { + throw new Error('Unknown insertion mode. This is a bug in React.'); + } + } +} +function writeEndSegment(destination, formatContext) { + switch (formatContext.insertionMode) { + case ROOT_HTML_MODE: + case HTML_MODE: { + return writeChunkAndReturn(destination, endSegmentHTML); + } + + case SVG_MODE: { + return writeChunkAndReturn(destination, endSegmentSVG); + } + + case MATHML_MODE: { + return writeChunkAndReturn(destination, endSegmentMathML); + } + + case HTML_TABLE_MODE: { + return writeChunkAndReturn(destination, endSegmentTable); + } + + case HTML_TABLE_BODY_MODE: { + return writeChunkAndReturn(destination, endSegmentTableBody); + } + + case HTML_TABLE_ROW_MODE: { + return writeChunkAndReturn(destination, endSegmentTableRow); + } + + case HTML_COLGROUP_MODE: { + return writeChunkAndReturn(destination, endSegmentColGroup); + } + + default: { + throw new Error('Unknown insertion mode. This is a bug in React.'); + } + } +} +const completeSegmentScript1Full = stringToPrecomputedChunk( + completeSegment + ';$RS("' +); +const completeSegmentScript1Partial = stringToPrecomputedChunk('$RS("'); +const completeSegmentScript2 = stringToPrecomputedChunk('","'); +const completeSegmentScript3 = stringToPrecomputedChunk('")</script>'); +function writeCompletedSegmentInstruction( + destination, + responseState, + contentSegmentID +) { + writeChunk(destination, responseState.startInlineScript); + + if (!responseState.sentCompleteSegmentFunction) { + // The first time we write this, we'll need to include the full implementation. + responseState.sentCompleteSegmentFunction = true; + writeChunk(destination, completeSegmentScript1Full); + } else { + // Future calls can just reuse the same function. + writeChunk(destination, completeSegmentScript1Partial); + } + + writeChunk(destination, responseState.segmentPrefix); + const formattedID = stringToChunk(contentSegmentID.toString(16)); + writeChunk(destination, formattedID); + writeChunk(destination, completeSegmentScript2); + writeChunk(destination, responseState.placeholderPrefix); + writeChunk(destination, formattedID); + return writeChunkAndReturn(destination, completeSegmentScript3); +} +const completeBoundaryScript1Full = stringToPrecomputedChunk( + completeBoundary + ';$RC("' +); +const completeBoundaryScript1Partial = stringToPrecomputedChunk('$RC("'); +const completeBoundaryWithStylesScript1FullBoth = stringToPrecomputedChunk( + completeBoundary + ';' + completeBoundaryWithStyles + ';$RR("' +); +const completeBoundaryWithStylesScript1FullPartial = stringToPrecomputedChunk( + completeBoundaryWithStyles + ';$RR("' +); +const completeBoundaryWithStylesScript1Partial = + stringToPrecomputedChunk('$RR("'); +const completeBoundaryScript2 = stringToPrecomputedChunk('","'); +const completeBoundaryScript2a = stringToPrecomputedChunk('",'); +const completeBoundaryScript3 = stringToPrecomputedChunk('"'); +const completeBoundaryScript4 = stringToPrecomputedChunk(')</script>'); +function writeCompletedBoundaryInstruction( + destination, + responseState, + boundaryID, + contentSegmentID, + boundaryResources +) { + let hasStyleDependencies; + + { + hasStyleDependencies = hasStyleResourceDependencies(boundaryResources); + } + + writeChunk(destination, responseState.startInlineScript); + + if (hasStyleDependencies) { + if (!responseState.sentCompleteBoundaryFunction) { + responseState.sentCompleteBoundaryFunction = true; + responseState.sentStyleInsertionFunction = true; + writeChunk(destination, completeBoundaryWithStylesScript1FullBoth); + } else if (!responseState.sentStyleInsertionFunction) { + responseState.sentStyleInsertionFunction = true; + writeChunk(destination, completeBoundaryWithStylesScript1FullPartial); + } else { + writeChunk(destination, completeBoundaryWithStylesScript1Partial); + } + } else { + if (!responseState.sentCompleteBoundaryFunction) { + responseState.sentCompleteBoundaryFunction = true; + writeChunk(destination, completeBoundaryScript1Full); + } else { + writeChunk(destination, completeBoundaryScript1Partial); + } + } + + if (boundaryID === null) { + throw new Error( + 'An ID must have been assigned before we can complete the boundary.' + ); + } + + const formattedContentID = stringToChunk(contentSegmentID.toString(16)); + writeChunk(destination, boundaryID); + writeChunk(destination, completeBoundaryScript2); + writeChunk(destination, responseState.segmentPrefix); + writeChunk(destination, formattedContentID); + + if (hasStyleDependencies) { + writeChunk(destination, completeBoundaryScript2a); + writeStyleResourceDependencies(destination, boundaryResources); + } else { + writeChunk(destination, completeBoundaryScript3); + } + + return writeChunkAndReturn(destination, completeBoundaryScript4); +} +const clientRenderScript1Full = stringToPrecomputedChunk( + clientRenderBoundary + ';$RX("' +); +const clientRenderScript1Partial = stringToPrecomputedChunk('$RX("'); +const clientRenderScript1A = stringToPrecomputedChunk('"'); +const clientRenderScript2 = stringToPrecomputedChunk(')</script>'); +const clientRenderErrorScriptArgInterstitial = stringToPrecomputedChunk(','); +function writeClientRenderBoundaryInstruction( + destination, + responseState, + boundaryID, + errorDigest, + errorMessage, + errorComponentStack +) { + writeChunk(destination, responseState.startInlineScript); + + if (!responseState.sentClientRenderFunction) { + // The first time we write this, we'll need to include the full implementation. + responseState.sentClientRenderFunction = true; + writeChunk(destination, clientRenderScript1Full); + } else { + // Future calls can just reuse the same function. + writeChunk(destination, clientRenderScript1Partial); + } + + if (boundaryID === null) { + throw new Error( + 'An ID must have been assigned before we can complete the boundary.' + ); + } + + writeChunk(destination, boundaryID); + writeChunk(destination, clientRenderScript1A); + + if (errorDigest || errorMessage || errorComponentStack) { + writeChunk(destination, clientRenderErrorScriptArgInterstitial); + writeChunk( + destination, + stringToChunk(escapeJSStringsForInstructionScripts(errorDigest || '')) + ); + } + + if (errorMessage || errorComponentStack) { + writeChunk(destination, clientRenderErrorScriptArgInterstitial); + writeChunk( + destination, + stringToChunk(escapeJSStringsForInstructionScripts(errorMessage || '')) + ); + } + + if (errorComponentStack) { + writeChunk(destination, clientRenderErrorScriptArgInterstitial); + writeChunk( + destination, + stringToChunk(escapeJSStringsForInstructionScripts(errorComponentStack)) + ); + } + + return writeChunkAndReturn(destination, clientRenderScript2); +} +const regexForJSStringsInInstructionScripts = /[<\u2028\u2029]/g; + +function escapeJSStringsForInstructionScripts(input) { + const escaped = JSON.stringify(input); + return escaped.replace(regexForJSStringsInInstructionScripts, (match) => { + switch (match) { + // santizing breaking out of strings and script tags + case '<': + return '\\u003c'; + + case '\u2028': + return '\\u2028'; + + case '\u2029': + return '\\u2029'; + + default: { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error( + 'escapeJSStringsForInstructionScripts encountered a match it does not know how to replace. this means the match regex and the replacement characters are no longer in sync. This is a bug in React' + ); + } + } + }); +} + +const regexForJSStringsInScripts = /[&><\u2028\u2029]/g; + +function escapeJSObjectForInstructionScripts(input) { + const escaped = JSON.stringify(input); + return escaped.replace(regexForJSStringsInScripts, (match) => { + switch (match) { + // santizing breaking out of strings and script tags + case '&': + return '\\u0026'; + + case '>': + return '\\u003e'; + + case '<': + return '\\u003c'; + + case '\u2028': + return '\\u2028'; + + case '\u2029': + return '\\u2029'; + + default: { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error( + 'escapeJSObjectForInstructionScripts encountered a match it does not know how to replace. this means the match regex and the replacement characters are no longer in sync. This is a bug in React' + ); + } + } + }); +} + +const precedencePlaceholderStart = stringToPrecomputedChunk( + '<style data-precedence="' +); +const precedencePlaceholderEnd = stringToPrecomputedChunk('"></style>'); +function writeInitialResources(destination, resources, responseState) { + function flushLinkResource(resource) { + if (!resource.flushed) { + pushLinkImpl(target, resource.props, responseState); + resource.flushed = true; + } + } + + const target = []; + const charset = resources.charset, + bases = resources.bases, + preconnects = resources.preconnects, + fontPreloads = resources.fontPreloads, + precedences = resources.precedences, + usedStylePreloads = resources.usedStylePreloads, + scripts = resources.scripts, + usedScriptPreloads = resources.usedScriptPreloads, + explicitStylePreloads = resources.explicitStylePreloads, + explicitScriptPreloads = resources.explicitScriptPreloads, + headResources = resources.headResources; + + if (charset) { + pushSelfClosing(target, charset.props, 'meta', responseState); + charset.flushed = true; + resources.charset = null; + } + + bases.forEach((r) => { + pushSelfClosing(target, r.props, 'base', responseState); + r.flushed = true; + }); + bases.clear(); + preconnects.forEach((r) => { + // font preload Resources should not already be flushed so we elide this check + pushLinkImpl(target, r.props, responseState); + r.flushed = true; + }); + preconnects.clear(); + fontPreloads.forEach((r) => { + // font preload Resources should not already be flushed so we elide this check + pushLinkImpl(target, r.props, responseState); + r.flushed = true; + }); + fontPreloads.clear(); // Flush stylesheets first by earliest precedence + + precedences.forEach((p, precedence) => { + if (p.size) { + p.forEach((r) => { + // resources should not already be flushed so we elide this check + pushLinkImpl(target, r.props, responseState); + r.flushed = true; + r.inShell = true; + r.hint.flushed = true; + }); + p.clear(); + } else { + target.push( + precedencePlaceholderStart, + stringToChunk(escapeTextForBrowser(precedence)), + precedencePlaceholderEnd + ); + } + }); + usedStylePreloads.forEach(flushLinkResource); + usedStylePreloads.clear(); + scripts.forEach((r) => { + // should never be flushed already + pushScriptImpl(target, r.props, responseState); + r.flushed = true; + r.hint.flushed = true; + }); + scripts.clear(); + usedScriptPreloads.forEach(flushLinkResource); + usedScriptPreloads.clear(); + explicitStylePreloads.forEach(flushLinkResource); + explicitStylePreloads.clear(); + explicitScriptPreloads.forEach(flushLinkResource); + explicitScriptPreloads.clear(); + headResources.forEach((r) => { + switch (r.type) { + case 'title': { + pushTitleImpl(target, r.props, responseState); + break; + } + + case 'meta': { + pushSelfClosing(target, r.props, 'meta', responseState); + break; + } + + case 'link': { + pushLinkImpl(target, r.props, responseState); + break; + } + } + + r.flushed = true; + }); + headResources.clear(); + let i; + let r = true; + + for (i = 0; i < target.length - 1; i++) { + writeChunk(destination, target[i]); + } + + if (i < target.length) { + r = writeChunkAndReturn(destination, target[i]); + } + + return r; +} +function writeImmediateResources(destination, resources, responseState) { + function flushLinkResource(resource) { + if (!resource.flushed) { + pushLinkImpl(target, resource.props, responseState); + resource.flushed = true; + } + } + + const target = []; + const charset = resources.charset, + preconnects = resources.preconnects, + fontPreloads = resources.fontPreloads, + usedStylePreloads = resources.usedStylePreloads, + scripts = resources.scripts, + usedScriptPreloads = resources.usedScriptPreloads, + explicitStylePreloads = resources.explicitStylePreloads, + explicitScriptPreloads = resources.explicitScriptPreloads, + headResources = resources.headResources; + + if (charset) { + pushSelfClosing(target, charset.props, 'meta', responseState); + charset.flushed = true; + resources.charset = null; + } + + preconnects.forEach((r) => { + // font preload Resources should not already be flushed so we elide this check + pushLinkImpl(target, r.props, responseState); + r.flushed = true; + }); + preconnects.clear(); + fontPreloads.forEach((r) => { + // font preload Resources should not already be flushed so we elide this check + pushLinkImpl(target, r.props, responseState); + r.flushed = true; }); - return b; -} -var Ja = v(' selected=""'); -function Ka(a, b, c, d) { - a.push(L(c)); - var f = (c = null), - e; - for (e in b) - if (w.call(b, e)) { - var g = b[e]; - if (null != g) - switch (e) { - case "children": - c = g; - break; - case "dangerouslySetInnerHTML": - f = g; - break; - default: - I(a, d, e, g); + fontPreloads.clear(); + usedStylePreloads.forEach(flushLinkResource); + usedStylePreloads.clear(); + scripts.forEach((r) => { + // should never be flushed already + pushStartGenericElement(target, r.props, 'script', responseState); + pushEndInstance(target, target, 'script', r.props); + r.flushed = true; + r.hint.flushed = true; + }); + scripts.clear(); + usedScriptPreloads.forEach(flushLinkResource); + usedScriptPreloads.clear(); + explicitStylePreloads.forEach(flushLinkResource); + explicitStylePreloads.clear(); + explicitScriptPreloads.forEach(flushLinkResource); + explicitScriptPreloads.clear(); + headResources.forEach((r) => { + switch (r.type) { + case 'title': { + pushTitleImpl(target, r.props, responseState); + break; + } + + case 'meta': { + pushSelfClosing(target, r.props, 'meta', responseState); + break; + } + + case 'link': { + pushLinkImpl(target, r.props, responseState); + break; + } + } + + r.flushed = true; + }); + headResources.clear(); + let i; + let r = true; + + for (i = 0; i < target.length - 1; i++) { + writeChunk(destination, target[i]); + } + + if (i < target.length) { + r = writeChunkAndReturn(destination, target[i]); + } + + return r; +} + +function hasStyleResourceDependencies(boundaryResources) { + const iter = boundaryResources.values(); // At the moment boundaries only accumulate style resources + // so we assume the type is correct and don't check it + + while (true) { + const _iter$next = iter.next(), + resource = _iter$next.value; + + if (!resource) break; // If every style Resource flushed in the shell we do not need to send + // any dependencies + + if (!resource.inShell) { + return true; + } + } + + return false; +} + +const arrayFirstOpenBracket = stringToPrecomputedChunk('['); +const arraySubsequentOpenBracket = stringToPrecomputedChunk(',['); +const arrayInterstitial = stringToPrecomputedChunk(','); +const arrayCloseBracket = stringToPrecomputedChunk(']'); + +function writeStyleResourceDependencies(destination, boundaryResources) { + writeChunk(destination, arrayFirstOpenBracket); + let nextArrayOpenBrackChunk = arrayFirstOpenBracket; + boundaryResources.forEach((resource) => { + if (resource.inShell); + else if (resource.flushed) { + writeChunk(destination, nextArrayOpenBrackChunk); + writeStyleResourceDependencyHrefOnly(destination, resource.href); + writeChunk(destination, arrayCloseBracket); + nextArrayOpenBrackChunk = arraySubsequentOpenBracket; + } else { + writeChunk(destination, nextArrayOpenBrackChunk); + writeStyleResourceDependency( + destination, + resource.href, + resource.precedence, + resource.props + ); + writeChunk(destination, arrayCloseBracket); + nextArrayOpenBrackChunk = arraySubsequentOpenBracket; + resource.flushed = true; + resource.hint.flushed = true; + } + }); + writeChunk(destination, arrayCloseBracket); +} + +function writeStyleResourceDependencyHrefOnly(destination, href) { + const coercedHref = '' + href; + writeChunk( + destination, + stringToChunk(escapeJSObjectForInstructionScripts(coercedHref)) + ); +} + +function writeStyleResourceDependency(destination, href, precedence, props) { + const coercedHref = '' + href; + writeChunk( + destination, + stringToChunk(escapeJSObjectForInstructionScripts(coercedHref)) + ); + + const coercedPrecedence = '' + precedence; + writeChunk(destination, arrayInterstitial); + writeChunk( + destination, + stringToChunk(escapeJSObjectForInstructionScripts(coercedPrecedence)) + ); + + for (const propKey in props) { + if (hasOwnProperty.call(props, propKey)) { + const propValue = props[propKey]; + + if (propValue == null) { + continue; + } + + switch (propKey) { + case 'href': + case 'rel': + case 'precedence': + case 'data-precedence': { + break; } + + case 'children': + case 'dangerouslySetInnerHTML': + throw new Error( + 'link' + + ' is a self-closing tag and must neither have `children` nor ' + + 'use `dangerouslySetInnerHTML`.' + ); + // eslint-disable-next-line-no-fallthrough + + default: + writeStyleResourceAttribute(destination, propKey, propValue); + break; + } } - a.push(J); - K(a, f, c); - return "string" === typeof c ? (a.push(u(A(c))), null) : c; -} -var La = v("\n"), - Ma = /^[a-zA-Z][a-zA-Z:_\.\-\d]*$/, - Na = new Map(); -function L(a) { - var b = Na.get(a); - if (void 0 === b) { - if (!Ma.test(a)) throw Error(k(65, a)); - b = v("<" + a); - Na.set(a, b); - } - return b; -} -var Oa = v("<!DOCTYPE html>"); -function Pa(a, b, c, d, f) { - switch (b) { - case "select": - a.push(L("select")); - var e = null, - g = null; - for (r in c) - if (w.call(c, r)) { - var h = c[r]; - if (null != h) - switch (r) { - case "children": - e = h; - break; - case "dangerouslySetInnerHTML": - g = h; - break; - case "defaultValue": - case "value": - break; - default: - I(a, d, r, h); - } + } + + return null; +} + +function writeStyleResourceAttribute(destination, name, value) { + let attributeName = name.toLowerCase(); + let attributeValue; + + switch (typeof value) { + case 'function': + case 'symbol': + return; + } + + switch (name) { + // Reserved names + case 'innerHTML': + case 'dangerouslySetInnerHTML': + case 'suppressContentEditableWarning': + case 'suppressHydrationWarning': + case 'style': + // Ignored + return; + // Attribute renames + + case 'className': + attributeName = 'class'; + break; + // Booleans + + case 'hidden': + if (value === false) { + return; + } + + attributeValue = ''; + break; + // Santized URLs + + case 'src': + case 'href': { + attributeValue = '' + value; + break; + } + + default: { + if (!isAttributeNameSafe(name)) { + return; + } + } + } + + if ( + // shouldIgnoreAttribute + // We have already filtered out null/undefined and reserved words. + name.length > 2 && + (name[0] === 'o' || name[0] === 'O') && + (name[1] === 'n' || name[1] === 'N') + ) { + return; + } + + attributeValue = '' + value; + writeChunk(destination, arrayInterstitial); + writeChunk( + destination, + stringToChunk(escapeJSObjectForInstructionScripts(attributeName)) + ); + writeChunk(destination, arrayInterstitial); + writeChunk( + destination, + stringToChunk(escapeJSObjectForInstructionScripts(attributeValue)) + ); +} + +// ATTENTION +// When adding new symbols to this file, +// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' +// The Symbol used to tag the ReactElement-like types. +const REACT_ELEMENT_TYPE = Symbol.for('react.element'); +const REACT_PORTAL_TYPE = Symbol.for('react.portal'); +const REACT_FRAGMENT_TYPE = Symbol.for('react.fragment'); +const REACT_STRICT_MODE_TYPE = Symbol.for('react.strict_mode'); +const REACT_PROFILER_TYPE = Symbol.for('react.profiler'); +const REACT_PROVIDER_TYPE = Symbol.for('react.provider'); +const REACT_CONTEXT_TYPE = Symbol.for('react.context'); +const REACT_SERVER_CONTEXT_TYPE = Symbol.for('react.server_context'); +const REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref'); +const REACT_SUSPENSE_TYPE = Symbol.for('react.suspense'); +const REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list'); +const REACT_MEMO_TYPE = Symbol.for('react.memo'); +const REACT_LAZY_TYPE = Symbol.for('react.lazy'); +const REACT_SCOPE_TYPE = Symbol.for('react.scope'); +const REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for('react.debug_trace_mode'); +const REACT_OFFSCREEN_TYPE = Symbol.for('react.offscreen'); +const REACT_LEGACY_HIDDEN_TYPE = Symbol.for('react.legacy_hidden'); +const REACT_CACHE_TYPE = Symbol.for('react.cache'); +const REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED = Symbol.for( + 'react.default_value' +); +const REACT_MEMO_CACHE_SENTINEL = Symbol.for('react.memo_cache_sentinel'); +const MAYBE_ITERATOR_SYMBOL = Symbol.iterator; +const FAUX_ITERATOR_SYMBOL = '@@iterator'; +function getIteratorFn(maybeIterable) { + if (maybeIterable === null || typeof maybeIterable !== 'object') { + return null; + } + + const maybeIterator = + (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || + maybeIterable[FAUX_ITERATOR_SYMBOL]; + + if (typeof maybeIterator === 'function') { + return maybeIterator; + } + + return null; +} + +function getWrappedName(outerType, innerType, wrapperName) { + const displayName = outerType.displayName; + + if (displayName) { + return displayName; + } + + const functionName = innerType.displayName || innerType.name || ''; + return functionName !== '' + ? wrapperName + '(' + functionName + ')' + : wrapperName; +} // Keep in sync with react-reconciler/getComponentNameFromFiber + +function getContextName(type) { + return type.displayName || 'Context'; +} // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. + +function getComponentNameFromType(type) { + if (type == null) { + // Host root, text node or just invalid type. + return null; + } + + if (typeof type === 'function') { + return type.displayName || type.name || null; + } + + if (typeof type === 'string') { + return type; + } + + switch (type) { + case REACT_FRAGMENT_TYPE: + return 'Fragment'; + + case REACT_PORTAL_TYPE: + return 'Portal'; + + case REACT_PROFILER_TYPE: + return 'Profiler'; + + case REACT_STRICT_MODE_TYPE: + return 'StrictMode'; + + case REACT_SUSPENSE_TYPE: + return 'Suspense'; + + case REACT_SUSPENSE_LIST_TYPE: + return 'SuspenseList'; + + case REACT_CACHE_TYPE: { + return 'Cache'; + } + } + + if (typeof type === 'object') { + switch (type.$$typeof) { + case REACT_CONTEXT_TYPE: + const context = type; + return getContextName(context) + '.Consumer'; + + case REACT_PROVIDER_TYPE: + const provider = type; + return getContextName(provider._context) + '.Provider'; + + case REACT_FORWARD_REF_TYPE: + return getWrappedName(type, type.render, 'ForwardRef'); + + case REACT_MEMO_TYPE: + const outerName = type.displayName || null; + + if (outerName !== null) { + return outerName; } - a.push(J); - K(a, g, e); - return e; - case "option": - g = f.selectedValue; - a.push(L("option")); - var m = (h = null), - q = null; - var r = null; - for (e in c) - if (w.call(c, e) && ((b = c[e]), null != b)) - switch (e) { - case "children": - h = b; - break; - case "selected": - q = b; - break; - case "dangerouslySetInnerHTML": - r = b; - break; - case "value": - m = b; - default: - I(a, d, e, b); - } - if (null != g) - if (((c = null !== m ? "" + m : Ia(h)), pa(g))) - for (d = 0; d < g.length; d++) { - if ("" + g[d] === c) { - a.push(Ja); - break; - } - } - else "" + g === c && a.push(Ja); - else q && a.push(Ja); - a.push(J); - K(a, r, h); - return h; - case "textarea": - a.push(L("textarea")); - r = g = e = null; - for (h in c) - if (w.call(c, h) && ((m = c[h]), null != m)) - switch (h) { - case "children": - r = m; - break; - case "value": - e = m; - break; - case "defaultValue": - g = m; - break; - case "dangerouslySetInnerHTML": - throw Error(k(91)); - default: - I(a, d, h, m); - } - null === e && null !== g && (e = g); - a.push(J); - if (null != r) { - if (null != e) throw Error(k(92)); - if (pa(r) && 1 < r.length) throw Error(k(93)); - e = "" + r; - } - "string" === typeof e && "\n" === e[0] && a.push(La); - null !== e && a.push(u(A("" + e))); - return null; - case "input": - a.push(L("input")); - m = r = h = e = null; - for (g in c) - if (w.call(c, g) && ((q = c[g]), null != q)) - switch (g) { - case "children": - case "dangerouslySetInnerHTML": - throw Error(k(399, "input")); - case "defaultChecked": - m = q; - break; - case "defaultValue": - h = q; - break; - case "checked": - r = q; - break; - case "value": - e = q; - break; - default: - I(a, d, g, q); - } - null !== r ? I(a, d, "checked", r) : null !== m && I(a, d, "checked", m); - null !== e ? I(a, d, "value", e) : null !== h && I(a, d, "value", h); - a.push(Ha); - return null; - case "menuitem": - a.push(L("menuitem")); - for (var E in c) - if (w.call(c, E) && ((e = c[E]), null != e)) - switch (E) { - case "children": - case "dangerouslySetInnerHTML": - throw Error(k(400)); - default: - I(a, d, E, e); - } - a.push(J); - return null; - case "listing": - case "pre": - a.push(L(b)); - g = e = null; - for (m in c) - if (w.call(c, m) && ((h = c[m]), null != h)) - switch (m) { - case "children": - e = h; - break; - case "dangerouslySetInnerHTML": - g = h; - break; - default: - I(a, d, m, h); - } - a.push(J); - if (null != g) { - if (null != e) throw Error(k(60)); - if ("object" !== typeof g || !("__html" in g)) throw Error(k(61)); - c = g.__html; - null !== c && - void 0 !== c && - ("string" === typeof c && 0 < c.length && "\n" === c[0] - ? a.push(La, u(c)) - : a.push(u("" + c))); - } - "string" === typeof e && "\n" === e[0] && a.push(La); - return e; - case "area": - case "base": - case "br": - case "col": - case "embed": - case "hr": - case "img": - case "keygen": - case "link": - case "meta": - case "param": - case "source": - case "track": - case "wbr": - a.push(L(b)); - for (var F in c) - if (w.call(c, F) && ((e = c[F]), null != e)) - switch (F) { - case "children": - case "dangerouslySetInnerHTML": - throw Error(k(399, b)); - default: - I(a, d, F, e); - } - a.push(Ha); - return null; - 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": - return Ka(a, c, b, d); - case "html": - return 0 === f.insertionMode && a.push(Oa), Ka(a, c, b, d); - default: - if (-1 === b.indexOf("-") && "string" !== typeof c.is) - return Ka(a, c, b, d); - a.push(L(b)); - g = e = null; - for (q in c) - if (w.call(c, q) && ((h = c[q]), null != h)) - switch (q) { - case "children": - e = h; - break; - case "dangerouslySetInnerHTML": - g = h; - break; - case "style": - Fa(a, d, h); - break; - case "suppressContentEditableWarning": - case "suppressHydrationWarning": - break; - default: - ia(q) && - "function" !== typeof h && - "symbol" !== typeof h && - a.push(G, u(q), H, u(A(h)), D); - } - a.push(J); - K(a, g, e); - return e; - } -} -var Qa = v("</"), - Ra = v(">"), - Sa = v('<template id="'), - Ta = v('"></template>'), - Ua = v("\x3c!--$--\x3e"), - Va = v('\x3c!--$?--\x3e<template id="'), - Wa = v('"></template>'), - Xa = v("\x3c!--$!--\x3e"), - Ya = v("\x3c!--/$--\x3e"); -function Za(a, b, c) { - p(a, Va); - if (null === c) throw Error(k(395)); - p(a, c); - return t(a, Wa); -} -var $a = v('<div hidden id="'), - ab = v('">'), - bb = v("</div>"), - cb = v('<svg aria-hidden="true" style="display:none" id="'), - db = v('">'), - eb = v("</svg>"), - fb = v('<math aria-hidden="true" style="display:none" id="'), - gb = v('">'), - hb = v("</math>"), - ib = v('<table hidden id="'), - jb = v('">'), - kb = v("</table>"), - lb = v('<table hidden><tbody id="'), - mb = v('">'), - nb = v("</tbody></table>"), - ob = v('<table hidden><tr id="'), - pb = v('">'), - qb = v("</tr></table>"), - rb = v('<table hidden><colgroup id="'), - sb = v('">'), - tb = v("</colgroup></table>"); -function ub(a, b, c, d) { - switch (c.insertionMode) { - case 0: - case 1: - return p(a, $a), p(a, b.segmentPrefix), p(a, u(d.toString(16))), t(a, ab); - case 2: - return p(a, cb), p(a, b.segmentPrefix), p(a, u(d.toString(16))), t(a, db); - case 3: - return p(a, fb), p(a, b.segmentPrefix), p(a, u(d.toString(16))), t(a, gb); - case 4: - return p(a, ib), p(a, b.segmentPrefix), p(a, u(d.toString(16))), t(a, jb); - case 5: - return p(a, lb), p(a, b.segmentPrefix), p(a, u(d.toString(16))), t(a, mb); - case 6: - return p(a, ob), p(a, b.segmentPrefix), p(a, u(d.toString(16))), t(a, pb); - case 7: - return p(a, rb), p(a, b.segmentPrefix), p(a, u(d.toString(16))), t(a, sb); - default: - throw Error(k(397)); - } -} -function vb(a, b) { - switch (b.insertionMode) { - case 0: - case 1: - return t(a, bb); - case 2: - return t(a, eb); - case 3: - return t(a, hb); - case 4: - return t(a, kb); - case 5: - return t(a, nb); - case 6: - return t(a, qb); - case 7: - return t(a, tb); - default: - throw Error(k(397)); - } -} -var wb = v( - 'function $RS(a,b){a=document.getElementById(a);b=document.getElementById(b);for(a.parentNode.removeChild(a);a.firstChild;)b.parentNode.insertBefore(a.firstChild,b);b.parentNode.removeChild(b)};$RS("' - ), - xb = v('$RS("'), - yb = v('","'), - zb = v('")\x3c/script>'), - Ab = v( - 'function $RC(a,b){a=document.getElementById(a);b=document.getElementById(b);b.parentNode.removeChild(b);if(a){a=a.previousSibling;var f=a.parentNode,c=a.nextSibling,e=0;do{if(c&&8===c.nodeType){var d=c.data;if("/$"===d)if(0===e)break;else e--;else"$"!==d&&"$?"!==d&&"$!"!==d||e++}d=c.nextSibling;f.removeChild(c);c=d}while(c);for(;b.firstChild;)f.insertBefore(b.firstChild,c);a.data="$";a._reactRetry&&a._reactRetry()}};$RC("' - ), - Bb = v('$RC("'), - Cb = v('","'), - Db = v('")\x3c/script>'), - Eb = v( - 'function $RX(a){if(a=document.getElementById(a))a=a.previousSibling,a.data="$!",a._reactRetry&&a._reactRetry()};$RX("' - ), - Fb = v('$RX("'), - Gb = v('")\x3c/script>'), - M = Object.assign, - Hb = Symbol.for("react.element"), - Ib = Symbol.for("react.portal"), - Jb = Symbol.for("react.fragment"), - Kb = Symbol.for("react.strict_mode"), - Lb = Symbol.for("react.profiler"), - Mb = Symbol.for("react.provider"), - Nb = Symbol.for("react.context"), - Ob = Symbol.for("react.forward_ref"), - Pb = Symbol.for("react.suspense"), - Qb = Symbol.for("react.suspense_list"), - Rb = Symbol.for("react.memo"), - Sb = Symbol.for("react.lazy"), - Tb = Symbol.for("react.scope"), - Ub = Symbol.for("react.debug_trace_mode"), - Vb = Symbol.for("react.legacy_hidden"), - Wb = Symbol.for("react.default_value"), - Xb = Symbol.iterator; -function Yb(a) { - if (null == a) return null; - if ("function" === typeof a) return a.displayName || a.name || null; - if ("string" === typeof a) return a; - switch (a) { - case Jb: - return "Fragment"; - case Ib: - return "Portal"; - case Lb: - return "Profiler"; - case Kb: - return "StrictMode"; - case Pb: - return "Suspense"; - case Qb: - return "SuspenseList"; - } - if ("object" === typeof a) - switch (a.$$typeof) { - case Nb: - return (a.displayName || "Context") + ".Consumer"; - case Mb: - return (a._context.displayName || "Context") + ".Provider"; - case Ob: - var b = a.render; - a = a.displayName; - a || - ((a = b.displayName || b.name || ""), - (a = "" !== a ? "ForwardRef(" + a + ")" : "ForwardRef")); - return a; - case Rb: - return ( - (b = a.displayName || null), null !== b ? b : Yb(a.type) || "Memo" - ); - case Sb: - b = a._payload; - a = a._init; + + return getComponentNameFromType(type.type) || 'Memo'; + + case REACT_LAZY_TYPE: { + const lazyComponent = type; + const payload = lazyComponent._payload; + const init = lazyComponent._init; + try { - return Yb(a(b)); - } catch (c) {} + return getComponentNameFromType(init(payload)); + } catch (x) { + return null; + } + } + + case REACT_SERVER_CONTEXT_TYPE: { + const context2 = type; + return (context2.displayName || context2._globalName) + '.Provider'; + } + + // eslint-disable-next-line no-fallthrough } + } + return null; } -var Zb = {}; -function $b(a, b) { - a = a.contextTypes; - if (!a) return Zb; - var c = {}, - d; - for (d in a) c[d] = b[d]; - return c; -} -var N = null; -function O(a, b) { - if (a !== b) { - a.context._currentValue = a.parentValue; - a = a.parent; - var c = b.parent; - if (null === a) { - if (null !== c) throw Error(k(401)); + +const ReactSharedInternals = + __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED$1; + +const ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; + +const ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; + +const emptyContextObject = {}; + +function getMaskedContext(type, unmaskedContext) { + { + const contextTypes = type.contextTypes; + + if (!contextTypes) { + return emptyContextObject; + } + + const context = {}; + + for (const key in contextTypes) { + context[key] = unmaskedContext[key]; + } + + return context; + } +} +function processChildContext(instance, type, parentContext, childContextTypes) { + { + // TODO (bvaughn) Replace this behavior with an invariant() in the future. + // It has only been added in Fiber to match the (unintentional) behavior in Stack. + if (typeof instance.getChildContext !== 'function') { + return parentContext; + } + + const childContext = instance.getChildContext(); + + for (const contextKey in childContext) { + if (!(contextKey in childContextTypes)) { + throw new Error( + (getComponentNameFromType(type) || 'Unknown') + + '.getChildContext(): key "' + + contextKey + + '" is not defined in childContextTypes.' + ); + } + } + + return assign({}, parentContext, childContext); + } +} + +// Forming a reverse tree. + +const rootContextSnapshot = null; // We assume that this runtime owns the "current" field on all ReactContext instances. +// This global (actually thread local) state represents what state all those "current", +// fields are currently in. + +let currentActiveSnapshot = null; + +function popNode(prev) { + { + prev.context._currentValue = prev.parentValue; + } +} + +function pushNode(next) { + { + next.context._currentValue = next.value; + } +} + +function popToNearestCommonAncestor(prev, next) { + if (prev === next); + else { + popNode(prev); + const parentPrev = prev.parent; + const parentNext = next.parent; + + if (parentPrev === null) { + if (parentNext !== null) { + throw new Error( + 'The stacks must reach the root at the same time. This is a bug in React.' + ); + } } else { - if (null === c) throw Error(k(401)); - O(a, c); - } - b.context._currentValue = b.value; - } -} -function ac(a) { - a.context._currentValue = a.parentValue; - a = a.parent; - null !== a && ac(a); -} -function bc(a) { - var b = a.parent; - null !== b && bc(b); - a.context._currentValue = a.value; -} -function cc(a, b) { - a.context._currentValue = a.parentValue; - a = a.parent; - if (null === a) throw Error(k(402)); - a.depth === b.depth ? O(a, b) : cc(a, b); -} -function dc(a, b) { - var c = b.parent; - if (null === c) throw Error(k(402)); - a.depth === c.depth ? O(a, c) : dc(a, c); - b.context._currentValue = b.value; -} -function P(a) { - var b = N; - b !== a && - (null === b - ? bc(a) - : null === a - ? ac(b) - : b.depth === a.depth - ? O(b, a) - : b.depth > a.depth - ? cc(b, a) - : dc(b, a), - (N = a)); -} -var ec = { - isMounted: function () { - return !1; + if (parentNext === null) { + throw new Error( + 'The stacks must reach the root at the same time. This is a bug in React.' + ); + } + + popToNearestCommonAncestor(parentPrev, parentNext); + } // On the way back, we push the new ones that weren't common. + + pushNode(next); + } +} + +function popAllPrevious(prev) { + popNode(prev); + const parentPrev = prev.parent; + + if (parentPrev !== null) { + popAllPrevious(parentPrev); + } +} + +function pushAllNext(next) { + const parentNext = next.parent; + + if (parentNext !== null) { + pushAllNext(parentNext); + } + + pushNode(next); +} + +function popPreviousToCommonLevel(prev, next) { + popNode(prev); + const parentPrev = prev.parent; + + if (parentPrev === null) { + throw new Error( + 'The depth must equal at least at zero before reaching the root. This is a bug in React.' + ); + } + + if (parentPrev.depth === next.depth) { + // We found the same level. Now we just need to find a shared ancestor. + popToNearestCommonAncestor(parentPrev, next); + } else { + // We must still be deeper. + popPreviousToCommonLevel(parentPrev, next); + } +} + +function popNextToCommonLevel(prev, next) { + const parentNext = next.parent; + + if (parentNext === null) { + throw new Error( + 'The depth must equal at least at zero before reaching the root. This is a bug in React.' + ); + } + + if (prev.depth === parentNext.depth) { + // We found the same level. Now we just need to find a shared ancestor. + popToNearestCommonAncestor(prev, parentNext); + } else { + // We must still be deeper. + popNextToCommonLevel(prev, parentNext); + } + + pushNode(next); +} // Perform context switching to the new snapshot. +// To make it cheap to read many contexts, while not suspending, we make the switch eagerly by +// updating all the context's current values. That way reads, always just read the current value. +// At the cost of updating contexts even if they're never read by this subtree. + +function switchContext(newSnapshot) { + // The basic algorithm we need to do is to pop back any contexts that are no longer on the stack. + // We also need to update any new contexts that are now on the stack with the deepest value. + // The easiest way to update new contexts is to just reapply them in reverse order from the + // perspective of the backpointers. To avoid allocating a lot when switching, we use the stack + // for that. Therefore this algorithm is recursive. + // 1) First we pop which ever snapshot tree was deepest. Popping old contexts as we go. + // 2) Then we find the nearest common ancestor from there. Popping old contexts as we go. + // 3) Then we reapply new contexts on the way back up the stack. + const prev = currentActiveSnapshot; + const next = newSnapshot; + + if (prev !== next) { + if (prev === null) { + // $FlowFixMe: This has to be non-null since it's not equal to prev. + pushAllNext(next); + } else if (next === null) { + popAllPrevious(prev); + } else if (prev.depth === next.depth) { + popToNearestCommonAncestor(prev, next); + } else if (prev.depth > next.depth) { + popPreviousToCommonLevel(prev, next); + } else { + popNextToCommonLevel(prev, next); + } + + currentActiveSnapshot = next; + } +} +function pushProvider(context, nextValue) { + let prevValue; + + { + prevValue = context._currentValue; + context._currentValue = nextValue; + } + + const prevNode = currentActiveSnapshot; + const newNode = { + parent: prevNode, + depth: prevNode === null ? 0 : prevNode.depth + 1, + context: context, + parentValue: prevValue, + value: nextValue, + }; + currentActiveSnapshot = newNode; + return newNode; +} +function popProvider(context) { + const prevSnapshot = currentActiveSnapshot; + + if (prevSnapshot === null) { + throw new Error( + 'Tried to pop a Context at the root of the app. This is a bug in React.' + ); + } + + { + const value = prevSnapshot.parentValue; + + if (value === REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED) { + prevSnapshot.context._currentValue = prevSnapshot.context._defaultValue; + } else { + prevSnapshot.context._currentValue = value; + } + } + + return (currentActiveSnapshot = prevSnapshot.parent); +} +function getActiveContext() { + return currentActiveSnapshot; +} +function readContext(context) { + const value = context._currentValue; + return value; +} + +/** + * `ReactInstanceMap` maintains a mapping from a public facing stateful + * instance (key) and the internal representation (value). This allows public + * methods to accept the user facing instance as an argument and map them back + * to internal methods. + * + * Note that this module is currently shared and assumed to be stateless. + * If this becomes an actual Map, that will break. + */ +function get(key) { + return key._reactInternals; +} +function set(key, value) { + key._reactInternals = value; +} + +const classComponentUpdater = { + isMounted(inst) { + return false; }, - enqueueSetState: function (a, b) { - a = a._reactInternals; - null !== a.queue && a.queue.push(b); + + enqueueSetState(inst, payload, callback) { + const internals = get(inst); + + if (internals.queue === null); + else { + internals.queue.push(payload); + } }, - enqueueReplaceState: function (a, b) { - a = a._reactInternals; - a.replace = !0; - a.queue = [b]; + + enqueueReplaceState(inst, payload, callback) { + const internals = get(inst); + internals.replace = true; + internals.queue = [payload]; + }, + + enqueueForceUpdate(inst, callback) { + const internals = get(inst); + + if (internals.queue === null); }, - enqueueForceUpdate: function () {}, }; -function fc(a, b, c, d) { - var f = void 0 !== a.state ? a.state : null; - a.updater = ec; - a.props = c; - a.state = f; - var e = { queue: [], replace: !1 }; - a._reactInternals = e; - var g = b.contextType; - a.context = "object" === typeof g && null !== g ? g._currentValue : d; - g = b.getDerivedStateFromProps; - "function" === typeof g && - ((g = g(c, f)), - (f = null === g || void 0 === g ? f : M({}, f, g)), - (a.state = f)); - if ( - "function" !== typeof b.getDerivedStateFromProps && - "function" !== typeof a.getSnapshotBeforeUpdate && - ("function" === typeof a.UNSAFE_componentWillMount || - "function" === typeof a.componentWillMount) - ) - if ( - ((b = a.state), - "function" === typeof a.componentWillMount && a.componentWillMount(), - "function" === typeof a.UNSAFE_componentWillMount && - a.UNSAFE_componentWillMount(), - b !== a.state && ec.enqueueReplaceState(a, a.state, null), - null !== e.queue && 0 < e.queue.length) - ) - if ( - ((b = e.queue), - (g = e.replace), - (e.queue = null), - (e.replace = !1), - g && 1 === b.length) - ) - a.state = b[0]; - else { - e = g ? b[0] : a.state; - f = !0; - for (g = g ? 1 : 0; g < b.length; g++) { - var h = b[g]; - h = "function" === typeof h ? h.call(a, e, c, d) : h; - null != h && (f ? ((f = !1), (e = M({}, e, h))) : M(e, h)); + +function applyDerivedStateFromProps( + instance, + ctor, + getDerivedStateFromProps, + prevState, + nextProps +) { + const partialState = getDerivedStateFromProps(nextProps, prevState); + + const newState = + partialState === null || partialState === undefined + ? prevState + : assign({}, prevState, partialState); + return newState; +} + +function constructClassInstance(ctor, props, maskedLegacyContext) { + let context = emptyContextObject; + const contextType = ctor.contextType; + + if (typeof contextType === 'object' && contextType !== null) { + context = readContext(contextType); + } else { + context = maskedLegacyContext; + } + + const instance = new ctor(props, context); + + return instance; +} + +function callComponentWillMount(type, instance) { + const oldState = instance.state; + + if (typeof instance.componentWillMount === 'function') { + instance.componentWillMount(); + } + + if (typeof instance.UNSAFE_componentWillMount === 'function') { + instance.UNSAFE_componentWillMount(); + } + + if (oldState !== instance.state) { + classComponentUpdater.enqueueReplaceState(instance, instance.state, null); + } +} + +function processUpdateQueue( + internalInstance, + inst, + props, + maskedLegacyContext +) { + if (internalInstance.queue !== null && internalInstance.queue.length > 0) { + const oldQueue = internalInstance.queue; + const oldReplace = internalInstance.replace; + internalInstance.queue = null; + internalInstance.replace = false; + + if (oldReplace && oldQueue.length === 1) { + inst.state = oldQueue[0]; + } else { + let nextState = oldReplace ? oldQueue[0] : inst.state; + let dontMutate = true; + + for (let i = oldReplace ? 1 : 0; i < oldQueue.length; i++) { + const partial = oldQueue[i]; + const partialState = + typeof partial === 'function' + ? partial.call(inst, nextState, props, maskedLegacyContext) + : partial; + + if (partialState != null) { + if (dontMutate) { + dontMutate = false; + nextState = assign({}, nextState, partialState); + } else { + assign(nextState, partialState); + } } - a.state = e; - } - else e.queue = null; -} -var gc = { id: 1, overflow: "" }; -function hc(a, b, c) { - var d = a.id; - a = a.overflow; - var f = 32 - Q(d) - 1; - d &= ~(1 << f); - c += 1; - var e = 32 - Q(b) + f; - if (30 < e) { - var g = f - (f % 5); - e = (d & ((1 << g) - 1)).toString(32); - d >>= g; - f -= g; - return { id: (1 << (32 - Q(b) + f)) | (c << f) | d, overflow: e + a }; - } - return { id: (1 << e) | (c << f) | d, overflow: a }; -} -var Q = Math.clz32 ? Math.clz32 : ic, - jc = Math.log, - kc = Math.LN2; -function ic(a) { - a >>>= 0; - return 0 === a ? 32 : (31 - ((jc(a) / kc) | 0)) | 0; -} -function lc(a, b) { - return (a === b && (0 !== a || 1 / a === 1 / b)) || (a !== a && b !== b); -} -var mc = "function" === typeof Object.is ? Object.is : lc, - R = null, - nc = null, - oc = null, - S = null, - T = !1, - pc = !1, - U = 0, - V = null, - qc = 0; -function W() { - if (null === R) throw Error(k(321)); - return R; -} -function rc() { - if (0 < qc) throw Error(k(312)); - return { memoizedState: null, queue: null, next: null }; -} -function sc() { - null === S - ? null === oc - ? ((T = !1), (oc = S = rc())) - : ((T = !0), (S = oc)) - : null === S.next - ? ((T = !1), (S = S.next = rc())) - : ((T = !0), (S = S.next)); - return S; -} -function tc() { - nc = R = null; - pc = !1; - oc = null; - qc = 0; - S = V = null; -} -function uc(a, b) { - return "function" === typeof b ? b(a) : b; -} -function vc(a, b, c) { - R = W(); - S = sc(); - if (T) { - var d = S.queue; - b = d.dispatch; - if (null !== V && ((c = V.get(d)), void 0 !== c)) { - V.delete(d); - d = S.memoizedState; - do (d = a(d, c.action)), (c = c.next); - while (null !== c); - S.memoizedState = d; - return [d, b]; - } - return [S.memoizedState, b]; - } - a = a === uc ? ("function" === typeof b ? b() : b) : void 0 !== c ? c(b) : b; - S.memoizedState = a; - a = S.queue = { last: null, dispatch: null }; - a = a.dispatch = wc.bind(null, R, a); - return [S.memoizedState, a]; -} -function xc(a, b) { - R = W(); - S = sc(); - b = void 0 === b ? null : b; - if (null !== S) { - var c = S.memoizedState; - if (null !== c && null !== b) { - var d = c[1]; - a: if (null === d) d = !1; + } + + inst.state = nextState; + } + } else { + internalInstance.queue = null; + } +} // Invokes the mount life-cycles on a previously never rendered instance. + +function mountClassInstance(instance, ctor, newProps, maskedLegacyContext) { + const initialState = instance.state !== undefined ? instance.state : null; + instance.updater = classComponentUpdater; + instance.props = newProps; + instance.state = initialState; // We don't bother initializing the refs object on the server, since we're not going to resolve them anyway. + // The internal instance will be used to manage updates that happen during this mount. + + const internalInstance = { + queue: [], + replace: false, + }; + set(instance, internalInstance); + const contextType = ctor.contextType; + + if (typeof contextType === 'object' && contextType !== null) { + instance.context = readContext(contextType); + } else { + instance.context = maskedLegacyContext; + } + + const getDerivedStateFromProps = ctor.getDerivedStateFromProps; + + if (typeof getDerivedStateFromProps === 'function') { + instance.state = applyDerivedStateFromProps( + instance, + ctor, + getDerivedStateFromProps, + initialState, + newProps + ); + } // In order to support react-lifecycles-compat polyfilled components, + // Unsafe lifecycles should not be invoked for components using the new APIs. + + if ( + typeof ctor.getDerivedStateFromProps !== 'function' && + typeof instance.getSnapshotBeforeUpdate !== 'function' && + (typeof instance.UNSAFE_componentWillMount === 'function' || + typeof instance.componentWillMount === 'function') + ) { + callComponentWillMount(ctor, instance); // If we had additional state updates during this life-cycle, let's + // process them now. + + processUpdateQueue( + internalInstance, + instance, + newProps, + maskedLegacyContext + ); + } +} + +// Ids are base 32 strings whose binary representation corresponds to the +// position of a node in a tree. +// Every time the tree forks into multiple children, we add additional bits to +// the left of the sequence that represent the position of the child within the +// current level of children. +// +// 00101 00010001011010101 +// ╰─┬─╯ ╰───────┬───────╯ +// Fork 5 of 20 Parent id +// +// The leading 0s are important. In the above example, you only need 3 bits to +// represent slot 5. However, you need 5 bits to represent all the forks at +// the current level, so we must account for the empty bits at the end. +// +// For this same reason, slots are 1-indexed instead of 0-indexed. Otherwise, +// the zeroth id at a level would be indistinguishable from its parent. +// +// If a node has only one child, and does not materialize an id (i.e. does not +// contain a useId hook), then we don't need to allocate any space in the +// sequence. It's treated as a transparent indirection. For example, these two +// trees produce the same ids: +// +// <> <> +// <Indirection> <A /> +// <A /> <B /> +// </Indirection> </> +// <B /> +// </> +// +// However, we cannot skip any node that materializes an id. Otherwise, a parent +// id that does not fork would be indistinguishable from its child id. For +// example, this tree does not fork, but the parent and child must have +// different ids. +// +// <Parent> +// <Child /> +// </Parent> +// +// To handle this scenario, every time we materialize an id, we allocate a +// new level with a single slot. You can think of this as a fork with only one +// prong, or an array of children with length 1. +// +// It's possible for the size of the sequence to exceed 32 bits, the max +// size for bitwise operations. When this happens, we make more room by +// converting the right part of the id to a string and storing it in an overflow +// variable. We use a base 32 string representation, because 32 is the largest +// power of 2 that is supported by toString(). We want the base to be large so +// that the resulting ids are compact, and we want the base to be a power of 2 +// because every log2(base) bits corresponds to a single character, i.e. every +// log2(32) = 5 bits. That means we can lop bits off the end 5 at a time without +// affecting the final result. +const emptyTreeContext = { + id: 1, + overflow: '', +}; +function getTreeId(context) { + const overflow = context.overflow; + const idWithLeadingBit = context.id; + const id = idWithLeadingBit & ~getLeadingBit(idWithLeadingBit); + return id.toString(32) + overflow; +} +function pushTreeContext(baseContext, totalChildren, index) { + const baseIdWithLeadingBit = baseContext.id; + const baseOverflow = baseContext.overflow; // The leftmost 1 marks the end of the sequence, non-inclusive. It's not part + // of the id; we use it to account for leading 0s. + + const baseLength = getBitLength(baseIdWithLeadingBit) - 1; + const baseId = baseIdWithLeadingBit & ~(1 << baseLength); + const slot = index + 1; + const length = getBitLength(totalChildren) + baseLength; // 30 is the max length we can store without overflowing, taking into + // consideration the leading 1 we use to mark the end of the sequence. + + if (length > 30) { + // We overflowed the bitwise-safe range. Fall back to slower algorithm. + // This branch assumes the length of the base id is greater than 5; it won't + // work for smaller ids, because you need 5 bits per character. + // + // We encode the id in multiple steps: first the base id, then the + // remaining digits. + // + // Each 5 bit sequence corresponds to a single base 32 character. So for + // example, if the current id is 23 bits long, we can convert 20 of those + // bits into a string of 4 characters, with 3 bits left over. + // + // First calculate how many bits in the base id represent a complete + // sequence of characters. + const numberOfOverflowBits = baseLength - (baseLength % 5); // Then create a bitmask that selects only those bits. + + const newOverflowBits = (1 << numberOfOverflowBits) - 1; // Select the bits, and convert them to a base 32 string. + + const newOverflow = (baseId & newOverflowBits).toString(32); // Now we can remove those bits from the base id. + + const restOfBaseId = baseId >> numberOfOverflowBits; + const restOfBaseLength = baseLength - numberOfOverflowBits; // Finally, encode the rest of the bits using the normal algorithm. Because + // we made more room, this time it won't overflow. + + const restOfLength = getBitLength(totalChildren) + restOfBaseLength; + const restOfNewBits = slot << restOfBaseLength; + const id = restOfNewBits | restOfBaseId; + const overflow = newOverflow + baseOverflow; + return { + id: (1 << restOfLength) | id, + overflow, + }; + } else { + // Normal path + const newBits = slot << baseLength; + const id = newBits | baseId; + const overflow = baseOverflow; + return { + id: (1 << length) | id, + overflow, + }; + } +} + +function getBitLength(number) { + return 32 - clz32(number); +} + +function getLeadingBit(id) { + return 1 << (getBitLength(id) - 1); +} // TODO: Math.clz32 is supported in Node 12+. Maybe we can drop the fallback. + +const clz32 = Math.clz32 ? Math.clz32 : clz32Fallback; // Count leading zeros. +// Based on: +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 + +const log = Math.log; +const LN2 = Math.LN2; + +function clz32Fallback(x) { + const asUint = x >>> 0; + + if (asUint === 0) { + return 32; + } + + return (31 - ((log(asUint) / LN2) | 0)) | 0; +} + +// Corresponds to ReactFiberWakeable and ReactFlightWakeable modules. Generally, +// changes to one module should be reflected in the others. +// TODO: Rename this module and the corresponding Fiber one to "Thenable" +// instead of "Wakeable". Or some other more appropriate name. +function createThenableState() { + // The ThenableState is created the first time a component suspends. If it + // suspends again, we'll reuse the same state. + return []; +} + +function noop() {} + +function trackUsedThenable(thenableState, thenable, index) { + const previous = thenableState[index]; + + if (previous === undefined) { + thenableState.push(thenable); + } else { + if (previous !== thenable) { + // Reuse the previous thenable, and drop the new one. We can assume + // they represent the same value, because components are idempotent. + // Avoid an unhandled rejection errors for the Promises that we'll + // intentionally ignore. + thenable.then(noop, noop); + thenable = previous; + } + } // We use an expando to track the status and result of a thenable so that we + // can synchronously unwrap the value. Think of this as an extension of the + // Promise API, or a custom interface that is a superset of Thenable. + // + // If the thenable doesn't have a status, set it to "pending" and attach + // a listener that will update its status and result when it resolves. + + switch (thenable.status) { + case 'fulfilled': { + const fulfilledValue = thenable.value; + return fulfilledValue; + } + + case 'rejected': { + const rejectedError = thenable.reason; + throw rejectedError; + } + + default: { + if (typeof thenable.status === 'string'); else { - for (var f = 0; f < d.length && f < b.length; f++) - if (!mc(b[f], d[f])) { - d = !1; - break a; + const pendingThenable = thenable; + pendingThenable.status = 'pending'; + pendingThenable.then( + (fulfilledValue) => { + if (thenable.status === 'pending') { + const fulfilledThenable = thenable; + fulfilledThenable.status = 'fulfilled'; + fulfilledThenable.value = fulfilledValue; + } + }, + (error) => { + if (thenable.status === 'pending') { + const rejectedThenable = thenable; + rejectedThenable.status = 'rejected'; + rejectedThenable.reason = error; + } } - d = !0; + ); + } // Suspend. + // TODO: Throwing here is an implementation detail that allows us to + // unwind the call stack. But we shouldn't allow it to leak into + // userspace. Throw an opaque placeholder value instead of the + // actual thenable. If it doesn't get captured by the work loop, log + // a warning, because that means something in userspace must have + // caught it. + + throw thenable; + } + } +} + +/** + * inlined Object.is polyfill to avoid requiring consumers ship their own + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is + */ +function is(x, y) { + return ( + (x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare + ); +} + +const objectIs = typeof Object.is === 'function' ? Object.is : is; // $FlowFixMe[method-unbinding] + +let currentlyRenderingComponent = null; +let currentlyRenderingTask = null; +let firstWorkInProgressHook = null; +let workInProgressHook = null; // Whether the work-in-progress hook is a re-rendered hook + +let isReRender = false; // Whether an update was scheduled during the currently executing render pass. + +let didScheduleRenderPhaseUpdate = false; // Counts the number of useId hooks in this component + +let localIdCounter = 0; // Counts the number of use(thenable) calls in this component + +let thenableIndexCounter = 0; +let thenableState = null; // Lazily created map of render-phase updates + +let renderPhaseUpdates = null; // Counter to prevent infinite loops. + +let numberOfReRenders = 0; +const RE_RENDER_LIMIT = 25; + +function resolveCurrentlyRenderingComponent() { + if (currentlyRenderingComponent === null) { + throw new Error( + 'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' + + ' one of the following reasons:\n' + + '1. You might have mismatching versions of React and the renderer (such as React DOM)\n' + + '2. You might be breaking the Rules of Hooks\n' + + '3. You might have more than one copy of React in the same app\n' + + 'See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.' + ); + } + + return currentlyRenderingComponent; +} + +function areHookInputsEqual(nextDeps, prevDeps) { + if (prevDeps === null) { + return false; + } + + for (let i = 0; i < prevDeps.length && i < nextDeps.length; i++) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + if (objectIs(nextDeps[i], prevDeps[i])) { + continue; + } + + return false; + } + + return true; +} + +function createHook() { + if (numberOfReRenders > 0) { + throw new Error('Rendered more hooks than during the previous render'); + } + + return { + memoizedState: null, + queue: null, + next: null, + }; +} + +function createWorkInProgressHook() { + if (workInProgressHook === null) { + // This is the first hook in the list + if (firstWorkInProgressHook === null) { + isReRender = false; + firstWorkInProgressHook = workInProgressHook = createHook(); + } else { + // There's already a work-in-progress. Reuse it. + isReRender = true; + workInProgressHook = firstWorkInProgressHook; + } + } else { + if (workInProgressHook.next === null) { + isReRender = false; // Append to the end of the list + + workInProgressHook = workInProgressHook.next = createHook(); + } else { + // There's already a work-in-progress. Reuse it. + isReRender = true; + workInProgressHook = workInProgressHook.next; + } + } + + return workInProgressHook; +} + +function prepareToUseHooks(task, componentIdentity, prevThenableState) { + currentlyRenderingComponent = componentIdentity; + currentlyRenderingTask = task; + // didScheduleRenderPhaseUpdate = false; + // firstWorkInProgressHook = null; + // numberOfReRenders = 0; + // renderPhaseUpdates = null; + // workInProgressHook = null; + + localIdCounter = 0; + thenableIndexCounter = 0; + thenableState = prevThenableState; +} +function finishHooks(Component, props, children, refOrContext) { + // This must be called after every function component to prevent hooks from + // being used in classes. + while (didScheduleRenderPhaseUpdate) { + // Updates were scheduled during the render phase. They are stored in + // the `renderPhaseUpdates` map. Call the component again, reusing the + // work-in-progress hooks and applying the additional updates on top. Keep + // restarting until no more updates are scheduled. + didScheduleRenderPhaseUpdate = false; + localIdCounter = 0; + thenableIndexCounter = 0; + numberOfReRenders += 1; // Start over from the beginning of the list + + workInProgressHook = null; + children = Component(props, refOrContext); + } + + resetHooksState(); + return children; +} +function getThenableStateAfterSuspending() { + const state = thenableState; + thenableState = null; + return state; +} +function checkDidRenderIdHook() { + // 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. + const didRenderIdHook = localIdCounter !== 0; + return didRenderIdHook; +} // Reset the internal hooks state if an error occurs while rendering a component + +function resetHooksState() { + currentlyRenderingComponent = null; + currentlyRenderingTask = null; + didScheduleRenderPhaseUpdate = false; + firstWorkInProgressHook = null; + numberOfReRenders = 0; + renderPhaseUpdates = null; + workInProgressHook = null; +} + +function readContext$1(context) { + return readContext(context); +} + +function useContext(context) { + resolveCurrentlyRenderingComponent(); + return readContext(context); +} + +function basicStateReducer(state, action) { + // $FlowFixMe: Flow doesn't like mixed types + return typeof action === 'function' ? action(state) : action; +} + +function useState(initialState) { + return useReducer( + basicStateReducer, // useReducer has a special case to support lazy useState initializers + initialState + ); +} +function useReducer(reducer, initialArg, init) { + currentlyRenderingComponent = resolveCurrentlyRenderingComponent(); + workInProgressHook = createWorkInProgressHook(); + + if (isReRender) { + // This is a re-render. Apply the new render phase updates to the previous + // current hook. + const queue = workInProgressHook.queue; + const dispatch = queue.dispatch; + + if (renderPhaseUpdates !== null) { + // Render phase updates are stored in a map of queue -> linked list + const firstRenderPhaseUpdate = renderPhaseUpdates.get(queue); + + if (firstRenderPhaseUpdate !== undefined) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + renderPhaseUpdates.delete(queue); // $FlowFixMe[incompatible-use] found when upgrading Flow + + let newState = workInProgressHook.memoizedState; + let update = firstRenderPhaseUpdate; + + do { + // Process this render phase update. We don't have to check the + // priority because it will always be the same as the current + // render's. + const action = update.action; + + newState = reducer(newState, action); + + update = update.next; + } while (update !== null); // $FlowFixMe[incompatible-use] found when upgrading Flow + + workInProgressHook.memoizedState = newState; + return [newState, dispatch]; } - if (d) return c[0]; + } // $FlowFixMe[incompatible-use] found when upgrading Flow + + return [workInProgressHook.memoizedState, dispatch]; + } else { + let initialState; + + if (reducer === basicStateReducer) { + // Special case for `useState`. + initialState = + typeof initialArg === 'function' ? initialArg() : initialArg; + } else { + initialState = init !== undefined ? init(initialArg) : initialArg; } + + workInProgressHook.memoizedState = initialState; // $FlowFixMe[incompatible-use] found when upgrading Flow + + const queue = (workInProgressHook.queue = { + last: null, + dispatch: null, + }); + const dispatch = (queue.dispatch = dispatchAction.bind( + null, + currentlyRenderingComponent, + queue + )); // $FlowFixMe[incompatible-use] found when upgrading Flow + + return [workInProgressHook.memoizedState, dispatch]; } - a = a(); - S.memoizedState = [a, b]; - return a; } -function wc(a, b, c) { - if (25 <= qc) throw Error(k(301)); - if (a === R) - if ( - ((pc = !0), - (a = { action: c, next: null }), - null === V && (V = new Map()), - (c = V.get(b)), - void 0 === c) - ) - V.set(b, a); - else { - for (b = c; null !== b.next; ) b = b.next; - b.next = a; - } -} -function yc() { - throw Error(k(394)); -} -function zc() {} -var Bc = { - readContext: function (a) { - return a._currentValue; - }, - useContext: function (a) { - W(); - return a._currentValue; - }, - useMemo: xc, - useReducer: vc, - useRef: function (a) { - R = W(); - S = sc(); - var b = S.memoizedState; - return null === b ? ((a = { current: a }), (S.memoizedState = a)) : b; - }, - useState: function (a) { - return vc(uc, a); - }, - useInsertionEffect: zc, - useLayoutEffect: function () {}, - useCallback: function (a, b) { - return xc(function () { - return a; - }, b); - }, - useImperativeHandle: zc, - useEffect: zc, - useDebugValue: zc, - useDeferredValue: function (a) { - W(); - return a; - }, - useTransition: function () { - W(); - return [!1, yc]; - }, - useId: function () { - var a = nc.treeContext; - var b = a.overflow; - a = a.id; - a = (a & ~(1 << (32 - Q(a) - 1))).toString(32) + b; - var c = Ac; - if (null === c) throw Error(k(404)); - b = U++; - a = ":" + c.idPrefix + "R" + a; - 0 < b && (a += "H" + b.toString(32)); - return a + ":"; - }, - useMutableSource: function (a, b) { - W(); - return b(a._source); - }, - useSyncExternalStore: function (a, b, c) { - if (void 0 === c) throw Error(k(407)); - return c(); - }, - }, - Ac = null, - Cc = - aa.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED - .ReactCurrentDispatcher; -function Dc(a) { - console.error(a); -} -function X() {} -function Ec(a, b, c, d, f, e, g, h, m) { - var q = [], - r = new Set(); - b = { + +function useMemo(nextCreate, deps) { + currentlyRenderingComponent = resolveCurrentlyRenderingComponent(); + workInProgressHook = createWorkInProgressHook(); + const nextDeps = deps === undefined ? null : deps; + + if (workInProgressHook !== null) { + const prevState = workInProgressHook.memoizedState; + + if (prevState !== null) { + if (nextDeps !== null) { + const prevDeps = prevState[1]; + + if (areHookInputsEqual(nextDeps, prevDeps)) { + return prevState[0]; + } + } + } + } + + const nextValue = nextCreate(); + + workInProgressHook.memoizedState = [nextValue, nextDeps]; + return nextValue; +} + +function useRef(initialValue) { + currentlyRenderingComponent = resolveCurrentlyRenderingComponent(); + workInProgressHook = createWorkInProgressHook(); + const previousRef = workInProgressHook.memoizedState; + + if (previousRef === null) { + const ref = { + current: initialValue, + }; + + workInProgressHook.memoizedState = ref; + return ref; + } else { + return previousRef; + } +} + +function useLayoutEffect(create, inputs) {} + +function dispatchAction(componentIdentity, queue, action) { + if (numberOfReRenders >= RE_RENDER_LIMIT) { + throw new Error( + 'Too many re-renders. React limits the number of renders to prevent ' + + 'an infinite loop.' + ); + } + + if (componentIdentity === currentlyRenderingComponent) { + // This is a render phase update. Stash it in a lazily-created map of + // queue -> linked list of updates. After this render pass, we'll restart + // and apply the stashed updates on top of the work-in-progress hook. + didScheduleRenderPhaseUpdate = true; + const update = { + action, + next: null, + }; + + if (renderPhaseUpdates === null) { + renderPhaseUpdates = new Map(); + } + + const firstRenderPhaseUpdate = renderPhaseUpdates.get(queue); + + if (firstRenderPhaseUpdate === undefined) { + // $FlowFixMe[incompatible-use] found when upgrading Flow + renderPhaseUpdates.set(queue, update); + } else { + // Append the update to the end of the list. + let lastRenderPhaseUpdate = firstRenderPhaseUpdate; + + while (lastRenderPhaseUpdate.next !== null) { + lastRenderPhaseUpdate = lastRenderPhaseUpdate.next; + } + + lastRenderPhaseUpdate.next = update; + } + } +} + +function useCallback(callback, deps) { + return useMemo(() => callback, deps); +} + +function throwOnUseEventCall() { + throw new Error( + "A function wrapped in useEvent can't be called during rendering." + ); +} + +function useEvent(callback) { + // $FlowIgnore[incompatible-return] + return throwOnUseEventCall; +} // TODO Decide on how to implement this hook for server rendering. +// If a mutation occurs during render, consider triggering a Suspense boundary +// and falling back to client rendering. + +function useMutableSource(source, getSnapshot, subscribe) { + resolveCurrentlyRenderingComponent(); + return getSnapshot(source._source); +} + +function useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { + if (getServerSnapshot === undefined) { + throw new Error( + 'Missing getServerSnapshot, which is required for ' + + 'server-rendered content. Will revert to client rendering.' + ); + } + + return getServerSnapshot(); +} + +function useDeferredValue(value) { + resolveCurrentlyRenderingComponent(); + return value; +} + +function unsupportedStartTransition() { + throw new Error('startTransition cannot be called during server rendering.'); +} + +function useTransition() { + resolveCurrentlyRenderingComponent(); + return [false, unsupportedStartTransition]; +} + +function useId() { + const task = currentlyRenderingTask; + const treeId = getTreeId(task.treeContext); + const responseState = currentResponseState; + + if (responseState === null) { + throw new Error( + 'Invalid hook call. Hooks can only be called inside of the body of a function component.' + ); + } + + const localId = localIdCounter++; + return makeId(responseState, treeId, localId); +} + +function use(usable) { + if (usable !== null && typeof usable === 'object') { + // $FlowFixMe[method-unbinding] + if (typeof usable.then === 'function') { + // This is a thenable. + const thenable = usable; // Track the position of the thenable within this fiber. + + const index = thenableIndexCounter; + thenableIndexCounter += 1; + + if (thenableState === null) { + thenableState = createThenableState(); + } + + return trackUsedThenable(thenableState, thenable, index); + } else if ( + usable.$$typeof === REACT_CONTEXT_TYPE || + usable.$$typeof === REACT_SERVER_CONTEXT_TYPE + ) { + const context = usable; + return readContext$1(context); + } + } // eslint-disable-next-line react-internal/safe-string-coercion + + throw new Error('An unsupported type was passed to use(): ' + String(usable)); +} + +function unsupportedRefresh() { + throw new Error('Cache cannot be refreshed during server rendering.'); +} + +function useCacheRefresh() { + return unsupportedRefresh; +} + +function useMemoCache(size) { + const data = new Array(size); + + for (let i = 0; i < size; i++) { + data[i] = REACT_MEMO_CACHE_SENTINEL; + } + + return data; +} + +function noop$1() {} + +const HooksDispatcher = { + readContext: readContext$1, + useContext, + useMemo, + useReducer, + useRef, + useState, + useInsertionEffect: noop$1, + useLayoutEffect, + useCallback, + // useImperativeHandle is not run in the server environment + useImperativeHandle: noop$1, + // Effects are not run in the server environment. + useEffect: noop$1, + // Debugging effect + useDebugValue: noop$1, + useDeferredValue, + useTransition, + useId, + // Subscriptions are not setup in a server environment. + useMutableSource, + useSyncExternalStore, +}; + +{ + HooksDispatcher.useCacheRefresh = useCacheRefresh; +} + +{ + HooksDispatcher.useEvent = useEvent; +} + +{ + HooksDispatcher.useMemoCache = useMemoCache; +} + +{ + HooksDispatcher.use = use; +} + +let currentResponseState = null; +function setCurrentResponseState(responseState) { + currentResponseState = responseState; +} + +function getCacheSignal() { + throw new Error('Not implemented.'); +} + +function getCacheForType(resourceType) { + throw new Error('Not implemented.'); +} + +const DefaultCacheDispatcher = { + getCacheSignal, + getCacheForType, +}; + +const ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher; +const ReactCurrentCache = ReactSharedInternals.ReactCurrentCache; +const ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; +const PENDING = 0; +const COMPLETED = 1; +const FLUSHED = 2; +const ABORTED = 3; +const ERRORED = 4; +const OPEN = 0; +const CLOSING = 1; +const CLOSED = 2; +// This is a default heuristic for how to split up the HTML content into progressive +// loading. Our goal is to be able to display additional new content about every 500ms. +// Faster than that is unnecessary and should be throttled on the client. It also +// adds unnecessary overhead to do more splits. We don't know if it's a higher or lower +// end device but higher end suffer less from the overhead than lower end does from +// not getting small enough pieces. We error on the side of low end. +// We base this on low end 3G speeds which is about 500kbits per second. We assume +// that there can be a reasonable drop off from max bandwidth which leaves you with +// as little as 80%. We can receive half of that each 500ms - at best. In practice, +// a little bandwidth is lost to processing and contention - e.g. CSS and images that +// are downloaded along with the main content. So we estimate about half of that to be +// the lower end throughput. In other words, we expect that you can at least show +// about 12.5kb of content per 500ms. Not counting starting latency for the first +// paint. +// 500 * 1024 / 8 * .8 * 0.5 / 2 +const DEFAULT_PROGRESSIVE_CHUNK_SIZE = 12800; + +function defaultErrorHandler(error) { + console['error'](error); // Don't transform to our wrapper + + return null; +} + +function noop$2() {} + +function createRequest( + children, + responseState, + rootFormatContext, + progressiveChunkSize, + onError, + onAllReady, + onShellReady, + onShellError, + onFatalError +) { + const pingedTasks = []; + const abortSet = new Set(); + const resources = createResources(); + const request = { destination: null, - responseState: b, - progressiveChunkSize: void 0 === d ? 12800 : d, - status: 0, + responseState, + progressiveChunkSize: + progressiveChunkSize === undefined + ? DEFAULT_PROGRESSIVE_CHUNK_SIZE + : progressiveChunkSize, + status: OPEN, fatalError: null, nextSegmentId: 0, allPendingTasks: 0, pendingRootTasks: 0, + resources, completedRootSegment: null, - abortableTasks: r, - pingedTasks: q, + abortableTasks: abortSet, + pingedTasks: pingedTasks, clientRenderedBoundaries: [], completedBoundaries: [], partialBoundaries: [], - onError: void 0 === f ? Dc : f, - onAllReady: void 0 === e ? X : e, - onShellReady: void 0 === g ? X : g, - onShellError: void 0 === h ? X : h, - onFatalError: void 0 === m ? X : m, + preamble: [], + postamble: [], + onError: onError === undefined ? defaultErrorHandler : onError, + onAllReady: onAllReady === undefined ? noop$2 : onAllReady, + onShellReady: onShellReady === undefined ? noop$2 : onShellReady, + onShellError: onShellError === undefined ? noop$2 : onShellError, + onFatalError: onFatalError === undefined ? noop$2 : onFatalError, + }; // This segment represents the root fallback. + + const 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; + const rootTask = createTask( + request, + null, + children, + null, + rootSegment, + abortSet, + emptyContextObject, + rootContextSnapshot, + emptyTreeContext + ); + pingedTasks.push(rootTask); + return request; +} + +function pingTask(request, task) { + const pingedTasks = request.pingedTasks; + pingedTasks.push(task); + + if (pingedTasks.length === 1) { + scheduleWork(() => performWork(request)); + } +} + +function createSuspenseBoundary(request, fallbackAbortableTasks) { + return { + id: UNINITIALIZED_SUSPENSE_BOUNDARY_ID, + rootSegmentID: -1, + parentFlushed: false, + pendingTasks: 0, + forceClientRender: false, + completedSegments: [], + byteSize: 0, + fallbackAbortableTasks, + errorDigest: null, + resources: createBoundaryResources(), }; - c = Fc(b, 0, null, c); - c.parentFlushed = !0; - a = Gc(b, a, null, c, r, Zb, null, gc); - q.push(a); - return b; -} -function Gc(a, b, c, d, f, e, g, h) { - a.allPendingTasks++; - null === c ? a.pendingRootTasks++ : c.pendingTasks++; - var m = { - node: b, - ping: function () { - var b = a.pingedTasks; - b.push(m); - 1 === b.length && Hc(a); - }, - blockedBoundary: c, - blockedSegment: d, - abortSet: f, - legacyContext: e, - context: g, - treeContext: h, +} + +function createTask( + request, + thenableState, + node, + blockedBoundary, + blockedSegment, + abortSet, + legacyContext, + context, + treeContext +) { + request.allPendingTasks++; + + if (blockedBoundary === null) { + request.pendingRootTasks++; + } else { + blockedBoundary.pendingTasks++; + } + + const task = { + node, + ping: () => pingTask(request, task), + blockedBoundary, + blockedSegment, + abortSet, + legacyContext, + context, + treeContext, + thenableState, }; - f.add(m); - return m; + + abortSet.add(task); + return task; } -function Fc(a, b, c, d) { + +function createPendingSegment( + request, + index, + boundary, + formatContext, + lastPushedText, + textEmbedded +) { return { - status: 0, + status: PENDING, id: -1, - index: b, - parentFlushed: !1, + // lazily assigned later + index, + parentFlushed: false, chunks: [], children: [], - formatContext: d, - boundary: c, + formatContext, + boundary, + lastPushedText, + textEmbedded, }; +} // DEV-only global reference to the currently executing task + +function pushFunctionComponentStackInDEV(task, type) {} + +function popComponentStackInDEV(task) {} // stash the component stack of an unwinding error until it is processed + +function logRecoverableError(request, error) { + // If this callback errors, we intentionally let that error bubble up to become a fatal error + // so that someone fixes the error reporting instead of hiding it. + const errorDigest = request.onError(error); + + if (errorDigest != null && typeof errorDigest !== 'string') { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error( + 'onError returned something with a type other than "string". onError should return a string and may return null or undefined but must not return anything else. It received something of type "' + + typeof errorDigest + + '" instead' + ); + } + + return errorDigest; } -function Y(a, b) { - a = a.onError; - a(b); -} -function Ic(a, b) { - var c = a.onShellError; - c(b); - c = a.onFatalError; - c(b); - null !== a.destination - ? ((a.status = 2), da(a.destination, b)) - : ((a.status = 1), (a.fatalError = b)); -} -function Jc(a, b, c, d, f) { - R = {}; - nc = b; - U = 0; - for (a = c(d, f); pc; ) - (pc = !1), (U = 0), (qc += 1), (S = null), (a = c(d, f)); - tc(); - return a; -} -function Kc(a, b, c, d) { - var f = c.render(), - e = d.childContextTypes; - if (null !== e && void 0 !== e) { - var g = b.legacyContext; - if ("function" !== typeof c.getChildContext) d = g; - else { - c = c.getChildContext(); - for (var h in c) - if (!(h in e)) throw Error(k(108, Yb(d) || "Unknown", h)); - d = M({}, g, c); - } - b.legacyContext = d; - Z(a, b, f); - b.legacyContext = g; - } else Z(a, b, f); -} -function Lc(a, b) { - if (a && a.defaultProps) { - b = M({}, b); - a = a.defaultProps; - for (var c in a) void 0 === b[c] && (b[c] = a[c]); - return b; - } - return b; -} -function Mc(a, b, c, d, f) { - if ("function" === typeof c) - if (c.prototype && c.prototype.isReactComponent) { - f = $b(c, b.legacyContext); - var e = c.contextType; - e = new c(d, "object" === typeof e && null !== e ? e._currentValue : f); - fc(e, c, d, f); - Kc(a, b, e, c); + +function fatalError(request, error) { + // This is called outside error handling code such as if the root errors outside + // a suspense boundary or if the root suspense boundary's fallback errors. + // It's also called if React itself or its host configs errors. + const onShellError = request.onShellError; + onShellError(error); + const onFatalError = request.onFatalError; + onFatalError(error); + + if (request.destination !== null) { + request.status = CLOSED; + closeWithError(request.destination, error); + } else { + request.status = CLOSING; + request.fatalError = error; + } +} + +function renderSuspenseBoundary(request, task, props) { + const parentBoundary = task.blockedBoundary; + const parentSegment = task.blockedSegment; // Each time we enter a suspense boundary, we split out into a new segment for + // the fallback so that we can later replace that segment with the content. + // This also lets us split out the main content even if it doesn't suspend, + // in case it ends up generating a large subtree of content. + + const fallback = props.fallback; + const content = props.children; + const fallbackAbortSet = new Set(); + const newBoundary = createSuspenseBoundary(request, fallbackAbortSet); + const insertionIndex = parentSegment.chunks.length; // The children of the boundary segment is actually the fallback. + + const boundarySegment = createPendingSegment( + request, + insertionIndex, + newBoundary, + parentSegment.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. + + const contentRootSegment = createPendingSegment( + request, + 0, + null, + parentSegment.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. + + contentRootSegment.parentFlushed = true; // Currently this is running synchronously. We could instead schedule this to pingedTasks. + // I suspect that there might be some efficiency benefits from not creating the suspended task + // and instead just using the stack if possible. + // TODO: Call this directly instead of messing with saving and restoring contexts. + // We can reuse the current context and task to render the content immediately without + // context switching. We just need to temporarily switch which boundary and which segment + // we're writing to. If something suspends, it'll spawn new suspended task with that context. + + task.blockedBoundary = newBoundary; + task.blockedSegment = contentRootSegment; + + { + setCurrentlyRenderingBoundaryResourcesTarget( + request.resources, + newBoundary.resources + ); + } + + try { + // We use the safe form because we don't handle suspending here. Only error handling. + renderNode(request, task, content); + pushSegmentFinale( + contentRootSegment.chunks, + request.responseState, + contentRootSegment.lastPushedText, + contentRootSegment.textEmbedded + ); + contentRootSegment.status = COMPLETED; + + if (enableFloat) { + if (newBoundary.pendingTasks === 0) { + hoistCompletedBoundaryResources(request, newBoundary); + } + } + + queueCompletedSegment(newBoundary, contentRootSegment); + + if (newBoundary.pendingTasks === 0) { + // 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.errorDigest = logRecoverableError(request, error); + // We don't need to schedule any task because we know the parent has written yet. + // We do need to fallthrough to create the fallback though. + } finally { + { + setCurrentlyRenderingBoundaryResourcesTarget( + request.resources, + parentBoundary ? parentBoundary.resources : null + ); + } + + task.blockedBoundary = parentBoundary; + task.blockedSegment = parentSegment; + } // 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. + + const suspendedFallbackTask = createTask( + request, + null, + fallback, + parentBoundary, + boundarySegment, + fallbackAbortSet, + task.legacyContext, + task.context, + task.treeContext + ); + // on preparing fallbacks if we don't have any more main content to task on. + + request.pingedTasks.push(suspendedFallbackTask); +} + +function hoistCompletedBoundaryResources(request, completedBoundary) { + if (request.completedRootSegment !== null || request.pendingRootTasks > 0) { + // The Shell has not flushed yet. we can hoist Resources for this boundary + // all the way to the Root. + hoistResourcesToRoot(request.resources, completedBoundary.resources); + } // We don't hoist if the root already flushed because late resources will be hoisted + // as boundaries flush +} + +function renderHostElement(request, task, type, props) { + const segment = task.blockedSegment; + const children = pushStartInstance( + segment.chunks, + request.preamble, + type, + props, + request.responseState, + segment.formatContext, + segment.lastPushedText + ); + segment.lastPushedText = false; + const prevContext = segment.formatContext; + segment.formatContext = getChildFormatContext(prevContext, type, props); // 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); // 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, request.postamble, type); + segment.lastPushedText = false; +} + +function shouldConstruct(Component) { + return Component.prototype && Component.prototype.isReactComponent; +} + +function renderWithHooks( + request, + task, + prevThenableState, + Component, + props, + secondArg +) { + const componentIdentity = {}; + prepareToUseHooks(task, componentIdentity, prevThenableState); + const result = Component(props, secondArg); + return finishHooks(Component, props, result, secondArg); +} + +function finishClassComponent(request, task, instance, Component, props) { + const nextChildren = instance.render(); + + { + const childContextTypes = Component.childContextTypes; + + if (childContextTypes !== null && childContextTypes !== undefined) { + const previousContext = task.legacyContext; + const mergedContext = processChildContext( + instance, + Component, + previousContext, + childContextTypes + ); + task.legacyContext = mergedContext; + renderNodeDestructive(request, task, null, nextChildren); + task.legacyContext = previousContext; + return; + } + } + + renderNodeDestructive(request, task, null, nextChildren); +} + +function renderClassComponent(request, task, Component, props) { + const maskedContext = getMaskedContext(Component, task.legacyContext); + const instance = constructClassInstance(Component, props, maskedContext); + mountClassInstance(instance, Component, props, maskedContext); + finishClassComponent(request, task, instance, Component); +} +// components for some reason. + +function renderIndeterminateComponent( + request, + task, + prevThenableState, + Component, + props +) { + let legacyContext; + + { + legacyContext = getMaskedContext(Component, task.legacyContext); + } + + const value = renderWithHooks( + request, + task, + prevThenableState, + Component, + props, + legacyContext + ); + const hasId = checkDidRenderIdHook(); + + if ( + // Run these checks in production only if the flag is off. + // Eventually we'll delete this branch altogether. + typeof value === 'object' && + value !== null && + typeof value.render === 'function' && + value.$$typeof === undefined + ) { + mountClassInstance(value, Component, props, legacyContext); + finishClassComponent(request, task, value, Component); + } else { + // the previous task every again, so we can use the destructive recursive form. + + if (hasId) { + // This component materialized an id. We treat this as its own level, with + // a single "child" slot. + const prevTreeContext = task.treeContext; + const totalChildren = 1; + const index = 0; + task.treeContext = pushTreeContext(prevTreeContext, totalChildren, index); + + try { + renderNodeDestructive(request, task, null, value); + } finally { + task.treeContext = prevTreeContext; + } } else { - e = $b(c, b.legacyContext); - f = Jc(a, b, c, d, e); - var g = 0 !== U; - if ( - "object" === typeof f && - null !== f && - "function" === typeof f.render && - void 0 === f.$$typeof - ) - fc(f, c, d, e), Kc(a, b, f, c); - else if (g) { - d = b.treeContext; - b.treeContext = hc(d, 1, 0); - try { - Z(a, b, f); - } finally { - b.treeContext = d; - } - } else Z(a, b, f); - } - else if ("string" === typeof c) - switch ( - ((f = b.blockedSegment), - (e = Pa(f.chunks, c, d, a.responseState, f.formatContext)), - (g = f.formatContext), - (f.formatContext = za(g, c, d)), - Nc(a, b, e), - (f.formatContext = g), - c) - ) { - case "area": - case "base": - case "br": - case "col": - case "embed": - case "hr": - case "img": - case "input": - case "keygen": - case "link": - case "meta": - case "param": - case "source": - case "track": - case "wbr": - break; - default: - f.chunks.push(Qa, u(c), Ra); + renderNodeDestructive(request, task, null, value); + } + } +} + +function resolveDefaultProps(Component, baseProps) { + if (Component && Component.defaultProps) { + // Resolve default props. Taken from ReactElement + const props = assign({}, baseProps); + const defaultProps = Component.defaultProps; + + for (const propName in defaultProps) { + if (props[propName] === undefined) { + props[propName] = defaultProps[propName]; + } } + + return props; + } + + return baseProps; +} + +function renderForwardRef(request, task, prevThenableState, type, props, ref) { + pushFunctionComponentStackInDEV(task, type.render); + const children = renderWithHooks( + request, + task, + prevThenableState, + type.render, + props, + ref + ); + const hasId = checkDidRenderIdHook(); + + if (hasId) { + // This component materialized an id. We treat this as its own level, with + // a single "child" slot. + const prevTreeContext = task.treeContext; + const totalChildren = 1; + const index = 0; + task.treeContext = pushTreeContext(prevTreeContext, totalChildren, index); + + try { + renderNodeDestructive(request, task, null, children); + } finally { + task.treeContext = prevTreeContext; + } + } else { + renderNodeDestructive(request, task, null, children); + } +} + +function renderMemo(request, task, prevThenableState, type, props, ref) { + const innerType = type.type; + const resolvedProps = resolveDefaultProps(innerType, props); + renderElement( + request, + task, + prevThenableState, + innerType, + resolvedProps, + ref + ); +} + +function renderContextConsumer(request, task, context, props) { + const render = props.children; + + const newValue = readContext(context); + const newChildren = render(newValue); + renderNodeDestructive(request, task, null, newChildren); +} + +function renderContextProvider(request, task, type, props) { + const context = type._context; + const value = props.value; + const children = props.children; + + task.context = pushProvider(context, value); + renderNodeDestructive(request, task, null, children); + task.context = popProvider(); +} + +function renderLazyComponent( + request, + task, + prevThenableState, + lazyComponent, + props, + ref +) { + const payload = lazyComponent._payload; + const init = lazyComponent._init; + const Component = init(payload); + const resolvedProps = resolveDefaultProps(Component, props); + renderElement( + request, + task, + prevThenableState, + Component, + resolvedProps, + ref + ); +} + +function renderOffscreen(request, task, props) { + const mode = props.mode; + + if (mode === 'hidden'); else { - switch (c) { - case Vb: - case Ub: - case Kb: - case Lb: - case Jb: - Z(a, b, d.children); + // A visible Offscreen boundary is treated exactly like a fragment: a + // pure indirection. + renderNodeDestructive(request, task, null, props.children); + } +} + +function renderElement(request, task, prevThenableState, type, props, ref) { + if (typeof type === 'function') { + if (shouldConstruct(type)) { + renderClassComponent(request, task, type, props); + return; + } else { + renderIndeterminateComponent( + request, + task, + prevThenableState, + type, + props + ); + return; + } + } + + if (typeof type === 'string') { + renderHostElement(request, task, type, props); + return; + } + + switch (type) { + // LegacyHidden acts the same as a fragment. This only works because we + // currently assume that every instance of LegacyHidden is accompanied by a + // host component wrapper. In the hidden mode, the host component is given a + // `hidden` attribute, which ensures that the initial HTML is not visible. + // To support the use of LegacyHidden as a true fragment, without an extra + // DOM node, we would have to hide the initial HTML in some other way. + // TODO: Delete in LegacyHidden. It's an unstable API only used in the + // www build. As a migration step, we could add a special prop to Offscreen + // that simulates the old behavior (no hiding, no change to effects). + case REACT_LEGACY_HIDDEN_TYPE: + case REACT_DEBUG_TRACING_MODE_TYPE: + case REACT_STRICT_MODE_TYPE: + case REACT_PROFILER_TYPE: + case REACT_FRAGMENT_TYPE: { + renderNodeDestructive(request, task, null, props.children); + return; + } + + case REACT_OFFSCREEN_TYPE: { + renderOffscreen(request, task, props); + return; + } + + case REACT_SUSPENSE_LIST_TYPE: { + renderNodeDestructive(request, task, null, props.children); + return; + } + + case REACT_SCOPE_TYPE: { + throw new Error('ReactDOMServer does not yet support scope components.'); + } + // eslint-disable-next-line-no-fallthrough + + case REACT_SUSPENSE_TYPE: { + { + renderSuspenseBoundary(request, task, props); + } + + return; + } + } + + if (typeof type === 'object' && type !== null) { + switch (type.$$typeof) { + case REACT_FORWARD_REF_TYPE: { + renderForwardRef(request, task, prevThenableState, type, props, ref); return; - case Qb: - Z(a, b, d.children); + } + + case REACT_MEMO_TYPE: { + renderMemo(request, task, prevThenableState, type, props, ref); return; - case Tb: - throw Error(k(343)); - case Pb: - a: { - c = b.blockedBoundary; - f = b.blockedSegment; - e = d.fallback; - d = d.children; - g = new Set(); - var h = { - id: null, - rootSegmentID: -1, - parentFlushed: !1, - pendingTasks: 0, - forceClientRender: !1, - completedSegments: [], - byteSize: 0, - fallbackAbortableTasks: g, - }, - m = Fc(a, f.chunks.length, h, f.formatContext); - f.children.push(m); - var q = Fc(a, 0, null, f.formatContext); - q.parentFlushed = !0; - b.blockedBoundary = h; - b.blockedSegment = q; - try { - if ((Nc(a, b, d), (q.status = 1), Oc(h, q), 0 === h.pendingTasks)) - break a; - } catch (r) { - (q.status = 4), Y(a, r), (h.forceClientRender = !0); - } finally { - (b.blockedBoundary = c), (b.blockedSegment = f); - } - b = Gc(a, e, c, m, g, b.legacyContext, b.context, b.treeContext); - a.pingedTasks.push(b); - } + } + + case REACT_PROVIDER_TYPE: { + renderContextProvider(request, task, type, props); return; - } - if ("object" === typeof c && null !== c) - switch (c.$$typeof) { - case Ob: - d = Jc(a, b, c.render, d, f); - if (0 !== U) { - c = b.treeContext; - b.treeContext = hc(c, 1, 0); - try { - Z(a, b, d); - } finally { - b.treeContext = c; - } - } else Z(a, b, d); - return; - case Rb: - c = c.type; - d = Lc(c, d); - Mc(a, b, c, d, f); - return; - case Mb: - f = d.children; - c = c._context; - d = d.value; - e = c._currentValue; - c._currentValue = d; - g = N; - N = d = { - parent: g, - depth: null === g ? 0 : g.depth + 1, - context: c, - parentValue: e, - value: d, - }; - b.context = d; - Z(a, b, f); - a = N; - if (null === a) throw Error(k(403)); - d = a.parentValue; - a.context._currentValue = d === Wb ? a.context._defaultValue : d; - a = N = a.parent; - b.context = a; - return; - case Nb: - d = d.children; - d = d(c._currentValue); - Z(a, b, d); - return; - case Sb: - f = c._init; - c = f(c._payload); - d = Lc(c, d); - Mc(a, b, c, d, void 0); - return; } - throw Error(k(130, null == c ? c : typeof c, "")); + + case REACT_CONTEXT_TYPE: { + renderContextConsumer(request, task, type, props); + return; + } + + case REACT_LAZY_TYPE: { + renderLazyComponent(request, task, prevThenableState, type, props); + return; + } + } } + + let info = ''; + + throw new Error( + 'Element type is invalid: expected a string (for built-in ' + + 'components) or a class/function (for composite components) ' + + ('but got: ' + (type == null ? type : typeof type) + '.' + info) + ); } -function Z(a, b, c) { - b.node = c; - if ("object" === typeof c && null !== c) { - switch (c.$$typeof) { - case Hb: - Mc(a, b, c.type, c.props, c.ref); + +function renderNodeDestructive( + request, + task, // The thenable state reused from the previous attempt, if any. This is almost + // always null, except when called by retryTask. + prevThenableState, + node +) { + { + return renderNodeDestructiveImpl(request, task, prevThenableState, node); + } +} // This function by it self renders a node and consumes the task by mutating it +// to update the current execution state. + +function renderNodeDestructiveImpl(request, task, prevThenableState, node) { + // Stash the node we're working on. We'll pick up from this task in case + // something suspends. + task.node = node; // Handle object types + + if (typeof node === 'object' && node !== null) { + switch (node.$$typeof) { + case REACT_ELEMENT_TYPE: { + const element = node; + const type = element.type; + const props = element.props; + const ref = element.ref; + renderElement(request, task, prevThenableState, type, props, ref); return; - case Ib: - throw Error(k(257)); - case Sb: - var d = c._init; - c = d(c._payload); - Z(a, b, c); + } + + case REACT_PORTAL_TYPE: + throw new Error( + 'Portals are not currently supported by the server renderer. ' + + 'Render them conditionally so that they only appear on the client render.' + ); + // eslint-disable-next-line-no-fallthrough + + case REACT_LAZY_TYPE: { + const lazyNode = node; + const payload = lazyNode._payload; + const init = lazyNode._init; + let resolvedNode; + + { + resolvedNode = init(payload); + } + + renderNodeDestructive(request, task, null, resolvedNode); return; + } } - if (pa(c)) { - Pc(a, b, c); + + if (isArray(node)) { + renderChildrenArray(request, task, node); return; } - null === c || "object" !== typeof c - ? (d = null) - : ((d = (Xb && c[Xb]) || c["@@iterator"]), - (d = "function" === typeof d ? d : null)); - if (d && (d = d.call(c))) { - c = d.next(); - if (!c.done) { - var f = []; - do f.push(c.value), (c = d.next()); - while (!c.done); - Pc(a, b, f); + + const iteratorFn = getIteratorFn(node); + + if (iteratorFn) { + const iterator = iteratorFn.call(node); + + if (iterator) { + // We need to know how many total children are in this set, so that we + // can allocate enough id slots to acommodate them. So we must exhaust + // the iterator before we start recursively rendering the children. + // TODO: This is not great but I think it's inherent to the id + // generation algorithm. + let step = iterator.next(); // If there are not entries, we need to push an empty so we start by checking that. + + if (!step.done) { + const children = []; + + do { + children.push(step.value); + step = iterator.next(); + } while (!step.done); + + renderChildrenArray(request, task, children); + return; + } + + return; } - return; - } - b = Object.prototype.toString.call(c); - throw Error( - k( - 31, - "[object Object]" === b - ? "object with keys {" + Object.keys(c).join(", ") + "}" - : b - ) + } // $FlowFixMe[method-unbinding] + + const childString = Object.prototype.toString.call(node); + throw new Error( + 'Objects are not valid as a React child (found: ' + + (childString === '[object Object]' + ? 'object with keys {' + Object.keys(node).join(', ') + '}' + : childString) + + '). ' + + 'If you meant to render a collection of children, use an array ' + + 'instead.' + ); + } + + if (typeof node === 'string') { + const segment = task.blockedSegment; + segment.lastPushedText = pushTextInstance( + task.blockedSegment.chunks, + node, + request.responseState, + segment.lastPushedText ); + return; + } + + if (typeof node === 'number') { + const segment = task.blockedSegment; + segment.lastPushedText = pushTextInstance( + task.blockedSegment.chunks, + '' + node, + request.responseState, + segment.lastPushedText + ); + return; } - "string" === typeof c - ? "" !== c && b.blockedSegment.chunks.push(u(A(c)), Aa) - : "number" === typeof c && - ((a = "" + c), "" !== a && b.blockedSegment.chunks.push(u(A(a)), Aa)); } -function Pc(a, b, c) { - for (var d = c.length, f = 0; f < d; f++) { - var e = b.treeContext; - b.treeContext = hc(e, d, f); + +function renderChildrenArray(request, task, children) { + const totalChildren = children.length; + + for (let i = 0; i < totalChildren; i++) { + const prevTreeContext = task.treeContext; + task.treeContext = pushTreeContext(prevTreeContext, totalChildren, i); + try { - Nc(a, b, c[f]); + // We need to use the non-destructive form so that we can safely pop back + // up and render the sibling if something suspends. + renderNode(request, task, children[i]); } finally { - b.treeContext = e; + task.treeContext = prevTreeContext; } } } -function Nc(a, b, c) { - var d = b.blockedSegment.formatContext, - f = b.legacyContext, - e = b.context; + +function spawnNewSuspendedTask(request, task, thenableState, x) { + // Something suspended, we'll need to create a new segment and resolve it later. + const segment = task.blockedSegment; + const insertionIndex = segment.chunks.length; + const newSegment = createPendingSegment( + request, + insertionIndex, + null, + segment.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; + const newTask = createTask( + request, + thenableState, + task.node, + task.blockedBoundary, + newSegment, + task.abortSet, + task.legacyContext, + task.context, + task.treeContext + ); + + const ping = newTask.ping; + x.then(ping, ping); +} // This is a non-destructive form of rendering a node. If it suspends it spawns +// a new task and restores the context of this task to what it was before. + +function renderNode(request, task, node) { + // TODO: Store segment.children.length here and reset it in case something + // suspended partially through writing something. + // Snapshot the current context in case something throws to interrupt the + // process. + const previousFormatContext = task.blockedSegment.formatContext; + const previousLegacyContext = task.legacyContext; + const previousContext = task.context; + try { - return Z(a, b, c); - } catch (m) { - if ( - (tc(), - "object" === typeof m && null !== m && "function" === typeof m.then) - ) { - c = m; - var g = b.blockedSegment, - h = Fc(a, g.chunks.length, null, g.formatContext); - g.children.push(h); - a = Gc( - a, - b.node, - b.blockedBoundary, - h, - b.abortSet, - b.legacyContext, - b.context, - b.treeContext - ).ping; - c.then(a, a); - b.blockedSegment.formatContext = d; - b.legacyContext = f; - b.context = e; - P(e); - } else - throw ( - ((b.blockedSegment.formatContext = d), - (b.legacyContext = f), - (b.context = e), - P(e), - m) - ); + return renderNodeDestructive(request, task, null, node); + } catch (x) { + resetHooksState(); + + if (typeof x === 'object' && x !== null && typeof x.then === 'function') { + const thenableState = getThenableStateAfterSuspending(); + spawnNewSuspendedTask(request, task, thenableState, x); // 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; // Restore all active ReactContexts to what they were before. + + switchContext(previousContext); + + 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; // Restore all active ReactContexts to what they were before. + + switchContext(previousContext); + // Let's terminate the rest of the tree and don't render any siblings. + + throw x; + } } } -function Qc(a) { - var b = a.blockedBoundary; - a = a.blockedSegment; - a.status = 3; - Rc(this, b, a); -} -function Sc(a) { - var b = a.blockedBoundary; - a.blockedSegment.status = 3; - null === b - ? (this.allPendingTasks--, - 2 !== this.status && - ((this.status = 2), - null !== this.destination && this.destination.close())) - : (b.pendingTasks--, - b.forceClientRender || - ((b.forceClientRender = !0), - b.parentFlushed && this.clientRenderedBoundaries.push(b)), - b.fallbackAbortableTasks.forEach(Sc, this), - b.fallbackAbortableTasks.clear(), - this.allPendingTasks--, - 0 === this.allPendingTasks && ((a = this.onAllReady), a())); -} -function Oc(a, b) { + +function erroredTask(request, boundary, segment, error) { + // Report the error to a global handler. + const errorDigest = logRecoverableError(request, error); + + if (boundary === null) { + fatalError(request, error); + } else { + boundary.pendingTasks--; + + if (!boundary.forceClientRender) { + boundary.forceClientRender = true; + boundary.errorDigest = errorDigest; + // so we can flush it, if the parent already flushed. + + if (boundary.parentFlushed) { + // We don't have a preference where in the queue this goes since it's likely + // to error on the client anyway. However, intentionally client-rendered + // boundaries should be flushed earlier so that they can start on the client. + // We reuse the same queue for errors. + request.clientRenderedBoundaries.push(boundary); + } + } + } + + request.allPendingTasks--; + + if (request.allPendingTasks === 0) { + const onAllReady = request.onAllReady; + onAllReady(); + } +} + +function abortTaskSoft(task) { + // This aborts task without aborting the parent boundary that it blocks. + // It's used for when we didn't need this task to complete the tree. + // If task was needed, then it should use abortTask instead. + const request = this; + const boundary = task.blockedBoundary; + const segment = task.blockedSegment; + segment.status = ABORTED; + finishedTask(request, boundary, segment); +} + +function abortTask(task, request, error) { + // This aborts the task and aborts the parent that it blocks, putting it into + // client rendered mode. + const boundary = task.blockedBoundary; + const segment = task.blockedSegment; + segment.status = ABORTED; + + if (boundary === null) { + request.allPendingTasks--; // We didn't complete the root so we have nothing to show. We can close + // the request; + + if (request.status !== CLOSING && request.status !== CLOSED) { + logRecoverableError(request, error); + fatalError(request, error); + } + } else { + boundary.pendingTasks--; + + if (!boundary.forceClientRender) { + boundary.forceClientRender = true; + boundary.errorDigest = request.onError(error); + + if (boundary.parentFlushed) { + request.clientRenderedBoundaries.push(boundary); + } + } // If this boundary was still pending then we haven't already cancelled its fallbacks. + // We'll need to abort the fallbacks, which will also error that parent boundary. + + boundary.fallbackAbortableTasks.forEach((fallbackTask) => + abortTask(fallbackTask, request, error) + ); + boundary.fallbackAbortableTasks.clear(); + request.allPendingTasks--; + + if (request.allPendingTasks === 0) { + const onAllReady = request.onAllReady; + onAllReady(); + } + } +} + +function queueCompletedSegment(boundary, segment) { if ( - 0 === b.chunks.length && - 1 === b.children.length && - null === b.children[0].boundary + segment.chunks.length === 0 && + segment.children.length === 1 && + segment.children[0].boundary === null ) { - var c = b.children[0]; - c.id = b.id; - c.parentFlushed = !0; - 1 === c.status && Oc(a, c); - } else a.completedSegments.push(b); -} -function Rc(a, b, c) { - if (null === b) { - if (c.parentFlushed) { - if (null !== a.completedRootSegment) throw Error(k(389)); - a.completedRootSegment = c; - } - a.pendingRootTasks--; - 0 === a.pendingRootTasks && - ((a.onShellError = X), (b = a.onShellReady), b()); - } else - b.pendingTasks--, - b.forceClientRender || - (0 === b.pendingTasks - ? (c.parentFlushed && 1 === c.status && Oc(b, c), - b.parentFlushed && a.completedBoundaries.push(b), - b.fallbackAbortableTasks.forEach(Qc, a), - b.fallbackAbortableTasks.clear()) - : c.parentFlushed && - 1 === c.status && - (Oc(b, c), - 1 === b.completedSegments.length && - b.parentFlushed && - a.partialBoundaries.push(b))); - a.allPendingTasks--; - 0 === a.allPendingTasks && ((a = a.onAllReady), a()); -} -function Hc(a) { - if (2 !== a.status) { - var b = N, - c = Cc.current; - Cc.current = Bc; - var d = Ac; - Ac = a.responseState; - try { - var f = a.pingedTasks, - e; - for (e = 0; e < f.length; e++) { - var g = f[e]; - var h = a, - m = g.blockedSegment; - if (0 === m.status) { - P(g.context); - try { - Z(h, g, g.node), - g.abortSet.delete(g), - (m.status = 1), - Rc(h, g.blockedBoundary, m); - } catch (C) { - if ( - (tc(), - "object" === typeof C && - null !== C && - "function" === typeof C.then) - ) { - var q = g.ping; - C.then(q, q); - } else { - g.abortSet.delete(g); - m.status = 4; - var r = g.blockedBoundary, - E = C; - Y(h, E); - null === r - ? Ic(h, E) - : (r.pendingTasks--, - r.forceClientRender || - ((r.forceClientRender = !0), - r.parentFlushed && h.clientRenderedBoundaries.push(r))); - h.allPendingTasks--; - if (0 === h.allPendingTasks) { - var F = h.onAllReady; - F(); - } + // 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. + const childSegment = segment.children[0]; + childSegment.id = segment.id; + childSegment.parentFlushed = true; + + if (childSegment.status === COMPLETED) { + queueCompletedSegment(boundary, childSegment); + } + } else { + const completedSegments = boundary.completedSegments; + completedSegments.push(segment); + } +} + +function finishedTask(request, boundary, segment) { + if (boundary === null) { + if (segment.parentFlushed) { + if (request.completedRootSegment !== null) { + throw new Error( + 'There can only be one root segment. This is a bug in React.' + ); + } + + request.completedRootSegment = segment; + } + + request.pendingRootTasks--; + + if (request.pendingRootTasks === 0) { + // We have completed the shell so the shell can't error anymore. + request.onShellError = noop$2; + const onShellReady = request.onShellReady; + onShellReady(); + } + } 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 (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 + // to emit it. + if (segment.status === COMPLETED) { + queueCompletedSegment(boundary, segment); + } + } + + { + hoistCompletedBoundaryResources(request, boundary); + } + + if (boundary.parentFlushed) { + // The segment might be part of a segment that didn't flush yet, but if the boundary's + // parent flushed, we need to schedule the boundary to be emitted. + request.completedBoundaries.push(boundary); + } // We can now cancel any pending task on the fallback since we won't need to show it anymore. + // This needs to happen after we read the parentFlushed flags because aborting can finish + // work which can trigger user code, which can start flushing, which can change those flags. + + boundary.fallbackAbortableTasks.forEach(abortTaskSoft, request); + boundary.fallbackAbortableTasks.clear(); + } else { + if (segment.parentFlushed) { + // Our parent 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 + // to emit it. + if (segment.status === COMPLETED) { + queueCompletedSegment(boundary, segment); + const completedSegments = boundary.completedSegments; + + if (completedSegments.length === 1) { + // This is the first time since we last flushed that we completed anything. + // We can schedule this boundary to emit its partially completed segments early + // in case the parent has already been flushed. + if (boundary.parentFlushed) { + request.partialBoundaries.push(boundary); } - } finally { } } } - f.splice(0, e); - null !== a.destination && Tc(a, a.destination); - } catch (C) { - Y(a, C), Ic(a, C); - } finally { - (Ac = d), (Cc.current = c), c === Bc && P(b); - } - } -} -function Uc(a, b, c) { - c.parentFlushed = !0; - switch (c.status) { - case 0: - var d = (c.id = a.nextSegmentId++); - a = a.responseState; - p(b, Sa); - p(b, a.placeholderPrefix); - a = u(d.toString(16)); - p(b, a); - return t(b, Ta); - case 1: - c.status = 2; - var f = !0; - d = c.chunks; - var e = 0; - c = c.children; - for (var g = 0; g < c.length; g++) { - for (f = c[g]; e < f.index; e++) p(b, d[e]); - f = Vc(a, b, f); - } - for (; e < d.length - 1; e++) p(b, d[e]); - e < d.length && (f = t(b, d[e])); - return f; - default: - throw Error(k(390)); - } -} -function Vc(a, b, c) { - var d = c.boundary; - if (null === d) return Uc(a, b, c); - d.parentFlushed = !0; - if (d.forceClientRender) t(b, Xa), Uc(a, b, c); - else if (0 < d.pendingTasks) { - d.rootSegmentID = a.nextSegmentId++; - 0 < d.completedSegments.length && a.partialBoundaries.push(d); - var f = a.responseState; - var e = f.nextSuspenseID++; - f = v(f.boundaryPrefix + e.toString(16)); - d = d.id = f; - Za(b, a.responseState, d); - Uc(a, b, c); - } else if (d.byteSize > a.progressiveChunkSize) - (d.rootSegmentID = a.nextSegmentId++), - a.completedBoundaries.push(d), - Za(b, a.responseState, d.id), - Uc(a, b, c); - else { - t(b, Ua); - c = d.completedSegments; - if (1 !== c.length) throw Error(k(391)); - Vc(a, b, c[0]); - } - return t(b, Ya); -} -function Wc(a, b, c) { - ub(b, a.responseState, c.formatContext, c.id); - Vc(a, b, c); - return vb(b, c.formatContext); -} -function Xc(a, b, c) { - for (var d = c.completedSegments, f = 0; f < d.length; f++) Yc(a, b, c, d[f]); - d.length = 0; - a = a.responseState; - d = c.id; - c = c.rootSegmentID; - p(b, a.startInlineScript); - a.sentCompleteBoundaryFunction - ? p(b, Bb) - : ((a.sentCompleteBoundaryFunction = !0), p(b, Ab)); - if (null === d) throw Error(k(395)); - c = u(c.toString(16)); - p(b, d); - p(b, Cb); - p(b, a.segmentPrefix); - p(b, c); - return t(b, Db); -} -function Yc(a, b, c, d) { - if (2 === d.status) return !0; - var f = d.id; - if (-1 === f) { - if (-1 === (d.id = c.rootSegmentID)) throw Error(k(392)); - return Wc(a, b, d); - } - Wc(a, b, d); - a = a.responseState; - p(b, a.startInlineScript); - a.sentCompleteSegmentFunction - ? p(b, xb) - : ((a.sentCompleteSegmentFunction = !0), p(b, wb)); - p(b, a.segmentPrefix); - f = u(f.toString(16)); - p(b, f); - p(b, yb); - p(b, a.placeholderPrefix); - p(b, f); - return t(b, zb); -} -function Tc(a, b) { - n = 0; + } + } + + request.allPendingTasks--; + + if (request.allPendingTasks === 0) { + // This needs to be called at the very end so that we can synchronously write the result + // in the callback if needed. + const onAllReady = request.onAllReady; + onAllReady(); + } +} + +function retryTask(request, task) { + { + const blockedBoundary = task.blockedBoundary; + setCurrentlyRenderingBoundaryResourcesTarget( + request.resources, + blockedBoundary ? blockedBoundary.resources : null + ); + } + + const segment = task.blockedSegment; + + if (segment.status !== PENDING) { + // We completed this by other means before we had a chance to retry it. + return; + } // We restore the context to what it was when we suspended. + // We don't restore it after we leave because it's likely that we'll end up + // needing a very similar context soon again. + + switchContext(task.context); + try { - var c = a.completedRootSegment; - if (null !== c && 0 === a.pendingRootTasks) { - Vc(a, b, c); - a.completedRootSegment = null; - var d = a.responseState.bootstrapChunks; - for (c = 0; c < d.length - 1; c++) p(b, d[c]); - c < d.length && t(b, d[c]); - } - var f = a.clientRenderedBoundaries, - e; - for (e = 0; e < f.length; e++) { - d = b; - var g = a.responseState, - h = f[e].id; - p(d, g.startInlineScript); - g.sentClientRenderFunction - ? p(d, Fb) - : ((g.sentClientRenderFunction = !0), p(d, Eb)); - if (null === h) throw Error(k(395)); - p(d, h); - if (!t(d, Gb)) { - a.destination = null; - e++; - f.splice(0, e); - return; + // We call the destructive form that mutates this task. That way if something + // suspends again, we can reuse the same task instead of spawning a new one. + // Reset the task's thenable state before continuing, so that if a later + // component suspends we can reuse the same task object. If the same + // component suspends again, the thenable state will be restored. + const prevThenableState = task.thenableState; + task.thenableState = null; + renderNodeDestructive(request, task, prevThenableState, task.node); + pushSegmentFinale( + segment.chunks, + request.responseState, + segment.lastPushedText, + segment.textEmbedded + ); + task.abortSet.delete(task); + segment.status = COMPLETED; + finishedTask(request, task.blockedBoundary, segment); + } catch (x) { + resetHooksState(); + + if (typeof x === 'object' && x !== null && typeof x.then === 'function') { + // Something suspended again, let's pick it back up later. + const ping = task.ping; + x.then(ping, ping); + task.thenableState = getThenableStateAfterSuspending(); + } else { + task.abortSet.delete(task); + segment.status = ERRORED; + erroredTask(request, task.blockedBoundary, segment, x); + } + } finally { + { + setCurrentlyRenderingBoundaryResourcesTarget(request.resources, null); + } + } +} + +function performWork(request) { + if (request.status === CLOSED) { + return; + } + + const prevContext = getActiveContext(); + const prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = HooksDispatcher; + let prevCacheDispatcher; + + { + prevCacheDispatcher = ReactCurrentCache.current; + ReactCurrentCache.current = DefaultCacheDispatcher; + } + + const previousHostDispatcher = prepareToRender(request.resources); + + const prevResponseState = currentResponseState; + setCurrentResponseState(request.responseState); + + try { + const pingedTasks = request.pingedTasks; + let i; + + for (i = 0; i < pingedTasks.length; i++) { + const task = pingedTasks[i]; + retryTask(request, task); + } + + pingedTasks.splice(0, i); + + if (request.destination !== null) { + flushCompletedQueues(request, request.destination); + } + } catch (error) { + logRecoverableError(request, error); + fatalError(request, error); + } finally { + setCurrentResponseState(prevResponseState); + ReactCurrentDispatcher$1.current = prevDispatcher; + + { + ReactCurrentCache.current = prevCacheDispatcher; + } + + cleanupAfterRender(previousHostDispatcher); + + if (prevDispatcher === HooksDispatcher) { + // This means that we were in a reentrant work loop. This could happen + // in a renderer that supports synchronous work like renderToString, + // when it's called from within another renderer. + // Normally we don't bother switching the contexts to their root/default + // values when leaving because we'll likely need the same or similar + // context again. However, when we're inside a synchronous loop like this + // we'll to restore the context to what it was before returning. + switchContext(prevContext); + } + } +} + +function flushSubtree(request, destination, segment) { + segment.parentFlushed = true; + + switch (segment.status) { + case PENDING: { + // 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. + const segmentID = (segment.id = request.nextSegmentId++); // 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); + } + + case COMPLETED: { + segment.status = FLUSHED; + let r = true; + const chunks = segment.chunks; + let chunkIdx = 0; + const children = segment.children; + + for (let childIdx = 0; childIdx < children.length; childIdx++) { + const nextChild = children[childIdx]; // Write all the chunks up until the next child. + + for (; chunkIdx < nextChild.index; chunkIdx++) { + writeChunk(destination, chunks[chunkIdx]); + } + + r = flushSegment(request, destination, nextChild); + } // Finally just write all the remaining chunks + + for (; chunkIdx < chunks.length - 1; chunkIdx++) { + writeChunk(destination, chunks[chunkIdx]); + } + + if (chunkIdx < chunks.length) { + r = writeChunkAndReturn(destination, chunks[chunkIdx]); } + + return r; } - f.splice(0, e); - var m = a.completedBoundaries; - for (e = 0; e < m.length; e++) - if (!Xc(a, b, m[e])) { - a.destination = null; - e++; - m.splice(0, e); + + default: { + throw new Error( + 'Aborted, errored or already flushed boundaries should not be flushed again. This is a bug in React.' + ); + } + } +} + +function flushSegment(request, destination, segment) { + const boundary = segment.boundary; + + if (boundary === null) { + // Not a suspense boundary. + return flushSubtree(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) { + // 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. + + 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++; + + 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. + + const id = (boundary.id = assignSuspenseBoundaryID(request.responseState)); + writeStartPendingSuspenseBoundary(destination, request.responseState, id); // Flush the fallback. + + flushSubtree(request, destination, segment); + return writeEndPendingSuspenseBoundary(destination, request.responseState); + } else if (boundary.byteSize > request.progressiveChunkSize) { + // This boundary is large and will be emitted separately so that we can progressively show + // other content. We add it to the queue during the flush because we have to ensure that + // the parent flushes first so that there's something to inject it into. + // We also have to make sure that it's emitted into the queue in a deterministic slot. + // I.e. we can't insert it here when it completes. + // Assign an ID to refer to the future content by. + boundary.rootSegmentID = request.nextSegmentId++; + request.completedBoundaries.push(boundary); // Emit a pending rendered suspense boundary wrapper. + + writeStartPendingSuspenseBoundary( + destination, + request.responseState, + boundary.id + ); // Flush the fallback. + + flushSubtree(request, destination, segment); + return writeEndPendingSuspenseBoundary(destination, request.responseState); + } else { + { + hoistResources(request.resources, boundary.resources); + } // We can inline this boundary's content as a complete boundary. + + writeStartCompletedSuspenseBoundary(destination, request.responseState); + const completedSegments = boundary.completedSegments; + + if (completedSegments.length !== 1) { + throw new Error( + 'A previously unvisited boundary must have exactly one root segment. This is a bug in React.' + ); + } + + const contentSegment = completedSegments[0]; + flushSegment(request, destination, contentSegment); + return writeEndCompletedSuspenseBoundary( + destination, + request.responseState + ); + } +} + +function flushInitialResources(destination, resources, responseState) { + writeInitialResources(destination, resources, responseState); +} + +function flushImmediateResources(destination, request) { + writeImmediateResources( + destination, + request.resources, + request.responseState + ); +} + +function flushClientRenderedBoundary(request, destination, boundary) { + return writeClientRenderBoundaryInstruction( + destination, + request.responseState, + boundary.id, + boundary.errorDigest, + boundary.errorMessage, + boundary.errorComponentStack + ); +} + +function flushSegmentContainer(request, destination, segment) { + writeStartSegment( + destination, + request.responseState, + segment.formatContext, + segment.id + ); + flushSegment(request, destination, segment); + return writeEndSegment(destination, segment.formatContext); +} + +function flushCompletedBoundary(request, destination, boundary) { + { + setCurrentlyRenderingBoundaryResourcesTarget( + request.resources, + boundary.resources + ); + } + + const completedSegments = boundary.completedSegments; + let i = 0; + + for (; i < completedSegments.length; i++) { + const segment = completedSegments[i]; + flushPartiallyCompletedSegment(request, destination, boundary, segment); + } + + completedSegments.length = 0; + return writeCompletedBoundaryInstruction( + destination, + request.responseState, + boundary.id, + boundary.rootSegmentID, + boundary.resources + ); +} + +function flushPartialBoundary(request, destination, boundary) { + { + setCurrentlyRenderingBoundaryResourcesTarget( + request.resources, + boundary.resources + ); + } + + const completedSegments = boundary.completedSegments; + let i = 0; + + for (; i < completedSegments.length; i++) { + const segment = completedSegments[i]; + + if ( + !flushPartiallyCompletedSegment(request, destination, boundary, segment) + ) { + i++; + completedSegments.splice(0, i); // Only write as much as the buffer wants. Something higher priority + // might want to write later. + + return false; + } + } + + completedSegments.splice(0, i); + return true; +} + +function flushPartiallyCompletedSegment( + request, + destination, + boundary, + segment +) { + if (segment.status === FLUSHED) { + // We've already flushed this inline. + return true; + } + + const segmentID = segment.id; + + if (segmentID === -1) { + // This segment wasn't previously referred to. This happens at the root of + // a boundary. We make kind of a leap here and assume this is the root. + const rootSegmentID = (segment.id = boundary.rootSegmentID); + + if (rootSegmentID === -1) { + 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 { + flushSegmentContainer(request, destination, segment); + return writeCompletedSegmentInstruction( + destination, + request.responseState, + segmentID + ); + } +} + +function flushCompletedQueues(request, destination) { + try { + // The structure of this is to go through each queue one by one and write + // until the sink tells us to stop. When we should stop, we still finish writing + // that item fully and then yield. At that point we remove the already completed + // items up until the point we completed them. + let i; + const completedRootSegment = request.completedRootSegment; + + if (completedRootSegment !== null) { + if (request.pendingRootTasks === 0) { + if (enableFloat) { + const preamble = request.preamble; + + for (i = 0; i < preamble.length; i++) { + // we expect the preamble to be tiny and will ignore backpressure + writeChunk(destination, preamble[i]); + } + + flushInitialResources( + destination, + request.resources, + request.responseState + ); + } + + flushSegment(request, destination, completedRootSegment); + request.completedRootSegment = null; + writeCompletedRoot(destination, request.responseState); + } else { + // We haven't flushed the root yet so we don't need to check any other branches further down return; } - m.splice(0, e); - ba(b); - n = 0; - var q = a.partialBoundaries; - for (e = 0; e < q.length; e++) { - var r = q[e]; - a: { - f = a; - g = b; - var E = r.completedSegments; - for (h = 0; h < E.length; h++) - if (!Yc(f, g, r, E[h])) { - h++; - E.splice(0, h); - var F = !1; - break a; - } - E.splice(0, h); - F = !0; + } else if (enableFloat) { + flushImmediateResources(destination, request); + } // 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. + + const clientRenderedBoundaries = request.clientRenderedBoundaries; + + for (i = 0; i < clientRenderedBoundaries.length; i++) { + const boundary = clientRenderedBoundaries[i]; + + if (!flushClientRenderedBoundary(request, destination, boundary)) { + request.destination = null; + i++; + clientRenderedBoundaries.splice(0, i); + return; } - if (!F) { - a.destination = null; - e++; - q.splice(0, e); + } + + clientRenderedBoundaries.splice(0, i); // Next we emit any complete boundaries. It's better to favor boundaries + // that are completely done since we can actually show them, than it is to emit + // any individual segments from a partially complete boundary. + + const completedBoundaries = request.completedBoundaries; + + for (i = 0; i < completedBoundaries.length; i++) { + const boundary = completedBoundaries[i]; + + if (!flushCompletedBoundary(request, destination, boundary)) { + request.destination = null; + i++; + completedBoundaries.splice(0, i); return; } } - q.splice(0, e); - var C = a.completedBoundaries; - for (e = 0; e < C.length; e++) - if (!Xc(a, b, C[e])) { - a.destination = null; - e++; - C.splice(0, e); + + completedBoundaries.splice(0, i); // Allow anything written so far to flush to the underlying sink before + // we continue with lower priorities. + + completeWriting(destination); + beginWriting(destination); // TODO: Here we'll emit data used by hydration. + // Next we emit any segments of any boundaries that are partially complete + // but not deeply complete. + + const partialBoundaries = request.partialBoundaries; + + for (i = 0; i < partialBoundaries.length; i++) { + const boundary = partialBoundaries[i]; + + if (!flushPartialBoundary(request, destination, boundary)) { + request.destination = null; + i++; + partialBoundaries.splice(0, i); return; } - C.splice(0, e); + } + + partialBoundaries.splice(0, i); // Next we check the completed boundaries again. This may have had + // boundaries added to it in case they were too larged to be inlined. + // New ones might be added in this loop. + + const largeBoundaries = request.completedBoundaries; + + for (i = 0; i < largeBoundaries.length; i++) { + const boundary = largeBoundaries[i]; + + if (!flushCompletedBoundary(request, destination, boundary)) { + request.destination = null; + i++; + largeBoundaries.splice(0, i); + return; + } + } + + largeBoundaries.splice(0, i); } finally { - ba(b), - 0 === a.allPendingTasks && - 0 === a.pingedTasks.length && - 0 === a.clientRenderedBoundaries.length && - 0 === a.completedBoundaries.length && - b.close(); + if ( + request.allPendingTasks === 0 && + request.pingedTasks.length === 0 && + request.clientRenderedBoundaries.length === 0 && + request.completedBoundaries.length === 0 // We don't need to check any partially completed segments because + // either they have pending task or they're complete. + ) { + { + const postamble = request.postamble; + + for (let i = 0; i < postamble.length; i++) { + writeChunk(destination, postamble[i]); + } + } + + close(destination); + } } } -function Zc(a) { + +function startWork(request) { + scheduleWork(() => performWork(request)); +} +function startFlowing(request, destination) { + if (request.status === CLOSING) { + request.status = CLOSED; + closeWithError(destination, request.fatalError); + return; + } + + if (request.status === CLOSED) { + return; + } + + if (request.destination !== null) { + // We're already flowing. + return; + } + + request.destination = destination; + try { - var b = a.abortableTasks; - b.forEach(Sc, a); - b.clear(); - null !== a.destination && Tc(a, a.destination); - } catch (c) { - Y(a, c), Ic(a, c); - } -} -export function renderToReadableStream(a, b) { - return new Promise(function (c, d) { - var f, - e, - g = new Promise(function (a, b) { - e = a; - f = b; - }), - h = Ec( - a, - xa( - b ? b.identifierPrefix : void 0, - b ? b.nonce : void 0, - b ? b.bootstrapScriptContent : void 0, - b ? b.bootstrapScripts : void 0, - b ? b.bootstrapModules : void 0 - ), - ya(b ? b.namespaceURI : void 0), - b ? b.progressiveChunkSize : void 0, - b ? b.onError : void 0, - e, - function () { - var a = new ReadableStream( - { - type: "direct", - pull: function (a) { - if (1 === h.status) (h.status = 2), da(a, h.fatalError); - else if (2 !== h.status && null === h.destination) { - h.destination = a; - try { - Tc(h, a); - } catch (F) { - Y(h, F), Ic(h, F); - } - } - }, - cancel: function () { - Zc(h); - }, - }, - { highWaterMark: 2048 } - ); - a.allReady = g; - c(a); - }, - function (a) { - g.catch(function () {}); - d(a); - }, - f - ); - if (b && b.signal) { - var m = b.signal, - q = function () { - Zc(h); - m.removeEventListener("abort", q); + flushCompletedQueues(request, destination); + } catch (error) { + logRecoverableError(request, error); + fatalError(request, error); + } +} // This is called to early terminate a request. It puts all pending boundaries in client rendered state. + +function abort(request, reason) { + try { + const abortableTasks = request.abortableTasks; + + if (abortableTasks.size > 0) { + const error = + reason === undefined + ? new Error('The render was aborted by the server without a reason.') + : reason; + abortableTasks.forEach((task) => abortTask(task, request, error)); + abortableTasks.clear(); + } + + if (request.destination !== null) { + flushCompletedQueues(request, request.destination); + } + } catch (error) { + logRecoverableError(request, error); + fatalError(request, error); + } +} + +function renderToReadableStream(children, options) { + return new Promise((resolve, reject) => { + let onFatalError; + let onAllReady; + const allReady = new Promise((res, rej) => { + onAllReady = res; + onFatalError = rej; + }); + + function onShellReady() { + const stream = new ReadableStream( + { + type: 'direct', + pull: (controller) => { + // $FlowIgnore + startFlowing(request, controller); + }, + cancel: (reason) => { + abort(request); + }, + }, // $FlowFixMe size() methods are not allowed on byte streams. + { + highWaterMark: 2048, + } + ); // TODO: Move to sub-classing ReadableStream. + + stream.allReady = allReady; + resolve(stream); + } + + function onShellError(error) { + // If the shell errors the caller of `renderToReadableStream` won't have access to `allReady`. + // However, `allReady` will be rejected by `onFatalError` as well. + // So we need to catch the duplicate, uncatchable fatal error in `allReady` to prevent a `UnhandledPromiseRejection`. + allReady.catch(() => {}); + reject(error); + } + + const request = createRequest( + children, + createResponseState( + options ? options.identifierPrefix : undefined, + options ? options.nonce : undefined, + options ? options.bootstrapScriptContent : undefined, + options ? options.bootstrapScripts : undefined, + options ? options.bootstrapModules : undefined, + options ? options.unstable_externalRuntimeSrc : undefined + ), + createRootFormatContext(options ? options.namespaceURI : undefined), + options ? options.progressiveChunkSize : undefined, + options ? options.onError : undefined, + onAllReady, + onShellReady, + onShellError, + onFatalError + ); + + if (options && options.signal) { + const signal = options.signal; + + if (signal.aborted) { + abort(request, signal.reason); + } else { + const listener = () => { + abort(request, signal.reason); + signal.removeEventListener('abort', listener); }; - m.addEventListener("abort", q); + + signal.addEventListener('abort', listener); + } } - Hc(h); + + startWork(request); }); } -export const version = "18.1.0"; + +export {renderToReadableStream, ReactVersion as version}; |