mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-02-04 06:23:45 +00:00
Add finalizer mode
When a type is finalized by V8, it's because it's fallen out of scope. When a type is finalized by Zig, it's because the Context is being shutdown. Those are two different environments and might require distinct cleanup logic. Specifically, a zig-initiated finalization needs to consider that the page and context are being shutdown. It isn't necessarily safe to execute JavaScript at this point, and thus, not safe to execute a callback (on_error, on_abort, ready_state_change, ...).
This commit is contained in:
@@ -92,11 +92,11 @@ pub fn Builder(comptime T: type) type {
|
||||
return entries;
|
||||
}
|
||||
|
||||
pub fn finalizer(comptime func: *const fn (self: *T) void) Finalizer {
|
||||
pub fn finalizer(comptime func: *const fn (self: *T, comptime shutdown: bool) void) Finalizer {
|
||||
return .{
|
||||
.from_zig = struct {
|
||||
fn wrap(ptr: *anyopaque) void {
|
||||
func(@ptrCast(@alignCast(ptr)));
|
||||
func(@ptrCast(@alignCast(ptr)), true);
|
||||
}
|
||||
}.wrap,
|
||||
|
||||
@@ -115,7 +115,7 @@ pub fn Builder(comptime T: type) type {
|
||||
if (!ctx.identity_map.contains(@intFromPtr(ptr))) {
|
||||
return;
|
||||
}
|
||||
func(self);
|
||||
func(self, false);
|
||||
ctx.release(ptr);
|
||||
}
|
||||
}.wrap,
|
||||
|
||||
@@ -90,9 +90,13 @@ pub fn init(page: *Page) !*XMLHttpRequest {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn deinit(self: *XMLHttpRequest) void {
|
||||
pub fn deinit(self: *XMLHttpRequest, comptime shutdown: bool) void {
|
||||
if (self._transfer) |transfer| {
|
||||
transfer.terminate();
|
||||
if (shutdown) {
|
||||
transfer.terminate();
|
||||
} else {
|
||||
transfer.abort(error.Abort);
|
||||
}
|
||||
self._transfer = null;
|
||||
}
|
||||
self._page.releaseArena(self._arena);
|
||||
|
||||
@@ -371,7 +371,7 @@ fn makeTransfer(self: *Client, req: Request) !*Transfer {
|
||||
return transfer;
|
||||
}
|
||||
|
||||
fn requestFailed(self: *Client, transfer: *Transfer, err: anyerror) void {
|
||||
fn requestFailed(self: *Client, transfer: *Transfer, err: anyerror, comptime execute_callback: bool) void {
|
||||
// this shouldn't happen, we'll crash in debug mode. But in release, we'll
|
||||
// just noop this state.
|
||||
if (comptime IS_DEBUG) {
|
||||
@@ -390,7 +390,9 @@ fn requestFailed(self: *Client, transfer: *Transfer, err: anyerror) void {
|
||||
});
|
||||
}
|
||||
|
||||
transfer.req.error_callback(transfer.ctx, err);
|
||||
if (execute_callback) {
|
||||
transfer.req.error_callback(transfer.ctx, err);
|
||||
}
|
||||
}
|
||||
|
||||
// Restrictive since it'll only work if there are no inflight requests. In some
|
||||
@@ -600,7 +602,7 @@ fn processMessages(self: *Client) !bool {
|
||||
if (!transfer._header_done_called) {
|
||||
const proceed = transfer.headerDoneCallback(easy) catch |err| {
|
||||
log.err(.http, "header_done_callback", .{ .err = err });
|
||||
self.requestFailed(transfer, err);
|
||||
self.requestFailed(transfer, err, true);
|
||||
continue;
|
||||
};
|
||||
if (!proceed) {
|
||||
@@ -611,7 +613,7 @@ fn processMessages(self: *Client) !bool {
|
||||
transfer.req.done_callback(transfer.ctx) catch |err| {
|
||||
// transfer isn't valid at this point, don't use it.
|
||||
log.err(.http, "done_callback", .{ .err = err });
|
||||
self.requestFailed(transfer, err);
|
||||
self.requestFailed(transfer, err, true);
|
||||
continue;
|
||||
};
|
||||
|
||||
@@ -622,7 +624,7 @@ fn processMessages(self: *Client) !bool {
|
||||
}
|
||||
processed = true;
|
||||
} else |err| {
|
||||
self.requestFailed(transfer, err);
|
||||
self.requestFailed(transfer, err, true);
|
||||
}
|
||||
}
|
||||
return processed;
|
||||
@@ -972,7 +974,7 @@ pub const Transfer = struct {
|
||||
}
|
||||
|
||||
pub fn abort(self: *Transfer, err: anyerror) void {
|
||||
self.client.requestFailed(self, err);
|
||||
self.client.requestFailed(self, err, true);
|
||||
if (self._handle != null) {
|
||||
self.client.endTransfer(self);
|
||||
}
|
||||
@@ -980,6 +982,7 @@ pub const Transfer = struct {
|
||||
}
|
||||
|
||||
pub fn terminate(self: *Transfer) void {
|
||||
self.client.requestFailed(self, error.Shutdown, false);
|
||||
if (self._handle != null) {
|
||||
self.client.endTransfer(self);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user