mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
perf(minifier): avoid repeated Atom creation in InjectGlobalVariables (#4802)
Re-use `Atom`s in `InjectGlobalVariables` minifier plugin. Instead of allocating a new `Atom` on every replacement, create `Atom` lazily when making first replacement, and cache it. As discussed in: https://github.com/oxc-project/oxc/pull/4759#discussion_r1711669464
This commit is contained in:
parent
62f759c1f2
commit
35f27420b9
1 changed files with 21 additions and 7 deletions
|
|
@ -83,11 +83,20 @@ impl InjectImportSpecifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&InjectImport> for DotDefine {
|
/// Wrapper around `DotDefine` which caches the `Atom` to replace with.
|
||||||
|
/// `value_atom` is populated lazily when first replacement happens.
|
||||||
|
/// If no replacement is made, `value_atom` remains `None`.
|
||||||
|
struct DotDefineState<'a> {
|
||||||
|
dot_define: DotDefine,
|
||||||
|
value_atom: Option<Atom<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&InjectImport> for DotDefineState<'a> {
|
||||||
fn from(inject: &InjectImport) -> Self {
|
fn from(inject: &InjectImport) -> Self {
|
||||||
let parts = inject.specifier.local().split('.').map(CompactStr::from).collect::<Vec<_>>();
|
let parts = inject.specifier.local().split('.').map(CompactStr::from).collect::<Vec<_>>();
|
||||||
let value = inject.replace_value.clone().unwrap();
|
let value = inject.replace_value.clone().unwrap();
|
||||||
Self { parts, value }
|
let dot_define = DotDefine { parts, value };
|
||||||
|
Self { dot_define, value_atom: None }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -102,7 +111,7 @@ pub struct InjectGlobalVariables<'a> {
|
||||||
|
|
||||||
// states
|
// states
|
||||||
/// Dot defines derived from the config.
|
/// Dot defines derived from the config.
|
||||||
dot_defines: Vec<DotDefine>,
|
dot_defines: Vec<DotDefineState<'a>>,
|
||||||
|
|
||||||
/// Identifiers for which dot define replaced a member expression.
|
/// Identifiers for which dot define replaced a member expression.
|
||||||
replaced_dot_defines:
|
replaced_dot_defines:
|
||||||
|
|
@ -138,7 +147,7 @@ impl<'a> InjectGlobalVariables<'a> {
|
||||||
.injects
|
.injects
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|i| i.replace_value.is_some())
|
.filter(|i| i.replace_value.is_some())
|
||||||
.map(DotDefine::from)
|
.map(DotDefineState::from)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
if !dot_defines.is_empty() {
|
if !dot_defines.is_empty() {
|
||||||
|
|
@ -211,10 +220,15 @@ impl<'a> InjectGlobalVariables<'a> {
|
||||||
|
|
||||||
fn replace_dot_defines(&mut self, expr: &mut Expression<'a>) {
|
fn replace_dot_defines(&mut self, expr: &mut Expression<'a>) {
|
||||||
if let Expression::StaticMemberExpression(member) = expr {
|
if let Expression::StaticMemberExpression(member) = expr {
|
||||||
for dot_define in &self.dot_defines {
|
for DotDefineState { dot_define, value_atom } in &mut self.dot_defines {
|
||||||
if ReplaceGlobalDefines::is_dot_define(dot_define, member) {
|
if ReplaceGlobalDefines::is_dot_define(dot_define, member) {
|
||||||
let value =
|
// Create `Atom` for replacement lazily on first replacement
|
||||||
self.ast.expression_identifier_reference(SPAN, dot_define.value.as_str());
|
if value_atom.is_none() {
|
||||||
|
*value_atom = Some(self.ast.atom(dot_define.value.as_str()));
|
||||||
|
}
|
||||||
|
let value_atom = value_atom.as_ref().unwrap().clone();
|
||||||
|
|
||||||
|
let value = self.ast.expression_identifier_reference(SPAN, value_atom);
|
||||||
*expr = value;
|
*expr = value;
|
||||||
self.replaced_dot_defines
|
self.replaced_dot_defines
|
||||||
.push((dot_define.parts[0].clone(), dot_define.value.clone()));
|
.push((dot_define.parts[0].clone(), dot_define.value.clone()));
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue