2022-01-07 22:09:52 -05:00
|
|
|
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
2020-09-05 20:34:02 -04:00
|
|
|
|
2022-12-07 14:21:18 -05:00
|
|
|
use crate::args::ReplFlags;
|
|
|
|
use crate::colors;
|
2021-09-24 11:10:42 -04:00
|
|
|
use crate::proc_state::ProcState;
|
2020-09-14 12:48:57 -04:00
|
|
|
use deno_core::error::AnyError;
|
2022-04-20 08:16:37 -04:00
|
|
|
use deno_runtime::permissions::Permissions;
|
2020-12-13 13:45:53 -05:00
|
|
|
use deno_runtime::worker::MainWorker;
|
2020-10-01 19:14:55 -04:00
|
|
|
use rustyline::error::ReadlineError;
|
2021-11-25 14:05:12 -05:00
|
|
|
|
2022-11-25 18:38:08 -05:00
|
|
|
mod cdp;
|
2021-11-25 14:05:12 -05:00
|
|
|
mod channel;
|
2021-12-17 20:18:17 -05:00
|
|
|
mod editor;
|
|
|
|
mod session;
|
2021-11-25 14:05:12 -05:00
|
|
|
|
|
|
|
use channel::rustyline_channel;
|
2021-12-17 20:18:17 -05:00
|
|
|
use channel::RustylineSyncMessage;
|
2021-11-25 14:05:12 -05:00
|
|
|
use channel::RustylineSyncMessageHandler;
|
2021-12-17 20:18:17 -05:00
|
|
|
use channel::RustylineSyncResponse;
|
|
|
|
use editor::EditorHelper;
|
|
|
|
use editor::ReplEditor;
|
|
|
|
use session::EvaluationOutput;
|
|
|
|
use session::ReplSession;
|
2020-10-14 08:34:05 -04:00
|
|
|
|
2021-06-09 19:07:50 -04:00
|
|
|
async fn read_line_and_poll(
|
|
|
|
repl_session: &mut ReplSession,
|
2021-11-25 14:05:12 -05:00
|
|
|
message_handler: &mut RustylineSyncMessageHandler,
|
2021-06-09 19:07:50 -04:00
|
|
|
editor: ReplEditor,
|
|
|
|
) -> Result<String, ReadlineError> {
|
2021-06-29 14:39:28 -04:00
|
|
|
let mut line_fut = tokio::task::spawn_blocking(move || editor.readline());
|
2021-06-09 19:07:50 -04:00
|
|
|
let mut poll_worker = true;
|
|
|
|
|
|
|
|
loop {
|
|
|
|
tokio::select! {
|
2021-06-29 14:39:28 -04:00
|
|
|
result = &mut line_fut => {
|
2021-06-09 19:07:50 -04:00
|
|
|
return result.unwrap();
|
|
|
|
}
|
2021-11-25 14:05:12 -05:00
|
|
|
result = message_handler.recv() => {
|
2021-12-15 13:23:43 -05:00
|
|
|
match result {
|
2022-02-07 11:05:49 -05:00
|
|
|
Some(RustylineSyncMessage::PostMessage { method, params }) => {
|
2021-12-15 13:23:43 -05:00
|
|
|
let result = repl_session
|
|
|
|
.post_message_with_event_loop(&method, params)
|
|
|
|
.await;
|
|
|
|
message_handler.send(RustylineSyncResponse::PostMessage(result)).unwrap();
|
|
|
|
},
|
|
|
|
Some(RustylineSyncMessage::LspCompletions {
|
|
|
|
line_text,
|
|
|
|
position,
|
|
|
|
}) => {
|
|
|
|
let result = repl_session.language_server.completions(&line_text, position).await;
|
|
|
|
message_handler.send(RustylineSyncResponse::LspCompletions(result)).unwrap();
|
|
|
|
}
|
|
|
|
None => {}, // channel closed
|
2021-06-29 14:39:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
poll_worker = true;
|
|
|
|
},
|
2021-06-09 19:07:50 -04:00
|
|
|
_ = repl_session.run_event_loop(), if poll_worker => {
|
|
|
|
poll_worker = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-10-18 10:19:47 -04:00
|
|
|
}
|
|
|
|
|
2022-04-20 08:16:37 -04:00
|
|
|
async fn read_eval_file(
|
|
|
|
ps: &ProcState,
|
|
|
|
eval_file: &str,
|
|
|
|
) -> Result<String, AnyError> {
|
|
|
|
let specifier = deno_core::resolve_url_or_path(eval_file)?;
|
|
|
|
|
|
|
|
let file = ps
|
|
|
|
.file_fetcher
|
|
|
|
.fetch(&specifier, &mut Permissions::allow_all())
|
|
|
|
.await?;
|
|
|
|
|
2022-05-20 16:40:55 -04:00
|
|
|
Ok((*file.source).to_string())
|
2022-04-20 08:16:37 -04:00
|
|
|
}
|
|
|
|
|
2020-10-01 19:14:55 -04:00
|
|
|
pub async fn run(
|
2021-09-24 11:10:42 -04:00
|
|
|
ps: &ProcState,
|
2021-06-09 19:07:50 -04:00
|
|
|
worker: MainWorker,
|
2022-12-07 14:21:18 -05:00
|
|
|
repl_flags: ReplFlags,
|
2021-12-11 09:56:45 -05:00
|
|
|
) -> Result<i32, AnyError> {
|
2021-06-09 19:07:50 -04:00
|
|
|
let mut repl_session = ReplSession::initialize(worker).await?;
|
2021-11-25 14:05:12 -05:00
|
|
|
let mut rustyline_channel = rustyline_channel();
|
2022-09-22 04:42:09 -04:00
|
|
|
let mut should_exit_on_interrupt = false;
|
2020-10-19 15:25:21 -04:00
|
|
|
|
2021-06-09 19:07:50 -04:00
|
|
|
let helper = EditorHelper {
|
|
|
|
context_id: repl_session.context_id,
|
2021-11-25 14:05:12 -05:00
|
|
|
sync_sender: rustyline_channel.0,
|
2020-10-01 19:14:55 -04:00
|
|
|
};
|
|
|
|
|
2022-11-25 19:04:30 -05:00
|
|
|
let history_file_path = ps.dir.repl_history_file_path();
|
2022-11-24 20:56:47 -05:00
|
|
|
let editor = ReplEditor::new(helper, history_file_path)?;
|
2020-10-01 19:14:55 -04:00
|
|
|
|
2022-12-07 14:21:18 -05:00
|
|
|
if let Some(eval_files) = repl_flags.eval_files {
|
2022-04-20 08:16:37 -04:00
|
|
|
for eval_file in eval_files {
|
|
|
|
match read_eval_file(ps, &eval_file).await {
|
|
|
|
Ok(eval_source) => {
|
|
|
|
let output = repl_session
|
|
|
|
.evaluate_line_and_get_output(&eval_source)
|
|
|
|
.await?;
|
|
|
|
// only output errors
|
|
|
|
if let EvaluationOutput::Error(error_text) = output {
|
2022-11-30 17:25:20 -05:00
|
|
|
println!(
|
|
|
|
"Error in --eval-file file \"{}\": {}",
|
|
|
|
eval_file, error_text
|
|
|
|
);
|
2022-04-20 08:16:37 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(e) => {
|
2022-11-30 17:25:20 -05:00
|
|
|
println!("Error in --eval-file file \"{}\": {}", eval_file, e);
|
2022-04-20 08:16:37 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-07 14:21:18 -05:00
|
|
|
if let Some(eval) = repl_flags.eval {
|
2021-08-06 17:30:28 -04:00
|
|
|
let output = repl_session.evaluate_line_and_get_output(&eval).await?;
|
|
|
|
// only output errors
|
|
|
|
if let EvaluationOutput::Error(error_text) = output {
|
2022-11-30 17:25:20 -05:00
|
|
|
println!("Error in --eval flag: {}", error_text);
|
2021-08-06 17:30:28 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-30 17:25:20 -05:00
|
|
|
// Doing this manually, instead of using `log::info!` because these messages
|
|
|
|
// are supposed to go to stdout, not stderr.
|
|
|
|
if !ps.options.is_quiet() {
|
|
|
|
println!("Deno {}", crate::version::deno());
|
|
|
|
println!("exit using ctrl+d, ctrl+c, or close()");
|
2022-12-07 14:21:18 -05:00
|
|
|
if repl_flags.is_default_command {
|
|
|
|
println!(
|
|
|
|
"{}",
|
|
|
|
colors::yellow("REPL is running with all permissions allowed.")
|
|
|
|
);
|
|
|
|
println!("To specify permissions, run `deno repl` with allow flags.")
|
|
|
|
}
|
2022-11-30 17:25:20 -05:00
|
|
|
}
|
2020-10-01 19:14:55 -04:00
|
|
|
|
2020-12-01 08:13:30 -05:00
|
|
|
loop {
|
2020-10-19 15:25:21 -04:00
|
|
|
let line = read_line_and_poll(
|
2021-06-09 19:07:50 -04:00
|
|
|
&mut repl_session,
|
2021-11-25 14:05:12 -05:00
|
|
|
&mut rustyline_channel.1,
|
2020-10-19 15:25:21 -04:00
|
|
|
editor.clone(),
|
|
|
|
)
|
|
|
|
.await;
|
2020-10-01 19:14:55 -04:00
|
|
|
match line {
|
|
|
|
Ok(line) => {
|
2022-09-22 04:42:09 -04:00
|
|
|
should_exit_on_interrupt = false;
|
2022-11-24 20:56:47 -05:00
|
|
|
editor.update_history(line.clone());
|
2021-06-21 15:13:25 -04:00
|
|
|
let output = repl_session.evaluate_line_and_get_output(&line).await?;
|
2020-10-01 19:14:55 -04:00
|
|
|
|
2020-12-01 08:13:30 -05:00
|
|
|
// 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().
|
2022-05-12 19:12:55 -04:00
|
|
|
if repl_session.closing().await? {
|
2020-12-01 08:13:30 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-10-19 07:41:25 -04:00
|
|
|
println!("{}", output);
|
2020-10-01 19:14:55 -04:00
|
|
|
}
|
|
|
|
Err(ReadlineError::Interrupted) => {
|
2022-09-22 04:42:09 -04:00
|
|
|
if should_exit_on_interrupt {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
should_exit_on_interrupt = true;
|
|
|
|
println!("press ctrl+c again to exit");
|
2020-10-19 08:06:21 -04:00
|
|
|
continue;
|
2020-10-01 19:14:55 -04:00
|
|
|
}
|
|
|
|
Err(ReadlineError::Eof) => {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Err(err) => {
|
|
|
|
println!("Error: {:?}", err);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-11-05 12:55:59 -05:00
|
|
|
}
|
|
|
|
|
2021-12-11 09:56:45 -05:00
|
|
|
Ok(repl_session.worker.get_exit_code())
|
2018-11-05 12:55:59 -05:00
|
|
|
}
|