bson 6.6.0 → 6.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -0
- package/bson.d.ts +148 -7
- package/lib/bson.bundle.js +134 -74
- package/lib/bson.bundle.js.map +1 -1
- package/lib/bson.cjs +134 -74
- package/lib/bson.cjs.map +1 -1
- package/lib/bson.mjs +134 -74
- package/lib/bson.mjs.map +1 -1
- package/lib/bson.rn.cjs +136 -75
- package/lib/bson.rn.cjs.map +1 -1
- package/package.json +14 -15
- package/src/constants.ts +1 -1
- package/src/double.ts +36 -0
- package/src/int_32.ts +34 -0
- package/src/long.ts +211 -31
- package/src/parse_utf8.ts +35 -0
- package/src/parser/deserializer.ts +1 -7
- package/src/utils/node_byte_utils.ts +2 -5
- package/src/utils/string_utils.ts +44 -0
- package/src/utils/web_byte_utils.ts +2 -8
- package/src/validate_utf8.ts +0 -47
package/lib/bson.rn.cjs
CHANGED
|
@@ -150,41 +150,21 @@ class BSONOffsetError extends BSONError {
|
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
const CONTINUING_CHAR = 0x80;
|
|
162
|
-
function validateUtf8(bytes, start, end) {
|
|
163
|
-
let continuation = 0;
|
|
164
|
-
for (let i = start; i < end; i += 1) {
|
|
165
|
-
const byte = bytes[i];
|
|
166
|
-
if (continuation) {
|
|
167
|
-
if ((byte & FIRST_TWO_BITS) !== CONTINUING_CHAR) {
|
|
168
|
-
return false;
|
|
169
|
-
}
|
|
170
|
-
continuation -= 1;
|
|
153
|
+
const { TextDecoder } = require('../vendor/text-encoding');
|
|
154
|
+
let TextDecoderFatal;
|
|
155
|
+
let TextDecoderNonFatal;
|
|
156
|
+
function parseUtf8(buffer, start, end, fatal) {
|
|
157
|
+
if (fatal) {
|
|
158
|
+
TextDecoderFatal ??= new TextDecoder('utf8', { fatal: true });
|
|
159
|
+
try {
|
|
160
|
+
return TextDecoderFatal.decode(buffer.subarray(start, end));
|
|
171
161
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
continuation = 1;
|
|
175
|
-
}
|
|
176
|
-
else if ((byte & FIRST_FOUR_BITS) === THREE_BIT_CHAR) {
|
|
177
|
-
continuation = 2;
|
|
178
|
-
}
|
|
179
|
-
else if ((byte & FIRST_FIVE_BITS) === FOUR_BIT_CHAR) {
|
|
180
|
-
continuation = 3;
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
return false;
|
|
184
|
-
}
|
|
162
|
+
catch (cause) {
|
|
163
|
+
throw new BSONError('Invalid UTF-8 string in BSON document', { cause });
|
|
185
164
|
}
|
|
186
165
|
}
|
|
187
|
-
|
|
166
|
+
TextDecoderNonFatal ??= new TextDecoder('utf8', { fatal: false });
|
|
167
|
+
return TextDecoderNonFatal.decode(buffer.subarray(start, end));
|
|
188
168
|
}
|
|
189
169
|
|
|
190
170
|
function tryReadBasicLatin(uint8array, start, end) {
|
|
@@ -305,9 +285,7 @@ const nodeJsByteUtils = {
|
|
|
305
285
|
if (fatal) {
|
|
306
286
|
for (let i = 0; i < string.length; i++) {
|
|
307
287
|
if (string.charCodeAt(i) === 0xfffd) {
|
|
308
|
-
|
|
309
|
-
throw new BSONError('Invalid UTF-8 string in BSON document');
|
|
310
|
-
}
|
|
288
|
+
parseUtf8(buffer, start, end, true);
|
|
311
289
|
break;
|
|
312
290
|
}
|
|
313
291
|
}
|
|
@@ -327,7 +305,7 @@ const nodeJsByteUtils = {
|
|
|
327
305
|
randomBytes: nodejsRandomBytes
|
|
328
306
|
};
|
|
329
307
|
|
|
330
|
-
const { TextEncoder
|
|
308
|
+
const { TextEncoder } = require('../vendor/text-encoding');
|
|
331
309
|
const { encode: btoa, decode: atob } = require('../vendor/base64');
|
|
332
310
|
function isReactNative() {
|
|
333
311
|
const { navigator } = globalThis;
|
|
@@ -433,15 +411,7 @@ const webByteUtils = {
|
|
|
433
411
|
if (basicLatin != null) {
|
|
434
412
|
return basicLatin;
|
|
435
413
|
}
|
|
436
|
-
|
|
437
|
-
try {
|
|
438
|
-
return new TextDecoder('utf8', { fatal }).decode(uint8array.slice(start, end));
|
|
439
|
-
}
|
|
440
|
-
catch (cause) {
|
|
441
|
-
throw new BSONError('Invalid UTF-8 string in BSON document', { cause });
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
return new TextDecoder('utf8', { fatal }).decode(uint8array.slice(start, end));
|
|
414
|
+
return parseUtf8(uint8array, start, end, fatal);
|
|
445
415
|
},
|
|
446
416
|
utf8ByteLength(input) {
|
|
447
417
|
return new TextEncoder().encode(input).byteLength;
|
|
@@ -854,6 +824,32 @@ class DBRef extends BSONValue {
|
|
|
854
824
|
}
|
|
855
825
|
}
|
|
856
826
|
|
|
827
|
+
function removeLeadingZerosAndExplicitPlus(str) {
|
|
828
|
+
if (str === '') {
|
|
829
|
+
return str;
|
|
830
|
+
}
|
|
831
|
+
let startIndex = 0;
|
|
832
|
+
const isNegative = str[startIndex] === '-';
|
|
833
|
+
const isExplicitlyPositive = str[startIndex] === '+';
|
|
834
|
+
if (isExplicitlyPositive || isNegative) {
|
|
835
|
+
startIndex += 1;
|
|
836
|
+
}
|
|
837
|
+
let foundInsignificantZero = false;
|
|
838
|
+
for (; startIndex < str.length && str[startIndex] === '0'; ++startIndex) {
|
|
839
|
+
foundInsignificantZero = true;
|
|
840
|
+
}
|
|
841
|
+
if (!foundInsignificantZero) {
|
|
842
|
+
return isExplicitlyPositive ? str.slice(1) : str;
|
|
843
|
+
}
|
|
844
|
+
return `${isNegative ? '-' : ''}${str.length === startIndex ? '0' : str.slice(startIndex)}`;
|
|
845
|
+
}
|
|
846
|
+
function validateStringCharacters(str, radix) {
|
|
847
|
+
radix = radix ?? 10;
|
|
848
|
+
const validCharacters = '0123456789abcdefghijklmnopqrstuvwxyz'.slice(0, radix);
|
|
849
|
+
const regex = new RegExp(`[^-+${validCharacters}]`, 'i');
|
|
850
|
+
return regex.test(str) ? false : str;
|
|
851
|
+
}
|
|
852
|
+
|
|
857
853
|
let wasm = undefined;
|
|
858
854
|
try {
|
|
859
855
|
wasm = new WebAssembly.Instance(new WebAssembly.Module(new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 13, 2, 96, 0, 1, 127, 96, 4, 127, 127, 127, 127, 1, 127, 3, 7, 6, 0, 1, 1, 1, 1, 1, 6, 6, 1, 127, 1, 65, 0, 11, 7, 50, 6, 3, 109, 117, 108, 0, 1, 5, 100, 105, 118, 95, 115, 0, 2, 5, 100, 105, 118, 95, 117, 0, 3, 5, 114, 101, 109, 95, 115, 0, 4, 5, 114, 101, 109, 95, 117, 0, 5, 8, 103, 101, 116, 95, 104, 105, 103, 104, 0, 0, 10, 191, 1, 6, 4, 0, 35, 0, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 126, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 127, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 128, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 129, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 130, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11])), {}).exports;
|
|
@@ -876,19 +872,18 @@ class Long extends BSONValue {
|
|
|
876
872
|
get __isLong__() {
|
|
877
873
|
return true;
|
|
878
874
|
}
|
|
879
|
-
constructor(
|
|
875
|
+
constructor(lowOrValue = 0, highOrUnsigned, unsigned) {
|
|
880
876
|
super();
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
}
|
|
877
|
+
const unsignedBool = typeof highOrUnsigned === 'boolean' ? highOrUnsigned : Boolean(unsigned);
|
|
878
|
+
const high = typeof highOrUnsigned === 'number' ? highOrUnsigned : 0;
|
|
879
|
+
const res = typeof lowOrValue === 'string'
|
|
880
|
+
? Long.fromString(lowOrValue, unsignedBool)
|
|
881
|
+
: typeof lowOrValue === 'bigint'
|
|
882
|
+
? Long.fromBigInt(lowOrValue, unsignedBool)
|
|
883
|
+
: { low: lowOrValue | 0, high: high | 0, unsigned: unsignedBool };
|
|
884
|
+
this.low = res.low;
|
|
885
|
+
this.high = res.high;
|
|
886
|
+
this.unsigned = res.unsigned;
|
|
892
887
|
}
|
|
893
888
|
static fromBits(lowBits, highBits, unsigned) {
|
|
894
889
|
return new Long(lowBits, highBits, unsigned);
|
|
@@ -940,27 +935,20 @@ class Long extends BSONValue {
|
|
|
940
935
|
return Long.fromBits(value % TWO_PWR_32_DBL | 0, (value / TWO_PWR_32_DBL) | 0, unsigned);
|
|
941
936
|
}
|
|
942
937
|
static fromBigInt(value, unsigned) {
|
|
943
|
-
|
|
938
|
+
const FROM_BIGINT_BIT_MASK = BigInt(0xffffffff);
|
|
939
|
+
const FROM_BIGINT_BIT_SHIFT = BigInt(32);
|
|
940
|
+
return new Long(Number(value & FROM_BIGINT_BIT_MASK), Number((value >> FROM_BIGINT_BIT_SHIFT) & FROM_BIGINT_BIT_MASK), unsigned);
|
|
944
941
|
}
|
|
945
|
-
static
|
|
942
|
+
static _fromString(str, unsigned, radix) {
|
|
946
943
|
if (str.length === 0)
|
|
947
944
|
throw new BSONError('empty string');
|
|
948
|
-
if (str === 'NaN' || str === 'Infinity' || str === '+Infinity' || str === '-Infinity')
|
|
949
|
-
return Long.ZERO;
|
|
950
|
-
if (typeof unsigned === 'number') {
|
|
951
|
-
(radix = unsigned), (unsigned = false);
|
|
952
|
-
}
|
|
953
|
-
else {
|
|
954
|
-
unsigned = !!unsigned;
|
|
955
|
-
}
|
|
956
|
-
radix = radix || 10;
|
|
957
945
|
if (radix < 2 || 36 < radix)
|
|
958
946
|
throw new BSONError('radix');
|
|
959
947
|
let p;
|
|
960
948
|
if ((p = str.indexOf('-')) > 0)
|
|
961
949
|
throw new BSONError('interior hyphen');
|
|
962
950
|
else if (p === 0) {
|
|
963
|
-
return Long.
|
|
951
|
+
return Long._fromString(str.substring(1), unsigned, radix).neg();
|
|
964
952
|
}
|
|
965
953
|
const radixToPower = Long.fromNumber(Math.pow(radix, 8));
|
|
966
954
|
let result = Long.ZERO;
|
|
@@ -978,6 +966,45 @@ class Long extends BSONValue {
|
|
|
978
966
|
result.unsigned = unsigned;
|
|
979
967
|
return result;
|
|
980
968
|
}
|
|
969
|
+
static fromStringStrict(str, unsignedOrRadix, radix) {
|
|
970
|
+
let unsigned = false;
|
|
971
|
+
if (typeof unsignedOrRadix === 'number') {
|
|
972
|
+
(radix = unsignedOrRadix), (unsignedOrRadix = false);
|
|
973
|
+
}
|
|
974
|
+
else {
|
|
975
|
+
unsigned = !!unsignedOrRadix;
|
|
976
|
+
}
|
|
977
|
+
radix ??= 10;
|
|
978
|
+
if (str.trim() !== str) {
|
|
979
|
+
throw new BSONError(`Input: '${str}' contains leading and/or trailing whitespace`);
|
|
980
|
+
}
|
|
981
|
+
if (!validateStringCharacters(str, radix)) {
|
|
982
|
+
throw new BSONError(`Input: '${str}' contains invalid characters for radix: ${radix}`);
|
|
983
|
+
}
|
|
984
|
+
const cleanedStr = removeLeadingZerosAndExplicitPlus(str);
|
|
985
|
+
const result = Long._fromString(cleanedStr, unsigned, radix);
|
|
986
|
+
if (result.toString(radix).toLowerCase() !== cleanedStr.toLowerCase()) {
|
|
987
|
+
throw new BSONError(`Input: ${str} is not representable as ${result.unsigned ? 'an unsigned' : 'a signed'} 64-bit Long ${radix != null ? `with radix: ${radix}` : ''}`);
|
|
988
|
+
}
|
|
989
|
+
return result;
|
|
990
|
+
}
|
|
991
|
+
static fromString(str, unsignedOrRadix, radix) {
|
|
992
|
+
let unsigned = false;
|
|
993
|
+
if (typeof unsignedOrRadix === 'number') {
|
|
994
|
+
(radix = unsignedOrRadix), (unsignedOrRadix = false);
|
|
995
|
+
}
|
|
996
|
+
else {
|
|
997
|
+
unsigned = !!unsignedOrRadix;
|
|
998
|
+
}
|
|
999
|
+
radix ??= 10;
|
|
1000
|
+
if (str === 'NaN' && radix < 24) {
|
|
1001
|
+
return Long.ZERO;
|
|
1002
|
+
}
|
|
1003
|
+
else if ((str === 'Infinity' || str === '+Infinity' || str === '-Infinity') && radix < 35) {
|
|
1004
|
+
return Long.ZERO;
|
|
1005
|
+
}
|
|
1006
|
+
return Long._fromString(str, unsigned, radix);
|
|
1007
|
+
}
|
|
981
1008
|
static fromBytes(bytes, unsigned, le) {
|
|
982
1009
|
return le ? Long.fromBytesLE(bytes, unsigned) : Long.fromBytesBE(bytes, unsigned);
|
|
983
1010
|
}
|
|
@@ -2055,6 +2082,28 @@ class Double extends BSONValue {
|
|
|
2055
2082
|
}
|
|
2056
2083
|
this.value = +value;
|
|
2057
2084
|
}
|
|
2085
|
+
static fromString(value) {
|
|
2086
|
+
const coercedValue = Number(value);
|
|
2087
|
+
if (value === 'NaN')
|
|
2088
|
+
return new Double(NaN);
|
|
2089
|
+
if (value === 'Infinity')
|
|
2090
|
+
return new Double(Infinity);
|
|
2091
|
+
if (value === '-Infinity')
|
|
2092
|
+
return new Double(-Infinity);
|
|
2093
|
+
if (!Number.isFinite(coercedValue)) {
|
|
2094
|
+
throw new BSONError(`Input: ${value} is not representable as a Double`);
|
|
2095
|
+
}
|
|
2096
|
+
if (value.trim() !== value) {
|
|
2097
|
+
throw new BSONError(`Input: '${value}' contains whitespace`);
|
|
2098
|
+
}
|
|
2099
|
+
if (value === '') {
|
|
2100
|
+
throw new BSONError(`Input is an empty string`);
|
|
2101
|
+
}
|
|
2102
|
+
if (/[^-0-9.+eE]/.test(value)) {
|
|
2103
|
+
throw new BSONError(`Input: '${value}' is not in decimal or exponential notation`);
|
|
2104
|
+
}
|
|
2105
|
+
return new Double(coercedValue);
|
|
2106
|
+
}
|
|
2058
2107
|
valueOf() {
|
|
2059
2108
|
return this.value;
|
|
2060
2109
|
}
|
|
@@ -2096,6 +2145,23 @@ class Int32 extends BSONValue {
|
|
|
2096
2145
|
}
|
|
2097
2146
|
this.value = +value | 0;
|
|
2098
2147
|
}
|
|
2148
|
+
static fromString(value) {
|
|
2149
|
+
const cleanedValue = removeLeadingZerosAndExplicitPlus(value);
|
|
2150
|
+
const coercedValue = Number(value);
|
|
2151
|
+
if (BSON_INT32_MAX < coercedValue) {
|
|
2152
|
+
throw new BSONError(`Input: '${value}' is larger than the maximum value for Int32`);
|
|
2153
|
+
}
|
|
2154
|
+
else if (BSON_INT32_MIN > coercedValue) {
|
|
2155
|
+
throw new BSONError(`Input: '${value}' is smaller than the minimum value for Int32`);
|
|
2156
|
+
}
|
|
2157
|
+
else if (!Number.isSafeInteger(coercedValue)) {
|
|
2158
|
+
throw new BSONError(`Input: '${value}' is not a safe integer`);
|
|
2159
|
+
}
|
|
2160
|
+
else if (coercedValue.toString() !== cleanedValue) {
|
|
2161
|
+
throw new BSONError(`Input: '${value}' is not a valid Int32 string`);
|
|
2162
|
+
}
|
|
2163
|
+
return new Int32(coercedValue);
|
|
2164
|
+
}
|
|
2099
2165
|
valueOf() {
|
|
2100
2166
|
return this.value;
|
|
2101
2167
|
}
|
|
@@ -3183,12 +3249,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
3183
3249
|
stringSize > buffer.length - index ||
|
|
3184
3250
|
buffer[index + stringSize - 1] !== 0)
|
|
3185
3251
|
throw new BSONError('bad string length in bson');
|
|
3186
|
-
|
|
3187
|
-
if (!validateUtf8(buffer, index, index + stringSize - 1)) {
|
|
3188
|
-
throw new BSONError('Invalid UTF-8 string in BSON document');
|
|
3189
|
-
}
|
|
3190
|
-
}
|
|
3191
|
-
const namespace = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, false);
|
|
3252
|
+
const namespace = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
|
|
3192
3253
|
index = index + stringSize;
|
|
3193
3254
|
const oidBuffer = ByteUtils.allocateUnsafe(12);
|
|
3194
3255
|
for (let i = 0; i < 12; i++)
|