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 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
201 %_Log('regexp', 'regexp-replace,%0r,%1S', [search, subject]); | 201 %_Log('regexp', 'regexp-replace,%0r,%1S', [search, subject]); |
202 if (IS_FUNCTION(replace)) { | 202 if (IS_FUNCTION(replace)) { |
203 if (search.global) { | 203 if (search.global) { |
204 return StringReplaceGlobalRegExpWithFunction(subject, search, replace); | 204 return StringReplaceGlobalRegExpWithFunction(subject, search, replace); |
205 } else { | 205 } else { |
206 return StringReplaceNonGlobalRegExpWithFunction(subject, | 206 return StringReplaceNonGlobalRegExpWithFunction(subject, |
207 search, | 207 search, |
208 replace); | 208 replace); |
209 } | 209 } |
210 } else { | 210 } else { |
211 return StringReplaceRegExp(subject, search, replace); | 211 return %StringReplaceRegExpWithString(subject, |
212 search, | |
213 TO_STRING_INLINE(replace), | |
214 lastMatchInfo); | |
212 } | 215 } |
213 } | 216 } |
214 | 217 |
215 // Convert the search argument to a string and search for it. | 218 // Convert the search argument to a string and search for it. |
216 search = TO_STRING_INLINE(search); | 219 if (!IS_STRING(search)) search = NonStringToString(search); |
217 var start = %StringIndexOf(subject, search, 0); | 220 var start = %StringIndexOf(subject, search, 0); |
218 if (start < 0) return subject; | 221 if (start < 0) return subject; |
219 var end = start + search.length; | 222 var end = start + search.length; |
220 | 223 |
221 var builder = new ReplaceResultBuilder(subject); | 224 var builder = new ReplaceResultBuilder(subject); |
222 // prefix | 225 // prefix |
223 builder.addSpecialSlice(0, start); | 226 builder.addSpecialSlice(0, start); |
224 | 227 |
225 // Compute the string to replace with. | 228 // Compute the string to replace with. |
226 if (IS_FUNCTION(replace)) { | 229 if (IS_FUNCTION(replace)) { |
227 builder.add(replace.call(null, search, start, subject)); | 230 builder.add(%_CallFunction(%GetGlobalReceiver(), |
231 search, | |
232 start, | |
233 subject, | |
234 replace)); | |
228 } else { | 235 } else { |
229 reusableMatchInfo[CAPTURE0] = start; | 236 reusableMatchInfo[CAPTURE0] = start; |
230 reusableMatchInfo[CAPTURE1] = end; | 237 reusableMatchInfo[CAPTURE1] = end; |
231 replace = TO_STRING_INLINE(replace); | 238 if (!IS_STRING(replace)) replace = NonStringToString(replace); |
Lasse Reichstein
2010/12/13 09:29:13
Is this really faster than the macro:
macro TO_ST
sandholm
2010/12/13 12:03:35
No, not really. I reverted this change.
| |
232 ExpandReplacement(replace, subject, reusableMatchInfo, builder); | 239 ExpandReplacement(replace, subject, reusableMatchInfo, builder); |
233 } | 240 } |
234 | 241 |
235 // suffix | 242 // suffix |
236 builder.addSpecialSlice(end, subject.length); | 243 builder.addSpecialSlice(end, subject.length); |
237 | 244 |
238 return builder.generate(); | 245 return builder.generate(); |
239 } | 246 } |
240 | 247 |
241 | 248 |
242 // Helper function for regular expressions in String.prototype.replace. | |
243 function StringReplaceRegExp(subject, regexp, replace) { | |
244 return %StringReplaceRegExpWithString(subject, | |
245 regexp, | |
246 TO_STRING_INLINE(replace), | |
247 lastMatchInfo); | |
248 } | |
249 | |
250 | |
251 // Expand the $-expressions in the string and return a new string with | 249 // Expand the $-expressions in the string and return a new string with |
252 // the result. | 250 // the result. |
253 function ExpandReplacement(string, subject, matchInfo, builder) { | 251 function ExpandReplacement(string, subject, matchInfo, builder) { |
254 var next = %StringIndexOf(string, '$', 0); | 252 var next = %StringIndexOf(string, '$', 0); |
255 if (next < 0) { | 253 if (next < 0) { |
256 builder.add(string); | 254 builder.add(string); |
257 return; | 255 return; |
258 } | 256 } |
259 | 257 |
260 // Compute the number of captures; see ECMA-262, 15.5.4.11, p. 102. | 258 // Compute the number of captures; see ECMA-262, 15.5.4.11, p. 102. |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
569 } | 567 } |
570 | 568 |
571 var currentIndex = 0; | 569 var currentIndex = 0; |
572 var startIndex = 0; | 570 var startIndex = 0; |
573 var result = []; | 571 var result = []; |
574 | 572 |
575 outer_loop: | 573 outer_loop: |
576 while (true) { | 574 while (true) { |
577 | 575 |
578 if (startIndex === length) { | 576 if (startIndex === length) { |
579 result[result.length] = subject.slice(currentIndex, length); | 577 result.push(subject.slice(currentIndex, length)); |
580 break; | 578 break; |
581 } | 579 } |
582 | 580 |
583 var matchInfo = splitMatch(separator, subject, currentIndex, startIndex); | 581 var matchInfo = splitMatch(separator, subject, currentIndex, startIndex); |
584 | 582 |
585 if (IS_NULL(matchInfo)) { | 583 if (IS_NULL(matchInfo)) { |
586 result[result.length] = subject.slice(currentIndex, length); | 584 result.push(subject.slice(currentIndex, length)); |
587 break; | 585 break; |
588 } | 586 } |
589 | 587 |
590 var endIndex = matchInfo[CAPTURE1]; | 588 var endIndex = matchInfo[CAPTURE1]; |
591 | 589 |
592 // We ignore a zero-length match at the currentIndex. | 590 // We ignore a zero-length match at the currentIndex. |
593 if (startIndex === endIndex && endIndex === currentIndex) { | 591 if (startIndex === endIndex && endIndex === currentIndex) { |
594 startIndex++; | 592 startIndex++; |
595 continue; | 593 continue; |
596 } | 594 } |
597 | 595 |
598 result[result.length] = SubString(subject, currentIndex, matchInfo[CAPTURE0] ); | 596 result.push(SubString(subject, currentIndex, matchInfo[CAPTURE0])); |
Lasse Reichstein
2010/12/13 09:29:13
No special casing of this substring?
sandholm
2010/12/13 12:03:35
I have only inlined SubString calls inside loops.
| |
599 if (result.length === limit) break; | 597 if (result.length === limit) break; |
600 | 598 |
601 var num_captures = NUMBER_OF_CAPTURES(matchInfo); | 599 var num_captures_plus3 = NUMBER_OF_CAPTURES(matchInfo) + 3; |
Lasse Reichstein
2010/12/13 09:29:13
Use REGEXP_FIRST_CAPTURE instead of 3.
sandholm
2010/12/13 12:03:35
Done.
| |
602 for (var i = 2; i < num_captures; i += 2) { | 600 for (var i = 5; i < num_captures_plus3; ) { |
Lasse Reichstein
2010/12/13 09:29:13
And REGEXP_FIRST_CAPTURE + 2 instead of 5.
sandholm
2010/12/13 12:03:35
Done.
| |
603 var start = matchInfo[CAPTURE(i)]; | 601 var start = matchInfo[i++]; |
604 var end = matchInfo[CAPTURE(i + 1)]; | 602 var end = matchInfo[i++]; |
605 if (start != -1 && end != -1) { | 603 if (end != -1) { |
606 result[result.length] = SubString(subject, start, end); | 604 if (start + 1 == end) { |
605 result.push(%_StringCharAt(subject, start)); | |
606 } else { | |
607 result.push(%_SubString(subject, start, end)); | |
608 } | |
607 } else { | 609 } else { |
608 result[result.length] = void 0; | 610 result.push(void 0); |
609 } | 611 } |
610 if (result.length === limit) break outer_loop; | 612 if (result.length === limit) break outer_loop; |
611 } | 613 } |
612 | 614 |
613 startIndex = currentIndex = endIndex; | 615 startIndex = currentIndex = endIndex; |
614 } | 616 } |
615 return result; | 617 return result; |
616 } | 618 } |
617 | 619 |
618 | 620 |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
929 "small", StringSmall, | 931 "small", StringSmall, |
930 "strike", StringStrike, | 932 "strike", StringStrike, |
931 "sub", StringSub, | 933 "sub", StringSub, |
932 "sup", StringSup, | 934 "sup", StringSup, |
933 "toJSON", StringToJSON | 935 "toJSON", StringToJSON |
934 )); | 936 )); |
935 } | 937 } |
936 | 938 |
937 | 939 |
938 SetupString(); | 940 SetupString(); |
OLD | NEW |