bson 4.5.1 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/HISTORY.md +572 -0
  2. package/bower.json +1 -1
  3. package/bson.d.ts +70 -13
  4. package/dist/bson.browser.esm.js +314 -177
  5. package/dist/bson.browser.esm.js.map +1 -1
  6. package/dist/bson.browser.umd.js +317 -176
  7. package/dist/bson.browser.umd.js.map +1 -1
  8. package/dist/bson.bundle.js +317 -176
  9. package/dist/bson.bundle.js.map +1 -1
  10. package/dist/bson.esm.js +314 -177
  11. package/dist/bson.esm.js.map +1 -1
  12. package/lib/binary.js +11 -9
  13. package/lib/binary.js.map +1 -1
  14. package/lib/bson.js +11 -3
  15. package/lib/bson.js.map +1 -1
  16. package/lib/code.js +0 -1
  17. package/lib/code.js.map +1 -1
  18. package/lib/constants.js +5 -1
  19. package/lib/constants.js.map +1 -1
  20. package/lib/db_ref.js +0 -1
  21. package/lib/db_ref.js.map +1 -1
  22. package/lib/decimal128.js +6 -5
  23. package/lib/decimal128.js.map +1 -1
  24. package/lib/double.js +3 -1
  25. package/lib/double.js.map +1 -1
  26. package/lib/ensure_buffer.js +3 -2
  27. package/lib/ensure_buffer.js.map +1 -1
  28. package/lib/error.js +55 -0
  29. package/lib/error.js.map +1 -0
  30. package/lib/extended_json.js +11 -5
  31. package/lib/extended_json.js.map +1 -1
  32. package/lib/int_32.js +4 -2
  33. package/lib/int_32.js.map +1 -1
  34. package/lib/objectid.js +39 -35
  35. package/lib/objectid.js.map +1 -1
  36. package/lib/parser/deserializer.js +131 -53
  37. package/lib/parser/deserializer.js.map +1 -1
  38. package/lib/parser/serializer.js +13 -12
  39. package/lib/parser/serializer.js.map +1 -1
  40. package/lib/regexp.js +9 -2
  41. package/lib/regexp.js.map +1 -1
  42. package/lib/symbol.js +0 -2
  43. package/lib/symbol.js.map +1 -1
  44. package/lib/uuid.js +4 -4
  45. package/lib/uuid.js.map +1 -1
  46. package/lib/uuid_utils.js +2 -1
  47. package/lib/uuid_utils.js.map +1 -1
  48. package/package.json +16 -3
  49. package/src/binary.ts +12 -10
  50. package/src/bson.ts +7 -1
  51. package/src/code.ts +0 -1
  52. package/src/constants.ts +6 -0
  53. package/src/db_ref.ts +0 -1
  54. package/src/decimal128.ts +6 -5
  55. package/src/double.ts +4 -1
  56. package/src/ensure_buffer.ts +3 -2
  57. package/src/error.ts +23 -0
  58. package/src/extended_json.ts +13 -5
  59. package/src/int_32.ts +5 -2
  60. package/src/objectid.ts +40 -43
  61. package/src/parser/deserializer.ts +159 -57
  62. package/src/parser/serializer.ts +13 -12
  63. package/src/regexp.ts +14 -2
  64. package/src/symbol.ts +0 -2
  65. package/src/uuid.ts +4 -4
  66. package/src/uuid_utils.ts +2 -1
@@ -2037,6 +2037,97 @@
2037
2037
  buffer$1.INSPECT_MAX_BYTES;
2038
2038
  buffer$1.kMaxLength;
2039
2039
 
2040
+ /*! *****************************************************************************
2041
+ Copyright (c) Microsoft Corporation.
2042
+
2043
+ Permission to use, copy, modify, and/or distribute this software for any
2044
+ purpose with or without fee is hereby granted.
2045
+
2046
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
2047
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
2048
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
2049
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
2050
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
2051
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2052
+ PERFORMANCE OF THIS SOFTWARE.
2053
+ ***************************************************************************** */
2054
+
2055
+ /* global Reflect, Promise */
2056
+ var _extendStatics = function extendStatics(d, b) {
2057
+ _extendStatics = Object.setPrototypeOf || {
2058
+ __proto__: []
2059
+ } instanceof Array && function (d, b) {
2060
+ d.__proto__ = b;
2061
+ } || function (d, b) {
2062
+ for (var p in b) {
2063
+ if (b.hasOwnProperty(p)) d[p] = b[p];
2064
+ }
2065
+ };
2066
+
2067
+ return _extendStatics(d, b);
2068
+ };
2069
+
2070
+ function __extends(d, b) {
2071
+ _extendStatics(d, b);
2072
+
2073
+ function __() {
2074
+ this.constructor = d;
2075
+ }
2076
+
2077
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
2078
+ }
2079
+
2080
+ var _assign = function __assign() {
2081
+ _assign = Object.assign || function __assign(t) {
2082
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
2083
+ s = arguments[i];
2084
+
2085
+ for (var p in s) {
2086
+ if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
2087
+ }
2088
+ }
2089
+
2090
+ return t;
2091
+ };
2092
+
2093
+ return _assign.apply(this, arguments);
2094
+ };
2095
+
2096
+ /** @public */
2097
+ var BSONError = /** @class */ (function (_super) {
2098
+ __extends(BSONError, _super);
2099
+ function BSONError(message) {
2100
+ var _this = _super.call(this, message) || this;
2101
+ Object.setPrototypeOf(_this, BSONError.prototype);
2102
+ return _this;
2103
+ }
2104
+ Object.defineProperty(BSONError.prototype, "name", {
2105
+ get: function () {
2106
+ return 'BSONError';
2107
+ },
2108
+ enumerable: false,
2109
+ configurable: true
2110
+ });
2111
+ return BSONError;
2112
+ }(Error));
2113
+ /** @public */
2114
+ var BSONTypeError = /** @class */ (function (_super) {
2115
+ __extends(BSONTypeError, _super);
2116
+ function BSONTypeError(message) {
2117
+ var _this = _super.call(this, message) || this;
2118
+ Object.setPrototypeOf(_this, BSONTypeError.prototype);
2119
+ return _this;
2120
+ }
2121
+ Object.defineProperty(BSONTypeError.prototype, "name", {
2122
+ get: function () {
2123
+ return 'BSONTypeError';
2124
+ },
2125
+ enumerable: false,
2126
+ configurable: true
2127
+ });
2128
+ return BSONTypeError;
2129
+ }(TypeError));
2130
+
2040
2131
  function checkForMath(potentialGlobal) {
2041
2132
  // eslint-disable-next-line eqeqeq
2042
2133
  return potentialGlobal && potentialGlobal.Math == Math && potentialGlobal;
@@ -2148,7 +2239,7 @@
2148
2239
  * @param potentialBuffer - The potential buffer
2149
2240
  * @returns Buffer the input if potentialBuffer is a buffer, or a buffer that
2150
2241
  * wraps a passed in Uint8Array
2151
- * @throws TypeError If anything other than a Buffer or Uint8Array is passed in
2242
+ * @throws BSONTypeError If anything other than a Buffer or Uint8Array is passed in
2152
2243
  */
2153
2244
  function ensureBuffer(potentialBuffer) {
2154
2245
  if (ArrayBuffer.isView(potentialBuffer)) {
@@ -2157,7 +2248,7 @@
2157
2248
  if (isAnyArrayBuffer(potentialBuffer)) {
2158
2249
  return buffer_1.from(potentialBuffer);
2159
2250
  }
2160
- throw new TypeError('Must use either Buffer or TypedArray');
2251
+ throw new BSONTypeError('Must use either Buffer or TypedArray');
2161
2252
  }
2162
2253
 
2163
2254
  // Validation regex for v4 uuid (validates with or without dashes)
@@ -2167,7 +2258,7 @@
2167
2258
  };
2168
2259
  var uuidHexStringToBuffer = function (hexString) {
2169
2260
  if (!uuidValidateString(hexString)) {
2170
- throw new TypeError('UUID string representations must be a 32 or 36 character hex string (dashes excluded/included). Format: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" or "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx".');
2261
+ throw new BSONTypeError('UUID string representations must be a 32 or 36 character hex string (dashes excluded/included). Format: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" or "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx".');
2171
2262
  }
2172
2263
  var sanitizedHexString = hexString.replace(/-/g, '');
2173
2264
  return buffer_1.from(sanitizedHexString, 'hex');
@@ -2215,7 +2306,7 @@
2215
2306
  this.id = uuidHexStringToBuffer(input);
2216
2307
  }
2217
2308
  else {
2218
- throw new TypeError('Argument passed in UUID constructor must be a UUID, a 16 byte Buffer or a 32/36 character hex string (dashes excluded/included, format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).');
2309
+ throw new BSONTypeError('Argument passed in UUID constructor must be a UUID, a 16 byte Buffer or a 32/36 character hex string (dashes excluded/included, format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).');
2219
2310
  }
2220
2311
  }
