diff --git a/Libraries/Core/Devtools/symbolicateStackTrace.js b/Libraries/Core/Devtools/symbolicateStackTrace.js index 7a6b8cd80ceca7..cfb266c7339cdd 100644 --- a/Libraries/Core/Devtools/symbolicateStackTrace.js +++ b/Libraries/Core/Devtools/symbolicateStackTrace.js @@ -12,14 +12,9 @@ const getDevServer = require('./getDevServer'); -import NativeSourceCode from '../../NativeModules/specs/NativeSourceCode'; - -// Avoid requiring fetch on load of this module; see symbolicateStackTrace -let fetch; - import type {StackFrame} from '../NativeExceptionsManager'; -export type CodeFrame = $ReadOnly<{| +export type CodeFrame = $ReadOnly<{ content: string, location: ?{ row: number, @@ -27,68 +22,26 @@ export type CodeFrame = $ReadOnly<{| ... }, fileName: string, -|}>; +}>; -export type SymbolicatedStackTrace = $ReadOnly<{| +export type SymbolicatedStackTrace = $ReadOnly<{ stack: Array, codeFrame: ?CodeFrame, -|}>; - -function isSourcedFromDisk(sourcePath: string): boolean { - return !/^http/.test(sourcePath) && /[\\/]/.test(sourcePath); -} +}>; 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) { - // flowlint-next-line untyped-import:off - fetch = global.fetch || require('../../Network/fetch').fetch; - } - const devServer = getDevServer(); if (!devServer.bundleLoadedFromServer) { - throw new Error('Bundle was not loaded from the packager'); - } - - let stackCopy = stack; - - const {scriptURL} = NativeSourceCode.getConstants(); - if (scriptURL) { - let foundInternalSource: boolean = false; - stackCopy = stack.map((frame: StackFrame) => { - if (frame.file == null) { - return frame; - } - - // If the sources exist on disk rather than appearing to come from the packager, - // replace the location with the packager URL until we reach an internal source - // which does not have a path (no slashes), indicating a switch from within - // the application to a surrounding debugging environment. - if (!foundInternalSource && isSourcedFromDisk(frame.file)) { - // Copy frame into new object and replace 'file' property - return {...frame, file: scriptURL}; - } - - foundInternalSource = true; - return frame; - }); + throw new Error('Bundle was not loaded from Metro.'); } + // Lazy-load `fetch` until the first symbolication call to avoid circular requires. + const fetch = global.fetch ?? require('../../Network/fetch'); const response = await fetch(devServer.url + 'symbolicate', { method: 'POST', - body: JSON.stringify({stack: stackCopy}), + body: JSON.stringify({stack}), }); return await response.json(); } diff --git a/Libraries/Network/fetch.js b/Libraries/Network/fetch.js index 65a02b9ee4d428..6ebb79c2ca51aa 100644 --- a/Libraries/Network/fetch.js +++ b/Libraries/Network/fetch.js @@ -4,6 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * + * @flow strict * @format */