Skip to content

Commit

Permalink
feat!(NODE-4710): remove capital D ObjectID export (#528)
Browse files Browse the repository at this point in the history
Co-authored-by: Durran Jordan <durran@gmail.com>
  • Loading branch information
nbbeeken and durran committed Dec 8, 2022
1 parent 196f9f8 commit 8511225
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 13 deletions.
4 changes: 4 additions & 0 deletions docs/upgrade-to-v5.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,7 @@ Now `-0` can be used directly
BSON.deserialize(BSON.serialize({ d: -0 }))
// type preservation, returns { d: -0 }
```

### Capital "D" ObjectID export removed

For clarity the deprecated and duplicate export `ObjectID` has been removed. `ObjectId` matches the class name and is equal in every way to the capital "D" export.
7 changes: 1 addition & 6 deletions src/bson.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,7 @@ export {
MinKey,
MaxKey,
BSONRegExp,
Decimal128,
// In 4.0.0 and 4.0.1, this property name was changed to ObjectId to match the class name.
// This caused interoperability problems with previous versions of the library, so in
// later builds we changed it back to ObjectID (capital D) to match legacy implementations.
ObjectId as ObjectID
Decimal128
};
export { BSONError, BSONTypeError } from './error';
export { BSONType } from './constants';
Expand Down Expand Up @@ -273,7 +269,6 @@ const BSON = {
MaxKey,
MinKey,
ObjectId,
ObjectID: ObjectId,
BSONRegExp,
BSONSymbol,
Timestamp,
Expand Down
5 changes: 4 additions & 1 deletion src/extended_json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,10 @@ const BSON_TYPE_MAPPINGS = {
MaxKey: () => new MaxKey(),
MinKey: () => new MinKey(),
ObjectID: (o: ObjectId) => new ObjectId(o),
ObjectId: (o: ObjectId) => new ObjectId(o), // support 4.0.0/4.0.1 before _bsontype was reverted back to ObjectID
// The _bsontype for ObjectId is spelled with a capital "D", to the mapping above will be used (most of the time)
// specifically BSON versions 4.0.0 and 4.0.1 the _bsontype was changed to "ObjectId" so we keep this mapping to support
// those version of BSON
ObjectId: (o: ObjectId) => new ObjectId(o),
BSONRegExp: (o: BSONRegExp) => new BSONRegExp(o.pattern, o.options),
Symbol: (o: BSONSymbol) => new BSONSymbol(o.value),
Timestamp: (o: Timestamp) => Timestamp.fromBits(o.low, o.high)
Expand Down
1 change: 0 additions & 1 deletion test/node/exports.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ const EXPECTED_EXPORTS = [
'MaxKey',
'BSONRegExp',
'Decimal128',
'ObjectID',
'BSONError',
'BSONTypeError',
'setInternalBufferSize',
Expand Down
9 changes: 5 additions & 4 deletions test/node/extended_json.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as BSON from '../register-bson';
const EJSON = BSON.EJSON;
import * as vm from 'node:vm';
import { expect } from 'chai';

// BSON types
const Binary = BSON.Binary;
Expand All @@ -13,7 +14,7 @@ const Int32 = BSON.Int32;
const Long = BSON.Long;
const MaxKey = BSON.MaxKey;
const MinKey = BSON.MinKey;
const ObjectID = BSON.ObjectID;
const ObjectID = BSON.ObjectId;
const ObjectId = BSON.ObjectId;
const BSONRegExp = BSON.BSONRegExp;
const BSONSymbol = BSON.BSONSymbol;
Expand Down Expand Up @@ -365,14 +366,14 @@ describe('Extended JSON', function () {
binary: new bsonModule.Binary(buffer),
code: new bsonModule.Code('function() {}'),
dbRef: new bsonModule.DBRef('tests', new Int32(1), 'test'),
decimal128: new bsonModule.Decimal128.fromString('9991223372036854775807'),
decimal128: bsonModule.Decimal128.fromString('9991223372036854775807'),
double: new bsonModule.Double(10.1),
int32: new bsonModule.Int32(10),
long: new bsonModule.Long.fromString('1223372036854775807'),
long: bsonModule.Long.fromString('1223372036854775807'),
maxKey: new bsonModule.MaxKey(),
// minKey: new bsonModule.MinKey(), // broken until #310 is fixed in 1.x
objectId: bsonModule.ObjectId.createFromHexString('111111111111111111111111'),
objectID: bsonModule.ObjectID.createFromHexString('111111111111111111111111'),
objectID: bsonModule.ObjectId.createFromHexString('111111111111111111111111'),
bsonRegExp: new bsonModule.BSONRegExp('hello world', 'i'),
symbol: bsonModule.BSONSymbol
? new bsonModule.BSONSymbol('symbol')
Expand Down
55 changes: 55 additions & 0 deletions test/node/object_id_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

const Buffer = require('buffer').Buffer;
const BSON = require('../register-bson');
const EJSON = BSON.EJSON;
const BSONTypeError = BSON.BSONTypeError;
const ObjectId = BSON.ObjectId;
const util = require('util');
const { expect } = require('chai');
const { bufferFromHexArray } = require('./tools/utils');
const getSymbolFrom = require('./tools/utils').getSymbolFrom;
const isBufferOrUint8Array = require('./tools/utils').isBufferOrUint8Array;

Expand All @@ -28,6 +31,58 @@ describe('ObjectId', function () {
});
});

describe('_bsontype casing cross compatibility', () => {
it('EJSON stringify understands capital or lowercase D _bsontype', () => {
const resultFromCapitalD = EJSON.stringify(
{ a: new ObjectId('00'.repeat(12)) },
{ relaxed: false }
);
const resultFromLowercaseD = EJSON.stringify(
{
a: new (class extends ObjectId {
get _bsontype() {
return 'ObjectId';
}
})('00'.repeat(12))
},
{ relaxed: false }
);

expect(JSON.parse(resultFromCapitalD))
.to.have.property('a')
.that.deep.equals({ $oid: '00'.repeat(12) });
expect(JSON.parse(resultFromLowercaseD))
.to.have.property('a')
.that.deep.equals({ $oid: '00'.repeat(12) });
});

it('EJSON stringify understands capital or lowercase D _bsontype', () => {
const resultFromCapitalD = BSON.serialize(
{ a: new ObjectId('00'.repeat(12)) },
{ relaxed: false }
);
const resultFromLowercaseD = BSON.serialize(
{
a: new (class extends ObjectId {
get _bsontype() {
return 'ObjectId';
}
})('00'.repeat(12))
},
{ relaxed: false }
);

const expectedBytes = bufferFromHexArray([
'07', // oid type
'6100', // 'a\x00'
'00'.repeat(12) // oid bytes
]);

expect(resultFromCapitalD).to.deep.equal(expectedBytes);
expect(resultFromLowercaseD).to.deep.equal(expectedBytes);
});
});

it('creates an objectId with user defined value in the timestamp field', function () {
const a = ObjectId.createFromTime(1);
expect(a.id.slice(0, 4)).to.deep.equal(Buffer.from([0, 0, 0, 1]));
Expand Down
2 changes: 1 addition & 1 deletion test/types/bson.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ expectError(MinKey.prototype.toJSON);
expectError(Long.prototype.toJSON);
expectError(BSONRegExp.prototype.toJSON);

// ObjectID uses a capital for backwards compatibility
// ObjectID uses a capital "D", this does not relate to the class name, or export name, only the determination for serialization
expectType<'ObjectID'>(ObjectId.prototype._bsontype)
// BSONSymbol was renamed to not conflict with the global JS Symbol
// but its _bsontype is still 'Symbol'
Expand Down

0 comments on commit 8511225

Please sign in to comment.