add v8 executor & default executor

This commit is contained in:
王劲鹏 2021-03-31 10:36:45 +08:00 committed by osborn
parent 500df331fc
commit 8bb7fdb66b
11 changed files with 570 additions and 151 deletions

View File

@ -30,6 +30,9 @@ SOURCES += \
engine/DoricNativeLog.cpp \
engine/DoricNativeRequire.cpp \
engine/DoricTimerExtension.cpp \
engine/native/NativeExecutor.cpp \
engine/v8/JSValueHelper.cpp \
engine/v8/V8Executor.cpp \
main.cpp \
plugin/DoricShaderPlugin.cpp \
shader/DoricGroupNode.cpp \
@ -92,6 +95,9 @@ HEADERS += \
engine/DoricNativeLog.h \
engine/DoricNativeRequire.h \
engine/DoricTimerExtension.h \
engine/native/NativeExecutor.h \
engine/v8/JSValueHelper.h \
engine/v8/V8Executor.h \
plugin/DoricNativePlugin.h \
plugin/DoricShaderPlugin.h \
shader/DoricGroupNode.h \

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.14.1, 2021-03-17T18:58:53. -->
<!-- Written by QtCreator 4.14.1, 2021-03-31T10:31:13. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
@ -86,6 +86,228 @@
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="DeviceType">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 6.0.2 MSVC2019 64bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 6.0.2 MSVC2019 64bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt6.602.win64_msvc2019_64_kit</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="int" key="EnableQmlDebugging">0</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:\Users\maverick\Workspace\Doric\doric-Qt\build-doric-Desktop_Qt_6_0_2_MSVC2019_64bit-Debug</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">C:/Users/maverick/Workspace/Doric/doric-Qt/build-doric-Desktop_Qt_6_0_2_MSVC2019_64bit-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
<value type="int" key="RunSystemFunction">0</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:\Users\maverick\Workspace\Doric\doric-Qt\build-doric-Desktop_Qt_6_0_2_MSVC2019_64bit-Release</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">C:/Users/maverick/Workspace/Doric/doric-Qt/build-doric-Desktop_Qt_6_0_2_MSVC2019_64bit-Release</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="int" key="QtQuickCompiler">0</value>
<value type="int" key="RunSystemFunction">0</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
<value type="int" key="EnableQmlDebugging">0</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:\Users\maverick\Workspace\Doric\doric-Qt\build-doric-Desktop_Qt_6_0_2_MSVC2019_64bit-Profile</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">C:/Users/maverick/Workspace/Doric/doric-Qt/build-doric-Desktop_Qt_6_0_2_MSVC2019_64bit-Profile</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="int" key="QtQuickCompiler">0</value>
<value type="int" key="RunSystemFunction">0</value>
<value type="int" key="SeparateDebugInfo">0</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">3</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="QString" key="Analyzer.Perf.CallgraphMode">dwarf</value>
<valuelist type="QVariantList" key="Analyzer.Perf.Events">
<value type="QString">cpu-cycles</value>
</valuelist>
<valuelist type="QVariantList" key="Analyzer.Perf.ExtraArguments"/>
<value type="int" key="Analyzer.Perf.Frequency">250</value>
<valuelist type="QVariantList" key="Analyzer.Perf.RecordArguments">
<value type="QString">-e</value>
<value type="QString">cpu-cycles</value>
<value type="QString">--call-graph</value>
<value type="QString">dwarf,4096</value>
<value type="QString">-F</value>
<value type="QString">250</value>
</valuelist>
<value type="QString" key="Analyzer.Perf.SampleMode">-F</value>
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="int" key="Analyzer.Perf.StackSize">4096</value>
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
<value type="QString" key="Analyzer.Valgrind.KCachegrindExecutable">kcachegrind</value>
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
<value type="int">0</value>
<value type="int">1</value>
<value type="int">2</value>
<value type="int">3</value>
<value type="int">4</value>
<value type="int">5</value>
<value type="int">6</value>
<value type="int">7</value>
<value type="int">8</value>
<value type="int">9</value>
<value type="int">10</value>
<value type="int">11</value>
<value type="int">12</value>
<value type="int">13</value>
<value type="int">14</value>
</valuelist>
<valuelist type="QVariantList" key="CustomOutputParsers"/>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:C:/Users/maverick/Workspace/Doric/doric-Qt/doric/doric.pro</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">C:/Users/maverick/Workspace/Doric/doric-Qt/doric/doric.pro</value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</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>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.Target.1</variable>
<valuemap type="QVariantMap">
<value type="QString" key="DeviceType">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 6.0.1 MinGW 64-bit</value>
@ -301,14 +523,13 @@
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</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_1_MinGW_64_bit-Debug</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="int">1</value>
<value type="int">2</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>

