@@ -23,6 +23,7 @@ use std::{borrow::Cow, collections::BTreeMap, future::Future, mem::take, ops::De
23
23
use anyhow:: { bail, Result } ;
24
24
use constant_condition:: { ConstantConditionCodeGen , ConstantConditionValue } ;
25
25
use constant_value:: ConstantValueCodeGen ;
26
+ use either:: Either ;
26
27
use indexmap:: map:: Entry ;
27
28
use lazy_static:: lazy_static;
28
29
use num_traits:: Zero ;
@@ -42,6 +43,7 @@ use swc_core::{
42
43
} ,
43
44
ecma:: {
44
45
ast:: * ,
46
+ utils:: IsDirective ,
45
47
visit:: {
46
48
fields:: { AssignExprField , AssignTargetField , SimpleAssignTargetField } ,
47
49
AstParentKind , AstParentNodeRef , VisitAstPath , VisitWithAstPath ,
@@ -169,6 +171,7 @@ pub struct AnalyzeEcmascriptModuleResult {
169
171
pub code_generation : ResolvedVc < CodeGens > ,
170
172
pub exports : ResolvedVc < EcmascriptExports > ,
171
173
pub async_module : ResolvedVc < OptionAsyncModule > ,
174
+ pub has_side_effect_free_directive : bool ,
172
175
/// `true` when the analysis was successful.
173
176
pub successful : bool ,
174
177
pub source_map : ResolvedVc < OptionStringifiedSourceMap > ,
@@ -221,6 +224,7 @@ pub struct AnalyzeEcmascriptModuleResultBuilder {
221
224
async_module : ResolvedVc < OptionAsyncModule > ,
222
225
successful : bool ,
223
226
source_map : Option < ResolvedVc < OptionStringifiedSourceMap > > ,
227
+ has_side_effect_free_directive : bool ,
224
228
}
225
229
226
230
impl AnalyzeEcmascriptModuleResultBuilder {
@@ -238,6 +242,7 @@ impl AnalyzeEcmascriptModuleResultBuilder {
238
242
async_module : ResolvedVc :: cell ( None ) ,
239
243
successful : false ,
240
244
source_map : None ,
245
+ has_side_effect_free_directive : false ,
241
246
}
242
247
}
243
248
@@ -297,6 +302,11 @@ impl AnalyzeEcmascriptModuleResultBuilder {
297
302
self . async_module = ResolvedVc :: cell ( Some ( async_module) ) ;
298
303
}
299
304
305
+ /// Set whether this module is side-efffect free according to a user-provided directive.
306
+ pub fn set_has_side_effect_free_directive ( & mut self , value : bool ) {
307
+ self . has_side_effect_free_directive = value;
308
+ }
309
+
300
310
/// Sets whether the analysis was successful.
301
311
pub fn set_successful ( & mut self , successful : bool ) {
302
312
self . successful = successful;
@@ -411,6 +421,7 @@ impl AnalyzeEcmascriptModuleResultBuilder {
411
421
code_generation : ResolvedVc :: cell ( self . code_gens ) ,
412
422
exports : self . exports . resolved_cell ( ) ,
413
423
async_module : self . async_module ,
424
+ has_side_effect_free_directive : self . has_side_effect_free_directive ,
414
425
successful : self . successful ,
415
426
source_map,
416
427
} ,
@@ -586,6 +597,33 @@ pub(crate) async fn analyse_ecmascript_module_internal(
586
597
return analysis. build ( Default :: default ( ) , false ) . await ;
587
598
} ;
588
599
600
+ let has_side_effect_free_directive = match program {
601
+ Program :: Module ( module) => Either :: Left (
602
+ module
603
+ . body
604
+ . iter ( )
605
+ . take_while ( |i| match i {
606
+ ModuleItem :: Stmt ( stmt) => stmt. directive_continue ( ) ,
607
+ ModuleItem :: ModuleDecl ( _) => false ,
608
+ } )
609
+ . filter_map ( |i| i. as_stmt ( ) ) ,
610
+ ) ,
611
+ Program :: Script ( script) => Either :: Right (
612
+ script
613
+ . body
614
+ . iter ( )
615
+ . take_while ( |stmt| stmt. directive_continue ( ) ) ,
616
+ ) ,
617
+ }
618
+ . any ( |f| match f {
619
+ Stmt :: Expr ( ExprStmt { expr, .. } ) => match & * * expr {
620
+ Expr :: Lit ( Lit :: Str ( Str { value, .. } ) ) => value == "use turbopack no side effects" ,
621
+ _ => false ,
622
+ } ,
623
+ _ => false ,
624
+ } ) ;
625
+ analysis. set_has_side_effect_free_directive ( has_side_effect_free_directive) ;
626
+
589
627
let compile_time_info = compile_time_info_for_module_type (
590
628
* raw_module. compile_time_info ,
591
629
eval_context. is_esm ( specified_type) ,
0 commit comments