18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
40bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *  Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved.
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  Copyright (C) 2007 Eric Seidel (eric@webkit.org)
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  This library is free software; you can redistribute it and/or
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  modify it under the terms of the GNU Library General Public
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  License as published by the Free Software Foundation; either
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  version 2 of the License, or (at your option) any later version.
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  This library is distributed in the hope that it will be useful,
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  but WITHOUT ANY WARRANTY; without even the implied warranty of
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  Library General Public License for more details.
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  You should have received a copy of the GNU Library General Public License
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  along with this library; see the file COPYING.LIB.  If not, write to
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  Boston, MA 02110-1301, USA.
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "JSObject.h"
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "DatePrototype.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ErrorConstructor.h"
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "GetterSetter.h"
30e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "JSFunction.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "JSGlobalObject.h"
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "NativeErrorConstructor.h"
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ObjectPrototype.h"
34231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "PropertyDescriptor.h"
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "PropertyNameArray.h"
36635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "Lookup.h"
37635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "Nodes.h"
38635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "Operations.h"
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <math.h>
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/Assertions.h>
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace JSC {
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectASSERT_CLASS_FITS_IN_CELL(JSObject);
4581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen MurdochASSERT_CLASS_FITS_IN_CELL(JSNonFinalObject);
462bde8e466a4451c7319e3a072d118917957d6554Steve BlockASSERT_CLASS_FITS_IN_CELL(JSFinalObject);
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
48a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochconst char* StrictModeReadonlyPropertyWriteError = "Attempted to assign to readonly property.";
49a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
5081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochconst ClassInfo JSObject::s_info = { "Object", 0, 0, 0 };
5181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
52d0825bca7fe65beaee391d30da42e937db621564Steve Blockstatic inline void getClassPropertyNames(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames, EnumerationMode mode)
53cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block{
54cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // Add properties from the static hashtables of properties
55cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    for (; classInfo; classInfo = classInfo->parentClass) {
56cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        const HashTable* table = classInfo->propHashTable(exec);
57cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        if (!table)
58cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            continue;
59cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        table->initializeIfNeeded(exec);
60cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        ASSERT(table->table);
61cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
62cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        int hashSizeMask = table->compactSize - 1;
63cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        const HashEntry* entry = table->table;
64cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        for (int i = 0; i <= hashSizeMask; ++i, ++entry) {
65d0825bca7fe65beaee391d30da42e937db621564Steve Block            if (entry->key() && (!(entry->attributes() & DontEnum) || (mode == IncludeDontEnumProperties)))
66cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                propertyNames.add(entry->key());
67cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        }
68cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    }
69cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block}
70cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid JSObject::markChildren(MarkStack& markStack)
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
73231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#ifndef NDEBUG
74231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    bool wasCheckingForDefaultMarkViolation = markStack.m_isCheckingForDefaultMarkViolation;
75231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    markStack.m_isCheckingForDefaultMarkViolation = false;
76231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif
77058ccc7ba0a4d59b9f6e92808332aa9895425fc7Andrei Popescu
78231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    markChildrenDirect(markStack);
79058ccc7ba0a4d59b9f6e92808332aa9895425fc7Andrei Popescu
80231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#ifndef NDEBUG
81231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    markStack.m_isCheckingForDefaultMarkViolation = wasCheckingForDefaultMarkViolation;
82231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectUString JSObject::className() const
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const ClassInfo* info = classInfo();
8881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT(info);
8981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return info->className;
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool JSObject::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void throwSetterError(ExecState* exec)
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
99545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    throwError(exec, createTypeError(exec, "setting a property that has only a getter"));
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// ECMA 8.6.2.2
1035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianvoid JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(value);
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (propertyName == exec->propertyNames().underscoreProto) {
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Setting __proto__ to a non-object, non-null value is silently ignored to match Mozilla.
110635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (!value.isObject() && !value.isNull())
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
1122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!setPrototypeWithCycleCheck(exec->globalData(), value))
113545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch            throwError(exec, createError(exec, "cyclic __proto__ value"));
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
116635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Check if there are any setters or getters in the prototype chain
1185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    JSValue prototype;
119635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    for (JSObject* obj = this; !obj->structure()->hasGetterSetterProperties(); obj = asObject(prototype)) {
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        prototype = obj->prototype();
121635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (prototype.isNull()) {
122a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (!putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot) && slot.isStrictMode())
123a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned attributes;
1295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    JSCell* specificValue;
1302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if ((m_structure->get(exec->globalData(), propertyName, attributes, specificValue) != WTF::notFound) && attributes & ReadOnly) {
131a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (slot.isStrictMode())
132a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            throwError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError));
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
134a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (JSObject* obj = this; ; obj = asObject(prototype)) {
1372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (JSValue gs = obj->getDirect(exec->globalData(), propertyName)) {
138635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            if (gs.isGetterSetter()) {
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                JSObject* setterFunc = asGetterSetter(gs)->setter();
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (!setterFunc) {
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    throwSetterError(exec);
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    return;
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                CallData callData;
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                CallType callType = setterFunc->getCallData(callData);
1475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                MarkedArgumentBuffer args;
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                args.append(value);
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                call(exec, setterFunc, callType, callData, this, args);
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return;
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // If there's an existing property on the object or one of its
1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // prototypes it should be replaced, so break here.
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        prototype = obj->prototype();
159635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (prototype.isNull())
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
163a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot) && slot.isStrictMode())
164a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return;
1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianvoid JSObject::put(ExecState* exec, unsigned propertyName, JSValue value)
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PutPropertySlot slot;
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    put(exec, Identifier::from(exec, propertyName), value, slot);
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
174545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdochvoid JSObject::putWithAttributes(JSGlobalData* globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
175545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch{
176545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    putDirectInternal(*globalData, propertyName, value, attributes, checkReadOnly, slot);
177545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch}
178545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch
179545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdochvoid JSObject::putWithAttributes(JSGlobalData* globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
180545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch{
181545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    putDirectInternal(*globalData, propertyName, value, attributes);
182545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch}
183545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch
184545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdochvoid JSObject::putWithAttributes(JSGlobalData* globalData, unsigned propertyName, JSValue value, unsigned attributes)
185545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch{
186545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    putWithAttributes(globalData, Identifier::from(globalData, propertyName), value, attributes);
187545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch}
188545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch
1895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianvoid JSObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    putDirectInternal(exec->globalData(), propertyName, value, attributes, checkReadOnly, slot);
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1945f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianvoid JSObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
1955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
1965f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    putDirectInternal(exec->globalData(), propertyName, value, attributes);
1975f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
1985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianvoid JSObject::putWithAttributes(ExecState* exec, unsigned propertyName, JSValue value, unsigned attributes)
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    putWithAttributes(exec, Identifier::from(exec, propertyName), value, attributes);
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool JSObject::hasProperty(ExecState* exec, const Identifier& propertyName) const
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PropertySlot slot;
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot);
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool JSObject::hasProperty(ExecState* exec, unsigned propertyName) const
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PropertySlot slot;
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot);
2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// ECMA 8.6.2.5
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool JSObject::deleteProperty(ExecState* exec, const Identifier& propertyName)
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned attributes;
2205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    JSCell* specificValue;
2212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (m_structure->get(exec->globalData(), propertyName, attributes, specificValue) != WTF::notFound) {
2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if ((attributes & DontDelete))
2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
2242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        removeDirect(exec->globalData(), propertyName);
2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Look in the static hashtable of properties
2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const HashEntry* entry = findPropertyHashEntry(exec, propertyName);
2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (entry && entry->attributes() & DontDelete)
2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false; // this builtin property can't be deleted
2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: Should the code here actually do some deletion?
2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool JSObject::hasOwnProperty(ExecState* exec, const Identifier& propertyName) const
2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PropertySlot slot;
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return const_cast<JSObject*>(this)->getOwnPropertySlot(exec, propertyName, slot);
2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool JSObject::deleteProperty(ExecState* exec, unsigned propertyName)
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return deleteProperty(exec, Identifier::from(exec, propertyName));
2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianstatic ALWAYS_INLINE JSValue callDefaultValueFunction(ExecState* exec, const JSObject* object, const Identifier& propertyName)
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2505f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    JSValue function = object->get(exec, propertyName);
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    CallData callData;
252545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    CallType callType = getCallData(function, callData);
2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (callType == CallTypeNone)
2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return exec->exception();
2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Prevent "toString" and "valueOf" from observing execution if an exception
2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // is pending.
2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (exec->hadException())
2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return exec->exception();
2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2615f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    JSValue result = call(exec, function, callType, callData, const_cast<JSObject*>(object), exec->emptyList());
262635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    ASSERT(!result.isGetterSetter());
2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (exec->hadException())
2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return exec->exception();
265635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (result.isObject())
2665f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return JSValue();
2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return result;
2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2705f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianbool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValue& result)
2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    result = defaultValue(exec, PreferNumber);
273635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    number = result.toNumber(exec);
274635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return !result.isString();
2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// ECMA 8.6.2.6
2785f1ab04193ad0130ca8204aadaceae083aca9881Feng QianJSValue JSObject::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Must call toString first for Date objects.
2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if ((hint == PreferString) || (hint != PreferNumber && prototype() == exec->lexicalGlobalObject()->datePrototype())) {
2825f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        JSValue value = callDefaultValueFunction(exec, this, exec->propertyNames().toString);
283635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (value)
2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return value;
285635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        value = callDefaultValueFunction(exec, this, exec->propertyNames().valueOf);
286635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (value)
2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return value;
2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
2895f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        JSValue value = callDefaultValueFunction(exec, this, exec->propertyNames().valueOf);
290635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (value)
2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return value;
292635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        value = callDefaultValueFunction(exec, this, exec->propertyNames().toString);
293635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (value)
2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return value;
2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!exec->hadException());
2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
299545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    return throwError(exec, createTypeError(exec, "No default value"));
3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst HashEntry* JSObject::findPropertyHashEntry(ExecState* exec, const Identifier& propertyName) const
3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (const ClassInfo* info = classInfo(); info; info = info->parentClass) {
3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (const HashTable* propHashTable = info->propHashTable(exec)) {
3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (const HashEntry* entry = propHashTable->entry(exec, propertyName))
3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return entry;
3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
313231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    JSValue object = getDirect(exec->globalData(), propertyName);
316635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (object && object.isGetterSetter()) {
317635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(m_structure->hasGetterSetterProperties());
3182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        asGetterSetter(object)->setGetter(exec->globalData(), getterFunction);
3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    JSGlobalData& globalData = exec->globalData();
3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PutPropertySlot slot;
3240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    GetterSetter* getterSetter = new (exec) GetterSetter(exec);
3252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    putDirectInternal(globalData, propertyName, getterSetter, attributes | Getter, true, slot);
3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
327635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // putDirect will change our Structure if we add a new property. For
328635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // getters and setters, though, we also need to change our Structure
3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // if we override an existing non-getter or non-setter.
3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (slot.type() != PutPropertySlot::NewProperty) {
3312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!m_structure->isDictionary())
3322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            setStructure(exec->globalData(), Structure::getterSetterTransition(globalData, m_structure.get()));
3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
335635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    m_structure->setHasGetterSetterProperties(true);
3362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    getterSetter->setGetter(globalData, getterFunction);
3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
339231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes)
3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    JSValue object = getDirect(exec->globalData(), propertyName);
342635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (object && object.isGetterSetter()) {
343635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(m_structure->hasGetterSetterProperties());
3442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        asGetterSetter(object)->setSetter(exec->globalData(), setterFunction);
3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    PutPropertySlot slot;
3490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    GetterSetter* getterSetter = new (exec) GetterSetter(exec);
350231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    putDirectInternal(exec->globalData(), propertyName, getterSetter, attributes | Setter, true, slot);
3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
352635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // putDirect will change our Structure if we add a new property. For
353635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // getters and setters, though, we also need to change our Structure
3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // if we override an existing non-getter or non-setter.
3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (slot.type() != PutPropertySlot::NewProperty) {
3562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!m_structure->isDictionary())
3572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            setStructure(exec->globalData(), Structure::getterSetterTransition(exec->globalData(), m_structure.get()));
3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
360635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    m_structure->setHasGetterSetterProperties(true);
3612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    getterSetter->setSetter(exec->globalData(), setterFunction);
3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochJSValue JSObject::lookupGetter(ExecState* exec, const Identifier& propertyName)
3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    JSObject* object = this;
3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (true) {
3682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (JSValue value = object->getDirect(exec->globalData(), propertyName)) {
369635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            if (!value.isGetterSetter())
3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return jsUndefined();
3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            JSObject* functionObject = asGetterSetter(value)->getter();
3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (!functionObject)
3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return jsUndefined();
3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return functionObject;
3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
377635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (!object->prototype() || !object->prototype().isObject())
3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return jsUndefined();
3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        object = asObject(object->prototype());
3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochJSValue JSObject::lookupSetter(ExecState* exec, const Identifier& propertyName)
3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    JSObject* object = this;
3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (true) {
3872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (JSValue value = object->getDirect(exec->globalData(), propertyName)) {
388635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            if (!value.isGetterSetter())
3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return jsUndefined();
3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            JSObject* functionObject = asGetterSetter(value)->setter();
3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (!functionObject)
3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return jsUndefined();
3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return functionObject;
3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
396635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (!object->prototype() || !object->prototype().isObject())
3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return jsUndefined();
3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        object = asObject(object->prototype());
3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianbool JSObject::hasInstance(ExecState* exec, JSValue value, JSValue proto)
4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!value.isObject())
4055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return false;
4065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
407635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (!proto.isObject()) {
408545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch        throwError(exec, createTypeError(exec, "instanceof called on an object with an invalid prototype property."));
4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    JSObject* object = asObject(value);
413635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    while ((object = object->prototype().getObject())) {
414635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (proto == object)
4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return true;
4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool JSObject::propertyIsEnumerable(ExecState* exec, const Identifier& propertyName) const
4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
422643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    PropertyDescriptor descriptor;
423643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (!const_cast<JSObject*>(this)->getOwnPropertyDescriptor(exec, propertyName, descriptor))
4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
425643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    return descriptor.enumerable();
4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool JSObject::getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificValue) const
4295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
4305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    unsigned attributes;
4312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (m_structure->get(exec->globalData(), propertyName, attributes, specificValue) != WTF::notFound)
4325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return true;
4335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
4345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // This could be a function within the static table? - should probably
4355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // also look in the hash?  This currently should not be a problem, since
4365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // we've currently always call 'get' first, which should have populated
4375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // the normal storage.
4385f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    return false;
4395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
4405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
441d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
443d0825bca7fe65beaee391d30da42e937db621564Steve Block    getOwnPropertyNames(exec, propertyNames, mode);
444cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
445cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (prototype().isNull())
446cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        return;
447cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
448cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    JSObject* prototype = asObject(this->prototype());
449cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    while(1) {
450cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        if (prototype->structure()->typeInfo().overridesGetPropertyNames()) {
451d0825bca7fe65beaee391d30da42e937db621564Steve Block            prototype->getPropertyNames(exec, propertyNames, mode);
452cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            break;
453cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        }
454d0825bca7fe65beaee391d30da42e937db621564Steve Block        prototype->getOwnPropertyNames(exec, propertyNames, mode);
455cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        JSValue nextProto = prototype->prototype();
456cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        if (nextProto.isNull())
457cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            break;
458cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        prototype = asObject(nextProto);
459cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    }
4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
462d0825bca7fe65beaee391d30da42e937db621564Steve Blockvoid JSObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
463231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
4642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_structure->getPropertyNames(exec->globalData(), propertyNames, mode);
465d0825bca7fe65beaee391d30da42e937db621564Steve Block    getClassPropertyNames(exec, classInfo(), propertyNames, mode);
466231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
467231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool JSObject::toBoolean(ExecState*) const
4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectdouble JSObject::toNumber(ExecState* exec) const
4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    JSValue primitive = toPrimitive(exec, PreferNumber);
476635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (exec->hadException()) // should be picked up soon in Nodes.cpp
4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0.0;
478635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return primitive.toNumber(exec);
4798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectUString JSObject::toString(ExecState* exec) const
4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    JSValue primitive = toPrimitive(exec, PreferString);
4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (exec->hadException())
4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return "";
486635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return primitive.toString(exec);
4878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4892bde8e466a4451c7319e3a072d118917957d6554Steve BlockJSObject* JSObject::toObject(ExecState*, JSGlobalObject*) const
4908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return const_cast<JSObject*>(this);
4928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectJSObject* JSObject::toThisObject(ExecState*) const
4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return const_cast<JSObject*>(this);
4978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
499a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochJSValue JSObject::toStrictThisObject(ExecState*) const
500a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
501a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return const_cast<JSObject*>(this);
502a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
503a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
504635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectJSObject* JSObject::unwrappedObject()
5058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
506635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return this;
5078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid JSObject::seal(JSGlobalData& globalData)
51081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
5112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    setStructure(globalData, Structure::sealTransition(globalData, m_structure.get()));
51281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
51381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
5142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid JSObject::freeze(JSGlobalData& globalData)
51581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
5162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    setStructure(globalData, Structure::freezeTransition(globalData, m_structure.get()));
51781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
51881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
5192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid JSObject::preventExtensions(JSGlobalData& globalData)
52081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
52181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (isExtensible())
5222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        setStructure(globalData, Structure::preventExtensionsTransition(globalData, m_structure.get()));
52381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
52481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
5252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid JSObject::removeDirect(JSGlobalData& globalData, const Identifier& propertyName)
5268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    size_t offset;
528231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_structure->isUncacheableDictionary()) {
5292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        offset = m_structure->removePropertyWithoutTransition(globalData, propertyName);
5308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (offset != WTF::notFound)
5312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            putUndefinedAtDirectOffset(offset);
5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
5338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    setStructure(globalData, Structure::removePropertyTransition(globalData, m_structure.get(), propertyName, offset));
5365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (offset != WTF::notFound)
5372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        putUndefinedAtDirectOffset(offset);
5388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid JSObject::putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr)
5418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5422fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    putDirectFunction(exec->globalData(), Identifier(exec, function->name(exec)), function, attr);
5438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
545e78cbe89e6f337f2f1fe40315be88f742b547151Steve Blockvoid JSObject::putDirectFunction(ExecState* exec, JSFunction* function, unsigned attr)
546e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block{
5472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    putDirectFunction(exec->globalData(), Identifier(exec, function->name(exec)), function, attr);
548e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block}
549e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block
5508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid JSObject::putDirectFunctionWithoutTransition(ExecState* exec, InternalFunction* function, unsigned attr)
5518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, function->name(exec)), function, attr);
5538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
555e78cbe89e6f337f2f1fe40315be88f742b547151Steve Blockvoid JSObject::putDirectFunctionWithoutTransition(ExecState* exec, JSFunction* function, unsigned attr)
556e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block{
5572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, function->name(exec)), function, attr);
558e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block}
559e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block
5602fc2651226baac27029e38c9d6ef883fa32084dbSteve BlockNEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, WriteBarrierBase<Unknown>* location)
5618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (JSObject* getterFunction = asGetterSetter(location->get())->getter()) {
563692e5dbf12901edacf14812a6fae25462920af42Steve Block        if (!structure()->isDictionary())
564692e5dbf12901edacf14812a6fae25462920af42Steve Block            slot.setCacheableGetterSlot(this, getterFunction, offsetForLocation(location));
565692e5dbf12901edacf14812a6fae25462920af42Steve Block        else
566692e5dbf12901edacf14812a6fae25462920af42Steve Block            slot.setGetterSlot(getterFunction);
567692e5dbf12901edacf14812a6fae25462920af42Steve Block    } else
5688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        slot.setUndefined();
5698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5712bde8e466a4451c7319e3a072d118917957d6554Steve BlockStructure* JSObject::createInheritorID(JSGlobalData& globalData)
5728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_inheritorID.set(globalData, this, createEmptyObjectStructure(globalData, this));
5742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(m_inheritorID->isEmpty());
5758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return m_inheritorID.get();
5768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid JSObject::allocatePropertyStorage(size_t oldSize, size_t newSize)
5798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
58081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    ASSERT(newSize > oldSize);
58181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
58281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    // It's important that this function not rely on m_structure, since
58381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    // we might be in the middle of a transition.
58481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    bool wasInline = (oldSize < JSObject::baseExternalStorageCapacity);
58581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
58681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    PropertyStorage oldPropertyStorage = m_propertyStorage;
58781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    PropertyStorage newPropertyStorage = new WriteBarrierBase<Unknown>[newSize];
58881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
58981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    for (unsigned i = 0; i < oldSize; ++i)
59081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch       newPropertyStorage[i] = oldPropertyStorage[i];
59181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
59281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (!wasInline)
59381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        delete [] oldPropertyStorage;
59481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
59581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    m_propertyStorage = newPropertyStorage;
5968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochbool JSObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
599231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
600231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    unsigned attributes = 0;
601231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    JSCell* cell = 0;
6022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    size_t offset = m_structure->get(exec->globalData(), propertyName, attributes, cell);
603231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (offset == WTF::notFound)
604231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return false;
605231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    descriptor.setDescriptor(getDirectOffset(offset), attributes);
606231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return true;
607231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
608231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
609231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockbool JSObject::getPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
6108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
611231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    JSObject* object = this;
612231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    while (true) {
613231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (object->getOwnPropertyDescriptor(exec, propertyName, descriptor))
614231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return true;
615231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        JSValue prototype = object->prototype();
616231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (!prototype.isObject())
617231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return false;
618231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        object = asObject(prototype);
619231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
620231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
621231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
62265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic bool putDescriptor(ExecState* exec, JSObject* target, const Identifier& propertyName, PropertyDescriptor& descriptor, unsigned attributes, const PropertyDescriptor& oldDescriptor)
623231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
624231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (descriptor.isGenericDescriptor() || descriptor.isDataDescriptor()) {
62565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (descriptor.isGenericDescriptor() && oldDescriptor.isAccessorDescriptor()) {
62665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            GetterSetter* accessor = new (exec) GetterSetter(exec);
62765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            if (oldDescriptor.getter()) {
62865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                attributes |= Getter;
6292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                accessor->setGetter(exec->globalData(), asObject(oldDescriptor.getter()));
63065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            }
63165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            if (oldDescriptor.setter()) {
63265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                attributes |= Setter;
6332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                accessor->setSetter(exec->globalData(), asObject(oldDescriptor.setter()));
63465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            }
63565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            target->putWithAttributes(exec, propertyName, accessor, attributes);
63665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            return true;
63765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        }
63865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        JSValue newValue = jsUndefined();
63965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (descriptor.value())
64065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            newValue = descriptor.value();
64165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        else if (oldDescriptor.value())
64265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            newValue = oldDescriptor.value();
64365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        target->putWithAttributes(exec, propertyName, newValue, attributes & ~(Getter | Setter));
644231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return true;
645231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
646231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    attributes &= ~ReadOnly;
647231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (descriptor.getter() && descriptor.getter().isObject())
648231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        target->defineGetter(exec, propertyName, asObject(descriptor.getter()), attributes);
649231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (exec->hadException())
650231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return false;
651231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (descriptor.setter() && descriptor.setter().isObject())
652231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        target->defineSetter(exec, propertyName, asObject(descriptor.setter()), attributes);
653231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return !exec->hadException();
654231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
655231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
656231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockbool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool throwException)
657231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
658231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // If we have a new property we can just put it on normally
659231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    PropertyDescriptor current;
66065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (!getOwnPropertyDescriptor(exec, propertyName, current)) {
66181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        // unless extensions are prevented!
66281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (!isExtensible()) {
66381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            if (throwException)
66481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                throwError(exec, createTypeError(exec, "Attempting to define property on object that is not extensible."));
66581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            return false;
66681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        }
66765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        PropertyDescriptor oldDescriptor;
66865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        oldDescriptor.setValue(jsUndefined());
66965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return putDescriptor(exec, this, propertyName, descriptor, descriptor.attributes(), oldDescriptor);
67065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
671231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
672231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (descriptor.isEmpty())
673231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return true;
674231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
675643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (current.equalTo(exec, descriptor))
676231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return true;
677231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
678231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // Filter out invalid changes
679231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!current.configurable()) {
680231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (descriptor.configurable()) {
681231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (throwException)
682545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch                throwError(exec, createTypeError(exec, "Attempting to configurable attribute of unconfigurable property."));
683231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return false;
684231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
685231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (descriptor.enumerablePresent() && descriptor.enumerable() != current.enumerable()) {
686231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (throwException)
687545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch                throwError(exec, createTypeError(exec, "Attempting to change enumerable attribute of unconfigurable property."));
688231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return false;
689231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
690231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
691231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
692231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // A generic descriptor is simply changing the attributes of an existing property
693231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (descriptor.isGenericDescriptor()) {
694231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (!current.attributesEqual(descriptor)) {
695231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            deleteProperty(exec, propertyName);
69665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current);
697231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
698231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return true;
699231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
700231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
701231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // Changing between a normal property or an accessor property
702231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (descriptor.isDataDescriptor() != current.isDataDescriptor()) {
703231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (!current.configurable()) {
704231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (throwException)
705545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch                throwError(exec, createTypeError(exec, "Attempting to change access mechanism for an unconfigurable property."));
706231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return false;
707231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
708231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        deleteProperty(exec, propertyName);
70965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current);
710231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
711231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
712231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // Changing the value and attributes of an existing property
713231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (descriptor.isDataDescriptor()) {
714231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (!current.configurable()) {
715231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (!current.writable() && descriptor.writable()) {
716231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                if (throwException)
717545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch                    throwError(exec, createTypeError(exec, "Attempting to change writable attribute of unconfigurable property."));
718231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                return false;
719231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            }
720231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (!current.writable()) {
721643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                if (descriptor.value() || !JSValue::strictEqual(exec, current.value(), descriptor.value())) {
722231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                    if (throwException)
723545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch                        throwError(exec, createTypeError(exec, "Attempting to change value of a readonly property."));
724231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                    return false;
725231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                }
726231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            }
727231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        } else if (current.attributesEqual(descriptor)) {
728231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (!descriptor.value())
729231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                return true;
730231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            PutPropertySlot slot;
731231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            put(exec, propertyName, descriptor.value(), slot);
732231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (exec->hadException())
733231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                return false;
734231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return true;
735231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
736231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        deleteProperty(exec, propertyName);
73765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current);
738231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
739231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
740231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // Changing the accessor functions of an existing accessor property
741231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ASSERT(descriptor.isAccessorDescriptor());
742231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!current.configurable()) {
7432bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (descriptor.setterPresent() && !(current.setterPresent() && JSValue::strictEqual(exec, current.setter(), descriptor.setter()))) {
744231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (throwException)
745545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch                throwError(exec, createTypeError(exec, "Attempting to change the setter of an unconfigurable property."));
746231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return false;
747231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
7482bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (descriptor.getterPresent() && !(current.getterPresent() && JSValue::strictEqual(exec, current.getter(), descriptor.getter()))) {
749231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (throwException)
750545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch                throwError(exec, createTypeError(exec, "Attempting to change the getter of an unconfigurable property."));
751231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return false;
752231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
753231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
7542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    JSValue accessor = getDirect(exec->globalData(), propertyName);
755231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!accessor)
756231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return false;
757231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    GetterSetter* getterSetter = asGetterSetter(accessor);
758231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (current.attributesEqual(descriptor)) {
759231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (descriptor.setter())
7602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            getterSetter->setSetter(exec->globalData(), asObject(descriptor.setter()));
761231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (descriptor.getter())
7622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            getterSetter->setGetter(exec->globalData(), asObject(descriptor.getter()));
763231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return true;
764231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
765231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    deleteProperty(exec, propertyName);
766231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    unsigned attrs = current.attributesWithOverride(descriptor);
767231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (descriptor.setter())
768231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        attrs |= Setter;
769231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (descriptor.getter())
770231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        attrs |= Getter;
7712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    putDirect(exec->globalData(), propertyName, getterSetter, attrs);
772231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return true;
7738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
775a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochJSObject* throwTypeError(ExecState* exec, const UString& message)
776a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
777a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return throwError(exec, createTypeError(exec, message));
778a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
779a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
7808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace JSC
781