@samitouri / QOS-React / commits / 51476de913

Guarded ensureScrollValueMonitoring against some malicious script on the Internet overriding native document.createEvent (fixes #6887) (#7621)

Mateusz Burzyński committed Aug 31, 2016 at 16:25 UTC 51476de9134f1a9d060dfe7566a1c752b68b381f
2 files changed +30 -2
src/renderers/dom/client/ReactBrowserEventEmitter.js
+14 -2
@@ -344,6 +344,19 @@ var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, {
344 );
345 },
346
347 + /**
348 + * Protect against document.createEvent() returning null
349 + * Some popup blocker extensions appear to do this:
350 + * https://github.com/facebook/react/issues/6887
351 + */
352 + supportsEventPageXY: function() {
353 + if (!document.createEvent) {
354 + return false;
355 + }
356 + var ev = document.createEvent('MouseEvent');
357 + return ev != null && 'pageX' in ev;
358 + },
359 +
360 /**
361 * Listens to window scroll and resize events. We cache scroll values so that
362 * application code can access them without triggering reflows.
@@ -357,8 +370,7 @@ var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, {
370 */
371 ensureScrollValueMonitoring: function() {
372 if (hasEventPageXY === undefined) {
360 - hasEventPageXY =
361 - document.createEvent && 'pageX' in document.createEvent('MouseEvent');
373 + hasEventPageXY = ReactBrowserEventEmitter.supportsEventPageXY();
374 }
375 if (!hasEventPageXY && !isMonitoringScrollValue) {
376 var refresh = ViewportMetrics.refreshScrollValues;
src/renderers/dom/client/__tests__/ReactBrowserEventEmitter-test.js
+16
@@ -452,4 +452,20 @@ describe('ReactBrowserEventEmitter', function() {
452 expect(idCallOrder[2]).toBe(getInternal(GRANDPARENT));
453 });
454
455 + it('should not crash ensureScrollValueMonitoring when createEvent returns null', function() {
456 + var originalCreateEvent = document.createEvent;
457 + document.createEvent = function() {
458 + return null;
459 + };
460 + spyOn(document, 'createEvent');
461 +
462 + try {
463 + var hasEventPageXY = ReactBrowserEventEmitter.supportsEventPageXY();
464 + expect(document.createEvent.calls.count()).toBe(1);
465 + expect(hasEventPageXY).toBe(false);
466 + } finally {
467 + document.createEvent = originalCreateEvent;
468 + }
469 + });
470 +
471 });