Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* 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
*/

export * from 'react-client/src/ReactFlightClientHostConfigBrowser';
export * from 'react-client/src/ReactFlightClientHostConfigStream';
export * from 'react-server-dom-webpack/src/ReactFlightClientWebpackBundlerConfig';
80 changes: 80 additions & 0 deletions packages/react-dom/src/server/ReactDOMFizzServerNext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* 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 type {ReactNodeList} from 'shared/ReactTypes';
import type {Destination} from 'react-server/src/ReactServerStreamConfigNext';

import ReactVersion from 'shared/ReactVersion';

import {
createRequest,
startWork,
startFlowing,
stopFlowing,
abort,
} from 'react-server/src/ReactFizzServer';

import {
createResponseState,
createRootFormatContext,
} from './ReactDOMServerFormatConfig';

type Options = {|
identifierPrefix?: string,
namespaceURI?: string,
progressiveChunkSize?: number,
onReadyToStream?: () => void,
onCompleteAll?: () => void,
onError?: (error: mixed) => void,
|};

type Controls = {|
abort(): void,
update(): void,
|};

function createRequestImpl(
children: ReactNodeList,
destination: Destination,
options: void | Options,
) {
return createRequest(
children,
destination,
createResponseState(options ? options.identifierPrefix : undefined),
createRootFormatContext(options ? options.namespaceURI : undefined),
options ? options.progressiveChunkSize : undefined,
options ? options.onError : undefined,
options ? options.onCompleteAll : undefined,
options ? options.onReadyToStream : undefined,
);
}

function renderToNextStream(
children: ReactNodeList,
destination: Destination,
options?: Options,
): Controls {
const request = createRequestImpl(children, destination, options);
startWork(request);
return {
abort() {
abort(request);
},
update() {
if (destination.ready) {
startFlowing(request);
} else {
stopFlowing(request);
}
},
};
}

export {renderToNextStream, ReactVersion as version};
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* 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
*/

export * from 'react-dom/src/client/ReactDOMHostConfig';
7 changes: 7 additions & 0 deletions packages/react-server/src/ReactFizzServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1915,6 +1915,13 @@ export function startFlowing(request: Request): void {
}
}

export function stopFlowing(request: Request): void {
if (request.status === CLOSED) {
return;
}
request.status = BUFFERING;
}

// This is called to early terminate a request. It puts all pending boundaries in client rendered state.
export function abort(request: Request): void {
try {
Expand Down
65 changes: 65 additions & 0 deletions packages/react-server/src/ReactServerStreamConfigNext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* 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
*/

declare function __next_scheduleReactServerStreamWork__(
callback: () => void,
): void;

export type Destination = {|
write: (chunk: Uint8Array) => void,
buffer: (shouldBuffer: boolean) => void,
flush: () => void,
close: (error: mixed) => void,
ready: boolean,
|};

export type PrecomputedChunk = Uint8Array;
export type Chunk = Uint8Array;

export function scheduleWork(callback: () => void) {
__next_scheduleReactServerStreamWork__(callback);
}

export function flushBuffered(destination: Destination) {
destination.flush();
}

export function beginWriting(destination: Destination) {
destination.buffer(true);
}

export function writeChunk(
destination: Destination,
chunk: PrecomputedChunk | Chunk,
): boolean {
destination.write(chunk);
return destination.ready;
}

export function completeWriting(destination: Destination) {
destination.buffer(false);
}

export function close(destination: Destination) {
destination.close();
}

const textEncoder = new TextEncoder();

export function stringToChunk(content: string): Chunk {
return textEncoder.encode(content);
}

export function stringToPrecomputedChunk(content: string): PrecomputedChunk {
return textEncoder.encode(content);
}

export function closeWithError(destination: Destination, error: mixed): void {
destination.close(error);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* 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
*/

export * from '../ReactFlightServerConfigStream';
export * from 'react-server-dom-webpack/src/ReactFlightServerWebpackBundlerConfig';
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* 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
*/

export * from 'react-dom/src/server/ReactDOMServerFormatConfig';
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* 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
*/

export * from '../ReactServerStreamConfigNext';
8 changes: 8 additions & 0 deletions scripts/rollup/bundles.js
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,14 @@ const bundles = [
global: 'ReactDOMServer',
externals: ['react'],
},
{
bundleTypes: [NODE_DEV, NODE_PROD],
moduleType: RENDERER,
entry: 'react-dom/src/server/ReactDOMFizzServerNext',
name: 'react-dom-server-next',
global: 'ReactDOMServer',
externals: ['react'],
},
{
bundleTypes: __EXPERIMENTAL__ ? [FB_WWW_DEV, FB_WWW_PROD] : [],
moduleType: RENDERER,
Expand Down
14 changes: 14 additions & 0 deletions scripts/shared/inlinedHostConfigs.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,20 @@ module.exports = [
isFlowTyped: true,
isServerSupported: true,
},
{
shortName: 'dom-next',
entryPoints: [
'react-dom/src/server/ReactDOMFizzServerNext', // react-dom/server
],
paths: [
'react-dom',
'react-server-dom-webpack',
'react-dom/src/server/ReactDOMFizzServerNext.js', // react-dom/server.browser
'react-client/src/ReactFlightClientStream.js', // We can only type check this in streaming configurations.
],
isFlowTyped: true,
isServerSupported: true,
},
{
shortName: 'art',
entryPoints: ['react-art'],
Expand Down