@@ -26,6 +26,7 @@ type thread struct {
2626 idPool * idPool
2727 sourceMap * sourceMap
2828 breakpointMap * breakpointMap
29+ variables * variableReferences
2930
3031 // Inputs to the evaluate call.
3132 c gateway.Client
@@ -48,11 +49,10 @@ type thread struct {
4849 mu sync.Mutex
4950
5051 // Attributes set when a thread is paused.
51- rCtx * build.ResultHandle
52- curPos digest.Digest
53-
54- // Lazy attributes that are set when a thread is paused.
55- stackTrace []dap.StackFrame
52+ rCtx * build.ResultHandle
53+ curPos digest.Digest
54+ stackTrace []int32
55+ frames map [int32 ]* frame
5656}
5757
5858type region struct {
@@ -154,6 +154,7 @@ func (t *thread) pause(c Context, err error, event dap.StoppedEventBody) <-chan
154154 }
155155 }
156156 }
157+ t .collectStackTrace ()
157158
158159 event .ThreadId = t .id
159160 c .C () <- & dap.StoppedEvent {
@@ -178,18 +179,7 @@ func (t *thread) resume(step stepType) {
178179 if t .paused == nil {
179180 return
180181 }
181-
182- if t .rCtx != nil {
183- t .rCtx .Done ()
184- t .rCtx = nil
185- }
186-
187- if t .stackTrace != nil {
188- for _ , frame := range t .stackTrace {
189- t .idPool .Put (int64 (frame .Id ))
190- }
191- t .stackTrace = nil
192- }
182+ t .releaseState ()
193183
194184 t .paused <- step
195185 close (t .paused )
@@ -207,10 +197,23 @@ func (t *thread) StackTrace() []dap.StackFrame {
207197 return []dap.StackFrame {}
208198 }
209199
210- if t .stackTrace == nil {
211- t .stackTrace = t .makeStackTrace ()
200+ frames := make ([]dap.StackFrame , len (t .stackTrace ))
201+ for i , id := range t .stackTrace {
202+ frames [i ] = t .frames [id ].StackFrame
212203 }
213- return t .stackTrace
204+ return frames
205+ }
206+
207+ func (t * thread ) Scopes (frameID int ) []dap.Scope {
208+ t .mu .Lock ()
209+ defer t .mu .Unlock ()
210+
211+ frame := t .frames [int32 (frameID )]
212+ return frame .Scopes ()
213+ }
214+
215+ func (t * thread ) Variables (id int ) []dap.Variable {
216+ return t .variables .Get (id )
214217}
215218
216219func (t * thread ) getLLBState (ctx Context ) error {
@@ -502,15 +505,16 @@ func (t *thread) solve(ctx context.Context, target digest.Digest) (gateway.Refer
502505 return res .SingleRef ()
503506}
504507
505- func (t * thread ) newStackFrame () dap.StackFrame {
506- return dap.StackFrame {
507- Id : int (t .idPool .Get ()),
508+ func (t * thread ) releaseState () {
509+ if t .rCtx != nil {
510+ t .rCtx .Done ()
511+ t .rCtx = nil
508512 }
513+ t .stackTrace = nil
514+ t .frames = nil
509515}
510516
511- func (t * thread ) makeStackTrace () []dap.StackFrame {
512- var frames []dap.StackFrame
513-
517+ func (t * thread ) collectStackTrace () {
514518 region := t .regionsByDigest [t .curPos ]
515519 r := t .regions [region ]
516520
@@ -519,45 +523,38 @@ func (t *thread) makeStackTrace() []dap.StackFrame {
519523 digests = digests [:index + 1 ]
520524 }
521525
526+ t .frames = make (map [int32 ]* frame )
522527 for i := len (digests ) - 1 ; i >= 0 ; i -- {
523528 dgst := digests [i ]
524529
525- frame := t .newStackFrame ()
530+ frame := & frame {}
531+ frame .Id = int (t .idPool .Get ())
532+
526533 if meta , ok := t .def .Metadata [dgst ]; ok {
527- fillStackFrameMetadata ( & frame , meta )
534+ frame . setNameFromMeta ( meta )
528535 }
529536 if loc , ok := t .def .Source .Locations [string (dgst )]; ok {
530- t . fillStackFrameLocation ( & frame , loc )
537+ frame . fillLocation ( t . def , loc , t . sourcePath )
531538 }
532- frames = append (frames , frame )
533- }
534- return frames
535- }
536539
537- func fillStackFrameMetadata ( frame * dap. StackFrame , meta llb. OpMetadata ) {
538- if name , ok := meta . Description [ "llb.customname" ]; ok {
539- frame . Name = name
540- } else if cmd , ok := meta . Description [ "com.docker.dockerfile.v1.command" ]; ok {
541- frame .Name = cmd
540+ if op := t . ops [ dgst ]; op != nil {
541+ frame . fillVarsFromOp ( op , t . variables )
542+ }
543+ t . stackTrace = append ( t . stackTrace , int32 ( frame . Id ))
544+ t . frames [ int32 ( frame .Id )] = frame
542545 }
543- // TODO: should we infer the name from somewhere else?
544546}
545547
546- func (t * thread ) fillStackFrameLocation (frame * dap.StackFrame , loc * pb.Locations ) {
547- for _ , l := range loc .Locations {
548- for _ , r := range l .Ranges {
549- frame .Line = int (r .Start .Line )
550- frame .Column = int (r .Start .Character )
551- frame .EndLine = int (r .End .Line )
552- frame .EndColumn = int (r .End .Character )
553-
554- info := t .def .Source .Infos [l .SourceIndex ]
555- frame .Source = & dap.Source {
556- Path : filepath .Join (t .sourcePath , info .Filename ),
557- }
558- return
559- }
548+ func (t * thread ) hasFrame (id int ) bool {
549+ t .mu .Lock ()
550+ defer t .mu .Unlock ()
551+
552+ if t .paused == nil {
553+ return false
560554 }
555+
556+ _ , ok := t .frames [int32 (id )]
557+ return ok
561558}
562559
563560func pop [S ~ []E , E any ](s * S ) E {
0 commit comments