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

Unified Diff: src/string.js

Issue 12177015: Refactor implementation for String.prototype.replace. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/runtime.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/string.js
diff --git a/src/string.js b/src/string.js
index b39976c51ed8a15332eccabecc2d1c34e26cf962..7d81abbcfda4ecb32f2663a09f5e1ea149d7fe2f 100644
--- a/src/string.js
+++ b/src/string.js
@@ -229,60 +229,78 @@ function StringReplace(search, replace) {
}
var subject = TO_STRING_INLINE(this);
- // Delegate to one of the regular expression variants if necessary.
+ // Decision tree for dispatch
+ // .. regexp search
+ // .... string replace
+ // ...... non-global search
+ // ........ empty string replace
+ // ........ non-empty string replace (with $-expansion)
+ // ...... global search
+ // ........ no need to circumvent last match info override
+ // ........ need to circument last match info override
+ // .... function replace
+ // ...... global search
+ // ...... non-global search
+ // .. string search
+ // .... special case that replaces with one single character
+ // ...... function replace
+ // ...... string replace (with $-expansion)
+
if (IS_REGEXP(search)) {
- // Emulate RegExp.prototype.exec's side effect in step 5, even though
+ // Emulate RegExp.prototype.exec's side effect in step 5, even if
// value is discarded.
ToInteger(search.lastIndex);
%_Log('regexp', 'regexp-replace,%0r,%1S', [search, subject]);
- if (IS_SPEC_FUNCTION(replace)) {
- if (search.global) {
- return StringReplaceGlobalRegExpWithFunction(subject, search, replace);
- } else {
- return StringReplaceNonGlobalRegExpWithFunction(subject,
- search,
- replace);
- }
- } else {
- if (lastMatchInfoOverride == null) {
- var answer = %StringReplaceRegExpWithString(subject,
- search,
- TO_STRING_INLINE(replace),
- lastMatchInfo);
- if (IS_UNDEFINED(answer)) { // No match. Return subject string.
- search.lastIndex = 0;
+
+ if (!IS_SPEC_FUNCTION(replace)) {
+ if (!search.global) {
+ // Non-global regexp search, string replace.
+ var match = DoRegExpExec(search, subject, 0);
+ if (match == null) {
+ search.lastIndex = 0
return subject;
}
- if (search.global) search.lastIndex = 0;
- return answer;
+ if (replace.length == 0) {
+ return SubString(subject, 0, match[CAPTURE0]) +
+ SubString(subject, match[CAPTURE1], subject.length)
+ }
+ return ExpandReplacement(TO_STRING_INLINE(replace),
+ subject,
+ lastMatchInfo,
+ SubString(subject, 0, match[CAPTURE0])) +
+ SubString(subject, match[CAPTURE1], subject.length);
ulan 2013/02/05 09:30:58 I would reformat by putting the first argument of
Yang 2013/02/05 10:47:32 Not entirely sure what you mean here.
+ }
+
+ // Global regexp search, string replace.
+ search.lastIndex = 0;
+ if (lastMatchInfoOverride == null) {
+ return %StringReplaceGlobalRegExpWithString(
+ subject, search, replace, lastMatchInfo);
} else {
// We use this hack to detect whether StringReplaceRegExpWithString
// found at least one hit. In that case we need to remove any
// override.
var saved_subject = lastMatchInfo[LAST_SUBJECT_INDEX];
lastMatchInfo[LAST_SUBJECT_INDEX] = 0;
- var answer = %StringReplaceRegExpWithString(subject,
- search,
- TO_STRING_INLINE(replace),
- lastMatchInfo);
- if (IS_UNDEFINED(answer)) { // No match. Return subject string.
- search.lastIndex = 0;
- lastMatchInfo[LAST_SUBJECT_INDEX] = saved_subject;
- return subject;
- }
+ var answer = %StringReplaceGlobalRegExpWithString(
+ subject, search, replace, lastMatchInfo);
if (%_IsSmi(lastMatchInfo[LAST_SUBJECT_INDEX])) {
lastMatchInfo[LAST_SUBJECT_INDEX] = saved_subject;
} else {
lastMatchInfoOverride = null;
}
- if (search.global) search.lastIndex = 0;
return answer;
}
}
+
+ if (search.global) {
+ // Global regexp search, function replace.
+ return StringReplaceGlobalRegExpWithFunction(subject, search, replace);
+ }
+ // Non-global regexp search, function replace.
+ return StringReplaceNonGlobalRegExpWithFunction(subject, search, replace);
}
- // Convert the search argument to a string and search for it.
- search = TO_STRING_INLINE(search);
ulan 2013/02/05 09:30:58 Looks like it was remove accidentally.
if (search.length == 1 &&
subject.length > 0xFF &&
IS_STRING(replace) &&
@@ -342,6 +360,38 @@ function ExpandReplacement(string, subject, matchInfo, result) {
} else if (peek == 39) { // $' - suffix
++position;
result += SubString(subject, matchInfo[CAPTURE1], subject.length);
+ } else if (peek >= 48 && peek <= 57) { // between '0' and '9'
+ // Convert to digit by subtracting '0'.
+ var scaled_index;
+ var advance;
+ if (peek == 48) { // $0...
+ if (position + 1 == string.length || // ends with '$0', invalid.
+ %_StringCharCodeAt(string, position + 1) != 49) { // not '$01'
ulan 2013/02/05 09:30:58 As discussed offline, we should check $02, ... $nn
+ scaled_index = 1 << 18;
+ } else {
+ scaled_index = 2; // 1 * 2
+ advance = 2;
+ }
+ } else if (peek == 49 &&
+ position + 1 < string.length &&
+ %_StringCharCodeAt(string, position + 1) == 48) { // $10
+ scaled_index = 20; // 10 * 2
+ advance = 2;
+ } else {
+ scaled_index = (peek - 48) << 1; // index * 2
+ advance = 1;
+ }
+
+ if (NUMBER_OF_CAPTURES(matchInfo) > scaled_index) {
+ var start = matchInfo[CAPTURE(scaled_index)];
+ if (start >= 0) {
+ result +=
+ SubString(subject, start, matchInfo[CAPTURE(scaled_index + 1)]);
+ }
+ position += advance;
+ } else {
+ result += '$';
+ }
} else {
result += '$';
}
« no previous file with comments | « src/runtime.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698