From 14a6de4200eacf5c3418a60d4bf1c174761576a3 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Mon, 14 Jun 2021 13:54:27 -0400 Subject: [PATCH] Add wrapper around the ServerFormatConfig for legacy mode This ensures that we can inject custom overrides without negatively affecting the new implementation. This adds another field for static mark up for example. --- .../src/server/ReactDOMLegacyServerBrowser.js | 4 +- .../src/server/ReactDOMLegacyServerNode.js | 4 +- .../ReactDOMLegacyServerStreamConfig.js | 2 - .../src/server/ReactDOMServerFormatConfig.js | 17 ++-- .../ReactDOMServerLegacyFormatConfig.js | 77 +++++++++++++++++++ .../src/ReactServerStreamConfigFB.js | 2 - .../src/ReactServerStreamConfigBrowser.js | 2 - .../src/ReactServerStreamConfigNode.js | 2 - .../ReactServerFormatConfig.dom-legacy.js | 2 +- 9 files changed, 91 insertions(+), 21 deletions(-) create mode 100644 packages/react-dom/src/server/ReactDOMServerLegacyFormatConfig.js diff --git a/packages/react-dom/src/server/ReactDOMLegacyServerBrowser.js b/packages/react-dom/src/server/ReactDOMLegacyServerBrowser.js index 5435c3b6449c7..5a01fa9327955 100644 --- a/packages/react-dom/src/server/ReactDOMLegacyServerBrowser.js +++ b/packages/react-dom/src/server/ReactDOMLegacyServerBrowser.js @@ -22,7 +22,7 @@ import { import { createResponseState, createRootFormatContext, -} from './ReactDOMServerFormatConfig'; +} from './ReactDOMServerLegacyFormatConfig'; type ServerOptions = { identifierPrefix?: string, @@ -59,7 +59,7 @@ function renderToString( const request = createRequest( children, destination, - createResponseState(options ? options.identifierPrefix : undefined), + createResponseState(false, options ? options.identifierPrefix : undefined), createRootFormatContext(undefined), Infinity, onError, diff --git a/packages/react-dom/src/server/ReactDOMLegacyServerNode.js b/packages/react-dom/src/server/ReactDOMLegacyServerNode.js index 29ba74f8ffaf7..55b05d90c4753 100644 --- a/packages/react-dom/src/server/ReactDOMLegacyServerNode.js +++ b/packages/react-dom/src/server/ReactDOMLegacyServerNode.js @@ -21,7 +21,7 @@ import { import { createResponseState, createRootFormatContext, -} from './ReactDOMServerFormatConfig'; +} from './ReactDOMServerLegacyFormatConfig'; import { version, @@ -77,7 +77,7 @@ function renderToNodeStream( const request = createRequest( children, destination, - createResponseState(options ? options.identifierPrefix : undefined), + createResponseState(false, options ? options.identifierPrefix : undefined), createRootFormatContext(undefined), Infinity, onError, diff --git a/packages/react-dom/src/server/ReactDOMLegacyServerStreamConfig.js b/packages/react-dom/src/server/ReactDOMLegacyServerStreamConfig.js index c1d6c1df07ef9..4cfe16091bc58 100644 --- a/packages/react-dom/src/server/ReactDOMLegacyServerStreamConfig.js +++ b/packages/react-dom/src/server/ReactDOMLegacyServerStreamConfig.js @@ -16,8 +16,6 @@ export type Destination = { export type PrecomputedChunk = string; export type Chunk = string; -export const isPrimaryStreamConfig = false; - export function scheduleWork(callback: () => void) { callback(); } diff --git a/packages/react-dom/src/server/ReactDOMServerFormatConfig.js b/packages/react-dom/src/server/ReactDOMServerFormatConfig.js index 7d705a6abe1d3..1e77b80184d22 100644 --- a/packages/react-dom/src/server/ReactDOMServerFormatConfig.js +++ b/packages/react-dom/src/server/ReactDOMServerFormatConfig.js @@ -23,7 +23,6 @@ import { writeChunk, stringToChunk, stringToPrecomputedChunk, - isPrimaryStreamConfig, } from 'react-server/src/ReactServerStreamConfig'; import { @@ -51,7 +50,7 @@ import isArray from 'shared/isArray'; // Used to distinguish these contexts from ones used in other renderers. // E.g. this can be used to distinguish legacy renderers from this modern one. -export const isPrimaryRenderer = isPrimaryStreamConfig; +export const isPrimaryRenderer = true; // Per response, global state that is not contextual to the rendering subtree. export type ResponseState = { @@ -63,18 +62,20 @@ export type ResponseState = { nextOpaqueID: number, sentCompleteSegmentFunction: boolean, sentCompleteBoundaryFunction: boolean, - sentClientRenderFunction: boolean, + sentClientRenderFunction: boolean, // We allow the legacy renderer to extend this object. + ... }; // Allows us to keep track of what we've already written so we can refer back to it. export function createResponseState( - identifierPrefix: string = '', + identifierPrefix: string | void, ): ResponseState { + const idPrefix = identifierPrefix === undefined ? '' : identifierPrefix; return { - placeholderPrefix: stringToPrecomputedChunk(identifierPrefix + 'P:'), - segmentPrefix: stringToPrecomputedChunk(identifierPrefix + 'S:'), - boundaryPrefix: identifierPrefix + 'B:', - opaqueIdentifierPrefix: identifierPrefix + 'R:', + placeholderPrefix: stringToPrecomputedChunk(idPrefix + 'P:'), + segmentPrefix: stringToPrecomputedChunk(idPrefix + 'S:'), + boundaryPrefix: idPrefix + 'B:', + opaqueIdentifierPrefix: idPrefix + 'R:', nextSuspenseID: 0, nextOpaqueID: 0, sentCompleteSegmentFunction: false, diff --git a/packages/react-dom/src/server/ReactDOMServerLegacyFormatConfig.js b/packages/react-dom/src/server/ReactDOMServerLegacyFormatConfig.js new file mode 100644 index 0000000000000..09e4f84a4a153 --- /dev/null +++ b/packages/react-dom/src/server/ReactDOMServerLegacyFormatConfig.js @@ -0,0 +1,77 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +import {createResponseState as createResponseStateImpl} from './ReactDOMServerFormatConfig'; + +import type {PrecomputedChunk} from 'react-server/src/ReactServerStreamConfig'; + +export const isPrimaryRenderer = false; + +export type ResponseState = { + // Keep this in sync with ReactDOMServerFormatConfig + placeholderPrefix: PrecomputedChunk, + segmentPrefix: PrecomputedChunk, + boundaryPrefix: string, + opaqueIdentifierPrefix: string, + nextSuspenseID: number, + nextOpaqueID: number, + sentCompleteSegmentFunction: boolean, + sentCompleteBoundaryFunction: boolean, + sentClientRenderFunction: boolean, + // This is an extra field for the legacy renderer + generateStaticMarkup: boolean, +}; + +export function createResponseState( + generateStaticMarkup: boolean, + identifierPrefix: string | void, +): ResponseState { + const responseState = createResponseStateImpl(identifierPrefix); + return { + // Keep this in sync with ReactDOMServerFormatConfig + placeholderPrefix: responseState.placeholderPrefix, + segmentPrefix: responseState.segmentPrefix, + boundaryPrefix: responseState.boundaryPrefix, + opaqueIdentifierPrefix: responseState.opaqueIdentifierPrefix, + nextSuspenseID: responseState.nextSuspenseID, + nextOpaqueID: responseState.nextOpaqueID, + sentCompleteSegmentFunction: responseState.sentCompleteSegmentFunction, + sentCompleteBoundaryFunction: responseState.sentCompleteBoundaryFunction, + sentClientRenderFunction: responseState.sentClientRenderFunction, + // This is an extra field for the legacy renderer + generateStaticMarkup, + }; +} + +export type { + FormatContext, + SuspenseBoundaryID, + OpaqueIDType, +} from './ReactDOMServerFormatConfig'; + +export { + createRootFormatContext, + getChildFormatContext, + createSuspenseBoundaryID, + makeServerID, + pushEmpty, + pushTextInstance, + pushStartInstance, + pushEndInstance, + writePlaceholder, + writeStartCompletedSuspenseBoundary, + writeStartPendingSuspenseBoundary, + writeStartClientRenderedSuspenseBoundary, + writeEndSuspenseBoundary, + writeStartSegment, + writeEndSegment, + writeCompletedSegmentInstruction, + writeCompletedBoundaryInstruction, + writeClientRenderBoundaryInstruction, +} from './ReactDOMServerFormatConfig'; diff --git a/packages/react-server-dom-relay/src/ReactServerStreamConfigFB.js b/packages/react-server-dom-relay/src/ReactServerStreamConfigFB.js index b13e5f3792601..e0477fd6197e7 100644 --- a/packages/react-server-dom-relay/src/ReactServerStreamConfigFB.js +++ b/packages/react-server-dom-relay/src/ReactServerStreamConfigFB.js @@ -17,8 +17,6 @@ export type Destination = { export type PrecomputedChunk = string; export type Chunk = string; -export const isPrimaryStreamConfig = true; - export function scheduleWork(callback: () => void) { // We don't schedule work in this model, and instead expect performWork to always be called repeatedly. } diff --git a/packages/react-server/src/ReactServerStreamConfigBrowser.js b/packages/react-server/src/ReactServerStreamConfigBrowser.js index b669002aff771..3714be4302765 100644 --- a/packages/react-server/src/ReactServerStreamConfigBrowser.js +++ b/packages/react-server/src/ReactServerStreamConfigBrowser.js @@ -12,8 +12,6 @@ export type Destination = ReadableStreamController; export type PrecomputedChunk = Uint8Array; export type Chunk = Uint8Array; -export const isPrimaryStreamConfig = true; - export function scheduleWork(callback: () => void) { callback(); } diff --git a/packages/react-server/src/ReactServerStreamConfigNode.js b/packages/react-server/src/ReactServerStreamConfigNode.js index 58ce127ba9659..348deb7605039 100644 --- a/packages/react-server/src/ReactServerStreamConfigNode.js +++ b/packages/react-server/src/ReactServerStreamConfigNode.js @@ -19,8 +19,6 @@ export type Destination = Writable & MightBeFlushable; export type PrecomputedChunk = Uint8Array; export type Chunk = string; -export const isPrimaryStreamConfig = true; - export function scheduleWork(callback: () => void) { setImmediate(callback); } diff --git a/packages/react-server/src/forks/ReactServerFormatConfig.dom-legacy.js b/packages/react-server/src/forks/ReactServerFormatConfig.dom-legacy.js index c6e482efeb60c..acbac5042b62a 100644 --- a/packages/react-server/src/forks/ReactServerFormatConfig.dom-legacy.js +++ b/packages/react-server/src/forks/ReactServerFormatConfig.dom-legacy.js @@ -7,4 +7,4 @@ * @flow */ -export * from 'react-dom/src/server/ReactDOMServerFormatConfig'; +export * from 'react-dom/src/server/ReactDOMServerLegacyFormatConfig';