Add support for private names
[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 "PropertyNameArray.h"
26
27 namespace JSC {
28
29 ASSERT_CLASS_FITS_IN_CELL(StringObject);
30 ASSERT_HAS_TRIVIAL_DESTRUCTOR(StringObject);
31
32 const ClassInfo StringObject::s_info = { "String", &JSWrapperObject::s_info, 0, 0, CREATE_METHOD_TABLE(StringObject) };
33
34 StringObject::StringObject(JSGlobalData& globalData, Structure* structure)
35     : JSWrapperObject(globalData, structure)
36 {
37 }
38
39 void StringObject::finishCreation(JSGlobalData& globalData, JSString* string)
40 {
41     Base::finishCreation(globalData);
42     ASSERT(inherits(&s_info));
43     setInternalValue(globalData, string);
44 }
45
46 bool StringObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
47 {
48     StringObject* thisObject = jsCast<StringObject*>(cell);
49     if (thisObject->internalValue()->getStringPropertySlot(exec, propertyName, slot))
50         return true;
51     return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
52 }
53     
54 bool StringObject::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, PropertySlot& slot)
55 {
56     StringObject* thisObject = jsCast<StringObject*>(cell);
57     if (thisObject->internalValue()->getStringPropertySlot(exec, propertyName, slot))
58         return true;    
59     return JSObject::getOwnPropertySlot(thisObject, exec, Identifier::from(exec, propertyName), slot);
60 }
61
62 bool StringObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor)
63 {
64     StringObject* thisObject = jsCast<StringObject*>(object);
65     if (thisObject->internalValue()->getStringPropertyDescriptor(exec, propertyName, descriptor))
66         return true;    
67     return JSObject::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
68 }
69
70 void StringObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
71 {
72     if (propertyName == exec->propertyNames().length) {
73         if (slot.isStrictMode())
74             throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
75         return;
76     }
77     JSObject::put(cell, exec, propertyName, value, slot);
78 }
79
80 bool StringObject::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor, bool throwException)
81 {
82     StringObject* thisObject = jsCast<StringObject*>(object);
83
84     if (propertyName == exec->propertyNames().length) {
85         if (!object->isExtensible()) {
86             if (throwException)
87                 throwError(exec, createTypeError(exec, "Attempting to define property on object that is not extensible."));
88             return false;
89         }
90         if (descriptor.configurablePresent() && descriptor.configurable()) {
91             if (throwException)
92                 throwError(exec, createTypeError(exec, "Attempting to configurable attribute of unconfigurable property."));
93             return false;
94         }
95         if (descriptor.enumerablePresent() && descriptor.enumerable()) {
96             if (throwException)
97                 throwError(exec, createTypeError(exec, "Attempting to change enumerable attribute of unconfigurable property."));
98             return false;
99         }
100         if (descriptor.isAccessorDescriptor()) {
101             if (throwException)
102                 throwError(exec, createTypeError(exec, "Attempting to change access mechanism for an unconfigurable property."));
103             return false;
104         }
105         if (descriptor.writablePresent() && descriptor.writable()) {
106             if (throwException)
107                 throwError(exec, createTypeError(exec, "Attempting to change writable attribute of unconfigurable property."));
108             return false;
109         }
110         if (!descriptor.value())
111             return true;
112         if (propertyName == exec->propertyNames().length && sameValue(exec, descriptor.value(), jsNumber(thisObject->internalValue()->length())))
113             return true;
114         if (throwException)
115             throwError(exec, createTypeError(exec, "Attempting to change value of a readonly property."));
116         return false;
117     }
118
119     return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
120 }
121
122 bool StringObject::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
123 {
124     StringObject* thisObject = jsCast<StringObject*>(cell);
125     if (propertyName == exec->propertyNames().length)
126         return false;
127     unsigned i = propertyName.asIndex();
128     if (thisObject->internalValue()->canGetIndex(i)) {
129         ASSERT(i != PropertyName::NotAnIndex); // No need for an explicit check, the above test would always fail!
130         return false;
131     }
132     return JSObject::deleteProperty(thisObject, exec, propertyName);
133 }
134
135 void StringObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
136 {
137     StringObject* thisObject = jsCast<StringObject*>(object);
138     int size = thisObject->internalValue()->length();
139     for (int i = 0; i < size; ++i)
140         propertyNames.add(Identifier(exec, UString::number(i)));
141     if (mode == IncludeDontEnumProperties)
142         propertyNames.add(exec->propertyNames().length);
143     return JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
144 }
145
146 } // namespace JSC