From 636352e0ca1e611c7673f2ab68538e1ddb2dc5b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Tue, 10 Jan 2023 14:35:44 +0100 Subject: 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. --- cli/node/mod.rs | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) (limited to 'cli/node') diff --git a/cli/node/mod.rs b/cli/node/mod.rs index e6cc22255..aed639bc4 100644 --- a/cli/node/mod.rs +++ b/cli/node/mod.rs @@ -25,12 +25,14 @@ use deno_runtime::deno_node::package_imports_resolve; use deno_runtime::deno_node::package_resolve; use deno_runtime::deno_node::path_to_declaration_path; use deno_runtime::deno_node::NodeModuleKind; +use deno_runtime::deno_node::NodePermissions; use deno_runtime::deno_node::NodeResolutionMode; use deno_runtime::deno_node::PackageJson; use deno_runtime::deno_node::PathClean; use deno_runtime::deno_node::RequireNpmResolver; use deno_runtime::deno_node::DEFAULT_CONDITIONS; use deno_runtime::deno_node::NODE_GLOBAL_THIS_NAME; +use deno_runtime::permissions::PermissionsContainer; use once_cell::sync::Lazy; use regex::Regex; @@ -440,6 +442,7 @@ pub fn node_resolve( referrer: &ModuleSpecifier, mode: NodeResolutionMode, npm_resolver: &dyn RequireNpmResolver, + permissions: &mut dyn NodePermissions, ) -> Result, AnyError> { // Note: if we are here, then the referrer is an esm module // TODO(bartlomieju): skipped "policy" part as we don't plan to support it @@ -481,6 +484,7 @@ pub fn node_resolve( DEFAULT_CONDITIONS, mode, npm_resolver, + permissions, )?; let url = match url { Some(url) => url, @@ -510,6 +514,7 @@ pub fn node_resolve_npm_reference( reference: &NpmPackageReference, mode: NodeResolutionMode, npm_resolver: &NpmPackageResolver, + permissions: &mut dyn NodePermissions, ) -> Result, AnyError> { let package_folder = npm_resolver.resolve_package_folder_from_deno_module(&reference.req)?; @@ -525,6 +530,7 @@ pub fn node_resolve_npm_reference( DEFAULT_CONDITIONS, mode, npm_resolver, + permissions, ) .with_context(|| { format!("Error resolving package config for '{}'", reference) @@ -553,11 +559,13 @@ pub fn node_resolve_binary_export( pkg_req: &NpmPackageReq, bin_name: Option<&str>, npm_resolver: &NpmPackageResolver, + permissions: &mut dyn NodePermissions, ) -> Result { let package_folder = npm_resolver.resolve_package_folder_from_deno_module(pkg_req)?; let package_json_path = package_folder.join("package.json"); - let package_json = PackageJson::load(npm_resolver, package_json_path)?; + let package_json = + PackageJson::load(npm_resolver, permissions, package_json_path)?; let bin = match &package_json.bin { Some(bin) => bin, None => bail!( @@ -665,11 +673,12 @@ fn package_config_resolve( conditions: &[&str], mode: NodeResolutionMode, npm_resolver: &dyn RequireNpmResolver, + permissions: &mut dyn NodePermissions, ) -> Result, AnyError> { let package_json_path = package_dir.join("package.json"); let referrer = ModuleSpecifier::from_directory_path(package_dir).unwrap(); let package_config = - PackageJson::load(npm_resolver, package_json_path.clone())?; + PackageJson::load(npm_resolver, permissions, package_json_path.clone())?; if let Some(exports) = &package_config.exports { let result = package_exports_resolve( &package_json_path, @@ -680,6 +689,7 @@ fn package_config_resolve( conditions, mode, npm_resolver, + permissions, ); match result { Ok(found) => return Ok(Some(found)), @@ -712,7 +722,11 @@ pub fn url_to_node_resolution( if url_str.starts_with("http") { Ok(NodeResolution::Esm(url)) } else if url_str.ends_with(".js") || url_str.ends_with(".d.ts") { - let package_config = get_closest_package_json(&url, npm_resolver)?; + let package_config = get_closest_package_json( + &url, + npm_resolver, + &mut PermissionsContainer::allow_all(), + )?; if package_config.typ == "module" { Ok(NodeResolution::Esm(url)) } else { @@ -786,6 +800,7 @@ fn module_resolve( conditions: &[&str], mode: NodeResolutionMode, npm_resolver: &dyn RequireNpmResolver, + permissions: &mut dyn NodePermissions, ) -> Result, AnyError> { // note: if we're here, the referrer is an esm module let url = if should_be_treated_as_relative_or_absolute_path(specifier) { @@ -811,6 +826,7 @@ fn module_resolve( conditions, mode, npm_resolver, + permissions, ) .map(|p| ModuleSpecifier::from_file_path(p).unwrap())?, ) @@ -824,6 +840,7 @@ fn module_resolve( conditions, mode, npm_resolver, + permissions, )? .map(|p| ModuleSpecifier::from_file_path(p).unwrap()) }; @@ -879,6 +896,7 @@ pub fn translate_cjs_to_esm( media_type: MediaType, npm_resolver: &NpmPackageResolver, node_analysis_cache: &NodeAnalysisCache, + permissions: &mut dyn NodePermissions, ) -> Result { fn perform_cjs_analysis( analysis_cache: &NodeAnalysisCache, @@ -956,6 +974,7 @@ pub fn translate_cjs_to_esm( &["deno", "require", "default"], NodeResolutionMode::Execution, npm_resolver, + permissions, )?; let reexport_specifier = ModuleSpecifier::from_file_path(resolved_reexport).unwrap(); @@ -1027,6 +1046,7 @@ fn resolve( conditions: &[&str], mode: NodeResolutionMode, npm_resolver: &dyn RequireNpmResolver, + permissions: &mut dyn NodePermissions, ) -> Result { if specifier.starts_with('/') { todo!(); @@ -1056,7 +1076,7 @@ fn resolve( let package_json_path = module_dir.join("package.json"); if package_json_path.exists() { let package_json = - PackageJson::load(npm_resolver, package_json_path.clone())?; + PackageJson::load(npm_resolver, permissions, package_json_path.clone())?; if let Some(exports) = &package_json.exports { return package_exports_resolve( @@ -1068,6 +1088,7 @@ fn resolve( conditions, mode, npm_resolver, + permissions, ); } @@ -1080,7 +1101,7 @@ fn resolve( let package_json_path = d.join("package.json"); if package_json_path.exists() { let package_json = - PackageJson::load(npm_resolver, package_json_path)?; + PackageJson::load(npm_resolver, permissions, package_json_path)?; if let Some(main) = package_json.main(NodeModuleKind::Cjs) { return Ok(d.join(main).clean()); } -- cgit v1.2.3