Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/regexp.js

Issue 1148007: Merge bleeding_edge from version 2.1.3 up to revision 4205... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/partial_snapshots/
Patch Set: Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 DONT_DELETE | READ_ONLY | DONT_ENUM); 88 DONT_DELETE | READ_ONLY | DONT_ENUM);
89 89
90 // ECMA-262, section 15.10.7.5. 90 // ECMA-262, section 15.10.7.5.
91 %SetProperty(object, 'lastIndex', 0, DONT_DELETE | DONT_ENUM); 91 %SetProperty(object, 'lastIndex', 0, DONT_DELETE | DONT_ENUM);
92 } else { // RegExp is being recompiled via RegExp.prototype.compile. 92 } else { // RegExp is being recompiled via RegExp.prototype.compile.
93 %IgnoreAttributesAndSetProperty(object, 'source', pattern); 93 %IgnoreAttributesAndSetProperty(object, 'source', pattern);
94 %IgnoreAttributesAndSetProperty(object, 'global', global); 94 %IgnoreAttributesAndSetProperty(object, 'global', global);
95 %IgnoreAttributesAndSetProperty(object, 'ignoreCase', ignoreCase); 95 %IgnoreAttributesAndSetProperty(object, 'ignoreCase', ignoreCase);
96 %IgnoreAttributesAndSetProperty(object, 'multiline', multiline); 96 %IgnoreAttributesAndSetProperty(object, 'multiline', multiline);
97 %IgnoreAttributesAndSetProperty(object, 'lastIndex', 0); 97 %IgnoreAttributesAndSetProperty(object, 'lastIndex', 0);
98 regExpCache.type = 'none';
98 } 99 }
99 100
100 // Call internal function to compile the pattern. 101 // Call internal function to compile the pattern.
101 %RegExpCompile(object, pattern, flags); 102 %RegExpCompile(object, pattern, flags);
102 } 103 }
103 104
104 105
105 function RegExpConstructor(pattern, flags) { 106 function RegExpConstructor(pattern, flags) {
106 if (%_IsConstructCall()) { 107 if (%_IsConstructCall()) {
107 DoConstructRegExp(this, pattern, flags, true); 108 DoConstructRegExp(this, pattern, flags, true);
(...skipping 25 matching lines...) Expand all
133 DoConstructRegExp(this, pattern, flags, false); 134 DoConstructRegExp(this, pattern, flags, false);
134 } 135 }
135 } 136 }
136 137
137 138
138 function DoRegExpExec(regexp, string, index) { 139 function DoRegExpExec(regexp, string, index) {
139 return %_RegExpExec(regexp, string, index, lastMatchInfo); 140 return %_RegExpExec(regexp, string, index, lastMatchInfo);
140 } 141 }
141 142
142 143
144 function RegExpCache() {
145 this.type = 'none';
146 this.regExp = 0;
147 this.subject = 0;
148 this.replaceString = 0;
149 this.lastIndex = 0;
150 this.answer = 0;
151 }
152
153
154 var regExpCache = new RegExpCache();
155
156
157 function CloneRegexpAnswer(array) {
158 var len = array.length;
159 var answer = new $Array(len);
160 for (var i = 0; i < len; i++) {
161 answer[i] = array[i];
162 }
163 answer.index = array.index;
164 answer.input = array.input;
165 return answer;
166 }
167
168
143 function RegExpExec(string) { 169 function RegExpExec(string) {
144 if (!IS_REGEXP(this)) { 170 if (!IS_REGEXP(this)) {
145 throw MakeTypeError('incompatible_method_receiver', 171 throw MakeTypeError('incompatible_method_receiver',
146 ['RegExp.prototype.exec', this]); 172 ['RegExp.prototype.exec', this]);
147 } 173 }
174
175 var cache = regExpCache;
176
177 if (%_ObjectEquals(cache.type, 'exec') &&
178 %_ObjectEquals(cache.lastIndex, this.lastIndex) &&
179 %_ObjectEquals(cache.regExp, this) &&
180 %_ObjectEquals(cache.subject, string)) {
181 var last = cache.answer;
182 if (last == null) {
183 return last;
184 } else {
185 return CloneRegexpAnswer(last);
186 }
187 }
188
148 if (%_ArgumentsLength() == 0) { 189 if (%_ArgumentsLength() == 0) {
149 var regExpInput = LAST_INPUT(lastMatchInfo); 190 var regExpInput = LAST_INPUT(lastMatchInfo);
150 if (IS_UNDEFINED(regExpInput)) { 191 if (IS_UNDEFINED(regExpInput)) {
151 throw MakeError('no_input_to_regexp', [this]); 192 throw MakeError('no_input_to_regexp', [this]);
152 } 193 }
153 string = regExpInput; 194 string = regExpInput;
154 } 195 }
155 var s; 196 var s;
156 if (IS_STRING(string)) { 197 if (IS_STRING(string)) {
157 s = string; 198 s = string;
158 } else { 199 } else {
159 s = ToString(string); 200 s = ToString(string);
160 } 201 }
161 var lastIndex = this.lastIndex; 202 var lastIndex = this.lastIndex;
203
162 var i = this.global ? TO_INTEGER(lastIndex) : 0; 204 var i = this.global ? TO_INTEGER(lastIndex) : 0;
163 205
164 if (i < 0 || i > s.length) { 206 if (i < 0 || i > s.length) {
165 this.lastIndex = 0; 207 this.lastIndex = 0;
166 return null; 208 return null;
167 } 209 }
168 210
169 %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]); 211 %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]);
170 // matchIndices is either null or the lastMatchInfo array. 212 // matchIndices is either null or the lastMatchInfo array.
171 var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo); 213 var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo);
172 214
173 if (matchIndices == null) { 215 if (matchIndices == null) {
174 if (this.global) this.lastIndex = 0; 216 if (this.global) this.lastIndex = 0;
175 return matchIndices; // no match 217 cache.lastIndex = lastIndex;
218 cache.regExp = this;
219 cache.subject = s;
220 cache.answer = matchIndices; // Null.
221 cache.type = 'exec';
222 return matchIndices; // No match.
176 } 223 }
177 224
178 var numResults = NUMBER_OF_CAPTURES(lastMatchInfo) >> 1; 225 var numResults = NUMBER_OF_CAPTURES(lastMatchInfo) >> 1;
179 var result; 226 var result;
180 if (numResults === 1) { 227 if (numResults === 1) {
181 var matchStart = lastMatchInfo[CAPTURE(0)]; 228 var matchStart = lastMatchInfo[CAPTURE(0)];
182 var matchEnd = lastMatchInfo[CAPTURE(1)]; 229 var matchEnd = lastMatchInfo[CAPTURE(1)];
183 result = [SubString(s, matchStart, matchEnd)]; 230 result = [SubString(s, matchStart, matchEnd)];
184 } else { 231 } else {
185 result = new $Array(numResults); 232 result = new $Array(numResults);
186 for (var i = 0; i < numResults; i++) { 233 for (var i = 0; i < numResults; i++) {
187 var matchStart = lastMatchInfo[CAPTURE(i << 1)]; 234 var matchStart = lastMatchInfo[CAPTURE(i << 1)];
188 var matchEnd = lastMatchInfo[CAPTURE((i << 1) + 1)]; 235 var matchEnd = lastMatchInfo[CAPTURE((i << 1) + 1)];
189 if (matchStart != -1 && matchEnd != -1) { 236 if (matchStart != -1 && matchEnd != -1) {
190 result[i] = SubString(s, matchStart, matchEnd); 237 result[i] = SubString(s, matchStart, matchEnd);
191 } else { 238 } else {
192 // Make sure the element is present. Avoid reading the undefined 239 // Make sure the element is present. Avoid reading the undefined
193 // property from the global object since this may change. 240 // property from the global object since this may change.
194 result[i] = void 0; 241 result[i] = void 0;
195 } 242 }
196 } 243 }
197 } 244 }
198 245
199 if (this.global)
200 this.lastIndex = lastMatchInfo[CAPTURE1];
201 result.index = lastMatchInfo[CAPTURE0]; 246 result.index = lastMatchInfo[CAPTURE0];
202 result.input = s; 247 result.input = s;
203 return result; 248 if (this.global) {
249 this.lastIndex = lastMatchInfo[CAPTURE1];
250 return result;
251 } else {
252 cache.regExp = this;
253 cache.subject = s;
254 cache.lastIndex = lastIndex;
255 cache.answer = result;
256 cache.type = 'exec';
257 return CloneRegexpAnswer(result);
258 }
204 } 259 }
205 260
206 261
207 // Section 15.10.6.3 doesn't actually make sense, but the intention seems to be 262 // Section 15.10.6.3 doesn't actually make sense, but the intention seems to be
208 // that test is defined in terms of String.prototype.exec. However, it probably 263 // that test is defined in terms of String.prototype.exec. However, it probably
209 // means the original value of String.prototype.exec, which is what everybody 264 // means the original value of String.prototype.exec, which is what everybody
210 // else implements. 265 // else implements.
211 function RegExpTest(string) { 266 function RegExpTest(string) {
212 if (!IS_REGEXP(this)) { 267 if (!IS_REGEXP(this)) {
213 throw MakeTypeError('incompatible_method_receiver', 268 throw MakeTypeError('incompatible_method_receiver',
214 ['RegExp.prototype.test', this]); 269 ['RegExp.prototype.test', this]);
215 } 270 }
216 if (%_ArgumentsLength() == 0) { 271 if (%_ArgumentsLength() == 0) {
217 var regExpInput = LAST_INPUT(lastMatchInfo); 272 var regExpInput = LAST_INPUT(lastMatchInfo);
218 if (IS_UNDEFINED(regExpInput)) { 273 if (IS_UNDEFINED(regExpInput)) {
219 throw MakeError('no_input_to_regexp', [this]); 274 throw MakeError('no_input_to_regexp', [this]);
220 } 275 }
221 string = regExpInput; 276 string = regExpInput;
222 } 277 }
223 var s = ToString(string); 278 var s;
279 if (IS_STRING(string)) {
280 s = string;
281 } else {
282 s = ToString(string);
283 }
284
285 var lastIndex = this.lastIndex;
286
287 var cache = regExpCache;
288
289 if (%_ObjectEquals(cache.type, 'test') &&
290 %_ObjectEquals(cache.regExp, this) &&
291 %_ObjectEquals(cache.subject, string) &&
292 %_ObjectEquals(cache.lastIndex, lastIndex)) {
293 return cache.answer;
294 }
295
224 var length = s.length; 296 var length = s.length;
225 var lastIndex = this.lastIndex;
226 var i = this.global ? TO_INTEGER(lastIndex) : 0; 297 var i = this.global ? TO_INTEGER(lastIndex) : 0;
227 298
299 cache.type = 'test';
300 cache.regExp = this;
301 cache.subject = s;
302 cache.lastIndex = i;
303
228 if (i < 0 || i > s.length) { 304 if (i < 0 || i > s.length) {
229 this.lastIndex = 0; 305 this.lastIndex = 0;
306 cache.answer = false;
230 return false; 307 return false;
231 } 308 }
232 309
233 %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]); 310 %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]);
234 // matchIndices is either null or the lastMatchInfo array. 311 // matchIndices is either null or the lastMatchInfo array.
235 var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo); 312 var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo);
236 313
237 if (matchIndices == null) { 314 if (matchIndices == null) {
238 if (this.global) this.lastIndex = 0; 315 if (this.global) this.lastIndex = 0;
316 cache.answer = false;
239 return false; 317 return false;
240 } 318 }
241 319
242 if (this.global) this.lastIndex = lastMatchInfo[CAPTURE1]; 320 if (this.global) this.lastIndex = lastMatchInfo[CAPTURE1];
321 cache.answer = true;
243 return true; 322 return true;
244 } 323 }
245 324
246 325
247 function RegExpToString() { 326 function RegExpToString() {
248 // If this.source is an empty string, output /(?:)/. 327 // If this.source is an empty string, output /(?:)/.
249 // http://bugzilla.mozilla.org/show_bug.cgi?id=225550 328 // http://bugzilla.mozilla.org/show_bug.cgi?id=225550
250 // ecma_2/RegExp/properties-001.js. 329 // ecma_2/RegExp/properties-001.js.
251 var src = this.source ? this.source : '(?:)'; 330 var src = this.source ? this.source : '(?:)';
252 var result = '/' + src + '/'; 331 var result = '/' + src + '/';
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 %FunctionSetLength($RegExp.prototype.compile, 1); 430 %FunctionSetLength($RegExp.prototype.compile, 1);
352 431
353 // The properties input, $input, and $_ are aliases for each other. When this 432 // The properties input, $input, and $_ are aliases for each other. When this
354 // value is set the value it is set to is coerced to a string. 433 // value is set the value it is set to is coerced to a string.
355 // Getter and setter for the input. 434 // Getter and setter for the input.
356 function RegExpGetInput() { 435 function RegExpGetInput() {
357 var regExpInput = LAST_INPUT(lastMatchInfo); 436 var regExpInput = LAST_INPUT(lastMatchInfo);
358 return IS_UNDEFINED(regExpInput) ? "" : regExpInput; 437 return IS_UNDEFINED(regExpInput) ? "" : regExpInput;
359 } 438 }
360 function RegExpSetInput(string) { 439 function RegExpSetInput(string) {
440 regExpCache.type = 'none';
361 LAST_INPUT(lastMatchInfo) = ToString(string); 441 LAST_INPUT(lastMatchInfo) = ToString(string);
362 }; 442 };
363 443
364 %DefineAccessor($RegExp, 'input', GETTER, RegExpGetInput, DONT_DELETE); 444 %DefineAccessor($RegExp, 'input', GETTER, RegExpGetInput, DONT_DELETE);
365 %DefineAccessor($RegExp, 'input', SETTER, RegExpSetInput, DONT_DELETE); 445 %DefineAccessor($RegExp, 'input', SETTER, RegExpSetInput, DONT_DELETE);
366 %DefineAccessor($RegExp, '$_', GETTER, RegExpGetInput, DONT_ENUM | DONT_DELETE ); 446 %DefineAccessor($RegExp, '$_', GETTER, RegExpGetInput, DONT_ENUM | DONT_DELETE );
367 %DefineAccessor($RegExp, '$_', SETTER, RegExpSetInput, DONT_ENUM | DONT_DELETE ); 447 %DefineAccessor($RegExp, '$_', SETTER, RegExpSetInput, DONT_ENUM | DONT_DELETE );
368 %DefineAccessor($RegExp, '$input', GETTER, RegExpGetInput, DONT_ENUM | DONT_DE LETE); 448 %DefineAccessor($RegExp, '$input', GETTER, RegExpGetInput, DONT_ENUM | DONT_DE LETE);
369 %DefineAccessor($RegExp, '$input', SETTER, RegExpSetInput, DONT_ENUM | DONT_DE LETE); 449 %DefineAccessor($RegExp, '$input', SETTER, RegExpSetInput, DONT_ENUM | DONT_DE LETE);
370 450
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 %DefineAccessor($RegExp, "$'", SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE); 488 %DefineAccessor($RegExp, "$'", SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE);
409 489
410 for (var i = 1; i < 10; ++i) { 490 for (var i = 1; i < 10; ++i) {
411 %DefineAccessor($RegExp, '$' + i, GETTER, RegExpMakeCaptureGetter(i), DONT_D ELETE); 491 %DefineAccessor($RegExp, '$' + i, GETTER, RegExpMakeCaptureGetter(i), DONT_D ELETE);
412 %DefineAccessor($RegExp, '$' + i, SETTER, NoOpSetter, DONT_DELETE); 492 %DefineAccessor($RegExp, '$' + i, SETTER, NoOpSetter, DONT_DELETE);
413 } 493 }
414 } 494 }
415 495
416 496
417 SetupRegExp(); 497 SetupRegExp();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698