8fe7b7bdfe628d889bdd1907e0bf40f21e756613
[WebKit-https.git] / LayoutTests / js / script-tests / regexp-unicode.js
1 description(
2 'Test for unicode regular expression processing'
3 );
4
5 // Test \u{} escapes in a regular expression
6 shouldBe('"a".match(/\u{61}/u)[0].length', '1');
7 shouldBe('"a".match(/\u{41}/ui)[0].length', '1');
8 shouldBe('"a".match(/\u{061}/u)[0].length', '1');
9 shouldBe('"a".match(/\u{041}/iu)[0].length', '1');
10 shouldBe('"\u{212}".match(/\u{212}/u)[0].length', '1');
11 shouldBe('"\u{212}".match(/\u{0212}/u)[0].length', '1');
12 shouldBe('"\u{1234}".match(/\u{1234}/u)[0].length', '1');
13 shouldBe('"\u{1234}".match(/\u{01234}/u)[0].length', '1');
14 shouldBe('"\u{2abc}".match(/\u{2abc}/u)[0].length', '1');
15 shouldBe('"\u{03fed}".match(/\u{03fed}/u)[0].length', '1');
16 shouldBe('"\u{12345}".match(/\u{12345}/u)[0].length', '2');
17 shouldBe('"\u{12345}".match(/\u{012345}/u)[0].length', '2');
18 shouldBe('"\u{1d306}".match(/\u{1d306}/u)[0].length', '2');
19 shouldBeTrue('/\u{1044f}/u.test("\ud801\udc4f")');
20 shouldBeTrue('/\ud801\udc4f/u.test("\u{1044f}")');
21
22 // Test basic unicode flag processing
23 shouldBe('"\u{1d306}".match(/\u{1d306}/u)[0].length', '2');
24 shouldBeTrue('/(\u{10000}|\u{10400}|\u{10429})/u.test("\u{10400}")');
25 shouldBe('"\u{10123}".match(/a|\u{10123}|b/u)[0].length', '2');
26 shouldBe('"b".match(/a|\u{10123}|b/u)[0].length', '1');
27 shouldBeFalse('/(?:a|\u{10123}|b)x/u.test("\u{10123}")');
28 shouldBeTrue('/(?:a|\u{10123}|b)x/u.test("\u{10123}x")');
29 shouldBeFalse('/(?:a|\u{10123}|b)x/u.test("b")');
30 shouldBeTrue('/(?:a|\u{10123}|b)x/u.test("bx")');
31 shouldBe('"a\u{10123}x".match(/a\u{10123}b|a\u{10123}x/u)[0].length', '4');
32
33 // Test unicode flag with ignore case
34 shouldBeTrue('/(\u{10000}|\u{10400}|\u{10429})x/ui.test("\u{10400}x")');
35 shouldBeTrue('/(\u{10000}|\u{10400}|\u{10429})x/ui.test("\u{10429}x")');
36 shouldBeTrue('/(\u{10000}|\u{10400}|\u{10429})x/ui.test("\u{10401}x")');
37 shouldBeTrue('/(\u{10000}|\u{10400}|\u{10429})x/ui.test("\u{10428}x")');
38 shouldBe('"\u{10429}".match(/a|\u{10401}|b/iu)[0].length', '2');
39 shouldBe('"B".match(/a|\u{10123}|b/iu)[0].length', '1');
40 shouldBeFalse('/(?:A|\u{10123}|b)x/iu.test("\u{10123}")');
41 shouldBeTrue('/(?:A|\u{10123}|b)x/iu.test("\u{10123}x")');
42 shouldBeFalse('/(?:A|\u{10123}|b)x/iu.test("b")');
43 shouldBeTrue('/(?:A|\u{10123}|b)x/iu.test("bx")');
44 shouldBe('"a\u{10123}X".match(/a\u{10123}b|a\u{10123}x/iu)[0].length', '4');
45 shouldBe('"\u0164x".match(/\u0165x/iu)[0].length', '2');
46 shouldBeTrue('/\\w/iu.test("\u017f")');
47 shouldBeTrue('/\\w/iu.test("\u212a")');
48 shouldBeFalse('/\\W/iu.test("\u017f")');
49 shouldBeFalse('/\\W/iu.test("\u212a")');
50 shouldBeTrue('/[\\w\\d]/iu.test("\u017f")');
51 shouldBeTrue('/[\\w\\d]/iu.test("\u212a")');
52 shouldBeFalse('/[^\\w\\d]/iu.test("\u017f")');
53 shouldBeFalse('/[^\\w\\d]/iu.test("\u212a")');
54 shouldBeFalse('/[\\W\\d]/iu.test("\u017f")');
55 shouldBeFalse('/[\\W\\d]/iu.test("\u212a")');
56 shouldBeTrue('/[^\\W\\d]/iu.test("\u017f")');
57 shouldBeTrue('/[^\\W\\d]/iu.test("\u212a")');
58 shouldBeTrue('/\\w/iu.test("S")');
59 shouldBeTrue('/\\w/iu.test("K")');
60 shouldBeFalse('/\\W/iu.test("S")');
61 shouldBeFalse('/\\W/iu.test("K")');
62 shouldBeTrue('/[\\w\\d]/iu.test("S")');
63 shouldBeTrue('/[\\w\\d]/iu.test("K")');
64 shouldBeFalse('/[^\\w\\d]/iu.test("S")');
65 shouldBeFalse('/[^\\w\\d]/iu.test("K")');
66 shouldBeFalse('/[\\W\\d]/iu.test("S")');
67 shouldBeFalse('/[\\W\\d]/iu.test("K")');
68 shouldBeTrue('/[^\\W\\d]/iu.test("S")');
69 shouldBeTrue('/[^\\W\\d]/iu.test("K")');
70 shouldBe('"Gras\u017foden is old German for grass".match(/.*?\\Bs\\u017foden/iu)[0]', '"Gras\u017foden"');
71 shouldBe('"Gras\u017foden is old German for grass".match(/.*?\\B\\u017foden/iu)[0]', '"Gras\u017foden"');
72 shouldBe('"Gras\u017foden is old German for grass".match(/.*?\\Boden/iu)[0]', '"Gras\u017foden"');
73 shouldBe('"Gras\u017foden is old German for grass".match(/.*?\\Bden/iu)[0]', '"Gras\u017foden"');
74 shouldBe('"Water freezes at 273\u212a which is 0C.".split(/\\b\\s/iu)', '["Water","freezes","at","273\u212a","which","is","0C."]');
75
76 // Test . matches with Unicode flag
77 shouldBe('"\u{1D306}".match(/^.$/u)[0].length', '2');
78 shouldBe('"It is 78\u00B0".match(/.*/u)[0].length', '9');
79 var stringWithDanglingFirstSurrogate = "X\uD801X";
80 shouldBe('stringWithDanglingFirstSurrogate.match(/.*/u)[0].length', '3'); // We should match a dangling first surrogate as 1 character
81 var stringWithDanglingSecondSurrogate = "X\uDF01X";
82 shouldBe('stringWithDanglingSecondSurrogate.match(/.*/u)[0].length', '3'); // We should match a dangling second surrogate as 1 character
83
84 // Test character classes with unicode characters with and without unicode flag
85 shouldBe('"\u{1d306}".match(/[\uD834\uDF06a]/)[0].length', '1');
86 shouldBe('"\u{1d306}".match(/[a\u{1d306}]/u)[0].length', '2');
87 shouldBe('"\u{1d306}".match(/[\u{1d306}a]/u)[0].length', '2');
88 shouldBe('"\u{1d306}".match(/[a-\uD834\uDF06]/)[0].length', '1');
89 shouldBe('"\u{1d306}".match(/[a-\u{1d306}]/u)[0].length', '2');
90
91 // Test a character class that is a range from one UTF16 to a Unicode character
92 shouldBe('"X".match(/[\u0020-\ud801\udc4f]/u)[0].length', '1');
93 shouldBe('"\u1000".match(/[\u0020-\ud801\udc4f]/u)[0].length', '1');
94 shouldBe('"\ud801\udc27".match(/[\u0020-\ud801\udc4f]/u)[0].length', '2');
95
96 var re1 = new RegExp("[^\u0020-\uD801\uDC4F]", "u");
97 shouldBeFalse('re1.test("Z")');
98 shouldBeFalse('re1.test("\u{1000}")');
99 shouldBeFalse('re1.test("\u{10400}")');
100
101 var re2 = new RegExp("[a-z\u{10000}-\u{15000}]", "iu");
102 shouldBeTrue('re2.test("A")');
103 shouldBeFalse('re2.test("\uffff")');
104 shouldBeTrue('re2.test("\u{12345}")');
105
106 // Make sure we properly handle dangling surrogates and combined surrogates
107 shouldBe('/[\u{10c01}\uD803#\uDC01]/u.exec("\u{10c01}").toString()', '"\u{10c01}"');
108 shouldBe('/[\uD803\u{10c01}\uDC01]/u.exec("\u{10c01}").toString()', '"\u{10c01}"');
109 shouldBe('/[\uD803#\uDC01\u{10c01}]/u.exec("\u{10c01}").toString()', '"\u{10c01}"');
110 shouldBe('/[\uD803\uD803\uDC01\uDC01]/u.exec("\u{10c01}").toString()', '"\u{10c01}"');
111 shouldBeNull('/[\u{10c01}\uD803#\uDC01]{2}/u.exec("\u{10c01}")');
112 shouldBeNull('/[\uD803\u{10c01}\uDC01]{2}/u.exec("\u{10c01}")');
113 shouldBeNull('/[\uD803#\uDC01\u{10c01}]{2}/u.exec("\u{10c01}")');
114 shouldBeNull('/[\uD803\uD803\uDC01\uDC01]{2}/u.exec("\u{10c01}")');
115 shouldBe('/\uD803|\uDC01|\u{10c01}/u.exec("\u{10c01}").toString()', '"\u{10c01}"');
116 shouldBe('/\uD803|\uD803\uDC01|\uDC01/u.exec("\u{10c01}").toString()', '"\u{10c01}"');
117 shouldBe('/\uD803|\uDC01|\u{10c01}/u.exec("\u{D803}").toString()', '"\u{D803}"');
118 shouldBe('/\uD803|\uD803\uDC01|\uDC01/u.exec("\u{DC01}").toString()', '"\u{DC01}"');
119 shouldBeNull('/\uD803\u{10c01}/u.exec("\u{10c01}")');
120 shouldBeNull('/\uD803\u{10c01}/u.exec("\uD803")');
121 shouldBe('"\uD803\u{10c01}".match(/\uD803\u{10c01}/u)[0].length', '3');
122
123 // Check quantified matches
124 shouldBeTrue('/\u{1d306}{2}/u.test("\u{1d306}\u{1d306}")');
125 shouldBeTrue('/\uD834\uDF06{2}/u.test("\uD834\uDF06\uD834\uDF06")');
126 shouldBe('"\u{10405}\u{10405}\u{10405}\u{10405}".match(/\u{10405}{3}/u)[0]', '"\u{10405}\u{10405}\u{10405}"');
127 shouldBe('"\u{10402}\u{10405}\u{10405}\u{10405}".match(/\u{10405}{3}/u)[0]', '"\u{10405}\u{10405}\u{10405}"');
128 shouldBe('"\u{10401}\u{10401}\u{10400}".match(/\u{10401}{1,3}/u)[0]', '"\u{10401}\u{10401}"');
129 shouldBe('"\u{10401}\u{10429}".match(/\u{10401}{1,3}/iu)[0]', '"\u{10401}\u{10429}"');
130 shouldBe('"\u{10401}\u{10429}\u{1042a}\u{10429}".match(/\u{10401}{1,}/iu)[0]', '"\u{10401}\u{10429}"');
131
132 // Check back tracking on partial matches
133 shouldBe('"\u{10311}\u{10311}\u{10311}".match(/\u{10311}*a|\u{10311}*./u)[0]', '"\u{10311}\u{10311}\u{10311}"');
134 shouldBe('"a\u{10311}\u{10311}".match(/a\u{10311}*?$/u)[0]', '"a\u{10311}\u{10311}"');
135 shouldBe('"a\u{10311}\u{10311}\u{10311}c".match(/a\u{10311}*cd|a\u{10311}*c/u)[0]', '"a\u{10311}\u{10311}\u{10311}c"');
136 shouldBe('"a\u{10311}\u{10311}\u{10311}c".match(/a\u{10311}+cd|a\u{10311}+c/u)[0]', '"a\u{10311}\u{10311}\u{10311}c"');
137 shouldBe('"\u{10311}\u{10311}\u{10311}".match(/\u{10311}+?a|\u{10311}+?./u)[0]', '"\u{10311}\u{10311}"');
138 shouldBe('"\u{10311}\u{10311}\u{10311}".match(/\u{10311}+?a|\u{10311}+?$/u)[0]', '"\u{10311}\u{10311}\u{10311}"');
139 shouldBe('"a\u{10311}\u{10311}\u{10311}c".match(/a\u{10311}*?cd|a\u{10311}*?c/u)[0]', '"a\u{10311}\u{10311}\u{10311}c"');
140 shouldBe('"a\u{10311}\u{10311}\u{10311}c".match(/a\u{10311}+?cd|a\u{10311}+?c/u)[0]', '"a\u{10311}\u{10311}\u{10311}c"');
141 shouldBe('"\u{10311}\u{10311}\u{10311}".match(/\u{10311}+?a|\u{10311}+?./iu)[0]', '"\u{10311}\u{10311}"');
142 shouldBe('"\u{1042a}\u{1042a}\u{10311}".match(/\u{10402}*\u{10200}|\u{10402}*\u{10311}/iu)[0]', '"\u{1042a}\u{1042a}\u{10311}"');
143 shouldBe('"\u{1042a}\u{1042a}\u{10311}".match(/\u{10402}+\u{10200}|\u{10402}+\u{10311}/iu)[0]', '"\u{1042a}\u{1042a}\u{10311}"');
144 shouldBe('"\u{1042a}\u{1042a}\u{10311}".match(/\u{10402}*?\u{10200}|\u{10402}*?\u{10311}/iu)[0]', '"\u{1042a}\u{1042a}\u{10311}"');
145 shouldBe('"\u{1042a}\u{1042a}\u{10311}".match(/\u{10402}+?\u{10200}|\u{10402}+?\u{10311}/iu)[0]', '"\u{1042a}\u{1042a}\u{10311}"');
146 shouldBe('"ab\u{10311}c\u{10a01}".match(/abc|ab\u{10311}cd|ab\u{10311}c\u{10a01}d|ab\u{10311}c\u{10a01}/u)[0]', '"ab\u{10311}c\u{10a01}"');
147 shouldBe('"ab\u{10428}c\u{10a01}".match(/abc|ab\u{10400}cd|ab\u{10400}c\u{10a01}d|ab\u{10400}c\u{10a01}/iu)[0]', '"ab\u{10428}c\u{10a01}"');
148 shouldBeFalse('/abc|ab\u{10400}cd|ab\u{10400}c\u{10a01}d|ab\u{10400}c\u{10a01}/iu.test("qwerty123")');
149 shouldBe('"a\u{10428}\u{10428}\u{10428}c".match(/ac|a\u{10400}*cd|a\u{10400}+cd|a\u{10400}+c/iu)[0]', '"a\u{10428}\u{10428}\u{10428}c"');
150 shouldBe('"ab\u{10428}\u{10428}\u{10428}c\u{10a01}".match(/abc|ab\u{10400}*cd|ab\u{10400}+c\u{10a01}d|ab\u{10400}+c\u{10a01}/iu)[0]', '"ab\u{10428}\u{10428}\u{10428}c\u{10a01}"');
151 shouldBe('"ab\u{10428}\u{10428}\u{10428}".match(/abc|ab\u{10428}*./u)[0]', '"ab\u{10428}\u{10428}\u{10428}"');
152 shouldBe('"ab\u{10428}\u{10428}\u{10428}".match(/abc|ab\u{10400}*./iu)[0]', '"ab\u{10428}\u{10428}\u{10428}"');
153 shouldBe('"\u{10400}".match(/a*/u)[0].length', '0');
154 shouldBe('"\u{10400}".match(/a*/ui)[0].length', '0');
155 shouldBe('"\u{10400}".match(/\\d*/u)[0].length', '0');
156 shouldBe('"123\u{10400}".match(/\\d*/u)[0]', '"123"');
157 shouldBe('"12X3\u{10400}4".match(/\\d{0,1}/ug)', '["1", "2", "", "3", "", "4", ""]');
158 shouldBe('"\u{10402}\u{10405}\u{10405}\u{10402}\u{10405}\u{10405}\u{10405}".match(/\u{10405}{3}/u)[0]', '"\u{10405}\u{10405}\u{10405}"');
159 shouldBe('"a\u{10410}\u{10410}b".match(/a(\u{10410}*?)bc|a(\u{10410}*?)b/ui)[0]', '"a\u{10410}\u{10410}b"');
160
161 var re3 = new RegExp("(a\u{10410}*bc)|(a\u{10410}*b)", "u");
162 var match3 = "a\u{10410}\u{10410}b".match(re3);
163 shouldBe('match3[0]', '"a\u{10410}\u{10410}b"');
164 shouldBeUndefined('match3[1]');
165 shouldBe('match3[2]', '"a\u{10410}\u{10410}b"');
166
167 var re4 = new RegExp("a(\u{10410}*)bc|a(\u{10410}*)b", "ui");
168 var match4 = "a\u{10438}\u{10438}b".match(re4);
169 shouldBe('match4[0]', '"a\u{10438}\u{10438}b"');
170 shouldBeUndefined('match4[1]');
171 shouldBe('match4[2]', '"\u{10438}\u{10438}"');
172
173 var match5 = "a\u{10412}\u{10412}b\u{10412}\u{10412}".match(/a(\u{10412}*)bc\1|a(\u{10412}*)b\2/u);
174 shouldBe('match5[0]', '"a\u{10412}\u{10412}b\u{10412}\u{10412}"');
175 shouldBeUndefined('match5[1]');
176 shouldBe('match5[2]', '"\u{10412}\u{10412}"');
177
178 var match6 = "a\u{10412}\u{10412}b\u{1043a}\u{10412}\u{1043a}".match(/a(\u{1043a}*)bc\1|a(\u{1043a}*)b\2/iu);
179 shouldBe('match6[0]', '"a\u{10412}\u{10412}b\u{1043a}\u{10412}"');
180 shouldBeUndefined('match6[1]');
181 shouldBe('match6[2]', '"\u{10412}\u{10412}"');
182
183 // Check unicode case insensitive matches
184 shouldBeTrue('/\u017ftop/ui.test("stop")');
185 shouldBeTrue('/stop/ui.test("\u017ftop")');
186 shouldBeTrue('/\u212aelvin/ui.test("kelvin")');
187 shouldBeTrue('/KELVIN/ui.test("\u212aelvin")');
188
189 // Verify that without the unicode flag, \u{} doesn't parse to a unicode escapes, but to a counted match of the character 'u'.
190 shouldBeTrue('/\\u{1}/.test("u")');
191 shouldBeFalse('/\\u{4}/.test("u")');
192 shouldBeTrue('/\\u{4}/.test("uuuu")');
193
194 // Check that \- escape works in a character class for a unicode pattern
195 shouldBe('"800-555-1212".match(/[0-9\\-]*/u)[0].length', '12');
196
197 // Check that counted Unicode character classes work.
198 var re7 = new RegExp("(?:[\u{1f0a1}\u{1f0b1}\u{1f0d1}\u{1f0c1}]{2,4})", "u");
199 shouldBe('"\u{1f0a1}\u{1f0d1}\u{1f0b8}\u{1f0c9}\u{1f0da}".match(re7)[0]', '"\u{1f0a1}\u{1f0d1}"');
200 shouldBe('"\u{1f0a1}\u{1f0d1}\u{1f0b1}\u{1f0c9}\u{1f0da}".match(re7)[0]', '"\u{1f0a1}\u{1f0d1}\u{1f0b1}"');
201 shouldBe('"\u{1f0a1}\u{1f0d1}\u{1f0b1}\u{1f0c1}\u{1f0da}".match(re7)[0]', '"\u{1f0a1}\u{1f0d1}\u{1f0b1}\u{1f0c1}"');
202 shouldBe('"\u{1f0a3}\u{1f0d1}\u{1f0b1}\u{1f0c1}\u{1f0da}".match(re7)[0]', '"\u{1f0d1}\u{1f0b1}\u{1f0c1}"');
203 shouldBe('"\u{10311}\u{10310}\u{10311}".match(/[\u{10301}\u{10311}]*a|[\u{10310}\u{10311}]*./iu)[0]', '"\u{10311}\u{10310}\u{10311}"');
204 shouldBe('"\u{10311}\u{10310}\u{10311}".match(/[\u{10301}\u{10311}]*?a|[\u{10310}\u{10311}]*?./iu)[0]', '"\u{10311}"');
205 shouldBe('"\u{10311}\u{10310}\u{10311}".match(/[\u{10301}\u{10311}]+a|[\u{10310}\u{10311}]+./iu)[0]', '"\u{10311}\u{10310}\u{10311}"');
206 shouldBe('"\u{10311}\u{10310}\u{10311}".match(/[\u{10301}\u{10311}]+?a|[\u{10310}\u{10311}]+?./iu)[0]', '"\u{10311}\u{10310}"');
207 shouldBe('"\u{10311}\u{10310}\u{10311}".match(/[\u{10301}\u{10311}]+?a$|[\u{10310}\u{10311}]+?.$/iu)[0]', '"\u{10311}\u{10310}\u{10311}"');
208 shouldBe('"\u{10311}\u{10310}\u{10311}".match(/[\u{10301}\u{10311}x]+a|[\u{10310}\u{10311}x]+./iu)[0]', '"\u{10311}\u{10310}\u{10311}"');
209 shouldBe('"\u{10311}\u{10310}\u{10311}".match(/[\u{10301}\u{10311}x]+?a|[\u{10310}\u{10311}x]+?./iu)[0]', '"\u{10311}\u{10310}"');
210
211 var re8 = new  RegExp("^([0-9a-z\.]{3,16})\\|\u{041d}\u{0410}\u{0427}\u{0410}\u{0422}\u{042c}", "ui");
212 shouldBe('"C83|\u{041d}\u{0410}\u{0427}\u{0410}\u{0422}\u{042c}".match(re8)[0]', '"C83|\u{041d}\u{0410}\u{0427}\u{0410}\u{0422}\u{042c}"');
213 shouldBe('"This.Is.16.Chars|\u{041d}\u{0410}\u{0427}\u{0410}\u{0422}\u{042c}".match(re8)[0]', '"This.Is.16.Chars|\u{041d}\u{0410}\u{0427}\u{0410}\u{0422}\u{042c}"');
214
215 // Check that unicode characters work with ^ and $ for multiline patterns
216 shouldBe('"Testing\\n\u{1234} 1 2 3".match(/^[\u{1000}-\u{100ff}] 1 2 3/um)[0]', '"\u{1234} 1 2 3"');
217 shouldBe('"Testing\\n\u{100f0} 1 2 3".match(/^[\u{1000}-\u{100ff}] 1 2 3/um)[0]', '"\u{100f0} 1 2 3"');
218 shouldBe('"g\\n\u{1234} 1 2 3".match(/g\\n^[\u{1000}-\u{100ff}] 1 2 3/um)[0]', '"g\\n\u{1234} 1 2 3"');
219 shouldBe('"g\\n\u{100f0} 1 2 3".match(/g\\n^[\u{1000}-\u{100ff}] 1 2 3/um)[0]', '"g\\n\u{100f0} 1 2 3"');
220 shouldBe('"Testing \u{1234}\\n1 2 3".match(/Testing [\u{1000}-\u{100ff}]$/um)[0]', '"Testing \u{1234}"');
221 shouldBe('"Testing \u{100f0}\\n1 2 3".match(/Testing [\u{1000}-\u{100ff}]$/um)[0]', '"Testing \u{100f0}"');
222 shouldBe('"Testing \u{1234}\\n1 2 3".match(/g [\u{1000}-\u{100ff}]$\\n1/um)[0]', '"g \u{1234}\\n1"');
223 shouldBe('"Testing \u{100f0}\\n1 2 3".match(/g [\u{1000}-\u{100ff}]$\\n1/um)[0]', '"g \u{100f0}\\n1"');
224
225 // Check that control letter escapes work with unicode flag
226 shouldBe('"this is b\ba test".match(/is b\\cha test/u)[0].length', '11');
227
228 // Check that invalid unicode patterns throw exceptions
229 shouldBe('new RegExp("\\\\/", "u").source', '"\\\\/"');
230 shouldThrow('r = new RegExp("\\\\u{110000}", "u")', '"SyntaxError: Invalid regular expression: invalid Unicode {} escape"');
231 shouldThrow('r = new RegExp("\u{10405}{2147483648}", "u")', '"SyntaxError: Invalid regular expression: pattern exceeds string length limits"');
232 shouldThrow('/{/u', '"SyntaxError: Invalid regular expression: incomplete {} quantifier for Unicode pattern"');
233 shouldThrow('/[a-\\d]/u', '"SyntaxError: Invalid regular expression: invalid range in character class for Unicode pattern"');
234 shouldThrow('/]/u', '"SyntaxError: Invalid regular expression: unmatched ] or } bracket for Unicode pattern"');
235 shouldThrow('/\\c9/u', '"SyntaxError: Invalid regular expression: invalid \\\\c escape for Unicode pattern"');
236
237 var invalidEscapeException = "SyntaxError: Invalid regular expression: invalid escaped character for Unicode pattern";
238 var newRegExp;
239
240 function shouldThrowInvalidEscape(pattern, error='invalidEscapeException')
241 {
242     newRegExp = 'r = new RegExp("' + pattern + '", "u")';
243
244     shouldThrow(newRegExp, error);
245 }
246
247 shouldThrowInvalidEscape("\\\\-");
248 shouldThrowInvalidEscape("\\\\a");
249 shouldThrowInvalidEscape("[\\\\a]");
250 shouldThrowInvalidEscape("[\\\\b]");
251 shouldThrowInvalidEscape("[\\\\B]");
252 shouldThrowInvalidEscape("\\\\x");
253 shouldThrowInvalidEscape("[\\\\x]");
254 shouldThrowInvalidEscape("\\\\u");
255 shouldThrowInvalidEscape("[\\\\u]");
256
257 shouldThrowInvalidEscape("\\\\u{", '"SyntaxError: Invalid regular expression: invalid Unicode {} escape"');
258 shouldThrowInvalidEscape("\\\\u{\\udead", '"SyntaxError: Invalid regular expression: invalid Unicode {} escape"');
259
260 // Check that invalid backreferences in unicode patterns throw exceptions.
261 shouldThrow(`/\\1/u`);
262 shouldThrow(`/\\2/u`);
263 shouldThrow(`/\\3/u`);
264 shouldThrow(`/\\4/u`);
265 shouldThrow(`/\\5/u`);
266 shouldThrow(`/\\6/u`);
267 shouldThrow(`/\\7/u`);
268 shouldThrow(`/\\8/u`);
269 shouldThrow(`/\\9/u`);
270 shouldNotThrow(`/(.)\\1/u`);
271 shouldNotThrow(`/(.)(.)\\2/u`);
272 shouldThrow(`/(.)(.)\\3/u`);
273
274 // Invalid backreferences are okay in non-unicode patterns.
275 shouldNotThrow(`/\\1/`);
276 shouldNotThrow(`/\\2/`);
277 shouldNotThrow(`/\\3/`);
278 shouldNotThrow(`/\\4/`);
279 shouldNotThrow(`/\\5/`);
280 shouldNotThrow(`/\\6/`);
281 shouldNotThrow(`/\\7/`);
282 shouldNotThrow(`/\\8/`);
283 shouldNotThrow(`/\\9/`);