mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
refactor: decouple node resolution from deno_core (#24724)
This commit is contained in:
parent
0cf7f268a7
commit
3bf147fe28
45 changed files with 939 additions and 518 deletions
22
Cargo.lock
generated
22
Cargo.lock
generated
|
@ -1167,6 +1167,7 @@ dependencies = [
|
||||||
"monch",
|
"monch",
|
||||||
"napi_sym",
|
"napi_sym",
|
||||||
"nix 0.26.2",
|
"nix 0.26.2",
|
||||||
|
"node_resolver",
|
||||||
"notify",
|
"notify",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"open",
|
"open",
|
||||||
|
@ -1767,6 +1768,7 @@ dependencies = [
|
||||||
"libz-sys",
|
"libz-sys",
|
||||||
"md-5",
|
"md-5",
|
||||||
"md4",
|
"md4",
|
||||||
|
"node_resolver",
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"num-bigint-dig",
|
"num-bigint-dig",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
|
@ -1908,6 +1910,7 @@ dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"netif",
|
"netif",
|
||||||
"nix 0.26.2",
|
"nix 0.26.2",
|
||||||
|
"node_resolver",
|
||||||
"notify",
|
"notify",
|
||||||
"ntapi",
|
"ntapi",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
@ -4341,6 +4344,25 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "node_resolver"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"async-trait",
|
||||||
|
"deno_media_type",
|
||||||
|
"deno_package_json",
|
||||||
|
"futures",
|
||||||
|
"lazy-regex",
|
||||||
|
"once_cell",
|
||||||
|
"path-clean",
|
||||||
|
"regex",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom"
|
name = "nom"
|
||||||
version = "5.1.3"
|
version = "5.1.3"
|
||||||
|
|
|
@ -21,6 +21,7 @@ members = [
|
||||||
"ext/napi",
|
"ext/napi",
|
||||||
"ext/net",
|
"ext/net",
|
||||||
"ext/node",
|
"ext/node",
|
||||||
|
"ext/node_resolver",
|
||||||
"ext/url",
|
"ext/url",
|
||||||
"ext/web",
|
"ext/web",
|
||||||
"ext/webgpu",
|
"ext/webgpu",
|
||||||
|
@ -83,6 +84,7 @@ deno_webgpu = { version = "0.129.0", path = "./ext/webgpu" }
|
||||||
deno_webidl = { version = "0.162.0", path = "./ext/webidl" }
|
deno_webidl = { version = "0.162.0", path = "./ext/webidl" }
|
||||||
deno_websocket = { version = "0.167.0", path = "./ext/websocket" }
|
deno_websocket = { version = "0.167.0", path = "./ext/websocket" }
|
||||||
deno_webstorage = { version = "0.157.0", path = "./ext/webstorage" }
|
deno_webstorage = { version = "0.157.0", path = "./ext/webstorage" }
|
||||||
|
node_resolver = { version = "0.1.0", path = "./ext/node_resolver" }
|
||||||
|
|
||||||
aes = "=0.8.3"
|
aes = "=0.8.3"
|
||||||
anyhow = "1.0.57"
|
anyhow = "1.0.57"
|
||||||
|
|
|
@ -80,6 +80,7 @@ deno_task_shell = "=0.17.0"
|
||||||
deno_terminal.workspace = true
|
deno_terminal.workspace = true
|
||||||
eszip = "=0.72.2"
|
eszip = "=0.72.2"
|
||||||
napi_sym.workspace = true
|
napi_sym.workspace = true
|
||||||
|
node_resolver.workspace = true
|
||||||
|
|
||||||
async-trait.workspace = true
|
async-trait.workspace = true
|
||||||
base32.workspace = true
|
base32.workspace = true
|
||||||
|
|
|
@ -820,9 +820,7 @@ impl CliOptions {
|
||||||
WorkspaceDiscoverOptions {
|
WorkspaceDiscoverOptions {
|
||||||
fs: Default::default(), // use real fs
|
fs: Default::default(), // use real fs
|
||||||
deno_json_cache: None,
|
deno_json_cache: None,
|
||||||
pkg_json_cache: Some(
|
pkg_json_cache: Some(&node_resolver::PackageJsonThreadLocalCache),
|
||||||
&deno_runtime::deno_node::PackageJsonThreadLocalCache,
|
|
||||||
),
|
|
||||||
workspace_cache: None,
|
workspace_cache: None,
|
||||||
config_parse_options,
|
config_parse_options,
|
||||||
additional_config_file_names,
|
additional_config_file_names,
|
||||||
|
|
|
@ -62,13 +62,14 @@ use deno_core::futures::FutureExt;
|
||||||
use deno_core::FeatureChecker;
|
use deno_core::FeatureChecker;
|
||||||
|
|
||||||
use deno_runtime::deno_fs;
|
use deno_runtime::deno_fs;
|
||||||
use deno_runtime::deno_node::analyze::NodeCodeTranslator;
|
use deno_runtime::deno_node::DenoFsNodeResolverEnv;
|
||||||
use deno_runtime::deno_node::NodeResolver;
|
use deno_runtime::deno_node::NodeResolver;
|
||||||
use deno_runtime::deno_tls::rustls::RootCertStore;
|
use deno_runtime::deno_tls::rustls::RootCertStore;
|
||||||
use deno_runtime::deno_tls::RootCertStoreProvider;
|
use deno_runtime::deno_tls::RootCertStoreProvider;
|
||||||
use deno_runtime::deno_web::BlobStore;
|
use deno_runtime::deno_web::BlobStore;
|
||||||
use deno_runtime::inspector_server::InspectorServer;
|
use deno_runtime::inspector_server::InspectorServer;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
|
use node_resolver::analyze::NodeCodeTranslator;
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -553,7 +554,7 @@ impl CliFactory {
|
||||||
.get_or_try_init_async(
|
.get_or_try_init_async(
|
||||||
async {
|
async {
|
||||||
Ok(Arc::new(NodeResolver::new(
|
Ok(Arc::new(NodeResolver::new(
|
||||||
self.fs().clone(),
|
DenoFsNodeResolverEnv::new(self.fs().clone()),
|
||||||
self.npm_resolver().await?.clone().into_npm_resolver(),
|
self.npm_resolver().await?.clone().into_npm_resolver(),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
@ -577,7 +578,7 @@ impl CliFactory {
|
||||||
|
|
||||||
Ok(Arc::new(NodeCodeTranslator::new(
|
Ok(Arc::new(NodeCodeTranslator::new(
|
||||||
cjs_esm_analyzer,
|
cjs_esm_analyzer,
|
||||||
self.fs().clone(),
|
DenoFsNodeResolverEnv::new(self.fs().clone()),
|
||||||
self.node_resolver().await?.clone(),
|
self.node_resolver().await?.clone(),
|
||||||
self.npm_resolver().await?.clone().into_npm_resolver(),
|
self.npm_resolver().await?.clone().into_npm_resolver(),
|
||||||
)))
|
)))
|
||||||
|
|
|
@ -23,7 +23,6 @@ use deno_core::serde::Serialize;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_core::serde_json::json;
|
use deno_core::serde_json::json;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use deno_runtime::deno_node::NpmResolver;
|
|
||||||
use deno_runtime::deno_node::PathClean;
|
use deno_runtime::deno_node::PathClean;
|
||||||
use deno_semver::jsr::JsrPackageNvReference;
|
use deno_semver::jsr::JsrPackageNvReference;
|
||||||
use deno_semver::jsr::JsrPackageReqReference;
|
use deno_semver::jsr::JsrPackageReqReference;
|
||||||
|
@ -34,6 +33,7 @@ use deno_semver::package::PackageReq;
|
||||||
use deno_semver::package::PackageReqReference;
|
use deno_semver::package::PackageReqReference;
|
||||||
use deno_semver::Version;
|
use deno_semver::Version;
|
||||||
use import_map::ImportMap;
|
use import_map::ImportMap;
|
||||||
|
use node_resolver::NpmResolver;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
|
@ -35,11 +35,7 @@ use deno_graph::GraphImport;
|
||||||
use deno_graph::ModuleSpecifier;
|
use deno_graph::ModuleSpecifier;
|
||||||
use deno_npm::NpmSystemInfo;
|
use deno_npm::NpmSystemInfo;
|
||||||
use deno_runtime::deno_fs;
|
use deno_runtime::deno_fs;
|
||||||
use deno_runtime::deno_node::errors::ClosestPkgJsonError;
|
|
||||||
use deno_runtime::deno_node::NodeResolution;
|
|
||||||
use deno_runtime::deno_node::NodeResolutionMode;
|
|
||||||
use deno_runtime::deno_node::NodeResolver;
|
use deno_runtime::deno_node::NodeResolver;
|
||||||
use deno_runtime::deno_node::NpmResolver;
|
|
||||||
use deno_runtime::deno_node::PackageJson;
|
use deno_runtime::deno_node::PackageJson;
|
||||||
use deno_runtime::fs_util::specifier_to_file_path;
|
use deno_runtime::fs_util::specifier_to_file_path;
|
||||||
use deno_semver::jsr::JsrPackageReqReference;
|
use deno_semver::jsr::JsrPackageReqReference;
|
||||||
|
@ -47,6 +43,10 @@ use deno_semver::npm::NpmPackageReqReference;
|
||||||
use deno_semver::package::PackageNv;
|
use deno_semver::package::PackageNv;
|
||||||
use deno_semver::package::PackageReq;
|
use deno_semver::package::PackageReq;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
use node_resolver::errors::ClosestPkgJsonError;
|
||||||
|
use node_resolver::NodeResolution;
|
||||||
|
use node_resolver::NodeResolutionMode;
|
||||||
|
use node_resolver::NpmResolver;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
|
@ -496,7 +496,7 @@ fn create_node_resolver(
|
||||||
let npm_resolver = npm_resolver?;
|
let npm_resolver = npm_resolver?;
|
||||||
let fs = Arc::new(deno_fs::RealFs);
|
let fs = Arc::new(deno_fs::RealFs);
|
||||||
let node_resolver_inner = Arc::new(NodeResolver::new(
|
let node_resolver_inner = Arc::new(NodeResolver::new(
|
||||||
fs.clone(),
|
deno_runtime::deno_node::DenoFsNodeResolverEnv::new(fs.clone()),
|
||||||
npm_resolver.clone().into_npm_resolver(),
|
npm_resolver.clone().into_npm_resolver(),
|
||||||
));
|
));
|
||||||
Some(Arc::new(CliNodeResolver::new(
|
Some(Arc::new(CliNodeResolver::new(
|
||||||
|
|
|
@ -64,9 +64,9 @@ use deno_graph::Module;
|
||||||
use deno_graph::ModuleGraph;
|
use deno_graph::ModuleGraph;
|
||||||
use deno_graph::Resolution;
|
use deno_graph::Resolution;
|
||||||
use deno_runtime::code_cache;
|
use deno_runtime::code_cache;
|
||||||
use deno_runtime::deno_node::NodeResolutionMode;
|
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
|
use node_resolver::NodeResolutionMode;
|
||||||
|
|
||||||
pub async fn load_top_level_deps(factory: &CliFactory) -> Result<(), AnyError> {
|
pub async fn load_top_level_deps(factory: &CliFactory) -> Result<(), AnyError> {
|
||||||
let npm_resolver = factory.npm_resolver().await?;
|
let npm_resolver = factory.npm_resolver().await?;
|
||||||
|
|
12
cli/node.rs
12
cli/node.rs
|
@ -6,10 +6,11 @@ use deno_ast::MediaType;
|
||||||
use deno_ast::ModuleSpecifier;
|
use deno_ast::ModuleSpecifier;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_runtime::deno_fs;
|
use deno_runtime::deno_fs;
|
||||||
use deno_runtime::deno_node::analyze::CjsAnalysis as ExtNodeCjsAnalysis;
|
use deno_runtime::deno_node::DenoFsNodeResolverEnv;
|
||||||
use deno_runtime::deno_node::analyze::CjsAnalysisExports;
|
use node_resolver::analyze::CjsAnalysis as ExtNodeCjsAnalysis;
|
||||||
use deno_runtime::deno_node::analyze::CjsCodeAnalyzer;
|
use node_resolver::analyze::CjsAnalysisExports;
|
||||||
use deno_runtime::deno_node::analyze::NodeCodeTranslator;
|
use node_resolver::analyze::CjsCodeAnalyzer;
|
||||||
|
use node_resolver::analyze::NodeCodeTranslator;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
|
@ -17,7 +18,8 @@ use crate::cache::CacheDBHash;
|
||||||
use crate::cache::NodeAnalysisCache;
|
use crate::cache::NodeAnalysisCache;
|
||||||
use crate::util::fs::canonicalize_path_maybe_not_exists;
|
use crate::util::fs::canonicalize_path_maybe_not_exists;
|
||||||
|
|
||||||
pub type CliNodeCodeTranslator = NodeCodeTranslator<CliCjsCodeAnalyzer>;
|
pub type CliNodeCodeTranslator =
|
||||||
|
NodeCodeTranslator<CliCjsCodeAnalyzer, DenoFsNodeResolverEnv>;
|
||||||
|
|
||||||
/// Resolves a specifier that is pointing into a node_modules folder.
|
/// Resolves a specifier that is pointing into a node_modules folder.
|
||||||
///
|
///
|
||||||
|
|
|
@ -11,14 +11,18 @@ use deno_core::error::AnyError;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_package_json::PackageJsonDepValue;
|
use deno_package_json::PackageJsonDepValue;
|
||||||
use deno_runtime::deno_fs::FileSystem;
|
use deno_runtime::deno_fs::FileSystem;
|
||||||
use deno_runtime::deno_node::errors::PackageFolderResolveError;
|
use deno_runtime::deno_node::DenoPkgJsonFsAdapter;
|
||||||
use deno_runtime::deno_node::errors::PackageFolderResolveIoError;
|
|
||||||
use deno_runtime::deno_node::errors::PackageNotFoundError;
|
|
||||||
use deno_runtime::deno_node::load_pkg_json;
|
|
||||||
use deno_runtime::deno_node::NodePermissions;
|
use deno_runtime::deno_node::NodePermissions;
|
||||||
use deno_runtime::deno_node::NpmResolver;
|
use deno_runtime::deno_node::NodeRequireResolver;
|
||||||
|
use deno_runtime::deno_node::NpmProcessStateProvider;
|
||||||
use deno_runtime::deno_node::PackageJson;
|
use deno_runtime::deno_node::PackageJson;
|
||||||
use deno_semver::package::PackageReq;
|
use deno_semver::package::PackageReq;
|
||||||
|
use node_resolver::errors::PackageFolderResolveError;
|
||||||
|
use node_resolver::errors::PackageFolderResolveIoError;
|
||||||
|
use node_resolver::errors::PackageJsonLoadError;
|
||||||
|
use node_resolver::errors::PackageNotFoundError;
|
||||||
|
use node_resolver::load_pkg_json;
|
||||||
|
use node_resolver::NpmResolver;
|
||||||
|
|
||||||
use crate::args::NpmProcessState;
|
use crate::args::NpmProcessState;
|
||||||
use crate::args::NpmProcessStateKind;
|
use crate::args::NpmProcessStateKind;
|
||||||
|
@ -49,6 +53,15 @@ pub struct ByonmCliNpmResolver {
|
||||||
root_node_modules_dir: Option<PathBuf>,
|
root_node_modules_dir: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ByonmCliNpmResolver {
|
||||||
|
fn load_pkg_json(
|
||||||
|
&self,
|
||||||
|
path: &Path,
|
||||||
|
) -> Result<Option<Arc<PackageJson>>, PackageJsonLoadError> {
|
||||||
|
load_pkg_json(&DenoPkgJsonFsAdapter(self.fs.as_ref()), path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ByonmCliNpmResolver {
|
impl ByonmCliNpmResolver {
|
||||||
/// Finds the ancestor package.json that contains the specified dependency.
|
/// Finds the ancestor package.json that contains the specified dependency.
|
||||||
pub fn find_ancestor_package_json_with_dep(
|
pub fn find_ancestor_package_json_with_dep(
|
||||||
|
@ -60,9 +73,7 @@ impl ByonmCliNpmResolver {
|
||||||
let mut current_folder = referrer_path.parent()?;
|
let mut current_folder = referrer_path.parent()?;
|
||||||
loop {
|
loop {
|
||||||
let pkg_json_path = current_folder.join("package.json");
|
let pkg_json_path = current_folder.join("package.json");
|
||||||
if let Ok(Some(pkg_json)) =
|
if let Ok(Some(pkg_json)) = self.load_pkg_json(&pkg_json_path) {
|
||||||
load_pkg_json(self.fs.as_ref(), &pkg_json_path)
|
|
||||||
{
|
|
||||||
if let Some(deps) = &pkg_json.dependencies {
|
if let Some(deps) = &pkg_json.dependencies {
|
||||||
if deps.contains_key(dep_name) {
|
if deps.contains_key(dep_name) {
|
||||||
return Some(pkg_json);
|
return Some(pkg_json);
|
||||||
|
@ -119,9 +130,7 @@ impl ByonmCliNpmResolver {
|
||||||
let mut current_path = file_path.as_path();
|
let mut current_path = file_path.as_path();
|
||||||
while let Some(dir_path) = current_path.parent() {
|
while let Some(dir_path) = current_path.parent() {
|
||||||
let package_json_path = dir_path.join("package.json");
|
let package_json_path = dir_path.join("package.json");
|
||||||
if let Some(pkg_json) =
|
if let Some(pkg_json) = self.load_pkg_json(&package_json_path)? {
|
||||||
load_pkg_json(self.fs.as_ref(), &package_json_path)?
|
|
||||||
{
|
|
||||||
if let Some(alias) =
|
if let Some(alias) =
|
||||||
resolve_alias_from_pkg_json(req, pkg_json.as_ref())
|
resolve_alias_from_pkg_json(req, pkg_json.as_ref())
|
||||||
{
|
{
|
||||||
|
@ -136,9 +145,7 @@ impl ByonmCliNpmResolver {
|
||||||
if let Some(root_node_modules_dir) = &self.root_node_modules_dir {
|
if let Some(root_node_modules_dir) = &self.root_node_modules_dir {
|
||||||
let root_pkg_json_path =
|
let root_pkg_json_path =
|
||||||
root_node_modules_dir.parent().unwrap().join("package.json");
|
root_node_modules_dir.parent().unwrap().join("package.json");
|
||||||
if let Some(pkg_json) =
|
if let Some(pkg_json) = self.load_pkg_json(&root_pkg_json_path)? {
|
||||||
load_pkg_json(self.fs.as_ref(), &root_pkg_json_path)?
|
|
||||||
{
|
|
||||||
if let Some(alias) = resolve_alias_from_pkg_json(req, pkg_json.as_ref())
|
if let Some(alias) = resolve_alias_from_pkg_json(req, pkg_json.as_ref())
|
||||||
{
|
{
|
||||||
return Ok((pkg_json, alias));
|
return Ok((pkg_json, alias));
|
||||||
|
@ -158,17 +165,6 @@ impl ByonmCliNpmResolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NpmResolver for ByonmCliNpmResolver {
|
impl NpmResolver for ByonmCliNpmResolver {
|
||||||
fn get_npm_process_state(&self) -> String {
|
|
||||||
serde_json::to_string(&NpmProcessState {
|
|
||||||
kind: NpmProcessStateKind::Byonm,
|
|
||||||
local_node_modules_path: self
|
|
||||||
.root_node_modules_dir
|
|
||||||
.as_ref()
|
|
||||||
.map(|p| p.to_string_lossy().to_string()),
|
|
||||||
})
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_package_folder_from_package(
|
fn resolve_package_folder_from_package(
|
||||||
&self,
|
&self,
|
||||||
name: &str,
|
name: &str,
|
||||||
|
@ -226,7 +222,9 @@ impl NpmResolver for ByonmCliNpmResolver {
|
||||||
.to_ascii_lowercase()
|
.to_ascii_lowercase()
|
||||||
.contains("/node_modules/")
|
.contains("/node_modules/")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NodeRequireResolver for ByonmCliNpmResolver {
|
||||||
fn ensure_read_permission(
|
fn ensure_read_permission(
|
||||||
&self,
|
&self,
|
||||||
permissions: &mut dyn NodePermissions,
|
permissions: &mut dyn NodePermissions,
|
||||||
|
@ -242,11 +240,34 @@ impl NpmResolver for ByonmCliNpmResolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl NpmProcessStateProvider for ByonmCliNpmResolver {
|
||||||
|
fn get_npm_process_state(&self) -> String {
|
||||||
|
serde_json::to_string(&NpmProcessState {
|
||||||
|
kind: NpmProcessStateKind::Byonm,
|
||||||
|
local_node_modules_path: self
|
||||||
|
.root_node_modules_dir
|
||||||
|
.as_ref()
|
||||||
|
.map(|p| p.to_string_lossy().to_string()),
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl CliNpmResolver for ByonmCliNpmResolver {
|
impl CliNpmResolver for ByonmCliNpmResolver {
|
||||||
fn into_npm_resolver(self: Arc<Self>) -> Arc<dyn NpmResolver> {
|
fn into_npm_resolver(self: Arc<Self>) -> Arc<dyn NpmResolver> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn into_require_resolver(self: Arc<Self>) -> Arc<dyn NodeRequireResolver> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_process_state_provider(
|
||||||
|
self: Arc<Self>,
|
||||||
|
) -> Arc<dyn NpmProcessStateProvider> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn clone_snapshotted(&self) -> Arc<dyn CliNpmResolver> {
|
fn clone_snapshotted(&self) -> Arc<dyn CliNpmResolver> {
|
||||||
Arc::new(Self {
|
Arc::new(Self {
|
||||||
fs: self.fs.clone(),
|
fs: self.fs.clone(),
|
||||||
|
|
|
@ -20,12 +20,14 @@ use deno_npm::NpmPackageId;
|
||||||
use deno_npm::NpmResolutionPackage;
|
use deno_npm::NpmResolutionPackage;
|
||||||
use deno_npm::NpmSystemInfo;
|
use deno_npm::NpmSystemInfo;
|
||||||
use deno_runtime::deno_fs::FileSystem;
|
use deno_runtime::deno_fs::FileSystem;
|
||||||
use deno_runtime::deno_node::errors::PackageFolderResolveError;
|
|
||||||
use deno_runtime::deno_node::errors::PackageFolderResolveIoError;
|
|
||||||
use deno_runtime::deno_node::NodePermissions;
|
use deno_runtime::deno_node::NodePermissions;
|
||||||
use deno_runtime::deno_node::NpmResolver;
|
use deno_runtime::deno_node::NodeRequireResolver;
|
||||||
|
use deno_runtime::deno_node::NpmProcessStateProvider;
|
||||||
use deno_semver::package::PackageNv;
|
use deno_semver::package::PackageNv;
|
||||||
use deno_semver::package::PackageReq;
|
use deno_semver::package::PackageReq;
|
||||||
|
use node_resolver::errors::PackageFolderResolveError;
|
||||||
|
use node_resolver::errors::PackageFolderResolveIoError;
|
||||||
|
use node_resolver::NpmResolver;
|
||||||
use resolution::AddPkgReqsResult;
|
use resolution::AddPkgReqsResult;
|
||||||
|
|
||||||
use crate::args::CliLockfile;
|
use crate::args::CliLockfile;
|
||||||
|
@ -531,14 +533,6 @@ fn npm_process_state(
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NpmResolver for ManagedCliNpmResolver {
|
impl NpmResolver for ManagedCliNpmResolver {
|
||||||
/// Gets the state of npm for the process.
|
|
||||||
fn get_npm_process_state(&self) -> String {
|
|
||||||
npm_process_state(
|
|
||||||
self.resolution.serialized_valid_snapshot(),
|
|
||||||
self.fs_resolver.node_modules_path().map(|p| p.as_path()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_package_folder_from_package(
|
fn resolve_package_folder_from_package(
|
||||||
&self,
|
&self,
|
||||||
name: &str,
|
name: &str,
|
||||||
|
@ -563,7 +557,9 @@ impl NpmResolver for ManagedCliNpmResolver {
|
||||||
debug_assert!(root_dir_url.as_str().ends_with('/'));
|
debug_assert!(root_dir_url.as_str().ends_with('/'));
|
||||||
specifier.as_ref().starts_with(root_dir_url.as_str())
|
specifier.as_ref().starts_with(root_dir_url.as_str())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NodeRequireResolver for ManagedCliNpmResolver {
|
||||||
fn ensure_read_permission(
|
fn ensure_read_permission(
|
||||||
&self,
|
&self,
|
||||||
permissions: &mut dyn NodePermissions,
|
permissions: &mut dyn NodePermissions,
|
||||||
|
@ -573,11 +569,30 @@ impl NpmResolver for ManagedCliNpmResolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl NpmProcessStateProvider for ManagedCliNpmResolver {
|
||||||
|
fn get_npm_process_state(&self) -> String {
|
||||||
|
npm_process_state(
|
||||||
|
self.resolution.serialized_valid_snapshot(),
|
||||||
|
self.fs_resolver.node_modules_path().map(|p| p.as_path()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl CliNpmResolver for ManagedCliNpmResolver {
|
impl CliNpmResolver for ManagedCliNpmResolver {
|
||||||
fn into_npm_resolver(self: Arc<Self>) -> Arc<dyn NpmResolver> {
|
fn into_npm_resolver(self: Arc<Self>) -> Arc<dyn NpmResolver> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn into_require_resolver(self: Arc<Self>) -> Arc<dyn NodeRequireResolver> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_process_state_provider(
|
||||||
|
self: Arc<Self>,
|
||||||
|
) -> Arc<dyn NpmProcessStateProvider> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn clone_snapshotted(&self) -> Arc<dyn CliNpmResolver> {
|
fn clone_snapshotted(&self) -> Arc<dyn CliNpmResolver> {
|
||||||
// create a new snapshotted npm resolution and resolver
|
// create a new snapshotted npm resolution and resolver
|
||||||
let npm_resolution = Arc::new(NpmResolution::new(
|
let npm_resolution = Arc::new(NpmResolution::new(
|
||||||
|
|
|
@ -18,8 +18,8 @@ use deno_npm::NpmPackageCacheFolderId;
|
||||||
use deno_npm::NpmPackageId;
|
use deno_npm::NpmPackageId;
|
||||||
use deno_npm::NpmResolutionPackage;
|
use deno_npm::NpmResolutionPackage;
|
||||||
use deno_runtime::deno_fs::FileSystem;
|
use deno_runtime::deno_fs::FileSystem;
|
||||||
use deno_runtime::deno_node::errors::PackageFolderResolveError;
|
|
||||||
use deno_runtime::deno_node::NodePermissions;
|
use deno_runtime::deno_node::NodePermissions;
|
||||||
|
use node_resolver::errors::PackageFolderResolveError;
|
||||||
|
|
||||||
use crate::npm::managed::cache::TarballCache;
|
use crate::npm::managed::cache::TarballCache;
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,10 @@ use deno_npm::NpmPackageCacheFolderId;
|
||||||
use deno_npm::NpmPackageId;
|
use deno_npm::NpmPackageId;
|
||||||
use deno_npm::NpmSystemInfo;
|
use deno_npm::NpmSystemInfo;
|
||||||
use deno_runtime::deno_fs::FileSystem;
|
use deno_runtime::deno_fs::FileSystem;
|
||||||
use deno_runtime::deno_node::errors::PackageFolderResolveError;
|
|
||||||
use deno_runtime::deno_node::errors::PackageNotFoundError;
|
|
||||||
use deno_runtime::deno_node::errors::ReferrerNotFoundError;
|
|
||||||
use deno_runtime::deno_node::NodePermissions;
|
use deno_runtime::deno_node::NodePermissions;
|
||||||
|
use node_resolver::errors::PackageFolderResolveError;
|
||||||
|
use node_resolver::errors::PackageNotFoundError;
|
||||||
|
use node_resolver::errors::ReferrerNotFoundError;
|
||||||
|
|
||||||
use super::super::cache::NpmCache;
|
use super::super::cache::NpmCache;
|
||||||
use super::super::cache::TarballCache;
|
use super::super::cache::TarballCache;
|
||||||
|
|
|
@ -32,12 +32,12 @@ use deno_npm::NpmPackageId;
|
||||||
use deno_npm::NpmResolutionPackage;
|
use deno_npm::NpmResolutionPackage;
|
||||||
use deno_npm::NpmSystemInfo;
|
use deno_npm::NpmSystemInfo;
|
||||||
use deno_runtime::deno_fs;
|
use deno_runtime::deno_fs;
|
||||||
use deno_runtime::deno_node::errors::PackageFolderResolveError;
|
|
||||||
use deno_runtime::deno_node::errors::PackageFolderResolveIoError;
|
|
||||||
use deno_runtime::deno_node::errors::PackageNotFoundError;
|
|
||||||
use deno_runtime::deno_node::errors::ReferrerNotFoundError;
|
|
||||||
use deno_runtime::deno_node::NodePermissions;
|
use deno_runtime::deno_node::NodePermissions;
|
||||||
use deno_semver::package::PackageNv;
|
use deno_semver::package::PackageNv;
|
||||||
|
use node_resolver::errors::PackageFolderResolveError;
|
||||||
|
use node_resolver::errors::PackageFolderResolveIoError;
|
||||||
|
use node_resolver::errors::PackageNotFoundError;
|
||||||
|
use node_resolver::errors::ReferrerNotFoundError;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
|
|
|
@ -13,10 +13,12 @@ use deno_ast::ModuleSpecifier;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_npm::registry::NpmPackageInfo;
|
use deno_npm::registry::NpmPackageInfo;
|
||||||
use deno_runtime::deno_node::NpmResolver;
|
use deno_runtime::deno_node::NodeRequireResolver;
|
||||||
|
use deno_runtime::deno_node::NpmProcessStateProvider;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||||
use deno_semver::package::PackageNv;
|
use deno_semver::package::PackageNv;
|
||||||
use deno_semver::package::PackageReq;
|
use deno_semver::package::PackageReq;
|
||||||
|
use node_resolver::NpmResolver;
|
||||||
|
|
||||||
use crate::args::npm_registry_url;
|
use crate::args::npm_registry_url;
|
||||||
use crate::file_fetcher::FileFetcher;
|
use crate::file_fetcher::FileFetcher;
|
||||||
|
@ -63,6 +65,10 @@ pub enum InnerCliNpmResolverRef<'a> {
|
||||||
|
|
||||||
pub trait CliNpmResolver: NpmResolver {
|
pub trait CliNpmResolver: NpmResolver {
|
||||||
fn into_npm_resolver(self: Arc<Self>) -> Arc<dyn NpmResolver>;
|
fn into_npm_resolver(self: Arc<Self>) -> Arc<dyn NpmResolver>;
|
||||||
|
fn into_require_resolver(self: Arc<Self>) -> Arc<dyn NodeRequireResolver>;
|
||||||
|
fn into_process_state_provider(
|
||||||
|
self: Arc<Self>,
|
||||||
|
) -> Arc<dyn NpmProcessStateProvider>;
|
||||||
|
|
||||||
fn clone_snapshotted(&self) -> Arc<dyn CliNpmResolver>;
|
fn clone_snapshotted(&self) -> Arc<dyn CliNpmResolver>;
|
||||||
|
|
||||||
|
|
|
@ -23,23 +23,23 @@ use deno_npm::resolution::NpmResolutionError;
|
||||||
use deno_package_json::PackageJsonDepValue;
|
use deno_package_json::PackageJsonDepValue;
|
||||||
use deno_runtime::deno_fs;
|
use deno_runtime::deno_fs;
|
||||||
use deno_runtime::deno_fs::FileSystem;
|
use deno_runtime::deno_fs::FileSystem;
|
||||||
use deno_runtime::deno_node::errors::ClosestPkgJsonError;
|
|
||||||
use deno_runtime::deno_node::errors::NodeResolveError;
|
|
||||||
use deno_runtime::deno_node::errors::NodeResolveErrorKind;
|
|
||||||
use deno_runtime::deno_node::errors::PackageFolderResolveErrorKind;
|
|
||||||
use deno_runtime::deno_node::errors::PackageFolderResolveIoError;
|
|
||||||
use deno_runtime::deno_node::errors::PackageNotFoundError;
|
|
||||||
use deno_runtime::deno_node::errors::PackageResolveErrorKind;
|
|
||||||
use deno_runtime::deno_node::errors::UrlToNodeResolutionError;
|
|
||||||
use deno_runtime::deno_node::is_builtin_node_module;
|
use deno_runtime::deno_node::is_builtin_node_module;
|
||||||
use deno_runtime::deno_node::NodeModuleKind;
|
|
||||||
use deno_runtime::deno_node::NodeResolution;
|
|
||||||
use deno_runtime::deno_node::NodeResolutionMode;
|
|
||||||
use deno_runtime::deno_node::NodeResolver;
|
use deno_runtime::deno_node::NodeResolver;
|
||||||
use deno_runtime::deno_node::PackageJson;
|
|
||||||
use deno_runtime::fs_util::specifier_to_file_path;
|
use deno_runtime::fs_util::specifier_to_file_path;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
use deno_semver::package::PackageReq;
|
use deno_semver::package::PackageReq;
|
||||||
|
use node_resolver::errors::ClosestPkgJsonError;
|
||||||
|
use node_resolver::errors::NodeResolveError;
|
||||||
|
use node_resolver::errors::NodeResolveErrorKind;
|
||||||
|
use node_resolver::errors::PackageFolderResolveErrorKind;
|
||||||
|
use node_resolver::errors::PackageFolderResolveIoError;
|
||||||
|
use node_resolver::errors::PackageNotFoundError;
|
||||||
|
use node_resolver::errors::PackageResolveErrorKind;
|
||||||
|
use node_resolver::errors::UrlToNodeResolutionError;
|
||||||
|
use node_resolver::NodeModuleKind;
|
||||||
|
use node_resolver::NodeResolution;
|
||||||
|
use node_resolver::NodeResolutionMode;
|
||||||
|
use node_resolver::PackageJson;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
|
@ -5,6 +5,42 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
|
|
||||||
|
use deno_ast::MediaType;
|
||||||
|
use deno_config::workspace::MappedResolution;
|
||||||
|
use deno_config::workspace::MappedResolutionError;
|
||||||
|
use deno_config::workspace::WorkspaceResolver;
|
||||||
|
use deno_core::anyhow::Context;
|
||||||
|
use deno_core::error::generic_error;
|
||||||
|
use deno_core::error::type_error;
|
||||||
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::futures::FutureExt;
|
||||||
|
use deno_core::v8_set_flags;
|
||||||
|
use deno_core::FeatureChecker;
|
||||||
|
use deno_core::ModuleLoader;
|
||||||
|
use deno_core::ModuleSourceCode;
|
||||||
|
use deno_core::ModuleSpecifier;
|
||||||
|
use deno_core::ModuleType;
|
||||||
|
use deno_core::RequestedModuleType;
|
||||||
|
use deno_core::ResolutionKind;
|
||||||
|
use deno_npm::npm_rc::ResolvedNpmRc;
|
||||||
|
use deno_package_json::PackageJsonDepValue;
|
||||||
|
use deno_runtime::deno_fs;
|
||||||
|
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::WorkerExecutionMode;
|
||||||
|
use deno_runtime::WorkerLogLevel;
|
||||||
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
|
use eszip::EszipRelativeFileBaseUrl;
|
||||||
|
use import_map::parse_from_json;
|
||||||
|
use node_resolver::analyze::NodeCodeTranslator;
|
||||||
|
use node_resolver::NodeResolutionMode;
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::args::create_default_npmrc;
|
use crate::args::create_default_npmrc;
|
||||||
use crate::args::get_root_cert_store;
|
use crate::args::get_root_cert_store;
|
||||||
use crate::args::npm_pkg_req_ref_to_binary_command;
|
use crate::args::npm_pkg_req_ref_to_binary_command;
|
||||||
|
@ -33,41 +69,6 @@ use crate::worker::CliMainWorkerFactory;
|
||||||
use crate::worker::CliMainWorkerOptions;
|
use crate::worker::CliMainWorkerOptions;
|
||||||
use crate::worker::ModuleLoaderAndSourceMapGetter;
|
use crate::worker::ModuleLoaderAndSourceMapGetter;
|
||||||
use crate::worker::ModuleLoaderFactory;
|
use crate::worker::ModuleLoaderFactory;
|
||||||
use deno_ast::MediaType;
|
|
||||||
use deno_config::workspace::MappedResolution;
|
|
||||||
use deno_config::workspace::MappedResolutionError;
|
|
||||||
use deno_config::workspace::WorkspaceResolver;
|
|
||||||
use deno_core::anyhow::Context;
|
|
||||||
use deno_core::error::generic_error;
|
|
||||||
use deno_core::error::type_error;
|
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_core::futures::FutureExt;
|
|
||||||
use deno_core::v8_set_flags;
|
|
||||||
use deno_core::FeatureChecker;
|
|
||||||
use deno_core::ModuleLoader;
|
|
||||||
use deno_core::ModuleSourceCode;
|
|
||||||
use deno_core::ModuleSpecifier;
|
|
||||||
use deno_core::ModuleType;
|
|
||||||
use deno_core::RequestedModuleType;
|
|
||||||
use deno_core::ResolutionKind;
|
|
||||||
use deno_npm::npm_rc::ResolvedNpmRc;
|
|
||||||
use deno_package_json::PackageJsonDepValue;
|
|
||||||
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::WorkerExecutionMode;
|
|
||||||
use deno_runtime::WorkerLogLevel;
|
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
|
||||||
use eszip::EszipRelativeFileBaseUrl;
|
|
||||||
use import_map::parse_from_json;
|
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::rc::Rc;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
pub mod binary;
|
pub mod binary;
|
||||||
mod file_system;
|
mod file_system;
|
||||||
|
@ -549,7 +550,7 @@ pub async fn run(
|
||||||
|
|
||||||
let has_node_modules_dir = npm_resolver.root_node_modules_path().is_some();
|
let has_node_modules_dir = npm_resolver.root_node_modules_path().is_some();
|
||||||
let node_resolver = Arc::new(NodeResolver::new(
|
let node_resolver = Arc::new(NodeResolver::new(
|
||||||
fs.clone(),
|
deno_runtime::deno_node::DenoFsNodeResolverEnv::new(fs.clone()),
|
||||||
npm_resolver.clone().into_npm_resolver(),
|
npm_resolver.clone().into_npm_resolver(),
|
||||||
));
|
));
|
||||||
let cjs_resolutions = Arc::new(CjsResolutionStore::default());
|
let cjs_resolutions = Arc::new(CjsResolutionStore::default());
|
||||||
|
@ -559,7 +560,7 @@ pub async fn run(
|
||||||
CliCjsCodeAnalyzer::new(node_analysis_cache, fs.clone());
|
CliCjsCodeAnalyzer::new(node_analysis_cache, fs.clone());
|
||||||
let node_code_translator = Arc::new(NodeCodeTranslator::new(
|
let node_code_translator = Arc::new(NodeCodeTranslator::new(
|
||||||
cjs_esm_code_analyzer,
|
cjs_esm_code_analyzer,
|
||||||
fs.clone(),
|
deno_runtime::deno_node::DenoFsNodeResolverEnv::new(fs.clone()),
|
||||||
node_resolver.clone(),
|
node_resolver.clone(),
|
||||||
npm_resolver.clone().into_npm_resolver(),
|
npm_resolver.clone().into_npm_resolver(),
|
||||||
));
|
));
|
||||||
|
|
|
@ -308,7 +308,7 @@ pub async fn add(
|
||||||
.context("Failed to update configuration file")?;
|
.context("Failed to update configuration file")?;
|
||||||
|
|
||||||
// clear the previously cached package.json from memory before reloading it
|
// clear the previously cached package.json from memory before reloading it
|
||||||
deno_node::PackageJsonThreadLocalCache::clear();
|
node_resolver::PackageJsonThreadLocalCache::clear();
|
||||||
// make a new CliFactory to pick up the updated config file
|
// make a new CliFactory to pick up the updated config file
|
||||||
let cli_factory = CliFactory::from_flags(flags);
|
let cli_factory = CliFactory::from_flags(flags);
|
||||||
// cache deps
|
// cache deps
|
||||||
|
|
|
@ -30,14 +30,14 @@ use deno_graph::GraphKind;
|
||||||
use deno_graph::Module;
|
use deno_graph::Module;
|
||||||
use deno_graph::ModuleGraph;
|
use deno_graph::ModuleGraph;
|
||||||
use deno_graph::ResolutionResolved;
|
use deno_graph::ResolutionResolved;
|
||||||
use deno_runtime::deno_node::errors::NodeJsErrorCode;
|
|
||||||
use deno_runtime::deno_node::errors::NodeJsErrorCoded;
|
|
||||||
use deno_runtime::deno_node::NodeModuleKind;
|
|
||||||
use deno_runtime::deno_node::NodeResolution;
|
|
||||||
use deno_runtime::deno_node::NodeResolutionMode;
|
|
||||||
use deno_runtime::deno_node::NodeResolver;
|
use deno_runtime::deno_node::NodeResolver;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
use lsp_types::Url;
|
use lsp_types::Url;
|
||||||
|
use node_resolver::errors::NodeJsErrorCode;
|
||||||
|
use node_resolver::errors::NodeJsErrorCoded;
|
||||||
|
use node_resolver::NodeModuleKind;
|
||||||
|
use node_resolver::NodeResolution;
|
||||||
|
use node_resolver::NodeResolutionMode;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
|
@ -22,8 +22,7 @@ use deno_runtime::code_cache;
|
||||||
use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel;
|
use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel;
|
||||||
use deno_runtime::deno_fs;
|
use deno_runtime::deno_fs;
|
||||||
use deno_runtime::deno_node;
|
use deno_runtime::deno_node;
|
||||||
use deno_runtime::deno_node::NodeResolution;
|
use deno_runtime::deno_node::NodeExtInitServices;
|
||||||
use deno_runtime::deno_node::NodeResolutionMode;
|
|
||||||
use deno_runtime::deno_node::NodeResolver;
|
use deno_runtime::deno_node::NodeResolver;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||||
use deno_runtime::deno_tls::RootCertStoreProvider;
|
use deno_runtime::deno_tls::RootCertStoreProvider;
|
||||||
|
@ -40,6 +39,8 @@ use deno_runtime::WorkerExecutionMode;
|
||||||
use deno_runtime::WorkerLogLevel;
|
use deno_runtime::WorkerLogLevel;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
use deno_terminal::colors;
|
use deno_terminal::colors;
|
||||||
|
use node_resolver::NodeResolution;
|
||||||
|
use node_resolver::NodeResolutionMode;
|
||||||
use tokio::select;
|
use tokio::select;
|
||||||
|
|
||||||
use crate::args::CliLockfile;
|
use crate::args::CliLockfile;
|
||||||
|
@ -144,7 +145,17 @@ struct SharedWorkerState {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SharedWorkerState {
|
impl SharedWorkerState {
|
||||||
// Currently empty
|
pub fn create_node_init_services(&self) -> NodeExtInitServices {
|
||||||
|
NodeExtInitServices {
|
||||||
|
node_require_resolver: self.npm_resolver.clone().into_require_resolver(),
|
||||||
|
node_resolver: self.node_resolver.clone(),
|
||||||
|
npm_process_state_provider: self
|
||||||
|
.npm_resolver
|
||||||
|
.clone()
|
||||||
|
.into_process_state_provider(),
|
||||||
|
npm_resolver: self.npm_resolver.clone().into_npm_resolver(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CliMainWorker {
|
pub struct CliMainWorker {
|
||||||
|
@ -599,8 +610,7 @@ impl CliMainWorkerFactory {
|
||||||
strace_ops: shared.options.strace_ops.clone(),
|
strace_ops: shared.options.strace_ops.clone(),
|
||||||
module_loader,
|
module_loader,
|
||||||
fs: shared.fs.clone(),
|
fs: shared.fs.clone(),
|
||||||
node_resolver: Some(shared.node_resolver.clone()),
|
node_services: Some(shared.create_node_init_services()),
|
||||||
npm_resolver: Some(shared.npm_resolver.clone().into_npm_resolver()),
|
|
||||||
get_error_class_fn: Some(&errors::get_error_class_name),
|
get_error_class_fn: Some(&errors::get_error_class_name),
|
||||||
cache_storage_dir,
|
cache_storage_dir,
|
||||||
origin_storage_dir,
|
origin_storage_dir,
|
||||||
|
@ -793,8 +803,7 @@ fn create_web_worker_callback(
|
||||||
format_js_error_fn: Some(Arc::new(format_js_error)),
|
format_js_error_fn: Some(Arc::new(format_js_error)),
|
||||||
module_loader,
|
module_loader,
|
||||||
fs: shared.fs.clone(),
|
fs: shared.fs.clone(),
|
||||||
node_resolver: Some(shared.node_resolver.clone()),
|
node_services: Some(shared.create_node_init_services()),
|
||||||
npm_resolver: Some(shared.npm_resolver.clone().into_npm_resolver()),
|
|
||||||
worker_type: args.worker_type,
|
worker_type: args.worker_type,
|
||||||
maybe_inspector_server,
|
maybe_inspector_server,
|
||||||
get_error_class_fn: Some(&errors::get_error_class_name),
|
get_error_class_fn: Some(&errors::get_error_class_name),
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
disallowed-methods = [
|
disallowed-methods = [
|
||||||
{ path = "std::env::current_dir", reason = "File system operations should be done using FileSystem trait" },
|
{ path = "std::env::current_dir", reason = "File system operations should be done using FileSystem trait" },
|
||||||
{ path = "std::path::Path::canonicalize", reason = "File system operations should be done using NodeFs trait" },
|
{ path = "std::path::Path::canonicalize", reason = "File system operations should be done using FileSystem trait" },
|
||||||
{ path = "std::path::Path::is_dir", reason = "File system operations should be done using NodeFs trait" },
|
{ path = "std::path::Path::is_dir", reason = "File system operations should be done using FileSystem trait" },
|
||||||
{ path = "std::path::Path::is_file", reason = "File system operations should be done using NodeFs trait" },
|
{ path = "std::path::Path::is_file", reason = "File system operations should be done using FileSystem trait" },
|
||||||
{ path = "std::path::Path::is_symlink", reason = "File system operations should be done using NodeFs trait" },
|
{ path = "std::path::Path::is_symlink", reason = "File system operations should be done using FileSystem trait" },
|
||||||
{ path = "std::path::Path::metadata", reason = "File system operations should be done using NodeFs trait" },
|
{ path = "std::path::Path::metadata", reason = "File system operations should be done using FileSystem trait" },
|
||||||
{ path = "std::path::Path::read_dir", reason = "File system operations should be done using NodeFs trait" },
|
{ path = "std::path::Path::read_dir", reason = "File system operations should be done using FileSystem trait" },
|
||||||
{ path = "std::path::Path::read_link", reason = "File system operations should be done using NodeFs trait" },
|
{ path = "std::path::Path::read_link", reason = "File system operations should be done using FileSystem trait" },
|
||||||
{ path = "std::path::Path::symlink_metadata", reason = "File system operations should be done using NodeFs trait" },
|
{ path = "std::path::Path::symlink_metadata", reason = "File system operations should be done using FileSystem trait" },
|
||||||
{ path = "std::path::Path::try_exists", reason = "File system operations should be done using NodeFs trait" },
|
{ path = "std::path::Path::try_exists", reason = "File system operations should be done using FileSystem trait" },
|
||||||
{ path = "std::path::PathBuf::exists", reason = "File system operations should be done using NodeFs trait" },
|
{ path = "std::path::PathBuf::exists", reason = "File system operations should be done using FileSystem trait" },
|
||||||
{ path = "std::path::PathBuf::canonicalize", reason = "File system operations should be done using NodeFs trait" },
|
{ path = "std::path::PathBuf::canonicalize", reason = "File system operations should be done using FileSystem trait" },
|
||||||
{ path = "std::path::PathBuf::is_dir", reason = "File system operations should be done using NodeFs trait" },
|
{ path = "std::path::PathBuf::is_dir", reason = "File system operations should be done using FileSystem trait" },
|
||||||
{ path = "std::path::PathBuf::is_file", reason = "File system operations should be done using NodeFs trait" },
|
{ path = "std::path::PathBuf::is_file", reason = "File system operations should be done using FileSystem trait" },
|
||||||
{ path = "std::path::PathBuf::is_symlink", reason = "File system operations should be done using NodeFs trait" },
|
{ path = "std::path::PathBuf::is_symlink", reason = "File system operations should be done using FileSystem trait" },
|
||||||
{ path = "std::path::PathBuf::metadata", reason = "File system operations should be done using NodeFs trait" },
|
{ path = "std::path::PathBuf::metadata", reason = "File system operations should be done using FileSystem trait" },
|
||||||
{ path = "std::path::PathBuf::read_dir", reason = "File system operations should be done using NodeFs trait" },
|
{ path = "std::path::PathBuf::read_dir", reason = "File system operations should be done using FileSystem trait" },
|
||||||
{ path = "std::path::PathBuf::read_link", reason = "File system operations should be done using NodeFs trait" },
|
{ path = "std::path::PathBuf::read_link", reason = "File system operations should be done using FileSystem trait" },
|
||||||
{ path = "std::path::PathBuf::symlink_metadata", reason = "File system operations should be done using NodeFs trait" },
|
{ path = "std::path::PathBuf::symlink_metadata", reason = "File system operations should be done using FileSystem trait" },
|
||||||
{ path = "std::path::PathBuf::try_exists", reason = "File system operations should be done using NodeFs trait" },
|
{ path = "std::path::PathBuf::try_exists", reason = "File system operations should be done using FileSystem trait" },
|
||||||
{ path = "std::env::set_current_dir", reason = "File system operations should be done using FileSystem trait" },
|
{ path = "std::env::set_current_dir", reason = "File system operations should be done using FileSystem trait" },
|
||||||
{ path = "std::env::temp_dir", reason = "File system operations should be done using FileSystem trait" },
|
{ path = "std::env::temp_dir", reason = "File system operations should be done using FileSystem trait" },
|
||||||
{ path = "std::fs::canonicalize", reason = "File system operations should be done using FileSystem trait" },
|
{ path = "std::fs::canonicalize", reason = "File system operations should be done using FileSystem trait" },
|
||||||
|
|
|
@ -6,80 +6,18 @@ pub use inner::*;
|
||||||
mod inner {
|
mod inner {
|
||||||
#![allow(clippy::disallowed_types)]
|
#![allow(clippy::disallowed_types)]
|
||||||
|
|
||||||
use std::ops::Deref;
|
|
||||||
use std::ops::DerefMut;
|
|
||||||
pub use std::sync::Arc as MaybeArc;
|
pub use std::sync::Arc as MaybeArc;
|
||||||
|
|
||||||
pub use core::marker::Send as MaybeSend;
|
pub use core::marker::Send as MaybeSend;
|
||||||
pub use core::marker::Sync as MaybeSync;
|
pub use core::marker::Sync as MaybeSync;
|
||||||
|
|
||||||
pub struct MaybeArcMutexGuard<'lock, T>(std::sync::MutexGuard<'lock, T>);
|
|
||||||
|
|
||||||
impl<'lock, T> Deref for MaybeArcMutexGuard<'lock, T> {
|
|
||||||
type Target = std::sync::MutexGuard<'lock, T>;
|
|
||||||
fn deref(&self) -> &std::sync::MutexGuard<'lock, T> {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'lock, T> DerefMut for MaybeArcMutexGuard<'lock, T> {
|
|
||||||
fn deref_mut(&mut self) -> &mut std::sync::MutexGuard<'lock, T> {
|
|
||||||
&mut self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct MaybeArcMutex<T>(std::sync::Arc<std::sync::Mutex<T>>);
|
|
||||||
impl<T> MaybeArcMutex<T> {
|
|
||||||
pub fn new(val: T) -> Self {
|
|
||||||
Self(std::sync::Arc::new(std::sync::Mutex::new(val)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'lock, T> MaybeArcMutex<T> {
|
|
||||||
pub fn lock(&'lock self) -> MaybeArcMutexGuard<'lock, T> {
|
|
||||||
MaybeArcMutexGuard(self.0.lock().unwrap())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "sync_fs"))]
|
#[cfg(not(feature = "sync_fs"))]
|
||||||
mod inner {
|
mod inner {
|
||||||
use std::ops::Deref;
|
|
||||||
use std::ops::DerefMut;
|
|
||||||
pub use std::rc::Rc as MaybeArc;
|
pub use std::rc::Rc as MaybeArc;
|
||||||
|
|
||||||
pub trait MaybeSync {}
|
pub trait MaybeSync {}
|
||||||
impl<T> MaybeSync for T where T: ?Sized {}
|
impl<T> MaybeSync for T where T: ?Sized {}
|
||||||
pub trait MaybeSend {}
|
pub trait MaybeSend {}
|
||||||
impl<T> MaybeSend for T where T: ?Sized {}
|
impl<T> MaybeSend for T where T: ?Sized {}
|
||||||
|
|
||||||
pub struct MaybeArcMutexGuard<'lock, T>(std::cell::RefMut<'lock, T>);
|
|
||||||
|
|
||||||
impl<'lock, T> Deref for MaybeArcMutexGuard<'lock, T> {
|
|
||||||
type Target = std::cell::RefMut<'lock, T>;
|
|
||||||
fn deref(&self) -> &std::cell::RefMut<'lock, T> {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'lock, T> DerefMut for MaybeArcMutexGuard<'lock, T> {
|
|
||||||
fn deref_mut(&mut self) -> &mut std::cell::RefMut<'lock, T> {
|
|
||||||
&mut self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct MaybeArcMutex<T>(std::rc::Rc<std::cell::RefCell<T>>);
|
|
||||||
impl<T> MaybeArcMutex<T> {
|
|
||||||
pub fn new(val: T) -> Self {
|
|
||||||
Self(std::rc::Rc::new(std::cell::RefCell::new(val)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'lock, T> MaybeArcMutex<T> {
|
|
||||||
pub fn lock(&'lock self) -> MaybeArcMutexGuard<'lock, T> {
|
|
||||||
MaybeArcMutexGuard(self.0.borrow_mut())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ description = "Node compatibility for Deno"
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
sync_fs = ["deno_package_json/sync"]
|
sync_fs = ["deno_package_json/sync", "node_resolver/sync"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
aead-gcm-stream = "0.1"
|
aead-gcm-stream = "0.1"
|
||||||
|
@ -55,6 +55,7 @@ libc.workspace = true
|
||||||
libz-sys.workspace = true
|
libz-sys.workspace = true
|
||||||
md-5 = { version = "0.10.5", features = ["oid"] }
|
md-5 = { version = "0.10.5", features = ["oid"] }
|
||||||
md4 = "0.10.2"
|
md4 = "0.10.2"
|
||||||
|
node_resolver.workspace = true
|
||||||
num-bigint.workspace = true
|
num-bigint.workspace = true
|
||||||
num-bigint-dig = "0.8.2"
|
num-bigint-dig = "0.8.2"
|
||||||
num-integer = "0.1.45"
|
num-integer = "0.1.45"
|
||||||
|
|
|
@ -6,7 +6,7 @@ use deno_core::v8;
|
||||||
use deno_core::v8::GetPropertyNamesArgs;
|
use deno_core::v8::GetPropertyNamesArgs;
|
||||||
use deno_core::v8::MapFnTo;
|
use deno_core::v8::MapFnTo;
|
||||||
|
|
||||||
use crate::resolution::NodeResolverRc;
|
use crate::NodeResolverRc;
|
||||||
|
|
||||||
// NOTE(bartlomieju): somehow calling `.map_fn_to()` multiple times on a function
|
// 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()`
|
// returns two different pointers. That shouldn't be the case as `.map_fn_to()`
|
||||||
|
|
161
ext/node/lib.rs
161
ext/node/lib.rs
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::located_script_name;
|
use deno_core::located_script_name;
|
||||||
|
@ -15,24 +14,20 @@ use deno_core::url::Url;
|
||||||
use deno_core::v8;
|
use deno_core::v8;
|
||||||
use deno_core::v8::ExternalReference;
|
use deno_core::v8::ExternalReference;
|
||||||
use deno_core::JsRuntime;
|
use deno_core::JsRuntime;
|
||||||
use deno_core::ModuleSpecifier;
|
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
use deno_fs::sync::MaybeSend;
|
use deno_fs::sync::MaybeSend;
|
||||||
use deno_fs::sync::MaybeSync;
|
use deno_fs::sync::MaybeSync;
|
||||||
|
use node_resolver::NpmResolverRc;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
extern crate libz_sys as zlib;
|
extern crate libz_sys as zlib;
|
||||||
|
|
||||||
pub mod analyze;
|
|
||||||
pub mod errors;
|
|
||||||
mod global;
|
mod global;
|
||||||
mod ops;
|
mod ops;
|
||||||
mod package_json;
|
|
||||||
mod path;
|
|
||||||
mod polyfill;
|
mod polyfill;
|
||||||
mod resolution;
|
|
||||||
|
|
||||||
pub use deno_package_json::PackageJson;
|
pub use deno_package_json::PackageJson;
|
||||||
|
pub use node_resolver::PathClean;
|
||||||
pub use ops::ipc::ChildPipeFd;
|
pub use ops::ipc::ChildPipeFd;
|
||||||
pub use ops::ipc::IpcJsonStreamResource;
|
pub use ops::ipc::IpcJsonStreamResource;
|
||||||
use ops::vm;
|
use ops::vm;
|
||||||
|
@ -40,17 +35,9 @@ pub use ops::vm::create_v8_context;
|
||||||
pub use ops::vm::init_global_template;
|
pub use ops::vm::init_global_template;
|
||||||
pub use ops::vm::ContextInitMode;
|
pub use ops::vm::ContextInitMode;
|
||||||
pub use ops::vm::VM_CONTEXT_INDEX;
|
pub use ops::vm::VM_CONTEXT_INDEX;
|
||||||
pub use package_json::load_pkg_json;
|
|
||||||
pub use package_json::PackageJsonThreadLocalCache;
|
|
||||||
pub use path::PathClean;
|
|
||||||
pub use polyfill::is_builtin_node_module;
|
pub use polyfill::is_builtin_node_module;
|
||||||
pub use polyfill::SUPPORTED_BUILTIN_NODE_MODULES;
|
pub use polyfill::SUPPORTED_BUILTIN_NODE_MODULES;
|
||||||
pub use polyfill::SUPPORTED_BUILTIN_NODE_MODULES_WITH_PREFIX;
|
pub use polyfill::SUPPORTED_BUILTIN_NODE_MODULES_WITH_PREFIX;
|
||||||
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_object_middleware;
|
||||||
use crate::global::global_template_middleware;
|
use crate::global::global_template_middleware;
|
||||||
|
@ -149,9 +136,12 @@ impl NodePermissions for deno_permissions::PermissionsContainer {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::disallowed_types)]
|
#[allow(clippy::disallowed_types)]
|
||||||
pub type NpmResolverRc = deno_fs::sync::MaybeArc<dyn NpmResolver>;
|
pub type NpmProcessStateProviderRc =
|
||||||
|
deno_fs::sync::MaybeArc<dyn NpmProcessStateProvider>;
|
||||||
|
|
||||||
pub trait NpmResolver: std::fmt::Debug + MaybeSend + MaybeSync {
|
pub trait NpmProcessStateProvider:
|
||||||
|
std::fmt::Debug + MaybeSend + MaybeSync
|
||||||
|
{
|
||||||
/// Gets a string containing the serialized npm state of the process.
|
/// Gets a string containing the serialized npm state of the process.
|
||||||
///
|
///
|
||||||
/// This will be set on the `DENO_DONT_USE_INTERNAL_NODE_COMPAT_STATE` environment
|
/// This will be set on the `DENO_DONT_USE_INTERNAL_NODE_COMPAT_STATE` environment
|
||||||
|
@ -161,34 +151,13 @@ pub trait NpmResolver: std::fmt::Debug + MaybeSend + MaybeSync {
|
||||||
// This method is only used in the CLI.
|
// This method is only used in the CLI.
|
||||||
String::new()
|
String::new()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Resolves an npm package folder path from an npm package referrer.
|
#[allow(clippy::disallowed_types)]
|
||||||
fn resolve_package_folder_from_package(
|
pub type NodeRequireResolverRc =
|
||||||
&self,
|
deno_fs::sync::MaybeArc<dyn NodeRequireResolver>;
|
||||||
specifier: &str,
|
|
||||||
referrer: &ModuleSpecifier,
|
|
||||||
) -> Result<PathBuf, errors::PackageFolderResolveError>;
|
|
||||||
|
|
||||||
fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool;
|
|
||||||
|
|
||||||
fn in_npm_package_at_dir_path(&self, path: &Path) -> bool {
|
|
||||||
let specifier =
|
|
||||||
match ModuleSpecifier::from_directory_path(path.to_path_buf().clean()) {
|
|
||||||
Ok(p) => p,
|
|
||||||
Err(_) => return false,
|
|
||||||
};
|
|
||||||
self.in_npm_package(&specifier)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn in_npm_package_at_file_path(&self, path: &Path) -> bool {
|
|
||||||
let specifier =
|
|
||||||
match ModuleSpecifier::from_file_path(path.to_path_buf().clean()) {
|
|
||||||
Ok(p) => p,
|
|
||||||
Err(_) => return false,
|
|
||||||
};
|
|
||||||
self.in_npm_package(&specifier)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
pub trait NodeRequireResolver: std::fmt::Debug + MaybeSend + MaybeSync {
|
||||||
fn ensure_read_permission(
|
fn ensure_read_permission(
|
||||||
&self,
|
&self,
|
||||||
permissions: &mut dyn NodePermissions,
|
permissions: &mut dyn NodePermissions,
|
||||||
|
@ -223,10 +192,17 @@ fn op_node_is_promise_rejected(value: v8::Local<v8::Value>) -> bool {
|
||||||
#[op2]
|
#[op2]
|
||||||
#[string]
|
#[string]
|
||||||
fn op_npm_process_state(state: &mut OpState) -> Result<String, AnyError> {
|
fn op_npm_process_state(state: &mut OpState) -> Result<String, AnyError> {
|
||||||
let npm_resolver = state.borrow_mut::<NpmResolverRc>();
|
let npm_resolver = state.borrow_mut::<NpmProcessStateProviderRc>();
|
||||||
Ok(npm_resolver.get_npm_process_state())
|
Ok(npm_resolver.get_npm_process_state())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct NodeExtInitServices {
|
||||||
|
pub node_require_resolver: NodeRequireResolverRc,
|
||||||
|
pub node_resolver: NodeResolverRc,
|
||||||
|
pub npm_process_state_provider: NpmProcessStateProviderRc,
|
||||||
|
pub npm_resolver: NpmResolverRc,
|
||||||
|
}
|
||||||
|
|
||||||
deno_core::extension!(deno_node,
|
deno_core::extension!(deno_node,
|
||||||
deps = [ deno_io, deno_fs ],
|
deps = [ deno_io, deno_fs ],
|
||||||
parameters = [P: NodePermissions],
|
parameters = [P: NodePermissions],
|
||||||
|
@ -643,21 +619,17 @@ deno_core::extension!(deno_node,
|
||||||
"node:zlib" = "zlib.ts",
|
"node:zlib" = "zlib.ts",
|
||||||
],
|
],
|
||||||
options = {
|
options = {
|
||||||
maybe_node_resolver: Option<NodeResolverRc>,
|
maybe_init: Option<NodeExtInitServices>,
|
||||||
maybe_npm_resolver: Option<NpmResolverRc>,
|
|
||||||
fs: deno_fs::FileSystemRc,
|
fs: deno_fs::FileSystemRc,
|
||||||
},
|
},
|
||||||
state = |state, options| {
|
state = |state, options| {
|
||||||
// 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());
|
state.put(options.fs.clone());
|
||||||
|
|
||||||
if let Some(node_resolver) = &options.maybe_node_resolver {
|
if let Some(init) = &options.maybe_init {
|
||||||
state.put(node_resolver.clone());
|
state.put(init.node_require_resolver.clone());
|
||||||
}
|
state.put(init.node_resolver.clone());
|
||||||
if let Some(npm_resolver) = &options.maybe_npm_resolver {
|
state.put(init.npm_resolver.clone());
|
||||||
state.put(npm_resolver.clone());
|
state.put(init.npm_process_state_provider.clone());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
global_template_middleware = global_template_middleware,
|
global_template_middleware = global_template_middleware,
|
||||||
|
@ -783,3 +755,84 @@ pub fn load_cjs_module(
|
||||||
js_runtime.execute_script(located_script_name!(), source_code)?;
|
js_runtime.execute_script(located_script_name!(), source_code)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type NodeResolver = node_resolver::NodeResolver<DenoFsNodeResolverEnv>;
|
||||||
|
#[allow(clippy::disallowed_types)]
|
||||||
|
pub type NodeResolverRc =
|
||||||
|
deno_fs::sync::MaybeArc<node_resolver::NodeResolver<DenoFsNodeResolverEnv>>;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DenoFsNodeResolverEnv {
|
||||||
|
fs: deno_fs::FileSystemRc,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DenoFsNodeResolverEnv {
|
||||||
|
pub fn new(fs: deno_fs::FileSystemRc) -> Self {
|
||||||
|
Self { fs }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl node_resolver::env::NodeResolverEnv for DenoFsNodeResolverEnv {
|
||||||
|
fn is_builtin_node_module(&self, specifier: &str) -> bool {
|
||||||
|
is_builtin_node_module(specifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn realpath_sync(
|
||||||
|
&self,
|
||||||
|
path: &std::path::Path,
|
||||||
|
) -> std::io::Result<std::path::PathBuf> {
|
||||||
|
self
|
||||||
|
.fs
|
||||||
|
.realpath_sync(path)
|
||||||
|
.map_err(|err| err.into_io_error())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stat_sync(
|
||||||
|
&self,
|
||||||
|
path: &std::path::Path,
|
||||||
|
) -> std::io::Result<node_resolver::env::NodeResolverFsStat> {
|
||||||
|
self
|
||||||
|
.fs
|
||||||
|
.stat_sync(path)
|
||||||
|
.map(|stat| node_resolver::env::NodeResolverFsStat {
|
||||||
|
is_file: stat.is_file,
|
||||||
|
is_dir: stat.is_directory,
|
||||||
|
is_symlink: stat.is_symlink,
|
||||||
|
})
|
||||||
|
.map_err(|err| err.into_io_error())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exists_sync(&self, path: &std::path::Path) -> bool {
|
||||||
|
self.fs.exists_sync(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pkg_json_fs(&self) -> &dyn deno_package_json::fs::DenoPkgJsonFs {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl deno_package_json::fs::DenoPkgJsonFs for DenoFsNodeResolverEnv {
|
||||||
|
fn read_to_string_lossy(
|
||||||
|
&self,
|
||||||
|
path: &std::path::Path,
|
||||||
|
) -> Result<String, std::io::Error> {
|
||||||
|
self
|
||||||
|
.fs
|
||||||
|
.read_text_file_lossy_sync(path, None)
|
||||||
|
.map_err(|err| err.into_io_error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DenoPkgJsonFsAdapter<'a>(pub &'a dyn deno_fs::FileSystem);
|
||||||
|
|
||||||
|
impl<'a> deno_package_json::fs::DenoPkgJsonFs for DenoPkgJsonFsAdapter<'a> {
|
||||||
|
fn read_to_string_lossy(
|
||||||
|
&self,
|
||||||
|
path: &Path,
|
||||||
|
) -> Result<String, std::io::Error> {
|
||||||
|
self
|
||||||
|
.0
|
||||||
|
.read_text_file_lossy_sync(path, None)
|
||||||
|
.map_err(|err| err.into_io_error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -10,16 +10,17 @@ use deno_core::JsRuntimeInspector;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
use deno_fs::FileSystemRc;
|
use deno_fs::FileSystemRc;
|
||||||
|
use node_resolver::NodeModuleKind;
|
||||||
|
use node_resolver::NodeResolutionMode;
|
||||||
|
use node_resolver::REQUIRE_CONDITIONS;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::resolution;
|
|
||||||
use crate::resolution::NodeResolverRc;
|
|
||||||
use crate::NodeModuleKind;
|
|
||||||
use crate::NodePermissions;
|
use crate::NodePermissions;
|
||||||
use crate::NodeResolutionMode;
|
use crate::NodeRequireResolverRc;
|
||||||
|
use crate::NodeResolverRc;
|
||||||
use crate::NpmResolverRc;
|
use crate::NpmResolverRc;
|
||||||
use crate::PackageJson;
|
use crate::PackageJson;
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@ fn ensure_read_permission<P>(
|
||||||
where
|
where
|
||||||
P: NodePermissions + 'static,
|
P: NodePermissions + 'static,
|
||||||
{
|
{
|
||||||
let resolver = state.borrow::<NpmResolverRc>().clone();
|
let resolver = state.borrow::<NodeRequireResolverRc>().clone();
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
resolver.ensure_read_permission(permissions, file_path)
|
resolver.ensure_read_permission(permissions, file_path)
|
||||||
}
|
}
|
||||||
|
@ -423,7 +424,7 @@ where
|
||||||
exports,
|
exports,
|
||||||
Some(&referrer),
|
Some(&referrer),
|
||||||
NodeModuleKind::Cjs,
|
NodeModuleKind::Cjs,
|
||||||
resolution::REQUIRE_CONDITIONS,
|
REQUIRE_CONDITIONS,
|
||||||
NodeResolutionMode::Execution,
|
NodeResolutionMode::Execution,
|
||||||
)?;
|
)?;
|
||||||
Ok(Some(if r.scheme() == "file" {
|
Ok(Some(if r.scheme() == "file" {
|
||||||
|
@ -511,7 +512,7 @@ where
|
||||||
exports,
|
exports,
|
||||||
Some(&referrer),
|
Some(&referrer),
|
||||||
NodeModuleKind::Cjs,
|
NodeModuleKind::Cjs,
|
||||||
resolution::REQUIRE_CONDITIONS,
|
REQUIRE_CONDITIONS,
|
||||||
NodeResolutionMode::Execution,
|
NodeResolutionMode::Execution,
|
||||||
)?;
|
)?;
|
||||||
Ok(Some(if r.scheme() == "file" {
|
Ok(Some(if r.scheme() == "file" {
|
||||||
|
@ -590,7 +591,7 @@ where
|
||||||
Some(&referrer_url),
|
Some(&referrer_url),
|
||||||
NodeModuleKind::Cjs,
|
NodeModuleKind::Cjs,
|
||||||
Some(&pkg),
|
Some(&pkg),
|
||||||
resolution::REQUIRE_CONDITIONS,
|
REQUIRE_CONDITIONS,
|
||||||
NodeResolutionMode::Execution,
|
NodeResolutionMode::Execution,
|
||||||
)?;
|
)?;
|
||||||
Ok(Some(url_to_file_path_string(&url)?))
|
Ok(Some(url_to_file_path_string(&url)?))
|
||||||
|
|
|
@ -6,13 +6,13 @@ use deno_core::op2;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
use deno_fs::FileSystemRc;
|
use deno_fs::FileSystemRc;
|
||||||
|
use node_resolver::NodeResolution;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::resolution;
|
|
||||||
use crate::resolution::NodeResolverRc;
|
|
||||||
use crate::NodePermissions;
|
use crate::NodePermissions;
|
||||||
use crate::NpmResolverRc;
|
use crate::NodeRequireResolverRc;
|
||||||
|
use crate::NodeResolverRc;
|
||||||
|
|
||||||
fn ensure_read_permission<P>(
|
fn ensure_read_permission<P>(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
|
@ -21,7 +21,7 @@ fn ensure_read_permission<P>(
|
||||||
where
|
where
|
||||||
P: NodePermissions + 'static,
|
P: NodePermissions + 'static,
|
||||||
{
|
{
|
||||||
let resolver = state.borrow::<NpmResolverRc>().clone();
|
let resolver = state.borrow::<NodeRequireResolverRc>().clone();
|
||||||
let permissions = state.borrow_mut::<P>();
|
let permissions = state.borrow_mut::<P>();
|
||||||
resolver.ensure_read_permission(permissions, file_path)
|
resolver.ensure_read_permission(permissions, file_path)
|
||||||
}
|
}
|
||||||
|
@ -64,9 +64,9 @@ where
|
||||||
}
|
}
|
||||||
let node_resolver = state.borrow::<NodeResolverRc>();
|
let node_resolver = state.borrow::<NodeResolverRc>();
|
||||||
match node_resolver.url_to_node_resolution(url)? {
|
match node_resolver.url_to_node_resolution(url)? {
|
||||||
resolution::NodeResolution::Esm(u) => Ok(u.to_string()),
|
NodeResolution::Esm(u) => Ok(u.to_string()),
|
||||||
resolution::NodeResolution::CommonJs(u) => wrap_cjs(u),
|
NodeResolution::CommonJs(u) => wrap_cjs(u),
|
||||||
_ => Err(generic_error("Neither ESM nor CJS")),
|
NodeResolution::BuiltIn(_) => Err(generic_error("Neither ESM nor CJS")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
|
||||||
|
|
||||||
use std::path::Component;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use deno_core::ModuleSpecifier;
|
|
||||||
|
|
||||||
/// Extension to path_clean::PathClean
|
|
||||||
pub trait PathClean<T> {
|
|
||||||
fn clean(&self) -> T;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PathClean<PathBuf> for PathBuf {
|
|
||||||
fn clean(&self) -> PathBuf {
|
|
||||||
let path = path_clean::PathClean::clean(self);
|
|
||||||
if cfg!(windows) && path.to_string_lossy().contains("..\\") {
|
|
||||||
// temporary workaround because path_clean::PathClean::clean is
|
|
||||||
// not good enough on windows
|
|
||||||
let mut components = Vec::new();
|
|
||||||
|
|
||||||
for component in path.components() {
|
|
||||||
match component {
|
|
||||||
Component::CurDir => {
|
|
||||||
// skip
|
|
||||||
}
|
|
||||||
Component::ParentDir => {
|
|
||||||
let maybe_last_component = components.pop();
|
|
||||||
if !matches!(maybe_last_component, Some(Component::Normal(_))) {
|
|
||||||
panic!("Error normalizing: {}", path.display());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Component::Normal(_) | Component::RootDir | Component::Prefix(_) => {
|
|
||||||
components.push(component);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
components.into_iter().collect::<PathBuf>()
|
|
||||||
} else {
|
|
||||||
path
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn to_file_specifier(path: &Path) -> ModuleSpecifier {
|
|
||||||
match ModuleSpecifier::from_file_path(path) {
|
|
||||||
Ok(url) => url,
|
|
||||||
Err(_) => panic!("Invalid path: {}", path.display()),
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,5 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use deno_core::ModuleSpecifier;
|
|
||||||
|
|
||||||
/// e.g. `is_builtin_node_module("assert")`
|
/// e.g. `is_builtin_node_module("assert")`
|
||||||
pub fn is_builtin_node_module(module_name: &str) -> bool {
|
pub fn is_builtin_node_module(module_name: &str) -> bool {
|
||||||
SUPPORTED_BUILTIN_NODE_MODULES
|
SUPPORTED_BUILTIN_NODE_MODULES
|
||||||
|
@ -9,18 +7,6 @@ pub fn is_builtin_node_module(module_name: &str) -> bool {
|
||||||
.any(|m| *m == module_name)
|
.any(|m| *m == module_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ex. returns `fs` for `node:fs`
|
|
||||||
pub fn get_module_name_from_builtin_node_module_specifier(
|
|
||||||
specifier: &ModuleSpecifier,
|
|
||||||
) -> Option<&str> {
|
|
||||||
if specifier.scheme() != "node" {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let (_, specifier) = specifier.as_str().split_once(':')?;
|
|
||||||
Some(specifier)
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! generate_builtin_node_module_lists {
|
macro_rules! generate_builtin_node_module_lists {
|
||||||
($( $module_name:literal ,)+) => {
|
($( $module_name:literal ,)+) => {
|
||||||
pub static SUPPORTED_BUILTIN_NODE_MODULES: &[&str] = &[
|
pub static SUPPORTED_BUILTIN_NODE_MODULES: &[&str] = &[
|
||||||
|
|
32
ext/node_resolver/Cargo.toml
Normal file
32
ext/node_resolver/Cargo.toml
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
# Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
[package]
|
||||||
|
name = "node_resolver"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
readme = "README.md"
|
||||||
|
repository.workspace = true
|
||||||
|
description = "Node.js module resolution algorithm used in Deno"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
path = "lib.rs"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
sync = ["deno_package_json/sync"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow.workspace = true
|
||||||
|
async-trait.workspace = true
|
||||||
|
deno_media_type.workspace = true
|
||||||
|
deno_package_json.workspace = true
|
||||||
|
futures.workspace = true
|
||||||
|
lazy-regex.workspace = true
|
||||||
|
once_cell.workspace = true
|
||||||
|
path-clean = "=0.1.0"
|
||||||
|
regex.workspace = true
|
||||||
|
serde_json.workspace = true
|
||||||
|
thiserror.workspace = true
|
||||||
|
tokio.workspace = true
|
||||||
|
url.workspace = true
|
6
ext/node_resolver/README.md
Normal file
6
ext/node_resolver/README.md
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# Node Resolver
|
||||||
|
|
||||||
|
[![crates](https://img.shields.io/crates/v/node_resolver.svg)](https://crates.io/crates/node_resolver)
|
||||||
|
[![docs](https://docs.rs/node_resolver/badge.svg)](https://docs.rs/node_resolver)
|
||||||
|
|
||||||
|
Provides Node.js compatible resolution for the Deno project.
|
|
@ -5,17 +5,17 @@ use std::collections::HashSet;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use deno_core::anyhow;
|
use futures::future::LocalBoxFuture;
|
||||||
use deno_core::anyhow::Context;
|
use futures::stream::FuturesUnordered;
|
||||||
use deno_core::futures::future::LocalBoxFuture;
|
use futures::FutureExt;
|
||||||
use deno_core::futures::stream::FuturesUnordered;
|
use futures::StreamExt;
|
||||||
use deno_core::futures::FutureExt;
|
|
||||||
use deno_core::futures::StreamExt;
|
|
||||||
use deno_core::ModuleSpecifier;
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
use deno_core::error::AnyError;
|
use anyhow::Context;
|
||||||
|
use anyhow::Error as AnyError;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
use crate::env::NodeResolverEnv;
|
||||||
use crate::package_json::load_pkg_json;
|
use crate::package_json::load_pkg_json;
|
||||||
use crate::path::to_file_specifier;
|
use crate::path::to_file_specifier;
|
||||||
use crate::resolution::NodeResolverRc;
|
use crate::resolution::NodeResolverRc;
|
||||||
|
@ -50,28 +50,33 @@ pub trait CjsCodeAnalyzer {
|
||||||
/// necessary.
|
/// necessary.
|
||||||
async fn analyze_cjs(
|
async fn analyze_cjs(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &Url,
|
||||||
maybe_source: Option<String>,
|
maybe_source: Option<String>,
|
||||||
) -> Result<CjsAnalysis, AnyError>;
|
) -> Result<CjsAnalysis, AnyError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct NodeCodeTranslator<TCjsCodeAnalyzer: CjsCodeAnalyzer> {
|
pub struct NodeCodeTranslator<
|
||||||
|
TCjsCodeAnalyzer: CjsCodeAnalyzer,
|
||||||
|
TNodeResolverEnv: NodeResolverEnv,
|
||||||
|
> {
|
||||||
cjs_code_analyzer: TCjsCodeAnalyzer,
|
cjs_code_analyzer: TCjsCodeAnalyzer,
|
||||||
fs: deno_fs::FileSystemRc,
|
env: TNodeResolverEnv,
|
||||||
node_resolver: NodeResolverRc,
|
node_resolver: NodeResolverRc<TNodeResolverEnv>,
|
||||||
npm_resolver: NpmResolverRc,
|
npm_resolver: NpmResolverRc,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<TCjsCodeAnalyzer: CjsCodeAnalyzer> NodeCodeTranslator<TCjsCodeAnalyzer> {
|
impl<TCjsCodeAnalyzer: CjsCodeAnalyzer, TNodeResolverEnv: NodeResolverEnv>
|
||||||
|
NodeCodeTranslator<TCjsCodeAnalyzer, TNodeResolverEnv>
|
||||||
|
{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
cjs_code_analyzer: TCjsCodeAnalyzer,
|
cjs_code_analyzer: TCjsCodeAnalyzer,
|
||||||
fs: deno_fs::FileSystemRc,
|
env: TNodeResolverEnv,
|
||||||
node_resolver: NodeResolverRc,
|
node_resolver: NodeResolverRc<TNodeResolverEnv>,
|
||||||
npm_resolver: NpmResolverRc,
|
npm_resolver: NpmResolverRc,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cjs_code_analyzer,
|
cjs_code_analyzer,
|
||||||
fs,
|
env,
|
||||||
node_resolver,
|
node_resolver,
|
||||||
npm_resolver,
|
npm_resolver,
|
||||||
}
|
}
|
||||||
|
@ -85,7 +90,7 @@ impl<TCjsCodeAnalyzer: CjsCodeAnalyzer> NodeCodeTranslator<TCjsCodeAnalyzer> {
|
||||||
/// If successful a source code for equivalent ES module is returned.
|
/// If successful a source code for equivalent ES module is returned.
|
||||||
pub async fn translate_cjs_to_esm(
|
pub async fn translate_cjs_to_esm(
|
||||||
&self,
|
&self,
|
||||||
entry_specifier: &ModuleSpecifier,
|
entry_specifier: &Url,
|
||||||
source: Option<String>,
|
source: Option<String>,
|
||||||
) -> Result<String, AnyError> {
|
) -> Result<String, AnyError> {
|
||||||
let mut temp_var_count = 0;
|
let mut temp_var_count = 0;
|
||||||
|
@ -173,7 +178,7 @@ impl<TCjsCodeAnalyzer: CjsCodeAnalyzer> NodeCodeTranslator<TCjsCodeAnalyzer> {
|
||||||
|
|
||||||
type AnalysisFuture<'a> = LocalBoxFuture<'a, Result<Analysis, AnyError>>;
|
type AnalysisFuture<'a> = LocalBoxFuture<'a, Result<Analysis, AnyError>>;
|
||||||
|
|
||||||
let mut handled_reexports: HashSet<ModuleSpecifier> = HashSet::default();
|
let mut handled_reexports: HashSet<Url> = HashSet::default();
|
||||||
handled_reexports.insert(entry_specifier.clone());
|
handled_reexports.insert(entry_specifier.clone());
|
||||||
let mut analyze_futures: FuturesUnordered<AnalysisFuture<'a>> =
|
let mut analyze_futures: FuturesUnordered<AnalysisFuture<'a>> =
|
||||||
FuturesUnordered::new();
|
FuturesUnordered::new();
|
||||||
|
@ -282,10 +287,10 @@ impl<TCjsCodeAnalyzer: CjsCodeAnalyzer> NodeCodeTranslator<TCjsCodeAnalyzer> {
|
||||||
fn resolve(
|
fn resolve(
|
||||||
&self,
|
&self,
|
||||||
specifier: &str,
|
specifier: &str,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &Url,
|
||||||
conditions: &[&str],
|
conditions: &[&str],
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
) -> Result<ModuleSpecifier, AnyError> {
|
) -> Result<Url, AnyError> {
|
||||||
if specifier.starts_with('/') {
|
if specifier.starts_with('/') {
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
|
@ -305,14 +310,14 @@ impl<TCjsCodeAnalyzer: CjsCodeAnalyzer> NodeCodeTranslator<TCjsCodeAnalyzer> {
|
||||||
let (package_specifier, package_subpath) =
|
let (package_specifier, package_subpath) =
|
||||||
parse_specifier(specifier).unwrap();
|
parse_specifier(specifier).unwrap();
|
||||||
|
|
||||||
// todo(dsherret): use not_found error on not found here
|
|
||||||
let module_dir = self.npm_resolver.resolve_package_folder_from_package(
|
let module_dir = self.npm_resolver.resolve_package_folder_from_package(
|
||||||
package_specifier.as_str(),
|
package_specifier.as_str(),
|
||||||
referrer,
|
referrer,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let package_json_path = module_dir.join("package.json");
|
let package_json_path = module_dir.join("package.json");
|
||||||
let maybe_package_json = load_pkg_json(&*self.fs, &package_json_path)?;
|
let maybe_package_json =
|
||||||
|
load_pkg_json(self.env.pkg_json_fs(), &package_json_path)?;
|
||||||
if let Some(package_json) = maybe_package_json {
|
if let Some(package_json) = maybe_package_json {
|
||||||
if let Some(exports) = &package_json.exports {
|
if let Some(exports) = &package_json.exports {
|
||||||
return self
|
return self
|
||||||
|
@ -332,11 +337,11 @@ impl<TCjsCodeAnalyzer: CjsCodeAnalyzer> NodeCodeTranslator<TCjsCodeAnalyzer> {
|
||||||
// old school
|
// old school
|
||||||
if package_subpath != "." {
|
if package_subpath != "." {
|
||||||
let d = module_dir.join(package_subpath);
|
let d = module_dir.join(package_subpath);
|
||||||
if self.fs.is_dir_sync(&d) {
|
if self.env.is_dir_sync(&d) {
|
||||||
// subdir might have a package.json that specifies the entrypoint
|
// subdir might have a package.json that specifies the entrypoint
|
||||||
let package_json_path = d.join("package.json");
|
let package_json_path = d.join("package.json");
|
||||||
let maybe_package_json =
|
let maybe_package_json =
|
||||||
load_pkg_json(&*self.fs, &package_json_path)?;
|
load_pkg_json(self.env.pkg_json_fs(), &package_json_path)?;
|
||||||
if let Some(package_json) = maybe_package_json {
|
if let Some(package_json) = maybe_package_json {
|
||||||
if let Some(main) = package_json.main(NodeModuleKind::Cjs) {
|
if let Some(main) = package_json.main(NodeModuleKind::Cjs) {
|
||||||
return Ok(to_file_specifier(&d.join(main).clean()));
|
return Ok(to_file_specifier(&d.join(main).clean()));
|
||||||
|
@ -381,13 +386,13 @@ impl<TCjsCodeAnalyzer: CjsCodeAnalyzer> NodeCodeTranslator<TCjsCodeAnalyzer> {
|
||||||
referrer: &Path,
|
referrer: &Path,
|
||||||
) -> Result<PathBuf, AnyError> {
|
) -> Result<PathBuf, AnyError> {
|
||||||
let p = p.clean();
|
let p = p.clean();
|
||||||
if self.fs.exists_sync(&p) {
|
if self.env.exists_sync(&p) {
|
||||||
let file_name = p.file_name().unwrap();
|
let file_name = p.file_name().unwrap();
|
||||||
let p_js =
|
let p_js =
|
||||||
p.with_file_name(format!("{}.js", file_name.to_str().unwrap()));
|
p.with_file_name(format!("{}.js", file_name.to_str().unwrap()));
|
||||||
if self.fs.is_file_sync(&p_js) {
|
if self.env.is_file_sync(&p_js) {
|
||||||
return Ok(p_js);
|
return Ok(p_js);
|
||||||
} else if self.fs.is_dir_sync(&p) {
|
} else if self.env.is_dir_sync(&p) {
|
||||||
return Ok(p.join("index.js"));
|
return Ok(p.join("index.js"));
|
||||||
} else {
|
} else {
|
||||||
return Ok(p);
|
return Ok(p);
|
||||||
|
@ -396,14 +401,14 @@ impl<TCjsCodeAnalyzer: CjsCodeAnalyzer> NodeCodeTranslator<TCjsCodeAnalyzer> {
|
||||||
{
|
{
|
||||||
let p_js =
|
let p_js =
|
||||||
p.with_file_name(format!("{}.js", file_name.to_str().unwrap()));
|
p.with_file_name(format!("{}.js", file_name.to_str().unwrap()));
|
||||||
if self.fs.is_file_sync(&p_js) {
|
if self.env.is_file_sync(&p_js) {
|
||||||
return Ok(p_js);
|
return Ok(p_js);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let p_json =
|
let p_json =
|
||||||
p.with_file_name(format!("{}.json", file_name.to_str().unwrap()));
|
p.with_file_name(format!("{}.json", file_name.to_str().unwrap()));
|
||||||
if self.fs.is_file_sync(&p_json) {
|
if self.env.is_file_sync(&p_json) {
|
||||||
return Ok(p_json);
|
return Ok(p_json);
|
||||||
}
|
}
|
||||||
}
|
}
|
48
ext/node_resolver/clippy.toml
Normal file
48
ext/node_resolver/clippy.toml
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
disallowed-methods = [
|
||||||
|
{ path = "std::env::current_dir", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::path::Path::canonicalize", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::path::Path::is_dir", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::path::Path::is_file", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::path::Path::is_symlink", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::path::Path::metadata", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::path::Path::read_dir", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::path::Path::read_link", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::path::Path::symlink_metadata", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::path::Path::try_exists", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::path::PathBuf::exists", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::path::PathBuf::canonicalize", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::path::PathBuf::is_dir", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::path::PathBuf::is_file", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::path::PathBuf::is_symlink", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::path::PathBuf::metadata", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::path::PathBuf::read_dir", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::path::PathBuf::read_link", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::path::PathBuf::symlink_metadata", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::path::PathBuf::try_exists", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::env::set_current_dir", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::env::temp_dir", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::fs::canonicalize", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::fs::copy", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::fs::create_dir_all", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::fs::create_dir", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::fs::DirBuilder::new", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::fs::hard_link", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::fs::metadata", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::fs::OpenOptions::new", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::fs::read_dir", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::fs::read_link", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::fs::read_to_string", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::fs::read", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::fs::remove_dir_all", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::fs::remove_dir", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::fs::remove_file", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::fs::rename", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::fs::set_permissions", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::fs::symlink_metadata", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::fs::write", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::path::Path::canonicalize", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
{ path = "std::path::Path::exists", reason = "File system operations should be done using NodeResolverFs trait" },
|
||||||
|
]
|
||||||
|
disallowed-types = [
|
||||||
|
{ path = "std::sync::Arc", reason = "use crate::sync::MaybeArc instead" },
|
||||||
|
]
|
39
ext/node_resolver/env.rs
Normal file
39
ext/node_resolver/env.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use crate::sync::MaybeSend;
|
||||||
|
use crate::sync::MaybeSync;
|
||||||
|
|
||||||
|
pub struct NodeResolverFsStat {
|
||||||
|
pub is_file: bool,
|
||||||
|
pub is_dir: bool,
|
||||||
|
pub is_symlink: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait NodeResolverEnv: std::fmt::Debug + MaybeSend + MaybeSync {
|
||||||
|
fn is_builtin_node_module(&self, specifier: &str) -> bool;
|
||||||
|
|
||||||
|
fn realpath_sync(&self, path: &Path) -> std::io::Result<PathBuf>;
|
||||||
|
|
||||||
|
fn stat_sync(&self, path: &Path) -> std::io::Result<NodeResolverFsStat>;
|
||||||
|
|
||||||
|
fn exists_sync(&self, path: &Path) -> bool;
|
||||||
|
|
||||||
|
fn is_file_sync(&self, path: &Path) -> bool {
|
||||||
|
self
|
||||||
|
.stat_sync(path)
|
||||||
|
.map(|stat| stat.is_file)
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_dir_sync(&self, path: &Path) -> bool {
|
||||||
|
self
|
||||||
|
.stat_sync(path)
|
||||||
|
.map(|stat| stat.is_dir)
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pkg_json_fs(&self) -> &dyn deno_package_json::fs::DenoPkgJsonFs;
|
||||||
|
}
|
|
@ -4,8 +4,8 @@ use std::borrow::Cow;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use deno_core::ModuleSpecifier;
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
use crate::NodeModuleKind;
|
use crate::NodeModuleKind;
|
||||||
use crate::NodeResolutionMode;
|
use crate::NodeResolutionMode;
|
||||||
|
@ -155,7 +155,7 @@ kinded_err!(PackageFolderResolveError, PackageFolderResolveErrorKind);
|
||||||
)]
|
)]
|
||||||
pub struct PackageNotFoundError {
|
pub struct PackageNotFoundError {
|
||||||
pub package_name: String,
|
pub package_name: String,
|
||||||
pub referrer: ModuleSpecifier,
|
pub referrer: Url,
|
||||||
/// Extra information about the referrer.
|
/// Extra information about the referrer.
|
||||||
pub referrer_extra: Option<String>,
|
pub referrer_extra: Option<String>,
|
||||||
}
|
}
|
||||||
|
@ -173,7 +173,7 @@ impl NodeJsErrorCoded for PackageNotFoundError {
|
||||||
referrer_extra.as_ref().map(|r| format!(" ({})", r)).unwrap_or_default()
|
referrer_extra.as_ref().map(|r| format!(" ({})", r)).unwrap_or_default()
|
||||||
)]
|
)]
|
||||||
pub struct ReferrerNotFoundError {
|
pub struct ReferrerNotFoundError {
|
||||||
pub referrer: ModuleSpecifier,
|
pub referrer: Url,
|
||||||
/// Extra information about the referrer.
|
/// Extra information about the referrer.
|
||||||
pub referrer_extra: Option<String>,
|
pub referrer_extra: Option<String>,
|
||||||
}
|
}
|
||||||
|
@ -188,7 +188,7 @@ impl NodeJsErrorCoded for ReferrerNotFoundError {
|
||||||
#[error("Failed resolving '{package_name}' from referrer '{referrer}'.")]
|
#[error("Failed resolving '{package_name}' from referrer '{referrer}'.")]
|
||||||
pub struct PackageFolderResolveIoError {
|
pub struct PackageFolderResolveIoError {
|
||||||
pub package_name: String,
|
pub package_name: String,
|
||||||
pub referrer: ModuleSpecifier,
|
pub referrer: Url,
|
||||||
#[source]
|
#[source]
|
||||||
pub source: std::io::Error,
|
pub source: std::io::Error,
|
||||||
}
|
}
|
||||||
|
@ -264,7 +264,7 @@ pub enum PackageSubpathResolveErrorKind {
|
||||||
pub struct PackageTargetNotFoundError {
|
pub struct PackageTargetNotFoundError {
|
||||||
pub pkg_json_path: PathBuf,
|
pub pkg_json_path: PathBuf,
|
||||||
pub target: String,
|
pub target: String,
|
||||||
pub maybe_referrer: Option<ModuleSpecifier>,
|
pub maybe_referrer: Option<Url>,
|
||||||
pub referrer_kind: NodeModuleKind,
|
pub referrer_kind: NodeModuleKind,
|
||||||
pub mode: NodeResolutionMode,
|
pub mode: NodeResolutionMode,
|
||||||
}
|
}
|
||||||
|
@ -333,8 +333,8 @@ pub struct TypesNotFoundError(pub Box<TypesNotFoundErrorData>);
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TypesNotFoundErrorData {
|
pub struct TypesNotFoundErrorData {
|
||||||
pub code_specifier: ModuleSpecifier,
|
pub code_specifier: Url,
|
||||||
pub maybe_referrer: Option<ModuleSpecifier>,
|
pub maybe_referrer: Option<Url>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeJsErrorCoded for TypesNotFoundError {
|
impl NodeJsErrorCoded for TypesNotFoundError {
|
||||||
|
@ -397,7 +397,7 @@ impl NodeJsErrorCoded for CanonicalizingPkgJsonDirError {
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
#[error("TypeScript files are not supported in npm packages: {specifier}")]
|
#[error("TypeScript files are not supported in npm packages: {specifier}")]
|
||||||
pub struct TypeScriptNotSupportedInNpmError {
|
pub struct TypeScriptNotSupportedInNpmError {
|
||||||
pub specifier: ModuleSpecifier,
|
pub specifier: Url,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeJsErrorCoded for TypeScriptNotSupportedInNpmError {
|
impl NodeJsErrorCoded for TypeScriptNotSupportedInNpmError {
|
||||||
|
@ -437,7 +437,7 @@ pub enum UrlToNodeResolutionErrorKind {
|
||||||
pub struct PackageImportNotDefinedError {
|
pub struct PackageImportNotDefinedError {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub package_json_path: Option<PathBuf>,
|
pub package_json_path: Option<PathBuf>,
|
||||||
pub maybe_referrer: Option<ModuleSpecifier>,
|
pub maybe_referrer: Option<Url>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeJsErrorCoded for PackageImportNotDefinedError {
|
impl NodeJsErrorCoded for PackageImportNotDefinedError {
|
||||||
|
@ -503,7 +503,7 @@ pub enum PackageResolveErrorKind {
|
||||||
#[error("Failed joining '{path}' from '{base}'.")]
|
#[error("Failed joining '{path}' from '{base}'.")]
|
||||||
pub struct NodeResolveRelativeJoinError {
|
pub struct NodeResolveRelativeJoinError {
|
||||||
pub path: String,
|
pub path: String,
|
||||||
pub base: ModuleSpecifier,
|
pub base: Url,
|
||||||
#[source]
|
#[source]
|
||||||
pub source: url::ParseError,
|
pub source: url::ParseError,
|
||||||
}
|
}
|
||||||
|
@ -568,8 +568,8 @@ impl NodeJsErrorCoded for FinalizeResolutionError {
|
||||||
maybe_referrer.as_ref().map(|referrer| format!(" imported from '{}'", referrer)).unwrap_or_default()
|
maybe_referrer.as_ref().map(|referrer| format!(" imported from '{}'", referrer)).unwrap_or_default()
|
||||||
)]
|
)]
|
||||||
pub struct ModuleNotFoundError {
|
pub struct ModuleNotFoundError {
|
||||||
pub specifier: ModuleSpecifier,
|
pub specifier: Url,
|
||||||
pub maybe_referrer: Option<ModuleSpecifier>,
|
pub maybe_referrer: Option<Url>,
|
||||||
pub typ: &'static str,
|
pub typ: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -587,8 +587,8 @@ impl NodeJsErrorCoded for ModuleNotFoundError {
|
||||||
maybe_referrer.as_ref().map(|referrer| format!(" imported from '{}'", referrer)).unwrap_or_default(),
|
maybe_referrer.as_ref().map(|referrer| format!(" imported from '{}'", referrer)).unwrap_or_default(),
|
||||||
)]
|
)]
|
||||||
pub struct UnsupportedDirImportError {
|
pub struct UnsupportedDirImportError {
|
||||||
pub dir_url: ModuleSpecifier,
|
pub dir_url: Url,
|
||||||
pub maybe_referrer: Option<ModuleSpecifier>,
|
pub maybe_referrer: Option<Url>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeJsErrorCoded for UnsupportedDirImportError {
|
impl NodeJsErrorCoded for UnsupportedDirImportError {
|
||||||
|
@ -603,7 +603,7 @@ pub struct InvalidPackageTargetError {
|
||||||
pub sub_path: String,
|
pub sub_path: String,
|
||||||
pub target: String,
|
pub target: String,
|
||||||
pub is_import: bool,
|
pub is_import: bool,
|
||||||
pub maybe_referrer: Option<ModuleSpecifier>,
|
pub maybe_referrer: Option<Url>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::error::Error for InvalidPackageTargetError {}
|
impl std::error::Error for InvalidPackageTargetError {}
|
||||||
|
@ -657,7 +657,7 @@ impl NodeJsErrorCoded for InvalidPackageTargetError {
|
||||||
pub struct PackagePathNotExportedError {
|
pub struct PackagePathNotExportedError {
|
||||||
pub pkg_json_path: PathBuf,
|
pub pkg_json_path: PathBuf,
|
||||||
pub subpath: String,
|
pub subpath: String,
|
||||||
pub maybe_referrer: Option<ModuleSpecifier>,
|
pub maybe_referrer: Option<Url>,
|
||||||
pub mode: NodeResolutionMode,
|
pub mode: NodeResolutionMode,
|
||||||
}
|
}
|
||||||
|
|
26
ext/node_resolver/lib.rs
Normal file
26
ext/node_resolver/lib.rs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
#![deny(clippy::print_stderr)]
|
||||||
|
#![deny(clippy::print_stdout)]
|
||||||
|
|
||||||
|
pub mod analyze;
|
||||||
|
pub mod env;
|
||||||
|
pub mod errors;
|
||||||
|
mod npm;
|
||||||
|
mod package_json;
|
||||||
|
mod path;
|
||||||
|
mod resolution;
|
||||||
|
mod sync;
|
||||||
|
|
||||||
|
pub use deno_package_json::PackageJson;
|
||||||
|
pub use npm::NpmResolver;
|
||||||
|
pub use npm::NpmResolverRc;
|
||||||
|
pub use package_json::load_pkg_json;
|
||||||
|
pub use package_json::PackageJsonThreadLocalCache;
|
||||||
|
pub use path::PathClean;
|
||||||
|
pub use resolution::NodeModuleKind;
|
||||||
|
pub use resolution::NodeResolution;
|
||||||
|
pub use resolution::NodeResolutionMode;
|
||||||
|
pub use resolution::NodeResolver;
|
||||||
|
pub use resolution::DEFAULT_CONDITIONS;
|
||||||
|
pub use resolution::REQUIRE_CONDITIONS;
|
41
ext/node_resolver/npm.rs
Normal file
41
ext/node_resolver/npm.rs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
use crate::errors;
|
||||||
|
use crate::path::PathClean;
|
||||||
|
use crate::sync::MaybeSend;
|
||||||
|
use crate::sync::MaybeSync;
|
||||||
|
|
||||||
|
#[allow(clippy::disallowed_types)]
|
||||||
|
pub type NpmResolverRc = crate::sync::MaybeArc<dyn NpmResolver>;
|
||||||
|
|
||||||
|
pub trait NpmResolver: std::fmt::Debug + MaybeSend + MaybeSync {
|
||||||
|
/// Resolves an npm package folder path from an npm package referrer.
|
||||||
|
fn resolve_package_folder_from_package(
|
||||||
|
&self,
|
||||||
|
specifier: &str,
|
||||||
|
referrer: &Url,
|
||||||
|
) -> Result<PathBuf, errors::PackageFolderResolveError>;
|
||||||
|
|
||||||
|
fn in_npm_package(&self, specifier: &Url) -> bool;
|
||||||
|
|
||||||
|
fn in_npm_package_at_dir_path(&self, path: &Path) -> bool {
|
||||||
|
let specifier = match Url::from_directory_path(path.to_path_buf().clean()) {
|
||||||
|
Ok(p) => p,
|
||||||
|
Err(_) => return false,
|
||||||
|
};
|
||||||
|
self.in_npm_package(&specifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn in_npm_package_at_file_path(&self, path: &Path) -> bool {
|
||||||
|
let specifier = match Url::from_file_path(path.to_path_buf().clean()) {
|
||||||
|
Ok(p) => p,
|
||||||
|
Err(_) => return false,
|
||||||
|
};
|
||||||
|
self.in_npm_package(&specifier)
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,31 +33,14 @@ impl deno_package_json::PackageJsonCache for PackageJsonThreadLocalCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DenoPkgJsonFsAdapter<'a>(pub &'a dyn deno_fs::FileSystem);
|
|
||||||
|
|
||||||
impl<'a> deno_package_json::fs::DenoPkgJsonFs for DenoPkgJsonFsAdapter<'a> {
|
|
||||||
fn read_to_string_lossy(
|
|
||||||
&self,
|
|
||||||
path: &Path,
|
|
||||||
) -> Result<String, std::io::Error> {
|
|
||||||
self
|
|
||||||
.0
|
|
||||||
.read_text_file_lossy_sync(path, None)
|
|
||||||
.map_err(|err| err.into_io_error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Helper to load a package.json file using the thread local cache
|
/// Helper to load a package.json file using the thread local cache
|
||||||
/// in deno_node.
|
/// in node_resolver.
|
||||||
pub fn load_pkg_json(
|
pub fn load_pkg_json(
|
||||||
fs: &dyn deno_fs::FileSystem,
|
fs: &dyn deno_package_json::fs::DenoPkgJsonFs,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
) -> Result<Option<PackageJsonRc>, PackageJsonLoadError> {
|
) -> Result<Option<PackageJsonRc>, PackageJsonLoadError> {
|
||||||
let result = PackageJson::load_from_path(
|
let result =
|
||||||
path,
|
PackageJson::load_from_path(path, fs, Some(&PackageJsonThreadLocalCache));
|
||||||
&DenoPkgJsonFsAdapter(fs),
|
|
||||||
Some(&PackageJsonThreadLocalCache),
|
|
||||||
);
|
|
||||||
match result {
|
match result {
|
||||||
Ok(pkg_json) => Ok(Some(pkg_json)),
|
Ok(pkg_json) => Ok(Some(pkg_json)),
|
||||||
Err(deno_package_json::PackageJsonLoadError::Io { source, .. })
|
Err(deno_package_json::PackageJsonLoadError::Io { source, .. })
|
142
ext/node_resolver/path.rs
Normal file
142
ext/node_resolver/path.rs
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use std::path::Component;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
/// Extension to path_clean::PathClean
|
||||||
|
pub trait PathClean<T> {
|
||||||
|
fn clean(&self) -> T;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PathClean<PathBuf> for PathBuf {
|
||||||
|
fn clean(&self) -> PathBuf {
|
||||||
|
let path = path_clean::PathClean::clean(self);
|
||||||
|
if cfg!(windows) && path.to_string_lossy().contains("..\\") {
|
||||||
|
// temporary workaround because path_clean::PathClean::clean is
|
||||||
|
// not good enough on windows
|
||||||
|
let mut components = Vec::new();
|
||||||
|
|
||||||
|
for component in path.components() {
|
||||||
|
match component {
|
||||||
|
Component::CurDir => {
|
||||||
|
// skip
|
||||||
|
}
|
||||||
|
Component::ParentDir => {
|
||||||
|
let maybe_last_component = components.pop();
|
||||||
|
if !matches!(maybe_last_component, Some(Component::Normal(_))) {
|
||||||
|
panic!("Error normalizing: {}", path.display());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Component::Normal(_) | Component::RootDir | Component::Prefix(_) => {
|
||||||
|
components.push(component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
components.into_iter().collect::<PathBuf>()
|
||||||
|
} else {
|
||||||
|
path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn to_file_specifier(path: &Path) -> Url {
|
||||||
|
match Url::from_file_path(path) {
|
||||||
|
Ok(url) => url,
|
||||||
|
Err(_) => panic!("Invalid path: {}", path.display()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo(dsherret): we have the below code also in deno_core and it
|
||||||
|
// would be good to somehow re-use it in both places (we don't want
|
||||||
|
// to create a dependency on deno_core here)
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
#[inline]
|
||||||
|
pub fn strip_unc_prefix(path: PathBuf) -> PathBuf {
|
||||||
|
path
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Strips the unc prefix (ex. \\?\) from Windows paths.
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub fn strip_unc_prefix(path: PathBuf) -> PathBuf {
|
||||||
|
use std::path::Component;
|
||||||
|
use std::path::Prefix;
|
||||||
|
|
||||||
|
let mut components = path.components();
|
||||||
|
match components.next() {
|
||||||
|
Some(Component::Prefix(prefix)) => {
|
||||||
|
match prefix.kind() {
|
||||||
|
// \\?\device
|
||||||
|
Prefix::Verbatim(device) => {
|
||||||
|
let mut path = PathBuf::new();
|
||||||
|
path.push(format!(r"\\{}\", device.to_string_lossy()));
|
||||||
|
path.extend(components.filter(|c| !matches!(c, Component::RootDir)));
|
||||||
|
path
|
||||||
|
}
|
||||||
|
// \\?\c:\path
|
||||||
|
Prefix::VerbatimDisk(_) => {
|
||||||
|
let mut path = PathBuf::new();
|
||||||
|
path.push(prefix.as_os_str().to_string_lossy().replace(r"\\?\", ""));
|
||||||
|
path.extend(components);
|
||||||
|
path
|
||||||
|
}
|
||||||
|
// \\?\UNC\hostname\share_name\path
|
||||||
|
Prefix::VerbatimUNC(hostname, share_name) => {
|
||||||
|
let mut path = PathBuf::new();
|
||||||
|
path.push(format!(
|
||||||
|
r"\\{}\{}\",
|
||||||
|
hostname.to_string_lossy(),
|
||||||
|
share_name.to_string_lossy()
|
||||||
|
));
|
||||||
|
path.extend(components.filter(|c| !matches!(c, Component::RootDir)));
|
||||||
|
path
|
||||||
|
}
|
||||||
|
_ => path,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => path,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
#[cfg(windows)]
|
||||||
|
#[test]
|
||||||
|
fn test_strip_unc_prefix() {
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
run_test(r"C:\", r"C:\");
|
||||||
|
run_test(r"C:\test\file.txt", r"C:\test\file.txt");
|
||||||
|
|
||||||
|
run_test(r"\\?\C:\", r"C:\");
|
||||||
|
run_test(r"\\?\C:\test\file.txt", r"C:\test\file.txt");
|
||||||
|
|
||||||
|
run_test(r"\\.\C:\", r"\\.\C:\");
|
||||||
|
run_test(r"\\.\C:\Test\file.txt", r"\\.\C:\Test\file.txt");
|
||||||
|
|
||||||
|
run_test(r"\\?\UNC\localhost\", r"\\localhost");
|
||||||
|
run_test(r"\\?\UNC\localhost\c$\", r"\\localhost\c$");
|
||||||
|
run_test(
|
||||||
|
r"\\?\UNC\localhost\c$\Windows\file.txt",
|
||||||
|
r"\\localhost\c$\Windows\file.txt",
|
||||||
|
);
|
||||||
|
run_test(r"\\?\UNC\wsl$\deno.json", r"\\wsl$\deno.json");
|
||||||
|
|
||||||
|
run_test(r"\\?\server1", r"\\server1");
|
||||||
|
run_test(r"\\?\server1\e$\", r"\\server1\e$\");
|
||||||
|
run_test(
|
||||||
|
r"\\?\server1\e$\test\file.txt",
|
||||||
|
r"\\server1\e$\test\file.txt",
|
||||||
|
);
|
||||||
|
|
||||||
|
fn run_test(input: &str, expected: &str) {
|
||||||
|
assert_eq!(
|
||||||
|
super::strip_unc_prefix(PathBuf::from(input)),
|
||||||
|
PathBuf::from(expected)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,16 +5,15 @@ use std::collections::HashMap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use deno_core::anyhow::bail;
|
use anyhow::bail;
|
||||||
use deno_core::error::AnyError;
|
use anyhow::Error as AnyError;
|
||||||
use deno_core::serde_json::Map;
|
|
||||||
use deno_core::serde_json::Value;
|
|
||||||
use deno_core::url::Url;
|
|
||||||
use deno_core::ModuleSpecifier;
|
|
||||||
use deno_fs::FileSystemRc;
|
|
||||||
use deno_media_type::MediaType;
|
use deno_media_type::MediaType;
|
||||||
use deno_package_json::PackageJsonRc;
|
use deno_package_json::PackageJsonRc;
|
||||||
|
use serde_json::Map;
|
||||||
|
use serde_json::Value;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
use crate::env::NodeResolverEnv;
|
||||||
use crate::errors;
|
use crate::errors;
|
||||||
use crate::errors::CanonicalizingPkgJsonDirError;
|
use crate::errors::CanonicalizingPkgJsonDirError;
|
||||||
use crate::errors::ClosestPkgJsonError;
|
use crate::errors::ClosestPkgJsonError;
|
||||||
|
@ -49,12 +48,11 @@ use crate::errors::TypesNotFoundErrorData;
|
||||||
use crate::errors::UnsupportedDirImportError;
|
use crate::errors::UnsupportedDirImportError;
|
||||||
use crate::errors::UnsupportedEsmUrlSchemeError;
|
use crate::errors::UnsupportedEsmUrlSchemeError;
|
||||||
use crate::errors::UrlToNodeResolutionError;
|
use crate::errors::UrlToNodeResolutionError;
|
||||||
use crate::is_builtin_node_module;
|
use crate::path::strip_unc_prefix;
|
||||||
use crate::path::to_file_specifier;
|
use crate::path::to_file_specifier;
|
||||||
use crate::polyfill::get_module_name_from_builtin_node_module_specifier;
|
|
||||||
use crate::NpmResolverRc;
|
use crate::NpmResolverRc;
|
||||||
use crate::PackageJson;
|
|
||||||
use crate::PathClean;
|
use crate::PathClean;
|
||||||
|
use deno_package_json::PackageJson;
|
||||||
|
|
||||||
pub static DEFAULT_CONDITIONS: &[&str] = &["deno", "node", "import"];
|
pub static DEFAULT_CONDITIONS: &[&str] = &["deno", "node", "import"];
|
||||||
pub static REQUIRE_CONDITIONS: &[&str] = &["require", "node"];
|
pub static REQUIRE_CONDITIONS: &[&str] = &["require", "node"];
|
||||||
|
@ -76,21 +74,21 @@ impl NodeResolutionMode {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum NodeResolution {
|
pub enum NodeResolution {
|
||||||
Esm(ModuleSpecifier),
|
Esm(Url),
|
||||||
CommonJs(ModuleSpecifier),
|
CommonJs(Url),
|
||||||
BuiltIn(String),
|
BuiltIn(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeResolution {
|
impl NodeResolution {
|
||||||
pub fn into_url(self) -> ModuleSpecifier {
|
pub fn into_url(self) -> Url {
|
||||||
match self {
|
match self {
|
||||||
Self::Esm(u) => u,
|
Self::Esm(u) => u,
|
||||||
Self::CommonJs(u) => u,
|
Self::CommonJs(u) => u,
|
||||||
Self::BuiltIn(specifier) => {
|
Self::BuiltIn(specifier) => {
|
||||||
if specifier.starts_with("node:") {
|
if specifier.starts_with("node:") {
|
||||||
ModuleSpecifier::parse(&specifier).unwrap()
|
Url::parse(&specifier).unwrap()
|
||||||
} else {
|
} else {
|
||||||
ModuleSpecifier::parse(&format!("node:{specifier}")).unwrap()
|
Url::parse(&format!("node:{specifier}")).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,7 +96,7 @@ impl NodeResolution {
|
||||||
|
|
||||||
pub fn into_specifier_and_media_type(
|
pub fn into_specifier_and_media_type(
|
||||||
resolution: Option<Self>,
|
resolution: Option<Self>,
|
||||||
) -> (ModuleSpecifier, MediaType) {
|
) -> (Url, MediaType) {
|
||||||
match resolution {
|
match resolution {
|
||||||
Some(NodeResolution::CommonJs(specifier)) => {
|
Some(NodeResolution::CommonJs(specifier)) => {
|
||||||
let media_type = MediaType::from_specifier(&specifier);
|
let media_type = MediaType::from_specifier(&specifier);
|
||||||
|
@ -126,7 +124,7 @@ impl NodeResolution {
|
||||||
}
|
}
|
||||||
Some(resolution) => (resolution.into_url(), MediaType::Dts),
|
Some(resolution) => (resolution.into_url(), MediaType::Dts),
|
||||||
None => (
|
None => (
|
||||||
ModuleSpecifier::parse("internal:///missing_dependency.d.ts").unwrap(),
|
Url::parse("internal:///missing_dependency.d.ts").unwrap(),
|
||||||
MediaType::Dts,
|
MediaType::Dts,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
@ -134,25 +132,25 @@ impl NodeResolution {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::disallowed_types)]
|
#[allow(clippy::disallowed_types)]
|
||||||
pub type NodeResolverRc = deno_fs::sync::MaybeArc<NodeResolver>;
|
pub type NodeResolverRc<TEnv> = crate::sync::MaybeArc<NodeResolver<TEnv>>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NodeResolver {
|
pub struct NodeResolver<TEnv: NodeResolverEnv> {
|
||||||
fs: FileSystemRc,
|
env: TEnv,
|
||||||
npm_resolver: NpmResolverRc,
|
npm_resolver: NpmResolverRc,
|
||||||
in_npm_package_cache: deno_fs::sync::MaybeArcMutex<HashMap<String, bool>>,
|
in_npm_package_cache: crate::sync::MaybeArcMutex<HashMap<String, bool>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeResolver {
|
impl<TEnv: NodeResolverEnv> NodeResolver<TEnv> {
|
||||||
pub fn new(fs: FileSystemRc, npm_resolver: NpmResolverRc) -> Self {
|
pub fn new(env: TEnv, npm_resolver: NpmResolverRc) -> Self {
|
||||||
Self {
|
Self {
|
||||||
fs,
|
env,
|
||||||
npm_resolver,
|
npm_resolver,
|
||||||
in_npm_package_cache: deno_fs::sync::MaybeArcMutex::new(HashMap::new()),
|
in_npm_package_cache: crate::sync::MaybeArcMutex::new(HashMap::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool {
|
pub fn in_npm_package(&self, specifier: &Url) -> bool {
|
||||||
self.npm_resolver.in_npm_package(specifier)
|
self.npm_resolver.in_npm_package(specifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,12 +161,11 @@ impl NodeResolver {
|
||||||
return *result;
|
return *result;
|
||||||
}
|
}
|
||||||
|
|
||||||
let result =
|
let result = if let Ok(specifier) = Url::parse(&specifier) {
|
||||||
if let Ok(specifier) = deno_core::ModuleSpecifier::parse(&specifier) {
|
self.npm_resolver.in_npm_package(&specifier)
|
||||||
self.npm_resolver.in_npm_package(&specifier)
|
} else {
|
||||||
} else {
|
false
|
||||||
false
|
};
|
||||||
};
|
|
||||||
cache.insert(specifier.into_owned(), result);
|
cache.insert(specifier.into_owned(), result);
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -178,14 +175,14 @@ impl NodeResolver {
|
||||||
pub fn resolve(
|
pub fn resolve(
|
||||||
&self,
|
&self,
|
||||||
specifier: &str,
|
specifier: &str,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &Url,
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
) -> Result<NodeResolution, NodeResolveError> {
|
) -> Result<NodeResolution, NodeResolveError> {
|
||||||
// Note: if we are here, then the referrer is an esm module
|
// 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
|
// TODO(bartlomieju): skipped "policy" part as we don't plan to support it
|
||||||
|
|
||||||
if crate::is_builtin_node_module(specifier) {
|
if self.env.is_builtin_node_module(specifier) {
|
||||||
return Ok(NodeResolution::BuiltIn(specifier.to_string()));
|
return Ok(NodeResolution::BuiltIn(specifier.to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,11 +245,11 @@ impl NodeResolver {
|
||||||
fn module_resolve(
|
fn module_resolve(
|
||||||
&self,
|
&self,
|
||||||
specifier: &str,
|
specifier: &str,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &Url,
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
conditions: &[&str],
|
conditions: &[&str],
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
) -> Result<ModuleSpecifier, NodeResolveError> {
|
) -> Result<Url, NodeResolveError> {
|
||||||
if should_be_treated_as_relative_or_absolute_path(specifier) {
|
if should_be_treated_as_relative_or_absolute_path(specifier) {
|
||||||
Ok(referrer.join(specifier).map_err(|err| {
|
Ok(referrer.join(specifier).map_err(|err| {
|
||||||
NodeResolveRelativeJoinError {
|
NodeResolveRelativeJoinError {
|
||||||
|
@ -289,9 +286,9 @@ impl NodeResolver {
|
||||||
|
|
||||||
fn finalize_resolution(
|
fn finalize_resolution(
|
||||||
&self,
|
&self,
|
||||||
resolved: ModuleSpecifier,
|
resolved: Url,
|
||||||
maybe_referrer: Option<&ModuleSpecifier>,
|
maybe_referrer: Option<&Url>,
|
||||||
) -> Result<ModuleSpecifier, FinalizeResolutionError> {
|
) -> Result<Url, FinalizeResolutionError> {
|
||||||
let encoded_sep_re = lazy_regex::regex!(r"%2F|%2C");
|
let encoded_sep_re = lazy_regex::regex!(r"%2F|%2C");
|
||||||
|
|
||||||
if encoded_sep_re.is_match(resolved.path()) {
|
if encoded_sep_re.is_match(resolved.path()) {
|
||||||
|
@ -325,9 +322,9 @@ impl NodeResolver {
|
||||||
p_str.to_string()
|
p_str.to_string()
|
||||||
};
|
};
|
||||||
|
|
||||||
let (is_dir, is_file) = if let Ok(stats) = self.fs.stat_sync(Path::new(&p))
|
let (is_dir, is_file) = if let Ok(stats) = self.env.stat_sync(Path::new(&p))
|
||||||
{
|
{
|
||||||
(stats.is_directory, stats.is_file)
|
(stats.is_dir, stats.is_file)
|
||||||
} else {
|
} else {
|
||||||
(false, false)
|
(false, false)
|
||||||
};
|
};
|
||||||
|
@ -357,7 +354,7 @@ impl NodeResolver {
|
||||||
&self,
|
&self,
|
||||||
package_dir: &Path,
|
package_dir: &Path,
|
||||||
package_subpath: Option<&str>,
|
package_subpath: Option<&str>,
|
||||||
maybe_referrer: Option<&ModuleSpecifier>,
|
maybe_referrer: Option<&Url>,
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
) -> Result<NodeResolution, ResolvePkgSubpathFromDenoModuleError> {
|
) -> Result<NodeResolution, ResolvePkgSubpathFromDenoModuleError> {
|
||||||
let node_module_kind = NodeModuleKind::Esm;
|
let node_module_kind = NodeModuleKind::Esm;
|
||||||
|
@ -430,7 +427,7 @@ impl NodeResolver {
|
||||||
|
|
||||||
pub fn url_to_node_resolution(
|
pub fn url_to_node_resolution(
|
||||||
&self,
|
&self,
|
||||||
url: ModuleSpecifier,
|
url: Url,
|
||||||
) -> Result<NodeResolution, UrlToNodeResolutionError> {
|
) -> Result<NodeResolution, UrlToNodeResolutionError> {
|
||||||
let url_str = url.as_str().to_lowercase();
|
let url_str = url.as_str().to_lowercase();
|
||||||
if url_str.starts_with("http") || url_str.ends_with(".json") {
|
if url_str.starts_with("http") || url_str.ends_with(".json") {
|
||||||
|
@ -459,11 +456,11 @@ impl NodeResolver {
|
||||||
fn path_to_declaration_url(
|
fn path_to_declaration_url(
|
||||||
&self,
|
&self,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
maybe_referrer: Option<&ModuleSpecifier>,
|
maybe_referrer: Option<&Url>,
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
) -> Result<ModuleSpecifier, TypesNotFoundError> {
|
) -> Result<Url, TypesNotFoundError> {
|
||||||
fn probe_extensions(
|
fn probe_extensions<TEnv: NodeResolverEnv>(
|
||||||
fs: &dyn deno_fs::FileSystem,
|
fs: &TEnv,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
lowercase_path: &str,
|
lowercase_path: &str,
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
|
@ -514,11 +511,11 @@ impl NodeResolver {
|
||||||
return Ok(to_file_specifier(path));
|
return Ok(to_file_specifier(path));
|
||||||
}
|
}
|
||||||
if let Some(path) =
|
if let Some(path) =
|
||||||
probe_extensions(&*self.fs, path, &lowercase_path, referrer_kind)
|
probe_extensions(&self.env, path, &lowercase_path, referrer_kind)
|
||||||
{
|
{
|
||||||
return Ok(to_file_specifier(&path));
|
return Ok(to_file_specifier(&path));
|
||||||
}
|
}
|
||||||
if self.fs.is_dir_sync(path) {
|
if self.env.is_dir_sync(path) {
|
||||||
let resolution_result = self.resolve_package_dir_subpath(
|
let resolution_result = self.resolve_package_dir_subpath(
|
||||||
path,
|
path,
|
||||||
/* sub path */ ".",
|
/* sub path */ ".",
|
||||||
|
@ -535,7 +532,7 @@ impl NodeResolver {
|
||||||
}
|
}
|
||||||
let index_path = path.join("index.js");
|
let index_path = path.join("index.js");
|
||||||
if let Some(path) = probe_extensions(
|
if let Some(path) = probe_extensions(
|
||||||
&*self.fs,
|
&self.env,
|
||||||
&index_path,
|
&index_path,
|
||||||
&index_path.to_string_lossy().to_lowercase(),
|
&index_path.to_string_lossy().to_lowercase(),
|
||||||
referrer_kind,
|
referrer_kind,
|
||||||
|
@ -554,15 +551,15 @@ impl NodeResolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub(super) fn package_imports_resolve(
|
pub fn package_imports_resolve(
|
||||||
&self,
|
&self,
|
||||||
name: &str,
|
name: &str,
|
||||||
maybe_referrer: Option<&ModuleSpecifier>,
|
maybe_referrer: Option<&Url>,
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
referrer_pkg_json: Option<&PackageJson>,
|
referrer_pkg_json: Option<&PackageJson>,
|
||||||
conditions: &[&str],
|
conditions: &[&str],
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
) -> Result<ModuleSpecifier, PackageImportsResolveError> {
|
) -> Result<Url, PackageImportsResolveError> {
|
||||||
if name == "#" || name.starts_with("#/") || name.ends_with('/') {
|
if name == "#" || name.starts_with("#/") || name.ends_with('/') {
|
||||||
let reason = "is not a valid internal imports specifier name";
|
let reason = "is not a valid internal imports specifier name";
|
||||||
return Err(
|
return Err(
|
||||||
|
@ -659,13 +656,13 @@ impl NodeResolver {
|
||||||
subpath: &str,
|
subpath: &str,
|
||||||
match_: &str,
|
match_: &str,
|
||||||
package_json_path: &Path,
|
package_json_path: &Path,
|
||||||
maybe_referrer: Option<&ModuleSpecifier>,
|
maybe_referrer: Option<&Url>,
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
pattern: bool,
|
pattern: bool,
|
||||||
internal: bool,
|
internal: bool,
|
||||||
conditions: &[&str],
|
conditions: &[&str],
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
) -> Result<ModuleSpecifier, PackageTargetResolveError> {
|
) -> Result<Url, PackageTargetResolveError> {
|
||||||
if !subpath.is_empty() && !pattern && !target.ends_with('/') {
|
if !subpath.is_empty() && !pattern && !target.ends_with('/') {
|
||||||
return Err(
|
return Err(
|
||||||
InvalidPackageTargetError {
|
InvalidPackageTargetError {
|
||||||
|
@ -739,11 +736,8 @@ impl NodeResolver {
|
||||||
return match result {
|
return match result {
|
||||||
Ok(url) => Ok(url),
|
Ok(url) => Ok(url),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
if is_builtin_node_module(target) {
|
if self.env.is_builtin_node_module(target) {
|
||||||
Ok(
|
Ok(Url::parse(&format!("node:{}", target)).unwrap())
|
||||||
ModuleSpecifier::parse(&format!("node:{}", target))
|
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
|
@ -824,13 +818,13 @@ impl NodeResolver {
|
||||||
target: &Value,
|
target: &Value,
|
||||||
subpath: &str,
|
subpath: &str,
|
||||||
package_subpath: &str,
|
package_subpath: &str,
|
||||||
maybe_referrer: Option<&ModuleSpecifier>,
|
maybe_referrer: Option<&Url>,
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
pattern: bool,
|
pattern: bool,
|
||||||
internal: bool,
|
internal: bool,
|
||||||
conditions: &[&str],
|
conditions: &[&str],
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
) -> Result<Option<ModuleSpecifier>, PackageTargetResolveError> {
|
) -> Result<Option<Url>, PackageTargetResolveError> {
|
||||||
let result = self.resolve_package_target_inner(
|
let result = self.resolve_package_target_inner(
|
||||||
package_json_path,
|
package_json_path,
|
||||||
target,
|
target,
|
||||||
|
@ -880,13 +874,13 @@ impl NodeResolver {
|
||||||
target: &Value,
|
target: &Value,
|
||||||
subpath: &str,
|
subpath: &str,
|
||||||
package_subpath: &str,
|
package_subpath: &str,
|
||||||
maybe_referrer: Option<&ModuleSpecifier>,
|
maybe_referrer: Option<&Url>,
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
pattern: bool,
|
pattern: bool,
|
||||||
internal: bool,
|
internal: bool,
|
||||||
conditions: &[&str],
|
conditions: &[&str],
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
) -> Result<Option<ModuleSpecifier>, PackageTargetResolveError> {
|
) -> Result<Option<Url>, PackageTargetResolveError> {
|
||||||
if let Some(target) = target.as_str() {
|
if let Some(target) = target.as_str() {
|
||||||
let url = self.resolve_package_target_string(
|
let url = self.resolve_package_target_string(
|
||||||
target,
|
target,
|
||||||
|
@ -1007,11 +1001,11 @@ impl NodeResolver {
|
||||||
package_json_path: &Path,
|
package_json_path: &Path,
|
||||||
package_subpath: &str,
|
package_subpath: &str,
|
||||||
package_exports: &Map<String, Value>,
|
package_exports: &Map<String, Value>,
|
||||||
maybe_referrer: Option<&ModuleSpecifier>,
|
maybe_referrer: Option<&Url>,
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
conditions: &[&str],
|
conditions: &[&str],
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
) -> Result<ModuleSpecifier, PackageExportsResolveError> {
|
) -> Result<Url, PackageExportsResolveError> {
|
||||||
if package_exports.contains_key(package_subpath)
|
if package_exports.contains_key(package_subpath)
|
||||||
&& package_subpath.find('*').is_none()
|
&& package_subpath.find('*').is_none()
|
||||||
&& !package_subpath.ends_with('/')
|
&& !package_subpath.ends_with('/')
|
||||||
|
@ -1120,11 +1114,11 @@ impl NodeResolver {
|
||||||
pub(super) fn package_resolve(
|
pub(super) fn package_resolve(
|
||||||
&self,
|
&self,
|
||||||
specifier: &str,
|
specifier: &str,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &Url,
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
conditions: &[&str],
|
conditions: &[&str],
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
) -> Result<ModuleSpecifier, PackageResolveError> {
|
) -> Result<Url, PackageResolveError> {
|
||||||
let (package_name, package_subpath, _is_scoped) =
|
let (package_name, package_subpath, _is_scoped) =
|
||||||
parse_npm_pkg_name(specifier, referrer)?;
|
parse_npm_pkg_name(specifier, referrer)?;
|
||||||
|
|
||||||
|
@ -1162,11 +1156,11 @@ impl NodeResolver {
|
||||||
&self,
|
&self,
|
||||||
package_name: &str,
|
package_name: &str,
|
||||||
package_subpath: &str,
|
package_subpath: &str,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &Url,
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
conditions: &[&str],
|
conditions: &[&str],
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
) -> Result<ModuleSpecifier, PackageResolveError> {
|
) -> Result<Url, PackageResolveError> {
|
||||||
let result = self.resolve_package_subpath_for_package_inner(
|
let result = self.resolve_package_subpath_for_package_inner(
|
||||||
package_name,
|
package_name,
|
||||||
package_subpath,
|
package_subpath,
|
||||||
|
@ -1175,7 +1169,7 @@ impl NodeResolver {
|
||||||
conditions,
|
conditions,
|
||||||
mode,
|
mode,
|
||||||
);
|
);
|
||||||
if mode.is_types() && !matches!(result, Ok(ModuleSpecifier { .. })) {
|
if mode.is_types() && !matches!(result, Ok(Url { .. })) {
|
||||||
// try to resolve with the @types package
|
// try to resolve with the @types package
|
||||||
let package_name = types_package_name(package_name);
|
let package_name = types_package_name(package_name);
|
||||||
if let Ok(result) = self.resolve_package_subpath_for_package_inner(
|
if let Ok(result) = self.resolve_package_subpath_for_package_inner(
|
||||||
|
@ -1197,11 +1191,11 @@ impl NodeResolver {
|
||||||
&self,
|
&self,
|
||||||
package_name: &str,
|
package_name: &str,
|
||||||
package_subpath: &str,
|
package_subpath: &str,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &Url,
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
conditions: &[&str],
|
conditions: &[&str],
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
) -> Result<ModuleSpecifier, PackageResolveError> {
|
) -> Result<Url, PackageResolveError> {
|
||||||
let package_dir_path = self
|
let package_dir_path = self
|
||||||
.npm_resolver
|
.npm_resolver
|
||||||
.resolve_package_folder_from_package(package_name, referrer)?;
|
.resolve_package_folder_from_package(package_name, referrer)?;
|
||||||
|
@ -1237,11 +1231,11 @@ impl NodeResolver {
|
||||||
&self,
|
&self,
|
||||||
package_dir_path: &Path,
|
package_dir_path: &Path,
|
||||||
package_subpath: &str,
|
package_subpath: &str,
|
||||||
maybe_referrer: Option<&ModuleSpecifier>,
|
maybe_referrer: Option<&Url>,
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
conditions: &[&str],
|
conditions: &[&str],
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
) -> Result<ModuleSpecifier, PackageSubpathResolveError> {
|
) -> Result<Url, PackageSubpathResolveError> {
|
||||||
let package_json_path = package_dir_path.join("package.json");
|
let package_json_path = package_dir_path.join("package.json");
|
||||||
match self.load_package_json(&package_json_path)? {
|
match self.load_package_json(&package_json_path)? {
|
||||||
Some(pkg_json) => self.resolve_package_subpath(
|
Some(pkg_json) => self.resolve_package_subpath(
|
||||||
|
@ -1271,11 +1265,11 @@ impl NodeResolver {
|
||||||
&self,
|
&self,
|
||||||
package_json: &PackageJson,
|
package_json: &PackageJson,
|
||||||
package_subpath: &str,
|
package_subpath: &str,
|
||||||
referrer: Option<&ModuleSpecifier>,
|
referrer: Option<&Url>,
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
conditions: &[&str],
|
conditions: &[&str],
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
) -> Result<ModuleSpecifier, PackageSubpathResolveError> {
|
) -> Result<Url, PackageSubpathResolveError> {
|
||||||
if let Some(exports) = &package_json.exports {
|
if let Some(exports) = &package_json.exports {
|
||||||
let result = self.package_exports_resolve(
|
let result = self.package_exports_resolve(
|
||||||
&package_json.path,
|
&package_json.path,
|
||||||
|
@ -1328,10 +1322,10 @@ impl NodeResolver {
|
||||||
&self,
|
&self,
|
||||||
directory: &Path,
|
directory: &Path,
|
||||||
package_subpath: &str,
|
package_subpath: &str,
|
||||||
referrer: Option<&ModuleSpecifier>,
|
referrer: Option<&Url>,
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
) -> Result<ModuleSpecifier, TypesNotFoundError> {
|
) -> Result<Url, TypesNotFoundError> {
|
||||||
assert_ne!(package_subpath, ".");
|
assert_ne!(package_subpath, ".");
|
||||||
let file_path = directory.join(package_subpath);
|
let file_path = directory.join(package_subpath);
|
||||||
if mode.is_types() {
|
if mode.is_types() {
|
||||||
|
@ -1345,10 +1339,10 @@ impl NodeResolver {
|
||||||
&self,
|
&self,
|
||||||
directory: &Path,
|
directory: &Path,
|
||||||
package_subpath: &str,
|
package_subpath: &str,
|
||||||
maybe_referrer: Option<&ModuleSpecifier>,
|
maybe_referrer: Option<&Url>,
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
) -> Result<ModuleSpecifier, LegacyResolveError> {
|
) -> Result<Url, LegacyResolveError> {
|
||||||
if package_subpath == "." {
|
if package_subpath == "." {
|
||||||
self.legacy_index_resolve(directory, maybe_referrer, referrer_kind, mode)
|
self.legacy_index_resolve(directory, maybe_referrer, referrer_kind, mode)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1366,7 +1360,7 @@ impl NodeResolver {
|
||||||
|
|
||||||
pub fn get_closest_package_json(
|
pub fn get_closest_package_json(
|
||||||
&self,
|
&self,
|
||||||
url: &ModuleSpecifier,
|
url: &Url,
|
||||||
) -> Result<Option<PackageJsonRc>, ClosestPkgJsonError> {
|
) -> Result<Option<PackageJsonRc>, ClosestPkgJsonError> {
|
||||||
let Ok(file_path) = url.to_file_path() else {
|
let Ok(file_path) = url.to_file_path() else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
|
@ -1380,10 +1374,10 @@ impl NodeResolver {
|
||||||
) -> Result<Option<PackageJsonRc>, ClosestPkgJsonError> {
|
) -> Result<Option<PackageJsonRc>, ClosestPkgJsonError> {
|
||||||
let parent_dir = file_path.parent().unwrap();
|
let parent_dir = file_path.parent().unwrap();
|
||||||
let current_dir =
|
let current_dir =
|
||||||
deno_core::strip_unc_prefix(self.fs.realpath_sync(parent_dir).map_err(
|
strip_unc_prefix(self.env.realpath_sync(parent_dir).map_err(
|
||||||
|source| CanonicalizingPkgJsonDirError {
|
|source| CanonicalizingPkgJsonDirError {
|
||||||
dir_path: parent_dir.to_path_buf(),
|
dir_path: parent_dir.to_path_buf(),
|
||||||
source: source.into_io_error(),
|
source,
|
||||||
},
|
},
|
||||||
)?);
|
)?);
|
||||||
for current_dir in current_dir.ancestors() {
|
for current_dir in current_dir.ancestors() {
|
||||||
|
@ -1396,20 +1390,23 @@ impl NodeResolver {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn load_package_json(
|
pub fn load_package_json(
|
||||||
&self,
|
&self,
|
||||||
package_json_path: &Path,
|
package_json_path: &Path,
|
||||||
) -> Result<Option<PackageJsonRc>, PackageJsonLoadError> {
|
) -> Result<Option<PackageJsonRc>, PackageJsonLoadError> {
|
||||||
crate::package_json::load_pkg_json(&*self.fs, package_json_path)
|
crate::package_json::load_pkg_json(
|
||||||
|
self.env.pkg_json_fs(),
|
||||||
|
package_json_path,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn legacy_main_resolve(
|
pub(super) fn legacy_main_resolve(
|
||||||
&self,
|
&self,
|
||||||
package_json: &PackageJson,
|
package_json: &PackageJson,
|
||||||
maybe_referrer: Option<&ModuleSpecifier>,
|
maybe_referrer: Option<&Url>,
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
) -> Result<ModuleSpecifier, LegacyResolveError> {
|
) -> Result<Url, LegacyResolveError> {
|
||||||
let maybe_main = if mode.is_types() {
|
let maybe_main = if mode.is_types() {
|
||||||
match package_json.types.as_ref() {
|
match package_json.types.as_ref() {
|
||||||
Some(types) => Some(types.as_str()),
|
Some(types) => Some(types.as_str()),
|
||||||
|
@ -1437,7 +1434,7 @@ impl NodeResolver {
|
||||||
|
|
||||||
if let Some(main) = maybe_main {
|
if let Some(main) = maybe_main {
|
||||||
let guess = package_json.path.parent().unwrap().join(main).clean();
|
let guess = package_json.path.parent().unwrap().join(main).clean();
|
||||||
if self.fs.is_file_sync(&guess) {
|
if self.env.is_file_sync(&guess) {
|
||||||
return Ok(to_file_specifier(&guess));
|
return Ok(to_file_specifier(&guess));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1466,7 +1463,7 @@ impl NodeResolver {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.join(format!("{main}{ending}"))
|
.join(format!("{main}{ending}"))
|
||||||
.clean();
|
.clean();
|
||||||
if self.fs.is_file_sync(&guess) {
|
if self.env.is_file_sync(&guess) {
|
||||||
// TODO(bartlomieju): emitLegacyIndexDeprecation()
|
// TODO(bartlomieju): emitLegacyIndexDeprecation()
|
||||||
return Ok(to_file_specifier(&guess));
|
return Ok(to_file_specifier(&guess));
|
||||||
}
|
}
|
||||||
|
@ -1484,10 +1481,10 @@ impl NodeResolver {
|
||||||
fn legacy_index_resolve(
|
fn legacy_index_resolve(
|
||||||
&self,
|
&self,
|
||||||
directory: &Path,
|
directory: &Path,
|
||||||
maybe_referrer: Option<&ModuleSpecifier>,
|
maybe_referrer: Option<&Url>,
|
||||||
referrer_kind: NodeModuleKind,
|
referrer_kind: NodeModuleKind,
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
) -> Result<ModuleSpecifier, LegacyResolveError> {
|
) -> Result<Url, LegacyResolveError> {
|
||||||
let index_file_names = if mode.is_types() {
|
let index_file_names = if mode.is_types() {
|
||||||
// todo(dsherret): investigate exactly how typescript does this
|
// todo(dsherret): investigate exactly how typescript does this
|
||||||
match referrer_kind {
|
match referrer_kind {
|
||||||
|
@ -1499,7 +1496,7 @@ impl NodeResolver {
|
||||||
};
|
};
|
||||||
for index_file_name in index_file_names {
|
for index_file_name in index_file_names {
|
||||||
let guess = directory.join(index_file_name).clean();
|
let guess = directory.join(index_file_name).clean();
|
||||||
if self.fs.is_file_sync(&guess) {
|
if self.env.is_file_sync(&guess) {
|
||||||
// TODO(bartlomieju): emitLegacyIndexDeprecation()
|
// TODO(bartlomieju): emitLegacyIndexDeprecation()
|
||||||
return Ok(to_file_specifier(&guess));
|
return Ok(to_file_specifier(&guess));
|
||||||
}
|
}
|
||||||
|
@ -1615,13 +1612,13 @@ fn resolve_bin_entry_value<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_file_path(url: &ModuleSpecifier) -> PathBuf {
|
fn to_file_path(url: &Url) -> PathBuf {
|
||||||
url
|
url
|
||||||
.to_file_path()
|
.to_file_path()
|
||||||
.unwrap_or_else(|_| panic!("Provided URL was not file:// URL: {url}"))
|
.unwrap_or_else(|_| panic!("Provided URL was not file:// URL: {url}"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_file_path_string(url: &ModuleSpecifier) -> String {
|
fn to_file_path_string(url: &Url) -> String {
|
||||||
to_file_path(url).display().to_string()
|
to_file_path(url).display().to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1696,7 +1693,7 @@ fn with_known_extension(path: &Path, ext: &str) -> PathBuf {
|
||||||
path.with_file_name(format!("{file_name}.{ext}"))
|
path.with_file_name(format!("{file_name}.{ext}"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_specifier_display_string(url: &ModuleSpecifier) -> String {
|
fn to_specifier_display_string(url: &Url) -> String {
|
||||||
if let Ok(path) = url.to_file_path() {
|
if let Ok(path) = url.to_file_path() {
|
||||||
path.display().to_string()
|
path.display().to_string()
|
||||||
} else {
|
} else {
|
||||||
|
@ -1708,7 +1705,7 @@ fn throw_invalid_subpath(
|
||||||
subpath: String,
|
subpath: String,
|
||||||
package_json_path: &Path,
|
package_json_path: &Path,
|
||||||
internal: bool,
|
internal: bool,
|
||||||
maybe_referrer: Option<&ModuleSpecifier>,
|
maybe_referrer: Option<&Url>,
|
||||||
) -> InvalidModuleSpecifierError {
|
) -> InvalidModuleSpecifierError {
|
||||||
let ie = if internal { "imports" } else { "exports" };
|
let ie = if internal { "imports" } else { "exports" };
|
||||||
let reason = format!(
|
let reason = format!(
|
||||||
|
@ -1725,7 +1722,7 @@ fn throw_invalid_subpath(
|
||||||
|
|
||||||
pub fn parse_npm_pkg_name(
|
pub fn parse_npm_pkg_name(
|
||||||
specifier: &str,
|
specifier: &str,
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &Url,
|
||||||
) -> Result<(String, String, bool), InvalidModuleSpecifierError> {
|
) -> Result<(String, String, bool), InvalidModuleSpecifierError> {
|
||||||
let mut separator_index = specifier.find('/');
|
let mut separator_index = specifier.find('/');
|
||||||
let mut valid_package_name = true;
|
let mut valid_package_name = true;
|
||||||
|
@ -1824,9 +1821,21 @@ fn types_package_name(package_name: &str) -> String {
|
||||||
format!("@types/{}", package_name.replace('/', "__"))
|
format!("@types/{}", package_name.replace('/', "__"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ex. returns `fs` for `node:fs`
|
||||||
|
fn get_module_name_from_builtin_node_module_specifier(
|
||||||
|
specifier: &Url,
|
||||||
|
) -> Option<&str> {
|
||||||
|
if specifier.scheme() != "node" {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (_, specifier) = specifier.as_str().split_once(':')?;
|
||||||
|
Some(specifier)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use deno_core::serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
86
ext/node_resolver/sync.rs
Normal file
86
ext/node_resolver/sync.rs
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
pub use inner::*;
|
||||||
|
|
||||||
|
#[cfg(feature = "sync")]
|
||||||
|
mod inner {
|
||||||
|
#![allow(clippy::disallowed_types)]
|
||||||
|
|
||||||
|
use std::ops::Deref;
|
||||||
|
use std::ops::DerefMut;
|
||||||
|
pub use std::sync::Arc as MaybeArc;
|
||||||
|
|
||||||
|
pub struct MaybeArcMutexGuard<'lock, T>(std::sync::MutexGuard<'lock, T>);
|
||||||
|
|
||||||
|
impl<'lock, T> Deref for MaybeArcMutexGuard<'lock, T> {
|
||||||
|
type Target = std::sync::MutexGuard<'lock, T>;
|
||||||
|
fn deref(&self) -> &std::sync::MutexGuard<'lock, T> {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'lock, T> DerefMut for MaybeArcMutexGuard<'lock, T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut std::sync::MutexGuard<'lock, T> {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct MaybeArcMutex<T>(std::sync::Arc<std::sync::Mutex<T>>);
|
||||||
|
impl<T> MaybeArcMutex<T> {
|
||||||
|
pub fn new(val: T) -> Self {
|
||||||
|
Self(std::sync::Arc::new(std::sync::Mutex::new(val)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'lock, T> MaybeArcMutex<T> {
|
||||||
|
pub fn lock(&'lock self) -> MaybeArcMutexGuard<'lock, T> {
|
||||||
|
MaybeArcMutexGuard(self.0.lock().unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub use core::marker::Send as MaybeSend;
|
||||||
|
pub use core::marker::Sync as MaybeSync;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "sync"))]
|
||||||
|
mod inner {
|
||||||
|
use std::ops::Deref;
|
||||||
|
use std::ops::DerefMut;
|
||||||
|
|
||||||
|
pub use std::rc::Rc as MaybeArc;
|
||||||
|
|
||||||
|
pub struct MaybeArcMutexGuard<'lock, T>(std::cell::RefMut<'lock, T>);
|
||||||
|
|
||||||
|
impl<'lock, T> Deref for MaybeArcMutexGuard<'lock, T> {
|
||||||
|
type Target = std::cell::RefMut<'lock, T>;
|
||||||
|
fn deref(&self) -> &std::cell::RefMut<'lock, T> {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'lock, T> DerefMut for MaybeArcMutexGuard<'lock, T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut std::cell::RefMut<'lock, T> {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct MaybeArcMutex<T>(std::rc::Rc<std::cell::RefCell<T>>);
|
||||||
|
impl<T> MaybeArcMutex<T> {
|
||||||
|
pub fn new(val: T) -> Self {
|
||||||
|
Self(std::rc::Rc::new(std::cell::RefCell::new(val)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'lock, T> MaybeArcMutex<T> {
|
||||||
|
pub fn lock(&'lock self) -> MaybeArcMutexGuard<'lock, T> {
|
||||||
|
MaybeArcMutexGuard(self.0.borrow_mut())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait MaybeSync {}
|
||||||
|
impl<T> MaybeSync for T where T: ?Sized {}
|
||||||
|
pub trait MaybeSend {}
|
||||||
|
impl<T> MaybeSend for T where T: ?Sized {}
|
||||||
|
}
|
|
@ -94,6 +94,7 @@ deno_webgpu.workspace = true
|
||||||
deno_webidl.workspace = true
|
deno_webidl.workspace = true
|
||||||
deno_websocket.workspace = true
|
deno_websocket.workspace = true
|
||||||
deno_webstorage.workspace = true
|
deno_webstorage.workspace = true
|
||||||
|
node_resolver = { workspace = true, features = ["sync"] }
|
||||||
|
|
||||||
dlopen2.workspace = true
|
dlopen2.workspace = true
|
||||||
encoding_rs.workspace = true
|
encoding_rs.workspace = true
|
||||||
|
|
|
@ -254,7 +254,7 @@ pub fn create_runtime_snapshot(
|
||||||
deno_http::deno_http::init_ops_and_esm::<DefaultHttpPropertyExtractor>(),
|
deno_http::deno_http::init_ops_and_esm::<DefaultHttpPropertyExtractor>(),
|
||||||
deno_io::deno_io::init_ops_and_esm(Default::default()),
|
deno_io::deno_io::init_ops_and_esm(Default::default()),
|
||||||
deno_fs::deno_fs::init_ops_and_esm::<Permissions>(fs.clone()),
|
deno_fs::deno_fs::init_ops_and_esm::<Permissions>(fs.clone()),
|
||||||
deno_node::deno_node::init_ops_and_esm::<Permissions>(None, None, fs),
|
deno_node::deno_node::init_ops_and_esm::<Permissions>(None, fs),
|
||||||
runtime::init_ops_and_esm(),
|
runtime::init_ops_and_esm(),
|
||||||
ops::runtime::deno_runtime::init_ops("deno:runtime".parse().unwrap()),
|
ops::runtime::deno_runtime::init_ops("deno:runtime".parse().unwrap()),
|
||||||
ops::worker_host::deno_worker_host::init_ops(
|
ops::worker_host::deno_worker_host::init_ops(
|
||||||
|
|
|
@ -43,7 +43,7 @@ use deno_fs::FileSystem;
|
||||||
use deno_http::DefaultHttpPropertyExtractor;
|
use deno_http::DefaultHttpPropertyExtractor;
|
||||||
use deno_io::Stdio;
|
use deno_io::Stdio;
|
||||||
use deno_kv::dynamic::MultiBackendDbHandler;
|
use deno_kv::dynamic::MultiBackendDbHandler;
|
||||||
use deno_node::NodeResolver;
|
use deno_node::NodeExtInitServices;
|
||||||
use deno_permissions::PermissionsContainer;
|
use deno_permissions::PermissionsContainer;
|
||||||
use deno_terminal::colors;
|
use deno_terminal::colors;
|
||||||
use deno_tls::RootCertStoreProvider;
|
use deno_tls::RootCertStoreProvider;
|
||||||
|
@ -364,8 +364,7 @@ pub struct WebWorkerOptions {
|
||||||
pub seed: Option<u64>,
|
pub seed: Option<u64>,
|
||||||
pub fs: Arc<dyn FileSystem>,
|
pub fs: Arc<dyn FileSystem>,
|
||||||
pub module_loader: Rc<dyn ModuleLoader>,
|
pub module_loader: Rc<dyn ModuleLoader>,
|
||||||
pub node_resolver: Option<Arc<NodeResolver>>,
|
pub node_services: Option<NodeExtInitServices>,
|
||||||
pub npm_resolver: Option<Arc<dyn deno_node::NpmResolver>>,
|
|
||||||
pub create_web_worker_cb: Arc<ops::worker_host::CreateWebWorkerCb>,
|
pub create_web_worker_cb: Arc<ops::worker_host::CreateWebWorkerCb>,
|
||||||
pub format_js_error_fn: Option<Arc<FormatJsErrorFn>>,
|
pub format_js_error_fn: Option<Arc<FormatJsErrorFn>>,
|
||||||
pub worker_type: WebWorkerType,
|
pub worker_type: WebWorkerType,
|
||||||
|
@ -490,8 +489,7 @@ impl WebWorker {
|
||||||
options.fs.clone(),
|
options.fs.clone(),
|
||||||
),
|
),
|
||||||
deno_node::deno_node::init_ops_and_esm::<PermissionsContainer>(
|
deno_node::deno_node::init_ops_and_esm::<PermissionsContainer>(
|
||||||
options.node_resolver,
|
options.node_services,
|
||||||
options.npm_resolver,
|
|
||||||
options.fs,
|
options.fs,
|
||||||
),
|
),
|
||||||
// Runtime ops that are always initialized for WebWorkers
|
// Runtime ops that are always initialized for WebWorkers
|
||||||
|
|
|
@ -38,6 +38,7 @@ use deno_fs::FileSystem;
|
||||||
use deno_http::DefaultHttpPropertyExtractor;
|
use deno_http::DefaultHttpPropertyExtractor;
|
||||||
use deno_io::Stdio;
|
use deno_io::Stdio;
|
||||||
use deno_kv::dynamic::MultiBackendDbHandler;
|
use deno_kv::dynamic::MultiBackendDbHandler;
|
||||||
|
use deno_node::NodeExtInitServices;
|
||||||
use deno_permissions::PermissionsContainer;
|
use deno_permissions::PermissionsContainer;
|
||||||
use deno_tls::RootCertStoreProvider;
|
use deno_tls::RootCertStoreProvider;
|
||||||
use deno_tls::TlsKeys;
|
use deno_tls::TlsKeys;
|
||||||
|
@ -155,8 +156,7 @@ pub struct WorkerOptions {
|
||||||
/// If not provided runtime will error if code being
|
/// If not provided runtime will error if code being
|
||||||
/// executed tries to load modules.
|
/// executed tries to load modules.
|
||||||
pub module_loader: Rc<dyn ModuleLoader>,
|
pub module_loader: Rc<dyn ModuleLoader>,
|
||||||
pub node_resolver: Option<Arc<deno_node::NodeResolver>>,
|
pub node_services: Option<NodeExtInitServices>,
|
||||||
pub npm_resolver: Option<Arc<dyn deno_node::NpmResolver>>,
|
|
||||||
// Callbacks invoked when creating new instance of WebWorker
|
// Callbacks invoked when creating new instance of WebWorker
|
||||||
pub create_web_worker_cb: Arc<ops::worker_host::CreateWebWorkerCb>,
|
pub create_web_worker_cb: Arc<ops::worker_host::CreateWebWorkerCb>,
|
||||||
pub format_js_error_fn: Option<Arc<FormatJsErrorFn>>,
|
pub format_js_error_fn: Option<Arc<FormatJsErrorFn>>,
|
||||||
|
@ -224,8 +224,7 @@ impl Default for WorkerOptions {
|
||||||
cache_storage_dir: Default::default(),
|
cache_storage_dir: Default::default(),
|
||||||
broadcast_channel: Default::default(),
|
broadcast_channel: Default::default(),
|
||||||
root_cert_store_provider: Default::default(),
|
root_cert_store_provider: Default::default(),
|
||||||
node_resolver: Default::default(),
|
node_services: Default::default(),
|
||||||
npm_resolver: Default::default(),
|
|
||||||
blob_store: Default::default(),
|
blob_store: Default::default(),
|
||||||
extensions: Default::default(),
|
extensions: Default::default(),
|
||||||
startup_snapshot: Default::default(),
|
startup_snapshot: Default::default(),
|
||||||
|
@ -414,8 +413,7 @@ impl MainWorker {
|
||||||
options.fs.clone(),
|
options.fs.clone(),
|
||||||
),
|
),
|
||||||
deno_node::deno_node::init_ops_and_esm::<PermissionsContainer>(
|
deno_node::deno_node::init_ops_and_esm::<PermissionsContainer>(
|
||||||
options.node_resolver,
|
options.node_services,
|
||||||
options.npm_resolver,
|
|
||||||
options.fs,
|
options.fs,
|
||||||
),
|
),
|
||||||
// Ops from this crate
|
// Ops from this crate
|
||||||
|
|
Loading…
Reference in a new issue