bson 6.2.0 → 6.4.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,94 @@ 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 tryReadBasicLatin(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
+ function tryWriteBasicLatin(destination, source, offset) {
216
+ if (source.length === 0)
217
+ return 0;
218
+ if (source.length > 25)
219
+ return null;
220
+ if (destination.length - offset < source.length)
221
+ return null;
222
+ for (let charOffset = 0, destinationOffset = offset; charOffset < source.length; charOffset++, destinationOffset++) {
223
+ const char = source.charCodeAt(charOffset);
224
+ if (char > 127)
225
+ return null;
226
+ destination[destinationOffset] = char;
227
+ }
228
+ return source.length;
229
+ }
230
+
143
231
  function nodejsMathRandomBytes(byteLength) {
144
232
  return nodeJsByteUtils.fromNumberArray(Array.from({ length: byteLength }, () => Math.floor(Math.random() * 256)));
145
233
  }
@@ -171,6 +259,9 @@ const nodeJsByteUtils = {
171
259
  allocate(size) {
172
260
  return Buffer.alloc(size);
173
261
  },
262
+ allocateUnsafe(size) {
263
+ return Buffer.allocUnsafe(size);
264
+ },
174
265
  equals(a, b) {
175
266
  return nodeJsByteUtils.toLocalBufferType(a).equals(b);
176
267
  },
@@ -195,16 +286,32 @@ const nodeJsByteUtils = {
195
286
  toHex(buffer) {
196
287
  return nodeJsByteUtils.toLocalBufferType(buffer).toString('hex');
197
288
  },
198
- fromUTF8(text) {
199
- return Buffer.from(text, 'utf8');
200
- },
201
- toUTF8(buffer, start, end) {
202
- return nodeJsByteUtils.toLocalBufferType(buffer).toString('utf8', start, end);
289
+ toUTF8(buffer, start, end, fatal) {
290
+ const basicLatin = end - start <= 20 ? tryReadBasicLatin(buffer, start, end) : null;
291
+ if (basicLatin != null) {
292
+ return basicLatin;
293
+ }
294
+ const string = nodeJsByteUtils.toLocalBufferType(buffer).toString('utf8', start, end);
295
+ if (fatal) {
296
+ for (let i = 0; i < string.length; i++) {
297
+ if (string.charCodeAt(i) === 0xfffd) {
298
+ if (!validateUtf8(buffer, start, end)) {
299
+ throw new BSONError('Invalid UTF-8 string in BSON document');
300
+ }
301
+ break;
302
+ }
303
+ }
304
+ }
305
+ return string;
203
306
  },
204
307
  utf8ByteLength(input) {
205
308
  return Buffer.byteLength(input, 'utf8');
206
309
  },
207
310
  encodeUTF8Into(buffer, source, byteOffset) {
311
+ const latinBytesWritten = tryWriteBasicLatin(buffer, source, byteOffset);
312
+ if (latinBytesWritten != null) {
313
+ return latinBytesWritten;
314
+ }
208
315
  return nodeJsByteUtils.toLocalBufferType(buffer).write(source, byteOffset, undefined, 'utf8');
209
316
  },
210
317
  randomBytes: nodejsRandomBytes
@@ -262,6 +369,9 @@ const webByteUtils = {
262
369
  }
263
370
  return new Uint8Array(size);
264
371
  },
372
+ allocateUnsafe(size) {
373
+ return webByteUtils.allocate(size);
374
+ },
265
375
  equals(a, b) {
266
376
  if (a.byteLength !== b.byteLength) {
267
377
  return false;
@@ -308,18 +418,27 @@ const webByteUtils = {
308
418
  toHex(uint8array) {
309
419
  return Array.from(uint8array, byte => byte.toString(16).padStart(2, '0')).join('');
310
420
  },
311
- fromUTF8(text) {
312
- return new TextEncoder().encode(text);
313
- },
314
- toUTF8(uint8array, start, end) {
315
- return new TextDecoder('utf8', { fatal: false }).decode(uint8array.slice(start, end));
421
+ toUTF8(uint8array, start, end, fatal) {
422
+ const basicLatin = end - start <= 20 ? tryReadBasicLatin(uint8array, start, end) : null;
423
+ if (basicLatin != null) {
424
+ return basicLatin;
425
+ }
426
+ if (fatal) {
427
+ try {
428
+ return new TextDecoder('utf8', { fatal }).decode(uint8array.slice(start, end));
429
+ }
430
+ catch (cause) {
431
+ throw new BSONError('Invalid UTF-8 string in BSON document', { cause });
432
+ }
433
+ }
434
+ return new TextDecoder('utf8', { fatal }).decode(uint8array.slice(start, end));
316
435
  },
317
436
  utf8ByteLength(input) {
318
- return webByteUtils.fromUTF8(input).byteLength;
437
+ return new TextEncoder().encode(input).byteLength;
319
438
  },
320
- encodeUTF8Into(buffer, source, byteOffset) {
321
- const bytes = webByteUtils.fromUTF8(source);
322
- buffer.set(bytes, byteOffset);
439
+ encodeUTF8Into(uint8array, source, byteOffset) {
440
+ const bytes = new TextEncoder().encode(source);
441
+ uint8array.set(bytes, byteOffset);
323
442
  return bytes.byteLength;
324
443
  },
325
444
  randomBytes: webRandomBytes
@@ -327,11 +446,6 @@ const webByteUtils = {
327
446
 
328
447
  const hasGlobalBuffer = typeof Buffer === 'function' && Buffer.prototype?._isBuffer !== true;
329
448
  const ByteUtils = hasGlobalBuffer ? nodeJsByteUtils : webByteUtils;
330
- class BSONDataView extends DataView {
331
- static fromUint8Array(input) {
332
- return new DataView(input.buffer, input.byteOffset, input.byteLength);
333
- }
334
- }
335
449
 
336
450
  class BSONValue {
337
451
  get [Symbol.for('@@mdb.bson.version')]() {
@@ -433,8 +547,8 @@ class Binary extends BSONValue {
433
547
  if (encoding === 'base64')
434
548
  return ByteUtils.toBase64(this.buffer);
435
549
  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);
550
+ return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength, false);
551
+ return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength, false);
438
552
  }
439
553
  toExtendedJSON(options) {
440
554
  options = options || {};
@@ -1751,7 +1865,7 @@ class Decimal128 extends BSONValue {
1751
1865
  if (isNegative) {
1752
1866
  dec.high = dec.high.or(Long.fromString('9223372036854775808'));
1753
1867
  }
1754
- const buffer = ByteUtils.allocate(16);
1868
+ const buffer = ByteUtils.allocateUnsafe(16);
1755
1869
  index = 0;
1756
1870
  buffer[index++] = dec.low.low & 0xff;
1757
1871
  buffer[index++] = (dec.low.low >> 8) & 0xff;
@@ -2024,9 +2138,99 @@ class MinKey extends BSONValue {
2024
2138
  }
2025
2139
  }
2026
2140
 
2141
+ const FLOAT = new Float64Array(1);
2142
+ const FLOAT_BYTES = new Uint8Array(FLOAT.buffer, 0, 8);
2143
+ const NumberUtils = {
2144
+ getInt32LE(source, offset) {
2145
+ return (source[offset] |
2146
+ (source[offset + 1] << 8) |
2147
+ (source[offset + 2] << 16) |
2148
+ (source[offset + 3] << 24));
2149
+ },
2150
+ getUint32LE(source, offset) {
2151
+ return (source[offset] +
2152
+ source[offset + 1] * 256 +
2153
+ source[offset + 2] * 65536 +
2154
+ source[offset + 3] * 16777216);
2155
+ },
2156
+ getUint32BE(source, offset) {
2157
+ return (source[offset + 3] +
2158
+ source[offset + 2] * 256 +
2159
+ source[offset + 1] * 65536 +
2160
+ source[offset] * 16777216);
2161
+ },
2162
+ getBigInt64LE(source, offset) {
2163
+ const lo = NumberUtils.getUint32LE(source, offset);
2164
+ const hi = NumberUtils.getUint32LE(source, offset + 4);
2165
+ return (BigInt(hi) << BigInt(32)) + BigInt(lo);
2166
+ },
2167
+ getFloat64LE(source, offset) {
2168
+ FLOAT_BYTES[0] = source[offset];
2169
+ FLOAT_BYTES[1] = source[offset + 1];
2170
+ FLOAT_BYTES[2] = source[offset + 2];
2171
+ FLOAT_BYTES[3] = source[offset + 3];
2172
+ FLOAT_BYTES[4] = source[offset + 4];
2173
+ FLOAT_BYTES[5] = source[offset + 5];
2174
+ FLOAT_BYTES[6] = source[offset + 6];
2175
+ FLOAT_BYTES[7] = source[offset + 7];
2176
+ return FLOAT[0];
2177
+ },
2178
+ setInt32BE(destination, offset, value) {
2179
+ destination[offset + 3] = value;
2180
+ value >>>= 8;
2181
+ destination[offset + 2] = value;
2182
+ value >>>= 8;
2183
+ destination[offset + 1] = value;
2184
+ value >>>= 8;
2185
+ destination[offset] = value;
2186
+ return 4;
2187
+ },
2188
+ setInt32LE(destination, offset, value) {
2189
+ destination[offset] = value;
2190
+ value >>>= 8;
2191
+ destination[offset + 1] = value;
2192
+ value >>>= 8;
2193
+ destination[offset + 2] = value;
2194
+ value >>>= 8;
2195
+ destination[offset + 3] = value;
2196
+ return 4;
2197
+ },
2198
+ setBigInt64LE(destination, offset, value) {
2199
+ const mask32bits = BigInt(4294967295);
2200
+ let lo = Number(value & mask32bits);
2201
+ destination[offset] = lo;
2202
+ lo >>= 8;
2203
+ destination[offset + 1] = lo;
2204
+ lo >>= 8;
2205
+ destination[offset + 2] = lo;
2206
+ lo >>= 8;
2207
+ destination[offset + 3] = lo;
2208
+ let hi = Number((value >> BigInt(32)) & mask32bits);
2209
+ destination[offset + 4] = hi;
2210
+ hi >>= 8;
2211
+ destination[offset + 5] = hi;
2212
+ hi >>= 8;
2213
+ destination[offset + 6] = hi;
2214
+ hi >>= 8;
2215
+ destination[offset + 7] = hi;
2216
+ return 8;
2217
+ },
2218
+ setFloat64LE(destination, offset, value) {
2219
+ FLOAT[0] = value;
2220
+ destination[offset] = FLOAT_BYTES[0];
2221
+ destination[offset + 1] = FLOAT_BYTES[1];
2222
+ destination[offset + 2] = FLOAT_BYTES[2];
2223
+ destination[offset + 3] = FLOAT_BYTES[3];
2224
+ destination[offset + 4] = FLOAT_BYTES[4];
2225
+ destination[offset + 5] = FLOAT_BYTES[5];
2226
+ destination[offset + 6] = FLOAT_BYTES[6];
2227
+ destination[offset + 7] = FLOAT_BYTES[7];
2228
+ return 8;
2229
+ }
2230
+ };
2231
+
2027
2232
  const checkForHexRegExp = new RegExp('^[0-9a-fA-F]{24}$');
2028
2233
  let PROCESS_UNIQUE = null;
2029
- const kId = Symbol('id');
2030
2234
  class ObjectId extends BSONValue {
2031
2235
  get _bsontype() {
2032
2236
  return 'ObjectId';
@@ -2049,14 +2253,14 @@ class ObjectId extends BSONValue {
2049
2253
  workingId = inputId;
2050
2254
  }
2051
2255
  if (workingId == null || typeof workingId === 'number') {
2052
- this[kId] = ObjectId.generate(typeof workingId === 'number' ? workingId : undefined);
2256
+ this.buffer = ObjectId.generate(typeof workingId === 'number' ? workingId : undefined);
2053
2257
  }
2054
2258
  else if (ArrayBuffer.isView(workingId) && workingId.byteLength === 12) {
2055
- this[kId] = ByteUtils.toLocalBufferType(workingId);
2259
+ this.buffer = ByteUtils.toLocalBufferType(workingId);
2056
2260
  }
2057
2261
  else if (typeof workingId === 'string') {
2058
2262
  if (workingId.length === 24 && checkForHexRegExp.test(workingId)) {
2059
- this[kId] = ByteUtils.fromHex(workingId);
2263
+ this.buffer = ByteUtils.fromHex(workingId);
2060
2264
  }
2061
2265
  else {
2062
2266
  throw new BSONError('input must be a 24 character hex string, 12 byte Uint8Array, or an integer');
@@ -2070,10 +2274,10 @@ class ObjectId extends BSONValue {
2070
2274
  }
2071
2275
  }
2072
2276
  get id() {
2073
- return this[kId];
2277
+ return this.buffer;
2074
2278
  }
2075
2279
  set id(value) {
2076
- this[kId] = value;
2280
+ this.buffer = value;
2077
2281
  if (ObjectId.cacheHexString) {
2078
2282
  this.__id = ByteUtils.toHex(value);
2079
2283
  }
@@ -2096,8 +2300,8 @@ class ObjectId extends BSONValue {
2096
2300
  time = Math.floor(Date.now() / 1000);
2097
2301
  }
2098
2302
  const inc = ObjectId.getInc();
2099
- const buffer = ByteUtils.allocate(12);
2100
- BSONDataView.fromUint8Array(buffer).setUint32(0, time, false);
2303
+ const buffer = ByteUtils.allocateUnsafe(12);
2304
+ NumberUtils.setInt32BE(buffer, 0, time);
2101
2305
  if (PROCESS_UNIQUE === null) {
2102
2306
  PROCESS_UNIQUE = ByteUtils.randomBytes(5);
2103
2307
  }
@@ -2132,7 +2336,7 @@ class ObjectId extends BSONValue {
2132
2336
  return false;
2133
2337
  }
2134
2338
  if (ObjectId.is(otherId)) {
2135
- return this[kId][11] === otherId[kId][11] && ByteUtils.equals(this[kId], otherId[kId]);
2339
+ return (this.buffer[11] === otherId.buffer[11] && ByteUtils.equals(this.buffer, otherId.buffer));
2136
2340
  }
2137
2341
  if (typeof otherId === 'string') {
2138
2342
  return otherId.toLowerCase() === this.toHexString();
@@ -2146,16 +2350,33 @@ class ObjectId extends BSONValue {
2146
2350
  }
2147
2351
  getTimestamp() {
2148
2352
  const timestamp = new Date();
2149
- const time = BSONDataView.fromUint8Array(this.id).getUint32(0, false);
2353
+ const time = NumberUtils.getUint32BE(this.buffer, 0);
2150
2354
  timestamp.setTime(Math.floor(time) * 1000);
2151
2355
  return timestamp;
2152
2356
  }
2153
2357
  static createPk() {
2154
2358
  return new ObjectId();
2155
2359
  }
2360
+ serializeInto(uint8array, index) {
2361
+ uint8array[index] = this.buffer[0];
2362
+ uint8array[index + 1] = this.buffer[1];
2363
+ uint8array[index + 2] = this.buffer[2];
2364
+ uint8array[index + 3] = this.buffer[3];
2365
+ uint8array[index + 4] = this.buffer[4];
2366
+ uint8array[index + 5] = this.buffer[5];
2367
+ uint8array[index + 6] = this.buffer[6];
2368
+ uint8array[index + 7] = this.buffer[7];
2369
+ uint8array[index + 8] = this.buffer[8];
2370
+ uint8array[index + 9] = this.buffer[9];
2371
+ uint8array[index + 10] = this.buffer[10];
2372
+ uint8array[index + 11] = this.buffer[11];
2373
+ return 12;
2374
+ }
2156
2375
  static createFromTime(time) {
2157
- const buffer = ByteUtils.fromNumberArray([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
2158
- BSONDataView.fromUint8Array(buffer).setUint32(0, time, false);
2376
+ const buffer = ByteUtils.allocate(12);
2377
+ for (let i = 11; i >= 4; i--)
2378
+ buffer[i] = 0;
2379
+ NumberUtils.setInt32BE(buffer, 0, time);
2159
2380
  return new ObjectId(buffer);
2160
2381
  }
2161
2382
  static createFromHexString(hexString) {
@@ -2522,52 +2743,12 @@ class Timestamp extends LongWithoutOverridesClass {
2522
2743
  }
2523
2744
  Timestamp.MAX_VALUE = Long.MAX_UNSIGNED_VALUE;
2524
2745
 
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
2746
  const JS_INT_MAX_LONG = Long.fromNumber(JS_INT_MAX);
2563
2747
  const JS_INT_MIN_LONG = Long.fromNumber(JS_INT_MIN);
2564
2748
  function internalDeserialize(buffer, options, isArray) {
2565
2749
  options = options == null ? {} : options;
2566
2750
  const index = options && options.index ? options.index : 0;
2567
- const size = buffer[index] |
2568
- (buffer[index + 1] << 8) |
2569
- (buffer[index + 2] << 16) |
2570
- (buffer[index + 3] << 24);
2751
+ const size = NumberUtils.getInt32LE(buffer, index);
2571
2752
  if (size < 5) {
2572
2753
  throw new BSONError(`bson size must be >= 5, is ${size}`);
2573
2754
  }
@@ -2603,7 +2784,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2603
2784
  const validation = options.validation == null ? { utf8: true } : options.validation;
2604
2785
  let globalUTFValidation = true;
2605
2786
  let validationSetting;
2606
- const utf8KeysSet = new Set();
2787
+ let utf8KeysSet;
2607
2788
  const utf8ValidatedKeys = validation.utf8;
2608
2789
  if (typeof utf8ValidatedKeys === 'boolean') {
2609
2790
  validationSetting = utf8ValidatedKeys;
@@ -2625,6 +2806,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2625
2806
  }
2626
2807
  }
2627
2808
  if (!globalUTFValidation) {
2809
+ utf8KeysSet = new Set();
2628
2810
  for (const key of Object.keys(utf8ValidatedKeys)) {
2629
2811
  utf8KeysSet.add(key);
2630
2812
  }
@@ -2632,14 +2814,14 @@ function deserializeObject(buffer, index, options, isArray = false) {
2632
2814
  const startIndex = index;
2633
2815
  if (buffer.length < 5)
2634
2816
  throw new BSONError('corrupt bson message < 5 bytes long');
2635
- const size = buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
2817
+ const size = NumberUtils.getInt32LE(buffer, index);
2818
+ index += 4;
2636
2819
  if (size < 5 || size > buffer.length)
2637
2820
  throw new BSONError('corrupt bson message');
2638
2821
  const object = isArray ? [] : {};
2639
2822
  let arrayIndex = 0;
2640
2823
  const done = false;
2641
2824
  let isPossibleDBRef = isArray ? false : null;
2642
- const dataview = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
2643
2825
  while (!done) {
2644
2826
  const elementType = buffer[index++];
2645
2827
  if (elementType === 0)
@@ -2650,9 +2832,9 @@ function deserializeObject(buffer, index, options, isArray = false) {
2650
2832
  }
2651
2833
  if (i >= buffer.byteLength)
2652
2834
  throw new BSONError('Bad BSON Document: illegal CString');
2653
- const name = isArray ? arrayIndex++ : ByteUtils.toUTF8(buffer, index, i);
2835
+ const name = isArray ? arrayIndex++ : ByteUtils.toUTF8(buffer, index, i, false);
2654
2836
  let shouldValidateKey = true;
2655
- if (globalUTFValidation || utf8KeysSet.has(name)) {
2837
+ if (globalUTFValidation || utf8KeysSet?.has(name)) {
2656
2838
  shouldValidateKey = validationSetting;
2657
2839
  }
2658
2840
  else {
@@ -2664,51 +2846,41 @@ function deserializeObject(buffer, index, options, isArray = false) {
2664
2846
  let value;
2665
2847
  index = i + 1;
2666
2848
  if (elementType === BSON_DATA_STRING) {
2667
- const stringSize = buffer[index++] |
2668
- (buffer[index++] << 8) |
2669
- (buffer[index++] << 16) |
2670
- (buffer[index++] << 24);
2849
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
2850
+ index += 4;
2671
2851
  if (stringSize <= 0 ||
2672
2852
  stringSize > buffer.length - index ||
2673
2853
  buffer[index + stringSize - 1] !== 0) {
2674
2854
  throw new BSONError('bad string length in bson');
2675
2855
  }
2676
- value = getValidatedString(buffer, index, index + stringSize - 1, shouldValidateKey);
2856
+ value = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
2677
2857
  index = index + stringSize;
2678
2858
  }
2679
2859
  else if (elementType === BSON_DATA_OID) {
2680
- const oid = ByteUtils.allocate(12);
2681
- oid.set(buffer.subarray(index, index + 12));
2860
+ const oid = ByteUtils.allocateUnsafe(12);
2861
+ for (let i = 0; i < 12; i++)
2862
+ oid[i] = buffer[index + i];
2682
2863
  value = new ObjectId(oid);
2683
2864
  index = index + 12;
2684
2865
  }
2685
2866
  else if (elementType === BSON_DATA_INT && promoteValues === false) {
2686
- value = new Int32(buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24));
2867
+ value = new Int32(NumberUtils.getInt32LE(buffer, index));
2868
+ index += 4;
2687
2869
  }
2688
2870
  else if (elementType === BSON_DATA_INT) {
2689
- value =
2690
- buffer[index++] |
2691
- (buffer[index++] << 8) |
2692
- (buffer[index++] << 16) |
2693
- (buffer[index++] << 24);
2694
- }
2695
- else if (elementType === BSON_DATA_NUMBER && promoteValues === false) {
2696
- value = new Double(dataview.getFloat64(index, true));
2697
- index = index + 8;
2871
+ value = NumberUtils.getInt32LE(buffer, index);
2872
+ index += 4;
2698
2873
  }
2699
2874
  else if (elementType === BSON_DATA_NUMBER) {
2700
- value = dataview.getFloat64(index, true);
2701
- index = index + 8;
2875
+ value = NumberUtils.getFloat64LE(buffer, index);
2876
+ index += 8;
2877
+ if (promoteValues === false)
2878
+ value = new Double(value);
2702
2879
  }
2703
2880
  else if (elementType === BSON_DATA_DATE) {
2704
- const lowBits = buffer[index++] |
2705
- (buffer[index++] << 8) |
2706
- (buffer[index++] << 16) |
2707
- (buffer[index++] << 24);
2708
- const highBits = buffer[index++] |
2709
- (buffer[index++] << 8) |
2710
- (buffer[index++] << 16) |
2711
- (buffer[index++] << 24);
2881
+ const lowBits = NumberUtils.getInt32LE(buffer, index);
2882
+ const highBits = NumberUtils.getInt32LE(buffer, index + 4);
2883
+ index += 8;
2712
2884
  value = new Date(new Long(lowBits, highBits).toNumber());
2713
2885
  }
2714
2886
  else if (elementType === BSON_DATA_BOOLEAN) {
@@ -2718,10 +2890,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2718
2890
  }
2719
2891
  else if (elementType === BSON_DATA_OBJECT) {
2720
2892
  const _index = index;
2721
- const objectSize = buffer[index] |
2722
- (buffer[index + 1] << 8) |
2723
- (buffer[index + 2] << 16) |
2724
- (buffer[index + 3] << 24);
2893
+ const objectSize = NumberUtils.getInt32LE(buffer, index);
2725
2894
  if (objectSize <= 0 || objectSize > buffer.length - index)
2726
2895
  throw new BSONError('bad embedded document length in bson');
2727
2896
  if (raw) {
@@ -2738,10 +2907,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2738
2907
  }
2739
2908
  else if (elementType === BSON_DATA_ARRAY) {
2740
2909
  const _index = index;
2741
- const objectSize = buffer[index] |
2742
- (buffer[index + 1] << 8) |
2743
- (buffer[index + 2] << 16) |
2744
- (buffer[index + 3] << 24);
2910
+ const objectSize = NumberUtils.getInt32LE(buffer, index);
2745
2911
  let arrayOptions = options;
2746
2912
  const stopIndex = index + objectSize;
2747
2913
  if (fieldsAsRaw && fieldsAsRaw[name]) {
@@ -2764,40 +2930,36 @@ function deserializeObject(buffer, index, options, isArray = false) {
2764
2930
  value = null;
2765
2931
  }
2766
2932
  else if (elementType === BSON_DATA_LONG) {
2767
- const dataview = BSONDataView.fromUint8Array(buffer.subarray(index, index + 8));
2768
- const lowBits = buffer[index++] |
2769
- (buffer[index++] << 8) |
2770
- (buffer[index++] << 16) |
2771
- (buffer[index++] << 24);
2772
- const highBits = buffer[index++] |
2773
- (buffer[index++] << 8) |
2774
- (buffer[index++] << 16) |
2775
- (buffer[index++] << 24);
2776
- const long = new Long(lowBits, highBits);
2777
2933
  if (useBigInt64) {
2778
- value = dataview.getBigInt64(0, true);
2779
- }
2780
- else if (promoteLongs && promoteValues === true) {
2781
- value =
2782
- long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG)
2783
- ? long.toNumber()
2784
- : long;
2934
+ value = NumberUtils.getBigInt64LE(buffer, index);
2935
+ index += 8;
2785
2936
  }
2786
2937
  else {
2787
- value = long;
2938
+ const lowBits = NumberUtils.getInt32LE(buffer, index);
2939
+ const highBits = NumberUtils.getInt32LE(buffer, index + 4);
2940
+ index += 8;
2941
+ const long = new Long(lowBits, highBits);
2942
+ if (promoteLongs && promoteValues === true) {
2943
+ value =
2944
+ long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG)
2945
+ ? long.toNumber()
2946
+ : long;
2947
+ }
2948
+ else {
2949
+ value = long;
2950
+ }
2788
2951
  }
2789
2952
  }
2790
2953
  else if (elementType === BSON_DATA_DECIMAL128) {
2791
- const bytes = ByteUtils.allocate(16);
2792
- bytes.set(buffer.subarray(index, index + 16), 0);
2954
+ const bytes = ByteUtils.allocateUnsafe(16);
2955
+ for (let i = 0; i < 16; i++)
2956
+ bytes[i] = buffer[index + i];
2793
2957
  index = index + 16;
2794
2958
  value = new Decimal128(bytes);
2795
2959
  }
2796
2960
  else if (elementType === BSON_DATA_BINARY) {
2797
- let binarySize = buffer[index++] |
2798
- (buffer[index++] << 8) |
2799
- (buffer[index++] << 16) |
2800
- (buffer[index++] << 24);
2961
+ let binarySize = NumberUtils.getInt32LE(buffer, index);
2962
+ index += 4;
2801
2963
  const totalBinarySize = binarySize;
2802
2964
  const subType = buffer[index++];
2803
2965
  if (binarySize < 0)
@@ -2806,11 +2968,8 @@ function deserializeObject(buffer, index, options, isArray = false) {
2806
2968
  throw new BSONError('Binary type size larger than document size');
2807
2969
  if (buffer['slice'] != null) {
2808
2970
  if (subType === Binary.SUBTYPE_BYTE_ARRAY) {
2809
- binarySize =
2810
- buffer[index++] |
2811
- (buffer[index++] << 8) |
2812
- (buffer[index++] << 16) |
2813
- (buffer[index++] << 24);
2971
+ binarySize = NumberUtils.getInt32LE(buffer, index);
2972
+ index += 4;
2814
2973
  if (binarySize < 0)
2815
2974
  throw new BSONError('Negative binary type element size found for subtype 0x02');
2816
2975
  if (binarySize > totalBinarySize - 4)
@@ -2829,13 +2988,9 @@ function deserializeObject(buffer, index, options, isArray = false) {
2829
2988
  }
2830
2989
  }
2831
2990
  else {
2832
- const _buffer = ByteUtils.allocate(binarySize);
2833
2991
  if (subType === Binary.SUBTYPE_BYTE_ARRAY) {
2834
- binarySize =
2835
- buffer[index++] |
2836
- (buffer[index++] << 8) |
2837
- (buffer[index++] << 16) |
2838
- (buffer[index++] << 24);
2992
+ binarySize = NumberUtils.getInt32LE(buffer, index);
2993
+ index += 4;
2839
2994
  if (binarySize < 0)
2840
2995
  throw new BSONError('Negative binary type element size found for subtype 0x02');
2841
2996
  if (binarySize > totalBinarySize - 4)
@@ -2843,11 +2998,11 @@ function deserializeObject(buffer, index, options, isArray = false) {
2843
2998
  if (binarySize < totalBinarySize - 4)
2844
2999
  throw new BSONError('Binary type with subtype 0x02 contains too short binary size');
2845
3000
  }
2846
- for (i = 0; i < binarySize; i++) {
2847
- _buffer[i] = buffer[index + i];
2848
- }
2849
3001
  if (promoteBuffers && promoteValues) {
2850
- value = _buffer;
3002
+ value = ByteUtils.allocateUnsafe(binarySize);
3003
+ for (i = 0; i < binarySize; i++) {
3004
+ value[i] = buffer[index + i];
3005
+ }
2851
3006
  }
2852
3007
  else {
2853
3008
  value = new Binary(buffer.slice(index, index + binarySize), subType);
@@ -2865,7 +3020,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2865
3020
  }
2866
3021
  if (i >= buffer.length)
2867
3022
  throw new BSONError('Bad BSON Document: illegal CString');
2868
- const source = ByteUtils.toUTF8(buffer, index, i);
3023
+ const source = ByteUtils.toUTF8(buffer, index, i, false);
2869
3024
  index = i + 1;
2870
3025
  i = index;
2871
3026
  while (buffer[i] !== 0x00 && i < buffer.length) {
@@ -2873,7 +3028,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2873
3028
  }
2874
3029
  if (i >= buffer.length)
2875
3030
  throw new BSONError('Bad BSON Document: illegal CString');
2876
- const regExpOptions = ByteUtils.toUTF8(buffer, index, i);
3031
+ const regExpOptions = ByteUtils.toUTF8(buffer, index, i, false);
2877
3032
  index = i + 1;
2878
3033
  const optionsArray = new Array(regExpOptions.length);
2879
3034
  for (i = 0; i < regExpOptions.length; i++) {
@@ -2898,7 +3053,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2898
3053
  }
2899
3054
  if (i >= buffer.length)
2900
3055
  throw new BSONError('Bad BSON Document: illegal CString');
2901
- const source = ByteUtils.toUTF8(buffer, index, i);
3056
+ const source = ByteUtils.toUTF8(buffer, index, i, false);
2902
3057
  index = i + 1;
2903
3058
  i = index;
2904
3059
  while (buffer[i] !== 0x00 && i < buffer.length) {
@@ -2906,34 +3061,28 @@ function deserializeObject(buffer, index, options, isArray = false) {
2906
3061
  }
2907
3062
  if (i >= buffer.length)
2908
3063
  throw new BSONError('Bad BSON Document: illegal CString');
2909
- const regExpOptions = ByteUtils.toUTF8(buffer, index, i);
3064
+ const regExpOptions = ByteUtils.toUTF8(buffer, index, i, false);
2910
3065
  index = i + 1;
2911
3066
  value = new BSONRegExp(source, regExpOptions);
2912
3067
  }
2913
3068
  else if (elementType === BSON_DATA_SYMBOL) {
2914
- const stringSize = buffer[index++] |
2915
- (buffer[index++] << 8) |
2916
- (buffer[index++] << 16) |
2917
- (buffer[index++] << 24);
3069
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
3070
+ index += 4;
2918
3071
  if (stringSize <= 0 ||
2919
3072
  stringSize > buffer.length - index ||
2920
3073
  buffer[index + stringSize - 1] !== 0) {
2921
3074
  throw new BSONError('bad string length in bson');
2922
3075
  }
2923
- const symbol = getValidatedString(buffer, index, index + stringSize - 1, shouldValidateKey);
3076
+ const symbol = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
2924
3077
  value = promoteValues ? symbol : new BSONSymbol(symbol);
2925
3078
  index = index + stringSize;
2926
3079
  }
2927
3080
  else if (elementType === BSON_DATA_TIMESTAMP) {
2928
- const i = buffer[index++] +
2929
- buffer[index++] * (1 << 8) +
2930
- buffer[index++] * (1 << 16) +
2931
- buffer[index++] * (1 << 24);
2932
- const t = buffer[index++] +
2933
- buffer[index++] * (1 << 8) +
2934
- buffer[index++] * (1 << 16) +
2935
- buffer[index++] * (1 << 24);
2936
- value = new Timestamp({ i, t });
3081
+ value = new Timestamp({
3082
+ i: NumberUtils.getUint32LE(buffer, index),
3083
+ t: NumberUtils.getUint32LE(buffer, index + 4)
3084
+ });
3085
+ index += 8;
2937
3086
  }
2938
3087
  else if (elementType === BSON_DATA_MIN_KEY) {
2939
3088
  value = new MinKey();
@@ -2942,43 +3091,34 @@ function deserializeObject(buffer, index, options, isArray = false) {
2942
3091
  value = new MaxKey();
2943
3092
  }
2944
3093
  else if (elementType === BSON_DATA_CODE) {
2945
- const stringSize = buffer[index++] |
2946
- (buffer[index++] << 8) |
2947
- (buffer[index++] << 16) |
2948
- (buffer[index++] << 24);
3094
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
3095
+ index += 4;
2949
3096
  if (stringSize <= 0 ||
2950
3097
  stringSize > buffer.length - index ||
2951
3098
  buffer[index + stringSize - 1] !== 0) {
2952
3099
  throw new BSONError('bad string length in bson');
2953
3100
  }
2954
- const functionString = getValidatedString(buffer, index, index + stringSize - 1, shouldValidateKey);
3101
+ const functionString = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
2955
3102
  value = new Code(functionString);
2956
3103
  index = index + stringSize;
2957
3104
  }
2958
3105
  else if (elementType === BSON_DATA_CODE_W_SCOPE) {
2959
- const totalSize = buffer[index++] |
2960
- (buffer[index++] << 8) |
2961
- (buffer[index++] << 16) |
2962
- (buffer[index++] << 24);
3106
+ const totalSize = NumberUtils.getInt32LE(buffer, index);
3107
+ index += 4;
2963
3108
  if (totalSize < 4 + 4 + 4 + 1) {
2964
3109
  throw new BSONError('code_w_scope total size shorter minimum expected length');
2965
3110
  }
2966
- const stringSize = buffer[index++] |
2967
- (buffer[index++] << 8) |
2968
- (buffer[index++] << 16) |
2969
- (buffer[index++] << 24);
3111
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
3112
+ index += 4;
2970
3113
  if (stringSize <= 0 ||
2971
3114
  stringSize > buffer.length - index ||
2972
3115
  buffer[index + stringSize - 1] !== 0) {
2973
3116
  throw new BSONError('bad string length in bson');
2974
3117
  }
2975
- const functionString = getValidatedString(buffer, index, index + stringSize - 1, shouldValidateKey);
3118
+ const functionString = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
2976
3119
  index = index + stringSize;
2977
3120
  const _index = index;
2978
- const objectSize = buffer[index] |
2979
- (buffer[index + 1] << 8) |
2980
- (buffer[index + 2] << 16) |
2981
- (buffer[index + 3] << 24);
3121
+ const objectSize = NumberUtils.getInt32LE(buffer, index);
2982
3122
  const scopeObject = deserializeObject(buffer, _index, options, false);
2983
3123
  index = index + objectSize;
2984
3124
  if (totalSize < 4 + 4 + objectSize + stringSize) {
@@ -2990,10 +3130,8 @@ function deserializeObject(buffer, index, options, isArray = false) {
2990
3130
  value = new Code(functionString, scopeObject);
2991
3131
  }
2992
3132
  else if (elementType === BSON_DATA_DBPOINTER) {
2993
- const stringSize = buffer[index++] |
2994
- (buffer[index++] << 8) |
2995
- (buffer[index++] << 16) |
2996
- (buffer[index++] << 24);
3133
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
3134
+ index += 4;
2997
3135
  if (stringSize <= 0 ||
2998
3136
  stringSize > buffer.length - index ||
2999
3137
  buffer[index + stringSize - 1] !== 0)
@@ -3003,10 +3141,11 @@ function deserializeObject(buffer, index, options, isArray = false) {
3003
3141
  throw new BSONError('Invalid UTF-8 string in BSON document');
3004
3142
  }
3005
3143
  }
3006
- const namespace = ByteUtils.toUTF8(buffer, index, index + stringSize - 1);
3144
+ const namespace = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, false);
3007
3145
  index = index + stringSize;
3008
- const oidBuffer = ByteUtils.allocate(12);
3009
- oidBuffer.set(buffer.subarray(index, index + 12), 0);
3146
+ const oidBuffer = ByteUtils.allocateUnsafe(12);
3147
+ for (let i = 0; i < 12; i++)
3148
+ oidBuffer[i] = buffer[index + i];
3010
3149
  const oid = new ObjectId(oidBuffer);
3011
3150
  index = index + 12;
3012
3151
  value = new DBRef(namespace, oid);
@@ -3042,20 +3181,6 @@ function deserializeObject(buffer, index, options, isArray = false) {
3042
3181
  }
3043
3182
  return object;
3044
3183
  }
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
3184
 
3060
3185
  const regexp = /\x00/;
3061
3186
  const ignoreKeys = new Set(['$db', '$ref', '$id', '$clusterTime']);
@@ -3065,17 +3190,11 @@ function serializeString(buffer, key, value, index) {
3065
3190
  index = index + numberOfWrittenBytes + 1;
3066
3191
  buffer[index - 1] = 0;
3067
3192
  const size = ByteUtils.encodeUTF8Into(buffer, value, index + 4);
3068
- buffer[index + 3] = ((size + 1) >> 24) & 0xff;
3069
- buffer[index + 2] = ((size + 1) >> 16) & 0xff;
3070
- buffer[index + 1] = ((size + 1) >> 8) & 0xff;
3071
- buffer[index] = (size + 1) & 0xff;
3193
+ NumberUtils.setInt32LE(buffer, index, size + 1);
3072
3194
  index = index + 4 + size;
3073
3195
  buffer[index++] = 0;
3074
3196
  return index;
3075
3197
  }
3076
- const NUMBER_SPACE = new DataView(new ArrayBuffer(8), 0, 8);
3077
- const FOUR_BYTE_VIEW_ON_NUMBER = new Uint8Array(NUMBER_SPACE.buffer, 0, 4);
3078
- const EIGHT_BYTE_VIEW_ON_NUMBER = new Uint8Array(NUMBER_SPACE.buffer, 0, 8);
3079
3198
  function serializeNumber(buffer, key, value, index) {
3080
3199
  const isNegativeZero = Object.is(value, -0);
3081
3200
  const type = !isNegativeZero &&
@@ -3084,19 +3203,16 @@ function serializeNumber(buffer, key, value, index) {
3084
3203
  value >= BSON_INT32_MIN
3085
3204
  ? BSON_DATA_INT
3086
3205
  : BSON_DATA_NUMBER;
3087
- if (type === BSON_DATA_INT) {
3088
- NUMBER_SPACE.setInt32(0, value, true);
3089
- }
3090
- else {
3091
- NUMBER_SPACE.setFloat64(0, value, true);
3092
- }
3093
- const bytes = type === BSON_DATA_INT ? FOUR_BYTE_VIEW_ON_NUMBER : EIGHT_BYTE_VIEW_ON_NUMBER;
3094
3206
  buffer[index++] = type;
3095
3207
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3096
3208
  index = index + numberOfWrittenBytes;
3097
3209
  buffer[index++] = 0x00;
3098
- buffer.set(bytes, index);
3099
- index += bytes.byteLength;
3210
+ if (type === BSON_DATA_INT) {
3211
+ index += NumberUtils.setInt32LE(buffer, index, value);
3212
+ }
3213
+ else {
3214
+ index += NumberUtils.setFloat64LE(buffer, index, value);
3215
+ }
3100
3216
  return index;
3101
3217
  }
3102
3218
  function serializeBigInt(buffer, key, value, index) {
@@ -3104,9 +3220,7 @@ function serializeBigInt(buffer, key, value, index) {
3104
3220
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3105
3221
  index += numberOfWrittenBytes;
3106
3222
  buffer[index++] = 0;
3107
- NUMBER_SPACE.setBigInt64(0, value, true);
3108
- buffer.set(EIGHT_BYTE_VIEW_ON_NUMBER, index);
3109
- index += EIGHT_BYTE_VIEW_ON_NUMBER.byteLength;
3223
+ index += NumberUtils.setBigInt64LE(buffer, index, value);
3110
3224
  return index;
3111
3225
  }
3112
3226
  function serializeNull(buffer, key, _, index) {
@@ -3132,14 +3246,8 @@ function serializeDate(buffer, key, value, index) {
3132
3246
  const dateInMilis = Long.fromNumber(value.getTime());
3133
3247
  const lowBits = dateInMilis.getLowBits();
3134
3248
  const highBits = dateInMilis.getHighBits();
3135
- buffer[index++] = lowBits & 0xff;
3136
- buffer[index++] = (lowBits >> 8) & 0xff;
3137
- buffer[index++] = (lowBits >> 16) & 0xff;
3138
- buffer[index++] = (lowBits >> 24) & 0xff;
3139
- buffer[index++] = highBits & 0xff;
3140
- buffer[index++] = (highBits >> 8) & 0xff;
3141
- buffer[index++] = (highBits >> 16) & 0xff;
3142
- buffer[index++] = (highBits >> 24) & 0xff;
3249
+ index += NumberUtils.setInt32LE(buffer, index, lowBits);
3250
+ index += NumberUtils.setInt32LE(buffer, index, highBits);
3143
3251
  return index;
3144
3252
  }
3145
3253
  function serializeRegExp(buffer, key, value, index) {
@@ -3196,15 +3304,7 @@ function serializeObjectId(buffer, key, value, index) {
3196
3304
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3197
3305
  index = index + numberOfWrittenBytes;
3198
3306
  buffer[index++] = 0;
3199
- const idValue = value.id;
3200
- if (isUint8Array(idValue)) {
3201
- for (let i = 0; i < 12; i++) {
3202
- buffer[index++] = idValue[i];
3203
- }
3204
- }
3205
- else {
3206
- throw new BSONError('object [' + JSON.stringify(value) + '] is not a valid ObjectId');
3207
- }
3307
+ index += value.serializeInto(buffer, index);
3208
3308
  return index;
3209
3309
  }
3210
3310
  function serializeBuffer(buffer, key, value, index) {
@@ -3213,12 +3313,15 @@ function serializeBuffer(buffer, key, value, index) {
3213
3313
  index = index + numberOfWrittenBytes;
3214
3314
  buffer[index++] = 0;
3215
3315
  const size = value.length;
3216
- buffer[index++] = size & 0xff;
3217
- buffer[index++] = (size >> 8) & 0xff;
3218
- buffer[index++] = (size >> 16) & 0xff;
3219
- buffer[index++] = (size >> 24) & 0xff;
3316
+ index += NumberUtils.setInt32LE(buffer, index, size);
3220
3317
  buffer[index++] = BSON_BINARY_SUBTYPE_DEFAULT;
3221
- buffer.set(value, index);
3318
+ if (size <= 16) {
3319
+ for (let i = 0; i < size; i++)
3320
+ buffer[index + i] = value[i];
3321
+ }
3322
+ else {
3323
+ buffer.set(value, index);
3324
+ }
3222
3325
  index = index + size;
3223
3326
  return index;
3224
3327
  }
@@ -3240,7 +3343,8 @@ function serializeDecimal128(buffer, key, value, index) {
3240
3343
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3241
3344
  index = index + numberOfWrittenBytes;
3242
3345
  buffer[index++] = 0;
3243
- buffer.set(value.bytes.subarray(0, 16), index);
3346
+ for (let i = 0; i < 16; i++)
3347
+ buffer[index + i] = value.bytes[i];
3244
3348
  return index + 16;
3245
3349
  }
3246
3350
  function serializeLong(buffer, key, value, index) {
@@ -3251,14 +3355,8 @@ function serializeLong(buffer, key, value, index) {
3251
3355
  buffer[index++] = 0;
3252
3356
  const lowBits = value.getLowBits();
3253
3357
  const highBits = value.getHighBits();
3254
- buffer[index++] = lowBits & 0xff;
3255
- buffer[index++] = (lowBits >> 8) & 0xff;
3256
- buffer[index++] = (lowBits >> 16) & 0xff;
3257
- buffer[index++] = (lowBits >> 24) & 0xff;
3258
- buffer[index++] = highBits & 0xff;
3259
- buffer[index++] = (highBits >> 8) & 0xff;
3260
- buffer[index++] = (highBits >> 16) & 0xff;
3261
- buffer[index++] = (highBits >> 24) & 0xff;
3358
+ index += NumberUtils.setInt32LE(buffer, index, lowBits);
3359
+ index += NumberUtils.setInt32LE(buffer, index, highBits);
3262
3360
  return index;
3263
3361
  }
3264
3362
  function serializeInt32(buffer, key, value, index) {
@@ -3267,10 +3365,7 @@ function serializeInt32(buffer, key, value, index) {
3267
3365
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3268
3366
  index = index + numberOfWrittenBytes;
3269
3367
  buffer[index++] = 0;
3270
- buffer[index++] = value & 0xff;
3271
- buffer[index++] = (value >> 8) & 0xff;
3272
- buffer[index++] = (value >> 16) & 0xff;
3273
- buffer[index++] = (value >> 24) & 0xff;
3368
+ index += NumberUtils.setInt32LE(buffer, index, value);
3274
3369
  return index;
3275
3370
  }
3276
3371
  function serializeDouble(buffer, key, value, index) {
@@ -3278,9 +3373,7 @@ function serializeDouble(buffer, key, value, index) {
3278
3373
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3279
3374
  index = index + numberOfWrittenBytes;
3280
3375
  buffer[index++] = 0;
3281
- NUMBER_SPACE.setFloat64(0, value.value, true);
3282
- buffer.set(EIGHT_BYTE_VIEW_ON_NUMBER, index);
3283
- index = index + 8;
3376
+ index += NumberUtils.setFloat64LE(buffer, index, value.value);
3284
3377
  return index;
3285
3378
  }
3286
3379
  function serializeFunction(buffer, key, value, index) {
@@ -3290,10 +3383,7 @@ function serializeFunction(buffer, key, value, index) {
3290
3383
  buffer[index++] = 0;
3291
3384
  const functionString = value.toString();
3292
3385
  const size = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
3293
- buffer[index] = size & 0xff;
3294
- buffer[index + 1] = (size >> 8) & 0xff;
3295
- buffer[index + 2] = (size >> 16) & 0xff;
3296
- buffer[index + 3] = (size >> 24) & 0xff;
3386
+ NumberUtils.setInt32LE(buffer, index, size);
3297
3387
  index = index + 4 + size - 1;
3298
3388
  buffer[index++] = 0;
3299
3389
  return index;
@@ -3308,19 +3398,13 @@ function serializeCode(buffer, key, value, index, checkKeys = false, depth = 0,
3308
3398
  const functionString = value.code;
3309
3399
  index = index + 4;
3310
3400
  const codeSize = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
3311
- buffer[index] = codeSize & 0xff;
3312
- buffer[index + 1] = (codeSize >> 8) & 0xff;
3313
- buffer[index + 2] = (codeSize >> 16) & 0xff;
3314
- buffer[index + 3] = (codeSize >> 24) & 0xff;
3401
+ NumberUtils.setInt32LE(buffer, index, codeSize);
3315
3402
  buffer[index + 4 + codeSize - 1] = 0;
3316
3403
  index = index + codeSize + 4;
3317
3404
  const endIndex = serializeInto(buffer, value.scope, checkKeys, index, depth + 1, serializeFunctions, ignoreUndefined, path);
3318
3405
  index = endIndex - 1;
3319
3406
  const totalSize = endIndex - startIndex;
3320
- buffer[startIndex++] = totalSize & 0xff;
3321
- buffer[startIndex++] = (totalSize >> 8) & 0xff;
3322
- buffer[startIndex++] = (totalSize >> 16) & 0xff;
3323
- buffer[startIndex++] = (totalSize >> 24) & 0xff;
3407
+ startIndex += NumberUtils.setInt32LE(buffer, startIndex, totalSize);
3324
3408
  buffer[index++] = 0;
3325
3409
  }
3326
3410
  else {
@@ -3330,10 +3414,7 @@ function serializeCode(buffer, key, value, index, checkKeys = false, depth = 0,
3330
3414
  buffer[index++] = 0;
3331
3415
  const functionString = value.code.toString();
3332
3416
  const size = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
3333
- buffer[index] = size & 0xff;
3334
- buffer[index + 1] = (size >> 8) & 0xff;
3335
- buffer[index + 2] = (size >> 16) & 0xff;
3336
- buffer[index + 3] = (size >> 24) & 0xff;
3417
+ NumberUtils.setInt32LE(buffer, index, size);
3337
3418
  index = index + 4 + size - 1;
3338
3419
  buffer[index++] = 0;
3339
3420
  }
@@ -3348,19 +3429,19 @@ function serializeBinary(buffer, key, value, index) {
3348
3429
  let size = value.position;
3349
3430
  if (value.sub_type === Binary.SUBTYPE_BYTE_ARRAY)
3350
3431
  size = size + 4;
3351
- buffer[index++] = size & 0xff;
3352
- buffer[index++] = (size >> 8) & 0xff;
3353
- buffer[index++] = (size >> 16) & 0xff;
3354
- buffer[index++] = (size >> 24) & 0xff;
3432
+ index += NumberUtils.setInt32LE(buffer, index, size);
3355
3433
  buffer[index++] = value.sub_type;
3356
3434
  if (value.sub_type === Binary.SUBTYPE_BYTE_ARRAY) {
3357
3435
  size = size - 4;
3358
- buffer[index++] = size & 0xff;
3359
- buffer[index++] = (size >> 8) & 0xff;
3360
- buffer[index++] = (size >> 16) & 0xff;
3361
- buffer[index++] = (size >> 24) & 0xff;
3436
+ index += NumberUtils.setInt32LE(buffer, index, size);
3437
+ }
3438
+ if (size <= 16) {
3439
+ for (let i = 0; i < size; i++)
3440
+ buffer[index + i] = data[i];
3441
+ }
3442
+ else {
3443
+ buffer.set(data, index);
3362
3444
  }
3363
- buffer.set(data, index);
3364
3445
  index = index + value.position;
3365
3446
  return index;
3366
3447
  }
@@ -3370,12 +3451,9 @@ function serializeSymbol(buffer, key, value, index) {
3370
3451
  index = index + numberOfWrittenBytes;
3371
3452
  buffer[index++] = 0;
3372
3453
  const size = ByteUtils.encodeUTF8Into(buffer, value.value, index + 4) + 1;
3373
- buffer[index] = size & 0xff;
3374
- buffer[index + 1] = (size >> 8) & 0xff;
3375
- buffer[index + 2] = (size >> 16) & 0xff;
3376
- buffer[index + 3] = (size >> 24) & 0xff;
3454
+ NumberUtils.setInt32LE(buffer, index, size);
3377
3455
  index = index + 4 + size - 1;
3378
- buffer[index++] = 0x00;
3456
+ buffer[index++] = 0;
3379
3457
  return index;
3380
3458
  }
3381
3459
  function serializeDBRef(buffer, key, value, index, depth, serializeFunctions, path) {
@@ -3394,10 +3472,7 @@ function serializeDBRef(buffer, key, value, index, depth, serializeFunctions, pa
3394
3472
  output = Object.assign(output, value.fields);
3395
3473
  const endIndex = serializeInto(buffer, output, false, index, depth + 1, serializeFunctions, true, path);
3396
3474
  const size = endIndex - startIndex;
3397
- buffer[startIndex++] = size & 0xff;
3398
- buffer[startIndex++] = (size >> 8) & 0xff;
3399
- buffer[startIndex++] = (size >> 16) & 0xff;
3400
- buffer[startIndex++] = (size >> 24) & 0xff;
3475
+ startIndex += NumberUtils.setInt32LE(buffer, index, size);
3401
3476
  return endIndex;
3402
3477
  }
3403
3478
  function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializeFunctions, ignoreUndefined, path) {
@@ -3533,7 +3608,7 @@ function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializ
3533
3608
  if ('$' === key[0]) {
3534
3609
  throw new BSONError('key ' + key + " must not start with '$'");
3535
3610
  }
3536
- else if (~key.indexOf('.')) {
3611
+ else if (key.includes('.')) {
3537
3612
  throw new BSONError('key ' + key + " must not contain '.'");
3538
3613
  }
3539
3614
  }
@@ -3631,7 +3706,7 @@ function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializ
3631
3706
  if ('$' === key[0]) {
3632
3707
  throw new BSONError('key ' + key + " must not start with '$'");
3633
3708
  }
3634
- else if (~key.indexOf('.')) {
3709
+ else if (key.includes('.')) {
3635
3710
  throw new BSONError('key ' + key + " must not contain '.'");
3636
3711
  }
3637
3712
  }
@@ -3715,10 +3790,7 @@ function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializ
3715
3790
  path.delete(object);
3716
3791
  buffer[index++] = 0x00;
3717
3792
  const size = index - startingIndex;
3718
- buffer[startingIndex++] = size & 0xff;
3719
- buffer[startingIndex++] = (size >> 8) & 0xff;
3720
- buffer[startingIndex++] = (size >> 16) & 0xff;
3721
- buffer[startingIndex++] = (size >> 24) & 0xff;
3793
+ startingIndex += NumberUtils.setInt32LE(buffer, startingIndex, size);
3722
3794
  return index;
3723
3795
  }
3724
3796
 
@@ -4048,7 +4120,7 @@ function serialize(object, options = {}) {
4048
4120
  buffer = ByteUtils.allocate(minInternalBufferSize);
4049
4121
  }
4050
4122
  const serializationIndex = serializeInto(buffer, object, checkKeys, 0, 0, serializeFunctions, ignoreUndefined, null);
4051
- const finishedBuffer = ByteUtils.allocate(serializationIndex);
4123
+ const finishedBuffer = ByteUtils.allocateUnsafe(serializationIndex);
4052
4124
  finishedBuffer.set(buffer.subarray(0, serializationIndex), 0);
4053
4125
  return finishedBuffer;
4054
4126
  }
@@ -4075,10 +4147,7 @@ function deserializeStream(data, startIndex, numberOfDocuments, documents, docSt
4075
4147
  const bufferData = ByteUtils.toLocalBufferType(data);
4076
4148
  let index = startIndex;
4077
4149
  for (let i = 0; i < numberOfDocuments; i++) {
4078
- const size = bufferData[index] |
4079
- (bufferData[index + 1] << 8) |
4080
- (bufferData[index + 2] << 16) |
4081
- (bufferData[index + 3] << 24);
4150
+ const size = NumberUtils.getInt32LE(bufferData, index);
4082
4151
  internalOptions.index = index;
4083
4152
  documents[docStartIndex + i] = internalDeserialize(bufferData, internalOptions);
4084
4153
  index = index + size;