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