@@ -21,6 +21,9 @@ pub struct RootVarDependency {
2121 pub is_imported : bool , // true if this is from global.imports
2222 pub is_exported : bool , // true if this is in global.exports
2323 pub depends_on : Vec < Id > , // Other identifiers this var depends on
24+ /// Original declaration kind for `Decl::Var` entries (`let`/`var`/`const`).
25+ /// `None` for function/class/enum declarations or synthesized entries.
26+ pub var_kind : Option < ast:: VarDeclKind > ,
2427}
2528
2629/// Analyzes dependencies between root-level variables and imports.
@@ -112,7 +115,14 @@ pub fn analyze_root_dependencies(
112115
113116 // First pass: collect ALL root declarations from the module body
114117 for item in & module. body {
115- if let ast:: ModuleItem :: Stmt ( ast:: Stmt :: Decl ( decl) ) = item {
118+ let decl = match item {
119+ ast:: ModuleItem :: Stmt ( ast:: Stmt :: Decl ( decl) ) => Some ( decl) ,
120+ ast:: ModuleItem :: ModuleDecl ( ast:: ModuleDecl :: ExportDecl ( export_decl) ) => {
121+ Some ( & export_decl. decl )
122+ }
123+ _ => None ,
124+ } ;
125+ if let Some ( decl) = decl {
116126 match decl {
117127 ast:: Decl :: Var ( var_decl) => {
118128 for decl in & var_decl. decls {
@@ -139,6 +149,7 @@ pub fn analyze_root_dependencies(
139149 is_imported : false ,
140150 is_exported : user_exported. contains ( & var_id) ,
141151 depends_on : Vec :: new ( ) ,
152+ var_kind : Some ( var_decl. kind ) ,
142153 } ,
143154 ) ;
144155 }
@@ -154,6 +165,7 @@ pub fn analyze_root_dependencies(
154165 is_imported : false ,
155166 is_exported : user_exported. contains ( & var_id) ,
156167 depends_on : Vec :: new ( ) ,
168+ var_kind : None ,
157169 } ) ;
158170 }
159171 ast:: Decl :: Class ( class) => {
@@ -165,6 +177,7 @@ pub fn analyze_root_dependencies(
165177 is_imported : false ,
166178 is_exported : user_exported. contains ( & var_id) ,
167179 depends_on : Vec :: new ( ) ,
180+ var_kind : None ,
168181 } ) ;
169182 }
170183 ast:: Decl :: TsEnum ( enu) => {
@@ -176,6 +189,7 @@ pub fn analyze_root_dependencies(
176189 is_imported : false ,
177190 is_exported : user_exported. contains ( & var_id) ,
178191 depends_on : Vec :: new ( ) ,
192+ var_kind : None ,
179193 } ) ;
180194 }
181195 _ => { }
@@ -197,6 +211,7 @@ pub fn analyze_root_dependencies(
197211 init : None ,
198212 definite : false ,
199213 } ) ,
214+ var_kind : None ,
200215 is_imported : false ,
201216 is_exported : user_exported. contains ( var_id) ,
202217 depends_on : Vec :: new ( ) ,
@@ -205,7 +220,14 @@ pub fn analyze_root_dependencies(
205220
206221 // Second pass: extract variable declarations and analyze dependencies
207222 for item in & module. body {
208- if let ast:: ModuleItem :: Stmt ( ast:: Stmt :: Decl ( decl) ) = item {
223+ let decl = match item {
224+ ast:: ModuleItem :: Stmt ( ast:: Stmt :: Decl ( decl) ) => Some ( decl) ,
225+ ast:: ModuleItem :: ModuleDecl ( ast:: ModuleDecl :: ExportDecl ( export_decl) ) => {
226+ Some ( & export_decl. decl )
227+ }
228+ _ => None ,
229+ } ;
230+ if let Some ( decl) = decl {
209231 match decl {
210232 ast:: Decl :: Var ( var_decl) => {
211233 for decl in & var_decl. decls {
@@ -593,3 +615,55 @@ fn collect_decl_idents_from_decl(decl: &ast::Decl, idents: &mut Vec<Id>) {
593615 _ => { }
594616 }
595617}
618+
619+ #[ cfg( test) ]
620+ mod tests {
621+ use super :: * ;
622+ use crate :: collector:: global_collect;
623+ use swc_atoms:: atom;
624+ use swc_common:: { SyntaxContext , DUMMY_SP } ;
625+
626+ #[ test]
627+ fn analyze_root_dependencies_tracks_export_decl_var_kind ( ) {
628+ let id = ast:: Ident :: new ( atom ! ( "counter" ) , DUMMY_SP , SyntaxContext :: empty ( ) ) ;
629+ let module = ast:: Module {
630+ span : DUMMY_SP ,
631+ shebang : None ,
632+ body : vec ! [ ast:: ModuleItem :: ModuleDecl ( ast:: ModuleDecl :: ExportDecl (
633+ ast:: ExportDecl {
634+ span: DUMMY_SP ,
635+ decl: ast:: Decl :: Var ( Box :: new( ast:: VarDecl {
636+ span: DUMMY_SP ,
637+ ctxt: SyntaxContext :: empty( ) ,
638+ kind: ast:: VarDeclKind :: Let ,
639+ declare: false ,
640+ decls: vec![ ast:: VarDeclarator {
641+ span: DUMMY_SP ,
642+ name: ast:: Pat :: Ident ( ast:: BindingIdent { id, type_ann: None } ) ,
643+ init: Some ( Box :: new( ast:: Expr :: Lit ( ast:: Lit :: Num ( ast:: Number {
644+ span: DUMMY_SP ,
645+ value: 0.0 ,
646+ raw: None ,
647+ } ) ) ) ) ,
648+ definite: false ,
649+ } ] ,
650+ } ) ) ,
651+ } ,
652+ ) ) ] ,
653+ } ;
654+
655+ let collect = global_collect ( & ast:: Program :: Module ( module. clone ( ) ) ) ;
656+ let deps = analyze_root_dependencies ( & module, & collect) ;
657+ let dep = deps
658+ . get ( & ( atom ! ( "counter" ) , SyntaxContext :: empty ( ) ) )
659+ . expect ( "counter dependency should exist" ) ;
660+
661+ assert_eq ! ( dep. var_kind, Some ( ast:: VarDeclKind :: Let ) ) ;
662+ match & dep. decl {
663+ RootVarDecl :: Var ( decl) => {
664+ assert ! ( decl. init. is_some( ) ) ;
665+ }
666+ _ => panic ! ( "expected var declarator" ) ,
667+ }
668+ }
669+ }
0 commit comments