@@ -225,6 +225,34 @@ export class AppState {
225225 } ) ;
226226 }
227227
228+ // Lock on the active Electron version that prevents other windows from removing it
229+ private versionLock : Lock | null = null ;
230+
231+ // Used to release the lock when the current window switches Electron versions
232+ private versionLockController = new AbortController ( ) ;
233+
234+ private static versionLockNamePrefix = 'version:' ;
235+
236+ public getVersionLockName ( ver : string ) {
237+ return [ AppState . versionLockNamePrefix , ver ] . join ( '' ) ;
238+ }
239+
240+ /**
241+ * Retrieves all Electron versions that are currently active in some window.
242+ */
243+ public async getActiveVersions ( ) : Promise < Set < string > > {
244+ return ( ( await navigator . locks . query ( ) ) . held || [ ] ) . reduce < Set < string > > (
245+ ( acc , item ) => {
246+ if ( item . name ?. startsWith ( AppState . versionLockNamePrefix ) ) {
247+ acc . add ( item . name ) ;
248+ }
249+
250+ return acc ;
251+ } ,
252+ new Set ( ) ,
253+ ) ;
254+ }
255+
228256 constructor ( versions : RunnableVersion [ ] ) {
229257 makeObservable < AppState , 'setPageHash' | 'setVersionStates' > ( this , {
230258 Bisector : observable ,
@@ -795,7 +823,9 @@ export class AppState {
795823 public async removeVersion ( ver : RunnableVersion ) : Promise < void > {
796824 const { version, state, source } = ver ;
797825
798- if ( ver === this . currentElectronVersion ) {
826+ const activeVersions = await this . getActiveVersions ( ) ;
827+
828+ if ( activeVersions . has ( this . getVersionLockName ( ver . version ) ) ) {
799829 console . log ( `State: Not removing active version ${ version } ` ) ;
800830 return ;
801831 }
@@ -954,10 +984,36 @@ export class AppState {
954984 return ;
955985 }
956986
987+ if ( this . versionLock ) {
988+ console . log ( `Releasing lock on version ${ this . version } ` ) ;
989+
990+ // release the lock on the previous version
991+ this . versionLockController . abort ( ) ;
992+
993+ // replace the spent AbortController
994+ this . versionLockController = new AbortController ( ) ;
995+ }
996+
957997 const { version } = ver ;
958998 console . log ( `State: Switching to Electron ${ version } ` ) ;
959999 this . version = version ;
9601000
1001+ navigator . locks . request (
1002+ this . getVersionLockName ( version ) ,
1003+ { mode : 'shared' } ,
1004+ ( lock ) => {
1005+ this . versionLock = lock ;
1006+
1007+ /**
1008+ * The lock is released when this promise resolves, so we keep it in the
1009+ * pending state until our AbortController is aborted.
1010+ */
1011+ return new Promise < void > ( ( resolve ) => {
1012+ this . versionLockController . signal . onabort = ( ) => resolve ( ) ;
1013+ } ) ;
1014+ } ,
1015+ ) ;
1016+
9611017 // If there's no current fiddle,
9621018 // or if the current fiddle is the previous version's template,
9631019 // then load the new version's template.
0 commit comments