@@ -23,6 +23,7 @@ import { debugAssert, fail } from './assert';
23
23
import { AsyncQueue , DelayedOperation , TimerId } from './async_queue' ;
24
24
import { FirestoreError } from './error' ;
25
25
import { logDebug , logError } from './log' ;
26
+ import { Deferred } from './promise' ;
26
27
27
28
const LOG_TAG = 'AsyncQueue' ;
28
29
@@ -49,6 +50,9 @@ export class AsyncQueueImpl implements AsyncQueue {
49
50
// assertion sanity-checks.
50
51
private operationInProgress = false ;
51
52
53
+ // Enabled during shutdown on Safari to prevent future access to IndexedDB.
54
+ private skipNonRestrictedTasks = false ;
55
+
52
56
// List of TimerIds to fast-forward delays for.
53
57
private timerIdsToSkip : TimerId [ ] = [ ] ;
54
58
@@ -97,9 +101,10 @@ export class AsyncQueueImpl implements AsyncQueue {
97
101
this . enqueueInternal ( op ) ;
98
102
}
99
103
100
- enterRestrictedMode ( ) : void {
104
+ enterRestrictedMode ( purgeExistingTasks ?: boolean ) : void {
101
105
if ( ! this . _isShuttingDown ) {
102
106
this . _isShuttingDown = true ;
107
+ this . skipNonRestrictedTasks = purgeExistingTasks || false ;
103
108
const document = getDocument ( ) ;
104
109
if ( document && typeof document . removeEventListener === 'function' ) {
105
110
document . removeEventListener (
@@ -114,9 +119,22 @@ export class AsyncQueueImpl implements AsyncQueue {
114
119
this . verifyNotFailed ( ) ;
115
120
if ( this . _isShuttingDown ) {
116
121
// Return a Promise which never resolves.
117
- return new Promise < T > ( resolve => { } ) ;
122
+ return new Promise < T > ( ( ) => { } ) ;
118
123
}
119
- return this . enqueueInternal ( op ) ;
124
+
125
+ // Create a deferred Promise that we can return to the callee. This
126
+ // allows us to return a "hanging Promise" only to the callee and still
127
+ // advance the queue even when the operation is not run.
128
+ const task = new Deferred < T > ( ) ;
129
+ return this . enqueueInternal < unknown > ( ( ) => {
130
+ if ( this . _isShuttingDown && this . skipNonRestrictedTasks ) {
131
+ // We do not resolve 'task'
132
+ return Promise . resolve ( ) ;
133
+ }
134
+
135
+ op ( ) . then ( task . resolve , task . reject ) ;
136
+ return task . promise ;
137
+ } ) . then ( ( ) => task . promise ) ;
120
138
}
121
139
122
140
enqueueRetryable ( op : ( ) => Promise < void > ) : void {
0 commit comments