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 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 115 } | 115 } |
| 116 | 116 |
| 117 RegExpInitialize(this, pattern, flags); | 117 RegExpInitialize(this, pattern, flags); |
| 118 | 118 |
| 119 // Return undefined for compatibility with JSC. | 119 // Return undefined for compatibility with JSC. |
| 120 // See http://crbug.com/585775 for web compat details. | 120 // See http://crbug.com/585775 for web compat details. |
| 121 } | 121 } |
| 122 | 122 |
| 123 | 123 |
| 124 function DoRegExpExec(regexp, string, index) { | 124 function DoRegExpExec(regexp, string, index) { |
| 125 return %_RegExpExec(regexp, string, index, RegExpLastMatchInfo); | 125 return %RegExpExec(regexp, string, index, RegExpLastMatchInfo); |
|
Dan Ehrenberg
2016/03/23 15:55:41
Why this change? Will it have performance implicat
Yang
2016/03/24 06:14:13
Thanks for catching this. I changed it for easier
| |
| 126 } | 126 } |
| 127 | 127 |
| 128 | 128 |
| 129 // This is kind of performance sensitive, so we want to avoid unnecessary | 129 // This is kind of performance sensitive, so we want to avoid unnecessary |
| 130 // type checks on inputs. But we also don't want to inline it several times | 130 // type checks on inputs. But we also don't want to inline it several times |
| 131 // manually, so we use a macro :-) | 131 // manually, so we use a macro :-) |
| 132 macro RETURN_NEW_RESULT_FROM_MATCH_INFO(MATCHINFO, STRING) | 132 macro RETURN_NEW_RESULT_FROM_MATCH_INFO(MATCHINFO, STRING) |
| 133 var numResults = NUMBER_OF_CAPTURES(MATCHINFO) >> 1; | 133 var numResults = NUMBER_OF_CAPTURES(MATCHINFO) >> 1; |
| 134 var start = MATCHINFO[CAPTURE0]; | 134 var start = MATCHINFO[CAPTURE0]; |
| 135 var end = MATCHINFO[CAPTURE1]; | 135 var end = MATCHINFO[CAPTURE1]; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 147 result[i] = %_SubString(STRING, start, end); | 147 result[i] = %_SubString(STRING, start, end); |
| 148 } | 148 } |
| 149 j++; | 149 j++; |
| 150 } | 150 } |
| 151 return result; | 151 return result; |
| 152 endmacro | 152 endmacro |
| 153 | 153 |
| 154 | 154 |
| 155 function RegExpExecNoTests(regexp, string, start) { | 155 function RegExpExecNoTests(regexp, string, start) { |
| 156 // Must be called with RegExp, string and positive integer as arguments. | 156 // Must be called with RegExp, string and positive integer as arguments. |
| 157 var matchInfo = %_RegExpExec(regexp, string, start, RegExpLastMatchInfo); | 157 var matchInfo = %RegExpExec(regexp, string, start, RegExpLastMatchInfo); |
| 158 if (matchInfo !== null) { | 158 if (matchInfo !== null) { |
| 159 // ES6 21.2.5.2.2 step 18. | 159 // ES6 21.2.5.2.2 step 18. |
| 160 if (REGEXP_STICKY(regexp)) regexp.lastIndex = matchInfo[CAPTURE1]; | 160 if (REGEXP_STICKY(regexp)) regexp.lastIndex = matchInfo[CAPTURE1]; |
| 161 RETURN_NEW_RESULT_FROM_MATCH_INFO(matchInfo, string); | 161 RETURN_NEW_RESULT_FROM_MATCH_INFO(matchInfo, string); |
| 162 } | 162 } |
| 163 regexp.lastIndex = 0; | 163 regexp.lastIndex = 0; |
| 164 return null; | 164 return null; |
| 165 } | 165 } |
| 166 | 166 |
| 167 | 167 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 182 if (updateLastIndex) { | 182 if (updateLastIndex) { |
| 183 if (i < 0 || i > string.length) { | 183 if (i < 0 || i > string.length) { |
| 184 this.lastIndex = 0; | 184 this.lastIndex = 0; |
| 185 return null; | 185 return null; |
| 186 } | 186 } |
| 187 } else { | 187 } else { |
| 188 i = 0; | 188 i = 0; |
| 189 } | 189 } |
| 190 | 190 |
| 191 // matchIndices is either null or the RegExpLastMatchInfo array. | 191 // matchIndices is either null or the RegExpLastMatchInfo array. |
| 192 var matchIndices = %_RegExpExec(this, string, i, RegExpLastMatchInfo); | 192 var matchIndices = %RegExpExec(this, string, i, RegExpLastMatchInfo); |
| 193 | 193 |
| 194 if (IS_NULL(matchIndices)) { | 194 if (IS_NULL(matchIndices)) { |
| 195 this.lastIndex = 0; | 195 this.lastIndex = 0; |
| 196 return null; | 196 return null; |
| 197 } | 197 } |
| 198 | 198 |
| 199 // Successful match. | 199 // Successful match. |
| 200 if (updateLastIndex) { | 200 if (updateLastIndex) { |
| 201 this.lastIndex = RegExpLastMatchInfo[CAPTURE1]; | 201 this.lastIndex = RegExpLastMatchInfo[CAPTURE1]; |
| 202 } | 202 } |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 224 // Conversion is required by the ES2015 specification (RegExpBuiltinExec | 224 // Conversion is required by the ES2015 specification (RegExpBuiltinExec |
| 225 // algorithm, step 4) even if the value is discarded for non-global RegExps. | 225 // algorithm, step 4) even if the value is discarded for non-global RegExps. |
| 226 var i = TO_LENGTH(lastIndex); | 226 var i = TO_LENGTH(lastIndex); |
| 227 | 227 |
| 228 if (REGEXP_GLOBAL(this) || REGEXP_STICKY(this)) { | 228 if (REGEXP_GLOBAL(this) || REGEXP_STICKY(this)) { |
| 229 if (i < 0 || i > string.length) { | 229 if (i < 0 || i > string.length) { |
| 230 this.lastIndex = 0; | 230 this.lastIndex = 0; |
| 231 return false; | 231 return false; |
| 232 } | 232 } |
| 233 // matchIndices is either null or the RegExpLastMatchInfo array. | 233 // matchIndices is either null or the RegExpLastMatchInfo array. |
| 234 var matchIndices = %_RegExpExec(this, string, i, RegExpLastMatchInfo); | 234 var matchIndices = %RegExpExec(this, string, i, RegExpLastMatchInfo); |
| 235 if (IS_NULL(matchIndices)) { | 235 if (IS_NULL(matchIndices)) { |
| 236 this.lastIndex = 0; | 236 this.lastIndex = 0; |
| 237 return false; | 237 return false; |
| 238 } | 238 } |
| 239 this.lastIndex = RegExpLastMatchInfo[CAPTURE1]; | 239 this.lastIndex = RegExpLastMatchInfo[CAPTURE1]; |
| 240 return true; | 240 return true; |
| 241 } else { | 241 } else { |
| 242 // Non-global, non-sticky regexp. | 242 // Non-global, non-sticky regexp. |
| 243 // Remove irrelevant preceeding '.*' in a test regexp. The expression | 243 // Remove irrelevant preceeding '.*' in a test regexp. The expression |
| 244 // checks whether this.source starts with '.*' and that the third char is | 244 // checks whether this.source starts with '.*' and that the third char is |
| 245 // not a '?'. But see https://code.google.com/p/v8/issues/detail?id=3560 | 245 // not a '?'. But see https://code.google.com/p/v8/issues/detail?id=3560 |
| 246 var regexp = this; | 246 var regexp = this; |
| 247 var source = REGEXP_SOURCE(regexp); | 247 var source = REGEXP_SOURCE(regexp); |
| 248 if (regexp.length >= 3 && | 248 if (regexp.length >= 3 && |
| 249 %_StringCharCodeAt(regexp, 0) == 46 && // '.' | 249 %_StringCharCodeAt(regexp, 0) == 46 && // '.' |
| 250 %_StringCharCodeAt(regexp, 1) == 42 && // '*' | 250 %_StringCharCodeAt(regexp, 1) == 42 && // '*' |
| 251 %_StringCharCodeAt(regexp, 2) != 63) { // '?' | 251 %_StringCharCodeAt(regexp, 2) != 63) { // '?' |
| 252 regexp = TrimRegExp(regexp); | 252 regexp = TrimRegExp(regexp); |
| 253 } | 253 } |
| 254 // matchIndices is either null or the RegExpLastMatchInfo array. | 254 // matchIndices is either null or the RegExpLastMatchInfo array. |
| 255 var matchIndices = %_RegExpExec(regexp, string, 0, RegExpLastMatchInfo); | 255 var matchIndices = %RegExpExec(regexp, string, 0, RegExpLastMatchInfo); |
| 256 if (IS_NULL(matchIndices)) { | 256 if (IS_NULL(matchIndices)) { |
| 257 this.lastIndex = 0; | 257 this.lastIndex = 0; |
| 258 return false; | 258 return false; |
| 259 } | 259 } |
| 260 return true; | 260 return true; |
| 261 } | 261 } |
| 262 } | 262 } |
| 263 | 263 |
| 264 function TrimRegExp(regexp) { | 264 function TrimRegExp(regexp) { |
| 265 if (regexp_key !== regexp) { | 265 if (regexp_key !== regexp) { |
| (...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 768 utils.InstallGetterSetter(GlobalRegExp, "$'", RegExpGetRightContext, NoOpSetter, | 768 utils.InstallGetterSetter(GlobalRegExp, "$'", RegExpGetRightContext, NoOpSetter, |
| 769 DONT_ENUM | DONT_DELETE); | 769 DONT_ENUM | DONT_DELETE); |
| 770 | 770 |
| 771 for (var i = 1; i < 10; ++i) { | 771 for (var i = 1; i < 10; ++i) { |
| 772 utils.InstallGetterSetter(GlobalRegExp, '$' + i, RegExpMakeCaptureGetter(i), | 772 utils.InstallGetterSetter(GlobalRegExp, '$' + i, RegExpMakeCaptureGetter(i), |
| 773 NoOpSetter, DONT_DELETE); | 773 NoOpSetter, DONT_DELETE); |
| 774 } | 774 } |
| 775 %ToFastProperties(GlobalRegExp); | 775 %ToFastProperties(GlobalRegExp); |
| 776 | 776 |
| 777 // ------------------------------------------------------------------- | 777 // ------------------------------------------------------------------- |
| 778 // Internal | |
| 779 | |
| 780 var InternalRegExpMatchInfo = UNDEFINED; | |
| 781 | |
| 782 function InternalRegExpMatch(regexp, subject) { | |
| 783 if (IS_UNDEFINED(InternalRegExpMatchInfo)) { | |
| 784 InternalRegExpMatchInfo = new InternalPackedArray(2, "", UNDEFINED, 0, 0); | |
| 785 } | |
| 786 var matchInfo = %RegExpExec(regexp, subject, 0, InternalRegExpMatchInfo); | |
| 787 if (!IS_NULL(matchInfo)) { | |
| 788 RETURN_NEW_RESULT_FROM_MATCH_INFO(matchInfo, subject); | |
| 789 } | |
| 790 return null; | |
| 791 } | |
| 792 | |
| 793 function InternalRegExpReplace(regexp, subject, replacement) { | |
| 794 return %StringReplaceGlobalRegExpWithString( | |
| 795 subject, regexp, replacement, InternalRegExpMatchInfo); | |
| 796 } | |
| 797 | |
| 798 // ------------------------------------------------------------------- | |
| 778 // Exports | 799 // Exports |
| 779 | 800 |
| 780 utils.Export(function(to) { | 801 utils.Export(function(to) { |
| 802 to.InternalRegExpMatch = InternalRegExpMatch; | |
| 803 to.InternalRegExpReplace = InternalRegExpReplace; | |
| 804 to.IsRegExp = IsRegExp; | |
| 781 to.RegExpExec = DoRegExpExec; | 805 to.RegExpExec = DoRegExpExec; |
| 782 to.RegExpExecNoTests = RegExpExecNoTests; | 806 to.RegExpExecNoTests = RegExpExecNoTests; |
| 783 to.RegExpLastMatchInfo = RegExpLastMatchInfo; | 807 to.RegExpLastMatchInfo = RegExpLastMatchInfo; |
| 784 to.RegExpTest = RegExpTest; | 808 to.RegExpTest = RegExpTest; |
| 785 to.IsRegExp = IsRegExp; | |
| 786 }); | 809 }); |
| 787 | 810 |
| 788 }) | 811 }) |
| OLD | NEW |