diff --git a/cli/args/config_file.rs b/cli/args/config_file.rs index 1928d02fb4..66b80b9d40 100644 --- a/cli/args/config_file.rs +++ b/cli/args/config_file.rs @@ -1033,20 +1033,37 @@ impl ConfigFile { /// JSX import source configuration. pub fn to_maybe_jsx_import_source_config( &self, - ) -> Option { - let compiler_options_value = self.json.compiler_options.as_ref()?; - let compiler_options: CompilerOptions = - serde_json::from_value(compiler_options_value.clone()).ok()?; - let module = match compiler_options.jsx.as_deref() { - Some("react-jsx") => Some("jsx-runtime".to_string()), - Some("react-jsxdev") => Some("jsx-dev-runtime".to_string()), - _ => None, + ) -> Result, AnyError> { + let Some(compiler_options_value) = self.json.compiler_options.as_ref() else { + return Ok(None); }; - module.map(|module| JsxImportSourceConfig { + let Some(compiler_options) = + serde_json::from_value::(compiler_options_value.clone()).ok() else { + return Ok(None); + }; + let module = match compiler_options.jsx.as_deref() { + Some("react-jsx") => "jsx-runtime".to_string(), + Some("react-jsxdev") => "jsx-dev-runtime".to_string(), + Some("react") | None => { + if compiler_options.jsx_import_source.is_some() { + bail!( + "'jsxImportSource' is only supported when 'jsx' is set to 'react-jsx' or 'react-jsxdev'.\n at {}", + self.specifier, + ); + } + return Ok(None); + } + Some(setting) => bail!( + "Unsupported 'jsx' compiler option value '{}'. Supported: 'react-jsx', 'react-jsxdev', 'react'\n at {}", + setting, + self.specifier, + ), + }; + Ok(Some(JsxImportSourceConfig { default_specifier: compiler_options.jsx_import_source, module, base_url: self.specifier.clone(), - }) + })) } pub fn resolve_tasks_config( @@ -1609,6 +1626,59 @@ mod tests { assert!(ConfigFile::new(config_text, config_specifier).is_err()); } + #[test] + fn test_jsx_invalid_setting() { + let config_text = r#"{ "compilerOptions": { "jsx": "preserve" } }"#; + let config_specifier = + ModuleSpecifier::parse("file:///deno/tsconfig.json").unwrap(); + let config = ConfigFile::new(config_text, config_specifier).unwrap(); + assert_eq!( + config.to_maybe_jsx_import_source_config().err().unwrap().to_string(), + concat!( + "Unsupported 'jsx' compiler option value 'preserve'. Supported: 'react-jsx', 'react-jsxdev', 'react'\n", + " at file:///deno/tsconfig.json", + ), + ); + } + + #[test] + fn test_jsx_import_source_only() { + let config_specifier = + ModuleSpecifier::parse("file:///deno/tsconfig.json").unwrap(); + { + let config_text = + r#"{ "compilerOptions": { "jsxImportSource": "test" } }"#; + let config = + ConfigFile::new(config_text, config_specifier.clone()).unwrap(); + assert_eq!( + config.to_maybe_jsx_import_source_config().err().unwrap().to_string(), + concat!( + "'jsxImportSource' is only supported when 'jsx' is set to 'react-jsx' or 'react-jsxdev'.\n", + " at file:///deno/tsconfig.json", + ), + ); + } + { + let config_text = r#"{ "compilerOptions": { "jsx": "react", "jsxImportSource": "test" } }"#; + let config = ConfigFile::new(config_text, config_specifier).unwrap(); + assert_eq!( + config.to_maybe_jsx_import_source_config().err().unwrap().to_string(), + concat!( + "'jsxImportSource' is only supported when 'jsx' is set to 'react-jsx' or 'react-jsxdev'.\n", + " at file:///deno/tsconfig.json", + ), + ); + } + } + + #[test] + fn test_jsx_import_source_valid() { + let config_text = r#"{ "compilerOptions": { "jsx": "react" } }"#; + let config_specifier = + ModuleSpecifier::parse("file:///deno/tsconfig.json").unwrap(); + assert!(ConfigFile::new(config_text, config_specifier).is_ok()); + } + #[test] fn test_tsconfig_as_bytes() { let mut tsconfig1 = TsConfig::new(json!({ diff --git a/cli/args/mod.rs b/cli/args/mod.rs index a979aa10c6..68cd3faa74 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -914,11 +914,11 @@ impl CliOptions { /// Return the JSX import source configuration. pub fn to_maybe_jsx_import_source_config( &self, - ) -> Option { - self - .maybe_config_file - .as_ref() - .and_then(|c| c.to_maybe_jsx_import_source_config()) + ) -> Result, AnyError> { + match self.maybe_config_file.as_ref() { + Some(config) => config.to_maybe_jsx_import_source_config(), + None => Ok(None), + } } /// Return any imports that should be brought into the scope of the module diff --git a/cli/factory.rs b/cli/factory.rs index 330865744f..28c436e354 100644 --- a/cli/factory.rs +++ b/cli/factory.rs @@ -398,7 +398,7 @@ impl CliFactory { .resolver .get_or_try_init_async(async { Ok(Arc::new(CliGraphResolver::new( - self.options.to_maybe_jsx_import_source_config(), + self.options.to_maybe_jsx_import_source_config()?, self.maybe_import_map().await?.clone(), self.options.no_npm(), self.npm_api()?.clone(), diff --git a/cli/lsp/documents.rs b/cli/lsp/documents.rs index d987279dee..2d3bed57af 100644 --- a/cli/lsp/documents.rs +++ b/cli/lsp/documents.rs @@ -1219,7 +1219,7 @@ impl Documents { }); let maybe_jsx_config = options .maybe_config_file - .and_then(|cf| cf.to_maybe_jsx_import_source_config()); + .and_then(|cf| cf.to_maybe_jsx_import_source_config().ok().flatten()); let new_resolver_config_hash = calculate_resolver_config_hash( &options.enabled_urls, options.document_preload_limit, diff --git a/cli/tools/vendor/mod.rs b/cli/tools/vendor/mod.rs index 49a984c875..fdea5fc26d 100644 --- a/cli/tools/vendor/mod.rs +++ b/cli/tools/vendor/mod.rs @@ -50,7 +50,7 @@ pub async fn vendor( let cli_options = factory.cli_options(); let entry_points = resolve_entry_points(&vendor_flags, cli_options.initial_cwd())?; - let jsx_import_source = cli_options.to_maybe_jsx_import_source_config(); + let jsx_import_source = cli_options.to_maybe_jsx_import_source_config()?; let module_graph_builder = factory.module_graph_builder().await?.clone(); let output = build::build(build::BuildInput { entry_points,