| 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 |