Skip to content

Commit d2bc284

Browse files
authored
fix: permit BSON types to be created without new (#424)
Reverts a change that upgraded the BSON types to es6 classes preventing types from being constructed without using new. NODE-3064
1 parent 616665f commit d2bc284

17 files changed

+88
-18
lines changed

.eslintignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ dist/
22
node_modules/
33
docs/
44
types/
5+
lib/
6+
*.d.ts

rollup.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const tsConfig = {
1010
checkJs: false,
1111
strict: true,
1212
alwaysStrict: true,
13-
target: 'ES2017',
13+
target: 'es5',
1414
module: 'commonjs',
1515
moduleResolution: 'node',
1616
lib: ['ES2017', 'ES2020.BigInt', 'ES2017.TypedArrays'],

src/binary.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,17 @@ export class Binary {
5050
/** User BSON type */
5151
static readonly SUBTYPE_USER_DEFINED = 128;
5252

53-
buffer: Buffer;
54-
sub_type: number;
55-
position: number;
53+
buffer!: Buffer;
54+
sub_type!: number;
55+
position!: number;
5656

5757
/**
5858
* @param buffer - a buffer object containing the binary data.
5959
* @param subType - the option binary type.
6060
*/
6161
constructor(buffer?: string | BinarySequence, subType?: number) {
62+
if (!(this instanceof Binary)) return new Binary(buffer, subType);
63+
6264
if (
6365
!(buffer == null) &&
6466
!(typeof buffer === 'string') &&

src/code.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@ export interface CodeExtended {
1313
export class Code {
1414
_bsontype!: 'Code';
1515

16-
code: string | Function;
16+
code!: string | Function;
1717
scope?: Document;
1818
/**
1919
* @param code - a string or function.
2020
* @param scope - an optional scope for the function.
2121
*/
2222
constructor(code: string | Function, scope?: Document) {
23+
if (!(this instanceof Code)) return new Code(code, scope);
24+
2325
this.code = code;
2426
this.scope = scope;
2527
}

src/db_ref.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,19 @@ export function isDBRefLike(value: unknown): value is DBRefLike {
2222
export class DBRef {
2323
_bsontype!: 'DBRef';
2424

25-
collection: string;
26-
oid: ObjectId;
25+
collection!: string;
26+
oid!: ObjectId;
2727
db?: string;
28-
fields: Document;
28+
fields!: Document;
2929

3030
/**
3131
* @param collection - the collection name.
3232
* @param oid - the reference ObjectId.
3333
* @param db - optional db name, if omitted the reference is local to the current db.
3434
*/
3535
constructor(collection: string, oid: ObjectId, db?: string, fields?: Document) {
36+
if (!(this instanceof DBRef)) return new DBRef(collection, oid, db, fields);
37+
3638
// check if namespace has been provided
3739
const parts = collection.split('.');
3840
if (parts.length === 2) {

src/decimal128.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,12 @@ export interface Decimal128Extended {
165165
export class Decimal128 {
166166
_bsontype!: 'Decimal128';
167167

168-
readonly bytes: Buffer;
168+
readonly bytes!: Buffer;
169169

170170
/** @param bytes - a buffer containing the raw Decimal128 bytes in little endian order */
171171
constructor(bytes: Buffer) {
172+
if (!(this instanceof Decimal128)) return new Decimal128(bytes);
173+
172174
this.bytes = bytes;
173175
}
174176

src/double.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ export interface DoubleExtended {
1212
export class Double {
1313
_bsontype!: 'Double';
1414

15-
value: number;
15+
value!: number;
1616
/**
1717
* Create a Double type
1818
*
1919
* @param value - the number we want to represent as a double.
2020
*/
2121
constructor(value: number) {
22+
if (!(this instanceof Double)) return new Double(value);
23+
2224
if ((value as unknown) instanceof Number) {
2325
value = value.valueOf();
2426
}

src/int_32.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ export interface Int32Extended {
1212
export class Int32 {
1313
_bsontype!: 'Int32';
1414

15-
value: number;
15+
value!: number;
1616
/**
1717
* Create an Int32 type
1818
*
1919
* @param value - the number we want to represent as an int32.
2020
*/
2121
constructor(value: number | string) {
22+
if (!(this instanceof Int32)) return new Int32(value);
23+
2224
if ((value as unknown) instanceof Number) {
2325
value = value.valueOf();
2426
}

src/long.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,17 @@ export class Long {
8282
/**
8383
* The high 32 bits as a signed value.
8484
*/
85-
high: number;
85+
high!: number;
8686

8787
/**
8888
* The low 32 bits as a signed value.
8989
*/
90-
low: number;
90+
low!: number;
9191

9292
/**
9393
* Whether unsigned or not.
9494
*/
95-
unsigned: boolean;
95+
unsigned!: boolean;
9696

9797
/**
9898
* Constructs a 64 bit two's-complement integer, given its low and high 32 bit values as *signed* integers.
@@ -102,6 +102,8 @@ export class Long {
102102
* @param unsigned - Whether unsigned or not, defaults to signed
103103
*/
104104
constructor(low = 0, high = 0, unsigned?: boolean) {
105+
if (!(this instanceof Long)) return new Long(low, high, unsigned);
106+
105107
this.low = low | 0;
106108
this.high = high | 0;
107109
this.unsigned = !!unsigned;

src/max_key.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ export interface MaxKeyExtended {
1010
export class MaxKey {
1111
_bsontype!: 'MaxKey';
1212

13+
constructor() {
14+
if (!(this instanceof MaxKey)) return new MaxKey();
15+
}
16+
1317
/** @internal */
1418
toExtendedJSON(): MaxKeyExtended {
1519
return { $maxKey: 1 };

src/min_key.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ export interface MinKeyExtended {
1010
export class MinKey {
1111
_bsontype!: 'MinKey';
1212

13+
constructor() {
14+
if (!(this instanceof MinKey)) return new MinKey();
15+
}
16+
1317
/** @internal */
1418
toExtendedJSON(): MinKeyExtended {
1519
return { $minKey: 1 };

src/objectid.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ export class ObjectId {
5757
* @param id - Can be a 24 character hex string, 12 byte binary Buffer, or a number.
5858
*/
5959
constructor(id?: string | Buffer | number | ObjectIdLike | ObjectId) {
60+
if (!(this instanceof ObjectId)) return new ObjectId(id);
61+
6062
// Duck-typing to support ObjectId from different npm packages
6163
if (id instanceof ObjectId) {
6264
this[kId] = id.id;

src/regexp.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,15 @@ export interface BSONRegExpExtended {
2525
export class BSONRegExp {
2626
_bsontype!: 'BSONRegExp';
2727

28-
pattern: string;
29-
options: string;
28+
pattern!: string;
29+
options!: string;
3030
/**
3131
* @param pattern - The regular expression pattern to match
3232
* @param options - The regular expression options
3333
*/
3434
constructor(pattern: string, options?: string) {
35+
if (!(this instanceof BSONRegExp)) return new BSONRegExp(pattern, options);
36+
3537
this.pattern = pattern;
3638
this.options = options ?? '';
3739
// Execute

src/symbol.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ export interface BSONSymbolExtended {
1010
export class BSONSymbol {
1111
_bsontype!: 'Symbol';
1212

13-
value: string;
13+
value!: string;
1414
/**
1515
* @param value - the string representing the symbol.
1616
*/
1717
constructor(value: string) {
18+
if (!(this instanceof BSONSymbol)) return new BSONSymbol(value);
19+
1820
this.value = value;
1921
}
2022

src/timestamp.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,13 @@ export class Timestamp extends LongWithoutOverridesClass {
3131
* @param low - the low (signed) 32 bits of the Timestamp.
3232
* @param high - the high (signed) 32 bits of the Timestamp.
3333
*/
34+
constructor(low: Long);
3435
constructor(low: number, high: number);
3536
constructor(low: number | Long, high?: number) {
37+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
38+
///@ts-expect-error
39+
if (!(this instanceof Timestamp)) return new Timestamp(low, high);
40+
3641
if (Long.isLong(low)) {
3742
super(low.low, low.high, true);
3843
} else {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'use strict';
2+
const BSON = require('../register-bson');
3+
4+
describe('Constructing BSON types', function () {
5+
it('with new keyword should work', function () {
6+
const oid = new BSON.ObjectId();
7+
new BSON.DBRef('test', oid);
8+
new BSON.BSONRegExp('aaa');
9+
new BSON.BSONSymbol('aaa');
10+
new BSON.Binary('aaa');
11+
new BSON.Code(function () {});
12+
new BSON.Decimal128('aaa');
13+
new BSON.Double(2.3);
14+
new BSON.Int32(1);
15+
new BSON.Long(0, 0);
16+
new BSON.Timestamp(0, 0);
17+
new BSON.MaxKey();
18+
new BSON.MinKey();
19+
});
20+
it('as a function call should work', function () {
21+
const oid = BSON.ObjectId();
22+
BSON.DBRef('test', oid);
23+
BSON.BSONRegExp('aaa');
24+
BSON.BSONSymbol('aaa');
25+
BSON.Binary('aaa');
26+
BSON.Code(function () {});
27+
BSON.Decimal128('aaa');
28+
BSON.Double(2.3);
29+
BSON.Int32(1);
30+
BSON.Long(0, 0);
31+
BSON.Timestamp(0, 0);
32+
BSON.MaxKey();
33+
BSON.MinKey();
34+
});
35+
});

tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"checkJs": false,
55
"strict": true,
66
"alwaysStrict": true,
7-
"target": "ES2017",
7+
"target": "es5",
88
"module": "commonjs",
99
"moduleResolution": "node",
1010
"lib": [

0 commit comments

Comments
 (0)