bson 4.6.5 → 5.0.0-alpha.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 (101) hide show
  1. package/bson.d.ts +208 -267
  2. package/lib/bson.bundle.js +4033 -0
  3. package/lib/bson.bundle.js.map +1 -0
  4. package/lib/bson.cjs +4028 -0
  5. package/lib/bson.cjs.map +1 -0
  6. package/lib/bson.mjs +4002 -0
  7. package/lib/bson.mjs.map +1 -0
  8. package/package.json +49 -61
  9. package/src/binary.ts +235 -37
  10. package/src/bson.ts +43 -129
  11. package/src/code.ts +24 -14
  12. package/src/constants.ts +28 -0
  13. package/src/db_ref.ts +13 -8
  14. package/src/decimal128.ts +31 -25
  15. package/src/double.ts +7 -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 +7 -5
  20. package/src/long.ts +16 -16
  21. package/src/max_key.ts +6 -6
  22. package/src/min_key.ts +6 -6
  23. package/src/objectid.ts +41 -74
  24. package/src/parser/calculate_size.ts +39 -63
  25. package/src/parser/deserializer.ts +47 -113
  26. package/src/parser/serializer.ts +234 -341
  27. package/src/parser/utils.ts +1 -99
  28. package/src/regexp.ts +16 -5
  29. package/src/symbol.ts +7 -5
  30. package/src/timestamp.ts +62 -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 -7471
  37. package/dist/bson.browser.esm.js.map +0 -1
  38. package/dist/bson.browser.umd.js +0 -7538
  39. package/dist/bson.browser.umd.js.map +0 -1
  40. package/dist/bson.bundle.js +0 -7537
  41. package/dist/bson.bundle.js.map +0 -1
  42. package/dist/bson.esm.js +0 -5437
  43. package/dist/bson.esm.js.map +0 -1
  44. package/lib/binary.js +0 -247
  45. package/lib/binary.js.map +0 -1
  46. package/lib/bson.js +0 -265
  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 -659
  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.js +0 -179
  93. package/lib/uuid.js.map +0 -1
  94. package/lib/uuid_utils.js +0 -35
  95. package/lib/uuid_utils.js.map +0 -1
  96. package/lib/validate_utf8.js +0 -47
  97. package/lib/validate_utf8.js.map +0 -1
  98. package/src/ensure_buffer.ts +0 -27
  99. package/src/map.ts +0 -119
  100. package/src/utils/global.ts +0 -22
  101. package/src/uuid.ts +0 -209
@@ -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,12 +386,15 @@ 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);
392
+ if (subType === constants.BSON_BINARY_SUBTYPE_UUID_NEW) {
393
+ value = value.toUUID();
394
+ }
420
395
  }
