| OLD | NEW |
| 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; | 12 var ExpandReplacement; |
| 13 var GlobalArray = global.Array; | 13 var GlobalArray = global.Array; |
| 14 var GlobalObject = global.Object; | 14 var GlobalObject = global.Object; |
| 15 var GlobalRegExp = global.RegExp; | 15 var GlobalRegExp = global.RegExp; |
| 16 var InternalArray = utils.InternalArray; | 16 var InternalArray = utils.InternalArray; |
| 17 var InternalPackedArray = utils.InternalPackedArray; | 17 var InternalPackedArray = utils.InternalPackedArray; |
| 18 var MaxSimple; | 18 var MaxSimple; |
| 19 var MinSimple; | 19 var MinSimple; |
| 20 var lastMatchInfoSymbol = utils.ImportNow("regexp_last_match_info_symbol"); |
| 20 var matchSymbol = utils.ImportNow("match_symbol"); | 21 var matchSymbol = utils.ImportNow("match_symbol"); |
| 21 var replaceSymbol = utils.ImportNow("replace_symbol"); | 22 var replaceSymbol = utils.ImportNow("replace_symbol"); |
| 22 var searchSymbol = utils.ImportNow("search_symbol"); | 23 var searchSymbol = utils.ImportNow("search_symbol"); |
| 23 var speciesSymbol = utils.ImportNow("species_symbol"); | 24 var speciesSymbol = utils.ImportNow("species_symbol"); |
| 24 var splitSymbol = utils.ImportNow("split_symbol"); | 25 var splitSymbol = utils.ImportNow("split_symbol"); |
| 25 var SpeciesConstructor; | 26 var SpeciesConstructor; |
| 26 | 27 |
| 27 utils.Import(function(from) { | 28 utils.Import(function(from) { |
| 28 ExpandReplacement = from.ExpandReplacement; | 29 ExpandReplacement = from.ExpandReplacement; |
| 29 MaxSimple = from.MaxSimple; | 30 MaxSimple = from.MaxSimple; |
| (...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 916 var previousLastIndex = this.lastIndex; | 917 var previousLastIndex = this.lastIndex; |
| 917 this.lastIndex = 0; | 918 this.lastIndex = 0; |
| 918 var result = RegExpSubclassExec(this, string); | 919 var result = RegExpSubclassExec(this, string); |
| 919 this.lastIndex = previousLastIndex; | 920 this.lastIndex = previousLastIndex; |
| 920 if (IS_NULL(result)) return -1; | 921 if (IS_NULL(result)) return -1; |
| 921 return result.index; | 922 return result.index; |
| 922 } | 923 } |
| 923 %FunctionRemovePrototype(RegExpSubclassSearch); | 924 %FunctionRemovePrototype(RegExpSubclassSearch); |
| 924 | 925 |
| 925 | 926 |
| 926 // Getters for the static properties lastMatch, lastParen, leftContext, and | |
| 927 // rightContext of the RegExp constructor. The properties are computed based | |
| 928 // on the captures array of the last successful match and the subject string | |
| 929 // of the last successful match. | |
| 930 function RegExpGetLastMatch() { | |
| 931 var regExpSubject = LAST_SUBJECT(RegExpLastMatchInfo); | |
| 932 return %_SubString(regExpSubject, | |
| 933 RegExpLastMatchInfo[CAPTURE0], | |
| 934 RegExpLastMatchInfo[CAPTURE1]); | |
| 935 } | |
| 936 | |
| 937 | |
| 938 function RegExpGetLastParen() { | |
| 939 var length = NUMBER_OF_CAPTURES(RegExpLastMatchInfo); | |
| 940 if (length <= 2) return ''; // There were no captures. | |
| 941 // We match the SpiderMonkey behavior: return the substring defined by the | |
| 942 // last pair (after the first pair) of elements of the capture array even if | |
| 943 // it is empty. | |
| 944 var regExpSubject = LAST_SUBJECT(RegExpLastMatchInfo); | |
| 945 var start = RegExpLastMatchInfo[CAPTURE(length - 2)]; | |
| 946 var end = RegExpLastMatchInfo[CAPTURE(length - 1)]; | |
| 947 if (start != -1 && end != -1) { | |
| 948 return %_SubString(regExpSubject, start, end); | |
| 949 } | |
| 950 return ""; | |
| 951 } | |
| 952 | |
| 953 | |
| 954 function RegExpGetLeftContext() { | |
| 955 var start_index; | |
| 956 var subject; | |
| 957 start_index = RegExpLastMatchInfo[CAPTURE0]; | |
| 958 subject = LAST_SUBJECT(RegExpLastMatchInfo); | |
| 959 return %_SubString(subject, 0, start_index); | |
| 960 } | |
| 961 | |
| 962 | |
| 963 function RegExpGetRightContext() { | |
| 964 var start_index; | |
| 965 var subject; | |
| 966 start_index = RegExpLastMatchInfo[CAPTURE1]; | |
| 967 subject = LAST_SUBJECT(RegExpLastMatchInfo); | |
| 968 return %_SubString(subject, start_index, subject.length); | |
| 969 } | |
| 970 | |
| 971 | |
| 972 // The properties $1..$9 are the first nine capturing substrings of the last | |
| 973 // successful match, or ''. The function RegExpMakeCaptureGetter will be | |
| 974 // called with indices from 1 to 9. | |
| 975 function RegExpMakeCaptureGetter(n) { | |
| 976 return function foo() { | |
| 977 var index = n * 2; | |
| 978 if (index >= NUMBER_OF_CAPTURES(RegExpLastMatchInfo)) return ''; | |
| 979 var matchStart = RegExpLastMatchInfo[CAPTURE(index)]; | |
| 980 var matchEnd = RegExpLastMatchInfo[CAPTURE(index + 1)]; | |
| 981 if (matchStart == -1 || matchEnd == -1) return ''; | |
| 982 return %_SubString(LAST_SUBJECT(RegExpLastMatchInfo), matchStart, matchEnd); | |
| 983 }; | |
| 984 } | |
| 985 | |
| 986 | |
| 987 // ES6 21.2.5.3. | |
| 988 function RegExpGetFlags() { | |
| 989 if (!IS_RECEIVER(this)) { | |
| 990 throw %make_type_error( | |
| 991 kRegExpNonObject, "RegExp.prototype.flags", TO_STRING(this)); | |
| 992 } | |
| 993 var result = ''; | |
| 994 if (this.global) result += 'g'; | |
| 995 if (this.ignoreCase) result += 'i'; | |
| 996 if (this.multiline) result += 'm'; | |
| 997 if (this.unicode) result += 'u'; | |
| 998 if (this.sticky) result += 'y'; | |
| 999 return result; | |
| 1000 } | |
| 1001 | |
| 1002 | |
| 1003 // ES6 21.2.5.4. | |
| 1004 function RegExpGetGlobal() { | |
| 1005 if (!IS_REGEXP(this)) { | |
| 1006 // TODO(littledan): Remove this RegExp compat workaround | |
| 1007 if (this === GlobalRegExp.prototype) { | |
| 1008 %IncrementUseCounter(kRegExpPrototypeOldFlagGetter); | |
| 1009 return UNDEFINED; | |
| 1010 } | |
| 1011 throw %make_type_error(kRegExpNonRegExp, "RegExp.prototype.global"); | |
| 1012 } | |
| 1013 return TO_BOOLEAN(REGEXP_GLOBAL(this)); | |
| 1014 } | |
| 1015 %SetForceInlineFlag(RegExpGetGlobal); | |
| 1016 | |
| 1017 | |
| 1018 // ES6 21.2.5.5. | |
| 1019 function RegExpGetIgnoreCase() { | |
| 1020 if (!IS_REGEXP(this)) { | |
| 1021 // TODO(littledan): Remove this RegExp compat workaround | |
| 1022 if (this === GlobalRegExp.prototype) { | |
| 1023 %IncrementUseCounter(kRegExpPrototypeOldFlagGetter); | |
| 1024 return UNDEFINED; | |
| 1025 } | |
| 1026 throw %make_type_error(kRegExpNonRegExp, "RegExp.prototype.ignoreCase"); | |
| 1027 } | |
| 1028 return TO_BOOLEAN(REGEXP_IGNORE_CASE(this)); | |
| 1029 } | |
| 1030 | |
| 1031 | |
| 1032 // ES6 21.2.5.7. | |
| 1033 function RegExpGetMultiline() { | |
| 1034 if (!IS_REGEXP(this)) { | |
| 1035 // TODO(littledan): Remove this RegExp compat workaround | |
| 1036 if (this === GlobalRegExp.prototype) { | |
| 1037 %IncrementUseCounter(kRegExpPrototypeOldFlagGetter); | |
| 1038 return UNDEFINED; | |
| 1039 } | |
| 1040 throw %make_type_error(kRegExpNonRegExp, "RegExp.prototype.multiline"); | |
| 1041 } | |
| 1042 return TO_BOOLEAN(REGEXP_MULTILINE(this)); | |
| 1043 } | |
| 1044 | |
| 1045 | |
| 1046 // ES6 21.2.5.10. | |
| 1047 function RegExpGetSource() { | |
| 1048 if (!IS_REGEXP(this)) { | |
| 1049 // TODO(littledan): Remove this RegExp compat workaround | |
| 1050 if (this === GlobalRegExp.prototype) { | |
| 1051 %IncrementUseCounter(kRegExpPrototypeSourceGetter); | |
| 1052 return "(?:)"; | |
| 1053 } | |
| 1054 throw %make_type_error(kRegExpNonRegExp, "RegExp.prototype.source"); | |
| 1055 } | |
| 1056 return REGEXP_SOURCE(this); | |
| 1057 } | |
| 1058 | |
| 1059 | |
| 1060 // ES6 21.2.5.12. | |
| 1061 function RegExpGetSticky() { | |
| 1062 if (!IS_REGEXP(this)) { | |
| 1063 // Compat fix: RegExp.prototype.sticky == undefined; UseCounter tracks it | |
| 1064 // TODO(littledan): Remove this workaround or standardize it | |
| 1065 if (this === GlobalRegExp.prototype) { | |
| 1066 %IncrementUseCounter(kRegExpPrototypeStickyGetter); | |
| 1067 return UNDEFINED; | |
| 1068 } | |
| 1069 throw %make_type_error(kRegExpNonRegExp, "RegExp.prototype.sticky"); | |
| 1070 } | |
| 1071 return TO_BOOLEAN(REGEXP_STICKY(this)); | |
| 1072 } | |
| 1073 %SetForceInlineFlag(RegExpGetSticky); | |
| 1074 | |
| 1075 | |
| 1076 // ES6 21.2.5.15. | |
| 1077 function RegExpGetUnicode() { | |
| 1078 if (!IS_REGEXP(this)) { | |
| 1079 // TODO(littledan): Remove this RegExp compat workaround | |
| 1080 if (this === GlobalRegExp.prototype) { | |
| 1081 %IncrementUseCounter(kRegExpPrototypeUnicodeGetter); | |
| 1082 return UNDEFINED; | |
| 1083 } | |
| 1084 throw %make_type_error(kRegExpNonRegExp, "RegExp.prototype.unicode"); | |
| 1085 } | |
| 1086 return TO_BOOLEAN(REGEXP_UNICODE(this)); | |
| 1087 } | |
| 1088 %SetForceInlineFlag(RegExpGetUnicode); | |
| 1089 | |
| 1090 | |
| 1091 function RegExpSpecies() { | |
| 1092 return this; | |
| 1093 } | |
| 1094 | |
| 1095 | |
| 1096 // ------------------------------------------------------------------- | 927 // ------------------------------------------------------------------- |
| 1097 | 928 |
| 1098 utils.InstallGetter(GlobalRegExp, speciesSymbol, RegExpSpecies); | |
| 1099 | |
| 1100 utils.InstallFunctions(GlobalRegExp.prototype, DONT_ENUM, [ | 929 utils.InstallFunctions(GlobalRegExp.prototype, DONT_ENUM, [ |
| 1101 "exec", RegExpSubclassExecJS, | 930 "exec", RegExpSubclassExecJS, |
| 1102 "test", RegExpSubclassTest, | 931 "test", RegExpSubclassTest, |
| 1103 "toString", RegExpToString, | 932 "toString", RegExpToString, |
| 1104 "compile", RegExpCompileJS, | 933 "compile", RegExpCompileJS, |
| 1105 matchSymbol, RegExpSubclassMatch, | 934 matchSymbol, RegExpSubclassMatch, |
| 1106 replaceSymbol, RegExpSubclassReplace, | 935 replaceSymbol, RegExpSubclassReplace, |
| 1107 searchSymbol, RegExpSubclassSearch, | 936 searchSymbol, RegExpSubclassSearch, |
| 1108 splitSymbol, RegExpSubclassSplit, | 937 splitSymbol, RegExpSubclassSplit, |
| 1109 ]); | 938 ]); |
| 1110 | 939 |
| 1111 utils.InstallGetter(GlobalRegExp.prototype, 'flags', RegExpGetFlags); | 940 // Temporary until all RegExpLastMatchInfo accesses are ported to C++. |
| 1112 utils.InstallGetter(GlobalRegExp.prototype, 'global', RegExpGetGlobal); | 941 SET_PRIVATE(GlobalRegExp, lastMatchInfoSymbol, RegExpLastMatchInfo); |
| 1113 utils.InstallGetter(GlobalRegExp.prototype, 'ignoreCase', RegExpGetIgnoreCase); | |
| 1114 utils.InstallGetter(GlobalRegExp.prototype, 'multiline', RegExpGetMultiline); | |
| 1115 utils.InstallGetter(GlobalRegExp.prototype, 'source', RegExpGetSource); | |
| 1116 utils.InstallGetter(GlobalRegExp.prototype, 'sticky', RegExpGetSticky); | |
| 1117 utils.InstallGetter(GlobalRegExp.prototype, 'unicode', RegExpGetUnicode); | |
| 1118 | |
| 1119 // The properties `input` and `$_` are aliases for each other. When this | |
| 1120 // value is set the value it is set to is coerced to a string. | |
| 1121 // Getter and setter for the input. | |
| 1122 var RegExpGetInput = function() { | |
| 1123 var regExpInput = LAST_INPUT(RegExpLastMatchInfo); | |
| 1124 return IS_UNDEFINED(regExpInput) ? "" : regExpInput; | |
| 1125 }; | |
| 1126 var RegExpSetInput = function(string) { | |
| 1127 LAST_INPUT(RegExpLastMatchInfo) = TO_STRING(string); | |
| 1128 }; | |
| 1129 | |
| 1130 %OptimizeObjectForAddingMultipleProperties(GlobalRegExp, 22); | |
| 1131 utils.InstallGetterSetter(GlobalRegExp, 'input', RegExpGetInput, RegExpSetInput, | |
| 1132 DONT_DELETE); | |
| 1133 utils.InstallGetterSetter(GlobalRegExp, '$_', RegExpGetInput, RegExpSetInput, | |
| 1134 DONT_ENUM | DONT_DELETE); | |
| 1135 | |
| 1136 | |
| 1137 var NoOpSetter = function(ignored) {}; | |
| 1138 | |
| 1139 | |
| 1140 // Static properties set by a successful match. | |
| 1141 utils.InstallGetterSetter(GlobalRegExp, 'lastMatch', RegExpGetLastMatch, | |
| 1142 NoOpSetter, DONT_DELETE); | |
| 1143 utils.InstallGetterSetter(GlobalRegExp, '$&', RegExpGetLastMatch, NoOpSetter, | |
| 1144 DONT_ENUM | DONT_DELETE); | |
| 1145 utils.InstallGetterSetter(GlobalRegExp, 'lastParen', RegExpGetLastParen, | |
| 1146 NoOpSetter, DONT_DELETE); | |
| 1147 utils.InstallGetterSetter(GlobalRegExp, '$+', RegExpGetLastParen, NoOpSetter, | |
| 1148 DONT_ENUM | DONT_DELETE); | |
| 1149 utils.InstallGetterSetter(GlobalRegExp, 'leftContext', RegExpGetLeftContext, | |
| 1150 NoOpSetter, DONT_DELETE); | |
| 1151 utils.InstallGetterSetter(GlobalRegExp, '$`', RegExpGetLeftContext, NoOpSetter, | |
| 1152 DONT_ENUM | DONT_DELETE); | |
| 1153 utils.InstallGetterSetter(GlobalRegExp, 'rightContext', RegExpGetRightContext, | |
| 1154 NoOpSetter, DONT_DELETE); | |
| 1155 utils.InstallGetterSetter(GlobalRegExp, "$'", RegExpGetRightContext, NoOpSetter, | |
| 1156 DONT_ENUM | DONT_DELETE); | |
| 1157 | |
| 1158 for (var i = 1; i < 10; ++i) { | |
| 1159 utils.InstallGetterSetter(GlobalRegExp, '$' + i, RegExpMakeCaptureGetter(i), | |
| 1160 NoOpSetter, DONT_DELETE); | |
| 1161 } | |
| 1162 %ToFastProperties(GlobalRegExp); | |
| 1163 | 942 |
| 1164 // ------------------------------------------------------------------- | 943 // ------------------------------------------------------------------- |
| 1165 // Internal | 944 // Internal |
| 1166 | 945 |
| 1167 var InternalRegExpMatchInfo = { | 946 var InternalRegExpMatchInfo = { |
| 1168 REGEXP_NUMBER_OF_CAPTURES: 2, | 947 REGEXP_NUMBER_OF_CAPTURES: 2, |
| 1169 REGEXP_LAST_SUBJECT: "", | 948 REGEXP_LAST_SUBJECT: "", |
| 1170 REGEXP_LAST_INPUT: UNDEFINED, | 949 REGEXP_LAST_INPUT: UNDEFINED, |
| 1171 CAPTURE0: 0, | 950 CAPTURE0: 0, |
| 1172 CAPTURE1: 0 | 951 CAPTURE1: 0 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1192 to.InternalRegExpMatch = InternalRegExpMatch; | 971 to.InternalRegExpMatch = InternalRegExpMatch; |
| 1193 to.InternalRegExpReplace = InternalRegExpReplace; | 972 to.InternalRegExpReplace = InternalRegExpReplace; |
| 1194 to.IsRegExp = IsRegExp; | 973 to.IsRegExp = IsRegExp; |
| 1195 to.RegExpExec = DoRegExpExec; | 974 to.RegExpExec = DoRegExpExec; |
| 1196 to.RegExpInitialize = RegExpInitialize; | 975 to.RegExpInitialize = RegExpInitialize; |
| 1197 to.RegExpLastMatchInfo = RegExpLastMatchInfo; | 976 to.RegExpLastMatchInfo = RegExpLastMatchInfo; |
| 1198 to.RegExpTest = RegExpTest; | 977 to.RegExpTest = RegExpTest; |
| 1199 }); | 978 }); |
| 1200 | 979 |
| 1201 }) | 980 }) |
| OLD | NEW |