mirror of
https://github.com/denoland/deno.git
synced 2024-12-22 07:14:47 -05:00
npm: ensure runtime exceptions are surfaced when debugger is attached (#16943)
Currently runtime exception are only displayed at the program end in terminal, which makes it only a partial fix, as a full fix requires https://github.com/denoland/rusty_v8/pull/1149 which adds new bindings to the inspector that allows to notify it about thrown exceptions. This will be handled in a follow up commit.
This commit is contained in:
parent
a7dd28a07c
commit
79285fa83b
3 changed files with 98 additions and 5 deletions
|
@ -1303,4 +1303,89 @@ mod inspector {
|
|||
child.kill().unwrap();
|
||||
child.wait().unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn inspector_error_with_npm_import() {
|
||||
let script =
|
||||
util::testdata_path().join("inspector/error_with_npm_import.js");
|
||||
let _server = http_server();
|
||||
|
||||
let mut child = util::deno_cmd()
|
||||
.arg("run")
|
||||
.arg("--quiet")
|
||||
.arg("-A")
|
||||
.arg(inspect_flag_with_unique_port("--inspect-brk"))
|
||||
.arg(script)
|
||||
.envs(util::env_vars_for_npm_tests())
|
||||
.stdout(std::process::Stdio::piped())
|
||||
.stderr(std::process::Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap();
|
||||
|
||||
let stderr = child.stderr.as_mut().unwrap();
|
||||
let mut stderr_lines =
|
||||
std::io::BufReader::new(stderr).lines().map(|r| r.unwrap());
|
||||
let ws_url = extract_ws_url_from_stderr(&mut stderr_lines);
|
||||
|
||||
let (socket, response) =
|
||||
tokio_tungstenite::connect_async(ws_url).await.unwrap();
|
||||
assert_eq!(response.status(), 101); // Switching protocols.
|
||||
|
||||
let (mut socket_tx, socket_rx) = socket.split();
|
||||
let mut socket_rx = socket_rx
|
||||
.map(|msg| msg.unwrap().to_string())
|
||||
.filter(|msg| {
|
||||
let pass = !msg.starts_with(r#"{"method":"Debugger.scriptParsed","#);
|
||||
futures::future::ready(pass)
|
||||
})
|
||||
.boxed_local();
|
||||
|
||||
assert_stderr_for_inspect_brk(&mut stderr_lines);
|
||||
|
||||
assert_inspector_messages(
|
||||
&mut socket_tx,
|
||||
&[
|
||||
r#"{"id":1,"method":"Runtime.enable"}"#,
|
||||
r#"{"id":2,"method":"Debugger.enable"}"#,
|
||||
],
|
||||
&mut socket_rx,
|
||||
&[
|
||||
r#"{"id":1,"result":{}}"#,
|
||||
r#"{"id":2,"result":{"debuggerId":"#,
|
||||
],
|
||||
&[
|
||||
r#"{"method":"Runtime.executionContextCreated","params":{"context":{"id":1,"#,
|
||||
],
|
||||
)
|
||||
.await;
|
||||
|
||||
assert_inspector_messages(
|
||||
&mut socket_tx,
|
||||
&[r#"{"id":3,"method":"Runtime.runIfWaitingForDebugger"}"#],
|
||||
&mut socket_rx,
|
||||
&[r#"{"id":3,"result":{}}"#],
|
||||
&[r#"{"method":"Debugger.paused","#],
|
||||
)
|
||||
.await;
|
||||
|
||||
assert_inspector_messages(
|
||||
&mut socket_tx,
|
||||
&[r#"{"id":4,"method":"Debugger.resume"}"#],
|
||||
&mut socket_rx,
|
||||
&[r#"{"id":4,"result":{}}"#],
|
||||
&[],
|
||||
)
|
||||
.await;
|
||||
|
||||
// TODO(bartlomieju): this is a partial fix, we should assert that
|
||||
// "Runtime.exceptionThrown" notification was sent, but a bindings for this
|
||||
// notification is not yet there
|
||||
assert_eq!(&stderr_lines.next().unwrap(), "Debugger session started.");
|
||||
assert_eq!(
|
||||
&stderr_lines.next().unwrap(),
|
||||
"error: Uncaught Error: boom!"
|
||||
);
|
||||
|
||||
assert_eq!(child.wait().unwrap().code(), Some(1));
|
||||
}
|
||||
}
|
||||
|
|
7
cli/tests/testdata/inspector/error_with_npm_import.js
vendored
Normal file
7
cli/tests/testdata/inspector/error_with_npm_import.js
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
// deno-lint-ignore-file
|
||||
|
||||
import chalk from "npm:chalk";
|
||||
|
||||
console.log("hello");
|
||||
|
||||
throw new Error("boom!");
|
|
@ -770,12 +770,13 @@ fn op_dispatch_exception(
|
|||
scope.terminate_execution();
|
||||
return;
|
||||
}
|
||||
match state.inspector().try_borrow() {
|
||||
Ok(inspector) if !inspector.has_active_sessions() => {
|
||||
|
||||
// FIXME(bartlomieju): I'm not sure if this assumption is valid... Maybe when
|
||||
// inspector is polling on pause?
|
||||
if state.inspector().try_borrow().is_ok() {
|
||||
scope.terminate_execution();
|
||||
}
|
||||
} else {
|
||||
// If the inspector is borrowed at this time, assume an inspector is active.
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue