feat(ecmascript): support arrays and objects for unary expression may_have_side_effects (#8990)

Detect `+[]` / `+{}` as side effect free.
This commit is contained in:
sapphi-red committed 2025-02-10 05:36:13 +00:00
1 parent 660c314f4e
commit 2a10a99444
2 files changed
+18

No files matched your search

@@ -82,6 +82,12 @@ pub trait MayHaveSideEffects {
!(matches!(ident.name.as_str(), "Infinity" | "NaN" | "undefined")
&& self.is_global_reference(ident))
}
Expression::ArrayExpression(arr) => {
self.array_expression_may_have_side_effects(arr)
}
// unless `Symbol.toPrimitive`, `valueOf`, `toString` is overridden,
// ToPrimitive for an object returns `"[object Object]"`
Expression::ObjectExpression(obj) => !obj.properties.is_empty(),
// ToNumber throws an error when the argument is Symbol / BigInt / an object that
// returns Symbol or BigInt from ToPrimitive
_ => true,
@@ -98,6 +104,12 @@ pub trait MayHaveSideEffects {
!(matches!(ident.name.as_str(), "Infinity" | "NaN" | "undefined")
&& self.is_global_reference(ident))
}
Expression::ArrayExpression(arr) => {
self.array_expression_may_have_side_effects(arr)
}
// unless `Symbol.toPrimitive`, `valueOf`, `toString` is overridden,
// ToPrimitive for an object returns `"[object Object]"`
Expression::ObjectExpression(obj) => !obj.properties.is_empty(),
// ToNumber throws an error when the argument is Symbol an object that
// returns Symbol from ToPrimitive
_ => true,
@@ -364,9 +364,12 @@ fn test_unary_expressions() {
test_with_global_variables("+Infinity", vec!["Infinity".to_string()], false);
test_with_global_variables("+NaN", vec!["NaN".to_string()], false);
test_with_global_variables("+undefined", vec!["undefined".to_string()], false); // NaN
test("+[]", false); // 0
test("+[foo()]", true);
test("+foo()", true);
test("+foo", true); // foo can be Symbol or BigInt
test("+Symbol()", true);
test("+{}", false); // NaN
test("+{ valueOf() { return Symbol() } }", true);
test("-0", false);
@@ -377,9 +380,12 @@ fn test_unary_expressions() {
test_with_global_variables("-Infinity", vec!["Infinity".to_string()], false);
test_with_global_variables("-NaN", vec!["NaN".to_string()], false);
test_with_global_variables("-undefined", vec!["undefined".to_string()], false); // NaN
test("-[]", false); // -0
test("-[foo()]", true);
test("-foo()", true);
test("-foo", true); // foo can be Symbol
test("-Symbol()", true);
test("-{}", false); // NaN
test("-{ valueOf() { return Symbol() } }", true);
test("~0", false);