refactor: version module exports a single const struct (#25014)

This commit rewrites the internal `version` module that exported
various information about the current executable. Instead of exporting
several consts, we are now exporting a single const structure that 
contains all the necessary information.

This is the first step towards cleaning up how we use this information
and should allow us to use SUI to be able to patch this information
in already produced binary making it easier to cut new releases.

---------

Co-authored-by: Divy Srivastava <dj.srivastava23@gmail.com>
This commit is contained in:
Bartek Iwańczuk 2024-08-15 22:47:16 +01:00 committed by GitHub
parent 5ec3c5c3a4
commit 2bb013f9ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 214 additions and 142 deletions

View File

@ -1334,7 +1334,7 @@ static UNSTABLE_HEADING: &str = "Unstable";
pub fn clap_root() -> Command {
let long_version = format!(
"{} ({}, {})\nv8 {}\ntypescript {}",
crate::version::deno(),
crate::version::DENO_VERSION_INFO.deno,
// TODO(bartlomieju): alter what's printed here.
// I think it's best if we print as follows:
// <version>(+<short_git_hash>) (<release_channel>, <profile>, <target>)
@ -1346,14 +1346,17 @@ pub fn clap_root() -> Command {
// v2.1.13-lts (LTS (long term support), release, aarch64-apple-darwin)
// For canary it would be:
// v1.46.0+25bb59d (canary, release, aarch64-apple-darwin)
if matches!(crate::version::RELEASE_CHANNEL, ReleaseChannel::Canary) {
if matches!(
crate::version::DENO_VERSION_INFO.release_channel,
ReleaseChannel::Canary
) {
"canary"
} else {
env!("PROFILE")
},
env!("TARGET"),
deno_core::v8_version(),
crate::version::TYPESCRIPT
crate::version::DENO_VERSION_INFO.typescript
);
let mut cmd = run_args(Command::new("deno"), true)
@ -1368,7 +1371,7 @@ pub fn clap_root() -> Command {
)
.color(ColorChoice::Auto)
.term_width(800)
.version(crate::version::deno())
.version(crate::version::DENO_VERSION_INFO.deno)
.long_version(long_version)
// cause --unstable flags to display at the bottom of the help text
.next_display_order(1000)

View File

@ -1293,7 +1293,10 @@ impl CliOptions {
return Ok(None);
};
Ok(Some(InspectorServer::new(host, version::get_user_agent())?))
Ok(Some(InspectorServer::new(
host,
version::DENO_VERSION_INFO.user_agent,
)?))
}
pub fn maybe_lockfile(&self) -> Option<&Arc<CliLockfile>> {

View File

@ -5,6 +5,7 @@ use std::path::PathBuf;
use deno_core::snapshot::*;
use deno_runtime::*;
mod shared;
mod ts {
use super::*;
@ -329,18 +330,7 @@ mod ts {
fn create_cli_snapshot(snapshot_path: PathBuf) {
use deno_runtime::ops::bootstrap::SnapshotOptions;
// NOTE(bartlomieju): keep in sync with `cli/version.rs`.
// Ideally we could deduplicate that code.
fn deno_version() -> String {
if env::var("DENO_CANARY").is_ok() {
format!("{}+{}", env!("CARGO_PKG_VERSION"), &git_commit_hash()[..7])
} else {
env!("CARGO_PKG_VERSION").to_string()
}
}
let snapshot_options = SnapshotOptions {
deno_version: deno_version(),
ts_version: ts::version(),
v8_version: deno_core::v8_version(),
target: std::env::var("TARGET").unwrap(),

8
cli/cache/caches.rs vendored
View File

@ -48,9 +48,13 @@ impl Caches {
cell
.get_or_init(|| {
if let Some(path) = path {
CacheDB::from_path(config, path, crate::version::deno())
CacheDB::from_path(
config,
path,
crate::version::DENO_VERSION_INFO.deno,
)
} else {
CacheDB::in_memory(config, crate::version::deno())
CacheDB::in_memory(config, crate::version::DENO_VERSION_INFO.deno)
}
})
.clone()

2
cli/cache/common.rs vendored
View File

@ -12,7 +12,7 @@ impl FastInsecureHasher {
pub fn new_deno_versioned() -> Self {
let mut hasher = Self::new_without_deno_version();
hasher.write_str(crate::version::deno());
hasher.write_str(crate::version::DENO_VERSION_INFO.deno);
hasher
}

2
cli/cache/emit.rs vendored
View File

@ -30,7 +30,7 @@ impl EmitCache {
pub fn new(disk_cache: DiskCache) -> Self {
Self {
disk_cache,
cli_version: crate::version::deno(),
cli_version: crate::version::DENO_VERSION_INFO.deno,
emit_failed_flag: Default::default(),
}
}

View File

@ -2,7 +2,7 @@
use crate::auth_tokens::AuthToken;
use crate::util::progress_bar::UpdateGuard;
use crate::version::get_user_agent;
use crate::version;
use cache_control::Cachability;
use cache_control::CacheControl;
@ -248,7 +248,7 @@ impl HttpClientProvider {
Entry::Occupied(entry) => Ok(HttpClient::new(entry.get().clone())),
Entry::Vacant(entry) => {
let client = create_http_client(
get_user_agent(),
version::DENO_VERSION_INFO.user_agent,
CreateHttpClientOptions {
root_cert_store: match &self.root_cert_store_provider {
Some(provider) => Some(provider.get_or_try_init()?.clone()),
@ -948,7 +948,7 @@ mod test {
let client = HttpClient::new(
create_http_client(
version::get_user_agent(),
version::DENO_VERSION_INFO.user_agent,
CreateHttpClientOptions {
ca_certs: vec![std::fs::read(
test_util::testdata_path().join("tls/RootCA.pem"),
@ -1000,7 +1000,7 @@ mod test {
let client = HttpClient::new(
create_http_client(
version::get_user_agent(),
version::DENO_VERSION_INFO.user_agent,
CreateHttpClientOptions::default(),
)
.unwrap(),
@ -1059,7 +1059,7 @@ mod test {
let client = HttpClient::new(
create_http_client(
version::get_user_agent(),
version::DENO_VERSION_INFO.user_agent,
CreateHttpClientOptions {
root_cert_store: Some(root_cert_store),
..Default::default()
@ -1108,7 +1108,7 @@ mod test {
.unwrap();
let client = HttpClient::new(
create_http_client(
version::get_user_agent(),
version::DENO_VERSION_INFO.user_agent,
CreateHttpClientOptions {
ca_certs: vec![std::fs::read(
test_util::testdata_path()
@ -1149,7 +1149,7 @@ mod test {
let url = Url::parse("https://localhost:5545/etag_script.ts").unwrap();
let client = HttpClient::new(
create_http_client(
version::get_user_agent(),
version::DENO_VERSION_INFO.user_agent,
CreateHttpClientOptions {
ca_certs: vec![std::fs::read(
test_util::testdata_path()
@ -1205,7 +1205,7 @@ mod test {
.unwrap();
let client = HttpClient::new(
create_http_client(
version::get_user_agent(),
version::DENO_VERSION_INFO.user_agent,
CreateHttpClientOptions {
ca_certs: vec![std::fs::read(
test_util::testdata_path()

View File

@ -691,7 +691,7 @@ impl Inner {
let version = format!(
"{} ({}, {})",
crate::version::deno(),
crate::version::DENO_VERSION_INFO.deno,
env!("PROFILE"),
env!("TARGET")
);

View File

@ -314,7 +314,7 @@ fn setup_panic_hook() {
eprintln!("var set and include the backtrace in your report.");
eprintln!();
eprintln!("Platform: {} {}", env::consts::OS, env::consts::ARCH);
eprintln!("Version: {}", version::deno());
eprintln!("Version: {}", version::DENO_VERSION_INFO.deno);
eprintln!("Args: {:?}", env::args().collect::<Vec<_>>());
eprintln!();
orig_hook(panic_info);

View File

@ -1,5 +1,6 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
/// This module is shared between build script and the binaries. Use it sparsely.
use deno_core::anyhow::bail;
use deno_core::error::AnyError;

View File

@ -417,18 +417,23 @@ impl<'a> DenoCompileBinaryWriter<'a> {
let target = compile_flags.resolve_target();
let binary_name = format!("denort-{target}.zip");
let binary_path_suffix = match crate::version::RELEASE_CHANNEL {
ReleaseChannel::Canary => {
format!("canary/{}/{}", crate::version::GIT_COMMIT_HASH, binary_name)
}
ReleaseChannel::Stable => {
format!("release/v{}/{}", env!("CARGO_PKG_VERSION"), binary_name)
}
_ => bail!(
"`deno compile` current doesn't support {} release channel",
crate::version::RELEASE_CHANNEL.name()
),
};
let binary_path_suffix =
match crate::version::DENO_VERSION_INFO.release_channel {
ReleaseChannel::Canary => {
format!(
"canary/{}/{}",
crate::version::DENO_VERSION_INFO.git_hash,
binary_name
)
}
ReleaseChannel::Stable => {
format!("release/v{}/{}", env!("CARGO_PKG_VERSION"), binary_name)
}
_ => bail!(
"`deno compile` current doesn't support {} release channel",
crate::version::DENO_VERSION_INFO.release_channel.name()
),
};
let download_directory = self.deno_dir.dl_folder_path();
let binary_path = download_directory.join(&binary_path_suffix);

View File

@ -13,7 +13,6 @@ use crate::util::file_watcher;
use crate::util::fs::collect_specifiers;
use crate::util::path::is_script_ext;
use crate::util::path::matches_pattern_or_exact_path;
use crate::version::get_user_agent;
use crate::worker::CliMainWorkerFactory;
use deno_config::glob::WalkEntry;

View File

@ -2,6 +2,8 @@
use serde::Serialize;
use crate::version;
use super::*;
pub trait BenchReporter {
@ -25,7 +27,11 @@ struct JsonReporterOutput {
impl Default for JsonReporterOutput {
fn default() -> Self {
Self {
runtime: format!("{} {}", get_user_agent(), env!("TARGET")),
runtime: format!(
"{} {}",
version::DENO_VERSION_INFO.user_agent,
env!("TARGET")
),
cpu: mitata::cpu::name(),
benches: vec![],
}
@ -150,7 +156,7 @@ impl BenchReporter for ConsoleReporter {
"{}\n",
colors::gray(format!(
"runtime: deno {} ({})",
crate::version::deno(),
crate::version::DENO_VERSION_INFO.deno,
env!("TARGET")
))
);

View File

@ -670,10 +670,10 @@ fn kernel_info() -> messaging::KernelInfoReply {
status: ReplyStatus::Ok,
protocol_version: "5.3".to_string(),
implementation: "Deno kernel".to_string(),
implementation_version: crate::version::deno().to_string(),
implementation_version: crate::version::DENO_VERSION_INFO.deno.to_string(),
language_info: messaging::LanguageInfo {
name: "typescript".to_string(),
version: crate::version::TYPESCRIPT.to_string(),
version: crate::version::DENO_VERSION_INFO.typescript.to_string(),
mimetype: "text/x.typescript".to_string(),
file_extension: ".ts".to_string(),
pygments_lexer: "typescript".to_string(),

View File

@ -242,7 +242,7 @@ pub async fn run(
// Doing this manually, instead of using `log::info!` because these messages
// are supposed to go to stdout, not stderr.
if !cli_options.is_quiet() {
println!("Deno {}", crate::version::deno());
println!("Deno {}", crate::version::DENO_VERSION_INFO.deno);
println!("exit using ctrl+d, ctrl+c, or close()");
if repl_flags.is_default_command {
println!(

View File

@ -140,7 +140,7 @@ impl VersionProvider for RealVersionProvider {
}
fn current_version(&self) -> Cow<str> {
Cow::Borrowed(version::release_version_or_canary_commit_hash())
Cow::Borrowed(version::DENO_VERSION_INFO.version_or_git_hash())
}
// TODO(bartlomieju): update to handle `Lts` channel
@ -148,7 +148,10 @@ impl VersionProvider for RealVersionProvider {
&self,
) -> Result<ReleaseChannel, AnyError> {
// TODO(bartlomieju): remove hitting a remote server
if matches!(version::RELEASE_CHANNEL, ReleaseChannel::Canary) {
if matches!(
version::DENO_VERSION_INFO.release_channel,
ReleaseChannel::Canary
) {
// If this fails for whatever reason, just return an empty vector.
// It's better to miss that than throw error here.
let rc_versions = get_rc_versions(
@ -160,7 +163,7 @@ impl VersionProvider for RealVersionProvider {
let is_current_exe_an_rc = rc_versions
.iter()
.any(|(hash, _)| hash == version::GIT_COMMIT_HASH);
.any(|(hash, _)| hash == version::DENO_VERSION_INFO.git_hash);
if is_current_exe_an_rc {
Ok(ReleaseChannel::Rc)
@ -338,7 +341,7 @@ pub fn check_for_upgrades(
log::info!(
"{} {} → {} {}",
colors::green("A new release of Deno is available:"),
colors::cyan(version::deno()),
colors::cyan(version::DENO_VERSION_INFO.deno),
colors::cyan(&upgrade_version),
colors::italic_gray("Run `deno upgrade` to install it.")
);
@ -546,7 +549,7 @@ pub async fn upgrade(
log::info!("Upgraded successfully (dry run)");
if !requested_version.is_canary() {
print_release_notes(
version::deno(),
version::DENO_VERSION_INFO.deno,
&selected_version_to_upgrade.version_or_hash,
);
}
@ -569,7 +572,10 @@ pub async fn upgrade(
colors::green(selected_version_to_upgrade.display())
);
if !requested_version.is_canary() {
print_release_notes(version::deno(), &selected_version_to_upgrade.display);
print_release_notes(
version::DENO_VERSION_INFO.deno,
&selected_version_to_upgrade.display,
);
}
drop(temp_dir); // delete the temp dir
@ -638,15 +644,20 @@ fn select_specific_version_for_upgrade(
) -> Result<Option<AvailableVersion>, AnyError> {
match release_channel {
ReleaseChannel::Stable => {
let current_is_passed =
if !matches!(version::RELEASE_CHANNEL, ReleaseChannel::Canary) {
version::deno() == version
} else {
false
};
let current_is_passed = if !matches!(
version::DENO_VERSION_INFO.release_channel,
ReleaseChannel::Canary
) {
version::DENO_VERSION_INFO.deno == version
} else {
false
};
if !force && current_is_passed {
log::info!("Version {} is already installed", version::deno());
log::info!(
"Version {} is already installed",
version::DENO_VERSION_INFO.deno
);
return Ok(None);
}
@ -657,9 +668,12 @@ fn select_specific_version_for_upgrade(
}))
}
ReleaseChannel::Canary => {
let current_is_passed = version::GIT_COMMIT_HASH == version;
let current_is_passed = version::DENO_VERSION_INFO.git_hash == version;
if !force && current_is_passed {
log::info!("Version {} is already installed", version::deno());
log::info!(
"Version {} is already installed",
version::DENO_VERSION_INFO.deno
);
return Ok(None);
}
@ -693,17 +707,19 @@ async fn find_latest_version_to_upgrade(
let (maybe_newer_latest_version, current_version) = match release_channel {
ReleaseChannel::Stable => {
let current_version = version::deno();
let current_is_most_recent =
if !matches!(version::RELEASE_CHANNEL, ReleaseChannel::Canary) {
let current = Version::parse_standard(current_version).unwrap();
let latest =
Version::parse_standard(&latest_version_found.version_or_hash)
.unwrap();
current >= latest
} else {
false
};
let current_version = version::DENO_VERSION_INFO.deno;
let current_is_most_recent = if !matches!(
version::DENO_VERSION_INFO.release_channel,
ReleaseChannel::Canary
) {
let current = Version::parse_standard(current_version).unwrap();
let latest =
Version::parse_standard(&latest_version_found.version_or_hash)
.unwrap();
current >= latest
} else {
false
};
if !force && current_is_most_recent {
(None, current_version)
@ -712,7 +728,7 @@ async fn find_latest_version_to_upgrade(
}
}
ReleaseChannel::Canary => {
let current_version = version::GIT_COMMIT_HASH;
let current_version = version::DENO_VERSION_INFO.git_hash;
let current_is_most_recent =
current_version == latest_version_found.version_or_hash;
@ -723,7 +739,7 @@ async fn find_latest_version_to_upgrade(
}
}
ReleaseChannel::Rc => {
let current_version = version::GIT_COMMIT_HASH;
let current_version = version::DENO_VERSION_INFO.git_hash;
let current_is_most_recent =
current_version == latest_version_found.version_or_hash;
@ -1054,7 +1070,7 @@ impl CheckVersionFile {
self.last_checked.to_rfc3339(),
self.latest_version,
self.current_version,
self.current_release_channel.serialize(),
self.current_release_channel.serialize()
)
}

View File

@ -1,47 +1,86 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use once_cell::sync::Lazy;
use crate::shared::ReleaseChannel;
pub const GIT_COMMIT_HASH: &str = env!("GIT_COMMIT_HASH");
pub const TYPESCRIPT: &str = env!("TS_VERSION");
const GIT_COMMIT_HASH: &str = env!("GIT_COMMIT_HASH");
const TYPESCRIPT: &str = env!("TS_VERSION");
const CARGO_PKG_VERSION: &str = env!("CARGO_PKG_VERSION");
// TODO(bartlomieju): ideally we could remove this const.
const IS_CANARY: bool = option_env!("DENO_CANARY").is_some();
pub const RELEASE_CHANNEL: ReleaseChannel = if IS_CANARY {
ReleaseChannel::Canary
} else {
ReleaseChannel::Stable
};
pub fn deno() -> &'static str {
if IS_CANARY {
concat!(
env!("CARGO_PKG_VERSION"),
"+",
env!("GIT_COMMIT_HASH_SHORT")
)
} else {
env!("CARGO_PKG_VERSION")
pub static DENO_VERSION_INFO: Lazy<DenoVersionInfo> = Lazy::new(|| {
let release_channel = libsui::find_section("denover")
.and_then(|buf| std::str::from_utf8(buf).ok())
.and_then(|str_| ReleaseChannel::deserialize(str_).ok())
.unwrap_or({
if IS_CANARY {
ReleaseChannel::Canary
} else {
ReleaseChannel::Stable
}
});
DenoVersionInfo {
// TODO(bartlomieju): fix further for RC and LTS releases
deno: if IS_CANARY {
concat!(
env!("CARGO_PKG_VERSION"),
"+",
env!("GIT_COMMIT_HASH_SHORT")
)
} else {
env!("CARGO_PKG_VERSION")
},
release_channel,
git_hash: GIT_COMMIT_HASH,
// Keep in sync with `deno` field.
// TODO(bartlomieju): fix further for RC and LTS releases
user_agent: if IS_CANARY {
concat!(
"Deno/",
env!("CARGO_PKG_VERSION"),
"+",
env!("GIT_COMMIT_HASH_SHORT")
)
} else {
concat!("Deno/", env!("CARGO_PKG_VERSION"))
},
typescript: TYPESCRIPT,
}
});
pub struct DenoVersionInfo {
/// Human-readable version of the current Deno binary.
///
/// For stable release, a semver, eg. `v1.46.2`.
/// For canary release, a semver + 7-char git hash, eg. `v1.46.3+asdfqwq`.
pub deno: &'static str,
pub release_channel: ReleaseChannel,
/// A full git hash.
pub git_hash: &'static str,
/// A user-agent header that will be used in HTTP client.
pub user_agent: &'static str,
pub typescript: &'static str,
}
// Keep this in sync with `deno()` above
pub fn get_user_agent() -> &'static str {
if IS_CANARY {
concat!(
"Deno/",
env!("CARGO_PKG_VERSION"),
"+",
env!("GIT_COMMIT_HASH_SHORT")
)
} else {
concat!("Deno/", env!("CARGO_PKG_VERSION"))
}
}
pub fn release_version_or_canary_commit_hash() -> &'static str {
if IS_CANARY {
GIT_COMMIT_HASH
} else {
env!("CARGO_PKG_VERSION")
impl DenoVersionInfo {
/// For stable release, a semver like, eg. `v1.46.2`.
/// For canary release a full git hash, eg. `9bdab6fb6b93eb43b1930f40987fa4997287f9c8`.
pub fn version_or_git_hash(&self) -> &'static str {
if IS_CANARY {
self.git_hash
} else {
CARGO_PKG_VERSION
}
}
}

View File

@ -581,6 +581,7 @@ impl CliMainWorkerFactory {
let options = WorkerOptions {
bootstrap: BootstrapOptions {
deno_version: crate::version::DENO_VERSION_INFO.deno.to_string(),
args: shared.options.argv.clone(),
cpu_count: std::thread::available_parallelism()
.map(|p| p.get())
@ -596,7 +597,7 @@ impl CliMainWorkerFactory {
color_level: colors::get_color_level(),
unstable: shared.options.unstable,
unstable_features,
user_agent: version::get_user_agent().to_string(),
user_agent: version::DENO_VERSION_INFO.user_agent.to_string(),
inspect: shared.options.is_inspecting,
has_node_modules_dir: shared.options.has_node_modules_dir,
argv0: shared.options.argv0.clone(),
@ -778,6 +779,7 @@ fn create_web_worker_callback(
let options = WebWorkerOptions {
bootstrap: BootstrapOptions {
deno_version: crate::version::DENO_VERSION_INFO.deno.to_string(),
args: shared.options.argv.clone(),
cpu_count: std::thread::available_parallelism()
.map(|p| p.get())
@ -793,7 +795,7 @@ fn create_web_worker_callback(
is_stderr_tty: deno_terminal::is_stderr_tty(),
unstable: shared.options.unstable,
unstable_features,
user_agent: version::get_user_agent().to_string(),
user_agent: version::DENO_VERSION_INFO.user_agent.to_string(),
inspect: shared.options.is_inspecting,
has_node_modules_dir: shared.options.has_node_modules_dir,
argv0: shared.options.argv0.clone(),

View File

@ -672,7 +672,6 @@ ObjectDefineProperties(finalDenoNs, {
});
const {
denoVersion,
tsVersion,
v8Version,
target,
@ -697,21 +696,22 @@ function bootstrapMainRuntime(runtimeOptions, warmup = false) {
}
const {
0: location_,
1: unstableFlag,
2: unstableFeatures,
3: inspectFlag,
5: hasNodeModulesDir,
6: argv0,
7: nodeDebug,
8: shouldDisableDeprecatedApiWarning,
9: shouldUseVerboseDeprecatedApiWarning,
10: future,
11: mode,
12: servePort,
13: serveHost,
14: serveIsMain,
15: serveWorkerCount,
0: denoVersion,
1: location_,
2: unstableFlag,
3: unstableFeatures,
4: inspectFlag,
6: hasNodeModulesDir,
7: argv0,
8: nodeDebug,
9: shouldDisableDeprecatedApiWarning,
10: shouldUseVerboseDeprecatedApiWarning,
11: future,
12: mode,
13: servePort,
14: serveHost,
15: serveIsMain,
16: serveWorkerCount,
} = runtimeOptions;
if (mode === executionModes.serve) {
@ -970,16 +970,17 @@ function bootstrapWorkerRuntime(
}
const {
0: location_,
1: unstableFlag,
2: unstableFeatures,
4: enableTestingFeaturesFlag,
5: hasNodeModulesDir,
6: argv0,
7: nodeDebug,
8: shouldDisableDeprecatedApiWarning,
9: shouldUseVerboseDeprecatedApiWarning,
10: future,
0: denoVersion,
1: location_,
2: unstableFlag,
3: unstableFeatures,
5: enableTestingFeaturesFlag,
6: hasNodeModulesDir,
7: argv0,
8: nodeDebug,
9: shouldDisableDeprecatedApiWarning,
10: shouldUseVerboseDeprecatedApiWarning,
11: future,
} = runtimeOptions;
// TODO(iuioiua): remove in Deno v2. This allows us to dynamically delete

View File

@ -36,7 +36,6 @@ deno_core::extension!(
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SnapshotOptions {
pub deno_version: String,
pub ts_version: String,
pub v8_version: &'static str,
pub target: String,
@ -54,7 +53,6 @@ impl Default for SnapshotOptions {
};
Self {
deno_version: "dev".to_owned(),
ts_version: "n/a".to_owned(),
v8_version: deno_core::v8_version(),
target,

View File

@ -92,6 +92,7 @@ impl From<log::Level> for WorkerLogLevel {
/// Common bootstrap options for MainWorker & WebWorker
#[derive(Clone)]
pub struct BootstrapOptions {
pub deno_version: String,
/// Sets `Deno.args` in JS runtime.
pub args: Vec<String>,
pub cpu_count: usize,
@ -134,6 +135,7 @@ impl Default for BootstrapOptions {
let user_agent = format!("Deno/{runtime_version}");
Self {
deno_version: runtime_version.to_string(),
user_agent,
cpu_count,
no_color: !colors::use_color(),
@ -174,6 +176,8 @@ impl Default for BootstrapOptions {
/// Keep this in sync with `99_main.js`.
#[derive(Serialize)]
struct BootstrapV8<'a>(
// deno version
&'a str,
// location
Option<&'a str>,
// unstable
@ -219,6 +223,7 @@ impl BootstrapOptions {
let (serve_is_main, serve_worker_count) = self.mode.serve_info();
let bootstrap = BootstrapV8(
&self.deno_version,
self.location.as_ref().map(|l| l.as_str()),
self.unstable,
self.unstable_features.as_ref(),