1717 * 2. Bridged modules.
1818 *
1919 * @providesModule InitializeJavaScriptAppEngine
20+ * @flow
2021 */
2122
2223/* eslint strict: 0 */
2324/* globals window: true */
2425
2526require ( 'regenerator-runtime/runtime' ) ;
2627
27- if ( typeof GLOBAL === ' undefined' ) {
28+ if ( global . GLOBAL === undefined ) {
2829 global . GLOBAL = global ;
2930}
3031
31- if ( typeof window === ' undefined' ) {
32+ if ( global . window === undefined ) {
3233 global . window = global ;
3334}
3435
35- function setUpProcess ( ) {
36+ function setUpProcess ( ) : void {
3637 global . process = global . process || { } ;
3738 global . process . env = global . process . env || { } ;
3839 if ( ! global . process . env . NODE_ENV ) {
3940 global . process . env . NODE_ENV = __DEV__ ? 'development' : 'production' ;
4041 }
4142}
4243
43- function setUpProfile ( ) {
44+ function setUpProfile ( ) : void {
4445 const Systrace = require ( 'Systrace' ) ;
4546 Systrace . setEnabled ( global . __RCTProfileIsProfiling || false ) ;
4647}
4748
48- function setUpConsole ( ) {
49+ function setUpConsole ( ) : void {
4950 // ExceptionsManager transitively requires Promise so we install it after
5051 const ExceptionsManager = require ( 'ExceptionsManager' ) ;
5152 ExceptionsManager . installConsoleErrorReporter ( ) ;
@@ -56,58 +57,56 @@ function setUpConsole() {
5657}
5758
5859/**
59- * Assigns a new global property, replacing the existing one if there is one.
60+ * Sets an object's property. If a property with the same name exists, this will
61+ * replace it but maintain its descriptor configuration.
6062 *
61- * Existing properties are preserved as `originalPropertyName`. Both properties
62- * will maintain the same enumerability & configurability.
63+ * The original property value will be preserved as `original[PropertyName]` so
64+ * that, if necessary, it can be restored. For example, if you want to route
65+ * network requests through DevTools (to trace them):
6366 *
64- * This allows you to undo the more aggressive polyfills, should you need to.
65- * For example, if you want to route network requests through DevTools (to trace
66- * them):
67+ * global.XMLHttpRequest = global.originalXMLHttpRequest;
6768 *
68- * global.XMLHttpRequest = global.originalXMLHttpRequest;
69- *
70- * For more info on that particular case, see:
71- * https://github.com/facebook/react-native/issues/934
69+ * @see https://github.com/facebook/react-native/issues/934
7270 */
73- function polyfillGlobal ( name , newValue , scope = global ) {
74- const descriptor = Object . getOwnPropertyDescriptor ( scope , name ) ;
71+ function defineProperty ( object : Object , name : string , newValue : mixed ) : void {
72+ const descriptor = Object . getOwnPropertyDescriptor ( object , name ) ;
7573 if ( descriptor ) {
7674 const backupName = `original${ name [ 0 ] . toUpperCase ( ) } ${ name . substr ( 1 ) } ` ;
77- Object . defineProperty ( scope , backupName , { ...descriptor , value : scope [ name ] } ) ;
75+ Object . defineProperty ( object , backupName , {
76+ ...descriptor ,
77+ value : object [ name ] ,
78+ } ) ;
7879 }
7980
8081 const { enumerable, writable} = descriptor || { } ;
81-
82- // jest for some bad reasons runs the polyfill code multiple times. In jest
83- // environment, XmlHttpRequest doesn't exist so getOwnPropertyDescriptor
84- // returns undefined and defineProperty default for writable is false.
85- // Therefore, the second time it runs, defineProperty will fatal :(
86-
87- Object . defineProperty ( scope , name , {
82+ Object . defineProperty ( object , name , {
8883 configurable : true ,
8984 enumerable : enumerable !== false ,
9085 writable : writable !== false ,
9186 value : newValue ,
9287 } ) ;
9388}
9489
95- function polyfillLazyGlobal ( name , valueFn , scope = global ) {
96- const descriptor = getPropertyDescriptor ( scope , name ) ;
90+ function defineLazyProperty (
91+ object : Object ,
92+ name : string ,
93+ getValue : ( ) = > mixed
94+ ) : void {
95+ const descriptor = getPropertyDescriptor ( object , name ) ;
9796 if ( descriptor ) {
9897 const backupName = `original${ name [ 0 ] . toUpperCase ( ) } ${ name . substr ( 1 ) } ` ;
99- Object . defineProperty ( scope , backupName , descriptor ) ;
98+ Object . defineProperty ( object , backupName , descriptor ) ;
10099 }
101100
102101 const { enumerable, writable} = descriptor || { } ;
103- Object . defineProperty ( scope , name , {
102+ Object . defineProperty ( object , name , {
104103 configurable : true ,
105104 enumerable : enumerable !== false ,
106105 get ( ) {
107- return ( global [ name ] = valueFn ( ) ) ;
106+ return ( object [ name ] = getValue ( ) ) ;
108107 } ,
109108 set ( value ) {
110- Object . defineProperty ( global , name , {
109+ Object . defineProperty ( object , name , {
111110 configurable : true ,
112111 enumerable : enumerable !== false ,
113112 writable : writable !== false ,
@@ -117,16 +116,7 @@ function polyfillLazyGlobal(name, valueFn, scope = global) {
117116 } ) ;
118117}
119118
120- /**
121- * Polyfill a module if it is not already defined in `scope`.
122- */
123- function polyfillIfNeeded ( name , polyfill , scope = global , descriptor = { } ) {
124- if ( scope [ name ] === undefined ) {
125- Object . defineProperty ( scope , name , { ...descriptor , value : polyfill } ) ;
126- }
127- }
128-
129- function setUpErrorHandler ( ) {
119+ function setUpErrorHandler ( ) : void {
130120 if ( global . __fbDisableExceptionsManager ) {
131121 return ;
132122 }
@@ -135,7 +125,9 @@ function setUpErrorHandler() {
135125 try {
136126 require ( 'ExceptionsManager' ) . handleException ( e , isFatal ) ;
137127 } catch ( ee ) {
128+ /* eslint-disable no-console-disallow */
138129 console . log ( 'Failed to print error: ' , ee . message ) ;
130+ /* eslint-enable no-console-disallow */
139131 throw e ;
140132 }
141133 }
@@ -151,9 +143,9 @@ function setUpErrorHandler() {
151143 * implement our own custom timing bridge that should be immune to
152144 * unexplainably dropped timing signals.
153145 */
154- function setUpTimers ( ) {
155- const defineLazyTimer = ( name ) => {
156- polyfillLazyGlobal ( name , ( ) => require ( 'JSTimers' ) [ name ] ) ;
146+ function setUpTimers ( ) : void {
147+ const defineLazyTimer = name => {
148+ defineLazyProperty ( global , name , ( ) => require ( 'JSTimers' ) [ name ] ) ;
157149 } ;
158150 defineLazyTimer ( 'setTimeout' ) ;
159151 defineLazyTimer ( 'setInterval' ) ;
@@ -165,7 +157,7 @@ function setUpTimers() {
165157 defineLazyTimer ( 'cancelAnimationFrame' ) ;
166158}
167159
168- function setUpAlert ( ) {
160+ function setUpAlert ( ) : void {
169161 if ( ! global . alert ) {
170162 global . alert = function ( text ) {
171163 // Require Alert on demand. Requiring it too early can lead to issues
@@ -175,45 +167,48 @@ function setUpAlert() {
175167 }
176168}
177169
178- function setUpPromise ( ) {
170+ function setUpPromise ( ) : void {
179171 // The native Promise implementation throws the following error:
180172 // ERROR: Event loop not supported.
181- polyfillLazyGlobal ( 'Promise' , ( ) => require ( 'Promise' ) ) ;
173+ defineLazyProperty ( global , 'Promise' , ( ) => require ( 'Promise' ) ) ;
182174}
183175
184- function setUpXHR ( ) {
176+ function setUpXHR ( ) : void {
185177 // The native XMLHttpRequest in Chrome dev tools is CORS aware and won't
186178 // let you fetch anything from the internet
187- polyfillLazyGlobal ( 'XMLHttpRequest' , ( ) => require ( 'XMLHttpRequest' ) ) ;
188- polyfillLazyGlobal ( 'FormData' , ( ) => require ( 'FormData' ) ) ;
179+ defineLazyProperty ( global , 'XMLHttpRequest' , ( ) => require ( 'XMLHttpRequest' ) ) ;
180+ defineLazyProperty ( global , 'FormData' , ( ) => require ( 'FormData' ) ) ;
189181
190- polyfillLazyGlobal ( 'fetch' , ( ) => require ( 'fetch' ) . fetch ) ;
191- polyfillLazyGlobal ( 'Headers' , ( ) => require ( 'fetch' ) . Headers ) ;
192- polyfillLazyGlobal ( 'Request' , ( ) => require ( 'fetch' ) . Request ) ;
193- polyfillLazyGlobal ( 'Response' , ( ) => require ( 'fetch' ) . Response ) ;
182+ defineLazyProperty ( global , 'fetch' , ( ) => require ( 'fetch' ) . fetch ) ;
183+ defineLazyProperty ( global , 'Headers' , ( ) => require ( 'fetch' ) . Headers ) ;
184+ defineLazyProperty ( global , 'Request' , ( ) => require ( 'fetch' ) . Request ) ;
185+ defineLazyProperty ( global , 'Response' , ( ) => require ( 'fetch' ) . Response ) ;
194186
195- polyfillLazyGlobal ( 'WebSocket' , ( ) => require ( 'WebSocket' ) ) ;
187+ defineLazyProperty ( global , 'WebSocket' , ( ) => require ( 'WebSocket' ) ) ;
196188}
197189
198- function setUpGeolocation ( ) {
199- polyfillIfNeeded ( 'navigator' , { } , global , {
200- writable : true ,
201- enumerable : true ,
202- configurable : true ,
203- } ) ;
204- Object . defineProperty ( global . navigator , 'product' , { value : 'ReactNative' } ) ;
205-
206- polyfillLazyGlobal ( 'geolocation' , ( ) => require ( 'Geolocation' ) , global . navigator ) ;
190+ function setUpGeolocation ( ) : void {
191+ if ( global . navigator === undefined ) {
192+ Object . defineProperty ( global , 'navigator' , {
193+ configurable : true ,
194+ enumerable : true ,
195+ writable : true ,
196+ value : { } ,
197+ } ) ;
198+ }
199+ const { navigator } = global ;
200+ Object . defineProperty ( navigator , 'product' , { value : 'ReactNative' } ) ;
201+ defineLazyProperty ( navigator , 'geolocation' , ( ) => require ( 'Geolocation' ) ) ;
207202}
208203
209- function setUpMapAndSet ( ) {
210- // We can't make these lazy as Map checks the global.Map to see if it's
211- // available but in our case it'll be a lazy getter .
212- polyfillGlobal ( 'Map' , require ( 'Map' ) ) ;
213- polyfillGlobal ( 'Set' , require ( 'Set' ) ) ;
204+ function setUpCollections ( ) : void {
205+ // We can't make these lazy because ` Map` checks for ` global.Map` (which would
206+ // not exist if it were lazily defined) .
207+ defineProperty ( global , 'Map' , require ( 'Map' ) ) ;
208+ defineProperty ( global , 'Set' , require ( 'Set' ) ) ;
214209}
215210
216- function setUpDevTools ( ) {
211+ function setUpDevTools ( ) : void {
217212 if ( __DEV__ ) {
218213 // not when debugging in chrome
219214 if ( ! window . document && require ( 'Platform' ) . OS === 'ios' ) {
@@ -226,7 +221,7 @@ function setUpDevTools() {
226221 }
227222}
228223
229- function getPropertyDescriptor ( object , name ) {
224+ function getPropertyDescriptor ( object : Object , name : string ) : any {
230225 while ( object ) {
231226 const descriptor = Object . getOwnPropertyDescriptor ( object , name ) ;
232227 if ( descriptor ) {
@@ -245,7 +240,7 @@ setUpPromise();
245240setUpErrorHandler ( ) ;
246241setUpXHR ( ) ;
247242setUpGeolocation ( ) ;
248- setUpMapAndSet ( ) ;
243+ setUpCollections ( ) ;
249244setUpDevTools ( ) ;
250245
251246// Just to make sure the JS gets packaged up. Wait until the JS environment has
0 commit comments