diff --git a/cli/tests/integration/worker_tests.rs b/cli/tests/integration/worker_tests.rs index c158776ee0..bf10578216 100644 --- a/cli/tests/integration/worker_tests.rs +++ b/cli/tests/integration/worker_tests.rs @@ -20,6 +20,20 @@ itest!(worker_nested_error { exit_code: 1, }); +itest!(worker_async_error { + args: "run -A --quiet --reload workers/worker_async_error.ts", + output: "workers/worker_async_error.ts.out", + http_server: true, + exit_code: 1, +}); + +itest!(worker_message_handler_error { + args: "run -A --quiet --reload workers/worker_message_handler_error.ts", + output: "workers/worker_message_handler_error.ts.out", + http_server: true, + exit_code: 1, +}); + itest!(nonexistent_worker { args: "run --allow-read workers/nonexistent_worker.ts", output: "workers/nonexistent_worker.out", diff --git a/cli/tests/testdata/worker_drop_handle_race.js.out b/cli/tests/testdata/worker_drop_handle_race.js.out index 71dfde620b..271e07854b 100644 --- a/cli/tests/testdata/worker_drop_handle_race.js.out +++ b/cli/tests/testdata/worker_drop_handle_race.js.out @@ -4,5 +4,5 @@ error: Uncaught (in worker "") Error at [WILDCARD]/workers/drop_handle_race.js:2:9 at fire (deno:ext/timers/[WILDCARD]) at handleTimerMacrotask (deno:ext/timers/[WILDCARD]) -error: Uncaught (in promise) Error: Unhandled error event reached main worker. +error: Uncaught (in promise) Error: Unhandled error event in child worker. at Worker.#pollControl (deno:runtime/js/11_workers.js:[WILDCARD]) diff --git a/cli/tests/testdata/workers/async_error.ts b/cli/tests/testdata/workers/async_error.ts new file mode 100644 index 0000000000..154b957b11 --- /dev/null +++ b/cli/tests/testdata/workers/async_error.ts @@ -0,0 +1,4 @@ +// deno-lint-ignore require-await +(async () => { + throw new Error("bar"); +})(); diff --git a/cli/tests/testdata/workers/message_handler_error.ts b/cli/tests/testdata/workers/message_handler_error.ts new file mode 100644 index 0000000000..3416faad10 --- /dev/null +++ b/cli/tests/testdata/workers/message_handler_error.ts @@ -0,0 +1,4 @@ +postMessage("ready"); +onmessage = () => { + throw new Error("bar"); +}; diff --git a/cli/tests/testdata/workers/nonexistent_worker.out b/cli/tests/testdata/workers/nonexistent_worker.out index 1651321bcf..99e94bfc9b 100644 --- a/cli/tests/testdata/workers/nonexistent_worker.out +++ b/cli/tests/testdata/workers/nonexistent_worker.out @@ -1,3 +1,3 @@ [WILDCARD]error: Uncaught (in worker "") Cannot resolve module "file:///[WILDCARD]/workers/doesnt_exist.js". -error: Uncaught (in promise) Error: Unhandled error event reached main worker. +error: Uncaught (in promise) Error: Unhandled error event in child worker. at Worker.#pollControl ([WILDCARD]) diff --git a/cli/tests/testdata/workers/permissions_blob_local.ts.out b/cli/tests/testdata/workers/permissions_blob_local.ts.out index 0835777ecd..b35d1d4db5 100644 --- a/cli/tests/testdata/workers/permissions_blob_local.ts.out +++ b/cli/tests/testdata/workers/permissions_blob_local.ts.out @@ -1,4 +1,4 @@ error: Uncaught (in worker "") Requires read access to "[WILDCARD]local_file.ts", run again with the --allow-read flag at blob:null/[WILDCARD]:1:0 -error: Uncaught (in promise) Error: Unhandled error event reached main worker. +error: Uncaught (in promise) Error: Unhandled error event in child worker. at Worker.#pollControl ([WILDCARD]) diff --git a/cli/tests/testdata/workers/permissions_blob_remote.ts.out b/cli/tests/testdata/workers/permissions_blob_remote.ts.out index 2d01458ca4..26936971a6 100644 --- a/cli/tests/testdata/workers/permissions_blob_remote.ts.out +++ b/cli/tests/testdata/workers/permissions_blob_remote.ts.out @@ -1,4 +1,4 @@ error: Uncaught (in worker "") Requires net access to "example.com", run again with the --allow-net flag at blob:null/[WILDCARD]:1:0 -error: Uncaught (in promise) Error: Unhandled error event reached main worker. +error: Uncaught (in promise) Error: Unhandled error event in child worker. at Worker.#pollControl ([WILDCARD]) diff --git a/cli/tests/testdata/workers/permissions_data_local.ts.out b/cli/tests/testdata/workers/permissions_data_local.ts.out index 2a6be2b57e..1e8c5fffa4 100644 --- a/cli/tests/testdata/workers/permissions_data_local.ts.out +++ b/cli/tests/testdata/workers/permissions_data_local.ts.out @@ -1,4 +1,4 @@ error: Uncaught (in worker "") Requires read access to "[WILDCARD]local_file.ts", run again with the --allow-read flag at data:application/javascript;base64,[WILDCARD]:1:0 -error: Uncaught (in promise) Error: Unhandled error event reached main worker. +error: Uncaught (in promise) Error: Unhandled error event in child worker. at Worker.#pollControl ([WILDCARD]) diff --git a/cli/tests/testdata/workers/permissions_data_remote.ts.out b/cli/tests/testdata/workers/permissions_data_remote.ts.out index 90677892a9..92eadf2842 100644 --- a/cli/tests/testdata/workers/permissions_data_remote.ts.out +++ b/cli/tests/testdata/workers/permissions_data_remote.ts.out @@ -1,4 +1,4 @@ error: Uncaught (in worker "") Requires net access to "example.com", run again with the --allow-net flag at data:application/javascript;base64,aW1wb3J0ICJodHRwczovL2V4YW1wbGUuY29tL3NvbWUvZmlsZS50cyI7:1:0 -error: Uncaught (in promise) Error: Unhandled error event reached main worker. +error: Uncaught (in promise) Error: Unhandled error event in child worker. at Worker.#pollControl ([WILDCARD]) diff --git a/cli/tests/testdata/workers/permissions_dynamic_remote.ts.out b/cli/tests/testdata/workers/permissions_dynamic_remote.ts.out index 3c4523ce0a..e5015abff4 100644 --- a/cli/tests/testdata/workers/permissions_dynamic_remote.ts.out +++ b/cli/tests/testdata/workers/permissions_dynamic_remote.ts.out @@ -2,5 +2,5 @@ error: Uncaught (in worker "") (in promise) TypeError: Requires net access to "e await import("https://example.com/some/file.ts"); ^ at async http://localhost:4545/workers/dynamic_remote.ts:2:1 -[WILDCARD]error: Uncaught (in promise) Error: Unhandled error event reached main worker. +[WILDCARD]error: Uncaught (in promise) Error: Unhandled error event in child worker. at Worker.#pollControl ([WILDCARD]) diff --git a/cli/tests/testdata/workers/permissions_remote_remote.ts.out b/cli/tests/testdata/workers/permissions_remote_remote.ts.out index 94a92c72d6..8998891a39 100644 --- a/cli/tests/testdata/workers/permissions_remote_remote.ts.out +++ b/cli/tests/testdata/workers/permissions_remote_remote.ts.out @@ -1,4 +1,4 @@ error: Uncaught (in worker "") Requires net access to "example.com", run again with the --allow-net flag at http://localhost:4545/workers/static_remote.ts:2:0 -error: Uncaught (in promise) Error: Unhandled error event reached main worker. +error: Uncaught (in promise) Error: Unhandled error event in child worker. at Worker.#pollControl ([WILDCARD]) diff --git a/cli/tests/testdata/workers/test.ts b/cli/tests/testdata/workers/test.ts index 9d3855fe11..effd104f5a 100644 --- a/cli/tests/testdata/workers/test.ts +++ b/cli/tests/testdata/workers/test.ts @@ -34,11 +34,6 @@ Deno.test({ tsWorker.postMessage("Hello World"); }; - jsWorker.onerror = (e: Event) => { - e.preventDefault(); - jsWorker.postMessage("Hello World"); - }; - jsWorker.postMessage("Hello World"); await promise; tsWorker.terminate(); diff --git a/cli/tests/testdata/workers/test_worker.js b/cli/tests/testdata/workers/test_worker.js index 4260975a66..2b2d1eeecf 100644 --- a/cli/tests/testdata/workers/test_worker.js +++ b/cli/tests/testdata/workers/test_worker.js @@ -1,19 +1,8 @@ -let thrown = false; - if (self.name !== "") { throw Error(`Bad worker name: ${self.name}, expected empty string.`); } onmessage = function (e) { - if (thrown === false) { - thrown = true; - throw new SyntaxError("[test error]"); - } - postMessage(e.data); close(); }; - -onerror = function () { - return false; -}; diff --git a/cli/tests/testdata/workers/worker_async_error.ts b/cli/tests/testdata/workers/worker_async_error.ts new file mode 100644 index 0000000000..05d2ffcb6e --- /dev/null +++ b/cli/tests/testdata/workers/worker_async_error.ts @@ -0,0 +1,5 @@ +const worker = new Worker( + new URL("async_error.ts", import.meta.url).href, + { type: "module", name: "foo" }, +); +setTimeout(() => worker.terminate(), 30000); diff --git a/cli/tests/testdata/workers/worker_async_error.ts.out b/cli/tests/testdata/workers/worker_async_error.ts.out new file mode 100644 index 0000000000..0a05534c5f --- /dev/null +++ b/cli/tests/testdata/workers/worker_async_error.ts.out @@ -0,0 +1,7 @@ +error: Uncaught (in worker "foo") (in promise) Error: bar + throw new Error("bar"); + ^ + at [WILDCARD]/async_error.ts:[WILDCARD] + at [WILDCARD]/async_error.ts:[WILDCARD] +error: Uncaught (in promise) Error: Unhandled error event in child worker. + at Worker.#pollControl ([WILDCARD]) diff --git a/cli/tests/testdata/workers/worker_error.ts.out b/cli/tests/testdata/workers/worker_error.ts.out index 4a8e92f00a..cb0a025507 100644 --- a/cli/tests/testdata/workers/worker_error.ts.out +++ b/cli/tests/testdata/workers/worker_error.ts.out @@ -1,5 +1,5 @@ [WILDCARD]error: Uncaught (in worker "bar") Error: foo[WILDCARD] at foo ([WILDCARD]) at [WILDCARD] -error: Uncaught (in promise) Error: Unhandled error event reached main worker. +error: Uncaught (in promise) Error: Unhandled error event in child worker. at Worker.#pollControl ([WILDCARD]) diff --git a/cli/tests/testdata/workers/worker_message_handler_error.ts b/cli/tests/testdata/workers/worker_message_handler_error.ts new file mode 100644 index 0000000000..eb538c1ce2 --- /dev/null +++ b/cli/tests/testdata/workers/worker_message_handler_error.ts @@ -0,0 +1,8 @@ +const worker = new Worker( + new URL("message_handler_error.ts", import.meta.url).href, + { type: "module", name: "foo" }, +); +worker.onmessage = () => { + worker.postMessage("ready"); +}; +setTimeout(() => worker.terminate(), 30000); diff --git a/cli/tests/testdata/workers/worker_message_handler_error.ts.out b/cli/tests/testdata/workers/worker_message_handler_error.ts.out new file mode 100644 index 0000000000..56458d5e44 --- /dev/null +++ b/cli/tests/testdata/workers/worker_message_handler_error.ts.out @@ -0,0 +1,7 @@ +error: Uncaught (in worker "foo") (in promise) Error: bar + throw new Error("bar"); + ^ + at onmessage ([WILDCARD]/message_handler_error.ts:[WILDCARD]) + at [WILDCARD] +error: Uncaught (in promise) Error: Unhandled error event in child worker. + at Worker.#pollControl ([WILDCARD]) diff --git a/cli/tests/testdata/workers/worker_nested_error.ts.out b/cli/tests/testdata/workers/worker_nested_error.ts.out index 4a8e92f00a..5c978ca9bb 100644 --- a/cli/tests/testdata/workers/worker_nested_error.ts.out +++ b/cli/tests/testdata/workers/worker_nested_error.ts.out @@ -1,5 +1,9 @@ [WILDCARD]error: Uncaught (in worker "bar") Error: foo[WILDCARD] - at foo ([WILDCARD]) - at [WILDCARD] -error: Uncaught (in promise) Error: Unhandled error event reached main worker. + throw new Error("foo"); + ^ + at foo ([WILDCARD]/workers/error.ts:[WILDCARD]) + at [WILDCARD]/workers/error.ts:[WILDCARD] +error: Uncaught (in worker "baz") (in promise) Error: Unhandled error event in child worker. + at Worker.#pollControl ([WILDCARD]) +error: Uncaught (in promise) Error: Unhandled error event in child worker. at Worker.#pollControl ([WILDCARD]) diff --git a/runtime/js/11_workers.js b/runtime/js/11_workers.js index 2b908b9f84..59ae7371da 100644 --- a/runtime/js/11_workers.js +++ b/runtime/js/11_workers.js @@ -14,7 +14,6 @@ } = window.__bootstrap.primordials; const webidl = window.__bootstrap.webidl; const { URL } = window.__bootstrap.url; - const { Window } = window.__bootstrap.globalInterfaces; const { getLocationHref } = window.__bootstrap.location; const { log, pathFromURL } = window.__bootstrap.util; const { defineEventHandler } = window.__bootstrap.webUtil; @@ -265,14 +264,7 @@ } /* falls through */ case 2: { // Error if (!this.#handleError(data)) { - if (globalThis instanceof Window) { - throw new Error("Unhandled error event reached main worker."); - } else { - core.opSync( - "op_worker_unhandled_error", - data.message, - ); - } + throw new Error("Unhandled error event in child worker."); } break; } diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js index 9bbc069719..152430a76b 100644 --- a/runtime/js/99_main.js +++ b/runtime/js/99_main.js @@ -157,10 +157,7 @@ delete Object.prototype.__proto__; globalDispatchEvent(errorEvent); if (!errorEvent.defaultPrevented) { - core.opSync( - "op_worker_unhandled_error", - e.message, - ); + throw e; } } } diff --git a/runtime/ops/web_worker.rs b/runtime/ops/web_worker.rs index 8439e43844..14ebb8d6e7 100644 --- a/runtime/ops/web_worker.rs +++ b/runtime/ops/web_worker.rs @@ -4,8 +4,6 @@ mod sync_fetch; use crate::web_worker::WebWorkerInternalHandle; use crate::web_worker::WebWorkerType; -use crate::web_worker::WorkerControlEvent; -use deno_core::error::generic_error; use deno_core::error::AnyError; use deno_core::op_async; use deno_core::op_sync; @@ -25,11 +23,6 @@ pub fn init() -> Extension { ("op_worker_recv_message", op_async(op_worker_recv_message)), // Notify host that guest worker closes. ("op_worker_close", op_sync(op_worker_close)), - // Notify host that guest worker has unhandled error. - ( - "op_worker_unhandled_error", - op_sync(op_worker_unhandled_error), - ), ("op_worker_get_type", op_sync(op_worker_get_type)), ("op_worker_sync_fetch", op_sync(op_worker_sync_fetch)), ]) @@ -70,23 +63,6 @@ fn op_worker_close(state: &mut OpState, _: (), _: ()) -> Result<(), AnyError> { Ok(()) } -/// A worker that encounters an uncaught error will pass this error -/// to its parent worker using this op. The parent worker will use -/// this same op to pass the error to its own parent (in case -/// `e.preventDefault()` was not called in `worker.onerror`). This -/// is done until the error reaches the root/ main worker. -fn op_worker_unhandled_error( - state: &mut OpState, - message: String, - _: (), -) -> Result<(), AnyError> { - let sender = state.borrow::().clone(); - sender - .post_event(WorkerControlEvent::Error(generic_error(message))) - .expect("Failed to propagate error event to parent worker"); - Ok(()) -} - fn op_worker_get_type( state: &mut OpState, _: (), diff --git a/runtime/web_worker.rs b/runtime/web_worker.rs index 98a8ae0769..1ca5deb7a8 100644 --- a/runtime/web_worker.rs +++ b/runtime/web_worker.rs @@ -525,15 +525,8 @@ impl WebWorker { return Poll::Ready(Ok(())); } - // In case of an error, pass to parent without terminating worker if let Err(e) = r { - print_worker_error(e.to_string(), &self.name); - let handle = self.internal_handle.clone(); - handle - .post_event(WorkerControlEvent::Error(e)) - .expect("Failed to post message to host"); - - return Poll::Pending; + return Poll::Ready(Err(e)); } panic!( @@ -593,6 +586,12 @@ pub fn run_web_worker( return Ok(()); } + let result = if result.is_ok() { + worker.run_event_loop(true).await + } else { + result + }; + if let Err(e) = result { print_worker_error(e.to_string(), &name); internal_handle @@ -603,7 +602,6 @@ pub fn run_web_worker( return Ok(()); } - let result = worker.run_event_loop(true).await; debug!("Worker thread shuts down {}", &name); result };