use std::borrow::Cow;
use std::path::Path;
use deno_core::FastString;
use deno_core::ModuleSpecifier;
use deno_error::JsErrorBox;
use deno_media_type::MediaType;
use deno_resolver::npm::DenoInNpmPackageChecker;
use node_resolver::errors::PackageJsonLoadError;
use node_resolver::InNpmPackageChecker;
use deno_runtime::deno_permissions::OpenAccessKind;
use deno_runtime::deno_permissions::PermissionsContainer;
pub struct FsCjsAnalysisSourceProvider {
permissions: PermissionsContainer,
in_npm_pkg_checker: DenoInNpmPackageChecker,
}
impl FsCjsAnalysisSourceProvider {
pub fn new(
permissions: PermissionsContainer,
in_npm_pkg_checker: DenoInNpmPackageChecker,
) -> Self {
Self {
permissions,
in_npm_pkg_checker,
}
}
}
impl node_resolver::analyze::CjsAnalysisSourceProvider for FsCjsAnalysisSourceProvider {
fn load_source<'a>(&'a self, specifier: &ModuleSpecifier) -> Option<Cow<'a, str>> {
let path = specifier.to_file_path().ok()?;
if !self.permissions.query_read_all() {
let canonical = std::fs::canonicalize(&path).unwrap_or_else(|_| path.clone());
let in_npm_package = ModuleSpecifier::from_file_path(&canonical)
.ok()
.map(|url| self.in_npm_pkg_checker.in_npm_package(&url))
.unwrap_or(false);
if !in_npm_package
&& self
.permissions
.check_open(
Cow::Owned(canonical),
OpenAccessKind::Read,
Some("CJS analysis"),
)
.is_err()
{
return None;
}
}
std::fs::read_to_string(path).ok().map(Cow::Owned)
}
}
pub struct SimpleNodeRequireLoader {
cjs_tracker: deno_resolver::cjs::CjsTrackerRc<
deno_resolver::npm::DenoInNpmPackageChecker,
sys_traits::impls::RealSys,
>,
in_npm_pkg_checker: DenoInNpmPackageChecker,
}
impl SimpleNodeRequireLoader {
pub fn new(
cjs_tracker: deno_resolver::cjs::CjsTrackerRc<
deno_resolver::npm::DenoInNpmPackageChecker,
sys_traits::impls::RealSys,
>,
in_npm_pkg_checker: DenoInNpmPackageChecker,
) -> Self {
Self {
cjs_tracker,
in_npm_pkg_checker,
}
}
}
impl deno_runtime::deno_node::NodeRequireLoader for SimpleNodeRequireLoader {
fn ensure_read_permission<'a>(
&self,
permissions: &mut deno_runtime::deno_permissions::PermissionsContainer,
path: Cow<'a, Path>,
) -> Result<Cow<'a, Path>, JsErrorBox> {
if permissions.query_read_all() {
return Ok(path);
}
let canonical =
std::fs::canonicalize(path.as_ref()).unwrap_or_else(|_| path.as_ref().to_path_buf());
let in_npm_package = ModuleSpecifier::from_file_path(&canonical)
.ok()
.map(|url| self.in_npm_pkg_checker.in_npm_package(&url))
.unwrap_or(false);
if in_npm_package {
return Ok(Cow::Owned(canonical));
}
permissions
.check_open(Cow::Owned(canonical), OpenAccessKind::Read, Some("require"))
.map(|checked| checked.into_path())
.map_err(JsErrorBox::from_err)
}
fn load_text_file_lossy(&self, path: &Path) -> Result<FastString, JsErrorBox> {
std::fs::read_to_string(path)
.map(Into::into)
.map_err(|e| JsErrorBox::generic(format!("Failed to read {path:?}: {e}")))
}
fn is_maybe_cjs(&self, specifier: &url::Url) -> Result<bool, PackageJsonLoadError> {
self.cjs_tracker
.is_maybe_cjs(specifier, MediaType::from_specifier(specifier))
}
fn is_maybe_cjs_from_require(
&self,
specifier: &url::Url,
) -> Result<bool, PackageJsonLoadError> {
self.cjs_tracker
.is_maybe_cjs_from_require(specifier, MediaType::from_specifier(specifier))
}
}