bson 7.2.0 → 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 +129 -5
- package/lib/bson.bundle.js +452 -452
- package/lib/bson.bundle.js.map +1 -1
- package/lib/bson.cjs +452 -452
- package/lib/bson.cjs.map +1 -1
- package/lib/bson.mjs +452 -452
- package/lib/bson.mjs.map +1 -1
- package/lib/bson.node.mjs +452 -452
- package/lib/bson.node.mjs.map +1 -1
- package/lib/bson.rn.cjs +453 -455
- package/lib/bson.rn.cjs.map +1 -1
- package/package.json +1 -1
- package/src/binary.ts +2 -2
- package/src/bson.ts +0 -2
- package/src/extended_json.ts +33 -12
- 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/lib/bson.cjs
CHANGED
|
@@ -698,7 +698,7 @@ class Binary extends BSONValue {
|
|
|
698
698
|
!Array.isArray(buffer)) {
|
|
699
699
|
throw new BSONError('Binary can only be constructed from Uint8Array or number[]');
|
|
700
700
|
}
|
|
701
|
-
this.sub_type = subType ?? Binary.BSON_BINARY_SUBTYPE_DEFAULT;
|
|
701
|
+
this.sub_type = (subType ?? Binary.BSON_BINARY_SUBTYPE_DEFAULT) & 0xff;
|
|
702
702
|
if (buffer == null) {
|
|
703
703
|
this.buffer = ByteUtils.allocate(Binary.BUFFER_SIZE);
|
|
704
704
|
this.position = 0;
|
|
@@ -804,7 +804,7 @@ class Binary extends BSONValue {
|
|
|
804
804
|
if (this.sub_type === Binary.SUBTYPE_UUID) {
|
|
805
805
|
return new UUID(this.buffer.subarray(0, this.position));
|
|
806
806
|
}
|
|
807
|
-
throw new BSONError(`Binary sub_type "${this.sub_type}" is not supported for converting to UUID. Only
|
|
807
|
+
throw new BSONError(`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.`);
|
|
808
808
|
}
|
|
809
809
|
static createFromHexString(hex, subType) {
|
|
810
810
|
return new Binary(ByteUtils.fromHex(hex), subType);
|
|
@@ -2593,13 +2593,24 @@ class MinKey extends BSONValue {
|
|
|
2593
2593
|
}
|
|
2594
2594
|
}
|
|
2595
2595
|
|
|
2596
|
-
let PROCESS_UNIQUE = null;
|
|
2597
2596
|
const __idCache = new WeakMap();
|
|
2598
2597
|
class ObjectId extends BSONValue {
|
|
2599
2598
|
get _bsontype() {
|
|
2600
2599
|
return 'ObjectId';
|
|
2601
2600
|
}
|
|
2602
|
-
static index =
|
|
2601
|
+
static index = 0;
|
|
2602
|
+
static PROCESS_UNIQUE = null;
|
|
2603
|
+
static resetState = () => {
|
|
2604
|
+
this.index = Math.floor(Math.random() * 0x1000000);
|
|
2605
|
+
this.PROCESS_UNIQUE = ByteUtils.randomBytes(5);
|
|
2606
|
+
};
|
|
2607
|
+
static {
|
|
2608
|
+
this.resetState();
|
|
2609
|
+
const { startupSnapshot } = globalThis?.process?.getBuiltinModule('v8') ?? {};
|
|
2610
|
+
if (startupSnapshot?.isBuildingSnapshot()) {
|
|
2611
|
+
startupSnapshot?.addDeserializeCallback(this.resetState);
|
|
2612
|
+
}
|
|
2613
|
+
}
|
|
2603
2614
|
static cacheHexString;
|
|
2604
2615
|
buffer;
|
|
2605
2616
|
constructor(inputId) {
|
|
@@ -2676,7 +2687,7 @@ class ObjectId extends BSONValue {
|
|
|
2676
2687
|
return hexString;
|
|
2677
2688
|
}
|
|
2678
2689
|
static getInc() {
|
|
2679
|
-
return (ObjectId.index = (ObjectId.index + 1) %
|
|
2690
|
+
return (ObjectId.index = (ObjectId.index + 1) % 0x1000000);
|
|
2680
2691
|
}
|
|
2681
2692
|
static generate(time) {
|
|
2682
2693
|
if ('number' !== typeof time) {
|
|
@@ -2685,9 +2696,7 @@ class ObjectId extends BSONValue {
|
|
|
2685
2696
|
const inc = ObjectId.getInc();
|
|
2686
2697
|
const buffer = ByteUtils.allocateUnsafe(12);
|
|
2687
2698
|
NumberUtils.setInt32BE(buffer, 0, time);
|
|
2688
|
-
|
|
2689
|
-
PROCESS_UNIQUE = ByteUtils.randomBytes(5);
|
|
2690
|
-
}
|
|
2699
|
+
const PROCESS_UNIQUE = this.PROCESS_UNIQUE;
|
|
2691
2700
|
buffer[4] = PROCESS_UNIQUE[0];
|
|
2692
2701
|
buffer[5] = PROCESS_UNIQUE[1];
|
|
2693
2702
|
buffer[6] = PROCESS_UNIQUE[2];
|
|
@@ -2805,23 +2814,33 @@ class ObjectId extends BSONValue {
|
|
|
2805
2814
|
}
|
|
2806
2815
|
|
|
2807
2816
|
function internalCalculateObjectSize(object, serializeFunctions, ignoreUndefined) {
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
+
const objectStack = [
|
|
2818
|
+
{ obj: object, ignoreUndefined: ignoreUndefined ?? false }
|
|
2819
|
+
];
|
|
2820
|
+
let total = 0;
|
|
2821
|
+
while (objectStack.length > 0) {
|
|
2822
|
+
const { obj, ignoreUndefined: frameIgnoreUndefined } = objectStack.pop();
|
|
2823
|
+
total += 5;
|
|
2824
|
+
const isObjArray = Array.isArray(obj);
|
|
2825
|
+
let target = obj;
|
|
2826
|
+
if (!isObjArray && typeof obj?.toBSON === 'function') {
|
|
2827
|
+
target = obj.toBSON();
|
|
2828
|
+
}
|
|
2829
|
+
if (isObjArray) {
|
|
2830
|
+
const array = target;
|
|
2831
|
+
for (let i = 0; i < array.length; i++) {
|
|
2832
|
+
total += calculateElementSize(i.toString(), array[i], serializeFunctions, true, frameIgnoreUndefined, objectStack);
|
|
2833
|
+
}
|
|
2817
2834
|
}
|
|
2818
|
-
|
|
2819
|
-
|
|
2835
|
+
else {
|
|
2836
|
+
for (const key of Object.keys(target)) {
|
|
2837
|
+
total += calculateElementSize(key, target[key], serializeFunctions, false, frameIgnoreUndefined, objectStack);
|
|
2838
|
+
}
|
|
2820
2839
|
}
|
|
2821
2840
|
}
|
|
2822
|
-
return
|
|
2841
|
+
return total;
|
|
2823
2842
|
}
|
|
2824
|
-
function
|
|
2843
|
+
function calculateElementSize(name, value, serializeFunctions = false, isArray = false, ignoreUndefined = false, objectStack) {
|
|
2825
2844
|
if (typeof value?.toBSON === 'function') {
|
|
2826
2845
|
value = value.toBSON();
|
|
2827
2846
|
}
|
|
@@ -2833,21 +2852,21 @@ function calculateElement(name, value, serializeFunctions = false, isArray = fal
|
|
|
2833
2852
|
value >= JS_INT_MIN &&
|
|
2834
2853
|
value <= JS_INT_MAX) {
|
|
2835
2854
|
if (value >= BSON_INT32_MIN && value <= BSON_INT32_MAX) {
|
|
2836
|
-
return
|
|
2855
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (4 + 1);
|
|
2837
2856
|
}
|
|
2838
2857
|
else {
|
|
2839
|
-
return
|
|
2858
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (8 + 1);
|
|
2840
2859
|
}
|
|
2841
2860
|
}
|
|
2842
2861
|
else {
|
|
2843
|
-
return
|
|
2862
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (8 + 1);
|
|
2844
2863
|
}
|
|
2845
2864
|
case 'undefined':
|
|
2846
2865
|
if (isArray || !ignoreUndefined)
|
|
2847
|
-
return
|
|
2866
|
+
return ByteUtils.utf8ByteLength(name) + 1 + 1;
|
|
2848
2867
|
return 0;
|
|
2849
2868
|
case 'boolean':
|
|
2850
|
-
return
|
|
2869
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (1 + 1);
|
|
2851
2870
|
case 'object':
|
|
2852
2871
|
if (value != null &&
|
|
2853
2872
|
typeof value._bsontype === 'string' &&
|
|
@@ -2855,39 +2874,41 @@ function calculateElement(name, value, serializeFunctions = false, isArray = fal
|
|
|
2855
2874
|
throw new BSONVersionError();
|
|
2856
2875
|
}
|
|
2857
2876
|
else if (value == null || value._bsontype === 'MinKey' || value._bsontype === 'MaxKey') {
|
|
2858
|
-
return
|
|
2877
|
+
return ByteUtils.utf8ByteLength(name) + 1 + 1;
|
|
2859
2878
|
}
|
|
2860
2879
|
else if (value._bsontype === 'ObjectId') {
|
|
2861
|
-
return
|
|
2880
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (12 + 1);
|
|
2862
2881
|
}
|
|
2863
2882
|
else if (value instanceof Date || isDate(value)) {
|
|
2864
|
-
return
|
|
2883
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (8 + 1);
|
|
2865
2884
|
}
|
|
2866
2885
|
else if (ArrayBuffer.isView(value) ||
|
|
2867
2886
|
value instanceof ArrayBuffer ||
|
|
2868
2887
|
isAnyArrayBuffer(value)) {
|
|
2869
|
-
return
|
|
2888
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (1 + 4 + 1) + value.byteLength;
|
|
2870
2889
|
}
|
|
2871
2890
|
else if (value._bsontype === 'Long' ||
|
|
2872
2891
|
value._bsontype === 'Double' ||
|
|
2873
2892
|
value._bsontype === 'Timestamp') {
|
|
2874
|
-
return
|
|
2893
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (8 + 1);
|
|
2875
2894
|
}
|
|
2876
2895
|
else if (value._bsontype === 'Decimal128') {
|
|
2877
|
-
return
|
|
2896
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (16 + 1);
|
|
2878
2897
|
}
|
|
2879
2898
|
else if (value._bsontype === 'Code') {
|
|
2880
2899
|
if (value.scope != null && Object.keys(value.scope).length > 0) {
|
|
2881
|
-
|
|
2900
|
+
objectStack.push({ obj: value.scope, ignoreUndefined });
|
|
2901
|
+
return (ByteUtils.utf8ByteLength(name) +
|
|
2902
|
+
1 +
|
|
2882
2903
|
1 +
|
|
2883
2904
|
4 +
|
|
2884
2905
|
4 +
|
|
2885
2906
|
ByteUtils.utf8ByteLength(value.code.toString()) +
|
|
2886
|
-
1
|
|
2887
|
-
internalCalculateObjectSize(value.scope, serializeFunctions, ignoreUndefined));
|
|
2907
|
+
1);
|
|
2888
2908
|
}
|
|
2889
2909
|
else {
|
|
2890
|
-
return (
|
|
2910
|
+
return (ByteUtils.utf8ByteLength(name) +
|
|
2911
|
+
1 +
|
|
2891
2912
|
1 +
|
|
2892
2913
|
4 +
|
|
2893
2914
|
ByteUtils.utf8ByteLength(value.code.toString()) +
|
|
@@ -2897,19 +2918,14 @@ function calculateElement(name, value, serializeFunctions = false, isArray = fal
|
|
|
2897
2918
|
else if (value._bsontype === 'Binary') {
|
|
2898
2919
|
const binary = value;
|
|
2899
2920
|
if (binary.sub_type === Binary.SUBTYPE_BYTE_ARRAY) {
|
|
2900
|
-
return (
|
|
2901
|
-
(binary.position + 1 + 4 + 1 + 4));
|
|
2921
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (binary.position + 1 + 4 + 1 + 4);
|
|
2902
2922
|
}
|
|
2903
2923
|
else {
|
|
2904
|
-
return
|
|
2924
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (binary.position + 1 + 4 + 1);
|
|
2905
2925
|
}
|
|
2906
2926
|
}
|
|
2907
2927
|
else if (value._bsontype === 'Symbol') {
|
|
2908
|
-
return ((name
|
|
2909
|
-
ByteUtils.utf8ByteLength(value.value) +
|
|
2910
|
-
4 +
|
|
2911
|
-
1 +
|
|
2912
|
-
1);
|
|
2928
|
+
return (ByteUtils.utf8ByteLength(name) + 1 + ByteUtils.utf8ByteLength(value.value) + 4 + 1 + 1);
|
|
2913
2929
|
}
|
|
2914
2930
|
else if (value._bsontype === 'DBRef') {
|
|
2915
2931
|
const ordered_values = Object.assign({
|
|
@@ -2919,12 +2935,12 @@ function calculateElement(name, value, serializeFunctions = false, isArray = fal
|
|
|
2919
2935
|
if (value.db != null) {
|
|
2920
2936
|
ordered_values['$db'] = value.db;
|
|
2921
2937
|
}
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
internalCalculateObjectSize(ordered_values, serializeFunctions, ignoreUndefined));
|
|
2938
|
+
objectStack.push({ obj: ordered_values, ignoreUndefined: true });
|
|
2939
|
+
return ByteUtils.utf8ByteLength(name) + 1 + 1;
|
|
2925
2940
|
}
|
|
2926
2941
|
else if (value instanceof RegExp || isRegExp(value)) {
|
|
2927
|
-
return (
|
|
2942
|
+
return (ByteUtils.utf8ByteLength(name) +
|
|
2943
|
+
1 +
|
|
2928
2944
|
1 +
|
|
2929
2945
|
ByteUtils.utf8ByteLength(value.source) +
|
|
2930
2946
|
1 +
|
|
@@ -2934,7 +2950,8 @@ function calculateElement(name, value, serializeFunctions = false, isArray = fal
|
|
|
2934
2950
|
1);
|
|
2935
2951
|
}
|
|
2936
2952
|
else if (value._bsontype === 'BSONRegExp') {
|
|
2937
|
-
return (
|
|
2953
|
+
return (ByteUtils.utf8ByteLength(name) +
|
|
2954
|
+
1 +
|
|
2938
2955
|
1 +
|
|
2939
2956
|
ByteUtils.utf8ByteLength(value.pattern) +
|
|
2940
2957
|
1 +
|
|
@@ -2942,13 +2959,13 @@ function calculateElement(name, value, serializeFunctions = false, isArray = fal
|
|
|
2942
2959
|
1);
|
|
2943
2960
|
}
|
|
2944
2961
|
else {
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
1);
|
|
2962
|
+
objectStack.push({ obj: value, ignoreUndefined });
|
|
2963
|
+
return ByteUtils.utf8ByteLength(name) + 1 + 1;
|
|
2948
2964
|
}
|
|
2949
2965
|
case 'function':
|
|
2950
2966
|
if (serializeFunctions) {
|
|
2951
|
-
return (
|
|
2967
|
+
return (ByteUtils.utf8ByteLength(name) +
|
|
2968
|
+
1 +
|
|
2952
2969
|
1 +
|
|
2953
2970
|
4 +
|
|
2954
2971
|
ByteUtils.utf8ByteLength(value.toString()) +
|
|
@@ -2956,7 +2973,7 @@ function calculateElement(name, value, serializeFunctions = false, isArray = fal
|
|
|
2956
2973
|
}
|
|
2957
2974
|
return 0;
|
|
2958
2975
|
case 'bigint':
|
|
2959
|
-
return
|
|
2976
|
+
return ByteUtils.utf8ByteLength(name) + 1 + (8 + 1);
|
|
2960
2977
|
case 'symbol':
|
|
2961
2978
|
return 0;
|
|
2962
2979
|
default:
|
|
@@ -3172,7 +3189,28 @@ function internalDeserialize(buffer, options, isArray) {
|
|
|
3172
3189
|
return deserializeObject(buffer, index, options, isArray);
|
|
3173
3190
|
}
|
|
3174
3191
|
const allowedDBRefKeys = /^\$ref$|^\$id$|^\$db$/;
|
|
3192
|
+
function assignValue(dest, name, value) {
|
|
3193
|
+
if (name === '__proto__') {
|
|
3194
|
+
Object.defineProperty(dest, name, {
|
|
3195
|
+
value,
|
|
3196
|
+
writable: true,
|
|
3197
|
+
enumerable: true,
|
|
3198
|
+
configurable: true
|
|
3199
|
+
});
|
|
3200
|
+
}
|
|
3201
|
+
else {
|
|
3202
|
+
dest[name] = value;
|
|
3203
|
+
}
|
|
3204
|
+
}
|
|
3205
|
+
function toPotentialDbRef(doc) {
|
|
3206
|
+
if (isDBRefLike(doc)) {
|
|
3207
|
+
const { $ref, $id, $db, ...fields } = doc;
|
|
3208
|
+
return new DBRef($ref, $id, $db, fields);
|
|
3209
|
+
}
|
|
3210
|
+
return doc;
|
|
3211
|
+
}
|
|
3175
3212
|
function deserializeObject(buffer, index, options, isArray = false) {
|
|
3213
|
+
options = { ...options };
|
|
3176
3214
|
const fieldsAsRaw = options['fieldsAsRaw'] == null ? null : options['fieldsAsRaw'];
|
|
3177
3215
|
const raw = options['raw'] == null ? false : options['raw'];
|
|
3178
3216
|
const bsonRegExp = typeof options['bsonRegExp'] === 'boolean' ? options['bsonRegExp'] : false;
|
|
@@ -3223,31 +3261,87 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
3223
3261
|
index += 4;
|
|
3224
3262
|
if (size < 5 || size > buffer.length)
|
|
3225
3263
|
throw new BSONError('corrupt bson message');
|
|
3226
|
-
const
|
|
3264
|
+
const rootObject = isArray ? [] : {};
|
|
3227
3265
|
let arrayIndex = 0;
|
|
3228
3266
|
let isPossibleDBRef = isArray ? false : null;
|
|
3267
|
+
let currentFrame = null;
|
|
3268
|
+
let currentDest = rootObject;
|
|
3269
|
+
let currentIsArray = isArray;
|
|
3229
3270
|
while (true) {
|
|
3230
3271
|
const elementType = buffer[index++];
|
|
3231
|
-
if (elementType === 0)
|
|
3232
|
-
|
|
3272
|
+
if (elementType === 0) {
|
|
3273
|
+
if (currentFrame) {
|
|
3274
|
+
if (index === currentFrame.lastIndex) {
|
|
3275
|
+
const completedFrame = currentFrame;
|
|
3276
|
+
currentFrame = completedFrame.prev;
|
|
3277
|
+
if (currentFrame === null) {
|
|
3278
|
+
currentDest = rootObject;
|
|
3279
|
+
currentIsArray = isArray;
|
|
3280
|
+
}
|
|
3281
|
+
else {
|
|
3282
|
+
currentDest = currentFrame.holdingDocument;
|
|
3283
|
+
currentIsArray = currentFrame.isArray;
|
|
3284
|
+
}
|
|
3285
|
+
let result = completedFrame.holdingDocument;
|
|
3286
|
+
switch (completedFrame.elementType) {
|
|
3287
|
+
case BSON_DATA_OBJECT:
|
|
3288
|
+
if (completedFrame.isPossibleDBRef) {
|
|
3289
|
+
result = toPotentialDbRef(result);
|
|
3290
|
+
}
|
|
3291
|
+
break;
|
|
3292
|
+
case BSON_DATA_ARRAY:
|
|
3293
|
+
break;
|
|
3294
|
+
case BSON_DATA_CODE_W_SCOPE:
|
|
3295
|
+
result = new Code(completedFrame.functionString, completedFrame.holdingDocument);
|
|
3296
|
+
break;
|
|
3297
|
+
default:
|
|
3298
|
+
throw new BSONError('Unexpected element type in frame stack');
|
|
3299
|
+
}
|
|
3300
|
+
assignValue(currentDest, completedFrame.propertyName, result);
|
|
3301
|
+
continue;
|
|
3302
|
+
}
|
|
3303
|
+
else {
|
|
3304
|
+
if (currentFrame.elementType === BSON_DATA_ARRAY) {
|
|
3305
|
+
throw new BSONError('corrupted array bson');
|
|
3306
|
+
}
|
|
3307
|
+
throw new BSONError('Bad BSON Document: object not properly terminated');
|
|
3308
|
+
}
|
|
3309
|
+
}
|
|
3310
|
+
else {
|
|
3311
|
+
break;
|
|
3312
|
+
}
|
|
3313
|
+
}
|
|
3233
3314
|
let i = index;
|
|
3234
3315
|
while (buffer[i] !== 0x00 && i < buffer.length) {
|
|
3235
3316
|
i++;
|
|
3236
3317
|
}
|
|
3237
3318
|
if (i >= buffer.byteLength)
|
|
3238
3319
|
throw new BSONError('Bad BSON Document: illegal CString');
|
|
3239
|
-
const name =
|
|
3240
|
-
|
|
3241
|
-
|
|
3320
|
+
const name = currentIsArray
|
|
3321
|
+
? currentFrame !== null
|
|
3322
|
+
? currentFrame.arrayIndex++
|
|
3323
|
+
: arrayIndex++
|
|
3324
|
+
: ByteUtils.toUTF8(buffer, index, i, false);
|
|
3325
|
+
let shouldValidateKey;
|
|
3326
|
+
if (currentFrame !== null) {
|
|
3327
|
+
shouldValidateKey = currentFrame.validationSetting;
|
|
3328
|
+
}
|
|
3329
|
+
else if (globalUTFValidation || utf8KeysSet?.has(name)) {
|
|
3242
3330
|
shouldValidateKey = validationSetting;
|
|
3243
3331
|
}
|
|
3244
3332
|
else {
|
|
3245
3333
|
shouldValidateKey = !validationSetting;
|
|
3246
3334
|
}
|
|
3247
|
-
if (
|
|
3335
|
+
if (currentFrame !== null) {
|
|
3336
|
+
if (currentFrame.isPossibleDBRef !== false && typeof name === 'string' && name[0] === '$') {
|
|
3337
|
+
currentFrame.isPossibleDBRef = allowedDBRefKeys.test(name);
|
|
3338
|
+
}
|
|
3339
|
+
}
|
|
3340
|
+
else if (isPossibleDBRef !== false && name[0] === '$') {
|
|
3248
3341
|
isPossibleDBRef = allowedDBRefKeys.test(name);
|
|
3249
3342
|
}
|
|
3250
3343
|
let value;
|
|
3344
|
+
let isDeferredValue = false;
|
|
3251
3345
|
index = i + 1;
|
|
3252
3346
|
if (elementType === BSON_DATA_STRING) {
|
|
3253
3347
|
const stringSize = NumberUtils.getInt32LE(buffer, index);
|
|
@@ -3293,39 +3387,58 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
3293
3387
|
value = buffer[index++] === 1;
|
|
3294
3388
|
}
|
|
3295
3389
|
else if (elementType === BSON_DATA_OBJECT) {
|
|
3296
|
-
const _index = index;
|
|
3297
3390
|
const objectSize = NumberUtils.getInt32LE(buffer, index);
|
|
3298
|
-
if (objectSize
|
|
3391
|
+
if (objectSize < 5 || objectSize > buffer.length - index)
|
|
3299
3392
|
throw new BSONError('bad embedded document length in bson');
|
|
3300
|
-
if (raw) {
|
|
3393
|
+
if (raw || (currentFrame?.raw ?? false)) {
|
|
3301
3394
|
value = buffer.subarray(index, index + objectSize);
|
|
3395
|
+
index = index + objectSize;
|
|
3302
3396
|
}
|
|
3303
3397
|
else {
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3398
|
+
isDeferredValue = true;
|
|
3399
|
+
const objectFrame = {
|
|
3400
|
+
holdingDocument: {},
|
|
3401
|
+
elementType: BSON_DATA_OBJECT,
|
|
3402
|
+
propertyName: name,
|
|
3403
|
+
functionString: null,
|
|
3404
|
+
lastIndex: index + objectSize,
|
|
3405
|
+
isArray: false,
|
|
3406
|
+
arrayIndex: 0,
|
|
3407
|
+
raw: false,
|
|
3408
|
+
isPossibleDBRef: null,
|
|
3409
|
+
validationSetting: shouldValidateKey,
|
|
3410
|
+
prev: currentFrame
|
|
3411
|
+
};
|
|
3412
|
+
currentFrame = objectFrame;
|
|
3413
|
+
currentDest = objectFrame.holdingDocument;
|
|
3414
|
+
currentIsArray = false;
|
|
3415
|
+
index = index + 4;
|
|
3309
3416
|
}
|
|
3310
|
-
index = index + objectSize;
|
|
3311
3417
|
}
|
|
3312
3418
|
else if (elementType === BSON_DATA_ARRAY) {
|
|
3313
|
-
const _index = index;
|
|
3314
3419
|
const objectSize = NumberUtils.getInt32LE(buffer, index);
|
|
3315
|
-
|
|
3420
|
+
if (objectSize < 5 || objectSize > buffer.length - index)
|
|
3421
|
+
throw new BSONError('bad embedded array length in bson');
|
|
3316
3422
|
const stopIndex = index + objectSize;
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3423
|
+
const arrayRaw = !!(fieldsAsRaw && fieldsAsRaw[name]) || (currentFrame?.raw ?? false);
|
|
3424
|
+
isDeferredValue = true;
|
|
3425
|
+
const arrayFrame = {
|
|
3426
|
+
holdingDocument: [],
|
|
3427
|
+
elementType: BSON_DATA_ARRAY,
|
|
3428
|
+
propertyName: name,
|
|
3429
|
+
functionString: null,
|
|
3430
|
+
lastIndex: stopIndex,
|
|
3431
|
+
isArray: true,
|
|
3432
|
+
arrayIndex: 0,
|
|
3433
|
+
raw: arrayRaw,
|
|
3434
|
+
isPossibleDBRef: false,
|
|
3435
|
+
validationSetting: shouldValidateKey,
|
|
3436
|
+
prev: currentFrame
|
|
3437
|
+
};
|
|
3438
|
+
currentFrame = arrayFrame;
|
|
3439
|
+
currentDest = arrayFrame.holdingDocument;
|
|
3440
|
+
currentIsArray = true;
|
|
3441
|
+
index = index + 4;
|
|
3329
3442
|
}
|
|
3330
3443
|
else if (elementType === BSON_DATA_UNDEFINED) {
|
|
3331
3444
|
value = undefined;
|
|
@@ -3497,15 +3610,32 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
3497
3610
|
index = index + stringSize;
|
|
3498
3611
|
const _index = index;
|
|
3499
3612
|
const objectSize = NumberUtils.getInt32LE(buffer, index);
|
|
3500
|
-
|
|
3501
|
-
|
|
3613
|
+
if (objectSize < 5 || objectSize > buffer.length - index)
|
|
3614
|
+
throw new BSONError('bad scope document size in code_w_scope');
|
|
3502
3615
|
if (totalSize < 4 + 4 + objectSize + stringSize) {
|
|
3503
3616
|
throw new BSONError('code_w_scope total size is too short, truncating scope');
|
|
3504
3617
|
}
|
|
3505
3618
|
if (totalSize > 4 + 4 + objectSize + stringSize) {
|
|
3506
3619
|
throw new BSONError('code_w_scope total size is too long, clips outer document');
|
|
3507
3620
|
}
|
|
3508
|
-
|
|
3621
|
+
isDeferredValue = true;
|
|
3622
|
+
const scopeFrame = {
|
|
3623
|
+
holdingDocument: {},
|
|
3624
|
+
elementType: BSON_DATA_CODE_W_SCOPE,
|
|
3625
|
+
propertyName: name,
|
|
3626
|
+
functionString: functionString,
|
|
3627
|
+
lastIndex: _index + objectSize,
|
|
3628
|
+
isArray: false,
|
|
3629
|
+
arrayIndex: 0,
|
|
3630
|
+
raw: false,
|
|
3631
|
+
isPossibleDBRef: null,
|
|
3632
|
+
validationSetting: shouldValidateKey,
|
|
3633
|
+
prev: currentFrame
|
|
3634
|
+
};
|
|
3635
|
+
currentFrame = scopeFrame;
|
|
3636
|
+
currentDest = scopeFrame.holdingDocument;
|
|
3637
|
+
currentIsArray = false;
|
|
3638
|
+
index = index + 4;
|
|
3509
3639
|
}
|
|
3510
3640
|
else if (elementType === BSON_DATA_DBPOINTER) {
|
|
3511
3641
|
const stringSize = NumberUtils.getInt32LE(buffer, index);
|
|
@@ -3526,18 +3656,14 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
3526
3656
|
else {
|
|
3527
3657
|
throw new BSONError(`Detected unknown BSON type ${elementType.toString(16)} for fieldname "${name}"`);
|
|
3528
3658
|
}
|
|
3529
|
-
if (
|
|
3530
|
-
|
|
3531
|
-
value,
|
|
3532
|
-
writable: true,
|
|
3533
|
-
enumerable: true,
|
|
3534
|
-
configurable: true
|
|
3535
|
-
});
|
|
3536
|
-
}
|
|
3537
|
-
else {
|
|
3538
|
-
object[name] = value;
|
|
3659
|
+
if (!isDeferredValue) {
|
|
3660
|
+
assignValue(currentDest, name, value);
|
|
3539
3661
|
}
|
|
3540
3662
|
}
|
|
3663
|
+
if (currentFrame !== null) {
|
|
3664
|
+
throw new BSONError('corrupted bson, more objects expected based on the current document size');
|
|
3665
|
+
}
|
|
3666
|
+
const object = rootObject;
|
|
3541
3667
|
if (size !== index - startIndex) {
|
|
3542
3668
|
if (isArray)
|
|
3543
3669
|
throw new BSONError('corrupt array bson');
|
|
@@ -3545,14 +3671,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
3545
3671
|
}
|
|
3546
3672
|
if (!isPossibleDBRef)
|
|
3547
3673
|
return object;
|
|
3548
|
-
|
|
3549
|
-
const copy = Object.assign({}, object);
|
|
3550
|
-
delete copy.$ref;
|
|
3551
|
-
delete copy.$id;
|
|
3552
|
-
delete copy.$db;
|
|
3553
|
-
return new DBRef(object.$ref, object.$id, object.$db, copy);
|
|
3554
|
-
}
|
|
3555
|
-
return object;
|
|
3674
|
+
return toPotentialDbRef(object);
|
|
3556
3675
|
}
|
|
3557
3676
|
|
|
3558
3677
|
const regexp = /\x00/;
|
|
@@ -3661,7 +3780,7 @@ function serializeMinMax(buffer, key, value, index) {
|
|
|
3661
3780
|
if (value === null) {
|
|
3662
3781
|
buffer[index++] = BSON_DATA_NULL;
|
|
3663
3782
|
}
|
|
3664
|
-
else if (value
|
|
3783
|
+
else if (value[bsonType] === 'MinKey') {
|
|
3665
3784
|
buffer[index++] = BSON_DATA_MIN_KEY;
|
|
3666
3785
|
}
|
|
3667
3786
|
else {
|
|
@@ -3698,19 +3817,6 @@ function serializeBuffer(buffer, key, value, index) {
|
|
|
3698
3817
|
index = index + size;
|
|
3699
3818
|
return index;
|
|
3700
3819
|
}
|
|
3701
|
-
function serializeObject(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, path) {
|
|
3702
|
-
if (path.has(value)) {
|
|
3703
|
-
throw new BSONError('Cannot convert circular structure to BSON');
|
|
3704
|
-
}
|
|
3705
|
-
path.add(value);
|
|
3706
|
-
buffer[index++] = Array.isArray(value) ? BSON_DATA_ARRAY : BSON_DATA_OBJECT;
|
|
3707
|
-
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
|
|
3708
|
-
index = index + numberOfWrittenBytes;
|
|
3709
|
-
buffer[index++] = 0;
|
|
3710
|
-
const endIndex = serializeInto(buffer, value, checkKeys, index, depth + 1, serializeFunctions, ignoreUndefined, path);
|
|
3711
|
-
path.delete(value);
|
|
3712
|
-
return endIndex;
|
|
3713
|
-
}
|
|
3714
3820
|
function serializeDecimal128(buffer, key, value, index) {
|
|
3715
3821
|
buffer[index++] = BSON_DATA_DECIMAL128;
|
|
3716
3822
|
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
|
|
@@ -3722,7 +3828,7 @@ function serializeDecimal128(buffer, key, value, index) {
|
|
|
3722
3828
|
}
|
|
3723
3829
|
function serializeLong(buffer, key, value, index) {
|
|
3724
3830
|
buffer[index++] =
|
|
3725
|
-
value
|
|
3831
|
+
value[bsonType] === 'Long' ? BSON_DATA_LONG : BSON_DATA_TIMESTAMP;
|
|
3726
3832
|
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
|
|
3727
3833
|
index = index + numberOfWrittenBytes;
|
|
3728
3834
|
buffer[index++] = 0;
|
|
@@ -3761,38 +3867,6 @@ function serializeFunction(buffer, key, value, index) {
|
|
|
3761
3867
|
buffer[index++] = 0;
|
|
3762
3868
|
return index;
|
|
3763
3869
|
}
|
|
3764
|
-
function serializeCode(buffer, key, value, index, checkKeys = false, depth = 0, serializeFunctions = false, ignoreUndefined = true, path) {
|
|
3765
|
-
if (value.scope && typeof value.scope === 'object') {
|
|
3766
|
-
buffer[index++] = BSON_DATA_CODE_W_SCOPE;
|
|
3767
|
-
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
|
|
3768
|
-
index = index + numberOfWrittenBytes;
|
|
3769
|
-
buffer[index++] = 0;
|
|
3770
|
-
let startIndex = index;
|
|
3771
|
-
const functionString = value.code;
|
|
3772
|
-
index = index + 4;
|
|
3773
|
-
const codeSize = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
|
|
3774
|
-
NumberUtils.setInt32LE(buffer, index, codeSize);
|
|
3775
|
-
buffer[index + 4 + codeSize - 1] = 0;
|
|
3776
|
-
index = index + codeSize + 4;
|
|
3777
|
-
const endIndex = serializeInto(buffer, value.scope, checkKeys, index, depth + 1, serializeFunctions, ignoreUndefined, path);
|
|
3778
|
-
index = endIndex - 1;
|
|
3779
|
-
const totalSize = endIndex - startIndex;
|
|
3780
|
-
startIndex += NumberUtils.setInt32LE(buffer, startIndex, totalSize);
|
|
3781
|
-
buffer[index++] = 0;
|
|
3782
|
-
}
|
|
3783
|
-
else {
|
|
3784
|
-
buffer[index++] = BSON_DATA_CODE;
|
|
3785
|
-
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
|
|
3786
|
-
index = index + numberOfWrittenBytes;
|
|
3787
|
-
buffer[index++] = 0;
|
|
3788
|
-
const functionString = value.code.toString();
|
|
3789
|
-
const size = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
|
|
3790
|
-
NumberUtils.setInt32LE(buffer, index, size);
|
|
3791
|
-
index = index + 4 + size - 1;
|
|
3792
|
-
buffer[index++] = 0;
|
|
3793
|
-
}
|
|
3794
|
-
return index;
|
|
3795
|
-
}
|
|
3796
3870
|
function serializeBinary(buffer, key, value, index) {
|
|
3797
3871
|
buffer[index++] = BSON_DATA_BINARY;
|
|
3798
3872
|
const numberOfWrittenBytes = ByteUtils.encodeUTF8Into(buffer, key, index);
|
|
@@ -3832,26 +3906,59 @@ function serializeSymbol(buffer, key, value, index) {
|
|
|
3832
3906
|
buffer[index++] = 0;
|
|
3833
3907
|
return index;
|
|
3834
3908
|
}
|
|
3835
|
-
function
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3909
|
+
function makeFrame(sourceObject, objectSizeIndex, codeSizeIndex, prev, checkKeys, ignoreUndefined) {
|
|
3910
|
+
if (Array.isArray(sourceObject)) {
|
|
3911
|
+
return {
|
|
3912
|
+
sourceObject,
|
|
3913
|
+
isArray: true,
|
|
3914
|
+
objectSizeIndex,
|
|
3915
|
+
codeSizeIndex,
|
|
3916
|
+
iterTarget: sourceObject,
|
|
3917
|
+
keys: null,
|
|
3918
|
+
keyIndex: 0,
|
|
3919
|
+
mapIterator: null,
|
|
3920
|
+
prev,
|
|
3921
|
+
checkKeys,
|
|
3922
|
+
ignoreUndefined
|
|
3923
|
+
};
|
|
3924
|
+
}
|
|
3925
|
+
if (sourceObject instanceof Map || isMap(sourceObject)) {
|
|
3926
|
+
return {
|
|
3927
|
+
sourceObject,
|
|
3928
|
+
isArray: false,
|
|
3929
|
+
objectSizeIndex,
|
|
3930
|
+
codeSizeIndex,
|
|
3931
|
+
iterTarget: sourceObject,
|
|
3932
|
+
keys: null,
|
|
3933
|
+
keyIndex: 0,
|
|
3934
|
+
mapIterator: sourceObject.entries(),
|
|
3935
|
+
prev,
|
|
3936
|
+
checkKeys,
|
|
3937
|
+
ignoreUndefined
|
|
3938
|
+
};
|
|
3939
|
+
}
|
|
3940
|
+
let target = sourceObject;
|
|
3941
|
+
if (typeof target?.toBSON === 'function') {
|
|
3942
|
+
target = target.toBSON();
|
|
3943
|
+
if (target != null && typeof target !== 'object') {
|
|
3944
|
+
throw new BSONError('toBSON function did not return an object');
|
|
3945
|
+
}
|
|
3946
|
+
}
|
|
3947
|
+
return {
|
|
3948
|
+
sourceObject,
|
|
3949
|
+
isArray: false,
|
|
3950
|
+
objectSizeIndex,
|
|
3951
|
+
codeSizeIndex,
|
|
3952
|
+
iterTarget: target,
|
|
3953
|
+
keys: Object.keys(target),
|
|
3954
|
+
keyIndex: 0,
|
|
3955
|
+
mapIterator: null,
|
|
3956
|
+
prev,
|
|
3957
|
+
checkKeys,
|
|
3958
|
+
ignoreUndefined
|
|
3844
3959
|
};
|
|
3845
|
-
if (value.db != null) {
|
|
3846
|
-
output.$db = value.db;
|
|
3847
|
-
}
|
|
3848
|
-
output = Object.assign(output, value.fields);
|
|
3849
|
-
const endIndex = serializeInto(buffer, output, false, index, depth + 1, serializeFunctions, true, path);
|
|
3850
|
-
const size = endIndex - startIndex;
|
|
3851
|
-
startIndex += NumberUtils.setInt32LE(buffer, index, size);
|
|
3852
|
-
return endIndex;
|
|
3853
3960
|
}
|
|
3854
|
-
function serializeInto(buffer, object, checkKeys, startingIndex,
|
|
3961
|
+
function serializeInto(buffer, object, checkKeys, startingIndex, serializeFunctions, ignoreUndefined, path) {
|
|
3855
3962
|
if (path == null) {
|
|
3856
3963
|
if (object == null) {
|
|
3857
3964
|
buffer[0] = 0x05;
|
|
@@ -3879,308 +3986,200 @@ function serializeInto(buffer, object, checkKeys, startingIndex, depth, serializ
|
|
|
3879
3986
|
path = new Set();
|
|
3880
3987
|
}
|
|
3881
3988
|
path.add(object);
|
|
3989
|
+
let currentFrame = makeFrame(object, startingIndex, null, null, checkKeys, ignoreUndefined);
|
|
3882
3990
|
let index = startingIndex + 4;
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
else if (value === null) {
|
|
3895
|
-
index = serializeNull(buffer, key, value, index);
|
|
3896
|
-
}
|
|
3897
|
-
else if (type === 'string') {
|
|
3898
|
-
index = serializeString(buffer, key, value, index);
|
|
3899
|
-
}
|
|
3900
|
-
else if (type === 'number') {
|
|
3901
|
-
index = serializeNumber(buffer, key, value, index);
|
|
3902
|
-
}
|
|
3903
|
-
else if (type === 'bigint') {
|
|
3904
|
-
index = serializeBigInt(buffer, key, value, index);
|
|
3905
|
-
}
|
|
3906
|
-
else if (type === 'boolean') {
|
|
3907
|
-
index = serializeBoolean(buffer, key, value, index);
|
|
3908
|
-
}
|
|
3909
|
-
else if (type === 'object' && value._bsontype == null) {
|
|
3910
|
-
if (value instanceof Date || isDate(value)) {
|
|
3911
|
-
index = serializeDate(buffer, key, value, index);
|
|
3912
|
-
}
|
|
3913
|
-
else if (value instanceof Uint8Array || isUint8Array(value)) {
|
|
3914
|
-
index = serializeBuffer(buffer, key, value, index);
|
|
3915
|
-
}
|
|
3916
|
-
else if (value instanceof RegExp || isRegExp(value)) {
|
|
3917
|
-
index = serializeRegExp(buffer, key, value, index);
|
|
3918
|
-
}
|
|
3919
|
-
else {
|
|
3920
|
-
index = serializeObject(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, path);
|
|
3991
|
+
while (currentFrame !== null) {
|
|
3992
|
+
const frame = currentFrame;
|
|
3993
|
+
let key;
|
|
3994
|
+
let value;
|
|
3995
|
+
if (frame.mapIterator !== null) {
|
|
3996
|
+
const next = frame.mapIterator.next();
|
|
3997
|
+
if (next.done) {
|
|
3998
|
+
buffer[index++] = 0x00;
|
|
3999
|
+
NumberUtils.setInt32LE(buffer, frame.objectSizeIndex, index - frame.objectSizeIndex);
|
|
4000
|
+
if (frame.codeSizeIndex !== null) {
|
|
4001
|
+
NumberUtils.setInt32LE(buffer, frame.codeSizeIndex, index - frame.codeSizeIndex);
|
|
3921
4002
|
}
|
|
4003
|
+
path.delete(frame.sourceObject);
|
|
4004
|
+
currentFrame = frame.prev;
|
|
4005
|
+
continue;
|
|
3922
4006
|
}
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
}
|
|
3933
|
-
else if (value._bsontype === 'Long' || value._bsontype === 'Timestamp') {
|
|
3934
|
-
index = serializeLong(buffer, key, value, index);
|
|
3935
|
-
}
|
|
3936
|
-
else if (value._bsontype === 'Double') {
|
|
3937
|
-
index = serializeDouble(buffer, key, value, index);
|
|
3938
|
-
}
|
|
3939
|
-
else if (value._bsontype === 'Code') {
|
|
3940
|
-
index = serializeCode(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, path);
|
|
3941
|
-
}
|
|
3942
|
-
else if (value._bsontype === 'Binary') {
|
|
3943
|
-
index = serializeBinary(buffer, key, value, index);
|
|
3944
|
-
}
|
|
3945
|
-
else if (value._bsontype === 'BSONSymbol') {
|
|
3946
|
-
index = serializeSymbol(buffer, key, value, index);
|
|
3947
|
-
}
|
|
3948
|
-
else if (value._bsontype === 'DBRef') {
|
|
3949
|
-
index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions, path);
|
|
3950
|
-
}
|
|
3951
|
-
else if (value._bsontype === 'BSONRegExp') {
|
|
3952
|
-
index = serializeBSONRegExp(buffer, key, value, index);
|
|
3953
|
-
}
|
|
3954
|
-
else if (value._bsontype === 'Int32') {
|
|
3955
|
-
index = serializeInt32(buffer, key, value, index);
|
|
3956
|
-
}
|
|
3957
|
-
else if (value._bsontype === 'MinKey' || value._bsontype === 'MaxKey') {
|
|
3958
|
-
index = serializeMinMax(buffer, key, value, index);
|
|
3959
|
-
}
|
|
3960
|
-
else if (typeof value._bsontype !== 'undefined') {
|
|
3961
|
-
throw new BSONError(`Unrecognized or invalid _bsontype: ${String(value._bsontype)}`);
|
|
4007
|
+
key = next.value[0];
|
|
4008
|
+
value = next.value[1];
|
|
4009
|
+
}
|
|
4010
|
+
else if (frame.keys !== null) {
|
|
4011
|
+
if (frame.keyIndex >= frame.keys.length) {
|
|
4012
|
+
buffer[index++] = 0x00;
|
|
4013
|
+
NumberUtils.setInt32LE(buffer, frame.objectSizeIndex, index - frame.objectSizeIndex);
|
|
4014
|
+
if (frame.codeSizeIndex !== null) {
|
|
4015
|
+
NumberUtils.setInt32LE(buffer, frame.codeSizeIndex, index - frame.codeSizeIndex);
|
|
3962
4016
|
}
|
|
4017
|
+
path.delete(frame.sourceObject);
|
|
4018
|
+
currentFrame = frame.prev;
|
|
4019
|
+
continue;
|
|
3963
4020
|
}
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
}
|
|
4021
|
+
key = frame.keys[frame.keyIndex++];
|
|
4022
|
+
value = frame.iterTarget[key];
|
|
3967
4023
|
}
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
4024
|
+
else {
|
|
4025
|
+
const arr = frame.iterTarget;
|
|
4026
|
+
if (frame.keyIndex >= arr.length) {
|
|
4027
|
+
buffer[index++] = 0x00;
|
|
4028
|
+
NumberUtils.setInt32LE(buffer, frame.objectSizeIndex, index - frame.objectSizeIndex);
|
|
4029
|
+
if (frame.codeSizeIndex !== null) {
|
|
4030
|
+
NumberUtils.setInt32LE(buffer, frame.codeSizeIndex, index - frame.codeSizeIndex);
|
|
4031
|
+
}
|
|
4032
|
+
path.delete(frame.sourceObject);
|
|
4033
|
+
currentFrame = frame.prev;
|
|
3976
4034
|
continue;
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
4035
|
+
}
|
|
4036
|
+
const i = frame.keyIndex++;
|
|
4037
|
+
key = String(i);
|
|
4038
|
+
value = arr[i];
|
|
4039
|
+
}
|
|
4040
|
+
if (typeof value?.toBSON === 'function') {
|
|
4041
|
+
value = value.toBSON();
|
|
4042
|
+
}
|
|
4043
|
+
if (!frame.isArray && typeof key === 'string' && !(key[0] === '$' && ignoreKeys.has(key))) {
|
|
4044
|
+
if (regexp.test(key)) {
|
|
4045
|
+
throw new BSONError('key ' + key + ' must not contain null bytes');
|
|
4046
|
+
}
|
|
4047
|
+
if (frame.checkKeys) {
|
|
4048
|
+
if ('$' === key[0]) {
|
|
4049
|
+
throw new BSONError('key ' + key + " must not start with '$'");
|
|
3986
4050
|
}
|
|
3987
|
-
if (
|
|
3988
|
-
|
|
3989
|
-
throw new BSONError('key ' + key + " must not start with '$'");
|
|
3990
|
-
}
|
|
3991
|
-
else if (key.includes('.')) {
|
|
3992
|
-
throw new BSONError('key ' + key + " must not contain '.'");
|
|
3993
|
-
}
|
|
4051
|
+
else if (key.includes('.')) {
|
|
4052
|
+
throw new BSONError('key ' + key + " must not contain '.'");
|
|
3994
4053
|
}
|
|
3995
4054
|
}
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
else if (value === null) {
|
|
4055
|
+
}
|
|
4056
|
+
const type = typeof value;
|
|
4057
|
+
if (value === undefined) {
|
|
4058
|
+
if (frame.isArray || frame.ignoreUndefined === false) {
|
|
4001
4059
|
index = serializeNull(buffer, key, value, index);
|
|
4002
4060
|
}
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4061
|
+
}
|
|
4062
|
+
else if (value === null) {
|
|
4063
|
+
index = serializeNull(buffer, key, value, index);
|
|
4064
|
+
}
|
|
4065
|
+
else if (type === 'string') {
|
|
4066
|
+
index = serializeString(buffer, key, value, index);
|
|
4067
|
+
}
|
|
4068
|
+
else if (type === 'number') {
|
|
4069
|
+
index = serializeNumber(buffer, key, value, index);
|
|
4070
|
+
}
|
|
4071
|
+
else if (type === 'bigint') {
|
|
4072
|
+
index = serializeBigInt(buffer, key, value, index);
|
|
4073
|
+
}
|
|
4074
|
+
else if (type === 'boolean') {
|
|
4075
|
+
index = serializeBoolean(buffer, key, value, index);
|
|
4076
|
+
}
|
|
4077
|
+
else if (type === 'object' && value._bsontype == null) {
|
|
4078
|
+
if (value instanceof Date || isDate(value)) {
|
|
4079
|
+
index = serializeDate(buffer, key, value, index);
|
|
4011
4080
|
}
|
|
4012
|
-
else if (
|
|
4013
|
-
index =
|
|
4081
|
+
else if (value instanceof Uint8Array || isUint8Array(value)) {
|
|
4082
|
+
index = serializeBuffer(buffer, key, value, index);
|
|
4014
4083
|
}
|
|
4015
|
-
else if (
|
|
4016
|
-
|
|
4017
|
-
index = serializeDate(buffer, key, value, index);
|
|
4018
|
-
}
|
|
4019
|
-
else if (value instanceof Uint8Array || isUint8Array(value)) {
|
|
4020
|
-
index = serializeBuffer(buffer, key, value, index);
|
|
4021
|
-
}
|
|
4022
|
-
else if (value instanceof RegExp || isRegExp(value)) {
|
|
4023
|
-
index = serializeRegExp(buffer, key, value, index);
|
|
4024
|
-
}
|
|
4025
|
-
else {
|
|
4026
|
-
index = serializeObject(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, path);
|
|
4027
|
-
}
|
|
4084
|
+
else if (value instanceof RegExp || isRegExp(value)) {
|
|
4085
|
+
index = serializeRegExp(buffer, key, value, index);
|
|
4028
4086
|
}
|
|
4029
|
-
else
|
|
4030
|
-
if (value
|
|
4031
|
-
throw new
|
|
4032
|
-
}
|
|
4033
|
-
else if (value._bsontype === 'ObjectId') {
|
|
4034
|
-
index = serializeObjectId(buffer, key, value, index);
|
|
4035
|
-
}
|
|
4036
|
-
else if (value._bsontype === 'Decimal128') {
|
|
4037
|
-
index = serializeDecimal128(buffer, key, value, index);
|
|
4038
|
-
}
|
|
4039
|
-
else if (value._bsontype === 'Long' || value._bsontype === 'Timestamp') {
|
|
4040
|
-
index = serializeLong(buffer, key, value, index);
|
|
4041
|
-
}
|
|
4042
|
-
else if (value._bsontype === 'Double') {
|
|
4043
|
-
index = serializeDouble(buffer, key, value, index);
|
|
4044
|
-
}
|
|
4045
|
-
else if (value._bsontype === 'Code') {
|
|
4046
|
-
index = serializeCode(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, path);
|
|
4047
|
-
}
|
|
4048
|
-
else if (value._bsontype === 'Binary') {
|
|
4049
|
-
index = serializeBinary(buffer, key, value, index);
|
|
4050
|
-
}
|
|
4051
|
-
else if (value._bsontype === 'BSONSymbol') {
|
|
4052
|
-
index = serializeSymbol(buffer, key, value, index);
|
|
4053
|
-
}
|
|
4054
|
-
else if (value._bsontype === 'DBRef') {
|
|
4055
|
-
index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions, path);
|
|
4056
|
-
}
|
|
4057
|
-
else if (value._bsontype === 'BSONRegExp') {
|
|
4058
|
-
index = serializeBSONRegExp(buffer, key, value, index);
|
|
4059
|
-
}
|
|
4060
|
-
else if (value._bsontype === 'Int32') {
|
|
4061
|
-
index = serializeInt32(buffer, key, value, index);
|
|
4062
|
-
}
|
|
4063
|
-
else if (value._bsontype === 'MinKey' || value._bsontype === 'MaxKey') {
|
|
4064
|
-
index = serializeMinMax(buffer, key, value, index);
|
|
4065
|
-
}
|
|
4066
|
-
else if (typeof value._bsontype !== 'undefined') {
|
|
4067
|
-
throw new BSONError(`Unrecognized or invalid _bsontype: ${String(value._bsontype)}`);
|
|
4087
|
+
else {
|
|
4088
|
+
if (path.has(value)) {
|
|
4089
|
+
throw new BSONError('Cannot convert circular structure to BSON');
|
|
4068
4090
|
}
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
index
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
object = object.toBSON();
|
|
4078
|
-
if (object != null && typeof object !== 'object') {
|
|
4079
|
-
throw new BSONError('toBSON function did not return an object');
|
|
4091
|
+
const nestedIsArray = Array.isArray(value);
|
|
4092
|
+
buffer[index++] = nestedIsArray ? BSON_DATA_ARRAY : BSON_DATA_OBJECT;
|
|
4093
|
+
index += ByteUtils.encodeUTF8Into(buffer, key, index);
|
|
4094
|
+
buffer[index++] = 0x00;
|
|
4095
|
+
const nestedStartIndex = index;
|
|
4096
|
+
path.add(value);
|
|
4097
|
+
currentFrame = makeFrame(value, nestedStartIndex, null, frame, frame.checkKeys, frame.ignoreUndefined);
|
|
4098
|
+
index += 4;
|
|
4080
4099
|
}
|
|
4081
4100
|
}
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
value = value.toBSON();
|
|
4101
|
+
else if (type === 'object') {
|
|
4102
|
+
if (value[BSON_VERSION_SYMBOL] !== BSON_MAJOR_VERSION) {
|
|
4103
|
+
throw new BSONVersionError();
|
|
4086
4104
|
}
|
|
4087
|
-
const
|
|
4088
|
-
if (
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4105
|
+
const tag = value[bsonType];
|
|
4106
|
+
if (tag === 'ObjectId') {
|
|
4107
|
+
index = serializeObjectId(buffer, key, value, index);
|
|
4108
|
+
}
|
|
4109
|
+
else if (tag === 'Decimal128') {
|
|
4110
|
+
index = serializeDecimal128(buffer, key, value, index);
|
|
4111
|
+
}
|
|
4112
|
+
else if (tag === 'Long' || tag === 'Timestamp') {
|
|
4113
|
+
index = serializeLong(buffer, key, value, index);
|
|
4114
|
+
}
|
|
4115
|
+
else if (tag === 'Double') {
|
|
4116
|
+
index = serializeDouble(buffer, key, value, index);
|
|
4117
|
+
}
|
|
4118
|
+
else if (tag === 'Code') {
|
|
4119
|
+
const codeValue = value;
|
|
4120
|
+
if (codeValue.scope && typeof codeValue.scope === 'object') {
|
|
4121
|
+
buffer[index++] = BSON_DATA_CODE_W_SCOPE;
|
|
4122
|
+
index += ByteUtils.encodeUTF8Into(buffer, key, index);
|
|
4123
|
+
buffer[index++] = 0x00;
|
|
4124
|
+
const codeTotalSizeIndex = index;
|
|
4125
|
+
index += 4;
|
|
4126
|
+
const functionString = codeValue.code;
|
|
4127
|
+
const codeSize = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
|
|
4128
|
+
NumberUtils.setInt32LE(buffer, index, codeSize);
|
|
4129
|
+
buffer[index + 4 + codeSize - 1] = 0;
|
|
4130
|
+
index = index + codeSize + 4;
|
|
4131
|
+
const scope = codeValue.scope;
|
|
4132
|
+
if (path.has(scope)) {
|
|
4133
|
+
throw new BSONError('Cannot convert circular structure to BSON');
|
|
4098
4134
|
}
|
|
4135
|
+
path.add(scope);
|
|
4136
|
+
currentFrame = makeFrame(scope, index, codeTotalSizeIndex, frame, frame.checkKeys, frame.ignoreUndefined);
|
|
4137
|
+
index += 4;
|
|
4138
|
+
}
|
|
4139
|
+
else {
|
|
4140
|
+
buffer[index++] = BSON_DATA_CODE;
|
|
4141
|
+
index += ByteUtils.encodeUTF8Into(buffer, key, index);
|
|
4142
|
+
buffer[index++] = 0x00;
|
|
4143
|
+
const functionString = codeValue.code.toString();
|
|
4144
|
+
const size = ByteUtils.encodeUTF8Into(buffer, functionString, index + 4) + 1;
|
|
4145
|
+
NumberUtils.setInt32LE(buffer, index, size);
|
|
4146
|
+
index = index + 4 + size - 1;
|
|
4147
|
+
buffer[index++] = 0;
|
|
4099
4148
|
}
|
|
4100
4149
|
}
|
|
4101
|
-
if (
|
|
4102
|
-
|
|
4103
|
-
index = serializeNull(buffer, key, value, index);
|
|
4104
|
-
}
|
|
4105
|
-
else if (value === null) {
|
|
4106
|
-
index = serializeNull(buffer, key, value, index);
|
|
4107
|
-
}
|
|
4108
|
-
else if (type === 'string') {
|
|
4109
|
-
index = serializeString(buffer, key, value, index);
|
|
4150
|
+
else if (tag === 'Binary') {
|
|
4151
|
+
index = serializeBinary(buffer, key, value, index);
|
|
4110
4152
|
}
|
|
4111
|
-
else if (
|
|
4112
|
-
index =
|
|
4153
|
+
else if (tag === 'BSONSymbol') {
|
|
4154
|
+
index = serializeSymbol(buffer, key, value, index);
|
|
4113
4155
|
}
|
|
4114
|
-
else if (
|
|
4115
|
-
|
|
4156
|
+
else if (tag === 'DBRef') {
|
|
4157
|
+
const dbref = value;
|
|
4158
|
+
const orderedValues = Object.assign({ $ref: dbref.collection, $id: dbref.oid }, dbref.db != null ? { $db: dbref.db } : null, dbref.fields);
|
|
4159
|
+
buffer[index++] = BSON_DATA_OBJECT;
|
|
4160
|
+
index += ByteUtils.encodeUTF8Into(buffer, key, index);
|
|
4161
|
+
buffer[index++] = 0x00;
|
|
4162
|
+
path.add(orderedValues);
|
|
4163
|
+
currentFrame = makeFrame(orderedValues, index, null, frame, false, true);
|
|
4164
|
+
index += 4;
|
|
4116
4165
|
}
|
|
4117
|
-
else if (
|
|
4118
|
-
index =
|
|
4166
|
+
else if (tag === 'BSONRegExp') {
|
|
4167
|
+
index = serializeBSONRegExp(buffer, key, value, index);
|
|
4119
4168
|
}
|
|
4120
|
-
else if (
|
|
4121
|
-
|
|
4122
|
-
index = serializeDate(buffer, key, value, index);
|
|
4123
|
-
}
|
|
4124
|
-
else if (value instanceof Uint8Array || isUint8Array(value)) {
|
|
4125
|
-
index = serializeBuffer(buffer, key, value, index);
|
|
4126
|
-
}
|
|
4127
|
-
else if (value instanceof RegExp || isRegExp(value)) {
|
|
4128
|
-
index = serializeRegExp(buffer, key, value, index);
|
|
4129
|
-
}
|
|
4130
|
-
else {
|
|
4131
|
-
index = serializeObject(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, path);
|
|
4132
|
-
}
|
|
4169
|
+
else if (tag === 'Int32') {
|
|
4170
|
+
index = serializeInt32(buffer, key, value, index);
|
|
4133
4171
|
}
|
|
4134
|
-
else if (
|
|
4135
|
-
|
|
4136
|
-
throw new BSONVersionError();
|
|
4137
|
-
}
|
|
4138
|
-
else if (value._bsontype === 'ObjectId') {
|
|
4139
|
-
index = serializeObjectId(buffer, key, value, index);
|
|
4140
|
-
}
|
|
4141
|
-
else if (value._bsontype === 'Decimal128') {
|
|
4142
|
-
index = serializeDecimal128(buffer, key, value, index);
|
|
4143
|
-
}
|
|
4144
|
-
else if (value._bsontype === 'Long' || value._bsontype === 'Timestamp') {
|
|
4145
|
-
index = serializeLong(buffer, key, value, index);
|
|
4146
|
-
}
|
|
4147
|
-
else if (value._bsontype === 'Double') {
|
|
4148
|
-
index = serializeDouble(buffer, key, value, index);
|
|
4149
|
-
}
|
|
4150
|
-
else if (value._bsontype === 'Code') {
|
|
4151
|
-
index = serializeCode(buffer, key, value, index, checkKeys, depth, serializeFunctions, ignoreUndefined, path);
|
|
4152
|
-
}
|
|
4153
|
-
else if (value._bsontype === 'Binary') {
|
|
4154
|
-
index = serializeBinary(buffer, key, value, index);
|
|
4155
|
-
}
|
|
4156
|
-
else if (value._bsontype === 'BSONSymbol') {
|
|
4157
|
-
index = serializeSymbol(buffer, key, value, index);
|
|
4158
|
-
}
|
|
4159
|
-
else if (value._bsontype === 'DBRef') {
|
|
4160
|
-
index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions, path);
|
|
4161
|
-
}
|
|
4162
|
-
else if (value._bsontype === 'BSONRegExp') {
|
|
4163
|
-
index = serializeBSONRegExp(buffer, key, value, index);
|
|
4164
|
-
}
|
|
4165
|
-
else if (value._bsontype === 'Int32') {
|
|
4166
|
-
index = serializeInt32(buffer, key, value, index);
|
|
4167
|
-
}
|
|
4168
|
-
else if (value._bsontype === 'MinKey' || value._bsontype === 'MaxKey') {
|
|
4169
|
-
index = serializeMinMax(buffer, key, value, index);
|
|
4170
|
-
}
|
|
4171
|
-
else if (typeof value._bsontype !== 'undefined') {
|
|
4172
|
-
throw new BSONError(`Unrecognized or invalid _bsontype: ${String(value._bsontype)}`);
|
|
4173
|
-
}
|
|
4172
|
+
else if (tag === 'MinKey' || tag === 'MaxKey') {
|
|
4173
|
+
index = serializeMinMax(buffer, key, value, index);
|
|
4174
4174
|
}
|
|
4175
|
-
else if (
|
|
4176
|
-
|
|
4175
|
+
else if (typeof value._bsontype !== 'undefined') {
|
|
4176
|
+
throw new BSONError(`Unrecognized or invalid _bsontype: ${String(value._bsontype)}`);
|
|
4177
4177
|
}
|
|
4178
4178
|
}
|
|
4179
|
+
else if (type === 'function' && serializeFunctions) {
|
|
4180
|
+
index = serializeFunction(buffer, key, value, index);
|
|
4181
|
+
}
|
|
4179
4182
|
}
|
|
4180
|
-
path.delete(object);
|
|
4181
|
-
buffer[index++] = 0x00;
|
|
4182
|
-
const size = index - startingIndex;
|
|
4183
|
-
startingIndex += NumberUtils.setInt32LE(buffer, startingIndex, size);
|
|
4184
4183
|
return index;
|
|
4185
4184
|
}
|
|
4186
4185
|
|
|
@@ -4463,21 +4462,22 @@ function parse(text, options) {
|
|
|
4463
4462
|
return deserializeValue(value, ejsonOptions);
|
|
4464
4463
|
});
|
|
4465
4464
|
}
|
|
4466
|
-
function stringify(value,
|
|
4467
|
-
if (
|
|
4468
|
-
options =
|
|
4469
|
-
|
|
4465
|
+
function stringify(value, replacerOrOptions, spaceOrOptions, options) {
|
|
4466
|
+
if (spaceOrOptions != null && typeof spaceOrOptions === 'object') {
|
|
4467
|
+
options = spaceOrOptions;
|
|
4468
|
+
spaceOrOptions = undefined;
|
|
4470
4469
|
}
|
|
4471
|
-
if (
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4470
|
+
if (replacerOrOptions != null &&
|
|
4471
|
+
typeof replacerOrOptions === 'object' &&
|
|
4472
|
+
!Array.isArray(replacerOrOptions)) {
|
|
4473
|
+
options = replacerOrOptions;
|
|
4474
|
+
replacerOrOptions = undefined;
|
|
4475
4475
|
}
|
|
4476
4476
|
const serializeOptions = Object.assign({ relaxed: true, legacy: false }, options, {
|
|
4477
4477
|
seenObjects: [{ propertyName: '(root)', obj: null }]
|
|
4478
4478
|
});
|
|
4479
4479
|
const doc = serializeValue(value, serializeOptions);
|
|
4480
|
-
return JSON.stringify(doc,
|
|
4480
|
+
return JSON.stringify(doc, replacerOrOptions, spaceOrOptions);
|
|
4481
4481
|
}
|
|
4482
4482
|
function EJSONserialize(value, options) {
|
|
4483
4483
|
options = options || {};
|
|
@@ -4639,7 +4639,7 @@ function serialize(object, options = {}) {
|
|
|
4639
4639
|
if (buffer.length < minInternalBufferSize) {
|
|
4640
4640
|
buffer = ByteUtils.allocate(minInternalBufferSize);
|
|
4641
4641
|
}
|
|
4642
|
-
const serializationIndex = serializeInto(buffer, object, checkKeys, 0,
|
|
4642
|
+
const serializationIndex = serializeInto(buffer, object, checkKeys, 0, serializeFunctions, ignoreUndefined, null);
|
|
4643
4643
|
const finishedBuffer = ByteUtils.allocateUnsafe(serializationIndex);
|
|
4644
4644
|
finishedBuffer.set(buffer.subarray(0, serializationIndex), 0);
|
|
4645
4645
|
return finishedBuffer;
|
|
@@ -4649,7 +4649,7 @@ function serializeWithBufferAndIndex(object, finalBuffer, options = {}) {
|
|
|
4649
4649
|
const serializeFunctions = typeof options.serializeFunctions === 'boolean' ? options.serializeFunctions : false;
|
|
4650
4650
|
const ignoreUndefined = typeof options.ignoreUndefined === 'boolean' ? options.ignoreUndefined : true;
|
|
4651
4651
|
const startIndex = typeof options.index === 'number' ? options.index : 0;
|
|
4652
|
-
const serializationIndex = serializeInto(buffer, object, checkKeys, 0,
|
|
4652
|
+
const serializationIndex = serializeInto(buffer, object, checkKeys, 0, serializeFunctions, ignoreUndefined, null);
|
|
4653
4653
|
finalBuffer.set(buffer.subarray(0, serializationIndex), startIndex);
|
|
4654
4654
|
return startIndex + serializationIndex - 1;
|
|
4655
4655
|
}
|