From 3d2d0ee771abe308aee9a0ab6c89fd09bac80330 Mon Sep 17 00:00:00 2001 From: Kitson Kelly Date: Thu, 26 Sep 2019 00:46:58 +1000 Subject: [PATCH] Handle uncaught worker errors without panicking (#3019) --- cli/deno_error.rs | 11 +++++++++++ cli/lib.rs | 15 +++------------ cli/ops/workers.rs | 7 ++++--- cli/tests/error_worker_dynamic.ts | 3 +++ cli/tests/error_worker_dynamic.ts.out | 3 +++ cli/tests/integration_tests.rs | 7 +++++++ 6 files changed, 31 insertions(+), 15 deletions(-) create mode 100644 cli/tests/error_worker_dynamic.ts create mode 100644 cli/tests/error_worker_dynamic.ts.out diff --git a/cli/deno_error.rs b/cli/deno_error.rs index 2066d9c529..eb885adb85 100644 --- a/cli/deno_error.rs +++ b/cli/deno_error.rs @@ -22,6 +22,17 @@ pub struct DenoError { msg: String, } +pub fn print_err_and_exit(err: ErrBox) { + eprintln!("{}", err.to_string()); + std::process::exit(1); +} + +pub fn js_check(r: Result<(), ErrBox>) { + if let Err(err) = r { + print_err_and_exit(err); + } +} + impl DenoError { pub fn new(kind: ErrorKind, msg: String) -> Self { Self { kind, msg } diff --git a/cli/lib.rs b/cli/lib.rs index 3f101b7756..1e598e262c 100644 --- a/cli/lib.rs +++ b/cli/lib.rs @@ -51,6 +51,8 @@ mod tokio_write; pub mod version; pub mod worker; +use crate::deno_error::js_check; +use crate::deno_error::print_err_and_exit; use crate::progress::Progress; use crate::state::ThreadSafeState; use crate::worker::Worker; @@ -90,17 +92,6 @@ impl log::Log for Logger { fn flush(&self) {} } -fn print_err_and_exit(err: ErrBox) { - eprintln!("{}", err.to_string()); - std::process::exit(1); -} - -fn js_check(r: Result<(), ErrBox>) { - if let Err(err) = r { - print_err_and_exit(err); - } -} - fn create_worker_and_state( flags: DenoFlags, argv: Vec, @@ -118,7 +109,7 @@ fn create_worker_and_state( }); // TODO(kevinkassimo): maybe make include_deno_namespace also configurable? let state = ThreadSafeState::new(flags, argv, progress, true) - .map_err(print_err_and_exit) + .map_err(deno_error::print_err_and_exit) .unwrap(); let worker = Worker::new( "main".to_string(), diff --git a/cli/ops/workers.rs b/cli/ops/workers.rs index 4eeecd068c..6950f25d61 100644 --- a/cli/ops/workers.rs +++ b/cli/ops/workers.rs @@ -1,5 +1,6 @@ // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. use super::dispatch_json::{Deserialize, JsonOp, Value}; +use crate::deno_error::js_check; use crate::deno_error::DenoError; use crate::deno_error::ErrorKind; use crate::resources; @@ -124,8 +125,8 @@ pub fn op_create_worker( let mut worker = Worker::new(name, startup_data::deno_isolate_init(), child_state); - worker.execute(&deno_main_call).unwrap(); - worker.execute("workerMain()").unwrap(); + js_check(worker.execute(&deno_main_call)); + js_check(worker.execute("workerMain()")); let exec_cb = move |worker: Worker| { let mut workers_tl = parent_state.workers.lock().unwrap(); @@ -135,7 +136,7 @@ pub fn op_create_worker( // Has provided source code, execute immediately. if has_source_code { - worker.execute(&source_code).unwrap(); + js_check(worker.execute(&source_code)); return Ok(JsonOp::Sync(exec_cb(worker))); } diff --git a/cli/tests/error_worker_dynamic.ts b/cli/tests/error_worker_dynamic.ts new file mode 100644 index 0000000000..16fadf5733 --- /dev/null +++ b/cli/tests/error_worker_dynamic.ts @@ -0,0 +1,3 @@ +const b = new Blob(['throw new Error("hello");']); +const blobURL = URL.createObjectURL(b); +new Worker(blobURL); diff --git a/cli/tests/error_worker_dynamic.ts.out b/cli/tests/error_worker_dynamic.ts.out new file mode 100644 index 0000000000..4bea7b656c --- /dev/null +++ b/cli/tests/error_worker_dynamic.ts.out @@ -0,0 +1,3 @@ +[WILDCARD]error: Uncaught Error: hello +[WILDCARD]__anonymous__:1:7 + at [WILDCARD]__anonymous__:1:7 diff --git a/cli/tests/integration_tests.rs b/cli/tests/integration_tests.rs index 4bb7fbe6e6..99ab54a021 100644 --- a/cli/tests/integration_tests.rs +++ b/cli/tests/integration_tests.rs @@ -474,6 +474,13 @@ itest!(error_type_definitions { output: "error_type_definitions.ts.out", }); +itest!(error_worker_dynamic { + args: "run --reload error_worker_dynamic.ts", + check_stderr: true, + exit_code: 1, + output: "error_worker_dynamic.ts.out", +}); + itest!(exit_error42 { exit_code: 42, args: "run --reload exit_error42.ts",