From 673403f950ee6198956c03c24989438de2e95a4e Mon Sep 17 00:00:00 2001 From: Muki Kiboigo Date: Mon, 25 May 2026 12:31:37 -0700 Subject: [PATCH] properly flush frame after syncRequest eval --- src/browser/ScriptManager.zig | 3 ++ src/browser/ScriptManagerBase.zig | 11 ------- src/network/layer/DeferringLayer.zig | 48 ++++++++++++++++++++++++++-- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/src/browser/ScriptManager.zig b/src/browser/ScriptManager.zig index 6d5d5dfd..b5f41eca 100644 --- a/src/browser/ScriptManager.zig +++ b/src/browser/ScriptManager.zig @@ -288,6 +288,9 @@ pub fn addFromElement(self: *ScriptManager, comptime from_parser: bool, script_e return; } + // This will flush any deferred scripts. + defer self.base.client.deferring_layer.flushFrame(self.base.owner.frameId()); + if (script.status < 200 or script.status > 299) { log.info(.http, "script load error", .{ .status = script.status }); script.executeCallback(comptime .wrap("error")); diff --git a/src/browser/ScriptManagerBase.zig b/src/browser/ScriptManagerBase.zig index 6a437534..6c72fa7a 100644 --- a/src/browser/ScriptManagerBase.zig +++ b/src/browser/ScriptManagerBase.zig @@ -390,17 +390,6 @@ pub fn staticScriptsDone(self: *ScriptManagerBase) void { lp.assert(self.static_scripts_done == false, "ScriptManagerBase.staticScriptsDone", .{}); self.static_scripts_done = true; - const frame_id = self.owner.frameId(); - if (comptime IS_DEBUG) { - const blocking_request_id = self.client.blocking_requests.get(frame_id); - lp.assert( - blocking_request_id == null, - "there should be no blocking request on this frame", - .{ .value = blocking_request_id }, - ); - } - self.client.deferring_layer.flushFrame(frame_id); - self.evaluate(); } diff --git a/src/network/layer/DeferringLayer.zig b/src/network/layer/DeferringLayer.zig index 73ae9cf5..018212e3 100644 --- a/src/network/layer/DeferringLayer.zig +++ b/src/network/layer/DeferringLayer.zig @@ -102,12 +102,17 @@ pub fn flushFrame(self: *DeferringLayer, frame_id: u32) void { while (node) |n| { node = n.next; const ctx: *DeferredContext = @fieldParentPtr("node", n); - if (!ctx.deferring or !ctx.terminal) continue; + if (!ctx.deferring) continue; const deferred_req = ctx.transfer.req; - if (deferred_req.frame_id == frame_id) { + if (deferred_req.frame_id != frame_id) continue; + + if (ctx.terminal) { self.active.remove(n); ctx.fire(); + } else { + ctx.firePartial(); + ctx.deferring = false; } } } @@ -296,4 +301,43 @@ const DeferredContext = struct { } } } + + fn firePartial(self: *DeferredContext) void { + const req = self.transfer.req; + const stable_response = self.stable_resp orelse return; + const response = Response.fromStable(&stable_response); + + for (self.buffered.items) |event| { + switch (event) { + .start => { + self.forward.forwardStart(response) catch |err| { + log.err(.http, "defer part start callback", .{ .err = err, .url = req.url }); + self.forward.forwardErr(err); + return; + }; + }, + .header => { + const proceed = self.forward.forwardHeader(response) catch |err| { + log.err(.http, "defer part header callback", .{ .err = err, .url = req.url }); + self.forward.forwardErr(err); + return; + }; + if (!proceed) { + self.forward.forwardErr(error.Abort); + return; + } + }, + .data => |chunk| { + self.forward.forwardData(response, chunk) catch |err| { + log.err(.http, "defer part data callback", .{ .err = err, .url = req.url }); + self.forward.forwardErr(err); + return; + }; + }, + .done, .err, .shutdown => @panic("firePartial cant fire terminal events"), + } + } + + self.buffered.clearRetainingCapacity(); + } };