diff --git a/src/bun.js/api/bun/socket.zig b/src/bun.js/api/bun/socket.zig index 2bdb48f618..cdd0e87a7f 100644 --- a/src/bun.js/api/bun/socket.zig +++ b/src/bun.js/api/bun/socket.zig @@ -2860,6 +2860,13 @@ fn NewSocket(comptime ssl: bool) type { return JSC.JSValue.jsNumber(this.bytes_written + this.buffered_data_for_node_net.len); } + pub fn getBufferedAmount( + this: *This, + _: *JSC.JSGlobalObject, + ) JSValue { + return JSC.JSValue.jsNumber(this.buffered_data_for_node_net.len); + } + pub fn getALPNProtocol( this: *This, globalObject: *JSC.JSGlobalObject, diff --git a/src/bun.js/api/server/NodeHTTPResponse.zig b/src/bun.js/api/server/NodeHTTPResponse.zig index 61a4922271..6493968cc2 100644 --- a/src/bun.js/api/server/NodeHTTPResponse.zig +++ b/src/bun.js/api/server/NodeHTTPResponse.zig @@ -369,7 +369,7 @@ pub fn getHasBody(this: *const NodeHTTPResponse, _: *JSC.JSGlobalObject) JSC.JSV pub fn getBufferedAmount(this: *const NodeHTTPResponse, _: *JSC.JSGlobalObject) JSC.JSValue { if (this.flags.request_has_completed or this.flags.socket_closed) { - return JSC.JSValue.jsNull(); + return JSC.JSValue.jsNumber(0); } return JSC.JSValue.jsNumber(this.raw_response.getBufferedAmount()); diff --git a/src/bun.js/api/sockets.classes.ts b/src/bun.js/api/sockets.classes.ts index b85d79176e..3a9da06c06 100644 --- a/src/bun.js/api/sockets.classes.ts +++ b/src/bun.js/api/sockets.classes.ts @@ -91,6 +91,9 @@ function generate(ssl) { bytesWritten: { getter: "getBytesWritten", }, + bufferedAmount: { + getter: "getBufferedAmount", + }, setNoDelay: { fn: "setNoDelay", length: 1, diff --git a/src/js/node/http.ts b/src/js/node/http.ts index 1184c50ba5..53f4463224 100644 --- a/src/js/node/http.ts +++ b/src/js/node/http.ts @@ -379,14 +379,19 @@ const NodeHTTPServerSocket = class Socket extends Duplex { $isCallable(closeCallback) && closeCallback(); } - _onTimeout = function () { + _onTimeout() { const handle = this[kHandle]; const response = handle?.response; + // if there is a response, and it has pending data, + // we suppress the timeout because a write is in progress if (response && response.getBufferedAmount() > 0) { return; } this.emit("timeout"); - }; + } + _unrefTimer() { + // for compatibility + } address() { return this[kHandle]?.remoteAddress || null; diff --git a/src/js/node/net.ts b/src/js/node/net.ts index eee2eebcaf..9927d875ca 100644 --- a/src/js/node/net.ts +++ b/src/js/node/net.ts @@ -587,6 +587,22 @@ Socket.prototype.address = function address() { }; }; +Socket.prototype._onTimeout = function () { + // if there is pending data, write is in progress + // so we suppress the timeout + if (this._pendingData) { + return; + } + + const handle = this._handle; + // if there is a handle, and it has pending data, + // we suppress the timeout because a write is in progress + if (handle && handle.bufferedAmount > 0) { + return; + } + this.emit("timeout"); +}; + Object.defineProperty(Socket.prototype, "bufferSize", { get: function () { return this.writableLength;