From e3fe0d03c54c875caf3181194b3ffb3bd1827be4 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Sun, 15 Jun 2025 16:12:32 -0700 Subject: [PATCH 1/3] [Flight] Serialize functions by reference --- .../src/__tests__/ReactFlight-test.js | 1 + packages/react-server/src/ReactFlightServer.js | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/react-client/src/__tests__/ReactFlight-test.js b/packages/react-client/src/__tests__/ReactFlight-test.js index 49968b33590d9..7dc940cfdd4ef 100644 --- a/packages/react-client/src/__tests__/ReactFlight-test.js +++ b/packages/react-client/src/__tests__/ReactFlight-test.js @@ -3276,6 +3276,7 @@ describe('ReactFlight', () => { expect(typeof loggedFn2).toBe('function'); expect(loggedFn2).not.toBe(foo); expect(loggedFn2.toString()).toBe(foo.toString()); + expect(loggedFn2).toBe(loggedFn); const promise = mockConsoleLog.mock.calls[0][1].promise; expect(promise).toBeInstanceOf(Promise); diff --git a/packages/react-server/src/ReactFlightServer.js b/packages/react-server/src/ReactFlightServer.js index e51197c5b2b19..5e527c7981116 100644 --- a/packages/react-server/src/ReactFlightServer.js +++ b/packages/react-server/src/ReactFlightServer.js @@ -4096,8 +4096,23 @@ function renderConsoleValue( } // Serialize the body of the function as an eval so it can be printed. + const writtenObjects = request.writtenObjects; + const existingReference = writtenObjects.get(value); + if (existingReference !== undefined) { + // We've already emitted this function, so we can + // just refer to that by its existing reference. + return existingReference; + } + // $FlowFixMe[method-unbinding] - return serializeEval('(' + Function.prototype.toString.call(value) + ')'); + const serializedValue = serializeEval('(' + Function.prototype.toString.call(value) + ')'); + request.pendingChunks++; + const id = request.nextChunkId++; + const processedChunk = encodeReferenceChunk(request, id, serializedValue); + request.completedRegularChunks.push(processedChunk); + const reference = serializeByValueID(id); + writtenObjects.set(value, reference); + return reference; } if (typeof value === 'symbol') { From df05572c849ed398e62225173a4945d791f6c533 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Sun, 15 Jun 2025 16:31:07 -0700 Subject: [PATCH 2/3] prettier --- packages/react-server/src/ReactFlightServer.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/react-server/src/ReactFlightServer.js b/packages/react-server/src/ReactFlightServer.js index 5e527c7981116..30ae7c7437b8b 100644 --- a/packages/react-server/src/ReactFlightServer.js +++ b/packages/react-server/src/ReactFlightServer.js @@ -4105,7 +4105,9 @@ function renderConsoleValue( } // $FlowFixMe[method-unbinding] - const serializedValue = serializeEval('(' + Function.prototype.toString.call(value) + ')'); + const serializedValue = serializeEval( + '(' + Function.prototype.toString.call(value) + ')', + ); request.pendingChunks++; const id = request.nextChunkId++; const processedChunk = encodeReferenceChunk(request, id, serializedValue); From 529af775e725e4ee8e15f095580b79f286c65749 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Sun, 15 Jun 2025 16:34:44 -0700 Subject: [PATCH 3/3] prettier broke flow --- packages/react-server/src/ReactFlightServer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-server/src/ReactFlightServer.js b/packages/react-server/src/ReactFlightServer.js index 30ae7c7437b8b..f40e3bd9deb66 100644 --- a/packages/react-server/src/ReactFlightServer.js +++ b/packages/react-server/src/ReactFlightServer.js @@ -4104,8 +4104,8 @@ function renderConsoleValue( return existingReference; } - // $FlowFixMe[method-unbinding] const serializedValue = serializeEval( + // $FlowFixMe[method-unbinding] '(' + Function.prototype.toString.call(value) + ')', ); request.pendingChunks++;