From dada2e4e0d52bd15a88aaa947c63d10bbdc5e13d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=8A=B2=E9=B9=8F?= Date: Fri, 2 Apr 2021 15:16:18 +0800 Subject: [PATCH] complete invoke (except callNative) --- doric-Qt/doric/doric.pro.user | 3 +- .../doric/engine/DoricBridgeExtension.cpp | 4 +- doric-Qt/doric/engine/DoricJSEngine.cpp | 122 ++++++------ doric-Qt/doric/engine/DoricNativeEmpty.cpp | 3 +- doric-Qt/doric/engine/DoricNativeEmpty.h | 3 +- doric-Qt/doric/engine/DoricNativeJSE.cpp | 57 ++++-- doric-Qt/doric/engine/DoricNativeJSE.h | 10 +- doric-Qt/doric/engine/DoricNativeRequire.cpp | 5 +- doric-Qt/doric/engine/DoricNativeRequire.h | 3 +- doric-Qt/doric/engine/v8/JSValueHelper.cpp | 52 +++-- doric-Qt/doric/engine/v8/JSValueHelper.h | 9 +- doric-Qt/doric/engine/v8/V8Executor.cpp | 187 +++++++++++++++++- doric-Qt/doric/engine/v8/V8Executor.h | 12 +- 13 files changed, 346 insertions(+), 124 deletions(-) diff --git a/doric-Qt/doric/doric.pro.user b/doric-Qt/doric/doric.pro.user index 0f75e02b..58a534bc 100644 --- a/doric-Qt/doric/doric.pro.user +++ b/doric-Qt/doric/doric.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -301,6 +301,7 @@ true false true + C:/Users/maverick/Workspace/Doric/doric-Qt/build-doric-Desktop_Qt_6_0_2_MSVC2019_64bit-Debug 1 diff --git a/doric-Qt/doric/engine/DoricBridgeExtension.cpp b/doric-Qt/doric/engine/DoricBridgeExtension.cpp index 3dd5f5e4..9fcbf90a 100644 --- a/doric-Qt/doric/engine/DoricBridgeExtension.cpp +++ b/doric-Qt/doric/engine/DoricBridgeExtension.cpp @@ -15,8 +15,8 @@ void DoricBridgeExtension::callNative(QString contextId, QString module, context->getDriver()->getRegistry()->acquirePluginInfo(module); if (classRegistered) { QObject *plugin = context->obtainPlugin(module); - QMetaObject::invokeMethod(plugin, methodName.toStdString().c_str(), - Qt::DirectConnection, QGenericReturnArgument(), + QMetaObject::invokeMethod(plugin, methodName.toUtf8(), Qt::DirectConnection, + QGenericReturnArgument(), Q_ARG(QJSValue, jsValue), Q_ARG(QString, callbackId)); } diff --git a/doric-Qt/doric/engine/DoricJSEngine.cpp b/doric-Qt/doric/engine/DoricJSEngine.cpp index 796e3c50..9e0dd606 100644 --- a/doric-Qt/doric/engine/DoricJSEngine.cpp +++ b/doric-Qt/doric/engine/DoricJSEngine.cpp @@ -18,73 +18,79 @@ 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(); + { + auto result = QtConcurrent::run( + &mJSThreadPool, [this] { mJSE = new DoricNativeJSE(JSEType::V8); }); + } + { + auto result = 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()); + 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); + mJSE->injectGlobalJSObject(DoricConstant::INJECT_ENVIRONMENT, envObject); - // inject log - DoricNativeLog *nativeLog = new DoricNativeLog(); - mJSE->injectGlobalJSFunction(DoricConstant::INJECT_LOG, nativeLog, - "function"); + // 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 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 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"); + // 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); + DoricBridgeExtension *bridgeExtension = new DoricBridgeExtension(); + mJSE->injectGlobalJSFunction(DoricConstant::INJECT_BRIDGE, + bridgeExtension, "callNative"); + }); + } - QString libName = DoricConstant::DORIC_MODULE_LIB; - QString libJS = - DoricUtils::readAssetFile("/doric", DoricConstant::DORIC_BUNDLE_LIB); - QString script = packageModuleScript(libName, libJS); + { + auto result = QtConcurrent::run(&mJSThreadPool, [this] { + loadBuiltinJS(DoricConstant::DORIC_BUNDLE_SANDBOX); - mJSE->loadJS(script, "Module://" + libName); - }); + 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, diff --git a/doric-Qt/doric/engine/DoricNativeEmpty.cpp b/doric-Qt/doric/engine/DoricNativeEmpty.cpp index 84d2ea9d..750a5f18 100644 --- a/doric-Qt/doric/engine/DoricNativeEmpty.cpp +++ b/doric-Qt/doric/engine/DoricNativeEmpty.cpp @@ -1,7 +1,6 @@ #include "DoricNativeEmpty.h" #include -Q_INVOKABLE QJSValue DoricNativeEmpty::function() { +Q_INVOKABLE void DoricNativeEmpty::function() { qDebug() << "nativeEmpty"; - return QJSValue::NullValue; } diff --git a/doric-Qt/doric/engine/DoricNativeEmpty.h b/doric-Qt/doric/engine/DoricNativeEmpty.h index 52240d11..34ab659c 100644 --- a/doric-Qt/doric/engine/DoricNativeEmpty.h +++ b/doric-Qt/doric/engine/DoricNativeEmpty.h @@ -1,7 +1,6 @@ #ifndef NATIVEEMPTY_H #define NATIVEEMPTY_H -#include #include class DoricNativeEmpty : public QObject { @@ -10,7 +9,7 @@ class DoricNativeEmpty : public QObject { public: DoricNativeEmpty(QObject *parent = nullptr) : QObject(parent) {} - Q_INVOKABLE QJSValue function(); + Q_INVOKABLE void function(); }; #endif // NATIVEEMPTY_H diff --git a/doric-Qt/doric/engine/DoricNativeJSE.cpp b/doric-Qt/doric/engine/DoricNativeJSE.cpp index d4459bf6..e7c2ca2c 100644 --- a/doric-Qt/doric/engine/DoricNativeJSE.cpp +++ b/doric-Qt/doric/engine/DoricNativeJSE.cpp @@ -1,33 +1,66 @@ #include -#include +#include +#include #include "../utils/DoricUtils.h" #include "DoricNativeJSE.h" -DoricNativeJSE::DoricNativeJSE() { - v8Executor = new V8Executor(); -// nativeExecutor = new NativeExecutor(); +DoricNativeJSE::DoricNativeJSE(JSEType type) { + mType = type; + if (mType == JSEType::V8) { + v8Executor = new V8Executor(); + } else if (mType == JSEType::Native) { + nativeExecutor = new NativeExecutor(); + } } QString DoricNativeJSE::loadJS(QString script, QString source) { -// return nativeExecutor->loadJS(script, source); - return v8Executor->loadJS(script, source); + if (mType == JSEType::V8) { + return v8Executor->loadJS(script, source); + } else if (mType == JSEType::Native) { + return nativeExecutor->loadJS(script, source); + } } void DoricNativeJSE::injectGlobalJSObject(QString name, QObject *object) { -// nativeExecutor->injectGlobalJSObject(name, object); - v8Executor->injectGlobalJSObject(name, object); + if (mType == JSEType::V8) { + QJsonObject jsonObject; + + QList propertyNames = object->dynamicPropertyNames(); + foreach (QByteArray propertyName, propertyNames) { + QString key = QString::fromStdString(propertyName.toStdString()); + object->property(propertyName).toString(); + if (key == "undefined" || key.isEmpty()) { + + } else { + jsonObject[key] = + QJsonValue::fromVariant(object->property(propertyName)); + } + } + + QJsonDocument doc(jsonObject); + QString strJson(doc.toJson(QJsonDocument::Compact)); + + v8Executor->injectGlobalJSObject(name, strJson.toUtf8().constData()); + } else if (mType == JSEType::Native) { + nativeExecutor->injectGlobalJSObject(name, object); + } } void DoricNativeJSE::injectGlobalJSFunction(QString name, QObject *function, QString property) { -// nativeExecutor->injectGlobalJSFunction(name, function, property); - // v8Executor->injectGlobalJSFunction(name, function, property); + if (mType == JSEType::V8) { + v8Executor->injectGlobalJSFunction(name, function, property); + } else if (mType == JSEType::Native) { + nativeExecutor->injectGlobalJSFunction(name, function, property); + } } QJSValue DoricNativeJSE::invokeObject(QString objectName, QString functionName, QVariantList arguments) { + if (mType == JSEType::V8) { return QJSValue::UndefinedValue; -// return nativeExecutor->invokeObject(objectName, functionName, arguments); - // return v8Executor->invokeObject(objectName, functionName, arguments); + } else if (mType == JSEType::Native) { + return nativeExecutor->invokeObject(objectName, functionName, arguments); + } } diff --git a/doric-Qt/doric/engine/DoricNativeJSE.h b/doric-Qt/doric/engine/DoricNativeJSE.h index 29de8405..4ea399ce 100644 --- a/doric-Qt/doric/engine/DoricNativeJSE.h +++ b/doric-Qt/doric/engine/DoricNativeJSE.h @@ -2,16 +2,20 @@ #define NATIVE_JSE_H #include "DoricInterfaceJSE.h" -//#include "native/NativeExecutor.h" +#include "native/NativeExecutor.h" #include "v8/V8Executor.h" +enum class JSEType { V8, Native }; + class DoricNativeJSE : public DoricInterfaceJSE { private: + JSEType mType; + V8Executor *v8Executor; -// NativeExecutor *nativeExecutor; + NativeExecutor *nativeExecutor; public: - DoricNativeJSE(); + DoricNativeJSE(JSEType type); QString loadJS(QString script, QString source) override; diff --git a/doric-Qt/doric/engine/DoricNativeRequire.cpp b/doric-Qt/doric/engine/DoricNativeRequire.cpp index 5830fdd7..7b98c1ad 100644 --- a/doric-Qt/doric/engine/DoricNativeRequire.cpp +++ b/doric-Qt/doric/engine/DoricNativeRequire.cpp @@ -2,7 +2,6 @@ #include -Q_INVOKABLE QJSValue DoricNativeRequire::function(QString name) { - qDebug() << "nativeRequire"; - return QJSValue::NullValue; +Q_INVOKABLE void DoricNativeRequire::function(QString name) { + qDebug() << "nativeRequire: " << name.toUtf8(); } diff --git a/doric-Qt/doric/engine/DoricNativeRequire.h b/doric-Qt/doric/engine/DoricNativeRequire.h index 70f1206a..e033e558 100644 --- a/doric-Qt/doric/engine/DoricNativeRequire.h +++ b/doric-Qt/doric/engine/DoricNativeRequire.h @@ -1,7 +1,6 @@ #ifndef NATIVE_REQUIRE_H #define NATIVE_REQUIRE_H -#include #include class DoricNativeRequire : public QObject { @@ -10,7 +9,7 @@ class DoricNativeRequire : public QObject { public: DoricNativeRequire(QObject *parent = nullptr) : QObject(parent) {} - Q_INVOKABLE QJSValue function(QString name); + Q_INVOKABLE void function(QString name); }; #endif // NATIVE_REQUIRE_H diff --git a/doric-Qt/doric/engine/v8/JSValueHelper.cpp b/doric-Qt/doric/engine/v8/JSValueHelper.cpp index 02def4f3..ba50c341 100644 --- a/doric-Qt/doric/engine/v8/JSValueHelper.cpp +++ b/doric-Qt/doric/engine/v8/JSValueHelper.cpp @@ -1,9 +1,6 @@ #include "JSValueHelper.h" -#include -#include - -std::string ToString(v8::Local object) { +std::string JS2String(v8::Local object) { v8::Isolate *isolate = v8::Isolate::GetCurrent(); v8::HandleScope handleScope(isolate); v8::Local context = isolate->GetEnteredOrMicrotaskContext(); @@ -22,42 +19,39 @@ std::string ToString(v8::Local object) { return std::string(*str2 ? *str2 : ""); } - v8::Local global = context->Global(); - v8::Local JSON = global->Get(context, NewV8String("JSON")) - .ToLocalChecked() - ->ToObject(context) - .ToLocalChecked(); - v8::Local argv[] = {object}; - v8::Local JSON_stringify = v8::Local::Cast( - JSON->Get(context, NewV8String("stringify")).ToLocalChecked()); v8::String::Utf8Value str( - isolate, JSON_stringify->Call(context, JSON, 1, argv).ToLocalChecked()); + isolate, v8::JSON::Stringify(context, object).ToLocalChecked()); return std::string(*str ? *str : ""); } -v8::Local ObjectToJS(QObject *object) { - QJsonObject jsonObject; - - QList propertyNames = object->dynamicPropertyNames(); - foreach (QByteArray propertyName, propertyNames) { - QString key = QString::fromStdString(propertyName.toStdString()); - object->property(propertyName).toString(); - if (key == "undefined" || key.isEmpty()) { - - } else { - jsonObject[key] = QJsonValue::fromVariant(object->property(propertyName)); - } +double JS2Number(v8::Local value) { + v8::HandleScope handleScope(v8::Isolate::GetCurrent()); + v8::Local context = + v8::Isolate::GetCurrent()->GetCurrentContext(); + if (value->IsNumber()) { + return value->ToNumber(context).ToLocalChecked()->Value(); + } else { + return 0; } +} - QJsonDocument doc(jsonObject); - QString strJson(doc.toJson(QJsonDocument::Compact)); +bool JS2Bool(v8::Local value) { + v8::HandleScope handleScope(v8::Isolate::GetCurrent()); + if (value->IsBoolean()) { + return value->ToBoolean(v8::Isolate::GetCurrent())->Value(); + } else { + return false; + } +} +v8::Local String2JS(std::string string) { v8::Isolate *isolate = v8::Isolate::GetCurrent(); v8::EscapableHandleScope handleScope(isolate); v8::Local context = isolate->GetEnteredOrMicrotaskContext(); - v8::Local jsString = NewV8String(strJson.toUtf8().constData()); + v8::Local jsString = NewV8String(string.c_str()); - v8::Local ret = v8::JSON::Parse(context, jsString).ToLocalChecked(); + v8::Local ret = + v8::JSON::Parse(context, jsString).ToLocalChecked(); return handleScope.Escape(ret); } diff --git a/doric-Qt/doric/engine/v8/JSValueHelper.h b/doric-Qt/doric/engine/v8/JSValueHelper.h index b353f006..44c452f1 100644 --- a/doric-Qt/doric/engine/v8/JSValueHelper.h +++ b/doric-Qt/doric/engine/v8/JSValueHelper.h @@ -1,7 +1,6 @@ #ifndef JSVALUEHELPER_H #define JSVALUEHELPER_H -#include #include #include "v8/v8.h" @@ -11,8 +10,12 @@ v8::NewStringType::kNormal) \ .ToLocalChecked() -std::string ToString(v8::Local object); +std::string JS2String(v8::Local object); -v8::Local ObjectToJS(QObject *object); +double JS2Number(v8::Local value); + +bool JS2Bool(v8::Local value); + +v8::Local String2JS(std::string string); #endif // JSVALUEHELPER_H diff --git a/doric-Qt/doric/engine/v8/V8Executor.cpp b/doric-Qt/doric/engine/v8/V8Executor.cpp index 08dba82a..1c8de69b 100644 --- a/doric-Qt/doric/engine/v8/V8Executor.cpp +++ b/doric-Qt/doric/engine/v8/V8Executor.cpp @@ -1,7 +1,11 @@ -#include "V8Executor.h" +#include + #include "JSValueHelper.h" +#include "V8Executor.h" V8Executor::V8Executor() : platform(v8::platform::NewDefaultPlatform()) { + v8::V8::InitializeICUDefaultLocation(""); + v8::V8::InitializeExternalStartupData(""); v8::V8::InitializePlatform(platform.get()); v8::V8::Initialize(); @@ -42,20 +46,33 @@ QString V8Executor::loadJS(QString script, QString source) { v8::HandleScope scope(isolate); v8::Local ret = innerExec(script.toUtf8().constData(), source.toUtf8().constData(), &exception); - std::string result = ToString(ret); + std::string result = JS2String(ret); return QString::fromUtf8(result.c_str()); } -void V8Executor::injectGlobalJSObject(QString name, QObject *target) { +void V8Executor::injectGlobalJSObject(QString name, std::string target) { v8::Isolate *isolate = m_isolate; v8::HandleScope handleScope(isolate); - v8::Local local = ObjectToJS(target); + v8::Local local = String2JS(target); injectObject(name.toUtf8().constData(), local); } +void V8Executor::injectGlobalJSFunction(QString name, QObject *function, + QString property) { + if (map->keys().contains(name)) { + qCritical() << "already injected"; + return; + } else { + QPair pair(function, property); + map->insert(name, pair); + } + injectFunctions(nullptr, name.toUtf8().constData(), true); +} + +// private segment void V8Executor::injectObject(const char *string, v8::Local local) { v8::Isolate *isolate = m_isolate; @@ -98,11 +115,169 @@ v8::Local V8Executor::innerExec(const char *script, v8::Local exc = v8::Local::Cast(exception); v8::Local stack = exc->Get(context, NewV8String("stack")).FromMaybe(exception); - *exception_str = ToString(stack); + *exception_str = JS2String(stack); } else { - *exception_str = ToString(exception); + *exception_str = JS2String(exception); } } } return handle_scope.Escape(result); } + +static void InjectedFunction(const v8::FunctionCallbackInfo &args) { + v8::Isolate *isolate = args.GetIsolate(); + v8::HandleScope scope(isolate); + v8::Local context = isolate->GetEnteredOrMicrotaskContext(); + v8::Local data = args.Data()->ToObject(context).ToLocalChecked(); + + std::string objectKey = + JS2String(data->Get(context, NewV8String("obj")).ToLocalChecked()) + .c_str(); + std::string functionKey = + JS2String(data->Get(context, NewV8String("func")).ToLocalChecked()) + .c_str(); + bool hashKey = data->Get(context, NewV8String("hashKey")) + .ToLocalChecked() + ->BooleanValue(isolate); + + // invoke + QPair pair = + map->find(QString::fromUtf8(functionKey.c_str())).value(); + + QString functionKeyQString = QString::fromUtf8(functionKey.c_str()); + + if (args.Length() == 0) { + if (functionKeyQString == "nativeEmpty") { + QMetaObject::invokeMethod(pair.first, pair.second.toUtf8().constData(), + Qt::DirectConnection, QGenericReturnArgument()); + } + } else if (args.Length() == 1) { + if (functionKeyQString == "nativeRequire") { + v8::Local arg = args[0]; + std::string argString = JS2String(arg); + + QMetaObject::invokeMethod( + pair.first, pair.second.toUtf8().constData(), Qt::DirectConnection, + QGenericReturnArgument(), + Q_ARG(QString, QString::fromUtf8(argString.c_str()))); + } else if (functionKeyQString == "nativeClearTimer") { + v8::Local arg = args[0]; + double number = JS2Number(arg); + + QMetaObject::invokeMethod(pair.first, pair.second.toUtf8().constData(), + Qt::DirectConnection, QGenericReturnArgument(), + Q_ARG(long, number)); + } + + } else if (args.Length() == 2) { + v8::Local arg0 = args[0]; + std::string argString0 = JS2String(arg0); + + v8::Local arg1 = args[1]; + std::string argString1 = JS2String(arg1); + + QMetaObject::invokeMethod( + pair.first, pair.second.toUtf8().constData(), Qt::DirectConnection, + QGenericReturnArgument(), + Q_ARG(QString, QString::fromUtf8(argString0.c_str())), + Q_ARG(QString, QString::fromUtf8(argString1.c_str()))); + } else if (args.Length() == 3) { + v8::Local arg0 = args[0]; + long argLong = JS2Number(arg0); + + v8::Local arg1 = args[1]; + int argInt = JS2Number(arg1); + + v8::Local arg2 = args[2]; + bool argBool = JS2Bool(arg2); + + QMetaObject::invokeMethod(pair.first, pair.second.toUtf8().constData(), + Qt::DirectConnection, QGenericReturnArgument(), + Q_ARG(long, argLong), Q_ARG(int, argInt), + Q_ARG(bool, argBool)); + } else if (args.Length() == 5) { + v8::Local arg0 = args[0]; + std::string argString0 = JS2String(arg0); + + v8::Local arg1 = args[1]; + std::string argString1 = JS2String(arg1); + + v8::Local arg2 = args[2]; + std::string argString2 = JS2String(arg2); + + v8::Local arg3 = args[3]; + std::string argString3 = JS2String(arg3); + + v8::Local arg4 = args[4]; + std::string argString4 = JS2String(arg4); + + QMetaObject::invokeMethod( + pair.first, pair.second.toUtf8().constData(), Qt::DirectConnection, + QGenericReturnArgument(), + Q_ARG(QString, QString::fromStdString(argString0)), + Q_ARG(QString, QString::fromStdString(argString1)), + Q_ARG(QString, QString::fromStdString(argString2)), + Q_ARG(QString, QString::fromStdString(argString3)), + Q_ARG(QString, QString::fromStdString(argString4))); + } + + // begin check to perform micro task checkpoint + + std::string objectNameString = "global"; + std::string functionKeyString = "nativeEmpty"; + + int objectCompareResult = strncmp(objectKey.c_str(), objectNameString.c_str(), + strlen(objectKey.c_str())); + + if (objectCompareResult == 0) { + int functionCompareResult = + strncmp(functionKey.c_str(), functionKeyString.c_str(), + strlen(functionKey.c_str())); + if (functionCompareResult == 0) { + isolate->PerformMicrotaskCheckpoint(); + } + } + // end check +} + +void V8Executor::injectFunctions(const char *objectName, + const char *functionName, bool hashKey) { + v8::Isolate *isolate = m_isolate; + + v8::HandleScope handle_scope(isolate); + v8::Local context = isolate->GetEnteredOrMicrotaskContext(); + v8::Local object = context->Global(); + if (objectName) { + object = object->Get(context, NewV8String(objectName)) + .ToLocalChecked() + ->ToObject(context) + .ToLocalChecked(); + } + + v8::Local name = NewV8String(functionName); + v8::Local data = v8::Object::New(isolate); + if (objectName) { + v8::Maybe result = + data->Set(context, NewV8String("obj"), NewV8String(objectName)); + result.ToChecked(); + } else { + v8::Maybe result = + data->Set(context, NewV8String("obj"), NewV8String("global")); + result.ToChecked(); + } + { + v8::Maybe result = + data->Set(context, NewV8String("func"), NewV8String(functionName)); + result.ToChecked(); + } + { + v8::Maybe result = data->Set(context, NewV8String("hashKey"), + v8::Boolean::New(isolate, hashKey)); + result.ToChecked(); + } + + v8::Local function = + v8::Function::New(context, InjectedFunction, data).ToLocalChecked(); + v8::Maybe result = object->Set(context, name, function); + result.ToChecked(); +} diff --git a/doric-Qt/doric/engine/v8/V8Executor.h b/doric-Qt/doric/engine/v8/V8Executor.h index c227048b..b0dd2059 100644 --- a/doric-Qt/doric/engine/v8/V8Executor.h +++ b/doric-Qt/doric/engine/v8/V8Executor.h @@ -4,9 +4,13 @@ #include "libplatform/libplatform.h" #include "v8/v8.h" +#include #include #include +static QMap> *map = + new QMap>(); + class V8Executor { private: @@ -21,6 +25,9 @@ private: v8::Local innerExec(const char *script, const char *source, std::string *exception_str); + void injectFunctions(const char *objectName, const char *functionName, + bool hashKey); + public: V8Executor(); @@ -28,7 +35,10 @@ public: QString loadJS(QString script, QString source); - void injectGlobalJSObject(QString name, QObject *object); + void injectGlobalJSObject(QString name, std::string target); + + void injectGlobalJSFunction(QString name, QObject *function, + QString property); }; #endif // V8EXECUTOR_H