Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion src/browser/Factory.zig
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const SlabAllocator = @import("../slab.zig").SlabAllocator;
const Page = @import("Page.zig");
const Node = @import("webapi/Node.zig");
const Event = @import("webapi/Event.zig");
const UIEvent = @import("webapi/event/UIEvent.zig");
const Element = @import("webapi/Element.zig");
const Document = @import("webapi/Document.zig");
const EventTarget = @import("webapi/EventTarget.zig");
Expand Down Expand Up @@ -170,11 +171,11 @@ pub fn eventTarget(self: *Factory, child: anytype) !*@TypeOf(child) {
pub fn event(self: *Factory, typ: []const u8, child: anytype) !*@TypeOf(child) {
const allocator = self._slab.allocator();

// Special case: Event has a _type_string field, so we need manual setup
const chain = try PrototypeChain(
&.{ Event, @TypeOf(child) },
).allocate(allocator);

// Special case: Event has a _type_string field, so we need manual setup
const event_ptr = chain.get(0);
event_ptr.* = .{
._type = unionInit(Event.Type, chain.get(1)),
Expand All @@ -185,6 +186,25 @@ pub fn event(self: *Factory, typ: []const u8, child: anytype) !*@TypeOf(child) {
return chain.get(1);
}

pub fn uiEvent(self: *Factory, typ: []const u8, child: anytype) !*@TypeOf(child) {
const allocator = self._slab.allocator();

const chain = try PrototypeChain(
&.{ Event, UIEvent, @TypeOf(child) },
).allocate(allocator);

// Special case: Event has a _type_string field, so we need manual setup
const event_ptr = chain.get(0);
event_ptr.* = .{
._type = unionInit(Event.Type, chain.get(1)),
._type_string = try String.init(self._page.arena, typ, .{}),
};
chain.setMiddle(1, UIEvent.Type);
chain.setLeaf(2, child);

return chain.get(2);
}

pub fn blob(self: *Factory, child: anytype) !*@TypeOf(child) {
const allocator = self._slab.allocator();

Expand Down
3 changes: 3 additions & 0 deletions src/browser/js/bridge.zig
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,9 @@ pub const JsApis = flattenTypes(&.{
@import("../webapi/event/NavigationCurrentEntryChangeEvent.zig"),
@import("../webapi/event/PageTransitionEvent.zig"),
@import("../webapi/event/PopStateEvent.zig"),
@import("../webapi/event/UIEvent.zig"),
@import("../webapi/event/MouseEvent.zig"),
@import("../webapi/event/KeyboardEvent.zig"),
@import("../webapi/MessageChannel.zig"),
@import("../webapi/MessagePort.zig"),
@import("../webapi/media/MediaError.zig"),
Expand Down
89 changes: 89 additions & 0 deletions src/browser/tests/event/keyboard.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<!DOCTYPE html>
<script src="../testing.js"></script>

<script id=default>
let event = new KeyboardEvent("test", { key: "a" });
testing.expectEqual(true, event instanceof KeyboardEvent);
testing.expectEqual(true, event instanceof Event);

testing.expectEqual("test", event.type);
testing.expectEqual("a", event.key);

testing.expectEqual(0, event.location);
testing.expectEqual(false, event.repeat);
testing.expectEqual(false, event.isComposing);

testing.expectEqual(false, event.ctrlKey);
testing.expectEqual(false, event.shiftKey);
testing.expectEqual(false, event.metaKey);
testing.expectEqual(false, event.altKey);
</script>

<script id=getModifierState>
event = new KeyboardEvent("test", {
altKey: true,
shiftKey: true,
metaKey: true,
ctrlKey: true,
});

testing.expectEqual(true, event.getModifierState("Alt"));
testing.expectEqual(true, event.getModifierState("AltGraph"));
testing.expectEqual(true, event.getModifierState("Control"));
testing.expectEqual(true, event.getModifierState("Shift"));
testing.expectEqual(true, event.getModifierState("Meta"));
</script>

<script id=keyDownListener>
event = new KeyboardEvent("keydown", { key: "z" });
let isKeyDown = false;

document.addEventListener("keydown", (e) => {
isKeyDown = true;

testing.expectEqual(true, e instanceof KeyboardEvent);
testing.expectEqual(true, e instanceof UIEvent);
testing.expectEqual(true, e instanceof Event);
testing.expectEqual("z", event.key);
});

document.dispatchEvent(event);

testing.expectEqual(true, isKeyDown);
</script>

<script id=keyUpListener>
event = new KeyboardEvent("keyup", { key: "x" });
let isKeyUp = false;

document.addEventListener("keyup", (e) => {
isKeyUp = true;

testing.expectEqual(true, e instanceof KeyboardEvent);
testing.expectEqual(true, e instanceof UIEvent);
testing.expectEqual(true, e instanceof Event);
testing.expectEqual("x", event.key);
});

document.dispatchEvent(event);

testing.expectEqual(true, isKeyUp);
</script>

<script id=keyPressListener>
event = new KeyboardEvent("keypress", { key: "w" });
let isKeyPress = false;

document.addEventListener("keypress", (e) => {
isKeyPress = true;

testing.expectEqual(true, e instanceof KeyboardEvent);
testing.expectEqual(true, e instanceof UIEvent);
testing.expectEqual(true, e instanceof Event);
testing.expectEqual("w", event.key);
});

document.dispatchEvent(event);

testing.expectEqual(true, isKeyPress);
</script>
37 changes: 37 additions & 0 deletions src/browser/tests/event/mouse.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<!DOCTYPE html>
<script src="../testing.js"></script>
<script id=default>
let event = new MouseEvent('click');
testing.expectEqual('click', event.type);
testing.expectEqual(true, event instanceof MouseEvent);
testing.expectEqual(true, event instanceof UIEvent);
testing.expectEqual(true, event instanceof Event);
testing.expectEqual(0, event.clientX);
testing.expectEqual(0, event.clientY);
testing.expectEqual(0, event.screenX);
testing.expectEqual(0, event.screenY);
</script>

<script id=parameters>
let new_event = new MouseEvent('click', { 'button': 0, 'clientX': 10, 'clientY': 20, screenX: 200, screenY: 500 });
testing.expectEqual(0, new_event.button);
testing.expectEqual(10, new_event.x);
testing.expectEqual(20, new_event.y);
testing.expectEqual(10, new_event.pageX);
testing.expectEqual(20, new_event.pageY);
testing.expectEqual(200, new_event.screenX);
testing.expectEqual(500, new_event.screenY);
</script>

<script id=listener>
let me = new MouseEvent('click');
testing.expectEqual(true, me instanceof Event);

var evt = null;
document.addEventListener('click', function (e) {
evt = e;
});
document.dispatchEvent(me);
testing.expectEqual('click', evt.type);
testing.expectEqual(true, evt instanceof MouseEvent);
</script>
54 changes: 54 additions & 0 deletions src/browser/tests/event/ui.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<!DOCTYPE html>
<script src="../testing.js"></script>

<script id=uiEventConstructor>
const evt = new UIEvent('click', {
detail: 5,
bubbles: true,
cancelable: true
});
testing.expectEqual('click', evt.type);
testing.expectEqual(5, evt.detail);
testing.expectEqual(true, evt.bubbles);
testing.expectEqual(true, evt.cancelable);
testing.expectEqual(window, evt.view);
</script>

<script id=uiEventWithView>
const evt2 = new UIEvent('mousedown', {
detail: 2,
view: window
});
testing.expectEqual('mousedown', evt2.type);
testing.expectEqual(2, evt2.detail);
testing.expectEqual(window, evt2.view);
</script>

<script id=uiEventDefaults>
const evt3 = new UIEvent('focus');
testing.expectEqual('focus', evt3.type);
testing.expectEqual(0, evt3.detail);
testing.expectEqual(false, evt3.bubbles);
testing.expectEqual(false, evt3.cancelable);
testing.expectEqual(window, evt3.view);
</script>

<script id=uiEventInheritance>
const evt4 = new UIEvent('blur', { detail: 1 });
testing.expectEqual('blur', evt4.type);
testing.expectEqual(Event.NONE, evt4.eventPhase);
testing.expectEqual(false, evt4.defaultPrevented);
testing.expectEqual(1, evt4.detail);
</script>

<script id=uiEventDetailTypes>
const evt5 = new UIEvent('custom', { detail: 0 });
const evt6 = new UIEvent('custom', { detail: 100 });
testing.expectEqual(0, evt5.detail);
testing.expectEqual(100, evt6.detail);
</script>

<script id=uiEventDetailTypes2>
const evt7 = new UIEvent('custom', { bubbles: true });
testing.expectEqual(0, evt7.detail);
</script>
6 changes: 3 additions & 3 deletions src/browser/webapi/Event.zig
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

const std = @import("std");
const js = @import("../js/js.zig");
const reflect = @import("../reflect.zig");

const Page = @import("../Page.zig");
const EventTarget = @import("EventTarget.zig");
Expand Down Expand Up @@ -60,9 +59,10 @@ pub const Type = union(enum) {
navigation_current_entry_change_event: *@import("event/NavigationCurrentEntryChangeEvent.zig"),
page_transition_event: *@import("event/PageTransitionEvent.zig"),
pop_state_event: *@import("event/PopStateEvent.zig"),
ui_event: *@import("event/UIEvent.zig"),
};

const Options = struct {
pub const Options = struct {
bubbles: bool = false,
cancelable: bool = false,
composed: bool = false,
Expand Down Expand Up @@ -210,7 +210,7 @@ pub fn inheritOptions(comptime T: type, comptime additions: anytype) type {

inline for (t_fields) |field| {
if (std.mem.eql(u8, field.name, "_proto")) {
const ProtoType = reflect.Struct(field.type);
const ProtoType = @typeInfo(field.type).pointer.child;
if (@hasDecl(ProtoType, "Options")) {
const parent_options = @typeInfo(ProtoType.Options);
all_fields = all_fields ++ parent_options.@"struct".fields;
Expand Down
Loading
Loading