OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 } | 137 } |
138 } | 138 } |
139 } | 139 } |
140 if (index < 0) { | 140 if (index < 0) { |
141 return -1; | 141 return -1; |
142 } | 142 } |
143 return %StringLastIndexOf(sub, pat, index); | 143 return %StringLastIndexOf(sub, pat, index); |
144 } | 144 } |
145 | 145 |
146 | 146 |
147 function CloneDenseArray(array) { | |
148 if (array === null) return null; | |
149 var clone = new $Array(array.length); | |
150 for (var i = 0; i < array.length; i++) { | |
151 clone[i] = array[i]; | |
152 } | |
153 return clone; | |
154 } | |
155 | |
156 | |
157 // ECMA-262 section 15.5.4.9 | 147 // ECMA-262 section 15.5.4.9 |
158 // | 148 // |
159 // This function is implementation specific. For now, we do not | 149 // This function is implementation specific. For now, we do not |
160 // do anything locale specific. | 150 // do anything locale specific. |
161 function StringLocaleCompare(other) { | 151 function StringLocaleCompare(other) { |
162 if (%_ArgumentsLength() === 0) return 0; | 152 if (%_ArgumentsLength() === 0) return 0; |
163 | 153 |
164 var this_str = TO_STRING_INLINE(this); | 154 var this_str = TO_STRING_INLINE(this); |
165 var other_str = TO_STRING_INLINE(other); | 155 var other_str = TO_STRING_INLINE(other); |
166 return %StringLocaleCompare(this_str, other_str); | 156 return %StringLocaleCompare(this_str, other_str); |
167 } | 157 } |
168 | 158 |
169 | 159 |
170 // ECMA-262 section 15.5.4.10 | 160 // ECMA-262 section 15.5.4.10 |
171 function StringMatch(regexp) { | 161 function StringMatch(regexp) { |
172 var subject = TO_STRING_INLINE(this); | 162 var subject = TO_STRING_INLINE(this); |
173 if (IS_REGEXP(regexp)) { | 163 if (IS_REGEXP(regexp)) { |
174 if (!regexp.global) return regexp.exec(subject); | 164 if (!regexp.global) return regexp.exec(subject); |
175 | 165 |
176 var cache = regExpCache; | |
177 var saveAnswer = false; | 166 var saveAnswer = false; |
178 | 167 |
179 if (%_ObjectEquals(cache.type, 'match') && | |
180 %_IsRegExpEquivalent(cache.regExp, regexp) && | |
181 %_ObjectEquals(cache.subject, subject)) { | |
182 if (cache.answerSaved) { | |
183 return CloneDenseArray(cache.answer); | |
184 } else { | |
185 saveAnswer = true; | |
186 } | |
187 } | |
188 %_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]); | 168 %_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]); |
189 // lastMatchInfo is defined in regexp.js. | 169 // lastMatchInfo is defined in regexp.js. |
190 var result = %StringMatch(subject, regexp, lastMatchInfo); | 170 return %StringMatch(subject, regexp, lastMatchInfo); |
191 cache.type = 'match'; | |
192 cache.regExp = regexp; | |
193 cache.subject = subject; | |
194 if (saveAnswer) cache.answer = CloneDenseArray(result); | |
195 cache.answerSaved = saveAnswer; | |
196 return result; | |
197 } | 171 } |
198 // Non-regexp argument. | 172 // Non-regexp argument. |
199 regexp = new $RegExp(regexp); | 173 regexp = new $RegExp(regexp); |
200 // Don't check regexp exec cache, since the regexp is new. | |
201 // TODO(lrn): Change this if we start caching regexps here. | |
202 return RegExpExecNoTests(regexp, subject, 0); | 174 return RegExpExecNoTests(regexp, subject, 0); |
203 } | 175 } |
204 | 176 |
205 | 177 |
206 // SubString is an internal function that returns the sub string of 'string'. | 178 // SubString is an internal function that returns the sub string of 'string'. |
207 // If resulting string is of length 1, we use the one character cache | 179 // If resulting string is of length 1, we use the one character cache |
208 // otherwise we call the runtime system. | 180 // otherwise we call the runtime system. |
209 function SubString(string, start, end) { | 181 function SubString(string, start, end) { |
210 // Use the one character string cache. | 182 // Use the one character string cache. |
211 if (start + 1 == end) { | 183 if (start + 1 == end) { |
(...skipping 12 matching lines...) Expand all Loading... |
224 | 196 |
225 | 197 |
226 // ECMA-262, section 15.5.4.11 | 198 // ECMA-262, section 15.5.4.11 |
227 function StringReplace(search, replace) { | 199 function StringReplace(search, replace) { |
228 var subject = TO_STRING_INLINE(this); | 200 var subject = TO_STRING_INLINE(this); |
229 | 201 |
230 // Delegate to one of the regular expression variants if necessary. | 202 // Delegate to one of the regular expression variants if necessary. |
231 if (IS_REGEXP(search)) { | 203 if (IS_REGEXP(search)) { |
232 %_Log('regexp', 'regexp-replace,%0r,%1S', [search, subject]); | 204 %_Log('regexp', 'regexp-replace,%0r,%1S', [search, subject]); |
233 if (IS_FUNCTION(replace)) { | 205 if (IS_FUNCTION(replace)) { |
234 regExpCache.type = 'none'; | |
235 if (search.global) { | 206 if (search.global) { |
236 return StringReplaceGlobalRegExpWithFunction(subject, search, replace); | 207 return StringReplaceGlobalRegExpWithFunction(subject, search, replace); |
237 } else { | 208 } else { |
238 return StringReplaceNonGlobalRegExpWithFunction(subject, | 209 return StringReplaceNonGlobalRegExpWithFunction(subject, |
239 search, | 210 search, |
240 replace); | 211 replace); |
241 } | 212 } |
242 } else { | 213 } else { |
243 return StringReplaceRegExp(subject, search, replace); | 214 return StringReplaceRegExp(subject, search, replace); |
244 } | 215 } |
(...skipping 21 matching lines...) Expand all Loading... |
266 | 237 |
267 // suffix | 238 // suffix |
268 builder.addSpecialSlice(end, subject.length); | 239 builder.addSpecialSlice(end, subject.length); |
269 | 240 |
270 return builder.generate(); | 241 return builder.generate(); |
271 } | 242 } |
272 | 243 |
273 | 244 |
274 // Helper function for regular expressions in String.prototype.replace. | 245 // Helper function for regular expressions in String.prototype.replace. |
275 function StringReplaceRegExp(subject, regexp, replace) { | 246 function StringReplaceRegExp(subject, regexp, replace) { |
276 var cache = regExpCache; | 247 return %StringReplaceRegExpWithString(subject, |
277 if (%_ObjectEquals(cache.type, 'replace') && | 248 regexp, |
278 %_IsRegExpEquivalent(cache.regExp, regexp) && | 249 TO_STRING_INLINE(replace), |
279 %_ObjectEquals(cache.replaceString, replace) && | 250 lastMatchInfo); |
280 %_ObjectEquals(cache.subject, subject)) { | |
281 return cache.answer; | |
282 } | |
283 replace = TO_STRING_INLINE(replace); | |
284 var answer = %StringReplaceRegExpWithString(subject, | |
285 regexp, | |
286 replace, | |
287 lastMatchInfo); | |
288 cache.subject = subject; | |
289 cache.regExp = regexp; | |
290 cache.replaceString = replace; | |
291 cache.answer = answer; | |
292 cache.type = 'replace'; | |
293 return answer; | |
294 } | 251 } |
295 | 252 |
296 | 253 |
297 // Expand the $-expressions in the string and return a new string with | 254 // Expand the $-expressions in the string and return a new string with |
298 // the result. | 255 // the result. |
299 function ExpandReplacement(string, subject, matchInfo, builder) { | 256 function ExpandReplacement(string, subject, matchInfo, builder) { |
300 var next = %StringIndexOf(string, '$', 0); | 257 var next = %StringIndexOf(string, '$', 0); |
301 if (next < 0) { | 258 if (next < 0) { |
302 builder.add(string); | 259 builder.add(string); |
303 return; | 260 return; |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
598 var separator_length = separator.length; | 555 var separator_length = separator.length; |
599 | 556 |
600 // If the separator string is empty then return the elements in the subject. | 557 // If the separator string is empty then return the elements in the subject. |
601 if (separator_length === 0) return %StringToArray(subject); | 558 if (separator_length === 0) return %StringToArray(subject); |
602 | 559 |
603 var result = %StringSplit(subject, separator, limit); | 560 var result = %StringSplit(subject, separator, limit); |
604 | 561 |
605 return result; | 562 return result; |
606 } | 563 } |
607 | 564 |
608 var cache = regExpCache; | |
609 var saveAnswer = false; | 565 var saveAnswer = false; |
610 | 566 |
611 if (%_ObjectEquals(cache.type, 'split') && | |
612 %_IsRegExpEquivalent(cache.regExp, separator) && | |
613 %_ObjectEquals(cache.subject, subject) && | |
614 %_ObjectEquals(cache.splitLimit, limit)) { | |
615 if (cache.answerSaved) { | |
616 return CloneDenseArray(cache.answer); | |
617 } else { | |
618 saveAnswer = true; | |
619 } | |
620 } | |
621 | |
622 cache.type = 'split'; | |
623 cache.regExp = separator; | |
624 cache.subject = subject; | |
625 cache.splitLimit = limit; | |
626 | |
627 %_Log('regexp', 'regexp-split,%0S,%1r', [subject, separator]); | 567 %_Log('regexp', 'regexp-split,%0S,%1r', [subject, separator]); |
628 | 568 |
629 if (length === 0) { | 569 if (length === 0) { |
630 cache.answerSaved = true; | |
631 if (splitMatch(separator, subject, 0, 0) != null) { | 570 if (splitMatch(separator, subject, 0, 0) != null) { |
632 cache.answer = []; | |
633 return []; | 571 return []; |
634 } | 572 } |
635 cache.answer = [subject]; | |
636 return [subject]; | 573 return [subject]; |
637 } | 574 } |
638 | 575 |
639 var currentIndex = 0; | 576 var currentIndex = 0; |
640 var startIndex = 0; | 577 var startIndex = 0; |
641 var result = []; | 578 var result = []; |
642 | 579 |
643 outer_loop: | 580 outer_loop: |
644 while (true) { | 581 while (true) { |
645 | 582 |
(...skipping 27 matching lines...) Expand all Loading... |
673 if (start != -1 && end != -1) { | 610 if (start != -1 && end != -1) { |
674 result[result.length] = SubString(subject, start, end); | 611 result[result.length] = SubString(subject, start, end); |
675 } else { | 612 } else { |
676 result[result.length] = void 0; | 613 result[result.length] = void 0; |
677 } | 614 } |
678 if (result.length === limit) break outer_loop; | 615 if (result.length === limit) break outer_loop; |
679 } | 616 } |
680 | 617 |
681 startIndex = currentIndex = endIndex; | 618 startIndex = currentIndex = endIndex; |
682 } | 619 } |
683 if (saveAnswer) cache.answer = CloneDenseArray(result); | |
684 cache.answerSaved = saveAnswer; | |
685 return result; | 620 return result; |
686 } | 621 } |
687 | 622 |
688 | 623 |
689 // ECMA-262 section 15.5.4.14 | 624 // ECMA-262 section 15.5.4.14 |
690 // Helper function used by split. This version returns the matchInfo | 625 // Helper function used by split. This version returns the matchInfo |
691 // instead of allocating a new array with basically the same information. | 626 // instead of allocating a new array with basically the same information. |
692 function splitMatch(separator, subject, current_index, start_index) { | 627 function splitMatch(separator, subject, current_index, start_index) { |
693 var matchInfo = DoRegExpExec(separator, subject, start_index); | 628 var matchInfo = DoRegExpExec(separator, subject, start_index); |
694 if (matchInfo == null) return null; | 629 if (matchInfo == null) return null; |
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
999 "small", StringSmall, | 934 "small", StringSmall, |
1000 "strike", StringStrike, | 935 "strike", StringStrike, |
1001 "sub", StringSub, | 936 "sub", StringSub, |
1002 "sup", StringSup, | 937 "sup", StringSup, |
1003 "toJSON", StringToJSON | 938 "toJSON", StringToJSON |
1004 )); | 939 )); |
1005 } | 940 } |
1006 | 941 |
1007 | 942 |
1008 SetupString(); | 943 SetupString(); |
OLD | NEW |