421
396
  } else {
422
- const _buffer = Buffer.alloc(binarySize);
397
+ const _buffer = ByteUtils.allocate(binarySize);
423
398
  // If we have subtype 2 skip the 4 bytes for the size
424
399
  if (subType === Binary.SUBTYPE_BYTE_ARRAY) {
425
400
  binarySize =
@@ -442,8 +417,10 @@ function deserializeObject(
442
417
 
443
418
  if (promoteBuffers && promoteValues) {
444
419
  value = _buffer;
420
+ } else if (subType === constants.BSON_BINARY_SUBTYPE_UUID_NEW) {
421
+ value = new Binary(buffer.slice(index, index + binarySize), subType).toUUID();
445
422
  } else {
446
- value = new Binary(_buffer, subType);
423
+ value = new Binary(buffer.slice(index, index + binarySize), subType);
447
424
  }
448
425
  }
449
426
 
@@ -459,7 +436,7 @@ function deserializeObject(
459
436
  // If are at the end of the buffer there is a problem with the document
460
437
  if (i >= buffer.length) throw new BSONError('Bad BSON Document: illegal CString');
461
438
  // Return the C string
462
- const source = buffer.toString('utf8', index, i);
439
+ const source = ByteUtils.toUTF8(buffer.subarray(index, i));
463
440
  // Create the regexp
464
441
  index = i + 1;
465
442
 
@@ -472,7 +449,7 @@ function deserializeObject(
472
449
  // If are at the end of the buffer there is a problem with the document
473
450
  if (i >= buffer.length) throw new BSONError('Bad BSON Document: illegal CString');
474
451
  // Return the C string
475
- const regExpOptions = buffer.toString('utf8', index, i);
452
+ const regExpOptions = ByteUtils.toUTF8(buffer.subarray(index, i));
476
453
  index = i + 1;
477
454
 
478
455
  // For each option add the corresponding one for javascript
@@ -504,7 +481,7 @@ function deserializeObject(
504
481
  // If are at the end of the buffer there is a problem with the document
505
482
  if (i >= buffer.length) throw new BSONError('Bad BSON Document: illegal CString');
506
483
  // Return the C string
507
- const source = buffer.toString('utf8', index, i);
484
+ const source = ByteUtils.toUTF8(buffer.subarray(index, i));
508
485
  index = i + 1;
509
486
 
510
487
  // Get the start search index
@@ -516,7 +493,7 @@ function deserializeObject(
516
493
  // If are at the end of the buffer there is a problem with the document
517
494
  if (i >= buffer.length) throw new BSONError('Bad BSON Document: illegal CString');
518
495
  // Return the C string
519
- const regExpOptions = buffer.toString('utf8', index, i);
496
+ const regExpOptions = ByteUtils.toUTF8(buffer.subarray(index, i));
520
497
  index = i + 1;
521
498
 
522
499
  // Set the object
@@ -538,18 +515,21 @@ function deserializeObject(
538
515
  value = promoteValues ? symbol : new BSONSymbol(symbol);
539
516
  index = index + stringSize;
540
517
  } else if (elementType === constants.BSON_DATA_TIMESTAMP) {
541
- const lowBits =
542
- buffer[index++] |
543
- (buffer[index++] << 8) |
544
- (buffer[index++] << 16) |
545
- (buffer[index++] << 24);
546
- const highBits =
547
- buffer[index++] |
548
- (buffer[index++] << 8) |
549
- (buffer[index++] << 16) |
550
- (buffer[index++] << 24);
551
-
552
- 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 });
553
533
  } else if (elementType === constants.BSON_DATA_MIN_KEY) {
554
534
  value = new MinKey();
555
535
  } else if (elementType === constants.BSON_DATA_MAX_KEY) {
@@ -574,18 +554,7 @@ function deserializeObject(
574
554
  shouldValidateKey
575
555
  );
576
556
 
577
- // If we are evaluating the functions
578
- if (evalFunctions) {
579
- // If we have cache enabled let's look for the md5 of the function in the cache
580
- if (cacheFunctions) {
581
- // Got to do this to avoid V8 deoptimizing the call due to finding eval
582
- value = isolateEval(functionString, functionCache, object);
583
- } else {
584
- value = isolateEval(functionString);
585
- }
586
- } else {
587
- value = new Code(functionString);
588
- }
557
+ value = new Code(functionString);
589
558
 
590
559
  // Update parse index position
591
560
  index = index + stringSize;
@@ -648,20 +617,7 @@ function deserializeObject(
648
617
  throw new BSONError('code_w_scope total size is too long, clips outer document');
649
618
  }
650
619
 
651
- // If we are evaluating the functions
652
- if (evalFunctions) {
653
- // If we have cache enabled let's look for the md5 of the function in the cache
654
- if (cacheFunctions) {
655
- // Got to do this to avoid V8 deoptimizing the call due to finding eval
656
- value = isolateEval(functionString, functionCache, object);
657
- } else {
658
- value = isolateEval(functionString);
659
- }
660
-
661
- value.scope = scopeObject;
662
- } else {
663
- value = new Code(functionString, scopeObject);
664
- }
620
+ value = new Code(functionString, scopeObject);
665
621
  } else if (elementType === constants.BSON_DATA_DBPOINTER) {
666
622
  // Get the code string size
667
623
  const stringSize =
@@ -682,13 +638,13 @@ function deserializeObject(
682
638
  throw new BSONError('Invalid UTF-8 string in BSON document');
683
639
  }
684
640
  }
685
- const namespace = buffer.toString('utf8', index, index + stringSize - 1);
641
+ const namespace = ByteUtils.toUTF8(buffer.subarray(index, index + stringSize - 1));
686
642
  // Update parse index position
687
643
  index = index + stringSize;
688
644
 
689
645
  // Read the oid
690
- const oidBuffer = Buffer.alloc(12);
691
- buffer.copy(oidBuffer, 0, index, index + 12);
646
+ const oidBuffer = ByteUtils.allocate(12);
647
+ oidBuffer.set(buffer.subarray(index, index + 12), 0);
692
648
  const oid = new ObjectId(oidBuffer);
693
649
 
694
650
  // Update the index
@@ -733,35 +689,13 @@ function deserializeObject(
733
689
  return object;
734
690
  }
735
691
 
736
- /**
737
- * Ensure eval is isolated, store the result in functionCache.
738
- *
739
- * @internal
740
- */
741
- function isolateEval(
742
- functionString: string,
743
- functionCache?: { [hash: string]: Function },
744
- object?: Document
745
- ) {
746
- // eslint-disable-next-line @typescript-eslint/no-implied-eval
747
- if (!functionCache) return new Function(functionString);
748
- // Check for cache hit, eval if missing and return cached function
749
- if (functionCache[functionString] == null) {
750
- // eslint-disable-next-line @typescript-eslint/no-implied-eval
751
- functionCache[functionString] = new Function(functionString);
752
- }
753
-
754
- // Set the object
755
- return functionCache[functionString].bind(object);
756
- }
757
-
758
692
  function getValidatedString(
759
- buffer: Buffer,
693
+ buffer: Uint8Array,
760
694
  start: number,
761
695
  end: number,
762
696
  shouldValidateUtf8: boolean
763
697
  ) {
764
- const value = buffer.toString('utf8', start, end);
698
+ const value = ByteUtils.toUTF8(buffer.subarray(start, end));
765
699
  // if utf8 validation is on, do the check
766
700
  if (shouldValidateUtf8) {
767
701
  for (let i = 0; i < value.length; i++) {