commit 6c8aca084c9078fe3f1f260e3d4fdcbaefa1e9a4
parent 5c1c817d7d025ae8796c1ccdc195f0109ae1a6ea
Author: André Bargull <andre.bargull@gmail.com>
Date: Mon, 13 Oct 2025 12:55:23 +0000
Bug 1990248 - Part 1: Add IndexToId with uint64_t argument. r=spidermonkey-reviewers,jandem
Also used in part 2.
Differential Revision: https://phabricator.services.mozilla.com/D265823
Diffstat:
5 files changed, 47 insertions(+), 40 deletions(-)
diff --git a/js/src/builtin/Array.cpp b/js/src/builtin/Array.cpp
@@ -259,27 +259,6 @@ JS_PUBLIC_API bool js::StringIsArrayIndex(const char16_t* str, uint32_t length,
return true;
}
-template <typename T>
-static bool ToId(JSContext* cx, T index, MutableHandleId id);
-
-template <>
-bool ToId(JSContext* cx, uint32_t index, MutableHandleId id) {
- return IndexToId(cx, index, id);
-}
-
-template <>
-bool ToId(JSContext* cx, uint64_t index, MutableHandleId id) {
- MOZ_ASSERT(index < uint64_t(DOUBLE_INTEGRAL_PRECISION_LIMIT));
-
- if (index == uint32_t(index)) {
- return IndexToId(cx, uint32_t(index), id);
- }
-
- Value tmp = DoubleValue(index);
- return PrimitiveValueToId<CanGC>(cx, HandleValue::fromMarkedLocation(&tmp),
- id);
-}
-
/*
* If the property at the given index exists, get its value into |vp| and set
* |*hole| to false. Otherwise set |*hole| to true and |vp| to Undefined.
@@ -306,7 +285,7 @@ static bool HasAndGetElement(JSContext* cx, HandleObject obj,
}
RootedId id(cx);
- if (!ToId(cx, index, &id)) {
+ if (!IndexToId(cx, index, &id)) {
return false;
}
@@ -475,7 +454,7 @@ static inline bool GetArrayElement(JSContext* cx, HandleObject obj,
}
RootedId id(cx);
- if (!ToId(cx, index, &id)) {
+ if (!IndexToId(cx, index, &id)) {
return false;
}
return GetProperty(cx, obj, obj, id, vp);
@@ -484,7 +463,7 @@ static inline bool GetArrayElement(JSContext* cx, HandleObject obj,
static inline bool DefineArrayElement(JSContext* cx, HandleObject obj,
uint64_t index, HandleValue value) {
RootedId id(cx);
- if (!ToId(cx, index, &id)) {
+ if (!IndexToId(cx, index, &id)) {
return false;
}
return DefineDataProperty(cx, obj, id, value);
@@ -494,10 +473,9 @@ static inline bool DefineArrayElement(JSContext* cx, HandleObject obj,
static inline bool SetArrayElement(JSContext* cx, HandleObject obj,
uint64_t index, HandleValue v) {
RootedId id(cx);
- if (!ToId(cx, index, &id)) {
+ if (!IndexToId(cx, index, &id)) {
return false;
}
-
return SetProperty(cx, obj, id, v);
}
@@ -536,7 +514,7 @@ static bool DeleteArrayElement(JSContext* cx, HandleObject obj, uint64_t index,
}
RootedId id(cx);
- if (!ToId(cx, index, &id)) {
+ if (!IndexToId(cx, index, &id)) {
return false;
}
return DeleteProperty(cx, obj, id, result);
@@ -551,7 +529,7 @@ static bool DeletePropertyOrThrow(JSContext* cx, HandleObject obj,
}
if (!success) {
RootedId id(cx);
- if (!ToId(cx, index, &id)) {
+ if (!IndexToId(cx, index, &id)) {
return false;
}
return success.reportError(cx, obj, id);
@@ -1586,7 +1564,7 @@ static bool SetArrayElements(JSContext* cx, HandleObject obj, uint64_t start,
return false;
}
- if (!ToId(cx, start++, &id)) {
+ if (!IndexToId(cx, start++, &id)) {
return false;
}
diff --git a/js/src/vm/JSAtomUtils-inl.h b/js/src/vm/JSAtomUtils-inl.h
@@ -82,6 +82,19 @@ inline bool IndexToId(JSContext* cx, uint32_t index, MutableHandleId idp) {
return IndexToIdSlow(cx, index, idp);
}
+bool IndexToIdSlow(JSContext* cx, uint64_t index, MutableHandleId idp);
+
+inline bool IndexToId(JSContext* cx, uint64_t index, MutableHandleId idp) {
+ MOZ_ASSERT(index < uint64_t(DOUBLE_INTEGRAL_PRECISION_LIMIT));
+
+ if (index <= PropertyKey::IntMax) {
+ idp.set(PropertyKey::Int(index));
+ return true;
+ }
+
+ return IndexToIdSlow(cx, index, idp);
+}
+
static MOZ_ALWAYS_INLINE JSLinearString* IdToString(
JSContext* cx, jsid id, gc::Heap heap = gc::Heap::Default) {
if (id.isString()) {
diff --git a/js/src/vm/JSAtomUtils.cpp b/js/src/vm/JSAtomUtils.cpp
@@ -916,6 +916,28 @@ bool js::IndexToIdSlow(JSContext* cx, uint32_t index, MutableHandleId idp) {
return true;
}
+bool js::IndexToIdSlow(JSContext* cx, uint64_t index, MutableHandleId idp) {
+ MOZ_ASSERT(index > JS::PropertyKey::IntMax);
+
+ // Plus one to include the largest number.
+ constexpr size_t UINT64_CHAR_BUFFER_LENGTH =
+ std::numeric_limits<uint64_t>::digits10 + 1;
+
+ char buf[UINT64_CHAR_BUFFER_LENGTH];
+
+ auto result = std::to_chars(buf, buf + std::size(buf), index, 10);
+ MOZ_ASSERT(result.ec == std::errc());
+
+ size_t length = result.ptr - buf;
+ JSAtom* atom = Atomize(cx, buf, length);
+ if (!atom) {
+ return false;
+ }
+
+ idp.set(JS::PropertyKey::NonIntAtom(atom));
+ return true;
+}
+
template <AllowGC allowGC>
static MOZ_ALWAYS_INLINE JSAtom* PrimitiveToAtom(JSContext* cx,
const Value& v) {
diff --git a/js/src/vm/NativeObject.cpp b/js/src/vm/NativeObject.cpp
@@ -2356,7 +2356,7 @@ bool js::NativeGetElement(JSContext* cx, Handle<NativeObject*> obj,
RootedId id(cx);
if (MOZ_LIKELY(index >= 0)) {
- if (!IndexToId(cx, index, &id)) {
+ if (!IndexToId(cx, uint32_t(index), &id)) {
return false;
}
} else {
diff --git a/js/src/vm/ObjectOperations-inl.h b/js/src/vm/ObjectOperations-inl.h
@@ -155,19 +155,13 @@ inline bool GetElement(JSContext* cx, JS::Handle<JSObject*> obj,
inline bool GetElementLargeIndex(JSContext* cx, JS::Handle<JSObject*> obj,
JS::Handle<JSObject*> receiver, uint64_t index,
JS::MutableHandle<JS::Value> vp) {
- MOZ_ASSERT(index < uint64_t(DOUBLE_INTEGRAL_PRECISION_LIMIT));
-
- if (MOZ_LIKELY(index <= UINT32_MAX)) {
- return GetElement(cx, obj, receiver, uint32_t(index), vp);
- }
-
- RootedValue tmp(cx, DoubleValue(index));
- RootedId id(cx);
- if (!PrimitiveValueToId<CanGC>(cx, tmp, &id)) {
+ JS::Rooted<jsid> id(cx);
+ if (!IndexToId(cx, index, &id)) {
return false;
}
- return GetProperty(cx, obj, obj, id, vp);
+ JS::Rooted<JS::Value> receiverValue(cx, JS::ObjectValue(*receiver));
+ return GetProperty(cx, obj, receiverValue, id, vp);
}
inline bool GetPropertyNoGC(JSContext* cx, JSObject* obj,