From 6a0b69ce7534118d0ef5a7f5e098fb15b4629546 Mon Sep 17 00:00:00 2001 From: Ruslan Lesiutin Date: Wed, 29 May 2024 18:49:51 +0100 Subject: [PATCH] fix[ReactDebugHooks/find-primitive-index]: remove some assumptions --- .../react-debug-tools/src/ReactDebugHooks.js | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/packages/react-debug-tools/src/ReactDebugHooks.js b/packages/react-debug-tools/src/ReactDebugHooks.js index 145dae4ddb0f4..09ba351235ecc 100644 --- a/packages/react-debug-tools/src/ReactDebugHooks.js +++ b/packages/react-debug-tools/src/ReactDebugHooks.js @@ -868,7 +868,12 @@ function findCommonAncestorIndex(rootStack: any, hookStack: any) { } function isReactWrapper(functionName: any, wrapperName: string) { - return parseHookName(functionName) === wrapperName; + const hookName = parseHookName(functionName); + if (wrapperName === 'HostTransitionStatus') { + return hookName === wrapperName || hookName === 'FormStatus'; + } + + return hookName === wrapperName; } function findPrimitiveIndex(hookStack: any, hook: HookLogEntry) { @@ -878,21 +883,24 @@ function findPrimitiveIndex(hookStack: any, hook: HookLogEntry) { return -1; } for (let i = 0; i < primitiveStack.length && i < hookStack.length; i++) { + // Note: there is no guarantee that we will find the top-most primitive frame in the stack + // For React Native (uses Hermes), these source fields will be identical and skipped if (primitiveStack[i].source !== hookStack[i].source) { - // If the next frame is a method from the dispatcher, we - // assume that the next frame after that is the actual public API call. - // This prohibits nesting dispatcher calls in hooks. + // If the next two frames are functions called `useX` then we assume that they're part of the + // wrappers that the React package or other packages adds around the dispatcher. + if ( + i < hookStack.length - 1 && + isReactWrapper(hookStack[i].functionName, hook.dispatcherHookName) + ) { + i++; + } if ( i < hookStack.length - 1 && isReactWrapper(hookStack[i].functionName, hook.dispatcherHookName) ) { i++; - // Guard against the dispatcher call being inlined. - // At this point we wouldn't be able to recover the actual React Hook name. - if (i < hookStack.length - 1) { - i++; - } } + return i; } } @@ -1040,7 +1048,7 @@ function buildTree( const levelChild: HooksNode = { id, isStateEditable, - name: name, + name, value: hook.value, subHooks: [], debugInfo: debugInfo,