diff --git a/packages/react-client/src/ReactFlightClient.js b/packages/react-client/src/ReactFlightClient.js index f2254d471cd..348132c7f25 100644 --- a/packages/react-client/src/ReactFlightClient.js +++ b/packages/react-client/src/ReactFlightClient.js @@ -4031,11 +4031,24 @@ const createFakeJSXCallStackInDEV: ( ) as any) : (null as any); +// v8 (Chromium, Node.js) defaults to 10 +// SpiderMonkey (Firefox) does not support Error.stackTraceLimit +// JSC (Safari) defaults to 100 +// The lower the limit, the more likely we'll not reach react_stack_bottom_frame +// The higher the limit, the slower Error() is when not inspecting with a debugger. +// When inspecting with a debugger, Error.stackTraceLimit has no impact on Error() performance (in v8). +const ownerStackTraceLimit = 10; + /** @noinline */ function fakeJSXCallSite() { // This extra call frame represents the JSX creation function. We always pop this frame // off before presenting so it needs to be part of the stack. - return new Error('react-stack-top-frame'); + let error; + const previousStackTraceLimit = Error.stackTraceLimit; + Error.stackTraceLimit = ownerStackTraceLimit; + error = Error('react-stack-top-frame'); // eslint-disable-line prefer-const + Error.stackTraceLimit = previousStackTraceLimit; + return error; } function initializeFakeStack( diff --git a/packages/react-client/src/__tests__/ReactFlight-test.js b/packages/react-client/src/__tests__/ReactFlight-test.js index 473b86aad2a..5bb9efea932 100644 --- a/packages/react-client/src/__tests__/ReactFlight-test.js +++ b/packages/react-client/src/__tests__/ReactFlight-test.js @@ -3915,6 +3915,25 @@ describe('ReactFlight', () => { expect(ReactNoop).toMatchRenderedOutput(Hello, Seb); }); + it('restores the stack trace limit after recreating JSX call sites', async () => { + function Component() { + return ReactServer.createElement('div'); + } + + const transport = ReactNoopFlightServer.render( + ReactServer.createElement(Component), + ); + const previousStackTraceLimit = Error.stackTraceLimit; + Error.stackTraceLimit = 50; + try { + await ReactNoopFlightClient.read(transport); + + expect(Error.stackTraceLimit).toBe(50); + } finally { + Error.stackTraceLimit = previousStackTraceLimit; + } + }); + // @gate __DEV__ it('can get the component owner stacks during rendering in dev', () => { let stack;