Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / v8 / test / mjsunit / regexp.js
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 function testEscape(str, regex) {
29   assertEquals("foo:bar:baz", str.split(regex).join(":"));
30 }
31
32 testEscape("foo\nbar\nbaz", /\n/);
33 testEscape("foo bar baz", /\s/);
34 testEscape("foo\tbar\tbaz", /\s/);
35 testEscape("foo-bar-baz", /\u002D/);
36
37 // Test containing null char in regexp.
38 var s = '[' + String.fromCharCode(0) + ']';
39 var re = new RegExp(s);
40 assertEquals(s.match(re).length, 1);
41 assertEquals(s.match(re)[0], String.fromCharCode(0));
42
43 // Test strings containing all line separators
44 s = 'aA\nbB\rcC\r\ndD\u2028eE\u2029fF';
45 re = /^./gm; // any non-newline character at the beginning of a line
46 var result = s.match(re);
47 assertEquals(result.length, 6);
48 assertEquals(result[0], 'a');
49 assertEquals(result[1], 'b');
50 assertEquals(result[2], 'c');
51 assertEquals(result[3], 'd');
52 assertEquals(result[4], 'e');
53 assertEquals(result[5], 'f');
54
55 re = /.$/gm; // any non-newline character at the end of a line
56 result = s.match(re);
57 assertEquals(result.length, 6);
58 assertEquals(result[0], 'A');
59 assertEquals(result[1], 'B');
60 assertEquals(result[2], 'C');
61 assertEquals(result[3], 'D');
62 assertEquals(result[4], 'E');
63 assertEquals(result[5], 'F');
64
65 re = /^[^]/gm; // *any* character at the beginning of a line
66 result = s.match(re);
67 assertEquals(result.length, 7);
68 assertEquals(result[0], 'a');
69 assertEquals(result[1], 'b');
70 assertEquals(result[2], 'c');
71 assertEquals(result[3], '\n');
72 assertEquals(result[4], 'd');
73 assertEquals(result[5], 'e');
74 assertEquals(result[6], 'f');
75
76 re = /[^]$/gm; // *any* character at the end of a line
77 result = s.match(re);
78 assertEquals(result.length, 7);
79 assertEquals(result[0], 'A');
80 assertEquals(result[1], 'B');
81 assertEquals(result[2], 'C');
82 assertEquals(result[3], '\r');
83 assertEquals(result[4], 'D');
84 assertEquals(result[5], 'E');
85 assertEquals(result[6], 'F');
86
87 // Some tests from the Mozilla tests, where our behavior used to differ from
88 // SpiderMonkey.
89 // From ecma_3/RegExp/regress-334158.js
90 assertTrue(/\ca/.test( "\x01" ));
91 assertFalse(/\ca/.test( "\\ca" ));
92 assertFalse(/\ca/.test( "ca" ));
93 assertTrue(/\c[a/]/.test( "\\ca" ));
94 assertTrue(/\c[a/]/.test( "\\c/" ));
95
96 // Test \c in character class
97 re = /^[\cM]$/;
98 assertTrue(re.test("\r"));
99 assertFalse(re.test("M"));
100 assertFalse(re.test("c"));
101 assertFalse(re.test("\\"));
102 assertFalse(re.test("\x03"));  // I.e., read as \cc
103
104 re = /^[\c]]$/;
105 assertTrue(re.test("c]"));
106 assertTrue(re.test("\\]"));
107 assertFalse(re.test("\x1d"));  // ']' & 0x1f
108 assertFalse(re.test("\x03]"));  // I.e., read as \cc
109
110 re = /^[\c1]$/;  // Digit control characters are masked in character classes.
111 assertTrue(re.test("\x11"));
112 assertFalse(re.test("\\"));
113 assertFalse(re.test("c"));
114 assertFalse(re.test("1"));
115
116 re = /^[\c_]$/;  // Underscore control character is masked in character classes.
117 assertTrue(re.test("\x1f"));
118 assertFalse(re.test("\\"));
119 assertFalse(re.test("c"));
120 assertFalse(re.test("_"));
121
122 re = /^[\c$]$/;  // Other characters are interpreted literally.
123 assertFalse(re.test("\x04"));
124 assertTrue(re.test("\\"));
125 assertTrue(re.test("c"));
126 assertTrue(re.test("$"));
127
128 assertTrue(/^[Z-\c-e]*$/.test("Z[\\cde"));
129
130 // Test that we handle \s and \S correctly on special Unicode characters.
131 re = /\s/;
132 assertTrue(re.test("\u2028"));
133 assertTrue(re.test("\u2029"));
134 assertTrue(re.test("\uFEFF"));
135
136 re = /\S/;
137 assertFalse(re.test("\u2028"));
138 assertFalse(re.test("\u2029"));
139 assertFalse(re.test("\uFEFF"));
140
141 // Test that we handle \s and \S correctly inside some bizarre
142 // character classes.
143 re = /[\s-:]/;
144 assertTrue(re.test('-'));
145 assertTrue(re.test(':'));
146 assertTrue(re.test(' '));
147 assertTrue(re.test('\t'));
148 assertTrue(re.test('\n'));
149 assertFalse(re.test('a'));
150 assertFalse(re.test('Z'));
151
152 re = /[\S-:]/;
153 assertTrue(re.test('-'));
154 assertTrue(re.test(':'));
155 assertFalse(re.test(' '));
156 assertFalse(re.test('\t'));
157 assertFalse(re.test('\n'));
158 assertTrue(re.test('a'));
159 assertTrue(re.test('Z'));
160
161 re = /[^\s-:]/;
162 assertFalse(re.test('-'));
163 assertFalse(re.test(':'));
164 assertFalse(re.test(' '));
165 assertFalse(re.test('\t'));
166 assertFalse(re.test('\n'));
167 assertTrue(re.test('a'));
168 assertTrue(re.test('Z'));
169
170 re = /[^\S-:]/;
171 assertFalse(re.test('-'));
172 assertFalse(re.test(':'));
173 assertTrue(re.test(' '));
174 assertTrue(re.test('\t'));
175 assertTrue(re.test('\n'));
176 assertFalse(re.test('a'));
177 assertFalse(re.test('Z'));
178
179 re = /[\s]/;
180 assertFalse(re.test('-'));
181 assertFalse(re.test(':'));
182 assertTrue(re.test(' '));
183 assertTrue(re.test('\t'));
184 assertTrue(re.test('\n'));
185 assertFalse(re.test('a'));
186 assertFalse(re.test('Z'));
187
188 re = /[^\s]/;
189 assertTrue(re.test('-'));
190 assertTrue(re.test(':'));
191 assertFalse(re.test(' '));
192 assertFalse(re.test('\t'));
193 assertFalse(re.test('\n'));
194 assertTrue(re.test('a'));
195 assertTrue(re.test('Z'));
196
197 re = /[\S]/;
198 assertTrue(re.test('-'));
199 assertTrue(re.test(':'));
200 assertFalse(re.test(' '));
201 assertFalse(re.test('\t'));
202 assertFalse(re.test('\n'));
203 assertTrue(re.test('a'));
204 assertTrue(re.test('Z'));
205
206 re = /[^\S]/;
207 assertFalse(re.test('-'));
208 assertFalse(re.test(':'));
209 assertTrue(re.test(' '));
210 assertTrue(re.test('\t'));
211 assertTrue(re.test('\n'));
212 assertFalse(re.test('a'));
213 assertFalse(re.test('Z'));
214
215 re = /[\s\S]/;
216 assertTrue(re.test('-'));
217 assertTrue(re.test(':'));
218 assertTrue(re.test(' '));
219 assertTrue(re.test('\t'));
220 assertTrue(re.test('\n'));
221 assertTrue(re.test('a'));
222 assertTrue(re.test('Z'));
223
224 re = /[^\s\S]/;
225 assertFalse(re.test('-'));
226 assertFalse(re.test(':'));
227 assertFalse(re.test(' '));
228 assertFalse(re.test('\t'));
229 assertFalse(re.test('\n'));
230 assertFalse(re.test('a'));
231 assertFalse(re.test('Z'));
232
233 // First - is treated as range operator, second as literal minus.
234 // This follows the specification in parsing, but doesn't throw on
235 // the \s at the beginning of the range.
236 re = /[\s-0-9]/;
237 assertTrue(re.test(' '));
238 assertTrue(re.test('\xA0'));
239 assertTrue(re.test('-'));
240 assertTrue(re.test('0'));
241 assertTrue(re.test('9'));
242 assertFalse(re.test('1'));
243
244 // Test beginning and end of line assertions with or without the
245 // multiline flag.
246 re = /^\d+/;
247 assertFalse(re.test("asdf\n123"));
248 re = /^\d+/m;
249 assertTrue(re.test("asdf\n123"));
250
251 re = /\d+$/;
252 assertFalse(re.test("123\nasdf"));
253 re = /\d+$/m;
254 assertTrue(re.test("123\nasdf"));
255
256 // Test that empty matches are handled correctly for multiline global
257 // regexps.
258 re = /^(.*)/mg;
259 assertEquals(3, "a\n\rb".match(re).length);
260 assertEquals("*a\n*b\r*c\n*\r*d\r*\n*e", "a\nb\rc\n\rd\r\ne".replace(re, "*$1"));
261
262 // Test that empty matches advance one character
263 re = new RegExp("", "g");
264 assertEquals("xAx", "A".replace(re, "x"));
265 assertEquals(3, String.fromCharCode(161).replace(re, "x").length);
266
267 // Test that we match the KJS behavior with regard to undefined constructor
268 // arguments:
269 re = new RegExp();
270 // KJS actually shows this as '//'.  Here we match the Firefox behavior (ie,
271 // giving a syntactically legal regexp literal).
272 assertEquals('/(?:)/', re.toString());
273 re = new RegExp(void 0);
274 assertEquals('/(?:)/', re.toString());
275 re.compile();
276 assertEquals('/(?:)/', re.toString());
277 re.compile(void 0);
278 assertEquals('/undefined/', re.toString());
279
280
281 // Check for lazy RegExp literal creation
282 function lazyLiteral(doit) {
283   if (doit) return "".replace(/foo(/gi, "");
284   return true;
285 }
286
287 assertTrue(lazyLiteral(false));
288 assertThrows("lazyLiteral(true)");
289
290 // Check $01 and $10
291 re = new RegExp("(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)");
292 assertEquals("t", "123456789t".replace(re, "$10"), "$10");
293 assertEquals("15", "123456789t".replace(re, "$15"), "$10");
294 assertEquals("1", "123456789t".replace(re, "$01"), "$01");
295 assertEquals("$001", "123456789t".replace(re, "$001"), "$001");
296 re = new RegExp("foo(.)");
297 assertEquals("bar$0", "foox".replace(re, "bar$0"), "$0");
298 assertEquals("bar$00", "foox".replace(re, "bar$00"), "$00");
299 assertEquals("bar$000", "foox".replace(re, "bar$000"), "$000");
300 assertEquals("barx", "foox".replace(re, "bar$01"), "$01 2");
301 assertEquals("barx5", "foox".replace(re, "bar$15"), "$15");
302
303 assertFalse(/()foo$\1/.test("football"), "football1");
304 assertFalse(/foo$(?=ball)/.test("football"), "football2");
305 assertFalse(/foo$(?!bar)/.test("football"), "football3");
306 assertTrue(/()foo$\1/.test("foo"), "football4");
307 assertTrue(/foo$(?=(ball)?)/.test("foo"), "football5");
308 assertTrue(/()foo$(?!bar)/.test("foo"), "football6");
309 assertFalse(/(x?)foo$\1/.test("football"), "football7");
310 assertFalse(/foo$(?=ball)/.test("football"), "football8");
311 assertFalse(/foo$(?!bar)/.test("football"), "football9");
312 assertTrue(/(x?)foo$\1/.test("foo"), "football10");
313 assertTrue(/foo$(?=(ball)?)/.test("foo"), "football11");
314 assertTrue(/foo$(?!bar)/.test("foo"), "football12");
315
316 // Check that the back reference has two successors.  See
317 // BackReferenceNode::PropagateForward.
318 assertFalse(/f(o)\b\1/.test('foo'));
319 assertTrue(/f(o)\B\1/.test('foo'));
320
321 // Back-reference, ignore case:
322 // ASCII
323 assertEquals("xaAx,a", String(/x(a)\1x/i.exec("xaAx")), "backref-ASCII");
324 assertFalse(/x(...)\1/i.test("xaaaaa"), "backref-ASCII-short");
325 assertTrue(/x((?:))\1\1x/i.test("xx"), "backref-ASCII-empty");
326 assertTrue(/x(?:...|(...))\1x/i.test("xabcx"), "backref-ASCII-uncaptured");
327 assertTrue(/x(?:...|(...))\1x/i.test("xabcABCx"), "backref-ASCII-backtrack");
328 assertEquals("xaBcAbCABCx,aBc",
329              String(/x(...)\1\1x/i.exec("xaBcAbCABCx")),
330              "backref-ASCII-twice");
331
332 for (var i = 0; i < 128; i++) {
333   var testName = "backref-ASCII-char-" + i + "," + (i^0x20);
334   var test = /^(.)\1$/i.test(String.fromCharCode(i, i ^ 0x20))
335   var c = String.fromCharCode(i);
336   if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')) {
337     assertTrue(test, testName);
338   } else {
339     assertFalse(test, testName);
340   }
341 }
342
343 assertFalse(/f(o)$\1/.test('foo'), "backref detects at_end");
344
345 // Check decimal escapes doesn't overflow.
346 // (Note: \214 is interpreted as octal).
347 assertArrayEquals(["\x8c7483648"],
348                   /\2147483648/.exec("\x8c7483648"),
349                   "Overflow decimal escape");
350
351
352 // Check numbers in quantifiers doesn't overflow and doesn't throw on
353 // too large numbers.
354 assertFalse(/a{111111111111111111111111111111111111111111111}/.test('b'),
355             "overlarge1");
356 assertFalse(/a{999999999999999999999999999999999999999999999}/.test('b'),
357             "overlarge2");
358 assertFalse(/a{1,111111111111111111111111111111111111111111111}/.test('b'),
359             "overlarge3");
360 assertFalse(/a{1,999999999999999999999999999999999999999999999}/.test('b'),
361             "overlarge4");
362 assertFalse(/a{2147483648}/.test('b'),
363             "overlarge5");
364 assertFalse(/a{21474836471}/.test('b'),
365             "overlarge6");
366 assertFalse(/a{1,2147483648}/.test('b'),
367             "overlarge7");
368 assertFalse(/a{1,21474836471}/.test('b'),
369             "overlarge8");
370 assertFalse(/a{2147483648,2147483648}/.test('b'),
371             "overlarge9");
372 assertFalse(/a{21474836471,21474836471}/.test('b'),
373             "overlarge10");
374 assertFalse(/a{2147483647}/.test('b'),
375             "overlarge11");
376 assertFalse(/a{1,2147483647}/.test('b'),
377             "overlarge12");
378 assertTrue(/a{1,2147483647}/.test('a'),
379             "overlarge13");
380 assertFalse(/a{2147483647,2147483647}/.test('a'),
381             "overlarge14");
382
383
384 // Check that we don't read past the end of the string.
385 assertFalse(/f/.test('b'));
386 assertFalse(/[abc]f/.test('x'));
387 assertFalse(/[abc]f/.test('xa'));
388 assertFalse(/[abc]</.test('x'));
389 assertFalse(/[abc]</.test('xa'));
390 assertFalse(/f/i.test('b'));
391 assertFalse(/[abc]f/i.test('x'));
392 assertFalse(/[abc]f/i.test('xa'));
393 assertFalse(/[abc]</i.test('x'));
394 assertFalse(/[abc]</i.test('xa'));
395 assertFalse(/f[abc]/.test('x'));
396 assertFalse(/f[abc]/.test('xa'));
397 assertFalse(/<[abc]/.test('x'));
398 assertFalse(/<[abc]/.test('xa'));
399 assertFalse(/f[abc]/i.test('x'));
400 assertFalse(/f[abc]/i.test('xa'));
401 assertFalse(/<[abc]/i.test('x'));
402 assertFalse(/<[abc]/i.test('xa'));
403
404 // Test that merging of quick test masks gets it right.
405 assertFalse(/x([0-7]%%x|[0-6]%%y)/.test('x7%%y'), 'qt');
406 assertFalse(/()x\1(y([0-7]%%%x|[0-6]%%%y)|dkjasldkas)/.test('xy7%%%y'), 'qt2');
407 assertFalse(/()x\1(y([0-7]%%%x|[0-6]%%%y)|dkjasldkas)/.test('xy%%%y'), 'qt3');
408 assertFalse(/()x\1y([0-7]%%%x|[0-6]%%%y)/.test('xy7%%%y'), 'qt4');
409 assertFalse(/()x\1(y([0-7]%%%x|[0-6]%%%y)|dkjasldkas)/.test('xy%%%y'), 'qt5');
410 assertFalse(/()x\1y([0-7]%%%x|[0-6]%%%y)/.test('xy7%%%y'), 'qt6');
411 assertFalse(/xy([0-7]%%%x|[0-6]%%%y)/.test('xy7%%%y'), 'qt7');
412 assertFalse(/x([0-7]%%%x|[0-6]%%%y)/.test('x7%%%y'), 'qt8');
413
414
415 // Don't hang on this one.
416 /[^\xfe-\xff]*/.test("");
417
418
419 var long = "a";
420 for (var i = 0; i < 100000; i++) {
421   long = "a?" + long;
422 }
423 // Don't crash on this one, but maybe throw an exception.
424 try {
425   RegExp(long).exec("a");
426 } catch (e) {
427   assertTrue(String(e).indexOf("Stack overflow") >= 0, "overflow");
428 }
429
430
431 // Test that compile works on modified objects
432 var re = /re+/;
433 assertEquals("re+", re.source);
434 assertFalse(re.global);
435 assertFalse(re.ignoreCase);
436 assertFalse(re.multiline);
437 assertEquals(0, re.lastIndex);
438
439 re.compile("ro+", "gim");
440 assertEquals("ro+", re.source);
441 assertTrue(re.global);
442 assertTrue(re.ignoreCase);
443 assertTrue(re.multiline);
444 assertEquals(0, re.lastIndex);
445
446 re.lastIndex = 42;
447 re.someOtherProperty = 42;
448 re.someDeletableProperty = 42;
449 re[37] = 37;
450 re[42] = 42;
451
452 re.compile("ra+", "i");
453 assertEquals("ra+", re.source);
454 assertFalse(re.global);
455 assertTrue(re.ignoreCase);
456 assertFalse(re.multiline);
457 assertEquals(0, re.lastIndex);
458
459 assertEquals(42, re.someOtherProperty);
460 assertEquals(42, re.someDeletableProperty);
461 assertEquals(37, re[37]);
462 assertEquals(42, re[42]);
463
464 re.lastIndex = -1;
465 re.someOtherProperty = 37;
466 re[42] = 37;
467 assertTrue(delete re[37]);
468 assertTrue(delete re.someDeletableProperty);
469 re.compile("ri+", "gm");
470
471 assertEquals("ri+", re.source);
472 assertTrue(re.global);
473 assertFalse(re.ignoreCase);
474 assertTrue(re.multiline);
475 assertEquals(0, re.lastIndex);
476 assertEquals(37, re.someOtherProperty);
477 assertEquals(37, re[42]);
478
479 // Test boundary-checks.
480 function assertRegExpTest(re, input, test) {
481   assertEquals(test, re.test(input), "test:" + re + ":" + input);
482 }
483
484 assertRegExpTest(/b\b/, "b", true);
485 assertRegExpTest(/b\b$/, "b", true);
486 assertRegExpTest(/\bb/, "b", true);
487 assertRegExpTest(/^\bb/, "b", true);
488 assertRegExpTest(/,\b/, ",", false);
489 assertRegExpTest(/,\b$/, ",", false);
490 assertRegExpTest(/\b,/, ",", false);
491 assertRegExpTest(/^\b,/, ",", false);
492
493 assertRegExpTest(/b\B/, "b", false);
494 assertRegExpTest(/b\B$/, "b", false);
495 assertRegExpTest(/\Bb/, "b", false);
496 assertRegExpTest(/^\Bb/, "b", false);
497 assertRegExpTest(/,\B/, ",", true);
498 assertRegExpTest(/,\B$/, ",", true);
499 assertRegExpTest(/\B,/, ",", true);
500 assertRegExpTest(/^\B,/, ",", true);
501
502 assertRegExpTest(/b\b/, "b,", true);
503 assertRegExpTest(/b\b/, "ba", false);
504 assertRegExpTest(/b\B/, "b,", false);
505 assertRegExpTest(/b\B/, "ba", true);
506
507 assertRegExpTest(/b\Bb/, "bb", true);
508 assertRegExpTest(/b\bb/, "bb", false);
509
510 assertRegExpTest(/b\b[,b]/, "bb", false);
511 assertRegExpTest(/b\B[,b]/, "bb", true);
512 assertRegExpTest(/b\b[,b]/, "b,", true);
513 assertRegExpTest(/b\B[,b]/, "b,", false);
514
515 assertRegExpTest(/[,b]\bb/, "bb", false);
516 assertRegExpTest(/[,b]\Bb/, "bb", true);
517 assertRegExpTest(/[,b]\bb/, ",b", true);
518 assertRegExpTest(/[,b]\Bb/, ",b", false);
519
520 assertRegExpTest(/[,b]\b[,b]/, "bb", false);
521 assertRegExpTest(/[,b]\B[,b]/, "bb", true);
522 assertRegExpTest(/[,b]\b[,b]/, ",b", true);
523 assertRegExpTest(/[,b]\B[,b]/, ",b", false);
524 assertRegExpTest(/[,b]\b[,b]/, "b,", true);
525 assertRegExpTest(/[,b]\B[,b]/, "b,", false);
526
527 // Test that caching of result doesn't share result objects.
528 // More iterations increases the chance of hitting a GC.
529 for (var i = 0; i < 100; i++) {
530   var re = /x(y)z/;
531   var res = re.exec("axyzb");
532   assertTrue(!!res);
533   assertEquals(2, res.length);
534   assertEquals("xyz", res[0]);
535   assertEquals("y", res[1]);
536   assertEquals(1, res.index);
537   assertEquals("axyzb", res.input);
538   assertEquals(undefined, res.foobar);
539
540   res.foobar = "Arglebargle";
541   res[3] = "Glopglyf";
542   assertEquals("Arglebargle", res.foobar);
543 }
544
545 // Test that we perform the spec required conversions in the correct order.
546 var log;
547 var string = "the string";
548 var fakeLastIndex = {
549       valueOf: function() {
550         log.push("li");
551         return 0;
552       }
553     };
554 var fakeString = {
555       toString: function() {
556         log.push("ts");
557         return string;
558       },
559       length: 0
560     };
561
562 var re = /str/;
563 log = [];
564 re.lastIndex = fakeLastIndex;
565 var result = re.exec(fakeString);
566 assertEquals(["str"], result);
567 assertEquals(["ts", "li"], log);
568
569 // Again, to check if caching interferes.
570 log = [];
571 re.lastIndex = fakeLastIndex;
572 result = re.exec(fakeString);
573 assertEquals(["str"], result);
574 assertEquals(["ts", "li"], log);
575
576 // And one more time, just to be certain.
577 log = [];
578 re.lastIndex = fakeLastIndex;
579 result = re.exec(fakeString);
580 assertEquals(["str"], result);
581 assertEquals(["ts", "li"], log);
582
583 // Now with a global regexp, where lastIndex is actually used.
584 re = /str/g;
585 log = [];
586 re.lastIndex = fakeLastIndex;
587 var result = re.exec(fakeString);
588 assertEquals(["str"], result);
589 assertEquals(["ts", "li"], log);
590
591 // Again, to check if caching interferes.
592 log = [];
593 re.lastIndex = fakeLastIndex;
594 result = re.exec(fakeString);
595 assertEquals(["str"], result);
596 assertEquals(["ts", "li"], log);
597
598 // And one more time, just to be certain.
599 log = [];
600 re.lastIndex = fakeLastIndex;
601 result = re.exec(fakeString);
602 assertEquals(["str"], result);
603 assertEquals(["ts", "li"], log);
604
605
606 // Check that properties of RegExp have the correct permissions.
607 var re = /x/g;
608 var desc = Object.getOwnPropertyDescriptor(re, "global");
609 assertEquals(true, desc.value);
610 assertEquals(false, desc.configurable);
611 assertEquals(false, desc.enumerable);
612 assertEquals(false, desc.writable);
613
614 desc = Object.getOwnPropertyDescriptor(re, "multiline");
615 assertEquals(false, desc.value);
616 assertEquals(false, desc.configurable);
617 assertEquals(false, desc.enumerable);
618 assertEquals(false, desc.writable);
619
620 desc = Object.getOwnPropertyDescriptor(re, "ignoreCase");
621 assertEquals(false, desc.value);
622 assertEquals(false, desc.configurable);
623 assertEquals(false, desc.enumerable);
624 assertEquals(false, desc.writable);
625
626 desc = Object.getOwnPropertyDescriptor(re, "lastIndex");
627 assertEquals(0, desc.value);
628 assertEquals(false, desc.configurable);
629 assertEquals(false, desc.enumerable);
630 assertEquals(true, desc.writable);
631
632
633 // Check that end-anchored regexps are optimized correctly.
634 var re = /(?:a|bc)g$/;
635 assertTrue(re.test("ag"));
636 assertTrue(re.test("bcg"));
637 assertTrue(re.test("abcg"));
638 assertTrue(re.test("zimbag"));
639 assertTrue(re.test("zimbcg"));
640
641 assertFalse(re.test("g"));
642 assertFalse(re.test(""));
643
644 // Global regexp (non-zero start).
645 var re = /(?:a|bc)g$/g;
646 assertTrue(re.test("ag"));
647 re.lastIndex = 1;  // Near start of string.
648 assertTrue(re.test("zimbag"));
649 re.lastIndex = 6;  // At end of string.
650 assertFalse(re.test("zimbag"));
651 re.lastIndex = 5;  // Near end of string.
652 assertFalse(re.test("zimbag"));
653 re.lastIndex = 4;
654 assertTrue(re.test("zimbag"));
655
656 // Anchored at both ends.
657 var re = /^(?:a|bc)g$/g;
658 assertTrue(re.test("ag"));
659 re.lastIndex = 1;
660 assertFalse(re.test("ag"));
661 re.lastIndex = 1;
662 assertFalse(re.test("zag"));
663
664 // Long max_length of RegExp.
665 var re = /VeryLongRegExp!{1,1000}$/;
666 assertTrue(re.test("BahoolaVeryLongRegExp!!!!!!"));
667 assertFalse(re.test("VeryLongRegExp"));
668 assertFalse(re.test("!"));
669
670 // End anchor inside disjunction.
671 var re = /(?:a$|bc$)/;
672 assertTrue(re.test("a"));
673 assertTrue(re.test("bc"));
674 assertTrue(re.test("abc"));
675 assertTrue(re.test("zimzamzumba"));
676 assertTrue(re.test("zimzamzumbc"));
677 assertFalse(re.test("c"));
678 assertFalse(re.test(""));
679
680 // Only partially anchored.
681 var re = /(?:a|bc$)/;
682 assertTrue(re.test("a"));
683 assertTrue(re.test("bc"));
684 assertEquals(["a"], re.exec("abc"));
685 assertEquals(4, re.exec("zimzamzumba").index);
686 assertEquals(["bc"], re.exec("zimzomzumbc"));
687 assertFalse(re.test("c"));
688 assertFalse(re.test(""));
689
690 // Valid syntax in ES5.
691 re = RegExp("(?:x)*");
692 re = RegExp("(x)*");
693
694 // Syntax extension relative to ES5, for matching JSC (and ES3).
695 // Shouldn't throw.
696 re = RegExp("(?=x)*");
697 re = RegExp("(?!x)*");
698
699 // Should throw. Shouldn't hit asserts in debug mode.
700 assertThrows("RegExp('(*)')");
701 assertThrows("RegExp('(?:*)')");
702 assertThrows("RegExp('(?=*)')");
703 assertThrows("RegExp('(?!*)')");
704
705 // Test trimmed regular expression for RegExp.test().
706 assertTrue(/.*abc/.test("abc"));
707 assertFalse(/.*\d+/.test("q"));
708
709 // Test that RegExp.prototype.toString() throws TypeError for
710 // incompatible receivers (ES5 section 15.10.6 and 15.10.6.4).
711 assertThrows("RegExp.prototype.toString.call(null)", TypeError);
712 assertThrows("RegExp.prototype.toString.call(0)", TypeError);
713 assertThrows("RegExp.prototype.toString.call('')", TypeError);
714 assertThrows("RegExp.prototype.toString.call(false)", TypeError);
715 assertThrows("RegExp.prototype.toString.call(true)", TypeError);
716 assertThrows("RegExp.prototype.toString.call([])", TypeError);
717 assertThrows("RegExp.prototype.toString.call({})", TypeError);
718 assertThrows("RegExp.prototype.toString.call(function(){})", TypeError);