PageRenderTime 21ms CodeModel.GetById 1ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 0ms

/platform/external/webkit/WebCore/bridge/qt/qt_class.cpp

https://github.com/aharish/totoro-gb-opensource-update2
C++ | 217 lines | 138 code | 35 blank | 44 comment | 35 complexity | 17462c9caf3604d1748b9e2e04218fef MD5 | raw file
  1/*
  2 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
  3 *
  4 *  This library is free software; you can redistribute it and/or
  5 *  modify it under the terms of the GNU Lesser General Public
  6 *  License as published by the Free Software Foundation; either
  7 *  version 2 of the License, or (at your option) any later version.
  8 *
  9 *  This library is distributed in the hope that it will be useful,
 10 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12 *  Lesser General Public License for more details.
 13 *
 14 *  You should have received a copy of the GNU Lesser General Public
 15 *  License along with this library; if not, write to the Free Software
 16 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 17 *
 18 */
 19
 20#include "config.h"
 21#include "Identifier.h"
 22
 23#include "qt_class.h"
 24#include "qt_instance.h"
 25#include "qt_runtime.h"
 26
 27#include <qmetaobject.h>
 28#include <qdebug.h>
 29
 30namespace JSC {
 31namespace Bindings {
 32
 33QtClass::QtClass(const QMetaObject* mo)
 34    : m_metaObject(mo)
 35{
 36}
 37
 38QtClass::~QtClass()
 39{
 40}
 41
 42typedef HashMap<const QMetaObject*, QtClass*> ClassesByMetaObject;
 43static ClassesByMetaObject* classesByMetaObject = 0;
 44
 45QtClass* QtClass::classForObject(QObject* o)
 46{
 47    if (!classesByMetaObject)
 48        classesByMetaObject = new ClassesByMetaObject;
 49
 50    const QMetaObject* mo = o->metaObject();
 51    QtClass* aClass = classesByMetaObject->get(mo);
 52    if (!aClass) {
 53        aClass = new QtClass(mo);
 54        classesByMetaObject->set(mo, aClass);
 55    }
 56
 57    return aClass;
 58}
 59
 60const char* QtClass::name() const
 61{
 62    return m_metaObject->className();
 63}
 64
 65// We use this to get at signals (so we can return a proper function object,
 66// and not get wrapped in RuntimeMethod). Also, use this for methods,
 67// so we can cache the object and return the same object for the same
 68// identifier.
 69JSValue QtClass::fallbackObject(ExecState* exec, Instance* inst, const Identifier& identifier)
 70{
 71    QtInstance* qtinst = static_cast<QtInstance*>(inst);
 72
 73    QByteArray name(identifier.ascii());
 74
 75    // First see if we have a cache hit
 76    JSObject* val = qtinst->m_methods.value(name);
 77    if (val)
 78        return val;
 79
 80    // Nope, create an entry
 81    QByteArray normal = QMetaObject::normalizedSignature(name.constData());
 82
 83    // See if there is an exact match
 84    int index = -1;
 85    if (normal.contains('(') && (index = m_metaObject->indexOfMethod(normal)) != -1) {
 86        QMetaMethod m = m_metaObject->method(index);
 87        if (m.access() != QMetaMethod::Private) {
 88            QtRuntimeMetaMethod* val = new (exec) QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false);
 89            qtinst->m_methods.insert(name, val);
 90            return val;
 91        }
 92    }
 93
 94    // Nope.. try a basename match
 95    int count = m_metaObject->methodCount();
 96    for (index = count - 1; index >= 0; --index) {
 97        const QMetaMethod m = m_metaObject->method(index);
 98        if (m.access() == QMetaMethod::Private)
 99            continue;
100
101        QByteArray signature = m.signature();
102        signature.truncate(signature.indexOf('('));
103
104        if (normal == signature) {
105            QtRuntimeMetaMethod* val = new (exec) QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false);
106            qtinst->m_methods.insert(name, val);
107            return val;
108        }
109    }
110
111    return jsUndefined();
112}
113
114// This functionality is handled by the fallback case above...
115MethodList QtClass::methodsNamed(const Identifier&, Instance*) const
116{
117    return MethodList();
118}
119
120// ### we may end up with a different search order than QtScript by not
121// folding this code into the fallbackMethod above, but Fields propagate out
122// of the binding code
123Field* QtClass::fieldNamed(const Identifier& identifier, Instance* instance) const
124{
125    // Check static properties first
126    QtInstance* qtinst = static_cast<QtInstance*>(instance);
127
128    QObject* obj = qtinst->getObject();
129    UString ustring = identifier.ustring();
130    QString objName((const QChar*)ustring.rep()->data(), ustring.size());
131    QByteArray ba = objName.toAscii();
132
133    // First check for a cached field
134    QtField* f = qtinst->m_fields.value(objName);
135
136    if (obj) {
137        if (f) {
138            // We only cache real metaproperties, but we do store the
139            // other types so we can delete them later
140            if (f->fieldType() == QtField::MetaProperty)
141                return f;
142            else if (f->fieldType() == QtField::DynamicProperty) {
143                if (obj->dynamicPropertyNames().indexOf(ba) >= 0)
144                    return f;
145                else {
146                    // Dynamic property that disappeared
147                    qtinst->m_fields.remove(objName);
148                    delete f;
149                }
150            } else {
151                QList<QObject*> children = obj->children();
152                for (int index = 0; index < children.count(); ++index) {
153                    QObject *child = children.at(index);
154                    if (child->objectName() == objName)
155                        return f;
156                }
157
158                // Didn't find it, delete it from the cache
159                qtinst->m_fields.remove(objName);
160                delete f;
161            }
162        }
163
164        int index = m_metaObject->indexOfProperty(identifier.ascii());
165        if (index >= 0) {
166            QMetaProperty prop = m_metaObject->property(index);
167
168            if (prop.isScriptable(obj)) {
169                f = new QtField(prop);
170                qtinst->m_fields.insert(objName, f);
171                return f;
172            }
173        }
174
175        // Dynamic properties
176        index = obj->dynamicPropertyNames().indexOf(ba);
177        if (index >= 0) {
178            f = new QtField(ba);
179            qtinst->m_fields.insert(objName, f);
180            return f;
181        }
182
183        // Child objects
184
185        QList<QObject*> children = obj->children();
186        for (index = 0; index < children.count(); ++index) {
187            QObject *child = children.at(index);
188            if (child->objectName() == objName) {
189                f = new QtField(child);
190                qtinst->m_fields.insert(objName, f);
191                return f;
192            }
193        }
194
195        // Nothing named this
196        return 0;
197    } else {
198        QByteArray ba(identifier.ascii());
199        // For compatibility with qtscript, cached methods don't cause
200        // errors until they are accessed, so don't blindly create an error
201        // here.
202        if (qtinst->m_methods.contains(ba))
203            return 0;
204
205        // deleted qobject, but can't throw an error from here (no exec)
206        // create a fake QtField that will throw upon access
207        if (!f) {
208            f = new QtField(ba);
209            qtinst->m_fields.insert(objName, f);
210        }
211        return f;
212    }
213}
214
215}
216}
217