@@ -207,6 +207,34 @@ export class AppState {
207207 versions : this . baseVersions ,
208208 } ) ;
209209
210+ // Lock on the active Electron version that prevents other windows from removing it
211+ private versionLock : Lock | null = null ;
212+
213+ // Used to release the lock when the current window switches Electron versions
214+ private versionLockController = new AbortController ( ) ;
215+
216+ private static versionLockNamePrefix = 'version:' ;
217+
218+ public getVersionLockName ( ver : string ) {
219+ return [ AppState . versionLockNamePrefix , ver ] . join ( '' ) ;
220+ }
221+
222+ /**
223+ * Retrieves all Electron versions that are currently active in some window.
224+ */
225+ public async getActiveVersions ( ) : Promise < Set < string > > {
226+ return ( ( await navigator . locks . query ( ) ) . held || [ ] ) . reduce < Set < string > > (
227+ ( acc , item ) => {
228+ if ( item . name ?. startsWith ( AppState . versionLockNamePrefix ) ) {
229+ acc . add ( item . name ) ;
230+ }
231+
232+ return acc ;
233+ } ,
234+ new Set ( ) ,
235+ ) ;
236+ }
237+
210238 constructor ( versions : RunnableVersion [ ] ) {
211239 makeObservable < AppState , 'setPageHash' > ( this , {
212240 Bisector : observable ,
@@ -700,7 +728,9 @@ export class AppState {
700728 public async removeVersion ( ver : RunnableVersion ) : Promise < void > {
701729 const { version, state, source } = ver ;
702730
703- if ( ver === this . currentElectronVersion ) {
731+ const activeVersions = await this . getActiveVersions ( ) ;
732+
733+ if ( activeVersions . has ( this . getVersionLockName ( ver . version ) ) ) {
704734 console . log ( `State: Not removing active version ${ version } ` ) ;
705735 return ;
706736 }
@@ -851,10 +881,36 @@ export class AppState {
851881 return ;
852882 }
853883
884+ if ( this . versionLock ) {
885+ console . log ( `Releasing lock on version ${ this . version } ` ) ;
886+
887+ // release the lock on the previous version
888+ this . versionLockController . abort ( ) ;
889+
890+ // replace the spent AbortController
891+ this . versionLockController = new AbortController ( ) ;
892+ }
893+
854894 const { version } = ver ;
855895 console . log ( `State: Switching to Electron ${ version } ` ) ;
856896 this . version = version ;
857897
898+ navigator . locks . request (
899+ this . getVersionLockName ( version ) ,
900+ { mode : 'shared' } ,
901+ ( lock ) => {
902+ this . versionLock = lock ;
903+
904+ /**
905+ * The lock is released when this promise resolves, so we keep it in the
906+ * pending state until our AbortController is aborted.
907+ */
908+ return new Promise < void > ( ( resolve ) => {
909+ this . versionLockController . signal . onabort = ( ) => resolve ( ) ;
910+ } ) ;
911+ } ,
912+ ) ;
913+
858914 // If there's no current fiddle,
859915 // or if the current fiddle is the previous version's template,
860916 // then load the new version's template.
0 commit comments