Skip to content

Commit 896061b

Browse files
committed
weakMap + tests
1 parent 295cc72 commit 896061b

File tree

2 files changed

+44
-24
lines changed

2 files changed

+44
-24
lines changed

src/objectid.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ import { NumberUtils } from './utils/number_utils';
77
// Unique sequence for the current process (initialized on first use)
88
let PROCESS_UNIQUE: Uint8Array | null = null;
99

10+
/** ObjectId hexString cache @internal */
11+
const __idCache = new WeakMap(); // TODO convert this to #__id private field when target updated to ES2022
12+
1013
/** @public */
1114
export interface ObjectIdLike {
1215
id: string | Uint8Array;
13-
__id?: string;
1416
toHexString(): string;
1517
}
1618

@@ -36,8 +38,6 @@ export class ObjectId extends BSONValue {
3638

3739
/** ObjectId Bytes @internal */
3840
private buffer!: Uint8Array;
39-
/** ObjectId hexString cache @internal */
40-
private __id?: string;
4141

4242
/**
4343
* Create ObjectId from a number.
@@ -113,7 +113,7 @@ export class ObjectId extends BSONValue {
113113
this.buffer = ByteUtils.fromHex(workingId);
114114
// If we are caching the hex string
115115
if (ObjectId.cacheHexString) {
116-
this.__id = workingId;
116+
__idCache.set(this, workingId);
117117
}
118118
} else {
119119
throw new BSONError(
@@ -136,7 +136,7 @@ export class ObjectId extends BSONValue {
136136
set id(value: Uint8Array) {
137137
this.buffer = value;
138138
if (ObjectId.cacheHexString) {
139-
this.__id = ByteUtils.toHex(value);
139+
__idCache.set(this, ByteUtils.toHex(value));
140140
}
141141
}
142142

@@ -165,14 +165,15 @@ export class ObjectId extends BSONValue {
165165

166166
/** Returns the ObjectId id as a 24 lowercase character hex string representation */
167167
toHexString(): string {
168-
if (ObjectId.cacheHexString && this.__id) {
169-
return this.__id;
168+
if (ObjectId.cacheHexString) {
169+
const __id = __idCache.get(this);
170+
if (__id) return __id;
170171
}
171172

172173
const hexString = ByteUtils.toHex(this.id);
173174

174-
if (ObjectId.cacheHexString && !this.__id) {
175-
this.__id = hexString;
175+
if (ObjectId.cacheHexString) {
176+
__idCache.set(this, hexString);
176177
}
177178

178179
return hexString;
@@ -370,6 +371,11 @@ export class ObjectId extends BSONValue {
370371
return new ObjectId(doc.$oid);
371372
}
372373

374+
/** @internal */
375+
private isCached(): boolean {
376+
return ObjectId.cacheHexString && __idCache.has(this);
377+
}
378+
373379
/**
374380
* Converts to a string representation of this Id.
375381
*

test/node/bson_test.js

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,41 +1573,55 @@ describe('BSON', function () {
15731573
*/
15741574
it('ObjectId should have a correct cached representation of the hexString', function (done) {
15751575
ObjectId.cacheHexString = true;
1576+
// generated ObjectID uses lazy caching
15761577
var a = new ObjectId();
1578+
expect(a.isCached()).to.be.false;
15771579
a.toHexString();
1578-
var __id = a.__id;
1579-
expect(__id).to.equal(a.toHexString());
1580+
expect(a.isCached()).to.be.true;
1581+
expect(a.toHexString()).to.equal(a.toHexString());
15801582

1581-
// hexString
1582-
a = new ObjectId(__id);
1583+
// hexString caches immediately
1584+
a = new ObjectId(a.toHexString());
1585+
expect(a.isCached()).to.be.true;
15831586
a.toHexString();
1584-
expect(__id).to.equal(a.toHexString());
1587+
expect(a.isCached()).to.be.true;
1588+
expect(a.toHexString()).to.equal(a.toHexString());
15851589

15861590
// fromHexString
1587-
a = ObjectId.createFromHexString(__id);
1591+
a = ObjectId.createFromHexString(a.toHexString());
1592+
expect(a.isCached()).to.be.false;
15881593
a.toHexString();
1589-
expect(a.__id).to.equal(a.toHexString());
1590-
expect(__id).to.equal(a.toHexString());
1594+
expect(a.isCached()).to.be.true;
1595+
expect(a.toHexString()).to.equal(a.toHexString());
15911596

15921597
// number
15931598
var genTime = a.generationTime;
15941599
a = new ObjectId(genTime);
1600+
expect(a.isCached()).to.be.false;
15951601
a.toHexString();
1596-
__id = a.__id;
1597-
expect(__id).to.equal(a.toHexString());
1602+
expect(a.isCached()).to.be.true;
1603+
expect(a.toHexString()).to.equal(a.toHexString());
15981604

15991605
// generationTime
1600-
delete a.__id;
16011606
a.generationTime = genTime;
1602-
expect(__id).to.equal(a.toHexString());
1607+
expect(a.isCached()).to.be.true;
1608+
expect(a.toHexString()).to.equal(a.toHexString());
16031609

16041610
// createFromTime
16051611
a = ObjectId.createFromTime(genTime);
1612+
expect(a.isCached()).to.be.false;
16061613
a.toHexString();
1607-
__id = a.__id;
1608-
expect(__id).to.equal(a.toHexString());
1614+
expect(a.isCached()).to.be.true;
1615+
expect(a.toHexString()).to.equal(a.toHexString());
1616+
16091617
ObjectId.cacheHexString = false;
16101618

1619+
// No longer caches after cache is disabled
1620+
a = new ObjectId();
1621+
expect(a.isCached()).to.be.false;
1622+
a.toHexString();
1623+
expect(a.isCached()).to.be.false;
1624+
16111625
done();
16121626
});
16131627

@@ -1792,7 +1806,7 @@ describe('BSON', function () {
17921806
);
17931807
expect(inspect(code)).to.equal(
17941808
/* eslint-disable */
1795-
`new Code(
1809+
`new Code(
17961810
'function iLoveJavaScript() {\\n' +
17971811
' do {\\n' +
17981812
" console.log('hello!');\\n" +

0 commit comments

Comments
 (0)