[Interest] How to set a QJSValue with functions as a context property in QQmlContext?

Richard Weickelt richard at weickelt.de
Mon Apr 13 16:58:25 CEST 2020


Is there a way to set a QJSValue as a context property in QQmlContext and
retain function properties?

I am loading a .js file with QJSEngine::importModule(). The result is
QJSValue object containing all exported functions and properties from the
module.

    // file.js
    export function someFunction(someArg) {
        return someArg;
    }
    export someVar = "value";

    // importing code
    QJSValue module = engine->importModule("/path/to/file.js");

Now I want to evaluate JS code snippets with my modules installed. I need
fine-grained control over contexts and my real-world application uses a
context hierarchy. So I use QQmlExpression and set my imported module as a
context property:

    fileContext->setContextProperty("Test", importedObject.toVariant());
    QQmlExpression expression(fileContext,
                              nullptr,
                              "Test.someFunction(\"value\");");

    QVariant value = expression.evaluate(nullptr);
    qDebug() << value;

But the result is an invalid QVariant. I guess that the conversion from
QJSValue to QVariant cannot retain callable properties. It works when
referencing Test.someVar in above expression.

So is there a way to use a QJSValue object with functions as a context property?

Thanks

Here is the complete test project
---------------------------------

#include <QCoreApplication>
#include <QDebug>
#include <QTimer>
#include <QQmlContext>
#include <QQmlEngine>
#include <QQmlExpression>

void test() {
    QQmlEngine *engine = new QQmlEngine(QCoreApplication::instance());
    QQmlContext *fileContext = new QQmlContext(engine->rootContext());

    QJSValue importedObject = engine->importModule("/path/to/file.js");
    fileContext->setContextProperty("Test", importedObject.toVariant());
    QQmlExpression expression(fileContext,
                              nullptr,
                              "Test.someFunction(\"value\");");

    QVariant value = expression.evaluate(nullptr);
    qDebug() << value;
    QCoreApplication::quit();
}

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    QTimer::singleShot(0, &app, &test);
    return app.exec();
}


More information about the Interest mailing list