diff --git a/front_end/core/host/RNPerfMetrics.ts b/front_end/core/host/RNPerfMetrics.ts index 207e5cabe75d..07b50d7aa7a3 100644 --- a/front_end/core/host/RNPerfMetrics.ts +++ b/front_end/core/host/RNPerfMetrics.ts @@ -259,6 +259,17 @@ class RNPerfMetrics { }); } + stackTraceSymbolicationFailed(stackTrace: string, line: string, reason: string): void { + this.sendEvent({ + eventName: 'StackTraceSymbolicationFailed', + params: { + stackTrace, + line, + reason, + }, + }); + } + panelShown(_panelName: string, _isLaunching?: boolean): void { // no-op // We only care about the "main" and "drawer" panels for now via panelShownInLocation(…) @@ -423,10 +434,19 @@ export type PanelClosedEvent = Readonly<{ }>, }>; +export type StackTraceSymbolicationFailed = Readonly<{ + eventName: 'StackTraceSymbolicationFailed', + params: Readonly<{ + stackTrace: string, + line: string, + reason: string, + }>, +}>; + export type ReactNativeChromeDevToolsEvent = EntrypointLoadingStartedEvent|EntrypointLoadingFinishedEvent|DebuggerReadyEvent|BrowserVisibilityChangeEvent| BrowserErrorEvent|RemoteDebuggingTerminatedEvent|DeveloperResourceLoadingStartedEvent| DeveloperResourceLoadingFinishedEvent|FuseboxSetClientMetadataStartedEvent|FuseboxSetClientMetadataFinishedEvent| - MemoryPanelActionStartedEvent|MemoryPanelActionFinishedEvent|PanelShownEvent|PanelClosedEvent; + MemoryPanelActionStartedEvent|MemoryPanelActionFinishedEvent|PanelShownEvent|PanelClosedEvent|StackTraceSymbolicationFailed; export type DecoratedReactNativeChromeDevToolsEvent = CommonEventFields&ReactNativeChromeDevToolsEvent; diff --git a/front_end/panels/console/ErrorStackParser.ts b/front_end/panels/console/ErrorStackParser.ts index 2842f57d5daf..402150a3463c 100644 --- a/front_end/panels/console/ErrorStackParser.ts +++ b/front_end/panels/console/ErrorStackParser.ts @@ -3,6 +3,7 @@ // found in the LICENSE file. import * as Common from '../../core/common/common.js'; +import * as Host from '../../core/host/host.js'; import type * as Platform from '../../core/platform/platform.js'; import type * as SDK from '../../core/sdk/sdk.js'; import type * as Protocol from '../../generated/protocol.js'; @@ -43,6 +44,7 @@ export function parseSourcePositionsFromErrorStack( const match = /^\s*at\s(async\s)?/.exec(line); if (!match) { if (linkInfos.length && linkInfos[linkInfos.length - 1].isCallFrame) { + Host.rnPerfMetrics.stackTraceSymbolicationFailed(stack, line, '"at (url)" not found'); return null; } linkInfos.push({line}); @@ -59,6 +61,7 @@ export function parseSourcePositionsFromErrorStack( do { left = line.indexOf(' (', left); if (left < 0) { + Host.rnPerfMetrics.stackTraceSymbolicationFailed(stack, line, 'left "(" not found'); return null; } left += 2; @@ -68,6 +71,7 @@ export function parseSourcePositionsFromErrorStack( left += 8; right = line.lastIndexOf(', ', right) - 1; if (right < 0) { + Host.rnPerfMetrics.stackTraceSymbolicationFailed(stack, line, 'right "(" not found'); return null; } } while (true); @@ -89,6 +93,7 @@ export function parseSourcePositionsFromErrorStack( url = parseOrScriptMatch(debuggerModel, Common.ParsedURL.ParsedURL.completeURL(baseURL, splitResult.url)); } if (!url) { + Host.rnPerfMetrics.stackTraceSymbolicationFailed(stack, line, 'url parsing failed'); return null; }