1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-23 15:49:44 -05:00

refactor(node): move most of cli/node to ext/node (#18797)

This is just a straight refactor and I didn't do any cleanup in
ext/node. After this PR we can start to clean it up and make things
private that don't need to be public anymore.
This commit is contained in:
David Sherret 2023-04-21 21:02:46 -04:00 committed by GitHub
parent 779d379c68
commit a615eb3b56
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 387 additions and 299 deletions

3
Cargo.lock generated
View file

@ -1132,6 +1132,9 @@ dependencies = [
"cbc",
"data-encoding",
"deno_core",
"deno_media_type",
"deno_npm",
"deno_semver",
"digest 0.10.6",
"dsa",
"ecb",

View file

@ -52,6 +52,9 @@ napi_sym = { version = "0.29.0", path = "./cli/napi/sym" }
deno_bench_util = { version = "0.93.0", path = "./bench_util" }
test_util = { path = "./test_util" }
deno_lockfile = "0.13.0"
deno_media_type = { version = "0.1.0", features = ["module_specifier"] }
deno_npm = "0.3.0"
deno_semver = "0.2.1"
# exts
deno_broadcast_channel = { version = "0.93.0", path = "./ext/broadcast_channel" }

View file

@ -47,9 +47,9 @@ deno_emit = "0.20.0"
deno_graph = "=0.48.0"
deno_lint = { version = "0.44.0", features = ["docs"] }
deno_lockfile.workspace = true
deno_npm = "0.3.0"
deno_npm.workspace = true
deno_runtime = { workspace = true, features = ["dont_create_runtime_snapshot", "include_js_files_for_snapshotting"] }
deno_semver = "0.2.1"
deno_semver.workspace = true
deno_task_shell = "0.11.0"
napi_sym.workspace = true

View file

@ -9,7 +9,7 @@ use crate::cache::ParsedSourceCache;
use crate::colors;
use crate::errors::get_error_class_name;
use crate::file_fetcher::FileFetcher;
use crate::npm::NpmPackageResolver;
use crate::npm::CliNpmResolver;
use crate::resolver::CliGraphResolver;
use crate::tools::check;
use crate::tools::check::TypeChecker;
@ -29,6 +29,7 @@ use deno_graph::ModuleGraph;
use deno_graph::ModuleGraphError;
use deno_graph::ResolutionError;
use deno_graph::SpecifierError;
use deno_runtime::deno_node;
use deno_runtime::permissions::PermissionsContainer;
use import_map::ImportMapError;
use std::collections::HashMap;
@ -165,7 +166,7 @@ pub fn graph_lock_or_exit(graph: &ModuleGraph, lockfile: &mut Lockfile) {
pub struct ModuleGraphBuilder {
options: Arc<CliOptions>,
resolver: Arc<CliGraphResolver>,
npm_resolver: Arc<NpmPackageResolver>,
npm_resolver: Arc<CliNpmResolver>,
parsed_source_cache: Arc<ParsedSourceCache>,
lockfile: Option<Arc<Mutex<Lockfile>>>,
emit_cache: cache::EmitCache,
@ -178,7 +179,7 @@ impl ModuleGraphBuilder {
pub fn new(
options: Arc<CliOptions>,
resolver: Arc<CliGraphResolver>,
npm_resolver: Arc<NpmPackageResolver>,
npm_resolver: Arc<CliNpmResolver>,
parsed_source_cache: Arc<ParsedSourceCache>,
lockfile: Option<Arc<Mutex<Lockfile>>>,
emit_cache: cache::EmitCache,
@ -377,7 +378,7 @@ pub fn get_resolution_error_bare_node_specifier(
error: &ResolutionError,
) -> Option<&str> {
get_resolution_error_bare_specifier(error).filter(|specifier| {
crate::node::resolve_builtin_node_module(specifier).is_ok()
deno_node::resolve_builtin_node_module(specifier).is_ok()
})
}

View file

@ -16,7 +16,6 @@ use super::tsc::TsServer;
use crate::args::LintOptions;
use crate::graph_util;
use crate::graph_util::enhanced_resolution_error_message;
use crate::node;
use crate::tools::lint::get_configured_rules;
use deno_ast::MediaType;
@ -31,6 +30,7 @@ use deno_graph::Resolution;
use deno_graph::ResolutionError;
use deno_graph::SpecifierError;
use deno_lint::rules::LintRule;
use deno_runtime::deno_node;
use deno_runtime::tokio_util::create_basic_runtime;
use deno_semver::npm::NpmPackageReqReference;
use log::error;
@ -469,8 +469,8 @@ async fn generate_lint_diagnostics(
}
// ignore any npm package files
if let Some(npm_resolver) = &snapshot.maybe_npm_resolver {
if npm_resolver.in_npm_package(document.specifier()) {
if let Some(node_resolver) = &snapshot.maybe_node_resolver {
if node_resolver.in_npm_package(document.specifier()) {
continue;
}
}
@ -926,7 +926,7 @@ fn diagnose_resolution(
}
} else if let Some(module_name) = specifier.as_str().strip_prefix("node:")
{
if node::resolve_builtin_node_module(module_name).is_err() {
if deno_node::resolve_builtin_node_module(module_name).is_err() {
diagnostics.push(
DenoDiagnostic::InvalidNodeSpecifier(specifier.clone())
.to_lsp_diagnostic(&range),

View file

@ -18,7 +18,6 @@ use crate::file_fetcher::map_content_type;
use crate::file_fetcher::SUPPORTED_SCHEMES;
use crate::lsp::logging::lsp_warn;
use crate::node::CliNodeResolver;
use crate::node::NodeResolution;
use crate::npm::CliNpmRegistryApi;
use crate::npm::NpmResolution;
use crate::npm::PackageJsonDepsInstaller;
@ -37,8 +36,11 @@ use deno_core::url;
use deno_core::ModuleSpecifier;
use deno_graph::GraphImport;
use deno_graph::Resolution;
use deno_runtime::deno_node;
use deno_runtime::deno_node::NodeResolution;
use deno_runtime::deno_node::NodeResolutionMode;
use deno_runtime::deno_node::PackageJson;
use deno_runtime::deno_node::RealFs;
use deno_runtime::permissions::PermissionsContainer;
use deno_semver::npm::NpmPackageReq;
use deno_semver::npm::NpmPackageReqReference;
@ -1069,7 +1071,7 @@ impl Documents {
// we're in an npm package, so use node resolution
results.push(Some(NodeResolution::into_specifier_and_media_type(
node_resolver
.resolve(
.resolve::<RealFs>(
&specifier,
referrer,
NodeResolutionMode::Types,
@ -1082,7 +1084,7 @@ impl Documents {
}
}
if let Some(module_name) = specifier.strip_prefix("node:") {
if crate::node::resolve_builtin_node_module(module_name).is_ok() {
if deno_node::resolve_builtin_node_module(module_name).is_ok() {
// return itself for node: specifiers because during type checking
// we resolve to the ambient modules in the @types/node package
// rather than deno_std/node
@ -1457,7 +1459,7 @@ fn node_resolve_npm_req_ref(
maybe_node_resolver.map(|node_resolver| {
NodeResolution::into_specifier_and_media_type(
node_resolver
.resolve_npm_req_reference(
.resolve_npm_req_reference::<RealFs>(
&npm_req_ref,
NodeResolutionMode::Types,
&mut PermissionsContainer::allow_all(),

View file

@ -9,6 +9,7 @@ use deno_core::serde_json;
use deno_core::serde_json::json;
use deno_core::serde_json::Value;
use deno_core::ModuleSpecifier;
use deno_runtime::deno_node::NodeResolver;
use deno_runtime::deno_node::PackageJson;
use deno_runtime::deno_web::BlobStore;
use import_map::ImportMap;
@ -81,8 +82,8 @@ use crate::lsp::urls::LspUrlKind;
use crate::node::CliNodeResolver;
use crate::npm::create_npm_fs_resolver;
use crate::npm::CliNpmRegistryApi;
use crate::npm::CliNpmResolver;
use crate::npm::NpmCache;
use crate::npm::NpmPackageResolver;
use crate::npm::NpmResolution;
use crate::proc_state::ProcState;
use crate::tools::fmt::format_file;
@ -103,7 +104,7 @@ pub struct StateSnapshot {
pub documents: Documents,
pub maybe_import_map: Option<Arc<ImportMap>>,
pub maybe_node_resolver: Option<Arc<CliNodeResolver>>,
pub maybe_npm_resolver: Option<Arc<NpmPackageResolver>>,
pub maybe_npm_resolver: Option<Arc<CliNpmResolver>>,
}
#[derive(Debug)]
@ -153,7 +154,7 @@ pub struct Inner {
/// Npm resolution that is stored in memory.
npm_resolution: Arc<NpmResolution>,
/// Resolver for npm packages.
npm_resolver: Arc<NpmPackageResolver>,
npm_resolver: Arc<CliNpmResolver>,
/// A collection of measurements which instrument that performance of the LSP.
performance: Arc<Performance>,
/// A memoized version of fixable diagnostic codes retrieved from TypeScript.
@ -424,7 +425,7 @@ fn create_lsp_structs(
) -> (
Arc<CliNpmRegistryApi>,
Arc<NpmCache>,
Arc<NpmPackageResolver>,
Arc<CliNpmResolver>,
Arc<NpmResolution>,
) {
let registry_url = CliNpmRegistryApi::default_url();
@ -457,11 +458,7 @@ fn create_lsp_structs(
(
api,
npm_cache,
Arc::new(NpmPackageResolver::new(
resolution.clone(),
fs_resolver,
None,
)),
Arc::new(CliNpmResolver::new(resolution.clone(), fs_resolver, None)),
resolution,
)
}
@ -703,19 +700,18 @@ impl Inner {
self.npm_resolution.snapshot(),
None,
));
let npm_resolver = Arc::new(NpmPackageResolver::new(
let npm_resolver = Arc::new(CliNpmResolver::new(
npm_resolution.clone(),
create_npm_fs_resolver(
self.npm_cache.clone(),
&ProgressBar::new(ProgressBarStyle::TextOnly),
self.npm_api.base_url().clone(),
npm_resolution.clone(),
npm_resolution,
None,
),
None,
));
let node_resolver =
Arc::new(CliNodeResolver::new(npm_resolution, npm_resolver.clone()));
let node_resolver = Arc::new(NodeResolver::new(npm_resolver.clone()));
Arc::new(StateSnapshot {
assets: self.assets.snapshot(),
cache_metadata: self.cache_metadata.clone(),

View file

@ -11,10 +11,8 @@ use crate::graph_util::graph_valid_with_cli_options;
use crate::graph_util::ModuleGraphBuilder;
use crate::graph_util::ModuleGraphContainer;
use crate::node;
use crate::node::CliCjsEsmCodeAnalyzer;
use crate::node::CliNodeCodeTranslator;
use crate::node::CliNodeResolver;
use crate::node::NodeResolution;
use crate::npm::CliRequireNpmResolver;
use crate::proc_state::CjsResolutionStore;
use crate::proc_state::FileWatcherReporter;
use crate::proc_state::ProcState;
@ -50,7 +48,8 @@ use deno_graph::JsonModule;
use deno_graph::Module;
use deno_graph::Resolution;
use deno_lockfile::Lockfile;
use deno_runtime::deno_node::analyze::NodeCodeTranslator;
use deno_runtime::deno_node;
use deno_runtime::deno_node::NodeResolution;
use deno_runtime::deno_node::NodeResolutionMode;
use deno_runtime::deno_node::RealFs;
use deno_runtime::permissions::PermissionsContainer;
@ -244,8 +243,7 @@ pub struct CliModuleLoader {
emitter: Arc<Emitter>,
graph_container: Arc<ModuleGraphContainer>,
module_load_preparer: Arc<ModuleLoadPreparer>,
node_code_translator:
Arc<NodeCodeTranslator<CliCjsEsmCodeAnalyzer, CliRequireNpmResolver>>,
node_code_translator: Arc<CliNodeCodeTranslator>,
node_resolver: Arc<CliNodeResolver>,
parsed_source_cache: Arc<ParsedSourceCache>,
resolver: Arc<CliGraphResolver>,
@ -430,7 +428,7 @@ impl CliModuleLoader {
fn handle_node_resolve_result(
&self,
result: Result<Option<node::NodeResolution>, AnyError>,
result: Result<Option<NodeResolution>, AnyError>,
) -> Result<ModuleSpecifier, AnyError> {
let response = match result? {
Some(response) => response,
@ -440,7 +438,7 @@ impl CliModuleLoader {
// remember that this was a common js resolution
self.cjs_resolutions.insert(specifier.clone());
} else if let NodeResolution::BuiltIn(specifier) = &response {
return node::resolve_builtin_node_module(specifier);
return deno_node::resolve_builtin_node_module(specifier);
}
Ok(response.into_url())
}
@ -468,7 +466,7 @@ impl ModuleLoader for CliModuleLoader {
if self.node_resolver.in_npm_package(referrer) {
// we're in an npm package, so use node resolution
return self
.handle_node_resolve_result(self.node_resolver.resolve(
.handle_node_resolve_result(self.node_resolver.resolve::<RealFs>(
specifier,
referrer,
NodeResolutionMode::Execution,
@ -494,7 +492,7 @@ impl ModuleLoader for CliModuleLoader {
return match graph.get(specifier) {
Some(Module::Npm(module)) => self
.handle_node_resolve_result(
self.node_resolver.resolve_npm_reference(
self.node_resolver.resolve_npm_reference::<RealFs>(
&module.nv_reference,
NodeResolutionMode::Execution,
&mut permissions,
@ -504,7 +502,7 @@ impl ModuleLoader for CliModuleLoader {
format!("Could not resolve '{}'.", module.nv_reference)
}),
Some(Module::Node(module)) => {
node::resolve_builtin_node_module(&module.module_name)
deno_node::resolve_builtin_node_module(&module.module_name)
}
Some(Module::Esm(module)) => Ok(module.specifier.clone()),
Some(Module::Json(module)) => Ok(module.specifier.clone()),
@ -526,7 +524,7 @@ impl ModuleLoader for CliModuleLoader {
// Built-in Node modules
if let Some(module_name) = specifier.strip_prefix("node:") {
return node::resolve_builtin_node_module(module_name);
return deno_node::resolve_builtin_node_module(module_name);
}
// FIXME(bartlomieju): this is a hacky way to provide compatibility with REPL
@ -556,9 +554,9 @@ impl ModuleLoader for CliModuleLoader {
{
return self
.handle_node_resolve_result(
self.node_resolver.resolve_npm_req_reference(
self.node_resolver.resolve_npm_req_reference::<RealFs>(
&reference,
deno_runtime::deno_node::NodeResolutionMode::Execution,
NodeResolutionMode::Execution,
&mut permissions,
),
)

View file

@ -1,6 +1,7 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use std::collections::HashSet;
use std::sync::Arc;
use deno_ast::swc::common::SyntaxContext;
use deno_ast::view::Node;
@ -13,8 +14,35 @@ use deno_ast::SourceRanged;
use deno_core::error::AnyError;
use deno_runtime::deno_node::analyze::CjsAnalysis as ExtNodeCjsAnalysis;
use deno_runtime::deno_node::analyze::CjsEsmCodeAnalyzer;
use deno_runtime::deno_node::analyze::NodeCodeTranslator;
use deno_runtime::deno_node::NodeResolver;
use crate::cache::NodeAnalysisCache;
use crate::npm::CliNpmResolver;
use crate::util::fs::canonicalize_path_maybe_not_exists;
pub type CliNodeCodeTranslator =
NodeCodeTranslator<CliCjsEsmCodeAnalyzer, Arc<CliNpmResolver>>;
pub type CliNodeResolver = NodeResolver<Arc<CliNpmResolver>>;
/// Resolves a specifier that is pointing into a node_modules folder.
///
/// Note: This should be called whenever getting the specifier from
/// a Module::External(module) reference because that module might
/// not be fully resolved at the time deno_graph is analyzing it
/// because the node_modules folder might not exist at that time.
pub fn resolve_specifier_into_node_modules(
specifier: &ModuleSpecifier,
) -> ModuleSpecifier {
specifier
.to_file_path()
.ok()
// this path might not exist at the time the graph is being created
// because the node_modules folder might not yet exist
.and_then(|path| canonicalize_path_maybe_not_exists(&path).ok())
.and_then(|path| ModuleSpecifier::from_file_path(path).ok())
.unwrap_or_else(|| specifier.clone())
}
pub struct CliCjsEsmCodeAnalyzer {
cache: NodeAnalysisCache,

View file

@ -13,6 +13,5 @@ pub use installer::PackageJsonDepsInstaller;
pub use registry::CliNpmRegistryApi;
pub use resolution::NpmResolution;
pub use resolvers::create_npm_fs_resolver;
pub use resolvers::CliRequireNpmResolver;
pub use resolvers::NpmPackageResolver;
pub use resolvers::CliNpmResolver;
pub use resolvers::NpmProcessState;

View file

@ -154,7 +154,7 @@ impl NpmResolution {
Ok(())
}
pub fn pkg_req_ref_to_nv_ref(
pub fn resolve_nv_ref_from_pkg_req_ref(
&self,
req_ref: &NpmPackageReqReference,
) -> Result<NpmPackageNvReference, PackageReqNotFoundError> {

View file

@ -20,10 +20,12 @@ use deno_npm::resolution::SerializedNpmResolutionSnapshot;
use deno_npm::NpmPackageId;
use deno_runtime::deno_node::NodePermissions;
use deno_runtime::deno_node::NodeResolutionMode;
use deno_runtime::deno_node::NpmResolver;
use deno_runtime::deno_node::PathClean;
use deno_runtime::deno_node::RequireNpmResolver;
use deno_semver::npm::NpmPackageNv;
use deno_semver::npm::NpmPackageNvReference;
use deno_semver::npm::NpmPackageReq;
use deno_semver::npm::NpmPackageReqReference;
use global::GlobalNpmPackageResolver;
use serde::Deserialize;
use serde::Serialize;
@ -45,13 +47,13 @@ pub struct NpmProcessState {
}
/// Brings together the npm resolution with the file system.
pub struct NpmPackageResolver {
pub struct CliNpmResolver {
fs_resolver: Arc<dyn NpmPackageFsResolver>,
resolution: Arc<NpmResolution>,
maybe_lockfile: Option<Arc<Mutex<Lockfile>>>,
}
impl std::fmt::Debug for NpmPackageResolver {
impl std::fmt::Debug for CliNpmResolver {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("NpmPackageResolver")
.field("fs_resolver", &"<omitted>")
@ -61,7 +63,7 @@ impl std::fmt::Debug for NpmPackageResolver {
}
}
impl NpmPackageResolver {
impl CliNpmResolver {
pub fn new(
resolution: Arc<NpmResolution>,
fs_resolver: Arc<dyn NpmPackageFsResolver>,
@ -85,15 +87,6 @@ impl NpmPackageResolver {
self.resolution.resolve_pkg_id_from_pkg_req(req)
}
/// Resolves an npm package folder path from a Deno module.
pub fn resolve_package_folder_from_deno_module(
&self,
pkg_nv: &NpmPackageNv,
) -> Result<PathBuf, AnyError> {
let pkg_id = self.resolution.resolve_pkg_id_from_deno_module(pkg_nv)?;
self.resolve_pkg_folder_from_deno_module_at_pkg_id(&pkg_id)
}
fn resolve_pkg_folder_from_deno_module_at_pkg_id(
&self,
pkg_id: &NpmPackageId,
@ -108,20 +101,6 @@ impl NpmPackageResolver {
Ok(path)
}
/// Resolves an npm package folder path from an npm package referrer.
pub fn resolve_package_folder_from_package(
&self,
name: &str,
referrer: &ModuleSpecifier,
mode: NodeResolutionMode,
) -> Result<PathBuf, AnyError> {
let path = self
.fs_resolver
.resolve_package_folder_from_package(name, referrer, mode)?;
log::debug!("Resolved {} from {} to {}", name, referrer, path.display());
Ok(path)
}
/// Resolve the root folder of the package the provided specifier is in.
///
/// This will error when the provided specifier is not in an npm package.
@ -228,26 +207,20 @@ impl NpmPackageResolver {
self.fs_resolver.cache_packages().await?;
Ok(())
}
pub fn as_require_npm_resolver(self: &Arc<Self>) -> CliRequireNpmResolver {
CliRequireNpmResolver(self.clone())
}
}
#[derive(Debug)]
pub struct CliRequireNpmResolver(Arc<NpmPackageResolver>);
impl RequireNpmResolver for CliRequireNpmResolver {
impl NpmResolver for CliNpmResolver {
fn resolve_package_folder_from_package(
&self,
specifier: &str,
referrer: &std::path::Path,
name: &str,
referrer: &ModuleSpecifier,
mode: NodeResolutionMode,
) -> Result<PathBuf, AnyError> {
let referrer = path_to_specifier(referrer)?;
self
.0
.resolve_package_folder_from_package(specifier, &referrer, mode)
let path = self
.fs_resolver
.resolve_package_folder_from_package(name, referrer, mode)?;
log::debug!("Resolved {} from {} to {}", name, referrer, path.display());
Ok(path)
}
fn resolve_package_folder_from_path(
@ -255,18 +228,34 @@ impl RequireNpmResolver for CliRequireNpmResolver {
path: &Path,
) -> Result<PathBuf, AnyError> {
let specifier = path_to_specifier(path)?;
self.0.resolve_package_folder_from_specifier(&specifier)
self.resolve_package_folder_from_specifier(&specifier)
}
fn in_npm_package(&self, path: &Path) -> bool {
let specifier =
match ModuleSpecifier::from_file_path(path.to_path_buf().clean()) {
Ok(p) => p,
Err(_) => return false,
};
fn resolve_package_folder_from_deno_module(
&self,
pkg_nv: &NpmPackageNv,
) -> Result<PathBuf, AnyError> {
let pkg_id = self.resolution.resolve_pkg_id_from_deno_module(pkg_nv)?;
self.resolve_pkg_folder_from_deno_module_at_pkg_id(&pkg_id)
}
fn resolve_pkg_id_from_pkg_req(
&self,
req: &NpmPackageReq,
) -> Result<NpmPackageId, PackageReqNotFoundError> {
self.resolution.resolve_pkg_id_from_pkg_req(req)
}
fn resolve_nv_ref_from_pkg_req_ref(
&self,
req_ref: &NpmPackageReqReference,
) -> Result<NpmPackageNvReference, PackageReqNotFoundError> {
self.resolution.resolve_nv_ref_from_pkg_req_ref(req_ref)
}
fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool {
self
.0
.resolve_package_folder_from_specifier(&specifier)
.resolve_package_folder_from_specifier(specifier)
.is_ok()
}
@ -275,7 +264,7 @@ impl RequireNpmResolver for CliRequireNpmResolver {
permissions: &mut dyn NodePermissions,
path: &Path,
) -> Result<(), AnyError> {
self.0.fs_resolver.ensure_read_permission(permissions, path)
self.fs_resolver.ensure_read_permission(permissions, path)
}
}

View file

@ -2,7 +2,7 @@
use std::sync::Arc;
use crate::npm::NpmPackageResolver;
use crate::npm::CliNpmResolver;
use deno_core::error::AnyError;
use deno_core::op;
use deno_core::Extension;
@ -11,14 +11,14 @@ use deno_core::OpState;
pub mod bench;
pub mod testing;
pub fn cli_exts(npm_resolver: Arc<NpmPackageResolver>) -> Vec<Extension> {
pub fn cli_exts(npm_resolver: Arc<CliNpmResolver>) -> Vec<Extension> {
vec![deno_cli::init_ops(npm_resolver)]
}
deno_core::extension!(deno_cli,
ops = [op_npm_process_state],
options = {
npm_resolver: Arc<NpmPackageResolver>,
npm_resolver: Arc<CliNpmResolver>,
},
state = |state, options| {
state.put(options.npm_resolver);
@ -30,6 +30,6 @@ deno_core::extension!(deno_cli,
#[op]
fn op_npm_process_state(state: &mut OpState) -> Result<String, AnyError> {
let npm_resolver = state.borrow_mut::<Arc<NpmPackageResolver>>();
let npm_resolver = state.borrow_mut::<Arc<CliNpmResolver>>();
Ok(npm_resolver.get_npm_process_state())
}

View file

@ -18,12 +18,12 @@ use crate::graph_util::ModuleGraphContainer;
use crate::http_util::HttpClient;
use crate::module_loader::ModuleLoadPreparer;
use crate::node::CliCjsEsmCodeAnalyzer;
use crate::node::CliNodeCodeTranslator;
use crate::node::CliNodeResolver;
use crate::npm::create_npm_fs_resolver;
use crate::npm::CliNpmRegistryApi;
use crate::npm::CliRequireNpmResolver;
use crate::npm::CliNpmResolver;
use crate::npm::NpmCache;
use crate::npm::NpmPackageResolver;
use crate::npm::NpmResolution;
use crate::npm::PackageJsonDepsInstaller;
use crate::resolver::CliGraphResolver;
@ -39,6 +39,7 @@ use deno_core::SharedArrayBufferStore;
use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel;
use deno_runtime::deno_node::analyze::NodeCodeTranslator;
use deno_runtime::deno_node::NodeResolver;
use deno_runtime::deno_tls::rustls::RootCertStore;
use deno_runtime::deno_web::BlobStore;
use deno_runtime::inspector_server::InspectorServer;
@ -77,12 +78,11 @@ pub struct Inner {
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
pub module_graph_builder: Arc<ModuleGraphBuilder>,
pub module_load_preparer: Arc<ModuleLoadPreparer>,
pub node_code_translator:
Arc<NodeCodeTranslator<CliCjsEsmCodeAnalyzer, CliRequireNpmResolver>>,
pub node_code_translator: Arc<CliNodeCodeTranslator>,
pub node_resolver: Arc<CliNodeResolver>,
pub npm_api: Arc<CliNpmRegistryApi>,
pub npm_cache: Arc<NpmCache>,
pub npm_resolver: Arc<NpmPackageResolver>,
pub npm_resolver: Arc<CliNpmResolver>,
pub npm_resolution: Arc<NpmResolution>,
pub package_json_deps_installer: Arc<PackageJsonDepsInstaller>,
pub cjs_resolutions: Arc<CjsResolutionStore>,
@ -252,7 +252,7 @@ impl ProcState {
npm_resolution.clone(),
cli_options.node_modules_dir_path(),
);
let npm_resolver = Arc::new(NpmPackageResolver::new(
let npm_resolver = Arc::new(CliNpmResolver::new(
npm_resolution.clone(),
npm_fs_resolver,
lockfile.as_ref().cloned(),
@ -310,12 +310,9 @@ impl ProcState {
let cjs_esm_analyzer = CliCjsEsmCodeAnalyzer::new(node_analysis_cache);
let node_code_translator = Arc::new(NodeCodeTranslator::new(
cjs_esm_analyzer,
npm_resolver.as_require_npm_resolver(),
));
let node_resolver = Arc::new(CliNodeResolver::new(
npm_resolution.clone(),
npm_resolver.clone(),
));
let node_resolver = Arc::new(NodeResolver::new(npm_resolver.clone()));
let type_checker = Arc::new(TypeChecker::new(
dir.clone(),
caches.clone(),

View file

@ -22,7 +22,7 @@ use crate::cache::DenoDir;
use crate::cache::FastInsecureHasher;
use crate::cache::TypeCheckCache;
use crate::node::CliNodeResolver;
use crate::npm::NpmPackageResolver;
use crate::npm::CliNpmResolver;
use crate::tsc;
use crate::version;
@ -43,7 +43,7 @@ pub struct TypeChecker {
caches: Arc<Caches>,
cli_options: Arc<CliOptions>,
node_resolver: Arc<CliNodeResolver>,
npm_resolver: Arc<NpmPackageResolver>,
npm_resolver: Arc<CliNpmResolver>,
}
impl TypeChecker {
@ -52,7 +52,7 @@ impl TypeChecker {
caches: Arc<Caches>,
cli_options: Arc<CliOptions>,
node_resolver: Arc<CliNodeResolver>,
npm_resolver: Arc<NpmPackageResolver>,
npm_resolver: Arc<CliNpmResolver>,
) -> Self {
Self {
deno_dir,

View file

@ -28,7 +28,7 @@ use crate::args::Flags;
use crate::args::InfoFlags;
use crate::display;
use crate::graph_util::graph_lock_or_exit;
use crate::npm::NpmPackageResolver;
use crate::npm::CliNpmResolver;
use crate::proc_state::ProcState;
use crate::util::checksum;
@ -141,7 +141,7 @@ fn print_cache_info(
fn add_npm_packages_to_json(
json: &mut serde_json::Value,
npm_resolver: &NpmPackageResolver,
npm_resolver: &CliNpmResolver,
) {
// ideally deno_graph could handle this, but for now we just modify the json here
let snapshot = npm_resolver.snapshot();
@ -318,7 +318,7 @@ struct NpmInfo {
impl NpmInfo {
pub fn build<'a>(
graph: &'a ModuleGraph,
npm_resolver: &'a NpmPackageResolver,
npm_resolver: &'a CliNpmResolver,
npm_snapshot: &'a NpmResolutionSnapshot,
) -> Self {
let mut info = NpmInfo::default();
@ -344,7 +344,7 @@ impl NpmInfo {
fn fill_package_info<'a>(
&mut self,
package: &NpmResolutionPackage,
npm_resolver: &'a NpmPackageResolver,
npm_resolver: &'a CliNpmResolver,
npm_snapshot: &'a NpmResolutionSnapshot,
) {
self
@ -380,7 +380,7 @@ struct GraphDisplayContext<'a> {
impl<'a> GraphDisplayContext<'a> {
pub fn write<TWrite: Write>(
graph: &'a ModuleGraph,
npm_resolver: &'a NpmPackageResolver,
npm_resolver: &'a CliNpmResolver,
writer: &mut TWrite,
) -> fmt::Result {
let npm_snapshot = npm_resolver.snapshot();

View file

@ -5,7 +5,7 @@ use crate::args::Flags;
use crate::args::TaskFlags;
use crate::colors;
use crate::node::CliNodeResolver;
use crate::npm::NpmPackageResolver;
use crate::npm::CliNpmResolver;
use crate::proc_state::ProcState;
use crate::util::fs::canonicalize_path;
use deno_core::anyhow::bail;
@ -13,6 +13,7 @@ use deno_core::anyhow::Context;
use deno_core::error::AnyError;
use deno_core::futures;
use deno_core::futures::future::LocalBoxFuture;
use deno_runtime::deno_node::RealFs;
use deno_semver::npm::NpmPackageNv;
use deno_task_shell::ExecuteResult;
use deno_task_shell::ShellCommand;
@ -234,13 +235,14 @@ impl ShellCommand for NpmPackageBinCommand {
}
fn resolve_npm_commands(
npm_resolver: &NpmPackageResolver,
npm_resolver: &CliNpmResolver,
node_resolver: &CliNodeResolver,
) -> Result<HashMap<String, Rc<dyn ShellCommand>>, AnyError> {
let mut result = HashMap::new();
let snapshot = npm_resolver.snapshot();
for id in snapshot.top_level_packages() {
let bin_commands = node_resolver.resolve_binary_commands(&id.nv)?;
let bin_commands =
node_resolver.resolve_binary_commands::<RealFs>(&id.nv)?;
for bin_command in bin_commands {
result.insert(
bin_command.to_string(),

View file

@ -5,7 +5,6 @@ use crate::args::TypeCheckMode;
use crate::cache::FastInsecureHasher;
use crate::node;
use crate::node::CliNodeResolver;
use crate::node::NodeResolution;
use crate::util::checksum;
use crate::util::path::mapped_specifier_for_tsc;
@ -33,7 +32,10 @@ use deno_core::Snapshot;
use deno_graph::Module;
use deno_graph::ModuleGraph;
use deno_graph::ResolutionResolved;
use deno_runtime::deno_node;
use deno_runtime::deno_node::NodeResolution;
use deno_runtime::deno_node::NodeResolutionMode;
use deno_runtime::deno_node::RealFs;
use deno_runtime::permissions::PermissionsContainer;
use deno_semver::npm::NpmPackageReqReference;
use lsp_types::Url;
@ -537,7 +539,7 @@ fn op_resolve(
};
for specifier in args.specifiers {
if let Some(module_name) = specifier.strip_prefix("node:") {
if crate::node::resolve_builtin_node_module(module_name).is_ok() {
if deno_node::resolve_builtin_node_module(module_name).is_ok() {
// return itself for node: specifiers because during type checking
// we resolve to the ambient modules in the @types/node package
// rather than deno_std/node
@ -635,7 +637,7 @@ fn resolve_graph_specifier_types(
}
Some(Module::Npm(module)) => {
if let Some(node_resolver) = &state.maybe_node_resolver {
let maybe_resolution = node_resolver.resolve_npm_reference(
let maybe_resolution = node_resolver.resolve_npm_reference::<RealFs>(
&module.nv_reference,
NodeResolutionMode::Types,
&mut PermissionsContainer::allow_all(),
@ -653,7 +655,9 @@ fn resolve_graph_specifier_types(
let specifier =
node::resolve_specifier_into_node_modules(&module.specifier);
NodeResolution::into_specifier_and_media_type(
node_resolver.url_to_node_resolution(specifier).ok(),
node_resolver
.url_to_node_resolution::<RealFs>(specifier)
.ok(),
)
}))
}
@ -674,7 +678,7 @@ fn resolve_non_graph_specifier_types(
// we're in an npm package, so use node resolution
Ok(Some(NodeResolution::into_specifier_and_media_type(
node_resolver
.resolve(
.resolve::<RealFs>(
specifier,
referrer,
NodeResolutionMode::Types,
@ -688,7 +692,7 @@ fn resolve_non_graph_specifier_types(
// we don't need this special code here.
// This could occur when resolving npm:@types/node when it is
// injected and not part of the graph
let maybe_resolution = node_resolver.resolve_npm_req_reference(
let maybe_resolution = node_resolver.resolve_npm_req_reference::<RealFs>(
&npm_ref,
NodeResolutionMode::Types,
&mut PermissionsContainer::allow_all(),

View file

@ -13,6 +13,8 @@ use deno_core::Extension;
use deno_core::ModuleId;
use deno_runtime::colors;
use deno_runtime::deno_node;
use deno_runtime::deno_node::NodeResolution;
use deno_runtime::deno_node::RealFs;
use deno_runtime::fmt_errors::format_js_error;
use deno_runtime::ops::worker_host::CreateWebWorkerCb;
use deno_runtime::ops::worker_host::WorkerEventCb;
@ -27,7 +29,6 @@ use deno_semver::npm::NpmPackageReqReference;
use crate::args::DenoSubcommand;
use crate::errors;
use crate::module_loader::CliModuleLoader;
use crate::node;
use crate::ops;
use crate::proc_state::ProcState;
use crate::tools;
@ -258,16 +259,16 @@ pub async fn create_custom_worker(
ps.npm_resolver
.add_package_reqs(vec![package_ref.req.clone()])
.await?;
let node_resolution =
ps.node_resolver.resolve_binary_export(&package_ref)?;
let is_main_cjs =
matches!(node_resolution, node::NodeResolution::CommonJs(_));
let node_resolution = ps
.node_resolver
.resolve_binary_export::<RealFs>(&package_ref)?;
let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_));
(node_resolution.into_url(), is_main_cjs)
} else if ps.options.is_npm_main() {
let node_resolution =
ps.node_resolver.url_to_node_resolution(main_module)?;
let is_main_cjs =
matches!(node_resolution, node::NodeResolution::CommonJs(_));
let node_resolution = ps
.node_resolver
.url_to_node_resolution::<RealFs>(main_module)?;
let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_));
(node_resolution.into_url(), is_main_cjs)
} else {
(main_module, false)
@ -344,7 +345,7 @@ pub async fn create_custom_worker(
should_break_on_first_statement: ps.options.inspect_brk().is_some(),
should_wait_for_inspector_session: ps.options.inspect_wait().is_some(),
module_loader,
npm_resolver: Some(Rc::new(ps.npm_resolver.as_require_npm_resolver())),
npm_resolver: Some(Rc::new(ps.npm_resolver.clone())),
get_error_class_fn: Some(&errors::get_error_class_name),
cache_storage_dir,
origin_storage_dir,
@ -467,7 +468,7 @@ fn create_web_worker_callback(
format_js_error_fn: Some(Arc::new(format_js_error)),
source_map_getter: Some(Box::new(module_loader.clone())),
module_loader,
npm_resolver: Some(Rc::new(ps.npm_resolver.as_require_npm_resolver())),
npm_resolver: Some(Rc::new(ps.npm_resolver.clone())),
worker_type: args.worker_type,
maybe_inspector_server,
get_error_class_fn: Some(&errors::get_error_class_name),

View file

@ -18,6 +18,9 @@ aes.workspace = true
cbc.workspace = true
data-encoding = "2.3.3"
deno_core.workspace = true
deno_media_type.workspace = true
deno_npm.workspace = true
deno_semver.workspace = true
digest = { version = "0.10.5", features = ["core-api", "std"] }
dsa = "0.6.1"
ecb.workspace = true

View file

@ -17,9 +17,9 @@ use crate::NodeFs;
use crate::NodeModuleKind;
use crate::NodePermissions;
use crate::NodeResolutionMode;
use crate::NpmResolver;
use crate::PackageJson;
use crate::PathClean;
use crate::RequireNpmResolver;
use crate::NODE_GLOBAL_THIS_NAME;
static NODE_GLOBALS: &[&str] = &[
@ -66,20 +66,18 @@ pub trait CjsEsmCodeAnalyzer {
pub struct NodeCodeTranslator<
TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer,
TRequireNpmResolver: RequireNpmResolver,
TNpmResolver: NpmResolver,
> {
cjs_esm_code_analyzer: TCjsEsmCodeAnalyzer,
npm_resolver: TRequireNpmResolver,
npm_resolver: TNpmResolver,
}
impl<
TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer,
TRequireNpmResolver: RequireNpmResolver,
> NodeCodeTranslator<TCjsEsmCodeAnalyzer, TRequireNpmResolver>
impl<TCjsEsmCodeAnalyzer: CjsEsmCodeAnalyzer, TNpmResolver: NpmResolver>
NodeCodeTranslator<TCjsEsmCodeAnalyzer, TNpmResolver>
{
pub fn new(
cjs_esm_code_analyzer: TCjsEsmCodeAnalyzer,
npm_resolver: TRequireNpmResolver,
npm_resolver: TNpmResolver,
) -> Self {
Self {
cjs_esm_code_analyzer,
@ -242,7 +240,7 @@ impl<
// todo(dsherret): use not_found error on not found here
let module_dir = self.npm_resolver.resolve_package_folder_from_package(
package_specifier.as_str(),
&referrer_path,
referrer,
mode,
)?;

View file

@ -5,12 +5,20 @@ use deno_core::located_script_name;
use deno_core::op;
use deno_core::serde_json;
use deno_core::JsRuntime;
use deno_core::ModuleSpecifier;
use deno_npm::resolution::PackageReqNotFoundError;
use deno_npm::NpmPackageId;
use deno_semver::npm::NpmPackageNv;
use deno_semver::npm::NpmPackageNvReference;
use deno_semver::npm::NpmPackageReq;
use deno_semver::npm::NpmPackageReqReference;
use once_cell::sync::Lazy;
use std::collections::HashSet;
use std::io;
use std::path::Path;
use std::path::PathBuf;
use std::rc::Rc;
use std::sync::Arc;
pub mod analyze;
mod crypto;
@ -21,14 +29,15 @@ mod package_json;
mod path;
mod polyfill;
mod resolution;
mod resolver;
mod v8;
mod winerror;
mod zlib;
pub use package_json::PackageJson;
pub use path::PathClean;
pub use polyfill::find_builtin_node_module;
pub use polyfill::is_builtin_node_module;
pub use polyfill::resolve_builtin_node_module;
pub use polyfill::NodeModulePolyfill;
pub use polyfill::SUPPORTED_BUILTIN_NODE_MODULES;
pub use resolution::get_closest_package_json;
@ -41,6 +50,8 @@ pub use resolution::path_to_declaration_path;
pub use resolution::NodeModuleKind;
pub use resolution::NodeResolutionMode;
pub use resolution::DEFAULT_CONDITIONS;
pub use resolver::NodeResolution;
pub use resolver::NodeResolver;
pub trait NodeEnv {
type P: NodePermissions;
@ -51,6 +62,14 @@ pub trait NodePermissions {
fn check_read(&mut self, path: &Path) -> Result<(), AnyError>;
}
pub(crate) struct AllowAllNodePermissions;
impl NodePermissions for AllowAllNodePermissions {
fn check_read(&mut self, _path: &Path) -> Result<(), AnyError> {
Ok(())
}
}
#[derive(Default, Clone)]
pub struct NodeFsMetadata {
pub is_file: bool,
@ -114,20 +133,47 @@ impl NodeFs for RealFs {
}
}
pub trait RequireNpmResolver {
pub trait NpmResolver {
/// Resolves an npm package folder path from an npm package referrer.
fn resolve_package_folder_from_package(
&self,
specifier: &str,
referrer: &Path,
referrer: &ModuleSpecifier,
mode: NodeResolutionMode,
) -> Result<PathBuf, AnyError>;
/// Resolves the npm package folder path from the specified path.
fn resolve_package_folder_from_path(
&self,
path: &Path,
) -> Result<PathBuf, AnyError>;
fn in_npm_package(&self, path: &Path) -> bool;
/// Resolves an npm package folder path from a Deno module.
fn resolve_package_folder_from_deno_module(
&self,
pkg_nv: &NpmPackageNv,
) -> Result<PathBuf, AnyError>;
fn resolve_pkg_id_from_pkg_req(
&self,
req: &NpmPackageReq,
) -> Result<NpmPackageId, PackageReqNotFoundError>;
fn resolve_nv_ref_from_pkg_req_ref(
&self,
req_ref: &NpmPackageReqReference,
) -> Result<NpmPackageNvReference, PackageReqNotFoundError>;
fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool;
fn in_npm_package_at_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)
}
fn ensure_read_permission(
&self,
@ -136,6 +182,57 @@ pub trait RequireNpmResolver {
) -> Result<(), AnyError>;
}
impl<T: NpmResolver + ?Sized> NpmResolver for Arc<T> {
fn resolve_package_folder_from_package(
&self,
specifier: &str,
referrer: &ModuleSpecifier,
mode: NodeResolutionMode,
) -> Result<PathBuf, AnyError> {
(**self).resolve_package_folder_from_package(specifier, referrer, mode)
}
fn resolve_package_folder_from_path(
&self,
path: &Path,
) -> Result<PathBuf, AnyError> {
(**self).resolve_package_folder_from_path(path)
}
fn resolve_package_folder_from_deno_module(
&self,
pkg_nv: &NpmPackageNv,
) -> Result<PathBuf, AnyError> {
(**self).resolve_package_folder_from_deno_module(pkg_nv)
}
fn resolve_pkg_id_from_pkg_req(
&self,
req: &NpmPackageReq,
) -> Result<NpmPackageId, PackageReqNotFoundError> {
(**self).resolve_pkg_id_from_pkg_req(req)
}
fn resolve_nv_ref_from_pkg_req_ref(
&self,
req_ref: &NpmPackageReqReference,
) -> Result<NpmPackageNvReference, PackageReqNotFoundError> {
(**self).resolve_nv_ref_from_pkg_req_ref(req_ref)
}
fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool {
(**self).in_npm_package(specifier)
}
fn ensure_read_permission(
&self,
permissions: &mut dyn NodePermissions,
path: &Path,
) -> Result<(), AnyError> {
(**self).ensure_read_permission(permissions, path)
}
}
pub static NODE_GLOBAL_THIS_NAME: Lazy<String> = Lazy::new(|| {
let now = std::time::SystemTime::now();
let seconds = now
@ -490,7 +587,7 @@ deno_core::extension!(deno_node,
"zlib.ts",
],
options = {
maybe_npm_resolver: Option<Rc<dyn RequireNpmResolver>>,
maybe_npm_resolver: Option<Rc<dyn NpmResolver>>,
},
state = |state, options| {
if let Some(npm_resolver) = options.maybe_npm_resolver {

View file

@ -7,6 +7,7 @@ use deno_core::normalize_path;
use deno_core::op;
use deno_core::url::Url;
use deno_core::JsRuntimeInspector;
use deno_core::ModuleSpecifier;
use deno_core::OpState;
use std::cell::RefCell;
use std::path::Path;
@ -20,8 +21,8 @@ use super::resolution;
use super::NodeModuleKind;
use super::NodePermissions;
use super::NodeResolutionMode;
use super::NpmResolver;
use super::PackageJson;
use super::RequireNpmResolver;
fn ensure_read_permission<P>(
state: &mut OpState,
@ -31,7 +32,7 @@ where
P: NodePermissions + 'static,
{
let resolver = {
let resolver = state.borrow::<Rc<dyn RequireNpmResolver>>();
let resolver = state.borrow::<Rc<dyn NpmResolver>>();
resolver.clone()
};
let permissions = state.borrow_mut::<P>();
@ -191,11 +192,11 @@ fn op_require_resolve_deno_dir(
request: String,
parent_filename: String,
) -> Option<String> {
let resolver = state.borrow::<Rc<dyn RequireNpmResolver>>();
let resolver = state.borrow::<Rc<dyn NpmResolver>>();
resolver
.resolve_package_folder_from_package(
&request,
&PathBuf::from(parent_filename),
&ModuleSpecifier::from_file_path(parent_filename).unwrap(),
NodeResolutionMode::Execution,
)
.ok()
@ -204,8 +205,8 @@ fn op_require_resolve_deno_dir(
#[op]
fn op_require_is_deno_dir_package(state: &mut OpState, path: String) -> bool {
let resolver = state.borrow::<Rc<dyn RequireNpmResolver>>();
resolver.in_npm_package(&PathBuf::from(path))
let resolver = state.borrow::<Rc<dyn NpmResolver>>();
resolver.in_npm_package_at_path(&PathBuf::from(path))
}
#[op]
@ -375,7 +376,7 @@ where
return Ok(None);
}
let resolver = state.borrow::<Rc<dyn RequireNpmResolver>>().clone();
let resolver = state.borrow::<Rc<dyn NpmResolver>>().clone();
let permissions = state.borrow_mut::<Env::P>();
let pkg = resolution::get_package_scope_config::<Env::Fs>(
&Url::from_file_path(parent_path.unwrap()).unwrap(),
@ -462,10 +463,11 @@ fn op_require_resolve_exports<Env>(
where
Env: NodeEnv + 'static,
{
let resolver = state.borrow::<Rc<dyn RequireNpmResolver>>().clone();
let resolver = state.borrow::<Rc<dyn NpmResolver>>().clone();
let permissions = state.borrow_mut::<Env::P>();
let pkg_path = if resolver.in_npm_package(&PathBuf::from(&modules_path))
let pkg_path = if resolver
.in_npm_package_at_path(&PathBuf::from(&modules_path))
&& !uses_local_node_modules_dir
{
modules_path
@ -515,7 +517,7 @@ where
state,
PathBuf::from(&filename).parent().unwrap(),
)?;
let resolver = state.borrow::<Rc<dyn RequireNpmResolver>>().clone();
let resolver = state.borrow::<Rc<dyn NpmResolver>>().clone();
let permissions = state.borrow_mut::<Env::P>();
resolution::get_closest_package_json::<Env::Fs>(
&Url::from_file_path(filename).unwrap(),
@ -532,7 +534,7 @@ fn op_require_read_package_scope<Env>(
where
Env: NodeEnv + 'static,
{
let resolver = state.borrow::<Rc<dyn RequireNpmResolver>>().clone();
let resolver = state.borrow::<Rc<dyn NpmResolver>>().clone();
let permissions = state.borrow_mut::<Env::P>();
let package_json_path = PathBuf::from(package_json_path);
PackageJson::load::<Env::Fs>(&*resolver, permissions, package_json_path).ok()
@ -549,7 +551,7 @@ where
{
let parent_path = PathBuf::from(&parent_filename);
ensure_read_permission::<Env::P>(state, &parent_path)?;
let resolver = state.borrow::<Rc<dyn RequireNpmResolver>>().clone();
let resolver = state.borrow::<Rc<dyn NpmResolver>>().clone();
let permissions = state.borrow_mut::<Env::P>();
let pkg = PackageJson::load::<Env::Fs>(
&*resolver,

View file

@ -4,7 +4,7 @@ use crate::NodeFs;
use crate::NodeModuleKind;
use crate::NodePermissions;
use super::RequireNpmResolver;
use super::NpmResolver;
use deno_core::anyhow;
use deno_core::anyhow::bail;
@ -63,7 +63,7 @@ impl PackageJson {
}
pub fn load<Fs: NodeFs>(
resolver: &dyn RequireNpmResolver,
resolver: &dyn NpmResolver,
permissions: &mut dyn NodePermissions,
path: PathBuf,
) -> Result<PackageJson, AnyError> {

View file

@ -1,8 +1,22 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
pub fn find_builtin_node_module(
module_name: &str,
) -> Option<&NodeModulePolyfill> {
use deno_core::error::generic_error;
use deno_core::error::AnyError;
use deno_core::url::Url;
use deno_core::ModuleSpecifier;
// TODO(bartlomieju): seems super wasteful to parse the specifier each time
pub fn resolve_builtin_node_module(module_name: &str) -> Result<Url, AnyError> {
if let Some(module) = find_builtin_node_module(module_name) {
return Ok(ModuleSpecifier::parse(module.specifier).unwrap());
}
Err(generic_error(format!(
"Unknown built-in \"node:\" module: {module_name}"
)))
}
fn find_builtin_node_module(module_name: &str) -> Option<&NodeModulePolyfill> {
SUPPORTED_BUILTIN_NODE_MODULES
.iter()
.find(|m| m.name == module_name)

View file

@ -16,7 +16,7 @@ use crate::package_json::PackageJson;
use crate::path::PathClean;
use crate::NodeFs;
use crate::NodePermissions;
use crate::RequireNpmResolver;
use crate::NpmResolver;
pub static DEFAULT_CONDITIONS: &[&str] = &["deno", "node", "import"];
pub static REQUIRE_CONDITIONS: &[&str] = &["require", "node"];
@ -190,7 +190,7 @@ pub fn package_imports_resolve<Fs: NodeFs>(
referrer_kind: NodeModuleKind,
conditions: &[&str],
mode: NodeResolutionMode,
npm_resolver: &dyn RequireNpmResolver,
npm_resolver: &dyn NpmResolver,
permissions: &mut dyn NodePermissions,
) -> Result<PathBuf, AnyError> {
if name == "#" || name.starts_with("#/") || name.ends_with('/') {
@ -328,7 +328,7 @@ fn resolve_package_target_string<Fs: NodeFs>(
internal: bool,
conditions: &[&str],
mode: NodeResolutionMode,
npm_resolver: &dyn RequireNpmResolver,
npm_resolver: &dyn NpmResolver,
permissions: &mut dyn NodePermissions,
) -> Result<PathBuf, AnyError> {
if !subpath.is_empty() && !pattern && !target.ends_with('/') {
@ -438,7 +438,7 @@ fn resolve_package_target<Fs: NodeFs>(
internal: bool,
conditions: &[&str],
mode: NodeResolutionMode,
npm_resolver: &dyn RequireNpmResolver,
npm_resolver: &dyn NpmResolver,
permissions: &mut dyn NodePermissions,
) -> Result<Option<PathBuf>, AnyError> {
if let Some(target) = target.as_str() {
@ -576,7 +576,7 @@ pub fn package_exports_resolve<Fs: NodeFs>(
referrer_kind: NodeModuleKind,
conditions: &[&str],
mode: NodeResolutionMode,
npm_resolver: &dyn RequireNpmResolver,
npm_resolver: &dyn NpmResolver,
permissions: &mut dyn NodePermissions,
) -> Result<PathBuf, AnyError> {
if package_exports.contains_key(&package_subpath)
@ -733,7 +733,7 @@ pub fn package_resolve<Fs: NodeFs>(
referrer_kind: NodeModuleKind,
conditions: &[&str],
mode: NodeResolutionMode,
npm_resolver: &dyn RequireNpmResolver,
npm_resolver: &dyn NpmResolver,
permissions: &mut dyn NodePermissions,
) -> Result<Option<PathBuf>, AnyError> {
let (package_name, package_subpath, _is_scoped) =
@ -763,7 +763,7 @@ pub fn package_resolve<Fs: NodeFs>(
let package_dir_path = npm_resolver.resolve_package_folder_from_package(
&package_name,
&referrer.to_file_path().unwrap(),
referrer,
mode,
)?;
let package_json_path = package_dir_path.join("package.json");
@ -815,7 +815,7 @@ pub fn package_resolve<Fs: NodeFs>(
pub fn get_package_scope_config<Fs: NodeFs>(
referrer: &ModuleSpecifier,
npm_resolver: &dyn RequireNpmResolver,
npm_resolver: &dyn NpmResolver,
permissions: &mut dyn NodePermissions,
) -> Result<PackageJson, AnyError> {
let root_folder = npm_resolver
@ -826,7 +826,7 @@ pub fn get_package_scope_config<Fs: NodeFs>(
pub fn get_closest_package_json<Fs: NodeFs>(
url: &ModuleSpecifier,
npm_resolver: &dyn RequireNpmResolver,
npm_resolver: &dyn NpmResolver,
permissions: &mut dyn NodePermissions,
) -> Result<PackageJson, AnyError> {
let package_json_path =
@ -836,7 +836,7 @@ pub fn get_closest_package_json<Fs: NodeFs>(
fn get_closest_package_json_path<Fs: NodeFs>(
url: &ModuleSpecifier,
npm_resolver: &dyn RequireNpmResolver,
npm_resolver: &dyn NpmResolver,
) -> Result<PathBuf, AnyError> {
let file_path = url.to_file_path().unwrap();
let mut current_dir = file_path.parent().unwrap();

View file

@ -2,45 +2,34 @@
use std::path::Path;
use std::path::PathBuf;
use std::sync::Arc;
use deno_ast::MediaType;
use deno_ast::ModuleSpecifier;
use deno_core::anyhow::bail;
use deno_core::anyhow::Context;
use deno_core::error::generic_error;
use deno_core::error::AnyError;
use deno_core::serde_json::Value;
use deno_core::url::Url;
use deno_runtime::deno_node;
use deno_runtime::deno_node::errors;
use deno_runtime::deno_node::find_builtin_node_module;
use deno_runtime::deno_node::get_closest_package_json;
use deno_runtime::deno_node::legacy_main_resolve;
use deno_runtime::deno_node::package_exports_resolve;
use deno_runtime::deno_node::package_imports_resolve;
use deno_runtime::deno_node::package_resolve;
use deno_runtime::deno_node::path_to_declaration_path;
use deno_runtime::deno_node::NodeModuleKind;
use deno_runtime::deno_node::NodePermissions;
use deno_runtime::deno_node::NodeResolutionMode;
use deno_runtime::deno_node::PackageJson;
use deno_runtime::deno_node::RealFs;
use deno_runtime::deno_node::RequireNpmResolver;
use deno_runtime::deno_node::DEFAULT_CONDITIONS;
use deno_runtime::permissions::PermissionsContainer;
use deno_core::ModuleSpecifier;
use deno_media_type::MediaType;
use deno_semver::npm::NpmPackageNv;
use deno_semver::npm::NpmPackageNvReference;
use deno_semver::npm::NpmPackageReqReference;
use crate::npm::CliRequireNpmResolver;
use crate::npm::NpmPackageResolver;
use crate::npm::NpmResolution;
use crate::util::fs::canonicalize_path_maybe_not_exists;
mod analyze;
pub use analyze::CliCjsEsmCodeAnalyzer;
use crate::errors;
use crate::get_closest_package_json;
use crate::legacy_main_resolve;
use crate::package_exports_resolve;
use crate::package_imports_resolve;
use crate::package_resolve;
use crate::path_to_declaration_path;
use crate::AllowAllNodePermissions;
use crate::NodeFs;
use crate::NodeModuleKind;
use crate::NodePermissions;
use crate::NodeResolutionMode;
use crate::NpmResolver;
use crate::PackageJson;
use crate::DEFAULT_CONDITIONS;
#[derive(Debug)]
pub enum NodeResolution {
@ -101,33 +90,15 @@ impl NodeResolution {
}
}
// TODO(bartlomieju): seems super wasteful to parse specified each time
pub fn resolve_builtin_node_module(module_name: &str) -> Result<Url, AnyError> {
if let Some(module) = find_builtin_node_module(module_name) {
return Ok(ModuleSpecifier::parse(module.specifier).unwrap());
}
Err(generic_error(format!(
"Unknown built-in \"node:\" module: {module_name}"
)))
}
#[derive(Debug)]
pub struct CliNodeResolver {
npm_resolution: Arc<NpmResolution>,
npm_resolver: Arc<NpmPackageResolver>,
require_npm_resolver: CliRequireNpmResolver,
pub struct NodeResolver<TRequireNpmResolver: NpmResolver> {
npm_resolver: TRequireNpmResolver,
}
impl CliNodeResolver {
pub fn new(
npm_resolution: Arc<NpmResolution>,
npm_package_resolver: Arc<NpmPackageResolver>,
) -> Self {
impl<TRequireNpmResolver: NpmResolver> NodeResolver<TRequireNpmResolver> {
pub fn new(require_npm_resolver: TRequireNpmResolver) -> Self {
Self {
npm_resolution,
require_npm_resolver: npm_package_resolver.as_require_npm_resolver(),
npm_resolver: npm_package_resolver,
npm_resolver: require_npm_resolver,
}
}
@ -137,7 +108,7 @@ impl CliNodeResolver {
/// This function is an implementation of `defaultResolve` in
/// `lib/internal/modules/esm/resolve.js` from Node.
pub fn resolve(
pub fn resolve<Fs: NodeFs>(
&self,
specifier: &str,
referrer: &ModuleSpecifier,
@ -147,7 +118,7 @@ impl CliNodeResolver {
// 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
if deno_node::is_builtin_node_module(specifier) {
if crate::is_builtin_node_module(specifier) {
return Ok(Some(NodeResolution::BuiltIn(specifier.to_string())));
}
@ -162,7 +133,7 @@ impl CliNodeResolver {
let split_specifier = url.as_str().split(':');
let specifier = split_specifier.skip(1).collect::<String>();
if deno_node::is_builtin_node_module(&specifier) {
if crate::is_builtin_node_module(&specifier) {
return Ok(Some(NodeResolution::BuiltIn(specifier)));
}
}
@ -178,7 +149,7 @@ impl CliNodeResolver {
}
}
let url = self.module_resolve(
let url = self.module_resolve::<Fs>(
specifier,
referrer,
DEFAULT_CONDITIONS,
@ -196,7 +167,7 @@ impl CliNodeResolver {
// todo(16370): the module kind is not correct here. I think we need
// typescript to tell us if the referrer is esm or cjs
let path =
match path_to_declaration_path::<RealFs>(path, NodeModuleKind::Esm) {
match path_to_declaration_path::<Fs>(path, NodeModuleKind::Esm) {
Some(path) => path,
None => return Ok(None),
};
@ -204,13 +175,13 @@ impl CliNodeResolver {
}
};
let resolve_response = self.url_to_node_resolution(url)?;
let resolve_response = self.url_to_node_resolution::<Fs>(url)?;
// TODO(bartlomieju): skipped checking errors for commonJS resolution and
// "preserveSymlinksMain"/"preserveSymlinks" options.
Ok(Some(resolve_response))
}
fn module_resolve(
fn module_resolve<Fs: NodeFs>(
&self,
specifier: &str,
referrer: &ModuleSpecifier,
@ -226,7 +197,7 @@ impl CliNodeResolver {
// todo(dsherret): the node module kind is not correct and we
// should use the value provided by typescript instead
let declaration_path =
path_to_declaration_path::<RealFs>(file_path, NodeModuleKind::Esm);
path_to_declaration_path::<Fs>(file_path, NodeModuleKind::Esm);
declaration_path.map(|declaration_path| {
ModuleSpecifier::from_file_path(declaration_path).unwrap()
})
@ -235,13 +206,13 @@ impl CliNodeResolver {
}
} else if specifier.starts_with('#') {
Some(
package_imports_resolve::<RealFs>(
package_imports_resolve::<Fs>(
specifier,
referrer,
NodeModuleKind::Esm,
conditions,
mode,
&self.require_npm_resolver,
&self.npm_resolver,
permissions,
)
.map(|p| ModuleSpecifier::from_file_path(p).unwrap())?,
@ -249,34 +220,36 @@ impl CliNodeResolver {
} else if let Ok(resolved) = Url::parse(specifier) {
Some(resolved)
} else {
package_resolve::<RealFs>(
package_resolve::<Fs>(
specifier,
referrer,
NodeModuleKind::Esm,
conditions,
mode,
&self.require_npm_resolver,
&self.npm_resolver,
permissions,
)?
.map(|p| ModuleSpecifier::from_file_path(p).unwrap())
};
Ok(match url {
Some(url) => Some(finalize_resolution(url, referrer)?),
Some(url) => Some(finalize_resolution::<Fs>(url, referrer)?),
None => None,
})
}
pub fn resolve_npm_req_reference(
pub fn resolve_npm_req_reference<Fs: NodeFs>(
&self,
reference: &NpmPackageReqReference,
mode: NodeResolutionMode,
permissions: &mut dyn NodePermissions,
) -> Result<Option<NodeResolution>, AnyError> {
let reference = self.npm_resolution.pkg_req_ref_to_nv_ref(reference)?;
self.resolve_npm_reference(&reference, mode, permissions)
let reference = self
.npm_resolver
.resolve_nv_ref_from_pkg_req_ref(reference)?;
self.resolve_npm_reference::<Fs>(&reference, mode, permissions)
}
pub fn resolve_npm_reference(
pub fn resolve_npm_reference<Fs: NodeFs>(
&self,
reference: &NpmPackageNvReference,
mode: NodeResolutionMode,
@ -286,7 +259,7 @@ impl CliNodeResolver {
.npm_resolver
.resolve_package_folder_from_deno_module(&reference.nv)?;
let node_module_kind = NodeModuleKind::Esm;
let maybe_resolved_path = package_config_resolve(
let maybe_resolved_path = package_config_resolve::<Fs>(
&reference
.sub_path
.as_ref()
@ -296,7 +269,7 @@ impl CliNodeResolver {
node_module_kind,
DEFAULT_CONDITIONS,
mode,
&self.require_npm_resolver,
&self.npm_resolver,
permissions,
)
.with_context(|| {
@ -309,23 +282,20 @@ impl CliNodeResolver {
let resolved_path = match mode {
NodeResolutionMode::Execution => resolved_path,
NodeResolutionMode::Types => {
match path_to_declaration_path::<RealFs>(
resolved_path,
node_module_kind,
) {
match path_to_declaration_path::<Fs>(resolved_path, node_module_kind) {
Some(path) => path,
None => return Ok(None),
}
}
};
let url = ModuleSpecifier::from_file_path(resolved_path).unwrap();
let resolve_response = self.url_to_node_resolution(url)?;
let resolve_response = self.url_to_node_resolution::<Fs>(url)?;
// TODO(bartlomieju): skipped checking errors for commonJS resolution and
// "preserveSymlinksMain"/"preserveSymlinks" options.
Ok(Some(resolve_response))
}
pub fn resolve_binary_commands(
pub fn resolve_binary_commands<Fs: NodeFs>(
&self,
pkg_nv: &NpmPackageNv,
) -> Result<Vec<String>, AnyError> {
@ -333,9 +303,9 @@ impl CliNodeResolver {
.npm_resolver
.resolve_package_folder_from_deno_module(pkg_nv)?;
let package_json_path = package_folder.join("package.json");
let package_json = PackageJson::load::<RealFs>(
&self.require_npm_resolver,
&mut PermissionsContainer::allow_all(),
let package_json = PackageJson::load::<Fs>(
&self.npm_resolver,
&mut AllowAllNodePermissions,
package_json_path,
)?;
@ -348,12 +318,12 @@ impl CliNodeResolver {
})
}
pub fn resolve_binary_export(
pub fn resolve_binary_export<Fs: NodeFs>(
&self,
pkg_ref: &NpmPackageReqReference,
) -> Result<NodeResolution, AnyError> {
let pkg_nv = self
.npm_resolution
.npm_resolver
.resolve_pkg_id_from_pkg_req(&pkg_ref.req)?
.nv;
let bin_name = pkg_ref.sub_path.as_deref();
@ -361,9 +331,9 @@ impl CliNodeResolver {
.npm_resolver
.resolve_package_folder_from_deno_module(&pkg_nv)?;
let package_json_path = package_folder.join("package.json");
let package_json = PackageJson::load::<RealFs>(
&self.require_npm_resolver,
&mut PermissionsContainer::allow_all(),
let package_json = PackageJson::load::<Fs>(
&self.npm_resolver,
&mut AllowAllNodePermissions,
package_json_path,
)?;
let bin = match &package_json.bin {
@ -377,13 +347,13 @@ impl CliNodeResolver {
let url =
ModuleSpecifier::from_file_path(package_folder.join(bin_entry)).unwrap();
let resolve_response = self.url_to_node_resolution(url)?;
let resolve_response = self.url_to_node_resolution::<Fs>(url)?;
// TODO(bartlomieju): skipped checking errors for commonJS resolution and
// "preserveSymlinksMain"/"preserveSymlinks" options.
Ok(resolve_response)
}
pub fn url_to_node_resolution(
pub fn url_to_node_resolution<Fs: NodeFs>(
&self,
url: ModuleSpecifier,
) -> Result<NodeResolution, AnyError> {
@ -391,10 +361,10 @@ impl CliNodeResolver {
if url_str.starts_with("http") {
Ok(NodeResolution::Esm(url))
} else if url_str.ends_with(".js") || url_str.ends_with(".d.ts") {
let package_config = get_closest_package_json::<RealFs>(
let package_config = get_closest_package_json::<Fs>(
&url,
&self.require_npm_resolver,
&mut PermissionsContainer::allow_all(),
&self.npm_resolver,
&mut AllowAllNodePermissions,
)?;
if package_config.typ == "module" {
Ok(NodeResolution::Esm(url))
@ -413,25 +383,6 @@ impl CliNodeResolver {
}
}
/// Resolves a specifier that is pointing into a node_modules folder.
///
/// Note: This should be called whenever getting the specifier from
/// a Module::External(module) reference because that module might
/// not be fully resolved at the time deno_graph is analyzing it
/// because the node_modules folder might not exist at that time.
pub fn resolve_specifier_into_node_modules(
specifier: &ModuleSpecifier,
) -> ModuleSpecifier {
specifier
.to_file_path()
.ok()
// this path might not exist at the time the graph is being created
// because the node_modules folder might not yet exist
.and_then(|path| canonicalize_path_maybe_not_exists(&path).ok())
.and_then(|path| ModuleSpecifier::from_file_path(path).ok())
.unwrap_or_else(|| specifier.clone())
}
fn resolve_bin_entry_value<'a>(
pkg_nv: &NpmPackageNv,
bin_name: Option<&str>,
@ -488,24 +439,24 @@ fn resolve_bin_entry_value<'a>(
}
}
fn package_config_resolve(
fn package_config_resolve<Fs: NodeFs>(
package_subpath: &str,
package_dir: &Path,
referrer_kind: NodeModuleKind,
conditions: &[&str],
mode: NodeResolutionMode,
npm_resolver: &dyn RequireNpmResolver,
npm_resolver: &dyn NpmResolver,
permissions: &mut dyn NodePermissions,
) -> Result<Option<PathBuf>, AnyError> {
let package_json_path = package_dir.join("package.json");
let referrer = ModuleSpecifier::from_directory_path(package_dir).unwrap();
let package_config = PackageJson::load::<RealFs>(
let package_config = PackageJson::load::<Fs>(
npm_resolver,
permissions,
package_json_path.clone(),
)?;
if let Some(exports) = &package_config.exports {
let result = package_exports_resolve::<RealFs>(
let result = package_exports_resolve::<Fs>(
&package_json_path,
package_subpath.to_string(),
exports,
@ -521,7 +472,7 @@ fn package_config_resolve(
Err(exports_err) => {
if mode.is_types() && package_subpath == "." {
if let Ok(Some(path)) =
legacy_main_resolve::<RealFs>(&package_config, referrer_kind, mode)
legacy_main_resolve::<Fs>(&package_config, referrer_kind, mode)
{
return Ok(Some(path));
} else {
@ -533,13 +484,13 @@ fn package_config_resolve(
}
}
if package_subpath == "." {
return legacy_main_resolve::<RealFs>(&package_config, referrer_kind, mode);
return legacy_main_resolve::<Fs>(&package_config, referrer_kind, mode);
}
Ok(Some(package_dir.join(package_subpath)))
}
fn finalize_resolution(
fn finalize_resolution<Fs: NodeFs>(
resolved: ModuleSpecifier,
base: &ModuleSpecifier,
) -> Result<ModuleSpecifier, AnyError> {
@ -567,8 +518,8 @@ fn finalize_resolution(
p_str.to_string()
};
let (is_dir, is_file) = if let Ok(stats) = std::fs::metadata(p) {
(stats.is_dir(), stats.is_file())
let (is_dir, is_file) = if let Ok(stats) = Fs::metadata(p) {
(stats.is_dir, stats.is_file)
} else {
(false, false)
};

View file

@ -37,7 +37,7 @@ use deno_core::SourceMapGetter;
use deno_fs::StdFs;
use deno_io::Stdio;
use deno_kv::sqlite::SqliteDbHandler;
use deno_node::RequireNpmResolver;
use deno_node::NpmResolver;
use deno_tls::rustls::RootCertStore;
use deno_web::create_entangled_message_port;
use deno_web::BlobStore;
@ -333,7 +333,7 @@ pub struct WebWorkerOptions {
pub root_cert_store: Option<RootCertStore>,
pub seed: Option<u64>,
pub module_loader: Rc<dyn ModuleLoader>,
pub npm_resolver: Option<Rc<dyn RequireNpmResolver>>,
pub npm_resolver: Option<Rc<dyn NpmResolver>>,
pub create_web_worker_cb: Arc<ops::worker_host::CreateWebWorkerCb>,
pub preload_module_cb: Arc<ops::worker_host::WorkerEventCb>,
pub pre_execute_module_cb: Arc<ops::worker_host::WorkerEventCb>,

View file

@ -33,7 +33,7 @@ use deno_core::SourceMapGetter;
use deno_fs::StdFs;
use deno_io::Stdio;
use deno_kv::sqlite::SqliteDbHandler;
use deno_node::RequireNpmResolver;
use deno_node::NpmResolver;
use deno_tls::rustls::RootCertStore;
use deno_web::BlobStore;
use log::debug;
@ -94,7 +94,7 @@ pub struct WorkerOptions {
/// If not provided runtime will error if code being
/// executed tries to load modules.
pub module_loader: Rc<dyn ModuleLoader>,
pub npm_resolver: Option<Rc<dyn RequireNpmResolver>>,
pub npm_resolver: Option<Rc<dyn NpmResolver>>,
// Callbacks invoked when creating new instance of WebWorker
pub create_web_worker_cb: Arc<ops::worker_host::CreateWebWorkerCb>,
pub web_worker_preload_module_cb: Arc<ops::worker_host::WorkerEventCb>,