From 998d44d54e325185bdc05e66dc56e9396d6d8178 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Tue, 14 Nov 2023 01:16:23 +0800 Subject: [PATCH] feat: dynamic import phase --- crates/swc_ecma_ast/src/expr.rs | 8 ++- crates/swc_ecma_codegen/src/lib.rs | 11 +++ crates/swc_ecma_parser/src/parser/expr.rs | 69 +++++++++++++------ .../swc_ecma_parser/src/parser/expr/tests.rs | 2 +- crates/swc_ecma_transforms_module/src/amd.rs | 6 +- .../src/common_js.rs | 6 +- crates/swc_ecma_visit/src/lib.rs | 1 + crates/swc_estree_compat/src/swcify/expr.rs | 2 + 8 files changed, 78 insertions(+), 27 deletions(-) diff --git a/crates/swc_ecma_ast/src/expr.rs b/crates/swc_ecma_ast/src/expr.rs index a4638348b7684..f7a6b7b5a4211 100644 --- a/crates/swc_ecma_ast/src/expr.rs +++ b/crates/swc_ecma_ast/src/expr.rs @@ -24,7 +24,7 @@ use crate::{ TsAsExpr, TsConstAssertion, TsInstantiation, TsNonNullExpr, TsSatisfiesExpr, TsTypeAnn, TsTypeAssertion, TsTypeParamDecl, TsTypeParamInstantiation, }, - ComputedPropName, Id, Invalid, + ComputedPropName, Id, ImportPhase, Invalid, }; #[ast_node(no_clone)] @@ -1124,11 +1124,15 @@ impl Take for Super { #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] pub struct Import { pub span: Span, + pub phase: ImportPhase, } impl Take for Import { fn dummy() -> Self { - Import { span: DUMMY_SP } + Import { + span: DUMMY_SP, + phase: ImportPhase::default(), + } } } diff --git a/crates/swc_ecma_codegen/src/lib.rs b/crates/swc_ecma_codegen/src/lib.rs index e3771cf2448d7..65e6ec29ff963 100644 --- a/crates/swc_ecma_codegen/src/lib.rs +++ b/crates/swc_ecma_codegen/src/lib.rs @@ -776,6 +776,17 @@ where #[emitter] fn emit_import_callee(&mut self, node: &Import) -> Result { keyword!(node.span, "import"); + match node.phase { + ImportPhase::Source => { + punct!("."); + keyword!("source") + } + ImportPhase::Defer => { + punct!("."); + keyword!("defer") + } + _ => {} + } } #[emitter] diff --git a/crates/swc_ecma_parser/src/parser/expr.rs b/crates/swc_ecma_parser/src/parser/expr.rs index bdbcc044935b8..0176a401d6f5f 100644 --- a/crates/swc_ecma_parser/src/parser/expr.rs +++ b/crates/swc_ecma_parser/src/parser/expr.rs @@ -259,19 +259,17 @@ impl Parser { tok!("import") => { let import = self.parse_ident_name()?; + if is!(self, '.') { self.state.found_module_item = true; if !self.ctx().can_be_module { let span = span!(self, start); self.emit_err(span, SyntaxError::ImportMetaInScript); } - return self - .parse_import_meta_prop(Import { span: import.span }) - .map(Expr::MetaProp) - .map(Box::new); + return self.parse_import_meta_prop(start, import.span); } - return self.parse_dynamic_import(start, import.span); + return self.parse_dynamic_import(start, import.span, ImportPhase::Evaluation); } tok!("async") => { @@ -541,19 +539,27 @@ impl Parser { } /// `parseImportMetaProperty` - pub(super) fn parse_import_meta_prop(&mut self, import: Import) -> PResult { + pub(super) fn parse_import_meta_prop( + &mut self, + start: BytePos, + import_span: Span, + ) -> PResult> { expect!(self, '.'); - let _ = if is!(self, "meta") { - self.parse_ident_name()? - } else { - unexpected!(self, "meta"); - }; + let ident = self.parse_ident_name()?; - Ok(MetaPropExpr { - span: span!(self, import.span.lo()), - kind: MetaPropKind::ImportMeta, - }) + match &*ident.sym { + "meta" => Ok(MetaPropExpr { + span: span!(self, import_span.lo()), + kind: MetaPropKind::ImportMeta, + } + .into()), + "source" => self.parse_dynamic_import(start, import_span, ImportPhase::Source), + // TODO: The proposal doesn't mention import.defer yet because it was + // pending on a decision for import.source. Wait to enable it until it's + // included in the proposal. + _ => unexpected!(self, "meta"), + } } /// `is_new_expr`: true iff we are parsing production 'NewExpression'. @@ -676,6 +682,7 @@ impl Parser { if eat!(self, "import") { let base = Callee::Import(Import { span: span!(self, start), + phase: Default::default(), }); return self.parse_subscripts(base, true, false); } @@ -1446,16 +1453,28 @@ impl Parser { return Ok(( Box::new(match obj { - Callee::Import(_) => match prop { - MemberProp::Ident(Ident { sym: meta, .. }) if &*meta == "meta" => { + callee @ Callee::Import(_) => match prop { + MemberProp::Ident(Ident { sym, .. }) => { if !self.ctx().can_be_module { let span = span!(self, start); self.emit_err(span, SyntaxError::ImportMetaInScript); } - Expr::MetaProp(MetaPropExpr { - span, - kind: MetaPropKind::ImportMeta, - }) + match &*sym { + "meta" => Expr::MetaProp(MetaPropExpr { + span, + kind: MetaPropKind::ImportMeta, + }), + _ => { + let args = self.parse_args(true)?; + + Expr::Call(CallExpr { + span, + callee, + args, + type_args: None, + }) + } + } } _ => { unexpected!(self, "meta"); @@ -1604,6 +1623,7 @@ impl Parser { if eat!(self, "import") { let obj = Callee::Import(Import { span: span!(self, start), + phase: Default::default(), }); return self.parse_subscripts(obj, false, false); } @@ -1648,6 +1668,7 @@ impl Parser { _ if callee.is_ident_ref_to("import") => ( Callee::Import(Import { span: callee.span(), + phase: Default::default(), }), true, ), @@ -2071,11 +2092,15 @@ impl Parser { &mut self, start: BytePos, import_span: Span, + phase: ImportPhase, ) -> PResult> { let args = self.parse_args(true)?; let import = Box::new(Expr::Call(CallExpr { span: span!(self, start), - callee: Callee::Import(Import { span: import_span }), + callee: Callee::Import(Import { + span: import_span, + phase, + }), args, type_args: Default::default(), })); diff --git a/crates/swc_ecma_parser/src/parser/expr/tests.rs b/crates/swc_ecma_parser/src/parser/expr/tests.rs index a91a7c01cab71..95956305db4ab 100644 --- a/crates/swc_ecma_parser/src/parser/expr/tests.rs +++ b/crates/swc_ecma_parser/src/parser/expr/tests.rs @@ -380,7 +380,7 @@ fn issue_328() { span, expr: Box::new(Expr::Call(CallExpr { span, - callee: Callee::Import(Import { span }), + callee: Callee::Import(Import { span, phase: Default::default() }), args: vec![ExprOrSpread { spread: None, expr: Box::new(Expr::Lit(Lit::Str(Str { diff --git a/crates/swc_ecma_transforms_module/src/amd.rs b/crates/swc_ecma_transforms_module/src/amd.rs index da64d68e07825..e09912d146c1c 100644 --- a/crates/swc_ecma_transforms_module/src/amd.rs +++ b/crates/swc_ecma_transforms_module/src/amd.rs @@ -282,7 +282,11 @@ where match n { Expr::Call(CallExpr { span, - callee: Callee::Import(Import { span: import_span }), + callee: + Callee::Import(Import { + span: import_span, + phase: ImportPhase::Evaluation, + }), args, .. }) if !self.config.ignore_dynamic => { diff --git a/crates/swc_ecma_transforms_module/src/common_js.rs b/crates/swc_ecma_transforms_module/src/common_js.rs index 64a1e23561856..0cd7e11f01d07 100644 --- a/crates/swc_ecma_transforms_module/src/common_js.rs +++ b/crates/swc_ecma_transforms_module/src/common_js.rs @@ -200,7 +200,11 @@ where match n { Expr::Call(CallExpr { span, - callee: Callee::Import(Import { span: import_span }), + callee: + Callee::Import(Import { + span: import_span, + phase: ImportPhase::Evaluation, + }), args, .. }) if !self.config.ignore_dynamic => { diff --git a/crates/swc_ecma_visit/src/lib.rs b/crates/swc_ecma_visit/src/lib.rs index 3bcfa5d12d817..e7961c40df321 100644 --- a/crates/swc_ecma_visit/src/lib.rs +++ b/crates/swc_ecma_visit/src/lib.rs @@ -856,6 +856,7 @@ define!({ } pub struct Import { pub span: Span, + pub phase: ImportPhase, } pub struct ExprOrSpread { pub spread: Option, diff --git a/crates/swc_estree_compat/src/swcify/expr.rs b/crates/swc_estree_compat/src/swcify/expr.rs index af8495a87f8c4..ed2a559f5af5d 100644 --- a/crates/swc_estree_compat/src/swcify/expr.rs +++ b/crates/swc_estree_compat/src/swcify/expr.rs @@ -744,6 +744,8 @@ impl Swcify for BabelImport { fn swcify(self, ctx: &Context) -> Self::Output { Import { span: ctx.span(&self.base), + // TODO + phase: Default::default(), } } }