mirror of https://github.com/svaarala/duktape.git
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.
357 lines
6.8 KiB
357 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);
|
|
}
|
|
|
|
|