[Flight] Simplify Relay row protocol (#20168)

* Simplify Relay protocol integration

* Encode Relay rows as tuples instead of objects

This is slightly more compact and more ressembles more closely the encoding
we use for the raw stream protocol.
This commit is contained in:
Sebastian Markbåge
2020-11-10 19:54:42 -08:00
committed by GitHub
parent 16e6dadba6
commit 35e53b4653
13 changed files with 132 additions and 208 deletions
@@ -7,10 +7,27 @@
* @flow
*/
export {
import type {RowEncoding} from './ReactFlightDOMRelayProtocol';
import type {Response} from 'react-client/src/ReactFlightClient';
import {
createResponse,
resolveModel,
resolveModule,
resolveError,
close,
} from 'react-client/src/ReactFlightClient';
export {createResponse, close};
export function resolveRow(response: Response, chunk: RowEncoding): void {
if (chunk[0] === 'J') {
resolveModel(response, chunk[1], chunk[2]);
} else if (chunk[0] === 'M') {
resolveModule(response, chunk[1], chunk[2]);
} else {
// $FlowFixMe: Flow doesn't support disjoint unions on tuples.
resolveError(response, chunk[1], chunk[2].message, chunk[2].stack);
}
}
@@ -26,7 +26,7 @@ export {
export type {ModuleMetaData} from 'ReactFlightDOMRelayClientIntegration';
export opaque type UninitializedModel = JSONValue;
export type UninitializedModel = JSONValue;
export type Response = ResponseBase;
@@ -0,0 +1,31 @@
/**
* 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 {ModuleMetaData} from 'ReactFlightDOMRelayServerIntegration';
export type JSONValue =
| string
| number
| boolean
| null
| {+[key: string]: JSONValue}
| Array<JSONValue>;
export type RowEncoding =
| ['J', number, JSONValue]
| ['M', number, ModuleMetaData]
| [
'E',
number,
{
message: string,
stack: string,
...
},
];
@@ -7,6 +7,8 @@
* @flow
*/
import type {RowEncoding, JSONValue} from './ReactFlightDOMRelayProtocol';
import type {Request, ReactModel} from 'react-server/src/ReactFlightServer';
import JSResourceReference from 'JSResourceReference';
@@ -22,9 +24,7 @@ import type {
import {resolveModelToJSON} from 'react-server/src/ReactFlightServer';
import {
emitModel,
emitModule,
emitError,
emitRow,
resolveModuleMetaData as resolveModuleMetaDataImpl,
} from 'ReactFlightDOMRelayServerIntegration';
@@ -45,34 +45,7 @@ export function resolveModuleMetaData<T>(
return resolveModuleMetaDataImpl(config, resource);
}
type JSONValue =
| string
| number
| boolean
| null
| {+[key: string]: JSONValue}
| Array<JSONValue>;
export type Chunk =
| {
type: 'json',
id: number,
json: JSONValue,
}
| {
type: 'module',
id: number,
json: ModuleMetaData,
}
| {
type: 'error',
id: number,
json: {
message: string,
stack: string,
...
},
};
export type Chunk = RowEncoding;
export function processErrorChunk(
request: Request,
@@ -80,14 +53,14 @@ export function processErrorChunk(
message: string,
stack: string,
): Chunk {
return {
type: 'error',
id: id,
json: {
return [
'E',
id,
{
message,
stack,
},
};
];
}
function convertModelToJSON(
@@ -126,11 +99,7 @@ export function processModelChunk(
model: ReactModel,
): Chunk {
const json = convertModelToJSON(request, {}, '', model);
return {
type: 'json',
id: id,
json: json,
};
return ['J', id, json];
}
export function processModuleChunk(
@@ -139,11 +108,7 @@ export function processModuleChunk(
moduleMetaData: ModuleMetaData,
): Chunk {
// The moduleMetaData is already a JSON serializable value.
return {
type: 'module',
id: id,
json: moduleMetaData,
};
return ['M', id, moduleMetaData];
}
export function scheduleWork(callback: () => void) {
@@ -155,13 +120,7 @@ export function flushBuffered(destination: Destination) {}
export function beginWriting(destination: Destination) {}
export function writeChunk(destination: Destination, chunk: Chunk): boolean {
if (chunk.type === 'json') {
emitModel(destination, chunk.id, chunk.json);
} else if (chunk.type === 'module') {
emitModule(destination, chunk.id, chunk.json);
} else {
emitError(destination, chunk.id, chunk.json.message, chunk.json.stack);
}
emitRow(destination, chunk);
return true;
}
@@ -8,26 +8,8 @@
'use strict';
const ReactFlightDOMRelayServerIntegration = {
emitModel(destination, id, json) {
destination.push({
type: 'json',
id: id,
json: json,
});
},
emitModule(destination, id, json) {
destination.push({
type: 'module',
id: id,
json: json,
});
},
emitError(destination, id, message, stack) {
destination.push({
type: 'error',
id: id,
json: {message, stack},
});
emitRow(destination, json) {
destination.push(json);
},
close(destination) {},
resolveModuleMetaData(config, resource) {
@@ -30,18 +30,7 @@ describe('ReactFlightDOMRelay', () => {
const response = ReactDOMFlightRelayClient.createResponse();
for (let i = 0; i < data.length; i++) {
const chunk = data[i];
if (chunk.type === 'json') {
ReactDOMFlightRelayClient.resolveModel(response, chunk.id, chunk.json);
} else if (chunk.type === 'module') {
ReactDOMFlightRelayClient.resolveModule(response, chunk.id, chunk.json);
} else {
ReactDOMFlightRelayClient.resolveError(
response,
chunk.id,
chunk.json.message,
chunk.json.stack,
);
}
ReactDOMFlightRelayClient.resolveRow(response, chunk);
}
ReactDOMFlightRelayClient.close(response);
const model = response.readRoot();
@@ -7,10 +7,27 @@
* @flow
*/
export {
import type {RowEncoding} from './ReactFlightNativeRelayProtocol';
import type {Response} from 'react-client/src/ReactFlightClient';
import {
createResponse,
resolveModel,
resolveModule,
resolveError,
close,
} from 'react-client/src/ReactFlightClient';
export {createResponse, close};
export function resolveRow(response: Response, chunk: RowEncoding): void {
if (chunk[0] === 'J') {
resolveModel(response, chunk[1], chunk[2]);
} else if (chunk[0] === 'M') {
resolveModule(response, chunk[1], chunk[2]);
} else {
// $FlowFixMe: Flow doesn't support disjoint unions on tuples.
resolveError(response, chunk[1], chunk[2].message, chunk[2].stack);
}
}
@@ -26,7 +26,7 @@ export {
export type {ModuleMetaData} from 'ReactFlightNativeRelayClientIntegration';
export opaque type UninitializedModel = JSONValue;
export type UninitializedModel = JSONValue;
export type Response = ResponseBase;
@@ -0,0 +1,31 @@
/**
* 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 {ModuleMetaData} from 'ReactFlightNativeRelayServerIntegration';
export type JSONValue =
| string
| number
| boolean
| null
| {+[key: string]: JSONValue}
| Array<JSONValue>;
export type RowEncoding =
| ['J', number, JSONValue]
| ['M', number, ModuleMetaData]
| [
'E',
number,
{
message: string,
stack: string,
...
},
];
@@ -7,6 +7,8 @@
* @flow
*/
import type {RowEncoding, JSONValue} from './ReactFlightNativeRelayProtocol';
import type {Request, ReactModel} from 'react-server/src/ReactFlightServer';
import JSResourceReferenceImpl from 'JSResourceReferenceImpl';
@@ -22,9 +24,7 @@ import type {
import {resolveModelToJSON} from 'react-server/src/ReactFlightServer';
import {
emitModel,
emitModule,
emitError,
emitRow,
resolveModuleMetaData as resolveModuleMetaDataImpl,
} from 'ReactFlightNativeRelayServerIntegration';
@@ -45,34 +45,7 @@ export function resolveModuleMetaData<T>(
return resolveModuleMetaDataImpl(config, resource);
}
type JSONValue =
| string
| number
| boolean
| null
| {+[key: string]: JSONValue}
| Array<JSONValue>;
export type Chunk =
| {
type: 'json',
id: number,
json: JSONValue,
}
| {
type: 'module',
id: number,
json: ModuleMetaData,
}
| {
type: 'error',
id: number,
json: {
message: string,
stack: string,
...
},
};
export type Chunk = RowEncoding;
export function processErrorChunk(
request: Request,
@@ -80,14 +53,14 @@ export function processErrorChunk(
message: string,
stack: string,
): Chunk {
return {
type: 'error',
id: id,
json: {
return [
'E',
id,
{
message,
stack,
},
};
];
}
function convertModelToJSON(
@@ -126,11 +99,7 @@ export function processModelChunk(
model: ReactModel,
): Chunk {
const json = convertModelToJSON(request, {}, '', model);
return {
type: 'json',
id: id,
json: json,
};
return ['J', id, json];
}
export function processModuleChunk(
@@ -139,11 +108,7 @@ export function processModuleChunk(
moduleMetaData: ModuleMetaData,
): Chunk {
// The moduleMetaData is already a JSON serializable value.
return {
type: 'module',
id: id,
json: moduleMetaData,
};
return ['M', id, moduleMetaData];
}
export function scheduleWork(callback: () => void) {
@@ -155,13 +120,7 @@ export function flushBuffered(destination: Destination) {}
export function beginWriting(destination: Destination) {}
export function writeChunk(destination: Destination, chunk: Chunk): boolean {
if (chunk.type === 'json') {
emitModel(destination, chunk.id, chunk.json);
} else if (chunk.type === 'module') {
emitModule(destination, chunk.id, chunk.json);
} else {
emitError(destination, chunk.id, chunk.json.message, chunk.json.stack);
}
emitRow(destination, chunk);
return true;
}
@@ -8,26 +8,8 @@
'use strict';
const ReactFlightNativeRelayServerIntegration = {
emitModel(destination, id, json) {
destination.push({
type: 'json',
id: id,
json: json,
});
},
emitModule(destination, id, json) {
destination.push({
type: 'module',
id: id,
json: json,
});
},
emitError(destination, id, message, stack) {
destination.push({
type: 'error',
id: id,
json: {message, stack},
});
emitRow(destination, json) {
destination.push(json);
},
close(destination) {},
resolveModuleMetaData(config, resource) {
@@ -45,26 +45,7 @@ describe('ReactFlightNativeRelay', () => {
const response = ReactNativeFlightRelayClient.createResponse();
for (let i = 0; i < data.length; i++) {
const chunk = data[i];
if (chunk.type === 'json') {
ReactNativeFlightRelayClient.resolveModel(
response,
chunk.id,
chunk.json,
);
} else if (chunk.type === 'module') {
ReactNativeFlightRelayClient.resolveModule(
response,
chunk.id,
chunk.json,
);
} else {
ReactNativeFlightRelayClient.resolveError(
response,
chunk.id,
chunk.json.message,
chunk.json.stack,
);
}
ReactNativeFlightRelayClient.resolveRow(response, chunk);
}
ReactNativeFlightRelayClient.close(response);
const model = response.readRoot();
+2 -26
View File
@@ -35,22 +35,10 @@ declare module 'JSResourceReferenceImpl' {
declare module 'ReactFlightDOMRelayServerIntegration' {
declare export opaque type Destination;
declare export opaque type BundlerConfig;
declare export function emitModel(
declare export function emitRow(
destination: Destination,
id: number,
json: JSONValue,
): void;
declare export function emitModule(
destination: Destination,
id: number,
json: ModuleMetaData,
): void;
declare export function emitError(
destination: Destination,
id: number,
message: string,
stack: string,
): void;
declare export function close(destination: Destination): void;
declare export type ModuleMetaData = JSONValue;
@@ -76,22 +64,10 @@ declare module 'ReactFlightDOMRelayClientIntegration' {
declare module 'ReactFlightNativeRelayServerIntegration' {
declare export opaque type Destination;
declare export opaque type BundlerConfig;
declare export function emitModel(
declare export function emitRow(
destination: Destination,
id: number,
json: JSONValue,
): void;
declare export function emitModule(
destination: Destination,
id: number,
json: ModuleMetaData,
): void;
declare export function emitError(
destination: Destination,
id: number,
message: string,
stack: string,
): void;
declare export function close(destination: Destination): void;
declare export type ModuleMetaData = JSONValue;