--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -1877,16 +1877,17 @@ js::array_sort(JSContext* cx, unsigned a
* value undefined and that is always greater than any other property.
* Thus to sort holes and undefs we simply count them, sort the rest
* of elements, append undefs after them and then make holes after
* undefs.
*/
undefs = 0;
bool allStrings = true;
bool allInts = true;
+ bool extraIndexed = ObjectMayHaveExtraIndexedProperties(obj);
RootedValue v(cx);
for (uint32_t i = 0; i < len; i++) {
if (!CheckForInterrupt(cx))
return false;
/* Clear vec[newlen] before including it in the rooted set. */
bool hole;
if (!GetElement(cx, obj, i, &hole, &v))
@@ -1909,17 +1910,20 @@ js::array_sort(JSContext* cx, unsigned a
*/
n = vec.length();
if (n == 0 && undefs == 0) {
args.rval().setObject(*obj);
return true;
}
/* Here len == n + undefs + number_of_holes. */
+ bool defaultOrMatch;
if (fval.isNull()) {
+ defaultOrMatch = true;
+
/*
* Sort using the default comparator converting all elements to
* strings.
*/
if (allStrings) {
JS_ALWAYS_TRUE(vec.resize(n * 2));
if (!MergeSort(vec.begin(), n, vec.begin() + n, SortComparatorStrings(cx)))
return false;
@@ -1933,16 +1937,17 @@ js::array_sort(JSContext* cx, unsigned a
if (!SortLexicographically(cx, &vec, n))
return false;
}
} else {
ComparatorMatchResult comp = MatchNumericComparator(cx, fval);
if (comp == Match_Failure)
return false;
+ defaultOrMatch = comp != Match_None;
if (comp != Match_None) {
if (allInts) {
JS_ALWAYS_TRUE(vec.resize(n * 2));
if (!MergeSort(vec.begin(), n, vec.begin() + n, SortComparatorInt32s[comp]))
return false;
} else {
if (!SortNumerically(cx, &vec, n, comp))
return false;
@@ -1953,17 +1958,20 @@ js::array_sort(JSContext* cx, unsigned a
if (!MergeSort(vec.begin(), n, vec.begin() + n,
SortComparatorFunction(cx, fval, fig)))
{
return false;
}
}
}
- if (!InitArrayElements(cx, obj, 0, uint32_t(n), vec.begin(), ShouldUpdateTypes::DontUpdate))
+ ShouldUpdateTypes updateTypes = !extraIndexed && (allStrings || allInts) && defaultOrMatch
+ ? ShouldUpdateTypes::DontUpdate
+ : ShouldUpdateTypes::Update;
+ if (!InitArrayElements(cx, obj, 0, uint32_t(n), vec.begin(), updateTypes))
return false;
}
/* Set undefs that sorted after the rest of elements. */
while (undefs != 0) {
--undefs;
if (!CheckForInterrupt(cx) || !SetArrayElement(cx, obj, n++, UndefinedHandleValue))
return false;