359
_stringDecoder: StringDecoder,
360
_closed: boolean,
361
_closedReason: mixed,
362
+ _allowPartialStream: boolean,
363
_tempRefs: void | TemporaryReferenceSet, // the set temporary references can be resolved from
364
_timeOrigin: number, // Profiling-only
365
_pendingInitialRender: null | TimeoutID, // Profiling-only,
1457
let chunk = chunks.get(id);
1458
if (!chunk) {
1459
if (response._closed) {
1459
- // We have already errored the response and we're not going to get
1460
- // anything more streaming in so this will immediately error.
1461
- chunk = createErrorChunk(response, response._closedReason);
1460
+ if (response._allowPartialStream) {
1461
+ // For partial streams, chunks accessed after close should be HALTED
1462
+ // (never resolve).
1463
+ chunk = createPendingChunk(response);
1464
+ const haltedChunk: HaltedChunk<any> = (chunk: any);
1465
+ haltedChunk.status = HALTED;
1466
+ haltedChunk.value = null;
1467
+ haltedChunk.reason = null;
1468
+ } else {
1469
+ // We have already errored the response and we're not going to get
1470
+ // anything more streaming in so this will immediately error.
1471
+ chunk = createErrorChunk(response, response._closedReason);
1472
+ }
1473
} else {
1474
chunk = createPendingChunk(response);
1475
}
2666
encodeFormAction: void | EncodeFormActionCallback,
2667
nonce: void | string,
2668
temporaryReferences: void | TemporaryReferenceSet,
2669
+ allowPartialStream: boolean,
2670
findSourceMapURL: void | FindSourceMapURLCallback, // DEV-only
2671
replayConsole: boolean, // DEV-only
2672
environmentName: void | string, // DEV-only
2686
this._fromJSON = (null: any);
2687
this._closed = false;
2688
this._closedReason = null;
2689
+ this._allowPartialStream = allowPartialStream;
2690
this._tempRefs = temporaryReferences;
2691
if (enableProfilerTimer && enableComponentPerformanceTrack) {
2692
this._timeOrigin = 0;
2780
encodeFormAction: void | EncodeFormActionCallback,
2781
nonce: void | string,
2782
temporaryReferences: void | TemporaryReferenceSet,
2783
+ allowPartialStream: boolean,
2784
findSourceMapURL: void | FindSourceMapURLCallback, // DEV-only
2785
replayConsole: boolean, // DEV-only
2786
environmentName: void | string, // DEV-only
2806
encodeFormAction,
2807
nonce,
2808
temporaryReferences,
2809
+ allowPartialStream,
2810
findSourceMapURL,
2811
replayConsole,
2812
environmentName,
5258
}
5259
5260
export function close(weakResponse: WeakResponse): void {
5246
- // In case there are any remaining unresolved chunks, they won't
5247
- // be resolved now. So we need to issue an error to those.
5248
- // Ideally we should be able to early bail out if we kept a
5249
- // ref count of pending chunks.
5250
- reportGlobalError(weakResponse, new Error('Connection closed.'));
5261
+ // In case there are any remaining unresolved chunks, they won't be resolved
5262
+ // now. So we either error or halt them depending on whether partial streams
5263
+ // are allowed.
5264
+ // TODO: Ideally we should be able to bail out early if we kept a ref count of
5265
+ // pending chunks.
5266
+ if (hasGCedResponse(weakResponse)) {
5267
+ return;
5268
+ }
5269
+ const response = unwrapWeakResponse(weakResponse);
5270
+ if (response._allowPartialStream) {
5271
+ // For partial streams, we halt pending chunks instead of erroring them.
5272
+ response._closed = true;
5273
+ response._chunks.forEach(chunk => {
5274
+ if (chunk.status === PENDING) {
5275
+ // Clear listeners to release closures and transition to HALTED.
5276
+ // Future .then() calls on HALTED chunks are no-ops.
5277
+ releasePendingChunk(response, chunk);
5278
+ const haltedChunk: HaltedChunk<any> = (chunk: any);
5279
+ haltedChunk.status = HALTED;
5280
+ haltedChunk.value = null;
5281
+ haltedChunk.reason = null;
5282
+ } else if (chunk.status === INITIALIZED && chunk.reason !== null) {
5283
+ // Stream chunk - close gracefully instead of erroring.
5284
+ chunk.reason.close('"$undefined"');
5285
+ }
5286
+ });
5287
+ if (__DEV__) {
5288
+ const debugChannel = response._debugChannel;
5289
+ if (debugChannel !== undefined) {
5290
+ closeDebugChannel(debugChannel);
5291
+ response._debugChannel = undefined;
5292
+ if (debugChannelRegistry !== null) {
5293
+ debugChannelRegistry.unregister(response);
5294
+ }
5295
+ }
5296
+ }
5297
+ } else {
5298
+ reportGlobalError(weakResponse, new Error('Connection closed.'));
5299
+ }
5300
}
5301
5302
function getCurrentOwnerInDEV(): null | ReactComponentInfo {