Skip to content

Commit bcf1fe2

Browse files
committed
feat(napi/parser): expose dynamic import expressions
closes #8369
1 parent b4c87e2 commit bcf1fe2

File tree

8 files changed

+101
-6
lines changed

8 files changed

+101
-6
lines changed

crates/oxc_parser/src/js/module.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ impl<'a> ParserImpl<'a> {
3434
self.ctx = self.ctx.and_in(has_in);
3535
self.bump(Kind::Comma);
3636
self.expect(Kind::RParen)?;
37-
Ok(self.ast.expression_import(self.end_span(span), expression, arguments, phase))
37+
let expr =
38+
self.ast.alloc_import_expression(self.end_span(span), expression, arguments, phase);
39+
self.module_record_builder.visit_import_expression(&expr);
40+
Ok(Expression::ImportExpression(expr))
3841
}
3942

4043
/// Section 16.2.2 Import Declaration

crates/oxc_parser/src/module_record.rs

+15
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,12 @@ impl<'a> ModuleRecordBuilder<'a> {
174174
}
175175
}
176176

177+
pub fn visit_import_expression(&mut self, e: &ImportExpression<'a>) {
178+
self.module_record
179+
.dynamic_imports
180+
.push(DynamicImport { span: e.span, module_request: e.source.span() });
181+
}
182+
177183
pub fn visit_import_meta(&mut self, span: Span) {
178184
self.module_record.has_module_syntax = true;
179185
self.module_record.import_metas.push(span);
@@ -701,4 +707,13 @@ mod module_record_tests {
701707
assert_eq!(module_record.import_metas[0], Span::new(0, 11));
702708
assert_eq!(module_record.import_metas[1], Span::new(17, 28));
703709
}
710+
711+
#[test]
712+
fn dynamic_imports() {
713+
let allocator = Allocator::default();
714+
let module_record = build(&allocator, "import('foo')");
715+
assert_eq!(module_record.dynamic_imports.len(), 1);
716+
assert_eq!(module_record.dynamic_imports[0].span, Span::new(0, 13));
717+
assert_eq!(module_record.dynamic_imports[0].module_request, Span::new(7, 12));
718+
}
704719
}

crates/oxc_syntax/src/module_record.rs

+13
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ pub struct ModuleRecord<'a> {
5757
/// Local exported bindings
5858
pub exported_bindings: FxHashMap<Atom<'a>, Span>,
5959

60+
/// Dynamic import expressions `import(specifier)`.
61+
pub dynamic_imports: Vec<'a, DynamicImport>,
62+
6063
/// Span position of `import.meta`.
6164
pub import_metas: Vec<'a, Span>,
6265
}
@@ -72,6 +75,7 @@ impl<'a> ModuleRecord<'a> {
7275
indirect_export_entries: Vec::new_in(allocator),
7376
star_export_entries: Vec::new_in(allocator),
7477
exported_bindings: FxHashMap::default(),
78+
dynamic_imports: Vec::new_in(allocator),
7579
import_metas: Vec::new_in(allocator),
7680
}
7781
}
@@ -374,6 +378,15 @@ pub struct RequestedModule {
374378
pub is_import: bool,
375379
}
376380

381+
/// Dynamic import expression.
382+
#[derive(Debug, Clone, Copy)]
383+
pub struct DynamicImport {
384+
/// Span of the import expression.
385+
pub span: Span,
386+
/// Span the ModuleSpecifier, which is an expression.
387+
pub module_request: Span,
388+
}
389+
377390
#[cfg(test)]
378391
mod test {
379392
use oxc_span::Span;

napi/parser/index.d.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ export interface Comment {
3737
end: number
3838
}
3939

40+
export interface DynamicImport {
41+
start: number
42+
end: number
43+
moduleRequest: Span
44+
}
45+
4046
export interface EcmaScriptModule {
4147
/**
4248
* Has ESM syntax.
@@ -46,10 +52,12 @@ export interface EcmaScriptModule {
4652
* Dynamic imports `import('foo')` are ignored since they can be used in non-ESM files.
4753
*/
4854
hasModuleSyntax: boolean
49-
/** Import Statements. */
55+
/** Import statements. */
5056
staticImports: Array<StaticImport>
51-
/** Export Statements. */
57+
/** Export statements. */
5258
staticExports: Array<StaticExport>
59+
/** Dynamic import expressions. */
60+
dynamicImports: Array<DynamicImport>
5361
/** Span positions` of `import.meta` */
5462
importMetas: Array<Span>
5563
}

napi/parser/src/convert.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use rustc_hash::FxHashMap;
33
use oxc::syntax::module_record::{self, ModuleRecord};
44

55
use crate::types::{
6-
EcmaScriptModule, ExportExportName, ExportExportNameKind, ExportImportName,
6+
DynamicImport, EcmaScriptModule, ExportExportName, ExportExportNameKind, ExportImportName,
77
ExportImportNameKind, ExportLocalName, ExportLocalNameKind, ImportName, ImportNameKind, Span,
88
StaticExport, StaticExportEntry, StaticImport, StaticImportEntry, ValueSpan,
99
};
@@ -55,12 +55,23 @@ impl From<&ModuleRecord<'_>> for EcmaScriptModule {
5555
.collect::<Vec<_>>();
5656
static_exports.sort_unstable_by_key(|e| e.start);
5757

58+
let dynamic_imports = record
59+
.dynamic_imports
60+
.iter()
61+
.map(|i| DynamicImport {
62+
start: i.span.start,
63+
end: i.span.end,
64+
module_request: Span::from(&i.module_request),
65+
})
66+
.collect::<Vec<_>>();
67+
5868
let import_metas = record.import_metas.iter().map(Span::from).collect();
5969

6070
Self {
6171
has_module_syntax: record.has_module_syntax,
6272
static_imports,
6373
static_exports,
74+
dynamic_imports,
6475
import_metas,
6576
}
6677
}

napi/parser/src/types.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,12 @@ pub struct EcmaScriptModule {
8181
///
8282
/// Dynamic imports `import('foo')` are ignored since they can be used in non-ESM files.
8383
pub has_module_syntax: bool,
84-
/// Import Statements.
84+
/// Import statements.
8585
pub static_imports: Vec<StaticImport>,
86-
/// Export Statements.
86+
/// Export statements.
8787
pub static_exports: Vec<StaticExport>,
88+
/// Dynamic import expressions.
89+
pub dynamic_imports: Vec<DynamicImport>,
8890
/// Span positions` of `import.meta`
8991
pub import_metas: Vec<Span>,
9092
}
@@ -245,3 +247,10 @@ pub enum ExportLocalNameKind {
245247
/// `export default function () {}`
246248
None,
247249
}
250+
251+
#[napi(object)]
252+
pub struct DynamicImport {
253+
pub start: u32,
254+
pub end: u32,
255+
pub module_request: Span,
256+
}

0 commit comments

Comments
 (0)