[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;