Skip to content
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
5 changes: 4 additions & 1 deletion crates/oxc_parser/src/js/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ impl<'a> ParserImpl<'a> {
self.ctx = self.ctx.and_in(has_in);
self.bump(Kind::Comma);
self.expect(Kind::RParen)?;
Ok(self.ast.expression_import(self.end_span(span), expression, arguments, phase))
let expr =
self.ast.alloc_import_expression(self.end_span(span), expression, arguments, phase);
self.module_record_builder.visit_import_expression(&expr);
Ok(Expression::ImportExpression(expr))
}

/// Section 16.2.2 Import Declaration
Expand Down
15 changes: 15 additions & 0 deletions crates/oxc_parser/src/module_record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@ impl<'a> ModuleRecordBuilder<'a> {
}
}

pub fn visit_import_expression(&mut self, e: &ImportExpression<'a>) {
self.module_record
.dynamic_imports
.push(DynamicImport { span: e.span, module_request: e.source.span() });
}

pub fn visit_import_meta(&mut self, span: Span) {
self.module_record.has_module_syntax = true;
self.module_record.import_metas.push(span);
Expand Down Expand Up @@ -701,4 +707,13 @@ mod module_record_tests {
assert_eq!(module_record.import_metas[0], Span::new(0, 11));
assert_eq!(module_record.import_metas[1], Span::new(17, 28));
}

#[test]
fn dynamic_imports() {
let allocator = Allocator::default();
let module_record = build(&allocator, "import('foo')");
assert_eq!(module_record.dynamic_imports.len(), 1);
assert_eq!(module_record.dynamic_imports[0].span, Span::new(0, 13));
assert_eq!(module_record.dynamic_imports[0].module_request, Span::new(7, 12));
}
}
13 changes: 13 additions & 0 deletions crates/oxc_syntax/src/module_record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ pub struct ModuleRecord<'a> {
/// Local exported bindings
pub exported_bindings: FxHashMap<Atom<'a>, Span>,

/// Dynamic import expressions `import(specifier)`.
pub dynamic_imports: Vec<'a, DynamicImport>,

/// Span position of `import.meta`.
pub import_metas: Vec<'a, Span>,
}
Expand All @@ -72,6 +75,7 @@ impl<'a> ModuleRecord<'a> {
indirect_export_entries: Vec::new_in(allocator),
star_export_entries: Vec::new_in(allocator),
exported_bindings: FxHashMap::default(),
dynamic_imports: Vec::new_in(allocator),
import_metas: Vec::new_in(allocator),
}
}
Expand Down Expand Up @@ -374,6 +378,15 @@ pub struct RequestedModule {
pub is_import: bool,
}

/// Dynamic import expression.
#[derive(Debug, Clone, Copy)]
pub struct DynamicImport {
/// Span of the import expression.
pub span: Span,
/// Span the ModuleSpecifier, which is an expression.
pub module_request: Span,
}

#[cfg(test)]
mod test {
use oxc_span::Span;
Expand Down
12 changes: 10 additions & 2 deletions napi/parser/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ export interface Comment {
end: number
}

export interface DynamicImport {
start: number
end: number
moduleRequest: Span
}

export interface EcmaScriptModule {
/**
* Has ESM syntax.
Expand All @@ -46,10 +52,12 @@ export interface EcmaScriptModule {
* Dynamic imports `import('foo')` are ignored since they can be used in non-ESM files.
*/
hasModuleSyntax: boolean
/** Import Statements. */
/** Import statements. */
staticImports: Array<StaticImport>
/** Export Statements. */
/** Export statements. */
staticExports: Array<StaticExport>
/** Dynamic import expressions. */
dynamicImports: Array<DynamicImport>
/** Span positions` of `import.meta` */
importMetas: Array<Span>
}
Expand Down
13 changes: 12 additions & 1 deletion napi/parser/src/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use rustc_hash::FxHashMap;
use oxc::syntax::module_record::{self, ModuleRecord};

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

let dynamic_imports = record
.dynamic_imports
.iter()
.map(|i| DynamicImport {
start: i.span.start,
end: i.span.end,
module_request: Span::from(&i.module_request),
})
.collect::<Vec<_>>();

let import_metas = record.import_metas.iter().map(Span::from).collect();

Self {
has_module_syntax: record.has_module_syntax,
static_imports,
static_exports,
dynamic_imports,
import_metas,
}
}
Expand Down
13 changes: 11 additions & 2 deletions napi/parser/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,12 @@ pub struct EcmaScriptModule {
///
/// Dynamic imports `import('foo')` are ignored since they can be used in non-ESM files.
pub has_module_syntax: bool,
/// Import Statements.
/// Import statements.
pub static_imports: Vec<StaticImport>,
/// Export Statements.
/// Export statements.
pub static_exports: Vec<StaticExport>,
/// Dynamic import expressions.
pub dynamic_imports: Vec<DynamicImport>,
/// Span positions` of `import.meta`
pub import_metas: Vec<Span>,
}
Expand Down Expand Up @@ -245,3 +247,10 @@ pub enum ExportLocalNameKind {
/// `export default function () {}`
None,
}

#[napi(object)]
pub struct DynamicImport {
pub start: u32,
pub end: u32,
pub module_request: Span,
}
Loading
Loading