bson 4.7.0 → 5.0.0-alpha.1

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 (98) hide show
  1. package/bson.d.ts +207 -259
  2. package/lib/bson.bundle.js +4034 -0
  3. package/lib/bson.bundle.js.map +1 -0
  4. package/lib/bson.cjs +4029 -0
  5. package/lib/bson.cjs.map +1 -0
  6. package/lib/bson.mjs +4003 -0
  7. package/lib/bson.mjs.map +1 -0
  8. package/package.json +49 -62
  9. package/src/binary.ts +64 -53
  10. package/src/bson.ts +27 -108
  11. package/src/code.ts +25 -14
  12. package/src/constants.ts +33 -0
  13. package/src/db_ref.ts +14 -8
  14. package/src/decimal128.ts +32 -25
  15. package/src/double.ts +8 -5
  16. package/src/error.ts +0 -2
  17. package/src/extended_json.ts +148 -148
  18. package/src/index.ts +19 -0
  19. package/src/int_32.ts +8 -5
  20. package/src/long.ts +17 -16
  21. package/src/max_key.ts +8 -6
  22. package/src/min_key.ts +8 -6
  23. package/src/objectid.ts +42 -74
  24. package/src/parser/calculate_size.ts +39 -63
  25. package/src/parser/deserializer.ts +41 -112
  26. package/src/parser/serializer.ts +234 -341
  27. package/src/parser/utils.ts +1 -99
  28. package/src/regexp.ts +17 -5
  29. package/src/symbol.ts +9 -5
  30. package/src/timestamp.ts +63 -27
  31. package/src/utils/byte_utils.ts +61 -0
  32. package/src/utils/node_byte_utils.ts +141 -0
  33. package/src/utils/web_byte_utils.ts +190 -0
  34. package/src/uuid_utils.ts +15 -15
  35. package/bower.json +0 -26
  36. package/dist/bson.browser.esm.js +0 -7470
  37. package/dist/bson.browser.esm.js.map +0 -1
  38. package/dist/bson.browser.umd.js +0 -7537
  39. package/dist/bson.browser.umd.js.map +0 -1
  40. package/dist/bson.bundle.js +0 -7536
  41. package/dist/bson.bundle.js.map +0 -1
  42. package/dist/bson.esm.js +0 -5436
  43. package/dist/bson.esm.js.map +0 -1
  44. package/lib/binary.js +0 -426
  45. package/lib/binary.js.map +0 -1
  46. package/lib/bson.js +0 -251
  47. package/lib/bson.js.map +0 -1
  48. package/lib/code.js +0 -46
  49. package/lib/code.js.map +0 -1
  50. package/lib/constants.js +0 -82
  51. package/lib/constants.js.map +0 -1
  52. package/lib/db_ref.js +0 -97
  53. package/lib/db_ref.js.map +0 -1
  54. package/lib/decimal128.js +0 -669
  55. package/lib/decimal128.js.map +0 -1
  56. package/lib/double.js +0 -76
  57. package/lib/double.js.map +0 -1
  58. package/lib/ensure_buffer.js +0 -25
  59. package/lib/ensure_buffer.js.map +0 -1
  60. package/lib/error.js +0 -55
  61. package/lib/error.js.map +0 -1
  62. package/lib/extended_json.js +0 -390
  63. package/lib/extended_json.js.map +0 -1
  64. package/lib/int_32.js +0 -58
  65. package/lib/int_32.js.map +0 -1
  66. package/lib/long.js +0 -900
  67. package/lib/long.js.map +0 -1
  68. package/lib/map.js +0 -123
  69. package/lib/map.js.map +0 -1
  70. package/lib/max_key.js +0 -33
  71. package/lib/max_key.js.map +0 -1
  72. package/lib/min_key.js +0 -33
  73. package/lib/min_key.js.map +0 -1
  74. package/lib/objectid.js +0 -299
  75. package/lib/objectid.js.map +0 -1
  76. package/lib/parser/calculate_size.js +0 -194
  77. package/lib/parser/calculate_size.js.map +0 -1
  78. package/lib/parser/deserializer.js +0 -665
  79. package/lib/parser/deserializer.js.map +0 -1
  80. package/lib/parser/serializer.js +0 -867
  81. package/lib/parser/serializer.js.map +0 -1
  82. package/lib/parser/utils.js +0 -115
  83. package/lib/parser/utils.js.map +0 -1
  84. package/lib/regexp.js +0 -74
  85. package/lib/regexp.js.map +0 -1
  86. package/lib/symbol.js +0 -48
  87. package/lib/symbol.js.map +0 -1
  88. package/lib/timestamp.js +0 -102
  89. package/lib/timestamp.js.map +0 -1
  90. package/lib/utils/global.js +0 -18
  91. package/lib/utils/global.js.map +0 -1
  92. package/lib/uuid_utils.js +0 -35
  93. package/lib/uuid_utils.js.map +0 -1
  94. package/lib/validate_utf8.js +0 -47
  95. package/lib/validate_utf8.js.map +0 -1
  96. package/src/ensure_buffer.ts +0 -27
  97. package/src/map.ts +0 -119
  98. package/src/utils/global.ts +0 -22
@@ -1,4 +1,3 @@
1
- import { Buffer } from 'buffer';
2
1
  import { Binary } from '../binary';
3
2
  import type { Document } from '../bson';
4
3
  import { Code } from '../code';
@@ -15,20 +14,11 @@ import { ObjectId } from '../objectid';
15
14
  import { BSONRegExp } from '../regexp';
16
15
  import { BSONSymbol } from '../symbol';
17
16
  import { Timestamp } from '../timestamp';
17
+ import { ByteUtils } from '../utils/byte_utils';
18
18
  import { validateUtf8 } from '../validate_utf8';
19
19
 
20
20
  /** @public */
21
21
  export interface DeserializeOptions {
22
- /** evaluate functions in the BSON document scoped to the object deserialized. */
23
- evalFunctions?: boolean;
24
- /** cache evaluated functions for reuse. */
25
- cacheFunctions?: boolean;
26
- /**
27
- * use a crc32 code for caching, otherwise use the string of the function.
28
- * @deprecated this option to use the crc32 function never worked as intended
29
- * due to the fact that the crc32 function itself was never implemented.
30
- * */
31
- cacheFunctionsCrc32?: boolean;
32
22
  /** when deserializing a Long will fit it into a Number if it's smaller than 53 bits */
33
23
  promoteLongs?: boolean;
34
24
  /** when deserializing a Binary will return it as a node.js Buffer instance. */
@@ -67,10 +57,8 @@ export interface DeserializeOptions {
67
57
  const JS_INT_MAX_LONG = Long.fromNumber(constants.JS_INT_MAX);
68
58
  const JS_INT_MIN_LONG = Long.fromNumber(constants.JS_INT_MIN);
69
59
 
70
- const functionCache: { [hash: string]: Function } = {};
71
-
72
- export function deserialize(
73
- buffer: Buffer,
60
+ export function internalDeserialize(
61
+ buffer: Uint8Array,
74
62
  options: DeserializeOptions,
75
63
  isArray?: boolean
76
64
  ): Document {
@@ -115,14 +103,11 @@ export function deserialize(
115
103
  const allowedDBRefKeys = /^\$ref$|^\$id$|^\$db$/;
116
104
 
117
105
  function deserializeObject(
118
- buffer: Buffer,
106
+ buffer: Uint8Array,
119
107
  index: number,
120
108
  options: DeserializeOptions,
121
109
  isArray = false
122
110
  ) {
123
- const evalFunctions = options['evalFunctions'] == null ? false : options['evalFunctions'];
124
- const cacheFunctions = options['cacheFunctions'] == null ? false : options['cacheFunctions'];
125
-
126
111
  const fieldsAsRaw = options['fieldsAsRaw'] == null ? null : options['fieldsAsRaw'];
127
112
 
128
113
  // Return raw bson buffer instead of parsing it
@@ -216,7 +201,7 @@ function deserializeObject(
216
201
  if (i >= buffer.byteLength) throw new BSONError('Bad BSON Document: illegal CString');
217
202
 
218
203
  // Represents the key
219
- const name = isArray ? arrayIndex++ : buffer.toString('utf8', index, i);
204
+ const name = isArray ? arrayIndex++ : ByteUtils.toUTF8(buffer.subarray(index, i));
220
205
 
221
206
  // shouldValidateKey is true if the key should be validated, false otherwise
222
207
  let shouldValidateKey = true;
@@ -249,8 +234,8 @@ function deserializeObject(
249
234
  value = getValidatedString(buffer, index, index + stringSize - 1, shouldValidateKey);
250
235
  index = index + stringSize;
251
236
  } else if (elementType === constants.BSON_DATA_OID) {
252
- const oid = Buffer.alloc(12);
253
- buffer.copy(oid, 0, index, index + 12);
237
+ const oid = ByteUtils.allocate(12);
238
+ oid.set(buffer.subarray(index, index + 12));
254
239
  value = new ObjectId(oid);
255
240
  index = index + 12;
256
241
  } else if (elementType === constants.BSON_DATA_INT && promoteValues === false) {
@@ -314,23 +299,16 @@ function deserializeObject(
314
299
  (buffer[index + 1] << 8) |
315
300
  (buffer[index + 2] << 16) |
316
301
  (buffer[index + 3] << 24);
317
- let arrayOptions = options;
302
+ let arrayOptions: DeserializeOptions = options;
318
303
 
319
304
  // Stop index
320
305
  const stopIndex = index + objectSize;
321
306
 
322
307
  // All elements of array to be returned as raw bson
323
308
  if (fieldsAsRaw && fieldsAsRaw[name]) {
324
- arrayOptions = {};
325
- for (const n in options) {
326
- (
327
- arrayOptions as {
328
- [key: string]: DeserializeOptions[keyof DeserializeOptions];
329
- }
330
- )[n] = options[n as keyof DeserializeOptions];
331
- }
332
- arrayOptions['raw'] = true;
309
+ arrayOptions = { ...options, raw: true };
333
310
  }
311
+
334
312
  if (!globalUTFValidation) {
335
313
  arrayOptions = { ...arrayOptions, validation: { utf8: shouldValidateKey } };
336
314
  }
@@ -367,19 +345,13 @@ function deserializeObject(
367
345
  }
368
346
  } else if (elementType === constants.BSON_DATA_DECIMAL128) {
369
347
  // Buffer to contain the decimal bytes
370
- const bytes = Buffer.alloc(16);
348
+ const bytes = ByteUtils.allocate(16);
371
349
  // Copy the next 16 bytes into the bytes buffer
372
- buffer.copy(bytes, 0, index, index + 16);
350
+ bytes.set(buffer.subarray(index, index + 16), 0);
373
351
  // Update index
374
352
  index = index + 16;
375
353
  // Assign the new Decimal128 value
376
- const decimal128 = new Decimal128(bytes) as Decimal128 | { toObject(): unknown };
377
- // If we have an alternative mapper use that
378
- if ('toObject' in decimal128 && typeof decimal128.toObject === 'function') {
379
- value = decimal128.toObject();
380
- } else {
381
- value = decimal128;
382
- }
354
+ value = new Decimal128(bytes);
383
355
  } else if (elementType === constants.BSON_DATA_BINARY) {
384
356
  let binarySize =
385
357
  buffer[index++] |
@@ -414,7 +386,7 @@ function deserializeObject(
414
386
  }
415
387
 
416
388
  if (promoteBuffers && promoteValues) {
417
- value = buffer.slice(index, index + binarySize);
389
+ value = ByteUtils.toLocalBufferType(buffer.slice(index, index + binarySize));
418
390
  } else {
419
391
  value = new Binary(buffer.slice(index, index + binarySize), subType);
420
392
  if (subType === constants.BSON_BINARY_SUBTYPE_UUID_NEW) {
@@ -422,7 +394,7 @@ function deserializeObject(
422
394
  }
423
395
  }
424
396
  } else {
425
- const _buffer = Buffer.alloc(binarySize);
397
+ const _buffer = ByteUtils.allocate(binarySize);
426
398
  // If we have subtype 2 skip the 4 bytes for the size
427
399
  if (subType === Binary.SUBTYPE_BYTE_ARRAY) {
428
400
  binarySize =
@@ -464,7 +436,7 @@ function deserializeObject(
464
436
  // If are at the end of the buffer there is a problem with the document
465
437
  if (i >= buffer.length) throw new BSONError('Bad BSON Document: illegal CString');
466
438
  // Return the C string
467
- const source = buffer.toString('utf8', index, i);
439
+ const source = ByteUtils.toUTF8(buffer.subarray(index, i));
468
440
  // Create the regexp
469
441
  index = i + 1;
470
442
 
@@ -477,7 +449,7 @@ function deserializeObject(
477
449
  // If are at the end of the buffer there is a problem with the document
478
450
  if (i >= buffer.length) throw new BSONError('Bad BSON Document: illegal CString');
479
451
  // Return the C string
480
- const regExpOptions = buffer.toString('utf8', index, i);
452
+ const regExpOptions = ByteUtils.toUTF8(buffer.subarray(index, i));
481
453
  index = i + 1;
482
454
 
483
455
  // For each option add the corresponding one for javascript
@@ -509,7 +481,7 @@ function deserializeObject(
509
481
  // If are at the end of the buffer there is a problem with the document
510
482
  if (i >= buffer.length) throw new BSONError('Bad BSON Document: illegal CString');
511
483
  // Return the C string
512
- const source = buffer.toString('utf8', index, i);
484
+ const source = ByteUtils.toUTF8(buffer.subarray(index, i));
513
485
  index = i + 1;
514
486
 
515
487
  // Get the start search index
@@ -521,7 +493,7 @@ function deserializeObject(
521
493
  // If are at the end of the buffer there is a problem with the document
522
494
  if (i >= buffer.length) throw new BSONError('Bad BSON Document: illegal CString');
523
495
  // Return the C string
524
- const regExpOptions = buffer.toString('utf8', index, i);
496
+ const regExpOptions = ByteUtils.toUTF8(buffer.subarray(index, i));
525
497
  index = i + 1;
526
498
 
527
499
  // Set the object
@@ -543,18 +515,21 @@ function deserializeObject(
543
515
  value = promoteValues ? symbol : new BSONSymbol(symbol);
544
516
  index = index + stringSize;
545
517
  } else if (elementType === constants.BSON_DATA_TIMESTAMP) {
546
- const lowBits =
547
- buffer[index++] |
548
- (buffer[index++] << 8) |
549
- (buffer[index++] << 16) |
550
- (buffer[index++] << 24);
551
- const highBits =
552
- buffer[index++] |
553
- (buffer[index++] << 8) |
554
- (buffer[index++] << 16) |
555
- (buffer[index++] << 24);
556
-
557
- value = new Timestamp(lowBits, highBits);
518
+ // We intentionally **do not** use bit shifting here
519
+ // Bit shifting in javascript coerces numbers to **signed** int32s
520
+ // We need to keep i, and t unsigned
521
+ const i =
522
+ buffer[index++] +
523
+ buffer[index++] * (1 << 8) +
524
+ buffer[index++] * (1 << 16) +
525
+ buffer[index++] * (1 << 24);
526
+ const t =
527
+ buffer[index++] +
528
+ buffer[index++] * (1 << 8) +
529
+ buffer[index++] * (1 << 16) +
530
+ buffer[index++] * (1 << 24);
531
+
532
+ value = new Timestamp({ i, t });
558
533
  } else if (elementType === constants.BSON_DATA_MIN_KEY) {
559
534
  value = new MinKey();
560
535
  } else if (elementType === constants.BSON_DATA_MAX_KEY) {
@@ -579,18 +554,7 @@ function deserializeObject(
579
554
  shouldValidateKey
580
555
  );
581
556
 
582
- // If we are evaluating the functions
583
- if (evalFunctions) {
584
- // If we have cache enabled let's look for the md5 of the function in the cache
585
- if (cacheFunctions) {
586
- // Got to do this to avoid V8 deoptimizing the call due to finding eval
587
- value = isolateEval(functionString, functionCache, object);
588
- } else {
589
- value = isolateEval(functionString);
590
- }
591
- } else {
592
- value = new Code(functionString);
593
- }
557
+ value = new Code(functionString);
594
558
 
595
559
  // Update parse index position
596
560
  index = index + stringSize;
@@ -653,20 +617,7 @@ function deserializeObject(
653
617
  throw new BSONError('code_w_scope total size is too long, clips outer document');
654
618
  }
655
619
 
656
- // If we are evaluating the functions
657
- if (evalFunctions) {
658
- // If we have cache enabled let's look for the md5 of the function in the cache
659
- if (cacheFunctions) {
660
- // Got to do this to avoid V8 deoptimizing the call due to finding eval
661
- value = isolateEval(functionString, functionCache, object);
662
- } else {
663
- value = isolateEval(functionString);
664
- }
665
-
666
- value.scope = scopeObject;
667
- } else {
668
- value = new Code(functionString, scopeObject);
669
- }
620
+ value = new Code(functionString, scopeObject);
670
621
  } else if (elementType === constants.BSON_DATA_DBPOINTER) {
671
622
  // Get the code string size
672
623
  const stringSize =
@@ -687,13 +638,13 @@ function deserializeObject(
687
638
  throw new BSONError('Invalid UTF-8 string in BSON document');
688
639
  }
689
640
  }
690
- const namespace = buffer.toString('utf8', index, index + stringSize - 1);
641
+ const namespace = ByteUtils.toUTF8(buffer.subarray(index, index + stringSize - 1));
691
642
  // Update parse index position
692
643
  index = index + stringSize;
693
644
 
694
645
  // Read the oid
695
- const oidBuffer = Buffer.alloc(12);
696
- buffer.copy(oidBuffer, 0, index, index + 12);
646
+ const oidBuffer = ByteUtils.allocate(12);
647
+ oidBuffer.set(buffer.subarray(index, index + 12), 0);
697
648
  const oid = new ObjectId(oidBuffer);
698
649
 
699
650
  // Update the index
@@ -738,35 +689,13 @@ function deserializeObject(
738
689
  return object;
739
690
  }
740
691
 
741
- /**
742
- * Ensure eval is isolated, store the result in functionCache.
743
- *
744
- * @internal
745
- */
746
- function isolateEval(
747
- functionString: string,
748
- functionCache?: { [hash: string]: Function },
749
- object?: Document
750
- ) {
751
- // eslint-disable-next-line @typescript-eslint/no-implied-eval
752
- if (!functionCache) return new Function(functionString);
753
- // Check for cache hit, eval if missing and return cached function
754
- if (functionCache[functionString] == null) {
755
- // eslint-disable-next-line @typescript-eslint/no-implied-eval
756
- functionCache[functionString] = new Function(functionString);
757
- }
758
-
759
- // Set the object
760
- return functionCache[functionString].bind(object);
761
- }
762
-
763
692
  function getValidatedString(
764
- buffer: Buffer,
693
+ buffer: Uint8Array,
765
694
  start: number,
766
695
  end: number,
767
696
  shouldValidateUtf8: boolean
768
697
  ) {
769
- const value = buffer.toString('utf8', start, end);
698
+ const value = ByteUtils.toUTF8(buffer.subarray(start, end));
770
699
  // if utf8 validation is on, do the check
771
700
  if (shouldValidateUtf8) {
772
701
  for (let i = 0; i < value.length; i++) {