Skip to content

fix: release settings form controls on unmount#42752

Merged
pedronfigueiredo merged 1 commit into
mainfrom
pnf/settings-form-control-memory-fix
May 21, 2026
Merged

fix: release settings form controls on unmount#42752
pedronfigueiredo merged 1 commit into
mainfrom
pnf/settings-form-control-memory-fix

Conversation

@pedronfigueiredo

@pedronfigueiredo pedronfigueiredo commented May 18, 2026

Copy link
Copy Markdown
Contributor

Description

The settings-route memory profile still retained one detached Settings page per route cycle after the shared image-listener fix. Heap snapshots showed the full settings subtree retained through React 17's per-node non-delegated listener on the native select:

V8EventListener -> native_bind -> select[data-testid="default-address-scope-dropdown"] -> parent settings DOM subtree

React 17 attaches per-node non-delegated listeners to form controls such as input, select, and textarea. On Settings unmount, this change detaches those retained listener targets and clears React's private host references so a retained listener target cannot keep the entire Settings tree alive. The cleanup is scoped to Settings and covered by a unit test that verifies the retained select is detached and scrubbed on unmount.

Changelog

CHANGELOG entry: null

Related issues

Fixes:

Manual testing steps

  1. source ~/.nvm/nvm.sh && nvm use && yarn build:test
  2. In the memory investigation worktree, with profiler tooling intentionally excluded from this PR and the earlier memory fixes applied: source ~/.nvm/nvm.sh && nvm use && yarn llm:memory -- --iterations 20 --flow settings-route --sample final --probe cdp --snapshot both --output test-artifacts/memory/settings-route-detach-form-controls-probe-cdp-heap-20.json
    PR: test: add memory profiling CLI for extension flows #42733

Profiler evidence:

  • settings-route before this change, after the earlier Safe Chains and image-listener fixes: runtime +10.49 MiB, JS +6.89 MiB, DOM nodes +5581, JS listeners +534 over 20 iterations.
  • settings-route after this change: runtime +5.60 MiB, JS +3.49 MiB, DOM nodes +183, JS listeners +55 over 20 iterations.
  • Heap delta after this change no longer shows retained copies of the settings root or default-address-scope-dropdown; remaining retained maskicon image nodes are detached from the settings tree.

Pre-merge author checklist

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Note

Medium Risk
Adds manual DOM cleanup during Settings unmount, which could inadvertently remove or interfere with elements if the selector scope or ref wiring is wrong. Changes are localized to the Settings page and covered by a new unit test.

Overview
Prevents Settings-route memory retention by adding an unmount cleanup in SettingsLayout that finds input/select/textarea/img under the settings root, deletes React 17 internal __reactFiber$/__reactProps$ references, and removes those nodes from the DOM.

Adds a regression test that mounts Settings with the default-address dropdown enabled, injects fake React internals onto the <select>, unmounts, and asserts the element is detached and the internal keys are cleared.

Reviewed by Cursor Bugbot for commit 6e95b11. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions

Copy link
Copy Markdown
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@metamaskbot metamaskbot added the team-confirmations Push issues to confirmations team label May 18, 2026
@sonarqubecloud

Copy link
Copy Markdown

@metamaskbotv2

metamaskbotv2 Bot commented May 18, 2026

Copy link
Copy Markdown
Contributor
Builds ready [6e95b11]
Deprecated Browserify fallback builds
⚡ Performance Benchmarks (Total: 🟢 13 pass · 🟡 11 warn · 🔴 0 fail)

Baseline (latest main): 51036da | Date: 5/2/2026 | Pipeline: 26037749706 | Baseline logs

Interaction Benchmarks · Samples: 5
Benchmarkchrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
confirmTx
[Sentry log · main/release]
🟡 [CI log]🟢 [CI log]
bridgeUserActions
[Sentry log · main/release]
🟡 [CI log]🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • loadNewAccount/load_new_account: -75%
  • loadNewAccount/total: -75%
  • bridgeUserActions/bridge_load_page: -38%
  • bridgeUserActions/bridge_load_asset_picker: -54%
  • bridgeUserActions/bridge_search_token: -30%
  • bridgeUserActions/total: -38%
  • loadNewAccount/load_new_account: -55%
  • loadNewAccount/total: -55%
  • bridgeUserActions/bridge_load_page: +33%
  • bridgeUserActions/bridge_load_asset_picker: -17%
  • bridgeUserActions/bridge_search_token: -27%
  • bridgeUserActions/total: -17%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 loadNewAccount/FCP: p75 1.9s
  • 🟡 confirmTx/FCP: p75 1.9s
  • 🟡 bridgeUserActions/FCP: p75 1.9s
  • 🟡 loadNewAccount/INP: p75 296ms
