aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bun.js/api/bun/socket.zig20
-rw-r--r--src/bun.js/api/sockets.classes.ts1
-rw-r--r--src/bun.js/bindings/ZigGeneratedClasses.cpp12
-rw-r--r--src/bun.js/bindings/ZigGeneratedClasses.h54
-rw-r--r--src/bun.js/bindings/generated_classes.zig2
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" });