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' ;
18
-
19
10
export type ReactModelRoot < T > = { |
20
11
model : T ,
21
12
| } ;
22
13
23
- type JSONValue =
14
+ export type JSONValue =
24
15
| number
25
16
| null
26
17
| boolean
27
18
| string
28
- | { [ key : string ] : JSONValue , ...} ;
19
+ | { [ key : string ] : JSONValue }
20
+ | Array < JSONValue > ;
29
21
30
22
const PENDING = 0 ;
31
23
const RESOLVED = 1 ;
@@ -48,39 +40,23 @@ type ErroredChunk = {|
48
40
| } ;
49
41
type Chunk = PendingChunk | ResolvedChunk | ErroredChunk ;
50
42
51
- type OpaqueResponseWithoutDecoder = {
52
- source : Source ,
43
+ export type Response = {
53
44
partialRow : string ,
54
45
modelRoot : ReactModelRoot < any > ,
55
46
chunks : Map < number , Chunk> ,
56
- fromJSON : ( key : string , value : JSONValue ) => any ,
57
- ...
58
47
} ;
59
48
60
- type OpaqueResponse = OpaqueResponseWithoutDecoder & {
61
- stringDecoder : StringDecoder ,
62
- ...
63
- } ;
64
-
65
- export function createResponse ( source : Source ) : OpaqueResponse {
49
+ export function createResponse ( ) : Response {
66
50
let modelRoot : ReactModelRoot < any > = ( { } : any ) ;
67
51
let rootChunk : Chunk = createPendingChunk ( ) ;
68
52
definePendingProperty ( modelRoot , 'model' , rootChunk ) ;
69
53
let chunks : Map < number , Chunk > = new Map ( ) ;
70
54
chunks . set ( 0 , rootChunk ) ;
71
-
72
- let response : OpaqueResponse = ( ( {
73
- source,
55
+ let response = {
74
56
partialRow : '' ,
75
57
modelRoot,
76
58
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
- }
59
+ } ;
84
60
return response ;
85
61
}
86
62
@@ -138,10 +114,7 @@ function resolveChunk(chunk: Chunk, value: mixed): void {
138
114
139
115
// Report that any missing chunks in the model is now going to throw this
140
116
// error upon read. Also notify any pending promises.
141
- export function reportGlobalError (
142
- response : OpaqueResponse ,
143
- error : Error ,
144
- ) : void {
117
+ export function reportGlobalError ( response : Response , error : Error ) : void {
145
118
response . chunks . forEach ( chunk => {
146
119
// If this chunk was already resolved or errored, it won't
147
120
// trigger an error but if it wasn't then we need to
@@ -168,8 +141,8 @@ function definePendingProperty(
168
141
} ) ;
169
142
}
170
143
171
- function parseFromJSON (
172
- response : OpaqueResponse ,
144
+ export function parseModelFromJSON (
145
+ response : Response ,
173
146
targetObj : Object ,
174
147
key : string ,
175
148
value : JSONValue ,
@@ -195,12 +168,11 @@ function parseFromJSON(
195
168
return value ;
196
169
}
197
170
198
- function resolveJSONRow (
199
- response : OpaqueResponse ,
171
+ export function resolveModelChunk < T > (
172
+ response : Response ,
200
173
id : number ,
201
- json : string ,
174
+ model : T ,
202
175
) : void {
203
- let model = JSON . parse ( json , response . fromJSON ) ;
204
176
let chunks = response . chunks ;
205
177
let chunk = chunks . get ( id ) ;
206
178
if ( ! chunk ) {
@@ -210,88 +182,31 @@ function resolveJSONRow(
210
182
}
211
183
}
212
184
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 ,
185
+ export function resolveErrorChunk (
186
+ response : Response ,
187
+ id : number ,
188
+ message : string ,
189
+ stack : string ,
269
190
) : 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
191
+ let error = new Error ( message ) ;
192
+ error . stack = stack ;
193
+ let chunks = response . chunks ;
194
+ let chunk = chunks . get ( id ) ;
195
+ if ( ! chunk ) {
196
+ chunks . set ( id , createErrorChunk ( error ) ) ;
197
+ } else {
198
+ triggerErrorOnChunk ( chunk , error ) ;
283
199
}
284
- response . partialRow += readPartialStringChunk ( stringDecoder , chunk ) ;
285
200
}
286
201
287
- export function complete ( response : OpaqueResponse ) : void {
202
+ export function close ( response : Response ) : void {
288
203
// In case there are any remaining unresolved chunks, they won't
289
204
// be resolved now. So we need to issue an error to those.
290
205
// Ideally we should be able to early bail out if we kept a
291
206
// ref count of pending chunks.
292
207
reportGlobalError ( response , new Error ( 'Connection closed.' ) ) ;
293
208
}
294
209
295
- export function getModelRoot < T > ( response : OpaqueResponse ) : ReactModelRoot < T > {
210
+ export function getModelRoot < T > ( response : Response ) : ReactModelRoot < T > {
296
211
return response . modelRoot ;
297
212
}
0 commit comments