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 |