Skip to content

Commit d7745a4

Browse files
authored
Merge pull request #902 from lightpanda-io/window_DOMContentLoaded
Trigger the DOMContentLoaded on the Window
2 parents 878dbd8 + ee50f12 commit d7745a4

File tree

4 files changed

+53
-3
lines changed

4 files changed

+53
-3
lines changed

src/browser/html/document.zig

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -278,15 +278,17 @@ pub const HTMLDocument = struct {
278278
const state = try page.getOrCreateNodeState(@alignCast(@ptrCast(self)));
279279
state.ready_state = .interactive;
280280

281-
const evt = try parser.eventCreate();
282-
defer parser.eventDestroy(evt);
283-
284281
log.debug(.script_event, "dispatch event", .{
285282
.type = "DOMContentLoaded",
286283
.source = "document",
287284
});
285+
286+
const evt = try parser.eventCreate();
287+
defer parser.eventDestroy(evt);
288288
try parser.eventInit(evt, "DOMContentLoaded", .{ .bubbles = true, .cancelable = true });
289289
_ = try parser.eventTargetDispatchEvent(parser.toEventTarget(parser.DocumentHTML, self), evt);
290+
291+
try page.window.dispatchForDocumentTarget(evt);
290292
}
291293

292294
pub fn documentIsComplete(self: *parser.DocumentHTML, page: *Page) !void {

src/browser/html/window.zig

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,23 @@ pub const Window = struct {
334334
);
335335
}
336336
}
337+
338+
// libdom's document doesn't have a parent, which is correct, but
339+
// breaks the event bubbling that happens for many events from
340+
// document -> window.
341+
// We need to force dispatch this event on the window, with the
342+
// document target.
343+
// In theory, we should do this for a lot of events and might need
344+
// to come up with a good way to solve this more generically. But
345+
// this specific event, and maybe a few others in the near future,
346+
// are blockers.
347+
// Worth noting that NetSurf itself appears to do something similar:
348+
// https://github.com/netsurf-browser/netsurf/blob/a32e1a03e1c91ee9f0aa211937dbae7a96831149/content/handlers/html/html.c#L380
349+
pub fn dispatchForDocumentTarget(self: *Window, evt: *parser.Event) !void {
350+
// we assume that this evt has already been dispatched on the document
351+
// and thus the target has already been set to the document.
352+
return self.base.redispatchEvent(evt);
353+
}
337354
};
338355

339356
const TimerCallback = struct {
@@ -491,4 +508,21 @@ test "Browser.HTML.Window" {
491508
.{ "var qm = false; window.queueMicrotask(() => {qm = true });", null },
492509
.{ "qm", "true" },
493510
}, .{});
511+
512+
{
513+
try runner.testCases(&.{
514+
.{
515+
\\ let dcl = false;
516+
\\ window.addEventListener('DOMContentLoaded', (e) => {
517+
\\ dcl = e.target == document;
518+
\\ });
519+
,
520+
null,
521+
},
522+
}, .{});
523+
try runner.dispatchDOMContentLoaded();
524+
try runner.testCases(&.{
525+
.{ "dcl", "true" },
526+
}, .{});
527+
}
494528
}

src/browser/netsurf.zig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,14 @@ pub const EventTargetTBase = extern struct {
846846
internal_type_.* = @intFromEnum(self.internal_target_type);
847847
return c.DOM_NO_ERR;
848848
}
849+
850+
// Called to simulate bubbling from a libdom node (e.g. the Document) to a
851+
// Zig instance (e.g. the Window).
852+
pub fn redispatchEvent(self: *EventTargetTBase, evt: *Event) !void {
853+
var res: bool = undefined;
854+
const err = c._dom_event_target_dispatch(@ptrCast(self), &self.eti, evt, c.DOM_BUBBLING_PHASE, &res);
855+
try DOMErr(err);
856+
}
849857
};
850858

851859
// MouseEvent

src/testing.zig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,12 @@ pub const JsRunner = struct {
474474
return err;
475475
};
476476
}
477+
478+
pub fn dispatchDOMContentLoaded(self: *JsRunner) !void {
479+
const HTMLDocument = @import("browser/html/document.zig").HTMLDocument;
480+
const html_doc = self.page.window.document;
481+
try HTMLDocument.documentIsLoaded(html_doc, self.page);
482+
}
477483
};
478484

479485
const RunnerOpts = struct {

0 commit comments

Comments
 (0)