fix(minifier): fold typeof comparisons with known object strings (#25017)

Calling `right.to_js_string(ctx)` to get the string of the expression and check whether its string belongs to any `typeof` value to keep compressing `typeof v == [1]` to `!1`.

I may be overthinking this case since this kind of use is quite rare in real-world scenarios. However, I didn't find it hard to implement, so I just got it to work.
This commit is contained in:
Dunqing committed 2026-07-29 02:12:20 +00:00
1 parent cfec06e9cb
commit e6734a5738
2 files changed
+18 -3

No files matched your search

@@ -790,8 +790,12 @@ impl<'a> PeepholeOptimizations {
let ty = right.value_type(ctx);
matches!(ty, ValueType::Undetermined | ValueType::String)
// a loose comparison with an object can be `true` via ToPrimitive
// (e.g. `typeof foo == ['object']` is true when `foo` is an object)
|| (ty == ValueType::Object && !is_strict)
// (e.g. `typeof foo == ['object']` is true when `foo` is an object),
// so only fold when the object's string value is statically known
// to not be a typeof result
|| (ty == ValueType::Object
&& !is_strict
&& right.to_js_string(ctx).is_none_or(|s| is_typeof_string(&s)))
}
};
@@ -1368,11 +1368,22 @@ fn test_fold_invalid_typeof_comparison() {
// strict equality with an object is always false
fold("typeof foo === [1]", "!1");
fold("typeof foo !== [1]", "!0");
fold("typeof foo === ['object']", "!1");
// but loose equality with an object can be true via ToPrimitive:
// `typeof foo == ['object']` is true when foo is an object
fold_same("typeof foo == ['object']");
fold_same("typeof foo != ['object']");
fold_same("typeof foo == [1]");
fold_same("typeof foo == ['function']");
fold_same("typeof foo == [['object']]");
fold_same("typeof foo == { toString: () => 'object' }");
fold_same("typeof foo == [x]");
// folds when the object's string value is statically known
// to not be a typeof result
fold("typeof foo == [1]", "!1");
fold("typeof foo == ['x']", "!1");
fold("typeof foo == []", "!1");
fold("typeof foo == [1, 2]", "!1");
fold("typeof foo == {}", "!1");
}
#[test]