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.cjs
CHANGED
|
@@ -136,41 +136,20 @@ class BSONOffsetError extends BSONError {
|
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const FOUR_BIT_CHAR = 0xf0;
|
|
147
|
-
const CONTINUING_CHAR = 0x80;
|
|
148
|
-
function validateUtf8(bytes, start, end) {
|
|
149
|
-
let continuation = 0;
|
|
150
|
-
for (let i = start; i < end; i += 1) {
|
|
151
|
-
const byte = bytes[i];
|
|
152
|
-
if (continuation) {
|
|
153
|
-
if ((byte & FIRST_TWO_BITS) !== CONTINUING_CHAR) {
|
|
154
|
-
return false;
|
|
155
|
-
}
|
|
156
|
-
continuation -= 1;
|
|
139
|
+
let TextDecoderFatal;
|
|
140
|
+
let TextDecoderNonFatal;
|
|
141
|
+
function parseUtf8(buffer, start, end, fatal) {
|
|
142
|
+
if (fatal) {
|
|
143
|
+
TextDecoderFatal ??= new TextDecoder('utf8', { fatal: true });
|
|
144
|
+
try {
|
|
145
|
+
return TextDecoderFatal.decode(buffer.subarray(start, end));
|
|
157
146
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
continuation = 1;
|
|
161
|
-
}
|
|
162
|
-
else if ((byte & FIRST_FOUR_BITS) === THREE_BIT_CHAR) {
|
|
163
|
-
continuation = 2;
|
|
164
|
-
}
|
|
165
|
-
else if ((byte & FIRST_FIVE_BITS) === FOUR_BIT_CHAR) {
|
|
166
|
-
continuation = 3;
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
return false;
|
|
170
|
-
}
|
|
147
|
+
catch (cause) {
|
|
148
|
+
throw new BSONError('Invalid UTF-8 string in BSON document', { cause });
|
|
171
149
|
}
|
|
172
150
|
}
|
|
173
|
-
|
|
151
|
+
TextDecoderNonFatal ??= new TextDecoder('utf8', { fatal: false });
|
|
152
|
+
return TextDecoderNonFatal.decode(buffer.subarray(start, end));
|
|
174
153
|
}
|
|
175
154
|
|
|
176
155
|
function tryReadBasicLatin(uint8array, start, end) {
|
|
@@ -291,9 +270,7 @@ const nodeJsByteUtils = {
|
|
|
291
270
|
if (fatal) {
|
|
292
271
|
for (let i = 0; i < string.length; i++) {
|
|
293
272
|
if (string.charCodeAt(i) === 0xfffd) {
|
|
294
|
-
|
|
295
|
-
throw new BSONError('Invalid UTF-8 string in BSON document');
|
|
296
|
-
}
|
|
273
|
+
parseUtf8(buffer, start, end, true);
|
|
297
274
|
break;
|
|
298
275
|
}
|
|
299
276
|
}
|
|
@@ -417,15 +394,7 @@ const webByteUtils = {
|
|
|
417
394
|
if (basicLatin != null) {
|
|
418
395
|
return basicLatin;
|
|
419
396
|
}
|
|
420
|
-
|
|
421
|
-
try {
|
|
422
|
-
return new TextDecoder('utf8', { fatal }).decode(uint8array.slice(start, end));
|
|
423
|
-
}
|
|
424
|
-
catch (cause) {
|
|
425
|
-
throw new BSONError('Invalid UTF-8 string in BSON document', { cause });
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
return new TextDecoder('utf8', { fatal }).decode(uint8array.slice(start, end));
|
|
397
|
+
return parseUtf8(uint8array, start, end, fatal);
|
|
429
398
|
},
|
|
430
399
|
utf8ByteLength(input) {
|
|
431
400
|
return new TextEncoder().encode(input).byteLength;
|
|
@@ -838,6 +807,32 @@ class DBRef extends BSONValue {
|
|
|
838
807
|
}
|
|
839
808
|
}
|
|
840
809
|
|
|
810
|
+
function removeLeadingZerosAndExplicitPlus(str) {
|
|
811
|
+
if (str === '') {
|
|
812
|
+
return str;
|
|
813
|
+
}
|
|
814
|
+
let startIndex = 0;
|
|
815
|
+
const isNegative = str[startIndex] === '-';
|
|
816
|
+
const isExplicitlyPositive = str[startIndex] === '+';
|
|
817
|
+
if (isExplicitlyPositive || isNegative) {
|
|
818
|
+
startIndex += 1;
|
|
819
|
+
}
|
|
820
|
+
let foundInsignificantZero = false;
|
|
821
|
+
for (; startIndex < str.length && str[startIndex] === '0'; ++startIndex) {
|
|
822
|
+
foundInsignificantZero = true;
|
|
823
|
+
}
|
|
824
|
+
if (!foundInsignificantZero) {
|
|
825
|
+
return isExplicitlyPositive ? str.slice(1) : str;
|
|
826
|
+
}
|
|
827
|
+
return `${isNegative ? '-' : ''}${str.length === startIndex ? '0' : str.slice(startIndex)}`;
|
|
828
|
+
}
|
|
829
|
+
function validateStringCharacters(str, radix) {
|
|
830
|
+
radix = radix ?? 10;
|
|
831
|
+
const validCharacters = '0123456789abcdefghijklmnopqrstuvwxyz'.slice(0, radix);
|
|
832
|
+
const regex = new RegExp(`[^-+${validCharacters}]`, 'i');
|
|
833
|
+
return regex.test(str) ? false : str;
|
|
834
|
+
}
|
|
835
|
+
|
|
841
836
|
let wasm = undefined;
|
|
842
837
|
try {
|
|
843
838
|
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;
|
|
@@ -860,19 +855,18 @@ class Long extends BSONValue {
|
|
|
860
855
|
get __isLong__() {
|
|
861
856
|
return true;
|
|
862
857
|
}
|
|
863
|
-
constructor(
|
|
858
|
+
constructor(lowOrValue = 0, highOrUnsigned, unsigned) {
|
|
864
859
|
super();
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
}
|
|
860
|
+
const unsignedBool = typeof highOrUnsigned === 'boolean' ? highOrUnsigned : Boolean(unsigned);
|
|
861
|
+
const high = typeof highOrUnsigned === 'number' ? highOrUnsigned : 0;
|
|
862
|
+
const res = typeof lowOrValue === 'string'
|
|
863
|
+
? Long.fromString(lowOrValue, unsignedBool)
|
|
864
|
+
: typeof lowOrValue === 'bigint'
|
|
865
|
+
? Long.fromBigInt(lowOrValue, unsignedBool)
|
|
866
|
+
: { low: lowOrValue | 0, high: high | 0, unsigned: unsignedBool };
|
|
867
|
+
this.low = res.low;
|
|
868
|
+
this.high = res.high;
|
|
869
|
+
this.unsigned = res.unsigned;
|
|
876
870
|
}
|
|
877
871
|
static fromBits(lowBits, highBits, unsigned) {
|
|
878
872
|
return new Long(lowBits, highBits, unsigned);
|
|
@@ -924,27 +918,20 @@ class Long extends BSONValue {
|
|
|
924
918
|
return Long.fromBits(value % TWO_PWR_32_DBL | 0, (value / TWO_PWR_32_DBL) | 0, unsigned);
|
|
925
919
|
}
|
|
926
920
|
static fromBigInt(value, unsigned) {
|
|
927
|
-
|
|
921
|
+
const FROM_BIGINT_BIT_MASK = BigInt(0xffffffff);
|
|
922
|
+
const FROM_BIGINT_BIT_SHIFT = BigInt(32);
|
|
923
|
+
return new Long(Number(value & FROM_BIGINT_BIT_MASK), Number((value >> FROM_BIGINT_BIT_SHIFT) & FROM_BIGINT_BIT_MASK), unsigned);
|
|
928
924
|
}
|
|
929
|
-
static
|
|
925
|
+
static _fromString(str, unsigned, radix) {
|
|
930
926
|
if (str.length === 0)
|
|
931
927
|
throw new BSONError('empty string');
|
|
932
|
-
if (str === 'NaN' || str === 'Infinity' || str === '+Infinity' || str === '-Infinity')
|
|
933
|
-
return Long.ZERO;
|
|
934
|
-
if (typeof unsigned === 'number') {
|
|
935
|
-
(radix = unsigned), (unsigned = false);
|
|
936
|
-
}
|
|
937
|
-
else {
|
|
938
|
-
unsigned = !!unsigned;
|
|
939
|
-
}
|
|
940
|
-
radix = radix || 10;
|
|
941
928
|
if (radix < 2 || 36 < radix)
|
|
942
929
|
throw new BSONError('radix');
|
|
943
930
|
let p;
|
|
944
931
|
if ((p = str.indexOf('-')) > 0)
|
|
945
932
|
throw new BSONError('interior hyphen');
|
|
946
933
|
else if (p === 0) {
|
|
947
|
-
return Long.
|
|
934
|
+
return Long._fromString(str.substring(1), unsigned, radix).neg();
|
|
948
935
|
}
|
|
949
936
|
const radixToPower = Long.fromNumber(Math.pow(radix, 8));
|
|
950
937
|
let result = Long.ZERO;
|
|
@@ -962,6 +949,45 @@ class Long extends BSONValue {
|
|
|
962
949
|
result.unsigned = unsigned;
|
|
963
950
|
return result;
|
|
964
951
|
}
|
|
952
|
+
static fromStringStrict(str, unsignedOrRadix, radix) {
|
|
953
|
+
let unsigned = false;
|
|
954
|
+
if (typeof unsignedOrRadix === 'number') {
|
|
955
|
+
(radix = unsignedOrRadix), (unsignedOrRadix = false);
|
|
956
|
+
}
|
|
957
|
+
else {
|
|
958
|
+
unsigned = !!unsignedOrRadix;
|
|
959
|
+
}
|
|
960
|
+
radix ??= 10;
|
|
961
|
+
if (str.trim() !== str) {
|
|
962
|
+
throw new BSONError(`Input: '${str}' contains leading and/or trailing whitespace`);
|
|
963
|
+
}
|
|
964
|
+
if (!validateStringCharacters(str, radix)) {
|
|
965
|
+
throw new BSONError(`Input: '${str}' contains invalid characters for radix: ${radix}`);
|
|
966
|
+
}
|
|
967
|
+
const cleanedStr = removeLeadingZerosAndExplicitPlus(str);
|
|
968
|
+
const result = Long._fromString(cleanedStr, unsigned, radix);
|
|
969
|
+
if (result.toString(radix).toLowerCase() !== cleanedStr.toLowerCase()) {
|
|
970
|
+
throw new BSONError(`Input: ${str} is not representable as ${result.unsigned ? 'an unsigned' : 'a signed'} 64-bit Long ${radix != null ? `with radix: ${radix}` : ''}`);
|
|
971
|
+
}
|
|
972
|
+
return result;
|
|
973
|
+
}
|
|
974
|
+
static fromString(str, unsignedOrRadix, radix) {
|
|
975
|
+
let unsigned = false;
|
|
976
|
+
if (typeof unsignedOrRadix === 'number') {
|
|
977
|
+
(radix = unsignedOrRadix), (unsignedOrRadix = false);
|
|
978
|
+
}
|
|
979
|
+
else {
|
|
980
|
+
unsigned = !!unsignedOrRadix;
|
|
981
|
+
}
|
|
982
|
+
radix ??= 10;
|
|
983
|
+
if (str === 'NaN' && radix < 24) {
|
|
984
|
+
return Long.ZERO;
|
|
985
|
+
}
|
|
986
|
+
else if ((str === 'Infinity' || str === '+Infinity' || str === '-Infinity') && radix < 35) {
|
|
987
|
+
return Long.ZERO;
|
|
988
|
+
}
|
|
989
|
+
return Long._fromString(str, unsigned, radix);
|
|
990
|
+
}
|
|
965
991
|
static fromBytes(bytes, unsigned, le) {
|
|
966
992
|
return le ? Long.fromBytesLE(bytes, unsigned) : Long.fromBytesBE(bytes, unsigned);
|
|
967
993
|
}
|
|
@@ -2039,6 +2065,28 @@ class Double extends BSONValue {
|
|
|
2039
2065
|
}
|
|
2040
2066
|
this.value = +value;
|
|
2041
2067
|
}
|
|
2068
|
+
static fromString(value) {
|
|
2069
|
+
const coercedValue = Number(value);
|
|
2070
|
+
if (value === 'NaN')
|
|
2071
|
+
return new Double(NaN);
|
|
2072
|
+
if (value === 'Infinity')
|
|
2073
|
+
return new Double(Infinity);
|
|
2074
|
+
if (value === '-Infinity')
|
|
2075
|
+
return new Double(-Infinity);
|
|
2076
|
+
if (!Number.isFinite(coercedValue)) {
|
|
2077
|
+
throw new BSONError(`Input: ${value} is not representable as a Double`);
|
|
2078
|
+
}
|
|
2079
|
+
if (value.trim() !== value) {
|
|
2080
|
+
throw new BSONError(`Input: '${value}' contains whitespace`);
|
|
2081
|
+
}
|
|
2082
|
+
if (value === '') {
|
|
2083
|
+
throw new BSONError(`Input is an empty string`);
|
|
2084
|
+
}
|
|
2085
|
+
if (/[^-0-9.+eE]/.test(value)) {
|
|
2086
|
+
throw new BSONError(`Input: '${value}' is not in decimal or exponential notation`);
|
|
2087
|
+
}
|
|
2088
|
+
return new Double(coercedValue);
|
|
2089
|
+
}
|
|
2042
2090
|
valueOf() {
|
|
2043
2091
|
return this.value;
|
|
2044
2092
|
}
|
|
@@ -2080,6 +2128,23 @@ class Int32 extends BSONValue {
|
|
|
2080
2128
|
}
|
|
2081
2129
|
this.value = +value | 0;
|
|
2082
2130
|
}
|
|
2131
|
+
static fromString(value) {
|
|
2132
|
+
const cleanedValue = removeLeadingZerosAndExplicitPlus(value);
|
|
2133
|
+
const coercedValue = Number(value);
|
|
2134
|
+
if (BSON_INT32_MAX < coercedValue) {
|
|
2135
|
+
throw new BSONError(`Input: '${value}' is larger than the maximum value for Int32`);
|
|
2136
|
+
}
|
|
2137
|
+
else if (BSON_INT32_MIN > coercedValue) {
|
|
2138
|
+
throw new BSONError(`Input: '${value}' is smaller than the minimum value for Int32`);
|
|
2139
|
+
}
|
|
2140
|
+
else if (!Number.isSafeInteger(coercedValue)) {
|
|
2141
|
+
throw new BSONError(`Input: '${value}' is not a safe integer`);
|
|
2142
|
+
}
|
|
2143
|
+
else if (coercedValue.toString() !== cleanedValue) {
|
|
2144
|
+
throw new BSONError(`Input: '${value}' is not a valid Int32 string`);
|
|
2145
|
+
}
|
|
2146
|
+
return new Int32(coercedValue);
|
|
2147
|
+
}
|
|
2083
2148
|
valueOf() {
|
|
2084
2149
|
return this.value;
|
|
2085
2150
|
}
|
|
@@ -3167,12 +3232,7 @@ function deserializeObject(buffer, index, options, isArray = false) {
|
|
|
3167
3232
|
stringSize > buffer.length - index ||
|
|
3168
3233
|
buffer[index + stringSize - 1] !== 0)
|
|
3169
3234
|
throw new BSONError('bad string length in bson');
|
|
3170
|
-
|
|
3171
|
-
if (!validateUtf8(buffer, index, index + stringSize - 1)) {
|
|
3172
|
-
throw new BSONError('Invalid UTF-8 string in BSON document');
|
|
3173
|
-
}
|
|
3174
|
-
}
|
|
3175
|
-
const namespace = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, false);
|
|
3235
|
+
const namespace = ByteUtils.toUTF8(buffer, index, index + stringSize - 1, shouldValidateKey);
|
|
3176
3236
|
index = index + stringSize;
|
|
3177
3237
|
const oidBuffer = ByteUtils.allocateUnsafe(12);
|
|
3178
3238
|
for (let i = 0; i < 12; i++)
|