2221
2312
  Object.defineProperty(UUID.prototype, "id", {
@@ -2255,14 +2346,13 @@
2255
2346
  };
2256
2347
  /**
2257
2348
  * Converts the id into a 36 character (dashes included) hex string, unless a encoding is specified.
2258
- * @internal
2259
2349
  */
2260
2350
  UUID.prototype.toString = function (encoding) {
2261
2351
  return encoding ? this.id.toString(encoding) : this.toHexString();
2262
2352
  };
2263
2353
  /**
2264
- * Converts the id into its JSON string representation. A 36 character (dashes included) hex string in the format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
2265
- * @internal
2354
+ * Converts the id into its JSON string representation.
2355
+ * A 36 character (dashes included) hex string in the format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
2266
2356
  */
2267
2357
  UUID.prototype.toJSON = function () {
2268
2358
  return this.toHexString();
@@ -2374,7 +2464,7 @@
2374
2464
  !ArrayBuffer.isView(buffer) &&
2375
2465
  !(buffer instanceof ArrayBuffer) &&
2376
2466
  !Array.isArray(buffer)) {
2377
- throw new TypeError('Binary can only be constructed from string, Buffer, TypedArray, or Array<number>');
2467
+ throw new BSONTypeError('Binary can only be constructed from string, Buffer, TypedArray, or Array<number>');
2378
2468
  }
2379
2469
  this.sub_type = subType !== null && subType !== void 0 ? subType : Binary.BSON_BINARY_SUBTYPE_DEFAULT;
2380
2470
  if (buffer == null) {
@@ -2406,10 +2496,10 @@
2406
2496
  Binary.prototype.put = function (byteValue) {
2407
2497
  // If it's a string and a has more than one character throw an error
2408
2498
  if (typeof byteValue === 'string' && byteValue.length !== 1) {
2409
- throw new TypeError('only accepts single character String');
2499
+ throw new BSONTypeError('only accepts single character String');
2410
2500
  }
2411
2501
  else if (typeof byteValue !== 'number' && byteValue.length !== 1)
2412
- throw new TypeError('only accepts single character Uint8Array or Array');
2502
+ throw new BSONTypeError('only accepts single character Uint8Array or Array');
2413
2503
  // Decode the byte value once
2414
2504
  var decodedByte;
2415
2505
  if (typeof byteValue === 'string') {
@@ -2422,7 +2512,7 @@
2422
2512
  decodedByte = byteValue[0];
2423
2513
  }
2424
2514
  if (decodedByte < 0 || decodedByte > 255) {
2425
- throw new TypeError('only accepts number in a valid unsigned byte range 0-255');
2515
+ throw new BSONTypeError('only accepts number in a valid unsigned byte range 0-255');
2426
2516
  }
2427
2517
  if (this.buffer.length > this.position) {
2428
2518
  this.buffer[this.position++] = decodedByte;
@@ -2494,11 +2584,9 @@
2494
2584
  Binary.prototype.length = function () {
2495
2585
  return this.position;
2496
2586
  };
2497
- /** @internal */
2498
2587
  Binary.prototype.toJSON = function () {
2499
2588
  return this.buffer.toString('base64');
2500
2589
  };
2501
- /** @internal */
2502
2590
  Binary.prototype.toString = function (format) {
2503
2591
  return this.buffer.toString(format);
2504
2592
  };
@@ -2520,12 +2608,11 @@
2520
2608
  }
2521
2609
  };
2522
2610
  };
2523
- /** @internal */
2524
2611
  Binary.prototype.toUUID = function () {
2525
2612
  if (this.sub_type === Binary.SUBTYPE_UUID) {
2526
2613
  return new UUID(this.buffer.slice(0, this.position));
2527
2614
  }
2528
- throw new Error("Binary sub_type \"" + this.sub_type + "\" is not supported for converting to UUID. Only \"" + Binary.SUBTYPE_UUID + "\" is currently supported.");
2615
+ throw new BSONError("Binary sub_type \"" + this.sub_type + "\" is not supported for converting to UUID. Only \"" + Binary.SUBTYPE_UUID + "\" is currently supported.");
2529
2616
  };
2530
2617
  /** @internal */
2531
2618
  Binary.fromExtendedJSON = function (doc, options) {
@@ -2549,7 +2636,7 @@
2549
2636
  data = uuidHexStringToBuffer(doc.$uuid);
2550
2637
  }
2551
2638
  if (!data) {
2552
- throw new TypeError("Unexpected Binary Extended JSON format " + JSON.stringify(doc));
2639
+ throw new BSONTypeError("Unexpected Binary Extended JSON format " + JSON.stringify(doc));
2553
2640
  }
2554
2641
  return new Binary(data, type);
2555
2642
  };
@@ -2580,6 +2667,10 @@
2580
2667
  Binary.SUBTYPE_UUID = 4;
2581
2668
  /** MD5 BSON type */
2582
2669
  Binary.SUBTYPE_MD5 = 5;
2670
+ /** Encrypted BSON type */
2671
+ Binary.SUBTYPE_ENCRYPTED = 6;
2672
+ /** Column BSON type */
2673
+ Binary.SUBTYPE_COLUMN = 7;
2583
2674
  /** User BSON type */
2584
2675
  Binary.SUBTYPE_USER_DEFINED = 128;
2585
2676
  return Binary;
@@ -2601,7 +2692,6 @@
2601
2692
  this.code = code;
2602
2693
  this.scope = scope;
2603
2694
  }
2604
- /** @internal */
2605
2695
  Code.prototype.toJSON = function () {
2606
2696
  return { code: this.code, scope: this.scope };
2607
2697
  };
@@ -2673,7 +2763,6 @@
2673
2763
  enumerable: false,
2674
2764
  configurable: true
2675
2765
  });
2676
- /** @internal */
2677
2766
  DBRef.prototype.toJSON = function () {
2678
2767
  var o = Object.assign({
2679
2768
  $ref: this.collection,
@@ -3700,7 +3789,7 @@
3700
3789
  return false;
3701
3790
  }
3702
3791
  function invalidErr(string, message) {
3703
- throw new TypeError("\"" + string + "\" is not a valid Decimal128 string - " + message);
3792
+ throw new BSONTypeError("\"" + string + "\" is not a valid Decimal128 string - " + message);
3704
3793
  }
3705
3794
  /**
3706
3795
  * A class representation of the BSON Decimal128 type.
@@ -3767,7 +3856,7 @@
3767
3856
  // TODO: implementing a custom parsing for this, or refactoring the regex would yield
3768
3857
  // further gains.
3769
3858
  if (representation.length >= 7000) {
3770
- throw new TypeError('' + representation + ' not a valid Decimal128 string');
3859
+ throw new BSONTypeError('' + representation + ' not a valid Decimal128 string');
3771
3860
  }
3772
3861
  // Results
3773
3862
  var stringMatch = representation.match(PARSE_STRING_REGEXP);
@@ -3775,7 +3864,7 @@
3775
3864
  var nanMatch = representation.match(PARSE_NAN_REGEXP);
3776
3865
  // Validate the string
3777
3866
  if ((!stringMatch && !infMatch && !nanMatch) || representation.length === 0) {
3778
- throw new TypeError('' + representation + ' not a valid Decimal128 string');
3867
+ throw new BSONTypeError('' + representation + ' not a valid Decimal128 string');
3779
3868
  }
3780
3869
  if (stringMatch) {
3781
3870
  // full_match = stringMatch[0]
@@ -3837,7 +3926,7 @@
3837
3926
  index = index + 1;
3838
3927
  }
3839
3928
  if (sawRadix && !nDigitsRead)
3840
- throw new TypeError('' + representation + ' not a valid Decimal128 string');
3929
+ throw new BSONTypeError('' + representation + ' not a valid Decimal128 string');
3841
3930
  // Read exponent if exists
3842
3931
  if (representation[index] === 'e' || representation[index] === 'E') {
3843
3932
  // Read exponent digits
@@ -3868,7 +3957,7 @@
3868
3957
  lastDigit = nDigitsStored - 1;
3869
3958
  significantDigits = nDigits;
3870
3959
  if (significantDigits !== 1) {
3871
- while (representation[firstNonZero + significantDigits - 1] === '0') {
3960
+ while (digits[firstNonZero + significantDigits - 1] === 0) {
3872
3961
  significantDigits = significantDigits - 1;
3873
3962
  }
3874
3963
  }
@@ -4293,10 +4382,12 @@
4293
4382
  Double.prototype.valueOf = function () {
4294
4383
  return this.value;
4295
4384
  };
4296
- /** @internal */
4297
4385
  Double.prototype.toJSON = function () {
4298
4386
  return this.value;
4299
4387
  };
4388
+ Double.prototype.toString = function (radix) {
4389
+ return this.value.toString(radix);
4390
+ };
4300
4391
  /** @internal */
4301
4392
  Double.prototype.toExtendedJSON = function (options) {
4302
4393
  if (options && (options.legacy || (options.relaxed && isFinite(this.value)))) {
@@ -4352,7 +4443,7 @@
4352
4443
  if (value instanceof Number) {
4353
4444
  value = value.valueOf();
4354
4445
  }
4355
- this.value = +value;
4446
+ this.value = +value | 0;
4356
4447
  }
4357
4448
  /**
4358
4449
  * Access the number value.
@@ -4362,7 +4453,9 @@
4362
4453
  Int32.prototype.valueOf = function () {
4363
4454
  return this.value;
4364
4455
  };
4365
- /** @internal */
4456
+ Int32.prototype.toString = function (radix) {
4457
+ return this.value.toString(radix);
4458
+ };
4366
4459
  Int32.prototype.toJSON = function () {
4367
4460
  return this.value;
4368
4461
  };
@@ -4456,50 +4549,57 @@
4456
4549
  /**
4457
4550
  * Create an ObjectId type
4458
4551
  *
4459
- * @param id - Can be a 24 character hex string, 12 byte binary Buffer, or a number.
4552
+ * @param inputId - Can be a 24 character hex string, 12 byte binary Buffer, or a number.
4460
4553
  */
4461
- function ObjectId(id) {
4554
+ function ObjectId(inputId) {
4462
4555
  if (!(this instanceof ObjectId))
4463
- return new ObjectId(id);
4464
- // Duck-typing to support ObjectId from different npm packages
4465
- if (id instanceof ObjectId) {
4466
- this[kId] = id.id;
4467
- this.__id = id.__id;
4468
- }
4469
- if (typeof id === 'object' && id && 'id' in id) {
4470
- if ('toHexString' in id && typeof id.toHexString === 'function') {
4471
- this[kId] = buffer_1.from(id.toHexString(), 'hex');
4556
+ return new ObjectId(inputId);
4557
+ // workingId is set based on type of input and whether valid id exists for the input
4558
+ var workingId;
4559
+ if (typeof inputId === 'object' && inputId && 'id' in inputId) {
4560
+ if (typeof inputId.id !== 'string' && !ArrayBuffer.isView(inputId.id)) {
4561
+ throw new BSONTypeError('Argument passed in must have an id that is of type string or Buffer');
4562
+ }
4563
+ if ('toHexString' in inputId && typeof inputId.toHexString === 'function') {
4564
+ workingId = buffer_1.from(inputId.toHexString(), 'hex');
4472
4565
  }
4473
4566
  else {
4474
- this[kId] = typeof id.id === 'string' ? buffer_1.from(id.id) : id.id;
4567
+ workingId = inputId.id;
4475
4568
  }
4476
4569
  }
4477
- // The most common use case (blank id, new objectId instance)
4478
- if (id == null || typeof id === 'number') {
4570
+ else {
4571
+ workingId = inputId;
4572
+ }
4573
+ // the following cases use workingId to construct an ObjectId
4574
+ if (workingId == null || typeof workingId === 'number') {
4575
+ // The most common use case (blank id, new objectId instance)
4479
4576
  // Generate a new id
4480
- this[kId] = ObjectId.generate(typeof id === 'number' ? id : undefined);
4481
- // If we are caching the hex string
4482
- if (ObjectId.cacheHexString) {
4483
- this.__id = this.id.toString('hex');
4484
- }
4577
+ this[kId] = ObjectId.generate(typeof workingId === 'number' ? workingId : undefined);
4485
4578
  }
4486
- if (ArrayBuffer.isView(id) && id.byteLength === 12) {
4487
- this[kId] = ensureBuffer(id);
4579
+ else if (ArrayBuffer.isView(workingId) && workingId.byteLength === 12) {
4580
+ this[kId] = ensureBuffer(workingId);
4488
4581
  }
4489
- if (typeof id === 'string') {
4490
- if (id.length === 12) {
4491
- var bytes = buffer_1.from(id);
4582
+ else if (typeof workingId === 'string') {
4583
+ if (workingId.length === 12) {
4584
+ var bytes = buffer_1.from(workingId);
4492
4585
  if (bytes.byteLength === 12) {
4493
4586
  this[kId] = bytes;
4494
4587
  }
4588
+ else {
4589
+ throw new BSONTypeError('Argument passed in must be a string of 12 bytes');
4590
+ }
4495
4591
  }
4496
- else if (id.length === 24 && checkForHexRegExp.test(id)) {
4497
- this[kId] = buffer_1.from(id, 'hex');
4592
+ else if (workingId.length === 24 && checkForHexRegExp.test(workingId)) {
4593
+ this[kId] = buffer_1.from(workingId, 'hex');
4498
4594
  }
4499
4595
  else {
4500
- throw new TypeError('Argument passed in must be a Buffer or string of 12 bytes or a string of 24 hex characters');
4596
+ throw new BSONTypeError('Argument passed in must be a string of 12 bytes or a string of 24 hex characters');
4501
4597
  }
4502
4598
  }
4599
+ else {
4600
+ throw new BSONTypeError('Argument passed in does not match the accepted types');
4601
+ }
4602
+ // If we are caching the hex string
4503
4603
  if (ObjectId.cacheHexString) {
4504
4604
  this.__id = this.id.toString('hex');
4505
4605
  }
@@ -4563,7 +4663,7 @@
4563
4663
  */
4564
4664
  ObjectId.generate = function (time) {
4565
4665
  if ('number' !== typeof time) {
4566
- time = ~~(Date.now() / 1000);
4666
+ time = Math.floor(Date.now() / 1000);
4567
4667
  }
4568
4668
  var inc = ObjectId.getInc();
4569
4669
  var buffer = buffer_1.alloc(12);
@@ -4589,7 +4689,6 @@
4589
4689
  * Converts the id into a 24 character hex string for printing
4590
4690
  *
4591
4691
  * @param format - The Buffer toString format parameter.
4592
- * @internal
4593
4692
  */
4594
4693
  ObjectId.prototype.toString = function (format) {
4595
4694
  // Is the id a buffer then use the buffer toString method to return the format
@@ -4597,10 +4696,7 @@
4597
4696
  return this.id.toString(format);
4598
4697
  return this.toHexString();
4599
4698
  };
4600
- /**
4601
- * Converts to its JSON the 24 character hex string representation.
4602
- * @internal
4603
- */
4699
+ /** Converts to its JSON the 24 character hex string representation. */
4604
4700
  ObjectId.prototype.toJSON = function () {
4605
4701
  return this.toHexString();
4606
4702
  };
@@ -4666,7 +4762,7 @@
4666
4762
  ObjectId.createFromHexString = function (hexString) {
4667
4763
  // Throw an error if it's not a valid setup
4668
4764
  if (typeof hexString === 'undefined' || (hexString != null && hexString.length !== 24)) {
4669
- throw new TypeError('Argument passed in must be a single String of 12 bytes or a string of 24 hex characters');
4765
+ throw new BSONTypeError('Argument passed in must be a single String of 12 bytes or a string of 24 hex characters');
4670
4766
  }
4671
4767
  return new ObjectId(buffer_1.from(hexString, 'hex'));
4672
4768
  };
@@ -4722,7 +4818,7 @@
4722
4818
  return "new ObjectId(\"" + this.toHexString() + "\")";
4723
4819
  };
4724
4820
  /** @internal */
4725
- ObjectId.index = ~~(Math.random() * 0xffffff);
4821
+ ObjectId.index = Math.floor(Math.random() * 0xffffff);
4726
4822
  return ObjectId;
4727
4823
  }());
4728
4824
  // Deprecated methods
@@ -4757,6 +4853,12 @@
4757
4853
  return new BSONRegExp(pattern, options);
4758
4854
  this.pattern = pattern;
4759
4855
  this.options = alphabetize(options !== null && options !== void 0 ? options : '');
4856
+ if (this.pattern.indexOf('\x00') !== -1) {
4857
+ throw new BSONError("BSON Regex patterns cannot contain null bytes, found: " + JSON.stringify(this.pattern));
4858
+ }
4859
+ if (this.options.indexOf('\x00') !== -1) {
4860
+ throw new BSONError("BSON Regex options cannot contain null bytes, found: " + JSON.stringify(this.options));
4861
+ }
4760
4862
  // Validate options
4761
4863
  for (var i = 0; i < this.options.length; i++) {
4762
4864
  if (!(this.options[i] === 'i' ||
@@ -4765,7 +4867,7 @@
4765
4867
  this.options[i] === 'l' ||
4766
4868
  this.options[i] === 's' ||
4767
4869
  this.options[i] === 'u')) {
4768
- throw new Error("The regular expression option [" + this.options[i] + "] is not supported");
4870
+ throw new BSONError("The regular expression option [" + this.options[i] + "] is not supported");
4769
4871
  }
4770
4872
  }
4771
4873
  }
@@ -4796,7 +4898,7 @@
4796
4898
  if ('$regularExpression' in doc) {
4797
4899
  return new BSONRegExp(doc.$regularExpression.pattern, BSONRegExp.parseOptions(doc.$regularExpression.options));
4798
4900
  }
4799
- throw new TypeError("Unexpected BSONRegExp EJSON object form: " + JSON.stringify(doc));
4901
+ throw new BSONTypeError("Unexpected BSONRegExp EJSON object form: " + JSON.stringify(doc));
4800
4902
  };
4801
4903
  return BSONRegExp;
4802
4904
  }());
@@ -4819,7 +4921,6 @@
4819
4921
  BSONSymbol.prototype.valueOf = function () {
4820
4922
  return this.value;
4821
4923
  };
4822
- /** @internal */
4823
4924
  BSONSymbol.prototype.toString = function () {
4824
4925
  return this.value;
4825
4926
  };
@@ -4827,7 +4928,6 @@
4827
4928
  BSONSymbol.prototype.inspect = function () {
4828
4929
  return "new BSONSymbol(\"" + this.value + "\")";
4829
4930
  };
4830
- /** @internal */
4831
4931
  BSONSymbol.prototype.toJSON = function () {
4832
4932
  return this.value;
4833
4933
  };
@@ -4847,46 +4947,6 @@
4847
4947
  }());
4848
4948
  Object.defineProperty(BSONSymbol.prototype, '_bsontype', { value: 'Symbol' });
4849
4949
 
4850
- /*! *****************************************************************************
4851
- Copyright (c) Microsoft Corporation.
4852
-
4853
- Permission to use, copy, modify, and/or distribute this software for any
4854
- purpose with or without fee is hereby granted.
4855
-
4856
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
4857
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
4858
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
4859
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
4860
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
4861
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
4862
- PERFORMANCE OF THIS SOFTWARE.
4863
- ***************************************************************************** */
4864
-
4865
- /* global Reflect, Promise */
4866
- var _extendStatics = function extendStatics(d, b) {
4867
- _extendStatics = Object.setPrototypeOf || {
4868
- __proto__: []
4869
- } instanceof Array && function (d, b) {
4870
- d.__proto__ = b;
4871
- } || function (d, b) {
4872
- for (var p in b) {
4873
- if (b.hasOwnProperty(p)) d[p] = b[p];
4874
- }
4875
- };
4876
-
4877
- return _extendStatics(d, b);
4878
- };
4879
-
4880
- function __extends(d, b) {
4881
- _extendStatics(d, b);
4882
-
4883
- function __() {
4884
- this.constructor = d;
4885
- }
4886
-
4887
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
4888
- }
4889
-
4890
4950
  /** @public */
4891
4951
  var LongWithoutOverridesClass = Long;
4892
4952
  /** @public */
@@ -5101,7 +5161,7 @@
5101
5161
  var current = props[props.length - 1];
5102
5162
  var leadingSpace = ' '.repeat(leadingPart.length + alreadySeen.length / 2);
5103
5163
  var dashes = '-'.repeat(circularPart.length + (alreadySeen.length + current.length) / 2 - 1);
5104
- throw new TypeError('Converting circular structure to EJSON:\n' +
5164
+ throw new BSONTypeError('Converting circular structure to EJSON:\n' +
5105
5165
  (" " + leadingPart + alreadySeen + circularPart + current + "\n") +
5106
5166
  (" " + leadingSpace + "\\" + dashes + "/"));
5107
5167
  }
@@ -5174,7 +5234,7 @@
5174
5234
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
5175
5235
  function serializeDocument(doc, options) {
5176
5236
  if (doc == null || typeof doc !== 'object')
5177
- throw new Error('not an object instance');
5237
+ throw new BSONError('not an object instance');
5178
5238
  var bsontype = doc._bsontype;
5179
5239
  if (typeof bsontype === 'undefined') {
5180
5240
  // It's a regular object. Recursively serialize its property values.
@@ -5201,7 +5261,7 @@
5201
5261
  // Copy the object into this library's version of that type.
5202
5262
  var mapper = BSON_TYPE_MAPPINGS[doc._bsontype];
5203
5263
  if (!mapper) {
5204
- throw new TypeError('Unrecognized or invalid _bsontype: ' + doc._bsontype);
5264
+ throw new BSONTypeError('Unrecognized or invalid _bsontype: ' + doc._bsontype);
5205
5265
  }
5206
5266
  outDoc = mapper(outDoc);
5207
5267
  }
@@ -5215,7 +5275,7 @@
5215
5275
  return outDoc.toExtendedJSON(options);
5216
5276
  }
5217
5277
  else {
5218
- throw new Error('_bsontype must be a string, but was: ' + typeof bsontype);
5278
+ throw new BSONError('_bsontype must be a string, but was: ' + typeof bsontype);
5219
5279
  }
5220
5280
  }
5221
5281
  /**
@@ -5250,7 +5310,12 @@
5250
5310
  finalOptions.strict = !finalOptions.relaxed;
5251
5311
  if (typeof finalOptions.strict === 'boolean')
5252
5312
  finalOptions.relaxed = !finalOptions.strict;
5253
- return JSON.parse(text, function (_key, value) { return deserializeValue(value, finalOptions); });
5313
+ return JSON.parse(text, function (key, value) {
5314
+ if (key.indexOf('\x00') !== -1) {
5315
+ throw new BSONError("BSON Document field names cannot contain null bytes, found: " + JSON.stringify(key));
5316
+ }
5317
+ return deserializeValue(value, finalOptions);
5318
+ });
5254
5319
  }
5255
5320
  EJSON.parse = parse;
5256
5321
  /**
@@ -5508,6 +5573,10 @@
5508
5573
  var BSON_BINARY_SUBTYPE_UUID_NEW = 4;
5509
5574
  /** Binary MD5 Type @internal */
5510
5575
  var BSON_BINARY_SUBTYPE_MD5 = 5;
5576
+ /** Encrypted BSON type @internal */
5577
+ var BSON_BINARY_SUBTYPE_ENCRYPTED = 6;
5578
+ /** Column BSON type @internal */
5579
+ var BSON_BINARY_SUBTYPE_COLUMN = 7;
5511
5580
  /** Binary User Defined Type @internal */
5512
5581
  var BSON_BINARY_SUBTYPE_USER_DEFINED = 128;
5513
5582
 
@@ -5752,20 +5821,20 @@
5752
5821
  (buffer[index + 2] << 16) |
5753
5822
  (buffer[index + 3] << 24);
5754
5823
  if (size < 5) {
5755
- throw new Error("bson size must be >= 5, is " + size);
5824
+ throw new BSONError("bson size must be >= 5, is " + size);
5756
5825
  }
5757
5826
  if (options.allowObjectSmallerThanBufferSize && buffer.length < size) {
5758
- throw new Error("buffer length " + buffer.length + " must be >= bson size " + size);
5827
+ throw new BSONError("buffer length " + buffer.length + " must be >= bson size " + size);
5759
5828
  }
5760
5829
  if (!options.allowObjectSmallerThanBufferSize && buffer.length !== size) {
5761
- throw new Error("buffer length " + buffer.length + " must === bson size " + size);
5830
+ throw new BSONError("buffer length " + buffer.length + " must === bson size " + size);
5762
5831
  }
5763
5832
  if (size + index > buffer.byteLength) {
5764
- throw new Error("(bson size " + size + " + options.index " + index + " must be <= buffer length " + buffer.byteLength + ")");
5833
+ throw new BSONError("(bson size " + size + " + options.index " + index + " must be <= buffer length " + buffer.byteLength + ")");
5765
5834
  }
5766
5835
  // Illegal end value
5767
5836
  if (buffer[index + size - 1] !== 0) {
5768
- throw new Error("One object, sized correctly, with a spot for an EOO, but the EOO isn't 0x00");
5837
+ throw new BSONError("One object, sized correctly, with a spot for an EOO, but the EOO isn't 0x00");
5769
5838
  }
5770
5839
  // Start deserializtion
5771
5840
  return deserializeObject(buffer, index, options, isArray);
@@ -5784,16 +5853,53 @@
5784
5853
  var promoteBuffers = options['promoteBuffers'] == null ? false : options['promoteBuffers'];
5785
5854
  var promoteLongs = options['promoteLongs'] == null ? true : options['promoteLongs'];
5786
5855
  var promoteValues = options['promoteValues'] == null ? true : options['promoteValues'];
5856
+ // Ensures default validation option if none given
5857
+ var validation = options.validation == null ? { utf8: true } : options.validation;
5858
+ // Shows if global utf-8 validation is enabled or disabled
5859
+ var globalUTFValidation = true;
5860
+ // Reflects utf-8 validation setting regardless of global or specific key validation
5861
+ var validationSetting;
5862
+ // Set of keys either to enable or disable validation on
5863
+ var utf8KeysSet = new Set();
5864
+ // Check for boolean uniformity and empty validation option
5865
+ var utf8ValidatedKeys = validation.utf8;
5866
+ if (typeof utf8ValidatedKeys === 'boolean') {
5867
+ validationSetting = utf8ValidatedKeys;
5868
+ }
5869
+ else {
5870
+ globalUTFValidation = false;
5871
+ var utf8ValidationValues = Object.keys(utf8ValidatedKeys).map(function (key) {
5872
+ return utf8ValidatedKeys[key];
5873
+ });
5874
+ if (utf8ValidationValues.length === 0) {
5875
+ throw new BSONError('UTF-8 validation setting cannot be empty');
5876
+ }
5877
+ if (typeof utf8ValidationValues[0] !== 'boolean') {
5878
+ throw new BSONError('Invalid UTF-8 validation option, must specify boolean values');
5879
+ }
5880
+ validationSetting = utf8ValidationValues[0];
5881
+ // Ensures boolean uniformity in utf-8 validation (all true or all false)
5882
+ if (!utf8ValidationValues.every(function (item) { return item === validationSetting; })) {
5883
+ throw new BSONError('Invalid UTF-8 validation option - keys must be all true or all false');
5884
+ }
5885
+ }
5886
+ // Add keys to set that will either be validated or not based on validationSetting
5887
+ if (!globalUTFValidation) {
5888
+ for (var _i = 0, _a = Object.keys(utf8ValidatedKeys); _i < _a.length; _i++) {
5889
+ var key = _a[_i];
5890
+ utf8KeysSet.add(key);
5891
+ }
5892
+ }
5787
5893
  // Set the start index
5788
5894
  var startIndex = index;
5789
5895
  // Validate that we have at least 4 bytes of buffer
5790
5896
  if (buffer.length < 5)
5791
- throw new Error('corrupt bson message < 5 bytes long');
5897
+ throw new BSONError('corrupt bson message < 5 bytes long');
5792
5898
  // Read the document size
5793
5899
  var size = buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
5794
5900
  // Ensure buffer is valid size
5795
5901
  if (size < 5 || size > buffer.length)
5796
- throw new Error('corrupt bson message');
5902
+ throw new BSONError('corrupt bson message');
5797
5903
  // Create holding object
5798
5904
  var object = isArray ? [] : {};
5799
5905
  // Used for arrays to skip having to perform utf8 decoding
@@ -5815,8 +5921,17 @@
5815
5921
  }
5816
5922
  // If are at the end of the buffer there is a problem with the document
5817
5923
  if (i >= buffer.byteLength)
5818
- throw new Error('Bad BSON Document: illegal CString');
5924
+ throw new BSONError('Bad BSON Document: illegal CString');
5925
+ // Represents the key
5819
5926
  var name = isArray ? arrayIndex++ : buffer.toString('utf8', index, i);
5927
+ // shouldValidateKey is true if the key should be validated, false otherwise
5928
+ var shouldValidateKey = true;
5929
+ if (globalUTFValidation || utf8KeysSet.has(name)) {
5930
+ shouldValidateKey = validationSetting;
5931
+ }
5932
+ else {
5933
+ shouldValidateKey = !validationSetting;
5934
+ }
5820
5935
  if (isPossibleDBRef !== false && name[0] === '$') {
5821
5936
  isPossibleDBRef = allowedDBRefKeys.test(name);
5822
5937
  }
@@ -5829,17 +5944,10 @@
5829
5944
  (buffer[index++] << 24);
5830
5945
  if (stringSize <= 0 ||
5831
5946
  stringSize > buffer.length - index ||
5832
- buffer[index + stringSize - 1] !== 0)
5833
- throw new Error('bad string length in bson');
5834
- value = buffer.toString('utf8', index, index + stringSize - 1);
5835
- for (var i_1 = 0; i_1 < value.length; i_1++) {
5836
- if (value.charCodeAt(i_1) === 0xfffd) {
5837
- if (!validateUtf8(buffer, index, index + stringSize - 1)) {
5838
- throw new Error('Invalid UTF-8 string in BSON document');
5839
- }
5840
- break;
5841
- }
5947
+ buffer[index + stringSize - 1] !== 0) {
5948
+ throw new BSONError('bad string length in bson');
5842
5949
  }
5950
+ value = getValidatedString(buffer, index, index + stringSize - 1, shouldValidateKey);
5843
5951
  index = index + stringSize;
5844
5952
  }
5845
5953
  else if (elementType === BSON_DATA_OID) {
@@ -5879,7 +5987,7 @@
5879
5987
  }
5880
5988
  else if (elementType === BSON_DATA_BOOLEAN) {
5881
5989
  if (buffer[index] !== 0 && buffer[index] !== 1)
5882
- throw new Error('illegal boolean type value');
5990
+ throw new BSONError('illegal boolean type value');
5883
5991
  value = buffer[index++] === 1;
5884
5992
  }
5885
5993
  else if (elementType === BSON_DATA_OBJECT) {
@@ -5889,13 +5997,17 @@
5889
5997
  (buffer[index + 2] << 16) |
5890
5998
  (buffer[index + 3] << 24);
5891
5999
  if (objectSize <= 0 || objectSize > buffer.length - index)
5892
- throw new Error('bad embedded document length in bson');
6000
+ throw new BSONError('bad embedded document length in bson');
5893
6001
  // We have a raw value
5894
6002
  if (raw) {
5895
6003
  value = buffer.slice(index, index + objectSize);
5896
6004
  }
5897
6005
  else {
5898
- value = deserializeObject(buffer, _index, options, false);
6006
+ var objectOptions = options;
6007
+ if (!globalUTFValidation) {
6008
+ objectOptions = _assign(_assign({}, options), { validation: { utf8: shouldValidateKey } });
6009
+ }
6010
+ value = deserializeObject(buffer, _index, objectOptions, false);
5899
6011
  }
5900
6012
  index = index + objectSize;
5901
6013
  }
@@ -5916,12 +6028,15 @@
5916
6028
  }
