From 2e7bcb422d593248cfb654ee1b7ffd341c83353c Mon Sep 17 00:00:00 2001 From: David Sherret Date: Wed, 5 Jul 2023 12:43:22 -0400 Subject: [PATCH] fix(vendor): support import mapped jsxImportSource (#19724) Closes #16108 --- cli/args/config_file.rs | 2 +- cli/tools/vendor/build.rs | 52 ++++++++++++++++++++++++++++++++++ cli/tools/vendor/import_map.rs | 17 +++++++++++ cli/tools/vendor/mod.rs | 2 ++ cli/tools/vendor/test.rs | 15 +++++++++- 5 files changed, 86 insertions(+), 2 deletions(-) diff --git a/cli/args/config_file.rs b/cli/args/config_file.rs index 9d1137b273..76b522a41a 100644 --- a/cli/args/config_file.rs +++ b/cli/args/config_file.rs @@ -28,7 +28,7 @@ use std::path::PathBuf; pub type MaybeImportsResult = Result, AnyError>; -#[derive(Hash)] +#[derive(Debug, Clone, Hash)] pub struct JsxImportSourceConfig { pub default_specifier: Option, pub module: String, diff --git a/cli/tools/vendor/build.rs b/cli/tools/vendor/build.rs index 11a1fb50e6..5cd50836f1 100644 --- a/cli/tools/vendor/build.rs +++ b/cli/tools/vendor/build.rs @@ -16,6 +16,7 @@ use deno_graph::ModuleGraph; use import_map::ImportMap; use import_map::SpecifierMap; +use crate::args::JsxImportSourceConfig; use crate::args::Lockfile; use crate::cache::ParsedSourceCache; use crate::graph_util; @@ -63,6 +64,7 @@ pub fn build( output_dir: &Path, original_import_map: Option<&ImportMap>, maybe_lockfile: Option>>, + jsx_import_source: Option<&JsxImportSourceConfig>, environment: &impl VendorEnvironment, ) -> Result { assert!(output_dir.is_absolute()); @@ -134,6 +136,7 @@ pub fn build( &all_modules, &mappings, original_import_map, + jsx_import_source, parsed_source_cache, )?; environment.write_file(&import_map_path, &import_map_text)?; @@ -218,6 +221,7 @@ fn build_proxy_module_source( #[cfg(test)] mod test { + use crate::args::JsxImportSourceConfig; use crate::tools::vendor::test::VendorTestBuilder; use deno_core::serde_json::json; use pretty_assertions::assert_eq; @@ -1147,6 +1151,54 @@ mod test { ); } + #[tokio::test] + async fn existing_import_map_jsx_import_source() { + let mut builder = VendorTestBuilder::default(); + builder.add_entry_point("/mod.tsx"); + builder.set_jsx_import_source_config(JsxImportSourceConfig { + default_specifier: Some("preact".to_string()), + module: "jsx-runtime".to_string(), + }); + let mut original_import_map = builder.new_import_map("/import_map.json"); + let imports = original_import_map.imports_mut(); + imports + .append( + "preact/".to_string(), + "https://localhost/preact/".to_string(), + ) + .unwrap(); + let output = builder + .with_loader(|loader| { + loader.add("/mod.tsx", "const myComponent =
;"); + loader.add_with_headers( + "https://localhost/preact/jsx-runtime", + "export function stuff() {}", + &[("content-type", "application/typescript")], + ); + }) + .set_original_import_map(original_import_map) + .build() + .await + .unwrap(); + + assert_eq!( + output.import_map, + Some(json!({ + "imports": { + "https://localhost/": "./localhost/", + "preact/jsx-runtime": "./localhost/preact/jsx-runtime.ts", + }, + })) + ); + assert_eq!( + output.files, + to_file_vec(&[( + "/vendor/localhost/preact/jsx-runtime.ts", + "export function stuff() {}" + ),]), + ); + } + #[tokio::test] async fn vendor_file_fails_loading_dynamic_import() { let mut builder = VendorTestBuilder::with_default_setup(); diff --git a/cli/tools/vendor/import_map.rs b/cli/tools/vendor/import_map.rs index dbda81a3a0..a23dde8051 100644 --- a/cli/tools/vendor/import_map.rs +++ b/cli/tools/vendor/import_map.rs @@ -14,6 +14,7 @@ use import_map::SpecifierMap; use indexmap::IndexMap; use log::warn; +use crate::args::JsxImportSourceConfig; use crate::cache::ParsedSourceCache; use super::mappings::Mappings; @@ -182,6 +183,7 @@ pub fn build_import_map( modules: &[&Module], mappings: &Mappings, original_import_map: Option<&ImportMap>, + jsx_import_source: Option<&JsxImportSourceConfig>, parsed_source_cache: &ParsedSourceCache, ) -> Result { let mut builder = ImportMapBuilder::new(base_dir, mappings); @@ -193,6 +195,21 @@ pub fn build_import_map( .add(base_specifier.to_string(), base_specifier); } + // add the jsx import source to the destination import map, if mapped in the original import map + if let (Some(import_map), Some(jsx_import_source)) = + (original_import_map, jsx_import_source) + { + if let Some(default_specifier) = &jsx_import_source.default_specifier { + let specifier_text = + format!("{}/{}", default_specifier, jsx_import_source.module); + if let Ok(resolved_url) = + import_map.resolve(&specifier_text, import_map.base_url()) + { + builder.imports.add(specifier_text, &resolved_url); + } + } + } + Ok(builder.into_import_map(original_import_map).to_json()) } diff --git a/cli/tools/vendor/mod.rs b/cli/tools/vendor/mod.rs index 61ada605c5..6a7096d68d 100644 --- a/cli/tools/vendor/mod.rs +++ b/cli/tools/vendor/mod.rs @@ -57,12 +57,14 @@ pub async fn vendor( let npm_package_count = graph.npm_packages.len(); let try_add_node_modules_dir = npm_package_count > 0 && cli_options.node_modules_dir_enablement().unwrap_or(true); + let jsx_import_source = cli_options.to_maybe_jsx_import_source_config(); let vendored_count = build::build( graph, factory.parsed_source_cache()?, &output_dir, factory.maybe_import_map().await?.as_deref(), factory.maybe_lockfile().clone(), + jsx_import_source.as_ref(), &build::RealVendorEnvironment, )?; diff --git a/cli/tools/vendor/test.rs b/cli/tools/vendor/test.rs index 08b6d8355b..4bc6941e29 100644 --- a/cli/tools/vendor/test.rs +++ b/cli/tools/vendor/test.rs @@ -20,6 +20,7 @@ use deno_graph::GraphKind; use deno_graph::ModuleGraph; use import_map::ImportMap; +use crate::args::JsxImportSourceConfig; use crate::cache::ParsedSourceCache; use crate::npm::CliNpmRegistryApi; use crate::npm::NpmResolution; @@ -184,6 +185,7 @@ pub struct VendorTestBuilder { loader: TestLoader, original_import_map: Option, environment: TestVendorEnvironment, + jsx_import_source_config: Option, } impl VendorTestBuilder { @@ -214,6 +216,14 @@ impl VendorTestBuilder { self } + pub fn set_jsx_import_source_config( + &mut self, + jsx_import_source_config: JsxImportSourceConfig, + ) -> &mut Self { + self.jsx_import_source_config = Some(jsx_import_source_config); + self + } + pub async fn build(&mut self) -> Result { let output_dir = make_path("/vendor"); let roots = self.entry_points.clone(); @@ -222,6 +232,7 @@ impl VendorTestBuilder { let analyzer = parsed_source_cache.as_analyzer(); let graph = build_test_graph( roots, + self.jsx_import_source_config.clone(), self.original_import_map.clone(), loader, &*analyzer, @@ -233,6 +244,7 @@ impl VendorTestBuilder { &output_dir, self.original_import_map.as_ref(), None, + self.jsx_import_source_config.as_ref(), &self.environment, )?; @@ -259,6 +271,7 @@ impl VendorTestBuilder { async fn build_test_graph( roots: Vec, + jsx_import_source_config: Option, original_import_map: Option, mut loader: TestLoader, analyzer: &dyn deno_graph::ModuleAnalyzer, @@ -271,7 +284,7 @@ async fn build_test_graph( None, )); CliGraphResolver::new( - None, + jsx_import_source_config, Some(Arc::new(original_import_map)), false, npm_registry_api,