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 (function(global, utils) { | 5 (function(global, utils) { |
6 | 6 |
7 'use strict'; | 7 'use strict'; |
8 | 8 |
9 %CheckIsBootstrapping(); | 9 %CheckIsBootstrapping(); |
10 | 10 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 if (start != -1) { | 96 if (start != -1) { |
97 end = MATCHINFO[j]; | 97 end = MATCHINFO[j]; |
98 result[i] = %_SubString(STRING, start, end); | 98 result[i] = %_SubString(STRING, start, end); |
99 } | 99 } |
100 j++; | 100 j++; |
101 } | 101 } |
102 return result; | 102 return result; |
103 endmacro | 103 endmacro |
104 | 104 |
105 | 105 |
| 106 |
106 // ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S ) | 107 // ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S ) |
107 // Also takes an optional exec method in case our caller | 108 // Also takes an optional exec method in case our caller |
108 // has already fetched exec. | 109 // has already fetched exec. |
109 function RegExpSubclassExec(regexp, string, exec) { | 110 function RegExpSubclassExec(regexp, string, exec) { |
110 if (IS_UNDEFINED(exec)) { | 111 if (IS_UNDEFINED(exec)) { |
111 exec = regexp.exec; | 112 exec = regexp.exec; |
112 } | 113 } |
113 if (IS_CALLABLE(exec)) { | 114 if (IS_CALLABLE(exec)) { |
114 var result = %_Call(exec, regexp, string); | 115 var result = %_Call(exec, regexp, string); |
115 if (!IS_RECEIVER(result) && !IS_NULL(result)) { | 116 if (!IS_RECEIVER(result) && !IS_NULL(result)) { |
116 throw %make_type_error(kInvalidRegExpExecResult); | 117 throw %make_type_error(kInvalidRegExpExecResult); |
117 } | 118 } |
118 return result; | 119 return result; |
119 } | 120 } |
120 return %_Call(RegExpExecJS, regexp, string); | 121 return %_Call(RegExpExecJS, regexp, string); |
121 } | 122 } |
122 %SetForceInlineFlag(RegExpSubclassExec); | 123 %SetForceInlineFlag(RegExpSubclassExec); |
123 | 124 |
124 | 125 |
| 126 // ES#sec-regexp.prototype.test RegExp.prototype.test ( S ) |
| 127 function RegExpSubclassTest(string) { |
| 128 if (!IS_RECEIVER(this)) { |
| 129 throw %make_type_error(kIncompatibleMethodReceiver, |
| 130 'RegExp.prototype.test', this); |
| 131 } |
| 132 string = TO_STRING(string); |
| 133 var match = RegExpSubclassExec(this, string); |
| 134 return !IS_NULL(match); |
| 135 } |
| 136 %FunctionRemovePrototype(RegExpSubclassTest); |
| 137 |
| 138 |
125 function AtSurrogatePair(subject, index) { | 139 function AtSurrogatePair(subject, index) { |
126 if (index + 1 >= subject.length) return false; | 140 if (index + 1 >= subject.length) return false; |
127 var first = %_StringCharCodeAt(subject, index); | 141 var first = %_StringCharCodeAt(subject, index); |
128 if (first < 0xD800 || first > 0xDBFF) return false; | 142 if (first < 0xD800 || first > 0xDBFF) return false; |
129 var second = %_StringCharCodeAt(subject, index + 1); | 143 var second = %_StringCharCodeAt(subject, index + 1); |
130 return second >= 0xDC00 && second <= 0xDFFF; | 144 return second >= 0xDC00 && second <= 0xDFFF; |
131 } | 145 } |
132 | 146 |
133 | 147 |
134 // Fast path implementation of RegExp.prototype[Symbol.split] which | 148 // Fast path implementation of RegExp.prototype[Symbol.split] which |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 } | 282 } |
269 } | 283 } |
270 } | 284 } |
271 %AddElement(array, arrayIndex, | 285 %AddElement(array, arrayIndex, |
272 %_SubString(string, prevStringIndex, size)); | 286 %_SubString(string, prevStringIndex, size)); |
273 return array; | 287 return array; |
274 } | 288 } |
275 %FunctionRemovePrototype(RegExpSubclassSplit); | 289 %FunctionRemovePrototype(RegExpSubclassSplit); |
276 | 290 |
277 | 291 |
| 292 // ES#sec-regexp.prototype-@@match |
| 293 // RegExp.prototype [ @@match ] ( string ) |
| 294 function RegExpSubclassMatch(string) { |
| 295 if (!IS_RECEIVER(this)) { |
| 296 throw %make_type_error(kIncompatibleMethodReceiver, |
| 297 "RegExp.prototype.@@match", this); |
| 298 } |
| 299 string = TO_STRING(string); |
| 300 var global = this.global; |
| 301 if (!global) return RegExpSubclassExec(this, string); |
| 302 var unicode = this.unicode; |
| 303 this.lastIndex = 0; |
| 304 var array = new InternalArray(); |
| 305 var n = 0; |
| 306 var result; |
| 307 while (true) { |
| 308 result = RegExpSubclassExec(this, string); |
| 309 if (IS_NULL(result)) { |
| 310 if (n === 0) return null; |
| 311 break; |
| 312 } |
| 313 var matchStr = TO_STRING(result[0]); |
| 314 array[n] = matchStr; |
| 315 if (matchStr === "") SetAdvancedStringIndex(this, string, unicode); |
| 316 n++; |
| 317 } |
| 318 var resultArray = []; |
| 319 %MoveArrayContents(array, resultArray); |
| 320 return resultArray; |
| 321 } |
| 322 %FunctionRemovePrototype(RegExpSubclassMatch); |
| 323 |
| 324 |
278 // Legacy implementation of RegExp.prototype[Symbol.replace] which | 325 // Legacy implementation of RegExp.prototype[Symbol.replace] which |
279 // doesn't properly call the underlying exec method. | 326 // doesn't properly call the underlying exec method. |
280 | 327 |
281 // TODO(lrn): This array will survive indefinitely if replace is never | 328 // TODO(lrn): This array will survive indefinitely if replace is never |
282 // called again. However, it will be empty, since the contents are cleared | 329 // called again. However, it will be empty, since the contents are cleared |
283 // in the finally block. | 330 // in the finally block. |
284 var reusableReplaceArray = new InternalArray(4); | 331 var reusableReplaceArray = new InternalArray(4); |
285 | 332 |
286 // Helper function for replacing regular expressions with the result of a | 333 // Helper function for replacing regular expressions with the result of a |
287 // function application in String.prototype.replace. | 334 // function application in String.prototype.replace. |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
662 %_SubString(string, nextSourcePosition, position) + replacement; | 709 %_SubString(string, nextSourcePosition, position) + replacement; |
663 nextSourcePosition = position + matchedLength; | 710 nextSourcePosition = position + matchedLength; |
664 } | 711 } |
665 } | 712 } |
666 if (nextSourcePosition >= length) return accumulatedResult; | 713 if (nextSourcePosition >= length) return accumulatedResult; |
667 return accumulatedResult + %_SubString(string, nextSourcePosition, length); | 714 return accumulatedResult + %_SubString(string, nextSourcePosition, length); |
668 } | 715 } |
669 %FunctionRemovePrototype(RegExpSubclassReplace); | 716 %FunctionRemovePrototype(RegExpSubclassReplace); |
670 | 717 |
671 | 718 |
| 719 // ES#sec-regexp.prototype-@@search |
| 720 // RegExp.prototype [ @@search ] ( string ) |
| 721 function RegExpSubclassSearch(string) { |
| 722 if (!IS_RECEIVER(this)) { |
| 723 throw %make_type_error(kIncompatibleMethodReceiver, |
| 724 "RegExp.prototype.@@search", this); |
| 725 } |
| 726 string = TO_STRING(string); |
| 727 var previousLastIndex = this.lastIndex; |
| 728 if (previousLastIndex != 0) this.lastIndex = 0; |
| 729 var result = RegExpSubclassExec(this, string); |
| 730 var currentLastIndex = this.lastIndex; |
| 731 if (currentLastIndex != previousLastIndex) this.lastIndex = previousLastIndex; |
| 732 if (IS_NULL(result)) return -1; |
| 733 return result.index; |
| 734 } |
| 735 %FunctionRemovePrototype(RegExpSubclassSearch); |
| 736 |
672 | 737 |
673 // ------------------------------------------------------------------- | 738 // ------------------------------------------------------------------- |
674 | 739 |
675 utils.InstallFunctions(GlobalRegExp.prototype, DONT_ENUM, [ | 740 utils.InstallFunctions(GlobalRegExp.prototype, DONT_ENUM, [ |
| 741 "test", RegExpSubclassTest, |
| 742 matchSymbol, RegExpSubclassMatch, |
676 replaceSymbol, RegExpSubclassReplace, | 743 replaceSymbol, RegExpSubclassReplace, |
| 744 searchSymbol, RegExpSubclassSearch, |
677 splitSymbol, RegExpSubclassSplit, | 745 splitSymbol, RegExpSubclassSplit, |
678 ]); | 746 ]); |
679 | 747 |
680 %InstallToContext(["regexp_last_match_info", RegExpLastMatchInfo]); | 748 %InstallToContext(["regexp_last_match_info", RegExpLastMatchInfo]); |
681 | 749 |
682 // ------------------------------------------------------------------- | 750 // ------------------------------------------------------------------- |
683 // Internal | 751 // Internal |
684 | 752 |
685 var InternalRegExpMatchInfo = { | 753 var InternalRegExpMatchInfo = { |
686 REGEXP_NUMBER_OF_CAPTURES: 2, | 754 REGEXP_NUMBER_OF_CAPTURES: 2, |
(...skipping 23 matching lines...) Expand all Loading... |
710 to.GetSubstitution = GetSubstitution; | 778 to.GetSubstitution = GetSubstitution; |
711 to.InternalRegExpMatch = InternalRegExpMatch; | 779 to.InternalRegExpMatch = InternalRegExpMatch; |
712 to.InternalRegExpReplace = InternalRegExpReplace; | 780 to.InternalRegExpReplace = InternalRegExpReplace; |
713 to.IsRegExp = IsRegExp; | 781 to.IsRegExp = IsRegExp; |
714 to.RegExpExec = DoRegExpExec; | 782 to.RegExpExec = DoRegExpExec; |
715 to.RegExpInitialize = RegExpInitialize; | 783 to.RegExpInitialize = RegExpInitialize; |
716 to.RegExpLastMatchInfo = RegExpLastMatchInfo; | 784 to.RegExpLastMatchInfo = RegExpLastMatchInfo; |
717 }); | 785 }); |
718 | 786 |
719 }) | 787 }) |
OLD | NEW |