diff --git a/Libraries/Core/Devtools/symbolicateStackTrace.js b/Libraries/Core/Devtools/symbolicateStackTrace.js index 7be076b3d..586034b47 100644 --- a/Libraries/Core/Devtools/symbolicateStackTrace.js +++ b/Libraries/Core/Devtools/symbolicateStackTrace.js @@ -14,7 +14,9 @@ const getDevServer = require('getDevServer'); const {SourceCode} = require('NativeModules'); -const {fetch} = require('fetch'); + +// Avoid requiring fetch on load of this module; see symbolicateStackTrace +let fetch; import type {StackFrame} from 'parseErrorStack'; @@ -23,6 +25,21 @@ function isSourcedFromDisk(sourcePath: string): boolean { } async function symbolicateStackTrace(stack: Array): Promise> { + // RN currently lazy loads whatwg-fetch using a custom fetch module, which, + // when called for the first time, requires and re-exports 'whatwg-fetch'. + // However, when a dependency of the project tries to require whatwg-fetch + // either directly or indirectly, whatwg-fetch is required before + // RN can lazy load whatwg-fetch. As whatwg-fetch checks + // for a fetch polyfill before loading, it will in turn try to load + // RN's fetch module, which immediately tries to import whatwg-fetch AGAIN. + // This causes a circular require which results in RN's fetch module + // exporting fetch as 'undefined'. + // The fix below postpones trying to load fetch until the first call to symbolicateStackTrace. + // At that time, we will have either global.fetch (whatwg-fetch) or RN's fetch. + if (!fetch) { + fetch = global.fetch || require('fetch').fetch; + } + const devServer = getDevServer(); if (!devServer.bundleLoadedFromServer) { throw new Error('Bundle was not loaded from the packager');