complete invoke (except callNative)
This commit is contained in:
parent
18cef64141
commit
dada2e4e0d
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE QtCreatorProject>
|
<!DOCTYPE QtCreatorProject>
|
||||||
<!-- Written by QtCreator 4.14.1, 2021-03-31T17:10:25. -->
|
<!-- Written by QtCreator 4.14.1, 2021-04-01T16:59:16. -->
|
||||||
<qtcreator>
|
<qtcreator>
|
||||||
<data>
|
<data>
|
||||||
<variable>EnvironmentId</variable>
|
<variable>EnvironmentId</variable>
|
||||||
@ -301,6 +301,7 @@
|
|||||||
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
<value type="QString" key="RunConfiguration.WorkingDirectory.default">C:/Users/maverick/Workspace/Doric/doric-Qt/build-doric-Desktop_Qt_6_0_2_MSVC2019_64bit-Debug</value>
|
||||||
</valuemap>
|
</valuemap>
|
||||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||||
</valuemap>
|
</valuemap>
|
||||||
|
@ -15,8 +15,8 @@ void DoricBridgeExtension::callNative(QString contextId, QString module,
|
|||||||
context->getDriver()->getRegistry()->acquirePluginInfo(module);
|
context->getDriver()->getRegistry()->acquirePluginInfo(module);
|
||||||
if (classRegistered) {
|
if (classRegistered) {
|
||||||
QObject *plugin = context->obtainPlugin(module);
|
QObject *plugin = context->obtainPlugin(module);
|
||||||
QMetaObject::invokeMethod(plugin, methodName.toStdString().c_str(),
|
QMetaObject::invokeMethod(plugin, methodName.toUtf8(), Qt::DirectConnection,
|
||||||
Qt::DirectConnection, QGenericReturnArgument(),
|
QGenericReturnArgument(),
|
||||||
Q_ARG(QJSValue, jsValue),
|
Q_ARG(QJSValue, jsValue),
|
||||||
Q_ARG(QString, callbackId));
|
Q_ARG(QString, callbackId));
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,12 @@
|
|||||||
DoricJSEngine::DoricJSEngine(QObject *parent) : QObject(parent) {
|
DoricJSEngine::DoricJSEngine(QObject *parent) : QObject(parent) {
|
||||||
mJSThreadPool.setMaxThreadCount(1);
|
mJSThreadPool.setMaxThreadCount(1);
|
||||||
|
|
||||||
QtConcurrent::run(&mJSThreadPool, [this] {
|
{
|
||||||
mJSE = new DoricNativeJSE();
|
auto result = QtConcurrent::run(
|
||||||
});
|
&mJSThreadPool, [this] { mJSE = new DoricNativeJSE(JSEType::V8); });
|
||||||
QtConcurrent::run(&mJSThreadPool, [this] {
|
}
|
||||||
|
{
|
||||||
|
auto result = QtConcurrent::run(&mJSThreadPool, [this] {
|
||||||
// inject env
|
// inject env
|
||||||
QScreen *screen = QGuiApplication::primaryScreen();
|
QScreen *screen = QGuiApplication::primaryScreen();
|
||||||
QRect screenGeometry = screen->geometry();
|
QRect screenGeometry = screen->geometry();
|
||||||
@ -72,10 +74,13 @@ DoricJSEngine::DoricJSEngine(QObject *parent) : QObject(parent) {
|
|||||||
timerExtension, "clearTimer");
|
timerExtension, "clearTimer");
|
||||||
|
|
||||||
DoricBridgeExtension *bridgeExtension = new DoricBridgeExtension();
|
DoricBridgeExtension *bridgeExtension = new DoricBridgeExtension();
|
||||||
mJSE->injectGlobalJSFunction(DoricConstant::INJECT_BRIDGE, bridgeExtension,
|
mJSE->injectGlobalJSFunction(DoricConstant::INJECT_BRIDGE,
|
||||||
"callNative");
|
bridgeExtension, "callNative");
|
||||||
});
|
});
|
||||||
QtConcurrent::run(&mJSThreadPool, [this] {
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto result = QtConcurrent::run(&mJSThreadPool, [this] {
|
||||||
loadBuiltinJS(DoricConstant::DORIC_BUNDLE_SANDBOX);
|
loadBuiltinJS(DoricConstant::DORIC_BUNDLE_SANDBOX);
|
||||||
|
|
||||||
QString libName = DoricConstant::DORIC_MODULE_LIB;
|
QString libName = DoricConstant::DORIC_MODULE_LIB;
|
||||||
@ -86,6 +91,7 @@ DoricJSEngine::DoricJSEngine(QObject *parent) : QObject(parent) {
|
|||||||
mJSE->loadJS(script, "Module://" + libName);
|
mJSE->loadJS(script, "Module://" + libName);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DoricJSEngine::prepareContext(QString contextId, QString script,
|
void DoricJSEngine::prepareContext(QString contextId, QString script,
|
||||||
QString source) {
|
QString source) {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#include "DoricNativeEmpty.h"
|
#include "DoricNativeEmpty.h"
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
Q_INVOKABLE QJSValue DoricNativeEmpty::function() {
|
Q_INVOKABLE void DoricNativeEmpty::function() {
|
||||||
qDebug() << "nativeEmpty";
|
qDebug() << "nativeEmpty";
|
||||||
return QJSValue::NullValue;
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#ifndef NATIVEEMPTY_H
|
#ifndef NATIVEEMPTY_H
|
||||||
#define NATIVEEMPTY_H
|
#define NATIVEEMPTY_H
|
||||||
|
|
||||||
#include <QJSValue>
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
class DoricNativeEmpty : public QObject {
|
class DoricNativeEmpty : public QObject {
|
||||||
@ -10,7 +9,7 @@ class DoricNativeEmpty : public QObject {
|
|||||||
public:
|
public:
|
||||||
DoricNativeEmpty(QObject *parent = nullptr) : QObject(parent) {}
|
DoricNativeEmpty(QObject *parent = nullptr) : QObject(parent) {}
|
||||||
|
|
||||||
Q_INVOKABLE QJSValue function();
|
Q_INVOKABLE void function();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // NATIVEEMPTY_H
|
#endif // NATIVEEMPTY_H
|
||||||
|
@ -1,33 +1,66 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QJSValueIterator>
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
#include "../utils/DoricUtils.h"
|
#include "../utils/DoricUtils.h"
|
||||||
#include "DoricNativeJSE.h"
|
#include "DoricNativeJSE.h"
|
||||||
|
|
||||||
DoricNativeJSE::DoricNativeJSE() {
|
DoricNativeJSE::DoricNativeJSE(JSEType type) {
|
||||||
|
mType = type;
|
||||||
|
if (mType == JSEType::V8) {
|
||||||
v8Executor = new V8Executor();
|
v8Executor = new V8Executor();
|
||||||
// nativeExecutor = new NativeExecutor();
|
} else if (mType == JSEType::Native) {
|
||||||
|
nativeExecutor = new NativeExecutor();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString DoricNativeJSE::loadJS(QString script, QString source) {
|
QString DoricNativeJSE::loadJS(QString script, QString source) {
|
||||||
// return nativeExecutor->loadJS(script, source);
|
if (mType == JSEType::V8) {
|
||||||
return v8Executor->loadJS(script, source);
|
return v8Executor->loadJS(script, source);
|
||||||
|
} else if (mType == JSEType::Native) {
|
||||||
|
return nativeExecutor->loadJS(script, source);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoricNativeJSE::injectGlobalJSObject(QString name, QObject *object) {
|
void DoricNativeJSE::injectGlobalJSObject(QString name, QObject *object) {
|
||||||
// nativeExecutor->injectGlobalJSObject(name, object);
|
if (mType == JSEType::V8) {
|
||||||
v8Executor->injectGlobalJSObject(name, object);
|
QJsonObject jsonObject;
|
||||||
|
|
||||||
|
QList<QByteArray> 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,
|
void DoricNativeJSE::injectGlobalJSFunction(QString name, QObject *function,
|
||||||
QString property) {
|
QString property) {
|
||||||
// nativeExecutor->injectGlobalJSFunction(name, function, property);
|
if (mType == JSEType::V8) {
|
||||||
// v8Executor->injectGlobalJSFunction(name, function, property);
|
v8Executor->injectGlobalJSFunction(name, function, property);
|
||||||
|
} else if (mType == JSEType::Native) {
|
||||||
|
nativeExecutor->injectGlobalJSFunction(name, function, property);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QJSValue DoricNativeJSE::invokeObject(QString objectName, QString functionName,
|
QJSValue DoricNativeJSE::invokeObject(QString objectName, QString functionName,
|
||||||
QVariantList arguments) {
|
QVariantList arguments) {
|
||||||
|
if (mType == JSEType::V8) {
|
||||||
return QJSValue::UndefinedValue;
|
return QJSValue::UndefinedValue;
|
||||||
// return nativeExecutor->invokeObject(objectName, functionName, arguments);
|
} else if (mType == JSEType::Native) {
|
||||||
// return v8Executor->invokeObject(objectName, functionName, arguments);
|
return nativeExecutor->invokeObject(objectName, functionName, arguments);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,16 +2,20 @@
|
|||||||
#define NATIVE_JSE_H
|
#define NATIVE_JSE_H
|
||||||
|
|
||||||
#include "DoricInterfaceJSE.h"
|
#include "DoricInterfaceJSE.h"
|
||||||
//#include "native/NativeExecutor.h"
|
#include "native/NativeExecutor.h"
|
||||||
#include "v8/V8Executor.h"
|
#include "v8/V8Executor.h"
|
||||||
|
|
||||||
|
enum class JSEType { V8, Native };
|
||||||
|
|
||||||
class DoricNativeJSE : public DoricInterfaceJSE {
|
class DoricNativeJSE : public DoricInterfaceJSE {
|
||||||
private:
|
private:
|
||||||
|
JSEType mType;
|
||||||
|
|
||||||
V8Executor *v8Executor;
|
V8Executor *v8Executor;
|
||||||
// NativeExecutor *nativeExecutor;
|
NativeExecutor *nativeExecutor;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DoricNativeJSE();
|
DoricNativeJSE(JSEType type);
|
||||||
|
|
||||||
QString loadJS(QString script, QString source) override;
|
QString loadJS(QString script, QString source) override;
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
Q_INVOKABLE QJSValue DoricNativeRequire::function(QString name) {
|
Q_INVOKABLE void DoricNativeRequire::function(QString name) {
|
||||||
qDebug() << "nativeRequire";
|
qDebug() << "nativeRequire: " << name.toUtf8();
|
||||||
return QJSValue::NullValue;
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#ifndef NATIVE_REQUIRE_H
|
#ifndef NATIVE_REQUIRE_H
|
||||||
#define NATIVE_REQUIRE_H
|
#define NATIVE_REQUIRE_H
|
||||||
|
|
||||||
#include <QJSValue>
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
class DoricNativeRequire : public QObject {
|
class DoricNativeRequire : public QObject {
|
||||||
@ -10,7 +9,7 @@ class DoricNativeRequire : public QObject {
|
|||||||
public:
|
public:
|
||||||
DoricNativeRequire(QObject *parent = nullptr) : QObject(parent) {}
|
DoricNativeRequire(QObject *parent = nullptr) : QObject(parent) {}
|
||||||
|
|
||||||
Q_INVOKABLE QJSValue function(QString name);
|
Q_INVOKABLE void function(QString name);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // NATIVE_REQUIRE_H
|
#endif // NATIVE_REQUIRE_H
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
#include "JSValueHelper.h"
|
#include "JSValueHelper.h"
|
||||||
|
|
||||||
#include <QJsonDocument>
|
std::string JS2String(v8::Local<v8::Value> object) {
|
||||||
#include <QJsonObject>
|
|
||||||
|
|
||||||
std::string ToString(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);
|
||||||
v8::Local<v8::Context> context = isolate->GetEnteredOrMicrotaskContext();
|
v8::Local<v8::Context> context = isolate->GetEnteredOrMicrotaskContext();
|
||||||
@ -22,42 +19,39 @@ std::string ToString(v8::Local<v8::Value> object) {
|
|||||||
return std::string(*str2 ? *str2 : "<string conversion failed>");
|
return std::string(*str2 ? *str2 : "<string conversion failed>");
|
||||||
}
|
}
|
||||||
|
|
||||||
v8::Local<v8::Object> global = context->Global();
|
|
||||||
v8::Local<v8::Object> JSON = global->Get(context, NewV8String("JSON"))
|
|
||||||
.ToLocalChecked()
|
|
||||||
->ToObject(context)
|
|
||||||
.ToLocalChecked();
|
|
||||||
v8::Local<v8::Value> argv[] = {object};
|
|
||||||
v8::Local<v8::Function> JSON_stringify = v8::Local<v8::Function>::Cast(
|
|
||||||
JSON->Get(context, NewV8String("stringify")).ToLocalChecked());
|
|
||||||
v8::String::Utf8Value str(
|
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 : "<string conversion failed>");
|
return std::string(*str ? *str : "<string conversion failed>");
|
||||||
}
|
}
|
||||||
|
|
||||||
v8::Local<v8::Value> ObjectToJS(QObject *object) {
|
double JS2Number(v8::Local<v8::Value> value) {
|
||||||
QJsonObject jsonObject;
|
v8::HandleScope handleScope(v8::Isolate::GetCurrent());
|
||||||
|
v8::Local<v8::Context> context =
|
||||||
QList<QByteArray> propertyNames = object->dynamicPropertyNames();
|
v8::Isolate::GetCurrent()->GetCurrentContext();
|
||||||
foreach (QByteArray propertyName, propertyNames) {
|
if (value->IsNumber()) {
|
||||||
QString key = QString::fromStdString(propertyName.toStdString());
|
return value->ToNumber(context).ToLocalChecked()->Value();
|
||||||
object->property(propertyName).toString();
|
|
||||||
if (key == "undefined" || key.isEmpty()) {
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
jsonObject[key] = QJsonValue::fromVariant(object->property(propertyName));
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonDocument doc(jsonObject);
|
bool JS2Bool(v8::Local<v8::Value> value) {
|
||||||
QString strJson(doc.toJson(QJsonDocument::Compact));
|
v8::HandleScope handleScope(v8::Isolate::GetCurrent());
|
||||||
|
if (value->IsBoolean()) {
|
||||||
|
return value->ToBoolean(v8::Isolate::GetCurrent())->Value();
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v8::Local<v8::Value> String2JS(std::string string) {
|
||||||
v8::Isolate *isolate = v8::Isolate::GetCurrent();
|
v8::Isolate *isolate = v8::Isolate::GetCurrent();
|
||||||
v8::EscapableHandleScope handleScope(isolate);
|
v8::EscapableHandleScope handleScope(isolate);
|
||||||
v8::Local<v8::Context> context = isolate->GetEnteredOrMicrotaskContext();
|
v8::Local<v8::Context> context = isolate->GetEnteredOrMicrotaskContext();
|
||||||
v8::Local<v8::String> jsString = NewV8String(strJson.toUtf8().constData());
|
v8::Local<v8::String> jsString = NewV8String(string.c_str());
|
||||||
|
|
||||||
v8::Local<v8::Value> ret = v8::JSON::Parse(context, jsString).ToLocalChecked();
|
v8::Local<v8::Value> ret =
|
||||||
|
v8::JSON::Parse(context, jsString).ToLocalChecked();
|
||||||
|
|
||||||
return handleScope.Escape(ret);
|
return handleScope.Escape(ret);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#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"
|
||||||
@ -11,8 +10,12 @@
|
|||||||
v8::NewStringType::kNormal) \
|
v8::NewStringType::kNormal) \
|
||||||
.ToLocalChecked()
|
.ToLocalChecked()
|
||||||
|
|
||||||
std::string ToString(v8::Local<v8::Value> object);
|
std::string JS2String(v8::Local<v8::Value> object);
|
||||||
|
|
||||||
v8::Local<v8::Value> ObjectToJS(QObject *object);
|
double JS2Number(v8::Local<v8::Value> value);
|
||||||
|
|
||||||
|
bool JS2Bool(v8::Local<v8::Value> value);
|
||||||
|
|
||||||
|
v8::Local<v8::Value> String2JS(std::string string);
|
||||||
|
|
||||||
#endif // JSVALUEHELPER_H
|
#endif // JSVALUEHELPER_H
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
#include "V8Executor.h"
|
#include <QDebug>
|
||||||
|
|
||||||
#include "JSValueHelper.h"
|
#include "JSValueHelper.h"
|
||||||
|
#include "V8Executor.h"
|
||||||
|
|
||||||
V8Executor::V8Executor() : platform(v8::platform::NewDefaultPlatform()) {
|
V8Executor::V8Executor() : platform(v8::platform::NewDefaultPlatform()) {
|
||||||
|
v8::V8::InitializeICUDefaultLocation("");
|
||||||
|
v8::V8::InitializeExternalStartupData("");
|
||||||
v8::V8::InitializePlatform(platform.get());
|
v8::V8::InitializePlatform(platform.get());
|
||||||
v8::V8::Initialize();
|
v8::V8::Initialize();
|
||||||
|
|
||||||
@ -42,20 +46,33 @@ QString V8Executor::loadJS(QString script, QString source) {
|
|||||||
v8::HandleScope scope(isolate);
|
v8::HandleScope scope(isolate);
|
||||||
v8::Local<v8::Value> ret = innerExec(script.toUtf8().constData(),
|
v8::Local<v8::Value> ret = innerExec(script.toUtf8().constData(),
|
||||||
source.toUtf8().constData(), &exception);
|
source.toUtf8().constData(), &exception);
|
||||||
std::string result = ToString(ret);
|
std::string result = JS2String(ret);
|
||||||
|
|
||||||
return QString::fromUtf8(result.c_str());
|
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::Isolate *isolate = m_isolate;
|
||||||
v8::HandleScope handleScope(isolate);
|
v8::HandleScope handleScope(isolate);
|
||||||
|
|
||||||
v8::Local<v8::Value> local = ObjectToJS(target);
|
v8::Local<v8::Value> local = String2JS(target);
|
||||||
|
|
||||||
injectObject(name.toUtf8().constData(), local);
|
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<QObject *, QString> pair(function, property);
|
||||||
|
map->insert(name, pair);
|
||||||
|
}
|
||||||
|
injectFunctions(nullptr, name.toUtf8().constData(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
@ -98,11 +115,169 @@ v8::Local<v8::Value> V8Executor::innerExec(const char *script,
|
|||||||
v8::Local<v8::Object> exc = v8::Local<v8::Object>::Cast(exception);
|
v8::Local<v8::Object> exc = v8::Local<v8::Object>::Cast(exception);
|
||||||
v8::Local<v8::Value> stack =
|
v8::Local<v8::Value> stack =
|
||||||
exc->Get(context, NewV8String("stack")).FromMaybe(exception);
|
exc->Get(context, NewV8String("stack")).FromMaybe(exception);
|
||||||
*exception_str = ToString(stack);
|
*exception_str = JS2String(stack);
|
||||||
} else {
|
} else {
|
||||||
*exception_str = ToString(exception);
|
*exception_str = JS2String(exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return handle_scope.Escape(result);
|
return handle_scope.Escape(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void InjectedFunction(const v8::FunctionCallbackInfo<v8::Value> &args) {
|
||||||
|
v8::Isolate *isolate = args.GetIsolate();
|
||||||
|
v8::HandleScope scope(isolate);
|
||||||
|
v8::Local<v8::Context> context = isolate->GetEnteredOrMicrotaskContext();
|
||||||
|
v8::Local<v8::Object> 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<QObject *, QString> 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<v8::Value> 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<v8::Value> 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<v8::Value> arg0 = args[0];
|
||||||
|
std::string argString0 = JS2String(arg0);
|
||||||
|
|
||||||
|
v8::Local<v8::Value> 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<v8::Value> arg0 = args[0];
|
||||||
|
long argLong = JS2Number(arg0);
|
||||||
|
|
||||||
|
v8::Local<v8::Value> arg1 = args[1];
|
||||||
|
int argInt = JS2Number(arg1);
|
||||||
|
|
||||||
|
v8::Local<v8::Value> 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<v8::Value> arg0 = args[0];
|
||||||
|
std::string argString0 = JS2String(arg0);
|
||||||
|
|
||||||
|
v8::Local<v8::Value> arg1 = args[1];
|
||||||
|
std::string argString1 = JS2String(arg1);
|
||||||
|
|
||||||
|
v8::Local<v8::Value> arg2 = args[2];
|
||||||
|
std::string argString2 = JS2String(arg2);
|
||||||
|
|
||||||
|
v8::Local<v8::Value> arg3 = args[3];
|
||||||
|
std::string argString3 = JS2String(arg3);
|
||||||
|
|
||||||
|
v8::Local<v8::Value> 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<v8::Context> context = isolate->GetEnteredOrMicrotaskContext();
|
||||||
|
v8::Local<v8::Object> object = context->Global();
|
||||||
|
if (objectName) {
|
||||||
|
object = object->Get(context, NewV8String(objectName))
|
||||||
|
.ToLocalChecked()
|
||||||
|
->ToObject(context)
|
||||||
|
.ToLocalChecked();
|
||||||
|
}
|
||||||
|
|
||||||
|
v8::Local<v8::String> name = NewV8String(functionName);
|
||||||
|
v8::Local<v8::Object> data = v8::Object::New(isolate);
|
||||||
|
if (objectName) {
|
||||||
|
v8::Maybe<bool> result =
|
||||||
|
data->Set(context, NewV8String("obj"), NewV8String(objectName));
|
||||||
|
result.ToChecked();
|
||||||
|
} else {
|
||||||
|
v8::Maybe<bool> result =
|
||||||
|
data->Set(context, NewV8String("obj"), NewV8String("global"));
|
||||||
|
result.ToChecked();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
v8::Maybe<bool> result =
|
||||||
|
data->Set(context, NewV8String("func"), NewV8String(functionName));
|
||||||
|
result.ToChecked();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
v8::Maybe<bool> result = data->Set(context, NewV8String("hashKey"),
|
||||||
|
v8::Boolean::New(isolate, hashKey));
|
||||||
|
result.ToChecked();
|
||||||
|
}
|
||||||
|
|
||||||
|
v8::Local<v8::Function> function =
|
||||||
|
v8::Function::New(context, InjectedFunction, data).ToLocalChecked();
|
||||||
|
v8::Maybe<bool> result = object->Set(context, name, function);
|
||||||
|
result.ToChecked();
|
||||||
|
}
|
||||||
|
@ -4,9 +4,13 @@
|
|||||||
#include "libplatform/libplatform.h"
|
#include "libplatform/libplatform.h"
|
||||||
#include "v8/v8.h"
|
#include "v8/v8.h"
|
||||||
|
|
||||||
|
#include <QMap>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
|
static QMap<QString, QPair<QObject *, QString>> *map =
|
||||||
|
new QMap<QString, QPair<QObject *, QString>>();
|
||||||
|
|
||||||
class V8Executor {
|
class V8Executor {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -21,6 +25,9 @@ private:
|
|||||||
v8::Local<v8::Value> innerExec(const char *script, const char *source,
|
v8::Local<v8::Value> innerExec(const char *script, const char *source,
|
||||||
std::string *exception_str);
|
std::string *exception_str);
|
||||||
|
|
||||||
|
void injectFunctions(const char *objectName, const char *functionName,
|
||||||
|
bool hashKey);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
V8Executor();
|
V8Executor();
|
||||||
|
|
||||||
@ -28,7 +35,10 @@ public:
|
|||||||
|
|
||||||
QString loadJS(QString script, QString source);
|
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
|
#endif // V8EXECUTOR_H
|
||||||
|
Reference in New Issue
Block a user