diff --git a/Userland/Libraries/LibJS/Runtime/PropertyName.h b/Userland/Libraries/LibJS/Runtime/PropertyName.h index 9242822558..62328dfa76 100644 --- a/Userland/Libraries/LibJS/Runtime/PropertyName.h +++ b/Userland/Libraries/LibJS/Runtime/PropertyName.h @@ -31,7 +31,7 @@ public: return {}; if (value.is_symbol()) return value.as_symbol(); - if (value.is_integral_number() && value.as_double() >= 0 && value.as_double() <= NumericLimits::max()) + if (value.is_integral_number() && value.as_double() >= 0 && value.as_double() < NumericLimits::max()) return value.as_u32(); auto string = value.to_string(global_object); if (string.is_null()) @@ -49,8 +49,8 @@ public: // FIXME: Replace this with requires(IsUnsigned)? // Needs changes in various places using `int` (but not actually being in the negative range) VERIFY(index >= 0); - if constexpr (NumericLimits::max() > NumericLimits::max()) - VERIFY(index <= NumericLimits::max()); + if constexpr (NumericLimits::max() >= NumericLimits::max()) + VERIFY(index < NumericLimits::max()); } PropertyName(char const* chars) @@ -131,7 +131,7 @@ public: } auto property_index = m_string.to_uint(TrimWhitespace::No); - if (!property_index.has_value()) { + if (!property_index.has_value() || property_index.value() == NumericLimits::max()) { m_string_may_be_number = false; return false; } diff --git a/Userland/Libraries/LibJS/Tests/object-expression-numeric-property.js b/Userland/Libraries/LibJS/Tests/object-expression-numeric-property.js new file mode 100644 index 0000000000..575e658390 --- /dev/null +++ b/Userland/Libraries/LibJS/Tests/object-expression-numeric-property.js @@ -0,0 +1,30 @@ +test("numeric properties", () => { + const i32Max = 2 ** 31 - 1; + const u32Max = 2 ** 32 - 1; + const o = { + [-1]: "foo", + 0: "foo", + 1: "foo", + [i32Max - 1]: "foo", + [i32Max]: "foo", + [i32Max + 1]: "foo", + [u32Max - 1]: "foo", + [u32Max]: "foo", + [u32Max + 1]: "foo", + }; + // Numeric properties come first in Object.getOwnPropertyNames()'s output, + // which means we can test what each is treated as internally. + expect(Object.getOwnPropertyNames(o)).toEqual([ + // Numeric properties + "0", + "1", + "2147483646", + "2147483647", + "2147483648", + "4294967294", + // Non-numeric properties + "-1", + "4294967295", // >= 2^32 - 1 + "4294967296", // >= 2^32 - 1 + ]); +});