| Index: src/string.js
|
| ===================================================================
|
| --- src/string.js (revision 414)
|
| +++ src/string.js (working copy)
|
| @@ -44,22 +44,33 @@
|
|
|
| %FunctionSetPrototype($String, new $String());
|
|
|
| -%AddProperty($String.prototype, "constructor", $String, DONT_ENUM);
|
| -
|
| -%AddProperty($String.prototype, "valueOf", function valueOf() {
|
| +// ECMA-262 section 15.5.4.2
|
| +function StringToString() {
|
| if (!IS_STRING(this) && %ClassOf(this) !== 'String')
|
| - throw new $TypeError('String.prototype.valueOf is not generic');
|
| + throw new $TypeError('String.prototype.toString is not generic');
|
| return %_ValueOf(this);
|
| -}, DONT_ENUM);
|
| +}
|
|
|
| -%AddProperty($String.prototype, "toString", function toString() {
|
| +
|
| +// ECMA-262 section 15.5.4.3
|
| +function StringValueOf() {
|
| if (!IS_STRING(this) && %ClassOf(this) !== 'String')
|
| - throw new $TypeError('String.prototype.toString is not generic');
|
| + throw new $TypeError('String.prototype.valueOf is not generic');
|
| return %_ValueOf(this);
|
| -}, DONT_ENUM);
|
| +}
|
|
|
| +
|
| +// ECMA-262, section 15.5.4.4
|
| +function StringCharAt(pos) {
|
| + var subject = ToString(this);
|
| + var index = TO_INTEGER(pos);
|
| + if (index >= subject.length || index < 0) return "";
|
| + return %CharFromCode(%StringCharCodeAt(subject, index));
|
| +}
|
| +
|
| +
|
| // ECMA-262 section 15.5.4.5
|
| -%AddProperty($String.prototype, "charCodeAt", function charCodeAt(pos) {
|
| +function StringCharCodeAt(pos) {
|
| var fast_answer = %_FastCharCodeAt(this, pos);
|
| if (%_IsSmi(fast_answer)) {
|
| return fast_answer;
|
| @@ -67,23 +78,97 @@
|
| var subject = ToString(this);
|
| var index = TO_INTEGER(pos);
|
| return %StringCharCodeAt(subject, index);
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| // ECMA-262, section 15.5.4.6
|
| -%AddProperty($String.prototype, "concat", function concat() {
|
| +function StringConcat() {
|
| var len = %_ArgumentsLength();
|
| var parts = new $Array(len + 1);
|
| parts[0] = ToString(this);
|
| for (var i = 0; i < len; i++)
|
| parts[i + 1] = ToString(%_Arguments(i));
|
| return parts.join('');
|
| -}, DONT_ENUM);
|
| +}
|
|
|
| // Match ES3 and Safari
|
| -%FunctionSetLength($String.prototype.concat, 1);
|
| +%FunctionSetLength(StringConcat, 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_len = subject_str.length;
|
| + var pattern_str_len = pattern_str.length;
|
| + var index = 0;
|
| + if (%_ArgumentsLength() > 1) {
|
| + var arg1 = %_Arguments(1); // position
|
| + index = TO_INTEGER(arg1);
|
| + }
|
| + if (index < 0) index = 0;
|
| + if (index > subject_str_len) index = subject_str_len;
|
| + if (pattern_str_len + index > subject_str_len) return -1;
|
| + return %StringIndexOf(subject_str, pattern_str, index);
|
| +}
|
| +
|
| +
|
| +// ECMA-262 section 15.5.4.8
|
| +function StringLastIndexOf(searchString /* position */) { // length == 1
|
| + var sub = ToString(this);
|
| + var pat = ToString(searchString);
|
| + var index = (%_ArgumentsLength() > 1)
|
| + ? ToNumber(%_Arguments(1) /* position */)
|
| + : $NaN;
|
| + var firstIndex;
|
| + if ($isNaN(index)) {
|
| + firstIndex = sub.length - pat.length;
|
| + } else {
|
| + firstIndex = TO_INTEGER(index);
|
| + if (firstIndex + pat.length > sub.length) {
|
| + firstIndex = sub.length - pat.length;
|
| + }
|
| + }
|
| + return %StringLastIndexOf(sub, pat, firstIndex);
|
| +}
|
| +
|
| +
|
| +// ECMA-262 section 15.5.4.9
|
| +//
|
| +// This function is implementation specific. For now, we do not
|
| +// do anything locale specific.
|
| +function StringLocaleCompare(other) {
|
| + if (%_ArgumentsLength() === 0) return 0;
|
| +
|
| + var this_str = ToString(this);
|
| + var other_str = ToString(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);
|
| +
|
| + if (!regexp.global) return regexp.exec(subject);
|
| + var matches = DoRegExpExecGlobal(regexp, subject);
|
| +
|
| + // If the regexp did not match, return null.
|
| + if (matches.length == 0) return null;
|
| +
|
| + // Build the result array.
|
| + var result = new $Array(match_string);
|
| + for (var i = 0; i < matches.length; ++i) {
|
| + var match = matches[i];
|
| + var match_string = subject.slice(match[0], match[1]);
|
| + result[i] = match_string;
|
| + }
|
| +
|
| + return result;
|
| +}
|
| +
|
| +
|
| // SubString is an internal function that returns the sub string of 'string'.
|
| // If resulting string is of length 1, we use the one character cache
|
| // otherwise we call the runtime system.
|
| @@ -95,7 +180,7 @@
|
|
|
|
|
| // ECMA-262, section 15.5.4.11
|
| -%AddProperty($String.prototype, "replace", function replace(search, replace) {
|
| +function StringReplace(search, replace) {
|
| var subject = ToString(this);
|
|
|
| // Delegate to one of the regular expression variants if necessary.
|
| @@ -128,7 +213,7 @@
|
| builder.add(SubString(subject, end, subject.length));
|
|
|
| return builder.generate();
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| // Helper function for regular expressions in String.prototype.replace.
|
| @@ -332,82 +417,8 @@
|
| }
|
|
|
|
|
| -// ECMA-262 section 15.5.4.7
|
| -%AddProperty($String.prototype, "indexOf", function indexOf(searchString /* position */) { // length == 1
|
| - var subject_str = ToString(this);
|
| - var pattern_str = ToString(searchString);
|
| - var subject_str_len = subject_str.length;
|
| - var pattern_str_len = pattern_str.length;
|
| - var index = 0;
|
| - if (%_ArgumentsLength() > 1) {
|
| - var arg1 = %_Arguments(1); // position
|
| - index = TO_INTEGER(arg1);
|
| - }
|
| - if (index < 0) index = 0;
|
| - if (index > subject_str_len) index = subject_str_len;
|
| - if (pattern_str_len + index > subject_str_len) return -1;
|
| - return %StringIndexOf(subject_str, pattern_str, index);
|
| -}, DONT_ENUM);
|
| -
|
| -
|
| -// ECMA-262 section 15.5.4.8
|
| -%AddProperty($String.prototype, "lastIndexOf", function lastIndexOf(searchString /* position */) { // length == 1
|
| - var sub = ToString(this);
|
| - var pat = ToString(searchString);
|
| - var index = (%_ArgumentsLength() > 1)
|
| - ? ToNumber(%_Arguments(1) /* position */)
|
| - : $NaN;
|
| - var firstIndex;
|
| - if ($isNaN(index)) {
|
| - firstIndex = sub.length - pat.length;
|
| - } else {
|
| - firstIndex = TO_INTEGER(index);
|
| - if (firstIndex + pat.length > sub.length) {
|
| - firstIndex = sub.length - pat.length;
|
| - }
|
| - }
|
| - return %StringLastIndexOf(sub, pat, firstIndex);
|
| -}, DONT_ENUM);
|
| -
|
| -
|
| -// ECMA-262 section 15.5.4.9
|
| -//
|
| -// This function is implementation specific. For now, we do not
|
| -// do anything locale specific.
|
| -%AddProperty($String.prototype, "localeCompare", function localeCompare(other) {
|
| - if (%_ArgumentsLength() === 0) return 0;
|
| -
|
| - var this_str = ToString(this);
|
| - var other_str = ToString(other);
|
| - return %StringLocaleCompare(this_str, other_str);
|
| -}, DONT_ENUM);
|
| -
|
| -
|
| -// ECMA-262 section 15.5.4.10
|
| -%AddProperty($String.prototype, "match", function match(regexp) {
|
| - if (!IS_REGEXP(regexp)) regexp = new ORIGINAL_REGEXP(regexp);
|
| - var subject = ToString(this);
|
| -
|
| - if (!regexp.global) return regexp.exec(subject);
|
| - var matches = DoRegExpExecGlobal(regexp, subject);
|
| -
|
| - // If the regexp did not match, return null.
|
| - if (matches.length == 0) return null;
|
| -
|
| - // Build the result array.
|
| - var result = new $Array(match_string);
|
| - for (var i = 0; i < matches.length; ++i) {
|
| - var match = matches[i];
|
| - var match_string = subject.slice(match[0], match[1]);
|
| - result[i] = match_string;
|
| - }
|
| -
|
| - return result;
|
| -}, DONT_ENUM);
|
| -
|
| -
|
| // ECMA-262 section 15.5.4.12
|
| -%AddProperty($String.prototype, "search", function search(re) {
|
| +function StringSearch(re) {
|
| var regexp = new ORIGINAL_REGEXP(re);
|
| var s = ToString(this);
|
| var last_idx = regexp.lastIndex; // keep old lastIndex
|
| @@ -418,11 +429,11 @@
|
| return -1;
|
| else
|
| return result.index;
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| // ECMA-262 section 15.5.4.13
|
| -%AddProperty($String.prototype, "slice", function slice(start, end) {
|
| +function StringSlice(start, end) {
|
| var s = ToString(this);
|
| var s_len = s.length;
|
| var start_i = TO_INTEGER(start);
|
| @@ -453,11 +464,11 @@
|
| num_c = 0;
|
|
|
| return SubString(s, start_i, start_i + num_c);
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| // ECMA-262 section 15.5.4.14
|
| -%AddProperty($String.prototype, "split", function split(separator, limit) {
|
| +function StringSplit(separator, limit) {
|
| var subject = ToString(this);
|
| var result = [];
|
| var lim = (limit === void 0) ? 0xffffffff : ToUint32(limit);
|
| @@ -518,7 +529,7 @@
|
|
|
| startIndex = currentIndex = endIndex;
|
| }
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| // ECMA-262 section 15.5.4.14
|
| @@ -549,7 +560,7 @@
|
|
|
|
|
| // ECMA-262 section 15.5.4.15
|
| -%AddProperty($String.prototype, "substring", function substring(start, end) {
|
| +function StringSubstring(start, end) {
|
| var s = ToString(this);
|
| var s_len = s.length;
|
| var start_i = TO_INTEGER(start);
|
| @@ -569,11 +580,11 @@
|
| }
|
|
|
| return SubString(s, start_i, end_i);
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| // This is not a part of ECMA-262.
|
| -%AddProperty($String.prototype, "substr", function substr(start, n) {
|
| +function StringSubstr(start, n) {
|
| var s = ToString(this);
|
| var len;
|
|
|
| @@ -607,35 +618,35 @@
|
| if (end > s.length) end = s.length;
|
|
|
| return SubString(s, start, end);
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| // ECMA-262, 15.5.4.16
|
| -%AddProperty($String.prototype, "toLowerCase", function toLowerCase() {
|
| +function StringToLowerCase() {
|
| return %StringToLowerCase(ToString(this));
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| // ECMA-262, 15.5.4.17
|
| -%AddProperty($String.prototype, "toLocaleLowerCase", function toLocaleLowerCase() {
|
| +function StringToLocaleLowerCase() {
|
| return %StringToLowerCase(ToString(this));
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| // ECMA-262, 15.5.4.18
|
| -%AddProperty($String.prototype, "toUpperCase", function toUpperCase() {
|
| +function StringToUpperCase() {
|
| return %StringToUpperCase(ToString(this));
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| // ECMA-262, 15.5.4.19
|
| -%AddProperty($String.prototype, "toLocaleUpperCase", function toLocaleUpperCase() {
|
| +function StringToLocaleUpperCase() {
|
| return %StringToUpperCase(ToString(this));
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| // ECMA-262, section 15.5.3.2
|
| -%AddProperty($String, "fromCharCode", function fromCharCode(code) {
|
| +function StringFromCharCode(code) {
|
| var n = %_ArgumentsLength();
|
| if (n == 1) return %CharFromCode(ToNumber(code) & 0xffff)
|
|
|
| @@ -645,20 +656,9 @@
|
| var codes = new $Array(n);
|
| for (var i = 0; i < n; i++) codes[i] = ToNumber(%_Arguments(i));
|
| return %StringFromCharCodeArray(codes);
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| -// ECMA-262, section 15.5.4.4
|
| -function charAt(pos) {
|
| - var subject = ToString(this);
|
| - var index = TO_INTEGER(pos);
|
| - if (index >= subject.length || index < 0) return "";
|
| - return %CharFromCode(%StringCharCodeAt(subject, index));
|
| -};
|
| -
|
| -%AddProperty($String.prototype, "charAt", charAt, DONT_ENUM);
|
| -
|
| -
|
| // Helper function for very basic XSS protection.
|
| function HtmlEscape(str) {
|
| return ToString(str).replace(/</g, "<")
|
| @@ -670,69 +670,69 @@
|
|
|
| // Compatibility support for KJS.
|
| // Tested by mozilla/js/tests/js1_5/Regress/regress-276103.js.
|
| -%AddProperty($String.prototype, "link", function link(s) {
|
| +function StringLink(s) {
|
| return "<a href=\"" + HtmlEscape(s) + "\">" + this + "</a>";
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| -%AddProperty($String.prototype, "anchor", function anchor(name) {
|
| +function StringAnchor(name) {
|
| return "<a name=\"" + HtmlEscape(name) + "\">" + this + "</a>";
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| -%AddProperty($String.prototype, "fontcolor", function fontcolor(color) {
|
| +function StringFontcolor(color) {
|
| return "<font color=\"" + HtmlEscape(color) + "\">" + this + "</font>";
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| -%AddProperty($String.prototype, "fontsize", function fontsize(size) {
|
| +function StringFontsize(size) {
|
| return "<font size=\"" + HtmlEscape(size) + "\">" + this + "</font>";
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| -%AddProperty($String.prototype, "big", function big() {
|
| +function StringBig() {
|
| return "<big>" + this + "</big>";
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| -%AddProperty($String.prototype, "blink", function blink() {
|
| +function StringBlink() {
|
| return "<blink>" + this + "</blink>";
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| -%AddProperty($String.prototype, "bold", function bold() {
|
| +function StringBold() {
|
| return "<b>" + this + "</b>";
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| -%AddProperty($String.prototype, "fixed", function fixed() {
|
| +function StringFixed() {
|
| return "<tt>" + this + "</tt>";
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| -%AddProperty($String.prototype, "italics", function italics() {
|
| +function StringItalics() {
|
| return "<i>" + this + "</i>";
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| -%AddProperty($String.prototype, "small", function small() {
|
| +function StringSmall() {
|
| return "<small>" + this + "</small>";
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| -%AddProperty($String.prototype, "strike", function strike() {
|
| +function StringStrike() {
|
| return "<strike>" + this + "</strike>";
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| -%AddProperty($String.prototype, "sub", function sub() {
|
| +function StringSub() {
|
| return "<sub>" + this + "</sub>";
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| -%AddProperty($String.prototype, "sup", function sup() {
|
| +function StringSup() {
|
| return "<sup>" + this + "</sup>";
|
| -}, DONT_ENUM);
|
| +}
|
|
|
|
|
| // StringBuilder support.
|
| @@ -778,3 +778,57 @@
|
| ReplaceResultBuilder.prototype.generate = function() {
|
| return %StringBuilderConcat(this.elements, this.special_string);
|
| }
|
| +
|
| +
|
| +// -------------------------------------------------------------------
|
| +
|
| +function SetupString() {
|
| + // Setup the constructor property on the String prototype object.
|
| + %AddProperty($String.prototype, "constructor", $String, DONT_ENUM);
|
| +
|
| +
|
| + // Setup the non-enumerable functions on the String object.
|
| + InstallFunctions($String, DONT_ENUM, $Array(
|
| + "fromCharCode", StringFromCharCode
|
| + ));
|
| +
|
| +
|
| + // Setup the non-enumerable functions on the String prototype object.
|
| + InstallFunctions($String.prototype, DONT_ENUM, $Array(
|
| + "valueOf", StringValueOf,
|
| + "toString", StringToString,
|
| + "charAt", StringCharAt,
|
| + "charCodeAt", StringCharCodeAt,
|
| + "concat", StringConcat,
|
| + "indexOf", StringIndexOf,
|
| + "lastIndexOf", StringLastIndexOf,
|
| + "localeCompare", StringLocaleCompare,
|
| + "match", StringMatch,
|
| + "replace", StringReplace,
|
| + "search", StringSearch,
|
| + "slice", StringSlice,
|
| + "split", StringSplit,
|
| + "substring", StringSubstring,
|
| + "substr", StringSubstr,
|
| + "toLowerCase", StringToLowerCase,
|
| + "toLocaleLowerCase", StringToLocaleLowerCase,
|
| + "toUpperCase", StringToUpperCase,
|
| + "toLocaleUpperCase", StringToLocaleUpperCase,
|
| + "link", StringLink,
|
| + "anchor", StringAnchor,
|
| + "fontcolor", StringFontcolor,
|
| + "fontsize", StringFontsize,
|
| + "big", StringBig,
|
| + "blink", StringBlink,
|
| + "bold", StringBold,
|
| + "fixed", StringFixed,
|
| + "italics", StringItalics,
|
| + "small", StringSmall,
|
| + "strike", StringStrike,
|
| + "sub", StringSub,
|
| + "sup", StringSup
|
| + ));
|
| +}
|
| +
|
| +
|
| +SetupString();
|
|
|