How to create a QJSValue object of type Error
-
Hi!,
Does anyone know how to create a QJSValue of type Error?
Context: I use QJSEngine::evaluate() to execute JavaScript code, that JavaScript code calls a C++ function. The QJSEngine::evaluate() throws a script exception (QJSValue of type Error) only if there is an error in the JavaScript code. Therefore, if there is an error in the C++ function I want to return a QJSValue of type error. I am following that path becasue QJSEngine::evaluate does not catch C++ exceptions.
Thank you so much.
-
I add additional info:
Here it is a code snippet of the intended functionality:
void CMainWindow::slot_ExecuteJVScript() { myCppClass myObject(parameters); //It has a foo() method. QJSEngine myEngine; myEngine.globalObject().setProperty("myObj", myEngine.newQObject(&myObject)); //Now we can access the C++ object from JavaScript code. QString myScriptJS = "var X = myObj.foo()"; //Calling a C++ function from JavaScript QJSValue myValue = myEngine.evaluate(myScriptJS); if(myValue.isError()) { //If there is an error in the JavaScript code we enter here //But I also wanto to enter here if there is an error in my foo() C++ function. } else { //Do things with myValue } }
Mini-Example of myCppClass::foo()
QJSValue myCppClass::foo() { if(something) { //Create a QJSValue myValue with some data return myValue; } else { //ERROR //Create a QJSValue of type Error return myValueOfTypeError; } }
-
@pablo_worker It seems that
ErrorObject
is under private headers so I doubt it could be used somehow.
A dirty workaround would be to force an error from that function :)
For eg. inside yourelse
part.else { QJSEngine engine; QJSValue val = engine.evaluate("f();"); //undefined function val.isError(); // this prints true }
-
@p3c0 Thank you.
However, the problem I see is now is that I can't return QJSValue. Because if it has been created inside a function it is deleted when the function ends.QJSValue myFunction() { QJSEngine engine; QJSValue val = engine.evaluate("asdf;"); //rubbish val.isError(); //this prints true return val; } QJSValue foo = myFunction(); foo.isError(); //this prints false
In addition, if it has been created with a QJSEngine, it loses its properties after the engine is deleted. Example:
else { QJSValue val; { QJSEngine engine; val = engine.evaluate("f()"); qDebug() << "val.isError:" << val.isError(); //this prints true } qDebug() << "val.isError:" << val.isError(); //this prints false }
I could pass the QJSEngine instance to the function, but still, I don't know how to hard-copy the QJSValue.
-
@pablo_worker You can pass reference of the same
QJSEngine
.QJSValue myFunction(QJSEngine &engine) { QJSValue val = engine.evaluate("asdf;"); //rubbish val.isError(); //this prints true return val; } QJSEngine myEngine; myFunction(myEngine).isError();
-
@pablo_worker Nope. They are copied.
-
@p3c0
I thought so, but there is something strange.
In this case it is true:
main.cpp#include <QCoreApplication> #include <QDebug> #include <QJSEngine> #include <QJSValue> QJSValue myFunction(QJSEngine &engine); int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QJSEngine myEngine; QJSValue theVal = myFunction(myEngine); qDebug() << "theVal.isError():" << theVal.isError(); //this prints true return a.exec(); } QJSValue myFunction(QJSEngine &engine) { QJSValue val = engine.evaluate("asf"); qDebug() << "val.isError():" << val.isError(); //this prints true return val; }
However, in this case it is not true
Calling the cpp function from JavaScript.
The debug output of this code is:In myFunction(), myVal.isError(): true
Outside, theVal.isError(): falseCMainWindow.h
#include <QMainWindow> #include <QtWidgets> #include "myCppClass.h" class CMainWindow : public QMainWindow { Q_OBJECT public: CMainWindow(QWidget *parent = 0) { setCentralWidget(new QWidget(this)); QJSEngine myEngine; myCppClass myObject(this, &myEngine); //this object has a myFunction() method. myEngine.globalObject().setProperty("myObj" ,myEngine.newQObject(&myObject)); QJSValue theVal = myEngine.evaluate("var X = myObj.myFunction();"); //calling the function from Javascript qDebug() << "Outside, theVal.isError():" << theVal.isError(); //this prints false } };
myCppClass.h
#include <QObject> #include <QJSEngine> #include <QJSValue> #include <QDebug> class myCppClass : public QObject { Q_OBJECT public: explicit myCppClass(QObject *parent = 0, QJSEngine *theEngine = nullptr) : QObject(parent), m_myEng(theEngine){} public slots: QJSValue myFunction(){ QJSValue myVal = m_myEng->evaluate("asdf"); //myVal will be a error. qDebug() << "In myFunction(), myVal.isError():" << myVal.isError(); //this prints true; return myVal; } private: QJSEngine *m_myEng; };
main.cpp
#include "CMainWindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); CMainWindow w; w.show(); return a.exec(); }
-
I have also noted something more, if I call the C++ function (that returns a QJSValue of type error) from JavaScript like this:
QJSValue theVal = myEngine.evaluate("var X = myObj.myFunction();"); //calling the c++ function from Javascript
I don't get the error in the variable "theVal" [theVal.isError() will say "false"]
However, if I call the function like this:
QJSValue theVal = myEngine.evaluate("var X = myObj.myFunction(); X "); // note the X
In this case the variable theVal does take the value X. And if I do theVal.isError() in this case it will show true.
Why is this?
-
@pablo_worker So AFAICS something from JS should be returned so that
evaluate
reports proper output. -
@p3c0 Thank you for your help.
The problem is that what I really want in the end is a way to catch errors thrown by C++ functions transparently to the user that writes JavaScript. So, the user can just write a script like:var X = myCppFunction(foo); var Y = myOtherCppFunction(bar); etc.
And when it is executed (myEngine.evaluate) the errors are catched by the C++ code of my application. Something like:
try { QJSValue theVal = myEngine.evaluate(the JavaScript script); if(theVal.isError) {//if there are errors in the JS code enter here} } catch( ) { // If there is an error in the Cpp functions called by the JS code enter here }
I have seen in this post that this is not currently possible with QJSEngine. In addition, I have seen that a ticket is already open. Therefore, I will have to think something to get around and wait untill the functionality is implemented.
Thank you for your help.