Skip to content

Commit 1d0b2b4

Browse files
nbbeekendurran
andauthored
test(NODE-6692): check that event emitters have error listeners (#4382)
Co-authored-by: Durran Jordan <[email protected]>
1 parent 6c81d4e commit 1d0b2b4

29 files changed

+129
-90
lines changed

.eslintrc.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@
119119
{
120120
"selector": "BinaryExpression[operator=/[=!]==?/] Literal[value='undefined']",
121121
"message": "Do not strictly check typeof undefined (NOTE: currently this rule only detects the usage of 'undefined' string literal so this could be a misfire)"
122+
},
123+
{
124+
"selector": "CallExpression[callee.property.name='removeAllListeners'][arguments.length=0]",
125+
"message": "removeAllListeners can remove error listeners leading to uncaught errors"
122126
}
123127
],
124128
"@typescript-eslint/no-unused-vars": "error",

.mocharc.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"source-map-support/register",
55
"ts-node/register",
66
"test/tools/runner/chai_addons.ts",
7-
"test/tools/runner/hooks/unhandled_checker.ts"
7+
"test/tools/runner/ee_checker.ts"
88
],
99
"extension": [
1010
"js",

src/change_stream.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -951,12 +951,10 @@ export class ChangeStream<
951951

952952
/** @internal */
953953
private _endStream(): void {
954-
const cursorStream = this.cursorStream;
955-
if (cursorStream) {
956-
['data', 'close', 'end', 'error'].forEach(event => cursorStream.removeAllListeners(event));
957-
cursorStream.destroy();
958-
}
959-
954+
this.cursorStream?.removeAllListeners('data');
955+
this.cursorStream?.removeAllListeners('close');
956+
this.cursorStream?.removeAllListeners('end');
957+
this.cursorStream?.destroy();
960958
this.cursorStream = undefined;
961959
}
962960

src/client-side-encryption/state_machine.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,6 @@ export class StateMachine {
344344
function destroySockets() {
345345
for (const sock of [socket, netSocket]) {
346346
if (sock) {
347-
sock.removeAllListeners();
348347
sock.destroy();
349348
}
350349
}

src/cmap/connect.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,6 @@ export async function makeSocket(options: MakeConnectionOptions): Promise<Stream
427427
throw error;
428428
} finally {
429429
socket.setTimeout(0);
430-
socket.removeAllListeners();
431430
if (cancellationHandler != null) {
432431
options.cancellationToken?.removeListener('cancel', cancellationHandler);
433432
}

src/cmap/connection.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import {
4646
HostAddress,
4747
maxWireVersion,
4848
type MongoDBNamespace,
49+
noop,
4950
now,
5051
once,
5152
squashError,
@@ -229,6 +230,7 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
229230

230231
constructor(stream: Stream, options: ConnectionOptions) {
231232
super();
233+
this.on('error', noop);
232234

233235
this.socket = stream;
234236
this.id = options.id;

src/cmap/connection_pool.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {
3434
kDispose,
3535
List,
3636
makeCounter,
37+
noop,
3738
now,
3839
promiseWithResolvers
3940
} from '../utils';
@@ -200,6 +201,7 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
200201

201202
constructor(server: Server, options: ConnectionPoolOptions) {
202203
super();
204+
this.on('error', noop);
203205

204206
this.options = Object.freeze({
205207
connectionType: Connection,

src/cursor/abstract_cursor.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
type Disposable,
2828
kDispose,
2929
type MongoDBNamespace,
30+
noop,
3031
squashError
3132
} from '../utils';
3233

@@ -267,6 +268,7 @@ export abstract class AbstractCursor<
267268
options: AbstractCursorOptions & Abortable = {}
268269
) {
269270
super();
271+
this.on('error', noop);
270272

271273
if (!client.s.isMongoClient) {
272274
throw new MongoRuntimeError('Cursor must be constructed with MongoClient');

src/gridfs/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { type Filter, TypedEventEmitter } from '../mongo_types';
77
import type { ReadPreference } from '../read_preference';
88
import type { Sort } from '../sort';
99
import { CSOTTimeoutContext } from '../timeout';
10-
import { resolveOptions } from '../utils';
10+
import { noop, resolveOptions } from '../utils';
1111
import { WriteConcern, type WriteConcernOptions } from '../write_concern';
1212
import type { FindOptions } from './../operations/find';
1313
import {
@@ -87,6 +87,7 @@ export class GridFSBucket extends TypedEventEmitter<GridFSBucketEvents> {
8787

8888
constructor(db: Db, options?: GridFSBucketOptions) {
8989
super();
90+
this.on('error', noop);
9091
this.setMaxListeners(0);
9192
const privateOptions = resolveOptions(db, {
9293
...DEFAULT_GRIDFS_BUCKET_OPTIONS,

src/mongo_client.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import {
5757
hostMatchesWildcards,
5858
isHostMatch,
5959
type MongoDBNamespace,
60+
noop,
6061
ns,
6162
resolveOptions,
6263
squashError
@@ -381,6 +382,7 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
381382

382383
constructor(url: string, options?: MongoClientOptions) {
383384
super();
385+
this.on('error', noop);
384386

385387
this.options = parseOptions(url, this, options);
386388

0 commit comments

Comments
 (0)