@@ -20,11 +20,10 @@ import { assert } from '../util/assert';
20
20
import { debug , error } from '../util/log' ;
21
21
import { primitiveComparator } from '../util/misc' ;
22
22
import { SortedSet } from '../util/sorted_set' ;
23
- import { isSafeInteger } from '../util/types' ;
23
+ import { isSafeInteger } from '../util/types' ;
24
24
25
25
const LOG_TAG = 'InstanceMetadataChannel' ;
26
26
27
-
28
27
const FIRESTORE_PREFIX = 'fs' ;
29
28
30
29
// The format of an instance key if:
@@ -96,7 +95,8 @@ export interface InstanceMetadataChannel {
96
95
* LocalStorage serialization. The InstanceKey is omitted here here as it is
97
96
* encoded as part of the key.
98
97
*/
99
- export interface InstanceStateSchema { // Visible for testing.
98
+ export interface InstanceStateSchema {
99
+ // Visible for testing.
100
100
lastUpdateTime : number ;
101
101
activeTargetIds : number [ ] ;
102
102
minMutationBatchId ?: number ;
@@ -132,14 +132,18 @@ class InstanceState {
132
132
* Parses an InstanceState from its JSON representation in LocalStorage.
133
133
* Logs a warning and returns null if the data could not be parsed.
134
134
*/
135
- static fromLocalStorageEntry ( instanceKey : string , value : string ) : InstanceState | null {
135
+ static fromLocalStorageEntry (
136
+ instanceKey : string ,
137
+ value : string
138
+ ) : InstanceState | null {
136
139
const instanceData = JSON . parse ( value ) as InstanceStateSchema ;
137
140
138
- let validData = typeof instanceData === 'object'
139
- && isSafeInteger ( instanceData . lastUpdateTime )
140
- && instanceData . activeTargetIds instanceof Array
141
- && isSafeInteger ( instanceData . minMutationBatchId )
142
- && isSafeInteger ( instanceData . maxMutationBatchId ) ;
141
+ let validData =
142
+ typeof instanceData === 'object' &&
143
+ isSafeInteger ( instanceData . lastUpdateTime ) &&
144
+ instanceData . activeTargetIds instanceof Array &&
145
+ isSafeInteger ( instanceData . minMutationBatchId ) &&
146
+ isSafeInteger ( instanceData . maxMutationBatchId ) ;
143
147
144
148
if ( validData ) {
145
149
let activeTargetIdsArray = instanceData . activeTargetIds ;
@@ -152,18 +156,20 @@ class InstanceState {
152
156
153
157
if ( validData ) {
154
158
return new InstanceState (
155
- instanceKey ,
156
- new Date ( instanceData . lastUpdateTime ) ,
157
- activeTargetIdsSet ,
158
- instanceData . minMutationBatchId ,
159
- instanceData . maxMutationBatchId
159
+ instanceKey ,
160
+ new Date ( instanceData . lastUpdateTime ) ,
161
+ activeTargetIdsSet ,
162
+ instanceData . minMutationBatchId ,
163
+ instanceData . maxMutationBatchId
160
164
) ;
161
165
}
162
166
}
163
167
164
- error ( LOG_TAG , `Failed to parse instance metadata for instance '${ instanceKey } '` ) ;
168
+ error (
169
+ LOG_TAG ,
170
+ `Failed to parse instance metadata for instance '${ instanceKey } '`
171
+ ) ;
165
172
return null ;
166
-
167
173
}
168
174
}
169
175
@@ -181,7 +187,13 @@ class LocalInstanceState extends InstanceState {
181
187
private pendingBatchIds = new SortedSet < BatchId > ( primitiveComparator ) ;
182
188
183
189
constructor ( instanceKey : InstanceKey ) {
184
- super ( instanceKey , new Date ( ) , new SortedSet < TargetId > ( primitiveComparator ) , null , null ) ;
190
+ super (
191
+ instanceKey ,
192
+ new Date ( ) ,
193
+ new SortedSet < TargetId > ( primitiveComparator ) ,
194
+ null ,
195
+ null
196
+ ) ;
185
197
}
186
198
187
199
get minMutationBatchId ( ) : BatchId | null {
@@ -268,12 +280,16 @@ export class WebStorageMetadataChannel implements InstanceMetadataChannel {
268
280
constructor ( private persistenceKey : string , private instanceKey : string ) {
269
281
this . localStorage = window ? window . localStorage : undefined ;
270
282
this . storageKey = toLocalStorageKey (
271
- INSTANCE_KEY_NAMESPACE ,
272
- this . persistenceKey ,
273
- this . instanceKey
283
+ INSTANCE_KEY_NAMESPACE ,
284
+ this . persistenceKey ,
285
+ this . instanceKey
286
+ ) ;
287
+ this . activeInstances [ this . instanceKey ] = new LocalInstanceState (
288
+ this . instanceKey
289
+ ) ;
290
+ this . instanceKeyRe = new RegExp (
291
+ `^fs_instances_${ persistenceKey } _[^_]{20}$`
274
292
) ;
275
- this . activeInstances [ this . instanceKey ] = new LocalInstanceState ( this . instanceKey ) ;
276
- this . instanceKeyRe = new RegExp ( `^fs_instances_${ persistenceKey } _[^_]{20}$` ) ;
277
293
}
278
294
279
295
/** Returns 'true' if LocalStorage is available in the current environment. */
@@ -284,8 +300,8 @@ export class WebStorageMetadataChannel implements InstanceMetadataChannel {
284
300
start ( knownInstances : InstanceKey [ ] ) : void {
285
301
if ( ! WebStorageMetadataChannel . isAvailable ( ) ) {
286
302
throw new FirestoreError (
287
- Code . UNIMPLEMENTED ,
288
- 'LocalStorage is not available on this platform.'
303
+ Code . UNIMPLEMENTED ,
304
+ 'LocalStorage is not available on this platform.'
289
305
) ;
290
306
}
291
307
assert ( ! this . started , 'LocalStorageMetadataNotifier already started' ) ;
@@ -294,11 +310,14 @@ export class WebStorageMetadataChannel implements InstanceMetadataChannel {
294
310
295
311
for ( const instanceKey of knownInstances ) {
296
312
const storageKey = toLocalStorageKey (
297
- INSTANCE_KEY_NAMESPACE ,
298
- this . persistenceKey ,
299
- instanceKey
313
+ INSTANCE_KEY_NAMESPACE ,
314
+ this . persistenceKey ,
315
+ instanceKey
316
+ ) ;
317
+ const instanceState = InstanceState . fromLocalStorageEntry (
318
+ instanceKey ,
319
+ this . localStorage . getItem ( storageKey )
300
320
) ;
301
- const instanceState = InstanceState . fromLocalStorageEntry ( instanceKey , this . localStorage . getItem ( storageKey ) ) ;
302
321
if ( instanceState ) {
303
322
this . activeInstances [ instanceState . instanceKey ] = instanceState ;
304
323
}
@@ -315,7 +334,7 @@ export class WebStorageMetadataChannel implements InstanceMetadataChannel {
315
334
minMutationBatch = this . activeInstances [ key ] . minMutationBatchId ;
316
335
} else {
317
336
minMutationBatch = Math . min (
318
- this . activeInstances [ key ] . minMutationBatchId ,
337
+ this . activeInstances [ key ] . minMutationBatchId ,
319
338
minMutationBatch
320
339
) ;
321
340
}
@@ -328,7 +347,9 @@ export class WebStorageMetadataChannel implements InstanceMetadataChannel {
328
347
let activeTargets = new SortedSet < TargetId > ( primitiveComparator ) ;
329
348
330
349
Object . keys ( this . activeInstances ) . forEach ( key => {
331
- activeTargets = activeTargets . unionWith ( this . activeInstances [ key ] . activeTargetIds ) ;
350
+ activeTargets = activeTargets . unionWith (
351
+ this . activeInstances [ key ] . activeTargetIds
352
+ ) ;
332
353
} ) ;
333
354
334
355
return activeTargets ;
@@ -356,29 +377,35 @@ export class WebStorageMetadataChannel implements InstanceMetadataChannel {
356
377
357
378
shutdown ( ) : void {
358
379
assert (
359
- this . started ,
360
- 'LocalStorageMetadataNotifier.shutdown() called when not started'
380
+ this . started ,
381
+ 'LocalStorageMetadataNotifier.shutdown() called when not started'
361
382
) ;
362
383
window . removeEventListener ( 'storage' , this . storageListener ) ;
363
384
this . localStorage . removeItem ( this . storageKey ) ;
364
385
this . started = false ;
365
386
}
366
387
367
- private handleStorageEvent ( event :StorageEvent ) : void {
388
+ private handleStorageEvent ( event : StorageEvent ) : void {
368
389
if ( ! this . started ) {
369
390
return ;
370
391
}
371
392
if ( event . storageArea === this . localStorage ) {
372
393
// TODO(multitab): This assert will likely become invalid as we add garbage
373
394
// collection.
374
- assert ( event . key !== this . storageKey , "Received LocalStorage notification for local change." ) ;
395
+ assert (
396
+ event . key !== this . storageKey ,
397
+ 'Received LocalStorage notification for local change.'
398
+ ) ;
375
399
376
400
const instanceKey = fromLocalStorageKey ( event . key , this . instanceKeyRe , 3 ) ;
377
401
if ( instanceKey ) {
378
402
if ( event . newValue == null ) {
379
403
delete this . activeInstances [ instanceKey ] ;
380
404
} else {
381
- const newInstance = InstanceState . fromLocalStorageEntry ( instanceKey , event . newValue ) ;
405
+ const newInstance = InstanceState . fromLocalStorageEntry (
406
+ instanceKey ,
407
+ event . newValue
408
+ ) ;
382
409
if ( newInstance ) {
383
410
this . activeInstances [ newInstance . instanceKey ] = newInstance ;
384
411
}
@@ -392,22 +419,22 @@ export class WebStorageMetadataChannel implements InstanceMetadataChannel {
392
419
}
393
420
394
421
private persistState ( ) : void {
395
- assert (
396
- this . started ,
397
- 'LocalStorageMetadataNotifier used before started.'
398
- ) ;
422
+ assert ( this . started , 'LocalStorageMetadataNotifier used before started.' ) ;
399
423
debug ( LOG_TAG , 'Persisting state in LocalStorage' ) ;
400
424
this . localInstanceState . refreshLastUpdateTime ( ) ;
401
- this . localStorage . setItem ( this . storageKey , this . localInstanceState . toLocalStorageJSON ( ) ) ;
425
+ this . localStorage . setItem (
426
+ this . storageKey ,
427
+ this . localInstanceState . toLocalStorageJSON ( )
428
+ ) ;
402
429
}
403
430
}
404
431
405
432
/** Assembles a key for LocalStorage */
406
433
function toLocalStorageKey ( ...segments : string [ ] ) : string {
407
434
segments . forEach ( value => {
408
435
assert (
409
- value . indexOf ( '_' ) === - 1 ,
410
- `Key element cannot contain '_', but was '${ value } '`
436
+ value . indexOf ( '_' ) === - 1 ,
437
+ `Key element cannot contain '_', but was '${ value } '`
411
438
) ;
412
439
} ) ;
413
440
@@ -417,11 +444,15 @@ function toLocalStorageKey(...segments: string[]): string {
417
444
/**
418
445
* Parses the segments from a key in LocalStorage. Returns null if the key
419
446
* doesn't match the provided regular expression. */
420
- function fromLocalStorageKey ( key : string , expectedMatch : RegExp , dataSegement :number ) : string | null {
447
+ function fromLocalStorageKey (
448
+ key : string ,
449
+ expectedMatch : RegExp ,
450
+ dataSegement : number
451
+ ) : string | null {
421
452
if ( ! expectedMatch . test ( key ) ) {
422
453
console . log ( 'key didnt match ' + key ) ;
423
454
return null ;
424
455
}
425
456
426
- return key . split ( "_" ) [ dataSegement ] ;
427
- }
457
+ return key . split ( '_' ) [ dataSegement ] ;
458
+ }
0 commit comments