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/lib/bson.rn.cjs
CHANGED
|
@@ -110,8 +110,8 @@ class BSONError extends Error {
|
|
|
110
110
|
get name() {
|
|
111
111
|
return 'BSONError';
|
|
112
112
|
}
|
|
113
|
-
constructor(message) {
|
|
114
|
-
super(message);
|
|
113
|
+
constructor(message, options) {
|
|
114
|
+
super(message, options);
|
|
115
115
|
}
|
|
116
116
|
static isBSONError(value) {
|
|
117
117
|
return (value != null &&
|
|
@@ -140,6 +140,79 @@ class BSONRuntimeError extends BSONError {
|
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
+
const FIRST_BIT = 0x80;
|
|
144
|
+
const FIRST_TWO_BITS = 0xc0;
|
|
145
|
+
const FIRST_THREE_BITS = 0xe0;
|
|
146
|
+
const FIRST_FOUR_BITS = 0xf0;
|
|
147
|
+
const FIRST_FIVE_BITS = 0xf8;
|
|
148
|
+
const TWO_BIT_CHAR = 0xc0;
|
|
149
|
+
const THREE_BIT_CHAR = 0xe0;
|
|
150
|
+
const FOUR_BIT_CHAR = 0xf0;
|
|
151
|
+
const CONTINUING_CHAR = 0x80;
|
|
152
|
+
function validateUtf8(bytes, start, end) {
|
|
153
|
+
let continuation = 0;
|
|
154
|
+
for (let i = start; i < end; i += 1) {
|
|
155
|
+
const byte = bytes[i];
|
|
156
|
+
if (continuation) {
|
|
157
|
+
if ((byte & FIRST_TWO_BITS) !== CONTINUING_CHAR) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
continuation -= 1;
|
|
161
|
+
}
|
|
162
|
+
else if (byte & FIRST_BIT) {
|
|
163
|
+
if ((byte & FIRST_THREE_BITS) === TWO_BIT_CHAR) {
|
|
164
|
+
continuation = 1;
|
|
165
|
+
}
|
|
166
|
+
else if ((byte & FIRST_FOUR_BITS) === THREE_BIT_CHAR) {
|
|
167
|
+
continuation = 2;
|
|
168
|
+
}
|
|
169
|
+
else if ((byte & FIRST_FIVE_BITS) === FOUR_BIT_CHAR) {
|
|
170
|
+
continuation = 3;
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return !continuation;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function tryLatin(uint8array, start, end) {
|
|
181
|
+
if (uint8array.length === 0) {
|
|
182
|
+
return '';
|
|
183
|
+
}
|
|
184
|
+
const stringByteLength = end - start;
|
|
185
|
+
if (stringByteLength === 0) {
|
|
186
|
+
return '';
|
|
187
|
+
}
|
|
188
|
+
if (stringByteLength > 20) {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
if (stringByteLength === 1 && uint8array[start] < 128) {
|
|
192
|
+
return String.fromCharCode(uint8array[start]);
|
|
193
|
+
}
|
|
194
|
+
if (stringByteLength === 2 && uint8array[start] < 128 && uint8array[start + 1] < 128) {
|
|
195
|
+
return String.fromCharCode(uint8array[start]) + String.fromCharCode(uint8array[start + 1]);
|
|
196
|
+
}
|
|
197
|
+
if (stringByteLength === 3 &&
|
|
198
|
+
uint8array[start] < 128 &&
|
|
199
|
+
uint8array[start + 1] < 128 &&
|
|
200
|
+
uint8array[start + 2] < 128) {
|
|
201
|
+
return (String.fromCharCode(uint8array[start]) +
|
|
202
|
+
String.fromCharCode(uint8array[start + 1]) +
|
|
203
|
+
String.fromCharCode(uint8array[start + 2]));
|
|
204
|
+
}
|
|
205
|
+
const latinBytes = [];
|
|
206
|
+
for (let i = start; i < end; i++) {
|
|
207
|
+
const byte = uint8array[i];
|
|
208
|
+
if (byte > 127) {
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
latinBytes.push(byte);
|
|
212
|
+
}
|
|
213
|
+
return String.fromCharCode(...latinBytes);
|
|
214
|
+
}
|
|
215
|
+
|
|
143
216
|
function nodejsMathRandomBytes(byteLength) {
|
|
144
217
|
return nodeJsByteUtils.fromNumberArray(Array.from({ length: byteLength }, () => Math.floor(Math.random() * 256)));
|
|
145
218
|
}
|
|
@@ -198,8 +271,23 @@ const nodeJsByteUtils = {
|
|
|
198
271
|
fromUTF8(text) {
|
|
199
272
|
return Buffer.from(text, 'utf8');
|
|
200
273
|
},
|
|
201
|
-
toUTF8(buffer, start, end) {
|
|
202
|
-
|
|
274
|
+
toUTF8(buffer, start, end, fatal) {
|
|
275
|
+
const basicLatin = end - start <= 20 ? tryLatin(buffer, start, end) : null;
|
|
276
|
+
if (basicLatin != null) {
|
|
277
|
+
return basicLatin;
|
|
278
|
+
}
|
|
279
|
+
const string = nodeJsByteUtils.toLocalBufferType(buffer).toString('utf8', start, end);
|
|
280
|
+
if (fatal) {
|
|
281
|
+
for (let i = 0; i < string.length; i++) {
|
|
282
|
+
if (string.charCodeAt(i) === 0xfffd) {
|
|
283
|
+
if (!validateUtf8(buffer, start, end)) {
|
|
284
|
+
throw new BSONError('Invalid UTF-8 string in BSON document');
|
|
285
|
+
}
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return string;
|
|
203
291
|
},
|
|
204
292
|
utf8ByteLength(input) {
|
|
205
293
|
return Buffer.byteLength(input, 'utf8');
|
|
@@ -311,8 +399,20 @@ const webByteUtils = {
|
|
|
311
399
|
fromUTF8(text) {
|
|
312
400
|
return new TextEncoder().encode(text);
|
|
313
401
|
},
|
|
314
|
-
toUTF8(uint8array, start, end) {
|
|
315
|
-
|
|
402
|
+
toUTF8(uint8array, start, end, fatal) {
|
|
403
|
+
const basicLatin = end - start <= 20 ? tryLatin(uint8array, start, end) : null;
|
|
404
|
+
if (basicLatin != null) {
|
|
405
|
+
return basicLatin;
|
|
406
|
+
}
|
|
407
|
+
if (fatal) {
|
|
408
|
+
try {
|
|
409
|
+
return new TextDecoder('utf8', { fatal }).decode(uint8array.slice(start, end));
|
|
410
|
+
}
|
|
411
|
+
catch (cause) {
|
|
412
|
+
throw new BSONError('Invalid UTF-8 string in BSON document', { cause });
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
return new TextDecoder('utf8', { fatal }).decode(uint8array.slice(start, end));
|
|
316
416
|
},
|
|
317
417
|
utf8ByteLength(input) {
|
|
318
418
|
return webByteUtils.fromUTF8(input).byteLength;
|
|
@@ -433,8 +533,8 @@ class Binary extends BSONValue {
|
|
|
433
533
|
if (encoding === 'base64')
|
|
434
534
|
return ByteUtils.toBase64(this.buffer);
|
|
435
535
|
if (encoding === 'utf8' || encoding === 'utf-8')
|
|
436
|
-
return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength);
|
|
437
|
-
return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength);
|
|
536
|
+
return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength, false);
|
|
537
|
+
return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength, false);
|
|
438
538
|
}
|
|
439
539
|
toExtendedJSON(options) {
|
|
440
540
|
options = options || {};
|
|
@@ -2522,43 +2622,6 @@ class Timestamp extends LongWithoutOverridesClass {
|
|
|
2522
2622
|
}
|
|
2523
2623
|
Timestamp.MAX_VALUE = Long.MAX_UNSIGNED_VALUE;
|
|
2524
2624
|
|
|
2525
|
-
const FIRST_BIT = 0x80;
|
|
2526
|
-
const FIRST_TWO_BITS = 0xc0;
|
|
2527
|
-
const FIRST_THREE_BITS = 0xe0;
|
|
2528
|
-
const FIRST_FOUR_BITS = 0xf0;
|
|
2529
|
-
const FIRST_FIVE_BITS = 0xf8;
|
|
2530
|
-
const TWO_BIT_CHAR = 0xc0;
|
|
2531
|
-
const THREE_BIT_CHAR = 0xe0;
|
|
2532
|
-
const FOUR_BIT_CHAR = 0xf0;
|
|
2533
|
-
const CONTINUING_CHAR = 0x80;
|
|
2534
|
-
function validateUtf8(bytes, start, end) {
|
|
2535
|
-
let continuation = 0;
|
|
2536
|
-
for (let i = start; i < end; i += 1) {
|
|
2537
|
-
const byte = bytes[i];
|
|
2538
|
-
if (continuation) {
|
|
2539
|
-
if ((byte & FIRST_TWO_BITS) !== CONTINUING_CHAR) {
|
|
2540
|
-
return false;
|
|
2541
|
-
}
|
|
2542
|
-
continuation -= 1;
|
|
2543
|
-
}
|
|
2544
|
-
else if (byte & FIRST_BIT) {
|
|
2545
|
-
if ((byte & FIRST_THREE_BITS) === TWO_BIT_CHAR) {
|
|
2546
|
-
continuation = 1;
|
|
2547
|
-
}
|
|
2548
|
-
else if ((byte & FIRST_FOUR_BITS) === THREE_BIT_CHAR) {
|
|
2549
|
-
continuation = 2;
|
|
2550
|
-
}
|
|
2551
|
-
else if ((byte & FIRST_FIVE_BITS) === FOUR_BIT_CHAR) {
|
|
2552
|
-
continuation = 3;
|
|
2553
|
-
}
|
|
2554
|
-
else {
|
|
2555
|
-
return false;
|
|
2556
|
-
}
|
|
2557
|
-
}
|
|
2558
|
-
}
|
|
2559
|
-
return !continuation;
|
|
2560
|
-
}
|
|
2561
|
-
|
|
2562
2625
|
const JS_INT_MAX_LONG = Long.fromNumber(JS_INT_MAX);
|
|
2563
2626
|
const JS_INT_MIN_LONG = Long.fromNumber(JS_INT_MIN);
|
|
2564
2627
|
function internalDeserialize(buffer, options, isArray) {
|
|
@@ -2650,7 +2713,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
2650
2713
|
}
|
|
2651
2714
|
if (i >= buffer.byteLength)
|
|
2652
2715
|
throw new BSONError('Bad BSON Document: illegal CString');
|
|
2653
|
-
const name = isArray ? arrayIndex++ : ByteUtils.toUTF8(buffer, index, i);
|
|
2716
|
+
const name = isArray ? arrayIndex++ : ByteUtils.toUTF8(buffer, index, i, false);
|
|
2654
2717
|
let shouldValidateKey = true;
|
|
2655
2718
|
if (globalUTFValidation || utf8KeysSet.has(name)) {
|
|
2656
2719
|
shouldValidateKey = validationSetting;
|
|
@@ -2673,7 +2736,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
2673
2736
|
buffer[index + stringSize - 1] !== 0) {
|
|
2674
2737
|
throw new BSONError('bad string length in bson');
|
|
2675
2738
|
}
|
|
2676
|
-
value =
|
|
2739
|
+
value = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
|
|
2677
2740
|
index = index + stringSize;
|
|
2678
2741
|
}
|
|
2679
2742
|
else if (elementType === BSON_DATA_OID) {
|
|
@@ -2865,7 +2928,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
2865
2928
|
}
|
|
2866
2929
|
if (i >= buffer.length)
|
|
2867
2930
|
throw new BSONError('Bad BSON Document: illegal CString');
|
|
2868
|
-
const source = ByteUtils.toUTF8(buffer, index, i);
|
|
2931
|
+
const source = ByteUtils.toUTF8(buffer, index, i, false);
|
|
2869
2932
|
index = i + 1;
|
|
2870
2933
|
i = index;
|
|
2871
2934
|
while (buffer[i] !== 0x00 && i < buffer.length) {
|
|
@@ -2873,7 +2936,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
2873
2936
|
}
|
|
2874
2937
|
if (i >= buffer.length)
|
|
2875
2938
|
throw new BSONError('Bad BSON Document: illegal CString');
|
|
2876
|
-
const regExpOptions = ByteUtils.toUTF8(buffer, index, i);
|
|
2939
|
+
const regExpOptions = ByteUtils.toUTF8(buffer, index, i, false);
|
|
2877
2940
|
index = i + 1;
|
|
2878
2941
|
const optionsArray = new Array(regExpOptions.length);
|
|
2879
2942
|
for (i = 0; i < regExpOptions.length; i++) {
|
|
@@ -2898,7 +2961,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
2898
2961
|
}
|
|
2899
2962
|
if (i >= buffer.length)
|
|
2900
2963
|
throw new BSONError('Bad BSON Document: illegal CString');
|
|
2901
|
-
const source = ByteUtils.toUTF8(buffer, index, i);
|
|
2964
|
+
const source = ByteUtils.toUTF8(buffer, index, i, false);
|
|
2902
2965
|
index = i + 1;
|
|
2903
2966
|
i = index;
|
|
2904
2967
|
while (buffer[i] !== 0x00 && i < buffer.length) {
|
|
@@ -2906,7 +2969,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
2906
2969
|
}
|
|
2907
2970
|
if (i >= buffer.length)
|
|
2908
2971
|
throw new BSONError('Bad BSON Document: illegal CString');
|
|
2909
|
-
const regExpOptions = ByteUtils.toUTF8(buffer, index, i);
|
|
2972
|
+
const regExpOptions = ByteUtils.toUTF8(buffer, index, i, false);
|
|
2910
2973
|
index = i + 1;
|
|
2911
2974
|
value = new BSONRegExp(source, regExpOptions);
|
|
2912
2975
|
}
|
|
@@ -2920,7 +2983,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
2920
2983
|
buffer[index + stringSize - 1] !== 0) {
|
|
2921
2984
|
throw new BSONError('bad string length in bson');
|
|
2922
2985
|
}
|
|
2923
|
-
const symbol =
|
|
2986
|
+
const symbol = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
|
|
2924
2987
|
value = promoteValues ? symbol : new BSONSymbol(symbol);
|
|
2925
2988
|
index = index + stringSize;
|
|
2926
2989
|
}
|
|
@@ -2951,7 +3014,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
2951
3014
|
buffer[index + stringSize - 1] !== 0) {
|
|
2952
3015
|
throw new BSONError('bad string length in bson');
|
|
2953
3016
|
}
|
|
2954
|
-
const functionString =
|
|
3017
|
+
const functionString = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
|
|
2955
3018
|
value = new Code(functionString);
|
|
2956
3019
|
index = index + stringSize;
|
|
2957
3020
|
}
|
|
@@ -2972,7 +3035,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
2972
3035
|
buffer[index + stringSize - 1] !== 0) {
|
|
2973
3036
|
throw new BSONError('bad string length in bson');
|
|
2974
3037
|
}
|
|
2975
|
-
const functionString =
|
|
3038
|
+
const functionString = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
|
|
2976
3039
|
index = index + stringSize;
|
|
2977
3040
|
const _index = index;
|
|
2978
3041
|
const objectSize = buffer[index] |
|
|
@@ -3003,7 +3066,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
3003
3066
|
throw new BSONError('Invalid UTF-8 string in BSON document');
|
|
3004
3067
|
}
|
|
3005
3068
|
}
|
|
3006
|
-
const namespace = ByteUtils.toUTF8(buffer, index, index + stringSize - 1);
|
|
3069
|
+
const namespace = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, false);
|
|
3007
3070
|
index = index + stringSize;
|
|
3008
3071
|
const oidBuffer = ByteUtils.allocate(12);
|
|
3009
3072
|
oidBuffer.set(buffer.subarray(index, index + 12), 0);
|
|
@@ -3042,20 +3105,6 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
3042
3105
|
}
|
|
3043
3106
|
return object;
|
|
3044
3107
|
}
|
|
3045
|
-
function getValidatedString(buffer, start, end, shouldValidateUtf8) {
|
|
3046
|
-
const value = ByteUtils.toUTF8(buffer, start, end);
|
|
3047
|
-
if (shouldValidateUtf8) {
|
|
3048
|
-
for (let i = 0; i < value.length; i++) {
|
|
3049
|
-
if (value.charCodeAt(i) === 0xfffd) {
|
|
3050
|
-
if (!validateUtf8(buffer, start, end)) {
|
|
3051
|
-
throw new BSONError('Invalid UTF-8 string in BSON document');
|
|
3052
|
-
}
|
|
3053
|
-
break;
|
|
3054
|
-
}
|
|
3055
|
-
}
|
|
3056
|
-
}
|
|
3057
|
-
return value;
|
|
3058
|
-
}
|
|
3059
3108
|
|
|
3060
3109
|
const regexp = /\x00/;
|
|
3061
3110
|
const ignoreKeys = new Set(['$db', '$ref', '$id', '$clusterTime']);
|