From 7c2abb9d579d13fa61339c24f8c39bc3c27c25db Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Wed, 3 Nov 2021 09:27:36 -0400 Subject: [PATCH] fix: Deno.emit crashes with BorrowMutError (#12627) Warn on await_holding_refcell_ref clippy rule to avoid this in the future. Fixes #12453 --- cli/ops/runtime_compiler.rs | 12 +++++++++--- cli/tests/integration/run_tests.rs | 18 ++++++++++++++++++ cli/tests/testdata/issue12453.js | 4 ++++ core/runtime.rs | 9 ++++++--- ext/web/message_port.rs | 1 + runtime/web_worker.rs | 1 + tools/lint.js | 9 ++++++++- 7 files changed, 47 insertions(+), 7 deletions(-) create mode 100644 cli/tests/testdata/issue12453.js diff --git a/cli/ops/runtime_compiler.rs b/cli/ops/runtime_compiler.rs index ab6992d19c..8f7a75146d 100644 --- a/cli/ops/runtime_compiler.rs +++ b/cli/ops/runtime_compiler.rs @@ -88,9 +88,15 @@ async fn op_emit( ) -> Result { deno_runtime::ops::check_unstable2(&state, "Deno.emit"); let root_specifier = args.root_specifier; - let state = state.borrow(); - let ps = state.borrow::(); - let mut runtime_permissions = { state.borrow::().clone() }; + let ps = { + let state = state.borrow(); + state.borrow::().clone() + }; + let mut runtime_permissions = { + let state = state.borrow(); + state.borrow::().clone() + }; + let mut cache: Box = if let Some(sources) = &args.sources { Box::new(cache::MemoryCacher::new(sources.clone())) diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs index ec42a8dc8f..b7480c44b1 100644 --- a/cli/tests/integration/run_tests.rs +++ b/cli/tests/integration/run_tests.rs @@ -2148,3 +2148,21 @@ itest!(eval_context_throw_dom_exception { args: "run eval_context_throw_dom_exception.js", output: "eval_context_throw_dom_exception.js.out", }); + +#[test] +fn issue12453() { + let _g = util::http_server(); + let deno_dir = util::new_deno_dir(); + let mut deno_cmd = util::deno_cmd_with_deno_dir(deno_dir.path()); + let status = deno_cmd + .current_dir(util::testdata_path()) + .arg("run") + .arg("--unstable") + .arg("--allow-net") + .arg("issue12453.js") + .spawn() + .unwrap() + .wait() + .unwrap(); + assert!(status.success()); +} diff --git a/cli/tests/testdata/issue12453.js b/cli/tests/testdata/issue12453.js new file mode 100644 index 0000000000..2ed1b5ae74 --- /dev/null +++ b/cli/tests/testdata/issue12453.js @@ -0,0 +1,4 @@ +const i = setInterval(() => { + Deno.emit("http://localhost:4545/subdir/mt_text_typescript.t1.ts"); + clearInterval(i); +}, 1); diff --git a/core/runtime.rs b/core/runtime.rs index 80221295da..704be7a769 100644 --- a/core/runtime.rs +++ b/core/runtime.rs @@ -2317,11 +2317,14 @@ assertEquals(1, notify_return_value); _: (), _: (), ) -> Result<(), AnyError> { - let op_state = op_state.borrow(); - let inner_state = op_state.borrow::(); + let n = { + let op_state = op_state.borrow(); + let inner_state = op_state.borrow::(); + inner_state.0 + }; // Future must be Poll::Pending on first call tokio::time::sleep(std::time::Duration::from_millis(1)).await; - if inner_state.0 != 42 { + if n != 42 { unreachable!(); } Ok(()) diff --git a/ext/web/message_port.rs b/ext/web/message_port.rs index d8d8e5907d..8734f9b65c 100644 --- a/ext/web/message_port.rs +++ b/ext/web/message_port.rs @@ -48,6 +48,7 @@ impl MessagePort { &self, state: Rc>, ) -> Result, AnyError> { + #![allow(clippy::await_holding_refcell_ref)] // TODO(ry) remove! let mut rx = self .rx .try_borrow_mut() diff --git a/runtime/web_worker.rs b/runtime/web_worker.rs index 8d3fcbb35a..c70d20ffcf 100644 --- a/runtime/web_worker.rs +++ b/runtime/web_worker.rs @@ -198,6 +198,7 @@ impl WebWorkerHandle { pub async fn get_control_event( &self, ) -> Result, AnyError> { + #![allow(clippy::await_holding_refcell_ref)] // TODO(ry) remove! let mut receiver = self.receiver.borrow_mut(); Ok(receiver.next().await) } diff --git a/tools/lint.js b/tools/lint.js index 03339bcbe4..bcb181e291 100755 --- a/tools/lint.js +++ b/tools/lint.js @@ -109,7 +109,14 @@ async function clippy() { } const p = Deno.run({ - cmd: [...cmd, "--", "-D", "clippy::all"], + cmd: [ + ...cmd, + "--", + "-D", + "clippy::all", + "-D", + "clippy::await_holding_refcell_ref", + ], }); const { success } = await p.status(); if (!success) {