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

(cherry picked from commit 51476de913)
This commit is contained in:
Mateusz Burzyński
2016-08-31 16:25:18 +02:00
committed by Paul O’Shannessy
parent 7b39bbaa91
commit 60ed71459c
2 changed files with 30 additions and 2 deletions
@@ -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;
@@ -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;
}
});
});