@@ -179,7 +179,7 @@ export type Response = {
179
179
_rowID : number , // parts of a row ID parsed so far
180
180
_rowTag : number , // 0 indicates that we're currently parsing the row ID
181
181
_rowLength : number , // remaining bytes in the row. 0 indicates that we're looking for a newline.
182
- _buffer : Array < string | Uint8Array > , // chunks received so far as part of this row
182
+ _buffer : Array < Uint8Array > , // chunks received so far as part of this row
183
183
} ;
184
184
185
185
function readChunk < T > (chunk: SomeChunk< T > ): T {
@@ -288,6 +288,14 @@ function createResolvedModuleChunk<T>(
288
288
return new Chunk ( RESOLVED_MODULE , value , null , response ) ;
289
289
}
290
290
291
+ function createInitializedTextChunk(
292
+ response: Response,
293
+ value: string,
294
+ ): InitializedChunk< string > {
295
+ // $FlowFixMe[invalid-constructor] Flow doesn't support functions as constructors
296
+ return new Chunk ( INITIALIZED , value , null , response ) ;
297
+ }
298
+
291
299
function resolveModelChunk< T > (
292
300
chunk: SomeChunk< T > ,
293
301
value: UninitializedModel,
@@ -704,6 +712,13 @@ function resolveModel(
704
712
}
705
713
}
706
714
715
+ function resolveText ( response : Response , id : number , text : string ) : void {
716
+ const chunks = response . _chunks ;
717
+ // We assume that we always reference large strings after they've been
718
+ // emitted.
719
+ chunks . set ( id , createInitializedTextChunk ( response , text ) ) ;
720
+ }
721
+
707
722
function resolveModule (
708
723
response : Response ,
709
724
id : number ,
@@ -818,26 +833,22 @@ function resolveHint(
818
833
code : string ,
819
834
model : UninitializedModel ,
820
835
) : void {
821
- const hintModel = parseModel < HintModel > ( response , model ) ;
836
+ const hintModel : HintModel = parseModel ( response , model ) ;
822
837
dispatchHint ( code , hintModel ) ;
823
838
}
824
839
825
840
function processFullRow (
826
841
response : Response ,
827
842
id : number ,
828
843
tag : number ,
829
- buffer : Array < string | Uint8Array > ,
844
+ buffer : Array < Uint8Array > ,
830
845
lastChunk : string | Uint8Array ,
831
846
) : void {
832
847
let row = '';
833
848
const stringDecoder = response . _stringDecoder ;
834
849
for ( let i = 0 ; i < buffer . length ; i ++ ) {
835
850
const chunk = buffer [ i ] ;
836
- if ( typeof chunk === 'string' ) {
837
- row += chunk ;
838
- } else {
839
- row + = readPartialStringChunk ( stringDecoder , chunk ) ;
840
- }
851
+ row += readPartialStringChunk ( stringDecoder , chunk ) ;
841
852
}
842
853
if ( typeof lastChunk === 'string' ) {
843
854
row += lastChunk ;
@@ -869,6 +880,10 @@ function processFullRow(
869
880
}
870
881
return ;
871
882
}
883
+ case 84 /* "T" */ : {
884
+ resolveText ( response , id , row ) ;
885
+ return ;
886
+ }
872
887
default : {
873
888
// We assume anything else is JSON.
874
889
resolveModel ( response , id , row ) ;
@@ -882,33 +897,50 @@ export function processBinaryChunk(
882
897
chunk : Uint8Array ,
883
898
) : void {
884
899
let i = 0 ;
885
- while ( i < chunk . length ) {
900
+ let rowState = response . _rowState ;
901
+ let rowID = response . _rowID ;
902
+ let rowTag = response . _rowTag ;
903
+ let rowLength = response . _rowLength ;
904
+ const buffer = response . _buffer ;
905
+ const chunkLength = chunk . length ;
906
+ while ( i < chunkLength ) {
886
907
let lastIdx = - 1 ;
887
- switch ( response . _rowState ) {
908
+ switch ( rowState ) {
888
909
case ROW_ID : {
889
910
const byte = chunk [ i ++ ] ;
890
911
if ( byte === 58 /* ":" */ ) {
891
912
// Finished the rowID, next we'll parse the tag.
892
- response . _rowState = ROW_TAG ;
913
+ rowState = ROW_TAG ;
893
914
} else {
894
- response . _rowID =
895
- ( response . _rowID << 4 ) | ( byte > 96 ? byte - 87 : byte - 48 ) ;
915
+ rowID = ( rowID << 4 ) | ( byte > 96 ? byte - 87 : byte - 48 ) ;
896
916
}
897
917
continue ;
898
918
}
899
919
case ROW_TAG : {
900
920
const resolvedRowTag = chunk [ i ] ;
901
- if ( resolvedRowTag > 64 && resolvedRowTag < 91 ) {
902
- response . _rowTag = resolvedRowTag ;
921
+ if ( resolvedRowTag === 84 /* "T" */ ) {
922
+ rowTag = resolvedRowTag ;
923
+ rowState = ROW_LENGTH ;
924
+ i ++ ;
925
+ } else if ( resolvedRowTag > 64 && resolvedRowTag < 91 /* "A"-"Z" */ ) {
926
+ rowTag = resolvedRowTag ;
927
+ rowState = ROW_CHUNK_BY_NEWLINE ;
903
928
i ++ ;
904
929
} else {
930
+ rowTag = 0 ;
931
+ rowState = ROW_CHUNK_BY_NEWLINE ;
905
932
// This was an unknown tag so it was probably part of the data.
906
933
}
907
- response . _rowState = ROW_CHUNK_BY_NEWLINE ;
908
934
continue ;
909
935
}
910
936
case ROW_LENGTH : {
911
- // TODO
937
+ const byte = chunk [ i ++ ] ;
938
+ if ( byte === 44 /* "," */ ) {
939
+ // Finished the rowLength, next we'll buffer up to that length.
940
+ rowState = ROW_CHUNK_BY_LENGTH ;
941
+ } else {
942
+ rowLength = ( rowLength << 4 ) | ( byte > 96 ? byte - 87 : byte - 48 ) ;
943
+ }
912
944
continue ;
913
945
}
914
946
case ROW_CHUNK_BY_NEWLINE : {
@@ -918,7 +950,6 @@ export function processBinaryChunk(
918
950
}
919
951
case ROW_CHUNK_BY_LENGTH : {
920
952
// We're looking for the remaining byte length
921
- const rowLength = response . _rowLength ;
922
953
if ( i + rowLength <= chunk . length ) {
923
954
lastIdx = i + rowLength ;
924
955
}
@@ -927,31 +958,34 @@ export function processBinaryChunk(
927
958
}
928
959
if ( lastIdx > - 1 ) {
929
960
// We found the last chunk of the row
930
- const lastChunk = chunk . slice ( i , lastIdx ) ;
931
- processFullRow (
932
- response ,
933
- response . _rowID ,
934
- response . _rowTag ,
935
- response . _buffer ,
936
- lastChunk ,
937
- ) ;
961
+ const offset = chunk . byteOffset + i ;
962
+ const length = lastIdx - i ;
963
+ const lastChunk = new Uint8Array ( chunk . buffer , offset , length ) ;
964
+ processFullRow ( response , rowID , rowTag , buffer , lastChunk ) ;
938
965
// Reset state machine for a new row
939
- response . _rowState = ROW_ID ;
940
- response . _rowTag = 0 ;
941
- response . _rowID = 0 ;
942
- response . _rowLength = 0 ;
943
- response . _buffer . length = 0 ;
966
+ rowState = ROW_ID ;
967
+ rowTag = 0 ;
968
+ rowID = 0 ;
969
+ rowLength = 0 ;
970
+ buffer . length = 0 ;
944
971
i = lastIdx + 1 ;
945
972
} else {
946
973
// The rest of this row is in a future chunk. We stash the rest of the
947
974
// current chunk until we can process the full row.
948
- const remainingSlice = chunk . slice ( i ) ;
949
- response . _buffer . push ( remainingSlice ) ;
950
- // Update how many bytes we're still waiting for.
951
- response . _rowLength -= remainingSlice . length ;
975
+ const offset = chunk . byteOffset + i ;
976
+ const length = chunk . byteLength - i ;
977
+ const remainingSlice = new Uint8Array ( chunk . buffer , offset , length ) ;
978
+ buffer . push ( remainingSlice ) ;
979
+ // Update how many bytes we're still waiting for. If we're looking for
980
+ // a newline, this doesn't hurt since we'll just ignore it.
981
+ rowLength -= remainingSlice . byteLength ;
952
982
break ;
953
983
}
954
984
}
985
+ response . _rowState = rowState ;
986
+ response . _rowID = rowID ;
987
+ response . _rowTag = rowTag ;
988
+ response . _rowLength = rowLength ;
955
989
}
956
990
957
991
function parseModel < T > (response: Response, json: UninitializedModel): T {
0 commit comments