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 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 // behavior. | 108 // behavior. |
109 if (IS_UNDEFINED(pattern) && %_ArgumentsLength() != 0) { | 109 if (IS_UNDEFINED(pattern) && %_ArgumentsLength() != 0) { |
110 DoConstructRegExp(this, 'undefined', flags, false); | 110 DoConstructRegExp(this, 'undefined', flags, false); |
111 } else { | 111 } else { |
112 DoConstructRegExp(this, pattern, flags, false); | 112 DoConstructRegExp(this, pattern, flags, false); |
113 } | 113 } |
114 } | 114 } |
115 | 115 |
116 | 116 |
117 function DoRegExpExec(regexp, string, index) { | 117 function DoRegExpExec(regexp, string, index) { |
118 return %_RegExpExec(regexp, string, index, lastMatchInfo); | 118 var result = %_RegExpExec(regexp, string, index, lastMatchInfo); |
| 119 if (result !== null) lastMatchInfoOverride = null; |
| 120 return result; |
119 } | 121 } |
120 | 122 |
121 | 123 |
122 function RegExpCache() { | 124 function RegExpCache() { |
123 this.type = 'none'; | 125 this.type = 'none'; |
124 this.regExp = 0; | 126 this.regExp = 0; |
125 this.subject = 0; | 127 this.subject = 0; |
126 this.replaceString = 0; | 128 this.replaceString = 0; |
127 this.lastIndex = 0; | 129 this.lastIndex = 0; |
128 this.answer = 0; | 130 this.answer = 0; |
129 // answerSaved marks whether the contents of answer is valid for a cache | 131 // answerSaved marks whether the contents of answer is valid for a cache |
130 // hit in RegExpExec, StringMatch and StringSplit. | 132 // hit in RegExpExec, StringMatch and StringSplit. |
131 this.answerSaved = false; | 133 this.answerSaved = false; |
132 } | 134 } |
133 | 135 |
134 | 136 |
135 var regExpCache = new RegExpCache(); | 137 var regExpCache = new RegExpCache(); |
136 | 138 |
137 | 139 |
138 function CloneRegExpResult(array) { | 140 function CloneRegExpResult(array) { |
139 if (array == null) return null; | 141 if (array == null) return null; |
140 var length = array.length; | 142 var length = array.length; |
141 var answer = %_RegExpConstructResult(length, array.index, array.input); | 143 var answer = %_RegExpConstructResult(length, array.index, array.input); |
142 for (var i = 0; i < length; i++) { | 144 for (var i = 0; i < length; i++) { |
143 answer[i] = array[i]; | 145 answer[i] = array[i]; |
144 } | 146 } |
145 return answer; | 147 return answer; |
146 } | 148 } |
147 | 149 |
148 | 150 |
149 function BuildResultFromMatchInfo(lastMatchInfo, s) { | 151 function BuildResultFromMatchInfo(lastMatchInfo, s) { |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 if (matchIndices == null) { | 232 if (matchIndices == null) { |
231 if (this.global) this.lastIndex = 0; | 233 if (this.global) this.lastIndex = 0; |
232 cache.lastIndex = lastIndex; | 234 cache.lastIndex = lastIndex; |
233 cache.regExp = this; | 235 cache.regExp = this; |
234 cache.subject = s; | 236 cache.subject = s; |
235 cache.answer = matchIndices; // Null. | 237 cache.answer = matchIndices; // Null. |
236 cache.answerSaved = true; // Safe since no cloning is needed. | 238 cache.answerSaved = true; // Safe since no cloning is needed. |
237 cache.type = 'exec'; | 239 cache.type = 'exec'; |
238 return matchIndices; // No match. | 240 return matchIndices; // No match. |
239 } | 241 } |
240 | 242 lastMatchInfoOverride = null; |
241 var result = BuildResultFromMatchInfo(matchIndices, s); | 243 var result = BuildResultFromMatchInfo(matchIndices, s); |
242 | 244 |
243 if (this.global) { | 245 if (this.global) { |
244 this.lastIndex = lastMatchInfo[CAPTURE1]; | 246 this.lastIndex = lastMatchInfo[CAPTURE1]; |
245 } else { | 247 } else { |
246 cache.regExp = this; | 248 cache.regExp = this; |
247 cache.subject = s; | 249 cache.subject = s; |
248 cache.lastIndex = lastIndex; | 250 cache.lastIndex = lastIndex; |
249 if (saveAnswer) cache.answer = CloneRegExpResult(result); | 251 if (saveAnswer) cache.answer = CloneRegExpResult(result); |
250 cache.answerSaved = saveAnswer; | 252 cache.answerSaved = saveAnswer; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 | 307 |
306 %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]); | 308 %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]); |
307 // matchIndices is either null or the lastMatchInfo array. | 309 // matchIndices is either null or the lastMatchInfo array. |
308 var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo); | 310 var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo); |
309 | 311 |
310 if (matchIndices == null) { | 312 if (matchIndices == null) { |
311 if (this.global) this.lastIndex = 0; | 313 if (this.global) this.lastIndex = 0; |
312 cache.answer = false; | 314 cache.answer = false; |
313 return false; | 315 return false; |
314 } | 316 } |
315 | 317 lastMatchInfoOverride = null; |
316 if (this.global) this.lastIndex = lastMatchInfo[CAPTURE1]; | 318 if (this.global) this.lastIndex = lastMatchInfo[CAPTURE1]; |
317 cache.answer = true; | 319 cache.answer = true; |
318 return true; | 320 return true; |
319 } | 321 } |
320 | 322 |
321 | 323 |
322 function RegExpToString() { | 324 function RegExpToString() { |
323 // If this.source is an empty string, output /(?:)/. | 325 // If this.source is an empty string, output /(?:)/. |
324 // http://bugzilla.mozilla.org/show_bug.cgi?id=225550 | 326 // http://bugzilla.mozilla.org/show_bug.cgi?id=225550 |
325 // ecma_2/RegExp/properties-001.js. | 327 // ecma_2/RegExp/properties-001.js. |
326 var src = this.source ? this.source : '(?:)'; | 328 var src = this.source ? this.source : '(?:)'; |
327 var result = '/' + src + '/'; | 329 var result = '/' + src + '/'; |
328 if (this.global) | 330 if (this.global) |
329 result += 'g'; | 331 result += 'g'; |
330 if (this.ignoreCase) | 332 if (this.ignoreCase) |
331 result += 'i'; | 333 result += 'i'; |
332 if (this.multiline) | 334 if (this.multiline) |
333 result += 'm'; | 335 result += 'm'; |
334 return result; | 336 return result; |
335 } | 337 } |
336 | 338 |
337 | 339 |
338 // Getters for the static properties lastMatch, lastParen, leftContext, and | 340 // Getters for the static properties lastMatch, lastParen, leftContext, and |
339 // rightContext of the RegExp constructor. The properties are computed based | 341 // rightContext of the RegExp constructor. The properties are computed based |
340 // on the captures array of the last successful match and the subject string | 342 // on the captures array of the last successful match and the subject string |
341 // of the last successful match. | 343 // of the last successful match. |
342 function RegExpGetLastMatch() { | 344 function RegExpGetLastMatch() { |
343 if (lastMatchInfoOverride) { return lastMatchInfoOverride[0]; } | 345 if (lastMatchInfoOverride !== null) { |
| 346 return lastMatchInfoOverride[0]; |
| 347 } |
344 var regExpSubject = LAST_SUBJECT(lastMatchInfo); | 348 var regExpSubject = LAST_SUBJECT(lastMatchInfo); |
345 return SubString(regExpSubject, | 349 return SubString(regExpSubject, |
346 lastMatchInfo[CAPTURE0], | 350 lastMatchInfo[CAPTURE0], |
347 lastMatchInfo[CAPTURE1]); | 351 lastMatchInfo[CAPTURE1]); |
348 } | 352 } |
349 | 353 |
350 | 354 |
351 function RegExpGetLastParen() { | 355 function RegExpGetLastParen() { |
352 if (lastMatchInfoOverride) { | 356 if (lastMatchInfoOverride) { |
353 var override = lastMatchInfoOverride; | 357 var override = lastMatchInfoOverride; |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 %DefineAccessor($RegExp, "$'", SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE); | 519 %DefineAccessor($RegExp, "$'", SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE); |
516 | 520 |
517 for (var i = 1; i < 10; ++i) { | 521 for (var i = 1; i < 10; ++i) { |
518 %DefineAccessor($RegExp, '$' + i, GETTER, RegExpMakeCaptureGetter(i), DONT_D
ELETE); | 522 %DefineAccessor($RegExp, '$' + i, GETTER, RegExpMakeCaptureGetter(i), DONT_D
ELETE); |
519 %DefineAccessor($RegExp, '$' + i, SETTER, NoOpSetter, DONT_DELETE); | 523 %DefineAccessor($RegExp, '$' + i, SETTER, NoOpSetter, DONT_DELETE); |
520 } | 524 } |
521 } | 525 } |
522 | 526 |
523 | 527 |
524 SetupRegExp(); | 528 SetupRegExp(); |
OLD | NEW |