Skip to content

Commit

Permalink
Support for converting ArrayLits to numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
levi-nz committed Jul 11, 2024
1 parent 381f09f commit ff2749d
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 0 deletions.
21 changes: 21 additions & 0 deletions crates/swc_ecma_transforms_optimization/src/simplify/expr/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,27 @@ fn test_unary_ops_4() {
fold("a=~~0xffffffff", "a=-1");
}

#[test]
fn test_unary_ops_5() {
// Empty arrays
fold("+[]", "0");
fold("+[[]]", "0");
fold("+[[[]]]", "0");

// Arrays with one element
fold("+[1]", "1");
fold("+[[1]]", "1");
fold("+[undefined]", "0");
fold("+[null]", "0");
fold("+[,]", "0");

// Arrays with more than one element
fold("+[1, 2]", "NaN");
fold("+[[1], 2]", "NaN");
fold("+[,1]", "NaN");
fold("+[,,]", "NaN");
}

#[test]
fn test_unary_ops_string_compare() {
fold_same("a = -1");
Expand Down
33 changes: 33 additions & 0 deletions crates/swc_ecma_utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,39 @@ pub trait ExprExt {
Lit::Str(Str { value, .. }) => return (Pure, num_from_str(value)),
_ => return (Pure, Unknown),
},
Expr::Array(array) => {
if array.elems.len() != 1 {
// Can only be converted to a number if there's exactly one element.
return (Pure, Known(if array.elems.is_empty() {
// Empty array is treated as zero.
0.0
} else {
// More than one element is treated as NaN.
f64::NAN
}));
}

let Some(elem) = array.elems.get(0) else {
return (Pure, Unknown);
};

// [,] is treated as zero.
let Some(e) = elem else {
return (Pure, Known(0.0));
};

// Ignore spread if it exists.
if e.spread.is_some() {
return (Pure, Unknown);
}

// Special case: undefined is treated as zero in arrays (e.g. +[undefined])
if e.expr.is_undefined(ctx) {
return (Pure, Known(0.0));
}

return e.expr.cast_to_number(ctx);
},
Expr::Ident(Ident { sym, span, .. }) => match &**sym {
"undefined" | "NaN" if span.ctxt == ctx.unresolved_ctxt => f64::NAN,
"Infinity" if span.ctxt == ctx.unresolved_ctxt => f64::INFINITY,
Expand Down

0 comments on commit ff2749d

Please sign in to comment.