diff options
author | Leo Kettmeir <crowlkats@toaxl.com> | 2023-02-07 20:22:46 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-07 20:22:46 +0100 |
commit | b4aa1530970f7b9cc4e6f2f27e077852c4e178d3 (patch) | |
tree | 3d008912affe8550692183bd2697a386db5e3c79 /core/modules.rs | |
parent | 65500f36e870b4ada3996b06aa287e30177d21a3 (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.rs | 92 |
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()) + ); + } } |