diff --git a/packages/internal-test-utils/debugInfo.js b/packages/internal-test-utils/debugInfo.js index b749c8db861..1bafceb503f 100644 --- a/packages/internal-test-utils/debugInfo.js +++ b/packages/internal-test-utils/debugInfo.js @@ -79,6 +79,18 @@ function normalizeIOInfo(config: DebugInfoConfig, ioInfo) { status: promise.status, }; } + } else if ('value' in ioInfo) { + // If value exists in ioInfo but is undefined (e.g., WeakRef was GC'd), + // ensure we still include it in the normalized output for consistency + copy.value = { + value: undefined, + }; + } else if (ioInfo.name && ioInfo.name !== 'rsc stream') { + // For non-rsc-stream IO that doesn't have a value field, add a default. + // This handles the case where the server doesn't send the field when WeakRef is GC'd. + copy.value = { + value: undefined, + }; } return copy; } diff --git a/scripts/jest/setupTests.js b/scripts/jest/setupTests.js index c3d34089063..aadb2801782 100644 --- a/scripts/jest/setupTests.js +++ b/scripts/jest/setupTests.js @@ -319,3 +319,14 @@ jest.mock('async_hooks', () => { }, }; }); + +// Ensure async hooks are disabled after each test to prevent cross-test pollution. +// This is needed because test files that load the Node server (with async debug hooks) +// can pollute test files that load the Edge server (which doesn't create new hooks +// to trigger the cleanup in the mock above). +afterEach(() => { + if (installedHook) { + installedHook.disable(); + installedHook = null; + } +});