Bug 1325052. r=Waldo, a=gchang
authorAndré Bargull <andre.bargull@gmail.com>
Thu, 19 Jan 2017 06:52:01 -0800
changeset 487463 886650fac5312a1d562d5360fd52c119ac37e214
parent 487462 f17cfdd983070a369c27abb86a9a134a974a21ca
child 487464 2d23434260fcf8db23f4d35718b0c8a11194fd59
push id46228
push userpaul@paul.cx
push dateTue, 21 Feb 2017 16:19:44 +0000
reviewersWaldo, gchang
bugs1325052
milestone45.7.1
Bug 1325052. r=Waldo, a=gchang
js/src/jsarray.cpp
--- 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;