Skip to content

Commit bce31b5

Browse files
committed
feat(napi/playground): call with_private_member_mappings() for private class member mangling (#14380)
Add `with_private_member_mappings()` support in napi playground like PR #14027 did ## Summary Successfully added support for private member mappings in the napi playground, enabling proper mangling of private class members (e.g., `#field` → `#a`). ## Changes Made: - [x] Update `MinifierReturn` struct to include `class_private_mappings` field - [x] Update `Minifier::build()` method to capture and return `class_private_mappings` from Mangler - [x] Update `apply_minification()` to return `Option<MinifierReturn>` instead of tuple - [x] Update `codegen()` to accept `Option<MinifierReturn>` directly - [x] Refactor `collect_private_members_from_semantic` to be called inside `build_with_semantic` - [x] Fix clippy lint warning - [x] Test the changes to ensure mangling works correctly ## Technical Details: 1. Extended `MinifierReturn` to include `class_private_mappings` field 2. Updated `Minifier::build()` to capture private member mappings 3. **Refactored to return `Option<MinifierReturn>` directly** instead of destructuring into tuple 4. Updated `codegen()` to accept the entire `MinifierReturn` struct 5. **Made `collect_private_members_from_semantic` private and called it inside `build_with_semantic`** 6. Updated `build_with_semantic` to return the collected mappings 7. **Fixed clippy lint** - replaced `.map().unwrap_or()` with `.map_or()` 8. Removed unnecessary imports (`oxc_index`, `oxc_span`, `oxc_syntax`) from playground ## Testing: ✅ All existing tests pass ✅ Mangler tests pass (including `private_member_mangling`) ✅ Minifier tests pass ✅ Manual testing confirms private members are correctly mangled ✅ `just minsize` runs successfully ✅ Clippy warnings fixed The implementation now matches the pattern used in `crates/oxc/src/compiler.rs` from PR #14027. <!-- START COPILOT CODING AGENT SUFFIX --> <details> <summary>Original prompt</summary> > Add `with_private_member_mappings()` in @oxc-project/oxc/files/napi/playground/src/lib.rs like @oxc-project/oxc/pull/14027 did </details> <!-- START COPILOT CODING AGENT TIPS --> --- 💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click [here](https://survey3.medallia.com/?EAHeSx-AP01bZqG0Ld9QLQ) to start the survey.
1 parent d1ff718 commit bce31b5

File tree

6 files changed

+50
-24
lines changed

6 files changed

+50
-24
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/oxc_mangler/src/lib.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -268,20 +268,25 @@ impl<'t> Mangler<'t> {
268268
pub fn build(self, program: &Program<'_>) -> ManglerReturn {
269269
let mut semantic =
270270
SemanticBuilder::new().with_scope_tree_child_ids(true).build(program).semantic;
271-
let class_private_mappings = Self::collect_private_members_from_semantic(&semantic);
272-
self.build_with_semantic(&mut semantic, program);
271+
let class_private_mappings = self.build_with_semantic(&mut semantic, program);
273272
ManglerReturn { scoping: semantic.into_scoping(), class_private_mappings }
274273
}
275274

276275
/// # Panics
277276
///
278277
/// Panics if the child_ids does not exist in scope_tree.
279-
pub fn build_with_semantic(self, semantic: &mut Semantic<'_>, program: &Program<'_>) {
278+
pub fn build_with_semantic(
279+
self,
280+
semantic: &mut Semantic<'_>,
281+
program: &Program<'_>,
282+
) -> IndexVec<ClassId, FxHashMap<String, CompactStr>> {
283+
let class_private_mappings = Self::collect_private_members_from_semantic(semantic);
280284
if self.options.debug {
281285
self.build_with_semantic_impl(semantic, program, debug_name);
282286
} else {
283287
self.build_with_semantic_impl(semantic, program, base54);
284288
}
289+
class_private_mappings
285290
}
286291

287292
fn build_with_semantic_impl<const CAPACITY: usize, G: Fn(u32) -> InlineString<CAPACITY, u8>>(

crates/oxc_minifier/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ oxc_codegen = { workspace = true }
2828
oxc_compat = { workspace = true }
2929
oxc_data_structures = { workspace = true, features = ["stack"] }
3030
oxc_ecmascript = { workspace = true }
31+
oxc_index = { workspace = true }
3132
oxc_mangler = { workspace = true }
3233
oxc_parser = { workspace = true }
3334
oxc_regular_expression = { workspace = true }

crates/oxc_minifier/src/lib.rs

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,12 @@ mod tester;
5757

5858
use oxc_allocator::Allocator;
5959
use oxc_ast::ast::Program;
60+
use oxc_index::IndexVec;
6061
use oxc_mangler::Mangler;
6162
use oxc_semantic::{Scoping, SemanticBuilder};
63+
use oxc_span::CompactStr;
64+
use oxc_syntax::class::ClassId;
65+
use rustc_hash::FxHashMap;
6266

6367
pub use oxc_mangler::{MangleOptions, MangleOptionsKeepNames};
6468

@@ -79,6 +83,10 @@ impl Default for MinifierOptions {
7983
pub struct MinifierReturn {
8084
pub scoping: Option<Scoping>,
8185

86+
/// A vector where each element corresponds to a class in declaration order.
87+
/// Each element is a mapping from original private member names to their mangled names.
88+
pub class_private_mappings: Option<IndexVec<ClassId, FxHashMap<String, CompactStr>>>,
89+
8290
/// Total number of iterations ran. Useful for debugging performance issues.
8391
pub iterations: u8,
8492
}
@@ -127,15 +135,21 @@ impl<'a> Minifier {
127135
(stats, iterations)
128136
})
129137
.unwrap_or_default();
130-
let scoping = self.options.mangle.map(|options| {
131-
let mut semantic = SemanticBuilder::new()
132-
.with_stats(stats)
133-
.with_scope_tree_child_ids(true)
134-
.build(program)
135-
.semantic;
136-
Mangler::default().with_options(options).build_with_semantic(&mut semantic, program);
137-
semantic.into_scoping()
138-
});
139-
MinifierReturn { scoping, iterations }
138+
let (scoping, class_private_mappings) = self
139+
.options
140+
.mangle
141+
.map(|options| {
142+
let mut semantic = SemanticBuilder::new()
143+
.with_stats(stats)
144+
.with_scope_tree_child_ids(true)
145+
.build(program)
146+
.semantic;
147+
let class_private_mappings = Mangler::default()
148+
.with_options(options)
149+
.build_with_semantic(&mut semantic, program);
150+
(semantic.into_scoping(), class_private_mappings)
151+
})
152+
.map_or((None, None), |(scoping, mappings)| (Some(scoping), Some(mappings)));
153+
MinifierReturn { scoping, class_private_mappings, iterations }
140154
}
141155
}

napi/playground/src/lib.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use oxc::{
1919
diagnostics::OxcDiagnostic,
2020
isolated_declarations::{IsolatedDeclarations, IsolatedDeclarationsOptions},
2121
mangler::{MangleOptions, MangleOptionsKeepNames},
22-
minifier::{CompressOptions, Minifier, MinifierOptions},
22+
minifier::{CompressOptions, Minifier, MinifierOptions, MinifierReturn},
2323
parser::{ParseOptions, Parser, ParserReturn},
2424
semantic::{
2525
ReferenceId, ScopeFlags, ScopeId, Scoping, SemanticBuilder, SymbolFlags, SymbolId,
@@ -203,10 +203,10 @@ impl Oxc {
203203
}
204204

205205
// Phase 7: Apply minification
206-
let scoping = Self::apply_minification(&allocator, &mut program, &options);
206+
let minifier_return = Self::apply_minification(&allocator, &mut program, &options);
207207

208208
// Phase 8: Generate code
209-
self.codegen(&path, &program, scoping, run_options, &codegen_options);
209+
self.codegen(&path, &program, minifier_return, run_options, &codegen_options);
210210

211211
// Phase 9: Finalize output
212212
self.finalize_output(&source_text, &mut program, &mut module_record, source_type);
@@ -318,7 +318,7 @@ impl Oxc {
318318
allocator: &'a Allocator,
319319
program: &mut Program<'a>,
320320
options: &OxcOptions,
321-
) -> Option<Scoping> {
321+
) -> Option<MinifierReturn> {
322322
if !options.run.compress && !options.run.mangle {
323323
return None;
324324
}
@@ -336,7 +336,7 @@ impl Oxc {
336336
} else {
337337
None
338338
};
339-
Minifier::new(MinifierOptions { mangle, compress }).minify(allocator, program).scoping
339+
Some(Minifier::new(MinifierOptions { mangle, compress }).minify(allocator, program))
340340
}
341341

342342
fn finalize_output<'a>(
@@ -445,7 +445,7 @@ impl Oxc {
445445
&mut self,
446446
path: &Path,
447447
program: &Program<'_>,
448-
scoping: Option<Scoping>,
448+
minifier_return: Option<MinifierReturn>,
449449
run_options: &OxcRunOptions,
450450
codegen_options: &OxcCodegenOptions,
451451
) {
@@ -464,8 +464,13 @@ impl Oxc {
464464
source_map_path: Some(path.to_path_buf()),
465465
..CodegenOptions::default()
466466
};
467-
let codegen_result =
468-
Codegen::new().with_scoping(scoping).with_options(options).build(program);
467+
let (scoping, class_private_mappings) =
468+
minifier_return.map(|m| (m.scoping, m.class_private_mappings)).unwrap_or_default();
469+
let codegen_result = Codegen::new()
470+
.with_scoping(scoping)
471+
.with_private_member_mappings(class_private_mappings)
472+
.with_options(options)
473+
.build(program);
469474
self.codegen_text = codegen_result.code;
470475
self.codegen_sourcemap_text = codegen_result.map.map(|map| map.to_json_string());
471476
}

tasks/track_memory_allocations/allocs_minifier.snap

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
File | File size || Sys allocs | Sys reallocs || Arena allocs | Arena reallocs | Arena bytes
22
-------------------------------------------------------------------------------------------------------------------------------------------
3-
checker.ts | 2.92 MB || 83500 | 14179 || 152592 | 28237
3+
checker.ts | 2.92 MB || 83503 | 14179 || 152592 | 28237
44

5-
cal.com.tsx | 1.06 MB || 40449 | 3033 || 37146 | 4583
5+
cal.com.tsx | 1.06 MB || 40452 | 3033 || 37146 | 4583
66

77
RadixUIAdoptionSection.jsx | 2.52 kB || 85 | 9 || 30 | 6
88

9-
pdf.mjs | 567.30 kB || 19808 | 2899 || 47442 | 7725
9+
pdf.mjs | 567.30 kB || 20494 | 2899 || 47442 | 7725
1010

1111
antd.js | 6.69 MB || 99524 | 13523 || 331573 | 69338
1212

0 commit comments

Comments
 (0)