diff --git a/cli/download_deno_binary.rs b/cli/download_deno_binary.rs new file mode 100644 index 0000000000..4b44949d76 --- /dev/null +++ b/cli/download_deno_binary.rs @@ -0,0 +1,97 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +use std::path::Path; +use std::path::PathBuf; + +use crate::http_util::HttpClient; +use crate::http_util::HttpClientProvider; +use crate::util::progress_bar::ProgressBar; +use crate::util::progress_bar::ProgressBarStyle; +use deno_core::anyhow::bail; +use deno_core::error::AnyError; + +use crate::cache::DenoDir; +use crate::shared::ReleaseChannel; + +#[derive(Clone, Copy, Debug)] +pub enum BinaryKind { + Deno, + Denort, +} + +impl BinaryKind { + pub fn name(&self) -> &str { + match self { + BinaryKind::Deno => "deno", + BinaryKind::Denort => "denort", + } + } +} + +pub async fn download_deno_binary( + http_client_provider: &HttpClientProvider, + deno_dir: &DenoDir, + binary_kind: BinaryKind, + target: &str, + version_or_git_hash: &str, + release_channel: ReleaseChannel, +) -> Result { + let binary_name = archive_name(binary_kind, target); + let binary_path_suffix = match release_channel { + ReleaseChannel::Canary => { + format!("canary/{}/{}", version_or_git_hash, binary_name,) + } + _ => { + format!("release/v{}/{}", version_or_git_hash, binary_name) + } + }; + + let download_directory = deno_dir.dl_folder_path(); + let binary_path = download_directory.join(&binary_path_suffix); + + if !binary_path.exists() { + let http_client = http_client_provider.get_or_create()?; + download_base_binary( + &http_client, + &download_directory, + &binary_path_suffix, + ) + .await?; + } + + Ok(binary_path) +} + +pub fn archive_name(binary_kind: BinaryKind, target: &str) -> String { + format!("{}-{}.zip", binary_kind.name(), target) +} + +async fn download_base_binary( + http_client: &HttpClient, + output_directory: &Path, + binary_path_suffix: &str, +) -> Result<(), AnyError> { + let download_url = format!("https://dl.deno.land/{binary_path_suffix}"); + let maybe_bytes = { + let progress_bars = ProgressBar::new(ProgressBarStyle::DownloadBars); + // provide an empty string here in order to prefer the downloading + // text above which will stay alive after the progress bars are complete + let progress = progress_bars.update(""); + http_client + .download_with_progress_and_retries( + download_url.parse()?, + None, + &progress, + ) + .await? + }; + let Some(bytes) = maybe_bytes else { + bail!("Failed downloading {download_url}. The version you requested may not have been built for the current architecture."); + }; + + std::fs::create_dir_all(output_directory)?; + let output_path = output_directory.join(binary_path_suffix); + std::fs::create_dir_all(output_path.parent().unwrap())?; + tokio::fs::write(output_path, bytes).await?; + Ok(()) +} diff --git a/cli/main.rs b/cli/main.rs index 04daff6700..59a1fb0cda 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -4,6 +4,7 @@ mod args; mod auth_tokens; mod cache; mod cdp; +mod download_deno_binary; mod emit; mod errors; mod factory; diff --git a/cli/mainrt.rs b/cli/mainrt.rs index f5b798f817..9af61e1288 100644 --- a/cli/mainrt.rs +++ b/cli/mainrt.rs @@ -10,6 +10,7 @@ mod standalone; mod args; mod auth_tokens; mod cache; +mod download_deno_binary; mod emit; mod errors; mod file_fetcher; diff --git a/cli/ops/bench.rs b/cli/ops/bench.rs index 79a7ddef0e..1f4a4bd9b5 100644 --- a/cli/ops/bench.rs +++ b/cli/ops/bench.rs @@ -2,7 +2,6 @@ use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; -use std::time; use deno_core::error::generic_error; use deno_core::error::type_error; @@ -13,6 +12,7 @@ use deno_core::ModuleSpecifier; use deno_core::OpState; use deno_runtime::deno_permissions::ChildPermissionsArg; use deno_runtime::deno_permissions::PermissionsContainer; +use deno_runtime::deno_web::StartTime; use tokio::sync::mpsc::UnboundedSender; use uuid::Uuid; @@ -148,7 +148,7 @@ fn op_dispatch_bench_event(state: &mut OpState, #[serde] event: BenchEvent) { #[op2(fast)] #[number] fn op_bench_now(state: &mut OpState) -> Result { - let ns = state.borrow::().elapsed().as_nanos(); + let ns = state.borrow::().elapsed().as_nanos(); let ns_u64 = u64::try_from(ns)?; Ok(ns_u64) } diff --git a/cli/standalone/binary.rs b/cli/standalone/binary.rs index 9e26512268..a81e40ad96 100644 --- a/cli/standalone/binary.rs +++ b/cli/standalone/binary.rs @@ -63,6 +63,9 @@ use crate::args::NpmInstallDepsProvider; use crate::args::PermissionFlags; use crate::args::UnstableConfig; use crate::cache::DenoDir; +use crate::download_deno_binary::archive_name; +use crate::download_deno_binary::download_deno_binary; +use crate::download_deno_binary::BinaryKind; use crate::emit::Emitter; use crate::file_fetcher::FileFetcher; use crate::http_util::HttpClientProvider; @@ -452,36 +455,24 @@ impl<'a> DenoCompileBinaryWriter<'a> { } let target = compile_flags.resolve_target(); - let binary_name = format!("denort-{target}.zip"); - 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 - ) - } - _ => { - format!("release/v{}/{}", env!("CARGO_PKG_VERSION"), binary_name) - } - }; + let archive_name = archive_name(BinaryKind::Denort, &target); - let download_directory = self.deno_dir.dl_folder_path(); - let binary_path = download_directory.join(&binary_path_suffix); - - if !binary_path.exists() { - self - .download_base_binary(&download_directory, &binary_path_suffix) - .await?; - } + let binary_path = download_deno_binary( + self.http_client_provider, + self.deno_dir, + BinaryKind::Denort, + &target, + crate::version::DENO_VERSION_INFO.version_or_git_hash(), + crate::version::DENO_VERSION_INFO.release_channel, + ) + .await?; let archive_data = std::fs::read(binary_path)?; let temp_dir = tempfile::TempDir::new()?; let base_binary_path = archive::unpack_into_dir(archive::UnpackArgs { - exe_name: "denort", - archive_name: &binary_name, + exe_name: BinaryKind::Denort.name(), + archive_name: &archive_name, archive_data: &archive_data, is_windows: target.contains("windows"), dest_path: temp_dir.path(), @@ -491,41 +482,6 @@ impl<'a> DenoCompileBinaryWriter<'a> { Ok(base_binary) } - async fn download_base_binary( - &self, - output_directory: &Path, - binary_path_suffix: &str, - ) -> Result<(), AnyError> { - let download_url = format!("https://dl.deno.land/{binary_path_suffix}"); - let maybe_bytes = { - let progress_bars = ProgressBar::new(ProgressBarStyle::DownloadBars); - let progress = progress_bars.update(&download_url); - - self - .http_client_provider - .get_or_create()? - .download_with_progress_and_retries( - download_url.parse()?, - None, - &progress, - ) - .await? - }; - let bytes = match maybe_bytes { - Some(bytes) => bytes, - None => { - log::info!("Download could not be found, aborting"); - std::process::exit(1) - } - }; - - std::fs::create_dir_all(output_directory)?; - let output_path = output_directory.join(binary_path_suffix); - std::fs::create_dir_all(output_path.parent().unwrap())?; - tokio::fs::write(output_path, bytes).await?; - Ok(()) - } - /// This functions creates a standalone deno binary by appending a bundle /// and magic trailer to the currently executing binary. #[allow(clippy::too_many_arguments)] diff --git a/cli/tools/registry/pm/cache_deps.rs b/cli/tools/registry/pm/cache_deps.rs index 365622d11f..d3c8da868c 100644 --- a/cli/tools/registry/pm/cache_deps.rs +++ b/cli/tools/registry/pm/cache_deps.rs @@ -44,7 +44,11 @@ pub async fn cache_top_level_deps( let mut seen_reqs = std::collections::HashSet::new(); - for entry in import_map.imports().entries() { + for entry in import_map.imports().entries().chain( + import_map + .scopes() + .flat_map(|scope| scope.imports.entries()), + ) { let Some(specifier) = entry.value else { continue; }; diff --git a/cli/tools/upgrade.rs b/cli/tools/upgrade.rs index 77a9f72b80..ed1bc06cfb 100644 --- a/cli/tools/upgrade.rs +++ b/cli/tools/upgrade.rs @@ -6,13 +6,14 @@ use crate::args::Flags; use crate::args::UpgradeFlags; use crate::args::UPGRADE_USAGE; use crate::colors; +use crate::download_deno_binary::archive_name; +use crate::download_deno_binary::download_deno_binary; +use crate::download_deno_binary::BinaryKind; use crate::factory::CliFactory; use crate::http_util::HttpClient; use crate::http_util::HttpClientProvider; use crate::shared::ReleaseChannel; use crate::util::archive; -use crate::util::progress_bar::ProgressBar; -use crate::util::progress_bar::ProgressBarStyle; use crate::version; use async_trait::async_trait; @@ -34,12 +35,8 @@ use std::process::Command; use std::sync::Arc; use std::time::Duration; -const RELEASE_URL: &str = "https://github.com/denoland/deno/releases"; -const CANARY_URL: &str = "https://dl.deno.land/canary"; -const DL_RELEASE_URL: &str = "https://dl.deno.land/release"; - -pub static ARCHIVE_NAME: Lazy = - Lazy::new(|| format!("deno-{}.zip", env!("TARGET"))); +static ARCHIVE_NAME: Lazy = + Lazy::new(|| archive_name(BinaryKind::Deno, env!("TARGET"))); // How often query server for new version. In hours. const UPGRADE_CHECK_INTERVAL: i64 = 24; @@ -532,13 +529,17 @@ pub async fn upgrade( return Ok(()); }; - let download_url = get_download_url( + let binary_path = download_deno_binary( + http_client_provider, + factory.deno_dir()?, + BinaryKind::Deno, + env!("TARGET"), &selected_version_to_upgrade.version_or_hash, requested_version.release_channel(), - )?; - log::info!("{}", colors::gray(format!("Downloading {}", &download_url))); - let Some(archive_data) = download_package(&client, download_url).await? - else { + ) + .await?; + + let Ok(archive_data) = tokio::fs::read(&binary_path).await else { log::error!("Download could not be found, aborting"); std::process::exit(1) }; @@ -881,48 +882,6 @@ fn base_upgrade_url() -> Cow<'static, str> { } } -fn get_download_url( - version: &str, - release_channel: ReleaseChannel, -) -> Result { - let download_url = match release_channel { - ReleaseChannel::Stable => { - format!("{}/download/v{}/{}", RELEASE_URL, version, *ARCHIVE_NAME) - } - ReleaseChannel::Rc => { - format!("{}/v{}/{}", DL_RELEASE_URL, version, *ARCHIVE_NAME) - } - ReleaseChannel::Canary => { - format!("{}/{}/{}", CANARY_URL, version, *ARCHIVE_NAME) - } - ReleaseChannel::Lts => { - format!("{}/v{}/{}", DL_RELEASE_URL, version, *ARCHIVE_NAME) - } - }; - - Url::parse(&download_url).with_context(|| { - format!( - "Failed to parse URL to download new release: {}", - download_url - ) - }) -} - -async fn download_package( - client: &HttpClient, - download_url: Url, -) -> Result>, AnyError> { - let progress_bar = ProgressBar::new(ProgressBarStyle::DownloadBars); - // provide an empty string here in order to prefer the downloading - // text above which will stay alive after the progress bars are complete - let progress = progress_bar.update(""); - let maybe_bytes = client - .download_with_progress_and_retries(download_url.clone(), None, &progress) - .await - .with_context(|| format!("Failed downloading {download_url}. The version you requested may not have been built for the current architecture."))?; - Ok(maybe_bytes) -} - fn replace_exe(from: &Path, to: &Path) -> Result<(), std::io::Error> { if cfg!(windows) { // On windows you cannot replace the currently running executable. diff --git a/ext/web/02_timers.js b/ext/web/02_timers.js index 89acaca42b..6058febd59 100644 --- a/ext/web/02_timers.js +++ b/ext/web/02_timers.js @@ -1,12 +1,9 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. import { core, primordials } from "ext:core/mod.js"; -import { op_defer, op_now } from "ext:core/ops"; +import { op_defer } from "ext:core/ops"; const { - Uint8Array, - Uint32Array, PromisePrototypeThen, - TypedArrayPrototypeGetBuffer, TypeError, indirectEval, ReflectApply, @@ -18,13 +15,6 @@ const { import * as webidl from "ext:deno_webidl/00_webidl.js"; -const hrU8 = new Uint8Array(8); -const hr = new Uint32Array(TypedArrayPrototypeGetBuffer(hrU8)); -function opNow() { - op_now(hrU8); - return (hr[0] * 1000 + hr[1] / 1e6); -} - // --------------------------------------------------------------------------- function checkThis(thisArg) { @@ -151,7 +141,6 @@ export { clearInterval, clearTimeout, defer, - opNow, refTimer, setImmediate, setInterval, diff --git a/ext/web/15_performance.js b/ext/web/15_performance.js index ea55572781..9e0e310a57 100644 --- a/ext/web/15_performance.js +++ b/ext/web/15_performance.js @@ -1,6 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. import { primordials } from "ext:core/mod.js"; +import { op_now, op_time_origin } from "ext:core/ops"; const { ArrayPrototypeFilter, ArrayPrototypePush, @@ -10,19 +11,34 @@ const { Symbol, SymbolFor, TypeError, + TypedArrayPrototypeGetBuffer, + Uint8Array, + Uint32Array, } = primordials; import * as webidl from "ext:deno_webidl/00_webidl.js"; import { structuredClone } from "./02_structured_clone.js"; import { createFilteredInspectProxy } from "ext:deno_console/01_console.js"; import { EventTarget } from "./02_event.js"; -import { opNow } from "./02_timers.js"; import { DOMException } from "./01_dom_exception.js"; const illegalConstructorKey = Symbol("illegalConstructorKey"); let performanceEntries = []; let timeOrigin; +const hrU8 = new Uint8Array(8); +const hr = new Uint32Array(TypedArrayPrototypeGetBuffer(hrU8)); + +function setTimeOrigin() { + op_time_origin(hrU8); + timeOrigin = hr[0] * 1000 + hr[1] / 1e6; +} + +function now() { + op_now(hrU8); + return hr[0] * 1000 + hr[1] / 1e6; +} + webidl.converters["PerformanceMarkOptions"] = webidl .createDictionaryConverter( "PerformanceMarkOptions", @@ -90,10 +106,6 @@ webidl.converters["DOMString or PerformanceMeasureOptions"] = ( return webidl.converters.DOMString(V, prefix, context, opts); }; -function setTimeOrigin(origin) { - timeOrigin = origin; -} - function findMostRecent( name, type, @@ -135,8 +147,6 @@ function filterByNameType( ); } -const now = opNow; - const _name = Symbol("[[name]]"); const _entryType = Symbol("[[entryType]]"); const _startTime = Symbol("[[startTime]]"); diff --git a/ext/web/lib.rs b/ext/web/lib.rs index 4935af5bd3..af0fc2c276 100644 --- a/ext/web/lib.rs +++ b/ext/web/lib.rs @@ -52,7 +52,8 @@ pub use crate::message_port::Transferable; use crate::timers::op_defer; use crate::timers::op_now; -use crate::timers::StartTime; +use crate::timers::op_time_origin; +pub use crate::timers::StartTime; pub use crate::timers::TimersPermission; deno_core::extension!(deno_web, @@ -84,6 +85,7 @@ deno_core::extension!(deno_web, compression::op_compression_write, compression::op_compression_finish, op_now

