function test(this_val, regexp_val, arg_count) { var t; try { if (arg_count === 0) { t = String.prototype.search.call(); } else if (arg_count === 1) { t = String.prototype.search.call(this_val); } else { t = String.prototype.search.call(this_val, regexp_val); } print(typeof t, t); } catch (e) { print(e.name); } } /*=== basic number 3 number -1 number 5 number 0 number 3 string 12345 number -1 string 12345 number 3 string 12345 number -1 string 12345 number 4 string 12345 number -1 number -1 number 3 number 0 ===*/ print('basic'); function basicTest() { // basic searches test('foobar', 'bar'); test('foobar', 'quux'); // non-BMP, verify that char index is returned test('\u1234\u0123foobar\udead\ubeef', 'bar'); // a string is always interpreted as a regexp, not literally test('foo', '.'); // RegExp global flag and lastIndex are ignored and unaffected re = /bar/; re.lastIndex = '12345'; test('foobar', re); print(typeof re.lastIndex, re.lastIndex); re = /bar/; re.lastIndex = '12345'; test('foobaz', re); print(typeof re.lastIndex, re.lastIndex); // RegExp multiline and ignoreCare work as expected re = /bar/i; re.lastIndex = '12345'; test('fooBaR', re); print(typeof re.lastIndex, re.lastIndex); re = /^bar/; // single line, does not match re.lastIndex = '12345'; test('foo\nbar', re); print(typeof re.lastIndex, re.lastIndex); re = /^bar/m; re.lastIndex = '12345'; test('foo\nbar', re); print(typeof re.lastIndex, re.lastIndex); // if regexp argument is not a RegExp, a fresh one is created; it will have // no flags, so regexp flags will be: global=false, multiline=false, ignoreCase=false test('Foo', 'foo'); // case sensitive -> no match test('foo\nbar', '^bar'); // single line -> no match // multiple matches -> report first test('foobarfoobarfoo', 'bar'); // empty string and empty search string test('', ''); } try { basicTest(); } catch (e) { print(e); } /*=== coercion TypeError TypeError TypeError number 1 number 2 number 1 number 1 number 1 number 8 number 0 number 0 number 3 number 3 number 3 number 3 number 3 number 3 number 1 number -1 ===*/ print('coercion'); function coercionTest() { // this coercion test(undefined, undefined, 0); test(undefined, 'foo'); test(null, 'foo'); test(true, 'rue'); test(false, 'lse'); test(123, '2'); test('foo', 'oo'); test([1,2], ',2'); test({ foo: 1, bar: 2 }, 'Object'); // regexp coercion -- RegExps are accepted as is, everything else is // handed over to the RegExp constructor (without coercion). The RegExp // constructor coerces with ToString(), except that undefined values are // coerced to the empty string (E5.1 Section 15.10.4.1). // // The undefined case should be same as an empty search string, i.e. // match at index 0. Rhino will work correctly for the first test // but if an explicit undefined argument is given, it will coerce it // to 'undefined' search string. test('fooundefinedbar', undefined, 1); // coerces to empty, match at 0 test('fooundefinedbar', undefined); // same test('foonullbar', null); test('footruebar', true); test('foofalsebar', false); test('foo123bar', 123); test('fooquuxbar', 'quux'); test('foo1,2bar', [1,2]); // interesting case: ToString(obj) will be '[object Object]' which is // a RegExp class expression! test('abcdefgh', { foo: 1, bar: 2 }); // match at offset 1 ('b') test('xxxP', { foo: 1, bar: 2 }); // no match } try { coercionTest(); } catch (e) { print(e); }