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

Side by Side Diff: src/string.js

Issue 1695002: Fix incorrect handling of global RegExp properties for nested replace-regexp-with-function. (Closed)
Patch Set: Created 10 years, 8 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
« no previous file with comments | « src/regexp.js ('k') | test/mjsunit/string-replace.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-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 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 168
169 var this_str = TO_STRING_INLINE(this); 169 var this_str = TO_STRING_INLINE(this);
170 var other_str = TO_STRING_INLINE(other); 170 var other_str = TO_STRING_INLINE(other);
171 return %StringLocaleCompare(this_str, other_str); 171 return %StringLocaleCompare(this_str, other_str);
172 } 172 }
173 173
174 174
175 // ECMA-262 section 15.5.4.10 175 // ECMA-262 section 15.5.4.10
176 function StringMatch(regexp) { 176 function StringMatch(regexp) {
177 var subject = TO_STRING_INLINE(this); 177 var subject = TO_STRING_INLINE(this);
178 if (IS_REGEXP(regexp)) { 178 if (IS_REGEXP(regexp)) {
179 if (!regexp.global) return regexp.exec(subject); 179 if (!regexp.global) return regexp.exec(subject);
180 180
181 var cache = regExpCache; 181 var cache = regExpCache;
182 var saveAnswer = false; 182 var saveAnswer = false;
183 183
184 if (%_ObjectEquals(cache.type, 'match') && 184 if (%_ObjectEquals(cache.type, 'match') &&
185 %_ObjectEquals(cache.regExp, regexp) && 185 %_ObjectEquals(cache.regExp, regexp) &&
186 %_ObjectEquals(cache.subject, subject)) { 186 %_ObjectEquals(cache.subject, subject)) {
187 if (cache.answerSaved) { 187 if (cache.answerSaved) {
188 return CloneDenseArray(cache.answer); 188 return CloneDenseArray(cache.answer);
189 } else { 189 } else {
190 saveAnswer = true; 190 saveAnswer = true;
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 var resultArray = reusableReplaceArray; 428 var resultArray = reusableReplaceArray;
429 if (resultArray) { 429 if (resultArray) {
430 reusableReplaceArray = null; 430 reusableReplaceArray = null;
431 } else { 431 } else {
432 // Inside a nested replace (replace called from the replacement function 432 // Inside a nested replace (replace called from the replacement function
433 // of another replace) or we have failed to set the reusable array 433 // of another replace) or we have failed to set the reusable array
434 // back due to an exception in a replacement function. Create a new 434 // back due to an exception in a replacement function. Create a new
435 // array to use in the future, or until the original is written back. 435 // array to use in the future, or until the original is written back.
436 resultArray = $Array(16); 436 resultArray = $Array(16);
437 } 437 }
438 try { 438
439 // Must handle exceptions thrown by the replace functions correctly, 439 var res = %RegExpExecMultiple(regexp,
440 // including unregistering global regexps. 440 subject,
441 var res = %RegExpExecMultiple(regexp, 441 lastMatchInfo,
442 subject, 442 resultArray);
443 lastMatchInfo, 443 regexp.lastIndex = 0;
444 resultArray); 444 if (IS_NULL(res)) {
445 regexp.lastIndex = 0; 445 // No matches at all.
446 if (IS_NULL(res)) { 446 return subject;
447 // No matches at all. 447 }
448 return subject; 448 var len = res.length;
449 var i = 0;
450 if (NUMBER_OF_CAPTURES(lastMatchInfo) == 2) {
451 var match_start = 0;
452 var override = [null, 0, subject];
453 while (i < len) {
454 var elem = res[i];
455 if (%_IsSmi(elem)) {
456 if (elem > 0) {
457 match_start = (elem >> 11) + (elem & 0x7ff);
458 } else {
459 match_start = res[++i] - elem;
460 }
461 } else {
462 override[0] = elem;
463 override[1] = match_start;
464 lastMatchInfoOverride = override;
465 var func_result = replace.call(null, elem, match_start, subject);
466 if (!IS_STRING(func_result)) {
467 func_result = NonStringToString(func_result);
468 }
469 res[i] = func_result;
470 match_start += elem.length;
471 }
472 i++;
449 } 473 }
450 var len = res.length; 474 } else {
451 var i = 0; 475 while (i < len) {
452 if (NUMBER_OF_CAPTURES(lastMatchInfo) == 2) { 476 var elem = res[i];
453 var match_start = 0; 477 if (!%_IsSmi(elem)) {
454 while (i < len) { 478 // elem must be an Array.
455 var elem = res[i]; 479 // Use the apply argument as backing for global RegExp properties.
456 if (%_IsSmi(elem)) { 480 lastMatchInfoOverride = elem;
457 if (elem > 0) { 481 var func_result = replace.apply(null, elem);
458 match_start = (elem >> 11) + (elem & 0x7ff); 482 if (!IS_STRING(func_result)) {
459 } else { 483 func_result = NonStringToString(func_result);
460 match_start = res[++i] - elem;
461 }
462 } else {
463 var func_result = replace.call(null, elem, match_start, subject);
464 if (!IS_STRING(func_result)) {
465 func_result = NonStringToString(func_result);
466 }
467 res[i] = func_result;
468 match_start += elem.length;
469 } 484 }
470 i++; 485 res[i] = func_result;
471 } 486 }
472 } else { 487 i++;
473 while (i < len) {
474 var elem = res[i];
475 if (!%_IsSmi(elem)) {
476 // elem must be an Array.
477 // Use the apply argument as backing for global RegExp properties.
478 lastMatchInfoOverride = elem;
479 var func_result = replace.apply(null, elem);
480 if (!IS_STRING(func_result)) {
481 func_result = NonStringToString(func_result);
482 }
483 res[i] = func_result;
484 }
485 i++;
486 }
487 } 488 }
488 var result = new ReplaceResultBuilder(subject, res);
489 return result.generate();
490 } finally {
491 lastMatchInfoOverride = null;
492 resultArray.length = 0;
493 reusableReplaceArray = resultArray;
494 } 489 }
490 var resultBuilder = new ReplaceResultBuilder(subject, res);
491 var result = resultBuilder.generate();
492 resultArray.length = 0;
493 reusableReplaceArray = resultArray;
494 return result;
495 } else { // Not a global regexp, no need to loop. 495 } else { // Not a global regexp, no need to loop.
496 var matchInfo = DoRegExpExec(regexp, subject, 0); 496 var matchInfo = DoRegExpExec(regexp, subject, 0);
497 if (IS_NULL(matchInfo)) return subject; 497 if (IS_NULL(matchInfo)) return subject;
498 498
499 var result = new ReplaceResultBuilder(subject); 499 var result = new ReplaceResultBuilder(subject);
500 result.addSpecialSlice(0, matchInfo[CAPTURE0]); 500 result.addSpecialSlice(0, matchInfo[CAPTURE0]);
501 var endOfMatch = matchInfo[CAPTURE1]; 501 var endOfMatch = matchInfo[CAPTURE1];
502 result.add(ApplyReplacementFunction(replace, matchInfo, subject)); 502 result.add(ApplyReplacementFunction(replace, matchInfo, subject));
503 // Can't use matchInfo any more from here, since the function could 503 // Can't use matchInfo any more from here, since the function could
504 // overwrite it. 504 // overwrite it.
(...skipping 30 matching lines...) Expand all
535 if (IS_STRING(re)) { 535 if (IS_STRING(re)) {
536 regexp = %_GetFromCache(STRING_TO_REGEXP_CACHE_ID, re); 536 regexp = %_GetFromCache(STRING_TO_REGEXP_CACHE_ID, re);
537 } else if (IS_REGEXP(re)) { 537 } else if (IS_REGEXP(re)) {
538 regexp = re; 538 regexp = re;
539 } else { 539 } else {
540 regexp = new $RegExp(re); 540 regexp = new $RegExp(re);
541 } 541 }
542 var s = TO_STRING_INLINE(this); 542 var s = TO_STRING_INLINE(this);
543 var match = DoRegExpExec(regexp, s, 0); 543 var match = DoRegExpExec(regexp, s, 0);
544 if (match) { 544 if (match) {
545 lastMatchInfo = match;
546 return match[CAPTURE0]; 545 return match[CAPTURE0];
547 } 546 }
548 return -1; 547 return -1;
549 } 548 }
550 549
551 550
552 // ECMA-262 section 15.5.4.13 551 // ECMA-262 section 15.5.4.13
553 function StringSlice(start, end) { 552 function StringSlice(start, end) {
554 var s = TO_STRING_INLINE(this); 553 var s = TO_STRING_INLINE(this);
555 var s_len = s.length; 554 var s_len = s.length;
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after
1004 "small", StringSmall, 1003 "small", StringSmall,
1005 "strike", StringStrike, 1004 "strike", StringStrike,
1006 "sub", StringSub, 1005 "sub", StringSub,
1007 "sup", StringSup, 1006 "sup", StringSup,
1008 "toJSON", StringToJSON 1007 "toJSON", StringToJSON
1009 )); 1008 ));
1010 } 1009 }
1011 1010
1012 1011
1013 SetupString(); 1012 SetupString();
OLDNEW
« no previous file with comments | « src/regexp.js ('k') | test/mjsunit/string-replace.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698