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.
@@ -98,8 +98,8 @@ class BSONError extends Error {
98
98
  get name() {
99
99
  return 'BSONError';
100
100
  }
101
- constructor(message) {
102
- super(message);
101
+ constructor(message, options) {
102
+ super(message, options);
103
103
  }
104
104
  static isBSONError(value) {
105
105
  return (value != null &&
@@ -128,6 +128,94 @@ class BSONRuntimeError extends BSONError {
128
128
  }
129
129
  }
130
130
 
131
+ const FIRST_BIT = 0x80;
132
+ const FIRST_TWO_BITS = 0xc0;
133
+ const FIRST_THREE_BITS = 0xe0;
134
+ const FIRST_FOUR_BITS = 0xf0;
135
+ const FIRST_FIVE_BITS = 0xf8;
136
+ const TWO_BIT_CHAR = 0xc0;
137
+ const THREE_BIT_CHAR = 0xe0;
138
+ const FOUR_BIT_CHAR = 0xf0;
139
+ const CONTINUING_CHAR = 0x80;
140
+ function validateUtf8(bytes, start, end) {
141
+ let continuation = 0;
142
+ for (let i = start; i < end; i += 1) {
143
+ const byte = bytes[i];
144
+ if (continuation) {
145
+ if ((byte & FIRST_TWO_BITS) !== CONTINUING_CHAR) {
146
+ return false;
147
+ }
148
+ continuation -= 1;
149
+ }
150
+ else if (byte & FIRST_BIT) {
151
+ if ((byte & FIRST_THREE_BITS) === TWO_BIT_CHAR) {
152
+ continuation = 1;
153
+ }
154
+ else if ((byte & FIRST_FOUR_BITS) === THREE_BIT_CHAR) {
155
+ continuation = 2;
156
+ }
157
+ else if ((byte & FIRST_FIVE_BITS) === FOUR_BIT_CHAR) {
158
+ continuation = 3;
159
+ }
160
+ else {
161
+ return false;
162
+ }
163
+ }
164
+ }
165
+ return !continuation;
166
+ }
167
+
168
+ function tryReadBasicLatin(uint8array, start, end) {
169
+ if (uint8array.length === 0) {
170
+ return '';
171
+ }
172
+ const stringByteLength = end - start;
173
+ if (stringByteLength === 0) {
174
+ return '';
175
+ }
176
+ if (stringByteLength > 20) {
177
+ return null;
178
+ }
179
+ if (stringByteLength === 1 && uint8array[start] < 128) {
180
+ return String.fromCharCode(uint8array[start]);
181
+ }
182
+ if (stringByteLength === 2 && uint8array[start] < 128 && uint8array[start + 1] < 128) {
183
+ return String.fromCharCode(uint8array[start]) + String.fromCharCode(uint8array[start + 1]);
184
+ }
185
+ if (stringByteLength === 3 &&
186
+ uint8array[start] < 128 &&
187
+ uint8array[start + 1] < 128 &&
188
+ uint8array[start + 2] < 128) {
189
+ return (String.fromCharCode(uint8array[start]) +
190
+ String.fromCharCode(uint8array[start + 1]) +
191
+ String.fromCharCode(uint8array[start + 2]));
192
+ }
193
+ const latinBytes = [];
194
+ for (let i = start; i < end; i++) {
195
+ const byte = uint8array[i];
196
+ if (byte > 127) {
197
+ return null;
198
+ }
199
+ latinBytes.push(byte);
200
+ }
201
+ return String.fromCharCode(...latinBytes);
202
+ }
203
+ function tryWriteBasicLatin(destination, source, offset) {
204
+ if (source.length === 0)
205
+ return 0;
206
+ if (source.length > 25)
207
+ return null;
208
+ if (destination.length - offset < source.length)
209
+ return null;
210
+ for (let charOffset = 0, destinationOffset = offset; charOffset < source.length; charOffset++, destinationOffset++) {
211
+ const char = source.charCodeAt(charOffset);
212
+ if (char > 127)
213
+ return null;
214
+ destination[destinationOffset] = char;
215
+ }
216
+ return source.length;
217
+ }
218
+
131
219
  function nodejsMathRandomBytes(byteLength) {
132
220
  return nodeJsByteUtils.fromNumberArray(Array.from({ length: byteLength }, () => Math.floor(Math.random() * 256)));
133
221
  }
@@ -159,6 +247,9 @@ const nodeJsByteUtils = {
159
247
  allocate(size) {
160
248
  return Buffer.alloc(size);
161
249
  },
250
+ allocateUnsafe(size) {
251
+ return Buffer.allocUnsafe(size);
252
+ },
162
253
  equals(a, b) {
163
254
  return nodeJsByteUtils.toLocalBufferType(a).equals(b);
164
255
  },
@@ -183,16 +274,32 @@ const nodeJsByteUtils = {
183
274
  toHex(buffer) {
184
275
  return nodeJsByteUtils.toLocalBufferType(buffer).toString('hex');
185
276
  },
186
- fromUTF8(text) {
187
- return Buffer.from(text, 'utf8');
188
- },
189
- toUTF8(buffer, start, end) {
190
- return nodeJsByteUtils.toLocalBufferType(buffer).toString('utf8', start, end);
277
+ toUTF8(buffer, start, end, fatal) {
278
+ const basicLatin = end - start <= 20 ? tryReadBasicLatin(buffer, start, end) : null;
279
+ if (basicLatin != null) {
280
+ return basicLatin;
281
+ }
282
+ const string = nodeJsByteUtils.toLocalBufferType(buffer).toString('utf8', start, end);
283
+ if (fatal) {
284
+ for (let i = 0; i < string.length; i++) {
285
+ if (string.charCodeAt(i) === 0xfffd) {
286
+ if (!validateUtf8(buffer, start, end)) {
287
+ throw new BSONError('Invalid UTF-8 string in BSON document');
288
+ }
289
+ break;
290
+ }
291
+ }
292
+ }
293
+ return string;
191
294
  },
192
295
  utf8ByteLength(input) {
193
296
  return Buffer.byteLength(input, 'utf8');
194
297
  },
195
298
  encodeUTF8Into(buffer, source, byteOffset) {
299
+ const latinBytesWritten = tryWriteBasicLatin(buffer, source, byteOffset);
300
+ if (latinBytesWritten != null) {
301
+ return latinBytesWritten;
302
+ }
196
303
  return nodeJsByteUtils.toLocalBufferType(buffer).write(source, byteOffset, undefined, 'utf8');
197
304
  },
198
305
  randomBytes: nodejsRandomBytes
@@ -248,6 +355,9 @@ const webByteUtils = {
248
355
  }
249
356
  return new Uint8Array(size);
250
357
  },
358
+ allocateUnsafe(size) {
359
+ return webByteUtils.allocate(size);
360
+ },
251
361
  equals(a, b) {
252
362
  if (a.byteLength !== b.byteLength) {
253
363
  return false;
@@ -294,18 +404,27 @@ const webByteUtils = {
294
404
  toHex(uint8array) {
295
405
  return Array.from(uint8array, byte => byte.toString(16).padStart(2, '0')).join('');
296
406
  },
297
- fromUTF8(text) {
298
- return new TextEncoder().encode(text);
299
- },
300
- toUTF8(uint8array, start, end) {
301
- return new TextDecoder('utf8', { fatal: false }).decode(uint8array.slice(start, end));
407
+ toUTF8(uint8array, start, end, fatal) {
408
+ const basicLatin = end - start <= 20 ? tryReadBasicLatin(uint8array, start, end) : null;
409
+ if (basicLatin != null) {
410
+ return basicLatin;
411
+ }
412
+ if (fatal) {
413
+ try {
414
+ return new TextDecoder('utf8', { fatal }).decode(uint8array.slice(start, end));
415
+ }
416
+ catch (cause) {
417
+ throw new BSONError('Invalid UTF-8 string in BSON document', { cause });
418
+ }
419
+ }
420
+ return new TextDecoder('utf8', { fatal }).decode(uint8array.slice(start, end));
302
421
  },
303
422
  utf8ByteLength(input) {
304
- return webByteUtils.fromUTF8(input).byteLength;
423
+ return new TextEncoder().encode(input).byteLength;
305
424
  },
306
- encodeUTF8Into(buffer, source, byteOffset) {
307
- const bytes = webByteUtils.fromUTF8(source);
308
- buffer.set(bytes, byteOffset);
425
+ encodeUTF8Into(uint8array, source, byteOffset) {
426
+ const bytes = new TextEncoder().encode(source);
427
+ uint8array.set(bytes, byteOffset);
309
428
  return bytes.byteLength;
310
429
  },
311
430
  randomBytes: webRandomBytes
@@ -313,11 +432,6 @@ const webByteUtils = {
313
432
 
314
433
  const hasGlobalBuffer = typeof Buffer === 'function' && Buffer.prototype?._isBuffer !== true;
315
434
  const ByteUtils = hasGlobalBuffer ? nodeJsByteUtils : webByteUtils;
316
- class BSONDataView extends DataView {
317
- static fromUint8Array(input) {
318
- return new DataView(input.buffer, input.byteOffset, input.byteLength);
319
- }
320
- }
321
435
 
322
436
  class BSONValue {
323
437
  get [Symbol.for('@@mdb.bson.version')]() {
@@ -419,8 +533,8 @@ class Binary extends BSONValue {
419
533
  if (encoding === 'base64')
420
534
  return ByteUtils.toBase64(this.buffer);
421
535
  if (encoding === 'utf8' || encoding === 'utf-8')
422
- return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength);
423
- return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength);
536
+ return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength, false);
537
+ return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength, false);
424
538
  }
425
539
  toExtendedJSON(options) {
426
540
  options = options || {};
@@ -1737,7 +1851,7 @@ class Decimal128 extends BSONValue {
1737
1851
  if (isNegative) {
1738
1852
  dec.high = dec.high.or(Long.fromString('9223372036854775808'));
1739
1853
  }
1740
- const buffer = ByteUtils.allocate(16);
1854
+ const buffer = ByteUtils.allocateUnsafe(16);
1741
1855
  index = 0;
1742
1856
  buffer[index++] = dec.low.low & 0xff;
1743
1857
  buffer[index++] = (dec.low.low >> 8) & 0xff;
@@ -2010,9 +2124,99 @@ class MinKey extends BSONValue {
2010
2124
  }
2011
2125
  }
2012
2126
 
2127
+ const FLOAT = new Float64Array(1);
2128
+ const FLOAT_BYTES = new Uint8Array(FLOAT.buffer, 0, 8);
2129
+ const NumberUtils = {
2130
+ getInt32LE(source, offset) {
2131
+ return (source[offset] |
2132
+ (source[offset + 1] << 8) |
2133
+ (source[offset + 2] << 16) |
2134
+ (source[offset + 3] << 24));
2135
+ },
2136
+ getUint32LE(source, offset) {
2137
+ return (source[offset] +
2138
+ source[offset + 1] * 256 +
2139
+ source[offset + 2] * 65536 +
2140
+ source[offset + 3] * 16777216);
2141
+ },
2142
+ getUint32BE(source, offset) {
2143
+ return (source[offset + 3] +
2144
+ source[offset + 2] * 256 +
2145
+ source[offset + 1] * 65536 +
2146
+ source[offset] * 16777216);
2147
+ },
2148
+ getBigInt64LE(source, offset) {
2149
+ const lo = NumberUtils.getUint32LE(source, offset);
2150
+ const hi = NumberUtils.getUint32LE(source, offset + 4);
2151
+ return (BigInt(hi) << BigInt(32)) + BigInt(lo);
2152
+ },
2153
+ getFloat64LE(source, offset) {
2154
+ FLOAT_BYTES[0] = source[offset];
2155
+ FLOAT_BYTES[1] = source[offset + 1];
2156
+ FLOAT_BYTES[2] = source[offset + 2];
2157
+ FLOAT_BYTES[3] = source[offset + 3];
2158
+ FLOAT_BYTES[4] = source[offset + 4];
2159
+ FLOAT_BYTES[5] = source[offset + 5];
2160
+ FLOAT_BYTES[6] = source[offset + 6];
2161
+ FLOAT_BYTES[7] = source[offset + 7];
2162
+ return FLOAT[0];
2163
+ },
2164
+ setInt32BE(destination, offset, value) {
2165
+ destination[offset + 3] = value;
2166
+ value >>>= 8;
2167
+ destination[offset + 2] = value;
2168
+ value >>>= 8;
2169
+ destination[offset + 1] = value;
2170
+ value >>>= 8;
2171
+ destination[offset] = value;
2172
+ return 4;
2173
+ },
2174
+ setInt32LE(destination, offset, value) {
2175
+ destination[offset] = value;
2176
+ value >>>= 8;
2177
+ destination[offset + 1] = value;
2178
+ value >>>= 8;
2179
+ destination[offset + 2] = value;
2180
+ value >>>= 8;
2181
+ destination[offset + 3] = value;
2182
+ return 4;
2183
+ },
2184
+ setBigInt64LE(destination, offset, value) {
2185
+ const mask32bits = BigInt(4294967295);
2186
+ let lo = Number(value & mask32bits);
2187
+ destination[offset] = lo;
2188
+ lo >>= 8;
2189
+ destination[offset + 1] = lo;
2190
+ lo >>= 8;
2191
+ destination[offset + 2] = lo;
2192
+ lo >>= 8;
2193
+ destination[offset + 3] = lo;
2194
+ let hi = Number((value >> BigInt(32)) & mask32bits);
2195
+ destination[offset + 4] = hi;
2196
+ hi >>= 8;
2197
+ destination[offset + 5] = hi;
2198
+ hi >>= 8;
2199
+ destination[offset + 6] = hi;
2200
+ hi >>= 8;
2201
+ destination[offset + 7] = hi;
2202
+ return 8;
2203
+ },
2204
+ setFloat64LE(destination, offset, value) {
2205
+ FLOAT[0] = value;
2206
+ destination[offset] = FLOAT_BYTES[0];
2207
+ destination[offset + 1] = FLOAT_BYTES[1];
2208
+ destination[offset + 2] = FLOAT_BYTES[2];
2209
+ destination[offset + 3] = FLOAT_BYTES[3];
2210
+ destination[offset + 4] = FLOAT_BYTES[4];
2211
+ destination[offset + 5] = FLOAT_BYTES[5];
2212
+ destination[offset + 6] = FLOAT_BYTES[6];
2213
+ destination[offset + 7] = FLOAT_BYTES[7];
2214
+ return 8;
2215
+ }
2216
+ };
2217
+
2013
2218
  const checkForHexRegExp = new RegExp('^[0-9a-fA-F]{24}$');
2014
2219
  let PROCESS_UNIQUE = null;
2015
- const kId = Symbol('id');
2016
2220
  class ObjectId extends BSONValue {
2017
2221
  get _bsontype() {
2018
2222
  return 'ObjectId';
@@ -2035,14 +2239,14 @@ class ObjectId extends BSONValue {
2035
2239
  workingId = inputId;
2036
2240
  }
2037
2241
  if (workingId == null || typeof workingId === 'number') {
2038
- this[kId] = ObjectId.generate(typeof workingId === 'number' ? workingId : undefined);
2242
+ this.buffer = ObjectId.generate(typeof workingId === 'number' ? workingId : undefined);
2039
2243
  }
2040
2244
  else if (ArrayBuffer.isView(workingId) && workingId.byteLength === 12) {
2041
- this[kId] = ByteUtils.toLocalBufferType(workingId);
2245
+ this.buffer = ByteUtils.toLocalBufferType(workingId);
2042
2246
  }
2043
2247
  else if (typeof workingId === 'string') {
2044
2248
  if (workingId.length === 24 && checkForHexRegExp.test(workingId)) {
2045
- this[kId] = ByteUtils.fromHex(workingId);
2249
+ this.buffer = ByteUtils.fromHex(workingId);
2046
2250
  }
2047
2251
  else {
2048
2252
  throw new BSONError('input must be a 24 character hex string, 12 byte Uint8Array, or an integer');
@@ -2056,10 +2260,10 @@ class ObjectId extends BSONValue {
2056
2260
  }
2057
2261
  }
2058
2262
  get id() {
2059
- return this[kId];
2263
+ return this.buffer;
2060
2264
  }
2061
2265
  set id(value) {
2062
- this[kId] = value;
2266
+ this.buffer = value;
2063
2267
  if (ObjectId.cacheHexString) {
2064
2268
  this.__id = ByteUtils.toHex(value);
2065
2269
  }
@@ -2082,8 +2286,8 @@ class ObjectId extends BSONValue {
2082
2286
  time = Math.floor(Date.now() / 1000);
2083
2287
  }
2084
2288
  const inc = ObjectId.getInc();
2085
- const buffer = ByteUtils.allocate(12);
2086
- BSONDataView.fromUint8Array(buffer).setUint32(0, time, false);
2289
+ const buffer = ByteUtils.allocateUnsafe(12);
2290
+ NumberUtils.setInt32BE(buffer, 0, time);
2087
2291
  if (PROCESS_UNIQUE === null) {
2088
2292
  PROCESS_UNIQUE = ByteUtils.randomBytes(5);
2089
2293
  }
@@ -2118,7 +2322,7 @@ class ObjectId extends BSONValue {
2118
2322
  return false;
2119
2323
  }
2120
2324
  if (ObjectId.is(otherId)) {
2121
- return this[kId][11] === otherId[kId][11] && ByteUtils.equals(this[kId], otherId[kId]);
2325
+ return (this.buffer[11] === otherId.buffer[11] && ByteUtils.equals(this.buffer, otherId.buffer));
2122
2326
  }
2123
2327
  if (typeof otherId === 'string') {
2124
2328
  return otherId.toLowerCase() === this.toHexString();
@@ -2132,16 +2336,33 @@ class ObjectId extends BSONValue {
2132
2336
  }
2133
2337
  getTimestamp() {
2134
2338
  const timestamp = new Date();
2135
- const time = BSONDataView.fromUint8Array(this.id).getUint32(0, false);
2339
+ const time = NumberUtils.getUint32BE(this.buffer, 0);
2136
2340
  timestamp.setTime(Math.floor(time) * 1000);
2137
2341
  return timestamp;
2138
2342
  }
2139
2343
  static createPk() {
2140
2344
  return new ObjectId();
2141
2345
  }
2346
+ serializeInto(uint8array, index) {
2347
+ uint8array[index] = this.buffer[0];
2348
+ uint8array[index + 1] = this.buffer[1];
2349
+ uint8array[index + 2] = this.buffer[2];
2350
+ uint8array[index + 3] = this.buffer[3];
2351
+ uint8array[index + 4] = this.buffer[4];
2352
+ uint8array[index + 5] = this.buffer[5];
2353
+ uint8array[index + 6] = this.buffer[6];
2354
+ uint8array[index + 7] = this.buffer[7];
2355
+ uint8array[index + 8] = this.buffer[8];
2356
+ uint8array[index + 9] = this.buffer[9];
2357
+ uint8array[index + 10] = this.buffer[10];
2358
+ uint8array[index + 11] = this.buffer[11];
2359
+ return 12;
2360
+ }
2142
2361
  static createFromTime(time) {
2143
- const buffer = ByteUtils.fromNumberArray([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
2144
- BSONDataView.fromUint8Array(buffer).setUint32(0, time, false);
2362
+ const buffer = ByteUtils.allocate(12);
2363
+ for (let i = 11; i >= 4; i--)
2364
+ buffer[i] = 0;
2365
+ NumberUtils.setInt32BE(buffer, 0, time);
2145
2366
  return new ObjectId(buffer);
2146
2367
  }
2147
2368
  static createFromHexString(hexString) {
@@ -2508,52 +2729,12 @@ class Timestamp extends LongWithoutOverridesClass {
2508
2729
  }
2509
2730
  Timestamp.MAX_VALUE = Long.MAX_UNSIGNED_VALUE;
2510
2731
 
2511
- const FIRST_BIT = 0x80;
2512
- const FIRST_TWO_BITS = 0xc0;
2513
- const FIRST_THREE_BITS = 0xe0;
2514
- const FIRST_FOUR_BITS = 0xf0;
2515
- const FIRST_FIVE_BITS = 0xf8;
2516
- const TWO_BIT_CHAR = 0xc0;
2517
- const THREE_BIT_CHAR = 0xe0;
2518
- const FOUR_BIT_CHAR = 0xf0;
2519
- const CONTINUING_CHAR = 0x80;
2520
- function validateUtf8(bytes, start, end) {
2521
- let continuation = 0;
2522
- for (let i = start; i < end; i += 1) {
2523
- const byte = bytes[i];
2524
- if (continuation) {
2525
- if ((byte & FIRST_TWO_BITS) !== CONTINUING_CHAR) {
2526
- return false;
2527
- }
2528
- continuation -= 1;
2529
- }
2530
- else if (byte & FIRST_BIT) {
2531
- if ((byte & FIRST_THREE_BITS) === TWO_BIT_CHAR) {
2532
- continuation = 1;
2533
- }
2534
- else if ((byte & FIRST_FOUR_BITS) === THREE_BIT_CHAR) {
2535
- continuation = 2;
2536
- }
2537
- else if ((byte & FIRST_FIVE_BITS) === FOUR_BIT_CHAR) {
2538
- continuation = 3;
2539
- }
2540
- else {
2541
- return false;
2542
- }
2543
- }
2544
- }
2545
- return !continuation;
2546
- }
2547
-
2548
2732
  const JS_INT_MAX_LONG = Long.fromNumber(JS_INT_MAX);
2549
2733
  const JS_INT_MIN_LONG = Long.fromNumber(JS_INT_MIN);
2550
2734
  function internalDeserialize(buffer, options, isArray) {
2551
2735
  options = options == null ? {} : options;
2552
2736
  const index = options && options.index ? options.index : 0;
2553
- const size = buffer[index] |
2554
- (buffer[index + 1] << 8) |
2555
- (buffer[index + 2] << 16) |
2556
- (buffer[index + 3] << 24);
2737
+ const size = NumberUtils.getInt32LE(buffer, index);
2557
2738
  if (size < 5) {
2558
2739
  throw new BSONError(`bson size must be >= 5, is ${size}`);
2559
2740
  }
@@ -2589,7 +2770,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2589
2770
  const validation = options.validation == null ? { utf8: true } : options.validation;
2590
2771
  let globalUTFValidation = true;
2591
2772
  let validationSetting;
2592
- const utf8KeysSet = new Set();
2773
+ let utf8KeysSet;
2593
2774
  const utf8ValidatedKeys = validation.utf8;
2594
2775
  if (typeof utf8ValidatedKeys === 'boolean') {
2595
2776
  validationSetting = utf8ValidatedKeys;
@@ -2611,6 +2792,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2611
2792
  }
2612
2793
  }
2613
2794
  if (!globalUTFValidation) {
2795
+ utf8KeysSet = new Set();
2614
2796
  for (const key of Object.keys(utf8ValidatedKeys)) {
2615
2797
  utf8KeysSet.add(key);
2616
2798
  }
@@ -2618,14 +2800,14 @@ function deserializeObject(buffer, index, options, isArray = false) {
2618
2800
  const startIndex = index;
2619
2801
  if (buffer.length < 5)
2620
2802
  throw new BSONError('corrupt bson message < 5 bytes long');
2621
- const size = buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24);
2803
+ const size = NumberUtils.getInt32LE(buffer, index);
2804
+ index += 4;
2622
2805
  if (size < 5 || size > buffer.length)
2623
2806
  throw new BSONError('corrupt bson message');
2624
2807
  const object = isArray ? [] : {};
2625
2808
  let arrayIndex = 0;
2626
2809
  const done = false;
2627
2810
  let isPossibleDBRef = isArray ? false : null;
2628
- const dataview = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
2629
2811
  while (!done) {
2630
2812
  const elementType = buffer[index++];
2631
2813
  if (elementType === 0)
@@ -2636,9 +2818,9 @@ function deserializeObject(buffer, index, options, isArray = false) {
2636
2818
  }
2637
2819
  if (i >= buffer.byteLength)
2638
2820
  throw new BSONError('Bad BSON Document: illegal CString');
2639
- const name = isArray ? arrayIndex++ : ByteUtils.toUTF8(buffer, index, i);
2821
+ const name = isArray ? arrayIndex++ : ByteUtils.toUTF8(buffer, index, i, false);
2640
2822
  let shouldValidateKey = true;
2641
- if (globalUTFValidation || utf8KeysSet.has(name)) {
2823
+ if (globalUTFValidation || utf8KeysSet?.has(name)) {
2642
2824
  shouldValidateKey = validationSetting;
2643
2825
  }
2644
2826
  else {
@@ -2650,51 +2832,41 @@ function deserializeObject(buffer, index, options, isArray = false) {
2650
2832
  let value;
2651
2833
  index = i + 1;
2652
2834
  if (elementType === BSON_DATA_STRING) {
2653
- const stringSize = buffer[index++] |
2654
- (buffer[index++] << 8) |
2655
- (buffer[index++] << 16) |
2656
- (buffer[index++] << 24);
2835
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
2836
+ index += 4;
2657
2837
  if (stringSize <= 0 ||
2658
2838
  stringSize > buffer.length - index ||
2659
2839
  buffer[index + stringSize - 1] !== 0) {
2660
2840
  throw new BSONError('bad string length in bson');
2661
2841
  }
2662
- value = getValidatedString(buffer, index, index + stringSize - 1, shouldValidateKey);
2842
+ value = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
2663
2843
  index = index + stringSize;
2664
2844
  }
2665
2845
  else if (elementType === BSON_DATA_OID) {
2666
- const oid = ByteUtils.allocate(12);
2667
- oid.set(buffer.subarray(index, index + 12));
2846
+ const oid = ByteUtils.allocateUnsafe(12);
2847
+ for (let i = 0; i < 12; i++)
2848
+ oid[i] = buffer[index + i];
2668
2849
  value = new ObjectId(oid);
2669
2850
  index = index + 12;
2670
2851
  }
2671
2852
  else if (elementType === BSON_DATA_INT && promoteValues === false) {
2672
- value = new Int32(buffer[index++] | (buffer[index++] << 8) | (buffer[index++] << 16) | (buffer[index++] << 24));
2853
+ value = new Int32(NumberUtils.getInt32LE(buffer, index));
2854
+ index += 4;
2673
2855
  }
2674
2856
  else if (elementType === BSON_DATA_INT) {
2675
- value =
2676
- buffer[index++] |
2677
- (buffer[index++] << 8) |
2678
- (buffer[index++] << 16) |
2679
- (buffer[index++] << 24);
2680
- }
2681
- else if (elementType === BSON_DATA_NUMBER && promoteValues === false) {
2682
- value = new Double(dataview.getFloat64(index, true));
2683
- index = index + 8;
2857
+ value = NumberUtils.getInt32LE(buffer, index);
2858
+ index += 4;
2684
2859
  }
2685
2860
  else if (elementType === BSON_DATA_NUMBER) {
2686
- value = dataview.getFloat64(index, true);
2687
- index = index + 8;
2861
+ value = NumberUtils.getFloat64LE(buffer, index);
2862
+ index += 8;
2863
+ if (promoteValues === false)
2864
+ value = new Double(value);
2688
2865
  }
2689
2866
  else if (elementType === BSON_DATA_DATE) {
2690
- const lowBits = buffer[index++] |
2691
- (buffer[index++] << 8) |
2692
- (buffer[index++] << 16) |
2693
- (buffer[index++] << 24);
2694
- const highBits = buffer[index++] |
2695
- (buffer[index++] << 8) |
2696
- (buffer[index++] << 16) |
2697
- (buffer[index++] << 24);
2867
+ const lowBits = NumberUtils.getInt32LE(buffer, index);
2868
+ const highBits = NumberUtils.getInt32LE(buffer, index + 4);
2869
+ index += 8;
2698
2870
  value = new Date(new Long(lowBits, highBits).toNumber());
2699
2871
  }
2700
2872
  else if (elementType === BSON_DATA_BOOLEAN) {
@@ -2704,10 +2876,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2704
2876
  }
2705
2877
  else if (elementType === BSON_DATA_OBJECT) {
2706
2878
  const _index = index;
2707
- const objectSize = buffer[index] |
2708
- (buffer[index + 1] << 8) |
2709
- (buffer[index + 2] << 16) |
2710
- (buffer[index + 3] << 24);
2879
+ const objectSize = NumberUtils.getInt32LE(buffer, index);
2711
2880
  if (objectSize <= 0 || objectSize > buffer.length - index)
2712
2881
  throw new BSONError('bad embedded document length in bson');
2713
2882
  if (raw) {
@@ -2724,10 +2893,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2724
2893
  }
2725
2894
  else if (elementType === BSON_DATA_ARRAY) {
2726
2895
  const _index = index;
2727
- const objectSize = buffer[index] |
2728
- (buffer[index + 1] << 8) |
2729
- (buffer[index + 2] << 16) |
2730
- (buffer[index + 3] << 24);
2896
+ const objectSize = NumberUtils.getInt32LE(buffer, index);
2731
2897
  let arrayOptions = options;
2732
2898
  const stopIndex = index + objectSize;
2733
2899
  if (fieldsAsRaw && fieldsAsRaw[name]) {
@@ -2750,40 +2916,36 @@ function deserializeObject(buffer, index, options, isArray = false) {
2750
2916
  value = null;
2751
2917
  }
2752
2918
  else if (elementType === BSON_DATA_LONG) {
2753
- const dataview = BSONDataView.fromUint8Array(buffer.subarray(index, index + 8));
2754
- const lowBits = buffer[index++] |
2755
- (buffer[index++] << 8) |
2756
- (buffer[index++] << 16) |
2757
- (buffer[index++] << 24);
2758
- const highBits = buffer[index++] |
2759
- (buffer[index++] << 8) |
2760
- (buffer[index++] << 16) |
2761
- (buffer[index++] << 24);
2762
- const long = new Long(lowBits, highBits);
2763
2919
  if (useBigInt64) {
2764
- value = dataview.getBigInt64(0, true);
2765
- }
2766
- else if (promoteLongs && promoteValues === true) {
2767
- value =
2768
- long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG)
2769
- ? long.toNumber()
2770
- : long;
2920
+ value = NumberUtils.getBigInt64LE(buffer, index);
2921
+ index += 8;
2771
2922
  }
2772
2923
  else {
2773
- value = long;
2924
+ const lowBits = NumberUtils.getInt32LE(buffer, index);
2925
+ const highBits = NumberUtils.getInt32LE(buffer, index + 4);
2926
+ index += 8;
2927
+ const long = new Long(lowBits, highBits);
2928
+ if (promoteLongs && promoteValues === true) {
2929
+ value =
2930
+ long.lessThanOrEqual(JS_INT_MAX_LONG) && long.greaterThanOrEqual(JS_INT_MIN_LONG)
2931
+ ? long.toNumber()
2932
+ : long;
2933
+ }
2934
+ else {
2935
+ value = long;
2936
+ }
2774
2937
  }
2775
2938
  }
2776
2939
  else if (elementType === BSON_DATA_DECIMAL128) {
2777
- const bytes = ByteUtils.allocate(16);
2778
- bytes.set(buffer.subarray(index, index + 16), 0);
2940
+ const bytes = ByteUtils.allocateUnsafe(16);
2941
+ for (let i = 0; i < 16; i++)
2942
+ bytes[i] = buffer[index + i];
2779
2943
  index = index + 16;
2780
2944
  value = new Decimal128(bytes);
2781
2945
  }
2782
2946
  else if (elementType === BSON_DATA_BINARY) {
2783
- let binarySize = buffer[index++] |
2784
- (buffer[index++] << 8) |
2785
- (buffer[index++] << 16) |
2786
- (buffer[index++] << 24);
2947
+ let binarySize = NumberUtils.getInt32LE(buffer, index);
2948
+ index += 4;
2787
2949
  const totalBinarySize = binarySize;
2788
2950
  const subType = buffer[index++];
2789
2951
  if (binarySize < 0)
@@ -2792,11 +2954,8 @@ function deserializeObject(buffer, index, options, isArray = false) {
2792
2954
  throw new BSONError('Binary type size larger than document size');
2793
2955
  if (buffer['slice'] != null) {
2794
2956
  if (subType === Binary.SUBTYPE_BYTE_ARRAY) {
2795
- binarySize =
2796
- buffer[index++] |
2797
- (buffer[index++] << 8) |
2798
- (buffer[index++] << 16) |
2799
- (buffer[index++] << 24);
2957
+ binarySize = NumberUtils.getInt32LE(buffer, index);
2958
+ index += 4;
2800
2959
  if (binarySize < 0)
2801
2960
  throw new BSONError('Negative binary type element size found for subtype 0x02');
2802
2961
  if (binarySize > totalBinarySize - 4)
@@ -2815,13 +2974,9 @@ function deserializeObject(buffer, index, options, isArray = false) {
2815
2974
  }
2816
2975
  }
2817
2976
  else {
2818
- const _buffer = ByteUtils.allocate(binarySize);
2819
2977
  if (subType === Binary.SUBTYPE_BYTE_ARRAY) {
2820
- binarySize =
2821
- buffer[index++] |
2822
- (buffer[index++] << 8) |
2823
- (buffer[index++] << 16) |
2824
- (buffer[index++] << 24);
2978
+ binarySize = NumberUtils.getInt32LE(buffer, index);
2979
+ index += 4;
2825
2980
  if (binarySize < 0)
2826
2981
  throw new BSONError('Negative binary type element size found for subtype 0x02');
2827
2982
  if (binarySize > totalBinarySize - 4)
@@ -2829,11 +2984,11 @@ function deserializeObject(buffer, index, options, isArray = false) {
2829
2984
  if (binarySize < totalBinarySize - 4)
2830
2985
  throw new BSONError('Binary type with subtype 0x02 contains too short binary size');
2831
2986
  }
2832
- for (i = 0; i < binarySize; i++) {
2833
- _buffer[i] = buffer[index + i];
2834
- }
2835
2987
  if (promoteBuffers && promoteValues) {
2836
- value = _buffer;
2988
+ value = ByteUtils.allocateUnsafe(binarySize);
2989
+ for (i = 0; i < binarySize; i++) {
2990
+ value[i] = buffer[index + i];
2991
+ }
2837
2992
  }
2838
2993
  else {
2839
2994
  value = new Binary(buffer.slice(index, index + binarySize), subType);
@@ -2851,7 +3006,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2851
3006
  }
2852
3007
  if (i >= buffer.length)
2853
3008
  throw new BSONError('Bad BSON Document: illegal CString');
2854
- const source = ByteUtils.toUTF8(buffer, index, i);
3009
+ const source = ByteUtils.toUTF8(buffer, index, i, false);
2855
3010
  index = i + 1;
2856
3011
  i = index;
2857
3012
  while (buffer[i] !== 0x00 && i < buffer.length) {
@@ -2859,7 +3014,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2859
3014
  }
2860
3015
  if (i >= buffer.length)
2861
3016
  throw new BSONError('Bad BSON Document: illegal CString');
2862
- const regExpOptions = ByteUtils.toUTF8(buffer, index, i);
3017
+ const regExpOptions = ByteUtils.toUTF8(buffer, index, i, false);
2863
3018
  index = i + 1;
2864
3019
  const optionsArray = new Array(regExpOptions.length);
2865
3020
  for (i = 0; i < regExpOptions.length; i++) {
@@ -2884,7 +3039,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
2884
3039
  }
2885
3040
  if (i >= buffer.length)
2886
3041
  throw new BSONError('Bad BSON Document: illegal CString');
2887
- const source = ByteUtils.toUTF8(buffer, index, i);
3042
+ const source = ByteUtils.toUTF8(buffer, index, i, false);
2888
3043
  index = i + 1;
2889
3044
  i = index;
2890
3045
  while (buffer[i] !== 0x00 && i < buffer.length) {
@@ -2892,34 +3047,28 @@ function deserializeObject(buffer, index, options, isArray = false) {
2892
3047
  }
2893
3048
  if (i >= buffer.length)
2894
3049
  throw new BSONError('Bad BSON Document: illegal CString');
2895
- const regExpOptions = ByteUtils.toUTF8(buffer, index, i);
3050
+ const regExpOptions = ByteUtils.toUTF8(buffer, index, i, false);
2896
3051
  index = i + 1;
2897
3052
  value = new BSONRegExp(source, regExpOptions);
2898
3053
  }
2899
3054
  else if (elementType === BSON_DATA_SYMBOL) {
2900
- const stringSize = buffer[index++] |
2901
- (buffer[index++] << 8) |
2902
- (buffer[index++] << 16) |
2903
- (buffer[index++] << 24);
3055
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
3056
+ index += 4;
2904
3057
  if (stringSize <= 0 ||
2905
3058
  stringSize > buffer.length - index ||
2906
3059
  buffer[index + stringSize - 1] !== 0) {
2907
3060
  throw new BSONError('bad string length in bson');
2908
3061
  }
2909
- const symbol = getValidatedString(buffer, index, index + stringSize - 1, shouldValidateKey);
3062
+ const symbol = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
2910
3063
  value = promoteValues ? symbol : new BSONSymbol(symbol);
2911
3064
  index = index + stringSize;
2912
3065
  }
2913
3066
  else if (elementType === BSON_DATA_TIMESTAMP) {
2914
- const i = buffer[index++] +
2915
- buffer[index++] * (1 << 8) +
2916
- buffer[index++] * (1 << 16) +
2917
- buffer[index++] * (1 << 24);
2918
- const t = buffer[index++] +
2919
- buffer[index++] * (1 << 8) +
2920
- buffer[index++] * (1 << 16) +
2921
- buffer[index++] * (1 << 24);
2922
- value = new Timestamp({ i, t });
3067
+ value = new Timestamp({
3068
+ i: NumberUtils.getUint32LE(buffer, index),
3069
+ t: NumberUtils.getUint32LE(buffer, index + 4)
3070
+ });
3071
+ index += 8;
2923
3072
  }
2924
3073
  else if (elementType === BSON_DATA_MIN_KEY) {
2925
3074
  value = new MinKey();
@@ -2928,43 +3077,34 @@ function deserializeObject(buffer, index, options, isArray = false) {
2928
3077
  value = new MaxKey();
2929
3078
  }
2930
3079
  else if (elementType === BSON_DATA_CODE) {
2931
- const stringSize = buffer[index++] |
2932
- (buffer[index++] << 8) |
2933
- (buffer[index++] << 16) |
2934
- (buffer[index++] << 24);
3080
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
3081
+ index += 4;
2935
3082
  if (stringSize <= 0 ||
2936
3083
  stringSize > buffer.length - index ||
2937
3084
  buffer[index + stringSize - 1] !== 0) {
2938
3085
  throw new BSONError('bad string length in bson');
2939
3086
  }
2940
- const functionString = getValidatedString(buffer, index, index + stringSize - 1, shouldValidateKey);
3087
+ const functionString = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
2941
3088
  value = new Code(functionString);
2942
3089
  index = index + stringSize;
2943
3090
  }
2944
3091
  else if (elementType === BSON_DATA_CODE_W_SCOPE) {
2945
- const totalSize = buffer[index++] |
2946
- (buffer[index++] << 8) |
2947
- (buffer[index++] << 16) |
2948
- (buffer[index++] << 24);
3092
+ const totalSize = NumberUtils.getInt32LE(buffer, index);
3093
+ index += 4;
2949
3094
  if (totalSize < 4 + 4 + 4 + 1) {
2950
3095
  throw new BSONError('code_w_scope total size shorter minimum expected length');
2951
3096
  }
2952
- const stringSize = buffer[index++] |
2953
- (buffer[index++] << 8) |
2954
- (buffer[index++] << 16) |
2955
- (buffer[index++] << 24);
3097
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
3098
+ index += 4;
2956
3099
  if (stringSize <= 0 ||
2957
3100
  stringSize > buffer.length - index ||
2958
3101
  buffer[index + stringSize - 1] !== 0) {
2959
3102
  throw new BSONError('bad string length in bson');
2960
3103
  }
2961
- const functionString = getValidatedString(buffer, index, index + stringSize - 1, shouldValidateKey);
3104
+ const functionString = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
2962
3105
  index = index + stringSize;
2963
3106
  const _index = index;
2964
- const objectSize = buffer[index] |
2965
- (buffer[index + 1] << 8) |
2966
- (buffer[index + 2] << 16) |
2967
- (buffer[index + 3] << 24);
3107
+ const objectSize = NumberUtils.getInt32LE(buffer, index);
2968
3108
  const scopeObject = deserializeObject(buffer, _index, options, false);
2969
3109
  index = index + objectSize;
2970
3110
  if (totalSize < 4 + 4 + objectSize + stringSize) {
@@ -2976,10 +3116,8 @@ function deserializeObject(buffer, index, options, isArray = false) {
2976
3116
  value = new Code(functionString, scopeObject);
2977
3117
  }
2978
3118
  else if (elementType === BSON_DATA_DBPOINTER) {
2979
- const stringSize = buffer[index++] |
2980
- (buffer[index++] << 8) |
2981
- (buffer[index++] << 16) |
2982
- (buffer[index++] << 24);
3119
+ const stringSize = NumberUtils.getInt32LE(buffer, index);
3120
+ index += 4;
2983
3121
  if (stringSize <= 0 ||
2984
3122
  stringSize > buffer.length - index ||
2985
3123
  buffer[index + stringSize - 1] !== 0)
@@ -2989,10 +3127,11 @@ function deserializeObject(buffer, index, options, isArray = false) {
2989
3127
  throw new BSONError('Invalid UTF-8 string in BSON document');
2990
3128
  }
2991
3129
  }
2992
- const namespace = ByteUtils.toUTF8(buffer, index, index + stringSize - 1);
3130
+ const namespace = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, false);
2993
3131
  index = index + stringSize;
2994
- const oidBuffer = ByteUtils.allocate(12);
2995
- oidBuffer.set(buffer.subarray(index, index + 12), 0);
3132
+ const oidBuffer = ByteUtils.allocateUnsafe(12);
3133
+ for (let i = 0; i < 12; i++)
3134
+ oidBuffer[i] = buffer[index + i];
2996
3135
  const oid = new ObjectId(oidBuffer);
2997
3136
  index = index + 12;
2998
3137
  value = new DBRef(namespace, oid);
@@ -3028,20 +3167,6 @@ function deserializeObject(buffer, index, options, isArray = false) {
3028
3167
  }
3029
3168
  return object;
3030
3169
  }
3031
- function getValidatedString(buffer, start, end, shouldValidateUtf8) {
3032
- const value = ByteUtils.toUTF8(buffer, start, end);
3033
- if (shouldValidateUtf8) {
3034
- for (let i = 0; i < value.length; i++) {
3035
- if (value.charCodeAt(i) === 0xfffd) {
3036
- if (!validateUtf8(buffer, start, end)) {
3037
- throw new BSONError('Invalid UTF-8 string in BSON document');
3038
- }
3039
- break;
3040
- }
3041
- }
3042
- }
3043
- return value;
3044
- }
3045
3170
 
3046
3171
  const regexp = /\x00/;
3047
3172
  const ignoreKeys = new Set(['$db', '$ref', '$id', '$clusterTime']);
@@ -3051,17 +3176,11 @@ function serializeString(buffer, key, value, index) {
3051
3176
  index = index + numberOfWrittenBytes + 1;
3052
3177
  buffer[index - 1] = 0;
3053
3178
  const size = ByteUtils.encodeUTF8Into(buffer, value, index + 4);
3054
- buffer[index + 3] = ((size + 1) >> 24) & 0xff;
3055
- buffer[index + 2] = ((size + 1) >> 16) & 0xff;
3056
- buffer[index + 1] = ((size + 1) >> 8) & 0xff;
3057
- buffer[index] = (size + 1) & 0xff;
3179
+ NumberUtils.setInt32LE(buffer, index, size + 1);
3058
3180
  index = index + 4 + size;
3059
3181
  buffer[index++] = 0;
3060
3182
  return index;
3061
3183
  }
3062
- const NUMBER_SPACE = new DataView(new ArrayBuffer(8), 0, 8);
3063
- const FOUR_BYTE_VIEW_ON_NUMBER = new Uint8Array(NUMBER_SPACE.buffer, 0, 4);
3064
- const EIGHT_BYTE_VIEW_ON_NUMBER = new Uint8Array(NUMBER_SPACE.buffer, 0, 8);
3065
3184
  function serializeNumber(buffer, key, value, index) {
3066
3185
  const isNegativeZero = Object.is(value, -0);
3067
3186
  const type = !isNegativeZero &&
@@ -3070,19 +3189,16 @@ function serializeNumber(buffer, key, value, index) {
3070
3189
  value >= BSON_INT32_MIN
3071
3190
  ? BSON_DATA_INT
3072
3191
  : BSON_DATA_NUMBER;
3073
- if (type === BSON_DATA_INT) {
3074
- NUMBER_SPACE.setInt32(0, value, true);
3075
- }
3076
- else {
3077
- NUMBER_SPACE.setFloat64(0, value, true);
3078
- }
3079
- const bytes = type === BSON_DATA_INT ? FOUR_BYTE_VIEW_ON_NUMBER : EIGHT_BYTE_VIEW_ON_NUMBER;
3080
3192
  buffer[index++] = type;
3081
3193
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3082
3194
  index = index + numberOfWrittenBytes;
3083
3195
  buffer[index++] = 0x00;
3084
- buffer.set(bytes, index);
3085
- index += bytes.byteLength;
3196
+ if (type === BSON_DATA_INT) {
3197
+ index += NumberUtils.setInt32LE(buffer, index, value);
3198
+ }
3199
+ else {
3200
+ index += NumberUtils.setFloat64LE(buffer, index, value);
3201
+ }
3086
3202
  return index;
3087
3203
  }
3088
3204
  function serializeBigInt(buffer, key, value, index) {
@@ -3090,9 +3206,7 @@ function serializeBigInt(buffer, key, value, index) {
3090
3206
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3091
3207
  index += numberOfWrittenBytes;
3092
3208
  buffer[index++] = 0;
3093
- NUMBER_SPACE.setBigInt64(0, value, true);
3094
- buffer.set(EIGHT_BYTE_VIEW_ON_NUMBER, index);
3095
- index += EIGHT_BYTE_VIEW_ON_NUMBER.byteLength;
3209
+ index += NumberUtils.setBigInt64LE(buffer, index, value);
3096
3210
  return index;
3097
3211
  }
3098
3212
  function serializeNull(buffer, key, _, index) {
@@ -3118,14 +3232,8 @@ function serializeDate(buffer, key, value, index) {
3118
3232
  const dateInMilis = Long.fromNumber(value.getTime());
3119
3233
  const lowBits = dateInMilis.getLowBits();
3120
3234
  const highBits = dateInMilis.getHighBits();
3121
- buffer[index++] = lowBits & 0xff;
3122
- buffer[index++] = (lowBits >> 8) & 0xff;
3123
- buffer[index++] = (lowBits >> 16) & 0xff;
3124
- buffer[index++] = (lowBits >> 24) & 0xff;
3125
- buffer[index++] = highBits & 0xff;
3126
- buffer[index++] = (highBits >> 8) & 0xff;
3127
- buffer[index++] = (highBits >> 16) & 0xff;
3128
- buffer[index++] = (highBits >> 24) & 0xff;
3235
+ index += NumberUtils.setInt32LE(buffer, index, lowBits);
3236
+ index += NumberUtils.setInt32LE(buffer, index, highBits);
3129
3237
  return index;
3130
3238
  }
3131
3239
  function serializeRegExp(buffer, key, value, index) {
@@ -3182,15 +3290,7 @@ function serializeObjectId(buffer, key, value, index) {
3182
3290
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3183
3291
  index = index + numberOfWrittenBytes;
3184
3292
  buffer[index++] = 0;
3185
- const idValue = value.id;
3186
- if (isUint8Array(idValue)) {
3187
- for (let i = 0; i < 12; i++) {
3188
- buffer[index++] = idValue[i];
3189
- }
3190
- }
3191
- else {
3192
- throw new BSONError('object [' + JSON.stringify(value) + '] is not a valid ObjectId');
3193
- }
3293
+ index += value.serializeInto(buffer, index);
3194
3294
  return index;
3195
3295
  }
3196
3296
  function serializeBuffer(buffer, key, value, index) {
@@ -3199,12 +3299,15 @@ function serializeBuffer(buffer, key, value, index) {
3199
3299
  index = index + numberOfWrittenBytes;
3200
3300
  buffer[index++] = 0;
3201
3301
  const size = value.length;
3202
- buffer[index++] = size & 0xff;
3203
- buffer[index++] = (size >> 8) & 0xff;
3204
- buffer[index++] = (size >> 16) & 0xff;
3205
- buffer[index++] = (size >> 24) & 0xff;
3302
+ index += NumberUtils.setInt32LE(buffer, index, size);
3206
3303
  buffer[index++] = BSON_BINARY_SUBTYPE_DEFAULT;
3207
- buffer.set(value, index);
3304
+ if (size <= 16) {
3305
+ for (let i = 0; i < size; i++)
3306
+ buffer[index + i] = value[i];
3307
+ }
3308
+ else {
3309
+ buffer.set(value, index);
3310
+ }
3208
3311
  index = index + size;
3209
3312
  return index;
3210
3313
  }
@@ -3226,7 +3329,8 @@ function serializeDecimal128(buffer, key, value, index) {
3226
3329
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3227
3330
  index = index + numberOfWrittenBytes;
3228
3331
  buffer[index++] = 0;
3229
- buffer.set(value.bytes.subarray(0, 16), index);
3332
+ for (let i = 0; i < 16; i++)
3333
+ buffer[index + i] = value.bytes[i];
3230
3334
  return index + 16;
3231
3335
  }
3232
3336
  function serializeLong(buffer, key, value, index) {
@@ -3237,14 +3341,8 @@ function serializeLong(buffer, key, value, index) {
3237
3341
  buffer[index++] = 0;
3238
3342
  const lowBits = value.getLowBits();
3239
3343
  const highBits = value.getHighBits();
3240
- buffer[index++] = lowBits & 0xff;
3241
- buffer[index++] = (lowBits >> 8) & 0xff;
3242
- buffer[index++] = (lowBits >> 16) & 0xff;
3243
- buffer[index++] = (lowBits >> 24) & 0xff;
3244
- buffer[index++] = highBits & 0xff;
3245
- buffer[index++] = (highBits >> 8) & 0xff;
3246
- buffer[index++] = (highBits >> 16) & 0xff;
3247
- buffer[index++] = (highBits >> 24) & 0xff;
3344
+ index += NumberUtils.setInt32LE(buffer, index, lowBits);
3345
+ index += NumberUtils.setInt32LE(buffer, index, highBits);
3248
3346
  return index;
3249
3347
  }
3250
3348
  function serializeInt32(buffer, key, value, index) {
@@ -3253,10 +3351,7 @@ function serializeInt32(buffer, key, value, index) {
3253
3351
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3254
3352
  index = index + numberOfWrittenBytes;
3255
3353
  buffer[index++] = 0;
3256
- buffer[index++] = value & 0xff;
3257
- buffer[index++] = (value >> 8) & 0xff;
3258
- buffer[index++] = (value >> 16) & 0xff;
3259
- buffer[index++] = (value >> 24) & 0xff;
3354
+ index += NumberUtils.setInt32LE(buffer, index, value);
3260
3355
  return index;
3261
3356
  }
3262
3357
  function serializeDouble(buffer, key, value, index) {
@@ -3264,9 +3359,7 @@ function serializeDouble(buffer, key, value, index) {
3264
3359
  const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
3265
3360
  index = index + numberOfWrittenBytes;
3266
3361
  buffer[index++] = 0;
3267
- NUMBER_SPACE.setFloat64(0, value.value, true);
3268
- buffer.set(EIGHT_BYTE_VIEW_ON_NUMBER, index);
3269
- index = index + 8;
3362
+ index += NumberUtils.setFloat64LE(buffer, index, value.value);
3270
3363
  return index;
3271
3364
  }
3272
3365
  function serializeFunction(buffer, key, value, index) {
@@ -3276,10 +3369,7 @@ function serializeFunction(buffer, key, value, index) {
3276
3369
  buffer[index++] = 0;
3277
3370
  const functionString = value.toString();
3278
3371
  const size = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
3279
- buffer[index] = size & 0xff;
3280
- buffer[index + 1] = (size >> 8) & 0xff;
3281
- buffer[index + 2] = (size >> 16) & 0xff;
3282
- buffer[index + 3] = (size >> 24) & 0xff;
3372
+ NumberUtils.setInt32LE(buffer, index, size);
3283
3373
  index = index + 4 + size - 1;
3284
3374
  buffer[index++] = 0;
3285
3375
  return index;
@@ -3294,19 +3384,13 @@ function serializeCode(buffer, key, value, index, checkKeys = false, depth = 0,
3294
3384
  const functionString = value.code;
3295
3385
  index = index + 4;
3296
3386
  const codeSize = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
3297
- buffer[index] = codeSize & 0xff;
3298
- buffer[index + 1] = (codeSize >> 8) & 0xff;
3299
- buffer[index + 2] = (codeSize >> 16) & 0xff;
3300
- buffer[index + 3] = (codeSize >> 24) & 0xff;
3387
+ NumberUtils.setInt32LE(buffer, index, codeSize);
3301
3388
  buffer[index + 4 + codeSize - 1] = 0;
3302
3389
  index = index + codeSize + 4;
3303
3390
  const endIndex = serializeInto(buffer, value.scope, checkKeys, index, depth + 1, serializeFunctions, ignoreUndefined, path);
3304
3391
  index = endIndex - 1;
3305
3392
  const totalSize = endIndex - startIndex;
3306
- buffer[startIndex++] = totalSize & 0xff;
3307
- buffer[startIndex++] = (totalSize >> 8) & 0xff;
3308
- buffer[startIndex++] = (totalSize >> 16) & 0xff;
3309
- buffer[startIndex++] = (totalSize >> 24) & 0xff;
3393
+ startIndex += NumberUtils.setInt32LE(buffer, startIndex, totalSize);
3310
3394
  buffer[index++] = 0;
3311
3395
  }
3312
3396
  else {
@@ -3316,10 +3400,7 @@ function serializeCode(buffer, key, value, index, checkKeys = false, depth = 0,
3316
3400
  buffer[index++] = 0;
3317
3401
  const functionString = value.code.toString();
3318
3402
  const size = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
3319
- buffer[index] = size & 0xff;
3320
- buffer[index + 1] = (size >> 8) & 0xff;
3321
- buffer[index + 2] = (size >> 16) & 0xff;
3322
- buffer[index + 3] = (size >> 24) & 0xff;
3403
+ NumberUtils.setInt32LE(buffer, index, size);
3323
3404
  index = index + 4 + size - 1;
3324
3405
  buffer[index++] = 0;
3325
3406
  }
@@ -3334,19 +3415,19 @@ function serializeBinary(buffer, key, value, index) {
3334
3415
  let size = value.position;
3335
3416
  if (value.sub_type === Binary.SUBTYPE_BYTE_ARRAY)
3336
3417
  size = size + 4;
3337
- buffer[index++] = size & 0xff;
3338
- buffer[index++] = (size >> 8) & 0xff;
3339
- buffer[index++] = (size >> 16) & 0xff;
3340
- buffer[index++] = (size >> 24) & 0xff;
3418
+ index += NumberUtils.setInt32LE(buffer, index, size);
3341
3419
  buffer[index++] = value.sub_type;
3342
3420
  if (value.sub_type === Binary.SUBTYPE_BYTE_ARRAY) {
3343
3421
  size = size - 4;
3344
- buffer[index++] = size & 0xff;
3345
- buffer[index++] = (size >> 8) & 0xff;
3346
- buffer[index++] = (size >> 16) & 0xff;
3347
- buffer[index++] = (size >> 24) & 0xff;
3422
+ index += NumberUtils.setInt32LE(buffer, index, size);
3423
+ }
3424
+ if (size <= 16) {
3425
+ for (let i = 0; i < size; i++)
3426
+ buffer[index + i] = data[i];
3427
+ }
3428
+ else {
3429
+ buffer.set(data, index);
3348
3430
  }
3349
- buffer.set(data, index);
3350
3431
  index = index + value.position;
3351
3432
  return index;
3352
3433
  }
@@ -3356,12 +3437,9 @@ function serializeSymbol(buffer, key, value, index) {
3356
3437
  index = index + numberOfWrittenBytes;
3357
3438
  buffer[index++] = 0;
3358
3439
  const size = ByteUtils.encodeUTF8Into(buffer, value.value, index + 4) + 1;
3359
- buffer[index] = size & 0xff;
3360
- buffer[index + 1] = (size >> 8) & 0xff;
3361
- buffer[index + 2] = (size >> 16) & 0xff;
3362
- buffer[index + 3] = (size >> 24) & 0xff;
3440
+ NumberUtils.setInt32LE(buffer, index, size);
3363
3441
  index = index + 4 + size - 1;
3364
- buffer[index++] = 0x00;
3442
+ buffer[index++] = 0;
3365
3443
  return index;
3366
3444
  }
3367
3445
  function serializeDBRef(buffer, key, value, index, depth, serializeFunctions, path) {
@@ -3380,10 +3458,7 @@ function serializeDBRef(buffer, key, value, index, depth, serializeFunctions, pa
3380
3458
  output = Object.assign(output, value.fields);
3381
3459
  const endIndex = serializeInto(buffer, output, false, index, depth + 1, serializeFunctions, true, path);
3382
3460
  const size = endIndex - startIndex;
3383
- buffer[startIndex++] = size & 0xff;
3384
- buffer[startIndex++] = (size >> 8) & 0xff;
3385
- buffer[startIndex++] = (size >> 16) & 0xff;
3386
- buffer[startIndex++] = (size >> 24) & 0xff;
3461
+ startIndex += NumberUtils.setInt32LE(buffer, index, size);
3387
3462
  return endIndex;
3388
3463
  }
3389
3464
  function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializeFunctions, ignoreUndefined, path) {
@@ -3519,7 +3594,7 @@ function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializ
3519
3594
  if ('$' === key[0]) {
3520
3595
  throw new BSONError('key ' + key + " must not start with '$'");
3521
3596
  }
3522
- else if (~key.indexOf('.')) {
3597
+ else if (key.includes('.')) {
3523
3598
  throw new BSONError('key ' + key + " must not contain '.'");
3524
3599
  }
3525
3600
  }
@@ -3617,7 +3692,7 @@ function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializ
3617
3692
  if ('$' === key[0]) {
3618
3693
  throw new BSONError('key ' + key + " must not start with '$'");
3619
3694
  }
3620
- else if (~key.indexOf('.')) {
3695
+ else if (key.includes('.')) {
3621
3696
  throw new BSONError('key ' + key + " must not contain '.'");
3622
3697
  }
3623
3698
  }
@@ -3701,10 +3776,7 @@ function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializ
3701
3776
  path.delete(object);
3702
3777
  buffer[index++] = 0x00;
3703
3778
  const size = index - startingIndex;
3704
- buffer[startingIndex++] = size & 0xff;
3705
- buffer[startingIndex++] = (size >> 8) & 0xff;
3706
- buffer[startingIndex++] = (size >> 16) & 0xff;
3707
- buffer[startingIndex++] = (size >> 24) & 0xff;
3779
+ startingIndex += NumberUtils.setInt32LE(buffer, startingIndex, size);
3708
3780
  return index;
3709
3781
  }
3710
3782
 
@@ -4034,7 +4106,7 @@ function serialize(object, options = {}) {
4034
4106
  buffer = ByteUtils.allocate(minInternalBufferSize);
4035
4107
  }
4036
4108
  const serializationIndex = serializeInto(buffer, object, checkKeys, 0, 0, serializeFunctions, ignoreUndefined, null);
4037
- const finishedBuffer = ByteUtils.allocate(serializationIndex);
4109
+ const finishedBuffer = ByteUtils.allocateUnsafe(serializationIndex);
4038
4110
  finishedBuffer.set(buffer.subarray(0, serializationIndex), 0);
4039
4111
  return finishedBuffer;
4040
4112
  }
@@ -4061,10 +4133,7 @@ function deserializeStream(data, startIndex, numberOfDocuments, documents, docSt
4061
4133
  const bufferData = ByteUtils.toLocalBufferType(data);
4062
4134
  let index = startIndex;
4063
4135
  for (let i = 0; i < numberOfDocuments; i++) {
4064
- const size = bufferData[index] |
4065
- (bufferData[index + 1] << 8) |
4066
- (bufferData[index + 2] << 16) |
4067
- (bufferData[index + 3] << 24);
4136
+ const size = NumberUtils.getInt32LE(bufferData, index);
4068
4137
  internalOptions.index = index;
4069
4138
  documents[docStartIndex + i] = internalDeserialize(bufferData, internalOptions);
4070
4139
  index = index + size;