bson 6.5.0 → 6.7.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
@@ -144,47 +144,27 @@ class BSONOffsetError extends BSONError {
144
144
  get name() {
145
145
  return 'BSONOffsetError';
146
146
  }
147
- constructor(message, offset) {
148
- super(`${message}. offset: ${offset}`);
147
+ constructor(message, offset, options) {
148
+ super(`${message}. offset: ${offset}`, options);
149
149
  this.offset = offset;
150
150
  }
151
151
  }
152
152
 
153
- const FIRST_BIT = 0x80;
154
- const FIRST_TWO_BITS = 0xc0;
155
- const FIRST_THREE_BITS = 0xe0;
156
- const FIRST_FOUR_BITS = 0xf0;
157
- const FIRST_FIVE_BITS = 0xf8;
158
- const TWO_BIT_CHAR = 0xc0;
159
- const THREE_BIT_CHAR = 0xe0;
160
- const FOUR_BIT_CHAR = 0xf0;
161
- const CONTINUING_CHAR = 0x80;
162
- function validateUtf8(bytes, start, end) {
163
- let continuation = 0;
164
- for (let i = start; i < end; i += 1) {
165
- const byte = bytes[i];
166
- if (continuation) {
167
- if ((byte & FIRST_TWO_BITS) !== CONTINUING_CHAR) {
168
- return false;
169
- }
170
- continuation -= 1;
153
+ const { TextDecoder } = require('../vendor/text-encoding');
154
+ let TextDecoderFatal;
155
+ let TextDecoderNonFatal;
156
+ function parseUtf8(buffer, start, end, fatal) {
157
+ if (fatal) {
158
+ TextDecoderFatal ??= new TextDecoder('utf8', { fatal: true });
159
+ try {
160
+ return TextDecoderFatal.decode(buffer.subarray(start, end));
171
161
  }
172
- else if (byte & FIRST_BIT) {
173
- if ((byte & FIRST_THREE_BITS) === TWO_BIT_CHAR) {
174
- continuation = 1;
175
- }
176
- else if ((byte & FIRST_FOUR_BITS) === THREE_BIT_CHAR) {
177
- continuation = 2;
178
- }
179
- else if ((byte & FIRST_FIVE_BITS) === FOUR_BIT_CHAR) {
180
- continuation = 3;
181
- }
182
- else {
183
- return false;
184
- }
162
+ catch (cause) {
163
+ throw new BSONError('Invalid UTF-8 string in BSON document', { cause });
185
164
  }
186
165
  }
187
- return !continuation;
166
+ TextDecoderNonFatal ??= new TextDecoder('utf8', { fatal: false });
167
+ return TextDecoderNonFatal.decode(buffer.subarray(start, end));
188
168
  }
189
169
 
190
170
  function tryReadBasicLatin(uint8array, start, end) {
@@ -305,9 +285,7 @@ const nodeJsByteUtils = {
305
285
  if (fatal) {
306
286
  for (let i = 0; i < string.length; i++) {
307
287
  if (string.charCodeAt(i) === 0xfffd) {
308
- if (!validateUtf8(buffer, start, end)) {
309
- throw new BSONError('Invalid UTF-8 string in BSON document');
310
- }
288
+ parseUtf8(buffer, start, end, true);
311
289
  break;
312
290
  }
313
291
  }
@@ -327,7 +305,7 @@ const nodeJsByteUtils = {
327
305
  randomBytes: nodejsRandomBytes
328
306
  };
329
307
 
330
- const { TextEncoder, TextDecoder } = require('../vendor/text-encoding');
308
+ const { TextEncoder } = require('../vendor/text-encoding');
331
309
  const { encode: btoa, decode: atob } = require('../vendor/base64');
332
310
  function isReactNative() {
333
311
  const { navigator } = globalThis;
@@ -433,15 +411,7 @@ const webByteUtils = {
433
411
  if (basicLatin != null) {
434
412
  return basicLatin;
435
413
  }
436
- if (fatal) {
437
- try {
438
- return new TextDecoder('utf8', { fatal }).decode(uint8array.slice(start, end));
439
- }
440
- catch (cause) {
441
- throw new BSONError('Invalid UTF-8 string in BSON document', { cause });
442
- }
443
- }
444
- return new TextDecoder('utf8', { fatal }).decode(uint8array.slice(start, end));
414
+ return parseUtf8(uint8array, start, end, fatal);
445
415
  },
446
416
  utf8ByteLength(input) {
447
417
  return new TextEncoder().encode(input).byteLength;
@@ -549,16 +519,16 @@ class Binary extends BSONValue {
549
519
  return this.position;
550
520
  }
551
521
  toJSON() {
552
- return ByteUtils.toBase64(this.buffer);
522
+ return ByteUtils.toBase64(this.buffer.subarray(0, this.position));
553
523
  }
554
524
  toString(encoding) {
555
525
  if (encoding === 'hex')
556
- return ByteUtils.toHex(this.buffer);
526
+ return ByteUtils.toHex(this.buffer.subarray(0, this.position));
557
527
  if (encoding === 'base64')
558
- return ByteUtils.toBase64(this.buffer);
528
+ return ByteUtils.toBase64(this.buffer.subarray(0, this.position));
559
529
  if (encoding === 'utf8' || encoding === 'utf-8')
560
- return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength, false);
561
- return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength, false);
530
+ return ByteUtils.toUTF8(this.buffer, 0, this.position, false);
531
+ return ByteUtils.toUTF8(this.buffer, 0, this.position, false);
562
532
  }
563
533
  toExtendedJSON(options) {
564
534
  options = options || {};
@@ -854,6 +824,32 @@ class DBRef extends BSONValue {
854
824
  }
855
825
  }
856
826
 
827
+ function removeLeadingZerosAndExplicitPlus(str) {
828
+ if (str === '') {
829
+ return str;
830
+ }
831
+ let startIndex = 0;
832
+ const isNegative = str[startIndex] === '-';
833
+ const isExplicitlyPositive = str[startIndex] === '+';
834
+ if (isExplicitlyPositive || isNegative) {
835
+ startIndex += 1;
836
+ }
837
+ let foundInsignificantZero = false;
838
+ for (; startIndex < str.length && str[startIndex] === '0'; ++startIndex) {
839
+ foundInsignificantZero = true;
840
+ }
841
+ if (!foundInsignificantZero) {
842
+ return isExplicitlyPositive ? str.slice(1) : str;
843
+ }
844
+ return `${isNegative ? '-' : ''}${str.length === startIndex ? '0' : str.slice(startIndex)}`;
845
+ }
846
+ function validateStringCharacters(str, radix) {
847
+ radix = radix ?? 10;
848
+ const validCharacters = '0123456789abcdefghijklmnopqrstuvwxyz'.slice(0, radix);
849
+ const regex = new RegExp(`[^-+${validCharacters}]`, 'i');
850
+ return regex.test(str) ? false : str;
851
+ }
852
+
857
853
  let wasm = undefined;
858
854
  try {
859
855
  wasm = new WebAssembly.Instance(new WebAssembly.Module(new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 13, 2, 96, 0, 1, 127, 96, 4, 127, 127, 127, 127, 1, 127, 3, 7, 6, 0, 1, 1, 1, 1, 1, 6, 6, 1, 127, 1, 65, 0, 11, 7, 50, 6, 3, 109, 117, 108, 0, 1, 5, 100, 105, 118, 95, 115, 0, 2, 5, 100, 105, 118, 95, 117, 0, 3, 5, 114, 101, 109, 95, 115, 0, 4, 5, 114, 101, 109, 95, 117, 0, 5, 8, 103, 101, 116, 95, 104, 105, 103, 104, 0, 0, 10, 191, 1, 6, 4, 0, 35, 0, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 126, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 127, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 128, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 129, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 130, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11])), {}).exports;
@@ -942,25 +938,16 @@ class Long extends BSONValue {
942
938
  static fromBigInt(value, unsigned) {
943
939
  return Long.fromString(value.toString(), unsigned);
944
940
  }
945
- static fromString(str, unsigned, radix) {
941
+ static _fromString(str, unsigned, radix) {
946
942
  if (str.length === 0)
947
943
  throw new BSONError('empty string');
948
- if (str === 'NaN' || str === 'Infinity' || str === '+Infinity' || str === '-Infinity')
949
- return Long.ZERO;
950
- if (typeof unsigned === 'number') {
951
- (radix = unsigned), (unsigned = false);
952
- }
953
- else {
954
- unsigned = !!unsigned;
955
- }
956
- radix = radix || 10;
957
944
  if (radix < 2 || 36 < radix)
958
945
  throw new BSONError('radix');
959
946
  let p;
960
947
  if ((p = str.indexOf('-')) > 0)
961
948
  throw new BSONError('interior hyphen');
962
949
  else if (p === 0) {
963
- return Long.fromString(str.substring(1), unsigned, radix).neg();
950
+ return Long._fromString(str.substring(1), unsigned, radix).neg();
964
951
  }
965
952
  const radixToPower = Long.fromNumber(Math.pow(radix, 8));
966
953
  let result = Long.ZERO;
@@ -978,6 +965,45 @@ class Long extends BSONValue {
978
965
  result.unsigned = unsigned;
979
966
  return result;
980
967
  }
968
+ static fromStringStrict(str, unsignedOrRadix, radix) {
969
+ let unsigned = false;
970
+ if (typeof unsignedOrRadix === 'number') {
971
+ (radix = unsignedOrRadix), (unsignedOrRadix = false);
972
+ }
973
+ else {
974
+ unsigned = !!unsignedOrRadix;
975
+ }
976
+ radix ??= 10;
977
+ if (str.trim() !== str) {
978
+ throw new BSONError(`Input: '${str}' contains leading and/or trailing whitespace`);
979
+ }
980
+ if (!validateStringCharacters(str, radix)) {
981
+ throw new BSONError(`Input: '${str}' contains invalid characters for radix: ${radix}`);
982
+ }
983
+ const cleanedStr = removeLeadingZerosAndExplicitPlus(str);
984
+ const result = Long._fromString(cleanedStr, unsigned, radix);
985
+ if (result.toString(radix).toLowerCase() !== cleanedStr.toLowerCase()) {
986
+ throw new BSONError(`Input: ${str} is not representable as ${result.unsigned ? 'an unsigned' : 'a signed'} 64-bit Long ${radix != null ? `with radix: ${radix}` : ''}`);
987
+ }
988
+ return result;
989
+ }
990
+ static fromString(str, unsignedOrRadix, radix) {
991
+ let unsigned = false;
992
+ if (typeof unsignedOrRadix === 'number') {
993
+ (radix = unsignedOrRadix), (unsignedOrRadix = false);
994
+ }
995
+ else {
996
+ unsigned = !!unsignedOrRadix;
997
+ }
998
+ radix ??= 10;
999
+ if (str === 'NaN' && radix < 24) {
1000
+ return Long.ZERO;
1001
+ }
1002
+ else if ((str === 'Infinity' || str === '+Infinity' || str === '-Infinity') && radix < 35) {
1003
+ return Long.ZERO;
1004
+ }
1005
+ return Long._fromString(str, unsigned, radix);
1006
+ }
981
1007
  static fromBytes(bytes, unsigned, le) {
982
1008
  return le ? Long.fromBytesLE(bytes, unsigned) : Long.fromBytesBE(bytes, unsigned);
983
1009
  }
@@ -2055,6 +2081,28 @@ class Double extends BSONValue {
2055
2081
  }
2056
2082
  this.value = +value;
2057
2083
  }
2084
+ static fromString(value) {
2085
+ const coercedValue = Number(value);
2086
+ if (value === 'NaN')
2087
+ return new Double(NaN);
2088
+ if (value === 'Infinity')
2089
+ return new Double(Infinity);
2090
+ if (value === '-Infinity')
2091
+ return new Double(-Infinity);
2092
+ if (!Number.isFinite(coercedValue)) {
2093
+ throw new BSONError(`Input: ${value} is not representable as a Double`);
2094
+ }
2095
+ if (value.trim() !== value) {
2096
+ throw new BSONError(`Input: '${value}' contains whitespace`);
2097
+ }
2098
+ if (value === '') {
2099
+ throw new BSONError(`Input is an empty string`);
2100
+ }
2101
+ if (/[^-0-9.+eE]/.test(value)) {
2102
+ throw new BSONError(`Input: '${value}' is not in decimal or exponential notation`);
2103
+ }
2104
+ return new Double(coercedValue);
2105
+ }
2058
2106
  valueOf() {
2059
2107
  return this.value;
2060
2108
  }
@@ -2096,6 +2144,23 @@ class Int32 extends BSONValue {
2096
2144
  }
2097
2145
  this.value = +value | 0;
2098
2146
  }
2147
+ static fromString(value) {
2148
+ const cleanedValue = removeLeadingZerosAndExplicitPlus(value);
2149
+ const coercedValue = Number(value);
2150
+ if (BSON_INT32_MAX < coercedValue) {
2151
+ throw new BSONError(`Input: '${value}' is larger than the maximum value for Int32`);
2152
+ }
2153
+ else if (BSON_INT32_MIN > coercedValue) {
2154
+ throw new BSONError(`Input: '${value}' is smaller than the minimum value for Int32`);
2155
+ }
2156
+ else if (!Number.isSafeInteger(coercedValue)) {
2157
+ throw new BSONError(`Input: '${value}' is not a safe integer`);
2158
+ }
2159
+ else if (coercedValue.toString() !== cleanedValue) {
2160
+ throw new BSONError(`Input: '${value}' is not a valid Int32 string`);
2161
+ }
2162
+ return new Int32(coercedValue);
2163
+ }
2099
2164
  valueOf() {
2100
2165
  return this.value;
2101
2166
  }
@@ -2154,6 +2219,15 @@ const FLOAT_BYTES = new Uint8Array(FLOAT.buffer, 0, 8);
2154
2219
  FLOAT[0] = -1;
2155
2220
  const isBigEndian = FLOAT_BYTES[7] === 0;
2156
2221
  const NumberUtils = {
2222
+ getNonnegativeInt32LE(source, offset) {
2223
+ if (source[offset + 3] > 127) {
2224
+ throw new RangeError(`Size cannot be negative at offset: ${offset}`);
2225
+ }
2226
+ return (source[offset] |
2227
+ (source[offset + 1] << 8) |
2228
+ (source[offset + 2] << 16) |
2229
+ (source[offset + 3] << 24));
2230
+ },
2157
2231
  getInt32LE(source, offset) {
2158
2232
  return (source[offset] |
2159
2233
  (source[offset + 1] << 8) |
@@ -3174,12 +3248,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
3174
3248
  stringSize > buffer.length - index ||
3175
3249
  buffer[index + stringSize - 1] !== 0)
3176
3250
  throw new BSONError('bad string length in bson');
3177
- if (validation != null && validation.utf8) {
3178
- if (!validateUtf8(buffer, index, index + stringSize - 1)) {
3179
- throw new BSONError('Invalid UTF-8 string in BSON document');
3180
- }
3181
- }
3182
- const namespace = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, false);
3251
+ const namespace = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
3183
3252
  index = index + stringSize;
3184
3253
  const oidBuffer = ByteUtils.allocateUnsafe(12);
3185
3254
  for (let i = 0; i < 12; i++)
@@ -4143,13 +4212,12 @@ EJSON.deserialize = EJSONdeserialize;
4143
4212
  Object.freeze(EJSON);
4144
4213
 
4145
4214
  function getSize(source, offset) {
4146
- if (source[offset + 3] > 127) {
4147
- throw new BSONOffsetError('BSON size cannot be negative', offset);
4215
+ try {
4216
+ return NumberUtils.getNonnegativeInt32LE(source, offset);
4217
+ }
4218
+ catch (cause) {
4219
+ throw new BSONOffsetError('BSON size cannot be negative', offset, { cause });
4148
4220
  }
4149
- return (source[offset] |
4150
- (source[offset + 1] << 8) |
4151
- (source[offset + 2] << 16) |
4152
- (source[offset + 3] << 24));
4153
4221
  }
4154
4222
  function findNull(bytes, offset) {
4155
4223
  let nullTerminatorOffset = offset;
@@ -4161,6 +4229,7 @@ function findNull(bytes, offset) {
4161
4229
  return nullTerminatorOffset;
4162
4230
  }
4163
4231
  function parseToElements(bytes, startOffset = 0) {
4232
+ startOffset ??= 0;
4164
4233
  if (bytes.length < 5) {
4165
4234
  throw new BSONOffsetError(`Input must be at least 5 bytes, got ${bytes.length} bytes`, startOffset);
4166
4235
  }
@@ -4186,7 +4255,10 @@ function parseToElements(bytes, startOffset = 0) {
4186
4255
  const nameLength = findNull(bytes, offset) - nameOffset;
4187
4256
  offset += nameLength + 1;
4188
4257
  let length;
4189
- if (type === 1 || type === 18 || type === 9 || type === 17) {
4258
+ if (type === 1 ||
4259
+ type === 18 ||
4260
+ type === 9 ||
4261
+ type === 17) {
4190
4262
  length = 8;
4191
4263
  }
4192
4264
  else if (type === 16) {
@@ -4201,13 +4273,18 @@ function parseToElements(bytes, startOffset = 0) {
4201
4273
  else if (type === 8) {
4202
4274
  length = 1;
4203
4275
  }
4204
- else if (type === 10 || type === 6 || type === 127 || type === 255) {
4276
+ else if (type === 10 ||
4277
+ type === 6 ||
4278
+ type === 127 ||
4279
+ type === 255) {
4205
4280
  length = 0;
4206
4281
  }
4207
4282
  else if (type === 11) {
4208
4283
  length = findNull(bytes, findNull(bytes, offset) + 1) + 1 - offset;
4209
4284
  }
4210
- else if (type === 3 || type === 4 || type === 15) {
4285
+ else if (type === 3 ||
4286
+ type === 4 ||
4287
+ type === 15) {
4211
4288
  length = getSize(bytes, offset);
4212
4289
  }
4213
4290
  else if (type === 2 ||
@@ -4237,7 +4314,8 @@ function parseToElements(bytes, startOffset = 0) {
4237
4314
 
4238
4315
  const onDemand = Object.create(null);
4239
4316
  onDemand.parseToElements = parseToElements;
4240
- onDemand.BSONOffsetError = BSONOffsetError;
4317
+ onDemand.ByteUtils = ByteUtils;
4318
+ onDemand.NumberUtils = NumberUtils;
4241
4319
  Object.freeze(onDemand);
4242
4320
 
4243
4321
  const MAXSIZE = 1024 * 1024 * 17;
@@ -4294,6 +4372,7 @@ function deserializeStream(data, startIndex, numberOfDocuments, documents, docSt
4294
4372
  var bson = /*#__PURE__*/Object.freeze({
4295
4373
  __proto__: null,
4296
4374
  BSONError: BSONError,
4375
+ BSONOffsetError: BSONOffsetError,
4297
4376
  BSONRegExp: BSONRegExp,
4298
4377
  BSONRuntimeError: BSONRuntimeError,
4299
4378
  BSONSymbol: BSONSymbol,
@@ -4324,6 +4403,7 @@ var bson = /*#__PURE__*/Object.freeze({
4324
4403
 
4325
4404
  exports.BSON = bson;
4326
4405
  exports.BSONError = BSONError;
4406
+ exports.BSONOffsetError = BSONOffsetError;
4327
4407
  exports.BSONRegExp = BSONRegExp;
4328
4408
  exports.BSONRuntimeError = BSONRuntimeError;
4329
4409
  exports.BSONSymbol = BSONSymbol;