bson 5.4.0 → 6.0.0-alpha

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 CHANGED
@@ -4,6 +4,7 @@ BSON is short for "Binary JSON," and is the binary-encoded serialization of JSON
4
4
  You can learn more about it in [the specification](http://bsonspec.org).
5
5
 
6
6
  ### Table of Contents
7
+
7
8
  - [Usage](#usage)
8
9
  - [Bugs/Feature Requests](#bugs--feature-requests)
9
10
  - [Installation](#installation)
@@ -18,7 +19,7 @@ Think you've found a bug? Want to see a new feature in `bson`? Please open a cas
18
19
  2. Navigate to the NODE project: [jira.mongodb.org/browse/NODE](https://jira.mongodb.org/browse/NODE)
19
20
  3. Click **Create Issue** - Please provide as much information as possible about the issue and how to reproduce it.
20
21
 
21
- Bug reports in JIRA for all driver projects (i.e. NODE, PYTHON, CSHARP, JAVA) and the Core Server (i.e. SERVER) project are **public**.
22
+ Bug reports in JIRA for the NODE driver project are **public**.
22
23
 
23
24
  ## Usage
24
25
 
@@ -67,9 +68,20 @@ If you are working directly in the browser without a bundler please use the `.mj
67
68
  npm install bson
68
69
  ```
69
70
 
71
+ ### MongoDB Node.js Driver Version Compatibility
72
+
73
+ Only the following version combinations with the [MongoDB Node.js Driver](https://github.com/mongodb/node-mongodb-native) are considered stable.
74
+
75
+ | | `bson@1.x` | `bson@4.x` | `bson@5.x` | `bson@6.x` |
76
+ | ------------- | ---------- | ---------- | ---------- | ---------- |
77
+ | `mongodb@6.x` | N/A | N/A | N/A | ✓ |
78
+ | `mongodb@5.x` | N/A | N/A | ✓ | N/A |
79
+ | `mongodb@4.x` | N/A | ✓ | N/A | N/A |
80
+ | `mongodb@3.x` | ✓ | N/A | N/A | N/A |
81
+
70
82
  ## Documentation
71
83
 
72
- ### BSON
84
+ ### BSON
73
85
 
74
86
  [API documentation](https://mongodb.github.io/node-mongodb-native/Next/modules/BSON.html)
75
87
 
@@ -77,31 +89,31 @@ npm install bson
77
89
 
78
90
  ### EJSON
79
91
 
80
- * [EJSON](#EJSON)
81
-
82
- * [.parse(text, [options])](#EJSON.parse)
92
+ - [EJSON](#EJSON)
83
93
 
84
- * [.stringify(value, [replacer], [space], [options])](#EJSON.stringify)
94
+ - [.parse(text, [options])](#EJSON.parse)
85
95
 
86
- * [.serialize(bson, [options])](#EJSON.serialize)
96
+ - [.stringify(value, [replacer], [space], [options])](#EJSON.stringify)
87
97
 
88
- * [.deserialize(ejson, [options])](#EJSON.deserialize)
98
+ - [.serialize(bson, [options])](#EJSON.serialize)
89
99
 
100
+ - [.deserialize(ejson, [options])](#EJSON.deserialize)
90
101
 
91
102
  <a name="EJSON.parse"></a>
92
103
 
93
- #### *EJSON*.parse(text, [options])
104
+ #### _EJSON_.parse(text, [options])
94
105
 
95
- | Param | Type | Default | Description |
96
- | --- | --- | --- | --- |
97
- | text | <code>string</code> | | |
98
- | [options] | <code>object</code> | | Optional settings |
106
+ | Param | Type | Default | Description |
107
+ | ----------------- | -------------------- | ----------------- | ---------------------------------------------------------------------------------- |
108
+ | text | <code>string</code> | | |
109
+ | [options] | <code>object</code> | | Optional settings |
99
110
  | [options.relaxed] | <code>boolean</code> | <code>true</code> | Attempt to return native JS types where possible, rather than BSON types (if true) |
100
111
 
101
112
  Parse an Extended JSON string, constructing the JavaScript value or object described by that
102
113
  string.
103
114
 
104
115
  **Example**
116
+
105
117
  ```js
106
118
  const { EJSON } = require('bson');
107
119
  const text = '{ "int32": { "$numberInt": "10" } }';
@@ -112,24 +124,26 @@ console.log(EJSON.parse(text, { relaxed: false }));
112
124
  // prints { int32: 10 }
113
125
  console.log(EJSON.parse(text));
114
126
  ```
127
+
115
128
  <a name="EJSON.stringify"></a>
116
129
 
117
- #### *EJSON*.stringify(value, [replacer], [space], [options])
130
+ #### _EJSON_.stringify(value, [replacer], [space], [options])
118
131
 
119
- | Param | Type | Default | Description |
120
- | --- | --- | --- | --- |
121
- | value | <code>object</code> | | The value to convert to extended JSON |
122
- | [replacer] | <code>function</code> \| <code>array</code> | | A function that alters the behavior of the stringification process, or an array of String and Number objects that serve as a whitelist for selecting/filtering the properties of the value object to be included in the JSON string. If this value is null or not provided, all properties of the object are included in the resulting JSON string |
123
- | [space] | <code>string</code> \| <code>number</code> | | A String or Number object that's used to insert white space into the output JSON string for readability purposes. |
124
- | [options] | <code>object</code> | | Optional settings |
125
- | [options.relaxed] | <code>boolean</code> | <code>true</code> | Enabled Extended JSON's `relaxed` mode |
126
- | [options.legacy] | <code>boolean</code> | <code>true</code> | Output in Extended JSON v1 |
132
+ | Param | Type | Default | Description |
133
+ | ----------------- | ------------------------------------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
134
+ | value | <code>object</code> | | The value to convert to extended JSON |
135
+ | [replacer] | <code>function</code> \| <code>array</code> | | A function that alters the behavior of the stringification process, or an array of String and Number objects that serve as a whitelist for selecting/filtering the properties of the value object to be included in the JSON string. If this value is null or not provided, all properties of the object are included in the resulting JSON string |
136
+ | [space] | <code>string</code> \| <code>number</code> | | A String or Number object that's used to insert white space into the output JSON string for readability purposes. |
137
+ | [options] | <code>object</code> | | Optional settings |
138
+ | [options.relaxed] | <code>boolean</code> | <code>true</code> | Enabled Extended JSON's `relaxed` mode |
139
+ | [options.legacy] | <code>boolean</code> | <code>true</code> | Output in Extended JSON v1 |
127
140
 
128
141
  Converts a BSON document to an Extended JSON string, optionally replacing values if a replacer
129
142
  function is specified or optionally including only the specified properties if a replacer array
130
143
  is specified.
131
144
 
132
145
  **Example**
146
+
133
147
  ```js
134
148
  const { EJSON } = require('bson');
135
149
  const Int32 = require('mongodb').Int32;
@@ -141,24 +155,25 @@ console.log(EJSON.stringify(doc, { relaxed: false }));
141
155
  // prints '{"int32":10}'
142
156
  console.log(EJSON.stringify(doc));
143
157
  ```
158
+
144
159
  <a name="EJSON.serialize"></a>
145
160
 
146
- #### *EJSON*.serialize(bson, [options])
161
+ #### _EJSON_.serialize(bson, [options])
147
162
 
148
- | Param | Type | Description |
149
- | --- | --- | --- |
150
- | bson | <code>object</code> | The object to serialize |
163
+ | Param | Type | Description |
164
+ | --------- | ------------------- | ---------------------------------------------------- |
165
+ | bson | <code>object</code> | The object to serialize |
151
166
  | [options] | <code>object</code> | Optional settings passed to the `stringify` function |
152
167
 
153
168
  Serializes an object to an Extended JSON string, and reparse it as a JavaScript object.
154
169
 
155
170
  <a name="EJSON.deserialize"></a>
156
171
 
157
- #### *EJSON*.deserialize(ejson, [options])
172
+ #### _EJSON_.deserialize(ejson, [options])
158
173
 
159
- | Param | Type | Description |
160
- | --- | --- | --- |
161
- | ejson | <code>object</code> | The Extended JSON object to deserialize |
174
+ | Param | Type | Description |
175
+ | --------- | ------------------- | -------------------------------------------- |
176
+ | ejson | <code>object</code> | The Extended JSON object to deserialize |
162
177
  | [options] | <code>object</code> | Optional settings passed to the parse method |
163
178
 
164
179
  Deserializes an Extended JSON object into a plain JavaScript object with native/BSON types
@@ -194,7 +209,7 @@ BSON vendors the required polyfills for `TextEncoder`, `TextDecoder`, `atob`, `b
194
209
  npm install --save react-native-get-random-values
195
210
  ```
196
211
 
197
- The following snippet should be placed at the top of the entrypoint (by default this is the root `index.js` file) for React Native projects using the BSON library. These lines must be placed for any code that imports `BSON`.
212
+ The following snippet should be placed at the top of the entrypoint (by default this is the root `index.js` file) for React Native projects using the BSON library. These lines must be placed for any code that imports `BSON`.
198
213
 
199
214
  ```typescript
200
215
  // Required Polyfills For ReactNative
@@ -211,7 +226,7 @@ This will cause React Native to import the `node_modules/bson/lib/bson.rn.cjs` b
211
226
 
212
227
  ### Technical Note about React Native module import
213
228
 
214
- The `"exports"` definition in our `package.json` will result in BSON's CommonJS bundle being imported in a React Native project instead of the ES module bundle. Importing the CommonJS bundle is necessary because BSON's ES module bundle of BSON uses top-level await, which is not supported syntax in [React Native's runtime hermes](https://hermesengine.dev/).
229
+ The `"exports"` definition in our `package.json` will result in BSON's CommonJS bundle being imported in a React Native project instead of the ES module bundle. Importing the CommonJS bundle is necessary because BSON's ES module bundle of BSON uses top-level await, which is not supported syntax in [React Native's runtime hermes](https://hermesengine.dev/).
215
230
 
216
231
  ## FAQ
217
232
 
package/bson.d.ts CHANGED
@@ -31,16 +31,10 @@ export declare class Binary extends BSONValue {
31
31
  position: number;
32
32
  /**
33
33
  * Create a new Binary instance.
34
- *
35
- * This constructor can accept a string as its first argument. In this case,
36
- * this string will be encoded using ISO-8859-1, **not** using UTF-8.
37
- * This is almost certainly not what you want. Use `new Binary(Buffer.from(string))`
38
- * instead to convert the string to a Buffer using UTF-8 first.
39
- *
40
34
  * @param buffer - a buffer object containing the binary data.
41
35
  * @param subType - the option binary type.
42
36
  */
43
- constructor(buffer?: string | BinarySequence, subType?: number);
37
+ constructor(buffer?: BinarySequence, subType?: number);
44
38
  /**
45
39
  * Updates this binary with byte_value.
46
40
  *
@@ -48,12 +42,12 @@ export declare class Binary extends BSONValue {
48
42
  */
49
43
  put(byteValue: string | number | Uint8Array | number[]): void;
50
44
  /**
51
- * Writes a buffer or string to the binary.
45
+ * Writes a buffer to the binary.
52
46
  *
53
47
  * @param sequence - a string or buffer to be written to the Binary BSON object.
54
48
  * @param offset - specify the binary of where to write the content.
55
49
  */
56
- write(sequence: string | BinarySequence, offset: number): void;
50
+ write(sequence: BinarySequence, offset: number): void;
57
51
  /**
58
52
  * Reads **length** bytes starting at **position**.
59
53
  *
@@ -61,13 +55,8 @@ export declare class Binary extends BSONValue {
61
55
  * @param length - the number of bytes to read.
62
56
  */
63
57
  read(position: number, length: number): BinarySequence;
64
- /**
65
- * Returns the value of this binary as a string.
66
- * @param asRaw - Will skip converting to a string
67
- * @remarks
68
- * This is handy when calling this function conditionally for some key value pairs and not others
69
- */
70
- value(asRaw?: boolean): string | BinarySequence;
58
+ /** returns a view of the binary value as a Uint8Array */
59
+ value(): Uint8Array;
71
60
  /** the length of the binary sequence */
72
61
  length(): number;
73
62
  toJSON(): string;
@@ -990,7 +979,7 @@ export declare class ObjectId extends BSONValue {
990
979
  */
991
980
  get id(): Uint8Array;
992
981
  set id(value: Uint8Array);
993
- /** Returns the ObjectId id as a 24 character hex string representation */
982
+ /** Returns the ObjectId id as a 24 lowercase character hex string representation */
994
983
  toHexString(): string;
995
984
  /* Excluded from this release type: getInc */
996
985
  /**
@@ -1006,12 +995,13 @@ export declare class ObjectId extends BSONValue {
1006
995
  toString(encoding?: 'hex' | 'base64'): string;
1007
996
  /** Converts to its JSON the 24 character hex string representation. */
1008
997
  toJSON(): string;
998
+ /* Excluded from this release type: is */
1009
999
  /**
1010
1000
  * Compares the equality of this ObjectId with `otherID`.
1011
1001
  *
1012
1002
  * @param otherId - ObjectId instance to compare against.
1013
1003
  */
1014
- equals(otherId: string | ObjectId | ObjectIdLike): boolean;
1004
+ equals(otherId: string | ObjectId | ObjectIdLike | undefined | null): boolean;
1015
1005
  /** Returns the generation date (accurate up to the second) that this ID was generated. */
1016
1006
  getTimestamp(): Date;
1017
1007
  /* Excluded from this release type: createPk */
@@ -1030,9 +1020,8 @@ export declare class ObjectId extends BSONValue {
1030
1020
  /** Creates an ObjectId instance from a base64 string */
1031
1021
  static createFromBase64(base64: string): ObjectId;
1032
1022
  /**
1033
- * Checks if a value is a valid bson ObjectId
1034
- *
1035
- * @param id - ObjectId instance to validate.
1023
+ * Checks if a value can be used to create a valid bson ObjectId
1024
+ * @param id - any JS value
1036
1025
  */
1037
1026
  static isValid(id: string | number | ObjectId | ObjectIdLike | Uint8Array): boolean;
1038
1027
  /* Excluded from this release type: toExtendedJSON */
@@ -1213,8 +1202,6 @@ export declare type TimestampOverrides = '_bsontype' | 'toExtendedJSON' | 'fromE
1213
1202
  * @public
1214
1203
  */
1215
1204
  export declare class UUID extends Binary {
1216
- /** @deprecated Hex string is no longer cached, this control will be removed in a future major release */
1217
- static cacheHexString: boolean;
1218
1205
  /**
1219
1206
  * Create a UUID type
1220
1207
  *
@@ -17,7 +17,7 @@ function isDate(d) {
17
17
  return Object.prototype.toString.call(d) === '[object Date]';
18
18
  }
19
19
 
20
- const BSON_MAJOR_VERSION = 5;
20
+ const BSON_MAJOR_VERSION = 6;
21
21
  const BSON_INT32_MAX = 0x7fffffff;
22
22
  const BSON_INT32_MIN = -0x80000000;
23
23
  const BSON_INT64_MAX = Math.pow(2, 63) - 1;
@@ -312,11 +312,11 @@ class Binary extends BSONValue {
312
312
  constructor(buffer, subType) {
313
313
  super();
314
314
  if (!(buffer == null) &&
315
- !(typeof buffer === 'string') &&
315
+ typeof buffer === 'string' &&
316
316
  !ArrayBuffer.isView(buffer) &&
317
- !(buffer instanceof ArrayBuffer) &&
317
+ !isAnyArrayBuffer(buffer) &&
318
318
  !Array.isArray(buffer)) {
319
- throw new BSONError('Binary can only be constructed from string, Buffer, TypedArray, or Array<number>');
319
+ throw new BSONError('Binary can only be constructed from Uint8Array or number[]');
320
320
  }
321
321
  this.sub_type = subType ?? Binary.BSON_BINARY_SUBTYPE_DEFAULT;
322
322
  if (buffer == null) {
@@ -324,15 +324,9 @@ class Binary extends BSONValue {
324
324
  this.position = 0;
325
325
  }
326
326
  else {
327
- if (typeof buffer === 'string') {
328
- this.buffer = ByteUtils.fromISO88591(buffer);
329
- }
330
- else if (Array.isArray(buffer)) {
331
- this.buffer = ByteUtils.fromNumberArray(buffer);
332
- }
333
- else {
334
- this.buffer = ByteUtils.toLocalBufferType(buffer);
335
- }
327
+ this.buffer = Array.isArray(buffer)
328
+ ? ByteUtils.fromNumberArray(buffer)
329
+ : ByteUtils.toLocalBufferType(buffer);
336
330
  this.position = this.buffer.byteLength;
337
331
  }
338
332
  }
@@ -378,25 +372,17 @@ class Binary extends BSONValue {
378
372
  offset + sequence.byteLength > this.position ? offset + sequence.length : this.position;
379
373
  }
380
374
  else if (typeof sequence === 'string') {
381
- const bytes = ByteUtils.fromISO88591(sequence);
382
- this.buffer.set(bytes, offset);
383
- this.position =
384
- offset + sequence.length > this.position ? offset + sequence.length : this.position;
375
+ throw new BSONError('input cannot be string');
385
376
  }
386
377
  }
387
378
  read(position, length) {
388
379
  length = length && length > 0 ? length : this.position;
389
380
  return this.buffer.slice(position, position + length);
390
381
  }
391
- value(asRaw) {
392
- asRaw = !!asRaw;
393
- if (asRaw && this.buffer.length === this.position) {
394
- return this.buffer;
395
- }
396
- if (asRaw) {
397
- return this.buffer.slice(0, this.position);
398
- }
399
- return ByteUtils.toISO88591(this.buffer.subarray(0, this.position));
382
+ value() {
383
+ return this.buffer.length === this.position
384
+ ? this.buffer
385
+ : this.buffer.subarray(0, this.position);
400
386
  }
401
387
  length() {
402
388
  return this.position;
@@ -597,7 +583,6 @@ class UUID extends Binary {
597
583
  return `new UUID("${this.toHexString()}")`;
598
584
  }
599
585
  }
600
- UUID.cacheHexString = false;
601
586
 
602
587
  class Code extends BSONValue {
603
588
  get _bsontype() {
@@ -628,7 +613,7 @@ class Code extends BSONValue {
628
613
  }
629
614
  inspect() {
630
615
  const codeJson = this.toJSON();
631
- return `new Code("${String(codeJson.code)}"${codeJson.scope != null ? `, ${JSON.stringify(codeJson.scope)}` : ''})`;
616
+ return `new Code(${JSON.stringify(String(codeJson.code))}${codeJson.scope != null ? `, ${JSON.stringify(codeJson.scope)}` : ''})`;
632
617
  }
633
618
  }
634
619
 
@@ -1438,6 +1423,7 @@ class Decimal128 extends BSONValue {
1438
1423
  }
1439
1424
  static fromString(representation) {
1440
1425
  let isNegative = false;
1426
+ let sawSign = false;
1441
1427
  let sawRadix = false;
1442
1428
  let foundNonZero = false;
1443
1429
  let significantDigits = 0;
@@ -1448,10 +1434,8 @@ class Decimal128 extends BSONValue {
1448
1434
  const digits = [0];
1449
1435
  let nDigitsStored = 0;
1450
1436
  let digitsInsert = 0;
1451
- let firstDigit = 0;
1452
1437
  let lastDigit = 0;
1453
1438
  let exponent = 0;
1454
- let i = 0;
1455
1439
  let significandHigh = new Long(0, 0);
1456
1440
  let significandLow = new Long(0, 0);
1457
1441
  let biasedExponent = 0;
@@ -1479,6 +1463,7 @@ class Decimal128 extends BSONValue {
1479
1463
  }
1480
1464
  }
1481
1465
  if (representation[index] === '+' || representation[index] === '-') {
1466
+ sawSign = true;
1482
1467
  isNegative = representation[index++] === '-';
1483
1468
  }
1484
1469
  if (!isDigit(representation[index]) && representation[index] !== '.') {
@@ -1497,7 +1482,7 @@ class Decimal128 extends BSONValue {
1497
1482
  index = index + 1;
1498
1483
  continue;
1499
1484
  }
1500
- if (nDigitsStored < 34) {
1485
+ if (nDigitsStored < MAX_DIGITS) {
1501
1486
  if (representation[index] !== '0' || foundNonZero) {
1502
1487
  if (!foundNonZero) {
1503
1488
  firstNonZero = nDigitsRead;
@@ -1525,10 +1510,7 @@ class Decimal128 extends BSONValue {
1525
1510
  }
1526
1511
  if (representation[index])
1527
1512
  return new Decimal128(NAN_BUFFER);
1528
- firstDigit = 0;
1529
1513
  if (!nDigitsStored) {
1530
- firstDigit = 0;
1531
- lastDigit = 0;
1532
1514
  digits[0] = 0;
1533
1515
  nDigits = 1;
1534
1516
  nDigitsStored = 1;
@@ -1538,12 +1520,12 @@ class Decimal128 extends BSONValue {
1538
1520
  lastDigit = nDigitsStored - 1;
1539
1521
  significantDigits = nDigits;
1540
1522
  if (significantDigits !== 1) {
1541
- while (digits[firstNonZero + significantDigits - 1] === 0) {
1523
+ while (representation[firstNonZero + significantDigits - 1 + Number(sawSign) + Number(sawRadix)] === '0') {
1542
1524
  significantDigits = significantDigits - 1;
1543
1525
  }
1544
1526
  }
1545
1527
  }
1546
- if (exponent <= radixPosition && radixPosition - exponent > 1 << 14) {
1528
+ if (exponent <= radixPosition && radixPosition > exponent + (1 << 14)) {
1547
1529
  exponent = EXPONENT_MIN;
1548
1530
  }
1549
1531
  else {
@@ -1551,9 +1533,8 @@ class Decimal128 extends BSONValue {
1551
1533
  }
1552
1534
  while (exponent > EXPONENT_MAX) {
1553
1535
  lastDigit = lastDigit + 1;
1554
- if (lastDigit - firstDigit > MAX_DIGITS) {
1555
- const digitsString = digits.join('');
1556
- if (digitsString.match(/^0+$/)) {
1536
+ if (lastDigit >= MAX_DIGITS) {
1537
+ if (significantDigits === 0) {
1557
1538
  exponent = EXPONENT_MAX;
1558
1539
  break;
1559
1540
  }
@@ -1562,69 +1543,43 @@ class Decimal128 extends BSONValue {
1562
1543
  exponent = exponent - 1;
1563
1544
  }
1564
1545
  while (exponent < EXPONENT_MIN || nDigitsStored < nDigits) {
1565
- if (lastDigit === 0 && significantDigits < nDigitsStored) {
1566
- exponent = EXPONENT_MIN;
1567
- significantDigits = 0;
1568
- break;
1546
+ if (lastDigit === 0) {
1547
+ if (significantDigits === 0) {
1548
+ exponent = EXPONENT_MIN;
1549
+ break;
1550
+ }
1551
+ invalidErr(representation, 'exponent underflow');
1569
1552
  }
1570
1553
  if (nDigitsStored < nDigits) {
1554
+ if (representation[nDigits - 1 + Number(sawSign) + Number(sawRadix)] !== '0' &&
1555
+ significantDigits !== 0) {
1556
+ invalidErr(representation, 'inexact rounding');
1557
+ }
1571
1558
  nDigits = nDigits - 1;
1572
1559
  }
1573
1560
  else {
1561
+ if (digits[lastDigit] !== 0) {
1562
+ invalidErr(representation, 'inexact rounding');
1563
+ }
1574
1564
  lastDigit = lastDigit - 1;
1575
1565
  }
1576
1566
  if (exponent < EXPONENT_MAX) {
1577
1567
  exponent = exponent + 1;
1578
1568
  }
1579
1569
  else {
1580
- const digitsString = digits.join('');
1581
- if (digitsString.match(/^0+$/)) {
1582
- exponent = EXPONENT_MAX;
1583
- break;
1584
- }
1585
1570
  invalidErr(representation, 'overflow');
1586
1571
  }
1587
1572
  }
1588
- if (lastDigit - firstDigit + 1 < significantDigits) {
1589
- let endOfString = nDigitsRead;
1573
+ if (lastDigit + 1 < significantDigits) {
1590
1574
  if (sawRadix) {
1591
1575
  firstNonZero = firstNonZero + 1;
1592
- endOfString = endOfString + 1;
1593
1576
  }
1594
- if (isNegative) {
1577
+ if (sawSign) {
1595
1578
  firstNonZero = firstNonZero + 1;
1596
- endOfString = endOfString + 1;
1597
1579
  }
1598
1580
  const roundDigit = parseInt(representation[firstNonZero + lastDigit + 1], 10);
1599
- let roundBit = 0;
1600
- if (roundDigit >= 5) {
1601
- roundBit = 1;
1602
- if (roundDigit === 5) {
1603
- roundBit = digits[lastDigit] % 2 === 1 ? 1 : 0;
1604
- for (i = firstNonZero + lastDigit + 2; i < endOfString; i++) {
1605
- if (parseInt(representation[i], 10)) {
1606
- roundBit = 1;
1607
- break;
1608
- }
1609
- }
1610
- }
1611
- }
1612
- if (roundBit) {
1613
- let dIdx = lastDigit;
1614
- for (; dIdx >= 0; dIdx--) {
1615
- if (++digits[dIdx] > 9) {
1616
- digits[dIdx] = 0;
1617
- if (dIdx === 0) {
1618
- if (exponent < EXPONENT_MAX) {
1619
- exponent = exponent + 1;
1620
- digits[dIdx] = 1;
1621
- }
1622
- else {
1623
- return new Decimal128(isNegative ? INF_NEGATIVE_BUFFER : INF_POSITIVE_BUFFER);
1624
- }
1625
- }
1626
- }
1627
- }
1581
+ if (roundDigit !== 0) {
1582
+ invalidErr(representation, 'inexact rounding');
1628
1583
  }
1629
1584
  }
1630
1585
  significandHigh = Long.fromNumber(0);
@@ -1633,8 +1588,8 @@ class Decimal128 extends BSONValue {
1633
1588
  significandHigh = Long.fromNumber(0);
1634
1589
  significandLow = Long.fromNumber(0);
1635
1590
  }
1636
- else if (lastDigit - firstDigit < 17) {
1637
- let dIdx = firstDigit;
1591
+ else if (lastDigit < 17) {
1592
+ let dIdx = 0;
1638
1593
  significandLow = Long.fromNumber(digits[dIdx++]);
1639
1594
  significandHigh = new Long(0, 0);
1640
1595
  for (; dIdx <= lastDigit; dIdx++) {
@@ -1643,7 +1598,7 @@ class Decimal128 extends BSONValue {
1643
1598
  }
1644
1599
  }
1645
1600
  else {
1646
- let dIdx = firstDigit;
1601
+ let dIdx = 0;
1647
1602
  significandHigh = Long.fromNumber(digits[dIdx++]);
1648
1603
  for (; dIdx <= lastDigit - 17; dIdx++) {
1649
1604
  significandHigh = significandHigh.multiply(Long.fromNumber(10));
@@ -1991,20 +1946,11 @@ class ObjectId extends BSONValue {
1991
1946
  this[kId] = ByteUtils.toLocalBufferType(workingId);
1992
1947
  }
1993
1948
  else if (typeof workingId === 'string') {
1994
- if (workingId.length === 12) {
1995
- const bytes = ByteUtils.fromUTF8(workingId);
1996
- if (bytes.byteLength === 12) {
1997
- this[kId] = bytes;
1998
- }
1999
- else {
2000
- throw new BSONError('Argument passed in must be a string of 12 bytes');
2001
- }
2002
- }
2003
- else if (workingId.length === 24 && checkForHexRegExp.test(workingId)) {
1949
+ if (workingId.length === 24 && checkForHexRegExp.test(workingId)) {
2004
1950
  this[kId] = ByteUtils.fromHex(workingId);
2005
1951
  }
2006
1952
  else {
2007
- throw new BSONError('Argument passed in must be a string of 12 bytes or a string of 24 hex characters or an integer');
1953
+ throw new BSONError('input must be a 24 character hex string, 12 byte Uint8Array, or an integer');
2008
1954
  }
2009
1955
  }
2010
1956
  else {
@@ -2066,30 +2012,25 @@ class ObjectId extends BSONValue {
2066
2012
  toJSON() {
2067
2013
  return this.toHexString();
2068
2014
  }
2015
+ static is(variable) {
2016
+ return (variable != null &&
2017
+ typeof variable === 'object' &&
2018
+ '_bsontype' in variable &&
2019
+ variable._bsontype === 'ObjectId');
2020
+ }
2069
2021
  equals(otherId) {
2070
2022
  if (otherId === undefined || otherId === null) {
2071
2023
  return false;
2072
2024
  }
2073
- if (otherId instanceof ObjectId) {
2025
+ if (ObjectId.is(otherId)) {
2074
2026
  return this[kId][11] === otherId[kId][11] && ByteUtils.equals(this[kId], otherId[kId]);
2075
2027
  }
2076
- if (typeof otherId === 'string' &&
2077
- ObjectId.isValid(otherId) &&
2078
- otherId.length === 12 &&
2079
- isUint8Array(this.id)) {
2080
- return ByteUtils.equals(this.id, ByteUtils.fromISO88591(otherId));
2081
- }
2082
- if (typeof otherId === 'string' && ObjectId.isValid(otherId) && otherId.length === 24) {
2028
+ if (typeof otherId === 'string') {
2083
2029
  return otherId.toLowerCase() === this.toHexString();
2084
2030
  }
2085
- if (typeof otherId === 'string' && ObjectId.isValid(otherId) && otherId.length === 12) {
2086
- return ByteUtils.equals(ByteUtils.fromUTF8(otherId), this.id);
2087
- }
2088
- if (typeof otherId === 'object' &&
2089
- 'toHexString' in otherId &&
2090
- typeof otherId.toHexString === 'function') {
2031
+ if (typeof otherId === 'object' && typeof otherId.toHexString === 'function') {
2091
2032
  const otherIdString = otherId.toHexString();
2092
- const thisIdString = this.toHexString().toLowerCase();
2033
+ const thisIdString = this.toHexString();
2093
2034
  return typeof otherIdString === 'string' && otherIdString.toLowerCase() === thisIdString;
2094
2035
  }
2095
2036
  return false;
@@ -2379,7 +2320,7 @@ class BSONSymbol extends BSONValue {
2379
2320
  return this.value;
2380
2321
  }
2381
2322
  inspect() {
2382
- return `new BSONSymbol("${this.value}")`;
2323
+ return `new BSONSymbol(${JSON.stringify(this.value)})`;
2383
2324
  }
2384
2325
  toJSON() {
2385
2326
  return this.value;