From 57c439d64a58053b262ec5dece477712facac0ee Mon Sep 17 00:00:00 2001 From: David Sherret Date: Mon, 16 Oct 2023 15:35:55 +0900 Subject: [PATCH 1/4] fix(resolver): resolution with ResolutionMode::Types should be attempted --- src/graph.rs | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/graph.rs b/src/graph.rs index 64e0cedf4..d571a267e 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -475,6 +475,14 @@ impl Resolution { self.ok().map(|r| &r.specifier) } + pub fn maybe_range(&self) -> Option<&Range> { + match self { + Resolution::None => None, + Resolution::Ok(r) => Some(&r.range), + Resolution::Err(e) => Some(e.range()), + } + } + pub fn ok(&self) -> Option<&ResolutionResolved> { if let Resolution::Ok(resolved) = self { Some(&**resolved) @@ -2054,7 +2062,30 @@ pub(crate) fn parse_esm_module_from_module_info( maybe_npm_resolver, ) } else { - Resolution::None + let range = Range::from_position_range( + module.specifier.clone(), + desc.specifier_range.clone(), + ); + // only check if the code resolution is for the same range + if Some(&range) == dep.maybe_code.maybe_range() { + let types_resolution = resolve( + &desc.specifier, + range, + ResolutionMode::Types, + maybe_resolver, + maybe_npm_resolver, + ); + // only use if the resolved specifier is different + if types_resolution.maybe_specifier() + != dep.maybe_code.maybe_specifier() + { + types_resolution + } else { + Resolution::None + } + } else { + Resolution::None + } }; dep.maybe_type = maybe_type } From f49849231fd3c6815d990e37d4820b36fae7a072 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Mon, 16 Oct 2023 15:45:29 +0900 Subject: [PATCH 2/4] Update comment --- src/graph.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/graph.rs b/src/graph.rs index d571a267e..74ebf5f2d 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -2075,7 +2075,8 @@ pub(crate) fn parse_esm_module_from_module_info( maybe_resolver, maybe_npm_resolver, ); - // only use if the resolved specifier is different + // only bother setting if the resolved specifier + // does not match the code specifier if types_resolution.maybe_specifier() != dep.maybe_code.maybe_specifier() { From 9b18e2caa3d8c3b9e5b67070b428cc8bff268adb Mon Sep 17 00:00:00 2001 From: David Sherret Date: Mon, 16 Oct 2023 15:56:18 +0900 Subject: [PATCH 3/4] Add test --- src/lib.rs | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 174c91d56..317d0a543 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3647,4 +3647,131 @@ export function a(a: A): B { assert!(iterator.next().is_none()); } } + + #[tokio::test] + async fn test_resolver_execution_and_types_resolution() { + #[derive(Debug)] + struct ExtResolver; + + impl crate::source::Resolver for ExtResolver { + fn resolve( + &self, + specifier_text: &str, + referrer: &ModuleSpecifier, + mode: ResolutionMode, + ) -> Result { + let specifier_text = match mode { + ResolutionMode::Types => format!("{}.d.ts", specifier_text), + ResolutionMode::Execution => format!("{}.js", specifier_text), + }; + Ok(resolve_import(&specifier_text, referrer)?) + } + } + + let mut loader = setup( + vec![ + ( + "file:///a/test01.ts", + Source::Module { + specifier: "file:///a/test01.ts", + maybe_headers: None, + content: r#" + import a from "./a"; + "#, + }, + ), + ( + "file:///a/a.js", + Source::Module { + specifier: "file:///a/a.js", + maybe_headers: None, + content: r#"export default 5;"#, + }, + ), + ( + "file:///a/a.d.ts", + Source::Module { + specifier: "file:///a/a.d.ts", + maybe_headers: None, + content: r#"export default 5;"#, + }, + ), + ], + vec![], + ); + let root_specifier = + ModuleSpecifier::parse("file:///a/test01.ts").expect("bad url"); + let mut graph = ModuleGraph::new(GraphKind::All); + let resolver = ExtResolver; + graph + .build( + vec![root_specifier.clone()], + &mut loader, + BuildOptions { + resolver: Some(&resolver), + ..Default::default() + }, + ) + .await; + assert_eq!( + json!(graph), + json!({ + "roots": [ + "file:///a/test01.ts" + ], + "modules": [ + { + "kind": "esm", + "size": 17, + "mediaType": "Dts", + "specifier": "file:///a/a.d.ts" + }, + { + "kind": "esm", + "size": 17, + "mediaType": "JavaScript", + "specifier": "file:///a/a.js" + }, + { + "dependencies": [ + { + "specifier": "./a", + "code": { + "specifier": "file:///a/a.js", + "span": { + "start": { + "line": 1, + "character": 26 + }, + "end": { + "line": 1, + "character": 31 + } + } + }, + "type": { + "specifier": "file:///a/a.d.ts", + "span": { + "start": { + "line": 1, + "character": 26 + }, + "end": { + "line": 1, + "character": 31 + } + } + }, + } + ], + "kind": "esm", + "size": 46, + "mediaType": "TypeScript", + "specifier": "file:///a/test01.ts" + } + ], + "redirects": {} + }) + ); + } } From 7e30be426b45ee74dc6be5ba601b877ca628c27e Mon Sep 17 00:00:00 2001 From: David Sherret Date: Mon, 16 Oct 2023 16:18:44 +0900 Subject: [PATCH 4/4] Fix JS tests --- js/test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/test.ts b/js/test.ts index 86077bc71..a3f53e20c 100644 --- a/js/test.ts +++ b/js/test.ts @@ -175,7 +175,7 @@ Deno.test({ return Promise.resolve(fixtures[specifier]); }, }); - assertEquals(resolveCount, 1); + assertEquals(resolveCount, 2); assertEquals(graph, { "roots": [ "file:///a/test.js", @@ -251,7 +251,7 @@ Deno.test({ "file:///a/deno.json": ["https://esm.sh/preact/jsx-runtime"], }, }); - assertEquals(resolveCount, 2); + assertEquals(resolveCount, 3); assertEquals(graph, { "roots": [ "file:///a/test.ts", @@ -348,7 +348,7 @@ Deno.test({ return Promise.resolve(fixtures[specifier]); }, }); - assertEquals(resolveCount, 1); + assertEquals(resolveCount, 2); assertEquals(graph, { "roots": [ "file:///a/test.js",