diff --git a/cli/main.rs b/cli/main.rs index 185982117ad1c9..d4a6846a8ee151 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -322,16 +322,18 @@ pub fn main() { // initialize the V8 platform on a parent thread of all threads that will spawn // V8 isolates. + let current_exe_path = current_exe().unwrap(); + let standalone = + standalone::extract_standalone(¤t_exe_path, args.clone()); let future = async move { - let current_exe_path = current_exe()?; - let standalone_res = - match standalone::extract_standalone(¤t_exe_path, args.clone()) - .await - { - Ok(Some((metadata, eszip))) => standalone::run(eszip, metadata).await, - Ok(None) => Ok(()), - Err(err) => Err(err), - }; + let standalone_res = match standalone { + Ok(Some(future)) => { + let (metadata, eszip) = future.await?; + standalone::run(eszip, metadata).await + } + Ok(None) => Ok(()), + Err(err) => Err(err), + }; // TODO(bartlomieju): doesn't handle exit code set by the runtime properly unwrap_or_exit(standalone_res); diff --git a/cli/mainrt.rs b/cli/mainrt.rs index 9c7ee3c5c9b182..ae4ea727f8535f 100644 --- a/cli/mainrt.rs +++ b/cli/mainrt.rs @@ -69,11 +69,16 @@ fn unwrap_or_exit(result: Result) -> T { fn main() { let args: Vec = env::args().collect(); + let current_exe_path = current_exe().unwrap(); + let standalone = + standalone::extract_standalone(¤t_exe_path, args.clone()); let future = async move { - let current_exe_path = current_exe().unwrap(); - match standalone::extract_standalone(¤t_exe_path, args).await { - Ok(Some((metadata, eszip))) => standalone::run(eszip, metadata).await, - Ok(None) => Err(generic_error("No archive found.")), + match standalone { + Ok(Some(future)) => { + let (metadata, eszip) = future.await?; + standalone::run(eszip, metadata).await + } + Ok(None) => Ok(()), Err(err) => Err(err), } }; diff --git a/cli/standalone/binary.rs b/cli/standalone/binary.rs index f9d65fdaa8c4e5..2b334ec466eb06 100644 --- a/cli/standalone/binary.rs +++ b/cli/standalone/binary.rs @@ -3,6 +3,7 @@ use std::collections::BTreeMap; use std::env::current_exe; use std::fs; +use std::future::Future; use std::io::Read; use std::io::Seek; use std::io::SeekFrom; @@ -236,49 +237,54 @@ pub fn is_standalone_binary(exe_path: &Path) -> bool { /// binary by skipping over the trailer width at the end of the file, /// then checking for the magic trailer string `d3n0l4nd`. If found, /// the bundle is executed. If not, this function exits with `Ok(None)`. -pub async fn extract_standalone( +pub fn extract_standalone( exe_path: &Path, cli_args: Vec, -) -> Result, AnyError> { - let file = std::fs::File::open(exe_path)?; - - let mut bufreader = - deno_core::futures::io::BufReader::new(AllowStdIo::new(file)); - - let _trailer_pos = bufreader - .seek(SeekFrom::End(-(TRAILER_SIZE as i64))) - .await?; +) -> Result< + Option>>, + AnyError, +> { + // We do the first part sync so it can complete quickly + let mut file = std::fs::File::open(exe_path)?; + file.seek(SeekFrom::End(-(TRAILER_SIZE as i64)))?; let mut trailer = [0; TRAILER_SIZE]; - bufreader.read_exact(&mut trailer).await?; + file.read_exact(&mut trailer)?; let trailer = match Trailer::parse(&trailer)? { None => return Ok(None), Some(trailer) => trailer, }; - bufreader.seek(SeekFrom::Start(trailer.eszip_pos)).await?; + file.seek(SeekFrom::Start(trailer.eszip_pos))?; + + // If we have an eszip, read it out + Ok(Some(async move { + let bufreader = + deno_core::futures::io::BufReader::new(AllowStdIo::new(file)); - let (eszip, loader) = eszip::EszipV2::parse(bufreader) - .await - .context("Failed to parse eszip header")?; + let (eszip, loader) = eszip::EszipV2::parse(bufreader) + .await + .context("Failed to parse eszip header")?; - let mut bufreader = loader.await.context("Failed to parse eszip archive")?; + let mut bufreader = + loader.await.context("Failed to parse eszip archive")?; - bufreader - .seek(SeekFrom::Start(trailer.metadata_pos)) - .await?; + bufreader + .seek(SeekFrom::Start(trailer.metadata_pos)) + .await?; - let mut metadata = String::new(); + let mut metadata = String::new(); - bufreader - .take(trailer.metadata_len()) - .read_to_string(&mut metadata) - .await - .context("Failed to read metadata from the current executable")?; + bufreader + .take(trailer.metadata_len()) + .read_to_string(&mut metadata) + .await + .context("Failed to read metadata from the current executable")?; - let mut metadata: Metadata = serde_json::from_str(&metadata).unwrap(); - metadata.argv.append(&mut cli_args[1..].to_vec()); + let mut metadata: Metadata = serde_json::from_str(&metadata).unwrap(); + metadata.argv.append(&mut cli_args[1..].to_vec()); - Ok(Some((metadata, eszip))) + Ok((metadata, eszip)) + })) } const TRAILER_SIZE: usize = std::mem::size_of::() + 8; // 8 bytes for the magic trailer string