diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/bun.js/api/bun/socket.zig | 20 | ||||
| -rw-r--r-- | src/bun.js/api/sockets.classes.ts | 1 | ||||
| -rw-r--r-- | src/bun.js/bindings/ZigGeneratedClasses.cpp | 12 | ||||
| -rw-r--r-- | src/bun.js/bindings/ZigGeneratedClasses.h | 54 | ||||
| -rw-r--r-- | src/bun.js/bindings/generated_classes.zig | 2 |
5 files changed, 81 insertions, 8 deletions
diff --git a/src/bun.js/api/bun/socket.zig b/src/bun.js/api/bun/socket.zig index 5bc1629c0..ccf265202 100644 --- a/src/bun.js/api/bun/socket.zig +++ b/src/bun.js/api/bun/socket.zig @@ -774,12 +774,18 @@ fn NewSocket(comptime ssl: bool) type { poll_ref: JSC.PollRef = JSC.PollRef.init(), reffer: JSC.Ref = JSC.Ref.init(), last_4: [4]u8 = .{ 0, 0, 0, 0 }, + has_pending_activity: std.atomic.Atomic(bool) = std.atomic.Atomic(bool).init(true), const This = @This(); const log = Output.scoped(.Socket, false); pub usingnamespace JSSocketType(ssl); + pub fn hasPendingActivity(this: *This) callconv(.C) bool { + @fence(.Acquire); + return this.has_pending_activity.load(.Acquire); + } + pub fn doConnect(this: *This, connection: Listener.UnixOrHost, socket_ctx: *uws.SocketContext) !void { switch (connection) { .host => |c| { @@ -874,13 +880,13 @@ fn NewSocket(comptime ssl: bool) type { _ = handlers.rejectPromise(err.toErrorInstance(handlers.globalObject)); this.reffer.unref(handlers.vm); handlers.markInactive(ssl, socket.context()); - this.finalize(); } pub fn markActive(this: *This) void { if (!this.reffer.has) { this.handlers.markActive(); this.reffer.ref(this.handlers.vm); + this.has_pending_activity.store(true, .Release); } } @@ -897,10 +903,7 @@ fn NewSocket(comptime ssl: bool) type { this.handlers.markInactive(ssl, this.socket.context()); this.poll_ref.unref(vm); - } - - if (this.this_value != .zero) { - this.this_value.unprotect(); + this.has_pending_activity.store(false, .Release); } } @@ -954,8 +957,8 @@ fn NewSocket(comptime ssl: bool) type { pub fn getThisValue(this: *This, globalObject: *JSC.JSGlobalObject) JSValue { if (this.this_value == .zero) { const value = this.toJS(globalObject); + value.ensureStillAlive(); this.this_value = value; - value.protect(); return value; } @@ -1346,9 +1349,9 @@ fn NewSocket(comptime ssl: bool) type { if (!this.socket.isClosed()) this.socket.flush(); this.detached = true; - this.markInactive(); if (!this.socket.isClosed()) this.socket.close(0, null); + this.markInactive(); } return JSValue.jsUndefined(); @@ -1364,9 +1367,10 @@ fn NewSocket(comptime ssl: bool) type { if (result != .zero and result.toInt32() > 0) { this.socket.flush(); this.detached = true; - this.markInactive(); + if (!this.socket.isClosed()) this.socket.close(0, null); + this.markInactive(); } return result; diff --git a/src/bun.js/api/sockets.classes.ts b/src/bun.js/api/sockets.classes.ts index 0c72d1d8d..105c6f748 100644 --- a/src/bun.js/api/sockets.classes.ts +++ b/src/bun.js/api/sockets.classes.ts @@ -4,6 +4,7 @@ function generate(ssl) { return define({ name: ssl ? "TCPSocket" : "TLSSocket", JSType: "0b11101110", + hasPendingActivity: true, proto: { write: { fn: "write", diff --git a/src/bun.js/bindings/ZigGeneratedClasses.cpp b/src/bun.js/bindings/ZigGeneratedClasses.cpp index 5618245cf..926bca81c 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses.cpp +++ b/src/bun.js/bindings/ZigGeneratedClasses.cpp @@ -488,6 +488,12 @@ extern "C" EncodedJSValue TCPSocket__getConstructor(Zig::GlobalObject* globalObj return JSValue::encode(globalObject->JSTCPSocketConstructor()); } +extern "C" bool TCPSocket__hasPendingActivity(void* ptr); +bool JSTCPSocket::internalHasPendingActivity() +{ + return TCPSocket__hasPendingActivity(m_ctx); +} + JSTCPSocket::~JSTCPSocket() { if (m_ctx) { @@ -1033,6 +1039,12 @@ extern "C" EncodedJSValue TLSSocket__getConstructor(Zig::GlobalObject* globalObj return JSValue::encode(globalObject->JSTLSSocketConstructor()); } +extern "C" bool TLSSocket__hasPendingActivity(void* ptr); +bool JSTLSSocket::internalHasPendingActivity() +{ + return TLSSocket__hasPendingActivity(m_ctx); +} + JSTLSSocket::~JSTLSSocket() { if (m_ctx) { diff --git a/src/bun.js/bindings/ZigGeneratedClasses.h b/src/bun.js/bindings/ZigGeneratedClasses.h index 69907386c..e94b33335 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses.h +++ b/src/bun.js/bindings/ZigGeneratedClasses.h @@ -60,10 +60,37 @@ public: : Base(vm, structure) { m_ctx = sinkPtr; + m_weakThis = JSC::Weak<JSTCPSocket>(this, getOwner()); } void finishCreation(JSC::VM&); + JSC::Weak<JSTCPSocket> m_weakThis; + bool internalHasPendingActivity(); + bool hasPendingActivity() + { + if (UNLIKELY(!m_ctx)) + return false; + + return this->internalHasPendingActivity(); + } + + class Owner final : public JSC::WeakHandleOwner { + public: + bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, JSC::AbstractSlotVisitor&, const char**) final + { + auto* controller = JSC::jsCast<JSTCPSocket*>(handle.slot()->asCell()); + return controller->hasPendingActivity(); + } + void finalize(JSC::Handle<JSC::Unknown>, void* context) final {} + }; + + static JSC::WeakHandleOwner* getOwner() + { + static NeverDestroyed<Owner> m_owner; + return &m_owner.get(); + } + DECLARE_VISIT_CHILDREN; mutable JSC::WriteBarrier<JSC::Unknown> m_data; @@ -115,10 +142,37 @@ public: : Base(vm, structure) { m_ctx = sinkPtr; + m_weakThis = JSC::Weak<JSTLSSocket>(this, getOwner()); } void finishCreation(JSC::VM&); + JSC::Weak<JSTLSSocket> m_weakThis; + bool internalHasPendingActivity(); + bool hasPendingActivity() + { + if (UNLIKELY(!m_ctx)) + return false; + + return this->internalHasPendingActivity(); + } + + class Owner final : public JSC::WeakHandleOwner { + public: + bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, JSC::AbstractSlotVisitor&, const char**) final + { + auto* controller = JSC::jsCast<JSTLSSocket*>(handle.slot()->asCell()); + return controller->hasPendingActivity(); + } + void finalize(JSC::Handle<JSC::Unknown>, void* context) final {} + }; + + static JSC::WeakHandleOwner* getOwner() + { + static NeverDestroyed<Owner> m_owner; + return &m_owner.get(); + } + DECLARE_VISIT_CHILDREN; mutable JSC::WriteBarrier<JSC::Unknown> m_data; diff --git a/src/bun.js/bindings/generated_classes.zig b/src/bun.js/bindings/generated_classes.zig index 1d323d942..7ed127ee5 100644 --- a/src/bun.js/bindings/generated_classes.zig +++ b/src/bun.js/bindings/generated_classes.zig @@ -156,6 +156,7 @@ pub const JSTCPSocket = struct { @export(TCPSocket.getLocalPort, .{ .name = "TCPSocketPrototype__getLocalPort" }); @export(TCPSocket.getReadyState, .{ .name = "TCPSocketPrototype__getReadyState" }); @export(TCPSocket.getRemoteAddress, .{ .name = "TCPSocketPrototype__getRemoteAddress" }); + @export(TCPSocket.hasPendingActivity, .{ .name = "TCPSocket__hasPendingActivity" }); @export(TCPSocket.ref, .{ .name = "TCPSocketPrototype__ref" }); @export(TCPSocket.reload, .{ .name = "TCPSocketPrototype__reload" }); @export(TCPSocket.setData, .{ .name = "TCPSocketPrototype__setData" }); @@ -315,6 +316,7 @@ pub const JSTLSSocket = struct { @export(TLSSocket.getLocalPort, .{ .name = "TLSSocketPrototype__getLocalPort" }); @export(TLSSocket.getReadyState, .{ .name = "TLSSocketPrototype__getReadyState" }); @export(TLSSocket.getRemoteAddress, .{ .name = "TLSSocketPrototype__getRemoteAddress" }); + @export(TLSSocket.hasPendingActivity, .{ .name = "TLSSocket__hasPendingActivity" }); @export(TLSSocket.ref, .{ .name = "TLSSocketPrototype__ref" }); @export(TLSSocket.reload, .{ .name = "TLSSocketPrototype__reload" }); @export(TLSSocket.setData, .{ .name = "TLSSocketPrototype__setData" }); |
