Skip to content

Commit

Permalink
fix: permit BSON types to be created without new (#424)
Browse files Browse the repository at this point in the history
Reverts a change that upgraded the BSON types to es6 classes
preventing types from being constructed without using new.

NODE-3064
  • Loading branch information
nbbeeken authored Mar 1, 2021
1 parent 616665f commit d2bc284
Show file tree
Hide file tree
Showing 17 changed files with 88 additions and 18 deletions.
2 changes: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ dist/
node_modules/
docs/
types/
lib/
*.d.ts
2 changes: 1 addition & 1 deletion rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const tsConfig = {
checkJs: false,
strict: true,
alwaysStrict: true,
target: 'ES2017',
target: 'es5',
module: 'commonjs',
moduleResolution: 'node',
lib: ['ES2017', 'ES2020.BigInt', 'ES2017.TypedArrays'],
Expand Down
8 changes: 5 additions & 3 deletions src/binary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,17 @@ export class Binary {
/** User BSON type */
static readonly SUBTYPE_USER_DEFINED = 128;

buffer: Buffer;
sub_type: number;
position: number;
buffer!: Buffer;
sub_type!: number;
position!: number;

/**
* @param buffer - a buffer object containing the binary data.
* @param subType - the option binary type.
*/
constructor(buffer?: string | BinarySequence, subType?: number) {
if (!(this instanceof Binary)) return new Binary(buffer, subType);

if (
!(buffer == null) &&
!(typeof buffer === 'string') &&
Expand Down
4 changes: 3 additions & 1 deletion src/code.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ export interface CodeExtended {
export class Code {
_bsontype!: 'Code';

code: string | Function;
code!: string | Function;
scope?: Document;
/**
* @param code - a string or function.
* @param scope - an optional scope for the function.
*/
constructor(code: string | Function, scope?: Document) {
if (!(this instanceof Code)) return new Code(code, scope);

this.code = code;
this.scope = scope;
}
Expand Down
8 changes: 5 additions & 3 deletions src/db_ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,19 @@ export function isDBRefLike(value: unknown): value is DBRefLike {
export class DBRef {
_bsontype!: 'DBRef';

collection: string;
oid: ObjectId;
collection!: string;
oid!: ObjectId;
db?: string;
fields: Document;
fields!: Document;

/**
* @param collection - the collection name.
* @param oid - the reference ObjectId.
* @param db - optional db name, if omitted the reference is local to the current db.
*/
constructor(collection: string, oid: ObjectId, db?: string, fields?: Document) {
if (!(this instanceof DBRef)) return new DBRef(collection, oid, db, fields);

// check if namespace has been provided
const parts = collection.split('.');
if (parts.length === 2) {
Expand Down
4 changes: 3 additions & 1 deletion src/decimal128.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,12 @@ export interface Decimal128Extended {
export class Decimal128 {
_bsontype!: 'Decimal128';

readonly bytes: Buffer;
readonly bytes!: Buffer;

/** @param bytes - a buffer containing the raw Decimal128 bytes in little endian order */
constructor(bytes: Buffer) {
if (!(this instanceof Decimal128)) return new Decimal128(bytes);

this.bytes = bytes;
}

Expand Down
4 changes: 3 additions & 1 deletion src/double.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ export interface DoubleExtended {
export class Double {
_bsontype!: 'Double';

value: number;
value!: number;
/**
* Create a Double type
*
* @param value - the number we want to represent as a double.
*/
constructor(value: number) {
if (!(this instanceof Double)) return new Double(value);

if ((value as unknown) instanceof Number) {
value = value.valueOf();
}
Expand Down
4 changes: 3 additions & 1 deletion src/int_32.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ export interface Int32Extended {
export class Int32 {
_bsontype!: 'Int32';

value: number;
value!: number;
/**
* Create an Int32 type
*
* @param value - the number we want to represent as an int32.
*/
constructor(value: number | string) {
if (!(this instanceof Int32)) return new Int32(value);

if ((value as unknown) instanceof Number) {
value = value.valueOf();
}
Expand Down
8 changes: 5 additions & 3 deletions src/long.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,17 @@ export class Long {
/**
* The high 32 bits as a signed value.
*/
high: number;
high!: number;

/**
* The low 32 bits as a signed value.
*/
low: number;
low!: number;

/**
* Whether unsigned or not.
*/
unsigned: boolean;
unsigned!: boolean;

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

this.low = low | 0;
this.high = high | 0;
this.unsigned = !!unsigned;
Expand Down
4 changes: 4 additions & 0 deletions src/max_key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ export interface MaxKeyExtended {
export class MaxKey {
_bsontype!: 'MaxKey';

constructor() {
if (!(this instanceof MaxKey)) return new MaxKey();
}

/** @internal */
toExtendedJSON(): MaxKeyExtended {
return { $maxKey: 1 };
Expand Down
4 changes: 4 additions & 0 deletions src/min_key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ export interface MinKeyExtended {
export class MinKey {
_bsontype!: 'MinKey';

constructor() {
if (!(this instanceof MinKey)) return new MinKey();
}

/** @internal */
toExtendedJSON(): MinKeyExtended {
return { $minKey: 1 };
Expand Down
2 changes: 2 additions & 0 deletions src/objectid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ export class ObjectId {
* @param id - Can be a 24 character hex string, 12 byte binary Buffer, or a number.
*/
constructor(id?: string | Buffer | number | ObjectIdLike | ObjectId) {
if (!(this instanceof ObjectId)) return new ObjectId(id);

// Duck-typing to support ObjectId from different npm packages
if (id instanceof ObjectId) {
this[kId] = id.id;
Expand Down
6 changes: 4 additions & 2 deletions src/regexp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ export interface BSONRegExpExtended {
export class BSONRegExp {
_bsontype!: 'BSONRegExp';

pattern: string;
options: string;
pattern!: string;
options!: string;
/**
* @param pattern - The regular expression pattern to match
* @param options - The regular expression options
*/
constructor(pattern: string, options?: string) {
if (!(this instanceof BSONRegExp)) return new BSONRegExp(pattern, options);

this.pattern = pattern;
this.options = options ?? '';
// Execute
Expand Down
4 changes: 3 additions & 1 deletion src/symbol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ export interface BSONSymbolExtended {
export class BSONSymbol {
_bsontype!: 'Symbol';

value: string;
value!: string;
/**
* @param value - the string representing the symbol.
*/
constructor(value: string) {
if (!(this instanceof BSONSymbol)) return new BSONSymbol(value);

this.value = value;
}

Expand Down
5 changes: 5 additions & 0 deletions src/timestamp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,13 @@ export class Timestamp extends LongWithoutOverridesClass {
* @param low - the low (signed) 32 bits of the Timestamp.
* @param high - the high (signed) 32 bits of the Timestamp.
*/
constructor(low: Long);
constructor(low: number, high: number);
constructor(low: number | Long, high?: number) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
///@ts-expect-error
if (!(this instanceof Timestamp)) return new Timestamp(low, high);

if (Long.isLong(low)) {
super(low.low, low.high, true);
} else {
Expand Down
35 changes: 35 additions & 0 deletions test/node/bson_types_construction_tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
'use strict';
const BSON = require('../register-bson');

describe('Constructing BSON types', function () {
it('with new keyword should work', function () {
const oid = new BSON.ObjectId();
new BSON.DBRef('test', oid);
new BSON.BSONRegExp('aaa');
new BSON.BSONSymbol('aaa');
new BSON.Binary('aaa');
new BSON.Code(function () {});
new BSON.Decimal128('aaa');
new BSON.Double(2.3);
new BSON.Int32(1);
new BSON.Long(0, 0);
new BSON.Timestamp(0, 0);
new BSON.MaxKey();
new BSON.MinKey();
});
it('as a function call should work', function () {
const oid = BSON.ObjectId();
BSON.DBRef('test', oid);
BSON.BSONRegExp('aaa');
BSON.BSONSymbol('aaa');
BSON.Binary('aaa');
BSON.Code(function () {});
BSON.Decimal128('aaa');
BSON.Double(2.3);
BSON.Int32(1);
BSON.Long(0, 0);
BSON.Timestamp(0, 0);
BSON.MaxKey();
BSON.MinKey();
});
});
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"checkJs": false,
"strict": true,
"alwaysStrict": true,
"target": "ES2017",
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"lib": [
Expand Down

0 comments on commit d2bc284

Please sign in to comment.