fix(ecmascript): treat shadowed global calls correctly (#13292)

`var Object; Object.create()` was treated as side effect free, but this should be treated as side effectful.
This commit is contained in:
sapphi-red committed 2025-08-25 14:52:51 +00:00
1 parent 593f54ccb6
commit 5d898e803b
2 files changed
+11 -6

No files matched your search

@@ -577,7 +577,7 @@ impl<'a> MayHaveSideEffects<'a> for CallExpression<'a> {
return self.arguments.iter().any(|e| e.may_have_side_effects(ctx));
}
let (ident, name) = match &self.callee {
let (object, name) = match &self.callee {
Expression::StaticMemberExpression(member) if !member.optional => {
(member.object.get_identifier_reference(), member.property.name.as_str())
}
@@ -592,10 +592,13 @@ impl<'a> MayHaveSideEffects<'a> for CallExpression<'a> {
_ => return true,
};
let Some(object) = ident.map(|ident| ident.name.as_str()) else { return true };
let Some(object) = object else { return true };
if !ctx.is_global_reference(object) {
return true;
}
#[rustfmt::skip]
let is_global = match object {
let is_global = match object.name.as_str() {
"Array" => matches!(name, "isArray" | "of"),
"ArrayBuffer" => name == "isView",
"Date" => matches!(name, "now" | "parse" | "UTC"),
@@ -1,5 +1,3 @@
use std::iter;
use javascript_globals::GLOBALS;
use rustc_hash::FxHashSet;
@@ -27,7 +25,7 @@ impl Default for Ctx {
global_variable_names: GLOBALS["builtin"]
.keys()
.copied()
.chain(iter::once("arguments"))
.chain(["arguments", "URL"])
.collect::<FxHashSet<_>>(),
annotation: true,
pure_function_names: vec![],
@@ -927,6 +925,10 @@ fn test_call_expressions() {
test("Uint32Array.of()", false);
test("Uint8Array.of()", false);
test("Uint8ClampedArray.of()", false);
// may have side effects if shadowed
test_with_global_variables("Date()", &[], true);
test_with_global_variables("Object.create()", &[], true);
}
#[test]