0

I'm moving from QScriptEngine (which is deprecated) to QJSEngine, and I see that I'm unable to use print:

  QJSEngine engine;

  QJSValue val = engine.evaluate(
        "print('123');"
        );

  if (val.isError()){
     qDebug() << "error: " << val.toString();
  }

  qDebug() << "val: " << val.toVariant();

The output is:

error:  "ReferenceError: print is not defined"

In QScriptEngine it works.

Then, what is the way to print something to console in QJSEngine? Can't find anything in docs. I tried to use console.log, but console is not defined as well.

Dmitry Frank
  • 10,417
  • 10
  • 64
  • 114

2 Answers2

6

From Qt 5.6 on, the solution is even easier: one can install Javascript extensions. One such extension is the console which provides a print function:

QJSEngine myEngine;
myEngine.installExtensions(QJSEngine::ConsoleExtension);
myEngine.eval("print(1 + 2)");
Mehrwolf
  • 8,208
  • 2
  • 26
  • 38
5

The print function is not implemented in QJSEngine. You will have to implement it yourself. Luckily you can write QObjects and make them available in your script. (See section "QObject Integration" at http://doc.qt.io/qt-5/qjsengine.html)

Here's how i've done it:

Create a class JSConsole inheriting from QObject:

Your own console class

jsconsole.h

#ifndef JSCONSOLE_H
#define JSCONSOLE_H

#include <QObject>

class JSConsole : public QObject
{
    Q_OBJECT
public:
    explicit JSConsole(QObject *parent = 0);

signals:

public slots:
    void log(QString msg);
};

#endif // JSCONSOLE_H

jsconsole.cpp

#include "jsconsole.h"
#include <QDebug>


JSConsole::JSConsole(QObject *parent) :
    QObject(parent)
{
}

void JSConsole::log(QString msg)
{
    qDebug() << "jsConsole: "<< msg;
}

Using it

Now you create a proxy object in the js engine by using QJSEngine.newQObject. After that you add it to your global object and use it.

QJSEngine engine;
JSConsole console;
QJSValue consoleObj =  engine.newQObject(&console);
engine.globalObject().setProperty("console", consoleObj);
QJSValue result = engine.evaluate("console.log('test');");

Error logging

I've searched a long time for errors in my c++ code, when i just made a spelling error in my js file. The following snippet would have helped avoid that.

if (result.isError())
{
    qDebug() << "result: " << result.property("lineNumber").toInt() << ":" << result.toString();
}

PS: First post after years of lurking. I've read tips on writing great answers but if I've made some mistakes/bad things please tell me.

May the code be with you

  • EDIT: As far as I understood, to make methods available from script, you have to define them as **slots**. – nitroxleecher Sep 04 '15 at 21:46
  • 1
    If availability of methods from scripts is the only reason to make them slots, then it's better to declare them with macro `Q_INVOKABLE` instead: it will show the programmer's intent more clearly. Thanks for the answer. And welcome to SO. – Dmitry Frank Sep 04 '15 at 22:15
  • This is really helping. Very little documentation available about this (and QJS Engine in general) – Ben Non Sep 17 '15 at 08:37