diff --git a/packages/firestore/src/api/credentials.ts b/packages/firestore/src/api/credentials.ts index 139bf085074..6e3a0034fc5 100644 --- a/packages/firestore/src/api/credentials.ts +++ b/packages/firestore/src/api/credentials.ts @@ -116,17 +116,14 @@ export class EmptyCredentialsProvider implements CredentialsProvider { invalidateToken(): void {} setChangeListener(changeListener: CredentialChangeListener): void { - assert(!this.changeListener, 'Can only call setChangeListener() once.'); + assert(!this.changeListener); this.changeListener = changeListener; // Fire with initial user. changeListener(User.UNAUTHENTICATED); } removeChangeListener(): void { - assert( - this.changeListener !== null, - 'removeChangeListener() when no listener registered' - ); + assert(this.changeListener !== null); this.changeListener = null; } } @@ -190,10 +187,7 @@ export class FirebaseCredentialsProvider implements CredentialsProvider { } getToken(): Promise { - assert( - this.tokenListener != null, - 'getToken cannot be called after listener removed.' - ); + assert(this.tokenListener != null); // Take note of the current value of the tokenCounter so that this method // can fail (with an ABORTED error) if there is a token change while the @@ -217,10 +211,7 @@ export class FirebaseCredentialsProvider implements CredentialsProvider { ); } else { if (tokenData) { - assert( - typeof tokenData.accessToken === 'string', - 'Invalid tokenData returned from getToken():' + tokenData - ); + assert(typeof tokenData.accessToken === 'string'); return new OAuthToken(tokenData.accessToken, this.currentUser); } else { return null; @@ -234,7 +225,7 @@ export class FirebaseCredentialsProvider implements CredentialsProvider { } setChangeListener(changeListener: CredentialChangeListener): void { - assert(!this.changeListener, 'Can only call setChangeListener() once.'); + assert(!this.changeListener); this.changeListener = changeListener; // Fire the initial event @@ -244,11 +235,8 @@ export class FirebaseCredentialsProvider implements CredentialsProvider { } removeChangeListener(): void { - assert(this.tokenListener != null, 'removeChangeListener() called twice'); - assert( - this.changeListener !== null, - 'removeChangeListener() called when no listener registered' - ); + assert(this.tokenListener != null); + assert(this.changeListener !== null); if (this.auth) { this.auth.removeAuthTokenListener(this.tokenListener!); @@ -263,10 +251,7 @@ export class FirebaseCredentialsProvider implements CredentialsProvider { // to guarantee to get the actual user. private getUser(): User { const currentUid = this.auth && this.auth.getUid(); - assert( - currentUid === null || typeof currentUid === 'string', - 'Received invalid UID: ' + currentUid - ); + assert(currentUid === null || typeof currentUid === 'string'); return new User(currentUid); } } @@ -348,8 +333,7 @@ export function makeCredentialsProvider( client !== null && client['auth'] && client['auth']['getAuthHeaderValueForFirstParty'] - ), - 'unexpected gapi interface' + ) ); return new FirstPartyCredentialsProvider( client, diff --git a/packages/firestore/src/api/database.ts b/packages/firestore/src/api/database.ts index 1bead553f71..5162c296f40 100644 --- a/packages/firestore/src/api/database.ts +++ b/packages/firestore/src/api/database.ts @@ -472,7 +472,7 @@ export class Firestore implements firestore.FirebaseFirestore, FirebaseService { observer: PartialObserver ): Unsubscribe { const errHandler = (err: Error): void => { - throw fail('Uncaught Error in onSnapshotsInSync'); + throw fail(); }; const asyncObserver = new AsyncObserver({ next: () => { @@ -514,9 +514,9 @@ export class Firestore implements firestore.FirebaseFirestore, FirebaseService { persistenceProvider: PersistenceProvider, persistenceSettings: PersistenceSettings ): Promise { - assert(!!this._settings.host, 'FirestoreSettings.host is not set'); + assert(!!this._settings.host); - assert(!this._firestoreClient, 'configureClient() called multiple times'); + assert(!this._firestoreClient); const databaseInfo = this.makeDatabaseInfo(); @@ -712,7 +712,7 @@ export class Transaction implements firestore.Transaction { .lookup([ref._key]) .then((docs: MaybeDocument[]) => { if (!docs || docs.length !== 1) { - return fail('Mismatch in docs returned from document lookup.'); + return fail(); } const doc = docs[0]; if (doc instanceof NoDocument) { @@ -734,9 +734,7 @@ export class Transaction implements firestore.Transaction { ref._converter ); } else { - throw fail( - `BatchGetDocumentsRequest returned unexpected document type: ${doc.constructor.name}` - ); + throw fail(); } }); } @@ -1212,10 +1210,7 @@ export class DocumentReference const asyncObserver = new AsyncObserver({ next: snapshot => { if (observer.next) { - assert( - snapshot.docs.size <= 1, - 'Too many documents returned on a document query' - ); + assert(snapshot.docs.size <= 1); const doc = snapshot.docs.get(this._key); observer.next( @@ -1457,10 +1452,7 @@ export class QueryDocumentSnapshot implements firestore.QueryDocumentSnapshot { data(options?: SnapshotOptions): T { const data = super.data(options); - assert( - data !== undefined, - 'Document in a QueryDocumentSnapshot should exist' - ); + assert(data !== undefined); return data; } } @@ -2539,14 +2531,8 @@ export function changesFromSnapshot( snapshot.mutatedKeys.has(change.doc.key), converter ); - assert( - change.type === ChangeType.Added, - 'Invalid event type for first snapshot' - ); - assert( - !lastDoc || snapshot.query.docComparator(lastDoc, change.doc) < 0, - 'Got added events in wrong order' - ); + assert(change.type === ChangeType.Added); + assert(!lastDoc || snapshot.query.docComparator(lastDoc, change.doc) < 0); lastDoc = change.doc; return { type: 'added' as firestore.DocumentChangeType, @@ -2576,7 +2562,7 @@ export function changesFromSnapshot( let newIndex = -1; if (change.type !== ChangeType.Added) { oldIndex = indexTracker.indexOf(change.doc.key); - assert(oldIndex >= 0, 'Index for document not found'); + assert(oldIndex >= 0); indexTracker = indexTracker.delete(change.doc.key); } if (change.type !== ChangeType.Removed) { @@ -2598,7 +2584,7 @@ function resultChangeType(type: ChangeType): firestore.DocumentChangeType { case ChangeType.Removed: return 'removed'; default: - return fail('Unknown change type: ' + type); + return fail(); } } diff --git a/packages/firestore/src/api/user_data_reader.ts b/packages/firestore/src/api/user_data_reader.ts index 12d7e8d59bb..b63d5ead0fb 100644 --- a/packages/firestore/src/api/user_data_reader.ts +++ b/packages/firestore/src/api/user_data_reader.ts @@ -136,7 +136,7 @@ function isWrite(dataSource: UserDataSource): boolean { case UserDataSource.ArrayArgument: return false; default: - throw fail(`Unexpected case for UserDataSource: ${dataSource}`); + throw fail(); } } @@ -353,9 +353,7 @@ export class UserDataReader { stringOrFieldPath ); } else { - throw fail( - 'Expected stringOrFieldPath to be a string or a FieldPath' - ); + throw fail(); } if (!context.contains(fieldPath)) { @@ -494,11 +492,8 @@ export class UserDataReader { FieldPath.EMPTY_PATH ); const parsed = this.parseData(input, context); - assert(parsed != null, 'Parsed data should not be null.'); - assert( - context.fieldTransforms.length === 0, - 'Field transforms should have been disallowed.' - ); + assert(parsed != null); + assert(context.fieldTransforms.length === 0); return parsed; } @@ -633,11 +628,7 @@ export class UserDataReader { // fieldMask so it gets deleted. context.fieldMask.push(context.path); } else if (context.dataSource === UserDataSource.Update) { - assert( - context.path.length > 0, - 'FieldValue.delete() at the top level should have already' + - ' been handled.' - ); + assert(context.path.length > 0); throw context.createError( 'FieldValue.delete() can only appear at the top level ' + 'of your update data' @@ -684,7 +675,7 @@ export class UserDataReader { new FieldTransform(context.path, numericIncrement) ); } else { - fail('Unknown FieldValue type: ' + value); + fail(); } } diff --git a/packages/firestore/src/api/user_data_writer.ts b/packages/firestore/src/api/user_data_writer.ts index cdef8f8a789..ffc27054900 100644 --- a/packages/firestore/src/api/user_data_writer.ts +++ b/packages/firestore/src/api/user_data_writer.ts @@ -84,7 +84,7 @@ export class UserDataWriter { case TypeOrder.ObjectValue: return this.convertObject(value.mapValue!); default: - throw fail('Invalid value type: ' + JSON.stringify(value)); + throw fail(); } } @@ -130,10 +130,7 @@ export class UserDataWriter { private convertReference(name: string): DocumentReference { const resourcePath = ResourcePath.fromString(name); - assert( - isValidResourceName(resourcePath), - 'ReferenceValue is not valid ' + name - ); + assert(isValidResourceName(resourcePath)); const databaseId = new DatabaseId(resourcePath.get(1), resourcePath.get(3)); const key = new DocumentKey(resourcePath.popFirst(5)); diff --git a/packages/firestore/src/core/event_manager.ts b/packages/firestore/src/core/event_manager.ts index ff0fa5600e3..cc93309957e 100644 --- a/packages/firestore/src/core/event_manager.ts +++ b/packages/firestore/src/core/event_manager.ts @@ -73,10 +73,7 @@ export class EventManager implements SyncEngineListener { // Run global snapshot listeners if a consistent snapshot has been emitted. const raisedEvent = listener.applyOnlineStateChange(this.onlineState); - assert( - !raisedEvent, - "applyOnlineStateChange() shouldn't raise an event for brand-new listeners." - ); + assert(!raisedEvent); if (queryInfo.viewSnap) { const raisedEvent = listener.onViewSnapshot(queryInfo.viewSnap); @@ -226,10 +223,7 @@ export class QueryListener { * indeed raised. */ onViewSnapshot(snap: ViewSnapshot): boolean { - assert( - snap.docChanges.length > 0 || snap.syncStateChanged, - 'We got a new snapshot with no changes?' - ); + assert(snap.docChanges.length > 0 || snap.syncStateChanged); if (!this.options.includeMetadataChanges) { // Remove the metadata only changes. @@ -288,10 +282,7 @@ export class QueryListener { snap: ViewSnapshot, onlineState: OnlineState ): boolean { - assert( - !this.raisedInitialEvent, - 'Determining whether to raise first event but already had first event' - ); + assert(!this.raisedInitialEvent); // Always raise the first event when we're synced if (!snap.fromCache) { @@ -304,10 +295,7 @@ export class QueryListener { // Don't raise the event if we're online, aren't synced yet (checked // above) and are waiting for a sync. if (this.options.waitForSyncWhenOnline && maybeOnline) { - assert( - snap.fromCache, - 'Waiting for sync, but snapshot is not from cache' - ); + assert(snap.fromCache); return false; } @@ -337,10 +325,7 @@ export class QueryListener { } private raiseInitialEvent(snap: ViewSnapshot): void { - assert( - !this.raisedInitialEvent, - 'Trying to raise initial events for second time' - ); + assert(!this.raisedInitialEvent); snap = ViewSnapshot.fromInitialDocuments( snap.query, snap.docs, diff --git a/packages/firestore/src/core/query.ts b/packages/firestore/src/core/query.ts index 1d139140881..672a5a33d29 100644 --- a/packages/firestore/src/core/query.ts +++ b/packages/firestore/src/core/query.ts @@ -98,8 +98,7 @@ export class Query { assert( inequalityField === null || (firstOrderByField !== null && - inequalityField.isEqual(firstOrderByField)), - 'First orderBy should match inequality field.' + inequalityField.isEqual(firstOrderByField)) ); this.memoizedOrderBy = []; let foundKeyOrdering = false; @@ -132,11 +131,10 @@ export class Query { this.getInequalityFilterField() == null || !(filter instanceof FieldFilter) || !filter.isInequality() || - filter.field.isEqual(this.getInequalityFilterField()!), - 'Query must only have one inequality field.' + filter.field.isEqual(this.getInequalityFilterField()!) ); - assert(!this.isDocumentQuery(), 'No filtering allowed for document query'); + assert(!this.isDocumentQuery()); const newFilters = this.filters.concat([filter]); return new Query( @@ -152,7 +150,7 @@ export class Query { } addOrderBy(orderBy: OrderBy): Query { - assert(!this.startAt && !this.endAt, 'Bounds must be set after orderBy'); + assert(!this.startAt && !this.endAt); // TODO(dimond): validate that orderBy does not list the same key twice. const newOrderBy = this.explicitOrderBy.concat([orderBy]); return new Query( @@ -284,10 +282,7 @@ export class Query { comparedOnKeyField = comparedOnKeyField || orderBy.field.isKeyField(); } // Assert that we actually compared by key - assert( - comparedOnKeyField, - "orderBy used that doesn't compare on key field" - ); + assert(comparedOnKeyField); return 0; } @@ -449,10 +444,7 @@ export class Query { } private assertValidBound(bound: Bound): void { - assert( - bound.position.length <= this.orderBy.length, - 'Bound is longer than orderBy' - ); + assert(bound.position.length <= this.orderBy.length); } } @@ -491,7 +483,7 @@ export class Operator { case 'array-contains-any': return Operator.ARRAY_CONTAINS_ANY; default: - return fail('Unknown FieldFilter operator: ' + op); + return fail(); } } @@ -521,23 +513,15 @@ export class FieldFilter extends Filter { static create(field: FieldPath, op: Operator, value: api.Value): FieldFilter { if (field.isKeyField()) { if (op === Operator.IN) { + assert(isArray(value)); assert( - isArray(value), - 'Comparing on key with IN, but filter value not an ArrayValue' - ); - assert( - (value.arrayValue.values || []).every(elem => isReferenceValue(elem)), - 'Comparing on key with IN, but an array value was not a RefValue' + (value.arrayValue.values || []).every(elem => isReferenceValue(elem)) ); return new KeyFieldInFilter(field, value); } else { + assert(isReferenceValue(value)); assert( - isReferenceValue(value), - 'Comparing on key, but filter value not a RefValue' - ); - assert( - op !== Operator.ARRAY_CONTAINS && op !== Operator.ARRAY_CONTAINS_ANY, - `'${op.toString()}' queries don't make sense on document keys.` + op !== Operator.ARRAY_CONTAINS && op !== Operator.ARRAY_CONTAINS_ANY ); return new KeyFieldFilter(field, op, value); } @@ -560,16 +544,10 @@ export class FieldFilter extends Filter { } else if (op === Operator.ARRAY_CONTAINS) { return new ArrayContainsFilter(field, value); } else if (op === Operator.IN) { - assert( - isArray(value), - 'IN filter has invalid value: ' + value.toString() - ); + assert(isArray(value)); return new InFilter(field, value); } else if (op === Operator.ARRAY_CONTAINS_ANY) { - assert( - isArray(value), - 'ARRAY_CONTAINS_ANY filter has invalid value: ' + value.toString() - ); + assert(isArray(value)); return new ArrayContainsAnyFilter(field, value); } else { return new FieldFilter(field, op, value); @@ -600,7 +578,7 @@ export class FieldFilter extends Filter { case Operator.GREATER_THAN_OR_EQUAL: return comparison >= 0; default: - return fail('Unknown FieldFilter operator: ' + this.op); + return fail(); } } @@ -651,7 +629,7 @@ export class KeyFieldFilter extends FieldFilter { constructor(field: FieldPath, op: Operator, value: api.Value) { super(field, op, value); - assert(isReferenceValue(value), 'KeyFieldFilter expects a ReferenceValue'); + assert(isReferenceValue(value)); this.key = DocumentKey.fromName(value.referenceValue); } @@ -667,12 +645,9 @@ export class KeyFieldInFilter extends FieldFilter { constructor(field: FieldPath, value: api.Value) { super(field, Operator.IN, value); - assert(isArray(value), 'KeyFieldInFilter expects an ArrayValue'); + assert(isArray(value)); this.keys = (value.arrayValue.values || []).map(v => { - assert( - isReferenceValue(v), - 'Comparing on key with IN, but an array value was not a ReferenceValue' - ); + assert(isReferenceValue(v)); return DocumentKey.fromName(v.referenceValue); }); } @@ -698,7 +673,7 @@ export class ArrayContainsFilter extends FieldFilter { export class InFilter extends FieldFilter { constructor(field: FieldPath, value: api.Value) { super(field, Operator.IN, value); - assert(isArray(value), 'InFilter expects an ArrayValue'); + assert(isArray(value)); } matches(doc: Document): boolean { @@ -711,7 +686,7 @@ export class InFilter extends FieldFilter { export class ArrayContainsAnyFilter extends FieldFilter { constructor(field: FieldPath, value: api.Value) { super(field, Operator.ARRAY_CONTAINS_ANY, value); - assert(isArray(value), 'ArrayContainsAnyFilter expects an ArrayValue'); + assert(isArray(value)); } matches(doc: Document): boolean { @@ -768,29 +743,20 @@ export class Bound { * order. */ sortsBeforeDocument(orderBy: OrderBy[], doc: Document): boolean { - assert( - this.position.length <= orderBy.length, - "Bound has more components than query's orderBy" - ); + assert(this.position.length <= orderBy.length); let comparison = 0; for (let i = 0; i < this.position.length; i++) { const orderByComponent = orderBy[i]; const component = this.position[i]; if (orderByComponent.field.isKeyField()) { - assert( - isReferenceValue(component), - 'Bound has a non-key value where the key path is being used.' - ); + assert(isReferenceValue(component)); comparison = DocumentKey.comparator( DocumentKey.fromName(component.referenceValue), doc.key ); } else { const docValue = doc.field(orderByComponent.field); - assert( - docValue !== null, - 'Field should exist since document matched the orderBy already.' - ); + assert(docValue !== null); comparison = valueCompare(component, docValue); } if (orderByComponent.dir === Direction.DESCENDING) { @@ -849,7 +815,7 @@ export class OrderBy { case Direction.DESCENDING: return -1 * comparison; default: - return fail('Unknown direction: ' + this.dir); + return fail(); } } diff --git a/packages/firestore/src/core/sync_engine.ts b/packages/firestore/src/core/sync_engine.ts index 7e9119234a0..407830b15f9 100644 --- a/packages/firestore/src/core/sync_engine.ts +++ b/packages/firestore/src/core/sync_engine.ts @@ -184,11 +184,8 @@ export class SyncEngine implements RemoteSyncer, SharedClientStateSyncer { /** Subscribes to SyncEngine notifications. Has to be called exactly once. */ subscribe(syncEngineListener: SyncEngineListener): void { - assert(syncEngineListener !== null, 'SyncEngine listener cannot be null'); - assert( - this.syncEngineListener === null, - 'SyncEngine already has a subscriber.' - ); + assert(syncEngineListener !== null); + assert(this.syncEngineListener === null); this.syncEngineListener = syncEngineListener; } @@ -260,14 +257,8 @@ export class SyncEngine implements RemoteSyncer, SharedClientStateSyncer { /* updateLimboDocuments= */ this.isPrimary === true, synthesizedTargetChange ); - assert( - viewChange.limboChanges.length === 0, - 'View returned limbo docs before target ack from the server.' - ); - assert( - !!viewChange.snapshot, - 'applyChanges for new view should always return a snapshot' - ); + assert(viewChange.limboChanges.length === 0); + assert(!!viewChange.snapshot); const data = new QueryView(query, targetId, view); this.queryViewsByQuery.set(query, data); @@ -304,7 +295,7 @@ export class SyncEngine implements RemoteSyncer, SharedClientStateSyncer { this.assertSubscribed('unlisten()'); const queryView = this.queryViewsByQuery.get(query)!; - assert(!!queryView, 'Trying to unlisten on query not found:' + query); + assert(!!queryView); // Only clean up the query view and target if this is the only query mapped // to the target. @@ -408,21 +399,14 @@ export class SyncEngine implements RemoteSyncer, SharedClientStateSyncer { targetChange.addedDocuments.size + targetChange.modifiedDocuments.size + targetChange.removedDocuments.size <= - 1, - 'Limbo resolution for single document contains multiple changes.' + 1 ); if (targetChange.addedDocuments.size > 0) { limboResolution.receivedDocument = true; } else if (targetChange.modifiedDocuments.size > 0) { - assert( - limboResolution.receivedDocument, - 'Received change for limbo target document without add.' - ); + assert(limboResolution.receivedDocument); } else if (targetChange.removedDocuments.size > 0) { - assert( - limboResolution.receivedDocument, - 'Received remove for limbo target document without add.' - ); + assert(limboResolution.receivedDocument); limboResolution.receivedDocument = false; } else { // This was probably just a CURRENT targetChange or similar. @@ -455,10 +439,7 @@ export class SyncEngine implements RemoteSyncer, SharedClientStateSyncer { const newViewSnapshots = [] as ViewSnapshot[]; this.queryViewsByQuery.forEach((query, queryView) => { const viewChange = queryView.view.applyOnlineStateChange(onlineState); - assert( - viewChange.limboChanges.length === 0, - 'OnlineState should not affect limbo documents.' - ); + assert(viewChange.limboChanges.length === 0); if (viewChange.snapshot) { newViewSnapshots.push(viewChange.snapshot); } @@ -550,7 +531,7 @@ export class SyncEngine implements RemoteSyncer, SharedClientStateSyncer { this.processUserCallback(batchId, error ? error : null); this.localStore.removeCachedMutationBatchMetadata(batchId); } else { - fail(`Unknown batchState: ${batchState}`); + fail(); } await this.emitNewSnapsAndNotifyLocalStore(documents); @@ -679,10 +660,7 @@ export class SyncEngine implements RemoteSyncer, SharedClientStateSyncer { if (newCallbacks) { const callback = newCallbacks.get(batchId); if (callback) { - assert( - batchId === newCallbacks.minKey(), - 'Mutation callbacks processed out-of-order?' - ); + assert(batchId === newCallbacks.minKey()); if (error) { callback.reject(error); } else { @@ -702,8 +680,7 @@ export class SyncEngine implements RemoteSyncer, SharedClientStateSyncer { assert( this.queriesByTarget[targetId] && - this.queriesByTarget[targetId].length !== 0, - `There are no queries mapped to target id ${targetId}` + this.queriesByTarget[targetId].length !== 0 ); for (const query of this.queriesByTarget[targetId]) { @@ -761,7 +738,7 @@ export class SyncEngine implements RemoteSyncer, SharedClientStateSyncer { this.removeLimboTarget(limboChange.key); } } else { - fail('Unknown limbo change: ' + JSON.stringify(limboChange)); + fail(); } } } @@ -858,10 +835,7 @@ export class SyncEngine implements RemoteSyncer, SharedClientStateSyncer { } private assertSubscribed(fnName: string): void { - assert( - this.syncEngineListener !== null, - 'Trying to call ' + fnName + ' before calling subscribe().' - ); + assert(this.syncEngineListener !== null); } async handleCredentialChange(user: User): Promise { @@ -976,7 +950,7 @@ export class SyncEngine implements RemoteSyncer, SharedClientStateSyncer { for (const query of queries) { const queryView = this.queryViewsByQuery.get(query); - assert(!!queryView, `No query view found for ${query}`); + assert(!!queryView); const viewChange = await this.synchronizeViewAndComputeSnapshot( queryView @@ -986,14 +960,11 @@ export class SyncEngine implements RemoteSyncer, SharedClientStateSyncer { } } } else { - assert( - this.isPrimary === true, - 'A secondary tab should never have an active target without an active query.' - ); + assert(this.isPrimary === true); // For queries that never executed on this client, we need to // allocate the target in LocalStore and initialize a new View. const target = await this.localStore.getTarget(targetId); - assert(!!target, `Target for id ${targetId} not found`); + assert(!!target); targetData = await this.localStore.allocateTarget(target); await this.initializeViewAndComputeSnapshot( this.synthesizeTargetToQuery(target!), @@ -1075,7 +1046,7 @@ export class SyncEngine implements RemoteSyncer, SharedClientStateSyncer { break; } default: - fail('Unexpected target state: ' + state); + fail(); } } } @@ -1090,12 +1061,9 @@ export class SyncEngine implements RemoteSyncer, SharedClientStateSyncer { } for (const targetId of added) { - assert( - !this.queriesByTarget[targetId], - 'Trying to add an already active target' - ); + assert(!this.queriesByTarget[targetId]); const target = await this.localStore.getTarget(targetId); - assert(!!target, `Query data for active target ${targetId} not found`); + assert(!!target); const targetData = await this.localStore.allocateTarget(target); await this.initializeViewAndComputeSnapshot( this.synthesizeTargetToQuery(target), @@ -1149,7 +1117,7 @@ export class SyncEngine implements RemoteSyncer, SharedClientStateSyncer { } for (const query of queries) { const queryView = this.queryViewsByQuery.get(query); - assert(!!queryView, `No query view found for ${query}`); + assert(!!queryView); keySet = keySet.unionWith(queryView.view.syncedDocuments); } return keySet; diff --git a/packages/firestore/src/core/target_id_generator.ts b/packages/firestore/src/core/target_id_generator.ts index 117f9823b19..83cd9a319c7 100644 --- a/packages/firestore/src/core/target_id_generator.ts +++ b/packages/firestore/src/core/target_id_generator.ts @@ -50,10 +50,7 @@ export class TargetIdGenerator { * will use the seed value as the next target ID. */ constructor(private generatorId: number, seed?: number) { - assert( - (generatorId & RESERVED_BITS) === generatorId, - `Generator ID ${generatorId} contains more than ${RESERVED_BITS} reserved bits` - ); + assert((generatorId & RESERVED_BITS) === generatorId); this.seek(seed !== undefined ? seed : this.generatorId); } @@ -74,10 +71,7 @@ export class TargetIdGenerator { } private seek(targetId: TargetId): void { - assert( - (targetId & RESERVED_BITS) === this.generatorId, - 'Cannot supply target ID from different generator ID' - ); + assert((targetId & RESERVED_BITS) === this.generatorId); this.nextId = targetId; } diff --git a/packages/firestore/src/core/transaction.ts b/packages/firestore/src/core/transaction.ts index 9c1ee3c6e8d..d5f429b14b2 100644 --- a/packages/firestore/src/core/transaction.ts +++ b/packages/firestore/src/core/transaction.ts @@ -71,7 +71,7 @@ export class Transaction { if (doc instanceof NoDocument || doc instanceof Document) { this.recordVersion(doc); } else { - fail('Document in a transaction was a ' + doc.constructor.name); + fail(); } }); return docs; @@ -125,7 +125,7 @@ export class Transaction { // For deleted docs, we must use baseVersion 0 when we overwrite them. docVersion = SnapshotVersion.forDeletedDoc(); } else { - throw fail('Document in a transaction was a ' + doc.constructor.name); + throw fail(); } const existingVersion = this.readVersions.get(doc.key); @@ -195,9 +195,6 @@ export class Transaction { } private ensureCommitNotCalled(): void { - assert( - !this.committed, - 'A transaction object cannot be used after its update callback has been invoked.' - ); + assert(!this.committed); } } diff --git a/packages/firestore/src/core/view.ts b/packages/firestore/src/core/view.ts index 605918503b3..77735ad941c 100644 --- a/packages/firestore/src/core/view.ts +++ b/packages/firestore/src/core/view.ts @@ -150,13 +150,7 @@ export class View { const oldDoc = oldDocumentSet.get(key); let newDoc = newMaybeDoc instanceof Document ? newMaybeDoc : null; if (newDoc) { - assert( - key.isEqual(newDoc.key), - 'Mismatching keys found in document changes: ' + - key + - ' != ' + - newDoc.key - ); + assert(key.isEqual(newDoc.key)); newDoc = this.query.matches(newDoc) ? newDoc : null; } @@ -242,10 +236,7 @@ export class View { } } - assert( - !needsRefill || !previousChanges, - 'View was refilled using docs that themselves needed refilling.' - ); + assert(!needsRefill || !previousChanges); return { documentSet: newDocumentSet, changeSet, @@ -288,7 +279,7 @@ export class View { updateLimboDocuments: boolean, targetChange?: TargetChange ): ViewChange { - assert(!docChanges.needsRefill, 'Cannot apply changes that need a refill'); + assert(!docChanges.needsRefill); const oldDocs = this.documentSet; this.documentSet = docChanges.documentSet; this.mutatedKeys = docChanges.mutatedKeys; @@ -390,10 +381,7 @@ export class View { key => (this._syncedDocuments = this._syncedDocuments.add(key)) ); targetChange.modifiedDocuments.forEach(key => - assert( - this._syncedDocuments.has(key), - `Modified document ${key} not found in view.` - ) + assert(this._syncedDocuments.has(key)) ); targetChange.removedDocuments.forEach( key => (this._syncedDocuments = this._syncedDocuments.delete(key)) @@ -491,7 +479,7 @@ function compareChangeType(c1: ChangeType, c2: ChangeType): number { case ChangeType.Removed: return 0; default: - return fail('Unknown ChangeType: ' + change); + return fail(); } }; diff --git a/packages/firestore/src/core/view_snapshot.ts b/packages/firestore/src/core/view_snapshot.ts index b3c87c85af8..3116e154b09 100644 --- a/packages/firestore/src/core/view_snapshot.ts +++ b/packages/firestore/src/core/view_snapshot.ts @@ -117,12 +117,7 @@ export class DocumentChangeSet { // Removed->Modified // Metadata->Added // Removed->Metadata - fail( - 'unsupported combination of changes: ' + - JSON.stringify(change) + - ' after ' + - JSON.stringify(oldChange) - ); + fail(); } } diff --git a/packages/firestore/src/local/encoded_resource_path.ts b/packages/firestore/src/local/encoded_resource_path.ts index 4c9d504d8d1..046dd15ae85 100644 --- a/packages/firestore/src/local/encoded_resource_path.ts +++ b/packages/firestore/src/local/encoded_resource_path.ts @@ -118,11 +118,10 @@ export function decode(path: EncodedResourcePath): ResourcePath { // Event the empty path must encode as a path of at least length 2. A path // with exactly 2 must be the empty path. const length = path.length; - assert(length >= 2, 'Invalid path ' + path); + assert(length >= 2); if (length === 2) { assert( - path.charAt(0) === escapeChar && path.charAt(1) === encodedSeparatorChar, - 'Non-empty path ' + path + ' had length 2' + path.charAt(0) === escapeChar && path.charAt(1) === encodedSeparatorChar ); return ResourcePath.EMPTY_PATH; } @@ -139,7 +138,7 @@ export function decode(path: EncodedResourcePath): ResourcePath { // there must be an end to this segment. const end = path.indexOf(escapeChar, start); if (end < 0 || end > lastReasonableEscapeIndex) { - fail('Invalid encoded resource path: "' + path + '"'); + fail(); } const next = path.charAt(end + 1); @@ -167,7 +166,7 @@ export function decode(path: EncodedResourcePath): ResourcePath { segmentBuilder += path.substring(start, end + 1); break; default: - fail('Invalid encoded resource path: "' + path + '"'); + fail(); } start = end + 2; @@ -194,6 +193,6 @@ export function prefixSuccessor( const c = path.charCodeAt(path.length - 1); // TODO(mcg): this really should be a general thing, but not worth it right // now - assert(c === 1, 'successor may only operate on paths generated by encode'); + assert(c === 1); return path.substring(0, path.length - 1) + String.fromCharCode(c + 1); } diff --git a/packages/firestore/src/local/index_free_query_engine.ts b/packages/firestore/src/local/index_free_query_engine.ts index c5770018ea2..f2582492b0c 100644 --- a/packages/firestore/src/local/index_free_query_engine.ts +++ b/packages/firestore/src/local/index_free_query_engine.ts @@ -64,10 +64,7 @@ export class IndexFreeQueryEngine implements QueryEngine { lastLimboFreeSnapshotVersion: SnapshotVersion, remoteKeys: DocumentKeySet ): PersistencePromise { - assert( - this.localDocumentsView !== undefined, - 'setLocalDocumentsView() not called' - ); + assert(this.localDocumentsView !== undefined); // Queries that match all documents don't benefit from using // IndexFreeQueries. It is more efficient to scan all documents in a diff --git a/packages/firestore/src/local/indexeddb_index_manager.ts b/packages/firestore/src/local/indexeddb_index_manager.ts index 74bcf90d56d..33c3b8982fb 100644 --- a/packages/firestore/src/local/indexeddb_index_manager.ts +++ b/packages/firestore/src/local/indexeddb_index_manager.ts @@ -51,7 +51,7 @@ export class IndexedDbIndexManager implements IndexManager { transaction: PersistenceTransaction, collectionPath: ResourcePath ): PersistencePromise { - assert(collectionPath.length % 2 === 1, 'Expected a collection path.'); + assert(collectionPath.length % 2 === 1); if (!this.collectionParentsCache.has(collectionPath)) { const collectionId = collectionPath.lastSegment(); const parentPath = collectionPath.popLast(); diff --git a/packages/firestore/src/local/indexeddb_mutation_queue.ts b/packages/firestore/src/local/indexeddb_mutation_queue.ts index 86a4ed146fb..ba1c41b1be2 100644 --- a/packages/firestore/src/local/indexeddb_mutation_queue.ts +++ b/packages/firestore/src/local/indexeddb_mutation_queue.ts @@ -92,7 +92,7 @@ export class IndexedDbMutationQueue implements MutationQueue { // In particular, are there any reserved characters? are empty ids allowed? // For the moment store these together in the same mutations table assuming // that empty userIDs aren't allowed. - assert(user.uid !== '', 'UserID must not be an empty string.'); + assert(user.uid !== ''); const userId = user.isAuthenticated() ? user.uid! : ''; return new IndexedDbMutationQueue( userId, @@ -173,7 +173,7 @@ export class IndexedDbMutationQueue implements MutationQueue { // We write an empty object to obtain key // eslint-disable-next-line @typescript-eslint/no-explicit-any return mutationStore.add({} as any).next(batchId => { - assert(typeof batchId === 'number', 'Auto-generated key is not a number'); + assert(typeof batchId === 'number'); const batch = new MutationBatch( batchId, @@ -222,10 +222,7 @@ export class IndexedDbMutationQueue implements MutationQueue { .get(batchId) .next(dbBatch => { if (dbBatch) { - assert( - dbBatch.userId === this.userId, - `Unexpected user '${dbBatch.userId}' for mutation batch ${batchId}` - ); + assert(dbBatch.userId === this.userId); return this.serializer.fromDbMutationBatch(dbBatch); } return null; @@ -266,10 +263,7 @@ export class IndexedDbMutationQueue implements MutationQueue { { index: DbMutationBatch.userMutationsIndex, range }, (key, dbBatch, control) => { if (dbBatch.userId === this.userId) { - assert( - dbBatch.batchId >= nextBatchId, - 'Should have found mutation after ' + nextBatchId - ); + assert(dbBatch.batchId >= nextBatchId); foundBatch = this.serializer.fromDbMutationBatch(dbBatch); } control.done(); @@ -346,17 +340,9 @@ export class IndexedDbMutationQueue implements MutationQueue { .get(batchId) .next(mutation => { if (!mutation) { - throw fail( - 'Dangling document-mutation reference found: ' + - indexKey + - ' which points to ' + - batchId - ); + throw fail(); } - assert( - mutation.userId === this.userId, - `Unexpected user '${mutation.userId}' for mutation batch ${batchId}` - ); + assert(mutation.userId === this.userId); results.push(this.serializer.fromDbMutationBatch(mutation)); }); }) @@ -411,14 +397,8 @@ export class IndexedDbMutationQueue implements MutationQueue { transaction: PersistenceTransaction, query: Query ): PersistencePromise { - assert( - !query.isDocumentQuery(), - "Document queries shouldn't go down this path" - ); - assert( - !query.isCollectionGroupQuery(), - 'CollectionGroup queries should be handled in LocalDocumentsView' - ); + assert(!query.isDocumentQuery()); + assert(!query.isCollectionGroupQuery()); const queryPath = query.path; const immediateChildrenLength = queryPath.length + 1; @@ -478,16 +458,9 @@ export class IndexedDbMutationQueue implements MutationQueue { .get(batchId) .next(mutation => { if (mutation === null) { - throw fail( - 'Dangling document-mutation reference found, ' + - 'which points to ' + - batchId - ); + throw fail(); } - assert( - mutation.userId === this.userId, - `Unexpected user '${mutation.userId}' for mutation batch ${batchId}` - ); + assert(mutation.userId === this.userId); results.push(this.serializer.fromDbMutationBatch(mutation)); }) ); @@ -549,12 +522,7 @@ export class IndexedDbMutationQueue implements MutationQueue { } }) .next(() => { - assert( - danglingMutationReferences.length === 0, - 'Document leak -- detected dangling mutation references when queue is empty. ' + - 'Dangling keys: ' + - danglingMutationReferences.map(p => p.canonicalString()) - ); + assert(danglingMutationReferences.length === 0); }); }); } @@ -656,11 +624,7 @@ export function removeMutationBatch( ); promises.push( removePromise.next(() => { - assert( - numDeleted === 1, - 'Dangling document-mutation reference found: Missing batch ' + - batch.batchId - ); + assert(numDeleted === 1); }) ); const removedDocuments: DocumentKey[] = []; diff --git a/packages/firestore/src/local/indexeddb_persistence.ts b/packages/firestore/src/local/indexeddb_persistence.ts index c2215694e2f..70625c0ac0a 100644 --- a/packages/firestore/src/local/indexeddb_persistence.ts +++ b/packages/firestore/src/local/indexeddb_persistence.ts @@ -183,9 +183,7 @@ export class IndexedDbPersistence implements Persistence { if (txn instanceof IndexedDbTransaction) { return SimpleDb.getStore(txn.simpleDbTransaction, store); } else { - throw fail( - 'IndexedDbPersistence must use instances of IndexedDbTransaction' - ); + throw fail(); } } @@ -304,8 +302,8 @@ export class IndexedDbPersistence implements Persistence { * @return {Promise} Whether persistence was enabled. */ private start(): Promise { - assert(!this.started, 'IndexedDbPersistence double-started!'); - assert(this.window !== null, "Expected 'window' to be defined"); + assert(!this.started); + assert(this.window !== null); return SimpleDb.openOrCreate( this.dbName, @@ -717,10 +715,7 @@ export class IndexedDbPersistence implements Persistence { } getMutationQueue(user: User): MutationQueue { - assert( - this.started, - 'Cannot initialize MutationQueue before persistence is started.' - ); + assert(this.started); return IndexedDbMutationQueue.forUser( user, this.serializer, @@ -730,26 +725,17 @@ export class IndexedDbPersistence implements Persistence { } getTargetCache(): IndexedDbTargetCache { - assert( - this.started, - 'Cannot initialize TargetCache before persistence is started.' - ); + assert(this.started); return this.targetCache; } getRemoteDocumentCache(): IndexedDbRemoteDocumentCache { - assert( - this.started, - 'Cannot initialize RemoteDocumentCache before persistence is started.' - ); + assert(this.started); return this.remoteDocumentCache; } getIndexManager(): IndexedDbIndexManager { - assert( - this.started, - 'Cannot initialize IndexManager before persistence is started.' - ); + assert(this.started); return this.indexManager; } @@ -947,8 +933,7 @@ export class IndexedDbPersistence implements Persistence { if (this.documentVisibilityHandler) { assert( this.document !== null && - typeof this.document.addEventListener === 'function', - "Expected 'document.addEventListener' to be a function" + typeof this.document.addEventListener === 'function' ); this.document.removeEventListener( 'visibilitychange', @@ -988,10 +973,7 @@ export class IndexedDbPersistence implements Persistence { private detachWindowUnloadHook(): void { if (this.windowUnloadHandler) { - assert( - typeof this.window.removeEventListener === 'function', - "Expected 'window.removeEventListener' to be a function" - ); + assert(typeof this.window.removeEventListener === 'function'); this.window.removeEventListener('unload', this.windowUnloadHandler); this.windowUnloadHandler = null; } @@ -1314,11 +1296,8 @@ export class IndexedDbPersistenceProvider implements PersistenceProvider { initialUser: User, settings: PersistenceSettings ): Promise { - assert( - settings.durable, - 'IndexedDbPersistenceProvider can only provide durable persistence' - ); - assert(!this.persistence, 'configure() already called'); + assert(settings.durable); + assert(!this.persistence); const persistenceKey = IndexedDbPersistence.buildStoragePrefix( databaseInfo @@ -1363,17 +1342,17 @@ export class IndexedDbPersistenceProvider implements PersistenceProvider { } getPersistence(): Persistence { - assert(!!this.persistence, 'initialize() not called'); + assert(!!this.persistence); return this.persistence; } getSharedClientState(): SharedClientState { - assert(!!this.sharedClientState, 'initialize() not called'); + assert(!!this.sharedClientState); return this.sharedClientState; } getGarbageCollectionScheduler(): GarbageCollectionScheduler { - assert(!!this.gcScheduler, 'initialize() not called'); + assert(!!this.gcScheduler); return this.gcScheduler; } diff --git a/packages/firestore/src/local/indexeddb_remote_document_cache.ts b/packages/firestore/src/local/indexeddb_remote_document_cache.ts index ff4e794b4ba..c2470305e8b 100644 --- a/packages/firestore/src/local/indexeddb_remote_document_cache.ts +++ b/packages/firestore/src/local/indexeddb_remote_document_cache.ts @@ -243,10 +243,7 @@ export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache { query: Query, sinceReadTime: SnapshotVersion ): PersistencePromise { - assert( - !query.isCollectionGroupQuery(), - 'CollectionGroup queries should be handled in LocalDocumentsView' - ); + assert(!query.isCollectionGroupQuery()); let results = documentMap(); const immediateChildrenPathLength = query.path.length + 1; @@ -363,7 +360,7 @@ export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache { return documentGlobalStore(txn) .get(DbRemoteDocumentGlobal.key) .next(metadata => { - assert(!!metadata, 'Missing document cache metadata'); + assert(!!metadata); return metadata!; }); } @@ -437,15 +434,9 @@ export class IndexedDbRemoteDocumentCache implements RemoteDocumentCache { this.changes.forEach((key, maybeDocument) => { const previousSize = this.documentSizes.get(key); - assert( - previousSize !== undefined, - `Cannot modify a document that wasn't read (for ${key})` - ); + assert(previousSize !== undefined); if (maybeDocument) { - assert( - !this.readTime.isEqual(SnapshotVersion.MIN), - 'Cannot add a document with a read time of zero' - ); + assert(!this.readTime.isEqual(SnapshotVersion.MIN)); const doc = this.documentCache.serializer.toDbRemoteDocument( maybeDocument, this.readTime @@ -565,7 +556,7 @@ export function dbDocumentSize(doc: DbRemoteDocument): number { } else if (doc.noDocument) { value = doc.noDocument; } else { - throw fail('Unknown remote document type'); + throw fail(); } return JSON.stringify(value).length; } diff --git a/packages/firestore/src/local/indexeddb_schema.ts b/packages/firestore/src/local/indexeddb_schema.ts index b7bd71377e5..50e0af80d5d 100644 --- a/packages/firestore/src/local/indexeddb_schema.ts +++ b/packages/firestore/src/local/indexeddb_schema.ts @@ -69,10 +69,7 @@ export class SchemaConverter implements SimpleDbSchemaConverter { toVersion: number ): PersistencePromise { assert( - fromVersion < toVersion && - fromVersion >= 0 && - toVersion <= SCHEMA_VERSION, - `Unexpected schema upgrade from v${fromVersion} to v${toVersion}.` + fromVersion < toVersion && fromVersion >= 0 && toVersion <= SCHEMA_VERSION ); const simpleDbTransaction = new SimpleDbTransaction(txn); @@ -195,10 +192,7 @@ export class SchemaConverter implements SimpleDbSchemaConverter { return PersistencePromise.forEach( dbBatches, (dbBatch: DbMutationBatch) => { - assert( - dbBatch.userId === queue.userId, - `Cannot process batch ${dbBatch.batchId} from unexpected user` - ); + assert(dbBatch.userId === queue.userId); const batch = this.serializer.fromDbMutationBatch(dbBatch); return removeMutationBatch( @@ -866,10 +860,7 @@ export class DbTargetDocument { */ public sequenceNumber?: ListenSequenceNumber ) { - assert( - (targetId === 0) === (sequenceNumber !== undefined), - 'A target-document row must either have targetId == 0 and a defined sequence number, or a non-zero targetId and no sequence number' - ); + assert((targetId === 0) === (sequenceNumber !== undefined)); } } diff --git a/packages/firestore/src/local/indexeddb_target_cache.ts b/packages/firestore/src/local/indexeddb_target_cache.ts index edbdc04b275..d36ff74c3f4 100644 --- a/packages/firestore/src/local/indexeddb_target_cache.ts +++ b/packages/firestore/src/local/indexeddb_target_cache.ts @@ -141,7 +141,7 @@ export class IndexedDbTargetCache implements TargetCache { .next(() => targetsStore(transaction).delete(targetData.targetId)) .next(() => this.retrieveMetadata(transaction)) .next(metadata => { - assert(metadata.targetCount > 0, 'Removing from an empty target cache'); + assert(metadata.targetCount > 0); metadata.targetCount -= 1; return this.saveMetadata(transaction, metadata); }); @@ -420,7 +420,7 @@ function retrieveMetadata( DbTargetGlobal.store ); return globalStore.get(DbTargetGlobal.key).next(metadata => { - assert(metadata !== null, 'Missing metadata row.'); + assert(metadata !== null); return metadata; }); } diff --git a/packages/firestore/src/local/local_documents_view.ts b/packages/firestore/src/local/local_documents_view.ts index 69dc839cc10..0057a8d0376 100644 --- a/packages/firestore/src/local/local_documents_view.ts +++ b/packages/firestore/src/local/local_documents_view.ts @@ -194,10 +194,7 @@ export class LocalDocumentsView { query: Query, sinceReadTime: SnapshotVersion ): PersistencePromise { - assert( - query.path.isEmpty(), - 'Currently we only support collection group queries at the root.' - ); + assert(query.path.isEmpty()); const collectionId = query.collectionGroup!; let results = documentMap(); return this.indexManager diff --git a/packages/firestore/src/local/local_serializer.ts b/packages/firestore/src/local/local_serializer.ts index f2901007ccd..34b49962bd3 100644 --- a/packages/firestore/src/local/local_serializer.ts +++ b/packages/firestore/src/local/local_serializer.ts @@ -67,7 +67,7 @@ export class LocalSerializer { const version = this.fromDbTimestamp(remoteDoc.unknownDocument.version); return new UnknownDocument(key, version); } else { - return fail('Unexpected DbRemoteDocument'); + return fail(); } } @@ -113,7 +113,7 @@ export class LocalSerializer { parentPath ); } else { - return fail('Unexpected MaybeDocument'); + return fail(); } } @@ -225,13 +225,7 @@ export class LocalSerializer { /** Encodes TargetData into a DbTarget for storage locally. */ toDbTarget(targetData: TargetData): DbTarget { - assert( - TargetPurpose.Listen === targetData.purpose, - 'Only queries with purpose ' + - TargetPurpose.Listen + - ' may be stored, got ' + - targetData.purpose - ); + assert(TargetPurpose.Listen === targetData.purpose); const dbTimestamp = this.toDbTimestamp(targetData.snapshotVersion); const dbLastLimboFreeTimestamp = this.toDbTimestamp( targetData.lastLimboFreeSnapshotVersion diff --git a/packages/firestore/src/local/local_store.ts b/packages/firestore/src/local/local_store.ts index e3006b812d0..4cb645f7691 100644 --- a/packages/firestore/src/local/local_store.ts +++ b/packages/firestore/src/local/local_store.ts @@ -198,10 +198,7 @@ export class LocalStore { private queryEngine: QueryEngine, initialUser: User ) { - assert( - persistence.started, - 'LocalStore was passed an unstarted persistence implementation' - ); + assert(persistence.started); this.persistence.referenceDelegate.setInMemoryPins( this.localViewReferences ); @@ -432,7 +429,7 @@ export class LocalStore { return this.mutationQueue .lookupMutationBatch(txn, batchId) .next((batch: MutationBatch | null) => { - assert(batch !== null, 'Attempt to reject nonexistent batch!'); + assert(batch !== null); affectedKeys = batch.keys(); return this.mutationQueue.removeMutationBatch(txn, batch); }) @@ -603,10 +600,7 @@ export class LocalStore { (doc.version.compareTo(existingDoc.version) === 0 && existingDoc.hasPendingWrites) ) { - assert( - !SnapshotVersion.MIN.isEqual(remoteVersion), - 'Cannot add a document when the remote version is zero' - ); + assert(!SnapshotVersion.MIN.isEqual(remoteVersion)); documentBuffer.addEntry(doc, remoteVersion); changedDocs = changedDocs.insert(key, doc); } else { @@ -641,13 +635,7 @@ export class LocalStore { const updateRemoteVersion = this.targetCache .getLastRemoteSnapshotVersion(txn) .next(lastRemoteSnapshotVersion => { - assert( - remoteVersion.compareTo(lastRemoteSnapshotVersion) >= 0, - 'Watch stream reverted to previous snapshot?? ' + - remoteVersion + - ' < ' + - lastRemoteSnapshotVersion - ); + assert(remoteVersion.compareTo(lastRemoteSnapshotVersion) >= 0); return this.targetCache.setTargetsMetadata( txn, txn.currentSequenceNumber, @@ -688,10 +676,7 @@ export class LocalStore { newTargetData: TargetData, change: TargetChange ): boolean { - assert( - newTargetData.resumeToken.approximateByteSize() > 0, - 'Attempted to persist target data with no resume token' - ); + assert(newTargetData.resumeToken.approximateByteSize() > 0); // Always persist target data if we don't already have a resume token. if (oldTargetData.resumeToken.approximateByteSize() === 0) { @@ -737,10 +722,7 @@ export class LocalStore { if (!viewChange.fromCache) { const targetData = this.targetDataByTarget.get(targetId); - assert( - targetData !== null, - `Can't set limbo-free snapshot version for unknown target: ${targetId}` - ); + assert(targetData !== null); // Advance the last limbo free snapshot version const lastLimboFreeSnapshotVersion = targetData.snapshotVersion; @@ -883,10 +865,7 @@ export class LocalStore { keepPersistedTargetData: boolean ): Promise { const targetData = this.targetDataByTarget.get(targetId); - assert( - targetData !== null, - `Tried to release nonexistent target: ${targetId}` - ); + assert(targetData !== null); const mode = keepPersistedTargetData ? 'readwrite' : 'readwrite-primary'; return this.persistence @@ -1010,21 +989,11 @@ export class LocalStore { .next((remoteDoc: MaybeDocument | null) => { let doc = remoteDoc; const ackVersion = batchResult.docVersions.get(docKey); - assert( - ackVersion !== null, - 'ackVersions should contain every doc in the write.' - ); + assert(ackVersion !== null); if (!doc || doc.version.compareTo(ackVersion!) < 0) { doc = batch.applyToRemoteDocument(docKey, doc, batchResult); if (!doc) { - assert( - !remoteDoc, - 'Mutation batch ' + - batch + - ' applied to document ' + - remoteDoc + - ' resulted in null' - ); + assert(!remoteDoc); } else { // We use the commitVersion as the readTime rather than the // document's updateTime since the updateTime is not advanced diff --git a/packages/firestore/src/local/lru_garbage_collector.ts b/packages/firestore/src/local/lru_garbage_collector.ts index 1a7ea7815e8..255c8db7cc1 100644 --- a/packages/firestore/src/local/lru_garbage_collector.ts +++ b/packages/firestore/src/local/lru_garbage_collector.ts @@ -226,10 +226,7 @@ export class LruScheduler { } start(localStore: LocalStore): void { - assert( - this.gcTask === null, - 'Cannot start an already started LruScheduler' - ); + assert(this.gcTask === null); if ( this.garbageCollector.params.cacheSizeCollectionThreshold !== LruParams.COLLECTION_DISABLED @@ -250,7 +247,7 @@ export class LruScheduler { } private scheduleGC(localStore: LocalStore): void { - assert(this.gcTask === null, 'Cannot schedule GC while a task is pending'); + assert(this.gcTask === null); const delay = this.hasRun ? REGULAR_GC_DELAY_MS : INITIAL_GC_DELAY_MS; logDebug( 'LruGarbageCollector', diff --git a/packages/firestore/src/local/memory_index_manager.ts b/packages/firestore/src/local/memory_index_manager.ts index f18a9b60c02..dbd550b8020 100644 --- a/packages/firestore/src/local/memory_index_manager.ts +++ b/packages/firestore/src/local/memory_index_manager.ts @@ -58,7 +58,7 @@ export class MemoryCollectionParentIndex { // Returns false if the entry already existed. add(collectionPath: ResourcePath): boolean { - assert(collectionPath.length % 2 === 1, 'Expected a collection path.'); + assert(collectionPath.length % 2 === 1); const collectionId = collectionPath.lastSegment(); const parentPath = collectionPath.popLast(); const existingParents = diff --git a/packages/firestore/src/local/memory_mutation_queue.ts b/packages/firestore/src/local/memory_mutation_queue.ts index ba59a8bbebd..4a34769b3f9 100644 --- a/packages/firestore/src/local/memory_mutation_queue.ts +++ b/packages/firestore/src/local/memory_mutation_queue.ts @@ -69,20 +69,11 @@ export class MemoryMutationQueue implements MutationQueue { ): PersistencePromise { const batchId = batch.batchId; const batchIndex = this.indexOfExistingBatchId(batchId, 'acknowledged'); - assert( - batchIndex === 0, - 'Can only acknowledge the first batch in the mutation queue' - ); + assert(batchIndex === 0); // Verify that the batch in the queue is the one to be acknowledged. const check = this.mutationQueue[batchIndex]; - assert( - batchId === check.batchId, - 'Queue ordering failure: expected batch ' + - batchId + - ', got batch ' + - check.batchId - ); + assert(batchId === check.batchId); this.lastStreamToken = streamToken; return PersistencePromise.resolve(); @@ -108,17 +99,14 @@ export class MemoryMutationQueue implements MutationQueue { baseMutations: Mutation[], mutations: Mutation[] ): PersistencePromise { - assert(mutations.length !== 0, 'Mutation batches should not be empty'); + assert(mutations.length !== 0); const batchId = this.nextBatchId; this.nextBatchId++; if (this.mutationQueue.length > 0) { const prior = this.mutationQueue[this.mutationQueue.length - 1]; - assert( - prior.batchId < batchId, - 'Mutation batchIDs must be monotonically increasing order' - ); + assert(prior.batchId < batchId); } const batch = new MutationBatch( @@ -156,7 +144,7 @@ export class MemoryMutationQueue implements MutationQueue { batchId: BatchId ): PersistencePromise { const mutationBatch = this.findMutationBatch(batchId); - assert(mutationBatch != null, 'Failed to find local mutation batch.'); + assert(mutationBatch != null); return PersistencePromise.resolve( mutationBatch.keys() ); @@ -197,15 +185,9 @@ export class MemoryMutationQueue implements MutationQueue { const end = new DocReference(documentKey, Number.POSITIVE_INFINITY); const result: MutationBatch[] = []; this.batchesByDocumentKey.forEachInRange([start, end], ref => { - assert( - documentKey.isEqual(ref.key), - "Should only iterate over a single key's batches" - ); + assert(documentKey.isEqual(ref.key)); const batch = this.findMutationBatch(ref.targetOrBatchId); - assert( - batch !== null, - 'Batches in the index must exist in the main table' - ); + assert(batch !== null); result.push(batch!); }); @@ -222,10 +204,7 @@ export class MemoryMutationQueue implements MutationQueue { const start = new DocReference(documentKey, 0); const end = new DocReference(documentKey, Number.POSITIVE_INFINITY); this.batchesByDocumentKey.forEachInRange([start, end], ref => { - assert( - documentKey.isEqual(ref.key), - "For each key, should only iterate over a single key's batches" - ); + assert(documentKey.isEqual(ref.key)); uniqueBatchIDs = uniqueBatchIDs.add(ref.targetOrBatchId); }); @@ -238,10 +217,7 @@ export class MemoryMutationQueue implements MutationQueue { transaction: PersistenceTransaction, query: Query ): PersistencePromise { - assert( - !query.isCollectionGroupQuery(), - 'CollectionGroup queries should be handled in LocalDocumentsView' - ); + assert(!query.isCollectionGroupQuery()); // Use the query path as a prefix for testing if a document matches the // query. const prefix = query.path; @@ -302,10 +278,7 @@ export class MemoryMutationQueue implements MutationQueue { // Find the position of the first batch for removal. This need not be the // first entry in the queue. const batchIndex = this.indexOfExistingBatchId(batch.batchId, 'removed'); - assert( - batchIndex === 0, - 'Can only remove the first entry of the mutation queue' - ); + assert(batchIndex === 0); this.mutationQueue.shift(); let references = this.batchesByDocumentKey; @@ -338,10 +311,7 @@ export class MemoryMutationQueue implements MutationQueue { txn: PersistenceTransaction ): PersistencePromise { if (this.mutationQueue.length === 0) { - assert( - this.batchesByDocumentKey.isEmpty(), - 'Document leak -- detected dangling mutation references when queue is empty.' - ); + assert(this.batchesByDocumentKey.isEmpty()); } return PersistencePromise.resolve(); } @@ -356,10 +326,7 @@ export class MemoryMutationQueue implements MutationQueue { */ private indexOfExistingBatchId(batchId: BatchId, action: string): number { const index = this.indexOfBatchId(batchId); - assert( - index >= 0 && index < this.mutationQueue.length, - 'Batches must exist to be ' + action - ); + assert(index >= 0 && index < this.mutationQueue.length); return index; } @@ -397,7 +364,7 @@ export class MemoryMutationQueue implements MutationQueue { } const batch = this.mutationQueue[index]; - assert(batch.batchId === batchId, 'If found batch must match'); + assert(batch.batchId === batchId); return batch; } } diff --git a/packages/firestore/src/local/memory_persistence.ts b/packages/firestore/src/local/memory_persistence.ts index 95eb7fc788d..979ddd25518 100644 --- a/packages/firestore/src/local/memory_persistence.ts +++ b/packages/firestore/src/local/memory_persistence.ts @@ -224,7 +224,7 @@ export class MemoryEagerDelegate implements MemoryReferenceDelegate { private get orphanedDocuments(): Set { if (!this._orphanedDocuments) { - throw fail('orphanedDocuments is only valid during a transaction.'); + throw fail(); } else { return this._orphanedDocuments; } @@ -534,7 +534,7 @@ export class MemoryPersistenceProvider implements PersistenceProvider { } getPersistence(): Persistence { - assert(!!this.clientId, 'initialize() not called'); + assert(!!this.clientId); return new MemoryPersistence( this.clientId, p => new MemoryEagerDelegate(p) diff --git a/packages/firestore/src/local/memory_remote_document_cache.ts b/packages/firestore/src/local/memory_remote_document_cache.ts index bccf797206f..0bd91a49f69 100644 --- a/packages/firestore/src/local/memory_remote_document_cache.ts +++ b/packages/firestore/src/local/memory_remote_document_cache.ts @@ -78,10 +78,7 @@ export class MemoryRemoteDocumentCache implements RemoteDocumentCache { doc: MaybeDocument, readTime: SnapshotVersion ): PersistencePromise { - assert( - !readTime.isEqual(SnapshotVersion.MIN), - 'Cannot add a document with a read time of zero' - ); + assert(!readTime.isEqual(SnapshotVersion.MIN)); const key = doc.key; const entry = this.docs.get(key); @@ -141,10 +138,7 @@ export class MemoryRemoteDocumentCache implements RemoteDocumentCache { query: Query, sinceReadTime: SnapshotVersion ): PersistencePromise { - assert( - !query.isCollectionGroupQuery(), - 'CollectionGroup queries should be handled in LocalDocumentsView' - ); + assert(!query.isCollectionGroupQuery()); let results = documentMap(); // Documents are ordered by key, so we can use a prefix scan to narrow down diff --git a/packages/firestore/src/local/memory_target_cache.ts b/packages/firestore/src/local/memory_target_cache.ts index 5db9d526a78..74a4c6defcc 100644 --- a/packages/firestore/src/local/memory_target_cache.ts +++ b/packages/firestore/src/local/memory_target_cache.ts @@ -113,10 +113,7 @@ export class MemoryTargetCache implements TargetCache { transaction: PersistenceTransaction, targetData: TargetData ): PersistencePromise { - assert( - !this.targets.has(targetData.target), - 'Adding a target that already exists' - ); + assert(!this.targets.has(targetData.target)); this.saveTargetData(targetData); this.targetCount += 1; return PersistencePromise.resolve(); @@ -126,10 +123,7 @@ export class MemoryTargetCache implements TargetCache { transaction: PersistenceTransaction, targetData: TargetData ): PersistencePromise { - assert( - this.targets.has(targetData.target), - 'Updating a non-existent target' - ); + assert(this.targets.has(targetData.target)); this.saveTargetData(targetData); return PersistencePromise.resolve(); } @@ -138,11 +132,8 @@ export class MemoryTargetCache implements TargetCache { transaction: PersistenceTransaction, targetData: TargetData ): PersistencePromise { - assert(this.targetCount > 0, 'Removing a target from an empty cache'); - assert( - this.targets.has(targetData.target), - 'Removing a non-existent target from the cache' - ); + assert(this.targetCount > 0); + assert(this.targets.has(targetData.target)); this.targets.delete(targetData.target); this.references.removeReferencesForId(targetData.targetId); this.targetCount -= 1; @@ -191,7 +182,7 @@ export class MemoryTargetCache implements TargetCache { ): never { // This method is only needed for multi-tab and we can't implement it // efficiently without additional data structures. - return fail('Not yet implemented.'); + return fail(); } addMatchingKeys( diff --git a/packages/firestore/src/local/persistence_promise.ts b/packages/firestore/src/local/persistence_promise.ts index 0565d938028..e7dcf48d4e6 100644 --- a/packages/firestore/src/local/persistence_promise.ts +++ b/packages/firestore/src/local/persistence_promise.ts @@ -86,7 +86,7 @@ export class PersistencePromise { catchFn?: RejectedHandler ): PersistencePromise { if (this.callbackAttached) { - fail('Called next() or catch() twice for PersistencePromise'); + fail(); } this.callbackAttached = true; if (this.isDone) { diff --git a/packages/firestore/src/local/remote_document_change_buffer.ts b/packages/firestore/src/local/remote_document_change_buffer.ts index dec6eec5658..63a22218713 100644 --- a/packages/firestore/src/local/remote_document_change_buffer.ts +++ b/packages/firestore/src/local/remote_document_change_buffer.ts @@ -70,18 +70,12 @@ export abstract class RemoteDocumentChangeBuffer { // Right now (for simplicity) we just track a single readTime for all the // added entries since we expect them to all be the same, but we could // rework to store per-entry readTimes if necessary. - assert( - this._readTime === undefined || this._readTime.isEqual(value), - 'All changes in a RemoteDocumentChangeBuffer must have the same read time' - ); + assert(this._readTime === undefined || this._readTime.isEqual(value)); this._readTime = value; } protected get readTime(): SnapshotVersion { - assert( - this._readTime !== undefined, - 'Read time is not set. All removeEntry() calls must include a readTime if `trackRemovals` is used.' - ); + assert(this._readTime !== undefined); return this._readTime; } @@ -165,6 +159,6 @@ export abstract class RemoteDocumentChangeBuffer { /** Helper to assert this.changes is not null */ protected assertNotApplied(): void { - assert(!this.changesApplied, 'Changes have already been applied.'); + assert(!this.changesApplied); } } diff --git a/packages/firestore/src/local/shared_client_state.ts b/packages/firestore/src/local/shared_client_state.ts index 5999221d946..a8fdfe82137 100644 --- a/packages/firestore/src/local/shared_client_state.ts +++ b/packages/firestore/src/local/shared_client_state.ts @@ -187,10 +187,7 @@ export class MutationMetadata { readonly state: MutationBatchState, readonly error?: FirestoreError ) { - assert( - (error !== undefined) === (state === 'rejected'), - `MutationMetadata must contain an error iff state is 'rejected'` - ); + assert((error !== undefined) === (state === 'rejected')); } /** @@ -269,10 +266,7 @@ export class QueryTargetMetadata { readonly state: QueryTargetState, readonly error?: FirestoreError ) { - assert( - (error !== undefined) === (state === 'rejected'), - `QueryTargetMetadata must contain an error iff state is 'rejected'` - ); + assert((error !== undefined) === (state === 'rejected')); } /** @@ -548,15 +542,9 @@ export class WebStorageSharedClientState implements SharedClientState { } async start(): Promise { - assert(!this.started, 'WebStorageSharedClientState already started'); - assert( - this.syncEngine !== null, - 'syncEngine property must be set before calling start()' - ); - assert( - this.onlineStateHandler !== null, - 'onlineStateHandler property must be set before calling start()' - ); + assert(!this.started); + assert(this.syncEngine !== null); + assert(this.onlineStateHandler !== null); // Retrieve the list of existing clients to backfill the data in // SharedClientState. @@ -809,7 +797,7 @@ export class WebStorageSharedClientState implements SharedClientState { } } } else if (event.key === this.sequenceNumberKey) { - assert(!!this.sequenceNumberHandler, 'Missing sequenceNumberHandler'); + assert(!!this.sequenceNumberHandler); const sequenceNumber = fromWebStorageSequenceNumber(event.newValue); if (sequenceNumber !== ListenSequence.INVALID) { this.sequenceNumberHandler!(sequenceNumber); @@ -897,7 +885,7 @@ export class WebStorageSharedClientState implements SharedClientState { value: string ): RemoteClientState | null { const clientId = this.fromWebStorageClientStateKey(key); - assert(clientId !== null, `Cannot parse client state key '${key}'`); + assert(clientId !== null); return RemoteClientState.fromWebStorageEntry(clientId, value); } @@ -910,7 +898,7 @@ export class WebStorageSharedClientState implements SharedClientState { value: string ): MutationMetadata | null { const match = this.mutationBatchKeyRe.exec(key); - assert(match !== null, `Cannot parse mutation batch key '${key}'`); + assert(match !== null); const batchId = Number(match[1]); const userId = match[2] !== undefined ? match[2] : null; @@ -930,7 +918,7 @@ export class WebStorageSharedClientState implements SharedClientState { value: string ): QueryTargetMetadata | null { const match = this.queryTargetKeyRe.exec(key); - assert(match !== null, `Cannot parse query target key '${key}'`); + assert(match !== null); const targetId = Number(match[1]); return QueryTargetMetadata.fromWebStorageEntry(targetId, value); @@ -1026,7 +1014,7 @@ function fromWebStorageSequenceNumber( if (seqString != null) { try { const parsed = JSON.parse(seqString); - assert(typeof parsed === 'number', 'Found non-numeric sequence number'); + assert(typeof parsed === 'number'); sequenceNumber = parsed; } catch (e) { logError(LOG_TAG, 'Failed to read sequence number from WebStorage', e); diff --git a/packages/firestore/src/local/shared_client_state_schema.ts b/packages/firestore/src/local/shared_client_state_schema.ts index 3701d011252..3adf89f335f 100644 --- a/packages/firestore/src/local/shared_client_state_schema.ts +++ b/packages/firestore/src/local/shared_client_state_schema.ts @@ -30,10 +30,7 @@ export function createWebStorageClientStateKey( persistenceKey: string, clientId: ClientId ): string { - assert( - clientId.indexOf('_') === -1, - `Client key cannot contain '_', but was '${clientId}'` - ); + assert(clientId.indexOf('_') === -1); return `${CLIENT_STATE_KEY_PREFIX}_${persistenceKey}_${clientId}`; } diff --git a/packages/firestore/src/local/simple_db.ts b/packages/firestore/src/local/simple_db.ts index 3be64714b9f..57b2586120e 100644 --- a/packages/firestore/src/local/simple_db.ts +++ b/packages/firestore/src/local/simple_db.ts @@ -64,10 +64,7 @@ export class SimpleDb { version: number, schemaConverter: SimpleDbSchemaConverter ): Promise { - assert( - SimpleDb.isAvailable(), - 'IndexedDB not supported in current environment.' - ); + assert(SimpleDb.isAvailable()); logDebug(LOG_TAG, 'Opening database:', name); return new PersistencePromise((resolve, reject) => { // TODO(mikelehen): Investigate browser compatibility. @@ -478,7 +475,7 @@ export class SimpleDbTransaction { storeName: string ): SimpleDbStore { const store = this.transaction.objectStore(storeName); - assert(!!store, 'Object store not part of transaction: ' + storeName); + assert(!!store); return new SimpleDbStore(store); } } @@ -738,10 +735,7 @@ export class SimpleDbStore< if (typeof indexOrRange === 'string') { indexName = indexOrRange; } else { - assert( - range === undefined, - '3rd argument must not be defined if 2nd is a range.' - ); + assert(range === undefined); range = indexOrRange; } } diff --git a/packages/firestore/src/local/simple_query_engine.ts b/packages/firestore/src/local/simple_query_engine.ts index b71b7cedf96..bc5776b69f9 100644 --- a/packages/firestore/src/local/simple_query_engine.ts +++ b/packages/firestore/src/local/simple_query_engine.ts @@ -42,10 +42,7 @@ export class SimpleQueryEngine implements QueryEngine { lastLimboFreeSnapshotVersion: SnapshotVersion, remoteKeys: DocumentKeySet ): PersistencePromise { - assert( - this.localDocumentsView !== undefined, - 'setLocalDocumentsView() not called' - ); + assert(this.localDocumentsView !== undefined); // TODO: Once LocalDocumentsView provides a getCollectionDocuments() // method, we should call that here and then filter the results. diff --git a/packages/firestore/src/model/document.ts b/packages/firestore/src/model/document.ts index 9753d0d02ad..a69cc47195c 100644 --- a/packages/firestore/src/model/document.ts +++ b/packages/firestore/src/model/document.ts @@ -114,7 +114,7 @@ export class Document extends MaybeDocument { if (v1 !== null && v2 !== null) { return valueCompare(v1, v2); } else { - return fail("Trying to compare documents on fields that don't exist"); + return fail(); } } } diff --git a/packages/firestore/src/model/document_key.ts b/packages/firestore/src/model/document_key.ts index 956ecde1ba0..7f4fb3fb47f 100644 --- a/packages/firestore/src/model/document_key.ts +++ b/packages/firestore/src/model/document_key.ts @@ -21,11 +21,7 @@ import { ResourcePath } from './path'; export class DocumentKey { constructor(readonly path: ResourcePath) { - assert( - DocumentKey.isDocumentKey(path), - 'Invalid DocumentKey with an odd number of segments: ' + - path.toArray().join('/') - ); + assert(DocumentKey.isDocumentKey(path)); } static fromName(name: string): DocumentKey { diff --git a/packages/firestore/src/model/field_value.ts b/packages/firestore/src/model/field_value.ts index 849fff24964..a6acc61f5fc 100644 --- a/packages/firestore/src/model/field_value.ts +++ b/packages/firestore/src/model/field_value.ts @@ -53,10 +53,7 @@ export class ObjectValue { static EMPTY = new ObjectValue({ mapValue: {} }); constructor(public readonly proto: { mapValue: api.MapValue }) { - assert( - !isServerTimestamp(proto), - 'ServerTimestamps should be converted to ServerTimestampValue' - ); + assert(!isServerTimestamp(proto)); } /** Returns a new Builder instance that is based on an empty object. */ @@ -162,7 +159,7 @@ export class ObjectValueBuilder { * @return The current Builder instance. */ set(path: FieldPath, value: api.Value): ObjectValueBuilder { - assert(!path.isEmpty(), 'Cannot set field for empty path on ObjectValue'); + assert(!path.isEmpty()); this.setOverlay(path, value); return this; } @@ -175,10 +172,7 @@ export class ObjectValueBuilder { * @return The current Builder instance. */ delete(path: FieldPath): ObjectValueBuilder { - assert( - !path.isEmpty(), - 'Cannot delete field for empty path on ObjectValue' - ); + assert(!path.isEmpty()); this.setOverlay(path, null); return this; } diff --git a/packages/firestore/src/model/mutation.ts b/packages/firestore/src/model/mutation.ts index 424ba7e833f..e834b93de53 100644 --- a/packages/firestore/src/model/mutation.ts +++ b/packages/firestore/src/model/mutation.ts @@ -139,10 +139,7 @@ export class Precondition { readonly updateTime?: SnapshotVersion, readonly exists?: boolean ) { - assert( - updateTime === undefined || exists === undefined, - 'Precondition can specify "exists" or "updateTime" but not both' - ); + assert(updateTime === undefined || exists === undefined); } /** Creates a new Precondition with an exists flag. */ @@ -173,7 +170,7 @@ export class Precondition { } else if (this.exists !== undefined) { return this.exists === maybeDoc instanceof Document; } else { - assert(this.isNone, 'Precondition should be empty'); + assert(this.isNone); return true; } } @@ -300,10 +297,7 @@ export abstract class Mutation { protected verifyKeyMatches(maybeDoc: MaybeDocument | null): void { if (maybeDoc != null) { - assert( - maybeDoc.key.isEqual(this.key), - 'Can only apply a mutation to a document with the same key' - ); + assert(maybeDoc.key.isEqual(this.key)); } } @@ -345,10 +339,7 @@ export class SetMutation extends Mutation { ): MaybeDocument { this.verifyKeyMatches(maybeDoc); - assert( - mutationResult.transformResults == null, - 'Transform results received by SetMutation.' - ); + assert(mutationResult.transformResults == null); // Unlike applyToLocalView, if we're applying a mutation to a remote // document the server has accepted the mutation so the precondition must @@ -422,10 +413,7 @@ export class PatchMutation extends Mutation { ): MaybeDocument { this.verifyKeyMatches(maybeDoc); - assert( - mutationResult.transformResults == null, - 'Transform results received by PatchMutation.' - ); + assert(mutationResult.transformResults == null); if (!this.precondition.isValidFor(maybeDoc)) { // Since the mutation was not rejected, we know that the precondition @@ -533,10 +521,7 @@ export class TransformMutation extends Mutation { ): MaybeDocument { this.verifyKeyMatches(maybeDoc); - assert( - mutationResult.transformResults != null, - 'Transform results missing for TransformMutation.' - ); + assert(mutationResult.transformResults != null); if (!this.precondition.isValidFor(maybeDoc)) { // Since the mutation was not rejected, we know that the precondition @@ -625,14 +610,8 @@ export class TransformMutation extends Mutation { * safe. */ private requireDocument(maybeDoc: MaybeDocument | null): Document { - assert( - maybeDoc instanceof Document, - 'Unknown MaybeDocument type ' + maybeDoc - ); - assert( - maybeDoc.key.isEqual(this.key), - 'Can only transform a document with the same key' - ); + assert(maybeDoc instanceof Document); + assert(maybeDoc.key.isEqual(this.key)); return maybeDoc; } @@ -650,11 +629,7 @@ export class TransformMutation extends Mutation { serverTransformResults: Array ): api.Value[] { const transformResults: api.Value[] = []; - assert( - this.fieldTransforms.length === serverTransformResults.length, - `server transform result count (${serverTransformResults.length}) ` + - `should match field transform count (${this.fieldTransforms.length})` - ); + assert(this.fieldTransforms.length === serverTransformResults.length); for (let i = 0; i < serverTransformResults.length; i++) { const fieldTransform = this.fieldTransforms[i]; @@ -718,10 +693,7 @@ export class TransformMutation extends Mutation { data: ObjectValue, transformResults: api.Value[] ): ObjectValue { - assert( - transformResults.length === this.fieldTransforms.length, - 'TransformResults length mismatch.' - ); + assert(transformResults.length === this.fieldTransforms.length); const builder = data.toBuilder(); for (let i = 0; i < this.fieldTransforms.length; i++) { @@ -747,10 +719,7 @@ export class DeleteMutation extends Mutation { ): MaybeDocument { this.verifyKeyMatches(maybeDoc); - assert( - mutationResult.transformResults == null, - 'Transform results received by DeleteMutation.' - ); + assert(mutationResult.transformResults == null); // Unlike applyToLocalView, if we're applying a mutation to a remote // document the server has accepted the mutation so the precondition must @@ -773,10 +742,7 @@ export class DeleteMutation extends Mutation { } if (maybeDoc) { - assert( - maybeDoc.key.isEqual(this.key), - 'Can only apply mutation to document with same key' - ); + assert(maybeDoc.key.isEqual(this.key)); } return new NoDocument(this.key, SnapshotVersion.forDeletedDoc()); } @@ -812,7 +778,7 @@ export class VerifyMutation extends Mutation { maybeDoc: MaybeDocument | null, mutationResult: MutationResult ): MaybeDocument { - fail('VerifyMutation should only be used in Transactions.'); + fail(); } applyToLocalView( @@ -820,11 +786,11 @@ export class VerifyMutation extends Mutation { baseDoc: MaybeDocument | null, localWriteTime: Timestamp ): MaybeDocument | null { - fail('VerifyMutation should only be used in Transactions.'); + fail(); } extractBaseValue(maybeDoc: MaybeDocument | null): null { - fail('VerifyMutation should only be used in Transactions.'); + fail(); } isEqual(other: Mutation): boolean { diff --git a/packages/firestore/src/model/mutation_batch.ts b/packages/firestore/src/model/mutation_batch.ts index a9f0fb5fe0f..574a5255250 100644 --- a/packages/firestore/src/model/mutation_batch.ts +++ b/packages/firestore/src/model/mutation_batch.ts @@ -55,7 +55,7 @@ export class MutationBatch { public baseMutations: Mutation[], public mutations: Mutation[] ) { - assert(mutations.length > 0, 'Cannot create an empty mutation batch'); + assert(mutations.length > 0); } /** @@ -73,20 +73,11 @@ export class MutationBatch { batchResult: MutationBatchResult ): MaybeDocument | null { if (maybeDoc) { - assert( - maybeDoc.key.isEqual(docKey), - `applyToRemoteDocument: key ${docKey} should match maybeDoc key - ${maybeDoc.key}` - ); + assert(maybeDoc.key.isEqual(docKey)); } const mutationResults = batchResult.mutationResults; - assert( - mutationResults.length === this.mutations.length, - `Mismatch between mutations length - (${this.mutations.length}) and mutation results length - (${mutationResults.length}).` - ); + assert(mutationResults.length === this.mutations.length); for (let i = 0; i < this.mutations.length; i++) { const mutation = this.mutations[i]; @@ -110,11 +101,7 @@ export class MutationBatch { maybeDoc: MaybeDocument | null ): MaybeDocument | null { if (maybeDoc) { - assert( - maybeDoc.key.isEqual(docKey), - `applyToLocalDocument: key ${docKey} should match maybeDoc key - ${maybeDoc.key}` - ); + assert(maybeDoc.key.isEqual(docKey)); } // First, apply the base state. This allows us to apply non-idempotent @@ -208,13 +195,7 @@ export class MutationBatchResult { results: MutationResult[], streamToken: ByteString ): MutationBatchResult { - assert( - batch.mutations.length === results.length, - 'Mutations sent ' + - batch.mutations.length + - ' must equal results received ' + - results.length - ); + assert(batch.mutations.length === results.length); let versionMap = documentVersionMap(); const mutations = batch.mutations; diff --git a/packages/firestore/src/model/path.ts b/packages/firestore/src/model/path.ts index e4b79e43e4d..c79b644c5f8 100644 --- a/packages/firestore/src/model/path.ts +++ b/packages/firestore/src/model/path.ts @@ -32,13 +32,13 @@ abstract class BasePath> { if (offset === undefined) { offset = 0; } else if (offset > segments.length) { - fail('offset ' + offset + ' out of range ' + segments.length); + fail(); } if (length === undefined) { length = segments.length - offset; } else if (length > segments.length - offset) { - fail('length ' + length + ' out of range ' + (segments.length - offset)); + fail(); } this.segments = segments; this.offset = offset; @@ -90,7 +90,7 @@ abstract class BasePath> { popFirst(size?: number): B { size = size === undefined ? 1 : size; - assert(this.length >= size, "Can't call popFirst() with less segments"); + assert(this.length >= size); return this.construct( this.segments, this.offset + size, @@ -99,12 +99,12 @@ abstract class BasePath> { } popLast(): B { - assert(!this.isEmpty(), "Can't call popLast() on empty path"); + assert(!this.isEmpty()); return this.construct(this.segments, this.offset, this.length - 1); } firstSegment(): string { - assert(!this.isEmpty(), "Can't call firstSegment() on empty path"); + assert(!this.isEmpty()); return this.segments[this.offset]; } @@ -113,7 +113,7 @@ abstract class BasePath> { } get(index: number): string { - assert(index < this.length, 'Index out of range'); + assert(index < this.length); return this.segments[this.offset + index]; } diff --git a/packages/firestore/src/model/transform_operation.ts b/packages/firestore/src/model/transform_operation.ts index fd887da2b16..981ae3bef7d 100644 --- a/packages/firestore/src/model/transform_operation.ts +++ b/packages/firestore/src/model/transform_operation.ts @@ -193,10 +193,7 @@ export class NumericIncrementTransformOperation implements TransformOperation { private readonly serializer: JsonProtoSerializer, readonly operand: api.Value ) { - assert( - isNumber(operand), - 'NumericIncrementTransform transform requires a NumberValue' - ); + assert(isNumber(operand)); } applyToLocalView( @@ -219,10 +216,7 @@ export class NumericIncrementTransformOperation implements TransformOperation { previousValue: api.Value | null, transformResult: api.Value | null ): api.Value { - assert( - transformResult !== null, - "Didn't receive transformResult for NUMERIC_ADD transform" - ); + assert(transformResult !== null); return transformResult; } diff --git a/packages/firestore/src/model/values.ts b/packages/firestore/src/model/values.ts index 26d0c863779..fff6fa340e7 100644 --- a/packages/firestore/src/model/values.ts +++ b/packages/firestore/src/model/values.ts @@ -62,7 +62,7 @@ export function typeOrder(value: api.Value): TypeOrder { } return TypeOrder.ObjectValue; } else { - return fail('Invalid value type: ' + JSON.stringify(value)); + return fail(); } } @@ -102,7 +102,7 @@ export function valueEquals(left: api.Value, right: api.Value): boolean { case TypeOrder.ObjectValue: return objectEquals(left, right); default: - return fail('Unexpected value type: ' + JSON.stringify(left)); + return fail(); } } @@ -224,7 +224,7 @@ export function valueCompare(left: api.Value, right: api.Value): number { case TypeOrder.ObjectValue: return compareMaps(left.mapValue!, right.mapValue!); default: - throw fail('Invalid value type: ' + leftType); + throw fail(); } } @@ -377,7 +377,7 @@ function canonifyValue(value: api.Value): string { } else if ('mapValue' in value) { return canonifyMap(value.mapValue!); } else { - return fail('Invalid value type: ' + JSON.stringify(value)); + return fail(); } } @@ -468,7 +468,7 @@ export function estimateByteSize(value: api.Value): number { case TypeOrder.ObjectValue: return estimateMapByteSize(value.mapValue!); default: - throw fail('Invalid value type: ' + JSON.stringify(value)); + throw fail(); } } @@ -494,7 +494,7 @@ function estimateArrayByteSize(arrayValue: api.ArrayValue): number { export function normalizeTimestamp( date: api.Timestamp ): { seconds: number; nanos: number } { - assert(!!date, 'Cannot normalize null or undefined timestamp.'); + assert(!!date); // The json interface (for the browser) will return an iso timestamp string, // while the proto js library (for node) will return a @@ -506,7 +506,7 @@ export function normalizeTimestamp( // Parse the nanos right out of the string. let nanos = 0; const fraction = ISO_TIMESTAMP_REG_EXP.exec(date); - assert(!!fraction, 'invalid timestamp: ' + date); + assert(!!fraction); if (fraction[1]) { // Pad the fraction out to 9 digits (nanos). let nanoStr = fraction[1]; diff --git a/packages/firestore/src/platform/platform.ts b/packages/firestore/src/platform/platform.ts index 7f6176e3a0d..d0ac39a9988 100644 --- a/packages/firestore/src/platform/platform.ts +++ b/packages/firestore/src/platform/platform.ts @@ -74,14 +74,14 @@ export class PlatformSupport { private static platform: Platform; static setPlatform(platform: Platform): void { if (PlatformSupport.platform) { - fail('Platform already defined'); + fail(); } PlatformSupport.platform = platform; } static getPlatform(): Platform { if (!PlatformSupport.platform) { - fail('Platform not set'); + fail(); } return PlatformSupport.platform; } diff --git a/packages/firestore/src/platform_browser/webchannel_connection.ts b/packages/firestore/src/platform_browser/webchannel_connection.ts index 5641d1ba64b..5d1f36b3a86 100644 --- a/packages/firestore/src/platform_browser/webchannel_connection.ts +++ b/packages/firestore/src/platform_browser/webchannel_connection.ts @@ -167,16 +167,7 @@ export class WebChannelConnection implements Connection { } break; default: - fail( - 'RPC "' + - rpcName + - '" failed with unanticipated ' + - 'webchannel error ' + - xhr.getLastErrorCode() + - ': ' + - xhr.getLastError() + - ', giving up.' - ); + fail(); } } finally { logDebug(LOG_TAG, 'RPC "' + rpcName + '" completed.'); @@ -374,7 +365,7 @@ export class WebChannelConnection implements Connection { msg => { if (!closed) { const msgData = msg!.data[0]; - assert(!!msgData, 'Got a webchannel message without data.'); + assert(!!msgData); // TODO(b/35143891): There is a bug in One Platform that caused errors // (and only errors) to be wrapped in an extra array. To be forward // compatible with the bug we need to check either condition. The latter @@ -423,7 +414,7 @@ export class WebChannelConnection implements Connection { // visible for testing makeUrl(rpcName: string): string { const urlRpcName = RPC_NAME_REST_MAPPING[rpcName]; - assert(urlRpcName !== undefined, 'Unknown REST mapping for: ' + rpcName); + assert(urlRpcName !== undefined); return ( this.baseUrl + '/' + diff --git a/packages/firestore/src/platform_node/grpc_connection.ts b/packages/firestore/src/platform_node/grpc_connection.ts index a933af52f6e..8660bf564c9 100644 --- a/packages/firestore/src/platform_node/grpc_connection.ts +++ b/packages/firestore/src/platform_node/grpc_connection.ts @@ -45,10 +45,7 @@ function createMetadata( databaseInfo: DatabaseInfo, token: Token | null ): grpc.Metadata { - assert( - token === null || token.type === 'OAuth', - 'If provided, token must be OAuth' - ); + assert(token === null || token.type === 'OAuth'); const metadata = new grpc.Metadata(); if (token) { diff --git a/packages/firestore/src/remote/datastore.ts b/packages/firestore/src/remote/datastore.ts index 231bb775998..254ee9b7045 100644 --- a/packages/firestore/src/remote/datastore.ts +++ b/packages/firestore/src/remote/datastore.ts @@ -114,7 +114,7 @@ export class Datastore { const result: MaybeDocument[] = []; keys.forEach(key => { const doc = docs.get(key); - assert(!!doc, 'Missing entity in write response for ' + key); + assert(!!doc); result.push(doc); }); return result; diff --git a/packages/firestore/src/remote/online_state_tracker.ts b/packages/firestore/src/remote/online_state_tracker.ts index d6f68598e15..721d7a30289 100644 --- a/packages/firestore/src/remote/online_state_tracker.ts +++ b/packages/firestore/src/remote/online_state_tracker.ts @@ -89,19 +89,13 @@ export class OnlineStateTracker { if (this.watchStreamFailures === 0) { this.setAndBroadcast(OnlineState.Unknown); - assert( - this.onlineStateTimer === null, - `onlineStateTimer shouldn't be started yet` - ); + assert(this.onlineStateTimer === null); this.onlineStateTimer = this.asyncQueue.enqueueAfterDelay( TimerId.OnlineStateTimeout, ONLINE_STATE_TIMEOUT_MS, () => { this.onlineStateTimer = null; - assert( - this.state === OnlineState.Unknown, - 'Timer should be canceled if we transitioned to a different state.' - ); + assert(this.state === OnlineState.Unknown); this.logClientOfflineWarningIfNecessary( `Backend didn't respond within ${ONLINE_STATE_TIMEOUT_MS / 1000} ` + `seconds.` @@ -130,8 +124,8 @@ export class OnlineStateTracker { // To get to OnlineState.Online, set() must have been called which would // have reset our heuristics. - assert(this.watchStreamFailures === 0, 'watchStreamFailures must be 0'); - assert(this.onlineStateTimer === null, 'onlineStateTimer must be null'); + assert(this.watchStreamFailures === 0); + assert(this.onlineStateTimer === null); } else { this.watchStreamFailures++; if (this.watchStreamFailures >= MAX_WATCH_STREAM_FAILURES) { diff --git a/packages/firestore/src/remote/persistent_stream.ts b/packages/firestore/src/remote/persistent_stream.ts index 2c8f5170ce6..a7679639c82 100644 --- a/packages/firestore/src/remote/persistent_stream.ts +++ b/packages/firestore/src/remote/persistent_stream.ts @@ -216,7 +216,7 @@ export abstract class PersistentStream< return; } - assert(this.state === PersistentStreamState.Initial, 'Already started'); + assert(this.state === PersistentStreamState.Initial); this.auth(); } @@ -241,7 +241,7 @@ export abstract class PersistentStream< * inhibit backoff if required. */ inhibitBackoff(): void { - assert(!this.isStarted(), 'Can only inhibit backoff in a stopped state'); + assert(!this.isStarted()); this.state = PersistentStreamState.Initial; this.backoff.reset(); @@ -309,10 +309,9 @@ export abstract class PersistentStream< finalState: PersistentStreamState, error?: FirestoreError ): Promise { - assert(this.isStarted(), 'Only started streams should be closed.'); + assert(this.isStarted()); assert( - finalState === PersistentStreamState.Error || isNullOrUndefined(error), - "Can't provide an error when not in an error state." + finalState === PersistentStreamState.Error || isNullOrUndefined(error) ); // Cancel any outstanding timers (they're guaranteed not to execute). @@ -376,10 +375,7 @@ export abstract class PersistentStream< protected abstract onMessage(message: ReceiveType): Promise; private auth(): void { - assert( - this.state === PersistentStreamState.Initial, - 'Must be in initial state to auth' - ); + assert(this.state === PersistentStreamState.Initial); this.state = PersistentStreamState.Starting; @@ -414,20 +410,14 @@ export abstract class PersistentStream< } private startStream(token: Token | null): void { - assert( - this.state === PersistentStreamState.Starting, - 'Trying to start stream in a non-starting state' - ); + assert(this.state === PersistentStreamState.Starting); const dispatchIfNotClosed = this.getCloseGuardedDispatcher(this.closeCount); this.stream = this.startRpc(token); this.stream.onOpen(() => { dispatchIfNotClosed(() => { - assert( - this.state === PersistentStreamState.Starting, - 'Expected stream to be in state Starting, but was ' + this.state - ); + assert(this.state === PersistentStreamState.Starting); this.state = PersistentStreamState.Open; return this.listener!.onOpen(); }); @@ -445,27 +435,21 @@ export abstract class PersistentStream< } private performBackoff(): void { - assert( - this.state === PersistentStreamState.Error, - 'Should only perform backoff when in Error state' - ); + assert(this.state === PersistentStreamState.Error); this.state = PersistentStreamState.Backoff; this.backoff.backoffAndRun(async () => { - assert( - this.state === PersistentStreamState.Backoff, - 'Backoff elapsed but state is now: ' + this.state - ); + assert(this.state === PersistentStreamState.Backoff); this.state = PersistentStreamState.Initial; this.start(); - assert(this.isStarted(), 'PersistentStream should have started'); + assert(this.isStarted()); }); } // Visible for tests handleStreamClose(error?: FirestoreError): Promise { - assert(this.isStarted(), "Can't handle server close on non-started stream"); + assert(this.isStarted()); logDebug(LOG_TAG, `close with error: ${error}`); this.stream = null; @@ -694,17 +678,13 @@ export class PersistentWriteStream extends PersistentStream< protected onMessage(responseProto: api.WriteResponse): Promise { // Always capture the last stream token. - assert( - !!responseProto.streamToken, - 'Got a write response without a stream token' - ); + assert(!!responseProto.streamToken); this.lastStreamToken = this.serializer.fromBytes(responseProto.streamToken); if (!this.handshakeComplete_) { // The first response is always the handshake response assert( - !responseProto.writeResults || responseProto.writeResults.length === 0, - 'Got mutation results for handshake' + !responseProto.writeResults || responseProto.writeResults.length === 0 ); this.handshakeComplete_ = true; return this.listener!.onHandshakeComplete(); @@ -731,8 +711,8 @@ export class PersistentWriteStream extends PersistentStream< * calls should wait until onHandshakeComplete was called. */ writeHandshake(): void { - assert(this.isOpen(), 'Writing handshake requires an opened stream'); - assert(!this.handshakeComplete_, 'Handshake already completed'); + assert(this.isOpen()); + assert(!this.handshakeComplete_); // TODO(dimond): Support stream resumption. We intentionally do not set the // stream token on the handshake, ignoring any stream token we might have. const request: WriteRequest = {}; @@ -742,15 +722,9 @@ export class PersistentWriteStream extends PersistentStream< /** Sends a group of mutations to the Firestore backend to apply. */ writeMutations(mutations: Mutation[]): void { - assert(this.isOpen(), 'Writing mutations requires an opened stream'); - assert( - this.handshakeComplete_, - 'Handshake must be complete before writing mutations' - ); - assert( - this.lastStreamToken.approximateByteSize() > 0, - 'Trying to write mutation without a token' - ); + assert(this.isOpen()); + assert(this.handshakeComplete_); + assert(this.lastStreamToken.approximateByteSize() > 0); const request: WriteRequest = { streamToken: this.serializer.toBytes(this.lastStreamToken), diff --git a/packages/firestore/src/remote/remote_store.ts b/packages/firestore/src/remote/remote_store.ts index 916cc0d7e10..e1120750f7d 100644 --- a/packages/firestore/src/remote/remote_store.ts +++ b/packages/firestore/src/remote/remote_store.ts @@ -262,10 +262,7 @@ export class RemoteStore implements TargetMetadataProvider { * not being listened to. */ unlisten(targetId: TargetId): void { - assert( - objUtils.contains(this.listenTargets, targetId), - `unlisten called on target no currently watched: ${targetId}` - ); + assert(objUtils.contains(this.listenTargets, targetId)); delete this.listenTargets[targetId]; if (this.watchStream.isOpen()) { @@ -314,10 +311,7 @@ export class RemoteStore implements TargetMetadataProvider { } private startWatchStream(): void { - assert( - this.shouldStartWatchStream(), - 'startWatchStream() called when shouldStartWatchStream() is false.' - ); + assert(this.shouldStartWatchStream()); this.watchChangeAggregator = new WatchChangeAggregator(this); this.watchStream.start(); @@ -354,10 +348,7 @@ export class RemoteStore implements TargetMetadataProvider { if (error === undefined) { // Graceful stop (due to stop() or idle timeout). Make sure that's // desirable. - assert( - !this.shouldStartWatchStream(), - 'Watch stream was stopped gracefully while still needed.' - ); + assert(!this.shouldStartWatchStream()); } this.cleanUpWatchStreamState(); @@ -397,10 +388,7 @@ export class RemoteStore implements TargetMetadataProvider { } else if (watchChange instanceof ExistenceFilterChange) { this.watchChangeAggregator!.handleExistenceFilter(watchChange); } else { - assert( - watchChange instanceof WatchTargetChange, - 'Expected watchChange to be an instance of WatchTargetChange' - ); + assert(watchChange instanceof WatchTargetChange); this.watchChangeAggregator!.handleTargetChange(watchChange); } @@ -420,10 +408,7 @@ export class RemoteStore implements TargetMetadataProvider { * SyncEngine. */ private raiseWatchSnapshot(snapshotVersion: SnapshotVersion): Promise { - assert( - !snapshotVersion.isEqual(SnapshotVersion.MIN), - "Can't raise event for unknown SnapshotVersion" - ); + assert(!snapshotVersion.isEqual(SnapshotVersion.MIN)); const remoteEvent = this.watchChangeAggregator!.createRemoteEvent( snapshotVersion ); @@ -482,7 +467,7 @@ export class RemoteStore implements TargetMetadataProvider { /** Handles an error on a target */ private handleTargetError(watchChange: WatchTargetChange): Promise { - assert(!!watchChange.cause, 'Handling target error without a cause'); + assert(!!watchChange.cause); const error = watchChange.cause!; let promiseChain = Promise.resolve(); watchChange.targetIds.forEach(targetId => { @@ -551,10 +536,7 @@ export class RemoteStore implements TargetMetadataProvider { * immediately if the write stream is established. */ private addToWritePipeline(batch: MutationBatch): void { - assert( - this.canAddToWritePipeline(), - 'addToWritePipeline called when pipeline is full' - ); + assert(this.canAddToWritePipeline()); this.writePipeline.push(batch); if (this.writeStream.isOpen() && this.writeStream.handshakeComplete) { @@ -571,10 +553,7 @@ export class RemoteStore implements TargetMetadataProvider { } private startWriteStream(): void { - assert( - this.shouldStartWriteStream(), - 'startWriteStream() called when shouldStartWriteStream() is false.' - ); + assert(this.shouldStartWriteStream()); this.writeStream.start(); } @@ -601,10 +580,7 @@ export class RemoteStore implements TargetMetadataProvider { ): Promise { // This is a response to a write containing mutations and should be // correlated to the first write in our write pipeline. - assert( - this.writePipeline.length > 0, - 'Got result for empty write pipeline' - ); + assert(this.writePipeline.length > 0); const batch = this.writePipeline.shift()!; const success = MutationBatchResult.from( batch, @@ -623,10 +599,7 @@ export class RemoteStore implements TargetMetadataProvider { if (error === undefined) { // Graceful stop (due to stop() or idle timeout). Make sure that's // desirable. - assert( - !this.shouldStartWriteStream(), - 'Write stream was stopped gracefully while still needed.' - ); + assert(!this.shouldStartWriteStream()); } // If the write stream closed due to an error, invoke the error callbacks if diff --git a/packages/firestore/src/remote/rpc_error.ts b/packages/firestore/src/remote/rpc_error.ts index a5362a5907d..7250c64a011 100644 --- a/packages/firestore/src/remote/rpc_error.ts +++ b/packages/firestore/src/remote/rpc_error.ts @@ -58,7 +58,7 @@ enum RpcCode { export function isPermanentError(code: Code): boolean { switch (code) { case Code.OK: - return fail('Treated status OK as error'); + return fail(); case Code.CANCELLED: case Code.UNKNOWN: case Code.DEADLINE_EXCEEDED: @@ -83,7 +83,7 @@ export function isPermanentError(code: Code): boolean { case Code.DATA_LOSS: return true; default: - return fail('Unknown status code: ' + code); + return fail(); } } @@ -171,7 +171,7 @@ export function mapCodeFromRpcCode(code: number | undefined): Code { case RpcCode.DATA_LOSS: return Code.DATA_LOSS; default: - return fail('Unknown status code: ' + code); + return fail(); } } @@ -220,7 +220,7 @@ export function mapRpcCodeFromCode(code: Code | undefined): number { case Code.DATA_LOSS: return RpcCode.DATA_LOSS; default: - return fail('Unknown status code: ' + code); + return fail(); } } diff --git a/packages/firestore/src/remote/serializer.ts b/packages/firestore/src/remote/serializer.ts index ff52027211c..05bd677bfbb 100644 --- a/packages/firestore/src/remote/serializer.ts +++ b/packages/firestore/src/remote/serializer.ts @@ -96,7 +96,7 @@ const OPERATORS = (() => { })(); function assertPresent(value: unknown, description: string): asserts value { - assert(!isNullOrUndefined(value), description + ' is missing'); + assert(!isNullOrUndefined(value)); } export interface SerializerOptions { @@ -241,16 +241,10 @@ export class JsonProtoSerializer { */ fromBytes(value: string | Uint8Array | undefined): ByteString { if (this.options.useProto3Json) { - assert( - value === undefined || typeof value === 'string', - 'value must be undefined or a string when using proto3 Json' - ); + assert(value === undefined || typeof value === 'string'); return ByteString.fromBase64String(value ? value : ''); } else { - assert( - value === undefined || value instanceof Uint8Array, - 'value must be undefined or Uint8Array' - ); + assert(value === undefined || value instanceof Uint8Array); return ByteString.fromUint8Array(value ? value : new Uint8Array()); } } @@ -260,7 +254,7 @@ export class JsonProtoSerializer { } fromVersion(version: api.Timestamp): SnapshotVersion { - assert(!!version, "Trying to deserialize version that isn't set"); + assert(!!version); return SnapshotVersion.fromTimestamp(this.fromTimestamp(version)); } @@ -273,10 +267,7 @@ export class JsonProtoSerializer { fromResourceName(name: string): ResourcePath { const resource = ResourcePath.fromString(name); - assert( - isValidResourceName(resource), - 'Tried to deserialize invalid key ' + resource.toString() - ); + assert(isValidResourceName(resource)); return resource; } @@ -286,20 +277,10 @@ export class JsonProtoSerializer { fromName(name: string): DocumentKey { const resource = this.fromResourceName(name); - assert( - resource.get(1) === this.databaseId.projectId, - 'Tried to deserialize key from different project: ' + - resource.get(1) + - ' vs ' + - this.databaseId.projectId - ); + assert(resource.get(1) === this.databaseId.projectId); assert( (!resource.get(3) && !this.databaseId.database) || - resource.get(3) === this.databaseId.database, - 'Tried to deserialize key from different database: ' + - resource.get(3) + - ' vs ' + - this.databaseId.database + resource.get(3) === this.databaseId.database ); return new DocumentKey(this.extractLocalPathFromResourceName(resource)); } @@ -342,10 +323,7 @@ export class JsonProtoSerializer { private extractLocalPathFromResourceName( resourceName: ResourcePath ): ResourcePath { - assert( - resourceName.length > 4 && resourceName.get(4) === 'documents', - 'tried to deserialize invalid key ' + resourceName.toString() - ); + assert(resourceName.length > 4 && resourceName.get(4) === 'documents'); return resourceName.popFirst(5); } @@ -358,10 +336,7 @@ export class JsonProtoSerializer { } toDocument(document: Document): api.Document { - assert( - !document.hasLocalMutations, - "Can't serialize documents with mutations." - ); + assert(!document.hasLocalMutations); return { name: this.toName(document.key), fields: document.toProto().mapValue.fields, @@ -382,10 +357,7 @@ export class JsonProtoSerializer { } private fromFound(doc: api.BatchGetDocumentsResponse): Document { - assert( - !!doc.found, - 'Tried to deserialize a found document from a missing document.' - ); + assert(!!doc.found); assertPresent(doc.found.name, 'doc.found.name'); assertPresent(doc.found.updateTime, 'doc.found.updateTime'); const key = this.fromName(doc.found.name); @@ -395,14 +367,8 @@ export class JsonProtoSerializer { } private fromMissing(result: api.BatchGetDocumentsResponse): NoDocument { - assert( - !!result.missing, - 'Tried to deserialize a missing document from a found document.' - ); - assert( - !!result.readTime, - 'Tried to deserialize a missing document without a read time.' - ); + assert(!!result.missing); + assert(!!result.readTime); const key = this.fromName(result.missing); const version = this.fromVersion(result.readTime); return new NoDocument(key, version); @@ -414,7 +380,7 @@ export class JsonProtoSerializer { } else if ('missing' in result) { return this.fromMissing(result); } - return fail('invalid batch get response: ' + JSON.stringify(result)); + return fail(); } private toWatchTargetChangeState( @@ -432,7 +398,7 @@ export class JsonProtoSerializer { case WatchTargetChangeState.Reset: return 'RESET'; default: - return fail('Unknown WatchTargetChangeState: ' + state); + return fail(); } } @@ -494,7 +460,7 @@ export class JsonProtoSerializer { } }; } - return fail('Unrecognized watch change: ' + JSON.stringify(watchChange)); + return fail(); } fromWatchChange(change: api.ListenResponse): WatchChange { @@ -568,7 +534,7 @@ export class JsonProtoSerializer { const targetId = filter.targetId; watchChange = new ExistenceFilterChange(targetId, existenceFilter); } else { - return fail('Unknown change type ' + JSON.stringify(change)); + return fail(); } return watchChange; } @@ -587,7 +553,7 @@ export class JsonProtoSerializer { } else if (state === 'RESET') { return WatchTargetChangeState.Reset; } else { - return fail('Got unexpected TargetChange.state: ' + state); + return fail(); } } @@ -635,7 +601,7 @@ export class JsonProtoSerializer { verify: this.toName(mutation.key) }; } else { - return fail('Unknown mutation type ' + mutation.type); + return fail(); } if (!mutation.precondition.isNone) { @@ -670,21 +636,18 @@ export class JsonProtoSerializer { const fieldTransforms = proto.transform.fieldTransforms!.map(transform => this.fromFieldTransform(transform) ); - assert( - precondition.exists === true, - 'Transforms only support precondition "exists == true"' - ); + assert(precondition.exists === true); return new TransformMutation(key, fieldTransforms); } else if (proto.verify) { const key = this.fromName(proto.verify); return new VerifyMutation(key, precondition); } else { - return fail('unknown mutation proto: ' + JSON.stringify(proto)); + return fail(); } } private toPrecondition(precondition: Precondition): api.Precondition { - assert(!precondition.isNone, "Can't serialize an empty precondition"); + assert(!precondition.isNone); if (precondition.updateTime !== undefined) { return { updateTime: this.toVersion(precondition.updateTime) @@ -692,7 +655,7 @@ export class JsonProtoSerializer { } else if (precondition.exists !== undefined) { return { exists: precondition.exists }; } else { - return fail('Unknown precondition'); + return fail(); } } @@ -736,10 +699,7 @@ export class JsonProtoSerializer { commitTime?: api.Timestamp ): MutationResult[] { if (protos && protos.length > 0) { - assert( - commitTime !== undefined, - 'Received a write result without a commit time' - ); + assert(commitTime !== undefined); return protos.map(proto => this.fromWriteResult(proto, commitTime)); } else { return []; @@ -773,17 +733,14 @@ export class JsonProtoSerializer { increment: transform.operand }; } else { - throw fail('Unknown transform: ' + fieldTransform.transform); + throw fail(); } } private fromFieldTransform(proto: api.FieldTransform): FieldTransform { let transform: TransformOperation | null = null; if ('setToServerValue' in proto) { - assert( - proto.setToServerValue === 'REQUEST_TIME', - 'Unknown server value transform proto: ' + JSON.stringify(proto) - ); + assert(proto.setToServerValue === 'REQUEST_TIME'); transform = ServerTimestampTransform.instance; } else if ('appendMissingElements' in proto) { const values = proto.appendMissingElements!.values || []; @@ -797,7 +754,7 @@ export class JsonProtoSerializer { proto.increment! ); } else { - fail('Unknown transform proto: ' + JSON.stringify(proto)); + fail(); } const fieldPath = FieldPath.fromServerFormat(proto.fieldPath!); return new FieldTransform(fieldPath, transform!); @@ -809,10 +766,7 @@ export class JsonProtoSerializer { fromDocumentsTarget(documentsTarget: api.DocumentsTarget): Target { const count = documentsTarget.documents!.length; - assert( - count === 1, - 'DocumentsTarget contained other than 1 document: ' + count - ); + assert(count === 1); const name = documentsTarget.documents![0]; return Query.atPath(this.fromQueryPath(name)).toTarget(); } @@ -822,10 +776,7 @@ export class JsonProtoSerializer { const result: api.QueryTarget = { structuredQuery: {} }; const path = target.path; if (target.collectionGroup !== null) { - assert( - path.length % 2 === 0, - 'Collection Group queries should be within a document path or root.' - ); + assert(path.length % 2 === 0); result.parent = this.toQueryPath(path); result.structuredQuery!.from = [ { @@ -834,10 +785,7 @@ export class JsonProtoSerializer { } ]; } else { - assert( - path.length % 2 !== 0, - 'Document queries with filters are not supported.' - ); + assert(path.length % 2 !== 0); result.parent = this.toQueryPath(path.popLast()); result.structuredQuery!.from = [{ collectionId: path.lastSegment() }]; } @@ -874,10 +822,7 @@ export class JsonProtoSerializer { const fromCount = query.from ? query.from.length : 0; let collectionGroup: string | null = null; if (fromCount > 0) { - assert( - fromCount === 1, - 'StructuredQuery.from with more than one collection is not supported.' - ); + assert(fromCount === 1); const from = query.from![0]; if (from.allDescendants) { collectionGroup = from.collectionId!; @@ -945,7 +890,7 @@ export class JsonProtoSerializer { case TargetPurpose.LimboResolution: return 'limbo-document'; default: - return fail('Unrecognized query purpose: ' + purpose); + return fail(); } } @@ -976,7 +921,7 @@ export class JsonProtoSerializer { if (filter instanceof FieldFilter) { return this.toUnaryOrFieldFilter(filter); } else { - return fail('Unrecognized filter: ' + JSON.stringify(filter)); + return fail(); } }); if (protos.length === 1) { @@ -997,7 +942,7 @@ export class JsonProtoSerializer { .filters!.map(f => this.fromFilter(f)) .reduce((accum, current) => accum.concat(current)); } else { - return fail('Unknown filter: ' + JSON.stringify(filter)); + return fail(); } } @@ -1066,9 +1011,9 @@ export class JsonProtoSerializer { case 'ARRAY_CONTAINS_ANY': return Operator.ARRAY_CONTAINS_ANY; case 'OPERATOR_UNSPECIFIED': - return fail('Unspecified operator'); + return fail(); default: - return fail('Unknown operator'); + return fail(); } } @@ -1148,9 +1093,9 @@ export class JsonProtoSerializer { nullValue: 'NULL_VALUE' }); case 'OPERATOR_UNSPECIFIED': - return fail('Unspecified filter'); + return fail(); default: - return fail('Unknown filter'); + return fail(); } } diff --git a/packages/firestore/src/remote/stream_bridge.ts b/packages/firestore/src/remote/stream_bridge.ts index 28b2ecf6592..92fc095cd02 100644 --- a/packages/firestore/src/remote/stream_bridge.ts +++ b/packages/firestore/src/remote/stream_bridge.ts @@ -39,17 +39,17 @@ export class StreamBridge implements Stream { } onOpen(callback: () => void): void { - assert(!this.wrappedOnOpen, 'Called onOpen on stream twice!'); + assert(!this.wrappedOnOpen); this.wrappedOnOpen = callback; } onClose(callback: (err?: FirestoreError) => void): void { - assert(!this.wrappedOnClose, 'Called onClose on stream twice!'); + assert(!this.wrappedOnClose); this.wrappedOnClose = callback; } onMessage(callback: (msg: O) => void): void { - assert(!this.wrappedOnMessage, 'Called onMessage on stream twice!'); + assert(!this.wrappedOnMessage); this.wrappedOnMessage = callback; } @@ -62,26 +62,17 @@ export class StreamBridge implements Stream { } callOnOpen(): void { - assert( - this.wrappedOnOpen !== undefined, - 'Cannot call onOpen because no callback was set' - ); + assert(this.wrappedOnOpen !== undefined); this.wrappedOnOpen(); } callOnClose(err?: FirestoreError): void { - assert( - this.wrappedOnClose !== undefined, - 'Cannot call onClose because no callback was set' - ); + assert(this.wrappedOnClose !== undefined); this.wrappedOnClose(err); } callOnMessage(msg: O): void { - assert( - this.wrappedOnMessage !== undefined, - 'Cannot call onMessage because no callback was set' - ); + assert(this.wrappedOnMessage !== undefined); this.wrappedOnMessage(msg); } } diff --git a/packages/firestore/src/remote/watch_change.ts b/packages/firestore/src/remote/watch_change.ts index c7bf0e7162b..30ea2762167 100644 --- a/packages/firestore/src/remote/watch_change.ts +++ b/packages/firestore/src/remote/watch_change.ts @@ -191,7 +191,7 @@ class TargetState { removedDocuments = removedDocuments.add(key); break; default: - fail('Encountered invalid change type: ' + changeType); + fail(); } }); @@ -330,10 +330,7 @@ export class WatchChangeAggregator { if (!targetState.isPending) { this.removeTarget(targetId); } - assert( - !targetChange.cause, - 'WatchChangeAggregator does not handle errored targets' - ); + assert(!targetChange.cause); break; case WatchTargetChangeState.Current: if (this.isActiveTarget(targetId)) { @@ -351,7 +348,7 @@ export class WatchChangeAggregator { } break; default: - fail('Unknown target watch change state: ' + targetChange.state); + fail(); } }); } @@ -399,10 +396,7 @@ export class WatchChangeAggregator { new NoDocument(key, SnapshotVersion.forDeletedDoc()) ); } else { - assert( - expectedCount === 1, - 'Single document existence filter with count: ' + expectedCount - ); + assert(expectedCount === 1); } } else { const currentSize = this.getCurrentDocumentCountForTarget(targetId); @@ -647,10 +641,7 @@ export class WatchChangeAggregator { * from all documents). */ private resetTarget(targetId: TargetId): void { - assert( - !this.targetStates[targetId].isPending, - 'Should only reset active targets' - ); + assert(!this.targetStates[targetId].isPending); this.targetStates[targetId] = new TargetState(); // Trigger removal for any documents currently mapped to this target. diff --git a/packages/firestore/src/util/assert.ts b/packages/firestore/src/util/assert.ts index bcaad5776d4..89249bbd42b 100644 --- a/packages/firestore/src/util/assert.ts +++ b/packages/firestore/src/util/assert.ts @@ -25,25 +25,19 @@ import { logError } from './log'; * @example * let futureVar = fail('not implemented yet'); */ -export function fail(failure: string): never { - // Log the failure in addition to throw an exception, just in case the - // exception is swallowed. - const message = - `FIRESTORE (${SDK_VERSION}) INTERNAL ASSERTION FAILED: ` + failure; - logError(message); - +export function fail(): never { // NOTE: We don't use FirestoreError here because these are internal failures // that cannot be handled by the user. (Also it would create a circular // dependency between the error and assert modules which doesn't work.) - throw new Error(message); + throw new Error('Internal Failure'); } /** * Fails if the given assertion condition is false, throwing an Error with the * given message if it did. */ -export function assert(assertion: boolean, message: string): asserts assertion { +export function assert(assertion: boolean): asserts assertion { if (!assertion) { - fail(message); + fail(); } } diff --git a/packages/firestore/src/util/async_queue.ts b/packages/firestore/src/util/async_queue.ts index 06b0912a3a0..c222ffc4235 100644 --- a/packages/firestore/src/util/async_queue.ts +++ b/packages/firestore/src/util/async_queue.ts @@ -324,10 +324,7 @@ export class AsyncQueue { ): CancelablePromise { this.verifyNotFailed(); - assert( - delayMs >= 0, - `Attempted to schedule an operation with a negative delay of ${delayMs}` - ); + assert(delayMs >= 0); // Fast-forward delays for timerIds that have been overriden. if (this.timerIdsToSkip.indexOf(timerId) > -1) { @@ -348,10 +345,7 @@ export class AsyncQueue { private verifyNotFailed(): void { if (this.failure) { - fail( - 'AsyncQueue is already failed: ' + - (this.failure.stack || this.failure.message) - ); + fail(); } } @@ -362,10 +356,7 @@ export class AsyncQueue { * to catch some bugs. */ verifyOperationInProgress(): void { - assert( - this.operationInProgress, - 'verifyOpInProgress() called when no op in progress on this queue.' - ); + assert(this.operationInProgress); } /** @@ -410,8 +401,7 @@ export class AsyncQueue { return this.drain().then(() => { assert( lastTimerId === TimerId.All || - this.containsDelayedOperation(lastTimerId), - `Attempted to drain to missing operation ${lastTimerId}` + this.containsDelayedOperation(lastTimerId) ); // Run ops in the same order they'd run if they ran naturally. @@ -439,7 +429,7 @@ export class AsyncQueue { private removeDelayedOperation(op: DelayedOperation): void { // NOTE: indexOf / slice are O(n), but delayedOperations is expected to be small. const index = this.delayedOperations.indexOf(op); - assert(index >= 0, 'Delayed operation not found.'); + assert(index >= 0); this.delayedOperations.splice(index, 1); } } diff --git a/packages/firestore/src/util/input_validation.ts b/packages/firestore/src/util/input_validation.ts index 52dc20d7b7b..22eb65dc227 100644 --- a/packages/firestore/src/util/input_validation.ts +++ b/packages/firestore/src/util/input_validation.ts @@ -381,7 +381,7 @@ export function valueDescription(input: unknown): string { } else if (typeof input === 'function') { return 'a function'; } else { - return fail('Unknown wrong type: ' + typeof input); + return fail(); } } diff --git a/packages/firestore/src/util/misc.ts b/packages/firestore/src/util/misc.ts index dd37a9d3b36..d5c1ca4e881 100644 --- a/packages/firestore/src/util/misc.ts +++ b/packages/firestore/src/util/misc.ts @@ -41,7 +41,7 @@ export class AutoId { } }); } - assert(autoId.length === 20, 'Invalid auto ID: ' + autoId); + assert(autoId.length === 20); return autoId; } } diff --git a/packages/firestore/src/util/obj.ts b/packages/firestore/src/util/obj.ts index 19a11d8c0df..3a85c60a18a 100644 --- a/packages/firestore/src/util/obj.ts +++ b/packages/firestore/src/util/obj.ts @@ -94,10 +94,7 @@ export function lookupOrInsert( } export function isEmpty(obj: Dict): boolean { - assert( - obj != null && typeof obj === 'object', - 'isEmpty() expects object parameter.' - ); + assert(obj != null && typeof obj === 'object'); for (const key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { return false; @@ -107,9 +104,6 @@ export function isEmpty(obj: Dict): boolean { } export function shallowCopy(obj: Dict): Dict { - assert( - obj && typeof obj === 'object', - 'shallowCopy() expects object parameter.' - ); + assert(obj && typeof obj === 'object'); return { ...obj }; } diff --git a/packages/firestore/src/util/sorted_map.ts b/packages/firestore/src/util/sorted_map.ts index 23aa6ddb1c4..3e6cea1c7d7 100644 --- a/packages/firestore/src/util/sorted_map.ts +++ b/packages/firestore/src/util/sorted_map.ts @@ -227,10 +227,7 @@ export class SortedMapIterator { } getNext(): Entry { - assert( - this.nodeStack.length > 0, - 'getNext() called on iterator when hasNext() is false.' - ); + assert(this.nodeStack.length > 0); let node = this.nodeStack.pop()!; const result = { key: node.key, value: node.value }; @@ -511,14 +508,14 @@ export class LLRBNode { // leaves is equal on both sides. This function verifies that or asserts. protected check(): number { if (this.isRed() && this.left.isRed()) { - throw fail('Red node has red child(' + this.key + ',' + this.value + ')'); + throw fail(); } if (this.right.isRed()) { - throw fail('Right child of (' + this.key + ',' + this.value + ') is red'); + throw fail(); } const blackDepth = (this.left as LLRBNode).check(); if (blackDepth !== (this.right as LLRBNode).check()) { - throw fail('Black depths differ'); + throw fail(); } else { return blackDepth + (this.isRed() ? 0 : 1); } @@ -528,19 +525,19 @@ export class LLRBNode { // Represents an empty node (a leaf node in the Red-Black Tree). export class LLRBEmptyNode { get key(): never { - throw fail('LLRBEmptyNode has no key.'); + throw fail(); } get value(): never { - throw fail('LLRBEmptyNode has no value.'); + throw fail(); } get color(): never { - throw fail('LLRBEmptyNode has no color.'); + throw fail(); } get left(): never { - throw fail('LLRBEmptyNode has no left child.'); + throw fail(); } get right(): never { - throw fail('LLRBEmptyNode has no right child.'); + throw fail(); } size = 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 d9b3cbd3b92..44b0a8063c2 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 @@ -139,10 +139,7 @@ describe('IndexFreeQueryEngine', () => { query: Query, lastLimboFreeSnapshot: SnapshotVersion ): Promise { - assert( - localDocuments.expectIndexFreeExecution !== undefined, - 'Encountered runQuery() call not wrapped in expectIndexFreeQuery()/expectFullCollectionQuery()' - ); + assert(localDocuments.expectIndexFreeExecution !== undefined); return persistence.runTransaction('runQuery', 'readonly', txn => { return targetCache diff --git a/packages/firestore/test/unit/local/local_store.test.ts b/packages/firestore/test/unit/local/local_store.test.ts index 1432365b6e3..4790d36c76b 100644 --- a/packages/firestore/test/unit/local/local_store.test.ts +++ b/packages/firestore/test/unit/local/local_store.test.ts @@ -298,10 +298,7 @@ class LocalStoreTester { toReturnChanged(...docs: MaybeDocument[]): LocalStoreTester { this.promiseChain = this.promiseChain.then(() => { - assert( - this.lastChanges !== null, - 'Called toReturnChanged() without prior after()' - ); + assert(this.lastChanges !== null); expect(this.lastChanges.size).to.equal(docs.length, 'number of changes'); for (const doc of docs) { const returned = this.lastChanges.get(doc.key); @@ -320,10 +317,7 @@ class LocalStoreTester { toReturnRemoved(...keyStrings: string[]): LocalStoreTester { this.promiseChain = this.promiseChain.then(() => { - assert( - this.lastChanges !== null, - 'Called toReturnRemoved() without prior after()' - ); + assert(this.lastChanges !== null); expect(this.lastChanges.size).to.equal( keyStrings.length, 'Number of actual changes mismatched number of expected changes' diff --git a/packages/firestore/test/unit/local/simple_db.test.ts b/packages/firestore/test/unit/local/simple_db.test.ts index 5927c24c390..e5704d70370 100644 --- a/packages/firestore/test/unit/local/simple_db.test.ts +++ b/packages/firestore/test/unit/local/simple_db.test.ts @@ -345,7 +345,7 @@ describe('SimpleDb', () => { iterated.push(value); return PersistencePromise.reject(new Error('Expected error')); }) - .next(() => fail('Promise not rejected')) + .next(() => fail()) .catch(err => { expect(err.message).to.eq('Expected error'); expect(iterated).to.deep.equal([testData[0]]); diff --git a/packages/firestore/test/unit/specs/describe_spec.ts b/packages/firestore/test/unit/specs/describe_spec.ts index 9c1eeb1f4e6..dc94c458570 100644 --- a/packages/firestore/test/unit/specs/describe_spec.ts +++ b/packages/firestore/test/unit/specs/describe_spec.ts @@ -157,14 +157,11 @@ export function specTest( } else { builder = commentOrBuilder; } - assert(!!builder, 'Missing spec builder'); + assert(!!builder); // Union in the tags for the describeSpec(). tags = tags.concat(describeTags); for (const tag of tags) { - assert( - KNOWN_TAGS.indexOf(tag) >= 0, - 'Unknown tag "' + tag + '" on test: ' + name - ); + assert(KNOWN_TAGS.indexOf(tag) >= 0); } if (!writeJSONFile) { @@ -192,11 +189,7 @@ export function specTest( } } } else { - assert( - tags.indexOf(EXCLUSIVE_TAG) === -1, - `The 'exclusive' tag is only supported for development and should not be exported to ` + - `other platforms.` - ); + assert(tags.indexOf(EXCLUSIVE_TAG) === -1); const spec = builder(); const specJSON = spec.toJSON(); diff --git a/packages/firestore/test/unit/specs/spec_builder.ts b/packages/firestore/test/unit/specs/spec_builder.ts index 3dc053cd5f7..e1d83f6c1df 100644 --- a/packages/firestore/test/unit/specs/spec_builder.ts +++ b/packages/firestore/test/unit/specs/spec_builder.ts @@ -209,10 +209,7 @@ export class SpecBuilder { // Configures Garbage Collection behavior (on or off). Default is on. withGCEnabled(gcEnabled: boolean): this { - assert( - !this.currentStep, - 'withGCEnabled() must be called before all spec steps.' - ); + assert(!this.currentStep); this.config.useGarbageCollection = gcEnabled; return this; } @@ -483,7 +480,7 @@ export class SpecBuilder { } else if (doc instanceof NoDocument) { // Don't send any updates } else { - fail('Unknown parameter: ' + doc); + fail(); } this.watchCurrents(query, 'resume-token-' + version); this.watchSnapshots(version); @@ -755,8 +752,7 @@ export class SpecBuilder { } assert( !events.errorCode || - !(events.added || events.modified || events.removed || events.metadata), - "Can't provide both error and events" + !(events.added || events.modified || events.removed || events.metadata) ); currentStep.expectedSnapshotEvents.push({ query: SpecBuilder.queryToSpec(query), @@ -890,7 +886,7 @@ export class SpecBuilder { userDataWriter.convertValue(filter.value) ] as SpecQueryFilter; } else { - return fail('Unknown filter: ' + filter); + return fail(); } }); } @@ -997,13 +993,10 @@ export class SpecBuilder { if (queryTargetId && limboTargetId) { // TODO(dimond): add support for query for doc and limbo doc at the same // time? - fail('Found both query and limbo doc with target ID, not supported yet'); + fail(); } const targetId = queryTargetId || limboTargetId; - assert( - !isNullOrUndefined(targetId), - 'No target ID found for query/limbo doc in spec' - ); + assert(!isNullOrUndefined(targetId)); return targetId; } } diff --git a/packages/firestore/test/unit/specs/spec_test_runner.ts b/packages/firestore/test/unit/specs/spec_test_runner.ts index f4f398737c8..ab2f4a06060 100644 --- a/packages/firestore/test/unit/specs/spec_test_runner.ts +++ b/packages/firestore/test/unit/specs/spec_test_runner.ts @@ -250,24 +250,15 @@ class MockConnection implements Connection { sendFn: (request: WriteRequest) => { ++this.writeStreamRequestCount; if (firstCall) { - assert( - !!request.database, - 'projectId must be set in the first message' - ); - assert( - !request.writes, - 'mutations must not be set in first request' - ); + assert(!!request.database); + assert(!request.writes); this.ackWrite(); // just send the token firstCall = false; return; } - assert( - !!request.streamToken, - 'streamToken must be set on all writes' - ); - assert(!!request.writes, 'writes must be set on all writes'); + assert(!!request.streamToken); + assert(!!request.writes); const barrier = this.writeSendBarriers.shift(); if (!barrier) { @@ -296,7 +287,7 @@ class MockConnection implements Connection { // Replace 'any' with conditional types. return writeStream as any; // eslint-disable-line @typescript-eslint/no-explicit-any } else { - assert(rpcName === 'Listen', 'Unexpected rpc name: ' + rpcName); + assert(rpcName === 'Listen'); if (this.watchStream !== null) { throw new Error('Stream opened twice!'); } @@ -312,7 +303,7 @@ class MockConnection implements Connection { } else if (request.removeTarget) { delete this.activeTargets[request.removeTarget]; } else { - fail('Invalid listen request'); + fail(); } }, closeFn: () => { @@ -379,12 +370,12 @@ class SharedWriteTracker { } peek(): Mutation[] { - assert(this.writes.length > 0, 'No pending mutations'); + assert(this.writes.length > 0); return this.writes[0]; } shift(): Mutation[] { - assert(this.writes.length > 0, 'No pending mutations'); + assert(this.writes.length > 0); return this.writes.shift()!; } } @@ -619,7 +610,7 @@ abstract class TestRunner { } else if ('changeUser' in step) { return this.doChangeUser(step.changeUser!); } else { - return fail('Unknown step: ' + JSON.stringify(step)); + return fail(); } } @@ -666,7 +657,7 @@ abstract class TestRunner { const querySpec = listenSpec[1]; const query = parseQuery(querySpec); const eventEmitter = this.queryListeners.get(query); - assert(!!eventEmitter, 'There must be a query to unlisten too!'); + assert(!!eventEmitter); this.queryListeners.delete(query); await this.queue.enqueue(() => this.eventManager.unlisten(eventEmitter!)); } @@ -779,10 +770,7 @@ abstract class TestRunner { private doWatchEntity(watchEntity: SpecWatchEntity): Promise { if (watchEntity.docs) { - assert( - !watchEntity.doc, - 'Exactly one of `doc` or `docs` needs to be set' - ); + assert(!watchEntity.doc); return sequence(watchEntity.docs, (specDocument: SpecDocument) => { return this.doWatchEntity({ doc: specDocument, @@ -816,16 +804,13 @@ abstract class TestRunner { ); return this.doWatchEvent(change); } else { - return fail('Either doc or docs must be set'); + return fail(); } } private doWatchFilter(watchFilter: SpecWatchFilter): Promise { const targetIds: TargetId[] = watchFilter[0]; - assert( - targetIds.length === 1, - 'ExistenceFilters currently support exactly one target only.' - ); + assert(targetIds.length === 1); const keys = watchFilter.slice(1); const filter = new ExistenceFilter(keys.length); const change = new ExistenceFilterChange(targetIds[0], filter); @@ -1339,9 +1324,7 @@ export async function runSpec( try { await sequence(steps, async step => { assert( - step.clientIndex === undefined || tags.indexOf(MULTI_CLIENT_TAG) !== -1, - "Cannot use 'client()' to initialize a test that is not tagged with " + - "'multi-client'. Did you mean to use 'spec()'?" + step.clientIndex === undefined || tags.indexOf(MULTI_CLIENT_TAG) !== -1 ); ++count; diff --git a/packages/firestore/test/util/helpers.ts b/packages/firestore/test/util/helpers.ts index b1492cb2e98..b40a1a4fd66 100644 --- a/packages/firestore/test/util/helpers.ts +++ b/packages/firestore/test/util/helpers.ts @@ -225,7 +225,7 @@ export function filter(path: string, op: string, value: unknown): FieldFilter { if (filter instanceof FieldFilter) { return filter; } else { - return fail('Unrecognized filter: ' + JSON.stringify(filter)); + return fail(); } } @@ -335,7 +335,7 @@ export function docAddedRemoteEvent( activeTargets?: TargetId[] ): RemoteEvent { const docs = Array.isArray(docOrDocs) ? docOrDocs : [docOrDocs]; - assert(docs.length !== 0, 'Cannot pass empty docs array'); + assert(docs.length !== 0); const allTargets = activeTargets ? activeTargets @@ -360,10 +360,7 @@ export function docAddedRemoteEvent( let version = SnapshotVersion.MIN; for (const doc of docs) { - assert( - !(doc instanceof Document) || !doc.hasLocalMutations, - "Docs from remote updates shouldn't have local changes." - ); + assert(!(doc instanceof Document) || !doc.hasLocalMutations); const docChange = new DocumentWatchChange( updatedInTargets || [], removedFromTargets || [], @@ -383,10 +380,7 @@ export function docUpdateRemoteEvent( removedFromTargets?: TargetId[], limboTargets?: TargetId[] ): RemoteEvent { - assert( - !(doc instanceof Document) || !doc.hasLocalMutations, - "Docs from remote updates shouldn't have local changes." - ); + assert(!(doc instanceof Document) || !doc.hasLocalMutations); const docChange = new DocumentWatchChange( updatedInTargets || [], removedFromTargets || [], @@ -525,7 +519,7 @@ export function resumeTokenForSnapshot( export function orderBy(path: string, op?: string): OrderBy { op = op || 'asc'; - assert(op === 'asc' || op === 'desc', 'Unknown direction: ' + op); + assert(op === 'asc' || op === 'desc'); const dir: Direction = op === 'asc' ? Direction.ASCENDING : Direction.DESCENDING; return new OrderBy(field(path), dir); @@ -601,7 +595,7 @@ export function documentSet(...args: unknown[]): DocumentSet { docSet = new DocumentSet(); } for (const doc of args) { - assert(doc instanceof Document, 'Bad argument, expected Document: ' + doc); + assert(doc instanceof Document); docSet = docSet.add(doc); } return docSet; @@ -642,14 +636,10 @@ export class DocComparator { export function expectEqual(left: any, right: any, message?: string): void { message = message || ''; if (typeof left.isEqual !== 'function') { - return fail( - JSON.stringify(left) + ' does not support isEqual (left) ' + message - ); + return fail(); } if (typeof right.isEqual !== 'function') { - return fail( - JSON.stringify(right) + ' does not support isEqual (right) ' + message - ); + return fail(); } expect(left.isEqual(right)).to.equal(true, message); expect(right.isEqual(left)).to.equal(true, message); diff --git a/packages/firestore/test/util/test_platform.ts b/packages/firestore/test/util/test_platform.ts index b3eaa034e0c..601efc25aae 100644 --- a/packages/firestore/test/util/test_platform.ts +++ b/packages/firestore/test/util/test_platform.ts @@ -65,7 +65,7 @@ export class FakeWindow { // The spec tests currently do not rely on 'unload' listeners. break; default: - fail(`MockWindow doesn't support events of type '${type}'`); + fail(); } } @@ -76,10 +76,7 @@ export class FakeWindow { registeredListener => listener !== registeredListener ); const newCount = this.storageListeners.length; - assert( - newCount === oldCount - 1, - "Listener passed to 'removeEventListener' doesn't match any registered listener." - ); + assert(newCount === oldCount - 1); } } } @@ -96,10 +93,7 @@ export class FakeDocument { } addEventListener(type: string, listener: EventListener): void { - assert( - type === 'visibilitychange', - "FakeDocument only supports events of type 'visibilitychange'" - ); + assert(type === 'visibilitychange'); this.visibilityListener = listener; }