summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/v8/src/string.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/v8/src/string.js')
-rw-r--r--src/3rdparty/v8/src/string.js1047
1 files changed, 0 insertions, 1047 deletions
diff --git a/src/3rdparty/v8/src/string.js b/src/3rdparty/v8/src/string.js
deleted file mode 100644
index 2f8043c..0000000
--- a/src/3rdparty/v8/src/string.js
+++ /dev/null
@@ -1,1047 +0,0 @@
-// Copyright 2012 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// This file relies on the fact that the following declaration has been made
-// in runtime.js:
-// var $String = global.String;
-// var $NaN = 0/0;
-
-
-// Set the String function and constructor.
-%SetCode($String, function(x) {
- var value = %_ArgumentsLength() == 0 ? '' : TO_STRING_INLINE(x);
- if (%_IsConstructCall()) {
- %_SetValueOf(this, value);
- } else {
- return value;
- }
-});
-
-%FunctionSetPrototype($String, new $String());
-
-// ECMA-262 section 15.5.4.2
-function StringToString() {
- if (!IS_STRING(this) && !IS_STRING_WRAPPER(this)) {
- throw new $TypeError('String.prototype.toString is not generic');
- }
- return %_ValueOf(this);
-}
-
-
-// ECMA-262 section 15.5.4.3
-function StringValueOf() {
- if (!IS_STRING(this) && !IS_STRING_WRAPPER(this)) {
- throw new $TypeError('String.prototype.valueOf is not generic');
- }
- return %_ValueOf(this);
-}
-
-
-// ECMA-262, section 15.5.4.4
-function StringCharAt(pos) {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.charAt"]);
- }
- var result = %_StringCharAt(this, pos);
- if (%_IsSmi(result)) {
- result = %_StringCharAt(TO_STRING_INLINE(this), TO_INTEGER(pos));
- }
- return result;
-}
-
-
-// ECMA-262 section 15.5.4.5
-function StringCharCodeAt(pos) {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.charCodeAt"]);
- }
- var result = %_StringCharCodeAt(this, pos);
- if (!%_IsSmi(result)) {
- result = %_StringCharCodeAt(TO_STRING_INLINE(this), TO_INTEGER(pos));
- }
- return result;
-}
-
-
-// ECMA-262, section 15.5.4.6
-function StringConcat() {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.concat"]);
- }
- var len = %_ArgumentsLength();
- var this_as_string = TO_STRING_INLINE(this);
- if (len === 1) {
- return this_as_string + %_Arguments(0);
- }
- var parts = new InternalArray(len + 1);
- parts[0] = this_as_string;
- for (var i = 0; i < len; i++) {
- var part = %_Arguments(i);
- parts[i + 1] = TO_STRING_INLINE(part);
- }
- return %StringBuilderConcat(parts, len + 1, "");
-}
-
-// Match ES3 and Safari
-%FunctionSetLength(StringConcat, 1);
-
-
-// ECMA-262 section 15.5.4.7
-function StringIndexOf(pattern /* position */) { // length == 1
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.indexOf"]);
- }
- var subject = TO_STRING_INLINE(this);
- pattern = TO_STRING_INLINE(pattern);
- var index = 0;
- if (%_ArgumentsLength() > 1) {
- index = %_Arguments(1); // position
- index = TO_INTEGER(index);
- if (index < 0) index = 0;
- if (index > subject.length) index = subject.length;
- }
- return %StringIndexOf(subject, pattern, index);
-}
-
-
-// ECMA-262 section 15.5.4.8
-function StringLastIndexOf(pat /* position */) { // length == 1
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.lastIndexOf"]);
- }
- var sub = TO_STRING_INLINE(this);
- var subLength = sub.length;
- var pat = TO_STRING_INLINE(pat);
- var patLength = pat.length;
- var index = subLength - patLength;
- if (%_ArgumentsLength() > 1) {
- var position = ToNumber(%_Arguments(1));
- if (!NUMBER_IS_NAN(position)) {
- position = TO_INTEGER(position);
- if (position < 0) {
- position = 0;
- }
- if (position + patLength < subLength) {
- index = position;
- }
- }
- }
- if (index < 0) {
- return -1;
- }
- return %StringLastIndexOf(sub, pat, index);
-}
-
-
-// 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 (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.localeCompare"]);
- }
- if (%_ArgumentsLength() === 0) return 0;
- return %StringLocaleCompare(TO_STRING_INLINE(this),
- TO_STRING_INLINE(other));
-}
-
-
-// ECMA-262 section 15.5.4.10
-function StringMatch(regexp) {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.match"]);
- }
- var subject = TO_STRING_INLINE(this);
- if (IS_REGEXP(regexp)) {
- // Emulate RegExp.prototype.exec's side effect in step 5, even though
- // value is discarded.
- ToInteger(regexp.lastIndex);
- if (!regexp.global) return RegExpExecNoTests(regexp, subject, 0);
- %_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]);
- // lastMatchInfo is defined in regexp.js.
- var result = %StringMatch(subject, regexp, lastMatchInfo);
- if (result !== null) lastMatchInfoOverride = null;
- regexp.lastIndex = 0;
- return result;
- }
- // Non-regexp argument.
- regexp = new $RegExp(regexp);
- return RegExpExecNoTests(regexp, subject, 0);
-}
-
-
-// This has the same size as the lastMatchInfo array, and can be used for
-// functions that expect that structure to be returned. It is used when the
-// needle is a string rather than a regexp. In this case we can't update
-// lastMatchArray without erroneously affecting the properties on the global
-// RegExp object.
-var reusableMatchInfo = [2, "", "", -1, -1];
-
-
-// ECMA-262, section 15.5.4.11
-function StringReplace(search, replace) {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.replace"]);
- }
- var subject = TO_STRING_INLINE(this);
-
- // Decision tree for dispatch
- // .. regexp search
- // .... string replace
- // ...... non-global search
- // ........ empty string replace
- // ........ non-empty string replace (with $-expansion)
- // ...... global search
- // ........ no need to circumvent last match info override
- // ........ need to circument last match info override
- // .... function replace
- // ...... global search
- // ...... non-global search
- // .. string search
- // .... special case that replaces with one single character
- // ...... function replace
- // ...... string replace (with $-expansion)
-
- if (IS_REGEXP(search)) {
- // Emulate RegExp.prototype.exec's side effect in step 5, even if
- // value is discarded.
- ToInteger(search.lastIndex);
- %_Log('regexp', 'regexp-replace,%0r,%1S', [search, subject]);
-
- if (!IS_SPEC_FUNCTION(replace)) {
- replace = TO_STRING_INLINE(replace);
-
- if (!search.global) {
- // Non-global regexp search, string replace.
- var match = DoRegExpExec(search, subject, 0);
- if (match == null) {
- search.lastIndex = 0
- return subject;
- }
- if (replace.length == 0) {
- return %_SubString(subject, 0, match[CAPTURE0]) +
- %_SubString(subject, match[CAPTURE1], subject.length)
- }
- return ExpandReplacement(replace, subject, lastMatchInfo,
- %_SubString(subject, 0, match[CAPTURE0])) +
- %_SubString(subject, match[CAPTURE1], subject.length);
- }
-
- // Global regexp search, string replace.
- search.lastIndex = 0;
- if (lastMatchInfoOverride == null) {
- return %StringReplaceGlobalRegExpWithString(
- subject, search, replace, lastMatchInfo);
- } else {
- // We use this hack to detect whether StringReplaceRegExpWithString
- // found at least one hit. In that case we need to remove any
- // override.
- var saved_subject = lastMatchInfo[LAST_SUBJECT_INDEX];
- lastMatchInfo[LAST_SUBJECT_INDEX] = 0;
- var answer = %StringReplaceGlobalRegExpWithString(
- subject, search, replace, lastMatchInfo);
- if (%_IsSmi(lastMatchInfo[LAST_SUBJECT_INDEX])) {
- lastMatchInfo[LAST_SUBJECT_INDEX] = saved_subject;
- } else {
- lastMatchInfoOverride = null;
- }
- return answer;
- }
- }
-
- if (search.global) {
- // Global regexp search, function replace.
- return StringReplaceGlobalRegExpWithFunction(subject, search, replace);
- }
- // Non-global regexp search, function replace.
- return StringReplaceNonGlobalRegExpWithFunction(subject, search, replace);
- }
-
- search = TO_STRING_INLINE(search);
-
- if (search.length == 1 &&
- subject.length > 0xFF &&
- IS_STRING(replace) &&
- %StringIndexOf(replace, '$', 0) < 0) {
- // Searching by traversing a cons string tree and replace with cons of
- // slices works only when the replaced string is a single character, being
- // replaced by a simple string and only pays off for long strings.
- return %StringReplaceOneCharWithString(subject, search, replace);
- }
- var start = %StringIndexOf(subject, search, 0);
- if (start < 0) return subject;
- var end = start + search.length;
-
- var result = %_SubString(subject, 0, start);
-
- // Compute the string to replace with.
- if (IS_SPEC_FUNCTION(replace)) {
- var receiver = %GetDefaultReceiver(replace);
- result += %_CallFunction(receiver, search, start, subject, replace);
- } else {
- reusableMatchInfo[CAPTURE0] = start;
- reusableMatchInfo[CAPTURE1] = end;
- result = ExpandReplacement(TO_STRING_INLINE(replace),
- subject,
- reusableMatchInfo,
- result);
- }
-
- return result + %_SubString(subject, end, subject.length);
-}
-
-
-// Expand the $-expressions in the string and return a new string with
-// the result.
-function ExpandReplacement(string, subject, matchInfo, result) {
- var length = string.length;
- var next = %StringIndexOf(string, '$', 0);
- if (next < 0) {
- if (length > 0) result += string;
- return result;
- }
-
- if (next > 0) result += %_SubString(string, 0, next);
-
- while (true) {
- var expansion = '$';
- var position = next + 1;
- if (position < length) {
- var peek = %_StringCharCodeAt(string, position);
- if (peek == 36) { // $$
- ++position;
- result += '$';
- } else if (peek == 38) { // $& - match
- ++position;
- result +=
- %_SubString(subject, matchInfo[CAPTURE0], matchInfo[CAPTURE1]);
- } else if (peek == 96) { // $` - prefix
- ++position;
- result += %_SubString(subject, 0, matchInfo[CAPTURE0]);
- } else if (peek == 39) { // $' - suffix
- ++position;
- result += %_SubString(subject, matchInfo[CAPTURE1], subject.length);
- } else if (peek >= 48 && peek <= 57) {
- // Valid indices are $1 .. $9, $01 .. $09 and $10 .. $99
- var scaled_index = (peek - 48) << 1;
- var advance = 1;
- var number_of_captures = NUMBER_OF_CAPTURES(matchInfo);
- if (position + 1 < string.length) {
- var next = %_StringCharCodeAt(string, position + 1);
- if (next >= 48 && next <= 57) {
- var new_scaled_index = scaled_index * 10 + ((next - 48) << 1);
- if (new_scaled_index < number_of_captures) {
- scaled_index = new_scaled_index;
- advance = 2;
- }
- }
- }
- if (scaled_index != 0 && scaled_index < number_of_captures) {
- var start = matchInfo[CAPTURE(scaled_index)];
- if (start >= 0) {
- result +=
- %_SubString(subject, start, matchInfo[CAPTURE(scaled_index + 1)]);
- }
- position += advance;
- } else {
- result += '$';
- }
- } else {
- result += '$';
- }
- } else {
- result += '$';
- }
-
- // Go the the next $ in the string.
- next = %StringIndexOf(string, '$', position);
-
- // Return if there are no more $ characters in the string. If we
- // haven't reached the end, we need to append the suffix.
- if (next < 0) {
- if (position < length) {
- result += %_SubString(string, position, length);
- }
- return result;
- }
-
- // Append substring between the previous and the next $ character.
- if (next > position) {
- result += %_SubString(string, position, next);
- }
- }
- return result;
-}
-
-
-// Compute the string of a given regular expression capture.
-function CaptureString(string, lastCaptureInfo, index) {
- // Scale the index.
- var scaled = index << 1;
- // Compute start and end.
- var start = lastCaptureInfo[CAPTURE(scaled)];
- // If start isn't valid, return undefined.
- if (start < 0) return;
- var end = lastCaptureInfo[CAPTURE(scaled + 1)];
- return %_SubString(string, start, end);
-}
-
-
-// TODO(lrn): This array will survive indefinitely if replace is never
-// called again. However, it will be empty, since the contents are cleared
-// in the finally block.
-var reusableReplaceArray = new InternalArray(16);
-
-// Helper function for replacing regular expressions with the result of a
-// function application in String.prototype.replace.
-function StringReplaceGlobalRegExpWithFunction(subject, regexp, replace) {
- var resultArray = reusableReplaceArray;
- if (resultArray) {
- reusableReplaceArray = null;
- } else {
- // Inside a nested replace (replace called from the replacement function
- // of another replace) or we have failed to set the reusable array
- // back due to an exception in a replacement function. Create a new
- // array to use in the future, or until the original is written back.
- resultArray = new InternalArray(16);
- }
- var res = %RegExpExecMultiple(regexp,
- subject,
- lastMatchInfo,
- resultArray);
- regexp.lastIndex = 0;
- if (IS_NULL(res)) {
- // No matches at all.
- reusableReplaceArray = resultArray;
- return subject;
- }
- var len = res.length;
- if (NUMBER_OF_CAPTURES(lastMatchInfo) == 2) {
- // If the number of captures is two then there are no explicit captures in
- // the regexp, just the implicit capture that captures the whole match. In
- // this case we can simplify quite a bit and end up with something faster.
- // The builder will consist of some integers that indicate slices of the
- // input string and some replacements that were returned from the replace
- // function.
- var match_start = 0;
- var override = new InternalPackedArray(null, 0, subject);
- var receiver = %GetDefaultReceiver(replace);
- for (var i = 0; i < len; i++) {
- var elem = res[i];
- if (%_IsSmi(elem)) {
- // Integers represent slices of the original string. Use these to
- // get the offsets we need for the override array (so things like
- // RegExp.leftContext work during the callback function.
- if (elem > 0) {
- match_start = (elem >> 11) + (elem & 0x7ff);
- } else {
- match_start = res[++i] - elem;
- }
- } else {
- override[0] = elem;
- override[1] = match_start;
- lastMatchInfoOverride = override;
- var func_result =
- %_CallFunction(receiver, elem, match_start, subject, replace);
- // Overwrite the i'th element in the results with the string we got
- // back from the callback function.
- res[i] = TO_STRING_INLINE(func_result);
- match_start += elem.length;
- }
- }
- } else {
- var receiver = %GetDefaultReceiver(replace);
- for (var i = 0; i < len; i++) {
- var elem = res[i];
- if (!%_IsSmi(elem)) {
- // elem must be an Array.
- // Use the apply argument as backing for global RegExp properties.
- lastMatchInfoOverride = elem;
- var func_result = %Apply(replace, receiver, elem, 0, elem.length);
- // Overwrite the i'th element in the results with the string we got
- // back from the callback function.
- res[i] = TO_STRING_INLINE(func_result);
- }
- }
- }
- var resultBuilder = new ReplaceResultBuilder(subject, res);
- var result = resultBuilder.generate();
- resultArray.length = 0;
- reusableReplaceArray = resultArray;
- return result;
-}
-
-
-function StringReplaceNonGlobalRegExpWithFunction(subject, regexp, replace) {
- var matchInfo = DoRegExpExec(regexp, subject, 0);
- if (IS_NULL(matchInfo)) {
- regexp.lastIndex = 0;
- return subject;
- }
- var index = matchInfo[CAPTURE0];
- var result = %_SubString(subject, 0, index);
- var endOfMatch = matchInfo[CAPTURE1];
- // Compute the parameter list consisting of the match, captures, index,
- // and subject for the replace function invocation.
- // The number of captures plus one for the match.
- var m = NUMBER_OF_CAPTURES(matchInfo) >> 1;
- var replacement;
- var receiver = %GetDefaultReceiver(replace);
- if (m == 1) {
- // No captures, only the match, which is always valid.
- var s = %_SubString(subject, index, endOfMatch);
- // Don't call directly to avoid exposing the built-in global object.
- replacement = %_CallFunction(receiver, s, index, subject, replace);
- } else {
- var parameters = new InternalArray(m + 2);
- for (var j = 0; j < m; j++) {
- parameters[j] = CaptureString(subject, matchInfo, j);
- }
- parameters[j] = index;
- parameters[j + 1] = subject;
-
- replacement = %Apply(replace, receiver, parameters, 0, j + 2);
- }
-
- result += replacement; // The add method converts to string if necessary.
- // Can't use matchInfo any more from here, since the function could
- // overwrite it.
- return result + %_SubString(subject, endOfMatch, subject.length);
-}
-
-
-// ECMA-262 section 15.5.4.12
-function StringSearch(re) {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.search"]);
- }
- var regexp;
- if (IS_STRING(re)) {
- regexp = %_GetFromCache(STRING_TO_REGEXP_CACHE_ID, re);
- } else if (IS_REGEXP(re)) {
- regexp = re;
- } else {
- regexp = new $RegExp(re);
- }
- var match = DoRegExpExec(regexp, TO_STRING_INLINE(this), 0);
- if (match) {
- return match[CAPTURE0];
- }
- return -1;
-}
-
-
-// ECMA-262 section 15.5.4.13
-function StringSlice(start, end) {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.slice"]);
- }
- var s = TO_STRING_INLINE(this);
- var s_len = s.length;
- var start_i = TO_INTEGER(start);
- var end_i = s_len;
- if (end !== void 0) {
- end_i = TO_INTEGER(end);
- }
-
- if (start_i < 0) {
- start_i += s_len;
- if (start_i < 0) {
- start_i = 0;
- }
- } else {
- if (start_i > s_len) {
- return '';
- }
- }
-
- if (end_i < 0) {
- end_i += s_len;
- if (end_i < 0) {
- return '';
- }
- } else {
- if (end_i > s_len) {
- end_i = s_len;
- }
- }
-
- if (end_i <= start_i) {
- return '';
- }
-
- return %_SubString(s, start_i, end_i);
-}
-
-
-// ECMA-262 section 15.5.4.14
-function StringSplit(separator, limit) {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.split"]);
- }
- var subject = TO_STRING_INLINE(this);
- limit = (IS_UNDEFINED(limit)) ? 0xffffffff : TO_UINT32(limit);
-
- // ECMA-262 says that if separator is undefined, the result should
- // be an array of size 1 containing the entire string.
- if (IS_UNDEFINED(separator)) {
- return [subject];
- }
-
- var length = subject.length;
- if (!IS_REGEXP(separator)) {
- separator = TO_STRING_INLINE(separator);
-
- if (limit === 0) return [];
-
- var separator_length = separator.length;
-
- // If the separator string is empty then return the elements in the subject.
- if (separator_length === 0) return %StringToArray(subject, limit);
-
- var result = %StringSplit(subject, separator, limit);
-
- return result;
- }
-
- if (limit === 0) return [];
-
- // Separator is a regular expression.
- return StringSplitOnRegExp(subject, separator, limit, length);
-}
-
-
-function StringSplitOnRegExp(subject, separator, limit, length) {
- %_Log('regexp', 'regexp-split,%0S,%1r', [subject, separator]);
-
- if (length === 0) {
- if (DoRegExpExec(separator, subject, 0, 0) != null) {
- return [];
- }
- return [subject];
- }
-
- var currentIndex = 0;
- var startIndex = 0;
- var startMatch = 0;
- var result = [];
-
- outer_loop:
- while (true) {
-
- if (startIndex === length) {
- result.push(%_SubString(subject, currentIndex, length));
- break;
- }
-
- 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.
- if (startIndex === endIndex && endIndex === currentIndex) {
- startIndex++;
- continue;
- }
-
- result.push(%_SubString(subject, currentIndex, startMatch));
-
- if (result.length === limit) break;
-
- var matchinfo_len = NUMBER_OF_CAPTURES(matchInfo) + REGEXP_FIRST_CAPTURE;
- for (var i = REGEXP_FIRST_CAPTURE + 2; i < matchinfo_len; ) {
- var start = matchInfo[i++];
- var end = matchInfo[i++];
- if (end != -1) {
- result.push(%_SubString(subject, start, end));
- } else {
- result.push(void 0);
- }
- if (result.length === limit) break outer_loop;
- }
-
- startIndex = currentIndex = endIndex;
- }
- return result;
-}
-
-
-// ECMA-262 section 15.5.4.15
-function StringSubstring(start, end) {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.subString"]);
- }
- var s = TO_STRING_INLINE(this);
- var s_len = s.length;
-
- var start_i = TO_INTEGER(start);
- if (start_i < 0) {
- start_i = 0;
- } else if (start_i > s_len) {
- start_i = s_len;
- }
-
- var end_i = s_len;
- if (!IS_UNDEFINED(end)) {
- end_i = TO_INTEGER(end);
- if (end_i > s_len) {
- end_i = s_len;
- } else {
- if (end_i < 0) end_i = 0;
- if (start_i > end_i) {
- var tmp = end_i;
- end_i = start_i;
- start_i = tmp;
- }
- }
- }
-
- return %_SubString(s, start_i, end_i);
-}
-
-
-// This is not a part of ECMA-262.
-function StringSubstr(start, n) {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.substr"]);
- }
- var s = TO_STRING_INLINE(this);
- var len;
-
- // Correct n: If not given, set to string length; if explicitly
- // set to undefined, zero, or negative, returns empty string.
- if (n === void 0) {
- len = s.length;
- } else {
- len = TO_INTEGER(n);
- if (len <= 0) return '';
- }
-
- // Correct start: If not given (or undefined), set to zero; otherwise
- // convert to integer and handle negative case.
- if (start === void 0) {
- start = 0;
- } else {
- start = TO_INTEGER(start);
- // If positive, and greater than or equal to the string length,
- // return empty string.
- if (start >= s.length) return '';
- // If negative and absolute value is larger than the string length,
- // use zero.
- if (start < 0) {
- start += s.length;
- if (start < 0) start = 0;
- }
- }
-
- var end = start + len;
- if (end > s.length) end = s.length;
-
- return %_SubString(s, start, end);
-}
-
-
-// ECMA-262, 15.5.4.16
-function StringToLowerCase() {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.toLowerCase"]);
- }
- return %StringToLowerCase(TO_STRING_INLINE(this));
-}
-
-
-// ECMA-262, 15.5.4.17
-function StringToLocaleLowerCase() {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.toLocaleLowerCase"]);
- }
- return %StringToLowerCase(TO_STRING_INLINE(this));
-}
-
-
-// ECMA-262, 15.5.4.18
-function StringToUpperCase() {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.toUpperCase"]);
- }
- return %StringToUpperCase(TO_STRING_INLINE(this));
-}
-
-
-// ECMA-262, 15.5.4.19
-function StringToLocaleUpperCase() {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.toLocaleUpperCase"]);
- }
- return %StringToUpperCase(TO_STRING_INLINE(this));
-}
-
-// ES5, 15.5.4.20
-function StringTrim() {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.trim"]);
- }
- return %StringTrim(TO_STRING_INLINE(this), true, true);
-}
-
-function StringTrimLeft() {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.trimLeft"]);
- }
- return %StringTrim(TO_STRING_INLINE(this), true, false);
-}
-
-function StringTrimRight() {
- if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
- throw MakeTypeError("called_on_null_or_undefined",
- ["String.prototype.trimRight"]);
- }
- return %StringTrim(TO_STRING_INLINE(this), false, true);
-}
-
-
-// ECMA-262, section 15.5.3.2
-function StringFromCharCode(code) {
- var n = %_ArgumentsLength();
- if (n == 1) {
- if (!%_IsSmi(code)) code = ToNumber(code);
- return %_StringCharFromCode(code & 0xffff);
- }
-
- var one_byte = %NewString(n, NEW_ONE_BYTE_STRING);
- var i;
- for (i = 0; i < n; i++) {
- var code = %_Arguments(i);
- if (!%_IsSmi(code)) code = ToNumber(code) & 0xffff;
- if (code < 0) code = code & 0xffff;
- if (code > 0xff) break;
- %_OneByteSeqStringSetChar(one_byte, i, code);
- }
- if (i == n) return one_byte;
- one_byte = %TruncateString(one_byte, i);
-
- var two_byte = %NewString(n - i, NEW_TWO_BYTE_STRING);
- for (var j = 0; i < n; i++, j++) {
- var code = %_Arguments(i);
- if (!%_IsSmi(code)) code = ToNumber(code) & 0xffff;
- %_TwoByteSeqStringSetChar(two_byte, j, code);
- }
- return one_byte + two_byte;
-}
-
-
-// Helper function for very basic XSS protection.
-function HtmlEscape(str) {
- return TO_STRING_INLINE(str).replace(/</g, "&lt;")
- .replace(/>/g, "&gt;")
- .replace(/"/g, "&quot;")
- .replace(/'/g, "&#039;");
-}
-
-
-// Compatibility support for KJS.
-// Tested by mozilla/js/tests/js1_5/Regress/regress-276103.js.
-function StringLink(s) {
- return "<a href=\"" + HtmlEscape(s) + "\">" + this + "</a>";
-}
-
-
-function StringAnchor(name) {
- return "<a name=\"" + HtmlEscape(name) + "\">" + this + "</a>";
-}
-
-
-function StringFontcolor(color) {
- return "<font color=\"" + HtmlEscape(color) + "\">" + this + "</font>";
-}
-
-
-function StringFontsize(size) {
- return "<font size=\"" + HtmlEscape(size) + "\">" + this + "</font>";
-}
-
-
-function StringBig() {
- return "<big>" + this + "</big>";
-}
-
-
-function StringBlink() {
- return "<blink>" + this + "</blink>";
-}
-
-
-function StringBold() {
- return "<b>" + this + "</b>";
-}
-
-
-function StringFixed() {
- return "<tt>" + this + "</tt>";
-}
-
-
-function StringItalics() {
- return "<i>" + this + "</i>";
-}
-
-
-function StringSmall() {
- return "<small>" + this + "</small>";
-}
-
-
-function StringStrike() {
- return "<strike>" + this + "</strike>";
-}
-
-
-function StringSub() {
- return "<sub>" + this + "</sub>";
-}
-
-
-function StringSup() {
- return "<sup>" + this + "</sup>";
-}
-
-
-// ReplaceResultBuilder support.
-function ReplaceResultBuilder(str) {
- if (%_ArgumentsLength() > 1) {
- this.elements = %_Arguments(1);
- } else {
- this.elements = new InternalArray();
- }
- this.special_string = str;
-}
-
-SetUpLockedPrototype(ReplaceResultBuilder,
- $Array("elements", "special_string"), $Array(
- "add", function(str) {
- str = TO_STRING_INLINE(str);
- if (str.length > 0) this.elements.push(str);
- },
- "addSpecialSlice", function(start, end) {
- var len = end - start;
- if (start < 0 || len <= 0) return;
- if (start < 0x80000 && len < 0x800) {
- this.elements.push((start << 11) | len);
- } else {
- // 0 < len <= String::kMaxLength and Smi::kMaxValue >= String::kMaxLength,
- // so -len is a smi.
- var elements = this.elements;
- elements.push(-len);
- elements.push(start);
- }
- },
- "generate", function() {
- var elements = this.elements;
- return %StringBuilderConcat(elements, elements.length, this.special_string);
- }
-));
-
-
-// -------------------------------------------------------------------
-
-function SetUpString() {
- %CheckIsBootstrapping();
- // Set up the constructor property on the String prototype object.
- %SetProperty($String.prototype, "constructor", $String, DONT_ENUM);
-
-
- // Set up the non-enumerable functions on the String object.
- InstallFunctions($String, DONT_ENUM, $Array(
- "fromCharCode", StringFromCharCode
- ));
-
-
- // Set up 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,
- "trim", StringTrim,
- "trimLeft", StringTrimLeft,
- "trimRight", StringTrimRight,
- "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();