[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