5917
6029
  arrayOptions['raw'] = true;
5918
6030
  }
6031
+ if (!globalUTFValidation) {
6032
+ arrayOptions = _assign(_assign({}, arrayOptions), { validation: { utf8: shouldValidateKey } });
6033
+ }
5919
6034
  value = deserializeObject(buffer, _index, arrayOptions, true);
5920
6035
  index = index + objectSize;
5921
6036
  if (buffer[index - 1] !== 0)
5922
- throw new Error('invalid array terminator byte');
6037
+ throw new BSONError('invalid array terminator byte');
5923
6038
  if (index !== stopIndex)
5924
- throw new Error('corrupted array bson');
6039
+ throw new BSONError('corrupted array bson');
5925
6040
  }
5926
6041
  else if (elementType === BSON_DATA_UNDEFINED) {
5927
6042
  value = undefined;
@@ -5977,10 +6092,10 @@
5977
6092
  var subType = buffer[index++];
5978
6093
  // Did we have a negative binary size, throw
5979
6094
  if (binarySize < 0)
5980
- throw new Error('Negative binary type element size found');
6095
+ throw new BSONError('Negative binary type element size found');
5981
6096
  // Is the length longer than the document
5982
6097
  if (binarySize > buffer.byteLength)
5983
- throw new Error('Binary type size larger than document size');
6098
+ throw new BSONError('Binary type size larger than document size');
5984
6099
  // Decode as raw Buffer object if options specifies it
5985
6100
  if (buffer['slice'] != null) {
5986
6101
  // If we have subtype 2 skip the 4 bytes for the size
@@ -5991,11 +6106,11 @@
5991
6106
  (buffer[index++] << 16) |
5992
6107
  (buffer[index++] << 24);
5993
6108
  if (binarySize < 0)
5994
- throw new Error('Negative binary type element size found for subtype 0x02');
6109
+ throw new BSONError('Negative binary type element size found for subtype 0x02');
5995
6110
  if (binarySize > totalBinarySize - 4)
5996
- throw new Error('Binary type with subtype 0x02 contains too long binary size');
6111
+ throw new BSONError('Binary type with subtype 0x02 contains too long binary size');
5997
6112
  if (binarySize < totalBinarySize - 4)
5998
- throw new Error('Binary type with subtype 0x02 contains too short binary size');
6113
+ throw new BSONError('Binary type with subtype 0x02 contains too short binary size');
5999
6114
  }
6000
6115
  if (promoteBuffers && promoteValues) {
6001
6116
  value = buffer.slice(index, index + binarySize);
@@ -6014,11 +6129,11 @@
6014
6129
  (buffer[index++] << 16) |
6015
6130
  (buffer[index++] << 24);
6016
6131
  if (binarySize < 0)
6017
- throw new Error('Negative binary type element size found for subtype 0x02');
6132
+ throw new BSONError('Negative binary type element size found for subtype 0x02');
6018
6133
  if (binarySize > totalBinarySize - 4)
6019
- throw new Error('Binary type with subtype 0x02 contains too long binary size');
6134
+ throw new BSONError('Binary type with subtype 0x02 contains too long binary size');
6020
6135
  if (binarySize < totalBinarySize - 4)
6021
- throw new Error('Binary type with subtype 0x02 contains too short binary size');
6136
+ throw new BSONError('Binary type with subtype 0x02 contains too short binary size');
6022
6137
  }
6023
6138
  // Copy the data
6024
6139
  for (i = 0; i < binarySize; i++) {
@@ -6043,7 +6158,7 @@
6043
6158
  }
6044
6159
  // If are at the end of the buffer there is a problem with the document
6045
6160
  if (i >= buffer.length)
6046
- throw new Error('Bad BSON Document: illegal CString');
6161
+ throw new BSONError('Bad BSON Document: illegal CString');
6047
6162
  // Return the C string
6048
6163
  var source = buffer.toString('utf8', index, i);
6049
6164
  // Create the regexp
@@ -6056,7 +6171,7 @@
6056
6171
  }
