Home | History | Annotate | Download | only in mjsunit
      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);
    719