1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-25 15:29:32 -05:00

refactor(tools/repl): reorganize code (#21810)

Some drive-by cleanup as I'm working through
https://github.com/denoland/deno_core/pull/415.
This commit is contained in:
Bartek Iwańczuk 2024-01-05 16:14:58 +01:00 committed by GitHub
parent e7e25db24f
commit 824f4fa55f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 97 additions and 58 deletions

View file

@ -526,3 +526,21 @@ pub struct ExceptionThrown {
pub timestamp: f64, pub timestamp: f64,
pub exception_details: ExceptionDetails, pub exception_details: ExceptionDetails,
} }
/// <https://chromedevtools.github.io/devtools-protocol/tot/Runtime/#event-executionContextCreated>
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ExecutionContextCreated {
pub context: ExecutionContextDescription,
}
/// <https://chromedevtools.github.io/devtools-protocol/tot/Runtime/#type-ExecutionContextDescription>
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ExecutionContextDescription {
pub id: ExecutionContextId,
pub origin: String,
pub name: String,
pub unique_id: String,
pub aux_data: Value,
}

View file

@ -33,7 +33,57 @@ pub use session::REPL_INTERNALS_NAME;
use super::test::TestEvent; use super::test::TestEvent;
use super::test::TestEventSender; use super::test::TestEventSender;
#[allow(clippy::await_holding_refcell_ref)] struct Repl {
session: ReplSession,
editor: ReplEditor,
message_handler: RustylineSyncMessageHandler,
}
impl Repl {
async fn run(&mut self) -> Result<(), AnyError> {
loop {
let line = read_line_and_poll(
&mut self.session,
&mut self.message_handler,
self.editor.clone(),
)
.await;
match line {
Ok(line) => {
self.editor.set_should_exit_on_interrupt(false);
self.editor.update_history(line.clone());
let output = self.session.evaluate_line_and_get_output(&line).await;
// We check for close and break here instead of making it a loop condition to get
// consistent behavior in when the user evaluates a call to close().
if self.session.closing().await? {
break;
}
println!("{output}");
}
Err(ReadlineError::Interrupted) => {
if self.editor.should_exit_on_interrupt() {
break;
}
self.editor.set_should_exit_on_interrupt(true);
println!("press ctrl+c again to exit");
continue;
}
Err(ReadlineError::Eof) => {
break;
}
Err(err) => {
println!("Error: {err:?}");
break;
}
}
}
Ok(())
}
}
async fn read_line_and_poll( async fn read_line_and_poll(
repl_session: &mut ReplSession, repl_session: &mut ReplSession,
message_handler: &mut RustylineSyncMessageHandler, message_handler: &mut RustylineSyncMessageHandler,
@ -42,7 +92,7 @@ async fn read_line_and_poll(
let mut line_fut = spawn_blocking(move || editor.readline()); let mut line_fut = spawn_blocking(move || editor.readline());
let mut poll_worker = true; let mut poll_worker = true;
let notifications_rc = repl_session.notifications.clone(); let notifications_rc = repl_session.notifications.clone();
let mut notifications = notifications_rc.borrow_mut(); let mut notifications = notifications_rc.lock().await;
loop { loop {
tokio::select! { tokio::select! {
@ -131,7 +181,7 @@ pub async fn run(flags: Flags, repl_flags: ReplFlags) -> Result<i32, AnyError> {
.await?; .await?;
worker.setup_repl().await?; worker.setup_repl().await?;
let worker = worker.into_main_worker(); let worker = worker.into_main_worker();
let mut repl_session = ReplSession::initialize( let session = ReplSession::initialize(
cli_options, cli_options,
npm_resolver, npm_resolver,
resolver, resolver,
@ -141,20 +191,27 @@ pub async fn run(flags: Flags, repl_flags: ReplFlags) -> Result<i32, AnyError> {
test_event_receiver, test_event_receiver,
) )
.await?; .await?;
let mut rustyline_channel = rustyline_channel(); let rustyline_channel = rustyline_channel();
let helper = EditorHelper { let helper = EditorHelper {
context_id: repl_session.context_id, context_id: session.context_id,
sync_sender: rustyline_channel.0, sync_sender: rustyline_channel.0,
}; };
let editor = ReplEditor::new(helper, history_file_path)?; let editor = ReplEditor::new(helper, history_file_path)?;
let mut repl = Repl {
session,
editor,
message_handler: rustyline_channel.1,
};
if let Some(eval_files) = repl_flags.eval_files { if let Some(eval_files) = repl_flags.eval_files {
for eval_file in eval_files { for eval_file in eval_files {
match read_eval_file(cli_options, file_fetcher, &eval_file).await { match read_eval_file(cli_options, file_fetcher, &eval_file).await {
Ok(eval_source) => { Ok(eval_source) => {
let output = repl_session let output = repl
.session
.evaluate_line_and_get_output(&eval_source) .evaluate_line_and_get_output(&eval_source)
.await; .await;
// only output errors // only output errors
@ -170,7 +227,7 @@ pub async fn run(flags: Flags, repl_flags: ReplFlags) -> Result<i32, AnyError> {
} }
if let Some(eval) = repl_flags.eval { if let Some(eval) = repl_flags.eval {
let output = repl_session.evaluate_line_and_get_output(&eval).await; let output = repl.session.evaluate_line_and_get_output(&eval).await;
// only output errors // only output errors
if let EvaluationOutput::Error(error_text) = output { if let EvaluationOutput::Error(error_text) = output {
println!("Error in --eval flag: {error_text}"); println!("Error in --eval flag: {error_text}");
@ -191,44 +248,7 @@ pub async fn run(flags: Flags, repl_flags: ReplFlags) -> Result<i32, AnyError> {
} }
} }
loop { repl.run().await?;
let line = read_line_and_poll(
&mut repl_session,
&mut rustyline_channel.1,
editor.clone(),
)
.await;
match line {
Ok(line) => {
editor.set_should_exit_on_interrupt(false);
editor.update_history(line.clone());
let output = repl_session.evaluate_line_and_get_output(&line).await;
// We check for close and break here instead of making it a loop condition to get Ok(repl.session.worker.exit_code())
// consistent behavior in when the user evaluates a call to close().
if repl_session.closing().await? {
break;
}
println!("{output}");
}
Err(ReadlineError::Interrupted) => {
if editor.should_exit_on_interrupt() {
break;
}
editor.set_should_exit_on_interrupt(true);
println!("press ctrl+c again to exit");
continue;
}
Err(ReadlineError::Eof) => {
break;
}
Err(err) => {
println!("Error: {err:?}");
break;
}
}
}
Ok(repl_session.worker.exit_code())
} }

View file

@ -1,7 +1,5 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use std::cell::RefCell;
use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use crate::args::CliOptions; use crate::args::CliOptions;
@ -49,6 +47,7 @@ use deno_semver::npm::NpmPackageReqReference;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use regex::Match; use regex::Match;
use regex::Regex; use regex::Regex;
use tokio::sync::Mutex;
fn comment_source_to_position_range( fn comment_source_to_position_range(
comment_start: SourcePos, comment_start: SourcePos,
@ -177,7 +176,7 @@ pub struct ReplSession {
session: LocalInspectorSession, session: LocalInspectorSession,
pub context_id: u64, pub context_id: u64,
pub language_server: ReplLanguageServer, pub language_server: ReplLanguageServer,
pub notifications: Rc<RefCell<UnboundedReceiver<Value>>>, pub notifications: Arc<Mutex<UnboundedReceiver<Value>>>,
referrer: ModuleSpecifier, referrer: ModuleSpecifier,
main_module: ModuleSpecifier, main_module: ModuleSpecifier,
test_reporter_factory: Box<dyn Fn() -> Box<dyn TestReporter>>, test_reporter_factory: Box<dyn Fn() -> Box<dyn TestReporter>>,
@ -218,18 +217,20 @@ impl ReplSession {
loop { loop {
let notification = notification_rx.next().await.unwrap(); let notification = notification_rx.next().await.unwrap();
let method = notification.get("method").unwrap().as_str().unwrap(); let notification =
let params = notification.get("params").unwrap(); serde_json::from_value::<cdp::Notification>(notification)?;
if method == "Runtime.executionContextCreated" { if notification.method == "Runtime.executionContextCreated" {
let context = params.get("context").unwrap(); let execution_context_created = serde_json::from_value::<
assert!(context cdp::ExecutionContextCreated,
.get("auxData") >(notification.params)?;
.unwrap() assert!(execution_context_created
.context
.aux_data
.get("isDefault") .get("isDefault")
.unwrap() .unwrap()
.as_bool() .as_bool()
.unwrap()); .unwrap());
context_id = context.get("id").unwrap().as_u64().unwrap(); context_id = execution_context_created.context.id;
break; break;
} }
} }
@ -247,7 +248,7 @@ impl ReplSession {
context_id, context_id,
language_server, language_server,
referrer, referrer,
notifications: Rc::new(RefCell::new(notification_rx)), notifications: Arc::new(Mutex::new(notification_rx)),
test_reporter_factory: Box::new(|| { test_reporter_factory: Box::new(|| {
Box::new(PrettyTestReporter::new(false, true, false, true)) Box::new(PrettyTestReporter::new(false, true, false, true))
}), }),