QJSEngine,全局和脚本,是啥导致语法错误

Posted

技术标签:

【中文标题】QJSEngine,全局和脚本,是啥导致语法错误【英文标题】:QJSEngine, global and script, what is causing the syntax errorQJSEngine,全局和脚本,是什么导致语法错误 【发布时间】:2020-04-08 07:24:15 【问题描述】:

我正在使用QJSEngine,我向对象添加了一个全局:

QJSValue objGlobal = pobjScriptEng->globalObject();

pobjScriptEng 是一个指向QJSEngine 实例的指针。

我有一张全局地图,地图类型定义:

std::map<QString, QString> mpGlobals;

我遍历全局映射,将它们添加到引擎中:

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 是对全局映射的引用。

我有一个脚本,其中包含对全局的引用,全局称为 db,是一个 JSON 对象,其中包含:

"db":"test","host":"localhost","usr":"root","pass":"123456"

我在调用setProperty 的循环中添加了一些调试日志,这就是应用程序输出中显示的内容:

itr->first "db" 
itr->second "\"db\":\"test\",\"host\":\"localhost\",\"usr\":\"root\",\"pass\":\"resuocra\""

语法错误来自JSON,但为什么没有错。我将result.toString() 转储到控制台,它包含:

SyntaxError: Expected token `,'

脚本:

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 );
    

运行我的应用程序并评估脚本时,我在“应用程序输出”中看到以下内容:

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] ---------------

忽略[js] 之前的所有内容,这是我的时间戳和调试信息,[js] 之后是所有控制台输出。

什么是:

SyntaxError: Expected token `,'

我看不出全局或脚本有什么问题。

如果我修改脚本并插入:

var db =  "db":"test","host":"localhost","usr":"root","pass":"123456";

作为第一行,没有显示语法错误,一切正常,那么使用setProperty添加全局有什么问题?

这是向地图添加全局的代码:

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));
    

一些定义:

clsXMLnode::msccGlobalDelimiter        is "="
clsXMLnode::mscintAssignmentParts      is 2
clsXMLnode::mscintGlobalName           is 0
clsXMLnode::mscintGlobalValue          is 1

【问题讨论】:

请在您设置它的地方添加全局 JSON 对象和相关代码。 @Azeem,你读过这篇文章了吗?第一行从引擎中获取全局对象,全局 JSON 定义见博文。 我在询问对 JSON 对象进行 JSON 解析的代码。你能展示那部分 C++ 代码吗?或者,也许,您可以打印它以确保它是 JS 代码的有效 JSON。 没有特殊的代码做解析,从文件中读取JSON并放入QString中,QString中使用“=”分割成变量和数据,然后是变量和数据被放入使用 mpGlobals 的地图中。我已编辑帖子以显示此功能。 没有使用QJsonDocument?您可以通过在设置之前打印所有值来进行验证吗?您可以在调用 setProperty 之前打印该循环中的那些。 【参考方案1】:

在这些行中,您正在为globalObject 设置属性:

QJSValue result = pobjScriptEng->evaluate( strData );
objGlobal.setProperty( strName, result );

例外:

SyntaxError: Expected token `,'

是由于配置JSON缺少括号()的原因,因此评估不成功。您需要使用resultQJSValue::isError() 方法检查这一点。

示例(参见documentation):

QJSValue result = pobjScriptEng->evaluate( strData );
if ( result.isError() )

    qDebug() << "Uncaught exception at line"
             << result.property("lineNumber").toInt()
             << ":" << result.toString();
    return -1;

正确封装后,JSON 配置将被成功评估并且应该可以工作。

这是一个完整的工作示例,带有 raw string literals 用于 JSON 和 javascript 代码:

#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;

输出:

js: ---------------
js: db: test
js: host: localhost
js: usr: root
js: pass: 123456
js: ---------------

分组运算符()语法上的相关JavaScript特定线程:

What do parentheses surrounding an object/function/class declaration mean?

【讨论】:

这是对象的新增内容吗? () 的要求? @SPlatten:不客气! documentation 使用此语法。 Here 也是。但是,我在文档中找不到任何具体的语法说明。 为什么开发人员不能直接修改评估例程来封装 () 中传递的所有内容? @SPlatten:这是reason,它来自 JavaScript 本身。刚刚在我的浏览器控制台上进行了测试,这很有意义。对于稍后调用的函数,调用者需要一个对象来稍后调用并包含在() 中返回该可调用对象。也许,JSON 对象也一样。示例:var t = (function test() console.log("hello"); ); 然后t() 会调用它。因此,匿名函数更有意义,因为在这种情况下,名称并不是那么重要的实体。

以上是关于QJSEngine,全局和脚本,是啥导致语法错误的主要内容,如果未能解决你的问题,请参考以下文章

在脚本调用的 C++ 函数中调用 QJSEngine::newQObject() 是不是有效?

如何使用 QJSEngine 构建 API?

Qt使用QJSEngine执行脚本

如何将枚举类型注册到 QJSEngine 以从脚本环境中使用?

QJSEngine - 暴露类和抛出错误

QJSEngine-暴露类和抛出错误