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