View File

@ -17,8 +17,12 @@
DoricJSEngine::DoricJSEngine(QObject *parent) : QObject(parent) {
mJSThreadPool.setMaxThreadCount(1);
mJSThreadPool.setStackSize(3000000000);
QtConcurrent::run(&mJSThreadPool, [this] { mJSE = new DoricNativeJSE(); });
QtConcurrent::run(&mJSThreadPool, [this] {
qDebug() << QThread::currentThread()->stackSize();
mJSE = new DoricNativeJSE();
});
QtConcurrent::run(&mJSThreadPool, [this] {
// inject env
QScreen *screen = QGuiApplication::primaryScreen();

View File

@ -5,159 +5,29 @@
#include "DoricNativeJSE.h"
DoricNativeJSE::DoricNativeJSE() {
mJSEngine.installExtensions(QJSEngine::AllExtensions);
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
v8::V8::Initialize();
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator =
v8::ArrayBuffer::Allocator::NewDefaultAllocator();
v8::Isolate *isolate = v8::Isolate::New(create_params);
{
v8::Isolate::Scope isolate_scope(isolate);
// Create a stack-allocated handle scope.
v8::HandleScope handle_scope(isolate);
// Create a new context.
v8::Local<v8::Context> context = v8::Context::New(isolate);
// Enter the context for compiling and running the hello world script.
v8::Context::Scope context_scope(context);
{
// Create a string containing the JavaScript source code.
v8::Local<v8::String> source =
v8::String::NewFromUtf8Literal(isolate, "'Hello' + ', World!'");
// Compile the source code.
v8::Local<v8::Script> script =
v8::Script::Compile(context, source).ToLocalChecked();
// Run the script to get the result.
v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();
// Convert the result to an UTF8 string and print it.
v8::String::Utf8Value utf8(isolate, result);
printf("%s\n", *utf8);
}
{
// Use the JavaScript API to generate a WebAssembly module.
//
// |bytes| contains the binary format for the following module:
//
// (func (export "add") (param i32 i32) (result i32)
// get_local 0
// get_local 1
// i32.add)
//
const char csource[] = R"(
let bytes = new Uint8Array([
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01,
0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07,
0x07, 0x01, 0x03, 0x61, 0x64, 0x64, 0x00, 0x00, 0x0a, 0x09, 0x01,
0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b
]);
let module = new WebAssembly.Module(bytes);
let instance = new WebAssembly.Instance(module);
instance.exports.add(3, 4);
)";
// Create a string containing the JavaScript source code.
v8::Local<v8::String> source =
v8::String::NewFromUtf8Literal(isolate, csource);
// Compile the source code.
v8::Local<v8::Script> script =
v8::Script::Compile(context, source).ToLocalChecked();
// Run the script to get the result.
v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();
// Convert the result to a uint32 and print it.
uint32_t number = result->Uint32Value(context).ToChecked();
printf("3 + 4 = %u\n", number);
}
}
// Dispose the isolate and tear down V8.
isolate->Dispose();
v8::V8::Dispose();
v8::V8::ShutdownPlatform();
delete create_params.array_buffer_allocator;
v8Executor = new V8Executor();
// nativeExecutor = new NativeExecutor();
}
QString DoricNativeJSE::loadJS(QString script, QString source) {
return mJSEngine.evaluate(script, source).toString();
// return nativeExecutor->loadJS(script, source);
return v8Executor->loadJS(script, source);
}
void DoricNativeJSE::injectGlobalJSObject(QString name, QObject *object) {
QJSValue jsObject = mJSEngine.newQObject(object);
QList<QByteArray> propertyNames = object->dynamicPropertyNames();
foreach (QByteArray propertyName, propertyNames) {
QString key = QString::fromStdString(propertyName.toStdString());
if (key == "undefined") {
} else {
jsObject.setProperty(
key, mJSEngine.toScriptValue(object->property(propertyName)));
}
}
mJSEngine.globalObject().setProperty(name, jsObject);
// nativeExecutor->injectGlobalJSObject(name, object);
v8Executor->injectGlobalJSObject(name, object);
}
void DoricNativeJSE::injectGlobalJSFunction(QString name, QObject *function,
QString property) {
QJSValue functionObject = mJSEngine.newQObject(function);
mJSEngine.globalObject().setProperty(name, functionObject.property(property));
// nativeExecutor->injectGlobalJSFunction(name, function, property);
// v8Executor->injectGlobalJSFunction(name, function, property);
}
QJSValue DoricNativeJSE::invokeObject(QString objectName, QString functionName,
QVariantList arguments) {
QJSValue object = mJSEngine.evaluate(objectName);
QJSValue function = object.property(functionName);
QJSValueList args;
foreach (QVariant variant, arguments) {
if (variant.type() == QVariant::String) {
args.push_back(QJSValue(variant.toString()));
} else if (variant.type() == QVariant::Map) {
QJSValue arg = mJSEngine.newObject();
QMap<QString, QVariant> map = variant.toMap();
foreach (QString key, map.keys()) {
QVariant value = map.value(key);
if (value.type() == QVariant::String) {
arg.setProperty(key, value.toString());
} else if (value.type() == QVariant::Int) {
arg.setProperty(key, value.toInt());
}
}
args.push_back(arg);
} else if (variant.type() == QVariant::StringList) {
QStringList array = variant.toStringList();
QJSValue arg = mJSEngine.newArray(array.size());
for (int i = 0; i != array.size(); i++) {
arg.setProperty(i, array.at(i));
}
args.push_back(arg);
}
}
QJSValue result = function.call(args);
if (result.isError()) {
qCritical() << "++++++++++++++++++++++++++++++++++++++++++++++++";
qCritical() << result.toString();
QStringList stacktraces = result.property("stack").toString().split("\n");
foreach (QString stacktrace, stacktraces) { qDebug() << stacktrace; }
qCritical() << "------------------------------------------------";
}
return result;
return QJSValue::UndefinedValue;
// return nativeExecutor->invokeObject(objectName, functionName, arguments);
// return v8Executor->invokeObject(objectName, functionName, arguments);
}

View File

@ -2,15 +2,13 @@
#define NATIVE_JSE_H
#include "DoricInterfaceJSE.h"
#include <QJSEngine>
#include <excpt.h>
#include "libplatform/libplatform.h"
#include "v8.h"
#include "native/NativeExecutor.h"
#include "v8/V8Executor.h"
class DoricNativeJSE : public DoricInterfaceJSE {
private:
QJSEngine mJSEngine;
V8Executor *v8Executor;
NativeExecutor *nativeExecutor;
public:
DoricNativeJSE();

View File

@ -0,0 +1,80 @@
#include "NativeExecutor.h"
NativeExecutor::NativeExecutor() {
mJSEngine = new QJSEngine();
mJSEngine->installExtensions(QJSEngine::AllExtensions);
}
NativeExecutor::~NativeExecutor() { delete mJSEngine; }
QString NativeExecutor::loadJS(QString script, QString source) {
return mJSEngine->evaluate(script, source).toString();
}
void NativeExecutor::injectGlobalJSObject(QString name, QObject *object) {
QJSValue jsObject = mJSEngine->newQObject(object);
QList<QByteArray> propertyNames = object->dynamicPropertyNames();
foreach (QByteArray propertyName, propertyNames) {
QString key = QString::fromStdString(propertyName.toStdString());
if (key == "undefined") {
} else {
jsObject.setProperty(
key, mJSEngine->toScriptValue(object->property(propertyName)));
}
}
mJSEngine->globalObject().setProperty(name, jsObject);
}
void NativeExecutor::injectGlobalJSFunction(QString name, QObject *function,
QString property) {
QJSValue functionObject = mJSEngine->newQObject(function);
mJSEngine->globalObject().setProperty(name,
functionObject.property(property));
}
QJSValue NativeExecutor::invokeObject(QString objectName, QString functionName,
QVariantList arguments) {
QJSValue object = mJSEngine->evaluate(objectName);
QJSValue function = object.property(functionName);
QJSValueList args;
foreach (QVariant variant, arguments) {
if (variant.type() == QVariant::String) {
args.push_back(QJSValue(variant.toString()));
} else if (variant.type() == QVariant::Map) {
QJSValue arg = mJSEngine->newObject();
QMap<QString, QVariant> map = variant.toMap();
foreach (QString key, map.keys()) {
QVariant value = map.value(key);
if (value.type() == QVariant::String) {
arg.setProperty(key, value.toString());
} else if (value.type() == QVariant::Int) {
arg.setProperty(key, value.toInt());
}
}
args.push_back(arg);
} else if (variant.type() == QVariant::StringList) {
QStringList array = variant.toStringList();
QJSValue arg = mJSEngine->newArray(array.size());
for (int i = 0; i != array.size(); i++) {
arg.setProperty(i, array.at(i));
}
args.push_back(arg);
}
}
QJSValue result = function.call(args);
if (result.isError()) {
qCritical() << "++++++++++++++++++++++++++++++++++++++++++++++++";
qCritical() << result.toString();
QStringList stacktraces = result.property("stack").toString().split("\n");
foreach (QString stacktrace, stacktraces) { qDebug() << stacktrace; }
qCritical() << "------------------------------------------------";
}
return result;
}

View File

@ -0,0 +1,27 @@
#ifndef NATIVEEXECUTOR_H
#define NATIVEEXECUTOR_H
#include <QJSEngine>
class NativeExecutor {
private:
QJSEngine *mJSEngine;
public:
NativeExecutor();
~NativeExecutor();
QString loadJS(QString script, QString source);
void injectGlobalJSObject(QString name, QObject *object);
void injectGlobalJSFunction(QString name, QObject *function,
QString property);
QJSValue invokeObject(QString objectName, QString functionName,
QVariantList arguments);
};
#endif // NATIVEEXECUTOR_H

View File

@ -0,0 +1,63 @@
#include "JSValueHelper.h"
#include <QJsonDocument>
#include <QJsonObject>
std::string ToString(v8::Local<v8::Value> object) {
v8::Isolate *isolate = v8::Isolate::GetCurrent();
v8::HandleScope handleScope(isolate);
v8::Local<v8::Context> context = isolate->GetEnteredOrMicrotaskContext();
if (object->IsString() || object->IsRegExp() || object->IsFunction()) {
v8::String::Utf8Value utf8(isolate, object);
return std::string(*utf8);
}
if (object->IsObject()) {
v8::MaybeLocal<v8::String> str = v8::JSON::Stringify(
context, object->ToObject(context).ToLocalChecked());
if (str.IsEmpty()) {
return "<string conversion failed>";
}
v8::Local<v8::String> s = str.ToLocalChecked();
v8::String::Utf8Value str2(isolate, s);
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(
isolate, JSON_stringify->Call(context, JSON, 1, argv).ToLocalChecked());
return std::string(*str ? *str : "<string conversion failed>");
}
v8::Local<v8::Value> ObjectToJS(QObject *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));
v8::Isolate *isolate = v8::Isolate::GetCurrent();
v8::EscapableHandleScope handleScope(isolate);
v8::Local<v8::Context> context = isolate->GetEnteredOrMicrotaskContext();
v8::Local<v8::String> jsString = NewV8String(strJson.toUtf8().constData());
v8::Local<v8::Value> ret = v8::JSON::Parse(context, jsString).ToLocalChecked();
return handleScope.Escape(ret);
}

View File

@ -0,0 +1,18 @@
#ifndef JSVALUEHELPER_H
#define JSVALUEHELPER_H
#include <QVariant>
#include <string>
#include "v8/v8.h"
#define NewV8String(name) \
v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), name, \
v8::NewStringType::kNormal) \
.ToLocalChecked()
std::string ToString(v8::Local<v8::Value> object);
v8::Local<v8::Value> ObjectToJS(QObject *object);
#endif // JSVALUEHELPER_H

