bson 4.7.0 → 5.0.0-alpha.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.
Files changed (98) hide show
  1. package/bson.d.ts +207 -259
  2. package/lib/bson.bundle.js +4033 -0
  3. package/lib/bson.bundle.js.map +1 -0
  4. package/lib/bson.cjs +4028 -0
  5. package/lib/bson.cjs.map +1 -0
  6. package/lib/bson.mjs +4002 -0
  7. package/lib/bson.mjs.map +1 -0
  8. package/package.json +49 -62
  9. package/src/binary.ts +63 -52
  10. package/src/bson.ts +27 -108
  11. package/src/code.ts +24 -14
  12. package/src/constants.ts +28 -0
  13. package/src/db_ref.ts +13 -8
  14. package/src/decimal128.ts +31 -25
  15. package/src/double.ts +7 -5
  16. package/src/error.ts +0 -2
  17. package/src/extended_json.ts +148 -148
  18. package/src/index.ts +19 -0
  19. package/src/int_32.ts +7 -5
  20. package/src/long.ts +16 -16
  21. package/src/max_key.ts +6 -6
  22. package/src/min_key.ts +6 -6
  23. package/src/objectid.ts +41 -74
  24. package/src/parser/calculate_size.ts +39 -63
  25. package/src/parser/deserializer.ts +41 -112
  26. package/src/parser/serializer.ts +234 -341
  27. package/src/parser/utils.ts +1 -99
  28. package/src/regexp.ts +16 -5
  29. package/src/symbol.ts +7 -5
  30. package/src/timestamp.ts +62 -27
  31. package/src/utils/byte_utils.ts +61 -0
  32. package/src/utils/node_byte_utils.ts +141 -0
  33. package/src/utils/web_byte_utils.ts +190 -0
  34. package/src/uuid_utils.ts +15 -15
  35. package/bower.json +0 -26
  36. package/dist/bson.browser.esm.js +0 -7470
  37. package/dist/bson.browser.esm.js.map +0 -1
  38. package/dist/bson.browser.umd.js +0 -7537
  39. package/dist/bson.browser.umd.js.map +0 -1
  40. package/dist/bson.bundle.js +0 -7536
  41. package/dist/bson.bundle.js.map +0 -1
  42. package/dist/bson.esm.js +0 -5436
  43. package/dist/bson.esm.js.map +0 -1
  44. package/lib/binary.js +0 -426
  45. package/lib/binary.js.map +0 -1
  46. package/lib/bson.js +0 -251
  47. package/lib/bson.js.map +0 -1
  48. package/lib/code.js +0 -46
  49. package/lib/code.js.map +0 -1
  50. package/lib/constants.js +0 -82
  51. package/lib/constants.js.map +0 -1
  52. package/lib/db_ref.js +0 -97
  53. package/lib/db_ref.js.map +0 -1
  54. package/lib/decimal128.js +0 -669
  55. package/lib/decimal128.js.map +0 -1
  56. package/lib/double.js +0 -76
  57. package/lib/double.js.map +0 -1
  58. package/lib/ensure_buffer.js +0 -25
  59. package/lib/ensure_buffer.js.map +0 -1
  60. package/lib/error.js +0 -55
  61. package/lib/error.js.map +0 -1
  62. package/lib/extended_json.js +0 -390
  63. package/lib/extended_json.js.map +0 -1
  64. package/lib/int_32.js +0 -58
  65. package/lib/int_32.js.map +0 -1
  66. package/lib/long.js +0 -900
  67. package/lib/long.js.map +0 -1
  68. package/lib/map.js +0 -123
  69. package/lib/map.js.map +0 -1
  70. package/lib/max_key.js +0 -33
  71. package/lib/max_key.js.map +0 -1
  72. package/lib/min_key.js +0 -33
  73. package/lib/min_key.js.map +0 -1
  74. package/lib/objectid.js +0 -299
  75. package/lib/objectid.js.map +0 -1
  76. package/lib/parser/calculate_size.js +0 -194
  77. package/lib/parser/calculate_size.js.map +0 -1
  78. package/lib/parser/deserializer.js +0 -665
  79. package/lib/parser/deserializer.js.map +0 -1
  80. package/lib/parser/serializer.js +0 -867
  81. package/lib/parser/serializer.js.map +0 -1
  82. package/lib/parser/utils.js +0 -115
  83. package/lib/parser/utils.js.map +0 -1
  84. package/lib/regexp.js +0 -74
  85. package/lib/regexp.js.map +0 -1
  86. package/lib/symbol.js +0 -48
  87. package/lib/symbol.js.map +0 -1
  88. package/lib/timestamp.js +0 -102
  89. package/lib/timestamp.js.map +0 -1
  90. package/lib/utils/global.js +0 -18
  91. package/lib/utils/global.js.map +0 -1
  92. package/lib/uuid_utils.js +0 -35
  93. package/lib/uuid_utils.js.map +0 -1
  94. package/lib/validate_utf8.js +0 -47
  95. package/lib/validate_utf8.js.map +0 -1
  96. package/src/ensure_buffer.ts +0 -27
  97. package/src/map.ts +0 -119
  98. package/src/utils/global.ts +0 -22
@@ -1,4 +1,3 @@
1
- import type { Buffer } from 'buffer';
2
1
  import { Binary } from '../binary';
3
2
  import type { BSONSymbol, DBRef, Document, MaxKey } from '../bson';
4
3
  import type { Code } from '../code';
@@ -6,23 +5,21 @@ import * as constants from '../constants';
6
5
  import type { DBRefLike } from '../db_ref';
7
6
  import type { Decimal128 } from '../decimal128';
8
7
  import type { Double } from '../double';
9
- import { ensureBuffer } from '../ensure_buffer';
10
8
  import { BSONError, BSONTypeError } from '../error';
11
- import { isBSONType } from '../extended_json';
12
9
  import type { Int32 } from '../int_32';
13
10
  import { Long } from '../long';
14
- import { Map } from '../map';
15
11
  import type { MinKey } from '../min_key';
16
12
  import type { ObjectId } from '../objectid';
17
13
  import type { BSONRegExp } from '../regexp';
14
+ import { ByteUtils } from '../utils/byte_utils';
18
15
  import {
16
+ isAnyArrayBuffer,
19
17
  isBigInt64Array,
20
18
  isBigUInt64Array,
21
19
  isDate,
22
20
  isMap,
23
21
  isRegExp,
24
- isUint8Array,
25
- normalizedFunctionString
22
+ isUint8Array
26
23
  } from './utils';
27
24
 
28
25
  /** @public */
