Home | History | Annotate | Download | only in mjsunit
      1 // Copyright 2008 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 inside some bizarre
    131 // character classes.
    132 re = /[\s-:]/;
    133 assertTrue(re.test('-'));
    134 assertTrue(re.test(':'));
    135 assertTrue(re.test(' '));
    136 assertTrue(re.test('\t'));
    137 assertTrue(re.test('\n'));
    138 assertFalse(re.test('a'));
    139 assertFalse(re.test('Z'));
    140 
    141 re = /[\S-:]/;
    142 assertTrue(re.test('-'));
    143 assertTrue(re.test(':'));
    144 assertFalse(re.test(' '));
    145 assertFalse(re.test('\t'));
    146 assertFalse(re.test('\n'));
    147 assertTrue(re.test('a'));
    148 assertTrue(re.test('Z'));
    149 
    150 re = /[^\s-:]/;
    151 assertFalse(re.test('-'));
    152 assertFalse(re.test(':'));
    153 assertFalse(re.test(' '));
    154 assertFalse(re.test('\t'));
    155 assertFalse(re.test('\n'));
    156 assertTrue(re.test('a'));
    157 assertTrue(re.test('Z'));
    158 
    159 re = /[^\S-:]/;
    160 assertFalse(re.test('-'));
    161 assertFalse(re.test(':'));
    162 assertTrue(re.test(' '));
    163 assertTrue(re.test('\t'));
    164 assertTrue(re.test('\n'));
    165 assertFalse(re.test('a'));
    166 assertFalse(re.test('Z'));
    167 
    168 re = /[\s]/;
    169 assertFalse(re.test('-'));
    170 assertFalse(re.test(':'));
    171 assertTrue(re.test(' '));
    172 assertTrue(re.test('\t'));
    173 assertTrue(re.test('\n'));
    174 assertFalse(re.test('a'));
    175 assertFalse(re.test('Z'));
    176 
    177 re = /[^\s]/;
    178 assertTrue(re.test('-'));
    179 assertTrue(re.test(':'));
    180 assertFalse(re.test(' '));
    181 assertFalse(re.test('\t'));
    182 assertFalse(re.test('\n'));
    183 assertTrue(re.test('a'));
    184 assertTrue(re.test('Z'));
    185 
    186 re = /[\S]/;
    187 assertTrue(re.test('-'));
    188 assertTrue(re.test(':'));
    189 assertFalse(re.test(' '));
    190 assertFalse(re.test('\t'));
    191 assertFalse(re.test('\n'));
    192 assertTrue(re.test('a'));
    193 assertTrue(re.test('Z'));
    194 
    195 re = /[^\S]/;
    196 assertFalse(re.test('-'));
    197 assertFalse(re.test(':'));
    198 assertTrue(re.test(' '));
    199 assertTrue(re.test('\t'));
    200 assertTrue(re.test('\n'));
    201 assertFalse(re.test('a'));
    202 assertFalse(re.test('Z'));
    203 
    204 re = /[\s\S]/;
    205 assertTrue(re.test('-'));
    206 assertTrue(re.test(':'));
    207 assertTrue(re.test(' '));
    208 assertTrue(re.test('\t'));
    209 assertTrue(re.test('\n'));
    210 assertTrue(re.test('a'));
    211 assertTrue(re.test('Z'));
    212 
    213 re = /[^\s\S]/;
    214 assertFalse(re.test('-'));
    215 assertFalse(re.test(':'));
    216 assertFalse(re.test(' '));
    217 assertFalse(re.test('\t'));
    218 assertFalse(re.test('\n'));
    219 assertFalse(re.test('a'));
    220 assertFalse(re.test('Z'));
    221 
    222 // First - is treated as range operator, second as literal minus.
    223 // This follows the specification in parsing, but doesn't throw on
    224 // the \s at the beginning of the range.
    225 re = /[\s-0-9]/;
    226 assertTrue(re.test(' '));
    227 assertTrue(re.test('\xA0'));
    228 assertTrue(re.test('-'));
    229 assertTrue(re.test('0'));
    230 assertTrue(re.test('9'));
    231 assertFalse(re.test('1'));
    232 
    233 // Test beginning and end of line assertions with or without the
    234 // multiline flag.
    235 re = /^\d+/;
    236 assertFalse(re.test("asdf\n123"));
    237 re = /^\d+/m;
    238 assertTrue(re.test("asdf\n123"));
    239 
    240 re = /\d+$/;
    241 assertFalse(re.test("123\nasdf"));
    242 re = /\d+$/m;
    243 assertTrue(re.test("123\nasdf"));
    244 
    245 // Test that empty matches are handled correctly for multiline global
    246 // regexps.
    247 re = /^(.*)/mg;
    248 assertEquals(3, "a\n\rb".match(re).length);
    249 assertEquals("*a\n*b\r*c\n*\r*d\r*\n*e", "a\nb\rc\n\rd\r\ne".replace(re, "*$1"));
    250 
    251 // Test that empty matches advance one character
    252 re = new RegExp("", "g");
    253 assertEquals("xAx", "A".replace(re, "x"));
    254 assertEquals(3, String.fromCharCode(161).replace(re, "x").length);
    255 
    256 // Test that we match the KJS behavior with regard to undefined constructor
    257 // arguments:
    258 re = new RegExp();
    259 // KJS actually shows this as '//'.  Here we match the Firefox behavior (ie,
    260 // giving a syntactically legal regexp literal).
    261 assertEquals('/(?:)/', re.toString());
    262 re = new RegExp(void 0);
    263 assertEquals('/(?:)/', re.toString());
    264 re.compile();
    265 assertEquals('/(?:)/', re.toString());
    266 re.compile(void 0);
    267 assertEquals('/undefined/', re.toString());
    268 
    269 
    270 // Check for lazy RegExp literal creation
    271 function lazyLiteral(doit) {
    272   if (doit) return "".replace(/foo(/gi, "");
    273   return true;
    274 }
    275 
    276 assertTrue(lazyLiteral(false));
    277 assertThrows("lazyLiteral(true)");
    278 
    279 // Check $01 and $10
    280 re = new RegExp("(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)");
    281 assertEquals("t", "123456789t".replace(re, "$10"), "$10");
    282 assertEquals("15", "123456789t".replace(re, "$15"), "$10");
    283 assertEquals("1", "123456789t".replace(re, "$01"), "$01");
    284 assertEquals("$001", "123456789t".replace(re, "$001"), "$001");
    285 re = new RegExp("foo(.)");
    286 assertEquals("bar$0", "foox".replace(re, "bar$0"), "$0");
    287 assertEquals("bar$00", "foox".replace(re, "bar$00"), "$00");
    288 assertEquals("bar$000", "foox".replace(re, "bar$000"), "$000");
    289 assertEquals("barx", "foox".replace(re, "bar$01"), "$01 2");
    290 assertEquals("barx5", "foox".replace(re, "bar$15"), "$15");
    291 
    292 assertFalse(/()foo$\1/.test("football"), "football1");
    293 assertFalse(/foo$(?=ball)/.test("football"), "football2");
    294 assertFalse(/foo$(?!bar)/.test("football"), "football3");
    295 assertTrue(/()foo$\1/.test("foo"), "football4");
    296 assertTrue(/foo$(?=(ball)?)/.test("foo"), "football5");
    297 assertTrue(/()foo$(?!bar)/.test("foo"), "football6");
    298 assertFalse(/(x?)foo$\1/.test("football"), "football7");
    299 assertFalse(/foo$(?=ball)/.test("football"), "football8");
    300 assertFalse(/foo$(?!bar)/.test("football"), "football9");
    301 assertTrue(/(x?)foo$\1/.test("foo"), "football10");
    302 assertTrue(/foo$(?=(ball)?)/.test("foo"), "football11");
    303 assertTrue(/foo$(?!bar)/.test("foo"), "football12");
    304 
    305 // Check that the back reference has two successors.  See
    306 // BackReferenceNode::PropagateForward.
    307 assertFalse(/f(o)\b\1/.test('foo'));
    308 assertTrue(/f(o)\B\1/.test('foo'));
    309 
    310 // Back-reference, ignore case:
    311 // ASCII
    312 assertEquals("xaAx,a", String(/x(a)\1x/i.exec("xaAx")), "backref-ASCII");
    313 assertFalse(/x(...)\1/i.test("xaaaaa"), "backref-ASCII-short");
    314 assertTrue(/x((?:))\1\1x/i.test("xx"), "backref-ASCII-empty");
    315 assertTrue(/x(?:...|(...))\1x/i.test("xabcx"), "backref-ASCII-uncaptured");
    316 assertTrue(/x(?:...|(...))\1x/i.test("xabcABCx"), "backref-ASCII-backtrack");
    317 assertEquals("xaBcAbCABCx,aBc",
    318              String(/x(...)\1\1x/i.exec("xaBcAbCABCx")),
    319              "backref-ASCII-twice");
    320 
    321 for (var i = 0; i < 128; i++) {
    322   var testName = "backref-ASCII-char-" + i + "," + (i^0x20);
    323   var test = /^(.)\1$/i.test(String.fromCharCode(i, i ^ 0x20))
    324   var c = String.fromCharCode(i);
    325   if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')) {
    326     assertTrue(test, testName);
    327   } else {
    328     assertFalse(test, testName);
    329   }
    330 }
    331 
    332 assertFalse(/f(o)$\1/.test('foo'), "backref detects at_end");
    333 
    334 // Check decimal escapes doesn't overflow.
    335 // (Note: \214 is interpreted as octal).
    336 assertEquals(/\2147483648/.exec("\x8c7483648"),
    337              ["\x8c7483648"],
    338              "Overflow decimal escape");
    339 
    340 
    341 // Check numbers in quantifiers doesn't overflow and doesn't throw on
    342 // too large numbers.
    343 assertFalse(/a{111111111111111111111111111111111111111111111}/.test('b'),
    344             "overlarge1");
    345 assertFalse(/a{999999999999999999999999999999999999999999999}/.test('b'),
    346             "overlarge2");
    347 assertFalse(/a{1,111111111111111111111111111111111111111111111}/.test('b'),
    348             "overlarge3");
    349 assertFalse(/a{1,999999999999999999999999999999999999999999999}/.test('b'),
    350             "overlarge4");
    351 assertFalse(/a{2147483648}/.test('b'),
    352             "overlarge5");
    353 assertFalse(/a{21474836471}/.test('b'),
    354             "overlarge6");
    355 assertFalse(/a{1,2147483648}/.test('b'),
    356             "overlarge7");
    357 assertFalse(/a{1,21474836471}/.test('b'),
    358             "overlarge8");
    359 assertFalse(/a{2147483648,2147483648}/.test('b'),
    360             "overlarge9");
    361 assertFalse(/a{21474836471,21474836471}/.test('b'),
    362             "overlarge10");
    363 assertFalse(/a{2147483647}/.test('b'),
    364             "overlarge11");
    365 assertFalse(/a{1,2147483647}/.test('b'),
    366             "overlarge12");
    367 assertTrue(/a{1,2147483647}/.test('a'),
    368             "overlarge13");
    369 assertFalse(/a{2147483647,2147483647}/.test('a'),
    370             "overlarge14");
    371 
    372 
    373 // Check that we don't read past the end of the string.
    374 assertFalse(/f/.test('b'));
    375 assertFalse(/[abc]f/.test('x'));
    376 assertFalse(/[abc]f/.test('xa'));
    377 assertFalse(/[abc]</.test('x'));
    378 assertFalse(/[abc]</.test('xa'));
    379 assertFalse(/f/i.test('b'));
    380 assertFalse(/[abc]f/i.test('x'));
    381 assertFalse(/[abc]f/i.test('xa'));
    382 assertFalse(/[abc]</i.test('x'));
    383 assertFalse(/[abc]</i.test('xa'));
    384 assertFalse(/f[abc]/.test('x'));
    385 assertFalse(/f[abc]/.test('xa'));
    386 assertFalse(/<[abc]/.test('x'));
    387 assertFalse(/<[abc]/.test('xa'));
    388 assertFalse(/f[abc]/i.test('x'));
    389 assertFalse(/f[abc]/i.test('xa'));
    390 assertFalse(/<[abc]/i.test('x'));
    391 assertFalse(/<[abc]/i.test('xa'));
    392 
    393 // Test that merging of quick test masks gets it right.
    394 assertFalse(/x([0-7]%%x|[0-6]%%y)/.test('x7%%y'), 'qt');
    395 assertFalse(/()x\1(y([0-7]%%%x|[0-6]%%%y)|dkjasldkas)/.test('xy7%%%y'), 'qt2');
    396 assertFalse(/()x\1(y([0-7]%%%x|[0-6]%%%y)|dkjasldkas)/.test('xy%%%y'), 'qt3');
    397 assertFalse(/()x\1y([0-7]%%%x|[0-6]%%%y)/.test('xy7%%%y'), 'qt4');
    398 assertFalse(/()x\1(y([0-7]%%%x|[0-6]%%%y)|dkjasldkas)/.test('xy%%%y'), 'qt5');
    399 assertFalse(/()x\1y([0-7]%%%x|[0-6]%%%y)/.test('xy7%%%y'), 'qt6');
    400 assertFalse(/xy([0-7]%%%x|[0-6]%%%y)/.test('xy7%%%y'), 'qt7');
    401 assertFalse(/x([0-7]%%%x|[0-6]%%%y)/.test('x7%%%y'), 'qt8');
    402 
    403 
    404 // Don't hang on this one.
    405 /[^\xfe-\xff]*/.test("");
    406 
    407 
    408 var long = "a";
    409 for (var i = 0; i < 100000; i++) {
    410   long = "a?" + long;
    411 }
    412 // Don't crash on this one, but maybe throw an exception.
    413 try {
    414   RegExp(long).exec("a");
    415 } catch (e) {
    416   assertTrue(String(e).indexOf("Stack overflow") >= 0, "overflow");
    417 }
    418 
    419 
    420 // Test that compile works on modified objects
    421 var re = /re+/;
    422 assertEquals("re+", re.source);
    423 assertFalse(re.global);
    424 assertFalse(re.ignoreCase);
    425 assertFalse(re.multiline);
    426 assertEquals(0, re.lastIndex);
    427 
    428 re.compile("ro+", "gim");
    429 assertEquals("ro+", re.source);
    430 assertTrue(re.global);
    431 assertTrue(re.ignoreCase);
    432 assertTrue(re.multiline);
    433 assertEquals(0, re.lastIndex);
    434 
    435 re.lastIndex = 42;
    436 re.someOtherProperty = 42;
    437 re.someDeletableProperty = 42;
    438 re[37] = 37;  
    439 re[42] = 42;  
    440 
    441 re.compile("ra+", "i");
    442 assertEquals("ra+", re.source);
    443 assertFalse(re.global);
    444 assertTrue(re.ignoreCase);
    445 assertFalse(re.multiline);
    446 assertEquals(0, re.lastIndex);
    447 
    448 assertEquals(42, re.someOtherProperty);
    449 assertEquals(42, re.someDeletableProperty);
    450 assertEquals(37, re[37]);
    451 assertEquals(42, re[42]);
    452 
    453 re.lastIndex = -1;
    454 re.someOtherProperty = 37;
    455 re[42] = 37;
    456 assertTrue(delete re[37]);
    457 assertTrue(delete re.someDeletableProperty);
    458 re.compile("ri+", "gm");
    459 
    460 assertEquals("ri+", re.source);
    461 assertTrue(re.global);
    462 assertFalse(re.ignoreCase);
    463 assertTrue(re.multiline);
    464 assertEquals(0, re.lastIndex);
    465 assertEquals(37, re.someOtherProperty);
    466 assertEquals(37, re[42]);
    467 
    468 // Test boundary-checks.
    469 function assertRegExpTest(re, input, test) { 
    470   assertEquals(test, re.test(input), "test:" + re + ":" + input);
    471 }
    472 
    473 assertRegExpTest(/b\b/, "b", true);
    474 assertRegExpTest(/b\b$/, "b", true);
    475 assertRegExpTest(/\bb/, "b", true);
    476 assertRegExpTest(/^\bb/, "b", true);
    477 assertRegExpTest(/,\b/, ",", false);
    478 assertRegExpTest(/,\b$/, ",", false);
    479 assertRegExpTest(/\b,/, ",", false);
    480 assertRegExpTest(/^\b,/, ",", false);
    481 
    482 assertRegExpTest(/b\B/, "b", false);
    483 assertRegExpTest(/b\B$/, "b", false);
    484 assertRegExpTest(/\Bb/, "b", false);
    485 assertRegExpTest(/^\Bb/, "b", false);
    486 assertRegExpTest(/,\B/, ",", true);
    487 assertRegExpTest(/,\B$/, ",", true);
    488 assertRegExpTest(/\B,/, ",", true);
    489 assertRegExpTest(/^\B,/, ",", true);
    490 
    491 assertRegExpTest(/b\b/, "b,", true);
    492 assertRegExpTest(/b\b/, "ba", false);
    493 assertRegExpTest(/b\B/, "b,", false);
    494 assertRegExpTest(/b\B/, "ba", true);
    495 
    496 assertRegExpTest(/b\Bb/, "bb", true);
    497 assertRegExpTest(/b\bb/, "bb", false);
    498 
    499 assertRegExpTest(/b\b[,b]/, "bb", false);
    500 assertRegExpTest(/b\B[,b]/, "bb", true);
    501 assertRegExpTest(/b\b[,b]/, "b,", true);
    502 assertRegExpTest(/b\B[,b]/, "b,", false);
    503 
    504 assertRegExpTest(/[,b]\bb/, "bb", false);
    505 assertRegExpTest(/[,b]\Bb/, "bb", true);
    506 assertRegExpTest(/[,b]\bb/, ",b", true);
    507 assertRegExpTest(/[,b]\Bb/, ",b", false);
    508 
    509 assertRegExpTest(/[,b]\b[,b]/, "bb", false);
    510 assertRegExpTest(/[,b]\B[,b]/, "bb", true);
    511 assertRegExpTest(/[,b]\b[,b]/, ",b", true);
    512 assertRegExpTest(/[,b]\B[,b]/, ",b", false);
    513 assertRegExpTest(/[,b]\b[,b]/, "b,", true);
    514 assertRegExpTest(/[,b]\B[,b]/, "b,", false);
    515 
    516 // Test that caching of result doesn't share result objects.
    517 // More iterations increases the chance of hitting a GC.
    518 for (var i = 0; i < 100; i++) {
    519   var re = /x(y)z/;
    520   var res = re.exec("axyzb");
    521   assertTrue(!!res);
    522   assertEquals(2, res.length);
    523   assertEquals("xyz", res[0]);
    524   assertEquals("y", res[1]);
    525   assertEquals(1, res.index);
    526   assertEquals("axyzb", res.input);
    527   assertEquals(undefined, res.foobar);
    528   
    529   res.foobar = "Arglebargle";
    530   res[3] = "Glopglyf";
    531   assertEquals("Arglebargle", res.foobar);
    532 }
    533 
    534 // Test that we perform the spec required conversions in the correct order.
    535 var log;
    536 var string = "the string";
    537 var fakeLastIndex = { 
    538       valueOf: function() { 
    539         log.push("li");
    540         return 0;
    541       } 
    542     };
    543 var fakeString = { 
    544       toString: function() {
    545         log.push("ts");
    546         return string;
    547       }, 
    548       length: 0 
    549     };
    550 
    551 var re = /str/;
    552 log = [];
    553 re.lastIndex = fakeLastIndex;
    554 var result = re.exec(fakeString);
    555 assertEquals(["str"], result);
    556 assertEquals(["ts", "li"], log);
    557 
    558 // Again, to check if caching interferes.
    559 log = [];
    560 re.lastIndex = fakeLastIndex;
    561 result = re.exec(fakeString);
    562 assertEquals(["str"], result);
    563 assertEquals(["ts", "li"], log);
    564 
    565 // And one more time, just to be certain.
    566 log = [];
    567 re.lastIndex = fakeLastIndex;
    568 result = re.exec(fakeString);
    569 assertEquals(["str"], result);
    570 assertEquals(["ts", "li"], log);
    571 
    572 // Now with a global regexp, where lastIndex is actually used.
    573 re = /str/g;
    574 log = [];
    575 re.lastIndex = fakeLastIndex;
    576 var result = re.exec(fakeString);
    577 assertEquals(["str"], result);
    578 assertEquals(["ts", "li"], log);
    579 
    580 // Again, to check if caching interferes.
    581 log = [];
    582 re.lastIndex = fakeLastIndex;
    583 result = re.exec(fakeString);
    584 assertEquals(["str"], result);
    585 assertEquals(["ts", "li"], log);
    586 
    587 // And one more time, just to be certain.
    588 log = [];
    589 re.lastIndex = fakeLastIndex;
    590 result = re.exec(fakeString);
    591 assertEquals(["str"], result);
    592 assertEquals(["ts", "li"], log);
    593 
    594 
    595 // Check that properties of RegExp have the correct permissions.
    596 var re = /x/g;
    597 var desc = Object.getOwnPropertyDescriptor(re, "global");
    598 assertEquals(true, desc.value);
    599 assertEquals(false, desc.configurable);
    600 assertEquals(false, desc.enumerable);
    601 assertEquals(false, desc.writable);
    602 
    603 desc = Object.getOwnPropertyDescriptor(re, "multiline");
    604 assertEquals(false, desc.value);
    605 assertEquals(false, desc.configurable);
    606 assertEquals(false, desc.enumerable);
    607 assertEquals(false, desc.writable);
    608 
    609 desc = Object.getOwnPropertyDescriptor(re, "ignoreCase");
    610 assertEquals(false, desc.value);
    611 assertEquals(false, desc.configurable);
    612 assertEquals(false, desc.enumerable);
    613 assertEquals(false, desc.writable);
    614 
    615 desc = Object.getOwnPropertyDescriptor(re, "lastIndex");
    616 assertEquals(0, desc.value);
    617 assertEquals(false, desc.configurable);
    618 assertEquals(false, desc.enumerable);
    619 assertEquals(true, desc.writable);
    620 
    621 
    622 // Check that end-anchored regexps are optimized correctly.
    623 var re = /(?:a|bc)g$/;
    624 assertTrue(re.test("ag"));
    625 assertTrue(re.test("bcg"));
    626 assertTrue(re.test("abcg"));
    627 assertTrue(re.test("zimbag"));
    628 assertTrue(re.test("zimbcg"));
    629 
    630 assertFalse(re.test("g"));
    631 assertFalse(re.test(""));
    632 
    633 // Global regexp (non-zero start).
    634 var re = /(?:a|bc)g$/g;
    635 assertTrue(re.test("ag"));
    636 re.lastIndex = 1;  // Near start of string.
    637 assertTrue(re.test("zimbag"));
    638 re.lastIndex = 6;  // At end of string.
    639 assertFalse(re.test("zimbag"));
    640 re.lastIndex = 5;  // Near end of string.
    641 assertFalse(re.test("zimbag"));
    642 re.lastIndex = 4;
    643 assertTrue(re.test("zimbag"));
    644 
    645 // Anchored at both ends.
    646 var re = /^(?:a|bc)g$/g;
    647 assertTrue(re.test("ag"));
    648 re.lastIndex = 1;
    649 assertFalse(re.test("ag"));
    650 re.lastIndex = 1;
    651 assertFalse(re.test("zag"));
    652 
    653 // Long max_length of RegExp.
    654 var re = /VeryLongRegExp!{1,1000}$/;
    655 assertTrue(re.test("BahoolaVeryLongRegExp!!!!!!"));
    656 assertFalse(re.test("VeryLongRegExp"));
    657 assertFalse(re.test("!"));
    658 
    659 // End anchor inside disjunction.
    660 var re = /(?:a$|bc$)/;
    661 assertTrue(re.test("a"));
    662 assertTrue(re.test("bc"));
    663 assertTrue(re.test("abc"));
    664 assertTrue(re.test("zimzamzumba"));
    665 assertTrue(re.test("zimzamzumbc"));
    666 assertFalse(re.test("c"));
    667 assertFalse(re.test(""));
    668 
    669 // Only partially anchored.
    670 var re = /(?:a|bc$)/;
    671 assertTrue(re.test("a"));
    672 assertTrue(re.test("bc"));
    673 assertEquals(["a"], re.exec("abc"));
    674 assertEquals(4, re.exec("zimzamzumba").index);
    675 assertEquals(["bc"], re.exec("zimzomzumbc"));
    676 assertFalse(re.test("c"));
    677 assertFalse(re.test(""));
    678 
    679 // Valid syntax in ES5.
    680 re = RegExp("(?:x)*");
    681 re = RegExp("(x)*");
    682 
    683 // Syntax extension relative to ES5, for matching JSC (and ES3).
    684 // Shouldn't throw.
    685 re = RegExp("(?=x)*");
    686 re = RegExp("(?!x)*");
    687 
    688 // Should throw. Shouldn't hit asserts in debug mode.
    689 assertThrows("RegExp('(*)')");
    690 assertThrows("RegExp('(?:*)')");
    691 assertThrows("RegExp('(?=*)')");
    692 assertThrows("RegExp('(?!*)')");
    693