@@ -2,15 +2,15 @@ use std::iter::{self, repeat_with};
22
33use itertools:: Itertools ;
44use keep_names:: collect_name_symbols;
5- use rustc_hash:: FxHashSet ;
5+ use rustc_hash:: { FxHashMap , FxHashSet } ;
66
77use base54:: base54;
88use oxc_allocator:: { Allocator , BitSet , Vec } ;
99use oxc_ast:: ast:: { Declaration , Program , Statement } ;
1010use oxc_data_structures:: inline_string:: InlineString ;
1111use oxc_index:: Idx ;
1212use oxc_semantic:: { AstNodes , Scoping , Semantic , SemanticBuilder , SymbolId } ;
13- use oxc_span:: Atom ;
13+ use oxc_span:: { Atom , CompactStr } ;
1414
1515pub ( crate ) mod base54;
1616mod keep_names;
@@ -56,6 +56,13 @@ impl TempAllocator<'_> {
5656 }
5757}
5858
59+ pub struct ManglerReturn {
60+ pub scoping : Scoping ,
61+ /// A vector where each element corresponds to a class in declaration order.
62+ /// Each element is a mapping from original private member names to their mangled names.
63+ pub class_private_mappings : std:: vec:: Vec < FxHashMap < String , CompactStr > > ,
64+ }
65+
5966/// # Name Mangler / Symbol Minification
6067///
6168/// ## Example
@@ -257,11 +264,12 @@ impl<'t> Mangler<'t> {
257264 /// Mangles the program. The resulting SymbolTable contains the mangled symbols - `program` is not modified.
258265 /// Pass the symbol table to oxc_codegen to generate the mangled code.
259266 #[ must_use]
260- pub fn build ( self , program : & Program < ' _ > ) -> Scoping {
267+ pub fn build ( self , program : & Program < ' _ > ) -> ManglerReturn {
261268 let mut semantic =
262269 SemanticBuilder :: new ( ) . with_scope_tree_child_ids ( true ) . build ( program) . semantic ;
270+ let class_private_mappings = Self :: collect_private_members_from_semantic ( & semantic) ;
263271 self . build_with_semantic ( & mut semantic, program) ;
264- semantic. into_scoping ( )
272+ ManglerReturn { scoping : semantic. into_scoping ( ) , class_private_mappings }
265273 }
266274
267275 /// # Panics
@@ -548,6 +556,36 @@ impl<'t> Mangler<'t> {
548556 let ids = collect_name_symbols ( keep_names, scoping, nodes) ;
549557 ( ids. iter ( ) . map ( |id| scoping. symbol_name ( * id) ) . collect ( ) , ids)
550558 }
559+
560+ /// Collects and generates mangled names for private members using semantic information
561+ /// Returns a Vec where each element corresponds to a class in declaration order
562+ fn collect_private_members_from_semantic (
563+ semantic : & Semantic < ' _ > ,
564+ ) -> std:: vec:: Vec < FxHashMap < String , CompactStr > > {
565+ let classes = semantic. classes ( ) ;
566+ classes
567+ . elements
568+ . iter ( )
569+ . map ( |class_elements| {
570+ assert ! ( u32 :: try_from( class_elements. len( ) ) . is_ok( ) , "too many class elements" ) ;
571+ class_elements
572+ . iter ( )
573+ . filter_map ( |element| {
574+ if element. is_private { Some ( element. name . to_string ( ) ) } else { None }
575+ } )
576+ . enumerate ( )
577+ . map ( |( i, name) | {
578+ #[ expect(
579+ clippy:: cast_possible_truncation,
580+ reason = "checked above with assert"
581+ ) ]
582+ let mangled = CompactStr :: new ( base54 ( i as u32 ) . as_str ( ) ) ;
583+ ( name, mangled)
584+ } )
585+ . collect :: < FxHashMap < _ , _ > > ( )
586+ } )
587+ . collect ( )
588+ }
551589}
552590
553591fn is_special_name ( name : & str ) -> bool {
0 commit comments