diff --git a/doric-Qt/doric/DoricNativeDriver.cpp b/doric-Qt/doric/DoricNativeDriver.cpp index 7869e029..9b09b61b 100644 --- a/doric-Qt/doric/DoricNativeDriver.cpp +++ b/doric-Qt/doric/DoricNativeDriver.cpp @@ -15,7 +15,7 @@ void DoricNativeDriver::invokeContextEntityMethod(QString contextId, void DoricNativeDriver::invokeDoricMethod(QString method, QVariantList args) { return DoricAsyncCall::ensureRunInThreadPool( &jsEngine.mJSThreadPool, [this, method, args] { - this->jsEngine.invokeDoricMethod(method, args).toString(); + this->jsEngine.invokeDoricMethod(method, args); }); } diff --git a/doric-Qt/doric/engine/DoricBridgeExtension.cpp b/doric-Qt/doric/engine/DoricBridgeExtension.cpp index 9fcbf90a..b967b8ec 100644 --- a/doric-Qt/doric/engine/DoricBridgeExtension.cpp +++ b/doric-Qt/doric/engine/DoricBridgeExtension.cpp @@ -1,4 +1,6 @@ #include +#include +#include #include #include "../DoricContextManager.h" @@ -8,7 +10,9 @@ DoricBridgeExtension::DoricBridgeExtension(QObject *parent) : QObject(parent) {} void DoricBridgeExtension::callNative(QString contextId, QString module, QString methodName, QString callbackId, - QJSValue jsValue) { + QString argument) { + QJsonDocument document = QJsonDocument::fromJson(argument.toUtf8()); + QJsonObject jsValue = document.object(); DoricContext *context = DoricContextManager::getInstance()->getContext(contextId); bool classRegistered = @@ -17,10 +21,10 @@ void DoricBridgeExtension::callNative(QString contextId, QString module, QObject *plugin = context->obtainPlugin(module); QMetaObject::invokeMethod(plugin, methodName.toUtf8(), Qt::DirectConnection, QGenericReturnArgument(), - Q_ARG(QJSValue, jsValue), + Q_ARG(QJsonObject, jsValue), Q_ARG(QString, callbackId)); } qDebug() << "contextId: " + contextId << "module: " + module << "methodName: " + methodName << "callbackId: " + callbackId - << "jsValue: " + jsValue.toString(); + << "jsValue: " + argument; } diff --git a/doric-Qt/doric/engine/DoricBridgeExtension.h b/doric-Qt/doric/engine/DoricBridgeExtension.h index a2901d1e..f31d098a 100644 --- a/doric-Qt/doric/engine/DoricBridgeExtension.h +++ b/doric-Qt/doric/engine/DoricBridgeExtension.h @@ -11,7 +11,7 @@ public: Q_INVOKABLE void callNative(QString contextId, QString module, QString methodName, QString callbackId, - QJSValue jsValue); + QString argument); }; #endif // BRIDGEEXTENSION_H diff --git a/doric-Qt/doric/engine/DoricInterfaceJSE.h b/doric-Qt/doric/engine/DoricInterfaceJSE.h index 68a878e1..905b657a 100644 --- a/doric-Qt/doric/engine/DoricInterfaceJSE.h +++ b/doric-Qt/doric/engine/DoricInterfaceJSE.h @@ -1,7 +1,6 @@ #ifndef INTERFACE_JSE_H #define INTERFACE_JSE_H -#include #include #include @@ -14,7 +13,7 @@ public: virtual void injectGlobalJSFunction(QString name, QObject *function, QString property) = 0; - virtual QJSValue invokeObject(QString objectName, QString functionName, + virtual void invokeObject(QString objectName, QString functionName, QVariantList arguments) = 0; }; diff --git a/doric-Qt/doric/engine/DoricJSEngine.cpp b/doric-Qt/doric/engine/DoricJSEngine.cpp index 9e0dd606..6a338e51 100644 --- a/doric-Qt/doric/engine/DoricJSEngine.cpp +++ b/doric-Qt/doric/engine/DoricJSEngine.cpp @@ -98,7 +98,7 @@ void DoricJSEngine::prepareContext(QString contextId, QString script, mJSE->loadJS(packageContextScript(contextId, script), "Context://" + source); } -QJSValue DoricJSEngine::invokeDoricMethod(QString method, +void DoricJSEngine::invokeDoricMethod(QString method, QVariantList arguments) { return mJSE->invokeObject(DoricConstant::GLOBAL_DORIC, method, arguments); } diff --git a/doric-Qt/doric/engine/DoricJSEngine.h b/doric-Qt/doric/engine/DoricJSEngine.h index 8ad5a1cc..979a6779 100644 --- a/doric-Qt/doric/engine/DoricJSEngine.h +++ b/doric-Qt/doric/engine/DoricJSEngine.h @@ -25,7 +25,7 @@ public: ~DoricJSEngine(); void prepareContext(QString contextId, QString script, QString source); - QJSValue invokeDoricMethod(QString method, QVariantList arguments); + void invokeDoricMethod(QString method, QVariantList arguments); DoricRegistry *getRegistry(); }; diff --git a/doric-Qt/doric/engine/DoricNativeJSE.cpp b/doric-Qt/doric/engine/DoricNativeJSE.cpp index e7c2ca2c..1a59c85b 100644 --- a/doric-Qt/doric/engine/DoricNativeJSE.cpp +++ b/doric-Qt/doric/engine/DoricNativeJSE.cpp @@ -56,11 +56,11 @@ void DoricNativeJSE::injectGlobalJSFunction(QString name, QObject *function, } } -QJSValue DoricNativeJSE::invokeObject(QString objectName, QString functionName, - QVariantList arguments) { +void DoricNativeJSE::invokeObject(QString objectName, QString functionName, + QVariantList arguments) { if (mType == JSEType::V8) { - return QJSValue::UndefinedValue; + v8Executor->invokeObject(objectName, functionName, arguments); } else if (mType == JSEType::Native) { - return nativeExecutor->invokeObject(objectName, functionName, arguments); + nativeExecutor->invokeObject(objectName, functionName, arguments); } } diff --git a/doric-Qt/doric/engine/DoricNativeJSE.h b/doric-Qt/doric/engine/DoricNativeJSE.h index 4ea399ce..a314696f 100644 --- a/doric-Qt/doric/engine/DoricNativeJSE.h +++ b/doric-Qt/doric/engine/DoricNativeJSE.h @@ -24,7 +24,7 @@ public: void injectGlobalJSFunction(QString name, QObject *function, QString property) override; - QJSValue invokeObject(QString objectName, QString functionName, + void invokeObject(QString objectName, QString functionName, QVariantList arguments) override; }; diff --git a/doric-Qt/doric/engine/v8/JSValueHelper.cpp b/doric-Qt/doric/engine/v8/JSValueHelper.cpp index ba50c341..57f56092 100644 --- a/doric-Qt/doric/engine/v8/JSValueHelper.cpp +++ b/doric-Qt/doric/engine/v8/JSValueHelper.cpp @@ -1,5 +1,8 @@ #include "JSValueHelper.h" +#include +#include + std::string JS2String(v8::Local object) { v8::Isolate *isolate = v8::Isolate::GetCurrent(); v8::HandleScope handleScope(isolate); @@ -55,3 +58,27 @@ v8::Local String2JS(std::string string) { return handleScope.Escape(ret); } + +v8::Local Variant2JS(QVariant variant) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope handle_scope(isolate); + + v8::Local jsValue; + if (variant.type() == QVariant::String) { + jsValue = NewV8String(variant.toString().toUtf8().constData()); + } else if (variant.type() == QVariant::Map) { + QMap map = variant.toMap(); + + QJsonObject jsonObject; + foreach (QString key, map.keys()) { + QVariant value = map.value(key); + jsonObject.insert(key, QJsonValue::fromVariant(value)); + } + QJsonDocument doc(jsonObject); + QString strJson(doc.toJson(QJsonDocument::Compact)); + jsValue = String2JS(strJson.toUtf8().constData()); + } else if (variant.type() == QVariant::StringList) { + qDebug() << ""; + } + return handle_scope.Escape(jsValue); +} diff --git a/doric-Qt/doric/engine/v8/JSValueHelper.h b/doric-Qt/doric/engine/v8/JSValueHelper.h index 44c452f1..8a4acfe6 100644 --- a/doric-Qt/doric/engine/v8/JSValueHelper.h +++ b/doric-Qt/doric/engine/v8/JSValueHelper.h @@ -1,6 +1,7 @@ #ifndef JSVALUEHELPER_H #define JSVALUEHELPER_H +#include #include #include "v8/v8.h" @@ -18,4 +19,6 @@ bool JS2Bool(v8::Local value); v8::Local String2JS(std::string string); +v8::Local Variant2JS(QVariant variant); + #endif // JSVALUEHELPER_H diff --git a/doric-Qt/doric/engine/v8/V8Executor.cpp b/doric-Qt/doric/engine/v8/V8Executor.cpp index 1c8de69b..deeb5c45 100644 --- a/doric-Qt/doric/engine/v8/V8Executor.cpp +++ b/doric-Qt/doric/engine/v8/V8Executor.cpp @@ -72,6 +72,22 @@ void V8Executor::injectGlobalJSFunction(QString name, QObject *function, injectFunctions(nullptr, name.toUtf8().constData(), true); } +void V8Executor::invokeObject(QString objectName, QString functionName, + QVariantList arguments) { + std::string exception; + v8::HandleScope handleScope(m_isolate); + int valueSize = arguments.size(); + + auto js_values = new v8::Local[valueSize]; + for (uint32_t i = 0; i < valueSize; i++) { + js_values[i] = Variant2JS(arguments.at(i)); + } + v8::Local value = invokeMethod(objectName.toUtf8().constData(), + functionName.toUtf8().constData(), + valueSize, js_values, &exception); + delete[] js_values; +} + // private segment void V8Executor::injectObject(const char *string, v8::Local local) { v8::Isolate *isolate = m_isolate; @@ -214,11 +230,11 @@ static void InjectedFunction(const v8::FunctionCallbackInfo &args) { 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))); + Q_ARG(QString, QString::fromUtf8(argString0.c_str())), + Q_ARG(QString, QString::fromUtf8(argString1.c_str())), + Q_ARG(QString, QString::fromUtf8(argString2.c_str())), + Q_ARG(QString, QString::fromUtf8(argString3.c_str())), + Q_ARG(QString, QString::fromUtf8(argString4.c_str()))); } // begin check to perform micro task checkpoint @@ -281,3 +297,52 @@ void V8Executor::injectFunctions(const char *objectName, v8::Maybe result = object->Set(context, name, function); result.ToChecked(); } + +v8::Local V8Executor::invokeMethod(const char *objectName, + const char *functionName, + int argc, + v8::Local argv[], + std::string *exception_str) { + v8::Isolate *isolate = m_isolate; + v8::EscapableHandleScope handle_scope(isolate); + v8::Local context = isolate->GetEnteredOrMicrotaskContext(); + v8::Local object = context->Global(); + v8::Local result = Undefined(isolate); + + if (objectName) { + object = object->Get(context, NewV8String(objectName)) + .ToLocalChecked() + ->ToObject(context) + .ToLocalChecked(); + } + if (object.IsEmpty()) { + *exception_str = std::string("Cannot find Object:") + + std::string(objectName ? objectName : "global"); + return handle_scope.Escape(result); + } + v8::Local target_value = + object->Get(context, NewV8String(functionName)).ToLocalChecked(); + if (!target_value->IsFunction()) { + *exception_str = + std::string("In ") + std::string(objectName ? objectName : "global") + + std::string("cannot find target function ") + std::string(functionName); + return handle_scope.Escape(result); + } + v8::TryCatch try_catch(isolate); + try_catch.SetVerbose(true); + v8::Local target_function = + v8::Local::Cast(target_value); + result = target_function->Call(context, object, argc, argv).ToLocalChecked(); + v8::Local exception = try_catch.Exception(); + if (!exception.IsEmpty()) { + if (exception->IsObject()) { + v8::Local exc = v8::Local::Cast(exception); + v8::Local stack = + exc->Get(context, NewV8String("stack")).FromMaybe(exception); + *exception_str = JS2String(stack); + } else { + *exception_str = JS2String(exception); + } + } + return handle_scope.Escape(result); +} diff --git a/doric-Qt/doric/engine/v8/V8Executor.h b/doric-Qt/doric/engine/v8/V8Executor.h index b0dd2059..af360fc2 100644 --- a/doric-Qt/doric/engine/v8/V8Executor.h +++ b/doric-Qt/doric/engine/v8/V8Executor.h @@ -28,6 +28,11 @@ private: void injectFunctions(const char *objectName, const char *functionName, bool hashKey); + v8::Local invokeMethod(const char *objectName, + const char *functionName, int argc, + v8::Local argv[], + std::string *exception_str); + public: V8Executor(); @@ -39,6 +44,9 @@ public: void injectGlobalJSFunction(QString name, QObject *function, QString property); + + void invokeObject(QString objectName, QString functionName, + QVariantList arguments); }; #endif // V8EXECUTOR_H