mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 20:28:58 +00:00
refactor(minifier): clean up ReplaceKnownMethods
This commit is contained in:
parent
bd8d677352
commit
0845162372
1 changed files with 25 additions and 67 deletions
|
|
@ -1,4 +1,7 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use cow_utils::CowUtils;
|
||||
|
||||
use oxc_ast::ast::*;
|
||||
use oxc_ecmascript::{
|
||||
constant_evaluation::ConstantEvaluation, StringCharAt, StringCharCodeAt, StringIndexOf,
|
||||
|
|
@ -37,55 +40,24 @@ impl PeepholeReplaceKnownMethods {
|
|||
node: &mut Expression<'a>,
|
||||
ctx: &mut TraverseCtx<'a>,
|
||||
) {
|
||||
let Expression::CallExpression(call_expr) = node else { return };
|
||||
|
||||
let Expression::StaticMemberExpression(member) = &call_expr.callee else { return };
|
||||
if let Expression::StringLiteral(string_lit) = &member.object {
|
||||
let Expression::CallExpression(ce) = node else { return };
|
||||
let Expression::StaticMemberExpression(member) = &ce.callee else { return };
|
||||
if let Expression::StringLiteral(s) = &member.object {
|
||||
let replacement = match member.property.name.as_str() {
|
||||
"toLowerCase" | "toUpperCase" | "trim" => match member.property.name.as_str() {
|
||||
"toLowerCase" => Some(ctx.ast.expression_string_literal(
|
||||
call_expr.span,
|
||||
string_lit.value.cow_to_lowercase(),
|
||||
None,
|
||||
)),
|
||||
"toUpperCase" => Some(ctx.ast.expression_string_literal(
|
||||
call_expr.span,
|
||||
string_lit.value.cow_to_uppercase(),
|
||||
None,
|
||||
)),
|
||||
"trim" => Some(ctx.ast.expression_string_literal(
|
||||
call_expr.span,
|
||||
string_lit.value.trim(),
|
||||
None,
|
||||
)),
|
||||
_ => None,
|
||||
},
|
||||
"indexOf" | "lastIndexOf" => Self::try_fold_string_index_of(
|
||||
call_expr.span,
|
||||
call_expr,
|
||||
member,
|
||||
string_lit,
|
||||
ctx,
|
||||
),
|
||||
"substring" | "slice" => Self::try_fold_string_substring_or_slice(
|
||||
call_expr.span,
|
||||
call_expr,
|
||||
string_lit,
|
||||
ctx,
|
||||
),
|
||||
"charAt" => {
|
||||
Self::try_fold_string_char_at(call_expr.span, call_expr, string_lit, ctx)
|
||||
"toLowerCase" | "toUpperCase" | "trim" => {
|
||||
let value = match member.property.name.as_str() {
|
||||
"toLowerCase" => s.value.cow_to_lowercase(),
|
||||
"toUpperCase" => s.value.cow_to_uppercase(),
|
||||
"trim" => Cow::Borrowed(s.value.trim()),
|
||||
_ => return,
|
||||
};
|
||||
Some(ctx.ast.expression_string_literal(ce.span, value, None))
|
||||
}
|
||||
"charCodeAt" => {
|
||||
Self::try_fold_string_char_code_at(call_expr.span, call_expr, string_lit, ctx)
|
||||
}
|
||||
"replace" | "replaceAll" => Self::try_fold_string_replace_or_string_replace_all(
|
||||
call_expr.span,
|
||||
call_expr,
|
||||
member,
|
||||
string_lit,
|
||||
ctx,
|
||||
),
|
||||
"indexOf" | "lastIndexOf" => Self::try_fold_string_index_of(ce, member, s, ctx),
|
||||
"substring" | "slice" => Self::try_fold_string_substring_or_slice(ce, s, ctx),
|
||||
"charAt" => Self::try_fold_string_char_at(ce, s, ctx),
|
||||
"charCodeAt" => Self::try_fold_string_char_code_at(ce, s, ctx),
|
||||
"replace" | "replaceAll" => Self::try_fold_string_replace(ce, member, s, ctx),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
|
|
@ -97,7 +69,6 @@ impl PeepholeReplaceKnownMethods {
|
|||
}
|
||||
|
||||
fn try_fold_string_index_of<'a>(
|
||||
span: Span,
|
||||
call_expr: &CallExpression<'a>,
|
||||
member: &StaticMemberExpression<'a>,
|
||||
string_lit: &StringLiteral<'a>,
|
||||
|
|
@ -108,13 +79,11 @@ impl PeepholeReplaceKnownMethods {
|
|||
None => None,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let search_start_index = match call_expr.arguments.get(1) {
|
||||
Some(Argument::NumericLiteral(numeric_lit)) => Some(numeric_lit.value),
|
||||
None => None,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let result = match member.property.name.as_str() {
|
||||
"indexOf" => string_lit.value.as_str().index_of(search_value, search_start_index),
|
||||
"lastIndexOf" => {
|
||||
|
|
@ -122,13 +91,12 @@ impl PeepholeReplaceKnownMethods {
|
|||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let span = call_expr.span;
|
||||
#[expect(clippy::cast_precision_loss)]
|
||||
Some(ctx.ast.expression_numeric_literal(span, result as f64, None, NumberBase::Decimal))
|
||||
}
|
||||
|
||||
fn try_fold_string_substring_or_slice<'a>(
|
||||
span: Span,
|
||||
call_expr: &CallExpression<'a>,
|
||||
string_lit: &StringLiteral<'a>,
|
||||
ctx: &mut TraverseCtx<'a>,
|
||||
|
|
@ -136,7 +104,7 @@ impl PeepholeReplaceKnownMethods {
|
|||
if call_expr.arguments.len() > 2 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let span = call_expr.span;
|
||||
let start_idx = call_expr.arguments.first().and_then(|arg| match arg {
|
||||
Argument::SpreadElement(_) => None,
|
||||
_ => Ctx(ctx).get_side_free_number_value(arg.to_expression()),
|
||||
|
|
@ -145,20 +113,17 @@ impl PeepholeReplaceKnownMethods {
|
|||
Argument::SpreadElement(_) => None,
|
||||
_ => Ctx(ctx).get_side_free_number_value(arg.to_expression()),
|
||||
});
|
||||
|
||||
#[expect(clippy::cast_precision_loss)]
|
||||
if start_idx.is_some_and(|start| start > string_lit.value.len() as f64 || start < 0.0)
|
||||
|| end_idx.is_some_and(|end| end > string_lit.value.len() as f64 || end < 0.0)
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
if let (Some(start), Some(end)) = (start_idx, end_idx) {
|
||||
if start > end {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
Some(ctx.ast.expression_string_literal(
|
||||
span,
|
||||
string_lit.value.as_str().substring(start_idx, end_idx),
|
||||
|
|
@ -167,7 +132,6 @@ impl PeepholeReplaceKnownMethods {
|
|||
}
|
||||
|
||||
fn try_fold_string_char_at<'a>(
|
||||
span: Span,
|
||||
call_expr: &CallExpression<'a>,
|
||||
string_lit: &StringLiteral<'a>,
|
||||
ctx: &mut TraverseCtx<'a>,
|
||||
|
|
@ -175,7 +139,7 @@ impl PeepholeReplaceKnownMethods {
|
|||
if call_expr.arguments.len() > 1 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let span = call_expr.span;
|
||||
let char_at_index: Option<f64> = match call_expr.arguments.first() {
|
||||
Some(Argument::NumericLiteral(numeric_lit)) => Some(numeric_lit.value),
|
||||
Some(Argument::UnaryExpression(unary_expr))
|
||||
|
|
@ -200,7 +164,6 @@ impl PeepholeReplaceKnownMethods {
|
|||
}
|
||||
|
||||
fn try_fold_string_char_code_at<'a>(
|
||||
span: Span,
|
||||
call_expr: &CallExpression<'a>,
|
||||
string_lit: &StringLiteral<'a>,
|
||||
ctx: &mut TraverseCtx<'a>,
|
||||
|
|
@ -209,16 +172,14 @@ impl PeepholeReplaceKnownMethods {
|
|||
Argument::SpreadElement(_) => None,
|
||||
_ => Ctx(ctx).get_side_free_number_value(arg.to_expression()),
|
||||
})?;
|
||||
|
||||
let span = call_expr.span;
|
||||
// TODO: if `result` is `None`, return `NaN` instead of skipping the optimization
|
||||
let result = string_lit.value.as_str().char_code_at(Some(char_at_index))?;
|
||||
|
||||
#[expect(clippy::cast_lossless)]
|
||||
Some(ctx.ast.expression_numeric_literal(span, result as f64, None, NumberBase::Decimal))
|
||||
}
|
||||
|
||||
fn try_fold_string_replace_or_string_replace_all<'a>(
|
||||
span: Span,
|
||||
fn try_fold_string_replace<'a>(
|
||||
call_expr: &CallExpression<'a>,
|
||||
member: &StaticMemberExpression<'a>,
|
||||
string_lit: &StringLiteral<'a>,
|
||||
|
|
@ -227,7 +188,7 @@ impl PeepholeReplaceKnownMethods {
|
|||
if call_expr.arguments.len() != 2 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let span = call_expr.span;
|
||||
let search_value = call_expr.arguments.first().unwrap();
|
||||
let search_value = match search_value {
|
||||
Argument::SpreadElement(_) => return None,
|
||||
|
|
@ -242,11 +203,9 @@ impl PeepholeReplaceKnownMethods {
|
|||
Ctx(ctx).get_side_free_string_value(replace_value.to_expression())?
|
||||
}
|
||||
};
|
||||
|
||||
if replace_value.contains('$') {
|
||||
return None;
|
||||
}
|
||||
|
||||
let result = match member.property.name.as_str() {
|
||||
"replace" => {
|
||||
string_lit.value.as_str().cow_replacen(search_value.as_ref(), &replace_value, 1)
|
||||
|
|
@ -256,7 +215,6 @@ impl PeepholeReplaceKnownMethods {
|
|||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
Some(ctx.ast.expression_string_literal(span, result, None))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue