mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 20:32:10 +00:00
feat(parser)!: stage 3 import source and import defer (#7706)
* https://github.com/tc39/proposal-defer-import-eval * https://github.com/tc39/proposal-source-phase-imports * https://tc39.es/proposal-source-phase-imports/#sec-ecmascript-language-expressions * https://tc39.es/proposal-defer-import-eval/#prod-NameSpaceImport
This commit is contained in:
parent
8c3a954336
commit
72eab6cd96
30 changed files with 1486 additions and 169 deletions
|
|
@ -2188,6 +2188,7 @@ pub struct ImportExpression<'a> {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub source: Expression<'a>,
|
pub source: Expression<'a>,
|
||||||
pub arguments: Vec<'a, Expression<'a>>,
|
pub arguments: Vec<'a, Expression<'a>>,
|
||||||
|
pub phase: Option<ImportPhase>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ast(visit)]
|
#[ast(visit)]
|
||||||
|
|
@ -2198,6 +2199,7 @@ pub struct ImportDeclaration<'a> {
|
||||||
/// `None` for `import 'foo'`, `Some([])` for `import {} from 'foo'`
|
/// `None` for `import 'foo'`, `Some([])` for `import {} from 'foo'`
|
||||||
pub specifiers: Option<Vec<'a, ImportDeclarationSpecifier<'a>>>,
|
pub specifiers: Option<Vec<'a, ImportDeclarationSpecifier<'a>>>,
|
||||||
pub source: StringLiteral<'a>,
|
pub source: StringLiteral<'a>,
|
||||||
|
pub phase: Option<ImportPhase>,
|
||||||
/// Some(vec![]) for empty assertion
|
/// Some(vec![]) for empty assertion
|
||||||
#[ts]
|
#[ts]
|
||||||
pub with_clause: Option<Box<'a, WithClause<'a>>>,
|
pub with_clause: Option<Box<'a, WithClause<'a>>>,
|
||||||
|
|
@ -2206,6 +2208,19 @@ pub struct ImportDeclaration<'a> {
|
||||||
pub import_kind: ImportOrExportKind,
|
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)]
|
#[ast(visit)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[generate_derive(CloneIn, GetSpan, GetSpanMut, GetAddress, ContentEq, ContentHash, ESTree)]
|
#[generate_derive(CloneIn, GetSpan, GetSpanMut, GetAddress, ContentEq, ContentHash, ESTree)]
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -697,19 +697,24 @@ const _: () = {
|
||||||
assert!(offset_of!(AccessorProperty, type_annotation) == 88usize);
|
assert!(offset_of!(AccessorProperty, type_annotation) == 88usize);
|
||||||
assert!(offset_of!(AccessorProperty, accessibility) == 96usize);
|
assert!(offset_of!(AccessorProperty, accessibility) == 96usize);
|
||||||
|
|
||||||
assert!(size_of::<ImportExpression>() == 56usize);
|
assert!(size_of::<ImportExpression>() == 64usize);
|
||||||
assert!(align_of::<ImportExpression>() == 8usize);
|
assert!(align_of::<ImportExpression>() == 8usize);
|
||||||
assert!(offset_of!(ImportExpression, span) == 0usize);
|
assert!(offset_of!(ImportExpression, span) == 0usize);
|
||||||
assert!(offset_of!(ImportExpression, source) == 8usize);
|
assert!(offset_of!(ImportExpression, source) == 8usize);
|
||||||
assert!(offset_of!(ImportExpression, arguments) == 24usize);
|
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!(align_of::<ImportDeclaration>() == 8usize);
|
||||||
assert!(offset_of!(ImportDeclaration, span) == 0usize);
|
assert!(offset_of!(ImportDeclaration, span) == 0usize);
|
||||||
assert!(offset_of!(ImportDeclaration, specifiers) == 8usize);
|
assert!(offset_of!(ImportDeclaration, specifiers) == 8usize);
|
||||||
assert!(offset_of!(ImportDeclaration, source) == 40usize);
|
assert!(offset_of!(ImportDeclaration, source) == 40usize);
|
||||||
assert!(offset_of!(ImportDeclaration, with_clause) == 80usize);
|
assert!(offset_of!(ImportDeclaration, phase) == 80usize);
|
||||||
assert!(offset_of!(ImportDeclaration, import_kind) == 88usize);
|
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!(size_of::<ImportDeclarationSpecifier>() == 16usize);
|
||||||
assert!(align_of::<ImportDeclarationSpecifier>() == 8usize);
|
assert!(align_of::<ImportDeclarationSpecifier>() == 8usize);
|
||||||
|
|
@ -2254,19 +2259,24 @@ const _: () = {
|
||||||
assert!(offset_of!(AccessorProperty, type_annotation) == 48usize);
|
assert!(offset_of!(AccessorProperty, type_annotation) == 48usize);
|
||||||
assert!(offset_of!(AccessorProperty, accessibility) == 52usize);
|
assert!(offset_of!(AccessorProperty, accessibility) == 52usize);
|
||||||
|
|
||||||
assert!(size_of::<ImportExpression>() == 32usize);
|
assert!(size_of::<ImportExpression>() == 36usize);
|
||||||
assert!(align_of::<ImportExpression>() == 4usize);
|
assert!(align_of::<ImportExpression>() == 4usize);
|
||||||
assert!(offset_of!(ImportExpression, span) == 0usize);
|
assert!(offset_of!(ImportExpression, span) == 0usize);
|
||||||
assert!(offset_of!(ImportExpression, source) == 8usize);
|
assert!(offset_of!(ImportExpression, source) == 8usize);
|
||||||
assert!(offset_of!(ImportExpression, arguments) == 16usize);
|
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!(align_of::<ImportDeclaration>() == 4usize);
|
||||||
assert!(offset_of!(ImportDeclaration, span) == 0usize);
|
assert!(offset_of!(ImportDeclaration, span) == 0usize);
|
||||||
assert!(offset_of!(ImportDeclaration, specifiers) == 8usize);
|
assert!(offset_of!(ImportDeclaration, specifiers) == 8usize);
|
||||||
assert!(offset_of!(ImportDeclaration, source) == 24usize);
|
assert!(offset_of!(ImportDeclaration, source) == 24usize);
|
||||||
assert!(offset_of!(ImportDeclaration, with_clause) == 48usize);
|
assert!(offset_of!(ImportDeclaration, phase) == 48usize);
|
||||||
assert!(offset_of!(ImportDeclaration, import_kind) == 52usize);
|
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!(size_of::<ImportDeclarationSpecifier>() == 8usize);
|
||||||
assert!(align_of::<ImportDeclarationSpecifier>() == 4usize);
|
assert!(align_of::<ImportDeclarationSpecifier>() == 4usize);
|
||||||
|
|
|
||||||
|
|
@ -833,14 +833,18 @@ impl<'a> AstBuilder<'a> {
|
||||||
/// - span: The [`Span`] covering this node
|
/// - span: The [`Span`] covering this node
|
||||||
/// - source
|
/// - source
|
||||||
/// - arguments
|
/// - arguments
|
||||||
|
/// - phase
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn expression_import(
|
pub fn expression_import(
|
||||||
self,
|
self,
|
||||||
span: Span,
|
span: Span,
|
||||||
source: Expression<'a>,
|
source: Expression<'a>,
|
||||||
arguments: Vec<'a, Expression<'a>>,
|
arguments: Vec<'a, Expression<'a>>,
|
||||||
|
phase: Option<ImportPhase>,
|
||||||
) -> Expression<'a> {
|
) -> 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`]
|
/// Build an [`Expression::LogicalExpression`]
|
||||||
|
|
@ -6587,6 +6591,7 @@ impl<'a> AstBuilder<'a> {
|
||||||
/// - span: The [`Span`] covering this node
|
/// - span: The [`Span`] covering this node
|
||||||
/// - specifiers: `None` for `import 'foo'`, `Some([])` for `import {} from 'foo'`
|
/// - specifiers: `None` for `import 'foo'`, `Some([])` for `import {} from 'foo'`
|
||||||
/// - source
|
/// - source
|
||||||
|
/// - phase
|
||||||
/// - with_clause: Some(vec![]) for empty assertion
|
/// - with_clause: Some(vec![]) for empty assertion
|
||||||
/// - import_kind: `import type { foo } from 'bar'`
|
/// - import_kind: `import type { foo } from 'bar'`
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
@ -6595,6 +6600,7 @@ impl<'a> AstBuilder<'a> {
|
||||||
span: Span,
|
span: Span,
|
||||||
specifiers: Option<Vec<'a, ImportDeclarationSpecifier<'a>>>,
|
specifiers: Option<Vec<'a, ImportDeclarationSpecifier<'a>>>,
|
||||||
source: StringLiteral<'a>,
|
source: StringLiteral<'a>,
|
||||||
|
phase: Option<ImportPhase>,
|
||||||
with_clause: T1,
|
with_clause: T1,
|
||||||
import_kind: ImportOrExportKind,
|
import_kind: ImportOrExportKind,
|
||||||
) -> ModuleDeclaration<'a>
|
) -> ModuleDeclaration<'a>
|
||||||
|
|
@ -6605,6 +6611,7 @@ impl<'a> AstBuilder<'a> {
|
||||||
span,
|
span,
|
||||||
specifiers,
|
specifiers,
|
||||||
source,
|
source,
|
||||||
|
phase,
|
||||||
with_clause,
|
with_clause,
|
||||||
import_kind,
|
import_kind,
|
||||||
)))
|
)))
|
||||||
|
|
@ -6836,14 +6843,16 @@ impl<'a> AstBuilder<'a> {
|
||||||
/// - span: The [`Span`] covering this node
|
/// - span: The [`Span`] covering this node
|
||||||
/// - source
|
/// - source
|
||||||
/// - arguments
|
/// - arguments
|
||||||
|
/// - phase
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn import_expression(
|
pub fn import_expression(
|
||||||
self,
|
self,
|
||||||
span: Span,
|
span: Span,
|
||||||
source: Expression<'a>,
|
source: Expression<'a>,
|
||||||
arguments: Vec<'a, Expression<'a>>,
|
arguments: Vec<'a, Expression<'a>>,
|
||||||
|
phase: Option<ImportPhase>,
|
||||||
) -> ImportExpression<'a> {
|
) -> ImportExpression<'a> {
|
||||||
ImportExpression { span, source, arguments }
|
ImportExpression { span, source, arguments, phase }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build an [`ImportExpression`], and store it in the memory arena.
|
/// Build an [`ImportExpression`], and store it in the memory arena.
|
||||||
|
|
@ -6854,14 +6863,16 @@ impl<'a> AstBuilder<'a> {
|
||||||
/// - span: The [`Span`] covering this node
|
/// - span: The [`Span`] covering this node
|
||||||
/// - source
|
/// - source
|
||||||
/// - arguments
|
/// - arguments
|
||||||
|
/// - phase
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn alloc_import_expression(
|
pub fn alloc_import_expression(
|
||||||
self,
|
self,
|
||||||
span: Span,
|
span: Span,
|
||||||
source: Expression<'a>,
|
source: Expression<'a>,
|
||||||
arguments: Vec<'a, Expression<'a>>,
|
arguments: Vec<'a, Expression<'a>>,
|
||||||
|
phase: Option<ImportPhase>,
|
||||||
) -> Box<'a, ImportExpression<'a>> {
|
) -> 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`].
|
/// Build an [`ImportDeclaration`].
|
||||||
|
|
@ -6872,6 +6883,7 @@ impl<'a> AstBuilder<'a> {
|
||||||
/// - span: The [`Span`] covering this node
|
/// - span: The [`Span`] covering this node
|
||||||
/// - specifiers: `None` for `import 'foo'`, `Some([])` for `import {} from 'foo'`
|
/// - specifiers: `None` for `import 'foo'`, `Some([])` for `import {} from 'foo'`
|
||||||
/// - source
|
/// - source
|
||||||
|
/// - phase
|
||||||
/// - with_clause: Some(vec![]) for empty assertion
|
/// - with_clause: Some(vec![]) for empty assertion
|
||||||
/// - import_kind: `import type { foo } from 'bar'`
|
/// - import_kind: `import type { foo } from 'bar'`
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
@ -6880,6 +6892,7 @@ impl<'a> AstBuilder<'a> {
|
||||||
span: Span,
|
span: Span,
|
||||||
specifiers: Option<Vec<'a, ImportDeclarationSpecifier<'a>>>,
|
specifiers: Option<Vec<'a, ImportDeclarationSpecifier<'a>>>,
|
||||||
source: StringLiteral<'a>,
|
source: StringLiteral<'a>,
|
||||||
|
phase: Option<ImportPhase>,
|
||||||
with_clause: T1,
|
with_clause: T1,
|
||||||
import_kind: ImportOrExportKind,
|
import_kind: ImportOrExportKind,
|
||||||
) -> ImportDeclaration<'a>
|
) -> ImportDeclaration<'a>
|
||||||
|
|
@ -6890,6 +6903,7 @@ impl<'a> AstBuilder<'a> {
|
||||||
span,
|
span,
|
||||||
specifiers,
|
specifiers,
|
||||||
source,
|
source,
|
||||||
|
phase,
|
||||||
with_clause: with_clause.into_in(self.allocator),
|
with_clause: with_clause.into_in(self.allocator),
|
||||||
import_kind,
|
import_kind,
|
||||||
}
|
}
|
||||||
|
|
@ -6903,6 +6917,7 @@ impl<'a> AstBuilder<'a> {
|
||||||
/// - span: The [`Span`] covering this node
|
/// - span: The [`Span`] covering this node
|
||||||
/// - specifiers: `None` for `import 'foo'`, `Some([])` for `import {} from 'foo'`
|
/// - specifiers: `None` for `import 'foo'`, `Some([])` for `import {} from 'foo'`
|
||||||
/// - source
|
/// - source
|
||||||
|
/// - phase
|
||||||
/// - with_clause: Some(vec![]) for empty assertion
|
/// - with_clause: Some(vec![]) for empty assertion
|
||||||
/// - import_kind: `import type { foo } from 'bar'`
|
/// - import_kind: `import type { foo } from 'bar'`
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
@ -6911,6 +6926,7 @@ impl<'a> AstBuilder<'a> {
|
||||||
span: Span,
|
span: Span,
|
||||||
specifiers: Option<Vec<'a, ImportDeclarationSpecifier<'a>>>,
|
specifiers: Option<Vec<'a, ImportDeclarationSpecifier<'a>>>,
|
||||||
source: StringLiteral<'a>,
|
source: StringLiteral<'a>,
|
||||||
|
phase: Option<ImportPhase>,
|
||||||
with_clause: T1,
|
with_clause: T1,
|
||||||
import_kind: ImportOrExportKind,
|
import_kind: ImportOrExportKind,
|
||||||
) -> Box<'a, ImportDeclaration<'a>>
|
) -> Box<'a, ImportDeclaration<'a>>
|
||||||
|
|
@ -6918,7 +6934,7 @@ impl<'a> AstBuilder<'a> {
|
||||||
T1: IntoIn<'a, Option<Box<'a, WithClause<'a>>>>,
|
T1: IntoIn<'a, Option<Box<'a, WithClause<'a>>>>,
|
||||||
{
|
{
|
||||||
Box::new_in(
|
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,
|
self.allocator,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2225,6 +2225,7 @@ impl<'new_alloc> CloneIn<'new_alloc> for ImportExpression<'_> {
|
||||||
span: CloneIn::clone_in(&self.span, allocator),
|
span: CloneIn::clone_in(&self.span, allocator),
|
||||||
source: CloneIn::clone_in(&self.source, allocator),
|
source: CloneIn::clone_in(&self.source, allocator),
|
||||||
arguments: CloneIn::clone_in(&self.arguments, allocator),
|
arguments: CloneIn::clone_in(&self.arguments, allocator),
|
||||||
|
phase: CloneIn::clone_in(&self.phase, allocator),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2236,12 +2237,23 @@ impl<'new_alloc> CloneIn<'new_alloc> for ImportDeclaration<'_> {
|
||||||
span: CloneIn::clone_in(&self.span, allocator),
|
span: CloneIn::clone_in(&self.span, allocator),
|
||||||
specifiers: CloneIn::clone_in(&self.specifiers, allocator),
|
specifiers: CloneIn::clone_in(&self.specifiers, allocator),
|
||||||
source: CloneIn::clone_in(&self.source, allocator),
|
source: CloneIn::clone_in(&self.source, allocator),
|
||||||
|
phase: CloneIn::clone_in(&self.phase, allocator),
|
||||||
with_clause: CloneIn::clone_in(&self.with_clause, allocator),
|
with_clause: CloneIn::clone_in(&self.with_clause, allocator),
|
||||||
import_kind: CloneIn::clone_in(&self.import_kind, 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<'_> {
|
impl<'new_alloc> CloneIn<'new_alloc> for ImportDeclarationSpecifier<'_> {
|
||||||
type Cloned = ImportDeclarationSpecifier<'new_alloc>;
|
type Cloned = ImportDeclarationSpecifier<'new_alloc>;
|
||||||
fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned {
|
fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned {
|
||||||
|
|
|
||||||
|
|
@ -2239,6 +2239,7 @@ impl ContentEq for ImportExpression<'_> {
|
||||||
fn content_eq(&self, other: &Self) -> bool {
|
fn content_eq(&self, other: &Self) -> bool {
|
||||||
ContentEq::content_eq(&self.source, &other.source)
|
ContentEq::content_eq(&self.source, &other.source)
|
||||||
&& ContentEq::content_eq(&self.arguments, &other.arguments)
|
&& ContentEq::content_eq(&self.arguments, &other.arguments)
|
||||||
|
&& ContentEq::content_eq(&self.phase, &other.phase)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2246,11 +2247,18 @@ impl ContentEq for ImportDeclaration<'_> {
|
||||||
fn content_eq(&self, other: &Self) -> bool {
|
fn content_eq(&self, other: &Self) -> bool {
|
||||||
ContentEq::content_eq(&self.specifiers, &other.specifiers)
|
ContentEq::content_eq(&self.specifiers, &other.specifiers)
|
||||||
&& ContentEq::content_eq(&self.source, &other.source)
|
&& 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.with_clause, &other.with_clause)
|
||||||
&& ContentEq::content_eq(&self.import_kind, &other.import_kind)
|
&& 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<'_> {
|
impl ContentEq for ImportDeclarationSpecifier<'_> {
|
||||||
fn content_eq(&self, other: &Self) -> bool {
|
fn content_eq(&self, other: &Self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
||||||
|
|
@ -1227,6 +1227,7 @@ impl ContentHash for ImportExpression<'_> {
|
||||||
fn content_hash<H: Hasher>(&self, state: &mut H) {
|
fn content_hash<H: Hasher>(&self, state: &mut H) {
|
||||||
ContentHash::content_hash(&self.source, state);
|
ContentHash::content_hash(&self.source, state);
|
||||||
ContentHash::content_hash(&self.arguments, state);
|
ContentHash::content_hash(&self.arguments, state);
|
||||||
|
ContentHash::content_hash(&self.phase, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1234,11 +1235,18 @@ impl ContentHash for ImportDeclaration<'_> {
|
||||||
fn content_hash<H: Hasher>(&self, state: &mut H) {
|
fn content_hash<H: Hasher>(&self, state: &mut H) {
|
||||||
ContentHash::content_hash(&self.specifiers, state);
|
ContentHash::content_hash(&self.specifiers, state);
|
||||||
ContentHash::content_hash(&self.source, state);
|
ContentHash::content_hash(&self.source, state);
|
||||||
|
ContentHash::content_hash(&self.phase, state);
|
||||||
ContentHash::content_hash(&self.with_clause, state);
|
ContentHash::content_hash(&self.with_clause, state);
|
||||||
ContentHash::content_hash(&self.import_kind, 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<'_> {
|
impl ContentHash for ImportDeclarationSpecifier<'_> {
|
||||||
fn content_hash<H: Hasher>(&self, state: &mut H) {
|
fn content_hash<H: Hasher>(&self, state: &mut H) {
|
||||||
ContentHash::content_hash(&discriminant(self), state);
|
ContentHash::content_hash(&discriminant(self), state);
|
||||||
|
|
|
||||||
|
|
@ -1685,6 +1685,7 @@ impl Serialize for ImportExpression<'_> {
|
||||||
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||||
map.serialize_entry("source", &self.source)?;
|
map.serialize_entry("source", &self.source)?;
|
||||||
map.serialize_entry("arguments", &self.arguments)?;
|
map.serialize_entry("arguments", &self.arguments)?;
|
||||||
|
map.serialize_entry("phase", &self.phase)?;
|
||||||
map.end()
|
map.end()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1696,12 +1697,22 @@ impl Serialize for ImportDeclaration<'_> {
|
||||||
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||||
map.serialize_entry("specifiers", &self.specifiers)?;
|
map.serialize_entry("specifiers", &self.specifiers)?;
|
||||||
map.serialize_entry("source", &self.source)?;
|
map.serialize_entry("source", &self.source)?;
|
||||||
|
map.serialize_entry("phase", &self.phase)?;
|
||||||
map.serialize_entry("withClause", &self.with_clause)?;
|
map.serialize_entry("withClause", &self.with_clause)?;
|
||||||
map.serialize_entry("importKind", &self.import_kind)?;
|
map.serialize_entry("importKind", &self.import_kind)?;
|
||||||
map.end()
|
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<'_> {
|
impl Serialize for ImportDeclarationSpecifier<'_> {
|
||||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
||||||
|
|
@ -732,6 +732,10 @@ impl Gen for ImportDeclaration<'_> {
|
||||||
if self.import_kind.is_type() {
|
if self.import_kind.is_type() {
|
||||||
p.print_str(" 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 let Some(specifiers) = &self.specifiers {
|
||||||
if specifiers.is_empty() {
|
if specifiers.is_empty() {
|
||||||
p.print_soft_space();
|
p.print_soft_space();
|
||||||
|
|
@ -1990,7 +1994,11 @@ impl GenExpr for ImportExpression<'_> {
|
||||||
p.wrap(wrap, |p| {
|
p.wrap(wrap, |p| {
|
||||||
p.print_space_before_identifier();
|
p.print_space_before_identifier();
|
||||||
p.add_source_mapping(self.span);
|
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 {
|
if has_comment {
|
||||||
p.indent();
|
p.indent();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
||||||
decl.span,
|
decl.span,
|
||||||
Some(new_specifiers),
|
Some(new_specifiers),
|
||||||
decl.source.clone(),
|
decl.source.clone(),
|
||||||
|
None,
|
||||||
decl.with_clause.clone_in(self.ast.allocator),
|
decl.with_clause.clone_in(self.ast.allocator),
|
||||||
decl.import_kind,
|
decl.import_kind,
|
||||||
))
|
))
|
||||||
|
|
|
||||||
|
|
@ -456,6 +456,16 @@ pub fn duplicate_export(x0: &str, span1: Span, span2: Span) -> OxcDiagnostic {
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cold]
|
||||||
|
pub fn import_meta(span: Span) -> OxcDiagnostic {
|
||||||
|
OxcDiagnostic::error("The only valid meta property for import is import.meta").with_label(span)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cold]
|
||||||
|
pub fn new_target(span: Span) -> OxcDiagnostic {
|
||||||
|
OxcDiagnostic::error("The only valid meta property for new is new.target").with_label(span)
|
||||||
|
}
|
||||||
|
|
||||||
// ================================= MODIFIERS =================================
|
// ================================= MODIFIERS =================================
|
||||||
|
|
||||||
#[cold]
|
#[cold]
|
||||||
|
|
|
||||||
|
|
@ -184,15 +184,7 @@ impl<'a> ParserImpl<'a> {
|
||||||
}
|
}
|
||||||
Kind::New => self.parse_new_expression(),
|
Kind::New => self.parse_new_expression(),
|
||||||
Kind::Super => Ok(self.parse_super()),
|
Kind::Super => Ok(self.parse_super()),
|
||||||
Kind::Import => {
|
Kind::Import => self.parse_import_meta_or_call(),
|
||||||
let span = self.start_span();
|
|
||||||
let identifier = self.parse_keyword_identifier(Kind::Import);
|
|
||||||
match self.cur_kind() {
|
|
||||||
Kind::Dot => self.parse_meta_property(span, identifier),
|
|
||||||
Kind::LParen => self.parse_import_expression(span),
|
|
||||||
_ => Err(self.unexpected()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Kind::LParen => self.parse_parenthesized_expression(span),
|
Kind::LParen => self.parse_parenthesized_expression(span),
|
||||||
Kind::Slash | Kind::SlashEq => self
|
Kind::Slash | Kind::SlashEq => self
|
||||||
.parse_literal_regexp()
|
.parse_literal_regexp()
|
||||||
|
|
@ -561,24 +553,40 @@ impl<'a> ParserImpl<'a> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Section 13.3 Meta Property
|
/// Section 13.3 ImportCall or ImportMeta
|
||||||
fn parse_meta_property(
|
fn parse_import_meta_or_call(&mut self) -> Result<Expression<'a>> {
|
||||||
&mut self,
|
let span = self.start_span();
|
||||||
span: Span,
|
let meta = self.parse_keyword_identifier(Kind::Import);
|
||||||
meta: IdentifierName<'a>,
|
match self.cur_kind() {
|
||||||
) -> Result<Expression<'a>> {
|
Kind::Dot => {
|
||||||
self.bump_any(); // bump `.`
|
self.bump_any(); // bump `.`
|
||||||
let kind = self.cur_kind();
|
match self.cur_kind() {
|
||||||
let property = match self.cur_kind() {
|
// `import.meta`
|
||||||
Kind::Meta => self.parse_keyword_identifier(Kind::Meta),
|
Kind::Meta => {
|
||||||
Kind::Target => self.parse_keyword_identifier(Kind::Target),
|
let property = self.parse_keyword_identifier(Kind::Meta);
|
||||||
_ => self.parse_identifier_name()?,
|
let span = self.end_span(span);
|
||||||
};
|
self.module_record_builder.visit_import_meta(span);
|
||||||
let span = self.end_span(span);
|
Ok(self.ast.expression_meta_property(span, meta, property))
|
||||||
if kind == Kind::Meta {
|
}
|
||||||
self.module_record_builder.visit_import_meta(span);
|
// `import.source(expr)`
|
||||||
|
Kind::Source => {
|
||||||
|
self.bump_any();
|
||||||
|
self.parse_import_expression(span, Some(ImportPhase::Source))
|
||||||
|
}
|
||||||
|
// `import.defer(expr)`
|
||||||
|
Kind::Defer => {
|
||||||
|
self.bump_any();
|
||||||
|
self.parse_import_expression(span, Some(ImportPhase::Defer))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.bump_any();
|
||||||
|
Err(diagnostics::import_meta(self.end_span(span)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Kind::LParen => self.parse_import_expression(span, None),
|
||||||
|
_ => Err(self.unexpected()),
|
||||||
}
|
}
|
||||||
Ok(self.ast.expression_meta_property(span, meta, property))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Section 13.3 Left-Hand-Side Expression
|
/// Section 13.3 Left-Hand-Side Expression
|
||||||
|
|
@ -760,8 +768,15 @@ impl<'a> ParserImpl<'a> {
|
||||||
fn parse_new_expression(&mut self) -> Result<Expression<'a>> {
|
fn parse_new_expression(&mut self) -> Result<Expression<'a>> {
|
||||||
let span = self.start_span();
|
let span = self.start_span();
|
||||||
let identifier = self.parse_keyword_identifier(Kind::New);
|
let identifier = self.parse_keyword_identifier(Kind::New);
|
||||||
if self.at(Kind::Dot) {
|
|
||||||
return self.parse_meta_property(span, identifier);
|
if self.eat(Kind::Dot) {
|
||||||
|
return if self.at(Kind::Target) {
|
||||||
|
let property = self.parse_keyword_identifier(Kind::Target);
|
||||||
|
Ok(self.ast.expression_meta_property(self.end_span(span), identifier, property))
|
||||||
|
} else {
|
||||||
|
self.bump_any();
|
||||||
|
Err(diagnostics::new_target(self.end_span(span)))
|
||||||
|
};
|
||||||
}
|
}
|
||||||
let rhs_span = self.start_span();
|
let rhs_span = self.start_span();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,17 @@ use crate::{diagnostics, lexer::Kind, modifiers::Modifiers, Context, ParserImpl}
|
||||||
impl<'a> ParserImpl<'a> {
|
impl<'a> ParserImpl<'a> {
|
||||||
/// [Import Call](https://tc39.es/ecma262/#sec-import-calls)
|
/// [Import Call](https://tc39.es/ecma262/#sec-import-calls)
|
||||||
/// `ImportCall` : import ( `AssignmentExpression` )
|
/// `ImportCall` : import ( `AssignmentExpression` )
|
||||||
pub(crate) fn parse_import_expression(&mut self, span: Span) -> Result<Expression<'a>> {
|
pub(crate) fn parse_import_expression(
|
||||||
self.bump_any(); // advance '('
|
&mut self,
|
||||||
|
span: Span,
|
||||||
|
phase: Option<ImportPhase>,
|
||||||
|
) -> Result<Expression<'a>> {
|
||||||
|
self.expect(Kind::LParen)?;
|
||||||
|
|
||||||
|
if self.eat(Kind::RParen) {
|
||||||
|
return Err(oxc_diagnostics::OxcDiagnostic::error("import() requires a specifier.")
|
||||||
|
.with_label(self.end_span(span)));
|
||||||
|
}
|
||||||
|
|
||||||
let has_in = self.ctx.has_in();
|
let has_in = self.ctx.has_in();
|
||||||
self.ctx = self.ctx.and_in(true);
|
self.ctx = self.ctx.and_in(true);
|
||||||
|
|
@ -25,7 +34,7 @@ impl<'a> ParserImpl<'a> {
|
||||||
self.ctx = self.ctx.and_in(has_in);
|
self.ctx = self.ctx.and_in(has_in);
|
||||||
self.bump(Kind::Comma);
|
self.bump(Kind::Comma);
|
||||||
self.expect(Kind::RParen)?;
|
self.expect(Kind::RParen)?;
|
||||||
Ok(self.ast.expression_import(self.end_span(span), expression, arguments))
|
Ok(self.ast.expression_import(self.end_span(span), expression, arguments, phase))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Section 16.2.2 Import Declaration
|
/// Section 16.2.2 Import Declaration
|
||||||
|
|
@ -45,7 +54,22 @@ impl<'a> ParserImpl<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// `import type ...`
|
// `import type ...`
|
||||||
let import_kind = self.parse_import_or_export_kind();
|
// `import source ...`
|
||||||
|
// `import defer ...`
|
||||||
|
let mut import_kind = ImportOrExportKind::Value;
|
||||||
|
let mut phase = None;
|
||||||
|
match self.cur_kind() {
|
||||||
|
Kind::Source if self.peek_kind().is_binding_identifier() => {
|
||||||
|
self.bump_any();
|
||||||
|
phase = Some(ImportPhase::Source);
|
||||||
|
}
|
||||||
|
Kind::Defer if self.peek_at(Kind::Star) => {
|
||||||
|
self.bump_any();
|
||||||
|
phase = Some(ImportPhase::Defer);
|
||||||
|
}
|
||||||
|
Kind::Type if self.is_ts => import_kind = self.parse_import_or_export_kind(),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
let specifiers = if self.at(Kind::Str) {
|
let specifiers = if self.at(Kind::Str) {
|
||||||
// import "source"
|
// import "source"
|
||||||
|
|
@ -64,6 +88,7 @@ impl<'a> ParserImpl<'a> {
|
||||||
span,
|
span,
|
||||||
specifiers,
|
specifiers,
|
||||||
source,
|
source,
|
||||||
|
phase,
|
||||||
with_clause,
|
with_clause,
|
||||||
import_kind,
|
import_kind,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -560,6 +560,7 @@ ascii_identifier_handler!(L_D(id_without_first_char) match id_without_first_char
|
||||||
"eclare" => Kind::Declare,
|
"eclare" => Kind::Declare,
|
||||||
"efault" => Kind::Default,
|
"efault" => Kind::Default,
|
||||||
"ebugger" => Kind::Debugger,
|
"ebugger" => Kind::Debugger,
|
||||||
|
"efer" => Kind::Defer,
|
||||||
_ => Kind::Ident,
|
_ => Kind::Ident,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -655,6 +656,7 @@ ascii_identifier_handler!(L_S(id_without_first_char) match id_without_first_char
|
||||||
"ymbol" => Kind::Symbol,
|
"ymbol" => Kind::Symbol,
|
||||||
"tring" => Kind::String,
|
"tring" => Kind::String,
|
||||||
"atisfies" => Kind::Satisfies,
|
"atisfies" => Kind::Satisfies,
|
||||||
|
"ource" => Kind::Source,
|
||||||
_ => Kind::Ident,
|
_ => Kind::Ident,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,8 @@ pub enum Kind {
|
||||||
Set,
|
Set,
|
||||||
Target, // new.target
|
Target, // new.target
|
||||||
Accessor, // keyword from https://github.com/tc39/proposal-decorators
|
Accessor, // keyword from https://github.com/tc39/proposal-decorators
|
||||||
|
Source, // import.source https://github.com/tc39/proposal-source-phase-imports
|
||||||
|
Defer, // import.defer https://github.com/tc39/proposal-defer-import-eval
|
||||||
// TypeScript Contextual Keywords
|
// TypeScript Contextual Keywords
|
||||||
Abstract,
|
Abstract,
|
||||||
As,
|
As,
|
||||||
|
|
@ -375,7 +377,9 @@ impl Kind {
|
||||||
matches!(self, Async | From | Get | Meta | Of | Set | Target | Accessor | Abstract | As | Asserts
|
matches!(self, Async | From | Get | Meta | Of | Set | Target | Accessor | Abstract | As | Asserts
|
||||||
| Assert | Any | Boolean | Constructor | Declare | Infer | Intrinsic | Is | KeyOf | Module
|
| Assert | Any | Boolean | Constructor | Declare | Infer | Intrinsic | Is | KeyOf | Module
|
||||||
| Namespace | Never | Out | Readonly | Require | Number | Object | Satisfies | String
|
| Namespace | Never | Out | Readonly | Require | Number | Object | Satisfies | String
|
||||||
| Symbol | Type | Undefined | Unique | Unknown | Using | Global | BigInt | Override)
|
| Symbol | Type | Undefined | Unique | Unknown | Using | Global | BigInt | Override
|
||||||
|
| Source | Defer
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
|
|
@ -455,6 +459,7 @@ impl Kind {
|
||||||
"using" => Using,
|
"using" => Using,
|
||||||
"while" => While,
|
"while" => While,
|
||||||
"yield" => Yield,
|
"yield" => Yield,
|
||||||
|
"defer" => Defer,
|
||||||
|
|
||||||
"assert" => Assert,
|
"assert" => Assert,
|
||||||
"bigint" => BigInt,
|
"bigint" => BigInt,
|
||||||
|
|
@ -474,6 +479,7 @@ impl Kind {
|
||||||
"target" => Target,
|
"target" => Target,
|
||||||
"typeof" => Typeof,
|
"typeof" => Typeof,
|
||||||
"unique" => Unique,
|
"unique" => Unique,
|
||||||
|
"source" => Source,
|
||||||
|
|
||||||
"asserts" => Asserts,
|
"asserts" => Asserts,
|
||||||
"boolean" => Boolean,
|
"boolean" => Boolean,
|
||||||
|
|
@ -566,6 +572,8 @@ impl Kind {
|
||||||
Override => "override",
|
Override => "override",
|
||||||
Type => "type",
|
Type => "type",
|
||||||
Target => "target",
|
Target => "target",
|
||||||
|
Source => "source",
|
||||||
|
Defer => "defer",
|
||||||
Implements => "implements",
|
Implements => "implements",
|
||||||
Interface => "interface",
|
Interface => "interface",
|
||||||
Package => "package",
|
Package => "package",
|
||||||
|
|
|
||||||
|
|
@ -365,30 +365,18 @@ fn new_target(span: Span) -> OxcDiagnostic {
|
||||||
.with_label(span)
|
.with_label(span)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_target_property(span: Span) -> OxcDiagnostic {
|
|
||||||
OxcDiagnostic::error("The only valid meta property for new is new.target").with_label(span)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn import_meta(span: Span) -> OxcDiagnostic {
|
fn import_meta(span: Span) -> OxcDiagnostic {
|
||||||
OxcDiagnostic::error("Unexpected import.meta expression")
|
OxcDiagnostic::error("Unexpected import.meta expression")
|
||||||
.with_help("import.meta is only allowed in module code")
|
.with_help("import.meta is only allowed in module code")
|
||||||
.with_label(span)
|
.with_label(span)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn import_meta_property(span: Span) -> OxcDiagnostic {
|
|
||||||
OxcDiagnostic::error("The only valid meta property for import is import.meta").with_label(span)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn check_meta_property<'a>(prop: &MetaProperty, node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
|
pub fn check_meta_property<'a>(prop: &MetaProperty, node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
|
||||||
match prop.meta.name.as_str() {
|
match prop.meta.name.as_str() {
|
||||||
"import" => {
|
"import" => {
|
||||||
if prop.property.name == "meta" {
|
if prop.property.name == "meta" && ctx.source_type.is_script() {
|
||||||
if ctx.source_type.is_script() {
|
ctx.error(import_meta(prop.span));
|
||||||
return ctx.error(import_meta(prop.span));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
ctx.error(import_meta_property(prop.span));
|
|
||||||
}
|
}
|
||||||
"new" => {
|
"new" => {
|
||||||
if prop.property.name == "target" {
|
if prop.property.name == "target" {
|
||||||
|
|
@ -405,11 +393,9 @@ pub fn check_meta_property<'a>(prop: &MetaProperty, node: &AstNode<'a>, ctx: &Se
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !in_function_scope {
|
if !in_function_scope {
|
||||||
return ctx.error(new_target(prop.span));
|
ctx.error(new_target(prop.span));
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
ctx.error(new_target_property(prop.span));
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -215,6 +215,7 @@ impl<'a> ModuleImportsStore<'a> {
|
||||||
SPAN,
|
SPAN,
|
||||||
Some(specifiers),
|
Some(specifiers),
|
||||||
ctx.ast.string_literal(SPAN, source, None),
|
ctx.ast.string_literal(SPAN, source, None),
|
||||||
|
None,
|
||||||
NONE,
|
NONE,
|
||||||
ImportOrExportKind::Value,
|
ImportOrExportKind::Value,
|
||||||
))
|
))
|
||||||
|
|
|
||||||
|
|
@ -202,7 +202,7 @@ impl<'a> InjectGlobalVariables<'a> {
|
||||||
let kind = ImportOrExportKind::Value;
|
let kind = ImportOrExportKind::Value;
|
||||||
let import_decl = self
|
let import_decl = self
|
||||||
.ast
|
.ast
|
||||||
.module_declaration_import_declaration(SPAN, specifiers, source, NONE, kind);
|
.module_declaration_import_declaration(SPAN, specifiers, source, None, NONE, kind);
|
||||||
Statement::from(import_decl)
|
Statement::from(import_decl)
|
||||||
});
|
});
|
||||||
program.body.splice(0..0, imports);
|
program.body.splice(0..0, imports);
|
||||||
|
|
|
||||||
|
|
@ -9260,6 +9260,7 @@ pub(crate) const OFFSET_IMPORT_EXPRESSION_SPAN: usize = offset_of!(ImportExpress
|
||||||
pub(crate) const OFFSET_IMPORT_EXPRESSION_SOURCE: usize = offset_of!(ImportExpression, source);
|
pub(crate) const OFFSET_IMPORT_EXPRESSION_SOURCE: usize = offset_of!(ImportExpression, source);
|
||||||
pub(crate) const OFFSET_IMPORT_EXPRESSION_ARGUMENTS: usize =
|
pub(crate) const OFFSET_IMPORT_EXPRESSION_ARGUMENTS: usize =
|
||||||
offset_of!(ImportExpression, arguments);
|
offset_of!(ImportExpression, arguments);
|
||||||
|
pub(crate) const OFFSET_IMPORT_EXPRESSION_PHASE: usize = offset_of!(ImportExpression, phase);
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
|
@ -9281,6 +9282,14 @@ impl<'a, 't> ImportExpressionWithoutSource<'a, 't> {
|
||||||
as *const Vec<'a, Expression<'a>>)
|
as *const Vec<'a, Expression<'a>>)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn phase(self) -> &'t Option<ImportPhase> {
|
||||||
|
unsafe {
|
||||||
|
&*((self.0 as *const u8).add(OFFSET_IMPORT_EXPRESSION_PHASE)
|
||||||
|
as *const Option<ImportPhase>)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 't> GetAddress for ImportExpressionWithoutSource<'a, 't> {
|
impl<'a, 't> GetAddress for ImportExpressionWithoutSource<'a, 't> {
|
||||||
|
|
@ -9309,6 +9318,14 @@ impl<'a, 't> ImportExpressionWithoutArguments<'a, 't> {
|
||||||
&*((self.0 as *const u8).add(OFFSET_IMPORT_EXPRESSION_SOURCE) as *const Expression<'a>)
|
&*((self.0 as *const u8).add(OFFSET_IMPORT_EXPRESSION_SOURCE) as *const Expression<'a>)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn phase(self) -> &'t Option<ImportPhase> {
|
||||||
|
unsafe {
|
||||||
|
&*((self.0 as *const u8).add(OFFSET_IMPORT_EXPRESSION_PHASE)
|
||||||
|
as *const Option<ImportPhase>)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 't> GetAddress for ImportExpressionWithoutArguments<'a, 't> {
|
impl<'a, 't> GetAddress for ImportExpressionWithoutArguments<'a, 't> {
|
||||||
|
|
@ -9322,6 +9339,7 @@ pub(crate) const OFFSET_IMPORT_DECLARATION_SPAN: usize = offset_of!(ImportDeclar
|
||||||
pub(crate) const OFFSET_IMPORT_DECLARATION_SPECIFIERS: usize =
|
pub(crate) const OFFSET_IMPORT_DECLARATION_SPECIFIERS: usize =
|
||||||
offset_of!(ImportDeclaration, specifiers);
|
offset_of!(ImportDeclaration, specifiers);
|
||||||
pub(crate) const OFFSET_IMPORT_DECLARATION_SOURCE: usize = offset_of!(ImportDeclaration, source);
|
pub(crate) const OFFSET_IMPORT_DECLARATION_SOURCE: usize = offset_of!(ImportDeclaration, source);
|
||||||
|
pub(crate) const OFFSET_IMPORT_DECLARATION_PHASE: usize = offset_of!(ImportDeclaration, phase);
|
||||||
pub(crate) const OFFSET_IMPORT_DECLARATION_WITH_CLAUSE: usize =
|
pub(crate) const OFFSET_IMPORT_DECLARATION_WITH_CLAUSE: usize =
|
||||||
offset_of!(ImportDeclaration, with_clause);
|
offset_of!(ImportDeclaration, with_clause);
|
||||||
pub(crate) const OFFSET_IMPORT_DECLARATION_IMPORT_KIND: usize =
|
pub(crate) const OFFSET_IMPORT_DECLARATION_IMPORT_KIND: usize =
|
||||||
|
|
@ -9348,6 +9366,14 @@ impl<'a, 't> ImportDeclarationWithoutSpecifiers<'a, 't> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn phase(self) -> &'t Option<ImportPhase> {
|
||||||
|
unsafe {
|
||||||
|
&*((self.0 as *const u8).add(OFFSET_IMPORT_DECLARATION_PHASE)
|
||||||
|
as *const Option<ImportPhase>)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_clause(self) -> &'t Option<Box<'a, WithClause<'a>>> {
|
pub fn with_clause(self) -> &'t Option<Box<'a, WithClause<'a>>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
@ -9393,6 +9419,14 @@ impl<'a, 't> ImportDeclarationWithoutSource<'a, 't> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn phase(self) -> &'t Option<ImportPhase> {
|
||||||
|
unsafe {
|
||||||
|
&*((self.0 as *const u8).add(OFFSET_IMPORT_DECLARATION_PHASE)
|
||||||
|
as *const Option<ImportPhase>)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_clause(self) -> &'t Option<Box<'a, WithClause<'a>>> {
|
pub fn with_clause(self) -> &'t Option<Box<'a, WithClause<'a>>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
@ -9446,6 +9480,14 @@ impl<'a, 't> ImportDeclarationWithoutWithClause<'a, 't> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn phase(self) -> &'t Option<ImportPhase> {
|
||||||
|
unsafe {
|
||||||
|
&*((self.0 as *const u8).add(OFFSET_IMPORT_DECLARATION_PHASE)
|
||||||
|
as *const Option<ImportPhase>)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn import_kind(self) -> &'t ImportOrExportKind {
|
pub fn import_kind(self) -> &'t ImportOrExportKind {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
||||||
4
npm/oxc-types/types.d.ts
vendored
4
npm/oxc-types/types.d.ts
vendored
|
|
@ -905,16 +905,20 @@ export interface ImportExpression extends Span {
|
||||||
type: 'ImportExpression';
|
type: 'ImportExpression';
|
||||||
source: Expression;
|
source: Expression;
|
||||||
arguments: Array<Expression>;
|
arguments: Array<Expression>;
|
||||||
|
phase: ImportPhase | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ImportDeclaration extends Span {
|
export interface ImportDeclaration extends Span {
|
||||||
type: 'ImportDeclaration';
|
type: 'ImportDeclaration';
|
||||||
specifiers: Array<ImportDeclarationSpecifier> | null;
|
specifiers: Array<ImportDeclarationSpecifier> | null;
|
||||||
source: StringLiteral;
|
source: StringLiteral;
|
||||||
|
phase: ImportPhase | null;
|
||||||
withClause: WithClause | null;
|
withClause: WithClause | null;
|
||||||
importKind: ImportOrExportKind;
|
importKind: ImportOrExportKind;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ImportPhase = 'source' | 'defer';
|
||||||
|
|
||||||
export type ImportDeclarationSpecifier = ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier;
|
export type ImportDeclarationSpecifier = ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier;
|
||||||
|
|
||||||
export interface ImportSpecifier extends Span {
|
export interface ImportSpecifier extends Span {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
commit: eefc5cf3
|
commit: eefc5cf3
|
||||||
|
|
||||||
codegen_test262 Summary:
|
codegen_test262 Summary:
|
||||||
AST Parsed : 44037/44037 (100.00%)
|
AST Parsed : 44169/44169 (100.00%)
|
||||||
Positive Passed: 44037/44037 (100.00%)
|
Positive Passed: 44169/44169 (100.00%)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
commit: eefc5cf3
|
commit: eefc5cf3
|
||||||
|
|
||||||
minifier_test262 Summary:
|
minifier_test262 Summary:
|
||||||
AST Parsed : 44037/44037 (100.00%)
|
AST Parsed : 44169/44169 (100.00%)
|
||||||
Positive Passed: 44037/44037 (100.00%)
|
Positive Passed: 44169/44169 (100.00%)
|
||||||
|
|
|
||||||
|
|
@ -5680,10 +5680,10 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
|
||||||
· ╰── `)` expected
|
· ╰── `)` expected
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
× Unexpected token
|
× import() requires a specifier.
|
||||||
╭─[babel/packages/babel-parser/test/fixtures/es2020/dynamic-import/no-args/input.js:1:8]
|
╭─[babel/packages/babel-parser/test/fixtures/es2020/dynamic-import/no-args/input.js:1:1]
|
||||||
1 │ import();
|
1 │ import();
|
||||||
· ─
|
· ────────
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
× The only valid meta property for import is import.meta
|
× The only valid meta property for import is import.meta
|
||||||
|
|
@ -5719,10 +5719,10 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
|
||||||
· ╰── `)` expected
|
· ╰── `)` expected
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
× Unexpected token
|
× import() requires a specifier.
|
||||||
╭─[babel/packages/babel-parser/test/fixtures/es2020/dynamic-import-createImportExpression-false/no-args/input.js:1:8]
|
╭─[babel/packages/babel-parser/test/fixtures/es2020/dynamic-import-createImportExpression-false/no-args/input.js:1:1]
|
||||||
1 │ import();
|
1 │ import();
|
||||||
· ─
|
· ────────
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
× Unexpected import.meta expression
|
× Unexpected import.meta expression
|
||||||
|
|
@ -8929,10 +8929,10 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
|
||||||
· ─────────
|
· ─────────
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
× Unexpected token
|
× The only valid meta property for new is new.target
|
||||||
╭─[babel/packages/babel-parser/test/fixtures/esprima/es2015-meta-property/invalid-dots/input.js:1:30]
|
╭─[babel/packages/babel-parser/test/fixtures/esprima/es2015-meta-property/invalid-dots/input.js:1:26]
|
||||||
1 │ var x = function() { y = new..target; }
|
1 │ var x = function() { y = new..target; }
|
||||||
· ─
|
· ─────
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
× Unexpected new.target expression
|
× Unexpected new.target expression
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,7 +1,7 @@
|
||||||
commit: d85767ab
|
commit: d85767ab
|
||||||
|
|
||||||
parser_typescript Summary:
|
parser_typescript Summary:
|
||||||
AST Parsed : 6495/6503 (99.88%)
|
AST Parsed : 6494/6503 (99.86%)
|
||||||
Positive Passed: 6483/6503 (99.69%)
|
Positive Passed: 6483/6503 (99.69%)
|
||||||
Negative Passed: 1239/5747 (21.56%)
|
Negative Passed: 1239/5747 (21.56%)
|
||||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ClassDeclaration10.ts
|
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ClassDeclaration10.ts
|
||||||
|
|
@ -4764,13 +4764,6 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/es2019/import
|
||||||
· ────────────
|
· ────────────
|
||||||
3 │ export let z = import.import.import.malkovich;
|
3 │ export let z = import.import.import.malkovich;
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
× The only valid meta property for import is import.meta
|
|
||||||
╭─[typescript/tests/cases/conformance/es2019/importMeta/importMeta.ts:3:16]
|
|
||||||
2 │ export let y = import.metal;
|
|
||||||
3 │ export let z = import.import.import.malkovich;
|
|
||||||
· ─────────────
|
|
||||||
╰────
|
|
||||||
Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/es6/moduleExportsSystem/topLevelVarHoistingCommonJS.ts
|
Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/es6/moduleExportsSystem/topLevelVarHoistingCommonJS.ts
|
||||||
|
|
||||||
× 'with' statements are not allowed
|
× 'with' statements are not allowed
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
commit: eefc5cf3
|
commit: eefc5cf3
|
||||||
|
|
||||||
semantic_test262 Summary:
|
semantic_test262 Summary:
|
||||||
AST Parsed : 44037/44037 (100.00%)
|
AST Parsed : 44169/44169 (100.00%)
|
||||||
Positive Passed: 43508/44037 (98.80%)
|
Positive Passed: 43637/44169 (98.80%)
|
||||||
tasks/coverage/test262/test/annexB/language/function-code/if-decl-else-decl-a-func-block-scoping.js
|
tasks/coverage/test262/test/annexB/language/function-code/if-decl-else-decl-a-func-block-scoping.js
|
||||||
semantic error: Symbol scope ID mismatch for "f":
|
semantic error: Symbol scope ID mismatch for "f":
|
||||||
after transform: SymbolId(3): ScopeId(4294967294)
|
after transform: SymbolId(3): ScopeId(4294967294)
|
||||||
|
|
@ -3740,6 +3740,15 @@ Unresolved references mismatch:
|
||||||
after transform: ["$DONE", "Object", "assert", "require"]
|
after transform: ["$DONE", "Object", "assert", "require"]
|
||||||
rebuilt : ["$DONE", "Object", "_superprop_getMethod", "assert", "require"]
|
rebuilt : ["$DONE", "Object", "_superprop_getMethod", "assert", "require"]
|
||||||
|
|
||||||
|
tasks/coverage/test262/test/language/import/import-defer/errors/resolution-error/import-defer-of-missing-module-fails.js
|
||||||
|
semantic error: Expected `from` but found `string`
|
||||||
|
|
||||||
|
tasks/coverage/test262/test/language/import/import-defer/errors/syntax-error/import-defer-of-syntax-error-fails.js
|
||||||
|
semantic error: Expected `from` but found `string`
|
||||||
|
|
||||||
|
tasks/coverage/test262/test/language/module-code/source-phase-import/import-source-binding-name.js
|
||||||
|
semantic error: Expected `from` but found `string`
|
||||||
|
|
||||||
tasks/coverage/test262/test/language/module-code/top-level-await/syntax/for-await-await-expr-func-expression.js
|
tasks/coverage/test262/test/language/module-code/top-level-await/syntax/for-await-await-expr-func-expression.js
|
||||||
semantic error: Scope children mismatch:
|
semantic error: Scope children mismatch:
|
||||||
after transform: ScopeId(14): [ScopeId(1)]
|
after transform: ScopeId(14): [ScopeId(1)]
|
||||||
|
|
|
||||||
|
|
@ -42303,7 +42303,6 @@ rebuilt : []
|
||||||
|
|
||||||
tasks/coverage/typescript/tests/cases/conformance/es2019/importMeta/importMeta.ts
|
tasks/coverage/typescript/tests/cases/conformance/es2019/importMeta/importMeta.ts
|
||||||
semantic error: The only valid meta property for import is import.meta
|
semantic error: The only valid meta property for import is import.meta
|
||||||
The only valid meta property for import is import.meta
|
|
||||||
|
|
||||||
tasks/coverage/typescript/tests/cases/conformance/es2019/importMeta/importMetaNarrowing.ts
|
tasks/coverage/typescript/tests/cases/conformance/es2019/importMeta/importMetaNarrowing.ts
|
||||||
semantic error: Scope children mismatch:
|
semantic error: Scope children mismatch:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
commit: eefc5cf3
|
commit: eefc5cf3
|
||||||
|
|
||||||
transformer_test262 Summary:
|
transformer_test262 Summary:
|
||||||
AST Parsed : 44037/44037 (100.00%)
|
AST Parsed : 44169/44169 (100.00%)
|
||||||
Positive Passed: 44037/44037 (100.00%)
|
Positive Passed: 44169/44169 (100.00%)
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,8 @@ static SKIP_FEATURES: &[&str] = &[
|
||||||
// stage 3
|
// stage 3
|
||||||
"decorators",
|
"decorators",
|
||||||
"explicit-resource-management",
|
"explicit-resource-management",
|
||||||
|
"source-phase-imports",
|
||||||
|
"import-defer",
|
||||||
];
|
];
|
||||||
|
|
||||||
static SKIP_INCLUDES: &[&str] = &[
|
static SKIP_INCLUDES: &[&str] = &[
|
||||||
|
|
|
||||||
|
|
@ -104,14 +104,10 @@ impl Case for Test262Case {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn skip_test_case(&self) -> bool {
|
fn skip_test_case(&self) -> bool {
|
||||||
[
|
false
|
||||||
// stage 3 https://github.com/tc39/proposal-source-phase-imports
|
// []
|
||||||
"source-phase-imports",
|
// .iter()
|
||||||
// stage 2.7 https://github.com/tc39/proposal-defer-import-eval
|
// .any(|feature| self.meta.features.iter().any(|f| **f == **feature))
|
||||||
"import-defer",
|
|
||||||
]
|
|
||||||
.iter()
|
|
||||||
.any(|feature| self.meta.features.iter().any(|f| **f == **feature))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unless configured otherwise (via the noStrict, onlyStrict, module, or raw flags),
|
// Unless configured otherwise (via the noStrict, onlyStrict, module, or raw flags),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue