/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. #include "config.h"
  20. #include "Identifier.h"
  21. #include "qt_class.h"
  22. #include "qt_instance.h"
  23. #include "qt_runtime.h"
  24. #include <qmetaobject.h>
  25. #include <qdebug.h>
  26. namespace JSC {
  27. namespace Bindings {
  28. QtClass::QtClass(const QMetaObject* mo)
  29. : m_metaObject(mo)
  30. {
  31. }
  32. QtClass::~QtClass()
  33. {
  34. }
  35. typedef HashMap<const QMetaObject*, QtClass*> ClassesByMetaObject;
  36. static ClassesByMetaObject* classesByMetaObject = 0;
  37. QtClass* QtClass::classForObject(QObject* o)
  38. {
  39. if (!classesByMetaObject)
  40. classesByMetaObject = new ClassesByMetaObject;
  41. const QMetaObject* mo = o->metaObject();
  42. QtClass* aClass = classesByMetaObject->get(mo);
  43. if (!aClass) {
  44. aClass = new QtClass(mo);
  45. classesByMetaObject->set(mo, aClass);
  46. }
  47. return aClass;
  48. }
  49. const char* QtClass::name() const
  50. {
  51. return m_metaObject->className();
  52. }
  53. // We use this to get at signals (so we can return a proper function object,
  54. // and not get wrapped in RuntimeMethod). Also, use this for methods,
  55. // so we can cache the object and return the same object for the same
  56. // identifier.
  57. JSValue QtClass::fallbackObject(ExecState* exec, Instance* inst, const Identifier& identifier)
  58. {
  59. QtInstance* qtinst = static_cast<QtInstance*>(inst);
  60. QByteArray name(identifier.ascii());
  61. // First see if we have a cache hit
  62. JSObject* val = qtinst->m_methods.value(name);
  63. if (val)
  64. return val;
  65. // Nope, create an entry
  66. QByteArray normal = QMetaObject::normalizedSignature(name.constData());
  67. // See if there is an exact match
  68. int index = -1;
  69. if (normal.contains('(') && (index = m_metaObject->indexOfMethod(normal)) != -1) {
  70. QMetaMethod m = m_metaObject->method(index);
  71. if (m.access() != QMetaMethod::Private) {
  72. QtRuntimeMetaMethod* val = new (exec) QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false);
  73. qtinst->m_methods.insert(name, val);
  74. return val;
  75. }
  76. }
  77. // Nope.. try a basename match
  78. int count = m_metaObject->methodCount();
  79. for (index = count - 1; index >= 0; --index) {
  80. const QMetaMethod m = m_metaObject->method(index);
  81. if (m.access() == QMetaMethod::Private)
  82. continue;
  83. QByteArray signature = m.signature();
  84. signature.truncate(signature.indexOf('('));
  85. if (normal == signature) {
  86. QtRuntimeMetaMethod* val = new (exec) QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false);
  87. qtinst->m_methods.insert(name, val);
  88. return val;
  89. }
  90. }
  91. return jsUndefined();
  92. }
  93. // This functionality is handled by the fallback case above...
  94. MethodList QtClass::methodsNamed(const Identifier&, Instance*) const
  95. {
  96. return MethodList();
  97. }
  98. // ### we may end up with a different search order than QtScript by not
  99. // folding this code into the fallbackMethod above, but Fields propagate out
  100. // of the binding code
  101. Field* QtClass::fieldNamed(const Identifier& identifier, Instance* instance) const
  102. {
  103. // Check static properties first
  104. QtInstance* qtinst = static_cast<QtInstance*>(instance);
  105. QObject* obj = qtinst->getObject();
  106. UString ustring = identifier.ustring();
  107. QString objName((const QChar*)ustring.rep()->data(), ustring.size());
  108. QByteArray ba = objName.toAscii();
  109. // First check for a cached field
  110. QtField* f = qtinst->m_fields.value(objName);
  111. if (obj) {
  112. if (f) {
  113. // We only cache real metaproperties, but we do store the
  114. // other types so we can delete them later
  115. if (f->fieldType() == QtField::MetaProperty)
  116. return f;
  117. else if (f->fieldType() == QtField::DynamicProperty) {
  118. if (obj->dynamicPropertyNames().indexOf(ba) >= 0)
  119. return f;
  120. else {
  121. // Dynamic property that disappeared
  122. qtinst->m_fields.remove(objName);
  123. delete f;
  124. }
  125. } else {
  126. QList<QObject*> children = obj->children();
  127. for (int index = 0; index < children.count(); ++index) {
  128. QObject *child = children.at(index);
  129. if (child->objectName() == objName)
  130. return f;
  131. }
  132. // Didn't find it, delete it from the cache
  133. qtinst->m_fields.remove(objName);
  134. delete f;
  135. }
  136. }
  137. int index = m_metaObject->indexOfProperty(identifier.ascii());
  138. if (index >= 0) {
  139. QMetaProperty prop = m_metaObject->property(index);
  140. if (prop.isScriptable(obj)) {
  141. f = new QtField(prop);
  142. qtinst->m_fields.insert(objName, f);
  143. return f;
  144. }
  145. }
  146. // Dynamic properties
  147. index = obj->dynamicPropertyNames().indexOf(ba);
  148. if (index >= 0) {
  149. f = new QtField(ba);
  150. qtinst->m_fields.insert(objName, f);
  151. return f;
  152. }
  153. // Child objects
  154. QList<QObject*> children = obj->children();
  155. for (index = 0; index < children.count(); ++index) {
  156. QObject *child = children.at(index);
  157. if (child->objectName() == objName) {
  158. f = new QtField(child);
  159. qtinst->m_fields.insert(objName, f);
  160. return f;
  161. }
  162. }
  163. // Nothing named this
  164. return 0;
  165. } else {
  166. QByteArray ba(identifier.ascii());
  167. // For compatibility with qtscript, cached methods don't cause
  168. // errors until they are accessed, so don't blindly create an error
  169. // here.
  170. if (qtinst->m_methods.contains(ba))
  171. return 0;
  172. // deleted qobject, but can't throw an error from here (no exec)
  173. // create a fake QtField that will throw upon access
  174. if (!f) {
  175. f = new QtField(ba);
  176. qtinst->m_fields.insert(objName, f);
  177. }
  178. return f;
  179. }
  180. }
  181. }
  182. }