我可以在QtScript中使用should.js吗?

我正在使用QtScript来自动化我的应用程序的部分开发和testing目的。 我已经到了想要testing断言的地步,并基于“独立断言库?” 和我在Debian软件库中find的东西,我去了Should.js。

我无法加载到我的Qt应用程序,因为它取决于Node的require()函数。 我尝试实现这个版本,从“CommonJS的支持require()”开始 ,结束于下面的代码。

可以使它工作,还是我注定要采取这种方法? 我可能会更好的将should.js的位复制到单个文件中吗? 我不想让自己负责保持更新。 (授权是一个非问题,因为我不打算重新分配此代码)。

这是我的MCVE; 抱歉,我不能把它缩短!

should.cpp

 #include <QCoreApplication> #include <QDateTime> #include <QDebug> #include <QDir> #include <QFile> #include <QFileInfo> #include <QScriptEngine> #include <QScriptContext> #include <QScriptContextInfo> #include <QTextStream> // Primitive implementation of Node.js require(). // NB Supports only .js sources. QScriptValue require(QScriptContext* context, QScriptEngine* engine) { const QString moduleName = context->argument(0).toString(); // First, look in our modules cache QScriptValue modules = engine->globalObject().property("$MODULES"); QScriptValue module = modules.property(moduleName); if (module.isValid()) { auto cached_file = module.property("filename"); auto time_stamp = module.property("timestamp"); auto code = module.property("code"); if (code.isObject() && cached_file.isString() && time_stamp.isDate()) { if (QFileInfo(cached_file.toString()).lastModified() == time_stamp.toDateTime()) { qDebug() << "found up-to-date module for require of" << moduleName; return code; } else { qDebug() << "cache stale for" << moduleName; } } } else { // Prepare a cache entry, as some modules recursively include each // other. This way, they at least get the partial definition of the // other, rather than a stack overflow. module = engine->newObject(); modules.setProperty(moduleName, module); } qDebug() << "require" << moduleName; // resolve filename relative to the calling script QString filename = moduleName + ".js"; for (auto *p = context; p; p = p->parentContext()) { QScriptContextInfo info(p); auto parent_file = info.fileName(); if (parent_file.isEmpty()) continue; // else, we reached a context with a filename QDir base_dir = QFileInfo(parent_file).dir(); filename = base_dir.filePath(filename); if (QFile::exists(filename)) { break; } } QFile file(filename); if (!file.open(QIODevice::ReadOnly)) { return context->throwValue(QString("Failed to open %0").arg(moduleName)); } QTextStream in(&file); in.setCodec("UTF-8"); auto script = in.readAll(); file.close(); #if 0 // I had to disable this, because it barfs on "get not()" definition - is // that a Node extension? Will it cause me problems even if I get require() // working? auto syntax_check = QScriptEngine::checkSyntax(script); if (syntax_check.state() != QScriptSyntaxCheckResult::Valid) { return context->throwValue(QString("%2:%0:%1: Syntax error: %3") .arg(syntax_check.errorLineNumber()) .arg(syntax_check.errorColumnNumber()) .arg(filename, syntax_check.errorMessage())); } #endif // create a new context, and capture the module's exports QScriptContext* newContext = engine->pushContext(); QScriptValue exports = engine->newObject(); newContext->activationObject().setProperty("exports", exports); module.setProperty("code", exports); module.setProperty("filename", filename); module.setProperty("timestamp", engine->newDate(QFileInfo(filename).lastModified())); // run the script engine->evaluate(script, filename); // get the exports module.setProperty("code", newContext->activationObject().property("exports")); engine->popContext(); if (engine->hasUncaughtException()) return engine->uncaughtException(); qDebug() << "loaded" << moduleName; return exports; } int main(int argc, char **argv) { QCoreApplication app(argc, argv); QScriptEngine engine; // register global require() function auto global = engine.globalObject(); global.setProperty("require", engine.newFunction(require)); global.setProperty("$MODULES", engine.newObject()); engine.evaluate("var should = require('/usr/lib/nodejs/should/lib/should');"); if (engine.hasUncaughtException()) { qCritical() << engine.uncaughtException().toString().toStdString().c_str(); qWarning() << engine.uncaughtExceptionBacktrace().join("\n").toStdString().c_str(); return 1; } return 0; } 

Makefile文件

 check: should ./should CXXFLAGS += -std=c++11 -Wall -Wextra -Werror CXXFLAGS += -fPIC CXXFLAGS += $(shell pkg-config --cflags Qt5Script) LDLIBS += $(shell pkg-config --libs Qt5Script) 

输出是

 require "/usr/lib/nodejs/should/lib/should" require "./util" require "./inspect" found up-to-date module for require of "./util" loaded "./inspect" require "assert" Failed to open assert <eval>() at /usr/lib/nodejs/should/lib/./util.js:126 <native>() at -1 <native>('./util') at -1 <eval>() at /usr/lib/nodejs/should/lib/should.js:8 <native>() at -1 <native>('/usr/lib/nodejs/should/lib/should') at -1 <global>() at 1 

(在传递 – 我如何得到实际的函数名称require在堆栈跟踪而不是<native> ?插槽pipe理这个,所以我应该能够,对不对?)

我已经仔细研究了一下,并且重写了C ++ Qt require系统对我来说有点费时,然后开始思考。 对于require核心模块的库也有问题(这又require本地模块会导致未定义的行为 – 读取:可能不起作用)。

方法#1 – C++ require()实现:

在C ++ Qt中实现自定义node require() ,就像它已经在你的问题和链接中启动了一样。 node.js require()的工作细节可以在这里find。 您需要在require()searchpath中有核心node模块(您可以从node.js源代码库获取它们)。

方法#2 – 使用browserify

由于我们在#1中试图解决的问题基本上是加载和cachingJavaScript文件,为什么不使用已经存在的东西为同一目的。 这样,我们可以避免手动工作,捆绑javascript我们有强烈的迹象表明,它将在浏览器(更有限的环境,然后node.js )工作。

 $ npm install -g browserify $ npm install expect 

index.js

 var expect = require('expect'); expect(1).toEqual(1); 

并运行browserify

 $ browserify index.js -o bundle.js 

在你的Qt C++

 QString script = loadFile("/path/to/bundle.js"); engine.evaluate(script); 

我们已经为require()做了一个解决方法,但是我不确定是互操作性的。 与Qt 。 此外,我已经遇到了一些js模块从QtScript的一些Syntax Error ,所以这是没有银子弹,即使它看起来如此。

注意:这也是一个有趣的项目: https : //github.com/svalaskevicius/qtjs-generator 。