Commit b57428e9 authored by dehrenberg's avatar dehrenberg Committed by Commit bot

Implement %TypedArray%.{fill,find,findIndex}

This patch adds three methods to TypedArrays which are already
implemented for arrays. The implementations are made by calling
out to the underlying code used by Arrays.

R=adamk@chromium.org
BUG=v8:3578
LOG=Y

Review URL: https://codereview.chromium.org/1136663005

Cr-Commit-Position: refs/heads/master@{#28382}
parent a863c4d3
...@@ -3,6 +3,9 @@ ...@@ -3,6 +3,9 @@
// found in the LICENSE file. // found in the LICENSE file.
var $innerArrayCopyWithin; var $innerArrayCopyWithin;
var $innerArrayFill;
var $innerArrayFind;
var $innerArrayFindIndex;
(function(global, exports) { (function(global, exports) {
...@@ -73,22 +76,11 @@ function ArrayCopyWithin(target, start, end) { ...@@ -73,22 +76,11 @@ function ArrayCopyWithin(target, start, end) {
return InnerArrayCopyWithin(target, start, end, array, length); return InnerArrayCopyWithin(target, start, end, array, length);
} }
// ES6 draft 07-15-13, section 15.4.3.23 function InnerArrayFind(predicate, thisArg, array, length) {
function ArrayFind(predicate /* thisArg */) { // length == 1
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.find");
var array = $toObject(this);
var length = $toInteger(array.length);
if (!IS_SPEC_FUNCTION(predicate)) { if (!IS_SPEC_FUNCTION(predicate)) {
throw MakeTypeError(kCalledNonCallable, predicate); throw MakeTypeError(kCalledNonCallable, predicate);
} }
var thisArg;
if (%_ArgumentsLength() > 1) {
thisArg = %_Arguments(1);
}
var needs_wrapper = false; var needs_wrapper = false;
if (IS_NULL(thisArg)) { if (IS_NULL(thisArg)) {
if (%IsSloppyModeFunction(predicate)) thisArg = UNDEFINED; if (%IsSloppyModeFunction(predicate)) thisArg = UNDEFINED;
...@@ -108,24 +100,23 @@ function ArrayFind(predicate /* thisArg */) { // length == 1 ...@@ -108,24 +100,23 @@ function ArrayFind(predicate /* thisArg */) { // length == 1
return; return;
} }
$innerArrayFind = InnerArrayFind;
// ES6 draft 07-15-13, section 15.4.3.23
// ES6 draft 07-15-13, section 15.4.3.24 function ArrayFind(predicate, thisArg) {
function ArrayFindIndex(predicate /* thisArg */) { // length == 1 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.find");
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.findIndex");
var array = $toObject(this); var array = $toObject(this);
var length = $toInteger(array.length); var length = $toInteger(array.length);
return InnerArrayFind(predicate, thisArg, array, length);
}
function InnerArrayFindIndex(predicate, thisArg, array, length) {
if (!IS_SPEC_FUNCTION(predicate)) { if (!IS_SPEC_FUNCTION(predicate)) {
throw MakeTypeError(kCalledNonCallable, predicate); throw MakeTypeError(kCalledNonCallable, predicate);
} }
var thisArg;
if (%_ArgumentsLength() > 1) {
thisArg = %_Arguments(1);
}
var needs_wrapper = false; var needs_wrapper = false;
if (IS_NULL(thisArg)) { if (IS_NULL(thisArg)) {
if (%IsSloppyModeFunction(predicate)) thisArg = UNDEFINED; if (%IsSloppyModeFunction(predicate)) thisArg = UNDEFINED;
...@@ -145,26 +136,22 @@ function ArrayFindIndex(predicate /* thisArg */) { // length == 1 ...@@ -145,26 +136,22 @@ function ArrayFindIndex(predicate /* thisArg */) { // length == 1
return -1; return -1;
} }
$innerArrayFindIndex = InnerArrayFindIndex;
// ES6 draft 07-15-13, section 15.4.3.24
// ES6, draft 04-05-14, section 22.1.3.6 function ArrayFindIndex(predicate, thisArg) {
function ArrayFill(value /* [, start [, end ] ] */) { // length == 1 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.findIndex");
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.fill");
var array = $toObject(this); var array = $toObject(this);
var length = TO_UINT32(array.length); var length = $toInteger(array.length);
var i = 0; return InnerArrayFindIndex(predicate, thisArg, array, length);
var end = length; }
if (%_ArgumentsLength() > 1) { // ES6, draft 04-05-14, section 22.1.3.6
i = %_Arguments(1); function InnerArrayFill(value, start, end, array, length) {
i = IS_UNDEFINED(i) ? 0 : TO_INTEGER(i); var i = IS_UNDEFINED(start) ? 0 : TO_INTEGER(start);
if (%_ArgumentsLength() > 2) { var end = IS_UNDEFINED(end) ? length : TO_INTEGER(end);
end = %_Arguments(2);
end = IS_UNDEFINED(end) ? length : TO_INTEGER(end);
}
}
if (i < 0) { if (i < 0) {
i += length; i += length;
...@@ -188,6 +175,17 @@ function ArrayFill(value /* [, start [, end ] ] */) { // length == 1 ...@@ -188,6 +175,17 @@ function ArrayFill(value /* [, start [, end ] ] */) { // length == 1
array[i] = value; array[i] = value;
return array; return array;
} }
$innerArrayFill = InnerArrayFill;
// ES6, draft 04-05-14, section 22.1.3.6
function ArrayFill(value, start, end) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.fill");
var array = $toObject(this);
var length = TO_UINT32(array.length);
return InnerArrayFill(value, start, end, array, length);
}
// ES6, draft 10-14-14, section 22.1.2.1 // ES6, draft 10-14-14, section 22.1.2.1
function ArrayFrom(arrayLike, mapfn, receiver) { function ArrayFrom(arrayLike, mapfn, receiver) {
...@@ -279,6 +277,9 @@ $installConstants(GlobalSymbol, [ ...@@ -279,6 +277,9 @@ $installConstants(GlobalSymbol, [
%FunctionSetLength(ArrayCopyWithin, 2); %FunctionSetLength(ArrayCopyWithin, 2);
%FunctionSetLength(ArrayFrom, 1); %FunctionSetLength(ArrayFrom, 1);
%FunctionSetLength(ArrayFill, 1);
%FunctionSetLength(ArrayFind, 1);
%FunctionSetLength(ArrayFindIndex, 1);
// Set up non-enumerable functions on the Array object. // Set up non-enumerable functions on the Array object.
$installFunctions(GlobalArray, DONT_ENUM, [ $installFunctions(GlobalArray, DONT_ENUM, [
......
...@@ -59,6 +59,37 @@ function TypedArrayForEach(f, receiver) { ...@@ -59,6 +59,37 @@ function TypedArrayForEach(f, receiver) {
} }
%FunctionSetLength(TypedArrayForEach, 1); %FunctionSetLength(TypedArrayForEach, 1);
// ES6 draft 04-05-14 section 22.2.3.8
function TypedArrayFill(value, start , end) {
if (!%IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
var length = %_TypedArrayGetLength(this);
return $innerArrayFill(value, start, end, this, length);
}
%FunctionSetLength(TypedArrayFill, 1);
// ES6 draft 07-15-13, section 22.2.3.10
function TypedArrayFind(predicate, thisArg) {
if (!%IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
var length = %_TypedArrayGetLength(this);
return $innerArrayFind(predicate, thisArg, this, length);
}
%FunctionSetLength(TypedArrayFind, 1);
// ES6 draft 07-15-13, section 22.2.3.11
function TypedArrayFindIndex(predicate, thisArg) {
if (!%IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
var length = %_TypedArrayGetLength(this);
return $innerArrayFindIndex(predicate, thisArg, this, length);
}
%FunctionSetLength(TypedArrayFindIndex, 1);
// ES6 draft 08-24-14, section 22.2.2.2 // ES6 draft 08-24-14, section 22.2.2.2
function TypedArrayOf() { function TypedArrayOf() {
var length = %_ArgumentsLength(); var length = %_ArgumentsLength();
...@@ -79,7 +110,10 @@ macro EXTEND_TYPED_ARRAY(NAME) ...@@ -79,7 +110,10 @@ macro EXTEND_TYPED_ARRAY(NAME)
$installFunctions(GlobalNAME.prototype, DONT_ENUM, [ $installFunctions(GlobalNAME.prototype, DONT_ENUM, [
"copyWithin", TypedArrayCopyWithin, "copyWithin", TypedArrayCopyWithin,
"every", TypedArrayEvery, "every", TypedArrayEvery,
"forEach", TypedArrayForEach "forEach", TypedArrayForEach,
"find", TypedArrayFind,
"findIndex", TypedArrayFindIndex,
"fill", TypedArrayFill
]); ]);
endmacro endmacro
......
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-arrays
var typedArrayConstructors = [
Uint8Array,
Int8Array,
Uint16Array,
Int16Array,
Uint32Array,
Int32Array,
Uint8ClampedArray,
Float32Array,
Float64Array];
for (var constructor of typedArrayConstructors) {
assertEquals(1, constructor.prototype.fill.length);
assertArrayEquals(new constructor([]).fill(8), []);
assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8), [8, 8, 8, 8, 8]);
assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8, 1), [0, 8, 8, 8, 8]);
assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8, 10), [0, 0, 0, 0, 0]);
assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8, -5), [8, 8, 8, 8, 8]);
assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8, 1, 4), [0, 8, 8, 8, 0]);
assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8, 1, -1), [0, 8, 8, 8, 0]);
assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8, 1, 42), [0, 8, 8, 8, 8]);
assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8, -3, 42), [0, 0, 8, 8, 8]);
assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8, -3, 4), [0, 0, 8, 8, 0]);
assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8, -2, -1), [0, 0, 0, 8, 0]);
assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8, -1, -3), [0, 0, 0, 0, 0]);
assertArrayEquals(new constructor([0, 0, 0, 0, 0]).fill(8, 0, 4), [8, 8, 8, 8, 0]);
// Test exceptions
assertThrows('constructor.prototype.fill.call(null)', TypeError);
assertThrows('constructor.prototype.fill.call(undefined)', TypeError);
assertThrows('constructor.prototype.fill.call([])', TypeError);
}
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-arrays
var typedArrayConstructors = [
Uint8Array,
Int8Array,
Uint16Array,
Int16Array,
Uint32Array,
Int32Array,
Uint8ClampedArray,
Float32Array,
Float64Array];
for (var constructor of typedArrayConstructors) {
assertEquals(1, constructor.prototype.find.length);
var a = new constructor([21, 22, 23, 24]);
assertEquals(undefined, a.find(function() { return false; }));
assertEquals(21, a.find(function() { return true; }));
assertEquals(undefined, a.find(function(val) { return 121 === val; }));
assertEquals(24, a.find(function(val) { return 24 === val; }));
assertEquals(23, a.find(function(val) { return 23 === val; }), null);
assertEquals(22, a.find(function(val) { return 22 === val; }), undefined);
//
// Test predicate is not called when array is empty
//
(function() {
var a = new constructor([]);
var l = -1;
var o = -1;
var v = -1;
var k = -1;
a.find(function(val, key, obj) {
o = obj;
l = obj.length;
v = val;
k = key;
return false;
});
assertEquals(-1, l);
assertEquals(-1, o);
assertEquals(-1, v);
assertEquals(-1, k);
})();
//
// Test predicate is called with correct arguments
//
(function() {
var a = new constructor([5]);
var l = -1;
var o = -1;
var v = -1;
var k = -1;
var found = a.find(function(val, key, obj) {
o = obj;
l = obj.length;
v = val;
k = key;
return false;
});
assertArrayEquals(a, o);
assertEquals(a.length, l);
assertEquals(5, v);
assertEquals(0, k);
assertEquals(undefined, found);
})();
//
// Test predicate is called array.length times
//
(function() {
var a = new constructor([1, 2, 3, 4, 5]);
var l = 0;
var found = a.find(function() {
l++;
return false;
});
assertEquals(a.length, l);
assertEquals(undefined, found);
})();
//
// Test array modifications
//
(function() {
a = new constructor([1, 2, 3]);
found = a.find(function(val, key) { a[key] = ++val; return false; });
assertArrayEquals([2, 3, 4], a);
assertEquals(3, a.length);
assertEquals(undefined, found);
})();
//
// Test thisArg
//
(function() {
// Test String as a thisArg
var found = new constructor([1, 2, 3]).find(function(val, key) {
return this.charAt(Number(key)) === String(val);
}, "321");
assertEquals(2, found);
// Test object as a thisArg
var thisArg = {
elementAt: function(key) {
return this[key];
}
};
Array.prototype.push.apply(thisArg, [3, 2, 1]);
found = new constructor([1, 2, 3]).find(function(val, key) {
return this.elementAt(key) === val;
}, thisArg);
assertEquals(2, found);
// Create a new object in each function call when receiver is a
// primitive value. See ECMA-262, Annex C.
a = [];
new constructor([1, 2]).find(function() { a.push(this) }, "");
assertTrue(a[0] !== a[1]);
// Do not create a new object otherwise.
a = [];
new constructor([1, 2]).find(function() { a.push(this) }, {});
assertEquals(a[0], a[1]);
// In strict mode primitive values should not be coerced to an object.
a = [];
new constructor([1, 2]).find(function() { 'use strict'; a.push(this); }, "");
assertEquals("", a[0]);
assertEquals(a[0], a[1]);
})();
// Test exceptions
assertThrows('constructor.prototype.find.call(null, function() { })',
TypeError);
assertThrows('constructor.prototype.find.call(undefined, function() { })',
TypeError);
assertThrows('constructor.prototype.find.apply(null, function() { }, [])',
TypeError);
assertThrows('constructor.prototype.find.apply(undefined, function() { }, [])',
TypeError);
assertThrows('constructor.prototype.find.apply([], function() { }, [])',
TypeError);
assertThrows('constructor.prototype.find.apply({}, function() { }, [])',
TypeError);
assertThrows('constructor.prototype.find.apply("", function() { }, [])',
TypeError);
assertThrows('new constructor([]).find(null)', TypeError);
assertThrows('new constructor([]).find(undefined)', TypeError);
assertThrows('new constructor([]).find(0)', TypeError);
assertThrows('new constructor([]).find(true)', TypeError);
assertThrows('new constructor([]).find(false)', TypeError);
assertThrows('new constructor([]).find("")', TypeError);
assertThrows('new constructor([]).find({})', TypeError);
assertThrows('new constructor([]).find([])', TypeError);
assertThrows('new constructor([]).find(/\d+/)', TypeError);
}
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-arrays
var typedArrayConstructors = [
Uint8Array,
Int8Array,
Uint16Array,
Int16Array,
Uint32Array,
Int32Array,
Uint8ClampedArray,
Float32Array,
Float64Array];
for (var constructor of typedArrayConstructors) {
assertEquals(1, constructor.prototype.findIndex.length);
var a = new constructor([21, 22, 23, 24]);
assertEquals(-1, a.findIndex(function() { return false; }));
assertEquals(-1, a.findIndex(function(val) { return 121 === val; }));
assertEquals(0, a.findIndex(function() { return true; }));
assertEquals(1, a.findIndex(function(val) { return 22 === val; }), undefined);
assertEquals(2, a.findIndex(function(val) { return 23 === val; }), null);
assertEquals(3, a.findIndex(function(val) { return 24 === val; }));
//
// Test predicate is not called when array is empty
//
(function() {
var a = new constructor([]);
var l = -1;
var o = -1;
var v = -1;
var k = -1;
a.findIndex(function(val, key, obj) {
o = obj;
l = obj.length;
v = val;
k = key;
return false;
});
assertEquals(-1, l);
assertEquals(-1, o);
assertEquals(-1, v);
assertEquals(-1, k);
})();
//
// Test predicate is called with correct argumetns
//
(function() {
var a = new constructor([5]);
var l = -1;
var o = -1;
var v = -1;
var k = -1;
var index = a.findIndex(function(val, key, obj) {
o = obj;
l = obj.length;
v = val;
k = key;
return false;
});
assertArrayEquals(a, o);
assertEquals(a.length, l);
assertEquals(5, v);
assertEquals(0, k);
assertEquals(-1, index);
})();
//
// Test predicate is called array.length times
//
(function() {
var a = new constructor([1, 2, 3, 4, 5]);
var l = 0;
a.findIndex(function() {
l++;
return false;
});
assertEquals(a.length, l);
})();
//
// Test array modifications
//
(function() {
a = new constructor([1, 2, 3]);
a.findIndex(function(val, key) { a[key] = ++val; return false; });
assertArrayEquals([2, 3, 4], a);
assertEquals(3, a.length);
})();
//
// Test thisArg
//
(function() {
// Test String as a thisArg
var index = new constructor([1, 2, 3]).findIndex(function(val, key) {
return this.charAt(Number(key)) === String(val);
}, "321");
assertEquals(1, index);
// Test object as a thisArg
var thisArg = {
elementAt: function(key) {
return this[key];
}
};
Array.prototype.push.apply(thisArg, [3, 2, 1]);
index = new constructor([1, 2, 3]).findIndex(function(val, key) {
return this.elementAt(key) === val;
}, thisArg);
assertEquals(1, index);
// Create a new object in each function call when receiver is a
// primitive value. See ECMA-262, Annex C.
a = [];
new constructor([1, 2]).findIndex(function() { a.push(this) }, "");
assertTrue(a[0] !== a[1]);
// Do not create a new object otherwise.
a = [];
new constructor([1, 2]).findIndex(function() { a.push(this) }, {});
assertEquals(a[0], a[1]);
// In strict mode primitive values should not be coerced to an object.
a = [];
new constructor([1, 2]).findIndex(function() { 'use strict'; a.push(this); }, "");
assertEquals("", a[0]);
assertEquals(a[0], a[1]);
})();
// Test exceptions
assertThrows('constructor.prototype.findIndex.call(null, function() { })',
TypeError);
assertThrows('constructor.prototype.findIndex.call(undefined, function() { })',
TypeError);
assertThrows('constructor.prototype.findIndex.apply(null, function() { }, [])',
TypeError);
assertThrows('constructor.prototype.findIndex.apply(undefined, function() { }, [])',
TypeError);
assertThrows('constructor.prototype.findIndex.apply([], function() { }, [])',
TypeError);
assertThrows('constructor.prototype.findIndex.apply({}, function() { }, [])',
TypeError);
assertThrows('constructor.prototype.findIndex.apply("", function() { }, [])',
TypeError);
assertThrows('new constructor([]).findIndex(null)', TypeError);
assertThrows('new constructor([]).findIndex(undefined)', TypeError);
assertThrows('new constructor([]).findIndex(0)', TypeError);
assertThrows('new constructor([]).findIndex(true)', TypeError);
assertThrows('new constructor([]).findIndex(false)', TypeError);
assertThrows('new constructor([]).findIndex("")', TypeError);
assertThrows('new constructor([]).findIndex({})', TypeError);
assertThrows('new constructor([]).findIndex([])', TypeError);
assertThrows('new constructor([]).findIndex(/\d+/)', TypeError);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment