Preserve original global properties when polyfilling them

Summary: Fixes #934.
Closes https://github.com/facebook/react-native/pull/3293

Reviewed By: @​svcscm

Differential Revision: D2525598

Pulled By: @vjeux

fb-gh-sync-id: 90672550f723a183897456dc9512851bfa34807a
This commit is contained in:
Ian MacLeod 2015-10-09 14:39:24 -07:00 committed by facebook-github-bot-4
parent aa8ead7cd6
commit c612d830bb
1 changed files with 33 additions and 8 deletions

View File

@ -44,6 +44,31 @@ function handleError(e, isFatal) {
} }
} }
/**
* Assigns a new global property, replacing the existing one if there is one.
*
* Existing properties are preserved as `originalPropertyName`. Both properties
* will maintain the same enumerability & configurability.
*
* This allows you to undo the more aggressive polyfills, should you need to.
* For example, if you want to route network requests through DevTools (to trace
* them):
*
* GLOBAL.XMLHTTPRequest = GLOBAL.originalXMLHTTPRequest;
*
* For more info on that particular case, see:
* https://github.com/facebook/react-native/issues/934
*/
function polyfillGlobal(name, newValue, scope=GLOBAL) {
var descriptor = Object.getOwnPropertyDescriptor(scope, name);
if (scope[name] !== undefined) {
var backupName = `original${name[0].toUpperCase()}${name.substr(1)}`;
Object.defineProperty(scope, backupName, {...descriptor, value: scope[name]});
}
Object.defineProperty(scope, name, {...descriptor, value: newValue});
}
function setUpRedBoxErrorHandler() { function setUpRedBoxErrorHandler() {
var ErrorUtils = require('ErrorUtils'); var ErrorUtils = require('ErrorUtils');
ErrorUtils.setGlobalHandler(handleError); ErrorUtils.setGlobalHandler(handleError);
@ -111,23 +136,23 @@ function setUpPromise() {
function setUpXHR() { function setUpXHR() {
// The native XMLHttpRequest in Chrome dev tools is CORS aware and won't // The native XMLHttpRequest in Chrome dev tools is CORS aware and won't
// let you fetch anything from the internet // let you fetch anything from the internet
GLOBAL.XMLHttpRequest = require('XMLHttpRequest'); polyfillGlobal('XMLHttpRequest', require('XMLHttpRequest'));
GLOBAL.FormData = require('FormData'); polyfillGlobal('FormData', require('FormData'));
var fetchPolyfill = require('fetch'); var fetchPolyfill = require('fetch');
GLOBAL.fetch = fetchPolyfill.fetch; polyfillGlobal('fetch', fetchPolyfill.fetch);
GLOBAL.Headers = fetchPolyfill.Headers; polyfillGlobal('Headers', fetchPolyfill.Headers);
GLOBAL.Request = fetchPolyfill.Request; polyfillGlobal('Request', fetchPolyfill.Request);
GLOBAL.Response = fetchPolyfill.Response; polyfillGlobal('Response', fetchPolyfill.Response);
} }
function setUpGeolocation() { function setUpGeolocation() {
GLOBAL.navigator = GLOBAL.navigator || {}; GLOBAL.navigator = GLOBAL.navigator || {};
GLOBAL.navigator.geolocation = require('Geolocation'); polyfillGlobal('geolocation', require('Geolocation'), GLOBAL.navigator);
} }
function setUpWebSockets() { function setUpWebSockets() {
GLOBAL.WebSocket = require('WebSocket'); polyfillGlobal('WebSocket', require('WebSocket'));
} }
function setUpProfile() { function setUpProfile() {