( requestHeaders: Record<string, string> | undefined )
| 126 | } |
| 127 | |
| 128 | export function createDebugChannel( |
| 129 | requestHeaders: Record<string, string> | undefined |
| 130 | ): { |
| 131 | writable?: WritableStream |
| 132 | readable?: ReadableStream |
| 133 | } { |
| 134 | let requestId: string | undefined |
| 135 | |
| 136 | if (requestHeaders) { |
| 137 | requestId = requestHeaders[NEXT_REQUEST_ID_HEADER] ?? undefined |
| 138 | |
| 139 | if (!requestId) { |
| 140 | throw new InvariantError( |
| 141 | `Expected a ${JSON.stringify(NEXT_REQUEST_ID_HEADER)} request header.` |
| 142 | ) |
| 143 | } |
| 144 | } else { |
| 145 | requestId = self.__next_r |
| 146 | |
| 147 | if (!requestId) { |
| 148 | throw new InvariantError( |
| 149 | `Expected a request ID to be defined for the document via self.__next_r.` |
| 150 | ) |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | // Only attempt to restore the sessionStorage debug channel entry for the |
| 155 | // initial document load (no request headers). Client-side navigations pass |
| 156 | // request headers and should always use the WebSocket-backed debug channel. |
| 157 | if (!requestHeaders && wasServedFromCache()) { |
| 158 | const readable = restoreDebugChannelFromSessionStorage(requestId) |
| 159 | |
| 160 | if (readable) { |
| 161 | return { readable } |
| 162 | } |
| 163 | |
| 164 | // Debug channel can't be restored — debug deps would block hydration. |
| 165 | // Force a fresh page load from the server. Return a never-closing stream |
| 166 | // so the Flight client stays parked until the reload tears the document |
| 167 | // down, instead of synchronously erroring with "Connection closed.". |
| 168 | location.reload() |
| 169 | return { readable: new ReadableStream() } |
| 170 | } |
| 171 | |
| 172 | const { readable } = getOrCreateDebugChannelReadableWriterPair(requestId) |
| 173 | |
| 174 | return { readable } |
| 175 | } |
no test coverage detected