| 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 | |
| 13 | |
| 14 var GlobalRegExp = global.RegExp; | |
| 15 var GlobalRegExpPrototype = GlobalRegExp.prototype; | |
| 16 var RegExpExecJS = GlobalRegExp.prototype.exec; | |
| 17 var matchSymbol = utils.ImportNow("match_symbol"); | |
| 18 | |
| 19 // ------------------------------------------------------------------- | |
| 20 | 12 |
| 21 // Property of the builtins object for recording the result of the last | 13 // Property of the builtins object for recording the result of the last |
| 22 // regexp match. The property RegExpLastMatchInfo includes the matchIndices | 14 // regexp match. The property RegExpLastMatchInfo includes the matchIndices |
| 23 // array of the last successful regexp match (an array of start/end index | 15 // array of the last successful regexp match (an array of start/end index |
| 24 // pairs for the match and all the captured substrings), the invariant is | 16 // pairs for the match and all the captured substrings), the invariant is |
| 25 // that there are at least two capture indices. The array also contains | 17 // that there are at least two capture indices. The array also contains |
| 26 // the subject string for the last successful match. | 18 // the subject string for the last successful match. |
| 27 // We use a JSObject rather than a JSArray so we don't have to manually update | 19 // We use a JSObject rather than a JSArray so we don't have to manually update |
| 28 // its length. | 20 // its length. |
| 29 var RegExpLastMatchInfo = { | 21 var RegExpLastMatchInfo = { |
| 30 REGEXP_NUMBER_OF_CAPTURES: 2, | 22 REGEXP_NUMBER_OF_CAPTURES: 2, |
| 31 REGEXP_LAST_SUBJECT: "", | 23 REGEXP_LAST_SUBJECT: "", |
| 32 REGEXP_LAST_INPUT: UNDEFINED, // Settable with RegExpSetInput. | 24 REGEXP_LAST_INPUT: UNDEFINED, // Settable with RegExpSetInput. |
| 33 CAPTURE0: 0, | 25 CAPTURE0: 0, |
| 34 CAPTURE1: 0 | 26 CAPTURE1: 0 |
| 35 }; | 27 }; |
| 36 | 28 |
| 37 // ------------------------------------------------------------------- | |
| 38 | |
| 39 // ES#sec-isregexp IsRegExp ( argument ) | |
| 40 function IsRegExp(o) { | |
| 41 if (!IS_RECEIVER(o)) return false; | |
| 42 var is_regexp = o[matchSymbol]; | |
| 43 if (!IS_UNDEFINED(is_regexp)) return TO_BOOLEAN(is_regexp); | |
| 44 return IS_REGEXP(o); | |
| 45 } | |
| 46 | |
| 47 | |
| 48 // ES#sec-regexpinitialize | |
| 49 // Runtime Semantics: RegExpInitialize ( obj, pattern, flags ) | |
| 50 function RegExpInitialize(object, pattern, flags) { | |
| 51 pattern = IS_UNDEFINED(pattern) ? '' : TO_STRING(pattern); | |
| 52 flags = IS_UNDEFINED(flags) ? '' : TO_STRING(flags); | |
| 53 %RegExpInitializeAndCompile(object, pattern, flags); | |
| 54 return object; | |
| 55 } | |
| 56 | |
| 57 | |
| 58 // This is kind of performance sensitive, so we want to avoid unnecessary | |
| 59 // type checks on inputs. But we also don't want to inline it several times | |
| 60 // manually, so we use a macro :-) | |
| 61 macro RETURN_NEW_RESULT_FROM_MATCH_INFO(MATCHINFO, STRING) | |
| 62 var numResults = NUMBER_OF_CAPTURES(MATCHINFO) >> 1; | |
| 63 var start = MATCHINFO[CAPTURE0]; | |
| 64 var end = MATCHINFO[CAPTURE1]; | |
| 65 // Calculate the substring of the first match before creating the result array | |
| 66 // to avoid an unnecessary write barrier storing the first result. | |
| 67 var first = %_SubString(STRING, start, end); | |
| 68 var result = %_RegExpConstructResult(numResults, start, STRING); | |
| 69 result[0] = first; | |
| 70 if (numResults == 1) return result; | |
| 71 var j = REGEXP_FIRST_CAPTURE + 2; | |
| 72 for (var i = 1; i < numResults; i++) { | |
| 73 start = MATCHINFO[j++]; | |
| 74 if (start != -1) { | |
| 75 end = MATCHINFO[j]; | |
| 76 result[i] = %_SubString(STRING, start, end); | |
| 77 } | |
| 78 j++; | |
| 79 } | |
| 80 return result; | |
| 81 endmacro | |
| 82 | |
| 83 // ES#sec-getsubstitution | 29 // ES#sec-getsubstitution |
| 84 // GetSubstitution(matched, str, position, captures, replacement) | 30 // GetSubstitution(matched, str, position, captures, replacement) |
| 85 // Expand the $-expressions in the string and return a new string with | 31 // Expand the $-expressions in the string and return a new string with |
| 86 // the result. | 32 // the result. |
| 87 function GetSubstitution(matched, string, position, captures, replacement) { | 33 function GetSubstitution(matched, string, position, captures, replacement) { |
| 88 var matchLength = matched.length; | 34 var matchLength = matched.length; |
| 89 var stringLength = string.length; | 35 var stringLength = string.length; |
| 90 var capturesLength = captures.length; | 36 var capturesLength = captures.length; |
| 91 var tailPos = position + matchLength; | 37 var tailPos = position + matchLength; |
| 92 var result = ""; | 38 var result = ""; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 } | 109 } |
| 164 } | 110 } |
| 165 return result; | 111 return result; |
| 166 } | 112 } |
| 167 | 113 |
| 168 // ------------------------------------------------------------------- | 114 // ------------------------------------------------------------------- |
| 169 | 115 |
| 170 %InstallToContext(["regexp_last_match_info", RegExpLastMatchInfo]); | 116 %InstallToContext(["regexp_last_match_info", RegExpLastMatchInfo]); |
| 171 | 117 |
| 172 // ------------------------------------------------------------------- | 118 // ------------------------------------------------------------------- |
| 173 // Internal | |
| 174 | |
| 175 var InternalRegExpMatchInfo = { | |
| 176 REGEXP_NUMBER_OF_CAPTURES: 2, | |
| 177 REGEXP_LAST_SUBJECT: "", | |
| 178 REGEXP_LAST_INPUT: UNDEFINED, | |
| 179 CAPTURE0: 0, | |
| 180 CAPTURE1: 0 | |
| 181 }; | |
| 182 | |
| 183 function InternalRegExpMatch(regexp, subject) { | |
| 184 var matchInfo = %_RegExpExec(regexp, subject, 0, InternalRegExpMatchInfo); | |
| 185 if (!IS_NULL(matchInfo)) { | |
| 186 RETURN_NEW_RESULT_FROM_MATCH_INFO(matchInfo, subject); | |
| 187 } | |
| 188 return null; | |
| 189 } | |
| 190 | |
| 191 function InternalRegExpReplace(regexp, subject, replacement) { | |
| 192 return %StringReplaceGlobalRegExpWithString( | |
| 193 subject, regexp, replacement, InternalRegExpMatchInfo); | |
| 194 } | |
| 195 | |
| 196 // ------------------------------------------------------------------- | |
| 197 // Exports | 119 // Exports |
| 198 | 120 |
| 199 utils.Export(function(to) { | 121 utils.Export(function(to) { |
| 200 to.GetSubstitution = GetSubstitution; | 122 to.GetSubstitution = GetSubstitution; |
| 201 to.InternalRegExpMatch = InternalRegExpMatch; | |
| 202 to.InternalRegExpReplace = InternalRegExpReplace; | |
| 203 to.IsRegExp = IsRegExp; | |
| 204 to.RegExpInitialize = RegExpInitialize; | |
| 205 to.RegExpLastMatchInfo = RegExpLastMatchInfo; | |
| 206 }); | 123 }); |
| 207 | 124 |
| 208 }) | 125 }) |
| OLD | NEW |