From 4ad573326dc676bf934b5b21461e17fb5a89068e Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Thu, 23 Apr 2020 10:28:16 -0700 Subject: [PATCH] Remove "cyclic" references (#2969) --- packages/firestore/src/api/database.ts | 50 +++++------ packages/firestore/src/core/query.ts | 90 +++++-------------- .../firestore/src/core/snapshot_version.ts | 6 +- packages/firestore/src/core/sync_engine.ts | 8 +- packages/firestore/src/core/transaction.ts | 10 +-- .../src/local/index_free_query_engine.ts | 4 +- .../local/indexeddb_remote_document_cache.ts | 14 +-- .../firestore/src/local/indexeddb_schema.ts | 2 +- .../src/local/local_documents_view.ts | 4 +- .../firestore/src/local/local_serializer.ts | 2 +- packages/firestore/src/local/local_store.ts | 16 ++-- .../src/local/memory_remote_document_cache.ts | 2 +- .../src/local/memory_target_cache.ts | 2 +- .../src/local/remote_document_cache.ts | 2 +- .../src/local/simple_query_engine.ts | 2 +- packages/firestore/src/local/target_data.ts | 4 +- packages/firestore/src/model/mutation.ts | 13 +-- packages/firestore/src/remote/remote_event.ts | 2 +- packages/firestore/src/remote/remote_store.ts | 6 +- packages/firestore/src/remote/serializer.ts | 38 ++++---- packages/firestore/src/remote/watch_change.ts | 2 +- .../firestore/src/util/input_validation.ts | 8 +- .../test/integration/remote/remote.test.ts | 8 +- .../local/index_free_query_engine.test.ts | 4 +- .../unit/local/indexeddb_persistence.test.ts | 2 +- .../test/unit/local/local_store.test.ts | 4 +- .../unit/local/lru_garbage_collector.test.ts | 2 +- .../unit/local/remote_document_cache.test.ts | 8 +- .../test/unit/local/target_cache.test.ts | 4 +- .../test/unit/model/mutation.test.ts | 4 +- .../test/unit/remote/remote_event.test.ts | 8 +- .../test/unit/remote/serializer.helper.ts | 44 ++++----- .../test/unit/specs/limbo_spec.test.ts | 2 +- .../firestore/test/unit/specs/spec_builder.ts | 4 +- .../test/unit/specs/spec_test_runner.ts | 4 +- packages/firestore/test/util/helpers.ts | 18 ++-- 36 files changed, 182 insertions(+), 221 deletions(-) diff --git a/packages/firestore/src/api/database.ts b/packages/firestore/src/api/database.ts index 6844571322b..89356b9d82c 100644 --- a/packages/firestore/src/api/database.ts +++ b/packages/firestore/src/api/database.ts @@ -69,7 +69,7 @@ import { validateStringEnum, valueDescription } from '../util/input_validation'; -import { logError, setLogLevel, LogLevel, getLogLevel } from '../util/log'; +import { getLogLevel, logError, LogLevel, setLogLevel } from '../util/log'; import { AutoId } from '../util/misc'; import { Deferred, Rejecter, Resolver } from '../util/promise'; import { FieldPath as ExternalFieldPath } from './field_path'; @@ -836,7 +836,7 @@ export class WriteBatch implements firestore.WriteBatch { convertedValue ); this._mutations = this._mutations.concat( - parsed.toMutations(ref._key, Precondition.NONE) + parsed.toMutations(ref._key, Precondition.none()) ); return this; } @@ -906,7 +906,7 @@ export class WriteBatch implements firestore.WriteBatch { this._firestore ); this._mutations = this._mutations.concat( - new DeleteMutation(ref._key, Precondition.NONE) + new DeleteMutation(ref._key, Precondition.none()) ); return this; } @@ -1031,7 +1031,7 @@ export class DocumentReference ) : this.firestore._dataReader.parseSetData(functionName, convertedValue); return this._firestoreClient.write( - parsed.toMutations(this._key, Precondition.NONE) + parsed.toMutations(this._key, Precondition.none()) ); } @@ -1075,7 +1075,7 @@ export class DocumentReference delete(): Promise { validateExactNumberOfArgs('DocumentReference.delete', arguments, 0); return this._firestoreClient.write([ - new DeleteMutation(this._key, Precondition.NONE) + new DeleteMutation(this._key, Precondition.none()) ]); } @@ -1447,32 +1447,31 @@ export class Query implements firestore.Query { // Enumerated from the WhereFilterOp type in index.d.ts. const whereFilterOpEnums = [ - '<', - '<=', - '==', - '>=', - '>', - 'array-contains', - 'in', - 'array-contains-any' + Operator.LESS_THAN, + Operator.LESS_THAN_OR_EQUAL, + Operator.EQUAL, + Operator.GREATER_THAN_OR_EQUAL, + Operator.GREATER_THAN, + Operator.ARRAY_CONTAINS, + Operator.IN, + Operator.ARRAY_CONTAINS_ANY ]; - validateStringEnum('Query.where', whereFilterOpEnums, 2, opStr); + const op = validateStringEnum('Query.where', whereFilterOpEnums, 2, opStr); let fieldValue: api.Value; const fieldPath = fieldPathFromArgument('Query.where', field); - const operator = Operator.fromString(opStr); if (fieldPath.isKeyField()) { if ( - operator === Operator.ARRAY_CONTAINS || - operator === Operator.ARRAY_CONTAINS_ANY + op === Operator.ARRAY_CONTAINS || + op === Operator.ARRAY_CONTAINS_ANY ) { throw new FirestoreError( Code.INVALID_ARGUMENT, - `Invalid Query. You can't perform '${operator.toString()}' ` + + `Invalid Query. You can't perform '${op}' ` + 'queries on FieldPath.documentId().' ); - } else if (operator === Operator.IN) { - this.validateDisjunctiveFilterElements(value, operator); + } else if (op === Operator.IN) { + this.validateDisjunctiveFilterElements(value, op); const referenceList: api.Value[] = []; for (const arrayValue of value as api.Value[]) { referenceList.push(this.parseDocumentIdValue(arrayValue)); @@ -1482,20 +1481,17 @@ export class Query implements firestore.Query { fieldValue = this.parseDocumentIdValue(value); } } else { - if ( - operator === Operator.IN || - operator === Operator.ARRAY_CONTAINS_ANY - ) { - this.validateDisjunctiveFilterElements(value, operator); + if (op === Operator.IN || op === Operator.ARRAY_CONTAINS_ANY) { + this.validateDisjunctiveFilterElements(value, op); } fieldValue = this.firestore._dataReader.parseQueryValue( 'Query.where', value, // We only allow nested arrays for IN queries. - /** allowArrays = */ operator === Operator.IN ? true : false + /** allowArrays = */ op === Operator.IN ); } - const filter = FieldFilter.create(fieldPath, operator, fieldValue); + const filter = FieldFilter.create(fieldPath, op, fieldValue); this.validateNewFilter(filter); return new Query( this._query.addFilter(filter), diff --git a/packages/firestore/src/core/query.ts b/packages/firestore/src/core/query.ts index 9328607109e..7f3e2a6820c 100644 --- a/packages/firestore/src/core/query.ts +++ b/packages/firestore/src/core/query.ts @@ -80,20 +80,20 @@ export class Query { get orderBy(): OrderBy[] { if (this.memoizedOrderBy === null) { + this.memoizedOrderBy = []; + const inequalityField = this.getInequalityFilterField(); const firstOrderByField = this.getFirstOrderByField(); if (inequalityField !== null && firstOrderByField === null) { // In order to implicitly add key ordering, we must also add the // inequality filter field for it to be a valid query. // Note that the default inequality field and key ordering is ascending. - if (inequalityField.isKeyField()) { - this.memoizedOrderBy = [KEY_ORDERING_ASC]; - } else { - this.memoizedOrderBy = [ - new OrderBy(inequalityField), - KEY_ORDERING_ASC - ]; + if (!inequalityField.isKeyField()) { + this.memoizedOrderBy.push(new OrderBy(inequalityField)); } + this.memoizedOrderBy.push( + new OrderBy(FieldPath.keyField(), Direction.ASCENDING) + ); } else { debugAssert( inequalityField === null || @@ -101,7 +101,6 @@ export class Query { inequalityField.isEqual(firstOrderByField)), 'First orderBy should match inequality field.' ); - this.memoizedOrderBy = []; let foundKeyOrdering = false; for (const orderBy of this.explicitOrderBy) { this.memoizedOrderBy.push(orderBy); @@ -117,9 +116,7 @@ export class Query { ? this.explicitOrderBy[this.explicitOrderBy.length - 1].dir : Direction.ASCENDING; this.memoizedOrderBy.push( - lastDirection === Direction.ASCENDING - ? KEY_ORDERING_ASC - : KEY_ORDERING_DESC + new OrderBy(FieldPath.keyField(), lastDirection) ); } } @@ -468,48 +465,15 @@ export abstract class Filter { abstract isEqual(filter: Filter): boolean; } -export class Operator { - static LESS_THAN = new Operator('<'); - static LESS_THAN_OR_EQUAL = new Operator('<='); - static EQUAL = new Operator('=='); - static GREATER_THAN = new Operator('>'); - static GREATER_THAN_OR_EQUAL = new Operator('>='); - static ARRAY_CONTAINS = new Operator('array-contains'); - static IN = new Operator('in'); - static ARRAY_CONTAINS_ANY = new Operator('array-contains-any'); - - static fromString(op: string): Operator { - switch (op) { - case '<': - return Operator.LESS_THAN; - case '<=': - return Operator.LESS_THAN_OR_EQUAL; - case '==': - return Operator.EQUAL; - case '>=': - return Operator.GREATER_THAN_OR_EQUAL; - case '>': - return Operator.GREATER_THAN; - case 'array-contains': - return Operator.ARRAY_CONTAINS; - case 'in': - return Operator.IN; - case 'array-contains-any': - return Operator.ARRAY_CONTAINS_ANY; - default: - return fail('Unknown FieldFilter operator: ' + op); - } - } - - constructor(public name: string) {} - - toString(): string { - return this.name; - } - - isEqual(other: Operator): boolean { - return this.name === other.name; - } +export const enum Operator { + LESS_THAN = '<', + LESS_THAN_OR_EQUAL = '<=', + EQUAL = '==', + GREATER_THAN = '>', + GREATER_THAN_OR_EQUAL = '>=', + ARRAY_CONTAINS = 'array-contains', + IN = 'in', + ARRAY_CONTAINS_ANY = 'array-contains-any' } export class FieldFilter extends Filter { @@ -635,7 +599,7 @@ export class FieldFilter extends Filter { isEqual(other: Filter): boolean { if (other instanceof FieldFilter) { return ( - this.op.isEqual(other.op) && + this.op === other.op && this.field.isEqual(other.field) && valueEquals(this.value, other.value) ); @@ -737,15 +701,9 @@ export class ArrayContainsAnyFilter extends FieldFilter { /** * The direction of sorting in an order by. */ -export class Direction { - static ASCENDING = new Direction('asc'); - static DESCENDING = new Direction('desc'); - - private constructor(public name: string) {} - - toString(): string { - return this.name; - } +export const enum Direction { + ASCENDING = 'asc', + DESCENDING = 'desc' } /** @@ -875,9 +833,3 @@ export class OrderBy { return this.dir === other.dir && this.field.isEqual(other.field); } } - -const KEY_ORDERING_ASC = new OrderBy(FieldPath.keyField(), Direction.ASCENDING); -const KEY_ORDERING_DESC = new OrderBy( - FieldPath.keyField(), - Direction.DESCENDING -); diff --git a/packages/firestore/src/core/snapshot_version.ts b/packages/firestore/src/core/snapshot_version.ts index 71f1a7b12fe..b73ea960c9e 100644 --- a/packages/firestore/src/core/snapshot_version.ts +++ b/packages/firestore/src/core/snapshot_version.ts @@ -22,14 +22,12 @@ import { Timestamp } from '../api/timestamp'; * timestamp, such as update_time or read_time. */ export class SnapshotVersion { - static readonly MIN = new SnapshotVersion(new Timestamp(0, 0)); - static fromTimestamp(value: Timestamp): SnapshotVersion { return new SnapshotVersion(value); } - static forDeletedDoc(): SnapshotVersion { - return SnapshotVersion.MIN; + static min(): SnapshotVersion { + return new SnapshotVersion(new Timestamp(0, 0)); } private constructor(private timestamp: Timestamp) {} diff --git a/packages/firestore/src/core/sync_engine.ts b/packages/firestore/src/core/sync_engine.ts index 50ac6a3eec5..b1a49181683 100644 --- a/packages/firestore/src/core/sync_engine.ts +++ b/packages/firestore/src/core/sync_engine.ts @@ -33,7 +33,7 @@ import { import { MaybeDocument, NoDocument } from '../model/document'; import { DocumentKey } from '../model/document_key'; import { Mutation } from '../model/mutation'; -import { MutationBatchResult, BATCHID_UNKNOWN } from '../model/mutation_batch'; +import { BATCHID_UNKNOWN, MutationBatchResult } from '../model/mutation_batch'; import { RemoteEvent, TargetChange } from '../remote/remote_event'; import { RemoteStore } from '../remote/remote_store'; import { RemoteSyncer } from '../remote/remote_syncer'; @@ -52,7 +52,7 @@ import { } from '../local/shared_client_state_syncer'; import { SortedSet } from '../util/sorted_set'; import { ListenSequence } from './listen_sequence'; -import { Query, LimitType } from './query'; +import { LimitType, Query } from './query'; import { SnapshotVersion } from './snapshot_version'; import { Target } from './target'; import { TargetIdGenerator } from './target_id_generator'; @@ -504,11 +504,11 @@ export class SyncEngine implements RemoteSyncer { ); documentUpdates = documentUpdates.insert( limboKey, - new NoDocument(limboKey, SnapshotVersion.forDeletedDoc()) + new NoDocument(limboKey, SnapshotVersion.min()) ); const resolvedLimboDocuments = documentKeySet().add(limboKey); const event = new RemoteEvent( - SnapshotVersion.MIN, + SnapshotVersion.min(), /* targetChanges= */ new Map(), /* targetMismatches= */ new SortedSet(primitiveComparator), documentUpdates, diff --git a/packages/firestore/src/core/transaction.ts b/packages/firestore/src/core/transaction.ts index 91a90bc19c7..a2268a01bc8 100644 --- a/packages/firestore/src/core/transaction.ts +++ b/packages/firestore/src/core/transaction.ts @@ -17,7 +17,7 @@ import { ParsedSetData, ParsedUpdateData } from '../api/user_data_reader'; import { documentVersionMap } from '../model/collections'; -import { Document, NoDocument, MaybeDocument } from '../model/document'; +import { Document, MaybeDocument, NoDocument } from '../model/document'; import { DocumentKey } from '../model/document_key'; import { @@ -27,7 +27,7 @@ import { VerifyMutation } from '../model/mutation'; import { Datastore } from '../remote/datastore'; -import { fail, debugAssert } from '../util/assert'; +import { debugAssert, fail } from '../util/assert'; import { Code, FirestoreError } from '../util/error'; import { SnapshotVersion } from './snapshot_version'; @@ -123,7 +123,7 @@ export class Transaction { docVersion = doc.version; } else if (doc instanceof NoDocument) { // For deleted docs, we must use baseVersion 0 when we overwrite them. - docVersion = SnapshotVersion.forDeletedDoc(); + docVersion = SnapshotVersion.min(); } else { throw fail('Document in a transaction was a ' + doc.constructor.name); } @@ -151,7 +151,7 @@ export class Transaction { if (!this.writtenDocs.has(key) && version) { return Precondition.updateTime(version); } else { - return Precondition.NONE; + return Precondition.none(); } } @@ -163,7 +163,7 @@ export class Transaction { // The first time a document is written, we want to take into account the // read time and existence if (!this.writtenDocs.has(key) && version) { - if (version.isEqual(SnapshotVersion.forDeletedDoc())) { + if (version.isEqual(SnapshotVersion.min())) { // The document doesn't exist, so fail the transaction. // This has to be validated locally because you can't send a diff --git a/packages/firestore/src/local/index_free_query_engine.ts b/packages/firestore/src/local/index_free_query_engine.ts index 86f3c131ee4..284803e0712 100644 --- a/packages/firestore/src/local/index_free_query_engine.ts +++ b/packages/firestore/src/local/index_free_query_engine.ts @@ -78,7 +78,7 @@ export class IndexFreeQueryEngine implements QueryEngine { // Queries that have never seen a snapshot without limbo free documents // should also be run as a full collection scan. - if (lastLimboFreeSnapshotVersion.isEqual(SnapshotVersion.MIN)) { + if (lastLimboFreeSnapshotVersion.isEqual(SnapshotVersion.min())) { return this.executeFullCollectionScan(transaction, query); } @@ -204,7 +204,7 @@ export class IndexFreeQueryEngine implements QueryEngine { return this.localDocumentsView!.getDocumentsMatchingQuery( transaction, query, - SnapshotVersion.MIN + SnapshotVersion.min() ); } } diff --git a/packages/firestore/src/local/indexeddb_remote_document_cache.ts b/packages/firestore/src/local/indexeddb_remote_document_cache.ts index 06d42ef0dce..cf073f2b766 100644 --- a/packages/firestore/src/local/indexeddb_remote_document_cache.ts +++ b/packages/firestore/src/local/indexeddb_remote_document_cache.ts @@ -252,7 +252,7 @@ export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache { const immediateChildrenPathLength = query.path.length + 1; const iterationOptions: IterateOptions = {}; - if (sinceReadTime.isEqual(SnapshotVersion.MIN)) { + if (sinceReadTime.isEqual(SnapshotVersion.min())) { // Documents are ordered by key, so we can use a prefix scan to narrow // down the documents we need to match the query against. const startKey = query.path.toArray(); @@ -330,7 +330,7 @@ export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache { /** * Returns the read time of the most recently read document in the cache, or - * SnapshotVersion.MIN if not available. + * SnapshotVersion.min() if not available. */ // PORTING NOTE: This is only used for multi-tab synchronization. getLastReadTime( @@ -338,8 +338,8 @@ export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache { ): PersistencePromise { const documentsStore = remoteDocumentsStore(transaction); - // If there are no existing entries, we return SnapshotVersion.MIN. - let readTime = SnapshotVersion.MIN; + // If there are no existing entries, we return SnapshotVersion.min(). + let readTime = SnapshotVersion.min(); return documentsStore .iterate( @@ -396,7 +396,7 @@ export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache { const doc = this.serializer.fromDbRemoteDocument(dbRemoteDoc); if ( doc instanceof NoDocument && - doc.version.isEqual(SnapshotVersion.forDeletedDoc()) + doc.version.isEqual(SnapshotVersion.min()) ) { // The document is a sentinel removal and should only be used in the // `getNewDocumentChanges()`. @@ -453,7 +453,7 @@ export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache { ); if (maybeDocument) { debugAssert( - !this.readTime.isEqual(SnapshotVersion.MIN), + !this.readTime.isEqual(SnapshotVersion.min()), 'Cannot add a document with a read time of zero' ); const doc = this.documentCache.serializer.toDbRemoteDocument( @@ -473,7 +473,7 @@ export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache { // with a version of 0 and ignored by `maybeDecodeDocument()` but // preserved in `getNewDocumentChanges()`. const deletedDoc = this.documentCache.serializer.toDbRemoteDocument( - new NoDocument(key, SnapshotVersion.forDeletedDoc()), + new NoDocument(key, SnapshotVersion.min()), this.readTime ); promises.push( diff --git a/packages/firestore/src/local/indexeddb_schema.ts b/packages/firestore/src/local/indexeddb_schema.ts index 6390af7e1a3..245279900d4 100644 --- a/packages/firestore/src/local/indexeddb_schema.ts +++ b/packages/firestore/src/local/indexeddb_schema.ts @@ -1011,7 +1011,7 @@ function writeEmptyTargetGlobalEntry( const metadata = new DbTargetGlobal( /*highestTargetId=*/ 0, /*lastListenSequenceNumber=*/ 0, - SnapshotVersion.MIN.toTimestamp(), + SnapshotVersion.min().toTimestamp(), /*targetCount=*/ 0 ); return globalStore.put(DbTargetGlobal.key, metadata); diff --git a/packages/firestore/src/local/local_documents_view.ts b/packages/firestore/src/local/local_documents_view.ts index 263a6aedd1a..75c43f8dafc 100644 --- a/packages/firestore/src/local/local_documents_view.ts +++ b/packages/firestore/src/local/local_documents_view.ts @@ -134,7 +134,7 @@ export class LocalDocumentsView { docs.forEach((key, maybeDoc) => { // TODO(http://b/32275378): Don't conflate missing / deleted. if (!maybeDoc) { - maybeDoc = new NoDocument(key, SnapshotVersion.forDeletedDoc()); + maybeDoc = new NoDocument(key, SnapshotVersion.min()); } results = results.insert(key, maybeDoc); }); @@ -148,7 +148,7 @@ export class LocalDocumentsView { * * @param transaction The persistence transaction. * @param query The query to match documents against. - * @param sinceReadTime If not set to SnapshotVersion.MIN, return only + * @param sinceReadTime If not set to SnapshotVersion.min(), return only * documents that have been read since this snapshot version (exclusive). */ getDocumentsMatchingQuery( diff --git a/packages/firestore/src/local/local_serializer.ts b/packages/firestore/src/local/local_serializer.ts index 495d4ee4ea4..e15697b934c 100644 --- a/packages/firestore/src/local/local_serializer.ts +++ b/packages/firestore/src/local/local_serializer.ts @@ -177,7 +177,7 @@ export class LocalSerializer { const lastLimboFreeSnapshotVersion = dbTarget.lastLimboFreeSnapshotVersion !== undefined ? this.fromDbTimestamp(dbTarget.lastLimboFreeSnapshotVersion) - : SnapshotVersion.MIN; + : SnapshotVersion.min(); let target: Target; if (isDocumentQuery(dbTarget.query)) { diff --git a/packages/firestore/src/local/local_store.ts b/packages/firestore/src/local/local_store.ts index d86a2a5a97d..1fcc424d874 100644 --- a/packages/firestore/src/local/local_store.ts +++ b/packages/firestore/src/local/local_store.ts @@ -193,7 +193,7 @@ export class LocalStore { * * PORTING NOTE: This is only used for multi-tab synchronization. */ - protected lastDocumentChangeReadTime = SnapshotVersion.MIN; + protected lastDocumentChangeReadTime = SnapshotVersion.min(); constructor( /** Manages our in-memory or durable persistence. */ @@ -563,13 +563,13 @@ export class LocalStore { // Note: The order of the steps below is important, since we want // to ensure that rejected limbo resolutions (which fabricate - // NoDocuments with SnapshotVersion.MIN) never add documents to + // NoDocuments with SnapshotVersion.min()) never add documents to // cache. if ( doc instanceof NoDocument && - doc.version.isEqual(SnapshotVersion.MIN) + doc.version.isEqual(SnapshotVersion.min()) ) { - // NoDocuments with SnapshotVersion.MIN are used in manufactured + // NoDocuments with SnapshotVersion.min() are used in manufactured // events. We remove these documents from cache since we lost // access. documentBuffer.removeEntry(key, remoteVersion); @@ -581,7 +581,7 @@ export class LocalStore { existingDoc.hasPendingWrites) ) { debugAssert( - !SnapshotVersion.MIN.isEqual(remoteVersion), + !SnapshotVersion.min().isEqual(remoteVersion), 'Cannot add a document when the remote version is zero' ); documentBuffer.addEntry(doc, remoteVersion); @@ -614,7 +614,7 @@ export class LocalStore { // can synthesize remote events when we get permission denied errors while // trying to resolve the state of a locally cached document that is in // limbo. - if (!remoteVersion.isEqual(SnapshotVersion.MIN)) { + if (!remoteVersion.isEqual(SnapshotVersion.min())) { const updateRemoteVersion = this.targetCache .getLastRemoteSnapshotVersion(txn) .next(lastRemoteSnapshotVersion => { @@ -910,7 +910,7 @@ export class LocalStore { query: Query, usePreviousResults: boolean ): Promise { - let lastLimboFreeSnapshotVersion = SnapshotVersion.MIN; + let lastLimboFreeSnapshotVersion = SnapshotVersion.min(); let remoteKeys = documentKeySet(); return this.persistence.runTransaction('Execute query', 'readonly', txn => { @@ -932,7 +932,7 @@ export class LocalStore { query, usePreviousResults ? lastLimboFreeSnapshotVersion - : SnapshotVersion.MIN, + : SnapshotVersion.min(), usePreviousResults ? remoteKeys : documentKeySet() ) ) diff --git a/packages/firestore/src/local/memory_remote_document_cache.ts b/packages/firestore/src/local/memory_remote_document_cache.ts index 4c53ed9551b..c8b147e6785 100644 --- a/packages/firestore/src/local/memory_remote_document_cache.ts +++ b/packages/firestore/src/local/memory_remote_document_cache.ts @@ -78,7 +78,7 @@ export class MemoryRemoteDocumentCache implements RemoteDocumentCache { readTime: SnapshotVersion ): PersistencePromise { debugAssert( - !readTime.isEqual(SnapshotVersion.MIN), + !readTime.isEqual(SnapshotVersion.min()), 'Cannot add a document with a read time of zero' ); diff --git a/packages/firestore/src/local/memory_target_cache.ts b/packages/firestore/src/local/memory_target_cache.ts index d33cfbe41f2..a915c795ffc 100644 --- a/packages/firestore/src/local/memory_target_cache.ts +++ b/packages/firestore/src/local/memory_target_cache.ts @@ -39,7 +39,7 @@ export class MemoryTargetCache implements TargetCache { private targets = new ObjectMap(t => t.canonicalId()); /** The last received snapshot version. */ - private lastRemoteSnapshotVersion = SnapshotVersion.MIN; + private lastRemoteSnapshotVersion = SnapshotVersion.min(); /** The highest numbered target ID encountered. */ private highestTargetId: TargetId = 0; /** The highest sequence number encountered. */ diff --git a/packages/firestore/src/local/remote_document_cache.ts b/packages/firestore/src/local/remote_document_cache.ts index a538c28e8b6..24deb9f7c41 100644 --- a/packages/firestore/src/local/remote_document_cache.ts +++ b/packages/firestore/src/local/remote_document_cache.ts @@ -71,7 +71,7 @@ export interface RemoteDocumentCache { * Cached NoDocument entries have no bearing on query results. * * @param query The query to match documents against. - * @param sinceReadTime If not set to SnapshotVersion.MIN, return only + * @param sinceReadTime If not set to SnapshotVersion.min(), return only * documents that have been read since this snapshot version (exclusive). * @return The set of matching documents. */ diff --git a/packages/firestore/src/local/simple_query_engine.ts b/packages/firestore/src/local/simple_query_engine.ts index 2a228e63eb2..a9f20d14f4e 100644 --- a/packages/firestore/src/local/simple_query_engine.ts +++ b/packages/firestore/src/local/simple_query_engine.ts @@ -52,7 +52,7 @@ export class SimpleQueryEngine implements QueryEngine { return this.localDocumentsView.getDocumentsMatchingQuery( transaction, query, - SnapshotVersion.MIN + SnapshotVersion.min() ); } } diff --git a/packages/firestore/src/local/target_data.ts b/packages/firestore/src/local/target_data.ts index d5284c2d899..95237e574a7 100644 --- a/packages/firestore/src/local/target_data.ts +++ b/packages/firestore/src/local/target_data.ts @@ -54,12 +54,12 @@ export class TargetData { */ readonly sequenceNumber: ListenSequenceNumber, /** The latest snapshot version seen for this target. */ - readonly snapshotVersion: SnapshotVersion = SnapshotVersion.MIN, + readonly snapshotVersion: SnapshotVersion = SnapshotVersion.min(), /** * The maximum snapshot version at which the associated view * contained no limbo documents. */ - readonly lastLimboFreeSnapshotVersion: SnapshotVersion = SnapshotVersion.MIN, + readonly lastLimboFreeSnapshotVersion: SnapshotVersion = SnapshotVersion.min(), /** * An opaque, server-assigned token that allows watching a target to be * resumed after disconnecting without retransmitting all the data that diff --git a/packages/firestore/src/model/mutation.ts b/packages/firestore/src/model/mutation.ts index 268ee43afca..b65980439ba 100644 --- a/packages/firestore/src/model/mutation.ts +++ b/packages/firestore/src/model/mutation.ts @@ -133,8 +133,6 @@ export const enum MutationType { * (meaning no precondition). */ export class Precondition { - static readonly NONE = new Precondition(); - private constructor( readonly updateTime?: SnapshotVersion, readonly exists?: boolean @@ -145,6 +143,11 @@ export class Precondition { ); } + /** Creates a new empty Precondition. */ + static none(): Precondition { + return new Precondition(); + } + /** Creates a new Precondition with an exists flag. */ static exists(exists: boolean): Precondition { return new Precondition(undefined, exists); @@ -314,7 +317,7 @@ export abstract class Mutation { * Returns the version from the given document for use as the result of a * mutation. Mutations are defined to return the version of the base document * only if it is an existing document. Deleted and unknown documents have a - * post-mutation version of SnapshotVersion.MIN. + * post-mutation version of SnapshotVersion.min(). */ protected static getPostMutationVersion( maybeDoc: MaybeDocument | null @@ -322,7 +325,7 @@ export abstract class Mutation { if (maybeDoc instanceof Document) { return maybeDoc.version; } else { - return SnapshotVersion.MIN; + return SnapshotVersion.min(); } } } @@ -781,7 +784,7 @@ export class DeleteMutation extends Mutation { 'Can only apply mutation to document with same key' ); } - return new NoDocument(this.key, SnapshotVersion.forDeletedDoc()); + return new NoDocument(this.key, SnapshotVersion.min()); } extractBaseValue(maybeDoc: MaybeDocument | null): null { diff --git a/packages/firestore/src/remote/remote_event.ts b/packages/firestore/src/remote/remote_event.ts index af9ed6eaa06..f85c3a42763 100644 --- a/packages/firestore/src/remote/remote_event.ts +++ b/packages/firestore/src/remote/remote_event.ts @@ -78,7 +78,7 @@ export class RemoteEvent { ) ); return new RemoteEvent( - SnapshotVersion.MIN, + SnapshotVersion.min(), targetChanges, targetIdSet(), maybeDocumentMap(), diff --git a/packages/firestore/src/remote/remote_store.ts b/packages/firestore/src/remote/remote_store.ts index dd3b5b5b97f..cb7bcbc8b68 100644 --- a/packages/firestore/src/remote/remote_store.ts +++ b/packages/firestore/src/remote/remote_store.ts @@ -402,11 +402,11 @@ export class RemoteStore implements TargetMetadataProvider { this.watchChangeAggregator!.handleTargetChange(watchChange); } - if (!snapshotVersion.isEqual(SnapshotVersion.MIN)) { + if (!snapshotVersion.isEqual(SnapshotVersion.min())) { const lastRemoteSnapshotVersion = await this.localStore.getLastRemoteSnapshotVersion(); if (snapshotVersion.compareTo(lastRemoteSnapshotVersion) >= 0) { // We have received a target change with a global snapshot if the snapshot - // version is not equal to SnapshotVersion.MIN. + // version is not equal to SnapshotVersion.min(). await this.raiseWatchSnapshot(snapshotVersion); } } @@ -419,7 +419,7 @@ export class RemoteStore implements TargetMetadataProvider { */ private raiseWatchSnapshot(snapshotVersion: SnapshotVersion): Promise { debugAssert( - !snapshotVersion.isEqual(SnapshotVersion.MIN), + !snapshotVersion.isEqual(SnapshotVersion.min()), "Can't raise event for unknown SnapshotVersion" ); const remoteEvent = this.watchChangeAggregator!.createRemoteEvent( diff --git a/packages/firestore/src/remote/serializer.ts b/packages/firestore/src/remote/serializer.ts index bd105a63460..be94570b37f 100644 --- a/packages/firestore/src/remote/serializer.ts +++ b/packages/firestore/src/remote/serializer.ts @@ -77,21 +77,21 @@ import { isNanValue, isNullValue, normalizeTimestamp } from '../model/values'; const DIRECTIONS = (() => { const dirs: { [dir: string]: api.OrderDirection } = {}; - dirs[Direction.ASCENDING.name] = 'ASCENDING'; - dirs[Direction.DESCENDING.name] = 'DESCENDING'; + dirs[Direction.ASCENDING] = 'ASCENDING'; + dirs[Direction.DESCENDING] = 'DESCENDING'; return dirs; })(); const OPERATORS = (() => { const ops: { [op: string]: api.FieldFilterOp } = {}; - ops[Operator.LESS_THAN.name] = 'LESS_THAN'; - ops[Operator.LESS_THAN_OR_EQUAL.name] = 'LESS_THAN_OR_EQUAL'; - ops[Operator.GREATER_THAN.name] = 'GREATER_THAN'; - ops[Operator.GREATER_THAN_OR_EQUAL.name] = 'GREATER_THAN_OR_EQUAL'; - ops[Operator.EQUAL.name] = 'EQUAL'; - ops[Operator.ARRAY_CONTAINS.name] = 'ARRAY_CONTAINS'; - ops[Operator.IN.name] = 'IN'; - ops[Operator.ARRAY_CONTAINS_ANY.name] = 'ARRAY_CONTAINS_ANY'; + ops[Operator.LESS_THAN] = 'LESS_THAN'; + ops[Operator.LESS_THAN_OR_EQUAL] = 'LESS_THAN_OR_EQUAL'; + ops[Operator.GREATER_THAN] = 'GREATER_THAN'; + ops[Operator.GREATER_THAN_OR_EQUAL] = 'GREATER_THAN_OR_EQUAL'; + ops[Operator.EQUAL] = 'EQUAL'; + ops[Operator.ARRAY_CONTAINS] = 'ARRAY_CONTAINS'; + ops[Operator.IN] = 'IN'; + ops[Operator.ARRAY_CONTAINS_ANY] = 'ARRAY_CONTAINS_ANY'; return ops; })(); @@ -467,7 +467,7 @@ export class JsonProtoSerializer { const key = this.fromName(docDelete.document); const version = docDelete.readTime ? this.fromVersion(docDelete.readTime) - : SnapshotVersion.forDeletedDoc(); + : SnapshotVersion.min(); const doc = new NoDocument(key, version); const removedTargetIds = docDelete.removedTargetIds || []; watchChange = new DocumentWatchChange([], removedTargetIds, doc.key, doc); @@ -516,14 +516,14 @@ export class JsonProtoSerializer { // is a read_time set and it applies to all targets (i.e. the list of // targets is empty). The backend is guaranteed to send such responses. if (!('targetChange' in change)) { - return SnapshotVersion.MIN; + return SnapshotVersion.min(); } const targetChange = change.targetChange!; if (targetChange.targetIds && targetChange.targetIds.length) { - return SnapshotVersion.MIN; + return SnapshotVersion.min(); } if (!targetChange.readTime) { - return SnapshotVersion.MIN; + return SnapshotVersion.min(); } return this.fromVersion(targetChange.readTime); } @@ -568,7 +568,7 @@ export class JsonProtoSerializer { fromMutation(proto: api.Write): Mutation { const precondition = proto.currentDocument ? this.fromPrecondition(proto.currentDocument) - : Precondition.NONE; + : Precondition.none(); if (proto.update) { assertPresent(proto.update.name, 'name'); @@ -622,7 +622,7 @@ export class JsonProtoSerializer { } else if (precondition.exists !== undefined) { return Precondition.exists(precondition.exists); } else { - return Precondition.NONE; + return Precondition.none(); } } @@ -635,7 +635,7 @@ export class JsonProtoSerializer { ? this.fromVersion(proto.updateTime) : this.fromVersion(commitTime); - if (version.isEqual(SnapshotVersion.MIN)) { + if (version.isEqual(SnapshotVersion.min())) { // The Firestore Emulator currently returns an update time of 0 for // deletes of non-existing documents (rather than null). This breaks the // test "get deleted doc while offline with source=cache" as NoDocuments @@ -947,7 +947,7 @@ export class JsonProtoSerializer { // visible for testing toDirection(dir: Direction): api.OrderDirection { - return DIRECTIONS[dir.name]; + return DIRECTIONS[dir]; } // visible for testing @@ -964,7 +964,7 @@ export class JsonProtoSerializer { // visible for testing toOperatorName(op: Operator): api.FieldFilterOp { - return OPERATORS[op.name]; + return OPERATORS[op]; } fromOperatorName(op: api.FieldFilterOp): Operator { diff --git a/packages/firestore/src/remote/watch_change.ts b/packages/firestore/src/remote/watch_change.ts index d33efd917f7..457173c5b08 100644 --- a/packages/firestore/src/remote/watch_change.ts +++ b/packages/firestore/src/remote/watch_change.ts @@ -399,7 +399,7 @@ export class WatchChangeAggregator { this.removeDocumentFromTarget( targetId, key, - new NoDocument(key, SnapshotVersion.forDeletedDoc()) + new NoDocument(key, SnapshotVersion.min()) ); } else { hardAssert( diff --git a/packages/firestore/src/util/input_validation.ts b/packages/firestore/src/util/input_validation.ts index 1ee0031255b..fe15c26c4d2 100644 --- a/packages/firestore/src/util/input_validation.ts +++ b/packages/firestore/src/util/input_validation.ts @@ -297,14 +297,15 @@ export function validateNamedOptionalPropertyEquals( * @param functionName Function making the validation call. * @param enums Array containing all possible values for the enum. * @param position Position of the argument in `functionName`. - * @param argument Arugment to validate. + * @param argument Argument to validate. + * @return The value as T if the argument can be converted. */ export function validateStringEnum( functionName: string, - enums: string[], + enums: T[], position: number, argument: unknown -): void { +): T { if (!enums.some(element => element === argument)) { throw new FirestoreError( Code.INVALID_ARGUMENT, @@ -313,6 +314,7 @@ export function validateStringEnum( `values: ${enums.join(', ')}` ); } + return argument as T; } /** Helper to validate the type of a provided input. */ diff --git a/packages/firestore/test/integration/remote/remote.test.ts b/packages/firestore/test/integration/remote/remote.test.ts index a305f8cb4bd..cb525b91f96 100644 --- a/packages/firestore/test/integration/remote/remote.test.ts +++ b/packages/firestore/test/integration/remote/remote.test.ts @@ -38,7 +38,7 @@ describe('Remote Storage', () => { expect(result.length).to.equal(1); const version = result[0].version; expect(version).not.to.equal(null); - expect(SnapshotVersion.MIN.compareTo(version!)).to.be.lessThan(0); + expect(SnapshotVersion.min().compareTo(version!)).to.be.lessThan(0); }); }); }); @@ -61,7 +61,7 @@ describe('Remote Storage', () => { if (doc instanceof Document) { expect(doc.data()).to.deep.equal(mutation.value); expect(doc.key).to.deep.equal(k); - expect(SnapshotVersion.MIN.compareTo(doc.version)).to.be.lessThan( + expect(SnapshotVersion.min().compareTo(doc.version)).to.be.lessThan( 0 ); } @@ -78,7 +78,9 @@ describe('Remote Storage', () => { expect(doc).to.be.an.instanceof(NoDocument); if (doc instanceof NoDocument) { expect(doc.key).to.deep.equal(k); - expect(SnapshotVersion.MIN.compareTo(doc.version)).to.be.lessThan(0); + expect(SnapshotVersion.min().compareTo(doc.version)).to.be.lessThan( + 0 + ); } }); }); diff --git a/packages/firestore/test/unit/local/index_free_query_engine.test.ts b/packages/firestore/test/unit/local/index_free_query_engine.test.ts index 15e3560fccf..d9d600299e2 100644 --- a/packages/firestore/test/unit/local/index_free_query_engine.test.ts +++ b/packages/firestore/test/unit/local/index_free_query_engine.test.ts @@ -60,7 +60,7 @@ const MATCHING_DOC_B = doc('coll/b', 1, { matches: true, order: 2 }); const UPDATED_MATCHING_DOC_B = doc('coll/b', 11, { matches: true, order: 2 }); const LAST_LIMBO_FREE_SNAPSHOT = version(10); -const MISSING_LAST_LIMBO_FREE_SNAPSHOT = SnapshotVersion.MIN; +const MISSING_LAST_LIMBO_FREE_SNAPSHOT = SnapshotVersion.min(); /** * A LocalDocumentsView wrapper that inspects the arguments to @@ -74,7 +74,7 @@ class TestLocalDocumentsView extends LocalDocumentsView { query: Query, sinceReadTime: SnapshotVersion ): PersistencePromise { - const indexFreeExecution = !SnapshotVersion.MIN.isEqual(sinceReadTime); + const indexFreeExecution = !SnapshotVersion.min().isEqual(sinceReadTime); expect(indexFreeExecution).to.eq( this.expectIndexFreeExecution, diff --git a/packages/firestore/test/unit/local/indexeddb_persistence.test.ts b/packages/firestore/test/unit/local/indexeddb_persistence.test.ts index 92d5b6f31a2..2b4168ced98 100644 --- a/packages/firestore/test/unit/local/indexeddb_persistence.test.ts +++ b/packages/firestore/test/unit/local/indexeddb_persistence.test.ts @@ -224,7 +224,7 @@ describe('IndexedDbSchema: createOrUpgradeDb', () => { const resetTargetGlobal = new DbTargetGlobal( /*highestTargetId=*/ 0, /*highestListenSequencNumber=*/ 0, - /*lastRemoteSnapshotVersion=*/ SnapshotVersion.MIN.toTimestamp(), + /*lastRemoteSnapshotVersion=*/ SnapshotVersion.min().toTimestamp(), /*targetCount=*/ 0 ); diff --git a/packages/firestore/test/unit/local/local_store.test.ts b/packages/firestore/test/unit/local/local_store.test.ts index e919d12ff69..dcab1919868 100644 --- a/packages/firestore/test/unit/local/local_store.test.ts +++ b/packages/firestore/test/unit/local/local_store.test.ts @@ -1457,7 +1457,7 @@ function genericLocalStoreTests( .afterAllocatingQuery(query) .toReturnTargetId(2) .afterMutations([ - patchMutation('foo/bar', {}, Precondition.NONE), + patchMutation('foo/bar', {}, Precondition.none()), transformMutation('foo/bar', { sum: PublicFieldValue.increment(1) }) ]) .toReturnChanged( @@ -1620,7 +1620,7 @@ function genericLocalStoreTests( ); expect( cachedTargetData!.lastLimboFreeSnapshotVersion.isEqual( - SnapshotVersion.MIN + SnapshotVersion.min() ) ).to.be.true; diff --git a/packages/firestore/test/unit/local/lru_garbage_collector.test.ts b/packages/firestore/test/unit/local/lru_garbage_collector.test.ts index b859f7eed40..8d6c455efd6 100644 --- a/packages/firestore/test/unit/local/lru_garbage_collector.test.ts +++ b/packages/firestore/test/unit/local/lru_garbage_collector.test.ts @@ -276,7 +276,7 @@ function genericLruGarbageCollectorTests( return new SetMutation( key, wrapObject({ baz: 'hello', world: 2 }), - Precondition.NONE + Precondition.none() ); } diff --git a/packages/firestore/test/unit/local/remote_document_cache.test.ts b/packages/firestore/test/unit/local/remote_document_cache.test.ts index c15701a9a1b..c84429f0563 100644 --- a/packages/firestore/test/unit/local/remote_document_cache.test.ts +++ b/packages/firestore/test/unit/local/remote_document_cache.test.ts @@ -125,7 +125,7 @@ describe('IndexedDbRemoteDocumentCache', () => { ); let { changedDocs, readTime } = await cache.getNewDocumentChanges( - SnapshotVersion.MIN + SnapshotVersion.min() ); assertMatches( [ @@ -143,7 +143,7 @@ describe('IndexedDbRemoteDocumentCache', () => { it('can get empty changes', async () => { const { changedDocs } = await cache.getNewDocumentChanges( - SnapshotVersion.MIN + SnapshotVersion.min() ); assertMatches([], changedDocs); }); @@ -160,7 +160,7 @@ describe('IndexedDbRemoteDocumentCache', () => { await cache.removeEntry(key('a/2'), version(4)); const { changedDocs } = await cache.getNewDocumentChanges( - SnapshotVersion.MIN + SnapshotVersion.min() ); assertMatches( [doc('a/1', 1, DOC_DATA), removedDoc('a/2'), doc('a/3', 3, DOC_DATA)], @@ -378,7 +378,7 @@ function genericRemoteDocumentCacheTests( const query = new Query(path('b')); const matchingDocs = await cache.getDocumentsMatchingQuery( query, - SnapshotVersion.MIN + SnapshotVersion.min() ); assertMatches( diff --git a/packages/firestore/test/unit/local/target_cache.test.ts b/packages/firestore/test/unit/local/target_cache.test.ts index 3229d2dc410..4aeddd94a65 100644 --- a/packages/firestore/test/unit/local/target_cache.test.ts +++ b/packages/firestore/test/unit/local/target_cache.test.ts @@ -135,7 +135,7 @@ function genericTargetCacheTests( TargetPurpose.Listen, ++previousSequenceNumber, snapshotVersion, - /* lastLimboFreeSnapshotVersion= */ SnapshotVersion.MIN, + /* lastLimboFreeSnapshotVersion= */ SnapshotVersion.min(), resumeToken ); } @@ -349,7 +349,7 @@ function genericTargetCacheTests( it('can get / set targets metadata', async () => { expect(await cache.getLastRemoteSnapshotVersion()).to.deep.equal( - SnapshotVersion.MIN + SnapshotVersion.min() ); // Can set the snapshot version. diff --git a/packages/firestore/test/unit/model/mutation.test.ts b/packages/firestore/test/unit/model/mutation.test.ts index 13834606de5..d4e68cc27f1 100644 --- a/packages/firestore/test/unit/model/mutation.test.ts +++ b/packages/firestore/test/unit/model/mutation.test.ts @@ -95,7 +95,7 @@ describe('Mutation', () => { const patch = patchMutation( 'collection/key', { 'foo.bar': 'new-bar-value' }, - Precondition.NONE + Precondition.none() ); const patchedDoc = patch.applyToLocalView(baseDoc, baseDoc, timestamp); @@ -116,7 +116,7 @@ describe('Mutation', () => { const patch = patchMutation( 'collection/key', { 'foo.bar': 'new-bar-value' }, - Precondition.NONE + Precondition.none() ); const patchedDoc = patch.applyToLocalView(baseDoc, baseDoc, timestamp); diff --git a/packages/firestore/test/unit/remote/remote_event.test.ts b/packages/firestore/test/unit/remote/remote_event.test.ts index ea3328379e4..7e7c58de990 100644 --- a/packages/firestore/test/unit/remote/remote_event.test.ts +++ b/packages/firestore/test/unit/remote/remote_event.test.ts @@ -459,7 +459,13 @@ describe('RemoteEvent', () => { expect(event.targetMismatches.size).to.equal(1); expect(event.targetChanges.size).to.equal(1); - const expected = updateMapping(SnapshotVersion.MIN, [], [], [doc1], false); + const expected = updateMapping( + SnapshotVersion.min(), + [], + [], + [doc1], + false + ); expectTargetChangeEquals(event.targetChanges.get(1)!, expected); }); diff --git a/packages/firestore/test/unit/remote/serializer.helper.ts b/packages/firestore/test/unit/remote/serializer.helper.ts index eb34dfd931e..bd7ea39326c 100644 --- a/packages/firestore/test/unit/remote/serializer.helper.ts +++ b/packages/firestore/test/unit/remote/serializer.helper.ts @@ -56,7 +56,6 @@ import { WatchTargetChangeState } from '../../../src/remote/watch_change'; import { Code, FirestoreError } from '../../../src/util/error'; -import { forEach } from '../../../src/util/obj'; import { addEqualityMatcher } from '../../util/equality_matcher'; import { bound, @@ -566,7 +565,7 @@ export function serializerTest( describe('toMutation', () => { it('converts DeleteMutation', () => { - const mutation = new DeleteMutation(key('docs/1'), Precondition.NONE); + const mutation = new DeleteMutation(key('docs/1'), Precondition.none()); const result = s.toMutation(mutation); expect(result).to.deep.equal({ delete: 'projects/p/databases/d/documents/docs/1' @@ -609,7 +608,7 @@ export function serializerTest( const mutation = patchMutation( 'bar/baz', { a: 'b', num: 1, 'some.deep.thing': 2 }, - Precondition.NONE + Precondition.none() ); const proto = { update: s.toMutationDocument(mutation.key, mutation.data), @@ -1250,8 +1249,8 @@ export function serializerTest( 1, TargetPurpose.Listen, 4, - SnapshotVersion.MIN, - SnapshotVersion.MIN, + SnapshotVersion.min(), + SnapshotVersion.min(), ByteString.fromUint8Array(new Uint8Array([1, 2, 3])) ) ); @@ -1279,14 +1278,20 @@ export function serializerTest( addEqualityMatcher(); it('contains all Operators', () => { - // giant hack - // eslint-disable-next-line @typescript-eslint/no-explicit-any - forEach(Operator as any, (name, op) => { - if (op instanceof Operator) { - expect(s.toOperatorName(op), 'for name').to.exist; - expect(s.fromOperatorName(s.toOperatorName(op))).to.deep.equal(op); - } - }); + const allOperators = [ + Operator.LESS_THAN, + Operator.LESS_THAN_OR_EQUAL, + Operator.EQUAL, + Operator.GREATER_THAN, + Operator.GREATER_THAN_OR_EQUAL, + Operator.ARRAY_CONTAINS, + Operator.IN, + Operator.ARRAY_CONTAINS_ANY + ]; + + for (const op of allOperators) { + expect(s.fromOperatorName(s.toOperatorName(op))).to.deep.equal(op); + } }); }); @@ -1294,14 +1299,11 @@ export function serializerTest( addEqualityMatcher(); it('contains all Directions', () => { - // giant hack - // eslint-disable-next-line @typescript-eslint/no-explicit-any - forEach(Direction as any, (name, dir) => { - if (dir instanceof Direction) { - expect(s.toDirection(dir), 'for ' + name).to.exist; - expect(s.fromDirection(s.toDirection(dir))).to.deep.equal(dir); - } - }); + const allDirections = [Direction.ASCENDING, Direction.DESCENDING]; + + for (const dir of allDirections) { + expect(s.fromDirection(s.toDirection(dir))).to.deep.equal(dir); + } }); }); diff --git a/packages/firestore/test/unit/specs/limbo_spec.test.ts b/packages/firestore/test/unit/specs/limbo_spec.test.ts index af5d9c6183d..239ef6a81bf 100644 --- a/packages/firestore/test/unit/specs/limbo_spec.test.ts +++ b/packages/firestore/test/unit/specs/limbo_spec.test.ts @@ -375,7 +375,7 @@ describeSpec('Limbo Documents:', [], () => { .expectLimboDocs(remoteDoc.key) // Fail the Limbo resolution which removes the document from the view. // This is internally propagated as a NoDocument with - // SnapshotVersion.MIN and a read time of zero. + // SnapshotVersion.min() and a read time of zero. .watchRemoves( Query.atPath(path('collection/a')), new RpcError(Code.PERMISSION_DENIED, 'Permission denied') diff --git a/packages/firestore/test/unit/specs/spec_builder.ts b/packages/firestore/test/unit/specs/spec_builder.ts index e8063b15d6e..1412eeba700 100644 --- a/packages/firestore/test/unit/specs/spec_builder.ts +++ b/packages/firestore/test/unit/specs/spec_builder.ts @@ -923,7 +923,7 @@ export class SpecBuilder { // TODO(dimond): Support non-JSON primitive values? return [ filter.field.canonicalString(), - filter.op.name, + filter.op, userDataWriter.convertValue(filter.value) ] as SpecQueryFilter; } else { @@ -935,7 +935,7 @@ export class SpecBuilder { spec.orderBys = query.explicitOrderBy.map(orderBy => { return [ orderBy.field.canonicalString(), - orderBy.dir.name + orderBy.dir ] as SpecQueryOrderBy; }); } diff --git a/packages/firestore/test/unit/specs/spec_test_runner.ts b/packages/firestore/test/unit/specs/spec_test_runner.ts index 083252a554b..09318d0139a 100644 --- a/packages/firestore/test/unit/specs/spec_test_runner.ts +++ b/packages/firestore/test/unit/specs/spec_test_runner.ts @@ -926,8 +926,8 @@ abstract class TestRunner { targetId, TargetPurpose.Listen, ARBITRARY_SEQUENCE_NUMBER, - SnapshotVersion.MIN, - SnapshotVersion.MIN, + SnapshotVersion.min(), + SnapshotVersion.min(), byteStringFromString(expected.resumeToken) ) ); diff --git a/packages/firestore/test/util/helpers.ts b/packages/firestore/test/util/helpers.ts index 94561b7fcbe..d6b506389d7 100644 --- a/packages/firestore/test/util/helpers.ts +++ b/packages/firestore/test/util/helpers.ts @@ -171,7 +171,7 @@ export function unknownDoc( } export function removedDoc(keyStr: string): NoDocument { - return new NoDocument(key(keyStr), SnapshotVersion.forDeletedDoc()); + return new NoDocument(key(keyStr), SnapshotVersion.min()); } export function wrap(value: unknown): api.Value { @@ -226,7 +226,7 @@ export function blob(...bytes: number[]): Blob { export function filter(path: string, op: string, value: unknown): FieldFilter { const dataValue = wrap(value); - const operator = Operator.fromString(op); + const operator = op as Operator; const filter = FieldFilter.create(field(path), operator, dataValue); if (filter instanceof FieldFilter) { @@ -240,7 +240,7 @@ export function setMutation( keyStr: string, json: JsonObject ): SetMutation { - return new SetMutation(key(keyStr), wrapObject(json), Precondition.NONE); + return new SetMutation(key(keyStr), wrapObject(json), Precondition.none()); } export function patchMutation( @@ -262,7 +262,7 @@ export function patchMutation( } export function deleteMutation(keyStr: string): DeleteMutation { - return new DeleteMutation(key(keyStr), Precondition.NONE); + return new DeleteMutation(key(keyStr), Precondition.none()); } /** @@ -364,7 +364,7 @@ export function docAddedRemoteEvent( } }); - let version = SnapshotVersion.MIN; + let version = SnapshotVersion.min(); for (const doc of docs) { debugAssert( @@ -451,7 +451,7 @@ export function addTargetMapping( ...docsOrKeys: Array ): TargetChange { return updateMapping( - SnapshotVersion.MIN, + SnapshotVersion.min(), docsOrKeys, [], [], @@ -463,7 +463,7 @@ export function ackTarget( ...docsOrKeys: Array ): TargetChange { return updateMapping( - SnapshotVersion.MIN, + SnapshotVersion.min(), docsOrKeys, [], [], @@ -538,7 +538,7 @@ export function stringFromBase64String(value?: string | Uint8Array): string { export function resumeTokenForSnapshot( snapshotVersion: SnapshotVersion ): ByteString { - if (snapshotVersion.isEqual(SnapshotVersion.MIN)) { + if (snapshotVersion.isEqual(SnapshotVersion.min())) { return ByteString.EMPTY_BYTE_STRING; } else { return byteStringFromString(snapshotVersion.toString()); @@ -588,7 +588,7 @@ export function documentUpdates( } else if (docOrKey instanceof DocumentKey) { changes = changes.insert( docOrKey, - new NoDocument(docOrKey, SnapshotVersion.forDeletedDoc()) + new NoDocument(docOrKey, SnapshotVersion.min()) ); } }