// Proposed for ES7
// https://github.com/tc39/Array.prototype.includes
-// 6e3b78c927aeda20b9d40e81303f9d44596cd904
-function ArrayIncludes(searchElement, fromIndex) {
- var array = TO_OBJECT(this);
- var len = $toLength(array.length);
-
- if (len === 0) {
+// 46c7532ec8499dea3e51aeb940d09e07547ed3f5
+function InnerArrayIncludes(searchElement, fromIndex, array, length) {
+ if (length === 0) {
return false;
}
if (n >= 0) {
k = n;
} else {
- k = len + n;
+ k = length + n;
if (k < 0) {
k = 0;
}
}
- while (k < len) {
+ while (k < length) {
var elementK = array[k];
if ($sameValueZero(searchElement, elementK)) {
return true;
return false;
}
+
+function ArrayIncludes(searchElement, fromIndex) {
+ CHECK_OBJECT_COERCIBLE(this, "Array.prototype.includes");
+
+ var array = TO_OBJECT(this);
+ var length = $toLength(array.length);
+
+ return InnerArrayIncludes(searchElement, fromIndex, array, length);
+}
+
+
+function TypedArrayIncludes(searchElement, fromIndex) {
+ if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
+
+ var length = %_TypedArrayGetLength(this);
+
+ return InnerArrayIncludes(searchElement, fromIndex, this, length);
+}
+
// -------------------------------------------------------------------
%FunctionSetLength(ArrayIncludes, 1);
+%FunctionSetLength(TypedArrayIncludes, 1);
-// Set up the non-enumerable functions on the Array prototype object.
+// Set up the non-enumerable function on the Array prototype object.
utils.InstallFunctions(GlobalArray.prototype, DONT_ENUM, [
"includes", ArrayIncludes
]);
+// Set up the non-enumerable function on the typed array prototypes.
+// This duplicates some of the machinery in harmony-typedarray.js in order to
+// keep includes behind the separate --harmony-array-includes flag.
+// TODO(littledan): Fix the TypedArray proto chain (bug v8:4085).
+
+macro TYPED_ARRAYS(FUNCTION)
+// arrayIds below should be synchronized with Runtime_TypedArrayInitialize.
+FUNCTION(Uint8Array)
+FUNCTION(Int8Array)
+FUNCTION(Uint16Array)
+FUNCTION(Int16Array)
+FUNCTION(Uint32Array)
+FUNCTION(Int32Array)
+FUNCTION(Float32Array)
+FUNCTION(Float64Array)
+FUNCTION(Uint8ClampedArray)
+endmacro
+
+macro DECLARE_GLOBALS(NAME)
+var GlobalNAME = global.NAME;
+endmacro
+
+macro EXTEND_TYPED_ARRAY(NAME)
+// Set up non-enumerable functions on the prototype object.
+utils.InstallFunctions(GlobalNAME.prototype, DONT_ENUM, [
+ "includes", TypedArrayIncludes
+]);
+endmacro
+
+TYPED_ARRAYS(DECLARE_GLOBALS)
+TYPED_ARRAYS(EXTEND_TYPED_ARRAY)
+
})
--- /dev/null
+// 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-array-includes
+
+// Largely ported from
+// https://github.com/tc39/Array.prototype.includes/tree/master/test/built-ins/TypedArray/prototype/includes
+// using https://www.npmjs.org/package/test262-to-mjsunit with further edits
+
+
+function testTypedArrays(callback) {
+ [
+ Uint8Array,
+ Int8Array,
+ Uint16Array,
+ Int16Array,
+ Uint32Array,
+ Int32Array,
+ Uint8ClampedArray,
+ Float32Array,
+ Float64Array
+ ]
+ .forEach(callback);
+}
+
+testTypedArrays.floatOnly = function (callback) {
+ [Float32Array, Float64Array].forEach(callback);
+};
+
+
+// %TypedArray%.prototype.includes throws a TypeError when used on non-typed
+// arrays
+(function() {
+ var taIncludes = Uint8Array.prototype.includes;
+
+ assertThrows(function() {
+ taIncludes.call({
+ length: 2,
+ 0: 1,
+ 1: 2
+ }, 2);
+ }, TypeError);
+
+ assertThrows(function() {
+ taIncludes.call([1, 2, 3], 2);
+ }, TypeError);
+
+ assertThrows(function() {
+ taIncludes.call(null, 2);
+ }, TypeError);
+
+ assertThrows(function() {
+ taIncludes.call(undefined, 2);
+ }, TypeError);
+})();
+
+
+// %TypedArray%.prototype.includes should terminate if ToNumber ends up being
+// called on a symbol fromIndex
+(function() {
+ testTypedArrays(function(TypedArrayConstructor) {
+ var ta = new TypedArrayConstructor([1, 2, 3]);
+
+ assertThrows(function() {
+ ta.includes(2, Symbol());
+ }, TypeError);
+ });
+})();
+
+
+// %TypedArray%.prototype.includes should terminate if an exception occurs
+// converting the fromIndex to a number
+(function() {
+ function Test262Error() {}
+
+ var fromIndex = {
+ valueOf: function() {
+ throw new Test262Error();
+ }
+ };
+
+ testTypedArrays(function(TypedArrayConstructor) {
+ var ta = new TypedArrayConstructor([1, 2, 3]);
+
+ assertThrows(function() {
+ ta.includes(2, fromIndex);
+ }, Test262Error);
+ });
+})();
+
+
+// %TypedArray%.prototype.includes should search the whole array, as the
+// optional second argument fromIndex defaults to 0
+(function() {
+ testTypedArrays(function(TypedArrayConstructor) {
+ var ta = new TypedArrayConstructor([1, 2, 3]);
+ assertTrue(ta.includes(1));
+ assertTrue(ta.includes(2));
+ assertTrue(ta.includes(3));
+ });
+})();
+
+
+// %TypedArray%.prototype.includes returns false if fromIndex is greater or
+// equal to the length of the array
+(function() {
+ testTypedArrays(function(TypedArrayConstructor) {
+ var ta = new TypedArrayConstructor([1, 2]);
+ assertFalse(ta.includes(2, 3));
+ assertFalse(ta.includes(2, 2));
+ });
+})();
+
+
+// %TypedArray%.prototype.includes searches the whole array if the computed
+// index from the given negative fromIndex argument is less than 0
+(function() {
+ testTypedArrays(function(TypedArrayConstructor) {
+ var ta = new TypedArrayConstructor([1, 3]);
+ assertTrue(ta.includes(1, -4));
+ assertTrue(ta.includes(1, -4));
+ });
+})();
+
+
+// %TypedArray%.prototype.includes should use a negative value as the offset
+// from the end of the array to compute fromIndex
+(function() {
+ testTypedArrays(function(TypedArrayConstructor) {
+ var ta = new TypedArrayConstructor([12, 13]);
+ assertTrue(ta.includes(13, -1));
+ assertFalse(ta.includes(12, -1));
+ assertTrue(ta.includes(12, -2));
+ });
+})();
+
+
+// %TypedArray%.prototype.includes converts its fromIndex parameter to an
+// integer
+(function() {
+ testTypedArrays(function(TypedArrayConstructor) {
+ var ta = new TypedArrayConstructor([1, 2, 3]);
+ assertFalse(ta.includes(1, 3.3));
+ assertTrue(ta.includes(1, -Infinity));
+ assertTrue(ta.includes(3, 2.9));
+ assertTrue(ta.includes(3, NaN));
+
+ var numberLike = {
+ valueOf: function() {
+ return 2;
+ }
+ };
+
+ assertFalse(ta.includes(1, numberLike));
+ assertFalse(ta.includes(1, "2"));
+ assertTrue(ta.includes(3, numberLike));
+ assertTrue(ta.includes(3, "2"));
+ });
+})();
+
+
+// %TypedArray%.prototype.includes should have length 1
+(function() {
+ assertEquals(1, Uint8Array.prototype.includes.length);
+})();
+
+
+// %TypedArray%.prototype.includes should have name property with value
+// 'includes'
+(function() {
+ assertEquals("includes", Uint8Array.prototype.includes.name);
+})();
+
+
+// %TypedArray%.prototype.includes should always return false on zero-length
+// typed arrays
+(function() {
+ testTypedArrays(function(TypedArrayConstructor) {
+ var ta = new TypedArrayConstructor([]);
+ assertFalse(ta.includes(2));
+ assertFalse(ta.includes());
+ assertFalse(ta.includes(undefined));
+ assertFalse(ta.includes(NaN));
+ });
+})();
+
+
+// %TypedArray%.prototype.includes should use the SameValueZero algorithm to
+// compare
+(function() {
+ testTypedArrays.floatOnly(function(FloatArrayConstructor) {
+ assertTrue(new FloatArrayConstructor([1, 2, NaN]).includes(NaN));
+ assertTrue(new FloatArrayConstructor([1, 2, -0]).includes(+0));
+ assertTrue(new FloatArrayConstructor([1, 2, -0]).includes(-0));
+ assertTrue(new FloatArrayConstructor([1, 2, +0]).includes(-0));
+ assertTrue(new FloatArrayConstructor([1, 2, +0]).includes(+0));
+ assertFalse(new FloatArrayConstructor([1, 2, -Infinity]).includes(+Infinity));
+ assertTrue(new FloatArrayConstructor([1, 2, -Infinity]).includes(-Infinity));
+ assertFalse(new FloatArrayConstructor([1, 2, +Infinity]).includes(-Infinity));
+ assertTrue(new FloatArrayConstructor([1, 2, +Infinity]).includes(+Infinity));
+ });
+})();