Skip to content

Commit

Permalink
feat(parser)!: stage 3 import source and import defer (#7706)
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen committed Dec 6, 2024
1 parent 8c3a954 commit 72eab6c
Show file tree
Hide file tree
Showing 30 changed files with 1,500 additions and 183 deletions.
15 changes: 15 additions & 0 deletions crates/oxc_ast/src/ast/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2188,6 +2188,7 @@ pub struct ImportExpression<'a> {
pub span: Span,
pub source: Expression<'a>,
pub arguments: Vec<'a, Expression<'a>>,
pub phase: Option<ImportPhase>,
}

#[ast(visit)]
Expand All @@ -2198,6 +2199,7 @@ pub struct ImportDeclaration<'a> {
/// `None` for `import 'foo'`, `Some([])` for `import {} from 'foo'`
pub specifiers: Option<Vec<'a, ImportDeclarationSpecifier<'a>>>,
pub source: StringLiteral<'a>,
pub phase: Option<ImportPhase>,
/// Some(vec![]) for empty assertion
#[ts]
pub with_clause: Option<Box<'a, WithClause<'a>>>,
Expand All @@ -2206,6 +2208,19 @@ pub struct ImportDeclaration<'a> {
pub import_kind: ImportOrExportKind,
}

/// Import Phase
///
/// <https://github.com/tc39/proposal-defer-import-eval>
/// <https://github.com/tc39/proposal-source-phase-imports>
/// <https://github.com/estree/estree/blob/2b48e56efc223ea477a45b5e034039934c5791fa/stage3/source-phase-imports.md>
#[ast]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[generate_derive(CloneIn, ContentEq, ContentHash, ESTree)]
pub enum ImportPhase {
Source = 0,
Defer = 1,
}

#[ast(visit)]
#[derive(Debug)]
#[generate_derive(CloneIn, GetSpan, GetSpanMut, GetAddress, ContentEq, ContentHash, ESTree)]
Expand Down
10 changes: 10 additions & 0 deletions crates/oxc_ast/src/ast_impl/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1478,3 +1478,13 @@ impl<'a> ModuleExportName<'a> {
}
}
}

