diff --git a/packages/react-dom/src/server/ReactDOMServerFormatConfig.js b/packages/react-dom/src/server/ReactDOMServerFormatConfig.js index 1b2bbc28f6669..78e909cff610c 100644 --- a/packages/react-dom/src/server/ReactDOMServerFormatConfig.js +++ b/packages/react-dom/src/server/ReactDOMServerFormatConfig.js @@ -168,17 +168,17 @@ export function getChildFormatContext( return parentContext; } -// This object is used to lazily reuse the ID of the first generated node, or assign one. -// We can't assign an ID up front because the node we're attaching it to might already -// have one. So we need to lazily use that if it's available. -export type SuspenseBoundaryID = { - formattedID: null | PrecomputedChunk, -}; +export type SuspenseBoundaryID = null | PrecomputedChunk; + +export const UNINITIALIZED_SUSPENSE_BOUNDARY_ID: SuspenseBoundaryID = null; -export function createSuspenseBoundaryID( +export function assignSuspenseBoundaryID( responseState: ResponseState, ): SuspenseBoundaryID { - return {formattedID: null}; + const generatedID = responseState.nextSuspenseID++; + return stringToPrecomputedChunk( + responseState.boundaryPrefix + generatedID.toString(16), + ); } export type OpaqueIDType = string; @@ -201,50 +201,13 @@ function encodeHTMLTextNode(text: string): string { return escapeTextForBrowser(text); } -function assignAnID( - responseState: ResponseState, - id: SuspenseBoundaryID, -): PrecomputedChunk { - // TODO: This approach doesn't yield deterministic results since this is assigned during render. - const generatedID = responseState.nextSuspenseID++; - return (id.formattedID = stringToPrecomputedChunk( - responseState.boundaryPrefix + generatedID.toString(16), - )); -} - -const dummyNode1 = stringToPrecomputedChunk(''); - -function pushDummyNodeWithID( - target: Array, - responseState: ResponseState, - assignID: SuspenseBoundaryID, -): void { - const id = assignAnID(responseState, assignID); - target.push(dummyNode1, id, dummyNode2); -} - -export function pushEmpty( - target: Array, - responseState: ResponseState, - assignID: null | SuspenseBoundaryID, -): void { - if (assignID !== null) { - pushDummyNodeWithID(target, responseState, assignID); - } -} - const textSeparator = stringToPrecomputedChunk(''); export function pushTextInstance( target: Array, text: string, responseState: ResponseState, - assignID: null | SuspenseBoundaryID, ): void { - if (assignID !== null) { - pushDummyNodeWithID(target, responseState, assignID); - } if (text === '') { // Empty text doesn't have a DOM node representation and the hydration is aware of this. return; @@ -514,30 +477,6 @@ function pushAttribute( const endOfStartTag = stringToPrecomputedChunk('>'); const endOfStartTagSelfClosing = stringToPrecomputedChunk('/>'); -const idAttr = stringToPrecomputedChunk(' id="'); -const attrEnd = stringToPrecomputedChunk('"'); - -function pushID( - target: Array, - responseState: ResponseState, - assignID: SuspenseBoundaryID, - existingID: mixed, -): void { - if ( - existingID !== null && - existingID !== undefined && - (typeof existingID === 'string' || typeof existingID === 'object') - ) { - // We can reuse the existing ID for our purposes. - assignID.formattedID = stringToPrecomputedChunk( - escapeTextForBrowser(existingID), - ); - } else { - const encodedID = assignAnID(responseState, assignID); - target.push(idAttr, encodedID, attrEnd); - } -} - function pushInnerHTML( target: Array, innerHTML, @@ -598,7 +537,6 @@ function pushStartSelect( target: Array, props: Object, responseState: ResponseState, - assignID: null | SuspenseBoundaryID, ): ReactNodeList { if (__DEV__) { checkControlledValueProps('select', props); @@ -651,9 +589,6 @@ function pushStartSelect( } } } - if (assignID !== null) { - pushID(target, responseState, assignID, props.id); - } target.push(endOfStartTag); pushInnerHTML(target, innerHTML, children); @@ -693,7 +628,6 @@ function pushStartOption( props: Object, responseState: ResponseState, formatContext: FormatContext, - assignID: null | SuspenseBoundaryID, ): ReactNodeList { const selectedValue = formatContext.selectedValue; @@ -776,10 +710,6 @@ function pushStartOption( target.push(selectedMarkerAttribute); } - if (assignID !== null) { - pushID(target, responseState, assignID, props.id); - } - target.push(endOfStartTag); pushInnerHTML(target, innerHTML, children); return children; @@ -789,7 +719,6 @@ function pushInput( target: Array, props: Object, responseState: ResponseState, - assignID: null | SuspenseBoundaryID, ): ReactNodeList { if (__DEV__) { checkControlledValueProps('input', props); @@ -883,10 +812,6 @@ function pushInput( pushAttribute(target, responseState, 'value', defaultValue); } - if (assignID !== null) { - pushID(target, responseState, assignID, props.id); - } - target.push(endOfStartTagSelfClosing); return null; } @@ -895,7 +820,6 @@ function pushStartTextArea( target: Array, props: Object, responseState: ResponseState, - assignID: null | SuspenseBoundaryID, ): ReactNodeList { if (__DEV__) { checkControlledValueProps('textarea', props); @@ -952,10 +876,6 @@ function pushStartTextArea( value = defaultValue; } - if (assignID !== null) { - pushID(target, responseState, assignID, props.id); - } - target.push(endOfStartTag); // TODO (yungsters): Remove support for children content in