Skip to content

Conversation

runway-github[bot]
Copy link
Contributor

@runway-github runway-github bot commented Oct 18, 2025

Description

This PR fixes an issue where Popper.js(used for dropdowns, tooltips, and
popovers) fails to access window.devicePixelRatio in production builds
due to LavaMoat scuttling. The issue was introduced by a recent
@popperjs/core update in PR
#36557
.
The problem stems from this upstream change in
floating-ui

which modified how Popper.js accesses the window object.

  • Popper.js now gets a reference to the real window via a DOM node
    rather than using the global window supplied to the LavaMoat compartment
  • LavaMoat's scuttling removes devicePixelRatio from the real global
    window object for security
  • The LavaMoat policy grants compartments access to specified globals,
    but Popper.js is trying to access them from the wrong window context
  • The upstream change was intended to handle iframe scenarios (pages
    with iframes where popovers from inside iframes render outside)

Two approaches were considered:

  1. Patching Popper.js - Would require ongoing maintenance with
    library updates
  2. Adding scuttling exception - Simpler, more maintainable approach
    that follows existing patterns

This solution was reached through collaborative investigation by
@markstacey and @davidmurdoch, who identified the root cause, evaluated
multiple approaches, and confirmed that the scuttling exception approach
works effectively
https://consensys.slack.com/archives/CTQAGKY5V/p1760559149075479 🙏

Open in GitHub Codespaces

Changelog

CHANGELOG entry: null

Related issues

Fixes: #36951
Fixes: https://consensyssoftware.atlassian.net/browse/CEUX-468

Manual testing steps

  1. Go to the latest build of the extension in this PR
  2. Test UI components that use Popper.js:
    • Open dropdowns in the UI
    • Hover over elements that show tooltips
    • Test any popover menus
  3. Verify that these components position correctly without console
    errors
  4. Check browser developer tools for any devicePixelRatio related
    errors (should be none)

Screenshots/Recordings

Before

Popper.js would fail to access devicePixelRatio in production builds
causing positioning issues

Screenshot 2025-10-17 at 3 20 36 PM

before720.mov

After

Popper.js components work correctly with proper positioning in all build
types

Screenshot 2025-10-17 at 2 53 17 PM

after720.mov

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

Expose devicePixelRatio globally in LavaMoat scuttle exceptions (moved from test-only) to restore Popper-based positioning.

  • Build/LavaMoat scuttling (development/build/index.js):
    • Add devicePixelRatio to global scuttleGlobalThisExceptions (for @popperjs/core and snap simple keyring site).
    • Remove devicePixelRatio from test-only exceptions (BUILD_TARGETS.TEST*).

Written by Cursor Bugbot for commit 90342ac. This will update automatically on new commits. Configure here.

70832c2

