summaryrefslogtreecommitdiff
path: root/core/modules.rs
diff options
context:
space:
mode:
authorLeo Kettmeir <crowlkats@toaxl.com>2023-02-07 20:22:46 +0100
committerGitHub <noreply@github.com>2023-02-07 20:22:46 +0100
commitb4aa1530970f7b9cc4e6f2f27e077852c4e178d3 (patch)
tree3d008912affe8550692183bd2697a386db5e3c79 /core/modules.rs
parent65500f36e870b4ada3996b06aa287e30177d21a3 (diff)
refactor: Use ES modules for internal runtime code (#17648)
This PR refactors all internal js files (except core) to be written as ES modules. `__bootstrap`has been mostly replaced with static imports in form in `internal:[path to file from repo root]`. To specify if files are ESM, an `esm` method has been added to `Extension`, similar to the `js` method. A new ModuleLoader called `InternalModuleLoader` has been added to enable the loading of internal specifiers, which is used in all situations except when a snapshot is only loaded, and not a new one is created from it. --------- Co-authored-by: Bartek IwaƄczuk <biwanczuk@gmail.com>
Diffstat (limited to 'core/modules.rs')
-rw-r--r--core/modules.rs92
1 files changed, 92 insertions, 0 deletions
diff --git a/core/modules.rs b/core/modules.rs
index 1b7169ea4..b57428070 100644
--- a/core/modules.rs
+++ b/core/modules.rs
@@ -292,6 +292,69 @@ impl ModuleLoader for NoopModuleLoader {
}
}
+pub struct InternalModuleLoader(Rc<dyn ModuleLoader>);
+
+impl InternalModuleLoader {
+ pub fn new(module_loader: Option<Rc<dyn ModuleLoader>>) -> Self {
+ InternalModuleLoader(
+ module_loader.unwrap_or_else(|| Rc::new(NoopModuleLoader)),
+ )
+ }
+}
+
+impl ModuleLoader for InternalModuleLoader {
+ fn resolve(
+ &self,
+ specifier: &str,
+ referrer: &str,
+ kind: ResolutionKind,
+ ) -> Result<ModuleSpecifier, Error> {
+ if let Ok(url_specifier) = ModuleSpecifier::parse(specifier) {
+ if url_specifier.scheme() == "internal" {
+ let referrer_specifier = ModuleSpecifier::parse(referrer).ok();
+ if referrer == "." || referrer_specifier.unwrap().scheme() == "internal"
+ {
+ return Ok(url_specifier);
+ } else {
+ return Err(generic_error(
+ "Cannot load internal module from external code",
+ ));
+ };
+ }
+ }
+
+ self.0.resolve(specifier, referrer, kind)
+ }
+
+ fn load(
+ &self,
+ module_specifier: &ModuleSpecifier,
+ maybe_referrer: Option<ModuleSpecifier>,
+ is_dyn_import: bool,
+ ) -> Pin<Box<ModuleSourceFuture>> {
+ self.0.load(module_specifier, maybe_referrer, is_dyn_import)
+ }
+
+ fn prepare_load(
+ &self,
+ op_state: Rc<RefCell<OpState>>,
+ module_specifier: &ModuleSpecifier,
+ maybe_referrer: Option<String>,
+ is_dyn_import: bool,
+ ) -> Pin<Box<dyn Future<Output = Result<(), Error>>>> {
+ if module_specifier.scheme() == "internal" {
+ return async { Ok(()) }.boxed_local();
+ }
+
+ self.0.prepare_load(
+ op_state,
+ module_specifier,
+ maybe_referrer,
+ is_dyn_import,
+ )
+ }
+}
+
/// Basic file system module loader.
///
/// Note that this loader will **block** event loop
@@ -2508,4 +2571,33 @@ if (import.meta.url != 'file:///main_with_code.js') throw Error();
)
.unwrap();
}
+
+ #[test]
+ fn internal_module_loader() {
+ let loader = InternalModuleLoader::new(None);
+ assert!(loader
+ .resolve("internal:foo", "internal:bar", ResolutionKind::Import)
+ .is_ok());
+ assert_eq!(
+ loader
+ .resolve("internal:foo", "file://bar", ResolutionKind::Import)
+ .err()
+ .map(|e| e.to_string()),
+ Some("Cannot load internal module from external code".to_string())
+ );
+ assert_eq!(
+ loader
+ .resolve("file://foo", "file://bar", ResolutionKind::Import)
+ .err()
+ .map(|e| e.to_string()),
+ Some("Module loading is not supported".to_string())
+ );
+ assert_eq!(
+ loader
+ .resolve("file://foo", "internal:bar", ResolutionKind::Import)
+ .err()
+ .map(|e| e.to_string()),
+ Some("Module loading is not supported".to_string())
+ );
+ }
}