bson 7.1.1 → 7.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -2
- package/bson.d.ts +156 -10
- package/lib/bson.bundle.js +479 -453
- package/lib/bson.bundle.js.map +1 -1
- package/lib/bson.cjs +479 -453
- package/lib/bson.cjs.map +1 -1
- package/lib/bson.mjs +479 -453
- package/lib/bson.mjs.map +1 -1
- package/lib/bson.node.mjs +479 -453
- package/lib/bson.node.mjs.map +1 -1
- package/lib/bson.rn.cjs +480 -456
- package/lib/bson.rn.cjs.map +1 -1
- package/package.json +1 -1
- package/src/binary.ts +2 -2
- package/src/bson.ts +6 -3
- package/src/extended_json.ts +63 -22
- package/src/objectid.ts +24 -10
- package/src/parser/calculate_size.ts +75 -68
- package/src/parser/deserializer.ts +227 -61
- package/src/parser/serializer.ts +272 -478
- package/src/timestamp.ts +157 -4
- package/src/utils/byte_utils.ts +8 -0
- package/src/utils/node_byte_utils.ts +12 -0
- package/src/utils/web_byte_utils.ts +43 -0
package/package.json
CHANGED
package/src/binary.ts
CHANGED
|
@@ -134,7 +134,7 @@ export class Binary extends BSONValue {
|
|
|
134
134
|
throw new BSONError('Binary can only be constructed from Uint8Array or number[]');
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
this.sub_type = subType ?? Binary.BSON_BINARY_SUBTYPE_DEFAULT;
|
|
137
|
+
this.sub_type = (subType ?? Binary.BSON_BINARY_SUBTYPE_DEFAULT) & 0xff;
|
|
138
138
|
|
|
139
139
|
if (buffer == null) {
|
|
140
140
|
// create an empty binary buffer
|
|
@@ -279,7 +279,7 @@ export class Binary extends BSONValue {
|
|
|
279
279
|
}
|
|
280
280
|
|
|
281
281
|
throw new BSONError(
|
|
282
|
-
`Binary sub_type "${this.sub_type}" is not supported for converting to UUID. Only
|
|
282
|
+
`Binary sub_type "${this.sub_type}" (${typeof this.sub_type}) is not supported for converting to UUID. Only 0x${Binary.SUBTYPE_UUID.toString(16).padStart(2, '0')} is currently supported.`
|
|
283
283
|
);
|
|
284
284
|
}
|
|
285
285
|
|
package/src/bson.ts
CHANGED
|
@@ -22,7 +22,12 @@ export type { CodeExtended } from './code';
|
|
|
22
22
|
export type { DBRefLike } from './db_ref';
|
|
23
23
|
export type { Decimal128Extended } from './decimal128';
|
|
24
24
|
export type { DoubleExtended } from './double';
|
|
25
|
-
export type {
|
|
25
|
+
export type {
|
|
26
|
+
EJSONOptions,
|
|
27
|
+
EJSONOptionsBase,
|
|
28
|
+
EJSONSerializeOptions,
|
|
29
|
+
EJSONParseOptions
|
|
30
|
+
} from './extended_json';
|
|
26
31
|
export type { Int32Extended } from './int_32';
|
|
27
32
|
export type { LongExtended } from './long';
|
|
28
33
|
export type { MaxKeyExtended } from './max_key';
|
|
@@ -112,7 +117,6 @@ export function serialize(object: Document, options: SerializeOptions = {}): Uin
|
|
|
112
117
|
object,
|
|
113
118
|
checkKeys,
|
|
114
119
|
0,
|
|
115
|
-
0,
|
|
116
120
|
serializeFunctions,
|
|
117
121
|
ignoreUndefined,
|
|
118
122
|
null
|
|
@@ -156,7 +160,6 @@ export function serializeWithBufferAndIndex(
|
|
|
156
160
|
object,
|
|
157
161
|
checkKeys,
|
|
158
162
|
0,
|
|
159
|
-
0,
|
|
160
163
|
serializeFunctions,
|
|
161
164
|
ignoreUndefined,
|
|
162
165
|
null
|
package/src/extended_json.ts
CHANGED
|
@@ -24,7 +24,7 @@ import { BSONSymbol } from './symbol';
|
|
|
24
24
|
import { Timestamp } from './timestamp';
|
|
25
25
|
|
|
26
26
|
/** @public */
|
|
27
|
-
export type
|
|
27
|
+
export type EJSONOptionsBase = {
|
|
28
28
|
/**
|
|
29
29
|
* Output using the Extended JSON v1 spec
|
|
30
30
|
* @defaultValue `false`
|
|
@@ -32,8 +32,22 @@ export type EJSONOptions = {
|
|
|
32
32
|
legacy?: boolean;
|
|
33
33
|
/**
|
|
34
34
|
* Enable Extended JSON's `relaxed` mode, which attempts to return native JS types where possible, rather than BSON types
|
|
35
|
-
* @defaultValue `false`
|
|
35
|
+
* @defaultValue `false`
|
|
36
|
+
*/
|
|
36
37
|
relaxed?: boolean;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/** @public */
|
|
41
|
+
export type EJSONSerializeOptions = EJSONOptionsBase & {
|
|
42
|
+
/**
|
|
43
|
+
* Omits undefined values from the output instead of converting them to null
|
|
44
|
+
* @defaultValue `false`
|
|
45
|
+
*/
|
|
46
|
+
ignoreUndefined?: boolean;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/** @public */
|
|
50
|
+
export type EJSONParseOptions = EJSONOptionsBase & {
|
|
37
51
|
/**
|
|
38
52
|
* Enable native bigint support
|
|
39
53
|
* @defaultValue `false`
|
|
@@ -41,6 +55,9 @@ export type EJSONOptions = {
|
|
|
41
55
|
useBigInt64?: boolean;
|
|
42
56
|
};
|
|
43
57
|
|
|
58
|
+
/** @public */
|
|
59
|
+
export type EJSONOptions = EJSONSerializeOptions & EJSONParseOptions;
|
|
60
|
+
|
|
44
61
|
/** @internal */
|
|
45
62
|
type BSONType =
|
|
46
63
|
| Binary
|
|
@@ -174,12 +191,12 @@ function deserializeValue(value: any, options: EJSONOptions = {}) {
|
|
|
174
191
|
return value;
|
|
175
192
|
}
|
|
176
193
|
|
|
177
|
-
type
|
|
194
|
+
type EJSONSerializeInternalOptions = EJSONSerializeOptions & {
|
|
178
195
|
seenObjects: { obj: unknown; propertyName: string }[];
|
|
179
196
|
};
|
|
180
197
|
|
|
181
198
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
182
|
-
function serializeArray(array: any[], options:
|
|
199
|
+
function serializeArray(array: any[], options: EJSONSerializeInternalOptions): any[] {
|
|
183
200
|
return array.map((v: unknown, index: number) => {
|
|
184
201
|
options.seenObjects.push({ propertyName: `index ${index}`, obj: null });
|
|
185
202
|
try {
|
|
@@ -197,7 +214,7 @@ function getISOString(date: Date) {
|
|
|
197
214
|
}
|
|
198
215
|
|
|
199
216
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
200
|
-
function serializeValue(value: any, options:
|
|
217
|
+
function serializeValue(value: any, options: EJSONSerializeInternalOptions): any {
|
|
201
218
|
if (value instanceof Map || isMap(value)) {
|
|
202
219
|
const obj: Record<string, unknown> = Object.create(null);
|
|
203
220
|
for (const [k, v] of value) {
|
|
@@ -242,7 +259,7 @@ function serializeValue(value: any, options: EJSONSerializeOptions): any {
|
|
|
242
259
|
|
|
243
260
|
if (Array.isArray(value)) return serializeArray(value, options);
|
|
244
261
|
|
|
245
|
-
if (value === undefined) return null;
|
|
262
|
+
if (value === undefined) return options.ignoreUndefined ? undefined : null;
|
|
246
263
|
|
|
247
264
|
if (value instanceof Date || isDate(value)) {
|
|
248
265
|
const dateNum = value.getTime(),
|
|
@@ -326,7 +343,7 @@ const BSON_TYPE_MAPPINGS = {
|
|
|
326
343
|
} as const;
|
|
327
344
|
|
|
328
345
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
329
|
-
function serializeDocument(doc: any, options:
|
|
346
|
+
function serializeDocument(doc: any, options: EJSONSerializeInternalOptions) {
|
|
330
347
|
if (doc == null || typeof doc !== 'object') throw new BSONError('not an object instance');
|
|
331
348
|
|
|
332
349
|
const bsontype: BSONType['_bsontype'] = doc._bsontype;
|
|
@@ -410,7 +427,7 @@ function serializeDocument(doc: any, options: EJSONSerializeOptions) {
|
|
|
410
427
|
* ```
|
|
411
428
|
*/
|
|
412
429
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
413
|
-
function parse(text: string, options?:
|
|
430
|
+
function parse(text: string, options?: EJSONParseOptions): any {
|
|
414
431
|
const ejsonOptions = {
|
|
415
432
|
useBigInt64: options?.useBigInt64 ?? false,
|
|
416
433
|
relaxed: options?.relaxed ?? true,
|
|
@@ -426,6 +443,7 @@ function parse(text: string, options?: EJSONOptions): any {
|
|
|
426
443
|
});
|
|
427
444
|
}
|
|
428
445
|
|
|
446
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
429
447
|
/**
|
|
430
448
|
* Converts a BSON document to an Extended JSON string, optionally replacing values if a replacer
|
|
431
449
|
* function is specified or optionally including only the specified properties if a replacer array
|
|
@@ -447,31 +465,54 @@ function parse(text: string, options?: EJSONOptions): any {
|
|
|
447
465
|
*
|
|
448
466
|
* // prints '{"int32":10}'
|
|
449
467
|
* console.log(EJSON.stringify(doc));
|
|
468
|
+
*
|
|
469
|
+
* // prints '{"int32":{"$numberInt":"10"}}' with 2 space indentation
|
|
470
|
+
* console.log(EJSON.stringify(doc, { relaxed: false }, 2));
|
|
450
471
|
* ```
|
|
451
472
|
*/
|
|
452
473
|
function stringify(
|
|
453
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
454
474
|
value: any,
|
|
455
|
-
|
|
456
|
-
replacer?: (number | string)[] | ((this: any, key: string, value: any) => any) | EJSONOptions,
|
|
475
|
+
replacer?: (number | string)[] | ((this: any, key: string, value: any) => any) | null,
|
|
457
476
|
space?: string | number,
|
|
458
|
-
options?:
|
|
477
|
+
options?: EJSONSerializeOptions
|
|
478
|
+
): string;
|
|
479
|
+
function stringify(
|
|
480
|
+
value: any,
|
|
481
|
+
replacer?: (number | string)[] | ((this: any, key: string, value: any) => any) | null,
|
|
482
|
+
options?: EJSONSerializeOptions
|
|
483
|
+
): string;
|
|
484
|
+
function stringify(value: any, options?: EJSONSerializeOptions, space?: string | number): string;
|
|
485
|
+
function stringify(
|
|
486
|
+
value: any,
|
|
487
|
+
replacerOrOptions?:
|
|
488
|
+
| (number | string)[]
|
|
489
|
+
| ((this: any, key: string, value: any) => any)
|
|
490
|
+
| null
|
|
491
|
+
| EJSONSerializeOptions,
|
|
492
|
+
spaceOrOptions?: string | number | EJSONSerializeOptions,
|
|
493
|
+
options?: EJSONSerializeOptions
|
|
459
494
|
): string {
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
495
|
+
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
496
|
+
|
|
497
|
+
if (spaceOrOptions != null && typeof spaceOrOptions === 'object') {
|
|
498
|
+
options = spaceOrOptions;
|
|
499
|
+
spaceOrOptions = undefined;
|
|
463
500
|
}
|
|
464
|
-
if (
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
501
|
+
if (
|
|
502
|
+
replacerOrOptions != null &&
|
|
503
|
+
typeof replacerOrOptions === 'object' &&
|
|
504
|
+
!Array.isArray(replacerOrOptions)
|
|
505
|
+
) {
|
|
506
|
+
options = replacerOrOptions;
|
|
507
|
+
replacerOrOptions = undefined;
|
|
468
508
|
}
|
|
509
|
+
|
|
469
510
|
const serializeOptions = Object.assign({ relaxed: true, legacy: false }, options, {
|
|
470
511
|
seenObjects: [{ propertyName: '(root)', obj: null }]
|
|
471
512
|
});
|
|
472
513
|
|
|
473
514
|
const doc = serializeValue(value, serializeOptions);
|
|
474
|
-
return JSON.stringify(doc,
|
|
515
|
+
return JSON.stringify(doc, replacerOrOptions as Parameters<JSON['stringify']>[1], spaceOrOptions);
|
|
475
516
|
}
|
|
476
517
|
|
|
477
518
|
/**
|
|
@@ -481,7 +522,7 @@ function stringify(
|
|
|
481
522
|
* @param options - Optional settings passed to the `stringify` function
|
|
482
523
|
*/
|
|
483
524
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
484
|
-
function EJSONserialize(value: any, options?:
|
|
525
|
+
function EJSONserialize(value: any, options?: EJSONSerializeOptions): Document {
|
|
485
526
|
options = options || {};
|
|
486
527
|
return JSON.parse(stringify(value, options));
|
|
487
528
|
}
|
|
@@ -493,7 +534,7 @@ function EJSONserialize(value: any, options?: EJSONOptions): Document {
|
|
|
493
534
|
* @param options - Optional settings passed to the parse method
|
|
494
535
|
*/
|
|
495
536
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
496
|
-
function EJSONdeserialize(ejson: Document, options?:
|
|
537
|
+
function EJSONdeserialize(ejson: Document, options?: EJSONParseOptions): any {
|
|
497
538
|
options = options || {};
|
|
498
539
|
return parse(JSON.stringify(ejson), options);
|
|
499
540
|
}
|
package/src/objectid.ts
CHANGED
|
@@ -4,9 +4,6 @@ import { type InspectFn, defaultInspect } from './parser/utils';
|
|
|
4
4
|
import { ByteUtils } from './utils/byte_utils';
|
|
5
5
|
import { NumberUtils } from './utils/number_utils';
|
|
6
6
|
|
|
7
|
-
// Unique sequence for the current process (initialized on first use)
|
|
8
|
-
let PROCESS_UNIQUE: Uint8Array | null = null;
|
|
9
|
-
|
|
10
7
|
/** ObjectId hexString cache @internal */
|
|
11
8
|
const __idCache = new WeakMap(); // TODO(NODE-6549): convert this to #__id private field when target updated to ES2022
|
|
12
9
|
|
|
@@ -33,7 +30,28 @@ export class ObjectId extends BSONValue {
|
|
|
33
30
|
}
|
|
34
31
|
|
|
35
32
|
/** @internal */
|
|
36
|
-
private static index =
|
|
33
|
+
private static index = 0;
|
|
34
|
+
|
|
35
|
+
/** Unique sequence for the current process (initialized on first use)
|
|
36
|
+
* @internal
|
|
37
|
+
*/
|
|
38
|
+
private static PROCESS_UNIQUE: Uint8Array | null = null;
|
|
39
|
+
|
|
40
|
+
/** @internal */
|
|
41
|
+
private static resetState = (): void => {
|
|
42
|
+
this.index = Math.floor(Math.random() * 0x1000000);
|
|
43
|
+
this.PROCESS_UNIQUE = ByteUtils.randomBytes(5);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
static {
|
|
47
|
+
this.resetState();
|
|
48
|
+
// https://nodejs.org/api/v8.html#startup-snapshot-api
|
|
49
|
+
// @ts-expect-error Node.js types not present since this is an optional API
|
|
50
|
+
const { startupSnapshot } = globalThis?.process?.getBuiltinModule('v8') ?? {};
|
|
51
|
+
if (startupSnapshot?.isBuildingSnapshot()) {
|
|
52
|
+
startupSnapshot?.addDeserializeCallback(this.resetState);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
37
55
|
|
|
38
56
|
static cacheHexString: boolean;
|
|
39
57
|
|
|
@@ -178,7 +196,7 @@ export class ObjectId extends BSONValue {
|
|
|
178
196
|
* @internal
|
|
179
197
|
*/
|
|
180
198
|
private static getInc(): number {
|
|
181
|
-
return (ObjectId.index = (ObjectId.index + 1) %
|
|
199
|
+
return (ObjectId.index = (ObjectId.index + 1) % 0x1000000);
|
|
182
200
|
}
|
|
183
201
|
|
|
184
202
|
/**
|
|
@@ -197,12 +215,8 @@ export class ObjectId extends BSONValue {
|
|
|
197
215
|
// 4-byte timestamp
|
|
198
216
|
NumberUtils.setInt32BE(buffer, 0, time);
|
|
199
217
|
|
|
200
|
-
// set PROCESS_UNIQUE if yet not initialized
|
|
201
|
-
if (PROCESS_UNIQUE === null) {
|
|
202
|
-
PROCESS_UNIQUE = ByteUtils.randomBytes(5);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
218
|
// 5-byte process unique
|
|
219
|
+
const PROCESS_UNIQUE = this.PROCESS_UNIQUE!;
|
|
206
220
|
buffer[4] = PROCESS_UNIQUE[0];
|
|
207
221
|
buffer[5] = PROCESS_UNIQUE[1];
|
|
208
222
|
buffer[6] = PROCESS_UNIQUE[2];
|
|
@@ -10,43 +10,64 @@ export function internalCalculateObjectSize(
|
|
|
10
10
|
serializeFunctions?: boolean,
|
|
11
11
|
ignoreUndefined?: boolean
|
|
12
12
|
): number {
|
|
13
|
-
|
|
13
|
+
// Each stack entry carries its own ignoreUndefined so DBRef fields can force ignoreUndefined=true
|
|
14
|
+
// regardless of the caller's setting, matching the behavior of serializeInto.
|
|
15
|
+
const objectStack: Array<{ obj: Document; ignoreUndefined: boolean }> = [
|
|
16
|
+
{ obj: object, ignoreUndefined: ignoreUndefined ?? false }
|
|
17
|
+
];
|
|
18
|
+
let total = 0;
|
|
14
19
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
i.toString(),
|
|
19
|
-
object[i],
|
|
20
|
-
serializeFunctions,
|
|
21
|
-
true,
|
|
22
|
-
ignoreUndefined
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
} else {
|
|
26
|
-
// If we have toBSON defined, override the current object
|
|
20
|
+
while (objectStack.length > 0) {
|
|
21
|
+
const { obj, ignoreUndefined: frameIgnoreUndefined } = objectStack.pop()!;
|
|
22
|
+
total += 5; // 4-byte size field + null terminator
|
|
27
23
|
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
const isObjArray = Array.isArray(obj);
|
|
25
|
+
let target = obj;
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
|
+
if (!isObjArray && typeof (obj as any)?.toBSON === 'function') {
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
|
+
target = (obj as any).toBSON();
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
if (isObjArray) {
|
|
33
|
+
const array = target as unknown[];
|
|
34
|
+
for (let i = 0; i < array.length; i++) {
|
|
35
|
+
total += calculateElementSize(
|
|
36
|
+
i.toString(),
|
|
37
|
+
array[i],
|
|
38
|
+
serializeFunctions,
|
|
39
|
+
true,
|
|
40
|
+
frameIgnoreUndefined,
|
|
41
|
+
objectStack
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
} else {
|
|
45
|
+
for (const key of Object.keys(target)) {
|
|
46
|
+
total += calculateElementSize(
|
|
47
|
+
key,
|
|
48
|
+
target[key],
|
|
49
|
+
serializeFunctions,
|
|
50
|
+
false,
|
|
51
|
+
frameIgnoreUndefined,
|
|
52
|
+
objectStack
|
|
53
|
+
);
|
|
54
|
+
}
|
|
35
55
|
}
|
|
36
56
|
}
|
|
37
57
|
|
|
38
|
-
return
|
|
58
|
+
return total;
|
|
39
59
|
}
|
|
40
60
|
|
|
41
61
|
/** @internal */
|
|
42
|
-
function
|
|
62
|
+
function calculateElementSize(
|
|
43
63
|
name: string,
|
|
44
64
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
45
65
|
value: any,
|
|
46
66
|
serializeFunctions = false,
|
|
47
67
|
isArray = false,
|
|
48
|
-
ignoreUndefined = false
|
|
49
|
-
|
|
68
|
+
ignoreUndefined = false,
|
|
69
|
+
objectStack: Array<{ obj: Document; ignoreUndefined: boolean }>
|
|
70
|
+
): number {
|
|
50
71
|
// If we have toBSON defined, override the current object
|
|
51
72
|
if (typeof value?.toBSON === 'function') {
|
|
52
73
|
value = value.toBSON();
|
|
@@ -63,20 +84,19 @@ function calculateElement(
|
|
|
63
84
|
) {
|
|
64
85
|
if (value >= constants.BSON_INT32_MIN && value <= constants.BSON_INT32_MAX) {
|
|
65
86
|
// 32 bit
|
|
66
|
-
return
|
|
87
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (4 + 1);
|
|
67
88
|
} else {
|
|
68
|
-
return
|
|
89
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (8 + 1);
|
|
69
90
|
}
|
|
70
91
|
} else {
|
|
71
92
|
// 64 bit
|
|
72
|
-
return
|
|
93
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (8 + 1);
|
|
73
94
|
}
|
|
74
95
|
case 'undefined':
|
|
75
|
-
if (isArray || !ignoreUndefined)
|
|
76
|
-
return (name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) + 1;
|
|
96
|
+
if (isArray || !ignoreUndefined) return ByteUtils.utf8ByteLength(name) + 1 + 1;
|
|
77
97
|
return 0;
|
|
78
98
|
case 'boolean':
|
|
79
|
-
return
|
|
99
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (1 + 1);
|
|
80
100
|
case 'object':
|
|
81
101
|
if (
|
|
82
102
|
value != null &&
|
|
@@ -85,42 +105,42 @@ function calculateElement(
|
|
|
85
105
|
) {
|
|
86
106
|
throw new BSONVersionError();
|
|
87
107
|
} else if (value == null || value._bsontype === 'MinKey' || value._bsontype === 'MaxKey') {
|
|
88
|
-
return
|
|
108
|
+
return ByteUtils.utf8ByteLength(name) + 1 + 1;
|
|
89
109
|
} else if (value._bsontype === 'ObjectId') {
|
|
90
|
-
return
|
|
110
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (12 + 1);
|
|
91
111
|
} else if (value instanceof Date || isDate(value)) {
|
|
92
|
-
return
|
|
112
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (8 + 1);
|
|
93
113
|
} else if (
|
|
94
114
|
ArrayBuffer.isView(value) ||
|
|
95
115
|
value instanceof ArrayBuffer ||
|
|
96
116
|
isAnyArrayBuffer(value)
|
|
97
117
|
) {
|
|
98
|
-
return (
|
|
99
|
-
(name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) + (1 + 4 + 1) + value.byteLength
|
|
100
|
-
);
|
|
118
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (1 + 4 + 1) + value.byteLength;
|
|
101
119
|
} else if (
|
|
102
120
|
value._bsontype === 'Long' ||
|
|
103
121
|
value._bsontype === 'Double' ||
|
|
104
122
|
value._bsontype === 'Timestamp'
|
|
105
123
|
) {
|
|
106
|
-
return
|
|
124
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (8 + 1);
|
|
107
125
|
} else if (value._bsontype === 'Decimal128') {
|
|
108
|
-
return
|
|
126
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (16 + 1);
|
|
109
127
|
} else if (value._bsontype === 'Code') {
|
|
110
128
|
// Calculate size depending on the availability of a scope
|
|
111
129
|
if (value.scope != null && Object.keys(value.scope).length > 0) {
|
|
130
|
+
objectStack.push({ obj: value.scope, ignoreUndefined });
|
|
112
131
|
return (
|
|
113
|
-
|
|
132
|
+
ByteUtils.utf8ByteLength(name) +
|
|
133
|
+
1 +
|
|
114
134
|
1 +
|
|
115
135
|
4 +
|
|
116
136
|
4 +
|
|
117
137
|
ByteUtils.utf8ByteLength(value.code.toString()) +
|
|
118
|
-
1
|
|
119
|
-
internalCalculateObjectSize(value.scope, serializeFunctions, ignoreUndefined)
|
|
138
|
+
1
|
|
120
139
|
);
|
|
121
140
|
} else {
|
|
122
141
|
return (
|
|
123
|
-
|
|
142
|
+
ByteUtils.utf8ByteLength(name) +
|
|
143
|
+
1 +
|
|
124
144
|
1 +
|
|
125
145
|
4 +
|
|
126
146
|
ByteUtils.utf8ByteLength(value.code.toString()) +
|
|
@@ -131,22 +151,13 @@ function calculateElement(
|
|
|
131
151
|
const binary: Binary = value;
|
|
132
152
|
// Check what kind of subtype we have
|
|
133
153
|
if (binary.sub_type === Binary.SUBTYPE_BYTE_ARRAY) {
|
|
134
|
-
return (
|
|
135
|
-
(name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) +
|
|
136
|
-
(binary.position + 1 + 4 + 1 + 4)
|
|
137
|
-
);
|
|
154
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (binary.position + 1 + 4 + 1 + 4);
|
|
138
155
|
} else {
|
|
139
|
-
return (
|
|
140
|
-
(name != null ? ByteUtils.utf8ByteLength(name) + 1 : 0) + (binary.position + 1 + 4 + 1)
|
|
141
|
-
);
|
|
156
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (binary.position + 1 + 4 + 1);
|
|
142
157
|
}
|
|
143
158
|
} else if (value._bsontype === 'Symbol') {
|
|
144
159
|
return (
|
|
145
|
-
(name
|
|
146
|
-
ByteUtils.utf8ByteLength(value.value) +
|
|
147
|
-
4 +
|
|
148
|
-
1 +
|
|
149
|
-
1
|
|
160
|
+
ByteUtils.utf8ByteLength(name) + 1 + ByteUtils.utf8ByteLength(value.value) + 4 + 1 + 1
|
|
150
161
|
);
|
|
151
162
|
} else if (value._bsontype === 'DBRef') {
|
|
152
163
|
// Set up correct object for serialization
|
|
@@ -163,14 +174,13 @@ function calculateElement(
|
|
|
163
174
|
ordered_values['$db'] = value.db;
|
|
164
175
|
}
|
|
165
176
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
internalCalculateObjectSize(ordered_values, serializeFunctions, ignoreUndefined)
|
|
170
|
-
);
|
|
177
|
+
// DBRef fields always use ignoreUndefined=true to match serializeInto behavior.
|
|
178
|
+
objectStack.push({ obj: ordered_values, ignoreUndefined: true });
|
|
179
|
+
return ByteUtils.utf8ByteLength(name) + 1 + 1;
|
|
171
180
|
} else if (value instanceof RegExp || isRegExp(value)) {
|
|
172
181
|
return (
|
|
173
|
-
|
|
182
|
+
ByteUtils.utf8ByteLength(name) +
|
|
183
|
+
1 +
|
|
174
184
|
1 +
|
|
175
185
|
ByteUtils.utf8ByteLength(value.source) +
|
|
176
186
|
1 +
|
|
@@ -181,7 +191,8 @@ function calculateElement(
|
|
|
181
191
|
);
|
|
182
192
|
} else if (value._bsontype === 'BSONRegExp') {
|
|
183
193
|
return (
|
|
184
|
-
|
|
194
|
+
ByteUtils.utf8ByteLength(name) +
|
|
195
|
+
1 +
|
|
185
196
|
1 +
|
|
186
197
|
ByteUtils.utf8ByteLength(value.pattern) +
|
|
187
198
|
1 +
|
|
@@ -189,16 +200,14 @@ function calculateElement(
|
|
|
189
200
|
1
|
|
190
201
|
);
|
|
191
202
|
} else {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
internalCalculateObjectSize(value, serializeFunctions, ignoreUndefined) +
|
|
195
|
-
1
|
|
196
|
-
);
|
|
203
|
+
objectStack.push({ obj: value, ignoreUndefined });
|
|
204
|
+
return ByteUtils.utf8ByteLength(name) + 1 + 1;
|
|
197
205
|
}
|
|
198
206
|
case 'function':
|
|
199
207
|
if (serializeFunctions) {
|
|
200
208
|
return (
|
|
201
|
-
|
|
209
|
+
ByteUtils.utf8ByteLength(name) +
|
|
210
|
+
1 +
|
|
202
211
|
1 +
|
|
203
212
|
4 +
|
|
204
213
|
ByteUtils.utf8ByteLength(value.toString()) +
|
|
@@ -207,12 +216,10 @@ function calculateElement(
|
|
|
207
216
|
}
|
|
208
217
|
return 0;
|
|
209
218
|
case 'bigint':
|
|
210
|
-
return
|
|
219
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (8 + 1);
|
|
211
220
|
case 'symbol':
|
|
212
221
|
return 0;
|
|
213
222
|
default:
|
|
214
223
|
throw new BSONError(`Unrecognized JS type: ${typeof value}`);
|
|
215
224
|
}
|
|
216
|
-
|
|
217
|
-
return 0;
|
|
218
225
|
}
|