From c612d830bbc765a7acdf1ccd47f94934aead259f Mon Sep 17 00:00:00 2001 From: Ian MacLeod Date: Fri, 9 Oct 2015 14:39:24 -0700 Subject: [PATCH] Preserve original global properties when polyfilling them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .../InitializeJavaScriptAppEngine.js | 41 +++++++++++++++---- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js b/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js index fcd695abd..5a1015758 100644 --- a/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js +++ b/Libraries/JavaScriptAppEngine/Initialization/InitializeJavaScriptAppEngine.js @@ -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() { var ErrorUtils = require('ErrorUtils'); ErrorUtils.setGlobalHandler(handleError); @@ -111,23 +136,23 @@ function setUpPromise() { function setUpXHR() { // The native XMLHttpRequest in Chrome dev tools is CORS aware and won't // let you fetch anything from the internet - GLOBAL.XMLHttpRequest = require('XMLHttpRequest'); - GLOBAL.FormData = require('FormData'); + polyfillGlobal('XMLHttpRequest', require('XMLHttpRequest')); + polyfillGlobal('FormData', require('FormData')); var fetchPolyfill = require('fetch'); - GLOBAL.fetch = fetchPolyfill.fetch; - GLOBAL.Headers = fetchPolyfill.Headers; - GLOBAL.Request = fetchPolyfill.Request; - GLOBAL.Response = fetchPolyfill.Response; + polyfillGlobal('fetch', fetchPolyfill.fetch); + polyfillGlobal('Headers', fetchPolyfill.Headers); + polyfillGlobal('Request', fetchPolyfill.Request); + polyfillGlobal('Response', fetchPolyfill.Response); } function setUpGeolocation() { GLOBAL.navigator = GLOBAL.navigator || {}; - GLOBAL.navigator.geolocation = require('Geolocation'); + polyfillGlobal('geolocation', require('Geolocation'), GLOBAL.navigator); } function setUpWebSockets() { - GLOBAL.WebSocket = require('WebSocket'); + polyfillGlobal('WebSocket', require('WebSocket')); } function setUpProfile() {