Skip to content

Commit 8904afa

Browse files
committed
Fix crash when event target is the window.
On page load, emitted by the page, the target is the window, but it's improperly cast since the pointer is actually `window.base`. This is going to be a problem in general for any Zig type dispatched as a target, but the Window one is the most obvious and the easiest to fix. If this issue comes up with other types, we'll need to come up with a more robust solution.
1 parent d95a18b commit 8904afa

File tree

5 files changed

+23
-12
lines changed

5 files changed

+23
-12
lines changed

src/browser/dom/event_target.zig

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,15 @@ pub const EventTarget = struct {
3333
pub const Self = parser.EventTarget;
3434
pub const Exception = DOMException;
3535

36-
pub fn toInterface(et: *parser.EventTarget) !Union {
37-
// NOTE: for now we state that all EventTarget are Nodes
38-
// TODO: handle other types (eg. Window)
36+
pub fn toInterface(et: *parser.EventTarget, page: *Page) !Union {
37+
// Not all targets are *parser.Nodes. page.zig emits a "load" event
38+
// where the target is a Window, which cannot be cast directly to a node.
39+
// Ideally, we'd remove this duality. Failing that, we'll need to embed
40+
// data into the *parser.EventTarget should we need this for other types.
41+
// For now, for the Window, which is a singleton, we can do this:
42+
if (@intFromPtr(et) == @intFromPtr(&page.window.base)) {
43+
return .{ .Window = &page.window };
44+
}
3945
return Nod.Node.toInterface(@as(*parser.Node, @ptrCast(et)));
4046
}
4147

src/browser/events/custom_event.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const JsObject = @import("../env.zig").JsObject;
2323
// https://dom.spec.whatwg.org/#interface-customevent
2424
pub const CustomEvent = struct {
2525
pub const prototype = *Event;
26+
pub const union_make_copy = true;
2627

2728
proto: parser.Event,
2829
detail: ?JsObject,

src/browser/events/event.zig

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const log = @import("../../log.zig");
2323
const parser = @import("../netsurf.zig");
2424
const generate = @import("../../runtime/generate.zig");
2525

26+
const Page = @import("../page.zig").Page;
2627
const DOMException = @import("../dom/exceptions.zig").DOMException;
2728
const EventTarget = @import("../dom/event_target.zig").EventTarget;
2829
const EventTargetUnion = @import("../dom/event_target.zig").Union;
@@ -76,16 +77,16 @@ pub const Event = struct {
7677
return try parser.eventType(self);
7778
}
7879

79-
pub fn get_target(self: *parser.Event) !?EventTargetUnion {
80+
pub fn get_target(self: *parser.Event, page: *Page) !?EventTargetUnion {
8081
const et = try parser.eventTarget(self);
8182
if (et == null) return null;
82-
return try EventTarget.toInterface(et.?);
83+
return try EventTarget.toInterface(et.?, page);
8384
}
8485

85-
pub fn get_currentTarget(self: *parser.Event) !?EventTargetUnion {
86+
pub fn get_currentTarget(self: *parser.Event, page: *Page) !?EventTargetUnion {
8687
const et = try parser.eventCurrentTarget(self);
8788
if (et == null) return null;
88-
return try EventTarget.toInterface(et.?);
89+
return try EventTarget.toInterface(et.?, page);
8990
}
9091

9192
pub fn get_eventPhase(self: *parser.Event) !u8 {

src/browser/xhr/progress_event.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const DOMException = @import("../dom/exceptions.zig").DOMException;
2424
pub const ProgressEvent = struct {
2525
pub const prototype = *Event;
2626
pub const Exception = DOMException;
27+
pub const union_make_copy = true;
2728

2829
pub const EventInit = struct {
2930
lengthComputable: bool = false,

src/runtime/generate.zig

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ pub fn Union(comptime interfaces: anytype) type {
7171
var FT = @field(tuple, field.name);
7272
if (@hasDecl(FT, "Self")) {
7373
FT = *(@field(FT, "Self"));
74+
} else if (!@hasDecl(FT, "union_make_copy")) {
75+
FT = *FT;
7476
}
7577
union_fields[index] = .{
7678
.type = FT,
@@ -171,7 +173,7 @@ fn filterMap(comptime count: usize, interfaces: [count]type) struct { usize, [co
171173
return .{ unfiltered_count, map };
172174
}
173175

174-
test "generate.Union" {
176+
test "generate: Union" {
175177
const Astruct = struct {
176178
pub const Self = Other;
177179
const Other = struct {};
@@ -188,15 +190,15 @@ test "generate.Union" {
188190
const value = Union(.{ Astruct, Bstruct, .{Cstruct} });
189191
const ti = @typeInfo(value).@"union";
190192
try std.testing.expectEqual(3, ti.fields.len);
191-
try std.testing.expectEqualStrings("*runtime.generate.test.generate.Union.Astruct.Other", @typeName(ti.fields[0].type));
193+
try std.testing.expectEqualStrings("*runtime.generate.test.generate: Union.Astruct.Other", @typeName(ti.fields[0].type));
192194
try std.testing.expectEqualStrings(ti.fields[0].name, "Astruct");
193-
try std.testing.expectEqual(Bstruct, ti.fields[1].type);
195+
try std.testing.expectEqual(*Bstruct, ti.fields[1].type);
194196
try std.testing.expectEqualStrings(ti.fields[1].name, "Bstruct");
195-
try std.testing.expectEqual(Cstruct, ti.fields[2].type);
197+
try std.testing.expectEqual(*Cstruct, ti.fields[2].type);
196198
try std.testing.expectEqualStrings(ti.fields[2].name, "Cstruct");
197199
}
198200

199-
test "generate.Tuple" {
201+
test "generate: Tuple" {
200202
const Astruct = struct {};
201203

202204
const Bstruct = struct {

0 commit comments

Comments
 (0)