OLD | NEW |
---|---|
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
128 this.answer = 0; | 128 this.answer = 0; |
129 // answerSaved marks whether the contents of answer is valid for a cache | 129 // answerSaved marks whether the contents of answer is valid for a cache |
130 // hit in RegExpExec, StringMatch and StringSplit. | 130 // hit in RegExpExec, StringMatch and StringSplit. |
131 this.answerSaved = false; | 131 this.answerSaved = false; |
132 } | 132 } |
133 | 133 |
134 | 134 |
135 var regExpCache = new RegExpCache(); | 135 var regExpCache = new RegExpCache(); |
136 | 136 |
137 | 137 |
138 function CloneRegexpAnswer(array) { | 138 function CloneRegExpResult(array) { |
139 if (array == null) return null; | 139 if (array == null) return null; |
140 var len = array.length; | 140 var length = array.length; |
141 var answer = new $Array(len); | 141 var answer = %_RegExpConstructResult(length, array.index, array.input); |
Søren Thygesen Gjesse
2010/04/13 07:22:29
Will it be possible to pass in the array to have t
Lasse Reichstein
2010/04/13 09:50:56
It's a good idea for an optional argument. The fun
| |
142 for (var i = 0; i < len; i++) { | 142 for (var i = 0; i < length; i++) { |
143 answer[i] = array[i]; | 143 answer[i] = array[i]; |
144 } | 144 } |
145 answer.index = array.index; | |
146 answer.input = array.input; | |
147 return answer; | 145 return answer; |
148 } | 146 } |
149 | 147 |
150 | 148 |
149 function BuildResultFromMatchInfo(lastMatchInfo, s) { | |
150 var numResults = NUMBER_OF_CAPTURES(lastMatchInfo) >> 1; | |
151 var result = %_RegExpConstructResult(numResults, lastMatchInfo[CAPTURE0], s); | |
152 if (numResults === 1) { | |
153 var matchStart = lastMatchInfo[CAPTURE(0)]; | |
154 var matchEnd = lastMatchInfo[CAPTURE(1)]; | |
155 result[0] = SubString(s, matchStart, matchEnd); | |
156 } else { | |
157 for (var i = 0; i < numResults; i++) { | |
158 var matchStart = lastMatchInfo[CAPTURE(i << 1)]; | |
159 var matchEnd = lastMatchInfo[CAPTURE((i << 1) + 1)]; | |
160 if (matchStart != -1 && matchEnd != -1) { | |
161 result[i] = SubString(s, matchStart, matchEnd); | |
162 } else { | |
163 // Make sure the element is present. Avoid reading the undefined | |
164 // property from the global object since this may change. | |
165 result[i] = void 0; | |
166 } | |
167 } | |
168 } | |
169 return result; | |
170 } | |
171 | |
172 | |
173 function RegExpExecNoTests(regexp, string, start) { | |
174 // Must be called with RegExp, string and positive integer as arguments. | |
175 var matchInfo = DoRegExpExec(regexp, string, start); | |
176 var result = null; | |
177 if (matchInfo !== null) { | |
178 result = BuildResultFromMatchInfo(matchInfo, string); | |
179 } | |
180 return result; | |
181 } | |
182 | |
183 | |
151 function RegExpExec(string) { | 184 function RegExpExec(string) { |
152 if (!IS_REGEXP(this)) { | 185 if (!IS_REGEXP(this)) { |
153 throw MakeTypeError('incompatible_method_receiver', | 186 throw MakeTypeError('incompatible_method_receiver', |
154 ['RegExp.prototype.exec', this]); | 187 ['RegExp.prototype.exec', this]); |
155 } | 188 } |
156 | 189 |
157 var cache = regExpCache; | 190 var cache = regExpCache; |
158 var saveAnswer = false; | 191 var saveAnswer = false; |
159 | 192 |
160 if (%_ObjectEquals(cache.type, 'exec') && | 193 if (%_ObjectEquals(cache.type, 'exec') && |
161 %_ObjectEquals(cache.lastIndex, this.lastIndex) && | 194 %_ObjectEquals(cache.lastIndex, this.lastIndex) && |
162 %_ObjectEquals(cache.regExp, this) && | 195 %_ObjectEquals(cache.regExp, this) && |
163 %_ObjectEquals(cache.subject, string)) { | 196 %_ObjectEquals(cache.subject, string)) { |
164 if (cache.answerSaved) { | 197 if (cache.answerSaved) { |
165 return CloneRegexpAnswer(cache.answer); | 198 return CloneRegExpResult(cache.answer); |
166 } else { | 199 } else { |
167 saveAnswer = true; | 200 saveAnswer = true; |
168 } | 201 } |
169 } | 202 } |
170 | 203 |
171 if (%_ArgumentsLength() == 0) { | 204 if (%_ArgumentsLength() == 0) { |
172 var regExpInput = LAST_INPUT(lastMatchInfo); | 205 var regExpInput = LAST_INPUT(lastMatchInfo); |
173 if (IS_UNDEFINED(regExpInput)) { | 206 if (IS_UNDEFINED(regExpInput)) { |
174 throw MakeError('no_input_to_regexp', [this]); | 207 throw MakeError('no_input_to_regexp', [this]); |
175 } | 208 } |
(...skipping 22 matching lines...) Expand all Loading... | |
198 if (this.global) this.lastIndex = 0; | 231 if (this.global) this.lastIndex = 0; |
199 cache.lastIndex = lastIndex; | 232 cache.lastIndex = lastIndex; |
200 cache.regExp = this; | 233 cache.regExp = this; |
201 cache.subject = s; | 234 cache.subject = s; |
202 cache.answer = matchIndices; // Null. | 235 cache.answer = matchIndices; // Null. |
203 cache.answerSaved = true; // Safe since no cloning is needed. | 236 cache.answerSaved = true; // Safe since no cloning is needed. |
204 cache.type = 'exec'; | 237 cache.type = 'exec'; |
205 return matchIndices; // No match. | 238 return matchIndices; // No match. |
206 } | 239 } |
207 | 240 |
208 var numResults = NUMBER_OF_CAPTURES(lastMatchInfo) >> 1; | 241 var result = BuildResultFromMatchInfo(matchIndices, s); |
209 var result; | |
210 if (numResults === 1) { | |
211 var matchStart = lastMatchInfo[CAPTURE(0)]; | |
212 var matchEnd = lastMatchInfo[CAPTURE(1)]; | |
213 result = [SubString(s, matchStart, matchEnd)]; | |
214 } else { | |
215 result = new $Array(numResults); | |
216 for (var i = 0; i < numResults; i++) { | |
217 var matchStart = lastMatchInfo[CAPTURE(i << 1)]; | |
218 var matchEnd = lastMatchInfo[CAPTURE((i << 1) + 1)]; | |
219 if (matchStart != -1 && matchEnd != -1) { | |
220 result[i] = SubString(s, matchStart, matchEnd); | |
221 } else { | |
222 // Make sure the element is present. Avoid reading the undefined | |
223 // property from the global object since this may change. | |
224 result[i] = void 0; | |
225 } | |
226 } | |
227 } | |
228 | 242 |
229 result.index = lastMatchInfo[CAPTURE0]; | |
230 result.input = s; | |
231 if (this.global) { | 243 if (this.global) { |
232 this.lastIndex = lastMatchInfo[CAPTURE1]; | 244 this.lastIndex = lastMatchInfo[CAPTURE1]; |
233 } else { | 245 } else { |
234 cache.regExp = this; | 246 cache.regExp = this; |
235 cache.subject = s; | 247 cache.subject = s; |
236 cache.lastIndex = lastIndex; | 248 cache.lastIndex = lastIndex; |
237 if (saveAnswer) cache.answer = CloneRegexpAnswer(result); | 249 if (saveAnswer) cache.answer = CloneRegExpResult(result); |
238 cache.answerSaved = saveAnswer; | 250 cache.answerSaved = saveAnswer; |
239 cache.type = 'exec'; | 251 cache.type = 'exec'; |
240 } | 252 } |
241 return result; | 253 return result; |
242 | 254 |
243 } | 255 } |
244 | 256 |
245 | 257 |
246 // Section 15.10.6.3 doesn't actually make sense, but the intention seems to be | 258 // Section 15.10.6.3 doesn't actually make sense, but the intention seems to be |
247 // that test is defined in terms of String.prototype.exec. However, it probably | 259 // that test is defined in terms of String.prototype.exec. However, it probably |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
503 %DefineAccessor($RegExp, "$'", SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE); | 515 %DefineAccessor($RegExp, "$'", SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE); |
504 | 516 |
505 for (var i = 1; i < 10; ++i) { | 517 for (var i = 1; i < 10; ++i) { |
506 %DefineAccessor($RegExp, '$' + i, GETTER, RegExpMakeCaptureGetter(i), DONT_D ELETE); | 518 %DefineAccessor($RegExp, '$' + i, GETTER, RegExpMakeCaptureGetter(i), DONT_D ELETE); |
507 %DefineAccessor($RegExp, '$' + i, SETTER, NoOpSetter, DONT_DELETE); | 519 %DefineAccessor($RegExp, '$' + i, SETTER, NoOpSetter, DONT_DELETE); |
508 } | 520 } |
509 } | 521 } |
510 | 522 |
511 | 523 |
512 SetupRegExp(); | 524 SetupRegExp(); |
OLD | NEW |