OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This file relies on the fact that the following declaration has been made | 5 // This file relies on the fact that the following declaration has been made |
6 // in runtime.js: | 6 // in runtime.js: |
7 // var $Object = global.Object; | 7 // var $Object = global.Object; |
8 // var $Array = global.Array; | 8 // var $Array = global.Array; |
9 | 9 |
10 var $RegExp = global.RegExp; | 10 var $RegExp = global.RegExp; |
11 | 11 |
12 // ------------------------------------------------------------------- | 12 // ------------------------------------------------------------------- |
13 | 13 |
14 // A recursive descent parser for Patterns according to the grammar of | 14 // A recursive descent parser for Patterns according to the grammar of |
15 // ECMA-262 15.10.1, with deviations noted below. | 15 // ECMA-262 15.10.1, with deviations noted below. |
16 function DoConstructRegExp(object, pattern, flags) { | 16 function DoConstructRegExp(object, pattern, flags) { |
17 // RegExp : Called as constructor; see ECMA-262, section 15.10.4. | 17 // RegExp : Called as constructor; see ECMA-262, section 15.10.4. |
18 if (IS_REGEXP(pattern)) { | 18 if (IS_REGEXP(pattern)) { |
19 if (!IS_UNDEFINED(flags)) { | 19 if (!IS_UNDEFINED(flags)) { |
20 throw MakeTypeError('regexp_flags', []); | 20 throw MakeTypeError('regexp_flags', []); |
21 } | 21 } |
22 flags = (pattern.global ? 'g' : '') | 22 flags = (pattern.global ? 'g' : '') |
23 + (pattern.ignoreCase ? 'i' : '') | 23 + (pattern.ignoreCase ? 'i' : '') |
24 + (pattern.multiline ? 'm' : ''); | 24 + (pattern.multiline ? 'm' : ''); |
25 if (%HarmonyRegExps()) | |
Yang
2014/09/15 09:23:16
While I'm fine with this (will be removed eventual
Erik Corry
2014/09/16 17:49:40
Done.
| |
26 flags += (pattern.sticky ? 'y' : ''); | |
25 pattern = pattern.source; | 27 pattern = pattern.source; |
26 } | 28 } |
27 | 29 |
28 pattern = IS_UNDEFINED(pattern) ? '' : ToString(pattern); | 30 pattern = IS_UNDEFINED(pattern) ? '' : ToString(pattern); |
29 flags = IS_UNDEFINED(flags) ? '' : ToString(flags); | 31 flags = IS_UNDEFINED(flags) ? '' : ToString(flags); |
30 | 32 |
31 var global = false; | 33 var global = false; |
32 var ignoreCase = false; | 34 var ignoreCase = false; |
33 var multiline = false; | 35 var multiline = false; |
36 var sticky = false; | |
34 for (var i = 0; i < flags.length; i++) { | 37 for (var i = 0; i < flags.length; i++) { |
35 var c = %_CallFunction(flags, i, StringCharAt); | 38 var c = %_CallFunction(flags, i, StringCharAt); |
36 switch (c) { | 39 switch (c) { |
37 case 'g': | 40 case 'g': |
38 if (global) { | 41 if (global) { |
39 throw MakeSyntaxError("invalid_regexp_flags", [flags]); | 42 throw MakeSyntaxError("invalid_regexp_flags", [flags]); |
40 } | 43 } |
41 global = true; | 44 global = true; |
42 break; | 45 break; |
43 case 'i': | 46 case 'i': |
44 if (ignoreCase) { | 47 if (ignoreCase) { |
45 throw MakeSyntaxError("invalid_regexp_flags", [flags]); | 48 throw MakeSyntaxError("invalid_regexp_flags", [flags]); |
46 } | 49 } |
47 ignoreCase = true; | 50 ignoreCase = true; |
48 break; | 51 break; |
49 case 'm': | 52 case 'm': |
50 if (multiline) { | 53 if (multiline) { |
51 throw MakeSyntaxError("invalid_regexp_flags", [flags]); | 54 throw MakeSyntaxError("invalid_regexp_flags", [flags]); |
52 } | 55 } |
53 multiline = true; | 56 multiline = true; |
54 break; | 57 break; |
58 case 'y': | |
59 if (!%HarmonyRegExps() || sticky) { | |
60 throw MakeSyntaxError("invalid_regexp_flags", [flags]); | |
61 } | |
62 sticky = true; | |
63 break; | |
55 default: | 64 default: |
56 throw MakeSyntaxError("invalid_regexp_flags", [flags]); | 65 throw MakeSyntaxError("invalid_regexp_flags", [flags]); |
57 } | 66 } |
58 } | 67 } |
59 | 68 |
60 %RegExpInitializeObject(object, pattern, global, ignoreCase, multiline); | 69 %RegExpInitializeObject(object, pattern, global, ignoreCase, multiline, sticky ); |
61 | 70 |
62 // Call internal function to compile the pattern. | 71 // Call internal function to compile the pattern. |
63 %RegExpCompile(object, pattern, flags); | 72 %RegExpCompile(object, pattern, flags); |
64 } | 73 } |
65 | 74 |
66 | 75 |
67 function RegExpConstructor(pattern, flags) { | 76 function RegExpConstructor(pattern, flags) { |
68 if (%_IsConstructCall()) { | 77 if (%_IsConstructCall()) { |
69 DoConstructRegExp(this, pattern, flags); | 78 DoConstructRegExp(this, pattern, flags); |
70 } else { | 79 } else { |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
220 } | 229 } |
221 lastMatchInfoOverride = null; | 230 lastMatchInfoOverride = null; |
222 this.lastIndex = lastMatchInfo[CAPTURE1]; | 231 this.lastIndex = lastMatchInfo[CAPTURE1]; |
223 return true; | 232 return true; |
224 } else { | 233 } else { |
225 // Non-global regexp. | 234 // Non-global regexp. |
226 // Remove irrelevant preceeding '.*' in a non-global test regexp. | 235 // Remove irrelevant preceeding '.*' in a non-global test regexp. |
227 // The expression checks whether this.source starts with '.*' and | 236 // The expression checks whether this.source starts with '.*' and |
228 // that the third char is not a '?'. | 237 // that the third char is not a '?'. |
229 var regexp = this; | 238 var regexp = this; |
230 if (%_StringCharCodeAt(regexp.source, 0) == 46 && // '.' | 239 if (!this.sticky && |
Yang
2014/09/15 09:23:16
We also need to record .lastIndex for sticky. If I
Erik Corry
2014/09/16 17:49:40
Done, and also added string length check.
| |
240 %_StringCharCodeAt(regexp.source, 0) == 46 && // '.' | |
231 %_StringCharCodeAt(regexp.source, 1) == 42 && // '*' | 241 %_StringCharCodeAt(regexp.source, 1) == 42 && // '*' |
232 %_StringCharCodeAt(regexp.source, 2) != 63) { // '?' | 242 %_StringCharCodeAt(regexp.source, 2) != 63) { // '?' |
233 regexp = TrimRegExp(regexp); | 243 regexp = TrimRegExp(regexp); |
234 } | 244 } |
235 // matchIndices is either null or the lastMatchInfo array. | 245 // matchIndices is either null or the lastMatchInfo array. |
236 var matchIndices = %_RegExpExec(regexp, string, 0, lastMatchInfo); | 246 var matchIndices = %_RegExpExec(regexp, string, 0, lastMatchInfo); |
237 if (IS_NULL(matchIndices)) { | 247 if (IS_NULL(matchIndices)) { |
238 this.lastIndex = 0; | 248 this.lastIndex = 0; |
239 return false; | 249 return false; |
240 } | 250 } |
(...skipping 16 matching lines...) Expand all Loading... | |
257 | 267 |
258 function RegExpToString() { | 268 function RegExpToString() { |
259 if (!IS_REGEXP(this)) { | 269 if (!IS_REGEXP(this)) { |
260 throw MakeTypeError('incompatible_method_receiver', | 270 throw MakeTypeError('incompatible_method_receiver', |
261 ['RegExp.prototype.toString', this]); | 271 ['RegExp.prototype.toString', this]); |
262 } | 272 } |
263 var result = '/' + this.source + '/'; | 273 var result = '/' + this.source + '/'; |
264 if (this.global) result += 'g'; | 274 if (this.global) result += 'g'; |
265 if (this.ignoreCase) result += 'i'; | 275 if (this.ignoreCase) result += 'i'; |
266 if (this.multiline) result += 'm'; | 276 if (this.multiline) result += 'm'; |
277 if (%HarmonyRegExps() && this.sticky) result += 'y'; | |
267 return result; | 278 return result; |
268 } | 279 } |
269 | 280 |
270 | 281 |
271 // Getters for the static properties lastMatch, lastParen, leftContext, and | 282 // Getters for the static properties lastMatch, lastParen, leftContext, and |
272 // rightContext of the RegExp constructor. The properties are computed based | 283 // rightContext of the RegExp constructor. The properties are computed based |
273 // on the captures array of the last successful match and the subject string | 284 // on the captures array of the last successful match and the subject string |
274 // of the last successful match. | 285 // of the last successful match. |
275 function RegExpGetLastMatch() { | 286 function RegExpGetLastMatch() { |
276 if (lastMatchInfoOverride !== null) { | 287 if (lastMatchInfoOverride !== null) { |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
455 | 466 |
456 for (var i = 1; i < 10; ++i) { | 467 for (var i = 1; i < 10; ++i) { |
457 %DefineAccessorPropertyUnchecked($RegExp, '$' + i, | 468 %DefineAccessorPropertyUnchecked($RegExp, '$' + i, |
458 RegExpMakeCaptureGetter(i), NoOpSetter, | 469 RegExpMakeCaptureGetter(i), NoOpSetter, |
459 DONT_DELETE); | 470 DONT_DELETE); |
460 } | 471 } |
461 %ToFastProperties($RegExp); | 472 %ToFastProperties($RegExp); |
462 } | 473 } |
463 | 474 |
464 SetUpRegExp(); | 475 SetUpRegExp(); |
OLD | NEW |