diff options
Diffstat (limited to 'ext')
-rw-r--r-- | ext/fetch/Cargo.toml | 1 | ||||
-rw-r--r-- | ext/fetch/lib.rs | 20 | ||||
-rw-r--r-- | ext/ffi/Cargo.toml | 1 | ||||
-rw-r--r-- | ext/ffi/lib.rs | 7 | ||||
-rw-r--r-- | ext/fs/Cargo.toml | 1 | ||||
-rw-r--r-- | ext/fs/lib.rs | 89 | ||||
-rw-r--r-- | ext/kv/Cargo.toml | 1 | ||||
-rw-r--r-- | ext/kv/remote.rs | 16 | ||||
-rw-r--r-- | ext/kv/sqlite.rs | 12 | ||||
-rw-r--r-- | ext/napi/Cargo.toml | 1 | ||||
-rw-r--r-- | ext/napi/lib.rs | 9 | ||||
-rw-r--r-- | ext/net/Cargo.toml | 1 | ||||
-rw-r--r-- | ext/net/lib.rs | 29 | ||||
-rw-r--r-- | ext/node/analyze.rs | 12 | ||||
-rw-r--r-- | ext/node/global.rs | 5 | ||||
-rw-r--r-- | ext/node/lib.rs | 78 | ||||
-rw-r--r-- | ext/node/ops/require.rs | 37 | ||||
-rw-r--r-- | ext/node/ops/worker_threads.rs | 9 | ||||
-rw-r--r-- | ext/node/package_json.rs | 2 | ||||
-rw-r--r-- | ext/node/resolution.rs | 106 | ||||
-rw-r--r-- | ext/web/Cargo.toml | 1 | ||||
-rw-r--r-- | ext/web/timers.rs | 7 | ||||
-rw-r--r-- | ext/websocket/Cargo.toml | 1 | ||||
-rw-r--r-- | ext/websocket/lib.rs | 11 |
24 files changed, 325 insertions, 132 deletions
diff --git a/ext/fetch/Cargo.toml b/ext/fetch/Cargo.toml index 75884466b..a5cc650b1 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 21ca04027..066f1685b 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 fb0d4ae2a..e8e984acb 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 4e8129240..26b06d98f 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 b5ac5199c..f13dc1cbf 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 d6794d3ac..2dce04b32 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<Cow<'a, Path>, 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 9cc7e0889..99f3d8051 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 9d5e099c7..a1273e78b 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<P: RemoteDbHandlerPermissions + 'static> { http_options: HttpOptions, _p: std::marker::PhantomData<P>, diff --git a/ext/kv/sqlite.rs b/ext/kv/sqlite.rs index a8a7fbace..6dd821bda 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<P: SqliteDbHandlerPermissions> SqliteDbHandler<P> { pub fn new( default_storage_dir: Option<PathBuf>, diff --git a/ext/napi/Cargo.toml b/ext/napi/Cargo.toml index 2342f313f..c6f3c7685 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 b3313f0fe..f4fa33438 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 b9ddf8d70..10dfd0d77 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 fa8074b34..3b6c05282 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<T: AsRef<str>>( + &mut self, + host: &(T, Option<u16>), + 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 b7adfd5ce..df68cb0fc 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<TCjsCodeAnalyzer: CjsCodeAnalyzer> NodeCodeTranslator<TCjsCodeAnalyzer> { &self, entry_specifier: &ModuleSpecifier, source: Option<String>, - permissions: &dyn NodePermissions, ) -> Result<String, AnyError> { let mut temp_var_count = 0; @@ -115,7 +114,6 @@ impl<TCjsCodeAnalyzer: CjsCodeAnalyzer> NodeCodeTranslator<TCjsCodeAnalyzer> { .analyze_reexports( entry_specifier, analysis.reexports, - permissions, &mut all_exports, &mut errors, ) @@ -161,7 +159,6 @@ impl<TCjsCodeAnalyzer: CjsCodeAnalyzer> NodeCodeTranslator<TCjsCodeAnalyzer> { &'a self, entry_specifier: &url::Url, reexports: Vec<String>, - permissions: &dyn NodePermissions, all_exports: &mut HashSet<String>, // this goes through the modules concurrently, so collect // the errors in order to be deterministic @@ -194,7 +191,6 @@ impl<TCjsCodeAnalyzer: CjsCodeAnalyzer> NodeCodeTranslator<TCjsCodeAnalyzer> { // 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<TCjsCodeAnalyzer: CjsCodeAnalyzer> NodeCodeTranslator<TCjsCodeAnalyzer> { referrer: &ModuleSpecifier, conditions: &[&str], mode: NodeResolutionMode, - permissions: &dyn NodePermissions, ) -> Result<ModuleSpecifier, AnyError> { if specifier.starts_with('/') { todo!(); @@ -319,7 +314,7 @@ impl<TCjsCodeAnalyzer: CjsCodeAnalyzer> NodeCodeTranslator<TCjsCodeAnalyzer> { 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<TCjsCodeAnalyzer: CjsCodeAnalyzer> NodeCodeTranslator<TCjsCodeAnalyzer> { NodeModuleKind::Esm, conditions, mode, - permissions, ); } @@ -345,7 +339,7 @@ impl<TCjsCodeAnalyzer: CjsCodeAnalyzer> NodeCodeTranslator<TCjsCodeAnalyzer> { 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 0aaa6ed8b..d2fe7a1e5 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::<Rc<NodeResolver>>() else { + let Some(node_resolver) = op_state.try_borrow::<NodeResolverRc>() else { return Mode::Deno; }; let mut buffer = [MaybeUninit::uninit(); 2048]; diff --git a/ext/node/lib.rs b/ext/node/lib.rs index 2b31f704f..a15125f60 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<dyn NpmResolver>; @@ -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<NodeResolverRc>, maybe_npm_resolver: Option<NpmResolverRc>, 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 176d64e56..de2687001 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<P>( where P: NodePermissions + 'static, { - let resolver = state.borrow::<NpmResolverRc>(); - let permissions = state.borrow::<P>(); + let resolver = state.borrow::<NpmResolverRc>().clone(); + let permissions = state.borrow_mut::<P>(); resolver.ensure_read_permission(permissions, file_path) } @@ -386,12 +387,11 @@ where return Ok(None); } - let node_resolver = state.borrow::<Rc<NodeResolver>>(); - let permissions = state.borrow::<P>(); + let node_resolver = state.borrow::<NodeResolverRc>(); 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::<FileSystemRc>(); let npm_resolver = state.borrow::<NpmResolverRc>(); - let node_resolver = state.borrow::<Rc<NodeResolver>>(); - let permissions = state.borrow::<P>(); + let node_resolver = state.borrow::<NodeResolverRc>(); 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::<Rc<NodeResolver>>(); - let permissions = state.borrow::<P>(); + let node_resolver = state.borrow::<NodeResolverRc>().clone(); + let permissions = state.borrow_mut::<P>(); node_resolver .get_closest_package_json( &Url::from_file_path(filename).unwrap(), @@ -559,8 +556,8 @@ pub fn op_require_read_package_scope<P>( where P: NodePermissions + 'static, { - let node_resolver = state.borrow::<Rc<NodeResolver>>(); - let permissions = state.borrow::<P>(); + let node_resolver = state.borrow::<NodeResolverRc>().clone(); + let permissions = state.borrow_mut::<P>(); 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::<P>(state, &referrer_path)?; - let node_resolver = state.borrow::<Rc<NodeResolver>>(); - let permissions = state.borrow::<P>(); - let Some(pkg) = node_resolver - .get_closest_package_json_from_path(&referrer_path, permissions)? + let node_resolver = state.borrow::<NodeResolverRc>(); + 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 18a4157d4..182ba0118 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<P>( @@ -22,8 +21,8 @@ fn ensure_read_permission<P>( where P: NodePermissions + 'static, { - let resolver = state.borrow::<NpmResolverRc>(); - let permissions = state.borrow::<P>(); + let resolver = state.borrow::<NpmResolverRc>().clone(); + let permissions = state.borrow_mut::<P>(); 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::<Rc<NodeResolver>>(); + let node_resolver = state.borrow::<NodeResolverRc>(); 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 d4ffc80d6..adae7d634 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<Rc<PackageJson>, AnyError> { resolver.ensure_read_permission(permissions, &path)?; diff --git a/ext/node/resolution.rs b/ext/node/resolution.rs index 37598810d..834b465cd 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<Option<NodeResolution>, 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<Option<ModuleSpecifier>, 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<Option<NodeResolution>, 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<Vec<String>, 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<NodeResolution, 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(), + )?; 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<Option<ModuleSpecifier>, 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<ModuleSpecifier, AnyError> { 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<ModuleSpecifier, AnyError> { 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<Option<ModuleSpecifier>, 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<ModuleSpecifier, AnyError> { 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<Option<ModuleSpecifier>, 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<Option<ModuleSpecifier>, 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<Option<Rc<PackageJson>>, 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<Option<Rc<PackageJson>>, 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<Rc<PackageJson>, AnyError> { PackageJson::load( @@ -1229,7 +1188,6 @@ impl NodeResolver { referrer: &ModuleSpecifier, referrer_kind: NodeModuleKind, mode: NodeResolutionMode, - permissions: &dyn NodePermissions, ) -> Result<Option<ModuleSpecifier>, 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 f99193e0b..ec65d51b4 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 b3060a46f..648be5715 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 f2e8c90f9..059f40f63 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 06a75faab..87503120b 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<Vec<String>>` could work, but there's a high chance /// that there might be another type alias pointing to a `Option<Vec<String>>`, which |