From f3711f28f4b5ddfd9a11d9952b0a33b75fc5bc9c Mon Sep 17 00:00:00 2001 From: Leo Kettmeir Date: Wed, 25 Jan 2023 05:03:03 +0100 Subject: [PATCH] feat(cli): add `DENO_V8_FLAGS` env var (#17313) Closes #5669 --- cli/args/flags.rs | 4 ++- cli/main.rs | 33 +++------------------ cli/standalone.rs | 9 ++---- cli/tests/integration/run_tests.rs | 6 ++++ cli/util/mod.rs | 1 + cli/util/v8.rs | 47 ++++++++++++++++++++++++++++++ 6 files changed, 63 insertions(+), 37 deletions(-) create mode 100644 cli/util/v8.rs diff --git a/cli/args/flags.rs b/cli/args/flags.rs index a5aff3d09e..9f7b9206f2 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -545,6 +545,7 @@ static ENV_VARIABLES_HELP: &str = r#"ENVIRONMENT VARIABLES: (alternative to passing --no-prompt on invocation) DENO_NO_UPDATE_CHECK Set to disable checking if a newer Deno version is available + DENO_V8_FLAGS Set V8 command line options DENO_WEBGPU_TRACE Directory to use for wgpu traces DENO_JOBS Number of parallel workers used for the --parallel flag with the test subcommand. Defaults to number @@ -2115,7 +2116,8 @@ fn v8_flags_arg<'a>() -> Arg<'a> { .use_value_delimiter(true) .require_equals(true) .help("Set V8 command line options") - .long_help("To see a list of all available flags use --v8-flags=--help.") + .long_help("To see a list of all available flags use --v8-flags=--help.\ + Any flags set with this flag are appended after the DENO_V8_FLAGS environmental variable") } fn seed_arg<'a>() -> Arg<'a> { diff --git a/cli/main.rs b/cli/main.rs index 08746042cc..8c0dd03541 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -31,43 +31,19 @@ use crate::args::Flags; use crate::proc_state::ProcState; use crate::resolver::CliResolver; use crate::util::display; +use crate::util::v8::get_v8_flags_from_env; +use crate::util::v8::init_v8_flags; use args::CliOptions; use deno_core::anyhow::Context; use deno_core::error::AnyError; use deno_core::error::JsError; -use deno_core::v8_set_flags; use deno_runtime::colors; use deno_runtime::fmt_errors::format_js_error; use deno_runtime::tokio_util::run_local; use std::env; -use std::iter::once; use std::path::PathBuf; -fn init_v8_flags(v8_flags: &[String]) { - let v8_flags_includes_help = v8_flags - .iter() - .any(|flag| flag == "-help" || flag == "--help"); - // Keep in sync with `standalone.rs`. - let v8_flags = once("UNUSED_BUT_NECESSARY_ARG0".to_owned()) - .chain(v8_flags.iter().cloned()) - .collect::>(); - let unrecognized_v8_flags = v8_set_flags(v8_flags) - .into_iter() - .skip(1) - .collect::>(); - if !unrecognized_v8_flags.is_empty() { - for f in unrecognized_v8_flags { - eprintln!("error: V8 did not recognize flag '{}'", f); - } - eprintln!("\nFor a list of V8 flags, use '--v8-flags=--help'"); - std::process::exit(1); - } - if v8_flags_includes_help { - std::process::exit(0); - } -} - async fn run_subcommand(flags: Flags) -> Result { match flags.subcommand.clone() { DenoSubcommand::Bench(bench_flags) => { @@ -285,9 +261,8 @@ pub fn main() { } Err(err) => unwrap_or_exit(Err(AnyError::from(err))), }; - if !flags.v8_flags.is_empty() { - init_v8_flags(&flags.v8_flags); - } + + init_v8_flags(&flags.v8_flags, get_v8_flags_from_env()); util::logger::init(flags.log_level); diff --git a/cli/standalone.rs b/cli/standalone.rs index 829baa5578..063ad7d337 100644 --- a/cli/standalone.rs +++ b/cli/standalone.rs @@ -6,6 +6,7 @@ use crate::colors; use crate::file_fetcher::get_source_from_data_url; use crate::ops; use crate::proc_state::ProcState; +use crate::util::v8::construct_v8_flags; use crate::version; use crate::CliResolver; use deno_core::anyhow::Context; @@ -38,7 +39,6 @@ use import_map::parse_from_json; use log::Level; use std::env::current_exe; use std::io::SeekFrom; -use std::iter::once; use std::pin::Pin; use std::rc::Rc; use std::sync::Arc; @@ -248,12 +248,7 @@ pub async fn run( todo!("Workers are currently not supported in standalone binaries"); }); - // Keep in sync with `main.rs`. - v8_set_flags( - once("UNUSED_BUT_NECESSARY_ARG0".to_owned()) - .chain(metadata.v8_flags.iter().cloned()) - .collect::>(), - ); + v8_set_flags(construct_v8_flags(&metadata.v8_flags, vec![])); let root_cert_store = ps.root_cert_store.clone(); diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs index d5a988bf43..2494df8811 100644 --- a/cli/tests/integration/run_tests.rs +++ b/cli/tests/integration/run_tests.rs @@ -1154,6 +1154,12 @@ itest!(v8_flags_run { output: "run/v8_flags.js.out", }); +itest!(v8_flags_env_run { + envs: vec![("DENO_V8_FLAGS".to_string(), "--expose-gc".to_string())], + args: "run run/v8_flags.js", + output: "run/v8_flags.js.out", +}); + itest!(v8_flags_unrecognized { args: "repl --v8-flags=--foo,bar,--trace-gc,-baz", output: "run/v8_flags_unrecognized.out", diff --git a/cli/util/mod.rs b/cli/util/mod.rs index d0b500e310..515bc64e99 100644 --- a/cli/util/mod.rs +++ b/cli/util/mod.rs @@ -13,4 +13,5 @@ pub mod path; pub mod progress_bar; pub mod text_encoding; pub mod unix; +pub mod v8; pub mod windows; diff --git a/cli/util/v8.rs b/cli/util/v8.rs new file mode 100644 index 0000000000..b6d6aa44ed --- /dev/null +++ b/cli/util/v8.rs @@ -0,0 +1,47 @@ +// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. + +#[inline(always)] +pub fn get_v8_flags_from_env() -> Vec { + std::env::var("DENO_V8_FLAGS") + .ok() + .map(|flags| flags.split(',').map(String::from).collect::>()) + .unwrap_or_default() +} + +#[inline(always)] +pub fn construct_v8_flags( + v8_flags: &[String], + env_v8_flags: Vec, +) -> Vec { + std::iter::once("UNUSED_BUT_NECESSARY_ARG0".to_owned()) + .chain(env_v8_flags.into_iter()) + .chain(v8_flags.iter().cloned()) + .collect::>() +} + +pub fn init_v8_flags(v8_flags: &[String], env_v8_flags: Vec) { + if v8_flags.is_empty() && env_v8_flags.is_empty() { + return; + } + + let v8_flags_includes_help = env_v8_flags + .iter() + .chain(v8_flags) + .any(|flag| flag == "-help" || flag == "--help"); + // Keep in sync with `standalone.rs`. + let v8_flags = construct_v8_flags(v8_flags, env_v8_flags); + let unrecognized_v8_flags = deno_core::v8_set_flags(v8_flags) + .into_iter() + .skip(1) + .collect::>(); + if !unrecognized_v8_flags.is_empty() { + for f in unrecognized_v8_flags { + eprintln!("error: V8 did not recognize flag '{}'", f); + } + eprintln!("\nFor a list of V8 flags, use '--v8-flags=--help'"); + std::process::exit(1); + } + if v8_flags_includes_help { + std::process::exit(0); + } +}