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/lib/bson.rn.cjs CHANGED
@@ -110,8 +110,8 @@ class BSONError extends Error {
110
110
  get name() {
111
111
  return 'BSONError';
112
112
  }
113
- constructor(message) {
114
- super(message);
113
+ constructor(message, options) {
114
+ super(message, options);
115
115
  }
116
116
  static isBSONError(value) {
117
117
  return (value != null &&
@@ -140,6 +140,79 @@ class BSONRuntimeError extends BSONError {
140
140
  }
141
141
  }
142
142
 
143
+ const FIRST_BIT = 0x80;
144
+ const FIRST_TWO_BITS = 0xc0;
145
+ const FIRST_THREE_BITS = 0xe0;
146
+ const FIRST_FOUR_BITS = 0xf0;
147
+ const FIRST_FIVE_BITS = 0xf8;
148
+ const TWO_BIT_CHAR = 0xc0;
149
+ const THREE_BIT_CHAR = 0xe0;
150
+ const FOUR_BIT_CHAR = 0xf0;
151
+ const CONTINUING_CHAR = 0x80;
152
+ function validateUtf8(bytes, start, end) {
153
+ let continuation = 0;
154
+ for (let i = start; i < end; i += 1) {
155
+ const byte = bytes[i];
156
+ if (continuation) {
157
+ if ((byte & FIRST_TWO_BITS) !== CONTINUING_CHAR) {
158
+ return false;
159
+ }
160
+ continuation -= 1;
161
+ }
162
+ else if (byte & FIRST_BIT) {
163
+ if ((byte & FIRST_THREE_BITS) === TWO_BIT_CHAR) {
164
+ continuation = 1;
165
+ }
166
+ else if ((byte & FIRST_FOUR_BITS) === THREE_BIT_CHAR) {
167
+ continuation = 2;
168
+ }
169
+ else if ((byte & FIRST_FIVE_BITS) === FOUR_BIT_CHAR) {
170
+ continuation = 3;
171
+ }
172
+ else {
173
+ return false;
174
+ }
175
+ }
176
+ }
177
+ return !continuation;
178
+ }
179
+
180
+ function tryLatin(uint8array, start, end) {
181
+ if (uint8array.length === 0) {
182
+ return '';
183
+ }
184
+ const stringByteLength = end - start;
185
+ if (stringByteLength === 0) {
186
+ return '';
187
+ }
188
+ if (stringByteLength > 20) {
189
+ return null;
190
+ }
191
+ if (stringByteLength === 1 && uint8array[start] < 128) {
192
+ return String.fromCharCode(uint8array[start]);
193
+ }
194
+ if (stringByteLength === 2 && uint8array[start] < 128 && uint8array[start + 1] < 128) {
195
+ return String.fromCharCode(uint8array[start]) + String.fromCharCode(uint8array[start + 1]);
196
+ }
197
+ if (stringByteLength === 3 &&
198
+ uint8array[start] < 128 &&
199
+ uint8array[start + 1] < 128 &&
200
+ uint8array[start + 2] < 128) {
201
+ return (String.fromCharCode(uint8array[start]) +
202
+ String.fromCharCode(uint8array[start + 1]) +
203
+ String.fromCharCode(uint8array[start + 2]));
204
+ }
205
+ const latinBytes = [];
206
+ for (let i = start; i < end; i++) {
207
+ const byte = uint8array[i];
208
+ if (byte > 127) {
209
+ return null;
210
+ }
211
+ latinBytes.push(byte);
212
+ }
213
+ return String.fromCharCode(...latinBytes);
214
+ }
215
+
143
216
  function nodejsMathRandomBytes(byteLength) {
144
217
  return nodeJsByteUtils.fromNumberArray(Array.from({ length: byteLength }, () => Math.floor(Math.random() * 256)));
145
218
  }
@@ -198,8 +271,23 @@ const nodeJsByteUtils = {
198
271
  fromUTF8(text) {
199
272
  return Buffer.from(text, 'utf8');
200
273
  },
201
- toUTF8(buffer, start, end) {
202
- return nodeJsByteUtils.toLocalBufferType(buffer).toString('utf8', start, end);
274
+ toUTF8(buffer, start, end, fatal) {
275
+ const basicLatin = end - start <= 20 ? tryLatin(buffer, start, end) : null;
276
+ if (basicLatin != null) {
277
+ return basicLatin;
278
+ }
279
+ const string = nodeJsByteUtils.toLocalBufferType(buffer).toString('utf8', start, end);
280
+ if (fatal) {
281
+ for (let i = 0; i < string.length; i++) {
282
+ if (string.charCodeAt(i) === 0xfffd) {
283
+ if (!validateUtf8(buffer, start, end)) {
284
+ throw new BSONError('Invalid UTF-8 string in BSON document');
285
+ }
286
+ break;
287
+ }
288
+ }
289
+ }
290
+ return string;
203
291
  },
204
292
  utf8ByteLength(input) {
205
293
  return Buffer.byteLength(input, 'utf8');
@@ -311,8 +399,20 @@ const webByteUtils = {
311
399
  fromUTF8(text) {
312
400
  return new TextEncoder().encode(text);
313
401
  },
314
- toUTF8(uint8array, start, end) {
315
- return new TextDecoder('utf8', { fatal: false }).decode(uint8array.slice(start, end));
402
+ toUTF8(uint8array, start, end, fatal) {
403
+ const basicLatin = end - start <= 20 ? tryLatin(uint8array, start, end) : null;
404
+ if (basicLatin != null) {
405
+ return basicLatin;
406
+ }
407
+ if (fatal) {
408
+ try {
409
+ return new TextDecoder('utf8', { fatal }).decode(uint8array.slice(start, end));
410
+ }
411
+ catch (cause) {
412
+ throw new BSONError('Invalid UTF-8 string in BSON document', { cause });
413
+ }
414
+ }
415
+ return new TextDecoder('utf8', { fatal }).decode(uint8array.slice(start, end));
316
416
  },
317
417
  utf8ByteLength(input) {
318
418
  return webByteUtils.fromUTF8(input).byteLength;
@@ -433,8 +533,8 @@ class Binary extends BSONValue {
433
533
  if (encoding === 'base64')
434
534
  return ByteUtils.toBase64(this.buffer);
435
535
  if (encoding === 'utf8' || encoding === 'utf-8')
436
- return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength);
437
- return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength);
536
+ return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength, false);
537
+ return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength, false);
438
538
  }
439
539
  toExtendedJSON(options) {
440
540
  options = options || {};
@@ -2522,43 +2622,6 @@ class Timestamp extends LongWithoutOverridesClass {
2522
2622
  }
2523
2623
  Timestamp.MAX_VALUE = Long.MAX_UNSIGNED_VALUE;
2524
2624
 
2525
- const FIRST_BIT = 0x80;
2526
- const FIRST_TWO_BITS = 0xc0;
2527
- const FIRST_THREE_BITS = 0xe0;
2528
- const FIRST_FOUR_BITS = 0xf0;
2529
- const FIRST_FIVE_BITS = 0xf8;
2530
- const TWO_BIT_CHAR = 0xc0;
2531
- const THREE_BIT_CHAR = 0xe0;
2532
- const FOUR_BIT_CHAR = 0xf0;
2533
- const CONTINUING_CHAR = 0x80;
2534
- function validateUtf8(bytes, start, end) {
2535
- let continuation = 0;
2536
- for (let i = start; i < end; i += 1) {
2537
- const byte = bytes[i];
2538
- if (continuation) {
2539
- if ((byte & FIRST_TWO_BITS) !== CONTINUING_CHAR) {
2540
- return false;
2541
- }
2542
- continuation -= 1;
2543
- }
2544
- else if (byte & FIRST_BIT) {
2545
- if ((byte & FIRST_THREE_BITS) === TWO_BIT_CHAR) {
2546
- continuation = 1;
2547
- }
2548
- else if ((byte & FIRST_FOUR_BITS) === THREE_BIT_CHAR) {
2549
- continuation = 2;
2550
- }
2551
- else if ((byte & FIRST_FIVE_BITS) === FOUR_BIT_CHAR) {
2552
- continuation = 3;
2553
- }
2554
- else {
2555
- return false;
2556
- }
2557
- }
2558
- }
2559
- return !continuation;
2560
- }
2561
-
2562
2625
  const JS_INT_MAX_LONG = Long.fromNumber(JS_INT_MAX);
2563
2626
  const JS_INT_MIN_LONG = Long.fromNumber(JS_INT_MIN);
2564
2627
  function internalDeserialize(buffer, options, isArray) {
@@ -2650,7 +2713,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2650
2713
  }
2651
2714
  if (i >= buffer.byteLength)
2652
2715
  throw new BSONError('Bad BSON Document: illegal CString');
2653
- const name = isArray ? arrayIndex++ : ByteUtils.toUTF8(buffer, index, i);
2716
+ const name = isArray ? arrayIndex++ : ByteUtils.toUTF8(buffer, index, i, false);
2654
2717
  let shouldValidateKey = true;
2655
2718
  if (globalUTFValidation || utf8KeysSet.has(name)) {
2656
2719
  shouldValidateKey = validationSetting;
@@ -2673,7 +2736,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2673
2736
  buffer[index + stringSize - 1] !== 0) {
2674
2737
  throw new BSONError('bad string length in bson');
2675
2738
  }
2676
- value = getValidatedString(buffer, index, index + stringSize - 1, shouldValidateKey);
2739
+ value = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
2677
2740
  index = index + stringSize;
2678
2741
  }
2679
2742
  else if (elementType === BSON_DATA_OID) {
@@ -2865,7 +2928,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2865
2928
  }
2866
2929
  if (i >= buffer.length)
2867
2930
  throw new BSONError('Bad BSON Document: illegal CString');
2868
- const source = ByteUtils.toUTF8(buffer, index, i);
2931
+ const source = ByteUtils.toUTF8(buffer, index, i, false);
2869
2932
  index = i + 1;
2870
2933
  i = index;
2871
2934
  while (buffer[i] !== 0x00 && i < buffer.length) {
@@ -2873,7 +2936,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2873
2936
  }
2874
2937
  if (i >= buffer.length)
2875
2938
  throw new BSONError('Bad BSON Document: illegal CString');
2876
- const regExpOptions = ByteUtils.toUTF8(buffer, index, i);
2939
+ const regExpOptions = ByteUtils.toUTF8(buffer, index, i, false);
2877
2940
  index = i + 1;
2878
2941
  const optionsArray = new Array(regExpOptions.length);
2879
2942
  for (i = 0; i < regExpOptions.length; i++) {
@@ -2898,7 +2961,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2898
2961
  }
2899
2962
  if (i >= buffer.length)
2900
2963
  throw new BSONError('Bad BSON Document: illegal CString');
2901
- const source = ByteUtils.toUTF8(buffer, index, i);
2964
+ const source = ByteUtils.toUTF8(buffer, index, i, false);
2902
2965
  index = i + 1;
2903
2966
  i = index;
2904
2967
  while (buffer[i] !== 0x00 && i < buffer.length) {
@@ -2906,7 +2969,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2906
2969
  }
2907
2970
  if (i >= buffer.length)
2908
2971
  throw new BSONError('Bad BSON Document: illegal CString');
2909
- const regExpOptions = ByteUtils.toUTF8(buffer, index, i);
2972
+ const regExpOptions = ByteUtils.toUTF8(buffer, index, i, false);
2910
2973
  index = i + 1;
2911
2974
  value = new BSONRegExp(source, regExpOptions);
2912
2975
  }
@@ -2920,7 +2983,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2920
2983
  buffer[index + stringSize - 1] !== 0) {
2921
2984
  throw new BSONError('bad string length in bson');
2922
2985
  }
2923
- const symbol = getValidatedString(buffer, index, index + stringSize - 1, shouldValidateKey);
2986
+ const symbol = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
2924
2987
  value = promoteValues ? symbol : new BSONSymbol(symbol);
2925
2988
  index = index + stringSize;
2926
2989
  }
@@ -2951,7 +3014,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2951
3014
  buffer[index + stringSize - 1] !== 0) {
2952
3015
  throw new BSONError('bad string length in bson');
2953
3016
  }
2954
- const functionString = getValidatedString(buffer, index, index + stringSize - 1, shouldValidateKey);
3017
+ const functionString = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
2955
3018
  value = new Code(functionString);
2956
3019
  index = index + stringSize;
2957
3020
  }
