mirror of
https://github.com/denoland/deno.git
synced 2025-01-21 21:50:00 -05:00
fix(runtime/js/workers): throw errors instead of using an op (#12249)
This commit is contained in:
parent
c0b6c0eea5
commit
b354eaa247
23 changed files with 74 additions and 74 deletions
|
@ -20,6 +20,20 @@ itest!(worker_nested_error {
|
||||||
exit_code: 1,
|
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 {
|
itest!(nonexistent_worker {
|
||||||
args: "run --allow-read workers/nonexistent_worker.ts",
|
args: "run --allow-read workers/nonexistent_worker.ts",
|
||||||
output: "workers/nonexistent_worker.out",
|
output: "workers/nonexistent_worker.out",
|
||||||
|
|
|
@ -4,5 +4,5 @@ error: Uncaught (in worker "") Error
|
||||||
at [WILDCARD]/workers/drop_handle_race.js:2:9
|
at [WILDCARD]/workers/drop_handle_race.js:2:9
|
||||||
at fire (deno:ext/timers/[WILDCARD])
|
at fire (deno:ext/timers/[WILDCARD])
|
||||||
at handleTimerMacrotask (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])
|
at Worker.#pollControl (deno:runtime/js/11_workers.js:[WILDCARD])
|
||||||
|
|
4
cli/tests/testdata/workers/async_error.ts
vendored
Normal file
4
cli/tests/testdata/workers/async_error.ts
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
// deno-lint-ignore require-await
|
||||||
|
(async () => {
|
||||||
|
throw new Error("bar");
|
||||||
|
})();
|
4
cli/tests/testdata/workers/message_handler_error.ts
vendored
Normal file
4
cli/tests/testdata/workers/message_handler_error.ts
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
postMessage("ready");
|
||||||
|
onmessage = () => {
|
||||||
|
throw new Error("bar");
|
||||||
|
};
|
|
@ -1,3 +1,3 @@
|
||||||
[WILDCARD]error: Uncaught (in worker "") Cannot resolve module "file:///[WILDCARD]/workers/doesnt_exist.js".
|
[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])
|
at Worker.#pollControl ([WILDCARD])
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Uncaught (in worker "") Requires read access to "[WILDCARD]local_file.ts", run again with the --allow-read flag
|
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
|
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])
|
at Worker.#pollControl ([WILDCARD])
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Uncaught (in worker "") Requires net access to "example.com", run again with the --allow-net flag
|
error: Uncaught (in worker "") Requires net access to "example.com", run again with the --allow-net flag
|
||||||
at blob:null/[WILDCARD]:1:0
|
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])
|
at Worker.#pollControl ([WILDCARD])
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Uncaught (in worker "") Requires read access to "[WILDCARD]local_file.ts", run again with the --allow-read flag
|
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
|
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])
|
at Worker.#pollControl ([WILDCARD])
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Uncaught (in worker "") Requires net access to "example.com", run again with the --allow-net flag
|
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
|
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])
|
at Worker.#pollControl ([WILDCARD])
|
||||||
|
|
|
@ -2,5 +2,5 @@ error: Uncaught (in worker "") (in promise) TypeError: Requires net access to "e
|
||||||
await import("https://example.com/some/file.ts");
|
await import("https://example.com/some/file.ts");
|
||||||
^
|
^
|
||||||
at async http://localhost:4545/workers/dynamic_remote.ts:2:1
|
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])
|
at Worker.#pollControl ([WILDCARD])
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Uncaught (in worker "") Requires net access to "example.com", run again with the --allow-net flag
|
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
|
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])
|
at Worker.#pollControl ([WILDCARD])
|
||||||
|
|
5
cli/tests/testdata/workers/test.ts
vendored
5
cli/tests/testdata/workers/test.ts
vendored
|
@ -34,11 +34,6 @@ Deno.test({
|
||||||
tsWorker.postMessage("Hello World");
|
tsWorker.postMessage("Hello World");
|
||||||
};
|
};
|
||||||
|
|
||||||
jsWorker.onerror = (e: Event) => {
|
|
||||||
e.preventDefault();
|
|
||||||
jsWorker.postMessage("Hello World");
|
|
||||||
};
|
|
||||||
|
|
||||||
jsWorker.postMessage("Hello World");
|
jsWorker.postMessage("Hello World");
|
||||||
await promise;
|
await promise;
|
||||||
tsWorker.terminate();
|
tsWorker.terminate();
|
||||||
|
|
11
cli/tests/testdata/workers/test_worker.js
vendored
11
cli/tests/testdata/workers/test_worker.js
vendored
|
@ -1,19 +1,8 @@
|
||||||
let thrown = false;
|
|
||||||
|
|
||||||
if (self.name !== "") {
|
if (self.name !== "") {
|
||||||
throw Error(`Bad worker name: ${self.name}, expected empty string.`);
|
throw Error(`Bad worker name: ${self.name}, expected empty string.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
onmessage = function (e) {
|
onmessage = function (e) {
|
||||||
if (thrown === false) {
|
|
||||||
thrown = true;
|
|
||||||
throw new SyntaxError("[test error]");
|
|
||||||
}
|
|
||||||
|
|
||||||
postMessage(e.data);
|
postMessage(e.data);
|
||||||
close();
|
close();
|
||||||
};
|
};
|
||||||
|
|
||||||
onerror = function () {
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
5
cli/tests/testdata/workers/worker_async_error.ts
vendored
Normal file
5
cli/tests/testdata/workers/worker_async_error.ts
vendored
Normal file
|
@ -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);
|
7
cli/tests/testdata/workers/worker_async_error.ts.out
vendored
Normal file
7
cli/tests/testdata/workers/worker_async_error.ts.out
vendored
Normal file
|
@ -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])
|
|
@ -1,5 +1,5 @@
|
||||||
[WILDCARD]error: Uncaught (in worker "bar") Error: foo[WILDCARD]
|
[WILDCARD]error: Uncaught (in worker "bar") Error: foo[WILDCARD]
|
||||||
at foo ([WILDCARD])
|
at foo ([WILDCARD])
|
||||||
at [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])
|
at Worker.#pollControl ([WILDCARD])
|
||||||
|
|
8
cli/tests/testdata/workers/worker_message_handler_error.ts
vendored
Normal file
8
cli/tests/testdata/workers/worker_message_handler_error.ts
vendored
Normal file
|
@ -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);
|
7
cli/tests/testdata/workers/worker_message_handler_error.ts.out
vendored
Normal file
7
cli/tests/testdata/workers/worker_message_handler_error.ts.out
vendored
Normal file
|
@ -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])
|
|
@ -1,5 +1,9 @@
|
||||||
[WILDCARD]error: Uncaught (in worker "bar") Error: foo[WILDCARD]
|
[WILDCARD]error: Uncaught (in worker "bar") Error: foo[WILDCARD]
|
||||||
at foo ([WILDCARD])
|
throw new Error("foo");
|
||||||
at [WILDCARD]
|
^
|
||||||
error: Uncaught (in promise) Error: Unhandled error event reached main worker.
|
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])
|
at Worker.#pollControl ([WILDCARD])
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
} = window.__bootstrap.primordials;
|
} = window.__bootstrap.primordials;
|
||||||
const webidl = window.__bootstrap.webidl;
|
const webidl = window.__bootstrap.webidl;
|
||||||
const { URL } = window.__bootstrap.url;
|
const { URL } = window.__bootstrap.url;
|
||||||
const { Window } = window.__bootstrap.globalInterfaces;
|
|
||||||
const { getLocationHref } = window.__bootstrap.location;
|
const { getLocationHref } = window.__bootstrap.location;
|
||||||
const { log, pathFromURL } = window.__bootstrap.util;
|
const { log, pathFromURL } = window.__bootstrap.util;
|
||||||
const { defineEventHandler } = window.__bootstrap.webUtil;
|
const { defineEventHandler } = window.__bootstrap.webUtil;
|
||||||
|
@ -265,14 +264,7 @@
|
||||||
} /* falls through */
|
} /* falls through */
|
||||||
case 2: { // Error
|
case 2: { // Error
|
||||||
if (!this.#handleError(data)) {
|
if (!this.#handleError(data)) {
|
||||||
if (globalThis instanceof Window) {
|
throw new Error("Unhandled error event in child worker.");
|
||||||
throw new Error("Unhandled error event reached main worker.");
|
|
||||||
} else {
|
|
||||||
core.opSync(
|
|
||||||
"op_worker_unhandled_error",
|
|
||||||
data.message,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,10 +157,7 @@ delete Object.prototype.__proto__;
|
||||||
|
|
||||||
globalDispatchEvent(errorEvent);
|
globalDispatchEvent(errorEvent);
|
||||||
if (!errorEvent.defaultPrevented) {
|
if (!errorEvent.defaultPrevented) {
|
||||||
core.opSync(
|
throw e;
|
||||||
"op_worker_unhandled_error",
|
|
||||||
e.message,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,6 @@ mod sync_fetch;
|
||||||
|
|
||||||
use crate::web_worker::WebWorkerInternalHandle;
|
use crate::web_worker::WebWorkerInternalHandle;
|
||||||
use crate::web_worker::WebWorkerType;
|
use crate::web_worker::WebWorkerType;
|
||||||
use crate::web_worker::WorkerControlEvent;
|
|
||||||
use deno_core::error::generic_error;
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::op_async;
|
use deno_core::op_async;
|
||||||
use deno_core::op_sync;
|
use deno_core::op_sync;
|
||||||
|
@ -25,11 +23,6 @@ pub fn init() -> Extension {
|
||||||
("op_worker_recv_message", op_async(op_worker_recv_message)),
|
("op_worker_recv_message", op_async(op_worker_recv_message)),
|
||||||
// Notify host that guest worker closes.
|
// Notify host that guest worker closes.
|
||||||
("op_worker_close", op_sync(op_worker_close)),
|
("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_get_type", op_sync(op_worker_get_type)),
|
||||||
("op_worker_sync_fetch", op_sync(op_worker_sync_fetch)),
|
("op_worker_sync_fetch", op_sync(op_worker_sync_fetch)),
|
||||||
])
|
])
|
||||||
|
@ -70,23 +63,6 @@ fn op_worker_close(state: &mut OpState, _: (), _: ()) -> Result<(), AnyError> {
|
||||||
Ok(())
|
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::<WebWorkerInternalHandle>().clone();
|
|
||||||
sender
|
|
||||||
.post_event(WorkerControlEvent::Error(generic_error(message)))
|
|
||||||
.expect("Failed to propagate error event to parent worker");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn op_worker_get_type(
|
fn op_worker_get_type(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
_: (),
|
_: (),
|
||||||
|
|
|
@ -525,15 +525,8 @@ impl WebWorker {
|
||||||
return Poll::Ready(Ok(()));
|
return Poll::Ready(Ok(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// In case of an error, pass to parent without terminating worker
|
|
||||||
if let Err(e) = r {
|
if let Err(e) = r {
|
||||||
print_worker_error(e.to_string(), &self.name);
|
return Poll::Ready(Err(e));
|
||||||
let handle = self.internal_handle.clone();
|
|
||||||
handle
|
|
||||||
.post_event(WorkerControlEvent::Error(e))
|
|
||||||
.expect("Failed to post message to host");
|
|
||||||
|
|
||||||
return Poll::Pending;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
panic!(
|
panic!(
|
||||||
|
@ -593,6 +586,12 @@ pub fn run_web_worker(
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let result = if result.is_ok() {
|
||||||
|
worker.run_event_loop(true).await
|
||||||
|
} else {
|
||||||
|
result
|
||||||
|
};
|
||||||
|
|
||||||
if let Err(e) = result {
|
if let Err(e) = result {
|
||||||
print_worker_error(e.to_string(), &name);
|
print_worker_error(e.to_string(), &name);
|
||||||
internal_handle
|
internal_handle
|
||||||
|
@ -603,7 +602,6 @@ pub fn run_web_worker(
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = worker.run_event_loop(true).await;
|
|
||||||
debug!("Worker thread shuts down {}", &name);
|
debug!("Worker thread shuts down {}", &name);
|
||||||
result
|
result
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue