@@ -17,6 +17,7 @@ const JS_DEBUG_USEPREVIEWAA = 'usePreviewAutoAttach';
1717const JS_DEBUG_IPC_KEY = 'jsDebugIpcState' ;
1818const NODE_DEBUG_SETTINGS = 'debug.node' ;
1919const AUTO_ATTACH_SETTING = 'autoAttach' ;
20+ const LAST_STATE_STORAGE_KEY = 'lastState' ;
2021
2122type AUTO_ATTACH_VALUES = 'disabled' | 'on' | 'off' ;
2223
@@ -28,10 +29,14 @@ const enum State {
2829}
2930
3031// on activation this feature is always disabled...
31- let currentState = Promise . resolve ( { state : State . Disabled , transitionData : null as unknown } ) ;
32+ let currentState : Promise < { context : vscode . ExtensionContext , state : State ; transitionData : unknown } > ;
3233let statusItem : vscode . StatusBarItem | undefined ; // and there is no status bar item
3334
3435export function activate ( context : vscode . ExtensionContext ) : void {
36+ const previousState = context . workspaceState . get < State > ( LAST_STATE_STORAGE_KEY , State . Disabled ) ;
37+ currentState = Promise . resolve ( transitions [ previousState ] . onActivate ?.( context , readCurrentState ( ) ) )
38+ . then ( ( ) => ( { context, state : State . Disabled , transitionData : null } ) ) ;
39+
3540 context . subscriptions . push ( vscode . commands . registerCommand ( TOGGLE_COMMAND , toggleAutoAttachSetting ) ) ;
3641
3742 // settings that can result in the "state" being changed--on/off/disable or useV3 toggles
@@ -43,17 +48,17 @@ export function activate(context: vscode.ExtensionContext): void {
4348 context . subscriptions . push (
4449 vscode . workspace . onDidChangeConfiguration ( ( e ) => {
4550 if ( effectualConfigurationSettings . some ( setting => e . affectsConfiguration ( setting ) ) ) {
46- updateAutoAttach ( context ) ;
51+ updateAutoAttach ( ) ;
4752 }
4853 } )
4954 ) ;
5055
51- updateAutoAttach ( context ) ;
56+ updateAutoAttach ( ) ;
5257}
5358
5459export async function deactivate ( ) : Promise < void > {
55- const { state, transitionData } = await currentState ;
56- await transitions [ state ] . exit ?.( transitionData ) ;
60+ const { context , state, transitionData } = await currentState ;
61+ await transitions [ state ] . exit ?.( context , transitionData ) ;
5762}
5863
5964function toggleAutoAttachSetting ( ) {
@@ -136,30 +141,33 @@ interface CachedIpcState {
136141}
137142
138143interface StateTransition < StateData > {
139- exit ?( stateData : StateData ) : Promise < void > | void ;
144+ onActivate ?( context : vscode . ExtensionContext , currentState : State ) : Promise < void > ;
145+ exit ?( context : vscode . ExtensionContext , stateData : StateData ) : Promise < void > | void ;
140146 enter ?( context : vscode . ExtensionContext ) : Promise < StateData > | StateData ;
141147}
142148
149+ const makeTransition = < T > ( tsn : StateTransition < T > ) => tsn ; // helper to apply generic type
150+
143151/**
144152 * Map of logic that happens when auto attach states are entered and exited.
145153 * All state transitions are queued and run in order; promises are awaited.
146154 */
147155const transitions : { [ S in State ] : StateTransition < unknown > } = {
148- [ State . Disabled ] : {
156+ [ State . Disabled ] : makeTransition ( {
149157 async enter ( context ) {
150158 statusItem ?. hide ( ) ;
151159 await clearJsDebugAttachState ( context ) ;
152160 } ,
153- } ,
161+ } ) ,
154162
155- [ State . Off ] : {
163+ [ State . Off ] : makeTransition ( {
156164 enter ( context ) {
157165 const statusItem = ensureStatusBarExists ( context ) ;
158166 statusItem . text = OFF_TEXT ;
159167 } ,
160- } ,
168+ } ) ,
161169
162- [ State . OnWithNodeDebug ] : {
170+ [ State . OnWithNodeDebug ] : makeTransition ( {
163171 async enter ( context ) {
164172 const statusItem = ensureStatusBarExists ( context ) ;
165173 const vscode_pid = process . env [ 'VSCODE_PID' ] ;
@@ -171,16 +179,16 @@ const transitions: { [S in State]: StateTransition<unknown> } = {
171179 async exit ( ) {
172180 await vscode . commands . executeCommand ( 'extension.node-debug.stopAutoAttach' ) ;
173181 } ,
174- } ,
182+ } ) ,
175183
176- [ State . OnWithJsDebug ] : {
184+ [ State . OnWithJsDebug ] : makeTransition < Server | null > ( {
177185 async enter ( context ) {
178186 const ipcAddress = await getIpcAddress ( context ) ;
179187 if ( ! ipcAddress ) {
180- return { context } ;
188+ return null ;
181189 }
182190
183- const server = await new Promise ( ( resolve , reject ) => {
191+ const server = await new Promise < Server > ( ( resolve , reject ) => {
184192 const s = createServer ( ( socket ) => {
185193 let data : Buffer [ ] = [ ] ;
186194 socket . on ( 'data' , ( chunk ) => data . push ( chunk ) ) ;
@@ -201,10 +209,10 @@ const transitions: { [S in State]: StateTransition<unknown> } = {
201209
202210 const statusItem = ensureStatusBarExists ( context ) ;
203211 statusItem . text = ON_TEXT ;
204- return { server, context } ;
212+ return server || null ;
205213 } ,
206214
207- async exit ( { server , context } : { server ?: Server , context : vscode . ExtensionContext } ) {
215+ async exit ( context , server ) {
208216 // we don't need to clear the environment variables--the bootloader will
209217 // no-op if the debug server is closed. This prevents having to reload
210218 // terminals if users want to turn it back on.
@@ -217,24 +225,31 @@ const transitions: { [S in State]: StateTransition<unknown> } = {
217225 await clearJsDebugAttachState ( context ) ;
218226 }
219227 } ,
220- } ,
228+
229+ async onActivate ( context , currentState ) {
230+ if ( currentState === State . OnWithNodeDebug || currentState === State . Disabled ) {
231+ await clearJsDebugAttachState ( context ) ;
232+ }
233+ }
234+ } ) ,
221235} ;
222236
223237/**
224238 * Updates the auto attach feature based on the user or workspace setting
225239 */
226- function updateAutoAttach ( context : vscode . ExtensionContext ) {
240+ function updateAutoAttach ( ) {
227241 const newState = readCurrentState ( ) ;
228242
229- currentState = currentState . then ( async ( { state : oldState , transitionData } ) => {
243+ currentState = currentState . then ( async ( { context , state : oldState , transitionData } ) => {
230244 if ( newState === oldState ) {
231- return { state : oldState , transitionData } ;
245+ return { context , state : oldState , transitionData } ;
232246 }
233247
234- await transitions [ oldState ] . exit ?.( transitionData ) ;
248+ await transitions [ oldState ] . exit ?.( context , transitionData ) ;
235249 const newData = await transitions [ newState ] . enter ?.( context ) ;
250+ await context . workspaceState . update ( LAST_STATE_STORAGE_KEY , newState ) ;
236251
237- return { state : newState , transitionData : newData } ;
252+ return { context , state : newState , transitionData : newData } ;
238253 } ) ;
239254}
240255
0 commit comments