18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2001 Peter Kelly (pmk@post.com) 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2004, 2007, 2008 Apple Inc. All rights reserved. 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is free software; you can redistribute it and/or 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modify it under the terms of the GNU Library General Public 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License as published by the Free Software Foundation; either 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version 2 of the License, or (at your option) any later version. 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is distributed in the hope that it will be useful, 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Library General Public License for more details. 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * You should have received a copy of the GNU Library General Public License 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * along with this library; see the file COPYING.LIB. If not, write to 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Boston, MA 02110-1301, USA. 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "JSString.h" 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "JSGlobalObject.h" 27f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick#include "JSGlobalObjectFunctions.h" 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "JSObject.h" 29643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include "Operations.h" 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "StringObject.h" 318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "StringPrototype.h" 328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace JSC { 34f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 35f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochstatic const unsigned substringFromRopeCutoff = 4; 368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 37643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// Overview: this methods converts a JSString from holding a string in rope form 38643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// down to a simple UString representation. It does so by building up the string 39643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// backwards, since we want to avoid recursion, we expect that the tree structure 40643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// representing the rope is likely imbalanced with more nodes down the left side 41643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// (since appending to the string is likely more common) - and as such resolving 42643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// in this fashion should minimize work queue size. (If we built the queue forwards 43f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick// we would likely have to place all of the constituent StringImpls into the 44643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// Vector before performing any concatenation, but by working backwards we likely 45643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// only fill the queue with the number of substrings at any given level in a 46643ca7872b450ea4efacab6188849e5aac2ba161Steve Block// rope-of-ropes.) 47643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid JSString::resolveRope(ExecState* exec) const 48643ca7872b450ea4efacab6188849e5aac2ba161Steve Block{ 49643ca7872b450ea4efacab6188849e5aac2ba161Steve Block ASSERT(isRope()); 50643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 51643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Allocate the buffer to hold the final string, position initially points to the end. 52643ca7872b450ea4efacab6188849e5aac2ba161Steve Block UChar* buffer; 53f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (PassRefPtr<StringImpl> newImpl = StringImpl::tryCreateUninitialized(m_length, buffer)) 54d0825bca7fe65beaee391d30da42e937db621564Steve Block m_value = newImpl; 55d0825bca7fe65beaee391d30da42e937db621564Steve Block else { 56692e5dbf12901edacf14812a6fae25462920af42Steve Block for (unsigned i = 0; i < m_fiberCount; ++i) { 57dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RopeImpl::deref(m_other.m_fibers[i]); 58692e5dbf12901edacf14812a6fae25462920af42Steve Block m_other.m_fibers[i] = 0; 59d0825bca7fe65beaee391d30da42e937db621564Steve Block } 60692e5dbf12901edacf14812a6fae25462920af42Steve Block m_fiberCount = 0; 61643ca7872b450ea4efacab6188849e5aac2ba161Steve Block ASSERT(!isRope()); 62643ca7872b450ea4efacab6188849e5aac2ba161Steve Block ASSERT(m_value == UString()); 63e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block if (exec) 64e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block throwOutOfMemoryError(exec); 65643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return; 66643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 67692e5dbf12901edacf14812a6fae25462920af42Steve Block UChar* position = buffer + m_length; 68643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 69dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // Start with the current RopeImpl. 70dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block Vector<RopeImpl::Fiber, 32> workQueue; 71dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RopeImpl::Fiber currentFiber; 72692e5dbf12901edacf14812a6fae25462920af42Steve Block for (unsigned i = 0; i < (m_fiberCount - 1); ++i) 73692e5dbf12901edacf14812a6fae25462920af42Steve Block workQueue.append(m_other.m_fibers[i]); 74692e5dbf12901edacf14812a6fae25462920af42Steve Block currentFiber = m_other.m_fibers[m_fiberCount - 1]; 75643ca7872b450ea4efacab6188849e5aac2ba161Steve Block while (true) { 76dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (RopeImpl::isRope(currentFiber)) { 77dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RopeImpl* rope = static_cast<RopeImpl*>(currentFiber); 78643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Copy the contents of the current rope into the workQueue, with the last item in 'currentFiber' 79643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // (we will be working backwards over the rope). 80692e5dbf12901edacf14812a6fae25462920af42Steve Block unsigned fiberCountMinusOne = rope->fiberCount() - 1; 81692e5dbf12901edacf14812a6fae25462920af42Steve Block for (unsigned i = 0; i < fiberCountMinusOne; ++i) 826c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen workQueue.append(rope->fibers()[i]); 836c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen currentFiber = rope->fibers()[fiberCountMinusOne]; 84643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } else { 85f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick StringImpl* string = static_cast<StringImpl*>(currentFiber); 86692e5dbf12901edacf14812a6fae25462920af42Steve Block unsigned length = string->length(); 87643ca7872b450ea4efacab6188849e5aac2ba161Steve Block position -= length; 88f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick StringImpl::copyChars(position, string->characters(), length); 89643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 90643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Was this the last item in the work queue? 91643ca7872b450ea4efacab6188849e5aac2ba161Steve Block if (workQueue.isEmpty()) { 92643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Create a string from the UChar buffer, clear the rope RefPtr. 93643ca7872b450ea4efacab6188849e5aac2ba161Steve Block ASSERT(buffer == position); 94692e5dbf12901edacf14812a6fae25462920af42Steve Block for (unsigned i = 0; i < m_fiberCount; ++i) { 95dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block RopeImpl::deref(m_other.m_fibers[i]); 96692e5dbf12901edacf14812a6fae25462920af42Steve Block m_other.m_fibers[i] = 0; 97d0825bca7fe65beaee391d30da42e937db621564Steve Block } 98692e5dbf12901edacf14812a6fae25462920af42Steve Block m_fiberCount = 0; 99643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 100643ca7872b450ea4efacab6188849e5aac2ba161Steve Block ASSERT(!isRope()); 101643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return; 102643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 103643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 104643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // No! - set the next item up to process. 105643ca7872b450ea4efacab6188849e5aac2ba161Steve Block currentFiber = workQueue.last(); 106643ca7872b450ea4efacab6188849e5aac2ba161Steve Block workQueue.removeLast(); 107643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 108643ca7872b450ea4efacab6188849e5aac2ba161Steve Block } 109643ca7872b450ea4efacab6188849e5aac2ba161Steve Block} 110f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 111f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// This function construsts a substring out of a rope without flattening by reusing the existing fibers. 112f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// This can reduce memory usage substantially. Since traversing ropes is slow the function will revert 113f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// back to flattening if the rope turns out to be long. 114f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochJSString* JSString::substringFromRope(ExecState* exec, unsigned substringStart, unsigned substringLength) 115f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 116f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT(isRope()); 117f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT(substringLength); 118f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 119f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch JSGlobalData* globalData = &exec->globalData(); 120f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 121f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch UString substringFibers[3]; 122f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 123f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch unsigned fiberCount = 0; 124f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch unsigned substringFiberCount = 0; 125f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch unsigned substringEnd = substringStart + substringLength; 126f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch unsigned fiberEnd = 0; 127f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 128f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch RopeIterator end; 129f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch for (RopeIterator it(m_other.m_fibers.data(), m_fiberCount); it != end; ++it) { 130f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ++fiberCount; 131f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch StringImpl* fiberString = *it; 132f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch unsigned fiberStart = fiberEnd; 133f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch fiberEnd = fiberStart + fiberString->length(); 134f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (fiberEnd <= substringStart) 135f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch continue; 136f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch unsigned copyStart = std::max(substringStart, fiberStart); 137f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch unsigned copyEnd = std::min(substringEnd, fiberEnd); 138f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (copyStart == fiberStart && copyEnd == fiberEnd) 139f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch substringFibers[substringFiberCount++] = UString(fiberString); 140f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 141f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch substringFibers[substringFiberCount++] = UString(StringImpl::create(fiberString, copyStart - fiberStart, copyEnd - copyStart)); 142f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (fiberEnd >= substringEnd) 143f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch break; 144f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (fiberCount > substringFromRopeCutoff || substringFiberCount >= 3) { 145f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // This turned out to be a really inefficient rope. Just flatten it. 146f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch resolveRope(exec); 147f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return jsSubstring(&exec->globalData(), m_value, substringStart, substringLength); 148f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 149f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 150f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT(substringFiberCount && substringFiberCount <= 3); 151f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 152f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (substringLength == 1) { 153f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT(substringFiberCount == 1); 154f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch UChar c = substringFibers[0].characters()[0]; 1552bde8e466a4451c7319e3a072d118917957d6554Steve Block if (c <= maxSingleCharacterString) 156f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return globalData->smallStrings.singleCharacterString(globalData, c); 157f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 158f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (substringFiberCount == 1) 159f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return new (globalData) JSString(globalData, substringFibers[0]); 160f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (substringFiberCount == 2) 161f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return new (globalData) JSString(globalData, substringFibers[0], substringFibers[1]); 162f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return new (globalData) JSString(globalData, substringFibers[0], substringFibers[1], substringFibers[2]); 163f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 164643ca7872b450ea4efacab6188849e5aac2ba161Steve Block 1656c2af9490927c3c5959b5cb07461b646f8b32f6cKristian MonsenJSValue JSString::replaceCharacter(ExecState* exec, UChar character, const UString& replacement) 1666c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen{ 1676c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (!isRope()) { 168f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick size_t matchPosition = m_value.find(character); 169f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (matchPosition == notFound) 1706c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen return JSValue(this); 171f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick return jsString(exec, m_value.substringSharingImpl(0, matchPosition), replacement, m_value.substringSharingImpl(matchPosition + 1)); 1726c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen } 1736c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 1746c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen RopeIterator end; 1756c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 1766c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen // Count total fibers and find matching string. 1776c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen size_t fiberCount = 0; 178f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick StringImpl* matchString = 0; 179f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick size_t matchPosition = notFound; 180ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block for (RopeIterator it(m_other.m_fibers.data(), m_fiberCount); it != end; ++it) { 1816c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen ++fiberCount; 1826c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (matchString) 1836c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen continue; 1846c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 185f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick StringImpl* string = *it; 1866c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen matchPosition = string->find(character); 187f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (matchPosition == notFound) 1886c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen continue; 1896c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen matchString = string; 1906c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen } 1916c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 1926c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (!matchString) 1936c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen return this; 1946c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 195f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick RopeBuilder builder(replacement.length() ? fiberCount + 2 : fiberCount + 1); 1966c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (UNLIKELY(builder.isOutOfMemory())) 1976c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen return throwOutOfMemoryError(exec); 1986c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 199ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block for (RopeIterator it(m_other.m_fibers.data(), m_fiberCount); it != end; ++it) { 200f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick StringImpl* string = *it; 2016c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen if (string != matchString) { 2026c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen builder.append(UString(string)); 2036c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen continue; 2046c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen } 2056c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 206f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick builder.append(UString(string).substringSharingImpl(0, matchPosition)); 207f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick if (replacement.length()) 2086c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen builder.append(replacement); 209f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick builder.append(UString(string).substringSharingImpl(matchPosition + 1)); 21006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen matchString = 0; 2116c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen } 2126c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 2136c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen JSGlobalData* globalData = &exec->globalData(); 2146c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen return JSValue(new (globalData) JSString(globalData, builder.release())); 2156c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen} 2166c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen 217dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockJSString* JSString::getIndexSlowCase(ExecState* exec, unsigned i) 218dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{ 219dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block ASSERT(isRope()); 220dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block resolveRope(exec); 221dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block // Return a safe no-value result, this should never be used, since the excetion will be thrown. 222dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block if (exec->exception()) 223dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return jsString(exec, ""); 224dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block ASSERT(!isRope()); 225f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick ASSERT(i < m_value.length()); 226dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block return jsSingleCharacterSubstring(exec, m_value, i); 227dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} 228dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block 2295f1ab04193ad0130ca8204aadaceae083aca9881Feng QianJSValue JSString::toPrimitive(ExecState*, PreferredPrimitiveType) const 2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return const_cast<JSString*>(this); 2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 234643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockbool JSString::getPrimitiveNumber(ExecState* exec, double& number, JSValue& result) 2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 236643ca7872b450ea4efacab6188849e5aac2ba161Steve Block result = this; 237f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick number = jsToNumber(value(exec)); 2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool JSString::toBoolean(ExecState*) const 2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 243692e5dbf12901edacf14812a6fae25462920af42Steve Block return m_length; 2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 246643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockdouble JSString::toNumber(ExecState* exec) const 2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 248f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick return jsToNumber(value(exec)); 2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 251643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockUString JSString::toString(ExecState* exec) const 2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 253643ca7872b450ea4efacab6188849e5aac2ba161Steve Block return value(exec); 2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2562bde8e466a4451c7319e3a072d118917957d6554Steve Blockinline StringObject* StringObject::create(ExecState* exec, JSGlobalObject* globalObject, JSString* string) 2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2582bde8e466a4451c7319e3a072d118917957d6554Steve Block return new (exec) StringObject(exec->globalData(), globalObject->stringObjectStructure(), string); 2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2612bde8e466a4451c7319e3a072d118917957d6554Steve BlockJSObject* JSString::toObject(ExecState* exec, JSGlobalObject* globalObject) const 2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2632bde8e466a4451c7319e3a072d118917957d6554Steve Block return StringObject::create(exec, globalObject, const_cast<JSString*>(this)); 2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectJSObject* JSString::toThisObject(ExecState* exec) const 2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2682bde8e466a4451c7319e3a072d118917957d6554Steve Block return StringObject::create(exec, exec->lexicalGlobalObject(), const_cast<JSString*>(this)); 2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool JSString::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) 2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // The semantics here are really getPropertySlot, not getOwnPropertySlot. 2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // This function should only be called by JSValue::get. 2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (getStringPropertySlot(exec, propertyName, slot)) 2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 2775f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (propertyName == exec->propertyNames().underscoreProto) { 2785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian slot.setValue(exec->lexicalGlobalObject()->stringPrototype()); 2795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return true; 2805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian } 2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project slot.setBase(this); 2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project JSObject* object; 2835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian for (JSValue prototype = exec->lexicalGlobalObject()->stringPrototype(); !prototype.isNull(); prototype = object->prototype()) { 2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project object = asObject(prototype); 2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (object->getOwnPropertySlot(exec, propertyName, slot)) 2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project slot.setUndefined(); 2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 292231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockbool JSString::getStringPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) 293231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 294231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (propertyName == exec->propertyNames().length) { 295e14391e94c850b8bd03680c23b38978db68687a8John Reck descriptor.setDescriptor(jsNumber(m_length), DontEnum | DontDelete | ReadOnly); 296231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return true; 297231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 298231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 299231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block bool isStrictUInt32; 300f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick unsigned i = propertyName.toUInt32(isStrictUInt32); 301692e5dbf12901edacf14812a6fae25462920af42Steve Block if (isStrictUInt32 && i < m_length) { 302dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block descriptor.setDescriptor(getIndex(exec, i), DontDelete | ReadOnly); 303231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return true; 304231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 305231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 306231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return false; 307231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 308231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 309231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockbool JSString::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) 310231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 311231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (getStringPropertyDescriptor(exec, propertyName, descriptor)) 312231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return true; 313231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (propertyName != exec->propertyNames().underscoreProto) 314231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return false; 315231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block descriptor.setDescriptor(exec->lexicalGlobalObject()->stringPrototype(), DontEnum); 316231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return true; 317231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 318231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool JSString::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot) 3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // The semantics here are really getPropertySlot, not getOwnPropertySlot. 3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // This function should only be called by JSValue::get. 3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (getStringPropertySlot(exec, propertyName, slot)) 3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return JSString::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot); 3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace JSC 329