1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-21 15:04:11 -05:00

feat: add --allow-import flag (#25469)

This replaces `--allow-net` for import permissions and makes the
security sandbox stricter by also checking permissions for statically
analyzable imports.

By default, this has a value of
`--allow-import=deno.land:443,jsr.io:443,esm.sh:443,raw.githubusercontent.com:443,gist.githubusercontent.com:443`,
but that can be overridden by providing a different set of hosts.

Additionally, when no value is provided, import permissions are inferred
from the CLI arguments so the following works because
`fresh.deno.dev:443` will be added to the list of allowed imports:

```ts
deno run -A -r https://fresh.deno.dev
```

---------

Co-authored-by: David Sherret <dsherret@gmail.com>
This commit is contained in:
Bartek Iwańczuk 2024-09-26 02:50:54 +01:00 committed by GitHub
parent 05415bb9de
commit 5504acea67
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
507 changed files with 1116 additions and 483 deletions

8
Cargo.lock generated
View file

@ -1584,9 +1584,9 @@ dependencies = [
[[package]] [[package]]
name = "deno_graph" name = "deno_graph"
version = "0.82.2" version = "0.82.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9328b62ffc7e806f1c92fd7a22e4ff3046fcb53f2d46e3e1297482b2c4c2bb9d" checksum = "938ed2efa1dd9fdcceeebc169b2b7910506b8dacc992cfdcffd84aa6a3eb8db0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -8119,9 +8119,9 @@ dependencies = [
[[package]] [[package]]
name = "webpki-root-certs" name = "webpki-root-certs"
version = "0.26.5" version = "0.26.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6d93b773107ba49bc84dd3b241e019c702d886fd5c457defe2ea8b1123a5dcd" checksum = "e8c6dfa3ac045bc517de14c7b1384298de1dbd229d38e08e169d9ae8c170937c"
dependencies = [ dependencies = [
"rustls-pki-types", "rustls-pki-types",
] ]

View file

@ -68,7 +68,7 @@ deno_cache_dir = { workspace = true }
deno_config = { version = "=0.35.0", features = ["workspace", "sync"] } deno_config = { version = "=0.35.0", features = ["workspace", "sync"] }
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] } deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
deno_doc = { version = "0.148.0", features = ["html", "syntect"] } 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_lint = { version = "=0.67.0", features = ["docs"] }
deno_lockfile.workspace = true deno_lockfile.workspace = true
deno_npm = "=0.25.2" deno_npm = "=0.25.2"

View file

