@@ -155,6 +155,7 @@ const RESOLVED_MODEL = 'resolved_model';
155155const RESOLVED_MODULE = 'resolved_module' ;
156156const INITIALIZED = 'fulfilled' ;
157157const ERRORED = 'rejected' ;
158+ const HALTED = 'halted' ; // DEV-only. Means it never resolves even if connection closes.
158159
159160type PendingChunk < T > = {
160161 status : 'pending' ,
@@ -221,13 +222,23 @@ type ErroredChunk<T> = {
221222 _debugInfo ?: null | ReactDebugInfo , // DEV-only
222223 then ( resolve : ( T ) => mixed , reject ?: ( mixed ) => mixed ) : void ,
223224} ;
225+ type HaltedChunk < T > = {
226+ status : 'halted' ,
227+ value : null ,
228+ reason : null ,
229+ _response : Response ,
230+ _children : Array < SomeChunk < any >> | ProfilingResult , // Profiling-only
231+ _debugInfo ?: null | ReactDebugInfo , // DEV-only
232+ then ( resolve : ( T ) => mixed , reject ?: ( mixed ) => mixed ) : void ,
233+ } ;
224234type SomeChunk < T > =
225235 | PendingChunk < T >
226236 | BlockedChunk < T >
227237 | ResolvedModelChunk < T >
228238 | ResolvedModuleChunk < T >
229239 | InitializedChunk < T >
230- | ErroredChunk < T > ;
240+ | ErroredChunk < T >
241+ | HaltedChunk < T > ;
231242
232243// $FlowFixMe[missing-this-annot]
233244function ReactPromise (
@@ -311,6 +322,9 @@ ReactPromise.prototype.then = function <T>(
311322 chunk . reason . push ( reject ) ;
312323 }
313324 break ;
325+ case HALTED : {
326+ break ;
327+ }
314328 default :
315329 if ( reject ) {
316330 reject ( chunk . reason ) ;
@@ -368,6 +382,7 @@ function readChunk<T>(chunk: SomeChunk<T>): T {
368382 return chunk . value ;
369383 case PENDING :
370384 case BLOCKED :
385+ case HALTED :
371386 // eslint-disable-next-line no-throw-literal
372387 throw ( ( chunk : any ) : Thenable < T > ) ;
373388 default :
@@ -1367,6 +1382,7 @@ function getOutlinedModel<T>(
13671382 return chunkValue ;
13681383 case PENDING :
13691384 case BLOCKED :
1385+ case HALTED :
13701386 return waitForReference ( chunk , parentObject, key, response, map, path ) ;
13711387 default :
13721388 // This is an error. Instead of erroring directly, we're going to encode this on
@@ -1470,10 +1486,6 @@ function parseModelString(
14701486 }
14711487 case '@': {
14721488 // Promise
1473- if ( value . length === 2 ) {
1474- // Infinite promise that never resolves.
1475- return new Promise ( ( ) => { } ) ;
1476- }
14771489 const id = parseInt ( value . slice ( 2 ) , 16 ) ;
14781490 const chunk = getChunk ( response , id ) ;
14791491 if ( enableProfilerTimer && enableComponentPerformanceTrack ) {
@@ -1769,6 +1781,22 @@ export function createResponse(
17691781 ) ;
17701782}
17711783
1784+ function resolveDebugHalt ( response : Response , id : number ) : void {
1785+ const chunks = response . _chunks ;
1786+ let chunk = chunks . get ( id ) ;
1787+ if ( ! chunk ) {
1788+ chunks . set ( id , ( chunk = createPendingChunk ( response ) ) ) ;
1789+ } else {
1790+ }
1791+ if ( chunk . status !== PENDING && chunk . status !== BLOCKED ) {
1792+ return ;
1793+ }
1794+ const haltedChunk : HaltedChunk < any > = ( chunk : any ) ;
1795+ haltedChunk . status = HALTED ;
1796+ haltedChunk . value = null ;
1797+ haltedChunk . reason = null ;
1798+ }
1799+
17721800function resolveModel (
17731801 response : Response ,
17741802 id : number ,
@@ -3337,6 +3365,10 @@ function processFullStringRow(
33373365 }
33383366 // Fallthrough
33393367 default : /* """ "{" "[" "t" "f" "n" "0" - "9" */ {
3368+ if ( __DEV__ && row === '' ) {
3369+ resolveDebugHalt ( response , id ) ;
3370+ return ;
3371+ }
33403372 // We assume anything else is JSON.
33413373 resolveModel ( response , id , row ) ;
33423374 return ;
0 commit comments