bson 6.2.0 → 6.3.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/bson.d.ts CHANGED
@@ -150,14 +150,16 @@ export { BSON }
150
150
  * @public
151
151
  * @category Error
152
152
  *
153
- * `BSONError` objects are thrown when BSON ecounters an error.
153
+ * `BSONError` objects are thrown when BSON encounters an error.
154
154
  *
155
155
  * This is the parent class for all the other errors thrown by this library.
156
156
  */
157
157
  export declare class BSONError extends Error {
158
158
  /* Excluded from this release type: bsonError */
159
159
  get name(): string;
160
- constructor(message: string);
160
+ constructor(message: string, options?: {
161
+ cause?: unknown;
162
+ });
161
163
  /**
162
164
  * @public
163
165
  *
@@ -994,9 +996,42 @@ export declare class ObjectId extends BSONValue {
994
996
  /* Excluded from this release type: [kId] */
995
997
  /* Excluded from this release type: __id */
996
998
  /**
997
- * Create an ObjectId type
999
+ * Create ObjectId from a number.
1000
+ *
1001
+ * @param inputId - A number.
1002
+ * @deprecated Instead, use `static createFromTime()` to set a numeric value for the new ObjectId.
1003
+ */
1004
+ constructor(inputId: number);
1005
+ /**
1006
+ * Create ObjectId from a 24 character hex string.
1007
+ *
1008
+ * @param inputId - A 24 character hex string.
1009
+ */
1010
+ constructor(inputId: string);
1011
+ /**
1012
+ * Create ObjectId from the BSON ObjectId type.
1013
+ *
1014
+ * @param inputId - The BSON ObjectId type.
1015
+ */
1016
+ constructor(inputId: ObjectId);
1017
+ /**
1018
+ * Create ObjectId from the object type that has the toHexString method.
1019
+ *
1020
+ * @param inputId - The ObjectIdLike type.
1021
+ */
1022
+ constructor(inputId: ObjectIdLike);
1023
+ /**
1024
+ * Create ObjectId from a 12 byte binary Buffer.
1025
+ *
1026
+ * @param inputId - A 12 byte binary Buffer.
1027
+ */
1028
+ constructor(inputId: Uint8Array);
1029
+ /** To generate a new ObjectId, use ObjectId() with no argument. */
1030
+ constructor();
1031
+ /**
1032
+ * Implementation overload.
998
1033
  *
999
- * @param inputId - Can be a 24 character hex string, 12 byte binary Buffer, or a number.
1034
+ * @param inputId - All input types that are used in the constructor implementation.
1000
1035
  */
1001
1036
  constructor(inputId?: string | number | ObjectId | ObjectIdLike | Uint8Array);
1002
1037
  /**
@@ -98,8 +98,8 @@ class BSONError extends Error {
98
98
  get name() {
99
99
  return 'BSONError';
100
100
  }
101
- constructor(message) {
102
- super(message);
101
+ constructor(message, options) {
102
+ super(message, options);
103
103
  }
104
104
  static isBSONError(value) {
105
105
  return (value != null &&
@@ -128,6 +128,79 @@ class BSONRuntimeError extends BSONError {
128
128
  }
129
129
  }
130
130
 
131
+ const FIRST_BIT = 0x80;
132
+ const FIRST_TWO_BITS = 0xc0;
133
+ const FIRST_THREE_BITS = 0xe0;
134
+ const FIRST_FOUR_BITS = 0xf0;
135
+ const FIRST_FIVE_BITS = 0xf8;
136
+ const TWO_BIT_CHAR = 0xc0;
137
+ const THREE_BIT_CHAR = 0xe0;
138
+ const FOUR_BIT_CHAR = 0xf0;
139
+ const CONTINUING_CHAR = 0x80;
140
+ function validateUtf8(bytes, start, end) {
141
+ let continuation = 0;
142
+ for (let i = start; i < end; i += 1) {
143
+ const byte = bytes[i];
144
+ if (continuation) {
145
+ if ((byte & FIRST_TWO_BITS) !== CONTINUING_CHAR) {
146
+ return false;
147
+ }
148
+ continuation -= 1;
149
+ }
150
+ else if (byte & FIRST_BIT) {
151
+ if ((byte & FIRST_THREE_BITS) === TWO_BIT_CHAR) {
152
+ continuation = 1;
153
+ }
154
+ else if ((byte & FIRST_FOUR_BITS) === THREE_BIT_CHAR) {
155
+ continuation = 2;
156
+ }
157
+ else if ((byte & FIRST_FIVE_BITS) === FOUR_BIT_CHAR) {
158
+ continuation = 3;
159
+ }
160
+ else {
161
+ return false;
162
+ }
163
+ }
164
+ }
165
+ return !continuation;
166
+ }
167
+
168
+ function tryLatin(uint8array, start, end) {
169
+ if (uint8array.length === 0) {
170
+ return '';
171
+ }
172
+ const stringByteLength = end - start;
173
+ if (stringByteLength === 0) {
174
+ return '';
175
+ }
176
+ if (stringByteLength > 20) {
177
+ return null;
178
+ }
179
+ if (stringByteLength === 1 && uint8array[start] < 128) {
180
+ return String.fromCharCode(uint8array[start]);
181
+ }
182
+ if (stringByteLength === 2 && uint8array[start] < 128 && uint8array[start + 1] < 128) {
183
+ return String.fromCharCode(uint8array[start]) + String.fromCharCode(uint8array[start + 1]);
184
+ }
185
+ if (stringByteLength === 3 &&
186
+ uint8array[start] < 128 &&
187
+ uint8array[start + 1] < 128 &&
188
+ uint8array[start + 2] < 128) {
189
+ return (String.fromCharCode(uint8array[start]) +
190
+ String.fromCharCode(uint8array[start + 1]) +
191
+ String.fromCharCode(uint8array[start + 2]));
192
+ }
193
+ const latinBytes = [];
194
+ for (let i = start; i < end; i++) {
195
+ const byte = uint8array[i];
196
+ if (byte > 127) {
197
+ return null;
198
+ }
199
+ latinBytes.push(byte);
200
+ }
201
+ return String.fromCharCode(...latinBytes);
202
+ }
203
+
131
204
  function nodejsMathRandomBytes(byteLength) {
132
205
  return nodeJsByteUtils.fromNumberArray(Array.from({ length: byteLength }, () => Math.floor(Math.random() * 256)));
133
206
  }
@@ -186,8 +259,23 @@ const nodeJsByteUtils = {
186
259
  fromUTF8(text) {
187
260
  return Buffer.from(text, 'utf8');
188
261
  },
189
- toUTF8(buffer, start, end) {
190
- return nodeJsByteUtils.toLocalBufferType(buffer).toString('utf8', start, end);
262
+ toUTF8(buffer, start, end, fatal) {
263
+ const basicLatin = end - start <= 20 ? tryLatin(buffer, start, end) : null;
264
+ if (basicLatin != null) {
265
+ return basicLatin;
266
+ }
267
+ const string = nodeJsByteUtils.toLocalBufferType(buffer).toString('utf8', start, end);
268
+ if (fatal) {
269
+ for (let i = 0; i < string.length; i++) {
270
+ if (string.charCodeAt(i) === 0xfffd) {
271
+ if (!validateUtf8(buffer, start, end)) {
272
+ throw new BSONError('Invalid UTF-8 string in BSON document');
273
+ }
274
+ break;
275
+ }
276
+ }
277
+ }
278
+ return string;
191
279
  },
192
280
  utf8ByteLength(input) {
193
281
  return Buffer.byteLength(input, 'utf8');
@@ -297,8 +385,20 @@ const webByteUtils = {
297
385
  fromUTF8(text) {
298
386
  return new TextEncoder().encode(text);
299
387
  },
300
- toUTF8(uint8array, start, end) {
301
- return new TextDecoder('utf8', { fatal: false }).decode(uint8array.slice(start, end));
388
+ toUTF8(uint8array, start, end, fatal) {
389
+ const basicLatin = end - start <= 20 ? tryLatin(uint8array, start, end) : null;
390
+ if (basicLatin != null) {
391
+ return basicLatin;
392
+ }
393
+ if (fatal) {
394
+ try {
395
+ return new TextDecoder('utf8', { fatal }).decode(uint8array.slice(start, end));
396
+ }
397
+ catch (cause) {
398
+ throw new BSONError('Invalid UTF-8 string in BSON document', { cause });
399
+ }
400
+ }
401
+ return new TextDecoder('utf8', { fatal }).decode(uint8array.slice(start, end));
302
402
  },
303
403
  utf8ByteLength(input) {
304
404
  return webByteUtils.fromUTF8(input).byteLength;
@@ -419,8 +519,8 @@ class Binary extends BSONValue {
419
519
  if (encoding === 'base64')
420
520
  return ByteUtils.toBase64(this.buffer);
421
521
  if (encoding === 'utf8' || encoding === 'utf-8')
422
- return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength);
423
- return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength);
522
+ return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength, false);
523
+ return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength, false);
424
524
  }
425
525
  toExtendedJSON(options) {
426
526
  options = options || {};
@@ -2508,43 +2608,6 @@ class Timestamp extends LongWithoutOverridesClass {
2508
2608
  }
2509
2609
  Timestamp.MAX_VALUE = Long.MAX_UNSIGNED_VALUE;
2510
2610
 
2511
- const FIRST_BIT = 0x80;
2512
- const FIRST_TWO_BITS = 0xc0;
2513
- const FIRST_THREE_BITS = 0xe0;
2514
- const FIRST_FOUR_BITS = 0xf0;
2515
- const FIRST_FIVE_BITS = 0xf8;
2516
- const TWO_BIT_CHAR = 0xc0;
2517
- const THREE_BIT_CHAR = 0xe0;
2518
- const FOUR_BIT_CHAR = 0xf0;
2519
- const CONTINUING_CHAR = 0x80;
2520
- function validateUtf8(bytes, start, end) {
2521
- let continuation = 0;
2522
- for (let i = start; i < end; i += 1) {
2523
- const byte = bytes[i];
2524
- if (continuation) {
2525
- if ((byte & FIRST_TWO_BITS) !== CONTINUING_CHAR) {
2526
- return false;
2527
- }
2528
- continuation -= 1;
2529
- }
2530
- else if (byte & FIRST_BIT) {
2531
- if ((byte & FIRST_THREE_BITS) === TWO_BIT_CHAR) {
2532
- continuation = 1;
2533
- }
2534
- else if ((byte & FIRST_FOUR_BITS) === THREE_BIT_CHAR) {
2535
- continuation = 2;
2536
- }
2537
- else if ((byte & FIRST_FIVE_BITS) === FOUR_BIT_CHAR) {
2538
- continuation = 3;
2539
- }
2540
- else {
2541
- return false;
2542
- }
2543
- }
2544
- }
2545
- return !continuation;
2546
- }
2547
-
2548
2611
  const JS_INT_MAX_LONG = Long.fromNumber(JS_INT_MAX);
2549
2612
  const JS_INT_MIN_LONG = Long.fromNumber(JS_INT_MIN);
2550
2613
  function internalDeserialize(buffer, options, isArray) {
@@ -2636,7 +2699,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2636
2699
  }
2637
2700
  if (i >= buffer.byteLength)
2638
2701
  throw new BSONError('Bad BSON Document: illegal CString');
2639
- const name = isArray ? arrayIndex++ : ByteUtils.toUTF8(buffer, index, i);
2702
+ const name = isArray ? arrayIndex++ : ByteUtils.toUTF8(buffer, index, i, false);
2640
2703
  let shouldValidateKey = true;
2641
2704
  if (globalUTFValidation || utf8KeysSet.has(name)) {
2642
2705
  shouldValidateKey = validationSetting;
@@ -2659,7 +2722,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2659
2722
  buffer[index + stringSize - 1] !== 0) {
2660
2723
  throw new BSONError('bad string length in bson');
2661
2724
  }
2662
- value = getValidatedString(buffer, index, index + stringSize - 1, shouldValidateKey);
2725
+ value = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
2663
2726
  index = index + stringSize;
2664
2727
  }
2665
2728
  else if (elementType === BSON_DATA_OID) {
@@ -2851,7 +2914,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2851
2914
  }
2852
2915
  if (i >= buffer.length)
2853
2916
  throw new BSONError('Bad BSON Document: illegal CString');
2854
- const source = ByteUtils.toUTF8(buffer, index, i);
2917
+ const source = ByteUtils.toUTF8(buffer, index, i, false);
2855
2918
  index = i + 1;
2856
2919
  i = index;
2857
2920
  while (buffer[i] !== 0x00 && i < buffer.length) {
@@ -2859,7 +2922,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2859
2922
  }
2860
2923
  if (i >= buffer.length)
2861
2924
  throw new BSONError('Bad BSON Document: illegal CString');
2862
- const regExpOptions = ByteUtils.toUTF8(buffer, index, i);
2925
+ const regExpOptions = ByteUtils.toUTF8(buffer, index, i, false);
2863
2926
  index = i + 1;
2864
2927
  const optionsArray = new Array(regExpOptions.length);
2865
2928
  for (i = 0; i < regExpOptions.length; i++) {
@@ -2884,7 +2947,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2884
2947
  }
2885
2948
  if (i >= buffer.length)
2886
2949
  throw new BSONError('Bad BSON Document: illegal CString');
2887
- const source = ByteUtils.toUTF8(buffer, index, i);
2950
+ const source = ByteUtils.toUTF8(buffer, index, i, false);
2888
2951
  index = i + 1;
2889
2952
  i = index;
2890
2953
  while (buffer[i] !== 0x00 && i < buffer.length) {
@@ -2892,7 +2955,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2892
2955
  }
2893
2956
  if (i >= buffer.length)
2894
2957
  throw new BSONError('Bad BSON Document: illegal CString');
2895
- const regExpOptions = ByteUtils.toUTF8(buffer, index, i);
2958
+ const regExpOptions = ByteUtils.toUTF8(buffer, index, i, false);
2896
2959
  index = i + 1;
2897
2960
  value = new BSONRegExp(source, regExpOptions);
2898
2961
  }
@@ -2906,7 +2969,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2906
2969
  buffer[index + stringSize - 1] !== 0) {
2907
2970
  throw new BSONError('bad string length in bson');
2908
2971
  }
2909
- const symbol = getValidatedString(buffer, index, index + stringSize - 1, shouldValidateKey);
2972
+ const symbol = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
2910
2973
  value = promoteValues ? symbol : new BSONSymbol(symbol);
2911
2974
  index = index + stringSize;
2912
2975
  }
@@ -2937,7 +3000,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2937
3000
  buffer[index + stringSize - 1] !== 0) {
2938
3001
  throw new BSONError('bad string length in bson');
2939
3002
  }
2940
- const functionString = getValidatedString(buffer, index, index + stringSize - 1, shouldValidateKey);
3003
+ const functionString = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
2941
3004
  value = new Code(functionString);
2942
3005
  index = index + stringSize;
2943
3006
  }
@@ -2958,7 +3021,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2958
3021
  buffer[index + stringSize - 1] !== 0) {
2959
3022
  throw new BSONError('bad string length in bson');
2960
3023
  }
2961
- const functionString = getValidatedString(buffer, index, index + stringSize - 1, shouldValidateKey);
3024
+ const functionString = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
2962
3025
  index = index + stringSize;
2963
3026
  const _index = index;
2964
3027
  const objectSize = buffer[index] |
@@ -2989,7 +3052,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2989
3052
  throw new BSONError('Invalid UTF-8 string in BSON document');
2990
3053
  }
2991
3054
  }
2992
- const namespace = ByteUtils.toUTF8(buffer, index, index + stringSize - 1);
3055
+ const namespace = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, false);
2993
3056
  index = index + stringSize;
2994
3057
  const oidBuffer = ByteUtils.allocate(12);
2995
3058
  oidBuffer.set(buffer.subarray(index, index + 12), 0);
@@ -3028,20 +3091,6 @@ function deserializeObject(buffer, index, options, isArray = false) {
3028
3091
  }
3029
3092
  return object;
3030
3093
  }
3031
- function getValidatedString(buffer, start, end, shouldValidateUtf8) {
3032
- const value = ByteUtils.toUTF8(buffer, start, end);
3033
- if (shouldValidateUtf8) {
3034
- for (let i = 0; i < value.length; i++) {
3035
- if (value.charCodeAt(i) === 0xfffd) {
3036
- if (!validateUtf8(buffer, start, end)) {
3037
- throw new BSONError('Invalid UTF-8 string in BSON document');
3038
- }
3039
- break;
3040
- }
3041
- }
3042
- }
3043
- return value;
3044
- }
3045
3094
 
3046
3095
  const regexp = /\x00/;
3047
3096
  const ignoreKeys = new Set(['$db', '$ref', '$id', '$clusterTime']);