Skip to content

fix(tool-server): key Fabric component-tree measurement by nativeTag so tap coords don't collapse to 0.5,0.5#286

Draft
latekvo wants to merge 1 commit into
mainfrom
fix/component-tree-fabric-nativetag
Draft

fix(tool-server): key Fabric component-tree measurement by nativeTag so tap coords don't collapse to 0.5,0.5#286
latekvo wants to merge 1 commit into
mainfrom
fix/component-tree-fabric-nativetag

Conversation

@latekvo

@latekvo latekvo commented Jun 1, 2026

Copy link
Copy Markdown
Member

Problem

debugger-component-tree returned every element with the same tap coordinate — (tap: 0.50,0.50) — on the New Architecture (Fabric/bridgeless), making the tool's primary output (per-element tap coordinates) unusable. Reproduced live on an RN 0.81.5 Fabric app; the tree walk, skip stats, and screen size were all correct, only the coordinates collapsed.

Root cause

The injected script (utils/debugger/scripts/component-tree.ts) batch-measures host views and caches each rect under a per-host key built as (hi.f ? 'f' : 'p') + hi.n. On Fabric, getHostInfo returns the shadow node object as hi.n ({ f: true, n: fiber.stateNode.node }), so the key stringifies to "f[object Object]" for every host. All hosts collapsed to a single cache entry → only the first (root) view was measured → every component inherited the root's full-screen rect → (x + w/2)/screenW, (y + h/2)/screenH = 0.5, 0.5 for all. Paper/old-arch was unaffected because there hi.n is already a numeric nativeTag.

Fix

Key the cache by a primitive nativeTag on Fabric (fiber.stateNode.canonical.nativeTag, the same field the Paper branch already uses), with a WeakMap-by-identity fallback so distinct shadow nodes can never share a key even if nativeTag were ever absent. getHostInfo now carries an explicit key, and the three cache-key derivations use it. Paper/old-arch behavior is unchanged.

Testing

Live (first-hand), on a running RN 0.81 Fabric app — walking the live fiber tree:

Fabric host nodes distinct measure keys
old key ('f' + node) 2140 1 ("f[object Object]")
new key ('f' + nativeTag) 2140 2140

Unit — adds test/debugger/component-tree-script.test.ts, which evaluates the injected script against a mocked Fabric tree of three siblings at distinct positions (the existing component-tree.test.ts only covered the pure post-processor with pre-filled rects, which is why this shipped). vitest run → passes with the fix; reverting component-tree.ts to main fails it with { y: 100 } to match { y: 300 } (the second component inheriting the first's rect — exactly the collapse).

…veTag

debugger-component-tree returned every element with the same (0.5, 0.5) tap coordinate on the New Architecture (Fabric). The per-host measure cache keyed each host by 'f' + hostInfo.n, where on Fabric n is the shadow-node OBJECT — which stringifies to "f[object Object]" for every node. All hosts collapsed to a single cache entry, so every component was assigned the first (root) view's full-screen rect, rendering as a centre-of-screen tap for everything.

Key by the numeric nativeTag (canonical.nativeTag) instead, with a WeakMap-by-identity fallback so distinct shadow nodes never share a key. Paper/old-arch is unchanged (its n was already a numeric tag).

Verified live against a running RN 0.81 Fabric app: 2140 host nodes now produce 2140 distinct measure keys (was 1). Adds a script-level test (the existing component-tree test only covered the pure post-processor with pre-filled rects).
@latekvo latekvo force-pushed the fix/component-tree-fabric-nativetag branch from 35eb73b to dec89dc Compare June 3, 2026 15:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant