// 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: --allow-natives-syntax

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);

// Shadowing length doesn't affect findIndex, unlike Array.prototype.findIndex
a = new constructor([1, 2]);
Object.defineProperty(a, 'length', {value: 1});
var x = 0;
assertEquals(a.findIndex(function(elt) { x += elt; return false; }), -1);
assertEquals(x, 3);
assertEquals(Array.prototype.findIndex.call(a,
    function(elt) { x += elt; return false; }), -1);
assertEquals(x, 4);

// Detached Operation
  var tmp = {
    [Symbol.toPrimitive]() {
      assertUnreachable("Parameter should not be processed when " +
                        "array.[[ViewedArrayBuffer]] is neutered.");
      return 0;
    }
  };
  var array = new constructor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
  %ArrayBufferNeuter(array.buffer);
  assertThrows(() => array.findIndex(tmp), TypeError);
}
