77 * @flow
88 */
99
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' ;
1811
1912export type ReactModelRoot < T > = { |
2013 model : T ,
2114| } ;
2215
23- type JSONValue =
16+ export type JSONValue =
2417 | number
2518 | null
2619 | boolean
2720 | string
28- | { [ key : string ] : JSONValue , ...} ;
21+ | { [ key : string ] : JSONValue }
22+ | Array < JSONValue > ;
2923
3024const PENDING = 0 ;
3125const RESOLVED = 1 ;
@@ -48,39 +42,25 @@ type ErroredChunk = {|
4842| } ;
4943type Chunk = PendingChunk | ResolvedChunk | ErroredChunk ;
5044
51- type OpaqueResponseWithoutDecoder = {
45+ export type Response = {
5246 source : Source ,
5347 partialRow : string ,
5448 modelRoot : ReactModelRoot < any > ,
5549 chunks : Map < number , Chunk> ,
56- fromJSON : ( key : string , value : JSONValue ) => any ,
57- ...
58- } ;
59-
60- type OpaqueResponse = OpaqueResponseWithoutDecoder & {
61- stringDecoder : StringDecoder ,
62- ...
6350} ;
6451
65- export function createResponse ( source : Source ) : OpaqueResponse {
52+ export function createResponse ( source : Source ) : Response {
6653 let modelRoot : ReactModelRoot < any > = ( { } : any ) ;
6754 let rootChunk : Chunk = createPendingChunk ( ) ;
6855 definePendingProperty ( modelRoot , 'model' , rootChunk ) ;
6956 let chunks : Map < number , Chunk > = new Map ( ) ;
7057 chunks . set ( 0 , rootChunk ) ;
71-
72- let response : OpaqueResponse = ( ( {
58+ let response = {
7359 source,
7460 partialRow : '' ,
7561 modelRoot,
7662 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+ } ;
8464 return response ;
8565}
8666
@@ -138,10 +118,7 @@ function resolveChunk(chunk: Chunk, value: mixed): void {
138118
139119// Report that any missing chunks in the model is now going to throw this
140120// 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 {
145122 response . chunks . forEach ( chunk => {
146123 // If this chunk was already resolved or errored, it won't
147124 // trigger an error but if it wasn't then we need to
@@ -168,8 +145,8 @@ function definePendingProperty(
168145 } ) ;
169146}
170147
171- function parseFromJSON (
172- response : OpaqueResponse ,
148+ export function parseModelFromJSON (
149+ response : Response ,
173150 targetObj : Object ,
174151 key : string ,
175152 value : JSONValue ,
@@ -195,12 +172,11 @@ function parseFromJSON(
195172 return value ;
196173}
197174
198- function resolveJSONRow (
199- response : OpaqueResponse ,
175+ export function resolveModelChunk < T > (
176+ response : Response ,
200177 id : number ,
201- json : string ,
178+ model : T ,
202179) : void {
203- let model = JSON . parse ( json , response . fromJSON ) ;
204180 let chunks = response . chunks ;
205181 let chunk = chunks . get ( id ) ;
206182 if ( ! chunk ) {
@@ -210,88 +186,31 @@ function resolveJSONRow(
210186 }
211187}
212188
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 ,
269194) : 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 ) ;
283203 }
284- response . partialRow += readPartialStringChunk ( stringDecoder , chunk ) ;
285204}
286205
287- export function complete ( response : OpaqueResponse ) : void {
206+ export function complete ( response : Response ) : void {
288207 // In case there are any remaining unresolved chunks, they won't
289208 // be resolved now. So we need to issue an error to those.
290209 // Ideally we should be able to early bail out if we kept a
291210 // ref count of pending chunks.
292211 reportGlobalError ( response , new Error ( 'Connection closed.' ) ) ;
293212}
294213
295- export function getModelRoot < T > ( response : OpaqueResponse ) : ReactModelRoot < T > {
214+ export function getModelRoot < T > ( response : Response ) : ReactModelRoot < T > {
296215 return response . modelRoot ;
297216}
0 commit comments