Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: jsr specifiers sometimes not resolved in dynamic imports #430

Merged
merged 1 commit into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions src/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2723,7 +2723,7 @@ impl From<LoadResponse> for PendingInfoResponse {
}
}

#[derive(Clone)]
#[derive(Debug, Clone)]
struct JsrPackageVersionInfoExt {
base_url: Url,
inner: Arc<JsrPackageVersionInfo>,
Expand All @@ -2738,7 +2738,7 @@ struct PendingInfo {

type PendingInfoFuture = LocalBoxFuture<'static, PendingInfo>;

#[derive(PartialEq, Eq, Hash)]
#[derive(Debug, PartialEq, Eq, Hash)]
pub(crate) struct AttributeTypeWithRange {
range: Range,
/// The kind of attribute (ex. "json").
Expand All @@ -2753,19 +2753,21 @@ struct PendingNpmRegistryInfoLoad {
type PendingNpmRegistryInfoLoadFutures =
FuturesUnordered<LocalBoxFuture<'static, PendingNpmRegistryInfoLoad>>;

#[derive(Default)]
#[derive(Debug, Default)]
struct PendingNpmState {
requested_registry_info_loads: HashSet<String>,
pending_registry_info_loads: PendingNpmRegistryInfoLoadFutures,
pending_resolutions: Vec<PendingNpmResolutionItem>,
}

#[derive(Debug)]
struct PendingJsrResolutionItem {
specifier: ModuleSpecifier,
package_ref: JsrPackageReqReference,
maybe_range: Option<Range>,
}

#[derive(Debug)]
struct PendingContentLoadItem {
specifier: ModuleSpecifier,
maybe_range: Option<Range>,
Expand All @@ -2781,7 +2783,7 @@ struct PendingJsrPackageVersionInfoLoadItem {

type PendingResult<T> = Shared<JoinHandle<Result<T, Arc<anyhow::Error>>>>;

#[derive(Default)]
#[derive(Debug, Default)]
struct PendingJsrState {
pending_package_info_loads:
HashMap<String, PendingResult<Option<Arc<JsrPackageInfo>>>>,
Expand All @@ -2792,13 +2794,14 @@ struct PendingJsrState {
FuturesUnordered<LocalBoxFuture<'static, PendingContentLoadItem>>,
}

#[derive(Debug)]
struct PendingDynamicBranch {
range: Range,
maybe_attribute_type: Option<AttributeTypeWithRange>,
maybe_version_info: Option<JsrPackageVersionInfoExt>,
}

#[derive(Default)]
#[derive(Debug, Default)]
struct PendingState {
pending: FuturesOrdered<PendingInfoFuture>,
jsr: PendingJsrState,
Expand Down Expand Up @@ -2962,7 +2965,10 @@ impl<'a, 'graph> Builder<'a, 'graph> {
// process any imports that are being added to the graph.
self.handle_provided_imports(imports);

loop {
while !(self.state.pending.is_empty()
&& self.state.jsr.pending_resolutions.is_empty()
&& self.state.dynamic_branches.is_empty())
{
let specifier = match self.state.pending.next().await {
Some(PendingInfo {
specifier,
Expand Down Expand Up @@ -3048,12 +3054,9 @@ impl<'a, 'graph> Builder<'a, 'graph> {
return;
}

// resolving jsr specifiers will load more specifiers
if self.state.pending.is_empty() {
self.resolve_dynamic_branches();

if self.state.pending.is_empty() {
break;
}
}
}
}
Expand Down Expand Up @@ -4301,6 +4304,7 @@ impl NpmSpecifierBuildPendingInfo {
}
}

#[derive(Debug)]
struct PendingNpmResolutionItem {
specifier: ModuleSpecifier,
package_ref: NpmPackageReqReference,
Expand Down
68 changes: 68 additions & 0 deletions tests/specs/graph/jsr/DynamicImportOfJsr.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# https://jsr.io/@scope/a/meta.json
{"versions": { "1.0.0": {} } }

# https://jsr.io/@scope/a/1.0.0_meta.json
{
"exports": {
".": "./mod.ts"
}
}
# https://jsr.io/@scope/a/1.0.0/mod.ts
export class Test {}

# mod.ts
await import("jsr:@scope/a");

# output
{
"roots": [
"file:///mod.ts"
],
"modules": [
{
"kind": "esm",
"dependencies": [
{
"specifier": "jsr:@scope/a",
"code": {
"specifier": "jsr:@scope/a",
"span": {
"start": {
"line": 0,
"character": 13
},
"end": {
"line": 0,
"character": 27
}
}
},
"isDynamic": true
}
],
"size": 30,
"mediaType": "TypeScript",
"specifier": "file:///mod.ts"
},
{
"kind": "esm",
"size": 21,
"mediaType": "TypeScript",
"specifier": "https://jsr.io/@scope/a/1.0.0/mod.ts"
}
],
"redirects": {
"jsr:@scope/a": "https://jsr.io/@scope/a/1.0.0/mod.ts"
},
"packages": {
"@scope/a": "@scope/[email protected]"
}
}

Fast check https://jsr.io/@scope/a/1.0.0/mod.ts:
{}
export class Test {
}
--- DTS ---
export declare class Test {
}