| 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 |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 | 150 |
| 151 | 151 |
| 152 // ECMA-262 section 15.5.4.10 | 152 // ECMA-262 section 15.5.4.10 |
| 153 function StringMatchJS(regexp) { | 153 function StringMatchJS(regexp) { |
| 154 CHECK_OBJECT_COERCIBLE(this, "String.prototype.match"); | 154 CHECK_OBJECT_COERCIBLE(this, "String.prototype.match"); |
| 155 | 155 |
| 156 var subject = TO_STRING(this); | 156 var subject = TO_STRING(this); |
| 157 if (IS_REGEXP(regexp)) { | 157 if (IS_REGEXP(regexp)) { |
| 158 if (!regexp.global) return RegExpExecNoTests(regexp, subject, 0); | 158 if (!regexp.global) return RegExpExecNoTests(regexp, subject, 0); |
| 159 var result = %StringMatch(subject, regexp, RegExpLastMatchInfo); | 159 var result = %StringMatch(subject, regexp, RegExpLastMatchInfo); |
| 160 if (result !== null) $regexpLastMatchInfoOverride = null; | |
| 161 regexp.lastIndex = 0; | 160 regexp.lastIndex = 0; |
| 162 return result; | 161 return result; |
| 163 } | 162 } |
| 164 // Non-regexp argument. | 163 // Non-regexp argument. |
| 165 regexp = new GlobalRegExp(regexp); | 164 regexp = new GlobalRegExp(regexp); |
| 166 return RegExpExecNoTests(regexp, subject, 0); | 165 return RegExpExecNoTests(regexp, subject, 0); |
| 167 } | 166 } |
| 168 | 167 |
| 169 | 168 |
| 170 // ECMA-262 v6, section 21.1.3.12 | 169 // ECMA-262 v6, section 21.1.3.12 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 return %_SubString(subject, 0, match[CAPTURE0]) + | 236 return %_SubString(subject, 0, match[CAPTURE0]) + |
| 238 %_SubString(subject, match[CAPTURE1], subject.length) | 237 %_SubString(subject, match[CAPTURE1], subject.length) |
| 239 } | 238 } |
| 240 return ExpandReplacement(replace, subject, RegExpLastMatchInfo, | 239 return ExpandReplacement(replace, subject, RegExpLastMatchInfo, |
| 241 %_SubString(subject, 0, match[CAPTURE0])) + | 240 %_SubString(subject, 0, match[CAPTURE0])) + |
| 242 %_SubString(subject, match[CAPTURE1], subject.length); | 241 %_SubString(subject, match[CAPTURE1], subject.length); |
| 243 } | 242 } |
| 244 | 243 |
| 245 // Global regexp search, string replace. | 244 // Global regexp search, string replace. |
| 246 search.lastIndex = 0; | 245 search.lastIndex = 0; |
| 247 if ($regexpLastMatchInfoOverride == null) { | 246 return %StringReplaceGlobalRegExpWithString( |
| 248 return %StringReplaceGlobalRegExpWithString( | 247 subject, search, replace, RegExpLastMatchInfo); |
| 249 subject, search, replace, RegExpLastMatchInfo); | |
| 250 } else { | |
| 251 // We use this hack to detect whether StringReplaceRegExpWithString | |
| 252 // found at least one hit. In that case we need to remove any | |
| 253 // override. | |
| 254 var saved_subject = RegExpLastMatchInfo[LAST_SUBJECT_INDEX]; | |
| 255 RegExpLastMatchInfo[LAST_SUBJECT_INDEX] = 0; | |
| 256 var answer = %StringReplaceGlobalRegExpWithString( | |
| 257 subject, search, replace, RegExpLastMatchInfo); | |
| 258 if (%_IsSmi(RegExpLastMatchInfo[LAST_SUBJECT_INDEX])) { | |
| 259 RegExpLastMatchInfo[LAST_SUBJECT_INDEX] = saved_subject; | |
| 260 } else { | |
| 261 $regexpLastMatchInfoOverride = null; | |
| 262 } | |
| 263 return answer; | |
| 264 } | |
| 265 } | 248 } |
| 266 | 249 |
| 267 if (search.global) { | 250 if (search.global) { |
| 268 // Global regexp search, function replace. | 251 // Global regexp search, function replace. |
| 269 return StringReplaceGlobalRegExpWithFunction(subject, search, replace); | 252 return StringReplaceGlobalRegExpWithFunction(subject, search, replace); |
| 270 } | 253 } |
| 271 // Non-global regexp search, function replace. | 254 // Non-global regexp search, function replace. |
| 272 return StringReplaceNonGlobalRegExpWithFunction(subject, search, replace); | 255 return StringReplaceNonGlobalRegExpWithFunction(subject, search, replace); |
| 273 } | 256 } |
| 274 | 257 |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 } | 414 } |
| 432 var len = res.length; | 415 var len = res.length; |
| 433 if (NUMBER_OF_CAPTURES(RegExpLastMatchInfo) == 2) { | 416 if (NUMBER_OF_CAPTURES(RegExpLastMatchInfo) == 2) { |
| 434 // If the number of captures is two then there are no explicit captures in | 417 // If the number of captures is two then there are no explicit captures in |
| 435 // the regexp, just the implicit capture that captures the whole match. In | 418 // the regexp, just the implicit capture that captures the whole match. In |
| 436 // this case we can simplify quite a bit and end up with something faster. | 419 // this case we can simplify quite a bit and end up with something faster. |
| 437 // The builder will consist of some integers that indicate slices of the | 420 // The builder will consist of some integers that indicate slices of the |
| 438 // input string and some replacements that were returned from the replace | 421 // input string and some replacements that were returned from the replace |
| 439 // function. | 422 // function. |
| 440 var match_start = 0; | 423 var match_start = 0; |
| 441 var override = new InternalPackedArray(null, 0, subject); | |
| 442 for (var i = 0; i < len; i++) { | 424 for (var i = 0; i < len; i++) { |
| 443 var elem = res[i]; | 425 var elem = res[i]; |
| 444 if (%_IsSmi(elem)) { | 426 if (%_IsSmi(elem)) { |
| 445 // Integers represent slices of the original string. Use these to | 427 // Integers represent slices of the original string. |
| 446 // get the offsets we need for the override array (so things like | |
| 447 // RegExp.leftContext work during the callback function. | |
| 448 if (elem > 0) { | 428 if (elem > 0) { |
| 449 match_start = (elem >> 11) + (elem & 0x7ff); | 429 match_start = (elem >> 11) + (elem & 0x7ff); |
| 450 } else { | 430 } else { |
| 451 match_start = res[++i] - elem; | 431 match_start = res[++i] - elem; |
| 452 } | 432 } |
| 453 } else { | 433 } else { |
| 454 override[0] = elem; | |
| 455 override[1] = match_start; | |
| 456 $regexpLastMatchInfoOverride = override; | |
| 457 var func_result = replace(elem, match_start, subject); | 434 var func_result = replace(elem, match_start, subject); |
| 458 // Overwrite the i'th element in the results with the string we got | 435 // Overwrite the i'th element in the results with the string we got |
| 459 // back from the callback function. | 436 // back from the callback function. |
| 460 res[i] = TO_STRING(func_result); | 437 res[i] = TO_STRING(func_result); |
| 461 match_start += elem.length; | 438 match_start += elem.length; |
| 462 } | 439 } |
| 463 } | 440 } |
| 464 } else { | 441 } else { |
| 465 for (var i = 0; i < len; i++) { | 442 for (var i = 0; i < len; i++) { |
| 466 var elem = res[i]; | 443 var elem = res[i]; |
| 467 if (!%_IsSmi(elem)) { | 444 if (!%_IsSmi(elem)) { |
| 468 // elem must be an Array. | 445 // elem must be an Array. |
| 469 // Use the apply argument as backing for global RegExp properties. | 446 // Use the apply argument as backing for global RegExp properties. |
| 470 $regexpLastMatchInfoOverride = elem; | |
| 471 var func_result = %Apply(replace, UNDEFINED, elem, 0, elem.length); | 447 var func_result = %Apply(replace, UNDEFINED, elem, 0, elem.length); |
| 472 // Overwrite the i'th element in the results with the string we got | 448 // Overwrite the i'th element in the results with the string we got |
| 473 // back from the callback function. | 449 // back from the callback function. |
| 474 res[i] = TO_STRING(func_result); | 450 res[i] = TO_STRING(func_result); |
| 475 } | 451 } |
| 476 } | 452 } |
| 477 } | 453 } |
| 478 var result = %StringBuilderConcat(res, res.length, subject); | 454 var result = %StringBuilderConcat(res, len, subject); |
| 479 resultArray.length = 0; | 455 resultArray.length = 0; |
| 480 reusableReplaceArray = resultArray; | 456 reusableReplaceArray = resultArray; |
| 481 return result; | 457 return result; |
| 482 } | 458 } |
| 483 | 459 |
| 484 | 460 |
| 485 function StringReplaceNonGlobalRegExpWithFunction(subject, regexp, replace) { | 461 function StringReplaceNonGlobalRegExpWithFunction(subject, regexp, replace) { |
| 486 var matchInfo = RegExpExec(regexp, subject, 0); | 462 var matchInfo = RegExpExec(regexp, subject, 0); |
| 487 if (IS_NULL(matchInfo)) { | 463 if (IS_NULL(matchInfo)) { |
| 488 regexp.lastIndex = 0; | 464 regexp.lastIndex = 0; |
| (...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1194 to.StringLastIndexOf = StringLastIndexOfJS; | 1170 to.StringLastIndexOf = StringLastIndexOfJS; |
| 1195 to.StringMatch = StringMatchJS; | 1171 to.StringMatch = StringMatchJS; |
| 1196 to.StringReplace = StringReplace; | 1172 to.StringReplace = StringReplace; |
| 1197 to.StringSlice = StringSlice; | 1173 to.StringSlice = StringSlice; |
| 1198 to.StringSplit = StringSplitJS; | 1174 to.StringSplit = StringSplitJS; |
| 1199 to.StringSubstr = StringSubstr; | 1175 to.StringSubstr = StringSubstr; |
| 1200 to.StringSubstring = StringSubstring; | 1176 to.StringSubstring = StringSubstring; |
| 1201 }); | 1177 }); |
| 1202 | 1178 |
| 1203 }) | 1179 }) |
| OLD | NEW |