mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 17:34:47 -05:00
perf: node resolution cache (#27838)
This adds a cache for node resolution, which makes repeat lookups about 15x faster.
This commit is contained in:
parent
073caf5fe9
commit
61faa32920
11 changed files with 261 additions and 29 deletions
|
@ -48,6 +48,7 @@ use deno_runtime::deno_web::BlobStore;
|
|||
use deno_runtime::inspector_server::InspectorServer;
|
||||
use deno_runtime::permissions::RuntimePermissionDescriptorParser;
|
||||
use node_resolver::analyze::NodeCodeTranslator;
|
||||
use node_resolver::cache::NodeResolutionThreadLocalCache;
|
||||
use once_cell::sync::OnceCell;
|
||||
use sys_traits::EnvCurrentDir;
|
||||
|
||||
|
@ -644,6 +645,7 @@ impl CliFactory {
|
|||
self.workspace_factory()?.clone(),
|
||||
ResolverFactoryOptions {
|
||||
conditions_from_resolution_mode: Default::default(),
|
||||
node_resolution_cache: Some(Arc::new(NodeResolutionThreadLocalCache)),
|
||||
no_sloppy_imports_cache: false,
|
||||
npm_system_info: self.flags.subcommand.npm_system_info(),
|
||||
specified_import_map: Some(Box::new(CliSpecifiedImportMapProvider {
|
||||
|
|
|
@ -33,6 +33,7 @@ use deno_semver::npm::NpmPackageReqReference;
|
|||
use deno_semver::package::PackageReq;
|
||||
use indexmap::IndexMap;
|
||||
use indexmap::IndexSet;
|
||||
use node_resolver::cache::NodeResolutionThreadLocalCache;
|
||||
use node_resolver::NodeResolutionKind;
|
||||
use node_resolver::ResolutionMode;
|
||||
use tower_lsp::lsp_types as lsp;
|
||||
|
@ -897,6 +898,7 @@ impl FileSystemDocuments {
|
|||
}
|
||||
};
|
||||
if dirty {
|
||||
NodeResolutionThreadLocalCache::clear();
|
||||
// attempt to update the file on the file system
|
||||
self.refresh_document(specifier, resolver, config, cache, file_referrer)
|
||||
} else {
|
||||
|
@ -1375,6 +1377,7 @@ impl Documents {
|
|||
self.resolver = resolver.clone();
|
||||
|
||||
node_resolver::PackageJsonThreadLocalCache::clear();
|
||||
NodeResolutionThreadLocalCache::clear();
|
||||
|
||||
{
|
||||
let fs_docs = &self.file_system_docs;
|
||||
|
@ -1440,6 +1443,7 @@ impl Documents {
|
|||
if !is_fs_docs_dirty && !self.dirty {
|
||||
return;
|
||||
}
|
||||
NodeResolutionThreadLocalCache::clear();
|
||||
let mut visit_doc = |doc: &Arc<Document>| {
|
||||
let scope = doc.scope();
|
||||
let dep_info = dep_info_by_scope.entry(scope.cloned()).or_default();
|
||||
|
|
|
@ -36,6 +36,8 @@ use deno_semver::npm::NpmPackageReqReference;
|
|||
use deno_semver::package::PackageNv;
|
||||
use deno_semver::package::PackageReq;
|
||||
use indexmap::IndexMap;
|
||||
use node_resolver::cache::NodeResolutionSys;
|
||||
use node_resolver::cache::NodeResolutionThreadLocalCache;
|
||||
use node_resolver::DenoIsBuiltInNodeModuleChecker;
|
||||
use node_resolver::NodeResolutionKind;
|
||||
use node_resolver::PackageJsonThreadLocalCache;
|
||||
|
@ -259,7 +261,7 @@ impl LspScopeResolver {
|
|||
root_node_modules_dir: byonm_npm_resolver
|
||||
.root_node_modules_path()
|
||||
.map(|p| p.to_path_buf()),
|
||||
sys: factory.sys.clone(),
|
||||
sys: factory.node_resolution_sys.clone(),
|
||||
pkg_json_resolver: self.pkg_json_resolver.clone(),
|
||||
},
|
||||
)
|
||||
|
@ -673,6 +675,7 @@ struct ResolverFactoryServices {
|
|||
struct ResolverFactory<'a> {
|
||||
config_data: Option<&'a Arc<ConfigData>>,
|
||||
pkg_json_resolver: Arc<CliPackageJsonResolver>,
|
||||
node_resolution_sys: NodeResolutionSys<CliSys>,
|
||||
sys: CliSys,
|
||||
services: ResolverFactoryServices,
|
||||
}
|
||||
|
@ -688,6 +691,10 @@ impl<'a> ResolverFactory<'a> {
|
|||
Self {
|
||||
config_data,
|
||||
pkg_json_resolver,
|
||||
node_resolution_sys: NodeResolutionSys::new(
|
||||
sys.clone(),
|
||||
Some(Arc::new(NodeResolutionThreadLocalCache)),
|
||||
),
|
||||
sys,
|
||||
services: Default::default(),
|
||||
}
|
||||
|
@ -706,7 +713,7 @@ impl<'a> ResolverFactory<'a> {
|
|||
let sys = CliSys::default();
|
||||
let options = if enable_byonm {
|
||||
CliNpmResolverCreateOptions::Byonm(CliByonmNpmResolverCreateOptions {
|
||||
sys: self.sys.clone(),
|
||||
sys: self.node_resolution_sys.clone(),
|
||||
pkg_json_resolver: self.pkg_json_resolver.clone(),
|
||||
root_node_modules_dir: self.config_data.and_then(|config_data| {
|
||||
config_data.node_modules_dir.clone().or_else(|| {
|
||||
|
@ -933,7 +940,7 @@ impl<'a> ResolverFactory<'a> {
|
|||
DenoIsBuiltInNodeModuleChecker,
|
||||
npm_resolver.clone(),
|
||||
self.pkg_json_resolver.clone(),
|
||||
self.sys.clone(),
|
||||
self.node_resolution_sys.clone(),
|
||||
node_resolver::ConditionsFromResolutionMode::default(),
|
||||
)))
|
||||
})
|
||||
|
|
|
@ -49,6 +49,7 @@ use indexmap::IndexMap;
|
|||
use indexmap::IndexSet;
|
||||
use lazy_regex::lazy_regex;
|
||||
use log::error;
|
||||
use node_resolver::cache::NodeResolutionThreadLocalCache;
|
||||
use node_resolver::ResolutionMode;
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Captures;
|
||||
|
@ -4600,6 +4601,9 @@ async fn op_poll_requests(
|
|||
state.pending_requests.take().unwrap()
|
||||
};
|
||||
|
||||
// clear the resolution cache after each request
|
||||
NodeResolutionThreadLocalCache::clear();
|
||||
|
||||
let Some((request, scope, snapshot, response_tx, token, change)) =
|
||||
pending_requests.recv().await
|
||||
else {
|
||||
|
|
|
@ -76,6 +76,7 @@ use deno_runtime::WorkerExecutionMode;
|
|||
use deno_runtime::WorkerLogLevel;
|
||||
use deno_semver::npm::NpmPackageReqReference;
|
||||
use node_resolver::analyze::NodeCodeTranslator;
|
||||
use node_resolver::cache::NodeResolutionSys;
|
||||
use node_resolver::errors::ClosestPkgJsonError;
|
||||
use node_resolver::DenoIsBuiltInNodeModuleChecker;
|
||||
use node_resolver::NodeResolutionKind;
|
||||
|
@ -707,6 +708,7 @@ pub async fn run(
|
|||
};
|
||||
NpmRegistryReadPermissionChecker::new(sys.clone(), mode)
|
||||
};
|
||||
let node_resolution_sys = NodeResolutionSys::new(sys.clone(), None);
|
||||
let (in_npm_pkg_checker, npm_resolver) = match metadata.node_modules {
|
||||
Some(NodeModules::Managed { node_modules_dir }) => {
|
||||
// create an npmrc that uses the fake npm_registry_url to resolve packages
|
||||
|
@ -756,7 +758,7 @@ pub async fn run(
|
|||
DenoInNpmPackageChecker::new(CreateInNpmPkgCheckerOptions::Byonm);
|
||||
let npm_resolver = NpmResolver::<DenoRtSys>::new::<DenoRtSys>(
|
||||
NpmResolverCreateOptions::Byonm(ByonmNpmResolverCreateOptions {
|
||||
sys: sys.clone(),
|
||||
sys: node_resolution_sys.clone(),
|
||||
pkg_json_resolver: pkg_json_resolver.clone(),
|
||||
root_node_modules_dir,
|
||||
}),
|
||||
|
@ -800,7 +802,7 @@ pub async fn run(
|
|||
DenoIsBuiltInNodeModuleChecker,
|
||||
npm_resolver.clone(),
|
||||
pkg_json_resolver.clone(),
|
||||
sys.clone(),
|
||||
node_resolution_sys,
|
||||
node_resolver::ConditionsFromResolutionMode::default(),
|
||||
));
|
||||
let cjs_tracker = Arc::new(CjsTracker::new(
|
||||
|
|
|
@ -18,6 +18,7 @@ use deno_package_json::PackageJsonRc;
|
|||
use deno_path_util::normalize_path;
|
||||
use deno_path_util::url_from_file_path;
|
||||
use deno_path_util::url_to_file_path;
|
||||
use node_resolver::cache::NodeResolutionThreadLocalCache;
|
||||
use node_resolver::errors::ClosestPkgJsonError;
|
||||
use node_resolver::InNpmPackageChecker;
|
||||
use node_resolver::NodeResolutionKind;
|
||||
|
@ -523,6 +524,8 @@ pub fn op_require_try_self<
|
|||
TSys,
|
||||
>>();
|
||||
let referrer = UrlOrPathRef::from_path(&pkg.path);
|
||||
// invalidate the resolution cache in case things have changed
|
||||
NodeResolutionThreadLocalCache::clear();
|
||||
let r = node_resolver.package_exports_resolve(
|
||||
&pkg.path,
|
||||
&expansion,
|
||||
|
@ -626,6 +629,7 @@ pub fn op_require_resolve_exports<
|
|||
} else {
|
||||
Some(PathBuf::from(parent_path))
|
||||
};
|
||||
NodeResolutionThreadLocalCache::clear();
|
||||
let r = node_resolver.package_exports_resolve(
|
||||
&pkg.path,
|
||||
&format!(".{expansion}"),
|
||||
|
@ -708,6 +712,7 @@ pub fn op_require_package_imports_resolve<
|
|||
TNpmPackageFolderResolver,
|
||||
TSys,
|
||||
>>();
|
||||
NodeResolutionThreadLocalCache::clear();
|
||||
let url = node_resolver.package_imports_resolve(
|
||||
&request,
|
||||
Some(&UrlOrPathRef::from_path(&referrer_path)),
|
||||
|
|
|
@ -23,6 +23,7 @@ use deno_npm::NpmSystemInfo;
|
|||
use deno_path_util::fs::canonicalize_path_maybe_not_exists;
|
||||
use deno_path_util::normalize_path;
|
||||
use futures::future::FutureExt;
|
||||
use node_resolver::cache::NodeResolutionSys;
|
||||
use node_resolver::ConditionsFromResolutionMode;
|
||||
use node_resolver::DenoIsBuiltInNodeModuleChecker;
|
||||
use node_resolver::NodeResolver;
|
||||
|
@ -561,6 +562,7 @@ pub struct ResolverFactoryOptions {
|
|||
pub conditions_from_resolution_mode: ConditionsFromResolutionMode,
|
||||
pub no_sloppy_imports_cache: bool,
|
||||
pub npm_system_info: NpmSystemInfo,
|
||||
pub node_resolution_cache: Option<node_resolver::NodeResolutionCacheRc>,
|
||||
pub package_json_cache: Option<node_resolver::PackageJsonCacheRc>,
|
||||
pub package_json_dep_resolution: Option<PackageJsonDepResolution>,
|
||||
pub specified_import_map: Option<Box<dyn SpecifiedImportMapProvider>>,
|
||||
|
@ -569,6 +571,7 @@ pub struct ResolverFactoryOptions {
|
|||
|
||||
pub struct ResolverFactory<TSys: WorkspaceFactorySys> {
|
||||
options: ResolverFactoryOptions,
|
||||
sys: NodeResolutionSys<TSys>,
|
||||
deno_resolver: async_once_cell::OnceCell<DefaultDenoResolverRc<TSys>>,
|
||||
in_npm_package_checker: Deferred<DenoInNpmPackageChecker>,
|
||||
node_resolver: Deferred<
|
||||
|
@ -602,6 +605,10 @@ impl<TSys: WorkspaceFactorySys> ResolverFactory<TSys> {
|
|||
options: ResolverFactoryOptions,
|
||||
) -> Self {
|
||||
Self {
|
||||
sys: NodeResolutionSys::new(
|
||||
workspace_factory.sys.clone(),
|
||||
options.node_resolution_cache.clone(),
|
||||
),
|
||||
deno_resolver: Default::default(),
|
||||
in_npm_package_checker: Default::default(),
|
||||
node_resolver: Default::default(),
|
||||
|
@ -688,7 +695,7 @@ impl<TSys: WorkspaceFactorySys> ResolverFactory<TSys> {
|
|||
DenoIsBuiltInNodeModuleChecker,
|
||||
self.npm_resolver()?.clone(),
|
||||
self.pkg_json_resolver().clone(),
|
||||
self.workspace_factory.sys.clone(),
|
||||
self.sys.clone(),
|
||||
self.options.conditions_from_resolution_mode.clone(),
|
||||
)))
|
||||
})
|
||||
|
@ -723,7 +730,7 @@ impl<TSys: WorkspaceFactorySys> ResolverFactory<TSys> {
|
|||
self.npm_resolver.get_or_try_init(|| {
|
||||
Ok(NpmResolver::<TSys>::new::<TSys>(if self.use_byonm()? {
|
||||
NpmResolverCreateOptions::Byonm(ByonmNpmResolverCreateOptions {
|
||||
sys: self.workspace_factory.sys.clone(),
|
||||
sys: self.sys.clone(),
|
||||
pkg_json_resolver: self.pkg_json_resolver().clone(),
|
||||
root_node_modules_dir: Some(
|
||||
match self.workspace_factory.node_modules_dir_path()? {
|
||||
|
|
|
@ -11,6 +11,7 @@ use deno_path_util::url_to_file_path;
|
|||
use deno_semver::package::PackageReq;
|
||||
use deno_semver::StackString;
|
||||
use deno_semver::Version;
|
||||
use node_resolver::cache::NodeResolutionSys;
|
||||
use node_resolver::errors::PackageFolderResolveError;
|
||||
use node_resolver::errors::PackageFolderResolveIoError;
|
||||
use node_resolver::errors::PackageJsonLoadError;
|
||||
|
@ -48,7 +49,7 @@ pub enum ByonmResolvePkgFolderFromDenoReqError {
|
|||
pub struct ByonmNpmResolverCreateOptions<TSys: FsRead> {
|
||||
// todo(dsherret): investigate removing this
|
||||
pub root_node_modules_dir: Option<PathBuf>,
|
||||
pub sys: TSys,
|
||||
pub sys: NodeResolutionSys<TSys>,
|
||||
pub pkg_json_resolver: PackageJsonResolverRc<TSys>,
|
||||
}
|
||||
|
||||
|
@ -60,7 +61,7 @@ pub type ByonmNpmResolverRc<TSys> =
|
|||
pub struct ByonmNpmResolver<
|
||||
TSys: FsCanonicalize + FsRead + FsMetadata + FsReadDir,
|
||||
> {
|
||||
sys: TSys,
|
||||
sys: NodeResolutionSys<TSys>,
|
||||
pkg_json_resolver: PackageJsonResolverRc<TSys>,
|
||||
root_node_modules_dir: Option<PathBuf>,
|
||||
}
|
||||
|
@ -136,14 +137,14 @@ impl<TSys: FsCanonicalize + FsRead + FsMetadata + FsReadDir>
|
|||
referrer: &Url,
|
||||
) -> Result<PathBuf, ByonmResolvePkgFolderFromDenoReqError> {
|
||||
fn node_resolve_dir<TSys: FsCanonicalize + FsMetadata>(
|
||||
sys: &TSys,
|
||||
sys: &NodeResolutionSys<TSys>,
|
||||
alias: &str,
|
||||
start_dir: &Path,
|
||||
) -> std::io::Result<Option<PathBuf>> {
|
||||
for ancestor in start_dir.ancestors() {
|
||||
let node_modules_folder = ancestor.join("node_modules");
|
||||
let sub_dir = join_package_name(Cow::Owned(node_modules_folder), alias);
|
||||
if sys.fs_is_dir_no_err(&sub_dir) {
|
||||
if sys.is_dir(&sub_dir) {
|
||||
return Ok(Some(
|
||||
deno_path_util::fs::canonicalize_path_maybe_not_exists(
|
||||
sys, &sub_dir,
|
||||
|
@ -385,7 +386,7 @@ impl<TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir>
|
|||
referrer: &UrlOrPathRef,
|
||||
) -> Result<PathBuf, PackageFolderResolveError> {
|
||||
fn inner<TSys: FsMetadata>(
|
||||
sys: &TSys,
|
||||
sys: &NodeResolutionSys<TSys>,
|
||||
name: &str,
|
||||
referrer: &UrlOrPathRef,
|
||||
) -> Result<PathBuf, PackageFolderResolveError> {
|
||||
|
@ -402,7 +403,7 @@ impl<TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir>
|
|||
};
|
||||
|
||||
let sub_dir = join_package_name(node_modules_folder, name);
|
||||
if sys.fs_is_dir_no_err(&sub_dir) {
|
||||
if sys.is_dir(&sub_dir) {
|
||||
return Ok(sub_dir);
|
||||
}
|
||||
}
|
||||
|
|
197
resolvers/node/cache.rs
Normal file
197
resolvers/node/cache.rs
Normal file
|
@ -0,0 +1,197 @@
|
|||
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use sys_traits::BaseFsCanonicalize;
|
||||
use sys_traits::BaseFsRead;
|
||||
use sys_traits::BaseFsReadDir;
|
||||
use sys_traits::FileType;
|
||||
use sys_traits::FsCanonicalize;
|
||||
use sys_traits::FsMetadata;
|
||||
use sys_traits::FsMetadataValue;
|
||||
use sys_traits::FsRead;
|
||||
use sys_traits::FsReadDir;
|
||||
|
||||
pub trait NodeResolutionCache:
|
||||
std::fmt::Debug + crate::sync::MaybeSend + crate::sync::MaybeSync
|
||||
{
|
||||
fn get_canonicalized(
|
||||
&self,
|
||||
path: &Path,
|
||||
) -> Option<Result<PathBuf, std::io::Error>>;
|
||||
fn set_canonicalized(&self, from: PathBuf, to: &std::io::Result<PathBuf>);
|
||||
fn get_file_type(&self, path: &Path) -> Option<Option<FileType>>;
|
||||
fn set_file_type(&self, path: PathBuf, value: Option<FileType>);
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
static CANONICALIZED_CACHE: RefCell<HashMap<PathBuf, Option<PathBuf>>> = RefCell::new(HashMap::new());
|
||||
static FILE_TYPE_CACHE: RefCell<HashMap<PathBuf, Option<FileType>>> = RefCell::new(HashMap::new());
|
||||
}
|
||||
|
||||
// We use thread local caches here because it's just more convenient
|
||||
// and easily allows workers to have separate caches.
|
||||
#[derive(Debug)]
|
||||
pub struct NodeResolutionThreadLocalCache;
|
||||
|
||||
impl NodeResolutionThreadLocalCache {
|
||||
pub fn clear() {
|
||||
CANONICALIZED_CACHE.with_borrow_mut(|cache| cache.clear());
|
||||
FILE_TYPE_CACHE.with_borrow_mut(|cache| cache.clear());
|
||||
}
|
||||
}
|
||||
|
||||
impl NodeResolutionCache for NodeResolutionThreadLocalCache {
|
||||
fn get_canonicalized(
|
||||
&self,
|
||||
path: &Path,
|
||||
) -> Option<Result<PathBuf, std::io::Error>> {
|
||||
CANONICALIZED_CACHE.with_borrow(|cache| {
|
||||
let item = cache.get(path)?;
|
||||
Some(match item {
|
||||
Some(value) => Ok(value.clone()),
|
||||
None => Err(std::io::Error::new(
|
||||
std::io::ErrorKind::NotFound,
|
||||
"Not found.",
|
||||
)),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn set_canonicalized(&self, from: PathBuf, to: &std::io::Result<PathBuf>) {
|
||||
CANONICALIZED_CACHE.with_borrow_mut(|cache| match to {
|
||||
Ok(to) => {
|
||||
cache.insert(from, Some(to.clone()));
|
||||
}
|
||||
Err(err) => {
|
||||
if err.kind() == std::io::ErrorKind::NotFound {
|
||||
cache.insert(from, None);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn get_file_type(&self, path: &Path) -> Option<Option<FileType>> {
|
||||
FILE_TYPE_CACHE.with_borrow(|cache| cache.get(path).cloned())
|
||||
}
|
||||
|
||||
fn set_file_type(&self, path: PathBuf, value: Option<FileType>) {
|
||||
FILE_TYPE_CACHE.with_borrow_mut(|cache| {
|
||||
cache.insert(path, value);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::disallowed_types)]
|
||||
pub type NodeResolutionCacheRc = crate::sync::MaybeArc<dyn NodeResolutionCache>;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct NodeResolutionSys<TSys> {
|
||||
sys: TSys,
|
||||
cache: Option<NodeResolutionCacheRc>,
|
||||
}
|
||||
|
||||
impl<TSys: Clone> Clone for NodeResolutionSys<TSys> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
sys: self.sys.clone(),
|
||||
cache: self.cache.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<TSys: FsMetadata> NodeResolutionSys<TSys> {
|
||||
pub fn new(sys: TSys, store: Option<NodeResolutionCacheRc>) -> Self {
|
||||
Self { sys, cache: store }
|
||||
}
|
||||
|
||||
pub fn is_file(&self, path: &Path) -> bool {
|
||||
match self.get_file_type(path) {
|
||||
Ok(file_type) => file_type.is_file(),
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_dir(&self, path: &Path) -> bool {
|
||||
match self.get_file_type(path) {
|
||||
Ok(file_type) => file_type.is_dir(),
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exists_(&self, path: &Path) -> bool {
|
||||
self.get_file_type(path).is_ok()
|
||||
}
|
||||
|
||||
pub fn get_file_type(&self, path: &Path) -> std::io::Result<FileType> {
|
||||
{
|
||||
if let Some(maybe_value) =
|
||||
self.cache.as_ref().and_then(|c| c.get_file_type(path))
|
||||
{
|
||||
return match maybe_value {
|
||||
Some(value) => Ok(value),
|
||||
None => Err(std::io::Error::new(
|
||||
std::io::ErrorKind::NotFound,
|
||||
"Not found.",
|
||||
)),
|
||||
};
|
||||
}
|
||||
}
|
||||
match self.sys.fs_metadata(path) {
|
||||
Ok(metadata) => {
|
||||
if let Some(cache) = &self.cache {
|
||||
cache.set_file_type(path.to_path_buf(), Some(metadata.file_type()));
|
||||
}
|
||||
Ok(metadata.file_type())
|
||||
}
|
||||
Err(err) => {
|
||||
if let Some(cache) = &self.cache {
|
||||
cache.set_file_type(path.to_path_buf(), None);
|
||||
}
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<TSys: FsCanonicalize> BaseFsCanonicalize for NodeResolutionSys<TSys> {
|
||||
fn base_fs_canonicalize(&self, from: &Path) -> std::io::Result<PathBuf> {
|
||||
if let Some(cache) = &self.cache {
|
||||
if let Some(result) = cache.get_canonicalized(from) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
let result = self.sys.base_fs_canonicalize(from);
|
||||
if let Some(cache) = &self.cache {
|
||||
cache.set_canonicalized(from.to_path_buf(), &result);
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl<TSys: FsReadDir> BaseFsReadDir for NodeResolutionSys<TSys> {
|
||||
type ReadDirEntry = TSys::ReadDirEntry;
|
||||
|
||||
#[inline(always)]
|
||||
fn base_fs_read_dir(
|
||||
&self,
|
||||
path: &Path,
|
||||
) -> std::io::Result<
|
||||
Box<dyn Iterator<Item = std::io::Result<Self::ReadDirEntry>> + '_>,
|
||||
> {
|
||||
self.sys.base_fs_read_dir(path)
|
||||
}
|
||||
}
|
||||
|
||||
impl<TSys: FsRead> BaseFsRead for NodeResolutionSys<TSys> {
|
||||
#[inline(always)]
|
||||
fn base_fs_read(
|
||||
&self,
|
||||
path: &Path,
|
||||
) -> std::io::Result<std::borrow::Cow<'static, [u8]>> {
|
||||
self.sys.base_fs_read(path)
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
pub mod analyze;
|
||||
mod builtin_modules;
|
||||
pub mod cache;
|
||||
pub mod errors;
|
||||
mod npm;
|
||||
mod package_json;
|
||||
|
@ -16,6 +17,8 @@ mod sync;
|
|||
pub use builtin_modules::DenoIsBuiltInNodeModuleChecker;
|
||||
pub use builtin_modules::IsBuiltInNodeModuleChecker;
|
||||
pub use builtin_modules::DENO_SUPPORTED_BUILTIN_NODE_MODULES;
|
||||
pub use cache::NodeResolutionCache;
|
||||
pub use cache::NodeResolutionCacheRc;
|
||||
pub use deno_package_json::PackageJson;
|
||||
pub use npm::InNpmPackageChecker;
|
||||
pub use npm::NpmPackageFolderResolver;
|
||||
|
|
|
@ -15,10 +15,10 @@ use serde_json::Value;
|
|||
use sys_traits::FileType;
|
||||
use sys_traits::FsCanonicalize;
|
||||
use sys_traits::FsMetadata;
|
||||
use sys_traits::FsMetadataValue;
|
||||
use sys_traits::FsRead;
|
||||
use url::Url;
|
||||
|
||||
use crate::cache::NodeResolutionSys;
|
||||
use crate::errors;
|
||||
use crate::errors::DataUrlReferrerError;
|
||||
use crate::errors::FinalizeResolutionError;
|
||||
|
@ -203,7 +203,7 @@ pub struct NodeResolver<
|
|||
is_built_in_node_module_checker: TIsBuiltInNodeModuleChecker,
|
||||
npm_pkg_folder_resolver: TNpmPackageFolderResolver,
|
||||
pkg_json_resolver: PackageJsonResolverRc<TSys>,
|
||||
sys: TSys,
|
||||
sys: NodeResolutionSys<TSys>,
|
||||
conditions_from_resolution_mode: ConditionsFromResolutionMode,
|
||||
}
|
||||
|
||||
|
@ -225,7 +225,7 @@ impl<
|
|||
is_built_in_node_module_checker: TIsBuiltInNodeModuleChecker,
|
||||
npm_pkg_folder_resolver: TNpmPackageFolderResolver,
|
||||
pkg_json_resolver: PackageJsonResolverRc<TSys>,
|
||||
sys: TSys,
|
||||
sys: NodeResolutionSys<TSys>,
|
||||
conditions_from_resolution_mode: ConditionsFromResolutionMode,
|
||||
) -> Self {
|
||||
Self {
|
||||
|
@ -434,12 +434,12 @@ impl<
|
|||
path
|
||||
};
|
||||
|
||||
let maybe_file_type = self.sys.fs_metadata(&path).map(|m| m.file_type());
|
||||
let maybe_file_type = self.sys.get_file_type(&path);
|
||||
match maybe_file_type {
|
||||
Ok(FileType::Dir) => {
|
||||
let suggested_file_name = ["index.mjs", "index.js", "index.cjs"]
|
||||
.into_iter()
|
||||
.find(|e| self.sys.fs_is_file_no_err(path.join(e)));
|
||||
.find(|e| self.sys.is_file(&path.join(e)));
|
||||
Err(
|
||||
UnsupportedDirImportError {
|
||||
dir_url: UrlOrPath::Path(path),
|
||||
|
@ -492,7 +492,7 @@ impl<
|
|||
if should_probe(path, resolved_method) {
|
||||
["js", "mjs", "cjs"]
|
||||
.into_iter()
|
||||
.find(|ext| self.sys.fs_is_file_no_err(with_known_extension(path, ext)))
|
||||
.find(|ext| self.sys.is_file(&with_known_extension(path, ext)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -638,7 +638,7 @@ impl<
|
|||
conditions: &[&str],
|
||||
) -> Result<MaybeTypesResolvedUrl, TypesNotFoundError> {
|
||||
fn probe_extensions<TSys: FsMetadata>(
|
||||
sys: &TSys,
|
||||
sys: &NodeResolutionSys<TSys>,
|
||||
path: &Path,
|
||||
media_type: MediaType,
|
||||
resolution_mode: ResolutionMode,
|
||||
|
@ -647,20 +647,20 @@ impl<
|
|||
let mut searched_for_d_cts = false;
|
||||
if media_type == MediaType::Mjs {
|
||||
let d_mts_path = with_known_extension(path, "d.mts");
|
||||
if sys.fs_is_file_no_err(&d_mts_path) {
|
||||
if sys.exists_(&d_mts_path) {
|
||||
return Some(d_mts_path);
|
||||
}
|
||||
searched_for_d_mts = true;
|
||||
} else if media_type == MediaType::Cjs {
|
||||
let d_cts_path = with_known_extension(path, "d.cts");
|
||||
if sys.fs_is_file_no_err(&d_cts_path) {
|
||||
if sys.exists_(&d_cts_path) {
|
||||
return Some(d_cts_path);
|
||||
}
|
||||
searched_for_d_cts = true;
|
||||
}
|
||||
|
||||
let dts_path = with_known_extension(path, "d.ts");
|
||||
if sys.fs_is_file_no_err(&dts_path) {
|
||||
if sys.exists_(&dts_path) {
|
||||
return Some(dts_path);
|
||||
}
|
||||
|
||||
|
@ -674,12 +674,12 @@ impl<
|
|||
_ => None, // already searched above
|
||||
};
|
||||
if let Some(specific_dts_path) = specific_dts_path {
|
||||
if sys.fs_is_file_no_err(&specific_dts_path) {
|
||||
if sys.exists_(&specific_dts_path) {
|
||||
return Some(specific_dts_path);
|
||||
}
|
||||
}
|
||||
let ts_path = with_known_extension(path, "ts");
|
||||
if sys.fs_is_file_no_err(&ts_path) {
|
||||
if sys.is_file(&ts_path) {
|
||||
return Some(ts_path);
|
||||
}
|
||||
None
|
||||
|
@ -697,7 +697,7 @@ impl<
|
|||
known_exists: true,
|
||||
})));
|
||||
}
|
||||
if self.sys.fs_is_dir_no_err(&local_path.path) {
|
||||
if self.sys.is_dir(&local_path.path) {
|
||||
let resolution_result = self.resolve_package_dir_subpath(
|
||||
&local_path.path,
|
||||
/* sub path */ ".",
|
||||
|
@ -1677,7 +1677,7 @@ impl<
|
|||
|
||||
if let Some(main) = maybe_main {
|
||||
let guess = package_json.path.parent().unwrap().join(main).clean();
|
||||
if self.sys.fs_is_file_no_err(&guess) {
|
||||
if self.sys.is_file(&guess) {
|
||||
return Ok(self.maybe_resolve_types(
|
||||
LocalUrlOrPath::Path(LocalPath {
|
||||
path: guess,
|
||||
|
@ -1715,7 +1715,7 @@ impl<
|
|||
.unwrap()
|
||||
.join(format!("{main}{ending}"))
|
||||
.clean();
|
||||
if self.sys.fs_is_file_no_err(&guess) {
|
||||
if self.sys.is_file(&guess) {
|
||||
// TODO(bartlomieju): emitLegacyIndexDeprecation()
|
||||
return Ok(MaybeTypesResolvedUrl(LocalUrlOrPath::Path(LocalPath {
|
||||
path: guess,
|
||||
|
@ -1753,7 +1753,7 @@ impl<
|
|||
};
|
||||
for index_file_name in index_file_names {
|
||||
let guess = directory.join(index_file_name).clean();
|
||||
if self.sys.fs_is_file_no_err(&guess) {
|
||||
if self.sys.is_file(&guess) {
|
||||
// TODO(bartlomieju): emitLegacyIndexDeprecation()
|
||||
return Ok(MaybeTypesResolvedUrl(LocalUrlOrPath::Path(LocalPath {
|
||||
path: guess,
|
||||
|
|
Loading…
Add table
Reference in a new issue