Index: src/string.js |
diff --git a/src/string.js b/src/string.js |
index ba01ed67e855172a45951160f28ba4669af47153..49f403de7da8140bb8aeebd9d87c00c329850a0d 100644 |
--- a/src/string.js |
+++ b/src/string.js |
@@ -34,7 +34,7 @@ |
// Set the String function and constructor. |
%SetCode($String, function(x) { |
- var value = %_ArgumentsLength() == 0 ? '' : ToString(x); |
+ var value = %_ArgumentsLength() == 0 ? '' : TO_STRING_INLINE(x); |
if (%_IsConstructCall()) { |
%_SetValueOf(this, value); |
} else { |
@@ -64,7 +64,7 @@ function StringValueOf() { |
function StringCharAt(pos) { |
var char_code = %_FastCharCodeAt(this, pos); |
if (!%_IsSmi(char_code)) { |
- var subject = ToString(this); |
+ var subject = TO_STRING_INLINE(this); |
var index = TO_INTEGER(pos); |
if (index >= subject.length || index < 0) return ""; |
char_code = %StringCharCodeAt(subject, index); |
@@ -79,7 +79,7 @@ function StringCharCodeAt(pos) { |
if (%_IsSmi(fast_answer)) { |
return fast_answer; |
} |
- var subject = ToString(this); |
+ var subject = TO_STRING_INLINE(this); |
var index = TO_INTEGER(pos); |
return %StringCharCodeAt(subject, index); |
} |
@@ -88,7 +88,7 @@ function StringCharCodeAt(pos) { |
// ECMA-262, section 15.5.4.6 |
function StringConcat() { |
var len = %_ArgumentsLength(); |
- var this_as_string = IS_STRING(this) ? this : ToString(this); |
+ var this_as_string = TO_STRING_INLINE(this); |
if (len === 1) { |
return this_as_string + %_Arguments(0); |
} |
@@ -96,7 +96,7 @@ function StringConcat() { |
parts[0] = this_as_string; |
for (var i = 0; i < len; i++) { |
var part = %_Arguments(i); |
- parts[i + 1] = IS_STRING(part) ? part : ToString(part); |
+ parts[i + 1] = TO_STRING_INLINE(part); |
} |
return %StringBuilderConcat(parts, len + 1, ""); |
} |
@@ -107,8 +107,8 @@ function StringConcat() { |
// ECMA-262 section 15.5.4.7 |
function StringIndexOf(searchString /* position */) { // length == 1 |
- var subject_str = ToString(this); |
- var pattern_str = ToString(searchString); |
+ var subject_str = TO_STRING_INLINE(this); |
+ var pattern_str = TO_STRING_INLINE(searchString); |
var subject_str_len = subject_str.length; |
var pattern_str_len = pattern_str.length; |
var index = 0; |
@@ -125,9 +125,9 @@ function StringIndexOf(searchString /* position */) { // length == 1 |
// ECMA-262 section 15.5.4.8 |
function StringLastIndexOf(searchString /* position */) { // length == 1 |
- var sub = ToString(this); |
+ var sub = TO_STRING_INLINE(this); |
var subLength = sub.length; |
- var pat = ToString(searchString); |
+ var pat = TO_STRING_INLINE(searchString); |
var patLength = pat.length; |
var index = subLength - patLength; |
if (%_ArgumentsLength() > 1) { |
@@ -156,8 +156,8 @@ function StringLastIndexOf(searchString /* position */) { // length == 1 |
function StringLocaleCompare(other) { |
if (%_ArgumentsLength() === 0) return 0; |
- var this_str = ToString(this); |
- var other_str = ToString(other); |
+ var this_str = TO_STRING_INLINE(this); |
+ var other_str = TO_STRING_INLINE(other); |
return %StringLocaleCompare(this_str, other_str); |
} |
@@ -165,7 +165,7 @@ function StringLocaleCompare(other) { |
// ECMA-262 section 15.5.4.10 |
function StringMatch(regexp) { |
if (!IS_REGEXP(regexp)) regexp = new ORIGINAL_REGEXP(regexp); |
- var subject = ToString(this); |
+ var subject = TO_STRING_INLINE(this); |
if (!regexp.global) return regexp.exec(subject); |
%_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]); |
@@ -200,7 +200,7 @@ var reusableMatchInfo = [2, "", "", -1, -1]; |
// ECMA-262, section 15.5.4.11 |
function StringReplace(search, replace) { |
- var subject = IS_STRING(this) ? this : ToString(this); |
+ var subject = TO_STRING_INLINE(this); |
// Delegate to one of the regular expression variants if necessary. |
if (IS_REGEXP(search)) { |
@@ -213,7 +213,7 @@ function StringReplace(search, replace) { |
} |
// Convert the search argument to a string and search for it. |
- search = IS_STRING(search) ? search : ToString(search); |
+ search = TO_STRING_INLINE(search); |
var start = %StringIndexOf(subject, search, 0); |
if (start < 0) return subject; |
var end = start + search.length; |
@@ -228,7 +228,7 @@ function StringReplace(search, replace) { |
} else { |
reusableMatchInfo[CAPTURE0] = start; |
reusableMatchInfo[CAPTURE1] = end; |
- if (!IS_STRING(replace)) replace = ToString(replace); |
+ replace = TO_STRING_INLINE(replace); |
ExpandReplacement(replace, subject, reusableMatchInfo, builder); |
} |
@@ -241,7 +241,7 @@ function StringReplace(search, replace) { |
// Helper function for regular expressions in String.prototype.replace. |
function StringReplaceRegExp(subject, regexp, replace) { |
- replace = ToString(replace); |
+ replace = TO_STRING_INLINE(replace); |
return %StringReplaceRegExpWithString(subject, |
regexp, |
replace, |
@@ -462,7 +462,7 @@ function ApplyReplacementFunction(replace, matchInfo, subject) { |
// ECMA-262 section 15.5.4.12 |
function StringSearch(re) { |
var regexp = new ORIGINAL_REGEXP(re); |
- var s = ToString(this); |
+ var s = TO_STRING_INLINE(this); |
var last_idx = regexp.lastIndex; // keep old lastIndex |
regexp.lastIndex = 0; // ignore re.global property |
var result = regexp.exec(s); |
@@ -476,7 +476,7 @@ function StringSearch(re) { |
// ECMA-262 section 15.5.4.13 |
function StringSlice(start, end) { |
- var s = ToString(this); |
+ var s = TO_STRING_INLINE(this); |
var s_len = s.length; |
var start_i = TO_INTEGER(start); |
var end_i = s_len; |
@@ -511,7 +511,7 @@ function StringSlice(start, end) { |
// ECMA-262 section 15.5.4.14 |
function StringSplit(separator, limit) { |
- var subject = ToString(this); |
+ var subject = TO_STRING_INLINE(this); |
limit = (IS_UNDEFINED(limit)) ? 0xffffffff : TO_UINT32(limit); |
if (limit === 0) return []; |
@@ -525,18 +525,35 @@ function StringSplit(separator, limit) { |
} |
var length = subject.length; |
- if (IS_REGEXP(separator)) { |
- %_Log('regexp', 'regexp-split,%0S,%1r', [subject, separator]); |
- } else { |
- separator = ToString(separator); |
+ if (!IS_REGEXP(separator)) { |
+ separator = TO_STRING_INLINE(separator); |
+ var separator_length = separator.length; |
+ |
// If the separator string is empty then return the elements in the subject. |
- if (separator.length == 0) { |
+ if (separator_length === 0) { |
var result = $Array(length); |
for (var i = 0; i < length; i++) result[i] = subject[i]; |
return result; |
} |
+ |
+ var result = []; |
+ var start_index = 0; |
+ var index; |
+ while (true) { |
+ if (start_index + separator_length > length || |
+ (index = %StringIndexOf(subject, separator, start_index)) === -1) { |
+ result.push(SubString(subject, start_index, length)); |
+ break; |
+ } |
+ if (result.push(SubString(subject, start_index, index)) === limit) break; |
+ start_index = index + separator_length; |
+ } |
+ |
+ return result; |
} |
+ %_Log('regexp', 'regexp-split,%0S,%1r', [subject, separator]); |
+ |
if (length === 0) { |
if (splitMatch(separator, subject, 0, 0) != null) return []; |
return [subject]; |
@@ -571,7 +588,8 @@ function StringSplit(separator, limit) { |
result[result.length] = SubString(subject, currentIndex, matchInfo[CAPTURE0]); |
if (result.length === limit) return result; |
- for (var i = 2; i < NUMBER_OF_CAPTURES(matchInfo); i += 2) { |
+ var num_captures = NUMBER_OF_CAPTURES(matchInfo); |
+ for (var i = 2; i < num_captures; i += 2) { |
var start = matchInfo[CAPTURE(i)]; |
var end = matchInfo[CAPTURE(i + 1)]; |
if (start != -1 && end != -1) { |
@@ -591,28 +609,18 @@ function StringSplit(separator, limit) { |
// 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) { |
- if (IS_REGEXP(separator)) { |
- 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; |
- } |
- |
- var separatorIndex = subject.indexOf(separator, start_index); |
- if (separatorIndex === -1) return null; |
- |
- reusableMatchInfo[CAPTURE0] = separatorIndex; |
- reusableMatchInfo[CAPTURE1] = separatorIndex + separator.length; |
- return reusableMatchInfo; |
-}; |
+ 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 = this; |
- if (!IS_STRING(s)) s = ToString(s); |
+ var s = TO_STRING_INLINE(this); |
var s_len = s.length; |
var start_i = TO_INTEGER(start); |
@@ -643,7 +651,7 @@ function StringSubstring(start, end) { |
// This is not a part of ECMA-262. |
function StringSubstr(start, n) { |
- var s = ToString(this); |
+ var s = TO_STRING_INLINE(this); |
var len; |
// Correct n: If not given, set to string length; if explicitly |
@@ -681,38 +689,38 @@ function StringSubstr(start, n) { |
// ECMA-262, 15.5.4.16 |
function StringToLowerCase() { |
- return %StringToLowerCase(ToString(this)); |
+ return %StringToLowerCase(TO_STRING_INLINE(this)); |
} |
// ECMA-262, 15.5.4.17 |
function StringToLocaleLowerCase() { |
- return %StringToLowerCase(ToString(this)); |
+ return %StringToLowerCase(TO_STRING_INLINE(this)); |
} |
// ECMA-262, 15.5.4.18 |
function StringToUpperCase() { |
- return %StringToUpperCase(ToString(this)); |
+ return %StringToUpperCase(TO_STRING_INLINE(this)); |
} |
// ECMA-262, 15.5.4.19 |
function StringToLocaleUpperCase() { |
- return %StringToUpperCase(ToString(this)); |
+ return %StringToUpperCase(TO_STRING_INLINE(this)); |
} |
// ES5, 15.5.4.20 |
function StringTrim() { |
- return %StringTrim(ToString(this), true, true); |
+ return %StringTrim(TO_STRING_INLINE(this), true, true); |
} |
function StringTrimLeft() { |
- return %StringTrim(ToString(this), true, false); |
+ return %StringTrim(TO_STRING_INLINE(this), true, false); |
} |
function StringTrimRight() { |
- return %StringTrim(ToString(this), false, true); |
+ return %StringTrim(TO_STRING_INLINE(this), false, true); |
} |
// ECMA-262, section 15.5.3.2 |
@@ -731,10 +739,10 @@ function StringFromCharCode(code) { |
// Helper function for very basic XSS protection. |
function HtmlEscape(str) { |
- return ToString(str).replace(/</g, "<") |
- .replace(/>/g, ">") |
- .replace(/"/g, """) |
- .replace(/'/g, "'"); |
+ return TO_STRING_INLINE(str).replace(/</g, "<") |
+ .replace(/>/g, ">") |
+ .replace(/"/g, """) |
+ .replace(/'/g, "'"); |
}; |
@@ -813,7 +821,7 @@ function ReplaceResultBuilder(str) { |
ReplaceResultBuilder.prototype.add = function(str) { |
- if (!IS_STRING(str)) str = ToString(str); |
+ str = TO_STRING_INLINE(str); |
if (str.length > 0) { |
var elements = this.elements; |
elements[elements.length] = str; |