@@ -48,24 +45,16 @@ const ignoreKeys = new Set(['$db', '$ref', '$id', '$clusterTime']);
48
45
  * This will catch any errors in index as a string generation
49
46
  */
50
47
 
51
- function serializeString(
52
- buffer: Buffer,
53
- key: string,
54
- value: string,
55
- index: number,
56
- isArray?: boolean
57
- ) {
48
+ function serializeString(buffer: Uint8Array, key: string, value: string, index: number) {
58
49
  // Encode String type
59
50
  buffer[index++] = constants.BSON_DATA_STRING;
60
51
  // Number of written bytes
61
- const numberOfWrittenBytes = !isArray
62
- ? buffer.write(key, index, undefined, 'utf8')
63
- : buffer.write(key, index, undefined, 'ascii');
52
+ const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
64
53
  // Encode the name
65
54
  index = index + numberOfWrittenBytes + 1;
66
55
  buffer[index - 1] = 0;
67
56
  // Write the string
68
- const size = buffer.write(value, index + 4, undefined, 'utf8');
57
+ const size = ByteUtils.encodeUTF8Into(buffer, value, index + 4);
69
58
  // Write the size of the string to buffer
70
59
  buffer[index + 3] = ((size + 1) >> 24) & 0xff;
71
60
  buffer[index + 2] = ((size + 1) >> 16) & 0xff;
@@ -78,69 +67,48 @@ function serializeString(
78
67
  return index;
79
68
  }
80
69
 
81
- const SPACE_FOR_FLOAT64 = new Uint8Array(8);
82
- const DV_FOR_FLOAT64 = new DataView(
83
- SPACE_FOR_FLOAT64.buffer,
84
- SPACE_FOR_FLOAT64.byteOffset,
85
- SPACE_FOR_FLOAT64.byteLength
86
- );
87
- function serializeNumber(
88
- buffer: Buffer,
89
- key: string,
90
- value: number,
91
- index: number,
92
- isArray?: boolean
93
- ) {
94
- // We have an integer value
95
- // TODO(NODE-2529): Add support for big int
96
- if (
97
- Number.isInteger(value) &&
98
- value >= constants.BSON_INT32_MIN &&
99
- value <= constants.BSON_INT32_MAX
100
- ) {
101
- // If the value fits in 32 bits encode as int32
102
- // Set int type 32 bits or less
103
- buffer[index++] = constants.BSON_DATA_INT;
104
- // Number of written bytes
105
- const numberOfWrittenBytes = !isArray
106
- ? buffer.write(key, index, undefined, 'utf8')
107
- : buffer.write(key, index, undefined, 'ascii');
108
- // Encode the name
109
- index = index + numberOfWrittenBytes;
110
- buffer[index++] = 0;
111
- // Write the int value
112
- buffer[index++] = value & 0xff;
113
- buffer[index++] = (value >> 8) & 0xff;
114
- buffer[index++] = (value >> 16) & 0xff;
115
- buffer[index++] = (value >> 24) & 0xff;
70
+ const NUMBER_SPACE = new DataView(new ArrayBuffer(8), 0, 8);
71
+ const FOUR_BYTE_VIEW_ON_NUMBER = new Uint8Array(NUMBER_SPACE.buffer, 0, 4);
72
+ const EIGHT_BYTE_VIEW_ON_NUMBER = new Uint8Array(NUMBER_SPACE.buffer, 0, 8);
73
+
74
+ function serializeNumber(buffer: Uint8Array, key: string, value: number, index: number) {
75
+ const isNegativeZero = Object.is(value, -0);
76
+
77
+ const type =
78
+ !isNegativeZero &&
79
+ Number.isSafeInteger(value) &&
80
+ value <= constants.BSON_INT32_MAX &&
81
+ value >= constants.BSON_INT32_MIN
82
+ ? constants.BSON_DATA_INT
83
+ : constants.BSON_DATA_NUMBER;
84
+
85
+ if (type === constants.BSON_DATA_INT) {
86
+ NUMBER_SPACE.setInt32(0, value, true);
116
87
  } else {
117
- // Encode as double
118
- buffer[index++] = constants.BSON_DATA_NUMBER;
119
- // Number of written bytes
120
- const numberOfWrittenBytes = !isArray
121
- ? buffer.write(key, index, undefined, 'utf8')
122
- : buffer.write(key, index, undefined, 'ascii');
123
- // Encode the name
124
- index = index + numberOfWrittenBytes;
125
- buffer[index++] = 0;
126
- // Write float
127
- DV_FOR_FLOAT64.setFloat64(0, value, true);
128
- buffer.set(SPACE_FOR_FLOAT64, index);
129
- // Adjust index
130
- index = index + 8;
88
+ NUMBER_SPACE.setFloat64(0, value, true);
131
89
  }
132
90
 
91
+ const bytes =
92
+ type === constants.BSON_DATA_INT ? FOUR_BYTE_VIEW_ON_NUMBER : EIGHT_BYTE_VIEW_ON_NUMBER;
93
+
94
+ buffer[index++] = type;
95
+
96
+ const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
97
+ index = index + numberOfWrittenBytes;
98
+ buffer[index++] = 0x00;
99
+
100
+ buffer.set(bytes, index);
101
+ index += bytes.byteLength;
102
+
133
103
  return index;
134
104
  }
135
105
 
136
- function serializeNull(buffer: Buffer, key: string, _: unknown, index: number, isArray?: boolean) {
106
+ function serializeNull(buffer: Uint8Array, key: string, _: unknown, index: number) {
137
107
  // Set long type
138
108
  buffer[index++] = constants.BSON_DATA_NULL;
139
109
 
140
110
  // Number of written bytes
141
- const numberOfWrittenBytes = !isArray
142
- ? buffer.write(key, index, undefined, 'utf8')
143
- : buffer.write(key, index, undefined, 'ascii');
111
+ const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
144
112
 
145
113
  // Encode the name
146
114
  index = index + numberOfWrittenBytes;
@@ -148,19 +116,11 @@ function serializeNull(buffer: Buffer, key: string, _: unknown, index: number, i
148
116
  return index;
149
117
  }
150
118
 
151
- function serializeBoolean(
152
- buffer: Buffer,
153
- key: string,
154
- value: boolean,
155
- index: number,
156
- isArray?: boolean
157
- ) {
119
+ function serializeBoolean(buffer: Uint8Array, key: string, value: boolean, index: number) {
158
120
  // Write the type
159
121
  buffer[index++] = constants.BSON_DATA_BOOLEAN;
160
122
  // Number of written bytes
161
- const numberOfWrittenBytes = !isArray
162
- ? buffer.write(key, index, undefined, 'utf8')
163
- : buffer.write(key, index, undefined, 'ascii');
123
+ const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
164
124
  // Encode the name
165
125
  index = index + numberOfWrittenBytes;
166
126
  buffer[index++] = 0;
@@ -169,13 +129,11 @@ function serializeBoolean(
169
129
  return index;
170
130
  }
171
131
 
172
- function serializeDate(buffer: Buffer, key: string, value: Date, index: number, isArray?: boolean) {
132
+ function serializeDate(buffer: Uint8Array, key: string, value: Date, index: number) {
173
133
  // Write the type
174
134
  buffer[index++] = constants.BSON_DATA_DATE;
175
135
  // Number of written bytes
176
- const numberOfWrittenBytes = !isArray
177
- ? buffer.write(key, index, undefined, 'utf8')
178
- : buffer.write(key, index, undefined, 'ascii');
136
+ const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
179
137
  // Encode the name
180
138
  index = index + numberOfWrittenBytes;
181
139
  buffer[index++] = 0;
@@ -197,19 +155,11 @@ function serializeDate(buffer: Buffer, key: string, value: Date, index: number,
197
155
  return index;
198
156
  }
199
157
 
200
- function serializeRegExp(
201
- buffer: Buffer,
202
- key: string,
203
- value: RegExp,
204
- index: number,
205
- isArray?: boolean
206
- ) {
158
+ function serializeRegExp(buffer: Uint8Array, key: string, value: RegExp, index: number) {
207
159
  // Write the type
208
160
  buffer[index++] = constants.BSON_DATA_REGEXP;
209
161
  // Number of written bytes
210
- const numberOfWrittenBytes = !isArray
211
- ? buffer.write(key, index, undefined, 'utf8')
212
- : buffer.write(key, index, undefined, 'ascii');
162
+ const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
213
163
 
214
164
  // Encode the name
215
165
  index = index + numberOfWrittenBytes;
@@ -218,7 +168,7 @@ function serializeRegExp(
218
168
  throw Error('value ' + value.source + ' must not contain null bytes');
219
169
  }
220
170
  // Adjust the index
221
- index = index + buffer.write(value.source, index, undefined, 'utf8');
171
+ index = index + ByteUtils.encodeUTF8Into(buffer, value.source, index);
222
172
  // Write zero
223
173
  buffer[index++] = 0x00;
224
174
  // Write the parameters
@@ -231,19 +181,11 @@ function serializeRegExp(
231
181
  return index;
232
182
  }
233
183
 
234
- function serializeBSONRegExp(
235
- buffer: Buffer,
236
- key: string,
237
- value: BSONRegExp,
238
- index: number,
239
- isArray?: boolean
240
- ) {
184
+ function serializeBSONRegExp(buffer: Uint8Array, key: string, value: BSONRegExp, index: number) {
241
185
  // Write the type
242
186
  buffer[index++] = constants.BSON_DATA_REGEXP;
243
187
  // Number of written bytes
244
- const numberOfWrittenBytes = !isArray
245
- ? buffer.write(key, index, undefined, 'utf8')
246
- : buffer.write(key, index, undefined, 'ascii');
188
+ const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
247
189
  // Encode the name
248
190
  index = index + numberOfWrittenBytes;
249
191
  buffer[index++] = 0;
@@ -256,23 +198,18 @@ function serializeBSONRegExp(
256
198
  }
257
199
 
258
200
  // Adjust the index
259
- index = index + buffer.write(value.pattern, index, undefined, 'utf8');
201
+ index = index + ByteUtils.encodeUTF8Into(buffer, value.pattern, index);
260
202
  // Write zero
261
203
  buffer[index++] = 0x00;
262
204
  // Write the options
263
- index = index + buffer.write(value.options.split('').sort().join(''), index, undefined, 'utf8');
205
+ const sortedOptions = value.options.split('').sort().join('');
206
+ index = index + ByteUtils.encodeUTF8Into(buffer, sortedOptions, index);
264
207
  // Add ending zero
265
208
  buffer[index++] = 0x00;
266
209
  return index;
267
210
  }
268
211
 
269
- function serializeMinMax(
270
- buffer: Buffer,
271
- key: string,
272
- value: MinKey | MaxKey,
273
- index: number,
274
- isArray?: boolean
275
- ) {
212
+ function serializeMinMax(buffer: Uint8Array, key: string, value: MinKey | MaxKey, index: number) {
276
213
  // Write the type of either min or max key
277
214
  if (value === null) {
278
215
  buffer[index++] = constants.BSON_DATA_NULL;
@@ -283,39 +220,25 @@ function serializeMinMax(
283
220
  }
284
221
 
285
222
  // Number of written bytes
286
- const numberOfWrittenBytes = !isArray
287
- ? buffer.write(key, index, undefined, 'utf8')
288
- : buffer.write(key, index, undefined, 'ascii');
223
+ const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
289
224
  // Encode the name
290
225
  index = index + numberOfWrittenBytes;
291
226
  buffer[index++] = 0;
292
227
  return index;
293
228
  }
294
229
 
295
- function serializeObjectId(
296
- buffer: Buffer,
297
- key: string,
298
- value: ObjectId,
299
- index: number,
300
- isArray?: boolean
301
- ) {
230
+ function serializeObjectId(buffer: Uint8Array, key: string, value: ObjectId, index: number) {
302
231
  // Write the type
303
232
  buffer[index++] = constants.BSON_DATA_OID;
304
233
  // Number of written bytes
305
- const numberOfWrittenBytes = !isArray
306
- ? buffer.write(key, index, undefined, 'utf8')
307
- : buffer.write(key, index, undefined, 'ascii');
234
+ const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
308
235
 
309
236
  // Encode the name
310
237
  index = index + numberOfWrittenBytes;
311
238
  buffer[index++] = 0;
312
239
 
313
240
  // Write the objectId into the shared buffer
314
- if (typeof value.id === 'string') {
315
- buffer.write(value.id, index, undefined, 'binary');
316
- } else if (isUint8Array(value.id)) {
317
- // Use the standard JS methods here because buffer.copy() is buggy with the
318
- // browser polyfill
241
+ if (isUint8Array(value.id)) {
319
242
  buffer.set(value.id.subarray(0, 12), index);
320
243
  } else {
321
244
  throw new BSONTypeError('object [' + JSON.stringify(value) + '] is not a valid ObjectId');
@@ -325,19 +248,11 @@ function serializeObjectId(
325
248
  return index + 12;
326
249
  }
327
250
 
328
- function serializeBuffer(
329
- buffer: Buffer,
330
- key: string,
331
- value: Buffer | Uint8Array,
332
- index: number,
333
- isArray?: boolean
334
- ) {
251
+ function serializeBuffer(buffer: Uint8Array, key: string, value: Uint8Array, index: number) {
335
252
  // Write the type
336
253
  buffer[index++] = constants.BSON_DATA_BINARY;
337
254
  // Number of written bytes
338
- const numberOfWrittenBytes = !isArray
339
- ? buffer.write(key, index, undefined, 'utf8')
340
- : buffer.write(key, index, undefined, 'ascii');
255
+ const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
341
256
  // Encode the name
342
257
  index = index + numberOfWrittenBytes;
343
258
  buffer[index++] = 0;
@@ -351,36 +266,33 @@ function serializeBuffer(
351
266
  // Write the default subtype
352
267
  buffer[index++] = constants.BSON_BINARY_SUBTYPE_DEFAULT;
353
268
  // Copy the content form the binary field to the buffer
354
- buffer.set(ensureBuffer(value), index);
269
+ buffer.set(value, index);
355
270
  // Adjust the index
356
271
  index = index + size;
357
272
  return index;
358
273
  }
359
274
 
360
275
  function serializeObject(
361
- buffer: Buffer,
276
+ buffer: Uint8Array,
362
277
  key: string,
363
278
  value: Document,
364
279
  index: number,
365
- checkKeys = false,
366
- depth = 0,
367
- serializeFunctions = false,
368
- ignoreUndefined = true,
369
- isArray = false,
370
- path: Document[] = []
280
+ checkKeys: boolean,
281
+ depth: number,
282
+ serializeFunctions: boolean,
283
+ ignoreUndefined: boolean,
284
+ path: Set<Document>
371
285
  ) {
372
- for (let i = 0; i < path.length; i++) {
373
- if (path[i] === value) throw new BSONError('cyclic dependency detected');
286
+ if (path.has(value)) {
287
+ throw new BSONError('Cannot convert circular structure to BSON');
374
288
  }
375
289
 
376
- // Push value to stack
377
- path.push(value);
290
+ path.add(value);
291
+
378
292
  // Write the type
379
293
  buffer[index++] = Array.isArray(value) ? constants.BSON_DATA_ARRAY : constants.BSON_DATA_OBJECT;
380
294
  // Number of written bytes
381
- const numberOfWrittenBytes = !isArray
382
- ? buffer.write(key, index, undefined, 'utf8')
383
- : buffer.write(key, index, undefined, 'ascii');
295
+ const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
384
296
  // Encode the name
385
297
  index = index + numberOfWrittenBytes;
386
298
  buffer[index++] = 0;
@@ -394,41 +306,30 @@ function serializeObject(
394
306
  ignoreUndefined,
395
307
  path
396
308
  );
397
- // Pop stack
398
- path.pop();
309
+
310
+ path.delete(value);
311
+
399
312
  return endIndex;
400
313
  }
401
314
 
402
- function serializeDecimal128(
403
- buffer: Buffer,
404
- key: string,
405
- value: Decimal128,
406
- index: number,
407
- isArray?: boolean
408
- ) {
315
+ function serializeDecimal128(buffer: Uint8Array, key: string, value: Decimal128, index: number) {
409
316
  buffer[index++] = constants.BSON_DATA_DECIMAL128;
410
317
  // Number of written bytes
411
- const numberOfWrittenBytes = !isArray
412
- ? buffer.write(key, index, undefined, 'utf8')
413
- : buffer.write(key, index, undefined, 'ascii');
318
+ const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
414
319
  // Encode the name
415
320
  index = index + numberOfWrittenBytes;
416
321
  buffer[index++] = 0;
417
322
  // Write the data from the value
418
- // Prefer the standard JS methods because their typechecking is not buggy,
419
- // unlike the `buffer` polyfill's.
420
323
  buffer.set(value.bytes.subarray(0, 16), index);
421
324
  return index + 16;
422
325
  }
423
326
 
424
- function serializeLong(buffer: Buffer, key: string, value: Long, index: number, isArray?: boolean) {
327
+ function serializeLong(buffer: Uint8Array, key: string, value: Long, index: number) {
425
328
  // Write the type
426
329
  buffer[index++] =
427
330
  value._bsontype === 'Long' ? constants.BSON_DATA_LONG : constants.BSON_DATA_TIMESTAMP;
428
331
  // Number of written bytes
429
- const numberOfWrittenBytes = !isArray
430
- ? buffer.write(key, index, undefined, 'utf8')
431
- : buffer.write(key, index, undefined, 'ascii');
332
+ const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
432
333
  // Encode the name
433
334
  index = index + numberOfWrittenBytes;
434
335
  buffer[index++] = 0;
@@ -448,20 +349,12 @@ function serializeLong(buffer: Buffer, key: string, value: Long, index: number,
448
349
  return index;
449
350
  }
450
351
 
451
- function serializeInt32(
452
- buffer: Buffer,
453
- key: string,
454
- value: Int32 | number,
455
- index: number,
456
- isArray?: boolean
457
- ) {
352
+ function serializeInt32(buffer: Uint8Array, key: string, value: Int32 | number, index: number) {
458
353
  value = value.valueOf();
459
354
  // Set int type 32 bits or less
460
355
  buffer[index++] = constants.BSON_DATA_INT;
461
356
  // Number of written bytes
462
- const numberOfWrittenBytes = !isArray
463
- ? buffer.write(key, index, undefined, 'utf8')
464
- : buffer.write(key, index, undefined, 'ascii');
357
+ const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
465
358
  // Encode the name
466
359
  index = index + numberOfWrittenBytes;
467
360
  buffer[index++] = 0;
@@ -473,56 +366,38 @@ function serializeInt32(
473
366
  return index;
474
367
  }
475
368
 
476
- function serializeDouble(
477
- buffer: Buffer,
478
- key: string,
479
- value: Double,
480
- index: number,
481
- isArray?: boolean
482
- ) {
369
+ function serializeDouble(buffer: Uint8Array, key: string, value: Double, index: number) {
483
370
  // Encode as double
484
371
  buffer[index++] = constants.BSON_DATA_NUMBER;
485
372
 
486
373
  // Number of written bytes
487
- const numberOfWrittenBytes = !isArray
488
- ? buffer.write(key, index, undefined, 'utf8')
489
- : buffer.write(key, index, undefined, 'ascii');
374
+ const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
490
375
 
491
376
  // Encode the name
492
377
  index = index + numberOfWrittenBytes;
493
378
  buffer[index++] = 0;
494
379
 
495
380
  // Write float
496
- DV_FOR_FLOAT64.setFloat64(0, value.value, true);
497
- buffer.set(SPACE_FOR_FLOAT64, index);
381
+ NUMBER_SPACE.setFloat64(0, value.value, true);
382
+ buffer.set(EIGHT_BYTE_VIEW_ON_NUMBER, index);
498
383
 
499
384
  // Adjust index
500
385
  index = index + 8;
501
386
  return index;
502
387
  }
503
388
 
504
- function serializeFunction(
505
- buffer: Buffer,
506
- key: string,
507
- value: Function,
508
- index: number,
509
- _checkKeys = false,
510
- _depth = 0,
511
- isArray?: boolean
512
- ) {
389
+ function serializeFunction(buffer: Uint8Array, key: string, value: Function, index: number) {
513
390
  buffer[index++] = constants.BSON_DATA_CODE;
514
391
  // Number of written bytes
515
- const numberOfWrittenBytes = !isArray
516
- ? buffer.write(key, index, undefined, 'utf8')
517
- : buffer.write(key, index, undefined, 'ascii');
392
+ const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
518
393
  // Encode the name
519
394
  index = index + numberOfWrittenBytes;
520
395
  buffer[index++] = 0;
521
396
  // Function string
522
- const functionString = normalizedFunctionString(value);
397
+ const functionString = value.toString();
523
398
 
524
399
  // Write the string
525
- const size = buffer.write(functionString, index + 4, undefined, 'utf8') + 1;
400
+ const size = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
526
401
  // Write the size of the string to buffer
527
402
  buffer[index] = size & 0xff;
528
403
  buffer[index + 1] = (size >> 8) & 0xff;
@@ -536,7 +411,7 @@ function serializeFunction(
536
411
  }
537
412
 
538
413
  function serializeCode(
539
- buffer: Buffer,
414
+ buffer: Uint8Array,
540
415
  key: string,
541
416
  value: Code,
542
417
  index: number,
@@ -544,15 +419,13 @@ function serializeCode(
544
419
  depth = 0,
545
420
  serializeFunctions = false,
546
421
  ignoreUndefined = true,
547
- isArray = false
422
+ path: Set<Document>
548
423
  ) {
549
424
  if (value.scope && typeof value.scope === 'object') {
550
425
  // Write the type
551
426
  buffer[index++] = constants.BSON_DATA_CODE_W_SCOPE;
552
427
  // Number of written bytes
553
- const numberOfWrittenBytes = !isArray
554
- ? buffer.write(key, index, undefined, 'utf8')
555
- : buffer.write(key, index, undefined, 'ascii');
428
+ const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
556
429
  // Encode the name
557
430
  index = index + numberOfWrittenBytes;
558
431
  buffer[index++] = 0;
@@ -562,11 +435,11 @@ function serializeCode(
562
435
 
563
436
  // Serialize the function
564
437
  // Get the function string
565
- const functionString = typeof value.code === 'string' ? value.code : value.code.toString();
438
+ const functionString = value.code;
566
439
  // Index adjustment
567
440
  index = index + 4;
568
441
  // Write string into buffer
569
- const codeSize = buffer.write(functionString, index + 4, undefined, 'utf8') + 1;
442
+ const codeSize = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
570
443
  // Write the size of the string to buffer
571
444
  buffer[index] = codeSize & 0xff;
572
445
  buffer[index + 1] = (codeSize >> 8) & 0xff;
@@ -577,7 +450,6 @@ function serializeCode(
577
450
  // Write the
578
451
  index = index + codeSize + 4;
579
452
 
580
- //
581
453
  // Serialize the scope value
582
454
  const endIndex = serializeInto(
583
455
  buffer,
@@ -586,7 +458,8 @@ function serializeCode(
586
458
  index,
587
459
  depth + 1,
588
460
  serializeFunctions,
589
- ignoreUndefined
461
+ ignoreUndefined,
462
+ path
590
463
  );
591
464
  index = endIndex - 1;
592
465
 
@@ -603,16 +476,14 @@ function serializeCode(
603
476
  } else {
604
477
  buffer[index++] = constants.BSON_DATA_CODE;
605
478
  // Number of written bytes
606
- const numberOfWrittenBytes = !isArray
607
- ? buffer.write(key, index, undefined, 'utf8')
608
- : buffer.write(key, index, undefined, 'ascii');
479
+ const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
609
480
  // Encode the name
610
481
  index = index + numberOfWrittenBytes;
611
482
  buffer[index++] = 0;
612
483
  // Function string
613
484
  const functionString = value.code.toString();
614
485
  // Write the string
615
- const size = buffer.write(functionString, index + 4, undefined, 'utf8') + 1;
486
+ const size = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
616
487
  // Write the size of the string to buffer
617
488
  buffer[index] = size & 0xff;
618
489
  buffer[index + 1] = (size >> 8) & 0xff;
@@ -627,24 +498,16 @@ function serializeCode(
627
498
  return index;
628
499
  }
629
500
 
630
- function serializeBinary(
631
- buffer: Buffer,
632
- key: string,
633
- value: Binary,
634
- index: number,
635
- isArray?: boolean
636
- ) {
501
+ function serializeBinary(buffer: Uint8Array, key: string, value: Binary, index: number) {
637
502
  // Write the type
638
503
  buffer[index++] = constants.BSON_DATA_BINARY;
639
504
  // Number of written bytes
640
- const numberOfWrittenBytes = !isArray
641
- ? buffer.write(key, index, undefined, 'utf8')
642
- : buffer.write(key, index, undefined, 'ascii');
505
+ const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
643
506
  // Encode the name
644
507
  index = index + numberOfWrittenBytes;
645
508
  buffer[index++] = 0;
646
509
  // Extract the buffer
647
- const data = value.value(true) as Buffer | Uint8Array;
510
+ const data = value.buffer;
648
511
  // Calculate size
649
512
  let size = value.position;
650
513
  // Add the deprecated 02 type 4 bytes of size to total
@@ -673,24 +536,16 @@ function serializeBinary(
673
536
  return index;
674
537
  }
675
538
 
676
- function serializeSymbol(
677
- buffer: Buffer,
678
- key: string,
679
- value: BSONSymbol,
680
- index: number,
681
- isArray?: boolean
682
- ) {
539
+ function serializeSymbol(buffer: Uint8Array, key: string, value: BSONSymbol, index: number) {
683
540
  // Write the type
684
541
  buffer[index++] = constants.BSON_DATA_SYMBOL;
685
542
  // Number of written bytes
686
- const numberOfWrittenBytes = !isArray
687
- ? buffer.write(key, index, undefined, 'utf8')
688
- : buffer.write(key, index, undefined, 'ascii');
543
+ const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
689
544
  // Encode the name
690
545
  index = index + numberOfWrittenBytes;
691
546
  buffer[index++] = 0;
692
547
  // Write the string
693
- const size = buffer.write(value.value, index + 4, undefined, 'utf8') + 1;
548
+ const size = ByteUtils.encodeUTF8Into(buffer, value.value, index + 4) + 1;
694
549
  // Write the size of the string to buffer
695
550
  buffer[index] = size & 0xff;
696
551
  buffer[index + 1] = (size >> 8) & 0xff;
@@ -704,20 +559,18 @@ function serializeSymbol(
704
559
  }
705
560
 
706
561
  function serializeDBRef(
707
- buffer: Buffer,
562
+ buffer: Uint8Array,
708
563
  key: string,
709
564
  value: DBRef,
710
565
  index: number,
711
566
  depth: number,
712
567
  serializeFunctions: boolean,
713
- isArray?: boolean
568
+ path: Set<Document>
714
569
  ) {
715
570
  // Write the type
716
571
  buffer[index++] = constants.BSON_DATA_OBJECT;
717
572
  // Number of written bytes
718
- const numberOfWrittenBytes = !isArray
719
- ? buffer.write(key, index, undefined, 'utf8')
720
- : buffer.write(key, index, undefined, 'ascii');
573
+ const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
721
574
 
722
575
  // Encode the name
723
576
  index = index + numberOfWrittenBytes;
@@ -734,7 +587,16 @@ function serializeDBRef(
734
587
  }
735
588
 
736
589
  output = Object.assign(output, value.fields);
737
- const endIndex = serializeInto(buffer, output, false, index, depth + 1, serializeFunctions);
590
+ const endIndex = serializeInto(
591
+ buffer,
592
+ output,
593
+ false,
594
+ index,
595
+ depth + 1,
596
+ serializeFunctions,
597
+ true,
598
+ path
599
+ );
738
600
 
739
601
  // Calculate object size
740
602
  const size = endIndex - startIndex;
@@ -748,20 +610,50 @@ function serializeDBRef(
748
610
  }
749
611
 
750
612
  export function serializeInto(
751
- buffer: Buffer,
613
+ buffer: Uint8Array,
752
614
  object: Document,
753
- checkKeys = false,
754
- startingIndex = 0,
755
- depth = 0,
756
- serializeFunctions = false,
757
- ignoreUndefined = true,
758
- path: Document[] = []
615
+ checkKeys: boolean,
616
+ startingIndex: number,
617
+ depth: number,
618
+ serializeFunctions: boolean,
619
+ ignoreUndefined: boolean,
620
+ path: Set<Document> | null
759
621
  ): number {
760
- startingIndex = startingIndex || 0;
761
- path = path || [];
622
+ if (path == null) {
623
+ // We are at the root input
624
+ if (object == null) {
625
+ // ONLY the root should turn into an empty document
626
+ // BSON Empty document has a size of 5 (LE)
627
+ buffer[0] = 0x05;
628
+ buffer[1] = 0x00;
629
+ buffer[2] = 0x00;
630
+ buffer[3] = 0x00;
631
+ // All documents end with null terminator
632
+ buffer[4] = 0x00;
633
+ return 5;
634
+ }
635
+
636
+ if (Array.isArray(object)) {
637
+ throw new BSONError('serialize does not support an array as the root input');
638
+ }
639
+ if (typeof object !== 'object') {
640
+ throw new BSONError('serialize does not support non-object as the root input');
641
+ } else if ('_bsontype' in object && typeof object._bsontype === 'string') {
642
+ throw new BSONError(`BSON types cannot be serialized as a document`);
643
+ } else if (
644
+ isDate(object) ||
645
+ isRegExp(object) ||
646
+ isUint8Array(object) ||
647
+ isAnyArrayBuffer(object)
648
+ ) {
649
+ throw new BSONError(`date, regexp, typedarray, and arraybuffer cannot be BSON documents`);
650
+ }
651
+
652
+ path = new Set();
653
+ }
762
654
 
763
655
  // Push the object to the path
764
- path.push(object);
656
+ path.add(object);
765
657
 
766
658
  // Start place to serialize into
767
659
  let index = startingIndex + 4;
@@ -779,26 +671,24 @@ export function serializeInto(
779
671
  }
780
672
 
781
673
  if (typeof value === 'string') {
782
- index = serializeString(buffer, key, value, index, true);
674
+ index = serializeString(buffer, key, value, index);
783
675
  } else if (typeof value === 'number') {
784
- index = serializeNumber(buffer, key, value, index, true);
676
+ index = serializeNumber(buffer, key, value, index);
785
677
  } else if (typeof value === 'bigint') {
786
678
  throw new BSONTypeError('Unsupported type BigInt, please use Decimal128');
787
679
  } else if (typeof value === 'boolean') {
788
- index = serializeBoolean(buffer, key, value, index, true);
680
+ index = serializeBoolean(buffer, key, value, index);
789
681
  } else if (value instanceof Date || isDate(value)) {
790
- index = serializeDate(buffer, key, value, index, true);
682
+ index = serializeDate(buffer, key, value, index);
791
683
  } else if (value === undefined) {
792
- index = serializeNull(buffer, key, value, index, true);
684
+ index = serializeNull(buffer, key, value, index);
793
685
  } else if (value === null) {
794
- index = serializeNull(buffer, key, value, index, true);
795
- } else if (value['_bsontype'] === 'ObjectId' || value['_bsontype'] === 'ObjectID') {
796
- index = serializeObjectId(buffer, key, value, index, true);
686
+ index = serializeNull(buffer, key, value, index);
797
687
  } else if (isUint8Array(value)) {
798
- index = serializeBuffer(buffer, key, value, index, true);
688
+ index = serializeBuffer(buffer, key, value, index);
799
689
  } else if (value instanceof RegExp || isRegExp(value)) {
800
- index = serializeRegExp(buffer, key, value, index, true);
801
- } else if (typeof value === 'object' && value['_bsontype'] == null) {
690
+ index = serializeRegExp(buffer, key, value, index);
691
+ } else if (typeof value === 'object' && value._bsontype == null) {
802
692
  index = serializeObject(
803
693
  buffer,
804
694
  key,
@@ -808,22 +698,21 @@ export function serializeInto(
808
698
  depth,
809
699
  serializeFunctions,
810
700
  ignoreUndefined,
811
- true,
812
701
  path
813
702
  );
814
- } else if (
815
- typeof value === 'object' &&
816
- isBSONType(value) &&
817
- value._bsontype === 'Decimal128'
818
- ) {
819
- index = serializeDecimal128(buffer, key, value, index, true);
820
- } else if (value['_bsontype'] === 'Long' || value['_bsontype'] === 'Timestamp') {
821
- index = serializeLong(buffer, key, value, index, true);
822
- } else if (value['_bsontype'] === 'Double') {
823
- index = serializeDouble(buffer, key, value, index, true);
703
+ } else if (typeof value === 'object' && value[Symbol.for('@@mdb.bson.version')] == null) {
704
+ throw new BSONError('Unsupported BSON version, bson types must be from bson 5.0 or later');
705
+ } else if (value._bsontype === 'ObjectId') {
706
+ index = serializeObjectId(buffer, key, value, index);
707
+ } else if (value._bsontype === 'Decimal128') {
708
+ index = serializeDecimal128(buffer, key, value, index);
709
+ } else if (value._bsontype === 'Long' || value._bsontype === 'Timestamp') {
710
+ index = serializeLong(buffer, key, value, index);
711
+ } else if (value._bsontype === 'Double') {
712
+ index = serializeDouble(buffer, key, value, index);
824
713
  } else if (typeof value === 'function' && serializeFunctions) {
825
- index = serializeFunction(buffer, key, value, index, checkKeys, depth, true);
826
- } else if (value['_bsontype'] === 'Code') {
714
+ index = serializeFunction(buffer, key, value, index);
715
+ } else if (value._bsontype === 'Code') {
827
716
  index = serializeCode(
828
717
  buffer,
829
718
  key,
@@ -833,22 +722,22 @@ export function serializeInto(
833
722
  depth,
834
723
  serializeFunctions,
835
724
  ignoreUndefined,
836
- true
725
+ path
837
726
  );
838
- } else if (value['_bsontype'] === 'Binary') {
839
- index = serializeBinary(buffer, key, value, index, true);
840
- } else if (value['_bsontype'] === 'Symbol') {
841
- index = serializeSymbol(buffer, key, value, index, true);
842
- } else if (value['_bsontype'] === 'DBRef') {
843
- index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions, true);
844
- } else if (value['_bsontype'] === 'BSONRegExp') {
845
- index = serializeBSONRegExp(buffer, key, value, index, true);
846
- } else if (value['_bsontype'] === 'Int32') {
847
- index = serializeInt32(buffer, key, value, index, true);
848
- } else if (value['_bsontype'] === 'MinKey' || value['_bsontype'] === 'MaxKey') {
849
- index = serializeMinMax(buffer, key, value, index, true);
850
- } else if (typeof value['_bsontype'] !== 'undefined') {
851
- throw new BSONTypeError(`Unrecognized or invalid _bsontype: ${String(value['_bsontype'])}`);
727
+ } else if (value._bsontype === 'Binary') {
728
+ index = serializeBinary(buffer, key, value, index);
729
+ } else if (value._bsontype === 'Symbol') {
730
+ index = serializeSymbol(buffer, key, value, index);
731
+ } else if (value._bsontype === 'DBRef') {
732
+ index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions, path);
733
+ } else if (value._bsontype === 'BSONRegExp') {
734
+ index = serializeBSONRegExp(buffer, key, value, index);
735
+ } else if (value._bsontype === 'Int32') {
736
+ index = serializeInt32(buffer, key, value, index);
737
+ } else if (value._bsontype === 'MinKey' || value._bsontype === 'MaxKey') {
738
+ index = serializeMinMax(buffer, key, value, index);
739
+ } else if (typeof value._bsontype !== 'undefined') {
740
+ throw new BSONTypeError(`Unrecognized or invalid _bsontype: ${String(value._bsontype)}`);
852
741
  }
853
742
  }
854
743
  } else if (object instanceof Map || isMap(object)) {
@@ -898,13 +787,11 @@ export function serializeInto(
898
787
  index = serializeDate(buffer, key, value, index);
899
788
  } else if (value === null || (value === undefined && ignoreUndefined === false)) {
900
789
  index = serializeNull(buffer, key, value, index);
901
- } else if (value['_bsontype'] === 'ObjectId' || value['_bsontype'] === 'ObjectID') {
902
- index = serializeObjectId(buffer, key, value, index);
903
790
  } else if (isUint8Array(value)) {
904
791
  index = serializeBuffer(buffer, key, value, index);
905
792
  } else if (value instanceof RegExp || isRegExp(value)) {
906
793
  index = serializeRegExp(buffer, key, value, index);
907
- } else if (type === 'object' && value['_bsontype'] == null) {
794
+ } else if (type === 'object' && value._bsontype == null) {
908
795
  index = serializeObject(
909
796
  buffer,
910
797
  key,
@@ -914,16 +801,19 @@ export function serializeInto(
914
801
  depth,
915
802
  serializeFunctions,
916
803
  ignoreUndefined,
917
- false,
918
804
  path
919
805
  );
920
- } else if (type === 'object' && value['_bsontype'] === 'Decimal128') {
806
+ } else if (typeof value === 'object' && value[Symbol.for('@@mdb.bson.version')] == null) {
807
+ throw new BSONError('Unsupported BSON version, bson types must be from bson 5.0 or later');
808
+ } else if (value._bsontype === 'ObjectId') {
809
+ index = serializeObjectId(buffer, key, value, index);
810
+ } else if (type === 'object' && value._bsontype === 'Decimal128') {
921
811
  index = serializeDecimal128(buffer, key, value, index);
922
- } else if (value['_bsontype'] === 'Long' || value['_bsontype'] === 'Timestamp') {
812
+ } else if (value._bsontype === 'Long' || value._bsontype === 'Timestamp') {
923
813
  index = serializeLong(buffer, key, value, index);
924
- } else if (value['_bsontype'] === 'Double') {
814
+ } else if (value._bsontype === 'Double') {
925
815
  index = serializeDouble(buffer, key, value, index);
926
- } else if (value['_bsontype'] === 'Code') {
816
+ } else if (value._bsontype === 'Code') {
927
817
  index = serializeCode(
928
818
  buffer,
929
819
  key,
@@ -932,24 +822,25 @@ export function serializeInto(
932
822
  checkKeys,
933
823
  depth,
934
824
  serializeFunctions,
935
- ignoreUndefined
825
+ ignoreUndefined,
826
+ path
936
827
  );
937
828
  } else if (typeof value === 'function' && serializeFunctions) {
938
- index = serializeFunction(buffer, key, value, index, checkKeys, depth, serializeFunctions);
939
- } else if (value['_bsontype'] === 'Binary') {
829
+ index = serializeFunction(buffer, key, value, index);
830
+ } else if (value._bsontype === 'Binary') {
940
831
  index = serializeBinary(buffer, key, value, index);
941
- } else if (value['_bsontype'] === 'Symbol') {
832
+ } else if (value._bsontype === 'Symbol') {
942
833
  index = serializeSymbol(buffer, key, value, index);
943
- } else if (value['_bsontype'] === 'DBRef') {
944
- index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions);
945
- } else if (value['_bsontype'] === 'BSONRegExp') {
834
+ } else if (value._bsontype === 'DBRef') {
835
+ index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions, path);
836
+ } else if (value._bsontype === 'BSONRegExp') {
946
837
  index = serializeBSONRegExp(buffer, key, value, index);
947
- } else if (value['_bsontype'] === 'Int32') {
838
+ } else if (value._bsontype === 'Int32') {
948
839
  index = serializeInt32(buffer, key, value, index);
949
- } else if (value['_bsontype'] === 'MinKey' || value['_bsontype'] === 'MaxKey') {
840
+ } else if (value._bsontype === 'MinKey' || value._bsontype === 'MaxKey') {
950
841
  index = serializeMinMax(buffer, key, value, index);
951
- } else if (typeof value['_bsontype'] !== 'undefined') {
952
- throw new BSONTypeError(`Unrecognized or invalid _bsontype: ${String(value['_bsontype'])}`);
842
+ } else if (typeof value._bsontype !== 'undefined') {
843
+ throw new BSONTypeError(`Unrecognized or invalid _bsontype: ${String(value._bsontype)}`);
953
844
  }
954
845
  }
955
846
  } else {
@@ -962,7 +853,7 @@ export function serializeInto(
962
853
  }
963
854
 
964
855
  // Iterate over all the keys
965
- for (const key in object) {
856
+ for (const key of Object.keys(object)) {
966
857
  let value = object[key];
967
858
  // Is there an override value
968
859
  if (typeof value?.toBSON === 'function') {
@@ -1003,13 +894,11 @@ export function serializeInto(
1003
894
  if (ignoreUndefined === false) index = serializeNull(buffer, key, value, index);
1004
895
  } else if (value === null) {
1005
896
  index = serializeNull(buffer, key, value, index);
1006
- } else if (value['_bsontype'] === 'ObjectId' || value['_bsontype'] === 'ObjectID') {
1007
- index = serializeObjectId(buffer, key, value, index);
1008
897
  } else if (isUint8Array(value)) {
1009
898
  index = serializeBuffer(buffer, key, value, index);
1010
899
  } else if (value instanceof RegExp || isRegExp(value)) {
1011
900
  index = serializeRegExp(buffer, key, value, index);
1012
- } else if (type === 'object' && value['_bsontype'] == null) {
901
+ } else if (type === 'object' && value._bsontype == null) {
1013
902
  index = serializeObject(
1014
903
  buffer,
1015
904
  key,
@@ -1019,16 +908,19 @@ export function serializeInto(
1019
908
  depth,
1020
909
  serializeFunctions,
1021
910
  ignoreUndefined,
1022
- false,
1023
911
  path
1024
912
  );
1025
- } else if (type === 'object' && value['_bsontype'] === 'Decimal128') {
913
+ } else if (typeof value === 'object' && value[Symbol.for('@@mdb.bson.version')] == null) {
914
+ throw new BSONError('Unsupported BSON version, bson types must be from bson 5.0 or later');
915
+ } else if (value._bsontype === 'ObjectId') {
916
+ index = serializeObjectId(buffer, key, value, index);
917
+ } else if (type === 'object' && value._bsontype === 'Decimal128') {
1026
918
  index = serializeDecimal128(buffer, key, value, index);
1027
- } else if (value['_bsontype'] === 'Long' || value['_bsontype'] === 'Timestamp') {
919
+ } else if (value._bsontype === 'Long' || value._bsontype === 'Timestamp') {
1028
920
  index = serializeLong(buffer, key, value, index);
1029
- } else if (value['_bsontype'] === 'Double') {
921
+ } else if (value._bsontype === 'Double') {
1030
922
  index = serializeDouble(buffer, key, value, index);
1031
- } else if (value['_bsontype'] === 'Code') {
923
+ } else if (value._bsontype === 'Code') {
1032
924
  index = serializeCode(
1033
925
  buffer,
1034
926
  key,
@@ -1037,30 +929,31 @@ export function serializeInto(
1037
929
  checkKeys,
1038
930
  depth,
1039
931
  serializeFunctions,
1040
- ignoreUndefined
932
+ ignoreUndefined,
933
+ path
1041
934
  );
1042
935
  } else if (typeof value === 'function' && serializeFunctions) {
1043
- index = serializeFunction(buffer, key, value, index, checkKeys, depth, serializeFunctions);
1044
- } else if (value['_bsontype'] === 'Binary') {
936
+ index = serializeFunction(buffer, key, value, index);
937
+ } else if (value._bsontype === 'Binary') {
1045
938
  index = serializeBinary(buffer, key, value, index);
1046
- } else if (value['_bsontype'] === 'Symbol') {
939
+ } else if (value._bsontype === 'Symbol') {
1047
940
  index = serializeSymbol(buffer, key, value, index);
1048
- } else if (value['_bsontype'] === 'DBRef') {
1049
- index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions);
1050
- } else if (value['_bsontype'] === 'BSONRegExp') {
941
+ } else if (value._bsontype === 'DBRef') {
942
+ index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions, path);
943
+ } else if (value._bsontype === 'BSONRegExp') {
1051
944
  index = serializeBSONRegExp(buffer, key, value, index);
1052
- } else if (value['_bsontype'] === 'Int32') {
945
+ } else if (value._bsontype === 'Int32') {
1053
946
  index = serializeInt32(buffer, key, value, index);
1054
- } else if (value['_bsontype'] === 'MinKey' || value['_bsontype'] === 'MaxKey') {
947
+ } else if (value._bsontype === 'MinKey' || value._bsontype === 'MaxKey') {
1055
948
  index = serializeMinMax(buffer, key, value, index);
1056
- } else if (typeof value['_bsontype'] !== 'undefined') {
1057
- throw new BSONTypeError(`Unrecognized or invalid _bsontype: ${String(value['_bsontype'])}`);
949
+ } else if (typeof value._bsontype !== 'undefined') {
950
+ throw new BSONTypeError(`Unrecognized or invalid _bsontype: ${String(value._bsontype)}`);
1058
951
  }
1059
952
  }
1060
953
  }
1061
954
 
1062
955
  // Remove the path
1063
- path.pop();
956
+ path.delete(object);
1064
957
 
1065
958
  // Final padding byte for object
1066
959
  buffer[index++] = 0x00;