Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add --allow-import flag #25469

Merged
merged 43 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
fbb40ad
feat: Add `--allow-imports` flag
bartlomieju Sep 5, 2024
8170f32
actually make it work for dynamic imports
bartlomieju Sep 5, 2024
9f947cc
merge in main
dsherret Sep 17, 2024
ef0ebc9
Merge branch 'main' into allow_imports
dsherret Sep 19, 2024
d040407
updates
dsherret Sep 19, 2024
ba90b1a
Merge branch 'main' into allow_imports
dsherret Sep 21, 2024
9d42419
Starting to use permissions container more
dsherret Sep 22, 2024
eaff962
Starting to use permissions container more
dsherret Sep 22, 2024
05a39e9
Saving for revert
dsherret Sep 22, 2024
f99c39c
Revert "Saving for revert"
dsherret Sep 22, 2024
282dab6
add permissions for check and cache. Allow reading from the file syst…
dsherret Sep 22, 2024
479d046
Start adding tests and fix it not working for run
dsherret Sep 22, 2024
2b58d88
fix up flags
dsherret Sep 22, 2024
b0c74e0
add 0.0.0.0
dsherret Sep 22, 2024
9e48c18
test jsr_host_from_url
dsherret Sep 22, 2024
240e2c0
add gist.githubusercontent.com
dsherret Sep 22, 2024
3f88938
update test because localhost is allowed by default (though maybe it …
dsherret Sep 22, 2024
43f4624
improve naming
dsherret Sep 22, 2024
4e6b5d2
Merge branch 'main' into allow_imports
dsherret Sep 23, 2024
5630383
Clippy
dsherret Sep 24, 2024
d90489f
Merge branch 'main' into allow_imports
dsherret Sep 24, 2024
b458c3d
Fixing up more tests
dsherret Sep 24, 2024
3927928
Merge branch 'main' into allow_imports
dsherret Sep 25, 2024
1787bf7
Checking in before revert
dsherret Sep 25, 2024
9e53639
Fix worker permissions and update expectations
dsherret Sep 25, 2024
b326096
finish
dsherret Sep 25, 2024
134718f
clippy
dsherret Sep 25, 2024
a232f95
Start removing localhost as allowed by default
dsherret Sep 25, 2024
abb5de4
Merge branch 'main' into allow_imports
dsherret Sep 25, 2024
f1282e5
fix run tests
dsherret Sep 25, 2024
9a164ec
fix lsp caching
dsherret Sep 25, 2024
1124b45
Update and fix more tests
dsherret Sep 25, 2024
2dca777
more test fixes
dsherret Sep 25, 2024
f0d1c05
more fixes
dsherret Sep 25, 2024
d315bf2
Do not load non-jsr remote modules in `deno publish`
dsherret Sep 25, 2024
02120ac
fix publish tests
dsherret Sep 25, 2024
65e1e96
add tests for doc
dsherret Sep 25, 2024
4facd74
fix remaining tests
dsherret Sep 25, 2024
f4b41c5
self review
dsherret Sep 25, 2024
41c63f2
improve help output
dsherret Sep 25, 2024
79b9992
fix check_specifiers test
dsherret Sep 26, 2024
d7e1744
review and update linux test
dsherret Sep 26, 2024
c66b814
fix failing windows test
dsherret Sep 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ deno_cache_dir = { workspace = true }
deno_config = { version = "=0.35.0", features = ["workspace", "sync"] }
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
deno_doc = { version = "0.148.0", features = ["html", "syntect"] }
deno_graph = { version = "=0.82.2" }
deno_graph = { version = "=0.82.3" }
deno_lint = { version = "=0.67.0", features = ["docs"] }
deno_lockfile.workspace = true
deno_npm = "=0.25.2"
Expand Down
254 changes: 204 additions & 50 deletions cli/args/flags.rs

Large diffs are not rendered by default.

102 changes: 67 additions & 35 deletions cli/args/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,7 @@ pub struct CliOptions {
// application need not concern itself with, so keep these private
flags: Arc<Flags>,
initial_cwd: PathBuf,
main_module_cell: std::sync::OnceLock<Result<ModuleSpecifier, AnyError>>,
maybe_node_modules_folder: Option<PathBuf>,
npmrc: Arc<ResolvedNpmRc>,
maybe_lockfile: Option<Arc<CliLockfile>>,
Expand Down Expand Up @@ -825,6 +826,7 @@ impl CliOptions {
npmrc,
maybe_node_modules_folder,
overrides: Default::default(),
main_module_cell: std::sync::OnceLock::new(),
start_dir,
deno_dir_provider,
})
Expand Down Expand Up @@ -1105,40 +1107,43 @@ impl CliOptions {
self.flags.env_file.as_ref()
}

pub fn resolve_main_module(&self) -> Result<ModuleSpecifier, AnyError> {
let main_module = match &self.flags.subcommand {
DenoSubcommand::Compile(compile_flags) => {
resolve_url_or_path(&compile_flags.source_file, self.initial_cwd())?
}
DenoSubcommand::Eval(_) => {
resolve_url_or_path("./$deno$eval.ts", self.initial_cwd())?
}
DenoSubcommand::Repl(_) => {
resolve_url_or_path("./$deno$repl.ts", self.initial_cwd())?
}
DenoSubcommand::Run(run_flags) => {
if run_flags.is_stdin() {
std::env::current_dir()
.context("Unable to get CWD")
.and_then(|cwd| {
resolve_url_or_path("./$deno$stdin.ts", &cwd)
.map_err(AnyError::from)
})?
} else if NpmPackageReqReference::from_str(&run_flags.script).is_ok() {
ModuleSpecifier::parse(&run_flags.script)?
} else {
resolve_url_or_path(&run_flags.script, self.initial_cwd())?
}
}
DenoSubcommand::Serve(run_flags) => {
resolve_url_or_path(&run_flags.script, self.initial_cwd())?
}
_ => {
bail!("No main module.")
}
};
pub fn resolve_main_module(&self) -> Result<&ModuleSpecifier, AnyError> {
self
.main_module_cell
.get_or_init(|| {
let main_module = match &self.flags.subcommand {
DenoSubcommand::Compile(compile_flags) => {
resolve_url_or_path(&compile_flags.source_file, self.initial_cwd())?
}
DenoSubcommand::Eval(_) => {
resolve_url_or_path("./$deno$eval.ts", self.initial_cwd())?
}
DenoSubcommand::Repl(_) => {
resolve_url_or_path("./$deno$repl.ts", self.initial_cwd())?
}
DenoSubcommand::Run(run_flags) => {
if run_flags.is_stdin() {
resolve_url_or_path("./$deno$stdin.ts", self.initial_cwd())?
} else if NpmPackageReqReference::from_str(&run_flags.script)
.is_ok()
{
ModuleSpecifier::parse(&run_flags.script)?
} else {
resolve_url_or_path(&run_flags.script, self.initial_cwd())?
}
}
DenoSubcommand::Serve(run_flags) => {
resolve_url_or_path(&run_flags.script, self.initial_cwd())?
}
_ => {
bail!("No main module.")
}
};

Ok(main_module)
Ok(main_module)
})
.as_ref()
.map_err(|err| deno_core::anyhow::anyhow!("{}", err))
}

pub fn resolve_file_header_overrides(
Expand All @@ -1159,7 +1164,7 @@ impl CliOptions {
(maybe_main_specifier, maybe_content_type)
{
HashMap::from([(
main_specifier,
main_specifier.clone(),
HashMap::from([("content-type".to_string(), content_type.to_string())]),
)])
} else {
Expand Down Expand Up @@ -1480,7 +1485,34 @@ impl CliOptions {
}

pub fn permissions_options(&self) -> PermissionsOptions {
self.flags.permissions.to_options()
fn files_to_urls(files: &[String]) -> Vec<Cow<'_, Url>> {
files
.iter()
.filter_map(|f| Url::parse(f).ok().map(Cow::Owned))
.collect()
}

// get a list of urls to imply for --allow-import
let cli_arg_urls = self
.resolve_main_module()
.ok()
.map(|url| vec![Cow::Borrowed(url)])
.or_else(|| match &self.flags.subcommand {
DenoSubcommand::Cache(cache_flags) => {
Some(files_to_urls(&cache_flags.files))
}
DenoSubcommand::Check(check_flags) => {
Some(files_to_urls(&check_flags.files))
}
DenoSubcommand::Install(InstallFlags {
kind: InstallKind::Global(flags),
}) => Url::parse(&flags.module_url)
.ok()
.map(|url| vec![Cow::Owned(url)]),
_ => None,
})
.unwrap_or_default();
self.flags.permissions.to_options(&cli_arg_urls)
}

pub fn reload_flag(&self) -> bool {
Expand Down
42 changes: 35 additions & 7 deletions cli/cache/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.

use crate::args::jsr_url;
use crate::args::CacheSetting;
use crate::errors::get_error_class_name;
use crate::file_fetcher::FetchNoFollowOptions;
use crate::file_fetcher::FetchOptions;
use crate::file_fetcher::FetchPermissionsOption;
use crate::file_fetcher::FetchPermissionsOptionRef;
use crate::file_fetcher::FileFetcher;
use crate::file_fetcher::FileOrRedirect;
use crate::npm::CliNpmResolver;
Expand All @@ -19,6 +20,7 @@ use deno_graph::source::CacheInfo;
use deno_graph::source::LoadFuture;
use deno_graph::source::LoadResponse;
use deno_graph::source::Loader;
use deno_runtime::deno_permissions::PermissionsContainer;
use std::collections::HashMap;
use std::path::Path;
use std::path::PathBuf;
Expand Down Expand Up @@ -104,6 +106,13 @@ pub type LocalLspHttpCache =
deno_cache_dir::LocalLspHttpCache<RealDenoCacheEnv>;
pub use deno_cache_dir::HttpCache;

pub struct FetchCacherOptions {
pub file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>,
pub permissions: PermissionsContainer,
/// If we're publishing for `deno publish`.
pub is_deno_publish: bool,
}

/// A "wrapper" for the FileFetcher and DiskCache for the Deno CLI that provides
/// a concise interface to the DENO_DIR when building module graphs.
pub struct FetchCacher {
Expand All @@ -112,26 +121,27 @@ pub struct FetchCacher {
global_http_cache: Arc<GlobalHttpCache>,
npm_resolver: Arc<dyn CliNpmResolver>,
module_info_cache: Arc<ModuleInfoCache>,
permissions: FetchPermissionsOption,
permissions: PermissionsContainer,
cache_info_enabled: bool,
is_deno_publish: bool,
}

impl FetchCacher {
pub fn new(
file_fetcher: Arc<FileFetcher>,
file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>,
global_http_cache: Arc<GlobalHttpCache>,
npm_resolver: Arc<dyn CliNpmResolver>,
module_info_cache: Arc<ModuleInfoCache>,
permissions: FetchPermissionsOption,
options: FetchCacherOptions,
) -> Self {
Self {
file_fetcher,
file_header_overrides,
global_http_cache,
npm_resolver,
module_info_cache,
permissions,
file_header_overrides: options.file_header_overrides,
permissions: options.permissions,
is_deno_publish: options.is_deno_publish,
cache_info_enabled: false,
}
}
Expand Down Expand Up @@ -208,10 +218,24 @@ impl Loader for FetchCacher {
}
}

if self.is_deno_publish
&& matches!(specifier.scheme(), "http" | "https")
&& !specifier.as_str().starts_with(jsr_url().as_str())
{
// mark non-JSR remote modules as external so we don't need --allow-import
// permissions as these will error out later when publishing
return Box::pin(futures::future::ready(Ok(Some(
LoadResponse::External {
specifier: specifier.clone(),
},
))));
}

let file_fetcher = self.file_fetcher.clone();
let file_header_overrides = self.file_header_overrides.clone();
let permissions = self.permissions.clone();
let specifier = specifier.clone();
let is_statically_analyzable = !options.was_dynamic_root;

async move {
let maybe_cache_setting = match options.cache_setting {
Expand All @@ -230,7 +254,11 @@ impl Loader for FetchCacher {
.fetch_no_follow_with_options(FetchNoFollowOptions {
fetch_options: FetchOptions {
specifier: &specifier,
permissions: permissions.as_ref(),
permissions: if is_statically_analyzable {
FetchPermissionsOptionRef::StaticContainer(&permissions)
} else {
FetchPermissionsOptionRef::DynamicContainer(&permissions)
},
maybe_accept: None,
maybe_cache_setting: maybe_cache_setting.as_ref(),
},
Expand Down
25 changes: 17 additions & 8 deletions cli/factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ struct CliFactoryServices {
node_resolver: Deferred<Arc<NodeResolver>>,
npm_resolver: Deferred<Arc<dyn CliNpmResolver>>,
permission_desc_parser: Deferred<Arc<RuntimePermissionDescriptorParser>>,
root_permissions_container: Deferred<PermissionsContainer>,
sloppy_imports_resolver: Deferred<Option<Arc<SloppyImportsResolver>>>,
text_only_progress_bar: Deferred<ProgressBar>,
type_checker: Deferred<Arc<TypeChecker>>,
Expand Down Expand Up @@ -626,6 +627,7 @@ impl CliFactory {
self.maybe_file_watcher_reporter().clone(),
self.file_fetcher()?.clone(),
self.global_http_cache()?.clone(),
self.root_permissions_container()?.clone(),
)))
})
.await
Expand Down Expand Up @@ -659,6 +661,7 @@ impl CliFactory {
Ok(Arc::new(MainModuleGraphContainer::new(
self.cli_options()?.clone(),
self.module_load_preparer().await?.clone(),
self.root_permissions_container()?.clone(),
)))
})
.await
Expand Down Expand Up @@ -755,15 +758,20 @@ impl CliFactory {
))
}

pub fn create_permissions_container(
pub fn root_permissions_container(
&self,
) -> Result<PermissionsContainer, AnyError> {
let desc_parser = self.permission_desc_parser()?.clone();
let permissions = Permissions::from_options(
desc_parser.as_ref(),
&self.cli_options()?.permissions_options(),
)?;
Ok(PermissionsContainer::new(desc_parser, permissions))
) -> Result<&PermissionsContainer, AnyError> {
self
.services
.root_permissions_container
.get_or_try_init(|| {
let desc_parser = self.permission_desc_parser()?.clone();
let permissions = Permissions::from_options(
desc_parser.as_ref(),
&self.cli_options()?.permissions_options(),
)?;
Ok(PermissionsContainer::new(desc_parser, permissions))
})
}

pub async fn create_cli_main_worker_factory(
Expand Down Expand Up @@ -816,6 +824,7 @@ impl CliFactory {
npm_resolver.clone(),
self.permission_desc_parser()?.clone(),
self.root_cert_store_provider().clone(),
self.root_permissions_container()?.clone(),
StorageKeyResolver::from_options(cli_options),
cli_options.sub_command().clone(),
self.create_cli_main_worker_options()?,
Expand Down
Loading
Loading