1 // Copyright 2014 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Flags: --allow-natives-syntax 6 7 var typedArrayConstructors = [ 8 Uint8Array, 9 Int8Array, 10 Uint16Array, 11 Int16Array, 12 Uint32Array, 13 Int32Array, 14 Uint8ClampedArray, 15 Float32Array, 16 Float64Array]; 17 18 function CheckTypedArrayIsNeutered(array) { 19 assertEquals(0, array.byteLength); 20 assertEquals(0, array.byteOffset); 21 assertEquals(0, array.length); 22 } 23 24 function TestTypedArrayForEach(constructor) { 25 assertEquals(1, constructor.prototype.forEach.length); 26 27 var a = new constructor(2); 28 a[0] = 0; 29 a[1] = 1; 30 31 var count = 0; 32 a.forEach(function (n) { count++; }); 33 assertEquals(2, count); 34 35 // Use specified object as this object when calling the function. 36 var o = { value: 42 }; 37 var result = []; 38 a.forEach(function (n, index, array) { result.push(this.value); }, o); 39 assertArrayEquals([42, 42], result); 40 41 // Modify the original array. 42 count = 0; 43 a.forEach(function (n, index, array) { array[index] = n + 1; count++ }); 44 assertEquals(2, count); 45 assertArrayEquals([1, 2], a); 46 47 // Check that values passed as second argument are wrapped into 48 // objects when calling into sloppy mode functions. 49 function CheckWrapping(value, wrapper) { 50 var wrappedValue = new wrapper(value); 51 52 a.forEach(function () { 53 assertEquals("object", typeof this); 54 assertEquals(wrappedValue, this); 55 }, value); 56 57 a.forEach(function () { 58 "use strict"; 59 assertEquals(typeof value, typeof this); 60 assertEquals(value, this); 61 }, value); 62 } 63 CheckWrapping(true, Boolean); 64 CheckWrapping(false, Boolean); 65 CheckWrapping("xxx", String); 66 CheckWrapping(42, Number); 67 CheckWrapping(3.14, Number); 68 CheckWrapping({}, Object); 69 70 // Throw before completing iteration, only the first element 71 // should be modified when thorwing mid-way. 72 count = 0; 73 a[0] = 42; 74 a[1] = 42; 75 try { 76 a.forEach(function (n, index, array) { 77 if (count > 0) throw "meh"; 78 array[index] = n + 1; 79 count++; 80 }); 81 } catch (e) { 82 } 83 assertEquals(1, count); 84 assertEquals(43, a[0]); 85 assertEquals(42, a[1]); 86 87 // Neutering the buffer backing the typed array mid-way should 88 // still make .forEach() finish, but exiting early due to the missing 89 // elements, and the array should keep being empty after detaching it. 90 // TODO(dehrenberg): According to the ES6 spec, accessing or testing 91 // for members on a detached TypedArray should throw, so really this 92 // should throw in the third iteration. However, this behavior matches 93 // the Khronos spec. 94 a = new constructor(3); 95 count = 0; 96 a.forEach(function (n, index, array) { 97 if (count > 0) %ArrayBufferNeuter(array.buffer); 98 array[index] = n + 1; 99 count++; 100 }); 101 assertEquals(2, count); 102 CheckTypedArrayIsNeutered(a); 103 assertEquals(undefined, a[0]); 104 105 // The method must work for typed arrays created from ArrayBuffer. 106 // The length of the ArrayBuffer is chosen so it is a multiple of 107 // all lengths of the typed array items. 108 a = new constructor(new ArrayBuffer(64)); 109 count = 0; 110 a.forEach(function (n) { count++ }); 111 assertEquals(a.length, count); 112 113 // Externalizing the array mid-way accessing the .buffer property 114 // should work. 115 a = new constructor(2); 116 count = 0; 117 var buffer = undefined; 118 a.forEach(function (n, index, array) { 119 if (count++ > 0) 120 buffer = array.buffer; 121 }); 122 assertEquals(2, count); 123 assertTrue(!!buffer); 124 assertEquals("ArrayBuffer", %_ClassOf(buffer)); 125 assertSame(buffer, a.buffer); 126 127 // The %TypedArray%.forEach() method should not work when 128 // transplanted to objects that are not typed arrays. 129 assertThrows(function () { constructor.prototype.forEach.call([1, 2, 3], function (x) {}) }, TypeError); 130 assertThrows(function () { constructor.prototype.forEach.call("abc", function (x) {}) }, TypeError); 131 assertThrows(function () { constructor.prototype.forEach.call({}, function (x) {}) }, TypeError); 132 assertThrows(function () { constructor.prototype.forEach.call(0, function (x) {}) }, TypeError); 133 134 // Method must be useable on instances of other typed arrays. 135 for (var i = 0; i < typedArrayConstructors.length; i++) { 136 count = 0; 137 a = new typedArrayConstructors[i](4); 138 constructor.prototype.forEach.call(a, function (x) { count++ }); 139 assertEquals(a.length, count); 140 } 141 142 // Shadowing length doesn't affect forEach, unlike Array.prototype.forEach 143 a = new constructor([1, 2]); 144 Object.defineProperty(a, 'length', {value: 1}); 145 var x = 0; 146 assertEquals(a.forEach(function(elt) { x += elt; }), undefined); 147 assertEquals(x, 3); 148 assertEquals(Array.prototype.forEach.call(a, 149 function(elt) { x += elt; }), undefined); 150 assertEquals(x, 4); 151 } 152 153 for (i = 0; i < typedArrayConstructors.length; i++) { 154 TestTypedArrayForEach(typedArrayConstructors[i]); 155 } 156