@@ -2972,7 +3035,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2972
3035
  buffer[index + stringSize - 1] !== 0) {
2973
3036
  throw new BSONError('bad string length in bson');
2974
3037
  }
2975
- const functionString = getValidatedString(buffer, index, index + stringSize - 1, shouldValidateKey);
3038
+ const functionString = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
2976
3039
  index = index + stringSize;
2977
3040
  const _index = index;
2978
3041
  const objectSize = buffer[index] |
@@ -3003,7 +3066,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
3003
3066
  throw new BSONError('Invalid UTF-8 string in BSON document');
3004
3067
  }
3005
3068
  }
3006
- const namespace = ByteUtils.toUTF8(buffer, index, index + stringSize - 1);
3069
+ const namespace = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, false);
3007
3070
  index = index + stringSize;
3008
3071
  const oidBuffer = ByteUtils.allocate(12);
3009
3072
  oidBuffer.set(buffer.subarray(index, index + 12), 0);
@@ -3042,20 +3105,6 @@ function deserializeObject(buffer, index, options, isArray = false) {
3042
3105
  }
3043
3106
  return object;
3044
3107
  }
3045
- function getValidatedString(buffer, start, end, shouldValidateUtf8) {
3046
- const value = ByteUtils.toUTF8(buffer, start, end);
3047
- if (shouldValidateUtf8) {
3048
- for (let i = 0; i < value.length; i++) {
3049
- if (value.charCodeAt(i) === 0xfffd) {
3050
- if (!validateUtf8(buffer, start, end)) {
3051
- throw new BSONError('Invalid UTF-8 string in BSON document');
3052
- }
3053
- break;
3054
- }
3055
- }
3056
- }
3057
- return value;
3058
- }
3059
3108
 
3060
3109
  const regexp = /\x00/;
3061
3110
  const ignoreKeys = new Set(['$db', '$ref', '$id', '$clusterTime']);