…ips, and popovers positioning cp-13.6.0 (#36967)

## **Description**

This PR fixes an issue where Popper.js(used for dropdowns, tooltips, and
popovers) fails to access `window.devicePixelRatio` in production builds
due to LavaMoat scuttling. The issue was introduced by a recent
@popperjs/core update in [PR
#36557](https://github.com/MetaMask/metamask-extension/pull/36557/files#diff-51e4f558fae534656963876761c95b83b6ef5da5103c4adef6768219ed76c2deR9408).
The problem stems from [this upstream change in
floating-ui](floating-ui/floating-ui#2229)
which modified how Popper.js accesses the window object.

- Popper.js now gets a reference to the real window via a DOM node
rather than using the global window supplied to the LavaMoat compartment
- LavaMoat's scuttling removes `devicePixelRatio` from the real global
window object for security
- The LavaMoat policy grants compartments access to specified globals,
but Popper.js is trying to access them from the wrong window context
- The upstream change was intended to handle iframe scenarios (pages
with iframes where popovers from inside iframes render outside)

Two approaches were considered:
1. **Patching Popper.js** - Would require ongoing maintenance with
library updates
2. **Adding scuttling exception** - Simpler, more maintainable approach
that follows existing patterns

This solution was reached through collaborative investigation by
@markstacey and @davidmurdoch, who identified the root cause, evaluated
multiple approaches, and confirmed that the scuttling exception approach
works effectively
https://consensys.slack.com/archives/CTQAGKY5V/p1760559149075479 🙏

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/36967?quickstart=1)

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: #36951
Fixes: https://consensyssoftware.atlassian.net/browse/CEUX-468

## **Manual testing steps**

1. Go to the latest build of the extension in this PR
2. Test UI components that use Popper.js:
   - Open dropdowns in the UI
   - Hover over elements that show tooltips
   - Test any popover menus
4. Verify that these components position correctly without console
errors
5. Check browser developer tools for any `devicePixelRatio` related
errors (should be none)

## **Screenshots/Recordings**

### **Before**
Popper.js would fail to access devicePixelRatio in production builds
causing positioning issues

<img width="413" height="640" alt="Screenshot 2025-10-17 at 3 20 36 PM"
src="https://github.com/user-attachments/assets/a04c16f2-7cdc-4b4b-b866-66917a2de87d"
/>



https://github.com/user-attachments/assets/91eb5594-1694-4718-804b-20613e6446bb

### **After**

Popper.js components work correctly with proper positioning in all build
types

<img width="417" height="644" alt="Screenshot 2025-10-17 at 2 53 17 PM"
src="https://github.com/user-attachments/assets/1bb75f03-a569-45f5-9da5-a6451fa33463"
/>


https://github.com/user-attachments/assets/2a2f13f1-a607-447b-bcf1-6631163f915c

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds `devicePixelRatio` to the default LavaMoat scuttle exceptions
(and removes the test-only entry) so Popper.js can read it in
production.
> 
> - **Build/LavaMoat**:
> - Add `devicePixelRatio` to default `scuttleGlobalThisExceptions` in
`development/build/index.js` for `@popperjs/core`.
> - Remove `devicePixelRatio` from the test-only exceptions list to
avoid duplication.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e27ff47. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Copy link
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-bots Bot team (for MetaMask Bot, Runway Bot, etc.) label Oct 18, 2025
@metamaskbot
Copy link
Collaborator

📊 Page Load Benchmark Results

Current Commit: 90342ac | Date: 10/18/2025

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.03s (±76ms) 🟡 | historical mean value: 1.04s ⬇️ (historical data)
  • domContentLoaded-> current mean value: 729ms (±85ms) 🟢 | historical mean value: 733ms ⬇️ (historical data)
  • firstContentfulPaint-> current mean value: 89ms (±126ms) 🟢 | historical mean value: 77ms ⬆️ (historical data)
📈 Detailed Results
Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.03s 76ms 994ms 1.38s 1.28s 1.38s
domContentLoaded 729ms 85ms 693ms 1.27s 967ms 1.27s
firstPaint 89ms 126ms 64ms 1.34s 88ms 1.34s
firstContentfulPaint 89ms 126ms 64ms 1.34s 88ms 1.34s
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms

Results generated automatically by MetaMask CI

@metamaskbot
Copy link
Collaborator

Builds ready [90342ac]
UI Startup Metrics (1245 ± 69 ms)
PlatformBuildTypePageMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
ChromeBrowserifyHomeuiStartup1245113515196912811368
load106696412586111041190
domContentLoaded106095912526010991184
domInteractive18134871738
firstPaint609145122742110531148
backgroundConnect2542422898257268
firstReactRender26194552837
getState1555491833
initialActions819716760
loadScripts812721100559845933
setupStore1062841118
WebpackHomeuiStartup8166991063748341017
load62557191578626864
domContentLoaded61856789277618856
domInteractive15114681336
firstPaint19054933193184582
backgroundConnect20104272534
firstReactRender25164473133
getState932231114
initialActions3018247
loadScripts61556688274616846
setupStore951731113
FirefoxBrowserifyHomeuiStartup13781202183510914231579
load1177104313957612291302
domContentLoaded1176104313947612281301
domInteractive1083330349114238
firstPaintNaNNaNNaNNaNNaNNaN
backgroundConnect3221113153569
firstReactRender24203942434
getState9419119814
initialActions41294311
loadScripts1154102613737411981278
setupStore116579936
WebpackHomeuiStartup15781391200011116231829
load1348117515888814031516
domContentLoaded1347117515878814021514
domInteractive1073136158108228
firstPaintNaNNaNNaNNaNNaNNaN
backgroundConnect3822311304262
firstReactRender312278133273
getState10311012919
initialActions41547311
loadScripts1324115615558713761486
setupStore14517924929

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

team-bots Bot team (for MetaMask Bot, Runway Bot, etc.)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants