Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: src/string.js

Issue 1515005: Revert svn r4269 and r4298. (Closed)
Patch Set: Created 10 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/runtime.cc ('k') | src/version.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 387 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 // Scale the index. 398 // Scale the index.
399 var scaled = index << 1; 399 var scaled = index << 1;
400 // Compute start and end. 400 // Compute start and end.
401 var start = matchInfo[CAPTURE(scaled)]; 401 var start = matchInfo[CAPTURE(scaled)];
402 var end = matchInfo[CAPTURE(scaled + 1)]; 402 var end = matchInfo[CAPTURE(scaled + 1)];
403 // If either start or end is missing return. 403 // If either start or end is missing return.
404 if (start < 0 || end <= start) return; 404 if (start < 0 || end <= start) return;
405 builder.addSpecialSlice(start, end); 405 builder.addSpecialSlice(start, end);
406 }; 406 };
407 407
408 // TODO(lrn): This array will survive indefinitely if replace is never
409 // called again. However, it will be empty, since the contents are cleared
410 // in the finally block.
411 var reusableReplaceArray = $Array(16);
412 408
413 // Helper function for replacing regular expressions with the result of a 409 // Helper function for replacing regular expressions with the result of a
414 // function application in String.prototype.replace. 410 // function application in String.prototype.replace. The function application
411 // must be interleaved with the regexp matching (contrary to ECMA-262
412 // 15.5.4.11) to mimic SpiderMonkey and KJS behavior when the function uses
413 // the static properties of the RegExp constructor. Example:
414 // 'abcd'.replace(/(.)/g, function() { return RegExp.$1; }
415 // should be 'abcd' and not 'dddd' (or anything else).
415 function StringReplaceRegExpWithFunction(subject, regexp, replace) { 416 function StringReplaceRegExpWithFunction(subject, regexp, replace) {
417 var matchInfo = DoRegExpExec(regexp, subject, 0);
418 if (IS_NULL(matchInfo)) return subject;
419
420 var result = new ReplaceResultBuilder(subject);
421 // There's at least one match. If the regexp is global, we have to loop
422 // over all matches. The loop is not in C++ code here like the one in
423 // RegExp.prototype.exec, because of the interleaved function application.
424 // Unfortunately, that means this code is nearly duplicated, here and in
425 // jsregexp.cc.
416 if (regexp.global) { 426 if (regexp.global) {
417 var resultArray = reusableReplaceArray; 427 var previous = 0;
418 if (resultArray) { 428 var startOfMatch;
419 reusableReplaceArray = null; 429 if (NUMBER_OF_CAPTURES(matchInfo) == 2) {
430 // Both branches contain essentially the same loop except for the call
431 // to the replace function. The branch is put outside of the loop for
432 // speed
433 do {
434 startOfMatch = matchInfo[CAPTURE0];
435 result.addSpecialSlice(previous, startOfMatch);
436 previous = matchInfo[CAPTURE1];
437 var match = SubString(subject, startOfMatch, previous);
438 // Don't call directly to avoid exposing the built-in global object.
439 result.add(replace.call(null, match, startOfMatch, subject));
440 // Can't use matchInfo any more from here, since the function could
441 // overwrite it.
442 // Continue with the next match.
443 // Increment previous if we matched an empty string, as per ECMA-262
444 // 15.5.4.10.
445 if (previous == startOfMatch) {
446 // Add the skipped character to the output, if any.
447 if (previous < subject.length) {
448 result.addSpecialSlice(previous, previous + 1);
449 }
450 previous++;
451 // Per ECMA-262 15.10.6.2, if the previous index is greater than the
452 // string length, there is no match
453 if (previous > subject.length) {
454 return result.generate();
455 }
456 }
457 matchInfo = DoRegExpExec(regexp, subject, previous);
458 } while (!IS_NULL(matchInfo));
420 } else { 459 } else {
421 // Inside a nested replace (replace called from the replacement function 460 do {
422 // of another replace) or we have failed to set the reusable array 461 startOfMatch = matchInfo[CAPTURE0];
423 // back due to an exception in a replacement function. Create a new 462 result.addSpecialSlice(previous, startOfMatch);
424 // array to use in the future, or until the original is written back. 463 previous = matchInfo[CAPTURE1];
425 resultArray = $Array(16); 464 result.add(ApplyReplacementFunction(replace, matchInfo, subject));
465 // Can't use matchInfo any more from here, since the function could
466 // overwrite it.
467 // Continue with the next match.
468 // Increment previous if we matched an empty string, as per ECMA-262
469 // 15.5.4.10.
470 if (previous == startOfMatch) {
471 // Add the skipped character to the output, if any.
472 if (previous < subject.length) {
473 result.addSpecialSlice(previous, previous + 1);
474 }
475 previous++;
476 // Per ECMA-262 15.10.6.2, if the previous index is greater than the
477 // string length, there is no match
478 if (previous > subject.length) {
479 return result.generate();
480 }
481 }
482 matchInfo = DoRegExpExec(regexp, subject, previous);
483 } while (!IS_NULL(matchInfo));
426 } 484 }
427 try { 485
428 // Must handle exceptions thrown by the replace functions correctly, 486 // Tack on the final right substring after the last match.
429 // including unregistering global regexps. 487 result.addSpecialSlice(previous, subject.length);
430 var res = %RegExpExecMultiple(regexp, 488
431 subject,
432 lastMatchInfo,
433 resultArray);
434 regexp.lastIndex = 0;
435 if (IS_NULL(res)) {
436 // No matches at all.
437 return subject;
438 }
439 var len = res.length;
440 var i = 0;
441 if (NUMBER_OF_CAPTURES(lastMatchInfo) == 2) {
442 var match_start = 0;
443 while (i < len) {
444 var elem = res[i];
445 if (%_IsSmi(elem)) {
446 if (elem > 0) {
447 match_start = (elem >> 11) + (elem & 0x7ff);
448 } else {
449 match_start = res[++i] - elem;
450 }
451 } else {
452 var func_result = replace.call(null, elem, match_start, subject);
453 if (!IS_STRING(func_result)) func_result = TO_STRING(func_result);
454 res[i] = func_result;
455 match_start += elem.length;
456 }
457 i++;
458 }
459 } else {
460 while (i < len) {
461 var elem = res[i];
462 if (!%_IsSmi(elem)) {
463 // elem must be an Array.
464 // Use the apply argument as backing for global RegExp properties.
465 lastMatchInfoOverride = elem;
466 var func_result = replace.apply(null, elem);
467 if (!IS_STRING(func_result)) func_result = TO_STRING(func_result);
468 res[i] = func_result;
469 }
470 i++;
471 }
472 }
473 var result = new ReplaceResultBuilder(subject, res);
474 return result.generate();
475 } finally {
476 lastMatchInfoOverride = null;
477 resultArray.length = 0;
478 reusableReplaceArray = resultArray;
479 }
480 } else { // Not a global regexp, no need to loop. 489 } else { // Not a global regexp, no need to loop.
481 var matchInfo = DoRegExpExec(regexp, subject, 0);
482 if (IS_NULL(matchInfo)) return subject;
483
484 var result = new ReplaceResultBuilder(subject);
485 result.addSpecialSlice(0, matchInfo[CAPTURE0]); 490 result.addSpecialSlice(0, matchInfo[CAPTURE0]);
486 var endOfMatch = matchInfo[CAPTURE1]; 491 var endOfMatch = matchInfo[CAPTURE1];
487 result.add(ApplyReplacementFunction(replace, matchInfo, subject)); 492 result.add(ApplyReplacementFunction(replace, matchInfo, subject));
488 // Can't use matchInfo any more from here, since the function could 493 // Can't use matchInfo any more from here, since the function could
489 // overwrite it. 494 // overwrite it.
490 result.addSpecialSlice(endOfMatch, subject.length); 495 result.addSpecialSlice(endOfMatch, subject.length);
491 return result.generate();
492 } 496 }
497
498 return result.generate();
493 } 499 }
494 500
495 501
496 // Helper function to apply a string replacement function once. 502 // Helper function to apply a string replacement function once.
497 function ApplyReplacementFunction(replace, matchInfo, subject) { 503 function ApplyReplacementFunction(replace, matchInfo, subject) {
498 // Compute the parameter list consisting of the match, captures, index, 504 // Compute the parameter list consisting of the match, captures, index,
499 // and subject for the replace function invocation. 505 // and subject for the replace function invocation.
500 var index = matchInfo[CAPTURE0]; 506 var index = matchInfo[CAPTURE0];
501 // The number of captures plus one for the match. 507 // The number of captures plus one for the match.
502 var m = NUMBER_OF_CAPTURES(matchInfo) >> 1; 508 var m = NUMBER_OF_CAPTURES(matchInfo) >> 1;
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after
881 } 887 }
882 888
883 889
884 function StringSup() { 890 function StringSup() {
885 return "<sup>" + this + "</sup>"; 891 return "<sup>" + this + "</sup>";
886 } 892 }
887 893
888 894
889 // ReplaceResultBuilder support. 895 // ReplaceResultBuilder support.
890 function ReplaceResultBuilder(str) { 896 function ReplaceResultBuilder(str) {
891 if (%_ArgumentsLength() > 1) { 897 this.__proto__ = void 0;
892 this.elements = %_Arguments(1); 898 this.elements = new $Array();
893 } else {
894 this.elements = new $Array();
895 }
896 this.special_string = str; 899 this.special_string = str;
897 } 900 }
898 901
899 902
900 ReplaceResultBuilder.prototype.add = function(str) { 903 ReplaceResultBuilder.prototype.add = function(str) {
901 str = TO_STRING_INLINE(str); 904 str = TO_STRING_INLINE(str);
902 if (str.length > 0) { 905 if (str.length > 0) {
903 var elements = this.elements; 906 var elements = this.elements;
904 elements[elements.length] = str; 907 elements[elements.length] = str;
905 } 908 }
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
981 "small", StringSmall, 984 "small", StringSmall,
982 "strike", StringStrike, 985 "strike", StringStrike,
983 "sub", StringSub, 986 "sub", StringSub,
984 "sup", StringSup, 987 "sup", StringSup,
985 "toJSON", StringToJSON 988 "toJSON", StringToJSON
986 )); 989 ));
987 } 990 }
988 991
989 992
990 SetupString(); 993 SetupString();
OLDNEW
« no previous file with comments | « src/runtime.cc ('k') | src/version.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698