mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-21 20:24:42 +00:00
Implement window.event property
Add the deprecated-but-widely-used window.event property that returns the Event currently being handled. Returns undefined when no event is being dispatched. Implementation saves and restores window._current_event around handler invocation in both dispatchDirect and dispatchNode, supporting nested event dispatch correctly. Fixes #1770 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -233,6 +233,12 @@ const DispatchDirectOptions = struct {
|
||||
pub fn dispatchDirect(self: *EventManager, target: *EventTarget, event: *Event, handler: anytype, comptime opts: DispatchDirectOptions) !void {
|
||||
const page = self.page;
|
||||
|
||||
// Set window.event to the currently dispatching event (WHATWG spec)
|
||||
const window = page.window;
|
||||
const prev_event = window._current_event;
|
||||
window._current_event = event;
|
||||
defer window._current_event = prev_event;
|
||||
|
||||
event.acquireRef();
|
||||
defer event.deinit(false, page._session);
|
||||
|
||||
@@ -398,6 +404,13 @@ fn dispatchNode(self: *EventManager, target: *Node, event: *Event, comptime opts
|
||||
}
|
||||
|
||||
const page = self.page;
|
||||
|
||||
// Set window.event to the currently dispatching event (WHATWG spec)
|
||||
const window = page.window;
|
||||
const prev_event = window._current_event;
|
||||
window._current_event = event;
|
||||
defer window._current_event = prev_event;
|
||||
|
||||
var was_handled = false;
|
||||
|
||||
// Create a single scope for all event handlers in this dispatch.
|
||||
|
||||
34
src/browser/tests/window/window_event.html
Normal file
34
src/browser/tests/window/window_event.html
Normal file
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<script src="../testing.js"></script>
|
||||
|
||||
<script id=windowEventUndefinedOutsideHandler>
|
||||
testing.expectEqual(undefined, window.event);
|
||||
</script>
|
||||
|
||||
<script id=windowEventSetDuringWindowHandler>
|
||||
var capturedEvent = null;
|
||||
|
||||
window.addEventListener('test-event', function(e) {
|
||||
capturedEvent = window.event;
|
||||
});
|
||||
|
||||
var ev = new Event('test-event');
|
||||
window.dispatchEvent(ev);
|
||||
|
||||
testing.expectEqual(ev, capturedEvent);
|
||||
testing.expectEqual(undefined, window.event);
|
||||
</script>
|
||||
|
||||
<script id=windowEventRestoredAfterHandler>
|
||||
var captured2 = null;
|
||||
|
||||
window.addEventListener('test-event-2', function(e) {
|
||||
captured2 = window.event;
|
||||
});
|
||||
|
||||
var ev2 = new Event('test-event-2');
|
||||
window.dispatchEvent(ev2);
|
||||
|
||||
testing.expectEqual(ev2, captured2);
|
||||
testing.expectEqual(undefined, window.event);
|
||||
</script>
|
||||
@@ -68,6 +68,7 @@ _on_popstate: ?js.Function.Global = null,
|
||||
_on_error: ?js.Function.Global = null,
|
||||
_on_message: ?js.Function.Global = null,
|
||||
_on_unhandled_rejection: ?js.Function.Global = null, // TODO: invoke on error
|
||||
_current_event: ?*Event = null,
|
||||
_location: *Location,
|
||||
_timer_id: u30 = 0,
|
||||
_timers: std.AutoHashMapUnmanaged(u32, *ScheduleCallback) = .{},
|
||||
@@ -90,6 +91,10 @@ pub fn asEventTarget(self: *Window) *EventTarget {
|
||||
return self._proto;
|
||||
}
|
||||
|
||||
pub fn getEvent(self: *const Window) ?*Event {
|
||||
return self._current_event;
|
||||
}
|
||||
|
||||
pub fn getSelf(self: *Window) *Window {
|
||||
return self;
|
||||
}
|
||||
@@ -805,6 +810,7 @@ pub const JsApi = struct {
|
||||
pub const onerror = bridge.accessor(Window.getOnError, Window.setOnError, .{});
|
||||
pub const onmessage = bridge.accessor(Window.getOnMessage, Window.setOnMessage, .{});
|
||||
pub const onunhandledrejection = bridge.accessor(Window.getOnUnhandledRejection, Window.setOnUnhandledRejection, .{});
|
||||
pub const event = bridge.accessor(Window.getEvent, null, .{ .null_as_undefined = true });
|
||||
pub const fetch = bridge.function(Window.fetch, .{});
|
||||
pub const queueMicrotask = bridge.function(Window.queueMicrotask, .{});
|
||||
pub const setTimeout = bridge.function(Window.setTimeout, .{});
|
||||
|
||||
Reference in New Issue
Block a user