blob: b9789805f69b466bdccafdeb457fbca8b192ad8d [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
7var typedArrayConstructors = [
8 Uint8Array,
9 Int8Array,
10 Uint16Array,
11 Int16Array,
12 Uint32Array,
13 Int32Array,
14 Uint8ClampedArray,
15 Float32Array,
16 Float64Array];
17
18function CheckTypedArrayIsNeutered(array) {
19 assertEquals(0, array.byteLength);
20 assertEquals(0, array.byteOffset);
21 assertEquals(0, array.length);
22}
23
24function 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
153for (i = 0; i < typedArrayConstructors.length; i++) {
154 TestTypedArrayForEach(typedArrayConstructors[i]);
155}