**Do you want to request a *feature* or report a *bug*?**
Report a bug.

**What is the current behavior?**
Programmatically calling window.print() can cause React to report strange errors before crashing under certain circumstances.  The trigger *seems to be* a call to print() that results in a React state change somewhere (which, in Chrome, seems to happen because the print preview it shows can cause media query events, which can be hooked up to calls to a setState function).  This does not always happen, however--as shown in the example if the code is not called from in a setTimeout it doesn't seem to crash.  In addition, if the user initiates printing instead (e.g. via CTRL+P), React never crashes.

The two errors I've seen happen as a result of this are `Failed to execute 'handleEvent' on 'EventListener': The provided callback is no longer runnable` (needs "Pause on caught exceptions" in Chrome's DevTools to catch), and after a few of those they're followed by `Maximum update depth exceeded` (even though the setState function is only called once).  Once this happens, there's a good chance the tab become completely unresponsive after the print dialog is closed.

**If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem.**

A minimal example can be found here: https://codesandbox.io/s/immutable-snowflake-06cj2 . There are no external dependencies. The code is commented with instructions to reproduce the behavior.

I've also included a copy of the code here for completeness' sake:

```jsx
import React from "react";
import ReactDOM from "react-dom";

// Custom hook to match media queries.
// The setMatch call in this function is at the bottom of the error stack.
function useMediaQuery(query) {

  const [match, setMatch] = React.useState(() => window.matchMedia(query).matches);

  React.useEffect(() => {
    const queryList = window.matchMedia(query);

    /*************************************************************/
    /* If this function is not called, the crash does not occur. */
    /* When window.print is called, this effect is run as a      */
    /* consequence. However React handles it causes errors and   */
    /* other strange behavior. Because Firefox handles printing  */
    /* differently, it does not crash.                           */
    /* While this is an example of using setState in useEffect,  */
    /* it is only run once before the error is thrown anyway.    */
    /*************************************************************/
    const handleMatch = () => setMatch(queryList.matches);
    handleMatch();

    // Bookkeeping, not relevant to the crash.
    queryList.addListener(handleMatch);
    return () => queryList.removeListener(handleMatch);
  }, [query]);

  return match;
}


export function App() {
  // This is the simplist media query that will cause a crash
  // But anything will work as long as it's different during printing.
  // For example, "(max-width: 1260px)" also works if the window
  // is wide enough.
  let isPrint = useMediaQuery("print");

  return (
    <div>
      <p style={{ fontWeight: 'bold' }}>Important: Only Chrome crashes; Firefox (and likely others) are safe.</p>
      <p>(You may need to open this page in its own window instead of the Code Sandbox split-screen.)</p>

      <button onClick={() => setTimeout(window.print, 100)}>Crashes</button>
      <button onClick={asyncPrint}>Crashes</button>
      <button onClick={() => window.print()}>Does not crash</button>
      <button onClick={syncPrint}>Does not crash</button>
      <p>(Note that pressing CTRL+P never crashes)</p>
      <p>If you click the button to call window.print(), React will behave strangely. Once the print preview is about to show, suddenly an error <code>"Failed to execute 'handleEvent' on 'EventListener': The provided callback is no longer runnable"</code> will be thrown. After that happens a few times, a <code>"Maximum update depth exceeded"</code> error will be thrown, even though the setState function is only called once.</p>
      <p>(Printing with CTRL+P won't crash, clicking the button to print will)</p>
    </div>
  );
}


function syncPrint() { window.print(); }
function asyncPrint() { setTimeout(window.print, 100); }


const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```

**What is the expected behavior?**
React should not throw errors after calling window.print(), even if doing so causes state changes.

**Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?**

This is the latest release (16.9.0).  I am unsure if other versions of React are affected.
The behavior was tested using Chrome 76 on Windows 10.  This behavior _will not happen_ in Firefox and likely other browsers as well, probably due to the unique way Chrome handles printing and print previews.




if (didError) {
        if (!didSetError) {
          
          error = new Error(
            'An error was thrown inside one of your components, but React ' +
              "doesn't know what it was. This is likely due to browser " +
              'flakiness. React does its best to preserve the "Pause on ' +
              'exceptions" behavior of the DevTools, which requires some ' +
              "DEV-mode only tricks. It's possible that these don't work in " +
              'your browser. Try triggering the error in production mode, ' +
              'or switching to a modern browser. If you suspect that this is ' +
              'actually an issue with React, please file an issue.',
          );
        } else if (isCrossOriginError) {
          error = new Error(
            "A cross-origin error was thrown. React doesn't have access to " +
              'the actual error object in development. ' +
              'See https:fb.me/react-crossorigin-error for more information.',
          );
        }
        this.onError(error);
      }
      
      window.removeEventListener('error', handleWindowError);
    };
    invokeGuardedCallbackImpl = invokeGuardedCallbackDev;
  }
}
export default invokeGuardedCallbackImpl;