From 6c82eff57601823b9443a702dba601ec2e1c149c Mon Sep 17 00:00:00 2001 From: Andrey Lunyov Date: Fri, 15 Dec 2023 15:57:48 -0500 Subject: [PATCH 1/6] [rsc @fb ] simplify implementation of isClientReference and friends --- .../src/ReactFlightDOMServerFB.js | 12 ++-- .../src/ReactFlightReferencesFB.js | 61 +++++++------------ .../ReactFlightDOMServerFB-test.internal.js | 17 ++++-- 3 files changed, 41 insertions(+), 49 deletions(-) diff --git a/packages/react-server-dom-fb/src/ReactFlightDOMServerFB.js b/packages/react-server-dom-fb/src/ReactFlightDOMServerFB.js index a0ab868688797..8ea8a4da72291 100644 --- a/packages/react-server-dom-fb/src/ReactFlightDOMServerFB.js +++ b/packages/react-server-dom-fb/src/ReactFlightDOMServerFB.js @@ -7,13 +7,15 @@ * @flow */ +import type {ClientReference} from './ReactFlightClientConfigFBBundler'; import type {ReactClientValue} from 'react-server/src/ReactFlightServer'; import type { Destination, Chunk, PrecomputedChunk, } from 'react-server/src/ReactServerStreamConfig'; -import type {ClientManifest} from './ReactFlightReferencesFB'; + +import {setClientReferenceImplementation} from './ReactFlightReferencesFB'; import { createRequest, @@ -24,10 +26,9 @@ import { import {setByteLengthOfChunkImplementation} from 'react-server/src/ReactServerStreamConfig'; export { - registerClientReference, - registerServerReference, getRequestedClientReferencesKeys, clearRequestedClientReferencesKeysSet, + setClientReferenceInterface, } from './ReactFlightReferencesFB'; type Options = { @@ -37,7 +38,6 @@ type Options = { function renderToDestination( destination: Destination, model: ReactClientValue, - bundlerConfig: ClientManifest, options?: Options, ): void { if (!configured) { @@ -47,7 +47,7 @@ function renderToDestination( } const request = createRequest( model, - bundlerConfig, + null, options ? options.onError : undefined, ); startWork(request); @@ -56,12 +56,14 @@ function renderToDestination( type Config = { byteLength: (chunk: Chunk | PrecomputedChunk) => number, + ClientReferenceImplementation: {...}, }; let configured = false; function setConfig(config: Config): void { setByteLengthOfChunkImplementation(config.byteLength); + setClientReferenceImplementation(config.ClientReferenceImplementation); configured = true; } diff --git a/packages/react-server-dom-fb/src/ReactFlightReferencesFB.js b/packages/react-server-dom-fb/src/ReactFlightReferencesFB.js index 27e51d06c1b5d..a0e6c229441ce 100644 --- a/packages/react-server-dom-fb/src/ReactFlightReferencesFB.js +++ b/packages/react-server-dom-fb/src/ReactFlightReferencesFB.js @@ -7,15 +7,16 @@ * @flow */ -export opaque type ClientManifest = mixed; +export type ClientManifest = null; // eslint-disable-next-line no-unused-vars export type ServerReference = string; // eslint-disable-next-line no-unused-vars -export type ClientReference = string; +export type ClientReference = { + getModuleId(): ClientReferenceKey, +}; -const registeredClientReferences = new Map(); const requestedClientReferencesKeys = new Set(); export type ClientReferenceKey = string; @@ -26,56 +27,38 @@ export type ClientReferenceMetadata = { export type ServerReferenceId = string; -export function registerClientReference( - clientReference: ClientReference, - moduleId: ClientReferenceKey, -): ClientReference { - const exportName = 'default'; // Currently, we only support modules with `default` export - registeredClientReferences.set(clientReference, { - moduleId, - exportName, - }); - - return clientReference; +let ClientReferenceImpl: {...} | null = null; +export function setClientReferenceImplementation(clientReferenceImpl: { + ... +}): void { + ClientReferenceImpl = clientReferenceImpl; } -export function isClientReference(reference: T): boolean { - return registeredClientReferences.has(reference); +export function isClientReference(reference: mixed): boolean { + if (ClientReferenceImpl == null) { + throw new Error('Expected ClientReferenceImpl.'); + } + if (reference instanceof ClientReferenceImpl) { + return true; + } + + return false; } export function getClientReferenceKey( clientReference: ClientReference, ): ClientReferenceKey { - const reference = registeredClientReferences.get(clientReference); - if (reference != null) { - requestedClientReferencesKeys.add(reference.moduleId); - return reference.moduleId; - } + const moduleId = clientReference.getModuleId(); + requestedClientReferencesKeys.add(moduleId); - throw new Error( - 'Expected client reference ' + clientReference + ' to be registered.', - ); + return clientReference.getModuleId(); } export function resolveClientReferenceMetadata( config: ClientManifest, clientReference: ClientReference, ): ClientReferenceMetadata { - const metadata = registeredClientReferences.get(clientReference); - if (metadata != null) { - return metadata; - } - - throw new Error( - 'Expected client reference ' + clientReference + ' to be registered.', - ); -} - -export function registerServerReference( - serverReference: ServerReference, - exportName: string, -): ServerReference { - throw new Error('registerServerReference: Not Implemented.'); + return {moduleId: clientReference.getModuleId(), exportName: 'default'}; } export function isServerReference(reference: T): boolean { diff --git a/packages/react-server-dom-fb/src/__tests__/ReactFlightDOMServerFB-test.internal.js b/packages/react-server-dom-fb/src/__tests__/ReactFlightDOMServerFB-test.internal.js index d83ef8aa0b502..1a9124cf45a21 100644 --- a/packages/react-server-dom-fb/src/__tests__/ReactFlightDOMServerFB-test.internal.js +++ b/packages/react-server-dom-fb/src/__tests__/ReactFlightDOMServerFB-test.internal.js @@ -28,7 +28,6 @@ let ReactDOMClient; let ReactServerDOMServer; let ReactServerDOMClient; let Suspense; -let registerClientReference; class Destination { #buffer = ''; @@ -57,14 +56,22 @@ class Destination { onError() {} } +class ClientReferenceImpl { + constructor(moduleId) { + this.moduleId = moduleId; + } + + getModuleId() { + return this.moduleId; + } +} + describe('ReactFlightDOM for FB', () => { beforeEach(() => { // For this first reset we are going to load the dom-node version of react-server-dom-turbopack/server // This can be thought of as essentially being the React Server Components scope with react-server // condition jest.resetModules(); - registerClientReference = - require('../ReactFlightReferencesFB').registerClientReference; jest.mock('react', () => require('react/src/ReactSharedSubsetFB')); @@ -78,8 +85,7 @@ describe('ReactFlightDOM for FB', () => { }); clientExports = value => { - registerClientReference(value, value.name); - return value; + return new ClientReferenceImpl(value.name); }; moduleMap = { @@ -91,6 +97,7 @@ describe('ReactFlightDOM for FB', () => { ReactServerDOMServer = require('../ReactFlightDOMServerFB'); ReactServerDOMServer.setConfig({ byteLength: str => Buffer.byteLength(str), + ClientReferenceImplementation: ClientReferenceImpl, }); // This reset is to load modules for the SSR/Browser scope. From ae93fcb5192252aee2ec4d3275720a26ed94f4d0 Mon Sep 17 00:00:00 2001 From: Andrey Lunyov Date: Fri, 15 Dec 2023 16:02:18 -0500 Subject: [PATCH 2/6] flow fix --- packages/react-server-dom-fb/src/ReactFlightDOMServerFB.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-server-dom-fb/src/ReactFlightDOMServerFB.js b/packages/react-server-dom-fb/src/ReactFlightDOMServerFB.js index 8ea8a4da72291..a1e3064771781 100644 --- a/packages/react-server-dom-fb/src/ReactFlightDOMServerFB.js +++ b/packages/react-server-dom-fb/src/ReactFlightDOMServerFB.js @@ -28,7 +28,7 @@ import {setByteLengthOfChunkImplementation} from 'react-server/src/ReactServerSt export { getRequestedClientReferencesKeys, clearRequestedClientReferencesKeysSet, - setClientReferenceInterface, + setClientReferenceImplementation, } from './ReactFlightReferencesFB'; type Options = { From 201dc0c24247e7c426d62ae9f8d9621bcaaaa344 Mon Sep 17 00:00:00 2001 From: Andrey Lunyov Date: Fri, 15 Dec 2023 16:02:39 -0500 Subject: [PATCH 3/6] lint --- packages/react-server-dom-fb/src/ReactFlightDOMServerFB.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/react-server-dom-fb/src/ReactFlightDOMServerFB.js b/packages/react-server-dom-fb/src/ReactFlightDOMServerFB.js index a1e3064771781..8cadf4685e3ff 100644 --- a/packages/react-server-dom-fb/src/ReactFlightDOMServerFB.js +++ b/packages/react-server-dom-fb/src/ReactFlightDOMServerFB.js @@ -7,7 +7,6 @@ * @flow */ -import type {ClientReference} from './ReactFlightClientConfigFBBundler'; import type {ReactClientValue} from 'react-server/src/ReactFlightServer'; import type { Destination, From 95a8c4f40ab8c9dc6c19acea663bdaa576af0164 Mon Sep 17 00:00:00 2001 From: Andrey Lunyov Date: Fri, 15 Dec 2023 16:04:42 -0500 Subject: [PATCH 4/6] minor change --- packages/react-server-dom-fb/src/ReactFlightReferencesFB.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/react-server-dom-fb/src/ReactFlightReferencesFB.js b/packages/react-server-dom-fb/src/ReactFlightReferencesFB.js index a0e6c229441ce..c211d7af43930 100644 --- a/packages/react-server-dom-fb/src/ReactFlightReferencesFB.js +++ b/packages/react-server-dom-fb/src/ReactFlightReferencesFB.js @@ -38,11 +38,7 @@ export function isClientReference(reference: mixed): boolean { if (ClientReferenceImpl == null) { throw new Error('Expected ClientReferenceImpl.'); } - if (reference instanceof ClientReferenceImpl) { - return true; - } - - return false; + return reference instanceof ClientReferenceImpl; } export function getClientReferenceKey( From 625e177122ffa339e5662fea854dc896c354a8a7 Mon Sep 17 00:00:00 2001 From: Andrey Lunyov Date: Fri, 15 Dec 2023 16:49:20 -0500 Subject: [PATCH 5/6] pass isClientReference via config --- .../src/ReactFlightDOMServerFB.js | 8 ++++---- .../src/ReactFlightReferencesFB.js | 17 +++++++++-------- .../ReactFlightDOMServerFB-test.internal.js | 2 +- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/packages/react-server-dom-fb/src/ReactFlightDOMServerFB.js b/packages/react-server-dom-fb/src/ReactFlightDOMServerFB.js index 8cadf4685e3ff..9cea942a75dba 100644 --- a/packages/react-server-dom-fb/src/ReactFlightDOMServerFB.js +++ b/packages/react-server-dom-fb/src/ReactFlightDOMServerFB.js @@ -14,7 +14,7 @@ import type { PrecomputedChunk, } from 'react-server/src/ReactServerStreamConfig'; -import {setClientReferenceImplementation} from './ReactFlightReferencesFB'; +import {setCheckIsClientReference} from './ReactFlightReferencesFB'; import { createRequest, @@ -27,7 +27,7 @@ import {setByteLengthOfChunkImplementation} from 'react-server/src/ReactServerSt export { getRequestedClientReferencesKeys, clearRequestedClientReferencesKeysSet, - setClientReferenceImplementation, + setCheckIsClientReference, } from './ReactFlightReferencesFB'; type Options = { @@ -55,14 +55,14 @@ function renderToDestination( type Config = { byteLength: (chunk: Chunk | PrecomputedChunk) => number, - ClientReferenceImplementation: {...}, + isClientReference: (reference: mixed) => boolean, }; let configured = false; function setConfig(config: Config): void { setByteLengthOfChunkImplementation(config.byteLength); - setClientReferenceImplementation(config.ClientReferenceImplementation); + setCheckIsClientReference(config.isClientReference); configured = true; } diff --git a/packages/react-server-dom-fb/src/ReactFlightReferencesFB.js b/packages/react-server-dom-fb/src/ReactFlightReferencesFB.js index c211d7af43930..21f09383a320d 100644 --- a/packages/react-server-dom-fb/src/ReactFlightReferencesFB.js +++ b/packages/react-server-dom-fb/src/ReactFlightReferencesFB.js @@ -27,18 +27,19 @@ export type ClientReferenceMetadata = { export type ServerReferenceId = string; -let ClientReferenceImpl: {...} | null = null; -export function setClientReferenceImplementation(clientReferenceImpl: { - ... -}): void { - ClientReferenceImpl = clientReferenceImpl; +let checkIsClientReference: (clientReference: mixed) => boolean; + +export function setCheckIsClientReference( + impl: (clientReference: mixed) => boolean, +): void { + checkIsClientReference = impl; } export function isClientReference(reference: mixed): boolean { - if (ClientReferenceImpl == null) { - throw new Error('Expected ClientReferenceImpl.'); + if (checkIsClientReference == null) { + throw new Error('Expected implementation for checkIsClientReference.'); } - return reference instanceof ClientReferenceImpl; + return checkIsClientReference(reference); } export function getClientReferenceKey( diff --git a/packages/react-server-dom-fb/src/__tests__/ReactFlightDOMServerFB-test.internal.js b/packages/react-server-dom-fb/src/__tests__/ReactFlightDOMServerFB-test.internal.js index 1a9124cf45a21..69cc1ff5e52e2 100644 --- a/packages/react-server-dom-fb/src/__tests__/ReactFlightDOMServerFB-test.internal.js +++ b/packages/react-server-dom-fb/src/__tests__/ReactFlightDOMServerFB-test.internal.js @@ -97,7 +97,7 @@ describe('ReactFlightDOM for FB', () => { ReactServerDOMServer = require('../ReactFlightDOMServerFB'); ReactServerDOMServer.setConfig({ byteLength: str => Buffer.byteLength(str), - ClientReferenceImplementation: ClientReferenceImpl, + isClientReference: reference => reference instanceof ClientReferenceImpl, }); // This reset is to load modules for the SSR/Browser scope. From 5f125f9e132142fc84cc386bdf67e204b11ca377 Mon Sep 17 00:00:00 2001 From: Andrey Lunyov Date: Sat, 16 Dec 2023 00:00:36 -0500 Subject: [PATCH 6/6] keep registerClientReference and registerServerReference --- .../src/ReactFlightDOMServerFB.js | 2 ++ .../src/ReactFlightReferencesFB.js | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/packages/react-server-dom-fb/src/ReactFlightDOMServerFB.js b/packages/react-server-dom-fb/src/ReactFlightDOMServerFB.js index 9cea942a75dba..fdfa5a008f659 100644 --- a/packages/react-server-dom-fb/src/ReactFlightDOMServerFB.js +++ b/packages/react-server-dom-fb/src/ReactFlightDOMServerFB.js @@ -25,6 +25,8 @@ import { import {setByteLengthOfChunkImplementation} from 'react-server/src/ReactServerStreamConfig'; export { + registerClientReference, + registerServerReference, getRequestedClientReferencesKeys, clearRequestedClientReferencesKeysSet, setCheckIsClientReference, diff --git a/packages/react-server-dom-fb/src/ReactFlightReferencesFB.js b/packages/react-server-dom-fb/src/ReactFlightReferencesFB.js index 21f09383a320d..561ec56c79eb5 100644 --- a/packages/react-server-dom-fb/src/ReactFlightReferencesFB.js +++ b/packages/react-server-dom-fb/src/ReactFlightReferencesFB.js @@ -35,6 +35,10 @@ export function setCheckIsClientReference( checkIsClientReference = impl; } +export function registerClientReference( + clientReference: ClientReference, +): void {} + export function isClientReference(reference: mixed): boolean { if (checkIsClientReference == null) { throw new Error('Expected implementation for checkIsClientReference.'); @@ -58,6 +62,14 @@ export function resolveClientReferenceMetadata( return {moduleId: clientReference.getModuleId(), exportName: 'default'}; } +export function registerServerReference( + serverReference: ServerReference, + id: string, + exportName: null | string, +): ServerReference { + throw new Error('registerServerReference: Not Implemented.'); +} + export function isServerReference(reference: T): boolean { throw new Error('isServerReference: Not Implemented.'); }