From 7f9e309ae8a5744bfa5ab30106edb77c864c2754 Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Mon, 4 Aug 2025 17:56:52 +0800 Subject: [PATCH] Shutdown clean async scripts Set parent current script --- src/browser/ScriptManager.zig | 70 +++++++++++++++++------------------ src/browser/page.zig | 6 +++ src/http/Http.zig | 7 ++-- src/main.zig | 2 + 4 files changed, 44 insertions(+), 41 deletions(-) diff --git a/src/browser/ScriptManager.zig b/src/browser/ScriptManager.zig index 8705ad08..2807a40d 100644 --- a/src/browser/ScriptManager.zig +++ b/src/browser/ScriptManager.zig @@ -37,16 +37,16 @@ page: *Page, // Only once this is true can deferred scripts be run static_scripts_done: bool, -// when async_count == 0 and static_script_done == true, the document is completed -// loading (i.e. page.documentIsComplete should be called). -async_count: usize, +// List of async scripts. We don't care about the execution order of these, but +// on shutdown/abort, we need to co cleanup any pending ones. +asyncs: OrderList, // Normal scripts (non-deffered & non-async). These must be executed ni order scripts: OrderList, // List of deferred scripts. These must be executed in order, but only once // dom_loaded == true, -deferred: OrderList, +deferreds: OrderList, client: *HttpClient, allocator: Allocator, @@ -60,9 +60,9 @@ pub fn init(browser: *Browser, page: *Page) ScriptManager { const allocator = browser.allocator; return .{ .page = page, + .asyncs = .{}, .scripts = .{}, - .deferred = .{}, - .async_count = 0, + .deferreds = .{}, .allocator = allocator, .client = browser.http_client, .static_scripts_done = false, @@ -77,8 +77,9 @@ pub fn deinit(self: *ScriptManager) void { } pub fn reset(self: *ScriptManager) void { + self.clearList(&self.asyncs); self.clearList(&self.scripts); - self.clearList(&self.deferred); + self.clearList(&self.deferreds); self.static_scripts_done = false; } @@ -200,15 +201,9 @@ pub fn addFromElement(self: *ScriptManager, element: *parser.Element) !void { return; } - if (self.getList(&pending_script.script)) |list| { - pending_script.node = .{.data = pending_script}; - list.append(&pending_script.node); - } else { - // async scripts don't get added to a list, because we can execute - // them in any order - std.debug.assert(script.is_async); - self.async_count += 1; - } + const list = self.getList(&pending_script.script); + pending_script.node = .{ .data = pending_script }; + list.append(&pending_script.node); errdefer pending_script.deinit(); @@ -282,7 +277,7 @@ fn evaluate(self: *ScriptManager) void { return; } - while (self.deferred.first) |n| { + while (self.deferreds.first) |n| { var pending_script = n.data; if (pending_script.complete == false) { return; @@ -295,7 +290,7 @@ fn evaluate(self: *ScriptManager) void { // state changes (this ultimately triggers the DOMContentLoaded event) page.documentIsLoaded(); - if (self.async_count == 0) { + if (self.asyncs.first == null) { // if we're here, then its like `asyncDone` // 1 - there are no async scripts pending // 2 - we checkecked static_scripts_done == true above @@ -306,28 +301,26 @@ fn evaluate(self: *ScriptManager) void { } pub fn isDone(self: *const ScriptManager) bool { - return self.async_count == 0 and // there are no more async scripts + return self.asyncs.first == null and // there are no more async scripts self.static_scripts_done and // and we've finished parsing the HTML to queue all self.scripts.first == null and // and there are no more