/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
- /*
- * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
- #include "config.h"
- #include "Identifier.h"
- #include "qt_class.h"
- #include "qt_instance.h"
- #include "qt_runtime.h"
- #include <qmetaobject.h>
- #include <qdebug.h>
- namespace JSC {
- namespace Bindings {
- QtClass::QtClass(const QMetaObject* mo)
- : m_metaObject(mo)
- {
- }
- QtClass::~QtClass()
- {
- }
- typedef HashMap<const QMetaObject*, QtClass*> ClassesByMetaObject;
- static ClassesByMetaObject* classesByMetaObject = 0;
- QtClass* QtClass::classForObject(QObject* o)
- {
- if (!classesByMetaObject)
- classesByMetaObject = new ClassesByMetaObject;
- const QMetaObject* mo = o->metaObject();
- QtClass* aClass = classesByMetaObject->get(mo);
- if (!aClass) {
- aClass = new QtClass(mo);
- classesByMetaObject->set(mo, aClass);
- }
- return aClass;
- }
- const char* QtClass::name() const
- {
- return m_metaObject->className();
- }
- // We use this to get at signals (so we can return a proper function object,
- // and not get wrapped in RuntimeMethod). Also, use this for methods,
- // so we can cache the object and return the same object for the same
- // identifier.
- JSValue QtClass::fallbackObject(ExecState* exec, Instance* inst, const Identifier& identifier)
- {
- QtInstance* qtinst = static_cast<QtInstance*>(inst);
- QByteArray name(identifier.ascii());
- // First see if we have a cache hit
- JSObject* val = qtinst->m_methods.value(name);
- if (val)
- return val;
- // Nope, create an entry
- QByteArray normal = QMetaObject::normalizedSignature(name.constData());
- // See if there is an exact match
- int index = -1;
- if (normal.contains('(') && (index = m_metaObject->indexOfMethod(normal)) != -1) {
- QMetaMethod m = m_metaObject->method(index);
- if (m.access() != QMetaMethod::Private) {
- QtRuntimeMetaMethod* val = new (exec) QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false);
- qtinst->m_methods.insert(name, val);
- return val;
- }
- }
- // Nope.. try a basename match
- int count = m_metaObject->methodCount();
- for (index = count - 1; index >= 0; --index) {
- const QMetaMethod m = m_metaObject->method(index);
- if (m.access() == QMetaMethod::Private)
- continue;
- QByteArray signature = m.signature();
- signature.truncate(signature.indexOf('('));
- if (normal == signature) {
- QtRuntimeMetaMethod* val = new (exec) QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false);
- qtinst->m_methods.insert(name, val);
- return val;
- }
- }
- return jsUndefined();
- }
- // This functionality is handled by the fallback case above...
- MethodList QtClass::methodsNamed(const Identifier&, Instance*) const
- {
- return MethodList();
- }
- // ### we may end up with a different search order than QtScript by not
- // folding this code into the fallbackMethod above, but Fields propagate out
- // of the binding code
- Field* QtClass::fieldNamed(const Identifier& identifier, Instance* instance) const
- {
- // Check static properties first
- QtInstance* qtinst = static_cast<QtInstance*>(instance);
- QObject* obj = qtinst->getObject();
- UString ustring = identifier.ustring();
- QString objName((const QChar*)ustring.rep()->data(), ustring.size());
- QByteArray ba = objName.toAscii();
- // First check for a cached field
- QtField* f = qtinst->m_fields.value(objName);
- if (obj) {
- if (f) {
- // We only cache real metaproperties, but we do store the
- // other types so we can delete them later
- if (f->fieldType() == QtField::MetaProperty)
- return f;
- else if (f->fieldType() == QtField::DynamicProperty) {
- if (obj->dynamicPropertyNames().indexOf(ba) >= 0)
- return f;
- else {
- // Dynamic property that disappeared
- qtinst->m_fields.remove(objName);
- delete f;
- }
- } else {
- QList<QObject*> children = obj->children();
- for (int index = 0; index < children.count(); ++index) {
- QObject *child = children.at(index);
- if (child->objectName() == objName)
- return f;
- }
- // Didn't find it, delete it from the cache
- qtinst->m_fields.remove(objName);
- delete f;
- }
- }
- int index = m_metaObject->indexOfProperty(identifier.ascii());
- if (index >= 0) {
- QMetaProperty prop = m_metaObject->property(index);
- if (prop.isScriptable(obj)) {
- f = new QtField(prop);
- qtinst->m_fields.insert(objName, f);
- return f;
- }
- }
- // Dynamic properties
- index = obj->dynamicPropertyNames().indexOf(ba);
- if (index >= 0) {
- f = new QtField(ba);
- qtinst->m_fields.insert(objName, f);
- return f;
- }
- // Child objects
- QList<QObject*> children = obj->children();
- for (index = 0; index < children.count(); ++index) {
- QObject *child = children.at(index);
- if (child->objectName() == objName) {
- f = new QtField(child);
- qtinst->m_fields.insert(objName, f);
- return f;
- }
- }
- // Nothing named this
- return 0;
- } else {
- QByteArray ba(identifier.ascii());
- // For compatibility with qtscript, cached methods don't cause
- // errors until they are accessed, so don't blindly create an error
- // here.
- if (qtinst->m_methods.contains(ba))
- return 0;
- // deleted qobject, but can't throw an error from here (no exec)
- // create a fake QtField that will throw upon access
- if (!f) {
- f = new QtField(ba);
- qtinst->m_fields.insert(objName, f);
- }
- return f;
- }
- }
- }
- }