Repository: facebook/react
Pull request: [Fiber] Don't throw away the Error object retaining the owner stack

We currently throw away the Error once we've used to the owner stack of a Fiber once. This maybe helps a bit with memory and redoing it but we really don't expect most Fibers to hit this at all. It's not very hot.

If we throw away the Error, then we can't use native debugger protocols to inspect the native stack. Instead, we'd have to maintain a url to resource map indefinitely like what Chrome DevTools does to map a url to a resource. Technically it's not even technically correct since the file path might not be reversible and could in theory conflict.


Changed files:
filename: packages/react-devtools-shared/src/backend/fiber/DevToolsFiberComponentStack.js
patch: @@ -199,7 +199,7 @@ export function getOwnerStackByFiberInDev(
       if (typeof owner.tag === 'number') {
         const fiber: Fiber = (owner: any);
         owner = fiber._debugOwner;
-        let debugStack = fiber._debugStack;
+        let debugStack: void | null | string | Error = fiber._debugStack;
         // If we don't actually print the stack if there is no owner of this JSX element.
         // In a real app it's typically not useful since the root app is always controlled
         // by the framework. These also tend to have noisy stacks because they're not rooted

filename: packages/react-reconciler/src/ReactFiberComponentStack.js
patch: @@ -177,20 +177,17 @@ export function getOwnerStackByFiberInDev(workInProgress: Fiber): string {
       if (typeof owner.tag === 'number') {
         const fiber: Fiber = (owner: any);
         owner = fiber._debugOwner;
-        let debugStack = fiber._debugStack;
+        const debugStack = fiber._debugStack;
         // If we don't actually print the stack if there is no owner of this JSX element.
         // In a real app it's typically not useful since the root app is always controlled
         // by the framework. These also tend to have noisy stacks because they're not rooted
         // in a React render but in some imperative bootstrapping code. It could be useful
         // if the element was created in module scope. E.g. hoisted. We could add a a single
         // stack frame for context for example but it doesn't say much if that's a wrapper.
         if (owner && debugStack) {
-          if (typeof debugStack !== 'string') {
-            // Stash the formatted stack so that we can avoid redoing the filtering.
-            fiber._debugStack = debugStack = formatOwnerStack(debugStack);
-          }
-          if (debugStack !== '') {
-            info += '\n' + debugStack;
+          const formattedStack = formatOwnerStack(debugStack);
+          if (formattedStack !== '') {
+            info += '\n' + formattedStack;
           }
         }
       } else if (owner.debugStack != null) {

filename: packages/react-reconciler/src/ReactInternalTypes.js
patch: @@ -200,7 +200,7 @@ export type Fiber = {
 
   _debugInfo?: ReactDebugInfo | null,
   _debugOwner?: ReactComponentInfo | Fiber | null,
-  _debugStack?: string | Error | null,
+  _debugStack?: Error | null,
   _debugTask?: ConsoleTask | null,
   _debugNeedsRemount?: boolean,