diff --git a/lib/bson/long.js b/lib/bson/long.js index 78215aa3..551d1a60 100644 --- a/lib/bson/long.js +++ b/lib/bson/long.js @@ -77,6 +77,11 @@ Long.prototype.toNumber = function() { return this.high_ * Long.TWO_PWR_32_DBL_ + this.getLowBitsUnsigned(); }; +/** Converts the Long to a BigInt (arbitrary precision). */ +Long.prototype.toBigInt = function () { + return BigInt(this.toString()); +} + /** * Return the JSON value. * @@ -711,6 +716,15 @@ Long.fromNumber = function(value) { } }; +/** + * Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned. + * @param {bigint} value - The number in question + * @returns {Long} The corresponding Long value + */ +Long.fromBigInt = function(value) { + return Long.fromString(value.toString(10), 10); +} + /** * 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. * diff --git a/lib/bson/parser/serializer.js b/lib/bson/parser/serializer.js index 6bb212ed..fab9b6f3 100644 --- a/lib/bson/parser/serializer.js +++ b/lib/bson/parser/serializer.js @@ -709,6 +709,8 @@ var serializeInto = function serializeInto( index = serializeString(buffer, key, value, index, true); } else if (type === 'number') { index = serializeNumber(buffer, key, value, index, true); + } else if(type === 'bigint') { + throw new TypeError('Unsupported type BigInt, please use Decimal128'); } else if (type === 'boolean') { index = serializeBoolean(buffer, key, value, index, true); } else if (value instanceof Date || isDate(value)) { @@ -820,6 +822,8 @@ var serializeInto = function serializeInto( index = serializeString(buffer, key, value, index); } else if (type === 'number') { index = serializeNumber(buffer, key, value, index); + } else if(type === 'bigint') { + throw new TypeError('Unsupported type BigInt, please use Decimal128'); } else if (type === 'boolean') { index = serializeBoolean(buffer, key, value, index); } else if (value instanceof Date || isDate(value)) { @@ -923,6 +927,8 @@ var serializeInto = function serializeInto( index = serializeString(buffer, key, value, index); } else if (type === 'number') { index = serializeNumber(buffer, key, value, index); + } else if(type === 'bigint') { + throw new TypeError('Unsupported type BigInt, please use Decimal128'); } else if (type === 'boolean') { index = serializeBoolean(buffer, key, value, index); } else if (value instanceof Date || isDate(value)) { diff --git a/test/node/bigint_test.js b/test/node/bigint_test.js new file mode 100644 index 00000000..701e064a --- /dev/null +++ b/test/node/bigint_test.js @@ -0,0 +1,59 @@ +/* globals BigInt */ +'use strict'; + +var createBSON = require('../utils'); +var BSON = require('../..'); +var bson = createBSON(); + +try { + BigInt(0); + + // will throw on the line above if BigInt is not supported in the runtime + + exports['Should error on serialize bigint'] = function (test) { + var testDoc = { b: BigInt(32) }; + try { + bson.serialize(testDoc) + test.ok(false); + } catch (error) { + test.ok(error instanceof TypeError); + test.ok(error.message === 'Unsupported type BigInt, please use Decimal128'); + } + test.done(); + }; + + exports['Should error on serialize bigint inside array'] = function (test) { + var testDoc = { b: [0, 1, BigInt(0x1ffffffff)] }; + try { + bson.serialize(testDoc) + test.ok(false); + } catch (error) { + test.ok(error instanceof TypeError); + test.ok(error.message === 'Unsupported type BigInt, please use Decimal128'); + } + test.done(); + }; + + exports['Should error on serialize bigint inside subdocument'] = function (test) { + var testDoc = { b: { a: BigInt(0x1ffffffff) } }; + try { + bson.serialize(testDoc) + test.ok(false); + } catch (error) { + test.ok(error instanceof TypeError); + test.ok(error.message === 'Unsupported type BigInt, please use Decimal128'); + } + test.done(); + }; + + exports['Should support conversion on Long type'] = function (test) { + var long = BSON.Long.fromBigInt(BigInt(200)); + test.ok(long._bsontype === 'Long'); + test.ok(long.toNumber() === 200); + test.ok(long.toBigInt() === BigInt(200)); + test.done(); + } + +} catch (_) { + // 'JS VM does not support BigInt' +}