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

Side by Side Diff: src/string.js

Issue 39186: Revert revisions 1383, 1384, 1391, 1398, 1401, 1402,... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 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
« no previous file with comments | « src/runtime.cc ('k') | test/mjsunit/regexp-static.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 if (!regexp.global) return regexp.exec(subject); 158 if (!regexp.global) return regexp.exec(subject);
159 %_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]); 159 %_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]);
160 var matches = DoRegExpExecGlobal(regexp, subject); 160 var matches = DoRegExpExecGlobal(regexp, subject);
161 161
162 // If the regexp did not match, return null. 162 // If the regexp did not match, return null.
163 if (matches.length == 0) return null; 163 if (matches.length == 0) return null;
164 164
165 // Build the result array. 165 // Build the result array.
166 var result = new $Array(match_string); 166 var result = new $Array(match_string);
167 for (var i = 0; i < matches.length; ++i) { 167 for (var i = 0; i < matches.length; ++i) {
168 var matchInfo = matches[i]; 168 var match = matches[i];
169 var match_string = subject.slice(matchInfo[CAPTURE0], 169 var match_string = subject.slice(match[0], match[1]);
170 matchInfo[CAPTURE1]);
171 result[i] = match_string; 170 result[i] = match_string;
172 } 171 }
173 172
174 return result; 173 return result;
175 } 174 }
176 175
177 176
178 // SubString is an internal function that returns the sub string of 'string'. 177 // SubString is an internal function that returns the sub string of 'string'.
179 // If resulting string is of length 1, we use the one character cache 178 // If resulting string is of length 1, we use the one character cache
180 // otherwise we call the runtime system. 179 // otherwise we call the runtime system.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 var end = start + search.length; 211 var end = start + search.length;
213 212
214 var builder = new ReplaceResultBuilder(subject); 213 var builder = new ReplaceResultBuilder(subject);
215 // prefix 214 // prefix
216 builder.addSpecialSlice(0, start); 215 builder.addSpecialSlice(0, start);
217 216
218 // Compute the string to replace with. 217 // Compute the string to replace with.
219 if (IS_FUNCTION(replace)) { 218 if (IS_FUNCTION(replace)) {
220 builder.add(replace.call(null, search, start, subject)); 219 builder.add(replace.call(null, search, start, subject));
221 } else { 220 } else {
222 reusableMatchInfo[CAPTURE0] = start; 221 ExpandReplacement(ToString(replace), subject, [ start, end ], builder);
223 reusableMatchInfo[CAPTURE1] = end;
224 ExpandReplacement(ToString(replace), subject, reusableMatchInfo, builder);
225 } 222 }
226 223
227 // suffix 224 // suffix
228 builder.addSpecialSlice(end, subject.length); 225 builder.addSpecialSlice(end, subject.length);
229 226
230 return builder.generate(); 227 return builder.generate();
231 } 228 }
232 229
233 230
234 // This has the same size as the lastMatchInfo array, and can be used for
235 // functions that expect that structure to be returned. It is used when the
236 // needle is a string rather than a regexp. In this case we can't update
237 // lastMatchArray without erroneously affecting the properties on the global
238 // RegExp object.
239 var reusableMatchInfo = [2, -1, -1, "", ""];
240 var reusableMatchArray = [ void 0 ];
241
242
243 // Helper function for regular expressions in String.prototype.replace. 231 // Helper function for regular expressions in String.prototype.replace.
244 function StringReplaceRegExp(subject, regexp, replace) { 232 function StringReplaceRegExp(subject, regexp, replace) {
245 // Compute an array of matches; each match is really a list of 233 // Compute an array of matches; each match is really a list of
246 // captures - pairs of (start, end) indexes into the subject string. 234 // captures - pairs of (start, end) indexes into the subject string.
247 var matches; 235 var matches;
248 if (regexp.global) { 236 if (regexp.global) {
249 matches = DoRegExpExecGlobal(regexp, subject); 237 matches = DoRegExpExecGlobal(regexp, subject);
250 if (matches.length == 0) return subject; 238 if (matches.length == 0) return subject;
251 } else { 239 } else {
252 var lastMatchInfo = DoRegExpExec(regexp, subject, 0); 240 var captures = DoRegExpExec(regexp, subject, 0);
253 if (IS_NULL(lastMatchInfo)) return subject; 241 if (IS_NULL(captures)) return subject;
254 reusableMatchArray[0] = lastMatchInfo; 242 matches = [ captures ];
255 matches = reusableMatchArray;
256 } 243 }
257 244
258 // Determine the number of matches. 245 // Determine the number of matches.
259 var length = matches.length; 246 var length = matches.length;
260 247
261 // Build the resulting string of subject slices and replacements. 248 // Build the resulting string of subject slices and replacements.
262 var result = new ReplaceResultBuilder(subject); 249 var result = new ReplaceResultBuilder(subject);
263 var previous = 0; 250 var previous = 0;
264 // The caller of StringReplaceRegExp must ensure that replace is not a 251 // The caller of StringReplaceRegExp must ensure that replace is not a
265 // function. 252 // function.
266 replace = ToString(replace); 253 replace = ToString(replace);
267 if (%StringIndexOf(replace, "$", 0) < 0) { 254 if (%StringIndexOf(replace, "$", 0) < 0) {
268 for (var i = 0; i < length; i++) { 255 for (var i = 0; i < length; i++) {
269 var matchInfo = matches[i]; 256 var captures = matches[i];
270 result.addSpecialSlice(previous, matchInfo[CAPTURE0]); 257 result.addSpecialSlice(previous, captures[0]);
271 result.add(replace); 258 result.add(replace);
272 previous = matchInfo[CAPTURE1]; // continue after match 259 previous = captures[1]; // continue after match
273 } 260 }
274 } else { 261 } else {
275 for (var i = 0; i < length; i++) { 262 for (var i = 0; i < length; i++) {
276 var matchInfo = matches[i]; 263 var captures = matches[i];
277 result.addSpecialSlice(previous, matchInfo[CAPTURE0]); 264 result.addSpecialSlice(previous, captures[0]);
278 ExpandReplacement(replace, subject, matchInfo, result); 265 ExpandReplacement(replace, subject, captures, result);
279 previous = matchInfo[CAPTURE1]; // continue after match 266 previous = captures[1]; // continue after match
280 } 267 }
281 } 268 }
282 result.addSpecialSlice(previous, subject.length); 269 result.addSpecialSlice(previous, subject.length);
283 return result.generate(); 270 return result.generate();
284 }; 271 };
285 272
286 273
287 // Expand the $-expressions in the string and return a new string with 274 // Expand the $-expressions in the string and return a new string with
288 // the result. 275 // the result.
289 function ExpandReplacement(string, subject, matchInfo, builder) { 276 function ExpandReplacement(string, subject, captures, builder) {
290 var next = %StringIndexOf(string, '$', 0); 277 var next = %StringIndexOf(string, '$', 0);
291 if (next < 0) { 278 if (next < 0) {
292 builder.add(string); 279 builder.add(string);
293 return; 280 return;
294 } 281 }
295 282
296 // Compute the number of captures; see ECMA-262, 15.5.4.11, p. 102. 283 // Compute the number of captures; see ECMA-262, 15.5.4.11, p. 102.
297 var m = NUMBER_OF_CAPTURES(matchInfo) >> 1; // Includes the match. 284 var m = captures.length >> 1; // includes the match
298 285
299 if (next > 0) builder.add(SubString(string, 0, next)); 286 if (next > 0) builder.add(SubString(string, 0, next));
300 var length = string.length; 287 var length = string.length;
301 288
302
303 while (true) { 289 while (true) {
304 var expansion = '$'; 290 var expansion = '$';
305 var position = next + 1; 291 var position = next + 1;
306 if (position < length) { 292 if (position < length) {
307 var peek = %_FastCharCodeAt(string, position); 293 var peek = %_FastCharCodeAt(string, position);
308 if (!%_IsSmi(peek)) { 294 if (!%_IsSmi(peek)) {
309 peek = %StringCharCodeAt(string, position); 295 peek = %StringCharCodeAt(string, position);
310 } 296 }
311 if (peek == 36) { // $$ 297 if (peek == 36) { // $$
312 ++position; 298 ++position;
313 builder.add('$'); 299 builder.add('$');
314 } else if (peek == 38) { // $& - match 300 } else if (peek == 38) { // $& - match
315 ++position; 301 ++position;
316 builder.addSpecialSlice(matchInfo[CAPTURE0], 302 builder.addSpecialSlice(captures[0], captures[1]);
317 matchInfo[CAPTURE1]);
318 } else if (peek == 96) { // $` - prefix 303 } else if (peek == 96) { // $` - prefix
319 ++position; 304 ++position;
320 builder.addSpecialSlice(0, matchInfo[CAPTURE0]); 305 builder.addSpecialSlice(0, captures[0]);
321 } else if (peek == 39) { // $' - suffix 306 } else if (peek == 39) { // $' - suffix
322 ++position; 307 ++position;
323 builder.addSpecialSlice(matchInfo[CAPTURE1], subject.length); 308 builder.addSpecialSlice(captures[1], subject.length);
324 } else if (peek >= 48 && peek <= 57) { // $n, 0 <= n <= 9 309 } else if (peek >= 48 && peek <= 57) { // $n, 0 <= n <= 9
325 ++position; 310 ++position;
326 var n = peek - 48; 311 var n = peek - 48;
327 if (position < length) { 312 if (position < length) {
328 peek = %_FastCharCodeAt(string, position); 313 peek = %_FastCharCodeAt(string, position);
329 if (!%_IsSmi(peek)) { 314 if (!%_IsSmi(peek)) {
330 peek = %StringCharCodeAt(string, position); 315 peek = %StringCharCodeAt(string, position);
331 } 316 }
332 // $nn, 01 <= nn <= 99 317 // $nn, 01 <= nn <= 99
333 if (n != 0 && peek == 48 || peek >= 49 && peek <= 57) { 318 if (n != 0 && peek == 48 || peek >= 49 && peek <= 57) {
334 var nn = n * 10 + (peek - 48); 319 var nn = n * 10 + (peek - 48);
335 if (nn < m) { 320 if (nn < m) {
336 // If the two digit capture reference is within range of 321 // If the two digit capture reference is within range of
337 // the captures, we use it instead of the single digit 322 // the captures, we use it instead of the single digit
338 // one. Otherwise, we fall back to using the single 323 // one. Otherwise, we fall back to using the single
339 // digit reference. This matches the behavior of 324 // digit reference. This matches the behavior of
340 // SpiderMonkey. 325 // SpiderMonkey.
341 ++position; 326 ++position;
342 n = nn; 327 n = nn;
343 } 328 }
344 } 329 }
345 } 330 }
346 if (0 < n && n < m) { 331 if (0 < n && n < m) {
347 addCaptureString(builder, matchInfo, n); 332 addCaptureString(builder, captures, n);
348 } else { 333 } else {
349 // Because of the captures range check in the parsing of two 334 // Because of the captures range check in the parsing of two
350 // digit capture references, we can only enter here when a 335 // digit capture references, we can only enter here when a
351 // single digit capture reference is outside the range of 336 // single digit capture reference is outside the range of
352 // captures. 337 // captures.
353 builder.add('$'); 338 builder.add('$');
354 --position; 339 --position;
355 } 340 }
356 } 341 }
357 } else { 342 } else {
(...skipping 11 matching lines...) Expand all
369 } 354 }
370 return; 355 return;
371 } 356 }
372 357
373 // Append substring between the previous and the next $ character. 358 // Append substring between the previous and the next $ character.
374 builder.add(SubString(string, position, next)); 359 builder.add(SubString(string, position, next));
375 } 360 }
376 }; 361 };
377 362
378 363
379 // Compute the string of a given regular expression capture. 364 // Compute the string of a given PCRE capture.
380 function CaptureString(string, lastCaptureInfo, index) { 365 function CaptureString(string, captures, index) {
381 // Scale the index. 366 // Scale the index.
382 var scaled = index << 1; 367 var scaled = index << 1;
383 // Compute start and end. 368 // Compute start and end.
384 var start = lastCaptureInfo[CAPTURE(scaled)]; 369 var start = captures[scaled];
385 var end = lastCaptureInfo[CAPTURE(scaled + 1)]; 370 var end = captures[scaled + 1];
386 // If either start or end is missing return undefined. 371 // If either start or end is missing return undefined.
387 if (start < 0 || end < 0) return; 372 if (start < 0 || end < 0) return;
388 return SubString(string, start, end); 373 return SubString(string, start, end);
389 }; 374 };
390 375
391 376
392 // Add the string of a given regular expression capture to the 377 // Add the string of a given PCRE capture to the ReplaceResultBuilder
393 // ReplaceResultBuilder 378 function addCaptureString(builder, captures, index) {
394 function addCaptureString(builder, matchInfo, index) {
395 // Scale the index. 379 // Scale the index.
396 var scaled = index << 1; 380 var scaled = index << 1;
397 // Compute start and end. 381 // Compute start and end.
398 var start = matchInfo[CAPTURE(scaled)]; 382 var start = captures[scaled];
399 var end = matchInfo[CAPTURE(scaled + 1)]; 383 var end = captures[scaled + 1];
400 // If either start or end is missing return. 384 // If either start or end is missing return.
401 if (start < 0 || end <= start) return; 385 if (start < 0 || end <= start) return;
402 builder.addSpecialSlice(start, end); 386 builder.addSpecialSlice(start, end);
403 }; 387 };
404 388
405 389
406 // Helper function for replacing regular expressions with the result of a 390 // Helper function for replacing regular expressions with the result of a
407 // function application in String.prototype.replace. The function application 391 // function application in String.prototype.replace. The function application
408 // must be interleaved with the regexp matching (contrary to ECMA-262 392 // must be interleaved with the regexp matching (contrary to ECMA-262
409 // 15.5.4.11) to mimic SpiderMonkey and KJS behavior when the function uses 393 // 15.5.4.11) to mimic SpiderMonkey and KJS behavior when the function uses
410 // the static properties of the RegExp constructor. Example: 394 // the static properties of the RegExp constructor. Example:
411 // 'abcd'.replace(/(.)/g, function() { return RegExp.$1; } 395 // 'abcd'.replace(/(.)/g, function() { return RegExp.$1; }
412 // should be 'abcd' and not 'dddd' (or anything else). 396 // should be 'abcd' and not 'dddd' (or anything else).
413 function StringReplaceRegExpWithFunction(subject, regexp, replace) { 397 function StringReplaceRegExpWithFunction(subject, regexp, replace) {
414 var result = new ReplaceResultBuilder(subject); 398 var result = new ReplaceResultBuilder(subject);
415 var lastMatchInfo = DoRegExpExec(regexp, subject, 0); 399 // Captures is an array of pairs of (start, end) indices for the match and
416 if (IS_NULL(lastMatchInfo)) return subject; 400 // any captured substrings.
401 var captures = DoRegExpExec(regexp, subject, 0);
402 if (IS_NULL(captures)) return subject;
417 403
418 // There's at least one match. If the regexp is global, we have to loop 404 // There's at least one match. If the regexp is global, we have to loop
419 // over all matches. The loop is not in C++ code here like the one in 405 // over all matches. The loop is not in C++ code here like the one in
420 // RegExp.prototype.exec, because of the interleaved function application. 406 // RegExp.prototype.exec, because of the interleaved function application.
421 // Unfortunately, that means this code is nearly duplicated, here and in 407 // Unfortunately, that means this code is nearly duplicated, here and in
422 // jsregexp.cc. 408 // jsregexp.cc.
423 if (regexp.global) { 409 if (regexp.global) {
424 var previous = 0; 410 var previous = 0;
425 do { 411 do {
426 result.addSpecialSlice(previous, lastMatchInfo[CAPTURE0]); 412 result.addSpecialSlice(previous, captures[0]);
427 var startOfMatch = lastMatchInfo[CAPTURE0]; 413 result.add(ApplyReplacementFunction(replace, captures, subject));
428 previous = lastMatchInfo[CAPTURE1];
429 result.add(ApplyReplacementFunction(replace, lastMatchInfo, subject));
430 // Can't use lastMatchInfo any more from here, since the function could
431 // overwrite it.
432 // Continue with the next match. 414 // Continue with the next match.
415 previous = captures[1];
433 // Increment previous if we matched an empty string, as per ECMA-262 416 // Increment previous if we matched an empty string, as per ECMA-262
434 // 15.5.4.10. 417 // 15.5.4.10.
435 if (previous == startOfMatch) { 418 if (previous == captures[0]) {
436 // Add the skipped character to the output, if any. 419 // Add the skipped character to the output, if any.
437 if (previous < subject.length) { 420 if (previous < subject.length) {
438 result.addSpecialSlice(previous, previous + 1); 421 result.addSpecialSlice(previous, previous + 1);
439 } 422 }
440 previous++; 423 previous++;
441 } 424 }
442 425
443 // Per ECMA-262 15.10.6.2, if the previous index is greater than the 426 // Per ECMA-262 15.10.6.2, if the previous index is greater than the
444 // string length, there is no match 427 // string length, there is no match
445 lastMatchInfo = (previous > subject.length) 428 captures = (previous > subject.length)
446 ? null 429 ? null
447 : DoRegExpExec(regexp, subject, previous); 430 : DoRegExpExec(regexp, subject, previous);
448 } while (!IS_NULL(lastMatchInfo)); 431 } while (!IS_NULL(captures));
449 432
450 // Tack on the final right substring after the last match, if necessary. 433 // Tack on the final right substring after the last match, if necessary.
451 if (previous < subject.length) { 434 if (previous < subject.length) {
452 result.addSpecialSlice(previous, subject.length); 435 result.addSpecialSlice(previous, subject.length);
453 } 436 }
454 } else { // Not a global regexp, no need to loop. 437 } else { // Not a global regexp, no need to loop.
455 result.addSpecialSlice(0, lastMatchInfo[CAPTURE0]); 438 result.addSpecialSlice(0, captures[0]);
456 var endOfMatch = lastMatchInfo[CAPTURE1]; 439 result.add(ApplyReplacementFunction(replace, captures, subject));
457 result.add(ApplyReplacementFunction(replace, lastMatchInfo, subject)); 440 result.addSpecialSlice(captures[1], subject.length);
458 // Can't use lastMatchInfo any more from here, since the function could
459 // overwrite it.
460 result.addSpecialSlice(endOfMatch, subject.length);
461 } 441 }
462 442
463 return result.generate(); 443 return result.generate();
464 } 444 }
465 445
466 446
467 // Helper function to apply a string replacement function once. 447 // Helper function to apply a string replacement function once.
468 function ApplyReplacementFunction(replace, lastMatchInfo, subject) { 448 function ApplyReplacementFunction(replace, captures, subject) {
469 // Compute the parameter list consisting of the match, captures, index, 449 // Compute the parameter list consisting of the match, captures, index,
470 // and subject for the replace function invocation. 450 // and subject for the replace function invocation.
471 var index = lastMatchInfo[CAPTURE0]; 451 var index = captures[0];
472 // The number of captures plus one for the match. 452 // The number of captures plus one for the match.
473 var m = NUMBER_OF_CAPTURES(lastMatchInfo) >> 1; 453 var m = captures.length >> 1;
474 if (m == 1) { 454 if (m == 1) {
475 var s = CaptureString(subject, lastMatchInfo, 0); 455 var s = CaptureString(subject, captures, 0);
476 // Don't call directly to avoid exposing the built-in global object. 456 // Don't call directly to avoid exposing the built-in global object.
477 return ToString(replace.call(null, s, index, subject)); 457 return ToString(replace.call(null, s, index, subject));
478 } 458 }
479 var parameters = $Array(m + 2); 459 var parameters = $Array(m + 2);
480 for (var j = 0; j < m; j++) { 460 for (var j = 0; j < m; j++) {
481 parameters[j] = CaptureString(subject, lastMatchInfo, j); 461 parameters[j] = CaptureString(subject, captures, j);
482 } 462 }
483 parameters[j] = index; 463 parameters[j] = index;
484 parameters[j + 1] = subject; 464 parameters[j + 1] = subject;
485 return ToString(replace.apply(null, parameters)); 465 return ToString(replace.apply(null, parameters));
486 } 466 }
487 467
488 468
489 // ECMA-262 section 15.5.4.12 469 // ECMA-262 section 15.5.4.12
490 function StringSearch(re) { 470 function StringSearch(re) {
491 var regexp = new ORIGINAL_REGEXP(re); 471 var regexp = new ORIGINAL_REGEXP(re);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
572 return result; 552 return result;
573 } 553 }
574 554
575 while (true) { 555 while (true) {
576 556
577 if (startIndex === length) { 557 if (startIndex === length) {
578 result[result.length] = subject.slice(currentIndex, length); 558 result[result.length] = subject.slice(currentIndex, length);
579 return result; 559 return result;
580 } 560 }
581 561
582 var lastMatchInfo = splitMatch(sep, subject, currentIndex, startIndex); 562 var match = splitMatch(sep, subject, currentIndex, startIndex);
583 563
584 if (IS_NULL(lastMatchInfo)) { 564 if (IS_NULL(match)) {
585 result[result.length] = subject.slice(currentIndex, length); 565 result[result.length] = subject.slice(currentIndex, length);
586 return result; 566 return result;
587 } 567 }
588 568
589 var endIndex = lastMatchInfo[CAPTURE1]; 569 var endIndex = match[0];
590 570
591 // We ignore a zero-length match at the currentIndex. 571 // We ignore a zero-length match at the currentIndex.
592 if (startIndex === endIndex && endIndex === currentIndex) { 572 if (startIndex === endIndex && endIndex === currentIndex) {
593 startIndex++; 573 startIndex++;
594 continue; 574 continue;
595 } 575 }
596 576
597 result[result.length] = 577 result[result.length] = match[1];
598 SubString(subject, currentIndex, lastMatchInfo[CAPTURE0]);
599 if (result.length === lim) return result; 578 if (result.length === lim) return result;
600 579
601 for (var i = 2; i < NUMBER_OF_CAPTURES(lastMatchInfo); i += 2) { 580 for (var i = 2; i < match.length; i++) {
602 var start = lastMatchInfo[CAPTURE(i)]; 581 result[result.length] = match[i];
603 var end = lastMatchInfo[CAPTURE(i + 1)];
604 if (start != -1 && end != -1) {
605 result[result.length] = SubString(subject,
606 lastMatchInfo[CAPTURE(i)],
607 lastMatchInfo[CAPTURE(i + 1)]);
608 } else {
609 result[result.length] = void 0;
610 }
611 if (result.length === lim) return result; 582 if (result.length === lim) return result;
612 } 583 }
613 584
614 startIndex = currentIndex = endIndex; 585 startIndex = currentIndex = endIndex;
615 } 586 }
616 } 587 }
617 588
618 589
619 // ECMA-262 section 15.5.4.14 590 // ECMA-262 section 15.5.4.14
620 // Helper function used by split. This version returns the lastMatchInfo 591 // Helper function used by split.
621 // instead of allocating a new array with basically the same information.
622 function splitMatch(separator, subject, current_index, start_index) { 592 function splitMatch(separator, subject, current_index, start_index) {
623 if (IS_REGEXP(separator)) { 593 if (IS_REGEXP(separator)) {
624 var lastMatchInfo = DoRegExpExec(separator, subject, start_index); 594 var ovector = DoRegExpExec(separator, subject, start_index);
625 if (lastMatchInfo == null) return null; 595 if (ovector == null) return null;
596 var nof_results = ovector.length >> 1;
597 var result = new $Array(nof_results + 1);
626 // Section 15.5.4.14 paragraph two says that we do not allow zero length 598 // Section 15.5.4.14 paragraph two says that we do not allow zero length
627 // matches at the end of the string. 599 // matches at the end of the string.
628 if (lastMatchInfo[CAPTURE0] === subject.length) return null; 600 if (ovector[0] === subject.length) return null;
629 return lastMatchInfo; 601 result[0] = ovector[1];
602 result[1] = subject.slice(current_index, ovector[0]);
603 for (var i = 1; i < nof_results; i++) {
604 var matching_start = ovector[2*i];
605 var matching_end = ovector[2*i + 1];
606 if (matching_start != -1 && matching_end != -1) {
607 result[i + 1] = subject.slice(matching_start, matching_end);
608 }
609 }
610 return result;
630 } 611 }
631 612
632 var separatorIndex = subject.indexOf(separator, start_index); 613 var separatorIndex = subject.indexOf(separator, start_index);
633 if (separatorIndex === -1) return null; 614 if (separatorIndex === -1) return null;
634 615
635 reusableMatchInfo[CAPTURE0] = separatorIndex; 616 return [ separatorIndex + separator.length, subject.slice(current_index, separ atorIndex) ];
636 reusableMatchInfo[CAPTURE1] = separatorIndex + separator.length;
637 return reusableMatchInfo;
638 }; 617 };
639 618
640 619
641 // ECMA-262 section 15.5.4.15 620 // ECMA-262 section 15.5.4.15
642 function StringSubstring(start, end) { 621 function StringSubstring(start, end) {
643 var s = ToString(this); 622 var s = ToString(this);
644 var s_len = s.length; 623 var s_len = s.length;
645 var start_i = TO_INTEGER(start); 624 var start_i = TO_INTEGER(start);
646 var end_i = s_len; 625 var end_i = s_len;
647 if (!IS_UNDEFINED(end)) 626 if (!IS_UNDEFINED(end))
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
904 "italics", StringItalics, 883 "italics", StringItalics,
905 "small", StringSmall, 884 "small", StringSmall,
906 "strike", StringStrike, 885 "strike", StringStrike,
907 "sub", StringSub, 886 "sub", StringSub,
908 "sup", StringSup 887 "sup", StringSup
909 )); 888 ));
910 } 889 }
911 890
912 891
913 SetupString(); 892 SetupString();
OLDNEW
« no previous file with comments | « src/runtime.cc ('k') | test/mjsunit/regexp-static.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698