blob: 741703848f8bb4b893b6d12d526b8a3fc33a099a [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import type * as Common from '../../core/common/common.js';
import type * as SDK from '../../core/sdk/sdk.js';
import type * as Workspace from '../workspace/workspace.js';
export type StackTrace = BaseStackTrace<Fragment>;
export type DebuggableStackTrace = BaseStackTrace<DebuggableFragment>;
export interface BaseStackTrace<SyncFragmentT extends Fragment> extends Common.EventTarget.EventTarget<EventTypes> {
readonly syncFragment: SyncFragmentT;
readonly asyncFragments: readonly AsyncFragment[];
}
export interface Fragment {
readonly frames: readonly Frame[];
}
export interface AsyncFragment extends Fragment {
readonly description: string;
}
export interface DebuggableFragment {
readonly frames: readonly DebuggableFrame[];
}
export interface Frame {
readonly url?: string;
readonly uiSourceCode?: Workspace.UISourceCode.UISourceCode;
readonly name?: string;
readonly line: number;
readonly column: number;
readonly missingDebugInfo?: MissingDebugInfo;
}
export interface DebuggableFrame extends Frame {
readonly sdkFrame: SDK.DebuggerModel.CallFrame;
}
export const enum MissingDebugInfoType {
/** No debug information at all for the call frame */
NO_INFO = 'NO_INFO',
/** Some debug information available, but it references files with debug information we were not able to retrieve */
PARTIAL_INFO = 'PARTIAL_INFO',
}
export type MissingDebugInfo = {
type: MissingDebugInfoType.NO_INFO,
}|{
type: MissingDebugInfoType.PARTIAL_INFO,
missingDebugFiles: SDK.DebuggerModel.MissingDebugFiles[],
};
export const enum Events {
UPDATED = 'UPDATED',
}
export interface EventTypes {
[Events.UPDATED]: void;
}
/**
* A small wrapper around a DebuggableFrame usable as a UI.Context flavor.
* This is necessary as DebuggableFrame are just interfaces and the impl classes are hidden.
*
* Moreover, re-translation creates a new DebuggableFrame instance even though the
* translation result stays the same, in which case we don't need a new instance for the flavor.
*/
export class DebuggableFrameFlavor {
static #last?: DebuggableFrameFlavor;
readonly frame: DebuggableFrame;
// TODO(crbug.com/465879478): Remove once this is no longer part of SDK.CallFrame.
// We need to stash this separately because DebuggerModel sets this on CallFrame after the
// fact so we can't just check it in the `equals` below.
readonly #missingDebugInfo: SDK.DebuggerModel.MissingDebugInfo|null;
/** Use the static {@link for}. Only public to satisfy the `setFlavor` Ctor type */
constructor(frame: DebuggableFrame) {
this.frame = frame;
this.#missingDebugInfo = frame.sdkFrame.missingDebugInfoDetails;
}
get sdkFrame(): SDK.DebuggerModel.CallFrame {
return this.frame.sdkFrame;
}
/** @returns the same instance of DebuggableFrameFlavor for repeated calls with the same (i.e. deep equal) DebuggableFrame */
static for(frame: DebuggableFrame): DebuggableFrameFlavor {
function equals(a: DebuggableFrame, b: DebuggableFrame): boolean {
return a.url === b.url && a.uiSourceCode === b.uiSourceCode && a.name === b.name && a.line === b.line &&
a.column === b.column && a.sdkFrame === b.sdkFrame;
}
if (!DebuggableFrameFlavor.#last || !equals(DebuggableFrameFlavor.#last.frame, frame) ||
DebuggableFrameFlavor.#last.#missingDebugInfo !== frame.sdkFrame.missingDebugInfoDetails) {
DebuggableFrameFlavor.#last = new DebuggableFrameFlavor(frame);
}
return DebuggableFrameFlavor.#last;
}
}