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 'use strict'; | 7 'use strict'; |
8 | 8 |
9 %CheckIsBootstrapping(); | 9 %CheckIsBootstrapping(); |
10 | 10 |
11 // ------------------------------------------------------------------- | 11 // ------------------------------------------------------------------- |
12 // Imports | 12 // Imports |
13 | 13 |
14 var GlobalArray = global.Array; | 14 var GlobalArray = global.Array; |
15 var GlobalObject = global.Object; | 15 var GlobalObject = global.Object; |
16 var GlobalRegExp = global.RegExp; | 16 var GlobalRegExp = global.RegExp; |
17 var GlobalRegExpPrototype; | 17 var GlobalRegExpPrototype = GlobalRegExp.prototype; |
18 var InternalArray = utils.InternalArray; | 18 var InternalArray = utils.InternalArray; |
19 var InternalPackedArray = utils.InternalPackedArray; | 19 var InternalPackedArray = utils.InternalPackedArray; |
20 var MaxSimple; | 20 var MaxSimple; |
21 var MinSimple; | 21 var MinSimple; |
| 22 var RegExpExecJS = GlobalRegExp.prototype.exec; |
22 var matchSymbol = utils.ImportNow("match_symbol"); | 23 var matchSymbol = utils.ImportNow("match_symbol"); |
23 var replaceSymbol = utils.ImportNow("replace_symbol"); | 24 var replaceSymbol = utils.ImportNow("replace_symbol"); |
24 var searchSymbol = utils.ImportNow("search_symbol"); | 25 var searchSymbol = utils.ImportNow("search_symbol"); |
25 var speciesSymbol = utils.ImportNow("species_symbol"); | 26 var speciesSymbol = utils.ImportNow("species_symbol"); |
26 var splitSymbol = utils.ImportNow("split_symbol"); | 27 var splitSymbol = utils.ImportNow("split_symbol"); |
27 var SpeciesConstructor; | 28 var SpeciesConstructor; |
28 | 29 |
29 utils.Import(function(from) { | 30 utils.Import(function(from) { |
30 MaxSimple = from.MaxSimple; | 31 MaxSimple = from.MaxSimple; |
31 MinSimple = from.MinSimple; | 32 MinSimple = from.MinSimple; |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 if (start != -1) { | 157 if (start != -1) { |
157 end = MATCHINFO[j]; | 158 end = MATCHINFO[j]; |
158 result[i] = %_SubString(STRING, start, end); | 159 result[i] = %_SubString(STRING, start, end); |
159 } | 160 } |
160 j++; | 161 j++; |
161 } | 162 } |
162 return result; | 163 return result; |
163 endmacro | 164 endmacro |
164 | 165 |
165 | 166 |
166 // ES#sec-regexp.prototype.exec | |
167 // RegExp.prototype.exec ( string ) | |
168 function RegExpExecJS(string) { | |
169 if (!IS_REGEXP(this)) { | |
170 throw %make_type_error(kIncompatibleMethodReceiver, | |
171 'RegExp.prototype.exec', this); | |
172 } | |
173 | |
174 string = TO_STRING(string); | |
175 | |
176 var lastIndex; | |
177 var global = TO_BOOLEAN(REGEXP_GLOBAL(this)); | |
178 var sticky = TO_BOOLEAN(REGEXP_STICKY(this)); | |
179 var updateLastIndex = global || sticky; | |
180 if (updateLastIndex) { | |
181 // TODO(jgruber): This is actually ToLength in the spec, but we bailout | |
182 // to the runtime in %_RegExpExec if lastIndex is not a Smi, so we are | |
183 // smart here and trick both TurboFan and Crankshaft to produce a Smi. | |
184 // This is a terrible hack, and correct for subtle reasons; it's a clear | |
185 // indicator that we need a predictable RegExp implementation where we | |
186 // don't need to add specific work-arounds for certain compiler issues. | |
187 lastIndex = +this.lastIndex; | |
188 if (lastIndex > string.length) { | |
189 this.lastIndex = 0; | |
190 return null; | |
191 } else if (lastIndex <= 0) { | |
192 lastIndex = 0; | |
193 } | |
194 lastIndex = lastIndex|0; | |
195 } else { | |
196 lastIndex = 0; | |
197 } | |
198 | |
199 // matchIndices is either null or the RegExpLastMatchInfo array. | |
200 var matchIndices = %_RegExpExec(this, string, lastIndex, RegExpLastMatchInfo); | |
201 | |
202 if (IS_NULL(matchIndices)) { | |
203 if (updateLastIndex) this.lastIndex = 0; | |
204 return null; | |
205 } | |
206 | |
207 // Successful match. | |
208 if (updateLastIndex) { | |
209 this.lastIndex = RegExpLastMatchInfo[CAPTURE1]; | |
210 } | |
211 RETURN_NEW_RESULT_FROM_MATCH_INFO(matchIndices, string); | |
212 } | |
213 %FunctionRemovePrototype(RegExpExecJS); | |
214 | |
215 | 167 |
216 // ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S ) | 168 // ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S ) |
217 // Also takes an optional exec method in case our caller | 169 // Also takes an optional exec method in case our caller |
218 // has already fetched exec. | 170 // has already fetched exec. |
219 function RegExpSubclassExec(regexp, string, exec) { | 171 function RegExpSubclassExec(regexp, string, exec) { |
220 if (IS_UNDEFINED(exec)) { | 172 if (IS_UNDEFINED(exec)) { |
221 exec = regexp.exec; | 173 exec = regexp.exec; |
222 } | 174 } |
223 if (IS_CALLABLE(exec)) { | 175 if (IS_CALLABLE(exec)) { |
224 var result = %_Call(exec, regexp, string); | 176 var result = %_Call(exec, regexp, string); |
(...skipping 790 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1015 | 967 |
1016 | 968 |
1017 function RegExpSpecies() { | 969 function RegExpSpecies() { |
1018 return this; | 970 return this; |
1019 } | 971 } |
1020 | 972 |
1021 | 973 |
1022 // ------------------------------------------------------------------- | 974 // ------------------------------------------------------------------- |
1023 | 975 |
1024 %FunctionSetInstanceClassName(GlobalRegExp, 'RegExp'); | 976 %FunctionSetInstanceClassName(GlobalRegExp, 'RegExp'); |
1025 GlobalRegExpPrototype = new GlobalObject(); | |
1026 %FunctionSetPrototype(GlobalRegExp, GlobalRegExpPrototype); | |
1027 %AddNamedProperty( | |
1028 GlobalRegExp.prototype, 'constructor', GlobalRegExp, DONT_ENUM); | |
1029 %SetCode(GlobalRegExp, RegExpConstructor); | 977 %SetCode(GlobalRegExp, RegExpConstructor); |
1030 | 978 |
1031 utils.InstallGetter(GlobalRegExp, speciesSymbol, RegExpSpecies); | 979 utils.InstallGetter(GlobalRegExp, speciesSymbol, RegExpSpecies); |
1032 | 980 |
1033 utils.InstallFunctions(GlobalRegExp.prototype, DONT_ENUM, [ | 981 utils.InstallFunctions(GlobalRegExp.prototype, DONT_ENUM, [ |
1034 "exec", RegExpExecJS, | |
1035 "test", RegExpSubclassTest, | 982 "test", RegExpSubclassTest, |
1036 "toString", RegExpToString, | 983 "toString", RegExpToString, |
1037 "compile", RegExpCompileJS, | 984 "compile", RegExpCompileJS, |
1038 matchSymbol, RegExpSubclassMatch, | 985 matchSymbol, RegExpSubclassMatch, |
1039 replaceSymbol, RegExpSubclassReplace, | 986 replaceSymbol, RegExpSubclassReplace, |
1040 searchSymbol, RegExpSubclassSearch, | 987 searchSymbol, RegExpSubclassSearch, |
1041 splitSymbol, RegExpSubclassSplit, | 988 splitSymbol, RegExpSubclassSplit, |
1042 ]); | 989 ]); |
1043 | 990 |
1044 utils.InstallGetter(GlobalRegExp.prototype, 'flags', RegExpGetFlags); | 991 utils.InstallGetter(GlobalRegExp.prototype, 'flags', RegExpGetFlags); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1096 NoOpSetter, DONT_ENUM); | 1043 NoOpSetter, DONT_ENUM); |
1097 utils.InstallGetterSetter(GlobalRegExp, "$'", RegExpGetRightContext, NoOpSetter, | 1044 utils.InstallGetterSetter(GlobalRegExp, "$'", RegExpGetRightContext, NoOpSetter, |
1098 DONT_ENUM); | 1045 DONT_ENUM); |
1099 | 1046 |
1100 for (var i = 1; i < 10; ++i) { | 1047 for (var i = 1; i < 10; ++i) { |
1101 utils.InstallGetterSetter(GlobalRegExp, '$' + i, RegExpMakeCaptureGetter(i), | 1048 utils.InstallGetterSetter(GlobalRegExp, '$' + i, RegExpMakeCaptureGetter(i), |
1102 NoOpSetter, DONT_ENUM); | 1049 NoOpSetter, DONT_ENUM); |
1103 } | 1050 } |
1104 %ToFastProperties(GlobalRegExp); | 1051 %ToFastProperties(GlobalRegExp); |
1105 | 1052 |
| 1053 %InstallToContext(["regexp_last_match_info", RegExpLastMatchInfo]); |
| 1054 |
1106 // ------------------------------------------------------------------- | 1055 // ------------------------------------------------------------------- |
1107 // Internal | 1056 // Internal |
1108 | 1057 |
1109 var InternalRegExpMatchInfo = { | 1058 var InternalRegExpMatchInfo = { |
1110 REGEXP_NUMBER_OF_CAPTURES: 2, | 1059 REGEXP_NUMBER_OF_CAPTURES: 2, |
1111 REGEXP_LAST_SUBJECT: "", | 1060 REGEXP_LAST_SUBJECT: "", |
1112 REGEXP_LAST_INPUT: UNDEFINED, | 1061 REGEXP_LAST_INPUT: UNDEFINED, |
1113 CAPTURE0: 0, | 1062 CAPTURE0: 0, |
1114 CAPTURE1: 0 | 1063 CAPTURE1: 0 |
1115 }; | 1064 }; |
(...skipping 18 matching lines...) Expand all Loading... |
1134 to.GetSubstitution = GetSubstitution; | 1083 to.GetSubstitution = GetSubstitution; |
1135 to.InternalRegExpMatch = InternalRegExpMatch; | 1084 to.InternalRegExpMatch = InternalRegExpMatch; |
1136 to.InternalRegExpReplace = InternalRegExpReplace; | 1085 to.InternalRegExpReplace = InternalRegExpReplace; |
1137 to.IsRegExp = IsRegExp; | 1086 to.IsRegExp = IsRegExp; |
1138 to.RegExpExec = DoRegExpExec; | 1087 to.RegExpExec = DoRegExpExec; |
1139 to.RegExpInitialize = RegExpInitialize; | 1088 to.RegExpInitialize = RegExpInitialize; |
1140 to.RegExpLastMatchInfo = RegExpLastMatchInfo; | 1089 to.RegExpLastMatchInfo = RegExpLastMatchInfo; |
1141 }); | 1090 }); |
1142 | 1091 |
1143 }) | 1092 }) |
OLD | NEW |