diff --git a/src/browser/HttpClient.zig b/src/browser/HttpClient.zig index 4006a73b..6cac364c 100644 --- a/src/browser/HttpClient.zig +++ b/src/browser/HttpClient.zig @@ -511,6 +511,12 @@ fn requestT(self: *Client, req: Request, owner: ?*Owner) !*Transfer { return transfer; } +pub fn waitFor(self: *Client, ctx: anytype, comptime isDone: fn (@TypeOf(ctx)) bool) !void { + while (!isDone(ctx)) { + try self.tick(200, .sync_wait); + } +} + const SyncContext = struct { allocator: Allocator, completion: union(enum) { @@ -574,17 +580,22 @@ pub fn syncRequest(self: *Client, allocator: Allocator, req: Request) !SyncRespo r.shutdown_callback = SyncContext.shutdownCallback; const transfer = try self.requestT(r, null); - while (sync_ctx.completion == .in_progress) { - self.tick(200, .sync_wait) catch |err| { - if (sync_ctx.completion == .in_progress) { - // tick failed for a reason unrelated to our transfer (likely OOM or - // client disconnect). transfer.req.ctx points at &sync_ctx on this - // stack — abort to sever that reference before we return - transfer.abort(err); + self.waitFor( + &sync_ctx, + struct { + fn done(ctx: *SyncContext) bool { + return ctx.completion != .in_progress; } - return err; - }; - } + }.done, + ) catch |err| { + if (sync_ctx.completion == .in_progress) { + // tick failed for a reason unrelated to our transfer (likely OOM or + // client disconnect). transfer.req.ctx points at &sync_ctx on this + // stack — abort to sever that reference before we return + transfer.abort(err); + } + return err; + }; switch (sync_ctx.completion) { .in_progress => @panic("Impossible to be in progress here."), diff --git a/src/browser/ScriptManagerBase.zig b/src/browser/ScriptManagerBase.zig index 02e6dbdf..fb3c26c0 100644 --- a/src/browser/ScriptManagerBase.zig +++ b/src/browser/ScriptManagerBase.zig @@ -296,32 +296,32 @@ pub fn waitForImport(self: *ScriptManagerBase, url: [:0]const u8) !ModuleSource self.is_evaluating = true; defer self.is_evaluating = was_evaluating; - var client = self.client; - while (true) { - switch (entry.value_ptr.state) { - .loading => { - _ = try client.tick(200, .sync_wait); - continue; - }, - .done => |script| { - var shared = false; - const buffer = entry.value_ptr.buffer; - const waiters = entry.value_ptr.waiters; - - if (waiters == 1) { - self.imported_modules.removeByPtr(entry.key_ptr); - } else { - shared = true; - entry.value_ptr.waiters = waiters - 1; - } - return .{ - .buffer = buffer, - .shared = shared, - .script = script, - }; - }, - .err => return error.Failed, + try self.client.waitFor(entry.value_ptr, struct { + fn done(m: *ImportedModule) bool { + return m.state != .loading; } + }.done); + + switch (entry.value_ptr.state) { + .loading => @panic("Impossible to be loading here."), + .done => |script| { + var shared = false; + const buffer = entry.value_ptr.buffer; + const waiters = entry.value_ptr.waiters; + + if (waiters == 1) { + self.imported_modules.removeByPtr(entry.key_ptr); + } else { + shared = true; + entry.value_ptr.waiters = waiters - 1; + } + return .{ + .buffer = buffer, + .shared = shared, + .script = script, + }; + }, + .err => return error.Failed, } }