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 |