mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-22 04:34:44 +00:00
Add Request.signal
Allows aborting a fetch. Improves github integration
This commit is contained in:
@@ -225,3 +225,17 @@
|
|||||||
URL.revokeObjectURL(blobUrl);
|
URL.revokeObjectURL(blobUrl);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script id=abort>
|
||||||
|
testing.async(async (restore) => {
|
||||||
|
const controller = new AbortController();
|
||||||
|
controller.abort();
|
||||||
|
try {
|
||||||
|
await fetch('http://127.0.0.1:9582/xhr', { signal: controller.signal });
|
||||||
|
testain.fail('fetch should have been aborted');
|
||||||
|
} catch (e) {
|
||||||
|
restore();
|
||||||
|
testing.expectEqual("AbortError", e.name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ const URL = @import("../../URL.zig");
|
|||||||
const Blob = @import("../Blob.zig");
|
const Blob = @import("../Blob.zig");
|
||||||
const Request = @import("Request.zig");
|
const Request = @import("Request.zig");
|
||||||
const Response = @import("Response.zig");
|
const Response = @import("Response.zig");
|
||||||
|
const AbortSignal = @import("../AbortSignal.zig");
|
||||||
|
const DOMException = @import("../DOMException.zig");
|
||||||
|
|
||||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||||
|
|
||||||
@@ -39,6 +41,7 @@ _buf: std.ArrayList(u8),
|
|||||||
_response: *Response,
|
_response: *Response,
|
||||||
_resolver: js.PromiseResolver.Global,
|
_resolver: js.PromiseResolver.Global,
|
||||||
_owns_response: bool,
|
_owns_response: bool,
|
||||||
|
_signal: ?*AbortSignal,
|
||||||
|
|
||||||
pub const Input = Request.Input;
|
pub const Input = Request.Input;
|
||||||
pub const InitOpts = Request.InitOpts;
|
pub const InitOpts = Request.InitOpts;
|
||||||
@@ -47,6 +50,13 @@ pub fn init(input: Input, options: ?InitOpts, page: *Page) !js.Promise {
|
|||||||
const request = try Request.init(input, options, page);
|
const request = try Request.init(input, options, page);
|
||||||
const resolver = page.js.local.?.createPromiseResolver();
|
const resolver = page.js.local.?.createPromiseResolver();
|
||||||
|
|
||||||
|
if (request._signal) |signal| {
|
||||||
|
if (signal._aborted) {
|
||||||
|
resolver.reject("fetch aborted", DOMException.init("The operation was aborted.", "AbortError"));
|
||||||
|
return resolver.promise();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (std.mem.startsWith(u8, request._url, "blob:")) {
|
if (std.mem.startsWith(u8, request._url, "blob:")) {
|
||||||
return handleBlobUrl(request._url, resolver, page);
|
return handleBlobUrl(request._url, resolver, page);
|
||||||
}
|
}
|
||||||
@@ -62,6 +72,7 @@ pub fn init(input: Input, options: ?InitOpts, page: *Page) !js.Promise {
|
|||||||
._resolver = try resolver.persist(),
|
._resolver = try resolver.persist(),
|
||||||
._response = response,
|
._response = response,
|
||||||
._owns_response = true,
|
._owns_response = true,
|
||||||
|
._signal = request._signal,
|
||||||
};
|
};
|
||||||
|
|
||||||
const http_client = page._session.browser.http_client;
|
const http_client = page._session.browser.http_client;
|
||||||
@@ -126,6 +137,12 @@ fn httpStartCallback(transfer: *HttpClient.Transfer) !void {
|
|||||||
fn httpHeaderDoneCallback(transfer: *HttpClient.Transfer) !bool {
|
fn httpHeaderDoneCallback(transfer: *HttpClient.Transfer) !bool {
|
||||||
const self: *Fetch = @ptrCast(@alignCast(transfer.ctx));
|
const self: *Fetch = @ptrCast(@alignCast(transfer.ctx));
|
||||||
|
|
||||||
|
if (self._signal) |signal| {
|
||||||
|
if (signal._aborted) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const arena = self._response._arena;
|
const arena = self._response._arena;
|
||||||
if (transfer.getContentLength()) |cl| {
|
if (transfer.getContentLength()) |cl| {
|
||||||
try self._buf.ensureTotalCapacity(arena, cl);
|
try self._buf.ensureTotalCapacity(arena, cl);
|
||||||
@@ -175,6 +192,14 @@ fn httpHeaderDoneCallback(transfer: *HttpClient.Transfer) !bool {
|
|||||||
|
|
||||||
fn httpDataCallback(transfer: *HttpClient.Transfer, data: []const u8) !void {
|
fn httpDataCallback(transfer: *HttpClient.Transfer, data: []const u8) !void {
|
||||||
const self: *Fetch = @ptrCast(@alignCast(transfer.ctx));
|
const self: *Fetch = @ptrCast(@alignCast(transfer.ctx));
|
||||||
|
|
||||||
|
// Check if aborted
|
||||||
|
if (self._signal) |signal| {
|
||||||
|
if (signal._aborted) {
|
||||||
|
return error.Abort;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try self._buf.appendSlice(self._response._arena, data);
|
try self._buf.appendSlice(self._response._arena, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ const URL = @import("../URL.zig");
|
|||||||
const Page = @import("../../Page.zig");
|
const Page = @import("../../Page.zig");
|
||||||
const Headers = @import("Headers.zig");
|
const Headers = @import("Headers.zig");
|
||||||
const Blob = @import("../Blob.zig");
|
const Blob = @import("../Blob.zig");
|
||||||
|
const AbortSignal = @import("../AbortSignal.zig");
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
const Request = @This();
|
const Request = @This();
|
||||||
@@ -36,6 +37,7 @@ _body: ?[]const u8,
|
|||||||
_arena: Allocator,
|
_arena: Allocator,
|
||||||
_cache: Cache,
|
_cache: Cache,
|
||||||
_credentials: Credentials,
|
_credentials: Credentials,
|
||||||
|
_signal: ?*AbortSignal,
|
||||||
|
|
||||||
pub const Input = union(enum) {
|
pub const Input = union(enum) {
|
||||||
request: *Request,
|
request: *Request,
|
||||||
@@ -48,6 +50,7 @@ pub const InitOpts = struct {
|
|||||||
body: ?[]const u8 = null,
|
body: ?[]const u8 = null,
|
||||||
cache: Cache = .default,
|
cache: Cache = .default,
|
||||||
credentials: Credentials = .@"same-origin",
|
credentials: Credentials = .@"same-origin",
|
||||||
|
signal: ?*AbortSignal = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const Credentials = enum {
|
const Credentials = enum {
|
||||||
@@ -97,6 +100,13 @@ pub fn init(input: Input, opts_: ?InitOpts, page: *Page) !*Request {
|
|||||||
.request => |r| r._body,
|
.request => |r| r._body,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const signal = if (opts.signal) |s|
|
||||||
|
s
|
||||||
|
else switch (input) {
|
||||||
|
.url => null,
|
||||||
|
.request => |r| r._signal,
|
||||||
|
};
|
||||||
|
|
||||||
return page._factory.create(Request{
|
return page._factory.create(Request{
|
||||||
._url = url,
|
._url = url,
|
||||||
._arena = arena,
|
._arena = arena,
|
||||||
@@ -105,6 +115,7 @@ pub fn init(input: Input, opts_: ?InitOpts, page: *Page) !*Request {
|
|||||||
._cache = opts.cache,
|
._cache = opts.cache,
|
||||||
._credentials = opts.credentials,
|
._credentials = opts.credentials,
|
||||||
._body = body,
|
._body = body,
|
||||||
|
._signal = signal,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,6 +155,10 @@ pub fn getCredentials(self: *const Request) []const u8 {
|
|||||||
return @tagName(self._credentials);
|
return @tagName(self._credentials);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn getSignal(self: *const Request) ?*AbortSignal {
|
||||||
|
return self._signal;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn getHeaders(self: *Request, page: *Page) !*Headers {
|
pub fn getHeaders(self: *Request, page: *Page) !*Headers {
|
||||||
if (self._headers) |headers| {
|
if (self._headers) |headers| {
|
||||||
return headers;
|
return headers;
|
||||||
@@ -200,6 +215,7 @@ pub fn clone(self: *const Request, page: *Page) !*Request {
|
|||||||
._cache = self._cache,
|
._cache = self._cache,
|
||||||
._credentials = self._credentials,
|
._credentials = self._credentials,
|
||||||
._body = self._body,
|
._body = self._body,
|
||||||
|
._signal = self._signal,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,6 +234,7 @@ pub const JsApi = struct {
|
|||||||
pub const headers = bridge.accessor(Request.getHeaders, null, .{});
|
pub const headers = bridge.accessor(Request.getHeaders, null, .{});
|
||||||
pub const cache = bridge.accessor(Request.getCache, null, .{});
|
pub const cache = bridge.accessor(Request.getCache, null, .{});
|
||||||
pub const credentials = bridge.accessor(Request.getCredentials, null, .{});
|
pub const credentials = bridge.accessor(Request.getCredentials, null, .{});
|
||||||
|
pub const signal = bridge.accessor(Request.getSignal, null, .{});
|
||||||
pub const blob = bridge.function(Request.blob, .{});
|
pub const blob = bridge.function(Request.blob, .{});
|
||||||
pub const text = bridge.function(Request.text, .{});
|
pub const text = bridge.function(Request.text, .{});
|
||||||
pub const json = bridge.function(Request.json, .{});
|
pub const json = bridge.function(Request.json, .{});
|
||||||
|
|||||||
Reference in New Issue
Block a user