1
1
use itertools:: Itertools ;
2
- use oxc_ast:: ast:: Program ;
2
+ use oxc_ast:: ast:: { Declaration , Program , Statement } ;
3
3
use oxc_index:: { index_vec, Idx , IndexVec } ;
4
4
use oxc_semantic:: { ReferenceId , ScopeTree , SemanticBuilder , SymbolId , SymbolTable } ;
5
5
use oxc_span:: CompactStr ;
6
+ use rustc_hash:: FxHashSet ;
6
7
7
8
type Slot = usize ;
8
9
@@ -85,6 +86,28 @@ impl Mangler {
85
86
pub fn build < ' a > ( mut self , program : & ' a Program < ' a > ) -> Mangler {
86
87
let semantic = SemanticBuilder :: new ( ) . build ( program) . semantic ;
87
88
89
+ let ( exported_names, exported_symbols) : ( FxHashSet < CompactStr > , FxHashSet < SymbolId > ) =
90
+ program
91
+ . body
92
+ . iter ( )
93
+ . filter_map ( |statement| {
94
+ let Statement :: ExportNamedDeclaration ( v) = statement else { return None } ;
95
+ v. declaration . as_ref ( )
96
+ } )
97
+ . flat_map ( |decl| {
98
+ if let Declaration :: VariableDeclaration ( decl) = decl {
99
+ itertools:: Either :: Left (
100
+ decl. declarations
101
+ . iter ( )
102
+ . filter_map ( |decl| decl. id . get_binding_identifier ( ) ) ,
103
+ )
104
+ } else {
105
+ itertools:: Either :: Right ( decl. id ( ) . into_iter ( ) )
106
+ }
107
+ } )
108
+ . map ( |id| ( id. name . to_compact_str ( ) , id. symbol_id ( ) ) )
109
+ . collect ( ) ;
110
+
88
111
// Mangle the symbol table by computing slots from the scope tree.
89
112
// A slot is the occurrence index of a binding identifier inside a scope.
90
113
let ( mut symbol_table, scope_tree) = semantic. into_symbol_table_and_scope_tree ( ) ;
@@ -126,8 +149,13 @@ impl Mangler {
126
149
}
127
150
}
128
151
129
- let frequencies =
130
- self . tally_slot_frequencies ( & symbol_table, & scope_tree, total_number_of_slots, & slots) ;
152
+ let frequencies = self . tally_slot_frequencies (
153
+ & symbol_table,
154
+ & exported_symbols,
155
+ & scope_tree,
156
+ total_number_of_slots,
157
+ & slots,
158
+ ) ;
131
159
132
160
let root_unresolved_references = scope_tree. root_unresolved_references ( ) ;
133
161
let root_bindings = scope_tree. get_bindings ( scope_tree. root_scope_id ( ) ) ;
@@ -145,7 +173,8 @@ impl Mangler {
145
173
if !is_keyword ( n)
146
174
&& !is_special_name ( n)
147
175
&& !root_unresolved_references. contains_key ( n)
148
- && ( self . options . top_level || !root_bindings. contains_key ( n) )
176
+ && !( root_bindings. contains_key ( n)
177
+ && ( !self . options . top_level || exported_names. contains ( n) ) )
149
178
{
150
179
break name;
151
180
}
@@ -206,14 +235,17 @@ impl Mangler {
206
235
fn tally_slot_frequencies (
207
236
& self ,
208
237
symbol_table : & SymbolTable ,
238
+ exported_symbols : & FxHashSet < SymbolId > ,
209
239
scope_tree : & ScopeTree ,
210
240
total_number_of_slots : usize ,
211
241
slots : & IndexVec < SymbolId , Slot > ,
212
242
) -> Vec < SlotFrequency > {
213
243
let root_scope_id = scope_tree. root_scope_id ( ) ;
214
244
let mut frequencies = vec ! [ SlotFrequency :: default ( ) ; total_number_of_slots] ;
215
245
for ( symbol_id, slot) in slots. iter_enumerated ( ) {
216
- if !self . options . top_level && symbol_table. get_scope_id ( symbol_id) == root_scope_id {
246
+ if symbol_table. get_scope_id ( symbol_id) == root_scope_id
247
+ && ( !self . options . top_level || exported_symbols. contains ( & symbol_id) )
248
+ {
217
249
continue ;
218
250
}
219
251
if is_special_name ( symbol_table. get_name ( symbol_id) ) {
0 commit comments