Index: src/string.js |
=================================================================== |
--- src/string.js (revision 6062) |
+++ src/string.js (working copy) |
@@ -159,7 +159,7 @@ |
function StringMatch(regexp) { |
var subject = TO_STRING_INLINE(this); |
if (IS_REGEXP(regexp)) { |
- if (!regexp.global) return regexp.exec(subject); |
+ if (!regexp.global) return RegExpExecNoTests(regexp, subject, 0); |
%_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]); |
// lastMatchInfo is defined in regexp.js. |
return %StringMatch(subject, regexp, lastMatchInfo); |
@@ -245,17 +245,18 @@ |
// Expand the $-expressions in the string and return a new string with |
// the result. |
function ExpandReplacement(string, subject, matchInfo, builder) { |
+ var length = string.length; |
+ var builder_elements = builder.elements; |
var next = %StringIndexOf(string, '$', 0); |
if (next < 0) { |
- builder.add(string); |
+ if (length > 0) builder_elements.push(string); |
return; |
} |
// Compute the number of captures; see ECMA-262, 15.5.4.11, p. 102. |
var m = NUMBER_OF_CAPTURES(matchInfo) >> 1; // Includes the match. |
- if (next > 0) builder.add(SubString(string, 0, next)); |
- var length = string.length; |
+ if (next > 0) builder_elements.push(SubString(string, 0, next)); |
while (true) { |
var expansion = '$'; |
@@ -264,7 +265,7 @@ |
var peek = %_StringCharCodeAt(string, position); |
if (peek == 36) { // $$ |
++position; |
- builder.add('$'); |
+ builder_elements.push('$'); |
} else if (peek == 38) { // $& - match |
++position; |
builder.addSpecialSlice(matchInfo[CAPTURE0], |
@@ -301,14 +302,14 @@ |
// digit capture references, we can only enter here when a |
// single digit capture reference is outside the range of |
// captures. |
- builder.add('$'); |
+ builder_elements.push('$'); |
--position; |
} |
} else { |
- builder.add('$'); |
+ builder_elements.push('$'); |
} |
} else { |
- builder.add('$'); |
+ builder_elements.push('$'); |
} |
// Go the the next $ in the string. |
@@ -318,13 +319,15 @@ |
// haven't reached the end, we need to append the suffix. |
if (next < 0) { |
if (position < length) { |
- builder.add(SubString(string, position, length)); |
+ builder_elements.push(SubString(string, position, length)); |
} |
return; |
} |
// Append substring between the previous and the next $ character. |
- builder.add(SubString(string, position, next)); |
+ if (next > position) { |
+ builder_elements.push(SubString(string, position, next)); |
+ } |
} |
}; |
@@ -559,23 +562,22 @@ |
var currentIndex = 0; |
var startIndex = 0; |
+ var startMatch = 0; |
var result = []; |
outer_loop: |
while (true) { |
if (startIndex === length) { |
- result.push(subject.slice(currentIndex, length)); |
+ result.push(SubString(subject, currentIndex, length)); |
break; |
} |
- var matchInfo = splitMatch(separator, subject, currentIndex, startIndex); |
- |
- if (IS_NULL(matchInfo)) { |
- result.push(subject.slice(currentIndex, length)); |
+ var matchInfo = DoRegExpExec(separator, subject, startIndex); |
+ if (matchInfo == null || length === (startMatch = matchInfo[CAPTURE0])) { |
+ result.push(SubString(subject, currentIndex, length)); |
break; |
} |
- |
var endIndex = matchInfo[CAPTURE1]; |
// We ignore a zero-length match at the currentIndex. |
@@ -584,7 +586,12 @@ |
continue; |
} |
- result.push(SubString(subject, currentIndex, matchInfo[CAPTURE0])); |
+ if (currentIndex + 1 == startMatch) { |
+ result.push(%_StringCharAt(subject, currentIndex)); |
+ } else { |
+ result.push(%_SubString(subject, currentIndex, startMatch)); |
+ } |
+ |
if (result.length === limit) break; |
var matchinfo_len = NUMBER_OF_CAPTURES(matchInfo) + REGEXP_FIRST_CAPTURE; |
@@ -609,19 +616,6 @@ |
} |
-// ECMA-262 section 15.5.4.14 |
-// Helper function used by split. This version returns the matchInfo |
-// instead of allocating a new array with basically the same information. |
-function splitMatch(separator, subject, current_index, start_index) { |
- var matchInfo = DoRegExpExec(separator, subject, start_index); |
- if (matchInfo == null) return null; |
- // Section 15.5.4.14 paragraph two says that we do not allow zero length |
- // matches at the end of the string. |
- if (matchInfo[CAPTURE0] === subject.length) return null; |
- return matchInfo; |
-} |
- |
- |
// ECMA-262 section 15.5.4.15 |
function StringSubstring(start, end) { |
var s = TO_STRING_INLINE(this); |
@@ -844,24 +838,21 @@ |
ReplaceResultBuilder.prototype.add = function(str) { |
str = TO_STRING_INLINE(str); |
- if (str.length > 0) { |
- var elements = this.elements; |
- elements[elements.length] = str; |
- } |
+ if (str.length > 0) this.elements.push(str); |
} |
ReplaceResultBuilder.prototype.addSpecialSlice = function(start, end) { |
var len = end - start; |
if (start < 0 || len <= 0) return; |
- var elements = this.elements; |
if (start < 0x80000 && len < 0x800) { |
- elements[elements.length] = (start << 11) | len; |
+ this.elements.push((start << 11) | len); |
} else { |
// 0 < len <= String::kMaxLength and Smi::kMaxValue >= String::kMaxLength, |
// so -len is a smi. |
- elements[elements.length] = -len; |
- elements[elements.length] = start; |
+ var elements = this.elements; |
+ elements.push(-len); |
+ elements.push(start); |
} |
} |