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:
parent
e7e25db24f
commit
824f4fa55f
3 changed files with 97 additions and 58 deletions
18
cli/cdp.rs
18
cli/cdp.rs
|
@ -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,
|
||||||
|
}
|
||||||
|
|
|
@ -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())
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
}),
|
}),
|
||||||
|
|
Loading…
Reference in a new issue