From 81d6ea8e1174d2b74c2a4806eaf279115cb3068f Mon Sep 17 00:00:00 2001 From: Kyle Kelley Date: Sun, 17 Sep 2023 09:38:52 -0700 Subject: feat(jupyter-kernel): accept nested objects from display calls (#20537) Closes #20535. # Screenshots ## JSON image ## Vegalite image # Implementation Instead of going the route of recursively getting all the objects under `application/.*json` keys, I went with `JSON.stringify`ing in denospace then parsing it from rust. One of the key benefits of serializing and deserializing is that non-JSON-able entries will get stripped automatically. This also keeps the code pretty simple. In the future we should _only_ do this for `application/.*json` keys. cc @mmastrac --- cli/tools/jupyter/server.rs | 53 +++++++++++++-------------------------------- 1 file changed, 15 insertions(+), 38 deletions(-) (limited to 'cli/tools/jupyter/server.rs') diff --git a/cli/tools/jupyter/server.rs b/cli/tools/jupyter/server.rs index e3e712065..2ed1a61d8 100644 --- a/cli/tools/jupyter/server.rs +++ b/cli/tools/jupyter/server.rs @@ -480,57 +480,34 @@ async fn get_jupyter_display( session: &mut repl::ReplSession, evaluate_result: &cdp::RemoteObject, ) -> Result>, AnyError> { - let mut data = HashMap::default(); let response = session .call_function_on_args( r#"function (object) {{ - return object[Symbol.for("Jupyter.display")](); - }}"# + return JSON.stringify(object[Symbol.for("Jupyter.display")]()); + }}"# .to_string(), &[evaluate_result.clone()], ) .await?; - if response.exception_details.is_some() { + if let Some(exception_details) = &response.exception_details { + // TODO(rgbkrk): Return an error in userspace instead of Jupyter logs + eprintln!("Exception encountered: {}", exception_details.text); return Ok(None); } - let object_id = response.result.object_id.unwrap(); - - let get_properties_response_result = session - .post_message_with_event_loop( - "Runtime.getProperties", - Some(cdp::GetPropertiesArgs { - object_id, - own_properties: Some(true), - accessor_properties_only: None, - generate_preview: None, - non_indexed_properties_only: Some(true), - }), - ) - .await; - - let Ok(get_properties_response) = get_properties_response_result else { - return Ok(None); - }; + if let Some(serde_json::Value::String(json_str)) = response.result.value { + let data: HashMap = + serde_json::from_str(&json_str)?; - let get_properties_response: cdp::GetPropertiesResponse = - serde_json::from_value(get_properties_response).unwrap(); - - for prop in get_properties_response.result.into_iter() { - if let Some(value) = &prop.value { - data.insert( - prop.name.to_string(), - value - .value - .clone() - .unwrap_or_else(|| serde_json::Value::Null), - ); + if !data.is_empty() { + return Ok(Some(data)); } - } - - if !data.is_empty() { - return Ok(Some(data)); + } else { + eprintln!( + "Unexpected response from Jupyter.display: {:?}", + response.result.clone().value + ); } Ok(None) -- cgit v1.2.3