From d1d561f5c1dccec9b705ab2428e56fdae780de3d Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Wed, 8 Apr 2026 09:09:25 +0800 Subject: [PATCH] Worker.close() --- src/browser/js/Scheduler.zig | 5 +++++ src/browser/webapi/Worker.zig | 6 +++--- src/browser/webapi/WorkerGlobalScope.zig | 12 ++++++++++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/browser/js/Scheduler.zig b/src/browser/js/Scheduler.zig index d9fb417e..1055c4d0 100644 --- a/src/browser/js/Scheduler.zig +++ b/src/browser/js/Scheduler.zig @@ -52,6 +52,11 @@ pub fn deinit(self: *Scheduler) void { finalizeTasks(&self.high_priority); } +pub fn reset(self: *Scheduler) void { + self.low_priority.clearRetainingCapacity(); + self.high_priority.clearRetainingCapacity(); +} + const AddOpts = struct { name: []const u8 = "", low_priority: bool = false, diff --git a/src/browser/webapi/Worker.zig b/src/browser/webapi/Worker.zig index 82a71ac6..df923458 100644 --- a/src/browser/webapi/Worker.zig +++ b/src/browser/webapi/Worker.zig @@ -82,7 +82,7 @@ pub fn init(url: []const u8, exec: *Execution) !*Worker { log.warn(.js, "invalid blob", .{ .target = "worker" }); return error.BlobNotFound; }; - try self.execute(blob._slice); + try self.loadInitialScript(blob._slice); return self; } @@ -164,10 +164,10 @@ fn httpDoneCallback(ctx: *anyopaque) !void { }); } - try self.execute(script); + try self.loadInitialScript(script); } -fn execute(self: *Worker, script: []const u8) !void { +fn loadInitialScript(self: *Worker, script: []const u8) !void { var ls: js.Local.Scope = undefined; self._worker_scope.js.localScope(&ls); defer ls.deinit(); diff --git a/src/browser/webapi/WorkerGlobalScope.zig b/src/browser/webapi/WorkerGlobalScope.zig index 2512baf5..f8f7ec7f 100644 --- a/src/browser/webapi/WorkerGlobalScope.zig +++ b/src/browser/webapi/WorkerGlobalScope.zig @@ -63,6 +63,7 @@ _worker: *Worker, _event_manager: EventManagerBase, // These fields represent the "Window"-like component of the WGS +_closed: bool = false, _proto: *EventTarget, _console: Console = .init, _crypto: Crypto = .init, @@ -199,6 +200,10 @@ pub fn postMessage(self: *WorkerGlobalScope, data: JS.Value) !void { // Called internally by Worker when it wants to post a message to us pub fn receiveMessage(self: *WorkerGlobalScope, data: JS.Value) !void { + if (self._closed) { + return; + } + const cloned_data: ?JS.Value.Temp = blk: { // Enter our context to clone the message var ls: JS.Local.Scope = undefined; @@ -269,6 +274,12 @@ pub fn unhandledPromiseRejection(self: *WorkerGlobalScope, no_handler: bool, rej } } +pub fn close(self: *WorkerGlobalScope) void { + // TOOD: we should also stop new tasks from being scheduled + self.js.scheduler.reset(); + self._closed = true; +} + pub fn reportError(self: *WorkerGlobalScope, err: JS.Value) !void { const error_event = try ErrorEvent.initTrusted(comptime .wrap("error"), .{ .@"error" = try err.temp(), @@ -414,6 +425,7 @@ pub const JsApi = struct { pub const structuredClone = bridge.function(WorkerGlobalScope.structuredClone, .{}); pub const postMessage = bridge.function(WorkerGlobalScope.postMessage, .{}); pub const reportError = bridge.function(WorkerGlobalScope.reportError, .{}); + pub const close = bridge.function(WorkerGlobalScope.close, .{}); pub const onmessage = bridge.accessor(WorkerGlobalScope.getOnMessage, WorkerGlobalScope.setOnMessage, .{}); pub const onmessageerror = bridge.accessor(WorkerGlobalScope.getOnMessageError, WorkerGlobalScope.setOnMessageError, .{});