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