@@ -33,42 +33,43 @@ class AutoDetect {
3333 MSP . read ( event . detail ) ;
3434 }
3535
36- verifyBoard ( ) {
36+ async verifyBoard ( ) {
3737 const port = PortHandler . portPicker . selectedPort ;
38- const isLoaded = TABS . firmware_flasher . targets ? Object . keys ( TABS . firmware_flasher . targets ) . length > 0 : false ;
39-
40- if ( ! PortHandler . portAvailable ) {
41- gui_log ( i18n . getMessage ( "firmwareFlasherNoValidPort" ) ) ;
42- return ;
43- }
44-
45- if ( ! isLoaded ) {
46- gui_log ( i18n . getMessage ( "firmwareFlasherNoTargetsLoaded" ) ) ;
47- return ;
48- }
49-
50- if ( serial . connected || serial . connectionId ) {
51- console . warn (
52- "Attempting to connect while there still is a connection" ,
53- serial . connected ,
54- serial . connectionId ,
55- serial . openCanceled ,
56- ) ;
57- serial . disconnect ( ) ;
58- return ;
59- }
60-
61- gui_log ( i18n . getMessage ( "firmwareFlasherDetectBoardQuery" ) ) ;
6238
6339 if ( ! port . startsWith ( "virtual" ) ) {
64- serial . addEventListener ( "connect" , this . boundHandleConnect , { once : true } ) ;
65- serial . addEventListener ( "disconnect" , this . boundHandleDisconnect , { once : true } ) ;
66-
67- console . log ( "Connecting to serial port" , port , serial . connected , serial . connectionId ) ;
68-
69- serial . connect ( port , { baudRate : PortHandler . portPicker . selectedBauds || 115200 } ) ;
70- } else {
71- gui_log ( i18n . getMessage ( "serialPortOpenFail" ) ) ;
40+ // Safely check firmware_flasher.targets (use optional chaining so this doesn't throw when undefined)
41+ const isLoaded = TABS . firmware_flasher ?. targets
42+ ? Object . keys ( TABS . firmware_flasher . targets ) . length > 0
43+ : false ;
44+ let result = false ;
45+ let attempted = false ;
46+
47+ try {
48+ if ( ! PortHandler . portAvailable ) {
49+ gui_log ( i18n . getMessage ( "firmwareFlasherNoValidPort" ) ) ;
50+ } else if ( ! isLoaded ) {
51+ gui_log ( i18n . getMessage ( "firmwareFlasherNoTargetsLoaded" ) ) ;
52+ } else if ( serial . connected || serial . connectionId ) {
53+ console . warn ( "Attempting to connect while there still is a connection" , serial . connected ) ;
54+ gui_log ( i18n . getMessage ( "serialPortOpenFail" ) ) ;
55+ } else {
56+ // We're about to attempt a connection: register listeners just-in-time
57+ attempted = true ;
58+ serial . addEventListener ( "connect" , this . boundHandleConnect , { once : true } ) ;
59+ serial . addEventListener ( "disconnect" , this . boundHandleDisconnect , { once : true } ) ;
60+
61+ console . log ( "Connecting to serial port" , port ) ;
62+ gui_log ( i18n . getMessage ( "firmwareFlasherDetectBoardQuery" ) ) ;
63+ result = await serial . connect ( port , { baudRate : PortHandler . portPicker . selectedBauds || 115200 } ) ;
64+ }
65+ } catch ( error ) {
66+ console . error ( "Failed to connect:" , error ) ;
67+ } finally {
68+ // Only run cleanup when we actually attempted a connection and it failed
69+ if ( attempted && ! result ) {
70+ this . cleanup ( ) ;
71+ }
72+ }
7273 }
7374 }
7475
@@ -116,17 +117,7 @@ class AutoDetect {
116117 ) ;
117118 }
118119
119- // Remove event listeners using stored references
120- serial . removeEventListener ( "receive" , this . boundHandleSerialReceive ) ;
121- serial . removeEventListener ( "connect" , this . boundHandleConnect ) ;
122- serial . removeEventListener ( "disconnect" , this . boundHandleDisconnect ) ;
123-
124- // Clean up MSP listeners
125- MSP . clearListeners ( ) ;
126- MSP . disconnect_cleanup ( ) ;
127-
128- // Disconnect without passing onClosed as a callback
129- serial . disconnect ( ) ;
120+ this . cleanup ( ) ;
130121 }
131122
132123 async getBoardInfo ( ) {
@@ -195,6 +186,25 @@ class AutoDetect {
195186 gui_log ( i18n . getMessage ( "serialPortOpenFail" ) ) ;
196187 }
197188 }
189+
190+ async cleanup ( ) {
191+ // Disconnect first, so the once-registered disconnect handler can fire
192+ try {
193+ await serial . disconnect ( ) ;
194+ } catch ( error ) {
195+ // Log the error with context but continue to run cleanup
196+ console . error ( "Serial disconnection failed:" , error ) ;
197+ } finally {
198+ // Remove event listeners using stored references (disconnect listener is once-registered and already removed)
199+ serial . removeEventListener ( "receive" , this . boundHandleSerialReceive ) ;
200+ serial . removeEventListener ( "connect" , this . boundHandleConnect ) ;
201+ // Do NOT remove disconnect listener, as it is once-registered and will be auto-removed
202+
203+ // Clean up MSP listeners after disconnect (always run)
204+ MSP . clearListeners ( ) ;
205+ MSP . disconnect_cleanup ( ) ;
206+ }
207+ }
198208}
199209
200210export default new AutoDetect ( ) ;
0 commit comments