blob: 203f99eec307438eee8d7040b37273a972e1814c [file] [view] [edit]
# Utilizing Source Maps in DevTools
This document describes how to utilize source maps and translate raw runtime
locations into original source locations inside the DevTools frontend.
DevTools provides a set of high-level abstractions and UI widgets to parse,
symbolize, and render stack traces and errors. Prefer these tools
over manual coordinate translation or raw string parsing.
---
## Central Coordinate Translation: DebuggerWorkspaceBinding
The `DebuggerWorkspaceBinding` class (located in `front_end/models/bindings/`)
acts as the central coordinator for mapping compiled/raw runtime coordinates
to workspace/UI locations. It manages various source mappings (such as source
maps, compiler mappings, and language plugins).
### Translating Raw Locations
To convert a single raw debugger location (with a script ID, line number, and
column number) into an original source location, use:
```ts
const uiLocation = await DebuggerWorkspaceBinding.instance()
.rawLocationToUILocation(rawLocation);
```
Since source maps may need to be loaded or parsed, this method returns a
`Promise` resolving to `Workspace.UISourceCode.UILocation | null`.
---
## Structured Stack Trace Abstractions
The project organizes stack traces and errors around two primary models:
### 1. StackTrace
Located in `front_end/models/stack_trace/`, a `StackTrace` represents a
structured stack trace. It is composed of:
- **`syncFragment`** (`Fragment`): The synchronous part of the call stack.
- **`asyncFragments`** (`AsyncFragment[]`): Asynchronous call stack segments,
each with a description (e.g., "Promise.then") and its own frames.
Each frame (`Frame`) contains properties like `url`, `uiSourceCode`, `name`
(translated name), `rawName` (untranslated name), `line`, `column`, and flags
indicating if the frame `isInline`, `isWasm`, or has `missingDebugInfo`.
#### Creating a StackTrace
`DebuggerWorkspaceBinding` provides several helpers depending on your source
format:
* **From CDP Protocol Stack Trace**:
```ts
const stackTrace = await DebuggerWorkspaceBinding.instance()
.createStackTraceFromProtocolRuntime(protocolStackTrace, target);
```
* **From Debugger Pause Event**:
```ts
const stackTrace = await DebuggerWorkspaceBinding.instance()
.createStackTraceFromDebuggerPaused(pausedDetails, target);
```
* **From an Error-Like Stack String**:
```ts
const stackTrace = await DebuggerWorkspaceBinding.instance()
.createStackTraceFromErrorStackLikeString(target, stackString, exceptionDetails);
```
---
### 2. SymbolizedError
Located in `front_end/models/bindings/SymbolizedError.ts`, `SymbolizedError` is
a union type of `SymbolizedErrorObject` and `UnparsableError`. It represents a
fully parsed and symbolized Error object.
* **`SymbolizedErrorObject`**: Contains the parsed error message (`message`),
the parsed `ParsedErrorStackTrace` (`stackTrace`), and an optional `cause`
(`SymbolizedError`), which allows recursive representation of chained
errors. It also handles special cases like compile-time or eval-time
`SyntaxError`s, exposing a `syntaxErrorLocation` pointing directly to where
the parse failed.
* **`UnparsableError`**: A fallback representation for stack traces that
cannot be structurally parsed.
#### Creating a SymbolizedError
To resolve a `RemoteObject` (of subtype `error` or type `string`) into a
symbolized representation:
```ts
const symbolizedError = await DebuggerWorkspaceBinding.instance()
.createSymbolizedError(remoteObject, exceptionDetails);
```
> **Memory Management Note:** Both `StackTrace` and `SymbolizedError` models
> listen to live location updates and must be properly `dispose()`d when no
> longer used to prevent memory leaks.
---
## UI Widgets
To render the above models in the DevTools UI, you should use the following
pre-built widgets instead of constructing your own custom tables or lists:
### 1. StackTracePreviewContent
Located in `front_end/ui/legacy/components/utils/JSPresentationUtils.ts`, this
widget renders a structured `StackTrace` inside a shadow DOM. It automatically
handles collapsible sections (expanded/collapsed) and ignore-listed files or
folders.
#### Usage:
```ts
import * as Components from '../../ui/legacy/components/utils/utils.js';
import * as Workspace from '../../models/workspace/workspace.js';
const preview = new Components.JSPresentationUtils.StackTracePreviewContent();
preview.stackTrace = stackTrace;
preview.options = {
expandable: true,
showColumnNumber: true,
ignoreListManager: Workspace.IgnoreListManager.IgnoreListManager.instance(),
};
```
---
### 2. SymbolizedErrorWidget
Located in `front_end/panels/console/SymbolizedErrorWidget.ts`, this widget is
designed to display a complete `SymbolizedError`, including its parsed message,
any nested `cause` errors (rendered recursively with "Caused by:"), and links for
syntax error locations.
#### Usage:
```ts
import * as Panels from '../../panels/panels.js';
import * as Workspace from '../../models/workspace/workspace.js';
const errorWidget = new Panels.Console.SymbolizedErrorWidget();
errorWidget.error = symbolizedError;
errorWidget.ignoreListManager = Workspace.IgnoreListManager.IgnoreListManager
.instance();
```
---
## Reaching Out
If none of the existing methods, abstractions, or widgets cover your specific
use-case, or if you need additional capabilities for coordinate/stack trace
symbolization, please **reach out to the DevTools team**. Do not roll your
own coordinate mapping or raw string parsing logic.