From 093f3ba56518aba6e7844c17f9ba1fd09dafc6d1 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Thu, 9 Jan 2025 12:10:07 -0500 Subject: [PATCH 1/7] refactor(npm): extract out some npm fs resolution code from the cli (#27607) Moves the npm fs resolvers into the deno_resolution crate. This does not entirely move things out, but is a step in that direction. --- Cargo.lock | 6 +- cli/http_util.rs | 5 +- cli/npm/managed/installer.rs | 2 +- cli/npm/managed/installers/global.rs | 2 +- cli/npm/managed/installers/local.rs | 4 +- cli/npm/managed/installers/mod.rs | 2 +- cli/npm/managed/mod.rs | 34 +++-- cli/npm/managed/resolvers/mod.rs | 33 ----- cli/npm/mod.rs | 3 +- resolvers/deno/Cargo.toml | 10 +- resolvers/deno/lib.rs | 8 ++ resolvers/deno/npm/local.rs | 85 ++++++++++++ .../deno/npm/managed}/common.rs | 10 +- .../deno/npm/managed}/global.rs | 75 +++++++--- .../deno/npm/managed}/local.rs | 130 +++++------------- resolvers/deno/npm/managed/mod.rs | 45 ++++++ .../deno}/npm/managed/resolution.rs | 15 +- resolvers/deno/npm/mod.rs | 15 +- resolvers/deno/sync.rs | 6 + resolvers/npm_cache/Cargo.toml | 5 - resolvers/npm_cache/lib.rs | 11 +- resolvers/npm_cache/registry_info.rs | 9 +- resolvers/npm_cache/tarball.rs | 8 +- resolvers/npm_cache/todo.md | 2 - 24 files changed, 312 insertions(+), 213 deletions(-) delete mode 100644 cli/npm/managed/resolvers/mod.rs rename {cli/npm/managed/resolvers => resolvers/deno/npm/managed}/common.rs (87%) rename {cli/npm/managed/resolvers => resolvers/deno/npm/managed}/global.rs (62%) rename {cli/npm/managed/resolvers => resolvers/deno/npm/managed}/local.rs (61%) create mode 100644 resolvers/deno/npm/managed/mod.rs rename {cli => resolvers/deno}/npm/managed/resolution.rs (91%) diff --git a/Cargo.lock b/Cargo.lock index d55c1a19aa..e94fd48410 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2096,12 +2096,10 @@ dependencies = [ name = "deno_npm_cache" version = "0.3.0" dependencies = [ - "anyhow", "async-trait", "base64 0.21.7", "boxed_error", "deno_cache_dir", - "deno_core", "deno_error", "deno_npm", "deno_path_util", @@ -2197,16 +2195,20 @@ name = "deno_resolver" version = "0.15.0" dependencies = [ "anyhow", + "async-trait", "base32", "boxed_error", "dashmap", + "deno_cache_dir", "deno_config", "deno_error", "deno_media_type", + "deno_npm", "deno_package_json", "deno_path_util", "deno_semver", "node_resolver", + "parking_lot", "sys_traits", "test_server", "thiserror 2.0.3", diff --git a/cli/http_util.rs b/cli/http_util.rs index 19d9071833..5e63ab0a4a 100644 --- a/cli/http_util.rs +++ b/cli/http_util.rs @@ -70,7 +70,7 @@ impl HttpClientProvider { } } - pub fn get_or_create(&self) -> Result { + pub fn get_or_create(&self) -> Result { use std::collections::hash_map::Entry; let thread_id = std::thread::current().id(); let mut clients = self.clients_by_thread_id.lock(); @@ -87,7 +87,8 @@ impl HttpClientProvider { }, ..self.options.clone() }, - )?; + ) + .map_err(JsErrorBox::from_err)?; entry.insert(client.clone()); Ok(HttpClient::new(client)) } diff --git a/cli/npm/managed/installer.rs b/cli/npm/managed/installer.rs index 30ac807023..9f1cc05968 100644 --- a/cli/npm/managed/installer.rs +++ b/cli/npm/managed/installer.rs @@ -13,13 +13,13 @@ use deno_npm::resolution::AddPkgReqsOptions; use deno_npm::resolution::NpmResolutionError; use deno_npm::resolution::NpmResolutionSnapshot; use deno_npm::NpmResolutionPackage; +use deno_resolver::npm::managed::NpmResolution; use deno_semver::jsr::JsrDepPackageReq; use deno_semver::package::PackageNv; use deno_semver::package::PackageReq; use deno_semver::SmallStackString; use deno_semver::VersionReq; -use super::resolution::NpmResolution; use crate::args::CliLockfile; use crate::npm::CliNpmRegistryInfoProvider; use crate::util::sync::TaskQueue; diff --git a/cli/npm/managed/installers/global.rs b/cli/npm/managed/installers/global.rs index d637c96122..477d73dbfb 100644 --- a/cli/npm/managed/installers/global.rs +++ b/cli/npm/managed/installers/global.rs @@ -11,8 +11,8 @@ use deno_core::futures::StreamExt; use deno_error::JsErrorBox; use deno_npm::NpmResolutionPackage; use deno_npm::NpmSystemInfo; +use deno_resolver::npm::managed::NpmResolution; -use super::super::resolution::NpmResolution; use super::common::lifecycle_scripts::LifecycleScriptsStrategy; use super::common::NpmPackageFsInstaller; use crate::args::LifecycleScriptsConfig; diff --git a/cli/npm/managed/installers/local.rs b/cli/npm/managed/installers/local.rs index e2c5653801..a8efaaeb00 100644 --- a/cli/npm/managed/installers/local.rs +++ b/cli/npm/managed/installers/local.rs @@ -24,19 +24,19 @@ use deno_npm::resolution::NpmResolutionSnapshot; use deno_npm::NpmResolutionPackage; use deno_npm::NpmSystemInfo; use deno_path_util::fs::atomic_write_file_with_retries; +use deno_resolver::npm::get_package_folder_id_folder_name; +use deno_resolver::npm::managed::NpmResolution; use deno_semver::package::PackageNv; use deno_semver::StackString; use serde::Deserialize; use serde::Serialize; -use super::super::resolution::NpmResolution; use super::common::bin_entries; use super::common::NpmPackageFsInstaller; use crate::args::LifecycleScriptsConfig; use crate::args::NpmInstallDepsProvider; use crate::cache::CACHE_PERM; use crate::colors; -use crate::npm::managed::resolvers::get_package_folder_id_folder_name; use crate::npm::managed::PackageCaching; use crate::npm::CliNpmCache; use crate::npm::CliNpmTarballCache; diff --git a/cli/npm/managed/installers/mod.rs b/cli/npm/managed/installers/mod.rs index 4514fa1ec3..39e0d6f77c 100644 --- a/cli/npm/managed/installers/mod.rs +++ b/cli/npm/managed/installers/mod.rs @@ -4,11 +4,11 @@ use std::path::PathBuf; use std::sync::Arc; use deno_npm::NpmSystemInfo; +use deno_resolver::npm::managed::NpmResolution; pub use self::common::NpmPackageFsInstaller; use self::global::GlobalNpmPackageInstaller; use self::local::LocalNpmPackageInstaller; -use super::resolution::NpmResolution; use crate::args::LifecycleScriptsConfig; use crate::args::NpmInstallDepsProvider; use crate::npm::CliNpmCache; diff --git a/cli/npm/managed/mod.rs b/cli/npm/managed/mod.rs index 6729a56b1e..5950af948c 100644 --- a/cli/npm/managed/mod.rs +++ b/cli/npm/managed/mod.rs @@ -23,6 +23,10 @@ use deno_npm::NpmResolutionPackage; use deno_npm::NpmSystemInfo; use deno_npm_cache::NpmCacheSetting; use deno_path_util::fs::canonicalize_path_maybe_not_exists; +use deno_resolver::npm::managed::create_npm_fs_resolver; +use deno_resolver::npm::managed::NpmPackageFsResolver; +use deno_resolver::npm::managed::NpmPackageFsResolverPackageFolderError; +use deno_resolver::npm::managed::NpmResolution; use deno_resolver::npm::CliNpmReqResolver; use deno_runtime::colors; use deno_runtime::ops::process::NpmProcessStateProvider; @@ -37,9 +41,6 @@ use node_resolver::errors::PackageFolderResolveIoError; use node_resolver::InNpmPackageChecker; use node_resolver::NpmPackageFolderResolver; -use self::resolution::NpmResolution; -use self::resolvers::create_npm_fs_resolver; -use self::resolvers::NpmPackageFsResolver; use super::CliNpmCache; use super::CliNpmCacheHttpClient; use super::CliNpmRegistryInfoProvider; @@ -60,8 +61,6 @@ use crate::util::sync::AtomicFlag; mod installer; mod installers; -mod resolution; -mod resolvers; pub enum CliNpmResolverManagedSnapshotOption { ResolveFromLockfile(Arc), @@ -104,6 +103,7 @@ pub async fn create_managed_npm_resolver_for_lsp( create_inner( http_client, npm_cache, + options.npm_cache_dir, options.npm_install_deps_provider, npm_api, options.sys, @@ -133,6 +133,7 @@ pub async fn create_managed_npm_resolver( Ok(create_inner( http_client, npm_cache, + options.npm_cache_dir, options.npm_install_deps_provider, api, options.sys, @@ -150,6 +151,7 @@ pub async fn create_managed_npm_resolver( fn create_inner( http_client: Arc, npm_cache: Arc, + npm_cache_dir: Arc, npm_install_deps_provider: Arc, registry_info_provider: Arc, sys: CliSys, @@ -181,7 +183,8 @@ fn create_inner( lifecycle_scripts.clone(), ); let fs_resolver = create_npm_fs_resolver( - npm_cache.clone(), + &npm_cache_dir, + &npm_rc, resolution.clone(), sys.clone(), node_modules_dir_path, @@ -192,7 +195,9 @@ fn create_inner( maybe_lockfile, registry_info_provider, npm_cache, + npm_cache_dir, npm_install_deps_provider, + npm_rc, resolution, sys, tarball_cache, @@ -314,7 +319,9 @@ pub struct ManagedCliNpmResolver { maybe_lockfile: Option>, registry_info_provider: Arc, npm_cache: Arc, + npm_cache_dir: Arc, npm_install_deps_provider: Arc, + npm_rc: Arc, sys: CliSys, resolution: Arc, resolution_installer: NpmResolutionInstaller, @@ -338,7 +345,7 @@ pub enum ResolvePkgFolderFromPkgIdError { #[class(inherit)] #[error("{0}")] NpmPackageFsResolverPackageFolder( - #[from] resolvers::NpmPackageFsResolverPackageFolderError, + #[from] NpmPackageFsResolverPackageFolderError, ), #[class(inherit)] #[error("{0}")] @@ -363,7 +370,9 @@ impl ManagedCliNpmResolver { maybe_lockfile: Option>, registry_info_provider: Arc, npm_cache: Arc, + npm_cache_dir: Arc, npm_install_deps_provider: Arc, + npm_rc: Arc, resolution: Arc, sys: CliSys, tarball_cache: Arc, @@ -382,7 +391,9 @@ impl ManagedCliNpmResolver { maybe_lockfile, registry_info_provider, npm_cache, + npm_cache_dir, npm_install_deps_provider, + npm_rc, text_only_progress_bar, resolution, resolution_installer, @@ -671,11 +682,11 @@ impl ManagedCliNpmResolver { } pub fn global_cache_root_path(&self) -> &Path { - self.npm_cache.root_dir_path() + self.npm_cache_dir.root_dir() } pub fn global_cache_root_url(&self) -> &Url { - self.npm_cache.root_dir_url() + self.npm_cache_dir.root_dir_url() } } @@ -772,7 +783,8 @@ impl CliNpmResolver for ManagedCliNpmResolver { self.lifecycle_scripts.clone(), ), create_npm_fs_resolver( - self.npm_cache.clone(), + &self.npm_cache_dir, + &self.npm_rc, npm_resolution.clone(), self.sys.clone(), self.root_node_modules_path().map(ToOwned::to_owned), @@ -780,7 +792,9 @@ impl CliNpmResolver for ManagedCliNpmResolver { self.maybe_lockfile.clone(), self.registry_info_provider.clone(), self.npm_cache.clone(), + self.npm_cache_dir.clone(), self.npm_install_deps_provider.clone(), + self.npm_rc.clone(), npm_resolution, self.sys.clone(), self.tarball_cache.clone(), diff --git a/cli/npm/managed/resolvers/mod.rs b/cli/npm/managed/resolvers/mod.rs deleted file mode 100644 index 8a89208c77..0000000000 --- a/cli/npm/managed/resolvers/mod.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2018-2025 the Deno authors. MIT license. - -mod common; -mod global; -mod local; - -use std::path::PathBuf; -use std::sync::Arc; - -pub use self::common::NpmPackageFsResolver; -pub use self::common::NpmPackageFsResolverPackageFolderError; -use self::global::GlobalNpmPackageResolver; -pub use self::local::get_package_folder_id_folder_name; -use self::local::LocalNpmPackageResolver; -use super::resolution::NpmResolution; -use crate::npm::CliNpmCache; -use crate::sys::CliSys; - -pub fn create_npm_fs_resolver( - npm_cache: Arc, - resolution: Arc, - sys: CliSys, - maybe_node_modules_path: Option, -) -> Arc { - match maybe_node_modules_path { - Some(node_modules_folder) => Arc::new(LocalNpmPackageResolver::new( - resolution, - sys, - node_modules_folder, - )), - None => Arc::new(GlobalNpmPackageResolver::new(npm_cache, resolution)), - } -} diff --git a/cli/npm/mod.rs b/cli/npm/mod.rs index d66b3e618f..56032e1a0b 100644 --- a/cli/npm/mod.rs +++ b/cli/npm/mod.rs @@ -11,6 +11,7 @@ use dashmap::DashMap; use deno_core::error::AnyError; use deno_core::serde_json; use deno_core::url::Url; +use deno_error::JsErrorBox; use deno_npm::npm_rc::ResolvedNpmRc; use deno_npm::registry::NpmPackageInfo; use deno_resolver::npm::ByonmInNpmPackageChecker; @@ -100,7 +101,7 @@ impl deno_npm_cache::NpmCacheHttpClient for CliNpmCacheHttpClient { }; deno_npm_cache::DownloadError { status_code, - error: err.into(), + error: JsErrorBox::from_err(err), } }) } diff --git a/resolvers/deno/Cargo.toml b/resolvers/deno/Cargo.toml index 0eeec14e77..059fdbc08e 100644 --- a/resolvers/deno/Cargo.toml +++ b/resolvers/deno/Cargo.toml @@ -18,18 +18,20 @@ sync = ["dashmap"] [dependencies] anyhow.workspace = true +async-trait.workspace = true base32.workspace = true boxed_error.workspace = true dashmap = { workspace = true, optional = true } +deno_cache_dir.workspace = true deno_config.workspace = true deno_error.workspace = true deno_media_type.workspace = true -deno_package_json.workspace = true -deno_package_json.features = ["sync"] +deno_npm.workspace = true +deno_package_json = { workspace = true, features = ["sync"] } deno_path_util.workspace = true deno_semver.workspace = true -node_resolver.workspace = true -node_resolver.features = ["sync"] +node_resolver = { workspace = true, features = ["sync"] } +parking_lot.workspace = true sys_traits.workspace = true thiserror.workspace = true url.workspace = true diff --git a/resolvers/deno/lib.rs b/resolvers/deno/lib.rs index 49b2cf4d1b..12d8effc46 100644 --- a/resolvers/deno/lib.rs +++ b/resolvers/deno/lib.rs @@ -6,12 +6,14 @@ use std::path::PathBuf; use boxed_error::Boxed; +use deno_cache_dir::npm::NpmCacheDir; use deno_config::workspace::MappedResolution; use deno_config::workspace::MappedResolutionDiagnostic; use deno_config::workspace::MappedResolutionError; use deno_config::workspace::WorkspaceResolvePkgJsonFolderError; use deno_config::workspace::WorkspaceResolver; use deno_error::JsError; +use deno_npm::npm_rc::ResolvedNpmRc; use deno_package_json::PackageJsonDepValue; use deno_package_json::PackageJsonDepValueParseError; use deno_semver::npm::NpmPackageReqReference; @@ -47,6 +49,12 @@ mod sync; #[allow(clippy::disallowed_types)] pub type WorkspaceResolverRc = crate::sync::MaybeArc; +#[allow(clippy::disallowed_types)] +pub(crate) type ResolvedNpmRcRc = crate::sync::MaybeArc; + +#[allow(clippy::disallowed_types)] +pub(crate) type NpmCacheDirRc = crate::sync::MaybeArc; + #[derive(Debug, Clone)] pub struct DenoResolution { pub url: Url, diff --git a/resolvers/deno/npm/local.rs b/resolvers/deno/npm/local.rs index 6322a4b3f7..b05864b856 100644 --- a/resolvers/deno/npm/local.rs +++ b/resolvers/deno/npm/local.rs @@ -2,6 +2,58 @@ use std::borrow::Cow; +use deno_cache_dir::npm::mixed_case_package_name_decode; +use deno_npm::NpmPackageCacheFolderId; +use deno_semver::package::PackageNv; +use deno_semver::StackString; + +#[inline] +pub fn get_package_folder_id_folder_name( + folder_id: &NpmPackageCacheFolderId, +) -> String { + get_package_folder_id_folder_name_from_parts( + &folder_id.nv, + folder_id.copy_index, + ) +} + +pub fn get_package_folder_id_folder_name_from_parts( + nv: &PackageNv, + copy_index: u8, +) -> String { + let copy_str = if copy_index == 0 { + Cow::Borrowed("") + } else { + Cow::Owned(format!("_{}", copy_index)) + }; + let name = normalize_pkg_name_for_node_modules_deno_folder(&nv.name); + format!("{}@{}{}", name, nv.version, copy_str) +} + +pub fn get_package_folder_id_from_folder_name( + folder_name: &str, +) -> Option { + let folder_name = folder_name.replace('+', "/"); + let (name, ending) = folder_name.rsplit_once('@')?; + let name: StackString = if let Some(encoded_name) = name.strip_prefix('_') { + StackString::from_string(mixed_case_package_name_decode(encoded_name)?) + } else { + name.into() + }; + let (raw_version, copy_index) = match ending.split_once('_') { + Some((raw_version, copy_index)) => { + let copy_index = copy_index.parse::().ok()?; + (raw_version, copy_index) + } + None => (ending, 0), + }; + let version = deno_semver::Version::parse_from_npm(raw_version).ok()?; + Some(NpmPackageCacheFolderId { + nv: PackageNv { name, version }, + copy_index, + }) +} + /// Normalizes a package name for use at `node_modules/.deno/@[_]` pub fn normalize_pkg_name_for_node_modules_deno_folder(name: &str) -> Cow { let name = if name.to_lowercase() == name { @@ -25,3 +77,36 @@ fn mixed_case_package_name_encode(name: &str) -> String { ) .to_lowercase() } + +#[cfg(test)] +mod test { + use deno_npm::NpmPackageCacheFolderId; + use deno_semver::package::PackageNv; + + use super::*; + + #[test] + fn test_get_package_folder_id_folder_name() { + let cases = vec![ + ( + NpmPackageCacheFolderId { + nv: PackageNv::from_str("@types/foo@1.2.3").unwrap(), + copy_index: 1, + }, + "@types+foo@1.2.3_1".to_string(), + ), + ( + NpmPackageCacheFolderId { + nv: PackageNv::from_str("JSON@3.2.1").unwrap(), + copy_index: 0, + }, + "_jjju6tq@3.2.1".to_string(), + ), + ]; + for (input, output) in cases { + assert_eq!(get_package_folder_id_folder_name(&input), output); + let folder_id = get_package_folder_id_from_folder_name(&output).unwrap(); + assert_eq!(folder_id, input); + } + } +} diff --git a/cli/npm/managed/resolvers/common.rs b/resolvers/deno/npm/managed/common.rs similarity index 87% rename from cli/npm/managed/resolvers/common.rs rename to resolvers/deno/npm/managed/common.rs index be0b40fa2a..23ed63e2f0 100644 --- a/cli/npm/managed/resolvers/common.rs +++ b/resolvers/deno/npm/managed/common.rs @@ -4,10 +4,14 @@ use std::path::Path; use std::path::PathBuf; use async_trait::async_trait; -use deno_ast::ModuleSpecifier; use deno_npm::NpmPackageCacheFolderId; use deno_npm::NpmPackageId; use node_resolver::errors::PackageFolderResolveError; +use url::Url; + +#[allow(clippy::disallowed_types)] +pub(super) type NpmPackageFsResolverRc = + crate::sync::MaybeArc; #[derive(Debug, thiserror::Error, deno_error::JsError)] #[class(generic)] @@ -34,11 +38,11 @@ pub trait NpmPackageFsResolver: Send + Sync { fn resolve_package_folder_from_package( &self, name: &str, - referrer: &ModuleSpecifier, + referrer: &Url, ) -> Result; fn resolve_package_cache_folder_id_from_specifier( &self, - specifier: &ModuleSpecifier, + specifier: &Url, ) -> Result, std::io::Error>; } diff --git a/cli/npm/managed/resolvers/global.rs b/resolvers/deno/npm/managed/global.rs similarity index 62% rename from cli/npm/managed/resolvers/global.rs rename to resolvers/deno/npm/managed/global.rs index d63d3a7e45..16a2bc7a70 100644 --- a/cli/npm/managed/resolvers/global.rs +++ b/resolvers/deno/npm/managed/global.rs @@ -4,30 +4,60 @@ use std::path::Path; use std::path::PathBuf; -use std::sync::Arc; use async_trait::async_trait; -use deno_ast::ModuleSpecifier; use deno_npm::NpmPackageCacheFolderId; use deno_npm::NpmPackageId; +use deno_semver::package::PackageNv; +use deno_semver::StackString; +use deno_semver::Version; use node_resolver::errors::PackageFolderResolveError; use node_resolver::errors::PackageNotFoundError; use node_resolver::errors::ReferrerNotFoundError; +use url::Url; -use super::super::resolution::NpmResolution; -use super::common::NpmPackageFsResolver; -use crate::npm::CliNpmCache; +use super::resolution::NpmResolutionRc; +use super::NpmCacheDirRc; +use super::NpmPackageFsResolver; +use crate::ResolvedNpmRcRc; /// Resolves packages from the global npm cache. #[derive(Debug)] pub struct GlobalNpmPackageResolver { - cache: Arc, - resolution: Arc, + cache: NpmCacheDirRc, + npm_rc: ResolvedNpmRcRc, + resolution: NpmResolutionRc, } impl GlobalNpmPackageResolver { - pub fn new(cache: Arc, resolution: Arc) -> Self { - Self { cache, resolution } + pub fn new( + cache: NpmCacheDirRc, + npm_rc: ResolvedNpmRcRc, + resolution: NpmResolutionRc, + ) -> Self { + Self { + cache, + npm_rc, + resolution, + } + } + + fn resolve_package_cache_folder_id_from_specifier_inner( + &self, + specifier: &Url, + ) -> Option { + self + .cache + .resolve_package_folder_id_from_specifier(specifier) + .and_then(|cache_id| { + Some(NpmPackageCacheFolderId { + nv: PackageNv { + name: StackString::from_string(cache_id.name), + version: Version::parse_from_npm(&cache_id.version).ok()?, + }, + copy_index: cache_id.copy_index, + }) + }) } } @@ -38,21 +68,26 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver { } fn maybe_package_folder(&self, id: &NpmPackageId) -> Option { - let folder_id = self + let folder_copy_index = self .resolution - .resolve_pkg_cache_folder_id_from_pkg_id(id)?; - Some(self.cache.package_folder_for_id(&folder_id)) + .resolve_pkg_cache_folder_copy_index_from_pkg_id(id)?; + let registry_url = self.npm_rc.get_registry_url(&id.nv.name); + Some(self.cache.package_folder_for_id( + &id.nv.name, + &id.nv.version.to_string(), + folder_copy_index, + registry_url, + )) } fn resolve_package_folder_from_package( &self, name: &str, - referrer: &ModuleSpecifier, + referrer: &Url, ) -> Result { use deno_npm::resolution::PackageNotFoundFromReferrerError; - let Some(referrer_cache_folder_id) = self - .cache - .resolve_package_folder_id_from_specifier(referrer) + let Some(referrer_cache_folder_id) = + self.resolve_package_cache_folder_id_from_specifier_inner(referrer) else { return Err( ReferrerNotFoundError { @@ -106,12 +141,8 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver { fn resolve_package_cache_folder_id_from_specifier( &self, - specifier: &ModuleSpecifier, + specifier: &Url, ) -> Result, std::io::Error> { - Ok( - self - .cache - .resolve_package_folder_id_from_specifier(specifier), - ) + Ok(self.resolve_package_cache_folder_id_from_specifier_inner(specifier)) } } diff --git a/cli/npm/managed/resolvers/local.rs b/resolvers/deno/npm/managed/local.rs similarity index 61% rename from cli/npm/managed/resolvers/local.rs rename to resolvers/deno/npm/managed/local.rs index 52d5ac5a9e..e84de964ad 100644 --- a/cli/npm/managed/resolvers/local.rs +++ b/resolvers/deno/npm/managed/local.rs @@ -5,49 +5,50 @@ use std::borrow::Cow; use std::path::Path; use std::path::PathBuf; -use std::sync::Arc; use async_trait::async_trait; -use deno_ast::ModuleSpecifier; -use deno_cache_dir::npm::mixed_case_package_name_decode; -use deno_core::url::Url; use deno_npm::NpmPackageCacheFolderId; use deno_npm::NpmPackageId; use deno_path_util::fs::canonicalize_path_maybe_not_exists; -use deno_resolver::npm::normalize_pkg_name_for_node_modules_deno_folder; -use deno_semver::package::PackageNv; -use deno_semver::StackString; +use deno_path_util::url_from_directory_path; use node_resolver::errors::PackageFolderResolveError; use node_resolver::errors::PackageFolderResolveIoError; use node_resolver::errors::PackageNotFoundError; use node_resolver::errors::ReferrerNotFoundError; +use sys_traits::FsCanonicalize; use sys_traits::FsMetadata; +use url::Url; -use super::super::resolution::NpmResolution; -use super::common::NpmPackageFsResolver; -use crate::sys::CliSys; +use super::resolution::NpmResolutionRc; +use super::NpmPackageFsResolver; +use crate::npm::local::get_package_folder_id_folder_name_from_parts; +use crate::npm::local::get_package_folder_id_from_folder_name; /// Resolver that creates a local node_modules directory /// and resolves packages from it. #[derive(Debug)] -pub struct LocalNpmPackageResolver { - resolution: Arc, - sys: CliSys, +pub struct LocalNpmPackageResolver< + TSys: FsCanonicalize + FsMetadata + Send + Sync, +> { + resolution: NpmResolutionRc, + sys: TSys, root_node_modules_path: PathBuf, root_node_modules_url: Url, } -impl LocalNpmPackageResolver { +impl + LocalNpmPackageResolver +{ #[allow(clippy::too_many_arguments)] pub fn new( - resolution: Arc, - sys: CliSys, + resolution: NpmResolutionRc, + sys: TSys, node_modules_folder: PathBuf, ) -> Self { Self { resolution, sys, - root_node_modules_url: Url::from_directory_path(&node_modules_folder) + root_node_modules_url: url_from_directory_path(&node_modules_folder) .unwrap(), root_node_modules_path: node_modules_folder, } @@ -67,7 +68,7 @@ impl LocalNpmPackageResolver { fn resolve_folder_for_specifier( &self, - specifier: &ModuleSpecifier, + specifier: &Url, ) -> Result, std::io::Error> { let Some(relative_url) = self.root_node_modules_url.make_relative(specifier) @@ -78,7 +79,7 @@ impl LocalNpmPackageResolver { return Ok(None); } // it's within the directory, so use it - let Some(path) = specifier.to_file_path().ok() else { + let Some(path) = deno_path_util::url_to_file_path(specifier).ok() else { return Ok(None); }; // Canonicalize the path so it's not pointing to the symlinked directory @@ -88,7 +89,7 @@ impl LocalNpmPackageResolver { fn resolve_package_folder_from_specifier( &self, - specifier: &ModuleSpecifier, + specifier: &Url, ) -> Result, std::io::Error> { let Some(local_path) = self.resolve_folder_for_specifier(specifier)? else { return Ok(None); @@ -99,31 +100,36 @@ impl LocalNpmPackageResolver { } #[async_trait(?Send)] -impl NpmPackageFsResolver for LocalNpmPackageResolver { +impl NpmPackageFsResolver + for LocalNpmPackageResolver +{ fn node_modules_path(&self) -> Option<&Path> { Some(self.root_node_modules_path.as_ref()) } fn maybe_package_folder(&self, id: &NpmPackageId) -> Option { - let cache_folder_id = self + let folder_copy_index = self .resolution - .resolve_pkg_cache_folder_id_from_pkg_id(id)?; + .resolve_pkg_cache_folder_copy_index_from_pkg_id(id)?; // package is stored at: // node_modules/.deno//node_modules/ Some( self .root_node_modules_path .join(".deno") - .join(get_package_folder_id_folder_name(&cache_folder_id)) + .join(get_package_folder_id_folder_name_from_parts( + &id.nv, + folder_copy_index, + )) .join("node_modules") - .join(&cache_folder_id.nv.name), + .join(&id.nv.name), ) } fn resolve_package_folder_from_package( &self, name: &str, - referrer: &ModuleSpecifier, + referrer: &Url, ) -> Result { let maybe_local_path = self .resolve_folder_for_specifier(referrer) @@ -173,7 +179,7 @@ impl NpmPackageFsResolver for LocalNpmPackageResolver { fn resolve_package_cache_folder_id_from_specifier( &self, - specifier: &ModuleSpecifier, + specifier: &Url, ) -> Result, std::io::Error> { let Some(folder_path) = self.resolve_package_folder_from_specifier(specifier)? @@ -198,43 +204,6 @@ impl NpmPackageFsResolver for LocalNpmPackageResolver { } } -pub fn get_package_folder_id_folder_name( - folder_id: &NpmPackageCacheFolderId, -) -> String { - let copy_str = if folder_id.copy_index == 0 { - Cow::Borrowed("") - } else { - Cow::Owned(format!("_{}", folder_id.copy_index)) - }; - let nv = &folder_id.nv; - let name = normalize_pkg_name_for_node_modules_deno_folder(&nv.name); - format!("{}@{}{}", name, nv.version, copy_str) -} - -fn get_package_folder_id_from_folder_name( - folder_name: &str, -) -> Option { - let folder_name = folder_name.replace('+', "/"); - let (name, ending) = folder_name.rsplit_once('@')?; - let name: StackString = if let Some(encoded_name) = name.strip_prefix('_') { - StackString::from_string(mixed_case_package_name_decode(encoded_name)?) - } else { - name.into() - }; - let (raw_version, copy_index) = match ending.split_once('_') { - Some((raw_version, copy_index)) => { - let copy_index = copy_index.parse::().ok()?; - (raw_version, copy_index) - } - None => (ending, 0), - }; - let version = deno_semver::Version::parse_from_npm(raw_version).ok()?; - Some(NpmPackageCacheFolderId { - nv: PackageNv { name, version }, - copy_index, - }) -} - fn join_package_name(path: &Path, package_name: &str) -> PathBuf { let mut path = path.to_path_buf(); // ensure backslashes are used on windows @@ -243,36 +212,3 @@ fn join_package_name(path: &Path, package_name: &str) -> PathBuf { } path } - -#[cfg(test)] -mod test { - use deno_npm::NpmPackageCacheFolderId; - use deno_semver::package::PackageNv; - - use super::*; - - #[test] - fn test_get_package_folder_id_folder_name() { - let cases = vec![ - ( - NpmPackageCacheFolderId { - nv: PackageNv::from_str("@types/foo@1.2.3").unwrap(), - copy_index: 1, - }, - "@types+foo@1.2.3_1".to_string(), - ), - ( - NpmPackageCacheFolderId { - nv: PackageNv::from_str("JSON@3.2.1").unwrap(), - copy_index: 0, - }, - "_jjju6tq@3.2.1".to_string(), - ), - ]; - for (input, output) in cases { - assert_eq!(get_package_folder_id_folder_name(&input), output); - let folder_id = get_package_folder_id_from_folder_name(&output).unwrap(); - assert_eq!(folder_id, input); - } - } -} diff --git a/resolvers/deno/npm/managed/mod.rs b/resolvers/deno/npm/managed/mod.rs new file mode 100644 index 0000000000..b460656eab --- /dev/null +++ b/resolvers/deno/npm/managed/mod.rs @@ -0,0 +1,45 @@ +// Copyright 2018-2025 the Deno authors. MIT license. + +mod common; +mod global; +mod local; +mod resolution; + +use std::path::PathBuf; + +use sys_traits::FsCanonicalize; +use sys_traits::FsMetadata; + +pub use self::common::NpmPackageFsResolver; +pub use self::common::NpmPackageFsResolverPackageFolderError; +use self::common::NpmPackageFsResolverRc; +use self::global::GlobalNpmPackageResolver; +use self::local::LocalNpmPackageResolver; +pub use self::resolution::NpmResolution; +use self::resolution::NpmResolutionRc; +use crate::sync::new_rc; +use crate::NpmCacheDirRc; +use crate::ResolvedNpmRcRc; + +pub fn create_npm_fs_resolver< + TSys: FsCanonicalize + FsMetadata + Send + Sync + 'static, +>( + npm_cache_dir: &NpmCacheDirRc, + npm_rc: &ResolvedNpmRcRc, + resolution: NpmResolutionRc, + sys: TSys, + maybe_node_modules_path: Option, +) -> NpmPackageFsResolverRc { + match maybe_node_modules_path { + Some(node_modules_folder) => new_rc(LocalNpmPackageResolver::new( + resolution, + sys, + node_modules_folder, + )), + None => new_rc(GlobalNpmPackageResolver::new( + npm_cache_dir.clone(), + npm_rc.clone(), + resolution, + )), + } +} diff --git a/cli/npm/managed/resolution.rs b/resolvers/deno/npm/managed/resolution.rs similarity index 91% rename from cli/npm/managed/resolution.rs rename to resolvers/deno/npm/managed/resolution.rs index 5178c20608..40ab91202c 100644 --- a/cli/npm/managed/resolution.rs +++ b/resolvers/deno/npm/managed/resolution.rs @@ -2,7 +2,6 @@ use std::collections::HashMap; -use deno_core::parking_lot::RwLock; use deno_npm::resolution::NpmPackagesPartitioned; use deno_npm::resolution::NpmResolutionSnapshot; use deno_npm::resolution::PackageCacheFolderIdNotFoundError; @@ -16,10 +15,12 @@ use deno_npm::NpmResolutionPackage; use deno_npm::NpmSystemInfo; use deno_semver::package::PackageNv; use deno_semver::package::PackageReq; +use parking_lot::RwLock; -/// Handles updating and storing npm resolution in memory where the underlying -/// snapshot can be updated concurrently. Additionally handles updating the lockfile -/// based on changes to the resolution. +#[allow(clippy::disallowed_types)] +pub(super) type NpmResolutionRc = crate::sync::MaybeArc; + +/// Handles updating and storing npm resolution in memory. /// /// This does not interact with the file system. pub struct NpmResolution { @@ -50,15 +51,15 @@ impl NpmResolution { } } - pub fn resolve_pkg_cache_folder_id_from_pkg_id( + pub fn resolve_pkg_cache_folder_copy_index_from_pkg_id( &self, id: &NpmPackageId, - ) -> Option { + ) -> Option { self .snapshot .read() .package_from_id(id) - .map(|p| p.get_package_cache_folder_id()) + .map(|p| p.copy_index) } pub fn resolve_pkg_id_from_pkg_cache_folder_id( diff --git a/resolvers/deno/npm/mod.rs b/resolvers/deno/npm/mod.rs index 2e7c4c888b..54282e677d 100644 --- a/resolvers/deno/npm/mod.rs +++ b/resolvers/deno/npm/mod.rs @@ -4,15 +4,9 @@ use std::fmt::Debug; use std::path::PathBuf; use boxed_error::Boxed; -pub use byonm::ByonmInNpmPackageChecker; -pub use byonm::ByonmNpmResolver; -pub use byonm::ByonmNpmResolverCreateOptions; -pub use byonm::ByonmNpmResolverRc; -pub use byonm::ByonmResolvePkgFolderFromDenoReqError; use deno_error::JsError; use deno_semver::npm::NpmPackageReqReference; use deno_semver::package::PackageReq; -pub use local::normalize_pkg_name_for_node_modules_deno_folder; use node_resolver::errors::NodeResolveError; use node_resolver::errors::NodeResolveErrorKind; use node_resolver::errors::PackageFolderResolveErrorKind; @@ -33,8 +27,17 @@ use sys_traits::FsReadDir; use thiserror::Error; use url::Url; +pub use self::byonm::ByonmInNpmPackageChecker; +pub use self::byonm::ByonmNpmResolver; +pub use self::byonm::ByonmNpmResolverCreateOptions; +pub use self::byonm::ByonmNpmResolverRc; +pub use self::byonm::ByonmResolvePkgFolderFromDenoReqError; +pub use self::local::get_package_folder_id_folder_name; +pub use self::local::normalize_pkg_name_for_node_modules_deno_folder; + mod byonm; mod local; +pub mod managed; #[derive(Debug, Error, JsError)] #[class(generic)] diff --git a/resolvers/deno/sync.rs b/resolvers/deno/sync.rs index 43635e62b7..10cdc5ec4d 100644 --- a/resolvers/deno/sync.rs +++ b/resolvers/deno/sync.rs @@ -46,3 +46,9 @@ mod inner { } } } + +#[allow(clippy::disallowed_types)] +#[inline] +pub fn new_rc(value: T) -> MaybeArc { + MaybeArc::new(value) +} diff --git a/resolvers/npm_cache/Cargo.toml b/resolvers/npm_cache/Cargo.toml index 328355d340..3cefc6538a 100644 --- a/resolvers/npm_cache/Cargo.toml +++ b/resolvers/npm_cache/Cargo.toml @@ -14,11 +14,6 @@ description = "Helpers for downloading and caching npm dependencies for Deno" path = "lib.rs" [dependencies] -# todo(dsherret): remove this dependency -anyhow.workspace = true -# todo(dsherret): remove this dependency -deno_core.workspace = true - async-trait.workspace = true base64.workspace = true boxed_error.workspace = true diff --git a/resolvers/npm_cache/lib.rs b/resolvers/npm_cache/lib.rs index 90c07de5d5..f0de201b75 100644 --- a/resolvers/npm_cache/lib.rs +++ b/resolvers/npm_cache/lib.rs @@ -6,7 +6,6 @@ use std::path::Path; use std::path::PathBuf; use std::sync::Arc; -use anyhow::Error as AnyError; use deno_cache_dir::file_fetcher::CacheSetting; use deno_cache_dir::npm::NpmCacheDir; use deno_error::JsErrorBox; @@ -51,7 +50,7 @@ pub use tarball::TarballCache; #[class(generic)] pub struct DownloadError { pub status_code: Option, - pub error: AnyError, + pub error: JsErrorBox, } impl std::error::Error for DownloadError { @@ -312,15 +311,17 @@ impl< &self, name: &str, package_info: &NpmPackageInfo, - ) -> Result<(), AnyError> { + ) -> Result<(), JsErrorBox> { let file_cache_path = self.get_registry_package_info_file_cache_path(name); - let file_text = serde_json::to_string(&package_info)?; + let file_text = + serde_json::to_string(&package_info).map_err(JsErrorBox::from_err)?; atomic_write_file_with_retries( &self.sys, &file_cache_path, file_text.as_bytes(), 0o644, - )?; + ) + .map_err(JsErrorBox::from_err)?; Ok(()) } diff --git a/resolvers/npm_cache/registry_info.rs b/resolvers/npm_cache/registry_info.rs index ece797abba..673f2ff445 100644 --- a/resolvers/npm_cache/registry_info.rs +++ b/resolvers/npm_cache/registry_info.rs @@ -5,11 +5,6 @@ use std::collections::HashSet; use std::sync::Arc; use async_trait::async_trait; -use deno_core::futures::future::LocalBoxFuture; -use deno_core::futures::FutureExt; -use deno_core::parking_lot::Mutex; -use deno_core::serde_json; -use deno_core::url::Url; use deno_error::JsErrorBox; use deno_npm::npm_rc::ResolvedNpmRc; use deno_npm::registry::NpmPackageInfo; @@ -17,6 +12,9 @@ use deno_npm::registry::NpmRegistryApi; use deno_npm::registry::NpmRegistryPackageInfoLoadError; use deno_unsync::sync::AtomicFlag; use deno_unsync::sync::MultiRuntimeAsyncValueCreator; +use futures::future::LocalBoxFuture; +use futures::FutureExt; +use parking_lot::Mutex; use sys_traits::FsCreateDirAll; use sys_traits::FsHardLink; use sys_traits::FsMetadata; @@ -26,6 +24,7 @@ use sys_traits::FsRemoveFile; use sys_traits::FsRename; use sys_traits::SystemRandom; use sys_traits::ThreadSleep; +use url::Url; use crate::remote::maybe_auth_header_for_npm_registry; use crate::NpmCache; diff --git a/resolvers/npm_cache/tarball.rs b/resolvers/npm_cache/tarball.rs index d9575ba9cd..7a9453e655 100644 --- a/resolvers/npm_cache/tarball.rs +++ b/resolvers/npm_cache/tarball.rs @@ -3,16 +3,15 @@ use std::collections::HashMap; use std::sync::Arc; -use deno_core::futures::future::LocalBoxFuture; -use deno_core::futures::FutureExt; -use deno_core::parking_lot::Mutex; -use deno_core::url::Url; use deno_error::JsErrorBox; use deno_npm::npm_rc::ResolvedNpmRc; use deno_npm::registry::NpmPackageVersionDistInfo; use deno_semver::package::PackageNv; use deno_unsync::sync::MultiRuntimeAsyncValueCreator; +use futures::future::LocalBoxFuture; +use futures::FutureExt; use http::StatusCode; +use parking_lot::Mutex; use sys_traits::FsCreateDirAll; use sys_traits::FsHardLink; use sys_traits::FsMetadata; @@ -22,6 +21,7 @@ use sys_traits::FsRemoveFile; use sys_traits::FsRename; use sys_traits::SystemRandom; use sys_traits::ThreadSleep; +use url::Url; use crate::remote::maybe_auth_header_for_npm_registry; use crate::tarball_extract::verify_and_extract_tarball; diff --git a/resolvers/npm_cache/todo.md b/resolvers/npm_cache/todo.md index e10b1cfd89..e460fcae86 100644 --- a/resolvers/npm_cache/todo.md +++ b/resolvers/npm_cache/todo.md @@ -1,7 +1,5 @@ This crate is a work in progress: -1. Remove `deno_core` dependency. -1. Remove `anyhow` dependency. 1. Add a clippy.toml file that bans accessing the file system directory and instead does it through a trait. 1. Make this crate work in Wasm. From 318f524c5c72feaffe4a76e2e8cbc8fca27fb75f Mon Sep 17 00:00:00 2001 From: Nayeem Rahman Date: Thu, 9 Jan 2025 17:54:14 +0000 Subject: [PATCH 2/7] fix(lsp): use verbatim specifier for URL auto-imports (#27605) --- cli/lsp/tsc.rs | 5 ++ tests/integration/lsp_tests.rs | 68 +++++++++++++++++++ .../imports_declaration/imports_interface.ts | 3 + .../subdir/imports_declaration/interface.d.ts | 3 + 4 files changed, 79 insertions(+) create mode 100644 tests/testdata/subdir/imports_declaration/imports_interface.ts create mode 100644 tests/testdata/subdir/imports_declaration/interface.d.ts diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs index 826021a288..cd1a724f5e 100644 --- a/cli/lsp/tsc.rs +++ b/cli/lsp/tsc.rs @@ -3972,6 +3972,11 @@ impl CompletionEntry { if let Some(mut new_specifier) = import_mapper .check_specifier(&import_data.normalized, specifier) .or_else(|| relative_specifier(specifier, &import_data.normalized)) + .or_else(|| { + ModuleSpecifier::parse(&import_data.raw.module_specifier) + .is_ok() + .then(|| import_data.normalized.to_string()) + }) { if new_specifier.contains("/node_modules/") { return None; diff --git a/tests/integration/lsp_tests.rs b/tests/integration/lsp_tests.rs index 9efb34f337..247851da9c 100644 --- a/tests/integration/lsp_tests.rs +++ b/tests/integration/lsp_tests.rs @@ -9937,6 +9937,74 @@ fn lsp_auto_imports_npm_auto() { client.shutdown(); } +// Regression test for https://github.com/denoland/deno/issues/23869. +#[test] +fn lsp_auto_imports_remote_dts() { + let context = TestContextBuilder::new() + .use_http_server() + .use_temp_cwd() + .build(); + let temp_dir = context.temp_dir(); + let mut client = context.new_lsp_command().build(); + client.initialize_default(); + client.did_open(json!({ + "textDocument": { + "uri": temp_dir.url().join("file.ts").unwrap(), + "languageId": "typescript", + "version": 1, + "text": r#" + import "http://localhost:4545/subdir/imports_declaration/imports_interface.ts"; + const a: SomeInterface + "#, + }, + })); + client.write_request( + "workspace/executeCommand", + json!({ + "command": "deno.cache", + "arguments": [[], temp_dir.url().join("file.ts").unwrap()], + }), + ); + let list = client.get_completion_list( + temp_dir.url().join("file.ts").unwrap(), + (2, 21), + json!({ "triggerKind": 2 }), + ); + assert!(!list.is_incomplete); + let item = list + .items + .iter() + .find(|item| item.label == "SomeInterface") + .unwrap(); + let res = client.write_request("completionItem/resolve", json!(item)); + assert_eq!( + res, + json!({ + "label": "SomeInterface", + "labelDetails": { + "description": "http://localhost:4545/subdir/imports_declaration/interface.d.ts", + }, + "kind": 8, + "detail": "interface SomeInterface", + "documentation": { + "kind": "markdown", + "value": "", + }, + "sortText": "￿16_1", + "additionalTextEdits": [ + { + "range": { + "start": { "line": 2, "character": 0 }, + "end": { "line": 2, "character": 0 }, + }, + "newText": " import { SomeInterface } from \"http://localhost:4545/subdir/imports_declaration/interface.d.ts\";\n", + }, + ], + }), + ); + client.shutdown(); +} + #[test] fn lsp_npm_specifier_unopened_file() { let context = TestContextBuilder::new() diff --git a/tests/testdata/subdir/imports_declaration/imports_interface.ts b/tests/testdata/subdir/imports_declaration/imports_interface.ts new file mode 100644 index 0000000000..5eb2e64d51 --- /dev/null +++ b/tests/testdata/subdir/imports_declaration/imports_interface.ts @@ -0,0 +1,3 @@ +import type { SomeInterface } from "./interface.d.ts"; + +export const someObject: SomeInterface = { someField: "someValue" }; diff --git a/tests/testdata/subdir/imports_declaration/interface.d.ts b/tests/testdata/subdir/imports_declaration/interface.d.ts new file mode 100644 index 0000000000..e1531905b9 --- /dev/null +++ b/tests/testdata/subdir/imports_declaration/interface.d.ts @@ -0,0 +1,3 @@ +export interface SomeInterface { + someField: string; +} From 966370c9080afa5fcf3b94617135a3306c1a76f4 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Thu, 9 Jan 2025 14:04:52 -0500 Subject: [PATCH 3/7] refactor(npm): move `InNpmPackageChecker` code to deno_resolver (#27609) As title. Will allow consumers to create this struct and use our behaviour. Closes #27409 --- cli/factory.rs | 9 ++++---- cli/lsp/resolver.rs | 8 +++---- cli/npm/managed/mod.rs | 30 -------------------------- cli/npm/mod.rs | 20 ----------------- cli/standalone/mod.rs | 10 ++++----- resolvers/deno/Cargo.toml | 6 +++--- resolvers/deno/npm/managed/common.rs | 5 ++++- resolvers/deno/npm/managed/mod.rs | 32 ++++++++++++++++++++++++++++ resolvers/deno/npm/mod.rs | 23 +++++++++++++++++++- resolvers/deno/sync.rs | 7 ++++++ 10 files changed, 81 insertions(+), 69 deletions(-) diff --git a/cli/factory.rs b/cli/factory.rs index 86902dfc3b..09b8004366 100644 --- a/cli/factory.rs +++ b/cli/factory.rs @@ -12,6 +12,8 @@ use deno_core::futures::FutureExt; use deno_core::FeatureChecker; use deno_error::JsErrorBox; use deno_resolver::cjs::IsCjsResolutionMode; +use deno_resolver::npm::managed::ManagedInNpmPkgCheckerCreateOptions; +use deno_resolver::npm::CreateInNpmPkgCheckerOptions; use deno_resolver::npm::NpmReqResolverOptions; use deno_resolver::DenoResolverOptions; use deno_resolver::NodeAndNpmReqResolver; @@ -64,14 +66,11 @@ use crate::node::CliNodeCodeTranslator; use crate::node::CliNodeResolver; use crate::node::CliPackageJsonResolver; use crate::npm::create_cli_npm_resolver; -use crate::npm::create_in_npm_pkg_checker; use crate::npm::CliByonmNpmResolverCreateOptions; -use crate::npm::CliManagedInNpmPkgCheckerCreateOptions; use crate::npm::CliManagedNpmResolverCreateOptions; use crate::npm::CliNpmResolver; use crate::npm::CliNpmResolverCreateOptions; use crate::npm::CliNpmResolverManagedSnapshotOption; -use crate::npm::CreateInNpmPkgCheckerOptions; use crate::npm::NpmRegistryReadPermissionChecker; use crate::npm::NpmRegistryReadPermissionCheckerMode; use crate::resolver::CjsTracker; @@ -387,7 +386,7 @@ impl CliFactory { CreateInNpmPkgCheckerOptions::Byonm } else { CreateInNpmPkgCheckerOptions::Managed( - CliManagedInNpmPkgCheckerCreateOptions { + ManagedInNpmPkgCheckerCreateOptions { root_cache_dir_url: self.npm_cache_dir()?.root_dir_url(), maybe_node_modules_path: cli_options .node_modules_dir_path() @@ -395,7 +394,7 @@ impl CliFactory { }, ) }; - Ok(create_in_npm_pkg_checker(options)) + Ok(deno_resolver::npm::create_in_npm_pkg_checker(options)) }) } diff --git a/cli/lsp/resolver.rs b/cli/lsp/resolver.rs index 51820432f7..9ae28405bf 100644 --- a/cli/lsp/resolver.rs +++ b/cli/lsp/resolver.rs @@ -23,6 +23,8 @@ use deno_graph::Range; use deno_npm::NpmSystemInfo; use deno_path_util::url_to_file_path; use deno_resolver::cjs::IsCjsResolutionMode; +use deno_resolver::npm::managed::ManagedInNpmPkgCheckerCreateOptions; +use deno_resolver::npm::CreateInNpmPkgCheckerOptions; use deno_resolver::npm::NpmReqResolverOptions; use deno_resolver::DenoResolverOptions; use deno_resolver::NodeAndNpmReqResolver; @@ -53,12 +55,10 @@ use crate::node::CliNodeResolver; use crate::node::CliPackageJsonResolver; use crate::npm::create_cli_npm_resolver_for_lsp; use crate::npm::CliByonmNpmResolverCreateOptions; -use crate::npm::CliManagedInNpmPkgCheckerCreateOptions; use crate::npm::CliManagedNpmResolverCreateOptions; use crate::npm::CliNpmResolver; use crate::npm::CliNpmResolverCreateOptions; use crate::npm::CliNpmResolverManagedSnapshotOption; -use crate::npm::CreateInNpmPkgCheckerOptions; use crate::npm::ManagedCliNpmResolver; use crate::resolver::CliDenoResolver; use crate::resolver::CliNpmReqResolver; @@ -736,14 +736,14 @@ impl<'a> ResolverFactory<'a> { pub fn in_npm_pkg_checker(&self) -> &Arc { self.services.in_npm_pkg_checker.get_or_init(|| { - crate::npm::create_in_npm_pkg_checker( + deno_resolver::npm::create_in_npm_pkg_checker( match self.services.npm_resolver.as_ref().map(|r| r.as_inner()) { Some(crate::npm::InnerCliNpmResolverRef::Byonm(_)) | None => { CreateInNpmPkgCheckerOptions::Byonm } Some(crate::npm::InnerCliNpmResolverRef::Managed(m)) => { CreateInNpmPkgCheckerOptions::Managed( - CliManagedInNpmPkgCheckerCreateOptions { + ManagedInNpmPkgCheckerCreateOptions { root_cache_dir_url: m.global_cache_root_url(), maybe_node_modules_path: m.maybe_node_modules_path(), }, diff --git a/cli/npm/managed/mod.rs b/cli/npm/managed/mod.rs index 5950af948c..3f4390988a 100644 --- a/cli/npm/managed/mod.rs +++ b/cli/npm/managed/mod.rs @@ -38,7 +38,6 @@ use installers::create_npm_fs_installer; use installers::NpmPackageFsInstaller; use node_resolver::errors::PackageFolderResolveError; use node_resolver::errors::PackageFolderResolveIoError; -use node_resolver::InNpmPackageChecker; use node_resolver::NpmPackageFolderResolver; use super::CliNpmCache; @@ -276,35 +275,6 @@ async fn snapshot_from_lockfile( Ok(snapshot) } -#[derive(Debug)] -struct ManagedInNpmPackageChecker { - root_dir: Url, -} - -impl InNpmPackageChecker for ManagedInNpmPackageChecker { - fn in_npm_package(&self, specifier: &Url) -> bool { - specifier.as_ref().starts_with(self.root_dir.as_str()) - } -} - -pub struct CliManagedInNpmPkgCheckerCreateOptions<'a> { - pub root_cache_dir_url: &'a Url, - pub maybe_node_modules_path: Option<&'a Path>, -} - -pub fn create_managed_in_npm_pkg_checker( - options: CliManagedInNpmPkgCheckerCreateOptions, -) -> Arc { - let root_dir = match options.maybe_node_modules_path { - Some(node_modules_folder) => { - deno_path_util::url_from_directory_path(node_modules_folder).unwrap() - } - None => options.root_cache_dir_url.clone(), - }; - debug_assert!(root_dir.as_str().ends_with('/')); - Arc::new(ManagedInNpmPackageChecker { root_dir }) -} - #[derive(Debug, Clone, PartialEq, Eq)] pub enum PackageCaching<'a> { Only(Cow<'a, [PackageReq]>), diff --git a/cli/npm/mod.rs b/cli/npm/mod.rs index 56032e1a0b..9ac478732d 100644 --- a/cli/npm/mod.rs +++ b/cli/npm/mod.rs @@ -14,7 +14,6 @@ use deno_core::url::Url; use deno_error::JsErrorBox; use deno_npm::npm_rc::ResolvedNpmRc; use deno_npm::registry::NpmPackageInfo; -use deno_resolver::npm::ByonmInNpmPackageChecker; use deno_resolver::npm::ByonmNpmResolver; use deno_resolver::npm::CliNpmReqResolver; use deno_resolver::npm::ResolvePkgFolderFromDenoReqError; @@ -23,13 +22,10 @@ use deno_semver::package::PackageNv; use deno_semver::package::PackageReq; use http::HeaderName; use http::HeaderValue; -use managed::create_managed_in_npm_pkg_checker; -use node_resolver::InNpmPackageChecker; use node_resolver::NpmPackageFolderResolver; pub use self::byonm::CliByonmNpmResolver; pub use self::byonm::CliByonmNpmResolverCreateOptions; -pub use self::managed::CliManagedInNpmPkgCheckerCreateOptions; pub use self::managed::CliManagedNpmResolverCreateOptions; pub use self::managed::CliNpmResolverManagedSnapshotOption; pub use self::managed::ManagedCliNpmResolver; @@ -134,22 +130,6 @@ pub async fn create_cli_npm_resolver( } } -pub enum CreateInNpmPkgCheckerOptions<'a> { - Managed(CliManagedInNpmPkgCheckerCreateOptions<'a>), - Byonm, -} - -pub fn create_in_npm_pkg_checker( - options: CreateInNpmPkgCheckerOptions, -) -> Arc { - match options { - CreateInNpmPkgCheckerOptions::Managed(options) => { - create_managed_in_npm_pkg_checker(options) - } - CreateInNpmPkgCheckerOptions::Byonm => Arc::new(ByonmInNpmPackageChecker), - } -} - pub enum InnerCliNpmResolverRef<'a> { Managed(&'a ManagedCliNpmResolver), #[allow(dead_code)] diff --git a/cli/standalone/mod.rs b/cli/standalone/mod.rs index 30e939cb7a..ecf9805b2d 100644 --- a/cli/standalone/mod.rs +++ b/cli/standalone/mod.rs @@ -39,6 +39,9 @@ use deno_error::JsErrorBox; use deno_npm::npm_rc::ResolvedNpmRc; use deno_package_json::PackageJsonDepValue; use deno_resolver::cjs::IsCjsResolutionMode; +use deno_resolver::npm::create_in_npm_pkg_checker; +use deno_resolver::npm::managed::ManagedInNpmPkgCheckerCreateOptions; +use deno_resolver::npm::CreateInNpmPkgCheckerOptions; use deno_resolver::npm::NpmReqResolverOptions; use deno_runtime::deno_fs; use deno_runtime::deno_fs::FileSystem; @@ -81,14 +84,11 @@ use crate::node::CliNodeCodeTranslator; use crate::node::CliNodeResolver; use crate::node::CliPackageJsonResolver; use crate::npm::create_cli_npm_resolver; -use crate::npm::create_in_npm_pkg_checker; use crate::npm::CliByonmNpmResolverCreateOptions; -use crate::npm::CliManagedInNpmPkgCheckerCreateOptions; use crate::npm::CliManagedNpmResolverCreateOptions; use crate::npm::CliNpmResolver; use crate::npm::CliNpmResolverCreateOptions; use crate::npm::CliNpmResolverManagedSnapshotOption; -use crate::npm::CreateInNpmPkgCheckerOptions; use crate::npm::NpmRegistryReadPermissionChecker; use crate::npm::NpmRegistryReadPermissionCheckerMode; use crate::resolver::CjsTracker; @@ -738,7 +738,7 @@ pub async fn run( .map(|node_modules_dir| root_path.join(node_modules_dir)); let in_npm_pkg_checker = create_in_npm_pkg_checker(CreateInNpmPkgCheckerOptions::Managed( - CliManagedInNpmPkgCheckerCreateOptions { + ManagedInNpmPkgCheckerCreateOptions { root_cache_dir_url: npm_cache_dir.root_dir_url(), maybe_node_modules_path: maybe_node_modules_path.as_deref(), }, @@ -796,7 +796,7 @@ pub async fn run( )); let in_npm_pkg_checker = create_in_npm_pkg_checker(CreateInNpmPkgCheckerOptions::Managed( - CliManagedInNpmPkgCheckerCreateOptions { + ManagedInNpmPkgCheckerCreateOptions { root_cache_dir_url: npm_cache_dir.root_dir_url(), maybe_node_modules_path: None, }, diff --git a/resolvers/deno/Cargo.toml b/resolvers/deno/Cargo.toml index 059fdbc08e..7a5d2833d0 100644 --- a/resolvers/deno/Cargo.toml +++ b/resolvers/deno/Cargo.toml @@ -14,7 +14,7 @@ description = "Deno resolution algorithm" path = "lib.rs" [features] -sync = ["dashmap"] +sync = ["dashmap", "deno_package_json/sync", "node_resolver/sync"] [dependencies] anyhow.workspace = true @@ -27,10 +27,10 @@ deno_config.workspace = true deno_error.workspace = true deno_media_type.workspace = true deno_npm.workspace = true -deno_package_json = { workspace = true, features = ["sync"] } +deno_package_json.workspace = true deno_path_util.workspace = true deno_semver.workspace = true -node_resolver = { workspace = true, features = ["sync"] } +node_resolver.workspace = true parking_lot.workspace = true sys_traits.workspace = true thiserror.workspace = true diff --git a/resolvers/deno/npm/managed/common.rs b/resolvers/deno/npm/managed/common.rs index 23ed63e2f0..5a4a517bf0 100644 --- a/resolvers/deno/npm/managed/common.rs +++ b/resolvers/deno/npm/managed/common.rs @@ -9,6 +9,9 @@ use deno_npm::NpmPackageId; use node_resolver::errors::PackageFolderResolveError; use url::Url; +use crate::sync::MaybeSend; +use crate::sync::MaybeSync; + #[allow(clippy::disallowed_types)] pub(super) type NpmPackageFsResolverRc = crate::sync::MaybeArc; @@ -20,7 +23,7 @@ pub struct NpmPackageFsResolverPackageFolderError(deno_semver::StackString); /// Part of the resolution that interacts with the file system. #[async_trait(?Send)] -pub trait NpmPackageFsResolver: Send + Sync { +pub trait NpmPackageFsResolver: MaybeSend + MaybeSync { /// The local node_modules folder if it is applicable to the implementation. fn node_modules_path(&self) -> Option<&Path>; diff --git a/resolvers/deno/npm/managed/mod.rs b/resolvers/deno/npm/managed/mod.rs index b460656eab..53b07f7d90 100644 --- a/resolvers/deno/npm/managed/mod.rs +++ b/resolvers/deno/npm/managed/mod.rs @@ -5,10 +5,13 @@ mod global; mod local; mod resolution; +use std::path::Path; use std::path::PathBuf; +use node_resolver::InNpmPackageChecker; use sys_traits::FsCanonicalize; use sys_traits::FsMetadata; +use url::Url; pub use self::common::NpmPackageFsResolver; pub use self::common::NpmPackageFsResolverPackageFolderError; @@ -43,3 +46,32 @@ pub fn create_npm_fs_resolver< )), } } + +#[derive(Debug)] +pub struct ManagedInNpmPackageChecker { + root_dir: Url, +} + +impl InNpmPackageChecker for ManagedInNpmPackageChecker { + fn in_npm_package(&self, specifier: &Url) -> bool { + specifier.as_ref().starts_with(self.root_dir.as_str()) + } +} + +pub struct ManagedInNpmPkgCheckerCreateOptions<'a> { + pub root_cache_dir_url: &'a Url, + pub maybe_node_modules_path: Option<&'a Path>, +} + +pub fn create_managed_in_npm_pkg_checker( + options: ManagedInNpmPkgCheckerCreateOptions, +) -> ManagedInNpmPackageChecker { + let root_dir = match options.maybe_node_modules_path { + Some(node_modules_folder) => { + deno_path_util::url_from_directory_path(node_modules_folder).unwrap() + } + None => options.root_cache_dir_url.clone(), + }; + debug_assert!(root_dir.as_str().ends_with('/')); + ManagedInNpmPackageChecker { root_dir } +} diff --git a/resolvers/deno/npm/mod.rs b/resolvers/deno/npm/mod.rs index 54282e677d..4b102d6491 100644 --- a/resolvers/deno/npm/mod.rs +++ b/resolvers/deno/npm/mod.rs @@ -34,11 +34,32 @@ pub use self::byonm::ByonmNpmResolverRc; pub use self::byonm::ByonmResolvePkgFolderFromDenoReqError; pub use self::local::get_package_folder_id_folder_name; pub use self::local::normalize_pkg_name_for_node_modules_deno_folder; +use self::managed::create_managed_in_npm_pkg_checker; +use self::managed::ManagedInNpmPkgCheckerCreateOptions; +use crate::sync::new_rc; +use crate::sync::MaybeSend; +use crate::sync::MaybeSync; mod byonm; mod local; pub mod managed; +pub enum CreateInNpmPkgCheckerOptions<'a> { + Managed(ManagedInNpmPkgCheckerCreateOptions<'a>), + Byonm, +} + +pub fn create_in_npm_pkg_checker( + options: CreateInNpmPkgCheckerOptions, +) -> InNpmPackageCheckerRc { + match options { + CreateInNpmPkgCheckerOptions::Managed(options) => { + new_rc(create_managed_in_npm_pkg_checker(options)) + } + CreateInNpmPkgCheckerOptions::Byonm => new_rc(ByonmInNpmPackageChecker), + } +} + #[derive(Debug, Error, JsError)] #[class(generic)] #[error("Could not resolve \"{}\", but found it in a package.json. Deno expects the node_modules/ directory to be up to date. Did you forget to run `deno install`?", specifier)] @@ -99,7 +120,7 @@ pub type CliNpmReqResolverRc = crate::sync::MaybeArc; // todo(dsherret): a temporary trait until we extract // out the CLI npm resolver into here -pub trait CliNpmReqResolver: Debug + Send + Sync { +pub trait CliNpmReqResolver: Debug + MaybeSend + MaybeSync { fn resolve_pkg_folder_from_deno_module_req( &self, req: &PackageReq, diff --git a/resolvers/deno/sync.rs b/resolvers/deno/sync.rs index 10cdc5ec4d..1734e84231 100644 --- a/resolvers/deno/sync.rs +++ b/resolvers/deno/sync.rs @@ -6,6 +6,8 @@ pub use inner::*; mod inner { #![allow(clippy::disallowed_types)] + pub use core::marker::Send as MaybeSend; + pub use core::marker::Sync as MaybeSync; pub use std::sync::Arc as MaybeArc; pub use dashmap::DashMap as MaybeDashMap; @@ -21,6 +23,11 @@ mod inner { use std::hash::RandomState; pub use std::rc::Rc as MaybeArc; + pub trait MaybeSync {} + impl MaybeSync for T where T: ?Sized {} + pub trait MaybeSend {} + impl MaybeSend for T where T: ?Sized {} + // Wrapper struct that exposes a subset of `DashMap` API. #[derive(Debug)] pub struct MaybeDashMap(RefCell>); From 1d64670f9cb13cb9a61f5fafa3a763edae2fde80 Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Thu, 9 Jan 2025 12:05:39 -0800 Subject: [PATCH 4/7] docs: added jsdoc for window.close() (#27608) --- cli/tsc/dts/lib.deno.window.d.ts | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/cli/tsc/dts/lib.deno.window.d.ts b/cli/tsc/dts/lib.deno.window.d.ts index 8a516beaf6..251f338be6 100644 --- a/cli/tsc/dts/lib.deno.window.d.ts +++ b/cli/tsc/dts/lib.deno.window.d.ts @@ -83,8 +83,30 @@ declare var window: Window & typeof globalThis; declare var self: Window & typeof globalThis; /** @category Platform */ declare var closed: boolean; -/** @category Platform */ + +/** + * Exits the current Deno process. + * + * This function terminates the process by signaling the runtime to exit. + * Similar to exit(0) in posix. Its behavior is similar to the `window.close()` + * method in the browser, but specific to the Deno runtime. + * + * Note: Use this function cautiously, as it will stop the execution of the + * entire Deno program immediately. + * + * @see https://developer.mozilla.org/en-US/docs/Web/API/Window/close + * + * @example + * ```ts + * console.log("About to close the Deno process."); + * close(); // The process will terminate here. + * console.log("This will not be logged."); // This line will never execute. + * ``` + * + * @category Platform + */ declare function close(): void; + /** @category Events */ declare var onerror: ((this: Window, ev: ErrorEvent) => any) | null; /** @category Events */ From 8bafb182ef6c9e096e3c2665ee5dfcaea447e637 Mon Sep 17 00:00:00 2001 From: denobot <33910674+denobot@users.noreply.github.com> Date: Thu, 9 Jan 2025 17:38:18 -0500 Subject: [PATCH 5/7] chore: forward v2.1.5 release commit to main (#27613) Co-authored-by: dsherret --- .github/workflows/ci.generate.ts | 2 +- .github/workflows/ci.yml | 8 ++-- Cargo.lock | 62 ++++++++++++------------- Cargo.toml | 60 ++++++++++++------------ Releases.md | 79 ++++++++++++++++++++++++++++++++ bench_util/Cargo.toml | 2 +- cli/Cargo.toml | 2 +- ext/broadcast_channel/Cargo.toml | 2 +- ext/cache/Cargo.toml | 2 +- ext/canvas/Cargo.toml | 2 +- ext/console/Cargo.toml | 2 +- ext/cron/Cargo.toml | 2 +- ext/crypto/Cargo.toml | 2 +- ext/fetch/Cargo.toml | 2 +- ext/ffi/Cargo.toml | 2 +- ext/fs/Cargo.toml | 2 +- ext/http/Cargo.toml | 2 +- ext/io/Cargo.toml | 2 +- ext/kv/Cargo.toml | 2 +- ext/napi/Cargo.toml | 2 +- ext/napi/sym/Cargo.toml | 2 +- ext/net/Cargo.toml | 2 +- ext/node/Cargo.toml | 2 +- ext/telemetry/Cargo.toml | 2 +- ext/tls/Cargo.toml | 2 +- ext/url/Cargo.toml | 2 +- ext/web/Cargo.toml | 2 +- ext/webgpu/Cargo.toml | 2 +- ext/webidl/Cargo.toml | 2 +- ext/websocket/Cargo.toml | 2 +- ext/webstorage/Cargo.toml | 2 +- resolvers/deno/Cargo.toml | 2 +- resolvers/node/Cargo.toml | 2 +- resolvers/npm_cache/Cargo.toml | 4 +- runtime/Cargo.toml | 2 +- runtime/permissions/Cargo.toml | 2 +- 36 files changed, 177 insertions(+), 98 deletions(-) diff --git a/.github/workflows/ci.generate.ts b/.github/workflows/ci.generate.ts index c8980180a0..3214fad509 100755 --- a/.github/workflows/ci.generate.ts +++ b/.github/workflows/ci.generate.ts @@ -5,7 +5,7 @@ import { stringify } from "jsr:@std/yaml@^0.221/stringify"; // Bump this number when you want to purge the cache. // Note: the tools/release/01_bump_crate_versions.ts script will update this version // automatically via regex, so ensure that this line maintains this format. -const cacheVersion = 32; +const cacheVersion = 33; const ubuntuX86Runner = "ubuntu-24.04"; const ubuntuX86XlRunner = "ubuntu-24.04-xl"; diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 524af7ac36..e560840d2e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -184,8 +184,8 @@ jobs: ~/.cargo/registry/index ~/.cargo/registry/cache ~/.cargo/git/db - key: '32-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles(''Cargo.lock'') }}' - restore-keys: '32-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-' + key: '33-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles(''Cargo.lock'') }}' + restore-keys: '33-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-' if: '!(matrix.skip)' - uses: dsherret/rust-toolchain-file@v1 if: '!(matrix.skip)' @@ -379,7 +379,7 @@ jobs: !./target/*/*.zip !./target/*/*.tar.gz key: never_saved - restore-keys: '32-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-' + restore-keys: '33-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-' - name: Apply and update mtime cache if: '!(matrix.skip) && (!startsWith(github.ref, ''refs/tags/''))' uses: ./.github/mtime_cache @@ -689,7 +689,7 @@ jobs: !./target/*/gn_root !./target/*/*.zip !./target/*/*.tar.gz - key: '32-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}' + key: '33-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}' publish-canary: name: publish canary runs-on: ubuntu-24.04 diff --git a/Cargo.lock b/Cargo.lock index e94fd48410..d16aafe6f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1244,7 +1244,7 @@ dependencies = [ [[package]] name = "deno" -version = "2.1.4" +version = "2.1.5" dependencies = [ "anstream", "async-trait", @@ -1421,7 +1421,7 @@ dependencies = [ [[package]] name = "deno_bench_util" -version = "0.178.0" +version = "0.179.0" dependencies = [ "bencher", "deno_core", @@ -1430,7 +1430,7 @@ dependencies = [ [[package]] name = "deno_broadcast_channel" -version = "0.178.0" +version = "0.179.0" dependencies = [ "async-trait", "deno_core", @@ -1442,7 +1442,7 @@ dependencies = [ [[package]] name = "deno_cache" -version = "0.116.0" +version = "0.117.0" dependencies = [ "async-trait", "deno_core", @@ -1485,7 +1485,7 @@ dependencies = [ [[package]] name = "deno_canvas" -version = "0.53.0" +version = "0.54.0" dependencies = [ "deno_core", "deno_error", @@ -1523,7 +1523,7 @@ dependencies = [ [[package]] name = "deno_console" -version = "0.184.0" +version = "0.185.0" dependencies = [ "deno_core", ] @@ -1574,7 +1574,7 @@ checksum = "fe4dccb6147bb3f3ba0c7a48e993bfeb999d2c2e47a81badee80e2b370c8d695" [[package]] name = "deno_cron" -version = "0.64.0" +version = "0.65.0" dependencies = [ "anyhow", "async-trait", @@ -1588,7 +1588,7 @@ dependencies = [ [[package]] name = "deno_crypto" -version = "0.198.0" +version = "0.199.0" dependencies = [ "aes", "aes-gcm", @@ -1681,7 +1681,7 @@ dependencies = [ [[package]] name = "deno_fetch" -version = "0.208.0" +version = "0.209.0" dependencies = [ "base64 0.21.7", "bytes", @@ -1718,7 +1718,7 @@ dependencies = [ [[package]] name = "deno_ffi" -version = "0.171.0" +version = "0.172.0" dependencies = [ "deno_core", "deno_error", @@ -1739,7 +1739,7 @@ dependencies = [ [[package]] name = "deno_fs" -version = "0.94.0" +version = "0.95.0" dependencies = [ "async-trait", "base32", @@ -1797,7 +1797,7 @@ dependencies = [ [[package]] name = "deno_http" -version = "0.182.0" +version = "0.183.0" dependencies = [ "async-compression", "async-trait", @@ -1837,7 +1837,7 @@ dependencies = [ [[package]] name = "deno_io" -version = "0.94.0" +version = "0.95.0" dependencies = [ "async-trait", "deno_core", @@ -1859,7 +1859,7 @@ dependencies = [ [[package]] name = "deno_kv" -version = "0.92.0" +version = "0.93.0" dependencies = [ "anyhow", "async-trait", @@ -1933,7 +1933,7 @@ dependencies = [ [[package]] name = "deno_napi" -version = "0.115.0" +version = "0.116.0" dependencies = [ "deno_core", "deno_error", @@ -1962,7 +1962,7 @@ dependencies = [ [[package]] name = "deno_net" -version = "0.176.0" +version = "0.177.0" dependencies = [ "deno_core", "deno_error", @@ -1981,7 +1981,7 @@ dependencies = [ [[package]] name = "deno_node" -version = "0.122.0" +version = "0.123.0" dependencies = [ "aead-gcm-stream", "aes", @@ -2094,7 +2094,7 @@ dependencies = [ [[package]] name = "deno_npm_cache" -version = "0.3.0" +version = "0.4.0" dependencies = [ "async-trait", "base64 0.21.7", @@ -2172,7 +2172,7 @@ dependencies = [ [[package]] name = "deno_permissions" -version = "0.43.0" +version = "0.44.0" dependencies = [ "capacity_builder 0.5.0", "deno_core", @@ -2192,7 +2192,7 @@ dependencies = [ [[package]] name = "deno_resolver" -version = "0.15.0" +version = "0.16.0" dependencies = [ "anyhow", "async-trait", @@ -2217,7 +2217,7 @@ dependencies = [ [[package]] name = "deno_runtime" -version = "0.192.0" +version = "0.193.0" dependencies = [ "color-print", "deno_ast", @@ -2323,7 +2323,7 @@ dependencies = [ [[package]] name = "deno_telemetry" -version = "0.6.0" +version = "0.7.0" dependencies = [ "async-trait", "deno_core", @@ -2366,7 +2366,7 @@ dependencies = [ [[package]] name = "deno_tls" -version = "0.171.0" +version = "0.172.0" dependencies = [ "deno_core", "deno_error", @@ -2417,7 +2417,7 @@ dependencies = [ [[package]] name = "deno_url" -version = "0.184.0" +version = "0.185.0" dependencies = [ "deno_bench_util", "deno_console", @@ -2430,7 +2430,7 @@ dependencies = [ [[package]] name = "deno_web" -version = "0.215.0" +version = "0.216.0" dependencies = [ "async-trait", "base64-simd 0.8.0", @@ -2453,7 +2453,7 @@ dependencies = [ [[package]] name = "deno_webgpu" -version = "0.151.0" +version = "0.152.0" dependencies = [ "deno_core", "deno_error", @@ -2467,7 +2467,7 @@ dependencies = [ [[package]] name = "deno_webidl" -version = "0.184.0" +version = "0.185.0" dependencies = [ "deno_bench_util", "deno_core", @@ -2475,7 +2475,7 @@ dependencies = [ [[package]] name = "deno_websocket" -version = "0.189.0" +version = "0.190.0" dependencies = [ "bytes", "deno_core", @@ -2498,7 +2498,7 @@ dependencies = [ [[package]] name = "deno_webstorage" -version = "0.179.0" +version = "0.180.0" dependencies = [ "deno_core", "deno_error", @@ -5070,7 +5070,7 @@ dependencies = [ [[package]] name = "napi_sym" -version = "0.114.0" +version = "0.115.0" dependencies = [ "quote", "serde", @@ -5125,7 +5125,7 @@ dependencies = [ [[package]] name = "node_resolver" -version = "0.22.0" +version = "0.23.0" dependencies = [ "anyhow", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index 75572162c4..b7c7219fba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,17 +50,17 @@ repository = "https://github.com/denoland/deno" deno_ast = { version = "=0.44.0", features = ["transpiling"] } deno_core = { version = "0.330.0" } -deno_bench_util = { version = "0.178.0", path = "./bench_util" } +deno_bench_util = { version = "0.179.0", path = "./bench_util" } deno_config = { version = "=0.43.0", features = ["workspace", "sync"] } deno_lockfile = "=0.24.0" deno_media_type = { version = "0.2.3", features = ["module_specifier"] } deno_npm = "=0.27.0" deno_path_util = "=0.3.0" -deno_permissions = { version = "0.43.0", path = "./runtime/permissions" } -deno_runtime = { version = "0.192.0", path = "./runtime" } +deno_permissions = { version = "0.44.0", path = "./runtime/permissions" } +deno_runtime = { version = "0.193.0", path = "./runtime" } deno_semver = "=0.7.1" deno_terminal = "0.2.0" -napi_sym = { version = "0.114.0", path = "./ext/napi/sym" } +napi_sym = { version = "0.115.0", path = "./ext/napi/sym" } test_util = { package = "test_server", path = "./tests/util/server" } denokv_proto = "0.9.0" @@ -69,34 +69,34 @@ denokv_remote = "0.9.0" denokv_sqlite = { default-features = false, version = "0.9.0" } # exts -deno_broadcast_channel = { version = "0.178.0", path = "./ext/broadcast_channel" } -deno_cache = { version = "0.116.0", path = "./ext/cache" } -deno_canvas = { version = "0.53.0", path = "./ext/canvas" } -deno_console = { version = "0.184.0", path = "./ext/console" } -deno_cron = { version = "0.64.0", path = "./ext/cron" } -deno_crypto = { version = "0.198.0", path = "./ext/crypto" } -deno_fetch = { version = "0.208.0", path = "./ext/fetch" } -deno_ffi = { version = "0.171.0", path = "./ext/ffi" } -deno_fs = { version = "0.94.0", path = "./ext/fs" } -deno_http = { version = "0.182.0", path = "./ext/http" } -deno_io = { version = "0.94.0", path = "./ext/io" } -deno_kv = { version = "0.92.0", path = "./ext/kv" } -deno_napi = { version = "0.115.0", path = "./ext/napi" } -deno_net = { version = "0.176.0", path = "./ext/net" } -deno_node = { version = "0.122.0", path = "./ext/node" } -deno_telemetry = { version = "0.6.0", path = "./ext/telemetry" } -deno_tls = { version = "0.171.0", path = "./ext/tls" } -deno_url = { version = "0.184.0", path = "./ext/url" } -deno_web = { version = "0.215.0", path = "./ext/web" } -deno_webgpu = { version = "0.151.0", path = "./ext/webgpu" } -deno_webidl = { version = "0.184.0", path = "./ext/webidl" } -deno_websocket = { version = "0.189.0", path = "./ext/websocket" } -deno_webstorage = { version = "0.179.0", path = "./ext/webstorage" } +deno_broadcast_channel = { version = "0.179.0", path = "./ext/broadcast_channel" } +deno_cache = { version = "0.117.0", path = "./ext/cache" } +deno_canvas = { version = "0.54.0", path = "./ext/canvas" } +deno_console = { version = "0.185.0", path = "./ext/console" } +deno_cron = { version = "0.65.0", path = "./ext/cron" } +deno_crypto = { version = "0.199.0", path = "./ext/crypto" } +deno_fetch = { version = "0.209.0", path = "./ext/fetch" } +deno_ffi = { version = "0.172.0", path = "./ext/ffi" } +deno_fs = { version = "0.95.0", path = "./ext/fs" } +deno_http = { version = "0.183.0", path = "./ext/http" } +deno_io = { version = "0.95.0", path = "./ext/io" } +deno_kv = { version = "0.93.0", path = "./ext/kv" } +deno_napi = { version = "0.116.0", path = "./ext/napi" } +deno_net = { version = "0.177.0", path = "./ext/net" } +deno_node = { version = "0.123.0", path = "./ext/node" } +deno_telemetry = { version = "0.7.0", path = "./ext/telemetry" } +deno_tls = { version = "0.172.0", path = "./ext/tls" } +deno_url = { version = "0.185.0", path = "./ext/url" } +deno_web = { version = "0.216.0", path = "./ext/web" } +deno_webgpu = { version = "0.152.0", path = "./ext/webgpu" } +deno_webidl = { version = "0.185.0", path = "./ext/webidl" } +deno_websocket = { version = "0.190.0", path = "./ext/websocket" } +deno_webstorage = { version = "0.180.0", path = "./ext/webstorage" } # resolvers -deno_npm_cache = { version = "0.3.0", path = "./resolvers/npm_cache" } -deno_resolver = { version = "0.15.0", path = "./resolvers/deno" } -node_resolver = { version = "0.22.0", path = "./resolvers/node" } +deno_npm_cache = { version = "0.4.0", path = "./resolvers/npm_cache" } +deno_resolver = { version = "0.16.0", path = "./resolvers/deno" } +node_resolver = { version = "0.23.0", path = "./resolvers/node" } aes = "=0.8.3" anyhow = "1.0.57" diff --git a/Releases.md b/Releases.md index aaae202a37..71cf524ca2 100644 --- a/Releases.md +++ b/Releases.md @@ -6,6 +6,85 @@ https://github.com/denoland/deno/releases We also have one-line install commands at: https://github.com/denoland/deno_install +### 2.1.5 / 2025.01.09 + +- feat(unstable): implement QUIC (#21942) +- feat(unstable): add JS linting plugin infrastructure (#27416) +- feat(unstable): add OTEL MeterProvider (#27240) +- feat(unstable): no config npm:@opentelemetry/api integration (#27541) +- feat(unstable): replace SpanExporter with TracerProvider (#27473) +- feat(unstable): support selectors in JS lint plugins (#27452) +- fix(check): line-break between diagnostic message chain entries (#27543) +- fix(check): move module not found errors to typescript diagnostics (#27533) +- fix(compile): analyze modules in directory specified in --include (#27296) +- fix(compile): be more deterministic when compiling the same code in different + directories (#27395) +- fix(compile): display embedded file sizes and total (#27360) +- fix(compile): output contents of embedded file system (#27302) +- fix(ext/fetch): better error message when body resource is unavailable + (#27429) +- fix(ext/fetch): retry some http/2 errors (#27417) +- fix(ext/fs): do not throw for bigint ctime/mtime/atime (#27453) +- fix(ext/http): improve error message when underlying resource of request body + unavailable (#27463) +- fix(ext/net): update moka cache to avoid potential panic in `Deno.resolveDns` + on some laptops with Ryzen CPU (#27572) +- fix(ext/node): fix `fs.access`/`fs.promises.access` with `X_OK` mode parameter + on Windows (#27407) +- fix(ext/node): fix `os.cpus()` on Linux (#27592) +- fix(ext/node): RangeError timingSafeEqual with different byteLength (#27470) +- fix(ext/node): add `truncate` method to the `FileHandle` class (#27389) +- fix(ext/node): add support of any length IV for aes-(128|256)-gcm ciphers + (#27476) +- fix(ext/node): convert brotli chunks with proper byte offset (#27455) +- fix(ext/node): do not exit worker thread when there is pending async op + (#27378) +- fix(ext/node): have `process` global available in Node context (#27562) +- fix(ext/node): make getCiphers return supported ciphers (#27466) +- fix(ext/node): sort list of built-in modules alphabetically (#27410) +- fix(ext/node): support createConnection option in node:http.request() (#25470) +- fix(ext/node): support private key export in JWK format (#27325) +- fix(ext/web): add `[[ErrorData]]` slot to `DOMException` (#27342) +- fix(ext/websocket): Fix close code without reason (#27578) +- fix(jsr): Wasm imports fail to load (#27594) +- fix(kv): improve backoff error message and inline documentation (#27537) +- fix(lint): fix single char selectors being ignored (#27576) +- fix(lockfile): include dependencies listed in external import map in lockfile + (#27337) +- fix(lsp): css preprocessor formatting (#27526) +- fix(lsp): don't skip dirs with enabled subdirs (#27580) +- fix(lsp): include "node:" prefix for node builtin auto-imports (#27404) +- fix(lsp): respect "typescript.suggestionActions.enabled" setting (#27373) +- fix(lsp): rewrite imports for 'Move to a new file' action (#27427) +- fix(lsp): sql and component file formatting (#27350) +- fix(lsp): use verbatim specifier for URL auto-imports (#27605) +- fix(no-slow-types): handle rest param with internal assignments (#27581) +- fix(node/fs): add a chmod method to the FileHandle class (#27522) +- fix(node): add missing `inspector/promises` (#27491) +- fix(node): handle cjs exports with escaped chars (#27438) +- fix(npm): deterministically output tags to initialized file (#27514) +- fix(npm): search node_modules folder for package matching npm specifier + (#27345) +- fix(outdated): ensure "Latest" version is greater than "Update" version + (#27390) +- fix(outdated): support updating dependencies in external import maps (#27339) +- fix(permissions): implicit `--allow-import` when using `--cached-only` + (#27530) +- fix(publish): infer literal types in const contexts (#27425) +- fix(task): properly handle task name wildcards with --recursive (#27396) +- fix(task): support tasks without commands (#27191) +- fix(unstable): don't error on non-existing attrs or type attr (#27456) +- fix: FastString v8_string() should error when cannot allocated (#27375) +- fix: deno_resolver crate without 'sync' feature (#27403) +- fix: incorrect memory info free/available bytes on mac (#27460) +- fix: upgrade deno_doc to 0.161.3 (#27377) +- perf(fs/windows): stat - only open file once (#27487) +- perf(node/fs/copy): reduce metadata lookups copying directory (#27495) +- perf: don't store duplicate info for ops in the snapshot (#27430) +- perf: remove now needless canonicalization getting closest package.json + (#27437) +- perf: upgrade to deno_semver 0.7 (#27426) + ### 2.1.4 / 2024.12.11 - feat(unstable): support caching npm dependencies only as they're needed diff --git a/bench_util/Cargo.toml b/bench_util/Cargo.toml index 3172426c27..30a88e931e 100644 --- a/bench_util/Cargo.toml +++ b/bench_util/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_bench_util" -version = "0.178.0" +version = "0.179.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/cli/Cargo.toml b/cli/Cargo.toml index b77c904c40..8248d40701 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno" -version = "2.1.4" +version = "2.1.5" authors.workspace = true default-run = "deno" edition.workspace = true diff --git a/ext/broadcast_channel/Cargo.toml b/ext/broadcast_channel/Cargo.toml index 27aa7df702..0e1e0c3fbd 100644 --- a/ext/broadcast_channel/Cargo.toml +++ b/ext/broadcast_channel/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_broadcast_channel" -version = "0.178.0" +version = "0.179.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/cache/Cargo.toml b/ext/cache/Cargo.toml index b77630832f..18fbe23a23 100644 --- a/ext/cache/Cargo.toml +++ b/ext/cache/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_cache" -version = "0.116.0" +version = "0.117.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/canvas/Cargo.toml b/ext/canvas/Cargo.toml index 11c6feabb8..e5c70b0054 100644 --- a/ext/canvas/Cargo.toml +++ b/ext/canvas/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_canvas" -version = "0.53.0" +version = "0.54.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/console/Cargo.toml b/ext/console/Cargo.toml index b4811265ba..24cdb040a7 100644 --- a/ext/console/Cargo.toml +++ b/ext/console/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_console" -version = "0.184.0" +version = "0.185.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/cron/Cargo.toml b/ext/cron/Cargo.toml index 224508265a..7b41593841 100644 --- a/ext/cron/Cargo.toml +++ b/ext/cron/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_cron" -version = "0.64.0" +version = "0.65.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/crypto/Cargo.toml b/ext/crypto/Cargo.toml index 96ddd1621f..c9876105e5 100644 --- a/ext/crypto/Cargo.toml +++ b/ext/crypto/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_crypto" -version = "0.198.0" +version = "0.199.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/fetch/Cargo.toml b/ext/fetch/Cargo.toml index 21f77153b9..a0d29291b0 100644 --- a/ext/fetch/Cargo.toml +++ b/ext/fetch/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_fetch" -version = "0.208.0" +version = "0.209.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/ffi/Cargo.toml b/ext/ffi/Cargo.toml index b78aa36d7c..d71c04f9ff 100644 --- a/ext/ffi/Cargo.toml +++ b/ext/ffi/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_ffi" -version = "0.171.0" +version = "0.172.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/fs/Cargo.toml b/ext/fs/Cargo.toml index 05141e46c9..df9d140ac3 100644 --- a/ext/fs/Cargo.toml +++ b/ext/fs/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_fs" -version = "0.94.0" +version = "0.95.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/http/Cargo.toml b/ext/http/Cargo.toml index 1ecb6f66c8..01198cb8e6 100644 --- a/ext/http/Cargo.toml +++ b/ext/http/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_http" -version = "0.182.0" +version = "0.183.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/io/Cargo.toml b/ext/io/Cargo.toml index 9d11e1b0f6..0de9dfca84 100644 --- a/ext/io/Cargo.toml +++ b/ext/io/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_io" -version = "0.94.0" +version = "0.95.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/kv/Cargo.toml b/ext/kv/Cargo.toml index 1a1cd346fb..726dccdfba 100644 --- a/ext/kv/Cargo.toml +++ b/ext/kv/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_kv" -version = "0.92.0" +version = "0.93.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/napi/Cargo.toml b/ext/napi/Cargo.toml index ac62cc5dc8..ff69d6a47e 100644 --- a/ext/napi/Cargo.toml +++ b/ext/napi/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_napi" -version = "0.115.0" +version = "0.116.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/napi/sym/Cargo.toml b/ext/napi/sym/Cargo.toml index c832a1fa30..f845b639ba 100644 --- a/ext/napi/sym/Cargo.toml +++ b/ext/napi/sym/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "napi_sym" -version = "0.114.0" +version = "0.115.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/net/Cargo.toml b/ext/net/Cargo.toml index ad20badb10..ba02fe8708 100644 --- a/ext/net/Cargo.toml +++ b/ext/net/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_net" -version = "0.176.0" +version = "0.177.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/node/Cargo.toml b/ext/node/Cargo.toml index 19936b74f1..6cd2b32866 100644 --- a/ext/node/Cargo.toml +++ b/ext/node/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_node" -version = "0.122.0" +version = "0.123.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/telemetry/Cargo.toml b/ext/telemetry/Cargo.toml index 484a90eeb1..a83a08c3fe 100644 --- a/ext/telemetry/Cargo.toml +++ b/ext/telemetry/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_telemetry" -version = "0.6.0" +version = "0.7.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/tls/Cargo.toml b/ext/tls/Cargo.toml index 1e804bd538..39b3d17c86 100644 --- a/ext/tls/Cargo.toml +++ b/ext/tls/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_tls" -version = "0.171.0" +version = "0.172.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/url/Cargo.toml b/ext/url/Cargo.toml index 1f7f7b36c6..2078571e39 100644 --- a/ext/url/Cargo.toml +++ b/ext/url/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_url" -version = "0.184.0" +version = "0.185.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/web/Cargo.toml b/ext/web/Cargo.toml index d5dbbdecca..065f1a12b1 100644 --- a/ext/web/Cargo.toml +++ b/ext/web/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_web" -version = "0.215.0" +version = "0.216.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/webgpu/Cargo.toml b/ext/webgpu/Cargo.toml index 4bb9fa9a41..369fdb02e6 100644 --- a/ext/webgpu/Cargo.toml +++ b/ext/webgpu/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_webgpu" -version = "0.151.0" +version = "0.152.0" authors = ["the Deno authors"] edition.workspace = true license = "MIT" diff --git a/ext/webidl/Cargo.toml b/ext/webidl/Cargo.toml index ab285c7204..adb072ff45 100644 --- a/ext/webidl/Cargo.toml +++ b/ext/webidl/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_webidl" -version = "0.184.0" +version = "0.185.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/websocket/Cargo.toml b/ext/websocket/Cargo.toml index dc24d52e16..a94da90484 100644 --- a/ext/websocket/Cargo.toml +++ b/ext/websocket/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_websocket" -version = "0.189.0" +version = "0.190.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/ext/webstorage/Cargo.toml b/ext/webstorage/Cargo.toml index 044aa41f6a..8a900f662b 100644 --- a/ext/webstorage/Cargo.toml +++ b/ext/webstorage/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_webstorage" -version = "0.179.0" +version = "0.180.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/resolvers/deno/Cargo.toml b/resolvers/deno/Cargo.toml index 7a5d2833d0..1c603ecaed 100644 --- a/resolvers/deno/Cargo.toml +++ b/resolvers/deno/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_resolver" -version = "0.15.0" +version = "0.16.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/resolvers/node/Cargo.toml b/resolvers/node/Cargo.toml index 31bca50a31..1c2a342a9f 100644 --- a/resolvers/node/Cargo.toml +++ b/resolvers/node/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "node_resolver" -version = "0.22.0" +version = "0.23.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/resolvers/npm_cache/Cargo.toml b/resolvers/npm_cache/Cargo.toml index 3cefc6538a..d73cee9cd6 100644 --- a/resolvers/npm_cache/Cargo.toml +++ b/resolvers/npm_cache/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_npm_cache" -version = "0.3.0" +version = "0.4.0" authors.workspace = true edition.workspace = true license.workspace = true @@ -18,7 +18,7 @@ async-trait.workspace = true base64.workspace = true boxed_error.workspace = true deno_cache_dir.workspace = true -deno_error.workspace = true +deno_error = { workspace = true, features = ["serde", "serde_json", "tokio"] } deno_npm.workspace = true deno_path_util.workspace = true deno_semver.workspace = true diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 72db8888f8..5ecd911e8a 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_runtime" -version = "0.192.0" +version = "0.193.0" authors.workspace = true edition.workspace = true license.workspace = true diff --git a/runtime/permissions/Cargo.toml b/runtime/permissions/Cargo.toml index be397fe6d3..52501ee197 100644 --- a/runtime/permissions/Cargo.toml +++ b/runtime/permissions/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_permissions" -version = "0.43.0" +version = "0.44.0" authors.workspace = true edition.workspace = true license.workspace = true From 34beeb7703d1845e31dce169b90f012834689808 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Thu, 9 Jan 2025 18:30:48 -0500 Subject: [PATCH 6/7] refactor(npm): move `SloppyImportsCachedFs` to deno_resolver (#27610) --- cli/factory.rs | 2 +- cli/graph_util.rs | 2 +- cli/lsp/config.rs | 2 +- cli/lsp/diagnostics.rs | 2 +- cli/resolver.rs | 68 ++------------------------------ cli/tools/registry/unfurl.rs | 2 +- resolvers/deno/sloppy_imports.rs | 48 ++++++++++++++++++++++ 7 files changed, 57 insertions(+), 69 deletions(-) diff --git a/cli/factory.rs b/cli/factory.rs index 09b8004366..d545fd6ddf 100644 --- a/cli/factory.rs +++ b/cli/factory.rs @@ -15,6 +15,7 @@ use deno_resolver::cjs::IsCjsResolutionMode; use deno_resolver::npm::managed::ManagedInNpmPkgCheckerCreateOptions; use deno_resolver::npm::CreateInNpmPkgCheckerOptions; use deno_resolver::npm::NpmReqResolverOptions; +use deno_resolver::sloppy_imports::SloppyImportsCachedFs; use deno_resolver::DenoResolverOptions; use deno_resolver::NodeAndNpmReqResolver; use deno_runtime::deno_fs; @@ -80,7 +81,6 @@ use crate::resolver::CliResolver; use crate::resolver::CliResolverOptions; use crate::resolver::CliSloppyImportsResolver; use crate::resolver::NpmModuleLoader; -use crate::resolver::SloppyImportsCachedFs; use crate::standalone::binary::DenoCompileBinaryWriter; use crate::sys::CliSys; use crate::tools::check::TypeChecker; diff --git a/cli/graph_util.rs b/cli/graph_util.rs index f32dae8a07..84beee027e 100644 --- a/cli/graph_util.rs +++ b/cli/graph_util.rs @@ -29,6 +29,7 @@ use deno_graph::ResolutionError; use deno_graph::SpecifierError; use deno_graph::WorkspaceFastCheckOption; use deno_path_util::url_to_file_path; +use deno_resolver::sloppy_imports::SloppyImportsCachedFs; use deno_resolver::sloppy_imports::SloppyImportsResolutionKind; use deno_runtime::deno_node; use deno_runtime::deno_permissions::PermissionsContainer; @@ -55,7 +56,6 @@ use crate::npm::CliNpmResolver; use crate::resolver::CjsTracker; use crate::resolver::CliResolver; use crate::resolver::CliSloppyImportsResolver; -use crate::resolver::SloppyImportsCachedFs; use crate::sys::CliSys; use crate::tools::check; use crate::tools::check::CheckError; diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs index 0cd8468153..7841ee0783 100644 --- a/cli/lsp/config.rs +++ b/cli/lsp/config.rs @@ -46,6 +46,7 @@ use deno_lint::linter::LintConfig as DenoLintConfig; use deno_npm::npm_rc::ResolvedNpmRc; use deno_package_json::PackageJsonCache; use deno_path_util::url_to_file_path; +use deno_resolver::sloppy_imports::SloppyImportsCachedFs; use deno_runtime::deno_node::PackageJson; use indexmap::IndexSet; use lsp_types::ClientCapabilities; @@ -65,7 +66,6 @@ use crate::cache::FastInsecureHasher; use crate::file_fetcher::CliFileFetcher; use crate::lsp::logging::lsp_warn; use crate::resolver::CliSloppyImportsResolver; -use crate::resolver::SloppyImportsCachedFs; use crate::sys::CliSys; use crate::tools::lint::CliLinter; use crate::tools::lint::CliLinterOptions; diff --git a/cli/lsp/diagnostics.rs b/cli/lsp/diagnostics.rs index 0982ff5ceb..42a1a0c52a 100644 --- a/cli/lsp/diagnostics.rs +++ b/cli/lsp/diagnostics.rs @@ -26,6 +26,7 @@ use deno_graph::Resolution; use deno_graph::ResolutionError; use deno_graph::SpecifierError; use deno_lint::linter::LintConfig as DenoLintConfig; +use deno_resolver::sloppy_imports::SloppyImportsCachedFs; use deno_resolver::sloppy_imports::SloppyImportsResolution; use deno_resolver::sloppy_imports::SloppyImportsResolutionKind; use deno_runtime::deno_node; @@ -61,7 +62,6 @@ use crate::graph_util; use crate::graph_util::enhanced_resolution_error_message; use crate::lsp::lsp_custom::DiagnosticBatchNotificationParams; use crate::resolver::CliSloppyImportsResolver; -use crate::resolver::SloppyImportsCachedFs; use crate::sys::CliSys; use crate::tools::lint::CliLinter; use crate::tools::lint::CliLinterOptions; diff --git a/cli/resolver.rs b/cli/resolver.rs index 7873a9cce0..1d12d5f8b7 100644 --- a/cli/resolver.rs +++ b/cli/resolver.rs @@ -1,12 +1,9 @@ // Copyright 2018-2025 the Deno authors. MIT license. use std::borrow::Cow; -use std::path::Path; -use std::path::PathBuf; use std::sync::Arc; use async_trait::async_trait; -use dashmap::DashMap; use dashmap::DashSet; use deno_ast::MediaType; use deno_config::workspace::MappedResolutionDiagnostic; @@ -22,6 +19,7 @@ use deno_graph::source::UnknownBuiltInNodeModuleError; use deno_graph::NpmLoadError; use deno_graph::NpmResolvePkgReqsResult; use deno_npm::resolution::NpmResolutionError; +use deno_resolver::sloppy_imports::SloppyImportsCachedFs; use deno_resolver::sloppy_imports::SloppyImportsResolver; use deno_runtime::colors; use deno_runtime::deno_fs; @@ -30,8 +28,6 @@ use deno_runtime::deno_node::RealIsBuiltInNodeModuleChecker; use deno_semver::package::PackageReq; use node_resolver::NodeResolutionKind; use node_resolver::ResolutionMode; -use sys_traits::FsMetadata; -use sys_traits::FsMetadataValue; use thiserror::Error; use crate::args::NpmCachingStrategy; @@ -45,11 +41,12 @@ use crate::util::text_encoding::from_utf8_lossy_cow; pub type CjsTracker = deno_resolver::cjs::CjsTracker; pub type IsCjsResolver = deno_resolver::cjs::IsCjsResolver; +pub type CliSloppyImportsCachedFs = SloppyImportsCachedFs; pub type CliSloppyImportsResolver = - SloppyImportsResolver; + SloppyImportsResolver; pub type CliDenoResolver = deno_resolver::DenoResolver< RealIsBuiltInNodeModuleChecker, - SloppyImportsCachedFs, + CliSloppyImportsCachedFs, CliSys, >; pub type CliNpmReqResolver = @@ -397,60 +394,3 @@ impl<'a> deno_graph::source::NpmResolver for WorkerCliNpmGraphResolver<'a> { self.bare_node_builtins_enabled } } - -#[derive(Debug)] -pub struct SloppyImportsCachedFs { - sys: CliSys, - cache: Option< - DashMap< - PathBuf, - Option, - >, - >, -} - -impl SloppyImportsCachedFs { - pub fn new(sys: CliSys) -> Self { - Self { - sys, - cache: Some(Default::default()), - } - } - - pub fn new_without_stat_cache(fs: CliSys) -> Self { - Self { - sys: fs, - cache: None, - } - } -} - -impl deno_resolver::sloppy_imports::SloppyImportResolverFs - for SloppyImportsCachedFs -{ - fn stat_sync( - &self, - path: &Path, - ) -> Option { - if let Some(cache) = &self.cache { - if let Some(entry) = cache.get(path) { - return *entry; - } - } - - let entry = self.sys.fs_metadata(path).ok().and_then(|stat| { - if stat.file_type().is_file() { - Some(deno_resolver::sloppy_imports::SloppyImportsFsEntry::File) - } else if stat.file_type().is_dir() { - Some(deno_resolver::sloppy_imports::SloppyImportsFsEntry::Dir) - } else { - None - } - }); - - if let Some(cache) = &self.cache { - cache.insert(path.to_owned(), entry); - } - entry - } -} diff --git a/cli/tools/registry/unfurl.rs b/cli/tools/registry/unfurl.rs index e3501c348b..e3fd4e715b 100644 --- a/cli/tools/registry/unfurl.rs +++ b/cli/tools/registry/unfurl.rs @@ -660,6 +660,7 @@ mod tests { use deno_config::workspace::ResolverWorkspaceJsrPackage; use deno_core::serde_json::json; use deno_core::url::Url; + use deno_resolver::sloppy_imports::SloppyImportsCachedFs; use deno_runtime::deno_node::PackageJson; use deno_semver::Version; use import_map::ImportMapWithDiagnostics; @@ -668,7 +669,6 @@ mod tests { use test_util::testdata_path; use super::*; - use crate::resolver::SloppyImportsCachedFs; use crate::sys::CliSys; fn parse_ast(specifier: &Url, source_code: &str) -> ParsedSource { diff --git a/resolvers/deno/sloppy_imports.rs b/resolvers/deno/sloppy_imports.rs index b6fbf487dd..486d2dab1e 100644 --- a/resolvers/deno/sloppy_imports.rs +++ b/resolvers/deno/sloppy_imports.rs @@ -7,8 +7,12 @@ use std::path::PathBuf; use deno_media_type::MediaType; use deno_path_util::url_from_file_path; use deno_path_util::url_to_file_path; +use sys_traits::FsMetadata; +use sys_traits::FsMetadataValue; use url::Url; +use crate::sync::MaybeDashMap; + #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum SloppyImportsFsEntry { File, @@ -368,6 +372,50 @@ impl SloppyImportsResolver { } } +#[derive(Debug)] +pub struct SloppyImportsCachedFs { + sys: TSys, + cache: Option>>, +} + +impl SloppyImportsCachedFs { + pub fn new(sys: TSys) -> Self { + Self { + sys, + cache: Some(Default::default()), + } + } + + pub fn new_without_stat_cache(sys: TSys) -> Self { + Self { sys, cache: None } + } +} + +impl SloppyImportResolverFs for SloppyImportsCachedFs { + fn stat_sync(&self, path: &Path) -> Option { + if let Some(cache) = &self.cache { + if let Some(entry) = cache.get(path) { + return *entry; + } + } + + let entry = self.sys.fs_metadata(path).ok().and_then(|stat| { + if stat.file_type().is_file() { + Some(SloppyImportsFsEntry::File) + } else if stat.file_type().is_dir() { + Some(SloppyImportsFsEntry::Dir) + } else { + None + } + }); + + if let Some(cache) = &self.cache { + cache.insert(path.to_owned(), entry); + } + entry + } +} + #[cfg(test)] mod test { use test_util::TestContext; From 475793f94dadbe90495be69bc49173407fe101f7 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Thu, 9 Jan 2025 19:01:47 -0500 Subject: [PATCH 7/7] refactor: implement `NpmPackageFolderResolver` in deno_resolver (#27614) --- Cargo.lock | 4 +- Cargo.toml | 2 +- cli/npm/mod.rs | 2 +- resolvers/deno/npm/byonm.rs | 4 +- resolvers/deno/npm/managed/common.rs | 14 ++---- resolvers/deno/npm/managed/global.rs | 41 +++++++++--------- resolvers/deno/npm/managed/local.rs | 65 ++++++++++++++++------------ resolvers/deno/npm/managed/mod.rs | 2 +- 8 files changed, 69 insertions(+), 65 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d16aafe6f0..71979d448a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7762,9 +7762,9 @@ dependencies = [ [[package]] name = "sys_traits" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c12873696bde6de3aea3cd27de8e52897177c5b368a6a30987fd4926e30f85" +checksum = "5b46ac05dfbe9fd3a9703eff20e17f5b31e7b6a54daf27a421dcd56c7a27ecdd" dependencies = [ "filetime", "getrandom", diff --git a/Cargo.toml b/Cargo.toml index b7c7219fba..48abe48305 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -193,7 +193,7 @@ slab = "0.4" smallvec = "1.8" socket2 = { version = "0.5.3", features = ["all"] } spki = "0.7.2" -sys_traits = "=0.1.6" +sys_traits = "=0.1.7" tar = "=0.4.40" tempfile = "3.4.0" termcolor = "1.1.3" diff --git a/cli/npm/mod.rs b/cli/npm/mod.rs index 9ac478732d..837fe26cf9 100644 --- a/cli/npm/mod.rs +++ b/cli/npm/mod.rs @@ -136,7 +136,7 @@ pub enum InnerCliNpmResolverRef<'a> { Byonm(&'a CliByonmNpmResolver), } -pub trait CliNpmResolver: NpmPackageFolderResolver + CliNpmReqResolver { +pub trait CliNpmResolver: CliNpmReqResolver { fn into_npm_pkg_folder_resolver( self: Arc, ) -> Arc; diff --git a/resolvers/deno/npm/byonm.rs b/resolvers/deno/npm/byonm.rs index e9aad66e3f..710608490a 100644 --- a/resolvers/deno/npm/byonm.rs +++ b/resolvers/deno/npm/byonm.rs @@ -400,14 +400,14 @@ impl< } impl< - Sys: FsCanonicalize + TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir + Send + Sync + std::fmt::Debug, - > NpmPackageFolderResolver for ByonmNpmResolver + > NpmPackageFolderResolver for ByonmNpmResolver { fn resolve_package_folder_from_package( &self, diff --git a/resolvers/deno/npm/managed/common.rs b/resolvers/deno/npm/managed/common.rs index 5a4a517bf0..8a523f3ea4 100644 --- a/resolvers/deno/npm/managed/common.rs +++ b/resolvers/deno/npm/managed/common.rs @@ -3,10 +3,9 @@ use std::path::Path; use std::path::PathBuf; -use async_trait::async_trait; use deno_npm::NpmPackageCacheFolderId; use deno_npm::NpmPackageId; -use node_resolver::errors::PackageFolderResolveError; +use node_resolver::NpmPackageFolderResolver; use url::Url; use crate::sync::MaybeSend; @@ -22,8 +21,9 @@ pub(super) type NpmPackageFsResolverRc = pub struct NpmPackageFsResolverPackageFolderError(deno_semver::StackString); /// Part of the resolution that interacts with the file system. -#[async_trait(?Send)] -pub trait NpmPackageFsResolver: MaybeSend + MaybeSync { +pub trait NpmPackageFsResolver: + NpmPackageFolderResolver + MaybeSend + MaybeSync +{ /// The local node_modules folder if it is applicable to the implementation. fn node_modules_path(&self) -> Option<&Path>; @@ -38,12 +38,6 @@ pub trait NpmPackageFsResolver: MaybeSend + MaybeSync { }) } - fn resolve_package_folder_from_package( - &self, - name: &str, - referrer: &Url, - ) -> Result; - fn resolve_package_cache_folder_id_from_specifier( &self, specifier: &Url, diff --git a/resolvers/deno/npm/managed/global.rs b/resolvers/deno/npm/managed/global.rs index 16a2bc7a70..cffe68a30e 100644 --- a/resolvers/deno/npm/managed/global.rs +++ b/resolvers/deno/npm/managed/global.rs @@ -5,7 +5,6 @@ use std::path::Path; use std::path::PathBuf; -use async_trait::async_trait; use deno_npm::NpmPackageCacheFolderId; use deno_npm::NpmPackageId; use deno_semver::package::PackageNv; @@ -14,6 +13,7 @@ use deno_semver::Version; use node_resolver::errors::PackageFolderResolveError; use node_resolver::errors::PackageNotFoundError; use node_resolver::errors::ReferrerNotFoundError; +use node_resolver::NpmPackageFolderResolver; use url::Url; use super::resolution::NpmResolutionRc; @@ -61,25 +61,7 @@ impl GlobalNpmPackageResolver { } } -#[async_trait(?Send)] -impl NpmPackageFsResolver for GlobalNpmPackageResolver { - fn node_modules_path(&self) -> Option<&Path> { - None - } - - fn maybe_package_folder(&self, id: &NpmPackageId) -> Option { - let folder_copy_index = self - .resolution - .resolve_pkg_cache_folder_copy_index_from_pkg_id(id)?; - let registry_url = self.npm_rc.get_registry_url(&id.nv.name); - Some(self.cache.package_folder_for_id( - &id.nv.name, - &id.nv.version.to_string(), - folder_copy_index, - registry_url, - )) - } - +impl NpmPackageFolderResolver for GlobalNpmPackageResolver { fn resolve_package_folder_from_package( &self, name: &str, @@ -138,6 +120,25 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver { }, } } +} + +impl NpmPackageFsResolver for GlobalNpmPackageResolver { + fn node_modules_path(&self) -> Option<&Path> { + None + } + + fn maybe_package_folder(&self, id: &NpmPackageId) -> Option { + let folder_copy_index = self + .resolution + .resolve_pkg_cache_folder_copy_index_from_pkg_id(id)?; + let registry_url = self.npm_rc.get_registry_url(&id.nv.name); + Some(self.cache.package_folder_for_id( + &id.nv.name, + &id.nv.version.to_string(), + folder_copy_index, + registry_url, + )) + } fn resolve_package_cache_folder_id_from_specifier( &self, diff --git a/resolvers/deno/npm/managed/local.rs b/resolvers/deno/npm/managed/local.rs index e84de964ad..f23f7bd591 100644 --- a/resolvers/deno/npm/managed/local.rs +++ b/resolvers/deno/npm/managed/local.rs @@ -6,7 +6,6 @@ use std::borrow::Cow; use std::path::Path; use std::path::PathBuf; -use async_trait::async_trait; use deno_npm::NpmPackageCacheFolderId; use deno_npm::NpmPackageId; use deno_path_util::fs::canonicalize_path_maybe_not_exists; @@ -15,6 +14,7 @@ use node_resolver::errors::PackageFolderResolveError; use node_resolver::errors::PackageFolderResolveIoError; use node_resolver::errors::PackageNotFoundError; use node_resolver::errors::ReferrerNotFoundError; +use node_resolver::NpmPackageFolderResolver; use sys_traits::FsCanonicalize; use sys_traits::FsMetadata; use url::Url; @@ -99,33 +99,9 @@ impl } } -#[async_trait(?Send)] -impl NpmPackageFsResolver - for LocalNpmPackageResolver +impl + NpmPackageFolderResolver for LocalNpmPackageResolver { - fn node_modules_path(&self) -> Option<&Path> { - Some(self.root_node_modules_path.as_ref()) - } - - fn maybe_package_folder(&self, id: &NpmPackageId) -> Option { - let folder_copy_index = self - .resolution - .resolve_pkg_cache_folder_copy_index_from_pkg_id(id)?; - // package is stored at: - // node_modules/.deno//node_modules/ - Some( - self - .root_node_modules_path - .join(".deno") - .join(get_package_folder_id_folder_name_from_parts( - &id.nv, - folder_copy_index, - )) - .join("node_modules") - .join(&id.nv.name), - ) - } - fn resolve_package_folder_from_package( &self, name: &str, @@ -159,7 +135,13 @@ impl NpmPackageFsResolver let sub_dir = join_package_name(&node_modules_folder, name); if self.sys.fs_is_dir_no_err(&sub_dir) { - return Ok(sub_dir); + return Ok(self.sys.fs_canonicalize(&sub_dir).map_err(|err| { + PackageFolderResolveIoError { + package_name: name.to_string(), + referrer: referrer.clone(), + source: err, + } + })?); } if current_folder == self.root_node_modules_path { @@ -176,6 +158,33 @@ impl NpmPackageFsResolver .into(), ) } +} + +impl + NpmPackageFsResolver for LocalNpmPackageResolver +{ + fn node_modules_path(&self) -> Option<&Path> { + Some(self.root_node_modules_path.as_ref()) + } + + fn maybe_package_folder(&self, id: &NpmPackageId) -> Option { + let folder_copy_index = self + .resolution + .resolve_pkg_cache_folder_copy_index_from_pkg_id(id)?; + // package is stored at: + // node_modules/.deno//node_modules/ + Some( + self + .root_node_modules_path + .join(".deno") + .join(get_package_folder_id_folder_name_from_parts( + &id.nv, + folder_copy_index, + )) + .join("node_modules") + .join(&id.nv.name), + ) + } fn resolve_package_cache_folder_id_from_specifier( &self, diff --git a/resolvers/deno/npm/managed/mod.rs b/resolvers/deno/npm/managed/mod.rs index 53b07f7d90..d08ee07d6a 100644 --- a/resolvers/deno/npm/managed/mod.rs +++ b/resolvers/deno/npm/managed/mod.rs @@ -25,7 +25,7 @@ use crate::NpmCacheDirRc; use crate::ResolvedNpmRcRc; pub fn create_npm_fs_resolver< - TSys: FsCanonicalize + FsMetadata + Send + Sync + 'static, + TSys: FsCanonicalize + FsMetadata + std::fmt::Debug + Send + Sync + 'static, >( npm_cache_dir: &NpmCacheDirRc, npm_rc: &ResolvedNpmRcRc,