( request: Request, task: Task, stream: ReadableStream, )
| 1082 | } |
| 1083 | |
| 1084 | function serializeReadableStream( |
| 1085 | request: Request, |
| 1086 | task: Task, |
| 1087 | stream: ReadableStream, |
| 1088 | ): string { |
| 1089 | // Detect if this is a BYOB stream. BYOB streams should be able to be read as bytes on the |
| 1090 | // receiving side. It also implies that different chunks can be split up or merged as opposed |
| 1091 | // to a readable stream that happens to have Uint8Array as the type which might expect it to be |
| 1092 | // received in the same slices. |
| 1093 | // $FlowFixMe: This is a Node.js extension. |
| 1094 | let supportsBYOB: void | boolean = stream.supportsBYOB; |
| 1095 | if (supportsBYOB === undefined) { |
| 1096 | try { |
| 1097 | // $FlowFixMe[extra-arg]: This argument is accepted. |
| 1098 | stream.getReader({mode: 'byob'}).releaseLock(); |
| 1099 | supportsBYOB = true; |
| 1100 | } catch (x) { |
| 1101 | supportsBYOB = false; |
| 1102 | } |
| 1103 | } |
| 1104 | |
| 1105 | const reader = stream.getReader(); |
| 1106 | |
| 1107 | // This task won't actually be retried. We just use it to attempt synchronous renders. |
| 1108 | const streamTask = createTask( |
| 1109 | request, |
| 1110 | task.model, |
| 1111 | task.keyPath, |
| 1112 | task.implicitSlot, |
| 1113 | task.formatContext, |
| 1114 | request.abortableTasks, |
| 1115 | enableProfilerTimer && |
| 1116 | (enableComponentPerformanceTrack || enableAsyncDebugInfo) |
| 1117 | ? task.time |
| 1118 | : 0, |
| 1119 | __DEV__ ? task.debugOwner : null, |
| 1120 | __DEV__ ? task.debugStack : null, |
| 1121 | __DEV__ ? task.debugTask : null, |
| 1122 | ); |
| 1123 | |
| 1124 | // The task represents the Stop row. This adds a Start row. |
| 1125 | request.pendingChunks++; |
| 1126 | const startStreamRow = |
| 1127 | streamTask.id.toString(16) + ':' + (supportsBYOB ? 'r' : 'R') + '\n'; |
| 1128 | request.completedRegularChunks.push(stringToChunk(startStreamRow)); |
| 1129 | |
| 1130 | function progress(entry: {done: boolean, value: ReactClientValue, ...}) { |
| 1131 | if (streamTask.status !== PENDING) { |
| 1132 | return; |
| 1133 | } |
| 1134 | |
| 1135 | if (entry.done) { |
| 1136 | streamTask.status = COMPLETED; |
| 1137 | const endStreamRow = streamTask.id.toString(16) + ':C\n'; |
| 1138 | request.completedRegularChunks.push(stringToChunk(endStreamRow)); |
| 1139 | request.abortableTasks.delete(streamTask); |
| 1140 | request.cacheController.signal.removeEventListener('abort', abortStream); |
| 1141 | enqueueFlush(request); |
no test coverage detected