0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-02-08 07:16:56 -05:00

Merge branch 'main' into lsc_cache

This commit is contained in:
Bartek Iwańczuk 2025-01-16 01:33:26 +01:00
commit f7f8274881
No known key found for this signature in database
GPG key ID: 0C6BCDDC3B3AD750
110 changed files with 2768 additions and 2090 deletions

View file

@ -5,7 +5,7 @@ import { stringify } from "jsr:@std/yaml@^0.221/stringify";
// Bump this number when you want to purge the cache. // Bump this number when you want to purge the cache.
// Note: the tools/release/01_bump_crate_versions.ts script will update this version // Note: the tools/release/01_bump_crate_versions.ts script will update this version
// automatically via regex, so ensure that this line maintains this format. // automatically via regex, so ensure that this line maintains this format.
const cacheVersion = 33; const cacheVersion = 35;
const ubuntuX86Runner = "ubuntu-24.04"; const ubuntuX86Runner = "ubuntu-24.04";
const ubuntuX86XlRunner = "ubuntu-24.04-xl"; const ubuntuX86XlRunner = "ubuntu-24.04-xl";
@ -14,7 +14,7 @@ const windowsX86Runner = "windows-2022";
const windowsX86XlRunner = "windows-2022-xl"; const windowsX86XlRunner = "windows-2022-xl";
const macosX86Runner = "macos-13"; const macosX86Runner = "macos-13";
const macosArmRunner = "macos-14"; const macosArmRunner = "macos-14";
const selfHostedMacosArmRunner = "self-hosted"; const selfHostedMacosArmRunner = "ghcr.io/cirruslabs/macos-runner:sonoma";
const Runners = { const Runners = {
linuxX86: { linuxX86: {
@ -41,8 +41,14 @@ const Runners = {
macosArm: { macosArm: {
os: "macos", os: "macos",
arch: "aarch64", arch: "aarch64",
runner: macosArmRunner,
},
macosArmSelfHosted: {
os: "macos",
arch: "aarch64",
// Actually use self-hosted runner only in denoland/deno on `main` branch.
runner: runner:
`\${{ github.repository == 'denoland/deno' && startsWith(github.ref, 'refs/tags/') && '${selfHostedMacosArmRunner}' || '${macosArmRunner}' }}`, `\${{ github.repository == 'denoland/deno' && github.ref == 'refs/heads/main' && '${selfHostedMacosArmRunner}' || '${macosArmRunner}' }}`,
}, },
windowsX86: { windowsX86: {
os: "windows", os: "windows",
@ -384,7 +390,7 @@ const ci = {
job: "test", job: "test",
profile: "debug", profile: "debug",
}, { }, {
...Runners.macosArm, ...Runners.macosArmSelfHosted,
job: "test", job: "test",
profile: "release", profile: "release",
skip_pr: true, skip_pr: true,
@ -486,7 +492,7 @@ const ci = {
}, },
{ {
name: "Cache Cargo home", name: "Cache Cargo home",
uses: "actions/cache@v4", uses: "cirruslabs/cache@v4",
with: { with: {
// See https://doc.rust-lang.org/cargo/guide/cargo-home.html#caching-the-cargo-home-in-ci // See https://doc.rust-lang.org/cargo/guide/cargo-home.html#caching-the-cargo-home-in-ci
// Note that with the new sparse registry format, we no longer have to cache a `.git` dir // Note that with the new sparse registry format, we no longer have to cache a `.git` dir

View file

@ -68,12 +68,12 @@ jobs:
skip: '${{ !contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'') }}' skip: '${{ !contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'') }}'
- os: macos - os: macos
arch: aarch64 arch: aarch64
runner: '${{ github.repository == ''denoland/deno'' && startsWith(github.ref, ''refs/tags/'') && ''self-hosted'' || ''macos-14'' }}' runner: macos-14
job: test job: test
profile: debug profile: debug
- os: macos - os: macos
arch: aarch64 arch: aarch64
runner: '${{ (!contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'')) && ''ubuntu-24.04'' || github.repository == ''denoland/deno'' && startsWith(github.ref, ''refs/tags/'') && ''self-hosted'' || ''macos-14'' }}' runner: '${{ (!contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'')) && ''ubuntu-24.04'' || github.repository == ''denoland/deno'' && github.ref == ''refs/heads/main'' && ''ghcr.io/cirruslabs/macos-runner:sonoma'' || ''macos-14'' }}'
job: test job: test
profile: release profile: release
skip: '${{ !contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'') }}' skip: '${{ !contains(github.event.pull_request.labels.*.name, ''ci-full'') && (github.event_name == ''pull_request'') }}'
@ -175,7 +175,7 @@ jobs:
tar --exclude=".git*" --exclude=target --exclude=third_party/prebuilt \ tar --exclude=".git*" --exclude=target --exclude=third_party/prebuilt \
-czvf target/release/deno_src.tar.gz -C .. deno -czvf target/release/deno_src.tar.gz -C .. deno
- name: Cache Cargo home - name: Cache Cargo home
uses: actions/cache@v4 uses: cirruslabs/cache@v4
with: with:
path: |- path: |-
~/.cargo/.crates.toml ~/.cargo/.crates.toml
@ -184,8 +184,8 @@ jobs:
~/.cargo/registry/index ~/.cargo/registry/index
~/.cargo/registry/cache ~/.cargo/registry/cache
~/.cargo/git/db ~/.cargo/git/db
key: '33-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles(''Cargo.lock'') }}' key: '35-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles(''Cargo.lock'') }}'
restore-keys: '33-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-' restore-keys: '35-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-'
if: '!(matrix.skip)' if: '!(matrix.skip)'
- uses: dsherret/rust-toolchain-file@v1 - uses: dsherret/rust-toolchain-file@v1
if: '!(matrix.skip)' if: '!(matrix.skip)'
@ -379,7 +379,7 @@ jobs:
!./target/*/*.zip !./target/*/*.zip
!./target/*/*.tar.gz !./target/*/*.tar.gz
key: never_saved key: never_saved
restore-keys: '33-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-' restore-keys: '35-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-'
- name: Apply and update mtime cache - name: Apply and update mtime cache
if: '!(matrix.skip) && (!startsWith(github.ref, ''refs/tags/''))' if: '!(matrix.skip) && (!startsWith(github.ref, ''refs/tags/''))'
uses: ./.github/mtime_cache uses: ./.github/mtime_cache
@ -689,7 +689,7 @@ jobs:
!./target/*/gn_root !./target/*/gn_root
!./target/*/*.zip !./target/*/*.zip
!./target/*/*.tar.gz !./target/*/*.tar.gz
key: '33-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}' key: '35-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}'
publish-canary: publish-canary:
name: publish canary name: publish canary
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04

52
Cargo.lock generated
View file

@ -1270,6 +1270,7 @@ dependencies = [
"deno_doc", "deno_doc",
"deno_error", "deno_error",
"deno_graph", "deno_graph",
"deno_lib",
"deno_lint", "deno_lint",
"deno_lockfile", "deno_lockfile",
"deno_npm", "deno_npm",
@ -1902,6 +1903,31 @@ dependencies = [
"url", "url",
] ]
[[package]]
name = "deno_lib"
version = "0.1.1"
dependencies = [
"deno_cache_dir",
"deno_error",
"deno_fs",
"deno_node",
"deno_path_util",
"deno_resolver",
"deno_runtime",
"deno_terminal 0.2.0",
"faster-hex",
"log",
"node_resolver",
"parking_lot",
"ring",
"serde",
"sys_traits",
"test_server",
"thiserror 2.0.3",
"tokio",
"url",
]
[[package]] [[package]]
name = "deno_lint" name = "deno_lint"
version = "0.68.2" version = "0.68.2"
@ -2151,6 +2177,27 @@ dependencies = [
"thiserror 2.0.3", "thiserror 2.0.3",
] ]
[[package]]
name = "deno_os"
version = "0.1.0"
dependencies = [
"deno_core",
"deno_error",
"deno_path_util",
"deno_permissions",
"deno_telemetry",
"libc",
"netif",
"ntapi",
"once_cell",
"serde",
"signal-hook",
"signal-hook-registry",
"thiserror 2.0.3",
"tokio",
"winapi",
]
[[package]] [[package]]
name = "deno_package_json" name = "deno_package_json"
version = "0.4.0" version = "0.4.0"
@ -2251,8 +2298,10 @@ dependencies = [
"deno_napi", "deno_napi",
"deno_net", "deno_net",
"deno_node", "deno_node",
"deno_os",
"deno_path_util", "deno_path_util",
"deno_permissions", "deno_permissions",
"deno_resolver",
"deno_telemetry", "deno_telemetry",
"deno_terminal 0.2.0", "deno_terminal 0.2.0",
"deno_tls", "deno_tls",
@ -2273,7 +2322,6 @@ dependencies = [
"hyper-util", "hyper-util",
"libc", "libc",
"log", "log",
"netif",
"nix", "nix",
"node_resolver", "node_resolver",
"notify", "notify",
@ -2284,8 +2332,6 @@ dependencies = [
"rustyline", "rustyline",
"same-file", "same-file",
"serde", "serde",
"signal-hook",
"signal-hook-registry",
"sys_traits", "sys_traits",
"tempfile", "tempfile",
"test_server", "test_server",

View file

@ -5,6 +5,7 @@ resolver = "2"
members = [ members = [
"bench_util", "bench_util",
"cli", "cli",
"cli/lib",
"ext/broadcast_channel", "ext/broadcast_channel",
"ext/cache", "ext/cache",
"ext/canvas", "ext/canvas",
@ -84,6 +85,7 @@ deno_kv = { version = "0.93.0", path = "./ext/kv" }
deno_napi = { version = "0.116.0", path = "./ext/napi" } deno_napi = { version = "0.116.0", path = "./ext/napi" }
deno_net = { version = "0.177.0", path = "./ext/net" } deno_net = { version = "0.177.0", path = "./ext/net" }
deno_node = { version = "0.123.0", path = "./ext/node" } deno_node = { version = "0.123.0", path = "./ext/node" }
deno_os = { version = "0.1.0", path = "./ext/os" }
deno_telemetry = { version = "0.7.0", path = "./ext/telemetry" } deno_telemetry = { version = "0.7.0", path = "./ext/telemetry" }
deno_tls = { version = "0.172.0", path = "./ext/tls" } deno_tls = { version = "0.172.0", path = "./ext/tls" }
deno_url = { version = "0.185.0", path = "./ext/url" } deno_url = { version = "0.185.0", path = "./ext/url" }
@ -93,7 +95,8 @@ deno_webidl = { version = "0.185.0", path = "./ext/webidl" }
deno_websocket = { version = "0.190.0", path = "./ext/websocket" } deno_websocket = { version = "0.190.0", path = "./ext/websocket" }
deno_webstorage = { version = "0.180.0", path = "./ext/webstorage" } deno_webstorage = { version = "0.180.0", path = "./ext/webstorage" }
# resolvers # workspace libraries
deno_lib = { version = "=0.1.1", path = "./cli/lib" }
deno_npm_cache = { version = "0.4.0", path = "./resolvers/npm_cache" } deno_npm_cache = { version = "0.4.0", path = "./resolvers/npm_cache" }
deno_resolver = { version = "0.16.0", path = "./resolvers/deno" } deno_resolver = { version = "0.16.0", path = "./resolvers/deno" }
node_resolver = { version = "0.23.0", path = "./resolvers/node" } node_resolver = { version = "0.23.0", path = "./resolvers/node" }

View file

@ -76,6 +76,7 @@ deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"]
deno_doc = { version = "=0.164.0", features = ["rust", "comrak"] } deno_doc = { version = "=0.164.0", features = ["rust", "comrak"] }
deno_error.workspace = true deno_error.workspace = true
deno_graph = { version = "=0.87.0" } deno_graph = { version = "=0.87.0" }
deno_lib.workspace = true
deno_lint = { version = "=0.68.2", features = ["docs"] } deno_lint = { version = "=0.68.2", features = ["docs"] }
deno_lockfile.workspace = true deno_lockfile.workspace = true
deno_npm.workspace = true deno_npm.workspace = true

View file

@ -58,6 +58,9 @@ use deno_core::serde_json;
use deno_core::url::Url; use deno_core::url::Url;
use deno_graph::GraphKind; use deno_graph::GraphKind;
pub use deno_json::check_warn_tsconfig; pub use deno_json::check_warn_tsconfig;
use deno_lib::cache::DenoDirProvider;
use deno_lib::env::has_flag_env_var;
use deno_lib::worker::StorageKeyResolver;
use deno_lint::linter::LintConfig as DenoLintConfig; use deno_lint::linter::LintConfig as DenoLintConfig;
use deno_npm::npm_rc::NpmRc; use deno_npm::npm_rc::NpmRc;
use deno_npm::npm_rc::ResolvedNpmRc; use deno_npm::npm_rc::ResolvedNpmRc;
@ -89,7 +92,6 @@ use serde::Serialize;
use sys_traits::EnvHomeDir; use sys_traits::EnvHomeDir;
use thiserror::Error; use thiserror::Error;
use crate::cache::DenoDirProvider;
use crate::file_fetcher::CliFileFetcher; use crate::file_fetcher::CliFileFetcher;
use crate::sys::CliSys; use crate::sys::CliSys;
use crate::util::fs::canonicalize_path_maybe_not_exists; use crate::util::fs::canonicalize_path_maybe_not_exists;
@ -768,7 +770,7 @@ pub struct CliOptions {
maybe_external_import_map: Option<(PathBuf, serde_json::Value)>, maybe_external_import_map: Option<(PathBuf, serde_json::Value)>,
overrides: CliOptionOverrides, overrides: CliOptionOverrides,
pub start_dir: Arc<WorkspaceDirectory>, pub start_dir: Arc<WorkspaceDirectory>,
pub deno_dir_provider: Arc<DenoDirProvider>, pub deno_dir_provider: Arc<DenoDirProvider<CliSys>>,
} }
impl CliOptions { impl CliOptions {
@ -1227,6 +1229,16 @@ impl CliOptions {
} }
} }
pub fn resolve_storage_key_resolver(&self) -> StorageKeyResolver {
if let Some(location) = &self.flags.location {
StorageKeyResolver::from_flag(location)
} else if let Some(deno_json) = self.start_dir.maybe_deno_json() {
StorageKeyResolver::from_config_file_url(&deno_json.specifier)
} else {
StorageKeyResolver::new_use_main_module()
}
}
// If the main module should be treated as being in an npm package. // If the main module should be treated as being in an npm package.
// This is triggered via a secret environment variable which is used // This is triggered via a secret environment variable which is used
// for functionality like child_process.fork. Users should NOT depend // for functionality like child_process.fork. Users should NOT depend
@ -1871,7 +1883,7 @@ fn resolve_node_modules_folder(
cwd: &Path, cwd: &Path,
flags: &Flags, flags: &Flags,
workspace: &Workspace, workspace: &Workspace,
deno_dir_provider: &Arc<DenoDirProvider>, deno_dir_provider: &Arc<DenoDirProvider<CliSys>>,
) -> Result<Option<PathBuf>, AnyError> { ) -> Result<Option<PathBuf>, AnyError> {
fn resolve_from_root(root_folder: &FolderConfigs, cwd: &Path) -> PathBuf { fn resolve_from_root(root_folder: &FolderConfigs, cwd: &Path) -> PathBuf {
root_folder root_folder
@ -1975,63 +1987,11 @@ fn resolve_import_map_specifier(
} }
} }
pub struct StorageKeyResolver(Option<Option<String>>);
impl StorageKeyResolver {
pub fn from_options(options: &CliOptions) -> Self {
Self(if let Some(location) = &options.flags.location {
// if a location is set, then the ascii serialization of the location is
// used, unless the origin is opaque, and then no storage origin is set, as
// we can't expect the origin to be reproducible
let storage_origin = location.origin();
if storage_origin.is_tuple() {
Some(Some(storage_origin.ascii_serialization()))
} else {
Some(None)
}
} else {
// otherwise we will use the path to the config file or None to
// fall back to using the main module's path
options
.start_dir
.maybe_deno_json()
.map(|config_file| Some(config_file.specifier.to_string()))
})
}
/// Creates a storage key resolver that will always resolve to being empty.
pub fn empty() -> Self {
Self(Some(None))
}
/// Resolves the storage key to use based on the current flags, config, or main module.
pub fn resolve_storage_key(
&self,
main_module: &ModuleSpecifier,
) -> Option<String> {
// use the stored value or fall back to using the path of the main module.
if let Some(maybe_value) = &self.0 {
maybe_value.clone()
} else {
Some(main_module.to_string())
}
}
}
/// Resolves the no_prompt value based on the cli flags and environment. /// Resolves the no_prompt value based on the cli flags and environment.
pub fn resolve_no_prompt(flags: &PermissionFlags) -> bool { pub fn resolve_no_prompt(flags: &PermissionFlags) -> bool {
flags.no_prompt || has_flag_env_var("DENO_NO_PROMPT") flags.no_prompt || has_flag_env_var("DENO_NO_PROMPT")
} }
pub fn has_trace_permissions_enabled() -> bool {
has_flag_env_var("DENO_TRACE_PERMISSIONS")
}
pub fn has_flag_env_var(name: &str) -> bool {
let value = env::var(name);
matches!(value.as_ref().map(|s| s.as_str()), Ok("1"))
}
pub fn npm_pkg_req_ref_to_binary_command( pub fn npm_pkg_req_ref_to_binary_command(
req_ref: &NpmPackageReqReference, req_ref: &NpmPackageReqReference,
) -> String { ) -> String {
@ -2160,27 +2120,6 @@ mod test {
assert_eq!(actual, None); assert_eq!(actual, None);
} }
#[test]
fn storage_key_resolver_test() {
let resolver = StorageKeyResolver(None);
let specifier = ModuleSpecifier::parse("file:///a.ts").unwrap();
assert_eq!(
resolver.resolve_storage_key(&specifier),
Some(specifier.to_string())
);
let resolver = StorageKeyResolver(Some(None));
assert_eq!(resolver.resolve_storage_key(&specifier), None);
let resolver = StorageKeyResolver(Some(Some("value".to_string())));
assert_eq!(
resolver.resolve_storage_key(&specifier),
Some("value".to_string())
);
// test empty
let resolver = StorageKeyResolver::empty();
assert_eq!(resolver.resolve_storage_key(&specifier), None);
}
#[test] #[test]
fn jsr_urls() { fn jsr_urls() {
let reg_url = jsr_url(); let reg_url = jsr_url();

7
cli/cache/caches.rs vendored
View file

@ -3,20 +3,21 @@
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
use deno_lib::cache::DenoDirProvider;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use super::cache_db::CacheDB; use super::cache_db::CacheDB;
use super::cache_db::CacheDBConfiguration; use super::cache_db::CacheDBConfiguration;
use super::check::TYPE_CHECK_CACHE_DB; use super::check::TYPE_CHECK_CACHE_DB;
use super::code_cache::CODE_CACHE_DB; use super::code_cache::CODE_CACHE_DB;
use super::deno_dir::DenoDirProvider;
use super::fast_check::FAST_CHECK_CACHE_DB; use super::fast_check::FAST_CHECK_CACHE_DB;
use super::incremental::INCREMENTAL_CACHE_DB; use super::incremental::INCREMENTAL_CACHE_DB;
use super::module_info::MODULE_INFO_CACHE_DB; use super::module_info::MODULE_INFO_CACHE_DB;
use super::node::NODE_ANALYSIS_CACHE_DB; use super::node::NODE_ANALYSIS_CACHE_DB;
use crate::sys::CliSys;
pub struct Caches { pub struct Caches {
dir_provider: Arc<DenoDirProvider>, dir_provider: Arc<DenoDirProvider<CliSys>>,
fmt_incremental_cache_db: OnceCell<CacheDB>, fmt_incremental_cache_db: OnceCell<CacheDB>,
lint_incremental_cache_db: OnceCell<CacheDB>, lint_incremental_cache_db: OnceCell<CacheDB>,
dep_analysis_db: OnceCell<CacheDB>, dep_analysis_db: OnceCell<CacheDB>,
@ -27,7 +28,7 @@ pub struct Caches {
} }
impl Caches { impl Caches {
pub fn new(dir: Arc<DenoDirProvider>) -> Self { pub fn new(dir: Arc<DenoDirProvider<CliSys>>) -> Self {
Self { Self {
dir_provider: dir, dir_provider: dir,
fmt_incremental_cache_db: Default::default(), fmt_incremental_cache_db: Default::default(),

7
cli/cache/emit.rs vendored
View file

@ -6,19 +6,20 @@ use deno_ast::ModuleSpecifier;
use deno_core::anyhow::anyhow; use deno_core::anyhow::anyhow;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::unsync::sync::AtomicFlag; use deno_core::unsync::sync::AtomicFlag;
use deno_lib::cache::DiskCache;
use super::DiskCache; use crate::sys::CliSys;
/// The cache that stores previously emitted files. /// The cache that stores previously emitted files.
#[derive(Debug)] #[derive(Debug)]
pub struct EmitCache { pub struct EmitCache {
disk_cache: DiskCache, disk_cache: DiskCache<CliSys>,
emit_failed_flag: AtomicFlag, emit_failed_flag: AtomicFlag,
file_serializer: EmitFileSerializer, file_serializer: EmitFileSerializer,
} }
impl EmitCache { impl EmitCache {
pub fn new(disk_cache: DiskCache) -> Self { pub fn new(disk_cache: DiskCache<CliSys>) -> Self {
Self { Self {
disk_cache, disk_cache,
emit_failed_flag: Default::default(), emit_failed_flag: Default::default(),

10
cli/cache/mod.rs vendored
View file

@ -15,6 +15,7 @@ use deno_graph::source::CacheInfo;
use deno_graph::source::LoadFuture; use deno_graph::source::LoadFuture;
use deno_graph::source::LoadResponse; use deno_graph::source::LoadResponse;
use deno_graph::source::Loader; use deno_graph::source::Loader;
use deno_resolver::npm::DenoInNpmPackageChecker;
use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::deno_permissions::PermissionsContainer;
use node_resolver::InNpmPackageChecker; use node_resolver::InNpmPackageChecker;
@ -30,8 +31,6 @@ mod caches;
mod check; mod check;
mod code_cache; mod code_cache;
mod common; mod common;
mod deno_dir;
mod disk_cache;
mod emit; mod emit;
mod fast_check; mod fast_check;
mod incremental; mod incremental;
@ -46,9 +45,6 @@ pub use code_cache::CodeCache;
pub use common::FastInsecureHasher; pub use common::FastInsecureHasher;
/// Permissions used to save a file in the disk caches. /// Permissions used to save a file in the disk caches.
pub use deno_cache_dir::CACHE_PERM; pub use deno_cache_dir::CACHE_PERM;
pub use deno_dir::DenoDir;
pub use deno_dir::DenoDirProvider;
pub use disk_cache::DiskCache;
pub use emit::EmitCache; pub use emit::EmitCache;
pub use fast_check::FastCheckCache; pub use fast_check::FastCheckCache;
pub use incremental::IncrementalCache; pub use incremental::IncrementalCache;
@ -76,7 +72,7 @@ pub struct FetchCacher {
pub file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>, pub file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>,
file_fetcher: Arc<CliFileFetcher>, file_fetcher: Arc<CliFileFetcher>,
global_http_cache: Arc<GlobalHttpCache>, global_http_cache: Arc<GlobalHttpCache>,
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>, in_npm_pkg_checker: DenoInNpmPackageChecker,
module_info_cache: Arc<ModuleInfoCache>, module_info_cache: Arc<ModuleInfoCache>,
permissions: PermissionsContainer, permissions: PermissionsContainer,
sys: CliSys, sys: CliSys,
@ -88,7 +84,7 @@ impl FetchCacher {
pub fn new( pub fn new(
file_fetcher: Arc<CliFileFetcher>, file_fetcher: Arc<CliFileFetcher>,
global_http_cache: Arc<GlobalHttpCache>, global_http_cache: Arc<GlobalHttpCache>,
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>, in_npm_pkg_checker: DenoInNpmPackageChecker,
module_info_cache: Arc<ModuleInfoCache>, module_info_cache: Arc<ModuleInfoCache>,
sys: CliSys, sys: CliSys,
options: FetchCacherOptions, options: FetchCacherOptions,

View file

@ -24,11 +24,11 @@ use deno_graph::ModuleGraph;
use crate::cache::EmitCache; use crate::cache::EmitCache;
use crate::cache::FastInsecureHasher; use crate::cache::FastInsecureHasher;
use crate::cache::ParsedSourceCache; use crate::cache::ParsedSourceCache;
use crate::resolver::CjsTracker; use crate::resolver::CliCjsTracker;
#[derive(Debug)] #[derive(Debug)]
pub struct Emitter { pub struct Emitter {
cjs_tracker: Arc<CjsTracker>, cjs_tracker: Arc<CliCjsTracker>,
emit_cache: Arc<EmitCache>, emit_cache: Arc<EmitCache>,
parsed_source_cache: Arc<ParsedSourceCache>, parsed_source_cache: Arc<ParsedSourceCache>,
transpile_and_emit_options: transpile_and_emit_options:
@ -39,7 +39,7 @@ pub struct Emitter {
impl Emitter { impl Emitter {
pub fn new( pub fn new(
cjs_tracker: Arc<CjsTracker>, cjs_tracker: Arc<CliCjsTracker>,
emit_cache: Arc<EmitCache>, emit_cache: Arc<EmitCache>,
parsed_source_cache: Arc<ParsedSourceCache>, parsed_source_cache: Arc<ParsedSourceCache>,
transpile_options: deno_ast::TranspileOptions, transpile_options: deno_ast::TranspileOptions,

View file

@ -11,11 +11,18 @@ use deno_core::error::AnyError;
use deno_core::futures::FutureExt; use deno_core::futures::FutureExt;
use deno_core::FeatureChecker; use deno_core::FeatureChecker;
use deno_error::JsErrorBox; use deno_error::JsErrorBox;
use deno_lib::cache::DenoDir;
use deno_lib::cache::DenoDirProvider;
use deno_lib::npm::NpmRegistryReadPermissionChecker;
use deno_lib::npm::NpmRegistryReadPermissionCheckerMode;
use deno_lib::worker::LibMainWorkerFactory;
use deno_lib::worker::LibMainWorkerOptions;
use deno_npm_cache::NpmCacheSetting; use deno_npm_cache::NpmCacheSetting;
use deno_resolver::cjs::IsCjsResolutionMode; use deno_resolver::cjs::IsCjsResolutionMode;
use deno_resolver::npm::managed::ManagedInNpmPkgCheckerCreateOptions; use deno_resolver::npm::managed::ManagedInNpmPkgCheckerCreateOptions;
use deno_resolver::npm::managed::NpmResolutionCell; use deno_resolver::npm::managed::NpmResolutionCell;
use deno_resolver::npm::CreateInNpmPkgCheckerOptions; use deno_resolver::npm::CreateInNpmPkgCheckerOptions;
use deno_resolver::npm::DenoInNpmPackageChecker;
use deno_resolver::npm::NpmReqResolverOptions; use deno_resolver::npm::NpmReqResolverOptions;
use deno_resolver::sloppy_imports::SloppyImportsCachedFs; use deno_resolver::sloppy_imports::SloppyImportsCachedFs;
use deno_resolver::DenoResolverOptions; use deno_resolver::DenoResolverOptions;
@ -32,7 +39,6 @@ use deno_runtime::inspector_server::InspectorServer;
use deno_runtime::permissions::RuntimePermissionDescriptorParser; use deno_runtime::permissions::RuntimePermissionDescriptorParser;
use log::warn; use log::warn;
use node_resolver::analyze::NodeCodeTranslator; use node_resolver::analyze::NodeCodeTranslator;
use node_resolver::InNpmPackageChecker;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use crate::args::check_warn_tsconfig; use crate::args::check_warn_tsconfig;
@ -42,12 +48,9 @@ use crate::args::CliOptions;
use crate::args::DenoSubcommand; use crate::args::DenoSubcommand;
use crate::args::Flags; use crate::args::Flags;
use crate::args::NpmInstallDepsProvider; use crate::args::NpmInstallDepsProvider;
use crate::args::StorageKeyResolver;
use crate::args::TsConfigType; use crate::args::TsConfigType;
use crate::cache::Caches; use crate::cache::Caches;
use crate::cache::CodeCache; use crate::cache::CodeCache;
use crate::cache::DenoDir;
use crate::cache::DenoDirProvider;
use crate::cache::EmitCache; use crate::cache::EmitCache;
use crate::cache::GlobalHttpCache; use crate::cache::GlobalHttpCache;
use crate::cache::HttpCache; use crate::cache::HttpCache;
@ -68,7 +71,7 @@ use crate::node::CliCjsCodeAnalyzer;
use crate::node::CliNodeCodeTranslator; use crate::node::CliNodeCodeTranslator;
use crate::node::CliNodeResolver; use crate::node::CliNodeResolver;
use crate::node::CliPackageJsonResolver; use crate::node::CliPackageJsonResolver;
use crate::npm::create_cli_npm_resolver; use crate::npm::create_npm_process_state_provider;
use crate::npm::installer::NpmInstaller; use crate::npm::installer::NpmInstaller;
use crate::npm::installer::NpmResolutionInstaller; use crate::npm::installer::NpmResolutionInstaller;
use crate::npm::CliByonmNpmResolverCreateOptions; use crate::npm::CliByonmNpmResolverCreateOptions;
@ -80,10 +83,8 @@ use crate::npm::CliNpmResolver;
use crate::npm::CliNpmResolverCreateOptions; use crate::npm::CliNpmResolverCreateOptions;
use crate::npm::CliNpmResolverManagedSnapshotOption; use crate::npm::CliNpmResolverManagedSnapshotOption;
use crate::npm::CliNpmTarballCache; use crate::npm::CliNpmTarballCache;
use crate::npm::NpmRegistryReadPermissionChecker;
use crate::npm::NpmRegistryReadPermissionCheckerMode;
use crate::npm::NpmResolutionInitializer; use crate::npm::NpmResolutionInitializer;
use crate::resolver::CjsTracker; use crate::resolver::CliCjsTracker;
use crate::resolver::CliDenoResolver; use crate::resolver::CliDenoResolver;
use crate::resolver::CliNpmGraphResolver; use crate::resolver::CliNpmGraphResolver;
use crate::resolver::CliNpmReqResolver; use crate::resolver::CliNpmReqResolver;
@ -190,7 +191,7 @@ impl<T> Deferred<T> {
struct CliFactoryServices { struct CliFactoryServices {
blob_store: Deferred<Arc<BlobStore>>, blob_store: Deferred<Arc<BlobStore>>,
caches: Deferred<Arc<Caches>>, caches: Deferred<Arc<Caches>>,
cjs_tracker: Deferred<Arc<CjsTracker>>, cjs_tracker: Deferred<Arc<CliCjsTracker>>,
cli_options: Deferred<Arc<CliOptions>>, cli_options: Deferred<Arc<CliOptions>>,
code_cache: Deferred<Arc<CodeCache>>, code_cache: Deferred<Arc<CodeCache>>,
deno_resolver: Deferred<Arc<CliDenoResolver>>, deno_resolver: Deferred<Arc<CliDenoResolver>>,
@ -203,7 +204,7 @@ struct CliFactoryServices {
global_http_cache: Deferred<Arc<GlobalHttpCache>>, global_http_cache: Deferred<Arc<GlobalHttpCache>>,
http_cache: Deferred<Arc<dyn HttpCache>>, http_cache: Deferred<Arc<dyn HttpCache>>,
http_client_provider: Deferred<Arc<HttpClientProvider>>, http_client_provider: Deferred<Arc<HttpClientProvider>>,
in_npm_pkg_checker: Deferred<Arc<dyn InNpmPackageChecker>>, in_npm_pkg_checker: Deferred<DenoInNpmPackageChecker>,
main_graph_container: Deferred<Arc<MainModuleGraphContainer>>, main_graph_container: Deferred<Arc<MainModuleGraphContainer>>,
maybe_file_watcher_reporter: Deferred<Option<FileWatcherReporter>>, maybe_file_watcher_reporter: Deferred<Option<FileWatcherReporter>>,
maybe_inspector_server: Deferred<Option<Arc<InspectorServer>>>, maybe_inspector_server: Deferred<Option<Arc<InspectorServer>>>,
@ -223,7 +224,7 @@ struct CliFactoryServices {
npm_resolution: Arc<NpmResolutionCell>, npm_resolution: Arc<NpmResolutionCell>,
npm_resolution_initializer: Deferred<Arc<NpmResolutionInitializer>>, npm_resolution_initializer: Deferred<Arc<NpmResolutionInitializer>>,
npm_resolution_installer: Deferred<Arc<NpmResolutionInstaller>>, npm_resolution_installer: Deferred<Arc<NpmResolutionInstaller>>,
npm_resolver: Deferred<Arc<dyn CliNpmResolver>>, npm_resolver: Deferred<CliNpmResolver>,
npm_tarball_cache: Deferred<Arc<CliNpmTarballCache>>, npm_tarball_cache: Deferred<Arc<CliNpmTarballCache>>,
parsed_source_cache: Deferred<Arc<ParsedSourceCache>>, parsed_source_cache: Deferred<Arc<ParsedSourceCache>>,
permission_desc_parser: permission_desc_parser:
@ -282,11 +283,13 @@ impl CliFactory {
}) })
} }
pub fn deno_dir_provider(&self) -> Result<&Arc<DenoDirProvider>, AnyError> { pub fn deno_dir_provider(
&self,
) -> Result<&Arc<DenoDirProvider<CliSys>>, AnyError> {
Ok(&self.cli_options()?.deno_dir_provider) Ok(&self.cli_options()?.deno_dir_provider)
} }
pub fn deno_dir(&self) -> Result<&DenoDir, AnyError> { pub fn deno_dir(&self) -> Result<&DenoDir<CliSys>, AnyError> {
Ok(self.deno_dir_provider()?.get_or_create()?) Ok(self.deno_dir_provider()?.get_or_create()?)
} }
@ -399,7 +402,7 @@ impl CliFactory {
pub fn in_npm_pkg_checker( pub fn in_npm_pkg_checker(
&self, &self,
) -> Result<&Arc<dyn InNpmPackageChecker>, AnyError> { ) -> Result<&DenoInNpmPackageChecker, AnyError> {
self.services.in_npm_pkg_checker.get_or_try_init(|| { self.services.in_npm_pkg_checker.get_or_try_init(|| {
let cli_options = self.cli_options()?; let cli_options = self.cli_options()?;
let options = if cli_options.use_byonm() { let options = if cli_options.use_byonm() {
@ -414,7 +417,7 @@ impl CliFactory {
}, },
) )
}; };
Ok(deno_resolver::npm::create_in_npm_pkg_checker(options)) Ok(DenoInNpmPackageChecker::new(options))
}) })
} }
@ -559,16 +562,14 @@ impl CliFactory {
}) })
} }
pub async fn npm_resolver( pub async fn npm_resolver(&self) -> Result<&CliNpmResolver, AnyError> {
&self,
) -> Result<&Arc<dyn CliNpmResolver>, AnyError> {
self self
.services .services
.npm_resolver .npm_resolver
.get_or_try_init_async( .get_or_try_init_async(
async { async {
let cli_options = self.cli_options()?; let cli_options = self.cli_options()?;
Ok(create_cli_npm_resolver(if cli_options.use_byonm() { Ok(CliNpmResolver::new(if cli_options.use_byonm() {
CliNpmResolverCreateOptions::Byonm( CliNpmResolverCreateOptions::Byonm(
CliByonmNpmResolverCreateOptions { CliByonmNpmResolverCreateOptions {
sys: self.sys(), sys: self.sys(),
@ -796,11 +797,7 @@ impl CliFactory {
Ok(Arc::new(CliNodeResolver::new( Ok(Arc::new(CliNodeResolver::new(
self.in_npm_pkg_checker()?.clone(), self.in_npm_pkg_checker()?.clone(),
RealIsBuiltInNodeModuleChecker, RealIsBuiltInNodeModuleChecker,
self self.npm_resolver().await?.clone(),
.npm_resolver()
.await?
.clone()
.into_npm_pkg_folder_resolver(),
self.pkg_json_resolver().clone(), self.pkg_json_resolver().clone(),
self.sys(), self.sys(),
node_resolver::ConditionsFromResolutionMode::default(), node_resolver::ConditionsFromResolutionMode::default(),
@ -833,11 +830,7 @@ impl CliFactory {
cjs_esm_analyzer, cjs_esm_analyzer,
self.in_npm_pkg_checker()?.clone(), self.in_npm_pkg_checker()?.clone(),
node_resolver, node_resolver,
self self.npm_resolver().await?.clone(),
.npm_resolver()
.await?
.clone()
.into_npm_pkg_folder_resolver(),
self.pkg_json_resolver().clone(), self.pkg_json_resolver().clone(),
self.sys(), self.sys(),
))) )))
@ -857,7 +850,7 @@ impl CliFactory {
sys: self.sys(), sys: self.sys(),
in_npm_pkg_checker: self.in_npm_pkg_checker()?.clone(), in_npm_pkg_checker: self.in_npm_pkg_checker()?.clone(),
node_resolver: self.node_resolver().await?.clone(), node_resolver: self.node_resolver().await?.clone(),
npm_resolver: npm_resolver.clone().into_byonm_or_managed(), npm_resolver: npm_resolver.clone(),
}))) })))
}) })
.await .await
@ -988,10 +981,10 @@ impl CliFactory {
.await .await
} }
pub fn cjs_tracker(&self) -> Result<&Arc<CjsTracker>, AnyError> { pub fn cjs_tracker(&self) -> Result<&Arc<CliCjsTracker>, AnyError> {
self.services.cjs_tracker.get_or_try_init(|| { self.services.cjs_tracker.get_or_try_init(|| {
let options = self.cli_options()?; let options = self.cli_options()?;
Ok(Arc::new(CjsTracker::new( Ok(Arc::new(CliCjsTracker::new(
self.in_npm_pkg_checker()?.clone(), self.in_npm_pkg_checker()?.clone(),
self.pkg_json_resolver().clone(), self.pkg_json_resolver().clone(),
if options.is_node_main() || options.unstable_detect_cjs() { if options.is_node_main() || options.unstable_detect_cjs() {
@ -1040,7 +1033,7 @@ impl CliFactory {
self.emitter()?, self.emitter()?,
self.file_fetcher()?, self.file_fetcher()?,
self.http_client_provider(), self.http_client_provider(),
self.npm_resolver().await?.as_ref(), self.npm_resolver().await?,
self.workspace_resolver().await?.as_ref(), self.workspace_resolver().await?.as_ref(),
cli_options.npm_system_info(), cli_options.npm_system_info(),
)) ))
@ -1094,19 +1087,7 @@ impl CliFactory {
Arc::new(NpmRegistryReadPermissionChecker::new(self.sys(), mode)) Arc::new(NpmRegistryReadPermissionChecker::new(self.sys(), mode))
}; };
Ok(CliMainWorkerFactory::new( let module_loader_factory = CliModuleLoaderFactory::new(
self.blob_store().clone(),
if cli_options.code_cache_enabled() {
Some(self.code_cache()?.clone())
} else {
None
},
self.feature_checker()?.clone(),
fs.clone(),
maybe_file_watcher_communicator,
self.maybe_inspector_server()?.clone(),
cli_options.maybe_lockfile().cloned(),
Box::new(CliModuleLoaderFactory::new(
cli_options, cli_options,
cjs_tracker, cjs_tracker,
if cli_options.code_cache_enabled() { if cli_options.code_cache_enabled() {
@ -1131,22 +1112,81 @@ impl CliFactory {
self.parsed_source_cache().clone(), self.parsed_source_cache().clone(),
self.resolver().await?.clone(), self.resolver().await?.clone(),
self.sys(), self.sys(),
)), );
let lib_main_worker_factory = LibMainWorkerFactory::new(
self.blob_store().clone(),
if cli_options.code_cache_enabled() {
Some(self.code_cache()?.clone())
} else {
None
},
self.feature_checker()?.clone(),
fs.clone(),
self.maybe_inspector_server()?.clone(),
Box::new(module_loader_factory),
node_resolver.clone(),
create_npm_process_state_provider(npm_resolver),
pkg_json_resolver,
self.root_cert_store_provider().clone(),
cli_options.resolve_storage_key_resolver(),
self.sys(),
self.create_lib_main_worker_options()?,
);
Ok(CliMainWorkerFactory::new(
lib_main_worker_factory,
maybe_file_watcher_communicator,
cli_options.maybe_lockfile().cloned(),
node_resolver.clone(), node_resolver.clone(),
self.npm_installer_if_managed()?.cloned(), self.npm_installer_if_managed()?.cloned(),
npm_resolver.clone(), npm_resolver.clone(),
pkg_json_resolver,
self.root_cert_store_provider().clone(),
self.root_permissions_container()?.clone(),
StorageKeyResolver::from_options(cli_options),
self.sys(), self.sys(),
cli_options.sub_command().clone(),
self.create_cli_main_worker_options()?, self.create_cli_main_worker_options()?,
self.cli_options()?.otel_config(), self.root_permissions_container()?.clone(),
self.cli_options()?.default_npm_caching_strategy(),
)) ))
} }
fn create_lib_main_worker_options(
&self,
) -> Result<LibMainWorkerOptions, AnyError> {
let cli_options = self.cli_options()?;
Ok(LibMainWorkerOptions {
argv: cli_options.argv().clone(),
// This optimization is only available for "run" subcommand
// because we need to register new ops for testing and jupyter
// integration.
skip_op_registration: cli_options.sub_command().is_run(),
log_level: cli_options.log_level().unwrap_or(log::Level::Info).into(),
enable_op_summary_metrics: cli_options.enable_op_summary_metrics(),
enable_testing_features: cli_options.enable_testing_features(),
has_node_modules_dir: cli_options.has_node_modules_dir(),
inspect_brk: cli_options.inspect_brk().is_some(),
inspect_wait: cli_options.inspect_wait().is_some(),
strace_ops: cli_options.strace_ops().clone(),
is_inspecting: cli_options.is_inspecting(),
location: cli_options.location_flag().clone(),
// if the user ran a binary command, we'll need to set process.argv[0]
// to be the name of the binary command instead of deno
argv0: cli_options
.take_binary_npm_command_name()
.or(std::env::args().next()),
node_debug: std::env::var("NODE_DEBUG").ok(),
origin_data_folder_path: Some(self.deno_dir()?.origin_data_folder_path()),
seed: cli_options.seed(),
unsafely_ignore_certificate_errors: cli_options
.unsafely_ignore_certificate_errors()
.clone(),
node_ipc: cli_options.node_ipc_fd(),
serve_port: cli_options.serve_port(),
serve_host: cli_options.serve_host(),
deno_version: crate::version::DENO_VERSION_INFO.deno,
deno_user_agent: crate::version::DENO_VERSION_INFO.user_agent,
otel_config: self.cli_options()?.otel_config(),
startup_snapshot: crate::js::deno_isolate_init(),
})
}
fn create_cli_main_worker_options( fn create_cli_main_worker_options(
&self, &self,
) -> Result<CliMainWorkerOptions, AnyError> { ) -> Result<CliMainWorkerOptions, AnyError> {
@ -1178,37 +1218,10 @@ impl CliFactory {
}; };
Ok(CliMainWorkerOptions { Ok(CliMainWorkerOptions {
argv: cli_options.argv().clone(), needs_test_modules: cli_options.sub_command().needs_test(),
// This optimization is only available for "run" subcommand
// because we need to register new ops for testing and jupyter
// integration.
skip_op_registration: cli_options.sub_command().is_run(),
log_level: cli_options.log_level().unwrap_or(log::Level::Info).into(),
enable_op_summary_metrics: cli_options.enable_op_summary_metrics(),
enable_testing_features: cli_options.enable_testing_features(),
has_node_modules_dir: cli_options.has_node_modules_dir(),
hmr: cli_options.has_hmr(),
inspect_brk: cli_options.inspect_brk().is_some(),
inspect_wait: cli_options.inspect_wait().is_some(),
strace_ops: cli_options.strace_ops().clone(),
is_inspecting: cli_options.is_inspecting(),
location: cli_options.location_flag().clone(),
// if the user ran a binary command, we'll need to set process.argv[0]
// to be the name of the binary command instead of deno
argv0: cli_options
.take_binary_npm_command_name()
.or(std::env::args().next()),
node_debug: std::env::var("NODE_DEBUG").ok(),
origin_data_folder_path: Some(self.deno_dir()?.origin_data_folder_path()),
seed: cli_options.seed(),
unsafely_ignore_certificate_errors: cli_options
.unsafely_ignore_certificate_errors()
.clone(),
create_hmr_runner, create_hmr_runner,
create_coverage_collector, create_coverage_collector,
node_ipc: cli_options.node_ipc_fd(), default_npm_caching_strategy: cli_options.default_npm_caching_strategy(),
serve_port: cli_options.serve_port(),
serve_host: cli_options.serve_host(),
}) })
} }
} }

View file

@ -30,6 +30,7 @@ use deno_graph::ResolutionError;
use deno_graph::SpecifierError; use deno_graph::SpecifierError;
use deno_graph::WorkspaceFastCheckOption; use deno_graph::WorkspaceFastCheckOption;
use deno_path_util::url_to_file_path; use deno_path_util::url_to_file_path;
use deno_resolver::npm::DenoInNpmPackageChecker;
use deno_resolver::sloppy_imports::SloppyImportsCachedFs; use deno_resolver::sloppy_imports::SloppyImportsCachedFs;
use deno_resolver::sloppy_imports::SloppyImportsResolutionKind; use deno_resolver::sloppy_imports::SloppyImportsResolutionKind;
use deno_runtime::deno_node; use deno_runtime::deno_node;
@ -37,7 +38,6 @@ use deno_runtime::deno_permissions::PermissionsContainer;
use deno_semver::jsr::JsrDepPackageReq; use deno_semver::jsr::JsrDepPackageReq;
use deno_semver::package::PackageNv; use deno_semver::package::PackageNv;
use deno_semver::SmallStackString; use deno_semver::SmallStackString;
use node_resolver::InNpmPackageChecker;
use crate::args::config_to_deno_graph_workspace_member; use crate::args::config_to_deno_graph_workspace_member;
use crate::args::jsr_url; use crate::args::jsr_url;
@ -55,7 +55,7 @@ use crate::file_fetcher::CliFileFetcher;
use crate::npm::installer::NpmInstaller; use crate::npm::installer::NpmInstaller;
use crate::npm::installer::PackageCaching; use crate::npm::installer::PackageCaching;
use crate::npm::CliNpmResolver; use crate::npm::CliNpmResolver;
use crate::resolver::CjsTracker; use crate::resolver::CliCjsTracker;
use crate::resolver::CliNpmGraphResolver; use crate::resolver::CliNpmGraphResolver;
use crate::resolver::CliResolver; use crate::resolver::CliResolver;
use crate::resolver::CliSloppyImportsResolver; use crate::resolver::CliSloppyImportsResolver;
@ -493,17 +493,17 @@ pub enum BuildGraphWithNpmResolutionError {
pub struct ModuleGraphBuilder { pub struct ModuleGraphBuilder {
caches: Arc<cache::Caches>, caches: Arc<cache::Caches>,
cjs_tracker: Arc<CjsTracker>, cjs_tracker: Arc<CliCjsTracker>,
cli_options: Arc<CliOptions>, cli_options: Arc<CliOptions>,
file_fetcher: Arc<CliFileFetcher>, file_fetcher: Arc<CliFileFetcher>,
global_http_cache: Arc<GlobalHttpCache>, global_http_cache: Arc<GlobalHttpCache>,
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>, in_npm_pkg_checker: DenoInNpmPackageChecker,
lockfile: Option<Arc<CliLockfile>>, lockfile: Option<Arc<CliLockfile>>,
maybe_file_watcher_reporter: Option<FileWatcherReporter>, maybe_file_watcher_reporter: Option<FileWatcherReporter>,
module_info_cache: Arc<ModuleInfoCache>, module_info_cache: Arc<ModuleInfoCache>,
npm_graph_resolver: Arc<CliNpmGraphResolver>, npm_graph_resolver: Arc<CliNpmGraphResolver>,
npm_installer: Option<Arc<NpmInstaller>>, npm_installer: Option<Arc<NpmInstaller>>,
npm_resolver: Arc<dyn CliNpmResolver>, npm_resolver: CliNpmResolver,
parsed_source_cache: Arc<ParsedSourceCache>, parsed_source_cache: Arc<ParsedSourceCache>,
resolver: Arc<CliResolver>, resolver: Arc<CliResolver>,
root_permissions_container: PermissionsContainer, root_permissions_container: PermissionsContainer,
@ -514,17 +514,17 @@ impl ModuleGraphBuilder {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn new( pub fn new(
caches: Arc<cache::Caches>, caches: Arc<cache::Caches>,
cjs_tracker: Arc<CjsTracker>, cjs_tracker: Arc<CliCjsTracker>,
cli_options: Arc<CliOptions>, cli_options: Arc<CliOptions>,
file_fetcher: Arc<CliFileFetcher>, file_fetcher: Arc<CliFileFetcher>,
global_http_cache: Arc<GlobalHttpCache>, global_http_cache: Arc<GlobalHttpCache>,
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>, in_npm_pkg_checker: DenoInNpmPackageChecker,
lockfile: Option<Arc<CliLockfile>>, lockfile: Option<Arc<CliLockfile>>,
maybe_file_watcher_reporter: Option<FileWatcherReporter>, maybe_file_watcher_reporter: Option<FileWatcherReporter>,
module_info_cache: Arc<ModuleInfoCache>, module_info_cache: Arc<ModuleInfoCache>,
npm_graph_resolver: Arc<CliNpmGraphResolver>, npm_graph_resolver: Arc<CliNpmGraphResolver>,
npm_installer: Option<Arc<NpmInstaller>>, npm_installer: Option<Arc<NpmInstaller>>,
npm_resolver: Arc<dyn CliNpmResolver>, npm_resolver: CliNpmResolver,
parsed_source_cache: Arc<ParsedSourceCache>, parsed_source_cache: Arc<ParsedSourceCache>,
resolver: Arc<CliResolver>, resolver: Arc<CliResolver>,
root_permissions_container: PermissionsContainer, root_permissions_container: PermissionsContainer,
@ -712,8 +712,7 @@ impl ModuleGraphBuilder {
let initial_package_deps_len = graph.packages.package_deps_sum(); let initial_package_deps_len = graph.packages.package_deps_sum();
let initial_package_mappings_len = graph.packages.mappings().len(); let initial_package_mappings_len = graph.packages.mappings().len();
if roots.iter().any(|r| r.scheme() == "npm") if roots.iter().any(|r| r.scheme() == "npm") && self.npm_resolver.is_byonm()
&& self.npm_resolver.as_byonm().is_some()
{ {
return Err(BuildGraphWithNpmResolutionError::UnsupportedNpmSpecifierEntrypointResolutionWay); return Err(BuildGraphWithNpmResolutionError::UnsupportedNpmSpecifierEntrypointResolutionWay);
} }
@ -1226,7 +1225,7 @@ fn format_deno_graph_error(err: &dyn Error) -> String {
#[derive(Debug)] #[derive(Debug)]
struct CliGraphResolver<'a> { struct CliGraphResolver<'a> {
cjs_tracker: &'a CjsTracker, cjs_tracker: &'a CliCjsTracker,
resolver: &'a CliResolver, resolver: &'a CliResolver,
jsx_import_source_config: Option<JsxImportSourceConfig>, jsx_import_source_config: Option<JsxImportSourceConfig>,
} }

View file

@ -8,7 +8,7 @@ import {
restorePermissions, restorePermissions,
} from "ext:cli/40_test_common.js"; } from "ext:cli/40_test_common.js";
import { Console } from "ext:deno_console/01_console.js"; import { Console } from "ext:deno_console/01_console.js";
import { setExitHandler } from "ext:runtime/30_os.js"; import { setExitHandler } from "ext:deno_os/30_os.js";
const { const {
op_register_bench, op_register_bench,
op_bench_get_origin, op_bench_get_origin,

View file

@ -26,7 +26,7 @@ const {
TypeError, TypeError,
} = primordials; } = primordials;
import { setExitHandler } from "ext:runtime/30_os.js"; import { setExitHandler } from "ext:deno_os/30_os.js";
// Capture `Deno` global so that users deleting or mangling it, won't // Capture `Deno` global so that users deleting or mangling it, won't
// have impact on our sanitizers. // have impact on our sanitizers.

37
cli/lib/Cargo.toml Normal file
View file

@ -0,0 +1,37 @@
# Copyright 2018-2025 the Deno authors. MIT license.
[package]
name = "deno_lib"
version = "0.1.1"
authors.workspace = true
edition.workspace = true
license.workspace = true
readme = "README.md"
repository.workspace = true
description = "Shared code between the Deno CLI and denort"
[lib]
path = "lib.rs"
[dependencies]
deno_cache_dir.workspace = true
deno_error.workspace = true
deno_fs = { workspace = true, features = ["sync_fs"] }
deno_node = { workspace = true, features = ["sync_fs"] }
deno_path_util.workspace = true
deno_resolver = { workspace = true, features = ["sync"] }
deno_runtime.workspace = true
deno_terminal.workspace = true
faster-hex.workspace = true
log.workspace = true
node_resolver = { workspace = true, features = ["sync"] }
parking_lot.workspace = true
ring.workspace = true
serde = { workspace = true, features = ["derive"] }
sys_traits.workspace = true
thiserror.workspace = true
tokio.workspace = true
url.workspace = true
[dev-dependencies]
test_util.workspace = true

4
cli/lib/README.md Normal file
View file

@ -0,0 +1,4 @@
# deno_lib
This crate contains the shared code between the Deno CLI and denort. It is
highly unstable.

View file

@ -4,21 +4,20 @@ use std::env;
use std::path::PathBuf; use std::path::PathBuf;
use deno_cache_dir::DenoDirResolutionError; use deno_cache_dir::DenoDirResolutionError;
use once_cell::sync::OnceCell;
use super::DiskCache; use super::DiskCache;
use crate::sys::CliSys; use crate::sys::DenoLibSys;
/// Lazily creates the deno dir which might be useful in scenarios /// Lazily creates the deno dir which might be useful in scenarios
/// where functionality wants to continue if the DENO_DIR can't be created. /// where functionality wants to continue if the DENO_DIR can't be created.
pub struct DenoDirProvider { pub struct DenoDirProvider<TSys: DenoLibSys> {
sys: CliSys, sys: TSys,
maybe_custom_root: Option<PathBuf>, maybe_custom_root: Option<PathBuf>,
deno_dir: OnceCell<Result<DenoDir, DenoDirResolutionError>>, deno_dir: std::sync::OnceLock<Result<DenoDir<TSys>, DenoDirResolutionError>>,
} }
impl DenoDirProvider { impl<TSys: DenoLibSys> DenoDirProvider<TSys> {
pub fn new(sys: CliSys, maybe_custom_root: Option<PathBuf>) -> Self { pub fn new(sys: TSys, maybe_custom_root: Option<PathBuf>) -> Self {
Self { Self {
sys, sys,
maybe_custom_root, maybe_custom_root,
@ -26,7 +25,9 @@ impl DenoDirProvider {
} }
} }
pub fn get_or_create(&self) -> Result<&DenoDir, DenoDirResolutionError> { pub fn get_or_create(
&self,
) -> Result<&DenoDir<TSys>, DenoDirResolutionError> {
self self
.deno_dir .deno_dir
.get_or_init(|| { .get_or_init(|| {
@ -49,16 +50,16 @@ impl DenoDirProvider {
/// `DenoDir` serves as coordinator for multiple `DiskCache`s containing them /// `DenoDir` serves as coordinator for multiple `DiskCache`s containing them
/// in single directory that can be controlled with `$DENO_DIR` env variable. /// in single directory that can be controlled with `$DENO_DIR` env variable.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct DenoDir { pub struct DenoDir<TSys: DenoLibSys> {
/// Example: /Users/rld/.deno/ /// Example: /Users/rld/.deno/
pub root: PathBuf, pub root: PathBuf,
/// Used by TsCompiler to cache compiler output. /// Used by TsCompiler to cache compiler output.
pub gen_cache: DiskCache, pub gen_cache: DiskCache<TSys>,
} }
impl DenoDir { impl<TSys: DenoLibSys> DenoDir<TSys> {
pub fn new( pub fn new(
sys: CliSys, sys: TSys,
maybe_custom_root: Option<PathBuf>, maybe_custom_root: Option<PathBuf>,
) -> Result<Self, deno_cache_dir::DenoDirResolutionError> { ) -> Result<Self, deno_cache_dir::DenoDirResolutionError> {
let root = deno_cache_dir::resolve_deno_dir( let root = deno_cache_dir::resolve_deno_dir(

View file

@ -9,22 +9,22 @@ use std::path::Prefix;
use std::str; use std::str;
use deno_cache_dir::url_to_filename; use deno_cache_dir::url_to_filename;
use deno_core::url::Host; use deno_cache_dir::CACHE_PERM;
use deno_core::url::Url;
use deno_path_util::fs::atomic_write_file_with_retries; use deno_path_util::fs::atomic_write_file_with_retries;
use url::Host;
use url::Url;
use super::CACHE_PERM; use crate::sys::DenoLibSys;
use crate::sys::CliSys;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct DiskCache { pub struct DiskCache<TSys: DenoLibSys> {
sys: CliSys, sys: TSys,
pub location: PathBuf, pub location: PathBuf,
} }
impl DiskCache { impl<TSys: DenoLibSys> DiskCache<TSys> {
/// `location` must be an absolute path. /// `location` must be an absolute path.
pub fn new(sys: CliSys, location: &Path) -> Self { pub fn new(sys: TSys, location: &Path) -> Self {
assert!(location.is_absolute()); assert!(location.is_absolute());
Self { Self {
sys, sys,
@ -130,6 +130,9 @@ impl DiskCache {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
// ok, testing
#[allow(clippy::disallowed_types)]
use sys_traits::impls::RealSys;
use test_util::TempDir; use test_util::TempDir;
use super::*; use super::*;
@ -138,7 +141,7 @@ mod tests {
fn test_set_get_cache_file() { fn test_set_get_cache_file() {
let temp_dir = TempDir::new(); let temp_dir = TempDir::new();
let sub_dir = temp_dir.path().join("sub_dir"); let sub_dir = temp_dir.path().join("sub_dir");
let cache = DiskCache::new(CliSys::default(), &sub_dir.to_path_buf()); let cache = DiskCache::new(RealSys, &sub_dir.to_path_buf());
let path = PathBuf::from("foo/bar.txt"); let path = PathBuf::from("foo/bar.txt");
cache.set(&path, b"hello").unwrap(); cache.set(&path, b"hello").unwrap();
assert_eq!(cache.get(&path).unwrap(), b"hello"); assert_eq!(cache.get(&path).unwrap(), b"hello");
@ -152,7 +155,7 @@ mod tests {
PathBuf::from("/deno_dir/") PathBuf::from("/deno_dir/")
}; };
let cache = DiskCache::new(CliSys::default(), &cache_location); let cache = DiskCache::new(RealSys, &cache_location);
let mut test_cases = vec![ let mut test_cases = vec![
( (
@ -208,7 +211,7 @@ mod tests {
} else { } else {
"/foo" "/foo"
}; };
let cache = DiskCache::new(CliSys::default(), &PathBuf::from(p)); let cache = DiskCache::new(RealSys, &PathBuf::from(p));
let mut test_cases = vec![ let mut test_cases = vec![
( (
@ -256,7 +259,7 @@ mod tests {
PathBuf::from("/deno_dir/") PathBuf::from("/deno_dir/")
}; };
let cache = DiskCache::new(CliSys::default(), &cache_location); let cache = DiskCache::new(RealSys, &cache_location);
let mut test_cases = vec!["unknown://localhost/test.ts"]; let mut test_cases = vec!["unknown://localhost/test.ts"];

8
cli/lib/cache/mod.rs vendored Normal file
View file

@ -0,0 +1,8 @@
// Copyright 2018-2025 the Deno authors. MIT license.
pub use deno_dir::DenoDir;
pub use deno_dir::DenoDirProvider;
pub use disk_cache::DiskCache;
mod deno_dir;
mod disk_cache;

10
cli/lib/env.rs Normal file
View file

@ -0,0 +1,10 @@
// Copyright 2018-2025 the Deno authors. MIT license.
pub fn has_trace_permissions_enabled() -> bool {
has_flag_env_var("DENO_TRACE_PERMISSIONS")
}
pub fn has_flag_env_var(name: &str) -> bool {
let value = std::env::var(name);
matches!(value.as_ref().map(|s| s.as_str()), Ok("1"))
}

9
cli/lib/lib.rs Normal file
View file

@ -0,0 +1,9 @@
// Copyright 2018-2025 the Deno authors. MIT license.
pub mod cache;
pub mod env;
pub mod npm;
pub mod standalone;
pub mod sys;
pub mod util;
pub mod worker;

6
cli/lib/npm/mod.rs Normal file
View file

@ -0,0 +1,6 @@
// Copyright 2018-2025 the Deno authors. MIT license.
mod permission_checker;
pub use permission_checker::NpmRegistryReadPermissionChecker;
pub use permission_checker::NpmRegistryReadPermissionCheckerMode;

View file

@ -6,12 +6,11 @@ use std::io::ErrorKind;
use std::path::Path; use std::path::Path;
use std::path::PathBuf; use std::path::PathBuf;
use deno_core::parking_lot::Mutex;
use deno_error::JsErrorBox; use deno_error::JsErrorBox;
use deno_runtime::deno_node::NodePermissions; use deno_runtime::deno_node::NodePermissions;
use sys_traits::FsCanonicalize; use parking_lot::Mutex;
use crate::sys::CliSys; use crate::sys::DenoLibSys;
#[derive(Debug)] #[derive(Debug)]
pub enum NpmRegistryReadPermissionCheckerMode { pub enum NpmRegistryReadPermissionCheckerMode {
@ -21,8 +20,8 @@ pub enum NpmRegistryReadPermissionCheckerMode {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct NpmRegistryReadPermissionChecker { pub struct NpmRegistryReadPermissionChecker<TSys: DenoLibSys> {
sys: CliSys, sys: TSys,
cache: Mutex<HashMap<PathBuf, PathBuf>>, cache: Mutex<HashMap<PathBuf, PathBuf>>,
mode: NpmRegistryReadPermissionCheckerMode, mode: NpmRegistryReadPermissionCheckerMode,
} }
@ -37,8 +36,8 @@ struct EnsureRegistryReadPermissionError {
source: std::io::Error, source: std::io::Error,
} }
impl NpmRegistryReadPermissionChecker { impl<TSys: DenoLibSys> NpmRegistryReadPermissionChecker<TSys> {
pub fn new(sys: CliSys, mode: NpmRegistryReadPermissionCheckerMode) -> Self { pub fn new(sys: TSys, mode: NpmRegistryReadPermissionCheckerMode) -> Self {
Self { Self {
sys, sys,
cache: Default::default(), cache: Default::default(),

View file

@ -0,0 +1,3 @@
// Copyright 2018-2025 the Deno authors. MIT license.
pub mod virtual_fs;

View file

@ -0,0 +1,296 @@
// Copyright 2018-2025 the Deno authors. MIT license.
use std::cmp::Ordering;
use std::path::Path;
use std::path::PathBuf;
use serde::Deserialize;
use serde::Serialize;
#[derive(Debug, Copy, Clone)]
pub enum VfsFileSubDataKind {
/// Raw bytes of the file.
Raw,
/// Bytes to use for module loading. For example, for TypeScript
/// files this will be the transpiled JavaScript source.
ModuleGraph,
}
#[derive(Debug, PartialEq, Eq)]
pub enum WindowsSystemRootablePath {
/// The root of the system above any drive letters.
WindowSystemRoot,
Path(PathBuf),
}
impl WindowsSystemRootablePath {
pub fn join(&self, name_component: &str) -> PathBuf {
// this method doesn't handle multiple components
debug_assert!(
!name_component.contains('\\'),
"Invalid component: {}",
name_component
);
debug_assert!(
!name_component.contains('/'),
"Invalid component: {}",
name_component
);
match self {
WindowsSystemRootablePath::WindowSystemRoot => {
// windows drive letter
PathBuf::from(&format!("{}\\", name_component))
}
WindowsSystemRootablePath::Path(path) => path.join(name_component),
}
}
}
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub enum FileSystemCaseSensitivity {
#[serde(rename = "s")]
Sensitive,
#[serde(rename = "i")]
Insensitive,
}
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct VirtualDirectoryEntries(Vec<VfsEntry>);
impl VirtualDirectoryEntries {
pub fn new(mut entries: Vec<VfsEntry>) -> Self {
// needs to be sorted by name
entries.sort_by(|a, b| a.name().cmp(b.name()));
Self(entries)
}
pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, VfsEntry> {
self.0.iter_mut()
}
pub fn iter(&self) -> std::slice::Iter<'_, VfsEntry> {
self.0.iter()
}
pub fn take_inner(&mut self) -> Vec<VfsEntry> {
std::mem::take(&mut self.0)
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn get_by_name(
&self,
name: &str,
case_sensitivity: FileSystemCaseSensitivity,
) -> Option<&VfsEntry> {
self
.binary_search(name, case_sensitivity)
.ok()
.map(|index| &self.0[index])
}
pub fn get_mut_by_name(
&mut self,
name: &str,
case_sensitivity: FileSystemCaseSensitivity,
) -> Option<&mut VfsEntry> {
self
.binary_search(name, case_sensitivity)
.ok()
.map(|index| &mut self.0[index])
}
pub fn get_mut_by_index(&mut self, index: usize) -> Option<&mut VfsEntry> {
self.0.get_mut(index)
}
pub fn binary_search(
&self,
name: &str,
case_sensitivity: FileSystemCaseSensitivity,
) -> Result<usize, usize> {
match case_sensitivity {
FileSystemCaseSensitivity::Sensitive => {
self.0.binary_search_by(|e| e.name().cmp(name))
}
FileSystemCaseSensitivity::Insensitive => self.0.binary_search_by(|e| {
e.name()
.chars()
.zip(name.chars())
.map(|(a, b)| a.to_ascii_lowercase().cmp(&b.to_ascii_lowercase()))
.find(|&ord| ord != Ordering::Equal)
.unwrap_or_else(|| e.name().len().cmp(&name.len()))
}),
}
}
pub fn insert(
&mut self,
entry: VfsEntry,
case_sensitivity: FileSystemCaseSensitivity,
) -> usize {
match self.binary_search(entry.name(), case_sensitivity) {
Ok(index) => {
self.0[index] = entry;
index
}
Err(insert_index) => {
self.0.insert(insert_index, entry);
insert_index
}
}
}
pub fn insert_or_modify(
&mut self,
name: &str,
case_sensitivity: FileSystemCaseSensitivity,
on_insert: impl FnOnce() -> VfsEntry,
on_modify: impl FnOnce(&mut VfsEntry),
) -> usize {
match self.binary_search(name, case_sensitivity) {
Ok(index) => {
on_modify(&mut self.0[index]);
index
}
Err(insert_index) => {
self.0.insert(insert_index, on_insert());
insert_index
}
}
}
pub fn remove(&mut self, index: usize) -> VfsEntry {
self.0.remove(index)
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct VirtualDirectory {
#[serde(rename = "n")]
pub name: String,
// should be sorted by name
#[serde(rename = "e")]
pub entries: VirtualDirectoryEntries,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct OffsetWithLength {
#[serde(rename = "o")]
pub offset: u64,
#[serde(rename = "l")]
pub len: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VirtualFile {
#[serde(rename = "n")]
pub name: String,
#[serde(rename = "o")]
pub offset: OffsetWithLength,
/// Offset file to use for module loading when it differs from the
/// raw file. Often this will be the same offset as above for data
/// such as JavaScript files, but for TypeScript files the `offset`
/// will be the original raw bytes when included as an asset and this
/// offset will be to the transpiled JavaScript source.
#[serde(rename = "m")]
pub module_graph_offset: OffsetWithLength,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct VirtualSymlinkParts(Vec<String>);
impl VirtualSymlinkParts {
pub fn from_path(path: &Path) -> Self {
Self(
path
.components()
.filter(|c| !matches!(c, std::path::Component::RootDir))
.map(|c| c.as_os_str().to_string_lossy().to_string())
.collect(),
)
}
pub fn take_parts(&mut self) -> Vec<String> {
std::mem::take(&mut self.0)
}
pub fn parts(&self) -> &[String] {
&self.0
}
pub fn set_parts(&mut self, parts: Vec<String>) {
self.0 = parts;
}
pub fn display(&self) -> String {
self.0.join("/")
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct VirtualSymlink {
#[serde(rename = "n")]
pub name: String,
#[serde(rename = "p")]
pub dest_parts: VirtualSymlinkParts,
}
impl VirtualSymlink {
pub fn resolve_dest_from_root(&self, root: &Path) -> PathBuf {
let mut dest = root.to_path_buf();
for part in &self.dest_parts.0 {
dest.push(part);
}
dest
}
}
#[derive(Debug, Copy, Clone)]
pub enum VfsEntryRef<'a> {
Dir(&'a VirtualDirectory),
File(&'a VirtualFile),
Symlink(&'a VirtualSymlink),
}
impl VfsEntryRef<'_> {
pub fn name(&self) -> &str {
match self {
Self::Dir(dir) => &dir.name,
Self::File(file) => &file.name,
Self::Symlink(symlink) => &symlink.name,
}
}
}
// todo(dsherret): we should store this more efficiently in the binary
#[derive(Debug, Serialize, Deserialize)]
pub enum VfsEntry {
Dir(VirtualDirectory),
File(VirtualFile),
Symlink(VirtualSymlink),
}
impl VfsEntry {
pub fn name(&self) -> &str {
match self {
Self::Dir(dir) => &dir.name,
Self::File(file) => &file.name,
Self::Symlink(symlink) => &symlink.name,
}
}
pub fn as_ref(&self) -> VfsEntryRef {
match self {
VfsEntry::Dir(dir) => VfsEntryRef::Dir(dir),
VfsEntry::File(file) => VfsEntryRef::File(file),
VfsEntry::Symlink(symlink) => VfsEntryRef::Symlink(symlink),
}
}
}

37
cli/lib/sys.rs Normal file
View file

@ -0,0 +1,37 @@
// Copyright 2018-2025 the Deno authors. MIT license.
use deno_node::ExtNodeSys;
use sys_traits::FsCanonicalize;
use sys_traits::FsCreateDirAll;
use sys_traits::FsMetadata;
use sys_traits::FsOpen;
use sys_traits::FsRead;
use sys_traits::FsReadDir;
use sys_traits::FsRemoveFile;
use sys_traits::FsRename;
use sys_traits::SystemRandom;
use sys_traits::ThreadSleep;
pub trait DenoLibSys:
FsCanonicalize
+ FsCreateDirAll
+ FsReadDir
+ FsMetadata
+ FsOpen
+ FsRemoveFile
+ FsRename
+ FsRead
+ ThreadSleep
+ SystemRandom
+ ExtNodeSys
+ Clone
+ Send
+ Sync
+ std::fmt::Debug
+ 'static
{
}
// ok, implementation
#[allow(clippy::disallowed_types)]
impl DenoLibSys for sys_traits::impls::RealSys {}

3
cli/lib/util/mod.rs Normal file
View file

@ -0,0 +1,3 @@
// Copyright 2018-2025 the Deno authors. MIT license.
pub mod checksum;

581
cli/lib/worker.rs Normal file
View file

@ -0,0 +1,581 @@
// Copyright 2018-2025 the Deno authors. MIT license.
use std::path::PathBuf;
use std::rc::Rc;
use std::sync::Arc;
use deno_core::error::JsError;
use deno_node::NodeRequireLoaderRc;
use deno_resolver::npm::DenoInNpmPackageChecker;
use deno_resolver::npm::NpmResolver;
use deno_runtime::colors;
use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel;
use deno_runtime::deno_core;
use deno_runtime::deno_core::error::CoreError;
use deno_runtime::deno_core::v8;
use deno_runtime::deno_core::CompiledWasmModuleStore;
use deno_runtime::deno_core::Extension;
use deno_runtime::deno_core::FeatureChecker;
use deno_runtime::deno_core::JsRuntime;
use deno_runtime::deno_core::LocalInspectorSession;
use deno_runtime::deno_core::ModuleLoader;
use deno_runtime::deno_core::SharedArrayBufferStore;
use deno_runtime::deno_fs;
use deno_runtime::deno_node::NodeExtInitServices;
use deno_runtime::deno_node::NodeRequireLoader;
use deno_runtime::deno_node::NodeResolver;
use deno_runtime::deno_permissions::PermissionsContainer;
use deno_runtime::deno_telemetry::OtelConfig;
use deno_runtime::deno_tls::RootCertStoreProvider;
use deno_runtime::deno_web::BlobStore;
use deno_runtime::fmt_errors::format_js_error;
use deno_runtime::inspector_server::InspectorServer;
use deno_runtime::ops::process::NpmProcessStateProviderRc;
use deno_runtime::ops::worker_host::CreateWebWorkerCb;
use deno_runtime::web_worker::WebWorker;
use deno_runtime::web_worker::WebWorkerOptions;
use deno_runtime::web_worker::WebWorkerServiceOptions;
use deno_runtime::worker::MainWorker;
use deno_runtime::worker::WorkerOptions;
use deno_runtime::worker::WorkerServiceOptions;
use deno_runtime::BootstrapOptions;
use deno_runtime::WorkerExecutionMode;
use deno_runtime::WorkerLogLevel;
use deno_runtime::UNSTABLE_GRANULAR_FLAGS;
use url::Url;
use crate::env::has_trace_permissions_enabled;
use crate::sys::DenoLibSys;
use crate::util::checksum;
pub struct CreateModuleLoaderResult {
pub module_loader: Rc<dyn ModuleLoader>,
pub node_require_loader: Rc<dyn NodeRequireLoader>,
}
pub trait ModuleLoaderFactory: Send + Sync {
fn create_for_main(
&self,
root_permissions: PermissionsContainer,
) -> CreateModuleLoaderResult;
fn create_for_worker(
&self,
parent_permissions: PermissionsContainer,
permissions: PermissionsContainer,
) -> CreateModuleLoaderResult;
}
enum StorageKeyResolverStrategy {
Specified(Option<String>),
UseMainModule,
}
pub struct StorageKeyResolver(StorageKeyResolverStrategy);
impl StorageKeyResolver {
pub fn from_flag(location: &Url) -> Self {
// if a location is set, then the ascii serialization of the location is
// used, unless the origin is opaque, and then no storage origin is set, as
// we can't expect the origin to be reproducible
let storage_origin = location.origin();
Self(StorageKeyResolverStrategy::Specified(
if storage_origin.is_tuple() {
Some(storage_origin.ascii_serialization())
} else {
None
},
))
}
pub fn from_config_file_url(url: &Url) -> Self {
Self(StorageKeyResolverStrategy::Specified(Some(url.to_string())))
}
pub fn new_use_main_module() -> Self {
Self(StorageKeyResolverStrategy::UseMainModule)
}
/// Creates a storage key resolver that will always resolve to being empty.
pub fn empty() -> Self {
Self(StorageKeyResolverStrategy::Specified(None))
}
/// Resolves the storage key to use based on the current flags, config, or main module.
pub fn resolve_storage_key(&self, main_module: &Url) -> Option<String> {
// use the stored value or fall back to using the path of the main module.
match &self.0 {
StorageKeyResolverStrategy::Specified(value) => value.clone(),
StorageKeyResolverStrategy::UseMainModule => {
Some(main_module.to_string())
}
}
}
}
// TODO(bartlomieju): this should be moved to some other place, added to avoid string
// duplication between worker setups and `deno info` output.
pub fn get_cache_storage_dir() -> PathBuf {
// Note: we currently use temp_dir() to avoid managing storage size.
std::env::temp_dir().join("deno_cache")
}
/// By default V8 uses 1.4Gb heap limit which is meant for browser tabs.
/// Instead probe for the total memory on the system and use it instead
/// as a default.
pub fn create_isolate_create_params() -> Option<v8::CreateParams> {
let maybe_mem_info = deno_runtime::deno_os::sys_info::mem_info();
maybe_mem_info.map(|mem_info| {
v8::CreateParams::default()
.heap_limits_from_system_memory(mem_info.total, 0)
})
}
pub struct LibMainWorkerOptions {
pub argv: Vec<String>,
pub deno_version: &'static str,
pub deno_user_agent: &'static str,
pub log_level: WorkerLogLevel,
pub enable_op_summary_metrics: bool,
pub enable_testing_features: bool,
pub has_node_modules_dir: bool,
pub inspect_brk: bool,
pub inspect_wait: bool,
pub strace_ops: Option<Vec<String>>,
pub is_inspecting: bool,
pub location: Option<Url>,
pub argv0: Option<String>,
pub node_debug: Option<String>,
pub otel_config: OtelConfig,
pub origin_data_folder_path: Option<PathBuf>,
pub seed: Option<u64>,
pub unsafely_ignore_certificate_errors: Option<Vec<String>>,
pub skip_op_registration: bool,
pub node_ipc: Option<i64>,
pub startup_snapshot: Option<&'static [u8]>,
pub serve_port: Option<u16>,
pub serve_host: Option<String>,
}
struct LibWorkerFactorySharedState<TSys: DenoLibSys> {
blob_store: Arc<BlobStore>,
broadcast_channel: InMemoryBroadcastChannel,
code_cache: Option<Arc<dyn deno_runtime::code_cache::CodeCache>>,
compiled_wasm_module_store: CompiledWasmModuleStore,
feature_checker: Arc<FeatureChecker>,
fs: Arc<dyn deno_fs::FileSystem>,
maybe_inspector_server: Option<Arc<InspectorServer>>,
module_loader_factory: Box<dyn ModuleLoaderFactory>,
node_resolver:
Arc<NodeResolver<DenoInNpmPackageChecker, NpmResolver<TSys>, TSys>>,
npm_process_state_provider: NpmProcessStateProviderRc,
pkg_json_resolver: Arc<node_resolver::PackageJsonResolver<TSys>>,
root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
shared_array_buffer_store: SharedArrayBufferStore,
storage_key_resolver: StorageKeyResolver,
sys: TSys,
options: LibMainWorkerOptions,
}
impl<TSys: DenoLibSys> LibWorkerFactorySharedState<TSys> {
fn resolve_unstable_features(
&self,
feature_checker: &FeatureChecker,
) -> Vec<i32> {
let mut unstable_features =
Vec::with_capacity(UNSTABLE_GRANULAR_FLAGS.len());
for granular_flag in UNSTABLE_GRANULAR_FLAGS {
if feature_checker.check(granular_flag.name) {
unstable_features.push(granular_flag.id);
}
}
unstable_features
}
fn create_node_init_services(
&self,
node_require_loader: NodeRequireLoaderRc,
) -> NodeExtInitServices<DenoInNpmPackageChecker, NpmResolver<TSys>, TSys> {
NodeExtInitServices {
node_require_loader,
node_resolver: self.node_resolver.clone(),
pkg_json_resolver: self.pkg_json_resolver.clone(),
sys: self.sys.clone(),
}
}
fn create_web_worker_callback(
self: &Arc<Self>,
stdio: deno_runtime::deno_io::Stdio,
) -> Arc<CreateWebWorkerCb> {
let shared = self.clone();
Arc::new(move |args| {
let maybe_inspector_server = shared.maybe_inspector_server.clone();
let CreateModuleLoaderResult {
module_loader,
node_require_loader,
} = shared.module_loader_factory.create_for_worker(
args.parent_permissions.clone(),
args.permissions.clone(),
);
let create_web_worker_cb =
shared.create_web_worker_callback(stdio.clone());
let maybe_storage_key = shared
.storage_key_resolver
.resolve_storage_key(&args.main_module);
let cache_storage_dir = maybe_storage_key.map(|key| {
// TODO(@satyarohith): storage quota management
get_cache_storage_dir().join(checksum::gen(&[key.as_bytes()]))
});
// TODO(bartlomieju): this is cruft, update FeatureChecker to spit out
// list of enabled features.
let feature_checker = shared.feature_checker.clone();
let unstable_features =
shared.resolve_unstable_features(feature_checker.as_ref());
let services = WebWorkerServiceOptions {
root_cert_store_provider: Some(shared.root_cert_store_provider.clone()),
module_loader,
fs: shared.fs.clone(),
node_services: Some(
shared.create_node_init_services(node_require_loader),
),
blob_store: shared.blob_store.clone(),
broadcast_channel: shared.broadcast_channel.clone(),
shared_array_buffer_store: Some(
shared.shared_array_buffer_store.clone(),
),
compiled_wasm_module_store: Some(
shared.compiled_wasm_module_store.clone(),
),
maybe_inspector_server,
feature_checker,
npm_process_state_provider: Some(
shared.npm_process_state_provider.clone(),
),
permissions: args.permissions,
};
let options = WebWorkerOptions {
name: args.name,
main_module: args.main_module.clone(),
worker_id: args.worker_id,
bootstrap: BootstrapOptions {
deno_version: shared.options.deno_version.to_string(),
args: shared.options.argv.clone(),
cpu_count: std::thread::available_parallelism()
.map(|p| p.get())
.unwrap_or(1),
log_level: shared.options.log_level,
enable_op_summary_metrics: shared.options.enable_op_summary_metrics,
enable_testing_features: shared.options.enable_testing_features,
locale: deno_core::v8::icu::get_language_tag(),
location: Some(args.main_module),
no_color: !colors::use_color(),
color_level: colors::get_color_level(),
is_stdout_tty: deno_terminal::is_stdout_tty(),
is_stderr_tty: deno_terminal::is_stderr_tty(),
unstable_features,
user_agent: shared.options.deno_user_agent.to_string(),
inspect: shared.options.is_inspecting,
has_node_modules_dir: shared.options.has_node_modules_dir,
argv0: shared.options.argv0.clone(),
node_debug: shared.options.node_debug.clone(),
node_ipc_fd: None,
mode: WorkerExecutionMode::Worker,
serve_port: shared.options.serve_port,
serve_host: shared.options.serve_host.clone(),
otel_config: shared.options.otel_config.clone(),
close_on_idle: args.close_on_idle,
},
extensions: vec![],
startup_snapshot: shared.options.startup_snapshot,
create_params: create_isolate_create_params(),
unsafely_ignore_certificate_errors: shared
.options
.unsafely_ignore_certificate_errors
.clone(),
seed: shared.options.seed,
create_web_worker_cb,
format_js_error_fn: Some(Arc::new(format_js_error)),
worker_type: args.worker_type,
stdio: stdio.clone(),
cache_storage_dir,
strace_ops: shared.options.strace_ops.clone(),
close_on_idle: args.close_on_idle,
maybe_worker_metadata: args.maybe_worker_metadata,
enable_stack_trace_arg_in_ops: has_trace_permissions_enabled(),
};
WebWorker::bootstrap_from_options(services, options)
})
}
}
pub struct LibMainWorkerFactory<TSys: DenoLibSys> {
shared: Arc<LibWorkerFactorySharedState<TSys>>,
}
impl<TSys: DenoLibSys> LibMainWorkerFactory<TSys> {
#[allow(clippy::too_many_arguments)]
pub fn new(
blob_store: Arc<BlobStore>,
code_cache: Option<Arc<dyn deno_runtime::code_cache::CodeCache>>,
feature_checker: Arc<FeatureChecker>,
fs: Arc<dyn deno_fs::FileSystem>,
maybe_inspector_server: Option<Arc<InspectorServer>>,
module_loader_factory: Box<dyn ModuleLoaderFactory>,
node_resolver: Arc<
NodeResolver<DenoInNpmPackageChecker, NpmResolver<TSys>, TSys>,
>,
npm_process_state_provider: NpmProcessStateProviderRc,
pkg_json_resolver: Arc<node_resolver::PackageJsonResolver<TSys>>,
root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
storage_key_resolver: StorageKeyResolver,
sys: TSys,
options: LibMainWorkerOptions,
) -> Self {
Self {
shared: Arc::new(LibWorkerFactorySharedState {
blob_store,
broadcast_channel: Default::default(),
code_cache,
compiled_wasm_module_store: Default::default(),
feature_checker,
fs,
maybe_inspector_server,
module_loader_factory,
node_resolver,
npm_process_state_provider,
pkg_json_resolver,
root_cert_store_provider,
shared_array_buffer_store: Default::default(),
storage_key_resolver,
sys,
options,
}),
}
}
pub fn create_custom_worker(
&self,
mode: WorkerExecutionMode,
main_module: Url,
permissions: PermissionsContainer,
custom_extensions: Vec<Extension>,
stdio: deno_runtime::deno_io::Stdio,
) -> Result<LibMainWorker, CoreError> {
let shared = &self.shared;
let CreateModuleLoaderResult {
module_loader,
node_require_loader,
} = shared
.module_loader_factory
.create_for_main(permissions.clone());
// TODO(bartlomieju): this is cruft, update FeatureChecker to spit out
// list of enabled features.
let feature_checker = shared.feature_checker.clone();
let unstable_features =
shared.resolve_unstable_features(feature_checker.as_ref());
let maybe_storage_key = shared
.storage_key_resolver
.resolve_storage_key(&main_module);
let origin_storage_dir = maybe_storage_key.as_ref().map(|key| {
shared
.options
.origin_data_folder_path
.as_ref()
.unwrap() // must be set if storage key resolver returns a value
.join(checksum::gen(&[key.as_bytes()]))
});
let cache_storage_dir = maybe_storage_key.map(|key| {
// TODO(@satyarohith): storage quota management
get_cache_storage_dir().join(checksum::gen(&[key.as_bytes()]))
});
let services = WorkerServiceOptions {
root_cert_store_provider: Some(shared.root_cert_store_provider.clone()),
module_loader,
fs: shared.fs.clone(),
node_services: Some(
shared.create_node_init_services(node_require_loader),
),
npm_process_state_provider: Some(
shared.npm_process_state_provider.clone(),
),
blob_store: shared.blob_store.clone(),
broadcast_channel: shared.broadcast_channel.clone(),
fetch_dns_resolver: Default::default(),
shared_array_buffer_store: Some(shared.shared_array_buffer_store.clone()),
compiled_wasm_module_store: Some(
shared.compiled_wasm_module_store.clone(),
),
feature_checker,
permissions,
v8_code_cache: shared.code_cache.clone(),
};
let options = WorkerOptions {
bootstrap: BootstrapOptions {
deno_version: shared.options.deno_version.to_string(),
args: shared.options.argv.clone(),
cpu_count: std::thread::available_parallelism()
.map(|p| p.get())
.unwrap_or(1),
log_level: shared.options.log_level,
enable_op_summary_metrics: shared.options.enable_op_summary_metrics,
enable_testing_features: shared.options.enable_testing_features,
locale: deno_core::v8::icu::get_language_tag(),
location: shared.options.location.clone(),
no_color: !colors::use_color(),
is_stdout_tty: deno_terminal::is_stdout_tty(),
is_stderr_tty: deno_terminal::is_stderr_tty(),
color_level: colors::get_color_level(),
unstable_features,
user_agent: shared.options.deno_user_agent.to_string(),
inspect: shared.options.is_inspecting,
has_node_modules_dir: shared.options.has_node_modules_dir,
argv0: shared.options.argv0.clone(),
node_debug: shared.options.node_debug.clone(),
node_ipc_fd: shared.options.node_ipc,
mode,
serve_port: shared.options.serve_port,
serve_host: shared.options.serve_host.clone(),
otel_config: shared.options.otel_config.clone(),
close_on_idle: true,
},
extensions: custom_extensions,
startup_snapshot: shared.options.startup_snapshot,
create_params: create_isolate_create_params(),
unsafely_ignore_certificate_errors: shared
.options
.unsafely_ignore_certificate_errors
.clone(),
seed: shared.options.seed,
format_js_error_fn: Some(Arc::new(format_js_error)),
create_web_worker_cb: shared.create_web_worker_callback(stdio.clone()),
maybe_inspector_server: shared.maybe_inspector_server.clone(),
should_break_on_first_statement: shared.options.inspect_brk,
should_wait_for_inspector_session: shared.options.inspect_wait,
strace_ops: shared.options.strace_ops.clone(),
cache_storage_dir,
origin_storage_dir,
stdio,
skip_op_registration: shared.options.skip_op_registration,
enable_stack_trace_arg_in_ops: has_trace_permissions_enabled(),
};
let worker =
MainWorker::bootstrap_from_options(&main_module, services, options);
Ok(LibMainWorker {
main_module,
worker,
})
}
}
pub struct LibMainWorker {
main_module: Url,
worker: MainWorker,
}
impl LibMainWorker {
pub fn into_main_worker(self) -> MainWorker {
self.worker
}
pub fn main_module(&self) -> &Url {
&self.main_module
}
pub fn js_runtime(&mut self) -> &mut JsRuntime {
&mut self.worker.js_runtime
}
#[inline]
pub fn create_inspector_session(&mut self) -> LocalInspectorSession {
self.worker.create_inspector_session()
}
#[inline]
pub fn dispatch_load_event(&mut self) -> Result<(), JsError> {
self.worker.dispatch_load_event()
}
#[inline]
pub fn dispatch_beforeunload_event(&mut self) -> Result<bool, JsError> {
self.worker.dispatch_beforeunload_event()
}
#[inline]
pub fn dispatch_process_beforeexit_event(&mut self) -> Result<bool, JsError> {
self.worker.dispatch_process_beforeexit_event()
}
#[inline]
pub fn dispatch_unload_event(&mut self) -> Result<(), JsError> {
self.worker.dispatch_unload_event()
}
#[inline]
pub fn dispatch_process_exit_event(&mut self) -> Result<(), JsError> {
self.worker.dispatch_process_exit_event()
}
pub async fn execute_main_module(&mut self) -> Result<(), CoreError> {
let id = self.worker.preload_main_module(&self.main_module).await?;
self.worker.evaluate_module(id).await
}
pub async fn execute_side_module(&mut self) -> Result<(), CoreError> {
let id = self.worker.preload_side_module(&self.main_module).await?;
self.worker.evaluate_module(id).await
}
#[inline]
pub async fn run_event_loop(
&mut self,
wait_for_inspector: bool,
) -> Result<(), CoreError> {
self.worker.run_event_loop(wait_for_inspector).await
}
#[inline]
pub fn exit_code(&self) -> i32 {
self.worker.exit_code()
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn storage_key_resolver_test() {
let resolver =
StorageKeyResolver(StorageKeyResolverStrategy::UseMainModule);
let specifier = Url::parse("file:///a.ts").unwrap();
assert_eq!(
resolver.resolve_storage_key(&specifier),
Some(specifier.to_string())
);
let resolver =
StorageKeyResolver(StorageKeyResolverStrategy::Specified(None));
assert_eq!(resolver.resolve_storage_key(&specifier), None);
let resolver = StorageKeyResolver(StorageKeyResolverStrategy::Specified(
Some("value".to_string()),
));
assert_eq!(
resolver.resolve_storage_key(&specifier),
Some("value".to_string())
);
// test empty
let resolver = StorageKeyResolver::empty();
assert_eq!(resolver.resolve_storage_key(&specifier), None);
}
}

View file

@ -19,6 +19,7 @@ use deno_core::ModuleSpecifier;
use deno_error::JsErrorBox; use deno_error::JsErrorBox;
use deno_lint::diagnostic::LintDiagnosticRange; use deno_lint::diagnostic::LintDiagnosticRange;
use deno_path_util::url_to_file_path; use deno_path_util::url_to_file_path;
use deno_resolver::npm::managed::NpmResolutionCell;
use deno_runtime::deno_node::PathClean; use deno_runtime::deno_node::PathClean;
use deno_semver::jsr::JsrPackageNvReference; use deno_semver::jsr::JsrPackageNvReference;
use deno_semver::jsr::JsrPackageReqReference; use deno_semver::jsr::JsrPackageReqReference;
@ -31,6 +32,7 @@ use deno_semver::SmallStackString;
use deno_semver::StackString; use deno_semver::StackString;
use deno_semver::Version; use deno_semver::Version;
use import_map::ImportMap; use import_map::ImportMap;
use node_resolver::InNpmPackageChecker;
use node_resolver::NodeResolutionKind; use node_resolver::NodeResolutionKind;
use node_resolver::ResolutionMode; use node_resolver::ResolutionMode;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
@ -365,7 +367,9 @@ impl<'a> TsResponseImportMapper<'a> {
if let Ok(Some(pkg_id)) = if let Ok(Some(pkg_id)) =
npm_resolver.resolve_pkg_id_from_specifier(specifier) npm_resolver.resolve_pkg_id_from_specifier(specifier)
{ {
let pkg_reqs = npm_resolver.resolve_pkg_reqs_from_pkg_id(&pkg_id); let pkg_reqs = npm_resolver
.resolution()
.resolve_pkg_reqs_from_pkg_id(&pkg_id);
// check if any pkg reqs match what is found in an import map // check if any pkg reqs match what is found in an import map
if !pkg_reqs.is_empty() { if !pkg_reqs.is_empty() {
let sub_path = npm_resolver let sub_path = npm_resolver
@ -1295,6 +1299,19 @@ impl CodeActionCollection {
range: &lsp::Range, range: &lsp::Range,
language_server: &language_server::Inner, language_server: &language_server::Inner,
) -> Option<lsp::CodeAction> { ) -> Option<lsp::CodeAction> {
fn top_package_req_for_name(
resolution: &NpmResolutionCell,
name: &str,
) -> Option<PackageReq> {
let package_reqs = resolution.package_reqs();
let mut entries = package_reqs
.into_iter()
.filter(|(_, nv)| nv.name == name)
.collect::<Vec<_>>();
entries.sort_by(|a, b| a.1.version.cmp(&b.1.version));
Some(entries.pop()?.0)
}
let (dep_key, dependency, _) = let (dep_key, dependency, _) =
document.get_maybe_dependency(&range.end)?; document.get_maybe_dependency(&range.end)?;
if dependency.maybe_deno_types_specifier.is_some() { if dependency.maybe_deno_types_specifier.is_some() {
@ -1382,9 +1399,10 @@ impl CodeActionCollection {
.and_then(|versions| versions.first().cloned())?; .and_then(|versions| versions.first().cloned())?;
let types_specifier_text = let types_specifier_text =
if let Some(npm_resolver) = managed_npm_resolver { if let Some(npm_resolver) = managed_npm_resolver {
let mut specifier_text = if let Some(req) = let mut specifier_text = if let Some(req) = top_package_req_for_name(
npm_resolver.top_package_req_for_name(&types_package_name) npm_resolver.resolution(),
{ &types_package_name,
) {
format!("npm:{req}") format!("npm:{req}")
} else { } else {
format!("npm:{}@^{}", &types_package_name, types_package_version) format!("npm:{}@^{}", &types_package_name, types_package_version)

View file

@ -8,9 +8,9 @@ use std::time::SystemTime;
use deno_core::url::Url; use deno_core::url::Url;
use deno_core::ModuleSpecifier; use deno_core::ModuleSpecifier;
use deno_lib::cache::DenoDir;
use deno_path_util::url_to_file_path; use deno_path_util::url_to_file_path;
use crate::cache::DenoDir;
use crate::cache::GlobalHttpCache; use crate::cache::GlobalHttpCache;
use crate::cache::HttpCache; use crate::cache::HttpCache;
use crate::cache::LocalLspHttpCache; use crate::cache::LocalLspHttpCache;
@ -70,7 +70,7 @@ fn calculate_fs_version_in_cache(
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct LspCache { pub struct LspCache {
deno_dir: DenoDir, deno_dir: DenoDir<CliSys>,
global: Arc<GlobalHttpCache>, global: Arc<GlobalHttpCache>,
vendors_by_scope: BTreeMap<ModuleSpecifier, Option<Arc<LocalLspHttpCache>>>, vendors_by_scope: BTreeMap<ModuleSpecifier, Option<Arc<LocalLspHttpCache>>>,
} }
@ -121,7 +121,7 @@ impl LspCache {
.collect(); .collect();
} }
pub fn deno_dir(&self) -> &DenoDir { pub fn deno_dir(&self) -> &DenoDir<CliSys> {
&self.deno_dir &self.deno_dir
} }

View file

@ -41,6 +41,7 @@ use deno_core::serde_json::json;
use deno_core::serde_json::Value; use deno_core::serde_json::Value;
use deno_core::url::Url; use deno_core::url::Url;
use deno_core::ModuleSpecifier; use deno_core::ModuleSpecifier;
use deno_lib::env::has_flag_env_var;
use deno_lint::linter::LintConfig as DenoLintConfig; use deno_lint::linter::LintConfig as DenoLintConfig;
use deno_npm::npm_rc::ResolvedNpmRc; use deno_npm::npm_rc::ResolvedNpmRc;
use deno_package_json::PackageJsonCache; use deno_package_json::PackageJsonCache;
@ -55,7 +56,6 @@ use super::logging::lsp_log;
use super::lsp_custom; use super::lsp_custom;
use super::urls::url_to_uri; use super::urls::url_to_uri;
use crate::args::discover_npmrc_from_workspace; use crate::args::discover_npmrc_from_workspace;
use crate::args::has_flag_env_var;
use crate::args::CliLockfile; use crate::args::CliLockfile;
use crate::args::CliLockfileReadFromPathOptions; use crate::args::CliLockfileReadFromPathOptions;
use crate::args::ConfigFile; use crate::args::ConfigFile;

View file

@ -265,7 +265,7 @@ impl TsDiagnosticsStore {
} }
pub fn should_send_diagnostic_batch_index_notifications() -> bool { pub fn should_send_diagnostic_batch_index_notifications() -> bool {
crate::args::has_flag_env_var( deno_lib::env::has_flag_env_var(
"DENO_DONT_USE_INTERNAL_LSP_DIAGNOSTIC_SYNC_FLAG", "DENO_DONT_USE_INTERNAL_LSP_DIAGNOSTIC_SYNC_FLAG",
) )
} }

View file

@ -27,6 +27,7 @@ use deno_core::url::Url;
use deno_core::ModuleSpecifier; use deno_core::ModuleSpecifier;
use deno_graph::GraphKind; use deno_graph::GraphKind;
use deno_graph::Resolution; use deno_graph::Resolution;
use deno_lib::env::has_flag_env_var;
use deno_path_util::url_to_file_path; use deno_path_util::url_to_file_path;
use deno_runtime::deno_tls::rustls::RootCertStore; use deno_runtime::deno_tls::rustls::RootCertStore;
use deno_runtime::deno_tls::RootCertStoreProvider; use deno_runtime::deno_tls::RootCertStoreProvider;
@ -95,7 +96,6 @@ use super::urls::uri_to_url;
use super::urls::url_to_uri; use super::urls::url_to_uri;
use crate::args::create_default_npmrc; use crate::args::create_default_npmrc;
use crate::args::get_root_cert_store; use crate::args::get_root_cert_store;
use crate::args::has_flag_env_var;
use crate::args::CaData; use crate::args::CaData;
use crate::args::CliOptions; use crate::args::CliOptions;
use crate::args::Flags; use crate::args::Flags;

View file

@ -26,6 +26,7 @@ use deno_resolver::cjs::IsCjsResolutionMode;
use deno_resolver::npm::managed::ManagedInNpmPkgCheckerCreateOptions; use deno_resolver::npm::managed::ManagedInNpmPkgCheckerCreateOptions;
use deno_resolver::npm::managed::NpmResolutionCell; use deno_resolver::npm::managed::NpmResolutionCell;
use deno_resolver::npm::CreateInNpmPkgCheckerOptions; use deno_resolver::npm::CreateInNpmPkgCheckerOptions;
use deno_resolver::npm::DenoInNpmPackageChecker;
use deno_resolver::npm::NpmReqResolverOptions; use deno_resolver::npm::NpmReqResolverOptions;
use deno_resolver::DenoResolverOptions; use deno_resolver::DenoResolverOptions;
use deno_resolver::NodeAndNpmReqResolver; use deno_resolver::NodeAndNpmReqResolver;
@ -35,7 +36,6 @@ use deno_semver::npm::NpmPackageReqReference;
use deno_semver::package::PackageNv; use deno_semver::package::PackageNv;
use deno_semver::package::PackageReq; use deno_semver::package::PackageReq;
use indexmap::IndexMap; use indexmap::IndexMap;
use node_resolver::InNpmPackageChecker;
use node_resolver::NodeResolutionKind; use node_resolver::NodeResolutionKind;
use node_resolver::ResolutionMode; use node_resolver::ResolutionMode;
@ -56,10 +56,10 @@ use crate::lsp::config::ConfigData;
use crate::lsp::logging::lsp_warn; use crate::lsp::logging::lsp_warn;
use crate::node::CliNodeResolver; use crate::node::CliNodeResolver;
use crate::node::CliPackageJsonResolver; use crate::node::CliPackageJsonResolver;
use crate::npm::create_cli_npm_resolver;
use crate::npm::installer::NpmInstaller; use crate::npm::installer::NpmInstaller;
use crate::npm::installer::NpmResolutionInstaller; use crate::npm::installer::NpmResolutionInstaller;
use crate::npm::CliByonmNpmResolverCreateOptions; use crate::npm::CliByonmNpmResolverCreateOptions;
use crate::npm::CliManagedNpmResolver;
use crate::npm::CliManagedNpmResolverCreateOptions; use crate::npm::CliManagedNpmResolverCreateOptions;
use crate::npm::CliNpmCache; use crate::npm::CliNpmCache;
use crate::npm::CliNpmCacheHttpClient; use crate::npm::CliNpmCacheHttpClient;
@ -67,14 +67,13 @@ use crate::npm::CliNpmRegistryInfoProvider;
use crate::npm::CliNpmResolver; use crate::npm::CliNpmResolver;
use crate::npm::CliNpmResolverCreateOptions; use crate::npm::CliNpmResolverCreateOptions;
use crate::npm::CliNpmResolverManagedSnapshotOption; use crate::npm::CliNpmResolverManagedSnapshotOption;
use crate::npm::ManagedCliNpmResolver;
use crate::npm::NpmResolutionInitializer; use crate::npm::NpmResolutionInitializer;
use crate::resolver::CliDenoResolver; use crate::resolver::CliDenoResolver;
use crate::resolver::CliIsCjsResolver;
use crate::resolver::CliNpmGraphResolver; use crate::resolver::CliNpmGraphResolver;
use crate::resolver::CliNpmReqResolver; use crate::resolver::CliNpmReqResolver;
use crate::resolver::CliResolver; use crate::resolver::CliResolver;
use crate::resolver::FoundPackageJsonDepFlag; use crate::resolver::FoundPackageJsonDepFlag;
use crate::resolver::IsCjsResolver;
use crate::sys::CliSys; use crate::sys::CliSys;
use crate::tsc::into_specifier_and_media_type; use crate::tsc::into_specifier_and_media_type;
use crate::util::progress_bar::ProgressBar; use crate::util::progress_bar::ProgressBar;
@ -83,12 +82,13 @@ use crate::util::progress_bar::ProgressBarStyle;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct LspScopeResolver { struct LspScopeResolver {
resolver: Arc<CliResolver>, resolver: Arc<CliResolver>,
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>, in_npm_pkg_checker: DenoInNpmPackageChecker,
is_cjs_resolver: Arc<IsCjsResolver>, is_cjs_resolver: Arc<CliIsCjsResolver>,
jsr_resolver: Option<Arc<JsrCacheResolver>>, jsr_resolver: Option<Arc<JsrCacheResolver>>,
npm_graph_resolver: Arc<CliNpmGraphResolver>, npm_graph_resolver: Arc<CliNpmGraphResolver>,
npm_installer: Option<Arc<NpmInstaller>>, npm_installer: Option<Arc<NpmInstaller>>,
npm_resolver: Option<Arc<dyn CliNpmResolver>>, npm_resolution: Arc<NpmResolutionCell>,
npm_resolver: Option<CliNpmResolver>,
node_resolver: Option<Arc<CliNodeResolver>>, node_resolver: Option<Arc<CliNodeResolver>>,
npm_pkg_req_resolver: Option<Arc<CliNpmReqResolver>>, npm_pkg_req_resolver: Option<Arc<CliNpmReqResolver>>,
pkg_json_resolver: Arc<CliPackageJsonResolver>, pkg_json_resolver: Arc<CliPackageJsonResolver>,
@ -111,6 +111,7 @@ impl Default for LspScopeResolver {
npm_installer: None, npm_installer: None,
npm_resolver: None, npm_resolver: None,
node_resolver: None, node_resolver: None,
npm_resolution: factory.services.npm_resolution.clone(),
npm_pkg_req_resolver: None, npm_pkg_req_resolver: None,
pkg_json_resolver: factory.pkg_json_resolver().clone(), pkg_json_resolver: factory.pkg_json_resolver().clone(),
redirect_resolver: None, redirect_resolver: None,
@ -224,6 +225,7 @@ impl LspScopeResolver {
npm_pkg_req_resolver, npm_pkg_req_resolver,
npm_resolver, npm_resolver,
npm_installer, npm_installer,
npm_resolution: factory.services.npm_resolution.clone(),
node_resolver, node_resolver,
pkg_json_resolver, pkg_json_resolver,
redirect_resolver, redirect_resolver,
@ -235,12 +237,58 @@ impl LspScopeResolver {
} }
fn snapshot(&self) -> Arc<Self> { fn snapshot(&self) -> Arc<Self> {
// create a copy of the resolution and then re-initialize the npm resolver from that
// todo(dsherret): this is pretty terrible... we should improve this. It should
// be possible to just change the npm_resolution on the new factory then access
// another method to create a new npm resolver
let mut factory = ResolverFactory::new(self.config_data.as_ref()); let mut factory = ResolverFactory::new(self.config_data.as_ref());
let npm_resolver = factory
self.npm_resolver.as_ref().map(|r| r.clone_snapshotted()); .services
.npm_resolution
.set_snapshot(self.npm_resolution.snapshot());
let npm_resolver = self.npm_resolver.as_ref();
if let Some(npm_resolver) = &npm_resolver { if let Some(npm_resolver) = &npm_resolver {
factory.set_npm_resolver(npm_resolver.clone()); factory.set_npm_resolver(CliNpmResolver::new::<CliSys>(
match npm_resolver {
CliNpmResolver::Byonm(byonm_npm_resolver) => {
CliNpmResolverCreateOptions::Byonm(
CliByonmNpmResolverCreateOptions {
root_node_modules_dir: byonm_npm_resolver
.root_node_modules_path()
.map(|p| p.to_path_buf()),
sys: CliSys::default(),
pkg_json_resolver: self.pkg_json_resolver.clone(),
},
)
} }
CliNpmResolver::Managed(managed_npm_resolver) => {
CliNpmResolverCreateOptions::Managed({
let npmrc = self
.config_data
.as_ref()
.and_then(|d| d.npmrc.clone())
.unwrap_or_else(create_default_npmrc);
let npm_cache_dir = Arc::new(NpmCacheDir::new(
&CliSys::default(),
managed_npm_resolver.global_cache_root_path().to_path_buf(),
npmrc.get_all_known_registries_urls(),
));
CliManagedNpmResolverCreateOptions {
sys: CliSys::default(),
npm_cache_dir,
maybe_node_modules_path: managed_npm_resolver
.root_node_modules_path()
.map(|p| p.to_path_buf()),
npmrc,
npm_resolution: factory.services.npm_resolution.clone(),
npm_system_info: NpmSystemInfo::default(),
}
})
}
},
));
}
Arc::new(Self { Arc::new(Self {
resolver: factory.cli_resolver().clone(), resolver: factory.cli_resolver().clone(),
in_npm_pkg_checker: factory.in_npm_pkg_checker().clone(), in_npm_pkg_checker: factory.in_npm_pkg_checker().clone(),
@ -250,6 +298,7 @@ impl LspScopeResolver {
// npm installer isn't necessary for a snapshot // npm installer isn't necessary for a snapshot
npm_installer: None, npm_installer: None,
npm_pkg_req_resolver: factory.npm_pkg_req_resolver().cloned(), npm_pkg_req_resolver: factory.npm_pkg_req_resolver().cloned(),
npm_resolution: factory.services.npm_resolution.clone(),
npm_resolver: factory.npm_resolver().cloned(), npm_resolver: factory.npm_resolver().cloned(),
node_resolver: factory.node_resolver().cloned(), node_resolver: factory.node_resolver().cloned(),
redirect_resolver: self.redirect_resolver.clone(), redirect_resolver: self.redirect_resolver.clone(),
@ -366,7 +415,7 @@ impl LspResolver {
pub fn as_is_cjs_resolver( pub fn as_is_cjs_resolver(
&self, &self,
file_referrer: Option<&ModuleSpecifier>, file_referrer: Option<&ModuleSpecifier>,
) -> &IsCjsResolver { ) -> &CliIsCjsResolver {
let resolver = self.get_scope_resolver(file_referrer); let resolver = self.get_scope_resolver(file_referrer);
resolver.is_cjs_resolver.as_ref() resolver.is_cjs_resolver.as_ref()
} }
@ -382,7 +431,7 @@ impl LspResolver {
pub fn in_npm_pkg_checker( pub fn in_npm_pkg_checker(
&self, &self,
file_referrer: Option<&ModuleSpecifier>, file_referrer: Option<&ModuleSpecifier>,
) -> &Arc<dyn InNpmPackageChecker> { ) -> &DenoInNpmPackageChecker {
let resolver = self.get_scope_resolver(file_referrer); let resolver = self.get_scope_resolver(file_referrer);
&resolver.in_npm_pkg_checker &resolver.in_npm_pkg_checker
} }
@ -390,7 +439,7 @@ impl LspResolver {
pub fn maybe_managed_npm_resolver( pub fn maybe_managed_npm_resolver(
&self, &self,
file_referrer: Option<&ModuleSpecifier>, file_referrer: Option<&ModuleSpecifier>,
) -> Option<&ManagedCliNpmResolver> { ) -> Option<&CliManagedNpmResolver> {
let resolver = self.get_scope_resolver(file_referrer); let resolver = self.get_scope_resolver(file_referrer);
resolver.npm_resolver.as_ref().and_then(|r| r.as_managed()) resolver.npm_resolver.as_ref().and_then(|r| r.as_managed())
} }
@ -605,13 +654,14 @@ pub struct ScopeDepInfo {
struct ResolverFactoryServices { struct ResolverFactoryServices {
cli_resolver: Deferred<Arc<CliResolver>>, cli_resolver: Deferred<Arc<CliResolver>>,
found_pkg_json_dep_flag: Arc<FoundPackageJsonDepFlag>, found_pkg_json_dep_flag: Arc<FoundPackageJsonDepFlag>,
in_npm_pkg_checker: Deferred<Arc<dyn InNpmPackageChecker>>, in_npm_pkg_checker: Deferred<DenoInNpmPackageChecker>,
is_cjs_resolver: Deferred<Arc<IsCjsResolver>>, is_cjs_resolver: Deferred<Arc<CliIsCjsResolver>>,
node_resolver: Deferred<Option<Arc<CliNodeResolver>>>, node_resolver: Deferred<Option<Arc<CliNodeResolver>>>,
npm_graph_resolver: Deferred<Arc<CliNpmGraphResolver>>, npm_graph_resolver: Deferred<Arc<CliNpmGraphResolver>>,
npm_installer: Option<Arc<NpmInstaller>>, npm_installer: Option<Arc<NpmInstaller>>,
npm_pkg_req_resolver: Deferred<Option<Arc<CliNpmReqResolver>>>, npm_pkg_req_resolver: Deferred<Option<Arc<CliNpmReqResolver>>>,
npm_resolver: Option<Arc<dyn CliNpmResolver>>, npm_resolver: Option<CliNpmResolver>,
npm_resolution: Arc<NpmResolutionCell>,
} }
struct ResolverFactory<'a> { struct ResolverFactory<'a> {
@ -686,10 +736,9 @@ impl<'a> ResolverFactory<'a> {
npm_client.clone(), npm_client.clone(),
npmrc.clone(), npmrc.clone(),
)); ));
let npm_resolution = Arc::new(NpmResolutionCell::default());
let npm_resolution_initializer = Arc::new(NpmResolutionInitializer::new( let npm_resolution_initializer = Arc::new(NpmResolutionInitializer::new(
registry_info_provider.clone(), registry_info_provider.clone(),
npm_resolution.clone(), self.services.npm_resolution.clone(),
match self.config_data.and_then(|d| d.lockfile.as_ref()) { match self.config_data.and_then(|d| d.lockfile.as_ref()) {
Some(lockfile) => { Some(lockfile) => {
CliNpmResolverManagedSnapshotOption::ResolveFromLockfile( CliNpmResolverManagedSnapshotOption::ResolveFromLockfile(
@ -712,13 +761,13 @@ impl<'a> ResolverFactory<'a> {
)); ));
let npm_resolution_installer = Arc::new(NpmResolutionInstaller::new( let npm_resolution_installer = Arc::new(NpmResolutionInstaller::new(
registry_info_provider, registry_info_provider,
npm_resolution.clone(), self.services.npm_resolution.clone(),
maybe_lockfile.clone(), maybe_lockfile.clone(),
)); ));
let npm_installer = Arc::new(NpmInstaller::new( let npm_installer = Arc::new(NpmInstaller::new(
npm_cache.clone(), npm_cache.clone(),
Arc::new(NpmInstallDepsProvider::empty()), Arc::new(NpmInstallDepsProvider::empty()),
npm_resolution.clone(), self.services.npm_resolution.clone(),
npm_resolution_initializer.clone(), npm_resolution_initializer.clone(),
npm_resolution_installer, npm_resolution_installer,
&pb, &pb,
@ -745,22 +794,22 @@ impl<'a> ResolverFactory<'a> {
npm_cache_dir, npm_cache_dir,
maybe_node_modules_path, maybe_node_modules_path,
npmrc, npmrc,
npm_resolution, npm_resolution: self.services.npm_resolution.clone(),
npm_system_info: NpmSystemInfo::default(), npm_system_info: NpmSystemInfo::default(),
}) })
}; };
self.set_npm_resolver(create_cli_npm_resolver(options)); self.set_npm_resolver(CliNpmResolver::new(options));
} }
pub fn set_npm_installer(&mut self, npm_installer: Arc<NpmInstaller>) { pub fn set_npm_installer(&mut self, npm_installer: Arc<NpmInstaller>) {
self.services.npm_installer = Some(npm_installer); self.services.npm_installer = Some(npm_installer);
} }
pub fn set_npm_resolver(&mut self, npm_resolver: Arc<dyn CliNpmResolver>) { pub fn set_npm_resolver(&mut self, npm_resolver: CliNpmResolver) {
self.services.npm_resolver = Some(npm_resolver); self.services.npm_resolver = Some(npm_resolver);
} }
pub fn npm_resolver(&self) -> Option<&Arc<dyn CliNpmResolver>> { pub fn npm_resolver(&self) -> Option<&CliNpmResolver> {
self.services.npm_resolver.as_ref() self.services.npm_resolver.as_ref()
} }
@ -825,29 +874,27 @@ impl<'a> ResolverFactory<'a> {
&self.pkg_json_resolver &self.pkg_json_resolver
} }
pub fn in_npm_pkg_checker(&self) -> &Arc<dyn InNpmPackageChecker> { pub fn in_npm_pkg_checker(&self) -> &DenoInNpmPackageChecker {
self.services.in_npm_pkg_checker.get_or_init(|| { self.services.in_npm_pkg_checker.get_or_init(|| {
deno_resolver::npm::create_in_npm_pkg_checker( DenoInNpmPackageChecker::new(match &self.services.npm_resolver {
match self.services.npm_resolver.as_ref().map(|r| r.as_inner()) { Some(CliNpmResolver::Byonm(_)) | None => {
Some(crate::npm::InnerCliNpmResolverRef::Byonm(_)) | None => {
CreateInNpmPkgCheckerOptions::Byonm CreateInNpmPkgCheckerOptions::Byonm
} }
Some(crate::npm::InnerCliNpmResolverRef::Managed(m)) => { Some(CliNpmResolver::Managed(m)) => {
CreateInNpmPkgCheckerOptions::Managed( CreateInNpmPkgCheckerOptions::Managed(
ManagedInNpmPkgCheckerCreateOptions { ManagedInNpmPkgCheckerCreateOptions {
root_cache_dir_url: m.global_cache_root_url(), root_cache_dir_url: m.global_cache_root_url(),
maybe_node_modules_path: m.maybe_node_modules_path(), maybe_node_modules_path: m.root_node_modules_path(),
}, },
) )
} }
}, })
)
}) })
} }
pub fn is_cjs_resolver(&self) -> &Arc<IsCjsResolver> { pub fn is_cjs_resolver(&self) -> &Arc<CliIsCjsResolver> {
self.services.is_cjs_resolver.get_or_init(|| { self.services.is_cjs_resolver.get_or_init(|| {
Arc::new(IsCjsResolver::new( Arc::new(CliIsCjsResolver::new(
self.in_npm_pkg_checker().clone(), self.in_npm_pkg_checker().clone(),
self.pkg_json_resolver().clone(), self.pkg_json_resolver().clone(),
if self if self
@ -871,7 +918,7 @@ impl<'a> ResolverFactory<'a> {
Some(Arc::new(CliNodeResolver::new( Some(Arc::new(CliNodeResolver::new(
self.in_npm_pkg_checker().clone(), self.in_npm_pkg_checker().clone(),
RealIsBuiltInNodeModuleChecker, RealIsBuiltInNodeModuleChecker,
npm_resolver.clone().into_npm_pkg_folder_resolver(), npm_resolver.clone(),
self.pkg_json_resolver.clone(), self.pkg_json_resolver.clone(),
self.sys.clone(), self.sys.clone(),
node_resolver::ConditionsFromResolutionMode::default(), node_resolver::ConditionsFromResolutionMode::default(),
@ -890,7 +937,7 @@ impl<'a> ResolverFactory<'a> {
Some(Arc::new(CliNpmReqResolver::new(NpmReqResolverOptions { Some(Arc::new(CliNpmReqResolver::new(NpmReqResolverOptions {
in_npm_pkg_checker: self.in_npm_pkg_checker().clone(), in_npm_pkg_checker: self.in_npm_pkg_checker().clone(),
node_resolver: node_resolver.clone(), node_resolver: node_resolver.clone(),
npm_resolver: npm_resolver.clone().into_byonm_or_managed(), npm_resolver: npm_resolver.clone(),
sys: self.sys.clone(), sys: self.sys.clone(),
}))) })))
}) })

View file

@ -5,6 +5,7 @@ use std::collections::HashSet;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::ModuleSpecifier; use deno_core::ModuleSpecifier;
use deno_lib::util::checksum;
use lsp::Range; use lsp::Range;
use tower_lsp::lsp_types as lsp; use tower_lsp::lsp_types as lsp;
@ -15,7 +16,6 @@ use crate::lsp::logging::lsp_warn;
use crate::lsp::urls::url_to_uri; use crate::lsp::urls::url_to_uri;
use crate::tools::test::TestDescription; use crate::tools::test::TestDescription;
use crate::tools::test::TestStepDescription; use crate::tools::test::TestStepDescription;
use crate::util::checksum;
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct TestDefinition { pub struct TestDefinition {

View file

@ -39,6 +39,7 @@ use deno_core::ModuleSpecifier;
use deno_core::OpState; use deno_core::OpState;
use deno_core::PollEventLoopOptions; use deno_core::PollEventLoopOptions;
use deno_core::RuntimeOptions; use deno_core::RuntimeOptions;
use deno_lib::worker::create_isolate_create_params;
use deno_path_util::url_to_file_path; use deno_path_util::url_to_file_path;
use deno_runtime::deno_node::SUPPORTED_BUILTIN_NODE_MODULES; use deno_runtime::deno_node::SUPPORTED_BUILTIN_NODE_MODULES;
use deno_runtime::inspector_server::InspectorServer; use deno_runtime::inspector_server::InspectorServer;
@ -96,7 +97,6 @@ use crate::util::path::relative_specifier;
use crate::util::path::to_percent_decoded_str; use crate::util::path::to_percent_decoded_str;
use crate::util::result::InfallibleResultExt; use crate::util::result::InfallibleResultExt;
use crate::util::v8::convert; use crate::util::v8::convert;
use crate::worker::create_isolate_create_params;
static BRACKET_ACCESSOR_RE: Lazy<Regex> = static BRACKET_ACCESSOR_RE: Lazy<Regex> =
lazy_regex!(r#"^\[['"](.+)[\['"]\]$"#); lazy_regex!(r#"^\[['"](.+)[\['"]\]$"#);

View file

@ -81,7 +81,7 @@ fn hash_data_specifier(specifier: &ModuleSpecifier) -> String {
file_name_str.push('?'); file_name_str.push('?');
file_name_str.push_str(query); file_name_str.push_str(query);
} }
crate::util::checksum::gen(&[file_name_str.as_bytes()]) deno_lib::util::checksum::gen(&[file_name_str.as_bytes()])
} }
fn to_deno_uri(specifier: &Url) -> String { fn to_deno_uri(specifier: &Url) -> String {

View file

@ -39,6 +39,10 @@ use deno_graph::ModuleGraph;
use deno_graph::ModuleGraphError; use deno_graph::ModuleGraphError;
use deno_graph::Resolution; use deno_graph::Resolution;
use deno_graph::WasmModule; use deno_graph::WasmModule;
use deno_lib::npm::NpmRegistryReadPermissionChecker;
use deno_lib::worker::CreateModuleLoaderResult;
use deno_lib::worker::ModuleLoaderFactory;
use deno_resolver::npm::DenoInNpmPackageChecker;
use deno_runtime::code_cache; use deno_runtime::code_cache;
use deno_runtime::deno_node::create_host_defined_options; use deno_runtime::deno_node::create_host_defined_options;
use deno_runtime::deno_node::NodeRequireLoader; use deno_runtime::deno_node::NodeRequireLoader;
@ -69,8 +73,7 @@ use crate::graph_util::ModuleGraphBuilder;
use crate::node::CliNodeCodeTranslator; use crate::node::CliNodeCodeTranslator;
use crate::node::CliNodeResolver; use crate::node::CliNodeResolver;
use crate::npm::CliNpmResolver; use crate::npm::CliNpmResolver;
use crate::npm::NpmRegistryReadPermissionChecker; use crate::resolver::CliCjsTracker;
use crate::resolver::CjsTracker;
use crate::resolver::CliNpmReqResolver; use crate::resolver::CliNpmReqResolver;
use crate::resolver::CliResolver; use crate::resolver::CliResolver;
use crate::resolver::ModuleCodeStringSource; use crate::resolver::ModuleCodeStringSource;
@ -83,8 +86,6 @@ use crate::tools::check::TypeChecker;
use crate::util::progress_bar::ProgressBar; use crate::util::progress_bar::ProgressBar;
use crate::util::text_encoding::code_without_source_map; use crate::util::text_encoding::code_without_source_map;
use crate::util::text_encoding::source_map_from_code; use crate::util::text_encoding::source_map_from_code;
use crate::worker::CreateModuleLoaderResult;
use crate::worker::ModuleLoaderFactory;
#[derive(Debug, thiserror::Error, deno_error::JsError)] #[derive(Debug, thiserror::Error, deno_error::JsError)]
pub enum PrepareModuleLoadError { pub enum PrepareModuleLoadError {
@ -233,18 +234,19 @@ struct SharedCliModuleLoaderState {
initial_cwd: PathBuf, initial_cwd: PathBuf,
is_inspecting: bool, is_inspecting: bool,
is_repl: bool, is_repl: bool,
cjs_tracker: Arc<CjsTracker>, cjs_tracker: Arc<CliCjsTracker>,
code_cache: Option<Arc<CodeCache>>, code_cache: Option<Arc<CodeCache>>,
emitter: Arc<Emitter>, emitter: Arc<Emitter>,
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>, in_npm_pkg_checker: DenoInNpmPackageChecker,
main_module_graph_container: Arc<MainModuleGraphContainer>, main_module_graph_container: Arc<MainModuleGraphContainer>,
module_load_preparer: Arc<ModuleLoadPreparer>, module_load_preparer: Arc<ModuleLoadPreparer>,
node_code_translator: Arc<CliNodeCodeTranslator>, node_code_translator: Arc<CliNodeCodeTranslator>,
node_resolver: Arc<CliNodeResolver>, node_resolver: Arc<CliNodeResolver>,
npm_module_loader: NpmModuleLoader, npm_module_loader: NpmModuleLoader,
npm_registry_permission_checker: Arc<NpmRegistryReadPermissionChecker>, npm_registry_permission_checker:
Arc<NpmRegistryReadPermissionChecker<CliSys>>,
npm_req_resolver: Arc<CliNpmReqResolver>, npm_req_resolver: Arc<CliNpmReqResolver>,
npm_resolver: Arc<dyn CliNpmResolver>, npm_resolver: CliNpmResolver,
parsed_source_cache: Arc<ParsedSourceCache>, parsed_source_cache: Arc<ParsedSourceCache>,
resolver: Arc<CliResolver>, resolver: Arc<CliResolver>,
sys: CliSys, sys: CliSys,
@ -294,18 +296,20 @@ impl CliModuleLoaderFactory {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn new( pub fn new(
options: &CliOptions, options: &CliOptions,
cjs_tracker: Arc<CjsTracker>, cjs_tracker: Arc<CliCjsTracker>,
code_cache: Option<Arc<CodeCache>>, code_cache: Option<Arc<CodeCache>>,
emitter: Arc<Emitter>, emitter: Arc<Emitter>,
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>, in_npm_pkg_checker: DenoInNpmPackageChecker,
main_module_graph_container: Arc<MainModuleGraphContainer>, main_module_graph_container: Arc<MainModuleGraphContainer>,
module_load_preparer: Arc<ModuleLoadPreparer>, module_load_preparer: Arc<ModuleLoadPreparer>,
node_code_translator: Arc<CliNodeCodeTranslator>, node_code_translator: Arc<CliNodeCodeTranslator>,
node_resolver: Arc<CliNodeResolver>, node_resolver: Arc<CliNodeResolver>,
npm_module_loader: NpmModuleLoader, npm_module_loader: NpmModuleLoader,
npm_registry_permission_checker: Arc<NpmRegistryReadPermissionChecker>, npm_registry_permission_checker: Arc<
NpmRegistryReadPermissionChecker<CliSys>,
>,
npm_req_resolver: Arc<CliNpmReqResolver>, npm_req_resolver: Arc<CliNpmReqResolver>,
npm_resolver: Arc<dyn CliNpmResolver>, npm_resolver: CliNpmResolver,
parsed_source_cache: Arc<ParsedSourceCache>, parsed_source_cache: Arc<ParsedSourceCache>,
resolver: Arc<CliResolver>, resolver: Arc<CliResolver>,
sys: CliSys, sys: CliSys,
@ -1139,12 +1143,13 @@ impl ModuleGraphUpdatePermit for WorkerModuleGraphUpdatePermit {
#[derive(Debug)] #[derive(Debug)]
struct CliNodeRequireLoader<TGraphContainer: ModuleGraphContainer> { struct CliNodeRequireLoader<TGraphContainer: ModuleGraphContainer> {
cjs_tracker: Arc<CjsTracker>, cjs_tracker: Arc<CliCjsTracker>,
emitter: Arc<Emitter>, emitter: Arc<Emitter>,
sys: CliSys, sys: CliSys,
graph_container: TGraphContainer, graph_container: TGraphContainer,
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>, in_npm_pkg_checker: DenoInNpmPackageChecker,
npm_registry_permission_checker: Arc<NpmRegistryReadPermissionChecker>, npm_registry_permission_checker:
Arc<NpmRegistryReadPermissionChecker<CliSys>>,
} }
impl<TGraphContainer: ModuleGraphContainer> NodeRequireLoader impl<TGraphContainer: ModuleGraphContainer> NodeRequireLoader

View file

@ -7,6 +7,7 @@ use deno_ast::MediaType;
use deno_ast::ModuleSpecifier; use deno_ast::ModuleSpecifier;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_graph::ParsedSourceStore; use deno_graph::ParsedSourceStore;
use deno_resolver::npm::DenoInNpmPackageChecker;
use deno_runtime::deno_fs; use deno_runtime::deno_fs;
use deno_runtime::deno_node::RealIsBuiltInNodeModuleChecker; use deno_runtime::deno_node::RealIsBuiltInNodeModuleChecker;
use node_resolver::analyze::CjsAnalysis as ExtNodeCjsAnalysis; use node_resolver::analyze::CjsAnalysis as ExtNodeCjsAnalysis;
@ -19,15 +20,22 @@ use serde::Serialize;
use crate::cache::CacheDBHash; use crate::cache::CacheDBHash;
use crate::cache::NodeAnalysisCache; use crate::cache::NodeAnalysisCache;
use crate::cache::ParsedSourceCache; use crate::cache::ParsedSourceCache;
use crate::resolver::CjsTracker; use crate::npm::CliNpmResolver;
use crate::resolver::CliCjsTracker;
use crate::sys::CliSys; use crate::sys::CliSys;
pub type CliNodeCodeTranslator = NodeCodeTranslator< pub type CliNodeCodeTranslator = NodeCodeTranslator<
CliCjsCodeAnalyzer, CliCjsCodeAnalyzer,
DenoInNpmPackageChecker,
RealIsBuiltInNodeModuleChecker, RealIsBuiltInNodeModuleChecker,
CliNpmResolver,
CliSys,
>;
pub type CliNodeResolver = deno_runtime::deno_node::NodeResolver<
DenoInNpmPackageChecker,
CliNpmResolver,
CliSys, CliSys,
>; >;
pub type CliNodeResolver = deno_runtime::deno_node::NodeResolver<CliSys>;
pub type CliPackageJsonResolver = node_resolver::PackageJsonResolver<CliSys>; pub type CliPackageJsonResolver = node_resolver::PackageJsonResolver<CliSys>;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
@ -43,7 +51,7 @@ pub enum CliCjsAnalysis {
pub struct CliCjsCodeAnalyzer { pub struct CliCjsCodeAnalyzer {
cache: NodeAnalysisCache, cache: NodeAnalysisCache,
cjs_tracker: Arc<CjsTracker>, cjs_tracker: Arc<CliCjsTracker>,
fs: deno_fs::FileSystemRc, fs: deno_fs::FileSystemRc,
parsed_source_cache: Option<Arc<ParsedSourceCache>>, parsed_source_cache: Option<Arc<ParsedSourceCache>>,
} }
@ -51,7 +59,7 @@ pub struct CliCjsCodeAnalyzer {
impl CliCjsCodeAnalyzer { impl CliCjsCodeAnalyzer {
pub fn new( pub fn new(
cache: NodeAnalysisCache, cache: NodeAnalysisCache,
cjs_tracker: Arc<CjsTracker>, cjs_tracker: Arc<CliCjsTracker>,
fs: deno_fs::FileSystemRc, fs: deno_fs::FileSystemRc,
parsed_source_cache: Option<Arc<ParsedSourceCache>>, parsed_source_cache: Option<Arc<ParsedSourceCache>>,
) -> Self { ) -> Self {

View file

@ -1,21 +1,12 @@
// Copyright 2018-2025 the Deno authors. MIT license. // Copyright 2018-2025 the Deno authors. MIT license.
use std::path::Path;
use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
use deno_core::serde_json; use deno_core::serde_json;
use deno_core::url::Url;
use deno_resolver::npm::ByonmNpmResolver; use deno_resolver::npm::ByonmNpmResolver;
use deno_resolver::npm::ByonmNpmResolverCreateOptions; use deno_resolver::npm::ByonmNpmResolverCreateOptions;
use deno_resolver::npm::ByonmOrManagedNpmResolver;
use deno_resolver::npm::ResolvePkgFolderFromDenoReqError;
use deno_runtime::ops::process::NpmProcessStateProvider; use deno_runtime::ops::process::NpmProcessStateProvider;
use deno_semver::package::PackageReq;
use node_resolver::NpmPackageFolderResolver;
use super::CliNpmResolver;
use super::InnerCliNpmResolverRef;
use crate::args::NpmProcessState; use crate::args::NpmProcessState;
use crate::args::NpmProcessStateKind; use crate::args::NpmProcessStateKind;
use crate::sys::CliSys; use crate::sys::CliSys;
@ -24,67 +15,18 @@ pub type CliByonmNpmResolverCreateOptions =
ByonmNpmResolverCreateOptions<CliSys>; ByonmNpmResolverCreateOptions<CliSys>;
pub type CliByonmNpmResolver = ByonmNpmResolver<CliSys>; pub type CliByonmNpmResolver = ByonmNpmResolver<CliSys>;
// todo(dsherret): the services hanging off `CliNpmResolver` doesn't seem ideal. We should probably decouple.
#[derive(Debug)] #[derive(Debug)]
struct CliByonmWrapper(Arc<CliByonmNpmResolver>); pub struct CliByonmNpmProcessStateProvider(pub Arc<CliByonmNpmResolver>);
impl NpmProcessStateProvider for CliByonmWrapper { impl NpmProcessStateProvider for CliByonmNpmProcessStateProvider {
fn get_npm_process_state(&self) -> String { fn get_npm_process_state(&self) -> String {
serde_json::to_string(&NpmProcessState { serde_json::to_string(&NpmProcessState {
kind: NpmProcessStateKind::Byonm, kind: NpmProcessStateKind::Byonm,
local_node_modules_path: self local_node_modules_path: self
.0 .0
.root_node_modules_dir() .root_node_modules_path()
.map(|p| p.to_string_lossy().to_string()), .map(|p| p.to_string_lossy().to_string()),
}) })
.unwrap() .unwrap()
} }
} }
impl CliNpmResolver for CliByonmNpmResolver {
fn into_npm_pkg_folder_resolver(
self: Arc<Self>,
) -> Arc<dyn NpmPackageFolderResolver> {
self
}
fn into_process_state_provider(
self: Arc<Self>,
) -> Arc<dyn NpmProcessStateProvider> {
Arc::new(CliByonmWrapper(self))
}
fn into_byonm_or_managed(
self: Arc<Self>,
) -> ByonmOrManagedNpmResolver<CliSys> {
ByonmOrManagedNpmResolver::Byonm(self)
}
fn clone_snapshotted(&self) -> Arc<dyn CliNpmResolver> {
Arc::new(self.clone())
}
fn as_inner(&self) -> InnerCliNpmResolverRef {
InnerCliNpmResolverRef::Byonm(self)
}
fn root_node_modules_path(&self) -> Option<&Path> {
self.root_node_modules_dir()
}
fn check_state_hash(&self) -> Option<u64> {
// it is very difficult to determine the check state hash for byonm
// so we just return None to signify check caching is not supported
None
}
fn resolve_pkg_folder_from_deno_module_req(
&self,
req: &PackageReq,
referrer: &Url,
) -> Result<PathBuf, ResolvePkgFolderFromDenoReqError> {
self
.resolve_pkg_folder_from_deno_module_req(req, referrer)
.map_err(ResolvePkgFolderFromDenoReqError::Byonm)
}
}

View file

@ -4,44 +4,28 @@ use std::path::Path;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
use deno_ast::ModuleSpecifier;
use deno_cache_dir::npm::NpmCacheDir;
use deno_core::parking_lot::Mutex; use deno_core::parking_lot::Mutex;
use deno_core::serde_json; use deno_core::serde_json;
use deno_core::url::Url;
use deno_error::JsError; use deno_error::JsError;
use deno_error::JsErrorBox; use deno_error::JsErrorBox;
use deno_npm::npm_rc::ResolvedNpmRc;
use deno_npm::registry::NpmRegistryApi; use deno_npm::registry::NpmRegistryApi;
use deno_npm::resolution::NpmResolutionSnapshot; use deno_npm::resolution::NpmResolutionSnapshot;
use deno_npm::resolution::PackageReqNotFoundError;
use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot; use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot;
use deno_npm::NpmPackageId; use deno_resolver::npm::managed::ManagedNpmResolverCreateOptions;
use deno_npm::NpmResolutionPackage;
use deno_npm::NpmSystemInfo;
use deno_resolver::npm::managed::NpmResolutionCell; use deno_resolver::npm::managed::NpmResolutionCell;
use deno_resolver::npm::managed::ResolvePkgFolderFromDenoModuleError; use deno_resolver::npm::ManagedNpmResolverRc;
use deno_resolver::npm::managed::ResolvePkgFolderFromPkgIdError;
use deno_resolver::npm::managed::ResolvePkgIdFromSpecifierError;
use deno_resolver::npm::ByonmOrManagedNpmResolver;
use deno_resolver::npm::ManagedNpmResolver;
use deno_resolver::npm::ResolvePkgFolderFromDenoReqError;
use deno_runtime::ops::process::NpmProcessStateProvider; use deno_runtime::ops::process::NpmProcessStateProvider;
use deno_semver::package::PackageNv;
use deno_semver::package::PackageReq;
use node_resolver::NpmPackageFolderResolver;
use sys_traits::FsMetadata;
use thiserror::Error; use thiserror::Error;
use super::CliNpmRegistryInfoProvider; use super::CliNpmRegistryInfoProvider;
use super::CliNpmResolver;
use super::InnerCliNpmResolverRef;
use crate::args::CliLockfile; use crate::args::CliLockfile;
use crate::args::NpmProcessState; use crate::args::NpmProcessState;
use crate::args::NpmProcessStateKind; use crate::args::NpmProcessStateKind;
use crate::cache::FastInsecureHasher;
use crate::sys::CliSys; use crate::sys::CliSys;
pub type CliManagedNpmResolverCreateOptions =
ManagedNpmResolverCreateOptions<CliSys>;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum CliNpmResolverManagedSnapshotOption { pub enum CliNpmResolverManagedSnapshotOption {
ResolveFromLockfile(Arc<CliLockfile>), ResolveFromLockfile(Arc<CliLockfile>),
@ -139,36 +123,6 @@ impl NpmResolutionInitializer {
} }
} }
pub struct CliManagedNpmResolverCreateOptions {
pub npm_cache_dir: Arc<NpmCacheDir>,
pub sys: CliSys,
pub maybe_node_modules_path: Option<PathBuf>,
pub npm_system_info: NpmSystemInfo,
pub npmrc: Arc<ResolvedNpmRc>,
pub npm_resolution: Arc<NpmResolutionCell>,
}
pub fn create_managed_npm_resolver(
options: CliManagedNpmResolverCreateOptions,
) -> Arc<dyn CliNpmResolver> {
let managed_npm_resolver =
Arc::new(ManagedNpmResolver::<CliSys>::new::<CliSys>(
&options.npm_cache_dir,
&options.npmrc,
options.npm_resolution.clone(),
options.sys.clone(),
options.maybe_node_modules_path,
));
Arc::new(ManagedCliNpmResolver::new(
managed_npm_resolver,
options.npm_cache_dir,
options.npmrc,
options.npm_resolution,
options.sys,
options.npm_system_info,
))
}
#[derive(Debug, Error, Clone, JsError)] #[derive(Debug, Error, Clone, JsError)]
#[error("failed reading lockfile '{}'", lockfile_path.display())] #[error("failed reading lockfile '{}'", lockfile_path.display())]
#[class(inherit)] #[class(inherit)]
@ -254,145 +208,6 @@ async fn snapshot_from_lockfile(
Ok(snapshot) Ok(snapshot)
} }
/// An npm resolver where the resolution is managed by Deno rather than
/// the user bringing their own node_modules (BYONM) on the file system.
pub struct ManagedCliNpmResolver {
managed_npm_resolver: Arc<ManagedNpmResolver<CliSys>>,
npm_cache_dir: Arc<NpmCacheDir>,
npm_rc: Arc<ResolvedNpmRc>,
sys: CliSys,
resolution: Arc<NpmResolutionCell>,
system_info: NpmSystemInfo,
}
impl std::fmt::Debug for ManagedCliNpmResolver {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ManagedCliNpmResolver")
.field("<omitted>", &"<omitted>")
.finish()
}
}
impl ManagedCliNpmResolver {
#[allow(clippy::too_many_arguments)]
pub fn new(
managed_npm_resolver: Arc<ManagedNpmResolver<CliSys>>,
npm_cache_dir: Arc<NpmCacheDir>,
npm_rc: Arc<ResolvedNpmRc>,
resolution: Arc<NpmResolutionCell>,
sys: CliSys,
system_info: NpmSystemInfo,
) -> Self {
Self {
managed_npm_resolver,
npm_cache_dir,
npm_rc,
resolution,
sys,
system_info,
}
}
pub fn resolve_pkg_folder_from_pkg_id(
&self,
pkg_id: &NpmPackageId,
) -> Result<PathBuf, ResolvePkgFolderFromPkgIdError> {
self
.managed_npm_resolver
.resolve_pkg_folder_from_pkg_id(pkg_id)
}
/// Resolves the package id from the provided specifier.
pub fn resolve_pkg_id_from_specifier(
&self,
specifier: &ModuleSpecifier,
) -> Result<Option<NpmPackageId>, ResolvePkgIdFromSpecifierError> {
self
.managed_npm_resolver
.resolve_pkg_id_from_specifier(specifier)
}
pub fn resolve_pkg_reqs_from_pkg_id(
&self,
id: &NpmPackageId,
) -> Vec<PackageReq> {
self.resolution.resolve_pkg_reqs_from_pkg_id(id)
}
pub fn all_system_packages(
&self,
system_info: &NpmSystemInfo,
) -> Vec<NpmResolutionPackage> {
self.resolution.all_system_packages(system_info)
}
/// Checks if the provided package req's folder is cached.
pub fn is_pkg_req_folder_cached(&self, req: &PackageReq) -> bool {
self
.resolve_pkg_id_from_pkg_req(req)
.ok()
.and_then(|id| {
self
.managed_npm_resolver
.resolve_pkg_folder_from_pkg_id(&id)
.ok()
})
.map(|folder| self.sys.fs_exists_no_err(folder))
.unwrap_or(false)
}
pub fn snapshot(&self) -> NpmResolutionSnapshot {
self.resolution.snapshot()
}
pub fn top_package_req_for_name(&self, name: &str) -> Option<PackageReq> {
let package_reqs = self.resolution.package_reqs();
let mut entries = package_reqs
.iter()
.filter(|(_, nv)| nv.name == name)
.collect::<Vec<_>>();
entries.sort_by_key(|(_, nv)| &nv.version);
Some(entries.last()?.0.clone())
}
pub fn serialized_valid_snapshot_for_system(
&self,
system_info: &NpmSystemInfo,
) -> ValidSerializedNpmResolutionSnapshot {
self
.resolution
.serialized_valid_snapshot_for_system(system_info)
}
pub fn resolve_pkg_folder_from_deno_module(
&self,
nv: &PackageNv,
) -> Result<PathBuf, ResolvePkgFolderFromDenoModuleError> {
self
.managed_npm_resolver
.resolve_pkg_folder_from_deno_module(nv)
}
pub fn resolve_pkg_id_from_pkg_req(
&self,
req: &PackageReq,
) -> Result<NpmPackageId, PackageReqNotFoundError> {
self.resolution.resolve_pkg_id_from_pkg_req(req)
}
pub fn maybe_node_modules_path(&self) -> Option<&Path> {
self.managed_npm_resolver.node_modules_path()
}
pub fn global_cache_root_path(&self) -> &Path {
self.npm_cache_dir.root_dir()
}
pub fn global_cache_root_url(&self) -> &Url {
self.npm_cache_dir.root_dir_url()
}
}
pub fn npm_process_state( pub fn npm_process_state(
snapshot: ValidSerializedNpmResolutionSnapshot, snapshot: ValidSerializedNpmResolutionSnapshot,
node_modules_path: Option<&Path>, node_modules_path: Option<&Path>,
@ -405,92 +220,14 @@ pub fn npm_process_state(
.unwrap() .unwrap()
} }
impl NpmProcessStateProvider for ManagedCliNpmResolver { #[derive(Debug)]
pub struct CliManagedNpmProcessStateProvider(pub ManagedNpmResolverRc<CliSys>);
impl NpmProcessStateProvider for CliManagedNpmProcessStateProvider {
fn get_npm_process_state(&self) -> String { fn get_npm_process_state(&self) -> String {
npm_process_state( npm_process_state(
self.resolution.serialized_valid_snapshot(), self.0.resolution().serialized_valid_snapshot(),
self.managed_npm_resolver.node_modules_path(), self.0.root_node_modules_path(),
) )
} }
} }
impl CliNpmResolver for ManagedCliNpmResolver {
fn into_npm_pkg_folder_resolver(
self: Arc<Self>,
) -> Arc<dyn NpmPackageFolderResolver> {
self.managed_npm_resolver.clone()
}
fn into_process_state_provider(
self: Arc<Self>,
) -> Arc<dyn NpmProcessStateProvider> {
self
}
fn into_byonm_or_managed(
self: Arc<Self>,
) -> ByonmOrManagedNpmResolver<CliSys> {
ByonmOrManagedNpmResolver::Managed(self.managed_npm_resolver.clone())
}
fn clone_snapshotted(&self) -> Arc<dyn CliNpmResolver> {
// create a new snapshotted npm resolution and resolver
let npm_resolution =
Arc::new(NpmResolutionCell::new(self.resolution.snapshot()));
Arc::new(ManagedCliNpmResolver::new(
Arc::new(ManagedNpmResolver::<CliSys>::new::<CliSys>(
&self.npm_cache_dir,
&self.npm_rc,
npm_resolution.clone(),
self.sys.clone(),
self.root_node_modules_path().map(ToOwned::to_owned),
)),
self.npm_cache_dir.clone(),
self.npm_rc.clone(),
npm_resolution,
self.sys.clone(),
self.system_info.clone(),
))
}
fn as_inner(&self) -> InnerCliNpmResolverRef {
InnerCliNpmResolverRef::Managed(self)
}
fn root_node_modules_path(&self) -> Option<&Path> {
self.managed_npm_resolver.node_modules_path()
}
fn check_state_hash(&self) -> Option<u64> {
// We could go further and check all the individual
// npm packages, but that's probably overkill.
let mut package_reqs = self
.resolution
.package_reqs()
.into_iter()
.collect::<Vec<_>>();
package_reqs.sort_by(|a, b| a.0.cmp(&b.0)); // determinism
let mut hasher = FastInsecureHasher::new_without_deno_version();
// ensure the cache gets busted when turning nodeModulesDir on or off
// as this could cause changes in resolution
hasher
.write_hashable(self.managed_npm_resolver.node_modules_path().is_some());
for (pkg_req, pkg_nv) in package_reqs {
hasher.write_hashable(&pkg_req);
hasher.write_hashable(&pkg_nv);
}
Some(hasher.finish())
}
fn resolve_pkg_folder_from_deno_module_req(
&self,
req: &PackageReq,
referrer: &Url,
) -> Result<PathBuf, ResolvePkgFolderFromDenoReqError> {
self
.managed_npm_resolver
.resolve_pkg_folder_from_deno_module_req(req, referrer)
.map_err(ResolvePkgFolderFromDenoReqError::Managed)
}
}

View file

@ -3,10 +3,7 @@
mod byonm; mod byonm;
pub mod installer; pub mod installer;
mod managed; mod managed;
mod permission_checker;
use std::path::Path;
use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
use dashmap::DashMap; use dashmap::DashMap;
@ -15,25 +12,17 @@ use deno_core::url::Url;
use deno_error::JsErrorBox; use deno_error::JsErrorBox;
use deno_npm::npm_rc::ResolvedNpmRc; use deno_npm::npm_rc::ResolvedNpmRc;
use deno_npm::registry::NpmPackageInfo; use deno_npm::registry::NpmPackageInfo;
use deno_resolver::npm::ByonmNpmResolver; use deno_runtime::ops::process::NpmProcessStateProviderRc;
use deno_resolver::npm::ByonmOrManagedNpmResolver;
use deno_resolver::npm::ResolvePkgFolderFromDenoReqError;
use deno_runtime::ops::process::NpmProcessStateProvider;
use deno_semver::package::PackageNv; use deno_semver::package::PackageNv;
use deno_semver::package::PackageReq; use deno_semver::package::PackageReq;
use http::HeaderName; use http::HeaderName;
use http::HeaderValue; use http::HeaderValue;
use node_resolver::NpmPackageFolderResolver;
pub use self::byonm::CliByonmNpmResolver;
pub use self::byonm::CliByonmNpmResolverCreateOptions; pub use self::byonm::CliByonmNpmResolverCreateOptions;
pub use self::managed::CliManagedNpmResolverCreateOptions; pub use self::managed::CliManagedNpmResolverCreateOptions;
pub use self::managed::CliNpmResolverManagedSnapshotOption; pub use self::managed::CliNpmResolverManagedSnapshotOption;
pub use self::managed::ManagedCliNpmResolver;
pub use self::managed::NpmResolutionInitializer; pub use self::managed::NpmResolutionInitializer;
pub use self::managed::ResolveSnapshotError; pub use self::managed::ResolveSnapshotError;
pub use self::permission_checker::NpmRegistryReadPermissionChecker;
pub use self::permission_checker::NpmRegistryReadPermissionCheckerMode;
use crate::file_fetcher::CliFileFetcher; use crate::file_fetcher::CliFileFetcher;
use crate::http_util::HttpClientProvider; use crate::http_util::HttpClientProvider;
use crate::sys::CliSys; use crate::sys::CliSys;
@ -44,6 +33,10 @@ pub type CliNpmTarballCache =
pub type CliNpmCache = deno_npm_cache::NpmCache<CliSys>; pub type CliNpmCache = deno_npm_cache::NpmCache<CliSys>;
pub type CliNpmRegistryInfoProvider = pub type CliNpmRegistryInfoProvider =
deno_npm_cache::RegistryInfoProvider<CliNpmCacheHttpClient, CliSys>; deno_npm_cache::RegistryInfoProvider<CliNpmCacheHttpClient, CliSys>;
pub type CliNpmResolver = deno_resolver::npm::NpmResolver<CliSys>;
pub type CliManagedNpmResolver = deno_resolver::npm::ManagedNpmResolver<CliSys>;
pub type CliNpmResolverCreateOptions =
deno_resolver::npm::NpmResolverCreateOptions<CliSys>;
#[derive(Debug)] #[derive(Debug)]
pub struct CliNpmCacheHttpClient { pub struct CliNpmCacheHttpClient {
@ -63,6 +56,19 @@ impl CliNpmCacheHttpClient {
} }
} }
pub fn create_npm_process_state_provider(
npm_resolver: &CliNpmResolver,
) -> NpmProcessStateProviderRc {
match npm_resolver {
CliNpmResolver::Byonm(byonm_npm_resolver) => Arc::new(
byonm::CliByonmNpmProcessStateProvider(byonm_npm_resolver.clone()),
),
CliNpmResolver::Managed(managed_npm_resolver) => Arc::new(
managed::CliManagedNpmProcessStateProvider(managed_npm_resolver.clone()),
),
}
}
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl deno_npm_cache::NpmCacheHttpClient for CliNpmCacheHttpClient { impl deno_npm_cache::NpmCacheHttpClient for CliNpmCacheHttpClient {
async fn download_with_retries_on_any_tokio_runtime( async fn download_with_retries_on_any_tokio_runtime(
@ -104,70 +110,6 @@ impl deno_npm_cache::NpmCacheHttpClient for CliNpmCacheHttpClient {
} }
} }
pub enum CliNpmResolverCreateOptions {
Managed(CliManagedNpmResolverCreateOptions),
Byonm(CliByonmNpmResolverCreateOptions),
}
pub fn create_cli_npm_resolver(
options: CliNpmResolverCreateOptions,
) -> Arc<dyn CliNpmResolver> {
use CliNpmResolverCreateOptions::*;
match options {
Managed(options) => managed::create_managed_npm_resolver(options),
Byonm(options) => Arc::new(ByonmNpmResolver::new(options)),
}
}
pub enum InnerCliNpmResolverRef<'a> {
Managed(&'a ManagedCliNpmResolver),
#[allow(dead_code)]
Byonm(&'a CliByonmNpmResolver),
}
// todo(dsherret): replace with an enum
pub trait CliNpmResolver: Send + Sync + std::fmt::Debug {
fn into_npm_pkg_folder_resolver(
self: Arc<Self>,
) -> Arc<dyn NpmPackageFolderResolver>;
fn into_process_state_provider(
self: Arc<Self>,
) -> Arc<dyn NpmProcessStateProvider>;
fn into_byonm_or_managed(
self: Arc<Self>,
) -> ByonmOrManagedNpmResolver<CliSys>;
fn clone_snapshotted(&self) -> Arc<dyn CliNpmResolver>;
fn as_inner(&self) -> InnerCliNpmResolverRef;
fn as_managed(&self) -> Option<&ManagedCliNpmResolver> {
match self.as_inner() {
InnerCliNpmResolverRef::Managed(inner) => Some(inner),
InnerCliNpmResolverRef::Byonm(_) => None,
}
}
fn as_byonm(&self) -> Option<&CliByonmNpmResolver> {
match self.as_inner() {
InnerCliNpmResolverRef::Managed(_) => None,
InnerCliNpmResolverRef::Byonm(inner) => Some(inner),
}
}
fn resolve_pkg_folder_from_deno_module_req(
&self,
req: &PackageReq,
referrer: &Url,
) -> Result<PathBuf, ResolvePkgFolderFromDenoReqError>;
fn root_node_modules_path(&self) -> Option<&Path>;
/// Returns a hash returning the state of the npm resolver
/// or `None` if the state currently can't be determined.
fn check_state_hash(&self) -> Option<u64>;
}
#[derive(Debug)] #[derive(Debug)]
pub struct NpmFetchResolver { pub struct NpmFetchResolver {
nv_by_req: DashMap<PackageReq, Option<PackageNv>>, nv_by_req: DashMap<PackageReq, Option<PackageNv>>,

View file

@ -19,6 +19,7 @@ use deno_graph::source::UnknownBuiltInNodeModuleError;
use deno_graph::NpmLoadError; use deno_graph::NpmLoadError;
use deno_graph::NpmResolvePkgReqsResult; use deno_graph::NpmResolvePkgReqsResult;
use deno_npm::resolution::NpmResolutionError; use deno_npm::resolution::NpmResolutionError;
use deno_resolver::npm::DenoInNpmPackageChecker;
use deno_resolver::sloppy_imports::SloppyImportsCachedFs; use deno_resolver::sloppy_imports::SloppyImportsCachedFs;
use deno_resolver::sloppy_imports::SloppyImportsResolver; use deno_resolver::sloppy_imports::SloppyImportsResolver;
use deno_runtime::colors; use deno_runtime::colors;
@ -35,22 +36,31 @@ use crate::args::DENO_DISABLE_PEDANTIC_NODE_WARNINGS;
use crate::node::CliNodeCodeTranslator; use crate::node::CliNodeCodeTranslator;
use crate::npm::installer::NpmInstaller; use crate::npm::installer::NpmInstaller;
use crate::npm::installer::PackageCaching; use crate::npm::installer::PackageCaching;
use crate::npm::CliNpmResolver;
use crate::sys::CliSys; use crate::sys::CliSys;
use crate::util::sync::AtomicFlag; use crate::util::sync::AtomicFlag;
use crate::util::text_encoding::from_utf8_lossy_cow; use crate::util::text_encoding::from_utf8_lossy_cow;
pub type CjsTracker = deno_resolver::cjs::CjsTracker<CliSys>; pub type CliCjsTracker =
pub type IsCjsResolver = deno_resolver::cjs::IsCjsResolver<CliSys>; deno_resolver::cjs::CjsTracker<DenoInNpmPackageChecker, CliSys>;
pub type CliIsCjsResolver =
deno_resolver::cjs::IsCjsResolver<DenoInNpmPackageChecker, CliSys>;
pub type CliSloppyImportsCachedFs = SloppyImportsCachedFs<CliSys>; pub type CliSloppyImportsCachedFs = SloppyImportsCachedFs<CliSys>;
pub type CliSloppyImportsResolver = pub type CliSloppyImportsResolver =
SloppyImportsResolver<CliSloppyImportsCachedFs>; SloppyImportsResolver<CliSloppyImportsCachedFs>;
pub type CliDenoResolver = deno_resolver::DenoResolver< pub type CliDenoResolver = deno_resolver::DenoResolver<
DenoInNpmPackageChecker,
RealIsBuiltInNodeModuleChecker, RealIsBuiltInNodeModuleChecker,
CliNpmResolver,
CliSloppyImportsCachedFs, CliSloppyImportsCachedFs,
CliSys, CliSys,
>; >;
pub type CliNpmReqResolver = pub type CliNpmReqResolver = deno_resolver::npm::NpmReqResolver<
deno_resolver::npm::NpmReqResolver<RealIsBuiltInNodeModuleChecker, CliSys>; DenoInNpmPackageChecker,
RealIsBuiltInNodeModuleChecker,
CliNpmResolver,
CliSys,
>;
pub struct ModuleCodeStringSource { pub struct ModuleCodeStringSource {
pub code: ModuleSourceCode, pub code: ModuleSourceCode,
@ -69,14 +79,14 @@ pub struct NotSupportedKindInNpmError {
// todo(dsherret): move to module_loader.rs (it seems to be here due to use in standalone) // todo(dsherret): move to module_loader.rs (it seems to be here due to use in standalone)
#[derive(Clone)] #[derive(Clone)]
pub struct NpmModuleLoader { pub struct NpmModuleLoader {
cjs_tracker: Arc<CjsTracker>, cjs_tracker: Arc<CliCjsTracker>,
fs: Arc<dyn deno_fs::FileSystem>, fs: Arc<dyn deno_fs::FileSystem>,
node_code_translator: Arc<CliNodeCodeTranslator>, node_code_translator: Arc<CliNodeCodeTranslator>,
} }
impl NpmModuleLoader { impl NpmModuleLoader {
pub fn new( pub fn new(
cjs_tracker: Arc<CjsTracker>, cjs_tracker: Arc<CliCjsTracker>,
fs: Arc<dyn deno_fs::FileSystem>, fs: Arc<dyn deno_fs::FileSystem>,
node_code_translator: Arc<CliNodeCodeTranslator>, node_code_translator: Arc<CliNodeCodeTranslator>,
) -> Self { ) -> Self {

View file

@ -38,6 +38,13 @@ use deno_core::futures::AsyncSeekExt;
use deno_core::serde_json; use deno_core::serde_json;
use deno_core::url::Url; use deno_core::url::Url;
use deno_graph::ModuleGraph; use deno_graph::ModuleGraph;
use deno_lib::cache::DenoDir;
use deno_lib::standalone::virtual_fs::FileSystemCaseSensitivity;
use deno_lib::standalone::virtual_fs::VfsEntry;
use deno_lib::standalone::virtual_fs::VfsFileSubDataKind;
use deno_lib::standalone::virtual_fs::VirtualDirectory;
use deno_lib::standalone::virtual_fs::VirtualDirectoryEntries;
use deno_lib::standalone::virtual_fs::WindowsSystemRootablePath;
use deno_npm::resolution::SerializedNpmResolutionSnapshot; use deno_npm::resolution::SerializedNpmResolutionSnapshot;
use deno_npm::resolution::SerializedNpmResolutionSnapshotPackage; use deno_npm::resolution::SerializedNpmResolutionSnapshotPackage;
use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot; use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot;
@ -73,29 +80,22 @@ use super::serialization::SourceMapStore;
use super::virtual_fs::output_vfs; use super::virtual_fs::output_vfs;
use super::virtual_fs::BuiltVfs; use super::virtual_fs::BuiltVfs;
use super::virtual_fs::FileBackedVfs; use super::virtual_fs::FileBackedVfs;
use super::virtual_fs::FileSystemCaseSensitivity;
use super::virtual_fs::VfsBuilder; use super::virtual_fs::VfsBuilder;
use super::virtual_fs::VfsFileSubDataKind;
use super::virtual_fs::VfsRoot; use super::virtual_fs::VfsRoot;
use super::virtual_fs::VirtualDirectory;
use super::virtual_fs::VirtualDirectoryEntries;
use super::virtual_fs::WindowsSystemRootablePath;
use crate::args::CaData; use crate::args::CaData;
use crate::args::CliOptions; use crate::args::CliOptions;
use crate::args::CompileFlags; use crate::args::CompileFlags;
use crate::args::NpmInstallDepsProvider; use crate::args::NpmInstallDepsProvider;
use crate::args::PermissionFlags; use crate::args::PermissionFlags;
use crate::args::UnstableConfig; use crate::args::UnstableConfig;
use crate::cache::DenoDir;
use crate::cache::FastInsecureHasher; use crate::cache::FastInsecureHasher;
use crate::emit::Emitter; use crate::emit::Emitter;
use crate::file_fetcher::CliFileFetcher; use crate::file_fetcher::CliFileFetcher;
use crate::http_util::HttpClientProvider; use crate::http_util::HttpClientProvider;
use crate::npm::CliNpmResolver; use crate::npm::CliNpmResolver;
use crate::npm::InnerCliNpmResolverRef; use crate::resolver::CliCjsTracker;
use crate::resolver::CjsTracker;
use crate::shared::ReleaseChannel; use crate::shared::ReleaseChannel;
use crate::standalone::virtual_fs::VfsEntry; use crate::sys::CliSys;
use crate::util::archive; use crate::util::archive;
use crate::util::fs::canonicalize_path; use crate::util::fs::canonicalize_path;
use crate::util::fs::canonicalize_path_maybe_not_exists; use crate::util::fs::canonicalize_path_maybe_not_exists;
@ -410,13 +410,13 @@ pub struct WriteBinOptions<'a> {
} }
pub struct DenoCompileBinaryWriter<'a> { pub struct DenoCompileBinaryWriter<'a> {
cjs_tracker: &'a CjsTracker, cjs_tracker: &'a CliCjsTracker,
cli_options: &'a CliOptions, cli_options: &'a CliOptions,
deno_dir: &'a DenoDir, deno_dir: &'a DenoDir<CliSys>,
emitter: &'a Emitter, emitter: &'a Emitter,
file_fetcher: &'a CliFileFetcher, file_fetcher: &'a CliFileFetcher,
http_client_provider: &'a HttpClientProvider, http_client_provider: &'a HttpClientProvider,
npm_resolver: &'a dyn CliNpmResolver, npm_resolver: &'a CliNpmResolver,
workspace_resolver: &'a WorkspaceResolver, workspace_resolver: &'a WorkspaceResolver,
npm_system_info: NpmSystemInfo, npm_system_info: NpmSystemInfo,
} }
@ -424,13 +424,13 @@ pub struct DenoCompileBinaryWriter<'a> {
impl<'a> DenoCompileBinaryWriter<'a> { impl<'a> DenoCompileBinaryWriter<'a> {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn new( pub fn new(
cjs_tracker: &'a CjsTracker, cjs_tracker: &'a CliCjsTracker,
cli_options: &'a CliOptions, cli_options: &'a CliOptions,
deno_dir: &'a DenoDir, deno_dir: &'a DenoDir<CliSys>,
emitter: &'a Emitter, emitter: &'a Emitter,
file_fetcher: &'a CliFileFetcher, file_fetcher: &'a CliFileFetcher,
http_client_provider: &'a HttpClientProvider, http_client_provider: &'a HttpClientProvider,
npm_resolver: &'a dyn CliNpmResolver, npm_resolver: &'a CliNpmResolver,
workspace_resolver: &'a WorkspaceResolver, workspace_resolver: &'a WorkspaceResolver,
npm_system_info: NpmSystemInfo, npm_system_info: NpmSystemInfo,
) -> Self { ) -> Self {
@ -599,10 +599,11 @@ impl<'a> DenoCompileBinaryWriter<'a> {
None => None, None => None,
}; };
let mut vfs = VfsBuilder::new(); let mut vfs = VfsBuilder::new();
let npm_snapshot = match self.npm_resolver.as_inner() { let npm_snapshot = match &self.npm_resolver {
InnerCliNpmResolverRef::Managed(managed) => { CliNpmResolver::Managed(managed) => {
let snapshot = let snapshot = managed
managed.serialized_valid_snapshot_for_system(&self.npm_system_info); .resolution()
.serialized_valid_snapshot_for_system(&self.npm_system_info);
if !snapshot.as_serialized().packages.is_empty() { if !snapshot.as_serialized().packages.is_empty() {
self.fill_npm_vfs(&mut vfs).context("Building npm vfs.")?; self.fill_npm_vfs(&mut vfs).context("Building npm vfs.")?;
Some(snapshot) Some(snapshot)
@ -610,7 +611,7 @@ impl<'a> DenoCompileBinaryWriter<'a> {
None None
} }
} }
InnerCliNpmResolverRef::Byonm(_) => { CliNpmResolver::Byonm(_) => {
self.fill_npm_vfs(&mut vfs)?; self.fill_npm_vfs(&mut vfs)?;
None None
} }
@ -751,8 +752,8 @@ impl<'a> DenoCompileBinaryWriter<'a> {
); );
} }
let node_modules = match self.npm_resolver.as_inner() { let node_modules = match &self.npm_resolver {
InnerCliNpmResolverRef::Managed(_) => { CliNpmResolver::Managed(_) => {
npm_snapshot.as_ref().map(|_| NodeModules::Managed { npm_snapshot.as_ref().map(|_| NodeModules::Managed {
node_modules_dir: self.npm_resolver.root_node_modules_path().map( node_modules_dir: self.npm_resolver.root_node_modules_path().map(
|path| { |path| {
@ -765,7 +766,7 @@ impl<'a> DenoCompileBinaryWriter<'a> {
), ),
}) })
} }
InnerCliNpmResolverRef::Byonm(resolver) => Some(NodeModules::Byonm { CliNpmResolver::Byonm(resolver) => Some(NodeModules::Byonm {
root_node_modules_dir: resolver.root_node_modules_path().map( root_node_modules_dir: resolver.root_node_modules_path().map(
|node_modules_dir| { |node_modules_dir| {
root_dir_url root_dir_url
@ -880,16 +881,17 @@ impl<'a> DenoCompileBinaryWriter<'a> {
} }
} }
match self.npm_resolver.as_inner() { match &self.npm_resolver {
InnerCliNpmResolverRef::Managed(npm_resolver) => { CliNpmResolver::Managed(npm_resolver) => {
if let Some(node_modules_path) = npm_resolver.root_node_modules_path() { if let Some(node_modules_path) = npm_resolver.root_node_modules_path() {
maybe_warn_different_system(&self.npm_system_info); maybe_warn_different_system(&self.npm_system_info);
builder.add_dir_recursive(node_modules_path)?; builder.add_dir_recursive(node_modules_path)?;
Ok(()) Ok(())
} else { } else {
// we'll flatten to remove any custom registries later // we'll flatten to remove any custom registries later
let mut packages = let mut packages = npm_resolver
npm_resolver.all_system_packages(&self.npm_system_info); .resolution()
.all_system_packages(&self.npm_system_info);
packages.sort_by(|a, b| a.id.cmp(&b.id)); // determinism packages.sort_by(|a, b| a.id.cmp(&b.id)); // determinism
for package in packages { for package in packages {
let folder = let folder =
@ -899,7 +901,7 @@ impl<'a> DenoCompileBinaryWriter<'a> {
Ok(()) Ok(())
} }
} }
InnerCliNpmResolverRef::Byonm(_) => { CliNpmResolver::Byonm(_) => {
maybe_warn_different_system(&self.npm_system_info); maybe_warn_different_system(&self.npm_system_info);
for pkg_json in self.cli_options.workspace().package_jsons() { for pkg_json in self.cli_options.workspace().package_jsons() {
builder.add_file_at_path(&pkg_json.path)?; builder.add_file_at_path(&pkg_json.path)?;
@ -942,8 +944,8 @@ impl<'a> DenoCompileBinaryWriter<'a> {
&self, &self,
mut vfs: VfsBuilder, mut vfs: VfsBuilder,
) -> BuiltVfs { ) -> BuiltVfs {
match self.npm_resolver.as_inner() { match &self.npm_resolver {
InnerCliNpmResolverRef::Managed(npm_resolver) => { CliNpmResolver::Managed(npm_resolver) => {
if npm_resolver.root_node_modules_path().is_some() { if npm_resolver.root_node_modules_path().is_some() {
return vfs.build(); return vfs.build();
} }
@ -1035,7 +1037,7 @@ impl<'a> DenoCompileBinaryWriter<'a> {
.insert(npm_global_cache_dir_entry, case_sensitivity); .insert(npm_global_cache_dir_entry, case_sensitivity);
built_vfs built_vfs
} }
InnerCliNpmResolverRef::Byonm(_) => vfs.build(), CliNpmResolver::Byonm(_) => vfs.build(),
} }
} }
} }

View file

@ -9,6 +9,7 @@ use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use std::time::SystemTime; use std::time::SystemTime;
use deno_lib::standalone::virtual_fs::VfsFileSubDataKind;
use deno_runtime::deno_fs::AccessCheckCb; use deno_runtime::deno_fs::AccessCheckCb;
use deno_runtime::deno_fs::FileSystem; use deno_runtime::deno_fs::FileSystem;
use deno_runtime::deno_fs::FsDirEntry; use deno_runtime::deno_fs::FsDirEntry;
@ -30,7 +31,6 @@ use super::virtual_fs::FileBackedVfs;
use super::virtual_fs::FileBackedVfsDirEntry; use super::virtual_fs::FileBackedVfsDirEntry;
use super::virtual_fs::FileBackedVfsFile; use super::virtual_fs::FileBackedVfsFile;
use super::virtual_fs::FileBackedVfsMetadata; use super::virtual_fs::FileBackedVfsMetadata;
use super::virtual_fs::VfsFileSubDataKind;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct DenoCompileFileSystem(Arc<FileBackedVfs>); pub struct DenoCompileFileSystem(Arc<FileBackedVfs>);

View file

@ -36,14 +36,24 @@ use deno_core::RequestedModuleType;
use deno_core::ResolutionKind; use deno_core::ResolutionKind;
use deno_core::SourceCodeCacheInfo; use deno_core::SourceCodeCacheInfo;
use deno_error::JsErrorBox; use deno_error::JsErrorBox;
use deno_lib::cache::DenoDirProvider;
use deno_lib::npm::NpmRegistryReadPermissionChecker;
use deno_lib::npm::NpmRegistryReadPermissionCheckerMode;
use deno_lib::standalone::virtual_fs::VfsFileSubDataKind;
use deno_lib::worker::CreateModuleLoaderResult;
use deno_lib::worker::LibMainWorkerFactory;
use deno_lib::worker::LibMainWorkerOptions;
use deno_lib::worker::ModuleLoaderFactory;
use deno_lib::worker::StorageKeyResolver;
use deno_npm::npm_rc::ResolvedNpmRc; use deno_npm::npm_rc::ResolvedNpmRc;
use deno_npm::resolution::NpmResolutionSnapshot; use deno_npm::resolution::NpmResolutionSnapshot;
use deno_package_json::PackageJsonDepValue; use deno_package_json::PackageJsonDepValue;
use deno_resolver::cjs::IsCjsResolutionMode; use deno_resolver::cjs::IsCjsResolutionMode;
use deno_resolver::npm::create_in_npm_pkg_checker;
use deno_resolver::npm::managed::ManagedInNpmPkgCheckerCreateOptions; use deno_resolver::npm::managed::ManagedInNpmPkgCheckerCreateOptions;
use deno_resolver::npm::managed::NpmResolutionCell; use deno_resolver::npm::managed::NpmResolutionCell;
use deno_resolver::npm::ByonmNpmResolverCreateOptions;
use deno_resolver::npm::CreateInNpmPkgCheckerOptions; use deno_resolver::npm::CreateInNpmPkgCheckerOptions;
use deno_resolver::npm::DenoInNpmPackageChecker;
use deno_resolver::npm::NpmReqResolverOptions; use deno_resolver::npm::NpmReqResolverOptions;
use deno_runtime::deno_fs; use deno_runtime::deno_fs;
use deno_runtime::deno_fs::FileSystem; use deno_runtime::deno_fs::FileSystem;
@ -68,16 +78,13 @@ use node_resolver::ResolutionMode;
use serialization::DenoCompileModuleSource; use serialization::DenoCompileModuleSource;
use serialization::SourceMapStore; use serialization::SourceMapStore;
use virtual_fs::FileBackedVfs; use virtual_fs::FileBackedVfs;
use virtual_fs::VfsFileSubDataKind;
use crate::args::create_default_npmrc; use crate::args::create_default_npmrc;
use crate::args::get_root_cert_store; use crate::args::get_root_cert_store;
use crate::args::npm_pkg_req_ref_to_binary_command; use crate::args::npm_pkg_req_ref_to_binary_command;
use crate::args::CaData; use crate::args::CaData;
use crate::args::NpmInstallDepsProvider; use crate::args::NpmInstallDepsProvider;
use crate::args::StorageKeyResolver;
use crate::cache::Caches; use crate::cache::Caches;
use crate::cache::DenoDirProvider;
use crate::cache::FastInsecureHasher; use crate::cache::FastInsecureHasher;
use crate::cache::NodeAnalysisCache; use crate::cache::NodeAnalysisCache;
use crate::http_util::HttpClientProvider; use crate::http_util::HttpClientProvider;
@ -85,16 +92,14 @@ use crate::node::CliCjsCodeAnalyzer;
use crate::node::CliNodeCodeTranslator; use crate::node::CliNodeCodeTranslator;
use crate::node::CliNodeResolver; use crate::node::CliNodeResolver;
use crate::node::CliPackageJsonResolver; use crate::node::CliPackageJsonResolver;
use crate::npm::create_cli_npm_resolver; use crate::npm::create_npm_process_state_provider;
use crate::npm::CliByonmNpmResolverCreateOptions; use crate::npm::CliByonmNpmResolverCreateOptions;
use crate::npm::CliManagedNpmResolverCreateOptions; use crate::npm::CliManagedNpmResolverCreateOptions;
use crate::npm::CliNpmResolver; use crate::npm::CliNpmResolver;
use crate::npm::CliNpmResolverCreateOptions; use crate::npm::CliNpmResolverCreateOptions;
use crate::npm::CliNpmResolverManagedSnapshotOption; use crate::npm::CliNpmResolverManagedSnapshotOption;
use crate::npm::NpmRegistryReadPermissionChecker;
use crate::npm::NpmRegistryReadPermissionCheckerMode;
use crate::npm::NpmResolutionInitializer; use crate::npm::NpmResolutionInitializer;
use crate::resolver::CjsTracker; use crate::resolver::CliCjsTracker;
use crate::resolver::CliNpmReqResolver; use crate::resolver::CliNpmReqResolver;
use crate::resolver::NpmModuleLoader; use crate::resolver::NpmModuleLoader;
use crate::sys::CliSys; use crate::sys::CliSys;
@ -105,8 +110,6 @@ use crate::util::v8::construct_v8_flags;
use crate::worker::CliCodeCache; use crate::worker::CliCodeCache;
use crate::worker::CliMainWorkerFactory; use crate::worker::CliMainWorkerFactory;
use crate::worker::CliMainWorkerOptions; use crate::worker::CliMainWorkerOptions;
use crate::worker::CreateModuleLoaderResult;
use crate::worker::ModuleLoaderFactory;
pub mod binary; pub mod binary;
mod code_cache; mod code_cache;
@ -122,16 +125,16 @@ use self::binary::Metadata;
pub use self::file_system::DenoCompileFileSystem; pub use self::file_system::DenoCompileFileSystem;
struct SharedModuleLoaderState { struct SharedModuleLoaderState {
cjs_tracker: Arc<CjsTracker>, cjs_tracker: Arc<CliCjsTracker>,
code_cache: Option<Arc<dyn CliCodeCache>>, code_cache: Option<Arc<dyn CliCodeCache>>,
fs: Arc<dyn deno_fs::FileSystem>, fs: Arc<dyn deno_fs::FileSystem>,
modules: StandaloneModules, modules: StandaloneModules,
node_code_translator: Arc<CliNodeCodeTranslator>, node_code_translator: Arc<CliNodeCodeTranslator>,
node_resolver: Arc<CliNodeResolver>, node_resolver: Arc<CliNodeResolver>,
npm_module_loader: Arc<NpmModuleLoader>, npm_module_loader: Arc<NpmModuleLoader>,
npm_registry_permission_checker: NpmRegistryReadPermissionChecker, npm_registry_permission_checker: NpmRegistryReadPermissionChecker<CliSys>,
npm_req_resolver: Arc<CliNpmReqResolver>, npm_req_resolver: Arc<CliNpmReqResolver>,
npm_resolver: Arc<dyn CliNpmResolver>, npm_resolver: CliNpmResolver,
source_maps: SourceMapStore, source_maps: SourceMapStore,
vfs: Arc<FileBackedVfs>, vfs: Arc<FileBackedVfs>,
workspace_resolver: WorkspaceResolver, workspace_resolver: WorkspaceResolver,
@ -734,7 +737,7 @@ pub async fn run(
let maybe_node_modules_path = node_modules_dir let maybe_node_modules_path = node_modules_dir
.map(|node_modules_dir| root_path.join(node_modules_dir)); .map(|node_modules_dir| root_path.join(node_modules_dir));
let in_npm_pkg_checker = let in_npm_pkg_checker =
create_in_npm_pkg_checker(CreateInNpmPkgCheckerOptions::Managed( DenoInNpmPackageChecker::new(CreateInNpmPkgCheckerOptions::Managed(
ManagedInNpmPkgCheckerCreateOptions { ManagedInNpmPkgCheckerCreateOptions {
root_cache_dir_url: npm_cache_dir.root_dir_url(), root_cache_dir_url: npm_cache_dir.root_dir_url(),
maybe_node_modules_path: maybe_node_modules_path.as_deref(), maybe_node_modules_path: maybe_node_modules_path.as_deref(),
@ -743,7 +746,7 @@ pub async fn run(
let npm_resolution = let npm_resolution =
Arc::new(NpmResolutionCell::new(NpmResolutionSnapshot::new(snapshot))); Arc::new(NpmResolutionCell::new(NpmResolutionSnapshot::new(snapshot)));
let npm_resolver = let npm_resolver =
create_cli_npm_resolver(CliNpmResolverCreateOptions::Managed( CliNpmResolver::new(CliNpmResolverCreateOptions::Managed(
CliManagedNpmResolverCreateOptions { CliManagedNpmResolverCreateOptions {
npm_resolution, npm_resolution,
npm_cache_dir, npm_cache_dir,
@ -761,8 +764,8 @@ pub async fn run(
let root_node_modules_dir = let root_node_modules_dir =
root_node_modules_dir.map(|p| vfs.root().join(p)); root_node_modules_dir.map(|p| vfs.root().join(p));
let in_npm_pkg_checker = let in_npm_pkg_checker =
create_in_npm_pkg_checker(CreateInNpmPkgCheckerOptions::Byonm); DenoInNpmPackageChecker::new(CreateInNpmPkgCheckerOptions::Byonm);
let npm_resolver = create_cli_npm_resolver( let npm_resolver = CliNpmResolver::new(
CliNpmResolverCreateOptions::Byonm(CliByonmNpmResolverCreateOptions { CliNpmResolverCreateOptions::Byonm(CliByonmNpmResolverCreateOptions {
sys: sys.clone(), sys: sys.clone(),
pkg_json_resolver: pkg_json_resolver.clone(), pkg_json_resolver: pkg_json_resolver.clone(),
@ -781,7 +784,7 @@ pub async fn run(
npmrc.get_all_known_registries_urls(), npmrc.get_all_known_registries_urls(),
)); ));
let in_npm_pkg_checker = let in_npm_pkg_checker =
create_in_npm_pkg_checker(CreateInNpmPkgCheckerOptions::Managed( DenoInNpmPackageChecker::new(CreateInNpmPkgCheckerOptions::Managed(
ManagedInNpmPkgCheckerCreateOptions { ManagedInNpmPkgCheckerCreateOptions {
root_cache_dir_url: npm_cache_dir.root_dir_url(), root_cache_dir_url: npm_cache_dir.root_dir_url(),
maybe_node_modules_path: None, maybe_node_modules_path: None,
@ -789,7 +792,7 @@ pub async fn run(
)); ));
let npm_resolution = Arc::new(NpmResolutionCell::default()); let npm_resolution = Arc::new(NpmResolutionCell::default());
let npm_resolver = let npm_resolver =
create_cli_npm_resolver(CliNpmResolverCreateOptions::Managed( CliNpmResolver::new(CliNpmResolverCreateOptions::Managed(
CliManagedNpmResolverCreateOptions { CliManagedNpmResolverCreateOptions {
npm_resolution, npm_resolution,
sys: sys.clone(), sys: sys.clone(),
@ -807,12 +810,12 @@ pub async fn run(
let node_resolver = Arc::new(NodeResolver::new( let node_resolver = Arc::new(NodeResolver::new(
in_npm_pkg_checker.clone(), in_npm_pkg_checker.clone(),
RealIsBuiltInNodeModuleChecker, RealIsBuiltInNodeModuleChecker,
npm_resolver.clone().into_npm_pkg_folder_resolver(), npm_resolver.clone(),
pkg_json_resolver.clone(), pkg_json_resolver.clone(),
sys.clone(), sys.clone(),
node_resolver::ConditionsFromResolutionMode::default(), node_resolver::ConditionsFromResolutionMode::default(),
)); ));
let cjs_tracker = Arc::new(CjsTracker::new( let cjs_tracker = Arc::new(CliCjsTracker::new(
in_npm_pkg_checker.clone(), in_npm_pkg_checker.clone(),
pkg_json_resolver.clone(), pkg_json_resolver.clone(),
if metadata.unstable_config.detect_cjs { if metadata.unstable_config.detect_cjs {
@ -830,7 +833,7 @@ pub async fn run(
sys: sys.clone(), sys: sys.clone(),
in_npm_pkg_checker: in_npm_pkg_checker.clone(), in_npm_pkg_checker: in_npm_pkg_checker.clone(),
node_resolver: node_resolver.clone(), node_resolver: node_resolver.clone(),
npm_resolver: npm_resolver.clone().into_byonm_or_managed(), npm_resolver: npm_resolver.clone(),
})); }));
let cjs_esm_code_analyzer = CliCjsCodeAnalyzer::new( let cjs_esm_code_analyzer = CliCjsCodeAnalyzer::new(
node_analysis_cache, node_analysis_cache,
@ -842,7 +845,7 @@ pub async fn run(
cjs_esm_code_analyzer, cjs_esm_code_analyzer,
in_npm_pkg_checker, in_npm_pkg_checker,
node_resolver.clone(), node_resolver.clone(),
npm_resolver.clone().into_npm_pkg_folder_resolver(), npm_resolver.clone(),
pkg_json_resolver.clone(), pkg_json_resolver.clone(),
sys.clone(), sys.clone(),
)); ));
@ -962,31 +965,12 @@ pub async fn run(
} }
checker checker
}); });
let worker_factory = CliMainWorkerFactory::new( let lib_main_worker_options = LibMainWorkerOptions {
Arc::new(BlobStore::default()),
code_cache,
feature_checker,
fs,
None,
None,
None,
Box::new(module_loader_factory),
node_resolver,
None,
npm_resolver,
pkg_json_resolver,
root_cert_store_provider,
permissions,
StorageKeyResolver::empty(),
sys,
crate::args::DenoSubcommand::Run(Default::default()),
CliMainWorkerOptions {
argv: metadata.argv, argv: metadata.argv,
log_level: WorkerLogLevel::Info, log_level: WorkerLogLevel::Info,
enable_op_summary_metrics: false, enable_op_summary_metrics: false,
enable_testing_features: false, enable_testing_features: false,
has_node_modules_dir, has_node_modules_dir,
hmr: false,
inspect_brk: false, inspect_brk: false,
inspect_wait: false, inspect_wait: false,
strace_ops: None, strace_ops: None,
@ -1002,14 +986,46 @@ pub async fn run(
seed: metadata.seed, seed: metadata.seed,
unsafely_ignore_certificate_errors: metadata unsafely_ignore_certificate_errors: metadata
.unsafely_ignore_certificate_errors, .unsafely_ignore_certificate_errors,
create_hmr_runner: None,
create_coverage_collector: None,
node_ipc: None, node_ipc: None,
serve_port: None, serve_port: None,
serve_host: None, serve_host: None,
}, deno_version: crate::version::DENO_VERSION_INFO.deno,
metadata.otel_config, deno_user_agent: crate::version::DENO_VERSION_INFO.user_agent,
crate::args::NpmCachingStrategy::Lazy, otel_config: metadata.otel_config,
startup_snapshot: crate::js::deno_isolate_init(),
};
let lib_main_worker_factory = LibMainWorkerFactory::new(
Arc::new(BlobStore::default()),
code_cache.map(|c| c.as_code_cache()),
feature_checker,
fs,
None,
Box::new(module_loader_factory),
node_resolver.clone(),
create_npm_process_state_provider(&npm_resolver),
pkg_json_resolver,
root_cert_store_provider,
StorageKeyResolver::empty(),
sys.clone(),
lib_main_worker_options,
);
// todo(dsherret): use LibMainWorker directly here and don't use CliMainWorkerFactory
let cli_main_worker_options = CliMainWorkerOptions {
create_hmr_runner: None,
create_coverage_collector: None,
needs_test_modules: false,
default_npm_caching_strategy: crate::args::NpmCachingStrategy::Lazy,
};
let worker_factory = CliMainWorkerFactory::new(
lib_main_worker_factory,
None,
None,
node_resolver,
None,
npm_resolver,
sys,
cli_main_worker_options,
permissions,
); );
// Initialize v8 once from the main thread. // Initialize v8 once from the main thread.

View file

@ -17,6 +17,7 @@ use deno_core::url::Url;
use deno_core::FastString; use deno_core::FastString;
use deno_core::ModuleSourceCode; use deno_core::ModuleSourceCode;
use deno_core::ModuleType; use deno_core::ModuleType;
use deno_lib::standalone::virtual_fs::VirtualDirectoryEntries;
use deno_npm::resolution::SerializedNpmResolutionSnapshot; use deno_npm::resolution::SerializedNpmResolutionSnapshot;
use deno_npm::resolution::SerializedNpmResolutionSnapshotPackage; use deno_npm::resolution::SerializedNpmResolutionSnapshotPackage;
use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot; use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot;
@ -27,10 +28,7 @@ use indexmap::IndexMap;
use super::binary::Metadata; use super::binary::Metadata;
use super::virtual_fs::BuiltVfs; use super::virtual_fs::BuiltVfs;
use super::virtual_fs::FileSystemCaseSensitivity;
use super::virtual_fs::VfsBuilder; use super::virtual_fs::VfsBuilder;
use super::virtual_fs::VirtualDirectoryEntries;
use crate::standalone::virtual_fs::VirtualDirectory;
const MAGIC_BYTES: &[u8; 8] = b"d3n0l4nd"; const MAGIC_BYTES: &[u8; 8] = b"d3n0l4nd";

View file

@ -23,6 +23,17 @@ use deno_core::parking_lot::Mutex;
use deno_core::BufMutView; use deno_core::BufMutView;
use deno_core::BufView; use deno_core::BufView;
use deno_core::ResourceHandleFd; use deno_core::ResourceHandleFd;
use deno_lib::standalone::virtual_fs::FileSystemCaseSensitivity;
use deno_lib::standalone::virtual_fs::OffsetWithLength;
use deno_lib::standalone::virtual_fs::VfsEntry;
use deno_lib::standalone::virtual_fs::VfsEntryRef;
use deno_lib::standalone::virtual_fs::VfsFileSubDataKind;
use deno_lib::standalone::virtual_fs::VirtualDirectory;
use deno_lib::standalone::virtual_fs::VirtualDirectoryEntries;
use deno_lib::standalone::virtual_fs::VirtualFile;
use deno_lib::standalone::virtual_fs::VirtualSymlink;
use deno_lib::standalone::virtual_fs::VirtualSymlinkParts;
use deno_lib::standalone::virtual_fs::WindowsSystemRootablePath;
use deno_path_util::normalize_path; use deno_path_util::normalize_path;
use deno_path_util::strip_unc_prefix; use deno_path_util::strip_unc_prefix;
use deno_runtime::deno_fs::FsDirEntry; use deno_runtime::deno_fs::FsDirEntry;
@ -41,37 +52,6 @@ use crate::util::display::human_size;
use crate::util::display::DisplayTreeNode; use crate::util::display::DisplayTreeNode;
use crate::util::fs::canonicalize_path; use crate::util::fs::canonicalize_path;
#[derive(Debug, PartialEq, Eq)]
pub enum WindowsSystemRootablePath {
/// The root of the system above any drive letters.
WindowSystemRoot,
Path(PathBuf),
}
impl WindowsSystemRootablePath {
pub fn join(&self, name_component: &str) -> PathBuf {
// this method doesn't handle multiple components
debug_assert!(
!name_component.contains('\\'),
"Invalid component: {}",
name_component
);
debug_assert!(
!name_component.contains('/'),
"Invalid component: {}",
name_component
);
match self {
WindowsSystemRootablePath::WindowSystemRoot => {
// windows drive letter
PathBuf::from(&format!("{}\\", name_component))
}
WindowsSystemRootablePath::Path(path) => path.join(name_component),
}
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct BuiltVfs { pub struct BuiltVfs {
pub root_path: WindowsSystemRootablePath, pub root_path: WindowsSystemRootablePath,
@ -80,15 +60,6 @@ pub struct BuiltVfs {
pub files: Vec<Vec<u8>>, pub files: Vec<Vec<u8>>,
} }
#[derive(Debug, Copy, Clone)]
pub enum VfsFileSubDataKind {
/// Raw bytes of the file.
Raw,
/// Bytes to use for module loading. For example, for TypeScript
/// files this will be the transpiled JavaScript source.
ModuleGraph,
}
#[derive(Debug)] #[derive(Debug)]
pub struct VfsBuilder { pub struct VfsBuilder {
executable_root: VirtualDirectory, executable_root: VirtualDirectory,
@ -232,24 +203,21 @@ impl VfsBuilder {
continue; continue;
} }
let name = component.as_os_str().to_string_lossy(); let name = component.as_os_str().to_string_lossy();
let index = match current_dir let index = current_dir.entries.insert_or_modify(
.entries &name,
.binary_search(&name, self.case_sensitivity) self.case_sensitivity,
{ || {
Ok(index) => index,
Err(insert_index) => {
current_dir.entries.0.insert(
insert_index,
VfsEntry::Dir(VirtualDirectory { VfsEntry::Dir(VirtualDirectory {
name: name.to_string(), name: name.to_string(),
entries: Default::default(), entries: Default::default(),
}), })
},
|_| {
// ignore
},
); );
insert_index match current_dir.entries.get_mut_by_index(index) {
} Some(VfsEntry::Dir(dir)) => {
};
match &mut current_dir.entries.0[index] {
VfsEntry::Dir(dir) => {
current_dir = dir; current_dir = dir;
} }
_ => unreachable!(), _ => unreachable!(),
@ -325,7 +293,7 @@ impl VfsBuilder {
sub_data_kind: VfsFileSubDataKind, sub_data_kind: VfsFileSubDataKind,
) -> Result<(), AnyError> { ) -> Result<(), AnyError> {
log::debug!("Adding file '{}'", path.display()); log::debug!("Adding file '{}'", path.display());
let checksum = util::checksum::gen(&[&data]); let checksum = deno_lib::util::checksum::gen(&[&data]);
let case_sensitivity = self.case_sensitivity; let case_sensitivity = self.case_sensitivity;
let offset = if let Some(offset) = self.file_offsets.get(&checksum) { let offset = if let Some(offset) = self.file_offsets.get(&checksum) {
// duplicate file, reuse an old offset // duplicate file, reuse an old offset
@ -341,10 +309,17 @@ impl VfsBuilder {
offset, offset,
len: data.len() as u64, len: data.len() as u64,
}; };
match dir.entries.binary_search(&name, case_sensitivity) { dir.entries.insert_or_modify(
Ok(index) => { &name,
let entry = &mut dir.entries.0[index]; case_sensitivity,
match entry { || {
VfsEntry::File(VirtualFile {
name: name.to_string(),
offset: offset_and_len,
module_graph_offset: offset_and_len,
})
},
|entry| match entry {
VfsEntry::File(virtual_file) => match sub_data_kind { VfsEntry::File(virtual_file) => match sub_data_kind {
VfsFileSubDataKind::Raw => { VfsFileSubDataKind::Raw => {
virtual_file.offset = offset_and_len; virtual_file.offset = offset_and_len;
@ -354,19 +329,8 @@ impl VfsBuilder {
} }
}, },
VfsEntry::Dir(_) | VfsEntry::Symlink(_) => unreachable!(), VfsEntry::Dir(_) | VfsEntry::Symlink(_) => unreachable!(),
} },
}
Err(insert_index) => {
dir.entries.0.insert(
insert_index,
VfsEntry::File(VirtualFile {
name: name.to_string(),
offset: offset_and_len,
module_graph_offset: offset_and_len,
}),
); );
}
}
// new file, update the list of files // new file, update the list of files
if self.current_offset == offset { if self.current_offset == offset {
@ -406,18 +370,19 @@ impl VfsBuilder {
let target = normalize_path(path.parent().unwrap().join(&target)); let target = normalize_path(path.parent().unwrap().join(&target));
let dir = self.add_dir_raw(path.parent().unwrap()); let dir = self.add_dir_raw(path.parent().unwrap());
let name = path.file_name().unwrap().to_string_lossy(); let name = path.file_name().unwrap().to_string_lossy();
match dir.entries.binary_search(&name, case_sensitivity) { dir.entries.insert_or_modify(
Ok(_) => {} // previously inserted &name,
Err(insert_index) => { case_sensitivity,
dir.entries.0.insert( || {
insert_index,
VfsEntry::Symlink(VirtualSymlink { VfsEntry::Symlink(VirtualSymlink {
name: name.to_string(), name: name.to_string(),
dest_parts: VirtualSymlinkParts::from_path(&target), dest_parts: VirtualSymlinkParts::from_path(&target),
}), })
},
|_| {
// ignore previously inserted
},
); );
}
}
let target_metadata = let target_metadata =
std::fs::symlink_metadata(&target).with_context(|| { std::fs::symlink_metadata(&target).with_context(|| {
format!("Reading symlink target '{}'", target.display()) format!("Reading symlink target '{}'", target.display())
@ -448,16 +413,20 @@ impl VfsBuilder {
dir: &mut VirtualDirectory, dir: &mut VirtualDirectory,
parts: &[String], parts: &[String],
) { ) {
for entry in &mut dir.entries.0 { for entry in dir.entries.iter_mut() {
match entry { match entry {
VfsEntry::Dir(dir) => { VfsEntry::Dir(dir) => {
strip_prefix_from_symlinks(dir, parts); strip_prefix_from_symlinks(dir, parts);
} }
VfsEntry::File(_) => {} VfsEntry::File(_) => {}
VfsEntry::Symlink(symlink) => { VfsEntry::Symlink(symlink) => {
let old_parts = std::mem::take(&mut symlink.dest_parts.0); let parts = symlink
symlink.dest_parts.0 = .dest_parts
old_parts.into_iter().skip(parts.len()).collect(); .take_parts()
.into_iter()
.skip(parts.len())
.collect();
symlink.dest_parts.set_parts(parts);
} }
} }
} }
@ -476,13 +445,13 @@ impl VfsBuilder {
if self.min_root_dir.as_ref() == Some(&current_path) { if self.min_root_dir.as_ref() == Some(&current_path) {
break; break;
} }
match &current_dir.entries.0[0] { match current_dir.entries.iter().next().unwrap() {
VfsEntry::Dir(dir) => { VfsEntry::Dir(dir) => {
if dir.name == DENO_COMPILE_GLOBAL_NODE_MODULES_DIR_NAME { if dir.name == DENO_COMPILE_GLOBAL_NODE_MODULES_DIR_NAME {
// special directory we want to maintain // special directory we want to maintain
break; break;
} }
match current_dir.entries.0.remove(0) { match current_dir.entries.remove(0) {
VfsEntry::Dir(dir) => { VfsEntry::Dir(dir) => {
current_path = current_path =
WindowsSystemRootablePath::Path(current_path.join(&dir.name)); WindowsSystemRootablePath::Path(current_path.join(&dir.name));
@ -497,7 +466,7 @@ impl VfsBuilder {
if let WindowsSystemRootablePath::Path(path) = &current_path { if let WindowsSystemRootablePath::Path(path) = &current_path {
strip_prefix_from_symlinks( strip_prefix_from_symlinks(
&mut current_dir, &mut current_dir,
&VirtualSymlinkParts::from_path(path).0, VirtualSymlinkParts::from_path(path).parts(),
); );
} }
BuiltVfs { BuiltVfs {
@ -577,7 +546,7 @@ fn vfs_as_display_tree(
All(Size), All(Size),
Subset(Vec<DirEntryOutput<'a>>), Subset(Vec<DirEntryOutput<'a>>),
File(Size), File(Size),
Symlink(&'a [String]), Symlink(&'a VirtualSymlinkParts),
} }
impl<'a> EntryOutput<'a> { impl<'a> EntryOutput<'a> {
@ -626,7 +595,7 @@ fn vfs_as_display_tree(
format!("{} ({})", name, format_size(*size)) format!("{} ({})", name, format_size(*size))
} }
EntryOutput::Symlink(parts) => { EntryOutput::Symlink(parts) => {
format!("{} --> {}", name, parts.join("/")) format!("{} --> {}", name, parts.display())
} }
}, },
children: match self { children: match self {
@ -769,7 +738,7 @@ fn vfs_as_display_tree(
EntryOutput::File(file_size(file, seen_offsets)) EntryOutput::File(file_size(file, seen_offsets))
} }
VfsEntry::Symlink(virtual_symlink) => { VfsEntry::Symlink(virtual_symlink) => {
EntryOutput::Symlink(&virtual_symlink.dest_parts.0) EntryOutput::Symlink(&virtual_symlink.dest_parts)
} }
}, },
}) })
@ -806,7 +775,7 @@ fn vfs_as_display_tree(
} }
VfsEntry::File(file) => EntryOutput::File(file_size(file, seen_offsets)), VfsEntry::File(file) => EntryOutput::File(file_size(file, seen_offsets)),
VfsEntry::Symlink(virtual_symlink) => { VfsEntry::Symlink(virtual_symlink) => {
EntryOutput::Symlink(&virtual_symlink.dest_parts.0) EntryOutput::Symlink(&virtual_symlink.dest_parts)
} }
} }
} }
@ -872,226 +841,6 @@ fn vfs_as_display_tree(
} }
} }
#[derive(Debug)]
enum VfsEntryRef<'a> {
Dir(&'a VirtualDirectory),
File(&'a VirtualFile),
Symlink(&'a VirtualSymlink),
}
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 {
Self::Dir(dir) => &dir.name,
Self::File(file) => &file.name,
Self::Symlink(symlink) => &symlink.name,
}
}
}
// todo(dsherret): we should store this more efficiently in the binary
#[derive(Debug, Serialize, Deserialize)]
pub enum VfsEntry {
Dir(VirtualDirectory),
File(VirtualFile),
Symlink(VirtualSymlink),
}
impl VfsEntry {
pub fn name(&self) -> &str {
match self {
Self::Dir(dir) => &dir.name,
Self::File(file) => &file.name,
Self::Symlink(symlink) => &symlink.name,
}
}
fn as_ref(&self) -> VfsEntryRef {
match self {
VfsEntry::Dir(dir) => VfsEntryRef::Dir(dir),
VfsEntry::File(file) => VfsEntryRef::File(file),
VfsEntry::Symlink(symlink) => VfsEntryRef::Symlink(symlink),
}
}
}
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub enum FileSystemCaseSensitivity {
#[serde(rename = "s")]
Sensitive,
#[serde(rename = "i")]
Insensitive,
}
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct VirtualDirectoryEntries(Vec<VfsEntry>);
impl VirtualDirectoryEntries {
pub fn new(mut entries: Vec<VfsEntry>) -> Self {
// needs to be sorted by name
entries.sort_by(|a, b| a.name().cmp(b.name()));
Self(entries)
}
pub fn take_inner(&mut self) -> Vec<VfsEntry> {
std::mem::take(&mut self.0)
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn get_by_name(
&self,
name: &str,
case_sensitivity: FileSystemCaseSensitivity,
) -> Option<&VfsEntry> {
self
.binary_search(name, case_sensitivity)
.ok()
.map(|index| &self.0[index])
}
pub fn get_mut_by_name(
&mut self,
name: &str,
case_sensitivity: FileSystemCaseSensitivity,
) -> Option<&mut VfsEntry> {
self
.binary_search(name, case_sensitivity)
.ok()
.map(|index| &mut self.0[index])
}
pub fn binary_search(
&self,
name: &str,
case_sensitivity: FileSystemCaseSensitivity,
) -> Result<usize, usize> {
match case_sensitivity {
FileSystemCaseSensitivity::Sensitive => {
self.0.binary_search_by(|e| e.name().cmp(name))
}
FileSystemCaseSensitivity::Insensitive => self.0.binary_search_by(|e| {
e.name()
.chars()
.zip(name.chars())
.map(|(a, b)| a.to_ascii_lowercase().cmp(&b.to_ascii_lowercase()))
.find(|&ord| ord != Ordering::Equal)
.unwrap_or_else(|| e.name().len().cmp(&name.len()))
}),
}
}
pub fn insert(
&mut self,
entry: VfsEntry,
case_sensitivity: FileSystemCaseSensitivity,
) {
match self.binary_search(entry.name(), case_sensitivity) {
Ok(index) => {
self.0[index] = entry;
}
Err(insert_index) => {
self.0.insert(insert_index, entry);
}
}
}
pub fn remove(&mut self, index: usize) -> VfsEntry {
self.0.remove(index)
}
pub fn iter(&self) -> std::slice::Iter<'_, VfsEntry> {
self.0.iter()
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct VirtualDirectory {
#[serde(rename = "n")]
pub name: String,
// should be sorted by name
#[serde(rename = "e")]
pub entries: VirtualDirectoryEntries,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct OffsetWithLength {
#[serde(rename = "o")]
pub offset: u64,
#[serde(rename = "l")]
pub len: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VirtualFile {
#[serde(rename = "n")]
pub name: String,
#[serde(rename = "o")]
pub offset: OffsetWithLength,
/// Offset file to use for module loading when it differs from the
/// raw file. Often this will be the same offset as above for data
/// such as JavaScript files, but for TypeScript files the `offset`
/// will be the original raw bytes when included as an asset and this
/// offset will be to the transpiled JavaScript source.
#[serde(rename = "m")]
pub module_graph_offset: OffsetWithLength,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct VirtualSymlinkParts(Vec<String>);
impl VirtualSymlinkParts {
pub fn from_path(path: &Path) -> Self {
Self(
path
.components()
.filter(|c| !matches!(c, std::path::Component::RootDir))
.map(|c| c.as_os_str().to_string_lossy().to_string())
.collect(),
)
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct VirtualSymlink {
#[serde(rename = "n")]
pub name: String,
#[serde(rename = "p")]
pub dest_parts: VirtualSymlinkParts,
}
impl VirtualSymlink {
pub fn resolve_dest_from_root(&self, root: &Path) -> PathBuf {
let mut dest = root.to_path_buf();
for part in &self.dest_parts.0 {
dest.push(part);
}
dest
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct VfsRoot { pub struct VfsRoot {
pub dir: VirtualDirectory, pub dir: VirtualDirectory,
@ -1430,6 +1179,21 @@ pub struct FileBackedVfsMetadata {
} }
impl FileBackedVfsMetadata { impl FileBackedVfsMetadata {
pub fn from_vfs_entry_ref(vfs_entry: VfsEntryRef) -> Self {
FileBackedVfsMetadata {
file_type: match vfs_entry {
VfsEntryRef::Dir(_) => sys_traits::FileType::Dir,
VfsEntryRef::File(_) => sys_traits::FileType::File,
VfsEntryRef::Symlink(_) => sys_traits::FileType::Symlink,
},
name: vfs_entry.name().to_string(),
len: match vfs_entry {
VfsEntryRef::Dir(_) => 0,
VfsEntryRef::File(file) => file.offset.len,
VfsEntryRef::Symlink(_) => 0,
},
}
}
pub fn as_fs_stat(&self) -> FsStat { pub fn as_fs_stat(&self) -> FsStat {
FsStat { FsStat {
is_directory: self.file_type == sys_traits::FileType::Dir, is_directory: self.file_type == sys_traits::FileType::Dir,
@ -1521,7 +1285,7 @@ impl FileBackedVfs {
let path = path.to_path_buf(); let path = path.to_path_buf();
Ok(dir.entries.iter().map(move |entry| FileBackedVfsDirEntry { Ok(dir.entries.iter().map(move |entry| FileBackedVfsDirEntry {
parent_path: path.to_path_buf(), parent_path: path.to_path_buf(),
metadata: entry.as_ref().as_metadata(), metadata: FileBackedVfsMetadata::from_vfs_entry_ref(entry.as_ref()),
})) }))
} }
@ -1544,12 +1308,12 @@ impl FileBackedVfs {
let (_, entry) = self let (_, entry) = self
.fs_root .fs_root
.find_entry_no_follow(path, self.case_sensitivity)?; .find_entry_no_follow(path, self.case_sensitivity)?;
Ok(entry.as_metadata()) Ok(FileBackedVfsMetadata::from_vfs_entry_ref(entry))
} }
pub fn stat(&self, path: &Path) -> std::io::Result<FileBackedVfsMetadata> { pub fn stat(&self, path: &Path) -> std::io::Result<FileBackedVfsMetadata> {
let (_, entry) = self.fs_root.find_entry(path, self.case_sensitivity)?; let (_, entry) = self.fs_root.find_entry(path, self.case_sensitivity)?;
Ok(entry.as_metadata()) Ok(FileBackedVfsMetadata::from_vfs_entry_ref(entry))
} }
pub fn canonicalize(&self, path: &Path) -> std::io::Result<PathBuf> { pub fn canonicalize(&self, path: &Path) -> std::io::Result<PathBuf> {

View file

@ -29,6 +29,8 @@ pub enum CliSys {
DenoCompile(DenoCompileFileSystem), DenoCompile(DenoCompileFileSystem),
} }
impl deno_lib::sys::DenoLibSys for CliSys {}
impl Default for CliSys { impl Default for CliSys {
fn default() -> Self { fn default() -> Self {
Self::Real(sys_traits::impls::RealSys) Self::Real(sys_traits::impls::RealSys)

View file

@ -25,9 +25,8 @@ use tokio::task::LocalSet;
use tokio_util::sync::CancellationToken; use tokio_util::sync::CancellationToken;
use crate::node::CliNodeResolver; use crate::node::CliNodeResolver;
use crate::npm::CliManagedNpmResolver;
use crate::npm::CliNpmResolver; use crate::npm::CliNpmResolver;
use crate::npm::InnerCliNpmResolverRef;
use crate::npm::ManagedCliNpmResolver;
pub fn get_script_with_args(script: &str, argv: &[String]) -> String { pub fn get_script_with_args(script: &str, argv: &[String]) -> String {
let additional_args = argv let additional_args = argv
@ -414,15 +413,15 @@ impl ShellCommand for NodeModulesFileRunCommand {
} }
pub fn resolve_custom_commands( pub fn resolve_custom_commands(
npm_resolver: &dyn CliNpmResolver, npm_resolver: &CliNpmResolver,
node_resolver: &CliNodeResolver, node_resolver: &CliNodeResolver,
) -> Result<HashMap<String, Rc<dyn ShellCommand>>, AnyError> { ) -> Result<HashMap<String, Rc<dyn ShellCommand>>, AnyError> {
let mut commands = match npm_resolver.as_inner() { let mut commands = match npm_resolver {
InnerCliNpmResolverRef::Byonm(npm_resolver) => { CliNpmResolver::Byonm(npm_resolver) => {
let node_modules_dir = npm_resolver.root_node_modules_path().unwrap(); let node_modules_dir = npm_resolver.root_node_modules_path().unwrap();
resolve_npm_commands_from_bin_dir(node_modules_dir) resolve_npm_commands_from_bin_dir(node_modules_dir)
} }
InnerCliNpmResolverRef::Managed(npm_resolver) => { CliNpmResolver::Managed(npm_resolver) => {
resolve_managed_npm_commands(npm_resolver, node_resolver)? resolve_managed_npm_commands(npm_resolver, node_resolver)?
} }
}; };
@ -521,13 +520,12 @@ fn resolve_execution_path_from_npx_shim(
} }
fn resolve_managed_npm_commands( fn resolve_managed_npm_commands(
npm_resolver: &ManagedCliNpmResolver, npm_resolver: &CliManagedNpmResolver,
node_resolver: &CliNodeResolver, node_resolver: &CliNodeResolver,
) -> Result<HashMap<String, Rc<dyn ShellCommand>>, AnyError> { ) -> Result<HashMap<String, Rc<dyn ShellCommand>>, AnyError> {
let mut result = HashMap::new(); let mut result = HashMap::new();
let snapshot = npm_resolver.snapshot(); for id in npm_resolver.resolution().top_level_packages() {
for id in snapshot.top_level_packages() { let package_folder = npm_resolver.resolve_pkg_folder_from_pkg_id(&id)?;
let package_folder = npm_resolver.resolve_pkg_folder_from_pkg_id(id)?;
let bin_commands = let bin_commands =
node_resolver.resolve_binary_commands(&package_folder)?; node_resolver.resolve_binary_commands(&package_folder)?;
for bin_command in bin_commands { for bin_command in bin_commands {
@ -598,7 +596,7 @@ async fn listen_ctrl_c(kill_signal: KillSignal) {
#[cfg(unix)] #[cfg(unix)]
async fn listen_and_forward_all_signals(kill_signal: KillSignal) { async fn listen_and_forward_all_signals(kill_signal: KillSignal) {
use deno_core::futures::FutureExt; use deno_core::futures::FutureExt;
use deno_runtime::signal::SIGNAL_NUMS; use deno_runtime::deno_os::signal::SIGNAL_NUMS;
// listen and forward every signal we support // listen and forward every signal we support
let mut futures = Vec::with_capacity(SIGNAL_NUMS.len()); let mut futures = Vec::with_capacity(SIGNAL_NUMS.len());

View file

@ -112,7 +112,7 @@ pub struct TypeChecker {
module_graph_builder: Arc<ModuleGraphBuilder>, module_graph_builder: Arc<ModuleGraphBuilder>,
npm_installer: Option<Arc<NpmInstaller>>, npm_installer: Option<Arc<NpmInstaller>>,
node_resolver: Arc<CliNodeResolver>, node_resolver: Arc<CliNodeResolver>,
npm_resolver: Arc<dyn CliNpmResolver>, npm_resolver: CliNpmResolver,
sys: CliSys, sys: CliSys,
} }
@ -146,7 +146,7 @@ impl TypeChecker {
module_graph_builder: Arc<ModuleGraphBuilder>, module_graph_builder: Arc<ModuleGraphBuilder>,
node_resolver: Arc<CliNodeResolver>, node_resolver: Arc<CliNodeResolver>,
npm_installer: Option<Arc<NpmInstaller>>, npm_installer: Option<Arc<NpmInstaller>>,
npm_resolver: Arc<dyn CliNpmResolver>, npm_resolver: CliNpmResolver,
sys: CliSys, sys: CliSys,
) -> Self { ) -> Self {
Self { Self {
@ -189,6 +189,29 @@ impl TypeChecker {
mut graph: ModuleGraph, mut graph: ModuleGraph,
options: CheckOptions, options: CheckOptions,
) -> Result<(Arc<ModuleGraph>, Diagnostics), CheckError> { ) -> Result<(Arc<ModuleGraph>, Diagnostics), CheckError> {
fn check_state_hash(resolver: &CliNpmResolver) -> Option<u64> {
match resolver {
CliNpmResolver::Byonm(_) => {
// not feasible and probably slower to compute
None
}
CliNpmResolver::Managed(resolver) => {
// we should probably go further and check all the individual npm packages
let mut package_reqs = resolver.resolution().package_reqs();
package_reqs.sort_by(|a, b| a.0.cmp(&b.0)); // determinism
let mut hasher = FastInsecureHasher::new_without_deno_version();
// ensure the cache gets busted when turning nodeModulesDir on or off
// as this could cause changes in resolution
hasher.write_hashable(resolver.root_node_modules_path().is_some());
for (pkg_req, pkg_nv) in package_reqs {
hasher.write_hashable(&pkg_req);
hasher.write_hashable(&pkg_nv);
}
Some(hasher.finish())
}
}
}
if !options.type_check_mode.is_true() || graph.roots.is_empty() { if !options.type_check_mode.is_true() || graph.roots.is_empty() {
return Ok((graph.into(), Default::default())); return Ok((graph.into(), Default::default()));
} }
@ -240,7 +263,7 @@ impl TypeChecker {
&self.sys, &self.sys,
&graph, &graph,
check_js, check_js,
self.npm_resolver.check_state_hash(), check_state_hash(&self.npm_resolver),
type_check_mode, type_check_mode,
&ts_config, &ts_config,
); );

View file

@ -4,8 +4,8 @@ use std::path::Path;
use deno_core::anyhow::Context; use deno_core::anyhow::Context;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_lib::cache::DenoDir;
use crate::cache::DenoDir;
use crate::colors; use crate::colors;
use crate::display; use crate::display;
use crate::sys::CliSys; use crate::sys::CliSys;

View file

@ -22,6 +22,7 @@ use deno_core::serde_json;
use deno_core::sourcemap::SourceMap; use deno_core::sourcemap::SourceMap;
use deno_core::url::Url; use deno_core::url::Url;
use deno_core::LocalInspectorSession; use deno_core::LocalInspectorSession;
use deno_resolver::npm::DenoInNpmPackageChecker;
use node_resolver::InNpmPackageChecker; use node_resolver::InNpmPackageChecker;
use regex::Regex; use regex::Regex;
use text_lines::TextLines; use text_lines::TextLines;
@ -464,7 +465,7 @@ fn filter_coverages(
coverages: Vec<cdp::ScriptCoverage>, coverages: Vec<cdp::ScriptCoverage>,
include: Vec<String>, include: Vec<String>,
exclude: Vec<String>, exclude: Vec<String>,
in_npm_pkg_checker: &dyn InNpmPackageChecker, in_npm_pkg_checker: &DenoInNpmPackageChecker,
) -> Vec<cdp::ScriptCoverage> { ) -> Vec<cdp::ScriptCoverage> {
let include: Vec<Regex> = let include: Vec<Regex> =
include.iter().map(|e| Regex::new(e).unwrap()).collect(); include.iter().map(|e| Regex::new(e).unwrap()).collect();
@ -532,7 +533,7 @@ pub fn cover_files(
script_coverages, script_coverages,
coverage_flags.include, coverage_flags.include,
coverage_flags.exclude, coverage_flags.exclude,
in_npm_pkg_checker.as_ref(), in_npm_pkg_checker,
); );
if script_coverages.is_empty() { if script_coverages.is_empty() {
return Err(anyhow!("No covered files included in the report")); return Err(anyhow!("No covered files included in the report"));

View file

@ -18,6 +18,7 @@ use deno_graph::Module;
use deno_graph::ModuleError; use deno_graph::ModuleError;
use deno_graph::ModuleGraph; use deno_graph::ModuleGraph;
use deno_graph::Resolution; use deno_graph::Resolution;
use deno_lib::util::checksum;
use deno_npm::npm_rc::ResolvedNpmRc; use deno_npm::npm_rc::ResolvedNpmRc;
use deno_npm::resolution::NpmResolutionSnapshot; use deno_npm::resolution::NpmResolutionSnapshot;
use deno_npm::NpmPackageId; use deno_npm::NpmPackageId;
@ -32,9 +33,7 @@ use crate::args::InfoFlags;
use crate::display; use crate::display;
use crate::factory::CliFactory; use crate::factory::CliFactory;
use crate::graph_util::graph_exit_integrity_errors; use crate::graph_util::graph_exit_integrity_errors;
use crate::npm::CliNpmResolver; use crate::npm::CliManagedNpmResolver;
use crate::npm::ManagedCliNpmResolver;
use crate::util::checksum;
use crate::util::display::DisplayTreeNode; use crate::util::display::DisplayTreeNode;
const JSON_SCHEMA_VERSION: u8 = 1; const JSON_SCHEMA_VERSION: u8 = 1;
@ -138,6 +137,10 @@ pub async fn info(
lockfile.write_if_changed()?; lockfile.write_if_changed()?;
} }
let maybe_npm_info = npm_resolver
.as_managed()
.map(|r| (r, r.resolution().snapshot()));
if info_flags.json { if info_flags.json {
let mut json_graph = serde_json::json!(graph); let mut json_graph = serde_json::json!(graph);
if let Some(output) = json_graph.as_object_mut() { if let Some(output) = json_graph.as_object_mut() {
@ -148,11 +151,19 @@ pub async fn info(
); );
} }
add_npm_packages_to_json(&mut json_graph, npm_resolver.as_ref(), npmrc); add_npm_packages_to_json(
&mut json_graph,
maybe_npm_info.as_ref().map(|(_, s)| s),
npmrc,
);
display::write_json_to_stdout(&json_graph)?; display::write_json_to_stdout(&json_graph)?;
} else { } else {
let mut output = String::new(); let mut output = String::new();
GraphDisplayContext::write(&graph, npm_resolver.as_ref(), &mut output)?; GraphDisplayContext::write(
&graph,
maybe_npm_info.as_ref().map(|(r, s)| (*r, s)),
&mut output,
)?;
display::write_to_stdout_ignore_sigpipe(output.as_bytes())?; display::write_to_stdout_ignore_sigpipe(output.as_bytes())?;
} }
} else { } else {
@ -180,7 +191,7 @@ fn print_cache_info(
let registry_cache = dir.registries_folder_path(); let registry_cache = dir.registries_folder_path();
let mut origin_dir = dir.origin_data_folder_path(); let mut origin_dir = dir.origin_data_folder_path();
let deno_dir = dir.root_path_for_display().to_string(); let deno_dir = dir.root_path_for_display().to_string();
let web_cache_dir = crate::worker::get_cache_storage_dir(); let web_cache_dir = deno_lib::worker::get_cache_storage_dir();
if let Some(location) = &location { if let Some(location) = &location {
origin_dir = origin_dir =
@ -251,15 +262,14 @@ fn print_cache_info(
fn add_npm_packages_to_json( fn add_npm_packages_to_json(
json: &mut serde_json::Value, json: &mut serde_json::Value,
npm_resolver: &dyn CliNpmResolver, npm_snapshot: Option<&NpmResolutionSnapshot>,
npmrc: &ResolvedNpmRc, npmrc: &ResolvedNpmRc,
) { ) {
let Some(npm_resolver) = npm_resolver.as_managed() else { let Some(npm_snapshot) = npm_snapshot else {
return; // does not include byonm to deno info's output return; // does not include byonm to deno info's output
}; };
// ideally deno_graph could handle this, but for now we just modify the json here // ideally deno_graph could handle this, but for now we just modify the json here
let snapshot = npm_resolver.snapshot();
let json = json.as_object_mut().unwrap(); let json = json.as_object_mut().unwrap();
let modules = json.get_mut("modules").and_then(|m| m.as_array_mut()); let modules = json.get_mut("modules").and_then(|m| m.as_array_mut());
if let Some(modules) = modules { if let Some(modules) = modules {
@ -273,7 +283,7 @@ fn add_npm_packages_to_json(
.and_then(|k| k.as_str()) .and_then(|k| k.as_str())
.and_then(|specifier| NpmPackageNvReference::from_str(specifier).ok()) .and_then(|specifier| NpmPackageNvReference::from_str(specifier).ok())
.and_then(|package_ref| { .and_then(|package_ref| {
snapshot npm_snapshot
.resolve_package_from_deno_module(package_ref.nv()) .resolve_package_from_deno_module(package_ref.nv())
.ok() .ok()
}); });
@ -295,7 +305,8 @@ fn add_npm_packages_to_json(
if let Some(specifier) = dep.get("specifier").and_then(|s| s.as_str()) if let Some(specifier) = dep.get("specifier").and_then(|s| s.as_str())
{ {
if let Ok(npm_ref) = NpmPackageReqReference::from_str(specifier) { if let Ok(npm_ref) = NpmPackageReqReference::from_str(specifier) {
if let Ok(pkg) = snapshot.resolve_pkg_from_pkg_req(npm_ref.req()) if let Ok(pkg) =
npm_snapshot.resolve_pkg_from_pkg_req(npm_ref.req())
{ {
dep.insert( dep.insert(
"npmPackage".to_string(), "npmPackage".to_string(),
@ -321,8 +332,9 @@ fn add_npm_packages_to_json(
} }
} }
let mut sorted_packages = let mut sorted_packages = npm_snapshot
snapshot.all_packages_for_every_system().collect::<Vec<_>>(); .all_packages_for_every_system()
.collect::<Vec<_>>();
sorted_packages.sort_by(|a, b| a.id.cmp(&b.id)); sorted_packages.sort_by(|a, b| a.id.cmp(&b.id));
let mut json_packages = serde_json::Map::with_capacity(sorted_packages.len()); let mut json_packages = serde_json::Map::with_capacity(sorted_packages.len());
for pkg in sorted_packages { for pkg in sorted_packages {
@ -356,7 +368,7 @@ struct NpmInfo {
impl NpmInfo { impl NpmInfo {
pub fn build<'a>( pub fn build<'a>(
graph: &'a ModuleGraph, graph: &'a ModuleGraph,
npm_resolver: &'a ManagedCliNpmResolver, npm_resolver: &'a CliManagedNpmResolver,
npm_snapshot: &'a NpmResolutionSnapshot, npm_snapshot: &'a NpmResolutionSnapshot,
) -> Self { ) -> Self {
let mut info = NpmInfo::default(); let mut info = NpmInfo::default();
@ -382,7 +394,7 @@ impl NpmInfo {
fn fill_package_info<'a>( fn fill_package_info<'a>(
&mut self, &mut self,
package: &NpmResolutionPackage, package: &NpmResolutionPackage,
npm_resolver: &'a ManagedCliNpmResolver, npm_resolver: &'a CliManagedNpmResolver,
npm_snapshot: &'a NpmResolutionSnapshot, npm_snapshot: &'a NpmResolutionSnapshot,
) { ) {
self.packages.insert(package.id.clone(), package.clone()); self.packages.insert(package.id.clone(), package.clone());
@ -419,13 +431,15 @@ struct GraphDisplayContext<'a> {
impl<'a> GraphDisplayContext<'a> { impl<'a> GraphDisplayContext<'a> {
pub fn write<TWrite: Write>( pub fn write<TWrite: Write>(
graph: &'a ModuleGraph, graph: &'a ModuleGraph,
npm_resolver: &'a dyn CliNpmResolver, managed_npm_info: Option<(
&'a CliManagedNpmResolver,
&'a NpmResolutionSnapshot,
)>,
writer: &mut TWrite, writer: &mut TWrite,
) -> Result<(), AnyError> { ) -> Result<(), AnyError> {
let npm_info = match npm_resolver.as_managed() { let npm_info = match managed_npm_info {
Some(npm_resolver) => { Some((npm_resolver, npm_snapshot)) => {
let npm_snapshot = npm_resolver.snapshot(); NpmInfo::build(graph, npm_resolver, npm_snapshot)
NpmInfo::build(graph, npm_resolver, &npm_snapshot)
} }
None => NpmInfo::default(), None => NpmInfo::default(),
}; };

View file

@ -451,7 +451,7 @@ pub struct DepManager {
// TODO(nathanwhit): probably shouldn't be pub // TODO(nathanwhit): probably shouldn't be pub
pub(crate) jsr_fetch_resolver: Arc<JsrFetchResolver>, pub(crate) jsr_fetch_resolver: Arc<JsrFetchResolver>,
pub(crate) npm_fetch_resolver: Arc<NpmFetchResolver>, pub(crate) npm_fetch_resolver: Arc<NpmFetchResolver>,
npm_resolver: Arc<dyn CliNpmResolver>, npm_resolver: CliNpmResolver,
npm_installer: Arc<NpmInstaller>, npm_installer: Arc<NpmInstaller>,
permissions_container: PermissionsContainer, permissions_container: PermissionsContainer,
main_module_graph_container: Arc<MainModuleGraphContainer>, main_module_graph_container: Arc<MainModuleGraphContainer>,
@ -463,7 +463,7 @@ pub struct DepManagerArgs {
pub jsr_fetch_resolver: Arc<JsrFetchResolver>, pub jsr_fetch_resolver: Arc<JsrFetchResolver>,
pub npm_fetch_resolver: Arc<NpmFetchResolver>, pub npm_fetch_resolver: Arc<NpmFetchResolver>,
pub npm_installer: Arc<NpmInstaller>, pub npm_installer: Arc<NpmInstaller>,
pub npm_resolver: Arc<dyn CliNpmResolver>, pub npm_resolver: CliNpmResolver,
pub permissions_container: PermissionsContainer, pub permissions_container: PermissionsContainer,
pub main_module_graph_container: Arc<MainModuleGraphContainer>, pub main_module_graph_container: Arc<MainModuleGraphContainer>,
pub lockfile: Option<Arc<CliLockfile>>, pub lockfile: Option<Arc<CliLockfile>>,
@ -551,9 +551,10 @@ impl DepManager {
let npm_resolver = self.npm_resolver.as_managed().unwrap(); let npm_resolver = self.npm_resolver.as_managed().unwrap();
if self.deps.iter().all(|dep| match dep.kind { if self.deps.iter().all(|dep| match dep.kind {
DepKind::Npm => { DepKind::Npm => npm_resolver
npm_resolver.resolve_pkg_id_from_pkg_req(&dep.req).is_ok() .resolution()
} .resolve_pkg_id_from_pkg_req(&dep.req)
.is_ok(),
DepKind::Jsr => graph.packages.mappings().contains_key(&dep.req), DepKind::Jsr => graph.packages.mappings().contains_key(&dep.req),
}) { }) {
self.dependencies_resolved.raise(); self.dependencies_resolved.raise();
@ -630,7 +631,12 @@ impl DepManager {
let graph = self.main_module_graph_container.graph(); let graph = self.main_module_graph_container.graph();
let mut resolved = Vec::with_capacity(self.deps.len()); let mut resolved = Vec::with_capacity(self.deps.len());
let snapshot = self.npm_resolver.as_managed().unwrap().snapshot(); let snapshot = self
.npm_resolver
.as_managed()
.unwrap()
.resolution()
.snapshot();
let resolved_npm = snapshot.package_reqs(); let resolved_npm = snapshot.package_reqs();
let resolved_jsr = graph.packages.mappings(); let resolved_jsr = graph.packages.mappings();
for dep in &self.deps { for dep in &self.deps {

View file

@ -43,7 +43,8 @@ pub async fn serve(
maybe_npm_install(&factory).await?; maybe_npm_install(&factory).await?;
let worker_factory = factory.create_cli_main_worker_factory().await?; let worker_factory =
Arc::new(factory.create_cli_main_worker_factory().await?);
let hmr = serve_flags let hmr = serve_flags
.watch .watch
.map(|watch_flags| watch_flags.hmr) .map(|watch_flags| watch_flags.hmr)
@ -58,7 +59,7 @@ pub async fn serve(
} }
async fn do_serve( async fn do_serve(
worker_factory: CliMainWorkerFactory, worker_factory: Arc<CliMainWorkerFactory>,
main_module: ModuleSpecifier, main_module: ModuleSpecifier,
worker_count: Option<usize>, worker_count: Option<usize>,
hmr: bool, hmr: bool,
@ -116,7 +117,7 @@ async fn do_serve(
async fn run_worker( async fn run_worker(
worker_count: usize, worker_count: usize,
worker_factory: CliMainWorkerFactory, worker_factory: Arc<CliMainWorkerFactory>,
main_module: ModuleSpecifier, main_module: ModuleSpecifier,
hmr: bool, hmr: bool,
) -> Result<i32, AnyError> { ) -> Result<i32, AnyError> {
@ -164,7 +165,8 @@ async fn serve_with_watch(
maybe_npm_install(&factory).await?; maybe_npm_install(&factory).await?;
let _ = watcher_communicator.watch_paths(cli_options.watch_paths()); let _ = watcher_communicator.watch_paths(cli_options.watch_paths());
let worker_factory = factory.create_cli_main_worker_factory().await?; let worker_factory =
Arc::new(factory.create_cli_main_worker_factory().await?);
do_serve(worker_factory, main_module.clone(), worker_count, hmr) do_serve(worker_factory, main_module.clone(), worker_count, hmr)
.await?; .await?;

View file

@ -220,7 +220,7 @@ pub async fn execute_script(
let task_runner = TaskRunner { let task_runner = TaskRunner {
task_flags: &task_flags, task_flags: &task_flags,
npm_installer: npm_installer.map(|n| n.as_ref()), npm_installer: npm_installer.map(|n| n.as_ref()),
npm_resolver: npm_resolver.as_ref(), npm_resolver,
node_resolver: node_resolver.as_ref(), node_resolver: node_resolver.as_ref(),
env_vars, env_vars,
cli_options, cli_options,
@ -271,7 +271,7 @@ struct RunSingleOptions<'a> {
struct TaskRunner<'a> { struct TaskRunner<'a> {
task_flags: &'a TaskFlags, task_flags: &'a TaskFlags,
npm_installer: Option<&'a NpmInstaller>, npm_installer: Option<&'a NpmInstaller>,
npm_resolver: &'a dyn CliNpmResolver, npm_resolver: &'a CliNpmResolver,
node_resolver: &'a CliNodeResolver, node_resolver: &'a CliNodeResolver,
env_vars: HashMap<String, String>, env_vars: HashMap<String, String>,
cli_options: &'a CliOptions, cli_options: &'a CliOptions,

View file

@ -28,6 +28,8 @@ use deno_graph::GraphKind;
use deno_graph::Module; use deno_graph::Module;
use deno_graph::ModuleGraph; use deno_graph::ModuleGraph;
use deno_graph::ResolutionResolved; use deno_graph::ResolutionResolved;
use deno_lib::util::checksum;
use deno_lib::worker::create_isolate_create_params;
use deno_resolver::npm::managed::ResolvePkgFolderFromDenoModuleError; use deno_resolver::npm::managed::ResolvePkgFolderFromDenoModuleError;
use deno_resolver::npm::ResolvePkgFolderFromDenoReqError; use deno_resolver::npm::ResolvePkgFolderFromDenoReqError;
use deno_semver::npm::NpmPackageReqReference; use deno_semver::npm::NpmPackageReqReference;
@ -46,11 +48,9 @@ use crate::cache::FastInsecureHasher;
use crate::cache::ModuleInfoCache; use crate::cache::ModuleInfoCache;
use crate::node::CliNodeResolver; use crate::node::CliNodeResolver;
use crate::npm::CliNpmResolver; use crate::npm::CliNpmResolver;
use crate::resolver::CjsTracker; use crate::resolver::CliCjsTracker;
use crate::sys::CliSys; use crate::sys::CliSys;
use crate::util::checksum;
use crate::util::path::mapped_specifier_for_tsc; use crate::util::path::mapped_specifier_for_tsc;
use crate::worker::create_isolate_create_params;
mod diagnostics; mod diagnostics;
@ -300,13 +300,13 @@ pub fn into_specifier_and_media_type(
#[derive(Debug)] #[derive(Debug)]
pub struct TypeCheckingCjsTracker { pub struct TypeCheckingCjsTracker {
cjs_tracker: Arc<CjsTracker>, cjs_tracker: Arc<CliCjsTracker>,
module_info_cache: Arc<ModuleInfoCache>, module_info_cache: Arc<ModuleInfoCache>,
} }
impl TypeCheckingCjsTracker { impl TypeCheckingCjsTracker {
pub fn new( pub fn new(
cjs_tracker: Arc<CjsTracker>, cjs_tracker: Arc<CliCjsTracker>,
module_info_cache: Arc<ModuleInfoCache>, module_info_cache: Arc<ModuleInfoCache>,
) -> Self { ) -> Self {
Self { Self {
@ -358,7 +358,7 @@ impl TypeCheckingCjsTracker {
pub struct RequestNpmState { pub struct RequestNpmState {
pub cjs_tracker: Arc<TypeCheckingCjsTracker>, pub cjs_tracker: Arc<TypeCheckingCjsTracker>,
pub node_resolver: Arc<CliNodeResolver>, pub node_resolver: Arc<CliNodeResolver>,
pub npm_resolver: Arc<dyn CliNpmResolver>, pub npm_resolver: CliNpmResolver,
} }
/// A structure representing a request to be sent to the tsc runtime. /// A structure representing a request to be sent to the tsc runtime.

View file

@ -25,6 +25,7 @@ use notify::Watcher;
use tokio::select; use tokio::select;
use tokio::sync::broadcast::error::RecvError; use tokio::sync::broadcast::error::RecvError;
use tokio::sync::mpsc; use tokio::sync::mpsc;
use tokio::sync::mpsc::error::SendError;
use tokio::sync::mpsc::UnboundedReceiver; use tokio::sync::mpsc::UnboundedReceiver;
use tokio::time::sleep; use tokio::time::sleep;
@ -141,36 +142,60 @@ fn create_print_after_restart_fn(clear_screen: bool) -> impl Fn() {
} }
} }
#[derive(Debug)]
pub struct WatcherCommunicatorOptions {
/// Send a list of paths that should be watched for changes.
pub paths_to_watch_tx: tokio::sync::mpsc::UnboundedSender<Vec<PathBuf>>,
/// Listen for a list of paths that were changed.
pub changed_paths_rx: tokio::sync::broadcast::Receiver<Option<Vec<PathBuf>>>,
pub changed_paths_tx: tokio::sync::broadcast::Sender<Option<Vec<PathBuf>>>,
/// Send a message to force a restart.
pub restart_tx: tokio::sync::mpsc::UnboundedSender<()>,
pub restart_mode: WatcherRestartMode,
pub banner: String,
}
/// An interface to interact with Deno's CLI file watcher. /// An interface to interact with Deno's CLI file watcher.
#[derive(Debug)] #[derive(Debug)]
pub struct WatcherCommunicator { pub struct WatcherCommunicator {
/// Send a list of paths that should be watched for changes. /// Send a list of paths that should be watched for changes.
paths_to_watch_tx: tokio::sync::mpsc::UnboundedSender<Vec<PathBuf>>, paths_to_watch_tx: tokio::sync::mpsc::UnboundedSender<Vec<PathBuf>>,
/// Listen for a list of paths that were changed. /// Listen for a list of paths that were changed.
changed_paths_rx: tokio::sync::broadcast::Receiver<Option<Vec<PathBuf>>>, changed_paths_rx: tokio::sync::broadcast::Receiver<Option<Vec<PathBuf>>>,
changed_paths_tx: tokio::sync::broadcast::Sender<Option<Vec<PathBuf>>>,
/// Send a message to force a restart. /// Send a message to force a restart.
restart_tx: tokio::sync::mpsc::UnboundedSender<()>, restart_tx: tokio::sync::mpsc::UnboundedSender<()>,
restart_mode: Mutex<WatcherRestartMode>, restart_mode: Mutex<WatcherRestartMode>,
banner: String, banner: String,
} }
impl WatcherCommunicator { impl WatcherCommunicator {
pub fn watch_paths(&self, paths: Vec<PathBuf>) -> Result<(), AnyError> { pub fn new(options: WatcherCommunicatorOptions) -> Self {
Self {
paths_to_watch_tx: options.paths_to_watch_tx,
changed_paths_rx: options.changed_paths_rx,
changed_paths_tx: options.changed_paths_tx,
restart_tx: options.restart_tx,
restart_mode: Mutex::new(options.restart_mode),
banner: options.banner,
}
}
pub fn watch_paths(
&self,
paths: Vec<PathBuf>,
) -> Result<(), SendError<Vec<PathBuf>>> {
if paths.is_empty() { if paths.is_empty() {
return Ok(()); return Ok(());
} }
self.paths_to_watch_tx.send(paths).map_err(AnyError::from) self.paths_to_watch_tx.send(paths)
} }
pub fn force_restart(&self) -> Result<(), AnyError> { pub fn force_restart(&self) -> Result<(), SendError<()>> {
// Change back to automatic mode, so that HMR can set up watching // Change back to automatic mode, so that HMR can set up watching
// from scratch. // from scratch.
*self.restart_mode.lock() = WatcherRestartMode::Automatic; *self.restart_mode.lock() = WatcherRestartMode::Automatic;
self.restart_tx.send(()).map_err(AnyError::from) self.restart_tx.send(())
} }
pub async fn watch_for_changed_paths( pub async fn watch_for_changed_paths(
@ -184,6 +209,22 @@ impl WatcherCommunicator {
*self.restart_mode.lock() = restart_mode; *self.restart_mode.lock() = restart_mode;
} }
pub fn send(
&self,
paths: Option<Vec<PathBuf>>,
) -> Result<(), SendError<Option<Vec<PathBuf>>>> {
match *self.restart_mode.lock() {
WatcherRestartMode::Automatic => {
self.restart_tx.send(()).map_err(|_| SendError(None))
}
WatcherRestartMode::Manual => self
.changed_paths_tx
.send(paths)
.map(|_| ())
.map_err(|e| SendError(e.0)),
}
}
pub fn print(&self, msg: String) { pub fn print(&self, msg: String) {
log::info!("{} {}", self.banner, colors::gray(msg)); log::info!("{} {}", self.banner, colors::gray(msg));
} }
@ -272,13 +313,15 @@ where
} = print_config; } = print_config;
let print_after_restart = create_print_after_restart_fn(clear_screen); let print_after_restart = create_print_after_restart_fn(clear_screen);
let watcher_communicator = Arc::new(WatcherCommunicator { let watcher_communicator =
Arc::new(WatcherCommunicator::new(WatcherCommunicatorOptions {
paths_to_watch_tx: paths_to_watch_tx.clone(), paths_to_watch_tx: paths_to_watch_tx.clone(),
changed_paths_rx: changed_paths_rx.resubscribe(), changed_paths_rx: changed_paths_rx.resubscribe(),
changed_paths_tx,
restart_tx: restart_tx.clone(), restart_tx: restart_tx.clone(),
restart_mode: Mutex::new(restart_mode), restart_mode,
banner: colors::intense_blue(banner).to_string(), banner: colors::intense_blue(banner).to_string(),
}); }));
info!("{} {} started.", colors::intense_blue(banner), job_name); info!("{} {} started.", colors::intense_blue(banner), job_name);
let changed_paths = Rc::new(RefCell::new(None)); let changed_paths = Rc::new(RefCell::new(None));
@ -292,15 +335,8 @@ where
.borrow_mut() .borrow_mut()
.clone_from(&received_changed_paths); .clone_from(&received_changed_paths);
match *watcher_.restart_mode.lock() {
WatcherRestartMode::Automatic => {
let _ = restart_tx.send(());
}
WatcherRestartMode::Manual => {
// TODO(bartlomieju): should we fail on sending changed paths? // TODO(bartlomieju): should we fail on sending changed paths?
let _ = changed_paths_tx.send(received_changed_paths); let _ = watcher_.send(received_changed_paths);
}
}
} }
}); });

View file

@ -2,7 +2,6 @@
// Note: Only add code in this folder that has no application specific logic // Note: Only add code in this folder that has no application specific logic
pub mod archive; pub mod archive;
pub mod checksum;
pub mod console; pub mod console;
pub mod diff; pub mod diff;
pub mod display; pub mod display;

View file

@ -1,8 +1,6 @@
// Copyright 2018-2025 the Deno authors. MIT license. // Copyright 2018-2025 the Deno authors. MIT license.
use std::path::Path; use std::path::Path;
use std::path::PathBuf;
use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use deno_ast::ModuleSpecifier; use deno_ast::ModuleSpecifier;
@ -10,76 +8,31 @@ use deno_core::anyhow::bail;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::error::CoreError; use deno_core::error::CoreError;
use deno_core::futures::FutureExt; use deno_core::futures::FutureExt;
use deno_core::url::Url;
use deno_core::v8; use deno_core::v8;
use deno_core::CompiledWasmModuleStore;
use deno_core::Extension; use deno_core::Extension;
use deno_core::FeatureChecker;
use deno_core::ModuleLoader;
use deno_core::PollEventLoopOptions; use deno_core::PollEventLoopOptions;
use deno_core::SharedArrayBufferStore;
use deno_error::JsErrorBox; use deno_error::JsErrorBox;
use deno_lib::worker::LibMainWorker;
use deno_lib::worker::LibMainWorkerFactory;
use deno_runtime::code_cache; use deno_runtime::code_cache;
use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel;
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_permissions::PermissionsContainer; use deno_runtime::deno_permissions::PermissionsContainer;
use deno_runtime::deno_tls::RootCertStoreProvider;
use deno_runtime::deno_web::BlobStore;
use deno_runtime::fmt_errors::format_js_error;
use deno_runtime::inspector_server::InspectorServer;
use deno_runtime::ops::process::NpmProcessStateProviderRc;
use deno_runtime::ops::worker_host::CreateWebWorkerCb;
use deno_runtime::web_worker::WebWorker;
use deno_runtime::web_worker::WebWorkerOptions;
use deno_runtime::web_worker::WebWorkerServiceOptions;
use deno_runtime::worker::MainWorker; use deno_runtime::worker::MainWorker;
use deno_runtime::worker::WorkerOptions;
use deno_runtime::worker::WorkerServiceOptions;
use deno_runtime::BootstrapOptions;
use deno_runtime::WorkerExecutionMode; use deno_runtime::WorkerExecutionMode;
use deno_runtime::WorkerLogLevel;
use deno_semver::npm::NpmPackageReqReference; use deno_semver::npm::NpmPackageReqReference;
use deno_telemetry::OtelConfig;
use deno_terminal::colors;
use node_resolver::NodeResolutionKind; use node_resolver::NodeResolutionKind;
use node_resolver::ResolutionMode; use node_resolver::ResolutionMode;
use sys_traits::EnvCurrentDir;
use tokio::select; use tokio::select;
use crate::args::CliLockfile; use crate::args::CliLockfile;
use crate::args::DenoSubcommand;
use crate::args::NpmCachingStrategy; use crate::args::NpmCachingStrategy;
use crate::args::StorageKeyResolver;
use crate::node::CliNodeResolver; use crate::node::CliNodeResolver;
use crate::node::CliPackageJsonResolver;
use crate::npm::installer::NpmInstaller; use crate::npm::installer::NpmInstaller;
use crate::npm::installer::PackageCaching; use crate::npm::installer::PackageCaching;
use crate::npm::CliNpmResolver; use crate::npm::CliNpmResolver;
use crate::sys::CliSys; use crate::sys::CliSys;
use crate::util::checksum;
use crate::util::file_watcher::WatcherCommunicator; use crate::util::file_watcher::WatcherCommunicator;
use crate::util::file_watcher::WatcherRestartMode; use crate::util::file_watcher::WatcherRestartMode;
use crate::version;
pub struct CreateModuleLoaderResult {
pub module_loader: Rc<dyn ModuleLoader>,
pub node_require_loader: Rc<dyn NodeRequireLoader>,
}
pub trait ModuleLoaderFactory: Send + Sync {
fn create_for_main(
&self,
root_permissions: PermissionsContainer,
) -> CreateModuleLoaderResult;
fn create_for_worker(
&self,
parent_permissions: PermissionsContainer,
permissions: PermissionsContainer,
) -> CreateModuleLoaderResult;
}
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
pub trait HmrRunner: Send + Sync { pub trait HmrRunner: Send + Sync {
@ -114,84 +67,28 @@ pub type CreateCoverageCollectorCb = Box<
>; >;
pub struct CliMainWorkerOptions { pub struct CliMainWorkerOptions {
pub argv: Vec<String>,
pub log_level: WorkerLogLevel,
pub enable_op_summary_metrics: bool,
pub enable_testing_features: bool,
pub has_node_modules_dir: bool,
pub hmr: bool,
pub inspect_brk: bool,
pub inspect_wait: bool,
pub strace_ops: Option<Vec<String>>,
pub is_inspecting: bool,
pub location: Option<Url>,
pub argv0: Option<String>,
pub node_debug: Option<String>,
pub origin_data_folder_path: Option<PathBuf>,
pub seed: Option<u64>,
pub unsafely_ignore_certificate_errors: Option<Vec<String>>,
pub skip_op_registration: bool,
pub create_hmr_runner: Option<CreateHmrRunnerCb>, pub create_hmr_runner: Option<CreateHmrRunnerCb>,
pub create_coverage_collector: Option<CreateCoverageCollectorCb>, pub create_coverage_collector: Option<CreateCoverageCollectorCb>,
pub node_ipc: Option<i64>, pub default_npm_caching_strategy: NpmCachingStrategy,
pub serve_port: Option<u16>, pub needs_test_modules: bool,
pub serve_host: Option<String>,
} }
struct SharedWorkerState { /// Data shared between the factory and workers.
blob_store: Arc<BlobStore>, struct SharedState {
broadcast_channel: InMemoryBroadcastChannel, pub create_hmr_runner: Option<CreateHmrRunnerCb>,
code_cache: Option<Arc<dyn CliCodeCache>>, pub create_coverage_collector: Option<CreateCoverageCollectorCb>,
compiled_wasm_module_store: CompiledWasmModuleStore, pub maybe_file_watcher_communicator: Option<Arc<WatcherCommunicator>>,
feature_checker: Arc<FeatureChecker>,
fs: Arc<dyn deno_fs::FileSystem>,
maybe_file_watcher_communicator: Option<Arc<WatcherCommunicator>>,
maybe_inspector_server: Option<Arc<InspectorServer>>,
maybe_lockfile: Option<Arc<CliLockfile>>,
module_loader_factory: Box<dyn ModuleLoaderFactory>,
node_resolver: Arc<CliNodeResolver>,
npm_installer: Option<Arc<NpmInstaller>>,
npm_resolver: Arc<dyn CliNpmResolver>,
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,
default_npm_caching_strategy: NpmCachingStrategy,
}
impl SharedWorkerState {
pub fn create_node_init_services(
&self,
node_require_loader: NodeRequireLoaderRc,
) -> 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(),
}
}
pub fn npm_process_state_provider(&self) -> NpmProcessStateProviderRc {
self.npm_resolver.clone().into_process_state_provider()
}
} }
pub struct CliMainWorker { pub struct CliMainWorker {
main_module: ModuleSpecifier, worker: LibMainWorker,
worker: MainWorker, shared: Arc<SharedState>,
shared: Arc<SharedWorkerState>,
} }
impl CliMainWorker { impl CliMainWorker {
#[inline]
pub fn into_main_worker(self) -> MainWorker { pub fn into_main_worker(self) -> MainWorker {
self.worker self.worker.into_main_worker()
} }
pub async fn setup_repl(&mut self) -> Result<(), AnyError> { pub async fn setup_repl(&mut self) -> Result<(), AnyError> {
@ -204,16 +101,13 @@ impl CliMainWorker {
self.maybe_setup_coverage_collector().await?; self.maybe_setup_coverage_collector().await?;
let mut maybe_hmr_runner = self.maybe_setup_hmr_runner().await?; let mut maybe_hmr_runner = self.maybe_setup_hmr_runner().await?;
log::debug!("main_module {}", self.main_module); log::debug!("main_module {}", self.worker.main_module());
self.execute_main_module().await?; self.execute_main_module().await?;
self.worker.dispatch_load_event()?; self.worker.dispatch_load_event()?;
loop { loop {
if let Some(hmr_runner) = maybe_hmr_runner.as_mut() { if let Some(hmr_runner) = maybe_hmr_runner.as_mut() {
let watcher_communicator =
self.shared.maybe_file_watcher_communicator.clone().unwrap();
let hmr_future = hmr_runner.run().boxed_local(); let hmr_future = hmr_runner.run().boxed_local();
let event_loop_future = self.worker.run_event_loop(false).boxed_local(); let event_loop_future = self.worker.run_event_loop(false).boxed_local();
@ -227,7 +121,11 @@ impl CliMainWorker {
} }
} }
if let Err(e) = result { if let Err(e) = result {
watcher_communicator self
.shared
.maybe_file_watcher_communicator
.as_ref()
.unwrap()
.change_restart_mode(WatcherRestartMode::Automatic); .change_restart_mode(WatcherRestartMode::Automatic);
return Err(e); return Err(e);
} }
@ -253,7 +151,7 @@ impl CliMainWorker {
if let Some(coverage_collector) = maybe_coverage_collector.as_mut() { if let Some(coverage_collector) = maybe_coverage_collector.as_mut() {
self self
.worker .worker
.js_runtime .js_runtime()
.with_event_loop_future( .with_event_loop_future(
coverage_collector.stop_collecting().boxed_local(), coverage_collector.stop_collecting().boxed_local(),
PollEventLoopOptions::default(), PollEventLoopOptions::default(),
@ -263,7 +161,7 @@ impl CliMainWorker {
if let Some(hmr_runner) = maybe_hmr_runner.as_mut() { if let Some(hmr_runner) = maybe_hmr_runner.as_mut() {
self self
.worker .worker
.js_runtime .js_runtime()
.with_event_loop_future( .with_event_loop_future(
hmr_runner.stop().boxed_local(), hmr_runner.stop().boxed_local(),
PollEventLoopOptions::default(), PollEventLoopOptions::default(),
@ -335,24 +233,20 @@ impl CliMainWorker {
executor.execute().await executor.execute().await
} }
#[inline]
pub async fn execute_main_module(&mut self) -> Result<(), CoreError> { pub async fn execute_main_module(&mut self) -> Result<(), CoreError> {
let id = self.worker.preload_main_module(&self.main_module).await?; self.worker.execute_main_module().await
self.worker.evaluate_module(id).await
} }
#[inline]
pub async fn execute_side_module(&mut self) -> Result<(), CoreError> { pub async fn execute_side_module(&mut self) -> Result<(), CoreError> {
let id = self.worker.preload_side_module(&self.main_module).await?; self.worker.execute_side_module().await
self.worker.evaluate_module(id).await
} }
pub async fn maybe_setup_hmr_runner( pub async fn maybe_setup_hmr_runner(
&mut self, &mut self,
) -> Result<Option<Box<dyn HmrRunner>>, AnyError> { ) -> Result<Option<Box<dyn HmrRunner>>, AnyError> {
if !self.shared.options.hmr { let Some(setup_hmr_runner) = self.shared.create_hmr_runner.as_ref() else {
return Ok(None);
}
let Some(setup_hmr_runner) = self.shared.options.create_hmr_runner.as_ref()
else {
return Ok(None); return Ok(None);
}; };
@ -362,7 +256,7 @@ impl CliMainWorker {
self self
.worker .worker
.js_runtime .js_runtime()
.with_event_loop_future( .with_event_loop_future(
hmr_runner.start().boxed_local(), hmr_runner.start().boxed_local(),
PollEventLoopOptions::default(), PollEventLoopOptions::default(),
@ -375,7 +269,7 @@ impl CliMainWorker {
&mut self, &mut self,
) -> Result<Option<Box<dyn CoverageCollector>>, AnyError> { ) -> Result<Option<Box<dyn CoverageCollector>>, AnyError> {
let Some(create_coverage_collector) = let Some(create_coverage_collector) =
self.shared.options.create_coverage_collector.as_ref() self.shared.create_coverage_collector.as_ref()
else { else {
return Ok(None); return Ok(None);
}; };
@ -384,7 +278,7 @@ impl CliMainWorker {
let mut coverage_collector = create_coverage_collector(session); let mut coverage_collector = create_coverage_collector(session);
self self
.worker .worker
.js_runtime .js_runtime()
.with_event_loop_future( .with_event_loop_future(
coverage_collector.start_collecting().boxed_local(), coverage_collector.start_collecting().boxed_local(),
PollEventLoopOptions::default(), PollEventLoopOptions::default(),
@ -398,72 +292,51 @@ impl CliMainWorker {
name: &'static str, name: &'static str,
source_code: &'static str, source_code: &'static str,
) -> Result<v8::Global<v8::Value>, CoreError> { ) -> Result<v8::Global<v8::Value>, CoreError> {
self.worker.js_runtime.execute_script(name, source_code) self.worker.js_runtime().execute_script(name, source_code)
} }
} }
// TODO(bartlomieju): this should be moved to some other place, added to avoid string
// duplication between worker setups and `deno info` output.
pub fn get_cache_storage_dir() -> PathBuf {
// Note: we currently use temp_dir() to avoid managing storage size.
std::env::temp_dir().join("deno_cache")
}
#[derive(Clone)]
pub struct CliMainWorkerFactory { pub struct CliMainWorkerFactory {
shared: Arc<SharedWorkerState>, lib_main_worker_factory: LibMainWorkerFactory<CliSys>,
maybe_lockfile: Option<Arc<CliLockfile>>,
node_resolver: Arc<CliNodeResolver>,
npm_installer: Option<Arc<NpmInstaller>>,
npm_resolver: CliNpmResolver,
root_permissions: PermissionsContainer,
shared: Arc<SharedState>,
sys: CliSys,
default_npm_caching_strategy: NpmCachingStrategy,
needs_test_modules: bool,
} }
impl CliMainWorkerFactory { impl CliMainWorkerFactory {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn new( pub fn new(
blob_store: Arc<BlobStore>, lib_main_worker_factory: LibMainWorkerFactory<CliSys>,
code_cache: Option<Arc<dyn CliCodeCache>>,
feature_checker: Arc<FeatureChecker>,
fs: Arc<dyn deno_fs::FileSystem>,
maybe_file_watcher_communicator: Option<Arc<WatcherCommunicator>>, maybe_file_watcher_communicator: Option<Arc<WatcherCommunicator>>,
maybe_inspector_server: Option<Arc<InspectorServer>>,
maybe_lockfile: Option<Arc<CliLockfile>>, maybe_lockfile: Option<Arc<CliLockfile>>,
module_loader_factory: Box<dyn ModuleLoaderFactory>,
node_resolver: Arc<CliNodeResolver>, node_resolver: Arc<CliNodeResolver>,
npm_installer: Option<Arc<NpmInstaller>>, npm_installer: Option<Arc<NpmInstaller>>,
npm_resolver: Arc<dyn CliNpmResolver>, npm_resolver: CliNpmResolver,
pkg_json_resolver: Arc<CliPackageJsonResolver>,
root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
root_permissions: PermissionsContainer,
storage_key_resolver: StorageKeyResolver,
sys: CliSys, sys: CliSys,
subcommand: DenoSubcommand,
options: CliMainWorkerOptions, options: CliMainWorkerOptions,
otel_config: OtelConfig, root_permissions: PermissionsContainer,
default_npm_caching_strategy: NpmCachingStrategy,
) -> Self { ) -> Self {
Self { Self {
shared: Arc::new(SharedWorkerState { lib_main_worker_factory,
blob_store,
broadcast_channel: Default::default(),
code_cache,
compiled_wasm_module_store: Default::default(),
feature_checker,
fs,
maybe_file_watcher_communicator,
maybe_inspector_server,
maybe_lockfile, maybe_lockfile,
module_loader_factory,
node_resolver, node_resolver,
npm_installer, npm_installer,
npm_resolver, npm_resolver,
pkg_json_resolver,
root_cert_store_provider,
root_permissions, root_permissions,
shared_array_buffer_store: Default::default(),
storage_key_resolver,
sys, sys,
options, shared: Arc::new(SharedState {
subcommand, create_hmr_runner: options.create_hmr_runner,
otel_config, create_coverage_collector: options.create_coverage_collector,
default_npm_caching_strategy, maybe_file_watcher_communicator,
}), }),
default_npm_caching_strategy: options.default_npm_caching_strategy,
needs_test_modules: options.needs_test_modules,
} }
} }
@ -476,7 +349,7 @@ impl CliMainWorkerFactory {
.create_custom_worker( .create_custom_worker(
mode, mode,
main_module, main_module,
self.shared.root_permissions.clone(), self.root_permissions.clone(),
vec![], vec![],
Default::default(), Default::default(),
) )
@ -491,23 +364,16 @@ impl CliMainWorkerFactory {
custom_extensions: Vec<Extension>, custom_extensions: Vec<Extension>,
stdio: deno_runtime::deno_io::Stdio, stdio: deno_runtime::deno_io::Stdio,
) -> Result<CliMainWorker, CoreError> { ) -> Result<CliMainWorker, CoreError> {
let shared = &self.shared;
let CreateModuleLoaderResult {
module_loader,
node_require_loader,
} = shared
.module_loader_factory
.create_for_main(permissions.clone());
let main_module = if let Ok(package_ref) = let main_module = if let Ok(package_ref) =
NpmPackageReqReference::from_specifier(&main_module) NpmPackageReqReference::from_specifier(&main_module)
{ {
if let Some(npm_installer) = &shared.npm_installer { if let Some(npm_installer) = &self.npm_installer {
let reqs = &[package_ref.req().clone()]; let reqs = &[package_ref.req().clone()];
npm_installer npm_installer
.add_package_reqs( .add_package_reqs(
reqs, reqs,
if matches!( if matches!(
shared.default_npm_caching_strategy, self.default_npm_caching_strategy,
NpmCachingStrategy::Lazy NpmCachingStrategy::Lazy
) { ) {
PackageCaching::Only(reqs.into()) PackageCaching::Only(reqs.into())
@ -520,18 +386,18 @@ impl CliMainWorkerFactory {
// use a fake referrer that can be used to discover the package.json if necessary // use a fake referrer that can be used to discover the package.json if necessary
let referrer = ModuleSpecifier::from_directory_path( let referrer = ModuleSpecifier::from_directory_path(
self.shared.fs.cwd().map_err(JsErrorBox::from_err)?, self.sys.env_current_dir().map_err(JsErrorBox::from_err)?,
) )
.unwrap() .unwrap()
.join("package.json")?; .join("package.json")?;
let package_folder = shared let package_folder = self
.npm_resolver .npm_resolver
.resolve_pkg_folder_from_deno_module_req(package_ref.req(), &referrer) .resolve_pkg_folder_from_deno_module_req(package_ref.req(), &referrer)
.map_err(JsErrorBox::from_err)?; .map_err(JsErrorBox::from_err)?;
let main_module = self let main_module = self
.resolve_binary_entrypoint(&package_folder, package_ref.sub_path())?; .resolve_binary_entrypoint(&package_folder, package_ref.sub_path())?;
if let Some(lockfile) = &shared.maybe_lockfile { if let Some(lockfile) = &self.maybe_lockfile {
// For npm binary commands, ensure that the lockfile gets updated // For npm binary commands, ensure that the lockfile gets updated
// so that we can re-use the npm resolution the next time it runs // so that we can re-use the npm resolution the next time it runs
// for better performance // for better performance
@ -543,119 +409,18 @@ impl CliMainWorkerFactory {
main_module main_module
}; };
let maybe_inspector_server = shared.maybe_inspector_server.clone(); let mut worker = self.lib_main_worker_factory.create_custom_worker(
let create_web_worker_cb =
create_web_worker_callback(shared.clone(), stdio.clone());
let maybe_storage_key = shared
.storage_key_resolver
.resolve_storage_key(&main_module);
let origin_storage_dir = maybe_storage_key.as_ref().map(|key| {
shared
.options
.origin_data_folder_path
.as_ref()
.unwrap() // must be set if storage key resolver returns a value
.join(checksum::gen(&[key.as_bytes()]))
});
let cache_storage_dir = maybe_storage_key.map(|key| {
// TODO(@satyarohith): storage quota management
get_cache_storage_dir().join(checksum::gen(&[key.as_bytes()]))
});
// TODO(bartlomieju): this is cruft, update FeatureChecker to spit out
// list of enabled features.
let feature_checker = shared.feature_checker.clone();
let mut unstable_features =
Vec::with_capacity(crate::UNSTABLE_GRANULAR_FLAGS.len());
for granular_flag in crate::UNSTABLE_GRANULAR_FLAGS {
if feature_checker.check(granular_flag.name) {
unstable_features.push(granular_flag.id);
}
}
let services = WorkerServiceOptions {
root_cert_store_provider: Some(shared.root_cert_store_provider.clone()),
module_loader,
fs: shared.fs.clone(),
node_services: Some(
shared.create_node_init_services(node_require_loader),
),
npm_process_state_provider: Some(shared.npm_process_state_provider()),
blob_store: shared.blob_store.clone(),
broadcast_channel: shared.broadcast_channel.clone(),
fetch_dns_resolver: Default::default(),
shared_array_buffer_store: Some(shared.shared_array_buffer_store.clone()),
compiled_wasm_module_store: Some(
shared.compiled_wasm_module_store.clone(),
),
feature_checker,
permissions,
v8_code_cache: shared.code_cache.clone().map(|c| c.as_code_cache()),
};
let options = WorkerOptions {
bootstrap: BootstrapOptions {
deno_version: crate::version::DENO_VERSION_INFO.deno.to_string(),
args: shared.options.argv.clone(),
cpu_count: std::thread::available_parallelism()
.map(|p| p.get())
.unwrap_or(1),
log_level: shared.options.log_level,
enable_op_summary_metrics: shared.options.enable_op_summary_metrics,
enable_testing_features: shared.options.enable_testing_features,
locale: deno_core::v8::icu::get_language_tag(),
location: shared.options.location.clone(),
no_color: !colors::use_color(),
is_stdout_tty: deno_terminal::is_stdout_tty(),
is_stderr_tty: deno_terminal::is_stderr_tty(),
color_level: colors::get_color_level(),
unstable_features,
user_agent: version::DENO_VERSION_INFO.user_agent.to_string(),
inspect: shared.options.is_inspecting,
has_node_modules_dir: shared.options.has_node_modules_dir,
argv0: shared.options.argv0.clone(),
node_debug: shared.options.node_debug.clone(),
node_ipc_fd: shared.options.node_ipc,
mode, mode,
serve_port: shared.options.serve_port, main_module,
serve_host: shared.options.serve_host.clone(), permissions,
otel_config: shared.otel_config.clone(), custom_extensions,
close_on_idle: true,
},
extensions: custom_extensions,
startup_snapshot: crate::js::deno_isolate_init(),
create_params: create_isolate_create_params(),
unsafely_ignore_certificate_errors: shared
.options
.unsafely_ignore_certificate_errors
.clone(),
seed: shared.options.seed,
format_js_error_fn: Some(Arc::new(format_js_error)),
create_web_worker_cb,
maybe_inspector_server,
should_break_on_first_statement: shared.options.inspect_brk,
should_wait_for_inspector_session: shared.options.inspect_wait,
strace_ops: shared.options.strace_ops.clone(),
cache_storage_dir,
origin_storage_dir,
stdio, stdio,
skip_op_registration: shared.options.skip_op_registration, )?;
enable_stack_trace_arg_in_ops: crate::args::has_trace_permissions_enabled(
),
};
let mut worker = MainWorker::bootstrap_from_options( if self.needs_test_modules {
main_module.clone(),
services,
options,
);
if self.shared.subcommand.needs_test() {
macro_rules! test_file { macro_rules! test_file {
($($file:literal),*) => { ($($file:literal),*) => {
$(worker.js_runtime.lazy_load_es_module_with_code( $(worker.js_runtime().lazy_load_es_module_with_code(
concat!("ext:cli/", $file), concat!("ext:cli/", $file),
deno_core::ascii_str_include!(concat!("js/", $file)), deno_core::ascii_str_include!(concat!("js/", $file)),
)?;)* )?;)*
@ -673,9 +438,8 @@ impl CliMainWorkerFactory {
} }
Ok(CliMainWorker { Ok(CliMainWorker {
main_module,
worker, worker,
shared: shared.clone(), shared: self.shared.clone(),
}) })
} }
@ -685,7 +449,6 @@ impl CliMainWorkerFactory {
sub_path: Option<&str>, sub_path: Option<&str>,
) -> Result<ModuleSpecifier, AnyError> { ) -> Result<ModuleSpecifier, AnyError> {
match self match self
.shared
.node_resolver .node_resolver
.resolve_binary_export(package_folder, sub_path) .resolve_binary_export(package_folder, sub_path)
{ {
@ -720,7 +483,6 @@ impl CliMainWorkerFactory {
} }
let specifier = self let specifier = self
.shared
.node_resolver .node_resolver
.resolve_package_subpath_from_deno_module( .resolve_package_subpath_from_deno_module(
package_folder, package_folder,
@ -741,136 +503,20 @@ impl CliMainWorkerFactory {
} }
} }
fn create_web_worker_callback(
shared: Arc<SharedWorkerState>,
stdio: deno_runtime::deno_io::Stdio,
) -> Arc<CreateWebWorkerCb> {
Arc::new(move |args| {
let maybe_inspector_server = shared.maybe_inspector_server.clone();
let CreateModuleLoaderResult {
module_loader,
node_require_loader,
} = shared.module_loader_factory.create_for_worker(
args.parent_permissions.clone(),
args.permissions.clone(),
);
let create_web_worker_cb =
create_web_worker_callback(shared.clone(), stdio.clone());
let maybe_storage_key = shared
.storage_key_resolver
.resolve_storage_key(&args.main_module);
let cache_storage_dir = maybe_storage_key.map(|key| {
// TODO(@satyarohith): storage quota management
get_cache_storage_dir().join(checksum::gen(&[key.as_bytes()]))
});
// TODO(bartlomieju): this is cruft, update FeatureChecker to spit out
// list of enabled features.
let feature_checker = shared.feature_checker.clone();
let mut unstable_features =
Vec::with_capacity(crate::UNSTABLE_GRANULAR_FLAGS.len());
for granular_flag in crate::UNSTABLE_GRANULAR_FLAGS {
if feature_checker.check(granular_flag.name) {
unstable_features.push(granular_flag.id);
}
}
let services = WebWorkerServiceOptions {
root_cert_store_provider: Some(shared.root_cert_store_provider.clone()),
module_loader,
fs: shared.fs.clone(),
node_services: Some(
shared.create_node_init_services(node_require_loader),
),
blob_store: shared.blob_store.clone(),
broadcast_channel: shared.broadcast_channel.clone(),
shared_array_buffer_store: Some(shared.shared_array_buffer_store.clone()),
compiled_wasm_module_store: Some(
shared.compiled_wasm_module_store.clone(),
),
maybe_inspector_server,
feature_checker,
npm_process_state_provider: Some(shared.npm_process_state_provider()),
permissions: args.permissions,
};
let options = WebWorkerOptions {
name: args.name,
main_module: args.main_module.clone(),
worker_id: args.worker_id,
bootstrap: BootstrapOptions {
deno_version: crate::version::DENO_VERSION_INFO.deno.to_string(),
args: shared.options.argv.clone(),
cpu_count: std::thread::available_parallelism()
.map(|p| p.get())
.unwrap_or(1),
log_level: shared.options.log_level,
enable_op_summary_metrics: shared.options.enable_op_summary_metrics,
enable_testing_features: shared.options.enable_testing_features,
locale: deno_core::v8::icu::get_language_tag(),
location: Some(args.main_module),
no_color: !colors::use_color(),
color_level: colors::get_color_level(),
is_stdout_tty: deno_terminal::is_stdout_tty(),
is_stderr_tty: deno_terminal::is_stderr_tty(),
unstable_features,
user_agent: version::DENO_VERSION_INFO.user_agent.to_string(),
inspect: shared.options.is_inspecting,
has_node_modules_dir: shared.options.has_node_modules_dir,
argv0: shared.options.argv0.clone(),
node_debug: shared.options.node_debug.clone(),
node_ipc_fd: None,
mode: WorkerExecutionMode::Worker,
serve_port: shared.options.serve_port,
serve_host: shared.options.serve_host.clone(),
otel_config: shared.otel_config.clone(),
close_on_idle: args.close_on_idle,
},
extensions: vec![],
startup_snapshot: crate::js::deno_isolate_init(),
create_params: create_isolate_create_params(),
unsafely_ignore_certificate_errors: shared
.options
.unsafely_ignore_certificate_errors
.clone(),
seed: shared.options.seed,
create_web_worker_cb,
format_js_error_fn: Some(Arc::new(format_js_error)),
worker_type: args.worker_type,
stdio: stdio.clone(),
cache_storage_dir,
strace_ops: shared.options.strace_ops.clone(),
close_on_idle: args.close_on_idle,
maybe_worker_metadata: args.maybe_worker_metadata,
enable_stack_trace_arg_in_ops: crate::args::has_trace_permissions_enabled(
),
};
WebWorker::bootstrap_from_options(services, options)
})
}
/// By default V8 uses 1.4Gb heap limit which is meant for browser tabs.
/// Instead probe for the total memory on the system and use it instead
/// as a default.
pub fn create_isolate_create_params() -> Option<v8::CreateParams> {
let maybe_mem_info = deno_runtime::sys_info::mem_info();
maybe_mem_info.map(|mem_info| {
v8::CreateParams::default()
.heap_limits_from_system_memory(mem_info.total, 0)
})
}
#[allow(clippy::print_stdout)] #[allow(clippy::print_stdout)]
#[allow(clippy::print_stderr)] #[allow(clippy::print_stderr)]
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::rc::Rc;
use deno_core::resolve_path; use deno_core::resolve_path;
use deno_core::FsModuleLoader; use deno_core::FsModuleLoader;
use deno_fs::RealFs; use deno_resolver::npm::DenoInNpmPackageChecker;
use deno_runtime::deno_fs::RealFs;
use deno_runtime::deno_permissions::Permissions; use deno_runtime::deno_permissions::Permissions;
use deno_runtime::permissions::RuntimePermissionDescriptorParser; use deno_runtime::permissions::RuntimePermissionDescriptorParser;
use deno_runtime::worker::WorkerOptions;
use deno_runtime::worker::WorkerServiceOptions;
use super::*; use super::*;
@ -886,8 +532,12 @@ mod tests {
..Default::default() ..Default::default()
}; };
MainWorker::bootstrap_from_options::<CliSys>( MainWorker::bootstrap_from_options::<
main_module, DenoInNpmPackageChecker,
CliNpmResolver,
CliSys,
>(
&main_module,
WorkerServiceOptions { WorkerServiceOptions {
module_loader: Rc::new(FsModuleLoader), module_loader: Rc::new(FsModuleLoader),
permissions: PermissionsContainer::new( permissions: PermissionsContainer::new(

View file

@ -15,8 +15,9 @@ use deno_core::v8;
use deno_core::v8::ExternalReference; use deno_core::v8::ExternalReference;
use deno_error::JsErrorBox; use deno_error::JsErrorBox;
use node_resolver::errors::ClosestPkgJsonError; use node_resolver::errors::ClosestPkgJsonError;
use node_resolver::InNpmPackageChecker;
use node_resolver::IsBuiltInNodeModuleChecker; use node_resolver::IsBuiltInNodeModuleChecker;
use node_resolver::NpmPackageFolderResolverRc; use node_resolver::NpmPackageFolderResolver;
use node_resolver::PackageJsonResolverRc; use node_resolver::PackageJsonResolverRc;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
@ -185,17 +186,21 @@ fn op_node_build_os() -> String {
} }
#[derive(Clone)] #[derive(Clone)]
pub struct NodeExtInitServices<TSys: ExtNodeSys> { pub struct NodeExtInitServices<
TInNpmPackageChecker: InNpmPackageChecker,
TNpmPackageFolderResolver: NpmPackageFolderResolver,
TSys: ExtNodeSys,
> {
pub node_require_loader: NodeRequireLoaderRc, pub node_require_loader: NodeRequireLoaderRc,
pub node_resolver: NodeResolverRc<TSys>, pub node_resolver:
pub npm_resolver: NpmPackageFolderResolverRc, NodeResolverRc<TInNpmPackageChecker, TNpmPackageFolderResolver, TSys>,
pub pkg_json_resolver: PackageJsonResolverRc<TSys>, pub pkg_json_resolver: PackageJsonResolverRc<TSys>,
pub sys: TSys, pub sys: TSys,
} }
deno_core::extension!(deno_node, deno_core::extension!(deno_node,
deps = [ deno_io, deno_fs ], deps = [ deno_io, deno_fs ],
parameters = [P: NodePermissions, TSys: ExtNodeSys], parameters = [P: NodePermissions, TInNpmPackageChecker: InNpmPackageChecker, TNpmPackageFolderResolver: NpmPackageFolderResolver, TSys: ExtNodeSys],
ops = [ ops = [
ops::blocklist::op_socket_address_parse, ops::blocklist::op_socket_address_parse,
ops::blocklist::op_socket_address_get_serialization, ops::blocklist::op_socket_address_get_serialization,
@ -395,13 +400,13 @@ deno_core::extension!(deno_node,
ops::require::op_require_init_paths, ops::require::op_require_init_paths,
ops::require::op_require_node_module_paths<P, TSys>, ops::require::op_require_node_module_paths<P, TSys>,
ops::require::op_require_proxy_path, ops::require::op_require_proxy_path,
ops::require::op_require_is_deno_dir_package<TSys>, ops::require::op_require_is_deno_dir_package<TInNpmPackageChecker, TNpmPackageFolderResolver, TSys>,
ops::require::op_require_resolve_deno_dir, ops::require::op_require_resolve_deno_dir<TInNpmPackageChecker, TNpmPackageFolderResolver, TSys>,
ops::require::op_require_is_maybe_cjs, ops::require::op_require_is_maybe_cjs,
ops::require::op_require_is_request_relative, ops::require::op_require_is_request_relative,
ops::require::op_require_resolve_lookup_paths, ops::require::op_require_resolve_lookup_paths,
ops::require::op_require_try_self_parent_path<P, TSys>, ops::require::op_require_try_self_parent_path<P, TSys>,
ops::require::op_require_try_self<P, TSys>, ops::require::op_require_try_self<P, TInNpmPackageChecker, TNpmPackageFolderResolver, TSys>,
ops::require::op_require_real_path<P, TSys>, ops::require::op_require_real_path<P, TSys>,
ops::require::op_require_path_is_absolute, ops::require::op_require_path_is_absolute,
ops::require::op_require_path_dirname, ops::require::op_require_path_dirname,
@ -410,9 +415,9 @@ deno_core::extension!(deno_node,
ops::require::op_require_path_basename, ops::require::op_require_path_basename,
ops::require::op_require_read_file<P>, ops::require::op_require_read_file<P>,
ops::require::op_require_as_file_path, ops::require::op_require_as_file_path,
ops::require::op_require_resolve_exports<P, TSys>, ops::require::op_require_resolve_exports<P, TInNpmPackageChecker, TNpmPackageFolderResolver, TSys>,
ops::require::op_require_read_package_scope<P, TSys>, ops::require::op_require_read_package_scope<P, TSys>,
ops::require::op_require_package_imports_resolve<P, TSys>, ops::require::op_require_package_imports_resolve<P, TInNpmPackageChecker, TNpmPackageFolderResolver, TSys>,
ops::require::op_require_break_on_next_statement, ops::require::op_require_break_on_next_statement,
ops::util::op_node_guess_handle_type, ops::util::op_node_guess_handle_type,
ops::worker_threads::op_worker_threads_filename<P, TSys>, ops::worker_threads::op_worker_threads_filename<P, TSys>,
@ -681,7 +686,7 @@ deno_core::extension!(deno_node,
"node:zlib" = "zlib.ts", "node:zlib" = "zlib.ts",
], ],
options = { options = {
maybe_init: Option<NodeExtInitServices<TSys>>, maybe_init: Option<NodeExtInitServices<TInNpmPackageChecker, TNpmPackageFolderResolver, TSys>>,
fs: deno_fs::FileSystemRc, fs: deno_fs::FileSystemRc,
}, },
state = |state, options| { state = |state, options| {
@ -691,7 +696,6 @@ deno_core::extension!(deno_node,
state.put(init.sys.clone()); state.put(init.sys.clone());
state.put(init.node_require_loader.clone()); state.put(init.node_require_loader.clone());
state.put(init.node_resolver.clone()); state.put(init.node_resolver.clone());
state.put(init.npm_resolver.clone());
state.put(init.pkg_json_resolver.clone()); state.put(init.pkg_json_resolver.clone());
} }
}, },
@ -833,10 +837,18 @@ pub trait ExtNodeSys:
impl ExtNodeSys for sys_traits::impls::RealSys {} impl ExtNodeSys for sys_traits::impls::RealSys {}
pub type NodeResolver<TSys> = pub type NodeResolver<TInNpmPackageChecker, TNpmPackageFolderResolver, TSys> =
node_resolver::NodeResolver<RealIsBuiltInNodeModuleChecker, TSys>; node_resolver::NodeResolver<
TInNpmPackageChecker,
RealIsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver,
TSys,
>;
#[allow(clippy::disallowed_types)] #[allow(clippy::disallowed_types)]
pub type NodeResolverRc<TSys> = deno_fs::sync::MaybeArc<NodeResolver<TSys>>; pub type NodeResolverRc<TInNpmPackageChecker, TNpmPackageFolderResolver, TSys> =
deno_fs::sync::MaybeArc<
NodeResolver<TInNpmPackageChecker, TNpmPackageFolderResolver, TSys>,
>;
#[allow(clippy::disallowed_types)] #[allow(clippy::disallowed_types)]
pub fn create_host_defined_options<'s>( pub fn create_host_defined_options<'s>(

View file

@ -19,7 +19,9 @@ use deno_path_util::normalize_path;
use deno_path_util::url_from_file_path; use deno_path_util::url_from_file_path;
use deno_path_util::url_to_file_path; use deno_path_util::url_to_file_path;
use node_resolver::errors::ClosestPkgJsonError; use node_resolver::errors::ClosestPkgJsonError;
use node_resolver::InNpmPackageChecker;
use node_resolver::NodeResolutionKind; use node_resolver::NodeResolutionKind;
use node_resolver::NpmPackageFolderResolver;
use node_resolver::ResolutionMode; use node_resolver::ResolutionMode;
use node_resolver::REQUIRE_CONDITIONS; use node_resolver::REQUIRE_CONDITIONS;
use sys_traits::FsCanonicalize; use sys_traits::FsCanonicalize;
@ -30,7 +32,6 @@ use crate::ExtNodeSys;
use crate::NodePermissions; use crate::NodePermissions;
use crate::NodeRequireLoaderRc; use crate::NodeRequireLoaderRc;
use crate::NodeResolverRc; use crate::NodeResolverRc;
use crate::NpmPackageFolderResolverRc;
use crate::PackageJsonResolverRc; use crate::PackageJsonResolverRc;
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
@ -256,12 +257,20 @@ pub fn op_require_is_request_relative(#[string] request: String) -> bool {
#[op2] #[op2]
#[string] #[string]
pub fn op_require_resolve_deno_dir( pub fn op_require_resolve_deno_dir<
TInNpmPackageChecker: InNpmPackageChecker + 'static,
TNpmPackageFolderResolver: NpmPackageFolderResolver + 'static,
TSys: ExtNodeSys + 'static,
>(
state: &mut OpState, state: &mut OpState,
#[string] request: String, #[string] request: String,
#[string] parent_filename: String, #[string] parent_filename: String,
) -> Result<Option<String>, deno_path_util::PathToUrlError> { ) -> Result<Option<String>, deno_path_util::PathToUrlError> {
let resolver = state.borrow::<NpmPackageFolderResolverRc>(); let resolver = state.borrow::<NodeResolverRc<
TInNpmPackageChecker,
TNpmPackageFolderResolver,
TSys,
>>();
Ok( Ok(
resolver resolver
@ -275,11 +284,19 @@ pub fn op_require_resolve_deno_dir(
} }
#[op2(fast)] #[op2(fast)]
pub fn op_require_is_deno_dir_package<TSys: ExtNodeSys + 'static>( pub fn op_require_is_deno_dir_package<
TInNpmPackageChecker: InNpmPackageChecker + 'static,
TNpmPackageFolderResolver: NpmPackageFolderResolver + 'static,
TSys: ExtNodeSys + 'static,
>(
state: &mut OpState, state: &mut OpState,
#[string] path: String, #[string] path: String,
) -> bool { ) -> bool {
let resolver = state.borrow::<NodeResolverRc<TSys>>(); let resolver = state.borrow::<NodeResolverRc<
TInNpmPackageChecker,
TNpmPackageFolderResolver,
TSys,
>>();
match deno_path_util::url_from_file_path(&PathBuf::from(path)) { match deno_path_util::url_from_file_path(&PathBuf::from(path)) {
Ok(specifier) => resolver.in_npm_package(&specifier), Ok(specifier) => resolver.in_npm_package(&specifier),
Err(_) => false, Err(_) => false,
@ -451,6 +468,8 @@ pub fn op_require_try_self_parent_path<
#[string] #[string]
pub fn op_require_try_self< pub fn op_require_try_self<
P: NodePermissions + 'static, P: NodePermissions + 'static,
TInNpmPackageChecker: InNpmPackageChecker + 'static,
TNpmPackageFolderResolver: NpmPackageFolderResolver + 'static,
TSys: ExtNodeSys + 'static, TSys: ExtNodeSys + 'static,
>( >(
state: &mut OpState, state: &mut OpState,
@ -493,7 +512,11 @@ pub fn op_require_try_self<
let referrer = deno_core::url::Url::from_file_path(&pkg.path).unwrap(); let referrer = deno_core::url::Url::from_file_path(&pkg.path).unwrap();
if let Some(exports) = &pkg.exports { if let Some(exports) = &pkg.exports {
let node_resolver = state.borrow::<NodeResolverRc<TSys>>(); let node_resolver = state.borrow::<NodeResolverRc<
TInNpmPackageChecker,
TNpmPackageFolderResolver,
TSys,
>>();
let r = node_resolver.package_exports_resolve( let r = node_resolver.package_exports_resolve(
&pkg.path, &pkg.path,
&expansion, &expansion,
@ -552,6 +575,8 @@ pub fn op_require_as_file_path(#[string] file_or_url: String) -> String {
#[string] #[string]
pub fn op_require_resolve_exports< pub fn op_require_resolve_exports<
P: NodePermissions + 'static, P: NodePermissions + 'static,
TInNpmPackageChecker: InNpmPackageChecker + 'static,
TNpmPackageFolderResolver: NpmPackageFolderResolver + 'static,
TSys: ExtNodeSys + 'static, TSys: ExtNodeSys + 'static,
>( >(
state: &mut OpState, state: &mut OpState,
@ -563,7 +588,11 @@ pub fn op_require_resolve_exports<
#[string] parent_path: String, #[string] parent_path: String,
) -> Result<Option<String>, RequireError> { ) -> Result<Option<String>, RequireError> {
let sys = state.borrow::<TSys>(); let sys = state.borrow::<TSys>();
let node_resolver = state.borrow::<NodeResolverRc<TSys>>(); let node_resolver = state.borrow::<NodeResolverRc<
TInNpmPackageChecker,
TNpmPackageFolderResolver,
TSys,
>>();
let pkg_json_resolver = state.borrow::<PackageJsonResolverRc<TSys>>(); let pkg_json_resolver = state.borrow::<PackageJsonResolverRc<TSys>>();
let modules_path = PathBuf::from(&modules_path_str); let modules_path = PathBuf::from(&modules_path_str);
@ -655,6 +684,8 @@ pub fn op_require_read_package_scope<
#[string] #[string]
pub fn op_require_package_imports_resolve< pub fn op_require_package_imports_resolve<
P: NodePermissions + 'static, P: NodePermissions + 'static,
TInNpmPackageChecker: InNpmPackageChecker + 'static,
TNpmPackageFolderResolver: NpmPackageFolderResolver + 'static,
TSys: ExtNodeSys + 'static, TSys: ExtNodeSys + 'static,
>( >(
state: &mut OpState, state: &mut OpState,
@ -672,7 +703,11 @@ pub fn op_require_package_imports_resolve<
}; };
if pkg.imports.is_some() { if pkg.imports.is_some() {
let node_resolver = state.borrow::<NodeResolverRc<TSys>>(); let node_resolver = state.borrow::<NodeResolverRc<
TInNpmPackageChecker,
TNpmPackageFolderResolver,
TSys,
>>();
let referrer_url = Url::from_file_path(&referrer_filename).unwrap(); let referrer_url = Url::from_file_path(&referrer_filename).unwrap();
let url = node_resolver.package_imports_resolve( let url = node_resolver.package_imports_resolve(
&request, &request,

View file

@ -154,7 +154,7 @@ export class TLSSocket extends net.Socket {
const afterConnect = handle.afterConnect; const afterConnect = handle.afterConnect;
handle.afterConnect = async (req: any, status: number) => { handle.afterConnect = async (req: any, status: number) => {
options.hostname ??= undefined; // coerce to undefined if null, startTls expects hostname to be undefined options.hostname ??= undefined; // coerce to undefined if null, startTls expects hostname to be undefined
if (tlssock._isNpmAgent) { if (tlssock._needsSockInitWorkaround) {
// skips the TLS handshake for @npmcli/agent as it's handled by // skips the TLS handshake for @npmcli/agent as it's handled by
// onSocket handler of ClientRequest object. // onSocket handler of ClientRequest object.
tlssock.emit("secure"); tlssock.emit("secure");

View file

@ -165,6 +165,11 @@ export class FileHandle extends EventEmitter {
assertNotClosed(this, promises.utimes.name); assertNotClosed(this, promises.utimes.name);
return promises.utimes(this.#path, atime, mtime); return promises.utimes(this.#path, atime, mtime);
} }
chown(uid: number, gid: number): Promise<void> {
assertNotClosed(this, promises.chown.name);
return promises.chown(this.#path, uid, gid);
}
} }
function assertNotClosed(handle: FileHandle, syscall: string) { function assertNotClosed(handle: FileHandle, syscall: string) {

View file

@ -1157,6 +1157,13 @@ function _emitCloseNT(s: Socket | Server) {
s.emit("close"); s.emit("close");
} }
// The packages that need socket initialization workaround
const pkgsNeedsSockInitWorkaround = [
"@npmcli/agent",
"npm-check-updates",
"playwright-core",
];
/** /**
* This class is an abstraction of a TCP socket or a streaming `IPC` endpoint * This class is an abstraction of a TCP socket or a streaming `IPC` endpoint
* (uses named pipes on Windows, and Unix domain sockets otherwise). It is also * (uses named pipes on Windows, and Unix domain sockets otherwise). It is also
@ -1201,9 +1208,11 @@ export class Socket extends Duplex {
_host: string | null = null; _host: string | null = null;
// deno-lint-ignore no-explicit-any // deno-lint-ignore no-explicit-any
_parent: any = null; _parent: any = null;
// The flag for detecting if it's called in @npmcli/agent // Skip some initialization (initial read and tls handshake if it's tls socket).
// If this flag is true, it's used as connection for http(s) request, and
// the reading and TLS handshake is done by the http client.
// See discussions in https://github.com/denoland/deno/pull/25470 for more details. // See discussions in https://github.com/denoland/deno/pull/25470 for more details.
_isNpmAgent = false; _needsSockInitWorkaround = false;
autoSelectFamilyAttemptedAddresses: AddressInfo[] | undefined = undefined; autoSelectFamilyAttemptedAddresses: AddressInfo[] | undefined = undefined;
constructor(options: SocketOptions | number) { constructor(options: SocketOptions | number) {
@ -1224,21 +1233,20 @@ export class Socket extends Duplex {
super(options); super(options);
// Note: If the socket is created from one of: // Note: If the socket is created from one of `pkgNeedsSockInitWorkaround`,
// - @npmcli/agent
// - npm-check-updates (bundles @npmcli/agent as a dependency)
// the 'socket' event on ClientRequest object happens after 'connect' event on Socket object. // the 'socket' event on ClientRequest object happens after 'connect' event on Socket object.
// That swaps the sequence of op_node_http_request_with_conn() call and // That swaps the sequence of op_node_http_request_with_conn() call and
// initial socket read. That causes op_node_http_request_with_conn() not // initial socket read. That causes op_node_http_request_with_conn() not
// working. // working.
// To avoid the above situation, we detect the socket created from // To avoid the above situation, we detect the socket created from
// @npmcli/agent and pause the socket (and also skips the startTls call // one of those packages using stack trace and pause the socket
// if it's TLSSocket) // (and also skips the startTls call if it's TLSSocket)
// TODO(kt3k): Remove this workaround // TODO(kt3k): Remove this workaround
const errorStack = new Error().stack; const errorStack = new Error().stack;
this._isNpmAgent = errorStack?.includes("@npmcli/agent") || this._needsSockInitWorkaround = pkgsNeedsSockInitWorkaround.some((pkg) =>
errorStack?.includes("npm-check-updates") || false; errorStack?.includes(pkg)
if (this._isNpmAgent) { );
if (this._needsSockInitWorkaround) {
this.pause(); this.pause();
} }

View file

@ -35,7 +35,7 @@ import { validateIntegerRange } from "ext:deno_node/_utils.ts";
import process from "node:process"; import process from "node:process";
import { isWindows } from "ext:deno_node/_util/os.ts"; import { isWindows } from "ext:deno_node/_util/os.ts";
import { os } from "ext:deno_node/internal_binding/constants.ts"; import { os } from "ext:deno_node/internal_binding/constants.ts";
import { osUptime } from "ext:runtime/30_os.js"; import { osUptime } from "ext:deno_os/30_os.js";
import { Buffer } from "ext:deno_node/internal/buffer.mjs"; import { Buffer } from "ext:deno_node/internal/buffer.mjs";
import { primordials } from "ext:core/mod.js"; import { primordials } from "ext:core/mod.js";
const { StringPrototypeEndsWith, StringPrototypeSlice } = primordials; const { StringPrototypeEndsWith, StringPrototypeSlice } = primordials;

View file

@ -58,7 +58,7 @@ import {
} from "ext:deno_node/_next_tick.ts"; } from "ext:deno_node/_next_tick.ts";
import { isWindows } from "ext:deno_node/_util/os.ts"; import { isWindows } from "ext:deno_node/_util/os.ts";
import * as io from "ext:deno_io/12_io.js"; import * as io from "ext:deno_io/12_io.js";
import * as denoOs from "ext:runtime/30_os.js"; import * as denoOs from "ext:deno_os/30_os.js";
export let argv0 = ""; export let argv0 = "";

33
ext/os/Cargo.toml Normal file
View file

@ -0,0 +1,33 @@
# Copyright 2018-2025 the Deno authors. MIT license.
[package]
name = "deno_os"
version = "0.1.0"
authors.workspace = true
edition.workspace = true
license.workspace = true
readme = "README.md"
repository.workspace = true
description = "OS specific APIs for Deno"
[lib]
path = "lib.rs"
[dependencies]
deno_core.workspace = true
deno_error.workspace = true
deno_path_util.workspace = true
deno_permissions.workspace = true
deno_telemetry.workspace = true
libc.workspace = true
netif = "0.1.6"
once_cell.workspace = true
serde.workspace = true
signal-hook = "0.3.17"
signal-hook-registry = "1.4.0"
thiserror.workspace = true
tokio.workspace = true
[target.'cfg(windows)'.dependencies]
winapi = { workspace = true, features = ["commapi", "knownfolders", "mswsock", "objbase", "psapi", "shlobj", "tlhelp32", "winbase", "winerror", "winuser", "winsock2"] }
ntapi = "0.4.0"

View file

@ -1,4 +1,6 @@
## `os` ops # deno_os
This crate implements OS specific APIs for Deno
`loadavg` `loadavg`

View file

@ -1,19 +1,54 @@
// Copyright 2018-2025 the Deno authors. MIT license. // Copyright 2018-2025 the Deno authors. MIT license.
use std::collections::HashMap; use std::collections::HashMap;
use std::collections::HashSet;
use std::env; use std::env;
use std::sync::atomic::AtomicI32;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use deno_core::op2; use deno_core::op2;
use deno_core::v8; use deno_core::v8;
use deno_core::OpState; use deno_core::OpState;
use deno_node::NODE_ENV_VAR_ALLOWLIST;
use deno_path_util::normalize_path; use deno_path_util::normalize_path;
use deno_permissions::PermissionCheckError; use deno_permissions::PermissionCheckError;
use deno_permissions::PermissionsContainer; use deno_permissions::PermissionsContainer;
use once_cell::sync::Lazy;
use serde::Serialize; use serde::Serialize;
use crate::sys_info; mod ops;
use crate::worker::ExitCode; pub mod signal;
pub mod sys_info;
pub use ops::signal::SignalError;
pub static NODE_ENV_VAR_ALLOWLIST: Lazy<HashSet<String>> = Lazy::new(|| {
// The full list of environment variables supported by Node.js is available
// at https://nodejs.org/api/cli.html#environment-variables
let mut set = HashSet::new();
set.insert("NODE_DEBUG".to_string());
set.insert("NODE_OPTIONS".to_string());
set
});
#[derive(Clone, Default)]
pub struct ExitCode(Arc<AtomicI32>);
impl ExitCode {
pub fn get(&self) -> i32 {
self.0.load(Ordering::Relaxed)
}
pub fn set(&mut self, code: i32) {
self.0.store(code, Ordering::Relaxed);
}
}
pub fn exit(code: i32) -> ! {
deno_telemetry::flush();
#[allow(clippy::disallowed_methods)]
std::process::exit(code);
}
deno_core::extension!( deno_core::extension!(
deno_os, deno_os,
@ -35,13 +70,21 @@ deno_core::extension!(
op_system_memory_info, op_system_memory_info,
op_uid, op_uid,
op_runtime_memory_usage, op_runtime_memory_usage,
ops::signal::op_signal_bind,
ops::signal::op_signal_unbind,
ops::signal::op_signal_poll,
], ],
esm = ["30_os.js", "40_signals.js"],
options = { options = {
exit_code: ExitCode, exit_code: ExitCode,
}, },
state = |state, options| { state = |state, options| {
state.put::<ExitCode>(options.exit_code); state.put::<ExitCode>(options.exit_code);
}, #[cfg(unix)]
{
state.put(ops::signal::SignalState::default());
}
}
); );
deno_core::extension!( deno_core::extension!(
@ -64,12 +107,16 @@ deno_core::extension!(
op_system_memory_info, op_system_memory_info,
op_uid, op_uid,
op_runtime_memory_usage, op_runtime_memory_usage,
ops::signal::op_signal_bind,
ops::signal::op_signal_unbind,
ops::signal::op_signal_poll,
], ],
esm = ["30_os.js", "40_signals.js"],
middleware = |op| match op.name { middleware = |op| match op.name {
"op_exit" | "op_set_exit_code" | "op_get_exit_code" => "op_exit" | "op_set_exit_code" | "op_get_exit_code" =>
op.with_implementation_from(&deno_core::op_void_sync()), op.with_implementation_from(&deno_core::op_void_sync()),
_ => op, _ => op,
}, }
); );
#[derive(Debug, thiserror::Error, deno_error::JsError)] #[derive(Debug, thiserror::Error, deno_error::JsError)]
@ -196,7 +243,7 @@ fn op_get_exit_code(state: &mut OpState) -> i32 {
#[op2(fast)] #[op2(fast)]
fn op_exit(state: &mut OpState) { fn op_exit(state: &mut OpState) {
let code = state.borrow::<ExitCode>().get(); let code = state.borrow::<ExitCode>().get();
crate::exit(code) exit(code)
} }
#[op2(stack_trace)] #[op2(stack_trace)]
@ -239,7 +286,7 @@ fn op_network_interfaces(
Ok(netif::up()?.map(NetworkInterface::from).collect()) Ok(netif::up()?.map(NetworkInterface::from).collect())
} }
#[derive(serde::Serialize)] #[derive(Serialize)]
struct NetworkInterface { struct NetworkInterface {
family: &'static str, family: &'static str,
name: String, name: String,

3
ext/os/ops/mod.rs Normal file
View file

@ -0,0 +1,3 @@
// Copyright 2018-2025 the Deno authors. MIT license.
pub mod signal;

View file

@ -33,17 +33,6 @@ use tokio::signal::windows::CtrlBreak;
#[cfg(windows)] #[cfg(windows)]
use tokio::signal::windows::CtrlC; use tokio::signal::windows::CtrlC;
deno_core::extension!(
deno_signal,
ops = [op_signal_bind, op_signal_unbind, op_signal_poll],
state = |state| {
#[cfg(unix)]
{
state.put(SignalState::default());
}
}
);
#[derive(Debug, thiserror::Error, deno_error::JsError)] #[derive(Debug, thiserror::Error, deno_error::JsError)]
pub enum SignalError { pub enum SignalError {
#[class(type)] #[class(type)]
@ -62,7 +51,7 @@ pub enum SignalError {
#[cfg(unix)] #[cfg(unix)]
#[derive(Default)] #[derive(Default)]
struct SignalState { pub struct SignalState {
enable_default_handlers: BTreeMap<libc::c_int, Arc<AtomicBool>>, enable_default_handlers: BTreeMap<libc::c_int, Arc<AtomicBool>>,
} }
@ -164,7 +153,7 @@ impl Resource for SignalStreamResource {
#[cfg(unix)] #[cfg(unix)]
#[op2(fast)] #[op2(fast)]
#[smi] #[smi]
fn op_signal_bind( pub fn op_signal_bind(
state: &mut OpState, state: &mut OpState,
#[string] sig: &str, #[string] sig: &str,
) -> Result<ResourceId, SignalError> { ) -> Result<ResourceId, SignalError> {
@ -201,7 +190,7 @@ fn op_signal_bind(
#[cfg(windows)] #[cfg(windows)]
#[op2(fast)] #[op2(fast)]
#[smi] #[smi]
fn op_signal_bind( pub fn op_signal_bind(
state: &mut OpState, state: &mut OpState,
#[string] sig: &str, #[string] sig: &str,
) -> Result<ResourceId, SignalError> { ) -> Result<ResourceId, SignalError> {
@ -225,7 +214,7 @@ fn op_signal_bind(
} }
#[op2(async)] #[op2(async)]
async fn op_signal_poll( pub async fn op_signal_poll(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
#[smi] rid: ResourceId, #[smi] rid: ResourceId,
) -> Result<bool, ResourceError> { ) -> Result<bool, ResourceError> {

View file

@ -2,7 +2,7 @@
use deno_media_type::MediaType; use deno_media_type::MediaType;
use node_resolver::errors::ClosestPkgJsonError; use node_resolver::errors::ClosestPkgJsonError;
use node_resolver::InNpmPackageCheckerRc; use node_resolver::InNpmPackageChecker;
use node_resolver::PackageJsonResolverRc; use node_resolver::PackageJsonResolverRc;
use node_resolver::ResolutionMode; use node_resolver::ResolutionMode;
use sys_traits::FsRead; use sys_traits::FsRead;
@ -16,14 +16,16 @@ use crate::sync::MaybeDashMap;
/// be CJS or ESM after they're loaded based on their contents. So these /// be CJS or ESM after they're loaded based on their contents. So these
/// files will be "maybe CJS" until they're loaded. /// files will be "maybe CJS" until they're loaded.
#[derive(Debug)] #[derive(Debug)]
pub struct CjsTracker<TSys: FsRead> { pub struct CjsTracker<TInNpmPackageChecker: InNpmPackageChecker, TSys: FsRead> {
is_cjs_resolver: IsCjsResolver<TSys>, is_cjs_resolver: IsCjsResolver<TInNpmPackageChecker, TSys>,
known: MaybeDashMap<Url, ResolutionMode>, known: MaybeDashMap<Url, ResolutionMode>,
} }
impl<TSys: FsRead> CjsTracker<TSys> { impl<TInNpmPackageChecker: InNpmPackageChecker, TSys: FsRead>
CjsTracker<TInNpmPackageChecker, TSys>
{
pub fn new( pub fn new(
in_npm_pkg_checker: InNpmPackageCheckerRc, in_npm_pkg_checker: TInNpmPackageChecker,
pkg_json_resolver: PackageJsonResolverRc<TSys>, pkg_json_resolver: PackageJsonResolverRc<TSys>,
mode: IsCjsResolutionMode, mode: IsCjsResolutionMode,
) -> Self { ) -> Self {
@ -125,15 +127,20 @@ pub enum IsCjsResolutionMode {
/// Resolves whether a module is CJS or ESM. /// Resolves whether a module is CJS or ESM.
#[derive(Debug)] #[derive(Debug)]
pub struct IsCjsResolver<TSys: FsRead> { pub struct IsCjsResolver<
in_npm_pkg_checker: InNpmPackageCheckerRc, TInNpmPackageChecker: InNpmPackageChecker,
TSys: FsRead,
> {
in_npm_pkg_checker: TInNpmPackageChecker,
pkg_json_resolver: PackageJsonResolverRc<TSys>, pkg_json_resolver: PackageJsonResolverRc<TSys>,
mode: IsCjsResolutionMode, mode: IsCjsResolutionMode,
} }
impl<TSys: FsRead> IsCjsResolver<TSys> { impl<TInNpmPackageChecker: InNpmPackageChecker, TSys: FsRead>
IsCjsResolver<TInNpmPackageChecker, TSys>
{
pub fn new( pub fn new(
in_npm_pkg_checker: InNpmPackageCheckerRc, in_npm_pkg_checker: TInNpmPackageChecker,
pkg_json_resolver: PackageJsonResolverRc<TSys>, pkg_json_resolver: PackageJsonResolverRc<TSys>,
mode: IsCjsResolutionMode, mode: IsCjsResolutionMode,
) -> Self { ) -> Self {

View file

@ -19,11 +19,12 @@ use deno_package_json::PackageJsonDepValueParseError;
use deno_semver::npm::NpmPackageReqReference; use deno_semver::npm::NpmPackageReqReference;
use node_resolver::errors::NodeResolveError; use node_resolver::errors::NodeResolveError;
use node_resolver::errors::PackageSubpathResolveError; use node_resolver::errors::PackageSubpathResolveError;
use node_resolver::InNpmPackageCheckerRc; use node_resolver::InNpmPackageChecker;
use node_resolver::IsBuiltInNodeModuleChecker; use node_resolver::IsBuiltInNodeModuleChecker;
use node_resolver::NodeResolution; use node_resolver::NodeResolution;
use node_resolver::NodeResolutionKind; use node_resolver::NodeResolutionKind;
use node_resolver::NodeResolverRc; use node_resolver::NodeResolverRc;
use node_resolver::NpmPackageFolderResolver;
use node_resolver::ResolutionMode; use node_resolver::ResolutionMode;
use npm::MissingPackageNodeModulesFolderError; use npm::MissingPackageNodeModulesFolderError;
use npm::NodeModulesOutOfDateError; use npm::NodeModulesOutOfDateError;
@ -101,22 +102,42 @@ pub enum DenoResolveErrorKind {
#[derive(Debug)] #[derive(Debug)]
pub struct NodeAndNpmReqResolver< pub struct NodeAndNpmReqResolver<
TInNpmPackageChecker: InNpmPackageChecker,
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker, TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver: NpmPackageFolderResolver,
TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir, TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir,
> { > {
pub node_resolver: NodeResolverRc<TIsBuiltInNodeModuleChecker, TSys>, pub node_resolver: NodeResolverRc<
pub npm_req_resolver: NpmReqResolverRc<TIsBuiltInNodeModuleChecker, TSys>, TInNpmPackageChecker,
TIsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver,
TSys,
>,
pub npm_req_resolver: NpmReqResolverRc<
TInNpmPackageChecker,
TIsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver,
TSys,
>,
} }
pub struct DenoResolverOptions< pub struct DenoResolverOptions<
'a, 'a,
TInNpmPackageChecker: InNpmPackageChecker,
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker, TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver: NpmPackageFolderResolver,
TSloppyImportResolverFs: SloppyImportResolverFs, TSloppyImportResolverFs: SloppyImportResolverFs,
TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir, TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir,
> { > {
pub in_npm_pkg_checker: InNpmPackageCheckerRc, pub in_npm_pkg_checker: TInNpmPackageChecker,
pub node_and_req_resolver: pub node_and_req_resolver: Option<
Option<NodeAndNpmReqResolver<TIsBuiltInNodeModuleChecker, TSys>>, NodeAndNpmReqResolver<
TInNpmPackageChecker,
TIsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver,
TSys,
>,
>,
pub sloppy_imports_resolver: pub sloppy_imports_resolver:
Option<SloppyImportsResolverRc<TSloppyImportResolverFs>>, Option<SloppyImportsResolverRc<TSloppyImportResolverFs>>,
pub workspace_resolver: WorkspaceResolverRc, pub workspace_resolver: WorkspaceResolverRc,
@ -131,13 +152,21 @@ pub struct DenoResolverOptions<
/// import map, JSX settings. /// import map, JSX settings.
#[derive(Debug)] #[derive(Debug)]
pub struct DenoResolver< pub struct DenoResolver<
TInNpmPackageChecker: InNpmPackageChecker,
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker, TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver: NpmPackageFolderResolver,
TSloppyImportResolverFs: SloppyImportResolverFs, TSloppyImportResolverFs: SloppyImportResolverFs,
TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir, TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir,
> { > {
in_npm_pkg_checker: InNpmPackageCheckerRc, in_npm_pkg_checker: TInNpmPackageChecker,
node_and_npm_resolver: node_and_npm_resolver: Option<
Option<NodeAndNpmReqResolver<TIsBuiltInNodeModuleChecker, TSys>>, NodeAndNpmReqResolver<
TInNpmPackageChecker,
TIsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver,
TSys,
>,
>,
sloppy_imports_resolver: sloppy_imports_resolver:
Option<SloppyImportsResolverRc<TSloppyImportResolverFs>>, Option<SloppyImportsResolverRc<TSloppyImportResolverFs>>,
workspace_resolver: WorkspaceResolverRc, workspace_resolver: WorkspaceResolverRc,
@ -146,14 +175,25 @@ pub struct DenoResolver<
} }
impl< impl<
TInNpmPackageChecker: InNpmPackageChecker,
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker, TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver: NpmPackageFolderResolver,
TSloppyImportResolverFs: SloppyImportResolverFs, TSloppyImportResolverFs: SloppyImportResolverFs,
TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir, TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir,
> DenoResolver<TIsBuiltInNodeModuleChecker, TSloppyImportResolverFs, TSys> >
DenoResolver<
TInNpmPackageChecker,
TIsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver,
TSloppyImportResolverFs,
TSys,
>
{ {
pub fn new( pub fn new(
options: DenoResolverOptions< options: DenoResolverOptions<
TInNpmPackageChecker,
TIsBuiltInNodeModuleChecker, TIsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver,
TSloppyImportResolverFs, TSloppyImportResolverFs,
TSys, TSys,
>, >,

View file

@ -27,8 +27,6 @@ use thiserror::Error;
use url::Url; use url::Url;
use super::local::normalize_pkg_name_for_node_modules_deno_folder; use super::local::normalize_pkg_name_for_node_modules_deno_folder;
use crate::sync::MaybeSend;
use crate::sync::MaybeSync;
#[derive(Debug, Error, deno_error::JsError)] #[derive(Debug, Error, deno_error::JsError)]
pub enum ByonmResolvePkgFolderFromDenoReqError { pub enum ByonmResolvePkgFolderFromDenoReqError {
@ -89,7 +87,7 @@ impl<TSys: FsCanonicalize + FsRead + FsMetadata + FsReadDir>
} }
} }
pub fn root_node_modules_dir(&self) -> Option<&Path> { pub fn root_node_modules_path(&self) -> Option<&Path> {
self.root_node_modules_dir.as_deref() self.root_node_modules_dir.as_deref()
} }
@ -377,15 +375,8 @@ impl<TSys: FsCanonicalize + FsRead + FsMetadata + FsReadDir>
} }
} }
impl< impl<TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir>
TSys: FsCanonicalize NpmPackageFolderResolver for ByonmNpmResolver<TSys>
+ FsMetadata
+ FsRead
+ FsReadDir
+ MaybeSend
+ MaybeSync
+ std::fmt::Debug,
> NpmPackageFolderResolver for ByonmNpmResolver<TSys>
{ {
fn resolve_package_folder_from_package( fn resolve_package_folder_from_package(
&self, &self,
@ -438,7 +429,7 @@ impl<
} }
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct ByonmInNpmPackageChecker; pub struct ByonmInNpmPackageChecker;
impl InNpmPackageChecker for ByonmInNpmPackageChecker { impl InNpmPackageChecker for ByonmInNpmPackageChecker {

View file

@ -6,26 +6,69 @@ use std::path::PathBuf;
use deno_npm::NpmPackageCacheFolderId; use deno_npm::NpmPackageCacheFolderId;
use deno_npm::NpmPackageId; use deno_npm::NpmPackageId;
use node_resolver::NpmPackageFolderResolver; use node_resolver::NpmPackageFolderResolver;
use sys_traits::FsCanonicalize;
use sys_traits::FsMetadata;
use url::Url; use url::Url;
use crate::sync::MaybeSend; #[derive(Debug)]
use crate::sync::MaybeSync; pub enum NpmPackageFsResolver<TSys: FsCanonicalize + FsMetadata> {
Local(super::local::LocalNpmPackageResolver<TSys>),
Global(super::global::GlobalNpmPackageResolver),
}
#[allow(clippy::disallowed_types)] impl<TSys: FsCanonicalize + FsMetadata> NpmPackageFsResolver<TSys> {
pub type NpmPackageFsResolverRc = /// The local node_modules folder (only for the local resolver).
crate::sync::MaybeArc<dyn NpmPackageFsResolver>; pub fn node_modules_path(&self) -> Option<&Path> {
match self {
NpmPackageFsResolver::Local(resolver) => resolver.node_modules_path(),
NpmPackageFsResolver::Global(_) => None,
}
}
/// Part of the resolution that interacts with the file system. pub fn maybe_package_folder(
pub trait NpmPackageFsResolver: &self,
NpmPackageFolderResolver + MaybeSend + MaybeSync package_id: &NpmPackageId,
{ ) -> Option<PathBuf> {
/// The local node_modules folder if it is applicable to the implementation. match self {
fn node_modules_path(&self) -> Option<&Path>; NpmPackageFsResolver::Local(resolver) => {
resolver.maybe_package_folder(package_id)
}
NpmPackageFsResolver::Global(resolver) => {
resolver.maybe_package_folder(package_id)
}
}
}
fn maybe_package_folder(&self, package_id: &NpmPackageId) -> Option<PathBuf>; pub fn resolve_package_cache_folder_id_from_specifier(
fn resolve_package_cache_folder_id_from_specifier(
&self, &self,
specifier: &Url, specifier: &Url,
) -> Result<Option<NpmPackageCacheFolderId>, std::io::Error>; ) -> Result<Option<NpmPackageCacheFolderId>, std::io::Error> {
match self {
NpmPackageFsResolver::Local(resolver) => {
resolver.resolve_package_cache_folder_id_from_specifier(specifier)
}
NpmPackageFsResolver::Global(resolver) => {
resolver.resolve_package_cache_folder_id_from_specifier(specifier)
}
}
}
}
impl<TSys: FsCanonicalize + FsMetadata> NpmPackageFolderResolver
for NpmPackageFsResolver<TSys>
{
fn resolve_package_folder_from_package(
&self,
specifier: &str,
referrer: &Url,
) -> Result<PathBuf, node_resolver::errors::PackageFolderResolveError> {
match self {
NpmPackageFsResolver::Local(r) => {
r.resolve_package_folder_from_package(specifier, referrer)
}
NpmPackageFsResolver::Global(r) => {
r.resolve_package_folder_from_package(specifier, referrer)
}
}
}
} }

View file

@ -2,7 +2,6 @@
//! Code for global npm cache resolution. //! Code for global npm cache resolution.
use std::path::Path;
use std::path::PathBuf; use std::path::PathBuf;
use deno_npm::NpmPackageCacheFolderId; use deno_npm::NpmPackageCacheFolderId;
@ -18,7 +17,6 @@ use url::Url;
use super::resolution::NpmResolutionCellRc; use super::resolution::NpmResolutionCellRc;
use super::NpmCacheDirRc; use super::NpmCacheDirRc;
use super::NpmPackageFsResolver;
use crate::ResolvedNpmRcRc; use crate::ResolvedNpmRcRc;
/// Resolves packages from the global npm cache. /// Resolves packages from the global npm cache.
@ -42,6 +40,26 @@ impl GlobalNpmPackageResolver {
} }
} }
pub fn maybe_package_folder(&self, id: &NpmPackageId) -> Option<PathBuf> {
let folder_copy_index = self
.resolution
.resolve_pkg_cache_folder_copy_index_from_pkg_id(id)?;
let registry_url = self.npm_rc.get_registry_url(&id.nv.name);
Some(self.cache.package_folder_for_id(
&id.nv.name,
&id.nv.version.to_string(),
folder_copy_index,
registry_url,
))
}
pub fn resolve_package_cache_folder_id_from_specifier(
&self,
specifier: &Url,
) -> Result<Option<NpmPackageCacheFolderId>, std::io::Error> {
Ok(self.resolve_package_cache_folder_id_from_specifier_inner(specifier))
}
fn resolve_package_cache_folder_id_from_specifier_inner( fn resolve_package_cache_folder_id_from_specifier_inner(
&self, &self,
specifier: &Url, specifier: &Url,
@ -121,29 +139,3 @@ impl NpmPackageFolderResolver for GlobalNpmPackageResolver {
} }
} }
} }
impl NpmPackageFsResolver for GlobalNpmPackageResolver {
fn node_modules_path(&self) -> Option<&Path> {
None
}
fn maybe_package_folder(&self, id: &NpmPackageId) -> Option<PathBuf> {
let folder_copy_index = self
.resolution
.resolve_pkg_cache_folder_copy_index_from_pkg_id(id)?;
let registry_url = self.npm_rc.get_registry_url(&id.nv.name);
Some(self.cache.package_folder_for_id(
&id.nv.name,
&id.nv.version.to_string(),
folder_copy_index,
registry_url,
))
}
fn resolve_package_cache_folder_id_from_specifier(
&self,
specifier: &Url,
) -> Result<Option<NpmPackageCacheFolderId>, std::io::Error> {
Ok(self.resolve_package_cache_folder_id_from_specifier_inner(specifier))
}
}

View file

@ -20,27 +20,20 @@ use sys_traits::FsMetadata;
use url::Url; use url::Url;
use super::resolution::NpmResolutionCellRc; use super::resolution::NpmResolutionCellRc;
use super::NpmPackageFsResolver;
use crate::npm::local::get_package_folder_id_folder_name_from_parts; use crate::npm::local::get_package_folder_id_folder_name_from_parts;
use crate::npm::local::get_package_folder_id_from_folder_name; use crate::npm::local::get_package_folder_id_from_folder_name;
use crate::sync::MaybeSend;
use crate::sync::MaybeSync;
/// Resolver that creates a local node_modules directory /// Resolver that creates a local node_modules directory
/// and resolves packages from it. /// and resolves packages from it.
#[derive(Debug)] #[derive(Debug)]
pub struct LocalNpmPackageResolver< pub struct LocalNpmPackageResolver<TSys: FsCanonicalize + FsMetadata> {
TSys: FsCanonicalize + FsMetadata + MaybeSend + MaybeSync,
> {
resolution: NpmResolutionCellRc, resolution: NpmResolutionCellRc,
sys: TSys, sys: TSys,
root_node_modules_path: PathBuf, root_node_modules_path: PathBuf,
root_node_modules_url: Url, root_node_modules_url: Url,
} }
impl<TSys: FsCanonicalize + FsMetadata + MaybeSend + MaybeSync> impl<TSys: FsCanonicalize + FsMetadata> LocalNpmPackageResolver<TSys> {
LocalNpmPackageResolver<TSys>
{
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn new( pub fn new(
resolution: NpmResolutionCellRc, resolution: NpmResolutionCellRc,
@ -56,6 +49,55 @@ impl<TSys: FsCanonicalize + FsMetadata + MaybeSend + MaybeSync>
} }
} }
pub fn node_modules_path(&self) -> Option<&Path> {
Some(self.root_node_modules_path.as_ref())
}
pub fn maybe_package_folder(&self, id: &NpmPackageId) -> Option<PathBuf> {
let folder_copy_index = self
.resolution
.resolve_pkg_cache_folder_copy_index_from_pkg_id(id)?;
// package is stored at:
// node_modules/.deno/<package_cache_folder_id_folder_name>/node_modules/<package_name>
Some(
self
.root_node_modules_path
.join(".deno")
.join(get_package_folder_id_folder_name_from_parts(
&id.nv,
folder_copy_index,
))
.join("node_modules")
.join(&id.nv.name),
)
}
pub fn resolve_package_cache_folder_id_from_specifier(
&self,
specifier: &Url,
) -> Result<Option<NpmPackageCacheFolderId>, std::io::Error> {
let Some(folder_path) =
self.resolve_package_folder_from_specifier(specifier)?
else {
return Ok(None);
};
// ex. project/node_modules/.deno/preact@10.24.3/node_modules/preact/
let Some(node_modules_ancestor) = folder_path
.ancestors()
.find(|ancestor| ancestor.ends_with("node_modules"))
else {
return Ok(None);
};
let Some(folder_name) =
node_modules_ancestor.parent().and_then(|p| p.file_name())
else {
return Ok(None);
};
Ok(get_package_folder_id_from_folder_name(
&folder_name.to_string_lossy(),
))
}
fn resolve_package_root(&self, path: &Path) -> PathBuf { fn resolve_package_root(&self, path: &Path) -> PathBuf {
let mut last_found = path; let mut last_found = path;
loop { loop {
@ -101,9 +143,8 @@ impl<TSys: FsCanonicalize + FsMetadata + MaybeSend + MaybeSync>
} }
} }
impl< impl<TSys: FsCanonicalize + FsMetadata> NpmPackageFolderResolver
TSys: FsCanonicalize + FsMetadata + MaybeSend + MaybeSync + std::fmt::Debug, for LocalNpmPackageResolver<TSys>
> NpmPackageFolderResolver for LocalNpmPackageResolver<TSys>
{ {
fn resolve_package_folder_from_package( fn resolve_package_folder_from_package(
&self, &self,
@ -163,60 +204,6 @@ impl<
} }
} }
impl<
TSys: FsCanonicalize + FsMetadata + MaybeSend + MaybeSync + std::fmt::Debug,
> NpmPackageFsResolver for LocalNpmPackageResolver<TSys>
{
fn node_modules_path(&self) -> Option<&Path> {
Some(self.root_node_modules_path.as_ref())
}
fn maybe_package_folder(&self, id: &NpmPackageId) -> Option<PathBuf> {
let folder_copy_index = self
.resolution
.resolve_pkg_cache_folder_copy_index_from_pkg_id(id)?;
// package is stored at:
// node_modules/.deno/<package_cache_folder_id_folder_name>/node_modules/<package_name>
Some(
self
.root_node_modules_path
.join(".deno")
.join(get_package_folder_id_folder_name_from_parts(
&id.nv,
folder_copy_index,
))
.join("node_modules")
.join(&id.nv.name),
)
}
fn resolve_package_cache_folder_id_from_specifier(
&self,
specifier: &Url,
) -> Result<Option<NpmPackageCacheFolderId>, std::io::Error> {
let Some(folder_path) =
self.resolve_package_folder_from_specifier(specifier)?
else {
return Ok(None);
};
// ex. project/node_modules/.deno/preact@10.24.3/node_modules/preact/
let Some(node_modules_ancestor) = folder_path
.ancestors()
.find(|ancestor| ancestor.ends_with("node_modules"))
else {
return Ok(None);
};
let Some(folder_name) =
node_modules_ancestor.parent().and_then(|p| p.file_name())
else {
return Ok(None);
};
Ok(get_package_folder_id_from_folder_name(
&folder_name.to_string_lossy(),
))
}
}
fn join_package_name(path: &Path, package_name: &str) -> PathBuf { fn join_package_name(path: &Path, package_name: &str) -> PathBuf {
let mut path = path.to_path_buf(); let mut path = path.to_path_buf();
// ensure backslashes are used on windows // ensure backslashes are used on windows

View file

@ -13,6 +13,7 @@ use deno_npm::resolution::PackageNvNotFoundError;
use deno_npm::resolution::PackageReqNotFoundError; use deno_npm::resolution::PackageReqNotFoundError;
use deno_npm::NpmPackageCacheFolderId; use deno_npm::NpmPackageCacheFolderId;
use deno_npm::NpmPackageId; use deno_npm::NpmPackageId;
use deno_npm::NpmSystemInfo;
use deno_path_util::fs::canonicalize_path_maybe_not_exists; use deno_path_util::fs::canonicalize_path_maybe_not_exists;
use deno_semver::package::PackageNv; use deno_semver::package::PackageNv;
use deno_semver::package::PackageReq; use deno_semver::package::PackageReq;
@ -23,14 +24,10 @@ use sys_traits::FsMetadata;
use url::Url; use url::Url;
use self::common::NpmPackageFsResolver; use self::common::NpmPackageFsResolver;
use self::common::NpmPackageFsResolverRc;
use self::global::GlobalNpmPackageResolver; use self::global::GlobalNpmPackageResolver;
use self::local::LocalNpmPackageResolver; use self::local::LocalNpmPackageResolver;
pub use self::resolution::NpmResolutionCell; pub use self::resolution::NpmResolutionCell;
pub use self::resolution::NpmResolutionCellRc; pub use self::resolution::NpmResolutionCellRc;
use crate::sync::new_rc;
use crate::sync::MaybeSend;
use crate::sync::MaybeSync;
use crate::NpmCacheDirRc; use crate::NpmCacheDirRc;
use crate::ResolvedNpmRcRc; use crate::ResolvedNpmRcRc;
@ -89,58 +86,84 @@ pub enum ResolvePkgIdFromSpecifierError {
NotFound(#[from] PackageCacheFolderIdNotFoundError), NotFound(#[from] PackageCacheFolderIdNotFoundError),
} }
pub struct ManagedNpmResolverCreateOptions<
TSys: FsCanonicalize + FsMetadata + Clone,
> {
pub npm_cache_dir: NpmCacheDirRc,
pub sys: TSys,
pub maybe_node_modules_path: Option<PathBuf>,
pub npm_system_info: NpmSystemInfo,
pub npmrc: ResolvedNpmRcRc,
pub npm_resolution: NpmResolutionCellRc,
}
#[allow(clippy::disallowed_types)] #[allow(clippy::disallowed_types)]
pub type ManagedNpmResolverRc<TSys> = pub type ManagedNpmResolverRc<TSys> =
crate::sync::MaybeArc<ManagedNpmResolver<TSys>>; crate::sync::MaybeArc<ManagedNpmResolver<TSys>>;
#[derive(Debug)] #[derive(Debug)]
pub struct ManagedNpmResolver<TSys: FsCanonicalize> { pub struct ManagedNpmResolver<TSys: FsCanonicalize + FsMetadata> {
fs_resolver: NpmPackageFsResolverRc, fs_resolver: NpmPackageFsResolver<TSys>,
npm_cache_dir: NpmCacheDirRc,
resolution: NpmResolutionCellRc, resolution: NpmResolutionCellRc,
sys: TSys, sys: TSys,
} }
impl<TSys: FsCanonicalize> ManagedNpmResolver<TSys> { impl<TSys: FsCanonicalize + FsMetadata> ManagedNpmResolver<TSys> {
pub fn new< pub fn new<TCreateSys: FsCanonicalize + FsMetadata + Clone>(
TCreateSys: FsCanonicalize options: ManagedNpmResolverCreateOptions<TCreateSys>,
+ FsMetadata
+ std::fmt::Debug
+ MaybeSend
+ MaybeSync
+ Clone
+ 'static,
>(
npm_cache_dir: &NpmCacheDirRc,
npm_rc: &ResolvedNpmRcRc,
resolution: NpmResolutionCellRc,
sys: TCreateSys,
maybe_node_modules_path: Option<PathBuf>,
) -> ManagedNpmResolver<TCreateSys> { ) -> ManagedNpmResolver<TCreateSys> {
let fs_resolver: NpmPackageFsResolverRc = match maybe_node_modules_path { let fs_resolver = match options.maybe_node_modules_path {
Some(node_modules_folder) => new_rc(LocalNpmPackageResolver::new( Some(node_modules_folder) => {
resolution.clone(), NpmPackageFsResolver::Local(LocalNpmPackageResolver::new(
sys.clone(), options.npm_resolution.clone(),
options.sys.clone(),
node_modules_folder, node_modules_folder,
)), ))
None => new_rc(GlobalNpmPackageResolver::new( }
npm_cache_dir.clone(), None => NpmPackageFsResolver::Global(GlobalNpmPackageResolver::new(
npm_rc.clone(), options.npm_cache_dir.clone(),
resolution.clone(), options.npmrc.clone(),
options.npm_resolution.clone(),
)), )),
}; };
ManagedNpmResolver { ManagedNpmResolver {
fs_resolver, fs_resolver,
sys, npm_cache_dir: options.npm_cache_dir,
resolution, sys: options.sys,
resolution: options.npm_resolution,
} }
} }
#[inline] #[inline]
pub fn node_modules_path(&self) -> Option<&Path> { pub fn root_node_modules_path(&self) -> Option<&Path> {
self.fs_resolver.node_modules_path() self.fs_resolver.node_modules_path()
} }
pub fn global_cache_root_path(&self) -> &Path {
self.npm_cache_dir.root_dir()
}
pub fn global_cache_root_url(&self) -> &Url {
self.npm_cache_dir.root_dir_url()
}
pub fn resolution(&self) -> &NpmResolutionCell {
self.resolution.as_ref()
}
/// Checks if the provided package req's folder is cached.
pub fn is_pkg_req_folder_cached(&self, req: &PackageReq) -> bool {
self
.resolution
.resolve_pkg_id_from_pkg_req(req)
.ok()
.and_then(|id| self.resolve_pkg_folder_from_pkg_id(&id).ok())
.map(|folder| self.sys.fs_exists_no_err(folder))
.unwrap_or(false)
}
pub fn resolve_pkg_folder_from_pkg_id( pub fn resolve_pkg_folder_from_pkg_id(
&self, &self,
package_id: &NpmPackageId, package_id: &NpmPackageId,
@ -213,8 +236,8 @@ impl<TSys: FsCanonicalize> ManagedNpmResolver<TSys> {
} }
} }
impl<TSys: FsCanonicalize + std::fmt::Debug + MaybeSend + MaybeSync> impl<TSys: FsCanonicalize + FsMetadata> NpmPackageFolderResolver
NpmPackageFolderResolver for ManagedNpmResolver<TSys> for ManagedNpmResolver<TSys>
{ {
fn resolve_package_folder_from_package( fn resolve_package_folder_from_package(
&self, &self,
@ -234,7 +257,7 @@ impl<TSys: FsCanonicalize + std::fmt::Debug + MaybeSend + MaybeSync>
} }
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct ManagedInNpmPackageChecker { pub struct ManagedInNpmPackageChecker {
root_dir: Url, root_dir: Url,
} }

View file

@ -1,7 +1,5 @@
// Copyright 2018-2025 the Deno authors. MIT license. // Copyright 2018-2025 the Deno authors. MIT license.
use std::collections::HashMap;
use deno_npm::resolution::NpmPackagesPartitioned; use deno_npm::resolution::NpmPackagesPartitioned;
use deno_npm::resolution::NpmResolutionSnapshot; use deno_npm::resolution::NpmResolutionSnapshot;
use deno_npm::resolution::PackageCacheFolderIdNotFoundError; use deno_npm::resolution::PackageCacheFolderIdNotFoundError;
@ -124,8 +122,23 @@ impl NpmResolutionCell {
.map(|pkg| pkg.id.clone()) .map(|pkg| pkg.id.clone())
} }
pub fn package_reqs(&self) -> HashMap<PackageReq, PackageNv> { pub fn package_reqs(&self) -> Vec<(PackageReq, PackageNv)> {
self.snapshot.read().package_reqs().clone() self
.snapshot
.read()
.package_reqs()
.iter()
.map(|(k, v)| (k.clone(), v.clone()))
.collect()
}
pub fn top_level_packages(&self) -> Vec<NpmPackageId> {
self
.snapshot
.read()
.top_level_packages()
.cloned()
.collect::<Vec<_>>()
} }
pub fn all_system_packages( pub fn all_system_packages(

View file

@ -1,6 +1,7 @@
// Copyright 2018-2025 the Deno authors. MIT license. // Copyright 2018-2025 the Deno authors. MIT license.
use std::fmt::Debug; use std::fmt::Debug;
use std::path::Path;
use std::path::PathBuf; use std::path::PathBuf;
use boxed_error::Boxed; use boxed_error::Boxed;
@ -14,11 +15,12 @@ use node_resolver::errors::PackageFolderResolveIoError;
use node_resolver::errors::PackageNotFoundError; use node_resolver::errors::PackageNotFoundError;
use node_resolver::errors::PackageResolveErrorKind; use node_resolver::errors::PackageResolveErrorKind;
use node_resolver::errors::PackageSubpathResolveError; use node_resolver::errors::PackageSubpathResolveError;
use node_resolver::InNpmPackageCheckerRc; use node_resolver::InNpmPackageChecker;
use node_resolver::IsBuiltInNodeModuleChecker; use node_resolver::IsBuiltInNodeModuleChecker;
use node_resolver::NodeResolution; use node_resolver::NodeResolution;
use node_resolver::NodeResolutionKind; use node_resolver::NodeResolutionKind;
use node_resolver::NodeResolverRc; use node_resolver::NodeResolverRc;
use node_resolver::NpmPackageFolderResolver;
use node_resolver::ResolutionMode; use node_resolver::ResolutionMode;
use sys_traits::FsCanonicalize; use sys_traits::FsCanonicalize;
use sys_traits::FsMetadata; use sys_traits::FsMetadata;
@ -35,10 +37,14 @@ pub use self::byonm::ByonmResolvePkgFolderFromDenoReqError;
pub use self::local::get_package_folder_id_folder_name; pub use self::local::get_package_folder_id_folder_name;
pub use self::local::normalize_pkg_name_for_node_modules_deno_folder; pub use self::local::normalize_pkg_name_for_node_modules_deno_folder;
use self::managed::create_managed_in_npm_pkg_checker; use self::managed::create_managed_in_npm_pkg_checker;
use self::managed::ManagedInNpmPackageChecker;
use self::managed::ManagedInNpmPkgCheckerCreateOptions; use self::managed::ManagedInNpmPkgCheckerCreateOptions;
pub use self::managed::ManagedNpmResolver; pub use self::managed::ManagedNpmResolver;
use self::managed::ManagedNpmResolverCreateOptions;
pub use self::managed::ManagedNpmResolverRc; pub use self::managed::ManagedNpmResolverRc;
use crate::sync::new_rc; use crate::sync::new_rc;
use crate::sync::MaybeSend;
use crate::sync::MaybeSync;
mod byonm; mod byonm;
mod local; mod local;
@ -49,14 +55,33 @@ pub enum CreateInNpmPkgCheckerOptions<'a> {
Byonm, Byonm,
} }
pub fn create_in_npm_pkg_checker( #[derive(Debug, Clone)]
options: CreateInNpmPkgCheckerOptions, pub enum DenoInNpmPackageChecker {
) -> InNpmPackageCheckerRc { Managed(ManagedInNpmPackageChecker),
Byonm(ByonmInNpmPackageChecker),
}
impl DenoInNpmPackageChecker {
pub fn new(options: CreateInNpmPkgCheckerOptions) -> Self {
match options { match options {
CreateInNpmPkgCheckerOptions::Managed(options) => { CreateInNpmPkgCheckerOptions::Managed(options) => {
new_rc(create_managed_in_npm_pkg_checker(options)) DenoInNpmPackageChecker::Managed(create_managed_in_npm_pkg_checker(
options,
))
}
CreateInNpmPkgCheckerOptions::Byonm => {
DenoInNpmPackageChecker::Byonm(ByonmInNpmPackageChecker)
}
}
}
}
impl InNpmPackageChecker for DenoInNpmPackageChecker {
fn in_npm_package(&self, specifier: &Url) -> bool {
match self {
DenoInNpmPackageChecker::Managed(c) => c.in_npm_package(specifier),
DenoInNpmPackageChecker::Byonm(c) => c.in_npm_package(specifier),
} }
CreateInNpmPkgCheckerOptions::Byonm => new_rc(ByonmInNpmPackageChecker),
} }
} }
@ -115,10 +140,22 @@ pub enum ResolvePkgFolderFromDenoReqError {
Byonm(byonm::ByonmResolvePkgFolderFromDenoReqError), Byonm(byonm::ByonmResolvePkgFolderFromDenoReqError),
} }
#[derive(Debug, Clone)] pub enum NpmResolverCreateOptions<
pub enum ByonmOrManagedNpmResolver< TSys: FsRead
TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir, + FsCanonicalize
+ FsMetadata
+ std::fmt::Debug
+ MaybeSend
+ MaybeSync
+ Clone
+ 'static,
> { > {
Managed(ManagedNpmResolverCreateOptions<TSys>),
Byonm(ByonmNpmResolverCreateOptions<TSys>),
}
#[derive(Debug, Clone)]
pub enum NpmResolver<TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir> {
/// The resolver when "bring your own node_modules" is enabled where Deno /// The resolver when "bring your own node_modules" is enabled where Deno
/// does not setup the node_modules directories automatically, but instead /// does not setup the node_modules directories automatically, but instead
/// uses what already exists on the file system. /// uses what already exists on the file system.
@ -126,57 +163,158 @@ pub enum ByonmOrManagedNpmResolver<
Managed(ManagedNpmResolverRc<TSys>), Managed(ManagedNpmResolverRc<TSys>),
} }
impl<TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir> impl<TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir> NpmResolver<TSys> {
ByonmOrManagedNpmResolver<TSys> pub fn new<
{ TCreateSys: FsCanonicalize
+ FsMetadata
+ FsRead
+ FsReadDir
+ std::fmt::Debug
+ MaybeSend
+ MaybeSync
+ Clone
+ 'static,
>(
options: NpmResolverCreateOptions<TCreateSys>,
) -> NpmResolver<TCreateSys> {
match options {
NpmResolverCreateOptions::Managed(options) => {
NpmResolver::Managed(new_rc(ManagedNpmResolver::<TCreateSys>::new::<
TCreateSys,
>(options)))
}
NpmResolverCreateOptions::Byonm(options) => {
NpmResolver::Byonm(new_rc(ByonmNpmResolver::new(options)))
}
}
}
pub fn is_byonm(&self) -> bool {
matches!(self, NpmResolver::Byonm(_))
}
pub fn is_managed(&self) -> bool {
matches!(self, NpmResolver::Managed(_))
}
pub fn as_managed(&self) -> Option<&ManagedNpmResolver<TSys>> {
match self {
NpmResolver::Managed(resolver) => Some(resolver),
NpmResolver::Byonm(_) => None,
}
}
pub fn root_node_modules_path(&self) -> Option<&Path> {
match self {
NpmResolver::Byonm(resolver) => resolver.root_node_modules_path(),
NpmResolver::Managed(resolver) => resolver.root_node_modules_path(),
}
}
pub fn resolve_pkg_folder_from_deno_module_req( pub fn resolve_pkg_folder_from_deno_module_req(
&self, &self,
req: &PackageReq, req: &PackageReq,
referrer: &Url, referrer: &Url,
) -> Result<PathBuf, ResolvePkgFolderFromDenoReqError> { ) -> Result<PathBuf, ResolvePkgFolderFromDenoReqError> {
match self { match self {
ByonmOrManagedNpmResolver::Byonm(byonm_resolver) => byonm_resolver NpmResolver::Byonm(byonm_resolver) => byonm_resolver
.resolve_pkg_folder_from_deno_module_req(req, referrer) .resolve_pkg_folder_from_deno_module_req(req, referrer)
.map_err(ResolvePkgFolderFromDenoReqError::Byonm), .map_err(ResolvePkgFolderFromDenoReqError::Byonm),
ByonmOrManagedNpmResolver::Managed(managed_resolver) => managed_resolver NpmResolver::Managed(managed_resolver) => managed_resolver
.resolve_pkg_folder_from_deno_module_req(req, referrer) .resolve_pkg_folder_from_deno_module_req(req, referrer)
.map_err(ResolvePkgFolderFromDenoReqError::Managed), .map_err(ResolvePkgFolderFromDenoReqError::Managed),
} }
} }
} }
impl<TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir>
NpmPackageFolderResolver for NpmResolver<TSys>
{
fn resolve_package_folder_from_package(
&self,
specifier: &str,
referrer: &Url,
) -> Result<PathBuf, node_resolver::errors::PackageFolderResolveError> {
match self {
NpmResolver::Byonm(byonm_resolver) => {
byonm_resolver.resolve_package_folder_from_package(specifier, referrer)
}
NpmResolver::Managed(managed_resolver) => managed_resolver
.resolve_package_folder_from_package(specifier, referrer),
}
}
}
pub struct NpmReqResolverOptions< pub struct NpmReqResolverOptions<
TInNpmPackageChecker: InNpmPackageChecker,
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker, TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver: NpmPackageFolderResolver,
TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir, TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir,
> { > {
pub in_npm_pkg_checker: InNpmPackageCheckerRc, pub in_npm_pkg_checker: TInNpmPackageChecker,
pub node_resolver: NodeResolverRc<TIsBuiltInNodeModuleChecker, TSys>, pub node_resolver: NodeResolverRc<
pub npm_resolver: ByonmOrManagedNpmResolver<TSys>, TInNpmPackageChecker,
TIsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver,
TSys,
>,
pub npm_resolver: NpmResolver<TSys>,
pub sys: TSys, pub sys: TSys,
} }
#[allow(clippy::disallowed_types)] #[allow(clippy::disallowed_types)]
pub type NpmReqResolverRc<TIsBuiltInNodeModuleChecker, TSys> = pub type NpmReqResolverRc<
crate::sync::MaybeArc<NpmReqResolver<TIsBuiltInNodeModuleChecker, TSys>>; TInNpmPackageChecker,
TIsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver,
TSys,
> = crate::sync::MaybeArc<
NpmReqResolver<
TInNpmPackageChecker,
TIsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver,
TSys,
>,
>;
#[derive(Debug)] #[derive(Debug)]
pub struct NpmReqResolver< pub struct NpmReqResolver<
TInNpmPackageChecker: InNpmPackageChecker,
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker, TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver: NpmPackageFolderResolver,
TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir, TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir,
> { > {
sys: TSys, sys: TSys,
in_npm_pkg_checker: InNpmPackageCheckerRc, in_npm_pkg_checker: TInNpmPackageChecker,
node_resolver: NodeResolverRc<TIsBuiltInNodeModuleChecker, TSys>, node_resolver: NodeResolverRc<
npm_resolver: ByonmOrManagedNpmResolver<TSys>, TInNpmPackageChecker,
TIsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver,
TSys,
>,
npm_resolver: NpmResolver<TSys>,
} }
impl< impl<
TInNpmPackageChecker: InNpmPackageChecker,
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker, TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver: NpmPackageFolderResolver,
TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir, TSys: FsCanonicalize + FsMetadata + FsRead + FsReadDir,
> NpmReqResolver<TIsBuiltInNodeModuleChecker, TSys> >
NpmReqResolver<
TInNpmPackageChecker,
TIsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver,
TSys,
>
{ {
pub fn new( pub fn new(
options: NpmReqResolverOptions<TIsBuiltInNodeModuleChecker, TSys>, options: NpmReqResolverOptions<
TInNpmPackageChecker,
TIsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver,
TSys,
>,
) -> Self { ) -> Self {
Self { Self {
sys: options.sys, sys: options.sys,
@ -224,7 +362,7 @@ impl<
match resolution_result { match resolution_result {
Ok(url) => Ok(url), Ok(url) => Ok(url),
Err(err) => { Err(err) => {
if matches!(self.npm_resolver, ByonmOrManagedNpmResolver::Byonm(_)) { if matches!(self.npm_resolver, NpmResolver::Byonm(_)) {
let package_json_path = package_folder.join("package.json"); let package_json_path = package_folder.join("package.json");
if !self.sys.fs_exists_no_err(&package_json_path) { if !self.sys.fs_exists_no_err(&package_json_path) {
return Err( return Err(
@ -292,9 +430,8 @@ impl<
.into_box(), .into_box(),
); );
} }
if let ByonmOrManagedNpmResolver::Byonm( if let NpmResolver::Byonm(byonm_npm_resolver) =
byonm_npm_resolver, &self.npm_resolver
) = &self.npm_resolver
{ {
if byonm_npm_resolver if byonm_npm_resolver
.find_ancestor_package_json_with_dep( .find_ancestor_package_json_with_dep(

View file

@ -20,11 +20,11 @@ use sys_traits::FsMetadata;
use sys_traits::FsRead; use sys_traits::FsRead;
use url::Url; use url::Url;
use crate::npm::InNpmPackageCheckerRc;
use crate::resolution::NodeResolverRc; use crate::resolution::NodeResolverRc;
use crate::InNpmPackageChecker;
use crate::IsBuiltInNodeModuleChecker; use crate::IsBuiltInNodeModuleChecker;
use crate::NodeResolutionKind; use crate::NodeResolutionKind;
use crate::NpmPackageFolderResolverRc; use crate::NpmPackageFolderResolver;
use crate::PackageJsonResolverRc; use crate::PackageJsonResolverRc;
use crate::PathClean; use crate::PathClean;
use crate::ResolutionMode; use crate::ResolutionMode;
@ -62,28 +62,49 @@ pub trait CjsCodeAnalyzer {
pub struct NodeCodeTranslator< pub struct NodeCodeTranslator<
TCjsCodeAnalyzer: CjsCodeAnalyzer, TCjsCodeAnalyzer: CjsCodeAnalyzer,
TInNpmPackageChecker: InNpmPackageChecker,
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker, TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver: NpmPackageFolderResolver,
TSys: FsCanonicalize + FsMetadata + FsRead, TSys: FsCanonicalize + FsMetadata + FsRead,
> { > {
cjs_code_analyzer: TCjsCodeAnalyzer, cjs_code_analyzer: TCjsCodeAnalyzer,
in_npm_pkg_checker: InNpmPackageCheckerRc, in_npm_pkg_checker: TInNpmPackageChecker,
node_resolver: NodeResolverRc<TIsBuiltInNodeModuleChecker, TSys>, node_resolver: NodeResolverRc<
npm_resolver: NpmPackageFolderResolverRc, TInNpmPackageChecker,
TIsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver,
TSys,
>,
npm_resolver: TNpmPackageFolderResolver,
pkg_json_resolver: PackageJsonResolverRc<TSys>, pkg_json_resolver: PackageJsonResolverRc<TSys>,
sys: TSys, sys: TSys,
} }
impl< impl<
TCjsCodeAnalyzer: CjsCodeAnalyzer, TCjsCodeAnalyzer: CjsCodeAnalyzer,
TInNpmPackageChecker: InNpmPackageChecker,
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker, TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver: NpmPackageFolderResolver,
TSys: FsCanonicalize + FsMetadata + FsRead, TSys: FsCanonicalize + FsMetadata + FsRead,
> NodeCodeTranslator<TCjsCodeAnalyzer, TIsBuiltInNodeModuleChecker, TSys> >
NodeCodeTranslator<
TCjsCodeAnalyzer,
TInNpmPackageChecker,
TIsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver,
TSys,
>
{ {
pub fn new( pub fn new(
cjs_code_analyzer: TCjsCodeAnalyzer, cjs_code_analyzer: TCjsCodeAnalyzer,
in_npm_pkg_checker: InNpmPackageCheckerRc, in_npm_pkg_checker: TInNpmPackageChecker,
node_resolver: NodeResolverRc<TIsBuiltInNodeModuleChecker, TSys>, node_resolver: NodeResolverRc<
npm_resolver: NpmPackageFolderResolverRc, TInNpmPackageChecker,
TIsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver,
TSys,
>,
npm_resolver: TNpmPackageFolderResolver,
pkg_json_resolver: PackageJsonResolverRc<TSys>, pkg_json_resolver: PackageJsonResolverRc<TSys>,
sys: TSys, sys: TSys,
) -> Self { ) -> Self {

View file

@ -14,9 +14,7 @@ mod sync;
pub use deno_package_json::PackageJson; pub use deno_package_json::PackageJson;
pub use npm::InNpmPackageChecker; pub use npm::InNpmPackageChecker;
pub use npm::InNpmPackageCheckerRc;
pub use npm::NpmPackageFolderResolver; pub use npm::NpmPackageFolderResolver;
pub use npm::NpmPackageFolderResolverRc;
pub use package_json::PackageJsonResolver; pub use package_json::PackageJsonResolver;
pub use package_json::PackageJsonResolverRc; pub use package_json::PackageJsonResolverRc;
pub use package_json::PackageJsonThreadLocalCache; pub use package_json::PackageJsonThreadLocalCache;

View file

@ -9,16 +9,8 @@ use url::Url;
use crate::errors; use crate::errors;
use crate::path::PathClean; use crate::path::PathClean;
use crate::sync::MaybeSend;
use crate::sync::MaybeSync;
#[allow(clippy::disallowed_types)] pub trait NpmPackageFolderResolver {
pub type NpmPackageFolderResolverRc =
crate::sync::MaybeArc<dyn NpmPackageFolderResolver>;
pub trait NpmPackageFolderResolver:
std::fmt::Debug + MaybeSend + MaybeSync
{
/// Resolves an npm package folder path from the specified referrer. /// Resolves an npm package folder path from the specified referrer.
fn resolve_package_folder_from_package( fn resolve_package_folder_from_package(
&self, &self,
@ -27,11 +19,8 @@ pub trait NpmPackageFolderResolver:
) -> Result<PathBuf, errors::PackageFolderResolveError>; ) -> Result<PathBuf, errors::PackageFolderResolveError>;
} }
#[allow(clippy::disallowed_types)]
pub type InNpmPackageCheckerRc = crate::sync::MaybeArc<dyn InNpmPackageChecker>;
/// Checks if a provided specifier is in an npm package. /// Checks if a provided specifier is in an npm package.
pub trait InNpmPackageChecker: std::fmt::Debug + MaybeSend + MaybeSync { pub trait InNpmPackageChecker {
fn in_npm_package(&self, specifier: &Url) -> bool; fn in_npm_package(&self, specifier: &Url) -> bool;
fn in_npm_package_at_dir_path(&self, path: &Path) -> bool { fn in_npm_package_at_dir_path(&self, path: &Path) -> bool {

View file

@ -46,8 +46,8 @@ use crate::errors::TypesNotFoundError;
use crate::errors::TypesNotFoundErrorData; use crate::errors::TypesNotFoundErrorData;
use crate::errors::UnsupportedDirImportError; use crate::errors::UnsupportedDirImportError;
use crate::errors::UnsupportedEsmUrlSchemeError; use crate::errors::UnsupportedEsmUrlSchemeError;
use crate::npm::InNpmPackageCheckerRc; use crate::InNpmPackageChecker;
use crate::NpmPackageFolderResolverRc; use crate::NpmPackageFolderResolver;
use crate::PackageJsonResolverRc; use crate::PackageJsonResolverRc;
use crate::PathClean; use crate::PathClean;
@ -137,31 +137,52 @@ pub trait IsBuiltInNodeModuleChecker: std::fmt::Debug {
} }
#[allow(clippy::disallowed_types)] #[allow(clippy::disallowed_types)]
pub type NodeResolverRc<TIsBuiltInNodeModuleChecker, TSys> = pub type NodeResolverRc<
crate::sync::MaybeArc<NodeResolver<TIsBuiltInNodeModuleChecker, TSys>>; TInNpmPackageChecker,
TIsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver,
TSys,
> = crate::sync::MaybeArc<
NodeResolver<
TInNpmPackageChecker,
TIsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver,
TSys,
>,
>;
#[derive(Debug)] #[derive(Debug)]
pub struct NodeResolver< pub struct NodeResolver<
TInNpmPackageChecker: InNpmPackageChecker,
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker, TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver: NpmPackageFolderResolver,
TSys: FsCanonicalize + FsMetadata + FsRead, TSys: FsCanonicalize + FsMetadata + FsRead,
> { > {
in_npm_pkg_checker: InNpmPackageCheckerRc, in_npm_pkg_checker: TInNpmPackageChecker,
is_built_in_node_module_checker: TIsBuiltInNodeModuleChecker, is_built_in_node_module_checker: TIsBuiltInNodeModuleChecker,
npm_pkg_folder_resolver: NpmPackageFolderResolverRc, npm_pkg_folder_resolver: TNpmPackageFolderResolver,
pkg_json_resolver: PackageJsonResolverRc<TSys>, pkg_json_resolver: PackageJsonResolverRc<TSys>,
sys: TSys, sys: TSys,
conditions_from_resolution_mode: ConditionsFromResolutionMode, conditions_from_resolution_mode: ConditionsFromResolutionMode,
} }
impl< impl<
TInNpmPackageChecker: InNpmPackageChecker,
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker, TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver: NpmPackageFolderResolver,
TSys: FsCanonicalize + FsMetadata + FsRead, TSys: FsCanonicalize + FsMetadata + FsRead,
> NodeResolver<TIsBuiltInNodeModuleChecker, TSys> >
NodeResolver<
TInNpmPackageChecker,
TIsBuiltInNodeModuleChecker,
TNpmPackageFolderResolver,
TSys,
>
{ {
pub fn new( pub fn new(
in_npm_pkg_checker: InNpmPackageCheckerRc, in_npm_pkg_checker: TInNpmPackageChecker,
is_built_in_node_module_checker: TIsBuiltInNodeModuleChecker, is_built_in_node_module_checker: TIsBuiltInNodeModuleChecker,
npm_pkg_folder_resolver: NpmPackageFolderResolverRc, npm_pkg_folder_resolver: TNpmPackageFolderResolver,
pkg_json_resolver: PackageJsonResolverRc<TSys>, pkg_json_resolver: PackageJsonResolverRc<TSys>,
sys: TSys, sys: TSys,
conditions_from_resolution_mode: ConditionsFromResolutionMode, conditions_from_resolution_mode: ConditionsFromResolutionMode,
@ -444,6 +465,17 @@ impl<
Ok(url) Ok(url)
} }
/// Resolves an npm package folder path from the specified referrer.
pub fn resolve_package_folder_from_package(
&self,
specifier: &str,
referrer: &Url,
) -> Result<PathBuf, errors::PackageFolderResolveError> {
self
.npm_pkg_folder_resolver
.resolve_package_folder_from_package(specifier, referrer)
}
/// Checks if the resolved file has a corresponding declaration file. /// Checks if the resolved file has a corresponding declaration file.
fn path_to_declaration_url( fn path_to_declaration_url(
&self, &self,

View file

@ -6,17 +6,10 @@ pub use inner::*;
mod inner { mod inner {
#![allow(clippy::disallowed_types)] #![allow(clippy::disallowed_types)]
pub use core::marker::Send as MaybeSend;
pub use core::marker::Sync as MaybeSync;
pub use std::sync::Arc as MaybeArc; pub use std::sync::Arc as MaybeArc;
} }
#[cfg(not(feature = "sync"))] #[cfg(not(feature = "sync"))]
mod inner { mod inner {
pub use std::rc::Rc as MaybeArc; pub use std::rc::Rc as MaybeArc;
pub trait MaybeSync {}
impl<T> MaybeSync for T where T: ?Sized {}
pub trait MaybeSend {}
impl<T> MaybeSend for T where T: ?Sized {}
} }

View file

@ -49,6 +49,7 @@ deno_core.workspace = true
deno_cron.workspace = true deno_cron.workspace = true
deno_crypto.workspace = true deno_crypto.workspace = true
deno_fetch.workspace = true deno_fetch.workspace = true
deno_os.workspace = true
deno_ffi.workspace = true deno_ffi.workspace = true
deno_fs = { workspace = true, features = ["sync_fs"] } deno_fs = { workspace = true, features = ["sync_fs"] }
deno_http.workspace = true deno_http.workspace = true
@ -89,8 +90,10 @@ deno_kv.workspace = true
deno_napi.workspace = true deno_napi.workspace = true
deno_net.workspace = true deno_net.workspace = true
deno_node.workspace = true deno_node.workspace = true
deno_os.workspace = true
deno_path_util.workspace = true deno_path_util.workspace = true
deno_permissions.workspace = true deno_permissions.workspace = true
deno_resolver.workspace = true
deno_telemetry.workspace = true deno_telemetry.workspace = true
deno_terminal.workspace = true deno_terminal.workspace = true
deno_tls.workspace = true deno_tls.workspace = true
@ -113,7 +116,6 @@ hyper-util.workspace = true
hyper_v014 = { workspace = true, features = ["server", "stream", "http1", "http2", "runtime"] } hyper_v014 = { workspace = true, features = ["server", "stream", "http1", "http2", "runtime"] }
libc.workspace = true libc.workspace = true
log.workspace = true log.workspace = true
netif = "0.1.6"
notify.workspace = true notify.workspace = true
once_cell.workspace = true once_cell.workspace = true
percent-encoding.workspace = true percent-encoding.workspace = true
@ -121,8 +123,6 @@ regex.workspace = true
rustyline = { workspace = true, features = ["custom-bindings"] } rustyline = { workspace = true, features = ["custom-bindings"] }
same-file = "1.0.6" same-file = "1.0.6"
serde.workspace = true serde.workspace = true
signal-hook = "0.3.17"
signal-hook-registry = "1.4.0"
sys_traits.workspace = true sys_traits.workspace = true
tempfile.workspace = true tempfile.workspace = true
thiserror.workspace = true thiserror.workspace = true

View file

@ -12,6 +12,8 @@ use deno_core::op2;
use deno_core::FsModuleLoader; use deno_core::FsModuleLoader;
use deno_core::ModuleSpecifier; use deno_core::ModuleSpecifier;
use deno_fs::RealFs; use deno_fs::RealFs;
use deno_resolver::npm::DenoInNpmPackageChecker;
use deno_resolver::npm::NpmResolver;
use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::deno_permissions::PermissionsContainer;
use deno_runtime::permissions::RuntimePermissionDescriptorParser; use deno_runtime::permissions::RuntimePermissionDescriptorParser;
use deno_runtime::worker::MainWorker; use deno_runtime::worker::MainWorker;
@ -41,8 +43,12 @@ async fn main() -> Result<(), AnyError> {
RuntimePermissionDescriptorParser::new(sys_traits::impls::RealSys), RuntimePermissionDescriptorParser::new(sys_traits::impls::RealSys),
); );
let mut worker = MainWorker::bootstrap_from_options( let mut worker = MainWorker::bootstrap_from_options(
main_module.clone(), &main_module,
WorkerServiceOptions::<sys_traits::impls::RealSys> { WorkerServiceOptions::<
DenoInNpmPackageChecker,
NpmResolver<sys_traits::impls::RealSys>,
sys_traits::impls::RealSys,
> {
module_loader: Rc::new(FsModuleLoader), module_loader: Rc::new(FsModuleLoader),
permissions: PermissionsContainer::allow_all(permission_desc_parser), permissions: PermissionsContainer::allow_all(permission_desc_parser),
blob_store: Default::default(), blob_store: Default::default(),

View file

@ -21,10 +21,10 @@ import * as version from "ext:runtime/01_version.ts";
import * as permissions from "ext:runtime/10_permissions.js"; import * as permissions from "ext:runtime/10_permissions.js";
import * as io from "ext:deno_io/12_io.js"; import * as io from "ext:deno_io/12_io.js";
import * as fs from "ext:deno_fs/30_fs.js"; import * as fs from "ext:deno_fs/30_fs.js";
import * as os from "ext:runtime/30_os.js"; import * as os from "ext:deno_os/30_os.js";
import * as fsEvents from "ext:runtime/40_fs_events.js"; import * as fsEvents from "ext:runtime/40_fs_events.js";
import * as process from "ext:runtime/40_process.js"; import * as process from "ext:runtime/40_process.js";
import * as signals from "ext:runtime/40_signals.js"; import * as signals from "ext:deno_os/40_signals.js";
import * as tty from "ext:runtime/40_tty.js"; import * as tty from "ext:runtime/40_tty.js";
import * as kv from "ext:deno_kv/01_db.ts"; import * as kv from "ext:deno_kv/01_db.ts";
import * as cron from "ext:deno_cron/01_cron.ts"; import * as cron from "ext:deno_cron/01_cron.ts";

View file

@ -55,7 +55,7 @@ import { registerDeclarativeServer } from "ext:deno_http/00_serve.ts";
import * as event from "ext:deno_web/02_event.js"; import * as event from "ext:deno_web/02_event.js";
import * as location from "ext:deno_web/12_location.js"; import * as location from "ext:deno_web/12_location.js";
import * as version from "ext:runtime/01_version.ts"; import * as version from "ext:runtime/01_version.ts";
import * as os from "ext:runtime/30_os.js"; import * as os from "ext:deno_os/30_os.js";
import * as timers from "ext:deno_web/02_timers.js"; import * as timers from "ext:deno_web/02_timers.js";
import { import {
getDefaultInspectOptions, getDefaultInspectOptions,

View file

@ -16,7 +16,9 @@ pub use deno_kv;
pub use deno_napi; pub use deno_napi;
pub use deno_net; pub use deno_net;
pub use deno_node; pub use deno_node;
pub use deno_os;
pub use deno_permissions; pub use deno_permissions;
pub use deno_telemetry;
pub use deno_terminal::colors; pub use deno_terminal::colors;
pub use deno_tls; pub use deno_tls;
pub use deno_url; pub use deno_url;
@ -33,9 +35,7 @@ pub mod inspector_server;
pub mod js; pub mod js;
pub mod ops; pub mod ops;
pub mod permissions; pub mod permissions;
pub mod signal;
pub mod snapshot; pub mod snapshot;
pub mod sys_info;
pub mod tokio_util; pub mod tokio_util;
pub mod web_worker; pub mod web_worker;
pub mod worker; pub mod worker;
@ -46,6 +46,7 @@ pub use worker_bootstrap::WorkerExecutionMode;
pub use worker_bootstrap::WorkerLogLevel; pub use worker_bootstrap::WorkerLogLevel;
pub mod shared; pub mod shared;
pub use deno_os::exit;
pub use shared::runtime; pub use shared::runtime;
pub struct UnstableGranularFlag { pub struct UnstableGranularFlag {
@ -147,12 +148,6 @@ pub static UNSTABLE_GRANULAR_FLAGS: &[UnstableGranularFlag] = &[
}, },
]; ];
pub fn exit(code: i32) -> ! {
deno_telemetry::flush();
#[allow(clippy::disallowed_methods)]
std::process::exit(code);
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;

View file

@ -3,11 +3,9 @@
pub mod bootstrap; pub mod bootstrap;
pub mod fs_events; pub mod fs_events;
pub mod http; pub mod http;
pub mod os;
pub mod permissions; pub mod permissions;
pub mod process; pub mod process;
pub mod runtime; pub mod runtime;
pub mod signal;
pub mod tty; pub mod tty;
pub mod web_worker; pub mod web_worker;
pub mod worker_host; pub mod worker_host;

View file

@ -31,14 +31,13 @@ use deno_io::ChildStderrResource;
use deno_io::ChildStdinResource; use deno_io::ChildStdinResource;
use deno_io::ChildStdoutResource; use deno_io::ChildStdoutResource;
use deno_io::IntoRawIoHandle; use deno_io::IntoRawIoHandle;
use deno_os::SignalError;
use deno_permissions::PermissionsContainer; use deno_permissions::PermissionsContainer;
use deno_permissions::RunQueryDescriptor; use deno_permissions::RunQueryDescriptor;
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
use tokio::process::Command; use tokio::process::Command;
use crate::ops::signal::SignalError;
pub const UNSTABLE_FEATURE_NAME: &str = "process"; pub const UNSTABLE_FEATURE_NAME: &str = "process";
#[derive(Copy, Clone, Eq, PartialEq, Deserialize)] #[derive(Copy, Clone, Eq, PartialEq, Deserialize)]
@ -296,7 +295,7 @@ impl TryFrom<ExitStatus> for ChildStatus {
success: false, success: false,
code: 128 + signal, code: 128 + signal,
#[cfg(unix)] #[cfg(unix)]
signal: Some(crate::signal::signal_int_to_str(signal)?.to_string()), signal: Some(deno_os::signal::signal_int_to_str(signal)?.to_string()),
#[cfg(not(unix))] #[cfg(not(unix))]
signal: None, signal: None,
} }
@ -1116,7 +1115,7 @@ mod deprecated {
#[cfg(unix)] #[cfg(unix)]
pub fn kill(pid: i32, signal: &str) -> Result<(), ProcessError> { pub fn kill(pid: i32, signal: &str) -> Result<(), ProcessError> {
let signo = crate::signal::signal_str_to_int(signal) let signo = deno_os::signal::signal_str_to_int(signal)
.map_err(SignalError::InvalidSignalStr)?; .map_err(SignalError::InvalidSignalStr)?;
use nix::sys::signal::kill as unix_kill; use nix::sys::signal::kill as unix_kill;
use nix::sys::signal::Signal; use nix::sys::signal::Signal;
@ -1144,7 +1143,7 @@ mod deprecated {
if !matches!(signal, "SIGKILL" | "SIGTERM") { if !matches!(signal, "SIGKILL" | "SIGTERM") {
Err( Err(
SignalError::InvalidSignalStr(crate::signal::InvalidSignalStrError( SignalError::InvalidSignalStr(deno_os::signal::InvalidSignalStrError(
signal.to_string(), signal.to_string(),
)) ))
.into(), .into(),

View file

@ -42,10 +42,8 @@ extension!(runtime,
"06_util.js", "06_util.js",
"10_permissions.js", "10_permissions.js",
"11_workers.js", "11_workers.js",
"30_os.js",
"40_fs_events.js", "40_fs_events.js",
"40_process.js", "40_process.js",
"40_signals.js",
"40_tty.js", "40_tty.js",
"41_prompt.js", "41_prompt.js",
"90_deno_ns.js", "90_deno_ns.js",

Some files were not shown because too many files have changed in this diff Show more