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

Side by Side Diff: src/js/regexp.js

Issue 2332333002: [regexp/string] Merge ExpandReplacement and GetSubstitution (Closed)
Patch Set: Fix test failures Created 4 years, 3 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 | « no previous file | src/js/string.js » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 (function(global, utils) { 5 (function(global, utils) {
6 6
7 %CheckIsBootstrapping(); 7 %CheckIsBootstrapping();
8 8
9 // ------------------------------------------------------------------- 9 // -------------------------------------------------------------------
10 // Imports 10 // Imports
11 11
12 var ExpandReplacement;
13 var GlobalArray = global.Array; 12 var GlobalArray = global.Array;
14 var GlobalObject = global.Object; 13 var GlobalObject = global.Object;
15 var GlobalRegExp = global.RegExp; 14 var GlobalRegExp = global.RegExp;
16 var GlobalRegExpPrototype; 15 var GlobalRegExpPrototype;
17 var InternalArray = utils.InternalArray; 16 var InternalArray = utils.InternalArray;
18 var InternalPackedArray = utils.InternalPackedArray; 17 var InternalPackedArray = utils.InternalPackedArray;
19 var MaxSimple; 18 var MaxSimple;
20 var MinSimple; 19 var MinSimple;
21 var matchSymbol = utils.ImportNow("match_symbol"); 20 var matchSymbol = utils.ImportNow("match_symbol");
22 var replaceSymbol = utils.ImportNow("replace_symbol"); 21 var replaceSymbol = utils.ImportNow("replace_symbol");
23 var searchSymbol = utils.ImportNow("search_symbol"); 22 var searchSymbol = utils.ImportNow("search_symbol");
24 var speciesSymbol = utils.ImportNow("species_symbol"); 23 var speciesSymbol = utils.ImportNow("species_symbol");
25 var splitSymbol = utils.ImportNow("split_symbol"); 24 var splitSymbol = utils.ImportNow("split_symbol");
26 var SpeciesConstructor; 25 var SpeciesConstructor;
27 26
28 utils.Import(function(from) { 27 utils.Import(function(from) {
29 ExpandReplacement = from.ExpandReplacement;
30 MaxSimple = from.MaxSimple; 28 MaxSimple = from.MaxSimple;
31 MinSimple = from.MinSimple; 29 MinSimple = from.MinSimple;
32 SpeciesConstructor = from.SpeciesConstructor; 30 SpeciesConstructor = from.SpeciesConstructor;
33 }); 31 });
34 32
35 // ------------------------------------------------------------------- 33 // -------------------------------------------------------------------
36 34
37 // Property of the builtins object for recording the result of the last 35 // Property of the builtins object for recording the result of the last
38 // regexp match. The property RegExpLastMatchInfo includes the matchIndices 36 // regexp match. The property RegExpLastMatchInfo includes the matchIndices
39 // array of the last successful regexp match (an array of start/end index 37 // array of the last successful regexp match (an array of start/end index
(...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after
683 681
684 replacement = %reflect_apply(replace, UNDEFINED, parameters); 682 replacement = %reflect_apply(replace, UNDEFINED, parameters);
685 } 683 }
686 684
687 result += replacement; // The add method converts to string if necessary. 685 result += replacement; // The add method converts to string if necessary.
688 // Can't use matchInfo any more from here, since the function could 686 // Can't use matchInfo any more from here, since the function could
689 // overwrite it. 687 // overwrite it.
690 return result + %_SubString(subject, endOfMatch, subject.length); 688 return result + %_SubString(subject, endOfMatch, subject.length);
691 } 689 }
692 690
691 // Wraps access to matchInfo's captures into a format understood by
692 // GetSubstitution.
693 function MatchInfoCaptureWrapper(matches, subject) {
694 this.length = NUMBER_OF_CAPTURES(matches) >> 1;
695 this.match = matches;
696 this.subject = subject;
697 }
698
699 MatchInfoCaptureWrapper.prototype.at = function(ix) {
700 const match = this.match;
701 const start = match[CAPTURE(ix << 1)];
702 if (start < 0) return UNDEFINED;
703 return %_SubString(this.subject, start, match[CAPTURE((ix << 1) + 1)]);
704 };
705 %SetForceInlineFlag(MatchInfoCaptureWrapper.prototype.at);
706
707 function ArrayCaptureWrapper(array) {
708 this.length = array.length;
709 this.array = array;
710 }
711
712 ArrayCaptureWrapper.prototype.at = function(ix) {
713 return this.array[ix];
714 };
715 %SetForceInlineFlag(ArrayCaptureWrapper.prototype.at);
693 716
694 function RegExpReplace(string, replace) { 717 function RegExpReplace(string, replace) {
695 if (!IS_REGEXP(this)) { 718 if (!IS_REGEXP(this)) {
696 throw %make_type_error(kIncompatibleMethodReceiver, 719 throw %make_type_error(kIncompatibleMethodReceiver,
697 "RegExp.prototype.@@replace", this); 720 "RegExp.prototype.@@replace", this);
698 } 721 }
699 var subject = TO_STRING(string); 722 var subject = TO_STRING(string);
700 var search = this; 723 var search = this;
701 724
702 if (!IS_CALLABLE(replace)) { 725 if (!IS_CALLABLE(replace)) {
703 replace = TO_STRING(replace); 726 replace = TO_STRING(replace);
704 727
705 if (!REGEXP_GLOBAL(search)) { 728 if (!REGEXP_GLOBAL(search)) {
706 // Non-global regexp search, string replace. 729 // Non-global regexp search, string replace.
707 var match = DoRegExpExec(search, subject, 0); 730 var match = DoRegExpExec(search, subject, 0);
708 if (match == null) { 731 if (match == null) {
709 search.lastIndex = 0 732 search.lastIndex = 0
710 return subject; 733 return subject;
711 } 734 }
712 if (replace.length == 0) { 735 if (replace.length == 0) {
713 return %_SubString(subject, 0, match[CAPTURE0]) + 736 return %_SubString(subject, 0, match[CAPTURE0]) +
714 %_SubString(subject, match[CAPTURE1], subject.length) 737 %_SubString(subject, match[CAPTURE1], subject.length)
715 } 738 }
716 return ExpandReplacement(replace, subject, RegExpLastMatchInfo, 739 const captures = new MatchInfoCaptureWrapper(match, subject);
717 %_SubString(subject, 0, match[CAPTURE0])) + 740 const start = match[CAPTURE0];
718 %_SubString(subject, match[CAPTURE1], subject.length); 741 const end = match[CAPTURE1];
742
743 const prefix = %_SubString(subject, 0, start);
744 const matched = %_SubString(subject, start, end);
745 const suffix = %_SubString(subject, end, subject.length);
746
747 return prefix +
748 GetSubstitution(matched, subject, start, captures, replace) +
749 suffix;
719 } 750 }
720 751
721 // Global regexp search, string replace. 752 // Global regexp search, string replace.
722 search.lastIndex = 0; 753 search.lastIndex = 0;
723 return %StringReplaceGlobalRegExpWithString( 754 return %StringReplaceGlobalRegExpWithString(
724 subject, search, replace, RegExpLastMatchInfo); 755 subject, search, replace, RegExpLastMatchInfo);
725 } 756 }
726 757
727 if (REGEXP_GLOBAL(search)) { 758 if (REGEXP_GLOBAL(search)) {
728 // Global regexp search, function replace. 759 // Global regexp search, function replace.
729 return StringReplaceGlobalRegExpWithFunction(subject, search, replace); 760 return StringReplaceGlobalRegExpWithFunction(subject, search, replace);
730 } 761 }
731 // Non-global regexp search, function replace. 762 // Non-global regexp search, function replace.
732 return StringReplaceNonGlobalRegExpWithFunction(subject, search, replace); 763 return StringReplaceNonGlobalRegExpWithFunction(subject, search, replace);
733 } 764 }
734 765
735 766
736 // ES#sec-getsubstitution 767 // ES#sec-getsubstitution
737 // GetSubstitution(matched, str, position, captures, replacement) 768 // GetSubstitution(matched, str, position, captures, replacement)
738 // Expand the $-expressions in the string and return a new string with 769 // Expand the $-expressions in the string and return a new string with
739 // the result. 770 // the result.
740 // TODO(littledan): Call this function from String.prototype.replace instead
741 // of the very similar ExpandReplacement in src/js/string.js
742 function GetSubstitution(matched, string, position, captures, replacement) { 771 function GetSubstitution(matched, string, position, captures, replacement) {
743 var matchLength = matched.length; 772 var matchLength = matched.length;
744 var stringLength = string.length; 773 var stringLength = string.length;
745 var capturesLength = captures.length; 774 var capturesLength = captures.length;
746 var tailPos = position + matchLength; 775 var tailPos = position + matchLength;
747 var result = ""; 776 var result = "";
748 var pos, expansion, peek, next, scaledIndex, advance, newScaledIndex; 777 var pos, expansion, peek, next, scaledIndex, advance, newScaledIndex;
749 778
750 var next = %StringIndexOf(replacement, '$', 0); 779 var next = %StringIndexOf(replacement, '$', 0);
751 if (next < 0) { 780 if (next < 0) {
(...skipping 28 matching lines...) Expand all
780 next = %_StringCharCodeAt(replacement, pos + 1); 809 next = %_StringCharCodeAt(replacement, pos + 1);
781 if (next >= 48 && next <= 57) { 810 if (next >= 48 && next <= 57) {
782 newScaledIndex = scaledIndex * 10 + ((next - 48)); 811 newScaledIndex = scaledIndex * 10 + ((next - 48));
783 if (newScaledIndex < capturesLength) { 812 if (newScaledIndex < capturesLength) {
784 scaledIndex = newScaledIndex; 813 scaledIndex = newScaledIndex;
785 advance = 2; 814 advance = 2;
786 } 815 }
787 } 816 }
788 } 817 }
789 if (scaledIndex != 0 && scaledIndex < capturesLength) { 818 if (scaledIndex != 0 && scaledIndex < capturesLength) {
790 var capture = captures[scaledIndex]; 819 var capture = captures.at(scaledIndex);
791 if (!IS_UNDEFINED(capture)) result += capture; 820 if (!IS_UNDEFINED(capture)) result += capture;
792 pos += advance; 821 pos += advance;
793 } else { 822 } else {
794 result += '$'; 823 result += '$';
795 } 824 }
796 } else { 825 } else {
797 result += '$'; 826 result += '$';
798 } 827 }
799 } else { 828 } else {
800 result += '$'; 829 result += '$';
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
904 if (functionalReplace) { 933 if (functionalReplace) {
905 var parameters = new InternalArray(capturesLength + 2); 934 var parameters = new InternalArray(capturesLength + 2);
906 for (var j = 0; j < capturesLength; j++) { 935 for (var j = 0; j < capturesLength; j++) {
907 parameters[j] = captures[j]; 936 parameters[j] = captures[j];
908 } 937 }
909 parameters[j] = position; 938 parameters[j] = position;
910 parameters[j + 1] = string; 939 parameters[j + 1] = string;
911 replacement = %reflect_apply(replace, UNDEFINED, parameters, 0, 940 replacement = %reflect_apply(replace, UNDEFINED, parameters, 0,
912 parameters.length); 941 parameters.length);
913 } else { 942 } else {
914 replacement = GetSubstitution(matched, string, position, captures, 943 const capturesWrapper = new ArrayCaptureWrapper(captures);
944 replacement = GetSubstitution(matched, string, position, capturesWrapper,
915 replace); 945 replace);
916 } 946 }
917 if (position >= nextSourcePosition) { 947 if (position >= nextSourcePosition) {
918 accumulatedResult += 948 accumulatedResult +=
919 %_SubString(string, nextSourcePosition, position) + replacement; 949 %_SubString(string, nextSourcePosition, position) + replacement;
920 nextSourcePosition = position + matchedLength; 950 nextSourcePosition = position + matchedLength;
921 } 951 }
922 } 952 }
923 if (nextSourcePosition >= length) return accumulatedResult; 953 if (nextSourcePosition >= length) return accumulatedResult;
924 return accumulatedResult + %_SubString(string, nextSourcePosition, length); 954 return accumulatedResult + %_SubString(string, nextSourcePosition, length);
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
1212 1242
1213 function InternalRegExpReplace(regexp, subject, replacement) { 1243 function InternalRegExpReplace(regexp, subject, replacement) {
1214 return %StringReplaceGlobalRegExpWithString( 1244 return %StringReplaceGlobalRegExpWithString(
1215 subject, regexp, replacement, InternalRegExpMatchInfo); 1245 subject, regexp, replacement, InternalRegExpMatchInfo);
1216 } 1246 }
1217 1247
1218 // ------------------------------------------------------------------- 1248 // -------------------------------------------------------------------
1219 // Exports 1249 // Exports
1220 1250
1221 utils.Export(function(to) { 1251 utils.Export(function(to) {
1252 to.GetSubstitution = GetSubstitution;
1222 to.InternalRegExpMatch = InternalRegExpMatch; 1253 to.InternalRegExpMatch = InternalRegExpMatch;
1223 to.InternalRegExpReplace = InternalRegExpReplace; 1254 to.InternalRegExpReplace = InternalRegExpReplace;
1224 to.IsRegExp = IsRegExp; 1255 to.IsRegExp = IsRegExp;
1225 to.RegExpExec = DoRegExpExec; 1256 to.RegExpExec = DoRegExpExec;
1226 to.RegExpInitialize = RegExpInitialize; 1257 to.RegExpInitialize = RegExpInitialize;
1227 to.RegExpLastMatchInfo = RegExpLastMatchInfo; 1258 to.RegExpLastMatchInfo = RegExpLastMatchInfo;
1228 to.RegExpTest = RegExpTest; 1259 to.RegExpTest = RegExpTest;
1229 }); 1260 });
1230 1261
1231 }) 1262 })
OLDNEW
« no previous file with comments | « no previous file | src/js/string.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698