bson 6.2.0 → 6.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bson.d.ts +39 -4
- package/lib/bson.bundle.js +118 -69
- package/lib/bson.bundle.js.map +1 -1
- package/lib/bson.cjs +118 -69
- package/lib/bson.cjs.map +1 -1
- package/lib/bson.mjs +118 -69
- package/lib/bson.mjs.map +1 -1
- package/lib/bson.rn.cjs +118 -69
- package/lib/bson.rn.cjs.map +1 -1
- package/package.json +19 -16
- package/src/binary.ts +2 -2
- package/src/error.ts +3 -3
- package/src/objectid.ts +42 -3
- package/src/parser/deserializer.ts +10 -31
- package/src/utils/byte_utils.ts +2 -2
- package/src/utils/latin.ts +61 -0
- package/src/utils/node_byte_utils.ts +21 -2
- package/src/utils/web_byte_utils.ts +15 -2
package/bson.d.ts
CHANGED
|
@@ -150,14 +150,16 @@ export { BSON }
|
|
|
150
150
|
* @public
|
|
151
151
|
* @category Error
|
|
152
152
|
*
|
|
153
|
-
* `BSONError` objects are thrown when BSON
|
|
153
|
+
* `BSONError` objects are thrown when BSON encounters an error.
|
|
154
154
|
*
|
|
155
155
|
* This is the parent class for all the other errors thrown by this library.
|
|
156
156
|
*/
|
|
157
157
|
export declare class BSONError extends Error {
|
|
158
158
|
/* Excluded from this release type: bsonError */
|
|
159
159
|
get name(): string;
|
|
160
|
-
constructor(message: string
|
|
160
|
+
constructor(message: string, options?: {
|
|
161
|
+
cause?: unknown;
|
|
162
|
+
});
|
|
161
163
|
/**
|
|
162
164
|
* @public
|
|
163
165
|
*
|
|
@@ -994,9 +996,42 @@ export declare class ObjectId extends BSONValue {
|
|
|
994
996
|
/* Excluded from this release type: [kId] */
|
|
995
997
|
/* Excluded from this release type: __id */
|
|
996
998
|
/**
|
|
997
|
-
* Create
|
|
999
|
+
* Create ObjectId from a number.
|
|
1000
|
+
*
|
|
1001
|
+
* @param inputId - A number.
|
|
1002
|
+
* @deprecated Instead, use `static createFromTime()` to set a numeric value for the new ObjectId.
|
|
1003
|
+
*/
|
|
1004
|
+
constructor(inputId: number);
|
|
1005
|
+
/**
|
|
1006
|
+
* Create ObjectId from a 24 character hex string.
|
|
1007
|
+
*
|
|
1008
|
+
* @param inputId - A 24 character hex string.
|
|
1009
|
+
*/
|
|
1010
|
+
constructor(inputId: string);
|
|
1011
|
+
/**
|
|
1012
|
+
* Create ObjectId from the BSON ObjectId type.
|
|
1013
|
+
*
|
|
1014
|
+
* @param inputId - The BSON ObjectId type.
|
|
1015
|
+
*/
|
|
1016
|
+
constructor(inputId: ObjectId);
|
|
1017
|
+
/**
|
|
1018
|
+
* Create ObjectId from the object type that has the toHexString method.
|
|
1019
|
+
*
|
|
1020
|
+
* @param inputId - The ObjectIdLike type.
|
|
1021
|
+
*/
|
|
1022
|
+
constructor(inputId: ObjectIdLike);
|
|
1023
|
+
/**
|
|
1024
|
+
* Create ObjectId from a 12 byte binary Buffer.
|
|
1025
|
+
*
|
|
1026
|
+
* @param inputId - A 12 byte binary Buffer.
|
|
1027
|
+
*/
|
|
1028
|
+
constructor(inputId: Uint8Array);
|
|
1029
|
+
/** To generate a new ObjectId, use ObjectId() with no argument. */
|
|
1030
|
+
constructor();
|
|
1031
|
+
/**
|
|
1032
|
+
* Implementation overload.
|
|
998
1033
|
*
|
|
999
|
-
* @param inputId -
|
|
1034
|
+
* @param inputId - All input types that are used in the constructor implementation.
|
|
1000
1035
|
*/
|
|
1001
1036
|
constructor(inputId?: string | number | ObjectId | ObjectIdLike | Uint8Array);
|
|
1002
1037
|
/**
|
package/lib/bson.bundle.js
CHANGED
|
@@ -98,8 +98,8 @@ class BSONError extends Error {
|
|
|
98
98
|
get name() {
|
|
99
99
|
return 'BSONError';
|
|
100
100
|
}
|
|
101
|
-
constructor(message) {
|
|
102
|
-
super(message);
|
|
101
|
+
constructor(message, options) {
|
|
102
|
+
super(message, options);
|
|
103
103
|
}
|
|
104
104
|
static isBSONError(value) {
|
|
105
105
|
return (value != null &&
|
|
@@ -128,6 +128,79 @@ class BSONRuntimeError extends BSONError {
|
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
+
const FIRST_BIT = 0x80;
|
|
132
|
+
const FIRST_TWO_BITS = 0xc0;
|
|
133
|
+
const FIRST_THREE_BITS = 0xe0;
|
|
134
|
+
const FIRST_FOUR_BITS = 0xf0;
|
|
135
|
+
const FIRST_FIVE_BITS = 0xf8;
|
|
136
|
+
const TWO_BIT_CHAR = 0xc0;
|
|
137
|
+
const THREE_BIT_CHAR = 0xe0;
|
|
138
|
+
const FOUR_BIT_CHAR = 0xf0;
|
|
139
|
+
const CONTINUING_CHAR = 0x80;
|
|
140
|
+
function validateUtf8(bytes, start, end) {
|
|
141
|
+
let continuation = 0;
|
|
142
|
+
for (let i = start; i < end; i += 1) {
|
|
143
|
+
const byte = bytes[i];
|
|
144
|
+
if (continuation) {
|
|
145
|
+
if ((byte & FIRST_TWO_BITS) !== CONTINUING_CHAR) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
continuation -= 1;
|
|
149
|
+
}
|
|
150
|
+
else if (byte & FIRST_BIT) {
|
|
151
|
+
if ((byte & FIRST_THREE_BITS) === TWO_BIT_CHAR) {
|
|
152
|
+
continuation = 1;
|
|
153
|
+
}
|
|
154
|
+
else if ((byte & FIRST_FOUR_BITS) === THREE_BIT_CHAR) {
|
|
155
|
+
continuation = 2;
|
|
156
|
+
}
|
|
157
|
+
else if ((byte & FIRST_FIVE_BITS) === FOUR_BIT_CHAR) {
|
|
158
|
+
continuation = 3;
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return !continuation;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function tryLatin(uint8array, start, end) {
|
|
169
|
+
if (uint8array.length === 0) {
|
|
170
|
+
return '';
|
|
171
|
+
}
|
|
172
|
+
const stringByteLength = end - start;
|
|
173
|
+
if (stringByteLength === 0) {
|
|
174
|
+
return '';
|
|
175
|
+
}
|
|
176
|
+
if (stringByteLength > 20) {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
if (stringByteLength === 1 && uint8array[start] < 128) {
|
|
180
|
+
return String.fromCharCode(uint8array[start]);
|
|
181
|
+
}
|
|
182
|
+
if (stringByteLength === 2 && uint8array[start] < 128 && uint8array[start + 1] < 128) {
|
|
183
|
+
return String.fromCharCode(uint8array[start]) + String.fromCharCode(uint8array[start + 1]);
|
|
184
|
+
}
|
|
185
|
+
if (stringByteLength === 3 &&
|
|
186
|
+
uint8array[start] < 128 &&
|
|
187
|
+
uint8array[start + 1] < 128 &&
|
|
188
|
+
uint8array[start + 2] < 128) {
|
|
189
|
+
return (String.fromCharCode(uint8array[start]) +
|
|
190
|
+
String.fromCharCode(uint8array[start + 1]) +
|
|
191
|
+
String.fromCharCode(uint8array[start + 2]));
|
|
192
|
+
}
|
|
193
|
+
const latinBytes = [];
|
|
194
|
+
for (let i = start; i < end; i++) {
|
|
195
|
+
const byte = uint8array[i];
|
|
196
|
+
if (byte > 127) {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
latinBytes.push(byte);
|
|
200
|
+
}
|
|
201
|
+
return String.fromCharCode(...latinBytes);
|
|
202
|
+
}
|
|
203
|
+
|
|
131
204
|
function nodejsMathRandomBytes(byteLength) {
|
|
132
205
|
return nodeJsByteUtils.fromNumberArray(Array.from({ length: byteLength }, () => Math.floor(Math.random() * 256)));
|
|
133
206
|
}
|
|
@@ -186,8 +259,23 @@ const nodeJsByteUtils = {
|
|
|
186
259
|
fromUTF8(text) {
|
|
187
260
|
return Buffer.from(text, 'utf8');
|
|
188
261
|
},
|
|
189
|
-
toUTF8(buffer, start, end) {
|
|
190
|
-
|
|
262
|
+
toUTF8(buffer, start, end, fatal) {
|
|
263
|
+
const basicLatin = end - start <= 20 ? tryLatin(buffer, start, end) : null;
|
|
264
|
+
if (basicLatin != null) {
|
|
265
|
+
return basicLatin;
|
|
266
|
+
}
|
|
267
|
+
const string = nodeJsByteUtils.toLocalBufferType(buffer).toString('utf8', start, end);
|
|
268
|
+
if (fatal) {
|
|
269
|
+
for (let i = 0; i < string.length; i++) {
|
|
270
|
+
if (string.charCodeAt(i) === 0xfffd) {
|
|
271
|
+
if (!validateUtf8(buffer, start, end)) {
|
|
272
|
+
throw new BSONError('Invalid UTF-8 string in BSON document');
|
|
273
|
+
}
|
|
274
|
+
break;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return string;
|
|
191
279
|
},
|
|
192
280
|
utf8ByteLength(input) {
|
|
193
281
|
return Buffer.byteLength(input, 'utf8');
|
|
@@ -297,8 +385,20 @@ const webByteUtils = {
|
|
|
297
385
|
fromUTF8(text) {
|
|
298
386
|
return new TextEncoder().encode(text);
|
|
299
387
|
},
|
|
300
|
-
toUTF8(uint8array, start, end) {
|
|
301
|
-
|
|
388
|
+
toUTF8(uint8array, start, end, fatal) {
|
|
389
|
+
const basicLatin = end - start <= 20 ? tryLatin(uint8array, start, end) : null;
|
|
390
|
+
if (basicLatin != null) {
|
|
391
|
+
return basicLatin;
|
|
392
|
+
}
|
|
393
|
+
if (fatal) {
|
|
394
|
+
try {
|
|
395
|
+
return new TextDecoder('utf8', { fatal }).decode(uint8array.slice(start, end));
|
|
396
|
+
}
|
|
397
|
+
catch (cause) {
|
|
398
|
+
throw new BSONError('Invalid UTF-8 string in BSON document', { cause });
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
return new TextDecoder('utf8', { fatal }).decode(uint8array.slice(start, end));
|
|
302
402
|
},
|
|
303
403
|
utf8ByteLength(input) {
|
|
304
404
|
return webByteUtils.fromUTF8(input).byteLength;
|
|
@@ -419,8 +519,8 @@ class Binary extends BSONValue {
|
|
|
419
519
|
if (encoding === 'base64')
|
|
420
520
|
return ByteUtils.toBase64(this.buffer);
|
|
421
521
|
if (encoding === 'utf8' || encoding === 'utf-8')
|
|
422
|
-
return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength);
|
|
423
|
-
return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength);
|
|
522
|
+
return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength, false);
|
|
523
|
+
return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength, false);
|
|
424
524
|
}
|
|
425
525
|
toExtendedJSON(options) {
|
|
426
526
|
options = options || {};
|
|
@@ -2508,43 +2608,6 @@ class Timestamp extends LongWithoutOverridesClass {
|
|
|
2508
2608
|
}
|
|
2509
2609
|
Timestamp.MAX_VALUE = Long.MAX_UNSIGNED_VALUE;
|
|
2510
2610
|
|
|
2511
|
-
const FIRST_BIT = 0x80;
|
|
2512
|
-
const FIRST_TWO_BITS = 0xc0;
|
|
2513
|
-
const FIRST_THREE_BITS = 0xe0;
|
|
2514
|
-
const FIRST_FOUR_BITS = 0xf0;
|
|
2515
|
-
const FIRST_FIVE_BITS = 0xf8;
|
|
2516
|
-
const TWO_BIT_CHAR = 0xc0;
|
|
2517
|
-
const THREE_BIT_CHAR = 0xe0;
|
|
2518
|
-
const FOUR_BIT_CHAR = 0xf0;
|
|
2519
|
-
const CONTINUING_CHAR = 0x80;
|
|
2520
|
-
function validateUtf8(bytes, start, end) {
|
|
2521
|
-
let continuation = 0;
|
|
2522
|
-
for (let i = start; i < end; i += 1) {
|
|
2523
|
-
const byte = bytes[i];
|
|
2524
|
-
if (continuation) {
|
|
2525
|
-
if ((byte & FIRST_TWO_BITS) !== CONTINUING_CHAR) {
|
|
2526
|
-
return false;
|
|
2527
|
-
}
|
|
2528
|
-
continuation -= 1;
|
|
2529
|
-
}
|
|
2530
|
-
else if (byte & FIRST_BIT) {
|
|
2531
|
-
if ((byte & FIRST_THREE_BITS) === TWO_BIT_CHAR) {
|
|
2532
|
-
continuation = 1;
|
|
2533
|
-
}
|
|
2534
|
-
else if ((byte & FIRST_FOUR_BITS) === THREE_BIT_CHAR) {
|
|
2535
|
-
continuation = 2;
|
|
2536
|
-
}
|
|
2537
|
-
else if ((byte & FIRST_FIVE_BITS) === FOUR_BIT_CHAR) {
|
|
2538
|
-
continuation = 3;
|
|
2539
|
-
}
|
|
2540
|
-
else {
|
|
2541
|
-
return false;
|
|
2542
|
-
}
|
|
2543
|
-
}
|
|
2544
|
-
}
|
|
2545
|
-
return !continuation;
|
|
2546
|
-
}
|
|
2547
|
-
|
|
2548
2611
|
const JS_INT_MAX_LONG = Long.fromNumber(JS_INT_MAX);
|
|
2549
2612
|
const JS_INT_MIN_LONG = Long.fromNumber(JS_INT_MIN);
|
|
2550
2613
|
function internalDeserialize(buffer, options, isArray) {
|
|
@@ -2636,7 +2699,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
2636
2699
|
}
|
|
2637
2700
|
if (i >= buffer.byteLength)
|
|
2638
2701
|
throw new BSONError('Bad BSON Document: illegal CString');
|
|
2639
|
-
const name = isArray ? arrayIndex++ : ByteUtils.toUTF8(buffer, index, i);
|
|
2702
|
+
const name = isArray ? arrayIndex++ : ByteUtils.toUTF8(buffer, index, i, false);
|
|
2640
2703
|
let shouldValidateKey = true;
|
|
2641
2704
|
if (globalUTFValidation || utf8KeysSet.has(name)) {
|
|
2642
2705
|
shouldValidateKey = validationSetting;
|
|
@@ -2659,7 +2722,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
2659
2722
|
buffer[index + stringSize - 1] !== 0) {
|
|
2660
2723
|
throw new BSONError('bad string length in bson');
|
|
2661
2724
|
}
|
|
2662
|
-
value =
|
|
2725
|
+
value = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
|
|
2663
2726
|
index = index + stringSize;
|
|
2664
2727
|
}
|
|
2665
2728
|
else if (elementType === BSON_DATA_OID) {
|
|
@@ -2851,7 +2914,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
2851
2914
|
}
|
|
2852
2915
|
if (i >= buffer.length)
|
|
2853
2916
|
throw new BSONError('Bad BSON Document: illegal CString');
|
|
2854
|
-
const source = ByteUtils.toUTF8(buffer, index, i);
|
|
2917
|
+
const source = ByteUtils.toUTF8(buffer, index, i, false);
|
|
2855
2918
|
index = i + 1;
|
|
2856
2919
|
i = index;
|
|
2857
2920
|
while (buffer[i] !== 0x00 && i < buffer.length) {
|
|
@@ -2859,7 +2922,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
2859
2922
|
}
|
|
2860
2923
|
if (i >= buffer.length)
|
|
2861
2924
|
throw new BSONError('Bad BSON Document: illegal CString');
|
|
2862
|
-
const regExpOptions = ByteUtils.toUTF8(buffer, index, i);
|
|
2925
|
+
const regExpOptions = ByteUtils.toUTF8(buffer, index, i, false);
|
|
2863
2926
|
index = i + 1;
|
|
2864
2927
|
const optionsArray = new Array(regExpOptions.length);
|
|
2865
2928
|
for (i = 0; i < regExpOptions.length; i++) {
|
|
@@ -2884,7 +2947,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
2884
2947
|
}
|
|
2885
2948
|
if (i >= buffer.length)
|
|
2886
2949
|
throw new BSONError('Bad BSON Document: illegal CString');
|
|
2887
|
-
const source = ByteUtils.toUTF8(buffer, index, i);
|
|
2950
|
+
const source = ByteUtils.toUTF8(buffer, index, i, false);
|
|
2888
2951
|
index = i + 1;
|
|
2889
2952
|
i = index;
|
|
2890
2953
|
while (buffer[i] !== 0x00 && i < buffer.length) {
|
|
@@ -2892,7 +2955,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
2892
2955
|
}
|
|
2893
2956
|
if (i >= buffer.length)
|
|
2894
2957
|
throw new BSONError('Bad BSON Document: illegal CString');
|
|
2895
|
-
const regExpOptions = ByteUtils.toUTF8(buffer, index, i);
|
|
2958
|
+
const regExpOptions = ByteUtils.toUTF8(buffer, index, i, false);
|
|
2896
2959
|
index = i + 1;
|
|
2897
2960
|
value = new BSONRegExp(source, regExpOptions);
|
|
2898
2961
|
}
|
|
@@ -2906,7 +2969,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
2906
2969
|
buffer[index + stringSize - 1] !== 0) {
|
|
2907
2970
|
throw new BSONError('bad string length in bson');
|
|
2908
2971
|
}
|
|
2909
|
-
const symbol =
|
|
2972
|
+
const symbol = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
|
|
2910
2973
|
value = promoteValues ? symbol : new BSONSymbol(symbol);
|
|
2911
2974
|
index = index + stringSize;
|
|
2912
2975
|
}
|
|
@@ -2937,7 +3000,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
2937
3000
|
buffer[index + stringSize - 1] !== 0) {
|
|
2938
3001
|
throw new BSONError('bad string length in bson');
|
|
2939
3002
|
}
|
|
2940
|
-
const functionString =
|
|
3003
|
+
const functionString = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
|
|
2941
3004
|
value = new Code(functionString);
|
|
2942
3005
|
index = index + stringSize;
|
|
2943
3006
|
}
|
|
@@ -2958,7 +3021,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
2958
3021
|
buffer[index + stringSize - 1] !== 0) {
|
|
2959
3022
|
throw new BSONError('bad string length in bson');
|
|
2960
3023
|
}
|
|
2961
|
-
const functionString =
|
|
3024
|
+
const functionString = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
|
|
2962
3025
|
index = index + stringSize;
|
|
2963
3026
|
const _index = index;
|
|
2964
3027
|
const objectSize = buffer[index] |
|
|
@@ -2989,7 +3052,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
2989
3052
|
throw new BSONError('Invalid UTF-8 string in BSON document');
|
|
2990
3053
|
}
|
|
2991
3054
|
}
|
|
2992
|
-
const namespace = ByteUtils.toUTF8(buffer, index, index + stringSize - 1);
|
|
3055
|
+
const namespace = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, false);
|
|
2993
3056
|
index = index + stringSize;
|
|
2994
3057
|
const oidBuffer = ByteUtils.allocate(12);
|
|
2995
3058
|
oidBuffer.set(buffer.subarray(index, index + 12), 0);
|
|
@@ -3028,20 +3091,6 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
3028
3091
|
}
|
|
3029
3092
|
return object;
|
|
3030
3093
|
}
|
|
3031
|
-
function getValidatedString(buffer, start, end, shouldValidateUtf8) {
|
|
3032
|
-
const value = ByteUtils.toUTF8(buffer, start, end);
|
|
3033
|
-
if (shouldValidateUtf8) {
|
|
3034
|
-
for (let i = 0; i < value.length; i++) {
|
|
3035
|
-
if (value.charCodeAt(i) === 0xfffd) {
|
|
3036
|
-
if (!validateUtf8(buffer, start, end)) {
|
|
3037
|
-
throw new BSONError('Invalid UTF-8 string in BSON document');
|
|
3038
|
-
}
|
|
3039
|
-
break;
|
|
3040
|
-
}
|
|
3041
|
-
}
|
|
3042
|
-
}
|
|
3043
|
-
return value;
|
|
3044
|
-
}
|
|
3045
3094
|
|
|
3046
3095
|
const regexp = /\x00/;
|
|
3047
3096
|
const ignoreKeys = new Set(['$db', '$ref', '$id', '$clusterTime']);
|