Bug 1247701 - Bail from ArrayShiftDenseKernel if the array is used by for-in iteration. r=jandem
authorTooru Fujisawa <arai_a@mac.com>
Wed, 17 Feb 2016 01:40:18 +0900
changeset 331324 c5631db6889e4a4c1afe3004aac3f22e5736b4a7
parent 331323 b7f93e7b0caad9cc07b1c8d3e0bcbad59c0d35f3
child 331325 995ff53a4d50c9986e3475c1b4bc1ea8cc0f7aad
push id10956
push userjolesen@mozilla.com
push dateTue, 16 Feb 2016 19:12:12 +0000
reviewersjandem
bugs1247701
milestone47.0a1
Bug 1247701 - Bail from ArrayShiftDenseKernel if the array is used by for-in iteration. r=jandem
js/src/jsarray.cpp
js/src/tests/ecma_6/Array/shift_for_in.js
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -2133,16 +2133,23 @@ js::ArrayShiftMoveElements(JSObject* obj
 
 template <JSValueType Type>
 DenseElementResult
 ArrayShiftDenseKernel(JSContext* cx, JSObject* obj, Value* rval)
 {
     if (ObjectMayHaveExtraIndexedProperties(obj))
         return DenseElementResult::Incomplete;
 
+    ObjectGroup* group = obj->getGroup(cx);
+    if (MOZ_UNLIKELY(!group))
+        return DenseElementResult::Failure;
+
+    if (MOZ_UNLIKELY(group->hasAllFlags(OBJECT_FLAG_ITERATED)))
+        return DenseElementResult::Incomplete;
+
     size_t initlen = GetBoxedOrUnboxedInitializedLength<Type>(obj);
     if (initlen == 0)
         return DenseElementResult::Incomplete;
 
     *rval = GetBoxedOrUnboxedDenseElement<Type>(obj, 0);
     if (rval->isMagic(JS_ELEMENTS_HOLE))
         rval->setUndefined();
 
@@ -2190,23 +2197,17 @@ js::array_shift(JSContext* cx, unsigned 
 
     /* Fast paths. */
     ArrayShiftDenseKernelFunctor functor(cx, obj, args.rval().address());
     DenseElementResult result = CallBoxedOrUnboxedSpecialization(functor, obj);
     if (result != DenseElementResult::Incomplete) {
         if (result == DenseElementResult::Failure)
             return false;
 
-        if (!SetLengthProperty(cx, obj, newlen))
-            return false;
-
-        RootedId id(cx);
-        if (!IndexToId(cx, newlen, &id))
-            return false;
-        return SuppressDeletedProperty(cx, obj, id);
+        return SetLengthProperty(cx, obj, newlen);
     }
 
     /* Steps 5, 10. */
     bool hole;
     if (!GetElement(cx, obj, uint32_t(0), &hole, args.rval()))
         return false;
 
     /* Steps 6-7. */
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Array/shift_for_in.js
@@ -0,0 +1,13 @@
+var BUGNUMBER = 1247701;
+var summary = 'Array.prototype.shift on a dense array with holes should update for-in enumeration properties.';
+
+print(BUGNUMBER + ": " + summary);
+
+var x = ["a", , "b", , "c", "d" , "e", "f", "g"];
+for (var p in x) {
+  assertEq(p in x, true);
+  x.shift();
+}
+
+if (typeof reportCompare === "function")
+  reportCompare(true, true);