From 0fe1c7a9ff84bb0d49a0fbe3de3d09d89bf1a785 Mon Sep 17 00:00:00 2001 From: James Ide Date: Tue, 1 Nov 2016 02:58:10 -0700 Subject: [PATCH] Fix symbolication failure caused by attempt to modify frozen frame Summary: This change makes so that processing stack trace before sending it to packager (see 7dbc805) doesn't modify original frames but creates a copies instead. This is required because after some changes that also have been landed in 0.35, frames that arrive to 'symbolicateStackTrace' are already frozen, so changing 'file' property of the original frame causes symbolication to fail. Closes https://github.com/facebook/react-native/pull/10655 Differential Revision: D4110273 fbshipit-source-id: 0302694b520d83a79c3cb67903038b3f494315f2 --- .../Core/Devtools/symbolicateStackTrace.js | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/Libraries/Core/Devtools/symbolicateStackTrace.js b/Libraries/Core/Devtools/symbolicateStackTrace.js index 2e544149d7e..7be076b3de3 100644 --- a/Libraries/Core/Devtools/symbolicateStackTrace.js +++ b/Libraries/Core/Devtools/symbolicateStackTrace.js @@ -18,27 +18,38 @@ const {fetch} = require('fetch'); import type {StackFrame} from 'parseErrorStack'; +function isSourcedFromDisk(sourcePath: string): boolean { + return !/^http/.test(sourcePath) && /[\\/]/.test(sourcePath); +} + async function symbolicateStackTrace(stack: Array): Promise> { const devServer = getDevServer(); if (!devServer.bundleLoadedFromServer) { throw new Error('Bundle was not loaded from the packager'); } + + let stackCopy = stack; + if (SourceCode.scriptURL) { - for (let i = 0; i < stack.length; ++i) { + let foundInternalSource: boolean = false; + stackCopy = stack.map((frame: StackFrame) => { // 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 (/^http/.test(stack[i].file) || !/[\\/]/.test(stack[i].file)) { - break; + if (!foundInternalSource && isSourcedFromDisk(frame.file)) { + // Copy frame into new object and replace 'file' property + return {...frame, file: SourceCode.scriptURL}; } - stack[i].file = SourceCode.scriptURL; - } + + foundInternalSource = true; + return frame; + }); } const response = await fetch(devServer.url + 'symbolicate', { method: 'POST', - body: JSON.stringify({stack}), + body: JSON.stringify({stack: stackCopy}), }); const json = await response.json(); return json.stack;