| 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 | |
| 107 // ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S ) | 106 // ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S ) |
| 108 // Also takes an optional exec method in case our caller | 107 // Also takes an optional exec method in case our caller |
| 109 // has already fetched exec. | 108 // has already fetched exec. |
| 110 function RegExpSubclassExec(regexp, string, exec) { | 109 function RegExpSubclassExec(regexp, string, exec) { |
| 111 if (IS_UNDEFINED(exec)) { | 110 if (IS_UNDEFINED(exec)) { |
| 112 exec = regexp.exec; | 111 exec = regexp.exec; |
| 113 } | 112 } |
| 114 if (IS_CALLABLE(exec)) { | 113 if (IS_CALLABLE(exec)) { |
| 115 var result = %_Call(exec, regexp, string); | 114 var result = %_Call(exec, regexp, string); |
| 116 if (!IS_RECEIVER(result) && !IS_NULL(result)) { | 115 if (!IS_RECEIVER(result) && !IS_NULL(result)) { |
| 117 throw %make_type_error(kInvalidRegExpExecResult); | 116 throw %make_type_error(kInvalidRegExpExecResult); |
| 118 } | 117 } |
| 119 return result; | 118 return result; |
| 120 } | 119 } |
| 121 return %_Call(RegExpExecJS, regexp, string); | 120 return %_Call(RegExpExecJS, regexp, string); |
| 122 } | 121 } |
| 123 %SetForceInlineFlag(RegExpSubclassExec); | 122 %SetForceInlineFlag(RegExpSubclassExec); |
| 124 | 123 |
| 125 | 124 |
| 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 | |
| 139 function AtSurrogatePair(subject, index) { | 125 function AtSurrogatePair(subject, index) { |
| 140 if (index + 1 >= subject.length) return false; | 126 if (index + 1 >= subject.length) return false; |
| 141 var first = %_StringCharCodeAt(subject, index); | 127 var first = %_StringCharCodeAt(subject, index); |
| 142 if (first < 0xD800 || first > 0xDBFF) return false; | 128 if (first < 0xD800 || first > 0xDBFF) return false; |
| 143 var second = %_StringCharCodeAt(subject, index + 1); | 129 var second = %_StringCharCodeAt(subject, index + 1); |
| 144 return second >= 0xDC00 && second <= 0xDFFF; | 130 return second >= 0xDC00 && second <= 0xDFFF; |
| 145 } | 131 } |
| 146 | 132 |
| 147 | 133 |
| 148 // Fast path implementation of RegExp.prototype[Symbol.split] which | 134 // Fast path implementation of RegExp.prototype[Symbol.split] which |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 282 } | 268 } |
| 283 } | 269 } |
| 284 } | 270 } |
| 285 %AddElement(array, arrayIndex, | 271 %AddElement(array, arrayIndex, |
| 286 %_SubString(string, prevStringIndex, size)); | 272 %_SubString(string, prevStringIndex, size)); |
| 287 return array; | 273 return array; |
| 288 } | 274 } |
| 289 %FunctionRemovePrototype(RegExpSubclassSplit); | 275 %FunctionRemovePrototype(RegExpSubclassSplit); |
| 290 | 276 |
| 291 | 277 |
| 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 | |
| 325 // Legacy implementation of RegExp.prototype[Symbol.replace] which | 278 // Legacy implementation of RegExp.prototype[Symbol.replace] which |
| 326 // doesn't properly call the underlying exec method. | 279 // doesn't properly call the underlying exec method. |
| 327 | 280 |
| 328 // TODO(lrn): This array will survive indefinitely if replace is never | 281 // TODO(lrn): This array will survive indefinitely if replace is never |
| 329 // called again. However, it will be empty, since the contents are cleared | 282 // called again. However, it will be empty, since the contents are cleared |
| 330 // in the finally block. | 283 // in the finally block. |
| 331 var reusableReplaceArray = new InternalArray(4); | 284 var reusableReplaceArray = new InternalArray(4); |
| 332 | 285 |
| 333 // Helper function for replacing regular expressions with the result of a | 286 // Helper function for replacing regular expressions with the result of a |
| 334 // function application in String.prototype.replace. | 287 // function application in String.prototype.replace. |
| (...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 709 %_SubString(string, nextSourcePosition, position) + replacement; | 662 %_SubString(string, nextSourcePosition, position) + replacement; |
| 710 nextSourcePosition = position + matchedLength; | 663 nextSourcePosition = position + matchedLength; |
| 711 } | 664 } |
| 712 } | 665 } |
| 713 if (nextSourcePosition >= length) return accumulatedResult; | 666 if (nextSourcePosition >= length) return accumulatedResult; |
| 714 return accumulatedResult + %_SubString(string, nextSourcePosition, length); | 667 return accumulatedResult + %_SubString(string, nextSourcePosition, length); |
| 715 } | 668 } |
| 716 %FunctionRemovePrototype(RegExpSubclassReplace); | 669 %FunctionRemovePrototype(RegExpSubclassReplace); |
| 717 | 670 |
| 718 | 671 |
| 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 | |
| 737 | 672 |
| 738 // ------------------------------------------------------------------- | 673 // ------------------------------------------------------------------- |
| 739 | 674 |
| 740 utils.InstallFunctions(GlobalRegExp.prototype, DONT_ENUM, [ | 675 utils.InstallFunctions(GlobalRegExp.prototype, DONT_ENUM, [ |
| 741 "test", RegExpSubclassTest, | |
| 742 matchSymbol, RegExpSubclassMatch, | |
| 743 replaceSymbol, RegExpSubclassReplace, | 676 replaceSymbol, RegExpSubclassReplace, |
| 744 searchSymbol, RegExpSubclassSearch, | |
| 745 splitSymbol, RegExpSubclassSplit, | 677 splitSymbol, RegExpSubclassSplit, |
| 746 ]); | 678 ]); |
| 747 | 679 |
| 748 %InstallToContext(["regexp_last_match_info", RegExpLastMatchInfo]); | 680 %InstallToContext(["regexp_last_match_info", RegExpLastMatchInfo]); |
| 749 | 681 |
| 750 // ------------------------------------------------------------------- | 682 // ------------------------------------------------------------------- |
| 751 // Internal | 683 // Internal |
| 752 | 684 |
| 753 var InternalRegExpMatchInfo = { | 685 var InternalRegExpMatchInfo = { |
| 754 REGEXP_NUMBER_OF_CAPTURES: 2, | 686 REGEXP_NUMBER_OF_CAPTURES: 2, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 778 to.GetSubstitution = GetSubstitution; | 710 to.GetSubstitution = GetSubstitution; |
| 779 to.InternalRegExpMatch = InternalRegExpMatch; | 711 to.InternalRegExpMatch = InternalRegExpMatch; |
| 780 to.InternalRegExpReplace = InternalRegExpReplace; | 712 to.InternalRegExpReplace = InternalRegExpReplace; |
| 781 to.IsRegExp = IsRegExp; | 713 to.IsRegExp = IsRegExp; |
| 782 to.RegExpExec = DoRegExpExec; | 714 to.RegExpExec = DoRegExpExec; |
| 783 to.RegExpInitialize = RegExpInitialize; | 715 to.RegExpInitialize = RegExpInitialize; |
| 784 to.RegExpLastMatchInfo = RegExpLastMatchInfo; | 716 to.RegExpLastMatchInfo = RegExpLastMatchInfo; |
| 785 }); | 717 }); |
| 786 | 718 |
| 787 }) | 719 }) |
| OLD | NEW |