@ -1,5 +1,6 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use std::borrow::Cow;
use std::collections::HashSet; use std::collections::HashSet;
use std::env; use std::env;
use std::ffi::OsString; use std::ffi::OsString;
@ -44,6 +45,7 @@ use crate::args::resolve_no_prompt;
use crate::util::fs::canonicalize_path; use crate::util::fs::canonicalize_path;
use super::flags_net; use super::flags_net;
use super::jsr_url;
#[derive(Clone, Debug, Default, Eq, PartialEq)] #[derive(Clone, Debug, Default, Eq, PartialEq)]
pub enum ConfigFlag { pub enum ConfigFlag {
@ -639,6 +641,7 @@ pub struct PermissionFlags {
pub allow_write: Option<Vec<String>>, pub allow_write: Option<Vec<String>>,
pub deny_write: Option<Vec<String>>, pub deny_write: Option<Vec<String>>,
pub no_prompt: bool, pub no_prompt: bool,
pub allow_import: Option<Vec<String>>,
} }
impl PermissionFlags { impl PermissionFlags {
@ -658,9 +661,10 @@ impl PermissionFlags {
|| self.deny_sys.is_some() || self.deny_sys.is_some()
|| self.allow_write.is_some() || self.allow_write.is_some()
|| self.deny_write.is_some() || self.deny_write.is_some()
|| self.allow_import.is_some()
} }
pub fn to_options(&self) -> PermissionsOptions { pub fn to_options(&self, cli_arg_urls: &[Cow<Url>]) -> PermissionsOptions {
fn handle_allow<T: Default>( fn handle_allow<T: Default>(
allow_all: bool, allow_all: bool,
value: Option<T>, value: Option<T>,
@ -673,6 +677,41 @@ impl PermissionFlags {
} }
} }
fn handle_imports(
cli_arg_urls: &[Cow<Url>],
imports: Option<Vec<String>>,
) -> Option<Vec<String>> {
if imports.is_some() {
return imports;
}
let builtin_allowed_import_hosts = [
"deno.land:443",
"esm.sh:443",
"jsr.io:443",
"raw.githubusercontent.com:443",
"gist.githubusercontent.com:443",
];
let mut imports =
Vec::with_capacity(builtin_allowed_import_hosts.len() + 1);
imports
.extend(builtin_allowed_import_hosts.iter().map(|s| s.to_string()));
// also add the JSR_URL env var
if let Some(jsr_host) = allow_import_host_from_url(jsr_url()) {
imports.push(jsr_host);
}
// include the cli arg urls
for url in cli_arg_urls {
if let Some(host) = allow_import_host_from_url(url) {
imports.push(host);
}
}
Some(imports)
}
PermissionsOptions { PermissionsOptions {
allow_all: self.allow_all, allow_all: self.allow_all,
allow_env: handle_allow(self.allow_all, self.allow_env.clone()), allow_env: handle_allow(self.allow_all, self.allow_env.clone()),
@ -689,11 +728,33 @@ impl PermissionFlags {
deny_sys: self.deny_sys.clone(), deny_sys: self.deny_sys.clone(),
allow_write: handle_allow(self.allow_all, self.allow_write.clone()), allow_write: handle_allow(self.allow_all, self.allow_write.clone()),
deny_write: self.deny_write.clone(), deny_write: self.deny_write.clone(),
allow_import: handle_imports(
cli_arg_urls,
handle_allow(self.allow_all, self.allow_import.clone()),
),
prompt: !resolve_no_prompt(self), prompt: !resolve_no_prompt(self),
} }
} }
} }
/// Gets the --allow-import host from the provided url
fn allow_import_host_from_url(url: &Url) -> Option<String> {
let host = url.host()?;
if let Some(port) = url.port() {
Some(format!("{}:{}", host, port))
} else {
use deno_core::url::Host::*;
match host {
Domain(domain) if domain == "jsr.io" && url.scheme() == "https" => None,
_ => match url.scheme() {
"https" => Some(format!("{}:443", host)),
"http" => Some(format!("{}:80", host)),
_ => None,
},
}
}
}
fn join_paths(allowlist: &[String], d: &str) -> String { fn join_paths(allowlist: &[String], d: &str) -> String {
allowlist allowlist
.iter() .iter()
@ -881,6 +942,17 @@ impl Flags {
_ => {} _ => {}
} }
match &self.permissions.allow_import {
Some(allowlist) if allowlist.is_empty() => {
args.push("--allow-import".to_string());
}
Some(allowlist) => {
let s = format!("--allow-import={}", allowlist.join(","));
args.push(s);
}
_ => {}
}
args args
} }
@ -991,6 +1063,7 @@ impl Flags {
self.permissions.allow_write = None; self.permissions.allow_write = None;
self.permissions.allow_sys = None; self.permissions.allow_sys = None;
self.permissions.allow_ffi = None; self.permissions.allow_ffi = None;
self.permissions.allow_import = None;
} }
pub fn resolve_watch_exclude_set( pub fn resolve_watch_exclude_set(
@ -1707,6 +1780,7 @@ Future runs of this module will trigger no downloads or compilation unless --rel
) )
.arg(frozen_lockfile_arg()) .arg(frozen_lockfile_arg())
.arg(allow_scripts_arg()) .arg(allow_scripts_arg())
.arg(allow_import_arg())
}) })
} }
@ -1766,6 +1840,7 @@ Unless --reload is specified, this command will not re-download already cached d
.required_unless_present("help") .required_unless_present("help")
.value_hint(ValueHint::FilePath), .value_hint(ValueHint::FilePath),
) )
.arg(allow_import_arg())
} }
) )
} }
@ -1994,6 +2069,7 @@ Show documentation for runtime built-ins:
.arg(no_lock_arg()) .arg(no_lock_arg())
.arg(no_npm_arg()) .arg(no_npm_arg())
.arg(no_remote_arg()) .arg(no_remote_arg())
.arg(allow_import_arg())
.arg( .arg(
Arg::new("json") Arg::new("json")
.long("json") .long("json")
@ -2358,6 +2434,7 @@ The following information is shown:
.help("UNSTABLE: Outputs the information in JSON format") .help("UNSTABLE: Outputs the information in JSON format")
.action(ArgAction::SetTrue), .action(ArgAction::SetTrue),
)) ))
.arg(allow_import_arg())
} }
fn install_subcommand() -> Command { fn install_subcommand() -> Command {
@ -3158,6 +3235,9 @@ fn permission_args(app: Command, requires: Option<&'static str>) -> Command {
<p(245)>--allow-read | --allow-read="/etc,/var/log.txt"</> <p(245)>--allow-read | --allow-read="/etc,/var/log.txt"</>
<g>-W, --allow-write[=<<PATH>...]</> Allow file system write access. Optionally specify allowed paths. <g>-W, --allow-write[=<<PATH>...]</> Allow file system write access. Optionally specify allowed paths.
<p(245)>--allow-write | --allow-write="/etc,/var/log.txt"</> <p(245)>--allow-write | --allow-write="/etc,/var/log.txt"</>
<g>-I, --allow-import[=<<IP_OR_HOSTNAME>...]</> Allow importing from remote hosts. Optionally specify allowed IP addresses and host names, with ports as necessary.
Default value: <p(245)>deno.land:443,jsr.io:443,esm.sh:443,raw.githubusercontent.com:443,user.githubusercontent.com:443</>
<p(245)>--allow-import | --allow-import="example.com,github.com"</>
<g>-N, --allow-net[=<<IP_OR_HOSTNAME>...]</> Allow network access. Optionally specify allowed IP addresses and host names, with ports as necessary. <g>-N, --allow-net[=<<IP_OR_HOSTNAME>...]</> Allow network access. Optionally specify allowed IP addresses and host names, with ports as necessary.
<p(245)>--allow-net | --allow-net="localhost:8080,deno.land"</> <p(245)>--allow-net | --allow-net="localhost:8080,deno.land"</>
<g>-E, --allow-env[=<<VARIABLE_NAME>...]</> Allow access to environment variables. Optionally specify accessible environment variables. <g>-E, --allow-env[=<<VARIABLE_NAME>...]</> Allow access to environment variables. Optionally specify accessible environment variables.
@ -3185,13 +3265,7 @@ fn permission_args(app: Command, requires: Option<&'static str>) -> Command {
"#)) "#))
.arg( .arg(
{ {
let mut arg = Arg::new("allow-all") let mut arg = allow_all_arg().hide(true);
.short('A')
.long("allow-all")
.action(ArgAction::SetTrue)
.help("Allow all permissions")
.hide(true)
;
if let Some(requires) = requires { if let Some(requires) = requires {
arg = arg.requires(requires) arg = arg.requires(requires)
} }
@ -3509,6 +3583,26 @@ fn permission_args(app: Command, requires: Option<&'static str>) -> Command {
arg arg
} }
) )
.arg(
{
let mut arg = allow_import_arg().hide(true);
if let Some(requires) = requires {
// allow this for install --global
if requires != "global" {
arg = arg.requires(requires)
}
}
arg
}
)
}
fn allow_all_arg() -> Arg {
Arg::new("allow-all")
.short('A')
.long("allow-all")
.action(ArgAction::SetTrue)
.help("Allow all permissions")
} }
fn runtime_args( fn runtime_args(
@ -3537,6 +3631,20 @@ fn runtime_args(
.arg(strace_ops_arg()) .arg(strace_ops_arg())
} }
fn allow_import_arg() -> Arg {
Arg::new("allow-import")
.long("allow-import")
.short('I')
.num_args(0..)
.use_value_delimiter(true)
.require_equals(true)
.value_name("IP_OR_HOSTNAME")
.help(cstr!(
"Allow importing from remote hosts. Optionally specify allowed IP addresses and host names, with ports as necessary. Default value: <p(245)>deno.land:443,jsr.io:443,esm.sh:443,raw.githubusercontent.com:443,user.githubusercontent.com:443</>"
))
.value_parser(flags_net::validator)
}
fn inspect_args(app: Command) -> Command { fn inspect_args(app: Command) -> Command {
app app
.arg( .arg(
@ -4174,6 +4282,7 @@ fn cache_parse(
unstable_args_parse(flags, matches, UnstableArgsConfig::ResolutionOnly); unstable_args_parse(flags, matches, UnstableArgsConfig::ResolutionOnly);
frozen_lockfile_arg_parse(flags, matches); frozen_lockfile_arg_parse(flags, matches);
allow_scripts_arg_parse(flags, matches)?; allow_scripts_arg_parse(flags, matches)?;
allow_import_parse(flags, matches);
let files = matches.remove_many::<String>("file").unwrap().collect(); let files = matches.remove_many::<String>("file").unwrap().collect();
flags.subcommand = DenoSubcommand::Cache(CacheFlags { files }); flags.subcommand = DenoSubcommand::Cache(CacheFlags { files });
Ok(()) Ok(())
@ -4195,6 +4304,7 @@ fn check_parse(
doc: matches.get_flag("doc"), doc: matches.get_flag("doc"),
doc_only: matches.get_flag("doc-only"), doc_only: matches.get_flag("doc-only"),
}); });
allow_import_parse(flags, matches);
Ok(()) Ok(())
} }
@ -4320,6 +4430,7 @@ fn doc_parse(
no_lock_arg_parse(flags, matches); no_lock_arg_parse(flags, matches);
no_npm_arg_parse(flags, matches); no_npm_arg_parse(flags, matches);
no_remote_arg_parse(flags, matches); no_remote_arg_parse(flags, matches);
allow_import_parse(flags, matches);
let source_files_val = matches.remove_many::<String>("source_file"); let source_files_val = matches.remove_many::<String>("source_file");
let source_files = if let Some(val) = source_files_val { let source_files = if let Some(val) = source_files_val {
@ -4460,6 +4571,7 @@ fn info_parse(
lock_args_parse(flags, matches); lock_args_parse(flags, matches);
no_remote_arg_parse(flags, matches); no_remote_arg_parse(flags, matches);
no_npm_arg_parse(flags, matches); no_npm_arg_parse(flags, matches);
allow_import_parse(flags, matches);
let json = matches.get_flag("json"); let json = matches.get_flag("json");
flags.subcommand = DenoSubcommand::Info(InfoFlags { flags.subcommand = DenoSubcommand::Info(InfoFlags {
file: matches.remove_one::<String>("file"), file: matches.remove_one::<String>("file"),
@ -4495,6 +4607,7 @@ fn install_parse(
force, force,
}), }),
}); });
return Ok(()); return Ok(());
} }
@ -5175,13 +5288,22 @@ fn permission_args_parse(
} }
if matches.get_flag("allow-hrtime") || matches.get_flag("deny-hrtime") { if matches.get_flag("allow-hrtime") || matches.get_flag("deny-hrtime") {
log::warn!("⚠️ Warning: `allow-hrtime` and `deny-hrtime` have been removed in Deno 2, as high resolution time is now always allowed."); // use eprintln instead of log::warn because logging hasn't been initialized yet
#[allow(clippy::print_stderr)]
{
eprintln!(
"{} `allow-hrtime` and `deny-hrtime` have been removed in Deno 2, as high resolution time is now always allowed",
deno_runtime::colors::yellow("Warning")
);
}
} }
if matches.get_flag("allow-all") { if matches.get_flag("allow-all") {
flags.allow_all(); flags.allow_all();
} }
allow_import_parse(flags, matches);
if matches.get_flag("no-prompt") { if matches.get_flag("no-prompt") {
flags.permissions.no_prompt = true; flags.permissions.no_prompt = true;
} }
@ -5189,6 +5311,13 @@ fn permission_args_parse(
Ok(()) Ok(())
} }
fn allow_import_parse(flags: &mut Flags, matches: &mut ArgMatches) {
if let Some(imports_wl) = matches.remove_many::<String>("allow-import") {
let imports_allowlist = flags_net::parse(imports_wl.collect()).unwrap();
flags.permissions.allow_import = Some(imports_allowlist);
}
}
fn unsafely_ignore_certificate_errors_parse( fn unsafely_ignore_certificate_errors_parse(
flags: &mut Flags, flags: &mut Flags,
matches: &mut ArgMatches, matches: &mut ArgMatches,
@ -6215,7 +6344,7 @@ mod tests {
#[test] #[test]
fn short_permission_flags() { fn short_permission_flags() {
let r = flags_from_vec(svec!["deno", "run", "-RNESW", "gist.ts"]); let r = flags_from_vec(svec!["deno", "run", "-RNESWI", "gist.ts"]);
assert_eq!( assert_eq!(
r.unwrap(), r.unwrap(),
Flags { Flags {
@ -6226,6 +6355,7 @@ mod tests {
allow_read: Some(vec![]), allow_read: Some(vec![]),
allow_write: Some(vec![]), allow_write: Some(vec![]),
allow_env: Some(vec![]), allow_env: Some(vec![]),
allow_import: Some(vec![]),
allow_net: Some(vec![]), allow_net: Some(vec![]),
allow_sys: Some(vec![]), allow_sys: Some(vec![]),
..Default::default() ..Default::default()
@ -10777,7 +10907,7 @@ mod tests {
} }
); );
// just make sure this doesn't panic // just make sure this doesn't panic
let _ = flags.permissions.to_options(); let _ = flags.permissions.to_options(&[]);
} }
#[test] #[test]
@ -10852,4 +10982,27 @@ mod tests {
Usage: deno repl [OPTIONS] [-- [ARGS]...]\n" Usage: deno repl [OPTIONS] [-- [ARGS]...]\n"
) )
} }
#[test]
fn test_allow_import_host_from_url() {
fn parse(text: &str) -> Option<String> {
allow_import_host_from_url(&Url::parse(text).unwrap())
}
assert_eq!(parse("https://jsr.io"), None);
assert_eq!(
parse("http://127.0.0.1:4250"),
Some("127.0.0.1:4250".to_string())
);
assert_eq!(parse("http://jsr.io"), Some("jsr.io:80".to_string()));
assert_eq!(
parse("https://example.com"),
Some("example.com:443".to_string())
);
assert_eq!(
parse("http://example.com"),
Some("example.com:80".to_string())
);
assert_eq!(parse("file:///example.com"), None);
}
} }

View file

@ -769,6 +769,7 @@ pub struct CliOptions {
// application need not concern itself with, so keep these private // application need not concern itself with, so keep these private
flags: Arc<Flags>, flags: Arc<Flags>,
initial_cwd: PathBuf, initial_cwd: PathBuf,
main_module_cell: std::sync::OnceLock<Result<ModuleSpecifier, AnyError>>,
maybe_node_modules_folder: Option<PathBuf>, maybe_node_modules_folder: Option<PathBuf>,
npmrc: Arc<ResolvedNpmRc>, npmrc: Arc<ResolvedNpmRc>,
maybe_lockfile: Option<Arc<CliLockfile>>, maybe_lockfile: Option<Arc<CliLockfile>>,
@ -825,6 +826,7 @@ impl CliOptions {
npmrc, npmrc,
maybe_node_modules_folder, maybe_node_modules_folder,
overrides: Default::default(), overrides: Default::default(),
main_module_cell: std::sync::OnceLock::new(),
start_dir, start_dir,
deno_dir_provider, deno_dir_provider,
}) })
@ -1105,7 +1107,10 @@ impl CliOptions {
self.flags.env_file.as_ref() self.flags.env_file.as_ref()
} }
pub fn resolve_main_module(&self) -> Result<ModuleSpecifier, AnyError> { pub fn resolve_main_module(&self) -> Result<&ModuleSpecifier, AnyError> {
self
.main_module_cell
.get_or_init(|| {
let main_module = match &self.flags.subcommand { let main_module = match &self.flags.subcommand {
DenoSubcommand::Compile(compile_flags) => { DenoSubcommand::Compile(compile_flags) => {
resolve_url_or_path(&compile_flags.source_file, self.initial_cwd())? resolve_url_or_path(&compile_flags.source_file, self.initial_cwd())?
@ -1118,13 +1123,10 @@ impl CliOptions {
} }
DenoSubcommand::Run(run_flags) => { DenoSubcommand::Run(run_flags) => {
if run_flags.is_stdin() { if run_flags.is_stdin() {
std::env::current_dir() resolve_url_or_path("./$deno$stdin.ts", self.initial_cwd())?
.context("Unable to get CWD") } else if NpmPackageReqReference::from_str(&run_flags.script)
.and_then(|cwd| { .is_ok()
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)? ModuleSpecifier::parse(&run_flags.script)?
} else { } else {
resolve_url_or_path(&run_flags.script, self.initial_cwd())? resolve_url_or_path(&run_flags.script, self.initial_cwd())?
@ -1139,6 +1141,9 @@ impl CliOptions {
}; };
Ok(main_module) Ok(main_module)
})
.as_ref()
.map_err(|err| deno_core::anyhow::anyhow!("{}", err))
} }
pub fn resolve_file_header_overrides( pub fn resolve_file_header_overrides(
@ -1159,7 +1164,7 @@ impl CliOptions {
(maybe_main_specifier, maybe_content_type) (maybe_main_specifier, maybe_content_type)
{ {
HashMap::from([( HashMap::from([(
main_specifier, main_specifier.clone(),
HashMap::from([("content-type".to_string(), content_type.to_string())]), HashMap::from([("content-type".to_string(), content_type.to_string())]),
)]) )])
} else { } else {
@ -1480,7 +1485,34 @@ impl CliOptions {
} }
pub fn permissions_options(&self) -> PermissionsOptions { 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 { pub fn reload_flag(&self) -> bool {

42
cli/cache/mod.rs vendored
View file

@ -1,10 +1,11 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use crate::args::jsr_url;
use crate::args::CacheSetting; use crate::args::CacheSetting;
use crate::errors::get_error_class_name; use crate::errors::get_error_class_name;
use crate::file_fetcher::FetchNoFollowOptions; use crate::file_fetcher::FetchNoFollowOptions;
use crate::file_fetcher::FetchOptions; use crate::file_fetcher::FetchOptions;
use crate::file_fetcher::FetchPermissionsOption; use crate::file_fetcher::FetchPermissionsOptionRef;
use crate::file_fetcher::FileFetcher; use crate::file_fetcher::FileFetcher;
use crate::file_fetcher::FileOrRedirect; use crate::file_fetcher::FileOrRedirect;
use crate::npm::CliNpmResolver; use crate::npm::CliNpmResolver;
@ -19,6 +20,7 @@ use deno_graph::source::CacheInfo;
use deno_graph::source::LoadFuture; use deno_graph::source::LoadFuture;
use deno_graph::source::LoadResponse; use deno_graph::source::LoadResponse;
use deno_graph::source::Loader; use deno_graph::source::Loader;
use deno_runtime::deno_permissions::PermissionsContainer;
use std::collections::HashMap; use std::collections::HashMap;
use std::path::Path; use std::path::Path;
use std::path::PathBuf; use std::path::PathBuf;
@ -104,6 +106,13 @@ pub type LocalLspHttpCache =
deno_cache_dir::LocalLspHttpCache<RealDenoCacheEnv>; deno_cache_dir::LocalLspHttpCache<RealDenoCacheEnv>;
pub use deno_cache_dir::HttpCache; 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 "wrapper" for the FileFetcher and DiskCache for the Deno CLI that provides
/// a concise interface to the DENO_DIR when building module graphs. /// a concise interface to the DENO_DIR when building module graphs.
pub struct FetchCacher { pub struct FetchCacher {
@ -112,26 +121,27 @@ pub struct FetchCacher {
global_http_cache: Arc<GlobalHttpCache>, global_http_cache: Arc<GlobalHttpCache>,
npm_resolver: Arc<dyn CliNpmResolver>, npm_resolver: Arc<dyn CliNpmResolver>,
module_info_cache: Arc<ModuleInfoCache>, module_info_cache: Arc<ModuleInfoCache>,
permissions: FetchPermissionsOption, permissions: PermissionsContainer,
cache_info_enabled: bool, cache_info_enabled: bool,
is_deno_publish: bool,
} }
impl FetchCacher { impl FetchCacher {
pub fn new( pub fn new(
file_fetcher: Arc<FileFetcher>, file_fetcher: Arc<FileFetcher>,
file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>,
global_http_cache: Arc<GlobalHttpCache>, global_http_cache: Arc<GlobalHttpCache>,
npm_resolver: Arc<dyn CliNpmResolver>, npm_resolver: Arc<dyn CliNpmResolver>,
module_info_cache: Arc<ModuleInfoCache>, module_info_cache: Arc<ModuleInfoCache>,
permissions: FetchPermissionsOption, options: FetchCacherOptions,
) -> Self { ) -> Self {
Self { Self {
file_fetcher, file_fetcher,
file_header_overrides,
global_http_cache, global_http_cache,
npm_resolver, npm_resolver,
module_info_cache, 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, cache_info_enabled: false,
} }
} }
@ -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_fetcher = self.file_fetcher.clone();
let file_header_overrides = self.file_header_overrides.clone(); let file_header_overrides = self.file_header_overrides.clone();
let permissions = self.permissions.clone(); let permissions = self.permissions.clone();
let specifier = specifier.clone(); let specifier = specifier.clone();
let is_statically_analyzable = !options.was_dynamic_root;
async move { async move {
let maybe_cache_setting = match options.cache_setting { let maybe_cache_setting = match options.cache_setting {
@ -230,7 +254,11 @@ impl Loader for FetchCacher {
.fetch_no_follow_with_options(FetchNoFollowOptions { .fetch_no_follow_with_options(FetchNoFollowOptions {
fetch_options: FetchOptions { fetch_options: FetchOptions {
specifier: &specifier, specifier: &specifier,
permissions: permissions.as_ref(), permissions: if is_statically_analyzable {
FetchPermissionsOptionRef::StaticContainer(&permissions)
} else {
FetchPermissionsOptionRef::DynamicContainer(&permissions)
},
maybe_accept: None, maybe_accept: None,
maybe_cache_setting: maybe_cache_setting.as_ref(), maybe_cache_setting: maybe_cache_setting.as_ref(),
}, },

View file

@ -185,6 +185,7 @@ struct CliFactoryServices {
node_resolver: Deferred<Arc<NodeResolver>>, node_resolver: Deferred<Arc<NodeResolver>>,
npm_resolver: Deferred<Arc<dyn CliNpmResolver>>, npm_resolver: Deferred<Arc<dyn CliNpmResolver>>,
permission_desc_parser: Deferred<Arc<RuntimePermissionDescriptorParser>>, permission_desc_parser: Deferred<Arc<RuntimePermissionDescriptorParser>>,
root_permissions_container: Deferred<PermissionsContainer>,
sloppy_imports_resolver: Deferred<Option<Arc<SloppyImportsResolver>>>, sloppy_imports_resolver: Deferred<Option<Arc<SloppyImportsResolver>>>,
text_only_progress_bar: Deferred<ProgressBar>, text_only_progress_bar: Deferred<ProgressBar>,
type_checker: Deferred<Arc<TypeChecker>>, type_checker: Deferred<Arc<TypeChecker>>,
@ -626,6 +627,7 @@ impl CliFactory {
self.maybe_file_watcher_reporter().clone(), self.maybe_file_watcher_reporter().clone(),
self.file_fetcher()?.clone(), self.file_fetcher()?.clone(),
self.global_http_cache()?.clone(), self.global_http_cache()?.clone(),
self.root_permissions_container()?.clone(),
))) )))
}) })
.await .await
@ -659,6 +661,7 @@ impl CliFactory {
Ok(Arc::new(MainModuleGraphContainer::new( Ok(Arc::new(MainModuleGraphContainer::new(
self.cli_options()?.clone(), self.cli_options()?.clone(),
self.module_load_preparer().await?.clone(), self.module_load_preparer().await?.clone(),
self.root_permissions_container()?.clone(),
))) )))
}) })
.await .await
@ -755,15 +758,20 @@ impl CliFactory {
)) ))
} }
pub fn create_permissions_container( pub fn root_permissions_container(
&self, &self,
) -> Result<PermissionsContainer, AnyError> { ) -> Result<&PermissionsContainer, AnyError> {
self
.services
.root_permissions_container
.get_or_try_init(|| {
let desc_parser = self.permission_desc_parser()?.clone(); let desc_parser = self.permission_desc_parser()?.clone();
let permissions = Permissions::from_options( let permissions = Permissions::from_options(
desc_parser.as_ref(), desc_parser.as_ref(),
&self.cli_options()?.permissions_options(), &self.cli_options()?.permissions_options(),
)?; )?;
Ok(PermissionsContainer::new(desc_parser, permissions)) Ok(PermissionsContainer::new(desc_parser, permissions))
})
} }
pub async fn create_cli_main_worker_factory( pub async fn create_cli_main_worker_factory(
@ -816,6 +824,7 @@ impl CliFactory {
npm_resolver.clone(), npm_resolver.clone(),
self.permission_desc_parser()?.clone(), self.permission_desc_parser()?.clone(),
self.root_cert_store_provider().clone(), self.root_cert_store_provider().clone(),
self.root_permissions_container()?.clone(),
StorageKeyResolver::from_options(cli_options), StorageKeyResolver::from_options(cli_options),
cli_options.sub_command().clone(), cli_options.sub_command().clone(),
self.create_cli_main_worker_options()?, self.create_cli_main_worker_options()?,

View file

@ -23,6 +23,7 @@ use deno_graph::source::LoaderChecksum;
use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::deno_permissions::PermissionsContainer;
use deno_runtime::deno_web::BlobStore; use deno_runtime::deno_web::BlobStore;
use deno_runtime::fs_util::specifier_to_file_path;
use log::debug; use log::debug;
use std::borrow::Cow; use std::borrow::Cow;
use std::collections::HashMap; use std::collections::HashMap;
@ -135,7 +136,7 @@ impl MemoryFiles {
/// Fetch a source file from the local file system. /// Fetch a source file from the local file system.
fn fetch_local(specifier: &ModuleSpecifier) -> Result<File, AnyError> { fn fetch_local(specifier: &ModuleSpecifier) -> Result<File, AnyError> {
let local = specifier.to_file_path().map_err(|_| { let local = specifier_to_file_path(specifier).map_err(|_| {
uri_error(format!("Invalid file path.\n Specifier: {specifier}")) uri_error(format!("Invalid file path.\n Specifier: {specifier}"))
})?; })?;
// If it doesnt have a extension, we want to treat it as typescript by default // If it doesnt have a extension, we want to treat it as typescript by default
@ -173,30 +174,8 @@ fn get_validated_scheme(
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub enum FetchPermissionsOptionRef<'a> { pub enum FetchPermissionsOptionRef<'a> {
AllowAll, AllowAll,
Container(&'a PermissionsContainer), DynamicContainer(&'a PermissionsContainer),
} StaticContainer(&'a PermissionsContainer),
#[derive(Debug, Clone)]
pub enum FetchPermissionsOption {
AllowAll,
Container(PermissionsContainer),
}
impl FetchPermissionsOption {
pub fn as_ref(&self) -> FetchPermissionsOptionRef {
match self {
FetchPermissionsOption::AllowAll => FetchPermissionsOptionRef::AllowAll,
FetchPermissionsOption::Container(container) => {
FetchPermissionsOptionRef::Container(container)
}
}
}
}
impl From<PermissionsContainer> for FetchPermissionsOption {
fn from(value: PermissionsContainer) -> Self {
Self::Container(value)
}
} }
pub struct FetchOptions<'a> { pub struct FetchOptions<'a> {
@ -564,7 +543,6 @@ impl FileFetcher {
} }
/// Fetch a source file and asynchronously return it. /// Fetch a source file and asynchronously return it.
#[allow(dead_code)] // todo(25469): undo when merging
#[inline(always)] #[inline(always)]
pub async fn fetch( pub async fn fetch(
&self, &self,
@ -572,7 +550,10 @@ impl FileFetcher {
permissions: &PermissionsContainer, permissions: &PermissionsContainer,
) -> Result<File, AnyError> { ) -> Result<File, AnyError> {
self self
.fetch_inner(specifier, FetchPermissionsOptionRef::Container(permissions)) .fetch_inner(
specifier,
FetchPermissionsOptionRef::StaticContainer(permissions),
)
.await .await
} }
@ -647,8 +628,17 @@ impl FileFetcher {
FetchPermissionsOptionRef::AllowAll => { FetchPermissionsOptionRef::AllowAll => {
// allow // allow
} }
FetchPermissionsOptionRef::Container(permissions) => { FetchPermissionsOptionRef::StaticContainer(permissions) => {
permissions.check_specifier(specifier)?; permissions.check_specifier(
specifier,
deno_runtime::deno_permissions::CheckSpecifierKind::Static,
)?;
}
FetchPermissionsOptionRef::DynamicContainer(permissions) => {
permissions.check_specifier(
specifier,
deno_runtime::deno_permissions::CheckSpecifierKind::Dynamic,
)?;
} }
} }
if let Some(file) = self.memory_files.get(specifier) { if let Some(file) = self.memory_files.get(specifier) {

View file

@ -9,9 +9,9 @@ use deno_core::error::AnyError;
use deno_core::parking_lot::RwLock; use deno_core::parking_lot::RwLock;
use deno_graph::ModuleGraph; use deno_graph::ModuleGraph;
use deno_runtime::colors; use deno_runtime::colors;
use deno_runtime::deno_permissions::PermissionsContainer;
use crate::args::CliOptions; use crate::args::CliOptions;
use crate::file_fetcher::FetchPermissionsOption;
use crate::module_loader::ModuleLoadPreparer; use crate::module_loader::ModuleLoadPreparer;
use crate::util::fs::collect_specifiers; use crate::util::fs::collect_specifiers;
use crate::util::path::is_script_ext; use crate::util::path::is_script_ext;
@ -45,12 +45,14 @@ pub struct MainModuleGraphContainer {
inner: Arc<RwLock<Arc<ModuleGraph>>>, inner: Arc<RwLock<Arc<ModuleGraph>>>,
cli_options: Arc<CliOptions>, cli_options: Arc<CliOptions>,
module_load_preparer: Arc<ModuleLoadPreparer>, module_load_preparer: Arc<ModuleLoadPreparer>,
root_permissions: PermissionsContainer,
} }
impl MainModuleGraphContainer { impl MainModuleGraphContainer {
pub fn new( pub fn new(
cli_options: Arc<CliOptions>, cli_options: Arc<CliOptions>,
module_load_preparer: Arc<ModuleLoadPreparer>, module_load_preparer: Arc<ModuleLoadPreparer>,
root_permissions: PermissionsContainer,
) -> Self { ) -> Self {
Self { Self {
update_queue: Default::default(), update_queue: Default::default(),
@ -59,6 +61,7 @@ impl MainModuleGraphContainer {
)))), )))),
cli_options, cli_options,
module_load_preparer, module_load_preparer,
root_permissions,
} }
} }
@ -76,7 +79,7 @@ impl MainModuleGraphContainer {
specifiers, specifiers,
false, false,
self.cli_options.ts_type_lib_window(), self.cli_options.ts_type_lib_window(),
FetchPermissionsOption::AllowAll, self.root_permissions.clone(),
ext_overwrite, ext_overwrite,
) )
.await?; .await?;

View file

@ -11,7 +11,6 @@ use crate::cache::ModuleInfoCache;
use crate::cache::ParsedSourceCache; use crate::cache::ParsedSourceCache;
use crate::colors; use crate::colors;
use crate::errors::get_error_class_name; use crate::errors::get_error_class_name;
use crate::file_fetcher::FetchPermissionsOption;
use crate::file_fetcher::FileFetcher; use crate::file_fetcher::FileFetcher;
use crate::npm::CliNpmResolver; use crate::npm::CliNpmResolver;
use crate::resolver::CliGraphResolver; use crate::resolver::CliGraphResolver;
@ -41,6 +40,7 @@ use deno_graph::ResolutionError;
use deno_graph::SpecifierError; use deno_graph::SpecifierError;
use deno_runtime::deno_fs::FileSystem; use deno_runtime::deno_fs::FileSystem;
use deno_runtime::deno_node; use deno_runtime::deno_node;
use deno_runtime::deno_permissions::PermissionsContainer;
use deno_runtime::fs_util::specifier_to_file_path; use deno_runtime::fs_util::specifier_to_file_path;
use deno_semver::jsr::JsrDepPackageReq; use deno_semver::jsr::JsrDepPackageReq;
use deno_semver::package::PackageNv; use deno_semver::package::PackageNv;
@ -249,6 +249,19 @@ impl ModuleGraphCreator {
package_configs: &[JsrPackageConfig], package_configs: &[JsrPackageConfig],
build_fast_check_graph: bool, build_fast_check_graph: bool,
) -> Result<ModuleGraph, AnyError> { ) -> Result<ModuleGraph, AnyError> {
fn graph_has_external_remote(graph: &ModuleGraph) -> bool {
// Earlier on, we marked external non-JSR modules as external.
// If the graph contains any of those, it would cause type checking
// to crash, so since publishing is going to fail anyway, skip type
// checking.
graph.modules().any(|module| match module {
deno_graph::Module::External(external_module) => {
matches!(external_module.specifier.scheme(), "http" | "https")
}
_ => false,
})
}
let mut roots = Vec::new(); let mut roots = Vec::new();
for package_config in package_configs { for package_config in package_configs {
roots.extend(package_config.config_file.resolve_export_value_urls()?); roots.extend(package_config.config_file.resolve_export_value_urls()?);
@ -262,9 +275,12 @@ impl ModuleGraphCreator {
}) })
.await?; .await?;
self.graph_valid(&graph)?; self.graph_valid(&graph)?;
if self.options.type_check_mode().is_true() { if self.options.type_check_mode().is_true()
&& !graph_has_external_remote(&graph)
{
self.type_check_graph(graph.clone()).await?; self.type_check_graph(graph.clone()).await?;
} }
if build_fast_check_graph { if build_fast_check_graph {
let fast_check_workspace_members = package_configs let fast_check_workspace_members = package_configs
.iter() .iter()
@ -279,6 +295,7 @@ impl ModuleGraphCreator {
}, },
)?; )?;
} }
Ok(graph) Ok(graph)
} }
@ -370,6 +387,7 @@ pub struct ModuleGraphBuilder {
maybe_file_watcher_reporter: Option<FileWatcherReporter>, maybe_file_watcher_reporter: Option<FileWatcherReporter>,
file_fetcher: Arc<FileFetcher>, file_fetcher: Arc<FileFetcher>,
global_http_cache: Arc<GlobalHttpCache>, global_http_cache: Arc<GlobalHttpCache>,
root_permissions_container: PermissionsContainer,
} }
impl ModuleGraphBuilder { impl ModuleGraphBuilder {
@ -386,6 +404,7 @@ impl ModuleGraphBuilder {
maybe_file_watcher_reporter: Option<FileWatcherReporter>, maybe_file_watcher_reporter: Option<FileWatcherReporter>,
file_fetcher: Arc<FileFetcher>, file_fetcher: Arc<FileFetcher>,
global_http_cache: Arc<GlobalHttpCache>, global_http_cache: Arc<GlobalHttpCache>,
root_permissions_container: PermissionsContainer,
) -> Self { ) -> Self {
Self { Self {
options, options,
@ -399,6 +418,7 @@ impl ModuleGraphBuilder {
maybe_file_watcher_reporter, maybe_file_watcher_reporter,
file_fetcher, file_fetcher,
global_http_cache, global_http_cache,
root_permissions_container,
} }
} }
@ -670,20 +690,26 @@ impl ModuleGraphBuilder {
/// Creates the default loader used for creating a graph. /// Creates the default loader used for creating a graph.
pub fn create_graph_loader(&self) -> cache::FetchCacher { pub fn create_graph_loader(&self) -> cache::FetchCacher {
self.create_fetch_cacher(FetchPermissionsOption::AllowAll) self.create_fetch_cacher(self.root_permissions_container.clone())
} }
pub fn create_fetch_cacher( pub fn create_fetch_cacher(
&self, &self,
permissions: FetchPermissionsOption, permissions: PermissionsContainer,
) -> cache::FetchCacher { ) -> cache::FetchCacher {
cache::FetchCacher::new( cache::FetchCacher::new(
self.file_fetcher.clone(), self.file_fetcher.clone(),
self.options.resolve_file_header_overrides(),
self.global_http_cache.clone(), self.global_http_cache.clone(),
self.npm_resolver.clone(), self.npm_resolver.clone(),
self.module_info_cache.clone(), self.module_info_cache.clone(),
cache::FetchCacherOptions {
file_header_overrides: self.options.resolve_file_header_overrides(),
permissions, permissions,
is_deno_publish: matches!(
self.options.sub_command(),
crate::args::DenoSubcommand::Publish { .. }
),
},
) )
} }

View file

@ -3614,6 +3614,11 @@ impl Inner {
}), }),
// bit of a hack to force the lsp to cache the @types/node package // bit of a hack to force the lsp to cache the @types/node package
type_check_mode: crate::args::TypeCheckMode::Local, type_check_mode: crate::args::TypeCheckMode::Local,
permissions: crate::args::PermissionFlags {
// allow remote import permissions in the lsp for now
allow_import: Some(vec![]),
..Default::default()
},
..Default::default() ..Default::default()
}), }),
initial_cwd, initial_cwd,

View file

@ -104,7 +104,7 @@ impl ModuleLoadPreparer {
roots: &[ModuleSpecifier], roots: &[ModuleSpecifier],
is_dynamic: bool, is_dynamic: bool,
lib: TsTypeLib, lib: TsTypeLib,
permissions: crate::file_fetcher::FetchPermissionsOption, permissions: PermissionsContainer,
ext_overwrite: Option<&String>, ext_overwrite: Option<&String>,
) -> Result<(), AnyError> { ) -> Result<(), AnyError> {
log::debug!("Preparing module load."); log::debug!("Preparing module load.");
@ -252,13 +252,15 @@ impl CliModuleLoaderFactory {
&self, &self,
graph_container: TGraphContainer, graph_container: TGraphContainer,
lib: TsTypeLib, lib: TsTypeLib,
root_permissions: PermissionsContainer, is_worker: bool,
dynamic_permissions: PermissionsContainer, parent_permissions: PermissionsContainer,
permissions: PermissionsContainer,
) -> ModuleLoaderAndSourceMapGetter { ) -> ModuleLoaderAndSourceMapGetter {
let loader = Rc::new(CliModuleLoader(Rc::new(CliModuleLoaderInner { let loader = Rc::new(CliModuleLoader(Rc::new(CliModuleLoaderInner {
lib, lib,
root_permissions, is_worker,
dynamic_permissions, parent_permissions,
permissions,
graph_container, graph_container,
emitter: self.shared.emitter.clone(), emitter: self.shared.emitter.clone(),
parsed_source_cache: self.shared.parsed_source_cache.clone(), parsed_source_cache: self.shared.parsed_source_cache.clone(),
@ -274,20 +276,20 @@ impl ModuleLoaderFactory for CliModuleLoaderFactory {
fn create_for_main( fn create_for_main(
&self, &self,
root_permissions: PermissionsContainer, root_permissions: PermissionsContainer,
dynamic_permissions: PermissionsContainer,
) -> ModuleLoaderAndSourceMapGetter { ) -> ModuleLoaderAndSourceMapGetter {
self.create_with_lib( self.create_with_lib(
(*self.shared.main_module_graph_container).clone(), (*self.shared.main_module_graph_container).clone(),
self.shared.lib_window, self.shared.lib_window,
/* is worker */ false,
root_permissions.clone(),
root_permissions, root_permissions,
dynamic_permissions,
) )
} }
fn create_for_worker( fn create_for_worker(
&self, &self,
root_permissions: PermissionsContainer, parent_permissions: PermissionsContainer,
dynamic_permissions: PermissionsContainer, permissions: PermissionsContainer,
) -> ModuleLoaderAndSourceMapGetter { ) -> ModuleLoaderAndSourceMapGetter {
self.create_with_lib( self.create_with_lib(
// create a fresh module graph for the worker // create a fresh module graph for the worker
@ -295,21 +297,21 @@ impl ModuleLoaderFactory for CliModuleLoaderFactory {
self.shared.graph_kind, self.shared.graph_kind,
))), ))),
self.shared.lib_worker, self.shared.lib_worker,
root_permissions, /* is worker */ true,
dynamic_permissions, parent_permissions,
permissions,
) )
} }
} }
struct CliModuleLoaderInner<TGraphContainer: ModuleGraphContainer> { struct CliModuleLoaderInner<TGraphContainer: ModuleGraphContainer> {
lib: TsTypeLib, lib: TsTypeLib,
is_worker: bool,
/// The initial set of permissions used to resolve the static imports in the /// The initial set of permissions used to resolve the static imports in the
/// worker. These are "allow all" for main worker, and parent thread /// worker. These are "allow all" for main worker, and parent thread
/// permissions for Web Worker. /// permissions for Web Worker.
root_permissions: PermissionsContainer, parent_permissions: PermissionsContainer,
/// Permissions used to resolve dynamic imports, these get passed as permissions: PermissionsContainer,
/// "root permissions" for Web Worker.
dynamic_permissions: PermissionsContainer,
shared: Arc<SharedCliModuleLoaderState>, shared: Arc<SharedCliModuleLoaderState>,
emitter: Arc<Emitter>, emitter: Arc<Emitter>,
parsed_source_cache: Arc<ParsedSourceCache>, parsed_source_cache: Arc<ParsedSourceCache>,
@ -769,11 +771,12 @@ impl<TGraphContainer: ModuleGraphContainer> ModuleLoader
} }
} }
let root_permissions = if is_dynamic { let permissions = if is_dynamic {
inner.dynamic_permissions.clone() inner.permissions.clone()
} else { } else {
inner.root_permissions.clone() inner.parent_permissions.clone()
}; };
let is_dynamic = is_dynamic || inner.is_worker; // consider workers as dynamic for permissions
let lib = inner.lib; let lib = inner.lib;
let mut update_permit = graph_container.acquire_update_permit().await; let mut update_permit = graph_container.acquire_update_permit().await;
let graph = update_permit.graph_mut(); let graph = update_permit.graph_mut();
@ -783,7 +786,7 @@ impl<TGraphContainer: ModuleGraphContainer> ModuleLoader
&[specifier], &[specifier],
is_dynamic, is_dynamic,
lib, lib,
root_permissions.into(), permissions,
None, None,
) )
.await?; .await?;

View file

@ -130,8 +130,6 @@ struct SharedModuleLoaderState {
#[derive(Clone)] #[derive(Clone)]
struct EmbeddedModuleLoader { struct EmbeddedModuleLoader {
shared: Arc<SharedModuleLoaderState>, shared: Arc<SharedModuleLoaderState>,
root_permissions: PermissionsContainer,
dynamic_permissions: PermissionsContainer,
} }
pub const MODULE_NOT_FOUND: &str = "Module not found"; pub const MODULE_NOT_FOUND: &str = "Module not found";
@ -402,28 +400,23 @@ struct StandaloneModuleLoaderFactory {
impl ModuleLoaderFactory for StandaloneModuleLoaderFactory { impl ModuleLoaderFactory for StandaloneModuleLoaderFactory {
fn create_for_main( fn create_for_main(
&self, &self,
root_permissions: PermissionsContainer, _root_permissions: PermissionsContainer,
dynamic_permissions: PermissionsContainer,
) -> ModuleLoaderAndSourceMapGetter { ) -> ModuleLoaderAndSourceMapGetter {
ModuleLoaderAndSourceMapGetter { ModuleLoaderAndSourceMapGetter {
module_loader: Rc::new(EmbeddedModuleLoader { module_loader: Rc::new(EmbeddedModuleLoader {
shared: self.shared.clone(), shared: self.shared.clone(),
root_permissions,
dynamic_permissions,
}), }),
} }
} }
fn create_for_worker( fn create_for_worker(
&self, &self,
root_permissions: PermissionsContainer, _parent_permissions: PermissionsContainer,
dynamic_permissions: PermissionsContainer, _permissions: PermissionsContainer,
) -> ModuleLoaderAndSourceMapGetter { ) -> ModuleLoaderAndSourceMapGetter {
ModuleLoaderAndSourceMapGetter { ModuleLoaderAndSourceMapGetter {
module_loader: Rc::new(EmbeddedModuleLoader { module_loader: Rc::new(EmbeddedModuleLoader {
shared: self.shared.clone(), shared: self.shared.clone(),
root_permissions,
dynamic_permissions,
}), }),
} }
} }
@ -664,7 +657,8 @@ pub async fn run(
}; };
let permissions = { let permissions = {
let mut permissions = metadata.permissions.to_options(); let mut permissions =
metadata.permissions.to_options(/* cli_arg_urls */ &[]);
// if running with an npm vfs, grant read access to it // if running with an npm vfs, grant read access to it
if let Some(vfs_root) = maybe_vfs_root { if let Some(vfs_root) = maybe_vfs_root {
match &mut permissions.allow_read { match &mut permissions.allow_read {
@ -713,6 +707,7 @@ pub async fn run(
npm_resolver, npm_resolver,
permission_desc_parser, permission_desc_parser,
root_cert_store_provider, root_cert_store_provider,
permissions,
StorageKeyResolver::empty(), StorageKeyResolver::empty(),
crate::args::DenoSubcommand::Run(Default::default()), crate::args::DenoSubcommand::Run(Default::default()),
CliMainWorkerOptions { CliMainWorkerOptions {
@ -752,7 +747,7 @@ pub async fn run(
deno_core::JsRuntime::init_platform(None, true); deno_core::JsRuntime::init_platform(None, true);
let mut worker = worker_factory let mut worker = worker_factory
.create_main_worker(WorkerExecutionMode::Run, main_module, permissions) .create_main_worker(WorkerExecutionMode::Run, main_module)
.await?; .await?;
let exit_code = worker.run().await?; let exit_code = worker.run().await?;

View file

@ -51,6 +51,7 @@ pub async fn check(
let specifiers_for_typecheck = if check_flags.doc || check_flags.doc_only { let specifiers_for_typecheck = if check_flags.doc || check_flags.doc_only {
let file_fetcher = factory.file_fetcher()?; let file_fetcher = factory.file_fetcher()?;
let root_permissions = factory.root_permissions_container()?;
let mut specifiers_for_typecheck = if check_flags.doc { let mut specifiers_for_typecheck = if check_flags.doc {
specifiers.clone() specifiers.clone()
@ -59,7 +60,7 @@ pub async fn check(
}; };
for s in specifiers { for s in specifiers {
let file = file_fetcher.fetch_bypass_permissions(&s).await?; let file = file_fetcher.fetch(&s, root_permissions).await?;
let snippet_files = extract::extract_snippet_files(file)?; let snippet_files = extract::extract_snippet_files(file)?;
for snippet_file in snippet_files { for snippet_file in snippet_files {
specifiers_for_typecheck.push(snippet_file.specifier.clone()); specifiers_for_typecheck.push(snippet_file.specifier.clone());

View file

@ -135,7 +135,7 @@ pub async fn compile(
file, file,
eszip, eszip,
root_dir_url, root_dir_url,
&module_specifier, module_specifier,
&compile_flags, &compile_flags,
cli_options, cli_options,
) )

View file

@ -644,8 +644,21 @@ impl<'a> GraphDisplayContext<'a> {
ModuleError::InvalidTypeAssertion { .. } => { ModuleError::InvalidTypeAssertion { .. } => {
self.build_error_msg(specifier, "(invalid import attribute)") self.build_error_msg(specifier, "(invalid import attribute)")
} }
ModuleError::LoadingErr(_, _, _) => { ModuleError::LoadingErr(_, _, err) => {
self.build_error_msg(specifier, "(loading error)") use deno_graph::ModuleLoadError::*;
let message = match err {
HttpsChecksumIntegrity(_) => "(checksum integrity error)",
Decode(_) => "(loading decode error)",
Loader(err) => match deno_core::error::get_custom_error_class(err) {
Some("NotCapable") => "(not capable, requires --allow-import)",
_ => "(loading error)",
},
Jsr(_) => "(loading error)",
NodeUnknownBuiltinModule(_) => "(unknown node built-in error)",
Npm(_) => "(npm loading error)",
TooManyRedirects => "(too many redirects error)",
};
self.build_error_msg(specifier, message.as_ref())
} }
ModuleError::ParseErr(_, _) => { ModuleError::ParseErr(_, _) => {
self.build_error_msg(specifier, "(parsing error)") self.build_error_msg(specifier, "(parsing error)")

View file

@ -3,7 +3,6 @@
use std::borrow::Cow; use std::borrow::Cow;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex;
use deno_ast::diagnostics::Diagnostic; use deno_ast::diagnostics::Diagnostic;
use deno_ast::diagnostics::DiagnosticLevel; use deno_ast::diagnostics::DiagnosticLevel;
@ -21,6 +20,7 @@ use deno_ast::SourceRanged;
use deno_ast::SourceTextInfo; use deno_ast::SourceTextInfo;
use deno_core::anyhow::anyhow; use deno_core::anyhow::anyhow;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::parking_lot::Mutex;
use deno_core::url::Url; use deno_core::url::Url;
use deno_graph::FastCheckDiagnostic; use deno_graph::FastCheckDiagnostic;
use deno_semver::Version; use deno_semver::Version;
@ -36,7 +36,7 @@ impl PublishDiagnosticsCollector {
pub fn print_and_error(&self) -> Result<(), AnyError> { pub fn print_and_error(&self) -> Result<(), AnyError> {
let mut errors = 0; let mut errors = 0;
let mut has_slow_types_errors = false; let mut has_slow_types_errors = false;
let mut diagnostics = self.diagnostics.lock().unwrap().take(); let mut diagnostics = self.diagnostics.lock().take();
diagnostics.sort_by_cached_key(|d| d.sorting_key()); diagnostics.sort_by_cached_key(|d| d.sorting_key());
@ -75,8 +75,16 @@ impl PublishDiagnosticsCollector {
} }
} }
pub fn has_error(&self) -> bool {
self
.diagnostics
.lock()
.iter()
.any(|d| matches!(d.level(), DiagnosticLevel::Error))
}
pub fn push(&self, diagnostic: PublishDiagnostic) { pub fn push(&self, diagnostic: PublishDiagnostic) {
self.diagnostics.lock().unwrap().push(diagnostic); self.diagnostics.lock().push(diagnostic);
} }
} }

View file

@ -341,13 +341,11 @@ impl PublishPreparer {
bail!("Exiting due to DENO_INTERNAL_FAST_CHECK_OVERWRITE") bail!("Exiting due to DENO_INTERNAL_FAST_CHECK_OVERWRITE")
} else { } else {
log::info!("Checking for slow types in the public API..."); log::info!("Checking for slow types in the public API...");
let mut any_pkg_had_diagnostics = false;
for package in package_configs { for package in package_configs {
let export_urls = package.config_file.resolve_export_value_urls()?; let export_urls = package.config_file.resolve_export_value_urls()?;
let diagnostics = let diagnostics =
collect_no_slow_type_diagnostics(&graph, &export_urls); collect_no_slow_type_diagnostics(&graph, &export_urls);
if !diagnostics.is_empty() { if !diagnostics.is_empty() {
any_pkg_had_diagnostics = true;
for diagnostic in diagnostics { for diagnostic in diagnostics {
diagnostics_collector diagnostics_collector
.push(PublishDiagnostic::FastCheck(diagnostic)); .push(PublishDiagnostic::FastCheck(diagnostic));
@ -355,7 +353,9 @@ impl PublishPreparer {
} }
} }
if any_pkg_had_diagnostics { // skip type checking the slow type graph if there are any errors because
// errors like remote modules existing will cause type checking to crash
if diagnostics_collector.has_error() {
Ok(Arc::new(graph)) Ok(Arc::new(graph))
} else { } else {
// fast check passed, type check the output as a temporary measure // fast check passed, type check the output as a temporary measure

View file

@ -16,6 +16,7 @@ pub async fn cache_top_level_deps(
) -> Result<(), AnyError> { ) -> Result<(), AnyError> {
let npm_resolver = factory.npm_resolver().await?; let npm_resolver = factory.npm_resolver().await?;
let cli_options = factory.cli_options()?; let cli_options = factory.cli_options()?;
let root_permissions = factory.root_permissions_container()?;
if let Some(npm_resolver) = npm_resolver.as_managed() { if let Some(npm_resolver) = npm_resolver.as_managed() {
if !npm_resolver.ensure_top_level_package_json_install().await? { if !npm_resolver.ensure_top_level_package_json_install().await? {
if let Some(lockfile) = cli_options.maybe_lockfile() { if let Some(lockfile) = cli_options.maybe_lockfile() {
@ -106,7 +107,7 @@ pub async fn cache_top_level_deps(
&roots, &roots,
false, false,
deno_config::deno_json::TsTypeLib::DenoWorker, deno_config::deno_json::TsTypeLib::DenoWorker,
crate::file_fetcher::FetchPermissionsOption::AllowAll, root_permissions.clone(),
None, None,
) )
.await?; .await?;

View file

@ -162,7 +162,7 @@ pub async fn run(
let factory = CliFactory::from_flags(flags); let factory = CliFactory::from_flags(flags);
let cli_options = factory.cli_options()?; let cli_options = factory.cli_options()?;
let main_module = cli_options.resolve_main_module()?; let main_module = cli_options.resolve_main_module()?;
let permissions = factory.create_permissions_container()?; let permissions = factory.root_permissions_container()?;
let npm_resolver = factory.npm_resolver().await?.clone(); let npm_resolver = factory.npm_resolver().await?.clone();
let resolver = factory.resolver().await?.clone(); let resolver = factory.resolver().await?.clone();
let file_fetcher = factory.file_fetcher()?; let file_fetcher = factory.file_fetcher()?;
@ -177,7 +177,7 @@ pub async fn run(
.create_custom_worker( .create_custom_worker(
WorkerExecutionMode::Repl, WorkerExecutionMode::Repl,
main_module.clone(), main_module.clone(),
permissions, permissions.clone(),
vec![crate::ops::testing::deno_test::init_ops(test_event_sender)], vec![crate::ops::testing::deno_test::init_ops(test_event_sender)],
Default::default(), Default::default(),
) )
@ -189,7 +189,7 @@ pub async fn run(
npm_resolver, npm_resolver,
resolver, resolver,
worker, worker,
main_module, main_module.clone(),
test_event_receiver, test_event_receiver,
) )
.await?; .await?;

View file

@ -60,10 +60,9 @@ pub async fn run_script(
maybe_npm_install(&factory).await?; maybe_npm_install(&factory).await?;
let permissions = factory.create_permissions_container()?;
let worker_factory = factory.create_cli_main_worker_factory().await?; let worker_factory = factory.create_cli_main_worker_factory().await?;
let mut worker = worker_factory let mut worker = worker_factory
.create_main_worker(mode, main_module, permissions) .create_main_worker(mode, main_module.clone())
.await?; .await?;
let exit_code = worker.run().await?; let exit_code = worker.run().await?;
@ -79,7 +78,6 @@ pub async fn run_from_stdin(flags: Arc<Flags>) -> Result<i32, AnyError> {
let file_fetcher = factory.file_fetcher()?; let file_fetcher = factory.file_fetcher()?;
let worker_factory = factory.create_cli_main_worker_factory().await?; let worker_factory = factory.create_cli_main_worker_factory().await?;
let permissions = factory.create_permissions_container()?;
let mut source = Vec::new(); let mut source = Vec::new();
std::io::stdin().read_to_end(&mut source)?; std::io::stdin().read_to_end(&mut source)?;
// Save a fake file into file fetcher cache // Save a fake file into file fetcher cache
@ -91,7 +89,7 @@ pub async fn run_from_stdin(flags: Arc<Flags>) -> Result<i32, AnyError> {
}); });
let mut worker = worker_factory let mut worker = worker_factory
.create_main_worker(WorkerExecutionMode::Run, main_module, permissions) .create_main_worker(WorkerExecutionMode::Run, main_module.clone())
.await?; .await?;
let exit_code = worker.run().await?; let exit_code = worker.run().await?;
Ok(exit_code) Ok(exit_code)
@ -125,11 +123,10 @@ async fn run_with_watch(
let _ = watcher_communicator.watch_paths(cli_options.watch_paths()); let _ = watcher_communicator.watch_paths(cli_options.watch_paths());
let permissions = factory.create_permissions_container()?;
let mut worker = factory let mut worker = factory
.create_cli_main_worker_factory() .create_cli_main_worker_factory()
.await? .await?
.create_main_worker(mode, main_module, permissions) .create_main_worker(mode, main_module.clone())
.await?; .await?;
if watch_flags.hmr { if watch_flags.hmr {
@ -173,10 +170,9 @@ pub async fn eval_command(
source: source_code.into_bytes().into(), source: source_code.into_bytes().into(),
}); });
let permissions = factory.create_permissions_container()?;
let worker_factory = factory.create_cli_main_worker_factory().await?; let worker_factory = factory.create_cli_main_worker_factory().await?;
let mut worker = worker_factory let mut worker = worker_factory
.create_main_worker(WorkerExecutionMode::Eval, main_module, permissions) .create_main_worker(WorkerExecutionMode::Eval, main_module.clone())
.await?; .await?;
let exit_code = worker.run().await?; let exit_code = worker.run().await?;
Ok(exit_code) Ok(exit_code)

View file

@ -5,7 +5,6 @@ use std::sync::Arc;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::futures::TryFutureExt; use deno_core::futures::TryFutureExt;
use deno_core::ModuleSpecifier; use deno_core::ModuleSpecifier;
use deno_runtime::deno_permissions::PermissionsContainer;
use super::run::check_permission_before_script; use super::run::check_permission_before_script;
use super::run::maybe_npm_install; use super::run::maybe_npm_install;
@ -44,13 +43,11 @@ pub async fn serve(
maybe_npm_install(&factory).await?; maybe_npm_install(&factory).await?;
let permissions = factory.create_permissions_container()?;
let worker_factory = factory.create_cli_main_worker_factory().await?; let worker_factory = factory.create_cli_main_worker_factory().await?;
do_serve( do_serve(
worker_factory, worker_factory,
main_module, main_module.clone(),
permissions,
serve_flags.worker_count, serve_flags.worker_count,
false, false,
) )
@ -60,7 +57,6 @@ pub async fn serve(
async fn do_serve( async fn do_serve(
worker_factory: CliMainWorkerFactory, worker_factory: CliMainWorkerFactory,
main_module: ModuleSpecifier, main_module: ModuleSpecifier,
permissions: PermissionsContainer,
worker_count: Option<usize>, worker_count: Option<usize>,
hmr: bool, hmr: bool,
) -> Result<i32, AnyError> { ) -> Result<i32, AnyError> {
@ -71,7 +67,6 @@ async fn do_serve(
worker_count, worker_count,
}, },
main_module.clone(), main_module.clone(),
permissions.clone(),
) )
.await?; .await?;
let worker_count = match worker_count { let worker_count = match worker_count {
@ -87,15 +82,13 @@ async fn do_serve(
for i in 0..extra_workers { for i in 0..extra_workers {
let worker_factory = worker_factory.clone(); let worker_factory = worker_factory.clone();
let main_module = main_module.clone(); let main_module = main_module.clone();
let permissions = permissions.clone();
let (tx, rx) = tokio::sync::oneshot::channel(); let (tx, rx) = tokio::sync::oneshot::channel();
channels.push(rx); channels.push(rx);
std::thread::Builder::new() std::thread::Builder::new()
.name(format!("serve-worker-{i}")) .name(format!("serve-worker-{i}"))
.spawn(move || { .spawn(move || {
deno_runtime::tokio_util::create_and_run_current_thread(async move { deno_runtime::tokio_util::create_and_run_current_thread(async move {
let result = let result = run_worker(i, worker_factory, main_module, hmr).await;
run_worker(i, worker_factory, main_module, permissions, hmr).await;
let _ = tx.send(result); let _ = tx.send(result);
}); });
})?; })?;
@ -124,7 +117,6 @@ async fn run_worker(
worker_count: usize, worker_count: usize,
worker_factory: CliMainWorkerFactory, worker_factory: CliMainWorkerFactory,
main_module: ModuleSpecifier, main_module: ModuleSpecifier,
permissions: PermissionsContainer,
hmr: bool, hmr: bool,
) -> Result<i32, AnyError> { ) -> Result<i32, AnyError> {
let mut worker = worker_factory let mut worker = worker_factory
@ -134,7 +126,6 @@ async fn run_worker(
worker_count: Some(worker_count), worker_count: Some(worker_count),
}, },
main_module, main_module,
permissions,
) )
.await?; .await?;
if hmr { if hmr {
@ -171,11 +162,9 @@ async fn serve_with_watch(
maybe_npm_install(&factory).await?; maybe_npm_install(&factory).await?;
let _ = watcher_communicator.watch_paths(cli_options.watch_paths()); let _ = watcher_communicator.watch_paths(cli_options.watch_paths());
let permissions = factory.create_permissions_container()?;
let worker_factory = factory.create_cli_main_worker_factory().await?; let worker_factory = factory.create_cli_main_worker_factory().await?;
do_serve(worker_factory, main_module, permissions, worker_count, hmr) do_serve(worker_factory, main_module.clone(), worker_count, hmr)
.await?; .await?;
Ok(()) Ok(())

View file

@ -62,13 +62,12 @@ pub trait ModuleLoaderFactory: Send + Sync {
fn create_for_main( fn create_for_main(
&self, &self,
root_permissions: PermissionsContainer, root_permissions: PermissionsContainer,
dynamic_permissions: PermissionsContainer,
) -> ModuleLoaderAndSourceMapGetter; ) -> ModuleLoaderAndSourceMapGetter;
fn create_for_worker( fn create_for_worker(
&self, &self,
root_permissions: PermissionsContainer, parent_permissions: PermissionsContainer,
dynamic_permissions: PermissionsContainer, permissions: PermissionsContainer,
) -> ModuleLoaderAndSourceMapGetter; ) -> ModuleLoaderAndSourceMapGetter;
} }
@ -136,6 +135,7 @@ struct SharedWorkerState {
npm_resolver: Arc<dyn CliNpmResolver>, npm_resolver: Arc<dyn CliNpmResolver>,
permission_desc_parser: Arc<RuntimePermissionDescriptorParser>, permission_desc_parser: Arc<RuntimePermissionDescriptorParser>,
root_cert_store_provider: Arc<dyn RootCertStoreProvider>, root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
root_permissions: PermissionsContainer,
shared_array_buffer_store: SharedArrayBufferStore, shared_array_buffer_store: SharedArrayBufferStore,
storage_key_resolver: StorageKeyResolver, storage_key_resolver: StorageKeyResolver,
options: CliMainWorkerOptions, options: CliMainWorkerOptions,
@ -432,6 +432,7 @@ impl CliMainWorkerFactory {
npm_resolver: Arc<dyn CliNpmResolver>, npm_resolver: Arc<dyn CliNpmResolver>,
permission_parser: Arc<RuntimePermissionDescriptorParser>, permission_parser: Arc<RuntimePermissionDescriptorParser>,
root_cert_store_provider: Arc<dyn RootCertStoreProvider>, root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
root_permissions: PermissionsContainer,
storage_key_resolver: StorageKeyResolver, storage_key_resolver: StorageKeyResolver,
subcommand: DenoSubcommand, subcommand: DenoSubcommand,
options: CliMainWorkerOptions, options: CliMainWorkerOptions,
@ -452,6 +453,7 @@ impl CliMainWorkerFactory {
npm_resolver, npm_resolver,
permission_desc_parser: permission_parser, permission_desc_parser: permission_parser,
root_cert_store_provider, root_cert_store_provider,
root_permissions,
shared_array_buffer_store: Default::default(), shared_array_buffer_store: Default::default(),
storage_key_resolver, storage_key_resolver,
options, options,
@ -464,13 +466,12 @@ impl CliMainWorkerFactory {
&self, &self,
mode: WorkerExecutionMode, mode: WorkerExecutionMode,
main_module: ModuleSpecifier, main_module: ModuleSpecifier,
permissions: PermissionsContainer,
) -> Result<CliMainWorker, AnyError> { ) -> Result<CliMainWorker, AnyError> {
self self
.create_custom_worker( .create_custom_worker(
mode, mode,
main_module, main_module,
permissions, self.shared.root_permissions.clone(),
vec![], vec![],
Default::default(), Default::default(),
) )
@ -530,13 +531,9 @@ impl CliMainWorkerFactory {
(main_module, is_cjs) (main_module, is_cjs)
}; };
let ModuleLoaderAndSourceMapGetter { module_loader } = let ModuleLoaderAndSourceMapGetter { module_loader } = shared
shared.module_loader_factory.create_for_main( .module_loader_factory
PermissionsContainer::allow_all( .create_for_main(permissions.clone());
self.shared.permission_desc_parser.clone(),
),
permissions.clone(),
);
let maybe_inspector_server = shared.maybe_inspector_server.clone(); let maybe_inspector_server = shared.maybe_inspector_server.clone();
let create_web_worker_cb = let create_web_worker_cb =

View file

@ -12,6 +12,7 @@ use deno_permissions::AllowRunDescriptorParseResult;
use deno_permissions::DenyRunDescriptor; use deno_permissions::DenyRunDescriptor;
use deno_permissions::EnvDescriptor; use deno_permissions::EnvDescriptor;
use deno_permissions::FfiDescriptor; use deno_permissions::FfiDescriptor;
use deno_permissions::ImportDescriptor;
use deno_permissions::NetDescriptor; use deno_permissions::NetDescriptor;
use deno_permissions::PathQueryDescriptor; use deno_permissions::PathQueryDescriptor;
use deno_permissions::ReadDescriptor; use deno_permissions::ReadDescriptor;
@ -75,6 +76,13 @@ impl deno_permissions::PermissionDescriptorParser
NetDescriptor::parse(text) NetDescriptor::parse(text)
} }
fn parse_import_descriptor(
&self,
text: &str,
) -> Result<ImportDescriptor, AnyError> {
ImportDescriptor::parse(text)
}
fn parse_env_descriptor( fn parse_env_descriptor(
&self, &self,
text: &str, text: &str,

View file

@ -14,7 +14,6 @@ use deno_core::serde::Deserializer;
use deno_core::serde::Serialize; use deno_core::serde::Serialize;
use deno_core::serde_json; use deno_core::serde_json;
use deno_core::unsync::sync::AtomicFlag; use deno_core::unsync::sync::AtomicFlag;
use deno_core::url;
use deno_core::url::Url; use deno_core::url::Url;
use deno_core::ModuleSpecifier; use deno_core::ModuleSpecifier;
use deno_terminal::colors; use deno_terminal::colors;
@ -950,6 +949,15 @@ impl NetDescriptor {
Ok(NetDescriptor(host, port)) Ok(NetDescriptor(host, port))
} }
pub fn from_url(url: &Url) -> Result<Self, AnyError> {
let host = url
.host_str()
.ok_or_else(|| type_error(format!("Missing host in url: '{}'", url)))?;
let host = Host::parse(host)?;
let port = url.port_or_known_default();
Ok(NetDescriptor(host, port))
}
} }
impl fmt::Display for NetDescriptor { impl fmt::Display for NetDescriptor {
@ -966,6 +974,73 @@ impl fmt::Display for NetDescriptor {
} }
} }
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct ImportDescriptor(NetDescriptor);
impl QueryDescriptor for ImportDescriptor {
type AllowDesc = ImportDescriptor;
type DenyDesc = ImportDescriptor;
fn flag_name() -> &'static str {
"import"
}
fn display_name(&self) -> Cow<str> {
self.0.display_name()
}
fn from_allow(allow: &Self::AllowDesc) -> Self {
Self(NetDescriptor::from_allow(&allow.0))
}
fn as_allow(&self) -> Option<Self::AllowDesc> {
self.0.as_allow().map(ImportDescriptor)
}
fn as_deny(&self) -> Self::DenyDesc {
Self(self.0.as_deny())
}
fn check_in_permission(
&self,
perm: &mut UnaryPermission<Self>,
api_name: Option<&str>,
) -> Result<(), AnyError> {
skip_check_if_is_permission_fully_granted!(perm);
perm.check_desc(Some(self), false, api_name)
}
fn matches_allow(&self, other: &Self::AllowDesc) -> bool {
self.0.matches_allow(&other.0)
}
fn matches_deny(&self, other: &Self::DenyDesc) -> bool {
self.0.matches_deny(&other.0)
}
fn revokes(&self, other: &Self::AllowDesc) -> bool {
self.0.revokes(&other.0)
}
fn stronger_than_deny(&self, other: &Self::DenyDesc) -> bool {
self.0.stronger_than_deny(&other.0)
}
fn overlaps_deny(&self, other: &Self::DenyDesc) -> bool {
self.0.overlaps_deny(&other.0)
}
}
impl ImportDescriptor {
pub fn parse(specifier: &str) -> Result<Self, AnyError> {
Ok(ImportDescriptor(NetDescriptor::parse(specifier)?))
}
pub fn from_url(url: &Url) -> Result<Self, AnyError> {
Ok(ImportDescriptor(NetDescriptor::from_url(url)?))
}
}
#[derive(Clone, Eq, PartialEq, Hash, Debug)] #[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct EnvDescriptor(EnvVarName); pub struct EnvDescriptor(EnvVarName);
@ -1519,19 +1594,35 @@ impl UnaryPermission<NetDescriptor> {
self.check_desc(Some(host), false, api_name) self.check_desc(Some(host), false, api_name)
} }
pub fn check_url( pub fn check_all(&mut self) -> Result<(), AnyError> {
skip_check_if_is_permission_fully_granted!(self);
self.check_desc(None, false, None)
}
}
impl UnaryPermission<ImportDescriptor> {
pub fn query(&self, host: Option<&ImportDescriptor>) -> PermissionState {
self.query_desc(host, AllowPartial::TreatAsPartialGranted)
}
pub fn request(
&mut self, &mut self,
url: &url::Url, host: Option<&ImportDescriptor>,
) -> PermissionState {
self.request_desc(host)
}
pub fn revoke(&mut self, host: Option<&ImportDescriptor>) -> PermissionState {
self.revoke_desc(host)
}
pub fn check(
&mut self,
host: &ImportDescriptor,
api_name: Option<&str>, api_name: Option<&str>,
) -> Result<(), AnyError> { ) -> Result<(), AnyError> {
skip_check_if_is_permission_fully_granted!(self); skip_check_if_is_permission_fully_granted!(self);
let host = url self.check_desc(Some(host), false, api_name)
.host_str()
.ok_or_else(|| type_error(format!("Missing host in url: '{}'", url)))?;
let host = Host::parse(host)?;
let port = url.port_or_known_default();
let descriptor = NetDescriptor(host, port);
self.check_desc(Some(&descriptor), false, api_name)
} }
pub fn check_all(&mut self) -> Result<(), AnyError> { pub fn check_all(&mut self) -> Result<(), AnyError> {
@ -1700,6 +1791,7 @@ pub struct Permissions {
pub sys: UnaryPermission<SysDescriptor>, pub sys: UnaryPermission<SysDescriptor>,
pub run: UnaryPermission<RunQueryDescriptor>, pub run: UnaryPermission<RunQueryDescriptor>,
pub ffi: UnaryPermission<FfiQueryDescriptor>, pub ffi: UnaryPermission<FfiQueryDescriptor>,
pub import: UnaryPermission<ImportDescriptor>,
pub all: UnitPermission, pub all: UnitPermission,
} }
@ -1720,6 +1812,7 @@ pub struct PermissionsOptions {
pub deny_sys: Option<Vec<String>>, pub deny_sys: Option<Vec<String>>,
pub allow_write: Option<Vec<String>>, pub allow_write: Option<Vec<String>>,
pub deny_write: Option<Vec<String>>, pub deny_write: Option<Vec<String>>,
pub allow_import: Option<Vec<String>>,
pub prompt: bool, pub prompt: bool,
} }
@ -1888,6 +1981,13 @@ impl Permissions {
})?, })?,
opts.prompt, opts.prompt,
)?, )?,
import: Permissions::new_unary(
parse_maybe_vec(opts.allow_import.as_deref(), |item| {
parser.parse_import_descriptor(item)
})?,
None,
opts.prompt,
)?,
all: Permissions::new_all(opts.allow_all), all: Permissions::new_all(opts.allow_all),
}) })
} }
@ -1902,6 +2002,7 @@ impl Permissions {
sys: UnaryPermission::allow_all(), sys: UnaryPermission::allow_all(),
run: UnaryPermission::allow_all(), run: UnaryPermission::allow_all(),
ffi: UnaryPermission::allow_all(), ffi: UnaryPermission::allow_all(),
import: UnaryPermission::allow_all(),
all: Permissions::new_all(true), all: Permissions::new_all(true),
} }
} }
@ -1925,35 +2026,10 @@ impl Permissions {
sys: Permissions::new_unary(None, None, prompt).unwrap(), sys: Permissions::new_unary(None, None, prompt).unwrap(),
run: Permissions::new_unary(None, None, prompt).unwrap(), run: Permissions::new_unary(None, None, prompt).unwrap(),
ffi: Permissions::new_unary(None, None, prompt).unwrap(), ffi: Permissions::new_unary(None, None, prompt).unwrap(),
import: Permissions::new_unary(None, None, prompt).unwrap(),
all: Permissions::new_all(false), all: Permissions::new_all(false),
} }
} }
/// A helper function that determines if the module specifier is a local or
/// remote, and performs a read or net check for the specifier.
pub fn check_specifier(
&mut self,
specifier: &ModuleSpecifier,
) -> Result<(), AnyError> {
match specifier.scheme() {
"file" => match specifier_to_file_path(specifier) {
Ok(path) => self.read.check(
&PathQueryDescriptor {
requested: path.to_string_lossy().into_owned(),
resolved: path,
}
.into_read(),
Some("import()"),
),
Err(_) => Err(uri_error(format!(
"Invalid file path.\n Specifier: {specifier}"
))),
},
"data" => Ok(()),
"blob" => Ok(()),
_ => self.net.check_url(specifier, Some("import()")),
}
}
} }
/// Attempts to convert a specifier to a file path. By default, uses the Url /// Attempts to convert a specifier to a file path. By default, uses the Url
@ -2002,6 +2078,12 @@ pub fn specifier_to_file_path(
} }
} }
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum CheckSpecifierKind {
Static,
Dynamic,
}
/// Wrapper struct for `Permissions` that can be shared across threads. /// Wrapper struct for `Permissions` that can be shared across threads.
/// ///
/// We need a way to have internal mutability for permissions as they might get /// We need a way to have internal mutability for permissions as they might get
@ -2039,8 +2121,43 @@ impl PermissionsContainer {
pub fn check_specifier( pub fn check_specifier(
&self, &self,
specifier: &ModuleSpecifier, specifier: &ModuleSpecifier,
kind: CheckSpecifierKind,
) -> Result<(), AnyError> { ) -> Result<(), AnyError> {
self.inner.lock().check_specifier(specifier) let mut inner = self.inner.lock();
match specifier.scheme() {
"file" => {
if inner.read.is_allow_all() || kind == CheckSpecifierKind::Static {
return Ok(());
}
match specifier_to_file_path(specifier) {
Ok(path) => inner.read.check(
&PathQueryDescriptor {
requested: path.to_string_lossy().into_owned(),
resolved: path,
}
.into_read(),
Some("import()"),
),
Err(_) => Err(uri_error(format!(
"Invalid file path.\n Specifier: {specifier}"
))),
}
}
"data" => Ok(()),
"blob" => Ok(()),
_ => {
if inner.import.is_allow_all() {
return Ok(()); // avoid allocation below
}
let desc = self
.descriptor_parser
.parse_import_descriptor_from_url(specifier)?;
inner.import.check(&desc, Some("import()"))?;
Ok(())
}
}
} }
#[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"] #[must_use = "the resolved return value to mitigate time-of-check to time-of-use issues"]
@ -2375,7 +2492,12 @@ impl PermissionsContainer {
url: &Url, url: &Url,
api_name: &str, api_name: &str,
) -> Result<(), AnyError> { ) -> Result<(), AnyError> {
self.inner.lock().net.check_url(url, Some(api_name)) let mut inner = self.inner.lock();
if inner.net.is_allow_all() {
return Ok(());
}
let desc = self.descriptor_parser.parse_net_descriptor_from_url(url)?;
inner.net.check(&desc, Some(api_name))
} }
#[inline(always)] #[inline(always)]
@ -2589,6 +2711,7 @@ pub struct ChildPermissionsArg {
env: ChildUnaryPermissionArg, env: ChildUnaryPermissionArg,
net: ChildUnaryPermissionArg, net: ChildUnaryPermissionArg,
ffi: ChildUnaryPermissionArg, ffi: ChildUnaryPermissionArg,
import: ChildUnaryPermissionArg,
read: ChildUnaryPermissionArg, read: ChildUnaryPermissionArg,
run: ChildUnaryPermissionArg, run: ChildUnaryPermissionArg,
sys: ChildUnaryPermissionArg, sys: ChildUnaryPermissionArg,
@ -2601,6 +2724,7 @@ impl ChildPermissionsArg {
env: ChildUnaryPermissionArg::Inherit, env: ChildUnaryPermissionArg::Inherit,
net: ChildUnaryPermissionArg::Inherit, net: ChildUnaryPermissionArg::Inherit,
ffi: ChildUnaryPermissionArg::Inherit, ffi: ChildUnaryPermissionArg::Inherit,
import: ChildUnaryPermissionArg::Inherit,
read: ChildUnaryPermissionArg::Inherit, read: ChildUnaryPermissionArg::Inherit,
run: ChildUnaryPermissionArg::Inherit, run: ChildUnaryPermissionArg::Inherit,
sys: ChildUnaryPermissionArg::Inherit, sys: ChildUnaryPermissionArg::Inherit,
@ -2613,6 +2737,7 @@ impl ChildPermissionsArg {
env: ChildUnaryPermissionArg::NotGranted, env: ChildUnaryPermissionArg::NotGranted,
net: ChildUnaryPermissionArg::NotGranted, net: ChildUnaryPermissionArg::NotGranted,
ffi: ChildUnaryPermissionArg::NotGranted, ffi: ChildUnaryPermissionArg::NotGranted,
import: ChildUnaryPermissionArg::NotGranted,
read: ChildUnaryPermissionArg::NotGranted, read: ChildUnaryPermissionArg::NotGranted,
run: ChildUnaryPermissionArg::NotGranted, run: ChildUnaryPermissionArg::NotGranted,
sys: ChildUnaryPermissionArg::NotGranted, sys: ChildUnaryPermissionArg::NotGranted,
@ -2677,6 +2802,11 @@ impl<'de> Deserialize<'de> for ChildPermissionsArg {
child_permissions_arg.ffi = arg.map_err(|e| { child_permissions_arg.ffi = arg.map_err(|e| {
de::Error::custom(format!("(deno.permissions.ffi) {e}")) de::Error::custom(format!("(deno.permissions.ffi) {e}"))
})?; })?;
} else if key == "import" {
let arg = serde_json::from_value::<ChildUnaryPermissionArg>(value);
child_permissions_arg.import = arg.map_err(|e| {
de::Error::custom(format!("(deno.permissions.import) {e}"))
})?;
} else if key == "read" { } else if key == "read" {
let arg = serde_json::from_value::<ChildUnaryPermissionArg>(value); let arg = serde_json::from_value::<ChildUnaryPermissionArg>(value);
child_permissions_arg.read = arg.map_err(|e| { child_permissions_arg.read = arg.map_err(|e| {
@ -2726,6 +2856,25 @@ pub trait PermissionDescriptorParser: Debug + Send + Sync {
fn parse_net_descriptor(&self, text: &str) fn parse_net_descriptor(&self, text: &str)
-> Result<NetDescriptor, AnyError>; -> Result<NetDescriptor, AnyError>;
fn parse_net_descriptor_from_url(
&self,
url: &Url,
) -> Result<NetDescriptor, AnyError> {
NetDescriptor::from_url(url)
}
fn parse_import_descriptor(
&self,
text: &str,
) -> Result<ImportDescriptor, AnyError>;
fn parse_import_descriptor_from_url(
&self,
url: &Url,
) -> Result<ImportDescriptor, AnyError> {
ImportDescriptor::from_url(url)
}
fn parse_env_descriptor(&self, text: &str) fn parse_env_descriptor(&self, text: &str)
-> Result<EnvDescriptor, AnyError>; -> Result<EnvDescriptor, AnyError>;
@ -2785,6 +2934,7 @@ pub fn create_child_permissions(
&child_permissions_arg.read, &child_permissions_arg.read,
&child_permissions_arg.write, &child_permissions_arg.write,
&child_permissions_arg.net, &child_permissions_arg.net,
&child_permissions_arg.import,
&child_permissions_arg.env, &child_permissions_arg.env,
&child_permissions_arg.sys, &child_permissions_arg.sys,
&child_permissions_arg.run, &child_permissions_arg.run,
@ -2808,6 +2958,11 @@ pub fn create_child_permissions(
.create_child_permissions(child_permissions_arg.write, |text| { .create_child_permissions(child_permissions_arg.write, |text| {
Ok(Some(parser.parse_write_descriptor(text)?)) Ok(Some(parser.parse_write_descriptor(text)?))
})?; })?;
worker_perms.import = main_perms
.import
.create_child_permissions(child_permissions_arg.import, |text| {
Ok(Some(parser.parse_import_descriptor(text)?))
})?;
worker_perms.net = main_perms worker_perms.net = main_perms
.net .net
.create_child_permissions(child_permissions_arg.net, |text| { .create_child_permissions(child_permissions_arg.net, |text| {
@ -2897,6 +3052,13 @@ mod tests {
NetDescriptor::parse(text) NetDescriptor::parse(text)
} }
fn parse_import_descriptor(
&self,
text: &str,
) -> Result<ImportDescriptor, AnyError> {
ImportDescriptor::parse(text)
}
fn parse_env_descriptor( fn parse_env_descriptor(
&self, &self,
text: &str, text: &str,
@ -3153,8 +3315,9 @@ mod tests {
#[test] #[test]
fn test_check_net_url() { fn test_check_net_url() {
let mut perms = Permissions::from_options( let parser = TestPermissionDescriptorParser;
&TestPermissionDescriptorParser, let perms = Permissions::from_options(
&parser,
&PermissionsOptions { &PermissionsOptions {
allow_net: Some(svec![ allow_net: Some(svec![
"localhost", "localhost",
@ -3168,6 +3331,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let mut perms = PermissionsContainer::new(Arc::new(parser), perms);
let url_tests = vec![ let url_tests = vec![
// Any protocol + port for localhost should be ok, since we don't specify // Any protocol + port for localhost should be ok, since we don't specify
@ -3209,8 +3373,8 @@ mod tests {
]; ];
for (url_str, is_ok) in url_tests { for (url_str, is_ok) in url_tests {
let u = url::Url::parse(url_str).unwrap(); let u = Url::parse(url_str).unwrap();
assert_eq!(is_ok, perms.net.check_url(&u, None).is_ok(), "{}", u); assert_eq!(is_ok, perms.check_net_url(&u, "api()").is_ok(), "{}", u);
} }
} }
@ -3222,48 +3386,78 @@ mod tests {
} else { } else {
svec!["/a"] svec!["/a"]
}; };
let mut perms = Permissions::from_options( let parser = TestPermissionDescriptorParser;
&TestPermissionDescriptorParser, let perms = Permissions::from_options(
&parser,
&PermissionsOptions { &PermissionsOptions {
allow_read: Some(read_allowlist), allow_read: Some(read_allowlist),
allow_net: Some(svec!["localhost"]), allow_import: Some(svec!["localhost"]),
..Default::default() ..Default::default()
}, },
) )
.unwrap(); .unwrap();
let perms = PermissionsContainer::new(Arc::new(parser), perms);
let mut fixtures = vec![ let mut fixtures = vec![
( (
ModuleSpecifier::parse("http://localhost:4545/mod.ts").unwrap(), ModuleSpecifier::parse("http://localhost:4545/mod.ts").unwrap(),
CheckSpecifierKind::Static,
true,
),
(
ModuleSpecifier::parse("http://localhost:4545/mod.ts").unwrap(),
CheckSpecifierKind::Dynamic,
true, true,
), ),
( (
ModuleSpecifier::parse("http://deno.land/x/mod.ts").unwrap(), ModuleSpecifier::parse("http://deno.land/x/mod.ts").unwrap(),
CheckSpecifierKind::Dynamic,
false, false,
), ),
( (
ModuleSpecifier::parse("data:text/plain,Hello%2C%20Deno!").unwrap(), ModuleSpecifier::parse("data:text/plain,Hello%2C%20Deno!").unwrap(),
CheckSpecifierKind::Dynamic,
true, true,
), ),
]; ];
if cfg!(target_os = "windows") { if cfg!(target_os = "windows") {
fixtures fixtures.push((
.push((ModuleSpecifier::parse("file:///C:/a/mod.ts").unwrap(), true)); ModuleSpecifier::parse("file:///C:/a/mod.ts").unwrap(),
CheckSpecifierKind::Dynamic,
true,
));
fixtures.push(( fixtures.push((
ModuleSpecifier::parse("file:///C:/b/mod.ts").unwrap(), ModuleSpecifier::parse("file:///C:/b/mod.ts").unwrap(),
CheckSpecifierKind::Static,
true,
));
fixtures.push((
ModuleSpecifier::parse("file:///C:/b/mod.ts").unwrap(),
CheckSpecifierKind::Dynamic,
false, false,
)); ));
} else { } else {
fixtures fixtures.push((
.push((ModuleSpecifier::parse("file:///a/mod.ts").unwrap(), true)); ModuleSpecifier::parse("file:///a/mod.ts").unwrap(),
fixtures CheckSpecifierKind::Dynamic,
.push((ModuleSpecifier::parse("file:///b/mod.ts").unwrap(), false)); true,
));
fixtures.push((
ModuleSpecifier::parse("file:///b/mod.ts").unwrap(),
CheckSpecifierKind::Static,
true,
));
fixtures.push((
ModuleSpecifier::parse("file:///b/mod.ts").unwrap(),
CheckSpecifierKind::Dynamic,
false,
));
} }
for (specifier, expected) in fixtures { for (specifier, kind, expected) in fixtures {
assert_eq!( assert_eq!(
perms.check_specifier(&specifier).is_ok(), perms.check_specifier(&specifier, kind).is_ok(),
expected, expected,
"{}", "{}",
specifier, specifier,
@ -3271,24 +3465,6 @@ mod tests {
} }
} }
#[test]
fn check_invalid_specifiers() {
set_prompter(Box::new(TestPrompter));
let mut perms = Permissions::allow_all();
let mut test_cases = vec![];
test_cases.push("file://dir");
test_cases.push("file://asdf/");
test_cases.push("file://remotehost/");
for url in test_cases {
assert!(perms
.check_specifier(&ModuleSpecifier::parse(url).unwrap())
.is_err());
}
}
#[test] #[test]
fn test_query() { fn test_query() {
set_prompter(Box::new(TestPrompter)); set_prompter(Box::new(TestPrompter));
@ -3885,6 +4061,7 @@ mod tests {
env: ChildUnaryPermissionArg::Inherit, env: ChildUnaryPermissionArg::Inherit,
net: ChildUnaryPermissionArg::Inherit, net: ChildUnaryPermissionArg::Inherit,
ffi: ChildUnaryPermissionArg::Inherit, ffi: ChildUnaryPermissionArg::Inherit,
import: ChildUnaryPermissionArg::Inherit,
read: ChildUnaryPermissionArg::Inherit, read: ChildUnaryPermissionArg::Inherit,
run: ChildUnaryPermissionArg::Inherit, run: ChildUnaryPermissionArg::Inherit,
sys: ChildUnaryPermissionArg::Inherit, sys: ChildUnaryPermissionArg::Inherit,
@ -3897,6 +4074,7 @@ mod tests {
env: ChildUnaryPermissionArg::NotGranted, env: ChildUnaryPermissionArg::NotGranted,
net: ChildUnaryPermissionArg::NotGranted, net: ChildUnaryPermissionArg::NotGranted,
ffi: ChildUnaryPermissionArg::NotGranted, ffi: ChildUnaryPermissionArg::NotGranted,
import: ChildUnaryPermissionArg::NotGranted,
read: ChildUnaryPermissionArg::NotGranted, read: ChildUnaryPermissionArg::NotGranted,
run: ChildUnaryPermissionArg::NotGranted, run: ChildUnaryPermissionArg::NotGranted,
sys: ChildUnaryPermissionArg::NotGranted, sys: ChildUnaryPermissionArg::NotGranted,
@ -3930,6 +4108,7 @@ mod tests {
"env": true, "env": true,
"net": true, "net": true,
"ffi": true, "ffi": true,
"import": true,
"read": true, "read": true,
"run": true, "run": true,
"sys": true, "sys": true,
@ -3940,6 +4119,7 @@ mod tests {
env: ChildUnaryPermissionArg::Granted, env: ChildUnaryPermissionArg::Granted,
net: ChildUnaryPermissionArg::Granted, net: ChildUnaryPermissionArg::Granted,
ffi: ChildUnaryPermissionArg::Granted, ffi: ChildUnaryPermissionArg::Granted,
import: ChildUnaryPermissionArg::Granted,
read: ChildUnaryPermissionArg::Granted, read: ChildUnaryPermissionArg::Granted,
run: ChildUnaryPermissionArg::Granted, run: ChildUnaryPermissionArg::Granted,
sys: ChildUnaryPermissionArg::Granted, sys: ChildUnaryPermissionArg::Granted,
@ -3951,6 +4131,7 @@ mod tests {
"env": false, "env": false,
"net": false, "net": false,
"ffi": false, "ffi": false,
"import": false,
"read": false, "read": false,
"run": false, "run": false,
"sys": false, "sys": false,
@ -3961,6 +4142,7 @@ mod tests {
env: ChildUnaryPermissionArg::NotGranted, env: ChildUnaryPermissionArg::NotGranted,
net: ChildUnaryPermissionArg::NotGranted, net: ChildUnaryPermissionArg::NotGranted,
ffi: ChildUnaryPermissionArg::NotGranted, ffi: ChildUnaryPermissionArg::NotGranted,
import: ChildUnaryPermissionArg::NotGranted,
read: ChildUnaryPermissionArg::NotGranted, read: ChildUnaryPermissionArg::NotGranted,
run: ChildUnaryPermissionArg::NotGranted, run: ChildUnaryPermissionArg::NotGranted,
sys: ChildUnaryPermissionArg::NotGranted, sys: ChildUnaryPermissionArg::NotGranted,
@ -3972,6 +4154,7 @@ mod tests {
"env": ["foo", "bar"], "env": ["foo", "bar"],
"net": ["foo", "bar:8000"], "net": ["foo", "bar:8000"],
"ffi": ["foo", "file:///bar/baz"], "ffi": ["foo", "file:///bar/baz"],
"import": ["example.com"],
"read": ["foo", "file:///bar/baz"], "read": ["foo", "file:///bar/baz"],
"run": ["foo", "file:///bar/baz", "./qux"], "run": ["foo", "file:///bar/baz", "./qux"],
"sys": ["hostname", "osRelease"], "sys": ["hostname", "osRelease"],
@ -3985,6 +4168,7 @@ mod tests {
"foo", "foo",
"file:///bar/baz" "file:///bar/baz"
]), ]),
import: ChildUnaryPermissionArg::GrantedList(svec!["example.com"]),
read: ChildUnaryPermissionArg::GrantedList(svec![ read: ChildUnaryPermissionArg::GrantedList(svec![
"foo", "foo",
"file:///bar/baz" "file:///bar/baz"

View file

@ -18,7 +18,7 @@ fn xdg_cache_home_dir() {
.env_clear() .env_clear()
.env("XDG_CACHE_HOME", &xdg_cache_home) .env("XDG_CACHE_HOME", &xdg_cache_home)
.args( .args(
"cache --reload --no-check http://localhost:4548/subdir/redirects/a.ts", "cache --allow-import --reload --no-check http://localhost:4548/subdir/redirects/a.ts",
) )
.run() .run()
.skip_output_check() .skip_output_check()

View file

@ -9,14 +9,14 @@ use util::TestContext;
use util::TestContextBuilder; use util::TestContextBuilder;
itest!(check_all { itest!(check_all {
args: "check --quiet --all check/all/check_all.ts", args: "check --allow-import --quiet --all check/all/check_all.ts",
output: "check/all/check_all.out", output: "check/all/check_all.out",
http_server: true, http_server: true,
exit_code: 1, exit_code: 1,
}); });
itest!(check_all_local { itest!(check_all_local {
args: "check --quiet check/all/check_all.ts", args: "check --allow-import --quiet check/all/check_all.ts",
output_str: Some(""), output_str: Some(""),
http_server: true, http_server: true,
}); });
@ -227,6 +227,7 @@ fn ts_no_recheck_on_redirect() {
let test_context = TestContext::default(); let test_context = TestContext::default();
let check_command = test_context.new_command().args_vec([ let check_command = test_context.new_command().args_vec([
"run", "run",
"--allow-import",
"--check", "--check",
"run/017_import_redirect.ts", "run/017_import_redirect.ts",
]); ]);

View file

@ -539,6 +539,7 @@ fn check_local_by_default() {
.new_command() .new_command()
.args_vec([ .args_vec([
"compile", "compile",
"--allow-import",
"--output", "--output",
&exe.to_string_lossy(), &exe.to_string_lossy(),
"./compile/check_local_by_default.ts", "./compile/check_local_by_default.ts",
@ -561,6 +562,7 @@ fn check_local_by_default2() {
.new_command() .new_command()
.args_vec([ .args_vec([
"compile", "compile",
"--allow-import",
"--output", "--output",
&exe.to_string_lossy(), &exe.to_string_lossy(),
"./compile/check_local_by_default2.ts" "./compile/check_local_by_default2.ts"

View file

@ -456,6 +456,7 @@ fn no_http_coverage_data() {
.new_command() .new_command()
.args_vec(vec![ .args_vec(vec![
"test".to_string(), "test".to_string(),
"--allow-import".to_string(),
"--quiet".to_string(), "--quiet".to_string(),
"--no-check".to_string(), "--no-check".to_string(),
format!("--coverage={}", tempdir), format!("--coverage={}", tempdir),

View file

@ -294,7 +294,7 @@ fn check_local_by_default() {
let script_path_str = script_path.to_string_lossy().to_string(); let script_path_str = script_path.to_string_lossy().to_string();
context context
.new_command() .new_command()
.args_vec(["install", "-g", script_path_str.as_str()]) .args_vec(["install", "-g", "--allow-import", script_path_str.as_str()])
.envs([ .envs([
("HOME", temp_dir_str.as_str()), ("HOME", temp_dir_str.as_str()),
("USERPROFILE", temp_dir_str.as_str()), ("USERPROFILE", temp_dir_str.as_str()),
@ -318,7 +318,7 @@ fn check_local_by_default2() {
let script_path_str = script_path.to_string_lossy().to_string(); let script_path_str = script_path.to_string_lossy().to_string();
context context
.new_command() .new_command()
.args_vec(["install", "-g", script_path_str.as_str()]) .args_vec(["install", "-g", "--allow-import", script_path_str.as_str()])
.envs([ .envs([
("HOME", temp_dir_str.as_str()), ("HOME", temp_dir_str.as_str()),
("NO_COLOR", "1"), ("NO_COLOR", "1"),

View file

@ -890,7 +890,7 @@ fn lsp_format_vendor_path() {
// put this dependency in the global cache // put this dependency in the global cache
context context
.new_command() .new_command()
.args("cache http://localhost:4545/run/002_hello.ts") .args("cache --allow-import http://localhost:4545/run/002_hello.ts")
.run() .run()
.skip_output_check(); .skip_output_check();

View file

@ -73,7 +73,7 @@ itest!(_005_more_imports {
}); });
itest!(_006_url_imports { itest!(_006_url_imports {
args: "run --quiet --reload run/006_url_imports.ts", args: "run --quiet --reload --allow-import run/006_url_imports.ts",
output: "run/006_url_imports.ts.out", output: "run/006_url_imports.ts.out",
http_server: true, http_server: true,
}); });
@ -105,24 +105,25 @@ itest!(_016_double_await {
}); });
itest!(_017_import_redirect { itest!(_017_import_redirect {
args: "run --quiet --reload run/017_import_redirect.ts", args: "run --quiet --allow-import --reload run/017_import_redirect.ts",
output: "run/017_import_redirect.ts.out", output: "run/017_import_redirect.ts.out",
}); });
itest!(_017_import_redirect_check { itest!(_017_import_redirect_check {
args: "run --quiet --reload --check run/017_import_redirect.ts", args:
"run --quiet --allow-import --reload --check run/017_import_redirect.ts",
output: "run/017_import_redirect.ts.out", output: "run/017_import_redirect.ts.out",
}); });
itest!(_017_import_redirect_vendor_dir { itest!(_017_import_redirect_vendor_dir {
args: args:
"run --quiet --reload --vendor --check $TESTDATA/run/017_import_redirect.ts", "run --quiet --allow-import --reload --vendor --check $TESTDATA/run/017_import_redirect.ts",
output: "run/017_import_redirect.ts.out", output: "run/017_import_redirect.ts.out",
temp_cwd: true, temp_cwd: true,
}); });
itest!(_017_import_redirect_info { itest!(_017_import_redirect_info {
args: "info --quiet --reload run/017_import_redirect.ts", args: "info --quiet --allow-import --reload run/017_import_redirect.ts",
output: "run/017_import_redirect_info.out", output: "run/017_import_redirect_info.out",
}); });
@ -132,7 +133,7 @@ itest!(_018_async_catch {
}); });
itest!(_019_media_types { itest!(_019_media_types {
args: "run --reload run/019_media_types.ts", args: "run --reload --allow-import run/019_media_types.ts",
output: "run/019_media_types.ts.out", output: "run/019_media_types.ts.out",
http_server: true, http_server: true,
}); });
@ -154,14 +155,14 @@ itest!(_025_reload_js_type_error {
}); });
itest!(_027_redirect_typescript { itest!(_027_redirect_typescript {
args: "run --quiet --reload run/027_redirect_typescript.ts", args: "run --quiet --reload --allow-import run/027_redirect_typescript.ts",
output: "run/027_redirect_typescript.ts.out", output: "run/027_redirect_typescript.ts.out",
http_server: true, http_server: true,
}); });
itest!(_027_redirect_typescript_vendor_dir { itest!(_027_redirect_typescript_vendor_dir {
args: args:
"run --quiet --reload --vendor $TESTDATA/run/027_redirect_typescript.ts", "run --quiet --reload --vendor --allow-import $TESTDATA/run/027_redirect_typescript.ts",
output: "run/027_redirect_typescript.ts.out", output: "run/027_redirect_typescript.ts.out",
http_server: true, http_server: true,
temp_cwd: true, temp_cwd: true,
@ -175,14 +176,14 @@ itest!(_028_args {
itest!(_033_import_map_remote { itest!(_033_import_map_remote {
args: args:
"run --quiet --reload --import-map=http://127.0.0.1:4545/import_maps/import_map_remote.json import_maps/test_remote.ts", "run --quiet --reload --allow-import --import-map=http://127.0.0.1:4545/import_maps/import_map_remote.json import_maps/test_remote.ts",
output: "run/033_import_map_remote.out", output: "run/033_import_map_remote.out",
http_server: true, http_server: true,
}); });
itest!(_033_import_map_vendor_dir_remote { itest!(_033_import_map_vendor_dir_remote {
args: args:
"run --quiet --reload --import-map=http://127.0.0.1:4545/import_maps/import_map_remote.json --vendor $TESTDATA/import_maps/test_remote.ts", "run --quiet --reload --allow-import --import-map=http://127.0.0.1:4545/import_maps/import_map_remote.json --vendor $TESTDATA/import_maps/test_remote.ts",
output: "run/033_import_map_remote.out", output: "run/033_import_map_remote.out",
http_server: true, http_server: true,
temp_cwd: true, temp_cwd: true,
@ -190,7 +191,7 @@ itest!(_033_import_map_vendor_dir_remote {
itest!(_033_import_map_data_uri { itest!(_033_import_map_data_uri {
args: args:
"run --quiet --reload --import-map=data:application/json;charset=utf-8;base64,ewogICJpbXBvcnRzIjogewogICAgInRlc3Rfc2VydmVyLyI6ICJodHRwOi8vbG9jYWxob3N0OjQ1NDUvIgogIH0KfQ== run/import_maps/test_data.ts", "run --quiet --reload --allow-import --import-map=data:application/json;charset=utf-8;base64,ewogICJpbXBvcnRzIjogewogICAgInRlc3Rfc2VydmVyLyI6ICJodHRwOi8vbG9jYWxob3N0OjQ1NDUvIgogIH0KfQ== run/import_maps/test_data.ts",
output: "run/import_maps/test_data.ts.out", output: "run/import_maps/test_data.ts.out",
http_server: true, http_server: true,
}); });
@ -201,7 +202,7 @@ itest!(onload {
}); });
itest!(_035_cached_only_flag { itest!(_035_cached_only_flag {
args: "run --reload --check --cached-only http://127.0.0.1:4545/run/019_media_types.ts", args: "run --reload --check --allow-import --cached-only http://127.0.0.1:4545/run/019_media_types.ts",
output: "run/035_cached_only_flag.out", output: "run/035_cached_only_flag.out",
exit_code: 1, exit_code: 1,
http_server: true, http_server: true,
@ -237,14 +238,14 @@ itest!(_047_jsx {
}); });
itest!(_048_media_types_jsx { itest!(_048_media_types_jsx {
args: "run --reload run/048_media_types_jsx.ts", args: "run --reload --allow-import run/048_media_types_jsx.ts",
output: "run/048_media_types_jsx.ts.out", output: "run/048_media_types_jsx.ts.out",
http_server: true, http_server: true,
}); });
itest!(_052_no_remote_flag { itest!(_052_no_remote_flag {
args: args:
"run --reload --check --no-remote http://127.0.0.1:4545/run/019_media_types.ts", "run --reload --check --allow-import --no-remote http://127.0.0.1:4545/run/019_media_types.ts",
output: "run/052_no_remote_flag.out", output: "run/052_no_remote_flag.out",
exit_code: 1, exit_code: 1,
http_server: true, http_server: true,
@ -467,7 +468,7 @@ itest!(dynamic_import_already_rejected {
}); });
itest!(dynamic_import_concurrent_non_statically_analyzable { itest!(dynamic_import_concurrent_non_statically_analyzable {
args: "run --allow-read --allow-net --quiet run/dynamic_import_concurrent_non_statically_analyzable/main.ts", args: "run --allow-import --allow-read --allow-net --quiet run/dynamic_import_concurrent_non_statically_analyzable/main.ts",
output: "run/dynamic_import_concurrent_non_statically_analyzable/main.out", output: "run/dynamic_import_concurrent_non_statically_analyzable/main.out",
http_server: true, http_server: true,
}); });
@ -802,7 +803,7 @@ itest!(private_field_presence_no_check {
itest!(lock_write_fetch { itest!(lock_write_fetch {
args: args:
"run --quiet --allow-read --allow-write --allow-env --allow-run run/lock_write_fetch/main.ts", "run --quiet --allow-import --allow-read --allow-write --allow-env --allow-run run/lock_write_fetch/main.ts",
output: "run/lock_write_fetch/main.out", output: "run/lock_write_fetch/main.out",
http_server: true, http_server: true,
exit_code: 0, exit_code: 0,
@ -810,26 +811,27 @@ itest!(lock_write_fetch {
itest!(lock_check_ok { itest!(lock_check_ok {
args: args:
"run --quiet --lock=run/lock_check_ok.json http://127.0.0.1:4545/run/003_relative_import.ts", "run --quiet --allow-import --lock=run/lock_check_ok.json http://127.0.0.1:4545/run/003_relative_import.ts",
output: "run/003_relative_import.ts.out", output: "run/003_relative_import.ts.out",
http_server: true, http_server: true,
}); });
itest!(lock_check_ok2 { itest!(lock_check_ok2 {
args: "run --lock=run/lock_check_ok2.json run/019_media_types.ts", args:
"run --allow-import --lock=run/lock_check_ok2.json run/019_media_types.ts",
output: "run/019_media_types.ts.out", output: "run/019_media_types.ts.out",
http_server: true, http_server: true,
}); });
itest!(lock_v2_check_ok { itest!(lock_v2_check_ok {
args: args:
"run --quiet --lock=run/lock_v2_check_ok.json http://127.0.0.1:4545/run/003_relative_import.ts", "run --allow-import --quiet --lock=run/lock_v2_check_ok.json http://127.0.0.1:4545/run/003_relative_import.ts",
output: "run/003_relative_import.ts.out", output: "run/003_relative_import.ts.out",
http_server: true, http_server: true,
}); });
itest!(lock_v2_check_ok2 { itest!(lock_v2_check_ok2 {
args: "run --lock=run/lock_v2_check_ok2.json run/019_media_types.ts", args: "run --allow-import --lock=run/lock_v2_check_ok2.json run/019_media_types.ts",
output: "run/019_media_types.ts.out", output: "run/019_media_types.ts.out",
http_server: true, http_server: true,
}); });
@ -849,7 +851,7 @@ fn lock_redirects() {
); );
context context
.new_command() .new_command()
.args("run main.ts") .args("run --allow-import main.ts")
.run() .run()
.skip_output_check(); .skip_output_check();
let initial_lockfile_text = r#"{ let initial_lockfile_text = r#"{
@ -865,7 +867,7 @@ fn lock_redirects() {
assert_eq!(temp_dir.read_to_string("deno.lock"), initial_lockfile_text); assert_eq!(temp_dir.read_to_string("deno.lock"), initial_lockfile_text);
context context
.new_command() .new_command()
.args("run main.ts") .args("run --allow-import main.ts")
.run() .run()
.assert_matches_text("Hello World\n"); .assert_matches_text("Hello World\n");
assert_eq!(temp_dir.read_to_string("deno.lock"), initial_lockfile_text); assert_eq!(temp_dir.read_to_string("deno.lock"), initial_lockfile_text);
@ -892,7 +894,7 @@ fn lock_redirects() {
// it should use the echo script instead // it should use the echo script instead
context context
.new_command() .new_command()
.args("run main.ts Hi there") .args("run --allow-import main.ts Hi there")
.run() .run()
.assert_matches_text(concat!( .assert_matches_text(concat!(
"Download http://localhost:4545/echo.ts\n", "Download http://localhost:4545/echo.ts\n",
@ -1260,7 +1262,7 @@ itest!(config_types {
itest!(config_types_remote { itest!(config_types_remote {
http_server: true, http_server: true,
args: "run --reload --quiet --check=all --config run/config_types/remote.tsconfig.json run/config_types/main.ts", args: "run --allow-import --reload --quiet --check=all --config run/config_types/remote.tsconfig.json run/config_types/main.ts",
output: "run/config_types/main.out", output: "run/config_types/main.out",
}); });
@ -1365,9 +1367,10 @@ itest!(error_015_dynamic_import_permissions {
http_server: true, http_server: true,
}); });
// We have an allow-net flag but not allow-read, it should still result in error. // We have an allow-import flag but not allow-read, it should still result in error.
itest!(error_016_dynamic_import_permissions2 { itest!(error_016_dynamic_import_permissions2 {
args: "run --reload --allow-net run/error_016_dynamic_import_permissions2.js", args:
"run --reload --allow-import run/error_016_dynamic_import_permissions2.js",
output: "run/error_016_dynamic_import_permissions2.out", output: "run/error_016_dynamic_import_permissions2.out",
exit_code: 1, exit_code: 1,
http_server: true, http_server: true,
@ -1428,7 +1431,7 @@ itest!(error_025_tab_indent {
}); });
itest!(error_026_remote_import_error { itest!(error_026_remote_import_error {
args: "run run/error_026_remote_import_error.ts", args: "run --allow-import run/error_026_remote_import_error.ts",
output: "run/error_026_remote_import_error.ts.out", output: "run/error_026_remote_import_error.ts.out",
exit_code: 1, exit_code: 1,
http_server: true, http_server: true,
@ -1471,18 +1474,18 @@ itest!(error_type_definitions {
}); });
itest!(error_local_static_import_from_remote_ts { itest!(error_local_static_import_from_remote_ts {
args: "run --reload http://localhost:4545/run/error_local_static_import_from_remote.ts", args: "run --allow-import --reload http://localhost:4545/run/error_local_static_import_from_remote.ts",
exit_code: 1, exit_code: 1,
http_server: true, http_server: true,
output: "run/error_local_static_import_from_remote.ts.out", output: "run/error_local_static_import_from_remote.ts.out",
}); });
itest!(error_local_static_import_from_remote_js { itest!(error_local_static_import_from_remote_js {
args: "run --reload http://localhost:4545/run/error_local_static_import_from_remote.js", args: "run --allow-import --reload http://localhost:4545/run/error_local_static_import_from_remote.js",
exit_code: 1, exit_code: 1,
http_server: true, http_server: true,
output: "run/error_local_static_import_from_remote.js.out", output: "run/error_local_static_import_from_remote.js.out",
}); });
itest!(exit_error42 { itest!(exit_error42 {
exit_code: 42, exit_code: 42,
@ -1531,7 +1534,7 @@ itest!(finalization_registry {
}); });
itest!(https_import { itest!(https_import {
args: "run --quiet --reload --cert tls/RootCA.pem run/https_import.ts", args: "run --allow-import --quiet --reload --cert tls/RootCA.pem run/https_import.ts",
output: "run/https_import.ts.out", output: "run/https_import.ts.out",
http_server: true, http_server: true,
}); });
@ -1542,7 +1545,7 @@ itest!(if_main {
}); });
itest!(import_meta { itest!(import_meta {
args: "run --quiet --reload --import-map=run/import_meta/importmap.json run/import_meta/main.ts", args: "run --allow-import --quiet --reload --import-map=run/import_meta/importmap.json run/import_meta/main.ts",
output: "run/import_meta/main.out", output: "run/import_meta/main.out",
http_server: true, http_server: true,
}); });
@ -1553,7 +1556,7 @@ itest!(main_module {
}); });
itest!(no_check { itest!(no_check {
args: "run --quiet --reload --no-check run/006_url_imports.ts", args: "run --allow-import --quiet --reload --no-check run/006_url_imports.ts",
output: "run/006_url_imports.ts.out", output: "run/006_url_imports.ts.out",
http_server: true, http_server: true,
}); });
@ -1569,14 +1572,15 @@ itest!(decorators_tc39_proposal {
}); });
itest!(check_remote { itest!(check_remote {
args: "run --quiet --reload --check=all run/no_check_remote.ts", args:
"run --quiet --allow-import --reload --check=all run/no_check_remote.ts",
output: "run/no_check_remote.ts.disabled.out", output: "run/no_check_remote.ts.disabled.out",
exit_code: 1, exit_code: 1,
http_server: true, http_server: true,
}); });
itest!(no_check_remote { itest!(no_check_remote {
args: "run --quiet --reload --no-check=remote run/no_check_remote.ts", args: "run --allow-import --quiet --reload --no-check=remote run/no_check_remote.ts",
output: "run/no_check_remote.ts.enabled.out", output: "run/no_check_remote.ts.enabled.out",
http_server: true, http_server: true,
}); });
@ -1603,13 +1607,15 @@ itest!(type_definitions_for_export {
}); });
itest!(type_directives_01 { itest!(type_directives_01 {
args: "run --reload --check=all -L debug run/type_directives_01.ts", args:
"run --allow-import --reload --check=all -L debug run/type_directives_01.ts",
output: "run/type_directives_01.ts.out", output: "run/type_directives_01.ts.out",
http_server: true, http_server: true,
}); });
itest!(type_directives_02 { itest!(type_directives_02 {
args: "run --reload --check=all -L debug run/type_directives_02.ts", args:
"run --allow-import --reload --check=all -L debug run/type_directives_02.ts",
output: "run/type_directives_02.ts.out", output: "run/type_directives_02.ts.out",
}); });
@ -1629,13 +1635,13 @@ fn type_directives_js_main() {
} }
itest!(type_directives_redirect { itest!(type_directives_redirect {
args: "run --reload --check run/type_directives_redirect.ts", args: "run --allow-import --reload --check run/type_directives_redirect.ts",
output: "run/type_directives_redirect.ts.out", output: "run/type_directives_redirect.ts.out",
http_server: true, http_server: true,
}); });
itest!(type_headers_deno_types { itest!(type_headers_deno_types {
args: "run --reload --check run/type_headers_deno_types.ts", args: "run --allow-import --reload --check run/type_headers_deno_types.ts",
output: "run/type_headers_deno_types.ts.out", output: "run/type_headers_deno_types.ts.out",
http_server: true, http_server: true,
}); });
@ -1839,20 +1845,20 @@ itest!(unstable_kv_enabled {
}); });
itest!(import_compression { itest!(import_compression {
args: "run --quiet --reload --allow-net run/import_compression/main.ts", args: "run --allow-import --quiet --reload --allow-net run/import_compression/main.ts",
output: "run/import_compression/main.out", output: "run/import_compression/main.out",
http_server: true, http_server: true,
}); });
itest!(disallow_http_from_https_js { itest!(disallow_http_from_https_js {
args: "run --quiet --reload --cert tls/RootCA.pem https://localhost:5545/run/disallow_http_from_https.js", args: "run --allow-import --quiet --reload --cert tls/RootCA.pem https://localhost:5545/run/disallow_http_from_https.js",
output: "run/disallow_http_from_https_js.out", output: "run/disallow_http_from_https_js.out",
http_server: true, http_server: true,
exit_code: 1, exit_code: 1,
}); });
itest!(disallow_http_from_https_ts { itest!(disallow_http_from_https_ts {
args: "run --quiet --reload --cert tls/RootCA.pem https://localhost:5545/run/disallow_http_from_https.ts", args: "run --allow-import --quiet --reload --cert tls/RootCA.pem https://localhost:5545/run/disallow_http_from_https.ts",
output: "run/disallow_http_from_https_ts.out", output: "run/disallow_http_from_https_ts.out",
http_server: true, http_server: true,
exit_code: 1, exit_code: 1,
@ -1904,7 +1910,7 @@ itest!(es_private_fields {
}); });
itest!(ts_import_from_js { itest!(ts_import_from_js {
args: "run --quiet --reload run/ts_import_from_js/main.js", args: "run --allow-import --quiet --reload run/ts_import_from_js/main.js",
output: "run/ts_import_from_js/main.out", output: "run/ts_import_from_js/main.out",
http_server: true, http_server: true,
}); });
@ -1915,100 +1921,101 @@ itest!(jsx_import_from_ts {
}); });
itest!(jsx_import_source_pragma { itest!(jsx_import_source_pragma {
args: "run --reload run/jsx_import_source_pragma.tsx", args: "run --reload --allow-import run/jsx_import_source_pragma.tsx",
output: "run/jsx_import_source.out", output: "run/jsx_import_source.out",
http_server: true, http_server: true,
}); });
itest!(jsx_import_source_pragma_with_config { itest!(jsx_import_source_pragma_with_config {
args: args:
"run --reload --config jsx/deno-jsx.jsonc --no-lock run/jsx_import_source_pragma.tsx", "run --reload --allow-import --config jsx/deno-jsx.jsonc --no-lock run/jsx_import_source_pragma.tsx",
output: "run/jsx_import_source.out", output: "run/jsx_import_source.out",
http_server: true, http_server: true,
}); });
itest!(jsx_import_source_pragma_with_dev_config { itest!(jsx_import_source_pragma_with_dev_config {
args: args:
"run --reload --config jsx/deno-jsxdev.jsonc --no-lock run/jsx_import_source_pragma.tsx", "run --reload --allow-import --config jsx/deno-jsxdev.jsonc --no-lock run/jsx_import_source_pragma.tsx",
output: "run/jsx_import_source_dev.out", output: "run/jsx_import_source_dev.out",
http_server: true, http_server: true,
}); });
itest!(jsx_import_source_no_pragma { itest!(jsx_import_source_no_pragma {
args: args:
"run --reload --config jsx/deno-jsx.jsonc --no-lock run/jsx_import_source_no_pragma.tsx", "run --allow-import --reload --config jsx/deno-jsx.jsonc --no-lock run/jsx_import_source_no_pragma.tsx",
output: "run/jsx_import_source.out", output: "run/jsx_import_source.out",
http_server: true, http_server: true,
}); });
itest!(jsx_import_source_no_pragma_dev { itest!(jsx_import_source_no_pragma_dev {
args: "run --reload --config jsx/deno-jsxdev.jsonc --no-lock run/jsx_import_source_no_pragma.tsx", args: "run --allow-import --reload --config jsx/deno-jsxdev.jsonc --no-lock run/jsx_import_source_no_pragma.tsx",
output: "run/jsx_import_source_dev.out", output: "run/jsx_import_source_dev.out",
http_server: true, http_server: true,
}); });
itest!(jsx_import_source_pragma_import_map { itest!(jsx_import_source_pragma_import_map {
args: "run --reload --import-map jsx/import-map.json run/jsx_import_source_pragma_import_map.tsx", args: "run --allow-import --reload --import-map jsx/import-map.json run/jsx_import_source_pragma_import_map.tsx",
output: "run/jsx_import_source_import_map.out", output: "run/jsx_import_source_import_map.out",
http_server: true, http_server: true,
}); });
itest!(jsx_import_source_pragma_import_map_dev { itest!(jsx_import_source_pragma_import_map_dev {
args: "run --reload --import-map jsx/import-map.json --config jsx/deno-jsxdev-import-map.jsonc run/jsx_import_source_pragma_import_map.tsx", args: "run --allow-import --reload --import-map jsx/import-map.json --config jsx/deno-jsxdev-import-map.jsonc run/jsx_import_source_pragma_import_map.tsx",
output: "run/jsx_import_source_import_map_dev.out", output: "run/jsx_import_source_import_map_dev.out",
http_server: true, http_server: true,
}); });
itest!(jsx_import_source_precompile_import_map { itest!(jsx_import_source_precompile_import_map {
args: "run --reload --check --import-map jsx/import-map.json --no-lock --config jsx/deno-jsx-precompile.jsonc run/jsx_precompile/no_pragma.tsx", args: "run --allow-import --reload --check --import-map jsx/import-map.json --no-lock --config jsx/deno-jsx-precompile.jsonc run/jsx_precompile/no_pragma.tsx",
output: "run/jsx_precompile/no_pragma.out", output: "run/jsx_precompile/no_pragma.out",
http_server: true, http_server: true,
}); });
itest!(jsx_import_source_precompile_import_map_skip_element { itest!(jsx_import_source_precompile_import_map_skip_element {
args: "run --reload --check --import-map jsx/import-map.json --no-lock --config jsx/deno-jsx-precompile-skip.jsonc run/jsx_precompile/skip.tsx", args: "run --allow-import --reload --check --import-map jsx/import-map.json --no-lock --config jsx/deno-jsx-precompile-skip.jsonc run/jsx_precompile/skip.tsx",
output: "run/jsx_precompile/skip.out", output: "run/jsx_precompile/skip.out",
http_server: true, http_server: true,
}); });
itest!(jsx_import_source_import_map { itest!(jsx_import_source_import_map {
args: "run --reload --import-map jsx/import-map.json --no-lock --config jsx/deno-jsx-import-map.jsonc run/jsx_import_source_no_pragma.tsx", args: "run --allow-import --reload --import-map jsx/import-map.json --no-lock --config jsx/deno-jsx-import-map.jsonc run/jsx_import_source_no_pragma.tsx",
output: "run/jsx_import_source_import_map.out", output: "run/jsx_import_source_import_map.out",
http_server: true, http_server: true,
}); });
itest!(jsx_import_source_import_map_dev { itest!(jsx_import_source_import_map_dev {
args: "run --reload --import-map jsx/import-map.json --no-lock --config jsx/deno-jsxdev-import-map.jsonc run/jsx_import_source_no_pragma.tsx", args: "run --allow-import --reload --import-map jsx/import-map.json --no-lock --config jsx/deno-jsxdev-import-map.jsonc run/jsx_import_source_no_pragma.tsx",
output: "run/jsx_import_source_import_map_dev.out", output: "run/jsx_import_source_import_map_dev.out",
http_server: true, http_server: true,
}); });
itest!(jsx_import_source_import_map_scoped { itest!(jsx_import_source_import_map_scoped {
args: "run --reload --import-map jsx/import-map-scoped.json --no-lock --config jsx/deno-jsx-import-map.jsonc subdir/jsx_import_source_no_pragma.tsx", args: "run --allow-import --reload --import-map jsx/import-map-scoped.json --no-lock --config jsx/deno-jsx-import-map.jsonc subdir/jsx_import_source_no_pragma.tsx",
output: "run/jsx_import_source_import_map.out", output: "run/jsx_import_source_import_map.out",
http_server: true, http_server: true,
}); });
itest!(jsx_import_source_import_map_scoped_dev { itest!(jsx_import_source_import_map_scoped_dev {
args: "run --reload --import-map jsx/import-map-scoped.json --no-lock --config jsx/deno-jsxdev-import-map.jsonc subdir/jsx_import_source_no_pragma.tsx", args: "run --allow-import --reload --import-map jsx/import-map-scoped.json --no-lock --config jsx/deno-jsxdev-import-map.jsonc subdir/jsx_import_source_no_pragma.tsx",
output: "run/jsx_import_source_import_map_dev.out", output: "run/jsx_import_source_import_map_dev.out",
http_server: true, http_server: true,
}); });
itest!(jsx_import_source_pragma_no_check { itest!(jsx_import_source_pragma_no_check {
args: "run --reload --no-check run/jsx_import_source_pragma.tsx", args:
"run --allow-import --reload --no-check run/jsx_import_source_pragma.tsx",
output: "run/jsx_import_source.out", output: "run/jsx_import_source.out",
http_server: true, http_server: true,
}); });
itest!(jsx_import_source_pragma_with_config_no_check { itest!(jsx_import_source_pragma_with_config_no_check {
args: "run --reload --config jsx/deno-jsx.jsonc --no-lock --no-check run/jsx_import_source_pragma.tsx", args: "run --allow-import --reload --config jsx/deno-jsx.jsonc --no-lock --no-check run/jsx_import_source_pragma.tsx",
output: "run/jsx_import_source.out", output: "run/jsx_import_source.out",
http_server: true, http_server: true,
}); });
itest!(jsx_import_source_pragma_with_config_vendor_dir { itest!(jsx_import_source_pragma_with_config_vendor_dir {
args: "run --reload --config jsx/deno-jsx.jsonc --no-lock --vendor $TESTDATA/run/jsx_import_source_pragma.tsx", args: "run --allow-import --reload --config jsx/deno-jsx.jsonc --no-lock --vendor $TESTDATA/run/jsx_import_source_pragma.tsx",
output: "run/jsx_import_source.out", output: "run/jsx_import_source.out",
http_server: true, http_server: true,
temp_cwd: true, temp_cwd: true,
@ -2017,19 +2024,19 @@ itest!(jsx_import_source_pragma_with_config_vendor_dir {
itest!(jsx_import_source_no_pragma_no_check { itest!(jsx_import_source_no_pragma_no_check {
args: args:
"run --reload --config jsx/deno-jsx.jsonc --no-lock --no-check run/jsx_import_source_no_pragma.tsx", "run --allow-import --reload --config jsx/deno-jsx.jsonc --no-lock --no-check run/jsx_import_source_no_pragma.tsx",
output: "run/jsx_import_source.out", output: "run/jsx_import_source.out",
http_server: true, http_server: true,
}); });
itest!(jsx_import_source_pragma_import_map_no_check { itest!(jsx_import_source_pragma_import_map_no_check {
args: "run --reload --import-map jsx/import-map.json --no-check run/jsx_import_source_pragma_import_map.tsx", args: "run --allow-import --reload --import-map jsx/import-map.json --no-check run/jsx_import_source_pragma_import_map.tsx",
output: "run/jsx_import_source_import_map.out", output: "run/jsx_import_source_import_map.out",
http_server: true, http_server: true,
}); });
itest!(jsx_import_source_import_map_no_check { itest!(jsx_import_source_import_map_no_check {
args: "run --reload --import-map jsx/import-map.json --no-lock --config jsx/deno-jsx-import-map.jsonc --no-check run/jsx_import_source_no_pragma.tsx", args: "run --allow-import --reload --import-map jsx/import-map.json --no-lock --config jsx/deno-jsx-import-map.jsonc --no-check run/jsx_import_source_no_pragma.tsx",
output: "run/jsx_import_source_import_map.out", output: "run/jsx_import_source_import_map.out",
http_server: true, http_server: true,
}); });
@ -2093,7 +2100,7 @@ itest!(import_data_url_import_relative {
}); });
itest!(import_data_url_imports { itest!(import_data_url_imports {
args: "run --quiet --reload run/import_data_url_imports.ts", args: "run --allow-import --quiet --reload run/import_data_url_imports.ts",
output: "run/import_data_url_imports.ts.out", output: "run/import_data_url_imports.ts.out",
http_server: true, http_server: true,
}); });
@ -2127,7 +2134,7 @@ itest!(import_blob_url_import_relative {
itest!(import_blob_url_imports { itest!(import_blob_url_imports {
args: args:
"run --quiet --reload --allow-net=localhost:4545 run/import_blob_url_imports.ts", "run --allow-import --quiet --reload --allow-net=localhost:4545 run/import_blob_url_imports.ts",
output: "run/import_blob_url_imports.ts.out", output: "run/import_blob_url_imports.ts.out",
http_server: true, http_server: true,
}); });
@ -2143,13 +2150,13 @@ itest!(import_blob_url {
}); });
itest!(import_file_with_colon { itest!(import_file_with_colon {
args: "run --quiet --reload run/import_file_with_colon.ts", args: "run --allow-import --quiet --reload run/import_file_with_colon.ts",
output: "run/import_file_with_colon.ts.out", output: "run/import_file_with_colon.ts.out",
http_server: true, http_server: true,
}); });
itest!(import_extensionless { itest!(import_extensionless {
args: "run --quiet --reload run/import_extensionless.ts", args: "run --allow-import --quiet --reload run/import_extensionless.ts",
output: "run/import_extensionless.ts.out", output: "run/import_extensionless.ts.out",
http_server: true, http_server: true,
}); });
@ -2195,7 +2202,7 @@ itest!(inline_js_source_map_2_with_inline_contents {
// was not commented out. The source line is remapped using source contents that // was not commented out. The source line is remapped using source contents that
// from the module graph. // from the module graph.
itest!(inline_js_source_map_with_contents_from_graph { itest!(inline_js_source_map_with_contents_from_graph {
args: "run --quiet run/inline_js_source_map_with_contents_from_graph.js", args: "run --allow-import --quiet run/inline_js_source_map_with_contents_from_graph.js",
output: "run/inline_js_source_map_with_contents_from_graph.js.out", output: "run/inline_js_source_map_with_contents_from_graph.js.out",
exit_code: 1, exit_code: 1,
http_server: true, http_server: true,
@ -3031,14 +3038,14 @@ mod permissions {
}); });
itest!(dynamic_import_permissions_remote_remote { itest!(dynamic_import_permissions_remote_remote {
args: "run --quiet --reload --allow-net=localhost:4545 dynamic_import/permissions_remote_remote.ts", args: "run --quiet --reload --allow-import=localhost:4545 dynamic_import/permissions_remote_remote.ts",
output: "dynamic_import/permissions_remote_remote.ts.out", output: "dynamic_import/permissions_remote_remote.ts.out",
http_server: true, http_server: true,
exit_code: 1, exit_code: 1,
}); });
itest!(dynamic_import_permissions_data_remote { itest!(dynamic_import_permissions_data_remote {
args: "run --quiet --reload --allow-net=localhost:4545 dynamic_import/permissions_data_remote.ts", args: "run --quiet --reload --allow-import=localhost:4545 dynamic_import/permissions_data_remote.ts",
output: "dynamic_import/permissions_data_remote.ts.out", output: "dynamic_import/permissions_data_remote.ts.out",
http_server: true, http_server: true,
exit_code: 1, exit_code: 1,
@ -3329,7 +3336,7 @@ itest!(no_config_auto_discovery_for_local_script {
}); });
itest!(config_not_auto_discovered_for_remote_script { itest!(config_not_auto_discovered_for_remote_script {
args: "run --quiet http://127.0.0.1:4545/run/with_config/server_side_work.ts", args: "run --allow-import --quiet http://127.0.0.1:4545/run/with_config/server_side_work.ts",
output_str: Some("ok\n"), output_str: Some("ok\n"),
http_server: true, http_server: true,
}); });
@ -3468,6 +3475,7 @@ fn check_local_then_remote() {
let output = util::deno_cmd_with_deno_dir(&deno_dir) let output = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path()) .current_dir(util::testdata_path())
.arg("run") .arg("run")
.arg("--allow-import")
.arg("--check") .arg("--check")
.arg("run/remote_type_error/main.ts") .arg("run/remote_type_error/main.ts")
.spawn() .spawn()
@ -3478,6 +3486,7 @@ fn check_local_then_remote() {
let output = util::deno_cmd_with_deno_dir(&deno_dir) let output = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path()) .current_dir(util::testdata_path())
.arg("run") .arg("run")
.arg("--allow-import")
.arg("--check=all") .arg("--check=all")
.arg("run/remote_type_error/main.ts") .arg("run/remote_type_error/main.ts")
.env("NO_COLOR", "1") .env("NO_COLOR", "1")
@ -3655,6 +3664,7 @@ fn cache_test() {
.env("DENO_DIR", deno_dir.path()) .env("DENO_DIR", deno_dir.path())
.current_dir(util::testdata_path()) .current_dir(util::testdata_path())
.arg("cache") .arg("cache")
.arg("--allow-import=localhost:4545")
.arg("--check=all") .arg("--check=all")
.arg("-L") .arg("-L")
.arg("debug") .arg("debug")
@ -3670,6 +3680,7 @@ fn cache_test() {
.env("NO_COLOR", "1") .env("NO_COLOR", "1")
.current_dir(util::testdata_path()) .current_dir(util::testdata_path())
.arg("run") .arg("run")
.arg("--allow-import=localhost:4545")
.arg(module_url.to_string()) .arg(module_url.to_string())
.output() .output()
.expect("Failed to spawn script"); .expect("Failed to spawn script");
@ -3819,6 +3830,7 @@ fn basic_auth_tokens() {
let output = util::deno_cmd() let output = util::deno_cmd()
.current_dir(util::root_path()) .current_dir(util::root_path())
.arg("run") .arg("run")
.arg("--allow-import")
.arg("http://127.0.0.1:4554/run/001_hello.js") .arg("http://127.0.0.1:4554/run/001_hello.js")
.piped_output() .piped_output()
.spawn() .spawn()
@ -3840,6 +3852,7 @@ fn basic_auth_tokens() {
let output = util::deno_cmd() let output = util::deno_cmd()
.current_dir(util::root_path()) .current_dir(util::root_path())
.arg("run") .arg("run")
.arg("--allow-import")
.arg("http://127.0.0.1:4554/run/001_hello.js") .arg("http://127.0.0.1:4554/run/001_hello.js")
.env("DENO_AUTH_TOKENS", "testuser123:testpassabc@127.0.0.1:4554") .env("DENO_AUTH_TOKENS", "testuser123:testpassabc@127.0.0.1:4554")
.piped_output() .piped_output()
@ -4404,7 +4417,7 @@ async fn websocket_server_idletimeout() {
} }
itest!(no_lock_flag { itest!(no_lock_flag {
args: "run --no-lock run/no_lock_flag/main.ts", args: "run --allow-import --no-lock run/no_lock_flag/main.ts",
output: "run/no_lock_flag/main.out", output: "run/no_lock_flag/main.out",
http_server: true, http_server: true,
exit_code: 0, exit_code: 0,
@ -4563,7 +4576,9 @@ pub fn vendor_dir_config_file() {
console.log(returnsHi());"#, console.log(returnsHi());"#,
); );
let deno_run_cmd = test_context.new_command().args("run --quiet main.ts"); let deno_run_cmd = test_context
.new_command()
.args("run --allow-import --quiet main.ts");
deno_run_cmd.run().assert_matches_text("Hi\n"); deno_run_cmd.run().assert_matches_text("Hi\n");
assert!(vendor_dir.exists()); assert!(vendor_dir.exists());
@ -4574,13 +4589,15 @@ console.log(returnsHi());"#,
assert!(!vendor_dir.exists()); assert!(!vendor_dir.exists());
test_context test_context
.new_command() .new_command()
.args("cache --quiet --vendor main.ts") .args("cache --allow-import --quiet --vendor main.ts")
.run(); .run();
assert!(vendor_dir.exists()); assert!(vendor_dir.exists());
rm_vendor_dir(); rm_vendor_dir();
temp_dir.write("deno.json", r#"{ "vendor": true }"#); temp_dir.write("deno.json", r#"{ "vendor": true }"#);
let cache_command = test_context.new_command().args("cache --quiet main.ts"); let cache_command = test_context
.new_command()
.args("cache --allow-import --quiet main.ts");
cache_command.run(); cache_command.run();
assert!(vendor_dir.exists()); assert!(vendor_dir.exists());
@ -4608,7 +4625,7 @@ console.log(returnsHi());"#,
test_context test_context
.new_command() .new_command()
// http_localhost_4545/subdir/#capitals_c75d7/main.js // http_localhost_4545/subdir/#capitals_c75d7/main.js
.args("cache http://localhost:4545/subdir/CAPITALS/main.js") .args("cache --allow-import http://localhost:4545/subdir/CAPITALS/main.js")
.run() .run()
.skip_output_check(); .skip_output_check();
assert_eq!( assert_eq!(
@ -4625,7 +4642,7 @@ console.log(returnsHi());"#,
test_context test_context
.new_command() .new_command()
// todo(dsherret): seems wrong that we don't auto-discover the config file to get the vendor directory for this // todo(dsherret): seems wrong that we don't auto-discover the config file to get the vendor directory for this
.args("run --vendor http://localhost:4545/subdir/CAPITALS/hello_there.ts") .args("run --allow-import --vendor http://localhost:4545/subdir/CAPITALS/hello_there.ts")
.run() .run()
.assert_matches_text("hello there\n"); .assert_matches_text("hello there\n");
@ -5120,21 +5137,23 @@ fn emit_failed_readonly_file_system() {
fn handle_invalid_path_error() { fn handle_invalid_path_error() {
let deno_cmd = util::deno_cmd_with_deno_dir(&util::new_deno_dir()); let deno_cmd = util::deno_cmd_with_deno_dir(&util::new_deno_dir());
let output = deno_cmd.arg("run").arg("file://asdf").output().unwrap(); let output = deno_cmd.arg("run").arg("file://asdf").output().unwrap();
assert!( assert_contains!(
String::from_utf8_lossy(&output.stderr).contains("Invalid file path.") String::from_utf8_lossy(&output.stderr),
"Invalid file path."
); );
let deno_cmd = util::deno_cmd_with_deno_dir(&util::new_deno_dir()); let deno_cmd = util::deno_cmd_with_deno_dir(&util::new_deno_dir());
let output = deno_cmd.arg("run").arg("/a/b").output().unwrap(); let output = deno_cmd.arg("run").arg("/a/b").output().unwrap();
assert!(String::from_utf8_lossy(&output.stderr).contains("Module not found")); assert_contains!(String::from_utf8_lossy(&output.stderr), "Module not found");
let deno_cmd = util::deno_cmd_with_deno_dir(&util::new_deno_dir()); let deno_cmd = util::deno_cmd_with_deno_dir(&util::new_deno_dir());
let output = deno_cmd.arg("run").arg("//a/b").output().unwrap(); let output = deno_cmd.arg("run").arg("//a/b").output().unwrap();
assert!( assert_contains!(
String::from_utf8_lossy(&output.stderr).contains("Invalid file path.") String::from_utf8_lossy(&output.stderr),
"Invalid file path."
); );
let deno_cmd = util::deno_cmd_with_deno_dir(&util::new_deno_dir()); let deno_cmd = util::deno_cmd_with_deno_dir(&util::new_deno_dir());
let output = deno_cmd.arg("run").arg("///a/b").output().unwrap(); let output = deno_cmd.arg("run").arg("///a/b").output().unwrap();
assert!(String::from_utf8_lossy(&output.stderr).contains("Module not found")); assert_contains!(String::from_utf8_lossy(&output.stderr), "Module not found");
} }

View file

@ -1399,6 +1399,7 @@ async fn run_watch_reload_once() {
let mut child = util::deno_cmd() let mut child = util::deno_cmd()
.current_dir(t.path()) .current_dir(t.path())
.arg("run") .arg("run")
.arg("--allow-import")
.arg("--watch") .arg("--watch")
.arg("--reload") .arg("--reload")
.arg(&file_to_watch) .arg(&file_to_watch)

View file

@ -1,4 +1,4 @@
{ {
"args": "bench --quiet check_local_by_default.ts", "args": "bench --allow-import --quiet check_local_by_default.ts",
"output": "check_local_by_default.out" "output": "check_local_by_default.out"
} }

View file

@ -1,5 +1,5 @@
{ {
"args": "bench --quiet check_local_by_default2.ts", "args": "bench --allow-import --quiet check_local_by_default2.ts",
"output": "check_local_by_default2.out", "output": "check_local_by_default2.out",
"exitCode": 1 "exitCode": 1
} }

View file

@ -1,4 +1,4 @@
{ {
"args": "cache --quiet check_local_by_default.ts", "args": "cache --quiet --allow-import check_local_by_default.ts",
"output": "check_local_by_default.out" "output": "check_local_by_default.out"
} }

View file

@ -1,4 +1,4 @@
{ {
"args": "cache --quiet check_local_by_default2.ts", "args": "cache --quiet --allow-import check_local_by_default2.ts",
"output": "check_local_by_default2.out" "output": "check_local_by_default2.out"
} }

View file

@ -1,4 +1,4 @@
{ {
"args": "cache --reload --check=all test.ts other.ts", "args": "cache --reload --allow-import --check=all test.ts other.ts",
"output": "fetch_multiple.out" "output": "fetch_multiple.out"
} }

View file

@ -1,5 +1,5 @@
{ {
"args": "cache *.ts", "args": "cache --allow-import *.ts",
"output": "Download http://localhost:4545/echo.ts\n", "output": "Download http://localhost:4545/echo.ts\n",
"exitCode": 0 "exitCode": 0
} }

View file

@ -1,4 +1,4 @@
{ {
"args": "cache --reload --check=all http://localhost:4548/subdir/redirects/a.ts", "args": "cache --reload --allow-import --check=all http://localhost:4548/subdir/redirects/a.ts",
"output": "redirect_cache.out" "output": "redirect_cache.out"
} }

View file

@ -1,6 +1,6 @@
{ {
"steps": [{ "steps": [{
"args": "run --quiet --reload --allow-net --cert RootCA.pem cafile_ts_fetch.ts", "args": "run --quiet --reload --allow-net --allow-import --cert RootCA.pem cafile_ts_fetch.ts",
"flaky": true, "flaky": true,
"output": "cafile_ts_fetch.ts.out" "output": "cafile_ts_fetch.ts.out"
}, { }, {
@ -8,11 +8,11 @@
"flaky": true, "flaky": true,
"output": "cafile_ts_fetch.ts.out" "output": "cafile_ts_fetch.ts.out"
}, { }, {
"args": "info --quiet --cert RootCA.pem https://localhost:5545/cert/cafile_info.ts", "args": "info --quiet --allow-import --cert RootCA.pem https://localhost:5545/cert/cafile_info.ts",
"flaky": true, "flaky": true,
"output": "cafile_info.ts.out" "output": "cafile_info.ts.out"
}, { }, {
"args": "cache --quiet --cert RootCA.pem http://localhost:4545/cert/cafile_url_imports.ts", "args": "cache --quiet --allow-import --cert RootCA.pem http://localhost:4545/cert/cafile_url_imports.ts",
"flaky": true, "flaky": true,
"output": "" "output": ""
}] }]

View file

@ -1,5 +1,5 @@
{ {
"args": "run --quiet --reload --cert RootCA.pem cafile_url_imports.ts", "args": "run --quiet --reload --allow-import --cert RootCA.pem cafile_url_imports.ts",
"flaky": true, "flaky": true,
"output": "cafile_url_imports.ts.out" "output": "cafile_url_imports.ts.out"
} }

View file

@ -1,5 +1,5 @@
{ {
"args": "run --quiet --reload --unsafely-ignore-certificate-errors=localhost cafile_url_imports.ts", "args": "run --quiet --allow-import --reload --unsafely-ignore-certificate-errors=localhost cafile_url_imports.ts",
"flaky": true, "flaky": true,
"output": "cafile_url_imports_unsafe_ssl.ts.out" "output": "cafile_url_imports_unsafe_ssl.ts.out"
} }

View file

@ -1,5 +1,5 @@
{ {
"args": "run --quiet --reload --allow-net --unsafely-ignore-certificate-errors=deno.land cafile_url_imports.ts", "args": "run --quiet --reload --allow-import --allow-net --unsafely-ignore-certificate-errors=deno.land cafile_url_imports.ts",
"output": "localhost_unsafe_ssl.ts.out", "output": "localhost_unsafe_ssl.ts.out",
"exitCode": 1 "exitCode": 1
} }

View file

@ -1,4 +1,4 @@
{ {
"args": "check --all main.tsx", "args": "check --allow-import --all main.tsx",
"output": "main.out" "output": "main.out"
} }

View file

@ -1,4 +1,4 @@
{ {
"args": "check --all main.tsx", "args": "check --allow-import --all main.tsx",
"output": "main.out" "output": "main.out"
} }

View file

@ -1,4 +1,4 @@
{ {
"args": "check --all main.ts", "args": "check --allow-import --all main.ts",
"output": "Download [WILDLINE]\nCheck [WILDLINE]\n" "output": "Download [WILDLINE]\nCheck [WILDLINE]\n"
} }

View file

@ -1,4 +1,5 @@
{ {
"tempDir": true,
"steps": [ "steps": [
{ {
"args": "compile --unstable-kv -A --output out main.ts", "args": "compile --unstable-kv -A --output out main.ts",

View file

@ -1,4 +1,4 @@
{ {
"args": "doc --reload types_header.ts", "args": "doc --allow-import --reload types_header.ts",
"output": "types_header.out" "output": "types_header.out"
} }

View file

@ -1,4 +1,4 @@
{ {
"args": "doc --reload http://127.0.0.1:4545/xTypeScriptTypes.js", "args": "doc --allow-import --reload http://127.0.0.1:4545/xTypeScriptTypes.js",
"output": "types_header.out" "output": "types_header.out"
} }

View file

@ -0,0 +1,4 @@
{
"args": "info --allow-import http://127.0.0.1:4545/run/048_media_types_jsx.ts",
"output": "049_info_flag_script_jsx.out"
}

Some files were not shown because too many files have changed in this diff Show more