]>
Commit | Line | Data |
---|---|---|
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 "JSCInlines.h" | |
27 | #include "PropertyNameArray.h" | |
28 | ||
29 | namespace JSC { | |
30 | ||
31 | STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(StringObject); | |
32 | ||
33 | const ClassInfo StringObject::s_info = { "String", &JSWrapperObject::s_info, 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 change 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 | Optional<uint32_t> index = parseIndex(propertyName); | |
132 | if (index && thisObject->internalValue()->canGetIndex(index.value())) { | |
133 | return false; | |
134 | } | |
135 | return JSObject::deleteProperty(thisObject, exec, propertyName); | |
136 | } | |
137 | ||
138 | bool StringObject::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i) | |
139 | { | |
140 | StringObject* thisObject = jsCast<StringObject*>(cell); | |
141 | if (thisObject->internalValue()->canGetIndex(i)) | |
142 | return false; | |
143 | return JSObject::deletePropertyByIndex(thisObject, exec, i); | |
144 | } | |
145 | ||
146 | void StringObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) | |
147 | { | |
148 | StringObject* thisObject = jsCast<StringObject*>(object); | |
149 | int size = thisObject->internalValue()->length(); | |
150 | for (int i = 0; i < size; ++i) | |
151 | propertyNames.add(Identifier::from(exec, i)); | |
152 | if (mode.includeDontEnumProperties()) | |
153 | propertyNames.add(exec->propertyNames().length); | |
154 | return JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode); | |
155 | } | |
156 | ||
157 | StringObject* constructString(VM& vm, JSGlobalObject* globalObject, JSValue string) | |
158 | { | |
159 | StringObject* object = StringObject::create(vm, globalObject->stringObjectStructure()); | |
160 | object->setInternalValue(vm, string); | |
161 | return object; | |
162 | } | |
163 | ||
164 | } // namespace JSC |