From bf0760411336ce5ebb1c103f766c8154af478414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Sat, 16 Sep 2023 02:42:09 +0200 Subject: feat: Add "deno jupyter" subcommand (#20337) This commit adds "deno jupyter" subcommand which provides a Deno kernel for Jupyter notebooks. The implementation is mostly based on Deno's REPL and reuses large parts of it (though there's some clean up that needs to happen in follow up PRs). Not all functionality of Jupyter kernel is implemented and some message type are still not implemented (eg. "inspect_request") but the kernel is fully working and provides all the capatibilities that the Deno REPL has; including TypeScript transpilation and npm packages support. Closes https://github.com/denoland/deno/issues/13016 --------- Co-authored-by: Adam Powers Co-authored-by: Kyle Kelley --- cli/tools/repl/mod.rs | 7 +++--- cli/tools/repl/session.rs | 63 +++++++++++++++++++++++++++++++---------------- 2 files changed, 46 insertions(+), 24 deletions(-) (limited to 'cli/tools/repl') diff --git a/cli/tools/repl/mod.rs b/cli/tools/repl/mod.rs index fb0891fa6..a1e741dfd 100644 --- a/cli/tools/repl/mod.rs +++ b/cli/tools/repl/mod.rs @@ -13,7 +13,7 @@ use deno_runtime::permissions::Permissions; use deno_runtime::permissions::PermissionsContainer; use rustyline::error::ReadlineError; -mod cdp; +pub(crate) mod cdp; mod channel; mod editor; mod session; @@ -24,8 +24,9 @@ use channel::RustylineSyncMessageHandler; use channel::RustylineSyncResponse; use editor::EditorHelper; use editor::ReplEditor; -use session::EvaluationOutput; -use session::ReplSession; +pub use session::EvaluationOutput; +pub use session::ReplSession; +pub use session::REPL_INTERNALS_NAME; #[allow(clippy::await_holding_refcell_ref)] async fn read_line_and_poll( diff --git a/cli/tools/repl/session.rs b/cli/tools/repl/session.rs index d89cc95c3..a1b602b4b 100644 --- a/cli/tools/repl/session.rs +++ b/cli/tools/repl/session.rs @@ -116,9 +116,10 @@ pub fn result_to_evaluation_output( } } -struct TsEvaluateResponse { - ts_code: String, - value: cdp::EvaluateResponse, +#[derive(Debug)] +pub struct TsEvaluateResponse { + pub ts_code: String, + pub value: cdp::EvaluateResponse, } pub struct ReplSession { @@ -305,7 +306,7 @@ impl ReplSession { result_to_evaluation_output(result) } - async fn evaluate_line_with_object_wrapping( + pub async fn evaluate_line_with_object_wrapping( &mut self, line: &str, ) -> Result { @@ -395,29 +396,24 @@ impl ReplSession { Ok(()) } - pub async fn get_eval_value( + pub async fn call_function_on_args( &mut self, - evaluate_result: &cdp::RemoteObject, - ) -> Result { - // TODO(caspervonb) we should investigate using previews here but to keep things - // consistent with the previous implementation we just get the preview result from - // Deno.inspectArgs. + function_declaration: String, + args: &[cdp::RemoteObject], + ) -> Result { + let arguments: Option> = if args.is_empty() { + None + } else { + Some(args.iter().map(|a| a.into()).collect()) + }; + let inspect_response = self .post_message_with_event_loop( "Runtime.callFunctionOn", Some(cdp::CallFunctionOnArgs { - function_declaration: format!( - r#"function (object) {{ - try {{ - return {0}.inspectArgs(["%o", object], {{ colors: !{0}.noColor }}); - }} catch (err) {{ - return {0}.inspectArgs(["%o", err]); - }} - }}"#, - *REPL_INTERNALS_NAME - ), + function_declaration, object_id: None, - arguments: Some(vec![evaluate_result.into()]), + arguments, silent: None, return_by_value: None, generate_preview: None, @@ -432,6 +428,31 @@ impl ReplSession { let response: cdp::CallFunctionOnResponse = serde_json::from_value(inspect_response)?; + Ok(response) + } + + pub async fn get_eval_value( + &mut self, + evaluate_result: &cdp::RemoteObject, + ) -> Result { + // TODO(caspervonb) we should investigate using previews here but to keep things + // consistent with the previous implementation we just get the preview result from + // Deno.inspectArgs. + let response = self + .call_function_on_args( + format!( + r#"function (object) {{ + try {{ + return {0}.inspectArgs(["%o", object], {{ colors: !{0}.noColor }}); + }} catch (err) {{ + return {0}.inspectArgs(["%o", err]); + }} + }}"#, + *REPL_INTERNALS_NAME + ), + &[evaluate_result.clone()], + ) + .await?; let value = response.result.value.unwrap(); let s = value.as_str().unwrap(); -- cgit v1.2.3