diff --git a/src/renderers/dom/client/ReactBrowserEventEmitter.js b/src/renderers/dom/client/ReactBrowserEventEmitter.js index dd7334f48463b..8f6bd8d8e6f2e 100644 --- a/src/renderers/dom/client/ReactBrowserEventEmitter.js +++ b/src/renderers/dom/client/ReactBrowserEventEmitter.js @@ -346,6 +346,19 @@ var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, { ); }, + /** + * Protect against document.createEvent() returning null + * Some popup blocker extensions appear to do this: + * https://github.com/facebook/react/issues/6887 + */ + supportsEventPageXY: function() { + if (!document.createEvent) { + return false; + } + var ev = document.createEvent('MouseEvent'); + return ev != null && 'pageX' in ev; + }, + /** * Listens to window scroll and resize events. We cache scroll values so that * application code can access them without triggering reflows. @@ -359,8 +372,7 @@ var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, { */ ensureScrollValueMonitoring: function() { if (hasEventPageXY === undefined) { - hasEventPageXY = - document.createEvent && 'pageX' in document.createEvent('MouseEvent'); + hasEventPageXY = ReactBrowserEventEmitter.supportsEventPageXY(); } if (!hasEventPageXY && !isMonitoringScrollValue) { var refresh = ViewportMetrics.refreshScrollValues; diff --git a/src/renderers/dom/client/__tests__/ReactBrowserEventEmitter-test.js b/src/renderers/dom/client/__tests__/ReactBrowserEventEmitter-test.js index 009bc5d223608..a0f2cf123db5b 100644 --- a/src/renderers/dom/client/__tests__/ReactBrowserEventEmitter-test.js +++ b/src/renderers/dom/client/__tests__/ReactBrowserEventEmitter-test.js @@ -454,4 +454,20 @@ describe('ReactBrowserEventEmitter', function() { expect(idCallOrder[2]).toBe(getInternal(GRANDPARENT)); }); + it('should not crash ensureScrollValueMonitoring when createEvent returns null', function() { + var originalCreateEvent = document.createEvent; + document.createEvent = function() { + return null; + }; + spyOn(document, 'createEvent'); + + try { + var hasEventPageXY = ReactBrowserEventEmitter.supportsEventPageXY(); + expect(document.createEvent.calls.count()).toBe(1); + expect(hasEventPageXY).toBe(false); + } finally { + document.createEvent = originalCreateEvent; + } + }); + });