code format & class prefix
This commit is contained in:
29
doric-Qt/doric/engine/DoricBridgeExtension.cpp
Normal file
29
doric-Qt/doric/engine/DoricBridgeExtension.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <QDebug>
|
||||
#include <QMetaObject>
|
||||
|
||||
#include "../DoricContextManager.h"
|
||||
#include "DoricBridgeExtension.h"
|
||||
|
||||
DoricBridgeExtension::DoricBridgeExtension(QObject *parent) : QObject(parent) {}
|
||||
|
||||
void DoricBridgeExtension::callNative(QString contextId, QString module,
|
||||
QString methodName, QString callbackId,
|
||||
QJSValue jsValue) {
|
||||
DoricContext *context =
|
||||
DoricContextManager::getInstance()->getContext(contextId);
|
||||
bool classRegistered =
|
||||
context->getDriver()->getRegistry()->acquirePluginInfo(module);
|
||||
if (classRegistered) {
|
||||
QObject *plugin = context->obtainPlugin(module);
|
||||
QMetaObject::invokeMethod(plugin, methodName.toStdString().c_str(),
|
||||
Qt::DirectConnection, QGenericReturnArgument(),
|
||||
Q_ARG(QJSValue, jsValue),
|
||||
Q_ARG(QString, callbackId));
|
||||
qDebug() << plugin;
|
||||
}
|
||||
qDebug() << "contextId: " + contextId;
|
||||
qDebug() << "module: " + module;
|
||||
qDebug() << "methodName: " + methodName;
|
||||
qDebug() << "callbackId: " + callbackId;
|
||||
qDebug() << "jsValue: " + jsValue.toString();
|
||||
}
|
17
doric-Qt/doric/engine/DoricBridgeExtension.h
Normal file
17
doric-Qt/doric/engine/DoricBridgeExtension.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef BRIDGEEXTENSION_H
|
||||
#define BRIDGEEXTENSION_H
|
||||
|
||||
#include <QJSValue>
|
||||
#include <QObject>
|
||||
|
||||
class DoricBridgeExtension : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DoricBridgeExtension(QObject *parent = nullptr);
|
||||
|
||||
Q_INVOKABLE void callNative(QString contextId, QString module,
|
||||
QString methodName, QString callbackId,
|
||||
QJSValue jsValue);
|
||||
};
|
||||
|
||||
#endif // BRIDGEEXTENSION_H
|
21
doric-Qt/doric/engine/DoricInterfaceJSE.h
Normal file
21
doric-Qt/doric/engine/DoricInterfaceJSE.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef INTERFACE_JSE_H
|
||||
#define INTERFACE_JSE_H
|
||||
|
||||
#include <QJSValue>
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
|
||||
class DoricInterfaceJSE {
|
||||
public:
|
||||
virtual QString loadJS(QString script, QString source) = 0;
|
||||
|
||||
virtual void injectGlobalJSObject(QString name, QObject *object) = 0;
|
||||
|
||||
virtual void injectGlobalJSFunction(QString name, QObject *function,
|
||||
QString property) = 0;
|
||||
|
||||
virtual QJSValue invokeObject(QString objectName, QString functionName,
|
||||
QVariantList arguments) = 0;
|
||||
};
|
||||
|
||||
#endif // INTERFACE_JSE_H
|
120
doric-Qt/doric/engine/DoricJSEngine.cpp
Normal file
120
doric-Qt/doric/engine/DoricJSEngine.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
#include <QGuiApplication>
|
||||
#include <QJsonObject>
|
||||
#include <QRect>
|
||||
#include <QScreen>
|
||||
#include <QSysInfo>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
|
||||
#include "../utils/DoricConstant.h"
|
||||
#include "../utils/DoricUtils.h"
|
||||
#include "DoricBridgeExtension.h"
|
||||
#include "DoricJSEngine.h"
|
||||
#include "DoricNativeEmpty.h"
|
||||
#include "DoricNativeJSE.h"
|
||||
#include "DoricNativeLog.h"
|
||||
#include "DoricNativeRequire.h"
|
||||
#include "DoricTimerExtension.h"
|
||||
|
||||
DoricJSEngine::DoricJSEngine(QObject *parent) : QObject(parent) {
|
||||
mJSThreadPool.setMaxThreadCount(1);
|
||||
|
||||
QtConcurrent::run(&mJSThreadPool, [this] { mJSE = new DoricNativeJSE(); });
|
||||
QtConcurrent::run(&mJSThreadPool, [this] {
|
||||
// inject env
|
||||
QScreen *screen = QGuiApplication::primaryScreen();
|
||||
QRect screenGeometry = screen->geometry();
|
||||
int screenWidth = screenGeometry.width();
|
||||
int screenHeight = screenGeometry.height();
|
||||
|
||||
QObject *envObject = new QObject();
|
||||
envObject->setProperty("platform", "Qt");
|
||||
envObject->setProperty("platformVersion", qVersion());
|
||||
envObject->setProperty("appName", "appName");
|
||||
envObject->setProperty("appVersion", "appVersion");
|
||||
envObject->setProperty("screenWidth", screenWidth);
|
||||
envObject->setProperty("screenHeight", screenHeight);
|
||||
envObject->setProperty("screenScale", 1);
|
||||
envObject->setProperty("statusBarHeight", 0);
|
||||
envObject->setProperty("hasNotch", false);
|
||||
envObject->setProperty("deviceBrand", QSysInfo::prettyProductName());
|
||||
envObject->setProperty("deviceModel", QSysInfo::productType());
|
||||
|
||||
mJSE->injectGlobalJSObject(DoricConstant::INJECT_ENVIRONMENT, envObject);
|
||||
|
||||
// inject log
|
||||
DoricNativeLog *nativeLog = new DoricNativeLog();
|
||||
mJSE->injectGlobalJSFunction(DoricConstant::INJECT_LOG, nativeLog,
|
||||
"function");
|
||||
|
||||
// inject empty
|
||||
DoricNativeEmpty *nativeEmpty = new DoricNativeEmpty();
|
||||
mJSE->injectGlobalJSFunction(DoricConstant::INJECT_EMPTY, nativeEmpty,
|
||||
"function");
|
||||
|
||||
// inject require
|
||||
DoricNativeRequire *nativeRequire = new DoricNativeRequire();
|
||||
mJSE->injectGlobalJSFunction(DoricConstant::INJECT_REQUIRE, nativeRequire,
|
||||
"function");
|
||||
|
||||
// inject timer set & clear
|
||||
DoricTimerExtension *timerExtension =
|
||||
new DoricTimerExtension([this](long timerId) {
|
||||
QVariantList arguments;
|
||||
arguments.push_back(QVariant((int)timerId));
|
||||
this->invokeDoricMethod(DoricConstant::DORIC_TIMER_CALLBACK,
|
||||
arguments);
|
||||
});
|
||||
mJSE->injectGlobalJSFunction(DoricConstant::INJECT_TIMER_SET,
|
||||
timerExtension, "setTimer");
|
||||
mJSE->injectGlobalJSFunction(DoricConstant::INJECT_TIMER_CLEAR,
|
||||
timerExtension, "clearTimer");
|
||||
|
||||
DoricBridgeExtension *bridgeExtension = new DoricBridgeExtension();
|
||||
mJSE->injectGlobalJSFunction(DoricConstant::INJECT_BRIDGE, bridgeExtension,
|
||||
"callNative");
|
||||
});
|
||||
QtConcurrent::run(&mJSThreadPool, [this] {
|
||||
loadBuiltinJS(DoricConstant::DORIC_BUNDLE_SANDBOX);
|
||||
|
||||
QString libName = DoricConstant::DORIC_MODULE_LIB;
|
||||
QString libJS =
|
||||
DoricUtils::readAssetFile("/doric", DoricConstant::DORIC_BUNDLE_LIB);
|
||||
QString script = packageModuleScript(libName, libJS);
|
||||
|
||||
mJSE->loadJS(script, "Module://" + libName);
|
||||
});
|
||||
}
|
||||
|
||||
void DoricJSEngine::prepareContext(QString contextId, QString script,
|
||||
QString source) {
|
||||
mJSE->loadJS(packageContextScript(contextId, script), "Context://" + source);
|
||||
}
|
||||
|
||||
QJSValue DoricJSEngine::invokeDoricMethod(QString method,
|
||||
QVariantList arguments) {
|
||||
return mJSE->invokeObject(DoricConstant::GLOBAL_DORIC, method, arguments);
|
||||
}
|
||||
|
||||
void DoricJSEngine::loadBuiltinJS(QString assetName) {
|
||||
QString script = DoricUtils::readAssetFile("/doric", assetName);
|
||||
QString result = mJSE->loadJS(script, "Assets://" + assetName);
|
||||
}
|
||||
|
||||
QString DoricJSEngine::packageContextScript(QString contextId,
|
||||
QString content) {
|
||||
return QString(DoricConstant::TEMPLATE_CONTEXT_CREATE)
|
||||
.replace("%s1", content)
|
||||
.replace("%s2", contextId)
|
||||
.replace("%s3", contextId);
|
||||
}
|
||||
|
||||
QString DoricJSEngine::packageModuleScript(QString moduleName,
|
||||
QString content) {
|
||||
return QString(DoricConstant::TEMPLATE_MODULE)
|
||||
.replace("%s1", moduleName)
|
||||
.replace("%s2", content);
|
||||
}
|
||||
|
||||
DoricRegistry *DoricJSEngine::getRegistry() { return this->mRegistry; }
|
||||
|
||||
DoricJSEngine::~DoricJSEngine() {}
|
32
doric-Qt/doric/engine/DoricJSEngine.h
Normal file
32
doric-Qt/doric/engine/DoricJSEngine.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef JSENGINE_H
|
||||
#define JSENGINE_H
|
||||
|
||||
#include <QJSValue>
|
||||
#include <QThreadPool>
|
||||
|
||||
#include "../DoricRegistry.h"
|
||||
#include "DoricInterfaceJSE.h"
|
||||
|
||||
class DoricJSEngine : public QObject {
|
||||
Q_OBJECT
|
||||
private:
|
||||
DoricInterfaceJSE *mJSE;
|
||||
DoricRegistry *mRegistry = new DoricRegistry();
|
||||
|
||||
void loadBuiltinJS(QString assetName);
|
||||
QString packageContextScript(QString contextId, QString content);
|
||||
QString packageModuleScript(QString moduleName, QString content);
|
||||
|
||||
public:
|
||||
QThreadPool mJSThreadPool;
|
||||
|
||||
explicit DoricJSEngine(QObject *parent = nullptr);
|
||||
|
||||
~DoricJSEngine();
|
||||
|
||||
void prepareContext(QString contextId, QString script, QString source);
|
||||
QJSValue invokeDoricMethod(QString method, QVariantList arguments);
|
||||
DoricRegistry *getRegistry();
|
||||
};
|
||||
|
||||
#endif // JSENGINE_H
|
7
doric-Qt/doric/engine/DoricNativeEmpty.cpp
Normal file
7
doric-Qt/doric/engine/DoricNativeEmpty.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
#include "DoricNativeEmpty.h"
|
||||
#include <QDebug>
|
||||
|
||||
Q_INVOKABLE QJSValue DoricNativeEmpty::function() {
|
||||
qDebug() << "nativeEmpty";
|
||||
return QJSValue::NullValue;
|
||||
}
|
16
doric-Qt/doric/engine/DoricNativeEmpty.h
Normal file
16
doric-Qt/doric/engine/DoricNativeEmpty.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef NATIVEEMPTY_H
|
||||
#define NATIVEEMPTY_H
|
||||
|
||||
#include <QJSValue>
|
||||
#include <QObject>
|
||||
|
||||
class DoricNativeEmpty : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DoricNativeEmpty(QObject *parent = nullptr) : QObject(parent) {}
|
||||
|
||||
Q_INVOKABLE QJSValue function();
|
||||
};
|
||||
|
||||
#endif // NATIVEEMPTY_H
|
65
doric-Qt/doric/engine/DoricNativeJSE.cpp
Normal file
65
doric-Qt/doric/engine/DoricNativeJSE.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "DoricNativeJSE.h"
|
||||
#include <QDebug>
|
||||
|
||||
DoricNativeJSE::DoricNativeJSE() {
|
||||
mJSEngine.installExtensions(QJSEngine::AllExtensions);
|
||||
}
|
||||
|
||||
QString DoricNativeJSE::loadJS(QString script, QString source) {
|
||||
return mJSEngine.evaluate(script, source).toString();
|
||||
}
|
||||
|
||||
void DoricNativeJSE::injectGlobalJSObject(QString name, QObject *object) {
|
||||
QJSValue jsObject = mJSEngine.newQObject(object);
|
||||
|
||||
QList<QByteArray> propertyNames = object->dynamicPropertyNames();
|
||||
foreach (QByteArray propertyName, propertyNames) {
|
||||
QString key = QString::fromStdString(propertyName.toStdString());
|
||||
if (key == "undefined") {
|
||||
|
||||
} else {
|
||||
jsObject.setProperty(
|
||||
key, mJSEngine.toScriptValue(object->property(propertyName)));
|
||||
}
|
||||
}
|
||||
|
||||
mJSEngine.globalObject().setProperty(name, jsObject);
|
||||
}
|
||||
|
||||
void DoricNativeJSE::injectGlobalJSFunction(QString name, QObject *function,
|
||||
QString property) {
|
||||
QJSValue functionObject = mJSEngine.newQObject(function);
|
||||
mJSEngine.globalObject().setProperty(name, functionObject.property(property));
|
||||
}
|
||||
|
||||
QJSValue DoricNativeJSE::invokeObject(QString objectName, QString functionName,
|
||||
QVariantList arguments) {
|
||||
QJSValue object = mJSEngine.evaluate(objectName);
|
||||
QJSValue function = object.property(functionName);
|
||||
|
||||
QJSValueList args;
|
||||
foreach (QVariant variant, arguments) {
|
||||
if (variant.type() == QVariant::String) {
|
||||
args.push_back(QJSValue(variant.toString()));
|
||||
} else if (variant.type() == QVariant::Map) {
|
||||
QJSValue arg = mJSEngine.newObject();
|
||||
QMap<QString, QVariant> map = variant.toMap();
|
||||
foreach (QString key, map.keys()) {
|
||||
QVariant value = map.value(key);
|
||||
if (value.type() == QVariant::String) {
|
||||
arg.setProperty(key, value.toString());
|
||||
} else if (value.type() == QVariant::Int) {
|
||||
arg.setProperty(key, value.toInt());
|
||||
}
|
||||
}
|
||||
args.push_back(arg);
|
||||
}
|
||||
}
|
||||
|
||||
QJSValue result = function.call(args);
|
||||
if (result.isError())
|
||||
qDebug() << "Uncaught exception at line"
|
||||
<< result.property("lineNumber").toInt() << ":"
|
||||
<< result.toString();
|
||||
return result;
|
||||
}
|
25
doric-Qt/doric/engine/DoricNativeJSE.h
Normal file
25
doric-Qt/doric/engine/DoricNativeJSE.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef NATIVE_JSE_H
|
||||
#define NATIVE_JSE_H
|
||||
|
||||
#include "DoricInterfaceJSE.h"
|
||||
#include <QJSEngine>
|
||||
|
||||
class DoricNativeJSE : public DoricInterfaceJSE {
|
||||
private:
|
||||
QJSEngine mJSEngine;
|
||||
|
||||
public:
|
||||
DoricNativeJSE();
|
||||
|
||||
QString loadJS(QString script, QString source) override;
|
||||
|
||||
void injectGlobalJSObject(QString name, QObject *object) override;
|
||||
|
||||
void injectGlobalJSFunction(QString name, QObject *function,
|
||||
QString property) override;
|
||||
|
||||
QJSValue invokeObject(QString objectName, QString functionName,
|
||||
QVariantList arguments) override;
|
||||
};
|
||||
|
||||
#endif // NATIVE_JSE_H
|
13
doric-Qt/doric/engine/DoricNativeLog.cpp
Normal file
13
doric-Qt/doric/engine/DoricNativeLog.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <QDebug>
|
||||
|
||||
#include "DoricNativeLog.h"
|
||||
|
||||
Q_INVOKABLE void DoricNativeLog::function(QString level, QString content) {
|
||||
if (level == 'w') {
|
||||
qWarning() << content;
|
||||
} else if (level == 'd') {
|
||||
qDebug() << content;
|
||||
} else if (level == 'e') {
|
||||
qCritical() << content;
|
||||
}
|
||||
}
|
15
doric-Qt/doric/engine/DoricNativeLog.h
Normal file
15
doric-Qt/doric/engine/DoricNativeLog.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef NATIVE_LOG_H
|
||||
#define NATIVE_LOG_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class DoricNativeLog : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DoricNativeLog(QObject *parent = nullptr) : QObject(parent) {}
|
||||
|
||||
Q_INVOKABLE void function(QString level, QString content);
|
||||
};
|
||||
|
||||
#endif // NATIVE_LOG_H
|
8
doric-Qt/doric/engine/DoricNativeRequire.cpp
Normal file
8
doric-Qt/doric/engine/DoricNativeRequire.cpp
Normal file
@@ -0,0 +1,8 @@
|
||||
#include "DoricNativeRequire.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
Q_INVOKABLE QJSValue DoricNativeRequire::function(QString name) {
|
||||
qDebug() << "nativeRequire";
|
||||
return QJSValue::NullValue;
|
||||
}
|
16
doric-Qt/doric/engine/DoricNativeRequire.h
Normal file
16
doric-Qt/doric/engine/DoricNativeRequire.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef NATIVE_REQUIRE_H
|
||||
#define NATIVE_REQUIRE_H
|
||||
|
||||
#include <QJSValue>
|
||||
#include <QObject>
|
||||
|
||||
class DoricNativeRequire : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DoricNativeRequire(QObject *parent = nullptr) : QObject(parent) {}
|
||||
|
||||
Q_INVOKABLE QJSValue function(QString name);
|
||||
};
|
||||
|
||||
#endif // NATIVE_REQUIRE_H
|
28
doric-Qt/doric/engine/DoricTimerExtension.cpp
Normal file
28
doric-Qt/doric/engine/DoricTimerExtension.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include <QTimer>
|
||||
|
||||
#include "../utils/DoricConstant.h"
|
||||
#include "DoricTimerExtension.h"
|
||||
|
||||
Q_INVOKABLE void DoricTimerExtension::setTimer(long timerId, int time,
|
||||
bool repeat) {
|
||||
QTimer *timer = new QTimer(this);
|
||||
timer->setSingleShot(!repeat);
|
||||
connect(timer, &QTimer::timeout, this, [=]() {
|
||||
if (deletedTimerIds->contains(timerId)) {
|
||||
deletedTimerIds->remove(timerId);
|
||||
delete timer;
|
||||
} else {
|
||||
this->method(timerId);
|
||||
|
||||
if (!repeat) {
|
||||
deletedTimerIds->remove(timerId);
|
||||
delete timer;
|
||||
}
|
||||
}
|
||||
});
|
||||
timer->start(time);
|
||||
}
|
||||
|
||||
Q_INVOKABLE void DoricTimerExtension::clearTimer(long timerId) {
|
||||
deletedTimerIds->insert(timerId);
|
||||
}
|
25
doric-Qt/doric/engine/DoricTimerExtension.h
Normal file
25
doric-Qt/doric/engine/DoricTimerExtension.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef NATIVETIMER_H
|
||||
#define NATIVETIMER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QSet>
|
||||
|
||||
class DoricTimerExtension : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QSet<long> *deletedTimerIds = new QSet<long>();
|
||||
std::function<void(long)> method;
|
||||
|
||||
public:
|
||||
explicit DoricTimerExtension(std::function<void(long)> method,
|
||||
QObject *parent = nullptr)
|
||||
: QObject(parent) {
|
||||
this->method = method;
|
||||
}
|
||||
|
||||
Q_INVOKABLE void setTimer(long timerId, int time, bool repeat);
|
||||
|
||||
Q_INVOKABLE void clearTimer(long timerId);
|
||||
};
|
||||
#endif // NATIVETIMER_H
|
@@ -1,30 +0,0 @@
|
||||
#include <QDebug>
|
||||
#include <QMetaObject>
|
||||
|
||||
#include "bridge_extension.h"
|
||||
#include "../context_manager.h"
|
||||
|
||||
BridgeExtension::BridgeExtension(QObject *parent) : QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void BridgeExtension::callNative(QString contextId, QString module, QString methodName, QString callbackId, QJSValue jsValue)
|
||||
{
|
||||
Context *context = ContextManager::getInstance()->getContext(contextId);
|
||||
bool classRegistered = context->getDriver()->getRegistry()->acquirePluginInfo(module);
|
||||
if (classRegistered) {
|
||||
QObject *plugin = context->obtainPlugin(module);
|
||||
QMetaObject::invokeMethod(
|
||||
plugin,
|
||||
methodName.toStdString().c_str(),
|
||||
Qt::DirectConnection, QGenericReturnArgument(),
|
||||
Q_ARG(QJSValue, jsValue), Q_ARG(QString, callbackId));
|
||||
qDebug() << plugin;
|
||||
}
|
||||
qDebug() << "contextId: " + contextId;
|
||||
qDebug() << "module: " + module;
|
||||
qDebug() << "methodName: " + methodName;
|
||||
qDebug() << "callbackId: " + callbackId;
|
||||
qDebug() << "jsValue: " + jsValue.toString();
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
#ifndef BRIDGEEXTENSION_H
|
||||
#define BRIDGEEXTENSION_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QJSValue>
|
||||
|
||||
class BridgeExtension : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit BridgeExtension(QObject *parent = nullptr);
|
||||
|
||||
Q_INVOKABLE void callNative(QString contextId, QString module, QString methodName, QString callbackId, QJSValue jsValue);
|
||||
};
|
||||
|
||||
#endif // BRIDGEEXTENSION_H
|
@@ -1,19 +0,0 @@
|
||||
#ifndef INTERFACE_JSE_H
|
||||
#define INTERFACE_JSE_H
|
||||
|
||||
#include <QString>
|
||||
#include <QJSValue>
|
||||
#include <QVariant>
|
||||
|
||||
class InterfaceJSE {
|
||||
public:
|
||||
virtual QString loadJS(QString script, QString source) = 0;
|
||||
|
||||
virtual void injectGlobalJSObject(QString name, QObject *object) = 0;
|
||||
|
||||
virtual void injectGlobalJSFunction(QString name, QObject *function, QString property) = 0;
|
||||
|
||||
virtual QJSValue invokeObject(QString objectName, QString functionName, QVariantList arguments) = 0;
|
||||
};
|
||||
|
||||
#endif // INTERFACE_JSE_H
|
@@ -1,116 +0,0 @@
|
||||
#include <QGuiApplication>
|
||||
#include <QJsonObject>
|
||||
#include <QRect>
|
||||
#include <QScreen>
|
||||
#include <QSysInfo>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
|
||||
#include "js_engine.h"
|
||||
#include "native_jse.h"
|
||||
#include "../utils/constant.h"
|
||||
#include "native_log.h"
|
||||
#include "native_empty.h"
|
||||
#include "native_require.h"
|
||||
#include "timer_extension.h"
|
||||
#include "bridge_extension.h"
|
||||
#include "../utils/utils.h"
|
||||
|
||||
JSEngine::JSEngine(QObject *parent) : QObject(parent)
|
||||
{
|
||||
mJSThreadPool.setMaxThreadCount(1);
|
||||
|
||||
QtConcurrent::run(&mJSThreadPool, [this]{
|
||||
mJSE = new NativeJSE();
|
||||
});
|
||||
QtConcurrent::run(&mJSThreadPool, [this]{
|
||||
// inject env
|
||||
QScreen *screen = QGuiApplication::primaryScreen();
|
||||
QRect screenGeometry = screen->geometry();
|
||||
int screenWidth = screenGeometry.width();
|
||||
int screenHeight = screenGeometry.height();
|
||||
|
||||
QObject *envObject = new QObject();
|
||||
envObject->setProperty("platform", "Qt");
|
||||
envObject->setProperty("platformVersion", qVersion());
|
||||
envObject->setProperty("appName", "appName");
|
||||
envObject->setProperty("appVersion", "appVersion");
|
||||
envObject->setProperty("screenWidth", screenWidth);
|
||||
envObject->setProperty("screenHeight", screenHeight);
|
||||
envObject->setProperty("screenScale", 1);
|
||||
envObject->setProperty("statusBarHeight", 0);
|
||||
envObject->setProperty("hasNotch", false);
|
||||
envObject->setProperty("deviceBrand", QSysInfo::prettyProductName());
|
||||
envObject->setProperty("deviceModel", QSysInfo::productType());
|
||||
|
||||
mJSE->injectGlobalJSObject(Constant::INJECT_ENVIRONMENT, envObject);
|
||||
|
||||
// inject log
|
||||
NativeLog *nativeLog = new NativeLog();
|
||||
mJSE->injectGlobalJSFunction(Constant::INJECT_LOG, nativeLog, "function");
|
||||
|
||||
// inject empty
|
||||
NativeEmpty *nativeEmpty = new NativeEmpty();
|
||||
mJSE->injectGlobalJSFunction(Constant::INJECT_EMPTY, nativeEmpty, "function");
|
||||
|
||||
// inject require
|
||||
NativeRequire *nativeRequire = new NativeRequire();
|
||||
mJSE->injectGlobalJSFunction(Constant::INJECT_REQUIRE, nativeRequire, "function");
|
||||
|
||||
// inject timer set & clear
|
||||
TimerExtension *timerExtension = new TimerExtension([this](long timerId){
|
||||
QVariantList arguments;
|
||||
arguments.push_back(QVariant((int)timerId));
|
||||
this->invokeDoricMethod(Constant::DORIC_TIMER_CALLBACK, arguments);
|
||||
});
|
||||
mJSE->injectGlobalJSFunction(Constant::INJECT_TIMER_SET, timerExtension, "setTimer");
|
||||
mJSE->injectGlobalJSFunction(Constant::INJECT_TIMER_CLEAR, timerExtension, "clearTimer");
|
||||
|
||||
BridgeExtension *bridgeExtension = new BridgeExtension();
|
||||
mJSE->injectGlobalJSFunction(Constant::INJECT_BRIDGE, bridgeExtension, "callNative");
|
||||
});
|
||||
QtConcurrent::run(&mJSThreadPool, [this]{
|
||||
loadBuiltinJS(Constant::DORIC_BUNDLE_SANDBOX);
|
||||
|
||||
QString libName = Constant::DORIC_MODULE_LIB;
|
||||
QString libJS = Utils::readAssetFile("/doric", Constant::DORIC_BUNDLE_LIB);
|
||||
QString script = packageModuleScript(libName, libJS);
|
||||
|
||||
mJSE->loadJS(script, "Module://" + libName);
|
||||
});
|
||||
}
|
||||
|
||||
void JSEngine::prepareContext(QString contextId, QString script, QString source)
|
||||
{
|
||||
mJSE->loadJS(packageContextScript(contextId, script), "Context://" + source);
|
||||
}
|
||||
|
||||
QJSValue JSEngine::invokeDoricMethod(QString method, QVariantList arguments)
|
||||
{
|
||||
return mJSE->invokeObject(Constant::GLOBAL_DORIC, method, arguments);
|
||||
}
|
||||
|
||||
void JSEngine::loadBuiltinJS(QString assetName)
|
||||
{
|
||||
QString script = Utils::readAssetFile("/doric", assetName);
|
||||
QString result = mJSE->loadJS(script, "Assets://" + assetName);
|
||||
}
|
||||
|
||||
QString JSEngine::packageContextScript(QString contextId, QString content)
|
||||
{
|
||||
return QString(Constant::TEMPLATE_CONTEXT_CREATE).replace("%s1", content).replace("%s2", contextId).replace("%s3", contextId);
|
||||
}
|
||||
|
||||
QString JSEngine::packageModuleScript(QString moduleName, QString content)
|
||||
{
|
||||
return QString(Constant::TEMPLATE_MODULE).replace("%s1", moduleName).replace("%s2", content);
|
||||
}
|
||||
|
||||
Registry *JSEngine::getRegistry()
|
||||
{
|
||||
return this->mRegistry;
|
||||
}
|
||||
|
||||
JSEngine::~JSEngine()
|
||||
{
|
||||
|
||||
}
|
@@ -1,32 +0,0 @@
|
||||
#ifndef JSENGINE_H
|
||||
#define JSENGINE_H
|
||||
|
||||
#include <QJSValue>
|
||||
#include <QThreadPool>
|
||||
|
||||
#include "interface_jse.h"
|
||||
#include "../registry.h"
|
||||
|
||||
class JSEngine : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
InterfaceJSE *mJSE;
|
||||
Registry *mRegistry = new Registry();
|
||||
|
||||
void loadBuiltinJS(QString assetName);
|
||||
QString packageContextScript(QString contextId, QString content);
|
||||
QString packageModuleScript(QString moduleName, QString content);
|
||||
public:
|
||||
QThreadPool mJSThreadPool;
|
||||
|
||||
explicit JSEngine(QObject *parent = nullptr);
|
||||
|
||||
~JSEngine();
|
||||
|
||||
void prepareContext(QString contextId, QString script, QString source);
|
||||
QJSValue invokeDoricMethod(QString method, QVariantList arguments);
|
||||
Registry *getRegistry();
|
||||
};
|
||||
|
||||
#endif // JSENGINE_H
|
@@ -1,7 +0,0 @@
|
||||
#include "native_empty.h"
|
||||
#include <QDebug>
|
||||
|
||||
Q_INVOKABLE QJSValue NativeEmpty::function() {
|
||||
qDebug() << "nativeEmpty";
|
||||
return QJSValue::NullValue;
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
#ifndef NATIVEEMPTY_H
|
||||
#define NATIVEEMPTY_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QJSValue>
|
||||
|
||||
class NativeEmpty : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NativeEmpty(QObject *parent = nullptr) : QObject(parent) {}
|
||||
|
||||
Q_INVOKABLE QJSValue function();
|
||||
};
|
||||
|
||||
#endif // NATIVEEMPTY_H
|
@@ -1,69 +0,0 @@
|
||||
#include "native_jse.h"
|
||||
#include <QDebug>
|
||||
|
||||
NativeJSE::NativeJSE()
|
||||
{
|
||||
mJSEngine.installExtensions(QJSEngine::AllExtensions);
|
||||
}
|
||||
|
||||
QString NativeJSE::loadJS(QString script, QString source)
|
||||
{
|
||||
return mJSEngine.evaluate(script, source).toString();
|
||||
}
|
||||
|
||||
void NativeJSE::injectGlobalJSObject(QString name, QObject *object)
|
||||
{
|
||||
QJSValue jsObject = mJSEngine.newQObject(object);
|
||||
|
||||
QList<QByteArray> propertyNames = object->dynamicPropertyNames();
|
||||
foreach(QByteArray propertyName, propertyNames)
|
||||
{
|
||||
QString key = QString::fromStdString(propertyName.toStdString());
|
||||
if (key == "undefined") {
|
||||
|
||||
} else {
|
||||
jsObject.setProperty(key, mJSEngine.toScriptValue(object->property(propertyName)));
|
||||
}
|
||||
}
|
||||
|
||||
mJSEngine.globalObject().setProperty(name, jsObject);
|
||||
}
|
||||
|
||||
void NativeJSE::injectGlobalJSFunction(QString name, QObject *function, QString property)
|
||||
{
|
||||
QJSValue functionObject = mJSEngine.newQObject(function);
|
||||
mJSEngine.globalObject().setProperty(name, functionObject.property(property));
|
||||
}
|
||||
|
||||
QJSValue NativeJSE::invokeObject(QString objectName, QString functionName, QVariantList arguments)
|
||||
{
|
||||
QJSValue object = mJSEngine.evaluate(objectName);
|
||||
QJSValue function = object.property(functionName);
|
||||
|
||||
QJSValueList args;
|
||||
foreach(QVariant variant, arguments) {
|
||||
if (variant.type() == QVariant::String) {
|
||||
args.push_back(QJSValue(variant.toString()));
|
||||
} else if (variant.type() == QVariant::Map) {
|
||||
QJSValue arg = mJSEngine.newObject();
|
||||
QMap<QString, QVariant> map = variant.toMap();
|
||||
foreach (QString key, map.keys()) {
|
||||
QVariant value = map.value(key);
|
||||
if (value.type() == QVariant::String) {
|
||||
arg.setProperty(key, value.toString());
|
||||
} else if (value.type() == QVariant::Int) {
|
||||
arg.setProperty(key, value.toInt());
|
||||
}
|
||||
}
|
||||
args.push_back(arg);
|
||||
}
|
||||
}
|
||||
|
||||
QJSValue result = function.call(args);
|
||||
if (result.isError())
|
||||
qDebug()
|
||||
<< "Uncaught exception at line"
|
||||
<< result.property("lineNumber").toInt()
|
||||
<< ":" << result.toString();
|
||||
return result;
|
||||
}
|
@@ -1,23 +0,0 @@
|
||||
#ifndef NATIVE_JSE_H
|
||||
#define NATIVE_JSE_H
|
||||
|
||||
#include <QJSEngine>
|
||||
#include "interface_jse.h"
|
||||
|
||||
class NativeJSE : public InterfaceJSE
|
||||
{
|
||||
private:
|
||||
QJSEngine mJSEngine;
|
||||
public:
|
||||
NativeJSE();
|
||||
|
||||
QString loadJS(QString script, QString source) override;
|
||||
|
||||
void injectGlobalJSObject(QString name, QObject *object) override;
|
||||
|
||||
void injectGlobalJSFunction(QString name, QObject *function, QString property) override;
|
||||
|
||||
QJSValue invokeObject(QString objectName, QString functionName, QVariantList arguments) override;
|
||||
};
|
||||
|
||||
#endif // NATIVE_JSE_H
|
@@ -1,13 +0,0 @@
|
||||
#include <QDebug>
|
||||
|
||||
#include "native_log.h"
|
||||
|
||||
Q_INVOKABLE void NativeLog::function(QString level, QString content) {
|
||||
if (level == 'w') {
|
||||
qWarning() << content;
|
||||
} else if (level == 'd') {
|
||||
qDebug() << content;
|
||||
} else if (level == 'e') {
|
||||
qCritical() << content;
|
||||
}
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
#ifndef NATIVE_LOG_H
|
||||
#define NATIVE_LOG_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class NativeLog : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NativeLog(QObject *parent = nullptr) : QObject(parent) {}
|
||||
|
||||
Q_INVOKABLE void function(QString level, QString content);
|
||||
};
|
||||
|
||||
#endif // NATIVE_LOG_H
|
@@ -1,8 +0,0 @@
|
||||
#include "native_require.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
Q_INVOKABLE QJSValue NativeRequire::function(QString name) {
|
||||
qDebug() << "nativeRequire";
|
||||
return QJSValue::NullValue;
|
||||
}
|
@@ -1,18 +0,0 @@
|
||||
#ifndef NATIVE_REQUIRE_H
|
||||
#define NATIVE_REQUIRE_H
|
||||
|
||||
|
||||
#include <QObject>
|
||||
#include <QJSValue>
|
||||
|
||||
class NativeRequire : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NativeRequire(QObject *parent = nullptr) : QObject(parent) {}
|
||||
|
||||
Q_INVOKABLE QJSValue function(QString name);
|
||||
};
|
||||
|
||||
|
||||
#endif // NATIVE_REQUIRE_H
|
@@ -1,27 +0,0 @@
|
||||
#include <QTimer>
|
||||
|
||||
#include "timer_extension.h"
|
||||
#include "../utils/constant.h"
|
||||
|
||||
Q_INVOKABLE void TimerExtension::setTimer(long timerId, int time, bool repeat) {
|
||||
QTimer *timer = new QTimer(this);
|
||||
timer->setSingleShot(!repeat);
|
||||
connect(timer, &QTimer::timeout, this, [=] () {
|
||||
if (deletedTimerIds->contains(timerId)) {
|
||||
deletedTimerIds->remove(timerId);
|
||||
delete timer;
|
||||
} else {
|
||||
this->method(timerId);
|
||||
|
||||
if (!repeat) {
|
||||
deletedTimerIds->remove(timerId);
|
||||
delete timer;
|
||||
}
|
||||
}
|
||||
});
|
||||
timer->start(time);
|
||||
}
|
||||
|
||||
Q_INVOKABLE void TimerExtension::clearTimer(long timerId) {
|
||||
deletedTimerIds->insert(timerId);
|
||||
}
|
@@ -1,24 +0,0 @@
|
||||
#ifndef NATIVETIMER_H
|
||||
#define NATIVETIMER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QSet>
|
||||
|
||||
class TimerExtension : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QSet<long> *deletedTimerIds = new QSet<long>();
|
||||
std::function<void(long)> method;
|
||||
|
||||
public:
|
||||
explicit TimerExtension(std::function<void(long)> method, QObject *parent = nullptr) : QObject(parent) {
|
||||
this->method = method;
|
||||
}
|
||||
|
||||
Q_INVOKABLE void setTimer(long timerId, int time, bool repeat);
|
||||
|
||||
Q_INVOKABLE void clearTimer(long timerId);
|
||||
|
||||
};
|
||||
#endif // NATIVETIMER_H
|
Reference in New Issue
Block a user