I am using the QJSEngine, I added a global to the object:
QJSValue objGlobal = pobjScriptEng->globalObject();
pobjScriptEng
is a pointer to an instance of QJSEngine
.
I have a map of globals, the map type definition:
std::map<QString, QString> mpGlobals;
I iterate through the globals map adding them to the engine:
for( mpGlobals::iterator itr=rmpGlobals.begin(); itr!=rmpGlobals.end(); itr++ ) {
QString strName(itr->first);
if ( objGlobal.hasProperty(strName) == false ) {
QString strData(itr->second);
QJSValue result = pobjScriptEng->evaluate(strData);
objGlobal.setProperty(strName, result);
}
}
rmpGlobals
is a reference to the globals map.
I have a script which includes a reference to a global, the global is called db
and is a JSON object that contains:
{"db":"test","host":"localhost","usr":"root","pass":"123456"}
I added some debug logs in the loop that calls setProperty
and this is what's displayed in the Application Output:
itr->first "db"
itr->second "{\"db\":\"test\",\"host\":\"localhost\",\"usr\":\"root\",\"pass\":\"resuocra\"}"
The syntax error is coming from the JSON, but why there is nothing wrong with it. I dumped result.toString()
to the console and it contains:
SyntaxError: Expected token `,'
The script:
function test() {
try{
console.info("---------------");
console.info("test(), Line 4");
if ( db === undefined ) {
console.info("db is undefined");
return;
}
if ( typeof db === "object" ) {
var mbr;
console.info("test(), Line 7");
console.info(db);
console.info("test(), Line 9");
for( mbr in db ) {
console.info("test(), Line12");
console.info(mbr);
console.info("test(), Line14");
}
console.info("test(), Line 14");
}
console.info("test(), Line 16");
console.info("---------------");
} catch( e ) {
console.warn( "test() WARNING: " + e );
}
}
When run my application and the script is evaluated I see the following in the "Application Output":
2020-04-08 08:21:36.320693+0100 XMLMPAM[3657:59571] [js] ---------------
2020-04-08 08:21:36.320732+0100 XMLMPAM[3657:59571] [js] test(), Line 4
2020-04-08 08:21:36.320747+0100 XMLMPAM[3657:59571] [js] test(), Line 7
2020-04-08 08:21:36.320762+0100 XMLMPAM[3657:59571] [js] SyntaxError: Expected token `,'
2020-04-08 08:21:36.320769+0100 XMLMPAM[3657:59571] [js] test(), Line 9
2020-04-08 08:21:36.320790+0100 XMLMPAM[3657:59571] [js] test(), Line 14
2020-04-08 08:21:36.320798+0100 XMLMPAM[3657:59571] [js] test(), Line 16
2020-04-08 08:21:36.320804+0100 XMLMPAM[3657:59571] [js] ---------------
Ignore everything before the [js]
that's my timestamp and debug information, after the [js]
is all the console output.
What is the:
SyntaxError: Expected token `,'
I can see nothing wrong in the global or the script.
If I modify the script and insert:
var db = {"db":"test","host":"localhost","usr":"root","pass":"123456"};
As the first line, the syntax error is not displayed and everything is ok, so what is wrong with global added using setProperty
?
Here is the code that adds a global to the map:
void clsXMLnode::addGlobal(QString strGlobal) {
QStringList slstGlobal = strGlobal.split(clsXMLnode::msccGlobalDelimiter);
if ( slstGlobal.length() == clsXMLnode::mscintAssignmentParts ) {
QString strName(slstGlobal[clsXMLnode::mscintGlobalName].trimmed())
,strValue(slstGlobal[clsXMLnode::mscintGlobalValue].trimmed());
msmpGlobals.insert(std::make_pair(strName, strValue));
}
}
Some definitions:
clsXMLnode::msccGlobalDelimiter is "="
clsXMLnode::mscintAssignmentParts is 2
clsXMLnode::mscintGlobalName is 0
clsXMLnode::mscintGlobalValue is 1
In these lines, you're setting the properties for globalObject
:
QJSValue result = pobjScriptEng->evaluate( strData );
objGlobal.setProperty( strName, result );
The exception:
SyntaxError: Expected token `,'
is due to the reason that the config JSON is missing the enclosing parentheses ()
so the evaluation is unsuccessful. You need to check this with QJSValue::isError()
method of result
.
Example (See documentation):
QJSValue result = pobjScriptEng->evaluate( strData );
if ( result.isError() )
{
qDebug() << "Uncaught exception at line"
<< result.property("lineNumber").toInt()
<< ":" << result.toString();
return -1;
}
Once enclosed properly, the JSON config would be evaluated successfully and it should work.
Here's a complete working example with raw string literals for JSON and JavaScript code:
#include <QCoreApplication>
#include <QJSEngine>
#include <QJSValue>
#include <QDebug>
int main( int argc, char** argv )
{
QCoreApplication app{ argc, argv };
const auto raw_config =
R"json((
{
"db": "test",
"host": "localhost",
"usr": "root",
"pass": "123456"
}
))json";
QJSEngine engine;
engine.installExtensions( QJSEngine::ConsoleExtension );
const auto json_config = engine.evaluate( raw_config );
if ( json_config.isError() )
{
qDebug() << "Uncaught exception at line"
<< json_config.property("lineNumber").toInt()
<< ":" << json_config.toString();
return -1;
}
engine.globalObject().setProperty( "db", json_config );
const auto test_script =
R"javascript((
function test() {
try{
console.info("---------------");
if ( db === undefined ) {
console.info("db is undefined");
return;
}
else if ( typeof db === "object" ) {
for( k in db ) {
console.info( k + ": " + db[k] );
}
}
console.info("---------------");
} catch( e ) {
console.warn( "test() WARNING: " + e );
}
}
))javascript";
auto test_func = engine.evaluate( test_script );
if ( test_func.isError() )
{
qDebug() << "Uncaught exception at line"
<< test_func.property("lineNumber").toInt()
<< ":" << test_func.toString();
return -1;
}
const auto result = test_func.call();
if ( result.isError() )
{
qDebug() << "Uncaught exception at line"
<< result.property("lineNumber").toInt()
<< ":" << result.toString();
return -1;
}
return 0;
}
Output:
js: ---------------
js: db: test
js: host: localhost
js: usr: root
js: pass: 123456
js: ---------------
Relevant JavaScript-specific thread on the grouping operator ()
syntax: