// 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 {
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);
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);
}
// 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);
}
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, "");
}
// 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;
// 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) {
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);
}
// 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]);
// 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)) {
}
// 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;
} else {
reusableMatchInfo[CAPTURE0] = start;
reusableMatchInfo[CAPTURE1] = end;
- if (!IS_STRING(replace)) replace = ToString(replace);
+ replace = TO_STRING_INLINE(replace);
ExpandReplacement(replace, subject, reusableMatchInfo, builder);
}
// 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,
// 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);
// 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;
// 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 [];
}
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];
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) {
// 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);
// 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
// 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
// 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, "'");
};
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;