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

@@ -1,5 +1,8 @@
#include "JSValueHelper.h"
#include <QJsonDocument>
#include <QJsonObject>
std::string JS2String(v8::Local<v8::Value> object) {
v8::Isolate *isolate = v8::Isolate::GetCurrent();
v8::HandleScope handleScope(isolate);
@@ -55,3 +58,27 @@ v8::Local<v8::Value> String2JS(std::string string) {
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
#define JSVALUEHELPER_H
#include <QVariant>
#include <string>
#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> Variant2JS(QVariant variant);
#endif // JSVALUEHELPER_H

View File

@@ -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<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
void V8Executor::injectObject(const char *string, v8::Local<v8::Value> local) {
v8::Isolate *isolate = m_isolate;
@@ -214,11 +230,11 @@ static void InjectedFunction(const v8::FunctionCallbackInfo<v8::Value> &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<bool> result = object->Set(context, name, function);
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,
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:
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