diff --git a/cli/main.rs b/cli/main.rs index 73349d5992..8e819927ee 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -92,6 +92,7 @@ use log::Level; use log::Metadata; use log::Record; use std::env; +use std::io::Read; use std::io::Write; use std::path::PathBuf; use std::pin::Pin; @@ -563,9 +564,36 @@ async fn run_repl(flags: Flags) -> Result<(), ErrBox> { async fn run_command(flags: Flags, script: String) -> Result<(), ErrBox> { let global_state = GlobalState::new(flags.clone())?; - let main_module = ModuleSpecifier::resolve_url_or_path(&script).unwrap(); + let main_module = if script != "-" { + ModuleSpecifier::resolve_url_or_path(&script).unwrap() + } else { + ModuleSpecifier::resolve_url_or_path("./__$deno$stdin.ts").unwrap() + }; let mut worker = MainWorker::create(global_state.clone(), main_module.clone())?; + if script == "-" { + let mut source = Vec::new(); + std::io::stdin().read_to_end(&mut source)?; + 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, + types_header: None, + media_type: MediaType::TypeScript, + source_code: source, + }; + // 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); worker.execute_module(&main_module).await?; write_lockfile(global_state)?; diff --git a/cli/tests/integration_tests.rs b/cli/tests/integration_tests.rs index 9c59e2a741..5ecd6d35bd 100644 --- a/cli/tests/integration_tests.rs +++ b/cli/tests/integration_tests.rs @@ -8,7 +8,7 @@ extern crate pty; extern crate tempfile; use futures::prelude::*; -use std::io::BufRead; +use std::io::{BufRead, Write}; use std::process::Command; use tempfile::TempDir; @@ -70,6 +70,50 @@ fn eval_p() { assert_eq!("3", stdout_str); } +#[test] + +fn run_from_stdin() { + let mut deno = util::deno_cmd() + .current_dir(util::root_path()) + .arg("run") + .arg("-") + .stdout(std::process::Stdio::piped()) + .stdin(std::process::Stdio::piped()) + .spawn() + .unwrap(); + deno + .stdin + .as_mut() + .unwrap() + .write_all(b"console.log(\"Hello World\");") + .unwrap(); + let output = deno.wait_with_output().unwrap(); + assert!(output.status.success()); + + let deno_out = std::str::from_utf8(&output.stdout).unwrap().trim(); + assert_eq!("Hello World", deno_out); + + let mut deno = util::deno_cmd() + .current_dir(util::root_path()) + .arg("run") + .arg("-") + .stdout(std::process::Stdio::piped()) + .stdin(std::process::Stdio::piped()) + .spawn() + .unwrap(); + deno + .stdin + .as_mut() + .unwrap() + .write_all(b"console.log(\"Bye cached code\");") + .unwrap(); + let output = deno.wait_with_output().unwrap(); + assert!(output.status.success()); + + let deno_out = std::str::from_utf8(&output.stdout).unwrap().trim(); + assert_eq!("Bye cached code", deno_out); +} + #[test] fn no_color() { let output = util::deno_cmd()