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

This commit is contained in:
Mateusz Burzyński
2016-08-31 15:25:18 +01:00
committed by Dan Abramov
parent 7d7defe30f
commit 51476de913
2 changed files with 30 additions and 2 deletions
@@ -344,6 +344,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.
@@ -357,8 +370,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;
@@ -452,4 +452,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;
}
});
});