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 5435c3b6449c74..5a01fa93279554 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 29ba74f8ffaf77..55b05d90c47533 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 c1d6c1df07ef97..4cfe16091bc584 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 7d705a6abe1d3f..1e77b80184d224 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 00000000000000..09e4f84a4a1532 --- /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 b13e5f3792601a..e0477fd6197e76 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 b669002aff7719..3714be43027657 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 58ce127ba96598..348deb76050395 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 c6e482efeb60c4..acbac5042b62ad 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';