@@ -94,7 +94,7 @@ public void EnableDebugMode()
94
94
_psesHost . Runspace . Debugger . SetDebugMode ( DebugModes . LocalScript | DebugModes . RemoteScript ) ;
95
95
}
96
96
97
- public void Abort ( ) => SetDebugResuming ( DebuggerResumeAction . Stop , isDisconnect : true ) ;
97
+ public void Abort ( ) => SetDebugResuming ( DebuggerResumeAction . Stop ) ;
98
98
99
99
public void BreakExecution ( ) => _psesHost . Runspace . Debugger . SetDebuggerStepMode ( enabled : true ) ;
100
100
@@ -106,10 +106,12 @@ public void EnableDebugMode()
106
106
107
107
public void StepOver ( ) => SetDebugResuming ( DebuggerResumeAction . StepOver ) ;
108
108
109
- public void SetDebugResuming ( DebuggerResumeAction debuggerResumeAction , bool isDisconnect = false )
109
+ public void SetDebugResuming ( DebuggerResumeAction debuggerResumeAction )
110
110
{
111
- // NOTE: We exit because the paused/stopped debugger is currently in a prompt REPL, and
112
- // to resume the debugger we must exit that REPL.
111
+ // We exit because the paused/stopped debugger is currently in a prompt REPL, and to
112
+ // resume the debugger we must exit that REPL. If we're continued from 'c' or 's', this
113
+ // is already set and so is a no-op; but if the user clicks the continue or step button,
114
+ // then this came over LSP and we need to set it.
113
115
_psesHost . SetExit ( ) ;
114
116
115
117
if ( LastStopEventArgs is not null )
@@ -127,23 +129,31 @@ public void SetDebugResuming(DebuggerResumeAction debuggerResumeAction, bool isD
127
129
return ;
128
130
}
129
131
130
- if ( debuggerResumeAction is DebuggerResumeAction . Stop )
132
+ // If we're stopping (or disconnecting, which is the same thing in LSP-land), then we
133
+ // want to cancel any debug prompts, remote prompts, debugged scripts, etc. However, if
134
+ // the debugged script has exited normally (or was quit with 'q'), we still get an LSP
135
+ // notification that eventually lands here with a stop event. In this case, the debug
136
+ // context is NOT active and we do not want to cancel the regular REPL.
137
+ if ( ! _psesHost . DebugContext . IsActive )
131
138
{
132
- // If we're disconnecting we want to unwind all the way back to the default, local
133
- // state. So we use UnwindCallStack here to ensure every context frame is cancelled.
134
- if ( isDisconnect )
135
- {
136
- _psesHost . UnwindCallStack ( ) ;
137
- return ;
138
- }
139
+ return ;
140
+ }
139
141
140
- _psesHost . CancelIdleParentTask ( ) ;
142
+ // If the debugger is active and we're stopping, we need to unwind everything.
143
+ if ( debuggerResumeAction is DebuggerResumeAction . Stop )
144
+ {
145
+ // TODO: We need to assign cancellation tokens to each frame, because the current
146
+ // logic results in a deadlock here when we try to cancel the scopes...which
147
+ // includes ourself (hence running it in a separate thread).
148
+ Task . Run ( ( ) => _psesHost . UnwindCallStack ( ) ) ;
141
149
return ;
142
150
}
143
151
152
+ // Otherwise we're continuing or stepping (i.e. resuming) so we need to cancel the
153
+ // debugger REPL.
144
154
if ( _psesHost . CurrentFrame . IsRepl )
145
155
{
146
- _psesHost . CancelCurrentTask ( ) ;
156
+ _psesHost . CancelIdleParentTask ( ) ;
147
157
}
148
158
}
149
159
@@ -166,15 +176,14 @@ public void ProcessDebuggerResult(DebuggerCommandResults debuggerResult)
166
176
{
167
177
if ( debuggerResult ? . ResumeAction is not null )
168
178
{
169
- SetDebugResuming ( debuggerResult . ResumeAction . Value ) ;
170
-
171
- // If a debugging command like `c` is specified in a nested remote
172
- // debugging prompt we need to unwind the nested execution loop.
173
- if ( _psesHost . CurrentFrame . IsRemote )
179
+ // Since we're processing a command like 'c' or 's' remotely, we need to tell the
180
+ // host to stop the remote REPL loop.
181
+ if ( debuggerResult . ResumeAction is not DebuggerResumeAction . Stop || _psesHost . CurrentFrame . IsRemote )
174
182
{
175
183
_psesHost . ForceSetExit ( ) ;
176
184
}
177
185
186
+ SetDebugResuming ( debuggerResult . ResumeAction . Value ) ;
178
187
RaiseDebuggerResumingEvent ( new DebuggerResumingEventArgs ( debuggerResult . ResumeAction . Value ) ) ;
179
188
180
189
// The Terminate exception is used by the engine for flow control
0 commit comments