From 386d5c8310891c5dc9627abbf2374e60bb4e50d2 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Thu, 6 Jun 2024 23:37:53 -0400 Subject: [PATCH] refactor: remove `PermissionsContainer` in deno_runtime (#24119) Also removes permissions being passed in for node resolution. It was completely useless because we only checked it for reading package.json files, but Deno reading package.json files for resolution is perfectly fine. My guess is this is also a perf improvement because Deno is doing less work. --- Cargo.lock | 8 + cli/args/flags.rs | 4 +- cli/args/import_map.rs | 2 +- cli/args/mod.rs | 2 +- cli/cache/mod.rs | 2 +- cli/file_fetcher.rs | 2 +- cli/graph_container.rs | 2 +- cli/graph_util.rs | 2 +- cli/jsr.rs | 2 +- cli/lsp/config.rs | 2 +- cli/lsp/jsr.rs | 2 +- cli/lsp/npm.rs | 2 +- cli/lsp/registries.rs | 2 +- cli/lsp/resolver.rs | 14 +- cli/lsp/testing/execution.rs | 2 +- cli/main.rs | 2 +- cli/module_loader.rs | 29 +-- cli/npm/byonm.rs | 2 +- cli/npm/managed/mod.rs | 2 +- cli/npm/managed/resolvers/common.rs | 4 +- cli/npm/managed/resolvers/global.rs | 2 +- cli/npm/managed/resolvers/local.rs | 2 +- cli/npm/mod.rs | 2 +- cli/ops/bench.rs | 8 +- cli/ops/testing.rs | 8 +- cli/resolver.rs | 42 ++--- cli/standalone/mod.rs | 20 +-- cli/tools/bench/mod.rs | 4 +- cli/tools/jupyter/mod.rs | 4 +- cli/tools/repl/mod.rs | 4 +- cli/tools/run/mod.rs | 4 +- cli/tools/test/mod.rs | 4 +- cli/tsc/mod.rs | 10 +- cli/worker.rs | 23 +-- ext/fetch/Cargo.toml | 1 + ext/fetch/lib.rs | 20 +++ ext/ffi/Cargo.toml | 1 + ext/ffi/lib.rs | 7 + ext/fs/Cargo.toml | 1 + ext/fs/lib.rs | 89 ++++++++- ext/kv/Cargo.toml | 1 + ext/kv/remote.rs | 16 ++ ext/kv/sqlite.rs | 12 ++ ext/napi/Cargo.toml | 1 + ext/napi/lib.rs | 9 + ext/net/Cargo.toml | 1 + ext/net/lib.rs | 29 +++ ext/node/analyze.rs | 12 +- ext/node/global.rs | 5 +- ext/node/lib.rs | 78 ++++++-- ext/node/ops/require.rs | 37 ++-- ext/node/ops/worker_threads.rs | 9 +- ext/node/package_json.rs | 2 +- ext/node/resolution.rs | 106 ++++------- ext/web/Cargo.toml | 1 + ext/web/timers.rs | 7 + ext/websocket/Cargo.toml | 1 + ext/websocket/lib.rs | 11 ++ runtime/examples/extension/main.rs | 2 +- runtime/lib.rs | 1 - runtime/ops/fs_events.rs | 2 +- runtime/ops/os/mod.rs | 2 +- runtime/ops/process.rs | 2 +- runtime/ops/runtime.rs | 2 +- runtime/ops/worker_host.rs | 8 +- runtime/permissions.rs | 268 ---------------------------- runtime/snapshot.rs | 8 +- runtime/web_worker.rs | 6 +- runtime/worker.rs | 8 +- 69 files changed, 428 insertions(+), 564 deletions(-) delete mode 100644 runtime/permissions.rs diff --git a/Cargo.lock b/Cargo.lock index 6b07f078e8..142788eb30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1432,6 +1432,7 @@ dependencies = [ "bytes", "data-url", "deno_core", + "deno_permissions", "deno_tls", "dyn-clone", "http 0.2.12", @@ -1447,6 +1448,7 @@ name = "deno_ffi" version = "0.142.0" dependencies = [ "deno_core", + "deno_permissions", "dlopen2", "dynasmrt", "libffi", @@ -1466,6 +1468,7 @@ dependencies = [ "base32", "deno_core", "deno_io", + "deno_permissions", "filetime", "junction", "libc", @@ -1572,6 +1575,7 @@ dependencies = [ "deno_core", "deno_fetch", "deno_node", + "deno_permissions", "deno_tls", "denokv_proto", "denokv_remote", @@ -1631,6 +1635,7 @@ name = "deno_napi" version = "0.85.0" dependencies = [ "deno_core", + "deno_permissions", "libloading 0.7.4", ] @@ -1652,6 +1657,7 @@ name = "deno_net" version = "0.147.0" dependencies = [ "deno_core", + "deno_permissions", "deno_tls", "pin-project", "rustls-tokio-stream", @@ -1928,6 +1934,7 @@ dependencies = [ "deno_bench_util", "deno_console", "deno_core", + "deno_permissions", "deno_url", "deno_webidl", "encoding_rs", @@ -1965,6 +1972,7 @@ dependencies = [ "bytes", "deno_core", "deno_net", + "deno_permissions", "deno_tls", "fastwebsockets", "h2 0.4.4", diff --git a/cli/args/flags.rs b/cli/args/flags.rs index 03d19746a1..711ec4c612 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -17,8 +17,8 @@ use deno_core::error::AnyError; use deno_core::resolve_url_or_path; use deno_core::url::Url; use deno_graph::GraphKind; -use deno_runtime::permissions::parse_sys_kind; -use deno_runtime::permissions::PermissionsOptions; +use deno_runtime::deno_permissions::parse_sys_kind; +use deno_runtime::deno_permissions::PermissionsOptions; use log::debug; use log::Level; use serde::Deserialize; diff --git a/cli/args/import_map.rs b/cli/args/import_map.rs index 767d0f770b..2dc5a21d1a 100644 --- a/cli/args/import_map.rs +++ b/cli/args/import_map.rs @@ -4,7 +4,7 @@ use deno_core::anyhow::Context; use deno_core::error::AnyError; use deno_core::serde_json; use deno_core::url::Url; -use deno_runtime::permissions::PermissionsContainer; +use deno_runtime::deno_permissions::PermissionsContainer; use import_map::ImportMap; use import_map::ImportMapDiagnostic; use log::warn; diff --git a/cli/args/mod.rs b/cli/args/mod.rs index d5e37acc8b..7422498355 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -47,13 +47,13 @@ use deno_core::parking_lot::Mutex; use deno_core::serde_json; use deno_core::url::Url; use deno_runtime::deno_node::PackageJson; +use deno_runtime::deno_permissions::PermissionsOptions; use deno_runtime::deno_tls::deno_native_certs::load_native_certs; use deno_runtime::deno_tls::rustls; use deno_runtime::deno_tls::rustls::RootCertStore; use deno_runtime::deno_tls::rustls_pemfile; use deno_runtime::deno_tls::webpki_roots; use deno_runtime::inspector_server::InspectorServer; -use deno_runtime::permissions::PermissionsOptions; use deno_terminal::colors; use dotenvy::from_filename; use once_cell::sync::Lazy; diff --git a/cli/cache/mod.rs b/cli/cache/mod.rs index aaaa427d7e..a8c60e97a2 100644 --- a/cli/cache/mod.rs +++ b/cli/cache/mod.rs @@ -17,7 +17,7 @@ use deno_graph::source::CacheInfo; use deno_graph::source::LoadFuture; use deno_graph::source::LoadResponse; use deno_graph::source::Loader; -use deno_runtime::permissions::PermissionsContainer; +use deno_runtime::deno_permissions::PermissionsContainer; use std::collections::HashMap; use std::path::Path; use std::path::PathBuf; diff --git a/cli/file_fetcher.rs b/cli/file_fetcher.rs index 0e0589d346..19acf2e2b8 100644 --- a/cli/file_fetcher.rs +++ b/cli/file_fetcher.rs @@ -22,8 +22,8 @@ use deno_core::url::Url; use deno_core::ModuleSpecifier; use deno_graph::source::LoaderChecksum; +use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::deno_web::BlobStore; -use deno_runtime::permissions::PermissionsContainer; use log::debug; use std::borrow::Cow; use std::collections::HashMap; diff --git a/cli/graph_container.rs b/cli/graph_container.rs index ec18ffaab4..40ccda9b20 100644 --- a/cli/graph_container.rs +++ b/cli/graph_container.rs @@ -8,7 +8,7 @@ use deno_core::parking_lot::RwLock; use deno_core::resolve_url_or_path; use deno_graph::ModuleGraph; use deno_runtime::colors; -use deno_runtime::permissions::PermissionsContainer; +use deno_runtime::deno_permissions::PermissionsContainer; use crate::args::CliOptions; use crate::module_loader::ModuleLoadPreparer; diff --git a/cli/graph_util.rs b/cli/graph_util.rs index 5e587b0d41..502702b075 100644 --- a/cli/graph_util.rs +++ b/cli/graph_util.rs @@ -41,7 +41,7 @@ use deno_graph::ResolutionError; use deno_graph::SpecifierError; use deno_runtime::deno_fs::FileSystem; use deno_runtime::deno_node; -use deno_runtime::permissions::PermissionsContainer; +use deno_runtime::deno_permissions::PermissionsContainer; use deno_semver::package::PackageNv; use deno_semver::package::PackageReq; use import_map::ImportMapError; diff --git a/cli/jsr.rs b/cli/jsr.rs index af0ace404e..e582ab9f0e 100644 --- a/cli/jsr.rs +++ b/cli/jsr.rs @@ -10,7 +10,7 @@ use deno_core::ModuleSpecifier; use deno_graph::packages::JsrPackageInfo; use deno_graph::packages::JsrPackageVersionInfo; use deno_lockfile::Lockfile; -use deno_runtime::permissions::PermissionsContainer; +use deno_runtime::deno_permissions::PermissionsContainer; use deno_semver::jsr::JsrPackageReqReference; use deno_semver::package::PackageNv; use deno_semver::package::PackageReq; diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs index 449051931b..f033888957 100644 --- a/cli/lsp/config.rs +++ b/cli/lsp/config.rs @@ -29,8 +29,8 @@ use deno_lint::linter::LintConfig; use deno_lockfile::Lockfile; use deno_npm::npm_rc::ResolvedNpmRc; use deno_runtime::deno_node::PackageJson; +use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::fs_util::specifier_to_file_path; -use deno_runtime::permissions::PermissionsContainer; use import_map::ImportMap; use lsp::Url; use lsp_types::ClientCapabilities; diff --git a/cli/lsp/jsr.rs b/cli/lsp/jsr.rs index a7b2f46acb..27db4b0c8d 100644 --- a/cli/lsp/jsr.rs +++ b/cli/lsp/jsr.rs @@ -7,7 +7,7 @@ use dashmap::DashMap; use deno_core::anyhow::anyhow; use deno_core::error::AnyError; use deno_core::serde_json; -use deno_runtime::permissions::PermissionsContainer; +use deno_runtime::deno_permissions::PermissionsContainer; use deno_semver::package::PackageNv; use deno_semver::Version; use serde::Deserialize; diff --git a/cli/lsp/npm.rs b/cli/lsp/npm.rs index d051237fbc..e5aa337440 100644 --- a/cli/lsp/npm.rs +++ b/cli/lsp/npm.rs @@ -4,7 +4,7 @@ use dashmap::DashMap; use deno_core::anyhow::anyhow; use deno_core::error::AnyError; use deno_core::serde_json; -use deno_runtime::permissions::PermissionsContainer; +use deno_runtime::deno_permissions::PermissionsContainer; use deno_semver::package::PackageNv; use deno_semver::Version; use serde::Deserialize; diff --git a/cli/lsp/registries.rs b/cli/lsp/registries.rs index 9a0ad6dddf..e194c61107 100644 --- a/cli/lsp/registries.rs +++ b/cli/lsp/registries.rs @@ -30,7 +30,7 @@ use deno_core::url::Position; use deno_core::url::Url; use deno_core::ModuleSpecifier; use deno_graph::Dependency; -use deno_runtime::permissions::PermissionsContainer; +use deno_runtime::deno_permissions::PermissionsContainer; use log::error; use once_cell::sync::Lazy; use std::collections::HashMap; diff --git a/cli/lsp/resolver.rs b/cli/lsp/resolver.rs index 2b465f695b..348eae76f6 100644 --- a/cli/lsp/resolver.rs +++ b/cli/lsp/resolver.rs @@ -38,7 +38,6 @@ use deno_runtime::deno_node::NodeResolutionMode; use deno_runtime::deno_node::NodeResolver; use deno_runtime::deno_node::PackageJson; use deno_runtime::fs_util::specifier_to_file_path; -use deno_runtime::permissions::PermissionsContainer; use deno_semver::jsr::JsrPackageReqReference; use deno_semver::npm::NpmPackageReqReference; use deno_semver::package::PackageNv; @@ -247,12 +246,7 @@ impl LspResolver { let node_resolver = self.node_resolver.as_ref()?; Some(NodeResolution::into_specifier_and_media_type( node_resolver - .resolve_req_reference( - req_ref, - &PermissionsContainer::allow_all(), - referrer, - NodeResolutionMode::Types, - ) + .resolve_req_reference(req_ref, referrer, NodeResolutionMode::Types) .ok(), )) } @@ -282,8 +276,10 @@ impl LspResolver { let Some(node_resolver) = self.node_resolver.as_ref() else { return Ok(None); }; - node_resolver - .get_closest_package_json(referrer, &PermissionsContainer::allow_all()) + node_resolver.get_closest_package_json( + referrer, + &mut deno_runtime::deno_node::AllowAllNodePermissions, + ) } pub fn resolve_redirects( diff --git a/cli/lsp/testing/execution.rs b/cli/lsp/testing/execution.rs index f56f5010f1..6393c86427 100644 --- a/cli/lsp/testing/execution.rs +++ b/cli/lsp/testing/execution.rs @@ -26,7 +26,7 @@ use deno_core::parking_lot::RwLock; use deno_core::unsync::spawn; use deno_core::unsync::spawn_blocking; use deno_core::ModuleSpecifier; -use deno_runtime::permissions::Permissions; +use deno_runtime::deno_permissions::Permissions; use deno_runtime::tokio_util::create_and_run_current_thread; use indexmap::IndexMap; use std::collections::HashMap; diff --git a/cli/main.rs b/cli/main.rs index e8bea9f546..f20ca17ff4 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -318,7 +318,7 @@ pub fn main() { util::windows::ensure_stdio_open(); #[cfg(windows)] colors::enable_ansi(); // For Windows 10 - deno_runtime::permissions::set_prompt_callbacks( + deno_runtime::deno_permissions::set_prompt_callbacks( Box::new(util::draw_thread::DrawThread::hide), Box::new(util::draw_thread::DrawThread::show), ); diff --git a/cli/module_loader.rs b/cli/module_loader.rs index c134f80e19..5bcc22c065 100644 --- a/cli/module_loader.rs +++ b/cli/module_loader.rs @@ -68,7 +68,7 @@ use deno_graph::Resolution; use deno_lockfile::Lockfile; use deno_runtime::code_cache; use deno_runtime::deno_node::NodeResolutionMode; -use deno_runtime::permissions::PermissionsContainer; +use deno_runtime::deno_permissions::PermissionsContainer; use deno_semver::npm::NpmPackageReqReference; pub async fn load_top_level_deps(factory: &CliFactory) -> Result<(), AnyError> { @@ -104,7 +104,7 @@ pub async fn load_top_level_deps(factory: &CliFactory) -> Result<(), AnyError> { &roots, false, factory.cli_options().ts_type_lib_window(), - deno_runtime::permissions::PermissionsContainer::allow_all(), + deno_runtime::deno_permissions::PermissionsContainer::allow_all(), ) .await?; } @@ -348,18 +348,12 @@ impl &self, specifier: &ModuleSpecifier, maybe_referrer: Option<&ModuleSpecifier>, - is_dynamic: bool, requested_module_type: RequestedModuleType, ) -> Result { - let permissions = if is_dynamic { - &self.dynamic_permissions - } else { - &self.root_permissions - }; let code_source = if let Some(result) = self .shared .npm_module_loader - .load_if_in_npm_package(specifier, maybe_referrer, permissions) + .load_if_in_npm_package(specifier, maybe_referrer) .await { result? @@ -448,19 +442,11 @@ impl &self, specifier: &str, referrer: &ModuleSpecifier, - kind: ResolutionKind, ) -> Result { - let permissions = if matches!(kind, ResolutionKind::DynamicImport) { - &self.dynamic_permissions - } else { - &self.root_permissions - }; - if let Some(result) = self.shared.node_resolver.resolve_if_in_npm_package( specifier, referrer, NodeResolutionMode::Execution, - permissions, ) { return match result? { Some(res) => Ok(res.into_url()), @@ -505,7 +491,6 @@ impl .node_resolver .resolve_req_reference( &reference, - permissions, referrer, NodeResolutionMode::Execution, ) @@ -530,7 +515,6 @@ impl module.nv_reference.sub_path(), referrer, NodeResolutionMode::Execution, - permissions, ) .with_context(|| { format!("Could not resolve '{}'.", module.nv_reference) @@ -720,7 +704,7 @@ impl ModuleLoader &self, specifier: &str, referrer: &str, - kind: ResolutionKind, + _kind: ResolutionKind, ) -> Result { fn ensure_not_jsr_non_jsr_remote_import( specifier: &ModuleSpecifier, @@ -736,7 +720,7 @@ impl ModuleLoader } let referrer = self.0.resolve_referrer(referrer)?; - let specifier = self.0.inner_resolve(specifier, &referrer, kind)?; + let specifier = self.0.inner_resolve(specifier, &referrer)?; ensure_not_jsr_non_jsr_remote_import(&specifier, &referrer)?; Ok(specifier) } @@ -745,7 +729,7 @@ impl ModuleLoader &self, specifier: &ModuleSpecifier, maybe_referrer: Option<&ModuleSpecifier>, - is_dynamic: bool, + _is_dynamic: bool, requested_module_type: RequestedModuleType, ) -> deno_core::ModuleLoadResponse { let inner = self.0.clone(); @@ -757,7 +741,6 @@ impl ModuleLoader .load_inner( &specifier, maybe_referrer.as_ref(), - is_dynamic, requested_module_type, ) .await diff --git a/cli/npm/byonm.rs b/cli/npm/byonm.rs index 9317455378..bfb9bed7f7 100644 --- a/cli/npm/byonm.rs +++ b/cli/npm/byonm.rs @@ -160,7 +160,7 @@ impl NpmResolver for ByonmCliNpmResolver { fn ensure_read_permission( &self, - permissions: &dyn NodePermissions, + permissions: &mut dyn NodePermissions, path: &Path, ) -> Result<(), AnyError> { if !path diff --git a/cli/npm/managed/mod.rs b/cli/npm/managed/mod.rs index 6a2dfdd673..2298ea9bd7 100644 --- a/cli/npm/managed/mod.rs +++ b/cli/npm/managed/mod.rs @@ -550,7 +550,7 @@ impl NpmResolver for ManagedCliNpmResolver { fn ensure_read_permission( &self, - permissions: &dyn NodePermissions, + permissions: &mut dyn NodePermissions, path: &Path, ) -> Result<(), AnyError> { self.fs_resolver.ensure_read_permission(permissions, path) diff --git a/cli/npm/managed/resolvers/common.rs b/cli/npm/managed/resolvers/common.rs index 5003e6a058..767b3f9c6d 100644 --- a/cli/npm/managed/resolvers/common.rs +++ b/cli/npm/managed/resolvers/common.rs @@ -53,7 +53,7 @@ pub trait NpmPackageFsResolver: Send + Sync { fn ensure_read_permission( &self, - permissions: &dyn NodePermissions, + permissions: &mut dyn NodePermissions, path: &Path, ) -> Result<(), AnyError>; } @@ -76,7 +76,7 @@ impl RegistryReadPermissionChecker { pub fn ensure_registry_read_permission( &self, - permissions: &dyn NodePermissions, + permissions: &mut dyn NodePermissions, path: &Path, ) -> Result<(), AnyError> { // allow reading if it's in the node_modules diff --git a/cli/npm/managed/resolvers/global.rs b/cli/npm/managed/resolvers/global.rs index 05c2472cf3..bfd2f4de36 100644 --- a/cli/npm/managed/resolvers/global.rs +++ b/cli/npm/managed/resolvers/global.rs @@ -146,7 +146,7 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver { fn ensure_read_permission( &self, - permissions: &dyn NodePermissions, + permissions: &mut dyn NodePermissions, path: &Path, ) -> Result<(), AnyError> { self diff --git a/cli/npm/managed/resolvers/local.rs b/cli/npm/managed/resolvers/local.rs index c64aacc397..4243d04f2a 100644 --- a/cli/npm/managed/resolvers/local.rs +++ b/cli/npm/managed/resolvers/local.rs @@ -243,7 +243,7 @@ impl NpmPackageFsResolver for LocalNpmPackageResolver { fn ensure_read_permission( &self, - permissions: &dyn NodePermissions, + permissions: &mut dyn NodePermissions, path: &Path, ) -> Result<(), AnyError> { self diff --git a/cli/npm/mod.rs b/cli/npm/mod.rs index ef230372fd..8d801744b1 100644 --- a/cli/npm/mod.rs +++ b/cli/npm/mod.rs @@ -14,7 +14,7 @@ use deno_core::error::AnyError; use deno_core::serde_json; use deno_npm::registry::NpmPackageInfo; use deno_runtime::deno_node::NpmResolver; -use deno_runtime::permissions::PermissionsContainer; +use deno_runtime::deno_permissions::PermissionsContainer; use deno_semver::package::PackageNv; use deno_semver::package::PackageReq; diff --git a/cli/ops/bench.rs b/cli/ops/bench.rs index 2c8c63ed66..5521253ffd 100644 --- a/cli/ops/bench.rs +++ b/cli/ops/bench.rs @@ -11,9 +11,9 @@ use deno_core::op2; use deno_core::v8; use deno_core::ModuleSpecifier; use deno_core::OpState; -use deno_runtime::permissions::create_child_permissions; -use deno_runtime::permissions::ChildPermissionsArg; -use deno_runtime::permissions::PermissionsContainer; +use deno_runtime::deno_permissions::create_child_permissions; +use deno_runtime::deno_permissions::ChildPermissionsArg; +use deno_runtime::deno_permissions::PermissionsContainer; use tokio::sync::mpsc::UnboundedSender; use uuid::Uuid; @@ -61,7 +61,7 @@ pub fn op_pledge_test_permissions( let token = Uuid::new_v4(); let parent_permissions = state.borrow_mut::(); let worker_permissions = { - let mut parent_permissions = parent_permissions.0 .0.lock(); + let mut parent_permissions = parent_permissions.0.lock(); let perms = create_child_permissions(&mut parent_permissions, args)?; PermissionsContainer::new(perms) }; diff --git a/cli/ops/testing.rs b/cli/ops/testing.rs index 6025b99172..b63a729470 100644 --- a/cli/ops/testing.rs +++ b/cli/ops/testing.rs @@ -16,9 +16,9 @@ use deno_core::op2; use deno_core::v8; use deno_core::ModuleSpecifier; use deno_core::OpState; -use deno_runtime::permissions::create_child_permissions; -use deno_runtime::permissions::ChildPermissionsArg; -use deno_runtime::permissions::PermissionsContainer; +use deno_runtime::deno_permissions::create_child_permissions; +use deno_runtime::deno_permissions::ChildPermissionsArg; +use deno_runtime::deno_permissions::PermissionsContainer; use serde::Serialize; use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; @@ -57,7 +57,7 @@ pub fn op_pledge_test_permissions( let token = Uuid::new_v4(); let parent_permissions = state.borrow_mut::(); let worker_permissions = { - let mut parent_permissions = parent_permissions.0 .0.lock(); + let mut parent_permissions = parent_permissions.0.lock(); let perms = create_child_permissions(&mut parent_permissions, args)?; PermissionsContainer::new(perms) }; diff --git a/cli/resolver.rs b/cli/resolver.rs index a28dfce91a..301cd0666d 100644 --- a/cli/resolver.rs +++ b/cli/resolver.rs @@ -30,7 +30,6 @@ use deno_runtime::deno_node::NodeResolver; use deno_runtime::deno_node::NpmResolver as DenoNodeNpmResolver; use deno_runtime::deno_node::PackageJson; use deno_runtime::fs_util::specifier_to_file_path; -use deno_runtime::permissions::PermissionsContainer; use deno_semver::npm::NpmPackageReqReference; use deno_semver::package::PackageReq; use import_map::ImportMap; @@ -100,7 +99,7 @@ impl CliNodeResolver { pub fn get_closest_package_json( &self, referrer: &ModuleSpecifier, - permissions: &dyn NodePermissions, + permissions: &mut dyn NodePermissions, ) -> Result>, AnyError> { self .node_resolver @@ -112,11 +111,10 @@ impl CliNodeResolver { specifier: &str, referrer: &ModuleSpecifier, mode: NodeResolutionMode, - permissions: &PermissionsContainer, ) -> Option, AnyError>> { if self.in_npm_package(referrer) { // we're in an npm package, so use node resolution - Some(self.resolve(specifier, referrer, mode, permissions)) + Some(self.resolve(specifier, referrer, mode)) } else { None } @@ -127,20 +125,15 @@ impl CliNodeResolver { specifier: &str, referrer: &ModuleSpecifier, mode: NodeResolutionMode, - permissions: &PermissionsContainer, ) -> Result, AnyError> { - self.handle_node_resolve_result(self.node_resolver.resolve( - specifier, - referrer, - mode, - permissions, - )) + self.handle_node_resolve_result( + self.node_resolver.resolve(specifier, referrer, mode), + ) } pub fn resolve_req_reference( &self, req_ref: &NpmPackageReqReference, - permissions: &PermissionsContainer, referrer: &ModuleSpecifier, mode: NodeResolutionMode, ) -> Result { @@ -152,7 +145,6 @@ impl CliNodeResolver { req_ref.sub_path(), referrer, mode, - permissions, )?; match maybe_resolution { Some(resolution) => Ok(resolution), @@ -181,7 +173,6 @@ impl CliNodeResolver { sub_path: Option<&str>, referrer: &ModuleSpecifier, mode: NodeResolutionMode, - permissions: &PermissionsContainer, ) -> Result, AnyError> { self.handle_node_resolve_result( self.node_resolver.resolve_package_subpath_from_deno_module( @@ -189,7 +180,6 @@ impl CliNodeResolver { sub_path, referrer, mode, - permissions, ), ) } @@ -278,10 +268,9 @@ impl NpmModuleLoader { &self, specifier: &ModuleSpecifier, maybe_referrer: Option<&ModuleSpecifier>, - permissions: &PermissionsContainer, ) -> Option> { if self.node_resolver.in_npm_package(specifier) { - Some(self.load(specifier, maybe_referrer, permissions).await) + Some(self.load(specifier, maybe_referrer).await) } else { None } @@ -291,7 +280,6 @@ impl NpmModuleLoader { &self, specifier: &ModuleSpecifier, maybe_referrer: Option<&ModuleSpecifier>, - permissions: &PermissionsContainer, ) -> Result { let file_path = specifier.to_file_path().unwrap(); let code = self @@ -336,7 +324,7 @@ impl NpmModuleLoader { ModuleSourceCode::String( self .node_code_translator - .translate_cjs_to_esm(specifier, Some(code), permissions) + .translate_cjs_to_esm(specifier, Some(code)) .await? .into(), ) @@ -638,12 +626,7 @@ impl Resolver for CliGraphResolver { { let node_resolver = self.node_resolver.as_ref().unwrap(); return node_resolver - .resolve_req_reference( - &npm_req_ref, - &PermissionsContainer::allow_all(), - referrer, - to_node_mode(mode), - ) + .resolve_req_reference(&npm_req_ref, referrer, to_node_mode(mode)) .map(|res| res.into_url()) .map_err(|err| err.into()); } @@ -651,12 +634,8 @@ impl Resolver for CliGraphResolver { Err(_) => { if referrer.scheme() == "file" { if let Some(node_resolver) = &self.node_resolver { - let node_result = node_resolver.resolve( - specifier, - referrer, - to_node_mode(mode), - &PermissionsContainer::allow_all(), - ); + let node_result = + node_resolver.resolve(specifier, referrer, to_node_mode(mode)); match node_result { Ok(Some(res)) => { return Ok(res.into_url()); @@ -694,7 +673,6 @@ impl Resolver for CliGraphResolver { specifier, referrer, to_node_mode(mode), - &PermissionsContainer::allow_all(), ); if let Some(Ok(Some(res))) = node_result { return Ok(res.into_url()); diff --git a/cli/standalone/mod.rs b/cli/standalone/mod.rs index 5e8c5c0b64..91e524ddaa 100644 --- a/cli/standalone/mod.rs +++ b/cli/standalone/mod.rs @@ -53,10 +53,10 @@ use deno_runtime::deno_fs; use deno_runtime::deno_node::analyze::NodeCodeTranslator; use deno_runtime::deno_node::NodeResolutionMode; use deno_runtime::deno_node::NodeResolver; +use deno_runtime::deno_permissions::Permissions; +use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::deno_tls::rustls::RootCertStore; use deno_runtime::deno_tls::RootCertStoreProvider; -use deno_runtime::permissions::Permissions; -use deno_runtime::permissions::PermissionsContainer; use deno_runtime::WorkerExecutionMode; use deno_runtime::WorkerLogLevel; use deno_semver::npm::NpmPackageReqReference; @@ -112,16 +112,10 @@ impl ModuleLoader for EmbeddedModuleLoader { })? }; - let permissions = if matches!(kind, ResolutionKind::DynamicImport) { - &self.dynamic_permissions - } else { - &self.root_permissions - }; if let Some(result) = self.shared.node_resolver.resolve_if_in_npm_package( specifier, &referrer, NodeResolutionMode::Execution, - permissions, ) { return match result? { Some(res) => Ok(res.into_url()), @@ -146,7 +140,6 @@ impl ModuleLoader for EmbeddedModuleLoader { .node_resolver .resolve_req_reference( &reference, - permissions, &referrer, NodeResolutionMode::Execution, ) @@ -174,7 +167,7 @@ impl ModuleLoader for EmbeddedModuleLoader { &self, original_specifier: &ModuleSpecifier, maybe_referrer: Option<&ModuleSpecifier>, - is_dynamic: bool, + _is_dynamic: bool, _requested_module_type: RequestedModuleType, ) -> deno_core::ModuleLoadResponse { if original_specifier.scheme() == "data" { @@ -203,15 +196,10 @@ impl ModuleLoader for EmbeddedModuleLoader { let npm_module_loader = self.shared.npm_module_loader.clone(); let original_specifier = original_specifier.clone(); let maybe_referrer = maybe_referrer.cloned(); - let permissions = if is_dynamic { - self.dynamic_permissions.clone() - } else { - self.root_permissions.clone() - }; return deno_core::ModuleLoadResponse::Async( async move { let code_source = npm_module_loader - .load(&original_specifier, maybe_referrer.as_ref(), &permissions) + .load(&original_specifier, maybe_referrer.as_ref()) .await?; Ok(deno_core::ModuleSource::new_with_redirect( match code_source.media_type { diff --git a/cli/tools/bench/mod.rs b/cli/tools/bench/mod.rs index a6c8d3e16b..0378d6ae21 100644 --- a/cli/tools/bench/mod.rs +++ b/cli/tools/bench/mod.rs @@ -31,8 +31,8 @@ use deno_core::unsync::spawn_blocking; use deno_core::v8; use deno_core::ModuleSpecifier; use deno_core::PollEventLoopOptions; -use deno_runtime::permissions::Permissions; -use deno_runtime::permissions::PermissionsContainer; +use deno_runtime::deno_permissions::Permissions; +use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::tokio_util::create_and_run_current_thread; use deno_runtime::WorkerExecutionMode; use indexmap::IndexMap; diff --git a/cli/tools/jupyter/mod.rs b/cli/tools/jupyter/mod.rs index 4b5009ba76..3b08928437 100644 --- a/cli/tools/jupyter/mod.rs +++ b/cli/tools/jupyter/mod.rs @@ -18,8 +18,8 @@ use deno_core::serde_json; use deno_core::url::Url; use deno_runtime::deno_io::Stdio; use deno_runtime::deno_io::StdioPipe; -use deno_runtime::permissions::Permissions; -use deno_runtime::permissions::PermissionsContainer; +use deno_runtime::deno_permissions::Permissions; +use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::WorkerExecutionMode; use deno_terminal::colors; diff --git a/cli/tools/repl/mod.rs b/cli/tools/repl/mod.rs index c29e29e71f..db1d75dadc 100644 --- a/cli/tools/repl/mod.rs +++ b/cli/tools/repl/mod.rs @@ -13,8 +13,8 @@ use deno_core::error::AnyError; use deno_core::futures::StreamExt; use deno_core::serde_json; use deno_core::unsync::spawn_blocking; -use deno_runtime::permissions::Permissions; -use deno_runtime::permissions::PermissionsContainer; +use deno_runtime::deno_permissions::Permissions; +use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::WorkerExecutionMode; use rustyline::error::ReadlineError; diff --git a/cli/tools/run/mod.rs b/cli/tools/run/mod.rs index 82dcae711c..f70cfd066f 100644 --- a/cli/tools/run/mod.rs +++ b/cli/tools/run/mod.rs @@ -3,8 +3,8 @@ use std::io::Read; use deno_core::error::AnyError; -use deno_runtime::permissions::Permissions; -use deno_runtime::permissions::PermissionsContainer; +use deno_runtime::deno_permissions::Permissions; +use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::WorkerExecutionMode; use crate::args::EvalFlags; diff --git a/cli/tools/test/mod.rs b/cli/tools/test/mod.rs index 06ff39abe1..7416b5a262 100644 --- a/cli/tools/test/mod.rs +++ b/cli/tools/test/mod.rs @@ -54,9 +54,9 @@ use deno_core::OpState; use deno_core::PollEventLoopOptions; use deno_runtime::deno_io::Stdio; use deno_runtime::deno_io::StdioPipe; +use deno_runtime::deno_permissions::Permissions; +use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::fmt_errors::format_js_error; -use deno_runtime::permissions::Permissions; -use deno_runtime::permissions::PermissionsContainer; use deno_runtime::tokio_util::create_and_run_current_thread; use deno_runtime::worker::MainWorker; use deno_runtime::WorkerExecutionMode; diff --git a/cli/tsc/mod.rs b/cli/tsc/mod.rs index c5365628d5..de4c05e27c 100644 --- a/cli/tsc/mod.rs +++ b/cli/tsc/mod.rs @@ -33,7 +33,6 @@ use deno_graph::ResolutionResolved; use deno_runtime::deno_node::NodeResolution; use deno_runtime::deno_node::NodeResolutionMode; use deno_runtime::deno_node::NodeResolver; -use deno_runtime::permissions::PermissionsContainer; use deno_semver::npm::NpmPackageReqReference; use lsp_types::Url; use once_cell::sync::Lazy; @@ -742,7 +741,6 @@ fn resolve_graph_specifier_types( module.nv_reference.sub_path(), referrer, NodeResolutionMode::Types, - &PermissionsContainer::allow_all(), )?; Ok(Some(NodeResolution::into_specifier_and_media_type( maybe_resolution, @@ -779,12 +777,7 @@ fn resolve_non_graph_specifier_types( // we're in an npm package, so use node resolution Ok(Some(NodeResolution::into_specifier_and_media_type( node_resolver - .resolve( - specifier, - referrer, - NodeResolutionMode::Types, - &PermissionsContainer::allow_all(), - ) + .resolve(specifier, referrer, NodeResolutionMode::Types) .ok() .flatten(), ))) @@ -802,7 +795,6 @@ fn resolve_non_graph_specifier_types( npm_req_ref.sub_path(), referrer, NodeResolutionMode::Types, - &PermissionsContainer::allow_all(), )?; Ok(Some(NodeResolution::into_specifier_and_media_type( maybe_resolution, diff --git a/cli/worker.rs b/cli/worker.rs index 7efa84369f..cb52b6101b 100644 --- a/cli/worker.rs +++ b/cli/worker.rs @@ -28,12 +28,12 @@ use deno_runtime::deno_node; use deno_runtime::deno_node::NodeResolution; use deno_runtime::deno_node::NodeResolutionMode; use deno_runtime::deno_node::NodeResolver; +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::worker_host::CreateWebWorkerCb; -use deno_runtime::permissions::PermissionsContainer; use deno_runtime::web_worker::WebWorker; use deno_runtime::web_worker::WebWorkerOptions; use deno_runtime::worker::MainWorker; @@ -522,11 +522,8 @@ impl CliMainWorkerFactory { package_ref.req(), &referrer, )?; - let node_resolution = self.resolve_binary_entrypoint( - &package_folder, - package_ref.sub_path(), - &permissions, - )?; + let node_resolution = self + .resolve_binary_entrypoint(&package_folder, package_ref.sub_path())?; let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_)); if let Some(lockfile) = &shared.maybe_lockfile { @@ -636,6 +633,7 @@ impl CliMainWorkerFactory { strace_ops: shared.options.strace_ops.clone(), module_loader, fs: shared.fs.clone(), + node_resolver: Some(shared.node_resolver.clone()), npm_resolver: Some(shared.npm_resolver.clone().into_npm_resolver()), get_error_class_fn: Some(&errors::get_error_class_name), cache_storage_dir, @@ -687,7 +685,6 @@ impl CliMainWorkerFactory { &self, package_folder: &Path, sub_path: Option<&str>, - permissions: &PermissionsContainer, ) -> Result { match self .shared @@ -697,11 +694,8 @@ impl CliMainWorkerFactory { Ok(node_resolution) => Ok(node_resolution), Err(original_err) => { // if the binary entrypoint was not found, fallback to regular node resolution - let result = self.resolve_binary_entrypoint_fallback( - package_folder, - sub_path, - permissions, - ); + let result = + self.resolve_binary_entrypoint_fallback(package_folder, sub_path); match result { Ok(Some(resolution)) => Ok(resolution), Ok(None) => Err(original_err), @@ -718,7 +712,6 @@ impl CliMainWorkerFactory { &self, package_folder: &Path, sub_path: Option<&str>, - permissions: &PermissionsContainer, ) -> Result, AnyError> { // only fallback if the user specified a sub path if sub_path.is_none() { @@ -739,7 +732,6 @@ impl CliMainWorkerFactory { sub_path, &referrer, NodeResolutionMode::Execution, - permissions, )? else { return Ok(None); @@ -843,6 +835,7 @@ fn create_web_worker_callback( source_map_getter, module_loader, fs: shared.fs.clone(), + node_resolver: Some(shared.node_resolver.clone()), npm_resolver: Some(shared.npm_resolver.clone().into_npm_resolver()), worker_type: args.worker_type, maybe_inspector_server, @@ -877,7 +870,7 @@ fn create_web_worker_callback( mod tests { use super::*; use deno_core::resolve_path; - use deno_runtime::permissions::Permissions; + use deno_runtime::deno_permissions::Permissions; fn create_test_worker() -> MainWorker { let main_module = diff --git a/ext/fetch/Cargo.toml b/ext/fetch/Cargo.toml index 75884466b0..a5cc650b12 100644 --- a/ext/fetch/Cargo.toml +++ b/ext/fetch/Cargo.toml @@ -17,6 +17,7 @@ path = "lib.rs" bytes.workspace = true data-url.workspace = true deno_core.workspace = true +deno_permissions.workspace = true deno_tls.workspace = true dyn-clone = "1" http_v02.workspace = true diff --git a/ext/fetch/lib.rs b/ext/fetch/lib.rs index 21ca040277..066f1685b0 100644 --- a/ext/fetch/lib.rs +++ b/ext/fetch/lib.rs @@ -281,6 +281,26 @@ pub trait FetchPermissions { fn check_read(&mut self, _p: &Path, api_name: &str) -> Result<(), AnyError>; } +impl FetchPermissions for deno_permissions::PermissionsContainer { + #[inline(always)] + fn check_net_url( + &mut self, + url: &Url, + api_name: &str, + ) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_net_url(self, url, api_name) + } + + #[inline(always)] + fn check_read( + &mut self, + path: &Path, + api_name: &str, + ) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_read(self, path, api_name) + } +} + #[op2] #[serde] #[allow(clippy::too_many_arguments)] diff --git a/ext/ffi/Cargo.toml b/ext/ffi/Cargo.toml index fb0d4ae2a1..e8e984acbf 100644 --- a/ext/ffi/Cargo.toml +++ b/ext/ffi/Cargo.toml @@ -15,6 +15,7 @@ path = "lib.rs" [dependencies] deno_core.workspace = true +deno_permissions.workspace = true dlopen2.workspace = true dynasmrt = "1.2.3" libffi = "=3.2.0" diff --git a/ext/ffi/lib.rs b/ext/ffi/lib.rs index 4e81292408..26b06d98fb 100644 --- a/ext/ffi/lib.rs +++ b/ext/ffi/lib.rs @@ -53,6 +53,13 @@ pub trait FfiPermissions { fn check_partial(&mut self, path: Option<&Path>) -> Result<(), AnyError>; } +impl FfiPermissions for deno_permissions::PermissionsContainer { + #[inline(always)] + fn check_partial(&mut self, path: Option<&Path>) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_ffi_partial(self, path) + } +} + deno_core::extension!(deno_ffi, deps = [ deno_web ], parameters = [P: FfiPermissions], diff --git a/ext/fs/Cargo.toml b/ext/fs/Cargo.toml index b5ac5199c7..f13dc1cbf2 100644 --- a/ext/fs/Cargo.toml +++ b/ext/fs/Cargo.toml @@ -21,6 +21,7 @@ async-trait.workspace = true base32.workspace = true deno_core.workspace = true deno_io.workspace = true +deno_permissions.workspace = true filetime.workspace = true libc.workspace = true rand.workspace = true diff --git a/ext/fs/lib.rs b/ext/fs/lib.rs index d6794d3acf..2dce04b325 100644 --- a/ext/fs/lib.rs +++ b/ext/fs/lib.rs @@ -23,9 +23,10 @@ use crate::ops::*; use deno_core::error::AnyError; use deno_core::OpState; use deno_io::fs::FsError; +use std::borrow::Cow; use std::path::Path; -pub trait FsPermissions: Send + Sync { +pub trait FsPermissions { fn check_open<'a>( &mut self, resolved: bool, @@ -78,6 +79,92 @@ pub trait FsPermissions: Send + Sync { } } +impl FsPermissions for deno_permissions::PermissionsContainer { + fn check_open<'a>( + &mut self, + resolved: bool, + read: bool, + write: bool, + path: &'a Path, + api_name: &str, + ) -> Result, FsError> { + if resolved { + self.check_special_file(path, api_name).map_err(|_| { + std::io::Error::from(std::io::ErrorKind::PermissionDenied) + })?; + return Ok(Cow::Borrowed(path)); + } + + // If somehow read or write aren't specified, use read + let read = read || !write; + if read { + FsPermissions::check_read(self, path, api_name) + .map_err(|_| FsError::PermissionDenied("read"))?; + } + if write { + FsPermissions::check_write(self, path, api_name) + .map_err(|_| FsError::PermissionDenied("write"))?; + } + Ok(Cow::Borrowed(path)) + } + + fn check_read( + &mut self, + path: &Path, + api_name: &str, + ) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_read(self, path, api_name) + } + + fn check_read_blind( + &mut self, + path: &Path, + display: &str, + api_name: &str, + ) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_read_blind( + self, path, display, api_name, + ) + } + + fn check_write( + &mut self, + path: &Path, + api_name: &str, + ) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_write(self, path, api_name) + } + + fn check_write_partial( + &mut self, + path: &Path, + api_name: &str, + ) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_write_partial( + self, path, api_name, + ) + } + + fn check_write_blind( + &mut self, + p: &Path, + display: &str, + api_name: &str, + ) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_write_blind( + self, p, display, api_name, + ) + } + + fn check_read_all(&mut self, api_name: &str) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_read_all(self, api_name) + } + + fn check_write_all(&mut self, api_name: &str) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_write_all(self, api_name) + } +} + pub const UNSTABLE_FEATURE_NAME: &str = "fs"; /// Helper for checking unstable features. Used for sync ops. diff --git a/ext/kv/Cargo.toml b/ext/kv/Cargo.toml index 9cc7e08895..99f3d8051c 100644 --- a/ext/kv/Cargo.toml +++ b/ext/kv/Cargo.toml @@ -21,6 +21,7 @@ chrono = { workspace = true, features = ["now"] } deno_core.workspace = true deno_fetch.workspace = true deno_node.workspace = true +deno_permissions.workspace = true deno_tls.workspace = true denokv_proto.workspace = true denokv_remote.workspace = true diff --git a/ext/kv/remote.rs b/ext/kv/remote.rs index 9d5e099c73..a1273e78b8 100644 --- a/ext/kv/remote.rs +++ b/ext/kv/remote.rs @@ -48,6 +48,22 @@ pub trait RemoteDbHandlerPermissions { ) -> Result<(), AnyError>; } +impl RemoteDbHandlerPermissions for deno_permissions::PermissionsContainer { + #[inline(always)] + fn check_env(&mut self, var: &str) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_env(self, var) + } + + #[inline(always)] + fn check_net_url( + &mut self, + url: &Url, + api_name: &str, + ) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_net_url(self, url, api_name) + } +} + pub struct RemoteDbHandler { http_options: HttpOptions, _p: std::marker::PhantomData

, diff --git a/ext/kv/sqlite.rs b/ext/kv/sqlite.rs index a8a7fbace3..6dd821bda9 100644 --- a/ext/kv/sqlite.rs +++ b/ext/kv/sqlite.rs @@ -40,6 +40,18 @@ pub trait SqliteDbHandlerPermissions { fn check_write(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError>; } +impl SqliteDbHandlerPermissions for deno_permissions::PermissionsContainer { + #[inline(always)] + fn check_read(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_read(self, p, api_name) + } + + #[inline(always)] + fn check_write(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_write(self, p, api_name) + } +} + impl SqliteDbHandler

{ pub fn new( default_storage_dir: Option, diff --git a/ext/napi/Cargo.toml b/ext/napi/Cargo.toml index 2342f313fc..c6f3c76853 100644 --- a/ext/napi/Cargo.toml +++ b/ext/napi/Cargo.toml @@ -15,4 +15,5 @@ path = "lib.rs" [dependencies] deno_core.workspace = true +deno_permissions.workspace = true libloading = { version = "0.7" } diff --git a/ext/napi/lib.rs b/ext/napi/lib.rs index b3313f0fec..f4fa33438f 100644 --- a/ext/napi/lib.rs +++ b/ext/napi/lib.rs @@ -432,6 +432,15 @@ pub trait NapiPermissions { -> std::result::Result<(), AnyError>; } +// NOTE(bartlomieju): for now, NAPI uses `--allow-ffi` flag, but that might +// change in the future. +impl NapiPermissions for deno_permissions::PermissionsContainer { + #[inline(always)] + fn check(&mut self, path: Option<&Path>) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_ffi(self, path) + } +} + /// # Safety /// /// This function is unsafe because it dereferences raw pointer Env. diff --git a/ext/net/Cargo.toml b/ext/net/Cargo.toml index b9ddf8d70a..10dfd0d77d 100644 --- a/ext/net/Cargo.toml +++ b/ext/net/Cargo.toml @@ -15,6 +15,7 @@ path = "lib.rs" [dependencies] deno_core.workspace = true +deno_permissions.workspace = true deno_tls.workspace = true pin-project.workspace = true rustls-tokio-stream.workspace = true diff --git a/ext/net/lib.rs b/ext/net/lib.rs index fa8074b345..3b6c05282b 100644 --- a/ext/net/lib.rs +++ b/ext/net/lib.rs @@ -30,6 +30,35 @@ pub trait NetPermissions { -> Result<(), AnyError>; } +impl NetPermissions for deno_permissions::PermissionsContainer { + #[inline(always)] + fn check_net>( + &mut self, + host: &(T, Option), + api_name: &str, + ) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_net(self, host, api_name) + } + + #[inline(always)] + fn check_read( + &mut self, + path: &Path, + api_name: &str, + ) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_read(self, path, api_name) + } + + #[inline(always)] + fn check_write( + &mut self, + path: &Path, + api_name: &str, + ) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_write(self, path, api_name) + } +} + /// Helper for checking unstable features. Used for sync ops. fn check_unstable(state: &OpState, api_name: &str) { // TODO(bartlomieju): replace with `state.feature_checker.check_or_exit` diff --git a/ext/node/analyze.rs b/ext/node/analyze.rs index b7adfd5ce8..df68cb0fc4 100644 --- a/ext/node/analyze.rs +++ b/ext/node/analyze.rs @@ -17,8 +17,8 @@ use deno_core::error::AnyError; use crate::path::to_file_specifier; use crate::resolution::NodeResolverRc; +use crate::AllowAllNodePermissions; use crate::NodeModuleKind; -use crate::NodePermissions; use crate::NodeResolutionMode; use crate::NpmResolverRc; use crate::PackageJson; @@ -87,7 +87,6 @@ impl NodeCodeTranslator { &self, entry_specifier: &ModuleSpecifier, source: Option, - permissions: &dyn NodePermissions, ) -> Result { let mut temp_var_count = 0; @@ -115,7 +114,6 @@ impl NodeCodeTranslator { .analyze_reexports( entry_specifier, analysis.reexports, - permissions, &mut all_exports, &mut errors, ) @@ -161,7 +159,6 @@ impl NodeCodeTranslator { &'a self, entry_specifier: &url::Url, reexports: Vec, - permissions: &dyn NodePermissions, all_exports: &mut HashSet, // this goes through the modules concurrently, so collect // the errors in order to be deterministic @@ -194,7 +191,6 @@ impl NodeCodeTranslator { // should be `deno-require`, because `deno` is already used in `esm_resolver.rs` &["deno", "require", "default"], NodeResolutionMode::Execution, - permissions, ); let reexport_specifier = match result { Ok(specifier) => specifier, @@ -287,7 +283,6 @@ impl NodeCodeTranslator { referrer: &ModuleSpecifier, conditions: &[&str], mode: NodeResolutionMode, - permissions: &dyn NodePermissions, ) -> Result { if specifier.starts_with('/') { todo!(); @@ -319,7 +314,7 @@ impl NodeCodeTranslator { let package_json = PackageJson::load( &*self.fs, &*self.npm_resolver, - permissions, + &mut AllowAllNodePermissions, package_json_path.clone(), )?; if package_json.exists { @@ -332,7 +327,6 @@ impl NodeCodeTranslator { NodeModuleKind::Esm, conditions, mode, - permissions, ); } @@ -345,7 +339,7 @@ impl NodeCodeTranslator { let package_json = PackageJson::load( &*self.fs, &*self.npm_resolver, - permissions, + &mut AllowAllNodePermissions, package_json_path, )?; if package_json.exists { diff --git a/ext/node/global.rs b/ext/node/global.rs index 0aaa6ed8bc..d2fe7a1e57 100644 --- a/ext/node/global.rs +++ b/ext/node/global.rs @@ -1,13 +1,12 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use std::mem::MaybeUninit; -use std::rc::Rc; use deno_core::v8; use deno_core::v8::GetPropertyNamesArgs; use deno_core::v8::MapFnTo; -use crate::NodeResolver; +use crate::resolution::NodeResolverRc; // NOTE(bartlomieju): somehow calling `.map_fn_to()` multiple times on a function // returns two different pointers. That shouldn't be the case as `.map_fn_to()` @@ -271,7 +270,7 @@ fn current_mode(scope: &mut v8::HandleScope) -> Mode { }; let op_state = deno_core::JsRuntime::op_state_from(scope); let op_state = op_state.borrow(); - let Some(node_resolver) = op_state.try_borrow::>() else { + let Some(node_resolver) = op_state.try_borrow::() else { return Mode::Deno; }; let mut buffer = [MaybeUninit::uninit(); 2048]; diff --git a/ext/node/lib.rs b/ext/node/lib.rs index 2b31f704f6..a15125f603 100644 --- a/ext/node/lib.rs +++ b/ext/node/lib.rs @@ -6,7 +6,6 @@ use std::collections::HashSet; use std::path::Path; use std::path::PathBuf; -use std::rc::Rc; use deno_core::error::AnyError; use deno_core::located_script_name; @@ -46,6 +45,7 @@ pub use resolution::NodeModuleKind; pub use resolution::NodeResolution; pub use resolution::NodeResolutionMode; pub use resolution::NodeResolver; +use resolution::NodeResolverRc; use crate::global::global_object_middleware; use crate::global::global_template_middleware; @@ -57,23 +57,23 @@ pub trait NodePermissions { api_name: &str, ) -> Result<(), AnyError>; #[inline(always)] - fn check_read(&self, path: &Path) -> Result<(), AnyError> { + fn check_read(&mut self, path: &Path) -> Result<(), AnyError> { self.check_read_with_api_name(path, None) } fn check_read_with_api_name( - &self, + &mut self, path: &Path, api_name: Option<&str>, ) -> Result<(), AnyError>; - fn check_sys(&self, kind: &str, api_name: &str) -> Result<(), AnyError>; + fn check_sys(&mut self, kind: &str, api_name: &str) -> Result<(), AnyError>; fn check_write_with_api_name( - &self, + &mut self, path: &Path, api_name: Option<&str>, ) -> Result<(), AnyError>; } -pub(crate) struct AllowAllNodePermissions; +pub struct AllowAllNodePermissions; impl NodePermissions for AllowAllNodePermissions { fn check_net_url( @@ -84,24 +84,65 @@ impl NodePermissions for AllowAllNodePermissions { Ok(()) } fn check_read_with_api_name( - &self, + &mut self, _path: &Path, _api_name: Option<&str>, ) -> Result<(), AnyError> { Ok(()) } fn check_write_with_api_name( - &self, + &mut self, _path: &Path, _api_name: Option<&str>, ) -> Result<(), AnyError> { Ok(()) } - fn check_sys(&self, _kind: &str, _api_name: &str) -> Result<(), AnyError> { + fn check_sys( + &mut self, + _kind: &str, + _api_name: &str, + ) -> Result<(), AnyError> { Ok(()) } } +impl NodePermissions for deno_permissions::PermissionsContainer { + #[inline(always)] + fn check_net_url( + &mut self, + url: &Url, + api_name: &str, + ) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_net_url(self, url, api_name) + } + + #[inline(always)] + fn check_read_with_api_name( + &mut self, + path: &Path, + api_name: Option<&str>, + ) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_read_with_api_name( + self, path, api_name, + ) + } + + #[inline(always)] + fn check_write_with_api_name( + &mut self, + path: &Path, + api_name: Option<&str>, + ) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_write_with_api_name( + self, path, api_name, + ) + } + + fn check_sys(&mut self, kind: &str, api_name: &str) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_sys(self, kind, api_name) + } +} + #[allow(clippy::disallowed_types)] pub type NpmResolverRc = deno_fs::sync::MaybeArc; @@ -146,7 +187,7 @@ pub trait NpmResolver: std::fmt::Debug + MaybeSend + MaybeSync { fn ensure_read_permission( &self, - permissions: &dyn NodePermissions, + permissions: &mut dyn NodePermissions, path: &Path, ) -> Result<(), AnyError>; } @@ -582,18 +623,21 @@ deno_core::extension!(deno_node, "node:zlib" = "zlib.ts", ], options = { + maybe_node_resolver: Option, maybe_npm_resolver: Option, fs: deno_fs::FileSystemRc, }, state = |state, options| { - let fs = options.fs; - state.put(fs.clone()); - if let Some(npm_resolver) = options.maybe_npm_resolver { + // you should provide both of these or neither + debug_assert_eq!(options.maybe_node_resolver.is_some(), options.maybe_npm_resolver.is_some()); + + state.put(options.fs.clone()); + + if let Some(node_resolver) = &options.maybe_node_resolver { + state.put(node_resolver.clone()); + } + if let Some(npm_resolver) = &options.maybe_npm_resolver { state.put(npm_resolver.clone()); - state.put(Rc::new(NodeResolver::new( - fs, - npm_resolver, - ))) } }, global_template_middleware = global_template_middleware, diff --git a/ext/node/ops/require.rs b/ext/node/ops/require.rs index 176d64e56b..de26870013 100644 --- a/ext/node/ops/require.rs +++ b/ext/node/ops/require.rs @@ -16,10 +16,11 @@ use std::path::PathBuf; use std::rc::Rc; use crate::resolution; +use crate::resolution::NodeResolverRc; +use crate::AllowAllNodePermissions; use crate::NodeModuleKind; use crate::NodePermissions; use crate::NodeResolutionMode; -use crate::NodeResolver; use crate::NpmResolverRc; use crate::PackageJson; @@ -30,8 +31,8 @@ fn ensure_read_permission

( where P: NodePermissions + 'static, { - let resolver = state.borrow::(); - let permissions = state.borrow::

(); + let resolver = state.borrow::().clone(); + let permissions = state.borrow_mut::

(); resolver.ensure_read_permission(permissions, file_path) } @@ -386,12 +387,11 @@ where return Ok(None); } - let node_resolver = state.borrow::>(); - let permissions = state.borrow::

(); + let node_resolver = state.borrow::(); let pkg = node_resolver .get_closest_package_json( &Url::from_file_path(parent_path.unwrap()).unwrap(), - permissions, + &mut AllowAllNodePermissions, ) .ok() .flatten(); @@ -428,7 +428,6 @@ where NodeModuleKind::Cjs, resolution::REQUIRE_CONDITIONS, NodeResolutionMode::Execution, - permissions, )?; Ok(Some(if r.scheme() == "file" { url_to_file_path_string(&r)? @@ -483,8 +482,7 @@ where { let fs = state.borrow::(); let npm_resolver = state.borrow::(); - let node_resolver = state.borrow::>(); - let permissions = state.borrow::

(); + let node_resolver = state.borrow::(); let pkg_path = if npm_resolver .in_npm_package_at_file_path(&PathBuf::from(&modules_path)) @@ -501,7 +499,7 @@ where } }; let pkg = node_resolver.load_package_json( - permissions, + &mut AllowAllNodePermissions, PathBuf::from(&pkg_path).join("package.json"), )?; @@ -515,7 +513,6 @@ where NodeModuleKind::Cjs, resolution::REQUIRE_CONDITIONS, NodeResolutionMode::Execution, - permissions, )?; Ok(Some(if r.scheme() == "file" { url_to_file_path_string(&r)? @@ -540,8 +537,8 @@ where state, PathBuf::from(&filename).parent().unwrap(), )?; - let node_resolver = state.borrow::>(); - let permissions = state.borrow::

(); + let node_resolver = state.borrow::().clone(); + let permissions = state.borrow_mut::

(); node_resolver .get_closest_package_json( &Url::from_file_path(filename).unwrap(), @@ -559,8 +556,8 @@ pub fn op_require_read_package_scope

( where P: NodePermissions + 'static, { - let node_resolver = state.borrow::>(); - let permissions = state.borrow::

(); + let node_resolver = state.borrow::().clone(); + let permissions = state.borrow_mut::

(); let package_json_path = PathBuf::from(package_json_path); node_resolver .load_package_json(permissions, package_json_path) @@ -580,10 +577,11 @@ where { let referrer_path = PathBuf::from(&referrer_filename); ensure_read_permission::

(state, &referrer_path)?; - let node_resolver = state.borrow::>(); - let permissions = state.borrow::

(); - let Some(pkg) = node_resolver - .get_closest_package_json_from_path(&referrer_path, permissions)? + let node_resolver = state.borrow::(); + let Some(pkg) = node_resolver.get_closest_package_json_from_path( + &referrer_path, + &mut AllowAllNodePermissions, + )? else { return Ok(None); }; @@ -598,7 +596,6 @@ where Some(&pkg), resolution::REQUIRE_CONDITIONS, NodeResolutionMode::Execution, - permissions, )?; Ok(Some(url_to_file_path_string(&url)?)) } else { diff --git a/ext/node/ops/worker_threads.rs b/ext/node/ops/worker_threads.rs index 18a4157d42..182ba0118d 100644 --- a/ext/node/ops/worker_threads.rs +++ b/ext/node/ops/worker_threads.rs @@ -8,11 +8,10 @@ use deno_core::OpState; use deno_fs::FileSystemRc; use std::path::Path; use std::path::PathBuf; -use std::rc::Rc; use crate::resolution; +use crate::resolution::NodeResolverRc; use crate::NodePermissions; -use crate::NodeResolver; use crate::NpmResolverRc; fn ensure_read_permission

( @@ -22,8 +21,8 @@ fn ensure_read_permission

( where P: NodePermissions + 'static, { - let resolver = state.borrow::(); - let permissions = state.borrow::

(); + let resolver = state.borrow::().clone(); + let permissions = state.borrow_mut::

(); resolver.ensure_read_permission(permissions, file_path) } @@ -63,7 +62,7 @@ where if !fs.exists_sync(&url_path) { return Err(generic_error(format!("File not found [{:?}]", url_path))); } - let node_resolver = state.borrow::>(); + let node_resolver = state.borrow::(); match node_resolver.url_to_node_resolution(url)? { resolution::NodeResolution::Esm(u) => Ok(u.to_string()), resolution::NodeResolution::CommonJs(u) => wrap_cjs(u), diff --git a/ext/node/package_json.rs b/ext/node/package_json.rs index d4ffc80d68..adae7d6344 100644 --- a/ext/node/package_json.rs +++ b/ext/node/package_json.rs @@ -65,7 +65,7 @@ impl PackageJson { pub fn load( fs: &dyn deno_fs::FileSystem, resolver: &dyn NpmResolver, - permissions: &dyn NodePermissions, + permissions: &mut dyn NodePermissions, path: PathBuf, ) -> Result, AnyError> { resolver.ensure_read_permission(permissions, &path)?; diff --git a/ext/node/resolution.rs b/ext/node/resolution.rs index 37598810d3..834b465cde 100644 --- a/ext/node/resolution.rs +++ b/ext/node/resolution.rs @@ -154,7 +154,6 @@ impl NodeResolver { specifier: &str, referrer: &ModuleSpecifier, mode: NodeResolutionMode, - permissions: &dyn NodePermissions, ) -> Result, AnyError> { // Note: if we are here, then the referrer is an esm module // TODO(bartlomieju): skipped "policy" part as we don't plan to support it @@ -187,13 +186,8 @@ impl NodeResolver { } } - let url = self.module_resolve( - specifier, - referrer, - DEFAULT_CONDITIONS, - mode, - permissions, - )?; + let url = + self.module_resolve(specifier, referrer, DEFAULT_CONDITIONS, mode)?; let url = match url { Some(url) => url, None => return Ok(None), @@ -204,12 +198,8 @@ impl NodeResolver { let path = url.to_file_path().unwrap(); // todo(16370): the module kind is not correct here. I think we need // typescript to tell us if the referrer is esm or cjs - let maybe_decl_url = self.path_to_declaration_url( - path, - referrer, - NodeModuleKind::Esm, - permissions, - )?; + let maybe_decl_url = + self.path_to_declaration_url(path, referrer, NodeModuleKind::Esm)?; match maybe_decl_url { Some(url) => url, None => return Ok(None), @@ -229,7 +219,6 @@ impl NodeResolver { referrer: &ModuleSpecifier, conditions: &[&str], mode: NodeResolutionMode, - permissions: &dyn NodePermissions, ) -> Result, AnyError> { // note: if we're here, the referrer is an esm module let url = if should_be_treated_as_relative_or_absolute_path(specifier) { @@ -242,13 +231,13 @@ impl NodeResolver { file_path, referrer, NodeModuleKind::Esm, - permissions, )? } else { Some(resolved_specifier) } } else if specifier.starts_with('#') { - let pkg_config = self.get_closest_package_json(referrer, permissions)?; + let pkg_config = self + .get_closest_package_json(referrer, &mut AllowAllNodePermissions)?; Some(self.package_imports_resolve( specifier, referrer, @@ -256,7 +245,6 @@ impl NodeResolver { pkg_config.as_deref(), conditions, mode, - permissions, )?) } else if let Ok(resolved) = Url::parse(specifier) { Some(resolved) @@ -267,7 +255,6 @@ impl NodeResolver { NodeModuleKind::Esm, conditions, mode, - permissions, )? }; Ok(match url { @@ -337,11 +324,12 @@ impl NodeResolver { package_subpath: Option<&str>, referrer: &ModuleSpecifier, mode: NodeResolutionMode, - permissions: &dyn NodePermissions, ) -> Result, AnyError> { let package_json_path = package_dir.join("package.json"); - let package_json = - self.load_package_json(permissions, package_json_path.clone())?; + let package_json = self.load_package_json( + &mut AllowAllNodePermissions, + package_json_path.clone(), + )?; let node_module_kind = NodeModuleKind::Esm; let package_subpath = package_subpath .map(|s| format!("./{s}")) @@ -354,7 +342,6 @@ impl NodeResolver { node_module_kind, DEFAULT_CONDITIONS, mode, - permissions, ) .with_context(|| { format!( @@ -376,7 +363,6 @@ impl NodeResolver { path, referrer, node_module_kind, - permissions, )? { Some(url) => url, None => return Ok(None), @@ -397,8 +383,10 @@ impl NodeResolver { package_folder: &Path, ) -> Result, AnyError> { let package_json_path = package_folder.join("package.json"); - let package_json = self - .load_package_json(&AllowAllNodePermissions, package_json_path.clone())?; + let package_json = self.load_package_json( + &mut AllowAllNodePermissions, + package_json_path.clone(), + )?; Ok(match &package_json.bin { Some(Value::String(_)) => { @@ -420,8 +408,10 @@ impl NodeResolver { sub_path: Option<&str>, ) -> Result { let package_json_path = package_folder.join("package.json"); - let package_json = self - .load_package_json(&AllowAllNodePermissions, package_json_path.clone())?; + let package_json = self.load_package_json( + &mut AllowAllNodePermissions, + package_json_path.clone(), + )?; let bin_entry = resolve_bin_entry_value(&package_json, sub_path)?; let url = to_file_specifier(&package_folder.join(bin_entry)); @@ -440,7 +430,7 @@ impl NodeResolver { Ok(NodeResolution::Esm(url)) } else if url_str.ends_with(".js") || url_str.ends_with(".d.ts") { let maybe_package_config = - self.get_closest_package_json(&url, &AllowAllNodePermissions)?; + self.get_closest_package_json(&url, &mut AllowAllNodePermissions)?; match maybe_package_config { Some(c) if c.typ == "module" => Ok(NodeResolution::Esm(url)), Some(_) => Ok(NodeResolution::CommonJs(url)), @@ -467,7 +457,6 @@ impl NodeResolver { path: PathBuf, referrer: &ModuleSpecifier, referrer_kind: NodeModuleKind, - permissions: &dyn NodePermissions, ) -> Result, AnyError> { fn probe_extensions( fs: &dyn deno_fs::FileSystem, @@ -528,7 +517,7 @@ impl NodeResolver { if self.fs.is_dir_sync(&path) { let package_json_path = path.join("package.json"); if let Ok(pkg_json) = - self.load_package_json(permissions, package_json_path) + self.load_package_json(&mut AllowAllNodePermissions, package_json_path) { let maybe_resolution = self.resolve_package_subpath( &pkg_json, @@ -540,7 +529,6 @@ impl NodeResolver { NodeModuleKind::Cjs => REQUIRE_CONDITIONS, }, NodeResolutionMode::Types, - permissions, )?; if let Some(resolution) = maybe_resolution { return Ok(Some(resolution)); @@ -572,7 +560,6 @@ impl NodeResolver { referrer_pkg_json: Option<&PackageJson>, conditions: &[&str], mode: NodeResolutionMode, - permissions: &dyn NodePermissions, ) -> Result { if name == "#" || name.starts_with("#/") || name.ends_with('/') { let reason = "is not a valid internal imports specifier name"; @@ -601,7 +588,6 @@ impl NodeResolver { true, conditions, mode, - permissions, )?; if let Some(resolved) = maybe_resolved { return Ok(resolved); @@ -644,7 +630,6 @@ impl NodeResolver { true, conditions, mode, - permissions, )?; if let Some(resolved) = maybe_resolved { return Ok(resolved); @@ -675,7 +660,6 @@ impl NodeResolver { internal: bool, conditions: &[&str], mode: NodeResolutionMode, - permissions: &dyn NodePermissions, ) -> Result { if !subpath.is_empty() && !pattern && !target.ends_with('/') { return Err(throw_invalid_package_target( @@ -715,7 +699,6 @@ impl NodeResolver { referrer_kind, conditions, mode, - permissions, ) { Ok(Some(url)) => Ok(url), Ok(None) => Err(generic_error("not found")), @@ -804,7 +787,6 @@ impl NodeResolver { internal: bool, conditions: &[&str], mode: NodeResolutionMode, - permissions: &dyn NodePermissions, ) -> Result, AnyError> { if let Some(target) = target.as_str() { let url = self.resolve_package_target_string( @@ -818,16 +800,10 @@ impl NodeResolver { internal, conditions, mode, - permissions, )?; if mode.is_types() && url.scheme() == "file" { let path = url.to_file_path().unwrap(); - return self.path_to_declaration_url( - path, - referrer, - referrer_kind, - permissions, - ); + return self.path_to_declaration_url(path, referrer, referrer_kind); } else { return Ok(Some(url)); } @@ -849,7 +825,6 @@ impl NodeResolver { internal, conditions, mode, - permissions, ); match resolved_result { @@ -898,7 +873,6 @@ impl NodeResolver { internal, conditions, mode, - permissions, )?; match resolved { Some(resolved) => return Ok(Some(resolved)), @@ -931,7 +905,6 @@ impl NodeResolver { referrer_kind: NodeModuleKind, conditions: &[&str], mode: NodeResolutionMode, - permissions: &dyn NodePermissions, ) -> Result { if package_exports.contains_key(package_subpath) && package_subpath.find('*').is_none() @@ -949,7 +922,6 @@ impl NodeResolver { false, conditions, mode, - permissions, )?; return match resolved { Some(resolved) => Ok(resolved), @@ -1009,7 +981,6 @@ impl NodeResolver { false, conditions, mode, - permissions, )?; if let Some(resolved) = maybe_resolved { return Ok(resolved); @@ -1038,13 +1009,12 @@ impl NodeResolver { referrer_kind: NodeModuleKind, conditions: &[&str], mode: NodeResolutionMode, - permissions: &dyn NodePermissions, ) -> Result, AnyError> { let (package_name, package_subpath, _is_scoped) = parse_npm_pkg_name(specifier, referrer)?; let Some(package_config) = - self.get_closest_package_json(referrer, permissions)? + self.get_closest_package_json(referrer, &mut AllowAllNodePermissions)? else { return Ok(None); }; @@ -1062,7 +1032,6 @@ impl NodeResolver { referrer_kind, conditions, mode, - permissions, ) .map(Some); } @@ -1087,8 +1056,8 @@ impl NodeResolver { // )) // Package match. - let package_json = - self.load_package_json(permissions, package_json_path)?; + let package_json = self + .load_package_json(&mut AllowAllNodePermissions, package_json_path)?; self.resolve_package_subpath( &package_json, &package_subpath, @@ -1096,7 +1065,6 @@ impl NodeResolver { referrer_kind, conditions, mode, - permissions, ) } @@ -1109,7 +1077,6 @@ impl NodeResolver { referrer_kind: NodeModuleKind, conditions: &[&str], mode: NodeResolutionMode, - permissions: &dyn NodePermissions, ) -> Result, AnyError> { if let Some(exports) = &package_json.exports { let result = self.package_exports_resolve( @@ -1120,7 +1087,6 @@ impl NodeResolver { referrer_kind, conditions, mode, - permissions, ); match result { Ok(found) => return Ok(Some(found)), @@ -1131,7 +1097,6 @@ impl NodeResolver { referrer, referrer_kind, mode, - permissions, ); } return Err(exports_err); @@ -1144,18 +1109,12 @@ impl NodeResolver { referrer, referrer_kind, mode, - permissions, ); } let file_path = package_json.path.parent().unwrap().join(package_subpath); if mode.is_types() { - self.path_to_declaration_url( - file_path, - referrer, - referrer_kind, - permissions, - ) + self.path_to_declaration_url(file_path, referrer, referrer_kind) } else { Ok(Some(to_file_specifier(&file_path))) } @@ -1164,7 +1123,7 @@ impl NodeResolver { pub fn get_closest_package_json( &self, url: &ModuleSpecifier, - permissions: &dyn NodePermissions, + permissions: &mut dyn NodePermissions, ) -> Result>, AnyError> { let Ok(file_path) = url.to_file_path() else { return Ok(None); @@ -1175,7 +1134,7 @@ impl NodeResolver { pub fn get_closest_package_json_from_path( &self, file_path: &Path, - permissions: &dyn NodePermissions, + permissions: &mut dyn NodePermissions, ) -> Result>, AnyError> { let Some(package_json_path) = self.get_closest_package_json_path(file_path)? @@ -1212,7 +1171,7 @@ impl NodeResolver { pub(super) fn load_package_json( &self, - permissions: &dyn NodePermissions, + permissions: &mut dyn NodePermissions, package_json_path: PathBuf, ) -> Result, AnyError> { PackageJson::load( @@ -1229,7 +1188,6 @@ impl NodeResolver { referrer: &ModuleSpecifier, referrer_kind: NodeModuleKind, mode: NodeResolutionMode, - permissions: &dyn NodePermissions, ) -> Result, AnyError> { let maybe_main = if mode.is_types() { match package_json.types.as_ref() { @@ -1239,12 +1197,8 @@ impl NodeResolver { // a corresponding declaration file if let Some(main) = package_json.main(referrer_kind) { let main = package_json.path.parent().unwrap().join(main).clean(); - let maybe_decl_url = self.path_to_declaration_url( - main, - referrer, - referrer_kind, - permissions, - )?; + let maybe_decl_url = + self.path_to_declaration_url(main, referrer, referrer_kind)?; if let Some(path) = maybe_decl_url { return Ok(Some(path)); } diff --git a/ext/web/Cargo.toml b/ext/web/Cargo.toml index f99193e0b5..ec65d51b44 100644 --- a/ext/web/Cargo.toml +++ b/ext/web/Cargo.toml @@ -18,6 +18,7 @@ async-trait.workspace = true base64-simd = "0.8" bytes.workspace = true deno_core.workspace = true +deno_permissions.workspace = true encoding_rs.workspace = true flate2 = { workspace = true, features = ["default"] } futures.workspace = true diff --git a/ext/web/timers.rs b/ext/web/timers.rs index b3060a46fd..648be57155 100644 --- a/ext/web/timers.rs +++ b/ext/web/timers.rs @@ -10,6 +10,13 @@ pub trait TimersPermission { fn allow_hrtime(&mut self) -> bool; } +impl TimersPermission for deno_permissions::PermissionsContainer { + #[inline(always)] + fn allow_hrtime(&mut self) -> bool { + deno_permissions::PermissionsContainer::allow_hrtime(self) + } +} + pub type StartTime = Instant; // Returns a milliseconds and nanoseconds subsec diff --git a/ext/websocket/Cargo.toml b/ext/websocket/Cargo.toml index f2e8c90f9c..059f40f633 100644 --- a/ext/websocket/Cargo.toml +++ b/ext/websocket/Cargo.toml @@ -17,6 +17,7 @@ path = "lib.rs" bytes.workspace = true deno_core.workspace = true deno_net.workspace = true +deno_permissions.workspace = true deno_tls.workspace = true fastwebsockets.workspace = true h2.workspace = true diff --git a/ext/websocket/lib.rs b/ext/websocket/lib.rs index 06a75faabd..87503120bf 100644 --- a/ext/websocket/lib.rs +++ b/ext/websocket/lib.rs @@ -99,6 +99,17 @@ pub trait WebSocketPermissions { ) -> Result<(), AnyError>; } +impl WebSocketPermissions for deno_permissions::PermissionsContainer { + #[inline(always)] + fn check_net_url( + &mut self, + url: &url::Url, + api_name: &str, + ) -> Result<(), AnyError> { + deno_permissions::PermissionsContainer::check_net_url(self, url, api_name) + } +} + /// `UnsafelyIgnoreCertificateErrors` is a wrapper struct so it can be placed inside `GothamState`; /// using type alias for a `Option>` could work, but there's a high chance /// that there might be another type alias pointing to a `Option>`, which diff --git a/runtime/examples/extension/main.rs b/runtime/examples/extension/main.rs index 0d7c4efb00..4339bdf679 100644 --- a/runtime/examples/extension/main.rs +++ b/runtime/examples/extension/main.rs @@ -10,7 +10,7 @@ use deno_core::error::AnyError; use deno_core::op2; use deno_core::FsModuleLoader; use deno_core::ModuleSpecifier; -use deno_runtime::permissions::PermissionsContainer; +use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::worker::MainWorker; use deno_runtime::worker::WorkerOptions; diff --git a/runtime/lib.rs b/runtime/lib.rs index ec751f207a..c92f5aea21 100644 --- a/runtime/lib.rs +++ b/runtime/lib.rs @@ -33,7 +33,6 @@ pub mod fs_util; pub mod inspector_server; pub mod js; pub mod ops; -pub mod permissions; pub mod snapshot; pub mod tokio_util; pub mod web_worker; diff --git a/runtime/ops/fs_events.rs b/runtime/ops/fs_events.rs index 1e8fab936b..367866162f 100644 --- a/runtime/ops/fs_events.rs +++ b/runtime/ops/fs_events.rs @@ -1,6 +1,5 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use crate::permissions::PermissionsContainer; use deno_core::error::AnyError; use deno_core::parking_lot::Mutex; use deno_core::AsyncRefCell; @@ -13,6 +12,7 @@ use deno_core::ResourceId; use deno_core::op2; +use deno_permissions::PermissionsContainer; use notify::event::Event as NotifyEvent; use notify::Error as NotifyError; use notify::EventKind; diff --git a/runtime/ops/os/mod.rs b/runtime/ops/os/mod.rs index f6f55f68fa..c2611f869b 100644 --- a/runtime/ops/os/mod.rs +++ b/runtime/ops/os/mod.rs @@ -1,7 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use super::utils::into_string; -use crate::permissions::PermissionsContainer; use crate::worker::ExitCode; use deno_core::error::type_error; use deno_core::error::AnyError; @@ -10,6 +9,7 @@ use deno_core::url::Url; use deno_core::v8; use deno_core::OpState; use deno_node::NODE_ENV_VAR_ALLOWLIST; +use deno_permissions::PermissionsContainer; use serde::Serialize; use std::collections::HashMap; use std::env; diff --git a/runtime/ops/process.rs b/runtime/ops/process.rs index bda6045aca..b894b35db7 100644 --- a/runtime/ops/process.rs +++ b/runtime/ops/process.rs @@ -1,7 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use super::check_unstable; -use crate::permissions::PermissionsContainer; use deno_core::anyhow::Context; use deno_core::error::type_error; use deno_core::error::AnyError; @@ -18,6 +17,7 @@ use deno_io::fs::FileResource; use deno_io::ChildStderrResource; use deno_io::ChildStdinResource; use deno_io::ChildStdoutResource; +use deno_permissions::PermissionsContainer; use serde::Deserialize; use serde::Serialize; use std::borrow::Cow; diff --git a/runtime/ops/runtime.rs b/runtime/ops/runtime.rs index 5b0b092c19..306e6ce8f7 100644 --- a/runtime/ops/runtime.rs +++ b/runtime/ops/runtime.rs @@ -1,10 +1,10 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use crate::permissions::PermissionsContainer; use deno_core::error::AnyError; use deno_core::op2; use deno_core::ModuleSpecifier; use deno_core::OpState; +use deno_permissions::PermissionsContainer; deno_core::extension!( deno_runtime, diff --git a/runtime/ops/worker_host.rs b/runtime/ops/worker_host.rs index e3360b8305..19475fedf1 100644 --- a/runtime/ops/worker_host.rs +++ b/runtime/ops/worker_host.rs @@ -1,9 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use crate::ops::TestingFeaturesEnabled; -use crate::permissions::create_child_permissions; -use crate::permissions::ChildPermissionsArg; -use crate::permissions::PermissionsContainer; use crate::web_worker::run_web_worker; use crate::web_worker::SendableWebWorkerHandle; use crate::web_worker::WebWorker; @@ -20,6 +17,9 @@ use deno_core::CancelFuture; use deno_core::CancelHandle; use deno_core::ModuleSpecifier; use deno_core::OpState; +use deno_permissions::create_child_permissions; +use deno_permissions::ChildPermissionsArg; +use deno_permissions::PermissionsContainer; use deno_web::deserialize_js_transferables; use deno_web::JsMessageData; use log::debug; @@ -156,7 +156,7 @@ fn op_create_worker( let parent_permissions = state.borrow_mut::(); let worker_permissions = if let Some(child_permissions_arg) = args.permissions { - let mut parent_permissions = parent_permissions.0 .0.lock(); + let mut parent_permissions = parent_permissions.0.lock(); let perms = create_child_permissions(&mut parent_permissions, child_permissions_arg)?; PermissionsContainer::new(perms) diff --git a/runtime/permissions.rs b/runtime/permissions.rs deleted file mode 100644 index edd03e1d52..0000000000 --- a/runtime/permissions.rs +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -use std::borrow::Cow; -use std::path::Path; - -use deno_core::error::AnyError; -use deno_core::url::Url; -pub use deno_io::fs::FsError; -pub use deno_permissions::create_child_permissions; -pub use deno_permissions::parse_sys_kind; -pub use deno_permissions::set_prompt_callbacks; -pub use deno_permissions::ChildPermissionsArg; -pub use deno_permissions::Permissions; -pub use deno_permissions::PermissionsOptions; - -// NOTE: Temporary permissions container to satisfy traits. We are migrating to the deno_permissions -// crate. -#[derive(Debug, Clone)] - -pub struct PermissionsContainer(pub deno_permissions::PermissionsContainer); - -impl PermissionsContainer { - pub fn new(permissions: deno_permissions::Permissions) -> Self { - Self(deno_permissions::PermissionsContainer::new(permissions)) - } - - pub fn allow_all() -> Self { - Self(deno_permissions::PermissionsContainer::allow_all()) - } -} - -impl std::ops::Deref for PermissionsContainer { - type Target = deno_permissions::PermissionsContainer; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl std::ops::DerefMut for PermissionsContainer { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - -impl deno_node::NodePermissions for PermissionsContainer { - #[inline(always)] - fn check_net_url( - &mut self, - url: &Url, - api_name: &str, - ) -> Result<(), AnyError> { - self.0.check_net_url(url, api_name) - } - - #[inline(always)] - fn check_read_with_api_name( - &self, - path: &Path, - api_name: Option<&str>, - ) -> Result<(), AnyError> { - self.0.check_read_with_api_name(path, api_name) - } - - #[inline(always)] - fn check_write_with_api_name( - &self, - path: &Path, - api_name: Option<&str>, - ) -> Result<(), AnyError> { - self.0.check_write_with_api_name(path, api_name) - } - - fn check_sys(&self, kind: &str, api_name: &str) -> Result<(), AnyError> { - self.0.check_sys(kind, api_name) - } -} - -impl deno_fetch::FetchPermissions for PermissionsContainer { - #[inline(always)] - fn check_net_url( - &mut self, - url: &Url, - api_name: &str, - ) -> Result<(), AnyError> { - self.0.check_net_url(url, api_name) - } - - #[inline(always)] - fn check_read( - &mut self, - path: &Path, - api_name: &str, - ) -> Result<(), AnyError> { - self.0.check_read(path, api_name) - } -} - -impl deno_net::NetPermissions for PermissionsContainer { - #[inline(always)] - fn check_net>( - &mut self, - host: &(T, Option), - api_name: &str, - ) -> Result<(), AnyError> { - self.0.check_net(host, api_name) - } - - #[inline(always)] - fn check_read( - &mut self, - path: &Path, - api_name: &str, - ) -> Result<(), AnyError> { - self.0.check_read(path, api_name) - } - - #[inline(always)] - fn check_write( - &mut self, - path: &Path, - api_name: &str, - ) -> Result<(), AnyError> { - self.0.check_write(path, api_name) - } -} - -impl deno_web::TimersPermission for PermissionsContainer { - #[inline(always)] - fn allow_hrtime(&mut self) -> bool { - self.0.allow_hrtime() - } -} - -impl deno_websocket::WebSocketPermissions for PermissionsContainer { - #[inline(always)] - fn check_net_url( - &mut self, - url: &Url, - api_name: &str, - ) -> Result<(), AnyError> { - self.0.check_net_url(url, api_name) - } -} - -impl deno_fs::FsPermissions for PermissionsContainer { - fn check_open<'a>( - &mut self, - resolved: bool, - read: bool, - write: bool, - path: &'a Path, - api_name: &str, - ) -> Result, FsError> { - if resolved { - self.check_special_file(path, api_name).map_err(|_| { - std::io::Error::from(std::io::ErrorKind::PermissionDenied) - })?; - return Ok(Cow::Borrowed(path)); - } - - // If somehow read or write aren't specified, use read - let read = read || !write; - if read { - deno_fs::FsPermissions::check_read(self, path, api_name) - .map_err(|_| FsError::PermissionDenied("read"))?; - } - if write { - deno_fs::FsPermissions::check_write(self, path, api_name) - .map_err(|_| FsError::PermissionDenied("write"))?; - } - Ok(Cow::Borrowed(path)) - } - - fn check_read( - &mut self, - path: &Path, - api_name: &str, - ) -> Result<(), AnyError> { - self.0.check_read(path, api_name) - } - - fn check_read_blind( - &mut self, - path: &Path, - display: &str, - api_name: &str, - ) -> Result<(), AnyError> { - self.0.check_read_blind(path, display, api_name) - } - - fn check_write( - &mut self, - path: &Path, - api_name: &str, - ) -> Result<(), AnyError> { - self.0.check_write(path, api_name) - } - - fn check_write_partial( - &mut self, - path: &Path, - api_name: &str, - ) -> Result<(), AnyError> { - self.0.check_write_partial(path, api_name) - } - - fn check_write_blind( - &mut self, - p: &Path, - display: &str, - api_name: &str, - ) -> Result<(), AnyError> { - self.0.check_write_blind(p, display, api_name) - } - - fn check_read_all(&mut self, api_name: &str) -> Result<(), AnyError> { - self.0.check_read_all(api_name) - } - - fn check_write_all(&mut self, api_name: &str) -> Result<(), AnyError> { - self.0.check_write_all(api_name) - } -} - -// NOTE(bartlomieju): for now, NAPI uses `--allow-ffi` flag, but that might -// change in the future. -impl deno_napi::NapiPermissions for PermissionsContainer { - #[inline(always)] - fn check(&mut self, path: Option<&Path>) -> Result<(), AnyError> { - self.0.check_ffi(path) - } -} - -impl deno_ffi::FfiPermissions for PermissionsContainer { - #[inline(always)] - fn check_partial(&mut self, path: Option<&Path>) -> Result<(), AnyError> { - self.0.check_ffi_partial(path) - } -} - -impl deno_kv::sqlite::SqliteDbHandlerPermissions for PermissionsContainer { - #[inline(always)] - fn check_read(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError> { - self.0.check_read(p, api_name) - } - - #[inline(always)] - fn check_write(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError> { - self.0.check_write(p, api_name) - } -} - -impl deno_kv::remote::RemoteDbHandlerPermissions for PermissionsContainer { - #[inline(always)] - fn check_env(&mut self, var: &str) -> Result<(), AnyError> { - self.0.check_env(var) - } - - #[inline(always)] - fn check_net_url( - &mut self, - url: &Url, - api_name: &str, - ) -> Result<(), AnyError> { - self.0.check_net_url(url, api_name) - } -} diff --git a/runtime/snapshot.rs b/runtime/snapshot.rs index 923ea0b759..7ae5e3ae5b 100644 --- a/runtime/snapshot.rs +++ b/runtime/snapshot.rs @@ -81,21 +81,21 @@ impl deno_node::NodePermissions for Permissions { unreachable!("snapshotting!") } fn check_read_with_api_name( - &self, + &mut self, _p: &Path, _api_name: Option<&str>, ) -> Result<(), deno_core::error::AnyError> { unreachable!("snapshotting!") } fn check_write_with_api_name( - &self, + &mut self, _p: &Path, _api_name: Option<&str>, ) -> Result<(), deno_core::error::AnyError> { unreachable!("snapshotting!") } fn check_sys( - &self, + &mut self, _kind: &str, _api_name: &str, ) -> Result<(), deno_core::error::AnyError> { @@ -254,7 +254,7 @@ pub fn create_runtime_snapshot( deno_http::deno_http::init_ops_and_esm::(), deno_io::deno_io::init_ops_and_esm(Default::default()), deno_fs::deno_fs::init_ops_and_esm::(fs.clone()), - deno_node::deno_node::init_ops_and_esm::(None, fs), + deno_node::deno_node::init_ops_and_esm::(None, None, fs), runtime::init_ops_and_esm(), ops::runtime::deno_runtime::init_ops("deno:runtime".parse().unwrap()), ops::worker_host::deno_worker_host::init_ops( diff --git a/runtime/web_worker.rs b/runtime/web_worker.rs index 8360356940..07a955efb8 100644 --- a/runtime/web_worker.rs +++ b/runtime/web_worker.rs @@ -2,7 +2,6 @@ use crate::inspector_server::InspectorServer; use crate::ops; use crate::ops::worker_host::WorkersTable; -use crate::permissions::PermissionsContainer; use crate::shared::maybe_transpile_source; use crate::shared::runtime; use crate::tokio_util::create_and_run_current_thread; @@ -45,6 +44,8 @@ use deno_fs::FileSystem; use deno_http::DefaultHttpPropertyExtractor; use deno_io::Stdio; use deno_kv::dynamic::MultiBackendDbHandler; +use deno_node::NodeResolver; +use deno_permissions::PermissionsContainer; use deno_terminal::colors; use deno_tls::RootCertStoreProvider; use deno_tls::TlsKeys; @@ -364,6 +365,7 @@ pub struct WebWorkerOptions { pub seed: Option, pub fs: Arc, pub module_loader: Rc, + pub node_resolver: Option>, pub npm_resolver: Option>, pub create_web_worker_cb: Arc, pub format_js_error_fn: Option>, @@ -411,7 +413,6 @@ impl WebWorker { enable_testing_features: bool, }, state = |state, options| { - state.put::(options.permissions.0.clone()); state.put::(options.permissions); state.put(ops::TestingFeaturesEnabled(options.enable_testing_features)); }, @@ -491,6 +492,7 @@ impl WebWorker { options.fs.clone(), ), deno_node::deno_node::init_ops_and_esm::( + options.node_resolver, options.npm_resolver, options.fs, ), diff --git a/runtime/worker.rs b/runtime/worker.rs index 09faa6e087..4e16afeeb1 100644 --- a/runtime/worker.rs +++ b/runtime/worker.rs @@ -39,6 +39,7 @@ use deno_fs::FileSystem; use deno_http::DefaultHttpPropertyExtractor; use deno_io::Stdio; use deno_kv::dynamic::MultiBackendDbHandler; +use deno_permissions::PermissionsContainer; use deno_tls::RootCertStoreProvider; use deno_tls::TlsKeys; use deno_web::BlobStore; @@ -48,7 +49,6 @@ use crate::code_cache::CodeCache; use crate::code_cache::CodeCacheType; use crate::inspector_server::InspectorServer; use crate::ops; -use crate::permissions::PermissionsContainer; use crate::shared::maybe_transpile_source; use crate::shared::runtime; use crate::BootstrapOptions; @@ -156,6 +156,7 @@ pub struct WorkerOptions { /// If not provided runtime will error if code being /// executed tries to load modules. pub module_loader: Rc, + pub node_resolver: Option>, pub npm_resolver: Option>, // Callbacks invoked when creating new instance of WebWorker pub create_web_worker_cb: Arc, @@ -227,6 +228,7 @@ impl Default for WorkerOptions { broadcast_channel: Default::default(), source_map_getter: Default::default(), root_cert_store_provider: Default::default(), + node_resolver: Default::default(), npm_resolver: Default::default(), blob_store: Default::default(), extensions: Default::default(), @@ -329,9 +331,6 @@ impl MainWorker { enable_testing_features: bool, }, state = |state, options| { - // Save the permissions container and the wrapper. - state.put::(options.permissions.0.clone()); - // This is temporary until we migrate all exts/ to the deno_permissions crate. state.put::(options.permissions); state.put(ops::TestingFeaturesEnabled(options.enable_testing_features)); }, @@ -419,6 +418,7 @@ impl MainWorker { options.fs.clone(), ), deno_node::deno_node::init_ops_and_esm::( + options.node_resolver, options.npm_resolver, options.fs, ),