Skip to content

Commit 82a4525

Browse files
committed
add direct event handlers
1 parent 4c95704 commit 82a4525

File tree

9 files changed

+95
-33
lines changed

9 files changed

+95
-33
lines changed

src/browser/events/event.zig

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
// along with this program. If not, see <https://www.gnu.org/licenses/>.
1818

1919
const std = @import("std");
20+
const js = @import("../js/js.zig");
2021
const Allocator = std.mem.Allocator;
2122

2223
const log = @import("../../log.zig");
@@ -231,8 +232,6 @@ pub const EventHandler = struct {
231232
node: parser.EventNode,
232233
listener: *parser.EventListener,
233234

234-
const js = @import("../js/js.zig");
235-
236235
pub const Listener = union(enum) {
237236
function: js.Function,
238237
object: js.Object,
@@ -404,6 +403,40 @@ const SignalCallback = struct {
404403
}
405404
};
406405

406+
pub fn DirectEventHandler(
407+
comptime TargetT: type,
408+
target: *TargetT,
409+
event_type: []const u8,
410+
maybe_listener: ?EventHandler.Listener,
411+
cb: *?js.Function,
412+
page_arena: std.mem.Allocator,
413+
) !void {
414+
const event_target = parser.toEventTarget(TargetT, target);
415+
416+
// Check if we have a listener set.
417+
if (cb.*) |callback| {
418+
const listener = try parser.eventTargetHasListener(event_target, event_type, false, callback.id);
419+
std.debug.assert(listener != null);
420+
try parser.eventTargetRemoveEventListener(event_target, event_type, listener.?, false);
421+
}
422+
423+
if (maybe_listener) |listener| {
424+
switch (listener) {
425+
// If an object is given as listener, do nothing.
426+
.object => {},
427+
.function => |callback| {
428+
_ = try EventHandler.register(page_arena, event_target, event_type, listener, null) orelse unreachable;
429+
cb.* = callback;
430+
431+
return;
432+
},
433+
}
434+
}
435+
436+
// Just unset the listener.
437+
cb.* = null;
438+
}
439+
407440
const testing = @import("../../testing.zig");
408441
test "Browser: Event" {
409442
try testing.htmlRunner("events/event.html");

src/browser/html/History.zig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,5 +177,6 @@ pub const PopStateEvent = struct {
177177

178178
const testing = @import("../../testing.zig");
179179
test "Browser: HTML.History" {
180-
try testing.htmlRunner("html/history.html");
180+
try testing.htmlRunner("html/history/history.html");
181+
try testing.htmlRunner("html/history/history2.html");
181182
}

src/browser/html/Navigation.zig

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const URL = @import("../../url.zig").URL;
2323
const js = @import("../js/js.zig");
2424
const Page = @import("../page.zig").Page;
2525

26+
const DirectEventHandler = @import("../events/event.zig").DirectEventHandler;
2627
const EventTarget = @import("../dom/event_target.zig").EventTarget;
2728
const EventHandler = @import("../events/event.zig").EventHandler;
2829

@@ -62,6 +63,8 @@ index: usize = 0,
6263
entries: std.ArrayListUnmanaged(*NavigationHistoryEntry) = .empty,
6364
next_entry_id: usize = 0,
6465

66+
oncurrententrychange_callback: ?js.Function = null,
67+
6568
// https://developer.mozilla.org/en-US/docs/Web/API/NavigationHistoryEntry
6669
const NavigationHistoryEntry = struct {
6770
pub const prototype = *EventTarget;
@@ -199,6 +202,16 @@ pub fn _forward(self: *Navigation, page: *Page) !NavigationReturn {
199202
return self.navigate(next_entry.url, .{ .traverse = new_index }, page);
200203
}
201204

205+
/// Returns `oncurrententrychange_callback`.
206+
pub fn get_oncurrententrychange(self: *const Navigation) ?js.Function {
207+
return self.oncurrententrychange_callback;
208+
}
209+
210+
/// Sets `oncurrententrychange_callback`.
211+
pub fn set_oncurrententrychange(self: *Navigation, maybe_listener: ?EventHandler.Listener, page: *Page) !void {
212+
try DirectEventHandler(Navigation, self, "currententrychange", maybe_listener, &self.oncurrententrychange_callback, page.arena);
213+
}
214+
202215
// This is for after true navigation processing, where we need to ensure that our entries are up to date.
203216
// This is only really safe to run in the `pageDoneCallback` where we can guarantee that the URL and NavigationKind are correct.
204217
pub fn processNavigation(self: *Navigation, page: *Page) !void {
@@ -456,5 +469,5 @@ pub const NavigationCurrentEntryChangeEvent = struct {
456469

457470
const testing = @import("../../testing.zig");
458471
test "Browser: Navigation" {
459-
try testing.htmlRunner("html/navigation.html");
472+
try testing.htmlRunner("html/navigation/navigation.html");
460473
}

src/browser/html/window.zig

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ const fetchFn = @import("../fetch/fetch.zig").fetch;
4444
const storage = @import("../storage/storage.zig");
4545
const ErrorEvent = @import("error_event.zig").ErrorEvent;
4646

47+
const DirectEventHandler = @import("../events/event.zig").DirectEventHandler;
48+
4749
// https://dom.spec.whatwg.org/#interface-window-extensions
4850
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#window
4951
pub const Window = struct {
@@ -70,6 +72,7 @@ pub const Window = struct {
7072
scroll_x: u32 = 0,
7173
scroll_y: u32 = 0,
7274
onload_callback: ?js.Function = null,
75+
onpopstate_callback: ?js.Function = null,
7376

7477
pub fn create(target: ?[]const u8, navigator: ?Navigator) !Window {
7578
var fbs = std.io.fixedBufferStream("");
@@ -111,31 +114,17 @@ pub const Window = struct {
111114

112115
/// Sets `onload_callback`.
113116
pub fn set_onload(self: *Window, maybe_listener: ?EventHandler.Listener, page: *Page) !void {
114-
const event_target = parser.toEventTarget(Window, self);
115-
const event_type = "load";
116-
117-
// Check if we have a listener set.
118-
if (self.onload_callback) |callback| {
119-
const listener = try parser.eventTargetHasListener(event_target, event_type, false, callback.id);
120-
std.debug.assert(listener != null);
121-
try parser.eventTargetRemoveEventListener(event_target, event_type, listener.?, false);
122-
}
123-
124-
if (maybe_listener) |listener| {
125-
switch (listener) {
126-
// If an object is given as listener, do nothing.
127-
.object => {},
128-
.function => |callback| {
129-
_ = try EventHandler.register(page.arena, event_target, event_type, listener, null) orelse unreachable;
130-
self.onload_callback = callback;
117+
try DirectEventHandler(Window, self, "load", maybe_listener, &self.onload_callback, page.arena);
118+
}
131119

132-
return;
133-
},
134-
}
135-
}
120+
/// Returns `onpopstate_callback`.
121+
pub fn get_onpopstate(self: *const Window) ?js.Function {
122+
return self.onpopstate_callback;
123+
}
136124

137-
// Just unset the listener.
138-
self.onload_callback = null;
125+
/// Sets `onpopstate_callback`.
126+
pub fn set_onpopstate(self: *Window, maybe_listener: ?EventHandler.Listener, page: *Page) !void {
127+
try DirectEventHandler(Window, self, "popstate", maybe_listener, &self.onpopstate_callback, page.arena);
139128
}
140129

141130
pub fn get_location(self: *Window) *Location {

src/tests/html/history.html renamed to src/tests/html/history/history.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!DOCTYPE html>
2-
<script src="../testing.js"></script>
2+
<script src="../../testing.js"></script>
33

44
<script id=history>
55
testing.expectEqual('auto', history.scrollRestoration);
@@ -11,7 +11,7 @@
1111
testing.expectEqual('auto', history.scrollRestoration);
1212
testing.expectEqual(null, history.state)
1313

14-
history.pushState({ testInProgress: true }, null, 'http://127.0.0.1:9582/src/tests/html/history2.html');
14+
history.pushState({ testInProgress: true }, null, 'http://127.0.0.1:9582/src/tests/html/history/history_after_nav.html');
1515
testing.expectEqual({ testInProgress: true }, history.state);
1616

1717
history.pushState({ testInProgress: false }, null, 'http://127.0.0.1:9582/xhr/json');
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<!DOCTYPE html>
2+
<script src="../../testing.js"></script>
3+
4+
<script id=history2>
5+
history.pushState(
6+
{"new": "field", testComplete: true },
7+
null,
8+
'http://127.0.0.1:9582/src/tests/html/history/history_after_nav.html'
9+
);
10+
11+
let popstateEventFired = false;
12+
let popstateEventState = null;
13+
14+
// uses the window event listener.
15+
window.onpopstate = (event) => {
16+
popstateEventFired = true;
17+
popstateEventState = event.state;
18+
};
19+
20+
testing.eventually(() => {
21+
testing.expectEqual(true, popstateEventFired);
22+
testing.expectEqual(true, popstateEventState.testComplete);
23+
})
24+
25+
history.back();
26+
</script>

src/tests/html/history2.html renamed to src/tests/html/history/history_after_nav.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!DOCTYPE html>
2-
<script src="../testing.js"></script>
2+
<script src="../../testing.js"></script>
33

44
<script id=history2>
55
testing.expectEqual(true, history.state && history.state.testInProgress);

src/tests/html/navigation.html renamed to src/tests/html/navigation/navigation.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!DOCTYPE html>
2-
<script src="../testing.js"></script>
2+
<script src="../../testing.js"></script>
33

44
<script id=navigation>
55
testing.expectEqual('object', typeof navigation);
@@ -12,7 +12,7 @@
1212
const currentIndex = navigation.currentEntry.index;
1313

1414
navigation.navigate(
15-
'http://127.0.0.1:9582/src/tests/html/navigation2.html',
15+
'http://127.0.0.1:9582/src/tests/html/navigation/navigation2.html',
1616
{ state: { currentIndex: currentIndex, navTestInProgress: true } }
1717
);
1818
</script>

src/tests/html/navigation2.html renamed to src/tests/html/navigation/navigation2.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!DOCTYPE html>
2-
<script src="../testing.js"></script>
2+
<script src="../../testing.js"></script>
33

44
<script id=navigation2>
55
const state = navigation.currentEntry.getState();

0 commit comments

Comments
 (0)