@@ -30,9 +30,11 @@ export class WorkerWrappedAsyncDatabaseConnection<Config extends ResolvedWebSQLO
3030 implements AsyncDatabaseConnection
3131{
3232 protected releaseSharedConnectionLock : ( ( ) => void ) | null ;
33+ protected lockAbortController : AbortController ;
3334
3435 constructor ( protected options : WrappedWorkerConnectionOptions < Config > ) {
3536 this . releaseSharedConnectionLock = null ;
37+ this . lockAbortController = new AbortController ( ) ;
3638 }
3739
3840 protected get baseConnection ( ) {
@@ -49,20 +51,38 @@ export class WorkerWrappedAsyncDatabaseConnection<Config extends ResolvedWebSQLO
4951 async shareConnection ( ) : Promise < SharedConnectionWorker > {
5052 const { identifier, remote } = this . options ;
5153 /**
52- * Hold a navigator lock in order to avoid features such as Chrome's frozen tabs
53- * from pausing the thread for this connection.
54+ * Hold a navigator lock in order to avoid features such as Chrome's frozen tabs,
55+ * or Edge's sleeping tabs from pausing the thread for this connection.
56+ * This promise resolves once a lock is obtained.
57+ * This lock will be held as long as this connection is open.
58+ * The `shareConnection` method should not be called on multiple tabs concurrently.
5459 */
55- await new Promise < void > ( ( resolve ) => {
56- navigator . locks . request ( `shared-connection-${ this . options . identifier } ` , async ( lock ) => {
57- resolve ( ) ; // We have a lock now
60+ await new Promise < void > ( ( lockObtained ) =>
61+ navigator . locks
62+ . request (
63+ `shared-connection-${ this . options . identifier } ` ,
64+ {
65+ signal : this . lockAbortController . signal
66+ } ,
67+ async ( ) => {
68+ lockObtained ( ) ;
69+
70+ // Free the lock when the connection is already closed.
71+ if ( this . lockAbortController . signal . aborted ) {
72+ return ;
73+ }
74+
75+ // Hold the lock while the shared connection is in use.
76+ await new Promise < void > ( ( releaseLock ) => {
77+ // We can use the resolver to free the lock
78+ this . releaseSharedConnectionLock = releaseLock ;
79+ } ) ;
80+ }
81+ )
82+ // We aren't concerned with errors here
83+ . catch ( ( ) => { } )
84+ ) ;
5885
59- // Hold the lock while the shared connection is in use.
60- await new Promise < void > ( ( freeLock ) => {
61- // We can use the resolver to free the lock
62- this . releaseSharedConnectionLock = freeLock ;
63- } ) ;
64- } ) ;
65- } ) ;
6686 const newPort = await remote [ Comlink . createEndpoint ] ( ) ;
6787 return { port : newPort , identifier } ;
6888 }
@@ -76,6 +96,8 @@ export class WorkerWrappedAsyncDatabaseConnection<Config extends ResolvedWebSQLO
7696 }
7797
7898 async close ( ) : Promise < void > {
99+ // Abort any pending lock requests.
100+ this . lockAbortController . abort ( ) ;
79101 this . releaseSharedConnectionLock ?.( ) ;
80102 await this . baseConnection . close ( ) ;
81103 this . options . remote [ Comlink . releaseProxy ] ( ) ;
0 commit comments