@samitouri / QOS-React / commits / 711c445bcc

[Flight] Limit fake JSX call site stacks to 10 frames (#37086)

Tim Neutkens committed Jul 22, 2026 at 12:29 UTC 711c445bccc331b3ef85a793feb8e13dcf968fc3
2 files changed +33 -1
packages/react-client/src/ReactFlightClient.js
+14 -1
@@ -4031,11 +4031,24 @@ const createFakeJSXCallStackInDEV: (
4031 ) as any)
4032 : (null as any);
4033
4034 +// v8 (Chromium, Node.js) defaults to 10
4035 +// SpiderMonkey (Firefox) does not support Error.stackTraceLimit
4036 +// JSC (Safari) defaults to 100
4037 +// The lower the limit, the more likely we'll not reach react_stack_bottom_frame
4038 +// The higher the limit, the slower Error() is when not inspecting with a debugger.
4039 +// When inspecting with a debugger, Error.stackTraceLimit has no impact on Error() performance (in v8).
4040 +const ownerStackTraceLimit = 10;
4041 +
4042 /** @noinline */
4043 function fakeJSXCallSite() {
4044 // This extra call frame represents the JSX creation function. We always pop this frame
4045 // off before presenting so it needs to be part of the stack.
4038 - return new Error('react-stack-top-frame');
4046 + let error;
4047 + const previousStackTraceLimit = Error.stackTraceLimit;
4048 + Error.stackTraceLimit = ownerStackTraceLimit;
4049 + error = Error('react-stack-top-frame'); // eslint-disable-line prefer-const
4050 + Error.stackTraceLimit = previousStackTraceLimit;
4051 + return error;
4052 }
4053
4054 function initializeFakeStack(
packages/react-client/src/__tests__/ReactFlight-test.js
+19
@@ -3915,6 +3915,25 @@ describe('ReactFlight', () => {
3915 expect(ReactNoop).toMatchRenderedOutput(<span>Hello, Seb</span>);
3916 });
3917
3918 + it('restores the stack trace limit after recreating JSX call sites', async () => {
3919 + function Component() {
3920 + return ReactServer.createElement('div');
3921 + }
3922 +
3923 + const transport = ReactNoopFlightServer.render(
3924 + ReactServer.createElement(Component),
3925 + );
3926 + const previousStackTraceLimit = Error.stackTraceLimit;
3927 + Error.stackTraceLimit = 50;
3928 + try {
3929 + await ReactNoopFlightClient.read(transport);
3930 +
3931 + expect(Error.stackTraceLimit).toBe(50);
3932 + } finally {
3933 + Error.stackTraceLimit = previousStackTraceLimit;
3934 + }
3935 + });
3936 +
3937 // @gate __DEV__
3938 it('can get the component owner stacks during rendering in dev', () => {
3939 let stack;