Source/JavaScriptCore: https://bugs.webkit.org/show_bug.cgi?id=119548
[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(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 void StringObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
64 {
65     if (propertyName == exec->propertyNames().length) {
66         if (slot.isStrictMode())
67             throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
68         return;
69     }
70     JSObject::put(cell, exec, propertyName, value, slot);
71 }
72
73 void StringObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)
74 {
75     StringObject* thisObject = jsCast<StringObject*>(cell);
76     if (thisObject->internalValue()->canGetIndex(propertyName)) {
77         if (shouldThrow)
78             throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
79         return;
80     }
81     JSObject::putByIndex(cell, exec, propertyName, value, shouldThrow);
82 }
83
84 bool StringObject::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool throwException)
85 {
86     StringObject* thisObject = jsCast<StringObject*>(object);
87
88     if (propertyName == exec->propertyNames().length) {
89         if (!object->isExtensible()) {
90             if (throwException)
91                 exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to define property on object that is not extensible.")));
92             return false;
93         }
94         if (descriptor.configurablePresent() && descriptor.configurable()) {
95             if (throwException)
96                 exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to configurable attribute of unconfigurable property.")));
97             return false;
98         }
99         if (descriptor.enumerablePresent() && descriptor.enumerable()) {
100             if (throwException)
101                 exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change enumerable attribute of unconfigurable property.")));
102             return false;
103         }
104         if (descriptor.isAccessorDescriptor()) {
105             if (throwException)
106                 exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change access mechanism for an unconfigurable property.")));
107             return false;
108         }
109         if (descriptor.writablePresent() && descriptor.writable()) {
110             if (throwException)
111                 exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change writable attribute of unconfigurable property.")));
112             return false;
113         }
114         if (!descriptor.value())
115             return true;
116         if (propertyName == exec->propertyNames().length && sameValue(exec, descriptor.value(), jsNumber(thisObject->internalValue()->length())))
117             return true;
118         if (throwException)
119             exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change value of a readonly property.")));
120         return false;
121     }
122
123     return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
124 }
125
126 bool StringObject::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
127 {
128     StringObject* thisObject = jsCast<StringObject*>(cell);
129     if (propertyName == exec->propertyNames().length)
130         return false;
131     unsigned i = propertyName.asIndex();
132     if (thisObject->internalValue()->canGetIndex(i)) {
133         ASSERT(i != PropertyName::NotAnIndex); // No need for an explicit check, the above test would always fail!
134         return false;
135     }
136     return JSObject::deleteProperty(thisObject, exec, propertyName);
137 }
138
139 bool StringObject::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i)
140 {
141     StringObject* thisObject = jsCast<StringObject*>(cell);
142     if (thisObject->internalValue()->canGetIndex(i))
143         return false;
144     return JSObject::deletePropertyByIndex(thisObject, exec, i);
145 }
146
147 void StringObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
148 {
149     StringObject* thisObject = jsCast<StringObject*>(object);
150     int size = thisObject->internalValue()->length();
151     for (int i = 0; i < size; ++i)
152         propertyNames.add(Identifier(exec, String::number(i)));
153     if (mode == IncludeDontEnumProperties)
154         propertyNames.add(exec->propertyNames().length);
155     return JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
156 }
157
158 StringObject* constructString(ExecState* exec, JSGlobalObject* globalObject, JSValue string)
159 {
160     StringObject* object = StringObject::create(exec, globalObject->stringObjectStructure());
161     object->setInternalValue(exec->vm(), string);
162     return object;
163 }
164
165 } // namespace JSC