18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  This library is free software; you can redistribute it and/or
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  modify it under the terms of the GNU Lesser General Public
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  License as published by the Free Software Foundation; either
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  version 2 of the License, or (at your option) any later version.
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  This library is distributed in the hope that it will be useful,
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  but WITHOUT ANY WARRANTY; without even the implied warranty of
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  Lesser General Public License for more details.
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  You should have received a copy of the GNU Lesser General Public
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  License along with this library; if not, write to the Free Software
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "qt_instance.h"
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ArgList.h"
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "JSDOMBinding.h"
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "JSGlobalObject.h"
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "JSLock.h"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "qt_class.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "qt_runtime.h"
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "PropertyNameArray.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "runtime_object.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ObjectPrototype.h"
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Error.h"
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <qmetaobject.h>
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <qdebug.h>
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <qmetatype.h>
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <qhash.h>
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace JSC {
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace Bindings {
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Cache QtInstances
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projecttypedef QMultiHash<void*, QtInstance*> QObjectInstanceMap;
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic QObjectInstanceMap cachedInstances;
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Derived RuntimeObject
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectclass QtRuntimeObjectImp : public RuntimeObjectImp {
48635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectpublic:
49635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    QtRuntimeObjectImp(ExecState*, PassRefPtr<Instance>);
50635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
51635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    static const ClassInfo s_info;
52635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
53231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    virtual void markChildren(MarkStack& markStack)
54635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    {
55231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        RuntimeObjectImp::markChildren(markStack);
56635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        QtInstance* instance = static_cast<QtInstance*>(getInternalInstance());
57635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (instance)
58231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            instance->markAggregate(markStack);
59635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
61643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    static PassRefPtr<Structure> createStructure(JSValue prototype)
62643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    {
63d0825bca7fe65beaee391d30da42e937db621564Steve Block        return Structure::create(prototype, TypeInfo(ObjectType,  StructureFlags), AnonymousSlotCount);
64643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
65643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
66643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockprotected:
67643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    static const unsigned StructureFlags = RuntimeObjectImp::StructureFlags | OverridesMarkChildren;
68643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
69635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectprivate:
70635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    virtual const ClassInfo* classInfo() const { return &s_info; }
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
73635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectconst ClassInfo QtRuntimeObjectImp::s_info = { "QtRuntimeObject", &RuntimeObjectImp::s_info, 0, 0 };
74635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectQtRuntimeObjectImp::QtRuntimeObjectImp(ExecState* exec, PassRefPtr<Instance> instance)
760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    : RuntimeObjectImp(exec, WebCore::deprecatedGetDOMStructure<QtRuntimeObjectImp>(exec), instance)
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// QtInstance
818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianQtInstance::QtInstance(QObject* o, PassRefPtr<RootObject> rootObject, QScriptEngine::ValueOwnership ownership)
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    : Instance(rootObject)
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_class(0)
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_object(o)
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_hashkey(o)
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_defaultMethod(0)
878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_ownership(ownership)
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectQtInstance::~QtInstance()
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    JSLock lock(SilenceAssertionsOnly);
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    cachedInstances.remove(m_hashkey);
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // clean up (unprotect from gc) the JSValues we've created
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_methods.clear();
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    qDeleteAll(m_fields);
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_fields.clear();
1028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (m_object) {
1048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        switch (m_ownership) {
1058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        case QScriptEngine::QtOwnership:
1068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            break;
1078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        case QScriptEngine::AutoOwnership:
1088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            if (m_object->parent())
1098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                break;
1108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            // fall through!
1118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        case QScriptEngine::ScriptOwnership:
1128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            delete m_object;
1138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            break;
1148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        }
1158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianPassRefPtr<QtInstance> QtInstance::getQtInstance(QObject* o, PassRefPtr<RootObject> rootObject, QScriptEngine::ValueOwnership ownership)
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    JSLock lock(SilenceAssertionsOnly);
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
122643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    foreach(QtInstance* instance, cachedInstances.values(o))
123643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (instance->rootObject() == rootObject) {
124643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            // The garbage collector removes instances, but it may happen that the wrapped
125643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            // QObject dies before the gc kicks in. To handle that case we have to do an additional
126643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            // check if to see if the instance's wrapped object is still alive. If it isn't, then
127643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            // we have to create a new wrapper.
128643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            if (!instance->getObject())
129643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                cachedInstances.remove(instance->hashKey());
130643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            else
131643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                return instance;
132643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        }
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    RefPtr<QtInstance> ret = QtInstance::create(o, rootObject, ownership);
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    cachedInstances.insert(o, ret.get());
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return ret.release();
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
140635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectbool QtInstance::getOwnPropertySlot(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
142635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return object->JSObject::getOwnPropertySlot(exec, propertyName, slot);
143635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
144635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianvoid QtInstance::put(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
146635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
147635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    object->JSObject::put(exec, propertyName, value, slot);
148635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
149635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid QtInstance::removeCachedMethod(JSObject* method)
1510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
1520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (m_defaultMethod == method)
1530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        m_defaultMethod = 0;
1540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    for(QHash<QByteArray, JSObject*>::Iterator it = m_methods.begin(),
1560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        end = m_methods.end(); it != end; ++it)
1570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (it.value() == method) {
1580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            m_methods.erase(it);
1590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            return;
1600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
1610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
1620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
163635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectQtInstance* QtInstance::getInstance(JSObject* object)
164635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
165635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (!object)
166635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return 0;
167635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (!object->inherits(&QtRuntimeObjectImp::s_info))
168635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return 0;
169635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return static_cast<QtInstance*>(static_cast<RuntimeObjectImp*>(object)->getInternalInstance());
1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectClass* QtInstance::getClass() const
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!m_class)
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_class = QtClass::classForObject(m_object);
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return m_class;
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
179231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockRuntimeObjectImp* QtInstance::newRuntimeObject(ExecState* exec)
180635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
1810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    JSLock lock(SilenceAssertionsOnly);
182231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return new (exec) QtRuntimeObjectImp(exec, this);
183635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
184635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
185231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid QtInstance::markAggregate(MarkStack& markStack)
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
187231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_defaultMethod)
188231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        markStack.append(m_defaultMethod);
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    foreach(JSObject* val, m_methods.values()) {
190231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (val)
191231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            markStack.append(val);
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid QtInstance::begin()
1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Do nothing.
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid QtInstance::end()
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Do nothing.
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid QtInstance::getPropertyNames(ExecState* exec, PropertyNameArray& array)
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // This is the enumerable properties, so put:
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // properties
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // dynamic properties
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // slots
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    QObject* obj = getObject();
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (obj) {
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        const QMetaObject* meta = obj->metaObject();
2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        int i;
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (i=0; i < meta->propertyCount(); i++) {
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            QMetaProperty prop = meta->property(i);
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (prop.isScriptable()) {
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                array.add(Identifier(exec, prop.name()));
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        QList<QByteArray> dynProps = obj->dynamicPropertyNames();
2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        foreach(QByteArray ba, dynProps) {
2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            array.add(Identifier(exec, ba.constData()));
2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (i=0; i < meta->methodCount(); i++) {
2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            QMetaMethod method = meta->method(i);
2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (method.access() != QMetaMethod::Private) {
2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                array.add(Identifier(exec, method.signature()));
2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2375f1ab04193ad0130ca8204aadaceae083aca9881Feng QianJSValue QtInstance::invokeMethod(ExecState*, const MethodList&, const ArgList&)
2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Implemented via fallbackMethod & QtRuntimeMetaMethod::callAsFunction
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return jsUndefined();
2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2445f1ab04193ad0130ca8204aadaceae083aca9881Feng QianJSValue QtInstance::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (hint == PreferString)
2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return stringValue(exec);
2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (hint == PreferNumber)
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return numberValue(exec);
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return valueOf(exec);
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2535f1ab04193ad0130ca8204aadaceae083aca9881Feng QianJSValue QtInstance::stringValue(ExecState* exec) const
2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Hmm.. see if there is a toString defined
2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    QByteArray buf;
2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool useDefault = true;
2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    getClass();
2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    QObject* obj = getObject();
2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_class && obj) {
2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Cheat and don't use the full name resolution
2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        int index = obj->metaObject()->indexOfMethod("toString()");
2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (index >= 0) {
2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            QMetaMethod m = obj->metaObject()->method(index);
2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Check to see how much we can call it
2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (m.access() != QMetaMethod::Private
2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                && m.methodType() != QMetaMethod::Signal
2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                && m.parameterTypes().count() == 0) {
2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                const char* retsig = m.typeName();
2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (retsig && *retsig) {
2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    QVariant ret(QMetaType::type(retsig), (void*)0);
2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    void * qargs[1];
2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    qargs[0] = ret.data();
2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (obj->qt_metacall(QMetaObject::InvokeMetaMethod, index, qargs) < 0) {
2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        if (ret.isValid() && ret.canConvert(QVariant::String)) {
2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            buf = ret.toString().toLatin1().constData(); // ### Latin 1? Ascii?
2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            useDefault = false;
2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        }
2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (useDefault) {
2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        const QMetaObject* meta = obj ? obj->metaObject() : &QObject::staticMetaObject;
2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        QString name = obj ? obj->objectName() : QString::fromUtf8("unnamed");
2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        QString str = QString::fromUtf8("%0(name = \"%1\")")
2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                      .arg(QLatin1String(meta->className())).arg(name);
2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        buf = str.toLatin1();
2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return jsString(exec, buf.constData());
2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2975f1ab04193ad0130ca8204aadaceae083aca9881Feng QianJSValue QtInstance::numberValue(ExecState* exec) const
2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return jsNumber(exec, 0);
3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3025f1ab04193ad0130ca8204aadaceae083aca9881Feng QianJSValue QtInstance::booleanValue() const
3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // ECMA 9.2
3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return jsBoolean(true);
3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3085f1ab04193ad0130ca8204aadaceae083aca9881Feng QianJSValue QtInstance::valueOf(ExecState* exec) const
3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return stringValue(exec);
3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// In qt_runtime.cpp
3145f1ab04193ad0130ca8204aadaceae083aca9881Feng QianJSValue convertQVariantToValue(ExecState*, PassRefPtr<RootObject> root, const QVariant& variant);
3155f1ab04193ad0130ca8204aadaceae083aca9881Feng QianQVariant convertValueToQVariant(ExecState*, JSValue, QMetaType::Type hint, int *distance);
3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst char* QtField::name() const
3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_type == MetaProperty)
3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return m_property.name();
3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else if (m_type == ChildObject && m_childObject)
3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return m_childObject->objectName().toLatin1();
3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else if (m_type == DynamicProperty)
3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return m_dynamicProperty.constData();
3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return ""; // deleted child object
3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3285f1ab04193ad0130ca8204aadaceae083aca9881Feng QianJSValue QtField::valueFromInstance(ExecState* exec, const Instance* inst) const
3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const QtInstance* instance = static_cast<const QtInstance*>(inst);
3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    QObject* obj = instance->getObject();
3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (obj) {
3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        QVariant val;
3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (m_type == MetaProperty) {
3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (m_property.isReadable())
3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                val = m_property.read(obj);
3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            else
3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return jsUndefined();
3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else if (m_type == ChildObject)
3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            val = QVariant::fromValue((QObject*) m_childObject);
3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else if (m_type == DynamicProperty)
3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            val = obj->property(m_dynamicProperty);
3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return convertQVariantToValue(exec, inst->rootObject(), val);
3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        QString msg = QString(QLatin1String("cannot access member `%1' of deleted QObject")).arg(QLatin1String(name()));
3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return throwError(exec, GeneralError, msg.toLatin1().constData());
3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianvoid QtField::setValueToInstance(ExecState* exec, const Instance* inst, JSValue aValue) const
3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_type == ChildObject) // QtScript doesn't allow setting to a named child
3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const QtInstance* instance = static_cast<const QtInstance*>(inst);
3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    QObject* obj = instance->getObject();
3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (obj) {
3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        QMetaType::Type argtype = QMetaType::Void;
3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (m_type == MetaProperty)
3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            argtype = (QMetaType::Type) QMetaType::type(m_property.typeName());
3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // dynamic properties just get any QVariant
3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        QVariant val = convertValueToQVariant(exec, aValue, argtype, 0);
3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (m_type == MetaProperty) {
3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (m_property.isWritable())
3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                m_property.write(obj, val);
3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else if (m_type == DynamicProperty)
3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            obj->setProperty(m_dynamicProperty.constData(), val);
3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        QString msg = QString(QLatin1String("cannot access member `%1' of deleted QObject")).arg(QLatin1String(name()));
3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        throwError(exec, GeneralError, msg.toLatin1().constData());
3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
380