jscript: Treat no argument as "undefined" in RegExp.test.
[wine] / dlls / jscript / tests / regexp.js
1 /*
2  * Copyright 2008 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19
20 var m, re, b, i, obj;
21
22 re = /a+/;
23 ok(re.lastIndex === 0, "re.lastIndex = " + re.lastIndex);
24
25 m = re.exec(" aabaaa");
26 ok(re.lastIndex === 3, "re.lastIndex = " + re.lastIndex);
27 ok(m.index === 1, "m.index = " + m.index);
28 ok(m.input === " aabaaa", "m.input = " + m.input);
29 ok(m.length === 1, "m.length = " + m.length);
30 ok(m[0] === "aa", "m[0] = " + m[0]);
31
32 m = re.exec(" aabaaa");
33 ok(re.lastIndex === 3, "re.lastIndex = " + re.lastIndex);
34 ok(m.index === 1, "m.index = " + m.index);
35 ok(m.input === " aabaaa", "m.input = " + m.input);
36 ok(m.length === 1, "m.length = " + m.length);
37 ok(m[0] === "aa", "m[0] = " + m[0]);
38
39 re = /a+/g;
40 ok(re.lastIndex === 0, "re.lastIndex = " + re.lastIndex);
41
42 m = re.exec(" aabaaa");
43 ok(re.lastIndex === 3, "re.lastIndex = " + re.lastIndex);
44 ok(m.index === 1, "m.index = " + m.index);
45 ok(m.input === " aabaaa", "m.input = " + m.input);
46 ok(m.length === 1, "m.length = " + m.length);
47 ok(m[0] === "aa", "m[0] = " + m[0]);
48
49 m = re.exec(" aabaaa");
50 ok(re.lastIndex === 7, "re.lastIndex = " + re.lastIndex);
51 ok(m.index === 4, "m.index = " + m.index);
52 ok(m.input === " aabaaa", "m.input = " + m.input);
53 ok(m.length === 1, "m.length = " + m.length);
54 ok(m[0] === "aaa", "m[0] = " + m[0]);
55
56 m = re.exec(" aabaaa");
57 ok(re.lastIndex === 0, "re.lastIndex = " + re.lastIndex);
58 ok(m === null, "m is not null");
59
60 re.exec("               a");
61 ok(re.lastIndex === 16, "re.lastIndex = " + re.lastIndex);
62
63 m = re.exec(" a");
64 ok(m === null, "m is not null");
65 ok(re.lastIndex === 0, "re.lastIndex = " + re.lastIndex);
66
67 m = re.exec(" a");
68 ok(re.lastIndex === 2, "re.lastIndex = " + re.lastIndex);
69
70 m = re.exec();
71 ok(m === null, "m is not null");
72 ok(re.lastIndex === 0, "re.lastIndex = " + re.lastIndex);
73
74 m = /(a|b)+|(c)/.exec("aa");
75 ok(m[0] === "aa", "m[0] = " + m[0]);
76 ok(m[1] === "a", "m[1] = " + m[1]);
77 ok(m[2] === "", "m[2] = " + m[2]);
78
79 b = re.test("  a ");
80 ok(b === true, "re.test('  a ') returned " + b);
81 ok(re.lastIndex === 3, "re.lastIndex = " + re.lastIndex);
82
83 b = re.test(" a ");
84 ok(b === false, "re.test(' a ') returned " + b);
85 ok(re.lastIndex === 0, "re.lastIndex = " + re.lastIndex);
86
87 re = /\[([^\[]+)\]/g;
88 m = re.exec(" [test]  ");
89 ok(re.lastIndex === 7, "re.lastIndex = " + re.lastIndex);
90 ok(m.index === 1, "m.index = " + m.index);
91 ok(m.input === " [test]  ", "m.input = " + m.input);
92 ok(m.length === 2, "m.length = " + m.length);
93 ok(m[0] === "[test]", "m[0] = " + m[0]);
94 ok(m[1] === "test", "m[1] = " + m[1]);
95
96 b = /a*/.test();
97 ok(b === true, "/a*/.test() returned " + b);
98
99 b = /f/.test();
100 ok(b === true, "/f/.test() returned " + b);
101
102 b = /abc/.test();
103 ok(b === false, "/abc/.test() returned " + b);
104
105 m = "abcabc".match(re = /ca/);
106 ok(typeof(m) === "object", "typeof m is not object");
107 ok(m.length === 1, "m.length is not 1");
108 ok(m["0"] === "ca", "m[0] is not \"ca\"");
109 ok(m.constructor === Array, "unexpected m.constructor");
110 ok(re.lastIndex === 4, "re.lastIndex = " + re.lastIndex);
111
112 m = "abcabc".match(/ab/);
113 ok(typeof(m) === "object", "typeof m is not object");
114 ok(m.length === 1, "m.length is not 1");
115 ok(m["0"] === "ab", "m[0] is not \"ab\"");
116
117 m = "abcabc".match(/ab/g);
118 ok(typeof(m) === "object", "typeof m is not object");
119 ok(m.length === 2, "m.length is not 2");
120 ok(m["0"] === "ab", "m[0] is not \"ab\"");
121 ok(m["1"] === "ab", "m[1] is not \"ab\"");
122 /* ok(m.input === "abcabc", "m.input = " + m.input); */
123
124 m = "abcabc".match(/Ab/g);
125 ok(typeof(m) === "object", "typeof m is not object");
126 ok(m === null, "m is not null");
127
128 m = "abcabc".match(/Ab/gi);
129 ok(typeof(m) === "object", "typeof m is not object");
130 ok(m.length === 2, "m.length is not 2");
131 ok(m["0"] === "ab", "m[0] is not \"ab\"");
132 ok(m["1"] === "ab", "m[1] is not \"ab\"");
133
134 m = "aaabcabc".match(/a+b/g);
135 ok(typeof(m) === "object", "typeof m is not object");
136 ok(m.length === 2, "m.length is not 2");
137 ok(m["0"] === "aaab", "m[0] is not \"ab\"");
138 ok(m["1"] === "ab", "m[1] is not \"ab\"");
139
140 m = "aaa\\\\cabc".match(/\\/g);
141 ok(typeof(m) === "object", "typeof m is not object");
142 ok(m.length === 2, "m.length is not 2");
143 ok(m["0"] === "\\", "m[0] is not \"\\\"");
144 ok(m["1"] === "\\", "m[1] is not \"\\\"");
145
146 m = "abcabc".match(new RegExp("ab"));
147 ok(typeof(m) === "object", "typeof m is not object");
148 ok(m.length === 1, "m.length is not 1");
149 ok(m["0"] === "ab", "m[0] is not \"ab\"");
150
151 m = "abcabc".match(new RegExp("ab","g"));
152 ok(typeof(m) === "object", "typeof m is not object");
153 ok(m.length === 2, "m.length is not 2");
154 ok(m["0"] === "ab", "m[0] is not \"ab\"");
155 ok(m["1"] === "ab", "m[1] is not \"ab\"");
156
157 m = "abcabc".match(new RegExp(/ab/g));
158 ok(typeof(m) === "object", "typeof m is not object");
159 ok(m.length === 2, "m.length is not 2");
160 ok(m["0"] === "ab", "m[0] is not \"ab\"");
161 ok(m["1"] === "ab", "m[1] is not \"ab\"");
162
163 m = "abcabc".match(new RegExp("ab","g", "test"));
164 ok(typeof(m) === "object", "typeof m is not object");
165 ok(m.length === 2, "m.length is not 2");
166 ok(m["0"] === "ab", "m[0] is not \"ab\"");
167 ok(m["1"] === "ab", "m[1] is not \"ab\"");
168
169 m = "abcabcg".match("ab", "g");
170 ok(typeof(m) === "object", "typeof m is not object");
171 ok(m.length === 1, "m.length is not 1");
172 ok(m["0"] === "ab", "m[0] is not \"ab\"");
173
174 m = "abcabc".match();
175 ok(m === null, "m is not null");
176
177 m = "abcabc".match(/(a)(b)cabc/);
178 ok(typeof(m) === "object", "typeof m is not object");
179 ok(m.length === 3, "m.length is not 3");
180 ok(m[0] === "abcabc", "m[0] is not \"abc\"");
181 ok(m[1] === "a", "m[1] is not \"a\"");
182 ok(m[2] === "b", "m[2] is not \"b\"");
183
184 re = /(a)bcabc/;
185 re.lastIndex = -3;
186 m = "abcabc".match(re);
187 ok(typeof(m) === "object", "typeof m is not object");
188 ok(m.length === 2, "m.length = " + m.length + "expected 3");
189 ok(m[0] === "abcabc", "m[0] is not \"abc\"");
190 ok(m[1] === "a", "m[1] is not \"a\"");
191 ok(re.lastIndex === 6, "re.lastIndex = " + re.lastIndex);
192
193 re = /(a)bcabc/;
194 re.lastIndex = 2;
195 m = "abcabcxxx".match(re);
196 ok(typeof(m) === "object", "typeof m is not object");
197 ok(m.length === 2, "m.length = " + m.length + "expected 3");
198 ok(m[0] === "abcabc", "m[0] is not \"abc\"");
199 ok(m[1] === "a", "m[1] is not \"a\"");
200 ok(m.input === "abcabcxxx", "m.input = " + m.input);
201 ok(re.lastIndex === 6, "re.lastIndex = " + re.lastIndex);
202
203 r = "- [test] -".replace(re = /\[([^\[]+)\]/g, "success");
204 ok(r === "- success -", "r = " + r + " expected '- success -'");
205 ok(re.lastIndex === 8, "re.lastIndex = " + re.lastIndex);
206
207 r = "[test] [test]".replace(/\[([^\[]+)\]/g, "aa");
208 ok(r === "aa aa", "r = " + r + "aa aa");
209
210 r = "[test] [test]".replace(/\[([^\[]+)\]/, "aa");
211 ok(r === "aa [test]", "r = " + r + " expected 'aa [test]'");
212
213 r = "- [test] -".replace(/\[([^\[]+)\]/g);
214 ok(r === "- undefined -", "r = " + r + " expected '- undefined -'");
215
216 r = "- [test] -".replace(/\[([^\[]+)\]/g, true);
217 ok(r === "- true -", "r = " + r + " expected '- true -'");
218
219 r = "- [test] -".replace(/\[([^\[]+)\]/g, true, "test");
220 ok(r === "- true -", "r = " + r + " expected '- true -'");
221
222 var tmp = 0;
223
224 function replaceFunc1(m, off, str) {
225     ok(arguments.length === 3, "arguments.length = " + arguments.length);
226
227     switch(tmp) {
228     case 0:
229         ok(m === "[test1]", "m = " + m + " expected [test1]");
230         ok(off === 0, "off = " + off + " expected 0");
231         break;
232     case 1:
233         ok(m === "[test2]", "m = " + m + " expected [test2]");
234         ok(off === 8, "off = " + off + " expected 8");
235         break;
236     default:
237         ok(false, "unexpected call");
238     }
239
240     ok(str === "[test1] [test2]", "str = " + arguments[3]);
241     return "r" + tmp++;
242 }
243
244 r = "[test1] [test2]".replace(/\[[^\[]+\]/g, replaceFunc1);
245 ok(r === "r0 r1", "r = " + r + " expected 'r0 r1'");
246
247 tmp = 0;
248
249 function replaceFunc2(m, subm, off, str) {
250     ok(arguments.length === 4, "arguments.length = " + arguments.length);
251
252     switch(tmp) {
253     case 0:
254         ok(subm === "test1", "subm = " + subm);
255         ok(m === "[test1]", "m = " + m + " expected [test1]");
256         ok(off === 0, "off = " + off + " expected 0");
257         break;
258     case 1:
259         ok(subm === "test2", "subm = " + subm);
260         ok(m === "[test2]", "m = " + m + " expected [test2]");
261         ok(off === 8, "off = " + off + " expected 8");
262         break;
263     default:
264         ok(false, "unexpected call");
265     }
266
267     ok(str === "[test1] [test2]", "str = " + arguments[3]);
268     return "r" + tmp++;
269 }
270
271 r = "[test1] [test2]".replace(/\[([^\[]+)\]/g, replaceFunc2);
272 ok(r === "r0 r1", "r = '" + r + "' expected 'r0 r1'");
273
274 r = "$1,$2".replace(/(\$(\d))/g, "$$1-$1$2");
275 ok(r === "$1-$11,$1-$22", "r = '" + r + "' expected '$1-$11,$1-$22'");
276
277 r = "abc &1 123".replace(/(\&(\d))/g, "$&");
278 ok(r === "abc &1 123", "r = '" + r + "' expected 'abc &1 123'");
279
280 r = "abc &1 123".replace(/(\&(\d))/g, "$'");
281 ok(r === "abc  123 123", "r = '" + r + "' expected 'abc  123 123'");
282
283 r = "abc &1 123".replace(/(\&(\d))/g, "$`");
284 ok(r === "abc abc  123", "r = '" + r + "' expected 'abc abc  123'");
285
286 r = "abc &1 123".replace(/(\&(\d))/g, "$3");
287 ok(r === "abc $3 123", "r = '" + r + "' expected 'abc $3 123'");
288
289 r = "abc &1 123".replace(/(\&(\d))/g, "$");
290 ok(r === "abc $ 123", "r = '" + r + "' expected 'abc $ 123'");
291
292 r = "abc &1 123".replace(/(\&(\d))/g, "$a");
293 ok(r === "abc $a 123", "r = '" + r + "' expected 'abc $a 123'");
294
295 r = "abc &1 123".replace(/(\&(\d))/g, "$11");
296 ok(r === "abc &11 123", "r = '" + r + "' expected 'abc &11 123'");
297
298 r = "abc &1 123".replace(/(\&(\d))/g, "$0");
299 ok(r === "abc $0 123", "r = '" + r + "' expected 'abc $0 123'");
300
301 r = "1 2 3".replace("2", "$&");
302 ok(r === "1 $& 3", "r = '" + r + "' expected '1 $& 3'");
303
304 r = "1 2 3".replace("2", "$'");
305 ok(r === "1 $' 3", "r = '" + r + "' expected '1 $' 3'");
306
307 r = "1,,2,3".split(/,+/g);
308 ok(r.length === 3, "r.length = " + r.length);
309 ok(r[0] === "1", "r[0] = " + r[0]);
310 ok(r[1] === "2", "r[1] = " + r[1]);
311 ok(r[2] === "3", "r[2] = " + r[2]);
312
313 r = "1,,2,3".split(/,+/);
314 ok(r.length === 3, "r.length = " + r.length);
315 ok(r[0] === "1", "r[0] = " + r[0]);
316 ok(r[1] === "2", "r[1] = " + r[1]);
317 ok(r[2] === "3", "r[2] = " + r[2]);
318
319 r = "1,,2,".split(/,+/);
320 ok(r.length === 2, "r.length = " + r.length);
321 ok(r[0] === "1", "r[0] = " + r[0]);
322 ok(r[1] === "2", "r[1] = " + r[1]);
323
324 re = /,+/;
325 r = "1,,2,".split(re);
326 ok(r.length === 2, "r.length = " + r.length);
327 ok(r[0] === "1", "r[0] = " + r[0]);
328 ok(r[1] === "2", "r[1] = " + r[1]);
329 ok(re.lastIndex === 5, "re.lastIndex = " + re.lastIndex);
330
331 re = /,+/g;
332 r = "1,,2,".split(re);
333 ok(r.length === 2, "r.length = " + r.length);
334 ok(r[0] === "1", "r[0] = " + r[0]);
335 ok(r[1] === "2", "r[1] = " + r[1]);
336 ok(re.lastIndex === 5, "re.lastIndex = " + re.lastIndex);
337
338 r = "1 12 \t3".split(re = /\s+/).join(";");
339 ok(r === "1;12;3", "r = " + r);
340 ok(re.lastIndex === 6, "re.lastIndex = " + re.lastIndex);
341
342 r = "123".split(re = /\s+/).join(";");
343 ok(r === "123", "r = " + r);
344 ok(re.lastIndex === 0, "re.lastIndex = " + re.lastIndex);
345
346 /* another standard violation */
347 r = "1 12 \t3".split(re = /(\s)+/g).join(";");
348 ok(r === "1;12;3", "r = " + r);
349 ok(re.lastIndex === 6, "re.lastIndex = " + re.lastIndex);
350
351 re = /,+/;
352 re.lastIndex = 4;
353 r = "1,,2,".split(re);
354 ok(r.length === 2, "r.length = " + r.length);
355 ok(r[0] === "1", "r[0] = " + r[0]);
356 ok(r[1] === "2", "r[1] = " + r[1]);
357 ok(re.lastIndex === 5, "re.lastIndex = " + re.lastIndex);
358
359 re = /abc[^d]/g;
360 ok(re.source === "abc[^d]", "re.source = '" + re.source + "', expected 'abc[^d]'");
361
362 re = /a\bc[^d]/g;
363 ok(re.source === "a\\bc[^d]", "re.source = '" + re.source + "', expected 'a\\bc[^d]'");
364
365 re = /abc/;
366 ok(re === RegExp(re), "re !== RegExp(re)");
367
368 re = RegExp("abc[^d]", "g");
369 ok(re.source === "abc[^d]", "re.source = '" + re.source + "', expected 'abc[^d]'");
370
371 re = /abc/;
372 ok(re === RegExp(re, undefined), "re !== RegExp(re, undefined)");
373
374 re = /abc/;
375 ok(re === RegExp(re, undefined, 1), "re !== RegExp(re, undefined, 1)");
376
377 re = /a/g;
378 ok(re.lastIndex === 0, "re.lastIndex = " + re.lastIndex + " expected 0");
379
380 m = re.exec(" a   ");
381 ok(re.lastIndex === 2, "re.lastIndex = " + re.lastIndex + " expected 2");
382 ok(m.index === 1, "m.index = " + m.index + " expected 1");
383
384 m = re.exec(" a   ");
385 ok(re.lastIndex === 0, "re.lastIndex = " + re.lastIndex + " expected 0");
386 ok(m === null, "m = " + m + " expected null");
387
388 re.lastIndex = 2;
389 m = re.exec(" a a ");
390 ok(re.lastIndex === 4, "re.lastIndex = " + re.lastIndex + " expected 4");
391 ok(m.index === 3, "m.index = " + m.index + " expected 3");
392
393 re.lastIndex = "2";
394 ok(re.lastIndex === "2", "re.lastIndex = " + re.lastIndex + " expected '2'");
395 m = re.exec(" a a ");
396 ok(re.lastIndex === 4, "re.lastIndex = " + re.lastIndex + " expected 4");
397 ok(m.index === 3, "m.index = " + m.index + " expected 3");
398
399 var li = 0;
400 var obj = new Object();
401 obj.valueOf = function() { return li; };
402
403 re.lastIndex = obj;
404 ok(re.lastIndex === obj, "re.lastIndex = " + re.lastIndex + " expected obj");
405 li = 2;
406 m = re.exec(" a a ");
407 ok(re.lastIndex === 2, "re.lastIndex = " + re.lastIndex + " expected 2");
408 ok(m.index === 1, "m.index = " + m.index + " expected 1");
409
410 re.lastIndex = 3;
411 re.lastIndex = "test";
412 ok(re.lastIndex === "test", "re.lastIndex = " + re.lastIndex + " expected 'test'");
413 m = re.exec(" a a ");
414 ok(re.lastIndex === 2 || re.lastIndex === 0, "re.lastIndex = " + re.lastIndex + " expected 2 or 0");
415 if(re.lastIndex != 0)
416     ok(m.index === 1, "m.index = " + m.index + " expected 1");
417 else
418     ok(m === null, "m = " + m + " expected null");
419
420 re.lastIndex = 0;
421 re.lastIndex = 3.9;
422 ok(re.lastIndex === 3.9, "re.lastIndex = " + re.lastIndex + " expected 3.9");
423 m = re.exec(" a a ");
424 ok(re.lastIndex === 4, "re.lastIndex = " + re.lastIndex + " expected 4");
425 ok(m.index === 3, "m.index = " + m.index + " expected 3");
426
427 obj.valueOf = function() { throw 0; }
428 re.lastIndex = obj;
429 ok(re.lastIndex === obj, "unexpected re.lastIndex");
430 m = re.exec(" a a ");
431 ok(re.lastIndex === 2, "re.lastIndex = " + re.lastIndex + " expected 2");
432 ok(m.index === 1, "m.index = " + m.index + " expected 1");
433
434 re.lastIndex = -3;
435 ok(re.lastIndex === -3, "re.lastIndex = " + re.lastIndex + " expected -3");
436 m = re.exec(" a a ");
437 ok(re.lastIndex === 0, "re.lastIndex = " + re.lastIndex + " expected 0");
438 ok(m === null, "m = " + m + " expected null");
439
440 re.lastIndex = -1;
441 ok(re.lastIndex === -1, "re.lastIndex = " + re.lastIndex + " expected -1");
442 m = re.exec("  ");
443 ok(re.lastIndex === 0, "re.lastIndex = " + re.lastIndex + " expected 0");
444 ok(m === null, "m = " + m + " expected null");
445
446 re = /a/;
447 re.lastIndex = -3;
448 ok(re.lastIndex === -3, "re.lastIndex = " + re.lastIndex + " expected -3");
449 m = re.exec(" a a ");
450 ok(re.lastIndex === 2, "re.lastIndex = " + re.lastIndex + " expected 0");
451 ok(m.index === 1, "m = " + m + " expected 1");
452
453 re.lastIndex = -1;
454 ok(re.lastIndex === -1, "re.lastIndex = " + re.lastIndex + " expected -1");
455 m = re.exec("  ");
456 ok(re.lastIndex === 0, "re.lastIndex = " + re.lastIndex + " expected 0");
457 ok(m === null, "m = " + m + " expected null");
458
459 re = /aa/g;
460 i = 'baacd'.search(re);
461 ok(i === 1, "'baacd'.search(re) = " + i);
462 ok(re.lastIndex === 3, "re.lastIndex = " + re.lastIndex);
463
464 re.lastIndex = 2;
465 i = 'baacdaa'.search(re);
466 ok(i === 1, "'baacd'.search(re) = " + i);
467 ok(re.lastIndex === 3, "re.lastIndex = " + re.lastIndex);
468
469 re = /aa/;
470 i = 'baacd'.search(re);
471 ok(i === 1, "'baacd'.search(re) = " + i);
472 ok(re.lastIndex === 3, "re.lastIndex = " + re.lastIndex);
473
474 re.lastIndex = 2;
475 i = 'baacdaa'.search(re);
476 ok(i === 1, "'baacd'.search(re) = " + i);
477 ok(re.lastIndex === 3, "re.lastIndex = " + re.lastIndex);
478
479 re = /d/g;
480 re.lastIndex = 1;
481 i = 'abc'.search(re);
482 ok(i === -1, "'abc'.search(/d/g) = " + i);
483 ok(re.lastIndex === 0, "re.lastIndex = " + re.lastIndex);
484
485 i = 'abcdde'.search(/[df]/);
486 ok(i === 3, "'abc'.search(/[df]/) = " + i);
487
488 i = 'abcdde'.search(/[df]/, "a");
489 ok(i === 3, "'abc'.search(/[df]/) = " + i);
490
491 i = 'abcdde'.search("[df]");
492 ok(i === 3, "'abc'.search(/d*/) = " + i);
493
494 obj = {
495     toString: function() { return "abc"; }
496 };
497 i = String.prototype.search.call(obj, "b");
498 ok(i === 1, "String.prototype.seatch.apply(obj, 'b') = " + i);
499
500 i = " undefined ".search();
501 ok(i === null, "' undefined '.search() = " + i);
502
503 reportSuccess();