Skip to content

Commit 3668407

Browse files
Improved error messages for custom types (#162)
1 parent 9cc94f4 commit 3668407

File tree

5 files changed

+39
-24
lines changed

5 files changed

+39
-24
lines changed

src/document.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1399,7 +1399,9 @@ function validateFieldValue(val, options, depth) {
13991399
} else if (is.instanceof(val, GeoPoint)) {
14001400
return true;
14011401
} else if (is.instanceof(val, FieldPath)) {
1402-
throw new Error('Cannot use "FieldPath" as a Firestore type.');
1402+
throw new Error(
1403+
'Cannot use object of type "FieldPath" as a Firestore value.'
1404+
);
14031405
} else if (is.object(val)) {
14041406
throw validate.customObjectError(val);
14051407
}

src/validate.js

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -141,21 +141,29 @@ module.exports = validators => {
141141
};
142142

143143
exports.customObjectError = val => {
144-
let typeName = is.object(val) ? val.constructor.name : typeof val;
145-
146-
switch (typeName) {
147-
case 'DocumentReference':
148-
case 'FieldPath':
149-
case 'FieldValue':
150-
case 'GeoPoint':
151-
return new Error(
152-
`Detected an object of type "${typeName}" that doesn't match the expected instance. Please ensure that ` +
153-
'the Firestore types you are using are from the same NPM package.'
154-
);
155-
default:
156-
return new Error(
157-
`Cannot use custom type "${typeName}" as a Firestore type.`
158-
);
144+
if (is.object(val) && val.constructor.name !== 'Object') {
145+
const typeName = val.constructor.name;
146+
switch (typeName) {
147+
case 'DocumentReference':
148+
case 'FieldPath':
149+
case 'FieldValue':
150+
case 'GeoPoint':
151+
return new Error(
152+
`Detected an object of type "${typeName}" that doesn't match the ` +
153+
'expected instance. Please ensure that the Firestore types you ' +
154+
'are using are from the same NPM package.'
155+
);
156+
default:
157+
return new Error(
158+
`Couldn't serialize object of type "${typeName}". Firestore ` +
159+
"doesn't support JavaScript objects with custom prototypes " +
160+
"(i.e. objects that were created via the 'new' operator)."
161+
);
162+
}
163+
} else {
164+
return new Error(
165+
`Invalid use of type "${typeof val}" as a Firestore argument.`
166+
);
159167
}
160168
};
161169

test/document.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -290,13 +290,18 @@ describe('serialize document', function() {
290290
it("doesn't serialize unsupported types", function() {
291291
assert.throws(() => {
292292
firestore.doc('collectionId/documentId').set({foo: undefined});
293-
}, /Cannot use custom type "undefined" as a Firestore type./);
293+
}, /Invalid use of type "undefined" as a Firestore argument./);
294294

295295
assert.throws(() => {
296296
firestore
297297
.doc('collectionId/documentId')
298298
.set({foo: Firestore.FieldPath.documentId()});
299-
}, /Cannot use "FieldPath" as a Firestore type./);
299+
}, /Cannot use object of type "FieldPath" as a Firestore value./);
300+
301+
assert.throws(() => {
302+
class Foo {}
303+
firestore.doc('collectionId/documentId').set({foo: new Foo()});
304+
}, /Argument "data" is not a valid Document. Couldn't serialize object of type "Foo". Firestore doesn't support JavaScript objects with custom prototypes \(i.e. objects that were created via the 'new' operator\)./);
300305
});
301306

302307
it('serializes date before 1970', function() {
@@ -780,7 +785,7 @@ describe('get document', function() {
780785
.then(doc => {
781786
assert.throws(() => {
782787
doc.get();
783-
}, /Argument "field" is not a valid FieldPath. Cannot use custom type "undefined" as a Firestore type./);
788+
}, /Argument "field" is not a valid FieldPath. Invalid use of type "undefined" as a Firestore argument./);
784789
});
785790
});
786791
});

test/order.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ describe('Order', function() {
8585
it('throws on invalid value', function() {
8686
assert.throws(() => {
8787
order.compare({}, {});
88-
}, /Cannot use custom type "Object" as a Firestore type/);
88+
}, /Invalid use of type "object" as a Firestore argument./);
8989
});
9090

9191
it('throws on invalid blob', function() {

test/query.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ describe('where() interface', function() {
709709
let query = firestore.collection('collectionId');
710710
query = query.where({}, '=', 'bar');
711711
return query.get();
712-
}, /Argument "fieldPath" is not a valid FieldPath. Cannot use custom type "Object" as a Firestore type./);
712+
}, /Argument "fieldPath" is not a valid FieldPath. Invalid use of type "object" as a Firestore argument/);
713713

714714
class FieldPath {}
715715
assert.throws(() => {
@@ -724,7 +724,7 @@ describe('where() interface', function() {
724724
let query = firestore.collection('collectionId');
725725
query = query.where('foo', '=', new Firestore.FieldPath('bar'));
726726
return query.get();
727-
}, /Argument "value" is not a valid FieldValue. Cannot use "FieldPath" as a Firestore type./);
727+
}, /Argument "value" is not a valid FieldValue. Cannot use object of type "FieldPath" as a Firestore value./);
728728
});
729729

730730
it('rejects field transforms as value', function() {
@@ -752,7 +752,7 @@ describe('where() interface', function() {
752752

753753
assert.throws(() => {
754754
query.where('foo', '=', new Foo()).get();
755-
}, /Argument "value" is not a valid FieldValue. Cannot use custom type "Foo" as a Firestore type./);
755+
}, /Argument "value" is not a valid FieldValue. Couldn't serialize object of type "Foo". Firestore doesn't support JavaScript objects with custom prototypes \(i.e. objects that were created via the 'new' operator\)./);
756756

757757
assert.throws(() => {
758758
query.where('foo', '=', new FieldPath()).get();
@@ -1039,7 +1039,7 @@ describe('select() interface', function() {
10391039
let query = firestore.collection('collectionId');
10401040
assert.throws(function() {
10411041
query.select(1);
1042-
}, /Argument at index 0 is not a valid FieldPath. Cannot use custom type "number" as a Firestore type./);
1042+
}, /Argument at index 0 is not a valid FieldPath. Invalid use of type "number" as a Firestore argument./);
10431043

10441044
assert.throws(function() {
10451045
query.select('.');

0 commit comments

Comments
 (0)