@@ -8,7 +8,7 @@ use rustc_hash::FxHashSet;
8
8
use oxc_allocator:: { Allocator , Vec } ;
9
9
use oxc_ast:: ast:: { Declaration , Program , Statement } ;
10
10
use oxc_index:: Idx ;
11
- use oxc_semantic:: { ReferenceId , ScopeTree , SemanticBuilder , SymbolId , SymbolTable } ;
11
+ use oxc_semantic:: { ReferenceId , ScopeTree , Semantic , SemanticBuilder , SymbolId , SymbolTable } ;
12
12
use oxc_span:: Atom ;
13
13
14
14
#[ derive( Default , Debug , Clone , Copy ) ]
@@ -92,24 +92,18 @@ impl Mangler {
92
92
pub fn build ( self , program : & Program < ' _ > ) -> Mangler {
93
93
let semantic =
94
94
SemanticBuilder :: new ( ) . with_scope_tree_child_ids ( true ) . build ( program) . semantic ;
95
- let ( symbol_table, scope_tree) = semantic. into_symbol_table_and_scope_tree ( ) ;
96
- self . build_with_symbols_and_scopes ( symbol_table, & scope_tree, program)
95
+ self . build_with_semantic ( semantic, program)
97
96
}
98
97
99
98
/// # Panics
100
99
///
101
100
/// Panics if the child_ids does not exist in scope_tree.
102
101
#[ must_use]
103
- pub fn build_with_symbols_and_scopes (
104
- self ,
105
- symbol_table : SymbolTable ,
106
- scope_tree : & ScopeTree ,
107
- program : & Program < ' _ > ,
108
- ) -> Mangler {
102
+ pub fn build_with_semantic ( self , semantic : Semantic < ' _ > , program : & Program < ' _ > ) -> Mangler {
109
103
if self . options . debug {
110
- self . build_with_symbols_and_scopes_impl ( symbol_table , scope_tree , program, debug_name)
104
+ self . build_with_symbols_and_scopes_impl ( semantic , program, debug_name)
111
105
} else {
112
- self . build_with_symbols_and_scopes_impl ( symbol_table , scope_tree , program, base54)
106
+ self . build_with_symbols_and_scopes_impl ( semantic , program, base54)
113
107
}
114
108
}
115
109
@@ -118,11 +112,12 @@ impl Mangler {
118
112
G : Fn ( usize ) -> InlineString < CAPACITY > ,
119
113
> (
120
114
mut self ,
121
- symbol_table : SymbolTable ,
122
- scope_tree : & ScopeTree ,
115
+ semantic : Semantic < ' _ > ,
123
116
program : & Program < ' _ > ,
124
117
generate_name : G ,
125
118
) -> Mangler {
119
+ let ( mut symbol_table, scope_tree, ast_nodes) = semantic. into_symbols_scopes_nodes ( ) ;
120
+
126
121
assert ! ( scope_tree. has_child_ids( ) , "child_id needs to be generated" ) ;
127
122
128
123
let ( exported_names, exported_symbols) = if self . options . top_level {
@@ -133,10 +128,6 @@ impl Mangler {
133
128
134
129
let allocator = Allocator :: default ( ) ;
135
130
136
- // Mangle the symbol table by computing slots from the scope tree.
137
- // A slot is the occurrence index of a binding identifier inside a scope.
138
- let mut symbol_table = symbol_table;
139
-
140
131
// All symbols with their assigned slots. Keyed by symbol id.
141
132
let mut slots: Vec < ' _ , Slot > = Vec :: with_capacity_in ( symbol_table. len ( ) , & allocator) ;
142
133
for _ in 0 ..symbol_table. len ( ) {
@@ -150,54 +141,57 @@ impl Mangler {
150
141
for scope_id in iter:: once ( scope_tree. root_scope_id ( ) )
151
142
. chain ( scope_tree. iter_all_child_ids ( scope_tree. root_scope_id ( ) ) )
152
143
{
144
+ let bindings = scope_tree. get_bindings ( scope_id) ;
145
+ if bindings. is_empty ( ) {
146
+ continue ;
147
+ }
148
+
149
+ let mut slot = slot_liveness. len ( ) ;
150
+
153
151
let nearest_var_scope_id = scope_tree
154
152
. ancestors ( scope_id)
155
153
. find ( |s_id| scope_tree. get_flags ( * s_id) . is_var ( ) )
156
154
. unwrap_or ( scope_tree. root_scope_id ( ) ) ;
157
- let bindings = scope_tree. get_bindings ( scope_id) ;
158
155
159
- let mut slot = slot_liveness. len ( ) ;
160
-
161
- if !bindings. is_empty ( ) {
162
- let reusable_slots = Vec :: from_iter_in (
163
- slot_liveness
164
- . iter ( )
165
- . enumerate ( )
166
- . filter ( |( _, slot_liveness) | !slot_liveness. contains ( scope_id. index ( ) ) )
167
- . map ( |( slot, _) | slot)
168
- . take ( bindings. len ( ) ) ,
169
- & allocator,
170
- ) ;
171
- let remaining_count = bindings. len ( ) - reusable_slots. len ( ) ;
172
-
173
- let assignable_slots =
174
- reusable_slots. into_iter ( ) . chain ( slot..slot + remaining_count) ;
175
- slot += remaining_count;
176
- if slot_liveness. len ( ) < slot {
177
- slot_liveness
178
- . resize_with ( slot, || FixedBitSet :: with_capacity ( scope_tree. len ( ) ) ) ;
179
- }
156
+ let reusable_slots = Vec :: from_iter_in (
157
+ slot_liveness
158
+ . iter ( )
159
+ . enumerate ( )
160
+ . filter ( |( _, slot_liveness) | !slot_liveness. contains ( scope_id. index ( ) ) )
161
+ . map ( |( slot, _) | slot)
162
+ . take ( bindings. len ( ) ) ,
163
+ & allocator,
164
+ ) ;
165
+
166
+ let remaining_count = bindings. len ( ) - reusable_slots. len ( ) ;
167
+
168
+ let assignable_slots = reusable_slots. into_iter ( ) . chain ( slot..slot + remaining_count) ;
169
+ slot += remaining_count;
170
+ if slot_liveness. len ( ) < slot {
171
+ slot_liveness. resize_with ( slot, || FixedBitSet :: with_capacity ( scope_tree. len ( ) ) ) ;
172
+ }
180
173
181
- // Sort `bindings` in declaration order.
182
- tmp_bindings. clear ( ) ;
183
- tmp_bindings. extend ( bindings. values ( ) . copied ( ) ) ;
184
- tmp_bindings. sort_unstable ( ) ;
185
- for ( symbol_id, assigned_slot) in tmp_bindings. iter ( ) . zip ( assignable_slots) {
186
- slots[ symbol_id. index ( ) ] = assigned_slot;
187
-
188
- let lived_scope_ids = symbol_table
189
- . get_resolved_references ( * symbol_id)
190
- . flat_map ( |reference| {
191
- // treat all symbols as var for now
192
- // the reusability can be improved by reducing the lived scope ids for const / let / class
193
- scope_tree
194
- . ancestors ( reference. scope_id ( ) )
195
- . take_while ( |s_id| * s_id != nearest_var_scope_id)
196
- } )
197
- . chain ( iter:: once ( nearest_var_scope_id) ) ;
198
- for scope_id in lived_scope_ids {
199
- slot_liveness[ assigned_slot] . insert ( scope_id. index ( ) ) ;
200
- }
174
+ // Sort `bindings` in declaration order.
175
+ tmp_bindings. clear ( ) ;
176
+ tmp_bindings. extend ( bindings. values ( ) . copied ( ) ) ;
177
+ tmp_bindings. sort_unstable ( ) ;
178
+ for ( symbol_id, assigned_slot) in tmp_bindings. iter ( ) . zip ( assignable_slots) {
179
+ slots[ symbol_id. index ( ) ] = assigned_slot;
180
+
181
+ let lived_scope_ids = symbol_table
182
+ . get_resolved_references ( * symbol_id)
183
+ . flat_map ( |reference| {
184
+ let scope_id = ast_nodes. get_node ( reference. node_id ( ) ) . scope_id ( ) ;
185
+ // Treat all symbols as var for now.
186
+ // Reusability can be improved by reducing the lived scope ids for const / let / class
187
+ scope_tree
188
+ . ancestors ( scope_id)
189
+ . take_while ( |s_id| * s_id != nearest_var_scope_id)
190
+ } )
191
+ . chain ( iter:: once ( nearest_var_scope_id) ) ;
192
+
193
+ for scope_id in lived_scope_ids {
194
+ slot_liveness[ assigned_slot] . insert ( scope_id. index ( ) ) ;
201
195
}
202
196
}
203
197
}
@@ -207,7 +201,7 @@ impl Mangler {
207
201
let frequencies = self . tally_slot_frequencies (
208
202
& symbol_table,
209
203
& exported_symbols,
210
- scope_tree,
204
+ & scope_tree,
211
205
total_number_of_slots,
212
206
& slots,
213
207
& allocator,
0 commit comments