mirror of
https://github.com/denoland/deno.git
synced 2024-12-25 00:29:09 -05:00
perf(runtime): optimize allocations in read/write checks (#15631)
This commit is contained in:
parent
19fb9abe33
commit
8e1c0e5141
3 changed files with 35 additions and 17 deletions
|
@ -9,6 +9,7 @@ use std::path::PathBuf;
|
||||||
///
|
///
|
||||||
/// Taken from Cargo
|
/// Taken from Cargo
|
||||||
/// <https://github.com/rust-lang/cargo/blob/af307a38c20a753ec60f0ad18be5abed3db3c9ac/src/cargo/util/paths.rs#L60-L85>
|
/// <https://github.com/rust-lang/cargo/blob/af307a38c20a753ec60f0ad18be5abed3db3c9ac/src/cargo/util/paths.rs#L60-L85>
|
||||||
|
#[inline]
|
||||||
pub fn normalize_path<P: AsRef<Path>>(path: P) -> PathBuf {
|
pub fn normalize_path<P: AsRef<Path>>(path: P) -> PathBuf {
|
||||||
let mut components = path.as_ref().components().peekable();
|
let mut components = path.as_ref().components().peekable();
|
||||||
let mut ret =
|
let mut ret =
|
||||||
|
|
|
@ -21,16 +21,15 @@ pub fn canonicalize_path(path: &Path) -> Result<PathBuf, Error> {
|
||||||
Ok(canonicalized_path)
|
Ok(canonicalized_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn resolve_from_cwd(path: &Path) -> Result<PathBuf, AnyError> {
|
pub fn resolve_from_cwd(path: &Path) -> Result<PathBuf, AnyError> {
|
||||||
let resolved_path = if path.is_absolute() {
|
if path.is_absolute() {
|
||||||
path.to_owned()
|
Ok(normalize_path(path))
|
||||||
} else {
|
} else {
|
||||||
let cwd =
|
let cwd =
|
||||||
current_dir().context("Failed to get current working directory")?;
|
current_dir().context("Failed to get current working directory")?;
|
||||||
cwd.join(path)
|
Ok(normalize_path(&cwd.join(path)))
|
||||||
};
|
}
|
||||||
|
|
||||||
Ok(normalize_path(&resolved_path))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -43,7 +43,7 @@ pub enum PermissionState {
|
||||||
|
|
||||||
impl PermissionState {
|
impl PermissionState {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn log_perm_access(name: &str, info: Option<&str>) {
|
fn log_perm_access(name: &str, info: impl FnOnce() -> Option<String>) {
|
||||||
// Eliminates log overhead (when logging is disabled),
|
// Eliminates log overhead (when logging is disabled),
|
||||||
// log_enabled!(Debug) check in a hot path still has overhead
|
// log_enabled!(Debug) check in a hot path still has overhead
|
||||||
// TODO(AaronO): generalize or upstream this optimization
|
// TODO(AaronO): generalize or upstream this optimization
|
||||||
|
@ -59,15 +59,15 @@ impl PermissionState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fmt_access(name: &str, info: Option<&str>) -> String {
|
fn fmt_access(name: &str, info: impl FnOnce() -> Option<String>) -> String {
|
||||||
format!(
|
format!(
|
||||||
"{} access{}",
|
"{} access{}",
|
||||||
name,
|
name,
|
||||||
info.map_or(String::new(), |info| { format!(" to {}", info) }),
|
info().map_or(String::new(), |info| { format!(" to {}", info) }),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error(name: &str, info: Option<&str>) -> AnyError {
|
fn error(name: &str, info: impl FnOnce() -> Option<String>) -> AnyError {
|
||||||
custom_error(
|
custom_error(
|
||||||
"PermissionDenied",
|
"PermissionDenied",
|
||||||
format!(
|
format!(
|
||||||
|
@ -79,11 +79,22 @@ impl PermissionState {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check the permission state. bool is whether a prompt was issued.
|
/// Check the permission state. bool is whether a prompt was issued.
|
||||||
|
#[inline]
|
||||||
fn check(
|
fn check(
|
||||||
self,
|
self,
|
||||||
name: &str,
|
name: &str,
|
||||||
info: Option<&str>,
|
info: Option<&str>,
|
||||||
prompt: bool,
|
prompt: bool,
|
||||||
|
) -> (Result<(), AnyError>, bool) {
|
||||||
|
self.check2(name, || info.map(|s| s.to_string()), prompt)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn check2(
|
||||||
|
self,
|
||||||
|
name: &str,
|
||||||
|
info: impl Fn() -> Option<String>,
|
||||||
|
prompt: bool,
|
||||||
) -> (Result<(), AnyError>, bool) {
|
) -> (Result<(), AnyError>, bool) {
|
||||||
match self {
|
match self {
|
||||||
PermissionState::Granted => {
|
PermissionState::Granted => {
|
||||||
|
@ -91,7 +102,11 @@ impl PermissionState {
|
||||||
(Ok(()), false)
|
(Ok(()), false)
|
||||||
}
|
}
|
||||||
PermissionState::Prompt if prompt => {
|
PermissionState::Prompt if prompt => {
|
||||||
let msg = Self::fmt_access(name, info);
|
let msg = format!(
|
||||||
|
"{} access{}",
|
||||||
|
name,
|
||||||
|
info().map_or(String::new(), |info| { format!(" to {}", info) }),
|
||||||
|
);
|
||||||
if permission_prompt(&msg, name) {
|
if permission_prompt(&msg, name) {
|
||||||
Self::log_perm_access(name, info);
|
Self::log_perm_access(name, info);
|
||||||
(Ok(()), true)
|
(Ok(()), true)
|
||||||
|
@ -367,14 +382,15 @@ impl UnaryPermission<ReadDescriptor> {
|
||||||
self.query(path)
|
self.query(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn check(&mut self, path: &Path) -> Result<(), AnyError> {
|
pub fn check(&mut self, path: &Path) -> Result<(), AnyError> {
|
||||||
let (resolved_path, display_path) = resolved_and_display_path(path);
|
let (result, prompted) = self.query(Some(path)).check2(
|
||||||
let (result, prompted) = self.query(Some(&resolved_path)).check(
|
|
||||||
self.name,
|
self.name,
|
||||||
Some(&format!("\"{}\"", display_path.display())),
|
|| Some(format!("\"{}\"", path.to_path_buf().display())),
|
||||||
self.prompt,
|
self.prompt,
|
||||||
);
|
);
|
||||||
if prompted {
|
if prompted {
|
||||||
|
let resolved_path = resolve_from_cwd(path).unwrap();
|
||||||
if result.is_ok() {
|
if result.is_ok() {
|
||||||
self.granted_list.insert(ReadDescriptor(resolved_path));
|
self.granted_list.insert(ReadDescriptor(resolved_path));
|
||||||
} else {
|
} else {
|
||||||
|
@ -518,14 +534,15 @@ impl UnaryPermission<WriteDescriptor> {
|
||||||
self.query(path)
|
self.query(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn check(&mut self, path: &Path) -> Result<(), AnyError> {
|
pub fn check(&mut self, path: &Path) -> Result<(), AnyError> {
|
||||||
let (resolved_path, display_path) = resolved_and_display_path(path);
|
let (result, prompted) = self.query(Some(path)).check2(
|
||||||
let (result, prompted) = self.query(Some(&resolved_path)).check(
|
|
||||||
self.name,
|
self.name,
|
||||||
Some(&format!("\"{}\"", display_path.display())),
|
|| Some(format!("\"{}\"", path.to_path_buf().display())),
|
||||||
self.prompt,
|
self.prompt,
|
||||||
);
|
);
|
||||||
if prompted {
|
if prompted {
|
||||||
|
let resolved_path = resolve_from_cwd(path).unwrap();
|
||||||
if result.is_ok() {
|
if result.is_ok() {
|
||||||
self.granted_list.insert(WriteDescriptor(resolved_path));
|
self.granted_list.insert(WriteDescriptor(resolved_path));
|
||||||
} else {
|
} else {
|
||||||
|
@ -1459,6 +1476,7 @@ pub fn resolve_ffi_allowlist(
|
||||||
|
|
||||||
/// Arbitrary helper. Resolves the path from CWD, and also gets a path that
|
/// Arbitrary helper. Resolves the path from CWD, and also gets a path that
|
||||||
/// can be displayed without leaking the CWD when not allowed.
|
/// can be displayed without leaking the CWD when not allowed.
|
||||||
|
#[inline]
|
||||||
fn resolved_and_display_path(path: &Path) -> (PathBuf, PathBuf) {
|
fn resolved_and_display_path(path: &Path) -> (PathBuf, PathBuf) {
|
||||||
let resolved_path = resolve_from_cwd(path).unwrap();
|
let resolved_path = resolve_from_cwd(path).unwrap();
|
||||||
let display_path = path.to_path_buf();
|
let display_path = path.to_path_buf();
|
||||||
|
|
Loading…
Reference in a new issue