diff options
author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2023-01-10 14:35:44 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-10 14:35:44 +0100 |
commit | 636352e0ca1e611c7673f2ab68538e1ddb2dc5b7 (patch) | |
tree | c250c7a74917cef683999e06283ea9f7182f372c /core/modules.rs | |
parent | 45768f0e832e54d61ddb5a62d62239aef0e597b5 (diff) |
fix(npm): allow to read package.json if permissions are granted (#17209)
This commit changes signature of "deno_core::ModuleLoader::resolve" to pass
an enum indicating whether or not we're resolving a specifier for dynamic import.
Additionally "CliModuleLoader" was changes to store both "parent permissions" (or
"root permissions") as well as "dynamic permissions" that allow to check for permissions
in top-level module load an dynamic imports.
Then all code paths that have anything to do with Node/npm compat are now checking
for permissions which are passed from module loader instance associated with given
worker.
Diffstat (limited to 'core/modules.rs')
-rw-r--r-- | core/modules.rs | 98 |
1 files changed, 70 insertions, 28 deletions
diff --git a/core/modules.rs b/core/modules.rs index 8abced200..917649c85 100644 --- a/core/modules.rs +++ b/core/modules.rs @@ -202,6 +202,20 @@ pub type ModuleSourceFuture = dyn Future<Output = Result<ModuleSource, Error>>; type ModuleLoadFuture = dyn Future<Output = Result<(ModuleRequest, ModuleSource), Error>>; +pub enum ResolutionKind { + /// This kind is used in only one situation: when a module is loaded via + /// `JsRuntime::load_main_module` and is the top-level module, ie. the one + /// passed as an argument to `JsRuntime::load_main_module`. + MainModule, + /// This kind is returned for all other modules during module load, that are + /// static imports. + Import, + /// This kind is returned for all modules that are loaded as a result of a + /// call to `import()` API (ie. top-level module as well as all its + /// dependencies, and any other `import()` calls from that load). + DynamicImport, +} + pub trait ModuleLoader { /// Returns an absolute URL. /// When implementing an spec-complaint VM, this should be exactly the @@ -210,11 +224,14 @@ pub trait ModuleLoader { /// /// `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, - _is_main: bool, + kind: ResolutionKind, ) -> Result<ModuleSpecifier, Error>; /// Given ModuleSpecifier, load its source code. @@ -256,7 +273,7 @@ impl ModuleLoader for NoopModuleLoader { &self, _specifier: &str, _referrer: &str, - _is_main: bool, + _kind: ResolutionKind, ) -> Result<ModuleSpecifier, Error> { Err(generic_error("Module loading is not supported")) } @@ -284,7 +301,7 @@ impl ModuleLoader for FsModuleLoader { &self, specifier: &str, referrer: &str, - _is_main: bool, + _kind: ResolutionKind, ) -> Result<ModuleSpecifier, Error> { Ok(resolve_import(specifier, referrer)?) } @@ -446,14 +463,16 @@ impl RecursiveModuleLoad { fn resolve_root(&self) -> Result<ModuleSpecifier, Error> { match self.init { LoadInit::Main(ref specifier) => { - self.loader.resolve(specifier, ".", true) + self + .loader + .resolve(specifier, ".", ResolutionKind::MainModule) } LoadInit::Side(ref specifier) => { - self.loader.resolve(specifier, ".", false) - } - LoadInit::DynamicImport(ref specifier, ref referrer, _) => { - self.loader.resolve(specifier, referrer, false) + self.loader.resolve(specifier, ".", ResolutionKind::Import) } + LoadInit::DynamicImport(ref specifier, ref referrer, _) => self + .loader + .resolve(specifier, referrer, ResolutionKind::DynamicImport), } } @@ -461,15 +480,25 @@ impl RecursiveModuleLoad { let op_state = self.op_state.clone(); let (module_specifier, maybe_referrer) = match self.init { LoadInit::Main(ref specifier) => { - let spec = self.loader.resolve(specifier, ".", true)?; + let spec = + self + .loader + .resolve(specifier, ".", ResolutionKind::MainModule)?; (spec, None) } LoadInit::Side(ref specifier) => { - let spec = self.loader.resolve(specifier, ".", false)?; + let spec = + self + .loader + .resolve(specifier, ".", ResolutionKind::Import)?; (spec, None) } LoadInit::DynamicImport(ref specifier, ref referrer, _) => { - let spec = self.loader.resolve(specifier, referrer, false)?; + let spec = self.loader.resolve( + specifier, + referrer, + ResolutionKind::DynamicImport, + )?; (spec, Some(referrer.to_string())) } }; @@ -537,6 +566,7 @@ impl RecursiveModuleLoad { self.is_currently_loading_main_module(), &module_source.module_url_found, &module_source.code, + self.is_dynamic_import(), )? } ModuleType::Json => self.module_map_rc.borrow_mut().new_json_module( @@ -868,6 +898,7 @@ impl ModuleMap { main: bool, name: &str, source: &[u8], + is_dynamic_import: bool, ) -> Result<ModuleId, ModuleError> { let name_str = v8::String::new(scope, name).unwrap(); let source_str = @@ -918,11 +949,18 @@ impl ModuleMap { return Err(ModuleError::Exception(exception)); } - let module_specifier = - match self.loader.resolve(&import_specifier, name, false) { - Ok(s) => s, - Err(e) => return Err(ModuleError::Other(e)), - }; + let module_specifier = match self.loader.resolve( + &import_specifier, + name, + if is_dynamic_import { + ResolutionKind::DynamicImport + } else { + ResolutionKind::Import + }, + ) { + Ok(s) => s, + Err(e) => return Err(ModuleError::Other(e)), + }; let asserted_module_type = get_asserted_module_type_from_assertions(&assertions); let request = ModuleRequest { @@ -1082,10 +1120,11 @@ impl ModuleMap { .borrow_mut() .dynamic_import_map .insert(load.id, resolver_handle); - let resolve_result = module_map_rc - .borrow() - .loader - .resolve(specifier, referrer, false); + let resolve_result = module_map_rc.borrow().loader.resolve( + specifier, + referrer, + ResolutionKind::DynamicImport, + ); let fut = match resolve_result { Ok(module_specifier) => { if module_map_rc @@ -1121,7 +1160,7 @@ impl ModuleMap { ) -> Option<v8::Local<'s, v8::Module>> { let resolved_specifier = self .loader - .resolve(specifier, referrer, false) + .resolve(specifier, referrer, ResolutionKind::Import) .expect("Module should have been already resolved"); let module_type = @@ -1332,7 +1371,7 @@ import "/a.js"; &self, specifier: &str, referrer: &str, - _is_root: bool, + _kind: ResolutionKind, ) -> Result<ModuleSpecifier, Error> { let referrer = if referrer == "." { "file:///" @@ -1448,7 +1487,7 @@ import "/a.js"; &self, specifier: &str, referrer: &str, - _is_main: bool, + _kind: ResolutionKind, ) -> Result<ModuleSpecifier, Error> { self.count.fetch_add(1, Ordering::Relaxed); assert_eq!(specifier, "./b.js"); @@ -1521,6 +1560,7 @@ import "/a.js"; let control = 42; Deno.core.ops.op_test(control); "#, + false, ) .unwrap(); @@ -1540,6 +1580,7 @@ import "/a.js"; false, "file:///b.js", b"export function b() { return 'b' }", + false, ) .unwrap(); let imports = module_map.get_requested_modules(mod_b).unwrap(); @@ -1570,7 +1611,7 @@ import "/a.js"; &self, specifier: &str, referrer: &str, - _is_main: bool, + _kind: ResolutionKind, ) -> Result<ModuleSpecifier, Error> { self.count.fetch_add(1, Ordering::Relaxed); assert_eq!(specifier, "./b.json"); @@ -1627,6 +1668,7 @@ import "/a.js"; assert(jsonData.a == "b"); assert(jsonData.c.d == 10); "#, + false, ) .unwrap(); @@ -1673,7 +1715,7 @@ import "/a.js"; &self, specifier: &str, referrer: &str, - _is_main: bool, + _kind: ResolutionKind, ) -> Result<ModuleSpecifier, Error> { self.count.fetch_add(1, Ordering::Relaxed); assert_eq!(specifier, "/foo.js"); @@ -1733,7 +1775,7 @@ import "/a.js"; &self, specifier: &str, referrer: &str, - _is_main: bool, + _kind: ResolutionKind, ) -> Result<ModuleSpecifier, Error> { let c = self.resolve_count.fetch_add(1, Ordering::Relaxed); assert!(c < 7); @@ -1866,7 +1908,7 @@ import "/a.js"; &self, specifier: &str, referrer: &str, - _is_main: bool, + _kind: ResolutionKind, ) -> Result<ModuleSpecifier, Error> { self.resolve_count.fetch_add(1, Ordering::Relaxed); let s = resolve_import(specifier, referrer).unwrap(); @@ -2242,7 +2284,7 @@ if (import.meta.url != 'file:///main_with_code.js') throw Error(); &self, specifier: &str, referrer: &str, - _is_main: bool, + _kind: ResolutionKind, ) -> Result<ModuleSpecifier, Error> { let s = resolve_import(specifier, referrer).unwrap(); Ok(s) |