Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 230 %_Log('regexp', 'regexp-replace,%0r,%1S', [search, subject]); | 230 %_Log('regexp', 'regexp-replace,%0r,%1S', [search, subject]); |
| 231 if (IS_SPEC_FUNCTION(replace)) { | 231 if (IS_SPEC_FUNCTION(replace)) { |
| 232 if (search.global) { | 232 if (search.global) { |
| 233 return StringReplaceGlobalRegExpWithFunction(subject, search, replace); | 233 return StringReplaceGlobalRegExpWithFunction(subject, search, replace); |
| 234 } else { | 234 } else { |
| 235 return StringReplaceNonGlobalRegExpWithFunction(subject, | 235 return StringReplaceNonGlobalRegExpWithFunction(subject, |
| 236 search, | 236 search, |
| 237 replace); | 237 replace); |
| 238 } | 238 } |
| 239 } else { | 239 } else { |
| 240 return %StringReplaceRegExpWithString(subject, | 240 if (lastMatchInfoOverride == null) { |
| 241 search, | 241 return %StringReplaceRegExpWithString(subject, |
| 242 TO_STRING_INLINE(replace), | 242 search, |
| 243 lastMatchInfo); | 243 TO_STRING_INLINE(replace), |
| 244 lastMatchInfo); | |
| 245 } else { | |
| 246 // We use this hack to detect whether StringReplaceRegExpWithString foun d | |
|
ulan
2012/04/23 16:59:23
Long line
Erik Corry
2012/04/23 18:54:02
Done.
| |
| 247 // at least one hit. In that case we need to remove any override. | |
| 248 var saved_subject = lastMatchInfo[LAST_SUBJECT_INDEX]; | |
| 249 lastMatchInfo[LAST_SUBJECT_INDEX] = 0; | |
|
ulan
2012/04/23 16:59:23
This is sad, but I don't see a better way.
Erik Corry
2012/04/23 18:54:02
Me neither.
| |
| 250 var answer = %StringReplaceRegExpWithString(subject, | |
| 251 search, | |
| 252 TO_STRING_INLINE(replace), | |
| 253 lastMatchInfo); | |
| 254 if (%_IsSmi(lastMatchInfo[LAST_SUBJECT_INDEX])) { | |
| 255 lastMatchInfo[LAST_SUBJECT_INDEX] = saved_subject; | |
| 256 } else { | |
| 257 lastMatchInfoOverride = null; | |
| 258 } | |
| 259 return answer; | |
| 260 } | |
| 244 } | 261 } |
| 245 } | 262 } |
| 246 | 263 |
| 247 // Convert the search argument to a string and search for it. | 264 // Convert the search argument to a string and search for it. |
| 248 search = TO_STRING_INLINE(search); | 265 search = TO_STRING_INLINE(search); |
| 249 if (search.length == 1 && | 266 if (search.length == 1 && |
| 250 subject.length > 0xFF && | 267 subject.length > 0xFF && |
| 251 IS_STRING(replace) && | 268 IS_STRING(replace) && |
| 252 %StringIndexOf(replace, '$', 0) < 0) { | 269 %StringIndexOf(replace, '$', 0) < 0) { |
| 253 // Searching by traversing a cons string tree and replace with cons of | 270 // Searching by traversing a cons string tree and replace with cons of |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 424 resultArray); | 441 resultArray); |
| 425 regexp.lastIndex = 0; | 442 regexp.lastIndex = 0; |
| 426 if (IS_NULL(res)) { | 443 if (IS_NULL(res)) { |
| 427 // No matches at all. | 444 // No matches at all. |
| 428 reusableReplaceArray = resultArray; | 445 reusableReplaceArray = resultArray; |
| 429 return subject; | 446 return subject; |
| 430 } | 447 } |
| 431 var len = res.length; | 448 var len = res.length; |
| 432 var i = 0; | 449 var i = 0; |
| 433 if (NUMBER_OF_CAPTURES(lastMatchInfo) == 2) { | 450 if (NUMBER_OF_CAPTURES(lastMatchInfo) == 2) { |
| 451 // If the number of captures is two then there are no explicit captures in | |
| 452 // the regexp, just the implicit capture that captures the whole match. In | |
| 453 // this case we can simplify quite a bit and end up with something faster. | |
| 454 // The builder will consist of some integers that indicate slices of the | |
| 455 // input string and some replacements that were returned from the replace | |
| 456 // function. | |
| 434 var match_start = 0; | 457 var match_start = 0; |
| 435 var override = new InternalArray(null, 0, subject); | 458 var override = new InternalArray(null, 0, subject); |
| 436 var receiver = %GetDefaultReceiver(replace); | 459 var receiver = %GetDefaultReceiver(replace); |
| 437 while (i < len) { | 460 // i is 0. |
| 461 for ( ; i < len; i++) { | |
|
ulan
2012/04/23 16:59:23
Can we make i local in the loop?
Erik Corry
2012/04/23 18:54:02
Well not really. This is JS, after all. But we c
| |
| 438 var elem = res[i]; | 462 var elem = res[i]; |
| 439 if (%_IsSmi(elem)) { | 463 if (%_IsSmi(elem)) { |
| 464 // Integers represent slices of the original string. Use these to | |
| 465 // get the offsets we need for the override array (so things like | |
| 466 // RegExp.leftContext work during the callback function. | |
| 440 if (elem > 0) { | 467 if (elem > 0) { |
| 441 match_start = (elem >> 11) + (elem & 0x7ff); | 468 match_start = (elem >> 11) + (elem & 0x7ff); |
| 442 } else { | 469 } else { |
| 443 match_start = res[++i] - elem; | 470 match_start = res[++i] - elem; |
| 444 } | 471 } |
| 445 } else { | 472 } else { |
| 446 override[0] = elem; | 473 override[0] = elem; |
| 447 override[1] = match_start; | 474 override[1] = match_start; |
| 448 lastMatchInfoOverride = override; | 475 lastMatchInfoOverride = override; |
| 449 var func_result = | 476 var func_result = |
| 450 %_CallFunction(receiver, elem, match_start, subject, replace); | 477 %_CallFunction(receiver, elem, match_start, subject, replace); |
| 478 // Overwrite the i'th element in the results with the string we got | |
| 479 // back from the callback function. | |
| 451 res[i] = TO_STRING_INLINE(func_result); | 480 res[i] = TO_STRING_INLINE(func_result); |
| 452 match_start += elem.length; | 481 match_start += elem.length; |
| 453 } | 482 } |
| 454 i++; | |
| 455 } | 483 } |
| 456 } else { | 484 } else { |
| 457 var receiver = %GetDefaultReceiver(replace); | 485 var receiver = %GetDefaultReceiver(replace); |
| 458 while (i < len) { | 486 // i is 0. |
| 487 for ( ; i < len; i++) { | |
|
ulan
2012/04/23 16:59:23
Can we make i local in the loop?
Erik Corry
2012/04/23 18:54:02
As above.
| |
| 459 var elem = res[i]; | 488 var elem = res[i]; |
| 460 if (!%_IsSmi(elem)) { | 489 if (!%_IsSmi(elem)) { |
| 461 // elem must be an Array. | 490 // elem must be an Array. |
| 462 // Use the apply argument as backing for global RegExp properties. | 491 // Use the apply argument as backing for global RegExp properties. |
| 463 lastMatchInfoOverride = elem; | 492 lastMatchInfoOverride = elem; |
| 464 var func_result = %Apply(replace, receiver, elem, 0, elem.length); | 493 var func_result = %Apply(replace, receiver, elem, 0, elem.length); |
| 494 // Overwrite the i'th element in the results with the string we got | |
| 495 // back from the callback function. | |
| 465 res[i] = TO_STRING_INLINE(func_result); | 496 res[i] = TO_STRING_INLINE(func_result); |
| 466 } | 497 } |
| 467 i++; | |
| 468 } | 498 } |
| 469 } | 499 } |
| 470 var resultBuilder = new ReplaceResultBuilder(subject, res); | 500 var resultBuilder = new ReplaceResultBuilder(subject, res); |
| 471 var result = resultBuilder.generate(); | 501 var result = resultBuilder.generate(); |
| 472 resultArray.length = 0; | 502 resultArray.length = 0; |
| 473 reusableReplaceArray = resultArray; | 503 reusableReplaceArray = resultArray; |
| 474 return result; | 504 return result; |
| 475 } | 505 } |
| 476 | 506 |
| 477 | 507 |
| (...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1011 "fixed", StringFixed, | 1041 "fixed", StringFixed, |
| 1012 "italics", StringItalics, | 1042 "italics", StringItalics, |
| 1013 "small", StringSmall, | 1043 "small", StringSmall, |
| 1014 "strike", StringStrike, | 1044 "strike", StringStrike, |
| 1015 "sub", StringSub, | 1045 "sub", StringSub, |
| 1016 "sup", StringSup | 1046 "sup", StringSup |
| 1017 )); | 1047 )); |
| 1018 } | 1048 } |
| 1019 | 1049 |
| 1020 SetUpString(); | 1050 SetUpString(); |
| OLD | NEW |