diff --git a/src/browser/tests/worker/worker.html b/src/browser/tests/worker/worker.html index 5a8562968..29472fa72 100644 --- a/src/browser/tests/worker/worker.html +++ b/src/browser/tests/worker/worker.html @@ -553,3 +553,42 @@ }); } + + + + diff --git a/src/browser/webapi/SharedWorkerGlobalScope.zig b/src/browser/webapi/SharedWorkerGlobalScope.zig index b7f3b9cbb..2d07bb5be 100644 --- a/src/browser/webapi/SharedWorkerGlobalScope.zig +++ b/src/browser/webapi/SharedWorkerGlobalScope.zig @@ -250,10 +250,14 @@ fn httpErrorCallback(ctx: *anyopaque, err: anyerror) void { self._http_transfer = null; self.releaseScriptArena(); - log.err(.browser, "shared worker fetch error", .{ - .url = self._url, - .err = err, - }); + // TransferCanceled is teardown cancelling a still-inflight script fetch, + // not a load failure. + if (err != error.TransferCanceled) { + log.err(.browser, "shared worker fetch error", .{ + .url = self._url, + .err = err, + }); + } // The worker will never load and onconnect will never be registered. // Drain the buffered connects so they get dispatched (and dropped at the diff --git a/src/browser/webapi/Worker.zig b/src/browser/webapi/Worker.zig index a1c5cd22f..b2cbab0db 100644 --- a/src/browser/webapi/Worker.zig +++ b/src/browser/webapi/Worker.zig @@ -268,10 +268,16 @@ fn httpErrorCallback(ctx: *anyopaque, err: anyerror) void { self._http_transfer = null; self.releaseScriptArena(); - log.err(.browser, "worker fetch error", .{ - .url = self._url, - .err = err, - }); + // TransferCanceled is not a load failure: terminate() (or worker teardown) + // cancelled a still-inflight script fetch. We shouldn't fireErrorEvent + // (or bother logging) + const canceled = err == error.TransferCanceled; + if (!canceled) { + log.err(.browser, "worker fetch error", .{ + .url = self._url, + .err = err, + }); + } // The worker will never load and onmessage will never be registered. // Drain any buffered messages so they get dispatched (and silently @@ -280,7 +286,9 @@ fn httpErrorCallback(ctx: *anyopaque, err: anyerror) void { self._script_loaded = true; self._worker_scope.drainPendingMessages(); - self.fireErrorEvent(@errorName(err), null); + if (!canceled) { + self.fireErrorEvent(@errorName(err), null); + } } fn releaseScriptArena(self: *Worker) void { @@ -481,7 +489,7 @@ pub const JsApi = struct { const testing = @import("../../testing.zig"); test "WebApi: Worker" { - testing.silenceLog(&.{.http}); + testing.silenceLog(&.{.http, .browser, .browser}); // Worker tests chain a worker-script fetch with a dynamic-import fetch // and a cross-context postMessage. The default 2 s assertion budget can