| 1 | /** |
| 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. |
| 3 | * |
| 4 | * This source code is licensed under the MIT license found in the |
| 5 | * LICENSE file in the root directory of this source tree. |
| 6 | * |
| 7 | * @flow |
| 8 | */ |
| 9 | |
| 10 | // This is a DevTools fork of ReactComponentInfoStack. |
| 11 | // This fork enables DevTools to use the same "native" component stack format, |
| 12 | // while still maintaining support for multiple renderer versions |
| 13 | // (which use different values for ReactTypeOfWork). |
| 14 | |
| 15 | import type {ReactComponentInfo} from 'shared/ReactTypes'; |
| 16 | |
| 17 | import {describeBuiltInComponentFrame} from '../shared/DevToolsComponentStackFrame'; |
| 18 | |
| 19 | import {formatOwnerStack} from '../shared/DevToolsOwnerStack'; |
| 20 | |
| 21 | export function getOwnerStackByComponentInfoInDev( |
| 22 | componentInfo: ReactComponentInfo, |
| 23 | ): string { |
| 24 | try { |
| 25 | let info = ''; |
| 26 | |
| 27 | // The owner stack of the current component will be where it was created, i.e. inside its owner. |
| 28 | // There's no actual name of the currently executing component. Instead, that is available |
| 29 | // on the regular stack that's currently executing. However, if there is no owner at all, then |
| 30 | // there's no stack frame so we add the name of the root component to the stack to know which |
| 31 | // component is currently executing. |
| 32 | if (!componentInfo.owner && typeof componentInfo.name === 'string') { |
| 33 | return describeBuiltInComponentFrame(componentInfo.name); |
| 34 | } |
| 35 | |
| 36 | let owner: void | null | ReactComponentInfo = componentInfo; |
| 37 | |
| 38 | while (owner) { |
| 39 | const ownerStack: ?Error = owner.debugStack; |
| 40 | if (ownerStack != null) { |
| 41 | // Server Component |
| 42 | owner = owner.owner; |
| 43 | if (owner) { |
| 44 | // TODO: Should we stash this somewhere for caching purposes? |
| 45 | info += '\n' + formatOwnerStack(ownerStack); |
| 46 | } |
| 47 | } else { |
| 48 | break; |
| 49 | } |
| 50 | } |
| 51 | return info; |
| 52 | } catch (x) { |
| 53 | return '\nError generating stack: ' + x.message + '\n' + x.stack; |
| 54 | } |
| 55 | } |