Skip to content

DevTools: Fix nested HOC name extraction in extractHOCNames#267

Closed
everettbu wants to merge 1 commit into
mainfrom
fix/devtools-nested-hoc-name-extraction
Closed

DevTools: Fix nested HOC name extraction in extractHOCNames#267
everettbu wants to merge 1 commit into
mainfrom
fix/devtools-nested-hoc-name-extraction

Conversation

@everettbu

Copy link
Copy Markdown

Mirror of facebook/react#35398
Original author: TerryTaoYY


Problem

extractHOCNames is responsible for unwrapping displayName strings such as: withFoo(withBar(Component))

The previous implementation used a global RegExp and iterated via RegExp.exec() while mutating the input string on each unwrap. Because global RegExp instances carry state via lastIndex, nested wrappers could stop unwrapping early and only record the outermost HOC.

Solution

Switch to an anchored, non-global RegExp so each unwrap re-parses the updated string from the beginning, eliminating lastIndex drift across iterations.

Tests

  • Added unit coverage for:
    • nested wrappers
    • a single wrapper
    • no HOC wrappers

Test Plan

node ./scripts/jest/jest-cli.js --project devtools --build
--runTestsByPath packages/react-devtools-shared/src/tests/extractHOCNames-test.js

extractHOCNames unwraps displayName strings like: withFoo(withBar(Component))

The previous implementation used a global RegExp and relied on RegExp.exec() while mutating the input string. Because global RegExp instances keep state via lastIndex, nested wrappers could stop unwrapping early and only record the outermost wrapper.

Use an anchored, non-global RegExp so each unwrap re-parses the updated name from the beginning, avoiding lastIndex drift.

Add unit tests covering nested wrappers, a single wrapper, and no-wrapper cases.

Test Plan:
node ./scripts/jest/jest-cli.js --project devtools --build \
  --runTestsByPath packages/react-devtools-shared/src/__tests__/extractHOCNames-test.js
@greptile-apps

greptile-apps Bot commented Dec 21, 2025

Copy link
Copy Markdown

Greptile Summary

Fixed a subtle RegExp bug in extractHOCNames where nested Higher-Order Component wrappers like Memo(Forget(Foo)) would fail to unwrap completely. The previous global RegExp carried lastIndex state across iterations, causing early termination when the string was mutated mid-loop.

  • Changed RegExp from global /g flag to anchored ^...$ pattern without global flag
  • Added anchors ensure complete string match from start to end on each iteration
  • Eliminated lastIndex drift by removing global flag, fixing nested HOC extraction
  • Added comprehensive test coverage for nested HOCs, single HOC, and no HOC cases

Confidence Score: 5/5

  • This PR is safe to merge with no risk
  • The fix correctly addresses the root cause by eliminating RegExp lastIndex state issues, the logic is sound and well-tested, and the change is minimal and focused
  • No files require special attention

Important Files Changed

Filename Overview
packages/react-devtools-shared/src/backend/views/utils.js Fixed RegExp from global to anchored non-global to eliminate lastIndex state issues in nested HOC unwrapping
packages/react-devtools-shared/src/tests/extractHOCNames-test.js Added comprehensive test coverage for nested HOCs, single HOC, and no HOC cases

@github-actions

Copy link
Copy Markdown

This pull request has been automatically marked as stale. If this pull request is still relevant, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize reviewing it yet. Your contribution is very much appreciated.

@github-actions github-actions Bot added the Resolution: Stale Automatically closed due to inactivity label Mar 21, 2026
@github-actions

Copy link
Copy Markdown

Closing this pull request after a prolonged period of inactivity. If this issue is still present in the latest release, please ask for this pull request to be reopened. Thank you!

@github-actions github-actions Bot closed this Mar 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed Resolution: Stale Automatically closed due to inactivity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants