Boshen 2024-12-06 16:15:52 +00:00
parent 8c3a954336
commit 72eab6cd96
30 changed files with 1486 additions and 169 deletions

View file

@ -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)]
@ -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>>>,
@ -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)]

View file

@ -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",
}
}
}

View file

@ -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);
@ -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);

View file

@ -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`]
@ -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]
@ -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>
@ -6605,6 +6611,7 @@ impl<'a> AstBuilder<'a> {
span,
specifiers,
source,
phase,
with_clause,
import_kind,
)))
@ -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.
@ -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`].
@ -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]
@ -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>
@ -6890,6 +6903,7 @@ impl<'a> AstBuilder<'a> {
span,
specifiers,
source,
phase,
with_clause: with_clause.into_in(self.allocator),
import_kind,
}
@ -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]
@ -6911,6 +6926,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,
) -> Box<'a, ImportDeclaration<'a>>
@ -6918,7 +6934,7 @@ impl<'a> AstBuilder<'a> {
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,
)
}

View file

@ -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),
}
}
}
@ -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 {

View file

@ -2239,6 +2239,7 @@ 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)
}
}
@ -2246,11 +2247,18 @@ 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 {

View file

@ -1227,6 +1227,7 @@ 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);
}
}
@ -1234,11 +1235,18 @@ 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);

View file

@ -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()
}
}
@ -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 {

View file

@ -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();
@ -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();
}

View file

@ -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,
))

View file

@ -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 =================================
#[cold]

View file

@ -184,15 +184,7 @@ impl<'a> ParserImpl<'a> {
}
Kind::New => self.parse_new_expression(),
Kind::Super => Ok(self.parse_super()),
Kind::Import => {
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::Import => self.parse_import_meta_or_call(),
Kind::LParen => self.parse_parenthesized_expression(span),
Kind::Slash | Kind::SlashEq => self
.parse_literal_regexp()
@ -561,24 +553,40 @@ impl<'a> ParserImpl<'a> {
)
}
/// Section 13.3 Meta Property
fn parse_meta_property(
&mut self,
span: Span,
meta: IdentifierName<'a>,
) -> Result<Expression<'a>> {
self.bump_any(); // bump `.`
let kind = self.cur_kind();
let property = match self.cur_kind() {
Kind::Meta => self.parse_keyword_identifier(Kind::Meta),
Kind::Target => self.parse_keyword_identifier(Kind::Target),
_ => self.parse_identifier_name()?,
};
let span = self.end_span(span);
if kind == Kind::Meta {
self.module_record_builder.visit_import_meta(span);
/// Section 13.3 ImportCall or ImportMeta
fn parse_import_meta_or_call(&mut self) -> Result<Expression<'a>> {
let span = self.start_span();
let meta = self.parse_keyword_identifier(Kind::Import);
match self.cur_kind() {
Kind::Dot => {
self.bump_any(); // bump `.`
match self.cur_kind() {
// `import.meta`
Kind::Meta => {
let property = self.parse_keyword_identifier(Kind::Meta);
let span = self.end_span(span);
self.module_record_builder.visit_import_meta(span);
Ok(self.ast.expression_meta_property(span, meta, property))
}
// `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
@ -760,8 +768,15 @@ impl<'a> ParserImpl<'a> {
fn parse_new_expression(&mut self) -> Result<Expression<'a>> {
let span = self.start_span();
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();

View file

@ -10,8 +10,17 @@ use crate::{diagnostics, lexer::Kind, modifiers::Modifiers, Context, ParserImpl}
impl<'a> ParserImpl<'a> {
/// [Import Call](https://tc39.es/ecma262/#sec-import-calls)
/// `ImportCall` : import ( `AssignmentExpression` )
pub(crate) fn parse_import_expression(&mut self, span: Span) -> Result<Expression<'a>> {
self.bump_any(); // advance '('
pub(crate) fn parse_import_expression(
&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();
self.ctx = self.ctx.and_in(true);
@ -25,7 +34,7 @@ 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))
Ok(self.ast.expression_import(self.end_span(span), expression, arguments, phase))
}
/// Section 16.2.2 Import Declaration
@ -45,7 +54,22 @@ impl<'a> ParserImpl<'a> {
}
// `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) {
// import "source"
@ -64,6 +88,7 @@ impl<'a> ParserImpl<'a> {
span,
specifiers,
source,
phase,
with_clause,
import_kind,
)

View file

@ -560,6 +560,7 @@ ascii_identifier_handler!(L_D(id_without_first_char) match id_without_first_char
"eclare" => Kind::Declare,
"efault" => Kind::Default,
"ebugger" => Kind::Debugger,
"efer" => Kind::Defer,
_ => Kind::Ident,
});
@ -655,6 +656,7 @@ ascii_identifier_handler!(L_S(id_without_first_char) match id_without_first_char
"ymbol" => Kind::Symbol,
"tring" => Kind::String,
"atisfies" => Kind::Satisfies,
"ource" => Kind::Source,
_ => Kind::Ident,
});

View file

@ -60,6 +60,8 @@ pub enum Kind {
Set,
Target, // new.target
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
Abstract,
As,
@ -375,7 +377,9 @@ impl Kind {
matches!(self, Async | From | Get | Meta | Of | Set | Target | Accessor | Abstract | As | Asserts
| Assert | Any | Boolean | Constructor | Declare | Infer | Intrinsic | Is | KeyOf | Module
| 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]
@ -455,6 +459,7 @@ impl Kind {
"using" => Using,
"while" => While,
"yield" => Yield,
"defer" => Defer,
"assert" => Assert,
"bigint" => BigInt,
@ -474,6 +479,7 @@ impl Kind {
"target" => Target,
"typeof" => Typeof,
"unique" => Unique,
"source" => Source,
"asserts" => Asserts,
"boolean" => Boolean,
@ -566,6 +572,8 @@ impl Kind {
Override => "override",
Type => "type",
Target => "target",
Source => "source",
Defer => "defer",
Implements => "implements",
Interface => "interface",
Package => "package",

View file

@ -365,30 +365,18 @@ fn new_target(span: Span) -> OxcDiagnostic {
.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 {
OxcDiagnostic::error("Unexpected import.meta expression")
.with_help("import.meta is only allowed in module code")
.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>) {
match prop.meta.name.as_str() {
"import" => {
if prop.property.name == "meta" {
if ctx.source_type.is_script() {
return ctx.error(import_meta(prop.span));
}
return;
if prop.property.name == "meta" && ctx.source_type.is_script() {
ctx.error(import_meta(prop.span));
}
ctx.error(import_meta_property(prop.span));
}
"new" => {
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 {
return ctx.error(new_target(prop.span));
ctx.error(new_target(prop.span));
}
return;
}
ctx.error(new_target_property(prop.span));
}
_ => {}
}

View file

@ -215,6 +215,7 @@ impl<'a> ModuleImportsStore<'a> {
SPAN,
Some(specifiers),
ctx.ast.string_literal(SPAN, source, None),
None,
NONE,
ImportOrExportKind::Value,
))

View file

@ -202,7 +202,7 @@ impl<'a> InjectGlobalVariables<'a> {
let kind = ImportOrExportKind::Value;
let import_decl = self
.ast
.module_declaration_import_declaration(SPAN, specifiers, source, NONE, kind);
.module_declaration_import_declaration(SPAN, specifiers, source, None, NONE, kind);
Statement::from(import_decl)
});
program.body.splice(0..0, imports);

View file

@ -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_ARGUMENTS: usize =
offset_of!(ImportExpression, arguments);
pub(crate) const OFFSET_IMPORT_EXPRESSION_PHASE: usize = offset_of!(ImportExpression, phase);
#[repr(transparent)]
#[derive(Clone, Copy, Debug)]
@ -9281,6 +9282,14 @@ impl<'a, 't> ImportExpressionWithoutSource<'a, 't> {
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> {
@ -9309,6 +9318,14 @@ impl<'a, 't> ImportExpressionWithoutArguments<'a, 't> {
&*((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> {
@ -9322,6 +9339,7 @@ pub(crate) const OFFSET_IMPORT_DECLARATION_SPAN: usize = offset_of!(ImportDeclar
pub(crate) const OFFSET_IMPORT_DECLARATION_SPECIFIERS: usize =
offset_of!(ImportDeclaration, specifiers);
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 =
offset_of!(ImportDeclaration, with_clause);
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]
pub fn with_clause(self) -> &'t Option<Box<'a, WithClause<'a>>> {
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]
pub fn with_clause(self) -> &'t Option<Box<'a, WithClause<'a>>> {
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]
pub fn import_kind(self) -> &'t ImportOrExportKind {
unsafe {

View file

@ -905,16 +905,20 @@ export interface ImportExpression extends Span {
type: 'ImportExpression';
source: Expression;
arguments: Array<Expression>;
phase: ImportPhase | null;
}
export interface ImportDeclaration extends Span {
type: 'ImportDeclaration';
specifiers: Array<ImportDeclarationSpecifier> | null;
source: StringLiteral;
phase: ImportPhase | null;
withClause: WithClause | null;
importKind: ImportOrExportKind;
}
export type ImportPhase = 'source' | 'defer';
export type ImportDeclarationSpecifier = ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier;
export interface ImportSpecifier extends Span {

View file

@ -1,5 +1,5 @@
commit: eefc5cf3
codegen_test262 Summary:
AST Parsed : 44037/44037 (100.00%)
Positive Passed: 44037/44037 (100.00%)
AST Parsed : 44169/44169 (100.00%)
Positive Passed: 44169/44169 (100.00%)

View file

@ -1,5 +1,5 @@
commit: eefc5cf3
minifier_test262 Summary:
AST Parsed : 44037/44037 (100.00%)
Positive Passed: 44037/44037 (100.00%)
AST Parsed : 44169/44169 (100.00%)
Positive Passed: 44169/44169 (100.00%)

View file

@ -5680,10 +5680,10 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
· ╰── `)` expected
╰────
× Unexpected token
╭─[babel/packages/babel-parser/test/fixtures/es2020/dynamic-import/no-args/input.js:1:8]
× import() requires a specifier.
╭─[babel/packages/babel-parser/test/fixtures/es2020/dynamic-import/no-args/input.js:1:1]
1 │ import();
·
· ───────
╰────
× 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
╰────
× Unexpected token
╭─[babel/packages/babel-parser/test/fixtures/es2020/dynamic-import-createImportExpression-false/no-args/input.js:1:8]
× import() requires a specifier.
╭─[babel/packages/babel-parser/test/fixtures/es2020/dynamic-import-createImportExpression-false/no-args/input.js:1:1]
1 │ import();
·
· ───────
╰────
× Unexpected import.meta expression
@ -8929,10 +8929,10 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
· ─────────
╰────
× Unexpected token
╭─[babel/packages/babel-parser/test/fixtures/esprima/es2015-meta-property/invalid-dots/input.js:1:30]
× 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:26]
1 │ var x = function() { y = new..target; }
·
· ────
╰────
× Unexpected new.target expression

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
commit: d85767ab
parser_typescript Summary:
AST Parsed : 6495/6503 (99.88%)
AST Parsed : 6494/6503 (99.86%)
Positive Passed: 6483/6503 (99.69%)
Negative Passed: 1239/5747 (21.56%)
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;
╰────
× 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
× 'with' statements are not allowed

View file

@ -1,8 +1,8 @@
commit: eefc5cf3
semantic_test262 Summary:
AST Parsed : 44037/44037 (100.00%)
Positive Passed: 43508/44037 (98.80%)
AST Parsed : 44169/44169 (100.00%)
Positive Passed: 43637/44169 (98.80%)
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":
after transform: SymbolId(3): ScopeId(4294967294)
@ -3740,6 +3740,15 @@ Unresolved references mismatch:
after transform: ["$DONE", "Object", "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
semantic error: Scope children mismatch:
after transform: ScopeId(14): [ScopeId(1)]

View file

@ -42303,7 +42303,6 @@ rebuilt : []
tasks/coverage/typescript/tests/cases/conformance/es2019/importMeta/importMeta.ts
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
semantic error: Scope children mismatch:

View file

@ -1,5 +1,5 @@
commit: eefc5cf3
transformer_test262 Summary:
AST Parsed : 44037/44037 (100.00%)
Positive Passed: 44037/44037 (100.00%)
AST Parsed : 44169/44169 (100.00%)
Positive Passed: 44169/44169 (100.00%)

View file

@ -57,6 +57,8 @@ static SKIP_FEATURES: &[&str] = &[
// stage 3
"decorators",
"explicit-resource-management",
"source-phase-imports",
"import-defer",
];
static SKIP_INCLUDES: &[&str] = &[

View file

@ -104,14 +104,10 @@ impl Case for Test262Case {
}
fn skip_test_case(&self) -> bool {
[
// stage 3 https://github.com/tc39/proposal-source-phase-imports
"source-phase-imports",
// stage 2.7 https://github.com/tc39/proposal-defer-import-eval
"import-defer",
]
.iter()
.any(|feature| self.meta.features.iter().any(|f| **f == **feature))
false
// []
// .iter()
// .any(|feature| self.meta.features.iter().any(|f| **f == **feature))
}
// Unless configured otherwise (via the noStrict, onlyStrict, module, or raw flags),