7
7
* @flow
8
8
*/
9
9
10
- import type { Source , StringDecoder } from './ReactFlightClientHostConfig' ;
11
-
12
- import {
13
- supportsBinaryStreams ,
14
- createStringDecoder ,
15
- readPartialStringChunk ,
16
- readFinalStringChunk ,
17
- } from './ReactFlightClientHostConfig' ;
10
+ import type { Source } from './ReactFlightClientHostConfig' ;
18
11
19
12
export type ReactModelRoot < T > = { |
20
13
model : T ,
21
14
| } ;
22
15
23
- type JSONValue =
16
+ export type JSONValue =
24
17
| number
25
18
| null
26
19
| boolean
27
20
| string
28
- | { [ key : string ] : JSONValue , ...} ;
21
+ | { [ key : string ] : JSONValue }
22
+ | Array < JSONValue > ;
29
23
30
24
const PENDING = 0 ;
31
25
const RESOLVED = 1 ;
@@ -48,39 +42,25 @@ type ErroredChunk = {|
48
42
| } ;
49
43
type Chunk = PendingChunk | ResolvedChunk | ErroredChunk ;
50
44
51
- type OpaqueResponseWithoutDecoder = {
45
+ export type Response = {
52
46
source : Source ,
53
47
partialRow : string ,
54
48
modelRoot : ReactModelRoot < any > ,
55
49
chunks : Map < number , Chunk> ,
56
- fromJSON : ( key : string , value : JSONValue ) => any ,
57
- ...
58
- } ;
59
-
60
- type OpaqueResponse = OpaqueResponseWithoutDecoder & {
61
- stringDecoder : StringDecoder ,
62
- ...
63
50
} ;
64
51
65
- export function createResponse ( source : Source ) : OpaqueResponse {
52
+ export function createResponse ( source : Source ) : Response {
66
53
let modelRoot : ReactModelRoot < any > = ( { } : any ) ;
67
54
let rootChunk : Chunk = createPendingChunk ( ) ;
68
55
definePendingProperty ( modelRoot , 'model' , rootChunk ) ;
69
56
let chunks : Map < number , Chunk > = new Map ( ) ;
70
57
chunks . set ( 0 , rootChunk ) ;
71
-
72
- let response : OpaqueResponse = ( ( {
58
+ let response = {
73
59
source,
74
60
partialRow : '' ,
75
61
modelRoot,
76
62
chunks : chunks ,
77
- fromJSON : function ( key , value ) {
78
- return parseFromJSON ( response , this , key , value ) ;
79
- } ,
80
- } : OpaqueResponseWithoutDecoder ) : any ) ;
81
- if ( supportsBinaryStreams ) {
82
- response . stringDecoder = createStringDecoder ( ) ;
83
- }
63
+ } ;
84
64
return response ;
85
65
}
86
66
@@ -138,10 +118,7 @@ function resolveChunk(chunk: Chunk, value: mixed): void {
138
118
139
119
// Report that any missing chunks in the model is now going to throw this
140
120
// error upon read. Also notify any pending promises.
141
- export function reportGlobalError (
142
- response : OpaqueResponse ,
143
- error : Error ,
144
- ) : void {
121
+ export function reportGlobalError ( response : Response , error : Error ) : void {
145
122
response . chunks . forEach ( chunk => {
146
123
// If this chunk was already resolved or errored, it won't
147
124
// trigger an error but if it wasn't then we need to
@@ -168,8 +145,8 @@ function definePendingProperty(
168
145
} ) ;
169
146
}
170
147
171
- function parseFromJSON (
172
- response : OpaqueResponse ,
148
+ export function parseModelFromJSON (
149
+ response : Response ,
173
150
targetObj : Object ,
174
151
key : string ,
175
152
value : JSONValue ,
@@ -195,12 +172,11 @@ function parseFromJSON(
195
172
return value ;
196
173
}
197
174
198
- function resolveJSONRow (
199
- response : OpaqueResponse ,
175
+ export function resolveModelChunk < T > (
176
+ response : Response ,
200
177
id : number ,
201
- json : string ,
178
+ model : T ,
202
179
) : void {
203
- let model = JSON . parse ( json , response . fromJSON ) ;
204
180
let chunks = response . chunks ;
205
181
let chunk = chunks . get ( id ) ;
206
182
if ( ! chunk ) {
@@ -210,88 +186,31 @@ function resolveJSONRow(
210
186
}
211
187
}
212
188
213
- function processFullRow ( response : OpaqueResponse , row : string ) : void {
214
- if ( row === '' ) {
215
- return ;
216
- }
217
- let tag = row [ 0 ] ;
218
- switch ( tag ) {
219
- case 'J' : {
220
- let colon = row . indexOf ( ':' , 1 ) ;
221
- let id = parseInt ( row . substring ( 1 , colon ) , 16 ) ;
222
- let json = row . substring ( colon + 1 ) ;
223
- resolveJSONRow ( response , id , json ) ;
224
- return ;
225
- }
226
- case 'E' : {
227
- let colon = row . indexOf ( ':' , 1 ) ;
228
- let id = parseInt ( row . substring ( 1 , colon ) , 16 ) ;
229
- let json = row . substring ( colon + 1 ) ;
230
- let errorInfo = JSON . parse ( json ) ;
231
- let error = new Error ( errorInfo . message ) ;
232
- error . stack = errorInfo . stack ;
233
- let chunks = response . chunks ;
234
- let chunk = chunks . get ( id ) ;
235
- if ( ! chunk ) {
236
- chunks . set ( id , createErrorChunk ( error ) ) ;
237
- } else {
238
- triggerErrorOnChunk ( chunk , error ) ;
239
- }
240
- return ;
241
- }
242
- default : {
243
- // Assume this is the root model.
244
- resolveJSONRow ( response , 0 , row ) ;
245
- return ;
246
- }
247
- }
248
- }
249
-
250
- export function processStringChunk (
251
- response : OpaqueResponse ,
252
- chunk : string ,
253
- offset : number ,
254
- ) : void {
255
- let linebreak = chunk . indexOf ( '\n' , offset ) ;
256
- while ( linebreak > - 1 ) {
257
- let fullrow = response . partialRow + chunk . substring ( offset , linebreak ) ;
258
- processFullRow ( response , fullrow ) ;
259
- response . partialRow = '' ;
260
- offset = linebreak + 1 ;
261
- linebreak = chunk . indexOf ( '\n' , offset ) ;
262
- }
263
- response . partialRow += chunk . substring ( offset ) ;
264
- }
265
-
266
- export function processBinaryChunk (
267
- response : OpaqueResponse ,
268
- chunk : Uint8Array ,
189
+ export function resolveErrorChunk (
190
+ response : Response ,
191
+ id : number ,
192
+ message : string ,
193
+ stack : string ,
269
194
) : void {
270
- if ( ! supportsBinaryStreams ) {
271
- throw new Error ( "This environment don't support binary chunks." ) ;
272
- }
273
- let stringDecoder = response . stringDecoder ;
274
- let linebreak = chunk . indexOf ( 10 ) ; // newline
275
- while ( linebreak > - 1 ) {
276
- let fullrow =
277
- response . partialRow +
278
- readFinalStringChunk ( stringDecoder , chunk . subarray ( 0 , linebreak ) ) ;
279
- processFullRow ( response , fullrow ) ;
280
- response . partialRow = '' ;
281
- chunk = chunk . subarray ( linebreak + 1 ) ;
282
- linebreak = chunk . indexOf ( 10 ) ; // newline
195
+ let error = new Error ( message ) ;
196
+ error . stack = stack ;
197
+ let chunks = response . chunks ;
198
+ let chunk = chunks . get ( id ) ;
199
+ if ( ! chunk ) {
200
+ chunks . set ( id , createErrorChunk ( error ) ) ;
201
+ } else {
202
+ triggerErrorOnChunk ( chunk , error ) ;
283
203
}
284
- response . partialRow += readPartialStringChunk ( stringDecoder , chunk ) ;
285
204
}
286
205
287
- export function complete ( response : OpaqueResponse ) : void {
206
+ export function complete ( response : Response ) : void {
288
207
// In case there are any remaining unresolved chunks, they won't
289
208
// be resolved now. So we need to issue an error to those.
290
209
// Ideally we should be able to early bail out if we kept a
291
210
// ref count of pending chunks.
292
211
reportGlobalError ( response , new Error ( 'Connection closed.' ) ) ;
293
212
}
294
213
295
- export function getModelRoot < T > ( response : OpaqueResponse ) : ReactModelRoot < T > {
214
+ export function getModelRoot < T > ( response : Response ) : ReactModelRoot < T > {
296
215
return response . modelRoot ;
297
216
}
0 commit comments