summaryrefslogtreecommitdiffstats
path: root/WebCore/bridge/qt/qt_class.cpp
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:30:52 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:30:52 -0800
commit8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2 (patch)
tree11425ea0b299d6fb89c6d3618a22d97d5bf68d0f /WebCore/bridge/qt/qt_class.cpp
parent648161bb0edfc3d43db63caed5cc5213bc6cb78f (diff)
downloadexternal_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.zip
external_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.tar.gz
external_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'WebCore/bridge/qt/qt_class.cpp')
-rw-r--r--WebCore/bridge/qt/qt_class.cpp217
1 files changed, 217 insertions, 0 deletions
diff --git a/WebCore/bridge/qt/qt_class.cpp b/WebCore/bridge/qt/qt_class.cpp
new file mode 100644
index 0000000..3fe3f89
--- /dev/null
+++ b/WebCore/bridge/qt/qt_class.cpp
@@ -0,0 +1,217 @@
+/*
+ * 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(QString::fromUtf16((const ushort*)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;
+ }
+}
+
+}
+}
+