1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-03 04:48:52 -05:00

refactor: do not use deno_fs::FileSystem everywhere (#27508)

This changes the cli to mostly use `std::fs` via `sys_traits` instead of
the implemention of `deno_fs::FileSystem`.
This commit is contained in:
David Sherret 2024-12-31 11:29:07 -05:00 committed by GitHub
parent 1cd36009b0
commit 4638caa740
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
74 changed files with 1304 additions and 1437 deletions

10
Cargo.lock generated
View file

@ -1737,14 +1737,12 @@ dependencies = [
"deno_path_util 0.3.0",
"deno_permissions",
"filetime",
"getrandom",
"junction",
"libc",
"nix",
"rand",
"rayon",
"serde",
"sys_traits",
"thiserror 2.0.3",
"winapi",
"windows-sys 0.59.0",
@ -2042,6 +2040,7 @@ dependencies = [
"sm3",
"spki",
"stable_deref_trait",
"sys_traits",
"thiserror 2.0.3",
"tokio",
"tokio-eld",
@ -2261,6 +2260,7 @@ dependencies = [
"serde",
"signal-hook",
"signal-hook-registry",
"sys_traits",
"tempfile",
"test_server",
"thiserror 2.0.3",
@ -7680,12 +7680,14 @@ dependencies = [
[[package]]
name = "sys_traits"
version = "0.1.1"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5a12729b699487bb50163466e87be7197871d83d04cc6815d430cf7c893bbd7"
checksum = "6683465f4e1d8fd75069cbc36c646258c05b7d8d6676bcb5d71968b99b7d5ae2"
dependencies = [
"filetime",
"getrandom",
"libc",
"parking_lot",
"windows-sys 0.59.0",
]

View file

@ -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.1"
sys_traits = "=0.1.4"
tar = "=0.4.40"
tempfile = "3.4.0"
termcolor = "1.1.3"

View file

@ -158,7 +158,7 @@ shell-escape = "=0.1.5"
spki = { version = "0.7", features = ["pem"] }
sqlformat = "=0.3.2"
strsim = "0.11.1"
sys_traits = { workspace = true, features = ["libc", "real", "winapi"] }
sys_traits = { workspace = true, features = ["getrandom", "filetime", "libc", "real", "strip_unc", "winapi"] }
tar.workspace = true
tempfile.workspace = true
text-size = "=1.1.0"
@ -187,6 +187,7 @@ nix.workspace = true
[dev-dependencies]
deno_bench_util.workspace = true
pretty_assertions.workspace = true
sys_traits = { workspace = true, features = ["memory"] }
test_util.workspace = true
[package.metadata.winres]

View file

@ -13,12 +13,12 @@ use deno_core::serde_json;
use deno_lockfile::WorkspaceMemberConfig;
use deno_package_json::PackageJsonDepValue;
use deno_path_util::fs::atomic_write_file_with_retries;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use deno_runtime::deno_node::PackageJson;
use deno_semver::jsr::JsrDepPackageReq;
use crate::args::deno_json::import_map_deps;
use crate::cache;
use crate::sys::CliSys;
use crate::Flags;
use crate::args::DenoSubcommand;
@ -36,6 +36,7 @@ pub struct CliLockfileReadFromPathOptions {
#[derive(Debug)]
pub struct CliLockfile {
sys: CliSys,
lockfile: Mutex<Lockfile>,
pub filename: PathBuf,
frozen: bool,
@ -92,7 +93,7 @@ impl CliLockfile {
// do an atomic write to reduce the chance of multiple deno
// processes corrupting the file
atomic_write_file_with_retries(
&FsSysTraitsAdapter::new_real(),
&self.sys,
&lockfile.filename,
&bytes,
cache::CACHE_PERM,
@ -103,6 +104,7 @@ impl CliLockfile {
}
pub fn discover(
sys: &CliSys,
flags: &Flags,
workspace: &Workspace,
maybe_external_import_map: Option<&serde_json::Value>,
@ -165,11 +167,14 @@ impl CliLockfile {
.unwrap_or(false)
});
let lockfile = Self::read_from_path(CliLockfileReadFromPathOptions {
file_path,
frozen,
skip_write: flags.internal.lockfile_skip_write,
})?;
let lockfile = Self::read_from_path(
sys,
CliLockfileReadFromPathOptions {
file_path,
frozen,
skip_write: flags.internal.lockfile_skip_write,
},
)?;
// initialize the lockfile with the workspace's configuration
let root_url = workspace.root_dir();
@ -225,6 +230,7 @@ impl CliLockfile {
}
pub fn read_from_path(
sys: &CliSys,
opts: CliLockfileReadFromPathOptions,
) -> Result<CliLockfile, AnyError> {
let lockfile = match std::fs::read_to_string(&opts.file_path) {
@ -243,6 +249,7 @@ impl CliLockfile {
}
};
Ok(CliLockfile {
sys: sys.clone(),
filename: lockfile.filename.clone(),
lockfile: Mutex::new(lockfile),
frozen: opts.frozen,

View file

@ -30,7 +30,6 @@ use deno_npm::npm_rc::ResolvedNpmRc;
use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot;
use deno_npm::NpmSystemInfo;
use deno_path_util::normalize_path;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use deno_semver::npm::NpmPackageReqReference;
use deno_semver::StackString;
use deno_telemetry::OtelConfig;
@ -89,6 +88,7 @@ use thiserror::Error;
use crate::cache::DenoDirProvider;
use crate::file_fetcher::CliFileFetcher;
use crate::sys::CliSys;
use crate::util::fs::canonicalize_path_maybe_not_exists;
use crate::version;
@ -573,7 +573,7 @@ fn discover_npmrc(
// TODO(bartlomieju): update to read both files - one in the project root and one and
// home dir and then merge them.
// 3. Try `.npmrc` in the user's home directory
if let Some(home_dir) = sys_traits::impls::RealSys.env_home_dir() {
if let Some(home_dir) = crate::sys::CliSys::default().env_home_dir() {
match try_to_read_npmrc(&home_dir) {
Ok(Some((source, path))) => {
return try_to_parse_npmrc(source, &path).map(|r| (r, Some(path)));
@ -772,7 +772,9 @@ pub struct CliOptions {
}
impl CliOptions {
#[allow(clippy::too_many_arguments)]
pub fn new(
sys: &CliSys,
flags: Arc<Flags>,
initial_cwd: PathBuf,
maybe_lockfile: Option<Arc<CliLockfile>>,
@ -797,8 +799,10 @@ impl CliOptions {
}
let maybe_lockfile = maybe_lockfile.filter(|_| !force_global_cache);
let deno_dir_provider =
Arc::new(DenoDirProvider::new(flags.internal.cache_path.clone()));
let deno_dir_provider = Arc::new(DenoDirProvider::new(
sys.clone(),
flags.internal.cache_path.clone(),
));
let maybe_node_modules_folder = resolve_node_modules_folder(
&initial_cwd,
&flags,
@ -823,7 +827,7 @@ impl CliOptions {
})
}
pub fn from_flags(flags: Arc<Flags>) -> Result<Self, AnyError> {
pub fn from_flags(sys: &CliSys, flags: Arc<Flags>) -> Result<Self, AnyError> {
let initial_cwd =
std::env::current_dir().with_context(|| "Failed getting cwd.")?;
let maybe_vendor_override = flags.vendor.map(|v| match v {
@ -867,7 +871,7 @@ impl CliOptions {
ConfigFlag::Discover => {
if let Some(start_paths) = flags.config_path_args(&initial_cwd) {
WorkspaceDirectory::discover(
&FsSysTraitsAdapter::new_real(),
sys,
WorkspaceDiscoverStart::Paths(&start_paths),
&resolve_workspace_discover_options(),
)?
@ -878,7 +882,7 @@ impl CliOptions {
ConfigFlag::Path(path) => {
let config_path = normalize_path(initial_cwd.join(path));
WorkspaceDirectory::discover(
&FsSysTraitsAdapter::new_real(),
sys,
WorkspaceDiscoverStart::ConfigFile(&config_path),
&resolve_workspace_discover_options(),
)?
@ -917,6 +921,7 @@ impl CliOptions {
};
let maybe_lock_file = CliLockfile::discover(
sys,
&flags,
&start_dir.workspace,
external_import_map.as_ref().map(|(_, v)| v),
@ -925,6 +930,7 @@ impl CliOptions {
log::debug!("Finished config loading.");
Self::new(
sys,
flags,
initial_cwd,
maybe_lock_file.map(Arc::new),

13
cli/cache/deno_dir.rs vendored
View file

@ -3,6 +3,8 @@
use deno_cache_dir::DenoDirResolutionError;
use once_cell::sync::OnceCell;
use crate::sys::CliSys;
use super::DiskCache;
use std::env;
@ -11,13 +13,15 @@ use std::path::PathBuf;
/// Lazily creates the deno dir which might be useful in scenarios
/// where functionality wants to continue if the DENO_DIR can't be created.
pub struct DenoDirProvider {
sys: CliSys,
maybe_custom_root: Option<PathBuf>,
deno_dir: OnceCell<Result<DenoDir, DenoDirResolutionError>>,
}
impl DenoDirProvider {
pub fn new(maybe_custom_root: Option<PathBuf>) -> Self {
pub fn new(sys: CliSys, maybe_custom_root: Option<PathBuf>) -> Self {
Self {
sys,
maybe_custom_root,
deno_dir: Default::default(),
}
@ -26,7 +30,9 @@ impl DenoDirProvider {
pub fn get_or_create(&self) -> Result<&DenoDir, DenoDirResolutionError> {
self
.deno_dir
.get_or_init(|| DenoDir::new(self.maybe_custom_root.clone()))
.get_or_init(|| {
DenoDir::new(self.sys.clone(), self.maybe_custom_root.clone())
})
.as_ref()
.map_err(|err| match err {
DenoDirResolutionError::NoCacheOrHomeDir => {
@ -53,6 +59,7 @@ pub struct DenoDir {
impl DenoDir {
pub fn new(
sys: CliSys,
maybe_custom_root: Option<PathBuf>,
) -> Result<Self, deno_cache_dir::DenoDirResolutionError> {
let root = deno_cache_dir::resolve_deno_dir(
@ -64,7 +71,7 @@ impl DenoDir {
let deno_dir = Self {
root,
gen_cache: DiskCache::new(&gen_path),
gen_cache: DiskCache::new(sys, &gen_path),
};
Ok(deno_dir)

View file

@ -1,12 +1,13 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use crate::sys::CliSys;
use super::CACHE_PERM;
use deno_cache_dir::url_to_filename;
use deno_core::url::Host;
use deno_core::url::Url;
use deno_path_util::fs::atomic_write_file_with_retries;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use std::ffi::OsStr;
use std::fs;
use std::path::Component;
@ -17,14 +18,16 @@ use std::str;
#[derive(Debug, Clone)]
pub struct DiskCache {
sys: CliSys,
pub location: PathBuf,
}
impl DiskCache {
/// `location` must be an absolute path.
pub fn new(location: &Path) -> Self {
pub fn new(sys: CliSys, location: &Path) -> Self {
assert!(location.is_absolute());
Self {
sys,
location: location.to_owned(),
}
}
@ -121,12 +124,7 @@ impl DiskCache {
pub fn set(&self, filename: &Path, data: &[u8]) -> std::io::Result<()> {
let path = self.location.join(filename);
atomic_write_file_with_retries(
&FsSysTraitsAdapter::new_real(),
&path,
data,
CACHE_PERM,
)
atomic_write_file_with_retries(&self.sys, &path, data, CACHE_PERM)
}
}
@ -139,7 +137,7 @@ mod tests {
fn test_set_get_cache_file() {
let temp_dir = TempDir::new();
let sub_dir = temp_dir.path().join("sub_dir");
let cache = DiskCache::new(&sub_dir.to_path_buf());
let cache = DiskCache::new(CliSys::default(), &sub_dir.to_path_buf());
let path = PathBuf::from("foo/bar.txt");
cache.set(&path, b"hello").unwrap();
assert_eq!(cache.get(&path).unwrap(), b"hello");
@ -153,7 +151,7 @@ mod tests {
PathBuf::from("/deno_dir/")
};
let cache = DiskCache::new(&cache_location);
let cache = DiskCache::new(CliSys::default(), &cache_location);
let mut test_cases = vec![
(
@ -209,7 +207,7 @@ mod tests {
} else {
"/foo"
};
let cache = DiskCache::new(&PathBuf::from(p));
let cache = DiskCache::new(CliSys::default(), &PathBuf::from(p));
let mut test_cases = vec![
(
@ -257,7 +255,7 @@ mod tests {
PathBuf::from("/deno_dir/")
};
let cache = DiskCache::new(&cache_location);
let cache = DiskCache::new(CliSys::default(), &cache_location);
let mut test_cases = vec!["unknown://localhost/test.ts"];

5
cli/cache/emit.rs vendored
View file

@ -159,12 +159,15 @@ impl EmitFileSerializer {
mod test {
use test_util::TempDir;
use crate::sys::CliSys;
use super::*;
#[test]
pub fn emit_cache_general_use() {
let temp_dir = TempDir::new();
let disk_cache = DiskCache::new(temp_dir.path().as_path());
let disk_cache =
DiskCache::new(CliSys::default(), temp_dir.path().as_path());
let cache = EmitCache {
disk_cache: disk_cache.clone(),
file_serializer: EmitFileSerializer {

13
cli/cache/mod.rs vendored
View file

@ -5,6 +5,7 @@ use crate::file_fetcher::CliFetchNoFollowErrorKind;
use crate::file_fetcher::CliFileFetcher;
use crate::file_fetcher::FetchNoFollowOptions;
use crate::file_fetcher::FetchPermissionsOptionRef;
use crate::sys::CliSys;
use deno_ast::MediaType;
use deno_cache_dir::file_fetcher::CacheSetting;
@ -18,7 +19,6 @@ use deno_graph::source::CacheInfo;
use deno_graph::source::LoadFuture;
use deno_graph::source::LoadResponse;
use deno_graph::source::Loader;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use deno_runtime::deno_permissions::PermissionsContainer;
use node_resolver::InNpmPackageChecker;
use std::collections::HashMap;
@ -58,10 +58,9 @@ pub use parsed_source::ParsedSourceCache;
/// Permissions used to save a file in the disk caches.
pub use deno_cache_dir::CACHE_PERM;
pub type GlobalHttpCache = deno_cache_dir::GlobalHttpCache<FsSysTraitsAdapter>;
pub type LocalHttpCache = deno_cache_dir::LocalHttpCache<FsSysTraitsAdapter>;
pub type LocalLspHttpCache =
deno_cache_dir::LocalLspHttpCache<FsSysTraitsAdapter>;
pub type GlobalHttpCache = deno_cache_dir::GlobalHttpCache<CliSys>;
pub type LocalHttpCache = deno_cache_dir::LocalHttpCache<CliSys>;
pub type LocalLspHttpCache = deno_cache_dir::LocalLspHttpCache<CliSys>;
pub use deno_cache_dir::HttpCache;
pub struct FetchCacherOptions {
@ -80,7 +79,7 @@ pub struct FetchCacher {
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
module_info_cache: Arc<ModuleInfoCache>,
permissions: PermissionsContainer,
sys: FsSysTraitsAdapter,
sys: CliSys,
is_deno_publish: bool,
cache_info_enabled: bool,
}
@ -91,7 +90,7 @@ impl FetchCacher {
global_http_cache: Arc<GlobalHttpCache>,
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
module_info_cache: Arc<ModuleInfoCache>,
sys: FsSysTraitsAdapter,
sys: CliSys,
options: FetchCacherOptions,
) -> Self {
Self {

View file

@ -4,6 +4,7 @@ disallowed-methods = [
]
disallowed-types = [
{ path = "reqwest::Client", reason = "use crate::http_util::HttpClient instead" },
{ path = "sys_traits::impls::RealSys", reason = "use crate::sys::CliSys instead" },
]
ignore-interior-mutability = [
"lsp_types::Uri",

View file

@ -31,6 +31,8 @@ use crate::module_loader::CliModuleLoaderFactory;
use crate::module_loader::ModuleLoadPreparer;
use crate::node::CliCjsCodeAnalyzer;
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;
@ -48,7 +50,8 @@ use crate::resolver::CliResolverOptions;
use crate::resolver::CliSloppyImportsResolver;
use crate::resolver::NpmModuleLoader;
use crate::resolver::SloppyImportsCachedFs;
use crate::standalone::DenoCompileBinaryWriter;
use crate::standalone::binary::DenoCompileBinaryWriter;
use crate::sys::CliSys;
use crate::tools::check::TypeChecker;
use crate::tools::coverage::CoverageCollector;
use crate::tools::lint::LintRuleProvider;
@ -74,9 +77,7 @@ use deno_resolver::npm::NpmReqResolverOptions;
use deno_resolver::DenoResolverOptions;
use deno_resolver::NodeAndNpmReqResolver;
use deno_runtime::deno_fs;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use deno_runtime::deno_node::NodeResolver;
use deno_runtime::deno_node::PackageJsonResolver;
use deno_runtime::deno_fs::RealFs;
use deno_runtime::deno_node::RealIsBuiltInNodeModuleChecker;
use deno_runtime::deno_permissions::Permissions;
use deno_runtime::deno_permissions::PermissionsContainer;
@ -198,13 +199,14 @@ struct CliFactoryServices {
module_info_cache: Deferred<Arc<ModuleInfoCache>>,
module_load_preparer: Deferred<Arc<ModuleLoadPreparer>>,
node_code_translator: Deferred<Arc<CliNodeCodeTranslator>>,
node_resolver: Deferred<Arc<NodeResolver>>,
node_resolver: Deferred<Arc<CliNodeResolver>>,
npm_cache_dir: Deferred<Arc<NpmCacheDir>>,
npm_req_resolver: Deferred<Arc<CliNpmReqResolver>>,
npm_resolver: Deferred<Arc<dyn CliNpmResolver>>,
parsed_source_cache: Deferred<Arc<ParsedSourceCache>>,
permission_desc_parser: Deferred<Arc<RuntimePermissionDescriptorParser>>,
pkg_json_resolver: Deferred<Arc<PackageJsonResolver>>,
permission_desc_parser:
Deferred<Arc<RuntimePermissionDescriptorParser<CliSys>>>,
pkg_json_resolver: Deferred<Arc<CliPackageJsonResolver>>,
resolver: Deferred<Arc<CliResolver>>,
root_cert_store_provider: Deferred<Arc<dyn RootCertStoreProvider>>,
root_permissions_container: Deferred<PermissionsContainer>,
@ -254,7 +256,7 @@ impl CliFactory {
pub fn cli_options(&self) -> Result<&Arc<CliOptions>, AnyError> {
self.services.cli_options.get_or_try_init(|| {
CliOptions::from_flags(self.flags.clone()).map(Arc::new)
CliOptions::from_flags(&self.sys(), self.flags.clone()).map(Arc::new)
})
}
@ -317,7 +319,7 @@ impl CliFactory {
pub fn global_http_cache(&self) -> Result<&Arc<GlobalHttpCache>, AnyError> {
self.services.global_http_cache.get_or_try_init(|| {
Ok(Arc::new(GlobalHttpCache::new(
FsSysTraitsAdapter(self.fs().clone()),
self.sys(),
self.deno_dir()?.remote_folder_path(),
)))
})
@ -355,6 +357,7 @@ impl CliFactory {
Ok(Arc::new(CliFileFetcher::new(
self.http_cache()?.clone(),
self.http_client_provider().clone(),
self.sys(),
self.blob_store().clone(),
Some(self.text_only_progress_bar().clone()),
!cli_options.no_remote(),
@ -365,7 +368,11 @@ impl CliFactory {
}
pub fn fs(&self) -> &Arc<dyn deno_fs::FileSystem> {
self.services.fs.get_or_init(|| Arc::new(deno_fs::RealFs))
self.services.fs.get_or_init(|| Arc::new(RealFs))
}
pub fn sys(&self) -> CliSys {
CliSys::default() // very cheap to make
}
pub fn in_npm_pkg_checker(
@ -391,11 +398,10 @@ impl CliFactory {
pub fn npm_cache_dir(&self) -> Result<&Arc<NpmCacheDir>, AnyError> {
self.services.npm_cache_dir.get_or_try_init(|| {
let fs = self.fs();
let global_path = self.deno_dir()?.npm_folder_path();
let cli_options = self.cli_options()?;
Ok(Arc::new(NpmCacheDir::new(
&FsSysTraitsAdapter(fs.clone()),
&self.sys(),
global_path,
cli_options.npmrc().get_all_known_registries_urls(),
)))
@ -410,12 +416,11 @@ impl CliFactory {
.npm_resolver
.get_or_try_init_async(
async {
let fs = self.fs();
let cli_options = self.cli_options()?;
create_cli_npm_resolver(if cli_options.use_byonm() {
CliNpmResolverCreateOptions::Byonm(
CliByonmNpmResolverCreateOptions {
sys: FsSysTraitsAdapter(fs.clone()),
sys: self.sys(),
pkg_json_resolver: self.pkg_json_resolver().clone(),
root_node_modules_dir: Some(
match cli_options.node_modules_dir_path() {
@ -439,7 +444,7 @@ impl CliFactory {
cli_options.workspace(),
),
),
sys: FsSysTraitsAdapter(self.fs().clone()),
sys: self.sys(),
snapshot: match cli_options.resolve_npm_resolution_snapshot()? {
Some(snapshot) => {
CliNpmResolverManagedSnapshotOption::Specified(Some(
@ -486,7 +491,7 @@ impl CliFactory {
.get_or_try_init(|| {
Ok(self.cli_options()?.unstable_sloppy_imports().then(|| {
Arc::new(CliSloppyImportsResolver::new(SloppyImportsCachedFs::new(
FsSysTraitsAdapter(self.fs().clone()),
self.sys(),
)))
}))
})
@ -647,13 +652,13 @@ impl CliFactory {
))
}
pub async fn node_resolver(&self) -> Result<&Arc<NodeResolver>, AnyError> {
pub async fn node_resolver(&self) -> Result<&Arc<CliNodeResolver>, AnyError> {
self
.services
.node_resolver
.get_or_try_init_async(
async {
Ok(Arc::new(NodeResolver::new(
Ok(Arc::new(CliNodeResolver::new(
self.in_npm_pkg_checker()?.clone(),
RealIsBuiltInNodeModuleChecker,
self
@ -662,7 +667,7 @@ impl CliFactory {
.clone()
.into_npm_pkg_folder_resolver(),
self.pkg_json_resolver().clone(),
FsSysTraitsAdapter(self.fs().clone()),
self.sys(),
)))
}
.boxed_local(),
@ -698,7 +703,7 @@ impl CliFactory {
.clone()
.into_npm_pkg_folder_resolver(),
self.pkg_json_resolver().clone(),
FsSysTraitsAdapter(self.fs().clone()),
self.sys(),
)))
})
.await
@ -714,7 +719,7 @@ impl CliFactory {
let npm_resolver = self.npm_resolver().await?;
Ok(Arc::new(CliNpmReqResolver::new(NpmReqResolverOptions {
byonm_resolver: (npm_resolver.clone()).into_maybe_byonm(),
sys: FsSysTraitsAdapter(self.fs().clone()),
sys: self.sys(),
in_npm_pkg_checker: self.in_npm_pkg_checker()?.clone(),
node_resolver: self.node_resolver().await?.clone(),
npm_req_resolver: npm_resolver.clone().into_npm_req_resolver(),
@ -723,12 +728,11 @@ impl CliFactory {
.await
}
pub fn pkg_json_resolver(&self) -> &Arc<PackageJsonResolver> {
self.services.pkg_json_resolver.get_or_init(|| {
Arc::new(PackageJsonResolver::new(FsSysTraitsAdapter(
self.fs().clone(),
)))
})
pub fn pkg_json_resolver(&self) -> &Arc<CliPackageJsonResolver> {
self
.services
.pkg_json_resolver
.get_or_init(|| Arc::new(CliPackageJsonResolver::new(self.sys())))
}
pub async fn type_checker(&self) -> Result<&Arc<TypeChecker>, AnyError> {
@ -774,7 +778,7 @@ impl CliFactory {
self.parsed_source_cache().clone(),
self.resolver().await?.clone(),
self.root_permissions_container()?.clone(),
FsSysTraitsAdapter(self.fs().clone()),
self.sys(),
)))
})
.await
@ -864,10 +868,9 @@ impl CliFactory {
pub fn permission_desc_parser(
&self,
) -> Result<&Arc<RuntimePermissionDescriptorParser>, AnyError> {
) -> Result<&Arc<RuntimePermissionDescriptorParser<CliSys>>, AnyError> {
self.services.permission_desc_parser.get_or_try_init(|| {
let fs = self.fs().clone();
Ok(Arc::new(RuntimePermissionDescriptorParser::new(fs)))
Ok(Arc::new(RuntimePermissionDescriptorParser::new(self.sys())))
})
}
@ -974,7 +977,7 @@ impl CliFactory {
),
self.parsed_source_cache().clone(),
self.resolver().await?.clone(),
FsSysTraitsAdapter(self.fs().clone()),
self.sys(),
)),
node_resolver.clone(),
npm_resolver.clone(),
@ -982,6 +985,7 @@ impl CliFactory {
self.root_cert_store_provider().clone(),
self.root_permissions_container()?.clone(),
StorageKeyResolver::from_options(cli_options),
self.sys(),
cli_options.sub_command().clone(),
self.create_cli_main_worker_options()?,
self.cli_options()?.otel_config(),

View file

@ -24,7 +24,6 @@ use deno_core::url::Url;
use deno_core::ModuleSpecifier;
use deno_error::JsError;
use deno_graph::source::LoaderChecksum;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use deno_runtime::deno_permissions::CheckSpecifierKind;
use deno_runtime::deno_permissions::PermissionCheckError;
use deno_runtime::deno_permissions::PermissionsContainer;
@ -38,6 +37,7 @@ use crate::cache::HttpCache;
use crate::colors;
use crate::http_util::get_response_body_with_progress;
use crate::http_util::HttpClientProvider;
use crate::sys::CliSys;
use crate::util::progress_bar::ProgressBar;
#[derive(Debug, Clone, Eq, PartialEq)]
@ -267,7 +267,7 @@ pub struct FetchNoFollowOptions<'a> {
type DenoCacheDirFileFetcher = deno_cache_dir::file_fetcher::FileFetcher<
BlobStoreAdapter,
FsSysTraitsAdapter,
CliSys,
HttpClientAdapter,
>;
@ -279,9 +279,11 @@ pub struct CliFileFetcher {
}
impl CliFileFetcher {
#[allow(clippy::too_many_arguments)]
pub fn new(
http_cache: Arc<dyn HttpCache>,
http_client_provider: Arc<HttpClientProvider>,
sys: CliSys,
blob_store: Arc<BlobStore>,
progress_bar: Option<ProgressBar>,
allow_remote: bool,
@ -289,7 +291,6 @@ impl CliFileFetcher {
download_log_level: log::Level,
) -> Self {
let memory_files = Arc::new(MemoryFiles::default());
let sys = FsSysTraitsAdapter::new_real();
let auth_tokens = AuthTokens::new_from_sys(&sys);
let file_fetcher = DenoCacheDirFileFetcher::new(
BlobStoreAdapter(blob_store),
@ -538,13 +539,11 @@ mod tests {
let temp_dir = maybe_temp_dir.unwrap_or_default();
let location = temp_dir.path().join("remote").to_path_buf();
let blob_store: Arc<BlobStore> = Default::default();
let cache = Arc::new(GlobalHttpCache::new(
FsSysTraitsAdapter::new_real(),
location,
));
let cache = Arc::new(GlobalHttpCache::new(CliSys::default(), location));
let file_fetcher = CliFileFetcher::new(
cache.clone(),
Arc::new(HttpClientProvider::new(None, None)),
CliSys::default(),
blob_store.clone(),
None,
true,
@ -754,11 +753,9 @@ mod tests {
// invocation and indicates to "cache bust".
let location = temp_dir.path().join("remote").to_path_buf();
let file_fetcher = CliFileFetcher::new(
Arc::new(GlobalHttpCache::new(
FsSysTraitsAdapter::new_real(),
location,
)),
Arc::new(GlobalHttpCache::new(CliSys::default(), location)),
Arc::new(HttpClientProvider::new(None, None)),
CliSys::default(),
Default::default(),
None,
true,
@ -783,14 +780,13 @@ mod tests {
let specifier =
resolve_url("http://localhost:4545/subdir/mismatch_ext.ts").unwrap();
let http_cache = Arc::new(GlobalHttpCache::new(
FsSysTraitsAdapter::new_real(),
location.clone(),
));
let http_cache =
Arc::new(GlobalHttpCache::new(CliSys::default(), location.clone()));
let file_modified_01 = {
let file_fetcher = CliFileFetcher::new(
http_cache.clone(),
Arc::new(HttpClientProvider::new(None, None)),
CliSys::default(),
Default::default(),
None,
true,
@ -810,11 +806,9 @@ mod tests {
let file_modified_02 = {
let file_fetcher = CliFileFetcher::new(
Arc::new(GlobalHttpCache::new(
FsSysTraitsAdapter::new_real(),
location,
)),
Arc::new(GlobalHttpCache::new(CliSys::default(), location)),
Arc::new(HttpClientProvider::new(None, None)),
CliSys::default(),
Default::default(),
None,
true,
@ -940,15 +934,14 @@ mod tests {
resolve_url("http://localhost:4548/subdir/mismatch_ext.ts").unwrap();
let redirected_specifier =
resolve_url("http://localhost:4546/subdir/mismatch_ext.ts").unwrap();
let http_cache = Arc::new(GlobalHttpCache::new(
FsSysTraitsAdapter::new_real(),
location.clone(),
));
let http_cache =
Arc::new(GlobalHttpCache::new(CliSys::default(), location.clone()));
let metadata_file_modified_01 = {
let file_fetcher = CliFileFetcher::new(
http_cache.clone(),
Arc::new(HttpClientProvider::new(None, None)),
CliSys::default(),
Default::default(),
None,
true,
@ -971,6 +964,7 @@ mod tests {
let file_fetcher = CliFileFetcher::new(
http_cache.clone(),
Arc::new(HttpClientProvider::new(None, None)),
CliSys::default(),
Default::default(),
None,
true,
@ -1075,11 +1069,9 @@ mod tests {
let temp_dir = TempDir::new();
let location = temp_dir.path().join("remote").to_path_buf();
let file_fetcher = CliFileFetcher::new(
Arc::new(GlobalHttpCache::new(
FsSysTraitsAdapter::new_real(),
location,
)),
Arc::new(GlobalHttpCache::new(CliSys::default(), location)),
Arc::new(HttpClientProvider::new(None, None)),
CliSys::default(),
Default::default(),
None,
false,
@ -1113,11 +1105,9 @@ mod tests {
let temp_dir = TempDir::new();
let location = temp_dir.path().join("remote").to_path_buf();
let file_fetcher_01 = CliFileFetcher::new(
Arc::new(GlobalHttpCache::new(
FsSysTraitsAdapter::new_real(),
location.clone(),
)),
Arc::new(GlobalHttpCache::new(CliSys::default(), location.clone())),
Arc::new(HttpClientProvider::new(None, None)),
CliSys::default(),
Default::default(),
None,
true,
@ -1125,11 +1115,9 @@ mod tests {
log::Level::Info,
);
let file_fetcher_02 = CliFileFetcher::new(
Arc::new(GlobalHttpCache::new(
FsSysTraitsAdapter::new_real(),
location,
)),
Arc::new(GlobalHttpCache::new(CliSys::default(), location)),
Arc::new(HttpClientProvider::new(None, None)),
CliSys::default(),
Default::default(),
None,
true,

View file

@ -29,7 +29,6 @@ use deno_graph::SpecifierError;
use deno_graph::WorkspaceFastCheckOption;
use deno_path_util::url_to_file_path;
use deno_resolver::sloppy_imports::SloppyImportsResolutionKind;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use deno_runtime::deno_node;
use deno_runtime::deno_permissions::PermissionsContainer;
use deno_semver::jsr::JsrDepPackageReq;
@ -57,6 +56,7 @@ 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::TypeChecker;
use crate::util::file_watcher::WatcherCommunicator;
@ -81,7 +81,7 @@ pub struct GraphValidOptions {
/// for the CLI.
pub fn graph_valid(
graph: &ModuleGraph,
sys: &FsSysTraitsAdapter,
sys: &CliSys,
roots: &[ModuleSpecifier],
options: GraphValidOptions,
) -> Result<(), AnyError> {
@ -141,7 +141,7 @@ pub struct GraphWalkErrorsOptions {
/// and enhances them with CLI information.
pub fn graph_walk_errors<'a>(
graph: &'a ModuleGraph,
sys: &'a FsSysTraitsAdapter,
sys: &'a CliSys,
roots: &'a [ModuleSpecifier],
options: GraphWalkErrorsOptions,
) -> impl Iterator<Item = AnyError> + 'a {
@ -443,7 +443,7 @@ pub struct ModuleGraphBuilder {
parsed_source_cache: Arc<ParsedSourceCache>,
resolver: Arc<CliResolver>,
root_permissions_container: PermissionsContainer,
sys: FsSysTraitsAdapter,
sys: CliSys,
}
impl ModuleGraphBuilder {
@ -462,7 +462,7 @@ impl ModuleGraphBuilder {
parsed_source_cache: Arc<ParsedSourceCache>,
resolver: Arc<CliResolver>,
root_permissions_container: PermissionsContainer,
sys: FsSysTraitsAdapter,
sys: CliSys,
) -> Self {
Self {
caches,
@ -836,7 +836,7 @@ pub fn enhanced_resolution_error_message(error: &ResolutionError) -> String {
}
fn enhanced_sloppy_imports_error_message(
sys: &FsSysTraitsAdapter,
sys: &CliSys,
error: &ModuleError,
) -> Option<String> {
match error {

View file

@ -7,11 +7,11 @@ use crate::cache::LocalLspHttpCache;
use crate::lsp::config::Config;
use crate::lsp::logging::lsp_log;
use crate::lsp::logging::lsp_warn;
use crate::sys::CliSys;
use deno_core::url::Url;
use deno_core::ModuleSpecifier;
use deno_path_util::url_to_file_path;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use std::collections::BTreeMap;
use std::fs;
use std::path::Path;
@ -92,12 +92,11 @@ impl LspCache {
})
.ok()
});
let deno_dir = DenoDir::new(global_cache_path)
let sys = CliSys::default();
let deno_dir = DenoDir::new(sys.clone(), global_cache_path)
.expect("should be infallible with absolute custom root");
let global = Arc::new(GlobalHttpCache::new(
FsSysTraitsAdapter::new_real(),
deno_dir.remote_folder_path(),
));
let global =
Arc::new(GlobalHttpCache::new(sys, deno_dir.remote_folder_path()));
Self {
deno_dir,
global,

View file

@ -36,7 +36,6 @@ 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_runtime::deno_fs::FsSysTraitsAdapter;
use deno_runtime::deno_node::PackageJson;
use indexmap::IndexSet;
use lsp_types::ClientCapabilities;
@ -65,6 +64,7 @@ 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;
use crate::tools::lint::LintRuleProvider;
@ -1227,7 +1227,7 @@ impl ConfigData {
Ok(scope_dir_path) => {
let paths = [scope_dir_path];
WorkspaceDirectory::discover(
&FsSysTraitsAdapter::new_real(),
&CliSys::default(),
match specified_config {
Some(config_path) => {
deno_config::workspace::WorkspaceDiscoverStart::ConfigFile(
@ -1615,9 +1615,7 @@ impl ConfigData {
|| unstable.contains("sloppy-imports");
let sloppy_imports_resolver = unstable_sloppy_imports.then(|| {
Arc::new(CliSloppyImportsResolver::new(
SloppyImportsCachedFs::new_without_stat_cache(
FsSysTraitsAdapter::new_real(),
),
SloppyImportsCachedFs::new_without_stat_cache(CliSys::default()),
))
});
let resolver = Arc::new(resolver);
@ -1921,17 +1919,20 @@ impl ConfigTree {
#[cfg(test)]
pub async fn inject_config_file(&mut self, config_file: ConfigFile) {
use sys_traits::FsCreateDirAll;
use sys_traits::FsWrite;
let scope = config_file.specifier.join(".").unwrap();
let json_text = serde_json::to_string(&config_file.json).unwrap();
let test_fs = Arc::new(deno_runtime::deno_fs::InMemoryFs::default());
let memory_sys = sys_traits::impls::InMemorySys::default();
let config_path = url_to_file_path(&config_file.specifier).unwrap();
test_fs.setup_text_files(vec![(
config_path.to_string_lossy().to_string(),
json_text,
)]);
memory_sys
.fs_create_dir_all(config_path.parent().unwrap())
.unwrap();
memory_sys.fs_write(&config_path, json_text).unwrap();
let workspace_dir = Arc::new(
WorkspaceDirectory::discover(
&FsSysTraitsAdapter(test_fs.clone()),
&memory_sys,
deno_config::workspace::WorkspaceDiscoverStart::ConfigFile(
&config_path,
),
@ -2008,11 +2009,14 @@ fn resolve_lockfile_from_path(
lockfile_path: PathBuf,
frozen: bool,
) -> Option<CliLockfile> {
match CliLockfile::read_from_path(CliLockfileReadFromPathOptions {
file_path: lockfile_path,
frozen,
skip_write: false,
}) {
match CliLockfile::read_from_path(
&CliSys::default(),
CliLockfileReadFromPathOptions {
file_path: lockfile_path,
frozen,
skip_write: false,
},
) {
Ok(value) => {
if value.filename.exists() {
if let Ok(specifier) = ModuleSpecifier::from_file_path(&value.filename)

View file

@ -21,6 +21,7 @@ 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;
use crate::tools::lint::LintRuleProvider;
@ -48,7 +49,6 @@ use deno_graph::SpecifierError;
use deno_lint::linter::LintConfig as DenoLintConfig;
use deno_resolver::sloppy_imports::SloppyImportsResolution;
use deno_resolver::sloppy_imports::SloppyImportsResolutionKind;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use deno_runtime::deno_node;
use deno_runtime::tokio_util::create_basic_runtime;
use deno_semver::jsr::JsrPackageReqReference;
@ -1281,7 +1281,7 @@ impl DenoDiagnostic {
Self::NotInstalledNpm(pkg_req, specifier) => (lsp::DiagnosticSeverity::ERROR, format!("npm package \"{pkg_req}\" is not installed or doesn't exist."), Some(json!({ "specifier": specifier }))),
Self::NoLocal(specifier) => {
let maybe_sloppy_resolution = CliSloppyImportsResolver::new(
SloppyImportsCachedFs::new(FsSysTraitsAdapter::new_real())
SloppyImportsCachedFs::new(CliSys::default())
).resolve(specifier, SloppyImportsResolutionKind::Execution);
let data = maybe_sloppy_resolution.as_ref().map(|res| {
json!({

View file

@ -17,7 +17,6 @@ use deno_core::ModuleSpecifier;
use deno_graph::GraphKind;
use deno_graph::Resolution;
use deno_path_util::url_to_file_path;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use deno_runtime::deno_tls::rustls::RootCertStore;
use deno_runtime::deno_tls::RootCertStoreProvider;
use deno_semver::jsr::JsrPackageReqReference;
@ -109,6 +108,7 @@ use crate::lsp::config::ConfigWatchedFileType;
use crate::lsp::logging::init_log_file;
use crate::lsp::tsc::file_text_changes_to_workspace_edit;
use crate::lsp::urls::LspUrlKind;
use crate::sys::CliSys;
use crate::tools::fmt::format_file;
use crate::tools::fmt::format_parsed_source;
use crate::tools::upgrade::check_for_upgrades_for_lsp;
@ -280,7 +280,7 @@ impl LanguageServer {
.await?;
graph_util::graph_valid(
&graph,
&FsSysTraitsAdapter(factory.fs().clone()),
&CliSys::default(),
&roots,
graph_util::GraphValidOptions {
kind: GraphKind::All,
@ -962,6 +962,7 @@ impl Inner {
let file_fetcher = CliFileFetcher::new(
self.cache.global().clone(),
self.http_client_provider.clone(),
CliSys::default(),
Default::default(),
None,
true,
@ -3613,7 +3614,7 @@ impl Inner {
let workspace = match config_data {
Some(d) => d.member_dir.clone(),
None => Arc::new(WorkspaceDirectory::discover(
&FsSysTraitsAdapter::new_real(),
&CliSys::default(),
deno_config::workspace::WorkspaceDiscoverStart::Paths(&[
initial_cwd.clone()
]),
@ -3634,6 +3635,7 @@ impl Inner {
)?),
};
let cli_options = CliOptions::new(
&CliSys::default(),
Arc::new(Flags {
internal: InternalFlags {
cache_path: Some(self.cache.deno_dir().root.clone()),

View file

@ -19,6 +19,7 @@ use crate::file_fetcher::FetchOptions;
use crate::file_fetcher::FetchPermissionsOptionRef;
use crate::file_fetcher::TextDecodedFile;
use crate::http_util::HttpClientProvider;
use crate::sys::CliSys;
use deno_cache_dir::file_fetcher::CacheSetting;
use deno_core::anyhow::anyhow;
@ -32,7 +33,6 @@ use deno_core::url::Position;
use deno_core::url::Url;
use deno_core::ModuleSpecifier;
use deno_graph::Dependency;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use log::error;
use once_cell::sync::Lazy;
use std::borrow::Cow;
@ -430,13 +430,12 @@ impl ModuleRegistry {
http_client_provider: Arc<HttpClientProvider>,
) -> Self {
// the http cache should always be the global one for registry completions
let http_cache = Arc::new(GlobalHttpCache::new(
FsSysTraitsAdapter::new_real(),
location.clone(),
));
let http_cache =
Arc::new(GlobalHttpCache::new(CliSys::default(), location.clone()));
let file_fetcher = CliFileFetcher::new(
http_cache.clone(),
http_client_provider,
CliSys::default(),
Default::default(),
None,
true,

View file

@ -19,9 +19,6 @@ use deno_resolver::cjs::IsCjsResolutionMode;
use deno_resolver::npm::NpmReqResolverOptions;
use deno_resolver::DenoResolverOptions;
use deno_resolver::NodeAndNpmReqResolver;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use deno_runtime::deno_node::NodeResolver;
use deno_runtime::deno_node::PackageJsonResolver;
use deno_runtime::deno_node::RealIsBuiltInNodeModuleChecker;
use deno_semver::jsr::JsrPackageReqReference;
use deno_semver::npm::NpmPackageReqReference;
@ -51,6 +48,8 @@ use crate::http_util::HttpClientProvider;
use crate::lsp::config::Config;
use crate::lsp::config::ConfigData;
use crate::lsp::logging::lsp_warn;
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;
@ -66,6 +65,7 @@ use crate::resolver::CliResolver;
use crate::resolver::CliResolverOptions;
use crate::resolver::IsCjsResolver;
use crate::resolver::WorkerCliNpmGraphResolver;
use crate::sys::CliSys;
use crate::tsc::into_specifier_and_media_type;
use crate::util::progress_bar::ProgressBar;
use crate::util::progress_bar::ProgressBarStyle;
@ -77,9 +77,9 @@ struct LspScopeResolver {
is_cjs_resolver: Arc<IsCjsResolver>,
jsr_resolver: Option<Arc<JsrCacheResolver>>,
npm_resolver: Option<Arc<dyn CliNpmResolver>>,
node_resolver: Option<Arc<NodeResolver>>,
node_resolver: Option<Arc<CliNodeResolver>>,
npm_pkg_req_resolver: Option<Arc<CliNpmReqResolver>>,
pkg_json_resolver: Arc<PackageJsonResolver>,
pkg_json_resolver: Arc<CliPackageJsonResolver>,
redirect_resolver: Option<Arc<RedirectResolver>>,
graph_imports: Arc<IndexMap<ModuleSpecifier, GraphImport>>,
dep_info: Arc<Mutex<Arc<ScopeDepInfo>>>,
@ -383,7 +383,7 @@ impl LspResolver {
pub fn pkg_json_resolver(
&self,
referrer: &ModuleSpecifier,
) -> &Arc<PackageJsonResolver> {
) -> &Arc<CliPackageJsonResolver> {
let resolver = self.get_scope_resolver(Some(referrer));
&resolver.pkg_json_resolver
}
@ -591,22 +591,22 @@ struct ResolverFactoryServices {
cli_resolver: Deferred<Arc<CliResolver>>,
in_npm_pkg_checker: Deferred<Arc<dyn InNpmPackageChecker>>,
is_cjs_resolver: Deferred<Arc<IsCjsResolver>>,
node_resolver: Deferred<Option<Arc<NodeResolver>>>,
node_resolver: Deferred<Option<Arc<CliNodeResolver>>>,
npm_pkg_req_resolver: Deferred<Option<Arc<CliNpmReqResolver>>>,
npm_resolver: Option<Arc<dyn CliNpmResolver>>,
}
struct ResolverFactory<'a> {
config_data: Option<&'a Arc<ConfigData>>,
pkg_json_resolver: Arc<PackageJsonResolver>,
sys: FsSysTraitsAdapter,
pkg_json_resolver: Arc<CliPackageJsonResolver>,
sys: CliSys,
services: ResolverFactoryServices,
}
impl<'a> ResolverFactory<'a> {
pub fn new(config_data: Option<&'a Arc<ConfigData>>) -> Self {
let sys = FsSysTraitsAdapter::new_real();
let pkg_json_resolver = Arc::new(PackageJsonResolver::new(sys.clone()));
let sys = CliSys::default();
let pkg_json_resolver = Arc::new(CliPackageJsonResolver::new(sys.clone()));
Self {
config_data,
pkg_json_resolver,
@ -621,7 +621,7 @@ impl<'a> ResolverFactory<'a> {
cache: &LspCache,
) {
let enable_byonm = self.config_data.map(|d| d.byonm).unwrap_or(false);
let sys = FsSysTraitsAdapter::new_real();
let sys = CliSys::default();
let options = if enable_byonm {
CliNpmResolverCreateOptions::Byonm(CliByonmNpmResolverCreateOptions {
sys,
@ -656,7 +656,7 @@ impl<'a> ResolverFactory<'a> {
}
None => CliNpmResolverManagedSnapshotOption::Specified(None),
},
sys: FsSysTraitsAdapter::new_real(),
sys: CliSys::default(),
npm_cache_dir,
// Use an "only" cache setting in order to make the
// user do an explicit "cache" command and prevent
@ -729,7 +729,7 @@ impl<'a> ResolverFactory<'a> {
})
}
pub fn pkg_json_resolver(&self) -> &Arc<PackageJsonResolver> {
pub fn pkg_json_resolver(&self) -> &Arc<CliPackageJsonResolver> {
&self.pkg_json_resolver
}
@ -770,13 +770,13 @@ impl<'a> ResolverFactory<'a> {
})
}
pub fn node_resolver(&self) -> Option<&Arc<NodeResolver>> {
pub fn node_resolver(&self) -> Option<&Arc<CliNodeResolver>> {
self
.services
.node_resolver
.get_or_init(|| {
let npm_resolver = self.services.npm_resolver.as_ref()?;
Some(Arc::new(NodeResolver::new(
Some(Arc::new(CliNodeResolver::new(
self.in_npm_pkg_checker().clone(),
RealIsBuiltInNodeModuleChecker,
npm_resolver.clone().into_npm_pkg_folder_resolver(),

View file

@ -20,6 +20,7 @@ mod ops;
mod resolver;
mod shared;
mod standalone;
mod sys;
mod task_runner;
mod tools;
mod tsc;

View file

@ -18,6 +18,7 @@ mod node;
mod npm;
mod resolver;
mod shared;
mod sys;
mod task_runner;
mod util;
mod version;
@ -31,11 +32,13 @@ use deno_runtime::tokio_util::create_and_run_current_thread_with_maybe_metrics;
pub use deno_runtime::UNSTABLE_GRANULAR_FLAGS;
use deno_terminal::colors;
use indexmap::IndexMap;
use standalone::DenoCompileFileSystem;
use std::borrow::Cow;
use std::collections::HashMap;
use std::env;
use std::env::current_exe;
use std::sync::Arc;
use crate::args::Flags;
@ -92,7 +95,9 @@ fn main() {
Some(data.metadata.otel_config.clone()),
);
load_env_vars(&data.metadata.env_vars_from_env_file);
let exit_code = standalone::run(data).await?;
let fs = DenoCompileFileSystem::new(data.vfs.clone());
let sys = crate::sys::CliSys::DenoCompile(fs.clone());
let exit_code = standalone::run(Arc::new(fs), sys, data).await?;
deno_runtime::exit(exit_code);
}
Ok(None) => Ok(()),

View file

@ -11,6 +11,8 @@ use std::sync::atomic::AtomicU16;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use crate::node::CliNodeResolver;
use crate::sys::CliSys;
use deno_ast::MediaType;
use deno_ast::ModuleKind;
use deno_core::anyhow::anyhow;
@ -39,10 +41,8 @@ use deno_graph::ModuleGraph;
use deno_graph::Resolution;
use deno_graph::WasmModule;
use deno_runtime::code_cache;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use deno_runtime::deno_node::create_host_defined_options;
use deno_runtime::deno_node::NodeRequireLoader;
use deno_runtime::deno_node::NodeResolver;
use deno_runtime::deno_permissions::PermissionsContainer;
use deno_semver::npm::NpmPackageReqReference;
use node_resolver::errors::ClosestPkgJsonError;
@ -220,13 +220,13 @@ struct SharedCliModuleLoaderState {
main_module_graph_container: Arc<MainModuleGraphContainer>,
module_load_preparer: Arc<ModuleLoadPreparer>,
node_code_translator: Arc<CliNodeCodeTranslator>,
node_resolver: Arc<NodeResolver>,
node_resolver: Arc<CliNodeResolver>,
npm_req_resolver: Arc<CliNpmReqResolver>,
npm_resolver: Arc<dyn CliNpmResolver>,
npm_module_loader: NpmModuleLoader,
parsed_source_cache: Arc<ParsedSourceCache>,
resolver: Arc<CliResolver>,
sys: FsSysTraitsAdapter,
sys: CliSys,
in_flight_loads_tracker: InFlightModuleLoadsTracker,
}
@ -280,13 +280,13 @@ impl CliModuleLoaderFactory {
main_module_graph_container: Arc<MainModuleGraphContainer>,
module_load_preparer: Arc<ModuleLoadPreparer>,
node_code_translator: Arc<CliNodeCodeTranslator>,
node_resolver: Arc<NodeResolver>,
node_resolver: Arc<CliNodeResolver>,
npm_req_resolver: Arc<CliNpmReqResolver>,
npm_resolver: Arc<dyn CliNpmResolver>,
npm_module_loader: NpmModuleLoader,
parsed_source_cache: Arc<ParsedSourceCache>,
resolver: Arc<CliResolver>,
sys: FsSysTraitsAdapter,
sys: CliSys,
) -> Self {
Self {
shared: Arc::new(SharedCliModuleLoaderState {
@ -1092,7 +1092,7 @@ impl ModuleGraphUpdatePermit for WorkerModuleGraphUpdatePermit {
struct CliNodeRequireLoader<TGraphContainer: ModuleGraphContainer> {
cjs_tracker: Arc<CjsTracker>,
emitter: Arc<Emitter>,
sys: FsSysTraitsAdapter,
sys: CliSys,
graph_container: TGraphContainer,
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
npm_resolver: Arc<dyn CliNpmResolver>,

View file

@ -8,7 +8,6 @@ use deno_ast::ModuleSpecifier;
use deno_core::error::AnyError;
use deno_graph::ParsedSourceStore;
use deno_runtime::deno_fs;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use deno_runtime::deno_node::RealIsBuiltInNodeModuleChecker;
use node_resolver::analyze::CjsAnalysis as ExtNodeCjsAnalysis;
use node_resolver::analyze::CjsAnalysisExports;
@ -21,12 +20,15 @@ use crate::cache::CacheDBHash;
use crate::cache::NodeAnalysisCache;
use crate::cache::ParsedSourceCache;
use crate::resolver::CjsTracker;
use crate::sys::CliSys;
pub type CliNodeCodeTranslator = NodeCodeTranslator<
CliCjsCodeAnalyzer,
RealIsBuiltInNodeModuleChecker,
FsSysTraitsAdapter,
CliSys,
>;
pub type CliNodeResolver = deno_runtime::deno_node::NodeResolver<CliSys>;
pub type CliPackageJsonResolver = node_resolver::PackageJsonResolver<CliSys>;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum CliCjsAnalysis {

View file

@ -4,12 +4,12 @@ use std::borrow::Cow;
use std::path::Path;
use std::sync::Arc;
use crate::sys::CliSys;
use deno_core::error::AnyError;
use deno_core::serde_json;
use deno_resolver::npm::ByonmNpmResolver;
use deno_resolver::npm::ByonmNpmResolverCreateOptions;
use deno_resolver::npm::CliNpmReqResolver;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use deno_runtime::deno_node::NodePermissions;
use deno_runtime::ops::process::NpmProcessStateProvider;
use node_resolver::NpmPackageFolderResolver;
@ -21,8 +21,8 @@ use super::CliNpmResolver;
use super::InnerCliNpmResolverRef;
pub type CliByonmNpmResolverCreateOptions =
ByonmNpmResolverCreateOptions<FsSysTraitsAdapter>;
pub type CliByonmNpmResolver = ByonmNpmResolver<FsSysTraitsAdapter>;
ByonmNpmResolverCreateOptions<CliSys>;
pub type CliByonmNpmResolver = ByonmNpmResolver<CliSys>;
// todo(dsherret): the services hanging off `CliNpmResolver` doesn't seem ideal. We should probably decouple.
#[derive(Debug)]

View file

@ -5,6 +5,7 @@ use std::path::Path;
use std::path::PathBuf;
use std::sync::Arc;
use crate::sys::CliSys;
use deno_ast::ModuleSpecifier;
use deno_cache_dir::npm::NpmCacheDir;
use deno_core::anyhow::Context;
@ -24,7 +25,6 @@ use deno_npm_cache::NpmCacheSetting;
use deno_path_util::fs::canonicalize_path_maybe_not_exists;
use deno_resolver::npm::CliNpmReqResolver;
use deno_runtime::colors;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use deno_runtime::deno_node::NodePermissions;
use deno_runtime::ops::process::NpmProcessStateProvider;
use deno_semver::package::PackageNv;
@ -70,7 +70,7 @@ pub struct CliManagedNpmResolverCreateOptions {
pub maybe_lockfile: Option<Arc<CliLockfile>>,
pub http_client_provider: Arc<crate::http_util::HttpClientProvider>,
pub npm_cache_dir: Arc<NpmCacheDir>,
pub sys: FsSysTraitsAdapter,
pub sys: CliSys,
pub cache_setting: deno_cache_dir::file_fetcher::CacheSetting,
pub text_only_progress_bar: crate::util::progress_bar::ProgressBar,
pub maybe_node_modules_path: Option<PathBuf>,
@ -149,7 +149,7 @@ fn create_inner(
npm_cache: Arc<CliNpmCache>,
npm_install_deps_provider: Arc<NpmInstallDepsProvider>,
registry_info_provider: Arc<CliNpmRegistryInfoProvider>,
sys: FsSysTraitsAdapter,
sys: CliSys,
text_only_progress_bar: crate::util::progress_bar::ProgressBar,
maybe_lockfile: Option<Arc<CliLockfile>>,
npm_rc: Arc<ResolvedNpmRc>,
@ -307,7 +307,7 @@ pub struct ManagedCliNpmResolver {
registry_info_provider: Arc<CliNpmRegistryInfoProvider>,
npm_cache: Arc<CliNpmCache>,
npm_install_deps_provider: Arc<NpmInstallDepsProvider>,
sys: FsSysTraitsAdapter,
sys: CliSys,
resolution: Arc<NpmResolution>,
tarball_cache: Arc<CliNpmTarballCache>,
text_only_progress_bar: ProgressBar,
@ -333,7 +333,7 @@ impl ManagedCliNpmResolver {
npm_cache: Arc<CliNpmCache>,
npm_install_deps_provider: Arc<NpmInstallDepsProvider>,
resolution: Arc<NpmResolution>,
sys: FsSysTraitsAdapter,
sys: CliSys,
tarball_cache: Arc<CliNpmTarballCache>,
text_only_progress_bar: ProgressBar,
npm_system_info: NpmSystemInfo,

View file

@ -20,13 +20,13 @@ use deno_core::futures::StreamExt;
use deno_npm::NpmPackageCacheFolderId;
use deno_npm::NpmPackageId;
use deno_npm::NpmResolutionPackage;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use deno_runtime::deno_node::NodePermissions;
use node_resolver::errors::PackageFolderResolveError;
use sys_traits::FsCanonicalize;
use super::super::PackageCaching;
use crate::npm::CliNpmTarballCache;
use crate::sys::CliSys;
/// Part of the resolution that interacts with the file system.
#[async_trait(?Send)]
@ -74,15 +74,15 @@ pub trait NpmPackageFsResolver: Send + Sync {
#[derive(Debug)]
pub struct RegistryReadPermissionChecker {
sys: FsSysTraitsAdapter,
sys: CliSys,
cache: Mutex<HashMap<PathBuf, PathBuf>>,
registry_path: PathBuf,
}
impl RegistryReadPermissionChecker {
pub fn new(fs: FsSysTraitsAdapter, registry_path: PathBuf) -> Self {
pub fn new(sys: CliSys, registry_path: PathBuf) -> Self {
Self {
sys: fs,
sys,
registry_path,
cache: Default::default(),
}

View file

@ -11,6 +11,7 @@ use crate::colors;
use crate::npm::managed::PackageCaching;
use crate::npm::CliNpmCache;
use crate::npm::CliNpmTarballCache;
use crate::sys::CliSys;
use async_trait::async_trait;
use deno_ast::ModuleSpecifier;
use deno_core::error::AnyError;
@ -18,7 +19,6 @@ use deno_npm::NpmPackageCacheFolderId;
use deno_npm::NpmPackageId;
use deno_npm::NpmResolutionPackage;
use deno_npm::NpmSystemInfo;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use deno_runtime::deno_node::NodePermissions;
use node_resolver::errors::PackageFolderResolveError;
use node_resolver::errors::PackageNotFoundError;
@ -49,7 +49,7 @@ impl GlobalNpmPackageResolver {
cache: Arc<CliNpmCache>,
tarball_cache: Arc<CliNpmTarballCache>,
resolution: Arc<NpmResolution>,
sys: FsSysTraitsAdapter,
sys: CliSys,
system_info: NpmSystemInfo,
lifecycle_scripts: LifecycleScriptsConfig,
) -> Self {

View file

@ -32,7 +32,6 @@ use deno_npm::NpmSystemInfo;
use deno_path_util::fs::atomic_write_file_with_retries;
use deno_path_util::fs::canonicalize_path_maybe_not_exists;
use deno_resolver::npm::normalize_pkg_name_for_node_modules_deno_folder;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use deno_runtime::deno_node::NodePermissions;
use deno_semver::package::PackageNv;
use deno_semver::StackString;
@ -51,6 +50,7 @@ use crate::colors;
use crate::npm::managed::PackageCaching;
use crate::npm::CliNpmCache;
use crate::npm::CliNpmTarballCache;
use crate::sys::CliSys;
use crate::util::fs::clone_dir_recursive;
use crate::util::fs::symlink_dir;
use crate::util::fs::LaxSingleProcessFsFlag;
@ -70,7 +70,7 @@ pub struct LocalNpmPackageResolver {
npm_install_deps_provider: Arc<NpmInstallDepsProvider>,
progress_bar: ProgressBar,
resolution: Arc<NpmResolution>,
sys: FsSysTraitsAdapter,
sys: CliSys,
tarball_cache: Arc<CliNpmTarballCache>,
root_node_modules_path: PathBuf,
root_node_modules_url: Url,
@ -86,7 +86,7 @@ impl LocalNpmPackageResolver {
npm_install_deps_provider: Arc<NpmInstallDepsProvider>,
progress_bar: ProgressBar,
resolution: Arc<NpmResolution>,
sys: FsSysTraitsAdapter,
sys: CliSys,
tarball_cache: Arc<CliNpmTarballCache>,
node_modules_folder: PathBuf,
system_info: NpmSystemInfo,
@ -926,7 +926,7 @@ impl SetupCache {
bincode::serialize(&self.current).ok().and_then(|data| {
atomic_write_file_with_retries(
&FsSysTraitsAdapter::new_real(),
&CliSys::default(),
&self.file_path,
&data,
CACHE_PERM,

View file

@ -7,8 +7,8 @@ mod local;
use std::path::PathBuf;
use std::sync::Arc;
use crate::sys::CliSys;
use deno_npm::NpmSystemInfo;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use crate::args::LifecycleScriptsConfig;
use crate::args::NpmInstallDepsProvider;
@ -29,7 +29,7 @@ pub fn create_npm_fs_resolver(
npm_install_deps_provider: &Arc<NpmInstallDepsProvider>,
progress_bar: &ProgressBar,
resolution: Arc<NpmResolution>,
sys: FsSysTraitsAdapter,
sys: CliSys,
tarball_cache: Arc<CliNpmTarballCache>,
maybe_node_modules_path: Option<PathBuf>,
system_info: NpmSystemInfo,

View file

@ -7,6 +7,7 @@ use std::borrow::Cow;
use std::path::Path;
use std::sync::Arc;
use crate::sys::CliSys;
use dashmap::DashMap;
use deno_core::error::AnyError;
use deno_core::serde_json;
@ -17,7 +18,6 @@ use deno_resolver::npm::ByonmInNpmPackageChecker;
use deno_resolver::npm::ByonmNpmResolver;
use deno_resolver::npm::CliNpmReqResolver;
use deno_resolver::npm::ResolvePkgFolderFromDenoReqError;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use deno_runtime::deno_node::NodePermissions;
use deno_runtime::ops::process::NpmProcessStateProvider;
use deno_semver::package::PackageNv;
@ -41,12 +41,10 @@ pub use self::managed::ManagedCliNpmResolver;
pub use self::managed::PackageCaching;
pub type CliNpmTarballCache =
deno_npm_cache::TarballCache<CliNpmCacheHttpClient, FsSysTraitsAdapter>;
pub type CliNpmCache = deno_npm_cache::NpmCache<FsSysTraitsAdapter>;
pub type CliNpmRegistryInfoProvider = deno_npm_cache::RegistryInfoProvider<
CliNpmCacheHttpClient,
FsSysTraitsAdapter,
>;
deno_npm_cache::TarballCache<CliNpmCacheHttpClient, CliSys>;
pub type CliNpmCache = deno_npm_cache::NpmCache<CliSys>;
pub type CliNpmRegistryInfoProvider =
deno_npm_cache::RegistryInfoProvider<CliNpmCacheHttpClient, CliSys>;
#[derive(Debug)]
pub struct CliNpmCacheHttpClient {

View file

@ -5,6 +5,7 @@ use std::path::Path;
use std::path::PathBuf;
use std::sync::Arc;
use crate::sys::CliSys;
use async_trait::async_trait;
use dashmap::DashMap;
use dashmap::DashSet;
@ -25,7 +26,6 @@ use deno_npm::resolution::NpmResolutionError;
use deno_resolver::sloppy_imports::SloppyImportsResolver;
use deno_runtime::colors;
use deno_runtime::deno_fs;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use deno_runtime::deno_node::is_builtin_node_module;
use deno_runtime::deno_node::RealIsBuiltInNodeModuleChecker;
use deno_semver::package::PackageReq;
@ -43,19 +43,17 @@ use crate::npm::InnerCliNpmResolverRef;
use crate::util::sync::AtomicFlag;
use crate::util::text_encoding::from_utf8_lossy_cow;
pub type CjsTracker = deno_resolver::cjs::CjsTracker<FsSysTraitsAdapter>;
pub type IsCjsResolver = deno_resolver::cjs::IsCjsResolver<FsSysTraitsAdapter>;
pub type CjsTracker = deno_resolver::cjs::CjsTracker<CliSys>;
pub type IsCjsResolver = deno_resolver::cjs::IsCjsResolver<CliSys>;
pub type CliSloppyImportsResolver =
SloppyImportsResolver<SloppyImportsCachedFs>;
pub type CliDenoResolver = deno_resolver::DenoResolver<
RealIsBuiltInNodeModuleChecker,
SloppyImportsCachedFs,
FsSysTraitsAdapter,
>;
pub type CliNpmReqResolver = deno_resolver::npm::NpmReqResolver<
RealIsBuiltInNodeModuleChecker,
FsSysTraitsAdapter,
CliSys,
>;
pub type CliNpmReqResolver =
deno_resolver::npm::NpmReqResolver<RealIsBuiltInNodeModuleChecker, CliSys>;
pub struct ModuleCodeStringSource {
pub code: ModuleSourceCode,
@ -397,7 +395,7 @@ impl<'a> deno_graph::source::NpmResolver for WorkerCliNpmGraphResolver<'a> {
#[derive(Debug)]
pub struct SloppyImportsCachedFs {
sys: FsSysTraitsAdapter,
sys: CliSys,
cache: Option<
DashMap<
PathBuf,
@ -407,14 +405,14 @@ pub struct SloppyImportsCachedFs {
}
impl SloppyImportsCachedFs {
pub fn new(sys: FsSysTraitsAdapter) -> Self {
pub fn new(sys: CliSys) -> Self {
Self {
sys,
cache: Some(Default::default()),
}
}
pub fn new_without_stat_cache(fs: FsSysTraitsAdapter) -> Self {
pub fn new_without_stat_cache(fs: CliSys) -> Self {
Self {
sys: fs,
cache: None,

View file

@ -259,7 +259,6 @@ pub fn is_standalone_binary(exe_path: &Path) -> bool {
}
pub struct StandaloneData {
pub fs: Arc<dyn deno_fs::FileSystem>,
pub metadata: Metadata,
pub modules: StandaloneModules,
pub npm_snapshot: Option<ValidSerializedNpmResolutionSnapshot>,
@ -382,10 +381,7 @@ pub fn extract_standalone(
};
Arc::new(FileBackedVfs::new(Cow::Borrowed(vfs_files_data), fs_root))
};
let fs: Arc<dyn deno_fs::FileSystem> =
Arc::new(DenoCompileFileSystem::new(vfs.clone()));
Ok(Some(StandaloneData {
fs,
metadata,
modules: StandaloneModules {
remote_modules,

View file

@ -18,7 +18,6 @@ use deno_core::unsync::sync::AtomicFlag;
use deno_path_util::get_atomic_path;
use deno_runtime::code_cache::CodeCache;
use deno_runtime::code_cache::CodeCacheType;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use crate::cache::FastInsecureHasher;
use crate::worker::CliCodeCache;
@ -191,7 +190,7 @@ impl FirstRunCodeCacheStrategy {
) {
let count = cache_data.len();
let temp_file =
get_atomic_path(&FsSysTraitsAdapter::new_real(), &self.file_path);
get_atomic_path(&sys_traits::impls::RealSys, &self.file_path);
match serialize(&temp_file, self.cache_key, cache_data) {
Ok(()) => {
if let Err(err) = std::fs::rename(&temp_file, &self.file_path) {

View file

@ -1,23 +1,34 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use std::borrow::Cow;
use std::io::ErrorKind;
use std::path::Path;
use std::path::PathBuf;
use std::rc::Rc;
use std::sync::Arc;
use std::time::Duration;
use std::time::SystemTime;
use deno_runtime::deno_fs::AccessCheckCb;
use deno_runtime::deno_fs::FileSystem;
use deno_runtime::deno_fs::FsDirEntry;
use deno_runtime::deno_fs::FsFileType;
use deno_runtime::deno_fs::FsStatSlim;
use deno_runtime::deno_fs::OpenOptions;
use deno_runtime::deno_fs::RealFs;
use deno_runtime::deno_io::fs::File;
use deno_runtime::deno_io::fs::FsError;
use deno_runtime::deno_io::fs::FsResult;
use deno_runtime::deno_io::fs::FsStat;
use sys_traits::boxed::BoxedFsDirEntry;
use sys_traits::boxed::BoxedFsMetadataValue;
use sys_traits::boxed::FsMetadataBoxed;
use sys_traits::boxed::FsReadDirBoxed;
use sys_traits::FsMetadata;
use super::virtual_fs::FileBackedVfs;
use super::virtual_fs::FileBackedVfsDirEntry;
use super::virtual_fs::FileBackedVfsFile;
use super::virtual_fs::FileBackedVfsMetadata;
use super::virtual_fs::VfsFileSubDataKind;
#[derive(Debug, Clone)]
@ -83,7 +94,7 @@ impl FileSystem for DenoCompileFileSystem {
access_check: Option<AccessCheckCb>,
) -> FsResult<Rc<dyn File>> {
if self.0.is_path_within(path) {
Ok(self.0.open_file(path)?)
Ok(Rc::new(self.0.open_file(path)?))
} else {
RealFs.open_sync(path, options, access_check)
}
@ -95,7 +106,7 @@ impl FileSystem for DenoCompileFileSystem {
access_check: Option<AccessCheckCb<'a>>,
) -> FsResult<Rc<dyn File>> {
if self.0.is_path_within(&path) {
Ok(self.0.open_file(&path)?)
Ok(Rc::new(self.0.open_file(&path)?))
} else {
RealFs.open_async(path, options, access_check).await
}
@ -215,14 +226,14 @@ impl FileSystem for DenoCompileFileSystem {
fn stat_sync(&self, path: &Path) -> FsResult<FsStat> {
if self.0.is_path_within(path) {
Ok(self.0.stat(path)?)
Ok(self.0.stat(path)?.as_fs_stat())
} else {
RealFs.stat_sync(path)
}
}
async fn stat_async(&self, path: PathBuf) -> FsResult<FsStat> {
if self.0.is_path_within(&path) {
Ok(self.0.stat(&path)?)
Ok(self.0.stat(&path)?.as_fs_stat())
} else {
RealFs.stat_async(path).await
}
@ -230,14 +241,14 @@ impl FileSystem for DenoCompileFileSystem {
fn lstat_sync(&self, path: &Path) -> FsResult<FsStat> {
if self.0.is_path_within(path) {
Ok(self.0.lstat(path)?)
Ok(self.0.lstat(path)?.as_fs_stat())
} else {
RealFs.lstat_sync(path)
}
}
async fn lstat_async(&self, path: PathBuf) -> FsResult<FsStat> {
if self.0.is_path_within(&path) {
Ok(self.0.lstat(&path)?)
Ok(self.0.lstat(&path)?.as_fs_stat())
} else {
RealFs.lstat_async(path).await
}
@ -398,3 +409,428 @@ impl FileSystem for DenoCompileFileSystem {
.await
}
}
impl sys_traits::BaseFsHardLink for DenoCompileFileSystem {
#[inline]
fn base_fs_hard_link(&self, src: &Path, dst: &Path) -> std::io::Result<()> {
self.link_sync(src, dst).map_err(|err| err.into_io_error())
}
}
impl sys_traits::BaseFsRead for DenoCompileFileSystem {
#[inline]
fn base_fs_read(&self, path: &Path) -> std::io::Result<Cow<'static, [u8]>> {
self
.read_file_sync(path, None)
.map_err(|err| err.into_io_error())
}
}
impl sys_traits::FsMetadataValue for FileBackedVfsMetadata {
fn file_type(&self) -> sys_traits::FileType {
self.file_type
}
fn len(&self) -> u64 {
self.len
}
fn accessed(&self) -> std::io::Result<SystemTime> {
Err(not_supported("accessed time"))
}
fn created(&self) -> std::io::Result<SystemTime> {
Err(not_supported("created time"))
}
fn changed(&self) -> std::io::Result<SystemTime> {
Err(not_supported("changed time"))
}
fn modified(&self) -> std::io::Result<SystemTime> {
Err(not_supported("modified time"))
}
fn dev(&self) -> std::io::Result<u64> {
Ok(0)
}
fn ino(&self) -> std::io::Result<u64> {
Ok(0)
}
fn mode(&self) -> std::io::Result<u32> {
Ok(0)
}
fn nlink(&self) -> std::io::Result<u64> {
Ok(0)
}
fn uid(&self) -> std::io::Result<u32> {
Ok(0)
}
fn gid(&self) -> std::io::Result<u32> {
Ok(0)
}
fn rdev(&self) -> std::io::Result<u64> {
Ok(0)
}
fn blksize(&self) -> std::io::Result<u64> {
Ok(0)
}
fn blocks(&self) -> std::io::Result<u64> {
Ok(0)
}
fn is_block_device(&self) -> std::io::Result<bool> {
Ok(false)
}
fn is_char_device(&self) -> std::io::Result<bool> {
Ok(false)
}
fn is_fifo(&self) -> std::io::Result<bool> {
Ok(false)
}
fn is_socket(&self) -> std::io::Result<bool> {
Ok(false)
}
fn file_attributes(&self) -> std::io::Result<u32> {
Ok(0)
}
}
fn not_supported(name: &str) -> std::io::Error {
std::io::Error::new(
ErrorKind::Unsupported,
format!(
"{} is not supported for an embedded deno compile file",
name
),
)
}
impl sys_traits::FsDirEntry for FileBackedVfsDirEntry {
type Metadata = BoxedFsMetadataValue;
fn file_name(&self) -> Cow<std::ffi::OsStr> {
Cow::Borrowed(self.metadata.name.as_ref())
}
fn file_type(&self) -> std::io::Result<sys_traits::FileType> {
Ok(self.metadata.file_type)
}
fn metadata(&self) -> std::io::Result<Self::Metadata> {
Ok(BoxedFsMetadataValue(Box::new(self.metadata.clone())))
}
fn path(&self) -> Cow<Path> {
Cow::Owned(self.parent_path.join(&self.metadata.name))
}
}
impl sys_traits::BaseFsReadDir for DenoCompileFileSystem {
type ReadDirEntry = BoxedFsDirEntry;
fn base_fs_read_dir(
&self,
path: &Path,
) -> std::io::Result<
Box<dyn Iterator<Item = std::io::Result<Self::ReadDirEntry>> + '_>,
> {
if self.0.is_path_within(path) {
let entries = self.0.read_dir_with_metadata(path)?;
Ok(Box::new(
entries.map(|entry| Ok(BoxedFsDirEntry::new(entry))),
))
} else {
#[allow(clippy::disallowed_types)] // ok because we're implementing the fs
sys_traits::impls::RealSys.fs_read_dir_boxed(path)
}
}
}
impl sys_traits::BaseFsCanonicalize for DenoCompileFileSystem {
#[inline]
fn base_fs_canonicalize(&self, path: &Path) -> std::io::Result<PathBuf> {
self.realpath_sync(path).map_err(|err| err.into_io_error())
}
}
impl sys_traits::BaseFsMetadata for DenoCompileFileSystem {
type Metadata = BoxedFsMetadataValue;
#[inline]
fn base_fs_metadata(&self, path: &Path) -> std::io::Result<Self::Metadata> {
if self.0.is_path_within(path) {
Ok(BoxedFsMetadataValue::new(self.0.stat(path)?))
} else {
#[allow(clippy::disallowed_types)] // ok because we're implementing the fs
sys_traits::impls::RealSys.fs_metadata_boxed(path)
}
}
#[inline]
fn base_fs_symlink_metadata(
&self,
path: &Path,
) -> std::io::Result<Self::Metadata> {
if self.0.is_path_within(path) {
Ok(BoxedFsMetadataValue::new(self.0.lstat(path)?))
} else {
#[allow(clippy::disallowed_types)] // ok because we're implementing the fs
sys_traits::impls::RealSys.fs_symlink_metadata_boxed(path)
}
}
}
impl sys_traits::BaseFsCreateDir for DenoCompileFileSystem {
#[inline]
fn base_fs_create_dir(
&self,
path: &Path,
options: &sys_traits::CreateDirOptions,
) -> std::io::Result<()> {
self
.mkdir_sync(path, options.recursive, options.mode)
.map_err(|err| err.into_io_error())
}
}
impl sys_traits::BaseFsRemoveFile for DenoCompileFileSystem {
#[inline]
fn base_fs_remove_file(&self, path: &Path) -> std::io::Result<()> {
self
.remove_sync(path, false)
.map_err(|err| err.into_io_error())
}
}
impl sys_traits::BaseFsRename for DenoCompileFileSystem {
#[inline]
fn base_fs_rename(&self, from: &Path, to: &Path) -> std::io::Result<()> {
self
.rename_sync(from, to)
.map_err(|err| err.into_io_error())
}
}
pub enum FsFileAdapter {
Real(sys_traits::impls::RealFsFile),
Vfs(FileBackedVfsFile),
}
impl sys_traits::FsFile for FsFileAdapter {}
impl sys_traits::FsFileAsRaw for FsFileAdapter {
#[cfg(windows)]
fn fs_file_as_raw_handle(&self) -> Option<std::os::windows::io::RawHandle> {
match self {
Self::Real(file) => file.fs_file_as_raw_handle(),
Self::Vfs(_) => None,
}
}
#[cfg(unix)]
fn fs_file_as_raw_fd(&self) -> Option<std::os::fd::RawFd> {
match self {
Self::Real(file) => file.fs_file_as_raw_fd(),
Self::Vfs(_) => None,
}
}
}
impl sys_traits::FsFileSyncData for FsFileAdapter {
fn fs_file_sync_data(&mut self) -> std::io::Result<()> {
match self {
Self::Real(file) => file.fs_file_sync_data(),
Self::Vfs(_) => Ok(()),
}
}
}
impl sys_traits::FsFileSyncAll for FsFileAdapter {
fn fs_file_sync_all(&mut self) -> std::io::Result<()> {
match self {
Self::Real(file) => file.fs_file_sync_all(),
Self::Vfs(_) => Ok(()),
}
}
}
impl sys_traits::FsFileSetPermissions for FsFileAdapter {
#[inline]
fn fs_file_set_permissions(&mut self, mode: u32) -> std::io::Result<()> {
match self {
Self::Real(file) => file.fs_file_set_permissions(mode),
Self::Vfs(_) => Ok(()),
}
}
}
impl std::io::Read for FsFileAdapter {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
match self {
Self::Real(file) => file.read(buf),
Self::Vfs(file) => file.read_to_buf(buf),
}
}
}
impl std::io::Seek for FsFileAdapter {
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
match self {
Self::Real(file) => file.seek(pos),
Self::Vfs(file) => file.seek(pos),
}
}
}
impl std::io::Write for FsFileAdapter {
#[inline]
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
match self {
Self::Real(file) => file.write(buf),
Self::Vfs(_) => Err(not_supported("writing files")),
}
}
#[inline]
fn flush(&mut self) -> std::io::Result<()> {
match self {
Self::Real(file) => file.flush(),
Self::Vfs(_) => Err(not_supported("writing files")),
}
}
}
impl sys_traits::FsFileSetLen for FsFileAdapter {
#[inline]
fn fs_file_set_len(&mut self, len: u64) -> std::io::Result<()> {
match self {
Self::Real(file) => file.fs_file_set_len(len),
Self::Vfs(_) => Err(not_supported("setting file length")),
}
}
}
impl sys_traits::FsFileSetTimes for FsFileAdapter {
fn fs_file_set_times(
&mut self,
times: sys_traits::FsFileTimes,
) -> std::io::Result<()> {
match self {
Self::Real(file) => file.fs_file_set_times(times),
Self::Vfs(_) => Err(not_supported("setting file times")),
}
}
}
impl sys_traits::FsFileLock for FsFileAdapter {
fn fs_file_lock(
&mut self,
mode: sys_traits::FsFileLockMode,
) -> std::io::Result<()> {
match self {
Self::Real(file) => file.fs_file_lock(mode),
Self::Vfs(_) => Err(not_supported("locking files")),
}
}
fn fs_file_try_lock(
&mut self,
mode: sys_traits::FsFileLockMode,
) -> std::io::Result<()> {
match self {
Self::Real(file) => file.fs_file_try_lock(mode),
Self::Vfs(_) => Err(not_supported("locking files")),
}
}
fn fs_file_unlock(&mut self) -> std::io::Result<()> {
match self {
Self::Real(file) => file.fs_file_unlock(),
Self::Vfs(_) => Err(not_supported("unlocking files")),
}
}
}
impl sys_traits::FsFileIsTerminal for FsFileAdapter {
#[inline]
fn fs_file_is_terminal(&self) -> bool {
match self {
Self::Real(file) => file.fs_file_is_terminal(),
Self::Vfs(_) => false,
}
}
}
impl sys_traits::BaseFsOpen for DenoCompileFileSystem {
type File = FsFileAdapter;
fn base_fs_open(
&self,
path: &Path,
options: &sys_traits::OpenOptions,
) -> std::io::Result<Self::File> {
if self.0.is_path_within(path) {
Ok(FsFileAdapter::Vfs(self.0.open_file(path)?))
} else {
#[allow(clippy::disallowed_types)] // ok because we're implementing the fs
Ok(FsFileAdapter::Real(
sys_traits::impls::RealSys.base_fs_open(path, options)?,
))
}
}
}
impl sys_traits::SystemRandom for DenoCompileFileSystem {
#[inline]
fn sys_random(&self, buf: &mut [u8]) -> std::io::Result<()> {
#[allow(clippy::disallowed_types)] // ok because we're implementing the fs
sys_traits::impls::RealSys.sys_random(buf)
}
}
impl sys_traits::SystemTimeNow for DenoCompileFileSystem {
#[inline]
fn sys_time_now(&self) -> SystemTime {
#[allow(clippy::disallowed_types)] // ok because we're implementing the fs
sys_traits::impls::RealSys.sys_time_now()
}
}
impl sys_traits::ThreadSleep for DenoCompileFileSystem {
#[inline]
fn thread_sleep(&self, dur: Duration) {
#[allow(clippy::disallowed_types)] // ok because we're implementing the fs
sys_traits::impls::RealSys.thread_sleep(dur)
}
}
impl sys_traits::EnvCurrentDir for DenoCompileFileSystem {
fn env_current_dir(&self) -> std::io::Result<PathBuf> {
#[allow(clippy::disallowed_types)] // ok because we're implementing the fs
sys_traits::impls::RealSys.env_current_dir()
}
}
impl sys_traits::BaseEnvVar for DenoCompileFileSystem {
fn base_env_var_os(
&self,
key: &std::ffi::OsStr,
) -> Option<std::ffi::OsString> {
#[allow(clippy::disallowed_types)] // ok because we're implementing the fs
sys_traits::impls::RealSys.base_env_var_os(key)
}
}

View file

@ -36,11 +36,10 @@ use deno_package_json::PackageJsonDepValue;
use deno_resolver::cjs::IsCjsResolutionMode;
use deno_resolver::npm::NpmReqResolverOptions;
use deno_runtime::deno_fs;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use deno_runtime::deno_fs::FileSystem;
use deno_runtime::deno_node::create_host_defined_options;
use deno_runtime::deno_node::NodeRequireLoader;
use deno_runtime::deno_node::NodeResolver;
use deno_runtime::deno_node::PackageJsonResolver;
use deno_runtime::deno_node::RealIsBuiltInNodeModuleChecker;
use deno_runtime::deno_permissions::Permissions;
use deno_runtime::deno_permissions::PermissionsContainer;
@ -77,6 +76,8 @@ use crate::cache::NodeAnalysisCache;
use crate::http_util::HttpClientProvider;
use crate::node::CliCjsCodeAnalyzer;
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;
@ -89,6 +90,7 @@ use crate::npm::CreateInNpmPkgCheckerOptions;
use crate::resolver::CjsTracker;
use crate::resolver::CliNpmReqResolver;
use crate::resolver::NpmModuleLoader;
use crate::sys::CliSys;
use crate::util::progress_bar::ProgressBar;
use crate::util::progress_bar::ProgressBarStyle;
use crate::util::text_encoding::from_utf8_lossy_cow;
@ -105,12 +107,12 @@ mod file_system;
mod serialization;
mod virtual_fs;
pub use self::file_system::DenoCompileFileSystem;
pub use binary::extract_standalone;
pub use binary::is_standalone_binary;
pub use binary::DenoCompileBinaryWriter;
use self::binary::Metadata;
use self::file_system::DenoCompileFileSystem;
struct SharedModuleLoaderState {
cjs_tracker: Arc<CjsTracker>,
@ -118,7 +120,7 @@ struct SharedModuleLoaderState {
fs: Arc<dyn deno_fs::FileSystem>,
modules: StandaloneModules,
node_code_translator: Arc<CliNodeCodeTranslator>,
node_resolver: Arc<NodeResolver>,
node_resolver: Arc<CliNodeResolver>,
npm_module_loader: Arc<NpmModuleLoader>,
npm_req_resolver: Arc<CliNpmReqResolver>,
npm_resolver: Arc<dyn CliNpmResolver>,
@ -627,9 +629,12 @@ impl RootCertStoreProvider for StandaloneRootCertStoreProvider {
}
}
pub async fn run(data: StandaloneData) -> Result<i32, AnyError> {
pub async fn run(
fs: Arc<dyn FileSystem>,
sys: CliSys,
data: StandaloneData,
) -> Result<i32, AnyError> {
let StandaloneData {
fs,
metadata,
modules,
npm_snapshot,
@ -637,7 +642,7 @@ pub async fn run(data: StandaloneData) -> Result<i32, AnyError> {
source_maps,
vfs,
} = data;
let deno_dir_provider = Arc::new(DenoDirProvider::new(None));
let deno_dir_provider = Arc::new(DenoDirProvider::new(sys.clone(), None));
let root_cert_store_provider = Arc::new(StandaloneRootCertStoreProvider {
ca_stores: metadata.ca_stores,
ca_data: metadata.ca_data.map(CaData::Bytes),
@ -655,8 +660,7 @@ pub async fn run(data: StandaloneData) -> Result<i32, AnyError> {
let main_module = root_dir_url.join(&metadata.entrypoint_key).unwrap();
let npm_global_cache_dir = root_path.join(".deno_compile_node_modules");
let cache_setting = CacheSetting::Only;
let sys = FsSysTraitsAdapter(fs.clone());
let pkg_json_resolver = Arc::new(PackageJsonResolver::new(sys.clone()));
let pkg_json_resolver = Arc::new(CliPackageJsonResolver::new(sys.clone()));
let (in_npm_pkg_checker, npm_resolver) = match metadata.node_modules {
Some(binary::NodeModules::Managed { node_modules_dir }) => {
// create an npmrc that uses the fake npm_registry_url to resolve packages
@ -807,7 +811,7 @@ pub async fn run(data: StandaloneData) -> Result<i32, AnyError> {
node_resolver.clone(),
npm_resolver.clone().into_npm_pkg_folder_resolver(),
pkg_json_resolver.clone(),
sys,
sys.clone(),
));
let workspace_resolver = {
let import_map = match metadata.workspace_resolver.import_map {
@ -910,7 +914,7 @@ pub async fn run(data: StandaloneData) -> Result<i32, AnyError> {
}
let desc_parser =
Arc::new(RuntimePermissionDescriptorParser::new(fs.clone()));
Arc::new(RuntimePermissionDescriptorParser::new(sys.clone()));
let permissions =
Permissions::from_options(desc_parser.as_ref(), &permissions)?;
PermissionsContainer::new(desc_parser, permissions)
@ -940,6 +944,7 @@ pub async fn run(data: StandaloneData) -> Result<i32, AnyError> {
root_cert_store_provider,
permissions,
StorageKeyResolver::empty(),
sys,
crate::args::DenoSubcommand::Run(Default::default()),
CliMainWorkerOptions {
argv: metadata.argv,

View file

@ -51,8 +51,16 @@ pub enum WindowsSystemRootablePath {
impl WindowsSystemRootablePath {
pub fn join(&self, name_component: &str) -> PathBuf {
// this method doesn't handle multiple components
debug_assert!(!name_component.contains('\\'));
debug_assert!(!name_component.contains('/'));
debug_assert!(
!name_component.contains('\\'),
"Invalid component: {}",
name_component
);
debug_assert!(
!name_component.contains('/'),
"Invalid component: {}",
name_component
);
match self {
WindowsSystemRootablePath::WindowSystemRoot => {
@ -847,78 +855,28 @@ enum VfsEntryRef<'a> {
Symlink(&'a VirtualSymlink),
}
impl<'a> VfsEntryRef<'a> {
pub fn as_fs_stat(&self) -> FsStat {
impl VfsEntryRef<'_> {
pub fn as_metadata(&self) -> FileBackedVfsMetadata {
FileBackedVfsMetadata {
file_type: match self {
Self::Dir(_) => sys_traits::FileType::Dir,
Self::File(_) => sys_traits::FileType::File,
Self::Symlink(_) => sys_traits::FileType::Symlink,
},
name: self.name().to_string(),
len: match self {
Self::Dir(_) => 0,
Self::File(file) => file.offset.len,
Self::Symlink(_) => 0,
},
}
}
pub fn name(&self) -> &str {
match self {
VfsEntryRef::Dir(_) => FsStat {
is_directory: true,
is_file: false,
is_symlink: false,
atime: None,
birthtime: None,
mtime: None,
ctime: None,
blksize: 0,
size: 0,
dev: 0,
ino: 0,
mode: 0,
nlink: 0,
uid: 0,
gid: 0,
rdev: 0,
blocks: 0,
is_block_device: false,
is_char_device: false,
is_fifo: false,
is_socket: false,
},
VfsEntryRef::File(file) => FsStat {
is_directory: false,
is_file: true,
is_symlink: false,
atime: None,
birthtime: None,
mtime: None,
ctime: None,
blksize: 0,
size: file.offset.len,
dev: 0,
ino: 0,
mode: 0,
nlink: 0,
uid: 0,
gid: 0,
rdev: 0,
blocks: 0,
is_block_device: false,
is_char_device: false,
is_fifo: false,
is_socket: false,
},
VfsEntryRef::Symlink(_) => FsStat {
is_directory: false,
is_file: false,
is_symlink: true,
atime: None,
birthtime: None,
mtime: None,
ctime: None,
blksize: 0,
size: 0,
dev: 0,
ino: 0,
mode: 0,
nlink: 0,
uid: 0,
gid: 0,
rdev: 0,
blocks: 0,
is_block_device: false,
is_char_device: false,
is_fifo: false,
is_socket: false,
},
Self::Dir(dir) => &dir.name,
Self::File(file) => &file.name,
Self::Symlink(symlink) => &symlink.name,
}
}
}
@ -934,9 +892,9 @@ pub enum VfsEntry {
impl VfsEntry {
pub fn name(&self) -> &str {
match self {
VfsEntry::Dir(dir) => &dir.name,
VfsEntry::File(file) => &file.name,
VfsEntry::Symlink(symlink) => &symlink.name,
Self::Dir(dir) => &dir.name,
Self::File(file) => &file.name,
Self::Symlink(symlink) => &symlink.name,
}
}
@ -1180,14 +1138,14 @@ impl VfsRoot {
}
}
struct FileBackedVfsFile {
pub struct FileBackedVfsFile {
file: VirtualFile,
pos: RefCell<u64>,
vfs: Arc<FileBackedVfs>,
}
impl FileBackedVfsFile {
fn seek(&self, pos: SeekFrom) -> FsResult<u64> {
pub fn seek(&self, pos: SeekFrom) -> std::io::Result<u64> {
match pos {
SeekFrom::Start(pos) => {
*self.pos.borrow_mut() = pos;
@ -1196,10 +1154,10 @@ impl FileBackedVfsFile {
SeekFrom::End(offset) => {
if offset < 0 && -offset as u64 > self.file.offset.len {
let msg = "An attempt was made to move the file pointer before the beginning of the file.";
Err(
std::io::Error::new(std::io::ErrorKind::PermissionDenied, msg)
.into(),
)
Err(std::io::Error::new(
std::io::ErrorKind::PermissionDenied,
msg,
))
} else {
let mut current_pos = self.pos.borrow_mut();
*current_pos = if offset >= 0 {
@ -1215,7 +1173,7 @@ impl FileBackedVfsFile {
if offset >= 0 {
*current_pos += offset as u64;
} else if -offset as u64 > *current_pos {
return Err(std::io::Error::new(std::io::ErrorKind::PermissionDenied, "An attempt was made to move the file pointer before the beginning of the file.").into());
return Err(std::io::Error::new(std::io::ErrorKind::PermissionDenied, "An attempt was made to move the file pointer before the beginning of the file."));
} else {
*current_pos -= -offset as u64;
}
@ -1224,7 +1182,7 @@ impl FileBackedVfsFile {
}
}
fn read_to_buf(&self, buf: &mut [u8]) -> FsResult<usize> {
pub fn read_to_buf(&self, buf: &mut [u8]) -> std::io::Result<usize> {
let read_pos = {
let mut pos = self.pos.borrow_mut();
let read_pos = *pos;
@ -1232,10 +1190,7 @@ impl FileBackedVfsFile {
*pos = std::cmp::min(self.file.offset.len, *pos + buf.len() as u64);
read_pos
};
self
.vfs
.read_file(&self.file, read_pos, buf)
.map_err(|err| err.into())
self.vfs.read_file(&self.file, read_pos, buf)
}
fn read_to_end(&self) -> FsResult<Cow<'static, [u8]>> {
@ -1270,7 +1225,7 @@ impl FileBackedVfsFile {
#[async_trait::async_trait(?Send)]
impl deno_io::fs::File for FileBackedVfsFile {
fn read_sync(self: Rc<Self>, buf: &mut [u8]) -> FsResult<usize> {
self.read_to_buf(buf)
self.read_to_buf(buf).map_err(Into::into)
}
async fn read_byob(
self: Rc<Self>,
@ -1314,10 +1269,10 @@ impl deno_io::fs::File for FileBackedVfsFile {
}
fn seek_sync(self: Rc<Self>, pos: SeekFrom) -> FsResult<u64> {
self.seek(pos)
self.seek(pos).map_err(|err| err.into())
}
async fn seek_async(self: Rc<Self>, pos: SeekFrom) -> FsResult<u64> {
self.seek(pos)
self.seek(pos).map_err(|err| err.into())
}
fn datasync_sync(self: Rc<Self>) -> FsResult<()> {
@ -1393,6 +1348,47 @@ impl deno_io::fs::File for FileBackedVfsFile {
}
}
#[derive(Debug, Clone)]
pub struct FileBackedVfsDirEntry {
pub parent_path: PathBuf,
pub metadata: FileBackedVfsMetadata,
}
#[derive(Debug, Clone)]
pub struct FileBackedVfsMetadata {
pub name: String,
pub file_type: sys_traits::FileType,
pub len: u64,
}
impl FileBackedVfsMetadata {
pub fn as_fs_stat(&self) -> FsStat {
FsStat {
is_directory: self.file_type == sys_traits::FileType::Dir,
is_file: self.file_type == sys_traits::FileType::File,
is_symlink: self.file_type == sys_traits::FileType::Symlink,
atime: None,
birthtime: None,
mtime: None,
ctime: None,
blksize: 0,
size: self.len,
dev: 0,
ino: 0,
mode: 0,
nlink: 0,
uid: 0,
gid: 0,
rdev: 0,
blocks: 0,
is_block_device: false,
is_char_device: false,
is_fifo: false,
is_socket: false,
}
}
}
#[derive(Debug)]
pub struct FileBackedVfs {
vfs_data: Cow<'static, [u8]>,
@ -1418,13 +1414,13 @@ impl FileBackedVfs {
pub fn open_file(
self: &Arc<Self>,
path: &Path,
) -> std::io::Result<Rc<dyn deno_io::fs::File>> {
) -> std::io::Result<FileBackedVfsFile> {
let file = self.file_entry(path)?;
Ok(Rc::new(FileBackedVfsFile {
Ok(FileBackedVfsFile {
file: file.clone(),
vfs: self.clone(),
pos: Default::default(),
}))
})
}
pub fn read_dir(&self, path: &Path) -> std::io::Result<Vec<FsDirEntry>> {
@ -1443,6 +1439,18 @@ impl FileBackedVfs {
)
}
pub fn read_dir_with_metadata<'a>(
&'a self,
path: &Path,
) -> std::io::Result<impl Iterator<Item = FileBackedVfsDirEntry> + 'a> {
let dir = self.dir_entry(path)?;
let path = path.to_path_buf();
Ok(dir.entries.iter().map(move |entry| FileBackedVfsDirEntry {
parent_path: path.to_path_buf(),
metadata: entry.as_ref().as_metadata(),
}))
}
pub fn read_link(&self, path: &Path) -> std::io::Result<PathBuf> {
let (_, entry) = self.fs_root.find_entry_no_follow(path)?;
match entry {
@ -1456,14 +1464,14 @@ impl FileBackedVfs {
}
}
pub fn lstat(&self, path: &Path) -> std::io::Result<FsStat> {
pub fn lstat(&self, path: &Path) -> std::io::Result<FileBackedVfsMetadata> {
let (_, entry) = self.fs_root.find_entry_no_follow(path)?;
Ok(entry.as_fs_stat())
Ok(entry.as_metadata())
}
pub fn stat(&self, path: &Path) -> std::io::Result<FsStat> {
pub fn stat(&self, path: &Path) -> std::io::Result<FileBackedVfsMetadata> {
let (_, entry) = self.fs_root.find_entry(path)?;
Ok(entry.as_fs_stat())
Ok(entry.as_metadata())
}
pub fn canonicalize(&self, path: &Path) -> std::io::Result<PathBuf> {
@ -1556,6 +1564,7 @@ impl FileBackedVfs {
#[cfg(test)]
mod test {
use console_static_text::ansi::strip_ansi_codes;
use deno_io::fs::File;
use std::io::Write;
use test_util::assert_contains;
use test_util::TempDir;
@ -1641,25 +1650,31 @@ mod test {
);
// metadata
assert!(
assert_eq!(
virtual_fs
.lstat(&dest_path.join("sub_dir").join("e.txt"))
.unwrap()
.is_symlink
.file_type,
sys_traits::FileType::Symlink,
);
assert!(
assert_eq!(
virtual_fs
.stat(&dest_path.join("sub_dir").join("e.txt"))
.unwrap()
.is_file
.file_type,
sys_traits::FileType::File,
);
assert!(
assert_eq!(
virtual_fs
.stat(&dest_path.join("sub_dir"))
.unwrap()
.is_directory,
.file_type,
sys_traits::FileType::Dir,
);
assert_eq!(
virtual_fs.stat(&dest_path.join("e.txt")).unwrap().file_type,
sys_traits::FileType::File
);
assert!(virtual_fs.stat(&dest_path.join("e.txt")).unwrap().is_file,);
}
#[test]
@ -1696,11 +1711,12 @@ mod test {
read_file(&virtual_fs, &dest_path.join("sub_dir_link").join("c.txt")),
"c",
);
assert!(
assert_eq!(
virtual_fs
.lstat(&dest_path.join("sub_dir_link"))
.unwrap()
.is_symlink
.file_type,
sys_traits::FileType::Symlink,
);
assert_eq!(
@ -1772,37 +1788,35 @@ mod test {
let (dest_path, virtual_fs) = into_virtual_fs(builder, &temp_dir);
let virtual_fs = Arc::new(virtual_fs);
let file = virtual_fs.open_file(&dest_path.join("a.txt")).unwrap();
file.clone().seek_sync(SeekFrom::Current(2)).unwrap();
file.seek(SeekFrom::Current(2)).unwrap();
let mut buf = vec![0; 2];
file.clone().read_sync(&mut buf).unwrap();
file.read_to_buf(&mut buf).unwrap();
assert_eq!(buf, b"23");
file.clone().read_sync(&mut buf).unwrap();
file.read_to_buf(&mut buf).unwrap();
assert_eq!(buf, b"45");
file.clone().seek_sync(SeekFrom::Current(-4)).unwrap();
file.clone().read_sync(&mut buf).unwrap();
file.seek(SeekFrom::Current(-4)).unwrap();
file.read_to_buf(&mut buf).unwrap();
assert_eq!(buf, b"23");
file.clone().seek_sync(SeekFrom::Start(2)).unwrap();
file.clone().read_sync(&mut buf).unwrap();
file.seek(SeekFrom::Start(2)).unwrap();
file.read_to_buf(&mut buf).unwrap();
assert_eq!(buf, b"23");
file.clone().seek_sync(SeekFrom::End(2)).unwrap();
file.clone().read_sync(&mut buf).unwrap();
file.seek(SeekFrom::End(2)).unwrap();
file.read_to_buf(&mut buf).unwrap();
assert_eq!(buf, b"89");
file.clone().seek_sync(SeekFrom::Current(-8)).unwrap();
file.clone().read_sync(&mut buf).unwrap();
file.seek(SeekFrom::Current(-8)).unwrap();
file.read_to_buf(&mut buf).unwrap();
assert_eq!(buf, b"23");
assert_eq!(
file
.clone()
.seek_sync(SeekFrom::Current(-5))
.err()
.unwrap()
.into_io_error()
.seek(SeekFrom::Current(-5))
.unwrap_err()
.to_string(),
"An attempt was made to move the file pointer before the beginning of the file."
);
// go beyond the file length, then back
file.clone().seek_sync(SeekFrom::Current(40)).unwrap();
file.clone().seek_sync(SeekFrom::Current(-38)).unwrap();
file.seek(SeekFrom::Current(40)).unwrap();
file.seek(SeekFrom::Current(-38)).unwrap();
let file = Rc::new(file);
let read_buf = file.clone().read(2).await.unwrap();
assert_eq!(read_buf.to_vec(), b"67");
file.clone().seek_sync(SeekFrom::Current(-2)).unwrap();

218
cli/sys.rs Normal file
View file

@ -0,0 +1,218 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
// todo(dsherret): this should instead use conditional compilation and directly
// surface the underlying implementation.
//
// The problem atm is that there's no way to have conditional compilation for
// denort or the deno binary. We should extract out denort to a separate binary.
use std::borrow::Cow;
use sys_traits::boxed::BoxedFsDirEntry;
use sys_traits::boxed::BoxedFsFile;
use sys_traits::boxed::BoxedFsMetadataValue;
use sys_traits::boxed::FsMetadataBoxed;
use sys_traits::boxed::FsOpenBoxed;
use sys_traits::boxed::FsReadDirBoxed;
use sys_traits::CreateDirOptions;
use crate::standalone::DenoCompileFileSystem;
#[derive(Debug, Clone)]
pub enum CliSys {
#[allow(dead_code)] // will be dead code for denort
#[allow(clippy::disallowed_types)] // ok because sys impl
Real(sys_traits::impls::RealSys),
#[allow(dead_code)] // will be dead code for deno
DenoCompile(DenoCompileFileSystem),
}
impl Default for CliSys {
fn default() -> Self {
Self::Real(sys_traits::impls::RealSys)
}
}
impl deno_runtime::deno_node::ExtNodeSys for CliSys {}
impl sys_traits::BaseFsHardLink for CliSys {
fn base_fs_hard_link(
&self,
src: &std::path::Path,
dst: &std::path::Path,
) -> std::io::Result<()> {
match self {
Self::Real(sys) => sys.base_fs_hard_link(src, dst),
Self::DenoCompile(sys) => sys.base_fs_hard_link(src, dst),
}
}
}
impl sys_traits::BaseFsRead for CliSys {
fn base_fs_read(
&self,
p: &std::path::Path,
) -> std::io::Result<Cow<'static, [u8]>> {
match self {
Self::Real(sys) => sys.base_fs_read(p),
Self::DenoCompile(sys) => sys.base_fs_read(p),
}
}
}
impl sys_traits::BaseFsReadDir for CliSys {
type ReadDirEntry = BoxedFsDirEntry;
fn base_fs_read_dir(
&self,
p: &std::path::Path,
) -> std::io::Result<
Box<dyn Iterator<Item = std::io::Result<Self::ReadDirEntry>> + '_>,
> {
match self {
Self::Real(sys) => sys.fs_read_dir_boxed(p),
Self::DenoCompile(sys) => sys.fs_read_dir_boxed(p),
}
}
}
impl sys_traits::BaseFsCanonicalize for CliSys {
fn base_fs_canonicalize(
&self,
p: &std::path::Path,
) -> std::io::Result<std::path::PathBuf> {
match self {
Self::Real(sys) => sys.base_fs_canonicalize(p),
Self::DenoCompile(sys) => sys.base_fs_canonicalize(p),
}
}
}
impl sys_traits::BaseFsMetadata for CliSys {
type Metadata = BoxedFsMetadataValue;
fn base_fs_metadata(
&self,
path: &std::path::Path,
) -> std::io::Result<Self::Metadata> {
match self {
Self::Real(sys) => sys.fs_metadata_boxed(path),
Self::DenoCompile(sys) => sys.fs_metadata_boxed(path),
}
}
fn base_fs_symlink_metadata(
&self,
path: &std::path::Path,
) -> std::io::Result<Self::Metadata> {
match self {
Self::Real(sys) => sys.fs_symlink_metadata_boxed(path),
Self::DenoCompile(sys) => sys.fs_symlink_metadata_boxed(path),
}
}
}
impl sys_traits::BaseFsCreateDir for CliSys {
fn base_fs_create_dir(
&self,
p: &std::path::Path,
options: &CreateDirOptions,
) -> std::io::Result<()> {
match self {
Self::Real(sys) => sys.base_fs_create_dir(p, options),
Self::DenoCompile(sys) => sys.base_fs_create_dir(p, options),
}
}
}
impl sys_traits::BaseFsOpen for CliSys {
type File = BoxedFsFile;
fn base_fs_open(
&self,
path: &std::path::Path,
options: &sys_traits::OpenOptions,
) -> std::io::Result<Self::File> {
match self {
Self::Real(sys) => sys.fs_open_boxed(path, options),
Self::DenoCompile(sys) => sys.fs_open_boxed(path, options),
}
}
}
impl sys_traits::BaseFsRemoveFile for CliSys {
fn base_fs_remove_file(&self, p: &std::path::Path) -> std::io::Result<()> {
match self {
Self::Real(sys) => sys.base_fs_remove_file(p),
Self::DenoCompile(sys) => sys.base_fs_remove_file(p),
}
}
}
impl sys_traits::BaseFsRename for CliSys {
fn base_fs_rename(
&self,
old: &std::path::Path,
new: &std::path::Path,
) -> std::io::Result<()> {
match self {
Self::Real(sys) => sys.base_fs_rename(old, new),
Self::DenoCompile(sys) => sys.base_fs_rename(old, new),
}
}
}
impl sys_traits::SystemRandom for CliSys {
fn sys_random(&self, buf: &mut [u8]) -> std::io::Result<()> {
match self {
Self::Real(sys) => sys.sys_random(buf),
Self::DenoCompile(sys) => sys.sys_random(buf),
}
}
}
impl sys_traits::SystemTimeNow for CliSys {
fn sys_time_now(&self) -> std::time::SystemTime {
match self {
Self::Real(sys) => sys.sys_time_now(),
Self::DenoCompile(sys) => sys.sys_time_now(),
}
}
}
impl sys_traits::ThreadSleep for CliSys {
fn thread_sleep(&self, dur: std::time::Duration) {
match self {
Self::Real(sys) => sys.thread_sleep(dur),
Self::DenoCompile(sys) => sys.thread_sleep(dur),
}
}
}
impl sys_traits::EnvCurrentDir for CliSys {
fn env_current_dir(&self) -> std::io::Result<std::path::PathBuf> {
match self {
Self::Real(sys) => sys.env_current_dir(),
Self::DenoCompile(sys) => sys.env_current_dir(),
}
}
}
impl sys_traits::BaseEnvVar for CliSys {
fn base_env_var_os(
&self,
key: &std::ffi::OsStr,
) -> Option<std::ffi::OsString> {
match self {
Self::Real(sys) => sys.base_env_var_os(key),
Self::DenoCompile(sys) => sys.base_env_var_os(key),
}
}
}
impl sys_traits::EnvHomeDir for CliSys {
fn env_home_dir(&self) -> Option<std::path::PathBuf> {
#[allow(clippy::disallowed_types)] // ok because sys impl
sys_traits::impls::RealSys.env_home_dir()
}
}

View file

@ -10,7 +10,6 @@ use deno_core::anyhow::Context;
use deno_core::error::AnyError;
use deno_core::futures;
use deno_core::futures::future::LocalBoxFuture;
use deno_runtime::deno_node::NodeResolver;
use deno_semver::package::PackageNv;
use deno_task_shell::ExecutableCommand;
use deno_task_shell::ExecuteResult;
@ -25,6 +24,7 @@ use tokio::task::JoinHandle;
use tokio::task::LocalSet;
use tokio_util::sync::CancellationToken;
use crate::node::CliNodeResolver;
use crate::npm::CliNpmResolver;
use crate::npm::InnerCliNpmResolverRef;
use crate::npm::ManagedCliNpmResolver;
@ -415,7 +415,7 @@ impl ShellCommand for NodeModulesFileRunCommand {
pub fn resolve_custom_commands(
npm_resolver: &dyn CliNpmResolver,
node_resolver: &NodeResolver,
node_resolver: &CliNodeResolver,
) -> Result<HashMap<String, Rc<dyn ShellCommand>>, AnyError> {
let mut commands = match npm_resolver.as_inner() {
InnerCliNpmResolverRef::Byonm(npm_resolver) => {
@ -522,7 +522,7 @@ fn resolve_execution_path_from_npx_shim(
fn resolve_managed_npm_commands(
npm_resolver: &ManagedCliNpmResolver,
node_resolver: &NodeResolver,
node_resolver: &CliNodeResolver,
) -> Result<HashMap<String, Rc<dyn ShellCommand>>, AnyError> {
let mut result = HashMap::new();
let snapshot = npm_resolver.snapshot();

View file

@ -7,6 +7,7 @@ use crate::display::write_json_to_stdout;
use crate::factory::CliFactory;
use crate::graph_util::has_graph_root_local_dependent_changed;
use crate::ops;
use crate::sys::CliSys;
use crate::tools::test::format_test_error;
use crate::tools::test::TestFilter;
use crate::util::file_watcher;
@ -265,7 +266,7 @@ async fn bench_specifier_inner(
async fn bench_specifiers(
worker_factory: Arc<CliMainWorkerFactory>,
permissions: &Permissions,
permissions_desc_parser: &Arc<RuntimePermissionDescriptorParser>,
permissions_desc_parser: &Arc<RuntimePermissionDescriptorParser<CliSys>>,
specifiers: Vec<ModuleSpecifier>,
options: BenchSpecifierOptions,
) -> Result<(), AnyError> {

View file

@ -9,7 +9,6 @@ use deno_ast::ModuleSpecifier;
use deno_core::error::AnyError;
use deno_graph::Module;
use deno_graph::ModuleGraph;
use deno_runtime::deno_node::NodeResolver;
use deno_terminal::colors;
use once_cell::sync::Lazy;
use regex::Regex;
@ -29,6 +28,7 @@ use crate::cache::TypeCheckCache;
use crate::factory::CliFactory;
use crate::graph_util::BuildFastCheckGraphOptions;
use crate::graph_util::ModuleGraphBuilder;
use crate::node::CliNodeResolver;
use crate::npm::CliNpmResolver;
use crate::tsc;
use crate::tsc::Diagnostics;
@ -103,7 +103,7 @@ pub struct TypeChecker {
cjs_tracker: Arc<TypeCheckingCjsTracker>,
cli_options: Arc<CliOptions>,
module_graph_builder: Arc<ModuleGraphBuilder>,
node_resolver: Arc<NodeResolver>,
node_resolver: Arc<CliNodeResolver>,
npm_resolver: Arc<dyn CliNpmResolver>,
}
@ -113,7 +113,7 @@ impl TypeChecker {
cjs_tracker: Arc<TypeCheckingCjsTracker>,
cli_options: Arc<CliOptions>,
module_graph_builder: Arc<ModuleGraphBuilder>,
node_resolver: Arc<NodeResolver>,
node_resolver: Arc<CliNodeResolver>,
npm_resolver: Arc<dyn CliNpmResolver>,
) -> Self {
Self {

View file

@ -7,6 +7,7 @@ use std::path::Path;
use crate::cache::DenoDir;
use crate::colors;
use crate::display;
use crate::sys::CliSys;
use crate::util::progress_bar::ProgressBar;
use crate::util::progress_bar::ProgressBarStyle;
use crate::util::progress_bar::ProgressMessagePrompt;
@ -28,7 +29,7 @@ impl CleanState {
}
pub fn clean() -> Result<(), AnyError> {
let deno_dir = DenoDir::new(None)?;
let deno_dir = DenoDir::new(CliSys::default(), None)?;
if deno_dir.root.exists() {
let no_of_files = walkdir::WalkDir::new(&deno_dir.root).into_iter().count();
let progress_bar = ProgressBar::new(ProgressBarStyle::ProgressBars);

View file

@ -5,8 +5,8 @@ use crate::args::CompileFlags;
use crate::args::Flags;
use crate::factory::CliFactory;
use crate::http_util::HttpClientProvider;
use crate::standalone::binary::is_standalone_binary;
use crate::standalone::binary::WriteBinOptions;
use crate::standalone::is_standalone_binary;
use deno_ast::MediaType;
use deno_ast::ModuleSpecifier;
use deno_core::anyhow::bail;

View file

@ -7,6 +7,7 @@ use crate::args::Flags;
use crate::cdp;
use crate::factory::CliFactory;
use crate::file_fetcher::TextDecodedFile;
use crate::sys::CliSys;
use crate::tools::fmt::format_json;
use crate::tools::test::is_supported_test_path;
use crate::util::text_encoding::source_map_from_code;
@ -26,7 +27,6 @@ use deno_core::serde_json;
use deno_core::sourcemap::SourceMap;
use deno_core::url::Url;
use deno_core::LocalInspectorSession;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use node_resolver::InNpmPackageChecker;
use regex::Regex;
use std::fs;
@ -429,7 +429,7 @@ fn collect_coverages(
.ignore_git_folder()
.ignore_node_modules()
.set_vendor_folder(cli_options.vendor_dir_path().map(ToOwned::to_owned))
.collect_file_patterns(&FsSysTraitsAdapter::new_real(), file_patterns)?;
.collect_file_patterns(&CliSys::default(), file_patterns)?;
let coverage_patterns = FilePatterns {
base: initial_cwd.to_path_buf(),

View file

@ -10,6 +10,7 @@ use crate::factory::CliFactory;
use crate::graph_util::graph_exit_integrity_errors;
use crate::graph_util::graph_walk_errors;
use crate::graph_util::GraphWalkErrorsOptions;
use crate::sys::CliSys;
use crate::tsc::get_types_declaration_file_text;
use crate::util::fs::collect_specifiers;
use deno_ast::diagnostics::Diagnostic;
@ -28,7 +29,6 @@ use deno_graph::EsParser;
use deno_graph::GraphKind;
use deno_graph::ModuleAnalyzer;
use deno_graph::ModuleSpecifier;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use doc::html::ShortPath;
use doc::DocDiagnostic;
use indexmap::IndexMap;
@ -115,7 +115,7 @@ pub async fn doc(
}
DocSourceFileFlag::Paths(ref source_files) => {
let module_graph_creator = factory.module_graph_creator().await?;
let fs = FsSysTraitsAdapter(factory.fs().clone());
let sys = CliSys::default();
let module_specifiers = collect_specifiers(
FilePatterns {
@ -142,7 +142,7 @@ pub async fn doc(
graph_exit_integrity_errors(&graph);
let errors = graph_walk_errors(
&graph,
&fs,
&sys,
&module_specifiers,
GraphWalkErrorsOptions {
check_js: false,

View file

@ -17,6 +17,7 @@ use crate::args::UnstableFmtOptions;
use crate::cache::Caches;
use crate::colors;
use crate::factory::CliFactory;
use crate::sys::CliSys;
use crate::util::diff::diff;
use crate::util::file_watcher;
use crate::util::fs::canonicalize_path;
@ -34,7 +35,6 @@ use deno_core::futures;
use deno_core::parking_lot::Mutex;
use deno_core::unsync::spawn_blocking;
use deno_core::url::Url;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use log::debug;
use log::info;
use log::warn;
@ -58,7 +58,7 @@ pub async fn format(
fmt_flags: FmtFlags,
) -> Result<(), AnyError> {
if fmt_flags.is_stdin() {
let cli_options = CliOptions::from_flags(flags)?;
let cli_options = CliOptions::from_flags(&CliSys::default(), flags)?;
let start_dir = &cli_options.start_dir;
let fmt_config = start_dir
.to_fmt_config(FilePatterns::new_with_base(start_dir.dir_path()))?;
@ -231,7 +231,7 @@ fn collect_fmt_files(
.ignore_node_modules()
.use_gitignore()
.set_vendor_folder(cli_options.vendor_dir_path().map(ToOwned::to_owned))
.collect_file_patterns(&FsSysTraitsAdapter::new_real(), files)
.collect_file_patterns(&CliSys::default(), files)
}
/// Formats markdown (using <https://github.com/dprint/dprint-plugin-markdown>) and its code blocks

View file

@ -364,6 +364,7 @@ async fn install_global(
let deps_file_fetcher = CliFileFetcher::new(
deps_http_cache.clone(),
http_client.clone(),
factory.sys(),
Default::default(),
None,
true,

View file

@ -16,8 +16,8 @@ use deno_lint::linter::LintFileOptions;
use deno_lint::linter::Linter as DenoLintLinter;
use deno_lint::linter::LinterOptions;
use deno_path_util::fs::atomic_write_file_with_retries;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use crate::sys::CliSys;
use crate::util::fs::specifier_from_file_path;
use super::rules::FileOrPackageLintRule;
@ -177,7 +177,7 @@ impl CliLinter {
if fix_iterations > 0 {
// everything looks good and the file still parses, so write it out
atomic_write_file_with_retries(
&FsSysTraitsAdapter::new_real(),
&CliSys::default(),
file_path,
source.text().as_bytes(),
crate::cache::CACHE_PERM,

View file

@ -21,7 +21,6 @@ use deno_core::unsync::future::SharedLocal;
use deno_graph::ModuleGraph;
use deno_lint::diagnostic::LintDiagnostic;
use deno_lint::linter::LintConfig as DenoLintConfig;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use log::debug;
use reporters::create_reporter;
use reporters::LintReporter;
@ -44,6 +43,7 @@ use crate::cache::IncrementalCache;
use crate::colors;
use crate::factory::CliFactory;
use crate::graph_util::ModuleGraphCreator;
use crate::sys::CliSys;
use crate::tools::fmt::run_parallelized;
use crate::util::display;
use crate::util::file_watcher;
@ -453,7 +453,7 @@ fn collect_lint_files(
.ignore_node_modules()
.use_gitignore()
.set_vendor_folder(cli_options.vendor_dir_path().map(ToOwned::to_owned))
.collect_file_patterns(&FsSysTraitsAdapter::new_real(), files)
.collect_file_patterns(&CliSys::default(), files)
}
#[allow(clippy::print_stdout)]

View file

@ -6,12 +6,12 @@ use std::collections::HashSet;
use std::path::Path;
use std::path::PathBuf;
use crate::sys::CliSys;
use deno_ast::MediaType;
use deno_ast::ModuleSpecifier;
use deno_config::glob::FileCollector;
use deno_config::glob::FilePatterns;
use deno_core::error::AnyError;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use thiserror::Error;
use crate::args::CliOptions;
@ -346,5 +346,5 @@ fn collect_paths(
.ignore_node_modules()
.set_vendor_folder(cli_options.vendor_dir_path().map(ToOwned::to_owned))
.use_gitignore()
.collect_file_patterns(&FsSysTraitsAdapter::new_real(), file_patterns)
.collect_file_patterns(&CliSys::default(), file_patterns)
}

View file

@ -415,6 +415,7 @@ pub async fn add(
let deps_file_fetcher = CliFileFetcher::new(
deps_http_cache.clone(),
http_client.clone(),
cli_factory.sys(),
Default::default(),
None,
true,

View file

@ -185,6 +185,7 @@ pub async fn outdated(
let file_fetcher = CliFileFetcher::new(
deps_http_cache.clone(),
http_client.clone(),
factory.sys(),
Default::default(),
None,
true,

View file

@ -658,13 +658,12 @@ mod tests {
use crate::resolver::SloppyImportsCachedFs;
use super::*;
use crate::sys::CliSys;
use deno_ast::MediaType;
use deno_ast::ModuleSpecifier;
use deno_config::workspace::ResolverWorkspaceJsrPackage;
use deno_core::serde_json::json;
use deno_core::url::Url;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use deno_runtime::deno_fs::RealFs;
use deno_runtime::deno_node::PackageJson;
use deno_semver::Version;
use import_map::ImportMapWithDiagnostics;
@ -725,7 +724,7 @@ mod tests {
);
let unfurler = SpecifierUnfurler::new(
Some(Arc::new(CliSloppyImportsResolver::new(
SloppyImportsCachedFs::new(FsSysTraitsAdapter::new_real()),
SloppyImportsCachedFs::new(CliSys::default()),
))),
Arc::new(workspace_resolver),
true,
@ -863,10 +862,10 @@ const warn2 = await import(`${expr}`);
],
deno_config::workspace::PackageJsonDepResolution::Enabled,
);
let fs = FsSysTraitsAdapter(Arc::new(RealFs));
let sys = CliSys::default();
let unfurler = SpecifierUnfurler::new(
Some(Arc::new(CliSloppyImportsResolver::new(
SloppyImportsCachedFs::new(fs),
SloppyImportsCachedFs::new(sys),
))),
Arc::new(workspace_resolver),
true,

View file

@ -25,7 +25,6 @@ use deno_core::futures::FutureExt;
use deno_core::futures::StreamExt;
use deno_core::url::Url;
use deno_path_util::normalize_path;
use deno_runtime::deno_node::NodeResolver;
use deno_task_shell::KillSignal;
use deno_task_shell::ShellCommand;
use indexmap::IndexMap;
@ -36,6 +35,7 @@ use crate::args::Flags;
use crate::args::TaskFlags;
use crate::colors;
use crate::factory::CliFactory;
use crate::node::CliNodeResolver;
use crate::npm::CliNpmResolver;
use crate::task_runner;
use crate::task_runner::run_future_forwarding_signals;
@ -267,7 +267,7 @@ struct RunSingleOptions<'a> {
struct TaskRunner<'a> {
task_flags: &'a TaskFlags,
npm_resolver: &'a dyn CliNpmResolver,
node_resolver: &'a NodeResolver,
node_resolver: &'a CliNodeResolver,
env_vars: HashMap<String, String>,
cli_options: &'a CliOptions,
concurrency: usize,

View file

@ -10,6 +10,7 @@ use crate::factory::CliFactory;
use crate::file_fetcher::CliFileFetcher;
use crate::graph_util::has_graph_root_local_dependent_changed;
use crate::ops;
use crate::sys::CliSys;
use crate::util::extract::extract_doc_tests;
use crate::util::file_watcher;
use crate::util::fs::collect_specifiers;
@ -1194,7 +1195,7 @@ static HAS_TEST_RUN_SIGINT_HANDLER: AtomicBool = AtomicBool::new(false);
async fn test_specifiers(
worker_factory: Arc<CliMainWorkerFactory>,
permissions: &Permissions,
permission_desc_parser: &Arc<RuntimePermissionDescriptorParser>,
permission_desc_parser: &Arc<RuntimePermissionDescriptorParser<CliSys>>,
specifiers: Vec<ModuleSpecifier>,
options: TestSpecifiersOptions,
) -> Result<(), AnyError> {

View file

@ -4,8 +4,10 @@ use crate::args::TsConfig;
use crate::args::TypeCheckMode;
use crate::cache::FastInsecureHasher;
use crate::cache::ModuleInfoCache;
use crate::node::CliNodeResolver;
use crate::npm::CliNpmResolver;
use crate::resolver::CjsTracker;
use crate::sys::CliSys;
use crate::util::checksum;
use crate::util::path::mapped_specifier_for_tsc;
use crate::worker::create_isolate_create_params;
@ -34,8 +36,6 @@ use deno_graph::Module;
use deno_graph::ModuleGraph;
use deno_graph::ResolutionResolved;
use deno_resolver::npm::ResolvePkgFolderFromDenoReqError;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use deno_runtime::deno_node::NodeResolver;
use deno_semver::npm::NpmPackageReqReference;
use node_resolver::errors::NodeJsErrorCode;
use node_resolver::errors::NodeJsErrorCoded;
@ -380,7 +380,7 @@ impl TypeCheckingCjsTracker {
#[derive(Debug)]
pub struct RequestNpmState {
pub cjs_tracker: Arc<TypeCheckingCjsTracker>,
pub node_resolver: Arc<NodeResolver>,
pub node_resolver: Arc<CliNodeResolver>,
pub npm_resolver: Arc<dyn CliNpmResolver>,
}
@ -661,7 +661,7 @@ fn op_load_inner(
} else {
// means it's Deno code importing an npm module
let specifier = resolve_specifier_into_node_modules(
&FsSysTraitsAdapter::new_real(),
&CliSys::default(),
&module.specifier,
);
Some(Cow::Owned(load_from_node_modules(
@ -925,7 +925,7 @@ fn resolve_graph_specifier_types(
// we currently only use "External" for when the module is in an npm package
Ok(state.maybe_npm.as_ref().map(|_| {
let specifier = resolve_specifier_into_node_modules(
&FsSysTraitsAdapter::new_real(),
&CliSys::default(),
&module.specifier,
);
into_specifier_and_media_type(Some(specifier))

View file

@ -17,8 +17,8 @@ use deno_core::anyhow::Context;
use deno_core::error::AnyError;
use deno_core::unsync::spawn_blocking;
use deno_core::ModuleSpecifier;
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use crate::sys::CliSys;
use crate::util::progress_bar::ProgressBar;
use crate::util::progress_bar::ProgressBarStyle;
use crate::util::progress_bar::ProgressMessagePrompt;
@ -76,7 +76,7 @@ pub fn canonicalize_path_maybe_not_exists(
path: &Path,
) -> Result<PathBuf, Error> {
deno_path_util::fs::canonicalize_path_maybe_not_exists(
&FsSysTraitsAdapter::new_real(),
&CliSys::default(),
path,
)
}
@ -126,7 +126,7 @@ pub fn collect_specifiers(
.ignore_git_folder()
.ignore_node_modules()
.set_vendor_folder(vendor_folder)
.collect_file_patterns(&FsSysTraitsAdapter::new_real(), files)?;
.collect_file_patterns(&CliSys::default(), files)?;
let mut collected_files_as_urls = collected_files
.iter()
.map(|f| specifier_from_file_path(f).unwrap())
@ -198,13 +198,11 @@ mod clone_dir_imp {
from: &std::path::Path,
to: &std::path::Path,
) -> Result<(), deno_core::error::AnyError> {
use deno_runtime::deno_fs::FsSysTraitsAdapter;
use crate::sys::CliSys;
if let Err(e) = deno_npm_cache::hard_link_dir_recursive(
&FsSysTraitsAdapter::new_real(),
from,
to,
) {
if let Err(e) =
deno_npm_cache::hard_link_dir_recursive(&CliSys::default(), from, to)
{
log::debug!("Failed to hard link dir {:?} to {:?}: {}", from, to, e);
super::copy_dir_recursive(from, to)?;
}

View file

@ -23,8 +23,6 @@ use deno_runtime::deno_fs;
use deno_runtime::deno_node::NodeExtInitServices;
use deno_runtime::deno_node::NodeRequireLoader;
use deno_runtime::deno_node::NodeRequireLoaderRc;
use deno_runtime::deno_node::NodeResolver;
use deno_runtime::deno_node::PackageJsonResolver;
use deno_runtime::deno_permissions::PermissionsContainer;
use deno_runtime::deno_tls::RootCertStoreProvider;
use deno_runtime::deno_web::BlobStore;
@ -53,7 +51,10 @@ use crate::args::DenoSubcommand;
use crate::args::NpmCachingStrategy;
use crate::args::StorageKeyResolver;
use crate::errors;
use crate::node::CliNodeResolver;
use crate::node::CliPackageJsonResolver;
use crate::npm::CliNpmResolver;
use crate::sys::CliSys;
use crate::util::checksum;
use crate::util::file_watcher::WatcherCommunicator;
use crate::util::file_watcher::WatcherRestartMode;
@ -145,13 +146,14 @@ struct SharedWorkerState {
maybe_inspector_server: Option<Arc<InspectorServer>>,
maybe_lockfile: Option<Arc<CliLockfile>>,
module_loader_factory: Box<dyn ModuleLoaderFactory>,
node_resolver: Arc<NodeResolver>,
node_resolver: Arc<CliNodeResolver>,
npm_resolver: Arc<dyn CliNpmResolver>,
pkg_json_resolver: Arc<PackageJsonResolver>,
pkg_json_resolver: Arc<CliPackageJsonResolver>,
root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
root_permissions: PermissionsContainer,
shared_array_buffer_store: SharedArrayBufferStore,
storage_key_resolver: StorageKeyResolver,
sys: CliSys,
options: CliMainWorkerOptions,
subcommand: DenoSubcommand,
otel_config: OtelConfig,
@ -162,12 +164,13 @@ impl SharedWorkerState {
pub fn create_node_init_services(
&self,
node_require_loader: NodeRequireLoaderRc,
) -> NodeExtInitServices {
) -> NodeExtInitServices<CliSys> {
NodeExtInitServices {
node_require_loader,
node_resolver: self.node_resolver.clone(),
npm_resolver: self.npm_resolver.clone().into_npm_pkg_folder_resolver(),
pkg_json_resolver: self.pkg_json_resolver.clone(),
sys: self.sys.clone(),
}
}
@ -418,12 +421,13 @@ impl CliMainWorkerFactory {
maybe_inspector_server: Option<Arc<InspectorServer>>,
maybe_lockfile: Option<Arc<CliLockfile>>,
module_loader_factory: Box<dyn ModuleLoaderFactory>,
node_resolver: Arc<NodeResolver>,
node_resolver: Arc<CliNodeResolver>,
npm_resolver: Arc<dyn CliNpmResolver>,
pkg_json_resolver: Arc<PackageJsonResolver>,
pkg_json_resolver: Arc<CliPackageJsonResolver>,
root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
root_permissions: PermissionsContainer,
storage_key_resolver: StorageKeyResolver,
sys: CliSys,
subcommand: DenoSubcommand,
options: CliMainWorkerOptions,
otel_config: OtelConfig,
@ -448,6 +452,7 @@ impl CliMainWorkerFactory {
root_permissions,
shared_array_buffer_store: Default::default(),
storage_key_resolver,
sys,
options,
subcommand,
otel_config,
@ -869,14 +874,15 @@ mod tests {
let main_module =
resolve_path("./hello.js", &std::env::current_dir().unwrap()).unwrap();
let fs = Arc::new(RealFs);
let permission_desc_parser =
Arc::new(RuntimePermissionDescriptorParser::new(fs.clone()));
let permission_desc_parser = Arc::new(
RuntimePermissionDescriptorParser::new(crate::sys::CliSys::default()),
);
let options = WorkerOptions {
startup_snapshot: crate::js::deno_isolate_init(),
..Default::default()
};
MainWorker::bootstrap_from_options(
MainWorker::bootstrap_from_options::<CliSys>(
main_module,
WorkerServiceOptions {
module_loader: Rc::new(FsModuleLoader),

View file

@ -25,12 +25,10 @@ deno_io.workspace = true
deno_path_util.workspace = true
deno_permissions.workspace = true
filetime.workspace = true
getrandom = "0.2"
libc.workspace = true
rand.workspace = true
rayon = "1.8.0"
serde.workspace = true
sys_traits.workspace = true
thiserror.workspace = true
[target.'cfg(unix)'.dependencies]

View file

@ -1,481 +0,0 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
// Allow using Arc for this module.
#![allow(clippy::disallowed_types)]
use std::borrow::Cow;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::io::Error;
use std::io::ErrorKind;
use std::path::Path;
use std::path::PathBuf;
use std::rc::Rc;
use std::sync::Arc;
use deno_core::parking_lot::Mutex;
use deno_io::fs::File;
use deno_io::fs::FsError;
use deno_io::fs::FsResult;
use deno_io::fs::FsStat;
use deno_path_util::normalize_path;
use crate::interface::AccessCheckCb;
use crate::interface::FsDirEntry;
use crate::interface::FsFileType;
use crate::FileSystem;
use crate::OpenOptions;
#[derive(Debug)]
enum PathEntry {
Dir,
File(Vec<u8>),
}
/// A very basic in-memory file system useful for swapping out in
/// the place of a RealFs for testing purposes.
///
/// Please develop this out as you need functionality.
#[derive(Debug, Default)]
pub struct InMemoryFs {
entries: Mutex<HashMap<PathBuf, Arc<PathEntry>>>,
}
impl InMemoryFs {
pub fn setup_text_files(&self, files: Vec<(String, String)>) {
for (path, text) in files {
let path = PathBuf::from(path);
self.mkdir_sync(path.parent().unwrap(), true, None).unwrap();
self
.write_file_sync(
&path,
OpenOptions::write(true, false, false, None),
None,
&text.into_bytes(),
)
.unwrap();
}
}
fn get_entry(&self, path: &Path) -> Option<Arc<PathEntry>> {
let path = normalize_path(path);
self.entries.lock().get(&path).cloned()
}
}
#[async_trait::async_trait(?Send)]
impl FileSystem for InMemoryFs {
fn cwd(&self) -> FsResult<PathBuf> {
Err(FsError::NotSupported)
}
fn tmp_dir(&self) -> FsResult<PathBuf> {
Err(FsError::NotSupported)
}
fn chdir(&self, _path: &Path) -> FsResult<()> {
Err(FsError::NotSupported)
}
fn umask(&self, _mask: Option<u32>) -> FsResult<u32> {
Err(FsError::NotSupported)
}
fn open_sync(
&self,
_path: &Path,
_options: OpenOptions,
_access_check: Option<AccessCheckCb>,
) -> FsResult<Rc<dyn File>> {
Err(FsError::NotSupported)
}
async fn open_async<'a>(
&'a self,
path: PathBuf,
options: OpenOptions,
access_check: Option<AccessCheckCb<'a>>,
) -> FsResult<Rc<dyn File>> {
self.open_sync(&path, options, access_check)
}
fn mkdir_sync(
&self,
path: &Path,
recursive: bool,
_mode: Option<u32>,
) -> FsResult<()> {
let path = normalize_path(path);
if let Some(parent) = path.parent() {
let entry = self.entries.lock().get(parent).cloned();
match entry {
Some(entry) => match &*entry {
PathEntry::File(_) => {
return Err(FsError::Io(Error::new(
ErrorKind::InvalidInput,
"Parent is a file",
)))
}
PathEntry::Dir => {}
},
None => {
if recursive {
self.mkdir_sync(parent, true, None)?;
} else {
return Err(FsError::Io(Error::new(
ErrorKind::NotFound,
"Not found",
)));
}
}
}
}
let entry = self.entries.lock().get(&path).cloned();
match entry {
Some(entry) => match &*entry {
PathEntry::File(_) => Err(FsError::Io(Error::new(
ErrorKind::InvalidInput,
"Is a file",
))),
PathEntry::Dir => Ok(()),
},
None => {
self.entries.lock().insert(path, Arc::new(PathEntry::Dir));
Ok(())
}
}
}
async fn mkdir_async(
&self,
path: PathBuf,
recursive: bool,
mode: Option<u32>,
) -> FsResult<()> {
self.mkdir_sync(&path, recursive, mode)
}
fn chmod_sync(&self, _path: &Path, _mode: u32) -> FsResult<()> {
Err(FsError::NotSupported)
}
async fn chmod_async(&self, path: PathBuf, mode: u32) -> FsResult<()> {
self.chmod_sync(&path, mode)
}
fn chown_sync(
&self,
_path: &Path,
_uid: Option<u32>,
_gid: Option<u32>,
) -> FsResult<()> {
Err(FsError::NotSupported)
}
async fn chown_async(
&self,
path: PathBuf,
uid: Option<u32>,
gid: Option<u32>,
) -> FsResult<()> {
self.chown_sync(&path, uid, gid)
}
fn lchown_sync(
&self,
_path: &Path,
_uid: Option<u32>,
_gid: Option<u32>,
) -> FsResult<()> {
Err(FsError::NotSupported)
}
async fn lchown_async(
&self,
path: PathBuf,
uid: Option<u32>,
gid: Option<u32>,
) -> FsResult<()> {
self.lchown_sync(&path, uid, gid)
}
fn remove_sync(&self, _path: &Path, _recursive: bool) -> FsResult<()> {
Err(FsError::NotSupported)
}
async fn remove_async(&self, path: PathBuf, recursive: bool) -> FsResult<()> {
self.remove_sync(&path, recursive)
}
fn copy_file_sync(&self, _from: &Path, _to: &Path) -> FsResult<()> {
Err(FsError::NotSupported)
}
async fn copy_file_async(&self, from: PathBuf, to: PathBuf) -> FsResult<()> {
self.copy_file_sync(&from, &to)
}
fn cp_sync(&self, _from: &Path, _to: &Path) -> FsResult<()> {
Err(FsError::NotSupported)
}
async fn cp_async(&self, from: PathBuf, to: PathBuf) -> FsResult<()> {
self.cp_sync(&from, &to)
}
fn stat_sync(&self, path: &Path) -> FsResult<FsStat> {
let entry = self.get_entry(path);
match entry {
Some(entry) => match &*entry {
PathEntry::Dir => Ok(FsStat {
is_file: false,
is_directory: true,
is_symlink: false,
size: 0,
mtime: None,
atime: None,
birthtime: None,
ctime: None,
dev: 0,
ino: 0,
mode: 0,
nlink: 0,
uid: 0,
gid: 0,
rdev: 0,
blksize: 0,
blocks: 0,
is_block_device: false,
is_char_device: false,
is_fifo: false,
is_socket: false,
}),
PathEntry::File(data) => Ok(FsStat {
is_file: true,
is_directory: false,
is_symlink: false,
size: data.len() as u64,
mtime: None,
atime: None,
birthtime: None,
ctime: None,
dev: 0,
ino: 0,
mode: 0,
nlink: 0,
uid: 0,
gid: 0,
rdev: 0,
blksize: 0,
blocks: 0,
is_block_device: false,
is_char_device: false,
is_fifo: false,
is_socket: false,
}),
},
None => Err(FsError::Io(Error::new(ErrorKind::NotFound, "Not found"))),
}
}
async fn stat_async(&self, path: PathBuf) -> FsResult<FsStat> {
self.stat_sync(&path)
}
fn lstat_sync(&self, _path: &Path) -> FsResult<FsStat> {
Err(FsError::NotSupported)
}
async fn lstat_async(&self, path: PathBuf) -> FsResult<FsStat> {
self.lstat_sync(&path)
}
fn realpath_sync(&self, _path: &Path) -> FsResult<PathBuf> {
Err(FsError::NotSupported)
}
async fn realpath_async(&self, path: PathBuf) -> FsResult<PathBuf> {
self.realpath_sync(&path)
}
fn read_dir_sync(&self, _path: &Path) -> FsResult<Vec<FsDirEntry>> {
Err(FsError::NotSupported)
}
async fn read_dir_async(&self, path: PathBuf) -> FsResult<Vec<FsDirEntry>> {
self.read_dir_sync(&path)
}
fn rename_sync(&self, _oldpath: &Path, _newpath: &Path) -> FsResult<()> {
Err(FsError::NotSupported)
}
async fn rename_async(
&self,
oldpath: PathBuf,
newpath: PathBuf,
) -> FsResult<()> {
self.rename_sync(&oldpath, &newpath)
}
fn link_sync(&self, _oldpath: &Path, _newpath: &Path) -> FsResult<()> {
Err(FsError::NotSupported)
}
async fn link_async(
&self,
oldpath: PathBuf,
newpath: PathBuf,
) -> FsResult<()> {
self.link_sync(&oldpath, &newpath)
}
fn symlink_sync(
&self,
_oldpath: &Path,
_newpath: &Path,
_file_type: Option<FsFileType>,
) -> FsResult<()> {
Err(FsError::NotSupported)
}
async fn symlink_async(
&self,
oldpath: PathBuf,
newpath: PathBuf,
file_type: Option<FsFileType>,
) -> FsResult<()> {
self.symlink_sync(&oldpath, &newpath, file_type)
}
fn read_link_sync(&self, _path: &Path) -> FsResult<PathBuf> {
Err(FsError::NotSupported)
}
async fn read_link_async(&self, path: PathBuf) -> FsResult<PathBuf> {
self.read_link_sync(&path)
}
fn truncate_sync(&self, _path: &Path, _len: u64) -> FsResult<()> {
Err(FsError::NotSupported)
}
async fn truncate_async(&self, path: PathBuf, len: u64) -> FsResult<()> {
self.truncate_sync(&path, len)
}
fn utime_sync(
&self,
_path: &Path,
_atime_secs: i64,
_atime_nanos: u32,
_mtime_secs: i64,
_mtime_nanos: u32,
) -> FsResult<()> {
Err(FsError::NotSupported)
}
async fn utime_async(
&self,
path: PathBuf,
atime_secs: i64,
atime_nanos: u32,
mtime_secs: i64,
mtime_nanos: u32,
) -> FsResult<()> {
self.utime_sync(&path, atime_secs, atime_nanos, mtime_secs, mtime_nanos)
}
fn lutime_sync(
&self,
_path: &Path,
_atime_secs: i64,
_atime_nanos: u32,
_mtime_secs: i64,
_mtime_nanos: u32,
) -> FsResult<()> {
Err(FsError::NotSupported)
}
async fn lutime_async(
&self,
path: PathBuf,
atime_secs: i64,
atime_nanos: u32,
mtime_secs: i64,
mtime_nanos: u32,
) -> FsResult<()> {
self.lutime_sync(&path, atime_secs, atime_nanos, mtime_secs, mtime_nanos)
}
fn write_file_sync(
&self,
path: &Path,
options: OpenOptions,
_access_check: Option<AccessCheckCb>,
data: &[u8],
) -> FsResult<()> {
let path = normalize_path(path);
let has_parent_dir = path
.parent()
.and_then(|parent| self.get_entry(parent))
.map(|e| matches!(*e, PathEntry::Dir))
.unwrap_or(false);
if !has_parent_dir {
return Err(FsError::Io(Error::new(
ErrorKind::NotFound,
"Parent directory does not exist",
)));
}
let mut entries = self.entries.lock();
let entry = entries.entry(path.clone());
match entry {
Entry::Occupied(mut entry) => {
if let PathEntry::File(existing_data) = &**entry.get() {
if options.create_new {
return Err(FsError::Io(Error::new(
ErrorKind::AlreadyExists,
"File already exists",
)));
}
if options.append {
let mut new_data = existing_data.clone();
new_data.extend_from_slice(data);
entry.insert(Arc::new(PathEntry::File(new_data)));
} else {
entry.insert(Arc::new(PathEntry::File(data.to_vec())));
}
Ok(())
} else {
Err(FsError::Io(Error::new(
ErrorKind::InvalidInput,
"Not a file",
)))
}
}
Entry::Vacant(entry) => {
entry.insert(Arc::new(PathEntry::File(data.to_vec())));
Ok(())
}
}
}
async fn write_file_async<'a>(
&'a self,
path: PathBuf,
options: OpenOptions,
access_check: Option<AccessCheckCb<'a>>,
data: Vec<u8>,
) -> FsResult<()> {
self.write_file_sync(&path, options, access_check, &data)
}
fn read_file_sync(
&self,
path: &Path,
_access_check: Option<AccessCheckCb>,
) -> FsResult<Cow<'static, [u8]>> {
let entry = self.get_entry(path);
match entry {
Some(entry) => match &*entry {
PathEntry::File(data) => Ok(Cow::Owned(data.clone())),
PathEntry::Dir => Err(FsError::Io(Error::new(
ErrorKind::InvalidInput,
"Is a directory",
))),
},
None => Err(FsError::Io(Error::new(ErrorKind::NotFound, "Not found"))),
}
}
async fn read_file_async<'a>(
&'a self,
path: PathBuf,
access_check: Option<AccessCheckCb<'a>>,
) -> FsResult<Cow<'static, [u8]>> {
self.read_file_sync(&path, access_check)
}
}

View file

@ -5,8 +5,6 @@ use std::borrow::Cow;
use std::path::Path;
use std::path::PathBuf;
use std::rc::Rc;
use std::time::Duration;
use std::time::SystemTime;
use serde::Deserialize;
use serde::Serialize;
@ -14,8 +12,6 @@ use serde::Serialize;
use deno_io::fs::File;
use deno_io::fs::FsResult;
use deno_io::fs::FsStat;
use sys_traits::FsFile;
use sys_traits::FsFileSetPermissions;
use crate::sync::MaybeSend;
use crate::sync::MaybeSync;
@ -75,7 +71,7 @@ pub enum FsFileType {
}
/// WARNING: This is part of the public JS Deno API.
#[derive(Debug, Serialize)]
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FsDirEntry {
pub name: String,
@ -104,56 +100,6 @@ impl<T> AccessCheckFn for T where
{
}
#[derive(Debug)]
pub struct FsStatSlim {
file_type: sys_traits::FileType,
modified: Result<SystemTime, std::io::Error>,
}
impl FsStatSlim {
pub fn from_std(metadata: &std::fs::Metadata) -> Self {
Self {
file_type: metadata.file_type().into(),
modified: metadata.modified(),
}
}
pub fn from_deno_fs_stat(data: &FsStat) -> Self {
FsStatSlim {
file_type: if data.is_file {
sys_traits::FileType::File
} else if data.is_directory {
sys_traits::FileType::Dir
} else if data.is_symlink {
sys_traits::FileType::Symlink
} else {
sys_traits::FileType::Unknown
},
modified: data
.mtime
.map(|ms| SystemTime::UNIX_EPOCH + Duration::from_millis(ms))
.ok_or_else(|| {
std::io::Error::new(std::io::ErrorKind::InvalidData, "No mtime")
}),
}
}
}
impl sys_traits::FsMetadataValue for FsStatSlim {
#[inline]
fn file_type(&self) -> sys_traits::FileType {
self.file_type
}
fn modified(&self) -> Result<SystemTime, std::io::Error> {
self
.modified
.as_ref()
.copied()
.map_err(|err| std::io::Error::new(err.kind(), err.to_string()))
}
}
pub type AccessCheckCb<'a> = &'a mut (dyn AccessCheckFn + 'a);
#[async_trait::async_trait(?Send)]
@ -415,289 +361,3 @@ fn string_from_utf8_lossy(buf: Vec<u8>) -> String {
Cow::Borrowed(_) => unsafe { String::from_utf8_unchecked(buf) },
}
}
// todo(dsherret): this is temporary. Instead of using the `FileSystem` trait implementation
// in the CLI, the CLI should instead create it's own file system using `sys_traits` traits
// then that can implement the `FileSystem` trait. Then this `FileSystem` trait can stay here
// for use only for `ext/fs` and not the entire CLI.
#[derive(Debug, Clone)]
pub struct FsSysTraitsAdapter(pub FileSystemRc);
impl FsSysTraitsAdapter {
pub fn new_real() -> Self {
Self(crate::sync::new_rc(crate::RealFs))
}
}
impl sys_traits::BaseFsHardLink for FsSysTraitsAdapter {
#[inline]
fn base_fs_hard_link(&self, src: &Path, dst: &Path) -> std::io::Result<()> {
self
.0
.link_sync(src, dst)
.map_err(|err| err.into_io_error())
}
}
impl sys_traits::BaseFsRead for FsSysTraitsAdapter {
#[inline]
fn base_fs_read(&self, path: &Path) -> std::io::Result<Cow<'static, [u8]>> {
self
.0
.read_file_sync(path, None)
.map_err(|err| err.into_io_error())
}
}
#[derive(Debug)]
pub struct FsSysTraitsAdapterReadDirEntry {
path: PathBuf,
entry: FsDirEntry,
}
impl sys_traits::FsDirEntry for FsSysTraitsAdapterReadDirEntry {
type Metadata = FsStatSlim;
fn file_name(&self) -> Cow<std::ffi::OsStr> {
Cow::Borrowed(self.entry.name.as_ref())
}
fn file_type(&self) -> std::io::Result<sys_traits::FileType> {
if self.entry.is_file {
Ok(sys_traits::FileType::File)
} else if self.entry.is_directory {
Ok(sys_traits::FileType::Dir)
} else if self.entry.is_symlink {
Ok(sys_traits::FileType::Symlink)
} else {
Ok(sys_traits::FileType::Unknown)
}
}
fn metadata(&self) -> std::io::Result<Self::Metadata> {
Ok(FsStatSlim {
file_type: self.file_type().unwrap(),
modified: Err(std::io::Error::new(
std::io::ErrorKind::Other,
"not supported",
)),
})
}
fn path(&self) -> Cow<Path> {
Cow::Borrowed(&self.path)
}
}
impl sys_traits::BaseFsReadDir for FsSysTraitsAdapter {
type ReadDirEntry = FsSysTraitsAdapterReadDirEntry;
fn base_fs_read_dir(
&self,
path: &Path,
) -> std::io::Result<
Box<dyn Iterator<Item = std::io::Result<Self::ReadDirEntry>>>,
> {
// todo(dsherret): needs to actually be iterable and not allocate a vector
let entries = self
.0
.read_dir_sync(path)
.map_err(|err| err.into_io_error())?;
let parent_dir = path.to_path_buf();
Ok(Box::new(entries.into_iter().map(move |entry| {
Ok(FsSysTraitsAdapterReadDirEntry {
path: parent_dir.join(&entry.name),
entry,
})
})))
}
}
impl sys_traits::BaseFsCanonicalize for FsSysTraitsAdapter {
#[inline]
fn base_fs_canonicalize(&self, path: &Path) -> std::io::Result<PathBuf> {
self
.0
.realpath_sync(path)
.map_err(|err| err.into_io_error())
}
}
impl sys_traits::BaseFsMetadata for FsSysTraitsAdapter {
type Metadata = FsStatSlim;
#[inline]
fn base_fs_metadata(&self, path: &Path) -> std::io::Result<Self::Metadata> {
self
.0
.stat_sync(path)
.map(|data| FsStatSlim::from_deno_fs_stat(&data))
.map_err(|err| err.into_io_error())
}
#[inline]
fn base_fs_symlink_metadata(
&self,
path: &Path,
) -> std::io::Result<Self::Metadata> {
self
.0
.lstat_sync(path)
.map(|data| FsStatSlim::from_deno_fs_stat(&data))
.map_err(|err| err.into_io_error())
}
}
impl sys_traits::BaseFsCreateDir for FsSysTraitsAdapter {
#[inline]
fn base_fs_create_dir(
&self,
path: &Path,
options: &sys_traits::CreateDirOptions,
) -> std::io::Result<()> {
self
.0
.mkdir_sync(path, options.recursive, options.mode)
.map_err(|err| err.into_io_error())
}
}
impl sys_traits::BaseFsRemoveFile for FsSysTraitsAdapter {
#[inline]
fn base_fs_remove_file(&self, path: &Path) -> std::io::Result<()> {
self
.0
.remove_sync(path, false)
.map_err(|err| err.into_io_error())
}
}
impl sys_traits::BaseFsRename for FsSysTraitsAdapter {
#[inline]
fn base_fs_rename(&self, from: &Path, to: &Path) -> std::io::Result<()> {
self
.0
.rename_sync(from, to)
.map_err(|err| err.into_io_error())
}
}
pub struct FsFileAdapter(pub Rc<dyn File>);
impl FsFile for FsFileAdapter {}
impl FsFileSetPermissions for FsFileAdapter {
#[inline]
fn fs_file_set_permissions(&mut self, mode: u32) -> std::io::Result<()> {
if cfg!(windows) {
Ok(()) // ignore
} else {
self
.0
.clone()
.chmod_sync(mode)
.map_err(|err| err.into_io_error())
}
}
}
impl std::io::Read for FsFileAdapter {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
self
.0
.clone()
.read_sync(buf)
.map_err(|err| err.into_io_error())
}
}
impl std::io::Seek for FsFileAdapter {
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
self
.0
.clone()
.seek_sync(pos)
.map_err(|err| err.into_io_error())
}
}
impl std::io::Write for FsFileAdapter {
#[inline]
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self
.0
.clone()
.write_sync(buf)
.map_err(|err| err.into_io_error())
}
#[inline]
fn flush(&mut self) -> std::io::Result<()> {
self
.0
.clone()
.sync_sync()
.map_err(|err| err.into_io_error())
}
}
impl sys_traits::BaseFsOpen for FsSysTraitsAdapter {
type File = FsFileAdapter;
fn base_fs_open(
&self,
path: &Path,
options: &sys_traits::OpenOptions,
) -> std::io::Result<Self::File> {
self
.0
.open_sync(
path,
OpenOptions {
read: options.read,
write: options.write,
create: options.create,
truncate: options.truncate,
append: options.append,
create_new: options.create_new,
mode: options.mode,
},
None,
)
.map(FsFileAdapter)
.map_err(|err| err.into_io_error())
}
}
impl sys_traits::SystemRandom for FsSysTraitsAdapter {
#[inline]
fn sys_random(&self, buf: &mut [u8]) -> std::io::Result<()> {
getrandom::getrandom(buf).map_err(|err| {
std::io::Error::new(std::io::ErrorKind::Other, err.to_string())
})
}
}
impl sys_traits::SystemTimeNow for FsSysTraitsAdapter {
#[inline]
fn sys_time_now(&self) -> SystemTime {
SystemTime::now()
}
}
impl sys_traits::ThreadSleep for FsSysTraitsAdapter {
#[inline]
fn thread_sleep(&self, dur: Duration) {
std::thread::sleep(dur);
}
}
impl sys_traits::BaseEnvVar for FsSysTraitsAdapter {
fn base_env_var_os(
&self,
key: &std::ffi::OsStr,
) -> Option<std::ffi::OsString> {
std::env::var_os(key)
}
}

View file

@ -1,25 +1,20 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
mod in_memory_fs;
mod interface;
mod ops;
mod std_fs;
pub mod sync;
pub use crate::in_memory_fs::InMemoryFs;
pub use crate::interface::AccessCheckCb;
pub use crate::interface::AccessCheckFn;
pub use crate::interface::FileSystem;
pub use crate::interface::FileSystemRc;
pub use crate::interface::FsDirEntry;
pub use crate::interface::FsFileType;
pub use crate::interface::FsStatSlim;
pub use crate::interface::FsSysTraitsAdapter;
pub use crate::interface::OpenOptions;
pub use crate::ops::FsOpsError;
pub use crate::ops::FsOpsErrorKind;
pub use crate::ops::OperationError;
pub use crate::ops::V8MaybeStaticStr;
pub use crate::std_fs::RealFs;
pub use crate::sync::MaybeSend;
pub use crate::sync::MaybeSync;

View file

@ -19,7 +19,6 @@ use crate::FsPermissions;
use crate::OpenOptions;
use boxed_error::Boxed;
use deno_core::op2;
use deno_core::v8;
use deno_core::CancelFuture;
use deno_core::CancelHandle;
use deno_core::FastString;
@ -27,7 +26,6 @@ use deno_core::JsBuffer;
use deno_core::OpState;
use deno_core::ResourceId;
use deno_core::ToJsBuffer;
use deno_core::ToV8;
use deno_io::fs::FileResource;
use deno_io::fs::FsError;
use deno_io::fs::FsStat;
@ -1384,51 +1382,12 @@ where
Ok(buf.into_owned().into_boxed_slice().into())
}
// todo(https://github.com/denoland/deno_core/pull/986): remove
// when upgrading deno_core
#[derive(Debug)]
pub struct FastStringV8AllocationError;
impl std::error::Error for FastStringV8AllocationError {}
impl std::fmt::Display for FastStringV8AllocationError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"failed to allocate string; buffer exceeds maximum length"
)
}
}
/// Maintains a static reference to the string if possible.
pub struct V8MaybeStaticStr(pub Cow<'static, str>);
impl<'s> ToV8<'s> for V8MaybeStaticStr {
type Error = FastStringV8AllocationError;
#[inline]
fn to_v8(
self,
scope: &mut v8::HandleScope<'s>,
) -> Result<v8::Local<'s, v8::Value>, Self::Error> {
Ok(
match self.0 {
Cow::Borrowed(text) => FastString::from_static(text),
Cow::Owned(value) => value.into(),
}
.v8_string(scope)
.map_err(|_| FastStringV8AllocationError)?
.into(),
)
}
}
#[op2(stack_trace)]
#[to_v8]
pub fn op_fs_read_file_text_sync<P>(
state: &mut OpState,
#[string] path: String,
) -> Result<V8MaybeStaticStr, FsOpsError>
) -> Result<FastString, FsOpsError>
where
P: FsPermissions + 'static,
{
@ -1440,7 +1399,10 @@ where
let str = fs
.read_text_file_lossy_sync(&path, Some(&mut access_check))
.map_err(|error| map_permission_error("readfile", error, &path))?;
Ok(V8MaybeStaticStr(str))
Ok(match str {
Cow::Borrowed(text) => FastString::from_static(text),
Cow::Owned(value) => value.into(),
})
}
#[op2(async, stack_trace)]
@ -1449,7 +1411,7 @@ pub async fn op_fs_read_file_text_async<P>(
state: Rc<RefCell<OpState>>,
#[string] path: String,
#[smi] cancel_rid: Option<ResourceId>,
) -> Result<V8MaybeStaticStr, FsOpsError>
) -> Result<FastString, FsOpsError>
where
P: FsPermissions + 'static,
{
@ -1483,7 +1445,10 @@ where
.map_err(|error| map_permission_error("readfile", error, &path))?
};
Ok(V8MaybeStaticStr(str))
Ok(match str {
Cow::Borrowed(text) => FastString::from_static(text),
Cow::Owned(value) => value.into(),
})
}
fn to_seek_from(offset: i64, whence: i32) -> Result<SeekFrom, FsOpsError> {

View file

@ -26,7 +26,7 @@ use crate::interface::FsFileType;
use crate::FileSystem;
use crate::OpenOptions;
#[derive(Debug, Clone)]
#[derive(Debug, Default, Clone)]
pub struct RealFs;
#[async_trait::async_trait(?Send)]

View file

@ -14,7 +14,7 @@ description = "Node compatibility for Deno"
path = "lib.rs"
[features]
sync_fs = ["deno_package_json/sync", "node_resolver/sync"]
sync_fs = ["deno_fs/sync_fs", "deno_package_json/sync", "node_resolver/sync"]
[dependencies]
aead-gcm-stream = "0.4"
@ -93,6 +93,7 @@ simd-json = "0.14.0"
sm3 = "0.4.2"
spki.workspace = true
stable_deref_trait = "1.2.0"
sys_traits = { workspace = true, features = ["real"] }
thiserror.workspace = true
tokio.workspace = true
tokio-eld = "0.2"

View file

@ -14,10 +14,10 @@ use deno_core::url::Url;
#[allow(unused_imports)]
use deno_core::v8;
use deno_core::v8::ExternalReference;
use deno_fs::FsSysTraitsAdapter;
use node_resolver::errors::ClosestPkgJsonError;
use node_resolver::IsBuiltInNodeModuleChecker;
use node_resolver::NpmPackageFolderResolverRc;
use node_resolver::PackageJsonResolverRc;
use once_cell::sync::Lazy;
extern crate libz_sys as zlib;
@ -185,16 +185,17 @@ fn op_node_build_os() -> String {
}
#[derive(Clone)]
pub struct NodeExtInitServices {
pub struct NodeExtInitServices<TSys: ExtNodeSys> {
pub node_require_loader: NodeRequireLoaderRc,
pub node_resolver: NodeResolverRc,
pub node_resolver: NodeResolverRc<TSys>,
pub npm_resolver: NpmPackageFolderResolverRc,
pub pkg_json_resolver: PackageJsonResolverRc,
pub pkg_json_resolver: PackageJsonResolverRc<TSys>,
pub sys: TSys,
}
deno_core::extension!(deno_node,
deps = [ deno_io, deno_fs ],
parameters = [P: NodePermissions],
parameters = [P: NodePermissions, TSys: ExtNodeSys],
ops = [
ops::blocklist::op_socket_address_parse,
ops::blocklist::op_socket_address_get_serialization,
@ -392,29 +393,29 @@ deno_core::extension!(deno_node,
op_node_build_os,
ops::require::op_require_can_parse_as_esm,
ops::require::op_require_init_paths,
ops::require::op_require_node_module_paths<P>,
ops::require::op_require_node_module_paths<P, TSys>,
ops::require::op_require_proxy_path,
ops::require::op_require_is_deno_dir_package,
ops::require::op_require_is_deno_dir_package<TSys>,
ops::require::op_require_resolve_deno_dir,
ops::require::op_require_is_maybe_cjs,
ops::require::op_require_is_request_relative,
ops::require::op_require_resolve_lookup_paths,
ops::require::op_require_try_self_parent_path<P>,
ops::require::op_require_try_self<P>,
ops::require::op_require_real_path<P>,
ops::require::op_require_try_self_parent_path<P, TSys>,
ops::require::op_require_try_self<P, TSys>,
ops::require::op_require_real_path<P, TSys>,
ops::require::op_require_path_is_absolute,
ops::require::op_require_path_dirname,
ops::require::op_require_stat<P>,
ops::require::op_require_stat<P, TSys>,
ops::require::op_require_path_resolve,
ops::require::op_require_path_basename,
ops::require::op_require_read_file<P>,
ops::require::op_require_as_file_path,
ops::require::op_require_resolve_exports<P>,
ops::require::op_require_read_package_scope<P>,
ops::require::op_require_package_imports_resolve<P>,
ops::require::op_require_resolve_exports<P, TSys>,
ops::require::op_require_read_package_scope<P, TSys>,
ops::require::op_require_package_imports_resolve<P, TSys>,
ops::require::op_require_break_on_next_statement,
ops::util::op_node_guess_handle_type,
ops::worker_threads::op_worker_threads_filename<P>,
ops::worker_threads::op_worker_threads_filename<P, TSys>,
ops::ipc::op_node_child_ipc_pipe,
ops::ipc::op_node_ipc_write,
ops::ipc::op_node_ipc_read,
@ -680,13 +681,14 @@ deno_core::extension!(deno_node,
"node:zlib" = "zlib.ts",
],
options = {
maybe_init: Option<NodeExtInitServices>,
maybe_init: Option<NodeExtInitServices<TSys>>,
fs: deno_fs::FileSystemRc,
},
state = |state, options| {
state.put(options.fs.clone());
if let Some(init) = &options.maybe_init {
state.put(init.sys.clone());
state.put(init.node_require_loader.clone());
state.put(init.node_resolver.clone());
state.put(init.npm_resolver.clone());
@ -820,18 +822,22 @@ impl IsBuiltInNodeModuleChecker for RealIsBuiltInNodeModuleChecker {
}
}
pub type NodeResolver = node_resolver::NodeResolver<
RealIsBuiltInNodeModuleChecker,
FsSysTraitsAdapter,
>;
pub trait ExtNodeSys:
sys_traits::BaseFsCanonicalize
+ sys_traits::BaseFsMetadata
+ sys_traits::BaseFsRead
+ sys_traits::EnvCurrentDir
+ Clone
{
}
impl ExtNodeSys for sys_traits::impls::RealSys {}
pub type NodeResolver<TSys> =
node_resolver::NodeResolver<RealIsBuiltInNodeModuleChecker, TSys>;
#[allow(clippy::disallowed_types)]
pub type NodeResolverRc = deno_fs::sync::MaybeArc<NodeResolver>;
pub type PackageJsonResolver =
node_resolver::PackageJsonResolver<FsSysTraitsAdapter>;
pub type NodeResolverRc<TSys> = deno_fs::sync::MaybeArc<NodeResolver<TSys>>;
#[allow(clippy::disallowed_types)]
pub type PackageJsonResolverRc = deno_fs::sync::MaybeArc<
node_resolver::PackageJsonResolver<FsSysTraitsAdapter>,
>;
pub fn create_host_defined_options<'s>(
scope: &mut v8::HandleScope<'s>,

View file

@ -1,14 +1,19 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use std::borrow::Cow;
use std::cell::RefCell;
use std::path::Path;
use std::path::PathBuf;
use std::rc::Rc;
use boxed_error::Boxed;
use deno_core::error::AnyError;
use deno_core::op2;
use deno_core::url::Url;
use deno_core::v8;
use deno_core::FastString;
use deno_core::JsRuntimeInspector;
use deno_core::OpState;
use deno_fs::FileSystemRc;
use deno_fs::V8MaybeStaticStr;
use deno_package_json::PackageJsonRc;
use deno_path_util::normalize_path;
use deno_path_util::url_from_file_path;
@ -17,12 +22,11 @@ use node_resolver::errors::ClosestPkgJsonError;
use node_resolver::NodeResolutionKind;
use node_resolver::ResolutionMode;
use node_resolver::REQUIRE_CONDITIONS;
use std::borrow::Cow;
use std::cell::RefCell;
use std::path::Path;
use std::path::PathBuf;
use std::rc::Rc;
use sys_traits::FsCanonicalize;
use sys_traits::FsMetadata;
use sys_traits::FsMetadataValue;
use crate::ExtNodeSys;
use crate::NodePermissions;
use crate::NodeRequireLoaderRc;
use crate::NodeResolverRc;
@ -68,11 +72,11 @@ pub enum RequireErrorKind {
#[error(transparent)]
UrlConversion(#[from] deno_path_util::PathToUrlError),
#[error(transparent)]
Fs(#[from] deno_io::fs::FsError),
Fs(#[from] std::io::Error),
#[error(transparent)]
ReadModule(deno_core::error::AnyError),
#[error("Unable to get CWD: {0}")]
UnableToGetCwd(deno_io::fs::FsError),
UnableToGetCwd(std::io::Error),
}
#[op2]
@ -128,19 +132,21 @@ pub fn op_require_init_paths() -> Vec<String> {
#[op2(stack_trace)]
#[serde]
pub fn op_require_node_module_paths<P>(
pub fn op_require_node_module_paths<
P: NodePermissions + 'static,
TSys: ExtNodeSys + 'static,
>(
state: &mut OpState,
#[string] from: String,
) -> Result<Vec<String>, RequireError>
where
P: NodePermissions + 'static,
{
let fs = state.borrow::<FileSystemRc>();
) -> Result<Vec<String>, RequireError> {
let sys = state.borrow::<TSys>();
// Guarantee that "from" is absolute.
let from = if from.starts_with("file:///") {
url_to_file_path(&Url::parse(&from)?)?
} else {
let current_dir = &fs.cwd().map_err(RequireErrorKind::UnableToGetCwd)?;
let current_dir = &sys
.env_current_dir()
.map_err(RequireErrorKind::UnableToGetCwd)?;
normalize_path(current_dir.join(from))
};
@ -238,11 +244,11 @@ pub fn op_require_resolve_deno_dir(
}
#[op2(fast)]
pub fn op_require_is_deno_dir_package(
pub fn op_require_is_deno_dir_package<TSys: ExtNodeSys + 'static>(
state: &mut OpState,
#[string] path: String,
) -> bool {
let resolver = state.borrow::<NodeResolverRc>();
let resolver = state.borrow::<NodeResolverRc<TSys>>();
match deno_path_util::url_from_file_path(&PathBuf::from(path)) {
Ok(specifier) => resolver.in_npm_package(&specifier),
Err(_) => false,
@ -297,18 +303,18 @@ pub fn op_require_path_is_absolute(#[string] p: String) -> bool {
}
#[op2(fast, stack_trace)]
pub fn op_require_stat<P>(
pub fn op_require_stat<
P: NodePermissions + 'static,
TSys: ExtNodeSys + 'static,
>(
state: &mut OpState,
#[string] path: String,
) -> Result<i32, deno_core::error::AnyError>
where
P: NodePermissions + 'static,
{
) -> Result<i32, deno_core::error::AnyError> {
let path = PathBuf::from(path);
let path = ensure_read_permission::<P>(state, &path)?;
let fs = state.borrow::<FileSystemRc>();
if let Ok(metadata) = fs.stat_sync(&path) {
if metadata.is_file {
let sys = state.borrow::<TSys>();
if let Ok(metadata) = sys.fs_metadata(&path) {
if metadata.file_type().is_file() {
return Ok(0);
} else {
return Ok(1);
@ -320,19 +326,19 @@ where
#[op2(stack_trace)]
#[string]
pub fn op_require_real_path<P>(
pub fn op_require_real_path<
P: NodePermissions + 'static,
TSys: ExtNodeSys + 'static,
>(
state: &mut OpState,
#[string] request: String,
) -> Result<String, RequireError>
where
P: NodePermissions + 'static,
{
) -> Result<String, RequireError> {
let path = PathBuf::from(request);
let path = ensure_read_permission::<P>(state, &path)
.map_err(RequireErrorKind::Permission)?;
let fs = state.borrow::<FileSystemRc>();
let sys = state.borrow::<TSys>();
let canonicalized_path =
deno_path_util::strip_unc_prefix(fs.realpath_sync(&path)?);
deno_path_util::strip_unc_prefix(sys.fs_canonicalize(&path)?);
Ok(canonicalized_path.to_string_lossy().into_owned())
}
@ -384,15 +390,15 @@ pub fn op_require_path_basename(
#[op2(stack_trace)]
#[string]
pub fn op_require_try_self_parent_path<P>(
pub fn op_require_try_self_parent_path<
P: NodePermissions + 'static,
TSys: ExtNodeSys + 'static,
>(
state: &mut OpState,
has_parent: bool,
#[string] maybe_parent_filename: Option<String>,
#[string] maybe_parent_id: Option<String>,
) -> Result<Option<String>, deno_core::error::AnyError>
where
P: NodePermissions + 'static,
{
) -> Result<Option<String>, deno_core::error::AnyError> {
if !has_parent {
return Ok(None);
}
@ -403,8 +409,8 @@ where
if let Some(parent_id) = maybe_parent_id {
if parent_id == "<repl>" || parent_id == "internal/preload" {
let fs = state.borrow::<FileSystemRc>();
if let Ok(cwd) = fs.cwd() {
let sys = state.borrow::<TSys>();
if let Ok(cwd) = sys.env_current_dir() {
let cwd = ensure_read_permission::<P>(state, &cwd)?;
return Ok(Some(cwd.to_string_lossy().into_owned()));
}
@ -415,19 +421,19 @@ where
#[op2(stack_trace)]
#[string]
pub fn op_require_try_self<P>(
pub fn op_require_try_self<
P: NodePermissions + 'static,
TSys: ExtNodeSys + 'static,
>(
state: &mut OpState,
#[string] parent_path: Option<String>,
#[string] request: String,
) -> Result<Option<String>, RequireError>
where
P: NodePermissions + 'static,
{
) -> Result<Option<String>, RequireError> {
if parent_path.is_none() {
return Ok(None);
}
let pkg_json_resolver = state.borrow::<PackageJsonResolverRc>();
let pkg_json_resolver = state.borrow::<PackageJsonResolverRc<TSys>>();
let pkg = pkg_json_resolver
.get_closest_package_json_from_file_path(&PathBuf::from(
parent_path.unwrap(),
@ -459,7 +465,7 @@ where
let referrer = deno_core::url::Url::from_file_path(&pkg.path).unwrap();
if let Some(exports) = &pkg.exports {
let node_resolver = state.borrow::<NodeResolverRc>();
let node_resolver = state.borrow::<NodeResolverRc<TSys>>();
let r = node_resolver.package_exports_resolve(
&pkg.path,
&expansion,
@ -484,7 +490,7 @@ where
pub fn op_require_read_file<P>(
state: &mut OpState,
#[string] file_path: String,
) -> Result<V8MaybeStaticStr, RequireError>
) -> Result<FastString, RequireError>
where
P: NodePermissions + 'static,
{
@ -495,7 +501,10 @@ where
let loader = state.borrow::<NodeRequireLoaderRc>();
loader
.load_text_file_lossy(&file_path)
.map(V8MaybeStaticStr)
.map(|s| match s {
Cow::Borrowed(s) => FastString::from_static(s),
Cow::Owned(s) => s.into(),
})
.map_err(|e| RequireErrorKind::ReadModule(e).into_box())
}
@ -513,7 +522,10 @@ pub fn op_require_as_file_path(#[string] file_or_url: String) -> String {
#[op2(stack_trace)]
#[string]
pub fn op_require_resolve_exports<P>(
pub fn op_require_resolve_exports<
P: NodePermissions + 'static,
TSys: ExtNodeSys + 'static,
>(
state: &mut OpState,
uses_local_node_modules_dir: bool,
#[string] modules_path_str: String,
@ -521,13 +533,10 @@ pub fn op_require_resolve_exports<P>(
#[string] name: String,
#[string] expansion: String,
#[string] parent_path: String,
) -> Result<Option<String>, RequireError>
where
P: NodePermissions + 'static,
{
let fs = state.borrow::<FileSystemRc>();
let node_resolver = state.borrow::<NodeResolverRc>();
let pkg_json_resolver = state.borrow::<PackageJsonResolverRc>();
) -> Result<Option<String>, RequireError> {
let sys = state.borrow::<TSys>();
let node_resolver = state.borrow::<NodeResolverRc<TSys>>();
let pkg_json_resolver = state.borrow::<PackageJsonResolverRc<TSys>>();
let modules_path = PathBuf::from(&modules_path_str);
let modules_specifier = deno_path_util::url_from_file_path(&modules_path)?;
@ -538,7 +547,7 @@ where
} else {
let mod_dir =
path_resolve([modules_path_str.as_str(), name.as_str()].into_iter());
if fs.is_dir_sync(&mod_dir) {
if sys.fs_is_dir_no_err(&mod_dir) {
mod_dir
} else {
modules_path
@ -589,14 +598,14 @@ pub fn op_require_is_maybe_cjs(
#[op2(stack_trace)]
#[serde]
pub fn op_require_read_package_scope<P>(
pub fn op_require_read_package_scope<
P: NodePermissions + 'static,
TSys: ExtNodeSys + 'static,
>(
state: &mut OpState,
#[string] package_json_path: String,
) -> Option<PackageJsonRc>
where
P: NodePermissions + 'static,
{
let pkg_json_resolver = state.borrow::<PackageJsonResolverRc>();
) -> Option<PackageJsonRc> {
let pkg_json_resolver = state.borrow::<PackageJsonResolverRc<TSys>>();
let package_json_path = PathBuf::from(package_json_path);
if package_json_path.file_name() != Some("package.json".as_ref()) {
// permissions: do not allow reading a non-package.json file
@ -610,18 +619,18 @@ where
#[op2(stack_trace)]
#[string]
pub fn op_require_package_imports_resolve<P>(
pub fn op_require_package_imports_resolve<
P: NodePermissions + 'static,
TSys: ExtNodeSys + 'static,
>(
state: &mut OpState,
#[string] referrer_filename: String,
#[string] request: String,
) -> Result<Option<String>, RequireError>
where
P: NodePermissions + 'static,
{
) -> Result<Option<String>, RequireError> {
let referrer_path = PathBuf::from(&referrer_filename);
let referrer_path = ensure_read_permission::<P>(state, &referrer_path)
.map_err(RequireErrorKind::Permission)?;
let pkg_json_resolver = state.borrow::<PackageJsonResolverRc>();
let pkg_json_resolver = state.borrow::<PackageJsonResolverRc<TSys>>();
let Some(pkg) = pkg_json_resolver
.get_closest_package_json_from_file_path(&referrer_path)?
else {
@ -629,7 +638,7 @@ where
};
if pkg.imports.is_some() {
let node_resolver = state.borrow::<NodeResolverRc>();
let node_resolver = state.borrow::<NodeResolverRc<TSys>>();
let referrer_url = Url::from_file_path(&referrer_filename).unwrap();
let url = node_resolver.package_imports_resolve(
&request,

View file

@ -1,13 +1,16 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use deno_core::op2;
use deno_core::url::Url;
use deno_core::OpState;
use deno_fs::FileSystemRc;
use std::borrow::Cow;
use std::path::Path;
use std::path::PathBuf;
use deno_core::op2;
use deno_core::url::Url;
use deno_core::OpState;
use sys_traits::FsCanonicalize;
use sys_traits::FsMetadata;
use crate::ExtNodeSys;
use crate::NodePermissions;
use crate::NodeRequireLoaderRc;
@ -41,19 +44,19 @@ pub enum WorkerThreadsFilenameError {
#[error("File not found [{0:?}]")]
FileNotFound(PathBuf),
#[error(transparent)]
Fs(#[from] deno_io::fs::FsError),
Fs(#[from] std::io::Error),
}
// todo(dsherret): we should remove this and do all this work inside op_create_worker
#[op2(stack_trace)]
#[string]
pub fn op_worker_threads_filename<P>(
pub fn op_worker_threads_filename<
P: NodePermissions + 'static,
TSys: ExtNodeSys + 'static,
>(
state: &mut OpState,
#[string] specifier: String,
) -> Result<String, WorkerThreadsFilenameError>
where
P: NodePermissions + 'static,
{
) -> Result<String, WorkerThreadsFilenameError> {
if specifier.starts_with("data:") {
return Ok(specifier);
}
@ -66,9 +69,9 @@ where
}
let path = ensure_read_permission::<P>(state, &path)
.map_err(WorkerThreadsFilenameError::Permission)?;
let fs = state.borrow::<FileSystemRc>();
let sys = state.borrow::<TSys>();
let canonicalized_path =
deno_path_util::strip_unc_prefix(fs.realpath_sync(&path)?);
deno_path_util::strip_unc_prefix(sys.fs_canonicalize(&path)?);
Url::from_file_path(canonicalized_path)
.map_err(|_| WorkerThreadsFilenameError::UrlFromPathString)?
};
@ -77,8 +80,8 @@ where
.map_err(|_| WorkerThreadsFilenameError::UrlToPathString)?;
let url_path = ensure_read_permission::<P>(state, &url_path)
.map_err(WorkerThreadsFilenameError::Permission)?;
let fs = state.borrow::<FileSystemRc>();
if !fs.exists_sync(&url_path) {
let sys = state.borrow::<TSys>();
if !sys.fs_exists_no_err(&url_path) {
return Err(WorkerThreadsFilenameError::FileNotFound(
url_path.to_path_buf(),
));

View file

@ -122,6 +122,7 @@ same-file = "1.0.6"
serde.workspace = true
signal-hook = "0.3.17"
signal-hook-registry = "1.4.0"
sys_traits.workspace = true
tempfile.workspace = true
thiserror.workspace = true
tokio.workspace = true

View file

@ -1157,7 +1157,7 @@ mod node {
WorkerThreadsFilenameError::UrlToPathString => "Error",
WorkerThreadsFilenameError::UrlToPath => "Error",
WorkerThreadsFilenameError::FileNotFound(_) => "Error",
WorkerThreadsFilenameError::Fs(e) => super::get_fs_error(e),
WorkerThreadsFilenameError::Fs(e) => super::get_io_error_class(e),
}
}
@ -1173,7 +1173,7 @@ mod node {
| UrlConversion(_)
| ReadModule(_)
| PackageImportsResolve(_) => "Error",
Fs(e) | UnableToGetCwd(e) => super::get_fs_error(e),
Fs(e) | UnableToGetCwd(e) => super::get_io_error_class(e),
}
}

View file

@ -37,11 +37,12 @@ async fn main() -> Result<(), AnyError> {
let main_module = ModuleSpecifier::from_file_path(js_path).unwrap();
eprintln!("Running {main_module}...");
let fs = Arc::new(RealFs);
let permission_desc_parser =
Arc::new(RuntimePermissionDescriptorParser::new(fs.clone()));
let permission_desc_parser = Arc::new(
RuntimePermissionDescriptorParser::new(sys_traits::impls::RealSys),
);
let mut worker = MainWorker::bootstrap_from_options(
main_module.clone(),
WorkerServiceOptions {
WorkerServiceOptions::<sys_traits::impls::RealSys> {
module_loader: Rc::new(FsModuleLoader),
permissions: PermissionsContainer::allow_all(permission_desc_parser),
blob_store: Default::default(),

View file

@ -21,13 +21,17 @@ use deno_permissions::SysDescriptorParseError;
use deno_permissions::WriteDescriptor;
#[derive(Debug)]
pub struct RuntimePermissionDescriptorParser {
fs: deno_fs::FileSystemRc,
pub struct RuntimePermissionDescriptorParser<
TSys: sys_traits::EnvCurrentDir + Send + Sync,
> {
sys: TSys,
}
impl RuntimePermissionDescriptorParser {
pub fn new(fs: deno_fs::FileSystemRc) -> Self {
Self { fs }
impl<TSys: sys_traits::EnvCurrentDir + Send + Sync>
RuntimePermissionDescriptorParser<TSys>
{
pub fn new(sys: TSys) -> Self {
Self { sys }
}
fn resolve_from_cwd(&self, path: &str) -> Result<PathBuf, PathResolveError> {
@ -45,14 +49,15 @@ impl RuntimePermissionDescriptorParser {
fn resolve_cwd(&self) -> Result<PathBuf, PathResolveError> {
self
.fs
.cwd()
.map_err(|e| PathResolveError::CwdResolve(e.into_io_error()))
.sys
.env_current_dir()
.map_err(PathResolveError::CwdResolve)
}
}
impl deno_permissions::PermissionDescriptorParser
for RuntimePermissionDescriptorParser
impl<TSys: sys_traits::EnvCurrentDir + Send + Sync + std::fmt::Debug>
deno_permissions::PermissionDescriptorParser
for RuntimePermissionDescriptorParser<TSys>
{
fn parse_read_descriptor(
&self,
@ -151,16 +156,14 @@ impl deno_permissions::PermissionDescriptorParser
#[cfg(test)]
mod test {
use std::sync::Arc;
use deno_fs::RealFs;
use deno_permissions::PermissionDescriptorParser;
use super::*;
#[test]
fn test_handle_empty_value() {
let parser = RuntimePermissionDescriptorParser::new(Arc::new(RealFs));
let parser =
RuntimePermissionDescriptorParser::new(sys_traits::impls::RealSys);
assert!(parser.parse_read_descriptor("").is_err());
assert!(parser.parse_write_descriptor("").is_err());
assert!(parser.parse_env_descriptor("").is_err());

View file

@ -306,7 +306,10 @@ pub fn create_runtime_snapshot(
),
deno_io::deno_io::init_ops_and_esm(Default::default()),
deno_fs::deno_fs::init_ops_and_esm::<Permissions>(fs.clone()),
deno_node::deno_node::init_ops_and_esm::<Permissions>(None, fs.clone()),
deno_node::deno_node::init_ops_and_esm::<
Permissions,
sys_traits::impls::RealSys,
>(None, fs.clone()),
runtime::init_ops_and_esm(),
ops::runtime::deno_runtime::init_ops("deno:runtime".parse().unwrap()),
ops::worker_host::deno_worker_host::init_ops(

View file

@ -33,6 +33,7 @@ use deno_fs::FileSystem;
use deno_http::DefaultHttpPropertyExtractor;
use deno_io::Stdio;
use deno_kv::dynamic::MultiBackendDbHandler;
use deno_node::ExtNodeSys;
use deno_node::NodeExtInitServices;
use deno_permissions::PermissionsContainer;
use deno_terminal::colors;
@ -337,7 +338,7 @@ fn create_handles(
(internal_handle, external_handle)
}
pub struct WebWorkerServiceOptions {
pub struct WebWorkerServiceOptions<TExtNodeSys: ExtNodeSys + 'static> {
pub blob_store: Arc<BlobStore>,
pub broadcast_channel: InMemoryBroadcastChannel,
pub compiled_wasm_module_store: Option<CompiledWasmModuleStore>,
@ -345,7 +346,7 @@ pub struct WebWorkerServiceOptions {
pub fs: Arc<dyn FileSystem>,
pub maybe_inspector_server: Option<Arc<InspectorServer>>,
pub module_loader: Rc<dyn ModuleLoader>,
pub node_services: Option<NodeExtInitServices>,
pub node_services: Option<NodeExtInitServices<TExtNodeSys>>,
pub npm_process_state_provider: Option<NpmProcessStateProviderRc>,
pub permissions: PermissionsContainer,
pub root_cert_store_provider: Option<Arc<dyn RootCertStoreProvider>>,
@ -402,8 +403,8 @@ impl Drop for WebWorker {
}
impl WebWorker {
pub fn bootstrap_from_options(
services: WebWorkerServiceOptions,
pub fn bootstrap_from_options<TExtNodeSys: ExtNodeSys + 'static>(
services: WebWorkerServiceOptions<TExtNodeSys>,
options: WebWorkerOptions,
) -> (Self, SendableWebWorkerHandle) {
let (mut worker, handle, bootstrap_options) =
@ -412,8 +413,8 @@ impl WebWorker {
(worker, handle)
}
fn from_options(
services: WebWorkerServiceOptions,
fn from_options<TExtNodeSys: ExtNodeSys + 'static>(
services: WebWorkerServiceOptions<TExtNodeSys>,
mut options: WebWorkerOptions,
) -> (Self, SendableWebWorkerHandle, BootstrapOptions) {
deno_core::extension!(deno_permissions_web_worker,
@ -504,7 +505,7 @@ impl WebWorker {
deno_fs::deno_fs::init_ops_and_esm::<PermissionsContainer>(
services.fs.clone(),
),
deno_node::deno_node::init_ops_and_esm::<PermissionsContainer>(
deno_node::deno_node::init_ops_and_esm::<PermissionsContainer, TExtNodeSys>(
services.node_services,
services.fs,
),

View file

@ -39,6 +39,7 @@ use deno_fs::FileSystem;
use deno_http::DefaultHttpPropertyExtractor;
use deno_io::Stdio;
use deno_kv::dynamic::MultiBackendDbHandler;
use deno_node::ExtNodeSys;
use deno_node::NodeExtInitServices;
use deno_permissions::PermissionsContainer;
use deno_tls::RootCertStoreProvider;
@ -128,7 +129,7 @@ pub struct MainWorker {
dispatch_process_exit_event_fn_global: v8::Global<v8::Function>,
}
pub struct WorkerServiceOptions {
pub struct WorkerServiceOptions<TExtNodeSys: ExtNodeSys> {
pub blob_store: Arc<BlobStore>,
pub broadcast_channel: InMemoryBroadcastChannel,
pub feature_checker: Arc<FeatureChecker>,
@ -139,7 +140,7 @@ pub struct WorkerServiceOptions {
/// If not provided runtime will error if code being
/// executed tries to load modules.
pub module_loader: Rc<dyn ModuleLoader>,
pub node_services: Option<NodeExtInitServices>,
pub node_services: Option<NodeExtInitServices<TExtNodeSys>>,
pub npm_process_state_provider: Option<NpmProcessStateProviderRc>,
pub permissions: PermissionsContainer,
pub root_cert_store_provider: Option<Arc<dyn RootCertStoreProvider>>,
@ -304,9 +305,9 @@ pub fn create_op_metrics(
}
impl MainWorker {
pub fn bootstrap_from_options(
pub fn bootstrap_from_options<TExtNodeSys: ExtNodeSys + 'static>(
main_module: ModuleSpecifier,
services: WorkerServiceOptions,
services: WorkerServiceOptions<TExtNodeSys>,
options: WorkerOptions,
) -> Self {
let (mut worker, bootstrap_options) =
@ -315,9 +316,9 @@ impl MainWorker {
worker
}
fn from_options(
fn from_options<TExtNodeSys: ExtNodeSys + 'static>(
main_module: ModuleSpecifier,
services: WorkerServiceOptions,
services: WorkerServiceOptions<TExtNodeSys>,
mut options: WorkerOptions,
) -> (Self, BootstrapOptions) {
deno_core::extension!(deno_permissions_worker,
@ -417,7 +418,7 @@ impl MainWorker {
deno_fs::deno_fs::init_ops_and_esm::<PermissionsContainer>(
services.fs.clone(),
),
deno_node::deno_node::init_ops_and_esm::<PermissionsContainer>(
deno_node::deno_node::init_ops_and_esm::<PermissionsContainer, TExtNodeSys>(
services.node_services,
services.fs,
),