6057
6172
  // If are at the end of the buffer there is a problem with the document
6058
6173
  if (i >= buffer.length)
6059
- throw new Error('Bad BSON Document: illegal CString');
6174
+ throw new BSONError('Bad BSON Document: illegal CString');
6060
6175
  // Return the C string
6061
6176
  var regExpOptions = buffer.toString('utf8', index, i);
6062
6177
  index = i + 1;
@@ -6087,7 +6202,7 @@
6087
6202
  }
6088
6203
  // If are at the end of the buffer there is a problem with the document
6089
6204
  if (i >= buffer.length)
6090
- throw new Error('Bad BSON Document: illegal CString');
6205
+ throw new BSONError('Bad BSON Document: illegal CString');
6091
6206
  // Return the C string
6092
6207
  var source = buffer.toString('utf8', index, i);
6093
6208
  index = i + 1;
@@ -6099,7 +6214,7 @@
6099
6214
  }
6100
6215
  // If are at the end of the buffer there is a problem with the document
6101
6216
  if (i >= buffer.length)
6102
- throw new Error('Bad BSON Document: illegal CString');
6217
+ throw new BSONError('Bad BSON Document: illegal CString');
6103
6218
  // Return the C string
6104
6219
  var regExpOptions = buffer.toString('utf8', index, i);
6105
6220
  index = i + 1;
@@ -6113,9 +6228,10 @@
6113
6228
  (buffer[index++] << 24);
6114
6229
  if (stringSize <= 0 ||
6115
6230
  stringSize > buffer.length - index ||
6116
- buffer[index + stringSize - 1] !== 0)
6117
- throw new Error('bad string length in bson');
6118
- var symbol = buffer.toString('utf8', index, index + stringSize - 1);
6231
+ buffer[index + stringSize - 1] !== 0) {
6232
+ throw new BSONError('bad string length in bson');
6233
+ }
6234
+ var symbol = getValidatedString(buffer, index, index + stringSize - 1, shouldValidateKey);
6119
6235
  value = promoteValues ? symbol : new BSONSymbol(symbol);
6120
6236
  index = index + stringSize;
6121
6237
  }
@@ -6143,9 +6259,10 @@
6143
6259
  (buffer[index++] << 24);
6144
6260
  if (stringSize <= 0 ||
6145
6261
  stringSize > buffer.length - index ||
6146
- buffer[index + stringSize - 1] !== 0)
6147
- throw new Error('bad string length in bson');
6148
- var functionString = buffer.toString('utf8', index, index + stringSize - 1);
6262
+ buffer[index + stringSize - 1] !== 0) {
6263
+ throw new BSONError('bad string length in bson');
6264
+ }
6265
+ var functionString = getValidatedString(buffer, index, index + stringSize - 1, shouldValidateKey);
6149
6266
  // If we are evaluating the functions
6150
6267
  if (evalFunctions) {
6151
6268
  // If we have cache enabled let's look for the md5 of the function in the cache
@@ -6170,7 +6287,7 @@
6170
6287
  (buffer[index++] << 24);
6171
6288
  // Element cannot be shorter than totalSize + stringSize + documentSize + terminator
6172
6289
  if (totalSize < 4 + 4 + 4 + 1) {
6173
- throw new Error('code_w_scope total size shorter minimum expected length');
6290
+ throw new BSONError('code_w_scope total size shorter minimum expected length');
6174
6291
  }
6175
6292
  // Get the code string size
6176
6293
  var stringSize = buffer[index++] |
@@ -6180,10 +6297,11 @@
6180
6297
  // Check if we have a valid string
6181
6298
  if (stringSize <= 0 ||
6182
6299
  stringSize > buffer.length - index ||
6183
- buffer[index + stringSize - 1] !== 0)
6184
- throw new Error('bad string length in bson');
6300
+ buffer[index + stringSize - 1] !== 0) {
6301
+ throw new BSONError('bad string length in bson');
6302
+ }
6185
6303
  // Javascript function
6186
- var functionString = buffer.toString('utf8', index, index + stringSize - 1);
6304
+ var functionString = getValidatedString(buffer, index, index + stringSize - 1, shouldValidateKey);
6187
6305
  // Update parse index position
6188
6306
  index = index + stringSize;
6189
6307
  // Parse the element
@@ -6199,11 +6317,11 @@
6199
6317
  index = index + objectSize;
6200
6318
  // Check if field length is too short
6201
6319
  if (totalSize < 4 + 4 + objectSize + stringSize) {
6202
- throw new Error('code_w_scope total size is too short, truncating scope');
6320
+ throw new BSONError('code_w_scope total size is too short, truncating scope');
6203
6321
  }
6204
6322
  // Check if totalSize field is too long
6205
6323
  if (totalSize > 4 + 4 + objectSize + stringSize) {
6206
- throw new Error('code_w_scope total size is too long, clips outer document');
6324
+ throw new BSONError('code_w_scope total size is too long, clips outer document');
6207
6325
  }
6208
6326
  // If we are evaluating the functions
6209
6327
  if (evalFunctions) {
@@ -6231,10 +6349,12 @@
6231
6349
  if (stringSize <= 0 ||
6232
6350
  stringSize > buffer.length - index ||
6233
6351
  buffer[index + stringSize - 1] !== 0)
6234
- throw new Error('bad string length in bson');
6352
+ throw new BSONError('bad string length in bson');
6235
6353
  // Namespace
6236
- if (!validateUtf8(buffer, index, index + stringSize - 1)) {
6237
- throw new Error('Invalid UTF-8 string in BSON document');
6354
+ if (validation != null && validation.utf8) {
6355
+ if (!validateUtf8(buffer, index, index + stringSize - 1)) {
6356
+ throw new BSONError('Invalid UTF-8 string in BSON document');
6357
+ }
6238
6358
  }
6239
6359
  var namespace = buffer.toString('utf8', index, index + stringSize - 1);
6240
6360
  // Update parse index position
@@ -6249,7 +6369,7 @@
6249
6369
  value = new DBRef(namespace, oid);
6250
6370
  }
6251
6371
  else {
6252
- throw new Error('Detected unknown BSON type ' + elementType.toString(16) + ' for fieldname "' + name + '"');
6372
+ throw new BSONError('Detected unknown BSON type ' + elementType.toString(16) + ' for fieldname "' + name + '"');
6253
6373
  }
6254
6374
  if (name === '__proto__') {
6255
6375
  Object.defineProperty(object, name, {
@@ -6266,8 +6386,8 @@
6266
6386
  // Check if the deserialization was against a valid array/object
6267
6387
  if (size !== index - startIndex) {
6268
6388
  if (isArray)
6269
- throw new Error('corrupt array bson');
6270
- throw new Error('corrupt object bson');
6389
+ throw new BSONError('corrupt array bson');
6390
+ throw new BSONError('corrupt object bson');
6271
6391
  }
6272
6392
  // if we did not find "$ref", "$id", "$db", or found an extraneous $key, don't make a DBRef
6273
6393
  if (!isPossibleDBRef)
@@ -6296,6 +6416,21 @@
6296
6416
  // Set the object
6297
6417
  return functionCache[functionString].bind(object);
6298
6418
  }
6419
+ function getValidatedString(buffer, start, end, shouldValidateUtf8) {
6420
+ var value = buffer.toString('utf8', start, end);
6421
+ // if utf8 validation is on, do the check
6422
+ if (shouldValidateUtf8) {
6423
+ for (var i = 0; i < value.length; i++) {
6424
+ if (value.charCodeAt(i) === 0xfffd) {
6425
+ if (!validateUtf8(buffer, start, end)) {
6426
+ throw new BSONError('Invalid UTF-8 string in BSON document');
6427
+ }
6428
+ break;
6429
+ }
6430
+ }
6431
+ }
6432
+ return value;
6433
+ }
6299
6434
 
6300
6435
  // Copyright (c) 2008, Fair Oaks Labs, Inc.
6301
6436
  function writeIEEE754(buffer, value, offset, endian, mLen, nBytes) {
@@ -6580,7 +6715,7 @@
6580
6715
  buffer.set(value.id.subarray(0, 12), index);
6581
6716
  }
6582
6717
  else {
6583
- throw new TypeError('object [' + JSON.stringify(value) + '] is not a valid ObjectId');
6718
+ throw new BSONTypeError('object [' + JSON.stringify(value) + '] is not a valid ObjectId');
6584
6719
  }
6585
6720
  // Adjust index
6586
6721
  return index + 12;
@@ -6619,7 +6754,7 @@
6619
6754
  if (path === void 0) { path = []; }
6620
6755
  for (var i = 0; i < path.length; i++) {
6621
6756
  if (path[i] === value)
6622
- throw new Error('cyclic dependency detected');
6757
+ throw new BSONError('cyclic dependency detected');
6623
6758
  }
6624
6759
  // Push value to stack
6625
6760
  path.push(value);
@@ -6922,7 +7057,7 @@
6922
7057
  // Is there an override value
6923
7058
  if (value && value.toBSON) {
6924
7059
  if (typeof value.toBSON !== 'function')
6925
- throw new TypeError('toBSON is not a function');
7060
+ throw new BSONTypeError('toBSON is not a function');
6926
7061
  value = value.toBSON();
6927
7062
  }
6928
7063
  if (typeof value === 'string') {
@@ -6932,7 +7067,7 @@
6932
7067
  index = serializeNumber(buffer, key, value, index, true);
6933
7068
  }
6934
7069
  else if (typeof value === 'bigint') {
6935
- throw new TypeError('Unsupported type BigInt, please use Decimal128');
7070
+ throw new BSONTypeError('Unsupported type BigInt, please use Decimal128');
6936
7071
  }
6937
7072
  else if (typeof value === 'boolean') {
6938
7073
  index = serializeBoolean(buffer, key, value, index, true);
@@ -6994,7 +7129,7 @@
6994
7129
  index = serializeMinMax(buffer, key, value, index, true);
6995
7130
  }
6996
7131
  else if (typeof value['_bsontype'] !== 'undefined') {
6997
- throw new TypeError('Unrecognized or invalid _bsontype: ' + value['_bsontype']);
7132
+ throw new BSONTypeError('Unrecognized or invalid _bsontype: ' + value['_bsontype']);
6998
7133
  }
6999
7134
  }
7000
7135
  }
@@ -7036,7 +7171,7 @@
7036
7171
  index = serializeNumber(buffer, key, value, index);
7037
7172
  }
7038
7173
  else if (type === 'bigint' || isBigInt64Array(value) || isBigUInt64Array(value)) {
7039
- throw new TypeError('Unsupported type BigInt, please use Decimal128');
7174
+ throw new BSONTypeError('Unsupported type BigInt, please use Decimal128');
7040
7175
  }
7041
7176
  else if (type === 'boolean') {
7042
7177
  index = serializeBoolean(buffer, key, value, index);
@@ -7093,7 +7228,7 @@
7093
7228
  index = serializeMinMax(buffer, key, value, index);
7094
7229
  }
7095
7230
  else if (typeof value['_bsontype'] !== 'undefined') {
7096
- throw new TypeError('Unrecognized or invalid _bsontype: ' + value['_bsontype']);
7231
+ throw new BSONTypeError('Unrecognized or invalid _bsontype: ' + value['_bsontype']);
7097
7232
  }
7098
7233
  }
7099
7234
  }
@@ -7101,10 +7236,10 @@
7101
7236
  // Did we provide a custom serialization method
7102
7237
  if (object.toBSON) {
7103
7238
  if (typeof object.toBSON !== 'function')
7104
- throw new TypeError('toBSON is not a function');
7239
+ throw new BSONTypeError('toBSON is not a function');
7105
7240
  object = object.toBSON();
7106
7241
  if (object != null && typeof object !== 'object')
7107
- throw new TypeError('toBSON function did not return an object');
7242
+ throw new BSONTypeError('toBSON function did not return an object');
7108
7243
  }
7109
7244
  // Iterate over all the keys
7110
7245
  for (var key in object) {
@@ -7112,7 +7247,7 @@
7112
7247
  // Is there an override value
7113
7248
  if (value && value.toBSON) {
7114
7249
  if (typeof value.toBSON !== 'function')
7115
- throw new TypeError('toBSON is not a function');
7250
+ throw new BSONTypeError('toBSON is not a function');
7116
7251
  value = value.toBSON();
7117
7252
  }
7118
7253
  // Check the type of the value
@@ -7140,7 +7275,7 @@
7140
7275
  index = serializeNumber(buffer, key, value, index);
7141
7276
  }
7142
7277
  else if (type === 'bigint') {
7143
- throw new TypeError('Unsupported type BigInt, please use Decimal128');
7278
+ throw new BSONTypeError('Unsupported type BigInt, please use Decimal128');
7144
7279
  }
7145
7280
  else if (type === 'boolean') {
7146
7281
  index = serializeBoolean(buffer, key, value, index);
@@ -7201,7 +7336,7 @@
7201
7336
  index = serializeMinMax(buffer, key, value, index);
7202
7337
  }
7203
7338
  else if (typeof value['_bsontype'] !== 'undefined') {
7204
- throw new TypeError('Unrecognized or invalid _bsontype: ' + value['_bsontype']);
7339
+ throw new BSONTypeError('Unrecognized or invalid _bsontype: ' + value['_bsontype']);
7205
7340
  }
7206
7341
  }
7207
7342
  }
@@ -7374,13 +7509,19 @@
7374
7509
  serializeWithBufferAndIndex: serializeWithBufferAndIndex,
7375
7510
  deserialize: deserialize,
7376
7511
  calculateObjectSize: calculateObjectSize,
7377
- deserializeStream: deserializeStream
7512
+ deserializeStream: deserializeStream,
7513
+ BSONError: BSONError,
7514
+ BSONTypeError: BSONTypeError
7378
7515
  };
7379
7516
 
7517
+ exports.BSONError = BSONError;
7380
7518
  exports.BSONRegExp = BSONRegExp;
7381
7519
  exports.BSONSymbol = BSONSymbol;
7520
+ exports.BSONTypeError = BSONTypeError;
7382
7521
  exports.BSON_BINARY_SUBTYPE_BYTE_ARRAY = BSON_BINARY_SUBTYPE_BYTE_ARRAY;
7522
+ exports.BSON_BINARY_SUBTYPE_COLUMN = BSON_BINARY_SUBTYPE_COLUMN;
7383
7523
  exports.BSON_BINARY_SUBTYPE_DEFAULT = BSON_BINARY_SUBTYPE_DEFAULT;
7524
+ exports.BSON_BINARY_SUBTYPE_ENCRYPTED = BSON_BINARY_SUBTYPE_ENCRYPTED;
7384
7525
  exports.BSON_BINARY_SUBTYPE_FUNCTION = BSON_BINARY_SUBTYPE_FUNCTION;
7385
7526
  exports.BSON_BINARY_SUBTYPE_MD5 = BSON_BINARY_SUBTYPE_MD5;
7386
7527
  exports.BSON_BINARY_SUBTYPE_USER_DEFINED = BSON_BINARY_SUBTYPE_USER_DEFINED;