1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-21 05:42:25 -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]]
name = "deno_graph"
version = "0.82.2"
version = "0.82.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9328b62ffc7e806f1c92fd7a22e4ff3046fcb53f2d46e3e1297482b2c4c2bb9d"
checksum = "938ed2efa1dd9fdcceeebc169b2b7910506b8dacc992cfdcffd84aa6a3eb8db0"
dependencies = [
"anyhow",
"async-trait",
@ -8119,9 +8119,9 @@ dependencies = [
[[package]]
name = "webpki-root-certs"
version = "0.26.5"
version = "0.26.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6d93b773107ba49bc84dd3b241e019c702d886fd5c457defe2ea8b1123a5dcd"
checksum = "e8c6dfa3ac045bc517de14c7b1384298de1dbd229d38e08e169d9ae8c170937c"
dependencies = [
"rustls-pki-types",
]

View file

@ -68,7 +68,7 @@ deno_cache_dir = { workspace = true }
deno_config = { version = "=0.35.0", features = ["workspace", "sync"] }
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
deno_doc = { version = "0.148.0", features = ["html", "syntect"] }
deno_graph = { version = "=0.82.2" }
deno_graph = { version = "=0.82.3" }
deno_lint = { version = "=0.67.0", features = ["docs"] }
deno_lockfile.workspace = true
deno_npm = "=0.25.2"

View file

@ -1,5 +1,6 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use std::borrow::Cow;
use std::collections::HashSet;
use std::env;
use std::ffi::OsString;
@ -44,6 +45,7 @@ use crate::args::resolve_no_prompt;
use crate::util::fs::canonicalize_path;
use super::flags_net;
use super::jsr_url;
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub enum ConfigFlag {
@ -639,6 +641,7 @@ pub struct PermissionFlags {
pub allow_write: Option<Vec<String>>,
pub deny_write: Option<Vec<String>>,
pub no_prompt: bool,
pub allow_import: Option<Vec<String>>,
}
impl PermissionFlags {
@ -658,9 +661,10 @@ impl PermissionFlags {
|| self.deny_sys.is_some()
|| self.allow_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>(
allow_all: bool,
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 {
allow_all: self.allow_all,
allow_env: handle_allow(self.allow_all, self.allow_env.clone()),
@ -689,11 +728,33 @@ impl PermissionFlags {
deny_sys: self.deny_sys.clone(),
allow_write: handle_allow(self.allow_all, self.allow_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),
}
}
}
/// 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 {
allowlist
.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
}
@ -991,6 +1063,7 @@ impl Flags {
self.permissions.allow_write = None;
self.permissions.allow_sys = None;
self.permissions.allow_ffi = None;
self.permissions.allow_import = None;
}
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(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")
.value_hint(ValueHint::FilePath),
)
.arg(allow_import_arg())
}
)
}
@ -1994,6 +2069,7 @@ Show documentation for runtime built-ins:
.arg(no_lock_arg())
.arg(no_npm_arg())
.arg(no_remote_arg())
.arg(allow_import_arg())
.arg(
Arg::new("json")
.long("json")
@ -2358,6 +2434,7 @@ The following information is shown:
.help("UNSTABLE: Outputs the information in JSON format")
.action(ArgAction::SetTrue),
))
.arg(allow_import_arg())
}
fn install_subcommand() -> Command {
@ -3151,47 +3228,44 @@ fn permission_args(app: Command, requires: Option<&'static str>) -> Command {
.after_help(cstr!(r#"<y>Permission options:</>
<y>Docs</>: <c>https://docs.deno.com/go/permissions</>
<g>-A, --allow-all</> Allow all permissions.
<g>--no-prompt</> Always throw if required permission wasn't passed.
<p(245)>Can also be set via the DENO_NO_PROMPT environment variable.</>
<g>-R, --allow-read[=<<PATH>...]</> Allow file system read access. Optionally specify allowed paths.
<p(245)>--allow-read | --allow-read="/etc,/var/log.txt"</>
<g>-W, --allow-write[=<<PATH>...]</> Allow file system write access. Optionally specify allowed paths.
<p(245)>--allow-write | --allow-write="/etc,/var/log.txt"</>
<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"</>
<g>-E, --allow-env[=<<VARIABLE_NAME>...]</> Allow access to environment variables. Optionally specify accessible environment variables.
<p(245)>--allow-env | --allow-env="PORT,HOME,PATH"</>
<g>-S, --allow-sys[=<<API_NAME>...]</> Allow access to OS information. Optionally allow specific APIs by function name.
<p(245)>--allow-sys | --allow-sys="systemMemoryInfo,osRelease"</>
<g>--allow-run[=<<PROGRAM_NAME>...]</> Allow running subprocesses. Optionally specify allowed runnable program names.
<p(245)>--allow-run | --allow-run="whoami,ps"</>
<g>--allow-ffi[=<<PATH>...]</> (Unstable) Allow loading dynamic libraries. Optionally specify allowed directories or files.
<p(245)>--allow-ffi | --allow-ffi="./libfoo.so"</>
<g> --deny-read[=<<PATH>...]</> Deny file system read access. Optionally specify denied paths.
<p(245)>--deny-read | --deny-read="/etc,/var/log.txt"</>
<g> --deny-write[=<<PATH>...]</> Deny file system write access. Optionally specify denied paths.
<p(245)>--deny-write | --deny-write="/etc,/var/log.txt"</>
<g> --deny-net[=<<IP_OR_HOSTNAME>...]</> Deny network access. Optionally specify defined IP addresses and host names, with ports as necessary.
<p(245)>--deny-net | --deny-net="localhost:8080,deno.land"</>
<g> --deny-env[=<<VARIABLE_NAME>...]</> Deny access to environment variables. Optionally specify inacessible environment variables.
<p(245)>--deny-env | --deny-env="PORT,HOME,PATH"</>
<g>-S, --deny-sys[=<<API_NAME>...]</> Deny access to OS information. Optionally deny specific APIs by function name.
<p(245)>--deny-sys | --deny-sys="systemMemoryInfo,osRelease"</>
<g>--deny-run[=<<PROGRAM_NAME>...]</> Deny running subprocesses. Optionally specify denied runnable program names.
<p(245)>--deny-run | --deny-run="whoami,ps"</>
<g>--deny-ffi[=<<PATH>...]</> (Unstable) Deny loading dynamic libraries. Optionally specify denied directories or files.
<p(245)>--deny-ffi | --deny-ffi="./libfoo.so"</>
<g>-A, --allow-all</> Allow all permissions.
<g>--no-prompt</> Always throw if required permission wasn't passed.
<p(245)>Can also be set via the DENO_NO_PROMPT environment variable.</>
<g>-R, --allow-read[=<<PATH>...]</> Allow file system read access. Optionally specify allowed paths.
<p(245)>--allow-read | --allow-read="/etc,/var/log.txt"</>
<g>-W, --allow-write[=<<PATH>...]</> Allow file system write access. Optionally specify allowed paths.
<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.
<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.
<p(245)>--allow-env | --allow-env="PORT,HOME,PATH"</>
<g>-S, --allow-sys[=<<API_NAME>...]</> Allow access to OS information. Optionally allow specific APIs by function name.
<p(245)>--allow-sys | --allow-sys="systemMemoryInfo,osRelease"</>
<g>--allow-run[=<<PROGRAM_NAME>...]</> Allow running subprocesses. Optionally specify allowed runnable program names.
<p(245)>--allow-run | --allow-run="whoami,ps"</>
<g>--allow-ffi[=<<PATH>...]</> (Unstable) Allow loading dynamic libraries. Optionally specify allowed directories or files.
<p(245)>--allow-ffi | --allow-ffi="./libfoo.so"</>
<g> --deny-read[=<<PATH>...]</> Deny file system read access. Optionally specify denied paths.
<p(245)>--deny-read | --deny-read="/etc,/var/log.txt"</>
<g> --deny-write[=<<PATH>...]</> Deny file system write access. Optionally specify denied paths.
<p(245)>--deny-write | --deny-write="/etc,/var/log.txt"</>
<g> --deny-net[=<<IP_OR_HOSTNAME>...]</> Deny network access. Optionally specify defined IP addresses and host names, with ports as necessary.
<p(245)>--deny-net | --deny-net="localhost:8080,deno.land"</>
<g> --deny-env[=<<VARIABLE_NAME>...]</> Deny access to environment variables. Optionally specify inacessible environment variables.
<p(245)>--deny-env | --deny-env="PORT,HOME,PATH"</>
<g>-S, --deny-sys[=<<API_NAME>...]</> Deny access to OS information. Optionally deny specific APIs by function name.
<p(245)>--deny-sys | --deny-sys="systemMemoryInfo,osRelease"</>
<g>--deny-run[=<<PROGRAM_NAME>...]</> Deny running subprocesses. Optionally specify denied runnable program names.
<p(245)>--deny-run | --deny-run="whoami,ps"</>
<g>--deny-ffi[=<<PATH>...]</> (Unstable) Deny loading dynamic libraries. Optionally specify denied directories or files.
<p(245)>--deny-ffi | --deny-ffi="./libfoo.so"</>
"#))
.arg(
{
let mut arg = Arg::new("allow-all")
.short('A')
.long("allow-all")
.action(ArgAction::SetTrue)
.help("Allow all permissions")
.hide(true)
;
let mut arg = allow_all_arg().hide(true);
if let Some(requires) = requires {
arg = arg.requires(requires)
}
@ -3200,7 +3274,7 @@ fn permission_args(app: Command, requires: Option<&'static str>) -> Command {
)
.arg(
{
let mut arg = Arg::new("allow-read")
let mut arg = Arg::new("allow-read")
.long("allow-read")
.short('R')
.num_args(0..)
@ -3218,7 +3292,7 @@ fn permission_args(app: Command, requires: Option<&'static str>) -> Command {
)
.arg(
{
let mut arg = Arg::new("deny-read")
let mut arg = Arg::new("deny-read")
.long("deny-read")
.num_args(0..)
.action(ArgAction::Append)
@ -3235,7 +3309,7 @@ fn permission_args(app: Command, requires: Option<&'static str>) -> Command {
)
.arg(
{
let mut arg = Arg::new("allow-write")
let mut arg = Arg::new("allow-write")
.long("allow-write")
.short('W')
.num_args(0..)
@ -3253,7 +3327,7 @@ fn permission_args(app: Command, requires: Option<&'static str>) -> Command {
)
.arg(
{
let mut arg = Arg::new("deny-write")
let mut arg = Arg::new("deny-write")
.long("deny-write")
.num_args(0..)
.action(ArgAction::Append)
@ -3270,7 +3344,7 @@ fn permission_args(app: Command, requires: Option<&'static str>) -> Command {
)
.arg(
{
let mut arg = Arg::new("allow-net")
let mut arg = Arg::new("allow-net")
.long("allow-net")
.short('N')
.num_args(0..)
@ -3289,7 +3363,7 @@ fn permission_args(app: Command, requires: Option<&'static str>) -> Command {
)
.arg(
{
let mut arg = Arg::new("deny-net")
let mut arg = Arg::new("deny-net")
.long("deny-net")
.num_args(0..)
.use_value_delimiter(true)
@ -3383,7 +3457,7 @@ fn permission_args(app: Command, requires: Option<&'static str>) -> Command {
)
.arg(
{
let mut arg = Arg::new("deny-sys")
let mut arg = Arg::new("deny-sys")
.long("deny-sys")
.num_args(0..)
.use_value_delimiter(true)
@ -3418,7 +3492,7 @@ fn permission_args(app: Command, requires: Option<&'static str>) -> Command {
)
.arg(
{
let mut arg = Arg::new("deny-run")
let mut arg = Arg::new("deny-run")
.long("deny-run")
.num_args(0..)
.use_value_delimiter(true)
@ -3509,6 +3583,26 @@ fn permission_args(app: Command, requires: Option<&'static str>) -> Command {
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(
@ -3537,6 +3631,20 @@ fn runtime_args(
.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 {
app
.arg(
@ -4174,6 +4282,7 @@ fn cache_parse(
unstable_args_parse(flags, matches, UnstableArgsConfig::ResolutionOnly);
frozen_lockfile_arg_parse(flags, matches);
allow_scripts_arg_parse(flags, matches)?;
allow_import_parse(flags, matches);
let files = matches.remove_many::<String>("file").unwrap().collect();
flags.subcommand = DenoSubcommand::Cache(CacheFlags { files });
Ok(())
@ -4195,6 +4304,7 @@ fn check_parse(
doc: matches.get_flag("doc"),
doc_only: matches.get_flag("doc-only"),
});
allow_import_parse(flags, matches);
Ok(())
}
@ -4320,6 +4430,7 @@ fn doc_parse(
no_lock_arg_parse(flags, matches);
no_npm_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 = if let Some(val) = source_files_val {
@ -4460,6 +4571,7 @@ fn info_parse(
lock_args_parse(flags, matches);
no_remote_arg_parse(flags, matches);
no_npm_arg_parse(flags, matches);
allow_import_parse(flags, matches);
let json = matches.get_flag("json");
flags.subcommand = DenoSubcommand::Info(InfoFlags {
file: matches.remove_one::<String>("file"),
@ -4495,6 +4607,7 @@ fn install_parse(
force,
}),
});
return Ok(());
}
@ -5175,13 +5288,22 @@ fn permission_args_parse(
}
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") {
flags.allow_all();
}
allow_import_parse(flags, matches);
if matches.get_flag("no-prompt") {
flags.permissions.no_prompt = true;
}
@ -5189,6 +5311,13 @@ fn permission_args_parse(
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(
flags: &mut Flags,
matches: &mut ArgMatches,
@ -6215,7 +6344,7 @@ mod tests {
#[test]
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!(
r.unwrap(),
Flags {
@ -6226,6 +6355,7 @@ mod tests {
allow_read: Some(vec![]),
allow_write: Some(vec![]),
allow_env: Some(vec![]),
allow_import: Some(vec![]),
allow_net: Some(vec![]),
allow_sys: Some(vec![]),
..Default::default()
@ -10777,7 +10907,7 @@ mod tests {
}
);
// just make sure this doesn't panic
let _ = flags.permissions.to_options();
let _ = flags.permissions.to_options(&[]);
}
#[test]
@ -10852,4 +10982,27 @@ mod tests {
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
flags: Arc<Flags>,
initial_cwd: PathBuf,
main_module_cell: std::sync::OnceLock<Result<ModuleSpecifier, AnyError>>,
maybe_node_modules_folder: Option<PathBuf>,
npmrc: Arc<ResolvedNpmRc>,
maybe_lockfile: Option<Arc<CliLockfile>>,
@ -825,6 +826,7 @@ impl CliOptions {
npmrc,
maybe_node_modules_folder,
overrides: Default::default(),
main_module_cell: std::sync::OnceLock::new(),
start_dir,
deno_dir_provider,
})
@ -1105,40 +1107,43 @@ impl CliOptions {
self.flags.env_file.as_ref()
}
pub fn resolve_main_module(&self) -> Result<ModuleSpecifier, AnyError> {
let main_module = match &self.flags.subcommand {
DenoSubcommand::Compile(compile_flags) => {
resolve_url_or_path(&compile_flags.source_file, self.initial_cwd())?
}
DenoSubcommand::Eval(_) => {
resolve_url_or_path("./$deno$eval.ts", self.initial_cwd())?
}
DenoSubcommand::Repl(_) => {
resolve_url_or_path("./$deno$repl.ts", self.initial_cwd())?
}
DenoSubcommand::Run(run_flags) => {
if run_flags.is_stdin() {
std::env::current_dir()
.context("Unable to get CWD")
.and_then(|cwd| {
resolve_url_or_path("./$deno$stdin.ts", &cwd)
.map_err(AnyError::from)
})?
} else if NpmPackageReqReference::from_str(&run_flags.script).is_ok() {
ModuleSpecifier::parse(&run_flags.script)?
} else {
resolve_url_or_path(&run_flags.script, self.initial_cwd())?
}
}
DenoSubcommand::Serve(run_flags) => {
resolve_url_or_path(&run_flags.script, self.initial_cwd())?
}
_ => {
bail!("No main module.")
}
};
pub fn resolve_main_module(&self) -> Result<&ModuleSpecifier, AnyError> {
self
.main_module_cell
.get_or_init(|| {
let main_module = match &self.flags.subcommand {
DenoSubcommand::Compile(compile_flags) => {
resolve_url_or_path(&compile_flags.source_file, self.initial_cwd())?
}
DenoSubcommand::Eval(_) => {
resolve_url_or_path("./$deno$eval.ts", self.initial_cwd())?
}
DenoSubcommand::Repl(_) => {
resolve_url_or_path("./$deno$repl.ts", self.initial_cwd())?
}
DenoSubcommand::Run(run_flags) => {
if run_flags.is_stdin() {
resolve_url_or_path("./$deno$stdin.ts", self.initial_cwd())?
} else if NpmPackageReqReference::from_str(&run_flags.script)
.is_ok()
{
ModuleSpecifier::parse(&run_flags.script)?
} else {
resolve_url_or_path(&run_flags.script, self.initial_cwd())?
}
}
DenoSubcommand::Serve(run_flags) => {
resolve_url_or_path(&run_flags.script, self.initial_cwd())?
}
_ => {
bail!("No main module.")
}
};
Ok(main_module)
Ok(main_module)
})
.as_ref()
.map_err(|err| deno_core::anyhow::anyhow!("{}", err))
}
pub fn resolve_file_header_overrides(
@ -1159,7 +1164,7 @@ impl CliOptions {
(maybe_main_specifier, maybe_content_type)
{
HashMap::from([(
main_specifier,
main_specifier.clone(),
HashMap::from([("content-type".to_string(), content_type.to_string())]),
)])
} else {
@ -1480,7 +1485,34 @@ impl CliOptions {
}
pub fn permissions_options(&self) -> PermissionsOptions {
self.flags.permissions.to_options()
fn files_to_urls(files: &[String]) -> Vec<Cow<'_, Url>> {
files
.iter()
.filter_map(|f| Url::parse(f).ok().map(Cow::Owned))
.collect()
}
// get a list of urls to imply for --allow-import
let cli_arg_urls = self
.resolve_main_module()
.ok()
.map(|url| vec![Cow::Borrowed(url)])
.or_else(|| match &self.flags.subcommand {
DenoSubcommand::Cache(cache_flags) => {
Some(files_to_urls(&cache_flags.files))
}
DenoSubcommand::Check(check_flags) => {
Some(files_to_urls(&check_flags.files))
}
DenoSubcommand::Install(InstallFlags {
kind: InstallKind::Global(flags),
}) => Url::parse(&flags.module_url)
.ok()
.map(|url| vec![Cow::Owned(url)]),
_ => None,
})
.unwrap_or_default();
self.flags.permissions.to_options(&cli_arg_urls)
}
pub fn reload_flag(&self) -> bool {

42
cli/cache/mod.rs vendored
View file

@ -1,10 +1,11 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use crate::args::jsr_url;
use crate::args::CacheSetting;
use crate::errors::get_error_class_name;
use crate::file_fetcher::FetchNoFollowOptions;
use crate::file_fetcher::FetchOptions;
use crate::file_fetcher::FetchPermissionsOption;
use crate::file_fetcher::FetchPermissionsOptionRef;
use crate::file_fetcher::FileFetcher;
use crate::file_fetcher::FileOrRedirect;
use crate::npm::CliNpmResolver;
@ -19,6 +20,7 @@ use deno_graph::source::CacheInfo;
use deno_graph::source::LoadFuture;
use deno_graph::source::LoadResponse;
use deno_graph::source::Loader;
use deno_runtime::deno_permissions::PermissionsContainer;
use std::collections::HashMap;
use std::path::Path;
use std::path::PathBuf;
@ -104,6 +106,13 @@ pub type LocalLspHttpCache =
deno_cache_dir::LocalLspHttpCache<RealDenoCacheEnv>;
pub use deno_cache_dir::HttpCache;
pub struct FetchCacherOptions {
pub file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>,
pub permissions: PermissionsContainer,
/// If we're publishing for `deno publish`.
pub is_deno_publish: bool,
}
/// A "wrapper" for the FileFetcher and DiskCache for the Deno CLI that provides
/// a concise interface to the DENO_DIR when building module graphs.
pub struct FetchCacher {
@ -112,26 +121,27 @@ pub struct FetchCacher {
global_http_cache: Arc<GlobalHttpCache>,
npm_resolver: Arc<dyn CliNpmResolver>,
module_info_cache: Arc<ModuleInfoCache>,
permissions: FetchPermissionsOption,
permissions: PermissionsContainer,
cache_info_enabled: bool,
is_deno_publish: bool,
}
impl FetchCacher {
pub fn new(
file_fetcher: Arc<FileFetcher>,
file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>,
global_http_cache: Arc<GlobalHttpCache>,
npm_resolver: Arc<dyn CliNpmResolver>,
module_info_cache: Arc<ModuleInfoCache>,
permissions: FetchPermissionsOption,
options: FetchCacherOptions,
) -> Self {
Self {
file_fetcher,
file_header_overrides,
global_http_cache,
npm_resolver,
module_info_cache,
permissions,
file_header_overrides: options.file_header_overrides,
permissions: options.permissions,
is_deno_publish: options.is_deno_publish,
cache_info_enabled: false,
}
}
@ -208,10 +218,24 @@ impl Loader for FetchCacher {
}
}
if self.is_deno_publish
&& matches!(specifier.scheme(), "http" | "https")
&& !specifier.as_str().starts_with(jsr_url().as_str())
{
// mark non-JSR remote modules as external so we don't need --allow-import
// permissions as these will error out later when publishing
return Box::pin(futures::future::ready(Ok(Some(
LoadResponse::External {
specifier: specifier.clone(),
},
))));
}
let file_fetcher = self.file_fetcher.clone();
let file_header_overrides = self.file_header_overrides.clone();
let permissions = self.permissions.clone();
let specifier = specifier.clone();
let is_statically_analyzable = !options.was_dynamic_root;
async move {
let maybe_cache_setting = match options.cache_setting {
@ -230,7 +254,11 @@ impl Loader for FetchCacher {
.fetch_no_follow_with_options(FetchNoFollowOptions {
fetch_options: FetchOptions {
specifier: &specifier,
permissions: permissions.as_ref(),
permissions: if is_statically_analyzable {
FetchPermissionsOptionRef::StaticContainer(&permissions)
} else {
FetchPermissionsOptionRef::DynamicContainer(&permissions)
},
maybe_accept: None,
maybe_cache_setting: maybe_cache_setting.as_ref(),
},

View file

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

View file

@ -23,6 +23,7 @@ use deno_graph::source::LoaderChecksum;
use deno_runtime::deno_permissions::PermissionsContainer;
use deno_runtime::deno_web::BlobStore;
use deno_runtime::fs_util::specifier_to_file_path;
use log::debug;
use std::borrow::Cow;
use std::collections::HashMap;
@ -135,7 +136,7 @@ impl MemoryFiles {
/// Fetch a source file from the local file system.
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}"))
})?;
// 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)]
pub enum FetchPermissionsOptionRef<'a> {
AllowAll,
Container(&'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)
}
DynamicContainer(&'a PermissionsContainer),
StaticContainer(&'a PermissionsContainer),
}
pub struct FetchOptions<'a> {
@ -564,7 +543,6 @@ impl FileFetcher {
}
/// Fetch a source file and asynchronously return it.
#[allow(dead_code)] // todo(25469): undo when merging
#[inline(always)]
pub async fn fetch(
&self,
@ -572,7 +550,10 @@ impl FileFetcher {
permissions: &PermissionsContainer,
) -> Result<File, AnyError> {
self
.fetch_inner(specifier, FetchPermissionsOptionRef::Container(permissions))
.fetch_inner(
specifier,
FetchPermissionsOptionRef::StaticContainer(permissions),
)
.await
}
@ -647,8 +628,17 @@ impl FileFetcher {
FetchPermissionsOptionRef::AllowAll => {
// allow
}
FetchPermissionsOptionRef::Container(permissions) => {
permissions.check_specifier(specifier)?;
FetchPermissionsOptionRef::StaticContainer(permissions) => {
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) {

View file

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

View file

@ -11,7 +11,6 @@ use crate::cache::ModuleInfoCache;
use crate::cache::ParsedSourceCache;
use crate::colors;
use crate::errors::get_error_class_name;
use crate::file_fetcher::FetchPermissionsOption;
use crate::file_fetcher::FileFetcher;
use crate::npm::CliNpmResolver;
use crate::resolver::CliGraphResolver;
@ -41,6 +40,7 @@ use deno_graph::ResolutionError;
use deno_graph::SpecifierError;
use deno_runtime::deno_fs::FileSystem;
use deno_runtime::deno_node;
use deno_runtime::deno_permissions::PermissionsContainer;
use deno_runtime::fs_util::specifier_to_file_path;
use deno_semver::jsr::JsrDepPackageReq;
use deno_semver::package::PackageNv;
@ -249,6 +249,19 @@ impl ModuleGraphCreator {
package_configs: &[JsrPackageConfig],
build_fast_check_graph: bool,
) -> 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();
for package_config in package_configs {
roots.extend(package_config.config_file.resolve_export_value_urls()?);
@ -262,9 +275,12 @@ impl ModuleGraphCreator {
})
.await?;
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?;
}
if build_fast_check_graph {
let fast_check_workspace_members = package_configs
.iter()
@ -279,6 +295,7 @@ impl ModuleGraphCreator {
},
)?;
}
Ok(graph)
}
@ -370,6 +387,7 @@ pub struct ModuleGraphBuilder {
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
file_fetcher: Arc<FileFetcher>,
global_http_cache: Arc<GlobalHttpCache>,
root_permissions_container: PermissionsContainer,
}
impl ModuleGraphBuilder {
@ -386,6 +404,7 @@ impl ModuleGraphBuilder {
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
file_fetcher: Arc<FileFetcher>,
global_http_cache: Arc<GlobalHttpCache>,
root_permissions_container: PermissionsContainer,
) -> Self {
Self {
options,
@ -399,6 +418,7 @@ impl ModuleGraphBuilder {
maybe_file_watcher_reporter,
file_fetcher,
global_http_cache,
root_permissions_container,
}
}
@ -670,20 +690,26 @@ impl ModuleGraphBuilder {
/// Creates the default loader used for creating a graph.
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(
&self,
permissions: FetchPermissionsOption,
permissions: PermissionsContainer,
) -> cache::FetchCacher {
cache::FetchCacher::new(
self.file_fetcher.clone(),
self.options.resolve_file_header_overrides(),
self.global_http_cache.clone(),
self.npm_resolver.clone(),
self.module_info_cache.clone(),
permissions,
cache::FetchCacherOptions {
file_header_overrides: self.options.resolve_file_header_overrides(),
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
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()
}),
initial_cwd,

View file

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

View file

@ -130,8 +130,6 @@ struct SharedModuleLoaderState {
#[derive(Clone)]
struct EmbeddedModuleLoader {
shared: Arc<SharedModuleLoaderState>,
root_permissions: PermissionsContainer,
dynamic_permissions: PermissionsContainer,
}
pub const MODULE_NOT_FOUND: &str = "Module not found";
@ -402,28 +400,23 @@ struct StandaloneModuleLoaderFactory {
impl ModuleLoaderFactory for StandaloneModuleLoaderFactory {
fn create_for_main(
&self,
root_permissions: PermissionsContainer,
dynamic_permissions: PermissionsContainer,
_root_permissions: PermissionsContainer,
) -> ModuleLoaderAndSourceMapGetter {
ModuleLoaderAndSourceMapGetter {
module_loader: Rc::new(EmbeddedModuleLoader {
shared: self.shared.clone(),
root_permissions,
dynamic_permissions,
}),
}
}
fn create_for_worker(
&self,
root_permissions: PermissionsContainer,
dynamic_permissions: PermissionsContainer,
_parent_permissions: PermissionsContainer,
_permissions: PermissionsContainer,
) -> ModuleLoaderAndSourceMapGetter {
ModuleLoaderAndSourceMapGetter {
module_loader: Rc::new(EmbeddedModuleLoader {
shared: self.shared.clone(),
root_permissions,
dynamic_permissions,
}),
}
}
@ -664,7 +657,8 @@ pub async fn run(
};
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 let Some(vfs_root) = maybe_vfs_root {
match &mut permissions.allow_read {
@ -713,6 +707,7 @@ pub async fn run(
npm_resolver,
permission_desc_parser,
root_cert_store_provider,
permissions,
StorageKeyResolver::empty(),
crate::args::DenoSubcommand::Run(Default::default()),
CliMainWorkerOptions {
@ -752,7 +747,7 @@ pub async fn run(
deno_core::JsRuntime::init_platform(None, true);
let mut worker = worker_factory
.create_main_worker(WorkerExecutionMode::Run, main_module, permissions)
.create_main_worker(WorkerExecutionMode::Run, main_module)
.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 file_fetcher = factory.file_fetcher()?;
let root_permissions = factory.root_permissions_container()?;
let mut specifiers_for_typecheck = if check_flags.doc {
specifiers.clone()
@ -59,7 +60,7 @@ pub async fn check(
};
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)?;
for snippet_file in snippet_files {
specifiers_for_typecheck.push(snippet_file.specifier.clone());

View file

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

View file

@ -644,8 +644,21 @@ impl<'a> GraphDisplayContext<'a> {
ModuleError::InvalidTypeAssertion { .. } => {
self.build_error_msg(specifier, "(invalid import attribute)")
}
ModuleError::LoadingErr(_, _, _) => {
self.build_error_msg(specifier, "(loading error)")
ModuleError::LoadingErr(_, _, err) => {
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(_, _) => {
self.build_error_msg(specifier, "(parsing error)")

View file

@ -3,7 +3,6 @@
use std::borrow::Cow;
use std::path::PathBuf;
use std::sync::Arc;
use std::sync::Mutex;
use deno_ast::diagnostics::Diagnostic;
use deno_ast::diagnostics::DiagnosticLevel;
@ -21,6 +20,7 @@ use deno_ast::SourceRanged;
use deno_ast::SourceTextInfo;
use deno_core::anyhow::anyhow;
use deno_core::error::AnyError;
use deno_core::parking_lot::Mutex;
use deno_core::url::Url;
use deno_graph::FastCheckDiagnostic;
use deno_semver::Version;
@ -36,7 +36,7 @@ impl PublishDiagnosticsCollector {
pub fn print_and_error(&self) -> Result<(), AnyError> {
let mut errors = 0;
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());
@ -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) {
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")
} else {
log::info!("Checking for slow types in the public API...");
let mut any_pkg_had_diagnostics = false;
for package in package_configs {
let export_urls = package.config_file.resolve_export_value_urls()?;
let diagnostics =
collect_no_slow_type_diagnostics(&graph, &export_urls);
if !diagnostics.is_empty() {
any_pkg_had_diagnostics = true;
for diagnostic in diagnostics {
diagnostics_collector
.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))
} else {
// 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> {
let npm_resolver = factory.npm_resolver().await?;
let cli_options = factory.cli_options()?;
let root_permissions = factory.root_permissions_container()?;
if let Some(npm_resolver) = npm_resolver.as_managed() {
if !npm_resolver.ensure_top_level_package_json_install().await? {
if let Some(lockfile) = cli_options.maybe_lockfile() {
@ -106,7 +107,7 @@ pub async fn cache_top_level_deps(
&roots,
false,
deno_config::deno_json::TsTypeLib::DenoWorker,
crate::file_fetcher::FetchPermissionsOption::AllowAll,
root_permissions.clone(),
None,
)
.await?;

View file

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

View file

@ -60,10 +60,9 @@ pub async fn run_script(
maybe_npm_install(&factory).await?;
let permissions = factory.create_permissions_container()?;
let worker_factory = factory.create_cli_main_worker_factory().await?;
let mut worker = worker_factory
.create_main_worker(mode, main_module, permissions)
.create_main_worker(mode, main_module.clone())
.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 worker_factory = factory.create_cli_main_worker_factory().await?;
let permissions = factory.create_permissions_container()?;
let mut source = Vec::new();
std::io::stdin().read_to_end(&mut source)?;
// 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
.create_main_worker(WorkerExecutionMode::Run, main_module, permissions)
.create_main_worker(WorkerExecutionMode::Run, main_module.clone())
.await?;
let exit_code = worker.run().await?;
Ok(exit_code)
@ -125,11 +123,10 @@ async fn run_with_watch(
let _ = watcher_communicator.watch_paths(cli_options.watch_paths());
let permissions = factory.create_permissions_container()?;
let mut worker = factory
.create_cli_main_worker_factory()
.await?
.create_main_worker(mode, main_module, permissions)
.create_main_worker(mode, main_module.clone())
.await?;
if watch_flags.hmr {
@ -173,10 +170,9 @@ pub async fn eval_command(
source: source_code.into_bytes().into(),
});
let permissions = factory.create_permissions_container()?;
let worker_factory = factory.create_cli_main_worker_factory().await?;
let mut worker = worker_factory
.create_main_worker(WorkerExecutionMode::Eval, main_module, permissions)
.create_main_worker(WorkerExecutionMode::Eval, main_module.clone())
.await?;
let exit_code = worker.run().await?;
Ok(exit_code)

View file

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

View file

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

View file

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

View file

@ -14,7 +14,6 @@ use deno_core::serde::Deserializer;
use deno_core::serde::Serialize;
use deno_core::serde_json;
use deno_core::unsync::sync::AtomicFlag;
use deno_core::url;
use deno_core::url::Url;
use deno_core::ModuleSpecifier;
use deno_terminal::colors;
@ -950,6 +949,15 @@ impl NetDescriptor {
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 {
@ -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)]
pub struct EnvDescriptor(EnvVarName);
@ -1519,19 +1594,35 @@ impl UnaryPermission<NetDescriptor> {
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,
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>,
) -> Result<(), AnyError> {
skip_check_if_is_permission_fully_granted!(self);
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();
let descriptor = NetDescriptor(host, port);
self.check_desc(Some(&descriptor), false, api_name)
self.check_desc(Some(host), false, api_name)
}
pub fn check_all(&mut self) -> Result<(), AnyError> {
@ -1700,6 +1791,7 @@ pub struct Permissions {
pub sys: UnaryPermission<SysDescriptor>,
pub run: UnaryPermission<RunQueryDescriptor>,
pub ffi: UnaryPermission<FfiQueryDescriptor>,
pub import: UnaryPermission<ImportDescriptor>,
pub all: UnitPermission,
}
@ -1720,6 +1812,7 @@ pub struct PermissionsOptions {
pub deny_sys: Option<Vec<String>>,
pub allow_write: Option<Vec<String>>,
pub deny_write: Option<Vec<String>>,
pub allow_import: Option<Vec<String>>,
pub prompt: bool,
}
@ -1888,6 +1981,13 @@ impl Permissions {
})?,
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),
})
}
@ -1902,6 +2002,7 @@ impl Permissions {
sys: UnaryPermission::allow_all(),
run: UnaryPermission::allow_all(),
ffi: UnaryPermission::allow_all(),
import: UnaryPermission::allow_all(),
all: Permissions::new_all(true),
}
}
@ -1925,35 +2026,10 @@ impl Permissions {
sys: Permissions::new_unary(None, None, prompt).unwrap(),
run: 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),
}
}
/// 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
@ -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.
///
/// We need a way to have internal mutability for permissions as they might get
@ -2039,8 +2121,43 @@ impl PermissionsContainer {
pub fn check_specifier(
&self,
specifier: &ModuleSpecifier,
kind: CheckSpecifierKind,
) -> 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"]
@ -2375,7 +2492,12 @@ impl PermissionsContainer {
url: &Url,
api_name: &str,
) -> 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)]
@ -2589,6 +2711,7 @@ pub struct ChildPermissionsArg {
env: ChildUnaryPermissionArg,
net: ChildUnaryPermissionArg,
ffi: ChildUnaryPermissionArg,
import: ChildUnaryPermissionArg,
read: ChildUnaryPermissionArg,
run: ChildUnaryPermissionArg,
sys: ChildUnaryPermissionArg,
@ -2601,6 +2724,7 @@ impl ChildPermissionsArg {
env: ChildUnaryPermissionArg::Inherit,
net: ChildUnaryPermissionArg::Inherit,
ffi: ChildUnaryPermissionArg::Inherit,
import: ChildUnaryPermissionArg::Inherit,
read: ChildUnaryPermissionArg::Inherit,
run: ChildUnaryPermissionArg::Inherit,
sys: ChildUnaryPermissionArg::Inherit,
@ -2613,6 +2737,7 @@ impl ChildPermissionsArg {
env: ChildUnaryPermissionArg::NotGranted,
net: ChildUnaryPermissionArg::NotGranted,
ffi: ChildUnaryPermissionArg::NotGranted,
import: ChildUnaryPermissionArg::NotGranted,
read: ChildUnaryPermissionArg::NotGranted,
run: ChildUnaryPermissionArg::NotGranted,
sys: ChildUnaryPermissionArg::NotGranted,
@ -2677,6 +2802,11 @@ impl<'de> Deserialize<'de> for ChildPermissionsArg {
child_permissions_arg.ffi = arg.map_err(|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" {
let arg = serde_json::from_value::<ChildUnaryPermissionArg>(value);
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)
-> 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)
-> Result<EnvDescriptor, AnyError>;
@ -2785,6 +2934,7 @@ pub fn create_child_permissions(
&child_permissions_arg.read,
&child_permissions_arg.write,
&child_permissions_arg.net,
&child_permissions_arg.import,
&child_permissions_arg.env,
&child_permissions_arg.sys,
&child_permissions_arg.run,
@ -2808,6 +2958,11 @@ pub fn create_child_permissions(
.create_child_permissions(child_permissions_arg.write, |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
.net
.create_child_permissions(child_permissions_arg.net, |text| {
@ -2897,6 +3052,13 @@ mod tests {
NetDescriptor::parse(text)
}
fn parse_import_descriptor(
&self,
text: &str,
) -> Result<ImportDescriptor, AnyError> {
ImportDescriptor::parse(text)
}
fn parse_env_descriptor(
&self,
text: &str,
@ -3153,8 +3315,9 @@ mod tests {
#[test]
fn test_check_net_url() {
let mut perms = Permissions::from_options(
&TestPermissionDescriptorParser,
let parser = TestPermissionDescriptorParser;
let perms = Permissions::from_options(
&parser,
&PermissionsOptions {
allow_net: Some(svec![
"localhost",
@ -3168,6 +3331,7 @@ mod tests {
},
)
.unwrap();
let mut perms = PermissionsContainer::new(Arc::new(parser), perms);
let url_tests = vec![
// 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 {
let u = url::Url::parse(url_str).unwrap();
assert_eq!(is_ok, perms.net.check_url(&u, None).is_ok(), "{}", u);
let u = Url::parse(url_str).unwrap();
assert_eq!(is_ok, perms.check_net_url(&u, "api()").is_ok(), "{}", u);
}
}
@ -3222,48 +3386,78 @@ mod tests {
} else {
svec!["/a"]
};
let mut perms = Permissions::from_options(
&TestPermissionDescriptorParser,
let parser = TestPermissionDescriptorParser;
let perms = Permissions::from_options(
&parser,
&PermissionsOptions {
allow_read: Some(read_allowlist),
allow_net: Some(svec!["localhost"]),
allow_import: Some(svec!["localhost"]),
..Default::default()
},
)
.unwrap();
let perms = PermissionsContainer::new(Arc::new(parser), perms);
let mut fixtures = vec![
(
ModuleSpecifier::parse("http://localhost:4545/mod.ts").unwrap(),
CheckSpecifierKind::Static,
true,
),
(
ModuleSpecifier::parse("http://localhost:4545/mod.ts").unwrap(),
CheckSpecifierKind::Dynamic,
true,
),
(
ModuleSpecifier::parse("http://deno.land/x/mod.ts").unwrap(),
CheckSpecifierKind::Dynamic,
false,
),
(
ModuleSpecifier::parse("data:text/plain,Hello%2C%20Deno!").unwrap(),
CheckSpecifierKind::Dynamic,
true,
),
];
if cfg!(target_os = "windows") {
fixtures
.push((ModuleSpecifier::parse("file:///C:/a/mod.ts").unwrap(), true));
fixtures.push((
ModuleSpecifier::parse("file:///C:/a/mod.ts").unwrap(),
CheckSpecifierKind::Dynamic,
true,
));
fixtures.push((
ModuleSpecifier::parse("file:///C:/b/mod.ts").unwrap(),
CheckSpecifierKind::Static,
true,
));
fixtures.push((
ModuleSpecifier::parse("file:///C:/b/mod.ts").unwrap(),
CheckSpecifierKind::Dynamic,
false,
));
} else {
fixtures
.push((ModuleSpecifier::parse("file:///a/mod.ts").unwrap(), true));
fixtures
.push((ModuleSpecifier::parse("file:///b/mod.ts").unwrap(), false));
fixtures.push((
ModuleSpecifier::parse("file:///a/mod.ts").unwrap(),
CheckSpecifierKind::Dynamic,
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!(
perms.check_specifier(&specifier).is_ok(),
perms.check_specifier(&specifier, kind).is_ok(),
expected,
"{}",
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]
fn test_query() {
set_prompter(Box::new(TestPrompter));
@ -3885,6 +4061,7 @@ mod tests {
env: ChildUnaryPermissionArg::Inherit,
net: ChildUnaryPermissionArg::Inherit,
ffi: ChildUnaryPermissionArg::Inherit,
import: ChildUnaryPermissionArg::Inherit,
read: ChildUnaryPermissionArg::Inherit,
run: ChildUnaryPermissionArg::Inherit,
sys: ChildUnaryPermissionArg::Inherit,
@ -3897,6 +4074,7 @@ mod tests {
env: ChildUnaryPermissionArg::NotGranted,
net: ChildUnaryPermissionArg::NotGranted,
ffi: ChildUnaryPermissionArg::NotGranted,
import: ChildUnaryPermissionArg::NotGranted,
read: ChildUnaryPermissionArg::NotGranted,
run: ChildUnaryPermissionArg::NotGranted,
sys: ChildUnaryPermissionArg::NotGranted,
@ -3930,6 +4108,7 @@ mod tests {
"env": true,
"net": true,
"ffi": true,
"import": true,
"read": true,
"run": true,
"sys": true,
@ -3940,6 +4119,7 @@ mod tests {
env: ChildUnaryPermissionArg::Granted,
net: ChildUnaryPermissionArg::Granted,
ffi: ChildUnaryPermissionArg::Granted,
import: ChildUnaryPermissionArg::Granted,
read: ChildUnaryPermissionArg::Granted,
run: ChildUnaryPermissionArg::Granted,
sys: ChildUnaryPermissionArg::Granted,
@ -3951,6 +4131,7 @@ mod tests {
"env": false,
"net": false,
"ffi": false,
"import": false,
"read": false,
"run": false,
"sys": false,
@ -3961,6 +4142,7 @@ mod tests {
env: ChildUnaryPermissionArg::NotGranted,
net: ChildUnaryPermissionArg::NotGranted,
ffi: ChildUnaryPermissionArg::NotGranted,
import: ChildUnaryPermissionArg::NotGranted,
read: ChildUnaryPermissionArg::NotGranted,
run: ChildUnaryPermissionArg::NotGranted,
sys: ChildUnaryPermissionArg::NotGranted,
@ -3972,6 +4154,7 @@ mod tests {
"env": ["foo", "bar"],
"net": ["foo", "bar:8000"],
"ffi": ["foo", "file:///bar/baz"],
"import": ["example.com"],
"read": ["foo", "file:///bar/baz"],
"run": ["foo", "file:///bar/baz", "./qux"],
"sys": ["hostname", "osRelease"],
@ -3985,6 +4168,7 @@ mod tests {
"foo",
"file:///bar/baz"
]),
import: ChildUnaryPermissionArg::GrantedList(svec!["example.com"]),
read: ChildUnaryPermissionArg::GrantedList(svec![
"foo",
"file:///bar/baz"

View file

@ -18,7 +18,7 @@ fn xdg_cache_home_dir() {
.env_clear()
.env("XDG_CACHE_HOME", &xdg_cache_home)
.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()
.skip_output_check()

View file

@ -9,14 +9,14 @@ use util::TestContext;
use util::TestContextBuilder;
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",
http_server: true,
exit_code: 1,
});
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(""),
http_server: true,
});
@ -227,6 +227,7 @@ fn ts_no_recheck_on_redirect() {
let test_context = TestContext::default();
let check_command = test_context.new_command().args_vec([
"run",
"--allow-import",
"--check",
"run/017_import_redirect.ts",
]);

View file

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

View file

@ -456,6 +456,7 @@ fn no_http_coverage_data() {
.new_command()
.args_vec(vec![
"test".to_string(),
"--allow-import".to_string(),
"--quiet".to_string(),
"--no-check".to_string(),
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();
context
.new_command()
.args_vec(["install", "-g", script_path_str.as_str()])
.args_vec(["install", "-g", "--allow-import", script_path_str.as_str()])
.envs([
("HOME", 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();
context
.new_command()
.args_vec(["install", "-g", script_path_str.as_str()])
.args_vec(["install", "-g", "--allow-import", script_path_str.as_str()])
.envs([
("HOME", temp_dir_str.as_str()),
("NO_COLOR", "1"),

View file

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

View file

@ -73,7 +73,7 @@ itest!(_005_more_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",
http_server: true,
});
@ -105,24 +105,25 @@ itest!(_016_double_await {
});
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",
});
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",
});
itest!(_017_import_redirect_vendor_dir {
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",
temp_cwd: true,
});
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",
});
@ -132,7 +133,7 @@ itest!(_018_async_catch {
});
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",
http_server: true,
});
@ -154,14 +155,14 @@ itest!(_025_reload_js_type_error {
});
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",
http_server: true,
});
itest!(_027_redirect_typescript_vendor_dir {
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",
http_server: true,
temp_cwd: true,
@ -175,14 +176,14 @@ itest!(_028_args {
itest!(_033_import_map_remote {
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",
http_server: true,
});
itest!(_033_import_map_vendor_dir_remote {
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",
http_server: true,
temp_cwd: true,
@ -190,7 +191,7 @@ itest!(_033_import_map_vendor_dir_remote {
itest!(_033_import_map_data_uri {
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",
http_server: true,
});
@ -201,7 +202,7 @@ itest!(onload {
});
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",
exit_code: 1,
http_server: true,
@ -237,14 +238,14 @@ itest!(_047_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",
http_server: true,
});
itest!(_052_no_remote_flag {
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",
exit_code: 1,
http_server: true,
@ -467,7 +468,7 @@ itest!(dynamic_import_already_rejected {
});
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",
http_server: true,
});
@ -802,7 +803,7 @@ itest!(private_field_presence_no_check {
itest!(lock_write_fetch {
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",
http_server: true,
exit_code: 0,
@ -810,26 +811,27 @@ itest!(lock_write_fetch {
itest!(lock_check_ok {
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",
http_server: true,
});
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",
http_server: true,
});
itest!(lock_v2_check_ok {
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",
http_server: true,
});
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",
http_server: true,
});
@ -849,7 +851,7 @@ fn lock_redirects() {
);
context
.new_command()
.args("run main.ts")
.args("run --allow-import main.ts")
.run()
.skip_output_check();
let initial_lockfile_text = r#"{
@ -865,7 +867,7 @@ fn lock_redirects() {
assert_eq!(temp_dir.read_to_string("deno.lock"), initial_lockfile_text);
context
.new_command()
.args("run main.ts")
.args("run --allow-import main.ts")
.run()
.assert_matches_text("Hello World\n");
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
context
.new_command()
.args("run main.ts Hi there")
.args("run --allow-import main.ts Hi there")
.run()
.assert_matches_text(concat!(
"Download http://localhost:4545/echo.ts\n",
@ -1260,7 +1262,7 @@ itest!(config_types {
itest!(config_types_remote {
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",
});
@ -1365,9 +1367,10 @@ itest!(error_015_dynamic_import_permissions {
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 {
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",
exit_code: 1,
http_server: true,
@ -1428,7 +1431,7 @@ itest!(error_025_tab_indent {
});
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",
exit_code: 1,
http_server: true,
@ -1471,18 +1474,18 @@ itest!(error_type_definitions {
});
itest!(error_local_static_import_from_remote_ts {
args: "run --reload http://localhost:4545/run/error_local_static_import_from_remote.ts",
exit_code: 1,
http_server: true,
output: "run/error_local_static_import_from_remote.ts.out",
});
args: "run --allow-import --reload http://localhost:4545/run/error_local_static_import_from_remote.ts",
exit_code: 1,
http_server: true,
output: "run/error_local_static_import_from_remote.ts.out",
});
itest!(error_local_static_import_from_remote_js {
args: "run --reload http://localhost:4545/run/error_local_static_import_from_remote.js",
exit_code: 1,
http_server: true,
output: "run/error_local_static_import_from_remote.js.out",
});
args: "run --allow-import --reload http://localhost:4545/run/error_local_static_import_from_remote.js",
exit_code: 1,
http_server: true,
output: "run/error_local_static_import_from_remote.js.out",
});
itest!(exit_error42 {
exit_code: 42,
@ -1531,7 +1534,7 @@ itest!(finalization_registry {
});
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",
http_server: true,
});
@ -1542,18 +1545,18 @@ itest!(if_main {
});
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",
http_server: true,
});
itest!(main_module {
args: "run --quiet --reload run/main_module/main.ts",
args: "run --quiet --reload run/main_module/main.ts",
output: "run/main_module/main.out",
});
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",
http_server: true,
});
@ -1569,14 +1572,15 @@ itest!(decorators_tc39_proposal {
});
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",
exit_code: 1,
http_server: true,
});
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",
http_server: true,
});
@ -1603,13 +1607,15 @@ itest!(type_definitions_for_export {
});
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",
http_server: true,
});
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",
});
@ -1629,13 +1635,13 @@ fn type_directives_js_main() {
}
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",
http_server: true,
});
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",
http_server: true,
});
@ -1839,20 +1845,20 @@ itest!(unstable_kv_enabled {
});
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",
http_server: true,
});
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",
http_server: true,
exit_code: 1,
});
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",
http_server: true,
exit_code: 1,
@ -1904,7 +1910,7 @@ itest!(es_private_fields {
});
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",
http_server: true,
});
@ -1915,100 +1921,101 @@ itest!(jsx_import_from_ts {
});
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",
http_server: true,
});
itest!(jsx_import_source_pragma_with_config {
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",
http_server: true,
});
itest!(jsx_import_source_pragma_with_dev_config {
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",
http_server: true,
});
itest!(jsx_import_source_no_pragma {
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",
http_server: true,
});
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",
http_server: true,
});
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",
http_server: true,
});
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",
http_server: true,
});
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",
http_server: true,
});
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",
http_server: true,
});
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",
http_server: true,
});
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",
http_server: true,
});
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",
http_server: true,
});
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",
http_server: true,
});
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",
http_server: true,
});
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",
http_server: true,
});
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",
http_server: 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 {
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",
http_server: true,
});
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",
http_server: true,
});
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",
http_server: true,
});
@ -2093,7 +2100,7 @@ itest!(import_data_url_import_relative {
});
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",
http_server: true,
});
@ -2127,7 +2134,7 @@ itest!(import_blob_url_import_relative {
itest!(import_blob_url_imports {
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",
http_server: true,
});
@ -2143,13 +2150,13 @@ itest!(import_blob_url {
});
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",
http_server: true,
});
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",
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
// from the module 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",
exit_code: 1,
http_server: true,
@ -3031,14 +3038,14 @@ mod permissions {
});
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",
http_server: true,
exit_code: 1,
});
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",
http_server: true,
exit_code: 1,
@ -3329,7 +3336,7 @@ itest!(no_config_auto_discovery_for_local_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"),
http_server: true,
});
@ -3468,6 +3475,7 @@ fn check_local_then_remote() {
let output = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("run")
.arg("--allow-import")
.arg("--check")
.arg("run/remote_type_error/main.ts")
.spawn()
@ -3478,6 +3486,7 @@ fn check_local_then_remote() {
let output = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(util::testdata_path())
.arg("run")
.arg("--allow-import")
.arg("--check=all")
.arg("run/remote_type_error/main.ts")
.env("NO_COLOR", "1")
@ -3655,6 +3664,7 @@ fn cache_test() {
.env("DENO_DIR", deno_dir.path())
.current_dir(util::testdata_path())
.arg("cache")
.arg("--allow-import=localhost:4545")
.arg("--check=all")
.arg("-L")
.arg("debug")
@ -3670,6 +3680,7 @@ fn cache_test() {
.env("NO_COLOR", "1")
.current_dir(util::testdata_path())
.arg("run")
.arg("--allow-import=localhost:4545")
.arg(module_url.to_string())
.output()
.expect("Failed to spawn script");
@ -3819,6 +3830,7 @@ fn basic_auth_tokens() {
let output = util::deno_cmd()
.current_dir(util::root_path())
.arg("run")
.arg("--allow-import")
.arg("http://127.0.0.1:4554/run/001_hello.js")
.piped_output()
.spawn()
@ -3840,6 +3852,7 @@ fn basic_auth_tokens() {
let output = util::deno_cmd()
.current_dir(util::root_path())
.arg("run")
.arg("--allow-import")
.arg("http://127.0.0.1:4554/run/001_hello.js")
.env("DENO_AUTH_TOKENS", "testuser123:testpassabc@127.0.0.1:4554")
.piped_output()
@ -4404,7 +4417,7 @@ async fn websocket_server_idletimeout() {
}
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",
http_server: true,
exit_code: 0,
@ -4563,7 +4576,9 @@ pub fn vendor_dir_config_file() {
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");
assert!(vendor_dir.exists());
@ -4574,13 +4589,15 @@ console.log(returnsHi());"#,
assert!(!vendor_dir.exists());
test_context
.new_command()
.args("cache --quiet --vendor main.ts")
.args("cache --allow-import --quiet --vendor main.ts")
.run();
assert!(vendor_dir.exists());
rm_vendor_dir();
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();
assert!(vendor_dir.exists());
@ -4608,7 +4625,7 @@ console.log(returnsHi());"#,
test_context
.new_command()
// 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()
.skip_output_check();
assert_eq!(
@ -4625,7 +4642,7 @@ console.log(returnsHi());"#,
test_context
.new_command()
// 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()
.assert_matches_text("hello there\n");
@ -5120,21 +5137,23 @@ fn emit_failed_readonly_file_system() {
fn handle_invalid_path_error() {
let deno_cmd = util::deno_cmd_with_deno_dir(&util::new_deno_dir());
let output = deno_cmd.arg("run").arg("file://asdf").output().unwrap();
assert!(
String::from_utf8_lossy(&output.stderr).contains("Invalid file path.")
assert_contains!(
String::from_utf8_lossy(&output.stderr),
"Invalid file path."
);
let deno_cmd = util::deno_cmd_with_deno_dir(&util::new_deno_dir());
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 output = deno_cmd.arg("run").arg("//a/b").output().unwrap();
assert!(
String::from_utf8_lossy(&output.stderr).contains("Invalid file path.")
assert_contains!(
String::from_utf8_lossy(&output.stderr),
"Invalid file path."
);
let deno_cmd = util::deno_cmd_with_deno_dir(&util::new_deno_dir());
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()
.current_dir(t.path())
.arg("run")
.arg("--allow-import")
.arg("--watch")
.arg("--reload")
.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"
}

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",
"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"
}

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"
}

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"
}

View file

@ -1,5 +1,5 @@
{
"args": "cache *.ts",
"args": "cache --allow-import *.ts",
"output": "Download http://localhost:4545/echo.ts\n",
"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"
}

View file

@ -1,6 +1,6 @@
{
"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,
"output": "cafile_ts_fetch.ts.out"
}, {
@ -8,11 +8,11 @@
"flaky": true,
"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,
"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,
"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,
"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,
"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",
"exitCode": 1
}

View file

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

View file

@ -1,4 +1,4 @@
{
"args": "check --all main.tsx",
"args": "check --allow-import --all main.tsx",
"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"
}

View file

@ -1,4 +1,5 @@
{
"tempDir": true,
"steps": [
{
"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"
}

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"
}

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