-
Type: Bug
-
Resolution: Fixed
-
Priority: Major - P3
-
Affects Version/s: 3.4.0
-
Component/s: None
-
Empty show more show less
BSON objects do not handle number objects well. In the case of the Double BSON objects, the result will be a NaN. In the case of an Int32 BSON object, the result will always be zero. Take the following code:
const MongoClient = require('mongodb').MongoClient; const bson = require('bson'); const assert = require('assert'); const url = 'mongodb://localhost:27017/bsonObjectFail?useUnifiedTopology=true'; const client = new MongoClient(url); (async function () { console.log('Start!'); await client.connect(); try { await client.db().dropDatabase(); // Drop DB for a clean slate. const db = client.db(); const coll = db.collection('test'); await coll.insertOne(\{a: new bson.Double(3.14)}); // This results in 3.14 await coll.insertOne(\{a: new bson.Double(new Number(3.14))});// This results in NaN // Verify sanity const countPromises = [ coll.countDocuments(\{ a: { $type: 'double' } }), coll.countDocuments(\{ a: 3.14 }), coll.countDocuments(\{ a: NaN }), ]; const [doubleCount, threeCount, nanCount] = await Promise.all(countPromises); console.log('Double count:', doubleCount); console.log('\{ a: 3.14 } count:', threeCount); console.log('\{ a: NaN } count:', nanCount); console.log('Done!'); } catch(err) { console.error(`Unexpected Error: ${err.stack}`); } finally { await client.close(); } })();
In an ideal world where BSON handles the Number object the output would look like this:
Double count: 2 { a: 3.14 } count: 2 { a: NaN } count: 0
However since it does not you get this instead:
Double count: 2 { a: 3.14 } count: 1 { a: NaN } count: 1
This can lead to very confusing errors along with data corruption if a user doesn't explicitly know that they need to pass the primitive number value to BSON. Suggest either adding an assert to the value or using something like `Number(value)` in the constructor to ensure that the number is converted to a primitive.