From be5e300abf9aee0f471c08f80d515c2b6f221eeb Mon Sep 17 00:00:00 2001 From: Hilke Heremans Date: Mon, 14 Nov 2016 09:09:34 -0800 Subject: [PATCH] Fix symbolication on stack trace with whatwg-fetch as a dependency Summary: This PR provides a workaround for issue #9605 which affects projects which directly or indirectly require `whatwg-fetch`. At that point, all symbolication on stack trace errors fails due to a circular require caused by RN's lazy loading of `fetch`, which results in `fetch` becoming `undefined`. The workaround is simple: we postpone requiring `fetch` until the first `symbolicateStackTrace` call, at which point we can be certain `fetch` is properly exported. It is then cached for future use. No tests have been added since, apparently, this module did not have any tests to begin with. Manual tests were performed on a regular project (not including `whatwg-fetch` externally) and a project that has direct and indirect includes for `whatwg-fetch`. Closes https://github.com/facebook/react-native/pull/10247 Differential Revision: D4175835 Pulled By: hramos fbshipit-source-id: d849a5874373e76f166ea6ab23f0f888792d1aef --- .../Core/Devtools/symbolicateStackTrace.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) 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');