Skip to content

Commit 212a7a6

Browse files
watsonsam-github
authored andcommitted
net: ensure net.connect calls Socket connect
It's important for people who monkey-patch `Socket.prototype.connect` that it's called by `net.connect` since it's not possible to monkey-patch `net.connect` directly (as the `connect` function is called directly by other parts of `lib/net.js` instead of calling the `exports.connect` function). Among the actors who monkey-patch `Socket.prototype.connect` are most APM vendors, the async-listener module and the continuation-local-storage module. Related: - #12342 - #12852 PR-URL: #12861 Reviewed-By: Sam Roberts <[email protected]> Reviewed-By: Luca Maraschi <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Jan Krems <[email protected]>
1 parent 65d6249 commit 212a7a6

File tree

2 files changed

+57
-14
lines changed

2 files changed

+57
-14
lines changed

lib/net.js

+18-14
Original file line numberDiff line numberDiff line change
@@ -87,15 +87,14 @@ function connect() {
8787
// TODO(joyeecheung): use destructuring when V8 is fast enough
8888
var normalized = normalizeArgs(args);
8989
var options = normalized[0];
90-
var cb = normalized[1];
9190
debug('createConnection', normalized);
9291
var socket = new Socket(options);
9392

9493
if (options.timeout) {
9594
socket.setTimeout(options.timeout);
9695
}
9796

98-
return realConnect.call(socket, options, cb);
97+
return Socket.prototype.connect.call(socket, normalized);
9998
}
10099

101100

@@ -915,18 +914,23 @@ function internalConnect(
915914

916915

917916
Socket.prototype.connect = function() {
918-
var args = new Array(arguments.length);
919-
for (var i = 0; i < arguments.length; i++)
920-
args[i] = arguments[i];
921-
// TODO(joyeecheung): use destructuring when V8 is fast enough
922-
var normalized = normalizeArgs(args);
923-
var options = normalized[0];
924-
var cb = normalized[1];
925-
return realConnect.call(this, options, cb);
926-
};
927-
917+
let normalized;
918+
// If passed an array, it's treated as an array of arguments that have
919+
// already been normalized (so we don't normalize more than once). This has
920+
// been solved before in https://github.com/nodejs/node/pull/12342, but was
921+
// reverted as it had unintended side effects.
922+
if (arguments.length === 1 && Array.isArray(arguments[0])) {
923+
normalized = arguments[0];
924+
} else {
925+
var args = new Array(arguments.length);
926+
for (var i = 0; i < arguments.length; i++)
927+
args[i] = arguments[i];
928+
// TODO(joyeecheung): use destructuring when V8 is fast enough
929+
normalized = normalizeArgs(args);
930+
}
931+
const options = normalized[0];
932+
const cb = normalized[1];
928933

929-
function realConnect(options, cb) {
930934
if (this.write !== Socket.prototype.write)
931935
this.write = Socket.prototype.write;
932936

@@ -967,7 +971,7 @@ function realConnect(options, cb) {
967971
lookupAndConnect(this, options);
968972
}
969973
return this;
970-
}
974+
};
971975

972976

973977
function lookupAndConnect(self, options) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
'use strict';
2+
const common = require('../common');
3+
4+
// This test checks that calling `net.connect` internally calls
5+
// `Socket.prototype.connect`.
6+
//
7+
// This is important for people who monkey-patch `Socket.prototype.connect`
8+
// since it's not possible to monkey-patch `net.connect` directly (as the core
9+
// `connect` function is called internally in Node instead of calling the
10+
// `exports.connect` function).
11+
//
12+
// Monkey-patching of `Socket.prototype.connect` is done by - among others -
13+
// most APM vendors, the async-listener module and the
14+
// continuation-local-storage module.
15+
//
16+
// Related:
17+
// - https://github.com/nodejs/node/pull/12342
18+
// - https://github.com/nodejs/node/pull/12852
19+
20+
const net = require('net');
21+
const Socket = net.Socket;
22+
23+
// Monkey patch Socket.prototype.connect to check that it's called.
24+
const orig = Socket.prototype.connect;
25+
Socket.prototype.connect = common.mustCall(function() {
26+
return orig.apply(this, arguments);
27+
});
28+
29+
const server = net.createServer();
30+
31+
server.listen(common.mustCall(function() {
32+
const port = server.address().port;
33+
const client = net.connect({port}, common.mustCall(function() {
34+
client.end();
35+
}));
36+
client.on('end', common.mustCall(function() {
37+
server.close();
38+
}));
39+
}));

0 commit comments

Comments
 (0)