diff --git a/src/browser/ScriptManager.zig b/src/browser/ScriptManager.zig index a0437c64a..08fced465 100644 --- a/src/browser/ScriptManager.zig +++ b/src/browser/ScriptManager.zig @@ -199,7 +199,7 @@ fn waitForPreload(self: *ScriptManager, url: [:0]const u8) ?*Script { _ = client.tickSync(200) catch return null; continue; }, - .done => |script| { + .done, .failed => |script| { // Preload scripts are single-use. We return it and it becomes // the caller's responsibility to free. _ = self.preloaded_scripts.remove(url); @@ -318,7 +318,7 @@ pub fn addFromElement(self: *ScriptManager, comptime from_parser: bool, script_e if (mode != .normal) { var preloaded = self.takePreload(remote_url); if (preloaded == null and kind == .module) { - preloaded = self.base.takeModuleHint(remote_url); + preloaded = try self.base.takeModuleHint(remote_url); } if (preloaded) |pre| { if (comptime lp.IS_DEBUG) { @@ -545,6 +545,7 @@ const PreloadedScript = struct { const State = union(enum) { loading: *Script, done: *Script, + failed: *Script, }; pub fn deinit(self: PreloadedScript) void { @@ -583,10 +584,12 @@ const PreloadedScript = struct { log.warn(.http, "script fetch error", .{ .err = err, .req = script.url, .extra = "preload", .status = script.status }); } + script.status = 0; // status == 0 is correctly treated as an error throughout + script.complete = true; + const self: *ScriptManager = @fieldParentPtr("base", script.manager); - _ = self.preloaded_scripts.remove(script.url); + self.preloaded_scripts.getPtr(script.url).?.state = .{ .failed = script }; script.queueHintEvent(.@"error"); - script.deinit(); } // Owner-driven teardown killed this preload fetch via Transfer.kill, which @@ -726,6 +729,52 @@ test "ScriptManager: preload whose submit fails synchronously releases its arena const url = "http://127.0.0.1:9582/fails-at-submit.js"; // A fetch was started (and failed), so the hint's error event fires. try testing.expectEqual(true, try sm.preloadScript(null, url)); - // errorCallback consumed the entry; nothing dangles in the map. - try testing.expectEqual(false, sm.preloaded_scripts.contains(url)); + // The failed entry stays for a