Skip to content

useMediaQuery causes error in Firefox browser extension content script #44986

@Mr-Quin

Description

@Mr-Quin

Steps to reproduce

Steps:

  1. Download this this minimal reproduction browser extension https://github.com/Mr-Quin/mui-firefox-debug/releases/tag/1.0.0
  2. Load it into Firefox and Chrome
  3. Go to https://www.google.com/ and compare the behavior between the browser

Current behavior

The example extension calls useMediaQuery("(prefers-color-scheme: dark)") and renders "Prefer dark: Yes/No" on the page

Behavior in Chrome:
image

In Firefox, the content script crashes with error

Uncaught TypeError: 'matchMedia' called on an object that does not implement interface Window.
    <anonymous> moz-extension://614e6a10-4d1a-4c77-93fa-2e3a5dd1fd2e/assets/index.tsx-CQJLccjk.js:3134
    useMemo moz-extension://614e6a10-4d1a-4c77-93fa-2e3a5dd1fd2e/assets/index.tsx-CQJLccjk.js:9316
    useMemo moz-extension://614e6a10-4d1a-4c77-93fa-2e3a5dd1fd2e/assets/index.tsx-CQJLccjk.js:584
    useMediaQueryNew moz-extension://614e6a10-4d1a-4c77-93fa-2e3a5dd1fd2e/assets/index.tsx-CQJLccjk.js:3129
    useMediaQuery2 moz-extension://614e6a10-4d1a-4c77-93fa-2e3a5dd1fd2e/assets/index.tsx-CQJLccjk.js:3168
    App moz-extension://614e6a10-4d1a-4c77-93fa-2e3a5dd1fd2e/assets/index.tsx-CQJLccjk.js:16771
    renderWithHooks moz-extension://614e6a10-4d1a-4c77-93fa-2e3a5dd1fd2e/assets/index.tsx-CQJLccjk.js:8411
    updateFunctionComponent moz-extension://614e6a10-4d1a-4c77-93fa-2e3a5dd1fd2e/assets/index.tsx-CQJLccjk.js:9908
    beginWork moz-extension://614e6a10-4d1a-4c77-93fa-2e3a5dd1fd2e/assets/index.tsx-CQJLccjk.js:10563
    performUnitOfWork moz-extension://614e6a10-4d1a-4c77-93fa-2e3a5dd1fd2e/assets/index.tsx-CQJLccjk.js:13628
    workLoopSync moz-extension://614e6a10-4d1a-4c77-93fa-2e3a5dd1fd2e/assets/index.tsx-CQJLccjk.js:13527
    renderRootSync moz-extension://614e6a10-4d1a-4c77-93fa-2e3a5dd1fd2e/assets/index.tsx-CQJLccjk.js:13511
    performWorkOnRoot moz-extension://614e6a10-4d1a-4c77-93fa-2e3a5dd1fd2e/assets/index.tsx-CQJLccjk.js:13213
    performWorkOnRootViaSchedulerTask moz-extension://614e6a10-4d1a-4c77-93fa-2e3a5dd1fd2e/assets/index.tsx-CQJLccjk.js:14053
    performWorkUntilDeadline moz-extension://614e6a10-4d1a-4c77-93fa-2e3a5dd1fd2e/assets/index.tsx-CQJLccjk.js:5668
[index.tsx-CQJLccjk.js:3134:39](moz-extension://614e6a10-4d1a-4c77-93fa-2e3a5dd1fd2e/assets/index.tsx-CQJLccjk.js)

image

Expected behavior

Using useMediaQuery should not crash the script in Firefox

Context

Offending line

function useMediaQueryNew(query, defaultMatches, matchMedia2, ssrMatchMedia, noSsr) {
  const getDefaultSnapshot = reactExports.useCallback(() => defaultMatches, [defaultMatches]);
  const getServerSnapshot = reactExports.useMemo(() => {
    if (noSsr && matchMedia2) {
      return () => matchMedia2(query).matches;
    }
    if (ssrMatchMedia !== null) {
      const {
        matches
      } = ssrMatchMedia(query);
      return () => matches;
    }
    return getDefaultSnapshot;
  }, [getDefaultSnapshot, query, ssrMatchMedia, noSsr, matchMedia2]);
  const [getSnapshot, subscribe] = reactExports.useMemo(() => {
    if (matchMedia2 === null) {
      return [getDefaultSnapshot, () => () => {
      }];
    }
    const mediaQueryList = matchMedia2(query); // <----------------- this one
    return [() => mediaQueryList.matches, (notify) => {
      mediaQueryList.addEventListener("change", notify);
      return () => {
        mediaQueryList.removeEventListener("change", notify);
      };
    }];
  }, [getDefaultSnapshot, matchMedia2, query]);
  const match2 = maybeReactUseSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
  return match2;
}

This might be a fairly niche use case, but a similar issue can be found here facebook/react#16606.

I was able to fix this by replacing this line in mui-system/src/useMediaQuery/useMediaQuery.ts

matchMedia = supportMatchMedia ? window.matchMedia : null,

with

matchMedia = supportMatchMedia ? window.matchMedia.bind(window) : null,

I don't know what exactly causes the issue in Firefox alone but looks like it has something to do with saving window methods to a variable and calling that variable.

Your environment

System:
OS: Windows 11 10.0.26100
Binaries:
Node: 20.12.1 - C:\Program Files\nodejs\node.EXE
npm: 10.5.0 - C:\Program Files\nodejs\npm.CMD
pnpm: 9.15.2 - C:\Program Files\nodejs\pnpm.CMD
Browsers:
Google Chrome 131.0.6778.265
Firefox Developer Edition 135.0b2
npmPackages:
@emotion/react: ^11.14.0 => 11.14.0
@emotion/styled: ^11.14.0 => 11.14.0
@mui/icons-material: ^6.3.0 => 6.3.1
@mui/material: ^6.3.0 => 6.3.1
@mui/system: ^6.3.0 => 6.3.1
@types/react: ^19.0.2 => 19.0.4
react: 19.0.0 => 19.0.0
react-dom: 19.0.0 => 19.0.0
typescript: ^5.7.2 => 5.7.3

Search keywords: extension firefox useMediaQuery matchMedia

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions