From 3b201ddfb7c52a46a92ad98c0082409561871501 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Sat, 27 Aug 2022 18:19:49 -0400 Subject: [PATCH 1/2] Fix error handling when the Flight client itself errors --- .../src/ReactFlightDOMClient.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/react-server-dom-webpack/src/ReactFlightDOMClient.js b/packages/react-server-dom-webpack/src/ReactFlightDOMClient.js index d8b5def41e0..32f8e794f4f 100644 --- a/packages/react-server-dom-webpack/src/ReactFlightDOMClient.js +++ b/packages/react-server-dom-webpack/src/ReactFlightDOMClient.js @@ -35,12 +35,18 @@ function startReadingFromStream( } const buffer: Uint8Array = (value: any); processBinaryChunk(response, buffer); - return reader.read().then(progress, error); + return reader + .read() + .then(progress) + .catch(error); } function error(e) { reportGlobalError(response, e); } - reader.read().then(progress, error); + reader + .read() + .then(progress) + .catch(error); } function createFromReadableStream( From 7c08ff56f42d49a6faa3c772d9db00f16ad175c4 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Mon, 29 Aug 2022 16:23:46 -0400 Subject: [PATCH 2/2] Serialize references to errors in the error priority queue It doesn't make sense to emit references to future values at higher pri than the value that they're referencing. This ensures that we don't emit hard forward references to values that don't yet exist. --- packages/react-client/src/ReactFlightClient.js | 5 +++++ packages/react-server/src/ReactFlightServer.js | 2 +- scripts/error-codes/codes.json | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/react-client/src/ReactFlightClient.js b/packages/react-client/src/ReactFlightClient.js index 13fb0897e74..d6ae368abf1 100644 --- a/packages/react-client/src/ReactFlightClient.js +++ b/packages/react-client/src/ReactFlightClient.js @@ -312,6 +312,11 @@ export function parseModelString( } else { const id = parseInt(value.substring(1), 16); const chunk = getChunk(response, id); + if (chunk._status === PENDING) { + throw new Error( + "We didn't expect to see a forward reference. This is a bug in the React Server.", + ); + } return readChunk(chunk); } } diff --git a/packages/react-server/src/ReactFlightServer.js b/packages/react-server/src/ReactFlightServer.js index 1577687c004..2a994fc8f32 100644 --- a/packages/react-server/src/ReactFlightServer.js +++ b/packages/react-server/src/ReactFlightServer.js @@ -902,7 +902,7 @@ function abortTask(task: Task, request: Request, errorId: number): void { // has a single value referencing the error. const ref = serializeByValueID(errorId); const processedChunk = processReferenceChunk(request, task.id, ref); - request.completedJSONChunks.push(processedChunk); + request.completedErrorChunks.push(processedChunk); } function flushCompletedChunks( diff --git a/scripts/error-codes/codes.json b/scripts/error-codes/codes.json index 423b30de52d..4817eadd990 100644 --- a/scripts/error-codes/codes.json +++ b/scripts/error-codes/codes.json @@ -423,5 +423,6 @@ "435": "Unexpected Suspense handler tag (%s). This is a bug in React.", "436": "Stylesheet resources need a unique representation in the DOM while hydrating and more than one matching DOM Node was found. To fix, ensure you are only rendering one stylesheet link with an href attribute of \"%s\".", "437": "the \"precedence\" prop for links to stylesheets expects to receive a string but received something of type \"%s\" instead.", - "438": "An unsupported type was passed to use(): %s" + "438": "An unsupported type was passed to use(): %s", + "439": "We didn't expect to see a forward reference. This is a bug in the React Server." }