Skip to content

Commit 35e53b4

Browse files
authored
[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.
1 parent 16e6dad commit 35e53b4

13 files changed

+132
-208
lines changed

packages/react-transport-dom-relay/src/ReactFlightDOMRelayClient.js

+18-1
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,27 @@
77
* @flow
88
*/
99

10-
export {
10+
import type {RowEncoding} from './ReactFlightDOMRelayProtocol';
11+
12+
import type {Response} from 'react-client/src/ReactFlightClient';
13+
14+
import {
1115
createResponse,
1216
resolveModel,
1317
resolveModule,
1418
resolveError,
1519
close,
1620
} from 'react-client/src/ReactFlightClient';
21+
22+
export {createResponse, close};
23+
24+
export function resolveRow(response: Response, chunk: RowEncoding): void {
25+
if (chunk[0] === 'J') {
26+
resolveModel(response, chunk[1], chunk[2]);
27+
} else if (chunk[0] === 'M') {
28+
resolveModule(response, chunk[1], chunk[2]);
29+
} else {
30+
// $FlowFixMe: Flow doesn't support disjoint unions on tuples.
31+
resolveError(response, chunk[1], chunk[2].message, chunk[2].stack);
32+
}
33+
}

packages/react-transport-dom-relay/src/ReactFlightDOMRelayClientHostConfig.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export {
2626

2727
export type {ModuleMetaData} from 'ReactFlightDOMRelayClientIntegration';
2828

29-
export opaque type UninitializedModel = JSONValue;
29+
export type UninitializedModel = JSONValue;
3030

3131
export type Response = ResponseBase;
3232

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow
8+
*/
9+
10+
import type {ModuleMetaData} from 'ReactFlightDOMRelayServerIntegration';
11+
12+
export type JSONValue =
13+
| string
14+
| number
15+
| boolean
16+
| null
17+
| {+[key: string]: JSONValue}
18+
| Array<JSONValue>;
19+
20+
export type RowEncoding =
21+
| ['J', number, JSONValue]
22+
| ['M', number, ModuleMetaData]
23+
| [
24+
'E',
25+
number,
26+
{
27+
message: string,
28+
stack: string,
29+
...
30+
},
31+
];

packages/react-transport-dom-relay/src/ReactFlightDOMRelayServerHostConfig.js

+12-53
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
* @flow
88
*/
99

10+
import type {RowEncoding, JSONValue} from './ReactFlightDOMRelayProtocol';
11+
1012
import type {Request, ReactModel} from 'react-server/src/ReactFlightServer';
1113

1214
import JSResourceReference from 'JSResourceReference';
@@ -22,9 +24,7 @@ import type {
2224
import {resolveModelToJSON} from 'react-server/src/ReactFlightServer';
2325

2426
import {
25-
emitModel,
26-
emitModule,
27-
emitError,
27+
emitRow,
2828
resolveModuleMetaData as resolveModuleMetaDataImpl,
2929
} from 'ReactFlightDOMRelayServerIntegration';
3030

@@ -45,49 +45,22 @@ export function resolveModuleMetaData<T>(
4545
return resolveModuleMetaDataImpl(config, resource);
4646
}
4747

48-
type JSONValue =
49-
| string
50-
| number
51-
| boolean
52-
| null
53-
| {+[key: string]: JSONValue}
54-
| Array<JSONValue>;
55-
56-
export type Chunk =
57-
| {
58-
type: 'json',
59-
id: number,
60-
json: JSONValue,
61-
}
62-
| {
63-
type: 'module',
64-
id: number,
65-
json: ModuleMetaData,
66-
}
67-
| {
68-
type: 'error',
69-
id: number,
70-
json: {
71-
message: string,
72-
stack: string,
73-
...
74-
},
75-
};
48+
export type Chunk = RowEncoding;
7649

7750
export function processErrorChunk(
7851
request: Request,
7952
id: number,
8053
message: string,
8154
stack: string,
8255
): Chunk {
83-
return {
84-
type: 'error',
85-
id: id,
86-
json: {
56+
return [
57+
'E',
58+
id,
59+
{
8760
message,
8861
stack,
8962
},
90-
};
63+
];
9164
}
9265

9366
function convertModelToJSON(
@@ -126,11 +99,7 @@ export function processModelChunk(
12699
model: ReactModel,
127100
): Chunk {
128101
const json = convertModelToJSON(request, {}, '', model);
129-
return {
130-
type: 'json',
131-
id: id,
132-
json: json,
133-
};
102+
return ['J', id, json];
134103
}
135104

136105
export function processModuleChunk(
@@ -139,11 +108,7 @@ export function processModuleChunk(
139108
moduleMetaData: ModuleMetaData,
140109
): Chunk {
141110
// The moduleMetaData is already a JSON serializable value.
142-
return {
143-
type: 'module',
144-
id: id,
145-
json: moduleMetaData,
146-
};
111+
return ['M', id, moduleMetaData];
147112
}
148113

149114
export function scheduleWork(callback: () => void) {
@@ -155,13 +120,7 @@ export function flushBuffered(destination: Destination) {}
155120
export function beginWriting(destination: Destination) {}
156121

157122
export function writeChunk(destination: Destination, chunk: Chunk): boolean {
158-
if (chunk.type === 'json') {
159-
emitModel(destination, chunk.id, chunk.json);
160-
} else if (chunk.type === 'module') {
161-
emitModule(destination, chunk.id, chunk.json);
162-
} else {
163-
emitError(destination, chunk.id, chunk.json.message, chunk.json.stack);
164-
}
123+
emitRow(destination, chunk);
165124
return true;
166125
}
167126

packages/react-transport-dom-relay/src/__mocks__/ReactFlightDOMRelayServerIntegration.js

+2-20
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,8 @@
88
'use strict';
99

1010
const ReactFlightDOMRelayServerIntegration = {
11-
emitModel(destination, id, json) {
12-
destination.push({
13-
type: 'json',
14-
id: id,
15-
json: json,
16-
});
17-
},
18-
emitModule(destination, id, json) {
19-
destination.push({
20-
type: 'module',
21-
id: id,
22-
json: json,
23-
});
24-
},
25-
emitError(destination, id, message, stack) {
26-
destination.push({
27-
type: 'error',
28-
id: id,
29-
json: {message, stack},
30-
});
11+
emitRow(destination, json) {
12+
destination.push(json);
3113
},
3214
close(destination) {},
3315
resolveModuleMetaData(config, resource) {

packages/react-transport-dom-relay/src/__tests__/ReactFlightDOMRelay-test.internal.js

+1-12
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,7 @@ describe('ReactFlightDOMRelay', () => {
3030
const response = ReactDOMFlightRelayClient.createResponse();
3131
for (let i = 0; i < data.length; i++) {
3232
const chunk = data[i];
33-
if (chunk.type === 'json') {
34-
ReactDOMFlightRelayClient.resolveModel(response, chunk.id, chunk.json);
35-
} else if (chunk.type === 'module') {
36-
ReactDOMFlightRelayClient.resolveModule(response, chunk.id, chunk.json);
37-
} else {
38-
ReactDOMFlightRelayClient.resolveError(
39-
response,
40-
chunk.id,
41-
chunk.json.message,
42-
chunk.json.stack,
43-
);
44-
}
33+
ReactDOMFlightRelayClient.resolveRow(response, chunk);
4534
}
4635
ReactDOMFlightRelayClient.close(response);
4736
const model = response.readRoot();

packages/react-transport-native-relay/src/ReactFlightNativeRelayClient.js

+18-1
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,27 @@
77
* @flow
88
*/
99

10-
export {
10+
import type {RowEncoding} from './ReactFlightNativeRelayProtocol';
11+
12+
import type {Response} from 'react-client/src/ReactFlightClient';
13+
14+
import {
1115
createResponse,
1216
resolveModel,
1317
resolveModule,
1418
resolveError,
1519
close,
1620
} from 'react-client/src/ReactFlightClient';
21+
22+
export {createResponse, close};
23+
24+
export function resolveRow(response: Response, chunk: RowEncoding): void {
25+
if (chunk[0] === 'J') {
26+
resolveModel(response, chunk[1], chunk[2]);
27+
} else if (chunk[0] === 'M') {
28+
resolveModule(response, chunk[1], chunk[2]);
29+
} else {
30+
// $FlowFixMe: Flow doesn't support disjoint unions on tuples.
31+
resolveError(response, chunk[1], chunk[2].message, chunk[2].stack);
32+
}
33+
}

packages/react-transport-native-relay/src/ReactFlightNativeRelayClientHostConfig.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export {
2626

2727
export type {ModuleMetaData} from 'ReactFlightNativeRelayClientIntegration';
2828

29-
export opaque type UninitializedModel = JSONValue;
29+
export type UninitializedModel = JSONValue;
3030

3131
export type Response = ResponseBase;
3232

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow
8+
*/
9+
10+
import type {ModuleMetaData} from 'ReactFlightNativeRelayServerIntegration';
11+
12+
export type JSONValue =
13+
| string
14+
| number
15+
| boolean
16+
| null
17+
| {+[key: string]: JSONValue}
18+
| Array<JSONValue>;
19+
20+
export type RowEncoding =
21+
| ['J', number, JSONValue]
22+
| ['M', number, ModuleMetaData]
23+
| [
24+
'E',
25+
number,
26+
{
27+
message: string,
28+
stack: string,
29+
...
30+
},
31+
];

0 commit comments

Comments
 (0)