summaryrefslogtreecommitdiff
path: root/core/modules/loaders.rs
diff options
context:
space:
mode:
authorMatt Mastracci <matthew@mastracci.com>2023-07-01 18:00:14 -0600
committerGitHub <noreply@github.com>2023-07-02 00:00:14 +0000
commite746b6d80654ba4e4e26370fe6e4f784ce841d92 (patch)
tree153ffad92a96126b9ab8e906dcdabf7648755931 /core/modules/loaders.rs
parentb9c0e7cd550ab14fa7da7e33ed87cbeeeb9785a0 (diff)
refactor(core): Extract deno_core (#19658)
`deno_core` is moving out! You'll find it at https://github.com/denoland/deno_core/ once this PR lands.
Diffstat (limited to 'core/modules/loaders.rs')
-rw-r--r--core/modules/loaders.rs253
1 files changed, 0 insertions, 253 deletions
diff --git a/core/modules/loaders.rs b/core/modules/loaders.rs
deleted file mode 100644
index bc645567e..000000000
--- a/core/modules/loaders.rs
+++ /dev/null
@@ -1,253 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-use crate::error::generic_error;
-use crate::error::AnyError;
-use crate::extensions::ExtensionFileSource;
-use crate::module_specifier::ModuleSpecifier;
-use crate::modules::ModuleCode;
-use crate::modules::ModuleSource;
-use crate::modules::ModuleSourceFuture;
-use crate::modules::ModuleType;
-use crate::modules::ResolutionKind;
-use crate::resolve_import;
-use crate::Extension;
-use anyhow::anyhow;
-use anyhow::Error;
-use futures::future::FutureExt;
-use std::cell::RefCell;
-use std::collections::HashMap;
-use std::collections::HashSet;
-use std::future::Future;
-use std::pin::Pin;
-use std::rc::Rc;
-
-pub trait ModuleLoader {
- /// Returns an absolute URL.
- /// When implementing an spec-complaint VM, this should be exactly the
- /// algorithm described here:
- /// <https://html.spec.whatwg.org/multipage/webappapis.html#resolve-a-module-specifier>
- ///
- /// `is_main` can be used to resolve from current working directory or
- /// apply import map for child imports.
- ///
- /// `is_dyn_import` can be used to check permissions or deny
- /// dynamic imports altogether.
- fn resolve(
- &self,
- specifier: &str,
- referrer: &str,
- kind: ResolutionKind,
- ) -> Result<ModuleSpecifier, Error>;
-
- /// Given ModuleSpecifier, load its source code.
- ///
- /// `is_dyn_import` can be used to check permissions or deny
- /// dynamic imports altogether.
- fn load(
- &self,
- module_specifier: &ModuleSpecifier,
- maybe_referrer: Option<&ModuleSpecifier>,
- is_dyn_import: bool,
- ) -> Pin<Box<ModuleSourceFuture>>;
-
- /// This hook can be used by implementors to do some preparation
- /// work before starting loading of modules.
- ///
- /// For example implementor might download multiple modules in
- /// parallel and transpile them to final JS sources before
- /// yielding control back to the runtime.
- ///
- /// It's not required to implement this method.
- fn prepare_load(
- &self,
- _module_specifier: &ModuleSpecifier,
- _maybe_referrer: Option<String>,
- _is_dyn_import: bool,
- ) -> Pin<Box<dyn Future<Output = Result<(), Error>>>> {
- async { Ok(()) }.boxed_local()
- }
-}
-
-/// Placeholder structure used when creating
-/// a runtime that doesn't support module loading.
-pub struct NoopModuleLoader;
-
-impl ModuleLoader for NoopModuleLoader {
- fn resolve(
- &self,
- specifier: &str,
- referrer: &str,
- _kind: ResolutionKind,
- ) -> Result<ModuleSpecifier, Error> {
- Err(generic_error(
- format!("Module loading is not supported; attempted to resolve: \"{specifier}\" from \"{referrer}\"")
- ))
- }
-
- fn load(
- &self,
- module_specifier: &ModuleSpecifier,
- maybe_referrer: Option<&ModuleSpecifier>,
- _is_dyn_import: bool,
- ) -> Pin<Box<ModuleSourceFuture>> {
- let err = generic_error(
- format!(
- "Module loading is not supported; attempted to load: \"{module_specifier}\" from \"{maybe_referrer:?}\"",
- )
- );
- async move { Err(err) }.boxed_local()
- }
-}
-
-/// Function that can be passed to the `ExtModuleLoader` that allows to
-/// transpile sources before passing to V8.
-pub type ExtModuleLoaderCb =
- Box<dyn Fn(&ExtensionFileSource) -> Result<ModuleCode, Error>>;
-
-pub(crate) struct ExtModuleLoader {
- maybe_load_callback: Option<Rc<ExtModuleLoaderCb>>,
- sources: RefCell<HashMap<String, ExtensionFileSource>>,
- used_specifiers: RefCell<HashSet<String>>,
-}
-
-impl ExtModuleLoader {
- pub fn new(
- extensions: &[Extension],
- maybe_load_callback: Option<Rc<ExtModuleLoaderCb>>,
- ) -> Self {
- let mut sources = HashMap::new();
- sources.extend(
- extensions
- .iter()
- .flat_map(|e| e.get_esm_sources())
- .map(|s| (s.specifier.to_string(), s.clone())),
- );
- ExtModuleLoader {
- maybe_load_callback,
- sources: RefCell::new(sources),
- used_specifiers: Default::default(),
- }
- }
-}
-
-impl ModuleLoader for ExtModuleLoader {
- fn resolve(
- &self,
- specifier: &str,
- referrer: &str,
- _kind: ResolutionKind,
- ) -> Result<ModuleSpecifier, Error> {
- Ok(resolve_import(specifier, referrer)?)
- }
-
- fn load(
- &self,
- specifier: &ModuleSpecifier,
- _maybe_referrer: Option<&ModuleSpecifier>,
- _is_dyn_import: bool,
- ) -> Pin<Box<ModuleSourceFuture>> {
- let sources = self.sources.borrow();
- let source = match sources.get(specifier.as_str()) {
- Some(source) => source,
- None => return futures::future::err(anyhow!("Specifier \"{}\" was not passed as an extension module and was not included in the snapshot.", specifier)).boxed_local(),
- };
- self
- .used_specifiers
- .borrow_mut()
- .insert(specifier.to_string());
- let result = if let Some(load_callback) = &self.maybe_load_callback {
- load_callback(source)
- } else {
- source.load()
- };
- match result {
- Ok(code) => {
- let res = ModuleSource::new(ModuleType::JavaScript, code, specifier);
- return futures::future::ok(res).boxed_local();
- }
- Err(err) => return futures::future::err(err).boxed_local(),
- }
- }
-
- fn prepare_load(
- &self,
- _specifier: &ModuleSpecifier,
- _maybe_referrer: Option<String>,
- _is_dyn_import: bool,
- ) -> Pin<Box<dyn Future<Output = Result<(), Error>>>> {
- async { Ok(()) }.boxed_local()
- }
-}
-
-impl Drop for ExtModuleLoader {
- fn drop(&mut self) {
- let sources = self.sources.get_mut();
- let used_specifiers = self.used_specifiers.get_mut();
- let unused_modules: Vec<_> = sources
- .iter()
- .filter(|(k, _)| !used_specifiers.contains(k.as_str()))
- .collect();
-
- if !unused_modules.is_empty() {
- let mut msg =
- "Following modules were passed to ExtModuleLoader but never used:\n"
- .to_string();
- for m in unused_modules {
- msg.push_str(" - ");
- msg.push_str(m.0);
- msg.push('\n');
- }
- panic!("{}", msg);
- }
- }
-}
-
-/// Basic file system module loader.
-///
-/// Note that this loader will **block** event loop
-/// when loading file as it uses synchronous FS API
-/// from standard library.
-pub struct FsModuleLoader;
-
-impl ModuleLoader for FsModuleLoader {
- fn resolve(
- &self,
- specifier: &str,
- referrer: &str,
- _kind: ResolutionKind,
- ) -> Result<ModuleSpecifier, Error> {
- Ok(resolve_import(specifier, referrer)?)
- }
-
- fn load(
- &self,
- module_specifier: &ModuleSpecifier,
- _maybe_referrer: Option<&ModuleSpecifier>,
- _is_dynamic: bool,
- ) -> Pin<Box<ModuleSourceFuture>> {
- fn load(
- module_specifier: &ModuleSpecifier,
- ) -> Result<ModuleSource, AnyError> {
- let path = module_specifier.to_file_path().map_err(|_| {
- generic_error(format!(
- "Provided module specifier \"{module_specifier}\" is not a file URL."
- ))
- })?;
- let module_type = if let Some(extension) = path.extension() {
- let ext = extension.to_string_lossy().to_lowercase();
- if ext == "json" {
- ModuleType::Json
- } else {
- ModuleType::JavaScript
- }
- } else {
- ModuleType::JavaScript
- };
-
- let code = std::fs::read_to_string(path)?.into();
- let module = ModuleSource::new(module_type, code, module_specifier);
- Ok(module)
- }
-
- futures::future::ready(load(module_specifier)).boxed_local()
- }
-}