]>
git.saurik.com Git - apple/javascriptcore.git/blob - bindings/qt/qt_class.cpp
59730b875ff4cbf1d37b385440070cbed58af3ff
2 * Copyright (C) 2006 Trolltech ASA
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.
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.
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
21 #include "identifier.h"
24 #include "qt_instance.h"
25 #include "qt_runtime.h"
27 #include <qmetaobject.h>
33 QtClass::QtClass(const QMetaObject
* mo
)
42 typedef HashMap
<const QMetaObject
*, QtClass
*> ClassesByMetaObject
;
43 static ClassesByMetaObject
* classesByMetaObject
= 0;
45 QtClass
* QtClass::classForObject(QObject
* o
)
47 if (!classesByMetaObject
)
48 classesByMetaObject
= new ClassesByMetaObject
;
50 const QMetaObject
* mo
= o
->metaObject();
51 QtClass
* aClass
= classesByMetaObject
->get(mo
);
53 aClass
= new QtClass(mo
);
54 classesByMetaObject
->set(mo
, aClass
);
60 const char* QtClass::name() const
62 return m_metaObject
->className();
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 JSValue* and return the same JSValue for the same
70 // Unfortunately... we need to gcProtect our JSValues, since we don't have
71 // access to an actual JS class that can mark() our JSValues.
73 JSValue
* QtClass::fallbackObject(ExecState
*exec
, Instance
*inst
, const Identifier
&identifier
)
75 QtInstance
* qtinst
= static_cast<QtInstance
*>(inst
);
77 QByteArray
name(identifier
.ascii());
79 // First see if we have a cache hit
80 JSValue
* val
= qtinst
->m_methods
.value(name
);
84 // Nope, create an entry
85 QByteArray normal
= QMetaObject::normalizedSignature(name
.constData());
87 // See if there is an exact match
89 if (normal
.contains('(') && (index
= m_metaObject
->indexOfMethod(normal
)) != -1) {
90 QMetaMethod m
= m_metaObject
->method(index
);
91 if (m
.access() != QMetaMethod::Private
) {
92 JSValue
*val
= new QtRuntimeMetaMethod(exec
, identifier
, static_cast<QtInstance
*>(inst
), index
, normal
, false);
94 qtinst
->m_methods
.insert(name
, val
);
99 // Nope.. try a basename match
100 int count
= m_metaObject
->methodCount();
101 for (index
= count
- 1; index
>= 0; --index
) {
102 const QMetaMethod m
= m_metaObject
->method(index
);
103 if (m
.access() == QMetaMethod::Private
)
106 QByteArray signature
= m
.signature();
107 signature
.truncate(signature
.indexOf('('));
109 if (normal
== signature
) {
110 JSValue
* val
= new QtRuntimeMetaMethod(exec
, identifier
, static_cast<QtInstance
*>(inst
), index
, normal
, false);
112 qtinst
->m_methods
.insert(name
, val
);
117 return jsUndefined();
120 // This functionality is handled by the fallback case above...
121 MethodList
QtClass::methodsNamed(const Identifier
&, Instance
*) const
126 // ### we may end up with a different search order than QtScript by not
127 // folding this code into the fallbackMethod above, but Fields propagate out
128 // of the binding code
129 Field
* QtClass::fieldNamed(const Identifier
& identifier
, Instance
* instance
) const
131 // Check static properties first
132 QtInstance
* qtinst
= static_cast<QtInstance
*>(instance
);
134 QObject
* obj
= qtinst
->getObject();
135 UString ustring
= identifier
.ustring();
136 QString
objName(QString::fromUtf16((const ushort
*)ustring
.rep()->data(),ustring
.size()));
137 QByteArray ba
= objName
.toAscii();
139 // First check for a cached field
140 QtField
* f
= qtinst
->m_fields
.value(objName
);
144 // We only cache real metaproperties, but we do store the
145 // other types so we can delete them later
146 if (f
->fieldType() == QtField::MetaProperty
)
148 else if (f
->fieldType() == QtField::DynamicProperty
) {
149 if (obj
->dynamicPropertyNames().indexOf(ba
) >= 0)
152 // Dynamic property that disappeared
153 qtinst
->m_fields
.remove(objName
);
157 QList
<QObject
*> children
= obj
->children();
158 for (int index
= 0; index
< children
.count(); ++index
) {
159 QObject
*child
= children
.at(index
);
160 if (child
->objectName() == objName
)
164 // Didn't find it, delete it from the cache
165 qtinst
->m_fields
.remove(objName
);
170 int index
= m_metaObject
->indexOfProperty(identifier
.ascii());
172 QMetaProperty prop
= m_metaObject
->property(index
);
174 if (prop
.isScriptable(obj
)) {
175 f
= new QtField(prop
);
176 qtinst
->m_fields
.insert(objName
, f
);
181 // Dynamic properties
182 index
= obj
->dynamicPropertyNames().indexOf(ba
);
185 qtinst
->m_fields
.insert(objName
, f
);
191 QList
<QObject
*> children
= obj
->children();
192 for (index
= 0; index
< children
.count(); ++index
) {
193 QObject
*child
= children
.at(index
);
194 if (child
->objectName() == objName
) {
195 f
= new QtField(child
);
196 qtinst
->m_fields
.insert(objName
, f
);
201 // Nothing named this
204 QByteArray
ba(identifier
.ascii());
205 // For compatibility with qtscript, cached methods don't cause
206 // errors until they are accessed, so don't blindly create an error
208 if (qtinst
->m_methods
.contains(ba
))
211 // deleted qobject, but can't throw an error from here (no exec)
212 // create a fake QtField that will throw upon access
215 qtinst
->m_fields
.insert(objName
, f
);