blob: 7537d5033de60e612e15608e524c0969533cdb34 [file] [log] [blame]
weinig@apple.comefdce0f2008-06-30 20:52:03 +00001/*
2 * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
fpizlo@apple.com3cb36ea2015-10-05 19:35:32 +00004 * Copyright (C) 2004, 2007, 2008, 2015 Apple Inc. All rights reserved.
weinig@apple.comefdce0f2008-06-30 20:52:03 +00005 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library 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 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#include "config.h"
24#include "JSString.h"
25
26#include "JSGlobalObject.h"
barraclough@apple.com794f4612010-08-18 07:41:22 +000027#include "JSGlobalObjectFunctions.h"
weinig@apple.comefdce0f2008-06-30 20:52:03 +000028#include "JSObject.h"
fpizlo@apple.comfb7eff22014-02-11 01:45:50 +000029#include "JSCInlines.h"
weinig@apple.comefdce0f2008-06-30 20:52:03 +000030#include "StringObject.h"
31#include "StringPrototype.h"
akling@apple.comede8a982014-07-08 22:36:59 +000032#include "StrongInlines.h"
weinig@apple.comefdce0f2008-06-30 20:52:03 +000033
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +000034namespace JSC {
antti@apple.com6261f1f2010-12-07 11:11:08 +000035
akling@apple.com2de49b72014-07-30 22:26:22 +000036const ClassInfo JSString::s_info = { "string", 0, 0, CREATE_METHOD_TABLE(JSString) };
oliver@apple.com23ce68f2011-04-25 21:21:28 +000037
ggaren@apple.comc09535a2015-10-06 01:59:02 +000038Structure* JSString::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
39{
40 return Structure::create(vm, globalObject, proto, TypeInfo(StringType, StructureFlags), info());
41}
42
msaboff@apple.com6e74e922012-04-27 23:51:17 +000043void JSRopeString::RopeBuilder::expand()
ggaren@apple.comfbf6d9a2011-10-19 02:54:29 +000044{
msaboff@apple.com6e74e922012-04-27 23:51:17 +000045 ASSERT(m_index == JSRopeString::s_maxInternalRopeLength);
ggaren@apple.comfbf6d9a2011-10-19 02:54:29 +000046 JSString* jsString = m_jsString;
fpizlo@apple.com75104a32014-04-15 23:33:11 +000047 RELEASE_ASSERT(jsString);
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +000048 m_jsString = jsStringBuilder(&m_vm);
ggaren@apple.comffbe44d2011-10-19 19:45:35 +000049 m_index = 0;
ggaren@apple.comfbf6d9a2011-10-19 02:54:29 +000050 append(jsString);
51}
52
mhahnenberg@apple.comc58d54d2011-12-16 19:06:44 +000053void JSString::destroy(JSCell* cell)
ggaren@apple.comfbf6d9a2011-10-19 02:54:29 +000054{
ggaren@apple.com72da8112012-05-26 22:40:46 +000055 JSString* thisObject = static_cast<JSString*>(cell);
mhahnenberg@apple.comc58d54d2011-12-16 19:06:44 +000056 thisObject->JSString::~JSString();
ggaren@apple.comfbf6d9a2011-10-19 02:54:29 +000057}
58
mhahnenberg@apple.com040ef242014-04-05 20:05:04 +000059void JSString::dumpToStream(const JSCell* cell, PrintStream& out)
60{
61 const JSString* thisObject = jsCast<const JSString*>(cell);
akling@apple.com63e35432014-05-05 06:24:44 +000062 out.printf("<%p, %s, [%u], ", thisObject, thisObject->className(), thisObject->length());
mhahnenberg@apple.com040ef242014-04-05 20:05:04 +000063 if (thisObject->isRope())
64 out.printf("[rope]");
65 else {
66 WTF::StringImpl* ourImpl = thisObject->m_value.impl();
67 if (ourImpl->is8Bit())
68 out.printf("[8 %p]", ourImpl->characters8());
69 else
70 out.printf("[16 %p]", ourImpl->characters16());
71 }
72 out.printf(">");
73}
74
mark.lam@apple.com0c264962016-08-15 21:52:22 +000075bool JSString::equalSlowCase(ExecState* exec, JSString* other) const
76{
77 String str1 = value(exec);
78 String str2 = other->value(exec);
79 if (exec->hadException())
80 return false;
81 return WTF::equal(*str1.impl(), *str2.impl());
82}
83
commit-queue@webkit.org00eb52f2016-03-01 02:07:12 +000084size_t JSString::estimatedSize(JSCell* cell)
85{
86 JSString* thisObject = jsCast<JSString*>(cell);
87 if (thisObject->isRope())
88 return Base::estimatedSize(cell);
89 return Base::estimatedSize(cell) + thisObject->m_value.impl()->costDuringGC();
90}
91
ggaren@apple.comfbf6d9a2011-10-19 02:54:29 +000092void JSString::visitChildren(JSCell* cell, SlotVisitor& visitor)
93{
mhahnenberg@apple.com135f0512011-11-11 20:40:10 +000094 JSString* thisObject = jsCast<JSString*>(cell);
ggaren@apple.comfbf6d9a2011-10-19 02:54:29 +000095 Base::visitChildren(thisObject, visitor);
msaboff@apple.com6e74e922012-04-27 23:51:17 +000096
97 if (thisObject->isRope())
98 static_cast<JSRopeString*>(thisObject)->visitFibers(visitor);
oliver@apple.com8cebf372013-07-25 04:03:46 +000099 else {
100 StringImpl* impl = thisObject->m_value.impl();
101 ASSERT(impl);
fpizlo@apple.com3cb36ea2015-10-05 19:35:32 +0000102 visitor.reportExtraMemoryVisited(impl->costDuringGC());
oliver@apple.com8cebf372013-07-25 04:03:46 +0000103 }
ggaren@apple.comfbf6d9a2011-10-19 02:54:29 +0000104}
105
msaboff@apple.com6e74e922012-04-27 23:51:17 +0000106void JSRopeString::visitFibers(SlotVisitor& visitor)
107{
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000108 if (isSubstring()) {
109 visitor.append(&substringBase());
110 return;
111 }
112 for (size_t i = 0; i < s_maxInternalRopeLength && fiber(i); ++i)
113 visitor.append(&fiber(i));
msaboff@apple.com6e74e922012-04-27 23:51:17 +0000114}
115
akling@apple.com63e35432014-05-05 06:24:44 +0000116static const unsigned maxLengthForOnStackResolve = 2048;
117
118void JSRopeString::resolveRopeInternal8(LChar* buffer) const
119{
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000120 if (isSubstring()) {
121 StringImpl::copyChars(
122 buffer, substringBase()->m_value.characters8() + substringOffset(), m_length);
123 return;
124 }
125
126 resolveRopeInternal8NoSubstring(buffer);
127}
128
129void JSRopeString::resolveRopeInternal8NoSubstring(LChar* buffer) const
130{
131 for (size_t i = 0; i < s_maxInternalRopeLength && fiber(i); ++i) {
132 if (fiber(i)->isRope()) {
akling@apple.com63e35432014-05-05 06:24:44 +0000133 resolveRopeSlowCase8(buffer);
134 return;
135 }
136 }
137
138 LChar* position = buffer;
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000139 for (size_t i = 0; i < s_maxInternalRopeLength && fiber(i); ++i) {
140 const StringImpl& fiberString = *fiber(i)->m_value.impl();
akling@apple.com63e35432014-05-05 06:24:44 +0000141 unsigned length = fiberString.length();
142 StringImpl::copyChars(position, fiberString.characters8(), length);
143 position += length;
144 }
145 ASSERT((buffer + m_length) == position);
146}
147
148void JSRopeString::resolveRopeInternal16(UChar* buffer) const
149{
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000150 if (isSubstring()) {
151 StringImpl::copyChars(
152 buffer, substringBase()->m_value.characters16() + substringOffset(), m_length);
153 return;
154 }
155
156 resolveRopeInternal16NoSubstring(buffer);
157}
158
159void JSRopeString::resolveRopeInternal16NoSubstring(UChar* buffer) const
160{
161 for (size_t i = 0; i < s_maxInternalRopeLength && fiber(i); ++i) {
162 if (fiber(i)->isRope()) {
akling@apple.com63e35432014-05-05 06:24:44 +0000163 resolveRopeSlowCase(buffer);
164 return;
165 }
166 }
167
168 UChar* position = buffer;
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000169 for (size_t i = 0; i < s_maxInternalRopeLength && fiber(i); ++i) {
170 const StringImpl& fiberString = *fiber(i)->m_value.impl();
akling@apple.com63e35432014-05-05 06:24:44 +0000171 unsigned length = fiberString.length();
172 if (fiberString.is8Bit())
173 StringImpl::copyChars(position, fiberString.characters8(), length);
174 else
175 StringImpl::copyChars(position, fiberString.characters16(), length);
176 position += length;
177 }
178 ASSERT((buffer + m_length) == position);
179}
180
181void JSRopeString::resolveRopeToAtomicString(ExecState* exec) const
182{
183 if (m_length > maxLengthForOnStackResolve) {
184 resolveRope(exec);
185 m_value = AtomicString(m_value);
akling@apple.coma8c49de2014-08-18 21:33:01 +0000186 setIs8Bit(m_value.impl()->is8Bit());
akling@apple.com63e35432014-05-05 06:24:44 +0000187 return;
188 }
189
190 if (is8Bit()) {
191 LChar buffer[maxLengthForOnStackResolve];
192 resolveRopeInternal8(buffer);
193 m_value = AtomicString(buffer, m_length);
akling@apple.coma8c49de2014-08-18 21:33:01 +0000194 setIs8Bit(m_value.impl()->is8Bit());
akling@apple.com63e35432014-05-05 06:24:44 +0000195 } else {
196 UChar buffer[maxLengthForOnStackResolve];
197 resolveRopeInternal16(buffer);
198 m_value = AtomicString(buffer, m_length);
akling@apple.coma8c49de2014-08-18 21:33:01 +0000199 setIs8Bit(m_value.impl()->is8Bit());
akling@apple.com63e35432014-05-05 06:24:44 +0000200 }
201
202 clearFibers();
203
204 // If we resolved a string that didn't previously exist, notify the heap that we've grown.
205 if (m_value.impl()->hasOneRef())
ggaren@apple.come2ebb8c2015-03-11 21:29:57 +0000206 Heap::heap(this)->reportExtraMemoryAllocated(m_value.impl()->cost());
akling@apple.com63e35432014-05-05 06:24:44 +0000207}
208
209void JSRopeString::clearFibers() const
210{
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000211 for (size_t i = 0; i < s_maxInternalRopeLength; ++i)
212 u[i].number = 0;
akling@apple.com63e35432014-05-05 06:24:44 +0000213}
214
utatane.tea@gmail.come0741fb2015-06-02 17:36:16 +0000215RefPtr<AtomicStringImpl> JSRopeString::resolveRopeToExistingAtomicString(ExecState* exec) const
akling@apple.com63e35432014-05-05 06:24:44 +0000216{
217 if (m_length > maxLengthForOnStackResolve) {
218 resolveRope(exec);
utatane.tea@gmail.come0741fb2015-06-02 17:36:16 +0000219 if (RefPtr<AtomicStringImpl> existingAtomicString = AtomicStringImpl::lookUp(m_value.impl())) {
akling@apple.com63e35432014-05-05 06:24:44 +0000220 m_value = *existingAtomicString;
akling@apple.coma8c49de2014-08-18 21:33:01 +0000221 setIs8Bit(m_value.impl()->is8Bit());
akling@apple.com63e35432014-05-05 06:24:44 +0000222 clearFibers();
223 return existingAtomicString;
224 }
225 return nullptr;
226 }
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000227
akling@apple.com63e35432014-05-05 06:24:44 +0000228 if (is8Bit()) {
229 LChar buffer[maxLengthForOnStackResolve];
230 resolveRopeInternal8(buffer);
utatane.tea@gmail.come0741fb2015-06-02 17:36:16 +0000231 if (RefPtr<AtomicStringImpl> existingAtomicString = AtomicStringImpl::lookUp(buffer, m_length)) {
akling@apple.com63e35432014-05-05 06:24:44 +0000232 m_value = *existingAtomicString;
akling@apple.coma8c49de2014-08-18 21:33:01 +0000233 setIs8Bit(m_value.impl()->is8Bit());
akling@apple.com63e35432014-05-05 06:24:44 +0000234 clearFibers();
235 return existingAtomicString;
236 }
237 } else {
238 UChar buffer[maxLengthForOnStackResolve];
239 resolveRopeInternal16(buffer);
utatane.tea@gmail.come0741fb2015-06-02 17:36:16 +0000240 if (RefPtr<AtomicStringImpl> existingAtomicString = AtomicStringImpl::lookUp(buffer, m_length)) {
akling@apple.com63e35432014-05-05 06:24:44 +0000241 m_value = *existingAtomicString;
akling@apple.coma8c49de2014-08-18 21:33:01 +0000242 setIs8Bit(m_value.impl()->is8Bit());
akling@apple.com63e35432014-05-05 06:24:44 +0000243 clearFibers();
244 return existingAtomicString;
245 }
246 }
247
248 return nullptr;
249}
250
msaboff@apple.com6e74e922012-04-27 23:51:17 +0000251void JSRopeString::resolveRope(ExecState* exec) const
msaboff@apple.com8cae2b12011-04-21 17:23:16 +0000252{
253 ASSERT(isRope());
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000254
255 if (isSubstring()) {
256 ASSERT(!substringBase()->isRope());
akling@apple.com46f3fe32016-02-18 17:25:42 +0000257 m_value = substringBase()->m_value.substringSharingImpl(substringOffset(), m_length);
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000258 substringBase().clear();
259 return;
260 }
261
msaboff@apple.com203e7852011-11-14 23:51:06 +0000262 if (is8Bit()) {
263 LChar* buffer;
krollin@apple.com19cde092016-06-08 01:31:17 +0000264 if (auto newImpl = StringImpl::tryCreateUninitialized(m_length, buffer)) {
ggaren@apple.come2ebb8c2015-03-11 21:29:57 +0000265 Heap::heap(this)->reportExtraMemoryAllocated(newImpl->cost());
krollin@apple.com19cde092016-06-08 01:31:17 +0000266 m_value = WTFMove(newImpl);
commit-queue@webkit.org1a15efe2012-02-28 16:02:02 +0000267 } else {
msaboff@apple.com203e7852011-11-14 23:51:06 +0000268 outOfMemory(exec);
269 return;
270 }
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000271 resolveRopeInternal8NoSubstring(buffer);
akling@apple.com63e35432014-05-05 06:24:44 +0000272 clearFibers();
msaboff@apple.com203e7852011-11-14 23:51:06 +0000273 ASSERT(!isRope());
msaboff@apple.com203e7852011-11-14 23:51:06 +0000274 return;
275 }
276
msaboff@apple.com8cae2b12011-04-21 17:23:16 +0000277 UChar* buffer;
krollin@apple.com19cde092016-06-08 01:31:17 +0000278 if (auto newImpl = StringImpl::tryCreateUninitialized(m_length, buffer)) {
ggaren@apple.come2ebb8c2015-03-11 21:29:57 +0000279 Heap::heap(this)->reportExtraMemoryAllocated(newImpl->cost());
krollin@apple.com19cde092016-06-08 01:31:17 +0000280 m_value = WTFMove(newImpl);
commit-queue@webkit.org1a15efe2012-02-28 16:02:02 +0000281 } else {
msaboff@apple.com8cae2b12011-04-21 17:23:16 +0000282 outOfMemory(exec);
283 return;
284 }
285
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000286 resolveRopeInternal16NoSubstring(buffer);
akling@apple.com63e35432014-05-05 06:24:44 +0000287 clearFibers();
msaboff@apple.com8cae2b12011-04-21 17:23:16 +0000288 ASSERT(!isRope());
289}
290
msaboff@apple.com203e7852011-11-14 23:51:06 +0000291// Overview: These functions convert a JSString from holding a string in rope form
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +0000292// down to a simple String representation. It does so by building up the string
barraclough@apple.com35d680c2009-12-04 02:15:18 +0000293// backwards, since we want to avoid recursion, we expect that the tree structure
294// representing the rope is likely imbalanced with more nodes down the left side
295// (since appending to the string is likely more common) - and as such resolving
296// in this fashion should minimize work queue size. (If we built the queue forwards
barraclough@apple.com4d95c9e2010-08-10 22:32:19 +0000297// we would likely have to place all of the constituent StringImpls into the
barraclough@apple.com35d680c2009-12-04 02:15:18 +0000298// Vector before performing any concatenation, but by working backwards we likely
299// only fill the queue with the number of substrings at any given level in a
msaboff@apple.com8cae2b12011-04-21 17:23:16 +0000300// rope-of-ropes.)
msaboff@apple.com6e74e922012-04-27 23:51:17 +0000301void JSRopeString::resolveRopeSlowCase8(LChar* buffer) const
barraclough@apple.com35d680c2009-12-04 02:15:18 +0000302{
msaboff@apple.com203e7852011-11-14 23:51:06 +0000303 LChar* position = buffer + m_length; // We will be working backwards over the rope.
oliver@apple.com4e3f9652013-04-08 04:14:50 +0000304 Vector<JSString*, 32, UnsafeVectorOverflow> workQueue; // Putting strings into a Vector is only OK because there are no GC points in this method.
ggaren@apple.comffbe44d2011-10-19 19:45:35 +0000305
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000306 for (size_t i = 0; i < s_maxInternalRopeLength && fiber(i); ++i)
307 workQueue.append(fiber(i).get());
ggaren@apple.comffbe44d2011-10-19 19:45:35 +0000308
309 while (!workQueue.isEmpty()) {
310 JSString* currentFiber = workQueue.last();
311 workQueue.removeLast();
akling@apple.com77ee6bf2014-05-05 06:10:03 +0000312
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000313 const LChar* characters;
314
ggaren@apple.comfbf6d9a2011-10-19 02:54:29 +0000315 if (currentFiber->isRope()) {
msaboff@apple.com6e74e922012-04-27 23:51:17 +0000316 JSRopeString* currentFiberAsRope = static_cast<JSRopeString*>(currentFiber);
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000317 if (!currentFiberAsRope->isSubstring()) {
318 for (size_t i = 0; i < s_maxInternalRopeLength && currentFiberAsRope->fiber(i); ++i)
319 workQueue.append(currentFiberAsRope->fiber(i).get());
320 continue;
321 }
322 ASSERT(!currentFiberAsRope->substringBase()->isRope());
323 characters =
324 currentFiberAsRope->substringBase()->m_value.characters8() +
325 currentFiberAsRope->substringOffset();
326 } else
327 characters = currentFiber->m_value.characters8();
328
329 unsigned length = currentFiber->length();
ggaren@apple.comffbe44d2011-10-19 19:45:35 +0000330 position -= length;
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000331 StringImpl::copyChars(position, characters, length);
msaboff@apple.com203e7852011-11-14 23:51:06 +0000332 }
333
334 ASSERT(buffer == position);
msaboff@apple.com203e7852011-11-14 23:51:06 +0000335}
336
msaboff@apple.com6e74e922012-04-27 23:51:17 +0000337void JSRopeString::resolveRopeSlowCase(UChar* buffer) const
msaboff@apple.com203e7852011-11-14 23:51:06 +0000338{
msaboff@apple.com203e7852011-11-14 23:51:06 +0000339 UChar* position = buffer + m_length; // We will be working backwards over the rope.
oliver@apple.com4e3f9652013-04-08 04:14:50 +0000340 Vector<JSString*, 32, UnsafeVectorOverflow> workQueue; // These strings are kept alive by the parent rope, so using a Vector is OK.
msaboff@apple.com203e7852011-11-14 23:51:06 +0000341
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000342 for (size_t i = 0; i < s_maxInternalRopeLength && fiber(i); ++i)
343 workQueue.append(fiber(i).get());
msaboff@apple.com203e7852011-11-14 23:51:06 +0000344
345 while (!workQueue.isEmpty()) {
346 JSString* currentFiber = workQueue.last();
347 workQueue.removeLast();
348
349 if (currentFiber->isRope()) {
msaboff@apple.com6e74e922012-04-27 23:51:17 +0000350 JSRopeString* currentFiberAsRope = static_cast<JSRopeString*>(currentFiber);
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000351 if (currentFiberAsRope->isSubstring()) {
352 ASSERT(!currentFiberAsRope->substringBase()->isRope());
353 StringImpl* string = static_cast<StringImpl*>(
354 currentFiberAsRope->substringBase()->m_value.impl());
355 unsigned offset = currentFiberAsRope->substringOffset();
356 unsigned length = currentFiberAsRope->length();
357 position -= length;
358 if (string->is8Bit())
359 StringImpl::copyChars(position, string->characters8() + offset, length);
360 else
361 StringImpl::copyChars(position, string->characters16() + offset, length);
362 continue;
363 }
364 for (size_t i = 0; i < s_maxInternalRopeLength && currentFiberAsRope->fiber(i); ++i)
365 workQueue.append(currentFiberAsRope->fiber(i).get());
msaboff@apple.com203e7852011-11-14 23:51:06 +0000366 continue;
367 }
368
369 StringImpl* string = static_cast<StringImpl*>(currentFiber->m_value.impl());
370 unsigned length = string->length();
371 position -= length;
msaboff@apple.comf25bc162012-09-07 01:29:12 +0000372 if (string->is8Bit())
373 StringImpl::copyChars(position, string->characters8(), length);
374 else
375 StringImpl::copyChars(position, string->characters16(), length);
barraclough@apple.com35d680c2009-12-04 02:15:18 +0000376 }
ggaren@apple.comffbe44d2011-10-19 19:45:35 +0000377
378 ASSERT(buffer == position);
barraclough@apple.com35d680c2009-12-04 02:15:18 +0000379}
msaboff@apple.com8cae2b12011-04-21 17:23:16 +0000380
msaboff@apple.com6e74e922012-04-27 23:51:17 +0000381void JSRopeString::outOfMemory(ExecState* exec) const
msaboff@apple.com8cae2b12011-04-21 17:23:16 +0000382{
akling@apple.com63e35432014-05-05 06:24:44 +0000383 clearFibers();
commit-queue@webkit.org7914d5a2012-02-23 19:29:14 +0000384 ASSERT(isRope());
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +0000385 ASSERT(m_value.isNull());
msaboff@apple.com8cae2b12011-04-21 17:23:16 +0000386 if (exec)
387 throwOutOfMemoryError(exec);
388}
389
ggaren@apple.comdc067b62009-05-01 22:43:39 +0000390JSValue JSString::toPrimitive(ExecState*, PreferredPrimitiveType) const
weinig@apple.comefdce0f2008-06-30 20:52:03 +0000391{
weinig@apple.com2947a912008-07-07 02:49:29 +0000392 return const_cast<JSString*>(this);
weinig@apple.comefdce0f2008-06-30 20:52:03 +0000393}
394
mhahnenberg@apple.com061133e2011-09-27 19:53:49 +0000395bool JSString::getPrimitiveNumber(ExecState* exec, double& number, JSValue& result) const
weinig@apple.comefdce0f2008-06-30 20:52:03 +0000396{
barraclough@apple.com35d680c2009-12-04 02:15:18 +0000397 result = this;
akling@apple.comc115b372015-12-19 02:32:46 +0000398 number = jsToNumber(unsafeView(*exec));
weinig@apple.comefdce0f2008-06-30 20:52:03 +0000399 return false;
400}
401
barraclough@apple.comb749f0b2009-12-07 23:14:04 +0000402double JSString::toNumber(ExecState* exec) const
weinig@apple.comefdce0f2008-06-30 20:52:03 +0000403{
akling@apple.comc115b372015-12-19 02:32:46 +0000404 return jsToNumber(unsafeView(*exec));
weinig@apple.comefdce0f2008-06-30 20:52:03 +0000405}
406
akling@apple.com019809c2013-10-06 18:16:48 +0000407inline StringObject* StringObject::create(VM& vm, JSGlobalObject* globalObject, JSString* string)
weinig@apple.comefdce0f2008-06-30 20:52:03 +0000408{
akling@apple.com019809c2013-10-06 18:16:48 +0000409 StringObject* object = new (NotNull, allocateCell<StringObject>(vm.heap)) StringObject(vm, globalObject->stringObjectStructure());
410 object->finishCreation(vm, string);
mhahnenberg@apple.com7317a7f2011-09-09 21:43:14 +0000411 return object;
weinig@apple.comefdce0f2008-06-30 20:52:03 +0000412}
413
oliver@apple.com3b6dc572011-03-28 23:39:16 +0000414JSObject* JSString::toObject(ExecState* exec, JSGlobalObject* globalObject) const
weinig@apple.comefdce0f2008-06-30 20:52:03 +0000415{
akling@apple.com019809c2013-10-06 18:16:48 +0000416 return StringObject::create(exec->vm(), globalObject, const_cast<JSString*>(this));
weinig@apple.comefdce0f2008-06-30 20:52:03 +0000417}
418
oliver@apple.come2fe4ce2013-07-25 03:59:41 +0000419JSValue JSString::toThis(JSCell* cell, ExecState* exec, ECMAMode ecmaMode)
weinig@apple.comefdce0f2008-06-30 20:52:03 +0000420{
oliver@apple.come2fe4ce2013-07-25 03:59:41 +0000421 if (ecmaMode == StrictMode)
422 return cell;
akling@apple.com019809c2013-10-06 18:16:48 +0000423 return StringObject::create(exec->vm(), exec->lexicalGlobalObject(), jsCast<JSString*>(cell));
weinig@apple.comefdce0f2008-06-30 20:52:03 +0000424}
425
barraclough@apple.com38d3c752012-05-12 00:39:43 +0000426bool JSString::getStringPropertyDescriptor(ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor)
oliver@apple.com4b4f7852009-08-26 16:52:15 +0000427{
428 if (propertyName == exec->propertyNames().length) {
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000429 descriptor.setDescriptor(jsNumber(m_length), DontEnum | DontDelete | ReadOnly);
oliver@apple.com4b4f7852009-08-26 16:52:15 +0000430 return true;
431 }
432
utatane.tea@gmail.comc7c203c2015-04-06 12:40:33 +0000433 Optional<uint32_t> index = parseIndex(propertyName);
434 if (index && index.value() < m_length) {
435 descriptor.setDescriptor(getIndex(exec, index.value()), DontDelete | ReadOnly);
oliver@apple.com4b4f7852009-08-26 16:52:15 +0000436 return true;
437 }
438
439 return false;
440}
441
akling@apple.comc3e85a62014-07-05 03:36:36 +0000442JSString* jsStringWithCacheSlowCase(VM& vm, StringImpl& stringImpl)
443{
akling@apple.com926b1102015-03-10 00:09:39 +0000444 if (JSString* string = vm.stringCache.get(&stringImpl))
445 return string;
446
447 JSString* string = jsString(&vm, String(stringImpl));
448 vm.lastCachedString.set(vm, string);
449 return string;
akling@apple.comc3e85a62014-07-05 03:36:36 +0000450}
451
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +0000452} // namespace JSC