feat(minifier): fold simple literals passed to unary + (#8943)

Added support for folding `+[]` and `+/any-regex/`.

`+` uses `ToNumber` and `ToNumber` uses `ToPrimitive` for objects. `ToPrimitive` for `[]` returns `""`, for `/any-regex/` it returns `"/any-regex/"`.

**References**
- [Spec of unary `+`](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-unary-plus-operator-runtime-semantics-evaluation)
- [Spec of `ToPrimitive`](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-toprimitive)
This commit is contained in:
sapphi-red committed 2025-02-07 15:35:59 +00:00
1 parent cad04d6a3f
commit 14462be069
2 files changed
+15 -2

No files matched your search

@@ -145,7 +145,20 @@ pub trait ConstantEvaluation<'a>: MayHaveSideEffects {
Expression::SequenceExpression(s) => {
s.expressions.last().and_then(|e| self.eval_to_number(e))
}
// If the object is empty, `toString` / `valueOf` / `Symbol.toPrimitive` is not overridden.
// (assuming that those methods in Object.prototype are not modified)
// In that case, `ToPrimitive` returns `"[object Object]"`
Expression::ObjectExpression(e) if e.properties.is_empty() => Some(f64::NAN),
// `ToPrimitive` for RegExp object returns `"/regexp/"`
Expression::RegExpLiteral(_) => Some(f64::NAN),
Expression::ArrayExpression(arr) => {
// If the array is empty, `ToPrimitive` returns `""`
if arr.elements.is_empty() {
Some(0.0)
} else {
None
}
}
expr => {
use crate::ToNumber;
expr.to_number()
@@ -891,9 +891,9 @@ fn constant_evaluation_test() {
test("x = !5", "x = !1;");
test("x = typeof 5", "x = 'number';");
test("x = +''", "x = 0;");
// test("x = +[]", "x = 0;");
test("x = +[]", "x = 0;");
test("x = +{}", "x = NaN;");
// test("x = +/1/", "x = NaN;");
test("x = +/1/", "x = NaN;");
test("x = +[1]", "x = +[1];");
test("x = +'123'", "x = 123;");
test("x = +'-123'", "x = -123;");