| 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 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 var matchInfo = DoRegExpExec(regexp, subject, 0); | 380 var matchInfo = DoRegExpExec(regexp, subject, 0); |
| 381 if (IS_NULL(matchInfo)) return subject; | 381 if (IS_NULL(matchInfo)) return subject; |
| 382 | 382 |
| 383 var result = new ReplaceResultBuilder(subject); | 383 var result = new ReplaceResultBuilder(subject); |
| 384 // There's at least one match. If the regexp is global, we have to loop | 384 // There's at least one match. If the regexp is global, we have to loop |
| 385 // over all matches. The loop is not in C++ code here like the one in | 385 // over all matches. The loop is not in C++ code here like the one in |
| 386 // RegExp.prototype.exec, because of the interleaved function application. | 386 // RegExp.prototype.exec, because of the interleaved function application. |
| 387 // Unfortunately, that means this code is nearly duplicated, here and in | 387 // Unfortunately, that means this code is nearly duplicated, here and in |
| 388 // jsregexp.cc. | 388 // jsregexp.cc. |
| 389 if (regexp.global) { | 389 if (regexp.global) { |
| 390 var numberOfCaptures = NUMBER_OF_CAPTURES(matchInfo) >> 1; | |
| 391 var previous = 0; | 390 var previous = 0; |
| 392 do { | 391 var startOfMatch; |
| 393 var startOfMatch = matchInfo[CAPTURE0]; | 392 if (NUMBER_OF_CAPTURES(matchInfo) == 2) { |
| 394 result.addSpecialSlice(previous, startOfMatch); | 393 // Both branches contain essentially the same loop except for the call |
| 395 previous = matchInfo[CAPTURE1]; | 394 // to the replace function. The branch is put outside of the loop for |
| 396 if (numberOfCaptures == 1) { | 395 // speed |
| 396 do { |
| 397 startOfMatch = matchInfo[CAPTURE0]; |
| 398 result.addSpecialSlice(previous, startOfMatch); |
| 399 previous = matchInfo[CAPTURE1]; |
| 397 var match = SubString(subject, startOfMatch, previous); | 400 var match = SubString(subject, startOfMatch, previous); |
| 398 // Don't call directly to avoid exposing the built-in global object. | 401 // Don't call directly to avoid exposing the built-in global object. |
| 399 result.add(replace.call(null, match, startOfMatch, subject)); | 402 result.add(replace.call(null, match, startOfMatch, subject)); |
| 400 } else { | 403 // Can't use matchInfo any more from here, since the function could |
| 404 // overwrite it. |
| 405 // Continue with the next match. |
| 406 // Increment previous if we matched an empty string, as per ECMA-262 |
| 407 // 15.5.4.10. |
| 408 if (previous == startOfMatch) { |
| 409 // Add the skipped character to the output, if any. |
| 410 if (previous < subject.length) { |
| 411 result.addSpecialSlice(previous, previous + 1); |
| 412 } |
| 413 previous++; |
| 414 // Per ECMA-262 15.10.6.2, if the previous index is greater than the |
| 415 // string length, there is no match |
| 416 if (previous > subject.length) { |
| 417 return result.generate(); |
| 418 } |
| 419 } |
| 420 matchInfo = DoRegExpExec(regexp, subject, previous); |
| 421 } while (!IS_NULL(matchInfo)); |
| 422 } else { |
| 423 do { |
| 424 startOfMatch = matchInfo[CAPTURE0]; |
| 425 result.addSpecialSlice(previous, startOfMatch); |
| 426 previous = matchInfo[CAPTURE1]; |
| 401 result.add(ApplyReplacementFunction(replace, matchInfo, subject)); | 427 result.add(ApplyReplacementFunction(replace, matchInfo, subject)); |
| 402 } | 428 // Can't use matchInfo any more from here, since the function could |
| 403 // Can't use matchInfo any more from here, since the function could | 429 // overwrite it. |
| 404 // overwrite it. | 430 // Continue with the next match. |
| 405 // Continue with the next match. | 431 // Increment previous if we matched an empty string, as per ECMA-262 |
| 406 // Increment previous if we matched an empty string, as per ECMA-262 | 432 // 15.5.4.10. |
| 407 // 15.5.4.10. | 433 if (previous == startOfMatch) { |
| 408 if (previous == startOfMatch) { | 434 // Add the skipped character to the output, if any. |
| 409 // Add the skipped character to the output, if any. | 435 if (previous < subject.length) { |
| 410 if (previous < subject.length) { | 436 result.addSpecialSlice(previous, previous + 1); |
| 411 result.addSpecialSlice(previous, previous + 1); | 437 } |
| 438 previous++; |
| 439 // Per ECMA-262 15.10.6.2, if the previous index is greater than the |
| 440 // string length, there is no match |
| 441 if (previous > subject.length) { |
| 442 return result.generate(); |
| 443 } |
| 412 } | 444 } |
| 413 previous++; | 445 matchInfo = DoRegExpExec(regexp, subject, previous); |
| 414 } | 446 } while (!IS_NULL(matchInfo)); |
| 447 } |
| 415 | 448 |
| 416 // Per ECMA-262 15.10.6.2, if the previous index is greater than the | 449 // Tack on the final right substring after the last match. |
| 417 // string length, there is no match | 450 result.addSpecialSlice(previous, subject.length); |
| 418 matchInfo = (previous > subject.length) | |
| 419 ? null | |
| 420 : DoRegExpExec(regexp, subject, previous); | |
| 421 } while (!IS_NULL(matchInfo)); | |
| 422 | 451 |
| 423 // Tack on the final right substring after the last match, if necessary. | |
| 424 if (previous < subject.length) { | |
| 425 result.addSpecialSlice(previous, subject.length); | |
| 426 } | |
| 427 } else { // Not a global regexp, no need to loop. | 452 } else { // Not a global regexp, no need to loop. |
| 428 result.addSpecialSlice(0, matchInfo[CAPTURE0]); | 453 result.addSpecialSlice(0, matchInfo[CAPTURE0]); |
| 429 var endOfMatch = matchInfo[CAPTURE1]; | 454 var endOfMatch = matchInfo[CAPTURE1]; |
| 430 result.add(ApplyReplacementFunction(replace, matchInfo, subject)); | 455 result.add(ApplyReplacementFunction(replace, matchInfo, subject)); |
| 431 // Can't use matchInfo any more from here, since the function could | 456 // Can't use matchInfo any more from here, since the function could |
| 432 // overwrite it. | 457 // overwrite it. |
| 433 result.addSpecialSlice(endOfMatch, subject.length); | 458 result.addSpecialSlice(endOfMatch, subject.length); |
| 434 } | 459 } |
| 435 | 460 |
| 436 return result.generate(); | 461 return result.generate(); |
| (...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 910 "small", StringSmall, | 935 "small", StringSmall, |
| 911 "strike", StringStrike, | 936 "strike", StringStrike, |
| 912 "sub", StringSub, | 937 "sub", StringSub, |
| 913 "sup", StringSup, | 938 "sup", StringSup, |
| 914 "toJSON", StringToJSON | 939 "toJSON", StringToJSON |
| 915 )); | 940 )); |
| 916 } | 941 } |
| 917 | 942 |
| 918 | 943 |
| 919 SetupString(); | 944 SetupString(); |
| OLD | NEW |