summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/tests/inspector_tests.rs35
-rw-r--r--core/inspector.rs37
-rw-r--r--core/runtime.rs18
3 files changed, 73 insertions, 17 deletions
diff --git a/cli/tests/inspector_tests.rs b/cli/tests/inspector_tests.rs
index febff7c28..94ebbb205 100644
--- a/cli/tests/inspector_tests.rs
+++ b/cli/tests/inspector_tests.rs
@@ -303,7 +303,6 @@ mod inspector {
.unwrap();
let msg = ws_read_msg(&mut socket).await;
- println!("response msg 1 {}", msg);
assert_starts_with!(msg, r#"{"id":6,"result":{"debuggerId":"#);
socket
@@ -312,7 +311,6 @@ mod inspector {
.unwrap();
let msg = ws_read_msg(&mut socket).await;
- println!("response msg 2 {}", msg);
assert_eq!(msg, r#"{"id":31,"result":{}}"#);
child.kill().unwrap();
@@ -546,6 +544,10 @@ mod inspector {
.filter(|s| !s.starts_with("Deno "));
assert_stderr_for_inspect(&mut stderr_lines);
+ assert_eq!(
+ &stdout_lines.next().unwrap(),
+ "exit using ctrl+d, ctrl+c, or close()"
+ );
assert_inspector_messages(
&mut socket_tx,
@@ -564,11 +566,6 @@ mod inspector {
)
.await;
- assert_eq!(
- &stdout_lines.next().unwrap(),
- "exit using ctrl+d, ctrl+c, or close()"
- );
-
assert_inspector_messages(
&mut socket_tx,
&[
@@ -577,7 +574,6 @@ mod inspector {
&mut socket_rx,
&[r#"{"id":3,"result":{}}"#], &[]
).await;
-
assert_inspector_messages(
&mut socket_tx,
&[
@@ -587,7 +583,6 @@ mod inspector {
&[r#"{"id":4,"result":{"result":{"type":"string","value":""#],
&[],
).await;
-
assert_inspector_messages(
&mut socket_tx,
&[
@@ -597,9 +592,7 @@ mod inspector {
&[r#"{"id":5,"result":{"result":{"type":"undefined"}}}"#],
&[r#"{"method":"Runtime.consoleAPICalled"#],
).await;
-
assert_eq!(&stderr_lines.next().unwrap(), "done");
-
drop(stdin);
child.wait().unwrap();
}
@@ -905,6 +898,26 @@ mod inspector {
assert_eq!(&stdout_lines.next().unwrap(), "hello");
assert_eq!(&stdout_lines.next().unwrap(), "world");
+ assert_inspector_messages(
+ &mut socket_tx,
+ &[],
+ &mut socket_rx,
+ &[],
+ &[
+ r#"{"method":"Debugger.resumed","params":{}}"#,
+ r#"{"method":"Runtime.consoleAPICalled","#,
+ r#"{"method":"Runtime.consoleAPICalled","#,
+ r#"{"method":"Runtime.executionContextDestroyed","params":{"executionContextId":1}}"#,
+ ],
+ )
+ .await;
+ let line = &stdout_lines.next().unwrap();
+
+ assert_eq!(
+ line,
+ "Program finished. Waiting for inspector to disconnect to exit the process..."
+ );
+
child.kill().unwrap();
child.wait().unwrap();
}
diff --git a/core/inspector.rs b/core/inspector.rs
index e3db65afe..8a9136091 100644
--- a/core/inspector.rs
+++ b/core/inspector.rs
@@ -35,6 +35,7 @@ use std::ptr::NonNull;
use std::rc::Rc;
use std::sync::Arc;
use std::thread;
+use v8::HandleScope;
pub enum InspectorMsgKind {
Notification,
@@ -213,10 +214,28 @@ impl JsRuntimeInspector {
self__
}
+ pub fn context_destroyed(
+ &mut self,
+ scope: &mut HandleScope,
+ context: v8::Global<v8::Context>,
+ ) {
+ let context = v8::Local::new(scope, context);
+ self
+ .v8_inspector
+ .borrow_mut()
+ .as_mut()
+ .unwrap()
+ .context_destroyed(context);
+ }
+
pub fn has_active_sessions(&self) -> bool {
self.sessions.borrow().has_active_sessions()
}
+ pub fn has_blocking_sessions(&self) -> bool {
+ self.sessions.borrow().has_blocking_sessions()
+ }
+
fn poll_sessions(
&self,
mut invoker_cx: Option<&mut Context>,
@@ -262,8 +281,11 @@ impl JsRuntimeInspector {
// Accept new connections.
let poll_result = sessions.session_rx.poll_next_unpin(cx);
if let Poll::Ready(Some(session_proxy)) = poll_result {
- let session =
- InspectorSession::new(sessions.v8_inspector.clone(), session_proxy);
+ let session = InspectorSession::new(
+ sessions.v8_inspector.clone(),
+ session_proxy,
+ false,
+ );
let prev = sessions.handshake.replace(session);
assert!(prev.is_none());
}
@@ -378,7 +400,7 @@ impl JsRuntimeInspector {
// InspectorSessions for a local session is added directly to the "established"
// sessions, so it doesn't need to go through the session sender.
let inspector_session =
- InspectorSession::new(self.v8_inspector.clone(), proxy);
+ InspectorSession::new(self.v8_inspector.clone(), proxy, true);
self
.sessions
.borrow_mut()
@@ -432,6 +454,10 @@ impl SessionContainer {
!self.established.is_empty() || self.handshake.is_some()
}
+ fn has_blocking_sessions(&self) -> bool {
+ self.established.iter().any(|s| s.blocking)
+ }
+
/// A temporary placeholder that should be used before actual
/// instance of V8Inspector is created. It's used in favor
/// of `Default` implementation to signal that it's not meant
@@ -528,6 +554,9 @@ struct InspectorSession {
v8_channel: v8::inspector::ChannelBase,
v8_session: v8::UniqueRef<v8::inspector::V8InspectorSession>,
proxy: InspectorSessionProxy,
+ // Describes if session should keep event loop alive, eg. a local REPL
+ // session should keep event loop alive, but a Websocket session shouldn't.
+ blocking: bool,
}
impl InspectorSession {
@@ -536,6 +565,7 @@ impl InspectorSession {
pub fn new(
v8_inspector_rc: Rc<RefCell<v8::UniquePtr<v8::inspector::V8Inspector>>>,
session_proxy: InspectorSessionProxy,
+ blocking: bool,
) -> Box<Self> {
new_box_with(move |self_ptr| {
let v8_channel = v8::inspector::ChannelBase::new::<Self>();
@@ -556,6 +586,7 @@ impl InspectorSession {
v8_channel,
v8_session,
proxy: session_proxy,
+ blocking,
}
})
}
diff --git a/core/runtime.rs b/core/runtime.rs
index 8cb38de2f..9ee3aad70 100644
--- a/core/runtime.rs
+++ b/core/runtime.rs
@@ -1099,9 +1099,21 @@ impl JsRuntime {
let pending_state = self.event_loop_pending_state();
if !pending_state.is_pending() && !maybe_scheduling {
if has_inspector {
- let inspector_has_active_sessions =
- self.inspector().borrow_mut().has_active_sessions();
- if wait_for_inspector && inspector_has_active_sessions {
+ let inspector = self.inspector();
+ let has_active_sessions = inspector.borrow().has_active_sessions();
+ let has_blocking_sessions = inspector.borrow().has_blocking_sessions();
+
+ if wait_for_inspector && has_active_sessions {
+ // If there are no blocking sessions (eg. REPL) we can now notify
+ // debugger that the program has finished running and we're ready
+ // to exit the process once debugger disconnects.
+ if !has_blocking_sessions {
+ let context = self.global_context();
+ let scope = &mut self.handle_scope();
+ inspector.borrow_mut().context_destroyed(scope, context);
+ println!("Program finished. Waiting for inspector to disconnect to exit the process...");
+ }
+
return Poll::Pending;
}
}