@samitouri / QOS-React / commits / d8aa94b0f4

Only capture stacks for up to 10 frames for Owner Stacks (#34864)

Sebastian "Sebbie" Silbermann committed Oct 16, 2025 at 18:00 UTC d8aa94b0f4f22aadd4762b7ca1c690d3d85ae776
1 file changed +57 -16
packages/react/src/jsx/ReactJSXElement.js
+57 -16
@@ -57,6 +57,14 @@ function getOwner() {
57 return null;
58 }
59
60 +// v8 (Chromium, Node.js) defaults to 10
61 +// SpiderMonkey (Firefox) does not support Error.stackTraceLimit
62 +// JSC (Safari) defaults to 100
63 +// The lower the limit, the more likely we'll not reach react_stack_bottom_frame
64 +// The higher the limit, the slower Error() is when not inspecting with a debugger.
65 +// When inspecting with a debugger, Error.stackTraceLimit has no impact on Error() performance (in v8).
66 +const ownerStackTraceLimit = 10;
67 +
68 /** @noinline */
69 function UnknownOwner() {
70 /** @noinline */
@@ -352,15 +360,24 @@ export function jsxProdSignatureRunningInDevWithDynamicChildren(
360 const trackActualOwner =
361 __DEV__ &&
362 ReactSharedInternals.recentlyCreatedOwnerStacks++ < ownerStackLimit;
363 + let debugStackDEV = false;
364 + if (__DEV__) {
365 + if (trackActualOwner) {
366 + const previousStackTraceLimit = Error.stackTraceLimit;
367 + Error.stackTraceLimit = ownerStackTraceLimit;
368 + debugStackDEV = Error('react-stack-top-frame');
369 + Error.stackTraceLimit = previousStackTraceLimit;
370 + } else {
371 + debugStackDEV = unknownOwnerDebugStack;
372 + }
373 + }
374 +
375 return jsxDEVImpl(
376 type,
377 config,
378 maybeKey,
379 isStaticChildren,
360 - __DEV__ &&
361 - (trackActualOwner
362 - ? Error('react-stack-top-frame')
363 - : unknownOwnerDebugStack),
380 + debugStackDEV,
381 __DEV__ &&
382 (trackActualOwner
383 ? createTask(getTaskName(type))
@@ -379,15 +396,23 @@ export function jsxProdSignatureRunningInDevWithStaticChildren(
396 const trackActualOwner =
397 __DEV__ &&
398 ReactSharedInternals.recentlyCreatedOwnerStacks++ < ownerStackLimit;
399 + let debugStackDEV = false;
400 + if (__DEV__) {
401 + if (trackActualOwner) {
402 + const previousStackTraceLimit = Error.stackTraceLimit;
403 + Error.stackTraceLimit = ownerStackTraceLimit;
404 + debugStackDEV = Error('react-stack-top-frame');
405 + Error.stackTraceLimit = previousStackTraceLimit;
406 + } else {
407 + debugStackDEV = unknownOwnerDebugStack;
408 + }
409 + }
410 return jsxDEVImpl(
411 type,
412 config,
413 maybeKey,
414 isStaticChildren,
387 - __DEV__ &&
388 - (trackActualOwner
389 - ? Error('react-stack-top-frame')
390 - : unknownOwnerDebugStack),
415 + debugStackDEV,
416 __DEV__ &&
417 (trackActualOwner
418 ? createTask(getTaskName(type))
@@ -408,15 +433,23 @@ export function jsxDEV(type, config, maybeKey, isStaticChildren) {
433 const trackActualOwner =
434 __DEV__ &&
435 ReactSharedInternals.recentlyCreatedOwnerStacks++ < ownerStackLimit;
436 + let debugStackDEV = false;
437 + if (__DEV__) {
438 + if (trackActualOwner) {
439 + const previousStackTraceLimit = Error.stackTraceLimit;
440 + Error.stackTraceLimit = ownerStackTraceLimit;
441 + debugStackDEV = Error('react-stack-top-frame');
442 + Error.stackTraceLimit = previousStackTraceLimit;
443 + } else {
444 + debugStackDEV = unknownOwnerDebugStack;
445 + }
446 + }
447 return jsxDEVImpl(
448 type,
449 config,
450 maybeKey,
451 isStaticChildren,
416 - __DEV__ &&
417 - (trackActualOwner
418 - ? Error('react-stack-top-frame')
419 - : unknownOwnerDebugStack),
452 + debugStackDEV,
453 __DEV__ &&
454 (trackActualOwner
455 ? createTask(getTaskName(type))
@@ -667,15 +700,23 @@ export function createElement(type, config, children) {
700 const trackActualOwner =
701 __DEV__ &&
702 ReactSharedInternals.recentlyCreatedOwnerStacks++ < ownerStackLimit;
703 + let debugStackDEV = false;
704 + if (__DEV__) {
705 + if (trackActualOwner) {
706 + const previousStackTraceLimit = Error.stackTraceLimit;
707 + Error.stackTraceLimit = ownerStackTraceLimit;
708 + debugStackDEV = Error('react-stack-top-frame');
709 + Error.stackTraceLimit = previousStackTraceLimit;
710 + } else {
711 + debugStackDEV = unknownOwnerDebugStack;
712 + }
713 + }
714 return ReactElement(
715 type,
716 key,
717 props,
718 getOwner(),
675 - __DEV__ &&
676 - (trackActualOwner
677 - ? Error('react-stack-top-frame')
678 - : unknownOwnerDebugStack),
719 + debugStackDEV,
720 __DEV__ &&
721 (trackActualOwner
722 ? createTask(getTaskName(type))