mirror of
https://github.com/denoland/deno.git
synced 2025-03-10 06:07:03 -04:00
implement with js and ops
This commit is contained in:
parent
295bab82e5
commit
4f75592369
3 changed files with 92 additions and 6 deletions
|
@ -1,10 +1,13 @@
|
|||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::create_main_worker;
|
||||
use crate::proc_state::ProcState;
|
||||
use crate::worker::create_main_worker_with_extensions;
|
||||
use deno_core::anyhow::Context;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::op;
|
||||
use deno_core::Extension;
|
||||
use deno_core::ModuleSpecifier;
|
||||
use deno_core::OpState;
|
||||
use deno_runtime::permissions::Permissions;
|
||||
use rustyline::error::ReadlineError;
|
||||
|
||||
|
@ -75,16 +78,52 @@ async fn read_eval_file(
|
|||
Ok((*file.source).to_string())
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct ReplState {
|
||||
needs_reload: bool,
|
||||
needs_save: bool,
|
||||
maybe_session_filename: Option<String>,
|
||||
}
|
||||
|
||||
#[op]
|
||||
pub fn op_repl_reload(state: &mut OpState) {
|
||||
let repl_state = state.borrow_mut::<ReplState>();
|
||||
repl_state.needs_reload = true;
|
||||
}
|
||||
|
||||
#[op]
|
||||
pub fn op_repl_save(
|
||||
state: &mut OpState,
|
||||
maybe_session_filename: Option<String>,
|
||||
) {
|
||||
let repl_state = state.borrow_mut::<ReplState>();
|
||||
repl_state.needs_save = true;
|
||||
repl_state.maybe_session_filename = maybe_session_filename;
|
||||
}
|
||||
|
||||
async fn create_repl_session(
|
||||
ps: &ProcState,
|
||||
module_url: ModuleSpecifier,
|
||||
maybe_eval_files: Option<Vec<String>>,
|
||||
maybe_eval: Option<String>,
|
||||
) -> Result<ReplSession, AnyError> {
|
||||
let mut worker = create_main_worker(
|
||||
let extension = Extension::builder()
|
||||
.ops(vec![op_repl_reload::decl(), op_repl_save::decl()])
|
||||
.state(move |state| {
|
||||
state.put(ReplState {
|
||||
needs_reload: false,
|
||||
needs_save: false,
|
||||
maybe_session_filename: None,
|
||||
});
|
||||
Ok(())
|
||||
})
|
||||
.build();
|
||||
|
||||
let mut worker = create_main_worker_with_extensions(
|
||||
ps,
|
||||
module_url.clone(),
|
||||
Permissions::from_options(&ps.options.permissions_options())?,
|
||||
vec![extension],
|
||||
)
|
||||
.await?;
|
||||
worker.setup_repl().await?;
|
||||
|
@ -122,6 +161,7 @@ async fn create_repl_session(
|
|||
}
|
||||
|
||||
fn save_session_to_file(
|
||||
session_history: &[String],
|
||||
maybe_filename: Option<String>,
|
||||
) -> Result<(), AnyError> {
|
||||
// TODO(bartlomieju): make date shorter
|
||||
|
@ -164,7 +204,6 @@ pub async fn run(
|
|||
println!("Exit using ctrl+d, ctrl+c, or close()");
|
||||
|
||||
let mut session_history: Vec<String> = vec![];
|
||||
|
||||
loop {
|
||||
let line = read_line_and_poll(
|
||||
&mut repl_session,
|
||||
|
@ -178,7 +217,7 @@ pub async fn run(
|
|||
editor.update_history(line.clone());
|
||||
|
||||
session_history.push(line.to_string());
|
||||
let output = repl_session.evaluate_line_and_get_output(line).await?;
|
||||
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
|
||||
// consistent behavior in when the user evaluates a call to close().
|
||||
|
@ -187,6 +226,36 @@ pub async fn run(
|
|||
}
|
||||
|
||||
println!("{}", output);
|
||||
|
||||
{
|
||||
let op_state = repl_session.worker.js_runtime.op_state();
|
||||
let repl_state = {
|
||||
let op_state = op_state.borrow();
|
||||
op_state.borrow::<ReplState>().clone()
|
||||
};
|
||||
if repl_state.needs_reload {
|
||||
drop(op_state);
|
||||
repl_session = create_repl_session(
|
||||
ps,
|
||||
module_url.clone(),
|
||||
maybe_eval_files.clone(),
|
||||
maybe_eval.clone(),
|
||||
)
|
||||
.await?;
|
||||
println!("Started a new REPL session. Global scope is now clean.");
|
||||
} else if repl_state.needs_save {
|
||||
let mut op_state = op_state.borrow_mut();
|
||||
op_state.put(ReplState {
|
||||
needs_reload: false,
|
||||
needs_save: false,
|
||||
maybe_session_filename: None,
|
||||
});
|
||||
save_session_to_file(
|
||||
&session_history,
|
||||
repl_state.maybe_session_filename,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(ReadlineError::Interrupted) => {
|
||||
if should_exit_on_interrupt {
|
||||
|
|
|
@ -46,14 +46,14 @@ globalThis.clear = console.clear.bind(console);
|
|||
|
||||
globalThis.repl = {
|
||||
help: () => {
|
||||
console.log("%cAvailable commands:", "font-style: bold");
|
||||
console.log("%cAvailable functions:", "font-style: italic");
|
||||
console.log("%crepl.help()", "color: green;", " Print this message");
|
||||
console.log("%crepl.reload()", "color: green;", " Create a new session without exiting the REPL");
|
||||
console.log("%crepl.exit()", "color: green;", " Exit the REPL");
|
||||
console.log("%crepl.save(maybeFilename)", "color: green;", " Save the current session to a file");
|
||||
console.log("%cclear()", "color: green;", " Clear screen");
|
||||
console.log("");
|
||||
console.log("%cAvailable variables:", "font-style: bold");
|
||||
console.log("%cAvailable variables:", "font-style: italic");
|
||||
console.log("%c_", "color: green;", " Last evaluation result");
|
||||
console.log("%c_error", "color: green;", " Last thrown error");
|
||||
},
|
||||
|
|
|
@ -418,6 +418,23 @@ pub async fn create_main_worker(
|
|||
.await
|
||||
}
|
||||
|
||||
pub async fn create_main_worker_with_extensions(
|
||||
ps: &ProcState,
|
||||
main_module: ModuleSpecifier,
|
||||
permissions: Permissions,
|
||||
custom_extensions: Vec<Extension>,
|
||||
) -> Result<CliMainWorker, AnyError> {
|
||||
create_main_worker_internal(
|
||||
ps,
|
||||
main_module,
|
||||
permissions,
|
||||
custom_extensions,
|
||||
Default::default(),
|
||||
false,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn create_main_worker_for_test_or_bench(
|
||||
ps: &ProcState,
|
||||
main_module: ModuleSpecifier,
|
||||
|
|
Loading…
Add table
Reference in a new issue