bson 6.4.0 → 6.6.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/lib/bson.mjs CHANGED
@@ -124,6 +124,15 @@ class BSONRuntimeError extends BSONError {
124
124
  super(message);
125
125
  }
126
126
  }
127
+ class BSONOffsetError extends BSONError {
128
+ get name() {
129
+ return 'BSONOffsetError';
130
+ }
131
+ constructor(message, offset, options) {
132
+ super(`${message}. offset: ${offset}`, options);
133
+ this.offset = offset;
134
+ }
135
+ }
127
136
 
128
137
  const FIRST_BIT = 0x80;
129
138
  const FIRST_TWO_BITS = 0xc0;
@@ -522,16 +531,16 @@ class Binary extends BSONValue {
522
531
  return this.position;
523
532
  }
524
533
  toJSON() {
525
- return ByteUtils.toBase64(this.buffer);
534
+ return ByteUtils.toBase64(this.buffer.subarray(0, this.position));
526
535
  }
527
536
  toString(encoding) {
528
537
  if (encoding === 'hex')
529
- return ByteUtils.toHex(this.buffer);
538
+ return ByteUtils.toHex(this.buffer.subarray(0, this.position));
530
539
  if (encoding === 'base64')
531
- return ByteUtils.toBase64(this.buffer);
540
+ return ByteUtils.toBase64(this.buffer.subarray(0, this.position));
532
541
  if (encoding === 'utf8' || encoding === 'utf-8')
533
- return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength, false);
534
- return ByteUtils.toUTF8(this.buffer, 0, this.buffer.byteLength, false);
542
+ return ByteUtils.toUTF8(this.buffer, 0, this.position, false);
543
+ return ByteUtils.toUTF8(this.buffer, 0, this.position, false);
535
544
  }
536
545
  toExtendedJSON(options) {
537
546
  options = options || {};
@@ -605,6 +614,7 @@ Binary.SUBTYPE_UUID = 4;
605
614
  Binary.SUBTYPE_MD5 = 5;
606
615
  Binary.SUBTYPE_ENCRYPTED = 6;
607
616
  Binary.SUBTYPE_COLUMN = 7;
617
+ Binary.SUBTYPE_SENSITIVE = 8;
608
618
  Binary.SUBTYPE_USER_DEFINED = 128;
609
619
  const UUID_BYTE_LENGTH = 16;
610
620
  const UUID_WITHOUT_DASHES = /^[0-9A-F]{32}$/i;
@@ -2123,7 +2133,18 @@ class MinKey extends BSONValue {
2123
2133
 
2124
2134
  const FLOAT = new Float64Array(1);
2125
2135
  const FLOAT_BYTES = new Uint8Array(FLOAT.buffer, 0, 8);
2136
+ FLOAT[0] = -1;
2137
+ const isBigEndian = FLOAT_BYTES[7] === 0;
2126
2138
  const NumberUtils = {
2139
+ getNonnegativeInt32LE(source, offset) {
2140
+ if (source[offset + 3] > 127) {
2141
+ throw new RangeError(`Size cannot be negative at offset: ${offset}`);
2142
+ }
2143
+ return (source[offset] |
2144
+ (source[offset + 1] << 8) |
2145
+ (source[offset + 2] << 16) |
2146
+ (source[offset + 3] << 24));
2147
+ },
2127
2148
  getInt32LE(source, offset) {
2128
2149
  return (source[offset] |
2129
2150
  (source[offset + 1] << 8) |
@@ -2147,17 +2168,29 @@ const NumberUtils = {
2147
2168
  const hi = NumberUtils.getUint32LE(source, offset + 4);
2148
2169
  return (BigInt(hi) << BigInt(32)) + BigInt(lo);
2149
2170
  },
2150
- getFloat64LE(source, offset) {
2151
- FLOAT_BYTES[0] = source[offset];
2152
- FLOAT_BYTES[1] = source[offset + 1];
2153
- FLOAT_BYTES[2] = source[offset + 2];
2154
- FLOAT_BYTES[3] = source[offset + 3];
2155
- FLOAT_BYTES[4] = source[offset + 4];
2156
- FLOAT_BYTES[5] = source[offset + 5];
2157
- FLOAT_BYTES[6] = source[offset + 6];
2158
- FLOAT_BYTES[7] = source[offset + 7];
2159
- return FLOAT[0];
2160
- },
2171
+ getFloat64LE: isBigEndian
2172
+ ? (source, offset) => {
2173
+ FLOAT_BYTES[7] = source[offset];
2174
+ FLOAT_BYTES[6] = source[offset + 1];
2175
+ FLOAT_BYTES[5] = source[offset + 2];
2176
+ FLOAT_BYTES[4] = source[offset + 3];
2177
+ FLOAT_BYTES[3] = source[offset + 4];
2178
+ FLOAT_BYTES[2] = source[offset + 5];
2179
+ FLOAT_BYTES[1] = source[offset + 6];
2180
+ FLOAT_BYTES[0] = source[offset + 7];
2181
+ return FLOAT[0];
2182
+ }
2183
+ : (source, offset) => {
2184
+ FLOAT_BYTES[0] = source[offset];
2185
+ FLOAT_BYTES[1] = source[offset + 1];
2186
+ FLOAT_BYTES[2] = source[offset + 2];
2187
+ FLOAT_BYTES[3] = source[offset + 3];
2188
+ FLOAT_BYTES[4] = source[offset + 4];
2189
+ FLOAT_BYTES[5] = source[offset + 5];
2190
+ FLOAT_BYTES[6] = source[offset + 6];
2191
+ FLOAT_BYTES[7] = source[offset + 7];
2192
+ return FLOAT[0];
2193
+ },
2161
2194
  setInt32BE(destination, offset, value) {
2162
2195
  destination[offset + 3] = value;
2163
2196
  value >>>= 8;
@@ -2198,18 +2231,31 @@ const NumberUtils = {
2198
2231
  destination[offset + 7] = hi;
2199
2232
  return 8;
2200
2233
  },
2201
- setFloat64LE(destination, offset, value) {
2202
- FLOAT[0] = value;
2203
- destination[offset] = FLOAT_BYTES[0];
2204
- destination[offset + 1] = FLOAT_BYTES[1];
2205
- destination[offset + 2] = FLOAT_BYTES[2];
2206
- destination[offset + 3] = FLOAT_BYTES[3];
2207
- destination[offset + 4] = FLOAT_BYTES[4];
2208
- destination[offset + 5] = FLOAT_BYTES[5];
2209
- destination[offset + 6] = FLOAT_BYTES[6];
2210
- destination[offset + 7] = FLOAT_BYTES[7];
2211
- return 8;
2212
- }
2234
+ setFloat64LE: isBigEndian
2235
+ ? (destination, offset, value) => {
2236
+ FLOAT[0] = value;
2237
+ destination[offset] = FLOAT_BYTES[7];
2238
+ destination[offset + 1] = FLOAT_BYTES[6];
2239
+ destination[offset + 2] = FLOAT_BYTES[5];
2240
+ destination[offset + 3] = FLOAT_BYTES[4];
2241
+ destination[offset + 4] = FLOAT_BYTES[3];
2242
+ destination[offset + 5] = FLOAT_BYTES[2];
2243
+ destination[offset + 6] = FLOAT_BYTES[1];
2244
+ destination[offset + 7] = FLOAT_BYTES[0];
2245
+ return 8;
2246
+ }
2247
+ : (destination, offset, value) => {
2248
+ FLOAT[0] = value;
2249
+ destination[offset] = FLOAT_BYTES[0];
2250
+ destination[offset + 1] = FLOAT_BYTES[1];
2251
+ destination[offset + 2] = FLOAT_BYTES[2];
2252
+ destination[offset + 3] = FLOAT_BYTES[3];
2253
+ destination[offset + 4] = FLOAT_BYTES[4];
2254
+ destination[offset + 5] = FLOAT_BYTES[5];
2255
+ destination[offset + 6] = FLOAT_BYTES[6];
2256
+ destination[offset + 7] = FLOAT_BYTES[7];
2257
+ return 8;
2258
+ }
2213
2259
  };
2214
2260
 
2215
2261
  const checkForHexRegExp = new RegExp('^[0-9a-fA-F]{24}$');
@@ -4087,6 +4133,113 @@ EJSON.serialize = EJSONserialize;
4087
4133
  EJSON.deserialize = EJSONdeserialize;
4088
4134
  Object.freeze(EJSON);
4089
4135
 
4136
+ function getSize(source, offset) {
4137
+ try {
4138
+ return NumberUtils.getNonnegativeInt32LE(source, offset);
4139
+ }
4140
+ catch (cause) {
4141
+ throw new BSONOffsetError('BSON size cannot be negative', offset, { cause });
4142
+ }
4143
+ }
4144
+ function findNull(bytes, offset) {
4145
+ let nullTerminatorOffset = offset;
4146
+ for (; bytes[nullTerminatorOffset] !== 0x00; nullTerminatorOffset++)
4147
+ ;
4148
+ if (nullTerminatorOffset === bytes.length - 1) {
4149
+ throw new BSONOffsetError('Null terminator not found', offset);
4150
+ }
4151
+ return nullTerminatorOffset;
4152
+ }
4153
+ function parseToElements(bytes, startOffset = 0) {
4154
+ startOffset ??= 0;
4155
+ if (bytes.length < 5) {
4156
+ throw new BSONOffsetError(`Input must be at least 5 bytes, got ${bytes.length} bytes`, startOffset);
4157
+ }
4158
+ const documentSize = getSize(bytes, startOffset);
4159
+ if (documentSize > bytes.length - startOffset) {
4160
+ throw new BSONOffsetError(`Parsed documentSize (${documentSize} bytes) does not match input length (${bytes.length} bytes)`, startOffset);
4161
+ }
4162
+ if (bytes[startOffset + documentSize - 1] !== 0x00) {
4163
+ throw new BSONOffsetError('BSON documents must end in 0x00', startOffset + documentSize);
4164
+ }
4165
+ const elements = [];
4166
+ let offset = startOffset + 4;
4167
+ while (offset <= documentSize + startOffset) {
4168
+ const type = bytes[offset];
4169
+ offset += 1;
4170
+ if (type === 0) {
4171
+ if (offset - startOffset !== documentSize) {
4172
+ throw new BSONOffsetError(`Invalid 0x00 type byte`, offset);
4173
+ }
4174
+ break;
4175
+ }
4176
+ const nameOffset = offset;
4177
+ const nameLength = findNull(bytes, offset) - nameOffset;
4178
+ offset += nameLength + 1;
4179
+ let length;
4180
+ if (type === 1 ||
4181
+ type === 18 ||
4182
+ type === 9 ||
4183
+ type === 17) {
4184
+ length = 8;
4185
+ }
4186
+ else if (type === 16) {
4187
+ length = 4;
4188
+ }
4189
+ else if (type === 7) {
4190
+ length = 12;
4191
+ }
4192
+ else if (type === 19) {
4193
+ length = 16;
4194
+ }
4195
+ else if (type === 8) {
4196
+ length = 1;
4197
+ }
4198
+ else if (type === 10 ||
4199
+ type === 6 ||
4200
+ type === 127 ||
4201
+ type === 255) {
4202
+ length = 0;
4203
+ }
4204
+ else if (type === 11) {
4205
+ length = findNull(bytes, findNull(bytes, offset) + 1) + 1 - offset;
4206
+ }
4207
+ else if (type === 3 ||
4208
+ type === 4 ||
4209
+ type === 15) {
4210
+ length = getSize(bytes, offset);
4211
+ }
4212
+ else if (type === 2 ||
4213
+ type === 5 ||
4214
+ type === 12 ||
4215
+ type === 13 ||
4216
+ type === 14) {
4217
+ length = getSize(bytes, offset) + 4;
4218
+ if (type === 5) {
4219
+ length += 1;
4220
+ }
4221
+ if (type === 12) {
4222
+ length += 12;
4223
+ }
4224
+ }
4225
+ else {
4226
+ throw new BSONOffsetError(`Invalid 0x${type.toString(16).padStart(2, '0')} type byte`, offset);
4227
+ }
4228
+ if (length > documentSize) {
4229
+ throw new BSONOffsetError('value reports length larger than document', offset);
4230
+ }
4231
+ elements.push([type, nameOffset, nameLength, offset, length]);
4232
+ offset += length;
4233
+ }
4234
+ return elements;
4235
+ }
4236
+
4237
+ const onDemand = Object.create(null);
4238
+ onDemand.parseToElements = parseToElements;
4239
+ onDemand.ByteUtils = ByteUtils;
4240
+ onDemand.NumberUtils = NumberUtils;
4241
+ Object.freeze(onDemand);
4242
+
4090
4243
  const MAXSIZE = 1024 * 1024 * 17;
4091
4244
  let buffer = ByteUtils.allocate(MAXSIZE);
4092
4245
  function setInternalBufferSize(size) {
@@ -4141,6 +4294,7 @@ function deserializeStream(data, startIndex, numberOfDocuments, documents, docSt
4141
4294
  var bson = /*#__PURE__*/Object.freeze({
4142
4295
  __proto__: null,
4143
4296
  BSONError: BSONError,
4297
+ BSONOffsetError: BSONOffsetError,
4144
4298
  BSONRegExp: BSONRegExp,
4145
4299
  BSONRuntimeError: BSONRuntimeError,
4146
4300
  BSONSymbol: BSONSymbol,
@@ -4163,10 +4317,11 @@ var bson = /*#__PURE__*/Object.freeze({
4163
4317
  calculateObjectSize: calculateObjectSize,
4164
4318
  deserialize: deserialize,
4165
4319
  deserializeStream: deserializeStream,
4320
+ onDemand: onDemand,
4166
4321
  serialize: serialize,
4167
4322
  serializeWithBufferAndIndex: serializeWithBufferAndIndex,
4168
4323
  setInternalBufferSize: setInternalBufferSize
4169
4324
  });
4170
4325
 
4171
- export { bson as BSON, BSONError, BSONRegExp, BSONRuntimeError, BSONSymbol, BSONType, BSONValue, BSONVersionError, Binary, Code, DBRef, Decimal128, Double, EJSON, Int32, Long, MaxKey, MinKey, ObjectId, Timestamp, UUID, calculateObjectSize, deserialize, deserializeStream, serialize, serializeWithBufferAndIndex, setInternalBufferSize };
4326
+ export { bson as BSON, BSONError, BSONOffsetError, BSONRegExp, BSONRuntimeError, BSONSymbol, BSONType, BSONValue, BSONVersionError, Binary, Code, DBRef, Decimal128, Double, EJSON, Int32, Long, MaxKey, MinKey, ObjectId, Timestamp, UUID, calculateObjectSize, deserialize, deserializeStream, onDemand, serialize, serializeWithBufferAndIndex, setInternalBufferSize };
4172
4327
  //# sourceMappingURL=bson.mjs.map