From f0ca9728aef7a97792c27895dbf35b76af551b44 Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Tue, 26 Aug 2025 13:10:55 +0800 Subject: [PATCH] Support dynamic scripts which are added to the DOM before src is set This should load the "src.js": ``` const s = document.createElement('script'); document.getElementsByTagName('body')[0].appendChild(s); s.src = "src.js" ``` Notice that src is set AFTER the element is added to the DOM. This PR enables the above, by 1 - skipping dynamically added scripts which don't have a src 2 - trying to load a script whenever `set_src` is called. (2) is safe because the ScriptManager already prevents scripts from being processed multiple times. Additionally, not only can the src be set after the script is added to the DOM, but onload and onerror can be set after the src: ``` s.src = "src.js" s.onload = ...; s.onerror = ...; ``` This PR also delays reading the onload/onerror callbacks until the script is done loading. This behavior is seen on reddit. --- src/browser/ScriptManager.zig | 48 +++++++++++++---------------------- src/browser/events/event.zig | 1 - src/browser/html/elements.zig | 21 +++++++++++---- src/browser/page.zig | 11 +++++++- 4 files changed, 44 insertions(+), 37 deletions(-) diff --git a/src/browser/ScriptManager.zig b/src/browser/ScriptManager.zig index bbed5633..e6f3bc93 100644 --- a/src/browser/ScriptManager.zig +++ b/src/browser/ScriptManager.zig @@ -147,32 +147,7 @@ pub fn addFromElement(self: *ScriptManager, element: *parser.Element) !void { return; }; - var onload: ?Script.Callback = null; - var onerror: ?Script.Callback = null; - const page = self.page; - if (page.getNodeState(@ptrCast(element))) |se| { - // if the script has a node state, then it was dynamically added and thus - // the onload/onerror were saved in the state (if there are any) - if (se.onload) |function| { - onload = .{ .function = function }; - } - if (se.onerror) |function| { - onerror = .{ .function = function }; - } - } else { - // if the script has no node state, then it could still be dynamically - // added (could have been dynamically added, but no attributes were set - // which required a node state to be created) or it could be a inline - //