1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
// 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);
})();
|