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

Unified Diff: src/string.js

Issue 1994019: Simplified replace JS a little. (Closed)
Patch Set: Address review comments. Forward to head. Created 10 years, 7 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 | « no previous file | 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 9433249188c9fccf26f42513a9bb011f1724c4a9..59a501f9ee502220124a68869aedeb9b10e03a13 100644
--- a/src/string.js
+++ b/src/string.js
@@ -241,7 +241,13 @@ function StringReplace(search, replace) {
%_Log('regexp', 'regexp-replace,%0r,%1S', [search, subject]);
if (IS_FUNCTION(replace)) {
regExpCache.type = 'none';
- return StringReplaceRegExpWithFunction(subject, search, replace);
+ if (search.global) {
+ return StringReplaceGlobalRegExpWithFunction(subject, search, replace);
+ } else {
+ return StringReplaceNonGlobalRegExpWithFunction(subject,
+ search,
+ replace);
+ }
} else {
return StringReplaceRegExp(subject, search, replace);
}
@@ -396,9 +402,9 @@ function CaptureString(string, lastCaptureInfo, index) {
var scaled = index << 1;
// Compute start and end.
var start = lastCaptureInfo[CAPTURE(scaled)];
+ // If start isn't valid, return undefined.
+ if (start < 0) return;
var end = lastCaptureInfo[CAPTURE(scaled + 1)];
- // If either start or end is missing return undefined.
- if (start < 0 || end < 0) return;
return SubString(string, start, end);
};
@@ -410,9 +416,8 @@ function addCaptureString(builder, matchInfo, index) {
var scaled = index << 1;
// Compute start and end.
var start = matchInfo[CAPTURE(scaled)];
+ if (start < 0) return;
var end = matchInfo[CAPTURE(scaled + 1)];
- // If either start or end is missing return.
- if (start < 0 || end <= start) return;
builder.addSpecialSlice(start, end);
};
@@ -423,112 +428,116 @@ var reusableReplaceArray = $Array(16);
// Helper function for replacing regular expressions with the result of a
// function application in String.prototype.replace.
-function StringReplaceRegExpWithFunction(subject, regexp, replace) {
- if (regexp.global) {
- var resultArray = reusableReplaceArray;
- if (resultArray) {
- reusableReplaceArray = null;
- } else {
- // Inside a nested replace (replace called from the replacement function
- // of another replace) or we have failed to set the reusable array
- // back due to an exception in a replacement function. Create a new
- // array to use in the future, or until the original is written back.
- resultArray = $Array(16);
- }
-
- var res = %RegExpExecMultiple(regexp,
- subject,
- lastMatchInfo,
- resultArray);
- regexp.lastIndex = 0;
- if (IS_NULL(res)) {
- // No matches at all.
- return subject;
- }
- var len = res.length;
- var i = 0;
- if (NUMBER_OF_CAPTURES(lastMatchInfo) == 2) {
- var match_start = 0;
- var override = [null, 0, subject];
- while (i < len) {
- var elem = res[i];
- if (%_IsSmi(elem)) {
- if (elem > 0) {
- match_start = (elem >> 11) + (elem & 0x7ff);
- } else {
- match_start = res[++i] - elem;
- }
+function StringReplaceGlobalRegExpWithFunction(subject, regexp, replace) {
+ var resultArray = reusableReplaceArray;
+ if (resultArray) {
+ reusableReplaceArray = null;
+ } else {
+ // Inside a nested replace (replace called from the replacement function
+ // of another replace) or we have failed to set the reusable array
+ // back due to an exception in a replacement function. Create a new
+ // array to use in the future, or until the original is written back.
+ resultArray = $Array(16);
+ }
+ var res = %RegExpExecMultiple(regexp,
+ subject,
+ lastMatchInfo,
+ resultArray);
+ regexp.lastIndex = 0;
+ if (IS_NULL(res)) {
+ // No matches at all.
+ reusableReplaceArray = resultArray;
+ return subject;
+ }
+ var len = res.length;
+ var i = 0;
+ if (NUMBER_OF_CAPTURES(lastMatchInfo) == 2) {
+ var match_start = 0;
+ var override = [null, 0, subject];
+ var receiver = %GetGlobalReceiver();
+ while (i < len) {
+ var elem = res[i];
+ if (%_IsSmi(elem)) {
+ if (elem > 0) {
+ match_start = (elem >> 11) + (elem & 0x7ff);
} else {
- override[0] = elem;
- override[1] = match_start;
- lastMatchInfoOverride = override;
- var func_result = replace.call(null, elem, match_start, subject);
- if (!IS_STRING(func_result)) {
- func_result = NonStringToString(func_result);
- }
- res[i] = func_result;
- match_start += elem.length;
+ match_start = res[++i] - elem;
}
- i++;
+ } else {
+ override[0] = elem;
+ override[1] = match_start;
+ lastMatchInfoOverride = override;
+ var func_result =
+ %_CallFunction(receiver, elem, match_start, subject, replace);
+ if (!IS_STRING(func_result)) {
+ func_result = NonStringToString(func_result);
+ }
+ res[i] = func_result;
+ match_start += elem.length;
}
- } else {
- while (i < len) {
- var elem = res[i];
- if (!%_IsSmi(elem)) {
- // elem must be an Array.
- // Use the apply argument as backing for global RegExp properties.
- lastMatchInfoOverride = elem;
- var func_result = replace.apply(null, elem);
- if (!IS_STRING(func_result)) {
- func_result = NonStringToString(func_result);
- }
- res[i] = func_result;
+ i++;
+ }
+ } else {
+ while (i < len) {
+ var elem = res[i];
+ if (!%_IsSmi(elem)) {
+ // elem must be an Array.
+ // Use the apply argument as backing for global RegExp properties.
+ lastMatchInfoOverride = elem;
+ var func_result = replace.apply(null, elem);
+ if (!IS_STRING(func_result)) {
+ func_result = NonStringToString(func_result);
}
- i++;
+ res[i] = func_result;
}
+ i++;
}
- var resultBuilder = new ReplaceResultBuilder(subject, res);
- var result = resultBuilder.generate();
- resultArray.length = 0;
- reusableReplaceArray = resultArray;
- return result;
- } else { // Not a global regexp, no need to loop.
- var matchInfo = DoRegExpExec(regexp, subject, 0);
- if (IS_NULL(matchInfo)) return subject;
-
- var result = new ReplaceResultBuilder(subject);
- result.addSpecialSlice(0, matchInfo[CAPTURE0]);
- var endOfMatch = matchInfo[CAPTURE1];
- result.add(ApplyReplacementFunction(replace, matchInfo, subject));
- // Can't use matchInfo any more from here, since the function could
- // overwrite it.
- result.addSpecialSlice(endOfMatch, subject.length);
- return result.generate();
}
+ var resultBuilder = new ReplaceResultBuilder(subject, res);
+ var result = resultBuilder.generate();
+ resultArray.length = 0;
+ reusableReplaceArray = resultArray;
+ return result;
}
-// Helper function to apply a string replacement function once.
-function ApplyReplacementFunction(replace, matchInfo, subject) {
+function StringReplaceNonGlobalRegExpWithFunction(subject, regexp, replace) {
+ var matchInfo = DoRegExpExec(regexp, subject, 0);
+ if (IS_NULL(matchInfo)) return subject;
+ var result = new ReplaceResultBuilder(subject);
+ var index = matchInfo[CAPTURE0];
+ result.addSpecialSlice(0, index);
+ var endOfMatch = matchInfo[CAPTURE1];
// Compute the parameter list consisting of the match, captures, index,
// and subject for the replace function invocation.
- var index = matchInfo[CAPTURE0];
// The number of captures plus one for the match.
var m = NUMBER_OF_CAPTURES(matchInfo) >> 1;
+ var replacement;
if (m == 1) {
- var s = CaptureString(subject, matchInfo, 0);
+ // No captures, only the match, which is always valid.
+ var s = SubString(subject, index, endOfMatch);
// Don't call directly to avoid exposing the built-in global object.
- return replace.call(null, s, index, subject);
- }
- var parameters = $Array(m + 2);
- for (var j = 0; j < m; j++) {
- parameters[j] = CaptureString(subject, matchInfo, j);
+ replacement =
+ %_CallFunction(%GetGlobalReceiver(), s, index, subject, replace);
+ } else {
+ var parameters = $Array(m + 2);
+ for (var j = 0; j < m; j++) {
+ parameters[j] = CaptureString(subject, matchInfo, j);
+ }
+ parameters[j] = index;
+ parameters[j + 1] = subject;
+
+ replacement = replace.apply(null, parameters);
}
- parameters[j] = index;
- parameters[j + 1] = subject;
- return replace.apply(null, parameters);
+
+ result.add(replacement); // The add method converts to string if necessary.
+ // Can't use matchInfo any more from here, since the function could
+ // overwrite it.
+ result.addSpecialSlice(endOfMatch, subject.length);
+ return result.generate();
}
+
// ECMA-262 section 15.5.4.12
function StringSearch(re) {
var regexp;
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698