[Development] QML and JavaScript extensions
Topi Mäenpää
topi.maenpaa at intopii.com
Mon Nov 11 09:38:28 CET 2013
Hi,
A couple of weeks ago, I wrote about this issue on Qt forums
(https://qt-project.org/forums/viewthread/33278/) and was advised to
bring it up here. So, here it goes again.
I'm the author of Into (http://intopii.com/into,
https://github.com/topiolli/into/) and a long-time Qt programmer since
version 3. I'm currently in charge of designing a new generation machine
vision platform that builds on Qt. To add some weight to this I'd like
to mention that we are currently in discussions about buying Digia's
development resources to the project.
I've been using Qt's JavaScript engines to provide a scripting interface
to Into about ever since QScriptEngine was introduced. It provided
fairly good extension interfaces and I was able to implement almost
everything I wanted using the public API.
Enter QML. From its introduction, it has been clear that using
JavaScript extension from QML applications was not a planned use case.
In Qt4, QDeclarativeEngine used QScriptEngine to evaluate JavaScript,
but it deliberately hid that as an "implementation detail". I brought up
this issue on the forums a couple of years ago
(http://qt-project.org/forums/viewthread/4333), and talked with
developers at Nokia and later Digia in person, but the situation hasn't
got any better. On the contrary, actually.
In Qt5, JavaScript as such is practically deprecated. It is only QML
now. Yes, there is QJSEngine, but it has no extension mechanism. In the
source code, even QJSEngine makes references to QML. To me, this is an
indication that providing QJSEngine as a top-level JavaScript engine
really was an afterthought. The switch to V4 in Qt 5.2 is another
indication: V8 would have been a better choice for pure JavaScript.
V8 was touted as the unifying solution for Qt JavaScript support. It
really would have made sense to use the same script engine everywhere. I
feared that the script engine would be changed once again and discussed
with Digia guys before switching to Qt5. The message was clear: QtScript
will be deprecated and QML with V8 is the future. This seemed to be a
sure bet, and the pointer to QV8Engine was even available through
QJSEngine::handle().
It wasn't until a few weeks ago somebody hinted me about the upcoming
change. My bad, of course. I should have followed the discussions more
closely. The funny thing is that the V4 implementation now needs to be
called QV8Engine to retain binary compatibility.
Following the switch to V4 Qt now has three different JavaScript
implementations: one in QtScript, another in QtWebkit, and yet another
one in QtDeclarative. They are not compatible to each other, and the
only one that provides an extension interface is the deprecated QtScript
module. There is no documented way of adding JS extensions to either
Webkit or (more importantly) QML.
The extension interface in QML is not only incomplete but also broken in
many ways (I have been hit at least by QTBUG-33976, QTBUG-33815,
QTBUG-33514, QTBUG-33438, QTBUG-33403, QTBUG-33398, QTBUG-30730 and
QTBUG-29769). This makes it practically impossible to write many types
of extensions to QML. The only use case that has good support is UI
components implemented by deriving QQuickItem. This is quite surprising
given that QML doesn't provide even such fundamental functionality as
file system access.
Consequently, I have needed to hack my extensions by using hidden
low-level APIs. As mentioned, this was just a matter of finding a
pointer to the internal QScriptEngine in Qt4. In Qt5, I have used the V8
API directly. Now that 5.2 uses a new engine I need to rework my
extensions once again.
Would it be possible to either fix the JS engine or, preferably, provide
a stable JavaScript extension API that could be used from QML?
Regards,
--
Topi Mäenpää
Co-founder, Intopii
intopii.com
+358 40 774 7749
More information about the Development
mailing list