[Qt-interest] Webkit, callbacks and QScriptValue

Nikhil Marathe nsm.nikhil at gmail.com
Mon May 24 08:29:31 CEST 2010


Hi all,

I have a very vexing problem related to the QtScript/QtWebKit modules.

When using QtScript module and QScriptEngine, javascript functions can
be passed as first class values and received in C++ code. For example:

//////////////// test.h /////////////////////


#include <QObject>
#include <QScriptValue>

class Custom : public QObject
{
Q_OBJECT
public :
  Q_INVOKABLE void callback( const QScriptValue &func );
};

/////////////// test.cpp //////////////////

#include <QObject>
#include <QtScript>
#include <QDebug>
#include <QApplication>

#include "test.h"

void Custom::callback( const QScriptValue &func )
{
    qDebug() << func.isFunction();
}

int main(int argc, char **argv)
{
    QApplication app(argc, argv);

    QScriptEngine engine;
    QScriptValue customObj = engine.newQObject(new Custom);
    engine.globalObject().setProperty("needs", customObj);
    engine.evaluate("needs.callback(function() {print('hello');})").toString();

    app.exec();
}

///////////////////////////////////////////////

This will print 'true' since a function was passed to needs.callback.

Now consider the same 'Custom' object introduced into QWebFrame using
addToJavaScriptWindowObject()

/////////////// new test.cpp //////////////////
#include <QObject>
#include <QtScript>
#include <QDebug>
#include <QtWebKit>
#include <QApplication>

#include "test.h"

void Custom::callback( const QScriptValue &func )
{
    qDebug() << func.isFunction();
}

int main(int argc, char **argv)
{
    QApplication app(argc, argv);

// enable the console
    QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled,
true);

    QWebInspector insp;

    QWebView view;
    view.load(QUrl("http://www.google.com"));
    view.page()->currentFrame()->addToJavaScriptWindowObject("needs",
new Custom);
    insp.setPage(view.page());
    insp.show();

    app.exec();
}
////////////////////////////////////////////////////////

Only the web inspector will be shown. Start the javascript console by
clicking the little icon at the bottom-left. Type:

         needs.callback(function() {})

The error is: TypeError: cannot call callback(): unknown type `QScriptValue`

Why is this so? I would really appreciate if someone could point out
how to get this working. The weird thing is that QObject::connect()
invoked from within JavaScript accepts a callback function literal
perfectly fine. So how does it do that.

For example, if needs.callback was implemented in JavaScript:

   needs.prototype.callback = function(func) {
       this.someSignal.connect(func);
   }

If I were to emit someSignal(), func would be called.

I tried using Q_DECLARE_METATYPE and friends to get QScriptValue to be
a valid type, but to no avail. Peeking into the qt sources
(src/3rdparty/webkit/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp), we
see that there are tests to catch these kind of errors, but no test
which actually verifies custom types ( they are commented out ),
although a lot of setup hullabaloo is done at the top of the file with
Q_DECLARE_METATYPE.

Thanks in advance. I hope my problem is explained well, I can provide
more details if required. The .pro file is

/////////////// test.pro /////////////
SOURCES += test.cpp
HEADERS += test.h

CONFIG += qt debug

QT += script webkit
////////////////////////////////////////////

Regards,
Nikhil



More information about the Qt-interest-old mailing list