bson 6.5.1 → 6.6.1
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 +82 -7
- package/lib/bson.bundle.js +37 -17
- package/lib/bson.bundle.js.map +1 -1
- package/lib/bson.cjs +37 -17
- package/lib/bson.cjs.map +1 -1
- package/lib/bson.mjs +37 -18
- package/lib/bson.mjs.map +1 -1
- package/lib/bson.rn.cjs +37 -17
- package/lib/bson.rn.cjs.map +1 -1
- package/package.json +1 -1
- package/src/binary.ts +5 -5
- package/src/bson.ts +2 -2
- package/src/error.ts +2 -2
- package/src/parser/on_demand/index.ts +10 -6
- package/src/parser/on_demand/parse_to_elements.ts +42 -28
- package/src/utils/byte_utils.ts +10 -4
- package/src/utils/number_utils.ts +37 -2
package/package.json
CHANGED
package/src/binary.ts
CHANGED
|
@@ -186,15 +186,15 @@ export class Binary extends BSONValue {
|
|
|
186
186
|
}
|
|
187
187
|
|
|
188
188
|
toJSON(): string {
|
|
189
|
-
return ByteUtils.toBase64(this.buffer);
|
|
189
|
+
return ByteUtils.toBase64(this.buffer.subarray(0, this.position));
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
toString(encoding?: 'hex' | 'base64' | 'utf8' | 'utf-8'): string {
|
|
193
|
-
if (encoding === 'hex') return ByteUtils.toHex(this.buffer);
|
|
194
|
-
if (encoding === 'base64') return ByteUtils.toBase64(this.buffer);
|
|
193
|
+
if (encoding === 'hex') return ByteUtils.toHex(this.buffer.subarray(0, this.position));
|
|
194
|
+
if (encoding === 'base64') return ByteUtils.toBase64(this.buffer.subarray(0, this.position));
|
|
195
195
|
if (encoding === 'utf8' || encoding === 'utf-8')
|
|
196
|
-
return ByteUtils.toUTF8(this.buffer, 0, this.
|
|
197
|
-
return ByteUtils.toUTF8(this.buffer, 0, this.
|
|
196
|
+
return ByteUtils.toUTF8(this.buffer, 0, this.position, false);
|
|
197
|
+
return ByteUtils.toUTF8(this.buffer, 0, this.position, false);
|
|
198
198
|
}
|
|
199
199
|
|
|
200
200
|
/** @internal */
|
package/src/bson.ts
CHANGED
|
@@ -51,10 +51,10 @@ export {
|
|
|
51
51
|
Decimal128
|
|
52
52
|
};
|
|
53
53
|
export { BSONValue } from './bson_value';
|
|
54
|
-
export { BSONError, BSONVersionError, BSONRuntimeError } from './error';
|
|
54
|
+
export { BSONError, BSONVersionError, BSONRuntimeError, BSONOffsetError } from './error';
|
|
55
55
|
export { BSONType } from './constants';
|
|
56
56
|
export { EJSON } from './extended_json';
|
|
57
|
-
export { onDemand } from './parser/on_demand/index';
|
|
57
|
+
export { onDemand, type OnDemand } from './parser/on_demand/index';
|
|
58
58
|
|
|
59
59
|
/** @public */
|
|
60
60
|
export interface Document {
|
package/src/error.ts
CHANGED
|
@@ -98,8 +98,8 @@ export class BSONOffsetError extends BSONError {
|
|
|
98
98
|
|
|
99
99
|
public offset: number;
|
|
100
100
|
|
|
101
|
-
constructor(message: string, offset: number) {
|
|
102
|
-
super(`${message}. offset: ${offset}
|
|
101
|
+
constructor(message: string, offset: number, options?: { cause?: unknown }) {
|
|
102
|
+
super(`${message}. offset: ${offset}`, options);
|
|
103
103
|
this.offset = offset;
|
|
104
104
|
}
|
|
105
105
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ByteUtils } from '../../utils/byte_utils';
|
|
2
|
+
import { NumberUtils } from '../../utils/number_utils';
|
|
2
3
|
import { type BSONElement, parseToElements } from './parse_to_elements';
|
|
3
4
|
/**
|
|
4
5
|
* @experimental
|
|
@@ -7,11 +8,13 @@ import { type BSONElement, parseToElements } from './parse_to_elements';
|
|
|
7
8
|
* A new set of BSON APIs that are currently experimental and not intended for production use.
|
|
8
9
|
*/
|
|
9
10
|
export type OnDemand = {
|
|
10
|
-
BSONOffsetError: {
|
|
11
|
-
new (message: string, offset: number): BSONOffsetError;
|
|
12
|
-
isBSONError(value: unknown): value is BSONError;
|
|
13
|
-
};
|
|
14
11
|
parseToElements: (this: void, bytes: Uint8Array, startOffset?: number) => Iterable<BSONElement>;
|
|
12
|
+
// Types
|
|
13
|
+
BSONElement: BSONElement;
|
|
14
|
+
|
|
15
|
+
// Utils
|
|
16
|
+
ByteUtils: ByteUtils;
|
|
17
|
+
NumberUtils: NumberUtils;
|
|
15
18
|
};
|
|
16
19
|
|
|
17
20
|
/**
|
|
@@ -21,7 +24,8 @@ export type OnDemand = {
|
|
|
21
24
|
const onDemand: OnDemand = Object.create(null);
|
|
22
25
|
|
|
23
26
|
onDemand.parseToElements = parseToElements;
|
|
24
|
-
onDemand.
|
|
27
|
+
onDemand.ByteUtils = ByteUtils;
|
|
28
|
+
onDemand.NumberUtils = NumberUtils;
|
|
25
29
|
|
|
26
30
|
Object.freeze(onDemand);
|
|
27
31
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */
|
|
2
1
|
import { BSONOffsetError } from '../../error';
|
|
2
|
+
import { NumberUtils } from '../../utils/number_utils';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @internal
|
|
@@ -9,7 +9,7 @@ import { BSONOffsetError } from '../../error';
|
|
|
9
9
|
* - `minKey` is set to 255 so unsigned comparisons succeed
|
|
10
10
|
* - Modify with caution, double check the bundle contains literals
|
|
11
11
|
*/
|
|
12
|
-
const enum
|
|
12
|
+
const enum BSONElementType {
|
|
13
13
|
double = 1,
|
|
14
14
|
string = 2,
|
|
15
15
|
object = 3,
|
|
@@ -45,17 +45,12 @@ export type BSONElement = [
|
|
|
45
45
|
length: number
|
|
46
46
|
];
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
function getSize(source: Uint8Array, offset: number) {
|
|
49
|
+
try {
|
|
50
|
+
return NumberUtils.getNonnegativeInt32LE(source, offset);
|
|
51
|
+
} catch (cause) {
|
|
52
|
+
throw new BSONOffsetError('BSON size cannot be negative', offset, { cause });
|
|
52
53
|
}
|
|
53
|
-
return (
|
|
54
|
-
source[offset] |
|
|
55
|
-
(source[offset + 1] << 8) |
|
|
56
|
-
(source[offset + 2] << 16) |
|
|
57
|
-
(source[offset + 3] << 24)
|
|
58
|
-
);
|
|
59
54
|
}
|
|
60
55
|
|
|
61
56
|
/**
|
|
@@ -80,7 +75,12 @@ function findNull(bytes: Uint8Array, offset: number): number {
|
|
|
80
75
|
* @public
|
|
81
76
|
* @experimental
|
|
82
77
|
*/
|
|
83
|
-
export function parseToElements(
|
|
78
|
+
export function parseToElements(
|
|
79
|
+
bytes: Uint8Array,
|
|
80
|
+
startOffset: number | null = 0
|
|
81
|
+
): Iterable<BSONElement> {
|
|
82
|
+
startOffset ??= 0;
|
|
83
|
+
|
|
84
84
|
if (bytes.length < 5) {
|
|
85
85
|
throw new BSONOffsetError(
|
|
86
86
|
`Input must be at least 5 bytes, got ${bytes.length} bytes`,
|
|
@@ -121,37 +121,51 @@ export function parseToElements(bytes: Uint8Array, startOffset = 0): Iterable<BS
|
|
|
121
121
|
|
|
122
122
|
let length: number;
|
|
123
123
|
|
|
124
|
-
if (
|
|
124
|
+
if (
|
|
125
|
+
type === BSONElementType.double ||
|
|
126
|
+
type === BSONElementType.long ||
|
|
127
|
+
type === BSONElementType.date ||
|
|
128
|
+
type === BSONElementType.timestamp
|
|
129
|
+
) {
|
|
125
130
|
length = 8;
|
|
126
|
-
} else if (type ===
|
|
131
|
+
} else if (type === BSONElementType.int) {
|
|
127
132
|
length = 4;
|
|
128
|
-
} else if (type ===
|
|
133
|
+
} else if (type === BSONElementType.objectId) {
|
|
129
134
|
length = 12;
|
|
130
|
-
} else if (type ===
|
|
135
|
+
} else if (type === BSONElementType.decimal) {
|
|
131
136
|
length = 16;
|
|
132
|
-
} else if (type ===
|
|
137
|
+
} else if (type === BSONElementType.bool) {
|
|
133
138
|
length = 1;
|
|
134
|
-
} else if (
|
|
139
|
+
} else if (
|
|
140
|
+
type === BSONElementType.null ||
|
|
141
|
+
type === BSONElementType.undefined ||
|
|
142
|
+
type === BSONElementType.maxKey ||
|
|
143
|
+
type === BSONElementType.minKey
|
|
144
|
+
) {
|
|
135
145
|
length = 0;
|
|
136
146
|
}
|
|
137
147
|
// Needs a size calculation
|
|
138
|
-
else if (type ===
|
|
148
|
+
else if (type === BSONElementType.regex) {
|
|
139
149
|
length = findNull(bytes, findNull(bytes, offset) + 1) + 1 - offset;
|
|
140
|
-
} else if (
|
|
150
|
+
} else if (
|
|
151
|
+
type === BSONElementType.object ||
|
|
152
|
+
type === BSONElementType.array ||
|
|
153
|
+
type === BSONElementType.javascriptWithScope
|
|
154
|
+
) {
|
|
141
155
|
length = getSize(bytes, offset);
|
|
142
156
|
} else if (
|
|
143
|
-
type ===
|
|
144
|
-
type ===
|
|
145
|
-
type ===
|
|
146
|
-
type ===
|
|
147
|
-
type ===
|
|
157
|
+
type === BSONElementType.string ||
|
|
158
|
+
type === BSONElementType.binData ||
|
|
159
|
+
type === BSONElementType.dbPointer ||
|
|
160
|
+
type === BSONElementType.javascript ||
|
|
161
|
+
type === BSONElementType.symbol
|
|
148
162
|
) {
|
|
149
163
|
length = getSize(bytes, offset) + 4;
|
|
150
|
-
if (type ===
|
|
164
|
+
if (type === BSONElementType.binData) {
|
|
151
165
|
// binary subtype
|
|
152
166
|
length += 1;
|
|
153
167
|
}
|
|
154
|
-
if (type ===
|
|
168
|
+
if (type === BSONElementType.dbPointer) {
|
|
155
169
|
// dbPointer's objectId
|
|
156
170
|
length += 12;
|
|
157
171
|
}
|
package/src/utils/byte_utils.ts
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { nodeJsByteUtils } from './node_byte_utils';
|
|
2
2
|
import { webByteUtils } from './web_byte_utils';
|
|
3
3
|
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* @public
|
|
6
|
+
* @experimental
|
|
7
|
+
*
|
|
8
|
+
* A collection of functions that help work with data in a Uint8Array.
|
|
9
|
+
* ByteUtils is configured at load time to use Node.js or Web based APIs for the internal implementations.
|
|
10
|
+
*/
|
|
5
11
|
export type ByteUtils = {
|
|
6
12
|
/** Transforms the input to an instance of Buffer if running on node, otherwise Uint8Array */
|
|
7
|
-
toLocalBufferType(buffer: Uint8Array | ArrayBufferView | ArrayBuffer)
|
|
13
|
+
toLocalBufferType: (buffer: Uint8Array | ArrayBufferView | ArrayBuffer) => Uint8Array;
|
|
8
14
|
/** Create empty space of size */
|
|
9
15
|
allocate: (size: number) => Uint8Array;
|
|
10
16
|
/** Create empty space of size, use pooled memory when available */
|
|
@@ -30,9 +36,9 @@ export type ByteUtils = {
|
|
|
30
36
|
/** Get the utf8 code unit count from a string if it were to be transformed to utf8 */
|
|
31
37
|
utf8ByteLength: (input: string) => number;
|
|
32
38
|
/** Encode UTF8 bytes generated from `source` string into `destination` at byteOffset. Returns the number of bytes encoded. */
|
|
33
|
-
encodeUTF8Into(destination: Uint8Array, source: string, byteOffset: number)
|
|
39
|
+
encodeUTF8Into: (destination: Uint8Array, source: string, byteOffset: number) => number;
|
|
34
40
|
/** Generate a Uint8Array filled with random bytes with byteLength */
|
|
35
|
-
randomBytes(byteLength: number)
|
|
41
|
+
randomBytes: (byteLength: number) => Uint8Array;
|
|
36
42
|
};
|
|
37
43
|
|
|
38
44
|
declare const Buffer: { new (): unknown; prototype?: { _isBuffer?: boolean } } | undefined;
|
|
@@ -6,12 +6,47 @@ FLOAT[0] = -1;
|
|
|
6
6
|
// Big endian [191, 240, 0, 0, 0, 0, 0, 0]
|
|
7
7
|
const isBigEndian = FLOAT_BYTES[7] === 0;
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* @experimental
|
|
11
|
+
* @public
|
|
12
|
+
*
|
|
13
|
+
* A collection of functions that get or set various numeric types and bit widths from a Uint8Array.
|
|
14
|
+
*/
|
|
15
|
+
export type NumberUtils = {
|
|
16
|
+
/**
|
|
17
|
+
* Parses a signed int32 at offset. Throws a `RangeError` if value is negative.
|
|
18
|
+
*/
|
|
19
|
+
getNonnegativeInt32LE: (source: Uint8Array, offset: number) => number;
|
|
20
|
+
getInt32LE: (source: Uint8Array, offset: number) => number;
|
|
21
|
+
getUint32LE: (source: Uint8Array, offset: number) => number;
|
|
22
|
+
getUint32BE: (source: Uint8Array, offset: number) => number;
|
|
23
|
+
getBigInt64LE: (source: Uint8Array, offset: number) => bigint;
|
|
24
|
+
getFloat64LE: (source: Uint8Array, offset: number) => number;
|
|
25
|
+
setInt32BE: (destination: Uint8Array, offset: number, value: number) => 4;
|
|
26
|
+
setInt32LE: (destination: Uint8Array, offset: number, value: number) => 4;
|
|
27
|
+
setBigInt64LE: (destination: Uint8Array, offset: number, value: bigint) => 8;
|
|
28
|
+
setFloat64LE: (destination: Uint8Array, offset: number, value: number) => 8;
|
|
29
|
+
};
|
|
30
|
+
|
|
9
31
|
/**
|
|
10
32
|
* Number parsing and serializing utilities.
|
|
11
33
|
*
|
|
12
|
-
* @
|
|
34
|
+
* @experimental
|
|
35
|
+
* @public
|
|
13
36
|
*/
|
|
14
|
-
export const NumberUtils = {
|
|
37
|
+
export const NumberUtils: NumberUtils = {
|
|
38
|
+
getNonnegativeInt32LE(source: Uint8Array, offset: number): number {
|
|
39
|
+
if (source[offset + 3] > 127) {
|
|
40
|
+
throw new RangeError(`Size cannot be negative at offset: ${offset}`);
|
|
41
|
+
}
|
|
42
|
+
return (
|
|
43
|
+
source[offset] |
|
|
44
|
+
(source[offset + 1] << 8) |
|
|
45
|
+
(source[offset + 2] << 16) |
|
|
46
|
+
(source[offset + 3] << 24)
|
|
47
|
+
);
|
|
48
|
+
},
|
|
49
|
+
|
|
15
50
|
/** Reads a little-endian 32-bit integer from source */
|
|
16
51
|
getInt32LE(source: Uint8Array, offset: number): number {
|
|
17
52
|
return (
|