Browse Source

Fix for ArrayIterator object.

typedarray.keys/values/entries should iterate over its internal length slot, instead of doing get('length'). Fixed that.
Also we should not be calling GetOwnItem (as per the spec). Fixed that.
Akrosh Gandhi 9 years ago
parent
commit
55ed2e4e11

+ 3 - 0
lib/Runtime/Library/JavascriptArray.cpp

@@ -8118,6 +8118,9 @@ Case0:
             JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NullOrUndefined, _u("Array.prototype.values"));
         }
 
+#if ENABLE_COPYONACCESS_ARRAY
+        JavascriptLibrary::CheckAndConvertCopyOnAccessNativeIntArray<Var>(thisObj);
+#endif
         return scriptContext->GetLibrary()->CreateArrayIterator(thisObj, JavascriptArrayIteratorKind::Value);
     }
 

+ 21 - 24
lib/Runtime/Library/JavascriptArrayIterator.cpp

@@ -58,17 +58,25 @@ namespace Js
         }
 
         int64 length;
-        bool bArray = false;
         JavascriptArray* pArr = nullptr;
-
-        if (DynamicObject::IsAnyArray(iterable) && !JavascriptArray::FromAnyArray(iterable)->IsCrossSiteObject())
+        TypedArrayBase *typedArrayBase = nullptr;
+        if (JavascriptArray::Is(iterable) && !JavascriptArray::FromVar(iterable)->IsCrossSiteObject())
         {
 #if ENABLE_COPYONACCESS_ARRAY
-            JavascriptLibrary::CheckAndConvertCopyOnAccessNativeIntArray<Var>(iterable);
+            Assert(!JavascriptCopyOnAccessNativeIntArray::Is(iterable));
 #endif
             pArr = JavascriptArray::FromAnyArray(iterable);
             length = pArr->GetLength();
-            bArray = true;
+        }
+        else if (TypedArrayBase::Is(iterable))
+        {
+            typedArrayBase = TypedArrayBase::FromVar(iterable);
+            if (typedArrayBase->IsDetachedBuffer())
+            {
+                JavascriptError::ThrowTypeError(scriptContext, JSERR_DetachedTypedArray);
+            }
+
+            length = typedArrayBase->GetLength();
         }
         else
         {
@@ -93,26 +101,15 @@ namespace Js
         }
 
         Var value;
-        if (index <= UINT_MAX)
+        if (pArr != nullptr)
         {
-            if (bArray)
-            {
-                if (JavascriptArray::Is(pArr))
-                {
-                    value = pArr->DirectGetItem((uint32)index);
-                }
-                else
-                {
-                    if (!JavascriptOperators::GetOwnItem(pArr, (uint32) index, &value, scriptContext))
-                    {
-                        value = library->GetUndefined();
-                    }
-                }
-            }
-            else
-            {
-                value = JavascriptOperators::OP_GetElementI_UInt32(iterable, (uint32)index, scriptContext);
-            }
+            Assert(index <= UINT_MAX);
+            value = pArr->DirectGetItem((uint32)index);
+        }
+        else if (typedArrayBase != nullptr)
+        {
+            Assert(index <= UINT_MAX);
+            value = typedArrayBase->DirectGetItem((uint32)index);
         }
         else
         {

+ 13 - 0
test/es6/typedarray_bugs.js

@@ -91,6 +91,19 @@ var tests = [
         });
     }
   },
+  {
+    name: "typedarray.prototype.keys should take length from internal slot",
+    body: function () {
+        var a = new Int8Array(4);
+        Object.defineProperty(a, 'length', {value : 10});
+        var b = a.keys();
+        var counter = 0;
+        for (var i of b) {
+            counter++;
+        }
+        assert.areEqual(counter, 4, "The iterable object should iterate only 4 times, not 10 times");
+    }
+  },
   
 ];