summaryrefslogtreecommitdiff
path: root/cli/inspector.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/inspector.rs')
-rw-r--r--cli/inspector.rs113
1 files changed, 113 insertions, 0 deletions
diff --git a/cli/inspector.rs b/cli/inspector.rs
index f68882e48..83e75bce4 100644
--- a/cli/inspector.rs
+++ b/cli/inspector.rs
@@ -5,6 +5,8 @@
//! https://hyperandroid.com/2020/02/12/v8-inspector-from-an-embedder-standpoint/
use core::convert::Infallible as Never; // Alias for the future `!` type.
+use deno_core::error::generic_error;
+use deno_core::error::AnyError;
use deno_core::futures::channel::mpsc;
use deno_core::futures::channel::mpsc::UnboundedReceiver;
use deno_core::futures::channel::mpsc::UnboundedSender;
@@ -17,6 +19,7 @@ use deno_core::futures::stream::FuturesUnordered;
use deno_core::futures::task;
use deno_core::futures::task::Context;
use deno_core::futures::task::Poll;
+use deno_core::serde_json;
use deno_core::serde_json::json;
use deno_core::serde_json::Value;
use deno_core::v8;
@@ -816,6 +819,116 @@ impl Future for DenoInspectorSession {
}
}
+/// A local inspector session that can be used to send and receive protocol messages directly on
+/// the same thread as an isolate.
+pub struct InspectorSession {
+ v8_channel: v8::inspector::ChannelBase,
+ v8_session: v8::UniqueRef<v8::inspector::V8InspectorSession>,
+ response_tx_map: HashMap<i32, oneshot::Sender<serde_json::Value>>,
+ next_message_id: i32,
+}
+
+impl Deref for InspectorSession {
+ type Target = v8::inspector::V8InspectorSession;
+ fn deref(&self) -> &Self::Target {
+ &self.v8_session
+ }
+}
+
+impl DerefMut for InspectorSession {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.v8_session
+ }
+}
+
+impl v8::inspector::ChannelImpl for InspectorSession {
+ fn base(&self) -> &v8::inspector::ChannelBase {
+ &self.v8_channel
+ }
+
+ fn base_mut(&mut self) -> &mut v8::inspector::ChannelBase {
+ &mut self.v8_channel
+ }
+
+ fn send_response(
+ &mut self,
+ call_id: i32,
+ message: v8::UniquePtr<v8::inspector::StringBuffer>,
+ ) {
+ let raw_message = message.unwrap().string().to_string();
+ let message = serde_json::from_str(&raw_message).unwrap();
+ self
+ .response_tx_map
+ .remove(&call_id)
+ .unwrap()
+ .send(message)
+ .unwrap();
+ }
+
+ fn send_notification(
+ &mut self,
+ _message: v8::UniquePtr<v8::inspector::StringBuffer>,
+ ) {
+ }
+
+ fn flush_protocol_notifications(&mut self) {}
+}
+
+impl InspectorSession {
+ const CONTEXT_GROUP_ID: i32 = 1;
+
+ pub fn new(inspector_ptr: *mut DenoInspector) -> Box<Self> {
+ new_box_with(move |self_ptr| {
+ let v8_channel = v8::inspector::ChannelBase::new::<Self>();
+ let v8_session = unsafe { &mut *inspector_ptr }.connect(
+ Self::CONTEXT_GROUP_ID,
+ unsafe { &mut *self_ptr },
+ v8::inspector::StringView::empty(),
+ );
+
+ let response_tx_map = HashMap::new();
+ let next_message_id = 0;
+
+ Self {
+ v8_channel,
+ v8_session,
+ response_tx_map,
+ next_message_id,
+ }
+ })
+ }
+
+ pub async fn post_message(
+ &mut self,
+ method: String,
+ params: Option<serde_json::Value>,
+ ) -> Result<serde_json::Value, AnyError> {
+ let id = self.next_message_id;
+ self.next_message_id += 1;
+
+ let (response_tx, response_rx) = oneshot::channel::<serde_json::Value>();
+ self.response_tx_map.insert(id, response_tx);
+
+ let message = json!({
+ "id": id,
+ "method": method,
+ "params": params,
+ });
+
+ let raw_message = serde_json::to_string(&message).unwrap();
+ let raw_message = v8::inspector::StringView::from(raw_message.as_bytes());
+ self.v8_session.dispatch_protocol_message(raw_message);
+
+ let response = response_rx.await.unwrap();
+ if let Some(error) = response.get("error") {
+ return Err(generic_error(format!("{}", error)));
+ }
+
+ let result = response.get("result").unwrap().clone();
+ Ok(result)
+ }
+}
+
fn new_box_with<T>(new_fn: impl FnOnce(*mut T) -> T) -> Box<T> {
let b = Box::new(MaybeUninit::<T>::uninit());
let p = Box::into_raw(b) as *mut T;