Skip to content

Commit 375f368

Browse files
authoredMar 9, 2021
fix: Throw error on bigint usage and add helpers to Long (#426)
Adds helpers toBigInt and fromBigInt to the Long class to help support 64bit values. Throws an error when bigint is attempted to be serialized. NODE-2378
1 parent 290dd6a commit 375f368

File tree

3 files changed

+79
-0
lines changed

3 files changed

+79
-0
lines changed
 

‎lib/bson/long.js

+14
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ Long.prototype.toNumber = function() {
7777
return this.high_ * Long.TWO_PWR_32_DBL_ + this.getLowBitsUnsigned();
7878
};
7979

80+
/** Converts the Long to a BigInt (arbitrary precision). */
81+
Long.prototype.toBigInt = function () {
82+
return BigInt(this.toString());
83+
}
84+
8085
/**
8186
* Return the JSON value.
8287
*
@@ -711,6 +716,15 @@ Long.fromNumber = function(value) {
711716
}
712717
};
713718

719+
/**
720+
* Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned.
721+
* @param {bigint} value - The number in question
722+
* @returns {Long} The corresponding Long value
723+
*/
724+
Long.fromBigInt = function(value) {
725+
return Long.fromString(value.toString(10), 10);
726+
}
727+
714728
/**
715729
* Returns a Long representing the 64-bit integer that comes by concatenating the given high and low bits. Each is assumed to use 32 bits.
716730
*

‎lib/bson/parser/serializer.js

+6
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,8 @@ var serializeInto = function serializeInto(
709709
index = serializeString(buffer, key, value, index, true);
710710
} else if (type === 'number') {
711711
index = serializeNumber(buffer, key, value, index, true);
712+
} else if(type === 'bigint') {
713+
throw new TypeError('Unsupported type BigInt, please use Decimal128');
712714
} else if (type === 'boolean') {
713715
index = serializeBoolean(buffer, key, value, index, true);
714716
} else if (value instanceof Date || isDate(value)) {
@@ -820,6 +822,8 @@ var serializeInto = function serializeInto(
820822
index = serializeString(buffer, key, value, index);
821823
} else if (type === 'number') {
822824
index = serializeNumber(buffer, key, value, index);
825+
} else if(type === 'bigint') {
826+
throw new TypeError('Unsupported type BigInt, please use Decimal128');
823827
} else if (type === 'boolean') {
824828
index = serializeBoolean(buffer, key, value, index);
825829
} else if (value instanceof Date || isDate(value)) {
@@ -923,6 +927,8 @@ var serializeInto = function serializeInto(
923927
index = serializeString(buffer, key, value, index);
924928
} else if (type === 'number') {
925929
index = serializeNumber(buffer, key, value, index);
930+
} else if(type === 'bigint') {
931+
throw new TypeError('Unsupported type BigInt, please use Decimal128');
926932
} else if (type === 'boolean') {
927933
index = serializeBoolean(buffer, key, value, index);
928934
} else if (value instanceof Date || isDate(value)) {

‎test/node/bigint_test.js

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/* globals BigInt */
2+
'use strict';
3+
4+
var createBSON = require('../utils');
5+
var BSON = require('../..');
6+
var bson = createBSON();
7+
8+
try {
9+
BigInt(0);
10+
11+
// will throw on the line above if BigInt is not supported in the runtime
12+
13+
exports['Should error on serialize bigint'] = function (test) {
14+
var testDoc = { b: BigInt(32) };
15+
try {
16+
bson.serialize(testDoc)
17+
test.ok(false);
18+
} catch (error) {
19+
test.ok(error instanceof TypeError);
20+
test.ok(error.message === 'Unsupported type BigInt, please use Decimal128');
21+
}
22+
test.done();
23+
};
24+
25+
exports['Should error on serialize bigint inside array'] = function (test) {
26+
var testDoc = { b: [0, 1, BigInt(0x1ffffffff)] };
27+
try {
28+
bson.serialize(testDoc)
29+
test.ok(false);
30+
} catch (error) {
31+
test.ok(error instanceof TypeError);
32+
test.ok(error.message === 'Unsupported type BigInt, please use Decimal128');
33+
}
34+
test.done();
35+
};
36+
37+
exports['Should error on serialize bigint inside subdocument'] = function (test) {
38+
var testDoc = { b: { a: BigInt(0x1ffffffff) } };
39+
try {
40+
bson.serialize(testDoc)
41+
test.ok(false);
42+
} catch (error) {
43+
test.ok(error instanceof TypeError);
44+
test.ok(error.message === 'Unsupported type BigInt, please use Decimal128');
45+
}
46+
test.done();
47+
};
48+
49+
exports['Should support conversion on Long type'] = function (test) {
50+
var long = BSON.Long.fromBigInt(BigInt(200));
51+
test.ok(long._bsontype === 'Long');
52+
test.ok(long.toNumber() === 200);
53+
test.ok(long.toBigInt() === BigInt(200));
54+
test.done();
55+
}
56+
57+
} catch (_) {
58+
// 'JS VM does not support BigInt'
59+
}

0 commit comments

Comments
 (0)
Please sign in to comment.