summaryrefslogtreecommitdiff
path: root/cli/module_loader.rs
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2024-01-27 22:40:36 +0530
committerGitHub <noreply@github.com>2024-01-27 09:10:36 -0800
commited65bc6abc0a164ea68fae62e9a4e545f729be2d (patch)
tree6d725f799bfd10b4ad564441505252234af6e847 /cli/module_loader.rs
parentd9191db0ce50b62cf54de9046d8c504599e30ae0 (diff)
refactor(cli): decouple resolvers from `module_loader.rs` for standalone use (#22147)
It makes it easier to write a standalone bin target for `deno compile` without pulling a lot of the tooling and tsc loader logic
Diffstat (limited to 'cli/module_loader.rs')
-rw-r--r--cli/module_loader.rs238
1 files changed, 3 insertions, 235 deletions
diff --git a/cli/module_loader.rs b/cli/module_loader.rs
index e6329a0ec..3d80aeb5c 100644
--- a/cli/module_loader.rs
+++ b/cli/module_loader.rs
@@ -14,9 +14,10 @@ use crate::graph_util::FileWatcherReporter;
use crate::graph_util::ModuleGraphBuilder;
use crate::graph_util::ModuleGraphContainer;
use crate::node;
-use crate::node::CliNodeCodeTranslator;
-use crate::npm::CliNpmResolver;
use crate::resolver::CliGraphResolver;
+use crate::resolver::CliNodeResolver;
+use crate::resolver::ModuleCodeStringSource;
+use crate::resolver::NpmModuleLoader;
use crate::tools::check;
use crate::tools::check::TypeChecker;
use crate::util::progress_bar::ProgressBar;
@@ -53,14 +54,10 @@ use deno_graph::Resolution;
use deno_lockfile::Lockfile;
use deno_runtime::colors;
use deno_runtime::deno_fs;
-use deno_runtime::deno_node::NodeResolution;
-use deno_runtime::deno_node::NodeResolutionMode;
-use deno_runtime::deno_node::NodeResolver;
use deno_runtime::permissions::PermissionsContainer;
use deno_semver::npm::NpmPackageReqReference;
use std::borrow::Cow;
use std::collections::HashSet;
-use std::path::Path;
use std::pin::Pin;
use std::rc::Rc;
use std::str;
@@ -271,12 +268,6 @@ impl ModuleLoadPreparer {
}
}
-pub struct ModuleCodeStringSource {
- pub code: ModuleCodeString,
- pub found_url: ModuleSpecifier,
- pub media_type: MediaType,
-}
-
struct PreparedModuleLoader {
emitter: Arc<Emitter>,
graph_container: Arc<ModuleGraphContainer>,
@@ -741,226 +732,3 @@ impl SourceMapGetter for CliSourceMapGetter {
}
}
}
-
-pub struct CliNodeResolver {
- cjs_resolutions: Arc<CjsResolutionStore>,
- node_resolver: Arc<NodeResolver>,
- npm_resolver: Arc<dyn CliNpmResolver>,
-}
-
-impl CliNodeResolver {
- pub fn new(
- cjs_resolutions: Arc<CjsResolutionStore>,
- node_resolver: Arc<NodeResolver>,
- npm_resolver: Arc<dyn CliNpmResolver>,
- ) -> Self {
- Self {
- cjs_resolutions,
- node_resolver,
- npm_resolver,
- }
- }
-
- pub fn in_npm_package(&self, referrer: &ModuleSpecifier) -> bool {
- self.npm_resolver.in_npm_package(referrer)
- }
-
- pub fn resolve_if_in_npm_package(
- &self,
- specifier: &str,
- referrer: &ModuleSpecifier,
- permissions: &PermissionsContainer,
- ) -> Option<Result<ModuleSpecifier, AnyError>> {
- if self.in_npm_package(referrer) {
- // we're in an npm package, so use node resolution
- Some(
- self
- .handle_node_resolve_result(self.node_resolver.resolve(
- specifier,
- referrer,
- NodeResolutionMode::Execution,
- permissions,
- ))
- .with_context(|| {
- format!("Could not resolve '{specifier}' from '{referrer}'.")
- }),
- )
- } else {
- None
- }
- }
-
- pub fn resolve_req_reference(
- &self,
- req_ref: &NpmPackageReqReference,
- permissions: &PermissionsContainer,
- referrer: &ModuleSpecifier,
- ) -> Result<ModuleSpecifier, AnyError> {
- let package_folder = self
- .npm_resolver
- .resolve_pkg_folder_from_deno_module_req(req_ref.req(), referrer)?;
- self
- .resolve_package_sub_path(
- &package_folder,
- req_ref.sub_path(),
- referrer,
- permissions,
- )
- .with_context(|| format!("Could not resolve '{}'.", req_ref))
- }
-
- pub fn resolve_package_sub_path(
- &self,
- package_folder: &Path,
- sub_path: Option<&str>,
- referrer: &ModuleSpecifier,
- permissions: &PermissionsContainer,
- ) -> Result<ModuleSpecifier, AnyError> {
- self.handle_node_resolve_result(
- self.node_resolver.resolve_package_subpath_from_deno_module(
- package_folder,
- sub_path,
- referrer,
- NodeResolutionMode::Execution,
- permissions,
- ),
- )
- }
-
- fn handle_node_resolve_result(
- &self,
- result: Result<Option<NodeResolution>, AnyError>,
- ) -> Result<ModuleSpecifier, AnyError> {
- let response = match result? {
- Some(response) => response,
- None => return Err(generic_error("not found")),
- };
- if let NodeResolution::CommonJs(specifier) = &response {
- // remember that this was a common js resolution
- self.cjs_resolutions.insert(specifier.clone());
- }
- Ok(response.into_url())
- }
-}
-
-pub struct NpmModuleLoader {
- cjs_resolutions: Arc<CjsResolutionStore>,
- node_code_translator: Arc<CliNodeCodeTranslator>,
- fs: Arc<dyn deno_fs::FileSystem>,
- node_resolver: Arc<CliNodeResolver>,
-}
-
-impl NpmModuleLoader {
- pub fn new(
- cjs_resolutions: Arc<CjsResolutionStore>,
- node_code_translator: Arc<CliNodeCodeTranslator>,
- fs: Arc<dyn deno_fs::FileSystem>,
- node_resolver: Arc<CliNodeResolver>,
- ) -> Self {
- Self {
- cjs_resolutions,
- node_code_translator,
- fs,
- node_resolver,
- }
- }
-
- pub fn maybe_prepare_load(
- &self,
- specifier: &ModuleSpecifier,
- ) -> Option<Result<(), AnyError>> {
- if self.node_resolver.in_npm_package(specifier) {
- // nothing to prepare
- Some(Ok(()))
- } else {
- None
- }
- }
-
- pub fn load_sync_if_in_npm_package(
- &self,
- specifier: &ModuleSpecifier,
- maybe_referrer: Option<&ModuleSpecifier>,
- permissions: &PermissionsContainer,
- ) -> Option<Result<ModuleCodeStringSource, AnyError>> {
- if self.node_resolver.in_npm_package(specifier) {
- Some(self.load_sync(specifier, maybe_referrer, permissions))
- } else {
- None
- }
- }
-
- fn load_sync(
- &self,
- specifier: &ModuleSpecifier,
- maybe_referrer: Option<&ModuleSpecifier>,
- permissions: &PermissionsContainer,
- ) -> Result<ModuleCodeStringSource, AnyError> {
- let file_path = specifier.to_file_path().unwrap();
- let code = self
- .fs
- .read_text_file_sync(&file_path)
- .map_err(AnyError::from)
- .with_context(|| {
- if file_path.is_dir() {
- // directory imports are not allowed when importing from an
- // ES module, so provide the user with a helpful error message
- let dir_path = file_path;
- let mut msg = "Directory import ".to_string();
- msg.push_str(&dir_path.to_string_lossy());
- if let Some(referrer) = &maybe_referrer {
- msg.push_str(" is not supported resolving import from ");
- msg.push_str(referrer.as_str());
- let entrypoint_name = ["index.mjs", "index.js", "index.cjs"]
- .iter()
- .find(|e| dir_path.join(e).is_file());
- if let Some(entrypoint_name) = entrypoint_name {
- msg.push_str("\nDid you mean to import ");
- msg.push_str(entrypoint_name);
- msg.push_str(" within the directory?");
- }
- }
- msg
- } else {
- let mut msg = "Unable to load ".to_string();
- msg.push_str(&file_path.to_string_lossy());
- if let Some(referrer) = &maybe_referrer {
- msg.push_str(" imported from ");
- msg.push_str(referrer.as_str());
- }
- msg
- }
- })?;
-
- let code = if self.cjs_resolutions.contains(specifier) {
- // translate cjs to esm if it's cjs and inject node globals
- self.node_code_translator.translate_cjs_to_esm(
- specifier,
- Some(code.as_str()),
- permissions,
- )?
- } else {
- // esm and json code is untouched
- code
- };
- Ok(ModuleCodeStringSource {
- code: code.into(),
- found_url: specifier.clone(),
- media_type: MediaType::from_specifier(specifier),
- })
- }
-}
-
-/// Keeps track of what module specifiers were resolved as CJS.
-#[derive(Debug, Default)]
-pub struct CjsResolutionStore(Mutex<HashSet<ModuleSpecifier>>);
-
-impl CjsResolutionStore {
- pub fn contains(&self, specifier: &ModuleSpecifier) -> bool {
- self.0.lock().contains(specifier)
- }
-
- pub fn insert(&self, specifier: ModuleSpecifier) {
- self.0.lock().insert(specifier);
- }
-}