v8/test/mjsunit/array-lastindexof.js
Hai Dang 5138e02ac1 Fix Array lastIndexOf to call [[HasProperty]] before [[Get]]
Also add more test cases of Array lastIndexOf with proxy, inspired by test262.

In the path for sparse arrays, no changes are needed because element accesses
are not observable there (thanks to UseSparseVariant).

Bug: v8:7813
Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng
Change-Id: Ifd47149f654e92f56d0a1ed6b3debc93718702be
Reviewed-on: https://chromium-review.googlesource.com/1160307
Commit-Queue: Hai Dang <dhai@google.com>
Reviewed-by: Sathya Gunasekaran <gsathya@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54887}
2018-08-03 08:45:55 +00:00

84 lines
2.5 KiB
JavaScript

// 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);
})();