impl ImportPhase {
#[allow(missing_docs)]
pub fn as_str(&self) -> &'static str {
match self {
Self::Source => "source",
Self::Defer => "defer",
}
}
}
26 changes: 18 additions & 8 deletions crates/oxc_ast/src/generated/assert_layouts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -697,19 +697,24 @@ const _: () = {
assert!(offset_of!(AccessorProperty, type_annotation) == 88usize);
assert!(offset_of!(AccessorProperty, accessibility) == 96usize);

assert!(size_of::<ImportExpression>() == 56usize);
assert!(size_of::<ImportExpression>() == 64usize);
assert!(align_of::<ImportExpression>() == 8usize);
assert!(offset_of!(ImportExpression, span) == 0usize);
assert!(offset_of!(ImportExpression, source) == 8usize);
assert!(offset_of!(ImportExpression, arguments) == 24usize);
assert!(offset_of!(ImportExpression, phase) == 56usize);

assert!(size_of::<ImportDeclaration>() == 96usize);
assert!(size_of::<ImportDeclaration>() == 104usize);
assert!(align_of::<ImportDeclaration>() == 8usize);
assert!(offset_of!(ImportDeclaration, span) == 0usize);
assert!(offset_of!(ImportDeclaration, specifiers) == 8usize);
assert!(offset_of!(ImportDeclaration, source) == 40usize);
assert!(offset_of!(ImportDeclaration, with_clause) == 80usize);
assert!(offset_of!(ImportDeclaration, import_kind) == 88usize);
assert!(offset_of!(ImportDeclaration, phase) == 80usize);
assert!(offset_of!(ImportDeclaration, with_clause) == 88usize);
assert!(offset_of!(ImportDeclaration, import_kind) == 96usize);

assert!(size_of::<ImportPhase>() == 1usize);
assert!(align_of::<ImportPhase>() == 1usize);

assert!(size_of::<ImportDeclarationSpecifier>() == 16usize);
assert!(align_of::<ImportDeclarationSpecifier>() == 8usize);
Expand Down Expand Up @@ -2254,19 +2259,24 @@ const _: () = {
assert!(offset_of!(AccessorProperty, type_annotation) == 48usize);
assert!(offset_of!(AccessorProperty, accessibility) == 52usize);

assert!(size_of::<ImportExpression>() == 32usize);
assert!(size_of::<ImportExpression>() == 36usize);
assert!(align_of::<ImportExpression>() == 4usize);
assert!(offset_of!(ImportExpression, span) == 0usize);
assert!(offset_of!(ImportExpression, source) == 8usize);
assert!(offset_of!(ImportExpression, arguments) == 16usize);
assert!(offset_of!(ImportExpression, phase) == 32usize);

assert!(size_of::<ImportDeclaration>() == 56usize);
assert!(size_of::<ImportDeclaration>() == 60usize);
assert!(align_of::<ImportDeclaration>() == 4usize);
assert!(offset_of!(ImportDeclaration, span) == 0usize);
assert!(offset_of!(ImportDeclaration, specifiers) == 8usize);
assert!(offset_of!(ImportDeclaration, source) == 24usize);
assert!(offset_of!(ImportDeclaration, with_clause) == 48usize);
assert!(offset_of!(ImportDeclaration, import_kind) == 52usize);
assert!(offset_of!(ImportDeclaration, phase) == 48usize);
assert!(offset_of!(ImportDeclaration, with_clause) == 52usize);
assert!(offset_of!(ImportDeclaration, import_kind) == 56usize);

assert!(size_of::<ImportPhase>() == 1usize);
assert!(align_of::<ImportPhase>() == 1usize);

assert!(size_of::<ImportDeclarationSpecifier>() == 8usize);
assert!(align_of::<ImportDeclarationSpecifier>() == 4usize);
Expand Down
24 changes: 20 additions & 4 deletions crates/oxc_ast/src/generated/ast_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -833,14 +833,18 @@ impl<'a> AstBuilder<'a> {
/// - span: The [`Span`] covering this node
/// - source
/// - arguments
/// - phase
#[inline]
pub fn expression_import(
self,
span: Span,
source: Expression<'a>,
arguments: Vec<'a, Expression<'a>>,
phase: Option<ImportPhase>,
) -> Expression<'a> {
Expression::ImportExpression(self.alloc(self.import_expression(span, source, arguments)))
Expression::ImportExpression(
self.alloc(self.import_expression(span, source, arguments, phase)),
)
}

/// Build an [`Expression::LogicalExpression`]
Expand Down Expand Up @@ -6587,6 +6591,7 @@ impl<'a> AstBuilder<'a> {
/// - span: The [`Span`] covering this node
/// - specifiers: `None` for `import 'foo'`, `Some([])` for `import {} from 'foo'`
/// - source
/// - phase
/// - with_clause: Some(vec![]) for empty assertion
/// - import_kind: `import type { foo } from 'bar'`
#[inline]
Expand All @@ -6595,6 +6600,7 @@ impl<'a> AstBuilder<'a> {
span: Span,
specifiers: Option<Vec<'a, ImportDeclarationSpecifier<'a>>>,
source: StringLiteral<'a>,
phase: Option<ImportPhase>,
with_clause: T1,
import_kind: ImportOrExportKind,
) -> ModuleDeclaration<'a>
Expand All @@ -6605,6 +6611,7 @@ impl<'a> AstBuilder<'a> {
span,
specifiers,
source,
phase,
with_clause,
import_kind,
)))
Expand Down Expand Up @@ -6836,14 +6843,16 @@ impl<'a> AstBuilder<'a> {
/// - span: The [`Span`] covering this node
/// - source
/// - arguments
/// - phase
#[inline]
pub fn import_expression(
self,
span: Span,
source: Expression<'a>,
arguments: Vec<'a, Expression<'a>>,
phase: Option<ImportPhase>,
) -> ImportExpression<'a> {
ImportExpression { span, source, arguments }
ImportExpression { span, source, arguments, phase }
}

/// Build an [`ImportExpression`], and store it in the memory arena.
Expand All @@ -6854,14 +6863,16 @@ impl<'a> AstBuilder<'a> {
/// - span: The [`Span`] covering this node
/// - source
/// - arguments
/// - phase
#[inline]
pub fn alloc_import_expression(
self,
span: Span,
source: Expression<'a>,
arguments: Vec<'a, Expression<'a>>,
phase: Option<ImportPhase>,
) -> Box<'a, ImportExpression<'a>> {
Box::new_in(self.import_expression(span, source, arguments), self.allocator)
Box::new_in(self.import_expression(span, source, arguments, phase), self.allocator)
}

/// Build an [`ImportDeclaration`].
Expand All @@ -6872,6 +6883,7 @@ impl<'a> AstBuilder<'a> {
/// - span: The [`Span`] covering this node
/// - specifiers: `None` for `import 'foo'`, `Some([])` for `import {} from 'foo'`
/// - source
/// - phase
/// - with_clause: Some(vec![]) for empty assertion
/// - import_kind: `import type { foo } from 'bar'`
#[inline]
Expand All @@ -6880,6 +6892,7 @@ impl<'a> AstBuilder<'a> {
span: Span,
specifiers: Option<Vec<'a, ImportDeclarationSpecifier<'a>>>,
source: StringLiteral<'a>,
phase: Option<ImportPhase>,
with_clause: T1,
import_kind: ImportOrExportKind,
) -> ImportDeclaration<'a>
Expand All @@ -6890,6 +6903,7 @@ impl<'a> AstBuilder<'a> {
span,
specifiers,
source,
phase,
with_clause: with_clause.into_in(self.allocator),
import_kind,
}
Expand All @@ -6903,6 +6917,7 @@ impl<'a> AstBuilder<'a> {
/// - span: The [`Span`] covering this node
/// - specifiers: `None` for `import 'foo'`, `Some([])` for `import {} from 'foo'`
/// - source
/// - phase
/// - with_clause: Some(vec![]) for empty assertion
/// - import_kind: `import type { foo } from 'bar'`
#[inline]
Expand All @@ -6911,14 +6926,15 @@ impl<'a> AstBuilder<'a> {
span: Span,
specifiers: Option<Vec<'a, ImportDeclarationSpecifier<'a>>>,
source: StringLiteral<'a>,
phase: Option<ImportPhase>,
with_clause: T1,
import_kind: ImportOrExportKind,
) -> Box<'a, ImportDeclaration<'a>>
where
T1: IntoIn<'a, Option<Box<'a, WithClause<'a>>>>,
{
Box::new_in(
self.import_declaration(span, specifiers, source, with_clause, import_kind),
self.import_declaration(span, specifiers, source, phase, with_clause, import_kind),
self.allocator,
)
}
Expand Down
12 changes: 12 additions & 0 deletions crates/oxc_ast/src/generated/derive_clone_in.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2225,6 +2225,7 @@ impl<'new_alloc> CloneIn<'new_alloc> for ImportExpression<'_> {
span: CloneIn::clone_in(&self.span, allocator),
source: CloneIn::clone_in(&self.source, allocator),
arguments: CloneIn::clone_in(&self.arguments, allocator),
phase: CloneIn::clone_in(&self.phase, allocator),
}
}
}
Expand All @@ -2236,12 +2237,23 @@ impl<'new_alloc> CloneIn<'new_alloc> for ImportDeclaration<'_> {
span: CloneIn::clone_in(&self.span, allocator),
specifiers: CloneIn::clone_in(&self.specifiers, allocator),
source: CloneIn::clone_in(&self.source, allocator),
phase: CloneIn::clone_in(&self.phase, allocator),
with_clause: CloneIn::clone_in(&self.with_clause, allocator),
import_kind: CloneIn::clone_in(&self.import_kind, allocator),
}
}
}

impl<'alloc> CloneIn<'alloc> for ImportPhase {
type Cloned = ImportPhase;
fn clone_in(&self, _: &'alloc Allocator) -> Self::Cloned {
match self {
Self::Source => ImportPhase::Source,
Self::Defer => ImportPhase::Defer,
}
}
}

impl<'new_alloc> CloneIn<'new_alloc> for ImportDeclarationSpecifier<'_> {
type Cloned = ImportDeclarationSpecifier<'new_alloc>;
fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned {
Expand Down
8 changes: 8 additions & 0 deletions crates/oxc_ast/src/generated/derive_content_eq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2239,18 +2239,26 @@ impl ContentEq for ImportExpression<'_> {
fn content_eq(&self, other: &Self) -> bool {
ContentEq::content_eq(&self.source, &other.source)
&& ContentEq::content_eq(&self.arguments, &other.arguments)
&& ContentEq::content_eq(&self.phase, &other.phase)
}
}

impl ContentEq for ImportDeclaration<'_> {
fn content_eq(&self, other: &Self) -> bool {
ContentEq::content_eq(&self.specifiers, &other.specifiers)
&& ContentEq::content_eq(&self.source, &other.source)
&& ContentEq::content_eq(&self.phase, &other.phase)
&& ContentEq::content_eq(&self.with_clause, &other.with_clause)
&& ContentEq::content_eq(&self.import_kind, &other.import_kind)
}
}

impl ContentEq for ImportPhase {
fn content_eq(&self, other: &Self) -> bool {
self == other
}
}

impl ContentEq for ImportDeclarationSpecifier<'_> {
fn content_eq(&self, other: &Self) -> bool {
match self {
Expand Down
8 changes: 8 additions & 0 deletions crates/oxc_ast/src/generated/derive_content_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1227,18 +1227,26 @@ impl ContentHash for ImportExpression<'_> {
fn content_hash<H: Hasher>(&self, state: &mut H) {
ContentHash::content_hash(&self.source, state);
ContentHash::content_hash(&self.arguments, state);
ContentHash::content_hash(&self.phase, state);
}
}

impl ContentHash for ImportDeclaration<'_> {
fn content_hash<H: Hasher>(&self, state: &mut H) {
ContentHash::content_hash(&self.specifiers, state);
ContentHash::content_hash(&self.source, state);
ContentHash::content_hash(&self.phase, state);
ContentHash::content_hash(&self.with_clause, state);
ContentHash::content_hash(&self.import_kind, state);
}
}

impl ContentHash for ImportPhase {
fn content_hash<H: Hasher>(&self, state: &mut H) {
ContentHash::content_hash(&discriminant(self), state);
}
}

impl ContentHash for ImportDeclarationSpecifier<'_> {
fn content_hash<H: Hasher>(&self, state: &mut H) {
ContentHash::content_hash(&discriminant(self), state);
Expand Down
11 changes: 11 additions & 0 deletions crates/oxc_ast/src/generated/derive_estree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1685,6 +1685,7 @@ impl Serialize for ImportExpression<'_> {
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
map.serialize_entry("source", &self.source)?;
map.serialize_entry("arguments", &self.arguments)?;
map.serialize_entry("phase", &self.phase)?;
map.end()
}
}
Expand All @@ -1696,12 +1697,22 @@ impl Serialize for ImportDeclaration<'_> {
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
map.serialize_entry("specifiers", &self.specifiers)?;
map.serialize_entry("source", &self.source)?;
map.serialize_entry("phase", &self.phase)?;
map.serialize_entry("withClause", &self.with_clause)?;
map.serialize_entry("importKind", &self.import_kind)?;
map.end()
}
}

impl Serialize for ImportPhase {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match *self {
ImportPhase::Source => serializer.serialize_unit_variant("ImportPhase", 0u32, "source"),
ImportPhase::Defer => serializer.serialize_unit_variant("ImportPhase", 1u32, "defer"),
}
}
}

impl Serialize for ImportDeclarationSpecifier<'_> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
Expand Down
10 changes: 9 additions & 1 deletion crates/oxc_codegen/src/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,10 @@ impl Gen for ImportDeclaration<'_> {
if self.import_kind.is_type() {
p.print_str(" type");
}
if let Some(phase) = self.phase {
p.print_hard_space();
p.print_str(phase.as_str());
}
if let Some(specifiers) = &self.specifiers {
if specifiers.is_empty() {
p.print_soft_space();
Expand Down Expand Up @@ -1990,7 +1994,11 @@ impl GenExpr for ImportExpression<'_> {
p.wrap(wrap, |p| {
p.print_space_before_identifier();
p.add_source_mapping(self.span);
p.print_str("import(");
p.print_str("import");
if let Some(phase) = self.phase {
p.print_str(phase.as_str());
}
p.print_ascii_byte(b'(');
if has_comment {
p.indent();
}
Expand Down
1 change: 1 addition & 0 deletions crates/oxc_isolated_declarations/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ impl<'a> IsolatedDeclarations<'a> {
decl.span,
Some(new_specifiers),
decl.source.clone(),
None,
decl.with_clause.clone_in(self.ast.allocator),
decl.import_kind,
))
Expand Down
Loading

0 comments on commit 72eab6c

Please sign in to comment.