| # 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. |