You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

358 lines
6.8 KiB

/*===
basic
number 6
number 9
number 6
number 9
number 0
number 3
number -1
number -1
number 0
number 0
number 0
number 0
number -1
number -1
number -1
number -1
===*/
print('basic');
function basicTest() {
var str = new String('foobarfoobar');
function p(x) {
print(typeof x, x);
}
p(str.lastIndexOf('foo'));
p(str.lastIndexOf('bar'));
p(str.lastIndexOf('foo', 6)); // last foo
p(str.lastIndexOf('bar', 9)); // last bar
p(str.lastIndexOf('foo', 5)); // first foo
p(str.lastIndexOf('bar', 8)); // first bar
p(str.lastIndexOf('bar', 2)); // not found
p(str.lastIndexOf('quux'));
// empty string; empty search matches with any initial position,
// non-empty search never matches
str = new String('');
p(str.indexOf(''));
p(str.indexOf('', -1));
p(str.indexOf('', 0));
p(str.indexOf('', 1));
p(str.indexOf('foo'));
p(str.indexOf('foo', -1));
p(str.indexOf('foo', 0));
p(str.indexOf('foo', 1));
}
try {
basicTest();
} catch (e) {
print(e);
}
/*===
empty
number 6
number 0
number 0
number 0
number 0
number 1
number 2
number 3
number 4
number 5
number 6
number 6
number 6
number 6
number 0
number 6
number 6
===*/
/* An empty search string is always found immediately at the starting
* position. Thus, the return value is the input position, clamped to
* to range [0,len(str)].
*
* There is some variance among implementations. Rhino will always
* return a value in the range [0,6] for the test below, but for
* indexOf() it will return -1 (not found) if initial position is 7
* or above.
*/
print('empty');
function emptyTest() {
var str = new String('foobar');
var i;
function p(x) {
print(typeof x, x);
}
p(str.lastIndexOf(''));
for (i = -3; i < 10; i++) {
p(str.lastIndexOf('', i));
}
p(str.lastIndexOf('', Number.NEGATIVE_INFINITY));
p(str.lastIndexOf('', Number.POSITIVE_INFINITY));
p(str.lastIndexOf('', Number.NaN)); // coerces to 0
}
try {
emptyTest();
} catch (e) {
print(e);
}
/*===
position
number 5
number 0
number 0
number 0
number 0
number 0
number 0
number 0
number 1
number 2
number 3
number 4
number 5
number 5
number 5
number 5
number 5
number 5
number 5
number 3
number 3
number 3
number 3
number 0
number 0
number 0
number 0
number -1
number -1
===*/
/* Position handling. The position is coerced with ToInteger(), then
* clamped to the range [0, len(str)]. ToInteger(NaN) is 0.
*/
print('position');
function positionTest() {
// test string, 'x' always found if index < 6
var str = 'xxxxxx';
function p(x) {
print(typeof x, x);
}
p(str.lastIndexOf('x'));
p(str.lastIndexOf('x', Number.NEGATIVE_INFINITY));
p(str.lastIndexOf('x', -123));
p(str.lastIndexOf('x', -3));
p(str.lastIndexOf('x', -2));
p(str.lastIndexOf('x', -1));
p(str.lastIndexOf('x', -0));
p(str.lastIndexOf('x', 0));
p(str.lastIndexOf('x', 1));
p(str.lastIndexOf('x', 2));
p(str.lastIndexOf('x', 3));
p(str.lastIndexOf('x', 4));
p(str.lastIndexOf('x', 5));
p(str.lastIndexOf('x', 6));
p(str.lastIndexOf('x', 7));
p(str.lastIndexOf('x', 8));
p(str.lastIndexOf('x', 123));
p(str.lastIndexOf('x', Number.POSITIVE_INFINITY));
p(str.lastIndexOf('x', Number.NaN));
// fractions
p(str.lastIndexOf('x', 3.0));
p(str.lastIndexOf('x', 3.1));
p(str.lastIndexOf('x', 3.5));
p(str.lastIndexOf('x', 3.9));
p(str.lastIndexOf('x', -3.0));
p(str.lastIndexOf('x', -3.1));
p(str.lastIndexOf('x', -3.5));
p(str.lastIndexOf('x', -3.9));
// if string is empty, even zero/NaN will yield -1 (not found)
str = new String('');
p(str.lastIndexOf('x', 0));
p(str.lastIndexOf('x', Number.NaN));
}
try {
positionTest();
} catch (e) {
print(e);
}
/*===
argument coercion
number 7
number 7
number 17
number 22
number 27
number 33
number 37
number 41
number 45
toString()
number 37
toString()
valueOf()
number 33
===*/
/* Argument coercion. Argument is coerced with ToString. */
print('argument coercion');
function argumentTest() {
var str = new String('foobar undefined null true false 123 baz 1,2 [object Object]');
function p(x) {
print(typeof x, x);
}
p(str.lastIndexOf()); // argument not given
p(str.lastIndexOf(undefined));
p(str.lastIndexOf(null));
p(str.lastIndexOf(true));
p(str.lastIndexOf(false));
p(str.lastIndexOf(123));
p(str.lastIndexOf('baz'));
p(str.lastIndexOf([1,2]));
p(str.lastIndexOf({ foo: 1, bar: 2 }));
// coercion side effect
p(str.lastIndexOf({
toString: function() { print('toString()'); return 'baz'; },
valueOf: function() { print('valueOf()'); return '123'; }
}));
// ToString() coercion falls back from toString() to valueOf() if toString()
// returns a non-primitive value
p(str.lastIndexOf({
toString: function() { print('toString()'); return []; },
valueOf: function() { print('valueOf()'); return '123'; }
}));
}
try {
argumentTest();
} catch (e) {
print(e);
}
/*===
this coercion
TypeError
TypeError
number 0
number 2
number 1
number 1
number 1
number 8
toString() this
toString() arg
number 5
===*/
/* This coercion, the method is generic. */
print('this coercion');
function thisCoercionTest() {
function test(x,y) {
var t;
try {
t = String.prototype.lastIndexOf.call(x, y);
print(typeof t, t);
} catch (e) {
print(e.name);
}
}
test(undefined, 'undefined'); // TypeError
test(null, 'null'); // TypeError
test(true, 'true');
test(false, 'lse');
test(123, '23');
test('quux', 'uux');
test([1,2], ',2');
test({ foo: 1, bar: 2 }, 'Object');
// coercion order if both this and searchString are coerced
test({
toString: function() { print('toString() this'); return 'test string'; },
valueOf: function() { print('valueOf() this'); return 'another value'; }
}, {
toString: function() { print('toString() arg'); return 'stri'; },
valueOf: function() { print('valueOf() arg'); return 'foo'; }
});
}
try {
thisCoercionTest();
} catch (e) {
print(e);
}
/*===
non-bmp
number 0
number 3
number 7
number 7
number 7
number -1
===*/
/* Because search happens internally using a byte search, a few simple tests
* with Unicode characters of varying length.
*/
print('non-bmp');
function nonBmpTest() {
var str = new String('foo\u1234bar\udeadquux\ubeefbaz');
function p(x) {
print(typeof x, x);
}
p(str.lastIndexOf('foo'));
p(str.lastIndexOf('\u1234'));
p(str.lastIndexOf('\udead'));
p(str.lastIndexOf('\udead', 7)); // found
p(str.lastIndexOf('\udead', 8)); // found
p(str.lastIndexOf('\udead', 6)); // not found
}
try {
nonBmpTest();
} catch (e) {
print(e);
}