, + op_time_origin

, op_defer, stream_resource::op_readable_stream_resource_allocate, stream_resource::op_readable_stream_resource_allocate_sized, @@ -123,7 +125,7 @@ deno_core::extension!(deno_web, if let Some(location) = options.maybe_location { state.put(Location(location)); } - state.put(StartTime::now()); + state.put(StartTime::default()); } ); diff --git a/ext/web/timers.rs b/ext/web/timers.rs index a9ab7c97e4..06444ed34f 100644 --- a/ext/web/timers.rs +++ b/ext/web/timers.rs @@ -4,7 +4,10 @@ use deno_core::op2; use deno_core::OpState; +use std::time::Duration; use std::time::Instant; +use std::time::SystemTime; +use std::time::UNIX_EPOCH; pub trait TimersPermission { fn allow_hrtime(&mut self) -> bool; @@ -17,21 +20,28 @@ impl TimersPermission for deno_permissions::PermissionsContainer { } } -pub type StartTime = Instant; +pub struct StartTime(Instant); -// Returns a milliseconds and nanoseconds subsec -// since the start time of the deno runtime. -// If the High precision flag is not set, the -// nanoseconds are rounded on 2ms. -#[op2(fast)] -pub fn op_now(state: &mut OpState, #[buffer] buf: &mut [u8]) +impl Default for StartTime { + fn default() -> Self { + Self(Instant::now()) + } +} + +impl std::ops::Deref for StartTime { + type Target = Instant; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn expose_time(state: &mut OpState, duration: Duration, out: &mut [u8]) where TP: TimersPermission + 'static, { - let start_time = state.borrow::(); - let elapsed = start_time.elapsed(); - let seconds = elapsed.as_secs(); - let mut subsec_nanos = elapsed.subsec_nanos(); + let seconds = duration.as_secs() as u32; + let mut subsec_nanos = duration.subsec_nanos(); // If the permission is not enabled // Round the nano result on 2 milliseconds @@ -40,14 +50,33 @@ where let reduced_time_precision = 2_000_000; // 2ms in nanoseconds subsec_nanos -= subsec_nanos % reduced_time_precision; } - if buf.len() < 8 { - return; + + if out.len() >= 8 { + out[0..4].copy_from_slice(&seconds.to_ne_bytes()); + out[4..8].copy_from_slice(&subsec_nanos.to_ne_bytes()); } - let buf: &mut [u32] = - // SAFETY: buffer is at least 8 bytes long. - unsafe { std::slice::from_raw_parts_mut(buf.as_mut_ptr() as _, 2) }; - buf[0] = seconds as u32; - buf[1] = subsec_nanos; +} + +#[op2(fast)] +pub fn op_now(state: &mut OpState, #[buffer] buf: &mut [u8]) +where + TP: TimersPermission + 'static, +{ + let start_time = state.borrow::(); + let elapsed = start_time.elapsed(); + expose_time::(state, elapsed, buf); +} + +#[op2(fast)] +pub fn op_time_origin(state: &mut OpState, #[buffer] buf: &mut [u8]) +where + TP: TimersPermission + 'static, +{ + // https://w3c.github.io/hr-time/#dfn-estimated-monotonic-time-of-the-unix-epoch + let wall_time = SystemTime::now(); + let monotonic_time = state.borrow::().elapsed(); + let epoch = wall_time.duration_since(UNIX_EPOCH).unwrap() - monotonic_time; + expose_time::(state, epoch, buf); } #[allow(clippy::unused_async)] diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js index 4d391dcc3a..6ddaa1335e 100644 --- a/runtime/js/99_main.js +++ b/runtime/js/99_main.js @@ -27,7 +27,6 @@ const { ArrayPrototypeForEach, ArrayPrototypeIncludes, ArrayPrototypeMap, - DateNow, Error, ErrorPrototype, FunctionPrototypeBind, @@ -642,7 +641,7 @@ function bootstrapMainRuntime(runtimeOptions, warmup = false) { removeImportedOps(); - performance.setTimeOrigin(DateNow()); + performance.setTimeOrigin(); globalThis_ = globalThis; // Remove bootstrapping data from the global scope @@ -858,7 +857,7 @@ function bootstrapWorkerRuntime( 7: nodeDebug, } = runtimeOptions; - performance.setTimeOrigin(DateNow()); + performance.setTimeOrigin(); globalThis_ = globalThis; // Remove bootstrapping data from the global scope diff --git a/tests/specs/install/installs_all_workspace_imports/__test__.jsonc b/tests/specs/install/installs_all_workspace_imports/__test__.jsonc new file mode 100644 index 0000000000..254fe8b989 --- /dev/null +++ b/tests/specs/install/installs_all_workspace_imports/__test__.jsonc @@ -0,0 +1,9 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "install", + "output": "install.out" + } + ] +} diff --git a/tests/specs/install/installs_all_workspace_imports/deno.json b/tests/specs/install/installs_all_workspace_imports/deno.json new file mode 100644 index 0000000000..ac77e26d9b --- /dev/null +++ b/tests/specs/install/installs_all_workspace_imports/deno.json @@ -0,0 +1,6 @@ +{ + "workspace": ["packages/foo", "packages/bar"], + "imports": { + "@denotest/subtract": "jsr:@denotest/subtract@^1.0.0" + } +} diff --git a/tests/specs/install/installs_all_workspace_imports/install.out b/tests/specs/install/installs_all_workspace_imports/install.out new file mode 100644 index 0000000000..b02e6cc033 --- /dev/null +++ b/tests/specs/install/installs_all_workspace_imports/install.out @@ -0,0 +1,10 @@ +[UNORDERED_START] +Download http://localhost:4260/@denotest%2fesm-basic +Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz +Download http://127.0.0.1:4250/@denotest/subtract/meta.json +Download http://127.0.0.1:4250/@denotest/add/meta.json +Download http://127.0.0.1:4250/@denotest/add/1.0.0_meta.json +Download http://127.0.0.1:4250/@denotest/subtract/1.0.0_meta.json +Download http://127.0.0.1:4250/@denotest/add/1.0.0/mod.ts +Download http://127.0.0.1:4250/@denotest/subtract/1.0.0/mod.ts +[UNORDERED_END] diff --git a/tests/specs/install/installs_all_workspace_imports/packages/bar/deno.json b/tests/specs/install/installs_all_workspace_imports/packages/bar/deno.json new file mode 100644 index 0000000000..0172071c39 --- /dev/null +++ b/tests/specs/install/installs_all_workspace_imports/packages/bar/deno.json @@ -0,0 +1,5 @@ +{ + "imports": { + "@denotest/esm-basic": "npm:@denotest/esm-basic@^1.0.0" + } +} diff --git a/tests/specs/install/installs_all_workspace_imports/packages/foo/deno.json b/tests/specs/install/installs_all_workspace_imports/packages/foo/deno.json new file mode 100644 index 0000000000..38ca2d4b85 --- /dev/null +++ b/tests/specs/install/installs_all_workspace_imports/packages/foo/deno.json @@ -0,0 +1,5 @@ +{ + "imports": { + "@denotest/add": "jsr:@denotest/add@^1.0.0" + } +} diff --git a/tests/specs/upgrade/out/upgrade.out b/tests/specs/upgrade/out/upgrade.out index a2b47d0ec8..5c5267c957 100644 --- a/tests/specs/upgrade/out/upgrade.out +++ b/tests/specs/upgrade/out/upgrade.out @@ -1,5 +1,4 @@ Current Deno version: [WILDCARD] -Downloading https://github.com/denoland/deno/releases/download/v1.43.2/deno-[WILDCARD].zip Deno is upgrading to version 1.43.2 Upgraded successfully to Deno v1.43.2 (stable) diff --git a/tests/specs/upgrade/space_in_tmp/upgrade.out b/tests/specs/upgrade/space_in_tmp/upgrade.out index a2b47d0ec8..5c5267c957 100644 --- a/tests/specs/upgrade/space_in_tmp/upgrade.out +++ b/tests/specs/upgrade/space_in_tmp/upgrade.out @@ -1,5 +1,4 @@ Current Deno version: [WILDCARD] -Downloading https://github.com/denoland/deno/releases/download/v1.43.2/deno-[WILDCARD].zip Deno is upgrading to version 1.43.2 Upgraded successfully to Deno v1.43.2 (stable) diff --git a/tests/specs/upgrade/specific_stable/upgrade.out b/tests/specs/upgrade/specific_stable/upgrade.out index a2b47d0ec8..5c5267c957 100644 --- a/tests/specs/upgrade/specific_stable/upgrade.out +++ b/tests/specs/upgrade/specific_stable/upgrade.out @@ -1,5 +1,4 @@ Current Deno version: [WILDCARD] -Downloading https://github.com/denoland/deno/releases/download/v1.43.2/deno-[WILDCARD].zip Deno is upgrading to version 1.43.2 Upgraded successfully to Deno v1.43.2 (stable)