blob: a913a7779dbea4498cc642cfa52b0568db028647 [file] [log] [blame]
mjs6f821c82002-03-22 00:31:57 +00001// -*- c-basic-offset: 2 -*-
kocienda66a6d362001-08-24 14:24:45 +00002/*
kocienda66a6d362001-08-24 14:24:45 +00003 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
darin@apple.coma313ead2008-01-27 08:54:25 +00004 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
kocienda66a6d362001-08-24 14:24:45 +00005 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
mjscdff33b2006-01-23 21:41:36 +000018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
mjs6f821c82002-03-22 00:31:57 +000019 *
kocienda66a6d362001-08-24 14:24:45 +000020 */
21
mjsb64c50a2005-10-03 21:13:12 +000022#include "config.h"
23#include "string_object.h"
24
mjs308be5a2006-08-14 03:06:14 +000025#include "JSWrapperObject.h"
mrowe@apple.come54b76f2007-12-06 04:14:59 +000026#include "PropertyNameArray.h"
darin@apple.com5c0863d2008-06-16 04:17:44 +000027#include "ArrayPrototype.h"
darin36d11362006-04-11 16:30:21 +000028#include "error_object.h"
mjs6f821c82002-03-22 00:31:57 +000029#include "operations.h"
darin@apple.com5c0863d2008-06-16 04:17:44 +000030#include "RegExpObject.h"
mrowe@apple.com1c11eae2007-10-29 03:00:16 +000031#include <wtf/MathExtras.h>
ap@webkit.orgafd03182008-03-06 17:50:08 +000032#include <wtf/unicode/Collator.h>
anderscaaa39c422006-12-20 20:11:47 +000033
darinf9e5d6c2007-01-09 14:54:26 +000034using namespace WTF;
35
36namespace KJS {
kocienda66a6d362001-08-24 14:24:45 +000037
darin@apple.com1edff432008-06-24 05:23:17 +000038static JSValue* stringProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&);
darin@apple.com1edff432008-06-24 05:23:17 +000039static JSValue* stringProtoFuncCharAt(ExecState*, JSObject*, JSValue*, const ArgList&);
40static JSValue* stringProtoFuncCharCodeAt(ExecState*, JSObject*, JSValue*, const ArgList&);
41static JSValue* stringProtoFuncConcat(ExecState*, JSObject*, JSValue*, const ArgList&);
42static JSValue* stringProtoFuncIndexOf(ExecState*, JSObject*, JSValue*, const ArgList&);
43static JSValue* stringProtoFuncLastIndexOf(ExecState*, JSObject*, JSValue*, const ArgList&);
44static JSValue* stringProtoFuncMatch(ExecState*, JSObject*, JSValue*, const ArgList&);
45static JSValue* stringProtoFuncReplace(ExecState*, JSObject*, JSValue*, const ArgList&);
46static JSValue* stringProtoFuncSearch(ExecState*, JSObject*, JSValue*, const ArgList&);
47static JSValue* stringProtoFuncSlice(ExecState*, JSObject*, JSValue*, const ArgList&);
48static JSValue* stringProtoFuncSplit(ExecState*, JSObject*, JSValue*, const ArgList&);
49static JSValue* stringProtoFuncSubstr(ExecState*, JSObject*, JSValue*, const ArgList&);
50static JSValue* stringProtoFuncSubstring(ExecState*, JSObject*, JSValue*, const ArgList&);
51static JSValue* stringProtoFuncToLowerCase(ExecState*, JSObject*, JSValue*, const ArgList&);
52static JSValue* stringProtoFuncToUpperCase(ExecState*, JSObject*, JSValue*, const ArgList&);
53static JSValue* stringProtoFuncToLocaleLowerCase(ExecState*, JSObject*, JSValue*, const ArgList&);
54static JSValue* stringProtoFuncToLocaleUpperCase(ExecState*, JSObject*, JSValue*, const ArgList&);
55static JSValue* stringProtoFuncLocaleCompare(ExecState*, JSObject*, JSValue*, const ArgList&);
56
57static JSValue* stringProtoFuncBig(ExecState*, JSObject*, JSValue*, const ArgList&);
58static JSValue* stringProtoFuncSmall(ExecState*, JSObject*, JSValue*, const ArgList&);
59static JSValue* stringProtoFuncBlink(ExecState*, JSObject*, JSValue*, const ArgList&);
60static JSValue* stringProtoFuncBold(ExecState*, JSObject*, JSValue*, const ArgList&);
61static JSValue* stringProtoFuncFixed(ExecState*, JSObject*, JSValue*, const ArgList&);
62static JSValue* stringProtoFuncItalics(ExecState*, JSObject*, JSValue*, const ArgList&);
63static JSValue* stringProtoFuncStrike(ExecState*, JSObject*, JSValue*, const ArgList&);
64static JSValue* stringProtoFuncSub(ExecState*, JSObject*, JSValue*, const ArgList&);
65static JSValue* stringProtoFuncSup(ExecState*, JSObject*, JSValue*, const ArgList&);
66static JSValue* stringProtoFuncFontcolor(ExecState*, JSObject*, JSValue*, const ArgList&);
67static JSValue* stringProtoFuncFontsize(ExecState*, JSObject*, JSValue*, const ArgList&);
68static JSValue* stringProtoFuncAnchor(ExecState*, JSObject*, JSValue*, const ArgList&);
69static JSValue* stringProtoFuncLink(ExecState*, JSObject*, JSValue*, const ArgList&);
70
71}
72
73#include "string_object.lut.h"
74
75namespace KJS {
76
darin@apple.com6de4edc2008-06-16 03:02:57 +000077// ------------------------------ StringObject ----------------------------
mjs6f821c82002-03-22 00:31:57 +000078
darin@apple.com6de4edc2008-06-16 03:02:57 +000079const ClassInfo StringObject::info = { "String", 0, 0, 0 };
mjs6f821c82002-03-22 00:31:57 +000080
ap@webkit.org960c28e2008-06-19 17:29:29 +000081StringObject::StringObject(ExecState* exec, JSObject* proto)
mjs308be5a2006-08-14 03:06:14 +000082 : JSWrapperObject(proto)
kocienda66a6d362001-08-24 14:24:45 +000083{
ap@webkit.org960c28e2008-06-19 17:29:29 +000084 setInternalValue(jsString(exec, ""));
kocienda66a6d362001-08-24 14:24:45 +000085}
86
ap@webkit.org960c28e2008-06-19 17:29:29 +000087StringObject::StringObject(JSObject* proto, JSString* string)
mjs06ed4662007-07-25 21:50:00 +000088 : JSWrapperObject(proto)
89{
90 setInternalValue(string);
91}
92
ap@webkit.org960c28e2008-06-19 17:29:29 +000093StringObject::StringObject(ExecState* exec, JSObject* proto, const UString& string)
mjs308be5a2006-08-14 03:06:14 +000094 : JSWrapperObject(proto)
darina6cae2c2002-11-19 06:53:35 +000095{
ap@webkit.org960c28e2008-06-19 17:29:29 +000096 setInternalValue(jsString(exec, string));
darina6cae2c2002-11-19 06:53:35 +000097}
98
darin@apple.com6de4edc2008-06-16 03:02:57 +000099bool StringObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
darina6cae2c2002-11-19 06:53:35 +0000100{
darin@apple.com68dbe312008-06-13 04:53:56 +0000101 if (internalValue()->getStringPropertySlot(exec, propertyName, slot))
eseidel74efded2007-10-29 07:55:34 +0000102 return true;
eseidel74efded2007-10-29 07:55:34 +0000103 return JSObject::getOwnPropertySlot(exec, propertyName, slot);
104}
105
darin@apple.com6de4edc2008-06-16 03:02:57 +0000106bool StringObject::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
eseidel74efded2007-10-29 07:55:34 +0000107{
darin@apple.com68dbe312008-06-13 04:53:56 +0000108 if (internalValue()->getStringPropertySlot(propertyName, slot))
109 return true;
ap@webkit.org07e5bce2008-06-16 23:28:38 +0000110 return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
darina6cae2c2002-11-19 06:53:35 +0000111}
112
darin@apple.com6de4edc2008-06-16 03:02:57 +0000113void StringObject::put(ExecState* exec, const Identifier& propertyName, JSValue* value)
darina6cae2c2002-11-19 06:53:35 +0000114{
darin@apple.come25e04e2008-02-24 05:01:27 +0000115 if (propertyName == exec->propertyNames().length)
116 return;
117 JSObject::put(exec, propertyName, value);
darina6cae2c2002-11-19 06:53:35 +0000118}
119
darin@apple.com6de4edc2008-06-16 03:02:57 +0000120bool StringObject::deleteProperty(ExecState *exec, const Identifier &propertyName)
darina6cae2c2002-11-19 06:53:35 +0000121{
mjs23fc88d2007-03-19 05:43:47 +0000122 if (propertyName == exec->propertyNames().length)
darina6cae2c2002-11-19 06:53:35 +0000123 return false;
darin35940e82005-12-11 02:06:17 +0000124 return JSObject::deleteProperty(exec, propertyName);
darina6cae2c2002-11-19 06:53:35 +0000125}
126
darin@apple.com6de4edc2008-06-16 03:02:57 +0000127void StringObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
ggarenc17d9842005-12-29 11:38:57 +0000128{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000129 int size = internalValue()->value().size();
ggarend49ee982006-07-12 10:01:06 +0000130 for (int i = 0; i < size; i++)
ap@webkit.org07e5bce2008-06-16 23:28:38 +0000131 propertyNames.add(Identifier(exec, UString::from(i)));
mjsb3598b82006-07-16 21:06:28 +0000132 return JSObject::getPropertyNames(exec, propertyNames);
ggarenc17d9842005-12-29 11:38:57 +0000133}
134
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000135UString StringObject::toString(ExecState*) const
136{
137 return internalValue()->value();
138}
139
140UString StringObject::toThisString(ExecState*) const
141{
142 return internalValue()->value();
143}
144
145JSString* StringObject::toThisJSString(ExecState*)
146{
147 return internalValue();
148}
149
darin35940e82005-12-11 02:06:17 +0000150// ------------------------------ StringPrototype ---------------------------
darin@apple.com6de4edc2008-06-16 03:02:57 +0000151const ClassInfo StringPrototype::info = { "String", &StringObject::info, 0, ExecState::stringTable };
mjs6f821c82002-03-22 00:31:57 +0000152/* Source for string_object.lut.h
153@begin stringTable 26
darin@apple.com1edff432008-06-24 05:23:17 +0000154 toString stringProtoFuncToString DontEnum|Function 0
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000155 valueOf stringProtoFuncToString DontEnum|Function 0
darin@apple.com1edff432008-06-24 05:23:17 +0000156 charAt stringProtoFuncCharAt DontEnum|Function 1
157 charCodeAt stringProtoFuncCharCodeAt DontEnum|Function 1
158 concat stringProtoFuncConcat DontEnum|Function 1
159 indexOf stringProtoFuncIndexOf DontEnum|Function 1
160 lastIndexOf stringProtoFuncLastIndexOf DontEnum|Function 1
161 match stringProtoFuncMatch DontEnum|Function 1
162 replace stringProtoFuncReplace DontEnum|Function 2
163 search stringProtoFuncSearch DontEnum|Function 1
164 slice stringProtoFuncSlice DontEnum|Function 2
165 split stringProtoFuncSplit DontEnum|Function 2
166 substr stringProtoFuncSubstr DontEnum|Function 2
167 substring stringProtoFuncSubstring DontEnum|Function 2
168 toLowerCase stringProtoFuncToLowerCase DontEnum|Function 0
169 toUpperCase stringProtoFuncToUpperCase DontEnum|Function 0
170 toLocaleLowerCase stringProtoFuncToLocaleLowerCase DontEnum|Function 0
171 toLocaleUpperCase stringProtoFuncToLocaleUpperCase DontEnum|Function 0
172 localeCompare stringProtoFuncLocaleCompare DontEnum|Function 1
weinig@apple.com31afc952008-01-16 21:50:19 +0000173
darin@apple.com1edff432008-06-24 05:23:17 +0000174 big stringProtoFuncBig DontEnum|Function 0
175 small stringProtoFuncSmall DontEnum|Function 0
176 blink stringProtoFuncBlink DontEnum|Function 0
177 bold stringProtoFuncBold DontEnum|Function 0
178 fixed stringProtoFuncFixed DontEnum|Function 0
179 italics stringProtoFuncItalics DontEnum|Function 0
180 strike stringProtoFuncStrike DontEnum|Function 0
181 sub stringProtoFuncSub DontEnum|Function 0
182 sup stringProtoFuncSup DontEnum|Function 0
183 fontcolor stringProtoFuncFontcolor DontEnum|Function 1
184 fontsize stringProtoFuncFontsize DontEnum|Function 1
185 anchor stringProtoFuncAnchor DontEnum|Function 1
186 link stringProtoFuncLink DontEnum|Function 1
mjs6f821c82002-03-22 00:31:57 +0000187@end
188*/
189// ECMA 15.5.4
mjs23fc88d2007-03-19 05:43:47 +0000190StringPrototype::StringPrototype(ExecState* exec, ObjectPrototype* objProto)
ap@webkit.org960c28e2008-06-19 17:29:29 +0000191 : StringObject(exec, objProto)
kocienda66a6d362001-08-24 14:24:45 +0000192{
darin@apple.com6de4edc2008-06-16 03:02:57 +0000193 // The constructor will be added later, after StringConstructor has been built
ap@webkit.org960c28e2008-06-19 17:29:29 +0000194 putDirect(exec->propertyNames().length, jsNumber(exec, 0), DontDelete | ReadOnly | DontEnum);
kocienda66a6d362001-08-24 14:24:45 +0000195}
196
darin35940e82005-12-11 02:06:17 +0000197bool StringPrototype::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot &slot)
kocienda66a6d362001-08-24 14:24:45 +0000198{
darin@apple.com6de4edc2008-06-16 03:02:57 +0000199 return getStaticFunctionSlot<StringObject>(exec, ExecState::stringTable(exec), this, propertyName, slot);
mjs6f821c82002-03-22 00:31:57 +0000200}
kocienda66a6d362001-08-24 14:24:45 +0000201
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000202// ------------------------------ Functions --------------------------
mjs6f821c82002-03-22 00:31:57 +0000203
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000204static inline UString substituteBackreferences(const UString& replacement, const UString& source, const int* ovector, RegExp* reg)
mjs5d90e062004-09-15 00:16:34 +0000205{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000206 UString substitutedReplacement;
207 int offset = 0;
ddkilzer31459a52006-06-03 04:56:56 +0000208 int i = -1;
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000209 while ((i = replacement.find('$', i + 1)) != -1) {
210 if (i + 1 == replacement.size())
ddkilzer31459a52006-06-03 04:56:56 +0000211 break;
mjs5d90e062004-09-15 00:16:34 +0000212
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000213 unsigned short ref = replacement[i + 1];
214 if (ref == '$') {
215 // "$$" -> "$"
216 ++i;
217 substitutedReplacement.append(replacement.data() + offset, i - offset);
218 offset = i + 1;
219 substitutedReplacement.append('$');
ddkilzer31459a52006-06-03 04:56:56 +0000220 continue;
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000221 }
222
223 int backrefStart;
224 int backrefLength;
225 int advance = 0;
226 if (ref == '&') {
ddkilzer31459a52006-06-03 04:56:56 +0000227 backrefStart = ovector[0];
228 backrefLength = ovector[1] - backrefStart;
229 } else if (ref == '`') {
230 backrefStart = 0;
231 backrefLength = ovector[0];
232 } else if (ref == '\'') {
233 backrefStart = ovector[1];
234 backrefLength = source.size() - backrefStart;
235 } else if (ref >= '0' && ref <= '9') {
236 // 1- and 2-digit back references are allowed
237 unsigned backrefIndex = ref - '0';
ggaren@apple.com8a50ec52007-11-07 17:18:39 +0000238 if (backrefIndex > reg->numSubpatterns())
ggarenb3ebb432006-06-06 05:59:43 +0000239 continue;
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000240 if (replacement.size() > i + 2) {
241 ref = replacement[i + 2];
ddkilzer31459a52006-06-03 04:56:56 +0000242 if (ref >= '0' && ref <= '9') {
243 backrefIndex = 10 * backrefIndex + ref - '0';
ggaren@apple.com8a50ec52007-11-07 17:18:39 +0000244 if (backrefIndex > reg->numSubpatterns())
ggarenb3ebb432006-06-06 05:59:43 +0000245 backrefIndex = backrefIndex / 10; // Fall back to the 1-digit reference
246 else
247 advance = 1;
ddkilzer31459a52006-06-03 04:56:56 +0000248 }
249 }
ddkilzer31459a52006-06-03 04:56:56 +0000250 backrefStart = ovector[2 * backrefIndex];
251 backrefLength = ovector[2 * backrefIndex + 1] - backrefStart;
252 } else
253 continue;
254
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000255 if (i - offset)
256 substitutedReplacement.append(replacement.data() + offset, i - offset);
257 i += 1 + advance;
258 offset = i + 1;
259 substitutedReplacement.append(source.data() + backrefStart, backrefLength);
mjs5d90e062004-09-15 00:16:34 +0000260 }
261
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000262 if (!offset)
263 return replacement;
264
265 if (replacement.size() - offset)
266 substitutedReplacement.append(replacement.data() + offset, replacement.size() - offset);
267
mjs5d90e062004-09-15 00:16:34 +0000268 return substitutedReplacement;
269}
ap@webkit.orgafd03182008-03-06 17:50:08 +0000270
weinig98352342007-05-29 23:07:02 +0000271static inline int localeCompare(const UString& a, const UString& b)
272{
ap@webkit.orgafd03182008-03-06 17:50:08 +0000273 return Collator::userDefault()->collate(reinterpret_cast<const ::UChar*>(a.data()), a.size(), reinterpret_cast<const ::UChar*>(b.data()), b.size());
weinig98352342007-05-29 23:07:02 +0000274}
anderscaaa39c422006-12-20 20:11:47 +0000275
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000276JSValue* stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
mjs5d90e062004-09-15 00:16:34 +0000277{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000278 JSString* sourceVal = thisValue->toThisJSString(exec);
279 const UString& source = sourceVal->value();
darine0dd9242005-06-22 17:26:17 +0000280
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000281 JSValue* pattern = args[0];
282
283 JSValue* replacement = args[1];
284 UString replacementString;
285 CallData callData;
darin@apple.com1edff432008-06-24 05:23:17 +0000286 CallType callType = replacement->getCallData(callData);
287 if (callType == CallTypeNone)
darinc13d2ca2005-08-08 04:07:46 +0000288 replacementString = replacement->toString(exec);
darine0dd9242005-06-22 17:26:17 +0000289
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000290 if (pattern->isObject(&RegExpObject::info)) {
291 RegExp* reg = static_cast<RegExpObject*>(pattern)->regExp();
ggaren@apple.com8a50ec52007-11-07 17:18:39 +0000292 bool global = reg->global();
mjs5d90e062004-09-15 00:16:34 +0000293
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000294 RegExpConstructor* regExpObj = exec->lexicalGlobalObject()->regExpConstructor();
mjs5d90e062004-09-15 00:16:34 +0000295
mjs5d90e062004-09-15 00:16:34 +0000296 int lastIndex = 0;
297 int startPosition = 0;
298
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000299 Vector<UString::Range, 16> sourceRanges;
300 Vector<UString, 16> replacements;
mjs5d90e062004-09-15 00:16:34 +0000301
302 // This is either a loop (if global is set) or a one-way (if not).
303 do {
darin9fa44df2007-10-31 14:46:41 +0000304 int matchIndex;
305 int matchLen;
306 int* ovector;
307 regExpObj->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector);
308 if (matchIndex < 0)
mjs5d90e062004-09-15 00:16:34 +0000309 break;
mjs5d90e062004-09-15 00:16:34 +0000310
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000311 sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex));
mjs5d90e062004-09-15 00:16:34 +0000312
darin@apple.com1edff432008-06-24 05:23:17 +0000313 if (callType != CallTypeNone) {
ggaren91f03742005-10-11 20:43:49 +0000314 int completeMatchStart = ovector[0];
darin@apple.com80d38f92008-06-16 05:28:46 +0000315 ArgList args;
darine0dd9242005-06-22 17:26:17 +0000316
ggaren@apple.com8a50ec52007-11-07 17:18:39 +0000317 for (unsigned i = 0; i < reg->numSubpatterns() + 1; i++) {
darin9fa44df2007-10-31 14:46:41 +0000318 int matchStart = ovector[i * 2];
319 int matchLen = ovector[i * 2 + 1] - matchStart;
bdash7891c022007-06-21 00:00:12 +0000320
darincd9cd762007-08-13 02:42:17 +0000321 if (matchStart < 0)
322 args.append(jsUndefined());
323 else
ap@webkit.org960c28e2008-06-19 17:29:29 +0000324 args.append(jsString(exec, source.substr(matchStart, matchLen)));
darine0dd9242005-06-22 17:26:17 +0000325 }
326
ap@webkit.org960c28e2008-06-19 17:29:29 +0000327 args.append(jsNumber(exec, completeMatchStart));
mjs0b003172007-08-05 05:20:35 +0000328 args.append(sourceVal);
darine0dd9242005-06-22 17:26:17 +0000329
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000330 replacements.append(call(exec, replacement, callType, callData, exec->globalThisValue(), args)->toString(exec));
bdash7891c022007-06-21 00:00:12 +0000331 } else
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000332 replacements.append(substituteBackreferences(replacementString, source, ovector, reg));
mjs5d90e062004-09-15 00:16:34 +0000333
334 lastIndex = matchIndex + matchLen;
335 startPosition = lastIndex;
336
337 // special case of empty match
338 if (matchLen == 0) {
339 startPosition++;
340 if (startPosition > source.size())
341 break;
342 }
343 } while (global);
344
345 if (lastIndex < source.size())
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000346 sourceRanges.append(UString::Range(lastIndex, source.size() - lastIndex));
mjs5d90e062004-09-15 00:16:34 +0000347
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000348 UString result = source.spliceSubstringsWithSeparators(sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size());
mjs5d90e062004-09-15 00:16:34 +0000349
mjs0b003172007-08-05 05:20:35 +0000350 if (result == source)
351 return sourceVal;
352
ap@webkit.org960c28e2008-06-19 17:29:29 +0000353 return jsString(exec, result);
mjs5d90e062004-09-15 00:16:34 +0000354 }
darin44b175c2005-04-29 00:22:55 +0000355
356 // First arg is a string
darinc13d2ca2005-08-08 04:07:46 +0000357 UString patternString = pattern->toString(exec);
darin44b175c2005-04-29 00:22:55 +0000358 int matchPos = source.find(patternString);
359 int matchLen = patternString.size();
360 // Do the replacement
361 if (matchPos == -1)
mjs0b003172007-08-05 05:20:35 +0000362 return sourceVal;
darine0dd9242005-06-22 17:26:17 +0000363
darin@apple.com1edff432008-06-24 05:23:17 +0000364 if (callType != CallTypeNone) {
darin@apple.com80d38f92008-06-16 05:28:46 +0000365 ArgList args;
darine0dd9242005-06-22 17:26:17 +0000366
ap@webkit.org960c28e2008-06-19 17:29:29 +0000367 args.append(jsString(exec, source.substr(matchPos, matchLen)));
368 args.append(jsNumber(exec, matchPos));
mjs0b003172007-08-05 05:20:35 +0000369 args.append(sourceVal);
darine0dd9242005-06-22 17:26:17 +0000370
darin@apple.com1edff432008-06-24 05:23:17 +0000371 replacementString = call(exec, replacement, callType, callData, exec->globalThisValue(), args)->toString(exec);
darine0dd9242005-06-22 17:26:17 +0000372 }
373
ap@webkit.org960c28e2008-06-19 17:29:29 +0000374 return jsString(exec, source.substr(0, matchPos) + replacementString + source.substr(matchPos + matchLen));
mjs5d90e062004-09-15 00:16:34 +0000375}
376
darin@apple.com1edff432008-06-24 05:23:17 +0000377JSValue* stringProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
mjs6f821c82002-03-22 00:31:57 +0000378{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000379 // Also used for valueOf.
mjs6f821c82002-03-22 00:31:57 +0000380
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000381 if (thisValue->isString())
382 return thisValue;
kocienda66a6d362001-08-24 14:24:45 +0000383
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000384 if (thisValue->isObject(&StringObject::info))
385 return static_cast<StringObject*>(thisValue)->internalValue();
mjs6f821c82002-03-22 00:31:57 +0000386
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000387 return throwError(exec, TypeError);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000388}
mjs6f821c82002-03-22 00:31:57 +0000389
darin@apple.com1edff432008-06-24 05:23:17 +0000390JSValue* stringProtoFuncCharAt(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000391{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000392 UString s = thisValue->toThisString(exec);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000393 int len = s.size();
mjs6f821c82002-03-22 00:31:57 +0000394
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000395 UString u;
396 JSValue* a0 = args[0];
397 double dpos = a0->toInteger(exec);
darin1622f9e2007-10-26 07:51:25 +0000398 if (dpos >= 0 && dpos < len)
darina51d07b2004-02-02 21:23:17 +0000399 u = s.substr(static_cast<int>(dpos), 1);
darin0dd092a2004-08-02 21:44:42 +0000400 else
401 u = "";
ap@webkit.org960c28e2008-06-19 17:29:29 +0000402 return jsString(exec, u);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000403}
404
darin@apple.com1edff432008-06-24 05:23:17 +0000405JSValue* stringProtoFuncCharCodeAt(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000406{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000407 UString s = thisValue->toThisString(exec);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000408 int len = s.size();
409
410 JSValue* result = 0;
411
412 JSValue* a0 = args[0];
413 double dpos = a0->toInteger(exec);
darin1622f9e2007-10-26 07:51:25 +0000414 if (dpos >= 0 && dpos < len)
ap@webkit.org960c28e2008-06-19 17:29:29 +0000415 result = jsNumber(exec, s[static_cast<int>(dpos)]);
darinf0d73262004-09-27 01:54:30 +0000416 else
ap@webkit.org960c28e2008-06-19 17:29:29 +0000417 result = jsNaN(exec);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000418 return result;
419}
420
darin@apple.com1edff432008-06-24 05:23:17 +0000421JSValue* stringProtoFuncConcat(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000422{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000423 UString s = thisValue->toThisString(exec);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000424
darin@apple.com80d38f92008-06-16 05:28:46 +0000425 ArgList::const_iterator end = args.end();
426 for (ArgList::const_iterator it = args.begin(); it != end; ++it) {
ggaren879ab752007-11-05 21:27:15 +0000427 s += (*it)->toString(exec);
mjs6f821c82002-03-22 00:31:57 +0000428 }
ap@webkit.org960c28e2008-06-19 17:29:29 +0000429 return jsString(exec, s);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000430}
431
darin@apple.com1edff432008-06-24 05:23:17 +0000432JSValue* stringProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000433{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000434 UString s = thisValue->toThisString(exec);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000435 int len = s.size();
436
437 JSValue* a0 = args[0];
438 JSValue* a1 = args[1];
439 UString u2 = a0->toString(exec);
440 double dpos = a1->toInteger(exec);
darin1622f9e2007-10-26 07:51:25 +0000441 if (dpos < 0)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000442 dpos = 0;
darin1622f9e2007-10-26 07:51:25 +0000443 else if (dpos > len)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000444 dpos = len;
ap@webkit.org960c28e2008-06-19 17:29:29 +0000445 return jsNumber(exec, s.find(u2, static_cast<int>(dpos)));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000446}
447
darin@apple.com1edff432008-06-24 05:23:17 +0000448JSValue* stringProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000449{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000450 UString s = thisValue->toThisString(exec);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000451 int len = s.size();
452
453 JSValue* a0 = args[0];
454 JSValue* a1 = args[1];
455
456 UString u2 = a0->toString(exec);
457 double dpos = a1->toIntegerPreserveNaN(exec);
darin1622f9e2007-10-26 07:51:25 +0000458 if (dpos < 0)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000459 dpos = 0;
darin1622f9e2007-10-26 07:51:25 +0000460 else if (!(dpos <= len)) // true for NaN
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000461 dpos = len;
ap@webkit.org960c28e2008-06-19 17:29:29 +0000462 return jsNumber(exec, s.rfind(u2, static_cast<int>(dpos)));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000463}
464
darin@apple.com1edff432008-06-24 05:23:17 +0000465JSValue* stringProtoFuncMatch(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000466{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000467 UString s = thisValue->toThisString(exec);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000468
469 JSValue* a0 = args[0];
470
471 UString u = s;
darin@apple.come4ba8cf2008-02-09 18:09:42 +0000472 RefPtr<RegExp> reg;
darin@apple.com6de4edc2008-06-16 03:02:57 +0000473 RegExpObject* imp = 0;
474 if (a0->isObject() && static_cast<JSObject *>(a0)->inherits(&RegExpObject::info)) {
475 reg = static_cast<RegExpObject *>(a0)->regExp();
ggaren91f03742005-10-11 20:43:49 +0000476 } else {
477 /*
darinb70665a2002-04-15 23:43:21 +0000478 * ECMA 15.5.4.12 String.prototype.search (regexp)
479 * If regexp is not an object whose [[Class]] property is "RegExp", it is
480 * replaced with the result of the expression new RegExp(regexp).
481 */
darin@apple.come4ba8cf2008-02-09 18:09:42 +0000482 reg = RegExp::create(a0->toString(exec));
mjs6f821c82002-03-22 00:31:57 +0000483 }
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000484 RegExpConstructor* regExpObj = exec->lexicalGlobalObject()->regExpConstructor();
darin9fa44df2007-10-31 14:46:41 +0000485 int pos;
486 int matchLength;
darin@apple.come4ba8cf2008-02-09 18:09:42 +0000487 regExpObj->performMatch(reg.get(), u, 0, pos, matchLength);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000488 JSValue* result;
489 if (!(reg->global())) {
490 // case without 'g' flag is handled like RegExp.prototype.exec
491 if (pos < 0)
492 result = jsNull();
493 else
494 result = regExpObj->arrayOfMatches(exec);
darin74f6ed62002-07-22 05:38:39 +0000495 } else {
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000496 // return array of matches
darin@apple.com80d38f92008-06-16 05:28:46 +0000497 ArgList list;
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000498 int lastIndex = 0;
499 while (pos >= 0) {
ap@webkit.org960c28e2008-06-19 17:29:29 +0000500 list.append(jsString(exec, u.substr(pos, matchLength)));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000501 lastIndex = pos;
502 pos += matchLength == 0 ? 1 : matchLength;
darin@apple.come4ba8cf2008-02-09 18:09:42 +0000503 regExpObj->performMatch(reg.get(), u, pos, pos, matchLength);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000504 }
505 if (imp)
darin@apple.com8e21ef12008-02-06 17:33:07 +0000506 imp->setLastIndex(lastIndex);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000507 if (list.isEmpty()) {
508 // if there are no matches at all, it's important to return
509 // Null instead of an empty array, because this matches
510 // other browsers and because Null is a false value.
511 result = jsNull();
darin74f6ed62002-07-22 05:38:39 +0000512 } else {
darin@apple.com1edff432008-06-24 05:23:17 +0000513 result = constructArray(exec, list);
darin74f6ed62002-07-22 05:38:39 +0000514 }
mjs6f821c82002-03-22 00:31:57 +0000515 }
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000516 return result;
517}
518
darin@apple.com1edff432008-06-24 05:23:17 +0000519JSValue* stringProtoFuncSearch(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000520{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000521 UString s = thisValue->toThisString(exec);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000522
523 JSValue* a0 = args[0];
524
525 UString u = s;
darin@apple.come4ba8cf2008-02-09 18:09:42 +0000526 RefPtr<RegExp> reg;
darin@apple.com6de4edc2008-06-16 03:02:57 +0000527 if (a0->isObject() && static_cast<JSObject*>(a0)->inherits(&RegExpObject::info)) {
528 reg = static_cast<RegExpObject*>(a0)->regExp();
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000529 } else {
530 /*
531 * ECMA 15.5.4.12 String.prototype.search (regexp)
532 * If regexp is not an object whose [[Class]] property is "RegExp", it is
533 * replaced with the result of the expression new RegExp(regexp).
534 */
darin@apple.come4ba8cf2008-02-09 18:09:42 +0000535 reg = RegExp::create(a0->toString(exec));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000536 }
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000537 RegExpConstructor* regExpObj = exec->lexicalGlobalObject()->regExpConstructor();
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000538 int pos;
539 int matchLength;
darin@apple.come4ba8cf2008-02-09 18:09:42 +0000540 regExpObj->performMatch(reg.get(), u, 0, pos, matchLength);
ap@webkit.org960c28e2008-06-19 17:29:29 +0000541 return jsNumber(exec, pos);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000542}
543
darin@apple.com1edff432008-06-24 05:23:17 +0000544JSValue* stringProtoFuncSlice(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000545{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000546 UString s = thisValue->toThisString(exec);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000547 int len = s.size();
548
549 JSValue* a0 = args[0];
550 JSValue* a1 = args[1];
551
552 // The arg processing is very much like ArrayProtoFunc::Slice
553 double start = a0->toInteger(exec);
554 double end = a1->isUndefined() ? len : a1->toInteger(exec);
555 double from = start < 0 ? len + start : start;
556 double to = end < 0 ? len + end : end;
557 if (to > from && to > 0 && from < len) {
ggarenbace8b62005-11-06 05:48:45 +0000558 if (from < 0)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000559 from = 0;
ggarenbace8b62005-11-06 05:48:45 +0000560 if (to > len)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000561 to = len;
ap@webkit.org960c28e2008-06-19 17:29:29 +0000562 return jsString(exec, s.substr(static_cast<int>(from), static_cast<int>(to - from)));
mjs6f821c82002-03-22 00:31:57 +0000563 }
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000564
ap@webkit.org960c28e2008-06-19 17:29:29 +0000565 return jsString(exec, "");
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000566}
567
darin@apple.com1edff432008-06-24 05:23:17 +0000568JSValue* stringProtoFuncSplit(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000569{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000570 UString s = thisValue->toThisString(exec);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000571
572 JSValue* a0 = args[0];
573 JSValue* a1 = args[1];
574
darin@apple.com1edff432008-06-24 05:23:17 +0000575 JSObject* res = constructEmptyArray(exec);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000576 JSValue* result = res;
577 UString u = s;
578 int pos;
579 int i = 0;
580 int p0 = 0;
darinc13d2ca2005-08-08 04:07:46 +0000581 uint32_t limit = a1->isUndefined() ? 0xFFFFFFFFU : a1->toUInt32(exec);
darin@apple.com6de4edc2008-06-16 03:02:57 +0000582 if (a0->isObject() && static_cast<JSObject *>(a0)->inherits(&RegExpObject::info)) {
583 RegExp *reg = static_cast<RegExpObject *>(a0)->regExp();
darin9fa44df2007-10-31 14:46:41 +0000584 if (u.isEmpty() && reg->match(u, 0) >= 0) {
darinae58eff2006-07-30 00:04:22 +0000585 // empty string matched by regexp -> empty array
ap@webkit.org960c28e2008-06-19 17:29:29 +0000586 res->put(exec, exec->propertyNames().length, jsNumber(exec, 0));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000587 return result;
mjs6f821c82002-03-22 00:31:57 +0000588 }
mjs6f821c82002-03-22 00:31:57 +0000589 pos = 0;
darine3385e92004-08-10 18:43:51 +0000590 while (static_cast<uint32_t>(i) != limit && pos < u.size()) {
darin9fa44df2007-10-31 14:46:41 +0000591 OwnArrayPtr<int> ovector;
592 int mpos = reg->match(u, pos, &ovector);
593 if (mpos < 0)
darinae58eff2006-07-30 00:04:22 +0000594 break;
darin9fa44df2007-10-31 14:46:41 +0000595 int mlen = ovector[1] - ovector[0];
596 pos = mpos + (mlen == 0 ? 1 : mlen);
597 if (mpos != p0 || mlen) {
ap@webkit.org960c28e2008-06-19 17:29:29 +0000598 res->put(exec,i, jsString(exec, u.substr(p0, mpos-p0)));
darin9fa44df2007-10-31 14:46:41 +0000599 p0 = mpos + mlen;
darinae58eff2006-07-30 00:04:22 +0000600 i++;
601 }
ggaren@apple.com8a50ec52007-11-07 17:18:39 +0000602 for (unsigned si = 1; si <= reg->numSubpatterns(); ++si) {
darincd9cd762007-08-13 02:42:17 +0000603 int spos = ovector[si * 2];
604 if (spos < 0)
605 res->put(exec, i++, jsUndefined());
606 else
ap@webkit.org960c28e2008-06-19 17:29:29 +0000607 res->put(exec, i++, jsString(exec, u.substr(spos, ovector[si * 2 + 1] - spos)));
darincd9cd762007-08-13 02:42:17 +0000608 }
mjs6f821c82002-03-22 00:31:57 +0000609 }
darine3385e92004-08-10 18:43:51 +0000610 } else {
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000611 UString u2 = a0->toString(exec);
mjs6f821c82002-03-22 00:31:57 +0000612 if (u2.isEmpty()) {
darinae58eff2006-07-30 00:04:22 +0000613 if (u.isEmpty()) {
614 // empty separator matches empty string -> empty array
ap@webkit.org960c28e2008-06-19 17:29:29 +0000615 res->put(exec, exec->propertyNames().length, jsNumber(exec, 0));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000616 return result;
darinae58eff2006-07-30 00:04:22 +0000617 } else {
618 while (static_cast<uint32_t>(i) != limit && i < u.size()-1)
ap@webkit.org960c28e2008-06-19 17:29:29 +0000619 res->put(exec, i++, jsString(exec, u.substr(p0++, 1)));
darinae58eff2006-07-30 00:04:22 +0000620 }
mjs6f821c82002-03-22 00:31:57 +0000621 } else {
darinae58eff2006-07-30 00:04:22 +0000622 while (static_cast<uint32_t>(i) != limit && (pos = u.find(u2, p0)) >= 0) {
ap@webkit.org960c28e2008-06-19 17:29:29 +0000623 res->put(exec, i, jsString(exec, u.substr(p0, pos - p0)));
darinae58eff2006-07-30 00:04:22 +0000624 p0 = pos + u2.size();
625 i++;
626 }
mjs6f821c82002-03-22 00:31:57 +0000627 }
628 }
629 // add remaining string, if any
darine3385e92004-08-10 18:43:51 +0000630 if (static_cast<uint32_t>(i) != limit)
ap@webkit.org960c28e2008-06-19 17:29:29 +0000631 res->put(exec, i++, jsString(exec, u.substr(p0)));
632 res->put(exec, exec->propertyNames().length, jsNumber(exec, i));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000633 return result;
634}
635
darin@apple.com1edff432008-06-24 05:23:17 +0000636JSValue* stringProtoFuncSubstr(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000637{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000638 UString s = thisValue->toThisString(exec);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000639 int len = s.size();
640
641 JSValue* a0 = args[0];
642 JSValue* a1 = args[1];
643
darin1622f9e2007-10-26 07:51:25 +0000644 double start = a0->toInteger(exec);
645 double length = a1->isUndefined() ? len : a1->toInteger(exec);
646 if (start >= len)
ap@webkit.org960c28e2008-06-19 17:29:29 +0000647 return jsString(exec, "");
darin1622f9e2007-10-26 07:51:25 +0000648 if (length < 0)
ap@webkit.org960c28e2008-06-19 17:29:29 +0000649 return jsString(exec, "");
darin1622f9e2007-10-26 07:51:25 +0000650 if (start < 0) {
651 start += len;
652 if (start < 0)
653 start = 0;
darina51d07b2004-02-02 21:23:17 +0000654 }
weinig@apple.com95835032008-01-16 01:22:25 +0000655 if (length > len)
656 length = len;
ap@webkit.org960c28e2008-06-19 17:29:29 +0000657 return jsString(exec, s.substr(static_cast<int>(start), static_cast<int>(length)));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000658}
659
darin@apple.com1edff432008-06-24 05:23:17 +0000660JSValue* stringProtoFuncSubstring(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000661{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000662 UString s = thisValue->toThisString(exec);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000663 int len = s.size();
664
665 JSValue* a0 = args[0];
666 JSValue* a1 = args[1];
667
darinc13d2ca2005-08-08 04:07:46 +0000668 double start = a0->toNumber(exec);
669 double end = a1->toNumber(exec);
mrowe@apple.com915de552007-10-29 02:52:04 +0000670 if (isnan(start))
mjs6f821c82002-03-22 00:31:57 +0000671 start = 0;
mrowe@apple.com915de552007-10-29 02:52:04 +0000672 if (isnan(end))
mjs6f821c82002-03-22 00:31:57 +0000673 end = 0;
674 if (start < 0)
675 start = 0;
676 if (end < 0)
677 end = 0;
678 if (start > len)
679 start = len;
680 if (end > len)
681 end = len;
darinc13d2ca2005-08-08 04:07:46 +0000682 if (a1->isUndefined())
mjs6f821c82002-03-22 00:31:57 +0000683 end = len;
684 if (start > end) {
685 double temp = end;
686 end = start;
687 start = temp;
688 }
ap@webkit.org960c28e2008-06-19 17:29:29 +0000689 return jsString(exec, s.substr((int)start, (int)end-(int)start));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000690}
691
darin@apple.com1edff432008-06-24 05:23:17 +0000692JSValue* stringProtoFuncToLowerCase(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000693{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000694 JSString* sVal = thisValue->toThisJSString(exec);
695 const UString& s = sVal->value();
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000696
darin0d66de72007-08-08 00:45:39 +0000697 int ssize = s.size();
698 if (!ssize)
699 return sVal;
eric@webkit.org87d855b2008-03-10 22:06:44 +0000700 Vector<UChar> buffer(ssize);
darin0d66de72007-08-08 00:45:39 +0000701 bool error;
eric@webkit.org87d855b2008-03-10 22:06:44 +0000702 int length = Unicode::toLower(buffer.data(), ssize, reinterpret_cast<const UChar*>(s.data()), ssize, &error);
darin0d66de72007-08-08 00:45:39 +0000703 if (error) {
704 buffer.resize(length);
eric@webkit.org87d855b2008-03-10 22:06:44 +0000705 length = Unicode::toLower(buffer.data(), length, reinterpret_cast<const UChar*>(s.data()), ssize, &error);
darin0d66de72007-08-08 00:45:39 +0000706 if (error)
707 return sVal;
708 }
709 if (length == ssize && memcmp(buffer.data(), s.data(), length * sizeof(UChar)) == 0)
710 return sVal;
ap@webkit.org960c28e2008-06-19 17:29:29 +0000711 return jsString(exec, UString(buffer.releaseBuffer(), length, false));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000712}
713
darin@apple.com1edff432008-06-24 05:23:17 +0000714JSValue* stringProtoFuncToUpperCase(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000715{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000716 JSString* sVal = thisValue->toThisJSString(exec);
717 const UString& s = sVal->value();
718
darin0d66de72007-08-08 00:45:39 +0000719 int ssize = s.size();
720 if (!ssize)
721 return sVal;
eric@webkit.org87d855b2008-03-10 22:06:44 +0000722 Vector<UChar> buffer(ssize);
darin0d66de72007-08-08 00:45:39 +0000723 bool error;
eric@webkit.org87d855b2008-03-10 22:06:44 +0000724 int length = Unicode::toUpper(buffer.data(), ssize, reinterpret_cast<const UChar*>(s.data()), ssize, &error);
darin0d66de72007-08-08 00:45:39 +0000725 if (error) {
726 buffer.resize(length);
eric@webkit.org87d855b2008-03-10 22:06:44 +0000727 length = Unicode::toUpper(buffer.data(), length, reinterpret_cast<const UChar*>(s.data()), ssize, &error);
darin0d66de72007-08-08 00:45:39 +0000728 if (error)
729 return sVal;
730 }
731 if (length == ssize && memcmp(buffer.data(), s.data(), length * sizeof(UChar)) == 0)
732 return sVal;
ap@webkit.org960c28e2008-06-19 17:29:29 +0000733 return jsString(exec, UString(buffer.releaseBuffer(), length, false));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000734}
735
darin@apple.com1edff432008-06-24 05:23:17 +0000736JSValue* stringProtoFuncToLocaleLowerCase(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000737{
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000738 // FIXME: See http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt for locale-sensitive mappings that aren't implemented.
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000739
740 JSString* sVal = thisValue->toThisJSString(exec);
741 const UString& s = sVal->value();
742
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000743 int ssize = s.size();
744 if (!ssize)
745 return sVal;
eric@webkit.org87d855b2008-03-10 22:06:44 +0000746 Vector<UChar> buffer(ssize);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000747 bool error;
eric@webkit.org87d855b2008-03-10 22:06:44 +0000748 int length = Unicode::toLower(buffer.data(), ssize, reinterpret_cast<const UChar*>(s.data()), ssize, &error);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000749 if (error) {
750 buffer.resize(length);
eric@webkit.org87d855b2008-03-10 22:06:44 +0000751 length = Unicode::toLower(buffer.data(), length, reinterpret_cast<const UChar*>(s.data()), ssize, &error);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000752 if (error)
753 return sVal;
754 }
755 if (length == ssize && memcmp(buffer.data(), s.data(), length * sizeof(UChar)) == 0)
756 return sVal;
ap@webkit.org960c28e2008-06-19 17:29:29 +0000757 return jsString(exec, UString(buffer.releaseBuffer(), length, false));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000758}
759
darin@apple.com1edff432008-06-24 05:23:17 +0000760JSValue* stringProtoFuncToLocaleUpperCase(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000761{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000762 JSString* sVal = thisValue->toThisJSString(exec);
763 const UString& s = sVal->value();
764
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000765 int ssize = s.size();
766 if (!ssize)
767 return sVal;
eric@webkit.org87d855b2008-03-10 22:06:44 +0000768 Vector<UChar> buffer(ssize);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000769 bool error;
eric@webkit.org87d855b2008-03-10 22:06:44 +0000770 int length = Unicode::toUpper(buffer.data(), ssize, reinterpret_cast<const UChar*>(s.data()), ssize, &error);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000771 if (error) {
772 buffer.resize(length);
eric@webkit.org87d855b2008-03-10 22:06:44 +0000773 length = Unicode::toUpper(buffer.data(), length, reinterpret_cast<const UChar*>(s.data()), ssize, &error);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000774 if (error)
775 return sVal;
776 }
777 if (length == ssize && memcmp(buffer.data(), s.data(), length * sizeof(UChar)) == 0)
778 return sVal;
ap@webkit.org960c28e2008-06-19 17:29:29 +0000779 return jsString(exec, UString(buffer.releaseBuffer(), length, false));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000780}
781
darin@apple.com1edff432008-06-24 05:23:17 +0000782JSValue* stringProtoFuncLocaleCompare(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000783{
weinig55d6dd22007-05-26 21:57:28 +0000784 if (args.size() < 1)
ap@webkit.org960c28e2008-06-19 17:29:29 +0000785 return jsNumber(exec, 0);
mjs6f821c82002-03-22 00:31:57 +0000786
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000787 UString s = thisValue->toThisString(exec);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000788 JSValue* a0 = args[0];
ap@webkit.org960c28e2008-06-19 17:29:29 +0000789 return jsNumber(exec, localeCompare(s, a0->toString(exec)));
mjs6f821c82002-03-22 00:31:57 +0000790}
791
darin@apple.com1edff432008-06-24 05:23:17 +0000792JSValue* stringProtoFuncBig(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000793{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000794 UString s = thisValue->toThisString(exec);
ap@webkit.org960c28e2008-06-19 17:29:29 +0000795 return jsString(exec, "<big>" + s + "</big>");
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000796}
797
darin@apple.com1edff432008-06-24 05:23:17 +0000798JSValue* stringProtoFuncSmall(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000799{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000800 UString s = thisValue->toThisString(exec);
ap@webkit.org960c28e2008-06-19 17:29:29 +0000801 return jsString(exec, "<small>" + s + "</small>");
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000802}
803
darin@apple.com1edff432008-06-24 05:23:17 +0000804JSValue* stringProtoFuncBlink(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000805{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000806 UString s = thisValue->toThisString(exec);
ap@webkit.org960c28e2008-06-19 17:29:29 +0000807 return jsString(exec, "<blink>" + s + "</blink>");
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000808}
809
darin@apple.com1edff432008-06-24 05:23:17 +0000810JSValue* stringProtoFuncBold(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000811{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000812 UString s = thisValue->toThisString(exec);
ap@webkit.org960c28e2008-06-19 17:29:29 +0000813 return jsString(exec, "<b>" + s + "</b>");
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000814}
815
darin@apple.com1edff432008-06-24 05:23:17 +0000816JSValue* stringProtoFuncFixed(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000817{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000818 UString s = thisValue->toThisString(exec);
ap@webkit.org960c28e2008-06-19 17:29:29 +0000819 return jsString(exec, "<tt>" + s + "</tt>");
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000820}
821
darin@apple.com1edff432008-06-24 05:23:17 +0000822JSValue* stringProtoFuncItalics(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000823{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000824 UString s = thisValue->toThisString(exec);
ap@webkit.org960c28e2008-06-19 17:29:29 +0000825 return jsString(exec, "<i>" + s + "</i>");
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000826}
827
darin@apple.com1edff432008-06-24 05:23:17 +0000828JSValue* stringProtoFuncStrike(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000829{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000830 UString s = thisValue->toThisString(exec);
ap@webkit.org960c28e2008-06-19 17:29:29 +0000831 return jsString(exec, "<strike>" + s + "</strike>");
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000832}
833
darin@apple.com1edff432008-06-24 05:23:17 +0000834JSValue* stringProtoFuncSub(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000835{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000836 UString s = thisValue->toThisString(exec);
ap@webkit.org960c28e2008-06-19 17:29:29 +0000837 return jsString(exec, "<sub>" + s + "</sub>");
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000838}
839
darin@apple.com1edff432008-06-24 05:23:17 +0000840JSValue* stringProtoFuncSup(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000841{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000842 UString s = thisValue->toThisString(exec);
ap@webkit.org960c28e2008-06-19 17:29:29 +0000843 return jsString(exec, "<sup>" + s + "</sup>");
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000844}
845
darin@apple.com1edff432008-06-24 05:23:17 +0000846JSValue* stringProtoFuncFontcolor(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000847{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000848 UString s = thisValue->toThisString(exec);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000849 JSValue* a0 = args[0];
ap@webkit.org960c28e2008-06-19 17:29:29 +0000850 return jsString(exec, "<font color=\"" + a0->toString(exec) + "\">" + s + "</font>");
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000851}
852
darin@apple.com1edff432008-06-24 05:23:17 +0000853JSValue* stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000854{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000855 UString s = thisValue->toThisString(exec);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000856 JSValue* a0 = args[0];
ap@webkit.org960c28e2008-06-19 17:29:29 +0000857 return jsString(exec, "<font size=\"" + a0->toString(exec) + "\">" + s + "</font>");
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000858}
859
darin@apple.com1edff432008-06-24 05:23:17 +0000860JSValue* stringProtoFuncAnchor(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000861{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000862 UString s = thisValue->toThisString(exec);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000863 JSValue* a0 = args[0];
ap@webkit.org960c28e2008-06-19 17:29:29 +0000864 return jsString(exec, "<a name=\"" + a0->toString(exec) + "\">" + s + "</a>");
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000865}
866
darin@apple.com1edff432008-06-24 05:23:17 +0000867JSValue* stringProtoFuncLink(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000868{
darin@apple.com59c4d4e2008-06-27 02:53:42 +0000869 UString s = thisValue->toThisString(exec);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000870 JSValue* a0 = args[0];
ap@webkit.org960c28e2008-06-19 17:29:29 +0000871 return jsString(exec, "<a href=\"" + a0->toString(exec) + "\">" + s + "</a>");
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000872}
873
darin@apple.com6de4edc2008-06-16 03:02:57 +0000874// ------------------------------ StringConstructor ------------------------------
mjs6f821c82002-03-22 00:31:57 +0000875
darin@apple.com1edff432008-06-24 05:23:17 +0000876static JSValue* stringFromCharCode(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
877{
878 UString s;
879 if (args.size()) {
880 UChar* buf = static_cast<UChar*>(fastMalloc(args.size() * sizeof(UChar)));
881 UChar* p = buf;
882 ArgList::const_iterator end = args.end();
883 for (ArgList::const_iterator it = args.begin(); it != end; ++it)
884 *p++ = static_cast<UChar>((*it)->toUInt32(exec));
885 s = UString(buf, args.size(), false);
886 } else
887 s = "";
888
889 return jsString(exec, s);
890}
891
darin@apple.com6de4edc2008-06-16 03:02:57 +0000892StringConstructor::StringConstructor(ExecState* exec, FunctionPrototype* funcProto, StringPrototype* stringProto)
ap@webkit.org07e5bce2008-06-16 23:28:38 +0000893 : InternalFunction(funcProto, Identifier(exec, stringProto->classInfo()->className))
mjs6f821c82002-03-22 00:31:57 +0000894{
mjs6f821c82002-03-22 00:31:57 +0000895 // ECMA 15.5.3.1 String.prototype
darin@apple.com1edff432008-06-24 05:23:17 +0000896 putDirect(exec->propertyNames().prototype, stringProto, ReadOnly | DontEnum | DontDelete);
mjs6f821c82002-03-22 00:31:57 +0000897
darin@apple.com1edff432008-06-24 05:23:17 +0000898 // ECMA 15.5.3.2 fromCharCode()
899 putDirectFunction(new (exec) PrototypeFunction(exec, funcProto, 1, exec->propertyNames().fromCharCode, stringFromCharCode), DontEnum);
mjs6f821c82002-03-22 00:31:57 +0000900
901 // no. of arguments for constructor
darin@apple.com1edff432008-06-24 05:23:17 +0000902 putDirect(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);
kocienda66a6d362001-08-24 14:24:45 +0000903}
904
905// ECMA 15.5.2
darin@apple.com1edff432008-06-24 05:23:17 +0000906static JSObject* constructWithStringConstructor(ExecState* exec, JSObject*, const ArgList& args)
kocienda66a6d362001-08-24 14:24:45 +0000907{
darin@apple.com1edff432008-06-24 05:23:17 +0000908 JSObject* prototype = exec->lexicalGlobalObject()->stringPrototype();
909 if (args.isEmpty())
910 return new (exec) StringObject(exec, prototype);
911 return new (exec) StringObject(exec, prototype, args[0]->toString(exec));
912}
913
914ConstructType StringConstructor::getConstructData(ConstructData& constructData)
915{
916 constructData.native.function = constructWithStringConstructor;
917 return ConstructTypeNative;
kocienda66a6d362001-08-24 14:24:45 +0000918}
919
mjs6f821c82002-03-22 00:31:57 +0000920// ECMA 15.5.1
darin@apple.com1edff432008-06-24 05:23:17 +0000921static JSValue* callStringConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
mjs6f821c82002-03-22 00:31:57 +0000922{
darin@apple.com1edff432008-06-24 05:23:17 +0000923 if (args.isEmpty())
924 return jsString(exec, "");
925 return jsString(exec, args[0]->toString(exec));
mjs6f821c82002-03-22 00:31:57 +0000926}
927
darin@apple.com1edff432008-06-24 05:23:17 +0000928CallType StringConstructor::getCallData(CallData& callData)
mjs6f821c82002-03-22 00:31:57 +0000929{
darin@apple.com1edff432008-06-24 05:23:17 +0000930 callData.native.function = callStringConstructor;
931 return CallTypeNative;
kocienda66a6d362001-08-24 14:24:45 +0000932}
darinf9e5d6c2007-01-09 14:54:26 +0000933
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000934} // namespace KJS