13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This file relies on the fact that the following declaration has been made
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// in runtime.js:
313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// var $String = global.String;
323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// var $NaN = 0/0;
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Set the String function and constructor.
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block%SetCode($String, function(x) {
37402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  var value = %_ArgumentsLength() == 0 ? '' : TO_STRING_INLINE(x);
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (%_IsConstructCall()) {
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    %_SetValueOf(this, value);
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return value;
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block});
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block%FunctionSetPrototype($String, new $String());
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ECMA-262 section 15.5.4.2
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringToString() {
493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!IS_STRING(this) && !IS_STRING_WRAPPER(this)) {
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    throw new $TypeError('String.prototype.toString is not generic');
513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return %_ValueOf(this);
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ECMA-262 section 15.5.4.3
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringValueOf() {
583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!IS_STRING(this) && !IS_STRING_WRAPPER(this)) {
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    throw new $TypeError('String.prototype.valueOf is not generic');
603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return %_ValueOf(this);
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ECMA-262, section 15.5.4.4
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringCharAt(pos) {
67257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
68257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
69257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["String.prototype.charAt"]);
70257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  var result = %_StringCharAt(this, pos);
727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (%_IsSmi(result)) {
737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    result = %_StringCharAt(TO_STRING_INLINE(this), TO_INTEGER(pos));
747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  return result;
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ECMA-262 section 15.5.4.5
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringCharCodeAt(pos) {
81257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
82257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
83257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["String.prototype.charCodeAt"]);
84257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  var result = %_StringCharCodeAt(this, pos);
867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (!%_IsSmi(result)) {
877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    result = %_StringCharCodeAt(TO_STRING_INLINE(this), TO_INTEGER(pos));
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  return result;
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ECMA-262, section 15.5.4.6
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringConcat() {
95257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    throw MakeTypeError("called_on_null_or_undefined",
973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        ["String.prototype.concat"]);
98257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
99402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  var len = %_ArgumentsLength();
100402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  var this_as_string = TO_STRING_INLINE(this);
101402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (len === 1) {
102402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    return this_as_string + %_Arguments(0);
103e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  var parts = new InternalArray(len + 1);
105402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  parts[0] = this_as_string;
106402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  for (var i = 0; i < len; i++) {
107402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    var part = %_Arguments(i);
108402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    parts[i + 1] = TO_STRING_INLINE(part);
109402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
110402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  return %StringBuilderConcat(parts, len + 1, "");
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Match ES3 and Safari
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block%FunctionSetLength(StringConcat, 1);
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ECMA-262 section 15.5.4.7
118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochfunction StringIndexOf(pattern /* position */) {  // length == 1
119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["String.prototype.indexOf"]);
122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  var subject = TO_STRING_INLINE(this);
1241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  pattern = TO_STRING_INLINE(pattern);
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var index = 0;
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (%_ArgumentsLength() > 1) {
1271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    index = %_Arguments(1);  // position
1281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    index = TO_INTEGER(index);
1291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (index < 0) index = 0;
1301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (index > subject.length) index = subject.length;
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return %StringIndexOf(subject, pattern, index);
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ECMA-262 section 15.5.4.8
137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochfunction StringLastIndexOf(pat /* position */) {  // length == 1
138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["String.prototype.lastIndexOf"]);
141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
142402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  var sub = TO_STRING_INLINE(this);
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var subLength = sub.length;
144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  var pat = TO_STRING_INLINE(pat);
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var patLength = pat.length;
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var index = subLength - patLength;
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (%_ArgumentsLength() > 1) {
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var position = ToNumber(%_Arguments(1));
1499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    if (!NUMBER_IS_NAN(position)) {
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      position = TO_INTEGER(position);
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (position < 0) {
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        position = 0;
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (position + patLength < subLength) {
15569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        index = position;
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (index < 0) {
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return -1;
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return %StringLastIndexOf(sub, pat, index);
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ECMA-262 section 15.5.4.9
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This function is implementation specific.  For now, we do not
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// do anything locale specific.
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringLocaleCompare(other) {
171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["String.prototype.localeCompare"]);
174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (%_ArgumentsLength() === 0) return 0;
17669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  return %StringLocaleCompare(TO_STRING_INLINE(this),
177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                              TO_STRING_INLINE(other));
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ECMA-262 section 15.5.4.10
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringMatch(regexp) {
183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["String.prototype.match"]);
186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
187402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  var subject = TO_STRING_INLINE(this);
1886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (IS_REGEXP(regexp)) {
189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (!regexp.global) return RegExpExecNoTests(regexp, subject, 0);
1906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    %_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]);
1916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // lastMatchInfo is defined in regexp.js.
1923e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    return %StringMatch(subject, regexp, lastMatchInfo);
1936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Non-regexp argument.
1956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  regexp = new $RegExp(regexp);
1966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return RegExpExecNoTests(regexp, subject, 0);
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SubString is an internal function that returns the sub string of 'string'.
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// If resulting string is of length 1, we use the one character cache
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// otherwise we call the runtime system.
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction SubString(string, start, end) {
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use the one character string cache.
205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (start + 1 == end) return %_StringCharAt(string, start);
206e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return %_SubString(string, start, end);
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This has the same size as the lastMatchInfo array, and can be used for
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// functions that expect that structure to be returned.  It is used when the
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// needle is a string rather than a regexp.  In this case we can't update
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// lastMatchArray without erroneously affecting the properties on the global
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// RegExp object.
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvar reusableMatchInfo = [2, "", "", -1, -1];
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ECMA-262, section 15.5.4.11
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringReplace(search, replace) {
220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["String.prototype.replace"]);
223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
224402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  var subject = TO_STRING_INLINE(this);
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Delegate to one of the regular expression variants if necessary.
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (IS_REGEXP(search)) {
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    %_Log('regexp', 'regexp-replace,%0r,%1S', [search, subject]);
229589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (IS_SPEC_FUNCTION(replace)) {
23025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      if (search.global) {
23125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        return StringReplaceGlobalRegExpWithFunction(subject, search, replace);
23225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      } else {
23325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        return StringReplaceNonGlobalRegExpWithFunction(subject,
23425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                                                        search,
23525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                                                        replace);
23625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      }
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return %StringReplaceRegExpWithString(subject,
239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            search,
240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            TO_STRING_INLINE(replace),
241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                            lastMatchInfo);
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Convert the search argument to a string and search for it.
246402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  search = TO_STRING_INLINE(search);
2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (search.length == 1 &&
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      subject.length > 0xFF &&
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      IS_STRING(replace) &&
2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      %StringIndexOf(replace, '$', 0) < 0) {
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Searching by traversing a cons string tree and replace with cons of
2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // slices works only when the replaced string is a single character, being
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // replaced by a simple string and only pays off for long strings.
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return %StringReplaceOneCharWithString(subject, search, replace);
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var start = %StringIndexOf(subject, search, 0);
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (start < 0) return subject;
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var end = start + search.length;
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var builder = new ReplaceResultBuilder(subject);
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // prefix
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  builder.addSpecialSlice(0, start);
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute the string to replace with.
265589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (IS_SPEC_FUNCTION(replace)) {
26669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    var receiver = %GetDefaultReceiver(replace);
2673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    builder.add(%_CallFunction(receiver,
268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               search,
269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               start,
270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               subject,
271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                               replace));
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    reusableMatchInfo[CAPTURE0] = start;
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    reusableMatchInfo[CAPTURE1] = end;
275402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    replace = TO_STRING_INLINE(replace);
276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ExpandReplacement(replace, subject, reusableMatchInfo, builder);
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // suffix
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  builder.addSpecialSlice(end, subject.length);
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return builder.generate();
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Expand the $-expressions in the string and return a new string with
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the result.
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ExpandReplacement(string, subject, matchInfo, builder) {
289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  var length = string.length;
290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  var builder_elements = builder.elements;
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var next = %StringIndexOf(string, '$', 0);
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (next < 0) {
293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (length > 0) builder_elements.push(string);
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute the number of captures; see ECMA-262, 15.5.4.11, p. 102.
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var m = NUMBER_OF_CAPTURES(matchInfo) >> 1;  // Includes the match.
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (next > 0) builder_elements.push(SubString(string, 0, next));
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (true) {
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var expansion = '$';
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var position = next + 1;
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (position < length) {
3067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      var peek = %_StringCharCodeAt(string, position);
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (peek == 36) {         // $$
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ++position;
309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        builder_elements.push('$');
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (peek == 38) {  // $& - match
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ++position;
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.addSpecialSlice(matchInfo[CAPTURE0],
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                matchInfo[CAPTURE1]);
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (peek == 96) {  // $` - prefix
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ++position;
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.addSpecialSlice(0, matchInfo[CAPTURE0]);
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (peek == 39) {  // $' - suffix
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ++position;
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.addSpecialSlice(matchInfo[CAPTURE1], subject.length);
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (peek >= 48 && peek <= 57) {  // $n, 0 <= n <= 9
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ++position;
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        var n = peek - 48;
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (position < length) {
3247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          peek = %_StringCharCodeAt(string, position);
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // $nn, 01 <= nn <= 99
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (n != 0 && peek == 48 || peek >= 49 && peek <= 57) {
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            var nn = n * 10 + (peek - 48);
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            if (nn < m) {
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              // If the two digit capture reference is within range of
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              // the captures, we use it instead of the single digit
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              // one. Otherwise, we fall back to using the single
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              // digit reference. This matches the behavior of
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              // SpiderMonkey.
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              ++position;
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              n = nn;
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            }
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (0 < n && n < m) {
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          addCaptureString(builder, matchInfo, n);
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // Because of the captures range check in the parsing of two
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // digit capture references, we can only enter here when a
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // single digit capture reference is outside the range of
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // captures.
346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          builder_elements.push('$');
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          --position;
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        builder_elements.push('$');
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      builder_elements.push('$');
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Go the the next $ in the string.
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    next = %StringIndexOf(string, '$', position);
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Return if there are no more $ characters in the string. If we
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // haven't reached the end, we need to append the suffix.
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (next < 0) {
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (position < length) {
363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        builder_elements.push(SubString(string, position, length));
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Append substring between the previous and the next $ character.
369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (next > position) {
370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      builder_elements.push(SubString(string, position, next));
371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Compute the string of a given regular expression capture.
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction CaptureString(string, lastCaptureInfo, index) {
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Scale the index.
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var scaled = index << 1;
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute start and end.
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var start = lastCaptureInfo[CAPTURE(scaled)];
38225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // If start isn't valid, return undefined.
38325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  if (start < 0) return;
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var end = lastCaptureInfo[CAPTURE(scaled + 1)];
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return SubString(string, start, end);
3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Add the string of a given regular expression capture to the
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ReplaceResultBuilder
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction addCaptureString(builder, matchInfo, index) {
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Scale the index.
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var scaled = index << 1;
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute start and end.
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var start = matchInfo[CAPTURE(scaled)];
39625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  if (start < 0) return;
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var end = matchInfo[CAPTURE(scaled + 1)];
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  builder.addSpecialSlice(start, end);
3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// TODO(lrn): This array will survive indefinitely if replace is never
4026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// called again. However, it will be empty, since the contents are cleared
4036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// in the finally block.
404e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvar reusableReplaceArray = new InternalArray(16);
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper function for replacing regular expressions with the result of a
4076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// function application in String.prototype.replace.
40825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsenfunction StringReplaceGlobalRegExpWithFunction(subject, regexp, replace) {
40925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  var resultArray = reusableReplaceArray;
41025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  if (resultArray) {
41125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    reusableReplaceArray = null;
41225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  } else {
41325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    // Inside a nested replace (replace called from the replacement function
41425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    // of another replace) or we have failed to set the reusable array
41525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    // back due to an exception in a replacement function. Create a new
41625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    // array to use in the future, or until the original is written back.
417e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    resultArray = new InternalArray(16);
41825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  }
41925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  var res = %RegExpExecMultiple(regexp,
42025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                                subject,
42125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                                lastMatchInfo,
42225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen                                resultArray);
42325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  regexp.lastIndex = 0;
42425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  if (IS_NULL(res)) {
42525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    // No matches at all.
42625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    reusableReplaceArray = resultArray;
42725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    return subject;
42825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  }
42925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  var len = res.length;
43025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  var i = 0;
43125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  if (NUMBER_OF_CAPTURES(lastMatchInfo) == 2) {
43225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    var match_start = 0;
433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    var override = new InternalArray(null, 0, subject);
43469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    var receiver = %GetDefaultReceiver(replace);
43525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    while (i < len) {
43625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      var elem = res[i];
43725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      if (%_IsSmi(elem)) {
43825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        if (elem > 0) {
43925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          match_start = (elem >> 11) + (elem & 0x7ff);
4406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        } else {
44125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen          match_start = res[++i] - elem;
44225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        }
44325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      } else {
44425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        override[0] = elem;
44525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        override[1] = match_start;
44625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        lastMatchInfoOverride = override;
44725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        var func_result =
44825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen            %_CallFunction(receiver, elem, match_start, subject, replace);
4491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        res[i] = TO_STRING_INLINE(func_result);
45025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        match_start += elem.length;
451d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      }
45225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      i++;
45325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    }
45425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  } else {
455589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    var receiver = %GetDefaultReceiver(replace);
45625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    while (i < len) {
45725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      var elem = res[i];
45825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      if (!%_IsSmi(elem)) {
45925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        // elem must be an Array.
46025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        // Use the apply argument as backing for global RegExp properties.
46125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen        lastMatchInfoOverride = elem;
462589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        var func_result = %Apply(replace, receiver, elem, 0, elem.length);
4631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        res[i] = TO_STRING_INLINE(func_result);
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
46525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      i++;
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
46825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  var resultBuilder = new ReplaceResultBuilder(subject, res);
46925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  var result = resultBuilder.generate();
47025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  resultArray.length = 0;
47125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  reusableReplaceArray = resultArray;
47225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return result;
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsenfunction StringReplaceNonGlobalRegExpWithFunction(subject, regexp, replace) {
47725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  var matchInfo = DoRegExpExec(regexp, subject, 0);
47825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  if (IS_NULL(matchInfo)) return subject;
47925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  var result = new ReplaceResultBuilder(subject);
48025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  var index = matchInfo[CAPTURE0];
48125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  result.addSpecialSlice(0, index);
48225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  var endOfMatch = matchInfo[CAPTURE1];
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute the parameter list consisting of the match, captures, index,
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // and subject for the replace function invocation.
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The number of captures plus one for the match.
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var m = NUMBER_OF_CAPTURES(matchInfo) >> 1;
48725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  var replacement;
488589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  var receiver = %GetDefaultReceiver(replace);
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (m == 1) {
49025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    // No captures, only the match, which is always valid.
49125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    var s = SubString(subject, index, endOfMatch);
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Don't call directly to avoid exposing the built-in global object.
49325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    replacement =
4943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        %_CallFunction(receiver, s, index, subject, replace);
49525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  } else {
496e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    var parameters = new InternalArray(m + 2);
49725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    for (var j = 0; j < m; j++) {
49825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      parameters[j] = CaptureString(subject, matchInfo, j);
49925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    }
50025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    parameters[j] = index;
50125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    parameters[j + 1] = subject;
50225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
503589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    replacement = %Apply(replace, receiver, parameters, 0, j + 2);
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
50525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
50625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  result.add(replacement);  // The add method converts to string if necessary.
50725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // Can't use matchInfo any more from here, since the function could
50825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // overwrite it.
50925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  result.addSpecialSlice(endOfMatch, subject.length);
51025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  return result.generate();
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
51325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ECMA-262 section 15.5.4.12
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringSearch(re) {
516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["String.prototype.search"]);
519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
5206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  var regexp;
5216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (IS_STRING(re)) {
5226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    regexp = %_GetFromCache(STRING_TO_REGEXP_CACHE_ID, re);
5236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else if (IS_REGEXP(re)) {
5246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    regexp = re;
5256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
5266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    regexp = new $RegExp(re);
5276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  var match = DoRegExpExec(regexp, TO_STRING_INLINE(this), 0);
5296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (match) {
5306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return match[CAPTURE0];
5316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
5326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return -1;
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ECMA-262 section 15.5.4.13
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringSlice(start, end) {
538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["String.prototype.slice"]);
541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
542402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  var s = TO_STRING_INLINE(this);
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var s_len = s.length;
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var start_i = TO_INTEGER(start);
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var end_i = s_len;
5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (end !== void 0) {
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    end_i = TO_INTEGER(end);
5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (start_i < 0) {
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    start_i += s_len;
5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (start_i < 0) {
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      start_i = 0;
5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (start_i > s_len) {
5573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return '';
5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (end_i < 0) {
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    end_i += s_len;
5633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (end_i < 0) {
5643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return '';
5653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
5673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (end_i > s_len) {
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      end_i = s_len;
5693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (end_i <= start_i) {
5733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return '';
5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return SubString(s, start_i, end_i);
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ECMA-262 section 15.5.4.14
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringSplit(separator, limit) {
582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["String.prototype.split"]);
585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
586402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  var subject = TO_STRING_INLINE(this);
587e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  limit = (IS_UNDEFINED(limit)) ? 0xffffffff : TO_UINT32(limit);
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ECMA-262 says that if separator is undefined, the result should
5903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // be an array of size 1 containing the entire string.
5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (IS_UNDEFINED(separator)) {
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return [subject];
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var length = subject.length;
596402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  if (!IS_REGEXP(separator)) {
597402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    separator = TO_STRING_INLINE(separator);
5983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (limit === 0) return [];
6003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
601402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    var separator_length = separator.length;
602402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If the separator string is empty then return the elements in the subject.
6048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    if (separator_length === 0) return %StringToArray(subject, limit);
605402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
6066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    var result = %StringSplit(subject, separator, limit);
607402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
608402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    return result;
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (limit === 0) return [];
6123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Separator is a regular expression.
6143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return StringSplitOnRegExp(subject, separator, limit, length);
6153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
6163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochfunction StringSplitOnRegExp(subject, separator, limit, length) {
619402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  %_Log('regexp', 'regexp-split,%0S,%1r', [subject, separator]);
620402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (length === 0) {
6223e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    if (DoRegExpExec(separator, subject, 0, 0) != null) {
6236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return [];
6246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return [subject];
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var currentIndex = 0;
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var startIndex = 0;
630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  var startMatch = 0;
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var result = [];
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  outer_loop:
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (true) {
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (startIndex === length) {
637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      result.push(SubString(subject, currentIndex, length));
6386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      break;
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    var matchInfo = DoRegExpExec(separator, subject, startIndex);
642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (matchInfo == null || length === (startMatch = matchInfo[CAPTURE0])) {
643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      result.push(SubString(subject, currentIndex, length));
6446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      break;
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var endIndex = matchInfo[CAPTURE1];
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // We ignore a zero-length match at the currentIndex.
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (startIndex === endIndex && endIndex === currentIndex) {
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      startIndex++;
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      continue;
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (currentIndex + 1 == startMatch) {
655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      result.push(%_StringCharAt(subject, currentIndex));
656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      result.push(%_SubString(subject, currentIndex, startMatch));
658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (result.length === limit) break;
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    var matchinfo_len = NUMBER_OF_CAPTURES(matchInfo) + REGEXP_FIRST_CAPTURE;
663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (var i = REGEXP_FIRST_CAPTURE + 2; i < matchinfo_len; ) {
664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      var start = matchInfo[i++];
665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      var end = matchInfo[i++];
666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (end != -1) {
667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (start + 1 == end) {
668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          result.push(%_StringCharAt(subject, start));
669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        } else {
670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          result.push(%_SubString(subject, start, end));
671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        result.push(void 0);
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
6756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (result.length === limit) break outer_loop;
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    startIndex = currentIndex = endIndex;
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
6806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return result;
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ECMA-262 section 15.5.4.15
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringSubstring(start, end) {
686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["String.prototype.subString"]);
689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
690402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  var s = TO_STRING_INLINE(this);
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var s_len = s.length;
692e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var start_i = TO_INTEGER(start);
694e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (start_i < 0) {
695e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    start_i = 0;
696e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  } else if (start_i > s_len) {
697e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    start_i = s_len;
698e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
699e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var end_i = s_len;
701e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (!IS_UNDEFINED(end)) {
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    end_i = TO_INTEGER(end);
703e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    if (end_i > s_len) {
704e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      end_i = s_len;
705e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    } else {
706e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (end_i < 0) end_i = 0;
707e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      if (start_i > end_i) {
708e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        var tmp = end_i;
709e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        end_i = start_i;
710e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke        start_i = tmp;
711e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      }
712e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return ((start_i + 1 == end_i)
716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          ? %_StringCharAt(s, start_i)
717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          : %_SubString(s, start_i, end_i));
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This is not a part of ECMA-262.
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringSubstr(start, n) {
723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["String.prototype.substr"]);
726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
727402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  var s = TO_STRING_INLINE(this);
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var len;
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Correct n: If not given, set to string length; if explicitly
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // set to undefined, zero, or negative, returns empty string.
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (n === void 0) {
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    len = s.length;
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    len = TO_INTEGER(n);
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (len <= 0) return '';
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Correct start: If not given (or undefined), set to zero; otherwise
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // convert to integer and handle negative case.
741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (start === void 0) {
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    start = 0;
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    start = TO_INTEGER(start);
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If positive, and greater than or equal to the string length,
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // return empty string.
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (start >= s.length) return '';
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If negative and absolute value is larger than the string length,
749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // use zero.
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (start < 0) {
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      start += s.length;
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (start < 0) start = 0;
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var end = start + len;
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (end > s.length) end = s.length;
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return ((start + 1 == end)
760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          ? %_StringCharAt(s, start)
761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          : %_SubString(s, start, end));
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ECMA-262, 15.5.4.16
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringToLowerCase() {
767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["String.prototype.toLowerCase"]);
770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
771402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  return %StringToLowerCase(TO_STRING_INLINE(this));
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ECMA-262, 15.5.4.17
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringToLocaleLowerCase() {
777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["String.prototype.toLocaleLowerCase"]);
780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
781402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  return %StringToLowerCase(TO_STRING_INLINE(this));
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ECMA-262, 15.5.4.18
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringToUpperCase() {
787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["String.prototype.toUpperCase"]);
790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
791402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  return %StringToUpperCase(TO_STRING_INLINE(this));
792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ECMA-262, 15.5.4.19
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringToLocaleUpperCase() {
797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["String.prototype.toLocaleUpperCase"]);
800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
801402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  return %StringToUpperCase(TO_STRING_INLINE(this));
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// ES5, 15.5.4.20
8053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockfunction StringTrim() {
806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["String.prototype.trim"]);
809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
810402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  return %StringTrim(TO_STRING_INLINE(this), true, true);
8113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
8123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockfunction StringTrimLeft() {
814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["String.prototype.trimLeft"]);
817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
818402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  return %StringTrim(TO_STRING_INLINE(this), true, false);
8193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
8203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
8213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockfunction StringTrimRight() {
822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    throw MakeTypeError("called_on_null_or_undefined",
824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                        ["String.prototype.trimRight"]);
825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
826402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  return %StringTrim(TO_STRING_INLINE(this), false, true);
8273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
829e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvar static_charcode_array = new InternalArray(4);
8306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ECMA-262, section 15.5.3.2
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringFromCharCode(code) {
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  var n = %_ArgumentsLength();
8346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (n == 1) {
8356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (!%_IsSmi(code)) code = ToNumber(code);
8367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    return %_StringCharFromCode(code & 0xffff);
8376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // NOTE: This is not super-efficient, but it is necessary because we
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // want to avoid converting to numbers from within the virtual
841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // machine. Maybe we can find another way of doing this?
8426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  var codes = static_charcode_array;
8436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (var i = 0; i < n; i++) {
8446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    var code = %_Arguments(i);
8456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (!%_IsSmi(code)) code = ToNumber(code);
8466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    codes[i] = code;
8476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
8486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  codes.length = n;
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return %StringFromCharCodeArray(codes);
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper function for very basic XSS protection.
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction HtmlEscape(str) {
855402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  return TO_STRING_INLINE(str).replace(/</g, "&lt;")
856402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                              .replace(/>/g, "&gt;")
857402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                              .replace(/"/g, "&quot;")
858402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                              .replace(/'/g, "&#039;");
8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Compatibility support for KJS.
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Tested by mozilla/js/tests/js1_5/Regress/regress-276103.js.
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringLink(s) {
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "<a href=\"" + HtmlEscape(s) + "\">" + this + "</a>";
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringAnchor(name) {
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "<a name=\"" + HtmlEscape(name) + "\">" + this + "</a>";
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringFontcolor(color) {
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "<font color=\"" + HtmlEscape(color) + "\">" + this + "</font>";
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringFontsize(size) {
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "<font size=\"" + HtmlEscape(size) + "\">" + this + "</font>";
881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringBig() {
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "<big>" + this + "</big>";
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringBlink() {
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "<blink>" + this + "</blink>";
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringBold() {
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "<b>" + this + "</b>";
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringFixed() {
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "<tt>" + this + "</tt>";
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringItalics() {
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "<i>" + this + "</i>";
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringSmall() {
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "<small>" + this + "</small>";
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringStrike() {
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "<strike>" + this + "</strike>";
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringSub() {
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "<sub>" + this + "</sub>";
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction StringSup() {
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return "<sup>" + this + "</sup>";
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
929e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ReplaceResultBuilder support.
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction ReplaceResultBuilder(str) {
9316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (%_ArgumentsLength() > 1) {
9326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    this.elements = %_Arguments(1);
9336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
934e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    this.elements = new InternalArray();
9356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  this.special_string = str;
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
939589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochSetUpLockedPrototype(ReplaceResultBuilder,
940589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  $Array("elements", "special_string"), $Array(
941589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  "add", function(str) {
942589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    str = TO_STRING_INLINE(str);
943589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (str.length > 0) this.elements.push(str);
944589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  },
945589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  "addSpecialSlice", function(start, end) {
946589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    var len = end - start;
947589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (start < 0 || len <= 0) return;
948589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    if (start < 0x80000 && len < 0x800) {
949589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      this.elements.push((start << 11) | len);
950589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    } else {
951589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // 0 < len <= String::kMaxLength and Smi::kMaxValue >= String::kMaxLength,
952589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // so -len is a smi.
953589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      var elements = this.elements;
954589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      elements.push(-len);
955589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      elements.push(start);
956589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
957589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  },
958589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  "generate", function() {
959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    var elements = this.elements;
960589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return %StringBuilderConcat(elements, elements.length, this.special_string);
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
962589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch));
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
967589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochfunction SetUpString() {
968589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  %CheckIsBootstrapping();
969589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Set up the constructor property on the String prototype object.
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  %SetProperty($String.prototype, "constructor", $String, DONT_ENUM);
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
973589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Set up the non-enumerable functions on the String object.
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InstallFunctions($String, DONT_ENUM, $Array(
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "fromCharCode", StringFromCharCode
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ));
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
979589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Set up the non-enumerable functions on the String prototype object.
9803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InstallFunctions($String.prototype, DONT_ENUM, $Array(
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "valueOf", StringValueOf,
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "toString", StringToString,
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "charAt", StringCharAt,
984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "charCodeAt", StringCharCodeAt,
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "concat", StringConcat,
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "indexOf", StringIndexOf,
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "lastIndexOf", StringLastIndexOf,
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "localeCompare", StringLocaleCompare,
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "match", StringMatch,
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "replace", StringReplace,
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "search", StringSearch,
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "slice", StringSlice,
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "split", StringSplit,
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "substring", StringSubstring,
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "substr", StringSubstr,
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "toLowerCase", StringToLowerCase,
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "toLocaleLowerCase", StringToLocaleLowerCase,
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "toUpperCase", StringToUpperCase,
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "toLocaleUpperCase", StringToLocaleUpperCase,
10003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    "trim", StringTrim,
10013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    "trimLeft", StringTrimLeft,
10023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    "trimRight", StringTrimRight,
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "link", StringLink,
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "anchor", StringAnchor,
1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "fontcolor", StringFontcolor,
1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "fontsize", StringFontsize,
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "big", StringBig,
1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "blink", StringBlink,
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "bold", StringBold,
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "fixed", StringFixed,
1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "italics", StringItalics,
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "small", StringSmall,
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "strike", StringStrike,
1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    "sub", StringSub,
1015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    "sup", StringSup
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ));
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1019589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochSetUpString();
1020