Index: src/js/regexp.js |
diff --git a/src/js/regexp.js b/src/js/regexp.js |
index f4101556b21dca293fd3c2c87a113bf1f6e4de99..39afd83b932b80aa750590b2dc81b3378e4fce8a 100644 |
--- a/src/js/regexp.js |
+++ b/src/js/regexp.js |
@@ -9,7 +9,6 @@ |
// ------------------------------------------------------------------- |
// Imports |
-var ExpandReplacement; |
var GlobalArray = global.Array; |
var GlobalObject = global.Object; |
var GlobalRegExp = global.RegExp; |
@@ -26,7 +25,6 @@ var splitSymbol = utils.ImportNow("split_symbol"); |
var SpeciesConstructor; |
utils.Import(function(from) { |
- ExpandReplacement = from.ExpandReplacement; |
MaxSimple = from.MaxSimple; |
MinSimple = from.MinSimple; |
SpeciesConstructor = from.SpeciesConstructor; |
@@ -690,6 +688,31 @@ function StringReplaceNonGlobalRegExpWithFunction(subject, regexp, replace) { |
return result + %_SubString(subject, endOfMatch, subject.length); |
} |
+// Wraps access to matchInfo's captures into a format understood by |
+// GetSubstitution. |
+function MatchInfoCaptureWrapper(matches, subject) { |
+ this.length = NUMBER_OF_CAPTURES(matches) >> 1; |
+ this.match = matches; |
+ this.subject = subject; |
+} |
+ |
+MatchInfoCaptureWrapper.prototype.at = function(ix) { |
+ const match = this.match; |
+ const start = match[CAPTURE(ix << 1)]; |
+ if (start < 0) return UNDEFINED; |
+ return %_SubString(this.subject, start, match[CAPTURE((ix << 1) + 1)]); |
+}; |
+%SetForceInlineFlag(MatchInfoCaptureWrapper.prototype.at); |
+ |
+function ArrayCaptureWrapper(array) { |
+ this.length = array.length; |
+ this.array = array; |
+} |
+ |
+ArrayCaptureWrapper.prototype.at = function(ix) { |
+ return this.array[ix]; |
+}; |
+%SetForceInlineFlag(ArrayCaptureWrapper.prototype.at); |
function RegExpReplace(string, replace) { |
if (!IS_REGEXP(this)) { |
@@ -713,9 +736,17 @@ function RegExpReplace(string, replace) { |
return %_SubString(subject, 0, match[CAPTURE0]) + |
%_SubString(subject, match[CAPTURE1], subject.length) |
} |
- return ExpandReplacement(replace, subject, RegExpLastMatchInfo, |
- %_SubString(subject, 0, match[CAPTURE0])) + |
- %_SubString(subject, match[CAPTURE1], subject.length); |
+ const captures = new MatchInfoCaptureWrapper(match, subject); |
+ const start = match[CAPTURE0]; |
+ const end = match[CAPTURE1]; |
+ |
+ const prefix = %_SubString(subject, 0, start); |
+ const matched = %_SubString(subject, start, end); |
+ const suffix = %_SubString(subject, end, subject.length); |
+ |
+ return prefix + |
+ GetSubstitution(matched, subject, start, captures, replace) + |
+ suffix; |
} |
// Global regexp search, string replace. |
@@ -737,8 +768,6 @@ function RegExpReplace(string, replace) { |
// GetSubstitution(matched, str, position, captures, replacement) |
// Expand the $-expressions in the string and return a new string with |
// the result. |
-// TODO(littledan): Call this function from String.prototype.replace instead |
-// of the very similar ExpandReplacement in src/js/string.js |
function GetSubstitution(matched, string, position, captures, replacement) { |
var matchLength = matched.length; |
var stringLength = string.length; |
@@ -787,7 +816,7 @@ function GetSubstitution(matched, string, position, captures, replacement) { |
} |
} |
if (scaledIndex != 0 && scaledIndex < capturesLength) { |
- var capture = captures[scaledIndex]; |
+ var capture = captures.at(scaledIndex); |
if (!IS_UNDEFINED(capture)) result += capture; |
pos += advance; |
} else { |
@@ -911,7 +940,8 @@ function RegExpSubclassReplace(string, replace) { |
replacement = %reflect_apply(replace, UNDEFINED, parameters, 0, |
parameters.length); |
} else { |
- replacement = GetSubstitution(matched, string, position, captures, |
+ const capturesWrapper = new ArrayCaptureWrapper(captures); |
+ replacement = GetSubstitution(matched, string, position, capturesWrapper, |
replace); |
} |
if (position >= nextSourcePosition) { |
@@ -1219,6 +1249,7 @@ function InternalRegExpReplace(regexp, subject, replacement) { |
// Exports |
utils.Export(function(to) { |
+ to.GetSubstitution = GetSubstitution; |
to.InternalRegExpMatch = InternalRegExpMatch; |
to.InternalRegExpReplace = InternalRegExpReplace; |
to.IsRegExp = IsRegExp; |