2024-01-01 14:58:21 -05:00
|
|
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
2021-10-10 17:26:22 -04:00
|
|
|
|
2024-09-25 21:50:54 -04:00
|
|
|
use crate::args::jsr_url;
|
2023-09-07 09:09:16 -04:00
|
|
|
use crate::args::CacheSetting;
|
2021-12-22 08:25:06 -05:00
|
|
|
use crate::errors::get_error_class_name;
|
2024-04-18 21:43:28 -04:00
|
|
|
use crate::file_fetcher::FetchNoFollowOptions;
|
2023-09-07 09:09:16 -04:00
|
|
|
use crate::file_fetcher::FetchOptions;
|
2024-09-25 21:50:54 -04:00
|
|
|
use crate::file_fetcher::FetchPermissionsOptionRef;
|
2021-10-10 17:26:22 -04:00
|
|
|
use crate::file_fetcher::FileFetcher;
|
2024-04-18 21:43:28 -04:00
|
|
|
use crate::file_fetcher::FileOrRedirect;
|
2023-10-25 14:39:00 -04:00
|
|
|
use crate::npm::CliNpmResolver;
|
2024-10-14 20:48:39 -04:00
|
|
|
use crate::resolver::CliNodeResolver;
|
2024-06-07 13:06:17 -04:00
|
|
|
use crate::util::fs::atomic_write_file_with_retries;
|
2024-09-28 08:50:16 -04:00
|
|
|
use crate::util::fs::atomic_write_file_with_retries_and_fs;
|
|
|
|
use crate::util::fs::AtomicWriteFileFsAdapter;
|
2024-09-05 10:22:13 -04:00
|
|
|
use crate::util::path::specifier_has_extension;
|
2024-10-14 20:48:39 -04:00
|
|
|
use crate::util::text_encoding::arc_str_to_bytes;
|
|
|
|
use crate::util::text_encoding::from_utf8_lossy_owned;
|
2021-10-10 17:26:22 -04:00
|
|
|
|
2023-09-07 09:09:16 -04:00
|
|
|
use deno_ast::MediaType;
|
2023-02-22 17:21:05 -05:00
|
|
|
use deno_core::futures;
|
2021-10-10 17:26:22 -04:00
|
|
|
use deno_core::futures::FutureExt;
|
|
|
|
use deno_core::ModuleSpecifier;
|
|
|
|
use deno_graph::source::CacheInfo;
|
|
|
|
use deno_graph::source::LoadFuture;
|
|
|
|
use deno_graph::source::LoadResponse;
|
|
|
|
use deno_graph::source::Loader;
|
2024-09-25 21:50:54 -04:00
|
|
|
use deno_runtime::deno_permissions::PermissionsContainer;
|
2023-03-22 10:15:53 -04:00
|
|
|
use std::collections::HashMap;
|
2023-08-08 10:23:02 -04:00
|
|
|
use std::path::Path;
|
2023-08-01 20:49:09 -04:00
|
|
|
use std::path::PathBuf;
|
2021-10-10 17:26:22 -04:00
|
|
|
use std::sync::Arc;
|
2023-08-08 10:23:02 -04:00
|
|
|
use std::time::SystemTime;
|
2021-10-10 17:26:22 -04:00
|
|
|
|
feat(core): initialize SQLite off-main-thread (#18401)
This gets SQLite off the flamegraph and reduces initialization time by
somewhere between 0.2ms and 0.5ms. In addition, I took the opportunity
to move all the cache management code to a single place and reduce
duplication. While the PR has a net gain of lines, much of that is just
being a bit more deliberate with how we're recovering from errors.
The existing caches had various policies for dealing with cache
corruption, so I've unified them and tried to isolate the decisions we
make for recovery in a single place (see `open_connection` in
`CacheDB`). The policy I chose was:
1. Retry twice to open on-disk caches
2. If that fails, try to delete the file and recreate it on-disk
3. If we fail to delete the file or re-create a new cache, use a
fallback strategy that can be chosen per-cache: InMemory (temporary
cache for the process run), BlackHole (ignore writes, return empty
reads), or Error (fail on every operation).
The caches all use the same general code now, and share the cache
failure recovery policy.
In addition, it cleans up a TODO in the `NodeAnalysisCache`.
2023-03-27 18:01:52 -04:00
|
|
|
mod cache_db;
|
|
|
|
mod caches;
|
2022-07-12 18:58:39 -04:00
|
|
|
mod check;
|
2024-04-17 10:19:55 -04:00
|
|
|
mod code_cache;
|
2022-07-12 18:58:39 -04:00
|
|
|
mod common;
|
2022-11-25 19:04:30 -05:00
|
|
|
mod deno_dir;
|
2022-07-12 18:58:39 -04:00
|
|
|
mod disk_cache;
|
|
|
|
mod emit;
|
2024-02-20 16:29:57 -05:00
|
|
|
mod fast_check;
|
2022-07-12 18:58:39 -04:00
|
|
|
mod incremental;
|
2023-10-25 18:13:22 -04:00
|
|
|
mod module_info;
|
2022-10-01 06:15:56 -04:00
|
|
|
mod node;
|
2022-08-22 12:14:59 -04:00
|
|
|
mod parsed_source;
|
2022-07-12 18:58:39 -04:00
|
|
|
|
2024-05-29 14:38:18 -04:00
|
|
|
pub use cache_db::CacheDBHash;
|
feat(core): initialize SQLite off-main-thread (#18401)
This gets SQLite off the flamegraph and reduces initialization time by
somewhere between 0.2ms and 0.5ms. In addition, I took the opportunity
to move all the cache management code to a single place and reduce
duplication. While the PR has a net gain of lines, much of that is just
being a bit more deliberate with how we're recovering from errors.
The existing caches had various policies for dealing with cache
corruption, so I've unified them and tried to isolate the decisions we
make for recovery in a single place (see `open_connection` in
`CacheDB`). The policy I chose was:
1. Retry twice to open on-disk caches
2. If that fails, try to delete the file and recreate it on-disk
3. If we fail to delete the file or re-create a new cache, use a
fallback strategy that can be chosen per-cache: InMemory (temporary
cache for the process run), BlackHole (ignore writes, return empty
reads), or Error (fail on every operation).
The caches all use the same general code now, and share the cache
failure recovery policy.
In addition, it cleans up a TODO in the `NodeAnalysisCache`.
2023-03-27 18:01:52 -04:00
|
|
|
pub use caches::Caches;
|
2022-07-12 18:58:39 -04:00
|
|
|
pub use check::TypeCheckCache;
|
2024-04-17 10:19:55 -04:00
|
|
|
pub use code_cache::CodeCache;
|
2022-07-19 11:58:18 -04:00
|
|
|
pub use common::FastInsecureHasher;
|
2024-06-26 18:17:00 -04:00
|
|
|
pub use deno_dir::dirs::home_dir;
|
2022-11-25 19:04:30 -05:00
|
|
|
pub use deno_dir::DenoDir;
|
2023-05-25 14:27:45 -04:00
|
|
|
pub use deno_dir::DenoDirProvider;
|
2022-07-12 18:58:39 -04:00
|
|
|
pub use disk_cache::DiskCache;
|
|
|
|
pub use emit::EmitCache;
|
2024-02-20 16:29:57 -05:00
|
|
|
pub use fast_check::FastCheckCache;
|
2022-07-12 18:58:39 -04:00
|
|
|
pub use incremental::IncrementalCache;
|
2023-10-25 18:13:22 -04:00
|
|
|
pub use module_info::ModuleInfoCache;
|
2022-10-01 06:15:56 -04:00
|
|
|
pub use node::NodeAnalysisCache;
|
2024-10-14 20:48:39 -04:00
|
|
|
pub use parsed_source::EsmOrCjsChecker;
|
2024-02-06 15:57:10 -05:00
|
|
|
pub use parsed_source::LazyGraphSourceParser;
|
2022-08-22 12:14:59 -04:00
|
|
|
pub use parsed_source::ParsedSourceCache;
|
2022-07-12 18:58:39 -04:00
|
|
|
|
2022-11-28 17:28:54 -05:00
|
|
|
/// Permissions used to save a file in the disk caches.
|
|
|
|
pub const CACHE_PERM: u32 = 0o644;
|
|
|
|
|
2023-08-08 10:23:02 -04:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct RealDenoCacheEnv;
|
|
|
|
|
|
|
|
impl deno_cache_dir::DenoCacheEnv for RealDenoCacheEnv {
|
2024-08-26 19:59:17 -04:00
|
|
|
fn read_file_bytes(&self, path: &Path) -> std::io::Result<Vec<u8>> {
|
|
|
|
std::fs::read(path)
|
2023-08-08 10:23:02 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
fn atomic_write_file(
|
|
|
|
&self,
|
|
|
|
path: &Path,
|
|
|
|
bytes: &[u8],
|
|
|
|
) -> std::io::Result<()> {
|
2024-06-07 13:06:17 -04:00
|
|
|
atomic_write_file_with_retries(path, bytes, CACHE_PERM)
|
2023-08-08 10:23:02 -04:00
|
|
|
}
|
|
|
|
|
2024-09-28 08:50:16 -04:00
|
|
|
fn canonicalize_path(&self, path: &Path) -> std::io::Result<PathBuf> {
|
|
|
|
crate::util::fs::canonicalize_path(path)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn create_dir_all(&self, path: &Path) -> std::io::Result<()> {
|
|
|
|
std::fs::create_dir_all(path)
|
|
|
|
}
|
|
|
|
|
2023-08-08 10:23:02 -04:00
|
|
|
fn modified(&self, path: &Path) -> std::io::Result<Option<SystemTime>> {
|
|
|
|
match std::fs::metadata(path) {
|
|
|
|
Ok(metadata) => Ok(Some(
|
|
|
|
metadata.modified().unwrap_or_else(|_| SystemTime::now()),
|
|
|
|
)),
|
|
|
|
Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(None),
|
|
|
|
Err(err) => Err(err),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_file(&self, path: &Path) -> bool {
|
|
|
|
path.is_file()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn time_now(&self) -> SystemTime {
|
|
|
|
SystemTime::now()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-28 08:50:16 -04:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct DenoCacheEnvFsAdapter<'a>(
|
|
|
|
pub &'a dyn deno_runtime::deno_fs::FileSystem,
|
|
|
|
);
|
|
|
|
|
|
|
|
impl<'a> deno_cache_dir::DenoCacheEnv for DenoCacheEnvFsAdapter<'a> {
|
|
|
|
fn read_file_bytes(&self, path: &Path) -> std::io::Result<Vec<u8>> {
|
|
|
|
self
|
|
|
|
.0
|
|
|
|
.read_file_sync(path, None)
|
|
|
|
.map_err(|err| err.into_io_error())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn atomic_write_file(
|
|
|
|
&self,
|
|
|
|
path: &Path,
|
|
|
|
bytes: &[u8],
|
|
|
|
) -> std::io::Result<()> {
|
|
|
|
atomic_write_file_with_retries_and_fs(
|
|
|
|
&AtomicWriteFileFsAdapter {
|
|
|
|
fs: self.0,
|
|
|
|
write_mode: CACHE_PERM,
|
|
|
|
},
|
|
|
|
path,
|
|
|
|
bytes,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn canonicalize_path(&self, path: &Path) -> std::io::Result<PathBuf> {
|
|
|
|
self.0.realpath_sync(path).map_err(|e| e.into_io_error())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn create_dir_all(&self, path: &Path) -> std::io::Result<()> {
|
|
|
|
self
|
|
|
|
.0
|
|
|
|
.mkdir_sync(path, true, None)
|
|
|
|
.map_err(|e| e.into_io_error())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn modified(&self, path: &Path) -> std::io::Result<Option<SystemTime>> {
|
|
|
|
self
|
|
|
|
.0
|
|
|
|
.stat_sync(path)
|
|
|
|
.map(|stat| {
|
|
|
|
stat
|
|
|
|
.mtime
|
|
|
|
.map(|ts| SystemTime::UNIX_EPOCH + std::time::Duration::from_secs(ts))
|
|
|
|
})
|
|
|
|
.map_err(|e| e.into_io_error())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_file(&self, path: &Path) -> bool {
|
|
|
|
self.0.is_file_sync(path)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn time_now(&self) -> SystemTime {
|
|
|
|
SystemTime::now()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-08 10:23:02 -04:00
|
|
|
pub type GlobalHttpCache = deno_cache_dir::GlobalHttpCache<RealDenoCacheEnv>;
|
|
|
|
pub type LocalHttpCache = deno_cache_dir::LocalHttpCache<RealDenoCacheEnv>;
|
|
|
|
pub type LocalLspHttpCache =
|
|
|
|
deno_cache_dir::LocalLspHttpCache<RealDenoCacheEnv>;
|
|
|
|
pub use deno_cache_dir::HttpCache;
|
|
|
|
|
2024-09-25 21:50:54 -04:00
|
|
|
pub struct FetchCacherOptions {
|
|
|
|
pub file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>,
|
|
|
|
pub permissions: PermissionsContainer,
|
|
|
|
/// If we're publishing for `deno publish`.
|
|
|
|
pub is_deno_publish: bool,
|
2024-10-14 20:48:39 -04:00
|
|
|
pub unstable_detect_cjs: bool,
|
2024-09-25 21:50:54 -04:00
|
|
|
}
|
|
|
|
|
2021-10-10 17:26:22 -04:00
|
|
|
/// A "wrapper" for the FileFetcher and DiskCache for the Deno CLI that provides
|
|
|
|
/// a concise interface to the DENO_DIR when building module graphs.
|
2022-03-23 09:54:22 -04:00
|
|
|
pub struct FetchCacher {
|
2024-09-18 15:15:13 -04:00
|
|
|
pub file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>,
|
2024-10-14 20:48:39 -04:00
|
|
|
esm_or_cjs_checker: Arc<EsmOrCjsChecker>,
|
|
|
|
file_fetcher: Arc<FileFetcher>,
|
2023-08-01 20:49:09 -04:00
|
|
|
global_http_cache: Arc<GlobalHttpCache>,
|
2024-10-14 20:48:39 -04:00
|
|
|
node_resolver: Arc<CliNodeResolver>,
|
2023-10-25 14:39:00 -04:00
|
|
|
npm_resolver: Arc<dyn CliNpmResolver>,
|
2023-10-25 18:13:22 -04:00
|
|
|
module_info_cache: Arc<ModuleInfoCache>,
|
2024-09-25 21:50:54 -04:00
|
|
|
permissions: PermissionsContainer,
|
|
|
|
is_deno_publish: bool,
|
2024-10-14 20:48:39 -04:00
|
|
|
unstable_detect_cjs: bool,
|
|
|
|
cache_info_enabled: bool,
|
2021-10-10 17:26:22 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl FetchCacher {
|
|
|
|
pub fn new(
|
2024-10-14 20:48:39 -04:00
|
|
|
esm_or_cjs_checker: Arc<EsmOrCjsChecker>,
|
2023-02-03 14:15:16 -05:00
|
|
|
file_fetcher: Arc<FileFetcher>,
|
2023-08-01 20:49:09 -04:00
|
|
|
global_http_cache: Arc<GlobalHttpCache>,
|
2024-10-14 20:48:39 -04:00
|
|
|
node_resolver: Arc<CliNodeResolver>,
|
2023-10-25 14:39:00 -04:00
|
|
|
npm_resolver: Arc<dyn CliNpmResolver>,
|
2023-10-25 18:13:22 -04:00
|
|
|
module_info_cache: Arc<ModuleInfoCache>,
|
2024-09-25 21:50:54 -04:00
|
|
|
options: FetchCacherOptions,
|
2021-10-10 17:26:22 -04:00
|
|
|
) -> Self {
|
|
|
|
Self {
|
|
|
|
file_fetcher,
|
2024-10-14 20:48:39 -04:00
|
|
|
esm_or_cjs_checker,
|
2023-08-01 20:49:09 -04:00
|
|
|
global_http_cache,
|
2024-10-14 20:48:39 -04:00
|
|
|
node_resolver,
|
2023-10-25 14:39:00 -04:00
|
|
|
npm_resolver,
|
2023-10-25 18:13:22 -04:00
|
|
|
module_info_cache,
|
2024-09-25 21:50:54 -04:00
|
|
|
file_header_overrides: options.file_header_overrides,
|
|
|
|
permissions: options.permissions,
|
|
|
|
is_deno_publish: options.is_deno_publish,
|
2024-10-14 20:48:39 -04:00
|
|
|
unstable_detect_cjs: options.unstable_detect_cjs,
|
2023-02-08 19:45:04 -05:00
|
|
|
cache_info_enabled: false,
|
2021-10-10 17:26:22 -04:00
|
|
|
}
|
|
|
|
}
|
2023-02-08 19:45:04 -05:00
|
|
|
|
|
|
|
/// The cache information takes a bit of time to fetch and it's
|
|
|
|
/// not always necessary. It should only be enabled for deno info.
|
|
|
|
pub fn enable_loading_cache_info(&mut self) {
|
|
|
|
self.cache_info_enabled = true;
|
|
|
|
}
|
2023-08-01 20:49:09 -04:00
|
|
|
|
2024-09-05 10:22:13 -04:00
|
|
|
/// Only use this for `deno info`.
|
2023-08-01 20:49:09 -04:00
|
|
|
fn get_local_path(&self, specifier: &ModuleSpecifier) -> Option<PathBuf> {
|
|
|
|
// TODO(@kitsonk) fix when deno_graph does not query cache for synthetic
|
|
|
|
// modules
|
|
|
|
if specifier.scheme() == "flags" {
|
|
|
|
None
|
|
|
|
} else if specifier.scheme() == "file" {
|
|
|
|
specifier.to_file_path().ok()
|
|
|
|
} else {
|
|
|
|
#[allow(deprecated)]
|
|
|
|
self
|
|
|
|
.global_http_cache
|
|
|
|
.get_global_cache_filepath(specifier)
|
|
|
|
.ok()
|
|
|
|
}
|
|
|
|
}
|
2021-10-10 17:26:22 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Loader for FetchCacher {
|
|
|
|
fn get_cache_info(&self, specifier: &ModuleSpecifier) -> Option<CacheInfo> {
|
2023-02-08 19:45:04 -05:00
|
|
|
if !self.cache_info_enabled {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
2023-07-08 16:06:45 -04:00
|
|
|
#[allow(deprecated)]
|
2023-08-01 20:49:09 -04:00
|
|
|
let local = self.get_local_path(specifier)?;
|
2021-10-10 17:26:22 -04:00
|
|
|
if local.is_file() {
|
2024-09-05 10:22:13 -04:00
|
|
|
Some(CacheInfo { local: Some(local) })
|
2021-10-10 17:26:22 -04:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn load(
|
2024-04-18 20:51:16 -04:00
|
|
|
&self,
|
2021-10-10 17:26:22 -04:00
|
|
|
specifier: &ModuleSpecifier,
|
2024-02-15 14:49:35 -05:00
|
|
|
options: deno_graph::source::LoadOptions,
|
2021-10-10 17:26:22 -04:00
|
|
|
) -> LoadFuture {
|
2023-09-07 09:09:16 -04:00
|
|
|
use deno_graph::source::CacheSetting as LoaderCacheSetting;
|
|
|
|
|
2024-09-05 10:22:13 -04:00
|
|
|
if specifier.scheme() == "file" {
|
|
|
|
if specifier.path().contains("/node_modules/") {
|
|
|
|
// The specifier might be in a completely different symlinked tree than
|
|
|
|
// what the node_modules url is in (ex. `/my-project-1/node_modules`
|
|
|
|
// symlinked to `/my-project-2/node_modules`), so first we checked if the path
|
|
|
|
// is in a node_modules dir to avoid needlessly canonicalizing, then now compare
|
|
|
|
// against the canonicalized specifier.
|
|
|
|
let specifier =
|
|
|
|
crate::node::resolve_specifier_into_node_modules(specifier);
|
|
|
|
if self.npm_resolver.in_npm_package(&specifier) {
|
|
|
|
return Box::pin(futures::future::ready(Ok(Some(
|
|
|
|
LoadResponse::External { specifier },
|
|
|
|
))));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// make local CJS modules external to the graph
|
|
|
|
if specifier_has_extension(specifier, "cjs") {
|
2023-10-25 14:39:00 -04:00
|
|
|
return Box::pin(futures::future::ready(Ok(Some(
|
2024-09-05 10:22:13 -04:00
|
|
|
LoadResponse::External {
|
|
|
|
specifier: specifier.clone(),
|
|
|
|
},
|
2023-10-25 14:39:00 -04:00
|
|
|
))));
|
2023-02-22 17:21:05 -05:00
|
|
|
}
|
2024-10-14 20:48:39 -04:00
|
|
|
|
|
|
|
if self.unstable_detect_cjs && specifier_has_extension(specifier, "js") {
|
|
|
|
if let Ok(Some(pkg_json)) =
|
|
|
|
self.node_resolver.get_closest_package_json(specifier)
|
|
|
|
{
|
|
|
|
if pkg_json.typ == "commonjs" {
|
|
|
|
if let Ok(path) = specifier.to_file_path() {
|
|
|
|
if let Ok(bytes) = std::fs::read(&path) {
|
|
|
|
let text: Arc<str> = from_utf8_lossy_owned(bytes).into();
|
|
|
|
let is_es_module = match self.esm_or_cjs_checker.is_esm(
|
|
|
|
specifier,
|
|
|
|
text.clone(),
|
|
|
|
MediaType::JavaScript,
|
|
|
|
) {
|
|
|
|
Ok(value) => value,
|
|
|
|
Err(err) => {
|
|
|
|
return Box::pin(futures::future::ready(Err(err.into())));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
if !is_es_module {
|
|
|
|
self.node_resolver.mark_cjs_resolution(specifier.clone());
|
|
|
|
return Box::pin(futures::future::ready(Ok(Some(
|
|
|
|
LoadResponse::External {
|
|
|
|
specifier: specifier.clone(),
|
|
|
|
},
|
|
|
|
))));
|
|
|
|
} else {
|
|
|
|
return Box::pin(futures::future::ready(Ok(Some(
|
|
|
|
LoadResponse::Module {
|
|
|
|
specifier: specifier.clone(),
|
|
|
|
content: arc_str_to_bytes(text),
|
|
|
|
maybe_headers: None,
|
|
|
|
},
|
|
|
|
))));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-02-22 17:21:05 -05:00
|
|
|
}
|
|
|
|
|
2024-09-25 21:50:54 -04:00
|
|
|
if self.is_deno_publish
|
|
|
|
&& matches!(specifier.scheme(), "http" | "https")
|
|
|
|
&& !specifier.as_str().starts_with(jsr_url().as_str())
|
|
|
|
{
|
|
|
|
// mark non-JSR remote modules as external so we don't need --allow-import
|
|
|
|
// permissions as these will error out later when publishing
|
|
|
|
return Box::pin(futures::future::ready(Ok(Some(
|
|
|
|
LoadResponse::External {
|
|
|
|
specifier: specifier.clone(),
|
|
|
|
},
|
|
|
|
))));
|
|
|
|
}
|
|
|
|
|
2021-10-10 17:26:22 -04:00
|
|
|
let file_fetcher = self.file_fetcher.clone();
|
2023-03-22 10:15:53 -04:00
|
|
|
let file_header_overrides = self.file_header_overrides.clone();
|
2023-09-07 09:09:16 -04:00
|
|
|
let permissions = self.permissions.clone();
|
2023-02-22 14:15:25 -05:00
|
|
|
let specifier = specifier.clone();
|
2024-09-25 21:50:54 -04:00
|
|
|
let is_statically_analyzable = !options.was_dynamic_root;
|
2021-10-10 17:26:22 -04:00
|
|
|
|
|
|
|
async move {
|
2024-02-15 14:49:35 -05:00
|
|
|
let maybe_cache_setting = match options.cache_setting {
|
2023-09-07 09:09:16 -04:00
|
|
|
LoaderCacheSetting::Use => None,
|
|
|
|
LoaderCacheSetting::Reload => {
|
|
|
|
if matches!(file_fetcher.cache_setting(), CacheSetting::Only) {
|
|
|
|
return Err(deno_core::anyhow::anyhow!(
|
2024-05-28 14:58:43 -04:00
|
|
|
"Could not resolve version constraint using only cached data. Try running again without --cached-only"
|
2023-09-07 09:09:16 -04:00
|
|
|
));
|
|
|
|
}
|
|
|
|
Some(CacheSetting::ReloadAll)
|
|
|
|
}
|
|
|
|
LoaderCacheSetting::Only => Some(CacheSetting::Only),
|
|
|
|
};
|
2022-01-13 11:58:00 -05:00
|
|
|
file_fetcher
|
2024-04-18 21:43:28 -04:00
|
|
|
.fetch_no_follow_with_options(FetchNoFollowOptions {
|
|
|
|
fetch_options: FetchOptions {
|
|
|
|
specifier: &specifier,
|
2024-09-25 21:50:54 -04:00
|
|
|
permissions: if is_statically_analyzable {
|
|
|
|
FetchPermissionsOptionRef::StaticContainer(&permissions)
|
|
|
|
} else {
|
|
|
|
FetchPermissionsOptionRef::DynamicContainer(&permissions)
|
|
|
|
},
|
2024-04-18 21:43:28 -04:00
|
|
|
maybe_accept: None,
|
|
|
|
maybe_cache_setting: maybe_cache_setting.as_ref(),
|
|
|
|
},
|
|
|
|
maybe_checksum: options.maybe_checksum.as_ref(),
|
2023-09-07 09:09:16 -04:00
|
|
|
})
|
2021-10-10 17:26:22 -04:00
|
|
|
.await
|
2024-04-18 21:43:28 -04:00
|
|
|
.map(|file_or_redirect| {
|
|
|
|
match file_or_redirect {
|
|
|
|
FileOrRedirect::File(file) => {
|
|
|
|
let maybe_headers =
|
|
|
|
match (file.maybe_headers, file_header_overrides.get(&specifier)) {
|
|
|
|
(Some(headers), Some(overrides)) => {
|
|
|
|
Some(headers.into_iter().chain(overrides.clone()).collect())
|
|
|
|
}
|
|
|
|
(Some(headers), None) => Some(headers),
|
|
|
|
(None, Some(overrides)) => Some(overrides.clone()),
|
|
|
|
(None, None) => None,
|
|
|
|
};
|
|
|
|
Ok(Some(LoadResponse::Module {
|
|
|
|
specifier: file.specifier,
|
|
|
|
maybe_headers,
|
|
|
|
content: file.source,
|
|
|
|
}))
|
|
|
|
},
|
|
|
|
FileOrRedirect::Redirect(redirect_specifier) => {
|
|
|
|
Ok(Some(LoadResponse::Redirect {
|
|
|
|
specifier: redirect_specifier,
|
|
|
|
}))
|
|
|
|
},
|
|
|
|
}
|
2023-03-15 17:46:36 -04:00
|
|
|
})
|
|
|
|
.unwrap_or_else(|err| {
|
2023-09-18 10:46:44 -04:00
|
|
|
if let Some(io_err) = err.downcast_ref::<std::io::Error>() {
|
|
|
|
if io_err.kind() == std::io::ErrorKind::NotFound {
|
2021-12-22 08:25:06 -05:00
|
|
|
return Ok(None);
|
2023-09-18 10:46:44 -04:00
|
|
|
} else {
|
|
|
|
return Err(err);
|
2021-10-10 17:26:22 -04:00
|
|
|
}
|
2023-03-15 17:46:36 -04:00
|
|
|
}
|
2023-09-18 10:46:44 -04:00
|
|
|
let error_class_name = get_error_class_name(&err);
|
|
|
|
match error_class_name {
|
|
|
|
"NotFound" => Ok(None),
|
2024-02-15 14:49:35 -05:00
|
|
|
"NotCached" if options.cache_setting == LoaderCacheSetting::Only => Ok(None),
|
2023-09-18 10:46:44 -04:00
|
|
|
_ => Err(err),
|
|
|
|
}
|
2023-03-15 17:46:36 -04:00
|
|
|
})
|
2021-10-10 17:26:22 -04:00
|
|
|
}
|
2024-06-03 17:17:08 -04:00
|
|
|
.boxed_local()
|
2021-10-10 17:26:22 -04:00
|
|
|
}
|
2023-09-07 09:09:16 -04:00
|
|
|
|
|
|
|
fn cache_module_info(
|
2024-04-18 20:51:16 -04:00
|
|
|
&self,
|
2023-09-07 09:09:16 -04:00
|
|
|
specifier: &ModuleSpecifier,
|
2024-09-05 10:22:13 -04:00
|
|
|
media_type: MediaType,
|
2024-01-31 22:15:22 -05:00
|
|
|
source: &Arc<[u8]>,
|
2023-09-07 09:09:16 -04:00
|
|
|
module_info: &deno_graph::ModuleInfo,
|
|
|
|
) {
|
2024-04-29 14:09:58 -04:00
|
|
|
log::debug!("Caching module info for {}", specifier);
|
2024-05-29 14:38:18 -04:00
|
|
|
let source_hash = CacheDBHash::from_source(source);
|
2023-10-25 18:13:22 -04:00
|
|
|
let result = self.module_info_cache.set_module_info(
|
2023-09-07 09:09:16 -04:00
|
|
|
specifier,
|
2024-09-05 10:22:13 -04:00
|
|
|
media_type,
|
2024-05-29 14:38:18 -04:00
|
|
|
source_hash,
|
2023-09-07 09:09:16 -04:00
|
|
|
module_info,
|
|
|
|
);
|
|
|
|
if let Err(err) = result {
|
|
|
|
log::debug!(
|
|
|
|
"Error saving module cache info for {}. {:#}",
|
|
|
|
specifier,
|
|
|
|
err
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2021-10-10 17:26:22 -04:00
|
|
|
}
|