@@ -182,6 +182,32 @@ impl VisitWith for SuperCall {
182182 }
183183}
184184
185+ /// The phase of a dynamic import call.
186+ ///
187+ /// Determines how the imported module is handled:
188+ /// - `Evaluation` (default): `import(specifier)` — loads, links, and evaluates the module.
189+ /// - `Defer`: `import.defer(specifier)` — deferred evaluation of the module.
190+ /// - `Source`: `import.source(specifier)` — source phase import.
191+ ///
192+ /// More information:
193+ /// - [import-defer proposal][defer]
194+ /// - [source-phase-imports proposal][source]
195+ ///
196+ /// [defer]: https://github.com/tc39/proposal-defer-import-eval
197+ /// [source]: https://github.com/tc39/proposal-source-phase-imports
198+ #[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
199+ #[ cfg_attr( feature = "arbitrary" , derive( arbitrary:: Arbitrary ) ) ]
200+ #[ derive( Clone , Copy , Debug , PartialEq , Eq , Default ) ]
201+ pub enum ImportPhase {
202+ /// `import(specifier)` — standard dynamic import.
203+ #[ default]
204+ Evaluation ,
205+ /// `import.defer(specifier)` — deferred import evaluation.
206+ Defer ,
207+ /// `import.source(specifier)` — source phase import.
208+ Source ,
209+ }
210+
185211/// The `import()` syntax, commonly called dynamic import, is a function-like expression that allows
186212/// loading an ECMAScript module asynchronously and dynamically into a potentially non-module
187213/// environment.
@@ -198,20 +224,22 @@ impl VisitWith for SuperCall {
198224pub struct ImportCall {
199225 specifier : Box < Expression > ,
200226 options : Option < Box < Expression > > ,
227+ phase : ImportPhase ,
201228 span : Span ,
202229}
203230
204231impl ImportCall {
205232 /// Creates a new `ImportCall` AST node.
206233 #[ inline]
207234 #[ must_use]
208- pub fn new < S > ( specifier : S , options : Option < Expression > , span : Span ) -> Self
235+ pub fn new < S > ( specifier : S , options : Option < Expression > , phase : ImportPhase , span : Span ) -> Self
209236 where
210237 S : Into < Expression > ,
211238 {
212239 Self {
213240 specifier : Box :: new ( specifier. into ( ) ) ,
214241 options : options. map ( Box :: new) ,
242+ phase,
215243 span,
216244 }
217245 }
@@ -235,6 +263,13 @@ impl ImportCall {
235263 self . options . as_deref ( )
236264 }
237265
266+ /// Returns the phase of this import call.
267+ #[ inline]
268+ #[ must_use]
269+ pub const fn phase ( & self ) -> ImportPhase {
270+ self . phase
271+ }
272+
238273 /// Gets the module specifier of the import call.
239274 ///
240275 /// This is an alias for [`Self::specifier`] for backwards compatibility.
@@ -256,14 +291,24 @@ impl Spanned for ImportCall {
256291impl ToInternedString for ImportCall {
257292 #[ inline]
258293 fn to_interned_string ( & self , interner : & Interner ) -> String {
294+ let phase_str = match self . phase {
295+ ImportPhase :: Evaluation => "" ,
296+ ImportPhase :: Defer => ".defer" ,
297+ ImportPhase :: Source => ".source" ,
298+ } ;
259299 if let Some ( options) = & self . options {
260300 format ! (
261- "import({}, {})" ,
301+ "import{}({}, {})" ,
302+ phase_str,
262303 self . specifier. to_interned_string( interner) ,
263304 options. to_interned_string( interner)
264305 )
265306 } else {
266- format ! ( "import({})" , self . specifier. to_interned_string( interner) )
307+ format ! (
308+ "import{}({})" ,
309+ phase_str,
310+ self . specifier. to_interned_string( interner)
311+ )
267312 }
268313 }
269314}
0 commit comments