OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 import "package:expect/expect.dart"; |
| 6 |
| 7 void testEscape(str, regex) { |
| 8 assertEquals("foo:bar:baz", str.split(regex).join(":")); |
| 9 } |
| 10 |
| 11 void assertEquals(actual, expected, [message]) => |
| 12 Expect.equals(actual, expected, message); |
| 13 void assertTrue(actual, [message]) => Expect.isTrue(actual, message); |
| 14 void assertFalse(actual, [message]) => Expect.isFalse(actual, message); |
| 15 void assertThrows(fn) => Expect.throws(fn); |
| 16 |
| 17 void main() { |
| 18 // Ensure we hit the optimizer. |
| 19 for (int i = 0; i < 50; i++) { |
| 20 testEscape("foo\nbar\nbaz", new RegExp(r"\n")); |
| 21 testEscape("foo bar baz", new RegExp(r"\s")); |
| 22 testEscape("foo\tbar\tbaz", new RegExp(r"\s")); |
| 23 testEscape("foo-bar-baz", new RegExp(r"\u002D")); |
| 24 |
| 25 // Test containing null char in regexp. |
| 26 var s = '[' + new String.fromCharCode(0) + ']'; |
| 27 var re = new RegExp(s); |
| 28 assertEquals(re.allMatches(s).length, 1); |
| 29 assertEquals(re.stringMatch(s), new String.fromCharCode(0)); |
| 30 |
| 31 |
| 32 final _vmFrame = new RegExp( |
| 33 r'^#\d+\s+(\S.*) \((.+?):(\d+)(?::(\d+))?\)$'); |
| 34 final _traceLine = |
| 35 "#0 Trace.Trace.parse (package:stack_trace/src/trace.dart:130:7)"; |
| 36 Expect.equals(_vmFrame.firstMatch(_traceLine).group(0), _traceLine); |
| 37 |
| 38 // Test the UTF16 case insensitive comparison. |
| 39 re = new RegExp(r"x(a)\1x", caseSensitive: false); |
| 40 Expect.equals(re.firstMatch("xaAx\u1234").group(0), "xaAx"); |
| 41 |
| 42 // Test strings containing all line separators |
| 43 s = 'aA\nbB\rcC\r\ndD\u2028eE\u2029fF'; |
| 44 // any non-newline character at the beginning of a line |
| 45 re = new RegExp(r"^.", multiLine: true); |
| 46 var result = re.allMatches(s).toList(); |
| 47 assertEquals(result.length, 6); |
| 48 assertEquals(result[0][0], 'a'); |
| 49 assertEquals(result[1][0], 'b'); |
| 50 assertEquals(result[2][0], 'c'); |
| 51 assertEquals(result[3][0], 'd'); |
| 52 assertEquals(result[4][0], 'e'); |
| 53 assertEquals(result[5][0], 'f'); |
| 54 |
| 55 // any non-newline character at the end of a line |
| 56 re = new RegExp(r".$", multiLine: true); |
| 57 result = re.allMatches(s).toList(); |
| 58 assertEquals(result.length, 6); |
| 59 assertEquals(result[0][0], 'A'); |
| 60 assertEquals(result[1][0], 'B'); |
| 61 assertEquals(result[2][0], 'C'); |
| 62 assertEquals(result[3][0], 'D'); |
| 63 assertEquals(result[4][0], 'E'); |
| 64 assertEquals(result[5][0], 'F'); |
| 65 |
| 66 // *any* character at the beginning of a line |
| 67 re = new RegExp(r"^[^]", multiLine: true); |
| 68 result = re.allMatches(s).toList(); |
| 69 assertEquals(result.length, 7); |
| 70 assertEquals(result[0][0], 'a'); |
| 71 assertEquals(result[1][0], 'b'); |
| 72 assertEquals(result[2][0], 'c'); |
| 73 assertEquals(result[3][0], '\n'); |
| 74 assertEquals(result[4][0], 'd'); |
| 75 assertEquals(result[5][0], 'e'); |
| 76 assertEquals(result[6][0], 'f'); |
| 77 |
| 78 // *any* character at the end of a line |
| 79 re = new RegExp(r"[^]$", multiLine: true); |
| 80 result = re.allMatches(s).toList(); |
| 81 assertEquals(result.length, 7); |
| 82 assertEquals(result[0][0], 'A'); |
| 83 assertEquals(result[1][0], 'B'); |
| 84 assertEquals(result[2][0], 'C'); |
| 85 assertEquals(result[3][0], '\r'); |
| 86 assertEquals(result[4][0], 'D'); |
| 87 assertEquals(result[5][0], 'E'); |
| 88 assertEquals(result[6][0], 'F'); |
| 89 |
| 90 // Some tests from the Mozilla tests, where our behavior used to differ from |
| 91 // SpiderMonkey. |
| 92 // From ecma_3/RegExp/regress-334158.js |
| 93 assertTrue( "\x01" .contains(new RegExp(r"\ca"))); |
| 94 assertFalse( "\\ca" .contains(new RegExp(r"\ca"))); |
| 95 assertFalse( "ca" .contains(new RegExp(r"\ca"))); |
| 96 assertTrue( "\\ca" .contains(new RegExp(r"\c[a/]"))); |
| 97 assertTrue( "\\c/" .contains(new RegExp(r"\c[a/]"))); |
| 98 |
| 99 // Test \c in character class |
| 100 re = r"^[\cM]$"; |
| 101 assertTrue("\r".contains(new RegExp(re))); |
| 102 assertFalse("M".contains(new RegExp(re))); |
| 103 assertFalse("c".contains(new RegExp(re))); |
| 104 assertFalse("\\".contains(new RegExp(re))); |
| 105 assertFalse("\x03".contains(new RegExp(re))); // I.e., read as \cc |
| 106 |
| 107 re = r"^[\c]]$"; |
| 108 assertTrue("c]".contains(new RegExp(re))); |
| 109 assertTrue("\\]".contains(new RegExp(re))); |
| 110 assertFalse("\x1d".contains(new RegExp(re))); // ']' & 0x1f |
| 111 assertFalse("\x03]".contains(new RegExp(re))); // I.e., read as \cc |
| 112 |
| 113 re = r"^[\c1]$"; // Digit control characters are masked in character classe
s. |
| 114 assertTrue("\x11".contains(new RegExp(re))); |
| 115 assertFalse("\\".contains(new RegExp(re))); |
| 116 assertFalse("c".contains(new RegExp(re))); |
| 117 assertFalse("1".contains(new RegExp(re))); |
| 118 |
| 119 // Underscore control character is masked in character classes. |
| 120 re = r"^[\c_]$"; |
| 121 assertTrue("\x1f".contains(new RegExp(re))); |
| 122 assertFalse("\\".contains(new RegExp(re))); |
| 123 assertFalse("c".contains(new RegExp(re))); |
| 124 assertFalse("_".contains(new RegExp(re))); |
| 125 |
| 126 re = r"^[\c$]$"; // Other characters are interpreted literally. |
| 127 assertFalse("\x04".contains(new RegExp(re))); |
| 128 assertTrue("\\".contains(new RegExp(re))); |
| 129 assertTrue("c".contains(new RegExp(re))); |
| 130 assertTrue(r"$".contains(new RegExp(re))); |
| 131 |
| 132 assertTrue("Z[\\cde".contains(new RegExp(r"^[Z-\c-e]*$"))); |
| 133 |
| 134 // Test that we handle \s and \S correctly on special Unicode characters. |
| 135 re = r"\s"; |
| 136 assertTrue("\u2028".contains(new RegExp(re))); |
| 137 assertTrue("\u2029".contains(new RegExp(re))); |
| 138 assertTrue("\uFEFF".contains(new RegExp(re))); |
| 139 |
| 140 re = r"\S"; |
| 141 assertFalse("\u2028".contains(new RegExp(re))); |
| 142 assertFalse("\u2029".contains(new RegExp(re))); |
| 143 assertFalse("\uFEFF".contains(new RegExp(re))); |
| 144 |
| 145 // Test that we handle \s and \S correctly inside some bizarre |
| 146 // character classes. |
| 147 re = r"[\s-:]"; |
| 148 assertTrue('-'.contains(new RegExp(re))); |
| 149 assertTrue(':'.contains(new RegExp(re))); |
| 150 assertTrue(' '.contains(new RegExp(re))); |
| 151 assertTrue('\t'.contains(new RegExp(re))); |
| 152 assertTrue('\n'.contains(new RegExp(re))); |
| 153 assertFalse('a'.contains(new RegExp(re))); |
| 154 assertFalse('Z'.contains(new RegExp(re))); |
| 155 |
| 156 re = r"[\S-:]"; |
| 157 assertTrue('-'.contains(new RegExp(re))); |
| 158 assertTrue(':'.contains(new RegExp(re))); |
| 159 assertFalse(' '.contains(new RegExp(re))); |
| 160 assertFalse('\t'.contains(new RegExp(re))); |
| 161 assertFalse('\n'.contains(new RegExp(re))); |
| 162 assertTrue('a'.contains(new RegExp(re))); |
| 163 assertTrue('Z'.contains(new RegExp(re))); |
| 164 |
| 165 re = r"[^\s-:]"; |
| 166 assertFalse('-'.contains(new RegExp(re))); |
| 167 assertFalse(':'.contains(new RegExp(re))); |
| 168 assertFalse(' '.contains(new RegExp(re))); |
| 169 assertFalse('\t'.contains(new RegExp(re))); |
| 170 assertFalse('\n'.contains(new RegExp(re))); |
| 171 assertTrue('a'.contains(new RegExp(re))); |
| 172 assertTrue('Z'.contains(new RegExp(re))); |
| 173 |
| 174 re = r"[^\S-:]"; |
| 175 assertFalse('-'.contains(new RegExp(re))); |
| 176 assertFalse(':'.contains(new RegExp(re))); |
| 177 assertTrue(' '.contains(new RegExp(re))); |
| 178 assertTrue('\t'.contains(new RegExp(re))); |
| 179 assertTrue('\n'.contains(new RegExp(re))); |
| 180 assertFalse('a'.contains(new RegExp(re))); |
| 181 assertFalse('Z'.contains(new RegExp(re))); |
| 182 |
| 183 re = r"[\s]"; |
| 184 assertFalse('-'.contains(new RegExp(re))); |
| 185 assertFalse(':'.contains(new RegExp(re))); |
| 186 assertTrue(' '.contains(new RegExp(re))); |
| 187 assertTrue('\t'.contains(new RegExp(re))); |
| 188 assertTrue('\n'.contains(new RegExp(re))); |
| 189 assertFalse('a'.contains(new RegExp(re))); |
| 190 assertFalse('Z'.contains(new RegExp(re))); |
| 191 |
| 192 re = r"[^\s]"; |
| 193 assertTrue('-'.contains(new RegExp(re))); |
| 194 assertTrue(':'.contains(new RegExp(re))); |
| 195 assertFalse(' '.contains(new RegExp(re))); |
| 196 assertFalse('\t'.contains(new RegExp(re))); |
| 197 assertFalse('\n'.contains(new RegExp(re))); |
| 198 assertTrue('a'.contains(new RegExp(re))); |
| 199 assertTrue('Z'.contains(new RegExp(re))); |
| 200 |
| 201 re = r"[\S]"; |
| 202 assertTrue('-'.contains(new RegExp(re))); |
| 203 assertTrue(':'.contains(new RegExp(re))); |
| 204 assertFalse(' '.contains(new RegExp(re))); |
| 205 assertFalse('\t'.contains(new RegExp(re))); |
| 206 assertFalse('\n'.contains(new RegExp(re))); |
| 207 assertTrue('a'.contains(new RegExp(re))); |
| 208 assertTrue('Z'.contains(new RegExp(re))); |
| 209 |
| 210 re = r"[^\S]"; |
| 211 assertFalse('-'.contains(new RegExp(re))); |
| 212 assertFalse(':'.contains(new RegExp(re))); |
| 213 assertTrue(' '.contains(new RegExp(re))); |
| 214 assertTrue('\t'.contains(new RegExp(re))); |
| 215 assertTrue('\n'.contains(new RegExp(re))); |
| 216 assertFalse('a'.contains(new RegExp(re))); |
| 217 assertFalse('Z'.contains(new RegExp(re))); |
| 218 |
| 219 re = r"[\s\S]"; |
| 220 assertTrue('-'.contains(new RegExp(re))); |
| 221 assertTrue(':'.contains(new RegExp(re))); |
| 222 assertTrue(' '.contains(new RegExp(re))); |
| 223 assertTrue('\t'.contains(new RegExp(re))); |
| 224 assertTrue('\n'.contains(new RegExp(re))); |
| 225 assertTrue('a'.contains(new RegExp(re))); |
| 226 assertTrue('Z'.contains(new RegExp(re))); |
| 227 |
| 228 re = r"[^\s\S]"; |
| 229 assertFalse('-'.contains(new RegExp(re))); |
| 230 assertFalse(':'.contains(new RegExp(re))); |
| 231 assertFalse(' '.contains(new RegExp(re))); |
| 232 assertFalse('\t'.contains(new RegExp(re))); |
| 233 assertFalse('\n'.contains(new RegExp(re))); |
| 234 assertFalse('a'.contains(new RegExp(re))); |
| 235 assertFalse('Z'.contains(new RegExp(re))); |
| 236 |
| 237 // First - is treated as range operator, second as literal minus. |
| 238 // This follows the specification in parsing, but doesn't throw on |
| 239 // the \s at the beginning of the range. |
| 240 re = r"[\s-0-9]"; |
| 241 assertTrue(' '.contains(new RegExp(re))); |
| 242 assertTrue('\xA0'.contains(new RegExp(re))); |
| 243 assertTrue('-'.contains(new RegExp(re))); |
| 244 assertTrue('0'.contains(new RegExp(re))); |
| 245 assertTrue('9'.contains(new RegExp(re))); |
| 246 assertFalse('1'.contains(new RegExp(re))); |
| 247 |
| 248 // Test beginning and end of line assertions with or without the |
| 249 // multiline flag. |
| 250 re = r"^\d+"; |
| 251 assertFalse("asdf\n123".contains(new RegExp(re))); |
| 252 re = new RegExp(r"^\d+", multiLine: true); |
| 253 assertTrue("asdf\n123".contains(re)); |
| 254 |
| 255 re = r"\d+$"; |
| 256 assertFalse("123\nasdf".contains(new RegExp(re))); |
| 257 re = new RegExp(r"\d+$", multiLine: true); |
| 258 assertTrue("123\nasdf".contains(re)); |
| 259 |
| 260 // Test that empty matches are handled correctly for multiline global |
| 261 // regexps. |
| 262 re = new RegExp(r"^(.*)", multiLine: true); |
| 263 assertEquals(3, re.allMatches("a\n\rb").length); |
| 264 assertEquals("*a\n*b\r*c\n*\r*d\r*\n*e", |
| 265 "a\nb\rc\n\rd\r\ne".replaceAllMapped(re, (Match m) => "*${m.group(1)}"))
; |
| 266 |
| 267 // Test that empty matches advance one character |
| 268 re = new RegExp(""); |
| 269 assertEquals("xAx", "A".replaceAll(re, "x")); |
| 270 assertEquals(3, new String.fromCharCode(161).replaceAll(re, "x").length); |
| 271 |
| 272 // Check for lazy RegExp literal creation |
| 273 void lazyLiteral(doit) { |
| 274 if (doit) return "".replaceAll( |
| 275 new RegExp(r"foo(", caseSensitive: false), ""); |
| 276 return true; |
| 277 } |
| 278 |
| 279 assertTrue(lazyLiteral(false)); |
| 280 assertThrows(() => lazyLiteral(true)); |
| 281 |
| 282 // Check $01 and $10 |
| 283 re = new RegExp("(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)"); |
| 284 assertEquals("t", "123456789t".replaceAllMapped( |
| 285 re, (Match m) => m.group(10))); |
| 286 assertEquals("15", "123456789t".replaceAllMapped( |
| 287 re, (Match m) => "${m.group(1)}5")); |
| 288 assertEquals("1", "123456789t".replaceAllMapped( |
| 289 re, (Match m) => m.group(1))); |
| 290 |
| 291 assertFalse("football".contains(new RegExp(r"()foo$\1")), "football1"); |
| 292 assertFalse("football".contains(new RegExp(r"foo$(?=ball)")), "football2"); |
| 293 assertFalse("football".contains(new RegExp(r"foo$(?!bar)")), "football3"); |
| 294 assertTrue("foo".contains(new RegExp(r"()foo$\1")), "football4"); |
| 295 assertTrue("foo".contains(new RegExp(r"foo$(?=(ball)?)")), "football5"); |
| 296 assertTrue("foo".contains(new RegExp(r"()foo$(?!bar)")), "football6"); |
| 297 assertFalse("football".contains(new RegExp(r"(x?)foo$\1")), "football7"); |
| 298 assertFalse("football".contains(new RegExp(r"foo$(?=ball)")), "football8"); |
| 299 assertFalse("football".contains(new RegExp(r"foo$(?!bar)")), "football9"); |
| 300 assertTrue("foo".contains(new RegExp(r"(x?)foo$\1")), "football10"); |
| 301 assertTrue("foo".contains(new RegExp(r"foo$(?=(ball)?)")), "football11"); |
| 302 assertTrue("foo".contains(new RegExp(r"foo$(?!bar)")), "football12"); |
| 303 |
| 304 // Check that the back reference has two successors. See |
| 305 // BackReferenceNode::PropagateForward. |
| 306 assertFalse('foo'.contains(new RegExp(r"f(o)\b\1"))); |
| 307 assertTrue('foo'.contains(new RegExp(r"f(o)\B\1"))); |
| 308 |
| 309 // Back-reference, ignore case: |
| 310 // ASCII |
| 311 assertEquals("a", new RegExp(r"x(a)\1x", caseSensitive: false) |
| 312 .firstMatch("xaAx").group(1), "backref-ASCII"); |
| 313 assertFalse("xaaaaa".contains(new RegExp(r"x(...)\1", caseSensitive: false))
, |
| 314 "backref-ASCII-short"); |
| 315 assertTrue("xx".contains(new RegExp(r"x((?:))\1\1x", caseSensitive: false)), |
| 316 "backref-ASCII-empty"); |
| 317 assertTrue("xabcx".contains( |
| 318 new RegExp(r"x(?:...|(...))\1x", caseSensitive: false)), |
| 319 "backref-ASCII-uncaptured"); |
| 320 assertTrue("xabcABCx".contains( |
| 321 new RegExp(r"x(?:...|(...))\1x", caseSensitive: false)), |
| 322 "backref-ASCII-backtrack"); |
| 323 assertEquals("aBc", new RegExp(r"x(...)\1\1x", caseSensitive: false) |
| 324 .firstMatch("xaBcAbCABCx").group(1), "backref-ASCII-twice"); |
| 325 |
| 326 for (var i = 0; i < 128; i++) { |
| 327 var testName = "backref-ASCII-char-$i,,${i^0x20}"; |
| 328 var test = new String.fromCharCodes([i, i ^ 0x20]) |
| 329 .contains(new RegExp(r"^(.)\1$", caseSensitive: false)); |
| 330 if (('A'.codeUnitAt(0) <= i && i <= 'Z'.codeUnitAt(0)) || |
| 331 ('a'.codeUnitAt(0) <= i && i <= 'z'.codeUnitAt(0))) { |
| 332 assertTrue(test, testName); |
| 333 } else { |
| 334 assertFalse(test, testName); |
| 335 } |
| 336 } |
| 337 |
| 338 assertFalse('foo'.contains(new RegExp(r"f(o)$\1")), "backref detects at_end"
); |
| 339 |
| 340 // Check decimal escapes doesn't overflow. |
| 341 // (Note: \214 is interpreted as octal). |
| 342 assertEquals("\x8c7483648", new RegExp(r"\2147483648") |
| 343 .firstMatch("\x8c7483648").group(0), "Overflow decimal escape"); |
| 344 |
| 345 // Check numbers in quantifiers doesn't overflow and doesn't throw on |
| 346 // too large numbers. |
| 347 assertFalse('b'.contains( |
| 348 new RegExp(r"a{111111111111111111111111111111111111111111111}")), |
| 349 "overlarge1"); |
| 350 assertFalse('b'.contains( |
| 351 new RegExp(r"a{999999999999999999999999999999999999999999999}")), |
| 352 "overlarge2"); |
| 353 assertFalse('b'.contains( |
| 354 new RegExp(r"a{1,111111111111111111111111111111111111111111111}")), |
| 355 "overlarge3"); |
| 356 assertFalse('b'.contains( |
| 357 new RegExp(r"a{1,999999999999999999999999999999999999999999999}")), |
| 358 "overlarge4"); |
| 359 assertFalse('b'.contains(new RegExp(r"a{2147483648}")), |
| 360 "overlarge5"); |
| 361 assertFalse('b'.contains(new RegExp(r"a{21474836471}")), |
| 362 "overlarge6"); |
| 363 assertFalse('b'.contains(new RegExp(r"a{1,2147483648}")), |
| 364 "overlarge7"); |
| 365 assertFalse('b'.contains(new RegExp(r"a{1,21474836471}")), |
| 366 "overlarge8"); |
| 367 assertFalse('b'.contains(new RegExp(r"a{2147483648,2147483648}")), |
| 368 "overlarge9"); |
| 369 assertFalse('b'.contains(new RegExp(r"a{21474836471,21474836471}")), |
| 370 "overlarge10"); |
| 371 assertFalse('b'.contains(new RegExp(r"a{2147483647}")), |
| 372 "overlarge11"); |
| 373 assertFalse('b'.contains(new RegExp(r"a{1,2147483647}")), |
| 374 "overlarge12"); |
| 375 assertTrue('a'.contains(new RegExp(r"a{1,2147483647}")), |
| 376 "overlarge13"); |
| 377 assertFalse('a'.contains(new RegExp(r"a{2147483647,2147483647}")), |
| 378 "overlarge14"); |
| 379 |
| 380 // Check that we don't read past the end of the string. |
| 381 assertFalse('b'.contains(new RegExp(r"f"))); |
| 382 assertFalse('x'.contains(new RegExp(r"[abc]f"))); |
| 383 assertFalse('xa'.contains(new RegExp(r"[abc]f"))); |
| 384 assertFalse('x'.contains(new RegExp(r"[abc]<"))); |
| 385 assertFalse('xa'.contains(new RegExp(r"[abc]<"))); |
| 386 assertFalse('b'.contains(new RegExp(r"f", caseSensitive: false))); |
| 387 assertFalse('x'.contains(new RegExp(r"[abc]f", caseSensitive: false))); |
| 388 assertFalse('xa'.contains(new RegExp(r"[abc]f", caseSensitive: false))); |
| 389 assertFalse('x'.contains(new RegExp(r"[abc]<", caseSensitive: false))); |
| 390 assertFalse('xa'.contains(new RegExp(r"[abc]<", caseSensitive: false))); |
| 391 assertFalse('x'.contains(new RegExp(r"f[abc]"))); |
| 392 assertFalse('xa'.contains(new RegExp(r"f[abc]"))); |
| 393 assertFalse('x'.contains(new RegExp(r"<[abc]"))); |
| 394 assertFalse('xa'.contains(new RegExp(r"<[abc]"))); |
| 395 assertFalse('x'.contains(new RegExp(r"f[abc]", caseSensitive: false))); |
| 396 assertFalse('xa'.contains(new RegExp(r"f[abc]", caseSensitive: false))); |
| 397 assertFalse('x'.contains(new RegExp(r"<[abc]", caseSensitive: false))); |
| 398 assertFalse('xa'.contains(new RegExp(r"<[abc]", caseSensitive: false))); |
| 399 |
| 400 // Test that merging of quick test masks gets it right. |
| 401 assertFalse('x7%%y'.contains(new RegExp(r"x([0-7]%%x|[0-6]%%y)")), 'qt'); |
| 402 assertFalse('xy7%%%y'.contains( |
| 403 new RegExp(r"()x\1(y([0-7]%%%x|[0-6]%%%y)|dkjasldkas)")), 'qt2'); |
| 404 assertFalse('xy%%%y'.contains( |
| 405 new RegExp(r"()x\1(y([0-7]%%%x|[0-6]%%%y)|dkjasldkas)")), 'qt3'); |
| 406 assertFalse('xy7%%%y'.contains( |
| 407 new RegExp(r"()x\1y([0-7]%%%x|[0-6]%%%y)")), 'qt4'); |
| 408 assertFalse('xy%%%y'.contains( |
| 409 new RegExp(r"()x\1(y([0-7]%%%x|[0-6]%%%y)|dkjasldkas)")), 'qt5'); |
| 410 assertFalse('xy7%%%y'.contains( |
| 411 new RegExp(r"()x\1y([0-7]%%%x|[0-6]%%%y)")), 'qt6'); |
| 412 assertFalse('xy7%%%y'.contains( |
| 413 new RegExp(r"xy([0-7]%%%x|[0-6]%%%y)")), 'qt7'); |
| 414 assertFalse('x7%%%y'.contains(new RegExp(r"x([0-7]%%%x|[0-6]%%%y)")), 'qt8')
; |
| 415 |
| 416 |
| 417 // Don't hang on this one. |
| 418 "".contains(new RegExp(r"[^\xfe-\xff]*")); |
| 419 |
| 420 var longbuffer = new StringBuffer("a"); |
| 421 for (var i = 0; i < 100000; i++) { |
| 422 longbuffer.write("a?"); |
| 423 } |
| 424 var long = longbuffer.toString(); |
| 425 |
| 426 // Don't crash on this one, but maybe throw an exception. |
| 427 try { |
| 428 new RegExp(long).allMatches("a"); |
| 429 } catch (e) { |
| 430 assertTrue(String(e).indexOf("Stack overflow") >= 0, "overflow"); |
| 431 } |
| 432 |
| 433 |
| 434 // Test boundary-checks. |
| 435 void assertRegExpTest(re, input, test) { |
| 436 assertEquals(test, input.contains( |
| 437 new RegExp(re)), "test:" + re + ":" + input); |
| 438 } |
| 439 |
| 440 assertRegExpTest(r"b\b", "b", true); |
| 441 assertRegExpTest(r"b\b$", "b", true); |
| 442 assertRegExpTest(r"\bb", "b", true); |
| 443 assertRegExpTest(r"^\bb", "b", true); |
| 444 assertRegExpTest(r",\b", ",", false); |
| 445 assertRegExpTest(r",\b$", ",", false); |
| 446 assertRegExpTest(r"\b,", ",", false); |
| 447 assertRegExpTest(r"^\b,", ",", false); |
| 448 |
| 449 assertRegExpTest(r"b\B", "b", false); |
| 450 assertRegExpTest(r"b\B$", "b", false); |
| 451 assertRegExpTest(r"\Bb", "b", false); |
| 452 assertRegExpTest(r"^\Bb", "b", false); |
| 453 assertRegExpTest(r",\B", ",", true); |
| 454 assertRegExpTest(r",\B$", ",", true); |
| 455 assertRegExpTest(r"\B,", ",", true); |
| 456 assertRegExpTest(r"^\B,", ",", true); |
| 457 |
| 458 assertRegExpTest(r"b\b", "b,", true); |
| 459 assertRegExpTest(r"b\b", "ba", false); |
| 460 assertRegExpTest(r"b\B", "b,", false); |
| 461 assertRegExpTest(r"b\B", "ba", true); |
| 462 |
| 463 assertRegExpTest(r"b\Bb", "bb", true); |
| 464 assertRegExpTest(r"b\bb", "bb", false); |
| 465 |
| 466 assertRegExpTest(r"b\b[,b]", "bb", false); |
| 467 assertRegExpTest(r"b\B[,b]", "bb", true); |
| 468 assertRegExpTest(r"b\b[,b]", "b,", true); |
| 469 assertRegExpTest(r"b\B[,b]", "b,", false); |
| 470 |
| 471 assertRegExpTest(r"[,b]\bb", "bb", false); |
| 472 assertRegExpTest(r"[,b]\Bb", "bb", true); |
| 473 assertRegExpTest(r"[,b]\bb", ",b", true); |
| 474 assertRegExpTest(r"[,b]\Bb", ",b", false); |
| 475 |
| 476 assertRegExpTest(r"[,b]\b[,b]", "bb", false); |
| 477 assertRegExpTest(r"[,b]\B[,b]", "bb", true); |
| 478 assertRegExpTest(r"[,b]\b[,b]", ",b", true); |
| 479 assertRegExpTest(r"[,b]\B[,b]", ",b", false); |
| 480 assertRegExpTest(r"[,b]\b[,b]", "b,", true); |
| 481 assertRegExpTest(r"[,b]\B[,b]", "b,", false); |
| 482 |
| 483 // Skipped tests from V8: |
| 484 |
| 485 // Test that caching of result doesn't share result objects. |
| 486 // More iterations increases the chance of hitting a GC. |
| 487 |
| 488 // Test that we perform the spec required conversions in the correct order. |
| 489 |
| 490 // Check that properties of RegExp have the correct permissions. |
| 491 |
| 492 // Check that end-anchored regexps are optimized correctly. |
| 493 re = r"(?:a|bc)g$"; |
| 494 assertTrue("ag".contains(new RegExp(re))); |
| 495 assertTrue("bcg".contains(new RegExp(re))); |
| 496 assertTrue("abcg".contains(new RegExp(re))); |
| 497 assertTrue("zimbag".contains(new RegExp(re))); |
| 498 assertTrue("zimbcg".contains(new RegExp(re))); |
| 499 |
| 500 assertFalse("g".contains(new RegExp(re))); |
| 501 assertFalse("".contains(new RegExp(re))); |
| 502 |
| 503 // Global regexp (non-zero start). |
| 504 re = r"(?:a|bc)g$"; |
| 505 assertTrue("ag".contains(new RegExp(re))); |
| 506 // Near start of string. |
| 507 assertTrue(new RegExp(re).allMatches("zimbag", 1).isNotEmpty); |
| 508 // At end of string. |
| 509 assertTrue(new RegExp(re).allMatches("zimbag", 6).isEmpty); |
| 510 5; // Near end of string. |
| 511 assertTrue(new RegExp(re).allMatches("zimbag", 5).isEmpty); |
| 512 assertTrue(new RegExp(re).allMatches("zimbag", 4).isNotEmpty); |
| 513 |
| 514 // Anchored at both ends. |
| 515 re = r"^(?:a|bc)g$"; |
| 516 assertTrue("ag".contains(new RegExp(re))); |
| 517 assertTrue(new RegExp(re).allMatches("ag", 1).isEmpty); |
| 518 assertTrue(new RegExp(re).allMatches("zag", 1).isEmpty); |
| 519 |
| 520 // Long max_length of RegExp. |
| 521 re = r"VeryLongRegExp!{1,1000}$"; |
| 522 assertTrue("BahoolaVeryLongRegExp!!!!!!".contains(new RegExp(re))); |
| 523 assertFalse("VeryLongRegExp".contains(new RegExp(re))); |
| 524 assertFalse("!".contains(new RegExp(re))); |
| 525 |
| 526 // End anchor inside disjunction. |
| 527 re = r"(?:a$|bc$)"; |
| 528 assertTrue("a".contains(new RegExp(re))); |
| 529 assertTrue("bc".contains(new RegExp(re))); |
| 530 assertTrue("abc".contains(new RegExp(re))); |
| 531 assertTrue("zimzamzumba".contains(new RegExp(re))); |
| 532 assertTrue("zimzamzumbc".contains(new RegExp(re))); |
| 533 assertFalse("c".contains(new RegExp(re))); |
| 534 assertFalse("".contains(new RegExp(re))); |
| 535 |
| 536 // Only partially anchored. |
| 537 re = r"(?:a|bc$)"; |
| 538 assertTrue("a".contains(new RegExp(re))); |
| 539 assertTrue("bc".contains(new RegExp(re))); |
| 540 assertEquals("a", new RegExp(re).firstMatch("abc").group(0)); |
| 541 assertEquals(4, new RegExp(re).firstMatch("zimzamzumba").start); |
| 542 assertEquals("bc", new RegExp(re).firstMatch("zimzomzumbc").group(0)); |
| 543 assertFalse("c".contains(new RegExp(re))); |
| 544 assertFalse("".contains(new RegExp(re))); |
| 545 |
| 546 // Valid syntax in ES5. |
| 547 re = new RegExp("(?:x)*"); |
| 548 re = new RegExp("(x)*"); |
| 549 |
| 550 // Syntax extension relative to ES5, for matching JSC (and ES3). |
| 551 // Shouldn't throw. |
| 552 re = new RegExp("(?=x)*"); |
| 553 re = new RegExp("(?!x)*"); |
| 554 |
| 555 // Should throw. Shouldn't hit asserts in debug mode. |
| 556 assertThrows(() => new RegExp('(*)')); |
| 557 assertThrows(() => new RegExp('(?:*)')); |
| 558 assertThrows(() => new RegExp('(?=*)')); |
| 559 assertThrows(() => new RegExp('(?!*)')); |
| 560 |
| 561 // Test trimmed regular expression for RegExp.test(). |
| 562 assertTrue("abc".contains(new RegExp(r".*abc"))); |
| 563 assertFalse("q".contains(new RegExp(r".*\d+"))); |
| 564 |
| 565 // Tests skipped from V8: |
| 566 // Test that RegExp.prototype.toString() throws TypeError for |
| 567 // incompatible receivers (ES5 section 15.10.6 and 15.10.6.4). |
| 568 } |
| 569 } |
OLD | NEW |