diff --git a/cli/graph_container.rs b/cli/graph_container.rs index 1fe30b47ab..78d589e86d 100644 --- a/cli/graph_container.rs +++ b/cli/graph_container.rs @@ -13,6 +13,7 @@ use deno_runtime::deno_permissions::PermissionsContainer; use crate::args::CliOptions; use crate::module_loader::ModuleLoadPreparer; +use crate::module_loader::PrepareModuleLoadOptions; use crate::util::fs::collect_specifiers; use crate::util::path::is_script_ext; @@ -48,6 +49,12 @@ pub struct MainModuleGraphContainer { root_permissions: PermissionsContainer, } +#[derive(Default, Debug)] +pub struct CheckSpecifiersOptions<'a> { + pub ext_overwrite: Option<&'a String>, + pub allow_unknown_media_types: bool, +} + impl MainModuleGraphContainer { pub fn new( cli_options: Arc, @@ -68,7 +75,7 @@ impl MainModuleGraphContainer { pub async fn check_specifiers( &self, specifiers: &[ModuleSpecifier], - ext_overwrite: Option<&String>, + options: CheckSpecifiersOptions<'_>, ) -> Result<(), AnyError> { let mut graph_permit = self.acquire_update_permit().await; let graph = graph_permit.graph_mut(); @@ -77,10 +84,13 @@ impl MainModuleGraphContainer { .prepare_module_load( graph, specifiers, - false, - self.cli_options.ts_type_lib_window(), - self.root_permissions.clone(), - ext_overwrite, + PrepareModuleLoadOptions { + is_dynamic: false, + lib: self.cli_options.ts_type_lib_window(), + permissions: self.root_permissions.clone(), + ext_overwrite: options.ext_overwrite, + allow_unknown_media_types: options.allow_unknown_media_types, + }, ) .await?; graph_permit.commit(); @@ -99,7 +109,7 @@ impl MainModuleGraphContainer { log::warn!("{} No matching files found.", colors::yellow("Warning")); } - self.check_specifiers(&specifiers, None).await + self.check_specifiers(&specifiers, Default::default()).await } pub fn collect_specifiers( diff --git a/cli/graph_util.rs b/cli/graph_util.rs index 1f6a9044b6..506bb371a7 100644 --- a/cli/graph_util.rs +++ b/cli/graph_util.rs @@ -78,6 +78,7 @@ pub struct GraphValidOptions<'a> { /// lockfile checksum mismatches and JSR integrity failures. /// Otherwise, surfaces integrity errors as errors. pub exit_integrity_errors: bool, + pub allow_unknown_media_types: bool, } /// Check if `roots` and their deps are available. Returns `Ok(())` if @@ -104,6 +105,7 @@ pub fn graph_valid( GraphWalkErrorsOptions { check_js: options.check_js, kind: options.kind, + allow_unknown_media_types: options.allow_unknown_media_types, }, ); if let Some(error) = errors.next() { @@ -143,6 +145,7 @@ pub fn fill_graph_from_lockfile( pub struct GraphWalkErrorsOptions<'a> { pub check_js: CheckJsOption<'a>, pub kind: GraphKind, + pub allow_unknown_media_types: bool, } /// Walks the errors found in the module graph that should be surfaced to users @@ -156,9 +159,10 @@ pub fn graph_walk_errors<'a>( fn should_ignore_error( sys: &CliSys, graph_kind: GraphKind, + allow_unknown_media_types: bool, error: &ModuleGraphError, ) -> bool { - if graph_kind == GraphKind::TypesOnly + if (graph_kind == GraphKind::TypesOnly || allow_unknown_media_types) && matches!( error, ModuleGraphError::ModuleError(ModuleError::UnsupportedMediaType(..)) @@ -183,8 +187,13 @@ pub fn graph_walk_errors<'a>( }, ) .errors() - .flat_map(|error| { - if should_ignore_error(sys, graph.graph_kind(), &error) { + .flat_map(move |error| { + if should_ignore_error( + sys, + graph.graph_kind(), + options.allow_unknown_media_types, + &error, + ) { log::debug!("Ignoring: {}", error); return None; } @@ -931,6 +940,7 @@ impl ModuleGraphBuilder { self.graph_roots_valid( graph, &graph.roots.iter().cloned().collect::>(), + false, ) } @@ -938,6 +948,7 @@ impl ModuleGraphBuilder { &self, graph: &ModuleGraph, roots: &[ModuleSpecifier], + allow_unknown_media_types: bool, ) -> Result<(), JsErrorBox> { graph_valid( graph, @@ -951,6 +962,7 @@ impl ModuleGraphBuilder { }, check_js: CheckJsOption::Custom(self.tsconfig_resolver.as_ref()), exit_integrity_errors: true, + allow_unknown_media_types, }, ) } diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index 9d253c250f..2785447ceb 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -280,6 +280,7 @@ impl LanguageServer { kind: GraphKind::All, check_js: CheckJsOption::False, exit_integrity_errors: false, + allow_unknown_media_types: true, }, )?; diff --git a/cli/lsp/testing/execution.rs b/cli/lsp/testing/execution.rs index 3d6d6f6b73..c36b34599f 100644 --- a/cli/lsp/testing/execution.rs +++ b/cli/lsp/testing/execution.rs @@ -235,7 +235,10 @@ impl TestRun { )?; let main_graph_container = factory.main_module_graph_container().await?; main_graph_container - .check_specifiers(&self.queue.iter().cloned().collect::>(), None) + .check_specifiers( + &self.queue.iter().cloned().collect::>(), + Default::default(), + ) .await?; let (concurrent_jobs, fail_fast) = diff --git a/cli/module_loader.rs b/cli/module_loader.rs index fda17d6b5e..e49ac14959 100644 --- a/cli/module_loader.rs +++ b/cli/module_loader.rs @@ -124,6 +124,14 @@ pub struct ModuleLoadPreparer { type_checker: Arc, } +pub struct PrepareModuleLoadOptions<'a> { + pub is_dynamic: bool, + pub lib: TsTypeLib, + pub permissions: PermissionsContainer, + pub ext_overwrite: Option<&'a String>, + pub allow_unknown_media_types: bool, +} + impl ModuleLoadPreparer { #[allow(clippy::too_many_arguments)] pub fn new( @@ -146,17 +154,20 @@ impl ModuleLoadPreparer { /// module before attempting to `load()` it from a `JsRuntime`. It will /// populate the graph data in memory with the necessary source code, write /// emits where necessary or report any module graph / type checking errors. - #[allow(clippy::too_many_arguments)] pub async fn prepare_module_load( &self, graph: &mut ModuleGraph, roots: &[ModuleSpecifier], - is_dynamic: bool, - lib: TsTypeLib, - permissions: PermissionsContainer, - ext_overwrite: Option<&String>, + options: PrepareModuleLoadOptions<'_>, ) -> Result<(), PrepareModuleLoadError> { log::debug!("Preparing module load."); + let PrepareModuleLoadOptions { + is_dynamic, + lib, + permissions, + ext_overwrite, + allow_unknown_media_types, + } = options; let _pb_clear_guard = self.progress_bar.clear_guard(); let mut cache = self.module_graph_builder.create_fetch_cacher(permissions); @@ -197,7 +208,7 @@ impl ModuleLoadPreparer { ) .await?; - self.graph_roots_valid(graph, roots)?; + self.graph_roots_valid(graph, roots, allow_unknown_media_types)?; // write the lockfile if there is one if let Some(lockfile) = &self.lockfile { @@ -235,8 +246,13 @@ impl ModuleLoadPreparer { &self, graph: &ModuleGraph, roots: &[ModuleSpecifier], + allow_unknown_media_types: bool, ) -> Result<(), JsErrorBox> { - self.module_graph_builder.graph_roots_valid(graph, roots) + self.module_graph_builder.graph_roots_valid( + graph, + roots, + allow_unknown_media_types, + ) } } @@ -1067,7 +1083,11 @@ impl ModuleLoader log::debug!("Skipping prepare module load."); // roots are already validated so we can skip those if !graph.roots.contains(&specifier) { - module_load_preparer.graph_roots_valid(&graph, &[specifier])?; + module_load_preparer.graph_roots_valid( + &graph, + &[specifier], + false, + )?; } return Ok(()); } @@ -1086,10 +1106,13 @@ impl ModuleLoader .prepare_module_load( graph, &[specifier], - is_dynamic, - lib, - permissions, - None, + PrepareModuleLoadOptions { + is_dynamic, + lib, + permissions, + ext_overwrite: None, + allow_unknown_media_types: false, + }, ) .await .map_err(JsErrorBox::from_err)?; diff --git a/cli/tools/bench/mod.rs b/cli/tools/bench/mod.rs index 0d8fb4750f..91030a61c0 100644 --- a/cli/tools/bench/mod.rs +++ b/cli/tools/bench/mod.rs @@ -38,6 +38,7 @@ use crate::args::Flags; use crate::colors; use crate::display::write_json_to_stdout; use crate::factory::CliFactory; +use crate::graph_container::CheckSpecifiersOptions; use crate::graph_util::has_graph_root_local_dependent_changed; use crate::ops; use crate::sys::CliSys; @@ -462,7 +463,13 @@ pub async fn run_benchmarks( let main_graph_container = factory.main_module_graph_container().await?; main_graph_container - .check_specifiers(&specifiers, cli_options.ext_flag().as_ref()) + .check_specifiers( + &specifiers, + CheckSpecifiersOptions { + ext_overwrite: cli_options.ext_flag().as_ref(), + ..Default::default() + }, + ) .await?; if workspace_bench_options.no_run { @@ -595,7 +602,13 @@ pub async fn run_benchmarks_with_watch( factory .main_module_graph_container() .await? - .check_specifiers(&specifiers, cli_options.ext_flag().as_ref()) + .check_specifiers( + &specifiers, + CheckSpecifiersOptions { + ext_overwrite: cli_options.ext_flag().as_ref(), + allow_unknown_media_types: false, + }, + ) .await?; if workspace_bench_options.no_run { diff --git a/cli/tools/check.rs b/cli/tools/check.rs index 1a5bcb8cca..1d21b1feb0 100644 --- a/cli/tools/check.rs +++ b/cli/tools/check.rs @@ -89,7 +89,7 @@ pub async fn check( }; main_graph_container - .check_specifiers(&specifiers_for_typecheck, None) + .check_specifiers(&specifiers_for_typecheck, Default::default()) .await } diff --git a/cli/tools/doc.rs b/cli/tools/doc.rs index ef45d08191..26b4af4a7f 100644 --- a/cli/tools/doc.rs +++ b/cli/tools/doc.rs @@ -151,6 +151,7 @@ pub async fn doc( GraphWalkErrorsOptions { check_js: CheckJsOption::False, kind: GraphKind::TypesOnly, + allow_unknown_media_types: false, }, ); for error in errors { diff --git a/cli/tools/installer.rs b/cli/tools/installer.rs index e4c7c66dda..e0f9917f28 100644 --- a/cli/tools/installer.rs +++ b/cli/tools/installer.rs @@ -279,8 +279,15 @@ pub(crate) async fn install_from_entrypoints( let factory = CliFactory::from_flags(flags.clone()); let emitter = factory.emitter()?; let main_graph_container = factory.main_module_graph_container().await?; + let specifiers = main_graph_container.collect_specifiers(entrypoints)?; main_graph_container - .load_and_type_check_files(entrypoints) + .check_specifiers( + &specifiers, + crate::graph_container::CheckSpecifiersOptions { + ext_overwrite: None, + allow_unknown_media_types: true, + }, + ) .await?; emitter .cache_module_emits(&main_graph_container.graph()) diff --git a/cli/tools/registry/pm/cache_deps.rs b/cli/tools/registry/pm/cache_deps.rs index 312d1af562..a2317cf498 100644 --- a/cli/tools/registry/pm/cache_deps.rs +++ b/cli/tools/registry/pm/cache_deps.rs @@ -136,7 +136,7 @@ pub async fn cache_top_level_deps( }, ) .await?; - maybe_graph_error = graph_builder.graph_roots_valid(graph, &roots); + maybe_graph_error = graph_builder.graph_roots_valid(graph, &roots, true); } npm_installer.cache_packages(PackageCaching::All).await?; diff --git a/cli/tools/registry/pm/deps.rs b/cli/tools/registry/pm/deps.rs index 849e72d3ec..6bbe949d0b 100644 --- a/cli/tools/registry/pm/deps.rs +++ b/cli/tools/registry/pm/deps.rs @@ -614,10 +614,13 @@ impl DepManager { .prepare_module_load( graph, &roots, - false, - deno_config::deno_json::TsTypeLib::DenoWindow, - self.permissions_container.clone(), - None, + crate::module_loader::PrepareModuleLoadOptions { + is_dynamic: false, + lib: deno_config::deno_json::TsTypeLib::DenoWindow, + permissions: self.permissions_container.clone(), + ext_overwrite: None, + allow_unknown_media_types: true, + }, ) .await?; diff --git a/cli/tools/test/mod.rs b/cli/tools/test/mod.rs index c3b9d5edc0..8f687e2f51 100644 --- a/cli/tools/test/mod.rs +++ b/cli/tools/test/mod.rs @@ -77,6 +77,7 @@ use crate::colors; use crate::display; use crate::factory::CliFactory; use crate::file_fetcher::CliFileFetcher; +use crate::graph_container::CheckSpecifiersOptions; use crate::graph_util::has_graph_root_local_dependent_changed; use crate::ops; use crate::sys::CliSys; @@ -1604,7 +1605,10 @@ pub async fn run_tests( main_graph_container .check_specifiers( &specifiers_for_typecheck_and_test, - cli_options.ext_flag().as_ref(), + CheckSpecifiersOptions { + ext_overwrite: cli_options.ext_flag().as_ref(), + ..Default::default() + }, ) .await?; @@ -1787,7 +1791,10 @@ pub async fn run_tests_with_watch( main_graph_container .check_specifiers( &specifiers_for_typecheck_and_test, - cli_options.ext_flag().as_ref(), + crate::graph_container::CheckSpecifiersOptions { + ext_overwrite: cli_options.ext_flag().as_ref(), + ..Default::default() + }, ) .await?; diff --git a/tests/specs/install/unknown_media_type/__test__.jsonc b/tests/specs/install/unknown_media_type/__test__.jsonc new file mode 100644 index 0000000000..cbbc7cc2e1 --- /dev/null +++ b/tests/specs/install/unknown_media_type/__test__.jsonc @@ -0,0 +1,9 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "install", + "output": "" + } + ] +} diff --git a/tests/specs/install/unknown_media_type/deno.json b/tests/specs/install/unknown_media_type/deno.json new file mode 100644 index 0000000000..e87d16e45d --- /dev/null +++ b/tests/specs/install/unknown_media_type/deno.json @@ -0,0 +1,5 @@ +{ + "imports": { + "foo": "./foo.ts" + } +} diff --git a/tests/specs/install/unknown_media_type/foo.ts b/tests/specs/install/unknown_media_type/foo.ts new file mode 100644 index 0000000000..bef3218578 --- /dev/null +++ b/tests/specs/install/unknown_media_type/foo.ts @@ -0,0 +1 @@ +import styles from "./styles.css"; diff --git a/tests/specs/install/unknown_media_type/styles.css b/tests/specs/install/unknown_media_type/styles.css new file mode 100644 index 0000000000..e69de29bb2