mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-21 20:24:42 +00:00
Protect against transfer.abort() being called during callback
This was already handled in most cases, but not for a body-less response. It's safe to call transfer.abort() during a callback, so long as the performing flag is set to true. This was set during the normal libcurl callbacks, but for a body-less response, we manually invoke the header_done_callback and were not setting the performing flag.
This commit is contained in:
@@ -252,3 +252,34 @@
|
||||
testing.expectEqual(XMLHttpRequest.UNSENT, req.readyState);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<script id=xhr_abort_callback_nobody>
|
||||
testing.async(async (restore) => {
|
||||
const req = new XMLHttpRequest();
|
||||
let abortFired = false;
|
||||
let errorFired = false;
|
||||
let loadEndFired = false;
|
||||
|
||||
await new Promise((resolve) => {
|
||||
req.onabort = () => { abortFired = true; };
|
||||
req.onerror = () => { errorFired = true; };
|
||||
req.onloadend = () => {
|
||||
loadEndFired = true;
|
||||
resolve();
|
||||
};
|
||||
|
||||
req.open('GET', 'http://127.0.0.1:9582/xhr_empty');
|
||||
req.onreadystatechange = (e) => {
|
||||
req.abort();
|
||||
}
|
||||
req.send();
|
||||
});
|
||||
|
||||
restore();
|
||||
testing.expectEqual(true, abortFired);
|
||||
testing.expectEqual(true, errorFired);
|
||||
testing.expectEqual(true, loadEndFired);
|
||||
testing.expectEqual(XMLHttpRequest.UNSENT, req.readyState);
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -789,25 +789,30 @@ fn processMessages(self: *Client) !bool {
|
||||
if (msg.err) |err| {
|
||||
requestFailed(transfer, err, true);
|
||||
} else blk: {
|
||||
// In case of request w/o data, we need to call the header done
|
||||
// callback now.
|
||||
if (!transfer._header_done_called) {
|
||||
const proceed = transfer.headerDoneCallback(&msg.conn) catch |err| {
|
||||
log.err(.http, "header_done_callback", .{ .err = err });
|
||||
{
|
||||
self.handles.performing = true;
|
||||
defer self.handles.performing = false;
|
||||
|
||||
// In case of request w/o data, we need to call the header done
|
||||
// callback now.
|
||||
if (!transfer._header_done_called) {
|
||||
const proceed = transfer.headerDoneCallback(&msg.conn) catch |err| {
|
||||
log.err(.http, "header_done_callback", .{ .err = err });
|
||||
requestFailed(transfer, err, true);
|
||||
continue;
|
||||
};
|
||||
if (!proceed) {
|
||||
requestFailed(transfer, error.Abort, true);
|
||||
break :blk;
|
||||
}
|
||||
}
|
||||
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 });
|
||||
requestFailed(transfer, err, true);
|
||||
continue;
|
||||
};
|
||||
if (!proceed) {
|
||||
requestFailed(transfer, error.Abort, true);
|
||||
break :blk;
|
||||
}
|
||||
}
|
||||
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 });
|
||||
requestFailed(transfer, err, true);
|
||||
continue;
|
||||
};
|
||||
|
||||
transfer.req.notification.dispatch(.http_request_done, &.{
|
||||
.transfer = transfer,
|
||||
@@ -1041,10 +1046,6 @@ pub const Transfer = struct {
|
||||
|
||||
pub fn abort(self: *Transfer, err: anyerror) void {
|
||||
requestFailed(self, err, true);
|
||||
if (self._conn == null) {
|
||||
self.deinit();
|
||||
return;
|
||||
}
|
||||
|
||||
const client = self.client;
|
||||
if (client.handles.performing) {
|
||||
|
||||
@@ -561,6 +561,14 @@ fn testHTTPHandler(req: *std.http.Server.Request) !void {
|
||||
});
|
||||
}
|
||||
|
||||
if (std.mem.eql(u8, path, "/xhr_empty")) {
|
||||
return req.respond("", .{
|
||||
.extra_headers = &.{
|
||||
.{ .name = "Content-Type", .value = "text/html; charset=utf-8" },
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (std.mem.eql(u8, path, "/xhr/json")) {
|
||||
return req.respond("{\"over\":\"9000!!!\",\"updated_at\":1765867200000}", .{
|
||||
.extra_headers = &.{
|
||||
|
||||
Reference in New Issue
Block a user