Startup Benchmarks · Samples: 100
Benchmarkchrome-webpackfirefox-webpack
startupStandardHome
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
startupPowerUserHome
[Sentry log · main/release]
🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • startupStandardHome/uiStartup: -24%
  • startupStandardHome/load: -20%
  • startupStandardHome/domContentLoaded: -19%
  • startupStandardHome/domInteractive: -12%
  • startupStandardHome/firstPaint: -51%
  • startupStandardHome/backgroundConnect: -42%
  • startupStandardHome/firstReactRender: -30%
  • startupStandardHome/loadScripts: -20%
  • startupStandardHome/setupStore: -14%
  • startupStandardHome/numNetworkReqs: -50%
  • startupStandardHome/load: +17%
  • startupStandardHome/domContentLoaded: +17%
  • startupStandardHome/domInteractive: -33%
  • startupStandardHome/backgroundConnect: +35%
  • startupStandardHome/firstReactRender: +28%
  • startupStandardHome/initialActions: +20%
  • startupStandardHome/loadScripts: +17%
  • startupStandardHome/numNetworkReqs: -45%
  • startupPowerUserHome/uiStartup: -40%
  • startupPowerUserHome/domInteractive: -79%
  • startupPowerUserHome/backgroundConnect: -73%
  • startupPowerUserHome/setupStore: -83%
  • startupPowerUserHome/numNetworkReqs: -77%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 startupPowerUserHome/LCP: p75 3.2s
User Journey Benchmarks · Samples: 5 · mock API
Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
assetDetails
[Sentry log · main/release]
🟡 [CI log]🟢 [CI log]
solanaAssetDetails
[Sentry log · main/release]
🟡 [CI log]🟢 [CI log]
importSrpHome
[Sentry log · main/release]
🟡 [CI log]🟢 [CI log]
sendTransactions
[Sentry log · main/release]
🟡 [CI log]🟡 [CI log]
swap
[Sentry log · main/release]
🟡 [CI log]🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • onboardingImportWallet/srpButtonToSrpForm: -81%
  • onboardingImportWallet/pwFormToMetricsScreen: +544%
  • onboardingImportWallet/metricsToWalletReadyScreen: -28%
  • onboardingImportWallet/doneButtonToHomeScreen: -85%
  • onboardingImportWallet/openAccountMenuToAccountListLoaded: +17%
  • onboardingImportWallet/total: -47%
  • onboardingNewWallet/srpButtonToPwForm: -76%
  • onboardingNewWallet/createPwToRecoveryScreen: +1328%
  • onboardingNewWallet/skipBackupToMetricsScreen: -68%
  • onboardingNewWallet/doneButtonToAssetList: -56%
  • onboardingNewWallet/total: -44%
  • assetDetails/assetClickToPriceChart: -79%
  • assetDetails/total: -79%
  • solanaAssetDetails/assetClickToPriceChart: -85%
  • solanaAssetDetails/total: -85%
  • importSrpHome/loginToHomeScreen: -39%
  • importSrpHome/openAccountMenuAfterLogin: -79%
  • importSrpHome/homeAfterImportWithNewWallet: -68%
  • importSrpHome/total: -64%
  • swap/openSwapPageFromHome: -97%
  • swap/fetchAndDisplaySwapQuotes: +36%
  • swap/total: +13%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 assetDetails/INP: p75 232ms
  • 🟡 assetDetails/FCP: p75 1.9s
  • 🟡 solanaAssetDetails/FCP: p75 2.0s
  • 🟡 importSrpHome/FCP: p75 1.9s
  • 🟡 sendTransactions/INP: p75 240ms
  • 🟡 sendTransactions/FCP: p75 1.9s
  • 🟡 swap/FCP: p75 1.9s
  • 🟡 sendTransactions/FCP: p75 1.8s
Dapp Page Load Benchmarks · Samples: 100
Benchmarkchrome-webpack
dappPageLoad
[Sentry log · main/release]
🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • dappPageLoad/pageLoadTime: +23%
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 2.38 KiB (0.04%)
  • ui: 7.52 KiB (0.08%)
  • common: 711 Bytes (0.01%)

@metamaskbotv2

metamaskbotv2 Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

✨ Files requiring CODEOWNER review ✨

👨‍🔧 @MetaMask/core-extension-ux (2 files, +69 -0)
  • 📁 ui/
    • 📁 pages/
      • 📁 settings/
        • 📄 settings.test.tsx +36 -0
        • 📄 settings.tsx +33 -0

@pedronfigueiredo pedronfigueiredo marked this pull request as ready for review May 20, 2026 12:37
@pedronfigueiredo pedronfigueiredo requested a review from a team as a code owner May 20, 2026 12:37

@ameliejyc ameliejyc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Manually tested and looks fine to me!

@pedronfigueiredo pedronfigueiredo added this pull request to the merge queue May 21, 2026
Merged via the queue into main with commit 0face5e May 21, 2026
215 of 219 checks passed
@pedronfigueiredo pedronfigueiredo deleted the pnf/settings-form-control-memory-fix branch May 21, 2026 14:30
@github-actions github-actions Bot locked and limited conversation to collaborators May 21, 2026
@metamaskbot metamaskbot added the release-13.33.0 Issue or pull request that will be included in release 13.33.0 label May 21, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-13.33.0 Issue or pull request that will be included in release 13.33.0 size-S team-confirmations Push issues to confirmations team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants