bson 6.8.0 → 6.10.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.
package/lib/bson.cjs CHANGED
@@ -1,19 +1,45 @@
1
1
  'use strict';
2
2
 
3
+ const map = new WeakMap();
4
+ const TYPES = {
5
+ ArrayBuffer: '[object ArrayBuffer]',
6
+ SharedArrayBuffer: '[object SharedArrayBuffer]',
7
+ Uint8Array: '[object Uint8Array]',
8
+ BigInt64Array: '[object BigInt64Array]',
9
+ BigUint64Array: '[object BigUint64Array]',
10
+ RegExp: '[object RegExp]',
11
+ Map: '[object Map]',
12
+ Date: '[object Date]'
13
+ };
14
+ function getPrototypeString(value) {
15
+ let str = map.get(value);
16
+ if (!str) {
17
+ str = Object.prototype.toString.call(value);
18
+ if (value !== null && typeof value === 'object') {
19
+ map.set(value, str);
20
+ }
21
+ }
22
+ return str;
23
+ }
3
24
  function isAnyArrayBuffer(value) {
4
- return ['[object ArrayBuffer]', '[object SharedArrayBuffer]'].includes(Object.prototype.toString.call(value));
25
+ const type = getPrototypeString(value);
26
+ return type === TYPES.ArrayBuffer || type === TYPES.SharedArrayBuffer;
5
27
  }
6
28
  function isUint8Array(value) {
7
- return Object.prototype.toString.call(value) === '[object Uint8Array]';
29
+ const type = getPrototypeString(value);
30
+ return type === TYPES.Uint8Array;
8
31
  }
9
32
  function isRegExp(d) {
10
- return Object.prototype.toString.call(d) === '[object RegExp]';
33
+ const type = getPrototypeString(d);
34
+ return type === TYPES.RegExp;
11
35
  }
12
36
  function isMap(d) {
13
- return Object.prototype.toString.call(d) === '[object Map]';
37
+ const type = getPrototypeString(d);
38
+ return type === TYPES.Map;
14
39
  }
15
40
  function isDate(d) {
16
- return Object.prototype.toString.call(d) === '[object Date]';
41
+ const type = getPrototypeString(d);
42
+ return type === TYPES.Date;
17
43
  }
18
44
  function defaultInspect(x, _options) {
19
45
  return JSON.stringify(x, (k, v) => {
@@ -37,6 +63,7 @@ function getStylizeFunction(options) {
37
63
  }
38
64
 
39
65
  const BSON_MAJOR_VERSION = 6;
66
+ const BSON_VERSION_SYMBOL = Symbol.for('@@mdb.bson.version');
40
67
  const BSON_INT32_MAX = 0x7fffffff;
41
68
  const BSON_INT32_MIN = -0x80000000;
42
69
  const BSON_INT64_MAX = Math.pow(2, 63) - 1;
@@ -229,7 +256,7 @@ const nodeJsByteUtils = {
229
256
  stringTag === '[object SharedArrayBuffer]') {
230
257
  return Buffer.from(potentialBuffer);
231
258
  }
232
- throw new BSONError(`Cannot create Buffer from ${String(potentialBuffer)}`);
259
+ throw new BSONError(`Cannot create Buffer from the passed potentialBuffer.`);
233
260
  },
234
261
  allocate(size) {
235
262
  return Buffer.alloc(size);
@@ -287,7 +314,10 @@ const nodeJsByteUtils = {
287
314
  }
288
315
  return nodeJsByteUtils.toLocalBufferType(buffer).write(source, byteOffset, undefined, 'utf8');
289
316
  },
290
- randomBytes: nodejsRandomBytes
317
+ randomBytes: nodejsRandomBytes,
318
+ swap32(buffer) {
319
+ return nodeJsByteUtils.toLocalBufferType(buffer).swap32();
320
+ }
291
321
  };
292
322
 
293
323
  function isReactNative() {
@@ -332,7 +362,7 @@ const webByteUtils = {
332
362
  stringTag === '[object SharedArrayBuffer]') {
333
363
  return new Uint8Array(potentialUint8array);
334
364
  }
335
- throw new BSONError(`Cannot make a Uint8Array from ${String(potentialUint8array)}`);
365
+ throw new BSONError(`Cannot make a Uint8Array from passed potentialBuffer.`);
336
366
  },
337
367
  allocate(size) {
338
368
  if (typeof size !== 'number') {
@@ -404,14 +434,30 @@ const webByteUtils = {
404
434
  uint8array.set(bytes, byteOffset);
405
435
  return bytes.byteLength;
406
436
  },
407
- randomBytes: webRandomBytes
437
+ randomBytes: webRandomBytes,
438
+ swap32(buffer) {
439
+ if (buffer.length % 4 !== 0) {
440
+ throw new RangeError('Buffer size must be a multiple of 32-bits');
441
+ }
442
+ for (let i = 0; i < buffer.length; i += 4) {
443
+ const byte0 = buffer[i];
444
+ const byte1 = buffer[i + 1];
445
+ const byte2 = buffer[i + 2];
446
+ const byte3 = buffer[i + 3];
447
+ buffer[i] = byte3;
448
+ buffer[i + 1] = byte2;
449
+ buffer[i + 2] = byte1;
450
+ buffer[i + 3] = byte0;
451
+ }
452
+ return buffer;
453
+ }
408
454
  };
409
455
 
410
456
  const hasGlobalBuffer = typeof Buffer === 'function' && Buffer.prototype?._isBuffer !== true;
411
457
  const ByteUtils = hasGlobalBuffer ? nodeJsByteUtils : webByteUtils;
412
458
 
413
459
  class BSONValue {
414
- get [Symbol.for('@@mdb.bson.version')]() {
460
+ get [BSON_VERSION_SYMBOL]() {
415
461
  return BSON_MAJOR_VERSION;
416
462
  }
417
463
  [Symbol.for('nodejs.util.inspect.custom')](depth, options, inspect) {
@@ -419,6 +465,134 @@ class BSONValue {
419
465
  }
420
466
  }
421
467
 
468
+ const FLOAT = new Float64Array(1);
469
+ const FLOAT_BYTES = new Uint8Array(FLOAT.buffer, 0, 8);
470
+ FLOAT[0] = -1;
471
+ const isBigEndian = FLOAT_BYTES[7] === 0;
472
+ const NumberUtils = {
473
+ isBigEndian,
474
+ getNonnegativeInt32LE(source, offset) {
475
+ if (source[offset + 3] > 127) {
476
+ throw new RangeError(`Size cannot be negative at offset: ${offset}`);
477
+ }
478
+ return (source[offset] |
479
+ (source[offset + 1] << 8) |
480
+ (source[offset + 2] << 16) |
481
+ (source[offset + 3] << 24));
482
+ },
483
+ getInt32LE(source, offset) {
484
+ return (source[offset] |
485
+ (source[offset + 1] << 8) |
486
+ (source[offset + 2] << 16) |
487
+ (source[offset + 3] << 24));
488
+ },
489
+ getUint32LE(source, offset) {
490
+ return (source[offset] +
491
+ source[offset + 1] * 256 +
492
+ source[offset + 2] * 65536 +
493
+ source[offset + 3] * 16777216);
494
+ },
495
+ getUint32BE(source, offset) {
496
+ return (source[offset + 3] +
497
+ source[offset + 2] * 256 +
498
+ source[offset + 1] * 65536 +
499
+ source[offset] * 16777216);
500
+ },
501
+ getBigInt64LE(source, offset) {
502
+ const lo = NumberUtils.getUint32LE(source, offset);
503
+ const hi = NumberUtils.getUint32LE(source, offset + 4);
504
+ return (BigInt(hi) << BigInt(32)) + BigInt(lo);
505
+ },
506
+ getFloat64LE: isBigEndian
507
+ ? (source, offset) => {
508
+ FLOAT_BYTES[7] = source[offset];
509
+ FLOAT_BYTES[6] = source[offset + 1];
510
+ FLOAT_BYTES[5] = source[offset + 2];
511
+ FLOAT_BYTES[4] = source[offset + 3];
512
+ FLOAT_BYTES[3] = source[offset + 4];
513
+ FLOAT_BYTES[2] = source[offset + 5];
514
+ FLOAT_BYTES[1] = source[offset + 6];
515
+ FLOAT_BYTES[0] = source[offset + 7];
516
+ return FLOAT[0];
517
+ }
518
+ : (source, offset) => {
519
+ FLOAT_BYTES[0] = source[offset];
520
+ FLOAT_BYTES[1] = source[offset + 1];
521
+ FLOAT_BYTES[2] = source[offset + 2];
522
+ FLOAT_BYTES[3] = source[offset + 3];
523
+ FLOAT_BYTES[4] = source[offset + 4];
524
+ FLOAT_BYTES[5] = source[offset + 5];
525
+ FLOAT_BYTES[6] = source[offset + 6];
526
+ FLOAT_BYTES[7] = source[offset + 7];
527
+ return FLOAT[0];
528
+ },
529
+ setInt32BE(destination, offset, value) {
530
+ destination[offset + 3] = value;
531
+ value >>>= 8;
532
+ destination[offset + 2] = value;
533
+ value >>>= 8;
534
+ destination[offset + 1] = value;
535
+ value >>>= 8;
536
+ destination[offset] = value;
537
+ return 4;
538
+ },
539
+ setInt32LE(destination, offset, value) {
540
+ destination[offset] = value;
541
+ value >>>= 8;
542
+ destination[offset + 1] = value;
543
+ value >>>= 8;
544
+ destination[offset + 2] = value;
545
+ value >>>= 8;
546
+ destination[offset + 3] = value;
547
+ return 4;
548
+ },
549
+ setBigInt64LE(destination, offset, value) {
550
+ const mask32bits = BigInt(0xffff_ffff);
551
+ let lo = Number(value & mask32bits);
552
+ destination[offset] = lo;
553
+ lo >>= 8;
554
+ destination[offset + 1] = lo;
555
+ lo >>= 8;
556
+ destination[offset + 2] = lo;
557
+ lo >>= 8;
558
+ destination[offset + 3] = lo;
559
+ let hi = Number((value >> BigInt(32)) & mask32bits);
560
+ destination[offset + 4] = hi;
561
+ hi >>= 8;
562
+ destination[offset + 5] = hi;
563
+ hi >>= 8;
564
+ destination[offset + 6] = hi;
565
+ hi >>= 8;
566
+ destination[offset + 7] = hi;
567
+ return 8;
568
+ },
569
+ setFloat64LE: isBigEndian
570
+ ? (destination, offset, value) => {
571
+ FLOAT[0] = value;
572
+ destination[offset] = FLOAT_BYTES[7];
573
+ destination[offset + 1] = FLOAT_BYTES[6];
574
+ destination[offset + 2] = FLOAT_BYTES[5];
575
+ destination[offset + 3] = FLOAT_BYTES[4];
576
+ destination[offset + 4] = FLOAT_BYTES[3];
577
+ destination[offset + 5] = FLOAT_BYTES[2];
578
+ destination[offset + 6] = FLOAT_BYTES[1];
579
+ destination[offset + 7] = FLOAT_BYTES[0];
580
+ return 8;
581
+ }
582
+ : (destination, offset, value) => {
583
+ FLOAT[0] = value;
584
+ destination[offset] = FLOAT_BYTES[0];
585
+ destination[offset + 1] = FLOAT_BYTES[1];
586
+ destination[offset + 2] = FLOAT_BYTES[2];
587
+ destination[offset + 3] = FLOAT_BYTES[3];
588
+ destination[offset + 4] = FLOAT_BYTES[4];
589
+ destination[offset + 5] = FLOAT_BYTES[5];
590
+ destination[offset + 6] = FLOAT_BYTES[6];
591
+ destination[offset + 7] = FLOAT_BYTES[7];
592
+ return 8;
593
+ }
594
+ };
595
+
422
596
  class Binary extends BSONValue {
423
597
  get _bsontype() {
424
598
  return 'Binary';
@@ -491,7 +665,8 @@ class Binary extends BSONValue {
491
665
  }
492
666
  read(position, length) {
493
667
  length = length && length > 0 ? length : this.position;
494
- return this.buffer.slice(position, position + length);
668
+ const end = position + length;
669
+ return this.buffer.subarray(position, end > this.position ? this.position : end);
495
670
  }
496
671
  value() {
497
672
  return this.buffer.length === this.position
@@ -515,6 +690,9 @@ class Binary extends BSONValue {
515
690
  }
516
691
  toExtendedJSON(options) {
517
692
  options = options || {};
693
+ if (this.sub_type === Binary.SUBTYPE_VECTOR) {
694
+ validateBinaryVector(this);
695
+ }
518
696
  const base64String = ByteUtils.toBase64(this.buffer);
519
697
  const subType = Number(this.sub_type).toString(16);
520
698
  if (options.legacy) {
@@ -532,7 +710,7 @@ class Binary extends BSONValue {
532
710
  }
533
711
  toUUID() {
534
712
  if (this.sub_type === Binary.SUBTYPE_UUID) {
535
- return new UUID(this.buffer.slice(0, this.position));
713
+ return new UUID(this.buffer.subarray(0, this.position));
536
714
  }
537
715
  throw new BSONError(`Binary sub_type "${this.sub_type}" is not supported for converting to UUID. Only "${Binary.SUBTYPE_UUID}" is currently supported.`);
538
716
  }
@@ -574,6 +752,99 @@ class Binary extends BSONValue {
574
752
  const subTypeArg = inspect(this.sub_type, options);
575
753
  return `Binary.createFromBase64(${base64Arg}, ${subTypeArg})`;
576
754
  }
755
+ toInt8Array() {
756
+ if (this.sub_type !== Binary.SUBTYPE_VECTOR) {
757
+ throw new BSONError('Binary sub_type is not Vector');
758
+ }
759
+ if (this.buffer[0] !== Binary.VECTOR_TYPE.Int8) {
760
+ throw new BSONError('Binary datatype field is not Int8');
761
+ }
762
+ return new Int8Array(this.buffer.buffer.slice(this.buffer.byteOffset + 2, this.buffer.byteOffset + this.position));
763
+ }
764
+ toFloat32Array() {
765
+ if (this.sub_type !== Binary.SUBTYPE_VECTOR) {
766
+ throw new BSONError('Binary sub_type is not Vector');
767
+ }
768
+ if (this.buffer[0] !== Binary.VECTOR_TYPE.Float32) {
769
+ throw new BSONError('Binary datatype field is not Float32');
770
+ }
771
+ const floatBytes = new Uint8Array(this.buffer.buffer.slice(this.buffer.byteOffset + 2, this.buffer.byteOffset + this.position));
772
+ if (NumberUtils.isBigEndian)
773
+ ByteUtils.swap32(floatBytes);
774
+ return new Float32Array(floatBytes.buffer);
775
+ }
776
+ toPackedBits() {
777
+ if (this.sub_type !== Binary.SUBTYPE_VECTOR) {
778
+ throw new BSONError('Binary sub_type is not Vector');
779
+ }
780
+ if (this.buffer[0] !== Binary.VECTOR_TYPE.PackedBit) {
781
+ throw new BSONError('Binary datatype field is not packed bit');
782
+ }
783
+ return new Uint8Array(this.buffer.buffer.slice(this.buffer.byteOffset + 2, this.buffer.byteOffset + this.position));
784
+ }
785
+ toBits() {
786
+ if (this.sub_type !== Binary.SUBTYPE_VECTOR) {
787
+ throw new BSONError('Binary sub_type is not Vector');
788
+ }
789
+ if (this.buffer[0] !== Binary.VECTOR_TYPE.PackedBit) {
790
+ throw new BSONError('Binary datatype field is not packed bit');
791
+ }
792
+ const byteCount = this.length() - 2;
793
+ const bitCount = byteCount * 8 - this.buffer[1];
794
+ const bits = new Int8Array(bitCount);
795
+ for (let bitOffset = 0; bitOffset < bits.length; bitOffset++) {
796
+ const byteOffset = (bitOffset / 8) | 0;
797
+ const byte = this.buffer[byteOffset + 2];
798
+ const shift = 7 - (bitOffset % 8);
799
+ const bit = (byte >> shift) & 1;
800
+ bits[bitOffset] = bit;
801
+ }
802
+ return bits;
803
+ }
804
+ static fromInt8Array(array) {
805
+ const buffer = ByteUtils.allocate(array.byteLength + 2);
806
+ buffer[0] = Binary.VECTOR_TYPE.Int8;
807
+ buffer[1] = 0;
808
+ const intBytes = new Uint8Array(array.buffer, array.byteOffset, array.byteLength);
809
+ buffer.set(intBytes, 2);
810
+ return new this(buffer, this.SUBTYPE_VECTOR);
811
+ }
812
+ static fromFloat32Array(array) {
813
+ const binaryBytes = ByteUtils.allocate(array.byteLength + 2);
814
+ binaryBytes[0] = Binary.VECTOR_TYPE.Float32;
815
+ binaryBytes[1] = 0;
816
+ const floatBytes = new Uint8Array(array.buffer, array.byteOffset, array.byteLength);
817
+ binaryBytes.set(floatBytes, 2);
818
+ if (NumberUtils.isBigEndian)
819
+ ByteUtils.swap32(new Uint8Array(binaryBytes.buffer, 2));
820
+ return new this(binaryBytes, this.SUBTYPE_VECTOR);
821
+ }
822
+ static fromPackedBits(array, padding = 0) {
823
+ const buffer = ByteUtils.allocate(array.byteLength + 2);
824
+ buffer[0] = Binary.VECTOR_TYPE.PackedBit;
825
+ buffer[1] = padding;
826
+ buffer.set(array, 2);
827
+ return new this(buffer, this.SUBTYPE_VECTOR);
828
+ }
829
+ static fromBits(bits) {
830
+ const byteLength = (bits.length + 7) >>> 3;
831
+ const bytes = new Uint8Array(byteLength + 2);
832
+ bytes[0] = Binary.VECTOR_TYPE.PackedBit;
833
+ const remainder = bits.length % 8;
834
+ bytes[1] = remainder === 0 ? 0 : 8 - remainder;
835
+ for (let bitOffset = 0; bitOffset < bits.length; bitOffset++) {
836
+ const byteOffset = bitOffset >>> 3;
837
+ const bit = bits[bitOffset];
838
+ if (bit !== 0 && bit !== 1) {
839
+ throw new BSONError(`Invalid bit value at ${bitOffset}: must be 0 or 1, found ${bits[bitOffset]}`);
840
+ }
841
+ if (bit === 0)
842
+ continue;
843
+ const shift = 7 - (bitOffset % 8);
844
+ bytes[byteOffset + 2] |= bit << shift;
845
+ }
846
+ return new this(bytes, Binary.SUBTYPE_VECTOR);
847
+ }
577
848
  }
578
849
  Binary.BSON_BINARY_SUBTYPE_DEFAULT = 0;
579
850
  Binary.BUFFER_SIZE = 256;
@@ -586,7 +857,30 @@ Binary.SUBTYPE_MD5 = 5;
586
857
  Binary.SUBTYPE_ENCRYPTED = 6;
587
858
  Binary.SUBTYPE_COLUMN = 7;
588
859
  Binary.SUBTYPE_SENSITIVE = 8;
860
+ Binary.SUBTYPE_VECTOR = 9;
589
861
  Binary.SUBTYPE_USER_DEFINED = 128;
862
+ Binary.VECTOR_TYPE = Object.freeze({
863
+ Int8: 0x03,
864
+ Float32: 0x27,
865
+ PackedBit: 0x10
866
+ });
867
+ function validateBinaryVector(vector) {
868
+ if (vector.sub_type !== Binary.SUBTYPE_VECTOR)
869
+ return;
870
+ const size = vector.position;
871
+ const datatype = vector.buffer[0];
872
+ const padding = vector.buffer[1];
873
+ if ((datatype === Binary.VECTOR_TYPE.Float32 || datatype === Binary.VECTOR_TYPE.Int8) &&
874
+ padding !== 0) {
875
+ throw new BSONError('Invalid Vector: padding must be zero for int8 and float32 vectors');
876
+ }
877
+ if (datatype === Binary.VECTOR_TYPE.PackedBit && padding !== 0 && size === 2) {
878
+ throw new BSONError('Invalid Vector: padding must be zero for packed bit vectors that are empty');
879
+ }
880
+ if (datatype === Binary.VECTOR_TYPE.PackedBit && padding > 7) {
881
+ throw new BSONError(`Invalid Vector: padding must be a value between 0 and 7. found: ${padding}`);
882
+ }
883
+ }
590
884
  const UUID_BYTE_LENGTH = 16;
591
885
  const UUID_WITHOUT_DASHES = /^[0-9A-F]{32}$/i;
592
886
  const UUID_WITH_DASHES = /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i;
@@ -1588,7 +1882,7 @@ class Decimal128 extends BSONValue {
1588
1882
  if (typeof bytes === 'string') {
1589
1883
  this.bytes = Decimal128.fromString(bytes).bytes;
1590
1884
  }
1591
- else if (isUint8Array(bytes)) {
1885
+ else if (bytes instanceof Uint8Array || isUint8Array(bytes)) {
1592
1886
  if (bytes.byteLength !== 16) {
1593
1887
  throw new BSONError('Decimal128 must take a Buffer of 16 bytes');
1594
1888
  }
@@ -2198,134 +2492,6 @@ class MinKey extends BSONValue {
2198
2492
  }
2199
2493
  }
2200
2494
 
2201
- const FLOAT = new Float64Array(1);
2202
- const FLOAT_BYTES = new Uint8Array(FLOAT.buffer, 0, 8);
2203
- FLOAT[0] = -1;
2204
- const isBigEndian = FLOAT_BYTES[7] === 0;
2205
- const NumberUtils = {
2206
- getNonnegativeInt32LE(source, offset) {
2207
- if (source[offset + 3] > 127) {
2208
- throw new RangeError(`Size cannot be negative at offset: ${offset}`);
2209
- }
2210
- return (source[offset] |
2211
- (source[offset + 1] << 8) |
2212
- (source[offset + 2] << 16) |
2213
- (source[offset + 3] << 24));
2214
- },
2215
- getInt32LE(source, offset) {
2216
- return (source[offset] |
2217
- (source[offset + 1] << 8) |
2218
- (source[offset + 2] << 16) |
2219
- (source[offset + 3] << 24));
2220
- },
2221
- getUint32LE(source, offset) {
2222
- return (source[offset] +
2223
- source[offset + 1] * 256 +
2224
- source[offset + 2] * 65536 +
2225
- source[offset + 3] * 16777216);
2226
- },
2227
- getUint32BE(source, offset) {
2228
- return (source[offset + 3] +
2229
- source[offset + 2] * 256 +
2230
- source[offset + 1] * 65536 +
2231
- source[offset] * 16777216);
2232
- },
2233
- getBigInt64LE(source, offset) {
2234
- const lo = NumberUtils.getUint32LE(source, offset);
2235
- const hi = NumberUtils.getUint32LE(source, offset + 4);
2236
- return (BigInt(hi) << BigInt(32)) + BigInt(lo);
2237
- },
2238
- getFloat64LE: isBigEndian
2239
- ? (source, offset) => {
2240
- FLOAT_BYTES[7] = source[offset];
2241
- FLOAT_BYTES[6] = source[offset + 1];
2242
- FLOAT_BYTES[5] = source[offset + 2];
2243
- FLOAT_BYTES[4] = source[offset + 3];
2244
- FLOAT_BYTES[3] = source[offset + 4];
2245
- FLOAT_BYTES[2] = source[offset + 5];
2246
- FLOAT_BYTES[1] = source[offset + 6];
2247
- FLOAT_BYTES[0] = source[offset + 7];
2248
- return FLOAT[0];
2249
- }
2250
- : (source, offset) => {
2251
- FLOAT_BYTES[0] = source[offset];
2252
- FLOAT_BYTES[1] = source[offset + 1];
2253
- FLOAT_BYTES[2] = source[offset + 2];
2254
- FLOAT_BYTES[3] = source[offset + 3];
2255
- FLOAT_BYTES[4] = source[offset + 4];
2256
- FLOAT_BYTES[5] = source[offset + 5];
2257
- FLOAT_BYTES[6] = source[offset + 6];
2258
- FLOAT_BYTES[7] = source[offset + 7];
2259
- return FLOAT[0];
2260
- },
2261
- setInt32BE(destination, offset, value) {
2262
- destination[offset + 3] = value;
2263
- value >>>= 8;
2264
- destination[offset + 2] = value;
2265
- value >>>= 8;
2266
- destination[offset + 1] = value;
2267
- value >>>= 8;
2268
- destination[offset] = value;
2269
- return 4;
2270
- },
2271
- setInt32LE(destination, offset, value) {
2272
- destination[offset] = value;
2273
- value >>>= 8;
2274
- destination[offset + 1] = value;
2275
- value >>>= 8;
2276
- destination[offset + 2] = value;
2277
- value >>>= 8;
2278
- destination[offset + 3] = value;
2279
- return 4;
2280
- },
2281
- setBigInt64LE(destination, offset, value) {
2282
- const mask32bits = BigInt(4294967295);
2283
- let lo = Number(value & mask32bits);
2284
- destination[offset] = lo;
2285
- lo >>= 8;
2286
- destination[offset + 1] = lo;
2287
- lo >>= 8;
2288
- destination[offset + 2] = lo;
2289
- lo >>= 8;
2290
- destination[offset + 3] = lo;
2291
- let hi = Number((value >> BigInt(32)) & mask32bits);
2292
- destination[offset + 4] = hi;
2293
- hi >>= 8;
2294
- destination[offset + 5] = hi;
2295
- hi >>= 8;
2296
- destination[offset + 6] = hi;
2297
- hi >>= 8;
2298
- destination[offset + 7] = hi;
2299
- return 8;
2300
- },
2301
- setFloat64LE: isBigEndian
2302
- ? (destination, offset, value) => {
2303
- FLOAT[0] = value;
2304
- destination[offset] = FLOAT_BYTES[7];
2305
- destination[offset + 1] = FLOAT_BYTES[6];
2306
- destination[offset + 2] = FLOAT_BYTES[5];
2307
- destination[offset + 3] = FLOAT_BYTES[4];
2308
- destination[offset + 4] = FLOAT_BYTES[3];
2309
- destination[offset + 5] = FLOAT_BYTES[2];
2310
- destination[offset + 6] = FLOAT_BYTES[1];
2311
- destination[offset + 7] = FLOAT_BYTES[0];
2312
- return 8;
2313
- }
2314
- : (destination, offset, value) => {
2315
- FLOAT[0] = value;
2316
- destination[offset] = FLOAT_BYTES[0];
2317
- destination[offset + 1] = FLOAT_BYTES[1];
2318
- destination[offset + 2] = FLOAT_BYTES[2];
2319
- destination[offset + 3] = FLOAT_BYTES[3];
2320
- destination[offset + 4] = FLOAT_BYTES[4];
2321
- destination[offset + 5] = FLOAT_BYTES[5];
2322
- destination[offset + 6] = FLOAT_BYTES[6];
2323
- destination[offset + 7] = FLOAT_BYTES[7];
2324
- return 8;
2325
- }
2326
- };
2327
-
2328
- const checkForHexRegExp = new RegExp('^[0-9a-fA-F]{24}$');
2329
2495
  let PROCESS_UNIQUE = null;
2330
2496
  class ObjectId extends BSONValue {
2331
2497
  get _bsontype() {
@@ -2355,7 +2521,7 @@ class ObjectId extends BSONValue {
2355
2521
  this.buffer = ByteUtils.toLocalBufferType(workingId);
2356
2522
  }
2357
2523
  else if (typeof workingId === 'string') {
2358
- if (workingId.length === 24 && checkForHexRegExp.test(workingId)) {
2524
+ if (ObjectId.validateHexString(workingId)) {
2359
2525
  this.buffer = ByteUtils.fromHex(workingId);
2360
2526
  }
2361
2527
  else {
@@ -2378,6 +2544,20 @@ class ObjectId extends BSONValue {
2378
2544
  this.__id = ByteUtils.toHex(value);
2379
2545
  }
2380
2546
  }
2547
+ static validateHexString(string) {
2548
+ if (string?.length !== 24)
2549
+ return false;
2550
+ for (let i = 0; i < 24; i++) {
2551
+ const char = string.charCodeAt(i);
2552
+ if ((char >= 48 && char <= 57) ||
2553
+ (char >= 97 && char <= 102) ||
2554
+ (char >= 65 && char <= 70)) {
2555
+ continue;
2556
+ }
2557
+ return false;
2558
+ }
2559
+ return true;
2560
+ }
2381
2561
  toHexString() {
2382
2562
  if (ObjectId.cacheHexString && this.__id) {
2383
2563
  return this.__id;
@@ -2490,6 +2670,8 @@ class ObjectId extends BSONValue {
2490
2670
  static isValid(id) {
2491
2671
  if (id == null)
2492
2672
  return false;
2673
+ if (typeof id === 'string')
2674
+ return ObjectId.validateHexString(id);
2493
2675
  try {
2494
2676
  new ObjectId(id);
2495
2677
  return true;
@@ -2560,7 +2742,7 @@ function calculateElement(name, value, serializeFunctions = false, isArray = fal
2560
2742
  case 'object':
2561
2743
  if (value != null &&
2562
2744
  typeof value._bsontype === 'string' &&
2563
- value[Symbol.for('@@mdb.bson.version')] !== BSON_MAJOR_VERSION) {
2745
+ value[BSON_VERSION_SYMBOL] !== BSON_MAJOR_VERSION) {
2564
2746
  throw new BSONVersionError();
2565
2747
  }
2566
2748
  else if (value == null || value._bsontype === 'MinKey' || value._bsontype === 'MaxKey') {
@@ -2764,6 +2946,12 @@ class Timestamp extends LongWithoutOverridesClass {
2764
2946
  get _bsontype() {
2765
2947
  return 'Timestamp';
2766
2948
  }
2949
+ get i() {
2950
+ return this.low >>> 0;
2951
+ }
2952
+ get t() {
2953
+ return this.high >>> 0;
2954
+ }
2767
2955
  constructor(low) {
2768
2956
  if (low == null) {
2769
2957
  super(0, 0, true);
@@ -2789,10 +2977,10 @@ class Timestamp extends LongWithoutOverridesClass {
2789
2977
  if (i < 0 || Number.isNaN(i)) {
2790
2978
  throw new BSONError('Timestamp constructed from { t, i } must provide a positive i');
2791
2979
  }
2792
- if (t > 4294967295) {
2980
+ if (t > 0xffff_ffff) {
2793
2981
  throw new BSONError('Timestamp constructed from { t, i } must provide t equal or less than uint32 max');
2794
2982
  }
2795
- if (i > 4294967295) {
2983
+ if (i > 0xffff_ffff) {
2796
2984
  throw new BSONError('Timestamp constructed from { t, i } must provide i equal or less than uint32 max');
2797
2985
  }
2798
2986
  super(i, t, true);
@@ -2819,7 +3007,7 @@ class Timestamp extends LongWithoutOverridesClass {
2819
3007
  return new Timestamp(Long.fromString(str, true, optRadix));
2820
3008
  }
2821
3009
  toExtendedJSON() {
2822
- return { $timestamp: { t: this.high >>> 0, i: this.low >>> 0 } };
3010
+ return { $timestamp: { t: this.t, i: this.i } };
2823
3011
  }
2824
3012
  static fromExtendedJSON(doc) {
2825
3013
  const i = Long.isLong(doc.$timestamp.i)
@@ -2832,8 +3020,8 @@ class Timestamp extends LongWithoutOverridesClass {
2832
3020
  }
2833
3021
  inspect(depth, options, inspect) {
2834
3022
  inspect ??= defaultInspect;
2835
- const t = inspect(this.high >>> 0, options);
2836
- const i = inspect(this.low >>> 0, options);
3023
+ const t = inspect(this.t, options);
3024
+ const i = inspect(this.i, options);
2837
3025
  return `new Timestamp({ t: ${t}, i: ${i} })`;
2838
3026
  }
2839
3027
  }
@@ -2990,7 +3178,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2990
3178
  if (objectSize <= 0 || objectSize > buffer.length - index)
2991
3179
  throw new BSONError('bad embedded document length in bson');
2992
3180
  if (raw) {
2993
- value = buffer.slice(index, index + objectSize);
3181
+ value = buffer.subarray(index, index + objectSize);
2994
3182
  }
2995
3183
  else {
2996
3184
  let objectOptions = options;
@@ -3062,49 +3250,23 @@ function deserializeObject(buffer, index, options, isArray = false) {
3062
3250
  throw new BSONError('Negative binary type element size found');
3063
3251
  if (binarySize > buffer.byteLength)
3064
3252
  throw new BSONError('Binary type size larger than document size');
3065
- if (buffer['slice'] != null) {
3066
- if (subType === Binary.SUBTYPE_BYTE_ARRAY) {
3067
- binarySize = NumberUtils.getInt32LE(buffer, index);
3068
- index += 4;
3069
- if (binarySize < 0)
3070
- throw new BSONError('Negative binary type element size found for subtype 0x02');
3071
- if (binarySize > totalBinarySize - 4)
3072
- throw new BSONError('Binary type with subtype 0x02 contains too long binary size');
3073
- if (binarySize < totalBinarySize - 4)
3074
- throw new BSONError('Binary type with subtype 0x02 contains too short binary size');
3075
- }
3076
- if (promoteBuffers && promoteValues) {
3077
- value = ByteUtils.toLocalBufferType(buffer.slice(index, index + binarySize));
3078
- }
3079
- else {
3080
- value = new Binary(buffer.slice(index, index + binarySize), subType);
3081
- if (subType === BSON_BINARY_SUBTYPE_UUID_NEW && UUID.isValid(value)) {
3082
- value = value.toUUID();
3083
- }
3084
- }
3253
+ if (subType === Binary.SUBTYPE_BYTE_ARRAY) {
3254
+ binarySize = NumberUtils.getInt32LE(buffer, index);
3255
+ index += 4;
3256
+ if (binarySize < 0)
3257
+ throw new BSONError('Negative binary type element size found for subtype 0x02');
3258
+ if (binarySize > totalBinarySize - 4)
3259
+ throw new BSONError('Binary type with subtype 0x02 contains too long binary size');
3260
+ if (binarySize < totalBinarySize - 4)
3261
+ throw new BSONError('Binary type with subtype 0x02 contains too short binary size');
3262
+ }
3263
+ if (promoteBuffers && promoteValues) {
3264
+ value = ByteUtils.toLocalBufferType(buffer.subarray(index, index + binarySize));
3085
3265
  }
3086
3266
  else {
3087
- if (subType === Binary.SUBTYPE_BYTE_ARRAY) {
3088
- binarySize = NumberUtils.getInt32LE(buffer, index);
3089
- index += 4;
3090
- if (binarySize < 0)
3091
- throw new BSONError('Negative binary type element size found for subtype 0x02');
3092
- if (binarySize > totalBinarySize - 4)
3093
- throw new BSONError('Binary type with subtype 0x02 contains too long binary size');
3094
- if (binarySize < totalBinarySize - 4)
3095
- throw new BSONError('Binary type with subtype 0x02 contains too short binary size');
3096
- }
3097
- if (promoteBuffers && promoteValues) {
3098
- value = ByteUtils.allocateUnsafe(binarySize);
3099
- for (i = 0; i < binarySize; i++) {
3100
- value[i] = buffer[index + i];
3101
- }
3102
- }
3103
- else {
3104
- value = new Binary(buffer.slice(index, index + binarySize), subType);
3105
- if (subType === BSON_BINARY_SUBTYPE_UUID_NEW && UUID.isValid(value)) {
3106
- value = value.toUUID();
3107
- }
3267
+ value = new Binary(buffer.subarray(index, index + binarySize), subType);
3268
+ if (subType === BSON_BINARY_SUBTYPE_UUID_NEW && UUID.isValid(value)) {
3269
+ value = value.toUUID();
3108
3270
  }
3109
3271
  }
3110
3272
  index = index + binarySize;
@@ -3526,6 +3688,9 @@ function serializeBinary(buffer, key, value, index) {
3526
3688
  size = size - 4;
3527
3689
  index += NumberUtils.setInt32LE(buffer, index, size);
3528
3690
  }
3691
+ if (value.sub_type === Binary.SUBTYPE_VECTOR) {
3692
+ validateBinaryVector(value);
3693
+ }
3529
3694
  if (size <= 16) {
3530
3695
  for (let i = 0; i < size; i++)
3531
3696
  buffer[index + i] = data[i];
@@ -3602,79 +3767,83 @@ function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializ
3602
3767
  if (typeof value?.toBSON === 'function') {
3603
3768
  value = value.toBSON();
3604
3769
  }
3605
- if (typeof value === 'string') {
3606
- index = serializeString(buffer, key, value, index);
3607
- }
3608
- else if (typeof value === 'number') {
3609
- index = serializeNumber(buffer, key, value, index);
3610
- }
3611
- else if (typeof value === 'bigint') {
3612
- index = serializeBigInt(buffer, key, value, index);
3613
- }
3614
- else if (typeof value === 'boolean') {
3615
- index = serializeBoolean(buffer, key, value, index);
3616
- }
3617
- else if (value instanceof Date || isDate(value)) {
3618
- index = serializeDate(buffer, key, value, index);
3619
- }
3620
- else if (value === undefined) {
3770
+ const type = typeof value;
3771
+ if (value === undefined) {
3621
3772
  index = serializeNull(buffer, key, value, index);
3622
3773
  }
3623
3774
  else if (value === null) {
3624
3775
  index = serializeNull(buffer, key, value, index);
3625
3776
  }
3626
- else if (isUint8Array(value)) {
3627
- index = serializeBuffer(buffer, key, value, index);
3628
- }
3629
- else if (value instanceof RegExp || isRegExp(value)) {
3630
- index = serializeRegExp(buffer, key, value, index);
3631
- }
3632
- else if (typeof value === 'object' && value._bsontype == null) {
3633
- index = serializeObject(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, path);
3777
+ else if (type === 'string') {
3778
+ index = serializeString(buffer, key, value, index);
3634
3779
  }
3635
- else if (typeof value === 'object' &&
3636
- value[Symbol.for('@@mdb.bson.version')] !== BSON_MAJOR_VERSION) {
3637
- throw new BSONVersionError();
3780
+ else if (type === 'number') {
3781
+ index = serializeNumber(buffer, key, value, index);
3638
3782
  }
3639
- else if (value._bsontype === 'ObjectId') {
3640
- index = serializeObjectId(buffer, key, value, index);
3783
+ else if (type === 'bigint') {
3784
+ index = serializeBigInt(buffer, key, value, index);
3641
3785
  }
3642
- else if (value._bsontype === 'Decimal128') {
3643
- index = serializeDecimal128(buffer, key, value, index);
3786
+ else if (type === 'boolean') {
3787
+ index = serializeBoolean(buffer, key, value, index);
3644
3788
  }
3645
- else if (value._bsontype === 'Long' || value._bsontype === 'Timestamp') {
3646
- index = serializeLong(buffer, key, value, index);
3789
+ else if (type === 'object' && value._bsontype == null) {
3790
+ if (value instanceof Date || isDate(value)) {
3791
+ index = serializeDate(buffer, key, value, index);
3792
+ }
3793
+ else if (value instanceof Uint8Array || isUint8Array(value)) {
3794
+ index = serializeBuffer(buffer, key, value, index);
3795
+ }
3796
+ else if (value instanceof RegExp || isRegExp(value)) {
3797
+ index = serializeRegExp(buffer, key, value, index);
3798
+ }
3799
+ else {
3800
+ index = serializeObject(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, path);
3801
+ }
3647
3802
  }
3648
- else if (value._bsontype === 'Double') {
3649
- index = serializeDouble(buffer, key, value, index);
3803
+ else if (type === 'object') {
3804
+ if (value[BSON_VERSION_SYMBOL] !== BSON_MAJOR_VERSION) {
3805
+ throw new BSONVersionError();
3806
+ }
3807
+ else if (value._bsontype === 'ObjectId') {
3808
+ index = serializeObjectId(buffer, key, value, index);
3809
+ }
3810
+ else if (value._bsontype === 'Decimal128') {
3811
+ index = serializeDecimal128(buffer, key, value, index);
3812
+ }
3813
+ else if (value._bsontype === 'Long' || value._bsontype === 'Timestamp') {
3814
+ index = serializeLong(buffer, key, value, index);
3815
+ }
3816
+ else if (value._bsontype === 'Double') {
3817
+ index = serializeDouble(buffer, key, value, index);
3818
+ }
3819
+ else if (value._bsontype === 'Code') {
3820
+ index = serializeCode(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, path);
3821
+ }
3822
+ else if (value._bsontype === 'Binary') {
3823
+ index = serializeBinary(buffer, key, value, index);
3824
+ }
3825
+ else if (value._bsontype === 'BSONSymbol') {
3826
+ index = serializeSymbol(buffer, key, value, index);
3827
+ }
3828
+ else if (value._bsontype === 'DBRef') {
3829
+ index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions, path);
3830
+ }
3831
+ else if (value._bsontype === 'BSONRegExp') {
3832
+ index = serializeBSONRegExp(buffer, key, value, index);
3833
+ }
3834
+ else if (value._bsontype === 'Int32') {
3835
+ index = serializeInt32(buffer, key, value, index);
3836
+ }
3837
+ else if (value._bsontype === 'MinKey' || value._bsontype === 'MaxKey') {
3838
+ index = serializeMinMax(buffer, key, value, index);
3839
+ }
3840
+ else if (typeof value._bsontype !== 'undefined') {
3841
+ throw new BSONError(`Unrecognized or invalid _bsontype: ${String(value._bsontype)}`);
3842
+ }
3650
3843
  }
3651
- else if (typeof value === 'function' && serializeFunctions) {
3844
+ else if (type === 'function' && serializeFunctions) {
3652
3845
  index = serializeFunction(buffer, key, value, index);
3653
3846
  }
3654
- else if (value._bsontype === 'Code') {
3655
- index = serializeCode(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, path);
3656
- }
3657
- else if (value._bsontype === 'Binary') {
3658
- index = serializeBinary(buffer, key, value, index);
3659
- }
3660
- else if (value._bsontype === 'BSONSymbol') {
3661
- index = serializeSymbol(buffer, key, value, index);
3662
- }
3663
- else if (value._bsontype === 'DBRef') {
3664
- index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions, path);
3665
- }
3666
- else if (value._bsontype === 'BSONRegExp') {
3667
- index = serializeBSONRegExp(buffer, key, value, index);
3668
- }
3669
- else if (value._bsontype === 'Int32') {
3670
- index = serializeInt32(buffer, key, value, index);
3671
- }
3672
- else if (value._bsontype === 'MinKey' || value._bsontype === 'MaxKey') {
3673
- index = serializeMinMax(buffer, key, value, index);
3674
- }
3675
- else if (typeof value._bsontype !== 'undefined') {
3676
- throw new BSONError(`Unrecognized or invalid _bsontype: ${String(value._bsontype)}`);
3677
- }
3678
3847
  }
3679
3848
  }
3680
3849
  else if (object instanceof Map || isMap(object)) {
@@ -3704,7 +3873,14 @@ function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializ
3704
3873
  }
3705
3874
  }
3706
3875
  }
3707
- if (type === 'string') {
3876
+ if (value === undefined) {
3877
+ if (ignoreUndefined === false)
3878
+ index = serializeNull(buffer, key, value, index);
3879
+ }
3880
+ else if (value === null) {
3881
+ index = serializeNull(buffer, key, value, index);
3882
+ }
3883
+ else if (type === 'string') {
3708
3884
  index = serializeString(buffer, key, value, index);
3709
3885
  }
3710
3886
  else if (type === 'number') {
@@ -3716,64 +3892,64 @@ function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializ
3716
3892
  else if (type === 'boolean') {
3717
3893
  index = serializeBoolean(buffer, key, value, index);
3718
3894
  }
3719
- else if (value instanceof Date || isDate(value)) {
3720
- index = serializeDate(buffer, key, value, index);
3721
- }
3722
- else if (value === null || (value === undefined && ignoreUndefined === false)) {
3723
- index = serializeNull(buffer, key, value, index);
3724
- }
3725
- else if (isUint8Array(value)) {
3726
- index = serializeBuffer(buffer, key, value, index);
3727
- }
3728
- else if (value instanceof RegExp || isRegExp(value)) {
3729
- index = serializeRegExp(buffer, key, value, index);
3730
- }
3731
3895
  else if (type === 'object' && value._bsontype == null) {
3732
- index = serializeObject(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, path);
3733
- }
3734
- else if (typeof value === 'object' &&
3735
- value[Symbol.for('@@mdb.bson.version')] !== BSON_MAJOR_VERSION) {
3736
- throw new BSONVersionError();
3737
- }
3738
- else if (value._bsontype === 'ObjectId') {
3739
- index = serializeObjectId(buffer, key, value, index);
3740
- }
3741
- else if (type === 'object' && value._bsontype === 'Decimal128') {
3742
- index = serializeDecimal128(buffer, key, value, index);
3743
- }
3744
- else if (value._bsontype === 'Long' || value._bsontype === 'Timestamp') {
3745
- index = serializeLong(buffer, key, value, index);
3746
- }
3747
- else if (value._bsontype === 'Double') {
3748
- index = serializeDouble(buffer, key, value, index);
3896
+ if (value instanceof Date || isDate(value)) {
3897
+ index = serializeDate(buffer, key, value, index);
3898
+ }
3899
+ else if (value instanceof Uint8Array || isUint8Array(value)) {
3900
+ index = serializeBuffer(buffer, key, value, index);
3901
+ }
3902
+ else if (value instanceof RegExp || isRegExp(value)) {
3903
+ index = serializeRegExp(buffer, key, value, index);
3904
+ }
3905
+ else {
3906
+ index = serializeObject(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, path);
3907
+ }
3749
3908
  }
3750
- else if (value._bsontype === 'Code') {
3751
- index = serializeCode(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, path);
3909
+ else if (type === 'object') {
3910
+ if (value[BSON_VERSION_SYMBOL] !== BSON_MAJOR_VERSION) {
3911
+ throw new BSONVersionError();
3912
+ }
3913
+ else if (value._bsontype === 'ObjectId') {
3914
+ index = serializeObjectId(buffer, key, value, index);
3915
+ }
3916
+ else if (value._bsontype === 'Decimal128') {
3917
+ index = serializeDecimal128(buffer, key, value, index);
3918
+ }
3919
+ else if (value._bsontype === 'Long' || value._bsontype === 'Timestamp') {
3920
+ index = serializeLong(buffer, key, value, index);
3921
+ }
3922
+ else if (value._bsontype === 'Double') {
3923
+ index = serializeDouble(buffer, key, value, index);
3924
+ }
3925
+ else if (value._bsontype === 'Code') {
3926
+ index = serializeCode(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, path);
3927
+ }
3928
+ else if (value._bsontype === 'Binary') {
3929
+ index = serializeBinary(buffer, key, value, index);
3930
+ }
3931
+ else if (value._bsontype === 'BSONSymbol') {
3932
+ index = serializeSymbol(buffer, key, value, index);
3933
+ }
3934
+ else if (value._bsontype === 'DBRef') {
3935
+ index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions, path);
3936
+ }
3937
+ else if (value._bsontype === 'BSONRegExp') {
3938
+ index = serializeBSONRegExp(buffer, key, value, index);
3939
+ }
3940
+ else if (value._bsontype === 'Int32') {
3941
+ index = serializeInt32(buffer, key, value, index);
3942
+ }
3943
+ else if (value._bsontype === 'MinKey' || value._bsontype === 'MaxKey') {
3944
+ index = serializeMinMax(buffer, key, value, index);
3945
+ }
3946
+ else if (typeof value._bsontype !== 'undefined') {
3947
+ throw new BSONError(`Unrecognized or invalid _bsontype: ${String(value._bsontype)}`);
3948
+ }
3752
3949
  }
3753
- else if (typeof value === 'function' && serializeFunctions) {
3950
+ else if (type === 'function' && serializeFunctions) {
3754
3951
  index = serializeFunction(buffer, key, value, index);
3755
3952
  }
3756
- else if (value._bsontype === 'Binary') {
3757
- index = serializeBinary(buffer, key, value, index);
3758
- }
3759
- else if (value._bsontype === 'BSONSymbol') {
3760
- index = serializeSymbol(buffer, key, value, index);
3761
- }
3762
- else if (value._bsontype === 'DBRef') {
3763
- index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions, path);
3764
- }
3765
- else if (value._bsontype === 'BSONRegExp') {
3766
- index = serializeBSONRegExp(buffer, key, value, index);
3767
- }
3768
- else if (value._bsontype === 'Int32') {
3769
- index = serializeInt32(buffer, key, value, index);
3770
- }
3771
- else if (value._bsontype === 'MinKey' || value._bsontype === 'MaxKey') {
3772
- index = serializeMinMax(buffer, key, value, index);
3773
- }
3774
- else if (typeof value._bsontype !== 'undefined') {
3775
- throw new BSONError(`Unrecognized or invalid _bsontype: ${String(value._bsontype)}`);
3776
- }
3777
3953
  }
3778
3954
  }
3779
3955
  else {
@@ -3802,7 +3978,14 @@ function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializ
3802
3978
  }
3803
3979
  }
3804
3980
  }
3805
- if (type === 'string') {
3981
+ if (value === undefined) {
3982
+ if (ignoreUndefined === false)
3983
+ index = serializeNull(buffer, key, value, index);
3984
+ }
3985
+ else if (value === null) {
3986
+ index = serializeNull(buffer, key, value, index);
3987
+ }
3988
+ else if (type === 'string') {
3806
3989
  index = serializeString(buffer, key, value, index);
3807
3990
  }
3808
3991
  else if (type === 'number') {
@@ -3814,68 +3997,64 @@ function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializ
3814
3997
  else if (type === 'boolean') {
3815
3998
  index = serializeBoolean(buffer, key, value, index);
3816
3999
  }
3817
- else if (value instanceof Date || isDate(value)) {
3818
- index = serializeDate(buffer, key, value, index);
3819
- }
3820
- else if (value === undefined) {
3821
- if (ignoreUndefined === false)
3822
- index = serializeNull(buffer, key, value, index);
3823
- }
3824
- else if (value === null) {
3825
- index = serializeNull(buffer, key, value, index);
3826
- }
3827
- else if (isUint8Array(value)) {
3828
- index = serializeBuffer(buffer, key, value, index);
3829
- }
3830
- else if (value instanceof RegExp || isRegExp(value)) {
3831
- index = serializeRegExp(buffer, key, value, index);
3832
- }
3833
4000
  else if (type === 'object' && value._bsontype == null) {
3834
- index = serializeObject(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, path);
3835
- }
3836
- else if (typeof value === 'object' &&
3837
- value[Symbol.for('@@mdb.bson.version')] !== BSON_MAJOR_VERSION) {
3838
- throw new BSONVersionError();
3839
- }
3840
- else if (value._bsontype === 'ObjectId') {
3841
- index = serializeObjectId(buffer, key, value, index);
3842
- }
3843
- else if (type === 'object' && value._bsontype === 'Decimal128') {
3844
- index = serializeDecimal128(buffer, key, value, index);
3845
- }
3846
- else if (value._bsontype === 'Long' || value._bsontype === 'Timestamp') {
3847
- index = serializeLong(buffer, key, value, index);
3848
- }
3849
- else if (value._bsontype === 'Double') {
3850
- index = serializeDouble(buffer, key, value, index);
4001
+ if (value instanceof Date || isDate(value)) {
4002
+ index = serializeDate(buffer, key, value, index);
4003
+ }
4004
+ else if (value instanceof Uint8Array || isUint8Array(value)) {
4005
+ index = serializeBuffer(buffer, key, value, index);
4006
+ }
4007
+ else if (value instanceof RegExp || isRegExp(value)) {
4008
+ index = serializeRegExp(buffer, key, value, index);
4009
+ }
4010
+ else {
4011
+ index = serializeObject(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, path);
4012
+ }
3851
4013
  }
3852
- else if (value._bsontype === 'Code') {
3853
- index = serializeCode(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, path);
4014
+ else if (type === 'object') {
4015
+ if (value[BSON_VERSION_SYMBOL] !== BSON_MAJOR_VERSION) {
4016
+ throw new BSONVersionError();
4017
+ }
4018
+ else if (value._bsontype === 'ObjectId') {
4019
+ index = serializeObjectId(buffer, key, value, index);
4020
+ }
4021
+ else if (value._bsontype === 'Decimal128') {
4022
+ index = serializeDecimal128(buffer, key, value, index);
4023
+ }
4024
+ else if (value._bsontype === 'Long' || value._bsontype === 'Timestamp') {
4025
+ index = serializeLong(buffer, key, value, index);
4026
+ }
4027
+ else if (value._bsontype === 'Double') {
4028
+ index = serializeDouble(buffer, key, value, index);
4029
+ }
4030
+ else if (value._bsontype === 'Code') {
4031
+ index = serializeCode(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, path);
4032
+ }
4033
+ else if (value._bsontype === 'Binary') {
4034
+ index = serializeBinary(buffer, key, value, index);
4035
+ }
4036
+ else if (value._bsontype === 'BSONSymbol') {
4037
+ index = serializeSymbol(buffer, key, value, index);
4038
+ }
4039
+ else if (value._bsontype === 'DBRef') {
4040
+ index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions, path);
4041
+ }
4042
+ else if (value._bsontype === 'BSONRegExp') {
4043
+ index = serializeBSONRegExp(buffer, key, value, index);
4044
+ }
4045
+ else if (value._bsontype === 'Int32') {
4046
+ index = serializeInt32(buffer, key, value, index);
4047
+ }
4048
+ else if (value._bsontype === 'MinKey' || value._bsontype === 'MaxKey') {
4049
+ index = serializeMinMax(buffer, key, value, index);
4050
+ }
4051
+ else if (typeof value._bsontype !== 'undefined') {
4052
+ throw new BSONError(`Unrecognized or invalid _bsontype: ${String(value._bsontype)}`);
4053
+ }
3854
4054
  }
3855
- else if (typeof value === 'function' && serializeFunctions) {
4055
+ else if (type === 'function' && serializeFunctions) {
3856
4056
  index = serializeFunction(buffer, key, value, index);
3857
4057
  }
3858
- else if (value._bsontype === 'Binary') {
3859
- index = serializeBinary(buffer, key, value, index);
3860
- }
3861
- else if (value._bsontype === 'BSONSymbol') {
3862
- index = serializeSymbol(buffer, key, value, index);
3863
- }
3864
- else if (value._bsontype === 'DBRef') {
3865
- index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions, path);
3866
- }
3867
- else if (value._bsontype === 'BSONRegExp') {
3868
- index = serializeBSONRegExp(buffer, key, value, index);
3869
- }
3870
- else if (value._bsontype === 'Int32') {
3871
- index = serializeInt32(buffer, key, value, index);
3872
- }
3873
- else if (value._bsontype === 'MinKey' || value._bsontype === 'MaxKey') {
3874
- index = serializeMinMax(buffer, key, value, index);
3875
- }
3876
- else if (typeof value._bsontype !== 'undefined') {
3877
- throw new BSONError(`Unrecognized or invalid _bsontype: ${String(value._bsontype)}`);
3878
- }
3879
4058
  }
3880
4059
  }
3881
4060
  path.delete(object);
@@ -4127,7 +4306,7 @@ function serializeDocument(doc, options) {
4127
4306
  else if (doc != null &&
4128
4307
  typeof doc === 'object' &&
4129
4308
  typeof doc._bsontype === 'string' &&
4130
- doc[Symbol.for('@@mdb.bson.version')] !== BSON_MAJOR_VERSION) {
4309
+ doc[BSON_VERSION_SYMBOL] !== BSON_MAJOR_VERSION) {
4131
4310
  throw new BSONVersionError();
4132
4311
  }
4133
4312
  else if (isBSONType(doc)) {