From 492fd86badb3e80a4fae406131039957597d45a2 Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Tue, 31 Mar 2026 16:46:31 +0800 Subject: [PATCH] Expand the lifetime of the XHR reference We need to take the self-reference to the XHR object as soon as the request is made. Previously, we were waiting until we got the start callback, but v8 could (and does) drop the reference before that happens. Unfortunately, that means we can no longer use _transfer == null to tell if we own a reference or not, so a new boolean was added. --- src/browser/webapi/net/XMLHttpRequest.zig | 16 +++++++++++++--- src/lightpanda.zig | 4 ++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/browser/webapi/net/XMLHttpRequest.zig b/src/browser/webapi/net/XMLHttpRequest.zig index 22587347..1572ebad 100644 --- a/src/browser/webapi/net/XMLHttpRequest.zig +++ b/src/browser/webapi/net/XMLHttpRequest.zig @@ -44,6 +44,7 @@ _page: *Page, _proto: *XMLHttpRequestEventTarget, _arena: Allocator, _transfer: ?*HttpClient.Transfer = null, +_has_ref: bool = false, _url: [:0]const u8 = "", _method: net_http.Method = .GET, @@ -136,6 +137,14 @@ pub fn deinit(self: *XMLHttpRequest, session: *Session) void { session.releaseArena(self._arena); } +fn releaseSelfRef(self: *XMLHttpRequest) void { + if (self._has_ref == false) { + return; + } + self.releaseRef(self._page._session); + self._has_ref = false; +} + pub fn releaseRef(self: *XMLHttpRequest, session: *Session) void { self._rc.release(self, session); } @@ -252,6 +261,8 @@ pub fn send(self: *XMLHttpRequest, body_: ?[]const u8) !void { .error_callback = httpErrorCallback, .shutdown_callback = httpShutdownCallback, }); + self.acquireRef(); + self._has_ref = true; } fn handleBlobUrl(self: *XMLHttpRequest, page: *Page) !void { @@ -393,7 +404,6 @@ fn httpStartCallback(transfer: *HttpClient.Transfer) !void { log.debug(.http, "request start", .{ .method = self._method, .url = self._url, .source = "xhr" }); } self._transfer = transfer; - self.acquireRef(); } fn httpHeaderCallback(transfer: *HttpClient.Transfer, header: net_http.Header) !void { @@ -501,8 +511,8 @@ fn httpErrorCallback(ctx: *anyopaque, err: anyerror) void { self.handleError(err); if (self._transfer != null) { self._transfer = null; - self.releaseRef(self._page._session); } + self.releaseSelfRef(); } fn httpShutdownCallback(ctx: *anyopaque) void { @@ -515,8 +525,8 @@ pub fn abort(self: *XMLHttpRequest) void { if (self._transfer) |transfer| { self._transfer = null; transfer.abort(error.Abort); - self.releaseRef(self._page._session); } + self.releaseSelfRef(); } fn handleError(self: *XMLHttpRequest, err: anyerror) void { diff --git a/src/lightpanda.zig b/src/lightpanda.zig index 36213624..7f202855 100644 --- a/src/lightpanda.zig +++ b/src/lightpanda.zig @@ -237,6 +237,10 @@ pub fn RC(comptime T: type) type { session.releaseArena(kv.value.arena); } } + + pub fn format(self: @This(), writer: *std.Io.Writer) !void { + return writer.print("{d}", .{self._refs}); + } }; }