Compare commits

...

5 Commits

Author SHA1 Message Date
autofix-ci[bot]
82d5d9ac1f [autofix.ci] apply automated fixes 2025-10-02 20:14:41 +00:00
Meghan Denny
36c2789ed3 Merge branch 'main' into nektro-patch-43494 2025-10-02 12:12:02 -08:00
Meghan Denny
72ab873196 fix 2025-10-02 12:46:59 -07:00
Meghan Denny
45890cc0ff bring this back too 2025-09-26 23:10:57 -07:00
Meghan Denny
4e26400dfe node:net: address todo 2025-09-26 22:57:20 -07:00
6 changed files with 150 additions and 51 deletions

View File

@@ -207,7 +207,7 @@ pub fn NewSocket(comptime ssl: bool) type {
pub fn handleError(this: *This, err_value: jsc.JSValue) void {
log("handleError", .{});
const handlers = this.getHandlers();
const handlers = this.handlers.?;
var vm = handlers.vm;
if (vm.isShuttingDown()) {
return;
@@ -225,7 +225,7 @@ pub fn NewSocket(comptime ssl: bool) type {
jsc.markBinding(@src());
if (this.socket.isDetached()) return;
if (this.native_callback.onWritable()) return;
const handlers = this.getHandlers();
const handlers = this.handlers.?;
const callback = handlers.onWritable;
if (callback == .zero) return;
@@ -255,7 +255,7 @@ pub fn NewSocket(comptime ssl: bool) type {
pub fn onTimeout(this: *This, _: Socket) void {
jsc.markBinding(@src());
if (this.socket.isDetached()) return;
const handlers = this.getHandlers();
const handlers = this.handlers.?;
log("onTimeout {s}", .{if (handlers.is_server) "S" else "C"});
const callback = handlers.onTimeout;
if (callback == .zero or this.flags.finalizing) return;
@@ -275,12 +275,8 @@ pub fn NewSocket(comptime ssl: bool) type {
};
}
pub fn getHandlers(this: *const This) *Handlers {
return this.handlers orelse @panic("No handlers set on Socket");
}
pub fn handleConnectError(this: *This, errno: c_int) void {
const handlers = this.getHandlers();
const handlers = this.handlers.?;
log("onConnectError {s} ({d}, {d})", .{ if (handlers.is_server) "S" else "C", errno, this.ref_count.get() });
// Ensure the socket is still alive for any defer's we have
this.ref();
@@ -360,7 +356,7 @@ pub fn NewSocket(comptime ssl: bool) type {
pub fn markActive(this: *This) void {
if (!this.flags.is_active) {
this.getHandlers().markActive();
this.handlers.?.markActive();
this.flags.is_active = true;
this.has_pending_activity.store(true, .release);
}
@@ -388,7 +384,7 @@ pub fn NewSocket(comptime ssl: bool) type {
}
this.flags.is_active = false;
const handlers = this.getHandlers();
const handlers = this.handlers.?;
const vm = handlers.vm;
handlers.markInactive();
this.poll_ref.unref(vm);
@@ -397,7 +393,7 @@ pub fn NewSocket(comptime ssl: bool) type {
}
pub fn isServer(this: *const This) bool {
return this.getHandlers().is_server;
return this.handlers.?.is_server;
}
pub fn onOpen(this: *This, socket: Socket) void {
@@ -449,7 +445,7 @@ pub fn NewSocket(comptime ssl: bool) type {
}
}
const handlers = this.getHandlers();
const handlers = this.handlers.?;
const callback = handlers.onOpen;
const handshake_callback = handlers.onHandshake;
@@ -501,7 +497,7 @@ pub fn NewSocket(comptime ssl: bool) type {
pub fn onEnd(this: *This, _: Socket) void {
jsc.markBinding(@src());
if (this.socket.isDetached()) return;
const handlers = this.getHandlers();
const handlers = this.handlers.?;
log("onEnd {s}", .{if (handlers.is_server) "S" else "C"});
// Ensure the socket remains alive until this is finished
this.ref();
@@ -532,7 +528,7 @@ pub fn NewSocket(comptime ssl: bool) type {
jsc.markBinding(@src());
this.flags.handshake_complete = true;
if (this.socket.isDetached()) return;
const handlers = this.getHandlers();
const handlers = this.handlers.?;
log("onHandshake {s} ({d})", .{ if (handlers.is_server) "S" else "C", success });
const authorized = if (success == 1) true else false;
@@ -598,7 +594,7 @@ pub fn NewSocket(comptime ssl: bool) type {
pub fn onClose(this: *This, _: Socket, err: c_int, _: ?*anyopaque) void {
jsc.markBinding(@src());
const handlers = this.getHandlers();
const handlers = this.handlers.?;
log("onClose {s}", .{if (handlers.is_server) "S" else "C"});
this.detachNativeCallback();
this.socket.detach();
@@ -645,7 +641,7 @@ pub fn NewSocket(comptime ssl: bool) type {
pub fn onData(this: *This, _: Socket, data: []const u8) void {
jsc.markBinding(@src());
if (this.socket.isDetached()) return;
const handlers = this.getHandlers();
const handlers = this.handlers.?;
log("onData {s} ({d})", .{ if (handlers.is_server) "S" else "C", data.len });
if (this.native_callback.onData(data)) return;
@@ -687,7 +683,7 @@ pub fn NewSocket(comptime ssl: bool) type {
}
pub fn getListener(this: *This, _: *jsc.JSGlobalObject) JSValue {
const handlers = this.getHandlers();
const handlers = this.handlers orelse return .js_undefined;
if (!handlers.is_server or this.socket.isDetached()) {
return .js_undefined;
@@ -698,7 +694,7 @@ pub fn NewSocket(comptime ssl: bool) type {
}
pub fn getReadyState(this: *This, _: *jsc.JSGlobalObject) JSValue {
if (this.socket.isDetached()) {
if (this.socket.isDetached() or this.socket.socket == .untached) {
return JSValue.jsNumber(@as(i32, -1));
} else if (this.socket.isClosed()) {
return JSValue.jsNumber(@as(i32, 0));
@@ -882,9 +878,12 @@ pub fn NewSocket(comptime ssl: bool) type {
}
pub fn writeBuffered(this: *This, globalObject: *jsc.JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!JSValue {
if (this.socket.socket == .untached) {
this.buffered_data_for_node_net.clearAndFree(bun.default_allocator);
return .false;
}
if (this.socket.isDetached()) {
this.buffered_data_for_node_net.clearAndFree(bun.default_allocator);
// TODO: should we separate unattached and detached? unattached shouldn't throw here
const err: jsc.SystemError = .{
.errno = @intFromEnum(bun.sys.SystemErrno.EBADF),
.code = .static("EBADF"),
@@ -1356,7 +1355,7 @@ pub fn NewSocket(comptime ssl: bool) type {
return globalObject.throw("Expected \"socket\" option", .{});
};
var prev_handlers = this.getHandlers();
var prev_handlers = this.handlers.?;
const handlers = try Handlers.fromJS(globalObject, socket_obj, prev_handlers.is_server);
@@ -1536,7 +1535,7 @@ pub fn NewSocket(comptime ssl: bool) type {
var raw_handlers_ptr = bun.handleOom(bun.default_allocator.create(Handlers));
raw_handlers_ptr.* = blk: {
const this_handlers = this.getHandlers();
const this_handlers = this.handlers.?;
break :blk .{
.vm = vm,
.globalObject = globalObject,
@@ -1581,7 +1580,7 @@ pub fn NewSocket(comptime ssl: bool) type {
tls.markActive();
// we're unrefing the original instance and refing the TLS instance
tls.poll_ref.ref(this.getHandlers().vm);
tls.poll_ref.ref(this.handlers.?.vm);
// mark both instances on socket data
if (new_socket.ext(WrappedSocket)) |ctx| {
@@ -1593,7 +1592,7 @@ pub fn NewSocket(comptime ssl: bool) type {
this.flags.is_active = false;
// will free handlers when hits 0 active connections
// the connection can be upgraded inside a handler call so we need to guarantee that it will be still alive
this.getHandlers().markInactive();
this.handlers.?.markInactive();
this.has_pending_activity.store(false, .release);
}

View File

@@ -632,7 +632,7 @@ pub fn connectInner(globalObject: *jsc.JSGlobalObject, prev_maybe_tcp: ?*TCPSock
}
bun.assert(prev.this_value != .zero);
prev.handlers = handlers_ptr;
bun.assert(prev.socket.socket == .detached);
// bun.assert(prev.socket.socket == .untached);
prev.connection = connection;
prev.protos = if (protos) |p| bun.handleOom(bun.default_allocator.dupe(u8, p)) else null;
prev.server_name = server_name;
@@ -642,7 +642,7 @@ pub fn connectInner(globalObject: *jsc.JSGlobalObject, prev_maybe_tcp: ?*TCPSock
.ref_count = .init(),
.handlers = handlers_ptr,
.this_value = .zero,
.socket = TLSSocket.Socket.detached,
.socket = TLSSocket.Socket.untached,
.connection = connection,
.protos = if (protos) |p| bun.handleOom(bun.default_allocator.dupe(u8, p)) else null,
.server_name = server_name,
@@ -667,7 +667,7 @@ pub fn connectInner(globalObject: *jsc.JSGlobalObject, prev_maybe_tcp: ?*TCPSock
var tcp = if (prev_maybe_tcp) |prev| blk: {
bun.assert(prev.this_value != .zero);
prev.handlers = handlers_ptr;
bun.assert(prev.socket.socket == .detached);
// bun.assert(prev.socket.socket == .untached);
bun.assert(prev.connection == null);
bun.assert(prev.protos == null);
bun.assert(prev.server_name == null);
@@ -677,7 +677,7 @@ pub fn connectInner(globalObject: *jsc.JSGlobalObject, prev_maybe_tcp: ?*TCPSock
.ref_count = .init(),
.handlers = handlers_ptr,
.this_value = .zero,
.socket = TCPSocket.Socket.detached,
.socket = TCPSocket.Socket.untached,
.connection = null,
.protos = null,
.server_name = null,
@@ -754,7 +754,7 @@ pub fn connectInner(globalObject: *jsc.JSGlobalObject, prev_maybe_tcp: ?*TCPSock
const socket = if (maybe_previous) |prev| blk: {
bun.assert(prev.this_value != .zero);
prev.handlers = handlers_ptr;
bun.assert(prev.socket.socket == .detached);
// bun.assert(prev.socket.socket == .untached);
prev.connection = connection;
prev.protos = if (protos) |p| bun.handleOom(bun.default_allocator.dupe(u8, p)) else null;
prev.server_name = server_name;
@@ -764,7 +764,7 @@ pub fn connectInner(globalObject: *jsc.JSGlobalObject, prev_maybe_tcp: ?*TCPSock
.ref_count = .init(),
.handlers = handlers_ptr,
.this_value = .zero,
.socket = SocketType.Socket.detached,
.socket = SocketType.Socket.untached,
.connection = connection,
.protos = if (protos) |p| bun.handleOom(bun.default_allocator.dupe(u8, p)) else null,
.server_name = server_name,

View File

@@ -640,11 +640,11 @@ extern "C" napi_status napi_is_typedarray(napi_env env, napi_value value, bool*
// it doesn't copy the string
// but it's only safe to use if we are not setting a property
// because we can't guarantee the lifetime of it
#define PROPERTY_NAME_FROM_UTF8(identifierName) \
size_t utf8Len = strlen(utf8Name); \
#define PROPERTY_NAME_FROM_UTF8(identifierName) \
size_t utf8Len = strlen(utf8Name); \
WTF::String&& nameString = WTF::charactersAreAllASCII(std::span { reinterpret_cast<const Latin1Character*>(utf8Name), utf8Len }) \
? WTF::String(WTF::StringImpl::createWithoutCopying({ utf8Name, utf8Len })) \
: WTF::String::fromUTF8(utf8Name); \
? WTF::String(WTF::StringImpl::createWithoutCopying({ utf8Name, utf8Len })) \
: WTF::String::fromUTF8(utf8Name); \
const JSC::PropertyName identifierName = JSC::Identifier::fromString(vm, nameString);
extern "C" napi_status napi_has_named_property(napi_env env, napi_value object,

View File

@@ -76,7 +76,7 @@ pub fn newDetachedSocket(globalThis: *jsc.JSGlobalObject, callframe: *jsc.CallFr
if (!is_ssl) {
const socket = bun.api.TCPSocket.new(.{
.socket = .detached,
.socket = .untached,
.socket_context = null,
.ref_count = .init(),
.protos = null,
@@ -85,7 +85,7 @@ pub fn newDetachedSocket(globalThis: *jsc.JSGlobalObject, callframe: *jsc.CallFr
return socket.getThisValue(globalThis);
} else {
const socket = bun.api.TLSSocket.new(.{
.socket = .detached,
.socket = .untached,
.socket_context = null,
.ref_count = .init(),
.protos = null,

View File

@@ -7,6 +7,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
const ThisSocket = @This();
pub const detached: NewSocketHandler(is_ssl) = NewSocketHandler(is_ssl){ .socket = .{ .detached = {} } };
pub const untached: NewSocketHandler(is_ssl) = NewSocketHandler(is_ssl){ .socket = .untached };
pub fn setNoDelay(this: ThisSocket, enabled: bool) bool {
return this.socket.setNoDelay(enabled);
@@ -38,6 +39,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
pub fn getVerifyError(this: ThisSocket) uws.us_bun_verify_error_t {
switch (this.socket) {
.untached => return std.mem.zeroes(us_bun_verify_error_t),
.connected => |socket| return socket.getVerifyError(is_ssl),
.upgradedDuplex => |socket| return socket.sslError(),
.pipe => |pipe| if (Environment.isWindows) return pipe.sslError() else return std.mem.zeroes(us_bun_verify_error_t),
@@ -47,6 +49,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
pub fn isEstablished(this: ThisSocket) bool {
switch (this.socket) {
.untached => return false,
.connected => |socket| return socket.isEstablished(comptime is_ssl),
.upgradedDuplex => |socket| return socket.isEstablished(),
.pipe => |pipe| if (Environment.isWindows) return pipe.isEstablished() else return false,
@@ -56,6 +59,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
pub fn timeout(this: ThisSocket, seconds: c_uint) void {
switch (this.socket) {
.untached => {},
.upgradedDuplex => |socket| socket.setTimeout(seconds),
.pipe => |pipe| if (Environment.isWindows) pipe.setTimeout(seconds),
.connected => |socket| socket.setTimeout(is_ssl, seconds),
@@ -66,6 +70,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
pub fn setTimeout(this: ThisSocket, seconds: c_uint) void {
switch (this.socket) {
.untached => {},
.connected => |socket| {
if (seconds > 240) {
socket.setTimeout(is_ssl, 0);
@@ -92,6 +97,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
pub fn setTimeoutMinutes(this: ThisSocket, minutes: c_uint) void {
switch (this.socket) {
.untached => {},
.connected => |socket| {
socket.setTimeout(is_ssl, 0);
socket.setLongTimeout(is_ssl, minutes);
@@ -251,6 +257,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
pub fn getNativeHandle(this: ThisSocket) ?*NativeSocketHandleType(is_ssl) {
return @ptrCast(switch (this.socket) {
.untached => null,
.connected => |socket| socket.getNativeHandle(is_ssl),
.connecting => |socket| socket.getNativeHandle(is_ssl),
.detached => null,
@@ -287,6 +294,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
std.meta.alignment(ContextType);
const ptr = switch (this.socket) {
.untached => return null,
.connected => |sock| sock.ext(is_ssl),
.connecting => |sock| sock.ext(is_ssl),
.detached => return null,
@@ -300,6 +308,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
/// This can be null if the socket was closed.
pub fn context(this: ThisSocket) ?*SocketContext {
switch (this.socket) {
.untached => return null,
.connected => |socket| return socket.context(is_ssl),
.connecting => |socket| return socket.context(is_ssl),
.detached => return null,
@@ -313,7 +322,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
.upgradedDuplex => |socket| socket.flush(),
.pipe => |pipe| if (comptime Environment.isWindows) pipe.flush(),
.connected => |socket| socket.flush(is_ssl),
.connecting, .detached => return,
.untached, .connecting, .detached => return,
}
}
@@ -322,7 +331,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
.upgradedDuplex => |socket| socket.encodeAndWrite(data),
.pipe => |pipe| if (comptime Environment.isWindows) pipe.encodeAndWrite(data) else 0,
.connected => |socket| socket.write(is_ssl, data),
.connecting, .detached => 0,
.untached, .connecting, .detached => 0,
};
}
@@ -330,14 +339,14 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
return switch (this.socket) {
.upgradedDuplex, .pipe => this.write(data),
.connected => |socket| socket.writeFd(data, file_descriptor),
.connecting, .detached => 0,
.untached, .connecting, .detached => 0,
};
}
pub fn rawWrite(this: ThisSocket, data: []const u8) i32 {
return switch (this.socket) {
.connected => |socket| socket.rawWrite(is_ssl, data),
.connecting, .detached => 0,
.untached, .connecting, .detached => 0,
.upgradedDuplex => |socket| socket.rawWrite(data),
.pipe => |pipe| if (comptime Environment.isWindows) pipe.rawWrite(data) else 0,
};
@@ -345,6 +354,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
pub fn shutdown(this: ThisSocket) void {
switch (this.socket) {
.untached => {},
.connected => |socket| socket.shutdown(is_ssl),
.connecting => |socket| {
debug("us_connecting_socket_shutdown({d})", .{@intFromPtr(socket)});
@@ -358,6 +368,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
pub fn shutdownRead(this: ThisSocket) void {
switch (this.socket) {
.untached => {},
.connected => |socket| socket.shutdownRead(is_ssl),
.connecting => |socket| {
debug("us_connecting_socket_shutdown_read({d})", .{@intFromPtr(socket)});
@@ -371,6 +382,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
pub fn isShutdown(this: ThisSocket) bool {
return switch (this.socket) {
.untached => true,
.connected => |socket| socket.isShutdown(is_ssl),
.connecting => |socket| blk: {
debug("us_connecting_socket_is_shut_down({d})", .{@intFromPtr(socket)});
@@ -392,6 +404,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
pub fn getError(this: ThisSocket) i32 {
switch (this.socket) {
.untached => return 0,
.connected => |socket| {
debug("us_socket_get_error({d})", .{@intFromPtr(socket)});
return socket.getError(is_ssl);
@@ -421,14 +434,14 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
pub fn localPort(this: ThisSocket) i32 {
return switch (this.socket) {
.connected => |socket| socket.localPort(is_ssl),
.pipe, .upgradedDuplex, .connecting, .detached => 0,
.untached, .pipe, .upgradedDuplex, .connecting, .detached => 0,
};
}
pub fn remotePort(this: ThisSocket) i32 {
return switch (this.socket) {
.connected => |socket| socket.remotePort(is_ssl),
.pipe, .upgradedDuplex, .connecting, .detached => 0,
.untached, .pipe, .upgradedDuplex, .connecting, .detached => 0,
};
}
@@ -438,7 +451,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
.connected => |sock| sock.remoteAddress(is_ssl, buf) catch |e| {
bun.Output.panic("Failed to get socket's remote address: {s}", .{@errorName(e)});
},
.pipe, .upgradedDuplex, .connecting, .detached => null,
.untached, .pipe, .upgradedDuplex, .connecting, .detached => null,
};
}
@@ -454,7 +467,7 @@ pub fn NewSocketHandler(comptime is_ssl: bool) type {
.connected => |sock| sock.localAddress(is_ssl, buf) catch |e| {
bun.Output.panic("Failed to get socket's local address: {s}", .{@errorName(e)});
},
.pipe, .upgradedDuplex, .connecting, .detached => null,
.untached, .pipe, .upgradedDuplex, .connecting, .detached => null,
};
}
@@ -963,6 +976,7 @@ pub const SocketTCP = NewSocketHandler(false);
pub const SocketTLS = NewSocketHandler(true);
pub const InternalSocket = union(enum) {
untached: void,
connected: *us_socket_t,
connecting: *ConnectingSocket,
detached: void,
@@ -971,6 +985,7 @@ pub const InternalSocket = union(enum) {
pub fn pauseResume(this: InternalSocket, ssl: bool, pause: bool) bool {
switch (this) {
.untached => return true,
.detached => return true,
.connected => |socket| {
if (pause) socket.pause(ssl) else socket.@"resume"(ssl);
@@ -996,7 +1011,7 @@ pub const InternalSocket = union(enum) {
}
}
pub fn isDetached(this: InternalSocket) bool {
return this == .detached;
return this == .detached or this == .untached;
}
pub fn isNamedPipe(this: InternalSocket) bool {
return this == .pipe;
@@ -1006,7 +1021,7 @@ pub const InternalSocket = union(enum) {
}
pub fn setNoDelay(this: InternalSocket, enabled: bool) bool {
switch (this) {
.pipe, .upgradedDuplex, .connecting, .detached => return false,
.pipe, .upgradedDuplex, .connecting, .detached, .untached => return false,
.connected => |socket| {
// only supported by connected sockets
socket.setNodelay(enabled);
@@ -1016,7 +1031,7 @@ pub const InternalSocket = union(enum) {
}
pub fn setKeepAlive(this: InternalSocket, enabled: bool, delay: u32) bool {
switch (this) {
.pipe, .upgradedDuplex, .connecting, .detached => return false,
.pipe, .upgradedDuplex, .connecting, .detached, .untached => return false,
.connected => |socket| {
// only supported by connected sockets and can fail
return socket.setKeepalive(enabled, delay) == 0;
@@ -1025,6 +1040,7 @@ pub const InternalSocket = union(enum) {
}
pub fn close(this: InternalSocket, comptime is_ssl: bool, code: us_socket_t.CloseCode) void {
switch (this) {
.untached => {},
.detached => {},
.connected => |socket| {
socket.close(is_ssl, code);
@@ -1043,6 +1059,7 @@ pub const InternalSocket = union(enum) {
pub fn isClosed(this: InternalSocket, comptime is_ssl: bool) bool {
return switch (this) {
.untached => true,
.connected => |socket| socket.isClosed(is_ssl),
.connecting => |socket| socket.isClosed(is_ssl),
.detached => true,
@@ -1053,6 +1070,7 @@ pub const InternalSocket = union(enum) {
pub fn get(this: @This()) ?*us_socket_t {
return switch (this) {
.untached => null,
.connected => this.connected,
.connecting => null,
.detached => null,
@@ -1063,25 +1081,29 @@ pub const InternalSocket = union(enum) {
pub fn eq(this: @This(), other: @This()) bool {
return switch (this) {
.untached => switch (other) {
.untached => true,
.upgradedDuplex, .connected, .connecting, .pipe, .detached => false,
},
.connected => switch (other) {
.connected => this.connected == other.connected,
.upgradedDuplex, .connecting, .detached, .pipe => false,
.untached, .upgradedDuplex, .connecting, .detached, .pipe => false,
},
.connecting => switch (other) {
.upgradedDuplex, .connected, .detached, .pipe => false,
.untached, .upgradedDuplex, .connected, .detached, .pipe => false,
.connecting => this.connecting == other.connecting,
},
.detached => switch (other) {
.detached => true,
.upgradedDuplex, .connected, .connecting, .pipe => false,
.untached, .upgradedDuplex, .connected, .connecting, .pipe => false,
},
.upgradedDuplex => switch (other) {
.upgradedDuplex => this.upgradedDuplex == other.upgradedDuplex,
.connected, .connecting, .detached, .pipe => false,
.untached, .connected, .connecting, .detached, .pipe => false,
},
.pipe => switch (other) {
.pipe => if (Environment.isWindows) other.pipe == other.pipe else false,
.connected, .connecting, .detached, .upgradedDuplex => false,
.untached, .connected, .connecting, .detached, .upgradedDuplex => false,
},
};
}

View File

@@ -0,0 +1,78 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict';
require('../common');
const assert = require('assert');
const net = require('net');
let bytesRead = 0;
let bytesWritten = 0;
let count = 0;
const tcp = net.Server(function(s) {
console.log('tcp server connection');
// trigger old mode.
s.resume();
s.on('end', function() {
bytesRead += s.bytesRead;
console.log(`tcp socket disconnect #${count}`);
});
});
tcp.listen(0, function doTest() {
console.error('listening');
const socket = net.createConnection(this.address().port);
socket.on('connect', function() {
count++;
console.error('CLIENT connect #%d', count);
socket.write('foo', function() {
console.error('CLIENT: write cb');
socket.end('bar');
});
});
socket.on('finish', function() {
bytesWritten += socket.bytesWritten;
console.error('CLIENT end event #%d', count);
});
socket.on('close', function() {
console.error('CLIENT close event #%d', count);
console.log(`Bytes read: ${bytesRead}`);
console.log(`Bytes written: ${bytesWritten}`);
if (count < 2) {
console.error('RECONNECTING');
socket.connect(tcp.address().port);
} else {
tcp.close();
}
});
});
process.on('exit', function() {
assert.strictEqual(bytesRead, 12);
assert.strictEqual(bytesWritten, 12);
});