Reviewed by Simon.
+ Add support for calling QObjects.
+ Add support for invokeDefaultMethod (via a call to
+ a specific slot), and also allow using it as a
+ constructor, like QtScript.
+
+
+ * bindings/qt/qt_class.cpp:
+ (KJS::Bindings::QtClass::fallbackObject):
+ * bindings/qt/qt_instance.cpp:
+ (KJS::Bindings::QtRuntimeObjectImp::construct):
+ (KJS::Bindings::QtInstance::QtInstance):
+ (KJS::Bindings::QtInstance::~QtInstance):
+ (KJS::Bindings::QtInstance::implementsCall):
+ (KJS::Bindings::QtInstance::invokeDefaultMethod):
+ * bindings/qt/qt_instance.h:
+ * bindings/qt/qt_runtime.cpp:
+ (KJS::Bindings::findMethodIndex):
+ (KJS::Bindings::QtRuntimeMetaMethod::QtRuntimeMetaMethod):
+ (KJS::Bindings::QtRuntimeMetaMethod::callAsFunction):
+ * bindings/qt/qt_runtime.h:
+
+2008-01-24 Michael Goddard <michael.goddard@trolltech.com>
+
+ Reviewed by Simon.
+
Code style cleanups.
Add spaces before/after braces in inline function.
if (normal.contains('(') && (index = m_metaObject->indexOfMethod(normal)) != -1) {
QMetaMethod m = m_metaObject->method(index);
if (m.access() != QMetaMethod::Private) {
- JSValue *val = new QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal);
+ JSValue *val = new QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false);
gcProtect(val);
qtinst->m_methods.insert(name, val);
return val;
signature.truncate(signature.indexOf('('));
if (normal == signature) {
- JSValue* val = new QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal);
+ JSValue* val = new QtRuntimeMetaMethod(exec, identifier, static_cast<QtInstance*>(inst), index, normal, false);
gcProtect(val);
qtinst->m_methods.insert(name, val);
return val;
#include "config.h"
#include "qt_instance.h"
+#include "JSGlobalObject.h"
#include "list.h"
#include "qt_class.h"
#include "qt_runtime.h"
#include "PropertyNameArray.h"
#include "runtime_object.h"
+#include "object_object.h"
#include <qmetaobject.h>
#include <qdebug.h>
QtRuntimeObjectImp(Instance*);
~QtRuntimeObjectImp();
virtual void invalidate();
+
+ // Additions
+ virtual bool implementsConstruct() const {return implementsCall();}
+ virtual JSObject* construct(ExecState* exec, const List& args);
protected:
void removeFromCache();
};
cachedObjects.remove(key);
}
+JSObject* QtRuntimeObjectImp::construct(ExecState* exec, const List& args)
+{
+ // ECMA 15.2.2.1 (?)
+ JSValue *val = callAsFunction(exec, this, args);
+
+ if (!val || val->type() == NullType || val->type() == UndefinedType)
+ return new JSObject(exec->lexicalGlobalObject()->objectPrototype());
+ else
+ return val->toObject(exec);
+}
+
// QtInstance
QtInstance::QtInstance(QObject* o, PassRefPtr<RootObject> rootObject)
: Instance(rootObject)
, m_class(0)
, m_object(o)
, m_hashkey(o)
+ , m_defaultMethod(0)
+ , m_defaultMethodIndex(-2)
{
}
delete f;
}
m_fields.clear();
+
+ if (m_defaultMethod)
+ gcUnprotect(m_defaultMethod);
}
QtInstance* QtInstance::getQtInstance(QObject* o, PassRefPtr<RootObject> rootObject)
// Do nothing.
}
-bool QtInstance::implementsCall() const
-{
- // typeof object that implements call == function
- return false;
-}
-
void QtInstance::getPropertyNames(ExecState* , PropertyNameArray& array)
{
// This is the enumerable properties, so put:
return jsUndefined();
}
-JSValue* QtInstance::invokeDefaultMethod(ExecState* exec, const List& )
+bool QtInstance::implementsCall() const
{
- // ### QtScript tries to invoke a meta method qscript_call
- if (!getObject()) {
- return throwError(exec, GeneralError, "cannot call function of deleted QObject");
+ // See if we have qscript_call
+ if (m_defaultMethodIndex == -2) {
+ if (m_object) {
+ const QMetaObject* meta = m_object->metaObject();
+ int count = meta->methodCount();
+ const QByteArray defsig("qscript_call");
+ for (int index = count - 1; index >= 0; --index) {
+ const QMetaMethod m = meta->method(index);
+
+ QByteArray signature = m.signature();
+ signature.truncate(signature.indexOf('('));
+
+ if (defsig == signature) {
+ m_defaultMethodIndex = index;
+ break;
+ }
+ }
+ }
+
+ if (m_defaultMethodIndex == -2) // Not checked
+ m_defaultMethodIndex = -1; // No qscript_call
}
- return jsUndefined();
+
+ // typeof object that implements call == function
+ return (m_defaultMethodIndex >= 0);
+}
+
+JSValue* QtInstance::invokeDefaultMethod(ExecState* exec, const List& args)
+{
+ // QtScript tries to invoke a meta method qscript_call
+ if (!getObject())
+ return throwError(exec, GeneralError, "cannot call function of deleted QObject");
+
+ // implementsCall will update our default method cache, if possible
+ if (implementsCall()) {
+ if (!m_defaultMethod) {
+ m_defaultMethod = new QtRuntimeMetaMethod(exec, Identifier("[[Call]]"),this, m_defaultMethodIndex, QByteArray("qscript_call"), true);
+ gcProtect(m_defaultMethod);
+ }
+
+ return m_defaultMethod->callAsFunction(exec, 0, args); // Luckily QtRuntimeMetaMethod ignores the obj parameter
+ } else
+ return throwError(exec, TypeError, "not a function");
}
JSValue* QtInstance::defaultValue(JSType hint) const
class QtClass;
class QtField;
+class QtRuntimeMetaMethod;
class QtInstance : public Instance
{
QObject* m_hashkey;
mutable QHash<QByteArray,JSValue*> m_methods;
mutable QHash<QString,QtField*> m_fields;
+ mutable QtRuntimeMetaMethod* m_defaultMethod;
+ mutable int m_defaultMethodIndex;
};
} // namespace Bindings
static int findMethodIndex(ExecState* exec,
const QMetaObject* meta,
const QByteArray& signature,
+ bool allowPrivate,
const List& jsArgs,
QVarLengthArray<QVariant, 10> &vars,
void** vvars,
const QMetaMethod m = meta->method(i);
// Don't choose private methods
- if (m.access() == QMetaMethod::Private)
+ if (m.access() == QMetaMethod::Private && !allowPrivate)
continue;
// try and find all matching named methods
return index;
}
-QtRuntimeMetaMethod::QtRuntimeMetaMethod(ExecState* exec, const Identifier& ident, PassRefPtr<QtInstance> inst, int index, const QByteArray& signature)
+QtRuntimeMetaMethod::QtRuntimeMetaMethod(ExecState* exec, const Identifier& ident, PassRefPtr<QtInstance> inst, int index, const QByteArray& signature, bool allowPrivate)
: QtRuntimeMethod (new QtRuntimeMetaMethodData(), exec, ident, inst)
{
QW_D(QtRuntimeMetaMethod);
d->m_index = index;
d->m_connect = 0;
d->m_disconnect = 0;
+ d->m_allowPrivate = allowPrivate;
}
void QtRuntimeMetaMethod::mark()
int methodIndex;
JSObject* errorObj = 0;
- if ((methodIndex = findMethodIndex(exec, obj->metaObject(), d->m_signature, args, vargs, (void**)qargs, &errorObj)) != -1) {
+ if ((methodIndex = findMethodIndex(exec, obj->metaObject(), d->m_signature, d->m_allowPrivate, args, vargs, (void **)qargs, &errorObj)) != -1) {
if (obj->qt_metacall(QMetaObject::InvokeMetaMethod, methodIndex, qargs) >= 0)
return jsUndefined();
public:
~QtRuntimeMetaMethodData();
QByteArray m_signature;
+ bool m_allowPrivate;
int m_index;
QtRuntimeConnectionMethod *m_connect;
QtRuntimeConnectionMethod *m_disconnect;
class QtRuntimeMetaMethod : public QtRuntimeMethod
{
public:
- QtRuntimeMetaMethod(ExecState *exec, const Identifier &n, PassRefPtr<QtInstance> inst, int index, const QByteArray& signature );
+ QtRuntimeMetaMethod(ExecState *exec, const Identifier &n, PassRefPtr<QtInstance> inst, int index, const QByteArray& signature, bool allowPrivate);
virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);