Skip to content

Commit 2e91927

Browse files
committed
feat: load source phase imports as assets
1 parent 5e77463 commit 2e91927

File tree

3 files changed

+129
-32
lines changed

3 files changed

+129
-32
lines changed

src/analysis.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,15 @@ impl ImportAttributes {
9898
pub enum DynamicDependencyKind {
9999
#[default]
100100
Import,
101+
ImportSource,
101102
Require,
102103
}
103104

104105
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
105106
#[serde(rename_all = "camelCase")]
106107
pub enum StaticDependencyKind {
107108
Import,
109+
ImportSource,
108110
ImportType,
109111
ImportEquals,
110112
Export,

src/ast/dep.rs

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use deno_ast::SourceRangedForSpanned;
88
use deno_ast::swc::ast;
99
use deno_ast::swc::ast::Callee;
1010
use deno_ast::swc::ast::Expr;
11+
use deno_ast::swc::ast::ImportPhase;
1112
use deno_ast::swc::atoms::Atom;
1213
use deno_ast::swc::common::comments::CommentKind;
1314
use deno_ast::swc::ecma_visit::Visit;
@@ -145,10 +146,11 @@ impl DependencyCollector<'_> {
145146
impl Visit for DependencyCollector<'_> {
146147
fn visit_import_decl(&mut self, node: &ast::ImportDecl) {
147148
let leading_comments = self.get_leading_comments(node.start());
148-
let kind = if node.type_only {
149-
StaticDependencyKind::ImportType
150-
} else {
151-
StaticDependencyKind::Import
149+
let kind = match (node.type_only, node.phase) {
150+
(true, _) => StaticDependencyKind::ImportType,
151+
(false, ImportPhase::Evaluation) => StaticDependencyKind::Import,
152+
(false, ImportPhase::Source) => StaticDependencyKind::ImportSource,
153+
(false, ImportPhase::Defer) => return,
152154
};
153155
self.items.push(
154156
StaticDependencyDescriptor {
@@ -241,10 +243,15 @@ impl Visit for DependencyCollector<'_> {
241243
fn visit_call_expr(&mut self, node: &ast::CallExpr) {
242244
node.visit_children_with(self);
243245

244-
let is_esm = matches!(&node.callee, Callee::Import(_));
245-
if !is_esm && !self.is_require(&node.callee) {
246-
return;
247-
}
246+
let kind = match &node.callee {
247+
Callee::Import(import) => match import.phase {
248+
ImportPhase::Evaluation => DynamicDependencyKind::Import,
249+
ImportPhase::Source => DynamicDependencyKind::ImportSource,
250+
ImportPhase::Defer => return,
251+
},
252+
_ if self.is_require(&node.callee) => DynamicDependencyKind::Require,
253+
_ => return,
254+
};
248255
let Some(arg) = node.args.first() else {
249256
return;
250257
};
@@ -332,11 +339,7 @@ impl Visit for DependencyCollector<'_> {
332339
let leading_comments = self.get_leading_comments(node.start());
333340
self.items.push(
334341
DynamicDependencyDescriptor {
335-
kind: if is_esm {
336-
DynamicDependencyKind::Import
337-
} else {
338-
DynamicDependencyKind::Require
339-
},
342+
kind,
340343
leading_comments,
341344
range: node.range(),
342345
argument,

src/graph.rs

Lines changed: 111 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,8 @@ fn is_false(v: &bool) -> bool {
946946
pub enum ImportKind {
947947
/// `import`/`export`
948948
Es,
949+
/// `import source`
950+
EsSource,
949951
/// `require`
950952
Require,
951953
/// `import type`/`export type`
@@ -965,9 +967,10 @@ pub enum ImportKind {
965967
impl ImportKind {
966968
pub fn is_runtime(&self) -> bool {
967969
match self {
968-
ImportKind::Es | ImportKind::Require | ImportKind::JsxImportSource => {
969-
true
970-
}
970+
ImportKind::Es
971+
| ImportKind::EsSource
972+
| ImportKind::Require
973+
| ImportKind::JsxImportSource => true,
971974
ImportKind::TsType
972975
| ImportKind::TsModuleAugmentation
973976
| ImportKind::TsReferencePath
@@ -976,6 +979,20 @@ impl ImportKind {
976979
}
977980
}
978981

982+
pub fn is_source_phase(&self) -> bool {
983+
match self {
984+
ImportKind::EsSource => true,
985+
ImportKind::Es
986+
| ImportKind::Require
987+
| ImportKind::JsxImportSource
988+
| ImportKind::TsType
989+
| ImportKind::TsModuleAugmentation
990+
| ImportKind::TsReferencePath
991+
| ImportKind::TsReferenceTypes
992+
| ImportKind::JsDoc => false,
993+
}
994+
}
995+
979996
fn is_es(&self) -> bool {
980997
matches!(self, ImportKind::Es)
981998
}
@@ -3577,19 +3594,25 @@ fn fill_module_dependencies(
35773594
)
35783595
}
35793596
DependencyDescriptor::Static(desc) => {
3580-
let is_import_or_export_type = matches!(
3581-
desc.kind,
3582-
StaticDependencyKind::ImportType | StaticDependencyKind::ExportType
3583-
);
3584-
if is_import_or_export_type && !graph_kind.include_types() {
3585-
continue; // skip
3586-
}
3587-
let is_types = is_import_or_export_type || media_type.is_declaration();
3597+
let kind = match desc.kind {
3598+
StaticDependencyKind::ImportType
3599+
| StaticDependencyKind::ExportType => {
3600+
if !graph_kind.include_types() {
3601+
continue;
3602+
}
3603+
ImportKind::TsType
3604+
}
3605+
StaticDependencyKind::ImportSource => ImportKind::EsSource,
3606+
_ => ImportKind::Es,
3607+
};
3608+
let is_types =
3609+
kind == ImportKind::TsType || media_type.is_declaration();
35883610
let specifier_range = Range {
35893611
specifier: module_specifier.clone(),
35903612
range: desc.specifier_range,
35913613
resolution_mode: match desc.kind {
35923614
StaticDependencyKind::Import
3615+
| StaticDependencyKind::ImportSource
35933616
| StaticDependencyKind::Export
35943617
| StaticDependencyKind::ImportType
35953618
| StaticDependencyKind::ExportType => is_types
@@ -3618,10 +3641,7 @@ fn fill_module_dependencies(
36183641
(
36193642
vec![Import {
36203643
specifier: desc.specifier,
3621-
kind: match is_import_or_export_type {
3622-
true => ImportKind::TsType,
3623-
false => ImportKind::Es,
3624-
},
3644+
kind,
36253645
specifier_range,
36263646
is_dynamic: false,
36273647
attributes: desc.import_attributes,
@@ -3657,7 +3677,8 @@ fn fill_module_dependencies(
36573677
specifier: module_specifier.clone(),
36583678
range: desc.argument_range,
36593679
resolution_mode: match desc.kind {
3660-
DynamicDependencyKind::Import => {
3680+
DynamicDependencyKind::Import
3681+
| DynamicDependencyKind::ImportSource => {
36613682
if media_type.is_declaration() {
36623683
None
36633684
} else {
@@ -3674,6 +3695,7 @@ fn fill_module_dependencies(
36743695
specifier,
36753696
kind: match desc.kind {
36763697
DynamicDependencyKind::Import => ImportKind::Es,
3698+
DynamicDependencyKind::ImportSource => ImportKind::EsSource,
36773699
DynamicDependencyKind::Require => ImportKind::Require,
36783700
},
36793701
specifier_range: specifier_range.clone(),
@@ -4987,7 +5009,6 @@ impl<'a, 'graph> Builder<'a, 'graph> {
49875009
let original_specifier = specifier;
49885010
let specifier = self.graph.redirects.get(specifier).unwrap_or(specifier);
49895011
if options.is_asset {
4990-
// this will always be set when an asset
49915012
if let Some(attribute) = &options.maybe_attribute_type {
49925013
let is_allowed = match attribute.kind.as_str() {
49935014
"bytes" => self.unstable_bytes_imports,
@@ -6092,7 +6113,10 @@ impl<'a, 'graph> Builder<'a, 'graph> {
60926113
if dep.is_dynamic && self.skip_dynamic_deps {
60936114
continue;
60946115
}
6095-
let is_asset = dep.imports.iter().all(|i| i.attributes.has_asset());
6116+
let is_asset = dep
6117+
.imports
6118+
.iter()
6119+
.all(|i| i.attributes.has_asset() || i.kind.is_source_phase());
60966120

60976121
if self.graph.graph_kind.include_code() || dep.maybe_type.is_none() {
60986122
if let Resolution::Ok(resolved) = &dep.maybe_code {
@@ -7383,6 +7407,8 @@ mod tests {
73837407
import 'file:///baz.json' assert { type: 'json' };
73847408
import type {} from 'file:///bar.ts';
73857409
/** @typedef { import('file:///bar.ts') } bar */
7410+
import source mathModule from 'file:///math_with_import.wasm';
7411+
await import.source('file:///math_with_import.wasm');
73867412
"
73877413
.to_vec()
73887414
.into(),
@@ -7410,7 +7436,22 @@ mod tests {
74107436
}))
74117437
})
74127438
}
7413-
_ => unreachable!(),
7439+
"file:///math_with_import.wasm" => Box::pin(async move {
7440+
Ok(Some(LoadResponse::Module {
7441+
specifier: specifier.clone(),
7442+
maybe_headers: None,
7443+
mtime: None,
7444+
content: include_bytes!(
7445+
"../tests/testdata/math_with_import.wasm"
7446+
)
7447+
.to_vec()
7448+
.into(),
7449+
}))
7450+
}),
7451+
"file:///math.ts" => unreachable!(
7452+
"Shouldn't load dependencies of wasm modules imported by source"
7453+
),
7454+
s => unreachable!("Tried to load: {s}"),
74147455
}
74157456
}
74167457
}
@@ -7428,6 +7469,10 @@ mod tests {
74287469
let module = module.js().unwrap();
74297470
let dependency_a = module.dependencies.get("file:///bar.ts").unwrap();
74307471
let dependency_b = module.dependencies.get("file:///baz.json").unwrap();
7472+
let dependency_c = module
7473+
.dependencies
7474+
.get("file:///math_with_import.wasm")
7475+
.unwrap();
74317476
assert_eq!(
74327477
dependency_a.imports,
74337478
vec![
@@ -7586,6 +7631,53 @@ mod tests {
75867631
is_side_effect: true,
75877632
}]
75887633
);
7634+
assert_eq!(
7635+
dependency_c.imports,
7636+
vec![
7637+
Import {
7638+
specifier: "file:///math_with_import.wasm".to_string(),
7639+
kind: ImportKind::EsSource,
7640+
specifier_range: Range {
7641+
specifier: Url::parse("file:///foo.ts").unwrap(),
7642+
range: PositionRange {
7643+
start: Position {
7644+
line: 10,
7645+
character: 46,
7646+
},
7647+
end: Position {
7648+
line: 10,
7649+
character: 77,
7650+
},
7651+
},
7652+
resolution_mode: Some(ResolutionMode::Import),
7653+
},
7654+
is_dynamic: false,
7655+
attributes: ImportAttributes::None,
7656+
is_side_effect: false,
7657+
},
7658+
Import {
7659+
specifier: "file:///math_with_import.wasm".to_string(),
7660+
kind: ImportKind::EsSource,
7661+
specifier_range: Range {
7662+
specifier: Url::parse("file:///foo.ts").unwrap(),
7663+
range: PositionRange {
7664+
start: Position {
7665+
line: 11,
7666+
character: 36,
7667+
},
7668+
end: Position {
7669+
line: 11,
7670+
character: 67,
7671+
},
7672+
},
7673+
resolution_mode: Some(ResolutionMode::Import),
7674+
},
7675+
is_dynamic: true,
7676+
attributes: ImportAttributes::None,
7677+
is_side_effect: false,
7678+
},
7679+
],
7680+
);
75897681
}
75907682

75917683
#[tokio::test]

0 commit comments

Comments
 (0)