0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-02-01 20:25:12 -05:00

Support TypeScript eval through deno eval -T flag (#4141)

This commit is contained in:
Kevin (Kun) "Kassimo" Qian 2020-02-28 06:17:56 -08:00 committed by GitHub
parent b5bf28e68f
commit 7255cc9bc0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 103 additions and 5 deletions

View file

@ -132,6 +132,19 @@ impl SourceFileFetcher {
.ok() .ok()
} }
/// Save a given source file into cache.
/// Allows injection of files that normally would not present
/// in filesystem.
/// This is useful when e.g. TS compiler retrieves a custom file
/// under a dummy specifier.
pub fn save_source_file_in_cache(
&self,
specifier: &ModuleSpecifier,
file: SourceFile,
) {
self.source_file_cache.set(specifier.to_string(), file);
}
pub async fn fetch_source_file( pub async fn fetch_source_file(
&self, &self,
specifier: &ModuleSpecifier, specifier: &ModuleSpecifier,

View file

@ -33,6 +33,7 @@ pub enum DenoSubcommand {
}, },
Eval { Eval {
code: String, code: String,
as_typescript: bool,
}, },
Fetch { Fetch {
files: Vec<String>, files: Vec<String>,
@ -401,7 +402,11 @@ fn eval_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
flags.allow_plugin = true; flags.allow_plugin = true;
flags.allow_hrtime = true; flags.allow_hrtime = true;
let code = matches.value_of("code").unwrap().to_string(); let code = matches.value_of("code").unwrap().to_string();
flags.subcommand = DenoSubcommand::Eval { code } let as_typescript = matches.is_present("ts");
flags.subcommand = DenoSubcommand::Eval {
code,
as_typescript,
}
} }
fn info_parse(flags: &mut Flags, matches: &clap::ArgMatches) { fn info_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
@ -662,7 +667,20 @@ fn eval_subcommand<'a, 'b>() -> App<'a, 'b> {
This command has implicit access to all permissions (--allow-all) This command has implicit access to all permissions (--allow-all)
deno eval \"console.log('hello world')\"", deno eval \"console.log('hello world')\"
To evaluate as TypeScript:
deno eval -T \"const v: string = 'hello'; console.log(v)\"
",
)
.arg(
Arg::with_name("ts")
.long("ts")
.short("T")
.help("Treat eval input as TypeScript")
.takes_value(false)
.multiple(false),
) )
.arg(Arg::with_name("code").takes_value(true).required(true)) .arg(Arg::with_name("code").takes_value(true).required(true))
.arg(v8_flags_arg()) .arg(v8_flags_arg())
@ -1497,6 +1515,34 @@ mod tests {
Flags { Flags {
subcommand: DenoSubcommand::Eval { subcommand: DenoSubcommand::Eval {
code: "'console.log(\"hello\")'".to_string(), code: "'console.log(\"hello\")'".to_string(),
as_typescript: false,
},
allow_net: true,
allow_env: true,
allow_run: true,
allow_read: true,
allow_write: true,
allow_plugin: true,
allow_hrtime: true,
..Flags::default()
}
);
}
#[test]
fn eval_typescript() {
let r = flags_from_vec_safe(svec![
"deno",
"eval",
"-T",
"'console.log(\"hello\")'"
]);
assert_eq!(
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Eval {
code: "'console.log(\"hello\")'".to_string(),
as_typescript: true,
}, },
allow_net: true, allow_net: true,
allow_env: true, allow_env: true,
@ -1519,6 +1565,7 @@ mod tests {
Flags { Flags {
subcommand: DenoSubcommand::Eval { subcommand: DenoSubcommand::Eval {
code: "42".to_string(), code: "42".to_string(),
as_typescript: false,
}, },
v8_flags: Some(svec!["--help"]), v8_flags: Some(svec!["--help"]),
allow_net: true, allow_net: true,
@ -2131,6 +2178,7 @@ fn eval_with_cafile() {
Flags { Flags {
subcommand: DenoSubcommand::Eval { subcommand: DenoSubcommand::Eval {
code: "console.log('hello world')".to_string(), code: "console.log('hello world')".to_string(),
as_typescript: false,
}, },
ca_file: Some("example.crt".to_owned()), ca_file: Some("example.crt".to_owned()),
allow_net: true, allow_net: true,

View file

@ -57,8 +57,10 @@ mod web_worker;
pub mod worker; pub mod worker;
use crate::compilers::TargetLib; use crate::compilers::TargetLib;
use crate::file_fetcher::SourceFile;
use crate::fs as deno_fs; use crate::fs as deno_fs;
use crate::global_state::GlobalState; use crate::global_state::GlobalState;
use crate::msg::MediaType;
use crate::ops::io::get_stdio; use crate::ops::io::get_stdio;
use crate::state::State; use crate::state::State;
use crate::worker::MainWorker; use crate::worker::MainWorker;
@ -279,14 +281,39 @@ async fn fetch_command(flags: Flags, files: Vec<String>) -> Result<(), ErrBox> {
Ok(()) Ok(())
} }
async fn eval_command(flags: Flags, code: String) -> Result<(), ErrBox> { async fn eval_command(
flags: Flags,
code: String,
as_typescript: bool,
) -> Result<(), ErrBox> {
// Force TypeScript compile. // Force TypeScript compile.
let main_module = let main_module =
ModuleSpecifier::resolve_url_or_path("./__$deno$eval.ts").unwrap(); ModuleSpecifier::resolve_url_or_path("./__$deno$eval.ts").unwrap();
let global_state = GlobalState::new(flags)?; let global_state = GlobalState::new(flags)?;
let mut worker = create_main_worker(global_state, main_module.clone())?; let mut worker = create_main_worker(global_state, main_module.clone())?;
let main_module_url = main_module.as_url().to_owned();
// Create a dummy source file.
let source_file = SourceFile {
filename: main_module_url.to_file_path().unwrap(),
url: main_module_url,
types_url: None,
media_type: if as_typescript {
MediaType::TypeScript
} else {
MediaType::JavaScript
},
source_code: code.clone().into_bytes(),
};
// Save our fake file into file fetcher cache
// to allow module access by TS compiler (e.g. op_fetch_source_files)
worker
.state
.borrow()
.global_state
.file_fetcher
.save_source_file_in_cache(&main_module, source_file);
debug!("main_module {}", &main_module); debug!("main_module {}", &main_module);
worker.execute_module_from_code(&main_module, code).await?; worker.execute_module(&main_module).await?;
worker.execute("window.dispatchEvent(new Event('load'))")?; worker.execute("window.dispatchEvent(new Event('load'))")?;
(&mut *worker).await?; (&mut *worker).await?;
worker.execute("window.dispatchEvent(new Event('unload'))")?; worker.execute("window.dispatchEvent(new Event('unload'))")?;
@ -409,7 +436,10 @@ pub fn main() {
source_file, source_file,
out_file, out_file,
} => bundle_command(flags, source_file, out_file).boxed_local(), } => bundle_command(flags, source_file, out_file).boxed_local(),
DenoSubcommand::Eval { code } => eval_command(flags, code).boxed_local(), DenoSubcommand::Eval {
code,
as_typescript,
} => eval_command(flags, code, as_typescript).boxed_local(),
DenoSubcommand::Fetch { files } => { DenoSubcommand::Fetch { files } => {
fetch_command(flags, files).boxed_local() fetch_command(flags, files).boxed_local()
} }

View file

@ -0,0 +1 @@
123

View file

@ -788,6 +788,12 @@ itest!(_029_eval {
output: "029_eval.out", output: "029_eval.out",
}); });
// Ugly parentheses due to whitespace delimiting problem.
itest!(_030_eval_ts {
args: "eval -T console.log((123)as(number))", // 'as' is a TS keyword only
output: "030_eval_ts.out",
});
itest!(_033_import_map { itest!(_033_import_map {
args: args:
"run --reload --importmap=importmaps/import_map.json importmaps/test.ts", "run --reload --importmap=importmaps/import_map.json importmaps/test.ts",