diff --git a/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js b/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js
index 9c7b5b62b19..40ee3971298 100644
--- a/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js
+++ b/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js
@@ -3051,4 +3051,60 @@ describe('ReactFlightDOMBrowser', () => {
`);
}
});
+
+ it('should resolve a cycle between debug info and the value it produces when using a debug channel', async () => {
+ // Same as `should resolve a cycle between debug info and the value it produces`, but using a debug channel.
+
+ function Inner({style}) {
+ return
;
+ }
+
+ function Component({style}) {
+ return ;
+ }
+
+ const style = {};
+ const element = ;
+ style.element = element;
+
+ let debugReadableStreamController;
+
+ const debugReadableStream = new ReadableStream({
+ start(controller) {
+ debugReadableStreamController = controller;
+ },
+ });
+
+ const rscStream = await serverAct(() =>
+ ReactServerDOMServer.renderToReadableStream(element, webpackMap, {
+ debugChannel: {
+ writable: new WritableStream({
+ write(chunk) {
+ debugReadableStreamController.enqueue(chunk);
+ },
+ close() {
+ debugReadableStreamController.close();
+ },
+ }),
+ },
+ }),
+ );
+
+ function ClientRoot({response}) {
+ return use(response);
+ }
+
+ const response = ReactServerDOMClient.createFromReadableStream(rscStream, {
+ debugChannel: {readable: debugReadableStream},
+ });
+
+ const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
+
+ await act(() => {
+ root.render();
+ });
+
+ expect(container.innerHTML).toBe('');
+ });
});
diff --git a/packages/react-server/src/ReactFlightServer.js b/packages/react-server/src/ReactFlightServer.js
index 546e1bbb64f..152be2eecca 100644
--- a/packages/react-server/src/ReactFlightServer.js
+++ b/packages/react-server/src/ReactFlightServer.js
@@ -4300,14 +4300,21 @@ function emitDebugChunk(
const json: string = serializeDebugModel(request, 500, debugInfo);
if (request.debugDestination !== null) {
- // Outline the actual timing information to the debug channel.
- const outlinedId = request.nextChunkId++;
- const debugRow = outlinedId.toString(16) + ':' + json + '\n';
- request.pendingDebugChunks++;
- request.completedDebugChunks.push(stringToChunk(debugRow));
- const row =
- serializeRowHeader('D', id) + '"$' + outlinedId.toString(16) + '"\n';
- request.completedRegularChunks.push(stringToChunk(row));
+ if (json[0] === '"' && json[1] === '$') {
+ // This is already an outlined reference so we can just emit it directly,
+ // without an unnecessary indirection.
+ const row = serializeRowHeader('D', id) + json + '\n';
+ request.completedRegularChunks.push(stringToChunk(row));
+ } else {
+ // Outline the debug information to the debug channel.
+ const outlinedId = request.nextChunkId++;
+ const debugRow = outlinedId.toString(16) + ':' + json + '\n';
+ request.pendingDebugChunks++;
+ request.completedDebugChunks.push(stringToChunk(debugRow));
+ const row =
+ serializeRowHeader('D', id) + '"$' + outlinedId.toString(16) + '"\n';
+ request.completedRegularChunks.push(stringToChunk(row));
+ }
} else {
const row = serializeRowHeader('D', id) + json + '\n';
request.completedRegularChunks.push(stringToChunk(row));