Skip to content

Commit 29b40d4

Browse files
Remove invalidClassError
1 parent ff78c48 commit 29b40d4

File tree

7 files changed

+58
-103
lines changed

7 files changed

+58
-103
lines changed

packages/firestore/exp/src/api/reference.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import {
2424
parseUpdateVarargs
2525
} from '../../../src/api/user_data_reader';
2626
import { debugAssert } from '../../../src/util/assert';
27-
import { cast } from '../../../lite/src/api/util';
27+
import { cast } from '../../../src/util/input_validation';
2828
import { DocumentSnapshot, QuerySnapshot } from './snapshot';
2929
import {
3030
applyFirestoreDataConverter,

packages/firestore/lite/src/api/util.ts

-46
This file was deleted.

packages/firestore/src/api/blob.ts

-4
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
import { isBase64Available } from '../platform/base64';
1919
import { Code, FirestoreError } from '../util/error';
20-
import { invalidClassError } from '../util/input_validation';
2120
import { ByteString } from '../util/byte_string';
2221
import { Bytes } from '../../lite/src/api/bytes';
2322

@@ -66,9 +65,6 @@ export class Blob extends Bytes {
6665

6766
static fromUint8Array(array: Uint8Array): Blob {
6867
assertUint8ArrayAvailable();
69-
if (!(array instanceof Uint8Array)) {
70-
throw invalidClassError('Blob.fromUint8Array', 'Uint8Array', 1, array);
71-
}
7268
return new Blob(ByteString.fromUint8Array(array));
7369
}
7470

packages/firestore/src/api/database.ts

+14-14
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import {
6262
findFilterOperator,
6363
getFirstOrderByField,
6464
getInequalityFilterField,
65+
hasLimitToLast,
6566
isCollectionGroupQuery,
6667
LimitType,
6768
newQueryComparator,
@@ -76,8 +77,7 @@ import {
7677
queryWithAddedOrderBy,
7778
queryWithEndAt,
7879
queryWithLimit,
79-
queryWithStartAt,
80-
hasLimitToLast
80+
queryWithStartAt
8181
} from '../core/query';
8282
import { Transaction as InternalTransaction } from '../core/transaction';
8383
import { ChangeType, ViewSnapshot } from '../core/view_snapshot';
@@ -92,11 +92,11 @@ import { debugAssert, fail } from '../util/assert';
9292
import { AsyncQueue } from '../util/async_queue';
9393
import { Code, FirestoreError } from '../util/error';
9494
import {
95-
invalidClassError,
96-
validatePositiveNumber,
97-
valueDescription,
95+
cast,
9896
validateIsNotUsedTogether,
99-
validateNonEmptyString
97+
validateNonEmptyString,
98+
validatePositiveNumber,
99+
valueDescription
100100
} from '../util/input_validation';
101101
import { getLogLevel, logError, LogLevel, setLogLevel } from '../util/log';
102102
import { AutoId } from '../util/misc';
@@ -1022,7 +1022,7 @@ export class DocumentReference<T = DocumentData>
10221022

10231023
isEqual(other: PublicDocumentReference<T>): boolean {
10241024
if (!(other instanceof DocumentReference)) {
1025-
throw invalidClassError('isEqual', 'DocumentReference', 1, other);
1025+
return false;
10261026
}
10271027
return (
10281028
this.firestore === other.firestore &&
@@ -1346,7 +1346,7 @@ export class DocumentSnapshot<T = DocumentData>
13461346

13471347
isEqual(other: PublicDocumentSnapshot<T>): boolean {
13481348
if (!(other instanceof DocumentSnapshot)) {
1349-
throw invalidClassError('isEqual', 'DocumentSnapshot', 1, other);
1349+
return false;
13501350
}
13511351
return (
13521352
this._firestore === other._firestore &&
@@ -1924,7 +1924,7 @@ export class Query<T = DocumentData> implements PublicQuery<T> {
19241924

19251925
isEqual(other: PublicQuery<T>): boolean {
19261926
if (!(other instanceof Query)) {
1927-
throw invalidClassError('isEqual', 'Query', 1, other);
1927+
return false;
19281928
}
19291929
return (
19301930
this.firestore === other.firestore &&
@@ -2126,7 +2126,7 @@ export class QuerySnapshot<T = DocumentData> implements PublicQuerySnapshot<T> {
21262126
/** Check the equality. The call can be very expensive. */
21272127
isEqual(other: PublicQuerySnapshot<T>): boolean {
21282128
if (!(other instanceof QuerySnapshot)) {
2129-
throw invalidClassError('isEqual', 'QuerySnapshot', 1, other);
2129+
return false;
21302130
}
21312131

21322132
return (
@@ -2199,6 +2199,7 @@ export class CollectionReference<T = DocumentData>
21992199
if (arguments.length === 0) {
22002200
pathString = AutoId.newId();
22012201
}
2202+
validateNonEmptyString('CollectionReference.doc', 'path', pathString);
22022203
const path = ResourcePath.fromString(pathString!);
22032204
return DocumentReference.forPath<T>(
22042205
this._query.path.child(path),
@@ -2264,15 +2265,14 @@ function validateReference<T>(
22642265
documentRef: PublicDocumentReference<T>,
22652266
firestore: Firestore
22662267
): _DocumentKeyReference<T> {
2267-
if (!(documentRef instanceof _DocumentKeyReference)) {
2268-
throw invalidClassError(methodName, 'DocumentReference', 1, documentRef);
2269-
} else if (documentRef.firestore !== firestore) {
2268+
const reference = cast<DocumentReference<T>>(documentRef, DocumentReference);
2269+
if (reference.firestore !== firestore) {
22702270
throw new FirestoreError(
22712271
Code.INVALID_ARGUMENT,
22722272
'Provided document reference is from a different Firestore instance.'
22732273
);
22742274
} else {
2275-
return documentRef;
2275+
return reference;
22762276
}
22772277
}
22782278

packages/firestore/src/api/field_path.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import { FieldPath as PublicFieldPath } from '@firebase/firestore-types';
1919

2020
import { FieldPath as InternalFieldPath } from '../model/path';
2121
import { Code, FirestoreError } from '../util/error';
22-
import { invalidClassError } from '../util/input_validation';
2322

2423
// The objects that are a part of this API are exposed to third-parties as
2524
// compiled javascript so we want to flag our private members with a leading
@@ -78,7 +77,7 @@ export class FieldPath extends _BaseFieldPath implements PublicFieldPath {
7877

7978
isEqual(other: PublicFieldPath): boolean {
8079
if (!(other instanceof FieldPath)) {
81-
throw invalidClassError('isEqual', 'FieldPath', 1, other);
80+
return false;
8281
}
8382
return this._internalPath.isEqual(other._internalPath);
8483
}

packages/firestore/src/util/input_validation.ts

+25-15
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
*/
1717
import { fail } from './assert';
1818
import { Code, FirestoreError } from './error';
19-
import { Dict, forEach } from './obj';
2019
import { DocumentKey } from '../model/document_key';
2120
import { ResourcePath } from '../model/path';
2221

@@ -143,21 +142,32 @@ export function tryGetCustomObjectType(input: object): string | null {
143142
}
144143

145144
/**
146-
* Helper method to throw an error that the provided argument did not pass
147-
* an instanceof check.
145+
* Casts `obj` to `T`. Throws if `obj` is not an instance of `T`.
146+
*
147+
* This cast is used in the Lite and Full SDK to verify instance types for
148+
* arguments passed to the public API.
148149
*/
149-
export function invalidClassError(
150-
functionName: string,
151-
type: string,
152-
position: number,
153-
argument: unknown
154-
): Error {
155-
const description = valueDescription(argument);
156-
return new FirestoreError(
157-
Code.INVALID_ARGUMENT,
158-
`Function ${functionName}() requires its ${ordinal(position)} ` +
159-
`argument to be a ${type}, but it was: ${description}`
160-
);
150+
export function cast<T>(
151+
obj: object,
152+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
153+
constructor: { new (...args: any[]): T }
154+
): T | never {
155+
if (!(obj instanceof constructor)) {
156+
if (constructor.name === obj.constructor.name) {
157+
throw new FirestoreError(
158+
Code.INVALID_ARGUMENT,
159+
'Type does not match the expected instance. Did you pass a ' +
160+
`reference from a different Firestore SDK?`
161+
);
162+
} else {
163+
const description = valueDescription(obj);
164+
throw new FirestoreError(
165+
Code.INVALID_ARGUMENT,
166+
`Expected type '${constructor.name}', but it was: ${description}`
167+
);
168+
}
169+
}
170+
return obj as T;
161171
}
162172

163173
export function validatePositiveNumber(

packages/firestore/test/integration/api/validation.test.ts

+17-21
Original file line numberDiff line numberDiff line change
@@ -1367,28 +1367,24 @@ apiDescribe('Validation:', (persistence: boolean) => {
13671367
}
13681368
);
13691369

1370-
validationIt.only(
1371-
persistence,
1372-
'cannot pass undefined as a field value',
1373-
db => {
1374-
const collection = db.collection('test');
1375-
if (usesFunctionalApi()) {
1376-
expect(() => collection.where('foo', '==', undefined)).to.throw(
1377-
'Function where() called with invalid data. Unsupported field value: undefined'
1378-
);
1379-
expect(() => collection.orderBy('foo').startAt(undefined)).to.throw(
1380-
'Function startAt() called with invalid data. Unsupported field value: undefined'
1381-
);
1382-
} else {
1383-
expect(() => collection.where('foo', '==', undefined)).to.throw(
1384-
'Function Query.where() called with invalid data. Unsupported field value: undefined'
1385-
);
1386-
expect(() => collection.orderBy('foo').startAt(undefined)).to.throw(
1387-
'Function Query.startAt() called with invalid data. Unsupported field value: undefined'
1388-
);
1389-
}
1370+
validationIt(persistence, 'cannot pass undefined as a field value', db => {
1371+
const collection = db.collection('test');
1372+
if (usesFunctionalApi()) {
1373+
expect(() => collection.where('foo', '==', undefined)).to.throw(
1374+
'Function where() called with invalid data. Unsupported field value: undefined'
1375+
);
1376+
expect(() => collection.orderBy('foo').startAt(undefined)).to.throw(
1377+
'Function startAt() called with invalid data. Unsupported field value: undefined'
1378+
);
1379+
} else {
1380+
expect(() => collection.where('foo', '==', undefined)).to.throw(
1381+
'Function Query.where() called with invalid data. Unsupported field value: undefined'
1382+
);
1383+
expect(() => collection.orderBy('foo').startAt(undefined)).to.throw(
1384+
'Function Query.startAt() called with invalid data. Unsupported field value: undefined'
1385+
);
13901386
}
1391-
);
1387+
});
13921388
});
13931389
});
13941390

0 commit comments

Comments
 (0)