diff --git a/unity/native_src/CMakeLists.txt b/unity/native_src/CMakeLists.txt index 3df863d4a2..80ef3acdfd 100644 --- a/unity/native_src/CMakeLists.txt +++ b/unity/native_src/CMakeLists.txt @@ -28,7 +28,7 @@ if ( NOT DEFINED JS_ENGINE ) set(JS_ENGINE v8) endif() -set(BACKEND_ROOT ${PROJECT_SOURCE_DIR}/.backends/${JS_ENGINE}) +set(BACKEND_ROOT ${PROJECT_SOURCE_DIR}/../native_src/.backends/${JS_ENGINE}) set(ThirdParty ${PROJECT_SOURCE_DIR}/../../unreal/Puerts/ThirdParty) @@ -46,24 +46,17 @@ include_directories( ) set ( PUERTS_INC + Inc/Common.h Inc/Log.h Inc/BackendEnv.h Inc/JSEngine.h Inc/V8Utils.h Inc/JSFunction.h + Inc/IPuertsPlugin.h ${PROJECT_SOURCE_DIR}/../../unreal/Puerts/Source/JsEnv/Private/V8InspectorImpl.h ${PROJECT_SOURCE_DIR}/../../unreal/Puerts/Source/JsEnv/Private/PromiseRejectCallback.hpp ) -set ( PUERTS_SRC - Src/Puerts.cpp - Src/Log.cpp - Src/BackendEnv.cpp - Src/JSEngine.cpp - Src/JSFunction.cpp - ${PROJECT_SOURCE_DIR}/../../unreal/Puerts/Source/JsEnv/Private/V8InspectorImpl.cpp -) - if(DEFINED PUERTS_EXTRA_SRC) list(APPEND PUERTS_SRC ${PUERTS_EXTRA_SRC}) endif() @@ -92,6 +85,21 @@ endmacro(source_group_by_dir) source_group_by_dir(${CMAKE_CURRENT_SOURCE_DIR} PUERTS_INC) source_group_by_dir(${CMAKE_CURRENT_SOURCE_DIR} PUERTS_SRC) +if("${JS_ENGINE}" STREQUAL "mult") + message("mult backend>>>>>>>>>>>>>>>>>>>>>>>>") + set ( PUERTS_SRC + Src/PuertsMultBackend.cpp + ) +else () + set ( PUERTS_SRC + Src/Puerts.cpp + Src/Log.cpp + Src/BackendEnv.cpp + Src/JSEngine.cpp + Src/JSFunction.cpp + ${PROJECT_SOURCE_DIR}/../../unreal/Puerts/Source/JsEnv/Private/V8InspectorImpl.cpp + ) +endif() if ( APPLE ) if ( IOS ) @@ -122,14 +130,54 @@ else () ) endif () -# target_compile_definitions (puerts PRIVATE THREAD_SAFE) +set(PUERTS_COMPILE_DEFINITIONS) + +if("${JS_ENGINE}" STREQUAL "mult") + # -------------------begin v8 backend------------------------- + add_library(v8backend STATIC + Src/Log.cpp + Src/BackendEnv.cpp + Src/JSEngine.cpp + Src/JSFunction.cpp + ${PROJECT_SOURCE_DIR}/../../unreal/Puerts/Source/JsEnv/Private/V8InspectorImpl.cpp + Src/PluginImpl.cpp + ) + target_include_directories (v8backend PRIVATE "${BACKEND_ROOT}/Inc/v8") + target_compile_definitions (v8backend PRIVATE PUERTS_NAMESPACE=puerts_v8) + target_compile_definitions (v8backend PRIVATE MULT_BACKENDS) + target_compile_definitions (v8backend PRIVATE V8_BACKEND) + # -------------------end v8 backend------------------------- + + # -------------------begin qjs backend------------------------- + add_library(qjsbackend STATIC + Src/Log.cpp + Src/BackendEnv.cpp + Src/JSEngine.cpp + Src/JSFunction.cpp + ${PROJECT_SOURCE_DIR}/../../unreal/Puerts/Source/JsEnv/Private/V8InspectorImpl.cpp + Src/PluginImpl.cpp + ) + target_include_directories (qjsbackend PRIVATE "${BACKEND_ROOT}/Inc/quickjs") + target_compile_definitions (qjsbackend PRIVATE PUERTS_NAMESPACE=puerts_qjs) + target_compile_definitions (qjsbackend PRIVATE MULT_BACKENDS) + target_compile_definitions (qjsbackend PRIVATE QJS_BACKEND) + target_compile_definitions (qjsbackend PRIVATE WITH_QUICKJS) + target_compile_definitions (qjsbackend PRIVATE WITHOUT_INSPECTOR) + target_compile_definitions (qjsbackend PRIVATE CUSTOMV8NAMESPACE=v8_qjs) + # -------------------end qjs backend------------------------- + + target_include_directories(puerts PRIVATE "${BACKEND_ROOT}/Inc/v8") #只需要用到V8_EXPORT + target_link_libraries(puerts v8backend qjsbackend ) +endif () + +# list(APPEND PUERTS_COMPILE_DEFINITIONS THREAD_SAFE) if ( WIN32 AND NOT CYGWIN ) - target_compile_definitions (puerts PRIVATE BUILDING_V8_SHARED) + list(APPEND PUERTS_COMPILE_DEFINITIONS BUILDING_V8_SHARED) endif () if ( NOT CMAKE_BUILD_TYPE MATCHES "Release" ) - target_compile_definitions (puerts PRIVATE PUERTS_DEBUG) + list(APPEND PUERTS_COMPILE_DEFINITIONS PUERTS_DEBUG) endif () if ( MSYS OR WIN32 ) @@ -142,7 +190,7 @@ if ( MSYS OR WIN32 ) endif () # definition - target_compile_definitions (puerts PRIVATE PLATFORM_WINDOWS) + list(APPEND PUERTS_COMPILE_DEFINITIONS PLATFORM_WINDOWS) elseif ( ANDROID ) @@ -154,7 +202,7 @@ elseif ( ANDROID ) set(BACKEND_LIB_NAMES "-Wl,--whole-archive$${BACKEND_LIB_NAMES}$-Wl,--no-whole-archive") if ( ANDROID_ABI STREQUAL "armeabi-v7a") # definition - target_compile_definitions (puerts PRIVATE PLATFORM_ANDROID_ARM) + list(APPEND PUERTS_COMPILE_DEFINITIONS PLATFORM_ANDROID_ARM) elseif ( ANDROID_ABI STREQUAL "arm64-v8a") # link @@ -163,10 +211,10 @@ elseif ( ANDROID ) ) # definition - target_compile_definitions (puerts PRIVATE PLATFORM_ANDROID_ARM64) + list(APPEND PUERTS_COMPILE_DEFINITIONS PLATFORM_ANDROID_ARM64) else () - target_compile_definitions (puerts PRIVATE PLATFORM_ANDROID_x64) + list(APPEND PUERTS_COMPILE_DEFINITIONS PLATFORM_ANDROID_x64) endif () #set_target_properties( puerts PROPERTIES LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/android_version.script) @@ -183,19 +231,19 @@ elseif ( APPLE ) if ( IOS ) #definition if(PLATFORM STREQUAL "SIMULATOR64") - target_compile_definitions (puerts PRIVATE PLATFORM_IOS_SIMULATOR) + list(APPEND PUERTS_COMPILE_DEFINITIONS PLATFORM_IOS_SIMULATOR) message(STATUS "SIMULATOR64 BUILD...") else () - target_compile_definitions (puerts PRIVATE PLATFORM_IOS) + list(APPEND PUERTS_COMPILE_DEFINITIONS PLATFORM_IOS) endif () else () #definition if ( DEFINED FOR_SILICON ) - target_compile_definitions (puerts PRIVATE PLATFORM_MAC_ARM64) + list(APPEND PUERTS_COMPILE_DEFINITIONS PLATFORM_MAC_ARM64) endif() - target_compile_definitions (puerts PRIVATE PLATFORM_MAC) + list(APPEND PUERTS_COMPILE_DEFINITIONS PLATFORM_MAC) endif () elseif (UNIX) @@ -203,7 +251,7 @@ elseif (UNIX) target_link_libraries(puerts pthread) # definition - target_compile_definitions (puerts PRIVATE PLATFORM_LINUX) + list(APPEND PUERTS_COMPILE_DEFINITIONS PLATFORM_LINUX) set(CMAKE_CXX_COMPILER "clang++") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -lc++abi") @@ -213,7 +261,22 @@ endif () target_link_libraries(puerts ${BACKEND_LIB_NAMES} ) -target_compile_definitions (puerts PRIVATE ${BACKEND_DEFINITIONS}) +list(APPEND PUERTS_COMPILE_DEFINITIONS ${BACKEND_DEFINITIONS}) + +target_compile_definitions (puerts PUBLIC ${PUERTS_COMPILE_DEFINITIONS}) +if("${JS_ENGINE}" STREQUAL "mult") + target_compile_definitions (v8backend PUBLIC ${PUERTS_COMPILE_DEFINITIONS}) + if ( WIN32 AND NOT CYGWIN AND NOT ( CMAKE_SYSTEM_NAME STREQUAL "WindowsStore" ) AND NOT ANDROID AND NOT MSYS) + set_property(TARGET v8backend PROPERTY + MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + endif () + + target_compile_definitions (qjsbackend PUBLIC ${PUERTS_COMPILE_DEFINITIONS}) + if ( WIN32 AND NOT CYGWIN AND NOT ( CMAKE_SYSTEM_NAME STREQUAL "WindowsStore" ) AND NOT ANDROID AND NOT MSYS) + set_property(TARGET qjsbackend PROPERTY + MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + endif () +endif () if ( WIN32 AND NOT CYGWIN AND NOT ( CMAKE_SYSTEM_NAME STREQUAL "WindowsStore" ) AND NOT ANDROID AND NOT MSYS) set_property(TARGET puerts PROPERTY diff --git a/unity/native_src/Inc/Common.h b/unity/native_src/Inc/Common.h index d8ff59c5a1..a608ec6cd3 100644 --- a/unity/native_src/Inc/Common.h +++ b/unity/native_src/Inc/Common.h @@ -16,6 +16,10 @@ #define PUERTS_NAMESPACE puerts #endif +#if defined(QJS_BACKEND) +namespace v8 = v8_qjs; +#endif + namespace puerts { diff --git a/unity/native_src/Inc/IPuertsPlugin.h b/unity/native_src/Inc/IPuertsPlugin.h new file mode 100644 index 0000000000..e055092db7 --- /dev/null +++ b/unity/native_src/Inc/IPuertsPlugin.h @@ -0,0 +1,212 @@ +/* +* Tencent is pleased to support the open source community by making Puerts available. +* Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. +* Puerts is licensed under the BSD 3-Clause License, except for the third-party components listed in the file 'LICENSE' which may be subject to their corresponding license terms. +* This file is subject to the terms and conditions defined in file 'LICENSE', which is part of this source code package. +*/ + +#pragma once + +#include +#include "Common.h" + +namespace puerts +{ + +typedef void (*FuncPtr)(void); + +class IPuertsPlugin +{ +public: + virtual int GetType() = 0; + + virtual void SetGlobalFunction(const char *Name, FuncPtr Callback, int64_t Data) = 0; + + virtual void SetModuleResolver(FuncPtr Resolver, int32_t Idx) = 0; + + virtual void* Eval(const char *Code, const char* Path) = 0; + + virtual bool ClearModuleCache(const char* Path) = 0; + + virtual int RegisterClass(int BaseTypeId, const char *FullName, FuncPtr Constructor, FuncPtr Destructor, int64_t Data, int Size) = 0; + + virtual int RegisterFunction(int ClassID, const char *Name, int IsStatic, FuncPtr Callback, int64_t Data) = 0; + + virtual int RegisterProperty(int ClassID, const char *Name, int IsStatic, FuncPtr Getter, int64_t GetterData, FuncPtr Setter, int64_t SetterData, int DontDelete) = 0; + + virtual const char* GetLastExceptionInfo(int *Length) = 0; + + virtual void LowMemoryNotification() = 0; + + virtual bool IdleNotificationDeadline(double DeadlineInSeconds) = 0; + + virtual void RequestMinorGarbageCollectionForTesting() = 0; + + virtual void RequestFullGarbageCollectionForTesting() = 0; + + + virtual void SetGeneralDestructor(FuncPtr GeneralDestructor) = 0; + + virtual void* GetJSObjectValueGetter() = 0; + + virtual void* GetModuleExecutor() = 0; + + virtual void* GetResultInfo() = 0; + + //-------------------------- begin js call cs -------------------------- + virtual void* GetArgumentValue(const void* Info, int Index) = 0; + + virtual JsValueType GetJsValueType(const void* Value, int IsOut) = 0; + + virtual JsValueType GetArgumentType(const void* Info, int Index, int IsOut) = 0; + + virtual double GetNumberFromValue(void* Value, int IsOut) = 0; + + virtual void SetNumberToOutValue(void* Value, double Number) = 0; + + virtual double GetDateFromValue(void* Value, int IsOut) = 0; + + virtual void SetDateToOutValue(void* Value, double Date) = 0; + + virtual const char *GetStringFromValue(void* Value, int *Length, int IsOut) = 0; + + virtual void SetStringToOutValue(void* Value, const char *Str) = 0; + + virtual int GetBooleanFromValue(void* Value, int IsOut) = 0; + + virtual void SetBooleanToOutValue(void* Value, int B) = 0; + + virtual int ValueIsBigInt(void* Value, int IsOut) = 0; + + virtual int64_t GetBigIntFromValue(void* Value, int IsOut) = 0; + + virtual void SetBigIntToOutValue(void* Value, int64_t BigInt) = 0; + + virtual const char* GetArrayBufferFromValue(void* Value, int *Length, int IsOut) = 0; + + virtual void SetArrayBufferToOutValue(void* Value, unsigned char *Bytes, int Length) = 0; + + virtual void *GetObjectFromValue(void* Value, int IsOut) = 0; + + virtual int GetTypeIdFromValue(void* Value, int IsOut) = 0; + + virtual void SetObjectToOutValue(void* Value, int ClassID, void* Ptr) = 0; + + virtual void SetNullToOutValue(void* Value) = 0; + + virtual void* GetFunctionFromValue(void* Value, int IsOut) = 0; + + virtual void* GetJSObjectFromValue(void* Value, int IsOut) = 0; + + virtual void ReleaseJSFunction(void* Function) = 0; + + virtual void ReleaseJSObject(void* Object) = 0; + + virtual void ThrowException(const char * Message) = 0; + + virtual void ReturnClass(const void* Info, int ClassID) = 0; + + virtual void ReturnObject(const void* Info, int ClassID, void* Ptr) = 0; + + virtual void ReturnNumber(const void* Info, double Number) = 0; + + virtual void ReturnString(const void* Info, const char* String) = 0; + + virtual void ReturnBigInt(const void* Info, int64_t BigInt) = 0; + + virtual void ReturnArrayBuffer(const void* Info, unsigned char *Bytes, int Length) = 0; + + virtual void ReturnBoolean(const void* Info, int Bool) = 0; + + virtual void ReturnDate(const void* Info, double Date) = 0; + + virtual void ReturnNull(const void* Info) = 0; + + virtual void ReturnFunction(const void* Info, void* Function) = 0; + + virtual void ReturnCSharpFunctionCallback(const void* Info, FuncPtr Callback, int64_t Data) = 0; + + virtual void ReturnJSObject(const void* Info, void* Object) = 0; + //-------------------------- end js call cs -------------------------- + + //-------------------------- bengin cs call js -------------------------- + + virtual void PushNullForJSFunction(void* Function) = 0; + + virtual void PushDateForJSFunction(void* Function, double DateValue) = 0; + + virtual void PushBooleanForJSFunction(void* Function, int B) = 0; + + virtual void PushBigIntForJSFunction(void* Function, int64_t V) = 0; + + virtual void PushArrayBufferForJSFunction(void* Function, unsigned char * Bytes, int Length) = 0; + + virtual void PushStringForJSFunction(void* Function, const char* S) = 0; + + virtual void PushNumberForJSFunction(void* Function, double D) = 0; + + virtual void PushObjectForJSFunction(void* Function, int ClassID, void* Ptr) = 0; + + virtual void PushJSFunctionForJSFunction(void* Function, void* V) = 0; + + virtual void PushJSObjectForJSFunction(void* Function, void* V) = 0; + + virtual void* InvokeJSFunction(void* Function, int HasResult) = 0; + + virtual JsValueType GetResultType(void* ResultInfo) = 0; + + virtual double GetNumberFromResult(void* ResultInfo) = 0; + + virtual double GetDateFromResult(void* ResultInfo) = 0; + + virtual const char *GetStringFromResult(void* ResultInfo, int *Length) = 0; + + virtual int GetBooleanFromResult(void* ResultInfo) = 0; + + virtual int ResultIsBigInt(void* ResultInfo) = 0; + + virtual int64_t GetBigIntFromResult(void* ResultInfo) = 0; + + virtual const char *GetArrayBufferFromResult(void* ResultInfo, int *Length) = 0; + + virtual void *GetObjectFromResult(void* ResultInfo) = 0; + + virtual int GetTypeIdFromResult(void* ResultInfo) = 0; + + virtual void* GetJSObjectFromResult(void* ResultInfo) = 0; + + virtual void* GetFunctionFromResult(void* ResultInfo) = 0; + + virtual void ResetResult(void* ResultInfo) = 0; + + virtual const char* GetFunctionLastExceptionInfo(void* Function, int *Length) = 0; + + //-------------------------- end cs call js -------------------------- + + //-------------------------- begin debug -------------------------- + + virtual void CreateInspector(int32_t Port) = 0; + + virtual void DestroyInspector() = 0; + + virtual int InspectorTick() = 0; + + virtual void LogicTick() = 0; + + //-------------------------- end debug -------------------------- + + virtual ~IPuertsPlugin() + { + } +}; + +struct PuertsPluginStore +{ + IPuertsPlugin* PuertsPlugin; +}; + +IPuertsPlugin* CreateV8Plugin(void* external_quickjs_runtime, void* external_quickjs_context); + +IPuertsPlugin* CreateQJSPlugin(void* external_quickjs_runtime, void* external_quickjs_context); + +} \ No newline at end of file diff --git a/unity/native_src/Inc/JSEngine.h b/unity/native_src/Inc/JSEngine.h index e0a0477116..a78d30480e 100644 --- a/unity/native_src/Inc/JSEngine.h +++ b/unity/native_src/Inc/JSEngine.h @@ -18,6 +18,9 @@ #include "JSFunction.h" #include "V8InspectorImpl.h" #include "BackendEnv.h" +#ifdef MULT_BACKENDS +#include "IPuertsPlugin.h" +#endif #if WITH_NODEJS #pragma warning(push, 0) @@ -31,9 +34,15 @@ namespace PUERTS_NAMESPACE { typedef char* (*CSharpModuleResolveCallback)(const char* identifer, int32_t jsEnvIdx, char*& pathForDebug); +#ifdef MULT_BACKENDS +typedef void(*CSharpFunctionCallback)(puerts::IPuertsPlugin* plugin, const v8::FunctionCallbackInfo& Info, void* Self, int ParamLen, int64_t UserData); + +typedef void* (*CSharpConstructorCallback)(puerts::IPuertsPlugin* plugin, const v8::FunctionCallbackInfo& Info, int ParamLen, int64_t UserData); +#else typedef void(*CSharpFunctionCallback)(v8::Isolate* Isolate, const v8::FunctionCallbackInfo& Info, void* Self, int ParamLen, int64_t UserData); typedef void* (*CSharpConstructorCallback)(v8::Isolate* Isolate, const v8::FunctionCallbackInfo& Info, int ParamLen, int64_t UserData); +#endif typedef void(*CSharpDestructorCallback)(void* Self, int64_t UserData); @@ -72,7 +81,11 @@ class JSEngine static void HostInitializeImportMetaObject(v8::Local context, v8::Local module, v8::Local meta); #endif public: +#ifdef MULT_BACKENDS + JSEngine(puerts::IPuertsPlugin* InPuertsPlugin, void* external_quickjs_runtime, void* external_quickjs_context); +#else JSEngine(void* external_quickjs_runtime, void* external_quickjs_context); +#endif ~JSEngine(); diff --git a/unity/native_src/Inc/JSFunction.h b/unity/native_src/Inc/JSFunction.h index 1189ade9b9..d1008dc000 100644 --- a/unity/native_src/Inc/JSFunction.h +++ b/unity/native_src/Inc/JSFunction.h @@ -10,6 +10,9 @@ #include #include #include "Common.h" +#ifdef MULT_BACKENDS +#include "IPuertsPlugin.h" +#endif #include "V8Utils.h" @@ -48,10 +51,14 @@ struct FValue v8::UniquePersistent Persistent; }; +#ifdef MULT_BACKENDS +struct FResultInfo : public puerts::PuertsPluginStore +#else struct FResultInfo +#endif { v8::Isolate* Isolate; - + v8::UniquePersistent Context; v8::UniquePersistent Result; @@ -60,7 +67,13 @@ struct FResultInfo class JSFunction { public: + FResultInfo ResultInfo; + +#ifdef MULT_BACKENDS + JSFunction(puerts::IPuertsPlugin* PuertsPlugin, v8::Isolate* InIsolate, v8::Local InContext, v8::Local InFunction, int32_t InIndex); +#else JSFunction(v8::Isolate* InIsolate, v8::Local InContext, v8::Local InFunction, int32_t InIndex); +#endif ~JSFunction(); @@ -74,8 +87,6 @@ class JSFunction v8::UniquePersistent LastException; - FResultInfo ResultInfo; - int32_t Index; }; } \ No newline at end of file diff --git a/unity/native_src/Src/JSEngine.cpp b/unity/native_src/Src/JSEngine.cpp index ff6c9069e0..cd68f5e71d 100644 --- a/unity/native_src/Src/JSEngine.cpp +++ b/unity/native_src/Src/JSEngine.cpp @@ -87,7 +87,11 @@ namespace PUERTS_NAMESPACE LastExceptionInfo = FV8Utils::ExceptionToString(MainIsolate, Exception); } +#ifdef MULT_BACKENDS + JSEngine::JSEngine(puerts::IPuertsPlugin* InPuertsPlugin, void* external_quickjs_runtime, void* external_quickjs_context) +#else JSEngine::JSEngine(void* external_quickjs_runtime, void* external_quickjs_context) +#endif { GeneralDestructor = nullptr; BackendEnv::GlobalPrepare(); @@ -107,6 +111,9 @@ namespace PUERTS_NAMESPACE MainIsolate = BackendEnv.CreateIsolate(external_quickjs_runtime); auto Isolate = MainIsolate; +#ifdef MULT_BACKENDS + ResultInfo.PuertsPlugin = InPuertsPlugin; +#endif ResultInfo.Isolate = MainIsolate; MainIsolate->SetData(0, this); MainIsolate->SetData(1, &BackendEnv); @@ -366,13 +373,21 @@ namespace PUERTS_NAMESPACE JSFunction* Function = nullptr; for (int i = 0; i < JSFunctions.size(); i++) { if (!JSFunctions[i]) { +#ifdef MULT_BACKENDS + Function = new JSFunction(ResultInfo.PuertsPlugin, InIsolate, InContext, InFunction, i); +#else Function = new JSFunction(InIsolate, InContext, InFunction, i); +#endif JSFunctions[i] = Function; break; } } if (!Function) { +#ifdef MULT_BACKENDS + Function = new JSFunction(ResultInfo.PuertsPlugin, InIsolate, InContext, InFunction, static_cast(JSFunctions.size())); +#else Function = new JSFunction(InIsolate, InContext, InFunction, static_cast(JSFunctions.size())); +#endif JSFunctions.push_back(Function); } InFunction->Set(InContext, FV8Utils::V8String(InIsolate, FUNCTION_INDEX_KEY), v8::Integer::New(InIsolate, Function->Index)); @@ -394,7 +409,12 @@ namespace PUERTS_NAMESPACE void* Ptr = CallbackInfo->IsStatic ? nullptr : FV8Utils::GetPoninter(Info.Holder()); +#ifdef MULT_BACKENDS + auto JsEngine = FV8Utils::IsolateData(Isolate); + CallbackInfo->Callback(JsEngine->ResultInfo.PuertsPlugin, Info, Ptr, Info.Length(), CallbackInfo->Data); +#else CallbackInfo->Callback(Isolate, Info, Ptr, Info.Length(), CallbackInfo->Data); +#endif } v8::Local JSEngine::ToTemplate(v8::Isolate* Isolate, bool IsStatic, CSharpFunctionCallback Callback, int64_t Data) @@ -424,6 +444,7 @@ namespace PUERTS_NAMESPACE static void NewWrap(const v8::FunctionCallbackInfo& Info) { v8::Isolate* Isolate = Info.GetIsolate(); + auto JsEngine = FV8Utils::IsolateData(Isolate); #ifdef THREAD_SAFE v8::Locker Locker(Isolate); #endif @@ -444,9 +465,13 @@ namespace PUERTS_NAMESPACE } else // Call by js new { +#ifdef MULT_BACKENDS + if (LifeCycleInfo->Constructor) Ptr = LifeCycleInfo->Constructor(JsEngine->ResultInfo.PuertsPlugin, Info, Info.Length(), LifeCycleInfo->Data); +#else if (LifeCycleInfo->Constructor) Ptr = LifeCycleInfo->Constructor(Isolate, Info, Info.Length(), LifeCycleInfo->Data); +#endif } - FV8Utils::IsolateData(Isolate)->BindObject(LifeCycleInfo, Ptr, Self); + JsEngine->BindObject(LifeCycleInfo, Ptr, Self); } else { diff --git a/unity/native_src/Src/JSFunction.cpp b/unity/native_src/Src/JSFunction.cpp index 65d0beef85..2c7162bcd8 100644 --- a/unity/native_src/Src/JSFunction.cpp +++ b/unity/native_src/Src/JSFunction.cpp @@ -25,8 +25,14 @@ namespace PUERTS_NAMESPACE GObject.Reset(); } +#ifdef MULT_BACKENDS + JSFunction::JSFunction(puerts::IPuertsPlugin* InPuertsPlugin, v8::Isolate* InIsolate, v8::Local InContext, v8::Local InFunction, int32_t InIndex) + { + ResultInfo.PuertsPlugin = InPuertsPlugin; +#else JSFunction::JSFunction(v8::Isolate* InIsolate, v8::Local InContext, v8::Local InFunction, int32_t InIndex) { +#endif ResultInfo.Isolate = InIsolate; ResultInfo.Context.Reset(InIsolate, InContext); GFunction.Reset(InIsolate, InFunction); diff --git a/unity/native_src/Src/PluginImpl.cpp b/unity/native_src/Src/PluginImpl.cpp new file mode 100644 index 0000000000..ad80cbf371 --- /dev/null +++ b/unity/native_src/Src/PluginImpl.cpp @@ -0,0 +1,1204 @@ +/* +* Tencent is pleased to support the open source community by making Puerts available. +* Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. +* Puerts is licensed under the BSD 3-Clause License, except for the third-party components listed in the file 'LICENSE' which may be subject to their corresponding license terms. +* This file is subject to the terms and conditions defined in file 'LICENSE', which is part of this source code package. +*/ + +#include "IPuertsPlugin.h" +#include "JSEngine.h" + +namespace PUERTS_NAMESPACE +{ + +class V8Plugin : public puerts::IPuertsPlugin +{ +public: + V8Plugin(void* external_quickjs_runtime, void* external_quickjs_context) + : jsEngine(this, external_quickjs_runtime, external_quickjs_context) + { + } + + virtual ~V8Plugin() override + { + } + + virtual int GetType() override; + + virtual void SetGlobalFunction(const char *Name, puerts::FuncPtr Callback, int64_t Data) override; + + virtual void SetModuleResolver(puerts::FuncPtr Resolver, int32_t Idx) override; + + virtual void* Eval(const char *Code, const char* Path) override; + + virtual bool ClearModuleCache(const char* Path) override; + + virtual int RegisterClass(int BaseTypeId, const char *FullName, puerts::FuncPtr Constructor, puerts::FuncPtr Destructor, int64_t Data, int Size) override; + + virtual int RegisterFunction(int ClassID, const char *Name, int IsStatic, puerts::FuncPtr Callback, int64_t Data) override; + + virtual int RegisterProperty(int ClassID, const char *Name, int IsStatic, puerts::FuncPtr Getter, int64_t GetterData, puerts::FuncPtr Setter, int64_t SetterData, int DontDelete) override; + + virtual const char* GetLastExceptionInfo(int *Length) override; + + virtual void LowMemoryNotification() override; + + virtual bool IdleNotificationDeadline(double DeadlineInSeconds) override; + + virtual void RequestMinorGarbageCollectionForTesting() override; + + virtual void RequestFullGarbageCollectionForTesting() override; + + + virtual void SetGeneralDestructor(puerts::FuncPtr GeneralDestructor) override; + + virtual void* GetJSObjectValueGetter() override; + + virtual void* GetModuleExecutor() override; + + virtual void* GetResultInfo() override; + + //-------------------------- begin js call cs -------------------------- + virtual void* GetArgumentValue(const void* Info, int Index) override; + + virtual puerts::JsValueType GetJsValueType(const void* Value, int IsOut) override; + + virtual puerts::JsValueType GetArgumentType(const void* Info, int Index, int IsOut) override; + + virtual double GetNumberFromValue(void* Value, int IsOut) override; + + virtual void SetNumberToOutValue(void* Value, double Number) override; + + virtual double GetDateFromValue(void* Value, int IsOut) override; + + virtual void SetDateToOutValue(void* Value, double Date) override; + + virtual const char *GetStringFromValue(void* Value, int *Length, int IsOut) override; + + virtual void SetStringToOutValue(void* Value, const char *Str) override; + + virtual int GetBooleanFromValue(void* Value, int IsOut) override; + + virtual void SetBooleanToOutValue(void* Value, int B) override; + + virtual int ValueIsBigInt(void* Value, int IsOut) override; + + virtual int64_t GetBigIntFromValue(void* Value, int IsOut) override; + + virtual void SetBigIntToOutValue(void* Value, int64_t BigInt) override; + + virtual const char* GetArrayBufferFromValue(void* Value, int *Length, int IsOut) override; + + virtual void SetArrayBufferToOutValue(void* Value, unsigned char *Bytes, int Length) override; + + virtual void *GetObjectFromValue(void* Value, int IsOut) override; + + virtual int GetTypeIdFromValue(void* Value, int IsOut) override; + + virtual void SetObjectToOutValue(void* Value, int ClassID, void* Ptr) override; + + virtual void SetNullToOutValue(void* Value) override; + + virtual void* GetFunctionFromValue(void* Value, int IsOut) override; + + virtual void* GetJSObjectFromValue(void* Value, int IsOut) override; + + virtual void ReleaseJSFunction(void* Function) override; + + virtual void ReleaseJSObject(void* Object) override; + + virtual void ThrowException(const char * Message) override; + + virtual void ReturnClass(const void* Info, int ClassID) override; + + virtual void ReturnObject(const void* Info, int ClassID, void* Ptr) override; + + virtual void ReturnNumber(const void* Info, double Number) override; + + virtual void ReturnString(const void* Info, const char* String) override; + + virtual void ReturnBigInt(const void* Info, int64_t BigInt) override; + + virtual void ReturnArrayBuffer(const void* Info, unsigned char *Bytes, int Length) override; + + virtual void ReturnBoolean(const void* Info, int Bool) override; + + virtual void ReturnDate(const void* Info, double Date) override; + + virtual void ReturnNull(const void* Info) override; + + virtual void ReturnFunction(const void* Info, void* Function) override; + + virtual void ReturnCSharpFunctionCallback(const void* Info, puerts::FuncPtr Callback, int64_t Data) override; + + virtual void ReturnJSObject(const void* Info, void* Object) override; + //-------------------------- end js call cs -------------------------- + + //-------------------------- bengin cs call js -------------------------- + + virtual void PushNullForJSFunction(void* Function) override; + + virtual void PushDateForJSFunction(void* Function, double DateValue) override; + + virtual void PushBooleanForJSFunction(void* Function, int B) override; + + virtual void PushBigIntForJSFunction(void* Function, int64_t V) override; + + virtual void PushArrayBufferForJSFunction(void* Function, unsigned char * Bytes, int Length) override; + + virtual void PushStringForJSFunction(void* Function, const char* S) override; + + virtual void PushNumberForJSFunction(void* Function, double D) override; + + virtual void PushObjectForJSFunction(void* Function, int ClassID, void* Ptr) override; + + virtual void PushJSFunctionForJSFunction(void* Function, void* V) override; + + virtual void PushJSObjectForJSFunction(void* Function, void* V) override; + + virtual void* InvokeJSFunction(void* Function, int HasResult) override; + + virtual puerts::JsValueType GetResultType(void* ResultInfo) override; + + virtual double GetNumberFromResult(void* ResultInfo) override; + + virtual double GetDateFromResult(void* ResultInfo) override; + + virtual const char *GetStringFromResult(void* ResultInfo, int *Length) override; + + virtual int GetBooleanFromResult(void* ResultInfo) override; + + virtual int ResultIsBigInt(void* ResultInfo) override; + + virtual int64_t GetBigIntFromResult(void* ResultInfo) override; + + virtual const char *GetArrayBufferFromResult(void* ResultInfo, int *Length) override; + + virtual void *GetObjectFromResult(void* ResultInfo) override; + + virtual int GetTypeIdFromResult(void* ResultInfo) override; + + virtual void* GetJSObjectFromResult(void* ResultInfo) override; + + virtual void* GetFunctionFromResult(void* ResultInfo) override; + + virtual void ResetResult(void* ResultInfo) override; + + virtual const char* GetFunctionLastExceptionInfo(void* Function, int *Length) override; + + //-------------------------- end cs call js -------------------------- + + //-------------------------- begin debug -------------------------- + + virtual void CreateInspector(int32_t Port) override; + + virtual void DestroyInspector() override; + + virtual int InspectorTick() override; + + virtual void LogicTick() override; + + //-------------------------- end debug -------------------------- + +private: + PUERTS_NAMESPACE::JSEngine jsEngine; +}; + +int V8Plugin::GetType() +{ +#ifdef V8_BACKEND + return 0; +#endif +#ifdef QJS_BACKEND + return 2; +#endif +} + +void V8Plugin::SetGlobalFunction(const char *Name, puerts::FuncPtr Callback, int64_t Data) +{ + jsEngine.SetGlobalFunction(Name, (PUERTS_NAMESPACE::CSharpFunctionCallback)Callback, Data); +} + +void V8Plugin::SetModuleResolver(puerts::FuncPtr Resolver, int32_t Idx) +{ + jsEngine.Idx = Idx; +} + +void* V8Plugin::Eval(const char *Code, const char* Path) +{ + if (jsEngine.Eval(Code, Path)) + { + return &(jsEngine.ResultInfo); + } + else + { + return nullptr; + } +} + +bool V8Plugin::ClearModuleCache(const char* Path) +{ + return jsEngine.ClearModuleCache(Path); +} + +int V8Plugin::RegisterClass(int BaseTypeId, const char *FullName, puerts::FuncPtr Constructor, puerts::FuncPtr Destructor, int64_t Data, int Size) +{ + return jsEngine.RegisterClass(FullName, BaseTypeId, (PUERTS_NAMESPACE::CSharpConstructorCallback)Constructor, (PUERTS_NAMESPACE::CSharpDestructorCallback)Destructor, Data, Size); +} + +int V8Plugin::RegisterFunction(int ClassID, const char *Name, int IsStatic, puerts::FuncPtr Callback, int64_t Data) +{ + return jsEngine.RegisterFunction(ClassID, Name, IsStatic, (PUERTS_NAMESPACE::CSharpFunctionCallback)Callback, Data) ? 1 : 0; +} + +int V8Plugin::RegisterProperty(int ClassID, const char *Name, int IsStatic, puerts::FuncPtr Getter, int64_t GetterData, puerts::FuncPtr Setter, int64_t SetterData, int DontDelete) +{ + return jsEngine.RegisterProperty(ClassID, Name, IsStatic, (PUERTS_NAMESPACE::CSharpFunctionCallback)Getter, GetterData, (PUERTS_NAMESPACE::CSharpFunctionCallback)Setter, SetterData, DontDelete) ? 1 : 0; +} + +const char* V8Plugin::GetLastExceptionInfo(int *Length) +{ + *Length = static_cast(strlen(jsEngine.LastExceptionInfo.c_str())); + return jsEngine.LastExceptionInfo.c_str(); +} + +void V8Plugin::LowMemoryNotification() +{ + jsEngine.LowMemoryNotification(); +} + +bool V8Plugin::IdleNotificationDeadline(double DeadlineInSeconds) +{ + return jsEngine.IdleNotificationDeadline(DeadlineInSeconds); +} + +void V8Plugin::RequestMinorGarbageCollectionForTesting() +{ + jsEngine.RequestMinorGarbageCollectionForTesting(); +} + +void V8Plugin::RequestFullGarbageCollectionForTesting() +{ + jsEngine.RequestFullGarbageCollectionForTesting(); +} + +void V8Plugin::SetGeneralDestructor(puerts::FuncPtr GeneralDestructor) +{ + jsEngine.GeneralDestructor = (PUERTS_NAMESPACE::CSharpDestructorCallback)GeneralDestructor; +} + +void* V8Plugin::GetJSObjectValueGetter() +{ + return jsEngine.JSObjectValueGetter; +} + +void* V8Plugin::GetModuleExecutor() +{ + return jsEngine.GetModuleExecutor(); +} + +void* V8Plugin::GetResultInfo() +{ + return &(jsEngine.ResultInfo); +} + +//-------------------------- begin js call cs -------------------------- +void* V8Plugin::GetArgumentValue(const void* pInfo, int Index) +{ + const v8::FunctionCallbackInfo& Info = *(const v8::FunctionCallbackInfo*)pInfo; + return *Info[Index]; +} + +puerts::JsValueType V8Plugin::GetJsValueType(const void* pValue, int IsOut) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + const v8::Value *Value = (const v8::Value *)pValue; + if (IsOut) + { + if (Value->IsObject()) + { + auto Context = Isolate->GetCurrentContext(); + auto Outer = Value->ToObject(Context).ToLocalChecked(); + auto MaybeValue = Outer->Get(Context, 0); + if (MaybeValue.IsEmpty()) + { + return puerts::NullOrUndefined; + } + auto Realvalue = MaybeValue.ToLocalChecked(); + return GetJsValueType(*Realvalue, false); + } + else + { + return puerts::NullOrUndefined; + } + } + else + { + auto Context = Isolate->GetCurrentContext(); + return FV8Utils::GetType(Context, Value); + } +} + +puerts::JsValueType V8Plugin::GetArgumentType(const void* pInfo, int Index, int IsOut) +{ + const v8::FunctionCallbackInfo& Info = *(const v8::FunctionCallbackInfo*)pInfo; + return GetJsValueType(*Info[Index], IsOut); +} + +double V8Plugin::GetNumberFromValue(void* pValue, int IsOut) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + const v8::Value *Value = (const v8::Value *)pValue; + if (IsOut) + { + auto Context = Isolate->GetCurrentContext(); + auto Outer = Value->ToObject(Context).ToLocalChecked(); + auto Realvalue = Outer->Get(Context, 0).ToLocalChecked(); + return GetNumberFromValue(*Realvalue, false); + } + else + { + auto Context = Isolate->GetCurrentContext(); + auto maybeNumber = Value->NumberValue(Context); + if (maybeNumber.IsNothing()) + return 0; + return maybeNumber.ToChecked(); + } +} + +void V8Plugin::SetNumberToOutValue(void* pValue, double Number) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + const v8::Value *Value = (const v8::Value *)pValue; + if (Value->IsObject()) + { + auto Context = Isolate->GetCurrentContext(); + auto Outer = Value->ToObject(Context).ToLocalChecked(); + auto ReturnVal = Outer->Set(Context, 0, v8::Number::New(Isolate, Number)); + } +} + +double V8Plugin::GetDateFromValue(void* pValue, int IsOut) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + v8::Value *Value = (v8::Value *)pValue; + if (IsOut) + { + auto Context = Isolate->GetCurrentContext(); + auto Outer = Value->ToObject(Context).ToLocalChecked(); + auto Realvalue = Outer->Get(Context, 0).ToLocalChecked(); + return GetDateFromValue(*Realvalue, false); + } + else + { + return v8::Date::Cast(Value)->ValueOf(); + } +} + +void V8Plugin::SetDateToOutValue(void* pValue, double Date) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + const v8::Value *Value = (const v8::Value *)pValue; + if (Value->IsObject()) + { + auto Context = Isolate->GetCurrentContext(); + auto Outer = Value->ToObject(Context).ToLocalChecked(); + auto ReturnVal = Outer->Set(Context, 0, v8::Date::New(Context, Date).ToLocalChecked()); + } +} + +const char *V8Plugin::GetStringFromValue(void* pValue, int *Length, int IsOut) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + const v8::Value *Value = (const v8::Value *)pValue; + if (IsOut) + { + auto Context = Isolate->GetCurrentContext(); + auto Outer = Value->ToObject(Context).ToLocalChecked(); + auto Realvalue = Outer->Get(Context, 0).ToLocalChecked(); + return GetStringFromValue(*Realvalue, Length, false); + } + else + { + if (Value->IsNullOrUndefined()) + { + *Length = 0; + return nullptr; + } + auto Context = Isolate->GetCurrentContext(); + v8::Local Str; + if (!Value->ToString(Context).ToLocal(&Str)) return nullptr; + *Length = Str->Utf8Length(Isolate); + if (jsEngine.StrBuffer.size() < *Length + 1) jsEngine.StrBuffer.reserve(*Length + 1); + Str->WriteUtf8(Isolate, jsEngine.StrBuffer.data()); + + return jsEngine.StrBuffer.data(); + } +} + +void V8Plugin::SetStringToOutValue(void* pValue, const char *Str) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + const v8::Value *Value = (const v8::Value *)pValue; + if (Value->IsObject()) + { + auto Context = Isolate->GetCurrentContext(); + auto Outer = Value->ToObject(Context).ToLocalChecked(); + auto ReturnVal = Outer->Set(Context, 0, FV8Utils::V8String(Isolate, Str)); + } +} + +int V8Plugin::GetBooleanFromValue(void* pValue, int IsOut) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + const v8::Value *Value = (const v8::Value *)pValue; + if (IsOut) + { + auto Context = Isolate->GetCurrentContext(); + auto Outer = Value->ToObject(Context).ToLocalChecked(); + auto Realvalue = Outer->Get(Context, 0).ToLocalChecked(); + return GetBooleanFromValue(*Realvalue, false); + } + else + { + return Value->BooleanValue(Isolate) ? 1 : 0; + } +} + +void V8Plugin::SetBooleanToOutValue(void* pValue, int B) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + const v8::Value *Value = (const v8::Value *)pValue; + if (Value->IsObject()) + { + auto Context = Isolate->GetCurrentContext(); + auto Outer = Value->ToObject(Context).ToLocalChecked(); + auto ReturnVal = Outer->Set(Context, 0, v8::Boolean::New(Isolate, B)); + } +} + +int V8Plugin::ValueIsBigInt(void* pValue, int IsOut) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + const v8::Value *Value = (const v8::Value *)pValue; + if (IsOut) + { + auto Context = Isolate->GetCurrentContext(); + auto Outer = Value->ToObject(Context).ToLocalChecked(); + auto Realvalue = Outer->Get(Context, 0).ToLocalChecked(); + return ValueIsBigInt(*Realvalue, false); + } + else + { + auto Context = Isolate->GetCurrentContext(); + return Value->IsBigInt() ? 1 : 0; + } +} + +int64_t V8Plugin::GetBigIntFromValue(void* pValue, int IsOut) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + const v8::Value *Value = (const v8::Value *)pValue; + if (IsOut) + { + auto Context = Isolate->GetCurrentContext(); + auto Outer = Value->ToObject(Context).ToLocalChecked(); + auto Realvalue = Outer->Get(Context, 0).ToLocalChecked(); + return GetBigIntFromValue(*Realvalue, false); + } + else + { + auto Context = Isolate->GetCurrentContext(); + return Value->ToBigInt(Context).ToLocalChecked()->Int64Value(); + } +} + +void V8Plugin::SetBigIntToOutValue(void* pValue, int64_t BigInt) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + const v8::Value *Value = (const v8::Value *)pValue; + if (Value->IsObject()) + { + auto Context = Isolate->GetCurrentContext(); + auto Outer = Value->ToObject(Context).ToLocalChecked(); + auto ReturnVal = Outer->Set(Context, 0, v8::BigInt::New(Isolate, BigInt)); + } +} + +const char* V8Plugin::GetArrayBufferFromValue(void* pValue, int *Length, int IsOut) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + v8::Value *Value = (v8::Value *)pValue; + if (IsOut) + { + auto Context = Isolate->GetCurrentContext(); + auto Outer = Value->ToObject(Context).ToLocalChecked(); + auto Realvalue = Outer->Get(Context, 0).ToLocalChecked(); + return GetArrayBufferFromValue(*Realvalue, Length, false); + } + else + { + if (Value->IsArrayBufferView()) + { + v8::ArrayBufferView * BuffView = v8::ArrayBufferView::Cast(Value); + *Length = static_cast(BuffView->ByteLength()); + auto ABS = BuffView->Buffer()->GetBackingStore(); + return static_cast(ABS->Data()) + BuffView->ByteOffset(); + } + else if (Value->IsArrayBuffer()) + { + auto Ab = v8::ArrayBuffer::Cast(Value); + auto ABS = Ab->GetBackingStore(); + *Length = static_cast(ABS->ByteLength()); + return static_cast(ABS->Data()); + } + else + { + return nullptr; + } + } +} + +void V8Plugin::SetArrayBufferToOutValue(void* pValue, unsigned char *Bytes, int Length) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + const v8::Value *Value = (const v8::Value *)pValue; + if (Value->IsObject()) + { + auto Context = Isolate->GetCurrentContext(); + auto Outer = Value->ToObject(Context).ToLocalChecked(); + v8::Local Ab = PUERTS_NAMESPACE::NewArrayBuffer(Isolate, Bytes, Length); + auto ReturnVal = Outer->Set(Context, 0, Ab); + } +} + +void* V8Plugin::GetObjectFromValue(void* pValue, int IsOut) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + v8::Value *Value = (v8::Value *)pValue; + if (IsOut) + { + auto Context = Isolate->GetCurrentContext(); + auto Outer = Value->ToObject(Context).ToLocalChecked(); + auto Realvalue = Outer->Get(Context, 0).ToLocalChecked(); + return GetObjectFromValue(*Realvalue, false); + } + else + { + auto Context = Isolate->GetCurrentContext(); + return FV8Utils::GetPoninter(Context, Value); + } +} + +int V8Plugin::GetTypeIdFromValue(void* pValue, int IsOut) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + v8::Value *Value = (v8::Value *)pValue; + if (IsOut) + { + auto Context = Isolate->GetCurrentContext(); + auto Outer = Value->ToObject(Context).ToLocalChecked(); + auto Realvalue = Outer->Get(Context, 0).ToLocalChecked(); + return GetTypeIdFromValue(*Realvalue, false); + } + else + { + if (Value->IsFunction()) + { + auto Context = Isolate->GetCurrentContext(); + auto Function = v8::Local::Cast(Value->ToObject(Context).ToLocalChecked()); + auto MaybeMap = Function->Get(Context, FV8Utils::V8String(Isolate, "__puertsMetadata")); + if (MaybeMap.IsEmpty()) return -1; + auto MaybeValue = v8::Local::Cast(MaybeMap.ToLocalChecked())->Get(Context, FV8Utils::V8String(Isolate, "classid")); + if (MaybeValue.IsEmpty()) return -1; + auto Value = MaybeValue.ToLocalChecked(); + if (!Value->IsInt32()) return -1; + return Value->Int32Value(Context).ToChecked(); + } + else + { + auto Context = Isolate->GetCurrentContext(); + auto LifeCycleInfo = static_cast(FV8Utils::GetPoninter(Context, Value, 1)); + return LifeCycleInfo ? LifeCycleInfo->ClassID : -1; + } + } +} + +void V8Plugin::SetObjectToOutValue(void* pValue, int ClassID, void* Ptr) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + const v8::Value *Value = (const v8::Value *)pValue; + if (Value->IsObject()) + { + auto Context = Isolate->GetCurrentContext(); + auto Object = jsEngine.FindOrAddObject(Isolate, Context, ClassID, Ptr); + auto Outer = Value->ToObject(Context).ToLocalChecked(); + auto ReturnVal = Outer->Set(Context, 0, Object); + } +} + +void V8Plugin::SetNullToOutValue(void* pValue) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + const v8::Value *Value = (const v8::Value *)pValue; + if (Value->IsObject()) + { + auto Context = Isolate->GetCurrentContext(); + auto Outer = Value->ToObject(Context).ToLocalChecked(); + auto ReturnVal = Outer->Set(Context, 0, v8::Null(Isolate)); + } +} + +void* V8Plugin::GetFunctionFromValue(void* pValue, int IsOut) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + const v8::Value *Value = (const v8::Value *)pValue; + if (IsOut) + { + auto Context = Isolate->GetCurrentContext(); + auto Outer = Value->ToObject(Context).ToLocalChecked(); + auto Realvalue = Outer->Get(Context, 0).ToLocalChecked(); + return GetFunctionFromValue(*Realvalue, false); + } + else + { + auto Context = Isolate->GetCurrentContext(); + auto Function = v8::Local::Cast(Value->ToObject(Context).ToLocalChecked()); + return jsEngine.CreateJSFunction(Isolate, Context, Function); + } +} + +void* V8Plugin::GetJSObjectFromValue(void* pValue, int IsOut) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + const v8::Value *Value = (const v8::Value *)pValue; + if (IsOut) + { + auto Context = Isolate->GetCurrentContext(); + auto Outer = Value->ToObject(Context).ToLocalChecked(); + auto Realvalue = Outer->Get(Context, 0).ToLocalChecked(); + return GetJSObjectFromValue(*Realvalue, false); + } + else + { + auto Context = Isolate->GetCurrentContext(); + auto JSObject = v8::Local::Cast(Value->ToObject(Context).ToLocalChecked()); + return jsEngine.CreateJSObject(Isolate, Context, JSObject); + } +} + +void V8Plugin::ReleaseJSFunction(void* pFunction) +{ + PUERTS_NAMESPACE::JSFunction *Function = (PUERTS_NAMESPACE::JSFunction *)pFunction; + if (Function) + { + jsEngine.ReleaseJSFunction(Function); + } +} + +void V8Plugin::ReleaseJSObject(void* pObject) +{ + PUERTS_NAMESPACE::JSObject *Object = (PUERTS_NAMESPACE::JSObject *)pObject; + if (Object) + { + jsEngine.ReleaseJSObject(Object); + } +} + +void V8Plugin::ThrowException(const char * Message) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + PUERTS_NAMESPACE::FV8Utils::ThrowException(Isolate, Message); +} + +void V8Plugin::ReturnClass(const void* pInfo, int ClassID) +{ + const v8::FunctionCallbackInfo& Info = *(const v8::FunctionCallbackInfo*)pInfo; + Info.GetReturnValue().Set(jsEngine.GetClassConstructor(ClassID)); +} + +void V8Plugin::ReturnObject(const void* pInfo, int ClassID, void* Ptr) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + const v8::FunctionCallbackInfo& Info = *(const v8::FunctionCallbackInfo*)pInfo; + Info.GetReturnValue().Set(jsEngine.FindOrAddObject(Isolate, Isolate->GetCurrentContext(), ClassID, Ptr)); +} + +void V8Plugin::ReturnNumber(const void* pInfo, double Number) +{ + const v8::FunctionCallbackInfo& Info = *(const v8::FunctionCallbackInfo*)pInfo; + Info.GetReturnValue().Set(Number); +} + +void V8Plugin::ReturnString(const void* pInfo, const char* String) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + const v8::FunctionCallbackInfo& Info = *(const v8::FunctionCallbackInfo*)pInfo; + Info.GetReturnValue().Set(PUERTS_NAMESPACE::FV8Utils::V8String(Isolate, String)); +} + +void V8Plugin::ReturnBigInt(const void* pInfo, int64_t BigInt) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + const v8::FunctionCallbackInfo& Info = *(const v8::FunctionCallbackInfo*)pInfo; + Info.GetReturnValue().Set(v8::BigInt::New(Isolate, BigInt)); +} + +void V8Plugin::ReturnArrayBuffer(const void* pInfo, unsigned char *Bytes, int Length) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + const v8::FunctionCallbackInfo& Info = *(const v8::FunctionCallbackInfo*)pInfo; + Info.GetReturnValue().Set(PUERTS_NAMESPACE::NewArrayBuffer(Isolate, Bytes, Length)); +} + +void V8Plugin::ReturnBoolean(const void* pInfo, int Bool) +{ + const v8::FunctionCallbackInfo& Info = *(const v8::FunctionCallbackInfo*)pInfo; + Info.GetReturnValue().Set(Bool ? true : false); +} + +void V8Plugin::ReturnDate(const void* pInfo, double Date) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + const v8::FunctionCallbackInfo& Info = *(const v8::FunctionCallbackInfo*)pInfo; + Info.GetReturnValue().Set(v8::Date::New(Isolate->GetCurrentContext(), Date).ToLocalChecked()); +} + +void V8Plugin::ReturnNull(const void* pInfo) +{ + const v8::FunctionCallbackInfo& Info = *(const v8::FunctionCallbackInfo*)pInfo; + Info.GetReturnValue().SetNull(); +} + +void V8Plugin::ReturnFunction(const void* pInfo, void* pFunction) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + PUERTS_NAMESPACE::JSFunction *Function = (PUERTS_NAMESPACE::JSFunction *)pFunction; + const v8::FunctionCallbackInfo& Info = *(const v8::FunctionCallbackInfo*)pInfo; + Info.GetReturnValue().Set(Function->GFunction.Get(Isolate)); +} + +void V8Plugin::ReturnCSharpFunctionCallback(const void* pInfo, puerts::FuncPtr Callback, int64_t Data) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + const v8::FunctionCallbackInfo& Info = *(const v8::FunctionCallbackInfo*)pInfo; +#ifdef THREAD_SAFE + v8::Locker Locker(Isolate); +#endif + v8::Isolate::Scope IsolateScope(Isolate); + v8::HandleScope HandleScope(Isolate); + v8::Local Context = jsEngine.ResultInfo.Context.Get(Isolate); + v8::Context::Scope ContextScope(Context); + + Info.GetReturnValue().Set(jsEngine.ToTemplate(Isolate, false, (PUERTS_NAMESPACE::CSharpFunctionCallback)Callback, Data)->GetFunction(Context).ToLocalChecked()); +} + +void V8Plugin::ReturnJSObject(const void* pInfo, void* pObject) +{ + v8::Isolate* Isolate = jsEngine.MainIsolate; + PUERTS_NAMESPACE::JSObject *Object = (PUERTS_NAMESPACE::JSObject *)pObject; + const v8::FunctionCallbackInfo& Info = *(const v8::FunctionCallbackInfo*)pInfo; + Info.GetReturnValue().Set(Object->GObject.Get(Isolate)); +} +//-------------------------- end js call cs -------------------------- + +//-------------------------- bengin cs call js -------------------------- + +void V8Plugin::PushNullForJSFunction(void* pFunction) +{ + PUERTS_NAMESPACE::JSFunction *Function = (PUERTS_NAMESPACE::JSFunction *)pFunction; + FValue Value; + Value.Type = puerts::NullOrUndefined; + Function->Arguments.push_back(std::move(Value)); +} + +void V8Plugin::PushDateForJSFunction(void* pFunction, double DateValue) +{ + PUERTS_NAMESPACE::JSFunction *Function = (PUERTS_NAMESPACE::JSFunction *)pFunction; + FValue Value; + Value.Type = puerts::Date; + Value.Number = DateValue; + Function->Arguments.push_back(std::move(Value)); +} + +void V8Plugin::PushBooleanForJSFunction(void* pFunction, int B) +{ + PUERTS_NAMESPACE::JSFunction *Function = (PUERTS_NAMESPACE::JSFunction *)pFunction; + FValue Value; + Value.Type = puerts::Boolean; + Value.Boolean = B; + Function->Arguments.push_back(std::move(Value)); +} + +void V8Plugin::PushBigIntForJSFunction(void* pFunction, int64_t V) +{ + PUERTS_NAMESPACE::JSFunction *Function = (PUERTS_NAMESPACE::JSFunction *)pFunction; + FValue Value; + Value.Type = puerts::BigInt; + Value.BigInt = V; + Function->Arguments.push_back(std::move(Value)); +} + +void V8Plugin::PushArrayBufferForJSFunction(void* pFunction, unsigned char * Bytes, int Length) +{ + PUERTS_NAMESPACE::JSFunction *Function = (PUERTS_NAMESPACE::JSFunction *)pFunction; + auto Isolate = Function->ResultInfo.Isolate; +#ifdef THREAD_SAFE + v8::Locker Locker(Isolate); +#endif + v8::Isolate::Scope IsolateScope(Isolate); + v8::HandleScope HandleScope(Isolate); + v8::Local Context = Function->ResultInfo.Context.Get(Isolate); + v8::Context::Scope ContextScope(Context); + FValue Value; + Value.Type = puerts::ArrayBuffer; + Value.Persistent.Reset(Isolate, PUERTS_NAMESPACE::NewArrayBuffer(Isolate, Bytes, Length)); + Function->Arguments.push_back(std::move(Value)); +} + +void V8Plugin::PushStringForJSFunction(void* pFunction, const char* S) +{ + PUERTS_NAMESPACE::JSFunction *Function = (PUERTS_NAMESPACE::JSFunction *)pFunction; + FValue Value; + Value.Type = puerts::String; + Value.Str = S; + Function->Arguments.push_back(std::move(Value)); +} + +void V8Plugin::PushNumberForJSFunction(void* pFunction, double D) +{ + PUERTS_NAMESPACE::JSFunction *Function = (PUERTS_NAMESPACE::JSFunction *)pFunction; + FValue Value; + Value.Type = puerts::Number; + Value.Number = D; + Function->Arguments.push_back(std::move(Value)); +} + +void V8Plugin::PushObjectForJSFunction(void* pFunction, int ClassID, void* Ptr) +{ + PUERTS_NAMESPACE::JSFunction *Function = (PUERTS_NAMESPACE::JSFunction *)pFunction; + FValue Value; + Value.Type = puerts::NativeObject; + auto Isolate = Function->ResultInfo.Isolate; + v8::Isolate::Scope IsolateScope(Isolate); + v8::HandleScope HandleScope(Isolate); + v8::Local Context = Function->ResultInfo.Context.Get(Isolate); + v8::Context::Scope ContextScope(Context); + auto localObj = jsEngine.FindOrAddObject(Isolate, Context, ClassID, Ptr); + Value.Persistent.Reset(Isolate, localObj); + Function->Arguments.push_back(std::move(Value)); +} + +void V8Plugin::PushJSFunctionForJSFunction(void* pFunction, void* V) +{ + PUERTS_NAMESPACE::JSFunction *Function = (PUERTS_NAMESPACE::JSFunction *)pFunction; + FValue Value; + Value.Type = puerts::Function; + Value.FunctionPtr = (PUERTS_NAMESPACE::JSFunction *)V; // TODO: 直接传指针安全吗? + Function->Arguments.push_back(std::move(Value)); +} + +void V8Plugin::PushJSObjectForJSFunction(void* pFunction, void* V) +{ + PUERTS_NAMESPACE::JSFunction *Function = (PUERTS_NAMESPACE::JSFunction *)pFunction; + FValue Value; + Value.Type = puerts::JsObject; + Value.JSObjectPtr = (PUERTS_NAMESPACE::JSObject *)V; + Function->Arguments.push_back(std::move(Value)); +} + +void* V8Plugin::InvokeJSFunction(void* pFunction, int HasResult) +{ + PUERTS_NAMESPACE::JSFunction *Function = (PUERTS_NAMESPACE::JSFunction *)pFunction; + if (Function->Invoke(HasResult)) + { + return &(Function->ResultInfo); + } + else + { + return nullptr; + } +} + +puerts::JsValueType V8Plugin::GetResultType(void* pResultInfo) +{ + PUERTS_NAMESPACE::FResultInfo *ResultInfo = (PUERTS_NAMESPACE::FResultInfo *)pResultInfo; + if (ResultInfo->Result.IsEmpty()) + { + return puerts::NullOrUndefined; + } + v8::Isolate* Isolate = ResultInfo->Isolate; +#ifdef THREAD_SAFE + v8::Locker Locker(Isolate); +#endif + v8::Isolate::Scope IsolateScope(Isolate); + v8::HandleScope HandleScope(Isolate); + v8::Local Context = ResultInfo->Context.Get(Isolate); + v8::Context::Scope ContextScope(Context); + auto Result = ResultInfo->Result.Get(Isolate); + return FV8Utils::GetType(Context, *Result); +} + +double V8Plugin::GetNumberFromResult(void* pResultInfo) +{ + PUERTS_NAMESPACE::FResultInfo *ResultInfo = (PUERTS_NAMESPACE::FResultInfo *)pResultInfo; + v8::Isolate* Isolate = ResultInfo->Isolate; +#ifdef THREAD_SAFE + v8::Locker Locker(Isolate); +#endif + v8::Isolate::Scope IsolateScope(Isolate); + v8::HandleScope HandleScope(Isolate); + v8::Local Context = ResultInfo->Context.Get(Isolate); + v8::Context::Scope ContextScope(Context); + auto Result = ResultInfo->Result.Get(Isolate); + + return Result->NumberValue(Context).ToChecked(); +} + +double V8Plugin::GetDateFromResult(void* pResultInfo) +{ + PUERTS_NAMESPACE::FResultInfo *ResultInfo = (PUERTS_NAMESPACE::FResultInfo *)pResultInfo; + v8::Isolate* Isolate = ResultInfo->Isolate; +#ifdef THREAD_SAFE + v8::Locker Locker(Isolate); +#endif + v8::Isolate::Scope IsolateScope(Isolate); + v8::HandleScope HandleScope(Isolate); + v8::Local Context = ResultInfo->Context.Get(Isolate); + v8::Context::Scope ContextScope(Context); + auto Result = ResultInfo->Result.Get(Isolate); + + return v8::Date::Cast(*Result)->ValueOf(); +} + +const char *V8Plugin::GetStringFromResult(void* pResultInfo, int *Length) +{ + PUERTS_NAMESPACE::FResultInfo *ResultInfo = (PUERTS_NAMESPACE::FResultInfo *)pResultInfo; + v8::Isolate* Isolate = ResultInfo->Isolate; +#ifdef THREAD_SAFE + v8::Locker Locker(Isolate); +#endif + v8::Isolate::Scope IsolateScope(Isolate); + v8::HandleScope HandleScope(Isolate); + v8::Local Context = ResultInfo->Context.Get(Isolate); + v8::Context::Scope ContextScope(Context); + + v8::Local Str; + auto Result = ResultInfo->Result.Get(Isolate); + if (Result->IsNullOrUndefined() || !Result->ToString(Context).ToLocal(&Str)) + { + *Length = 0; + return nullptr; + } + *Length = Str->Utf8Length(Isolate); + if (jsEngine.StrBuffer.size() < *Length + 1) jsEngine.StrBuffer.reserve(*Length + 1); + Str->WriteUtf8(Isolate, jsEngine.StrBuffer.data()); + + return jsEngine.StrBuffer.data(); +} + +int V8Plugin::GetBooleanFromResult(void* pResultInfo) +{ + PUERTS_NAMESPACE::FResultInfo *ResultInfo = (PUERTS_NAMESPACE::FResultInfo *)pResultInfo; + v8::Isolate* Isolate = ResultInfo->Isolate; +#ifdef THREAD_SAFE + v8::Locker Locker(Isolate); +#endif + v8::Isolate::Scope IsolateScope(Isolate); + v8::HandleScope HandleScope(Isolate); + v8::Local Context = ResultInfo->Context.Get(Isolate); + v8::Context::Scope ContextScope(Context); + auto Result = ResultInfo->Result.Get(Isolate); + + return Result->BooleanValue(Isolate) ? 1 : 0; +} + +int V8Plugin::ResultIsBigInt(void* pResultInfo) //TODO: ? +{ + PUERTS_NAMESPACE::FResultInfo *ResultInfo = (PUERTS_NAMESPACE::FResultInfo *)pResultInfo; + v8::Isolate* Isolate = ResultInfo->Isolate; +#ifdef THREAD_SAFE + v8::Locker Locker(Isolate); +#endif + v8::Isolate::Scope IsolateScope(Isolate); + v8::HandleScope HandleScope(Isolate); + v8::Local Context = ResultInfo->Context.Get(Isolate); + v8::Context::Scope ContextScope(Context); + auto Result = ResultInfo->Result.Get(Isolate); + + return Result->IsBigInt() ? 1 : 0; +} + +int64_t V8Plugin::GetBigIntFromResult(void* pResultInfo) +{ + PUERTS_NAMESPACE::FResultInfo *ResultInfo = (PUERTS_NAMESPACE::FResultInfo *)pResultInfo; + v8::Isolate* Isolate = ResultInfo->Isolate; +#ifdef THREAD_SAFE + v8::Locker Locker(Isolate); +#endif + v8::Isolate::Scope IsolateScope(Isolate); + v8::HandleScope HandleScope(Isolate); + v8::Local Context = ResultInfo->Context.Get(Isolate); + v8::Context::Scope ContextScope(Context); + auto Result = ResultInfo->Result.Get(Isolate); + + return Result->ToBigInt(Context).ToLocalChecked()->Int64Value(); +} + +const char *V8Plugin::GetArrayBufferFromResult(void* pResultInfo, int *Length) +{ + PUERTS_NAMESPACE::FResultInfo *ResultInfo = (PUERTS_NAMESPACE::FResultInfo *)pResultInfo; + v8::Isolate* Isolate = ResultInfo->Isolate; +#ifdef THREAD_SAFE + v8::Locker Locker(Isolate); +#endif + v8::Isolate::Scope IsolateScope(Isolate); + v8::HandleScope HandleScope(Isolate); + v8::Local Context = ResultInfo->Context.Get(Isolate); + v8::Context::Scope ContextScope(Context); + + auto Value = ResultInfo->Result.Get(Isolate); + if (Value->IsArrayBufferView()) + { + v8::Local BuffView = Value.As(); + *Length = static_cast(BuffView->ByteLength()); + auto ABS = BuffView->Buffer()->GetBackingStore(); + return static_cast(ABS->Data()) + BuffView->ByteOffset(); + } + else if (Value->IsArrayBuffer()) + { + auto Ab = v8::Local ::Cast(Value); + auto ABS = Ab->GetBackingStore(); + *Length = static_cast(ABS->ByteLength()); + return static_cast(ABS->Data()); + } + else + { + return nullptr; + } +} + +void *V8Plugin::GetObjectFromResult(void* pResultInfo) +{ + PUERTS_NAMESPACE::FResultInfo *ResultInfo = (PUERTS_NAMESPACE::FResultInfo *)pResultInfo; + v8::Isolate* Isolate = ResultInfo->Isolate; +#ifdef THREAD_SAFE + v8::Locker Locker(Isolate); +#endif + v8::Isolate::Scope IsolateScope(Isolate); + v8::HandleScope HandleScope(Isolate); + v8::Local Context = ResultInfo->Context.Get(Isolate); + v8::Context::Scope ContextScope(Context); + auto Result = ResultInfo->Result.Get(Isolate); + + return FV8Utils::GetPoninter(Context, Result); +} + +int V8Plugin::GetTypeIdFromResult(void* pResultInfo) +{ + PUERTS_NAMESPACE::FResultInfo *ResultInfo = (PUERTS_NAMESPACE::FResultInfo *)pResultInfo; + v8::Isolate* Isolate = ResultInfo->Isolate; +#ifdef THREAD_SAFE + v8::Locker Locker(Isolate); +#endif + v8::Isolate::Scope IsolateScope(Isolate); + v8::HandleScope HandleScope(Isolate); + v8::Local Context = ResultInfo->Context.Get(Isolate); + v8::Context::Scope ContextScope(Context); + auto Result = ResultInfo->Result.Get(Isolate); + + auto LifeCycleInfo = static_cast(FV8Utils::GetPoninter(Context, Result, 1)); + return LifeCycleInfo ? LifeCycleInfo->ClassID : -1; +} + +void* V8Plugin::GetJSObjectFromResult(void* pResultInfo) +{ + PUERTS_NAMESPACE::FResultInfo *ResultInfo = (PUERTS_NAMESPACE::FResultInfo *)pResultInfo; + v8::Isolate* Isolate = ResultInfo->Isolate; +#ifdef THREAD_SAFE + v8::Locker Locker(Isolate); +#endif + v8::Isolate::Scope IsolateScope(Isolate); + v8::HandleScope HandleScope(Isolate); + v8::Local Context = ResultInfo->Context.Get(Isolate); + v8::Context::Scope ContextScope(Context); + auto Result = ResultInfo->Result.Get(Isolate); + + auto V8Object = v8::Local::Cast(Result->ToObject(Context).ToLocalChecked()); + return jsEngine.CreateJSObject(Isolate, Context, V8Object); +} + +void* V8Plugin::GetFunctionFromResult(void* pResultInfo) +{ + PUERTS_NAMESPACE::FResultInfo *ResultInfo = (PUERTS_NAMESPACE::FResultInfo *)pResultInfo; + v8::Isolate* Isolate = ResultInfo->Isolate; +#ifdef THREAD_SAFE + v8::Locker Locker(Isolate); +#endif + v8::Isolate::Scope IsolateScope(Isolate); + v8::HandleScope HandleScope(Isolate); + v8::Local Context = ResultInfo->Context.Get(Isolate); + v8::Context::Scope ContextScope(Context); + auto Result = ResultInfo->Result.Get(Isolate); + + auto V8Function = v8::Local::Cast(Result->ToObject(Context).ToLocalChecked()); + return jsEngine.CreateJSFunction(Isolate, Context, V8Function); +} + +void V8Plugin::ResetResult(void* pResultInfo) +{ + PUERTS_NAMESPACE::FResultInfo *ResultInfo = (PUERTS_NAMESPACE::FResultInfo *)pResultInfo; + ResultInfo->Result.Reset(); +} + +const char* V8Plugin::GetFunctionLastExceptionInfo(void* pFunction, int *Length) +{ + PUERTS_NAMESPACE::JSFunction *Function = (PUERTS_NAMESPACE::JSFunction *)pFunction; + *Length = static_cast(strlen(Function->LastExceptionInfo.c_str())); + return Function->LastExceptionInfo.c_str(); +} + +//-------------------------- end cs call js -------------------------- + +//-------------------------- begin debug -------------------------- + +void V8Plugin::CreateInspector(int32_t Port) +{ + jsEngine.CreateInspector(Port); +} + +void V8Plugin::V8Plugin::DestroyInspector() +{ + jsEngine.DestroyInspector(); +} + +int V8Plugin::InspectorTick() +{ + return jsEngine.InspectorTick() ? 1 : 0; +} + +void V8Plugin::LogicTick() +{ + return jsEngine.LogicTick(); +} + +//-------------------------- end debug -------------------------- + +} + +namespace puerts +{ +#ifdef V8_BACKEND + IPuertsPlugin* CreateV8Plugin(void* external_quickjs_runtime, void* external_quickjs_context) + { + return new PUERTS_NAMESPACE::V8Plugin(external_quickjs_runtime, external_quickjs_context); + } +#endif + +#ifdef QJS_BACKEND + IPuertsPlugin* CreateQJSPlugin(void* external_quickjs_runtime, void* external_quickjs_context) + { + return new PUERTS_NAMESPACE::V8Plugin(external_quickjs_runtime, external_quickjs_context); + } +#endif +} \ No newline at end of file diff --git a/unity/native_src/Src/PuertsMultBackend.cpp b/unity/native_src/Src/PuertsMultBackend.cpp new file mode 100644 index 0000000000..46807b9dc2 --- /dev/null +++ b/unity/native_src/Src/PuertsMultBackend.cpp @@ -0,0 +1,500 @@ +/* +* Tencent is pleased to support the open source community by making Puerts available. +* Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. +* Puerts is licensed under the BSD 3-Clause License, except for the third-party components listed in the file 'LICENSE' which may be subject to their corresponding license terms. +* This file is subject to the terms and conditions defined in file 'LICENSE', which is part of this source code package. +*/ + +#include +#include "IPuertsPlugin.h" +#include "Log.h" + +#define API_LEVEL 33 + +LogCallback GLogCallback = nullptr; +LogCallback GLogWarningCallback = nullptr; +LogCallback GLogErrorCallback = nullptr; + +#ifdef __cplusplus +extern "C" { +#endif + +// deprecated, delete in 1.4 plz +V8_EXPORT int GetLibVersion() +{ + return API_LEVEL; +} +V8_EXPORT int GetApiLevel() +{ + return API_LEVEL; +} + +V8_EXPORT int GetLibBackend(puerts::IPuertsPlugin* plugin) +{ + return 0; +} + +V8_EXPORT puerts::IPuertsPlugin* CreateJSEngine(int backend) +{ + if (0 == backend) + { + return puerts::CreateV8Plugin(nullptr, nullptr); + } + else if (2 == backend) + { + return puerts::CreateQJSPlugin(nullptr, nullptr); + } + else + { + return nullptr; + } +} + +V8_EXPORT puerts::IPuertsPlugin* CreateJSEngineWithExternalEnv(int backend, void* external_quickjs_runtime, void* external_quickjs_context) +{ +#if WITH_QUICKJS + return nullptr; +#else + return nullptr; +#endif +} + +V8_EXPORT void DestroyJSEngine(puerts::IPuertsPlugin* plugin) +{ + delete plugin; +} + +V8_EXPORT void SetGlobalFunction(puerts::IPuertsPlugin* plugin, const char *Name, puerts::FuncPtr Callback, int64_t Data) +{ + plugin->SetGlobalFunction(Name, Callback, Data); +} + +V8_EXPORT void SetModuleResolver(puerts::IPuertsPlugin* plugin, puerts::FuncPtr Resolver, int32_t Idx) +{ + plugin->SetModuleResolver(Resolver, Idx); +} + +V8_EXPORT void* Eval(puerts::IPuertsPlugin* plugin, const char *Code, const char* Path) +{ + if (plugin->Eval(Code, Path)) + { + return plugin->GetResultInfo(); + } + else + { + return nullptr; + } +} + +V8_EXPORT bool ClearModuleCache(puerts::IPuertsPlugin* plugin, const char* Path) +{ + return plugin->ClearModuleCache(Path); +} + +V8_EXPORT int _RegisterClass(puerts::IPuertsPlugin* plugin, int BaseTypeId, const char *FullName, puerts::FuncPtr Constructor, puerts::FuncPtr Destructor, int64_t Data) +{ + return plugin->RegisterClass(BaseTypeId, FullName, Constructor, Destructor, Data, 0); +} + +V8_EXPORT int RegisterStruct(puerts::IPuertsPlugin* plugin, int BaseTypeId, const char *FullName, puerts::FuncPtr Constructor, puerts::FuncPtr Destructor, int64_t Data, int Size) +{ + return plugin->RegisterClass(BaseTypeId, FullName, Constructor, Destructor, Data, Size); +} + +V8_EXPORT int RegisterFunction(puerts::IPuertsPlugin* plugin, int ClassID, const char *Name, int IsStatic, puerts::FuncPtr Callback, int64_t Data) +{ + return plugin->RegisterFunction(ClassID, Name, IsStatic, Callback, Data) ? 1 : 0; +} + +V8_EXPORT int RegisterProperty(puerts::IPuertsPlugin* plugin, int ClassID, const char *Name, int IsStatic, puerts::FuncPtr Getter, int64_t GetterData, puerts::FuncPtr Setter, int64_t SetterData, int DontDelete) +{ + return plugin->RegisterProperty(ClassID, Name, IsStatic, Getter, GetterData, Setter, SetterData, DontDelete) ? 1 : 0; +} + +V8_EXPORT const char* GetLastExceptionInfo(puerts::IPuertsPlugin* plugin, int *Length) +{ + return plugin->GetLastExceptionInfo(Length); +} + +V8_EXPORT void LowMemoryNotification(puerts::IPuertsPlugin* plugin) +{ + plugin->LowMemoryNotification(); +} +V8_EXPORT bool IdleNotificationDeadline(puerts::IPuertsPlugin* plugin, double DeadlineInSeconds) +{ + return plugin->IdleNotificationDeadline(DeadlineInSeconds); +} +V8_EXPORT void RequestMinorGarbageCollectionForTesting(puerts::IPuertsPlugin* plugin) +{ + plugin->RequestMinorGarbageCollectionForTesting(); +} +V8_EXPORT void RequestFullGarbageCollectionForTesting(puerts::IPuertsPlugin* plugin) +{ + plugin->RequestFullGarbageCollectionForTesting(); +} + +V8_EXPORT void SetGeneralDestructor(puerts::IPuertsPlugin* plugin, puerts::FuncPtr GeneralDestructor) +{ + plugin->SetGeneralDestructor(GeneralDestructor); +} + +V8_EXPORT void* GetJSObjectValueGetter(puerts::IPuertsPlugin* plugin) +{ + return plugin->GetJSObjectValueGetter(); +} + +V8_EXPORT void* GetModuleExecutor(puerts::IPuertsPlugin* plugin) +{ + return plugin->GetModuleExecutor(); +} + +//-------------------------- begin js call cs -------------------------- +V8_EXPORT const void* GetArgumentValue(puerts::IPuertsPlugin* plugin, const void* Info, int Index) +{ + return plugin->GetArgumentValue(Info, Index); +} + +V8_EXPORT puerts::JsValueType GetJsValueType(puerts::IPuertsPlugin* plugin, const void* Value, int IsOut) +{ + return plugin->GetJsValueType(Value, IsOut); +} + +V8_EXPORT puerts::JsValueType GetArgumentType(puerts::IPuertsPlugin* plugin, const void* Info, int Index, int IsOut) +{ + return plugin->GetArgumentType(Info, Index, IsOut); +} + +V8_EXPORT double GetNumberFromValue(puerts::IPuertsPlugin* plugin, void* Value, int IsOut) +{ + return plugin->GetNumberFromValue(Value, IsOut); +} + +V8_EXPORT void SetNumberToOutValue(puerts::IPuertsPlugin* plugin, void* Value, double Number) +{ + plugin->SetNumberToOutValue(Value, Number); +} + +V8_EXPORT double GetDateFromValue(puerts::IPuertsPlugin* plugin, void* Value, int IsOut) +{ + return plugin->GetDateFromValue(Value, IsOut); +} + +V8_EXPORT void SetDateToOutValue(puerts::IPuertsPlugin* plugin, void* Value, double Date) +{ + plugin->SetDateToOutValue(Value, Date); +} + +V8_EXPORT const char *GetStringFromValue(puerts::IPuertsPlugin* plugin, void* Value, int *Length, int IsOut) +{ + return plugin->GetStringFromValue(Value, Length, IsOut); +} + +V8_EXPORT void SetStringToOutValue(puerts::IPuertsPlugin* plugin, void* Value, const char *Str) +{ + plugin->SetStringToOutValue(Value, Str); +} + +V8_EXPORT int GetBooleanFromValue(puerts::IPuertsPlugin* plugin, void* Value, int IsOut) +{ + return plugin->GetBooleanFromValue(Value, IsOut); +} + +V8_EXPORT void SetBooleanToOutValue(puerts::IPuertsPlugin* plugin, void* Value, int B) +{ + plugin->SetBooleanToOutValue(Value, B); +} + +V8_EXPORT int ValueIsBigInt(puerts::IPuertsPlugin* plugin, void* Value, int IsOut) +{ + return plugin->ValueIsBigInt(Value, IsOut); +} + +V8_EXPORT int64_t GetBigIntFromValue(puerts::IPuertsPlugin* plugin, void* Value, int IsOut) +{ + return plugin->GetBigIntFromValue(Value, IsOut); +} + +V8_EXPORT void SetBigIntToOutValue(puerts::IPuertsPlugin* plugin, void* Value, int64_t BigInt) +{ + plugin->SetBigIntToOutValue(Value, BigInt); +} + +V8_EXPORT const char* GetArrayBufferFromValue(puerts::IPuertsPlugin* plugin, void* Value, int *Length, int IsOut) +{ + return plugin->GetArrayBufferFromValue(Value, Length, IsOut); +} + +V8_EXPORT void SetArrayBufferToOutValue(puerts::IPuertsPlugin* plugin, void* Value, unsigned char *Bytes, int Length) +{ + plugin->SetArrayBufferToOutValue(Value, Bytes, Length); +} + +V8_EXPORT void *GetObjectFromValue(puerts::IPuertsPlugin* plugin, void* Value, int IsOut) +{ + return plugin->GetObjectFromValue(Value, IsOut); +} + +V8_EXPORT int GetTypeIdFromValue(puerts::IPuertsPlugin* plugin, void* Value, int IsOut) +{ + return plugin->GetTypeIdFromValue(Value, IsOut); +} + +V8_EXPORT void SetObjectToOutValue(puerts::IPuertsPlugin* plugin, void* Value, int ClassID, void* Ptr) +{ + plugin->SetObjectToOutValue(Value, ClassID, Ptr); +} + +V8_EXPORT void SetNullToOutValue(puerts::IPuertsPlugin* plugin, void* Value) +{ + plugin->SetNullToOutValue(Value); +} + +V8_EXPORT void* GetFunctionFromValue(puerts::IPuertsPlugin* plugin, void* Value, int IsOut) +{ + return plugin->GetFunctionFromValue(Value, IsOut); +} + +V8_EXPORT void* GetJSObjectFromValue(puerts::IPuertsPlugin* plugin, void* Value, int IsOut) +{ + return plugin->GetJSObjectFromValue(Value, IsOut); +} + +V8_EXPORT void ReleaseJSFunction(puerts::IPuertsPlugin* plugin, void* Function) +{ + plugin->ReleaseJSFunction(Function); +} +V8_EXPORT void ReleaseJSObject(puerts::IPuertsPlugin* plugin, void* Object) +{ + plugin->ReleaseJSObject(Object); +} + +V8_EXPORT void ThrowException(puerts::IPuertsPlugin* plugin, const char * Message) +{ + plugin->ThrowException(Message); +} + +V8_EXPORT void ReturnClass(puerts::IPuertsPlugin* plugin, const void* Info, int ClassID) +{ + plugin->ReturnClass(Info, ClassID); +} + +V8_EXPORT void ReturnObject(puerts::IPuertsPlugin* plugin, const void* Info, int ClassID, void* Ptr) +{ + plugin->ReturnObject(Info, ClassID, Ptr); +} + +V8_EXPORT void ReturnNumber(puerts::IPuertsPlugin* plugin, const void* Info, double Number) +{ + plugin->ReturnNumber(Info, Number); +} + +V8_EXPORT void ReturnString(puerts::IPuertsPlugin* plugin, const void* Info, const char* String) +{ + plugin->ReturnString(Info, String); +} + +V8_EXPORT void ReturnBigInt(puerts::IPuertsPlugin* plugin, const void* Info, int64_t BigInt) +{ + plugin->ReturnBigInt(Info, BigInt); +} + +V8_EXPORT void ReturnArrayBuffer(puerts::IPuertsPlugin* plugin, const void* Info, unsigned char *Bytes, int Length) +{ + plugin->ReturnArrayBuffer(Info, Bytes, Length); +} + +V8_EXPORT void ReturnBoolean(puerts::IPuertsPlugin* plugin, const void* Info, int Bool) +{ + plugin->ReturnBoolean(Info, Bool); +} + +V8_EXPORT void ReturnDate(puerts::IPuertsPlugin* plugin, const void* Info, double Date) +{ + plugin->ReturnDate(Info, Date); +} + +V8_EXPORT void ReturnNull(puerts::IPuertsPlugin* plugin, const void* Info) +{ + plugin->ReturnNull(Info); +} + +V8_EXPORT void ReturnFunction(puerts::IPuertsPlugin* plugin, const void* Info, void* Function) +{ + plugin->ReturnFunction(Info, Function); +} + +V8_EXPORT void ReturnCSharpFunctionCallback(puerts::IPuertsPlugin* plugin, const void* Info, puerts::FuncPtr Callback, int64_t Data) +{ + plugin->ReturnCSharpFunctionCallback(Info, Callback, Data); +} + +V8_EXPORT void ReturnJSObject(puerts::IPuertsPlugin* plugin, const void* Info, void* Object) +{ + plugin->ReturnJSObject(Info, Object); +} + +//-------------------------- end js call cs -------------------------- + +//-------------------------- bengin cs call js -------------------------- + +V8_EXPORT void PushNullForJSFunction(puerts::PuertsPluginStore* Function) +{ + Function->PuertsPlugin->PushNullForJSFunction(Function); +} + +V8_EXPORT void PushDateForJSFunction(puerts::PuertsPluginStore* Function, double DateValue) +{ + Function->PuertsPlugin->PushDateForJSFunction(Function, DateValue); +} + +V8_EXPORT void PushBooleanForJSFunction(puerts::PuertsPluginStore* Function, int B) +{ + Function->PuertsPlugin->PushBooleanForJSFunction(Function, B); +} + +V8_EXPORT void PushBigIntForJSFunction(puerts::PuertsPluginStore* Function, int64_t V) +{ + Function->PuertsPlugin->PushBigIntForJSFunction(Function, V); +} + +V8_EXPORT void PushArrayBufferForJSFunction(puerts::PuertsPluginStore* Function, unsigned char * Bytes, int Length) +{ + Function->PuertsPlugin->PushArrayBufferForJSFunction(Function, Bytes, Length); +} + +V8_EXPORT void PushStringForJSFunction(puerts::PuertsPluginStore* Function, const char* S) +{ + Function->PuertsPlugin->PushStringForJSFunction(Function, S); +} + +V8_EXPORT void PushNumberForJSFunction(puerts::PuertsPluginStore* Function, double D) +{ + Function->PuertsPlugin->PushNumberForJSFunction(Function, D); +} + +V8_EXPORT void PushObjectForJSFunction(puerts::PuertsPluginStore* Function, int ClassID, void* Ptr) +{ + Function->PuertsPlugin->PushObjectForJSFunction(Function, ClassID, Ptr); +} + +V8_EXPORT void PushJSFunctionForJSFunction(puerts::PuertsPluginStore* Function, void* V) +{ + Function->PuertsPlugin->PushJSFunctionForJSFunction(Function, V); +} + +V8_EXPORT void PushJSObjectForJSFunction(puerts::PuertsPluginStore* Function, void* V) +{ + Function->PuertsPlugin->PushJSObjectForJSFunction(Function, V); +} + +V8_EXPORT void* InvokeJSFunction(puerts::PuertsPluginStore* Function, int HasResult) +{ + return Function->PuertsPlugin->InvokeJSFunction(Function, HasResult); +} + +V8_EXPORT puerts::JsValueType GetResultType(puerts::PuertsPluginStore* ResultInfo) +{ + return ResultInfo->PuertsPlugin->GetResultType(ResultInfo); +} + +V8_EXPORT double GetNumberFromResult(puerts::PuertsPluginStore* ResultInfo) +{ + return ResultInfo->PuertsPlugin->GetNumberFromResult(ResultInfo); +} + +V8_EXPORT double GetDateFromResult(puerts::PuertsPluginStore* ResultInfo) +{ + return ResultInfo->PuertsPlugin->GetDateFromResult(ResultInfo); +} + +V8_EXPORT const char *GetStringFromResult(puerts::PuertsPluginStore* ResultInfo, int *Length) +{ + return ResultInfo->PuertsPlugin->GetStringFromResult(ResultInfo, Length); +} + +V8_EXPORT int GetBooleanFromResult(puerts::PuertsPluginStore* ResultInfo) +{ + return ResultInfo->PuertsPlugin->GetBooleanFromResult(ResultInfo); +} + +V8_EXPORT int ResultIsBigInt(puerts::PuertsPluginStore* ResultInfo) +{ + return ResultInfo->PuertsPlugin->ResultIsBigInt(ResultInfo); +} + +V8_EXPORT int64_t GetBigIntFromResult(puerts::PuertsPluginStore* ResultInfo) +{ + return ResultInfo->PuertsPlugin->GetBigIntFromResult(ResultInfo); +} + +V8_EXPORT const char *GetArrayBufferFromResult(puerts::PuertsPluginStore* ResultInfo, int *Length) +{ + return ResultInfo->PuertsPlugin->GetArrayBufferFromResult(ResultInfo, Length); +} + +V8_EXPORT void *GetObjectFromResult(puerts::PuertsPluginStore* ResultInfo) +{ + return ResultInfo->PuertsPlugin->GetObjectFromResult(ResultInfo); +} + +V8_EXPORT int GetTypeIdFromResult(puerts::PuertsPluginStore* ResultInfo) +{ + return ResultInfo->PuertsPlugin->GetTypeIdFromResult(ResultInfo); +} + +V8_EXPORT void* GetJSObjectFromResult(puerts::PuertsPluginStore* ResultInfo) +{ + return ResultInfo->PuertsPlugin->GetJSObjectFromResult(ResultInfo); +} + +V8_EXPORT void* GetFunctionFromResult(puerts::PuertsPluginStore* ResultInfo) +{ + return ResultInfo->PuertsPlugin->GetFunctionFromResult(ResultInfo); +} + +V8_EXPORT void ResetResult(puerts::PuertsPluginStore* ResultInfo) +{ + ResultInfo->PuertsPlugin->ResetResult(ResultInfo); +} + +V8_EXPORT const char* GetFunctionLastExceptionInfo(puerts::PuertsPluginStore* Function, int *Length) +{ + return Function->PuertsPlugin->GetFunctionLastExceptionInfo(Function, Length); +} + +//-------------------------- end cs call js -------------------------- + +//-------------------------- begin debug -------------------------- + +V8_EXPORT void CreateInspector(puerts::IPuertsPlugin* plugin, int32_t Port) +{ + plugin->CreateInspector(Port); +} + +V8_EXPORT void DestroyInspector(puerts::IPuertsPlugin* plugin) +{ + plugin->DestroyInspector(); +} + +V8_EXPORT int InspectorTick(puerts::IPuertsPlugin* plugin) +{ + return plugin->InspectorTick() ? 1 : 0; +} + +V8_EXPORT void LogicTick(puerts::IPuertsPlugin* plugin) +{ + return plugin->LogicTick(); +} + +V8_EXPORT void SetLogCallback(LogCallback Log, LogCallback LogWarning, LogCallback LogError) +{ + GLogCallback = Log; + GLogWarningCallback = LogError; + GLogErrorCallback = LogWarning; +} + +//-------------------------- end debug -------------------------- + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/unity/native_src/cmake/backends.json b/unity/native_src/cmake/backends.json index b761bcb16b..efd28a966d 100644 --- a/unity/native_src/cmake/backends.json +++ b/unity/native_src/cmake/backends.json @@ -296,5 +296,74 @@ } } } + }, + "mult": { + "url": "https://github.com/puerts/backend-v8/releases/download/V8_9.4.146.24_230822/v8_bin_9.4.146.24.tgz", + "config": { + "definition": [ + "V8_94_OR_NEWER" + ], + "include": [ + "/Inc" + ], + "link-libraries": { + "android": { + "armv7": [ + "/Lib/Android/armeabi-v7a/libwee8.a", + "/Lib/Android/armeabi-v7a/libquickjs.a" + ], + "arm64": [ + "/Lib/Android/arm64-v8a/libwee8.a", + "/Lib/Android/arm64-v8a/libquickjs.a" + ], + "x64": [ + "/Lib/Android/x64/libwee8.a", + "/Lib/Android/x86_64/libquickjs.a" + ] + }, + "win": { + "ia32": [ + "/Lib/Win32/wee8.lib", + "/Lib/Win32/quickjs.dll.lib" + ], + "x64": [ + "/Lib/Win64/wee8.lib", + "/Lib/Win64/quickjs.dll.lib" + ] + }, + "osx": { + "x64": [ + "/Lib/macOS/libwee8.a", + "/Lib/macOS/libquickjs.a" + ], + "arm64": [ + "/Lib/macOS_arm64/libwee8.a", + "/Lib/macOS_arm64/libquickjs.a" + ] + }, + "linux": { + "x64": [ + "/Lib/Linux/libwee8.a", + "/Lib/Linux/libquickjs.a" + ] + } + }, + "copy-libraries": { + "ios": { + "arm64": [ + "/Lib/iOS/arm64/libwee8.a", + "/Lib/iOS/arm64/libquickjs.a" + ] + }, + "win": { + "ia32": [ + "/Lib/Win32/*.dll" + ], + "x64": [ + "/Lib/Win64/*.dll" + ] + } + } + } } } \ No newline at end of file