1/*
2 *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 *  Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
5 *
6 *  This library is free software; you can redistribute it and/or
7 *  modify it under the terms of the GNU Library General Public
8 *  License as published by the Free Software Foundation; either
9 *  version 2 of the License, or (at your option) any later version.
10 *
11 *  This library is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 *  Library General Public License for more details.
15 *
16 *  You should have received a copy of the GNU Library General Public License
17 *  along with this library; see the file COPYING.LIB.  If not, write to
18 *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 *  Boston, MA 02110-1301, USA.
20 *
21 */
22
23#include "config.h"
24#include "JSCell.h"
25
26#include "ArrayBufferView.h"
27#include "JSFunction.h"
28#include "JSString.h"
29#include "JSObject.h"
30#include "NumberObject.h"
31#include "JSCInlines.h"
32#include <wtf/MathExtras.h>
33
34namespace JSC {
35
36COMPILE_ASSERT(sizeof(JSCell) == sizeof(uint64_t), jscell_is_eight_bytes);
37STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSCell);
38
39void JSCell::destroy(JSCell* cell)
40{
41    cell->JSCell::~JSCell();
42}
43
44void JSCell::dump(PrintStream& out) const
45{
46    methodTable()->dumpToStream(this, out);
47}
48
49void JSCell::dumpToStream(const JSCell* cell, PrintStream& out)
50{
51    out.printf("<%p, %s>", cell, cell->className());
52}
53
54void JSCell::copyBackingStore(JSCell*, CopyVisitor&, CopyToken)
55{
56}
57
58bool JSCell::getString(ExecState* exec, String& stringValue) const
59{
60    if (!isString())
61        return false;
62    stringValue = static_cast<const JSString*>(this)->value(exec);
63    return true;
64}
65
66String JSCell::getString(ExecState* exec) const
67{
68    return isString() ? static_cast<const JSString*>(this)->value(exec) : String();
69}
70
71JSObject* JSCell::getObject()
72{
73    return isObject() ? asObject(this) : 0;
74}
75
76const JSObject* JSCell::getObject() const
77{
78    return isObject() ? static_cast<const JSObject*>(this) : 0;
79}
80
81CallType JSCell::getCallData(JSCell*, CallData& callData)
82{
83    callData.js.functionExecutable = 0;
84    callData.js.scope = 0;
85    callData.native.function = 0;
86    return CallTypeNone;
87}
88
89ConstructType JSCell::getConstructData(JSCell*, ConstructData& constructData)
90{
91    constructData.js.functionExecutable = 0;
92    constructData.js.scope = 0;
93    constructData.native.function = 0;
94    return ConstructTypeNone;
95}
96
97void JSCell::put(JSCell* cell, ExecState* exec, PropertyName identifier, JSValue value, PutPropertySlot& slot)
98{
99    if (cell->isString()) {
100        JSValue(cell).putToPrimitive(exec, identifier, value, slot);
101        return;
102    }
103    JSObject* thisObject = cell->toObject(exec, exec->lexicalGlobalObject());
104    thisObject->methodTable(exec->vm())->put(thisObject, exec, identifier, value, slot);
105}
106
107void JSCell::putByIndex(JSCell* cell, ExecState* exec, unsigned identifier, JSValue value, bool shouldThrow)
108{
109    if (cell->isString()) {
110        PutPropertySlot slot(cell, shouldThrow);
111        JSValue(cell).putToPrimitive(exec, Identifier::from(exec, identifier), value, slot);
112        return;
113    }
114    JSObject* thisObject = cell->toObject(exec, exec->lexicalGlobalObject());
115    thisObject->methodTable(exec->vm())->putByIndex(thisObject, exec, identifier, value, shouldThrow);
116}
117
118bool JSCell::deleteProperty(JSCell* cell, ExecState* exec, PropertyName identifier)
119{
120    JSObject* thisObject = cell->toObject(exec, exec->lexicalGlobalObject());
121    return thisObject->methodTable(exec->vm())->deleteProperty(thisObject, exec, identifier);
122}
123
124bool JSCell::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned identifier)
125{
126    JSObject* thisObject = cell->toObject(exec, exec->lexicalGlobalObject());
127    return thisObject->methodTable(exec->vm())->deletePropertyByIndex(thisObject, exec, identifier);
128}
129
130JSValue JSCell::toThis(JSCell* cell, ExecState* exec, ECMAMode ecmaMode)
131{
132    if (ecmaMode == StrictMode)
133        return cell;
134    return cell->toObject(exec, exec->lexicalGlobalObject());
135}
136
137JSValue JSCell::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
138{
139    if (isString())
140        return static_cast<const JSString*>(this)->toPrimitive(exec, preferredType);
141    return static_cast<const JSObject*>(this)->toPrimitive(exec, preferredType);
142}
143
144bool JSCell::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value) const
145{
146    if (isString())
147        return static_cast<const JSString*>(this)->getPrimitiveNumber(exec, number, value);
148    return static_cast<const JSObject*>(this)->getPrimitiveNumber(exec, number, value);
149}
150
151double JSCell::toNumber(ExecState* exec) const
152{
153    if (isString())
154        return static_cast<const JSString*>(this)->toNumber(exec);
155    return static_cast<const JSObject*>(this)->toNumber(exec);
156}
157
158JSObject* JSCell::toObject(ExecState* exec, JSGlobalObject* globalObject) const
159{
160    if (isString())
161        return static_cast<const JSString*>(this)->toObject(exec, globalObject);
162    ASSERT(isObject());
163    return jsCast<JSObject*>(const_cast<JSCell*>(this));
164}
165
166void slowValidateCell(JSCell* cell)
167{
168    ASSERT_GC_OBJECT_LOOKS_VALID(cell);
169}
170
171JSValue JSCell::defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType)
172{
173    RELEASE_ASSERT_NOT_REACHED();
174    return jsUndefined();
175}
176
177bool JSCell::getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&)
178{
179    RELEASE_ASSERT_NOT_REACHED();
180    return false;
181}
182
183bool JSCell::getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned, PropertySlot&)
184{
185    RELEASE_ASSERT_NOT_REACHED();
186    return false;
187}
188
189void JSCell::getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode)
190{
191    RELEASE_ASSERT_NOT_REACHED();
192}
193
194void JSCell::getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode)
195{
196    RELEASE_ASSERT_NOT_REACHED();
197}
198
199String JSCell::className(const JSObject*)
200{
201    RELEASE_ASSERT_NOT_REACHED();
202    return String();
203}
204
205const char* JSCell::className() const
206{
207    return classInfo()->className;
208}
209
210void JSCell::getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode)
211{
212    RELEASE_ASSERT_NOT_REACHED();
213}
214
215bool JSCell::customHasInstance(JSObject*, ExecState*, JSValue)
216{
217    RELEASE_ASSERT_NOT_REACHED();
218    return false;
219}
220
221bool JSCell::defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool)
222{
223    RELEASE_ASSERT_NOT_REACHED();
224    return false;
225}
226
227ArrayBuffer* JSCell::slowDownAndWasteMemory(JSArrayBufferView*)
228{
229    RELEASE_ASSERT_NOT_REACHED();
230    return 0;
231}
232
233PassRefPtr<ArrayBufferView> JSCell::getTypedArrayImpl(JSArrayBufferView*)
234{
235    RELEASE_ASSERT_NOT_REACHED();
236    return 0;
237}
238
239} // namespace JSC
240