View File

@ -0,0 +1,101 @@
#include "V8Executor.h"
#include "JSValueHelper.h"
#include <QThread>
V8Executor::V8Executor() {
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
v8::V8::Initialize();
create_params.array_buffer_allocator =
v8::ArrayBuffer::Allocator::NewDefaultAllocator();
m_isolate = v8::Isolate::New(create_params);
m_isolate_scope = new v8::Isolate::Scope(m_isolate);
v8::Isolate *isolate = v8::Isolate::GetCurrent();
v8::HandleScope scope(isolate);
v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate, nullptr, global);
context->Enter();
m_global_context = new v8::Global<v8::Context>(isolate, context);
}
V8Executor::~V8Executor() {
{
v8::HandleScope scope(m_isolate);
v8::Local<v8::Context> context = m_global_context->Get(m_isolate);
context->Exit();
}
m_global_context->Reset();
delete m_global_context;
delete m_isolate_scope;
m_isolate->Dispose();
v8::V8::Dispose();
v8::V8::ShutdownPlatform();
delete create_params.array_buffer_allocator;
}
QString V8Executor::loadJS(QString script, QString source) {
std::string exception;
v8::HandleScope scope(m_isolate);
v8::Local<v8::Value> ret = innerExec(script.toUtf8().constData(),
source.toUtf8().constData(), &exception);
std::string result = ToString(ret);
return QString::fromUtf8(result.c_str());
}
void V8Executor::injectGlobalJSObject(QString name, QObject *target) {
v8::HandleScope handleScope(v8::Isolate::GetCurrent());
v8::Local<v8::Value> local = ObjectToJS(target);
v8::Isolate *isolate = m_isolate;
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = isolate->GetEnteredOrMicrotaskContext();
v8::Local<v8::Object> object = context->Global();
v8::Maybe<bool> result =
object->Set(context, NewV8String(name.toUtf8().constData()), local);
result.ToChecked();
}
v8::Local<v8::Value> V8Executor::innerExec(const char *script,
const char *source,
std::string *exception_str) {
v8::Isolate *isolate = m_isolate;
v8::EscapableHandleScope handle_scope(isolate);
v8::Local<v8::Value> result = Undefined(isolate);
v8::Local<v8::Context> context = isolate->GetEnteredOrMicrotaskContext();
v8::Context::Scope context_scope(context);
v8::ScriptOrigin origin(NewV8String(source));
if (script) {
v8::Local<v8::String> jsSource = NewV8String(script);
v8::TryCatch try_catch(isolate);
try_catch.SetVerbose(true);
v8::MaybeLocal<v8::Script> maybeScript =
v8::Script::Compile(context, jsSource, &origin);
if (!maybeScript.IsEmpty()) {
v8::Local<v8::Script> js_script = maybeScript.ToLocalChecked();
v8::MaybeLocal<v8::Value> res = js_script->Run(context);
if (!res.IsEmpty()) {
result = res.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 = ToString(stack);
} else {
*exception_str = ToString(exception);
}
}
}
return handle_scope.Escape(result);
}

View File

@ -0,0 +1,31 @@
#ifndef V8EXECUTOR_H
#define V8EXECUTOR_H
#include "libplatform/libplatform.h"
#include "v8/v8.h"
#include <QObject>
#include <QString>
class V8Executor {
private:
v8::Isolate::CreateParams create_params;
v8::Isolate *m_isolate;
v8::Isolate::Scope *m_isolate_scope;
v8::Global<v8::Context> *m_global_context;
v8::Local<v8::Value> innerExec(const char *script, const char *source,
std::string *exception_str);
public:
V8Executor();
~V8Executor();
QString loadJS(QString script, QString source);
void injectGlobalJSObject(QString name, QObject *object);
};
#endif // V8EXECUTOR_H