diff --git a/cli/standalone/mod.rs b/cli/standalone/mod.rs index 14d4ad533c..16f4c9e650 100644 --- a/cli/standalone/mod.rs +++ b/cli/standalone/mod.rs @@ -311,7 +311,7 @@ pub async fn run( http_client.clone(), progress_bar.clone(), )); - let (fs, node_modules_path, snapshot) = if let Some(snapshot) = + let (fs, vfs_root, node_modules_path, snapshot) = if let Some(snapshot) = metadata.npm_snapshot { let vfs_root_dir_path = if metadata.node_modules_dir { @@ -319,8 +319,8 @@ pub async fn run( } else { npm_cache.registry_folder(&npm_registry_url) }; - let vfs = - load_npm_vfs(vfs_root_dir_path).context("Failed to load npm vfs.")?; + let vfs = load_npm_vfs(vfs_root_dir_path.clone()) + .context("Failed to load npm vfs.")?; let node_modules_path = if metadata.node_modules_dir { Some(vfs.root().to_path_buf()) } else { @@ -328,6 +328,7 @@ pub async fn run( }; ( Arc::new(DenoCompileFileSystem::new(vfs)) as Arc, + Some(vfs_root_dir_path), node_modules_path, Some(snapshot.into_valid()?), ) @@ -336,6 +337,7 @@ pub async fn run( Arc::new(deno_fs::RealFs) as Arc, None, None, + None, ) }; let npm_resolution = Arc::new(NpmResolution::from_serialized( @@ -395,9 +397,25 @@ pub async fn run( }), }; - let permissions = PermissionsContainer::new(Permissions::from_options( - &metadata.permissions, - )?); + let permissions = { + let mut permissions = metadata.permissions; + // if running with an npm vfs, grant read access to it + if let Some(vfs_root) = vfs_root { + match &mut permissions.allow_read { + Some(vec) if vec.is_empty() => { + // do nothing, already granted + } + Some(vec) => { + vec.push(vfs_root); + } + None => { + permissions.allow_read = Some(vec![vfs_root]); + } + } + } + + PermissionsContainer::new(Permissions::from_options(&permissions)?) + }; let worker_factory = CliMainWorkerFactory::new( StorageKeyResolver::empty(), npm_resolver.clone(), diff --git a/cli/tests/integration/compile_tests.rs b/cli/tests/integration/compile_tests.rs index 05128bc076..4938b36cd2 100644 --- a/cli/tests/integration/compile_tests.rs +++ b/cli/tests/integration/compile_tests.rs @@ -912,11 +912,13 @@ testing[WILDCARD]this fn compile_npm_file_system() { run_npm_bin_compile_test(RunNpmBinCompileOptions { input_specifier: "compile/npm_fs/main.ts", + compile_args: vec!["-A"], + run_args: vec![], output_file: "compile/npm_fs/main.out", node_modules_dir: true, input_name: Some("binary"), expected_name: "binary", - run_args: vec![], + exit_code: 0, }); } @@ -924,11 +926,13 @@ fn compile_npm_file_system() { fn compile_npm_bin_esm() { run_npm_bin_compile_test(RunNpmBinCompileOptions { input_specifier: "npm:@denotest/bin/cli-esm", + compile_args: vec![], run_args: vec!["this", "is", "a", "test"], output_file: "npm/deno_run_esm.out", node_modules_dir: false, input_name: None, expected_name: "cli-esm", + exit_code: 0, }); } @@ -936,23 +940,55 @@ fn compile_npm_bin_esm() { fn compile_npm_bin_cjs() { run_npm_bin_compile_test(RunNpmBinCompileOptions { input_specifier: "npm:@denotest/bin/cli-cjs", + compile_args: vec![], run_args: vec!["this", "is", "a", "test"], output_file: "npm/deno_run_cjs.out", node_modules_dir: false, input_name: None, expected_name: "cli-cjs", + exit_code: 0, }); } #[test] -fn compile_npm_cowsay() { +fn compile_npm_cowsay_main() { run_npm_bin_compile_test(RunNpmBinCompileOptions { input_specifier: "npm:cowsay@1.5.0", + compile_args: vec!["--allow-read"], run_args: vec!["Hello"], output_file: "npm/deno_run_cowsay.out", node_modules_dir: false, input_name: None, expected_name: "cowsay", + exit_code: 0, + }); +} + +#[test] +fn compile_npm_vfs_implicit_read_permissions() { + run_npm_bin_compile_test(RunNpmBinCompileOptions { + input_specifier: "compile/vfs_implicit_read_permission/main.ts", + compile_args: vec![], + run_args: vec![], + output_file: "compile/vfs_implicit_read_permission/main.out", + node_modules_dir: false, + input_name: Some("binary"), + expected_name: "binary", + exit_code: 0, + }); +} + +#[test] +fn compile_npm_no_permissions() { + run_npm_bin_compile_test(RunNpmBinCompileOptions { + input_specifier: "npm:cowsay@1.5.0", + compile_args: vec![], + run_args: vec!["Hello"], + output_file: "npm/deno_run_cowsay_no_permissions.out", + node_modules_dir: false, + input_name: None, + expected_name: "cowsay", + exit_code: 1, }); } @@ -960,11 +996,13 @@ fn compile_npm_cowsay() { fn compile_npm_cowsay_explicit() { run_npm_bin_compile_test(RunNpmBinCompileOptions { input_specifier: "npm:cowsay@1.5.0/cowsay", + compile_args: vec!["--allow-read"], run_args: vec!["Hello"], output_file: "npm/deno_run_cowsay.out", node_modules_dir: false, input_name: None, expected_name: "cowsay", + exit_code: 0, }); } @@ -972,21 +1010,25 @@ fn compile_npm_cowsay_explicit() { fn compile_npm_cowthink() { run_npm_bin_compile_test(RunNpmBinCompileOptions { input_specifier: "npm:cowsay@1.5.0/cowthink", + compile_args: vec!["--allow-read"], run_args: vec!["Hello"], output_file: "npm/deno_run_cowthink.out", node_modules_dir: false, input_name: None, expected_name: "cowthink", + exit_code: 0, }); } struct RunNpmBinCompileOptions<'a> { input_specifier: &'a str, - output_file: &'a str, node_modules_dir: bool, + output_file: &'a str, input_name: Option<&'a str>, expected_name: &'a str, run_args: Vec<&'a str>, + compile_args: Vec<&'a str>, + exit_code: i32, } fn run_npm_bin_compile_test(opts: RunNpmBinCompileOptions) { @@ -1006,7 +1048,9 @@ fn run_npm_bin_compile_test(opts: RunNpmBinCompileOptions) { .to_string() }; - let mut args = vec!["compile".to_string(), "-A".to_string()]; + let mut args = vec!["compile".to_string()]; + + args.extend(opts.compile_args.iter().map(|s| s.to_string())); if opts.node_modules_dir { args.push("--node-modules-dir".to_string()); @@ -1036,4 +1080,5 @@ fn run_npm_bin_compile_test(opts: RunNpmBinCompileOptions) { .args_vec(opts.run_args) .run(); output.assert_matches_file(opts.output_file); + output.assert_exit_code(opts.exit_code); } diff --git a/cli/tests/testdata/compile/vfs_implicit_read_permission/main.out b/cli/tests/testdata/compile/vfs_implicit_read_permission/main.out new file mode 100644 index 0000000000..17d05159c2 --- /dev/null +++ b/cli/tests/testdata/compile/vfs_implicit_read_permission/main.out @@ -0,0 +1,8 @@ + __________________ +< Hello from Deno! > + ------------------ + \ ^__^ + \ (oo)\_______ + (__)\ )\/\ + ||----w | + || || diff --git a/cli/tests/testdata/compile/vfs_implicit_read_permission/main.ts b/cli/tests/testdata/compile/vfs_implicit_read_permission/main.ts new file mode 100644 index 0000000000..56ad1e095f --- /dev/null +++ b/cli/tests/testdata/compile/vfs_implicit_read_permission/main.ts @@ -0,0 +1,3 @@ +// this will read a file from the package +import { say } from "npm:cowsay@1.5.0"; +console.log(say({ text: "Hello from Deno!" })); diff --git a/cli/tests/testdata/npm/deno_run_cowsay_no_permissions.out b/cli/tests/testdata/npm/deno_run_cowsay_no_permissions.out new file mode 100644 index 0000000000..206ef1484f --- /dev/null +++ b/cli/tests/testdata/npm/deno_run_cowsay_no_permissions.out @@ -0,0 +1,2 @@ +error: Uncaught PermissionDenied: Requires read access to , run again with the --allow-read flag +[WILDCARD] diff --git a/test_util/src/builders.rs b/test_util/src/builders.rs index 33a1a98f01..a000e5bcd3 100644 --- a/test_util/src/builders.rs +++ b/test_util/src/builders.rs @@ -394,7 +394,7 @@ impl TestCommandBuilder { (Some(combined_reader), None) }; - let mut process = command.spawn().unwrap(); + let mut process = command.spawn().expect("Failed spawning command"); if let Some(input) = &self.stdin { let mut p_stdin = process.stdin.take().unwrap();