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 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 | 168 |
169 var this_str = TO_STRING_INLINE(this); | 169 var this_str = TO_STRING_INLINE(this); |
170 var other_str = TO_STRING_INLINE(other); | 170 var other_str = TO_STRING_INLINE(other); |
171 return %StringLocaleCompare(this_str, other_str); | 171 return %StringLocaleCompare(this_str, other_str); |
172 } | 172 } |
173 | 173 |
174 | 174 |
175 // ECMA-262 section 15.5.4.10 | 175 // ECMA-262 section 15.5.4.10 |
176 function StringMatch(regexp) { | 176 function StringMatch(regexp) { |
177 var subject = TO_STRING_INLINE(this); | 177 var subject = TO_STRING_INLINE(this); |
178 if (IS_REGEXP(regexp)) { | 178 if (IS_REGEXP(regexp)) { |
179 if (!regexp.global) return regexp.exec(subject); | 179 if (!regexp.global) return regexp.exec(subject); |
180 | 180 |
181 var cache = regExpCache; | 181 var cache = regExpCache; |
182 var saveAnswer = false; | 182 var saveAnswer = false; |
183 | 183 |
184 if (%_ObjectEquals(cache.type, 'match') && | 184 if (%_ObjectEquals(cache.type, 'match') && |
185 %_ObjectEquals(cache.regExp, regexp) && | 185 %_ObjectEquals(cache.regExp, regexp) && |
186 %_ObjectEquals(cache.subject, subject)) { | 186 %_ObjectEquals(cache.subject, subject)) { |
187 if (cache.answerSaved) { | 187 if (cache.answerSaved) { |
188 return CloneDenseArray(cache.answer); | 188 return CloneDenseArray(cache.answer); |
189 } else { | 189 } else { |
190 saveAnswer = true; | 190 saveAnswer = true; |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 var resultArray = reusableReplaceArray; | 428 var resultArray = reusableReplaceArray; |
429 if (resultArray) { | 429 if (resultArray) { |
430 reusableReplaceArray = null; | 430 reusableReplaceArray = null; |
431 } else { | 431 } else { |
432 // Inside a nested replace (replace called from the replacement function | 432 // Inside a nested replace (replace called from the replacement function |
433 // of another replace) or we have failed to set the reusable array | 433 // of another replace) or we have failed to set the reusable array |
434 // back due to an exception in a replacement function. Create a new | 434 // back due to an exception in a replacement function. Create a new |
435 // array to use in the future, or until the original is written back. | 435 // array to use in the future, or until the original is written back. |
436 resultArray = $Array(16); | 436 resultArray = $Array(16); |
437 } | 437 } |
438 try { | 438 |
439 // Must handle exceptions thrown by the replace functions correctly, | 439 var res = %RegExpExecMultiple(regexp, |
440 // including unregistering global regexps. | 440 subject, |
441 var res = %RegExpExecMultiple(regexp, | 441 lastMatchInfo, |
442 subject, | 442 resultArray); |
443 lastMatchInfo, | 443 regexp.lastIndex = 0; |
444 resultArray); | 444 if (IS_NULL(res)) { |
445 regexp.lastIndex = 0; | 445 // No matches at all. |
446 if (IS_NULL(res)) { | 446 return subject; |
447 // No matches at all. | 447 } |
448 return subject; | 448 var len = res.length; |
| 449 var i = 0; |
| 450 if (NUMBER_OF_CAPTURES(lastMatchInfo) == 2) { |
| 451 var match_start = 0; |
| 452 var override = [null, 0, subject]; |
| 453 while (i < len) { |
| 454 var elem = res[i]; |
| 455 if (%_IsSmi(elem)) { |
| 456 if (elem > 0) { |
| 457 match_start = (elem >> 11) + (elem & 0x7ff); |
| 458 } else { |
| 459 match_start = res[++i] - elem; |
| 460 } |
| 461 } else { |
| 462 override[0] = elem; |
| 463 override[1] = match_start; |
| 464 lastMatchInfoOverride = override; |
| 465 var func_result = replace.call(null, elem, match_start, subject); |
| 466 if (!IS_STRING(func_result)) { |
| 467 func_result = NonStringToString(func_result); |
| 468 } |
| 469 res[i] = func_result; |
| 470 match_start += elem.length; |
| 471 } |
| 472 i++; |
449 } | 473 } |
450 var len = res.length; | 474 } else { |
451 var i = 0; | 475 while (i < len) { |
452 if (NUMBER_OF_CAPTURES(lastMatchInfo) == 2) { | 476 var elem = res[i]; |
453 var match_start = 0; | 477 if (!%_IsSmi(elem)) { |
454 while (i < len) { | 478 // elem must be an Array. |
455 var elem = res[i]; | 479 // Use the apply argument as backing for global RegExp properties. |
456 if (%_IsSmi(elem)) { | 480 lastMatchInfoOverride = elem; |
457 if (elem > 0) { | 481 var func_result = replace.apply(null, elem); |
458 match_start = (elem >> 11) + (elem & 0x7ff); | 482 if (!IS_STRING(func_result)) { |
459 } else { | 483 func_result = NonStringToString(func_result); |
460 match_start = res[++i] - elem; | |
461 } | |
462 } else { | |
463 var func_result = replace.call(null, elem, match_start, subject); | |
464 if (!IS_STRING(func_result)) { | |
465 func_result = NonStringToString(func_result); | |
466 } | |
467 res[i] = func_result; | |
468 match_start += elem.length; | |
469 } | 484 } |
470 i++; | 485 res[i] = func_result; |
471 } | 486 } |
472 } else { | 487 i++; |
473 while (i < len) { | |
474 var elem = res[i]; | |
475 if (!%_IsSmi(elem)) { | |
476 // elem must be an Array. | |
477 // Use the apply argument as backing for global RegExp properties. | |
478 lastMatchInfoOverride = elem; | |
479 var func_result = replace.apply(null, elem); | |
480 if (!IS_STRING(func_result)) { | |
481 func_result = NonStringToString(func_result); | |
482 } | |
483 res[i] = func_result; | |
484 } | |
485 i++; | |
486 } | |
487 } | 488 } |
488 var result = new ReplaceResultBuilder(subject, res); | |
489 return result.generate(); | |
490 } finally { | |
491 lastMatchInfoOverride = null; | |
492 resultArray.length = 0; | |
493 reusableReplaceArray = resultArray; | |
494 } | 489 } |
| 490 var resultBuilder = new ReplaceResultBuilder(subject, res); |
| 491 var result = resultBuilder.generate(); |
| 492 resultArray.length = 0; |
| 493 reusableReplaceArray = resultArray; |
| 494 return result; |
495 } else { // Not a global regexp, no need to loop. | 495 } else { // Not a global regexp, no need to loop. |
496 var matchInfo = DoRegExpExec(regexp, subject, 0); | 496 var matchInfo = DoRegExpExec(regexp, subject, 0); |
497 if (IS_NULL(matchInfo)) return subject; | 497 if (IS_NULL(matchInfo)) return subject; |
498 | 498 |
499 var result = new ReplaceResultBuilder(subject); | 499 var result = new ReplaceResultBuilder(subject); |
500 result.addSpecialSlice(0, matchInfo[CAPTURE0]); | 500 result.addSpecialSlice(0, matchInfo[CAPTURE0]); |
501 var endOfMatch = matchInfo[CAPTURE1]; | 501 var endOfMatch = matchInfo[CAPTURE1]; |
502 result.add(ApplyReplacementFunction(replace, matchInfo, subject)); | 502 result.add(ApplyReplacementFunction(replace, matchInfo, subject)); |
503 // Can't use matchInfo any more from here, since the function could | 503 // Can't use matchInfo any more from here, since the function could |
504 // overwrite it. | 504 // overwrite it. |
(...skipping 30 matching lines...) Expand all Loading... |
535 if (IS_STRING(re)) { | 535 if (IS_STRING(re)) { |
536 regexp = %_GetFromCache(STRING_TO_REGEXP_CACHE_ID, re); | 536 regexp = %_GetFromCache(STRING_TO_REGEXP_CACHE_ID, re); |
537 } else if (IS_REGEXP(re)) { | 537 } else if (IS_REGEXP(re)) { |
538 regexp = re; | 538 regexp = re; |
539 } else { | 539 } else { |
540 regexp = new $RegExp(re); | 540 regexp = new $RegExp(re); |
541 } | 541 } |
542 var s = TO_STRING_INLINE(this); | 542 var s = TO_STRING_INLINE(this); |
543 var match = DoRegExpExec(regexp, s, 0); | 543 var match = DoRegExpExec(regexp, s, 0); |
544 if (match) { | 544 if (match) { |
545 lastMatchInfo = match; | |
546 return match[CAPTURE0]; | 545 return match[CAPTURE0]; |
547 } | 546 } |
548 return -1; | 547 return -1; |
549 } | 548 } |
550 | 549 |
551 | 550 |
552 // ECMA-262 section 15.5.4.13 | 551 // ECMA-262 section 15.5.4.13 |
553 function StringSlice(start, end) { | 552 function StringSlice(start, end) { |
554 var s = TO_STRING_INLINE(this); | 553 var s = TO_STRING_INLINE(this); |
555 var s_len = s.length; | 554 var s_len = s.length; |
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1004 "small", StringSmall, | 1003 "small", StringSmall, |
1005 "strike", StringStrike, | 1004 "strike", StringStrike, |
1006 "sub", StringSub, | 1005 "sub", StringSub, |
1007 "sup", StringSup, | 1006 "sup", StringSup, |
1008 "toJSON", StringToJSON | 1007 "toJSON", StringToJSON |
1009 )); | 1008 )); |
1010 } | 1009 } |
1011 | 1010 |
1012 | 1011 |
1013 SetupString(); | 1012 SetupString(); |
OLD | NEW |