mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
feat(minifier): minimize x["0"] -> x[0] (#8316)
This commit is contained in:
parent
a542013773
commit
051fbb6909
4 changed files with 78 additions and 19 deletions
|
|
@ -46,15 +46,22 @@ impl<'a> ConvertToDottedProperties {
|
|||
) {
|
||||
if let MemberExpression::ComputedMemberExpression(e) = expr {
|
||||
let Expression::StringLiteral(s) = &e.expression else { return };
|
||||
if !is_identifier_name(&s.value) {
|
||||
if is_identifier_name(&s.value) {
|
||||
let property = ctx.ast.identifier_name(s.span, s.value.clone());
|
||||
let object = ctx.ast.move_expression(&mut e.object);
|
||||
*expr = MemberExpression::StaticMemberExpression(
|
||||
ctx.ast.alloc_static_member_expression(e.span, object, property, e.optional),
|
||||
);
|
||||
self.changed = true;
|
||||
return;
|
||||
}
|
||||
let property = ctx.ast.identifier_name(s.span, s.value.clone());
|
||||
let object = ctx.ast.move_expression(&mut e.object);
|
||||
*expr = MemberExpression::StaticMemberExpression(
|
||||
ctx.ast.alloc_static_member_expression(e.span, object, property, e.optional),
|
||||
);
|
||||
self.changed = true;
|
||||
let v = s.value.as_str();
|
||||
if !e.optional {
|
||||
if let Some(n) = Ctx::string_to_equivalent_number_value(v) {
|
||||
e.expression =
|
||||
ctx.ast.expression_numeric_literal(s.span, n, None, NumberBase::Decimal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -110,7 +117,6 @@ mod test {
|
|||
test_same("a[';']");
|
||||
test_same("a[':']");
|
||||
test_same("a['.']");
|
||||
test_same("a['0']");
|
||||
test_same("a['p ']");
|
||||
test_same("a['p' + '']");
|
||||
test_same("a[p]");
|
||||
|
|
@ -282,4 +288,29 @@ mod test {
|
|||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_index() {
|
||||
test("x['y']", "x.y;");
|
||||
test_same("x['y z']");
|
||||
test("x?.['y']", "x?.y;");
|
||||
test_same("x?.['y z']");
|
||||
test("x?.['y']()", "x?.y();");
|
||||
test_same("x?.['y z']()");
|
||||
test_same("x['y' + 'z']");
|
||||
test_same("x?.['y' + 'z']");
|
||||
test("x['0']", "x[0];");
|
||||
test("x['123']", "x[123];");
|
||||
test("x['-123']", "x[-123];");
|
||||
test_same("x['-0']");
|
||||
test_same("x['+0']");
|
||||
test_same("x['01']");
|
||||
test_same("x['-01']");
|
||||
test_same("x['0x1']");
|
||||
test_same("x['-0x1']");
|
||||
test("x['2147483647']", "x[2147483647]");
|
||||
test_same("x['2147483648']");
|
||||
test_same("x['-2147483648']");
|
||||
test_same("x['-2147483649']");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -843,16 +843,14 @@ impl<'a, 'b> PeepholeSubstituteAlternateSyntax {
|
|||
*key = PropertyKey::StaticIdentifier(
|
||||
ctx.ast.alloc_identifier_name(s.span, s.value.clone()),
|
||||
);
|
||||
} else if (!s.value.starts_with('0') && !s.value.starts_with('+')) || s.value.len() <= 1 {
|
||||
if let Ok(value) = s.value.parse::<u32>() {
|
||||
self.changed = true;
|
||||
*key = PropertyKey::NumericLiteral(ctx.ast.alloc_numeric_literal(
|
||||
s.span,
|
||||
value as f64,
|
||||
None,
|
||||
NumberBase::Decimal,
|
||||
));
|
||||
}
|
||||
} else if let Some(value) = Ctx::string_to_equivalent_number_value(s.value.as_str()) {
|
||||
self.changed = true;
|
||||
*key = PropertyKey::NumericLiteral(ctx.ast.alloc_numeric_literal(
|
||||
s.span,
|
||||
value,
|
||||
None,
|
||||
NumberBase::Decimal,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,4 +82,34 @@ impl<'a> Ctx<'a, '_> {
|
|||
}
|
||||
false
|
||||
}
|
||||
|
||||
// https://github.com/evanw/esbuild/blob/v0.24.2/internal/js_ast/js_ast_helpers.go#L2641
|
||||
pub fn string_to_equivalent_number_value(s: &str) -> Option<f64> {
|
||||
if s.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let mut is_negative = false;
|
||||
let mut int_value = 0i32;
|
||||
let mut start = 0;
|
||||
let bytes = s.as_bytes();
|
||||
if bytes[0] == b'-' && s.len() > 1 {
|
||||
is_negative = true;
|
||||
start += 1;
|
||||
}
|
||||
if bytes[start] == b'0' && s.len() > 1 {
|
||||
return None;
|
||||
}
|
||||
for b in &bytes[start..] {
|
||||
if b.is_ascii_digit() {
|
||||
int_value =
|
||||
int_value.checked_mul(10).and_then(|v| v.checked_add(i32::from(b & 15)))?;
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
if is_negative {
|
||||
int_value = -int_value;
|
||||
}
|
||||
Some(f64::from(int_value))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ Original | minified | minified | gzip | gzip | Fixture
|
|||
|
||||
3.20 MB | 1.01 MB | 1.01 MB | 331.88 kB | 331.56 kB | echarts.js
|
||||
|
||||
6.69 MB | 2.32 MB | 2.31 MB | 492.76 kB | 488.28 kB | antd.js
|
||||
6.69 MB | 2.32 MB | 2.31 MB | 492.77 kB | 488.28 kB | antd.js
|
||||
|
||||
10.95 MB | 3.50 MB | 3.49 MB | 909.12 kB | 915.50 kB | typescript.js
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue