complete invoke method on v8

This commit is contained in:
王劲鹏 2021-04-02 17:23:36 +08:00 committed by osborn
parent dada2e4e0d
commit 7458d0f4c0
12 changed files with 125 additions and 19 deletions

View File

@ -15,7 +15,7 @@ void DoricNativeDriver::invokeContextEntityMethod(QString contextId,
void DoricNativeDriver::invokeDoricMethod(QString method, QVariantList args) { void DoricNativeDriver::invokeDoricMethod(QString method, QVariantList args) {
return DoricAsyncCall::ensureRunInThreadPool( return DoricAsyncCall::ensureRunInThreadPool(
&jsEngine.mJSThreadPool, [this, method, args] { &jsEngine.mJSThreadPool, [this, method, args] {
this->jsEngine.invokeDoricMethod(method, args).toString(); this->jsEngine.invokeDoricMethod(method, args);
}); });
} }

View File

@ -1,4 +1,6 @@
#include <QDebug> #include <QDebug>
#include <QJsonDocument>
#include <QJsonObject>
#include <QMetaObject> #include <QMetaObject>
#include "../DoricContextManager.h" #include "../DoricContextManager.h"
@ -8,7 +10,9 @@ DoricBridgeExtension::DoricBridgeExtension(QObject *parent) : QObject(parent) {}
void DoricBridgeExtension::callNative(QString contextId, QString module, void DoricBridgeExtension::callNative(QString contextId, QString module,
QString methodName, QString callbackId, QString methodName, QString callbackId,
QJSValue jsValue) { QString argument) {
QJsonDocument document = QJsonDocument::fromJson(argument.toUtf8());
QJsonObject jsValue = document.object();
DoricContext *context = DoricContext *context =
DoricContextManager::getInstance()->getContext(contextId); DoricContextManager::getInstance()->getContext(contextId);
bool classRegistered = bool classRegistered =
@ -17,10 +21,10 @@ void DoricBridgeExtension::callNative(QString contextId, QString module,
QObject *plugin = context->obtainPlugin(module); QObject *plugin = context->obtainPlugin(module);
QMetaObject::invokeMethod(plugin, methodName.toUtf8(), Qt::DirectConnection, QMetaObject::invokeMethod(plugin, methodName.toUtf8(), Qt::DirectConnection,
QGenericReturnArgument(), QGenericReturnArgument(),
Q_ARG(QJSValue, jsValue), Q_ARG(QJsonObject, jsValue),
Q_ARG(QString, callbackId)); Q_ARG(QString, callbackId));
} }
qDebug() << "contextId: " + contextId << "module: " + module qDebug() << "contextId: " + contextId << "module: " + module
<< "methodName: " + methodName << "callbackId: " + callbackId << "methodName: " + methodName << "callbackId: " + callbackId
<< "jsValue: " + jsValue.toString(); << "jsValue: " + argument;
} }

View File

@ -11,7 +11,7 @@ public:
Q_INVOKABLE void callNative(QString contextId, QString module, Q_INVOKABLE void callNative(QString contextId, QString module,
QString methodName, QString callbackId, QString methodName, QString callbackId,
QJSValue jsValue); QString argument);
}; };
#endif // BRIDGEEXTENSION_H #endif // BRIDGEEXTENSION_H

View File

@ -1,7 +1,6 @@
#ifndef INTERFACE_JSE_H #ifndef INTERFACE_JSE_H
#define INTERFACE_JSE_H #define INTERFACE_JSE_H
#include <QJSValue>
#include <QString> #include <QString>
#include <QVariant> #include <QVariant>
@ -14,7 +13,7 @@ public:
virtual void injectGlobalJSFunction(QString name, QObject *function, virtual void injectGlobalJSFunction(QString name, QObject *function,
QString property) = 0; QString property) = 0;
virtual QJSValue invokeObject(QString objectName, QString functionName, virtual void invokeObject(QString objectName, QString functionName,
QVariantList arguments) = 0; QVariantList arguments) = 0;
}; };

View File

@ -98,7 +98,7 @@ void DoricJSEngine::prepareContext(QString contextId, QString script,
mJSE->loadJS(packageContextScript(contextId, script), "Context://" + source); mJSE->loadJS(packageContextScript(contextId, script), "Context://" + source);
} }
QJSValue DoricJSEngine::invokeDoricMethod(QString method, void DoricJSEngine::invokeDoricMethod(QString method,
QVariantList arguments) { QVariantList arguments) {
return mJSE->invokeObject(DoricConstant::GLOBAL_DORIC, method, arguments); return mJSE->invokeObject(DoricConstant::GLOBAL_DORIC, method, arguments);
} }

View File

@ -25,7 +25,7 @@ public:
~DoricJSEngine(); ~DoricJSEngine();
void prepareContext(QString contextId, QString script, QString source); void prepareContext(QString contextId, QString script, QString source);
QJSValue invokeDoricMethod(QString method, QVariantList arguments); void invokeDoricMethod(QString method, QVariantList arguments);
DoricRegistry *getRegistry(); DoricRegistry *getRegistry();
}; };

View File

@ -56,11 +56,11 @@ void DoricNativeJSE::injectGlobalJSFunction(QString name, QObject *function,
} }
} }
QJSValue DoricNativeJSE::invokeObject(QString objectName, QString functionName, void DoricNativeJSE::invokeObject(QString objectName, QString functionName,
QVariantList arguments) { QVariantList arguments) {
if (mType == JSEType::V8) { if (mType == JSEType::V8) {
return QJSValue::UndefinedValue; v8Executor->invokeObject(objectName, functionName, arguments);
} else if (mType == JSEType::Native) { } else if (mType == JSEType::Native) {
return nativeExecutor->invokeObject(objectName, functionName, arguments); nativeExecutor->invokeObject(objectName, functionName, arguments);
} }
} }

View File

@ -24,7 +24,7 @@ public:
void injectGlobalJSFunction(QString name, QObject *function, void injectGlobalJSFunction(QString name, QObject *function,
QString property) override; QString property) override;
QJSValue invokeObject(QString objectName, QString functionName, void invokeObject(QString objectName, QString functionName,
QVariantList arguments) override; QVariantList arguments) override;
}; };

View File

@ -1,5 +1,8 @@
#include "JSValueHelper.h" #include "JSValueHelper.h"
#include <QJsonDocument>
#include <QJsonObject>
std::string JS2String(v8::Local<v8::Value> object) { std::string JS2String(v8::Local<v8::Value> object) {
v8::Isolate *isolate = v8::Isolate::GetCurrent(); v8::Isolate *isolate = v8::Isolate::GetCurrent();
v8::HandleScope handleScope(isolate); v8::HandleScope handleScope(isolate);
@ -55,3 +58,27 @@ v8::Local<v8::Value> String2JS(std::string string) {
return handleScope.Escape(ret); return handleScope.Escape(ret);
} }
v8::Local<v8::Value> Variant2JS(QVariant variant) {
v8::Isolate *isolate = v8::Isolate::GetCurrent();
v8::EscapableHandleScope handle_scope(isolate);
v8::Local<v8::Value> jsValue;
if (variant.type() == QVariant::String) {
jsValue = NewV8String(variant.toString().toUtf8().constData());
} else if (variant.type() == QVariant::Map) {
QMap<QString, QVariant> 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);
}

View File

@ -1,6 +1,7 @@
#ifndef JSVALUEHELPER_H #ifndef JSVALUEHELPER_H
#define JSVALUEHELPER_H #define JSVALUEHELPER_H
#include <QVariant>
#include <string> #include <string>
#include "v8/v8.h" #include "v8/v8.h"
@ -18,4 +19,6 @@ bool JS2Bool(v8::Local<v8::Value> value);
v8::Local<v8::Value> String2JS(std::string string); v8::Local<v8::Value> String2JS(std::string string);
v8::Local<v8::Value> Variant2JS(QVariant variant);
#endif // JSVALUEHELPER_H #endif // JSVALUEHELPER_H

View File

@ -72,6 +72,22 @@ void V8Executor::injectGlobalJSFunction(QString name, QObject *function,
injectFunctions(nullptr, name.toUtf8().constData(), true); 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<v8::Value>[valueSize];
for (uint32_t i = 0; i < valueSize; i++) {
js_values[i] = Variant2JS(arguments.at(i));
}
v8::Local<v8::Value> value = invokeMethod(objectName.toUtf8().constData(),
functionName.toUtf8().constData(),
valueSize, js_values, &exception);
delete[] js_values;
}
// private segment // private segment
void V8Executor::injectObject(const char *string, v8::Local<v8::Value> local) { void V8Executor::injectObject(const char *string, v8::Local<v8::Value> local) {
v8::Isolate *isolate = m_isolate; v8::Isolate *isolate = m_isolate;
@ -214,11 +230,11 @@ static void InjectedFunction(const v8::FunctionCallbackInfo<v8::Value> &args) {
QMetaObject::invokeMethod( QMetaObject::invokeMethod(
pair.first, pair.second.toUtf8().constData(), Qt::DirectConnection, pair.first, pair.second.toUtf8().constData(), Qt::DirectConnection,
QGenericReturnArgument(), QGenericReturnArgument(),
Q_ARG(QString, QString::fromStdString(argString0)), Q_ARG(QString, QString::fromUtf8(argString0.c_str())),
Q_ARG(QString, QString::fromStdString(argString1)), Q_ARG(QString, QString::fromUtf8(argString1.c_str())),
Q_ARG(QString, QString::fromStdString(argString2)), Q_ARG(QString, QString::fromUtf8(argString2.c_str())),
Q_ARG(QString, QString::fromStdString(argString3)), Q_ARG(QString, QString::fromUtf8(argString3.c_str())),
Q_ARG(QString, QString::fromStdString(argString4))); Q_ARG(QString, QString::fromUtf8(argString4.c_str())));
} }
// begin check to perform micro task checkpoint // begin check to perform micro task checkpoint
@ -281,3 +297,52 @@ void V8Executor::injectFunctions(const char *objectName,
v8::Maybe<bool> result = object->Set(context, name, function); v8::Maybe<bool> result = object->Set(context, name, function);
result.ToChecked(); result.ToChecked();
} }
v8::Local<v8::Value> V8Executor::invokeMethod(const char *objectName,
const char *functionName,
int argc,
v8::Local<v8::Value> argv[],
std::string *exception_str) {
v8::Isolate *isolate = m_isolate;
v8::EscapableHandleScope handle_scope(isolate);
v8::Local<v8::Context> context = isolate->GetEnteredOrMicrotaskContext();
v8::Local<v8::Object> object = context->Global();
v8::Local<v8::Value> 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<v8::Value> 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<v8::Function> target_function =
v8::Local<v8::Function>::Cast(target_value);
result = target_function->Call(context, object, argc, argv).ToLocalChecked();
v8::Local<v8::Value> exception = try_catch.Exception();
if (!exception.IsEmpty()) {
if (exception->IsObject()) {
v8::Local<v8::Object> exc = v8::Local<v8::Object>::Cast(exception);
v8::Local<v8::Value> stack =
exc->Get(context, NewV8String("stack")).FromMaybe(exception);
*exception_str = JS2String(stack);
} else {
*exception_str = JS2String(exception);
}
}
return handle_scope.Escape(result);
}

View File

@ -28,6 +28,11 @@ private:
void injectFunctions(const char *objectName, const char *functionName, void injectFunctions(const char *objectName, const char *functionName,
bool hashKey); bool hashKey);
v8::Local<v8::Value> invokeMethod(const char *objectName,
const char *functionName, int argc,
v8::Local<v8::Value> argv[],
std::string *exception_str);
public: public:
V8Executor(); V8Executor();
@ -39,6 +44,9 @@ public:
void injectGlobalJSFunction(QString name, QObject *function, void injectGlobalJSFunction(QString name, QObject *function,
QString property); QString property);
void invokeObject(QString objectName, QString functionName,
QVariantList arguments);
}; };
#endif // V8EXECUTOR_H #endif // V8EXECUTOR_H