Skip to content

Commit cff6383

Browse files
committed
2 parents 5afb588 + 7453b0e commit cff6383

23 files changed

+432
-123
lines changed

packages/firebase/index.d.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7763,7 +7763,7 @@ declare namespace firebase.firestore {
77637763
export interface PersistenceSettings {
77647764
/**
77657765
* Whether to synchronize the in-memory state of multiple tabs. Setting this
7766-
* to 'true' in all open tabs enables shared access to local persistence,
7766+
* to `true` in all open tabs enables shared access to local persistence,
77677767
* shared execution of queries and latency-compensated local document updates
77687768
* across all connected instances.
77697769
*
@@ -7775,14 +7775,27 @@ declare namespace firebase.firestore {
77757775

77767776
/**
77777777
* Whether to synchronize the in-memory state of multiple tabs. Setting this
7778-
* to 'true' in all open tabs enables shared access to local persistence,
7778+
* to `true` in all open tabs enables shared access to local persistence,
77797779
* shared execution of queries and latency-compensated local document updates
77807780
* across all connected instances.
77817781
*
7782-
* @deprecated This setting is deprecated. To enabled synchronization between
7782+
* @deprecated This setting is deprecated. To enable synchronization between
77837783
* multiple tabs, please use `synchronizeTabs: true` instead.
77847784
*/
77857785
experimentalTabSynchronization?: boolean;
7786+
7787+
/**
7788+
* Whether to force enable persistence for the client. This cannot be used
7789+
* with `synchronizeTabs:true` and is primarily intended for use with Web
7790+
* Workers. Setting this to `true` will enable persistence, but cause other
7791+
* tabs using persistence to fail.
7792+
*
7793+
* This setting may be removed in a future release. If you find yourself
7794+
* using it for a specific use case or run into any issues, please tell us
7795+
* about it in
7796+
* https://github.com/firebase/firebase-js-sdk/issues/983.
7797+
*/
7798+
experimentalForceOwningTab?: boolean;
77867799
}
77877800

77887801
export type LogLevel = 'debug' | 'error' | 'silent';

packages/firestore-types/index.d.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,16 @@ export interface Settings {
3535
export interface PersistenceSettings {
3636
synchronizeTabs?: boolean;
3737
experimentalTabSynchronization?: boolean;
38+
experimentalForceOwningTab?: boolean;
3839
}
3940

40-
export type LogLevel = 'debug' | 'error' | 'silent';
41+
export type LogLevel =
42+
| 'debug'
43+
| 'error'
44+
| 'silent'
45+
| 'warn'
46+
| 'info'
47+
| 'verbose';
4148

4249
export function setLogLevel(logLevel: LogLevel): void;
4350

packages/firestore/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
in IndexedDB. Previously, these errors crashed the client.
1515
- [fixed] Fixed a source of IndexedDB-related crashes for tabs that receive
1616
multi-tab notifications while the file system is locked.
17+
- [feature] Added an `experimentalForceOwningTab` setting that can be used to
18+
enable persistence in environments without LocalStorage, which allows
19+
persistence to be used in Web Workers (#983).
1720

1821
# 1.10.2
1922
- [fixed] Temporarily reverted the use of window.crypto to generate document

packages/firestore/lite/index.node.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,24 @@ import { Firestore } from './src/api/database';
2020
import { version } from '../package.json';
2121
import { Component, ComponentType } from '@firebase/component';
2222

23+
import '../src/platform_node/node_init';
24+
2325
export {
2426
Firestore,
2527
initializeFirestore,
2628
getFirestore
2729
} from './src/api/database';
2830

31+
// TOOD(firestorelite): Add tests when setDoc() is available
32+
export {
33+
FieldValue,
34+
deleteField,
35+
increment,
36+
arrayRemove,
37+
arrayUnion,
38+
serverTimestamp
39+
} from './src/api/field_value';
40+
2941
export function registerFirestore(): void {
3042
_registerComponent(
3143
new Component(
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/**
2+
* @license
3+
* Copyright 2020 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import * as firestore from '../../';
19+
20+
import { validateAtLeastNumberOfArgs } from '../../../src/util/input_validation';
21+
import {
22+
ArrayRemoveFieldValueImpl,
23+
ArrayUnionFieldValueImpl,
24+
DeleteFieldValueImpl,
25+
NumericIncrementFieldValueImpl,
26+
SerializableFieldValue,
27+
ServerTimestampFieldValueImpl
28+
} from '../../../src/api/field_value';
29+
import { ParseContext } from '../../../src/api/user_data_reader';
30+
import { FieldTransform } from '../../../src/model/mutation';
31+
32+
/** The public FieldValue class of the lite API. */
33+
export abstract class FieldValue extends SerializableFieldValue
34+
implements firestore.FieldValue {}
35+
36+
/**
37+
* A delegate class that allows the FieldValue implementations returned by
38+
* deleteField(), serverTimestamp(), arrayUnion(), arrayRemove() and
39+
* increment() to be an instance of the lite FieldValue class declared above.
40+
*
41+
* We don't directly subclass `FieldValue` in the various field value
42+
* implementations as the base FieldValue class differs between the lite, full
43+
* and legacy SDK.
44+
*/
45+
class FieldValueDelegate extends FieldValue implements firestore.FieldValue {
46+
readonly _methodName: string;
47+
48+
constructor(readonly _delegate: SerializableFieldValue) {
49+
super();
50+
this._methodName = _delegate._methodName;
51+
}
52+
53+
_toFieldTransform(context: ParseContext): FieldTransform | null {
54+
return this._delegate._toFieldTransform(context);
55+
}
56+
57+
isEqual(other: firestore.FieldValue): boolean {
58+
if (!(other instanceof FieldValueDelegate)) {
59+
return false;
60+
}
61+
return this._delegate.isEqual(other._delegate);
62+
}
63+
}
64+
65+
export function deleteField(): firestore.FieldValue {
66+
return new FieldValueDelegate(new DeleteFieldValueImpl('delete'));
67+
}
68+
69+
export function serverTimestamp(): firestore.FieldValue {
70+
return new FieldValueDelegate(
71+
new ServerTimestampFieldValueImpl('serverTimestamp')
72+
);
73+
}
74+
75+
export function arrayUnion(...elements: unknown[]): firestore.FieldValue {
76+
validateAtLeastNumberOfArgs('arrayUnion()', arguments, 1);
77+
// NOTE: We don't actually parse the data until it's used in set() or
78+
// update() since we'd need the Firestore instance to do this.
79+
return new FieldValueDelegate(
80+
new ArrayUnionFieldValueImpl('arrayUnion', elements)
81+
);
82+
}
83+
84+
export function arrayRemove(...elements: unknown[]): firestore.FieldValue {
85+
validateAtLeastNumberOfArgs('arrayRemove()', arguments, 1);
86+
// NOTE: We don't actually parse the data until it's used in set() or
87+
// update() since we'd need the Firestore instance to do this.
88+
return new FieldValueDelegate(
89+
new ArrayRemoveFieldValueImpl('arrayRemove', elements)
90+
);
91+
}
92+
93+
export function increment(n: number): firestore.FieldValue {
94+
return new FieldValueDelegate(
95+
new NumericIncrementFieldValueImpl('increment', n)
96+
);
97+
}

packages/firestore/lite/test/integration.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import {
2323
getFirestore,
2424
initializeFirestore
2525
} from '../src/api/database';
26+
import { expectEqual, expectNotEqual } from '../../test/util/helpers';
27+
import { FieldValue } from '../../src/api/field_value';
2628

2729
describe('Firestore', () => {
2830
it('can provide setting', () => {
@@ -57,3 +59,21 @@ describe('Firestore', () => {
5759
);
5860
});
5961
});
62+
63+
describe('FieldValue', () => {
64+
it('support equality checking with isEqual()', () => {
65+
expectEqual(FieldValue.delete(), FieldValue.delete());
66+
expectEqual(FieldValue.serverTimestamp(), FieldValue.serverTimestamp());
67+
expectNotEqual(FieldValue.delete(), FieldValue.serverTimestamp());
68+
// TODO(firestorelite): Add test when field value is available
69+
//expectNotEqual(FieldValue.delete(), documentId());
70+
});
71+
72+
it('support instanceof checks', () => {
73+
expect(FieldValue.delete()).to.be.an.instanceOf(FieldValue);
74+
expect(FieldValue.serverTimestamp()).to.be.an.instanceOf(FieldValue);
75+
expect(FieldValue.increment(1)).to.be.an.instanceOf(FieldValue);
76+
expect(FieldValue.arrayUnion('a')).to.be.an.instanceOf(FieldValue);
77+
expect(FieldValue.arrayRemove('a')).to.be.an.instanceOf(FieldValue);
78+
});
79+
});

packages/firestore/src/api/database.ts

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ export class Firestore implements firestore.FirebaseFirestore, FirebaseService {
384384
}
385385

386386
let synchronizeTabs = false;
387+
let experimentalForceOwningTab = false;
387388

388389
if (settings) {
389390
if (settings.experimentalTabSynchronization !== undefined) {
@@ -395,12 +396,24 @@ export class Firestore implements firestore.FirebaseFirestore, FirebaseService {
395396
settings.synchronizeTabs ??
396397
settings.experimentalTabSynchronization ??
397398
DEFAULT_SYNCHRONIZE_TABS;
399+
400+
experimentalForceOwningTab = settings.experimentalForceOwningTab
401+
? settings.experimentalForceOwningTab
402+
: false;
403+
404+
if (synchronizeTabs && experimentalForceOwningTab) {
405+
throw new FirestoreError(
406+
Code.INVALID_ARGUMENT,
407+
"The 'experimentalForceOwningTab' setting cannot be used with 'synchronizeTabs'."
408+
);
409+
}
398410
}
399411

400412
return this.configureClient(this._componentProvider, {
401413
durable: true,
402414
cacheSizeBytes: this._settings.cacheSizeBytes,
403-
synchronizeTabs
415+
synchronizeTabs,
416+
forceOwningTab: experimentalForceOwningTab
404417
});
405418
}
406419

@@ -620,8 +633,16 @@ export class Firestore implements firestore.FirebaseFirestore, FirebaseService {
620633
switch (getLogLevel()) {
621634
case LogLevel.DEBUG:
622635
return 'debug';
636+
case LogLevel.ERROR:
637+
return 'error';
623638
case LogLevel.SILENT:
624639
return 'silent';
640+
case LogLevel.WARN:
641+
return 'warn';
642+
case LogLevel.INFO:
643+
return 'info';
644+
case LogLevel.VERBOSE:
645+
return 'verbose';
625646
default:
626647
// The default log level is error
627648
return 'error';
@@ -630,23 +651,13 @@ export class Firestore implements firestore.FirebaseFirestore, FirebaseService {
630651

631652
static setLogLevel(level: firestore.LogLevel): void {
632653
validateExactNumberOfArgs('Firestore.setLogLevel', arguments, 1);
633-
validateArgType('Firestore.setLogLevel', 'non-empty string', 1, level);
634-
switch (level) {
635-
case 'debug':
636-
setLogLevel(LogLevel.DEBUG);
637-
break;
638-
case 'error':
639-
setLogLevel(LogLevel.ERROR);
640-
break;
641-
case 'silent':
642-
setLogLevel(LogLevel.SILENT);
643-
break;
644-
default:
645-
throw new FirestoreError(
646-
Code.INVALID_ARGUMENT,
647-
'Invalid log level: ' + level
648-
);
649-
}
654+
validateStringEnum(
655+
'setLogLevel',
656+
['debug', 'error', 'silent', 'warn', 'info', 'verbose'],
657+
1,
658+
level
659+
);
660+
setLogLevel(level);
650661
}
651662

652663
// Note: this is not a property because the minifier can't work correctly with

0 commit comments

Comments
 (0)