| // Copyright 2017 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. |
| |
| assertThrows(() => { |
| Array.prototype.lastIndexOf.call(null, 42); |
| }, TypeError); |
| assertThrows(() => { |
| Array.prototype.lastIndexOf.call(undefined, 42); |
| }, TypeError); |
| |
| /* Tests inspired by test262's |
| lastIndexOf/calls-only-has-on-prototype-after-length-zeroed.js */ |
| // Stateful fromIndex that tries to empty the array |
| (function testFromIndex() { |
| var array = [5, undefined, 7]; |
| var fromIndex = { |
| valueOf: function() { |
| array.length = 1; |
| return 2; |
| } |
| }; |
| assertEquals(-1, array.lastIndexOf(undefined, fromIndex)); |
| |
| array = [5, undefined, 7]; |
| assertEquals(0, array.lastIndexOf(5, fromIndex)); |
| })(); |
| |
| // Stateful fromIndex and proxy as Prototype |
| // Must test for [[HasProperty]] before [[Get]] |
| var testHasProperty = function(value) { |
| var array = [5, undefined, 7]; |
| var fromIndex = { |
| valueOf: function() { |
| array.length = 0; |
| return 2; |
| } |
| }; |
| |
| // Install a prototype that only has [[HasProperty]], and throws on [[Get]] |
| Object.setPrototypeOf(array, |
| new Proxy(Array.prototype, { |
| has: function(t, pk) { return pk in t; }, |
| get: function () { throw new Error('[[Get]] trap called') }, |
| })); |
| |
| assertEquals(-1, Array.prototype.lastIndexOf.call(array, value, fromIndex)); |
| } |
| |
| testHasProperty(5); |
| testHasProperty(undefined); |
| |
| // Test call order: [[HasProperty]] before [[Get]] |
| var testHasPropertyThenGet = function(value) { |
| var array = [5, , 7]; |
| var log = []; |
| |
| // Install a prototype with only [[HasProperty]] and [[Get]] |
| Object.setPrototypeOf(array, |
| new Proxy(Array.prototype, { |
| has: function() { log.push("HasProperty"); return true; }, |
| get: function() { log.push("Get"); }, |
| })); |
| // The 2nd element (index 1) will trigger the calls to the prototype |
| Array.prototype.lastIndexOf.call(array, value); |
| assertEquals(["HasProperty", "Get"], log); |
| } |
| |
| testHasPropertyThenGet(5); |
| testHasPropertyThenGet(undefined); |
| |
| // Test for sparse Arrays |
| /* This will not enter the fast path for sparse arrays, due to UseSparseVariant |
| excluding array elements with accessors */ |
| (function() { |
| var array = new Array(10000); |
| array[0] = 5; array[9999] = 7; |
| |
| var count = 0; |
| Object.defineProperty(array.__proto__, 9998, { get: () => ++count }); |
| Array.prototype.lastIndexOf.call(array, 0); |
| assertEquals(1,count); |
| })(); |