@@ -37,7 +37,7 @@ import * as i18n from '../../../../core/i18n/i18n.js';
3737import * as SDK from '../../../../core/sdk/sdk.js' ;
3838import * as StackTrace from '../../../../models/stack_trace/stack_trace.js' ;
3939import * as Workspace from '../../../../models/workspace/workspace.js' ;
40- import { Directives , html , nothing , render } from '../../../lit/lit.js' ;
40+ import { Directives , html , nothing , render , type TemplateResult } from '../../../lit/lit.js' ;
4141import * as VisualLogging from '../../../visual_logging/visual_logging.js' ;
4242import * as UI from '../../legacy.js' ;
4343
@@ -107,19 +107,71 @@ export interface ViewInput {
107107export type View = ( input : ViewInput , output : object , target : HTMLElement ) => void ;
108108
109109export const DEFAULT_VIEW : View = ( input , output , target ) => {
110+ let renderExpandButton = Boolean ( input . expandable ) ;
111+ const maybeRenderExpandButton = ( ) : TemplateResult => {
112+ // clang-format off
113+ const result = html `
114+ ${ renderExpandButton ? html `
115+ < button class ="arrow-icon-button " jslog =${ VisualLogging . expand ( ) . track ( { click : true } ) } @click =${ input . onExpand } >
116+ < span class ="arrow-icon "> </ span >
117+ </ button >
118+ ` : '\n' } `;
119+ // clang-format on
120+ renderExpandButton = false ;
121+ return result ;
122+ } ;
123+
110124 const classes = {
111125 'stack-preview-container' : true ,
112126 'width-constrained' : Boolean ( input . widthConstrained ) ,
113127 expandable : Boolean ( input . expandable ) ,
114128 expanded : Boolean ( input . expanded ) ,
115129 'show-hidden-rows' : Boolean ( input . showIgnoreListed ) ,
116130 } ;
131+ const { stackTrace} = input ;
117132 // clang-format off
118133 render ( html `
119134 < style > ${ jsUtilsStyles } </ style >
120135 < table class =${ classMap ( classes ) } >
121- ${ renderStackTraceTable ( input ) }
122- ${ input . stackTrace ? html `
136+ ${ stackTrace ? html `
137+ ${ [ stackTrace . syncFragment , ...stackTrace . asyncFragments ] . map ( fragment => html `
138+ < tbody >
139+ ${ 'description' in fragment ? html `
140+ < tr class ="stack-preview-async-row ">
141+ < td > ${ maybeRenderExpandButton ( ) } </ td >
142+ < td class ="stack-preview-async-description ">
143+ ${ UI . UIUtils . asyncFragmentLabel ( stackTrace , fragment as StackTrace . StackTrace . AsyncFragment ) }
144+ </ td >
145+ < td > </ td >
146+ < td > </ td >
147+ </ tr >
148+ ` : nothing }
149+ ${ fragment . frames . map ( ( frame , i ) => {
150+ const previousStackFrameWasBreakpointCondition = i > 0 && [
151+ SDK . DebuggerModel . COND_BREAKPOINT_SOURCE_URL ,
152+ SDK . DebuggerModel . LOGPOINT_SOURCE_URL ,
153+ ] . includes ( fragment . frames [ i - 1 ] . url ?? '' ) ;
154+ const link = Linkifier . linkifyStackTraceFrame ( frame , {
155+ showColumnNumber : Boolean ( input . showColumnNumber ) ,
156+ tabStop : Boolean ( input . tabStops ) ,
157+ inlineFrameIndex : 0 ,
158+ revealBreakpoint : previousStackFrameWasBreakpointCondition ,
159+ maxLength : UI . UIUtils . MaxLengthForDisplayedURLsInConsole ,
160+ } ) ;
161+ link . setAttribute ( 'jslog' , `${ VisualLogging . link ( 'stack-trace' ) . track ( { click : true } ) } ` ) ;
162+ link . addEventListener ( 'contextmenu' , populateContextMenu . bind ( null , link ) ) ;
163+ return html `
164+ < tr >
165+ < td > ${ maybeRenderExpandButton ( ) } </ td >
166+ < td class ="function-name ">
167+ ${ UI . UIUtils . beautifyFunctionName ( frame . name ?? '' ) }
168+ </ td >
169+ < td > @ </ td >
170+ < td class ="link "> ${ link } </ td >
171+ </ tr >
172+ ` ; } ) }
173+ </ tbody >
174+ ` ) }
123175 < tfoot >
124176 < tr class ="show-all-link ">
125177 < td > </ td >
@@ -144,80 +196,6 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
144196 // clang-format on
145197} ;
146198
147- function renderStackTraceTable ( options : ViewInput ) : DocumentFragment {
148- const container = document . createDocumentFragment ( ) ;
149-
150- if ( ! options . stackTrace ) {
151- return container ;
152- }
153- const { stackTrace} = options ;
154-
155- function buildStackTraceRowsHelper ( fragment : StackTrace . StackTrace . Fragment | StackTrace . StackTrace . AsyncFragment ) :
156- Array < StackTraceRegularRow | StackTraceAsyncRow > {
157- const stackTraceRows : Array < StackTraceRegularRow | StackTraceAsyncRow > = [ ] ;
158- if ( 'description' in fragment ) {
159- stackTraceRows . push ( { asyncDescription : UI . UIUtils . asyncFragmentLabel ( stackTrace , fragment ) } ) ;
160- }
161- let previousStackFrameWasBreakpointCondition = false ;
162- for ( const frame of fragment . frames ) {
163- const functionName = UI . UIUtils . beautifyFunctionName ( frame . name ?? '' ) ;
164- const link = Linkifier . linkifyStackTraceFrame ( frame , {
165- showColumnNumber : Boolean ( options . showColumnNumber ) ,
166- tabStop : Boolean ( options . tabStops ) ,
167- inlineFrameIndex : 0 ,
168- revealBreakpoint : previousStackFrameWasBreakpointCondition ,
169- maxLength : UI . UIUtils . MaxLengthForDisplayedURLsInConsole ,
170- } ) ;
171- link . setAttribute ( 'jslog' , `${ VisualLogging . link ( 'stack-trace' ) . track ( { click : true } ) } ` ) ;
172- link . addEventListener ( 'contextmenu' , populateContextMenu . bind ( null , link ) ) ;
173-
174- stackTraceRows . push ( { functionName, link} ) ;
175- previousStackFrameWasBreakpointCondition = [
176- SDK . DebuggerModel . COND_BREAKPOINT_SOURCE_URL ,
177- SDK . DebuggerModel . LOGPOINT_SOURCE_URL ,
178- ] . includes ( frame . url ?? '' ) ;
179- }
180-
181- return stackTraceRows ;
182- }
183-
184- // The tableSection groups one or more synchronous call frames together.
185- // Wherever there is an asynchronous call, a new section is created.
186- let firstRow = true ;
187- for ( const fragment of [ stackTrace . syncFragment , ...stackTrace . asyncFragments ] ) {
188- if ( fragment . frames . length === 0 ) {
189- continue ;
190- }
191-
192- const stackTraceRows = buildStackTraceRowsHelper ( fragment ) ;
193- const tableSection = container . createChild ( 'tbody' ) ;
194- for ( const item of stackTraceRows ) {
195- const row = tableSection . createChild ( 'tr' ) ;
196- if ( firstRow && options . expandable ) {
197- const button = row . createChild ( 'td' ) . createChild ( 'button' , 'arrow-icon-button' ) ;
198- button . createChild ( 'span' , 'arrow-icon' ) ;
199- button . setAttribute ( 'jslog' , `${ VisualLogging . expand ( ) . track ( { click : true } ) } ` ) ;
200- button . addEventListener ( 'click' , options . onExpand ) ;
201- firstRow = false ;
202- } else {
203- row . createChild ( 'td' ) . textContent = '\n' ;
204- }
205- if ( 'asyncDescription' in item ) {
206- row . createChild ( 'td' , 'stack-preview-async-description' ) . textContent = item . asyncDescription ;
207- row . createChild ( 'td' ) ;
208- row . createChild ( 'td' ) ;
209- row . classList . add ( 'stack-preview-async-row' ) ;
210- } else {
211- row . createChild ( 'td' , 'function-name' ) . textContent = item . functionName ;
212- row . createChild ( 'td' ) . textContent = ' @ ' ;
213- row . createChild ( 'td' , 'link' ) . appendChild ( item . link ) ;
214- }
215- }
216- }
217-
218- return container ;
219- }
220-
221199export interface Options {
222200 tabStops ?: boolean ;
223201 // Whether the width of stack trace preview
@@ -228,15 +206,6 @@ export interface Options {
228206 expandable ?: boolean ;
229207}
230208
231- interface StackTraceRegularRow {
232- functionName : string ;
233- link : HTMLElement ;
234- }
235-
236- interface StackTraceAsyncRow {
237- asyncDescription : string ;
238- }
239-
240209export class StackTracePreviewContent extends UI . Widget . Widget {
241210 readonly #view: View ;
242211
0 commit comments