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 |