Chromium Code Reviews| 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 |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 134 | 134 |
| 135 | 135 |
| 136 function DoRegExpExec(regexp, string, index) { | 136 function DoRegExpExec(regexp, string, index) { |
| 137 return %_RegExpExec(regexp, string, index, RegExpLastMatchInfo); | 137 return %_RegExpExec(regexp, string, index, RegExpLastMatchInfo); |
| 138 } | 138 } |
| 139 | 139 |
| 140 | 140 |
| 141 // This is kind of performance sensitive, so we want to avoid unnecessary | 141 // This is kind of performance sensitive, so we want to avoid unnecessary |
| 142 // type checks on inputs. But we also don't want to inline it several times | 142 // type checks on inputs. But we also don't want to inline it several times |
| 143 // manually, so we use a macro :-) | 143 // manually, so we use a macro :-) |
| 144 macro RETURN_NEW_RESULT_FROM_MATCH_INFO(MATCHINFO, STRING) | 144 macro RETURN_NEW_RESULT_FROM_MATCH_INFO(MATCHINFO, STRING, JSREGEXP) |
| 145 var numResults = NUMBER_OF_CAPTURES(MATCHINFO) >> 1; | 145 var numResults = NUMBER_OF_CAPTURES(MATCHINFO) >> 1; |
| 146 var start = MATCHINFO[CAPTURE0]; | 146 var start = MATCHINFO[CAPTURE0]; |
| 147 var end = MATCHINFO[CAPTURE1]; | 147 var end = MATCHINFO[CAPTURE1]; |
| 148 // Calculate the substring of the first match before creating the result array | 148 // Calculate the substring of the first match before creating the result array |
| 149 // to avoid an unnecessary write barrier storing the first result. | 149 // to avoid an unnecessary write barrier storing the first result. |
| 150 var first = %_SubString(STRING, start, end); | 150 var first = %_SubString(STRING, start, end); |
| 151 var result = %_RegExpConstructResult(numResults, start, STRING); | 151 var result = %_RegExpConstructResult(numResults, start, STRING); |
| 152 result[0] = first; | 152 result[0] = first; |
| 153 if (numResults == 1) return result; | 153 if (numResults == 1) return result; |
| 154 var j = REGEXP_FIRST_CAPTURE + 2; | 154 var j = REGEXP_FIRST_CAPTURE + 2; |
| 155 for (var i = 1; i < numResults; i++) { | 155 for (var i = 1; i < numResults; i++) { |
| 156 start = MATCHINFO[j++]; | 156 start = MATCHINFO[j++]; |
| 157 if (start != -1) { | 157 if (start != -1) { |
| 158 end = MATCHINFO[j]; | 158 end = MATCHINFO[j]; |
| 159 result[i] = %_SubString(STRING, start, end); | 159 result[i] = %_SubString(STRING, start, end); |
| 160 } | 160 } |
| 161 j++; | 161 j++; |
| 162 } | 162 } |
| 163 // For each named capture 'a', create a property result.a containing the | |
| 164 // corresponding captured string. | |
| 165 %RegExpResultAttachNamedCaptures(result, JSREGEXP); | |
|
Yang
2016/06/13 10:54:52
This is going to be fairly expensive, and affects
jgruber
2016/06/13 13:09:59
I'm tending towards this as an initial approach. T
| |
| 163 return result; | 166 return result; |
| 164 endmacro | 167 endmacro |
| 165 | 168 |
| 166 | 169 |
| 167 function RegExpExecNoTests(regexp, string, start) { | 170 function RegExpExecNoTests(regexp, string, start) { |
| 168 // Must be called with RegExp, string and positive integer as arguments. | 171 // Must be called with RegExp, string and positive integer as arguments. |
| 169 var matchInfo = %_RegExpExec(regexp, string, start, RegExpLastMatchInfo); | 172 var matchInfo = %_RegExpExec(regexp, string, start, RegExpLastMatchInfo); |
| 170 if (matchInfo !== null) { | 173 if (matchInfo !== null) { |
| 171 // ES6 21.2.5.2.2 step 18. | 174 // ES6 21.2.5.2.2 step 18. |
| 172 if (REGEXP_STICKY(regexp)) regexp.lastIndex = matchInfo[CAPTURE1]; | 175 if (REGEXP_STICKY(regexp)) regexp.lastIndex = matchInfo[CAPTURE1]; |
| 173 RETURN_NEW_RESULT_FROM_MATCH_INFO(matchInfo, string); | 176 RETURN_NEW_RESULT_FROM_MATCH_INFO(matchInfo, string, regexp); |
| 174 } | 177 } |
| 175 regexp.lastIndex = 0; | 178 regexp.lastIndex = 0; |
| 176 return null; | 179 return null; |
| 177 } | 180 } |
| 178 | 181 |
| 179 | 182 |
| 180 // ES#sec-regexp.prototype.exec | 183 // ES#sec-regexp.prototype.exec |
| 181 // RegExp.prototype.exec ( string ) | 184 // RegExp.prototype.exec ( string ) |
| 182 function RegExpSubclassExecJS(string) { | 185 function RegExpSubclassExecJS(string) { |
| 183 if (!IS_REGEXP(this)) { | 186 if (!IS_REGEXP(this)) { |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 212 | 215 |
| 213 if (IS_NULL(matchIndices)) { | 216 if (IS_NULL(matchIndices)) { |
| 214 this.lastIndex = 0; | 217 this.lastIndex = 0; |
| 215 return null; | 218 return null; |
| 216 } | 219 } |
| 217 | 220 |
| 218 // Successful match. | 221 // Successful match. |
| 219 if (updateLastIndex) { | 222 if (updateLastIndex) { |
| 220 this.lastIndex = RegExpLastMatchInfo[CAPTURE1]; | 223 this.lastIndex = RegExpLastMatchInfo[CAPTURE1]; |
| 221 } | 224 } |
| 222 RETURN_NEW_RESULT_FROM_MATCH_INFO(matchIndices, string); | 225 RETURN_NEW_RESULT_FROM_MATCH_INFO(matchIndices, string, this); |
| 223 } | 226 } |
| 224 %FunctionRemovePrototype(RegExpSubclassExecJS); | 227 %FunctionRemovePrototype(RegExpSubclassExecJS); |
| 225 | 228 |
| 226 | 229 |
| 227 // Legacy implementation of RegExp.prototype.exec | 230 // Legacy implementation of RegExp.prototype.exec |
| 228 function RegExpExecJS(string) { | 231 function RegExpExecJS(string) { |
| 229 if (!IS_REGEXP(this)) { | 232 if (!IS_REGEXP(this)) { |
| 230 throw MakeTypeError(kIncompatibleMethodReceiver, | 233 throw MakeTypeError(kIncompatibleMethodReceiver, |
| 231 'RegExp.prototype.exec', this); | 234 'RegExp.prototype.exec', this); |
| 232 } | 235 } |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 253 | 256 |
| 254 if (IS_NULL(matchIndices)) { | 257 if (IS_NULL(matchIndices)) { |
| 255 this.lastIndex = 0; | 258 this.lastIndex = 0; |
| 256 return null; | 259 return null; |
| 257 } | 260 } |
| 258 | 261 |
| 259 // Successful match. | 262 // Successful match. |
| 260 if (updateLastIndex) { | 263 if (updateLastIndex) { |
| 261 this.lastIndex = RegExpLastMatchInfo[CAPTURE1]; | 264 this.lastIndex = RegExpLastMatchInfo[CAPTURE1]; |
| 262 } | 265 } |
| 263 RETURN_NEW_RESULT_FROM_MATCH_INFO(matchIndices, string); | 266 RETURN_NEW_RESULT_FROM_MATCH_INFO(matchIndices, string, this); |
| 264 } | 267 } |
| 265 | 268 |
| 266 | 269 |
| 267 // ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S ) | 270 // ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S ) |
| 268 // Also takes an optional exec method in case our caller | 271 // Also takes an optional exec method in case our caller |
| 269 // has already fetched exec. | 272 // has already fetched exec. |
| 270 function RegExpSubclassExec(regexp, string, exec) { | 273 function RegExpSubclassExec(regexp, string, exec) { |
| 271 if (IS_UNDEFINED(exec)) { | 274 if (IS_UNDEFINED(exec)) { |
| 272 exec = regexp.exec; | 275 exec = regexp.exec; |
| 273 } | 276 } |
| (...skipping 933 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1207 %ToFastProperties(GlobalRegExp); | 1210 %ToFastProperties(GlobalRegExp); |
| 1208 | 1211 |
| 1209 // ------------------------------------------------------------------- | 1212 // ------------------------------------------------------------------- |
| 1210 // Internal | 1213 // Internal |
| 1211 | 1214 |
| 1212 var InternalRegExpMatchInfo = new InternalPackedArray(2, "", UNDEFINED, 0, 0); | 1215 var InternalRegExpMatchInfo = new InternalPackedArray(2, "", UNDEFINED, 0, 0); |
| 1213 | 1216 |
| 1214 function InternalRegExpMatch(regexp, subject) { | 1217 function InternalRegExpMatch(regexp, subject) { |
| 1215 var matchInfo = %_RegExpExec(regexp, subject, 0, InternalRegExpMatchInfo); | 1218 var matchInfo = %_RegExpExec(regexp, subject, 0, InternalRegExpMatchInfo); |
| 1216 if (!IS_NULL(matchInfo)) { | 1219 if (!IS_NULL(matchInfo)) { |
| 1217 RETURN_NEW_RESULT_FROM_MATCH_INFO(matchInfo, subject); | 1220 RETURN_NEW_RESULT_FROM_MATCH_INFO(matchInfo, subject, regexp); |
| 1218 } | 1221 } |
| 1219 return null; | 1222 return null; |
| 1220 } | 1223 } |
| 1221 | 1224 |
| 1222 function InternalRegExpReplace(regexp, subject, replacement) { | 1225 function InternalRegExpReplace(regexp, subject, replacement) { |
| 1223 return %StringReplaceGlobalRegExpWithString( | 1226 return %StringReplaceGlobalRegExpWithString( |
| 1224 subject, regexp, replacement, InternalRegExpMatchInfo); | 1227 subject, regexp, replacement, InternalRegExpMatchInfo); |
| 1225 } | 1228 } |
| 1226 | 1229 |
| 1227 // ------------------------------------------------------------------- | 1230 // ------------------------------------------------------------------- |
| 1228 // Exports | 1231 // Exports |
| 1229 | 1232 |
| 1230 utils.Export(function(to) { | 1233 utils.Export(function(to) { |
| 1231 to.InternalRegExpMatch = InternalRegExpMatch; | 1234 to.InternalRegExpMatch = InternalRegExpMatch; |
| 1232 to.InternalRegExpReplace = InternalRegExpReplace; | 1235 to.InternalRegExpReplace = InternalRegExpReplace; |
| 1233 to.IsRegExp = IsRegExp; | 1236 to.IsRegExp = IsRegExp; |
| 1234 to.RegExpExec = DoRegExpExec; | 1237 to.RegExpExec = DoRegExpExec; |
| 1235 to.RegExpInitialize = RegExpInitialize; | 1238 to.RegExpInitialize = RegExpInitialize; |
| 1236 to.RegExpLastMatchInfo = RegExpLastMatchInfo; | 1239 to.RegExpLastMatchInfo = RegExpLastMatchInfo; |
| 1237 to.RegExpSubclassExecJS = RegExpSubclassExecJS; | 1240 to.RegExpSubclassExecJS = RegExpSubclassExecJS; |
| 1238 to.RegExpSubclassMatch = RegExpSubclassMatch; | 1241 to.RegExpSubclassMatch = RegExpSubclassMatch; |
| 1239 to.RegExpSubclassReplace = RegExpSubclassReplace; | 1242 to.RegExpSubclassReplace = RegExpSubclassReplace; |
| 1240 to.RegExpSubclassSearch = RegExpSubclassSearch; | 1243 to.RegExpSubclassSearch = RegExpSubclassSearch; |
| 1241 to.RegExpSubclassSplit = RegExpSubclassSplit; | 1244 to.RegExpSubclassSplit = RegExpSubclassSplit; |
| 1242 to.RegExpSubclassTest = RegExpSubclassTest; | 1245 to.RegExpSubclassTest = RegExpSubclassTest; |
| 1243 to.RegExpTest = RegExpTest; | 1246 to.RegExpTest = RegExpTest; |
| 1244 }); | 1247 }); |
| 1245 | 1248 |
| 1246 }) | 1249 }) |
| OLD | NEW |