Prevent double-execution of script tags.

Depends on https://github.com/lightpanda-io/libdom/pull/31
This commit is contained in:
Karl Seguin
2025-07-22 07:54:39 +08:00
parent 0b793d82fe
commit ca574df3be
3 changed files with 34 additions and 1 deletions

View File

@@ -2885,3 +2885,15 @@ pub fn buttonGetType(button: *Button) ![]const u8 {
const s = s_ orelse return "button";
return strToData(s);
}
pub fn scriptGetProcessed(script: *Script) !bool {
var processed: bool = false;
const err = c.dom_html_script_element_get_processed(script, &processed);
try DOMErr(err);
return processed;
}
pub fn scriptSetProcessed(script: *Script, processed: bool) !void {
const err = c.dom_html_script_element_set_processed(script, processed);
try DOMErr(err);
}

View File

@@ -451,6 +451,12 @@ pub const Page = struct {
// if no src is present, we evaluate the text source.
// https://html.spec.whatwg.org/multipage/scripting.html#script-processing-model
fn tryEvalScript(self: *Page, script: *const Script) !void {
if (try script.alreadyProcessed()) {
return;
}
try script.markAsProcessed();
const html_doc = self.window.document;
try parser.documentHTMLSetCurrentScript(html_doc, @ptrCast(script.element));
@@ -998,6 +1004,21 @@ const Script = struct {
return null;
}
// If a script tag gets dynamically created and added to the dom:
// document.getElementsByTagName('head')[0].appendChild(script)
// that script tag will immediately get executed by our scriptAddedCallback.
// However, if the location where the script tag is inserted happens to be
// below where processHTMLDoc curently is, then we'll re-run that same script
// again in processHTMLDoc. This flag is used to let us know if a specific
// <script> has already been processed.
fn alreadyProcessed(self: *const Script) !bool {
return parser.scriptGetProcessed(@ptrCast(self.element));
}
fn markAsProcessed(self: *const Script) !void {
return parser.scriptSetProcessed(@ptrCast(self.element), true);
}
fn eval(self: *const Script, page: *Page, body: []const u8) !void {
var try_catch: Env.TryCatch = undefined;
try_catch.init(page.main_context);