Skip to content

Commit 08d2ea6

Browse files
committed
abort controller
1 parent 7a311a1 commit 08d2ea6

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// Copyright (C) 2023-2024 Lightpanda (Selecy SAS)
2+
//
3+
// Francis Bouvier <francis@lightpanda.io>
4+
// Pierre Tachoire <pierre@lightpanda.io>
5+
//
6+
// This program is free software: you can redistribute it and/or modify
7+
// it under the terms of the GNU Affero General Public License as
8+
// published by the Free Software Foundation, either version 3 of the
9+
// License, or (at your option) any later version.
10+
//
11+
// This program is distributed in the hope that it will be useful,
12+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
// GNU Affero General Public License for more details.
15+
//
16+
// You should have received a copy of the GNU Affero General Public License
17+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
19+
const std = @import("std");
20+
const parser = @import("../netsurf.zig");
21+
const EventTarget = @import("../dom/event_target.zig").EventTarget;
22+
23+
pub const Interfaces = .{
24+
AbortController,
25+
Signal,
26+
};
27+
28+
const AbortController = @This();
29+
30+
signal: ?Signal = null,
31+
32+
pub fn constructor() AbortController {
33+
return .{};
34+
}
35+
36+
pub fn get_signal(self: *AbortController) *Signal {
37+
if (self.signal) |*s| {
38+
return s;
39+
}
40+
self.signal = .init;
41+
return &self.signal.?;
42+
}
43+
44+
pub fn abort(self: *AbortController, reason_: ?[]const u8) void {
45+
const signal = &self.signal;
46+
47+
signal.aborted = true;
48+
signal.reason = reason_ orelse "AbortError";
49+
50+
const abort_event = try parser.eventCreate();
51+
defer parser.eventDestroy(abort_event);
52+
try parser.eventInit(abort_event, "abort", .{});
53+
_ = try parser.eventTargetDispatchEvent(
54+
parser.toEventTarget(Signal, signal),
55+
abort_event,
56+
);
57+
}
58+
59+
pub const Signal = struct {
60+
pub const prototype = *EventTarget;
61+
62+
aborted: bool,
63+
reason: ?[]const u8,
64+
proto: parser.EventTargetTBase,
65+
66+
pub const init: Signal = .{
67+
.proto = .{},
68+
.reason = null,
69+
.aborted = false,
70+
};
71+
72+
pub fn get_aborted(self: *const Signal) bool {
73+
return self.aborted;
74+
}
75+
76+
const Reason = union(enum) {
77+
reason: []const u8,
78+
undefined: void,
79+
};
80+
pub fn get_reason(self: *const Signal) Reason {
81+
if (self.reason) |r| {
82+
return .{ .reason = r };
83+
}
84+
return .{ .undefined = {} };
85+
}
86+
};
87+
88+
const testing = @import("../../testing.zig");
89+
test "Browser.HTML.AbortController" {
90+
var runner = try testing.jsRunner(testing.tracking_allocator, .{});
91+
defer runner.deinit();
92+
93+
try runner.testCases(&.{
94+
.{ "var called = false", null },
95+
.{ "var a1 = new AbortController()", null },
96+
.{ "var s1 = a1.signal", null },
97+
.{ "s1.reason", "undefined" },
98+
.{ "var target;", null },
99+
.{
100+
\\ s1.addEventListener('abort', (e) => {
101+
\\ called = 1;
102+
\\ target = e.target;
103+
\\
104+
\\ });
105+
\\ target == s1
106+
, "true" },
107+
.{ "a1.abort()", null },
108+
.{ "s1.aborted", "true" },
109+
.{ "s1.reason", "undefined" },
110+
.{ "called", "1" },
111+
}, .{});
112+
}

src/browser/html/html.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,5 @@ pub const Interfaces = .{
3939
@import("DataSet.zig"),
4040
@import("screen.zig").Interfaces,
4141
@import("error_event.zig").ErrorEvent,
42+
@import("AbortController.zig").Interfaces,
4243
};

0 commit comments

Comments
 (0)