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) {
return DoricAsyncCall::ensureRunInThreadPool(
&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 <QJsonDocument>
#include <QJsonObject>
#include <QMetaObject>
#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;
}

View File

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

View File

@ -1,7 +1,6 @@
#ifndef INTERFACE_JSE_H
#define INTERFACE_JSE_H
#include <QJSValue>
#include <QString>
#include <QVariant>
@ -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;
};

View File

@ -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);
}

View File

@ -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();
};

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) {
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);
}
}

View File

@ -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;
};

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