bson 6.3.0 → 6.5.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
@@ -78,6 +78,7 @@ const BSON_BINARY_SUBTYPE_UUID_NEW = 4;
78
78
  const BSON_BINARY_SUBTYPE_MD5 = 5;
79
79
  const BSON_BINARY_SUBTYPE_ENCRYPTED = 6;
80
80
  const BSON_BINARY_SUBTYPE_COLUMN = 7;
81
+ const BSON_BINARY_SUBTYPE_SENSITIVE = 8;
81
82
  const BSON_BINARY_SUBTYPE_USER_DEFINED = 128;
82
83
  const BSONType = Object.freeze({
83
84
  double: 1,
@@ -139,6 +140,15 @@ class BSONRuntimeError extends BSONError {
139
140
  super(message);
140
141
  }
141
142
  }
143
+ class BSONOffsetError extends BSONError {
144
+ get name() {
145
+ return 'BSONOffsetError';
146
+ }
147
+ constructor(message, offset) {
148
+ super(`${message}. offset: ${offset}`);
149
+ this.offset = offset;
150
+ }
151
+ }
142
152
 
143
153
  const FIRST_BIT = 0x80;
144
154
  const FIRST_TWO_BITS = 0xc0;
@@ -177,7 +187,7 @@ function validateUtf8(bytes, start, end) {
177
187
  return !continuation;
178
188
  }
179
189
 
180
- function tryLatin(uint8array, start, end) {
190
+ function tryReadBasicLatin(uint8array, start, end) {
181
191
  if (uint8array.length === 0) {
182
192
  return '';
183
193
  }
@@ -212,6 +222,21 @@ function tryLatin(uint8array, start, end) {
212
222
  }
213
223
  return String.fromCharCode(...latinBytes);
214
224
  }
225
+ function tryWriteBasicLatin(destination, source, offset) {
226
+ if (source.length === 0)
227
+ return 0;
228
+ if (source.length > 25)
229
+ return null;
230
+ if (destination.length - offset < source.length)
231
+ return null;
232
+ for (let charOffset = 0, destinationOffset = offset; charOffset < source.length; charOffset++, destinationOffset++) {
233
+ const char = source.charCodeAt(charOffset);
234
+ if (char > 127)
235
+ return null;
236
+ destination[destinationOffset] = char;
237
+ }
238
+ return source.length;
239
+ }
215
240
 
216
241
  function nodejsMathRandomBytes(byteLength) {
217
242
  return nodeJsByteUtils.fromNumberArray(Array.from({ length: byteLength }, () => Math.floor(Math.random() * 256)));
@@ -244,6 +269,9 @@ const nodeJsByteUtils = {
244
269
  allocate(size) {
245
270
  return Buffer.alloc(size);
246
271
  },
272
+ allocateUnsafe(size) {
273
+ return Buffer.allocUnsafe(size);
274
+ },
247
275
  equals(a, b) {
248
276
  return nodeJsByteUtils.toLocalBufferType(a).equals(b);
249
277
  },
@@ -268,11 +296,8 @@ const nodeJsByteUtils = {
268
296
  toHex(buffer) {
269
297
  return nodeJsByteUtils.toLocalBufferType(buffer).toString('hex');
270
298
  },
271
- fromUTF8(text) {
272
- return Buffer.from(text, 'utf8');
273
- },
274
299
  toUTF8(buffer, start, end, fatal) {
275
- const basicLatin = end - start <= 20 ? tryLatin(buffer, start, end) : null;
300
+ const basicLatin = end - start <= 20 ? tryReadBasicLatin(buffer, start, end) : null;
276
301
  if (basicLatin != null) {
277
302
  return basicLatin;
278
303
  }
@@ -293,6 +318,10 @@ const nodeJsByteUtils = {
293
318
  return Buffer.byteLength(input, 'utf8');
294
319
  },
295
320
  encodeUTF8Into(buffer, source, byteOffset) {
321
+ const latinBytesWritten = tryWriteBasicLatin(buffer, source, byteOffset);
322
+ if (latinBytesWritten != null) {
323
+ return latinBytesWritten;
324
+ }
296
325
  return nodeJsByteUtils.toLocalBufferType(buffer).write(source, byteOffset, undefined, 'utf8');
297
326
  },
298
327
  randomBytes: nodejsRandomBytes
@@ -350,6 +379,9 @@ const webByteUtils = {
350
379
  }
351
380
  return new Uint8Array(size);
352
381
  },
382
+ allocateUnsafe(size) {
383
+ return webByteUtils.allocate(size);
384
+ },
353
385
  equals(a, b) {
354
386
  if (a.byteLength !== b.byteLength) {
355
387
  return false;
@@ -396,11 +428,8 @@ const webByteUtils = {
396
428
  toHex(uint8array) {
397
429
  return Array.from(uint8array, byte => byte.toString(16).padStart(2, '0')).join('');
398
430
  },
399
- fromUTF8(text) {
400
- return new TextEncoder().encode(text);
401
- },
402
431
  toUTF8(uint8array, start, end, fatal) {
403
- const basicLatin = end - start <= 20 ? tryLatin(uint8array, start, end) : null;
432
+ const basicLatin = end - start <= 20 ? tryReadBasicLatin(uint8array, start, end) : null;
404
433
  if (basicLatin != null) {
405
434
  return basicLatin;
406
435
  }
@@ -415,11 +444,11 @@ const webByteUtils = {
415
444
  return new TextDecoder('utf8', { fatal }).decode(uint8array.slice(start, end));
416
445
  },
417
446
  utf8ByteLength(input) {
418
- return webByteUtils.fromUTF8(input).byteLength;
447
+ return new TextEncoder().encode(input).byteLength;
419
448
  },
420
- encodeUTF8Into(buffer, source, byteOffset) {
421
- const bytes = webByteUtils.fromUTF8(source);
422
- buffer.set(bytes, byteOffset);
449
+ encodeUTF8Into(uint8array, source, byteOffset) {
450
+ const bytes = new TextEncoder().encode(source);
451
+ uint8array.set(bytes, byteOffset);
423
452
  return bytes.byteLength;
424
453
  },
425
454
  randomBytes: webRandomBytes
@@ -427,11 +456,6 @@ const webByteUtils = {
427
456
 
428
457
  const hasGlobalBuffer = typeof Buffer === 'function' && Buffer.prototype?._isBuffer !== true;
429
458
  const ByteUtils = hasGlobalBuffer ? nodeJsByteUtils : webByteUtils;
430
- class BSONDataView extends DataView {
431
- static fromUint8Array(input) {
432
- return new DataView(input.buffer, input.byteOffset, input.byteLength);
433
- }
434
- }
435
459
 
436
460
  class BSONValue {
437
461
  get [Symbol.for('@@mdb.bson.version')]() {
@@ -608,6 +632,7 @@ Binary.SUBTYPE_UUID = 4;
608
632
  Binary.SUBTYPE_MD5 = 5;
609
633
  Binary.SUBTYPE_ENCRYPTED = 6;
610
634
  Binary.SUBTYPE_COLUMN = 7;
635
+ Binary.SUBTYPE_SENSITIVE = 8;
611
636
  Binary.SUBTYPE_USER_DEFINED = 128;
612
637
  const UUID_BYTE_LENGTH = 16;
613
638
  const UUID_WITHOUT_DASHES = /^[0-9A-F]{32}$/i;
@@ -1851,7 +1876,7 @@ class Decimal128 extends BSONValue {
1851
1876
  if (isNegative) {
1852
1877
  dec.high = dec.high.or(Long.fromString('9223372036854775808'));
1853
1878
  }
1854
- const buffer = ByteUtils.allocate(16);
1879
+ const buffer = ByteUtils.allocateUnsafe(16);
1855
1880
  index = 0;
1856
1881
  buffer[index++] = dec.low.low & 0xff;
1857
1882
  buffer[index++] = (dec.low.low >> 8) & 0xff;
@@ -2124,9 +2149,126 @@ class MinKey extends BSONValue {
2124
2149
  }
2125
2150
  }
2126
2151
 
2152
+ const FLOAT = new Float64Array(1);
2153
+ const FLOAT_BYTES = new Uint8Array(FLOAT.buffer, 0, 8);
2154
+ FLOAT[0] = -1;
2155
+ const isBigEndian = FLOAT_BYTES[7] === 0;
2156
+ const NumberUtils = {
2157
+ getInt32LE(source, offset) {
2158
+ return (source[offset] |
2159
+ (source[offset + 1] << 8) |
2160
+ (source[offset + 2] << 16) |
2161
+ (source[offset + 3] << 24));
2162
+ },
2163
+ getUint32LE(source, offset) {
2164
+ return (source[offset] +
2165
+ source[offset + 1] * 256 +
2166
+ source[offset + 2] * 65536 +
2167
+ source[offset + 3] * 16777216);
2168
+ },
2169
+ getUint32BE(source, offset) {
2170
+ return (source[offset + 3] +
2171
+ source[offset + 2] * 256 +
2172
+ source[offset + 1] * 65536 +
2173
+ source[offset] * 16777216);
2174
+ },
2175
+ getBigInt64LE(source, offset) {
2176
+ const lo = NumberUtils.getUint32LE(source, offset);
2177
+ const hi = NumberUtils.getUint32LE(source, offset + 4);
2178
+ return (BigInt(hi) << BigInt(32)) + BigInt(lo);
2179
+ },
2180
+ getFloat64LE: isBigEndian
2181
+ ? (source, offset) => {
2182
+ FLOAT_BYTES[7] = source[offset];
2183
+ FLOAT_BYTES[6] = source[offset + 1];
2184
+ FLOAT_BYTES[5] = source[offset + 2];
2185
+ FLOAT_BYTES[4] = source[offset + 3];
2186
+ FLOAT_BYTES[3] = source[offset + 4];
2187
+ FLOAT_BYTES[2] = source[offset + 5];
2188
+ FLOAT_BYTES[1] = source[offset + 6];
2189
+ FLOAT_BYTES[0] = source[offset + 7];
2190
+ return FLOAT[0];
2191
+ }
2192
+ : (source, offset) => {
2193
+ FLOAT_BYTES[0] = source[offset];
2194
+ FLOAT_BYTES[1] = source[offset + 1];
2195
+ FLOAT_BYTES[2] = source[offset + 2];
2196
+ FLOAT_BYTES[3] = source[offset + 3];
2197
+ FLOAT_BYTES[4] = source[offset + 4];
2198
+ FLOAT_BYTES[5] = source[offset + 5];
2199
+ FLOAT_BYTES[6] = source[offset + 6];
2200
+ FLOAT_BYTES[7] = source[offset + 7];
2201
+ return FLOAT[0];
2202
+ },
2203
+ setInt32BE(destination, offset, value) {
2204
+ destination[offset + 3] = value;
2205
+ value >>>= 8;
2206
+ destination[offset + 2] = value;
2207
+ value >>>= 8;
2208
+ destination[offset + 1] = value;
2209
+ value >>>= 8;
2210
+ destination[offset] = value;
2211
+ return 4;
2212
+ },
2213
+ setInt32LE(destination, offset, value) {
2214
+ destination[offset] = value;
2215
+ value >>>= 8;
2216
+ destination[offset + 1] = value;
2217
+ value >>>= 8;
2218
+ destination[offset + 2] = value;
2219
+ value >>>= 8;
2220
+ destination[offset + 3] = value;
2221
+ return 4;
2222
+ },
2223
+ setBigInt64LE(destination, offset, value) {
2224
+ const mask32bits = BigInt(4294967295);
2225
+ let lo = Number(value & mask32bits);
2226
+ destination[offset] = lo;
2227
+ lo >>= 8;
2228
+ destination[offset + 1] = lo;
2229
+ lo >>= 8;
2230
+ destination[offset + 2] = lo;
2231
+ lo >>= 8;
2232
+ destination[offset + 3] = lo;
2233
+ let hi = Number((value >> BigInt(32)) & mask32bits);
2234
+ destination[offset + 4] = hi;
2235
+ hi >>= 8;
2236
+ destination[offset + 5] = hi;
2237
+ hi >>= 8;
2238
+ destination[offset + 6] = hi;
2239
+ hi >>= 8;
2240
+ destination[offset + 7] = hi;
2241
+ return 8;
2242
+ },
2243
+ setFloat64LE: isBigEndian
2244
+ ? (destination, offset, value) => {
2245
+ FLOAT[0] = value;
2246
+ destination[offset] = FLOAT_BYTES[7];
2247
+ destination[offset + 1] = FLOAT_BYTES[6];
2248
+ destination[offset + 2] = FLOAT_BYTES[5];
2249
+ destination[offset + 3] = FLOAT_BYTES[4];
2250
+ destination[offset + 4] = FLOAT_BYTES[3];
2251
+ destination[offset + 5] = FLOAT_BYTES[2];
2252
+ destination[offset + 6] = FLOAT_BYTES[1];
2253
+ destination[offset + 7] = FLOAT_BYTES[0];
2254
+ return 8;
2255
+ }
2256
+ : (destination, offset, value) => {
2257
+ FLOAT[0] = value;
2258
+ destination[offset] = FLOAT_BYTES[0];
2259
+ destination[offset + 1] = FLOAT_BYTES[1];
2260
+ destination[offset + 2] = FLOAT_BYTES[2];
2261
+ destination[offset + 3] = FLOAT_BYTES[3];
2262
+ destination[offset + 4] = FLOAT_BYTES[4];
2263
+ destination[offset + 5] = FLOAT_BYTES[5];
2264
+ destination[offset + 6] = FLOAT_BYTES[6];
2265
+ destination[offset + 7] = FLOAT_BYTES[7];
2266
+ return 8;
2267
+ }
2268
+ };
2269
+
2127
2270
  const checkForHexRegExp = new RegExp('^[0-9a-fA-F]{24}$');
2128
2271
  let PROCESS_UNIQUE = null;
2129
- const kId = Symbol('id');
2130
2272
  class ObjectId extends BSONValue {
2131
2273
  get _bsontype() {
2132
2274
  return 'ObjectId';
@@ -2149,14 +2291,14 @@ class ObjectId extends BSONValue {
2149
2291
  workingId = inputId;
2150
2292
  }
2151
2293
  if (workingId == null || typeof workingId === 'number') {
2152
- this[kId] = ObjectId.generate(typeof workingId === 'number' ? workingId : undefined);
2294
+ this.buffer = ObjectId.generate(typeof workingId === 'number' ? workingId : undefined);
2153
2295
  }
2154
2296
  else if (ArrayBuffer.isView(workingId) && workingId.byteLength === 12) {
2155
- this[kId] = ByteUtils.toLocalBufferType(workingId);
2297
+ this.buffer = ByteUtils.toLocalBufferType(workingId);
2156
2298
  }
2157
2299
  else if (typeof workingId === 'string') {
2158
2300
  if (workingId.length === 24 && checkForHexRegExp.test(workingId)) {
2159
- this[kId] = ByteUtils.fromHex(workingId);
2301
+ this.buffer = ByteUtils.fromHex(workingId);
2160
2302
  }
2161
2303
  else {
2162
2304
  throw new BSONError('input must be a 24 character hex string, 12 byte Uint8Array, or an integer');
@@ -2170,10 +2312,10 @@ class ObjectId extends BSONValue {
2170
2312
  }
2171
2313
  }
2172
2314
  get id() {
2173
- return this[kId];
2315
+ return this.buffer;
2174
2316
  }
2175
2317
  set id(value) {
2176
- this[kId] = value;
2318
+ this.buffer = value;
2177
2319
  if (ObjectId.cacheHexString) {
2178
2320
  this.__id = ByteUtils.toHex(value);
2179
2321
  }
@@ -2196,8 +2338,8 @@ class ObjectId extends BSONValue {
2196
2338
  time = Math.floor(Date.now() / 1000);
2197
2339
  }
2198
2340
  const inc = ObjectId.getInc();
2199
- const buffer = ByteUtils.allocate(12);
2200
- BSONDataView.fromUint8Array(buffer).setUint32(0, time, false);
2341
+ const buffer = ByteUtils.allocateUnsafe(12);
2342
+ NumberUtils.setInt32BE(buffer, 0, time);
2201
2343
  if (PROCESS_UNIQUE === null) {
2202
2344
  PROCESS_UNIQUE = ByteUtils.randomBytes(5);
2203
2345
  }
@@ -2232,7 +2374,7 @@ class ObjectId extends BSONValue {
2232
2374
  return false;
2233
2375
  }
2234
2376
  if (ObjectId.is(otherId)) {
2235
- return this[kId][11] === otherId[kId][11] && ByteUtils.equals(this[kId], otherId[kId]);
2377
+ return (this.buffer[11] === otherId.buffer[11] && ByteUtils.equals(this.buffer, otherId.buffer));
2236
2378
  }
2237
2379
  if (typeof otherId === 'string') {
2238
2380
  return otherId.toLowerCase() === this.toHexString();
@@ -2246,16 +2388,33 @@ class ObjectId extends BSONValue {
2246
2388
  }
2247
2389
  getTimestamp() {
2248
2390
  const timestamp = new Date();
2249
- const time = BSONDataView.fromUint8Array(this.id).getUint32(0, false);
2391
+ const time = NumberUtils.getUint32BE(this.buffer, 0);
2250
2392
  timestamp.setTime(Math.floor(time) * 1000);
2251
2393
  return timestamp;
2252
2394
  }
2253
2395
  static createPk() {
2254
2396
  return new ObjectId();
2255
2397
  }
2398
+ serializeInto(uint8array, index) {
2399
+ uint8array[index] = this.buffer[0];
2400
+ uint8array[index + 1] = this.buffer[1];
2401
+ uint8array[index + 2] = this.buffer[2];
2402
+ uint8array[index + 3] = this.buffer[3];
2403
+ uint8array[index + 4] = this.buffer[4];
2404
+ uint8array[index + 5] = this.buffer[5];
2405
+ uint8array[index + 6] = this.buffer[6];
2406
+ uint8array[index + 7] = this.buffer[7];
2407
+ uint8array[index + 8] = this.buffer[8];
2408
+ uint8array[index + 9] = this.buffer[9];
2409
+ uint8array[index + 10] = this.buffer[10];
2410
+ uint8array[index + 11] = this.buffer[11];
2411
+ return 12;
2412
+ }
2256
2413
  static createFromTime(time) {
2257
- const buffer = ByteUtils.fromNumberArray([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
2258
- BSONDataView.fromUint8Array(buffer).setUint32(0, time, false);
2414
+ const buffer = ByteUtils.allocate(12);
2415
+ for (let i = 11; i >= 4; i--)
2416
+ buffer[i] = 0;
2417
+ NumberUtils.setInt32BE(buffer, 0, time);
2259
2418
  return new ObjectId(buffer);
2260
2419
  }
2261
2420
  static createFromHexString(hexString) {
@@ -2627,10 +2786,7 @@ const JS_INT_MIN_LONG = Long.fromNumber(JS_INT_MIN);
2627
2786
  function internalDeserialize(buffer, options, isArray) {
2628
2787
  options = options == null ? {} : options;
2629
2788
  const index = options && options.index ? options.index : 0;
2630
- const size = buffer[index] |
2631
- (buffer[index + 1] << 8) |
2632
- (buffer[index + 2] << 16) |
2633
- (buffer[index + 3] << 24);
2789
+ const size = NumberUtils.getInt32LE(buffer, index);
2634
2790
  if (size < 5) {
2635
2791
  throw new BSONError(`bson size must be >= 5, is ${size}`);
2636
2792
  }
@@ -2666,7 +2822,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2666
2822
  const validation = options.validation == null ? { utf8: true } : options.validation;
2667
2823
  let globalUTFValidation = true;
2668
2824
  let validationSetting;
2669
- const utf8KeysSet = new Set();
2825
+ let utf8KeysSet;
2670
2826
  const utf8ValidatedKeys = validation.utf8;
2671
2827
  if (typeof utf8ValidatedKeys === 'boolean') {
2672
2828
  validationSetting = utf8ValidatedKeys;
@@ -2688,6 +2844,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2688
2844
  }
2689
2845
  }
2690
2846
  if (!globalUTFValidation) {
2847
+ utf8KeysSet = new Set();
2691
2848
  for (const key of Object.keys(utf8ValidatedKeys)) {
2692
2849
  utf8KeysSet.add(key);
2693
2850
  }
@@ -2695,14 +2852,14 @@ function deserializeObject(buffer, index, options, isArray = false) {
2695
2852
  const startIndex = index;
2696
2853
  if (buffer.length < 5)
2697
2854
  throw new BSONError('corrupt bson message < 5 bytes long');
2698
- const size = buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
2855
+ const size = NumberUtils.getInt32LE(buffer, index);
2856
+ index += 4;
2699
2857
  if (size < 5 || size > buffer.length)
2700
2858
  throw new BSONError('corrupt bson message');
2701
2859
  const object = isArray ? [] : {};
2702
2860
  let arrayIndex = 0;
2703
2861
  const done = false;
2704
2862
  let isPossibleDBRef = isArray ? false : null;
2705
- const dataview = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
2706
2863
  while (!done) {
2707
2864
  const elementType = buffer[index++];
2708
2865
  if (elementType === 0)
@@ -2715,7 +2872,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2715
2872
  throw new BSONError('Bad BSON Document: illegal CString');
2716
2873
  const name = isArray ? arrayIndex++ : ByteUtils.toUTF8(buffer, index, i, false);
2717
2874
  let shouldValidateKey = true;
2718
- if (globalUTFValidation || utf8KeysSet.has(name)) {
2875
+ if (globalUTFValidation || utf8KeysSet?.has(name)) {
2719
2876
  shouldValidateKey = validationSetting;
2720
2877
  }
2721
2878
  else {
@@ -2727,10 +2884,8 @@ function deserializeObject(buffer, index, options, isArray = false) {
2727
2884
  let value;
2728
2885
  index = i + 1;
2729
2886
  if (elementType === BSON_DATA_STRING) {
2730
- const stringSize = buffer[index++] |
2731
- (buffer[index++] << 8) |
2732
- (buffer[index++] << 16) |
2733
- (buffer[index++] << 24);
2887
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
2888
+ index += 4;
2734
2889
  if (stringSize <= 0 ||
2735
2890
  stringSize > buffer.length - index ||
2736
2891
  buffer[index + stringSize - 1] !== 0) {
@@ -2740,38 +2895,30 @@ function deserializeObject(buffer, index, options, isArray = false) {
2740
2895
  index = index + stringSize;
2741
2896
  }
2742
2897
  else if (elementType === BSON_DATA_OID) {
2743
- const oid = ByteUtils.allocate(12);
2744
- oid.set(buffer.subarray(index, index + 12));
2898
+ const oid = ByteUtils.allocateUnsafe(12);
2899
+ for (let i = 0; i < 12; i++)
2900
+ oid[i] = buffer[index + i];
2745
2901
  value = new ObjectId(oid);
2746
2902
  index = index + 12;
2747
2903
  }
2748
2904
  else if (elementType === BSON_DATA_INT && promoteValues === false) {
2749
- value = new Int32(buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24));
2905
+ value = new Int32(NumberUtils.getInt32LE(buffer, index));
2906
+ index += 4;
2750
2907
  }
2751
2908
  else if (elementType === BSON_DATA_INT) {
2752
- value =
2753
- buffer[index++] |
2754
- (buffer[index++] << 8) |
2755
- (buffer[index++] << 16) |
2756
- (buffer[index++] << 24);
2757
- }
2758
- else if (elementType === BSON_DATA_NUMBER && promoteValues === false) {
2759
- value = new Double(dataview.getFloat64(index, true));
2760
- index = index + 8;
2909
+ value = NumberUtils.getInt32LE(buffer, index);
2910
+ index += 4;
2761
2911
  }
2762
2912
  else if (elementType === BSON_DATA_NUMBER) {
2763
- value = dataview.getFloat64(index, true);
2764
- index = index + 8;
2913
+ value = NumberUtils.getFloat64LE(buffer, index);
2914
+ index += 8;
2915
+ if (promoteValues === false)
2916
+ value = new Double(value);
2765
2917
  }
2766
2918
  else if (elementType === BSON_DATA_DATE) {
2767
- const lowBits = buffer[index++] |
2768
- (buffer[index++] << 8) |
2769
- (buffer[index++] << 16) |
2770
- (buffer[index++] << 24);
2771
- const highBits = buffer[index++] |
2772
- (buffer[index++] << 8) |
2773
- (buffer[index++] << 16) |
2774
- (buffer[index++] << 24);
2919
+ const lowBits = NumberUtils.getInt32LE(buffer, index);
2920
+ const highBits = NumberUtils.getInt32LE(buffer, index + 4);
2921
+ index += 8;
2775
2922
  value = new Date(new Long(lowBits, highBits).toNumber());
2776
2923
  }
2777
2924
  else if (elementType === BSON_DATA_BOOLEAN) {
@@ -2781,10 +2928,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2781
2928
  }
2782
2929
  else if (elementType === BSON_DATA_OBJECT) {
2783
2930
  const _index = index;
2784
- const objectSize = buffer[index] |
2785
- (buffer[index + 1] << 8) |
2786
- (buffer[index + 2] << 16) |
2787
- (buffer[index + 3] << 24);
2931
+ const objectSize = NumberUtils.getInt32LE(buffer, index);
2788
2932
  if (objectSize <= 0 || objectSize > buffer.length - index)
2789
2933
  throw new BSONError('bad embedded document length in bson');
2790
2934
  if (raw) {
@@ -2801,10 +2945,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2801
2945
  }
2802
2946
  else if (elementType === BSON_DATA_ARRAY) {
2803
2947
  const _index = index;
2804
- const objectSize = buffer[index] |
2805
- (buffer[index + 1] << 8) |
2806
- (buffer[index + 2] << 16) |
2807
- (buffer[index + 3] << 24);
2948
+ const objectSize = NumberUtils.getInt32LE(buffer, index);
2808
2949
  let arrayOptions = options;
2809
2950
  const stopIndex = index + objectSize;
2810
2951
  if (fieldsAsRaw && fieldsAsRaw[name]) {
@@ -2827,40 +2968,36 @@ function deserializeObject(buffer, index, options, isArray = false) {
2827
2968
  value = null;
2828
2969
  }
2829
2970
  else if (elementType === BSON_DATA_LONG) {
2830
- const dataview = BSONDataView.fromUint8Array(buffer.subarray(index, index + 8));
2831
- const lowBits = buffer[index++] |
2832
- (buffer[index++] << 8) |
2833
- (buffer[index++] << 16) |
2834
- (buffer[index++] << 24);
2835
- const highBits = buffer[index++] |
2836
- (buffer[index++] << 8) |
2837
- (buffer[index++] << 16) |
2838
- (buffer[index++] << 24);
2839
- const long = new Long(lowBits, highBits);
2840
2971
  if (useBigInt64) {
2841
- value = dataview.getBigInt64(0, true);
2842
- }
2843
- else if (promoteLongs && promoteValues === true) {
2844
- value =
2845
- long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG)
2846
- ? long.toNumber()
2847
- : long;
2972
+ value = NumberUtils.getBigInt64LE(buffer, index);
2973
+ index += 8;
2848
2974
  }
2849
2975
  else {
2850
- value = long;
2976
+ const lowBits = NumberUtils.getInt32LE(buffer, index);
2977
+ const highBits = NumberUtils.getInt32LE(buffer, index + 4);
2978
+ index += 8;
2979
+ const long = new Long(lowBits, highBits);
2980
+ if (promoteLongs && promoteValues === true) {
2981
+ value =
2982
+ long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG)
2983
+ ? long.toNumber()
2984
+ : long;
2985
+ }
2986
+ else {
2987
+ value = long;
2988
+ }
2851
2989
  }
2852
2990
  }
2853
2991
  else if (elementType === BSON_DATA_DECIMAL128) {
2854
- const bytes = ByteUtils.allocate(16);
2855
- bytes.set(buffer.subarray(index, index + 16), 0);
2992
+ const bytes = ByteUtils.allocateUnsafe(16);
2993
+ for (let i = 0; i < 16; i++)
2994
+ bytes[i] = buffer[index + i];
2856
2995
  index = index + 16;
2857
2996
  value = new Decimal128(bytes);
2858
2997
  }
2859
2998
  else if (elementType === BSON_DATA_BINARY) {
2860
- let binarySize = buffer[index++] |
2861
- (buffer[index++] << 8) |
2862
- (buffer[index++] << 16) |
2863
- (buffer[index++] << 24);
2999
+ let binarySize = NumberUtils.getInt32LE(buffer, index);
3000
+ index += 4;
2864
3001
  const totalBinarySize = binarySize;
2865
3002
  const subType = buffer[index++];
2866
3003
  if (binarySize < 0)
@@ -2869,11 +3006,8 @@ function deserializeObject(buffer, index, options, isArray = false) {
2869
3006
  throw new BSONError('Binary type size larger than document size');
2870
3007
  if (buffer['slice'] != null) {
2871
3008
  if (subType === Binary.SUBTYPE_BYTE_ARRAY) {
2872
- binarySize =
2873
- buffer[index++] |
2874
- (buffer[index++] << 8) |
2875
- (buffer[index++] << 16) |
2876
- (buffer[index++] << 24);
3009
+ binarySize = NumberUtils.getInt32LE(buffer, index);
3010
+ index += 4;
2877
3011
  if (binarySize < 0)
2878
3012
  throw new BSONError('Negative binary type element size found for subtype 0x02');
2879
3013
  if (binarySize > totalBinarySize - 4)
@@ -2892,13 +3026,9 @@ function deserializeObject(buffer, index, options, isArray = false) {
2892
3026
  }
2893
3027
  }
2894
3028
  else {
2895
- const _buffer = ByteUtils.allocate(binarySize);
2896
3029
  if (subType === Binary.SUBTYPE_BYTE_ARRAY) {
2897
- binarySize =
2898
- buffer[index++] |
2899
- (buffer[index++] << 8) |
2900
- (buffer[index++] << 16) |
2901
- (buffer[index++] << 24);
3030
+ binarySize = NumberUtils.getInt32LE(buffer, index);
3031
+ index += 4;
2902
3032
  if (binarySize < 0)
2903
3033
  throw new BSONError('Negative binary type element size found for subtype 0x02');
2904
3034
  if (binarySize > totalBinarySize - 4)
@@ -2906,11 +3036,11 @@ function deserializeObject(buffer, index, options, isArray = false) {
2906
3036
  if (binarySize < totalBinarySize - 4)
2907
3037
  throw new BSONError('Binary type with subtype 0x02 contains too short binary size');
2908
3038
  }
2909
- for (i = 0; i < binarySize; i++) {
2910
- _buffer[i] = buffer[index + i];
2911
- }
2912
3039
  if (promoteBuffers && promoteValues) {
2913
- value = _buffer;
3040
+ value = ByteUtils.allocateUnsafe(binarySize);
3041
+ for (i = 0; i < binarySize; i++) {
3042
+ value[i] = buffer[index + i];
3043
+ }
2914
3044
  }
2915
3045
  else {
2916
3046
  value = new Binary(buffer.slice(index, index + binarySize), subType);
@@ -2974,10 +3104,8 @@ function deserializeObject(buffer, index, options, isArray = false) {
2974
3104
  value = new BSONRegExp(source, regExpOptions);
2975
3105
  }
2976
3106
  else if (elementType === BSON_DATA_SYMBOL) {
2977
- const stringSize = buffer[index++] |
2978
- (buffer[index++] << 8) |
2979
- (buffer[index++] << 16) |
2980
- (buffer[index++] << 24);
3107
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
3108
+ index += 4;
2981
3109
  if (stringSize <= 0 ||
2982
3110
  stringSize > buffer.length - index ||
2983
3111
  buffer[index + stringSize - 1] !== 0) {
@@ -2988,15 +3116,11 @@ function deserializeObject(buffer, index, options, isArray = false) {
2988
3116
  index = index + stringSize;
2989
3117
  }
2990
3118
  else if (elementType === BSON_DATA_TIMESTAMP) {
2991
- const i = buffer[index++] +
2992
- buffer[index++] * (1 << 8) +
2993
- buffer[index++] * (1 << 16) +
2994
- buffer[index++] * (1 << 24);
2995
- const t = buffer[index++] +
2996
- buffer[index++] * (1 << 8) +
2997
- buffer[index++] * (1 << 16) +
2998
- buffer[index++] * (1 << 24);
2999
- value = new Timestamp({ i, t });
3119
+ value = new Timestamp({
3120
+ i: NumberUtils.getUint32LE(buffer, index),
3121
+ t: NumberUtils.getUint32LE(buffer, index + 4)
3122
+ });
3123
+ index += 8;
3000
3124
  }
3001
3125
  else if (elementType === BSON_DATA_MIN_KEY) {
3002
3126
  value = new MinKey();
@@ -3005,10 +3129,8 @@ function deserializeObject(buffer, index, options, isArray = false) {
3005
3129
  value = new MaxKey();
3006
3130
  }
3007
3131
  else if (elementType === BSON_DATA_CODE) {
3008
- const stringSize = buffer[index++] |
3009
- (buffer[index++] << 8) |
3010
- (buffer[index++] << 16) |
3011
- (buffer[index++] << 24);
3132
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
3133
+ index += 4;
3012
3134
  if (stringSize <= 0 ||
3013
3135
  stringSize > buffer.length - index ||
3014
3136
  buffer[index + stringSize - 1] !== 0) {
@@ -3019,17 +3141,13 @@ function deserializeObject(buffer, index, options, isArray = false) {
3019
3141
  index = index + stringSize;
3020
3142
  }
3021
3143
  else if (elementType === BSON_DATA_CODE_W_SCOPE) {
3022
- const totalSize = buffer[index++] |
3023
- (buffer[index++] << 8) |
3024
- (buffer[index++] << 16) |
3025
- (buffer[index++] << 24);
3144
+ const totalSize = NumberUtils.getInt32LE(buffer, index);
3145
+ index += 4;
3026
3146
  if (totalSize < 4 + 4 + 4 + 1) {
3027
3147
  throw new BSONError('code_w_scope total size shorter minimum expected length');
3028
3148
  }
3029
- const stringSize = buffer[index++] |
3030
- (buffer[index++] << 8) |
3031
- (buffer[index++] << 16) |
3032
- (buffer[index++] << 24);
3149
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
3150
+ index += 4;
3033
3151
  if (stringSize <= 0 ||
3034
3152
  stringSize > buffer.length - index ||
3035
3153
  buffer[index + stringSize - 1] !== 0) {
@@ -3038,10 +3156,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
3038
3156
  const functionString = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
3039
3157
  index = index + stringSize;
3040
3158
  const _index = index;
3041
- const objectSize = buffer[index] |
3042
- (buffer[index + 1] << 8) |
3043
- (buffer[index + 2] << 16) |
3044
- (buffer[index + 3] << 24);
3159
+ const objectSize = NumberUtils.getInt32LE(buffer, index);
3045
3160
  const scopeObject = deserializeObject(buffer, _index, options, false);
3046
3161
  index = index + objectSize;
3047
3162
  if (totalSize < 4 + 4 + objectSize + stringSize) {
@@ -3053,10 +3168,8 @@ function deserializeObject(buffer, index, options, isArray = false) {
3053
3168
  value = new Code(functionString, scopeObject);
3054
3169
  }
3055
3170
  else if (elementType === BSON_DATA_DBPOINTER) {
3056
- const stringSize = buffer[index++] |
3057
- (buffer[index++] << 8) |
3058
- (buffer[index++] << 16) |
3059
- (buffer[index++] << 24);
3171
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
3172
+ index += 4;
3060
3173
  if (stringSize <= 0 ||
3061
3174
  stringSize > buffer.length - index ||
3062
3175
  buffer[index + stringSize - 1] !== 0)
@@ -3068,8 +3181,9 @@ function deserializeObject(buffer, index, options, isArray = false) {
3068
3181
  }
3069
3182
  const namespace = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, false);
3070
3183
  index = index + stringSize;
3071
- const oidBuffer = ByteUtils.allocate(12);
3072
- oidBuffer.set(buffer.subarray(index, index + 12), 0);
3184
+ const oidBuffer = ByteUtils.allocateUnsafe(12);
3185
+ for (let i = 0; i < 12; i++)
3186
+ oidBuffer[i] = buffer[index + i];
3073
3187
  const oid = new ObjectId(oidBuffer);
3074
3188
  index = index + 12;
3075
3189
  value = new DBRef(namespace, oid);
@@ -3114,17 +3228,11 @@ function serializeString(buffer, key, value, index) {
3114
3228
  index = index + numberOfWrittenBytes + 1;
3115
3229
  buffer[index - 1] = 0;
3116
3230
  const size = ByteUtils.encodeUTF8Into(buffer, value, index + 4);
3117
- buffer[index + 3] = ((size + 1) >> 24) & 0xff;
3118
- buffer[index + 2] = ((size + 1) >> 16) & 0xff;
3119
- buffer[index + 1] = ((size + 1) >> 8) & 0xff;
3120
- buffer[index] = (size + 1) & 0xff;
3231
+ NumberUtils.setInt32LE(buffer, index, size + 1);
3121
3232
  index = index + 4 + size;
3122
3233
  buffer[index++] = 0;
3123
3234
  return index;
3124
3235
  }
3125
- const NUMBER_SPACE = new DataView(new ArrayBuffer(8), 0, 8);
3126
- const FOUR_BYTE_VIEW_ON_NUMBER = new Uint8Array(NUMBER_SPACE.buffer, 0, 4);
3127
- const EIGHT_BYTE_VIEW_ON_NUMBER = new Uint8Array(NUMBER_SPACE.buffer, 0, 8);
3128
3236
  function serializeNumber(buffer, key, value, index) {
3129
3237
  const isNegativeZero = Object.is(value, -0);
3130
3238
  const type = !isNegativeZero &&
@@ -3133,19 +3241,16 @@ function serializeNumber(buffer, key, value, index) {
3133
3241
  value >= BSON_INT32_MIN
3134
3242
  ? BSON_DATA_INT
3135
3243
  : BSON_DATA_NUMBER;
3136
- if (type === BSON_DATA_INT) {
3137
- NUMBER_SPACE.setInt32(0, value, true);
3138
- }
3139
- else {
3140
- NUMBER_SPACE.setFloat64(0, value, true);
3141
- }
3142
- const bytes = type === BSON_DATA_INT ? FOUR_BYTE_VIEW_ON_NUMBER : EIGHT_BYTE_VIEW_ON_NUMBER;
3143
3244
  buffer[index++] = type;
3144
3245
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3145
3246
  index = index + numberOfWrittenBytes;
3146
3247
  buffer[index++] = 0x00;
3147
- buffer.set(bytes, index);
3148
- index += bytes.byteLength;
3248
+ if (type === BSON_DATA_INT) {
3249
+ index += NumberUtils.setInt32LE(buffer, index, value);
3250
+ }
3251
+ else {
3252
+ index += NumberUtils.setFloat64LE(buffer, index, value);
3253
+ }
3149
3254
  return index;
3150
3255
  }
3151
3256
  function serializeBigInt(buffer, key, value, index) {
@@ -3153,9 +3258,7 @@ function serializeBigInt(buffer, key, value, index) {
3153
3258
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3154
3259
  index += numberOfWrittenBytes;
3155
3260
  buffer[index++] = 0;
3156
- NUMBER_SPACE.setBigInt64(0, value, true);
3157
- buffer.set(EIGHT_BYTE_VIEW_ON_NUMBER, index);
3158
- index += EIGHT_BYTE_VIEW_ON_NUMBER.byteLength;
3261
+ index += NumberUtils.setBigInt64LE(buffer, index, value);
3159
3262
  return index;
3160
3263
  }
3161
3264
  function serializeNull(buffer, key, _, index) {
@@ -3181,14 +3284,8 @@ function serializeDate(buffer, key, value, index) {
3181
3284
  const dateInMilis = Long.fromNumber(value.getTime());
3182
3285
  const lowBits = dateInMilis.getLowBits();
3183
3286
  const highBits = dateInMilis.getHighBits();
3184
- buffer[index++] = lowBits & 0xff;
3185
- buffer[index++] = (lowBits >> 8) & 0xff;
3186
- buffer[index++] = (lowBits >> 16) & 0xff;
3187
- buffer[index++] = (lowBits >> 24) & 0xff;
3188
- buffer[index++] = highBits & 0xff;
3189
- buffer[index++] = (highBits >> 8) & 0xff;
3190
- buffer[index++] = (highBits >> 16) & 0xff;
3191
- buffer[index++] = (highBits >> 24) & 0xff;
3287
+ index += NumberUtils.setInt32LE(buffer, index, lowBits);
3288
+ index += NumberUtils.setInt32LE(buffer, index, highBits);
3192
3289
  return index;
3193
3290
  }
3194
3291
  function serializeRegExp(buffer, key, value, index) {
@@ -3245,15 +3342,7 @@ function serializeObjectId(buffer, key, value, index) {
3245
3342
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3246
3343
  index = index + numberOfWrittenBytes;
3247
3344
  buffer[index++] = 0;
3248
- const idValue = value.id;
3249
- if (isUint8Array(idValue)) {
3250
- for (let i = 0; i < 12; i++) {
3251
- buffer[index++] = idValue[i];
3252
- }
3253
- }
3254
- else {
3255
- throw new BSONError('object [' + JSON.stringify(value) + '] is not a valid ObjectId');
3256
- }
3345
+ index += value.serializeInto(buffer, index);
3257
3346
  return index;
3258
3347
  }
3259
3348
  function serializeBuffer(buffer, key, value, index) {
@@ -3262,12 +3351,15 @@ function serializeBuffer(buffer, key, value, index) {
3262
3351
  index = index + numberOfWrittenBytes;
3263
3352
  buffer[index++] = 0;
3264
3353
  const size = value.length;
3265
- buffer[index++] = size & 0xff;
3266
- buffer[index++] = (size >> 8) & 0xff;
3267
- buffer[index++] = (size >> 16) & 0xff;
3268
- buffer[index++] = (size >> 24) & 0xff;
3354
+ index += NumberUtils.setInt32LE(buffer, index, size);
3269
3355
  buffer[index++] = BSON_BINARY_SUBTYPE_DEFAULT;
3270
- buffer.set(value, index);
3356
+ if (size <= 16) {
3357
+ for (let i = 0; i < size; i++)
3358
+ buffer[index + i] = value[i];
3359
+ }
3360
+ else {
3361
+ buffer.set(value, index);
3362
+ }
3271
3363
  index = index + size;
3272
3364
  return index;
3273
3365
  }
@@ -3289,7 +3381,8 @@ function serializeDecimal128(buffer, key, value, index) {
3289
3381
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3290
3382
  index = index + numberOfWrittenBytes;
3291
3383
  buffer[index++] = 0;
3292
- buffer.set(value.bytes.subarray(0, 16), index);
3384
+ for (let i = 0; i < 16; i++)
3385
+ buffer[index + i] = value.bytes[i];
3293
3386
  return index + 16;
3294
3387
  }
3295
3388
  function serializeLong(buffer, key, value, index) {
@@ -3300,14 +3393,8 @@ function serializeLong(buffer, key, value, index) {
3300
3393
  buffer[index++] = 0;
3301
3394
  const lowBits = value.getLowBits();
3302
3395
  const highBits = value.getHighBits();
3303
- buffer[index++] = lowBits & 0xff;
3304
- buffer[index++] = (lowBits >> 8) & 0xff;
3305
- buffer[index++] = (lowBits >> 16) & 0xff;
3306
- buffer[index++] = (lowBits >> 24) & 0xff;
3307
- buffer[index++] = highBits & 0xff;
3308
- buffer[index++] = (highBits >> 8) & 0xff;
3309
- buffer[index++] = (highBits >> 16) & 0xff;
3310
- buffer[index++] = (highBits >> 24) & 0xff;
3396
+ index += NumberUtils.setInt32LE(buffer, index, lowBits);
3397
+ index += NumberUtils.setInt32LE(buffer, index, highBits);
3311
3398
  return index;
3312
3399
  }
3313
3400
  function serializeInt32(buffer, key, value, index) {
@@ -3316,10 +3403,7 @@ function serializeInt32(buffer, key, value, index) {
3316
3403
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3317
3404
  index = index + numberOfWrittenBytes;
3318
3405
  buffer[index++] = 0;
3319
- buffer[index++] = value & 0xff;
3320
- buffer[index++] = (value >> 8) & 0xff;
3321
- buffer[index++] = (value >> 16) & 0xff;
3322
- buffer[index++] = (value >> 24) & 0xff;
3406
+ index += NumberUtils.setInt32LE(buffer, index, value);
3323
3407
  return index;
3324
3408
  }
3325
3409
  function serializeDouble(buffer, key, value, index) {
@@ -3327,9 +3411,7 @@ function serializeDouble(buffer, key, value, index) {
3327
3411
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3328
3412
  index = index + numberOfWrittenBytes;
3329
3413
  buffer[index++] = 0;
3330
- NUMBER_SPACE.setFloat64(0, value.value, true);
3331
- buffer.set(EIGHT_BYTE_VIEW_ON_NUMBER, index);
3332
- index = index + 8;
3414
+ index += NumberUtils.setFloat64LE(buffer, index, value.value);
3333
3415
  return index;
3334
3416
  }
3335
3417
  function serializeFunction(buffer, key, value, index) {
@@ -3339,10 +3421,7 @@ function serializeFunction(buffer, key, value, index) {
3339
3421
  buffer[index++] = 0;
3340
3422
  const functionString = value.toString();
3341
3423
  const size = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
3342
- buffer[index] = size & 0xff;
3343
- buffer[index + 1] = (size >> 8) & 0xff;
3344
- buffer[index + 2] = (size >> 16) & 0xff;
3345
- buffer[index + 3] = (size >> 24) & 0xff;
3424
+ NumberUtils.setInt32LE(buffer, index, size);
3346
3425
  index = index + 4 + size - 1;
3347
3426
  buffer[index++] = 0;
3348
3427
  return index;
@@ -3357,19 +3436,13 @@ function serializeCode(buffer, key, value, index, checkKeys = false, depth = 0,
3357
3436
  const functionString = value.code;
3358
3437
  index = index + 4;
3359
3438
  const codeSize = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
3360
- buffer[index] = codeSize & 0xff;
3361
- buffer[index + 1] = (codeSize >> 8) & 0xff;
3362
- buffer[index + 2] = (codeSize >> 16) & 0xff;
3363
- buffer[index + 3] = (codeSize >> 24) & 0xff;
3439
+ NumberUtils.setInt32LE(buffer, index, codeSize);
3364
3440
  buffer[index + 4 + codeSize - 1] = 0;
3365
3441
  index = index + codeSize + 4;
3366
3442
  const endIndex = serializeInto(buffer, value.scope, checkKeys, index, depth + 1, serializeFunctions, ignoreUndefined, path);
3367
3443
  index = endIndex - 1;
3368
3444
  const totalSize = endIndex - startIndex;
3369
- buffer[startIndex++] = totalSize & 0xff;
3370
- buffer[startIndex++] = (totalSize >> 8) & 0xff;
3371
- buffer[startIndex++] = (totalSize >> 16) & 0xff;
3372
- buffer[startIndex++] = (totalSize >> 24) & 0xff;
3445
+ startIndex += NumberUtils.setInt32LE(buffer, startIndex, totalSize);
3373
3446
  buffer[index++] = 0;
3374
3447
  }
3375
3448
  else {
@@ -3379,10 +3452,7 @@ function serializeCode(buffer, key, value, index, checkKeys = false, depth = 0,
3379
3452
  buffer[index++] = 0;
3380
3453
  const functionString = value.code.toString();
3381
3454
  const size = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
3382
- buffer[index] = size & 0xff;
3383
- buffer[index + 1] = (size >> 8) & 0xff;
3384
- buffer[index + 2] = (size >> 16) & 0xff;
3385
- buffer[index + 3] = (size >> 24) & 0xff;
3455
+ NumberUtils.setInt32LE(buffer, index, size);
3386
3456
  index = index + 4 + size - 1;
3387
3457
  buffer[index++] = 0;
3388
3458
  }
@@ -3397,19 +3467,19 @@ function serializeBinary(buffer, key, value, index) {
3397
3467
  let size = value.position;
3398
3468
  if (value.sub_type === Binary.SUBTYPE_BYTE_ARRAY)
3399
3469
  size = size + 4;
3400
- buffer[index++] = size & 0xff;
3401
- buffer[index++] = (size >> 8) & 0xff;
3402
- buffer[index++] = (size >> 16) & 0xff;
3403
- buffer[index++] = (size >> 24) & 0xff;
3470
+ index += NumberUtils.setInt32LE(buffer, index, size);
3404
3471
  buffer[index++] = value.sub_type;
3405
3472
  if (value.sub_type === Binary.SUBTYPE_BYTE_ARRAY) {
3406
3473
  size = size - 4;
3407
- buffer[index++] = size & 0xff;
3408
- buffer[index++] = (size >> 8) & 0xff;
3409
- buffer[index++] = (size >> 16) & 0xff;
3410
- buffer[index++] = (size >> 24) & 0xff;
3474
+ index += NumberUtils.setInt32LE(buffer, index, size);
3475
+ }
3476
+ if (size <= 16) {
3477
+ for (let i = 0; i < size; i++)
3478
+ buffer[index + i] = data[i];
3479
+ }
3480
+ else {
3481
+ buffer.set(data, index);
3411
3482
  }
3412
- buffer.set(data, index);
3413
3483
  index = index + value.position;
3414
3484
  return index;
3415
3485
  }
@@ -3419,12 +3489,9 @@ function serializeSymbol(buffer, key, value, index) {
3419
3489
  index = index + numberOfWrittenBytes;
3420
3490
  buffer[index++] = 0;
3421
3491
  const size = ByteUtils.encodeUTF8Into(buffer, value.value, index + 4) + 1;
3422
- buffer[index] = size & 0xff;
3423
- buffer[index + 1] = (size >> 8) & 0xff;
3424
- buffer[index + 2] = (size >> 16) & 0xff;
3425
- buffer[index + 3] = (size >> 24) & 0xff;
3492
+ NumberUtils.setInt32LE(buffer, index, size);
3426
3493
  index = index + 4 + size - 1;
3427
- buffer[index++] = 0x00;
3494
+ buffer[index++] = 0;
3428
3495
  return index;
3429
3496
  }
3430
3497
  function serializeDBRef(buffer, key, value, index, depth, serializeFunctions, path) {
@@ -3443,10 +3510,7 @@ function serializeDBRef(buffer, key, value, index, depth, serializeFunctions, pa
3443
3510
  output = Object.assign(output, value.fields);
3444
3511
  const endIndex = serializeInto(buffer, output, false, index, depth + 1, serializeFunctions, true, path);
3445
3512
  const size = endIndex - startIndex;
3446
- buffer[startIndex++] = size & 0xff;
3447
- buffer[startIndex++] = (size >> 8) & 0xff;
3448
- buffer[startIndex++] = (size >> 16) & 0xff;
3449
- buffer[startIndex++] = (size >> 24) & 0xff;
3513
+ startIndex += NumberUtils.setInt32LE(buffer, index, size);
3450
3514
  return endIndex;
3451
3515
  }
3452
3516
  function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializeFunctions, ignoreUndefined, path) {
@@ -3582,7 +3646,7 @@ function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializ
3582
3646
  if ('$' === key[0]) {
3583
3647
  throw new BSONError('key ' + key + " must not start with '$'");
3584
3648
  }
3585
- else if (~key.indexOf('.')) {
3649
+ else if (key.includes('.')) {
3586
3650
  throw new BSONError('key ' + key + " must not contain '.'");
3587
3651
  }
3588
3652
  }
@@ -3680,7 +3744,7 @@ function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializ
3680
3744
  if ('$' === key[0]) {
3681
3745
  throw new BSONError('key ' + key + " must not start with '$'");
3682
3746
  }
3683
- else if (~key.indexOf('.')) {
3747
+ else if (key.includes('.')) {
3684
3748
  throw new BSONError('key ' + key + " must not contain '.'");
3685
3749
  }
3686
3750
  }
@@ -3764,10 +3828,7 @@ function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializ
3764
3828
  path.delete(object);
3765
3829
  buffer[index++] = 0x00;
3766
3830
  const size = index - startingIndex;
3767
- buffer[startingIndex++] = size & 0xff;
3768
- buffer[startingIndex++] = (size >> 8) & 0xff;
3769
- buffer[startingIndex++] = (size >> 16) & 0xff;
3770
- buffer[startingIndex++] = (size >> 24) & 0xff;
3831
+ startingIndex += NumberUtils.setInt32LE(buffer, startingIndex, size);
3771
3832
  return index;
3772
3833
  }
3773
3834
 
@@ -4081,6 +4142,104 @@ EJSON.serialize = EJSONserialize;
4081
4142
  EJSON.deserialize = EJSONdeserialize;
4082
4143
  Object.freeze(EJSON);
4083
4144
 
4145
+ function getSize(source, offset) {
4146
+ if (source[offset + 3] > 127) {
4147
+ throw new BSONOffsetError('BSON size cannot be negative', offset);
4148
+ }
4149
+ return (source[offset] |
4150
+ (source[offset + 1] << 8) |
4151
+ (source[offset + 2] << 16) |
4152
+ (source[offset + 3] << 24));
4153
+ }
4154
+ function findNull(bytes, offset) {
4155
+ let nullTerminatorOffset = offset;
4156
+ for (; bytes[nullTerminatorOffset] !== 0x00; nullTerminatorOffset++)
4157
+ ;
4158
+ if (nullTerminatorOffset === bytes.length - 1) {
4159
+ throw new BSONOffsetError('Null terminator not found', offset);
4160
+ }
4161
+ return nullTerminatorOffset;
4162
+ }
4163
+ function parseToElements(bytes, startOffset = 0) {
4164
+ if (bytes.length < 5) {
4165
+ throw new BSONOffsetError(`Input must be at least 5 bytes, got ${bytes.length} bytes`, startOffset);
4166
+ }
4167
+ const documentSize = getSize(bytes, startOffset);
4168
+ if (documentSize > bytes.length - startOffset) {
4169
+ throw new BSONOffsetError(`Parsed documentSize (${documentSize} bytes) does not match input length (${bytes.length} bytes)`, startOffset);
4170
+ }
4171
+ if (bytes[startOffset + documentSize - 1] !== 0x00) {
4172
+ throw new BSONOffsetError('BSON documents must end in 0x00', startOffset + documentSize);
4173
+ }
4174
+ const elements = [];
4175
+ let offset = startOffset + 4;
4176
+ while (offset <= documentSize + startOffset) {
4177
+ const type = bytes[offset];
4178
+ offset += 1;
4179
+ if (type === 0) {
4180
+ if (offset - startOffset !== documentSize) {
4181
+ throw new BSONOffsetError(`Invalid 0x00 type byte`, offset);
4182
+ }
4183
+ break;
4184
+ }
4185
+ const nameOffset = offset;
4186
+ const nameLength = findNull(bytes, offset) - nameOffset;
4187
+ offset += nameLength + 1;
4188
+ let length;
4189
+ if (type === 1 || type === 18 || type === 9 || type === 17) {
4190
+ length = 8;
4191
+ }
4192
+ else if (type === 16) {
4193
+ length = 4;
4194
+ }
4195
+ else if (type === 7) {
4196
+ length = 12;
4197
+ }
4198
+ else if (type === 19) {
4199
+ length = 16;
4200
+ }
4201
+ else if (type === 8) {
4202
+ length = 1;
4203
+ }
4204
+ else if (type === 10 || type === 6 || type === 127 || type === 255) {
4205
+ length = 0;
4206
+ }
4207
+ else if (type === 11) {
4208
+ length = findNull(bytes, findNull(bytes, offset) + 1) + 1 - offset;
4209
+ }
4210
+ else if (type === 3 || type === 4 || type === 15) {
4211
+ length = getSize(bytes, offset);
4212
+ }
4213
+ else if (type === 2 ||
4214
+ type === 5 ||
4215
+ type === 12 ||
4216
+ type === 13 ||
4217
+ type === 14) {
4218
+ length = getSize(bytes, offset) + 4;
4219
+ if (type === 5) {
4220
+ length += 1;
4221
+ }
4222
+ if (type === 12) {
4223
+ length += 12;
4224
+ }
4225
+ }
4226
+ else {
4227
+ throw new BSONOffsetError(`Invalid 0x${type.toString(16).padStart(2, '0')} type byte`, offset);
4228
+ }
4229
+ if (length > documentSize) {
4230
+ throw new BSONOffsetError('value reports length larger than document', offset);
4231
+ }
4232
+ elements.push([type, nameOffset, nameLength, offset, length]);
4233
+ offset += length;
4234
+ }
4235
+ return elements;
4236
+ }
4237
+
4238
+ const onDemand = Object.create(null);
4239
+ onDemand.parseToElements = parseToElements;
4240
+ onDemand.BSONOffsetError = BSONOffsetError;
4241
+ Object.freeze(onDemand);
4242
+
4084
4243
  const MAXSIZE = 1024 * 1024 * 17;
4085
4244
  let buffer = ByteUtils.allocate(MAXSIZE);
4086
4245
  function setInternalBufferSize(size) {
@@ -4097,7 +4256,7 @@ function serialize(object, options = {}) {
4097
4256
  buffer = ByteUtils.allocate(minInternalBufferSize);
4098
4257
  }
4099
4258
  const serializationIndex = serializeInto(buffer, object, checkKeys, 0, 0, serializeFunctions, ignoreUndefined, null);
4100
- const finishedBuffer = ByteUtils.allocate(serializationIndex);
4259
+ const finishedBuffer = ByteUtils.allocateUnsafe(serializationIndex);
4101
4260
  finishedBuffer.set(buffer.subarray(0, serializationIndex), 0);
4102
4261
  return finishedBuffer;
4103
4262
  }
@@ -4124,10 +4283,7 @@ function deserializeStream(data, startIndex, numberOfDocuments, documents, docSt
4124
4283
  const bufferData = ByteUtils.toLocalBufferType(data);
4125
4284
  let index = startIndex;
4126
4285
  for (let i = 0; i < numberOfDocuments; i++) {
4127
- const size = bufferData[index] |
4128
- (bufferData[index + 1] << 8) |
4129
- (bufferData[index + 2] << 16) |
4130
- (bufferData[index + 3] << 24);
4286
+ const size = NumberUtils.getInt32LE(bufferData, index);
4131
4287
  internalOptions.index = index;
4132
4288
  documents[docStartIndex + i] = internalDeserialize(bufferData, internalOptions);
4133
4289
  index = index + size;
@@ -4160,6 +4316,7 @@ var bson = /*#__PURE__*/Object.freeze({
4160
4316
  calculateObjectSize: calculateObjectSize,
4161
4317
  deserialize: deserialize,
4162
4318
  deserializeStream: deserializeStream,
4319
+ onDemand: onDemand,
4163
4320
  serialize: serialize,
4164
4321
  serializeWithBufferAndIndex: serializeWithBufferAndIndex,
4165
4322
  setInternalBufferSize: setInternalBufferSize
@@ -4189,6 +4346,7 @@ exports.UUID = UUID;
4189
4346
  exports.calculateObjectSize = calculateObjectSize;
4190
4347
  exports.deserialize = deserialize;
4191
4348
  exports.deserializeStream = deserializeStream;
4349
+ exports.onDemand = onDemand;
4192
4350
  exports.serialize = serialize;
4193
4351
  exports.serializeWithBufferAndIndex = serializeWithBufferAndIndex;
4194
4352
  exports.setInternalBufferSize = setInternalBufferSize;