Skip to content

Commit 4501a1c

Browse files
authored
fix(NODE-4281): ensure that the driver always uses Node.js timers (#3275)
Ensure that the driver always uses the Node.js timers API, rather than the global one, in case they diverge. This affects Compass, where the `setTimeout(...).unref()` usage currently results in uncaught exceptions because `setTimeout()` returns a number in browsers. This change adds `import ... from 'timers';` where necessary and adds a linter rule to prevent regressions. If this is not an acceptable solution, we can go back to the drawing board, but this seems like a good solution that doesn’t add too much overhead when writing driver code.
1 parent 47adfb3 commit 4501a1c

30 files changed

+79
-1
lines changed

.eslintrc.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,21 @@
3838
"property": "only"
3939
}
4040
],
41+
"no-restricted-globals": [
42+
"error",
43+
{
44+
"name": "setTimeout",
45+
"message": "Use `import { setTimeout } from 'timers';` instead"
46+
},
47+
{
48+
"name": "setImmediate",
49+
"message": "Use `import { setImmediate } from 'timers';` instead"
50+
},
51+
{
52+
"name": "setInterval",
53+
"message": "Use `import { setInterval } from 'timers';` instead"
54+
}
55+
],
4156
"prettier/prettier": "error",
4257
"tsdoc/syntax": "warn",
4358
"no-console": "error",

src/change_stream.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Denque = require('denque');
22
import type { Readable } from 'stream';
3+
import { setTimeout } from 'timers';
34

45
import type { Document, Long, Timestamp } from './bson';
56
import { Collection } from './collection';

src/cmap/connection.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { setTimeout } from 'timers';
2+
13
import { BSONSerializeOptions, Document, Long, ObjectId, pluckBSONSerializeOptions } from '../bson';
24
import {
35
CLOSE,

src/cmap/connection_pool.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import Denque = require('denque');
2+
import { setTimeout } from 'timers';
3+
24
import type { ObjectId } from '../bson';
35
import {
46
APM_EVENTS,

src/sdam/monitor.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { setTimeout } from 'timers';
2+
13
import { Document, Long } from '../bson';
24
import { connect } from '../cmap/connect';
35
import { Connection, ConnectionOptions } from '../cmap/connection';

src/sdam/srv_polling.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as dns from 'dns';
2+
import { setTimeout } from 'timers';
23

34
import { MongoRuntimeError } from '../error';
45
import { Logger, LoggerOptions } from '../logger';

src/sdam/topology.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import Denque = require('denque');
2+
import { setTimeout } from 'timers';
3+
24
import type { BSONSerializeOptions, Document } from '../bson';
35
import { deserialize, serialize } from '../bson';
46
import type { MongoCredentials } from '../cmap/auth/mongo_credentials';

src/utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as crypto from 'crypto';
22
import type { SrvRecord } from 'dns';
33
import * as os from 'os';
4+
import { setTimeout } from 'timers';
45
import { URL } from 'url';
56

67
import { Document, ObjectId, resolveBSONOptions } from './bson';

test/integration/change-streams/change_stream.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { strict as assert } from 'assert';
22
import { expect } from 'chai';
33
import { on, once } from 'events';
44
import { PassThrough } from 'stream';
5+
import { setTimeout } from 'timers';
56
import { promisify } from 'util';
67

78
import {

test/integration/change-streams/change_streams.prose.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { expect } from 'chai';
22
import * as sinon from 'sinon';
3+
import { setTimeout } from 'timers';
34

45
import {
56
ChangeStream,

0 commit comments

Comments
 (0)