mirror of
https://github.com/denoland/deno.git
synced 2024-12-25 00:29:09 -05:00
feat(cli): don't check permissions for statically analyzable dynamic imports (#18713)
Closes #17697 Closes #17658
This commit is contained in:
parent
c2f5c09692
commit
3d8a4d3b81
16 changed files with 40 additions and 52 deletions
17
cli/cache/mod.rs
vendored
17
cli/cache/mod.rs
vendored
|
@ -45,10 +45,9 @@ pub const CACHE_PERM: u32 = 0o644;
|
||||||
/// a concise interface to the DENO_DIR when building module graphs.
|
/// a concise interface to the DENO_DIR when building module graphs.
|
||||||
pub struct FetchCacher {
|
pub struct FetchCacher {
|
||||||
emit_cache: EmitCache,
|
emit_cache: EmitCache,
|
||||||
dynamic_permissions: PermissionsContainer,
|
|
||||||
file_fetcher: Arc<FileFetcher>,
|
file_fetcher: Arc<FileFetcher>,
|
||||||
file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>,
|
file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>,
|
||||||
root_permissions: PermissionsContainer,
|
permissions: PermissionsContainer,
|
||||||
cache_info_enabled: bool,
|
cache_info_enabled: bool,
|
||||||
maybe_local_node_modules_url: Option<ModuleSpecifier>,
|
maybe_local_node_modules_url: Option<ModuleSpecifier>,
|
||||||
}
|
}
|
||||||
|
@ -58,16 +57,14 @@ impl FetchCacher {
|
||||||
emit_cache: EmitCache,
|
emit_cache: EmitCache,
|
||||||
file_fetcher: Arc<FileFetcher>,
|
file_fetcher: Arc<FileFetcher>,
|
||||||
file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>,
|
file_header_overrides: HashMap<ModuleSpecifier, HashMap<String, String>>,
|
||||||
root_permissions: PermissionsContainer,
|
permissions: PermissionsContainer,
|
||||||
dynamic_permissions: PermissionsContainer,
|
|
||||||
maybe_local_node_modules_url: Option<ModuleSpecifier>,
|
maybe_local_node_modules_url: Option<ModuleSpecifier>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
emit_cache,
|
emit_cache,
|
||||||
dynamic_permissions,
|
|
||||||
file_fetcher,
|
file_fetcher,
|
||||||
file_header_overrides,
|
file_header_overrides,
|
||||||
root_permissions,
|
permissions,
|
||||||
cache_info_enabled: false,
|
cache_info_enabled: false,
|
||||||
maybe_local_node_modules_url,
|
maybe_local_node_modules_url,
|
||||||
}
|
}
|
||||||
|
@ -105,7 +102,7 @@ impl Loader for FetchCacher {
|
||||||
fn load(
|
fn load(
|
||||||
&mut self,
|
&mut self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
is_dynamic: bool,
|
_is_dynamic: bool,
|
||||||
) -> LoadFuture {
|
) -> LoadFuture {
|
||||||
if let Some(node_modules_url) = self.maybe_local_node_modules_url.as_ref() {
|
if let Some(node_modules_url) = self.maybe_local_node_modules_url.as_ref() {
|
||||||
// The specifier might be in a completely different symlinked tree than
|
// The specifier might be in a completely different symlinked tree than
|
||||||
|
@ -124,11 +121,7 @@ impl Loader for FetchCacher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let permissions = if is_dynamic {
|
let permissions = self.permissions.clone();
|
||||||
self.dynamic_permissions.clone()
|
|
||||||
} else {
|
|
||||||
self.root_permissions.clone()
|
|
||||||
};
|
|
||||||
let file_fetcher = self.file_fetcher.clone();
|
let file_fetcher = self.file_fetcher.clone();
|
||||||
let file_header_overrides = self.file_header_overrides.clone();
|
let file_header_overrides = self.file_header_overrides.clone();
|
||||||
let specifier = specifier.clone();
|
let specifier = specifier.clone();
|
||||||
|
|
|
@ -314,23 +314,18 @@ impl ModuleGraphBuilder {
|
||||||
|
|
||||||
/// Creates the default loader used for creating a graph.
|
/// Creates the default loader used for creating a graph.
|
||||||
pub fn create_graph_loader(&self) -> cache::FetchCacher {
|
pub fn create_graph_loader(&self) -> cache::FetchCacher {
|
||||||
self.create_fetch_cacher(
|
self.create_fetch_cacher(PermissionsContainer::allow_all())
|
||||||
PermissionsContainer::allow_all(),
|
|
||||||
PermissionsContainer::allow_all(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_fetch_cacher(
|
pub fn create_fetch_cacher(
|
||||||
&self,
|
&self,
|
||||||
root_permissions: PermissionsContainer,
|
permissions: PermissionsContainer,
|
||||||
dynamic_permissions: PermissionsContainer,
|
|
||||||
) -> cache::FetchCacher {
|
) -> cache::FetchCacher {
|
||||||
cache::FetchCacher::new(
|
cache::FetchCacher::new(
|
||||||
self.emit_cache.clone(),
|
self.emit_cache.clone(),
|
||||||
self.file_fetcher.clone(),
|
self.file_fetcher.clone(),
|
||||||
self.options.resolve_file_header_overrides(),
|
self.options.resolve_file_header_overrides(),
|
||||||
root_permissions,
|
permissions,
|
||||||
dynamic_permissions,
|
|
||||||
self.options.node_modules_dir_specifier(),
|
self.options.node_modules_dir_specifier(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,7 +226,6 @@ impl TestRun {
|
||||||
Permissions::from_options(&ps.options.permissions_options())?;
|
Permissions::from_options(&ps.options.permissions_options())?;
|
||||||
test::check_specifiers(
|
test::check_specifiers(
|
||||||
&ps,
|
&ps,
|
||||||
permissions.clone(),
|
|
||||||
self
|
self
|
||||||
.queue
|
.queue
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -109,15 +109,12 @@ impl ModuleLoadPreparer {
|
||||||
roots: Vec<ModuleSpecifier>,
|
roots: Vec<ModuleSpecifier>,
|
||||||
is_dynamic: bool,
|
is_dynamic: bool,
|
||||||
lib: TsTypeLib,
|
lib: TsTypeLib,
|
||||||
root_permissions: PermissionsContainer,
|
permissions: PermissionsContainer,
|
||||||
dynamic_permissions: PermissionsContainer,
|
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
log::debug!("Preparing module load.");
|
log::debug!("Preparing module load.");
|
||||||
let _pb_clear_guard = self.progress_bar.clear_guard();
|
let _pb_clear_guard = self.progress_bar.clear_guard();
|
||||||
|
|
||||||
let mut cache = self
|
let mut cache = self.module_graph_builder.create_fetch_cacher(permissions);
|
||||||
.module_graph_builder
|
|
||||||
.create_fetch_cacher(root_permissions, dynamic_permissions);
|
|
||||||
let maybe_imports = self.options.to_maybe_imports()?;
|
let maybe_imports = self.options.to_maybe_imports()?;
|
||||||
let graph_resolver = self.resolver.as_graph_resolver();
|
let graph_resolver = self.resolver.as_graph_resolver();
|
||||||
let graph_npm_resolver = self.resolver.as_graph_npm_resolver();
|
let graph_npm_resolver = self.resolver.as_graph_npm_resolver();
|
||||||
|
@ -216,7 +213,6 @@ impl ModuleLoadPreparer {
|
||||||
false,
|
false,
|
||||||
lib,
|
lib,
|
||||||
PermissionsContainer::allow_all(),
|
PermissionsContainer::allow_all(),
|
||||||
PermissionsContainer::allow_all(),
|
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -537,7 +533,6 @@ impl ModuleLoader for CliModuleLoader {
|
||||||
let specifier = specifier.clone();
|
let specifier = specifier.clone();
|
||||||
let module_load_preparer = self.module_load_preparer.clone();
|
let module_load_preparer = self.module_load_preparer.clone();
|
||||||
|
|
||||||
let dynamic_permissions = self.dynamic_permissions.clone();
|
|
||||||
let root_permissions = if is_dynamic {
|
let root_permissions = if is_dynamic {
|
||||||
self.dynamic_permissions.clone()
|
self.dynamic_permissions.clone()
|
||||||
} else {
|
} else {
|
||||||
|
@ -547,13 +542,7 @@ impl ModuleLoader for CliModuleLoader {
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
module_load_preparer
|
module_load_preparer
|
||||||
.prepare_module_load(
|
.prepare_module_load(vec![specifier], is_dynamic, lib, root_permissions)
|
||||||
vec![specifier],
|
|
||||||
is_dynamic,
|
|
||||||
lib,
|
|
||||||
root_permissions,
|
|
||||||
dynamic_permissions,
|
|
||||||
)
|
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
.boxed_local()
|
.boxed_local()
|
||||||
|
|
|
@ -2661,6 +2661,11 @@ mod permissions {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
itest!(dynamic_import_static_analysis_no_permissions {
|
||||||
|
args: "run --quiet --reload --no-prompt dynamic_import/static_analysis_no_permissions.ts",
|
||||||
|
output: "dynamic_import/static_analysis_no_permissions.ts.out",
|
||||||
|
});
|
||||||
|
|
||||||
itest!(dynamic_import_permissions_remote_remote {
|
itest!(dynamic_import_permissions_remote_remote {
|
||||||
args: "run --quiet --reload --allow-net=localhost:4545 dynamic_import/permissions_remote_remote.ts",
|
args: "run --quiet --reload --allow-net=localhost:4545 dynamic_import/permissions_remote_remote.ts",
|
||||||
output: "dynamic_import/permissions_remote_remote.ts.out",
|
output: "dynamic_import/permissions_remote_remote.ts.out",
|
||||||
|
|
0
cli/tests/testdata/dynamic_import/empty_1.ts
vendored
Normal file
0
cli/tests/testdata/dynamic_import/empty_1.ts
vendored
Normal file
0
cli/tests/testdata/dynamic_import/empty_2.ts
vendored
Normal file
0
cli/tests/testdata/dynamic_import/empty_2.ts
vendored
Normal file
|
@ -1,3 +1,3 @@
|
||||||
await import(
|
await import(
|
||||||
"http://localhost:4545/dynamic_import/static_remote.ts"
|
"" + "http://localhost:4545/dynamic_import/static_remote.ts"
|
||||||
);
|
);
|
||||||
|
|
13
cli/tests/testdata/dynamic_import/static_analysis_no_permissions.ts
vendored
Normal file
13
cli/tests/testdata/dynamic_import/static_analysis_no_permissions.ts
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
try {
|
||||||
|
await import("./empty_1.ts");
|
||||||
|
console.log("✅ Succeeded importing statically analyzable specifier");
|
||||||
|
} catch {
|
||||||
|
console.log("❌ Failed importing statically analyzable specifier");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await import("" + "./empty_2.ts");
|
||||||
|
console.log("❌ Succeeded importing non-statically analyzable specifier");
|
||||||
|
} catch {
|
||||||
|
console.log("✅ Failed importing non-statically analyzable specifier");
|
||||||
|
}
|
2
cli/tests/testdata/dynamic_import/static_analysis_no_permissions.ts.out
vendored
Normal file
2
cli/tests/testdata/dynamic_import/static_analysis_no_permissions.ts.out
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
✅ Succeeded importing statically analyzable specifier
|
||||||
|
✅ Failed importing non-statically analyzable specifier
|
|
@ -1,3 +1,3 @@
|
||||||
(async () => {
|
(async () => {
|
||||||
await import("http://localhost:4545/subdir/mod4.js");
|
await import("" + "http://localhost:4545/subdir/mod4.js");
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Uncaught (in promise) TypeError: Requires net access to "localhost:4545", run again with the --allow-net flag
|
error: Uncaught (in promise) TypeError: Requires net access to "localhost:4545", run again with the --allow-net flag
|
||||||
await import("http://localhost:4545/subdir/mod4.js");
|
await import("" + "http://localhost:4545/subdir/mod4.js");
|
||||||
^
|
^
|
||||||
at async file://[WILDCARD]/error_015_dynamic_import_permissions.js:2:3
|
at async file://[WILDCARD]/error_015_dynamic_import_permissions.js:2:3
|
||||||
|
|
2
cli/tests/testdata/workers/dynamic_remote.ts
vendored
2
cli/tests/testdata/workers/dynamic_remote.ts
vendored
|
@ -1,2 +1,2 @@
|
||||||
// This file doesn't really exist, but it doesn't matter, a "PermissionsDenied" error should be thrown.
|
// This file doesn't really exist, but it doesn't matter, a "PermissionsDenied" error should be thrown.
|
||||||
await import("https://example.com/some/file.ts");
|
await import("" + "https://example.com/some/file.ts");
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: Uncaught (in worker "") (in promise) TypeError: Requires net access to "example.com", run again with the --allow-net flag
|
error: Uncaught (in worker "") (in promise) TypeError: Requires net access to "example.com", run again with the --allow-net flag
|
||||||
await import("https://example.com/some/file.ts");
|
await import("" + "https://example.com/some/file.ts");
|
||||||
^
|
^
|
||||||
at async http://localhost:4545/workers/dynamic_remote.ts:2:1
|
at async http://localhost:4545/workers/dynamic_remote.ts:2:1
|
||||||
[WILDCARD]error: Uncaught (in promise) Error: Unhandled error in child worker.
|
[WILDCARD]error: Uncaught (in promise) Error: Unhandled error in child worker.
|
||||||
|
|
|
@ -418,7 +418,6 @@ impl BenchReporter for ConsoleReporter {
|
||||||
/// Type check a collection of module and document specifiers.
|
/// Type check a collection of module and document specifiers.
|
||||||
async fn check_specifiers(
|
async fn check_specifiers(
|
||||||
ps: &ProcState,
|
ps: &ProcState,
|
||||||
permissions: Permissions,
|
|
||||||
specifiers: Vec<ModuleSpecifier>,
|
specifiers: Vec<ModuleSpecifier>,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
let lib = ps.options.ts_type_lib_window();
|
let lib = ps.options.ts_type_lib_window();
|
||||||
|
@ -428,10 +427,8 @@ async fn check_specifiers(
|
||||||
false,
|
false,
|
||||||
lib,
|
lib,
|
||||||
PermissionsContainer::allow_all(),
|
PermissionsContainer::allow_all(),
|
||||||
PermissionsContainer::new(permissions),
|
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -654,7 +651,7 @@ pub async fn run_benchmarks(
|
||||||
return Err(generic_error("No bench modules found"));
|
return Err(generic_error("No bench modules found"));
|
||||||
}
|
}
|
||||||
|
|
||||||
check_specifiers(&ps, permissions.clone(), specifiers.clone()).await?;
|
check_specifiers(&ps, specifiers.clone()).await?;
|
||||||
|
|
||||||
if bench_options.no_run {
|
if bench_options.no_run {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -813,7 +810,7 @@ pub async fn run_benchmarks_with_watch(
|
||||||
.filter(|specifier| modules_to_reload.contains(specifier))
|
.filter(|specifier| modules_to_reload.contains(specifier))
|
||||||
.collect::<Vec<ModuleSpecifier>>();
|
.collect::<Vec<ModuleSpecifier>>();
|
||||||
|
|
||||||
check_specifiers(&ps, permissions.clone(), specifiers.clone()).await?;
|
check_specifiers(&ps, specifiers.clone()).await?;
|
||||||
|
|
||||||
if bench_options.no_run {
|
if bench_options.no_run {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
|
@ -1230,7 +1230,6 @@ async fn fetch_inline_files(
|
||||||
/// Type check a collection of module and document specifiers.
|
/// Type check a collection of module and document specifiers.
|
||||||
pub async fn check_specifiers(
|
pub async fn check_specifiers(
|
||||||
ps: &ProcState,
|
ps: &ProcState,
|
||||||
permissions: Permissions,
|
|
||||||
specifiers: Vec<(ModuleSpecifier, TestMode)>,
|
specifiers: Vec<(ModuleSpecifier, TestMode)>,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
let lib = ps.options.ts_type_lib_window();
|
let lib = ps.options.ts_type_lib_window();
|
||||||
|
@ -1265,7 +1264,6 @@ pub async fn check_specifiers(
|
||||||
false,
|
false,
|
||||||
lib,
|
lib,
|
||||||
PermissionsContainer::new(Permissions::allow_all()),
|
PermissionsContainer::new(Permissions::allow_all()),
|
||||||
PermissionsContainer::new(permissions.clone()),
|
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
@ -1287,7 +1285,6 @@ pub async fn check_specifiers(
|
||||||
false,
|
false,
|
||||||
lib,
|
lib,
|
||||||
PermissionsContainer::allow_all(),
|
PermissionsContainer::allow_all(),
|
||||||
PermissionsContainer::new(permissions),
|
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
@ -1648,8 +1645,7 @@ pub async fn run_tests(
|
||||||
return Err(generic_error("No test modules found"));
|
return Err(generic_error("No test modules found"));
|
||||||
}
|
}
|
||||||
|
|
||||||
check_specifiers(&ps, permissions.clone(), specifiers_with_mode.clone())
|
check_specifiers(&ps, specifiers_with_mode.clone()).await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
if test_options.no_run {
|
if test_options.no_run {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -1821,8 +1817,7 @@ pub async fn run_tests_with_watch(
|
||||||
.filter(|(specifier, _)| modules_to_reload.contains(specifier))
|
.filter(|(specifier, _)| modules_to_reload.contains(specifier))
|
||||||
.collect::<Vec<(ModuleSpecifier, TestMode)>>();
|
.collect::<Vec<(ModuleSpecifier, TestMode)>>();
|
||||||
|
|
||||||
check_specifiers(&ps, permissions.clone(), specifiers_with_mode.clone())
|
check_specifiers(&ps, specifiers_with_mode.clone()).await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
if test_options.no_run {
|
if test_options.no_run {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
Loading…
Reference in a new issue