summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorLinus Groh <mail@linusgroh.de>2021-07-06 16:45:54 +0100
committerLinus Groh <mail@linusgroh.de>2021-07-06 17:29:12 +0100
commit83f61748a528d6d60c216d358c65c9cd6cec0dbc (patch)
treeb38eafba5a205f9ed0246694b3cdcfa97d874029 /Userland
parent47bd25a2f15b2f4c9b27a149f4452f21330cdbbe (diff)
downloadserenity-83f61748a528d6d60c216d358c65c9cd6cec0dbc.zip
LibJS: Don't treat 2^32 - 1 as numeric PropertyName
10.4.2 Array Exotic Objects https://tc39.es/ecma262/#sec-array-exotic-objects A String property name P is an array index if and only if ToString(ToUint32(P)) equals P and ToUint32(P) is not the same value as 𝔽(2^32 - 1).
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Libraries/LibJS/Runtime/PropertyName.h8
-rw-r--r--Userland/Libraries/LibJS/Tests/object-expression-numeric-property.js30
2 files changed, 34 insertions, 4 deletions
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<u32>::max())
+ if (value.is_integral_number() && value.as_double() >= 0 && value.as_double() < NumericLimits<u32>::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<T>)?
// Needs changes in various places using `int` (but not actually being in the negative range)
VERIFY(index >= 0);
- if constexpr (NumericLimits<T>::max() > NumericLimits<u32>::max())
- VERIFY(index <= NumericLimits<u32>::max());
+ if constexpr (NumericLimits<T>::max() >= NumericLimits<u32>::max())
+ VERIFY(index < NumericLimits<u32>::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<u32>::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
+ ]);
+});