c032b8b0d28e1d3a085992998788bd32d9772f21
[WebKit-https.git] / Source / JavaScriptCore / runtime / StringObject.cpp
1 /*
2  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  *
19  */
20
21 #include "config.h"
22 #include "StringObject.h"
23
24 #include "Error.h"
25 #include "JSGlobalObject.h"
26 #include "Operations.h"
27 #include "PropertyNameArray.h"
28
29 namespace JSC {
30
31 ASSERT_HAS_TRIVIAL_DESTRUCTOR(StringObject);
32
33 const ClassInfo StringObject::s_info = { "String", &JSWrapperObject::s_info, 0, 0, CREATE_METHOD_TABLE(StringObject) };
34
35 StringObject::StringObject(VM& vm, Structure* structure)
36     : JSWrapperObject(vm, structure)
37 {
38 }
39
40 void StringObject::finishCreation(VM& vm, JSString* string)
41 {
42     Base::finishCreation(vm);
43     ASSERT(inherits(&s_info));
44     setInternalValue(vm, string);
45 }
46
47 bool StringObject::getOwnPropertySlot(JSObject* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
48 {
49     StringObject* thisObject = jsCast<StringObject*>(cell);
50     if (thisObject->internalValue()->getStringPropertySlot(exec, propertyName, slot))
51         return true;
52     return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
53 }
54     
55 bool StringObject::getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned propertyName, PropertySlot& slot)
56 {
57     StringObject* thisObject = jsCast<StringObject*>(object);
58     if (thisObject->internalValue()->getStringPropertySlot(exec, propertyName, slot))
59         return true;    
60     return JSObject::getOwnPropertySlot(thisObject, exec, Identifier::from(exec, propertyName), slot);
61 }
62
63 bool StringObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor)
64 {
65     StringObject* thisObject = jsCast<StringObject*>(object);
66     if (thisObject->internalValue()->getStringPropertyDescriptor(exec, propertyName, descriptor))
67         return true;    
68     return JSObject::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
69 }
70
71 void StringObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
72 {
73     if (propertyName == exec->propertyNames().length) {
74         if (slot.isStrictMode())
75             throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
76         return;
77     }
78     JSObject::put(cell, exec, propertyName, value, slot);
79 }
80
81 void StringObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)
82 {
83     StringObject* thisObject = jsCast<StringObject*>(cell);
84     if (thisObject->internalValue()->canGetIndex(propertyName)) {
85         if (shouldThrow)
86             throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
87         return;
88     }
89     JSObject::putByIndex(cell, exec, propertyName, value, shouldThrow);
90 }
91
92 bool StringObject::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor, bool throwException)
93 {
94     StringObject* thisObject = jsCast<StringObject*>(object);
95
96     if (propertyName == exec->propertyNames().length) {
97         if (!object->isExtensible()) {
98             if (throwException)
99                 throwError(exec, createTypeError(exec, ASCIILiteral("Attempting to define property on object that is not extensible.")));
100             return false;
101         }
102         if (descriptor.configurablePresent() && descriptor.configurable()) {
103             if (throwException)
104                 throwError(exec, createTypeError(exec, ASCIILiteral("Attempting to configurable attribute of unconfigurable property.")));
105             return false;
106         }
107         if (descriptor.enumerablePresent() && descriptor.enumerable()) {
108             if (throwException)
109                 throwError(exec, createTypeError(exec, ASCIILiteral("Attempting to change enumerable attribute of unconfigurable property.")));
110             return false;
111         }
112         if (descriptor.isAccessorDescriptor()) {
113             if (throwException)
114                 throwError(exec, createTypeError(exec, ASCIILiteral("Attempting to change access mechanism for an unconfigurable property.")));
115             return false;
116         }
117         if (descriptor.writablePresent() && descriptor.writable()) {
118             if (throwException)
119                 throwError(exec, createTypeError(exec, ASCIILiteral("Attempting to change writable attribute of unconfigurable property.")));
120             return false;
121         }
122         if (!descriptor.value())
123             return true;
124         if (propertyName == exec->propertyNames().length && sameValue(exec, descriptor.value(), jsNumber(thisObject->internalValue()->length())))
125             return true;
126         if (throwException)
127             throwError(exec, createTypeError(exec, ASCIILiteral("Attempting to change value of a readonly property.")));
128         return false;
129     }
130
131     return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
132 }
133
134 bool StringObject::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
135 {
136     StringObject* thisObject = jsCast<StringObject*>(cell);
137     if (propertyName == exec->propertyNames().length)
138         return false;
139     unsigned i = propertyName.asIndex();
140     if (thisObject->internalValue()->canGetIndex(i)) {
141         ASSERT(i != PropertyName::NotAnIndex); // No need for an explicit check, the above test would always fail!
142         return false;
143     }
144     return JSObject::deleteProperty(thisObject, exec, propertyName);
145 }
146
147 bool StringObject::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i)
148 {
149     StringObject* thisObject = jsCast<StringObject*>(cell);
150     if (thisObject->internalValue()->canGetIndex(i))
151         return false;
152     return JSObject::deletePropertyByIndex(thisObject, exec, i);
153 }
154
155 void StringObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
156 {
157     StringObject* thisObject = jsCast<StringObject*>(object);
158     int size = thisObject->internalValue()->length();
159     for (int i = 0; i < size; ++i)
160         propertyNames.add(Identifier(exec, String::number(i)));
161     if (mode == IncludeDontEnumProperties)
162         propertyNames.add(exec->propertyNames().length);
163     return JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
164 }
165
166 StringObject* constructString(ExecState* exec, JSGlobalObject* globalObject, JSValue string)
167 {
168     StringObject* object = StringObject::create(exec, globalObject->stringObjectStructure());
169     object->setInternalValue(exec->vm(), string);
170     return object;
171 }
172
173 } // namespace JSC